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