Commit | Line | Data |
---|---|---|
90f326d0 JA |
1 | /* |
2 | * Shamelessly lifted from Beej's Guide to Network Programming, found here: | |
3 | * | |
4 | * http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html#serialization | |
5 | * | |
6 | * Below code was granted to the public domain. | |
7 | */ | |
802ad4a8 | 8 | #include "ieee754.h" |
90f326d0 JA |
9 | |
10 | uint64_t pack754(long double f, unsigned bits, unsigned expbits) | |
11 | { | |
12 | long double fnorm; | |
13 | int shift; | |
14 | long long sign, exp, significand; | |
15 | unsigned significandbits = bits - expbits - 1; // -1 for sign bit | |
16 | ||
17 | // get this special case out of the way | |
18 | if (f == 0.0) | |
19 | return 0; | |
20 | ||
21 | // check sign and begin normalization | |
22 | if (f < 0) { | |
23 | sign = 1; | |
24 | fnorm = -f; | |
25 | } else { | |
26 | sign = 0; | |
27 | fnorm = f; | |
28 | } | |
29 | ||
30 | // get the normalized form of f and track the exponent | |
31 | shift = 0; | |
32 | while (fnorm >= 2.0) { | |
33 | fnorm /= 2.0; | |
34 | shift++; | |
35 | } | |
36 | while (fnorm < 1.0) { | |
37 | fnorm *= 2.0; | |
38 | shift--; | |
39 | } | |
40 | fnorm = fnorm - 1.0; | |
41 | ||
42 | // calculate the binary form (non-float) of the significand data | |
43 | significand = fnorm * ((1LL << significandbits) + 0.5f); | |
44 | ||
45 | // get the biased exponent | |
46 | exp = shift + ((1 << (expbits - 1)) - 1); // shift + bias | |
47 | ||
48 | // return the final answer | |
49 | return (sign << (bits - 1)) | (exp << (bits-expbits - 1)) | significand; | |
50 | } | |
51 | ||
52 | long double unpack754(uint64_t i, unsigned bits, unsigned expbits) | |
53 | { | |
54 | long double result; | |
55 | long long shift; | |
56 | unsigned bias; | |
57 | unsigned significandbits = bits - expbits - 1; // -1 for sign bit | |
58 | ||
59 | if (i == 0) | |
60 | return 0.0; | |
61 | ||
62 | // pull the significand | |
63 | result = (i & ((1LL << significandbits) - 1)); // mask | |
64 | result /= (1LL << significandbits); // convert back to float | |
65 | result += 1.0f; // add the one back on | |
66 | ||
67 | // deal with the exponent | |
68 | bias = (1 << (expbits - 1)) - 1; | |
69 | shift = ((i >> significandbits) & ((1LL << expbits) - 1)) - bias; | |
70 | while (shift > 0) { | |
71 | result *= 2.0; | |
72 | shift--; | |
73 | } | |
74 | while (shift < 0) { | |
75 | result /= 2.0; | |
76 | shift++; | |
77 | } | |
78 | ||
79 | // sign it | |
80 | result *= (i >> (bits - 1)) & 1 ? -1.0 : 1.0; | |
81 | ||
82 | return result; | |
83 | } |