xref: /plan9-contrib/sys/src/ape/lib/ap/stdio/_fconv.c (revision 22df390c30710ddd2119f3e7bb6c92dc399cabb9)
13e12c5d1SDavid du Colombier /* Common routines for _dtoa and strtod */
23e12c5d1SDavid du Colombier 
33e12c5d1SDavid du Colombier #include "fconv.h"
43e12c5d1SDavid du Colombier 
53e12c5d1SDavid du Colombier #ifdef DEBUG
63e12c5d1SDavid du Colombier #include <stdio.h>
73e12c5d1SDavid du Colombier #define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);}
83e12c5d1SDavid du Colombier #endif
93e12c5d1SDavid du Colombier 
103e12c5d1SDavid du Colombier  double
113e12c5d1SDavid du Colombier _tens[] = {
123e12c5d1SDavid du Colombier 		1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
133e12c5d1SDavid du Colombier 		1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
143e12c5d1SDavid du Colombier 		1e20, 1e21, 1e22
153e12c5d1SDavid du Colombier #ifdef VAX
163e12c5d1SDavid du Colombier 		, 1e23, 1e24
173e12c5d1SDavid du Colombier #endif
183e12c5d1SDavid du Colombier 		};
193e12c5d1SDavid du Colombier 
203e12c5d1SDavid du Colombier 
213e12c5d1SDavid du Colombier #ifdef IEEE_Arith
223e12c5d1SDavid du Colombier double _bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 };
233e12c5d1SDavid du Colombier double _tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, 1e-256 };
243e12c5d1SDavid du Colombier #else
253e12c5d1SDavid du Colombier #ifdef IBM
263e12c5d1SDavid du Colombier double _bigtens[] = { 1e16, 1e32, 1e64 };
273e12c5d1SDavid du Colombier double _tinytens[] = { 1e-16, 1e-32, 1e-64 };
283e12c5d1SDavid du Colombier #else
293e12c5d1SDavid du Colombier double _bigtens[] = { 1e16, 1e32 };
303e12c5d1SDavid du Colombier double _tinytens[] = { 1e-16, 1e-32 };
313e12c5d1SDavid du Colombier #endif
323e12c5d1SDavid du Colombier #endif
333e12c5d1SDavid du Colombier 
343e12c5d1SDavid du Colombier  static Bigint *freelist[Kmax+1];
353e12c5d1SDavid du Colombier 
363e12c5d1SDavid du Colombier  Bigint *
_Balloc(int k)373e12c5d1SDavid du Colombier _Balloc(int k)
383e12c5d1SDavid du Colombier {
393e12c5d1SDavid du Colombier 	int x;
403e12c5d1SDavid du Colombier 	Bigint *rv;
413e12c5d1SDavid du Colombier 
423e12c5d1SDavid du Colombier 	if (rv = freelist[k]) {
433e12c5d1SDavid du Colombier 		freelist[k] = rv->next;
443e12c5d1SDavid du Colombier 		}
453e12c5d1SDavid du Colombier 	else {
463e12c5d1SDavid du Colombier 		x = 1 << k;
473e12c5d1SDavid du Colombier 		rv = (Bigint *)malloc(sizeof(Bigint) + (x-1)*sizeof(long));
483e12c5d1SDavid du Colombier 		rv->k = k;
493e12c5d1SDavid du Colombier 		rv->maxwds = x;
503e12c5d1SDavid du Colombier 		}
513e12c5d1SDavid du Colombier 	rv->sign = rv->wds = 0;
523e12c5d1SDavid du Colombier 	return rv;
533e12c5d1SDavid du Colombier 	}
543e12c5d1SDavid du Colombier 
553e12c5d1SDavid du Colombier  void
_Bfree(Bigint * v)563e12c5d1SDavid du Colombier _Bfree(Bigint *v)
573e12c5d1SDavid du Colombier {
583e12c5d1SDavid du Colombier 	if (v) {
593e12c5d1SDavid du Colombier 		v->next = freelist[v->k];
603e12c5d1SDavid du Colombier 		freelist[v->k] = v;
613e12c5d1SDavid du Colombier 		}
623e12c5d1SDavid du Colombier 	}
633e12c5d1SDavid du Colombier 
643e12c5d1SDavid du Colombier 
653e12c5d1SDavid du Colombier  Bigint *
_multadd(Bigint * b,int m,int a)663e12c5d1SDavid du Colombier _multadd(Bigint *b, int m, int a)	/* multiply by m and add a */
673e12c5d1SDavid du Colombier {
683e12c5d1SDavid du Colombier 	int i, wds;
693e12c5d1SDavid du Colombier 	unsigned long *x, y;
703e12c5d1SDavid du Colombier #ifdef Pack_32
713e12c5d1SDavid du Colombier 	unsigned long xi, z;
723e12c5d1SDavid du Colombier #endif
733e12c5d1SDavid du Colombier 	Bigint *b1;
743e12c5d1SDavid du Colombier 
753e12c5d1SDavid du Colombier 	wds = b->wds;
763e12c5d1SDavid du Colombier 	x = b->x;
773e12c5d1SDavid du Colombier 	i = 0;
783e12c5d1SDavid du Colombier 	do {
793e12c5d1SDavid du Colombier #ifdef Pack_32
803e12c5d1SDavid du Colombier 		xi = *x;
813e12c5d1SDavid du Colombier 		y = (xi & 0xffff) * m + a;
823e12c5d1SDavid du Colombier 		z = (xi >> 16) * m + (y >> 16);
833e12c5d1SDavid du Colombier 		a = (int)(z >> 16);
843e12c5d1SDavid du Colombier 		*x++ = (z << 16) + (y & 0xffff);
853e12c5d1SDavid du Colombier #else
863e12c5d1SDavid du Colombier 		y = *x * m + a;
873e12c5d1SDavid du Colombier 		a = (int)(y >> 16);
883e12c5d1SDavid du Colombier 		*x++ = y & 0xffff;
893e12c5d1SDavid du Colombier #endif
903e12c5d1SDavid du Colombier 		}
913e12c5d1SDavid du Colombier 		while(++i < wds);
923e12c5d1SDavid du Colombier 	if (a) {
933e12c5d1SDavid du Colombier 		if (wds >= b->maxwds) {
943e12c5d1SDavid du Colombier 			b1 = Balloc(b->k+1);
953e12c5d1SDavid du Colombier 			Bcopy(b1, b);
963e12c5d1SDavid du Colombier 			Bfree(b);
973e12c5d1SDavid du Colombier 			b = b1;
983e12c5d1SDavid du Colombier 			}
993e12c5d1SDavid du Colombier 		b->x[wds++] = a;
1003e12c5d1SDavid du Colombier 		b->wds = wds;
1013e12c5d1SDavid du Colombier 		}
1023e12c5d1SDavid du Colombier 	return b;
1033e12c5d1SDavid du Colombier 	}
1043e12c5d1SDavid du Colombier 
1053e12c5d1SDavid du Colombier  int
_hi0bits(register unsigned long x)1063e12c5d1SDavid du Colombier _hi0bits(register unsigned long x)
1073e12c5d1SDavid du Colombier {
1083e12c5d1SDavid du Colombier 	register int k = 0;
1093e12c5d1SDavid du Colombier 
1103e12c5d1SDavid du Colombier 	if (!(x & 0xffff0000)) {
1113e12c5d1SDavid du Colombier 		k = 16;
1123e12c5d1SDavid du Colombier 		x <<= 16;
1133e12c5d1SDavid du Colombier 		}
1143e12c5d1SDavid du Colombier 	if (!(x & 0xff000000)) {
1153e12c5d1SDavid du Colombier 		k += 8;
1163e12c5d1SDavid du Colombier 		x <<= 8;
1173e12c5d1SDavid du Colombier 		}
1183e12c5d1SDavid du Colombier 	if (!(x & 0xf0000000)) {
1193e12c5d1SDavid du Colombier 		k += 4;
1203e12c5d1SDavid du Colombier 		x <<= 4;
1213e12c5d1SDavid du Colombier 		}
1223e12c5d1SDavid du Colombier 	if (!(x & 0xc0000000)) {
1233e12c5d1SDavid du Colombier 		k += 2;
1243e12c5d1SDavid du Colombier 		x <<= 2;
1253e12c5d1SDavid du Colombier 		}
1263e12c5d1SDavid du Colombier 	if (!(x & 0x80000000)) {
1273e12c5d1SDavid du Colombier 		k++;
1283e12c5d1SDavid du Colombier 		if (!(x & 0x40000000))
1293e12c5d1SDavid du Colombier 			return 32;
1303e12c5d1SDavid du Colombier 		}
1313e12c5d1SDavid du Colombier 	return k;
1323e12c5d1SDavid du Colombier 	}
1333e12c5d1SDavid du Colombier 
1343e12c5d1SDavid du Colombier  static int
lo0bits(unsigned long * y)1353e12c5d1SDavid du Colombier lo0bits(unsigned long *y)
1363e12c5d1SDavid du Colombier {
1373e12c5d1SDavid du Colombier 	register int k;
1383e12c5d1SDavid du Colombier 	register unsigned long x = *y;
1393e12c5d1SDavid du Colombier 
1403e12c5d1SDavid du Colombier 	if (x & 7) {
1413e12c5d1SDavid du Colombier 		if (x & 1)
1423e12c5d1SDavid du Colombier 			return 0;
1433e12c5d1SDavid du Colombier 		if (x & 2) {
1443e12c5d1SDavid du Colombier 			*y = x >> 1;
1453e12c5d1SDavid du Colombier 			return 1;
1463e12c5d1SDavid du Colombier 			}
1473e12c5d1SDavid du Colombier 		*y = x >> 2;
1483e12c5d1SDavid du Colombier 		return 2;
1493e12c5d1SDavid du Colombier 		}
1503e12c5d1SDavid du Colombier 	k = 0;
1513e12c5d1SDavid du Colombier 	if (!(x & 0xffff)) {
1523e12c5d1SDavid du Colombier 		k = 16;
1533e12c5d1SDavid du Colombier 		x >>= 16;
1543e12c5d1SDavid du Colombier 		}
1553e12c5d1SDavid du Colombier 	if (!(x & 0xff)) {
1563e12c5d1SDavid du Colombier 		k += 8;
1573e12c5d1SDavid du Colombier 		x >>= 8;
1583e12c5d1SDavid du Colombier 		}
1593e12c5d1SDavid du Colombier 	if (!(x & 0xf)) {
1603e12c5d1SDavid du Colombier 		k += 4;
1613e12c5d1SDavid du Colombier 		x >>= 4;
1623e12c5d1SDavid du Colombier 		}
1633e12c5d1SDavid du Colombier 	if (!(x & 0x3)) {
1643e12c5d1SDavid du Colombier 		k += 2;
1653e12c5d1SDavid du Colombier 		x >>= 2;
1663e12c5d1SDavid du Colombier 		}
1673e12c5d1SDavid du Colombier 	if (!(x & 1)) {
1683e12c5d1SDavid du Colombier 		k++;
1693e12c5d1SDavid du Colombier 		x >>= 1;
1703e12c5d1SDavid du Colombier 		if (!x & 1)
1713e12c5d1SDavid du Colombier 			return 32;
1723e12c5d1SDavid du Colombier 		}
1733e12c5d1SDavid du Colombier 	*y = x;
1743e12c5d1SDavid du Colombier 	return k;
1753e12c5d1SDavid du Colombier 	}
1763e12c5d1SDavid du Colombier 
1773e12c5d1SDavid du Colombier  Bigint *
_i2b(int i)1783e12c5d1SDavid du Colombier _i2b(int i)
1793e12c5d1SDavid du Colombier {
1803e12c5d1SDavid du Colombier 	Bigint *b;
1813e12c5d1SDavid du Colombier 
1823e12c5d1SDavid du Colombier 	b = Balloc(1);
1833e12c5d1SDavid du Colombier 	b->x[0] = i;
1843e12c5d1SDavid du Colombier 	b->wds = 1;
1853e12c5d1SDavid du Colombier 	return b;
1863e12c5d1SDavid du Colombier 	}
1873e12c5d1SDavid du Colombier 
1883e12c5d1SDavid du Colombier  Bigint *
_mult(Bigint * a,Bigint * b)1893e12c5d1SDavid du Colombier _mult(Bigint *a, Bigint *b)
1903e12c5d1SDavid du Colombier {
1913e12c5d1SDavid du Colombier 	Bigint *c;
1923e12c5d1SDavid du Colombier 	int k, wa, wb, wc;
1933e12c5d1SDavid du Colombier 	unsigned long carry, y, z;
1943e12c5d1SDavid du Colombier 	unsigned long *x, *xa, *xae, *xb, *xbe, *xc, *xc0;
1953e12c5d1SDavid du Colombier #ifdef Pack_32
1963e12c5d1SDavid du Colombier 	unsigned long z2;
1973e12c5d1SDavid du Colombier #endif
1983e12c5d1SDavid du Colombier 
1993e12c5d1SDavid du Colombier 	if (a->wds < b->wds) {
2003e12c5d1SDavid du Colombier 		c = a;
2013e12c5d1SDavid du Colombier 		a = b;
2023e12c5d1SDavid du Colombier 		b = c;
2033e12c5d1SDavid du Colombier 		}
2043e12c5d1SDavid du Colombier 	k = a->k;
2053e12c5d1SDavid du Colombier 	wa = a->wds;
2063e12c5d1SDavid du Colombier 	wb = b->wds;
2073e12c5d1SDavid du Colombier 	wc = wa + wb;
2083e12c5d1SDavid du Colombier 	if (wc > a->maxwds)
2093e12c5d1SDavid du Colombier 		k++;
2103e12c5d1SDavid du Colombier 	c = Balloc(k);
2113e12c5d1SDavid du Colombier 	for(x = c->x, xa = x + wc; x < xa; x++)
2123e12c5d1SDavid du Colombier 		*x = 0;
2133e12c5d1SDavid du Colombier 	xa = a->x;
2143e12c5d1SDavid du Colombier 	xae = xa + wa;
2153e12c5d1SDavid du Colombier 	xb = b->x;
2163e12c5d1SDavid du Colombier 	xbe = xb + wb;
2173e12c5d1SDavid du Colombier 	xc0 = c->x;
2183e12c5d1SDavid du Colombier #ifdef Pack_32
2193e12c5d1SDavid du Colombier 	for(; xb < xbe; xb++, xc0++) {
2203e12c5d1SDavid du Colombier 		if (y = *xb & 0xffff) {
2213e12c5d1SDavid du Colombier 			x = xa;
2223e12c5d1SDavid du Colombier 			xc = xc0;
2233e12c5d1SDavid du Colombier 			carry = 0;
2243e12c5d1SDavid du Colombier 			do {
2253e12c5d1SDavid du Colombier 				z = (*x & 0xffff) * y + (*xc & 0xffff) + carry;
2263e12c5d1SDavid du Colombier 				carry = z >> 16;
2273e12c5d1SDavid du Colombier 				z2 = (*x++ >> 16) * y + (*xc >> 16) + carry;
2283e12c5d1SDavid du Colombier 				carry = z2 >> 16;
2293e12c5d1SDavid du Colombier 				Storeinc(xc, z2, z);
2303e12c5d1SDavid du Colombier 				}
2313e12c5d1SDavid du Colombier 				while(x < xae);
2323e12c5d1SDavid du Colombier 			*xc = carry;
2333e12c5d1SDavid du Colombier 			}
2343e12c5d1SDavid du Colombier 		if (y = *xb >> 16) {
2353e12c5d1SDavid du Colombier 			x = xa;
2363e12c5d1SDavid du Colombier 			xc = xc0;
2373e12c5d1SDavid du Colombier 			carry = 0;
2383e12c5d1SDavid du Colombier 			z2 = *xc;
2393e12c5d1SDavid du Colombier 			do {
2403e12c5d1SDavid du Colombier 				z = (*x & 0xffff) * y + (*xc >> 16) + carry;
2413e12c5d1SDavid du Colombier 				carry = z >> 16;
2423e12c5d1SDavid du Colombier 				Storeinc(xc, z, z2);
2433e12c5d1SDavid du Colombier 				z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry;
2443e12c5d1SDavid du Colombier 				carry = z2 >> 16;
2453e12c5d1SDavid du Colombier 				}
2463e12c5d1SDavid du Colombier 				while(x < xae);
2473e12c5d1SDavid du Colombier 			*xc = z2;
2483e12c5d1SDavid du Colombier 			}
2493e12c5d1SDavid du Colombier 		}
2503e12c5d1SDavid du Colombier #else
2513e12c5d1SDavid du Colombier 	for(; xb < xbe; xc0++) {
2523e12c5d1SDavid du Colombier 		if (y = *xb++) {
2533e12c5d1SDavid du Colombier 			x = xa;
2543e12c5d1SDavid du Colombier 			xc = xc0;
2553e12c5d1SDavid du Colombier 			carry = 0;
2563e12c5d1SDavid du Colombier 			do {
2573e12c5d1SDavid du Colombier 				z = *x++ * y + *xc + carry;
2583e12c5d1SDavid du Colombier 				carry = z >> 16;
2593e12c5d1SDavid du Colombier 				*xc++ = z & 0xffff;
2603e12c5d1SDavid du Colombier 				}
2613e12c5d1SDavid du Colombier 				while(x < xae);
2623e12c5d1SDavid du Colombier 			*xc = carry;
2633e12c5d1SDavid du Colombier 			}
2643e12c5d1SDavid du Colombier 		}
2653e12c5d1SDavid du Colombier #endif
2663e12c5d1SDavid du Colombier 	for(xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ;
2673e12c5d1SDavid du Colombier 	c->wds = wc;
2683e12c5d1SDavid du Colombier 	return c;
2693e12c5d1SDavid du Colombier 	}
2703e12c5d1SDavid du Colombier 
2713e12c5d1SDavid du Colombier  static Bigint *p5s;
2723e12c5d1SDavid du Colombier 
2733e12c5d1SDavid du Colombier  Bigint *
_pow5mult(Bigint * b,int k)2743e12c5d1SDavid du Colombier _pow5mult(Bigint *b, int k)
2753e12c5d1SDavid du Colombier {
2763e12c5d1SDavid du Colombier 	Bigint *b1, *p5, *p51;
2773e12c5d1SDavid du Colombier 	int i;
2783e12c5d1SDavid du Colombier 	static int p05[3] = { 5, 25, 125 };
2793e12c5d1SDavid du Colombier 
2803e12c5d1SDavid du Colombier 	if (i = k & 3)
2813e12c5d1SDavid du Colombier 		b = multadd(b, p05[i-1], 0);
2823e12c5d1SDavid du Colombier 
2833e12c5d1SDavid du Colombier 	if (!(k >>= 2))
2843e12c5d1SDavid du Colombier 		return b;
2853e12c5d1SDavid du Colombier 	if (!(p5 = p5s)) {
2863e12c5d1SDavid du Colombier 		/* first time */
2873e12c5d1SDavid du Colombier 		p5 = p5s = i2b(625);
2883e12c5d1SDavid du Colombier 		p5->next = 0;
2893e12c5d1SDavid du Colombier 		}
2903e12c5d1SDavid du Colombier 	for(;;) {
2913e12c5d1SDavid du Colombier 		if (k & 1) {
2923e12c5d1SDavid du Colombier 			b1 = mult(b, p5);
2933e12c5d1SDavid du Colombier 			Bfree(b);
2943e12c5d1SDavid du Colombier 			b = b1;
2953e12c5d1SDavid du Colombier 			}
2963e12c5d1SDavid du Colombier 		if (!(k >>= 1))
2973e12c5d1SDavid du Colombier 			break;
2983e12c5d1SDavid du Colombier 		if (!(p51 = p5->next)) {
2993e12c5d1SDavid du Colombier 			p51 = p5->next = mult(p5,p5);
3003e12c5d1SDavid du Colombier 			p51->next = 0;
3013e12c5d1SDavid du Colombier 			}
3023e12c5d1SDavid du Colombier 		p5 = p51;
3033e12c5d1SDavid du Colombier 		}
3043e12c5d1SDavid du Colombier 	return b;
3053e12c5d1SDavid du Colombier 	}
3063e12c5d1SDavid du Colombier 
3073e12c5d1SDavid du Colombier  Bigint *
_lshift(Bigint * b,int k)3083e12c5d1SDavid du Colombier _lshift(Bigint *b, int k)
3093e12c5d1SDavid du Colombier {
3103e12c5d1SDavid du Colombier 	int i, k1, n, n1;
3113e12c5d1SDavid du Colombier 	Bigint *b1;
3123e12c5d1SDavid du Colombier 	unsigned long *x, *x1, *xe, z;
3133e12c5d1SDavid du Colombier 
3143e12c5d1SDavid du Colombier #ifdef Pack_32
3153e12c5d1SDavid du Colombier 	n = k >> 5;
3163e12c5d1SDavid du Colombier #else
3173e12c5d1SDavid du Colombier 	n = k >> 4;
3183e12c5d1SDavid du Colombier #endif
3193e12c5d1SDavid du Colombier 	k1 = b->k;
3203e12c5d1SDavid du Colombier 	n1 = n + b->wds + 1;
3213e12c5d1SDavid du Colombier 	for(i = b->maxwds; n1 > i; i <<= 1)
3223e12c5d1SDavid du Colombier 		k1++;
3233e12c5d1SDavid du Colombier 	b1 = Balloc(k1);
3243e12c5d1SDavid du Colombier 	x1 = b1->x;
3253e12c5d1SDavid du Colombier 	for(i = 0; i < n; i++)
3263e12c5d1SDavid du Colombier 		*x1++ = 0;
3273e12c5d1SDavid du Colombier 	x = b->x;
3283e12c5d1SDavid du Colombier 	xe = x + b->wds;
3293e12c5d1SDavid du Colombier #ifdef Pack_32
3303e12c5d1SDavid du Colombier 	if (k &= 0x1f) {
3313e12c5d1SDavid du Colombier 		k1 = 32 - k;
3323e12c5d1SDavid du Colombier 		z = 0;
3333e12c5d1SDavid du Colombier 		do {
3343e12c5d1SDavid du Colombier 			*x1++ = *x << k | z;
3353e12c5d1SDavid du Colombier 			z = *x++ >> k1;
3363e12c5d1SDavid du Colombier 			}
3373e12c5d1SDavid du Colombier 			while(x < xe);
3383e12c5d1SDavid du Colombier 		if (*x1 = z)
3393e12c5d1SDavid du Colombier 			++n1;
3403e12c5d1SDavid du Colombier 		}
3413e12c5d1SDavid du Colombier #else
3423e12c5d1SDavid du Colombier 	if (k &= 0xf) {
3433e12c5d1SDavid du Colombier 		k1 = 16 - k;
3443e12c5d1SDavid du Colombier 		z = 0;
3453e12c5d1SDavid du Colombier 		do {
3463e12c5d1SDavid du Colombier 			*x1++ = *x << k  & 0xffff | z;
3473e12c5d1SDavid du Colombier 			z = *x++ >> k1;
3483e12c5d1SDavid du Colombier 			}
3493e12c5d1SDavid du Colombier 			while(x < xe);
3503e12c5d1SDavid du Colombier 		if (*x1 = z)
3513e12c5d1SDavid du Colombier 			++n1;
3523e12c5d1SDavid du Colombier 		}
3533e12c5d1SDavid du Colombier #endif
3543e12c5d1SDavid du Colombier 	else do
3553e12c5d1SDavid du Colombier 		*x1++ = *x++;
3563e12c5d1SDavid du Colombier 		while(x < xe);
3573e12c5d1SDavid du Colombier 	b1->wds = n1 - 1;
3583e12c5d1SDavid du Colombier 	Bfree(b);
3593e12c5d1SDavid du Colombier 	return b1;
3603e12c5d1SDavid du Colombier 	}
3613e12c5d1SDavid du Colombier 
3623e12c5d1SDavid du Colombier  int
_cmp(Bigint * a,Bigint * b)3633e12c5d1SDavid du Colombier _cmp(Bigint *a, Bigint *b)
3643e12c5d1SDavid du Colombier {
3653e12c5d1SDavid du Colombier 	unsigned long *xa, *xa0, *xb, *xb0;
3663e12c5d1SDavid du Colombier 	int i, j;
3673e12c5d1SDavid du Colombier 
3683e12c5d1SDavid du Colombier 	i = a->wds;
3693e12c5d1SDavid du Colombier 	j = b->wds;
3703e12c5d1SDavid du Colombier #ifdef DEBUG
3713e12c5d1SDavid du Colombier 	if (i > 1 && !a->x[i-1])
3723e12c5d1SDavid du Colombier 		Bug("cmp called with a->x[a->wds-1] == 0");
3733e12c5d1SDavid du Colombier 	if (j > 1 && !b->x[j-1])
3743e12c5d1SDavid du Colombier 		Bug("cmp called with b->x[b->wds-1] == 0");
3753e12c5d1SDavid du Colombier #endif
3763e12c5d1SDavid du Colombier 	if (i -= j)
3773e12c5d1SDavid du Colombier 		return i;
3783e12c5d1SDavid du Colombier 	xa0 = a->x;
3793e12c5d1SDavid du Colombier 	xa = xa0 + j;
3803e12c5d1SDavid du Colombier 	xb0 = b->x;
3813e12c5d1SDavid du Colombier 	xb = xb0 + j;
3823e12c5d1SDavid du Colombier 	for(;;) {
3833e12c5d1SDavid du Colombier 		if (*--xa != *--xb)
3843e12c5d1SDavid du Colombier 			return *xa < *xb ? -1 : 1;
3853e12c5d1SDavid du Colombier 		if (xa <= xa0)
3863e12c5d1SDavid du Colombier 			break;
3873e12c5d1SDavid du Colombier 		}
3883e12c5d1SDavid du Colombier 	return 0;
3893e12c5d1SDavid du Colombier 	}
3903e12c5d1SDavid du Colombier 
3913e12c5d1SDavid du Colombier  Bigint *
_diff(Bigint * a,Bigint * b)3923e12c5d1SDavid du Colombier _diff(Bigint *a, Bigint *b)
3933e12c5d1SDavid du Colombier {
3943e12c5d1SDavid du Colombier 	Bigint *c;
3953e12c5d1SDavid du Colombier 	int i, wa, wb;
3963e12c5d1SDavid du Colombier 	long borrow, y;	/* We need signed shifts here. */
3973e12c5d1SDavid du Colombier 	unsigned long *xa, *xae, *xb, *xbe, *xc;
3983e12c5d1SDavid du Colombier #ifdef Pack_32
3993e12c5d1SDavid du Colombier 	long z;
4003e12c5d1SDavid du Colombier #endif
4013e12c5d1SDavid du Colombier 
4023e12c5d1SDavid du Colombier 	i = cmp(a,b);
4033e12c5d1SDavid du Colombier 	if (!i) {
4043e12c5d1SDavid du Colombier 		c = Balloc(0);
4053e12c5d1SDavid du Colombier 		c->wds = 1;
4063e12c5d1SDavid du Colombier 		c->x[0] = 0;
4073e12c5d1SDavid du Colombier 		return c;
4083e12c5d1SDavid du Colombier 		}
4093e12c5d1SDavid du Colombier 	if (i < 0) {
4103e12c5d1SDavid du Colombier 		c = a;
4113e12c5d1SDavid du Colombier 		a = b;
4123e12c5d1SDavid du Colombier 		b = c;
4133e12c5d1SDavid du Colombier 		i = 1;
4143e12c5d1SDavid du Colombier 		}
4153e12c5d1SDavid du Colombier 	else
4163e12c5d1SDavid du Colombier 		i = 0;
4173e12c5d1SDavid du Colombier 	c = Balloc(a->k);
4183e12c5d1SDavid du Colombier 	c->sign = i;
4193e12c5d1SDavid du Colombier 	wa = a->wds;
4203e12c5d1SDavid du Colombier 	xa = a->x;
4213e12c5d1SDavid du Colombier 	xae = xa + wa;
4223e12c5d1SDavid du Colombier 	wb = b->wds;
4233e12c5d1SDavid du Colombier 	xb = b->x;
4243e12c5d1SDavid du Colombier 	xbe = xb + wb;
4253e12c5d1SDavid du Colombier 	xc = c->x;
4263e12c5d1SDavid du Colombier 	borrow = 0;
4273e12c5d1SDavid du Colombier #ifdef Pack_32
4283e12c5d1SDavid du Colombier 	do {
4293e12c5d1SDavid du Colombier 		y = (*xa & 0xffff) - (*xb & 0xffff) + borrow;
4303e12c5d1SDavid du Colombier 		borrow = y >> 16;
4313e12c5d1SDavid du Colombier 		Sign_Extend(borrow, y);
4323e12c5d1SDavid du Colombier 		z = (*xa++ >> 16) - (*xb++ >> 16) + borrow;
4333e12c5d1SDavid du Colombier 		borrow = z >> 16;
4343e12c5d1SDavid du Colombier 		Sign_Extend(borrow, z);
4353e12c5d1SDavid du Colombier 		Storeinc(xc, z, y);
4363e12c5d1SDavid du Colombier 		}
4373e12c5d1SDavid du Colombier 		while(xb < xbe);
4383e12c5d1SDavid du Colombier 	while(xa < xae) {
4393e12c5d1SDavid du Colombier 		y = (*xa & 0xffff) + borrow;
4403e12c5d1SDavid du Colombier 		borrow = y >> 16;
4413e12c5d1SDavid du Colombier 		Sign_Extend(borrow, y);
4423e12c5d1SDavid du Colombier 		z = (*xa++ >> 16) + borrow;
4433e12c5d1SDavid du Colombier 		borrow = z >> 16;
4443e12c5d1SDavid du Colombier 		Sign_Extend(borrow, z);
4453e12c5d1SDavid du Colombier 		Storeinc(xc, z, y);
4463e12c5d1SDavid du Colombier 		}
4473e12c5d1SDavid du Colombier #else
4483e12c5d1SDavid du Colombier 	do {
4493e12c5d1SDavid du Colombier 		y = *xa++ - *xb++ + borrow;
4503e12c5d1SDavid du Colombier 		borrow = y >> 16;
4513e12c5d1SDavid du Colombier 		Sign_Extend(borrow, y);
4523e12c5d1SDavid du Colombier 		*xc++ = y & 0xffff;
4533e12c5d1SDavid du Colombier 		}
4543e12c5d1SDavid du Colombier 		while(xb < xbe);
4553e12c5d1SDavid du Colombier 	while(xa < xae) {
4563e12c5d1SDavid du Colombier 		y = *xa++ + borrow;
4573e12c5d1SDavid du Colombier 		borrow = y >> 16;
4583e12c5d1SDavid du Colombier 		Sign_Extend(borrow, y);
4593e12c5d1SDavid du Colombier 		*xc++ = y & 0xffff;
4603e12c5d1SDavid du Colombier 		}
4613e12c5d1SDavid du Colombier #endif
4623e12c5d1SDavid du Colombier 	while(!*--xc)
4633e12c5d1SDavid du Colombier 		wa--;
4643e12c5d1SDavid du Colombier 	c->wds = wa;
4653e12c5d1SDavid du Colombier 	return c;
4663e12c5d1SDavid du Colombier 	}
4673e12c5d1SDavid du Colombier 
4683e12c5d1SDavid du Colombier  Bigint *
_d2b(double darg,int * e,int * bits)4693e12c5d1SDavid du Colombier _d2b(double darg, int *e, int *bits)
4703e12c5d1SDavid du Colombier {
4713e12c5d1SDavid du Colombier 	Bigint *b;
4723e12c5d1SDavid du Colombier 	int de, i, k;
4733e12c5d1SDavid du Colombier 	unsigned long *x, y, z;
4743e12c5d1SDavid du Colombier 	Dul d;
4753e12c5d1SDavid du Colombier #ifdef VAX
4763e12c5d1SDavid du Colombier 	unsigned long d0, d1;
4773e12c5d1SDavid du Colombier 	d.d = darg;
4783e12c5d1SDavid du Colombier 	d0 = word0(d) >> 16 | word0(d) << 16;
4793e12c5d1SDavid du Colombier 	d1 = word1(d) >> 16 | word1(d) << 16;
4803e12c5d1SDavid du Colombier #else
4813e12c5d1SDavid du Colombier 	d.d = darg;
4823e12c5d1SDavid du Colombier #define d0 word0(d)
4833e12c5d1SDavid du Colombier #define d1 word1(d)
4843e12c5d1SDavid du Colombier #endif
4853e12c5d1SDavid du Colombier 
4863e12c5d1SDavid du Colombier #ifdef Pack_32
4873e12c5d1SDavid du Colombier 	b = Balloc(1);
4883e12c5d1SDavid du Colombier #else
4893e12c5d1SDavid du Colombier 	b = Balloc(2);
4903e12c5d1SDavid du Colombier #endif
4913e12c5d1SDavid du Colombier 	x = b->x;
4923e12c5d1SDavid du Colombier 
4933e12c5d1SDavid du Colombier 	z = d0 & Frac_mask;
4943e12c5d1SDavid du Colombier 	d0 &= 0x7fffffff;	/* clear sign bit, which we ignore */
4953e12c5d1SDavid du Colombier #ifdef Sudden_Underflow
4963e12c5d1SDavid du Colombier 	de = (int)(d0 >> Exp_shift);
4973e12c5d1SDavid du Colombier #ifndef IBM
4983e12c5d1SDavid du Colombier 	z |= Exp_msk11;
4993e12c5d1SDavid du Colombier #endif
5003e12c5d1SDavid du Colombier #else
5013e12c5d1SDavid du Colombier 	if (de = (int)(d0 >> Exp_shift))
5023e12c5d1SDavid du Colombier 		z |= Exp_msk1;
5033e12c5d1SDavid du Colombier #endif
5043e12c5d1SDavid du Colombier #ifdef Pack_32
5053e12c5d1SDavid du Colombier 	if (y = d1) {
5063e12c5d1SDavid du Colombier 		if (k = lo0bits(&y)) {
5073e12c5d1SDavid du Colombier 			x[0] = y | z << 32 - k;
5083e12c5d1SDavid du Colombier 			z >>= k;
5093e12c5d1SDavid du Colombier 			}
5103e12c5d1SDavid du Colombier 		else
5113e12c5d1SDavid du Colombier 			x[0] = y;
5123e12c5d1SDavid du Colombier 		i = b->wds = (x[1] = z) ? 2 : 1;
513*22df390cSDavid du Colombier 		USED(i);
5143e12c5d1SDavid du Colombier 		}
5153e12c5d1SDavid du Colombier 	else {
5163e12c5d1SDavid du Colombier #ifdef DEBUG
5173e12c5d1SDavid du Colombier 		if (!z)
5183e12c5d1SDavid du Colombier 			Bug("Zero passed to d2b");
5193e12c5d1SDavid du Colombier #endif
5203e12c5d1SDavid du Colombier 		k = lo0bits(&z);
5213e12c5d1SDavid du Colombier 		x[0] = z;
5223e12c5d1SDavid du Colombier 		i = b->wds = 1;
523*22df390cSDavid du Colombier 		USED(i);
5243e12c5d1SDavid du Colombier 		k += 32;
5253e12c5d1SDavid du Colombier 		}
5263e12c5d1SDavid du Colombier #else
5273e12c5d1SDavid du Colombier 	if (y = d1) {
5283e12c5d1SDavid du Colombier 		if (k = lo0bits(&y))
5293e12c5d1SDavid du Colombier 			if (k >= 16) {
5303e12c5d1SDavid du Colombier 				x[0] = y | z << 32 - k & 0xffff;
5313e12c5d1SDavid du Colombier 				x[1] = z >> k - 16 & 0xffff;
5323e12c5d1SDavid du Colombier 				x[2] = z >> k;
5333e12c5d1SDavid du Colombier 				i = 2;
5343e12c5d1SDavid du Colombier 				}
5353e12c5d1SDavid du Colombier 			else {
5363e12c5d1SDavid du Colombier 				x[0] = y & 0xffff;
5373e12c5d1SDavid du Colombier 				x[1] = y >> 16 | z << 16 - k & 0xffff;
5383e12c5d1SDavid du Colombier 				x[2] = z >> k & 0xffff;
5393e12c5d1SDavid du Colombier 				x[3] = z >> k+16;
5403e12c5d1SDavid du Colombier 				i = 3;
5413e12c5d1SDavid du Colombier 				}
5423e12c5d1SDavid du Colombier 		else {
5433e12c5d1SDavid du Colombier 			x[0] = y & 0xffff;
5443e12c5d1SDavid du Colombier 			x[1] = y >> 16;
5453e12c5d1SDavid du Colombier 			x[2] = z & 0xffff;
5463e12c5d1SDavid du Colombier 			x[3] = z >> 16;
5473e12c5d1SDavid du Colombier 			i = 3;
5483e12c5d1SDavid du Colombier 			}
5493e12c5d1SDavid du Colombier 		}
5503e12c5d1SDavid du Colombier 	else {
5513e12c5d1SDavid du Colombier #ifdef DEBUG
5523e12c5d1SDavid du Colombier 		if (!z)
5533e12c5d1SDavid du Colombier 			Bug("Zero passed to d2b");
5543e12c5d1SDavid du Colombier #endif
5553e12c5d1SDavid du Colombier 		k = lo0bits(&z);
5563e12c5d1SDavid du Colombier 		if (k >= 16) {
5573e12c5d1SDavid du Colombier 			x[0] = z;
5583e12c5d1SDavid du Colombier 			i = 0;
5593e12c5d1SDavid du Colombier 			}
5603e12c5d1SDavid du Colombier 		else {
5613e12c5d1SDavid du Colombier 			x[0] = z & 0xffff;
5623e12c5d1SDavid du Colombier 			x[1] = z >> 16;
5633e12c5d1SDavid du Colombier 			i = 1;
5643e12c5d1SDavid du Colombier 			}
5653e12c5d1SDavid du Colombier 		k += 32;
5663e12c5d1SDavid du Colombier 		}
5673e12c5d1SDavid du Colombier 	while(!x[i])
5683e12c5d1SDavid du Colombier 		--i;
5693e12c5d1SDavid du Colombier 	b->wds = i + 1;
5703e12c5d1SDavid du Colombier #endif
5713e12c5d1SDavid du Colombier #ifndef Sudden_Underflow
5723e12c5d1SDavid du Colombier 	if (de) {
5733e12c5d1SDavid du Colombier #endif
5743e12c5d1SDavid du Colombier #ifdef IBM
5753e12c5d1SDavid du Colombier 		*e = (de - Bias - (P-1) << 2) + k;
5763e12c5d1SDavid du Colombier 		*bits = 4*P + 8 - k - hi0bits(word0(d) & Frac_mask);
5773e12c5d1SDavid du Colombier #else
5783e12c5d1SDavid du Colombier 		*e = de - Bias - (P-1) + k;
5793e12c5d1SDavid du Colombier 		*bits = P - k;
5803e12c5d1SDavid du Colombier #endif
5813e12c5d1SDavid du Colombier #ifndef Sudden_Underflow
5823e12c5d1SDavid du Colombier 		}
5833e12c5d1SDavid du Colombier 	else {
5843e12c5d1SDavid du Colombier 		*e = de - Bias - (P-1) + 1 + k;
5853e12c5d1SDavid du Colombier #ifdef Pack_32
5863e12c5d1SDavid du Colombier 		*bits = 32*i - hi0bits(x[i-1]);
5873e12c5d1SDavid du Colombier #else
5883e12c5d1SDavid du Colombier 		*bits = (i+2)*16 - hi0bits(x[i]);
5893e12c5d1SDavid du Colombier #endif
5903e12c5d1SDavid du Colombier 		}
5913e12c5d1SDavid du Colombier #endif
5923e12c5d1SDavid du Colombier 	return b;
5933e12c5d1SDavid du Colombier 	}
5943e12c5d1SDavid du Colombier #undef d0
5953e12c5d1SDavid du Colombier #undef d1
596