xref: /freebsd/contrib/gdtoa/dmisc.c (revision c88250a57d53dba5de2e77508383019ff63e88b6)
1cc36ccd1SDavid Schultz /****************************************************************
2cc36ccd1SDavid Schultz 
3cc36ccd1SDavid Schultz The author of this software is David M. Gay.
4cc36ccd1SDavid Schultz 
5cc36ccd1SDavid Schultz Copyright (C) 1998 by Lucent Technologies
6cc36ccd1SDavid Schultz All Rights Reserved
7cc36ccd1SDavid Schultz 
8cc36ccd1SDavid Schultz Permission to use, copy, modify, and distribute this software and
9cc36ccd1SDavid Schultz its documentation for any purpose and without fee is hereby
10cc36ccd1SDavid Schultz granted, provided that the above copyright notice appear in all
11cc36ccd1SDavid Schultz copies and that both that the copyright notice and this
12cc36ccd1SDavid Schultz permission notice and warranty disclaimer appear in supporting
13cc36ccd1SDavid Schultz documentation, and that the name of Lucent or any of its entities
14cc36ccd1SDavid Schultz not be used in advertising or publicity pertaining to
15cc36ccd1SDavid Schultz distribution of the software without specific, written prior
16cc36ccd1SDavid Schultz permission.
17cc36ccd1SDavid Schultz 
18cc36ccd1SDavid Schultz LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
19cc36ccd1SDavid Schultz INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
20cc36ccd1SDavid Schultz IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
21cc36ccd1SDavid Schultz SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
22cc36ccd1SDavid Schultz WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
23cc36ccd1SDavid Schultz IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
24cc36ccd1SDavid Schultz ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
25cc36ccd1SDavid Schultz THIS SOFTWARE.
26cc36ccd1SDavid Schultz 
27cc36ccd1SDavid Schultz ****************************************************************/
28cc36ccd1SDavid Schultz 
29c88250a5SDavid Schultz /* Please send bug reports to David M. Gay (dmg at acm dot org,
30c88250a5SDavid Schultz  * with " at " changed at "@" and " dot " changed to ".").	*/
31cc36ccd1SDavid Schultz 
32cc36ccd1SDavid Schultz #include "gdtoaimp.h"
33cc36ccd1SDavid Schultz 
34cc36ccd1SDavid Schultz #ifndef MULTIPLE_THREADS
35cc36ccd1SDavid Schultz  char *dtoa_result;
36cc36ccd1SDavid Schultz #endif
37cc36ccd1SDavid Schultz 
38cc36ccd1SDavid Schultz  char *
39cc36ccd1SDavid Schultz #ifdef KR_headers
rv_alloc(i)40cc36ccd1SDavid Schultz rv_alloc(i) int i;
41cc36ccd1SDavid Schultz #else
42cc36ccd1SDavid Schultz rv_alloc(int i)
43cc36ccd1SDavid Schultz #endif
44cc36ccd1SDavid Schultz {
45cc36ccd1SDavid Schultz 	int j, k, *r;
46cc36ccd1SDavid Schultz 
47cc36ccd1SDavid Schultz 	j = sizeof(ULong);
48cc36ccd1SDavid Schultz 	for(k = 0;
49cc36ccd1SDavid Schultz 		sizeof(Bigint) - sizeof(ULong) - sizeof(int) + j <= i;
50cc36ccd1SDavid Schultz 		j <<= 1)
51cc36ccd1SDavid Schultz 			k++;
52cc36ccd1SDavid Schultz 	r = (int*)Balloc(k);
53cc36ccd1SDavid Schultz 	*r = k;
54cc36ccd1SDavid Schultz 	return
55cc36ccd1SDavid Schultz #ifndef MULTIPLE_THREADS
56cc36ccd1SDavid Schultz 	dtoa_result =
57cc36ccd1SDavid Schultz #endif
58cc36ccd1SDavid Schultz 		(char *)(r+1);
59cc36ccd1SDavid Schultz 	}
60cc36ccd1SDavid Schultz 
61cc36ccd1SDavid Schultz  char *
62cc36ccd1SDavid Schultz #ifdef KR_headers
nrv_alloc(s,rve,n)63cc36ccd1SDavid Schultz nrv_alloc(s, rve, n) char *s, **rve; int n;
64cc36ccd1SDavid Schultz #else
65cc36ccd1SDavid Schultz nrv_alloc(char *s, char **rve, int n)
66cc36ccd1SDavid Schultz #endif
67cc36ccd1SDavid Schultz {
68cc36ccd1SDavid Schultz 	char *rv, *t;
69cc36ccd1SDavid Schultz 
70cc36ccd1SDavid Schultz 	t = rv = rv_alloc(n);
71cc36ccd1SDavid Schultz 	while((*t = *s++) !=0)
72cc36ccd1SDavid Schultz 		t++;
73cc36ccd1SDavid Schultz 	if (rve)
74cc36ccd1SDavid Schultz 		*rve = t;
75cc36ccd1SDavid Schultz 	return rv;
76cc36ccd1SDavid Schultz 	}
77cc36ccd1SDavid Schultz 
78cc36ccd1SDavid Schultz /* freedtoa(s) must be used to free values s returned by dtoa
79cc36ccd1SDavid Schultz  * when MULTIPLE_THREADS is #defined.  It should be used in all cases,
80cc36ccd1SDavid Schultz  * but for consistency with earlier versions of dtoa, it is optional
81cc36ccd1SDavid Schultz  * when MULTIPLE_THREADS is not defined.
82cc36ccd1SDavid Schultz  */
83cc36ccd1SDavid Schultz 
84cc36ccd1SDavid Schultz  void
85cc36ccd1SDavid Schultz #ifdef KR_headers
freedtoa(s)86cc36ccd1SDavid Schultz freedtoa(s) char *s;
87cc36ccd1SDavid Schultz #else
88cc36ccd1SDavid Schultz freedtoa(char *s)
89cc36ccd1SDavid Schultz #endif
90cc36ccd1SDavid Schultz {
91cc36ccd1SDavid Schultz 	Bigint *b = (Bigint *)((int *)s - 1);
92cc36ccd1SDavid Schultz 	b->maxwds = 1 << (b->k = *(int*)b);
93cc36ccd1SDavid Schultz 	Bfree(b);
94cc36ccd1SDavid Schultz #ifndef MULTIPLE_THREADS
95cc36ccd1SDavid Schultz 	if (s == dtoa_result)
96cc36ccd1SDavid Schultz 		dtoa_result = 0;
97cc36ccd1SDavid Schultz #endif
98cc36ccd1SDavid Schultz 	}
99cc36ccd1SDavid Schultz 
100cc36ccd1SDavid Schultz  int
quorem(b,S)101cc36ccd1SDavid Schultz quorem
102cc36ccd1SDavid Schultz #ifdef KR_headers
103cc36ccd1SDavid Schultz 	(b, S) Bigint *b, *S;
104cc36ccd1SDavid Schultz #else
105cc36ccd1SDavid Schultz 	(Bigint *b, Bigint *S)
106cc36ccd1SDavid Schultz #endif
107cc36ccd1SDavid Schultz {
108cc36ccd1SDavid Schultz 	int n;
109cc36ccd1SDavid Schultz 	ULong *bx, *bxe, q, *sx, *sxe;
110cc36ccd1SDavid Schultz #ifdef ULLong
111cc36ccd1SDavid Schultz 	ULLong borrow, carry, y, ys;
112cc36ccd1SDavid Schultz #else
113cc36ccd1SDavid Schultz 	ULong borrow, carry, y, ys;
114cc36ccd1SDavid Schultz #ifdef Pack_32
115cc36ccd1SDavid Schultz 	ULong si, z, zs;
116cc36ccd1SDavid Schultz #endif
117cc36ccd1SDavid Schultz #endif
118cc36ccd1SDavid Schultz 
119cc36ccd1SDavid Schultz 	n = S->wds;
120cc36ccd1SDavid Schultz #ifdef DEBUG
121cc36ccd1SDavid Schultz 	/*debug*/ if (b->wds > n)
122cc36ccd1SDavid Schultz 	/*debug*/	Bug("oversize b in quorem");
123cc36ccd1SDavid Schultz #endif
124cc36ccd1SDavid Schultz 	if (b->wds < n)
125cc36ccd1SDavid Schultz 		return 0;
126cc36ccd1SDavid Schultz 	sx = S->x;
127cc36ccd1SDavid Schultz 	sxe = sx + --n;
128cc36ccd1SDavid Schultz 	bx = b->x;
129cc36ccd1SDavid Schultz 	bxe = bx + n;
130cc36ccd1SDavid Schultz 	q = *bxe / (*sxe + 1);	/* ensure q <= true quotient */
131cc36ccd1SDavid Schultz #ifdef DEBUG
132cc36ccd1SDavid Schultz 	/*debug*/ if (q > 9)
133cc36ccd1SDavid Schultz 	/*debug*/	Bug("oversized quotient in quorem");
134cc36ccd1SDavid Schultz #endif
135cc36ccd1SDavid Schultz 	if (q) {
136cc36ccd1SDavid Schultz 		borrow = 0;
137cc36ccd1SDavid Schultz 		carry = 0;
138cc36ccd1SDavid Schultz 		do {
139cc36ccd1SDavid Schultz #ifdef ULLong
140cc36ccd1SDavid Schultz 			ys = *sx++ * (ULLong)q + carry;
141cc36ccd1SDavid Schultz 			carry = ys >> 32;
142cc36ccd1SDavid Schultz 			y = *bx - (ys & 0xffffffffUL) - borrow;
143cc36ccd1SDavid Schultz 			borrow = y >> 32 & 1UL;
144cc36ccd1SDavid Schultz 			*bx++ = y & 0xffffffffUL;
145cc36ccd1SDavid Schultz #else
146cc36ccd1SDavid Schultz #ifdef Pack_32
147cc36ccd1SDavid Schultz 			si = *sx++;
148cc36ccd1SDavid Schultz 			ys = (si & 0xffff) * q + carry;
149cc36ccd1SDavid Schultz 			zs = (si >> 16) * q + (ys >> 16);
150cc36ccd1SDavid Schultz 			carry = zs >> 16;
151cc36ccd1SDavid Schultz 			y = (*bx & 0xffff) - (ys & 0xffff) - borrow;
152cc36ccd1SDavid Schultz 			borrow = (y & 0x10000) >> 16;
153cc36ccd1SDavid Schultz 			z = (*bx >> 16) - (zs & 0xffff) - borrow;
154cc36ccd1SDavid Schultz 			borrow = (z & 0x10000) >> 16;
155cc36ccd1SDavid Schultz 			Storeinc(bx, z, y);
156cc36ccd1SDavid Schultz #else
157cc36ccd1SDavid Schultz 			ys = *sx++ * q + carry;
158cc36ccd1SDavid Schultz 			carry = ys >> 16;
159cc36ccd1SDavid Schultz 			y = *bx - (ys & 0xffff) - borrow;
160cc36ccd1SDavid Schultz 			borrow = (y & 0x10000) >> 16;
161cc36ccd1SDavid Schultz 			*bx++ = y & 0xffff;
162cc36ccd1SDavid Schultz #endif
163cc36ccd1SDavid Schultz #endif
164cc36ccd1SDavid Schultz 			}
165cc36ccd1SDavid Schultz 			while(sx <= sxe);
166cc36ccd1SDavid Schultz 		if (!*bxe) {
167cc36ccd1SDavid Schultz 			bx = b->x;
168cc36ccd1SDavid Schultz 			while(--bxe > bx && !*bxe)
169cc36ccd1SDavid Schultz 				--n;
170cc36ccd1SDavid Schultz 			b->wds = n;
171cc36ccd1SDavid Schultz 			}
172cc36ccd1SDavid Schultz 		}
173cc36ccd1SDavid Schultz 	if (cmp(b, S) >= 0) {
174cc36ccd1SDavid Schultz 		q++;
175cc36ccd1SDavid Schultz 		borrow = 0;
176cc36ccd1SDavid Schultz 		carry = 0;
177cc36ccd1SDavid Schultz 		bx = b->x;
178cc36ccd1SDavid Schultz 		sx = S->x;
179cc36ccd1SDavid Schultz 		do {
180cc36ccd1SDavid Schultz #ifdef ULLong
181cc36ccd1SDavid Schultz 			ys = *sx++ + carry;
182cc36ccd1SDavid Schultz 			carry = ys >> 32;
183cc36ccd1SDavid Schultz 			y = *bx - (ys & 0xffffffffUL) - borrow;
184cc36ccd1SDavid Schultz 			borrow = y >> 32 & 1UL;
185cc36ccd1SDavid Schultz 			*bx++ = y & 0xffffffffUL;
186cc36ccd1SDavid Schultz #else
187cc36ccd1SDavid Schultz #ifdef Pack_32
188cc36ccd1SDavid Schultz 			si = *sx++;
189cc36ccd1SDavid Schultz 			ys = (si & 0xffff) + carry;
190cc36ccd1SDavid Schultz 			zs = (si >> 16) + (ys >> 16);
191cc36ccd1SDavid Schultz 			carry = zs >> 16;
192cc36ccd1SDavid Schultz 			y = (*bx & 0xffff) - (ys & 0xffff) - borrow;
193cc36ccd1SDavid Schultz 			borrow = (y & 0x10000) >> 16;
194cc36ccd1SDavid Schultz 			z = (*bx >> 16) - (zs & 0xffff) - borrow;
195cc36ccd1SDavid Schultz 			borrow = (z & 0x10000) >> 16;
196cc36ccd1SDavid Schultz 			Storeinc(bx, z, y);
197cc36ccd1SDavid Schultz #else
198cc36ccd1SDavid Schultz 			ys = *sx++ + carry;
199cc36ccd1SDavid Schultz 			carry = ys >> 16;
200cc36ccd1SDavid Schultz 			y = *bx - (ys & 0xffff) - borrow;
201cc36ccd1SDavid Schultz 			borrow = (y & 0x10000) >> 16;
202cc36ccd1SDavid Schultz 			*bx++ = y & 0xffff;
203cc36ccd1SDavid Schultz #endif
204cc36ccd1SDavid Schultz #endif
205cc36ccd1SDavid Schultz 			}
206cc36ccd1SDavid Schultz 			while(sx <= sxe);
207cc36ccd1SDavid Schultz 		bx = b->x;
208cc36ccd1SDavid Schultz 		bxe = bx + n;
209cc36ccd1SDavid Schultz 		if (!*bxe) {
210cc36ccd1SDavid Schultz 			while(--bxe > bx && !*bxe)
211cc36ccd1SDavid Schultz 				--n;
212cc36ccd1SDavid Schultz 			b->wds = n;
213cc36ccd1SDavid Schultz 			}
214cc36ccd1SDavid Schultz 		}
215cc36ccd1SDavid Schultz 	return q;
216cc36ccd1SDavid Schultz 	}
217