sz_float.c 13.6 KB
Newer Older
T
tickduan 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
/**
 *  @file sz_float.c
 *  @author Sheng Di, Dingwen Tao, Xin Liang, Xiangyu Zou, Tao Lu, Wen Xia, Xuan Wang, Weizhe Zhang
 *  @date Aug, 2016
 *  @brief SZ_Init, Compression and Decompression functions
 *  (C) 2016 by Mathematics and Computer Science (MCS), Argonne National Laboratory.
 *      See COPYRIGHT in top-level directory.
 */


#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <math.h>
#include "sz.h"
#include "CompressElement.h"
#include "DynamicByteArray.h"
#include "TightDataPointStorageF.h"
#include "sz_float.h"
#include "szd_float.h"
#include "zlib.h"
#include "utility.h"

T
tickduan 已提交
26 27 28
# define MIN(_a, _b) (((_a) < (_b)) ? (_a) : (_b))


T
tickduan 已提交
29

T
tickduan 已提交
30
void computeReqLength_float(double realPrecision, short rangeExpo, int* reqLength, float* medianValue)
T
tickduan 已提交
31
{
T
tickduan 已提交
32 33
	short realPrecExpo = getPrecisionReqLength_double(realPrecision);
	*reqLength = 9 + rangeExpo - realPrecExpo + 1; //radExpo-reqExpo == reqMantiLength
T
tickduan 已提交
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
	if(*reqLength<9)
		*reqLength = 9;
	if(*reqLength>32)
	{	
		*reqLength = 32;
		*medianValue = 0;
	}			
}


unsigned int optimize_intervals_float_1D(float *oriData, size_t dataLength, double realPrecision)
{	
	size_t i = 0, radiusIndex;
	float pred_value = 0, pred_err;
	size_t *intervals = (size_t*)malloc(confparams_cpr->maxRangeRadius*sizeof(size_t));
	memset(intervals, 0, confparams_cpr->maxRangeRadius*sizeof(size_t));
	size_t totalSampleSize = dataLength/confparams_cpr->sampleDistance;
	for(i=2;i<dataLength;i++)
	{
		if(i%confparams_cpr->sampleDistance==0)
		{
			//pred_value = 2*oriData[i-1] - oriData[i-2];
			pred_value = oriData[i-1];
			pred_err = fabs(pred_value - oriData[i]);
			radiusIndex = (unsigned long)((pred_err/realPrecision+1)/2);
			if(radiusIndex>=confparams_cpr->maxRangeRadius)
				radiusIndex = confparams_cpr->maxRangeRadius - 1;			
			intervals[radiusIndex]++;
		}
	}
	//compute the appropriate number
	size_t targetCount = totalSampleSize*confparams_cpr->predThreshold;
	size_t sum = 0;
	for(i=0;i<confparams_cpr->maxRangeRadius;i++)
	{
		sum += intervals[i];
		if(sum>targetCount)
			break;
	}
	if(i>=confparams_cpr->maxRangeRadius)
		i = confparams_cpr->maxRangeRadius-1;
		
	unsigned int accIntervals = 2*(i+1);
	unsigned int powerOf2 = roundUpToPowerOf2(accIntervals);
	
	if(powerOf2<32)
		powerOf2 = 32;
	
	free(intervals);
	//printf("accIntervals=%d, powerOf2=%d\n", accIntervals, powerOf2);
	return powerOf2;
}

TightDataPointStorageF* SZ_compress_float_1D_MDQ(float *oriData, 
T
tickduan 已提交
88
				size_t dataLength, float realPrecision, float valueRangeSize, float medianValue_f)
