szd_double.c 11.1 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
/**
 *  @file szd_double.c
 *  @author Sheng Di, Dingwen Tao, Xin Liang, Xiangyu Zou, Tao Lu, Wen Xia, Xuan Wang, Weizhe Zhang
 *  @date Aug, 2016
 *  @brief 
 *  (C) 2016 by Mathematics and Computer Science (MCS), Argonne National Laboratory.
 *      See COPYRIGHT in top-level directory.
 */

#include <stdlib.h> 
#include <stdio.h>
#include <string.h>
#include "szd_double.h"
#include "TightDataPointStorageD.h"
#include "sz.h"
#include "Huffman.h"
#include "szd_double_pwr.h"
#include "szd_double_ts.h"
#include "utility.h"

T
tickduan 已提交
21 22
int SZ_decompress_args_double(double* newData, size_t r1, unsigned char* cmpBytes, 
				size_t cmpSize, int compressionType, double* hist_data, sz_exedata* pde_exe, sz_params* pde_params)
T
tickduan 已提交
23
{
T
tickduan 已提交
24 25
	int status = SZ_SUCCESS;
	size_t dataLength = r1;
T
tickduan 已提交
26 27 28 29 30 31 32 33
	
	//unsigned char* tmpBytes;
	size_t targetUncompressSize = dataLength <<3; //i.e., *8
	//tmpSize must be "much" smaller than dataLength
	size_t i, tmpSize = 12+MetaDataByteLength_double+exe_params->SZ_SIZE_TYPE;
	unsigned char* szTmpBytes;
	if(cmpSize!=12+4+MetaDataByteLength_double && cmpSize!=12+8+MetaDataByteLength_double)
	{
T
tickduan 已提交
34 35
		pde_params->losslessCompressor = is_lossless_compressed_data(cmpBytes, cmpSize);
		if(pde_params->szMode!=SZ_TEMPORAL_COMPRESSION)
T
tickduan 已提交
36
		{
T
tickduan 已提交
37 38
			if(pde_params->losslessCompressor!=-1)
				pde_params->szMode = SZ_BEST_COMPRESSION;
T
tickduan 已提交
39
			else
T
tickduan 已提交
40
				pde_params->szMode = SZ_BEST_SPEED;			
T
tickduan 已提交
41
		}
T
tickduan 已提交
42 43


T
tickduan 已提交
44
		if(pde_params->szMode==SZ_BEST_SPEED)
T
tickduan 已提交
45 46 47 48
		{
			tmpSize = cmpSize;
			szTmpBytes = cmpBytes;	
		}	
T
tickduan 已提交
49
		else if(pde_params->szMode==SZ_BEST_COMPRESSION || pde_params->szMode==SZ_DEFAULT_COMPRESSION || pde_params->szMode==SZ_TEMPORAL_COMPRESSION)
T
tickduan 已提交
50 51 52
		{
			if(targetUncompressSize<MIN_ZLIB_DEC_ALLOMEM_BYTES) //Considering the minimum size
				targetUncompressSize = MIN_ZLIB_DEC_ALLOMEM_BYTES; 			
T
tickduan 已提交
53
			tmpSize = sz_lossless_decompress(pde_params->losslessCompressor, cmpBytes, (unsigned long)cmpSize, &szTmpBytes, (unsigned long)targetUncompressSize+4+MetaDataByteLength_double+exe_params->SZ_SIZE_TYPE);			
T
tickduan 已提交
54 55 56 57 58 59
			//szTmpBytes = (unsigned char*)malloc(sizeof(unsigned char)*tmpSize);
			//memcpy(szTmpBytes, tmpBytes, tmpSize);
			//free(tmpBytes); //release useless memory		
		}
		else
		{
T
tickduan 已提交
60
			printf("Wrong value of pde_params->szMode in the double compressed bytes.\n");
T
tickduan 已提交
61 62 63 64 65 66 67
			status = SZ_MERR;
			return status;
		}	
	}
	else
		szTmpBytes = cmpBytes;
		
T
tickduan 已提交
68
	pde_params->sol_ID = szTmpBytes[4+14]; //szTmpBytes: version(3bytes), samebyte(1byte), [14]:sol_ID=SZ or SZ_Transpose		
T
tickduan 已提交
69 70
	//TODO: convert szTmpBytes to double array.
	TightDataPointStorageD* tdps;
T
tickduan 已提交
71
	int errBoundMode = new_TightDataPointStorageD_fromFlatBytes(&tdps, szTmpBytes, tmpSize, pde_exe, pde_params);
T
tickduan 已提交
72

T
tickduan 已提交
73
	int dim = r1;
T
tickduan 已提交
74 75 76
	int doubleSize = sizeof(double);
	if(tdps->isLossless)
	{
T
tickduan 已提交
77
		// *newData = (double*)malloc(doubleSize*dataLength); comment by tickduan
T
tickduan 已提交
78 79
		if(sysEndianType==BIG_ENDIAN_SYSTEM)
		{
T
tickduan 已提交
80
			memcpy(newData, szTmpBytes+4+MetaDataByteLength_double+exe_params->SZ_SIZE_TYPE, dataLength*doubleSize);
T
tickduan 已提交
81 82 83 84 85
		}
		else
		{
			unsigned char* p = szTmpBytes+4+MetaDataByteLength_double+exe_params->SZ_SIZE_TYPE;
			for(i=0;i<dataLength;i++,p+=doubleSize)
T
tickduan 已提交
86
				newData[i] = bytesToDouble(p);
T
tickduan 已提交
87 88
		}		
	}
T
tickduan 已提交
89
	else if(pde_params->sol_ID==SZ_Transpose)
T
tickduan 已提交
90
	{
T
tickduan 已提交
91
		getSnapshotData_double_1D(newData,dataLength,tdps, errBoundMode, 0, hist_data, pde_params);		
T
tickduan 已提交
92
	}
T
tickduan 已提交
93
	else //pde_params->sol_ID==SZ
T
tickduan 已提交
94 95 96
	{
		if(tdps->raBytes_size > 0) //v2.0
		{
T
tickduan 已提交
97
			getSnapshotData_double_1D(newData,r1,tdps, errBoundMode, 0, hist_data, pde_params);
T
tickduan 已提交
98 99 100
		}
		else //1.4.13 or time-based compression
		{
T
tickduan 已提交
101
			getSnapshotData_double_1D(newData,r1,tdps, errBoundMode, compressionType, hist_data, pde_params);
T
tickduan 已提交
102 103 104
		}
	}	

T
tickduan 已提交
105
	if(pde_params->protectValueRange)
T
tickduan 已提交
106
	{
T
tickduan 已提交
107
		double* nd = newData;
T
tickduan 已提交
108 109
		double min = pde_params->dmin;
		double max = pde_params->dmax;		
T
tickduan 已提交
110 111 112 113 114 115 116 117 118 119 120 121 122
		for(i=0;i<dataLength;i++)
		{
			double v = nd[i];
			if(v <= max && v >= min)
				continue;
			if(v < min)
				nd[i] = min;
			else if(v > max)
				nd[i] = max;
		}
	}

	free_TightDataPointStorageD2(tdps);
T
tickduan 已提交
123
	if(pde_params->szMode!=SZ_BEST_SPEED && cmpSize!=12+MetaDataByteLength_double+exe_params->SZ_SIZE_TYPE)
T
tickduan 已提交
124 125 126 127
		free(szTmpBytes);	
	return status;
}

