-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathoptimize_cpu.cc
More file actions
130 lines (96 loc) · 3.85 KB
/
optimize_cpu.cc
File metadata and controls
130 lines (96 loc) · 3.85 KB
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
26
27
28
29
30
31
32
33
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include "optimize.h"
#include "huffman.h"
#include "test_compress_common.h"
#include "test_compress_cpu.h"
float OptimizationData::getSorted(int index) {
if (index < 0 || index >= count()) {
assert(index >= 0 && index < count());
return 0;
}
return sorted[index];
}
int OptimizationData::findSorted(float value) {
return std::lower_bound(sorted, sorted+count(), value) - sorted;
}
/** Call this to try out compression parameters thresholdValue and binCount.
The resulting output file size and some error metrics will be returned.
input parameters:
optData - just pass the value passed to optimizeParameters()
thresholdValue - the threshold value to test (the actual value, not
the fraction of the data set that is to be cut off)
binCount - the quantization bin count value to test.
If this is negative, no quantization will be done.
testParameters() will just apply the threshold and
then the inverse wavelet transform.
quantAlg - QUANT_ALG_LOG, QUANT_ALG_LLOYD, QUANT_ALG_UNIFORM,
or QUANT_ALG_UNKNOWN if no quantization is to be done.
output parameters:
outputSize - size of the output data, in bytes
l1Error, l2Error, pSNR - error metrics
On error, return false.
On success, return true.
*/
bool testParameters(OptimizationData *o,
float thresholdValue, int binCount,
QuantizeAlgorithm quantAlg,
int *outputSizeBytes,
float *l1Error, float *l2Error, float *mse, float *pSNR,
float *relativeError) {
WaveletCompressionParam param = o->transformedData->param;
param.binCount = binCount;
param.quantAlg = quantAlg;
param.thresholdValue = thresholdValue;
CubeFloat inverseWaveletInput;
inverseWaveletInput.size = o->transformedData->size;
inverseWaveletInput.allocate();
*outputSizeBytes = 0;
int count = o->transformedData->count();
// If binCount is invalid, don't quantize and dequantize.
// Just apply the threshold and reverse the wavelet transform.
if (binCount <= 0) {
// apply threshold
const float *readp = o->transformedData->pointer(0,0,0);
float *writep = inverseWaveletInput.pointer(0,0,0);
for (int i=0; i < count; i++) {
if (fabsf(readp[i]) <= thresholdValue) {
writep[i] = 0;
} else {
writep[i] = readp[i];
}
}
} else { // binCount > 0
// o->transformedData->print("before quantize");
// quantize and dequantize the data
CubeInt quantizedData;
int firstNonzero = o->findSorted(thresholdValue);
int nonzeroCount = count - firstNonzero;
int zeroBin;
const float *nonzeroData = o->sorted + firstNonzero;
if (!quantize(*o->transformedData, quantizedData,
o->maxAbsVal, param,
nonzeroData, nonzeroCount,
o->minVal, o->maxVal, &zeroBin))
return false;
quantizedData.param = param;
if (!o->doCompressZeros) zeroBin = -1;
// quantizedData.print("after quantize");
// compute the huffman coding
Huffman huff;
initHuffman(huff, &quantizedData, NULL, zeroBin);
// just get the size of the encoded data; don't write it out
*outputSizeBytes = huff.totalEncodedLengthBytes();
// dequantize
if (!dequantize(quantizedData, inverseWaveletInput, param))
return false;
}
// compare to original
ErrorAccumulator errAccum;
computeErrorRatesAfterDequant(&inverseWaveletInput, param, o->originalData,
&errAccum);
if (l1Error) *l1Error = errAccum.getL1Error();
if (l1Error) *l2Error = errAccum.getL2Error();
if (mse) *mse = errAccum.getMeanSquaredError();
if (pSNR) *pSNR = errAccum.getPeakSignalToNoiseRatio();
if (relativeError) *relativeError = errAccum.getRelativeError();
return true;
}