T
tickduan 已提交
89 90 91 92 93 94 95
{
	unsigned int quantization_intervals;
	if(exe_params->optQuantMode==1)
		quantization_intervals = optimize_intervals_float_1D_opt(oriData, dataLength, realPrecision);
	else
		quantization_intervals = exe_params->intvCapacity;
	//updateQuantizationInfo(quantization_intervals);	
T
tickduan 已提交
96
	int half_interval = quantization_intervals/2;
T
tickduan 已提交
97

T
tickduan 已提交
98 99 100
    //
	// calc reqlength and need set medianValue to zero. 
	// 
T
tickduan 已提交
101
	size_t i;
T
tickduan 已提交
102
	int reqLength; // need save bits length for one float .  value ragne 9~32 
T
tickduan 已提交
103
	float medianValue = medianValue_f;
T
tickduan 已提交
104
	short rangeExpo = getExponent_float(valueRangeSize/2);
T
tickduan 已提交
105
	
T
tickduan 已提交
106
	computeReqLength_float(realPrecision, rangeExpo, &reqLength, &medianValue);	
T
tickduan 已提交
107

T
tickduan 已提交
108 109 110
	//
	//  malloc all 
	//
T
tickduan 已提交
111
	
T
tickduan 已提交
112 113 114 115
	// 1 type 
	int* type = (int*) malloc(dataLength*sizeof(int));	
	float* spaceFillingValue = oriData; //
	// 2 lead
T
tickduan 已提交
116 117
	DynamicIntArray *exactLeadNumArray;
	new_DIA(&exactLeadNumArray, DynArrayInitLen);
T
tickduan 已提交
118
	// 3 mid
T
tickduan 已提交
119 120
	DynamicByteArray *exactMidByteArray;
	new_DBA(&exactMidByteArray, DynArrayInitLen);
T
tickduan 已提交
121
	// 4 residual bit
T
tickduan 已提交
122 123 124
	DynamicIntArray *resiBitArray;
	new_DIA(&resiBitArray, DynArrayInitLen);
	
T
tickduan 已提交
125 126
	unsigned char preDiffBytes[4];
	intToBytes_bigEndian(preDiffBytes, 0);
T
tickduan 已提交
127
	
T
tickduan 已提交
128
	// calc save byte length and bit lengths with reqLength
T
tickduan 已提交
129 130
	int reqBytesLength = reqLength/8;
	int resiBitsLength = reqLength%8;
T
tickduan 已提交
131
	//float last3CmprsData[3] = {0};
T
tickduan 已提交
132 133 134 135 136 137 138

	FloatValueCompressElement *vce = (FloatValueCompressElement*)malloc(sizeof(FloatValueCompressElement));
	LossyCompressionElement *lce = (LossyCompressionElement*)malloc(sizeof(LossyCompressionElement));
				
	//add the first data	
	type[0] = 0;
	compressSingleFloatValue(vce, spaceFillingValue[0], realPrecision, medianValue, reqLength, reqBytesLength, resiBitsLength);
T
tickduan 已提交
139 140 141 142
	// set lce
	updateLossyCompElement_Float(vce->curBytes, preDiffBytes, reqBytesLength, resiBitsLength, lce);
	memcpy(preDiffBytes, vce->curBytes, 4);
	// lce to arrays
T
tickduan 已提交
143
	addExactData(exactMidByteArray, exactLeadNumArray, resiBitArray, lce);
T
tickduan 已提交
144
	//listAdd_float(last3CmprsData, vce->data);
T
tickduan 已提交
145 146 147 148
		
	//add the second data
	type[1] = 0;
	compressSingleFloatValue(vce, spaceFillingValue[1], realPrecision, medianValue, reqLength, reqBytesLength, resiBitsLength);
T
tickduan 已提交
149 150
	updateLossyCompElement_Float(vce->curBytes, preDiffBytes, reqBytesLength, resiBitsLength, lce);
	memcpy(preDiffBytes, vce->curBytes, 4);
T
tickduan 已提交
151
	addExactData(exactMidByteArray, exactLeadNumArray, resiBitArray, lce);
T
tickduan 已提交
152
	//listAdd_float(last3CmprsData, vce->data);
T
tickduan 已提交
153

T
tickduan 已提交
154 155
	int state;
	float checkRadius;
T
tickduan 已提交
156
	float oriFloat;
T
tickduan 已提交
157
	float pred = vce->data;
T
tickduan 已提交
158
	float diff;
T
tickduan 已提交
159
	checkRadius = (quantization_intervals-1)*realPrecision;
T
tickduan 已提交
160
	float double_realpreci = 2*realPrecision;
T
tickduan 已提交
161 162
	float recip_precision = 1/realPrecision;
	
T
tickduan 已提交
163
	for(i=2; i < dataLength; i++)
T
tickduan 已提交
164
	{	
T
tickduan 已提交
165
		oriFloat = spaceFillingValue[i];
T
tickduan 已提交
166 167
		//pred = 2*last3CmprsData[0] - last3CmprsData[1];
		//pred = last3CmprsData[0];
T
tickduan 已提交
168 169
		diff = fabsf(oriFloat - pred);	
		if(diff < checkRadius)
T
tickduan 已提交
170
		{
T
tickduan 已提交
171 172
			state = ((int)( diff * recip_precision + 1))>>1;
			if(oriFloat >= pred)
T
tickduan 已提交
173
			{
T
tickduan 已提交
174 175
				type[i] = half_interval + state;
				pred = pred + state * double_realpreci;
T
tickduan 已提交
176 177 178
			}
			else //curData<pred
			{
T
tickduan 已提交
179 180
				type[i] = half_interval - state;
				pred = pred - state * double_realpreci;
T
tickduan 已提交
181 182 183
			}
				
			//double-check the prediction error in case of machine-epsilon impact	
T
tickduan 已提交
184
			if(fabs(oriFloat - pred) > realPrecision)
T
tickduan 已提交
185 186
			{	
				type[i] = 0;				
T
tickduan 已提交
187 188 189
				compressSingleFloatValue(vce, oriFloat, realPrecision, medianValue, reqLength, reqBytesLength, resiBitsLength);
				updateLossyCompElement_Float(vce->curBytes, preDiffBytes, reqBytesLength, resiBitsLength, lce);
				memcpy(preDiffBytes, vce->curBytes, 4);
T
tickduan 已提交
190 191 192
				addExactData(exactMidByteArray, exactLeadNumArray, resiBitArray, lce);		
				
				//listAdd_float(last3CmprsData, vce->data);	
T
tickduan 已提交
193
				pred = vce->data;				
T
tickduan 已提交
194 195 196
			}
			else
			{
T
tickduan 已提交
197
				//listAdd_float(last3CmprsData, pred);	
T
tickduan 已提交
198
			}	
T
tickduan 已提交
199
			// go next
T
tickduan 已提交
200 201 202 203 204
			continue;
		}
		
		//unpredictable data processing		
		type[i] = 0;		
T
tickduan 已提交
205 206 207
		compressSingleFloatValue(vce, oriFloat, realPrecision, medianValue, reqLength, reqBytesLength, resiBitsLength);
		updateLossyCompElement_Float(vce->curBytes, preDiffBytes, reqBytesLength, resiBitsLength, lce);
		memcpy(preDiffBytes, vce->curBytes, 4);
T
tickduan 已提交
208 209 210
		addExactData(exactMidByteArray, exactLeadNumArray, resiBitArray, lce);

		//listAdd_float(last3CmprsData, vce->data);
T
tickduan 已提交
211
		pred = vce->data;	
T
tickduan 已提交
212 213 214 215 216 217 218
		
	}//end of for
		
//	char* expSegmentsInBytes;
//	int expSegmentsInBytes_size = convertESCToBytes(esc, &expSegmentsInBytes);
	size_t exactDataNum = exactLeadNumArray->size;
	
T
tickduan 已提交
219
	TightDataPointStorageF* tdps = NULL;			
T
tickduan 已提交
220 221 222 223 224
	new_TightDataPointStorageF(&tdps, dataLength, exactDataNum, 
			type, exactMidByteArray->array, exactMidByteArray->size,  
			exactLeadNumArray->array,  
			resiBitArray->array, resiBitArray->size, 
			resiBitsLength,
T
tickduan 已提交
225
			realPrecision, medianValue, (char)reqLength, quantization_intervals, 0);
T
tickduan 已提交
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243

//sdi:Debug
/*	int sum =0;
	for(i=0;i<dataLength;i++)
		if(type[i]==0) sum++;
	printf("opt_quantizations=%d, exactDataNum=%zu, sum=%d\n",quantization_intervals, exactDataNum, sum);
*/	
	//free memory
	free_DIA(exactLeadNumArray);
	free_DIA(resiBitArray);
	free(type);	
	free(vce);
	free(lce);	
	free(exactMidByteArray); //exactMidByteArray->array has been released in free_TightDataPointStorageF(tdps);
	
	return tdps;
}

