date and time created 88/07/22 16:08:01 by bostic
[unix-history] / usr / src / old / as.vax / bignum2.c
CommitLineData
d4b6f0a4 1/*
bcf1365c
DF
2 * Copyright (c) 1982 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
d4b6f0a4 5 */
bcf1365c 6
d4b6f0a4 7#ifndef lint
bcf1365c 8static char sccsid[] = "@(#)bignum2.c 5.1 (Berkeley) %G%";
d4b6f0a4
RH
9#endif not lint
10
11#include <stdio.h>
12#include "as.h"
13Bignum Znumber; /* zero reference */
14#define MINEXP -32768 /* never generate; reserved for id 0 */
15
16Bignum intconvert(number, convto)
17 Bignum number;
18 int convto;
19{
20 reg int i;
21 if (number.num_tag == convto)
22 return(number);
23 if (ty_nbyte[number.num_tag] > ty_nbyte[convto] && (passno == 2)){
24 yywarning("Conversion between %s and %s looses significance",
25 ty_string[number.num_tag],
26 ty_string[convto]);
27 }
28 for (i = ty_nbyte[convto]; i < ty_nbyte[TYPO]; i++)
29 number.num_uchar[i] = 0;
30 return(number);
31}
32
33#define CONV(src, dst) (((src) << TYPLG) + (dst))
34
35Bignum floatconvert(number, convto)
36 Bignum number;
37 int convto;
38{
39 reg u_int *bp; /* r11 */
40 int loss = 0;
41 int gain = 0;
42 int mixs = 0;
43 Ovf ovf;
44
45 if (number.num_tag == convto)
46 return(number);
47 bp = &number.num_uint[0];
48#ifdef lint
49 *bp = *bp;
50#endif lint
51
52 switch(CONV(number.num_tag, convto)){
53
54 case CONV(TYPF, TYPD): asm("cvtfd (r11), (r11)"); break;
55 case CONV(TYPF, TYPG): mixs++; break;
56 case CONV(TYPF, TYPH): mixs++; break;
57
58 case CONV(TYPD, TYPF): asm("cvtdf (r11), (r11)"); break;
59 case CONV(TYPD, TYPG): mixs++; break;
60 case CONV(TYPD, TYPH): mixs++; break;
61
62 case CONV(TYPG, TYPF): mixs++; break;
63 case CONV(TYPG, TYPD): mixs++; break;
64 case CONV(TYPG, TYPH): mixs++; break;
65
66 case CONV(TYPH, TYPF): mixs++; break;
67 case CONV(TYPH, TYPD): mixs++; break;
68 case CONV(TYPH, TYPG): mixs++; break;
69 default: panic("Bad floating point conversion?");
70 }
71 if ((gain || mixs || loss) && (passno == 2)){
72 yywarning("Converting from %s to %s: %s ",
73 ty_string[number.num_tag],
74 ty_string[convto],
75 gain ? "gains significance" :
76 (loss ? "looses significance" : "mixs exponent formats")
77 );
78 }
79 if (mixs){
80 number = bignumconvert(number, convto, &ovf);
81 if (ovf && passno == 2){
82 yywarning("Floating conversion over/underflowed\n");
83 }
84 } else {
85 number.num_tag = convto;
86 }
87 return(number);
88}
89
90/*
91 * Convert a big number between various representations
92 */
93Bignum bignumconvert(number, toconv, ovfp)
94 Bignum number;
95 int toconv;
96 Ovf *ovfp;
97{
98 int tag;
99
100 *ovfp = 0;
101 tag = number.num_tag;
102 if (tag == toconv)
103 return(number);
104 if (tag == TYPUNPACKED){
105 return(bignumpack(number, toconv, ovfp));
106 }
107 if (toconv == TYPUNPACKED){
108 return(bignumunpack(number, ovfp));
109 }
110 return(bignumpack(bignumunpack(number, ovfp), toconv, ovfp));
111}
112
113Bignum bignumunpack(Packed, ovfp)
114 Bignum Packed;
115 Ovf *ovfp;
116{
117 Bignum Mantissa;
118 Bignum Enumber;
119 reg int i;
120 int j;
121 int k;
122 reg struct ty_bigdesc *p;
123 reg chptr packed;
124 reg chptr mantissa;
125 reg chptr enumber;
126 u_short exponent;
127 int sign;
128 int mask;
129
130 p = &ty_bigdesc[Packed.num_tag];
131
132 *ovfp = 0;
133 Mantissa = Znumber;
134 sign = 0;
135 exponent = 0;
136 mantissa = CH_FIELD(Mantissa);
137 enumber = CH_FIELD(Enumber);
138 packed = CH_FIELD(Packed);
139
140 if (isclear(packed)){
141 Mantissa.num_tag = TYPUNPACKED;
142 Mantissa.num_exponent = MINEXP;
143 return(Mantissa);
144 }
145 /*
146 * map the packed number into the mantissa, using
147 * the unpacking map
148 */
149 mapnumber(mantissa, packed, 16, p->b_upmmap);
150 /*
151 * perform the mantissa shifting.
152 * This may appear to overflow; all that is lost
153 * is low order bits of the exponent.
154 */
155 (void)numshift(p->b_mlshift, mantissa, mantissa);
156 /*
157 * handle sign and exponent
158 */
159 switch(Packed.num_tag){
160 case TYPB:
161 case TYPW:
162 case TYPL:
163 case TYPO:
164 case TYPQ:
165 sign = 0;
166 exponent = p->b_eexcess;
167 if (mantissa[HOC] & SIGNBIT){
168 sign = -1;
169 *ovfp |= numnegate(mantissa, mantissa);
170 }
171 /*
172 * Normalize the packed by left shifting,
173 * adjusting the exponent as we go.
174 * Do a binary weighted left shift for some speed.
175 */
176 k = 0;
177 for (j = 4; j >= 0; --j){
178 i = 1 << j; /* 16, 8, 4, 2, 1 */
179 while(1){
180 if (k >= p->b_msigbits)
181 break;
182 mask = ONES(i) << (CH_BITS - i);
183 if (mantissa[HOC] & mask)
184 break;
185 (void)numshift(i, mantissa, mantissa);
186 k += i;
187 exponent -= i;
188 }
189 }
190 assert(mantissa[HOC] & SIGNBIT, "integer <<ing");
191 /*
192 * now, kick the most significant bit off the top
193 */
194 (void)numshift(1, mantissa, mantissa);
195 break;
196 default:
197 /*
198 * map the exponent into the local area.
199 */
200 Enumber = Znumber;
201 mapnumber(enumber, packed, 2, p->b_upemap);
202 /*
203 * Extract the exponent, and get rid
204 * of the sign bit
205 */
206 exponent = Enumber.num_ushort[0] & ONES(15);
207 /*
208 * shift the exponent, and get rid of high order
209 * trash
210 */
211 exponent >>= p->b_ershift;
212 exponent &= ONES(p->b_esigbits);
213 /*
214 * un excess the exponent
215 */
216 exponent -= p->b_eexcess;
217 /*
218 * extract and extend the sign bit
219 */
220 sign = (Enumber.num_ushort[0] & ~ONES(15)) ? -1 : 0;
221 }
222 /*
223 * Assemble the pieces, and return the number
224 */
225 Mantissa.num_tag = TYPUNPACKED;
226 Mantissa.num_sign = sign;
227 Mantissa.num_exponent = exponent;
228 return(Mantissa);
229}
230
231Bignum bignumpack(Unpacked, toconv, ovfp)
232 Bignum Unpacked;
233 int toconv;
234 Ovf *ovfp;
235{
236 Bignum Back;
237 Bignum Enumber;
238 Bignum Temp;
239
240 short exponent;
241 char sign;
242 reg struct ty_bigdesc *p;
243 reg chptr back;
244 reg chptr enumber;
245 reg chptr temp;
246 reg chptr unpacked;
247
248 int i,j;
249
250 if (Unpacked.num_tag != TYPUNPACKED)
251 panic("Argument to bignumpack is not unpacked");
252
253 *ovfp = 0;
254 Back = Znumber;
255 Temp = Znumber;
256 Back.num_tag = toconv;
257
258 back = CH_FIELD(Back);
259 temp = CH_FIELD(Temp);
260 enumber = CH_FIELD(Enumber);
261 unpacked = CH_FIELD(Unpacked);
262 p = &ty_bigdesc[toconv];
263
264 exponent = Unpacked.num_exponent;
265 sign = Unpacked.num_sign;
266 if (exponent == MINEXP)
267 return(Back); /* identically zero */
268
269 switch(toconv){
270 case TYPB:
271 case TYPW:
272 case TYPL:
273 case TYPQ:
274 case TYPO:
275 /*
276 * Put back in the assumed high order fraction
277 * bit that is always a 1.
278 */
279 (void)numshift(-1, temp, unpacked);
280 temp[HOC] |= SIGNBIT;
281 if (exponent > p->b_eexcess){
282 /*
283 * Construct the largest positive integer
284 */
285 (void)numclear(temp);
286 (void)num1comp(temp, temp);
287 temp[HOC] &= ~SIGNBIT;
288 sign = sign;
289 *ovfp |= OVF_OVERFLOW;
290 } else
291 if (exponent <= 0){
292 /*
293 * chop the temp; underflow to integer 0
294 */
295 (void)numclear(temp);
296 sign = 0;
297 *ovfp |= OVF_UNDERFLOW;
298 } else {
299 /*
300 * denormalize the temp.
301 * This will again chop, by shifting
302 * bits off the right end into oblivion.
303 */
304 for (j = 4; j >= 0; --j){
305 i = 1 << j; /* 16, 8, 4, 2, 1 */
306 while(exponent + i <= p->b_eexcess){
307 numshift(-i, temp, temp);
308 exponent += i;
309 }
310 }
311 }
312 /*
313 * negate the temp if the sign is set
314 */
315 if (sign)
316 *ovfp |= numnegate(temp, temp);
317 /*
318 * Stuff the temp number into the return area
319 */
320 mapnumber(back, temp, 16, p->b_pmmap);
321 return(Back);
322 default:
323 /*
324 * Shift the mantissa to the right, filling in zeroes on
325 * the left. This aligns the least significant bit
326 * on the bottom of a byte, something that upround
327 * will use.
328 * Put the result into a temporary.
329 * Even though the shift may be zero, there
330 * is still a copy involved here.
331 */
332 (void)numshift(-(p->b_mlshift), temp, unpacked);
333 /*
334 * Perform the rounding by adding in 0.5 ulp's
335 */
336 exponent = upround(&Temp, p, exponent);
337 /*
338 * Do a range check on the exponent, in preparation
339 * to stuffing it in.
340 */
341 if ((short)(exponent + p->b_eexcess) == 0){
342 /*
343 * Sorry, no gradual underflow on the
344 * VAX. Chop this beasty totally to zero
345 */
346 goto zeroret;
347 } else
348 if ((short)(exponent + p->b_eexcess) < 0){
349 /*
350 * True underflow will happen;
351 * Chop everything to positive zero
352 */
353 zeroret:
354 (void)numclear(temp);
355 exponent = 0;
356 sign = 0; /* avoid reserved operand! */
357 *ovfp |= OVF_UNDERFLOW;
358 } else
359 if ((unsigned)(exponent + p->b_eexcess)
360 >= (unsigned)(1 << p->b_esigbits)){
361 /*
362 * Construct the largest magnitude possible
363 * floating point unpacked: 0.{1}111111111
364 */
365 (void)numclear(temp);
366 (void)num1comp(temp, temp);
367 exponent = ONES(p->b_esigbits);
368 sign = sign;
369 *ovfp |= OVF_OVERFLOW;
370 } else {
371 /*
372 * The exponent will fit.
373 * Bias it up, and the common code will stuff it.
374 */
375 exponent += p->b_eexcess;
376 }
377 exponent <<= p->b_ershift;
378 /*
379 * mask out trash for the sign, and put in the sign.
380 */
381 exponent &= ONES(15);
382 if (sign)
383 exponent |= ~ONES(15);
384 Enumber.num_ushort[0] = exponent;
385 /*
386 * Map the unpacked exponent into the value going back
387 */
388 mapnumber(back, enumber, 2, p->b_pemap);
389 /*
390 * Stuff the unpacked mantissa into the return area
391 */
392 mapnumber(back, temp, 16, p->b_pmmap);
393 return(Back);
394 }
395 /*NOTREACHED*/
396}
397
398mapnumber(chp1, chp2, nbytes, themap)
399 chptr chp1, chp2;
400 int nbytes;
401 char *themap;
402{
403 reg int i;
404 reg u_char *p1, *p2;
405
406 p1 = (u_char *)chp1;
407 p2 = (u_char *)chp2;
408 for (i = 0; i < nbytes; i++){
409 switch(themap[i]){
410 case NOTAKE:
411 break;
412 default:
413 p1[themap[i]] |= p2[i];
414 break;
415 }
416 }
417}
418
419#define UPSHIFT 2
420/*
421 * round in 1/2 ulp in the number, possibly modifying
422 * the binary exponent if there was total carry out.
423 * Return the modified exponent
424 */
425int upround(numberp, p, exponent)
426 reg Bignum *numberp;
427 reg struct ty_bigdesc *p;
428 int exponent;
429{
430 reg u_char *bytep;
431 int nbytes;
432 int byteindex;
433 int hofractionbit;
434 int ovffractionbit;
435 reg int ovfbitindex;
436 reg chptr number;
437 static Bignum ulp;
438
439 /*
440 * Find out the byte index of the byte containing the ulp
441 */
442 number = CH_FIELD(numberp[0]);
443 bytep = numberp->num_uchar;
444
445 nbytes = (p->b_msigbits - 1) + p->b_mlshift;
446 assert((nbytes % 8) == 0, "mantissa sig bits");
447 nbytes /= 8;
448 byteindex = 15 - nbytes;
449 assert(byteindex >= 0, "ulp in outer space");
450 /*
451 * Shift the number to the right by two places,
452 * so that we can do full arithmetic without overflowing
453 * to the left.
454 */
455 numshift(-UPSHIFT, number, number);
456 /*
457 * Construct the missing high order fraction bit
458 */
459 ovfbitindex = 8 - (p->b_mlshift + UPSHIFT);
460 assert(ovfbitindex >= 0, "Shifted byte 15 into byte 14");
461 hofractionbit = (0x01 << ovfbitindex);
462 ovffractionbit = (0x02 << ovfbitindex);
463 bytep[15] |= hofractionbit;
464 /*
465 * construct the unit in the last place, and it
466 * to the fraction
467 */
468 ulp.num_uchar[byteindex] |= (0x80 >> UPSHIFT);
469 numaddv(number, number, CH_FIELD(ulp));
470 ulp.num_uchar[byteindex] &= ~(0x80 >> UPSHIFT);
471 /*
472 * Check if there was an overflow,
473 * and adjust by shifting.
474 * Also, bring the number back into canonical
475 * unpacked form by left shifting by two to undeo
476 * what we did before.
477 */
478 if (bytep[15] & ovffractionbit){
479 exponent += 1;
480 numshift(UPSHIFT - 1, number, number);
481 } else {
482 numshift(UPSHIFT, number, number);
483 }
484 /*
485 * Clear off trash in the unused bits of the high
486 * order byte of the number
487 */
488 bytep[15] &= ONES(8 - p->b_mlshift);
489 return(exponent);
490}
491#ifdef DEBUG
492bignumprint(number)
493 Bignum number;
494{
495 printf("Bignum: %s (exp: %d, sign: %d) 0x%08x%08x%08x%08x",
496 ty_string[number.num_tag],
497 number.num_exponent,
498 number.num_sign,
499 number.num_uint[3],
500 number.num_uint[2],
501 number.num_uint[1],
502 number.num_uint[0]);
503 switch(number.num_tag){
504 case TYPB:
505 case TYPW:
506 case TYPL:
507 case TYPQ:
508 case TYPO:
509 case TYPUNPACKED:
510 break;
511 case TYPF:
512 printf(" == %10.8e", number.num_num.numFf_float.Ff_value);
513 break;
514 case TYPD:
515 printf(" == %20.17e", number.num_num.numFd_float.Fd_value);
516 break;
517 case TYPG:
518 case TYPH:
519 break;
520 }
521}
522
523numprintovf(ovf)
524 Ovf ovf;
525{
526 int i;
527 static struct ovftab{
528 Ovf which;
529 char *print;
530 } ovftab[] = {
531 OVF_POSOVF, "posovf",
532 OVF_MAXINT, "maxint",
533 OVF_ADDV, "addv",
534 OVF_LSHIFT, "lshift",
535 OVF_F, "F float",
536 OVF_D, "D float",
537 OVF_G, "G float",
538 OVF_H, "H float",
539 OVF_OVERFLOW, "cvt overflow",
540 OVF_UNDERFLOW, "cvt underflow",
541 0, 0
542 };
543 for(i = 0; ovftab[i].which; i++){
544 if (ovf & ovftab[i].which)
545 printf("Overflow(%s) ", ovftab[i].print);
546 }
547}
548#endif DEBUG