/src/tdengine/contrib/TSZ/sz/src/dataCompression.c
Line | Count | Source |
1 | | /** |
2 | | * @file double_compression.c |
3 | | * @author Sheng Di, Dingwen Tao, Xin Liang, Xiangyu Zou, Tao Lu, Wen Xia, Xuan Wang, Weizhe Zhang |
4 | | * @date April, 2016 |
5 | | * @brief Compression Technique for double array |
6 | | * (C) 2016 by Mathematics and Computer Science (MCS), Argonne National Laboratory. |
7 | | * See COPYRIGHT in top-level directory. |
8 | | */ |
9 | | |
10 | | #include <stdio.h> |
11 | | #include <stdlib.h> |
12 | | #include <string.h> |
13 | | #include "sz.h" |
14 | | #include "DynamicByteArray.h" |
15 | | #include "DynamicIntArray.h" |
16 | | #include "TightDataPointStorageD.h" |
17 | | #include "CompressElement.h" |
18 | | #include "dataCompression.h" |
19 | | |
20 | | |
21 | | |
22 | | float computeRangeSize_float(float* oriData, size_t size, float* valueRangeSize, float* medianValue) |
23 | 0 | { |
24 | 0 | size_t i = 0; |
25 | 0 | float min = oriData[0]; |
26 | 0 | float max = min; |
27 | 0 | for(i=1;i<size;i++) |
28 | 0 | { |
29 | 0 | float data = oriData[i]; |
30 | 0 | if(min>data) |
31 | 0 | min = data; |
32 | 0 | else if(max<data) |
33 | 0 | max = data; |
34 | 0 | } |
35 | |
|
36 | 0 | *valueRangeSize = max - min; |
37 | 0 | *medianValue = min + *valueRangeSize/2; |
38 | 0 | return min; |
39 | 0 | } |
40 | | |
41 | | double computeRangeSize_double(double* oriData, size_t size, double* valueRangeSize, double* medianValue) |
42 | 0 | { |
43 | 0 | size_t i = 0; |
44 | 0 | double min = oriData[0]; |
45 | 0 | double max = min; |
46 | 0 | for(i=1;i<size;i++) |
47 | 0 | { |
48 | 0 | double data = oriData[i]; |
49 | 0 | if(min>data) |
50 | 0 | min = data; |
51 | 0 | else if(max<data) |
52 | 0 | max = data; |
53 | 0 | } |
54 | | |
55 | 0 | *valueRangeSize = max - min; |
56 | 0 | *medianValue = min + *valueRangeSize/2; |
57 | 0 | return min; |
58 | 0 | } |
59 | | |
60 | | double min_d(double a, double b) |
61 | 0 | { |
62 | 0 | if(a<b) |
63 | 0 | return a; |
64 | 0 | else |
65 | 0 | return b; |
66 | 0 | } |
67 | | |
68 | | double max_d(double a, double b) |
69 | 0 | { |
70 | 0 | if(a>b) |
71 | 0 | return a; |
72 | 0 | else |
73 | 0 | return b; |
74 | 0 | } |
75 | | |
76 | | float min_f(float a, float b) |
77 | 0 | { |
78 | 0 | if(a<b) |
79 | 0 | return a; |
80 | 0 | else |
81 | 0 | return b; |
82 | 0 | } |
83 | | |
84 | | float max_f(float a, float b) |
85 | 0 | { |
86 | 0 | if(a>b) |
87 | 0 | return a; |
88 | 0 | else |
89 | 0 | return b; |
90 | 0 | } |
91 | | |
92 | | double getRealPrecision_double(double valueRangeSize, int errBoundMode, double absErrBound, double relBoundRatio, int *status) |
93 | 0 | { |
94 | 0 | int state = SZ_SUCCESS; |
95 | 0 | double precision = 0; |
96 | 0 | if(errBoundMode==SZ_ABS||errBoundMode==ABS_OR_PW_REL||errBoundMode==ABS_AND_PW_REL) |
97 | 0 | precision = absErrBound; |
98 | 0 | else if(errBoundMode==REL||errBoundMode==REL_OR_PW_REL||errBoundMode==REL_AND_PW_REL) |
99 | 0 | precision = relBoundRatio*valueRangeSize; |
100 | 0 | else if(errBoundMode==ABS_AND_REL) |
101 | 0 | precision = min_d(absErrBound, relBoundRatio*valueRangeSize); |
102 | 0 | else if(errBoundMode==ABS_OR_REL) |
103 | 0 | precision = max_d(absErrBound, relBoundRatio*valueRangeSize); |
104 | 0 | else if(errBoundMode==PW_REL) |
105 | 0 | precision = 0; |
106 | 0 | else |
107 | 0 | { |
108 | 0 | printf("Error: error-bound-mode is incorrect!\n"); |
109 | 0 | state = SZ_BERR; |
110 | 0 | } |
111 | 0 | *status = state; |
112 | 0 | return precision; |
113 | 0 | } |
114 | | |
115 | | double getRealPrecision_float(float valueRangeSize, int errBoundMode, double absErrBound, double relBoundRatio, int *status) |
116 | 0 | { |
117 | 0 | int state = SZ_SUCCESS; |
118 | 0 | double precision = 0; |
119 | 0 | if(errBoundMode==SZ_ABS||errBoundMode==ABS_OR_PW_REL||errBoundMode==ABS_AND_PW_REL) |
120 | 0 | precision = absErrBound; |
121 | 0 | else if(errBoundMode==REL||errBoundMode==REL_OR_PW_REL||errBoundMode==REL_AND_PW_REL) |
122 | 0 | precision = relBoundRatio*valueRangeSize; |
123 | 0 | else if(errBoundMode==ABS_AND_REL) |
124 | 0 | precision = min_f(absErrBound, relBoundRatio*valueRangeSize); |
125 | 0 | else if(errBoundMode==ABS_OR_REL) |
126 | 0 | precision = max_f(absErrBound, relBoundRatio*valueRangeSize); |
127 | 0 | else if(errBoundMode==PW_REL) |
128 | 0 | precision = 0; |
129 | 0 | else |
130 | 0 | { |
131 | 0 | printf("Error: error-bound-mode is incorrect!\n"); |
132 | 0 | state = SZ_BERR; |
133 | 0 | } |
134 | 0 | *status = state; |
135 | 0 | return precision; |
136 | 0 | } |
137 | | |
138 | | double getRealPrecision_int(int64_t valueRangeSize, int errBoundMode, double absErrBound, double relBoundRatio, int *status) |
139 | 0 | { |
140 | 0 | int state = SZ_SUCCESS; |
141 | 0 | double precision = 0; |
142 | 0 | if(errBoundMode==SZ_ABS||errBoundMode==ABS_OR_PW_REL||errBoundMode==ABS_AND_PW_REL) |
143 | 0 | precision = absErrBound; |
144 | 0 | else if(errBoundMode==REL||errBoundMode==REL_OR_PW_REL||errBoundMode==REL_AND_PW_REL) |
145 | 0 | precision = relBoundRatio*valueRangeSize; |
146 | 0 | else if(errBoundMode==ABS_AND_REL) |
147 | 0 | precision = min_f(absErrBound, relBoundRatio*valueRangeSize); |
148 | 0 | else if(errBoundMode==ABS_OR_REL) |
149 | 0 | precision = max_f(absErrBound, relBoundRatio*valueRangeSize); |
150 | 0 | else if(errBoundMode==PW_REL) |
151 | 0 | precision = -1; |
152 | 0 | else |
153 | 0 | { |
154 | 0 | printf("Error: error-bound-mode is incorrect!\n"); |
155 | 0 | state = SZ_BERR; |
156 | 0 | } |
157 | 0 | *status = state; |
158 | 0 | return precision; |
159 | 0 | } |
160 | | |
161 | | void symTransform_8bytes(unsigned char data[8]) |
162 | 0 | { |
163 | 0 | unsigned char tmp = data[0]; |
164 | 0 | data[0] = data[7]; |
165 | 0 | data[7] = tmp; |
166 | |
|
167 | 0 | tmp = data[1]; |
168 | 0 | data[1] = data[6]; |
169 | 0 | data[6] = tmp; |
170 | | |
171 | 0 | tmp = data[2]; |
172 | 0 | data[2] = data[5]; |
173 | 0 | data[5] = tmp; |
174 | | |
175 | 0 | tmp = data[3]; |
176 | 0 | data[3] = data[4]; |
177 | 0 | data[4] = tmp; |
178 | 0 | } |
179 | | |
180 | | INLINE void symTransform_2bytes(unsigned char data[2]) |
181 | 0 | { |
182 | 0 | unsigned char tmp = data[0]; |
183 | 0 | data[0] = data[1]; |
184 | 0 | data[1] = tmp; |
185 | 0 | } |
186 | | |
187 | | INLINE void symTransform_4bytes(unsigned char data[4]) |
188 | 0 | { |
189 | 0 | unsigned char tmp = data[0]; |
190 | 0 | data[0] = data[3]; |
191 | 0 | data[3] = tmp; |
192 | |
|
193 | 0 | tmp = data[1]; |
194 | 0 | data[1] = data[2]; |
195 | 0 | data[2] = tmp; |
196 | 0 | } |
197 | | |
198 | | INLINE void compressSingleFloatValue(FloatValueCompressElement *vce, float oriValue, float precision, float medianValue, |
199 | | int reqLength, int reqBytesLength, int resiBitsLength) |
200 | 0 | { |
201 | 0 | lfloat diffVal; |
202 | 0 | diffVal.value = oriValue - medianValue; |
203 | | |
204 | | // calc ignore bit count |
205 | 0 | int ignBitCount = 32 - reqLength; |
206 | 0 | if(ignBitCount<0) |
207 | 0 | ignBitCount = 0; |
208 | | |
209 | 0 | int32ToBytes_bigEndian(vce->curBytes, diffVal.ivalue); |
210 | | |
211 | | // truncate diff value tail bit with ignBitCount |
212 | 0 | diffVal.ivalue = (diffVal.ivalue >> ignBitCount) << ignBitCount; |
213 | | |
214 | | // save to vce |
215 | 0 | vce->data = diffVal.value + medianValue; |
216 | 0 | vce->curValue = diffVal.ivalue; |
217 | 0 | vce->reqBytesLength = reqBytesLength; |
218 | 0 | vce->resiBitsLength = resiBitsLength; |
219 | 0 | } |
220 | | |
221 | | void compressSingleDoubleValue(DoubleValueCompressElement *vce, double tgtValue, double precision, double medianValue, |
222 | | int reqLength, int reqBytesLength, int resiBitsLength) |
223 | 0 | { |
224 | 0 | double normValue = tgtValue - medianValue; |
225 | |
|
226 | 0 | ldouble lfBuf; |
227 | 0 | lfBuf.value = normValue; |
228 | | |
229 | 0 | int ignBytesLength = 64 - reqLength; |
230 | 0 | if(ignBytesLength<0) |
231 | 0 | ignBytesLength = 0; |
232 | |
|
233 | 0 | uint64_t tmp_long = lfBuf.lvalue; |
234 | 0 | int64ToBytes_bigEndian(vce->curBytes, tmp_long); |
235 | | |
236 | 0 | lfBuf.lvalue = (lfBuf.lvalue >> ignBytesLength)<<ignBytesLength; |
237 | | |
238 | | //double tmpValue = lfBuf.value; |
239 | | |
240 | 0 | vce->data = lfBuf.value+medianValue; |
241 | 0 | vce->curValue = tmp_long; |
242 | 0 | vce->reqBytesLength = reqBytesLength; |
243 | 0 | vce->resiBitsLength = resiBitsLength; |
244 | 0 | } |
245 | | |
246 | | int compIdenticalLeadingBytesCount_double(unsigned char* preBytes, unsigned char* curBytes) |
247 | 0 | { |
248 | 0 | int i, n = 0; |
249 | 0 | for(i=0;i<8;i++) |
250 | 0 | if(preBytes[i]==curBytes[i]) |
251 | 0 | n++; |
252 | 0 | else |
253 | 0 | break; |
254 | 0 | if(n>3) n = 3; |
255 | 0 | return n; |
256 | 0 | } |
257 | | |
258 | | INLINE int compIdenticalLeadingBytesCount_float(unsigned char* preBytes, unsigned char* curBytes) |
259 | 0 | { |
260 | 0 | int i, n = 0; |
261 | 0 | for(i=0;i<4;i++) |
262 | 0 | if(preBytes[i]==curBytes[i]) |
263 | 0 | n++; |
264 | 0 | else |
265 | 0 | break; |
266 | 0 | if(n>3) n = 3; |
267 | 0 | return n; |
268 | 0 | } |
269 | | |
270 | | //TODO double-check the correctness... |
271 | | INLINE void addExactData(DynamicByteArray *exactMidByteArray, DynamicIntArray *exactLeadNumArray, |
272 | | DynamicIntArray *resiBitArray, LossyCompressionElement *lce) |
273 | 0 | { |
274 | 0 | int i; |
275 | 0 | int leadByteLength = lce->leadingZeroBytes; |
276 | 0 | addDIA_Data(exactLeadNumArray, leadByteLength); |
277 | 0 | unsigned char* intMidBytes = lce->integerMidBytes; |
278 | 0 | int integerMidBytesLength = lce->integerMidBytes_Length; |
279 | 0 | int resMidBitsLength = lce->resMidBitsLength; |
280 | 0 | if(intMidBytes!=NULL||resMidBitsLength!=0) |
281 | 0 | { |
282 | 0 | if(intMidBytes!=NULL) |
283 | 0 | for(i = 0;i<integerMidBytesLength;i++) |
284 | 0 | addDBA_Data(exactMidByteArray, intMidBytes[i]); |
285 | 0 | if(resMidBitsLength!=0) |
286 | 0 | addDIA_Data(resiBitArray, lce->residualMidBits); |
287 | 0 | } |
288 | 0 | } |
289 | | |
290 | | /** |
291 | | * @deprecated |
292 | | * @return: the length of the coefficient array. |
293 | | * */ |
294 | | int getPredictionCoefficients(int layers, int dimension, int **coeff_array, int *status) |
295 | 0 | { |
296 | 0 | size_t size = 0; |
297 | 0 | switch(dimension) |
298 | 0 | { |
299 | 0 | case 1: |
300 | 0 | switch(layers) |
301 | 0 | { |
302 | 0 | case 1: |
303 | 0 | *coeff_array = (int*)malloc(sizeof(int)); |
304 | 0 | (*coeff_array)[0] = 1; |
305 | 0 | size = 1; |
306 | 0 | break; |
307 | 0 | case 2: |
308 | 0 | *coeff_array = (int*)malloc(2*sizeof(int)); |
309 | 0 | (*coeff_array)[0] = 2; |
310 | 0 | (*coeff_array)[1] = -1; |
311 | 0 | size = 2; |
312 | 0 | break; |
313 | 0 | case 3: |
314 | 0 | *coeff_array = (int*)malloc(3*sizeof(int)); |
315 | 0 | (*coeff_array)[0] = 3; |
316 | 0 | (*coeff_array)[1] = -3; |
317 | 0 | (*coeff_array)[2] = 1; |
318 | 0 | break; |
319 | 0 | } |
320 | 0 | break; |
321 | 0 | case 2: |
322 | 0 | switch(layers) |
323 | 0 | { |
324 | 0 | case 1: |
325 | | |
326 | 0 | break; |
327 | 0 | case 2: |
328 | | |
329 | 0 | break; |
330 | 0 | case 3: |
331 | | |
332 | 0 | break; |
333 | 0 | } |
334 | 0 | break; |
335 | 0 | case 3: |
336 | 0 | switch(layers) |
337 | 0 | { |
338 | 0 | case 1: |
339 | | |
340 | 0 | break; |
341 | 0 | case 2: |
342 | | |
343 | 0 | break; |
344 | 0 | case 3: |
345 | | |
346 | 0 | break; |
347 | 0 | } |
348 | 0 | break; |
349 | 0 | default: |
350 | 0 | printf("Error: dimension must be no greater than 3 in the current version.\n"); |
351 | 0 | *status = SZ_DERR; |
352 | 0 | } |
353 | 0 | *status = SZ_SUCCESS; |
354 | 0 | return size; |
355 | 0 | } |
356 | | |
357 | | int computeBlockEdgeSize_2D(int segmentSize) |
358 | 0 | { |
359 | 0 | int i = 1; |
360 | 0 | for(i=1; i<segmentSize;i++) |
361 | 0 | { |
362 | 0 | if(i*i>segmentSize) |
363 | 0 | break; |
364 | 0 | } |
365 | 0 | return i; |
366 | | //return (int)(sqrt(segmentSize)+1); |
367 | 0 | } |
368 | | |
369 | | int computeBlockEdgeSize_3D(int segmentSize) |
370 | 0 | { |
371 | 0 | int i = 1; |
372 | 0 | for(i=1; i<segmentSize;i++) |
373 | 0 | { |
374 | 0 | if(i*i*i>segmentSize) |
375 | 0 | break; |
376 | 0 | } |
377 | 0 | return i; |
378 | | //return (int)(pow(segmentSize, 1.0/3)+1); |
379 | 0 | } |
380 | | |
381 | | //The following functions are float-precision version of dealing with the unpredictable data points |
382 | | int generateLossyCoefficients_float(float* oriData, double precision, size_t nbEle, int* reqBytesLength, int* resiBitsLength, float* medianValue, float* decData) |
383 | 0 | { |
384 | 0 | float valueRangeSize; |
385 | | |
386 | 0 | computeRangeSize_float(oriData, nbEle, &valueRangeSize, medianValue); |
387 | 0 | short radExpo = getExponent_float(valueRangeSize/2); |
388 | | |
389 | 0 | int reqLength; |
390 | 0 | computeReqLength_float(precision, radExpo, &reqLength, medianValue); |
391 | | |
392 | 0 | *reqBytesLength = reqLength/8; |
393 | 0 | *resiBitsLength = reqLength%8; |
394 | | |
395 | 0 | size_t i = 0; |
396 | 0 | for(i = 0;i < nbEle;i++) |
397 | 0 | { |
398 | 0 | float normValue = oriData[i] - *medianValue; |
399 | |
|
400 | 0 | lfloat lfBuf; |
401 | 0 | lfBuf.value = normValue; |
402 | | |
403 | 0 | int ignBytesLength = 32 - reqLength; |
404 | 0 | if(ignBytesLength<0) |
405 | 0 | ignBytesLength = 0; |
406 | | |
407 | 0 | lfBuf.ivalue = (lfBuf.ivalue >> ignBytesLength) << ignBytesLength; |
408 | | |
409 | | //float tmpValue = lfBuf.value; |
410 | | |
411 | 0 | decData[i] = lfBuf.value + *medianValue; |
412 | 0 | } |
413 | 0 | return reqLength; |
414 | 0 | } |
415 | | |
416 | | /** |
417 | | * @param float* oriData: inplace argument (input / output) |
418 | | * |
419 | | * */ |
420 | | int compressExactDataArray_float(float* oriData, double precision, size_t nbEle, unsigned char** leadArray, unsigned char** midArray, unsigned char** resiArray, |
421 | | int reqLength, int reqBytesLength, int resiBitsLength, float medianValue) |
422 | 0 | { |
423 | | //allocate memory for coefficient compression arrays |
424 | 0 | DynamicIntArray *exactLeadNumArray; |
425 | 0 | new_DIA(&exactLeadNumArray, DynArrayInitLen); |
426 | 0 | DynamicByteArray *exactMidByteArray; |
427 | 0 | new_DBA(&exactMidByteArray, DynArrayInitLen); |
428 | 0 | DynamicIntArray *resiBitArray; |
429 | 0 | new_DIA(&resiBitArray, DynArrayInitLen); |
430 | 0 | unsigned char preDataBytes[4] = {0,0,0,0}; |
431 | | |
432 | | //allocate memory for vce and lce |
433 | 0 | FloatValueCompressElement *vce = (FloatValueCompressElement*)malloc(sizeof(FloatValueCompressElement)); |
434 | 0 | LossyCompressionElement *lce = (LossyCompressionElement*)malloc(sizeof(LossyCompressionElement)); |
435 | |
|
436 | 0 | size_t i = 0; |
437 | 0 | for(i = 0;i < nbEle;i++) |
438 | 0 | { |
439 | 0 | compressSingleFloatValue(vce, oriData[i], precision, medianValue, reqLength, reqBytesLength, resiBitsLength); |
440 | 0 | updateLossyCompElement_Float(vce->curBytes, preDataBytes, reqBytesLength, resiBitsLength, lce); |
441 | 0 | memcpy(preDataBytes,vce->curBytes,4); |
442 | 0 | addExactData(exactMidByteArray, exactLeadNumArray, resiBitArray, lce); |
443 | 0 | oriData[i] = vce->data; |
444 | 0 | } |
445 | 0 | convertDIAtoInts(exactLeadNumArray, leadArray); |
446 | 0 | convertDBAtoBytes(exactMidByteArray,midArray); |
447 | 0 | convertDIAtoInts(resiBitArray, resiArray); |
448 | |
|
449 | 0 | size_t midArraySize = exactMidByteArray->size; |
450 | | |
451 | 0 | free(vce); |
452 | 0 | free(lce); |
453 | | |
454 | 0 | free_DIA(exactLeadNumArray); |
455 | 0 | free_DBA(exactMidByteArray); |
456 | 0 | free_DIA(resiBitArray); |
457 | | |
458 | 0 | return midArraySize; |
459 | 0 | } |
460 | | |
461 | | void decompressExactDataArray_float(unsigned char* leadNum, unsigned char* exactMidBytes, unsigned char* residualMidBits, size_t nbEle, int reqLength, float medianValue, float** decData) |
462 | 0 | { |
463 | 0 | *decData = (float*)malloc(nbEle*sizeof(float)); |
464 | 0 | size_t i = 0, j = 0, k = 0, l = 0, p = 0, curByteIndex = 0; |
465 | 0 | float exactData = 0; |
466 | 0 | unsigned char preBytes[4] = {0,0,0,0}; |
467 | 0 | unsigned char curBytes[4]; |
468 | 0 | int resiBits; |
469 | 0 | unsigned char leadingNum; |
470 | | |
471 | 0 | int reqBytesLength = reqLength/8; |
472 | 0 | int resiBitsLength = reqLength%8; |
473 | | |
474 | 0 | for(i = 0; i<nbEle;i++) |
475 | 0 | { |
476 | | // compute resiBits |
477 | 0 | resiBits = 0; |
478 | 0 | if (resiBitsLength != 0) { |
479 | 0 | int kMod8 = k % 8; |
480 | 0 | int rightMovSteps = getRightMovingSteps(kMod8, resiBitsLength); |
481 | 0 | if (rightMovSteps > 0) { |
482 | 0 | int code = getRightMovingCode(kMod8, resiBitsLength); |
483 | 0 | resiBits = (residualMidBits[p] & code) >> rightMovSteps; |
484 | 0 | } else if (rightMovSteps < 0) { |
485 | 0 | int code1 = getLeftMovingCode(kMod8); |
486 | 0 | int code2 = getRightMovingCode(kMod8, resiBitsLength); |
487 | 0 | int leftMovSteps = -rightMovSteps; |
488 | 0 | rightMovSteps = 8 - leftMovSteps; |
489 | 0 | resiBits = (residualMidBits[p] & code1) << leftMovSteps; |
490 | 0 | p++; |
491 | 0 | resiBits = resiBits |
492 | 0 | | ((residualMidBits[p] & code2) >> rightMovSteps); |
493 | 0 | } else // rightMovSteps == 0 |
494 | 0 | { |
495 | 0 | int code = getRightMovingCode(kMod8, resiBitsLength); |
496 | 0 | resiBits = (residualMidBits[p] & code); |
497 | 0 | p++; |
498 | 0 | } |
499 | 0 | k += resiBitsLength; |
500 | 0 | } |
501 | | |
502 | | // recover the exact data |
503 | 0 | memset(curBytes, 0, 4); |
504 | 0 | leadingNum = leadNum[l++]; |
505 | 0 | memcpy(curBytes, preBytes, leadingNum); |
506 | 0 | for (j = leadingNum; j < reqBytesLength; j++) |
507 | 0 | curBytes[j] = exactMidBytes[curByteIndex++]; |
508 | 0 | if (resiBitsLength != 0) { |
509 | 0 | unsigned char resiByte = (unsigned char) (resiBits << (8 - resiBitsLength)); |
510 | 0 | curBytes[reqBytesLength] = resiByte; |
511 | 0 | } |
512 | |
|
513 | 0 | exactData = bytesToFloat(curBytes); |
514 | 0 | (*decData)[i] = exactData + medianValue; |
515 | 0 | memcpy(preBytes,curBytes,4); |
516 | 0 | } |
517 | 0 | } |
518 | | |
519 | | //double-precision version of dealing with unpredictable data points in sz 2.0 |
520 | | int generateLossyCoefficients_double(double* oriData, double precision, size_t nbEle, int* reqBytesLength, int* resiBitsLength, double* medianValue, double* decData) |
521 | 0 | { |
522 | 0 | double valueRangeSize; |
523 | | |
524 | 0 | computeRangeSize_double(oriData, nbEle, &valueRangeSize, medianValue); |
525 | 0 | short radExpo = getExponent_double(valueRangeSize/2); |
526 | | |
527 | 0 | int reqLength; |
528 | 0 | computeReqLength_double(precision, radExpo, &reqLength, medianValue); |
529 | | |
530 | 0 | *reqBytesLength = reqLength/8; |
531 | 0 | *resiBitsLength = reqLength%8; |
532 | | |
533 | 0 | size_t i = 0; |
534 | 0 | for(i = 0;i < nbEle;i++) |
535 | 0 | { |
536 | 0 | double normValue = oriData[i] - *medianValue; |
537 | |
|
538 | 0 | ldouble ldBuf; |
539 | 0 | ldBuf.value = normValue; |
540 | | |
541 | 0 | int ignBytesLength = 64 - reqLength; |
542 | 0 | if(ignBytesLength<0) |
543 | 0 | ignBytesLength = 0; |
544 | | |
545 | 0 | ldBuf.lvalue = (ldBuf.lvalue >> ignBytesLength) << ignBytesLength; |
546 | | |
547 | 0 | decData[i] = ldBuf.value + *medianValue; |
548 | 0 | } |
549 | 0 | return reqLength; |
550 | 0 | } |
551 | | |
552 | | /** |
553 | | * @param double* oriData: inplace argument (input / output) |
554 | | * |
555 | | * */ |
556 | | int compressExactDataArray_double(double* oriData, double precision, size_t nbEle, unsigned char** leadArray, unsigned char** midArray, unsigned char** resiArray, |
557 | | int reqLength, int reqBytesLength, int resiBitsLength, double medianValue) |
558 | 0 | { |
559 | | //allocate memory for coefficient compression arrays |
560 | 0 | DynamicIntArray *exactLeadNumArray; |
561 | 0 | new_DIA(&exactLeadNumArray, DynArrayInitLen); |
562 | 0 | DynamicByteArray *exactMidByteArray; |
563 | 0 | new_DBA(&exactMidByteArray, DynArrayInitLen); |
564 | 0 | DynamicIntArray *resiBitArray; |
565 | 0 | new_DIA(&resiBitArray, DynArrayInitLen); |
566 | 0 | unsigned char preDataBytes[8] = {0,0,0,0,0,0,0,0}; |
567 | | |
568 | | //allocate memory for vce and lce |
569 | 0 | DoubleValueCompressElement *vce = (DoubleValueCompressElement*)malloc(sizeof(DoubleValueCompressElement)); |
570 | 0 | LossyCompressionElement *lce = (LossyCompressionElement*)malloc(sizeof(LossyCompressionElement)); |
571 | |
|
572 | 0 | size_t i = 0; |
573 | 0 | for(i = 0;i < nbEle;i++) |
574 | 0 | { |
575 | 0 | compressSingleDoubleValue(vce, oriData[i], precision, medianValue, reqLength, reqBytesLength, resiBitsLength); |
576 | 0 | updateLossyCompElement_Double(vce->curBytes, preDataBytes, reqBytesLength, resiBitsLength, lce); |
577 | 0 | memcpy(preDataBytes,vce->curBytes,8); |
578 | 0 | addExactData(exactMidByteArray, exactLeadNumArray, resiBitArray, lce); |
579 | 0 | oriData[i] = vce->data; |
580 | 0 | } |
581 | 0 | convertDIAtoInts(exactLeadNumArray, leadArray); |
582 | 0 | convertDBAtoBytes(exactMidByteArray,midArray); |
583 | 0 | convertDIAtoInts(resiBitArray, resiArray); |
584 | |
|
585 | 0 | size_t midArraySize = exactMidByteArray->size; |
586 | | |
587 | 0 | free(vce); |
588 | 0 | free(lce); |
589 | | |
590 | 0 | free_DIA(exactLeadNumArray); |
591 | 0 | free_DBA(exactMidByteArray); |
592 | 0 | free_DIA(resiBitArray); |
593 | | |
594 | 0 | return midArraySize; |
595 | 0 | } |
596 | | |
597 | | void decompressExactDataArray_double(unsigned char* leadNum, unsigned char* exactMidBytes, unsigned char* residualMidBits, size_t nbEle, int reqLength, double medianValue, double** decData) |
598 | 0 | { |
599 | 0 | *decData = (double*)malloc(nbEle*sizeof(double)); |
600 | 0 | size_t i = 0, j = 0, k = 0, l = 0, p = 0, curByteIndex = 0; |
601 | 0 | double exactData = 0; |
602 | 0 | unsigned char preBytes[8] = {0,0,0,0,0,0,0,0}; |
603 | 0 | unsigned char curBytes[8]; |
604 | 0 | int resiBits; |
605 | 0 | unsigned char leadingNum; |
606 | | |
607 | 0 | int reqBytesLength = reqLength/8; |
608 | 0 | int resiBitsLength = reqLength%8; |
609 | | |
610 | 0 | for(i = 0; i<nbEle;i++) |
611 | 0 | { |
612 | | // compute resiBits |
613 | 0 | resiBits = 0; |
614 | 0 | if (resiBitsLength != 0) { |
615 | 0 | int kMod8 = k % 8; |
616 | 0 | int rightMovSteps = getRightMovingSteps(kMod8, resiBitsLength); |
617 | 0 | if (rightMovSteps > 0) { |
618 | 0 | int code = getRightMovingCode(kMod8, resiBitsLength); |
619 | 0 | resiBits = (residualMidBits[p] & code) >> rightMovSteps; |
620 | 0 | } else if (rightMovSteps < 0) { |
621 | 0 | int code1 = getLeftMovingCode(kMod8); |
622 | 0 | int code2 = getRightMovingCode(kMod8, resiBitsLength); |
623 | 0 | int leftMovSteps = -rightMovSteps; |
624 | 0 | rightMovSteps = 8 - leftMovSteps; |
625 | 0 | resiBits = (residualMidBits[p] & code1) << leftMovSteps; |
626 | 0 | p++; |
627 | 0 | resiBits = resiBits |
628 | 0 | | ((residualMidBits[p] & code2) >> rightMovSteps); |
629 | 0 | } else // rightMovSteps == 0 |
630 | 0 | { |
631 | 0 | int code = getRightMovingCode(kMod8, resiBitsLength); |
632 | 0 | resiBits = (residualMidBits[p] & code); |
633 | 0 | p++; |
634 | 0 | } |
635 | 0 | k += resiBitsLength; |
636 | 0 | } |
637 | | |
638 | | // recover the exact data |
639 | 0 | memset(curBytes, 0, 8); |
640 | 0 | leadingNum = leadNum[l++]; |
641 | 0 | memcpy(curBytes, preBytes, leadingNum); |
642 | 0 | for (j = leadingNum; j < reqBytesLength; j++) |
643 | 0 | curBytes[j] = exactMidBytes[curByteIndex++]; |
644 | 0 | if (resiBitsLength != 0) { |
645 | 0 | unsigned char resiByte = (unsigned char) (resiBits << (8 - resiBitsLength)); |
646 | 0 | curBytes[reqBytesLength] = resiByte; |
647 | 0 | } |
648 | |
|
649 | 0 | exactData = bytesToDouble(curBytes); |
650 | 0 | (*decData)[i] = exactData + medianValue; |
651 | 0 | memcpy(preBytes,curBytes,8); |
652 | 0 | } |
653 | 0 | } |