tieee.c - plan9port - [fork] Plan 9 from user space
(HTM) git clone git://src.adamsgaard.dk/plan9port
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) LICENSE
---
tieee.c (3265B)
---
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <mach.h>
5
6 /*
7 * These routines assume that if the number is representable
8 * in IEEE floating point, it will be representable in the native
9 * double format. Naive but workable, probably.
10 */
11 int
12 ieeeftoa64(char *buf, uint n, u32int h, u32int l)
13 {
14 double fr;
15 int exp;
16
17 if (n <= 0)
18 return 0;
19
20
21 if(h & (1UL<<31)){
22 *buf++ = '-';
23 h &= ~(1UL<<31);
24 }else
25 *buf++ = ' ';
26 n--;
27 if(l == 0 && h == 0)
28 return snprint(buf, n, "0.");
29 exp = (h>>20) & ((1L<<11)-1L);
30 if(exp == 0)
31 return snprint(buf, n, "DeN(%.8lux%.8lux)", h, l);
32 if(exp == ((1L<<11)-1L)){
33 if(l==0 && (h&((1L<<20)-1L)) == 0)
34 return snprint(buf, n, "Inf");
35 else
36 return snprint(buf, n, "NaN(%.8lux%.8lux)", h&((1L<<20)-1L), l);
37 }
38 exp -= (1L<<10) - 2L;
39 fr = l & ((1L<<16)-1L);
40 fr /= 1L<<16;
41 fr += (l>>16) & ((1L<<16)-1L);
42 fr /= 1L<<16;
43 fr += (h & (1L<<20)-1L) | (1L<<20);
44 fr /= 1L<<21;
45 fr = ldexp(fr, exp);
46 return snprint(buf, n, "%.18g", fr);
47 }
48
49 int
50 ieeeftoa32(char *buf, uint n, u32int h)
51 {
52 double fr;
53 int exp;
54
55 if (n <= 0)
56 return 0;
57
58 if(h & (1UL<<31)){
59 *buf++ = '-';
60 h &= ~(1UL<<31);
61 }else
62 *buf++ = ' ';
63 n--;
64 if(h == 0)
65 return snprint(buf, n, "0.");
66 exp = (h>>23) & ((1L<<8)-1L);
67 if(exp == 0)
68 return snprint(buf, n, "DeN(%.8lux)", h);
69 if(exp == ((1L<<8)-1L)){
70 if((h&((1L<<23)-1L)) == 0)
71 return snprint(buf, n, "Inf");
72 else
73 return snprint(buf, n, "NaN(%.8lux)", h&((1L<<23)-1L));
74 }
75 exp -= (1L<<7) - 2L;
76 fr = (h & ((1L<<23)-1L)) | (1L<<23);
77 fr /= 1L<<24;
78 fr = ldexp(fr, exp);
79 return snprint(buf, n, "%.9g", fr);
80 }
81
82 int
83 beieeeftoa32(char *buf, uint n, void *s)
84 {
85 return ieeeftoa32(buf, n, beswap4(*(u32int*)s));
86 }
87
88 int
89 beieeeftoa64(char *buf, uint n, void *s)
90 {
91 return ieeeftoa64(buf, n, beswap4(*(u32int*)s), beswap4(((u32int*)(s))[1]));
92 }
93
94 int
95 leieeeftoa32(char *buf, uint n, void *s)
96 {
97 return ieeeftoa32(buf, n, leswap4(*(u32int*)s));
98 }
99
100 int
101 leieeeftoa64(char *buf, uint n, void *s)
102 {
103 return ieeeftoa64(buf, n, leswap4(((u32int*)(s))[1]), leswap4(*(u32int*)s));
104 }
105
106 /* packed in 12 bytes, with s[2]==s[3]==0; mantissa starts at s[4]*/
107 int
108 beieeeftoa80(char *buf, uint n, void *s)
109 {
110 uchar *reg = (uchar*)s;
111 int i;
112 ulong x;
113 uchar ieee[8+8]; /* room for slop */
114 uchar *p, *q;
115
116 memset(ieee, 0, sizeof(ieee));
117 /* sign */
118 if(reg[0] & 0x80)
119 ieee[0] |= 0x80;
120
121 /* exponent */
122 x = ((reg[0]&0x7F)<<8) | reg[1];
123 if(x == 0) /* number is ±0 */
124 goto done;
125 if(x == 0x7FFF){
126 if(memcmp(reg+4, ieee+1, 8) == 0){ /* infinity */
127 x = 2047;
128 }else{ /* NaN */
129 x = 2047;
130 ieee[7] = 0x1; /* make sure */
131 }
132 ieee[0] |= x>>4;
133 ieee[1] |= (x&0xF)<<4;
134 goto done;
135 }
136 x -= 0x3FFF; /* exponent bias */
137 x += 1023;
138 if(x >= (1<<11) || ((reg[4]&0x80)==0 && x!=0))
139 return snprint(buf, n, "not in range");
140 ieee[0] |= x>>4;
141 ieee[1] |= (x&0xF)<<4;
142
143 /* mantissa */
144 p = reg+4;
145 q = ieee+1;
146 for(i=0; i<56; i+=8, p++, q++){ /* move one byte */
147 x = (p[0]&0x7F) << 1;
148 if(p[1] & 0x80)
149 x |= 1;
150 q[0] |= x>>4;
151 q[1] |= (x&0xF)<<4;
152 }
153 done:
154 return beieeeftoa64(buf, n, (void*)ieee);
155 }
156
157
158 int
159 leieeeftoa80(char *buf, uint n, void *s)
160 {
161 int i;
162 char *cp;
163 char b[12];
164
165 cp = (char*) s;
166 for(i=0; i<12; i++)
167 b[11-i] = *cp++;
168 return beieeeftoa80(buf, n, b);
169 }