xref: /netbsd-src/lib/libc/gdtoa/misc.c (revision 86bf846403575818a862abc8c9f59ae2028684c5)
1*86bf8464Smlelstv /* $NetBSD: misc.c,v 1.11 2011/11/21 09:46:19 mlelstv Exp $ */
27684d5e0Skleink 
37684d5e0Skleink /****************************************************************
47684d5e0Skleink 
57684d5e0Skleink The author of this software is David M. Gay.
67684d5e0Skleink 
77684d5e0Skleink Copyright (C) 1998, 1999 by Lucent Technologies
87684d5e0Skleink All Rights Reserved
97684d5e0Skleink 
107684d5e0Skleink Permission to use, copy, modify, and distribute this software and
117684d5e0Skleink its documentation for any purpose and without fee is hereby
127684d5e0Skleink granted, provided that the above copyright notice appear in all
137684d5e0Skleink copies and that both that the copyright notice and this
147684d5e0Skleink permission notice and warranty disclaimer appear in supporting
157684d5e0Skleink documentation, and that the name of Lucent or any of its entities
167684d5e0Skleink not be used in advertising or publicity pertaining to
177684d5e0Skleink distribution of the software without specific, written prior
187684d5e0Skleink permission.
197684d5e0Skleink 
207684d5e0Skleink LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
217684d5e0Skleink INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
227684d5e0Skleink IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
237684d5e0Skleink SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
247684d5e0Skleink WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
257684d5e0Skleink IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
267684d5e0Skleink ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
277684d5e0Skleink THIS SOFTWARE.
287684d5e0Skleink 
297684d5e0Skleink ****************************************************************/
307684d5e0Skleink 
317684d5e0Skleink /* Please send bug reports to David M. Gay (dmg at acm dot org,
327684d5e0Skleink  * with " at " changed at "@" and " dot " changed to ".").	*/
337684d5e0Skleink 
347684d5e0Skleink #include "gdtoaimp.h"
357684d5e0Skleink 
367684d5e0Skleink  static Bigint *freelist[Kmax+1];
377684d5e0Skleink #ifndef Omit_Private_Memory
387684d5e0Skleink #ifndef PRIVATE_MEM
397684d5e0Skleink #define PRIVATE_MEM 2304
407684d5e0Skleink #endif
417684d5e0Skleink #define PRIVATE_mem ((PRIVATE_MEM+sizeof(double)-1)/sizeof(double))
427684d5e0Skleink static double private_mem[PRIVATE_mem], *pmem_next = private_mem;
437684d5e0Skleink #endif
447684d5e0Skleink 
457684d5e0Skleink  Bigint *
Balloc(k)467684d5e0Skleink Balloc
477684d5e0Skleink #ifdef KR_headers
48a23ced05Schristos 	(k) int k;
497684d5e0Skleink #else
50a23ced05Schristos 	(int k)
517684d5e0Skleink #endif
527684d5e0Skleink {
537684d5e0Skleink 	int x;
547684d5e0Skleink 	Bigint *rv;
557684d5e0Skleink #ifndef Omit_Private_Memory
5661e56760Schristos 	size_t len;
577684d5e0Skleink #endif
587684d5e0Skleink 
597684d5e0Skleink 	ACQUIRE_DTOA_LOCK(0);
6061e56760Schristos 	/* The k > Kmax case does not need ACQUIRE_DTOA_LOCK(0), */
6161e56760Schristos 	/* but this case seems very unlikely. */
62a23ced05Schristos 	if ((size_t)k <= Kmax && (rv = freelist[k]) !=0) {
637684d5e0Skleink 		freelist[k] = rv->next;
647684d5e0Skleink 		}
657684d5e0Skleink 	else {
66a23ced05Schristos 		x = 1 << k;
677684d5e0Skleink #ifdef Omit_Private_Memory
687684d5e0Skleink 		rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(ULong));
697684d5e0Skleink #else
707684d5e0Skleink 		len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1)
717684d5e0Skleink 			/sizeof(double);
72a23ced05Schristos 		if ((size_t)k <= Kmax && pmem_next - private_mem + len <= PRIVATE_mem) {
73ac898a26Skleink 			rv = (Bigint*)(void *)pmem_next;
747684d5e0Skleink 			pmem_next += len;
757684d5e0Skleink 			}
767684d5e0Skleink 		else
777684d5e0Skleink 			rv = (Bigint*)MALLOC(len*sizeof(double));
787684d5e0Skleink #endif
79*86bf8464Smlelstv 		if (rv == NULL) {
80*86bf8464Smlelstv 			FREE_DTOA_LOCK(0);
81ab625449Schristos 			return NULL;
82*86bf8464Smlelstv 		}
83a23ced05Schristos 		rv->k = k;
847684d5e0Skleink 		rv->maxwds = x;
857684d5e0Skleink 		}
867684d5e0Skleink 	FREE_DTOA_LOCK(0);
877684d5e0Skleink 	rv->sign = rv->wds = 0;
887684d5e0Skleink 	return rv;
897684d5e0Skleink 	}
907684d5e0Skleink 
917684d5e0Skleink  void
Bfree(v)927684d5e0Skleink Bfree
937684d5e0Skleink #ifdef KR_headers
947684d5e0Skleink 	(v) Bigint *v;
957684d5e0Skleink #else
967684d5e0Skleink 	(Bigint *v)
977684d5e0Skleink #endif
987684d5e0Skleink {
997684d5e0Skleink 	if (v) {
10061e56760Schristos 		if ((size_t)v->k > Kmax)
10161e56760Schristos #ifdef FREE
10261e56760Schristos 			FREE((void*)v);
10361e56760Schristos #else
10461e56760Schristos 			free((void*)v);
10561e56760Schristos #endif
10661e56760Schristos 		else {
1077684d5e0Skleink 			ACQUIRE_DTOA_LOCK(0);
1087684d5e0Skleink 			v->next = freelist[v->k];
1097684d5e0Skleink 			freelist[v->k] = v;
1107684d5e0Skleink 			FREE_DTOA_LOCK(0);
1117684d5e0Skleink 			}
1127684d5e0Skleink 		}
11361e56760Schristos 	}
1147684d5e0Skleink 
1157684d5e0Skleink  int
lo0bits(y)1167684d5e0Skleink lo0bits
1177684d5e0Skleink #ifdef KR_headers
1187684d5e0Skleink 	(y) ULong *y;
1197684d5e0Skleink #else
1207684d5e0Skleink 	(ULong *y)
1217684d5e0Skleink #endif
1227684d5e0Skleink {
123ac898a26Skleink 	int k;
124ac898a26Skleink 	ULong x = *y;
1257684d5e0Skleink 
1267684d5e0Skleink 	if (x & 7) {
1277684d5e0Skleink 		if (x & 1)
1287684d5e0Skleink 			return 0;
1297684d5e0Skleink 		if (x & 2) {
1307684d5e0Skleink 			*y = x >> 1;
1317684d5e0Skleink 			return 1;
1327684d5e0Skleink 			}
1337684d5e0Skleink 		*y = x >> 2;
1347684d5e0Skleink 		return 2;
1357684d5e0Skleink 		}
1367684d5e0Skleink 	k = 0;
1377684d5e0Skleink 	if (!(x & 0xffff)) {
1387684d5e0Skleink 		k = 16;
1397684d5e0Skleink 		x >>= 16;
1407684d5e0Skleink 		}
1417684d5e0Skleink 	if (!(x & 0xff)) {
1427684d5e0Skleink 		k += 8;
1437684d5e0Skleink 		x >>= 8;
1447684d5e0Skleink 		}
1457684d5e0Skleink 	if (!(x & 0xf)) {
1467684d5e0Skleink 		k += 4;
1477684d5e0Skleink 		x >>= 4;
1487684d5e0Skleink 		}
1497684d5e0Skleink 	if (!(x & 0x3)) {
1507684d5e0Skleink 		k += 2;
1517684d5e0Skleink 		x >>= 2;
1527684d5e0Skleink 		}
1537684d5e0Skleink 	if (!(x & 1)) {
1547684d5e0Skleink 		k++;
1557684d5e0Skleink 		x >>= 1;
1567684d5e0Skleink 		if (!x)
1577684d5e0Skleink 			return 32;
1587684d5e0Skleink 		}
1597684d5e0Skleink 	*y = x;
1607684d5e0Skleink 	return k;
1617684d5e0Skleink 	}
1627684d5e0Skleink 
1637684d5e0Skleink  Bigint *
multadd(b,m,a)1647684d5e0Skleink multadd
1657684d5e0Skleink #ifdef KR_headers
1667684d5e0Skleink 	(b, m, a) Bigint *b; int m, a;
1677684d5e0Skleink #else
1687684d5e0Skleink 	(Bigint *b, int m, int a)	/* multiply by m and add a */
1697684d5e0Skleink #endif
1707684d5e0Skleink {
1717684d5e0Skleink 	int i, wds;
1727684d5e0Skleink #ifdef ULLong
1737684d5e0Skleink 	ULong *x;
1747684d5e0Skleink 	ULLong carry, y;
1757684d5e0Skleink #else
1767684d5e0Skleink 	ULong carry, *x, y;
1777684d5e0Skleink #ifdef Pack_32
1787684d5e0Skleink 	ULong xi, z;
1797684d5e0Skleink #endif
1807684d5e0Skleink #endif
1817684d5e0Skleink 	Bigint *b1;
1827684d5e0Skleink 
1837684d5e0Skleink 	wds = b->wds;
1847684d5e0Skleink 	x = b->x;
1857684d5e0Skleink 	i = 0;
1867684d5e0Skleink 	carry = a;
1877684d5e0Skleink 	do {
1887684d5e0Skleink #ifdef ULLong
1897684d5e0Skleink 		y = *x * (ULLong)m + carry;
1907684d5e0Skleink 		carry = y >> 32;
191ac898a26Skleink 		/* LINTED conversion */
1927684d5e0Skleink 		*x++ = y & 0xffffffffUL;
1937684d5e0Skleink #else
1947684d5e0Skleink #ifdef Pack_32
1957684d5e0Skleink 		xi = *x;
1967684d5e0Skleink 		y = (xi & 0xffff) * m + carry;
1977684d5e0Skleink 		z = (xi >> 16) * m + (y >> 16);
1987684d5e0Skleink 		carry = z >> 16;
1997684d5e0Skleink 		*x++ = (z << 16) + (y & 0xffff);
2007684d5e0Skleink #else
2017684d5e0Skleink 		y = *x * m + carry;
2027684d5e0Skleink 		carry = y >> 16;
2037684d5e0Skleink 		*x++ = y & 0xffff;
2047684d5e0Skleink #endif
2057684d5e0Skleink #endif
2067684d5e0Skleink 		}
2077684d5e0Skleink 		while(++i < wds);
2087684d5e0Skleink 	if (carry) {
2097684d5e0Skleink 		if (wds >= b->maxwds) {
2107684d5e0Skleink 			b1 = Balloc(b->k+1);
211ab625449Schristos 			if (b1 == NULL) {
212ab625449Schristos 				Bfree(b);
213ab625449Schristos 				return NULL;
214ab625449Schristos 				}
2157684d5e0Skleink 			Bcopy(b1, b);
2167684d5e0Skleink 			Bfree(b);
2177684d5e0Skleink 			b = b1;
2187684d5e0Skleink 			}
219ac898a26Skleink 		/* LINTED conversion */
2207684d5e0Skleink 		b->x[wds++] = carry;
2217684d5e0Skleink 		b->wds = wds;
2227684d5e0Skleink 		}
2237684d5e0Skleink 	return b;
2247684d5e0Skleink 	}
2257684d5e0Skleink 
2267684d5e0Skleink  int
hi0bits_D2A(x)2277684d5e0Skleink hi0bits_D2A
2287684d5e0Skleink #ifdef KR_headers
229ac898a26Skleink 	(x) ULong x;
2307684d5e0Skleink #else
231ac898a26Skleink 	(ULong x)
2327684d5e0Skleink #endif
2337684d5e0Skleink {
234ac898a26Skleink 	int k = 0;
2357684d5e0Skleink 
2367684d5e0Skleink 	if (!(x & 0xffff0000)) {
2377684d5e0Skleink 		k = 16;
2387684d5e0Skleink 		x <<= 16;
2397684d5e0Skleink 		}
2407684d5e0Skleink 	if (!(x & 0xff000000)) {
2417684d5e0Skleink 		k += 8;
2427684d5e0Skleink 		x <<= 8;
2437684d5e0Skleink 		}
2447684d5e0Skleink 	if (!(x & 0xf0000000)) {
2457684d5e0Skleink 		k += 4;
2467684d5e0Skleink 		x <<= 4;
2477684d5e0Skleink 		}
2487684d5e0Skleink 	if (!(x & 0xc0000000)) {
2497684d5e0Skleink 		k += 2;
2507684d5e0Skleink 		x <<= 2;
2517684d5e0Skleink 		}
2527684d5e0Skleink 	if (!(x & 0x80000000)) {
2537684d5e0Skleink 		k++;
2547684d5e0Skleink 		if (!(x & 0x40000000))
2557684d5e0Skleink 			return 32;
2567684d5e0Skleink 		}
2577684d5e0Skleink 	return k;
2587684d5e0Skleink 	}
2597684d5e0Skleink 
2607684d5e0Skleink  Bigint *
i2b(i)2617684d5e0Skleink i2b
2627684d5e0Skleink #ifdef KR_headers
2637684d5e0Skleink 	(i) int i;
2647684d5e0Skleink #else
2657684d5e0Skleink 	(int i)
2667684d5e0Skleink #endif
2677684d5e0Skleink {
2687684d5e0Skleink 	Bigint *b;
2697684d5e0Skleink 
2707684d5e0Skleink 	b = Balloc(1);
271ab625449Schristos 	if (b == NULL)
272ab625449Schristos 		return NULL;
2737684d5e0Skleink 	b->x[0] = i;
2747684d5e0Skleink 	b->wds = 1;
2757684d5e0Skleink 	return b;
2767684d5e0Skleink 	}
2777684d5e0Skleink 
2787684d5e0Skleink  Bigint *
mult(a,b)2797684d5e0Skleink mult
2807684d5e0Skleink #ifdef KR_headers
2817684d5e0Skleink 	(a, b) Bigint *a, *b;
2827684d5e0Skleink #else
2837684d5e0Skleink 	(Bigint *a, Bigint *b)
2847684d5e0Skleink #endif
2857684d5e0Skleink {
2867684d5e0Skleink 	Bigint *c;
2877684d5e0Skleink 	int k, wa, wb, wc;
2887684d5e0Skleink 	ULong *x, *xa, *xae, *xb, *xbe, *xc, *xc0;
2897684d5e0Skleink 	ULong y;
2907684d5e0Skleink #ifdef ULLong
2917684d5e0Skleink 	ULLong carry, z;
2927684d5e0Skleink #else
2937684d5e0Skleink 	ULong carry, z;
2947684d5e0Skleink #ifdef Pack_32
2957684d5e0Skleink 	ULong z2;
2967684d5e0Skleink #endif
2977684d5e0Skleink #endif
2987684d5e0Skleink 
2997684d5e0Skleink 	if (a->wds < b->wds) {
3007684d5e0Skleink 		c = a;
3017684d5e0Skleink 		a = b;
3027684d5e0Skleink 		b = c;
3037684d5e0Skleink 		}
3047684d5e0Skleink 	k = a->k;
3057684d5e0Skleink 	wa = a->wds;
3067684d5e0Skleink 	wb = b->wds;
3077684d5e0Skleink 	wc = wa + wb;
3087684d5e0Skleink 	if (wc > a->maxwds)
3097684d5e0Skleink 		k++;
3107684d5e0Skleink 	c = Balloc(k);
311ab625449Schristos 	if (c == NULL)
312ab625449Schristos 		return NULL;
3137684d5e0Skleink 	for(x = c->x, xa = x + wc; x < xa; x++)
3147684d5e0Skleink 		*x = 0;
3157684d5e0Skleink 	xa = a->x;
3167684d5e0Skleink 	xae = xa + wa;
3177684d5e0Skleink 	xb = b->x;
3187684d5e0Skleink 	xbe = xb + wb;
3197684d5e0Skleink 	xc0 = c->x;
3207684d5e0Skleink #ifdef ULLong
3217684d5e0Skleink 	for(; xb < xbe; xc0++) {
3227684d5e0Skleink 		if ( (y = *xb++) !=0) {
3237684d5e0Skleink 			x = xa;
3247684d5e0Skleink 			xc = xc0;
3257684d5e0Skleink 			carry = 0;
3267684d5e0Skleink 			do {
3277684d5e0Skleink 				z = *x++ * (ULLong)y + *xc + carry;
3287684d5e0Skleink 				carry = z >> 32;
329ac898a26Skleink 				/* LINTED conversion */
3307684d5e0Skleink 				*xc++ = z & 0xffffffffUL;
3317684d5e0Skleink 				}
3327684d5e0Skleink 				while(x < xae);
333ac898a26Skleink 			/* LINTED conversion */
3347684d5e0Skleink 			*xc = carry;
3357684d5e0Skleink 			}
3367684d5e0Skleink 		}
3377684d5e0Skleink #else
3387684d5e0Skleink #ifdef Pack_32
3397684d5e0Skleink 	for(; xb < xbe; xb++, xc0++) {
3407684d5e0Skleink 		if ( (y = *xb & 0xffff) !=0) {
3417684d5e0Skleink 			x = xa;
3427684d5e0Skleink 			xc = xc0;
3437684d5e0Skleink 			carry = 0;
3447684d5e0Skleink 			do {
3457684d5e0Skleink 				z = (*x & 0xffff) * y + (*xc & 0xffff) + carry;
3467684d5e0Skleink 				carry = z >> 16;
3477684d5e0Skleink 				z2 = (*x++ >> 16) * y + (*xc >> 16) + carry;
3487684d5e0Skleink 				carry = z2 >> 16;
3497684d5e0Skleink 				Storeinc(xc, z2, z);
3507684d5e0Skleink 				}
3517684d5e0Skleink 				while(x < xae);
3527684d5e0Skleink 			*xc = carry;
3537684d5e0Skleink 			}
3547684d5e0Skleink 		if ( (y = *xb >> 16) !=0) {
3557684d5e0Skleink 			x = xa;
3567684d5e0Skleink 			xc = xc0;
3577684d5e0Skleink 			carry = 0;
3587684d5e0Skleink 			z2 = *xc;
3597684d5e0Skleink 			do {
3607684d5e0Skleink 				z = (*x & 0xffff) * y + (*xc >> 16) + carry;
3617684d5e0Skleink 				carry = z >> 16;
3627684d5e0Skleink 				Storeinc(xc, z, z2);
3637684d5e0Skleink 				z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry;
3647684d5e0Skleink 				carry = z2 >> 16;
3657684d5e0Skleink 				}
3667684d5e0Skleink 				while(x < xae);
3677684d5e0Skleink 			*xc = z2;
3687684d5e0Skleink 			}
3697684d5e0Skleink 		}
3707684d5e0Skleink #else
3717684d5e0Skleink 	for(; xb < xbe; xc0++) {
3727684d5e0Skleink 		if ( (y = *xb++) !=0) {
3737684d5e0Skleink 			x = xa;
3747684d5e0Skleink 			xc = xc0;
3757684d5e0Skleink 			carry = 0;
3767684d5e0Skleink 			do {
3777684d5e0Skleink 				z = *x++ * y + *xc + carry;
3787684d5e0Skleink 				carry = z >> 16;
3797684d5e0Skleink 				*xc++ = z & 0xffff;
3807684d5e0Skleink 				}
3817684d5e0Skleink 				while(x < xae);
3827684d5e0Skleink 			*xc = carry;
3837684d5e0Skleink 			}
3847684d5e0Skleink 		}
3857684d5e0Skleink #endif
3867684d5e0Skleink #endif
3877684d5e0Skleink 	for(xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ;
3887684d5e0Skleink 	c->wds = wc;
3897684d5e0Skleink 	return c;
3907684d5e0Skleink 	}
3917684d5e0Skleink 
3927684d5e0Skleink  static Bigint *p5s;
3937684d5e0Skleink 
3947684d5e0Skleink  Bigint *
pow5mult(b,k)3957684d5e0Skleink pow5mult
3967684d5e0Skleink #ifdef KR_headers
3977684d5e0Skleink 	(b, k) Bigint *b; int k;
3987684d5e0Skleink #else
3997684d5e0Skleink 	(Bigint *b, int k)
4007684d5e0Skleink #endif
4017684d5e0Skleink {
4027684d5e0Skleink 	Bigint *b1, *p5, *p51;
4037684d5e0Skleink 	int i;
404b24124a7Schristos 	static CONST int p05[3] = { 5, 25, 125 };
4057684d5e0Skleink 
406ab625449Schristos 	if ( (i = k & 3) !=0) {
4077684d5e0Skleink 		b = multadd(b, p05[i-1], 0);
408ab625449Schristos 		if (b == NULL)
409ab625449Schristos 			return NULL;
410ab625449Schristos 		}
4117684d5e0Skleink 
412ac898a26Skleink 	if (!(k = (unsigned int)k >> 2))
4137684d5e0Skleink 		return b;
4147684d5e0Skleink 	if ((p5 = p5s) == 0) {
4157684d5e0Skleink 		/* first time */
4167684d5e0Skleink #ifdef MULTIPLE_THREADS
4177684d5e0Skleink 		ACQUIRE_DTOA_LOCK(1);
4187684d5e0Skleink 		if (!(p5 = p5s)) {
4197684d5e0Skleink 			p5 = p5s = i2b(625);
420b2707ef3Schristos 			if (p5 == NULL) {
421b2707ef3Schristos 				FREE_DTOA_LOCK(1);
422ab625449Schristos 				return NULL;
423b2707ef3Schristos 			}
4247684d5e0Skleink 			p5->next = 0;
4257684d5e0Skleink 			}
4267684d5e0Skleink 		FREE_DTOA_LOCK(1);
4277684d5e0Skleink #else
4287684d5e0Skleink 		p5 = p5s = i2b(625);
429ab625449Schristos 		if (p5 == NULL)
430ab625449Schristos 			return NULL;
4317684d5e0Skleink 		p5->next = 0;
4327684d5e0Skleink #endif
4337684d5e0Skleink 		}
4347684d5e0Skleink 	for(;;) {
4357684d5e0Skleink 		if (k & 1) {
4367684d5e0Skleink 			b1 = mult(b, p5);
437ab625449Schristos 			if (b1 == NULL)
438ab625449Schristos 				return NULL;
439f0c33b33Schristos 			Bfree(b);
4407684d5e0Skleink 			b = b1;
4417684d5e0Skleink 			}
442ac898a26Skleink 		if (!(k = (unsigned int)k >> 1))
4437684d5e0Skleink 			break;
4447684d5e0Skleink 		if ((p51 = p5->next) == 0) {
4457684d5e0Skleink #ifdef MULTIPLE_THREADS
4467684d5e0Skleink 			ACQUIRE_DTOA_LOCK(1);
4477684d5e0Skleink 			if (!(p51 = p5->next)) {
4487684d5e0Skleink 				p51 = p5->next = mult(p5,p5);
44934407547Smartin 				if (p51 == NULL) {
45034407547Smartin 					FREE_DTOA_LOCK(1);
451ab625449Schristos 					return NULL;
45234407547Smartin 				}
4537684d5e0Skleink 				p51->next = 0;
4547684d5e0Skleink 				}
4557684d5e0Skleink 			FREE_DTOA_LOCK(1);
4567684d5e0Skleink #else
4577684d5e0Skleink 			p51 = p5->next = mult(p5,p5);
458ab625449Schristos 			if (p51 == NULL)
459ab625449Schristos 				return NULL;
4607684d5e0Skleink 			p51->next = 0;
4617684d5e0Skleink #endif
4627684d5e0Skleink 			}
4637684d5e0Skleink 		p5 = p51;
4647684d5e0Skleink 		}
4657684d5e0Skleink 	return b;
4667684d5e0Skleink 	}
4677684d5e0Skleink 
4687684d5e0Skleink  Bigint *
lshift(b,k)4697684d5e0Skleink lshift
4707684d5e0Skleink #ifdef KR_headers
4717684d5e0Skleink 	(b, k) Bigint *b; int k;
4727684d5e0Skleink #else
4737684d5e0Skleink 	(Bigint *b, int k)
4747684d5e0Skleink #endif
4757684d5e0Skleink {
4767684d5e0Skleink 	int i, k1, n, n1;
4777684d5e0Skleink 	Bigint *b1;
4787684d5e0Skleink 	ULong *x, *x1, *xe, z;
4797684d5e0Skleink 
480ac898a26Skleink 	n = (unsigned int)k >> kshift;
4817684d5e0Skleink 	k1 = b->k;
4827684d5e0Skleink 	n1 = n + b->wds + 1;
4837684d5e0Skleink 	for(i = b->maxwds; n1 > i; i <<= 1)
4847684d5e0Skleink 		k1++;
4857684d5e0Skleink 	b1 = Balloc(k1);
486ab625449Schristos 	if (b1 == NULL)
487ab625449Schristos 		return NULL;
4887684d5e0Skleink 	x1 = b1->x;
4897684d5e0Skleink 	for(i = 0; i < n; i++)
4907684d5e0Skleink 		*x1++ = 0;
4917684d5e0Skleink 	x = b->x;
4927684d5e0Skleink 	xe = x + b->wds;
4937684d5e0Skleink 	if (k &= kmask) {
4947684d5e0Skleink #ifdef Pack_32
4957684d5e0Skleink 		k1 = 32 - k;
4967684d5e0Skleink 		z = 0;
4977684d5e0Skleink 		do {
4987684d5e0Skleink 			*x1++ = *x << k | z;
4997684d5e0Skleink 			z = *x++ >> k1;
5007684d5e0Skleink 			}
5017684d5e0Skleink 			while(x < xe);
5027684d5e0Skleink 		if ((*x1 = z) !=0)
5037684d5e0Skleink 			++n1;
5047684d5e0Skleink #else
5057684d5e0Skleink 		k1 = 16 - k;
5067684d5e0Skleink 		z = 0;
5077684d5e0Skleink 		do {
5087684d5e0Skleink 			*x1++ = *x << k  & 0xffff | z;
5097684d5e0Skleink 			z = *x++ >> k1;
5107684d5e0Skleink 			}
5117684d5e0Skleink 			while(x < xe);
5127684d5e0Skleink 		if (*x1 = z)
5137684d5e0Skleink 			++n1;
5147684d5e0Skleink #endif
5157684d5e0Skleink 		}
5167684d5e0Skleink 	else do
5177684d5e0Skleink 		*x1++ = *x++;
5187684d5e0Skleink 		while(x < xe);
5197684d5e0Skleink 	b1->wds = n1 - 1;
5207684d5e0Skleink 	Bfree(b);
5217684d5e0Skleink 	return b1;
5227684d5e0Skleink 	}
5237684d5e0Skleink 
5247684d5e0Skleink  int
cmp(a,b)5257684d5e0Skleink cmp
5267684d5e0Skleink #ifdef KR_headers
5277684d5e0Skleink 	(a, b) Bigint *a, *b;
5287684d5e0Skleink #else
5297684d5e0Skleink 	(Bigint *a, Bigint *b)
5307684d5e0Skleink #endif
5317684d5e0Skleink {
5327684d5e0Skleink 	ULong *xa, *xa0, *xb, *xb0;
5337684d5e0Skleink 	int i, j;
5347684d5e0Skleink 
5357684d5e0Skleink 	i = a->wds;
5367684d5e0Skleink 	j = b->wds;
5377684d5e0Skleink #ifdef DEBUG
5387684d5e0Skleink 	if (i > 1 && !a->x[i-1])
5397684d5e0Skleink 		Bug("cmp called with a->x[a->wds-1] == 0");
5407684d5e0Skleink 	if (j > 1 && !b->x[j-1])
5417684d5e0Skleink 		Bug("cmp called with b->x[b->wds-1] == 0");
5427684d5e0Skleink #endif
5437684d5e0Skleink 	if (i -= j)
5447684d5e0Skleink 		return i;
5457684d5e0Skleink 	xa0 = a->x;
5467684d5e0Skleink 	xa = xa0 + j;
5477684d5e0Skleink 	xb0 = b->x;
5487684d5e0Skleink 	xb = xb0 + j;
5497684d5e0Skleink 	for(;;) {
5507684d5e0Skleink 		if (*--xa != *--xb)
5517684d5e0Skleink 			return *xa < *xb ? -1 : 1;
5527684d5e0Skleink 		if (xa <= xa0)
5537684d5e0Skleink 			break;
5547684d5e0Skleink 		}
5557684d5e0Skleink 	return 0;
5567684d5e0Skleink 	}
5577684d5e0Skleink 
5587684d5e0Skleink  Bigint *
diff(a,b)5597684d5e0Skleink diff
5607684d5e0Skleink #ifdef KR_headers
5617684d5e0Skleink 	(a, b) Bigint *a, *b;
5627684d5e0Skleink #else
5637684d5e0Skleink 	(Bigint *a, Bigint *b)
5647684d5e0Skleink #endif
5657684d5e0Skleink {
5667684d5e0Skleink 	Bigint *c;
5677684d5e0Skleink 	int i, wa, wb;
5687684d5e0Skleink 	ULong *xa, *xae, *xb, *xbe, *xc;
5697684d5e0Skleink #ifdef ULLong
5707684d5e0Skleink 	ULLong borrow, y;
5717684d5e0Skleink #else
5727684d5e0Skleink 	ULong borrow, y;
5737684d5e0Skleink #ifdef Pack_32
5747684d5e0Skleink 	ULong z;
5757684d5e0Skleink #endif
5767684d5e0Skleink #endif
5777684d5e0Skleink 
5787684d5e0Skleink 	i = cmp(a,b);
5797684d5e0Skleink 	if (!i) {
5807684d5e0Skleink 		c = Balloc(0);
581ab625449Schristos 		if (c == NULL)
582ab625449Schristos 			return NULL;
5837684d5e0Skleink 		c->wds = 1;
5847684d5e0Skleink 		c->x[0] = 0;
5857684d5e0Skleink 		return c;
5867684d5e0Skleink 		}
5877684d5e0Skleink 	if (i < 0) {
5887684d5e0Skleink 		c = a;
5897684d5e0Skleink 		a = b;
5907684d5e0Skleink 		b = c;
5917684d5e0Skleink 		i = 1;
5927684d5e0Skleink 		}
5937684d5e0Skleink 	else
5947684d5e0Skleink 		i = 0;
5957684d5e0Skleink 	c = Balloc(a->k);
596ab625449Schristos 	if (c == NULL)
597ab625449Schristos 		return NULL;
5987684d5e0Skleink 	c->sign = i;
5997684d5e0Skleink 	wa = a->wds;
6007684d5e0Skleink 	xa = a->x;
6017684d5e0Skleink 	xae = xa + wa;
6027684d5e0Skleink 	wb = b->wds;
6037684d5e0Skleink 	xb = b->x;
6047684d5e0Skleink 	xbe = xb + wb;
6057684d5e0Skleink 	xc = c->x;
6067684d5e0Skleink 	borrow = 0;
6077684d5e0Skleink #ifdef ULLong
6087684d5e0Skleink 	do {
6097684d5e0Skleink 		y = (ULLong)*xa++ - *xb++ - borrow;
6107684d5e0Skleink 		borrow = y >> 32 & 1UL;
611ac898a26Skleink 		/* LINTED conversion */
6127684d5e0Skleink 		*xc++ = y & 0xffffffffUL;
6137684d5e0Skleink 		}
6147684d5e0Skleink 		while(xb < xbe);
6157684d5e0Skleink 	while(xa < xae) {
6167684d5e0Skleink 		y = *xa++ - borrow;
6177684d5e0Skleink 		borrow = y >> 32 & 1UL;
618ac898a26Skleink 		/* LINTED conversion */
6197684d5e0Skleink 		*xc++ = y & 0xffffffffUL;
6207684d5e0Skleink 		}
6217684d5e0Skleink #else
6227684d5e0Skleink #ifdef Pack_32
6237684d5e0Skleink 	do {
6247684d5e0Skleink 		y = (*xa & 0xffff) - (*xb & 0xffff) - borrow;
6257684d5e0Skleink 		borrow = (y & 0x10000) >> 16;
6267684d5e0Skleink 		z = (*xa++ >> 16) - (*xb++ >> 16) - borrow;
6277684d5e0Skleink 		borrow = (z & 0x10000) >> 16;
6287684d5e0Skleink 		Storeinc(xc, z, y);
6297684d5e0Skleink 		}
6307684d5e0Skleink 		while(xb < xbe);
6317684d5e0Skleink 	while(xa < xae) {
6327684d5e0Skleink 		y = (*xa & 0xffff) - borrow;
6337684d5e0Skleink 		borrow = (y & 0x10000) >> 16;
6347684d5e0Skleink 		z = (*xa++ >> 16) - borrow;
6357684d5e0Skleink 		borrow = (z & 0x10000) >> 16;
6367684d5e0Skleink 		Storeinc(xc, z, y);
6377684d5e0Skleink 		}
6387684d5e0Skleink #else
6397684d5e0Skleink 	do {
6407684d5e0Skleink 		y = *xa++ - *xb++ - borrow;
6417684d5e0Skleink 		borrow = (y & 0x10000) >> 16;
6427684d5e0Skleink 		*xc++ = y & 0xffff;
6437684d5e0Skleink 		}
6447684d5e0Skleink 		while(xb < xbe);
6457684d5e0Skleink 	while(xa < xae) {
6467684d5e0Skleink 		y = *xa++ - borrow;
6477684d5e0Skleink 		borrow = (y & 0x10000) >> 16;
6487684d5e0Skleink 		*xc++ = y & 0xffff;
6497684d5e0Skleink 		}
6507684d5e0Skleink #endif
6517684d5e0Skleink #endif
6527684d5e0Skleink 	while(!*--xc)
6537684d5e0Skleink 		wa--;
6547684d5e0Skleink 	c->wds = wa;
6557684d5e0Skleink 	return c;
6567684d5e0Skleink 	}
6577684d5e0Skleink 
6587684d5e0Skleink  double
b2d(a,e)6597684d5e0Skleink b2d
6607684d5e0Skleink #ifdef KR_headers
6617684d5e0Skleink 	(a, e) Bigint *a; int *e;
6627684d5e0Skleink #else
6637684d5e0Skleink 	(Bigint *a, int *e)
6647684d5e0Skleink #endif
6657684d5e0Skleink {
6667684d5e0Skleink 	ULong *xa, *xa0, w, y, z;
6677684d5e0Skleink 	int k;
66861e56760Schristos 	U d;
6697684d5e0Skleink #ifdef VAX
6707684d5e0Skleink 	ULong d0, d1;
6717684d5e0Skleink #else
67261e56760Schristos #define d0 word0(&d)
67361e56760Schristos #define d1 word1(&d)
6747684d5e0Skleink #endif
6757684d5e0Skleink 
6767684d5e0Skleink 	xa0 = a->x;
6777684d5e0Skleink 	xa = xa0 + a->wds;
6787684d5e0Skleink 	y = *--xa;
6797684d5e0Skleink #ifdef DEBUG
6807684d5e0Skleink 	if (!y) Bug("zero y in b2d");
6817684d5e0Skleink #endif
6827684d5e0Skleink 	k = hi0bits(y);
6837684d5e0Skleink 	*e = 32 - k;
6847684d5e0Skleink #ifdef Pack_32
6857684d5e0Skleink 	if (k < Ebits) {
686ac898a26Skleink 		d0 = Exp_1 | y >> (Ebits - k);
6877684d5e0Skleink 		w = xa > xa0 ? *--xa : 0;
688ac898a26Skleink 		d1 = y << ((32-Ebits) + k) | w >> (Ebits - k);
6897684d5e0Skleink 		goto ret_d;
6907684d5e0Skleink 		}
6917684d5e0Skleink 	z = xa > xa0 ? *--xa : 0;
6927684d5e0Skleink 	if (k -= Ebits) {
693ac898a26Skleink 		d0 = Exp_1 | y << k | z >> (32 - k);
6947684d5e0Skleink 		y = xa > xa0 ? *--xa : 0;
695ac898a26Skleink 		d1 = z << k | y >> (32 - k);
6967684d5e0Skleink 		}
6977684d5e0Skleink 	else {
6987684d5e0Skleink 		d0 = Exp_1 | y;
6997684d5e0Skleink 		d1 = z;
7007684d5e0Skleink 		}
7017684d5e0Skleink #else
7027684d5e0Skleink 	if (k < Ebits + 16) {
7037684d5e0Skleink 		z = xa > xa0 ? *--xa : 0;
7047684d5e0Skleink 		d0 = Exp_1 | y << k - Ebits | z >> Ebits + 16 - k;
7057684d5e0Skleink 		w = xa > xa0 ? *--xa : 0;
7067684d5e0Skleink 		y = xa > xa0 ? *--xa : 0;
7077684d5e0Skleink 		d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k;
7087684d5e0Skleink 		goto ret_d;
7097684d5e0Skleink 		}
7107684d5e0Skleink 	z = xa > xa0 ? *--xa : 0;
7117684d5e0Skleink 	w = xa > xa0 ? *--xa : 0;
7127684d5e0Skleink 	k -= Ebits + 16;
7137684d5e0Skleink 	d0 = Exp_1 | y << k + 16 | z << k | w >> 16 - k;
7147684d5e0Skleink 	y = xa > xa0 ? *--xa : 0;
7157684d5e0Skleink 	d1 = w << k + 16 | y << k;
7167684d5e0Skleink #endif
7177684d5e0Skleink  ret_d:
7187684d5e0Skleink #ifdef VAX
71961e56760Schristos 	word0(&d) = d0 >> 16 | d0 << 16;
72061e56760Schristos 	word1(&d) = d1 >> 16 | d1 << 16;
7217684d5e0Skleink #endif
72261e56760Schristos 	return dval(&d);
7237684d5e0Skleink 	}
7247684d5e0Skleink #undef d0
7257684d5e0Skleink #undef d1
7267684d5e0Skleink 
7277684d5e0Skleink  Bigint *
d2b(dd,e,bits)7287684d5e0Skleink d2b
7297684d5e0Skleink #ifdef KR_headers
73061e56760Schristos 	(dd, e, bits) double dd; int *e, *bits;
7317684d5e0Skleink #else
73261e56760Schristos 	(double dd, int *e, int *bits)
7337684d5e0Skleink #endif
7347684d5e0Skleink {
7357684d5e0Skleink 	Bigint *b;
73661e56760Schristos 	U d;
7377684d5e0Skleink #ifndef Sudden_Underflow
7387684d5e0Skleink 	int i;
7397684d5e0Skleink #endif
7407684d5e0Skleink 	int de, k;
7417684d5e0Skleink 	ULong *x, y, z;
7427684d5e0Skleink #ifdef VAX
7437684d5e0Skleink 	ULong d0, d1;
7447684d5e0Skleink #else
74561e56760Schristos #define d0 word0(&d)
74661e56760Schristos #define d1 word1(&d)
74761e56760Schristos #endif
74861e56760Schristos 	d.d = dd;
74961e56760Schristos #ifdef VAX
75061e56760Schristos 	d0 = word0(&d) >> 16 | word0(&d) << 16;
75161e56760Schristos 	d1 = word1(&d) >> 16 | word1(&d) << 16;
7527684d5e0Skleink #endif
7537684d5e0Skleink 
7547684d5e0Skleink #ifdef Pack_32
7557684d5e0Skleink 	b = Balloc(1);
7567684d5e0Skleink #else
7577684d5e0Skleink 	b = Balloc(2);
7587684d5e0Skleink #endif
759ab625449Schristos 	if (b == NULL)
760ab625449Schristos 		return NULL;
7617684d5e0Skleink 	x = b->x;
7627684d5e0Skleink 
7637684d5e0Skleink 	z = d0 & Frac_mask;
7647684d5e0Skleink 	d0 &= 0x7fffffff;	/* clear sign bit, which we ignore */
7657684d5e0Skleink #ifdef Sudden_Underflow
7667684d5e0Skleink 	de = (int)(d0 >> Exp_shift);
7677684d5e0Skleink #ifndef IBM
7687684d5e0Skleink 	z |= Exp_msk11;
7697684d5e0Skleink #endif
7707684d5e0Skleink #else
7717684d5e0Skleink 	if ( (de = (int)(d0 >> Exp_shift)) !=0)
7727684d5e0Skleink 		z |= Exp_msk1;
7737684d5e0Skleink #endif
7747684d5e0Skleink #ifdef Pack_32
7757684d5e0Skleink 	if ( (y = d1) !=0) {
7767684d5e0Skleink 		if ( (k = lo0bits(&y)) !=0) {
777ac898a26Skleink 			x[0] = y | z << (32 - k);
7787684d5e0Skleink 			z >>= k;
7797684d5e0Skleink 			}
7807684d5e0Skleink 		else
7817684d5e0Skleink 			x[0] = y;
7827684d5e0Skleink #ifndef Sudden_Underflow
7837684d5e0Skleink 		i =
7847684d5e0Skleink #endif
7857684d5e0Skleink 		     b->wds = (x[1] = z) !=0 ? 2 : 1;
7867684d5e0Skleink 		}
7877684d5e0Skleink 	else {
7887684d5e0Skleink 		k = lo0bits(&z);
7897684d5e0Skleink 		x[0] = z;
7907684d5e0Skleink #ifndef Sudden_Underflow
7917684d5e0Skleink 		i =
7927684d5e0Skleink #endif
7937684d5e0Skleink 		    b->wds = 1;
7947684d5e0Skleink 		k += 32;
7957684d5e0Skleink 		}
7967684d5e0Skleink #else
7977684d5e0Skleink 	if ( (y = d1) !=0) {
7987684d5e0Skleink 		if ( (k = lo0bits(&y)) !=0)
7997684d5e0Skleink 			if (k >= 16) {
8007684d5e0Skleink 				x[0] = y | z << 32 - k & 0xffff;
8017684d5e0Skleink 				x[1] = z >> k - 16 & 0xffff;
8027684d5e0Skleink 				x[2] = z >> k;
8037684d5e0Skleink 				i = 2;
8047684d5e0Skleink 				}
8057684d5e0Skleink 			else {
8067684d5e0Skleink 				x[0] = y & 0xffff;
8077684d5e0Skleink 				x[1] = y >> 16 | z << 16 - k & 0xffff;
8087684d5e0Skleink 				x[2] = z >> k & 0xffff;
8097684d5e0Skleink 				x[3] = z >> k+16;
8107684d5e0Skleink 				i = 3;
8117684d5e0Skleink 				}
8127684d5e0Skleink 		else {
8137684d5e0Skleink 			x[0] = y & 0xffff;
8147684d5e0Skleink 			x[1] = y >> 16;
8157684d5e0Skleink 			x[2] = z & 0xffff;
8167684d5e0Skleink 			x[3] = z >> 16;
8177684d5e0Skleink 			i = 3;
8187684d5e0Skleink 			}
8197684d5e0Skleink 		}
8207684d5e0Skleink 	else {
8217684d5e0Skleink #ifdef DEBUG
8227684d5e0Skleink 		if (!z)
8237684d5e0Skleink 			Bug("Zero passed to d2b");
8247684d5e0Skleink #endif
8257684d5e0Skleink 		k = lo0bits(&z);
8267684d5e0Skleink 		if (k >= 16) {
8277684d5e0Skleink 			x[0] = z;
8287684d5e0Skleink 			i = 0;
8297684d5e0Skleink 			}
8307684d5e0Skleink 		else {
8317684d5e0Skleink 			x[0] = z & 0xffff;
8327684d5e0Skleink 			x[1] = z >> 16;
8337684d5e0Skleink 			i = 1;
8347684d5e0Skleink 			}
8357684d5e0Skleink 		k += 32;
8367684d5e0Skleink 		}
8377684d5e0Skleink 	while(!x[i])
8387684d5e0Skleink 		--i;
8397684d5e0Skleink 	b->wds = i + 1;
8407684d5e0Skleink #endif
8417684d5e0Skleink #ifndef Sudden_Underflow
8427684d5e0Skleink 	if (de) {
8437684d5e0Skleink #endif
8447684d5e0Skleink #ifdef IBM
8457684d5e0Skleink 		*e = (de - Bias - (P-1) << 2) + k;
84661e56760Schristos 		*bits = 4*P + 8 - k - hi0bits(word0(&d) & Frac_mask);
8477684d5e0Skleink #else
8487684d5e0Skleink 		*e = de - Bias - (P-1) + k;
8497684d5e0Skleink 		*bits = P - k;
8507684d5e0Skleink #endif
8517684d5e0Skleink #ifndef Sudden_Underflow
8527684d5e0Skleink 		}
8537684d5e0Skleink 	else {
8547684d5e0Skleink 		*e = de - Bias - (P-1) + 1 + k;
8557684d5e0Skleink #ifdef Pack_32
8567684d5e0Skleink 		*bits = 32*i - hi0bits(x[i-1]);
8577684d5e0Skleink #else
8587684d5e0Skleink 		*bits = (i+2)*16 - hi0bits(x[i]);
8597684d5e0Skleink #endif
8607684d5e0Skleink 		}
8617684d5e0Skleink #endif
8627684d5e0Skleink 	return b;
8637684d5e0Skleink 	}
8647684d5e0Skleink #undef d0
8657684d5e0Skleink #undef d1
8667684d5e0Skleink 
8677684d5e0Skleink  CONST double
8687684d5e0Skleink #ifdef IEEE_Arith
8697684d5e0Skleink bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 };
8707684d5e0Skleink CONST double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, 1e-256
8717684d5e0Skleink 		};
8727684d5e0Skleink #else
8737684d5e0Skleink #ifdef IBM
8747684d5e0Skleink bigtens[] = { 1e16, 1e32, 1e64 };
8757684d5e0Skleink CONST double tinytens[] = { 1e-16, 1e-32, 1e-64 };
8767684d5e0Skleink #else
8777684d5e0Skleink bigtens[] = { 1e16, 1e32 };
8787684d5e0Skleink CONST double tinytens[] = { 1e-16, 1e-32 };
8797684d5e0Skleink #endif
8807684d5e0Skleink #endif
8817684d5e0Skleink 
8827684d5e0Skleink  CONST double
8837684d5e0Skleink tens[] = {
8847684d5e0Skleink 		1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
8857684d5e0Skleink 		1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
8867684d5e0Skleink 		1e20, 1e21, 1e22
8877684d5e0Skleink #ifdef VAX
8887684d5e0Skleink 		, 1e23, 1e24
8897684d5e0Skleink #endif
8907684d5e0Skleink 		};
8917684d5e0Skleink 
8927684d5e0Skleink  char *
8937684d5e0Skleink #ifdef KR_headers
strcp_D2A(a,b)8947684d5e0Skleink strcp_D2A(a, b) char *a; char *b;
8957684d5e0Skleink #else
8967684d5e0Skleink strcp_D2A(char *a, CONST char *b)
8977684d5e0Skleink #endif
8987684d5e0Skleink {
899ac898a26Skleink 	while((*a = *b++))
9007684d5e0Skleink 		a++;
9017684d5e0Skleink 	return a;
9027684d5e0Skleink 	}
9037684d5e0Skleink 
9047684d5e0Skleink #ifdef NO_STRING_H
9057684d5e0Skleink 
9067684d5e0Skleink  Char *
9077684d5e0Skleink #ifdef KR_headers
memcpy_D2A(a,b,len)9087684d5e0Skleink memcpy_D2A(a, b, len) Char *a; Char *b; size_t len;
9097684d5e0Skleink #else
9107684d5e0Skleink memcpy_D2A(void *a1, void *b1, size_t len)
9117684d5e0Skleink #endif
9127684d5e0Skleink {
913ac898a26Skleink 	char *a = (char*)a1, *ae = a + len;
914ac898a26Skleink 	char *b = (char*)b1, *a0 = a;
9157684d5e0Skleink 	while(a < ae)
9167684d5e0Skleink 		*a++ = *b++;
9177684d5e0Skleink 	return a0;
9187684d5e0Skleink 	}
9197684d5e0Skleink 
9207684d5e0Skleink #endif /* NO_STRING_H */
921