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
|
#include "DataFormats/Math/interface/libminifloat.h"
namespace {
MiniFloatConverter dummy; // so the constructor is called
}
uint32_t MiniFloatConverter::mantissatable[2048];
uint32_t MiniFloatConverter::exponenttable[64];
uint16_t MiniFloatConverter::offsettable[64];
uint16_t MiniFloatConverter::basetable[512];
uint8_t MiniFloatConverter::shifttable[512];
MiniFloatConverter::MiniFloatConverter() {
static bool once = false;
if (!once) {
filltables();
once = true;
}
}
void MiniFloatConverter::filltables() {
// ==== mantissatable ===
// -- zero --
mantissatable[0] = 0;
// -- denorm --
for (unsigned int i = 1; i <= 1023; ++i) {
unsigned int m = (i << 13), e = 0;
while (!(m & 0x00800000)) { // While not normalized
e -= 0x00800000; // Decrement exponent (1<<23)
m <<= 1; // Shift mantissa
}
m &= ~0x00800000; // Clear leading 1 bit
e += 0x38800000; // Adjust bias ((127-14)<<23)
mantissatable[i] = m | e;
}
// -- norm --
for (unsigned int i = 1024; i <= 2047; ++i) {
mantissatable[i] = 0x38000000 + ((i - 1024) << 13);
}
// ==== exponenttable ===
exponenttable[0] = 0;
for (unsigned int i = 1; i <= 30; ++i)
exponenttable[i] = i << 23;
exponenttable[31] = 0x47800000;
exponenttable[32] = 0x80000000u;
for (unsigned int i = 33; i <= 62; ++i)
exponenttable[i] = 0x80000000u | ((i - 32) << 23);
exponenttable[63] = 0xC7800000;
// ==== offsettable ====
for (unsigned int i = 0; i <= 63; ++i)
offsettable[i] = ((i == 0 || i == 32) ? 0 : 1024);
// ==== basetable, shifttable ===
for (unsigned i = 0; i < 256; ++i) {
int e = int(i) - 127;
if (e < -24) { // Very small numbers map to zero
basetable[i | 0x000] = 0x0000;
basetable[i | 0x100] = 0x8000;
shifttable[i | 0x000] = 24;
shifttable[i | 0x100] = 24;
} else if (e < -14) { // Small numbers map to denorms
basetable[i | 0x000] = (0x0400 >> (-e - 14));
basetable[i | 0x100] = (0x0400 >> (-e - 14)) | 0x8000;
shifttable[i | 0x000] = -e - 1;
shifttable[i | 0x100] = -e - 1;
} else if (e <= 15) { // Normal numbers just lose precision
basetable[i | 0x000] = ((e + 15) << 10);
basetable[i | 0x100] = ((e + 15) << 10) | 0x8000;
shifttable[i | 0x000] = 13;
shifttable[i | 0x100] = 13;
} else if (e < 128) { // Large numbers map to Infinity
basetable[i | 0x000] = 0x7C00;
basetable[i | 0x100] = 0xFC00;
shifttable[i | 0x000] = 24;
shifttable[i | 0x100] = 24;
} else { // Infinity and NaN's stay Infinity and NaN's
basetable[i | 0x000] = 0x7C00;
basetable[i | 0x100] = 0xFC00;
shifttable[i | 0x000] = 13;
shifttable[i | 0x100] = 13;
}
}
}
|