* Updating common/lib * Updating lib/csu * Updating lib/libc * Updating libexec/ld.elf_so * Corrected test on __minix in featuretest to actually follow the meaning of the comment. * Cleaned up _REENTRANT-related defintions. * Disabled -D_REENTRANT for libfetch * Removing some unneeded __NBSD_LIBC defines and tests Change-Id: Ic1394baef74d11b9f86b312f5ff4bbc3cbf72ce2
		
			
				
	
	
		
			921 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			921 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* $NetBSD: misc.c,v 1.11 2011/11/21 09:46:19 mlelstv Exp $ */
 | 
						|
 | 
						|
/****************************************************************
 | 
						|
 | 
						|
The author of this software is David M. Gay.
 | 
						|
 | 
						|
Copyright (C) 1998, 1999 by Lucent Technologies
 | 
						|
All Rights Reserved
 | 
						|
 | 
						|
Permission to use, copy, modify, and distribute this software and
 | 
						|
its documentation for any purpose and without fee is hereby
 | 
						|
granted, provided that the above copyright notice appear in all
 | 
						|
copies and that both that the copyright notice and this
 | 
						|
permission notice and warranty disclaimer appear in supporting
 | 
						|
documentation, and that the name of Lucent or any of its entities
 | 
						|
not be used in advertising or publicity pertaining to
 | 
						|
distribution of the software without specific, written prior
 | 
						|
permission.
 | 
						|
 | 
						|
LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 | 
						|
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
 | 
						|
IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
 | 
						|
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
						|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
 | 
						|
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 | 
						|
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
 | 
						|
THIS SOFTWARE.
 | 
						|
 | 
						|
****************************************************************/
 | 
						|
 | 
						|
/* Please send bug reports to David M. Gay (dmg at acm dot org,
 | 
						|
 * with " at " changed at "@" and " dot " changed to ".").	*/
 | 
						|
 | 
						|
#include "gdtoaimp.h"
 | 
						|
 | 
						|
 static Bigint *freelist[Kmax+1];
 | 
						|
#ifndef Omit_Private_Memory
 | 
						|
#ifndef PRIVATE_MEM
 | 
						|
#define PRIVATE_MEM 2304
 | 
						|
#endif
 | 
						|
#define PRIVATE_mem ((PRIVATE_MEM+sizeof(double)-1)/sizeof(double))
 | 
						|
static double private_mem[PRIVATE_mem], *pmem_next = private_mem;
 | 
						|
#endif
 | 
						|
 | 
						|
 Bigint *
 | 
						|
Balloc
 | 
						|
#ifdef KR_headers
 | 
						|
	(k) int k;
 | 
						|
#else
 | 
						|
	(int k)
 | 
						|
#endif
 | 
						|
{
 | 
						|
	int x;
 | 
						|
	Bigint *rv;
 | 
						|
#ifndef Omit_Private_Memory
 | 
						|
	size_t len;
 | 
						|
#endif
 | 
						|
 | 
						|
	ACQUIRE_DTOA_LOCK(0);
 | 
						|
	/* The k > Kmax case does not need ACQUIRE_DTOA_LOCK(0), */
 | 
						|
	/* but this case seems very unlikely. */
 | 
						|
	if ((size_t)k <= Kmax && (rv = freelist[k]) !=0) {
 | 
						|
		freelist[k] = rv->next;
 | 
						|
		}
 | 
						|
	else {
 | 
						|
		x = 1 << k;
 | 
						|
#ifdef Omit_Private_Memory
 | 
						|
		rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(ULong));
 | 
						|
#else
 | 
						|
		len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1)
 | 
						|
			/sizeof(double);
 | 
						|
		if ((size_t)k <= Kmax && pmem_next - private_mem + len <= PRIVATE_mem) {
 | 
						|
			rv = (Bigint*)(void *)pmem_next;
 | 
						|
			pmem_next += len;
 | 
						|
			}
 | 
						|
		else
 | 
						|
			rv = (Bigint*)MALLOC(len*sizeof(double));
 | 
						|
#endif
 | 
						|
		if (rv == NULL) {
 | 
						|
			FREE_DTOA_LOCK(0);
 | 
						|
			return NULL;
 | 
						|
		}
 | 
						|
		rv->k = k;
 | 
						|
		rv->maxwds = x;
 | 
						|
		}
 | 
						|
	FREE_DTOA_LOCK(0);
 | 
						|
	rv->sign = rv->wds = 0;
 | 
						|
	return rv;
 | 
						|
	}
 | 
						|
 | 
						|
 void
 | 
						|
Bfree
 | 
						|
#ifdef KR_headers
 | 
						|
	(v) Bigint *v;
 | 
						|
#else
 | 
						|
	(Bigint *v)
 | 
						|
