Peano
Loading...
Searching...
No Matches
CompressedFloatingPointNumbers.cpp
Go to the documentation of this file.
2#include "tarch/Assertions.h"
4#include "tarch/la/Scalar.h"
5
6#include <bitset>
7
8
10 const double values[],
11 int count,
12 double maxError
13) {
14 assertion(count>0);
15
16 int result = 0;
17 for (int i=0; i<count; i++) {
18 result = std::max(result, findMostAgressiveCompression(values[i],maxError));
19 }
20 assertion(result>0);
21 return result;
22}
23
24
25#if defined(CompilerICC)
27#elif defined(CompilerCLANG)
29#else
31#endif
32 double value,
33 double maxError
34) {
35 if (std::abs(value)<maxError) {
36 return 0;
37 }
38
39 assertion(value==value);
40 assertion1( sizeof(long int)*8>=64, sizeof(long int) );
41 assertion(maxError>=0.0);
42
43 // We may not use 7 though we use seven out of eight bits for the first byte.
44 // If we shift by seven, we can end up with the highest byte set for
45 // 0.0155759, e.g.
46 int shiftExponent = 6;
47
48 const long int sign = value < 0.0 ? -1 : 1;
49
50 if (sign<0) {
51 value = -value;
52 }
53
54 int integerExponent;
55 const double significand = std::frexp(value , &integerExponent);
56
57 int usedBytes = 0;
58 double error = std::numeric_limits<double>::max();
59 while (
60 usedBytes<6
61 &&
62 error > maxError
63 ) {
64 usedBytes++;
65
66 const double shiftMantissa = std::pow( 2.0,shiftExponent );
67
68 int exponent = integerExponent-shiftExponent;
69 long int mantissa = static_cast<long int>( std::round(significand*shiftMantissa) );
70
71 error = std::abs( std::ldexp(mantissa,exponent) - value );
72
73 shiftExponent+=8;
74 }
75
76 assertion(usedBytes>=1);
77 assertion(usedBytes<=7);
78
79 return usedBytes;
80}
81
82
83
84#ifdef CompilerICC
86#elif defined(CompilerCLANG)
88#else
90#endif
91 double value,
92 char exponent[8],
93 long int mantissa[8],
94 double error[8]
95) {
96 assertion(value==value);
97 assertion1( sizeof(long int)*8>=64, sizeof(long int) );
98
99 // We may not use 7 though we use seven out of eight bits for the first byte.
100 // If we shift by seven, we can end up with the highest byte set for
101 // 0.0155759, e.g.
102 int shiftExponent = 6;
103
104 const long int sign = value < 0.0 ? -1 : 1;
105
106 if (sign<0) {
107 value = -value;
108 }
109
110 int integerExponent;
111 const double significand = std::frexp(value , &integerExponent);
112
113 for (int i=0; i<8; i++) {
114 const double shiftMantissa = std::pow( 2.0,shiftExponent );
115
116 if (integerExponent-shiftExponent >= std::numeric_limits<char>::min() ) {
117 exponent[i] = static_cast<char>( integerExponent-shiftExponent );
118 mantissa[i] = static_cast<long int>( std::round(significand*shiftMantissa) );
119 }
120 else {
121 exponent[i] = 0;
122 mantissa[i] = 0;
123 }
124 error[i] = std::abs( std::ldexp(mantissa[i],exponent[i]) - value );
125
126 assertion5( mantissa[i]>=0, value, mantissa[i], exponent[i], error[i], sign );
127
128 std::bitset<64>* mantissaAsBitset = reinterpret_cast<std::bitset<64>*>( &(mantissa[i]) );
129
130 #ifdef Asserts
131 for (int j=(i+1)*8-1; j<64; j++) {
133 !(*mantissaAsBitset)[j],
134 *mantissaAsBitset, value, static_cast<int>( exponent[i] ), mantissa[i], error[i], i, j, significand, integerExponent
135 );
136 }
137 #endif
138
139 if (sign<0) {
140 assertion ( (*mantissaAsBitset)[ (i+1)*8-1 ]==false );
141 mantissaAsBitset->flip( (i+1)*8-1 );
142 }
143
144 shiftExponent+=8;
145 }
146}
147
148
149#ifdef CompilerICC
151#elif defined(CompilerCLANG)
153#else
155#endif
156 double value,
157 char& exponent,
158 long int& mantissa,
159 int bytesForMantissa
160) {
161 assertion(value==value);
162 assertion1( sizeof(long int)*8>=64, sizeof(long int) );
163
164 // We may not use 7 though we use seven out of eight bits for the first byte.
165 // If we shift by seven, we can end up with the highest byte set for
166 // 0.0155759, e.g.
167 int shiftExponent = 6 + (bytesForMantissa-1)*8;
168
169 const long int sign = value < 0.0 ? -1 : 1;
170
171 if (sign<0) {
172 value = -value;
173 }
174
175 int integerExponent;
176 const double significand = std::frexp(value , &integerExponent);
177
178 int exponentAsInteger = integerExponent-shiftExponent;
179
180 if (exponentAsInteger <= std::numeric_limits<char>::min()) {
181 exponent = 0;
182 mantissa = 0;
183 }
184 else {
185 exponent = static_cast<char>( exponentAsInteger );
186
187 const double shiftMantissa = std::pow( 2.0,shiftExponent );
188 mantissa = static_cast<long int>( std::round(significand*shiftMantissa) );
189
190 assertion4( mantissa>=0, value, mantissa, exponent, sign );
191
192 std::bitset<64>* mantissaAsBitset = reinterpret_cast<std::bitset<64>*>( &(mantissa) );
193
194 if (sign<0) {
195 assertion ( (*mantissaAsBitset)[ (bytesForMantissa)*8-1 ]==false );
196 mantissaAsBitset->flip( (bytesForMantissa)*8-1 );
197 }
198 }
199}
200
201
202
204 double value,
205 char exponent[4],
206 int mantissa[4],
207 double error[4]
208) {
209 assertion(value==value);
210 assertion1( sizeof(int)*8>=32, sizeof(int) );
211
212 // We may not use 7 though we use seven out of eight bits for the first byte.
213 // If we shift by seven, we can end up with the highest byte set for
214 // 0.0155759, e.g.
215 int shiftExponent = 6;
216
217 const long int sign = value < 0.0 ? -1 : 1;
218
219 if (sign<0) {
220 value = -value;
221 }
222
223 int integerExponent;
224 const double significand = std::frexp(value , &integerExponent);
225
226 for (int i=0; i<4; i++) {
227 const double shiftMantissa = std::pow( 2.0,shiftExponent );
228
229 if (integerExponent-shiftExponent >= std::numeric_limits<char>::min() ) {
230 exponent[i] = static_cast<char>( integerExponent-shiftExponent );
231 mantissa[i] = static_cast<int>( std::round(significand*shiftMantissa) );
232 }
233 else {
234 exponent[i] = 0;
235 mantissa[i] = 0;
236 }
237 error[i] = std::abs( std::ldexp(mantissa[i],exponent[i]) - value );
238
239 assertion5( mantissa[i]>=0, value, mantissa[i], exponent[i], error[i], sign );
240
241 std::bitset< sizeof(int)*8 >* mantissaAsBitset = reinterpret_cast<std::bitset< sizeof(int)*8 >*>( &(mantissa[i]) );
242
243 #ifdef Asserts
244 for (int j=(i+1)*8-1; j<static_cast<int>( sizeof(int) )*8; j++) {
246 !(*mantissaAsBitset)[j],
247 *mantissaAsBitset, value, static_cast<int>( exponent[i] ), mantissa[i], error[i], i, j, significand, integerExponent
248 );
249 }
250 #endif
251
252 if (sign<0) {
253 assertion ( (*mantissaAsBitset)[ (i+1)*8-1 ]==false );
254 mantissaAsBitset->flip( (i+1)*8-1 );
255 }
256
257 shiftExponent+=8;
258 }
259}
260
261
263 char exponent,
264 long int mantissa,
265 int bytesUsed
266) {
267 assertion( bytesUsed>=1 );
268
269 std::bitset<64>* mantissaAsBitset = reinterpret_cast<std::bitset<64>*>( &mantissa );
270
271 if ( (*mantissaAsBitset)[ bytesUsed*8-1 ] ) {
272 mantissaAsBitset->flip( bytesUsed*8-1 );
273 mantissa = -mantissa;
274 }
275
276 const double doubleMantissa = mantissa;
277 const int intExponent = exponent;
278
279 return std::ldexp(doubleMantissa,intExponent);
280}
281
282
#define assertion4(expr, param0, param1, param2, param3)
#define assertion1(expr, param)
#define assertion9(expr, param0, param1, param2, param3, param4, param5, param6, param7, param8)
#define assertion(expr)
#define assertion5(expr, param0, param1, param2, param3, param4)
int __attribute__((optimize("O0"))) toolbox
#define CompilerCLANG
Definition LinuxAMD.h:6
j
Definition euler.py:99
CF abs(const CF &cf)
int sign(double value, double tolerance=NUMERICAL_ZERO_DIFFERENCE)
void decompose(const double &value, char &exponent, T &mantissa)
Takes a double and returns the exponent and the mantissa.
double compose(const char &exponent, const T &mantissa)
int findMostAgressiveCompression(double value, double maxAbsoluteError)
Analyses the handed data and determines the most aggressive compression.
void decomposeIntoFourVariants(double value, char exponent[4], int mantissa[4], double error[4])
void decomposeIntoEightVariants(double value, char exponent[8], long int mantissa[8], double error[8])
Decompose floating point value.