T
tickduan 已提交
128
void decompressDataSeries_double_1D(double* data, size_t dataSeriesLength, double* hist_data, TightDataPointStorageD* tdps) 
T
tickduan 已提交
129 130 131 132 133 134 135 136 137 138 139
{
	//updateQuantizationInfo(tdps->intervals);
	int intvRadius = tdps->intervals/2;
	size_t i, j, k = 0, p = 0, l = 0; // k is to track the location of residual_bit
								// in resiMidBits, p is to track the
								// byte_index of resiMidBits, l is for
								// leadNum
	unsigned char* leadNum;
	double interval = tdps->realPrecision*2;
	
	convertByteArray2IntArray_fast_2b(tdps->exactDataNum, tdps->leadNumArray, tdps->leadNumArray_size, &leadNum);
T
tickduan 已提交
140
	//*data = (double*)malloc(sizeof(double)*dataSeriesLength); comment by tickduan
T
tickduan 已提交
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204

	int* type = (int*)malloc(dataSeriesLength*sizeof(int));

	HuffmanTree* huffmanTree = createHuffmanTree(tdps->stateNum);
	decode_withTree(huffmanTree, tdps->typeArray, dataSeriesLength, type);
	SZ_ReleaseHuffman(huffmanTree);	
	
	unsigned char preBytes[8];
	unsigned char curBytes[8];
	
	memset(preBytes, 0, 8);

	size_t curByteIndex = 0;
	int reqBytesLength, resiBitsLength, resiBits; 
	unsigned char leadingNum;	
	double medianValue, exactData, predValue;
	
	reqBytesLength = tdps->reqLength/8;
	resiBitsLength = tdps->reqLength%8;
	medianValue = tdps->medianValue;
	
	int type_;
	for (i = 0; i < dataSeriesLength; i++) {
		type_ = type[i];
		switch (type_) {
		case 0:
			// compute resiBits
			resiBits = 0;
			if (resiBitsLength != 0) {
				int kMod8 = k % 8;
				int rightMovSteps = getRightMovingSteps(kMod8, resiBitsLength);
				if (rightMovSteps > 0) {
					int code = getRightMovingCode(kMod8, resiBitsLength);
					resiBits = (tdps->residualMidBits[p] & code) >> rightMovSteps;
				} else if (rightMovSteps < 0) {
					int code1 = getLeftMovingCode(kMod8);
					int code2 = getRightMovingCode(kMod8, resiBitsLength);
					int leftMovSteps = -rightMovSteps;
					rightMovSteps = 8 - leftMovSteps;
					resiBits = (tdps->residualMidBits[p] & code1) << leftMovSteps;
					p++;
					resiBits = resiBits
							| ((tdps->residualMidBits[p] & code2) >> rightMovSteps);
				} else // rightMovSteps == 0
				{
					int code = getRightMovingCode(kMod8, resiBitsLength);
					resiBits = (tdps->residualMidBits[p] & code);
					p++;
				}
				k += resiBitsLength;
			}

			// recover the exact data
			memset(curBytes, 0, 8);
			leadingNum = leadNum[l++];
			memcpy(curBytes, preBytes, leadingNum);
			for (j = leadingNum; j < reqBytesLength; j++)
				curBytes[j] = tdps->exactMidBytes[curByteIndex++];
			if (resiBitsLength != 0) {
				unsigned char resiByte = (unsigned char) (resiBits << (8 - resiBitsLength));
				curBytes[reqBytesLength] = resiByte;
			}
			
			exactData = bytesToDouble(curBytes);
T
tickduan 已提交
205
			data[i] = exactData + medianValue;
T
tickduan 已提交
206 207 208
			memcpy(preBytes,curBytes,8);
			break;
		default:
T
tickduan 已提交
209 210 211
			//predValue = 2 * data[i-1] - data[i-2];
			predValue = data[i-1];
			data[i] = predValue + (type_-intvRadius)*interval;
T
tickduan 已提交
212 213
			break;
		}
T
tickduan 已提交
214
		//printf("%.30G\n",data[i]);
T
tickduan 已提交
215 216 217 218 219 220 221
	}
	
	free(leadNum);
	free(type);
	return;
}