#endif
 | 
						|
{
 | 
						|
	if (v) {
 | 
						|
		if ((size_t)v->k > Kmax)
 | 
						|
#ifdef FREE
 | 
						|
			FREE((void*)v);
 | 
						|
#else
 | 
						|
			free((void*)v);
 | 
						|
#endif
 | 
						|
		else {
 | 
						|
			ACQUIRE_DTOA_LOCK(0);
 | 
						|
			v->next = freelist[v->k];
 | 
						|
			freelist[v->k] = v;
 | 
						|
			FREE_DTOA_LOCK(0);
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
 int
 | 
						|
lo0bits
 | 
						|
#ifdef KR_headers
 | 
						|
	(y) ULong *y;
 | 
						|
#else
 | 
						|
	(ULong *y)
 | 
						|
#endif
 | 
						|
{
 | 
						|
	int k;
 | 
						|
	ULong x = *y;
 | 
						|
 | 
						|
	if (x & 7) {
 | 
						|
		if (x & 1)
 | 
						|
			return 0;
 | 
						|
		if (x & 2) {
 | 
						|
			*y = x >> 1;
 | 
						|
			return 1;
 | 
						|
			}
 | 
						|
		*y = x >> 2;
 | 
						|
		return 2;
 | 
						|
		}
 | 
						|
	k = 0;
 | 
						|
	if (!(x & 0xffff)) {
 | 
						|
		k = 16;
 | 
						|
		x >>= 16;
 | 
						|
		}
 | 
						|
	if (!(x & 0xff)) {
 | 
						|
		k += 8;
 | 
						|
		x >>= 8;
 | 
						|
		}
 | 
						|
	if (!(x & 0xf)) {
 | 
						|
		k += 4;
 | 
						|
		x >>= 4;
 | 
						|
		}
 | 
						|
	if (!(x & 0x3)) {
 | 
						|
		k += 2;
 | 
						|
		x >>= 2;
 | 
						|
		}
 | 
						|
	if (!(x & 1)) {
 | 
						|
		k++;
 | 
						|
		x >>= 1;
 | 
						|
		if (!x)
 | 
						|
			return 32;
 | 
						|
		}
 | 
						|
	*y = x;
 | 
						|
	return k;
 | 
						|
	}
 | 
						|
 | 
						|
 Bigint *
 | 
						|
multadd
 | 
						|
#ifdef KR_headers
 | 
						|
	(b, m, a) Bigint *b; int m, a;
 | 
						|
#else
 | 
						|
	(Bigint *b, int m, int a)	/* multiply by m and add a */
 | 
						|
#endif
 | 
						|
{
 | 
						|
	int i, wds;
 | 
						|
#ifdef ULLong
 | 
						|
	ULong *x;
 | 
						|
	ULLong carry, y;
 | 
						|
#else
 | 
						|
	ULong carry, *x, y;
 | 
						|
#ifdef Pack_32
 | 
						|
	ULong xi, z;
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
	Bigint *b1;
 | 
						|
 | 
						|
	wds = b->wds;
 | 
						|
	x = b->x;
 | 
						|
	i = 0;
 | 
						|
	carry = a;
 | 
						|
	do {
 | 
						|
#ifdef ULLong
 | 
						|
		y = *x * (ULLong)m + carry;
 | 
						|
		carry = y >> 32;
 | 
						|
		/* LINTED conversion */
 | 
						|
		*x++ = y & 0xffffffffUL;
 | 
						|
#else
 | 
						|
#ifdef Pack_32
 | 
						|
		xi = *x;
 | 
						|
		y = (xi & 0xffff) * m + carry;
 | 
						|
		z = (xi >> 16) * m + (y >> 16);
 | 
						|
		carry = z >> 16;
 | 
						|
		*x++ = (z << 16) + (y & 0xffff);
 | 
						|
#else
 | 
						|
		y = *x * m + carry;
 | 
						|
		carry = y >> 16;
 | 
						|
		*x++ = y & 0xffff;
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
		}
 | 
						|
		while(++i < wds);
 | 
						|
	if (carry) {
 | 
						|
		if (wds >= b->maxwds) {
 | 
						|
			b1 = Balloc(b->k+1);
 | 
						|
			if (b1 == NULL) {
 | 
						|
				Bfree(b);
 | 
						|
				return NULL;
 | 
						|
				}
 | 
						|
			Bcopy(b1, b);
 | 
						|
			Bfree(b);
 | 
						|
			b = b1;
 | 
						|
			}
 | 
						|
		/* LINTED conversion */
 | 
						|
		b->x[wds++] = carry;
 | 
						|
		b->wds = wds;
 | 
						|
		}
 | 
						|
	return b;
 | 
						|
	}
 | 
						|
 | 
						|
 int
 | 
						|
hi0bits_D2A
 | 
						|
#ifdef KR_headers
 | 
						|
	(x) ULong x;
 | 
						|
#else
 | 
						|
	(ULong x)
 | 
						|
#endif
 | 
						|
{
 | 
						|
	int k = 0;
 | 
						|
 | 
						|
	if (!(x & 0xffff0000)) {
 | 
						|
		k = 16;
 | 
						|
		x <<= 16;
 | 
						|
		}
 | 
						|
	if (!(x & 0xff000000)) {
 | 
						|
		k += 8;
 | 
						|
		x <<= 8;
 | 
						|
		}
 | 
						|
	if (!(x & 0xf0000000)) {
 | 
						|
		k += 4;
 | 
						|
		x <<= 4;
 | 
						|
		}
 | 
						|
	if (!(x & 0xc0000000)) {
 | 
						|
		k += 2;
 | 
						|
		x <<= 2;
 | 
						|
		}
 | 
						|
	if (!(x & 0x80000000)) {
 | 
						|
		k++;
 | 
						|
		if (!(x & 0x40000000))
 | 
						|
			return 32;
 | 
						|
		}
 | 
						|
	return k;
 | 
						|
	}
 | 
						|
 | 
						|
 Bigint *
 | 
						|
i2b
 | 
						|
#ifdef KR_headers
 | 
						|
	(i) int i;
 | 
						|
#else
 | 
						|
	(int i)
 | 
						|
#endif
 | 
						|
{
 | 
						|
	Bigint *b;
 | 
						|
 | 
						|
	b = Balloc(1);
 | 
						|
	if (b == NULL)
 | 
						|
		return NULL;
 | 
						|
	b->x[0] = i;
 | 
						|
	b->wds = 1;
 | 
						|
	return b;
 | 
						|
	}
 | 
						|
 | 
						|
 Bigint *
 | 
						|
mult
 | 
						|
#ifdef KR_headers
 | 
						|
	(a, b) Bigint *a, *b;
 | 
						|
#else
 | 
						|
	(Bigint *a, Bigint *b)
 | 
						|
#endif
 | 
						|
{
 | 
						|
	Bigint *c;
 | 
						|
	int k, wa, wb, wc;
 | 
						|
	ULong *x, *xa, *xae, *xb, *xbe, *xc, *xc0;
 | 
						|
	ULong y;
 | 
						|
#ifdef ULLong
 | 
						|
	ULLong carry, z;
 | 
						|
#else
 | 
						|
	ULong carry, z;
 | 
						|
#ifdef Pack_32
 | 
						|
	ULong z2;
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
 | 
						|
	if (a->wds < b->wds) {
 | 
						|
		c = a;
 | 
						|
		a = b;
 | 
						|
		b = c;
 | 
						|
		}
 | 
						|
	k = a->k;
 | 
						|
	wa = a->wds;
 | 
						|
	wb = b->wds;
 | 
						|
	wc = wa + wb;
 | 
						|
	if (wc > a->maxwds)
 | 
						|
		k++;
 | 
						|
	c = Balloc(k);
 | 
						|
	if (c == NULL)
 | 
						|
		return NULL;
 | 
						|
	for(x = c->x, xa = x + wc; x < xa; x++)
 | 
						|
		*x = 0;
 | 
						|
	xa = a->x;
 | 
						|
	xae = xa + wa;
 | 
						|
	xb = b->x;
 | 
						|
	xbe = xb + wb;
 | 
						|
	xc0 = c->x;
 | 
						|
#ifdef ULLong
 | 
						|
	for(; xb < xbe; xc0++) {
 | 
						|
		if ( (y = *xb++) !=0) {
 | 
						|
			x = xa;
 | 
						|
			xc = xc0;
 | 
						|
			carry = 0;
 | 
						|
			do {
 | 
						|
				z = *x++ * (ULLong)y + *xc + carry;
 | 
						|
				carry = z >> 32;
 | 
						|
				/* LINTED conversion */
 | 
						|
				*xc++ = z & 0xffffffffUL;
 | 
						|
				}
 | 
						|
				while(x < xae);
 | 
						|
			/* LINTED conversion */
 | 
						|
			*xc = carry;
 | 
						|
			}
 | 
						|
		}
 | 
						|
#else
 | 
						|
#ifdef Pack_32
 | 
						|
	for(; xb < xbe; xb++, xc0++) {
 | 
						|
		if ( (y = *xb & 0xffff) !=0) {
 | 
						|
			x = xa;
 | 
						|
			xc = xc0;
 | 
						|
			carry = 0;
 | 
						|
			do {
 | 
						|
				z = (*x & 0xffff) * y + (*xc & 0xffff) + carry;
 | 
						|
				carry = z >> 16;
 | 
						|
				z2 = (*x++ >> 16) * y + (*xc >> 16) + carry;
 | 
						|
				carry = z2 >> 16;
 | 
						|
				Storeinc(xc, z2, z);
 | 
						|
				}
 | 
						|
				while(x < xae);
 | 
						|
			*xc = carry;
 | 
						|
			}
 | 
						|
		if ( (y = *xb >> 16) !=0) {
 | 
						|
			x = xa;
 | 
						|
			xc = xc0;
 | 
						|
			carry = 0;
 | 
						|
			z2 = *xc;
 | 
						|
			do {
 | 
						|
				z = (*x & 0xffff) * y + (*xc >> 16) + carry;
 | 
						|
				carry = z >> 16;
 | 
						|
				Storeinc(xc, z, z2);
 | 
						|
				z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry;
 | 
						|
				carry = z2 >> 16;
 | 
						|
				}
 | 
						|
				while(x < xae);
 | 
						|
			*xc = z2;
 | 
						|
			}
 | 
						|
		}
 | 
						|
#else
 | 
						|
	for(; xb < xbe; xc0++) {
 | 
						|
		if ( (y = *xb++) !=0) {
 | 
						|
			x = xa;
 | 
						|
			xc = xc0;
 | 
						|
			carry = 0;
 | 
						|
			do {
 | 
						|
				z = *x++ * y + *xc + carry;
 | 
						|
				carry = z >> 16;
 | 
						|
				*xc++ = z & 0xffff;
 | 
						|
				}
 | 
						|
				while(x < xae);
 | 
						|
			*xc = carry;
 | 
						|
			}
 | 
						|
		}
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
	for(xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ;
 | 
						|
	c->wds = wc;
 | 
						|
	return c;
 | 
						|
	}
 | 
						|
 | 
						|
 static Bigint *p5s;
 | 
						|
 | 
						|
 Bigint *
 | 
						|
pow5mult
 | 
						|
#ifdef KR_headers
 | 
						|
	(b, k) Bigint *b; int k;
 | 
						|
#else
 | 
						|
	(Bigint *b, int k)
 | 
						|
#endif
 | 
						|
{
 | 
						|
	Bigint *b1, *p5, *p51;
 | 
						|
	int i;
 | 
						|
	static CONST int p05[3] = { 5, 25, 125 };
 | 
						|
 | 
						|
	if ( (i = k & 3) !=0) {
 | 
						|
		b = multadd(b, p05[i-1], 0);
 | 
						|
		if (b == NULL)
 | 
						|
			return NULL;
 | 
						|
		}
 | 
						|
 | 
						|
	if (!(k = (unsigned int)k >> 2))
 | 
						|
		return b;
 | 
						|
	if ((p5 = p5s) == 0) {
 | 
						|
		/* first time */
 | 
						|
#ifdef MULTIPLE_THREADS
 | 
						|
		ACQUIRE_DTOA_LOCK(1);
 | 
						|
		if (!(p5 = p5s)) {
 | 
						|
			p5 = p5s = i2b(625);
 | 
						|
			if (p5 == NULL) {
 | 
						|
				FREE_DTOA_LOCK(1);
 | 
						|
				return NULL;
 | 
						|
			}
 | 
						|
			p5->next = 0;
 | 
						|
			}
 | 
						|
		FREE_DTOA_LOCK(1);
 | 
						|
#else
 | 
						|
		p5 = p5s = i2b(625);
 | 
						|
		if (p5 == NULL)
 | 
						|
			return NULL;
 | 
						|
		p5->next = 0;
 | 
						|
#endif
 | 
						|
		}
 | 
						|
	for(;;) {
 | 
						|
		if (k & 1) {
 | 
						|
			b1 = mult(b, p5);
 | 
						|
			if (b1 == NULL)
 | 
						|
				return NULL;
 | 
						|
			Bfree(b);
 | 
						|
			b = b1;
 | 
						|
			}
 | 
						|
		if (!(k = (unsigned int)k >> 1))
 | 
						|
			break;
 | 
						|
		if ((p51 = p5->next) == 0) {
 | 
						|
#ifdef MULTIPLE_THREADS
 | 
						|
			ACQUIRE_DTOA_LOCK(1);
 | 
						|
			if (!(p51 = p5->next)) {
 | 
						|
				p51 = p5->next = mult(p5,p5);
 | 
						|
				if (p51 == NULL) {
 | 
						|
					FREE_DTOA_LOCK(1);
 | 
						|
					return NULL;
 | 
						|
				}
 | 
						|
				p51->next = 0;
 | 
						|
				}
 | 
						|
			FREE_DTOA_LOCK(1);
 | 
						|
#else
 | 
						|
			p51 = p5->next = mult(p5,p5);
 | 
						|
			if (p51 == NULL)
 | 
						|
				return NULL;
 | 
						|
			p51->next = 0;
 | 
						|
#endif
 | 
						|
			}
 | 
						|
		p5 = p51;
 | 
						|
		}
 | 
						|
	return b;
 | 
						|
	}
 | 
						|
 | 
						|
 Bigint *
 | 
						|
lshift
 | 
						|
#ifdef KR_headers
 | 
						|
	(b, k) Bigint *b; int k;
 | 
						|
#else
 | 
						|
	(Bigint *b, int k)
 | 
						|
#endif
 | 
						|
{
 | 
						|
	int i, k1, n, n1;
 | 
						|
	Bigint *b1;
 | 
						|
	ULong *x, *x1, *xe, z;
 | 
						|
 | 
						|
	n = (unsigned int)k >> kshift;
 | 
						|
	k1 = b->k;
 | 
						|
	n1 = n + b->wds + 1;
 | 
						|
	for(i = b->maxwds; n1 > i; i <<= 1)
 | 
						|
		k1++;
 | 
						|
	b1 = Balloc(k1);
 | 
						|
	if (b1 == NULL)
 | 
						|
		return NULL;
 | 
						|
	x1 = b1->x;
 | 
						|
	for(i = 0; i < n; i++)
 | 
						|
		*x1++ = 0;
 | 
						|
	x = b->x;
 | 
						|
	xe = x + b->wds;
 | 
						|
	if (k &= kmask) {
 | 
						|
#ifdef Pack_32
 | 
						|
		k1 = 32 - k;
 | 
						|
		z = 0;
 | 
						|
		do {
 | 
						|
			*x1++ = *x << k | z;
 | 
						|
			z = *x++ >> k1;
 | 
						|
			}
 | 
						|
			while(x < xe);
 | 
						|
		if ((*x1 = z) !=0)
 | 
						|
			++n1;
 | 
						|
#else
 | 
						|
		k1 = 16 - k;
 | 
						|
		z = 0;
 | 
						|
		do {
 | 
						|
			*x1++ = *x << k  & 0xffff | z;
 | 
						|
			z = *x++ >> k1;
 | 
						|
			}
 | 
						|
			while(x < xe);
 | 
						|
		if (*x1 = z)
 | 
						|
			++n1;
 | 
						|
#endif
 | 
						|
		}
 | 
						|
	else do
 | 
						|
		*x1++ = *x++;
 | 
						|
		while(x < xe);
 | 
						|
	b1->wds = n1 - 1;
 | 
						|
	Bfree(b);
 | 
						|
	return b1;
 | 
						|
	}
 | 
						|
 | 
						|
 int
 | 
						|
cmp
 | 
						|
#ifdef KR_headers
 | 
						|
	(a, b) Bigint *a, *b;
 | 
						|
#else
 | 
						|
	(Bigint *a, Bigint *b)
 | 
						|
#endif
 | 
						|
{
 | 
						|
	ULong *xa, *xa0, *xb, *xb0;
 | 
						|
	int i, j;
 | 
						|
 | 
						|
	i = a->wds;
 | 
						|
	j = b->wds;
 | 
						|
#ifdef DEBUG
 | 
						|
	if (i > 1 && !a->x[i-1])
 | 
						|
		Bug("cmp called with a->x[a->wds-1] == 0");
 | 
						|
	if (j > 1 && !b->x[j-1])
 | 
						|
		Bug("cmp called with b->x[b->wds-1] == 0");
 | 
						|
#endif
 | 
						|
	if (i -= j)
 | 
						|
		return i;
 | 
						|
	xa0 = a->x;
 | 
						|
	xa = xa0 + j;
 | 
						|
	xb0 = b->x;
 | 
						|
	xb = xb0 + j;
 | 
						|
	for(;;) {
 | 
						|
		if (*--xa != *--xb)
 | 
						|
			return *xa < *xb ? -1 : 1;
 | 
						|
		if (xa <= xa0)
 | 
						|
			break;
 | 
						|
		}
 | 
						|
	return 0;
 | 
						|
	}
 | 
						|
 | 
						|
 Bigint *
 | 
						|
diff
 | 
						|
#ifdef KR_headers
 | 
						|
	(a, b) Bigint *a, *b;
 | 
						|
#else
 | 
						|
	(Bigint *a, Bigint *b)
 | 
						|
#endif
 | 
						|
{
 | 
						|
	Bigint *c;
 | 
						|
	int i, wa, wb;
 | 
						|
	ULong *xa, *xae, *xb, *xbe, *xc;
 | 
						|
#ifdef ULLong
 | 
						|
	ULLong borrow, y;
 | 
						|
#else
 | 
						|
	ULong borrow, y;
 | 
						|
#ifdef Pack_32
 | 
						|
	ULong z;
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
 | 
						|
	i = cmp(a,b);
 | 
						|
	if (!i) {
 | 
						|
		c = Balloc(0);
 | 
						|
		if (c == NULL)
 | 
						|
			return NULL;
 | 
						|
		c->wds = 1;
 | 
						|
		c->x[0] = 0;
 | 
						|
		return c;
 | 
						|
		}
 | 
						|
	if (i < 0) {
 | 
						|
		c = a;
 | 
						|
		a = b;
 | 
						|
		b = c;
 | 
						|
		i = 1;
 | 
						|
		}
 | 
						|
	else
 | 
						|
		i = 0;
 | 
						|
	c = Balloc(a->k);
 | 
						|
	if (c == NULL)
 | 
						|
		return NULL;
 | 
						|
	c->sign = i;
 | 
						|
	wa = a->wds;
 | 
						|
	xa = a->x;
 | 
						|
	xae = xa + wa;
 | 
						|
	wb = b->wds;
 | 
						|
	xb = b->x;
 | 
						|
	xbe = xb + wb;
 | 
						|
	xc = c->x;
 | 
						|
	borrow = 0;
 | 
						|
#ifdef ULLong
 | 
						|
	do {
 | 
						|
		y = (ULLong)*xa++ - *xb++ - borrow;
 | 
						|
		borrow = y >> 32 & 1UL;
 | 
						|
		/* LINTED conversion */
 | 
						|
		*xc++ = y & 0xffffffffUL;
 | 
						|
		}
 | 
						|
		while(xb < xbe);
 | 
						|
	while(xa < xae) {
 | 
						|
		y = *xa++ - borrow;
 | 
						|
		borrow = y >> 32 & 1UL;
 | 
						|
		/* LINTED conversion */
 | 
						|
		*xc++ = y & 0xffffffffUL;
 | 
						|
		}
 | 
						|
#else
 | 
						|
#ifdef Pack_32
 | 
						|
	do {
 | 
						|
		y = (*xa & 0xffff) - (*xb & 0xffff) - borrow;
 | 
						|
		borrow = (y & 0x10000) >> 16;
 | 
						|
		z = (*xa++ >> 16) - (*xb++ >> 16) - borrow;
 | 
						|
		borrow = (z & 0x10000) >> 16;
 | 
						|
		Storeinc(xc, z, y);
 | 
						|
		}
 | 
						|
		while(xb < xbe);
 | 
						|
	while(xa < xae) {
 | 
						|
		y = (*xa & 0xffff) - borrow;
 | 
						|
		borrow = (y & 0x10000) >> 16;
 | 
						|
		z = (*xa++ >> 16) - borrow;
 | 
						|
		borrow = (z & 0x10000) >> 16;
 | 
						|
		Storeinc(xc, z, y);
 | 
						|
		}
 | 
						|
#else
 | 
						|
	do {
 | 
						|
		y = *xa++ - *xb++ - borrow;
 | 
						|
		borrow = (y & 0x10000) >> 16;
 | 
						|
		*xc++ = y & 0xffff;
 | 
						|
		}
 | 
						|
		while(xb < xbe);
 | 
						|
	while(xa < xae) {
 | 
						|
		y = *xa++ - borrow;
 | 
						|
		borrow = (y & 0x10000) >> 16;
 | 
						|
		*xc++ = y & 0xffff;
 | 
						|
		}
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
	while(!*--xc)
 | 
						|
		wa--;
 | 
						|
	c->wds = wa;
 | 
						|
	return c;
 | 
						|
	}
 | 
						|
 | 
						|
 double
 | 
						|
b2d
 | 
						|
#ifdef KR_headers
 | 
						|
	(a, e) Bigint *a; int *e;
 | 
						|
#else
 | 
						|
	(Bigint *a, int *e)
 | 
						|
#endif
 | 
						|
{
 | 
						|
	ULong *xa, *xa0, w, y, z;
 | 
						|
	int k;
 | 
						|
	U d;
 | 
						|
#ifdef VAX
 | 
						|
	ULong d0, d1;
 | 
						|
#else
 | 
						|
#define d0 word0(&d)
 | 
						|
#define d1 word1(&d)
 | 
						|
#endif
 | 
						|
 | 
						|
	xa0 = a->x;
 | 
						|
	xa = xa0 + a->wds;
 | 
						|
	y = *--xa;
 | 
						|
#ifdef DEBUG
 | 
						|
	if (!y) Bug("zero y in b2d");
 | 
						|
#endif
 | 
						|
	k = hi0bits(y);
 | 
						|
	*e = 32 - k;
 | 
						|
#ifdef Pack_32
 | 
						|
	if (k < Ebits) {
 | 
						|
		d0 = Exp_1 | y >> (Ebits - k);
 | 
						|
		w = xa > xa0 ? *--xa : 0;
 | 
						|
		d1 = y << ((32-Ebits) + k) | w >> (Ebits - k);
 | 
						|
		goto ret_d;
 | 
						|
		}
 | 
						|
	z = xa > xa0 ? *--xa : 0;
 | 
						|
	if (k -= Ebits) {
 | 
						|
		d0 = Exp_1 | y << k | z >> (32 - k);
 | 
						|
		y = xa > xa0 ? *--xa : 0;
 | 
						|
		d1 = z << k | y >> (32 - k);
 | 
						|
		}
 | 
						|
	else {
 | 
						|
		d0 = Exp_1 | y;
 | 
						|
		d1 = z;
 | 
						|
		}
 | 
						|
#else
 | 
						|
	if (k < Ebits + 16) {
 | 
						|
		z = xa > xa0 ? *--xa : 0;
 | 
						|
		d0 = Exp_1 | y << k - Ebits | z >> Ebits + 16 - k;
 | 
						|
		w = xa > xa0 ? *--xa : 0;
 | 
						|
		y = xa > xa0 ? *--xa : 0;
 | 
						|
		d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k;
 | 
						|
		goto ret_d;
 | 
						|
		}
 | 
						|
	z = xa > xa0 ? *--xa : 0;
 | 
						|
	w = xa > xa0 ? *--xa : 0;
 | 
						|
	k -= Ebits + 16;
 | 
						|
	d0 = Exp_1 | y << k + 16 | z << k | w >> 16 - k;
 | 
						|
	y = xa > xa0 ? *--xa : 0;
 | 
						|
	d1 = w << k + 16 | y << k;
 | 
						|
#endif
 | 
						|
 ret_d:
 | 
						|
#ifdef VAX
 | 
						|
	word0(&d) = d0 >> 16 | d0 << 16;
 | 
						|
	word1(&d) = d1 >> 16 | d1 << 16;
 | 
						|
#endif
 | 
						|
	return dval(&d);
 | 
						|
	}
 | 
						|
#undef d0
 | 
						|
#undef d1
 | 
						|
 | 
						|
 Bigint *
 | 
						|
d2b
 | 
						|
#ifdef KR_headers
 | 
						|
	(dd, e, bits) double dd; int *e, *bits;
 | 
						|
#else
 | 
						|
	(double dd, int *e, int *bits)
 | 
						|
#endif
 | 
						|
{
 | 
						|
	Bigint *b;
 | 
						|
	U d;
 | 
						|
#ifndef Sudden_Underflow
 | 
						|
	int i;
 | 
						|
#endif
 | 
						|
	int de, k;
 | 
						|
	ULong *x, y, z;
 | 
						|
#ifdef VAX
 | 
						|
	ULong d0, d1;
 | 
						|
#else
 | 
						|
#define d0 word0(&d)
 | 
						|
#define d1 word1(&d)
 | 
						|
#endif
 | 
						|
	d.d = dd;
 | 
						|
#ifdef VAX
 | 
						|
	d0 = word0(&d) >> 16 | word0(&d) << 16;
 | 
						|
	d1 = word1(&d) >> 16 | word1(&d) << 16;
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef Pack_32
 | 
						|
	b = Balloc(1);
 | 
						|
#else
 | 
						|
	b = Balloc(2);
 | 
						|
#endif
 | 
						|
	if (b == NULL)
 | 
						|
		return NULL;
 | 
						|
	x = b->x;
 | 
						|
 | 
						|
	z = d0 & Frac_mask;
 | 
						|
	d0 &= 0x7fffffff;	/* clear sign bit, which we ignore */
 | 
						|
#ifdef Sudden_Underflow
 | 
						|
	de = (int)(d0 >> Exp_shift);
 | 
						|
#ifndef IBM
 | 
						|
	z |= Exp_msk11;
 | 
						|
#endif
 | 
						|
#else
 | 
						|
	if ( (de = (int)(d0 >> Exp_shift)) !=0)
 | 
						|
		z |= Exp_msk1;
 | 
						|
#endif
 | 
						|
#ifdef Pack_32
 | 
						|
	if ( (y = d1) !=0) {
 | 
						|
		if ( (k = lo0bits(&y)) !=0) {
 | 
						|
			x[0] = y | z << (32 - k);
 | 
						|
			z >>= k;
 | 
						|
			}
 | 
						|
		else
 | 
						|
			x[0] = y;
 | 
						|
#ifndef Sudden_Underflow
 | 
						|
		i =
 | 
						|
#endif
 | 
						|
		     b->wds = (x[1] = z) !=0 ? 2 : 1;
 | 
						|
		}
 | 
						|
	else {
 | 
						|
		k = lo0bits(&z);
 | 
						|
		x[0] = z;
 | 
						|
#ifndef Sudden_Underflow
 | 
						|
		i =
 | 
						|
#endif
 | 
						|
		    b->wds = 1;
 | 
						|
		k += 32;
 | 
						|
		}
 | 
						|
#else
 | 
						|
	if ( (y = d1) !=0) {
 | 
						|
		if ( (k = lo0bits(&y)) !=0)
 | 
						|
			if (k >= 16) {
 | 
						|
				x[0] = y | z << 32 - k & 0xffff;
 | 
						|
				x[1] = z >> k - 16 & 0xffff;
 | 
						|
				x[2] = z >> k;
 | 
						|
				i = 2;
 | 
						|
				}
 | 
						|
			else {
 | 
						|
				x[0] = y & 0xffff;
 | 
						|
				x[1] = y >> 16 | z << 16 - k & 0xffff;
 | 
						|
				x[2] = z >> k & 0xffff;
 | 
						|
				x[3] = z >> k+16;
 | 
						|
				i = 3;
 | 
						|
				}
 | 
						|
		else {
 | 
						|
			x[0] = y & 0xffff;
 | 
						|
			x[1] = y >> 16;
 | 
						|
			x[2] = z & 0xffff;
 | 
						|
			x[3] = z >> 16;
 | 
						|
			i = 3;
 | 
						|
			}
 | 
						|
		}
 | 
						|
	else {
 | 
						|
#ifdef DEBUG
 | 
						|
		if (!z)
 | 
						|
			Bug("Zero passed to d2b");
 | 
						|
#endif
 | 
						|
		k = lo0bits(&z);
 | 
						|
		if (k >= 16) {
 | 
						|
			x[0] = z;
 | 
						|
			i = 0;
 | 
						|
			}
 | 
						|
		else {
 | 
						|
			x[0] = z & 0xffff;
 | 
						|
			x[1] = z >> 16;
 | 
						|
			i = 1;
 | 
						|
			}
 | 
						|
		k += 32;
 | 
						|
		}
 | 
						|
	while(!x[i])
 | 
						|
		--i;
 | 
						|
	b->wds = i + 1;
 | 
						|
#endif
 | 
						|
#ifndef Sudden_Underflow
 | 
						|
	if (de) {
 | 
						|
#endif
 | 
						|
#ifdef IBM
 | 
						|
		*e = (de - Bias - (P-1) << 2) + k;
 | 
						|
		*bits = 4*P + 8 - k - hi0bits(word0(&d) & Frac_mask);
 | 
						|
#else
 | 
						|
		*e = de - Bias - (P-1) + k;
 | 
						|
		*bits = P - k;
 | 
						|
#endif
 | 
						|
#ifndef Sudden_Underflow
 | 
						|
		}
 | 
						|
	else {
 | 
						|
		*e = de - Bias - (P-1) + 1 + k;
 | 
						|
#ifdef Pack_32
 | 
						|
		*bits = 32*i - hi0bits(x[i-1]);
 | 
						|
#else
 | 
						|
		*bits = (i+2)*16 - hi0bits(x[i]);
 | 
						|
#endif
 | 
						|
		}
 | 
						|
#endif
 | 
						|
	return b;
 | 
						|
	}
 | 
						|
#undef d0
 | 
						|
#undef d1
 | 
						|
 | 
						|
 CONST double
 | 
						|
#ifdef IEEE_Arith
 | 
						|
bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 };
 | 
						|
CONST double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, 1e-256
 | 
						|
		};
 | 
						|
#else
 | 
						|
#ifdef IBM
 | 
						|
bigtens[] = { 1e16, 1e32, 1e64 };
 | 
						|
CONST double tinytens[] = { 1e-16, 1e-32, 1e-64 };
 | 
						|
#else
 | 
						|
bigtens[] = { 1e16, 1e32 };
 | 
						|
CONST double tinytens[] = { 1e-16, 1e-32 };
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
 | 
						|
 CONST double
 | 
						|
tens[] = {
 | 
						|
		1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
 | 
						|
		1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
 | 
						|
		1e20, 1e21, 1e22
 | 
						|
#ifdef VAX
 | 
						|
		, 1e23, 1e24
 | 
						|
#endif
 | 
						|
		};
 | 
						|
 | 
						|
 char *
 | 
						|
#ifdef KR_headers
 | 
						|
strcp_D2A(a, b) char *a; char *b;
 | 
						|
#else
 | 
						|
strcp_D2A(char *a, CONST char *b)
 | 
						|
#endif
 | 
						|
{
 | 
						|
	while((*a = *b++))
 | 
						|
		a++;
 | 
						|
	return a;
 | 
						|
	}
 | 
						|
 | 
						|
#ifdef NO_STRING_H
 | 
						|
 | 
						|
 Char *
 | 
						|
#ifdef KR_headers
 | 
						|
memcpy_D2A(a, b, len) Char *a; Char *b; size_t len;
 | 
						|
#else
 | 
						|
memcpy_D2A(void *a1, void *b1, size_t len)
 | 
						|
#endif
 | 
						|
{
 | 
						|
	char *a = (char*)a1, *ae = a + len;
 | 
						|
	char *b = (char*)b1, *a0 = a;
 | 
						|
	while(a < ae)
 | 
						|
		*a++ = *b++;
 | 
						|
	return a0;
 | 
						|
	}
 | 
						|
 | 
						|
#endif /* NO_STRING_H */
 |