~iaz/+junk/book-GNP

« back to all changes in this revision

Viewing changes to examples/ieee754.c

  • Committer: ivan.a.zorin at gmail
  • Date: 2011-08-20 10:58:21 UTC
  • Revision ID: ivan.a.zorin@gmail.com-20110820105821-qf3pzwgifu2b6yih
book source code examples: Guide to Network Programming

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <stdio.h>
 
2
#include <stdint.h>
 
3
#include <inttypes.h>
 
4
 
 
5
#define pack754_32(f) (pack754((f), 32, 8))
 
6
#define pack754_64(f) (pack754((f), 64, 11))
 
7
#define unpack754_32(i) (unpack754((i), 32, 8))
 
8
#define unpack754_64(i) (unpack754((i), 64, 11))
 
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
        if (f == 0.0) return 0; // get this special case out of the way
 
18
 
 
19
        // check sign and begin normalization
 
20
        if (f < 0) { sign = 1; fnorm = -f; }
 
21
        else { sign = 0; fnorm = f; }
 
22
 
 
23
        // get the normalized form of f and track the exponent
 
24
        shift = 0;
 
25
        while(fnorm >= 2.0) { fnorm /= 2.0; shift++; }
 
26
        while(fnorm < 1.0) { fnorm *= 2.0; shift--; }
 
27
        fnorm = fnorm - 1.0;
 
28
 
 
29
        // calculate the binary form (non-float) of the significand data
 
30
        significand = fnorm * ((1LL<<significandbits) + 0.5f);
 
31
 
 
32
        // get the biased exponent
 
33
        exp = shift + ((1<<(expbits-1)) - 1); // shift + bias
 
34
 
 
35
        // return the final answer
 
36
        return (sign<<(bits-1)) | (exp<<(bits-expbits-1)) | significand;
 
37
}
 
38
 
 
39
long double unpack754(uint64_t i, unsigned bits, unsigned expbits)
 
40
{
 
41
        long double result;
 
42
        long long shift;
 
43
        unsigned bias;
 
44
        unsigned significandbits = bits - expbits - 1; // -1 for sign bit
 
45
 
 
46
        if (i == 0) return 0.0;
 
47
 
 
48
        // pull the significand
 
49
        result = (i&((1LL<<significandbits)-1)); // mask
 
50
        result /= (1LL<<significandbits); // convert back to float
 
51
        result += 1.0f; // add the one back on
 
52
 
 
53
        // deal with the exponent
 
54
        bias = (1<<(expbits-1)) - 1;
 
55
        shift = ((i>>significandbits)&((1LL<<expbits)-1)) - bias;
 
56
        while(shift > 0) { result *= 2.0; shift--; }
 
57
        while(shift < 0) { result /= 2.0; shift++; }
 
58
 
 
59
        // sign it
 
60
        result *= (i>>(bits-1))&1? -1.0: 1.0;
 
61
 
 
62
        return result;
 
63
}
 
64
 
 
65
int main(void)
 
66
{
 
67
        float f = 3.1415926, f2;
 
68
        double d = 3.14159265358979323, d2;
 
69
        uint32_t fi;
 
70
        uint64_t di;
 
71
 
 
72
        fi = pack754_32(f);
 
73
        f2 = unpack754_32(fi);
 
74
 
 
75
        di = pack754_64(d);
 
76
        d2 = unpack754_64(di);
 
77
 
 
78
        printf("float before : %.7f\n", f);
 
79
        printf("float encoded: 0x%08" PRIx32 "\n", fi);
 
80
        printf("float after  : %.7f\n\n", f2);
 
81
 
 
82
        printf("double before : %.20lf\n", d);
 
83
        printf("double encoded: 0x%016" PRIx64 "\n", di);
 
84
        printf("double after  : %.20lf\n", d2);
 
85
 
 
86
        return 0;
 
87
}
 
88