T
tickduan 已提交
244 245 246
// compress core algorithm  if success return true else return false
bool SZ_compress_args_float_NoCkRngeNoGzip_1D( unsigned char* newByteData, float *oriData, 
                   size_t dataLength, double realPrecision, size_t *outSize, float valueRangeSize, float medianValue_f)
T
tickduan 已提交
247
{		
T
tickduan 已提交
248
	// get tdps
T
tickduan 已提交
249
	TightDataPointStorageF* tdps = NULL;	
T
tickduan 已提交
250
	tdps = SZ_compress_float_1D_MDQ(oriData, dataLength, realPrecision, valueRangeSize, medianValue_f);	
T
tickduan 已提交
251 252 253 254 255 256 257 258 259 260 261
	if(tdps == NULL)
	  return false;

    // serialize 
	if(!convertTDPStoFlatBytes_float(tdps, newByteData, outSize))
	{
		free_TightDataPointStorageF(tdps);
		return false;
	}
	  
	// check compressed size large than original
T
tickduan 已提交
262
	if(*outSize > 1 + MetaDataByteLength + exe_params->SZ_SIZE_TYPE + 1 + sizeof(float)*dataLength)
T
tickduan 已提交
263 264 265
	{
		return false;
	}	
T
tickduan 已提交
266 267
	
	free_TightDataPointStorageF(tdps);
T
tickduan 已提交
268
	return true;
T
tickduan 已提交
269 270 271
}


