Merge branch 'master' of https://github.com/celestinechen/fio
[fio.git] / lib / ieee754.c
CommitLineData
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
10uint64_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
52long 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}