T
tickduan 已提交
222
/*MSST19*/
T
tickduan 已提交
223
void decompressDataSeries_double_1D_MSST19(double* data, size_t dataSeriesLength, TightDataPointStorageD* tdps) 
T
tickduan 已提交
224 225 226
{
	//updateQuantizationInfo(tdps->intervals);
	int intvRadius = tdps->intervals/2;
T
tickduan 已提交
227 228 229 230 231
	int intvCapacity = tdps->intervals;
	size_t i, j, k = 0, p = 0, l = 0; // k is to track the location of residual_bit
								// in resiMidBits, p is to track the
								// byte_index of resiMidBits, l is for
								// leadNum
T
tickduan 已提交
232
	unsigned char* leadNum;
T
tickduan 已提交
233 234
	//double interval = tdps->realPrecision*2;
	
T
tickduan 已提交
235
	convertByteArray2IntArray_fast_2b(tdps->exactDataNum, tdps->leadNumArray, tdps->leadNumArray_size, &leadNum);
T
tickduan 已提交
236
	//*data = (double*)malloc(sizeof(double)*dataSeriesLength); comment by tickduan
T
tickduan 已提交
237 238

	int* type = (int*)malloc(dataSeriesLength*sizeof(int));
T
tickduan 已提交
239
	
T
tickduan 已提交
240
	HuffmanTree* huffmanTree = createHuffmanTree(tdps->stateNum);
T
tickduan 已提交
241 242
	decode_withTree_MSST19(huffmanTree, tdps->typeArray, dataSeriesLength, type, tdps->max_bits);
	//decode_withTree(huffmanTree, tdps->typeArray, dataSeriesLength, type);
T
tickduan 已提交
243 244 245
	SZ_ReleaseHuffman(huffmanTree);	
	unsigned char preBytes[8];
	unsigned char curBytes[8];
T
tickduan 已提交
246
	
T
tickduan 已提交
247 248 249 250 251
	memset(preBytes, 0, 8);

	size_t curByteIndex = 0;
	int reqBytesLength, resiBitsLength, resiBits; 
	unsigned char leadingNum;	
T
tickduan 已提交
252
	double exactData, predValue = 0;
T
tickduan 已提交
253 254
	reqBytesLength = tdps->reqLength/8;
	resiBitsLength = tdps->reqLength%8;
T
tickduan 已提交
255 256 257 258 259 260
	//float threshold = tdps->minLogValue;
	double* precisionTable = (double*)malloc(sizeof(double) * intvCapacity);
	double inv = 2.0-pow(2, -(tdps->plus_bits));
	for(int i=0; i<intvCapacity; i++){
		double test = pow((1+tdps->realPrecision), inv*(i - intvRadius));
		precisionTable[i] = test;
T
tickduan 已提交
261 262
	}

T
tickduan 已提交
263 264 265 266 267
	int type_;
	for (i = 0; i < dataSeriesLength; i++) {
		type_ = type[i];
		switch (type_) {
		case 0:
T
tickduan 已提交
268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293
			// compute resiBits
			resiBits = 0;
			if (resiBitsLength != 0) {
				int kMod8 = k % 8;
				int rightMovSteps = getRightMovingSteps(kMod8, resiBitsLength);
				if (rightMovSteps > 0) {
					int code = getRightMovingCode(kMod8, resiBitsLength);
					resiBits = (tdps->residualMidBits[p] & code) >> rightMovSteps;
				} else if (rightMovSteps < 0) {
					int code1 = getLeftMovingCode(kMod8);
					int code2 = getRightMovingCode(kMod8, resiBitsLength);
					int leftMovSteps = -rightMovSteps;
					rightMovSteps = 8 - leftMovSteps;
					resiBits = (tdps->residualMidBits[p] & code1) << leftMovSteps;
					p++;
					resiBits = resiBits
							| ((tdps->residualMidBits[p] & code2) >> rightMovSteps);
				} else // rightMovSteps == 0
				{
					int code = getRightMovingCode(kMod8, resiBitsLength);
					resiBits = (tdps->residualMidBits[p] & code);
					p++;
				}
				k += resiBitsLength;
			}

T
tickduan 已提交
294
			// recover the exact data	
T
tickduan 已提交
295 296 297 298 299 300 301 302 303
			memset(curBytes, 0, 8);
			leadingNum = leadNum[l++];
			memcpy(curBytes, preBytes, leadingNum);
			for (j = leadingNum; j < reqBytesLength; j++)
				curBytes[j] = tdps->exactMidBytes[curByteIndex++];
			if (resiBitsLength != 0) {
				unsigned char resiByte = (unsigned char) (resiBits << (8 - resiBitsLength));
				curBytes[reqBytesLength] = resiByte;
			}
T
tickduan 已提交
304
			
T
tickduan 已提交
305
			exactData = bytesToDouble(curBytes);
T
tickduan 已提交
306
			data[i] = exactData;
T
tickduan 已提交
307
			memcpy(preBytes,curBytes,8);
T
tickduan 已提交
308
			predValue = data[i];
T
tickduan 已提交
309 310
			break;
		default:
T
tickduan 已提交
311 312
			//predValue = 2 * data[i-1] - data[i-2];
			//predValue = data[i-1];
T
tickduan 已提交
313
			predValue = fabs(predValue) * precisionTable[type_];
T
tickduan 已提交
314
			data[i] = predValue;
T
tickduan 已提交
315
			break;
T
tickduan 已提交
316 317
		}
	}
T
tickduan 已提交
318 319
	
	free(precisionTable);
T
tickduan 已提交
320 321 322 323 324
	free(leadNum);
	free(type);
	return;
}