T
tickduan 已提交
272
void SZ_compress_args_float_withinRange(unsigned char* newByteData, float *oriData, size_t dataLength, size_t *outSize)
T
tickduan 已提交
273 274 275 276
{
	TightDataPointStorageF* tdps = (TightDataPointStorageF*) malloc(sizeof(TightDataPointStorageF));
	tdps->leadNumArray = NULL;
	tdps->residualMidBits = NULL;
T
tickduan 已提交
277
	
T
tickduan 已提交
278 279 280 281 282 283 284
	tdps->allSameData = 1;
	tdps->dataSeriesLength = dataLength;
	tdps->exactMidBytes = (unsigned char*)malloc(sizeof(unsigned char)*4);
	tdps->isLossless = 0;
	float value = oriData[0];
	floatToBytes(tdps->exactMidBytes, value);
	tdps->exactMidBytes_size = 4;
T
tickduan 已提交
285
	
T
tickduan 已提交
286 287 288 289 290 291 292 293
	size_t tmpOutSize;
	//unsigned char *tmpByteData;
	convertTDPStoFlatBytes_float(tdps, newByteData, &tmpOutSize);

	//*newByteData = (unsigned char*)malloc(sizeof(unsigned char)*12); //for floating-point data (1+3+4+4)
	//memcpy(*newByteData, tmpByteData, 12);
	*outSize = tmpOutSize; //8+SZ_SIZE_TYPE; //8==3+1+4(float_size)
	free_TightDataPointStorageF(tdps);	
T
tickduan 已提交
294 295
}

T
tickduan 已提交
296 297 298 299
void cost_start();
double cost_end(const char* tag);
void show_rate( int in_len, int out_len);

T
tickduan 已提交
300
int SZ_compress_args_float(float *oriData, size_t r1, unsigned char* newByteData, size_t *outSize, sz_params* params)
T
tickduan 已提交
301
{
T
tickduan 已提交
302 303
	int status = SZ_SUCCESS;
	size_t dataLength = r1;
T
tickduan 已提交
304
	
T
tickduan 已提交
305
	//cost_start();
T
tickduan 已提交
306
	// check at least elements count  
T
tickduan 已提交
307 308
	if(dataLength <= MIN_NUM_OF_ELEMENTS)
	{
T
tickduan 已提交
309
		printf("error, input elements count=%d less than %d, so need not do compress.\n", (int)dataLength, MIN_NUM_OF_ELEMENTS);
T
tickduan 已提交
310
		return SZ_LITTER_ELEMENT;
T
tickduan 已提交
311 312 313 314
	}
	
	float valueRangeSize = 0, medianValue = 0;
	float min = 0;
T
tickduan 已提交
315

T
tickduan 已提交
316
	min = computeRangeSize_float(oriData, dataLength, &valueRangeSize, &medianValue);	
T
tickduan 已提交
317 318

	// calc max
T
tickduan 已提交
319
	float max = min+valueRangeSize;
T
tickduan 已提交
320 321
	params->fmin = min;
	params->fmax = max;
T
tickduan 已提交
322
	
T
tickduan 已提交
323
	// calc precision
T
tickduan 已提交
324
	double realPrecision = 0; 
T
tickduan 已提交
325
	if(params->errorBoundMode==PSNR)
T
tickduan 已提交
326
	{
T
tickduan 已提交
327 328
		params->errorBoundMode = SZ_ABS;
		realPrecision = params->absErrBound = computeABSErrBoundFromPSNR(params->psnr, (double)params->predThreshold, (double)valueRangeSize);
T
tickduan 已提交
329 330
		//printf("realPrecision=%lf\n", realPrecision);
	}
T
tickduan 已提交
331
	else if(params->errorBoundMode==NORM) //norm error = sqrt(sum((xi-xi_)^2))
T
tickduan 已提交
332
	{
T
tickduan 已提交
333 334
		params->errorBoundMode = SZ_ABS;
		realPrecision = params->absErrBound = computeABSErrBoundFromNORM_ERR(params->normErr, dataLength);
T
tickduan 已提交
335
		//printf("realPrecision=%lf\n", realPrecision);				
T
tickduan 已提交
336 337 338
	}
	else
	{
T
tickduan 已提交
339 340
		realPrecision = getRealPrecision_float(valueRangeSize, params->errorBoundMode, params->absErrBound, params->relBoundRatio, &status);
		params->absErrBound = realPrecision;
T
tickduan 已提交
341
	}	
T
tickduan 已提交
342

T
tickduan 已提交
343 344 345 346 347
	//cost_end(" sz_pre_calc");

    //
	// do compress 
	//
T
tickduan 已提交
348
	if(valueRangeSize <= realPrecision)
T
tickduan 已提交
349
	{		
T
tickduan 已提交
350
		// special deal with same data
T
tickduan 已提交
351
		SZ_compress_args_float_withinRange(newByteData, oriData, dataLength, outSize);
T
tickduan 已提交
352
		return SZ_SUCCESS;
T
tickduan 已提交
353
	}
T
tickduan 已提交
354

T
tickduan 已提交
355 356 357 358 359 360 361 362 363 364
	//
	// first compress with sz
	//		
	size_t tmpOutSize = 0;
	unsigned char* tmpByteData  =  newByteData;
	bool twoStage =  params->szMode != SZ_BEST_SPEED;
	if(twoStage)
	{
		tmpByteData = (unsigned char*)malloc(r1*sizeof(float) + 1024);
	}
T
tickduan 已提交
365

T
tickduan 已提交
366 367
	// compress core algorithm
	if(!SZ_compress_args_float_NoCkRngeNoGzip_1D(tmpByteData, oriData, r1, realPrecision, &tmpOutSize, valueRangeSize, medianValue))
T
tickduan 已提交
368
	{
T
tickduan 已提交
369 370 371 372
		*outSize = 0;
		if(twoStage)
			free(tmpByteData);
		return SZ_ALGORITHM_ERR;
T
tickduan 已提交
373
	}
T
tickduan 已提交
374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393

    //cost_end(" sz_first_compress");
	//show_rate(r1*sizeof(float), *outSize);
	//
	//  second compress with Call Zstd or Gzip 
	//
	//cost_start();
	if(!twoStage)
	{
		*outSize = tmpOutSize;
	}
	else
	{
		*outSize = sz_lossless_compress(params->losslessCompressor, params->gzipMode, tmpByteData, tmpOutSize, newByteData);
		free(tmpByteData);	
	}

	//cost_end(" sz_second_compress");
	//show_rate(r1*sizeof(float), *outSize);
	return SZ_SUCCESS;
T
tickduan 已提交
394
}
T
tickduan 已提交
395

