client: use temp buffer for single output flush for json/disk util
[fio.git] / lib / ieee754.c
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 "ieee754.h"
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 }