T
tickduan 已提交
325
void getSnapshotData_double_1D(double* data, size_t dataSeriesLength, TightDataPointStorageD* tdps, int errBoundMode, int compressionType, double* hist_data, sz_params* pde_params) 
T
tickduan 已提交
326
{
T
tickduan 已提交
327 328 329
	size_t i;
	if (tdps->allSameData) {
		double value = bytesToDouble(tdps->exactMidBytes);
T
tickduan 已提交
330 331

		//*data = (double*)malloc(sizeof(double)*dataSeriesLength); comment by tickduan
T
tickduan 已提交
332
		for (i = 0; i < dataSeriesLength; i++)
T
tickduan 已提交
333
			data[i] = value;
T
tickduan 已提交
334 335 336
	} else {
		if (tdps->rtypeArray == NULL) {
			if(errBoundMode < PW_REL)
T
tickduan 已提交
337
			{
T
tickduan 已提交
338
				decompressDataSeries_double_1D(data, dataSeriesLength, hist_data, tdps);
T
tickduan 已提交
339
			}
T
tickduan 已提交
340 341 342 343 344 345 346
			else 
			{
				if(confparams_dec->accelerate_pw_rel_compression)
					decompressDataSeries_double_1D_pwr_pre_log_MSST19(data, dataSeriesLength, tdps);
				else
					decompressDataSeries_double_1D_pwr_pre_log(data, dataSeriesLength, tdps);
				//decompressDataSeries_double_1D_pwrgroup(data, dataSeriesLength, tdps);
T
tickduan 已提交
347 348 349 350 351 352 353 354
			}
			return;
		} else {
			//TODO
		}
	}
}