FreeBSD/Linux Kernel Cross Reference
sys/bitsy/fpi.c
1 /*
2 * Floating Point Interpreter.
3 * shamelessly stolen from an original by ark.
4 */
5 #include "fpi.h"
6
7 void
8 fpiround(Internal *i)
9 {
10 unsigned long guard;
11
12 guard = i->l & GuardMask;
13 i->l &= ~GuardMask;
14 if(guard > (LsBit>>1) || (guard == (LsBit>>1) && (i->l & LsBit))){
15 i->l += LsBit;
16 if(i->l & CarryBit){
17 i->l &= ~CarryBit;
18 i->h++;
19 if(i->h & CarryBit){
20 if (i->h & 0x01)
21 i->l |= CarryBit;
22 i->l >>= 1;
23 i->h >>= 1;
24 i->e++;
25 }
26 }
27 }
28 }
29
30 static void
31 matchexponents(Internal *x, Internal *y)
32 {
33 int count;
34
35 count = y->e - x->e;
36 x->e = y->e;
37 if(count >= 2*FractBits){
38 x->l = x->l || x->h;
39 x->h = 0;
40 return;
41 }
42 if(count >= FractBits){
43 count -= FractBits;
44 x->l = x->h|(x->l != 0);
45 x->h = 0;
46 }
47 while(count > 0){
48 count--;
49 if(x->h & 0x01)
50 x->l |= CarryBit;
51 if(x->l & 0x01)
52 x->l |= 2;
53 x->l >>= 1;
54 x->h >>= 1;
55 }
56 }
57
58 static void
59 shift(Internal *i)
60 {
61 i->e--;
62 i->h <<= 1;
63 i->l <<= 1;
64 if(i->l & CarryBit){
65 i->l &= ~CarryBit;
66 i->h |= 0x01;
67 }
68 }
69
70 static void
71 normalise(Internal *i)
72 {
73 while((i->h & HiddenBit) == 0)
74 shift(i);
75 }
76
77 static void
78 renormalise(Internal *i)
79 {
80 if(i->e < -2 * FractBits)
81 i->e = -2 * FractBits;
82 while(i->e < 1){
83 i->e++;
84 if(i->h & 0x01)
85 i->l |= CarryBit;
86 i->h >>= 1;
87 i->l = (i->l>>1)|(i->l & 0x01);
88 }
89 if(i->e >= ExpInfinity)
90 SetInfinity(i);
91 }
92
93 void
94 fpinormalise(Internal *x)
95 {
96 if(!IsWeird(x) && !IsZero(x))
97 normalise(x);
98 }
99
100 void
101 fpiadd(Internal *x, Internal *y, Internal *i)
102 {
103 Internal *t;
104
105 i->s = x->s;
106 if(IsWeird(x) || IsWeird(y)){
107 if(IsNaN(x) || IsNaN(y))
108 SetQNaN(i);
109 else
110 SetInfinity(i);
111 return;
112 }
113 if(x->e > y->e){
114 t = x;
115 x = y;
116 y = t;
117 }
118 matchexponents(x, y);
119 i->e = x->e;
120 i->h = x->h + y->h;
121 i->l = x->l + y->l;
122 if(i->l & CarryBit){
123 i->h++;
124 i->l &= ~CarryBit;
125 }
126 if(i->h & (HiddenBit<<1)){
127 if(i->h & 0x01)
128 i->l |= CarryBit;
129 i->l = (i->l>>1)|(i->l & 0x01);
130 i->h >>= 1;
131 i->e++;
132 }
133 if(IsWeird(i))
134 SetInfinity(i);
135 }
136
137 void
138 fpisub(Internal *x, Internal *y, Internal *i)
139 {
140 Internal *t;
141
142 if(y->e < x->e
143 || (y->e == x->e && (y->h < x->h || (y->h == x->h && y->l < x->l)))){
144 t = x;
145 x = y;
146 y = t;
147 }
148 i->s = y->s;
149 if(IsNaN(y)){
150 SetQNaN(i);
151 return;
152 }
153 if(IsInfinity(y)){
154 if(IsInfinity(x))
155 SetQNaN(i);
156 else
157 SetInfinity(i);
158 return;
159 }
160 matchexponents(x, y);
161 i->e = y->e;
162 i->h = y->h - x->h;
163 i->l = y->l - x->l;
164 if(i->l < 0){
165 i->l += CarryBit;
166 i->h--;
167 }
168 if(i->h == 0 && i->l == 0)
169 SetZero(i);
170 else while(i->e > 1 && (i->h & HiddenBit) == 0)
171 shift(i);
172 }
173
174 #define CHUNK (FractBits/2)
175 #define CMASK ((1<<CHUNK)-1)
176 #define HI(x) ((short)((x)>>CHUNK) & CMASK)
177 #define LO(x) ((short)(x) & CMASK)
178 #define SPILL(x) ((x)>>CHUNK)
179 #define M(x, y) ((long)a[x]*(long)b[y])
180 #define C(h, l) (((long)((h) & CMASK)<<CHUNK)|((l) & CMASK))
181
182 void
183 fpimul(Internal *x, Internal *y, Internal *i)
184 {
185 long a[4], b[4], c[7], f[4];
186
187 i->s = x->s^y->s;
188 if(IsWeird(x) || IsWeird(y)){
189 if(IsNaN(x) || IsNaN(y) || IsZero(x) || IsZero(y))
190 SetQNaN(i);
191 else
192 SetInfinity(i);
193 return;
194 }
195 else if(IsZero(x) || IsZero(y)){
196 SetZero(i);
197 return;
198 }
199 normalise(x);
200 normalise(y);
201 i->e = x->e + y->e - (ExpBias - 1);
202
203 a[0] = HI(x->h); b[0] = HI(y->h);
204 a[1] = LO(x->h); b[1] = LO(y->h);
205 a[2] = HI(x->l); b[2] = HI(y->l);
206 a[3] = LO(x->l); b[3] = LO(y->l);
207
208 c[6] = M(3, 3);
209 c[5] = M(2, 3) + M(3, 2) + SPILL(c[6]);
210 c[4] = M(1, 3) + M(2, 2) + M(3, 1) + SPILL(c[5]);
211 c[3] = M(0, 3) + M(1, 2) + M(2, 1) + M(3, 0) + SPILL(c[4]);
212 c[2] = M(0, 2) + M(1, 1) + M(2, 0) + SPILL(c[3]);
213 c[1] = M(0, 1) + M(1, 0) + SPILL(c[2]);
214 c[0] = M(0, 0) + SPILL(c[1]);
215
216 f[0] = c[0];
217 f[1] = C(c[1], c[2]);
218 f[2] = C(c[3], c[4]);
219 f[3] = C(c[5], c[6]);
220
221 if((f[0] & HiddenBit) == 0){
222 f[0] <<= 1;
223 f[1] <<= 1;
224 f[2] <<= 1;
225 f[3] <<= 1;
226 if(f[1] & CarryBit){
227 f[0] |= 1;
228 f[1] &= ~CarryBit;
229 }
230 if(f[2] & CarryBit){
231 f[1] |= 1;
232 f[2] &= ~CarryBit;
233 }
234 if(f[3] & CarryBit){
235 f[2] |= 1;
236 f[3] &= ~CarryBit;
237 }
238 i->e--;
239 }
240 i->h = f[0];
241 i->l = f[1];
242 if(f[2] || f[3])
243 i->l |= 1;
244 renormalise(i);
245 }
246
247 void
248 fpidiv(Internal *x, Internal *y, Internal *i)
249 {
250 i->s = x->s^y->s;
251 if(IsNaN(x) || IsNaN(y)
252 || (IsInfinity(x) && IsInfinity(y)) || (IsZero(x) && IsZero(y))){
253 SetQNaN(i);
254 return;
255 }
256 else if(IsZero(x) || IsInfinity(y)){
257 SetInfinity(i);
258 return;
259 }
260 else if(IsInfinity(x) || IsZero(y)){
261 SetZero(i);
262 return;
263 }
264 normalise(x);
265 normalise(y);
266 i->h = 0;
267 i->l = 0;
268 i->e = y->e - x->e + (ExpBias + 2*FractBits - 1);
269 do{
270 if(y->h > x->h || (y->h == x->h && y->l >= x->l)){
271 i->l |= 0x01;
272 y->h -= x->h;
273 y->l -= x->l;
274 if(y->l < 0){
275 y->l += CarryBit;
276 y->h--;
277 }
278 }
279 shift(y);
280 shift(i);
281 }while ((i->h & HiddenBit) == 0);
282 if(y->h || y->l)
283 i->l |= 0x01;
284 renormalise(i);
285 }
286
287 int
288 fpicmp(Internal *x, Internal *y)
289 {
290 if(IsNaN(x) && IsNaN(y))
291 return 0;
292 if(IsInfinity(x) && IsInfinity(y))
293 return y->s - x->s;
294 if(x->e == y->e && x->h == y->h && x->l == y->l)
295 return y->s - x->s;
296 if(x->e < y->e
297 || (x->e == y->e && (x->h < y->h || (x->h == y->h && x->l < y->l))))
298 return y->s ? 1: -1;
299 return x->s ? -1: 1;
300 }
Cache object: eb9476a38b1ebf8409b61eb4a9d3631b
|