T
tickduan 已提交
396 397 398 399 400 401 402
unsigned int optimize_intervals_float_1D_opt(float *oriData, size_t dataLength, double realPrecision)
{	
	size_t i = 0, radiusIndex;
	float pred_value = 0, pred_err;
	size_t *intervals = (size_t*)malloc(confparams_cpr->maxRangeRadius*sizeof(size_t));
	memset(intervals, 0, confparams_cpr->maxRangeRadius*sizeof(size_t));
	size_t totalSampleSize = 0;//dataLength/confparams_cpr->sampleDistance;
T
tickduan 已提交
403

T
tickduan 已提交
404 405 406 407 408 409 410 411 412
	float * data_pos = oriData + 2;
	while(data_pos - oriData < dataLength){
		totalSampleSize++;
		pred_value = data_pos[-1];
		pred_err = fabs(pred_value - *data_pos);
		radiusIndex = (unsigned long)((pred_err/realPrecision+1)/2);
		if(radiusIndex>=confparams_cpr->maxRangeRadius)
			radiusIndex = confparams_cpr->maxRangeRadius - 1;			
		intervals[radiusIndex]++;
T
tickduan 已提交
413

T
tickduan 已提交
414 415 416 417 418 419 420 421 422 423 424 425 426
		data_pos += confparams_cpr->sampleDistance;
	}
	//compute the appropriate number
	size_t targetCount = totalSampleSize*confparams_cpr->predThreshold;
	size_t sum = 0;
	for(i=0;i<confparams_cpr->maxRangeRadius;i++)
	{
		sum += intervals[i];
		if(sum>targetCount)
			break;
	}
	if(i>=confparams_cpr->maxRangeRadius)
		i = confparams_cpr->maxRangeRadius-1;
T
tickduan 已提交
427
		
T
tickduan 已提交
428 429
	unsigned int accIntervals = 2*(i+1);
	unsigned int powerOf2 = roundUpToPowerOf2(accIntervals);
T
tickduan 已提交
430
	
T
tickduan 已提交
431 432
	if(powerOf2<32)
		powerOf2 = 32;
T
tickduan 已提交
433
	
T
tickduan 已提交
434 435 436
	free(intervals);
	return powerOf2;
}