Blame


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