xref: /openbsd-src/lib/libc/gdtoa/misc.c (revision 3240e6a8f93e9dcb3b95e7fafb9e2b27f13c7c9d)
17b36286aSmartynas /****************************************************************
27b36286aSmartynas 
37b36286aSmartynas The author of this software is David M. Gay.
47b36286aSmartynas 
57b36286aSmartynas Copyright (C) 1998, 1999 by Lucent Technologies
67b36286aSmartynas All Rights Reserved
77b36286aSmartynas 
87b36286aSmartynas Permission to use, copy, modify, and distribute this software and
97b36286aSmartynas its documentation for any purpose and without fee is hereby
107b36286aSmartynas granted, provided that the above copyright notice appear in all
117b36286aSmartynas copies and that both that the copyright notice and this
127b36286aSmartynas permission notice and warranty disclaimer appear in supporting
137b36286aSmartynas documentation, and that the name of Lucent or any of its entities
147b36286aSmartynas not be used in advertising or publicity pertaining to
157b36286aSmartynas distribution of the software without specific, written prior
167b36286aSmartynas permission.
177b36286aSmartynas 
187b36286aSmartynas LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
197b36286aSmartynas INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
207b36286aSmartynas IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
217b36286aSmartynas SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
227b36286aSmartynas WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
237b36286aSmartynas IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
247b36286aSmartynas ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
257b36286aSmartynas THIS SOFTWARE.
267b36286aSmartynas 
277b36286aSmartynas ****************************************************************/
287b36286aSmartynas 
297b36286aSmartynas /* Please send bug reports to David M. Gay (dmg at acm dot org,
307b36286aSmartynas  * with " at " changed at "@" and " dot " changed to ".").	*/
317b36286aSmartynas 
327b36286aSmartynas #include "gdtoaimp.h"
337b36286aSmartynas 
347b36286aSmartynas  static Bigint *freelist[Kmax+1];
357b36286aSmartynas #ifndef Omit_Private_Memory
367b36286aSmartynas #ifndef PRIVATE_MEM
377b36286aSmartynas #define PRIVATE_MEM 2304
387b36286aSmartynas #endif
397b36286aSmartynas #define PRIVATE_mem ((PRIVATE_MEM+sizeof(double)-1)/sizeof(double))
407b36286aSmartynas static double private_mem[PRIVATE_mem], *pmem_next = private_mem;
417b36286aSmartynas #endif
427b36286aSmartynas 
43076bdf1eSderaadt #ifdef MULTIPLE_THREADS
44076bdf1eSderaadt static void *__dtoa_locks[] = { NULL, NULL };
45076bdf1eSderaadt #endif
46076bdf1eSderaadt 
477b36286aSmartynas  Bigint *
Balloc(k)487b36286aSmartynas Balloc
497b36286aSmartynas #ifdef KR_headers
507b36286aSmartynas 	(k) int k;
517b36286aSmartynas #else
527b36286aSmartynas 	(int k)
537b36286aSmartynas #endif
547b36286aSmartynas {
557b36286aSmartynas 	int x;
567b36286aSmartynas 	Bigint *rv;
577b36286aSmartynas #ifndef Omit_Private_Memory
587b36286aSmartynas 	unsigned int len;
597b36286aSmartynas #endif
607b36286aSmartynas 
617b36286aSmartynas 	ACQUIRE_DTOA_LOCK(0);
621a653cbcSmartynas 	/* The k > Kmax case does not need ACQUIRE_DTOA_LOCK(0), */
631a653cbcSmartynas 	/* but this case seems very unlikely. */
64f4514f75Smartynas 	if (k <= Kmax && (rv = freelist[k]) !=0) {
657b36286aSmartynas 		freelist[k] = rv->next;
667b36286aSmartynas 		}
677b36286aSmartynas 	else {
687b36286aSmartynas 		x = 1 << k;
697b36286aSmartynas #ifdef Omit_Private_Memory
707b36286aSmartynas 		rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(ULong));
71384cfdc1Smartynas 		if (rv == NULL)
72384cfdc1Smartynas 			return (NULL);
737b36286aSmartynas #else
747b36286aSmartynas 		len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1)
757b36286aSmartynas 			/sizeof(double);
76f4514f75Smartynas 		if (k <= Kmax && pmem_next - private_mem + len <= PRIVATE_mem) {
777b36286aSmartynas 			rv = (Bigint*)pmem_next;
787b36286aSmartynas 			pmem_next += len;
797b36286aSmartynas 			}
80384cfdc1Smartynas 		else {
817b36286aSmartynas 			rv = (Bigint*)MALLOC(len*sizeof(double));
82384cfdc1Smartynas 			if (rv == NULL)
83384cfdc1Smartynas 				return (NULL);
84384cfdc1Smartynas 		}
857b36286aSmartynas #endif
867b36286aSmartynas 		rv->k = k;
877b36286aSmartynas 		rv->maxwds = x;
887b36286aSmartynas 		}
897b36286aSmartynas 	FREE_DTOA_LOCK(0);
907b36286aSmartynas 	rv->sign = rv->wds = 0;
917b36286aSmartynas 	return rv;
927b36286aSmartynas 	}
937b36286aSmartynas 
947b36286aSmartynas  void
Bfree(v)957b36286aSmartynas Bfree
967b36286aSmartynas #ifdef KR_headers
977b36286aSmartynas 	(v) Bigint *v;
987b36286aSmartynas #else
997b36286aSmartynas 	(Bigint *v)
1007b36286aSmartynas #endif
1017b36286aSmartynas {
1027b36286aSmartynas 	if (v) {
1031a653cbcSmartynas 		if (v->k > Kmax)
1041a653cbcSmartynas #ifdef FREE
105*3240e6a8Sguenther 			FREE(v);
1061a653cbcSmartynas #else
107*3240e6a8Sguenther 			free(v);
1081a653cbcSmartynas #endif
1091a653cbcSmartynas 		else {
1107b36286aSmartynas 			ACQUIRE_DTOA_LOCK(0);
1117b36286aSmartynas 			v->next = freelist[v->k];
1127b36286aSmartynas 			freelist[v->k] = v;
1137b36286aSmartynas 			FREE_DTOA_LOCK(0);
1147b36286aSmartynas 			}
1157b36286aSmartynas 		}
1161a653cbcSmartynas 	}
1177b36286aSmartynas 
1187b36286aSmartynas  int
lo0bits(y)1197b36286aSmartynas lo0bits
1207b36286aSmartynas #ifdef KR_headers
1217b36286aSmartynas 	(y) ULong *y;
1227b36286aSmartynas #else
1237b36286aSmartynas 	(ULong *y)
1247b36286aSmartynas #endif
1257b36286aSmartynas {
1261a653cbcSmartynas 	int k;
1271a653cbcSmartynas 	ULong x = *y;
1287b36286aSmartynas 
1297b36286aSmartynas 	if (x & 7) {
1307b36286aSmartynas 		if (x & 1)
1317b36286aSmartynas 			return 0;
1327b36286aSmartynas 		if (x & 2) {
1337b36286aSmartynas 			*y = x >> 1;
1347b36286aSmartynas 			return 1;
1357b36286aSmartynas 			}
1367b36286aSmartynas 		*y = x >> 2;
1377b36286aSmartynas 		return 2;
1387b36286aSmartynas 		}
1397b36286aSmartynas 	k = 0;
1407b36286aSmartynas 	if (!(x & 0xffff)) {
1417b36286aSmartynas 		k = 16;
1427b36286aSmartynas 		x >>= 16;
1437b36286aSmartynas 		}
1447b36286aSmartynas 	if (!(x & 0xff)) {
1457b36286aSmartynas 		k += 8;
1467b36286aSmartynas 		x >>= 8;
1477b36286aSmartynas 		}
1487b36286aSmartynas 	if (!(x & 0xf)) {
1497b36286aSmartynas 		k += 4;
1507b36286aSmartynas 		x >>= 4;
1517b36286aSmartynas 		}
1527b36286aSmartynas 	if (!(x & 0x3)) {
1537b36286aSmartynas 		k += 2;
1547b36286aSmartynas 		x >>= 2;
1557b36286aSmartynas 		}
1567b36286aSmartynas 	if (!(x & 1)) {
1577b36286aSmartynas 		k++;
1587b36286aSmartynas 		x >>= 1;
1597b36286aSmartynas 		if (!x)
1607b36286aSmartynas 			return 32;
1617b36286aSmartynas 		}
1627b36286aSmartynas 	*y = x;
1637b36286aSmartynas 	return k;
1647b36286aSmartynas 	}
1657b36286aSmartynas 
1667b36286aSmartynas  Bigint *
multadd(b,m,a)1677b36286aSmartynas multadd
1687b36286aSmartynas #ifdef KR_headers
1697b36286aSmartynas 	(b, m, a) Bigint *b; int m, a;
1707b36286aSmartynas #else
1717b36286aSmartynas 	(Bigint *b, int m, int a)	/* multiply by m and add a */
1727b36286aSmartynas #endif
1737b36286aSmartynas {
1747b36286aSmartynas 	int i, wds;
1757b36286aSmartynas #ifdef ULLong
1767b36286aSmartynas 	ULong *x;
1777b36286aSmartynas 	ULLong carry, y;
1787b36286aSmartynas #else
1797b36286aSmartynas 	ULong carry, *x, y;
1807b36286aSmartynas #ifdef Pack_32
1817b36286aSmartynas 	ULong xi, z;
1827b36286aSmartynas #endif
1837b36286aSmartynas #endif
1847b36286aSmartynas 	Bigint *b1;
1857b36286aSmartynas 
1867b36286aSmartynas 	wds = b->wds;
1877b36286aSmartynas 	x = b->x;
1887b36286aSmartynas 	i = 0;
1897b36286aSmartynas 	carry = a;
1907b36286aSmartynas 	do {
1917b36286aSmartynas #ifdef ULLong
1927b36286aSmartynas 		y = *x * (ULLong)m + carry;
1937b36286aSmartynas 		carry = y >> 32;
1947b36286aSmartynas 		*x++ = y & 0xffffffffUL;
1957b36286aSmartynas #else
1967b36286aSmartynas #ifdef Pack_32
1977b36286aSmartynas 		xi = *x;
1987b36286aSmartynas 		y = (xi & 0xffff) * m + carry;
1997b36286aSmartynas 		z = (xi >> 16) * m + (y >> 16);
2007b36286aSmartynas 		carry = z >> 16;
2017b36286aSmartynas 		*x++ = (z << 16) + (y & 0xffff);
2027b36286aSmartynas #else
2037b36286aSmartynas 		y = *x * m + carry;
2047b36286aSmartynas 		carry = y >> 16;
2057b36286aSmartynas 		*x++ = y & 0xffff;
2067b36286aSmartynas #endif
2077b36286aSmartynas #endif
2087b36286aSmartynas 		}
2097b36286aSmartynas 		while(++i < wds);
2107b36286aSmartynas 	if (carry) {
2117b36286aSmartynas 		if (wds >= b->maxwds) {
2127b36286aSmartynas 			b1 = Balloc(b->k+1);
213384cfdc1Smartynas 			if (b1 == NULL)
214384cfdc1Smartynas 				return (NULL);
2157b36286aSmartynas 			Bcopy(b1, b);
2167b36286aSmartynas 			Bfree(b);
2177b36286aSmartynas 			b = b1;
2187b36286aSmartynas 			}
2197b36286aSmartynas 		b->x[wds++] = carry;
2207b36286aSmartynas 		b->wds = wds;
2217b36286aSmartynas 		}
2227b36286aSmartynas 	return b;
2237b36286aSmartynas 	}
2247b36286aSmartynas 
2257b36286aSmartynas  int
hi0bits_D2A(x)2267b36286aSmartynas hi0bits_D2A
2277b36286aSmartynas #ifdef KR_headers
2281a653cbcSmartynas 	(x) ULong x;
2297b36286aSmartynas #else
2301a653cbcSmartynas 	(ULong x)
2317b36286aSmartynas #endif
2327b36286aSmartynas {
2331a653cbcSmartynas 	int k = 0;
2347b36286aSmartynas 
2357b36286aSmartynas 	if (!(x & 0xffff0000)) {
2367b36286aSmartynas 		k = 16;
2377b36286aSmartynas 		x <<= 16;
2387b36286aSmartynas 		}
2397b36286aSmartynas 	if (!(x & 0xff000000)) {
2407b36286aSmartynas 		k += 8;
2417b36286aSmartynas 		x <<= 8;
2427b36286aSmartynas 		}
2437b36286aSmartynas 	if (!(x & 0xf0000000)) {
2447b36286aSmartynas 		k += 4;
2457b36286aSmartynas 		x <<= 4;
2467b36286aSmartynas 		}
2477b36286aSmartynas 	if (!(x & 0xc0000000)) {
2487b36286aSmartynas 		k += 2;
2497b36286aSmartynas 		x <<= 2;
2507b36286aSmartynas 		}
2517b36286aSmartynas 	if (!(x & 0x80000000)) {
2527b36286aSmartynas 		k++;
2537b36286aSmartynas 		if (!(x & 0x40000000))
2547b36286aSmartynas 			return 32;
2557b36286aSmartynas 		}
2567b36286aSmartynas 	return k;
2577b36286aSmartynas 	}
2587b36286aSmartynas 
2597b36286aSmartynas  Bigint *
i2b(i)2607b36286aSmartynas i2b
2617b36286aSmartynas #ifdef KR_headers
2627b36286aSmartynas 	(i) int i;
2637b36286aSmartynas #else
2647b36286aSmartynas 	(int i)
2657b36286aSmartynas #endif
2667b36286aSmartynas {
2677b36286aSmartynas 	Bigint *b;
2687b36286aSmartynas 
2697b36286aSmartynas 	b = Balloc(1);
270384cfdc1Smartynas 	if (b == NULL)
271384cfdc1Smartynas 		return (NULL);
2727b36286aSmartynas 	b->x[0] = i;
2737b36286aSmartynas 	b->wds = 1;
2747b36286aSmartynas 	return b;
2757b36286aSmartynas 	}
2767b36286aSmartynas 
2777b36286aSmartynas  Bigint *
mult(a,b)2787b36286aSmartynas mult
2797b36286aSmartynas #ifdef KR_headers
2807b36286aSmartynas 	(a, b) Bigint *a, *b;
2817b36286aSmartynas #else
2827b36286aSmartynas 	(Bigint *a, Bigint *b)
2837b36286aSmartynas #endif
2847b36286aSmartynas {
2857b36286aSmartynas 	Bigint *c;
2867b36286aSmartynas 	int k, wa, wb, wc;
2877b36286aSmartynas 	ULong *x, *xa, *xae, *xb, *xbe, *xc, *xc0;
2887b36286aSmartynas 	ULong y;
2897b36286aSmartynas #ifdef ULLong
2907b36286aSmartynas 	ULLong carry, z;
2917b36286aSmartynas #else
2927b36286aSmartynas 	ULong carry, z;
2937b36286aSmartynas #ifdef Pack_32
2947b36286aSmartynas 	ULong z2;
2957b36286aSmartynas #endif
2967b36286aSmartynas #endif
2977b36286aSmartynas 
2987b36286aSmartynas 	if (a->wds < b->wds) {
2997b36286aSmartynas 		c = a;
3007b36286aSmartynas 		a = b;
3017b36286aSmartynas 		b = c;
3027b36286aSmartynas 		}
3037b36286aSmartynas 	k = a->k;
3047b36286aSmartynas 	wa = a->wds;
3057b36286aSmartynas 	wb = b->wds;
3067b36286aSmartynas 	wc = wa + wb;
3077b36286aSmartynas 	if (wc > a->maxwds)
3087b36286aSmartynas 		k++;
3097b36286aSmartynas 	c = Balloc(k);
310384cfdc1Smartynas 	if (c == NULL)
311384cfdc1Smartynas 		return (NULL);
3127b36286aSmartynas 	for(x = c->x, xa = x + wc; x < xa; x++)
3137b36286aSmartynas 		*x = 0;
3147b36286aSmartynas 	xa = a->x;
3157b36286aSmartynas 	xae = xa + wa;
3167b36286aSmartynas 	xb = b->x;
3177b36286aSmartynas 	xbe = xb + wb;
3187b36286aSmartynas 	xc0 = c->x;
3197b36286aSmartynas #ifdef ULLong
3207b36286aSmartynas 	for(; xb < xbe; xc0++) {
3217b36286aSmartynas 		if ( (y = *xb++) !=0) {
3227b36286aSmartynas 			x = xa;
3237b36286aSmartynas 			xc = xc0;
3247b36286aSmartynas 			carry = 0;
3257b36286aSmartynas 			do {
3267b36286aSmartynas 				z = *x++ * (ULLong)y + *xc + carry;
3277b36286aSmartynas 				carry = z >> 32;
3287b36286aSmartynas 				*xc++ = z & 0xffffffffUL;
3297b36286aSmartynas 				}
3307b36286aSmartynas 				while(x < xae);
3317b36286aSmartynas 			*xc = carry;
3327b36286aSmartynas 			}
3337b36286aSmartynas 		}
3347b36286aSmartynas #else
3357b36286aSmartynas #ifdef Pack_32
3367b36286aSmartynas 	for(; xb < xbe; xb++, xc0++) {
3377b36286aSmartynas 		if ( (y = *xb & 0xffff) !=0) {
3387b36286aSmartynas 			x = xa;
3397b36286aSmartynas 			xc = xc0;
3407b36286aSmartynas 			carry = 0;
3417b36286aSmartynas 			do {
3427b36286aSmartynas 				z = (*x & 0xffff) * y + (*xc & 0xffff) + carry;
3437b36286aSmartynas 				carry = z >> 16;
3447b36286aSmartynas 				z2 = (*x++ >> 16) * y + (*xc >> 16) + carry;
3457b36286aSmartynas 				carry = z2 >> 16;
3467b36286aSmartynas 				Storeinc(xc, z2, z);
3477b36286aSmartynas 				}
3487b36286aSmartynas 				while(x < xae);
3497b36286aSmartynas 			*xc = carry;
3507b36286aSmartynas 			}
3517b36286aSmartynas 		if ( (y = *xb >> 16) !=0) {
3527b36286aSmartynas 			x = xa;
3537b36286aSmartynas 			xc = xc0;
3547b36286aSmartynas 			carry = 0;
3557b36286aSmartynas 			z2 = *xc;
3567b36286aSmartynas 			do {
3577b36286aSmartynas 				z = (*x & 0xffff) * y + (*xc >> 16) + carry;
3587b36286aSmartynas 				carry = z >> 16;
3597b36286aSmartynas 				Storeinc(xc, z, z2);
3607b36286aSmartynas 				z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry;
3617b36286aSmartynas 				carry = z2 >> 16;
3627b36286aSmartynas 				}
3637b36286aSmartynas 				while(x < xae);
3647b36286aSmartynas 			*xc = z2;
3657b36286aSmartynas 			}
3667b36286aSmartynas 		}
3677b36286aSmartynas #else
3687b36286aSmartynas 	for(; xb < xbe; xc0++) {
3697b36286aSmartynas 		if ( (y = *xb++) !=0) {
3707b36286aSmartynas 			x = xa;
3717b36286aSmartynas 			xc = xc0;
3727b36286aSmartynas 			carry = 0;
3737b36286aSmartynas 			do {
3747b36286aSmartynas 				z = *x++ * y + *xc + carry;
3757b36286aSmartynas 				carry = z >> 16;
3767b36286aSmartynas 				*xc++ = z & 0xffff;
3777b36286aSmartynas 				}
3787b36286aSmartynas 				while(x < xae);
3797b36286aSmartynas 			*xc = carry;
3807b36286aSmartynas 			}
3817b36286aSmartynas 		}
3827b36286aSmartynas #endif
3837b36286aSmartynas #endif
3847b36286aSmartynas 	for(xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ;
3857b36286aSmartynas 	c->wds = wc;
3867b36286aSmartynas 	return c;
3877b36286aSmartynas 	}
3887b36286aSmartynas 
3897b36286aSmartynas  static Bigint *p5s;
3907b36286aSmartynas 
3917b36286aSmartynas  Bigint *
pow5mult(b,k)3927b36286aSmartynas pow5mult
3937b36286aSmartynas #ifdef KR_headers
3947b36286aSmartynas 	(b, k) Bigint *b; int k;
3957b36286aSmartynas #else
3967b36286aSmartynas 	(Bigint *b, int k)
3977b36286aSmartynas #endif
3987b36286aSmartynas {
3997b36286aSmartynas 	Bigint *b1, *p5, *p51;
4007b36286aSmartynas 	int i;
4017b36286aSmartynas 	static int p05[3] = { 5, 25, 125 };
4027b36286aSmartynas 
403384cfdc1Smartynas 	if ( (i = k & 3) !=0) {
4047b36286aSmartynas 		b = multadd(b, p05[i-1], 0);
405384cfdc1Smartynas 		if (b == NULL)
406384cfdc1Smartynas 			return (NULL);
407384cfdc1Smartynas 		}
4087b36286aSmartynas 
4097b36286aSmartynas 	if (!(k >>= 2))
4107b36286aSmartynas 		return b;
4117b36286aSmartynas 	if ((p5 = p5s) == 0) {
4127b36286aSmartynas 		/* first time */
4137b36286aSmartynas #ifdef MULTIPLE_THREADS
4147b36286aSmartynas 		ACQUIRE_DTOA_LOCK(1);
4157b36286aSmartynas 		if (!(p5 = p5s)) {
4167b36286aSmartynas 			p5 = p5s = i2b(625);
417384cfdc1Smartynas 			if (p5 == NULL)
418384cfdc1Smartynas 				return (NULL);
4197b36286aSmartynas 			p5->next = 0;
4207b36286aSmartynas 			}
4217b36286aSmartynas 		FREE_DTOA_LOCK(1);
4227b36286aSmartynas #else
4237b36286aSmartynas 		p5 = p5s = i2b(625);
424384cfdc1Smartynas 		if (p5 == NULL)
425384cfdc1Smartynas 			return (NULL);
4267b36286aSmartynas 		p5->next = 0;
4277b36286aSmartynas #endif
4287b36286aSmartynas 		}
4297b36286aSmartynas 	for(;;) {
4307b36286aSmartynas 		if (k & 1) {
4317b36286aSmartynas 			b1 = mult(b, p5);
432384cfdc1Smartynas 			if (b1 == NULL)
433384cfdc1Smartynas 				return (NULL);
4347b36286aSmartynas 			Bfree(b);
4357b36286aSmartynas 			b = b1;
4367b36286aSmartynas 			}
4377b36286aSmartynas 		if (!(k >>= 1))
4387b36286aSmartynas 			break;
4397b36286aSmartynas 		if ((p51 = p5->next) == 0) {
4407b36286aSmartynas #ifdef MULTIPLE_THREADS
4417b36286aSmartynas 			ACQUIRE_DTOA_LOCK(1);
4427b36286aSmartynas 			if (!(p51 = p5->next)) {
4437b36286aSmartynas 				p51 = p5->next = mult(p5,p5);
444384cfdc1Smartynas 				if (p51 == NULL)
445384cfdc1Smartynas 					return (NULL);
4467b36286aSmartynas 				p51->next = 0;
4477b36286aSmartynas 				}
4487b36286aSmartynas 			FREE_DTOA_LOCK(1);
4497b36286aSmartynas #else
4507b36286aSmartynas 			p51 = p5->next = mult(p5,p5);
451384cfdc1Smartynas 			if (p51 == NULL)
452384cfdc1Smartynas 				return (NULL);
4537b36286aSmartynas 			p51->next = 0;
4547b36286aSmartynas #endif
4557b36286aSmartynas 			}
4567b36286aSmartynas 		p5 = p51;
4577b36286aSmartynas 		}
4587b36286aSmartynas 	return b;
4597b36286aSmartynas 	}
4607b36286aSmartynas 
4617b36286aSmartynas  Bigint *
lshift(b,k)4627b36286aSmartynas lshift
4637b36286aSmartynas #ifdef KR_headers
4647b36286aSmartynas 	(b, k) Bigint *b; int k;
4657b36286aSmartynas #else
4667b36286aSmartynas 	(Bigint *b, int k)
4677b36286aSmartynas #endif
4687b36286aSmartynas {
4697b36286aSmartynas 	int i, k1, n, n1;
4707b36286aSmartynas 	Bigint *b1;
4717b36286aSmartynas 	ULong *x, *x1, *xe, z;
4727b36286aSmartynas 
4737b36286aSmartynas 	n = k >> kshift;
4747b36286aSmartynas 	k1 = b->k;
4757b36286aSmartynas 	n1 = n + b->wds + 1;
4767b36286aSmartynas 	for(i = b->maxwds; n1 > i; i <<= 1)
4777b36286aSmartynas 		k1++;
4787b36286aSmartynas 	b1 = Balloc(k1);
479384cfdc1Smartynas 	if (b1 == NULL)
480384cfdc1Smartynas 		return (NULL);
4817b36286aSmartynas 	x1 = b1->x;
4827b36286aSmartynas 	for(i = 0; i < n; i++)
4837b36286aSmartynas 		*x1++ = 0;
4847b36286aSmartynas 	x = b->x;
4857b36286aSmartynas 	xe = x + b->wds;
4867b36286aSmartynas 	if (k &= kmask) {
4877b36286aSmartynas #ifdef Pack_32
4887b36286aSmartynas 		k1 = 32 - k;
4897b36286aSmartynas 		z = 0;
4907b36286aSmartynas 		do {
4917b36286aSmartynas 			*x1++ = *x << k | z;
4927b36286aSmartynas 			z = *x++ >> k1;
4937b36286aSmartynas 			}
4947b36286aSmartynas 			while(x < xe);
4957b36286aSmartynas 		if ((*x1 = z) !=0)
4967b36286aSmartynas 			++n1;
4977b36286aSmartynas #else
4987b36286aSmartynas 		k1 = 16 - k;
4997b36286aSmartynas 		z = 0;
5007b36286aSmartynas 		do {
5017b36286aSmartynas 			*x1++ = *x << k  & 0xffff | z;
5027b36286aSmartynas 			z = *x++ >> k1;
5037b36286aSmartynas 			}
5047b36286aSmartynas 			while(x < xe);
5057b36286aSmartynas 		if (*x1 = z)
5067b36286aSmartynas 			++n1;
5077b36286aSmartynas #endif
5087b36286aSmartynas 		}
5097b36286aSmartynas 	else do
5107b36286aSmartynas 		*x1++ = *x++;
5117b36286aSmartynas 		while(x < xe);
5127b36286aSmartynas 	b1->wds = n1 - 1;
5137b36286aSmartynas 	Bfree(b);
5147b36286aSmartynas 	return b1;
5157b36286aSmartynas 	}
5167b36286aSmartynas 
5177b36286aSmartynas  int
cmp(a,b)5187b36286aSmartynas cmp
5197b36286aSmartynas #ifdef KR_headers
5207b36286aSmartynas 	(a, b) Bigint *a, *b;
5217b36286aSmartynas #else
5227b36286aSmartynas 	(Bigint *a, Bigint *b)
5237b36286aSmartynas #endif
5247b36286aSmartynas {
5257b36286aSmartynas 	ULong *xa, *xa0, *xb, *xb0;
5267b36286aSmartynas 	int i, j;
5277b36286aSmartynas 
5287b36286aSmartynas 	i = a->wds;
5297b36286aSmartynas 	j = b->wds;
5307b36286aSmartynas #ifdef DEBUG
5317b36286aSmartynas 	if (i > 1 && !a->x[i-1])
5327b36286aSmartynas 		Bug("cmp called with a->x[a->wds-1] == 0");
5337b36286aSmartynas 	if (j > 1 && !b->x[j-1])
5347b36286aSmartynas 		Bug("cmp called with b->x[b->wds-1] == 0");
5357b36286aSmartynas #endif
5367b36286aSmartynas 	if (i -= j)
5377b36286aSmartynas 		return i;
5387b36286aSmartynas 	xa0 = a->x;
5397b36286aSmartynas 	xa = xa0 + j;
5407b36286aSmartynas 	xb0 = b->x;
5417b36286aSmartynas 	xb = xb0 + j;
5427b36286aSmartynas 	for(;;) {
5437b36286aSmartynas 		if (*--xa != *--xb)
5447b36286aSmartynas 			return *xa < *xb ? -1 : 1;
5457b36286aSmartynas 		if (xa <= xa0)
5467b36286aSmartynas 			break;
5477b36286aSmartynas 		}
5487b36286aSmartynas 	return 0;
5497b36286aSmartynas 	}
5507b36286aSmartynas 
5517b36286aSmartynas  Bigint *
diff(a,b)5527b36286aSmartynas diff
5537b36286aSmartynas #ifdef KR_headers
5547b36286aSmartynas 	(a, b) Bigint *a, *b;
5557b36286aSmartynas #else
5567b36286aSmartynas 	(Bigint *a, Bigint *b)
5577b36286aSmartynas #endif
5587b36286aSmartynas {
5597b36286aSmartynas 	Bigint *c;
5607b36286aSmartynas 	int i, wa, wb;
5617b36286aSmartynas 	ULong *xa, *xae, *xb, *xbe, *xc;
5627b36286aSmartynas #ifdef ULLong
5637b36286aSmartynas 	ULLong borrow, y;
5647b36286aSmartynas #else
5657b36286aSmartynas 	ULong borrow, y;
5667b36286aSmartynas #ifdef Pack_32
5677b36286aSmartynas 	ULong z;
5687b36286aSmartynas #endif
5697b36286aSmartynas #endif
5707b36286aSmartynas 
5717b36286aSmartynas 	i = cmp(a,b);
5727b36286aSmartynas 	if (!i) {
5737b36286aSmartynas 		c = Balloc(0);
574384cfdc1Smartynas 		if (c == NULL)
575384cfdc1Smartynas 			return (NULL);
5767b36286aSmartynas 		c->wds = 1;
5777b36286aSmartynas 		c->x[0] = 0;
5787b36286aSmartynas 		return c;
5797b36286aSmartynas 		}
5807b36286aSmartynas 	if (i < 0) {
5817b36286aSmartynas 		c = a;
5827b36286aSmartynas 		a = b;
5837b36286aSmartynas 		b = c;
5847b36286aSmartynas 		i = 1;
5857b36286aSmartynas 		}
5867b36286aSmartynas 	else
5877b36286aSmartynas 		i = 0;
5887b36286aSmartynas 	c = Balloc(a->k);
589384cfdc1Smartynas 	if (c == NULL)
590384cfdc1Smartynas 		return (NULL);
5917b36286aSmartynas 	c->sign = i;
5927b36286aSmartynas 	wa = a->wds;
5937b36286aSmartynas 	xa = a->x;
5947b36286aSmartynas 	xae = xa + wa;
5957b36286aSmartynas 	wb = b->wds;
5967b36286aSmartynas 	xb = b->x;
5977b36286aSmartynas 	xbe = xb + wb;
5987b36286aSmartynas 	xc = c->x;
5997b36286aSmartynas 	borrow = 0;
6007b36286aSmartynas #ifdef ULLong
6017b36286aSmartynas 	do {
6027b36286aSmartynas 		y = (ULLong)*xa++ - *xb++ - borrow;
6037b36286aSmartynas 		borrow = y >> 32 & 1UL;
6047b36286aSmartynas 		*xc++ = y & 0xffffffffUL;
6057b36286aSmartynas 		}
6067b36286aSmartynas 		while(xb < xbe);
6077b36286aSmartynas 	while(xa < xae) {
6087b36286aSmartynas 		y = *xa++ - borrow;
6097b36286aSmartynas 		borrow = y >> 32 & 1UL;
6107b36286aSmartynas 		*xc++ = y & 0xffffffffUL;
6117b36286aSmartynas 		}
6127b36286aSmartynas #else
6137b36286aSmartynas #ifdef Pack_32
6147b36286aSmartynas 	do {
6157b36286aSmartynas 		y = (*xa & 0xffff) - (*xb & 0xffff) - borrow;
6167b36286aSmartynas 		borrow = (y & 0x10000) >> 16;
6177b36286aSmartynas 		z = (*xa++ >> 16) - (*xb++ >> 16) - borrow;
6187b36286aSmartynas 		borrow = (z & 0x10000) >> 16;
6197b36286aSmartynas 		Storeinc(xc, z, y);
6207b36286aSmartynas 		}
6217b36286aSmartynas 		while(xb < xbe);
6227b36286aSmartynas 	while(xa < xae) {
6237b36286aSmartynas 		y = (*xa & 0xffff) - borrow;
6247b36286aSmartynas 		borrow = (y & 0x10000) >> 16;
6257b36286aSmartynas 		z = (*xa++ >> 16) - borrow;
6267b36286aSmartynas 		borrow = (z & 0x10000) >> 16;
6277b36286aSmartynas 		Storeinc(xc, z, y);
6287b36286aSmartynas 		}
6297b36286aSmartynas #else
6307b36286aSmartynas 	do {
6317b36286aSmartynas 		y = *xa++ - *xb++ - borrow;
6327b36286aSmartynas 		borrow = (y & 0x10000) >> 16;
6337b36286aSmartynas 		*xc++ = y & 0xffff;
6347b36286aSmartynas 		}
6357b36286aSmartynas 		while(xb < xbe);
6367b36286aSmartynas 	while(xa < xae) {
6377b36286aSmartynas 		y = *xa++ - borrow;
6387b36286aSmartynas 		borrow = (y & 0x10000) >> 16;
6397b36286aSmartynas 		*xc++ = y & 0xffff;
6407b36286aSmartynas 		}
6417b36286aSmartynas #endif
6427b36286aSmartynas #endif
6437b36286aSmartynas 	while(!*--xc)
6447b36286aSmartynas 		wa--;
6457b36286aSmartynas 	c->wds = wa;
6467b36286aSmartynas 	return c;
6477b36286aSmartynas 	}
6487b36286aSmartynas 
6497b36286aSmartynas  double
b2d(a,e)6507b36286aSmartynas b2d
6517b36286aSmartynas #ifdef KR_headers
6527b36286aSmartynas 	(a, e) Bigint *a; int *e;
6537b36286aSmartynas #else
6547b36286aSmartynas 	(Bigint *a, int *e)
6557b36286aSmartynas #endif
6567b36286aSmartynas {
6577b36286aSmartynas 	ULong *xa, *xa0, w, y, z;
6587b36286aSmartynas 	int k;
6591a653cbcSmartynas 	U d;
6607b36286aSmartynas #ifdef VAX
6617b36286aSmartynas 	ULong d0, d1;
6627b36286aSmartynas #else
6631a653cbcSmartynas #define d0 word0(&d)
6641a653cbcSmartynas #define d1 word1(&d)
6657b36286aSmartynas #endif
6667b36286aSmartynas 
6677b36286aSmartynas 	xa0 = a->x;
6687b36286aSmartynas 	xa = xa0 + a->wds;
6697b36286aSmartynas 	y = *--xa;
6707b36286aSmartynas #ifdef DEBUG
6717b36286aSmartynas 	if (!y) Bug("zero y in b2d");
6727b36286aSmartynas #endif
6737b36286aSmartynas 	k = hi0bits(y);
6747b36286aSmartynas 	*e = 32 - k;
6757b36286aSmartynas #ifdef Pack_32
6767b36286aSmartynas 	if (k < Ebits) {
6771a653cbcSmartynas 		d0 = Exp_1 | y >> (Ebits - k);
6787b36286aSmartynas 		w = xa > xa0 ? *--xa : 0;
6791a653cbcSmartynas 		d1 = y << ((32-Ebits) + k) | w >> (Ebits - k);
6807b36286aSmartynas 		goto ret_d;
6817b36286aSmartynas 		}
6827b36286aSmartynas 	z = xa > xa0 ? *--xa : 0;
6837b36286aSmartynas 	if (k -= Ebits) {
6841a653cbcSmartynas 		d0 = Exp_1 | y << k | z >> (32 - k);
6857b36286aSmartynas 		y = xa > xa0 ? *--xa : 0;
6861a653cbcSmartynas 		d1 = z << k | y >> (32 - k);
6877b36286aSmartynas 		}
6887b36286aSmartynas 	else {
6897b36286aSmartynas 		d0 = Exp_1 | y;
6907b36286aSmartynas 		d1 = z;
6917b36286aSmartynas 		}
6927b36286aSmartynas #else
6937b36286aSmartynas 	if (k < Ebits + 16) {
6947b36286aSmartynas 		z = xa > xa0 ? *--xa : 0;
6957b36286aSmartynas 		d0 = Exp_1 | y << k - Ebits | z >> Ebits + 16 - k;
6967b36286aSmartynas 		w = xa > xa0 ? *--xa : 0;
6977b36286aSmartynas 		y = xa > xa0 ? *--xa : 0;
6987b36286aSmartynas 		d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k;
6997b36286aSmartynas 		goto ret_d;
7007b36286aSmartynas 		}
7017b36286aSmartynas 	z = xa > xa0 ? *--xa : 0;
7027b36286aSmartynas 	w = xa > xa0 ? *--xa : 0;
7037b36286aSmartynas 	k -= Ebits + 16;
7047b36286aSmartynas 	d0 = Exp_1 | y << k + 16 | z << k | w >> 16 - k;
7057b36286aSmartynas 	y = xa > xa0 ? *--xa : 0;
7067b36286aSmartynas 	d1 = w << k + 16 | y << k;
7077b36286aSmartynas #endif
7087b36286aSmartynas  ret_d:
7097b36286aSmartynas #ifdef VAX
7101a653cbcSmartynas 	word0(&d) = d0 >> 16 | d0 << 16;
7111a653cbcSmartynas 	word1(&d) = d1 >> 16 | d1 << 16;
7127b36286aSmartynas #endif
7131a653cbcSmartynas 	return dval(&d);
7147b36286aSmartynas 	}
7157b36286aSmartynas #undef d0
7167b36286aSmartynas #undef d1
7177b36286aSmartynas 
7187b36286aSmartynas  Bigint *
d2b(dd,e,bits)7197b36286aSmartynas d2b
7207b36286aSmartynas #ifdef KR_headers
7211a653cbcSmartynas 	(dd, e, bits) double dd; int *e, *bits;
7227b36286aSmartynas #else
7231a653cbcSmartynas 	(double dd, int *e, int *bits)
7247b36286aSmartynas #endif
7257b36286aSmartynas {
7267b36286aSmartynas 	Bigint *b;
7271a653cbcSmartynas 	U d;
7287b36286aSmartynas #ifndef Sudden_Underflow
7297b36286aSmartynas 	int i;
7307b36286aSmartynas #endif
7317b36286aSmartynas 	int de, k;
7327b36286aSmartynas 	ULong *x, y, z;
7337b36286aSmartynas #ifdef VAX
7347b36286aSmartynas 	ULong d0, d1;
7357b36286aSmartynas #else
7361a653cbcSmartynas #define d0 word0(&d)
7371a653cbcSmartynas #define d1 word1(&d)
7381a653cbcSmartynas #endif
7391a653cbcSmartynas 	d.d = dd;
7401a653cbcSmartynas #ifdef VAX
7411a653cbcSmartynas 	d0 = word0(&d) >> 16 | word0(&d) << 16;
7421a653cbcSmartynas 	d1 = word1(&d) >> 16 | word1(&d) << 16;
7437b36286aSmartynas #endif
7447b36286aSmartynas 
7457b36286aSmartynas #ifdef Pack_32
7467b36286aSmartynas 	b = Balloc(1);
7477b36286aSmartynas #else
7487b36286aSmartynas 	b = Balloc(2);
7497b36286aSmartynas #endif
750384cfdc1Smartynas 	if (b == NULL)
751384cfdc1Smartynas 		return (NULL);
7527b36286aSmartynas 	x = b->x;
7537b36286aSmartynas 
7547b36286aSmartynas 	z = d0 & Frac_mask;
7557b36286aSmartynas 	d0 &= 0x7fffffff;	/* clear sign bit, which we ignore */
7567b36286aSmartynas #ifdef Sudden_Underflow
7577b36286aSmartynas 	de = (int)(d0 >> Exp_shift);
7587b36286aSmartynas #ifndef IBM
7597b36286aSmartynas 	z |= Exp_msk11;
7607b36286aSmartynas #endif
7617b36286aSmartynas #else
7627b36286aSmartynas 	if ( (de = (int)(d0 >> Exp_shift)) !=0)
7637b36286aSmartynas 		z |= Exp_msk1;
7647b36286aSmartynas #endif
7657b36286aSmartynas #ifdef Pack_32
7667b36286aSmartynas 	if ( (y = d1) !=0) {
7677b36286aSmartynas 		if ( (k = lo0bits(&y)) !=0) {
7681a653cbcSmartynas 			x[0] = y | z << (32 - k);
7697b36286aSmartynas 			z >>= k;
7707b36286aSmartynas 			}
7717b36286aSmartynas 		else
7727b36286aSmartynas 			x[0] = y;
7737b36286aSmartynas #ifndef Sudden_Underflow
7747b36286aSmartynas 		i =
7757b36286aSmartynas #endif
7767b36286aSmartynas 		     b->wds = (x[1] = z) !=0 ? 2 : 1;
7777b36286aSmartynas 		}
7787b36286aSmartynas 	else {
7797b36286aSmartynas 		k = lo0bits(&z);
7807b36286aSmartynas 		x[0] = z;
7817b36286aSmartynas #ifndef Sudden_Underflow
7827b36286aSmartynas 		i =
7837b36286aSmartynas #endif
7847b36286aSmartynas 		    b->wds = 1;
7857b36286aSmartynas 		k += 32;
7867b36286aSmartynas 		}
7877b36286aSmartynas #else
7887b36286aSmartynas 	if ( (y = d1) !=0) {
7897b36286aSmartynas 		if ( (k = lo0bits(&y)) !=0)
7907b36286aSmartynas 			if (k >= 16) {
7917b36286aSmartynas 				x[0] = y | z << 32 - k & 0xffff;
7927b36286aSmartynas 				x[1] = z >> k - 16 & 0xffff;
7937b36286aSmartynas 				x[2] = z >> k;
7947b36286aSmartynas 				i = 2;
7957b36286aSmartynas 				}
7967b36286aSmartynas 			else {
7977b36286aSmartynas 				x[0] = y & 0xffff;
7987b36286aSmartynas 				x[1] = y >> 16 | z << 16 - k & 0xffff;
7997b36286aSmartynas 				x[2] = z >> k & 0xffff;
8007b36286aSmartynas 				x[3] = z >> k+16;
8017b36286aSmartynas 				i = 3;
8027b36286aSmartynas 				}
8037b36286aSmartynas 		else {
8047b36286aSmartynas 			x[0] = y & 0xffff;
8057b36286aSmartynas 			x[1] = y >> 16;
8067b36286aSmartynas 			x[2] = z & 0xffff;
8077b36286aSmartynas 			x[3] = z >> 16;
8087b36286aSmartynas 			i = 3;
8097b36286aSmartynas 			}
8107b36286aSmartynas 		}
8117b36286aSmartynas 	else {
8127b36286aSmartynas #ifdef DEBUG
8137b36286aSmartynas 		if (!z)
8147b36286aSmartynas 			Bug("Zero passed to d2b");
8157b36286aSmartynas #endif
8167b36286aSmartynas 		k = lo0bits(&z);
8177b36286aSmartynas 		if (k >= 16) {
8187b36286aSmartynas 			x[0] = z;
8197b36286aSmartynas 			i = 0;
8207b36286aSmartynas 			}
8217b36286aSmartynas 		else {
8227b36286aSmartynas 			x[0] = z & 0xffff;
8237b36286aSmartynas 			x[1] = z >> 16;
8247b36286aSmartynas 			i = 1;
8257b36286aSmartynas 			}
8267b36286aSmartynas 		k += 32;
8277b36286aSmartynas 		}
8287b36286aSmartynas 	while(!x[i])
8297b36286aSmartynas 		--i;
8307b36286aSmartynas 	b->wds = i + 1;
8317b36286aSmartynas #endif
8327b36286aSmartynas #ifndef Sudden_Underflow
8337b36286aSmartynas 	if (de) {
8347b36286aSmartynas #endif
8357b36286aSmartynas #ifdef IBM
8367b36286aSmartynas 		*e = (de - Bias - (P-1) << 2) + k;
8371a653cbcSmartynas 		*bits = 4*P + 8 - k - hi0bits(word0(&d) & Frac_mask);
8387b36286aSmartynas #else
8397b36286aSmartynas 		*e = de - Bias - (P-1) + k;
8407b36286aSmartynas 		*bits = P - k;
8417b36286aSmartynas #endif
8427b36286aSmartynas #ifndef Sudden_Underflow
8437b36286aSmartynas 		}
8447b36286aSmartynas 	else {
8457b36286aSmartynas 		*e = de - Bias - (P-1) + 1 + k;
8467b36286aSmartynas #ifdef Pack_32
8477b36286aSmartynas 		*bits = 32*i - hi0bits(x[i-1]);
8487b36286aSmartynas #else
8497b36286aSmartynas 		*bits = (i+2)*16 - hi0bits(x[i]);
8507b36286aSmartynas #endif
8517b36286aSmartynas 		}
8527b36286aSmartynas #endif
8537b36286aSmartynas 	return b;
8547b36286aSmartynas 	}
8557b36286aSmartynas #undef d0
8567b36286aSmartynas #undef d1
8577b36286aSmartynas 
8587b36286aSmartynas  CONST double
8597b36286aSmartynas #ifdef IEEE_Arith
8607b36286aSmartynas bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 };
8617b36286aSmartynas CONST double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, 1e-256
8627b36286aSmartynas 		};
8637b36286aSmartynas #else
8647b36286aSmartynas #ifdef IBM
8657b36286aSmartynas bigtens[] = { 1e16, 1e32, 1e64 };
8667b36286aSmartynas CONST double tinytens[] = { 1e-16, 1e-32, 1e-64 };
8677b36286aSmartynas #else
8687b36286aSmartynas bigtens[] = { 1e16, 1e32 };
8697b36286aSmartynas CONST double tinytens[] = { 1e-16, 1e-32 };
8707b36286aSmartynas #endif
8717b36286aSmartynas #endif
8727b36286aSmartynas 
8737b36286aSmartynas  CONST double
8747b36286aSmartynas tens[] = {
8757b36286aSmartynas 		1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
8767b36286aSmartynas 		1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
8777b36286aSmartynas 		1e20, 1e21, 1e22
8787b36286aSmartynas #ifdef VAX
8797b36286aSmartynas 		, 1e23, 1e24
8807b36286aSmartynas #endif
8817b36286aSmartynas 		};
8827b36286aSmartynas 
883b3b7ef2eSguenther #ifdef NO_STRING_H
884b3b7ef2eSguenther 
8857b36286aSmartynas  char *
8867b36286aSmartynas #ifdef KR_headers
strcp_D2A(a,b)8877b36286aSmartynas strcp_D2A(a, b) char *a; char *b;
8887b36286aSmartynas #else
8897b36286aSmartynas strcp_D2A(char *a, CONST char *b)
8907b36286aSmartynas #endif
8917b36286aSmartynas {
8921a653cbcSmartynas 	while((*a = *b++))
8937b36286aSmartynas 		a++;
8947b36286aSmartynas 	return a;
8957b36286aSmartynas 	}
8967b36286aSmartynas 
8977b36286aSmartynas  Char *
8987b36286aSmartynas #ifdef KR_headers
memcpy_D2A(a,b,len)8997b36286aSmartynas memcpy_D2A(a, b, len) Char *a; Char *b; size_t len;
9007b36286aSmartynas #else
9017b36286aSmartynas memcpy_D2A(void *a1, void *b1, size_t len)
9027b36286aSmartynas #endif
9037b36286aSmartynas {
9041a653cbcSmartynas 	char *a = (char*)a1, *ae = a + len;
9051a653cbcSmartynas 	char *b = (char*)b1, *a0 = a;
9067b36286aSmartynas 	while(a < ae)
9077b36286aSmartynas 		*a++ = *b++;
9087b36286aSmartynas 	return a0;
9097b36286aSmartynas 	}
9107b36286aSmartynas 
9117b36286aSmartynas #endif /* NO_STRING_H */
912