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 */ 8 #include <inttypes.h> 9 #include "ieee754.h" 10 11 uint64_t pack754(long double f, unsigned bits, unsigned expbits) 12 { 13 long double fnorm; 14 int shift; 15 long long sign, exp, significand; 16 unsigned significandbits = bits - expbits - 1; // -1 for sign bit 17 18 // get this special case out of the way 19 if (f == 0.0) 20 return 0; 21 22 // check sign and begin normalization 23 if (f < 0) { 24 sign = 1; 25 fnorm = -f; 26 } else { 27 sign = 0; 28 fnorm = f; 29 } 30 31 // get the normalized form of f and track the exponent 32 shift = 0; 33 while (fnorm >= 2.0) { 34 fnorm /= 2.0; 35 shift++; 36 } 37 while (fnorm < 1.0) { 38 fnorm *= 2.0; 39 shift--; 40 } 41 fnorm = fnorm - 1.0; 42 43 // calculate the binary form (non-float) of the significand data 44 significand = fnorm * ((1LL << significandbits) + 0.5f); 45 46 // get the biased exponent 47 exp = shift + ((1 << (expbits - 1)) - 1); // shift + bias 48 49 // return the final answer 50 return (sign << (bits - 1)) | (exp << (bits-expbits - 1)) | significand; 51 } 52 53 long double unpack754(uint64_t i, unsigned bits, unsigned expbits) 54 { 55 long double result; 56 long long shift; 57 unsigned bias; 58 unsigned significandbits = bits - expbits - 1; // -1 for sign bit 59 60 if (i == 0) 61 return 0.0; 62 63 // pull the significand 64 result = (i & ((1LL << significandbits) - 1)); // mask 65 result /= (1LL << significandbits); // convert back to float 66 result += 1.0f; // add the one back on 67 68 // deal with the exponent 69 bias = (1 << (expbits - 1)) - 1; 70 shift = ((i >> significandbits) & ((1LL << expbits) - 1)) - bias; 71 while (shift > 0) { 72 result *= 2.0; 73 shift--; 74 } 75 while (shift < 0) { 76 result /= 2.0; 77 shift++; 78 } 79 80 // sign it 81 result *= (i >> (bits - 1)) & 1 ? -1.0 : 1.0; 82 83 return result; 84 } 85