Coverage Report

Created: 2026-06-09 06:46

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}