xref: /freebsd/contrib/gdtoa/strtodg.c (revision 8fa0b743820f61c661ba5f3ea0e3be0dc137910e)
1cc36ccd1SDavid Schultz /****************************************************************
2cc36ccd1SDavid Schultz 
3cc36ccd1SDavid Schultz The author of this software is David M. Gay.
4cc36ccd1SDavid Schultz 
5cc36ccd1SDavid Schultz Copyright (C) 1998-2001 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 #ifdef USE_LOCALE
35cc36ccd1SDavid Schultz #include "locale.h"
36cc36ccd1SDavid Schultz #endif
37cc36ccd1SDavid Schultz 
38cc36ccd1SDavid Schultz  static CONST int
39cc36ccd1SDavid Schultz fivesbits[] = {	 0,  3,  5,  7, 10, 12, 14, 17, 19, 21,
40cc36ccd1SDavid Schultz 		24, 26, 28, 31, 33, 35, 38, 40, 42, 45,
41cc36ccd1SDavid Schultz 		47, 49, 52
42cc36ccd1SDavid Schultz #ifdef VAX
43cc36ccd1SDavid Schultz 		, 54, 56
44cc36ccd1SDavid Schultz #endif
45cc36ccd1SDavid Schultz 		};
46cc36ccd1SDavid Schultz 
47cc36ccd1SDavid Schultz  Bigint *
48cc36ccd1SDavid Schultz #ifdef KR_headers
increment(b)49cc36ccd1SDavid Schultz increment(b) Bigint *b;
50cc36ccd1SDavid Schultz #else
51cc36ccd1SDavid Schultz increment(Bigint *b)
52cc36ccd1SDavid Schultz #endif
53cc36ccd1SDavid Schultz {
54cc36ccd1SDavid Schultz 	ULong *x, *xe;
55cc36ccd1SDavid Schultz 	Bigint *b1;
56cc36ccd1SDavid Schultz #ifdef Pack_16
57cc36ccd1SDavid Schultz 	ULong carry = 1, y;
58cc36ccd1SDavid Schultz #endif
59cc36ccd1SDavid Schultz 
60cc36ccd1SDavid Schultz 	x = b->x;
61cc36ccd1SDavid Schultz 	xe = x + b->wds;
62cc36ccd1SDavid Schultz #ifdef Pack_32
63cc36ccd1SDavid Schultz 	do {
64cc36ccd1SDavid Schultz 		if (*x < (ULong)0xffffffffL) {
65cc36ccd1SDavid Schultz 			++*x;
66cc36ccd1SDavid Schultz 			return b;
67cc36ccd1SDavid Schultz 			}
68cc36ccd1SDavid Schultz 		*x++ = 0;
69cc36ccd1SDavid Schultz 		} while(x < xe);
70cc36ccd1SDavid Schultz #else
71cc36ccd1SDavid Schultz 	do {
72cc36ccd1SDavid Schultz 		y = *x + carry;
73cc36ccd1SDavid Schultz 		carry = y >> 16;
74cc36ccd1SDavid Schultz 		*x++ = y & 0xffff;
75cc36ccd1SDavid Schultz 		if (!carry)
76cc36ccd1SDavid Schultz 			return b;
77cc36ccd1SDavid Schultz 		} while(x < xe);
78cc36ccd1SDavid Schultz 	if (carry)
79cc36ccd1SDavid Schultz #endif
80cc36ccd1SDavid Schultz 	{
81cc36ccd1SDavid Schultz 		if (b->wds >= b->maxwds) {
82cc36ccd1SDavid Schultz 			b1 = Balloc(b->k+1);
83cc36ccd1SDavid Schultz 			Bcopy(b1,b);
84cc36ccd1SDavid Schultz 			Bfree(b);
85cc36ccd1SDavid Schultz 			b = b1;
86cc36ccd1SDavid Schultz 			}
87cc36ccd1SDavid Schultz 		b->x[b->wds++] = 1;
88cc36ccd1SDavid Schultz 		}
89cc36ccd1SDavid Schultz 	return b;
90cc36ccd1SDavid Schultz 	}
91cc36ccd1SDavid Schultz 
92ae2cbf4cSDavid Schultz  void
93cc36ccd1SDavid Schultz #ifdef KR_headers
decrement(b)94cc36ccd1SDavid Schultz decrement(b) Bigint *b;
95cc36ccd1SDavid Schultz #else
96cc36ccd1SDavid Schultz decrement(Bigint *b)
97cc36ccd1SDavid Schultz #endif
98cc36ccd1SDavid Schultz {
99cc36ccd1SDavid Schultz 	ULong *x, *xe;
100cc36ccd1SDavid Schultz #ifdef Pack_16
101cc36ccd1SDavid Schultz 	ULong borrow = 1, y;
102cc36ccd1SDavid Schultz #endif
103cc36ccd1SDavid Schultz 
104cc36ccd1SDavid Schultz 	x = b->x;
105cc36ccd1SDavid Schultz 	xe = x + b->wds;
106cc36ccd1SDavid Schultz #ifdef Pack_32
107cc36ccd1SDavid Schultz 	do {
108cc36ccd1SDavid Schultz 		if (*x) {
109cc36ccd1SDavid Schultz 			--*x;
110cc36ccd1SDavid Schultz 			break;
111cc36ccd1SDavid Schultz 			}
112cc36ccd1SDavid Schultz 		*x++ = 0xffffffffL;
113cc36ccd1SDavid Schultz 		}
114cc36ccd1SDavid Schultz 		while(x < xe);
115cc36ccd1SDavid Schultz #else
116cc36ccd1SDavid Schultz 	do {
117cc36ccd1SDavid Schultz 		y = *x - borrow;
118cc36ccd1SDavid Schultz 		borrow = (y & 0x10000) >> 16;
119cc36ccd1SDavid Schultz 		*x++ = y & 0xffff;
120cc36ccd1SDavid Schultz 		} while(borrow && x < xe);
121cc36ccd1SDavid Schultz #endif
122cc36ccd1SDavid Schultz 	}
123cc36ccd1SDavid Schultz 
124cc36ccd1SDavid Schultz  static int
125cc36ccd1SDavid Schultz #ifdef KR_headers
all_on(b,n)126cc36ccd1SDavid Schultz all_on(b, n) Bigint *b; int n;
127cc36ccd1SDavid Schultz #else
128cc36ccd1SDavid Schultz all_on(Bigint *b, int n)
129cc36ccd1SDavid Schultz #endif
130cc36ccd1SDavid Schultz {
131cc36ccd1SDavid Schultz 	ULong *x, *xe;
132cc36ccd1SDavid Schultz 
133cc36ccd1SDavid Schultz 	x = b->x;
134cc36ccd1SDavid Schultz 	xe = x + (n >> kshift);
135cc36ccd1SDavid Schultz 	while(x < xe)
136cc36ccd1SDavid Schultz 		if ((*x++ & ALL_ON) != ALL_ON)
137cc36ccd1SDavid Schultz 			return 0;
138cc36ccd1SDavid Schultz 	if (n &= kmask)
139cc36ccd1SDavid Schultz 		return ((*x | (ALL_ON << n)) & ALL_ON) == ALL_ON;
140cc36ccd1SDavid Schultz 	return 1;
141cc36ccd1SDavid Schultz 	}
142cc36ccd1SDavid Schultz 
143cc36ccd1SDavid Schultz  Bigint *
144cc36ccd1SDavid Schultz #ifdef KR_headers
set_ones(b,n)145cc36ccd1SDavid Schultz set_ones(b, n) Bigint *b; int n;
146cc36ccd1SDavid Schultz #else
147cc36ccd1SDavid Schultz set_ones(Bigint *b, int n)
148cc36ccd1SDavid Schultz #endif
149cc36ccd1SDavid Schultz {
150cc36ccd1SDavid Schultz 	int k;
151cc36ccd1SDavid Schultz 	ULong *x, *xe;
152cc36ccd1SDavid Schultz 
153cc36ccd1SDavid Schultz 	k = (n + ((1 << kshift) - 1)) >> kshift;
154cc36ccd1SDavid Schultz 	if (b->k < k) {
155cc36ccd1SDavid Schultz 		Bfree(b);
156cc36ccd1SDavid Schultz 		b = Balloc(k);
157cc36ccd1SDavid Schultz 		}
158cc36ccd1SDavid Schultz 	k = n >> kshift;
159cc36ccd1SDavid Schultz 	if (n &= kmask)
160cc36ccd1SDavid Schultz 		k++;
161cc36ccd1SDavid Schultz 	b->wds = k;
162cc36ccd1SDavid Schultz 	x = b->x;
163cc36ccd1SDavid Schultz 	xe = x + k;
164cc36ccd1SDavid Schultz 	while(x < xe)
165cc36ccd1SDavid Schultz 		*x++ = ALL_ON;
166cc36ccd1SDavid Schultz 	if (n)
167cc36ccd1SDavid Schultz 		x[-1] >>= ULbits - n;
168cc36ccd1SDavid Schultz 	return b;
169cc36ccd1SDavid Schultz 	}
170cc36ccd1SDavid Schultz 
171cc36ccd1SDavid Schultz  static int
rvOK(d,fpi,exp,bits,exact,rd,irv)172cc36ccd1SDavid Schultz rvOK
173cc36ccd1SDavid Schultz #ifdef KR_headers
174cc36ccd1SDavid Schultz  (d, fpi, exp, bits, exact, rd, irv)
17550dad48bSDavid Schultz  U *d; FPI *fpi; Long *exp; ULong *bits; int exact, rd, *irv;
176cc36ccd1SDavid Schultz #else
17750dad48bSDavid Schultz  (U *d, FPI *fpi, Long *exp, ULong *bits, int exact, int rd, int *irv)
178cc36ccd1SDavid Schultz #endif
179cc36ccd1SDavid Schultz {
180cc36ccd1SDavid Schultz 	Bigint *b;
181cc36ccd1SDavid Schultz 	ULong carry, inex, lostbits;
182cc36ccd1SDavid Schultz 	int bdif, e, j, k, k1, nb, rv;
183cc36ccd1SDavid Schultz 
184cc36ccd1SDavid Schultz 	carry = rv = 0;
18550dad48bSDavid Schultz 	b = d2b(dval(d), &e, &bdif);
186cc36ccd1SDavid Schultz 	bdif -= nb = fpi->nbits;
187cc36ccd1SDavid Schultz 	e += bdif;
188cc36ccd1SDavid Schultz 	if (bdif <= 0) {
189cc36ccd1SDavid Schultz 		if (exact)
190cc36ccd1SDavid Schultz 			goto trunc;
191cc36ccd1SDavid Schultz 		goto ret;
192cc36ccd1SDavid Schultz 		}
193cc36ccd1SDavid Schultz 	if (P == nb) {
194cc36ccd1SDavid Schultz 		if (
195cc36ccd1SDavid Schultz #ifndef IMPRECISE_INEXACT
196cc36ccd1SDavid Schultz 			exact &&
197cc36ccd1SDavid Schultz #endif
198cc36ccd1SDavid Schultz 			fpi->rounding ==
199cc36ccd1SDavid Schultz #ifdef RND_PRODQUOT
200cc36ccd1SDavid Schultz 					FPI_Round_near
201cc36ccd1SDavid Schultz #else
202cc36ccd1SDavid Schultz 					Flt_Rounds
203cc36ccd1SDavid Schultz #endif
204cc36ccd1SDavid Schultz 			) goto trunc;
205cc36ccd1SDavid Schultz 		goto ret;
206cc36ccd1SDavid Schultz 		}
207cc36ccd1SDavid Schultz 	switch(rd) {
208ae2cbf4cSDavid Schultz 	  case 1: /* round down (toward -Infinity) */
209cc36ccd1SDavid Schultz 		goto trunc;
210ae2cbf4cSDavid Schultz 	  case 2: /* round up (toward +Infinity) */
211cc36ccd1SDavid Schultz 		break;
212cc36ccd1SDavid Schultz 	  default: /* round near */
213cc36ccd1SDavid Schultz 		k = bdif - 1;
214cc36ccd1SDavid Schultz 		if (k < 0)
215cc36ccd1SDavid Schultz 			goto trunc;
216cc36ccd1SDavid Schultz 		if (!k) {
217cc36ccd1SDavid Schultz 			if (!exact)
218cc36ccd1SDavid Schultz 				goto ret;
219cc36ccd1SDavid Schultz 			if (b->x[0] & 2)
220cc36ccd1SDavid Schultz 				break;
221cc36ccd1SDavid Schultz 			goto trunc;
222cc36ccd1SDavid Schultz 			}
223cc36ccd1SDavid Schultz 		if (b->x[k>>kshift] & ((ULong)1 << (k & kmask)))
224cc36ccd1SDavid Schultz 			break;
225cc36ccd1SDavid Schultz 		goto trunc;
226cc36ccd1SDavid Schultz 	  }
227cc36ccd1SDavid Schultz 	/* "break" cases: round up 1 bit, then truncate; bdif > 0 */
228cc36ccd1SDavid Schultz 	carry = 1;
229cc36ccd1SDavid Schultz  trunc:
230cc36ccd1SDavid Schultz 	inex = lostbits = 0;
231cc36ccd1SDavid Schultz 	if (bdif > 0) {
232cc36ccd1SDavid Schultz 		if ( (lostbits = any_on(b, bdif)) !=0)
233cc36ccd1SDavid Schultz 			inex = STRTOG_Inexlo;
234cc36ccd1SDavid Schultz 		rshift(b, bdif);
235cc36ccd1SDavid Schultz 		if (carry) {
236cc36ccd1SDavid Schultz 			inex = STRTOG_Inexhi;
237cc36ccd1SDavid Schultz 			b = increment(b);
238cc36ccd1SDavid Schultz 			if ( (j = nb & kmask) !=0)
239c88250a5SDavid Schultz 				j = ULbits - j;
240cc36ccd1SDavid Schultz 			if (hi0bits(b->x[b->wds - 1]) != j) {
241cc36ccd1SDavid Schultz 				if (!lostbits)
242cc36ccd1SDavid Schultz 					lostbits = b->x[0] & 1;
243cc36ccd1SDavid Schultz 				rshift(b, 1);
244cc36ccd1SDavid Schultz 				e++;
245cc36ccd1SDavid Schultz 				}
246cc36ccd1SDavid Schultz 			}
247cc36ccd1SDavid Schultz 		}
248cc36ccd1SDavid Schultz 	else if (bdif < 0)
249cc36ccd1SDavid Schultz 		b = lshift(b, -bdif);
250cc36ccd1SDavid Schultz 	if (e < fpi->emin) {
251cc36ccd1SDavid Schultz 		k = fpi->emin - e;
252cc36ccd1SDavid Schultz 		e = fpi->emin;
253cc36ccd1SDavid Schultz 		if (k > nb || fpi->sudden_underflow) {
254cc36ccd1SDavid Schultz 			b->wds = inex = 0;
255cc36ccd1SDavid Schultz 			*irv = STRTOG_Underflow | STRTOG_Inexlo;
256cc36ccd1SDavid Schultz 			}
257cc36ccd1SDavid Schultz 		else {
258cc36ccd1SDavid Schultz 			k1 = k - 1;
259cc36ccd1SDavid Schultz 			if (k1 > 0 && !lostbits)
260cc36ccd1SDavid Schultz 				lostbits = any_on(b, k1);
261cc36ccd1SDavid Schultz 			if (!lostbits && !exact)
262cc36ccd1SDavid Schultz 				goto ret;
263cc36ccd1SDavid Schultz 			lostbits |=
264cc36ccd1SDavid Schultz 			  carry = b->x[k1>>kshift] & (1 << (k1 & kmask));
265cc36ccd1SDavid Schultz 			rshift(b, k);
266cc36ccd1SDavid Schultz 			*irv = STRTOG_Denormal;
267cc36ccd1SDavid Schultz 			if (carry) {
268cc36ccd1SDavid Schultz 				b = increment(b);
269cc36ccd1SDavid Schultz 				inex = STRTOG_Inexhi | STRTOG_Underflow;
270cc36ccd1SDavid Schultz 				}
271cc36ccd1SDavid Schultz 			else if (lostbits)
272cc36ccd1SDavid Schultz 				inex = STRTOG_Inexlo | STRTOG_Underflow;
273cc36ccd1SDavid Schultz 			}
274cc36ccd1SDavid Schultz 		}
275cc36ccd1SDavid Schultz 	else if (e > fpi->emax) {
276cc36ccd1SDavid Schultz 		e = fpi->emax + 1;
277cc36ccd1SDavid Schultz 		*irv = STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
278cc36ccd1SDavid Schultz #ifndef NO_ERRNO
279cc36ccd1SDavid Schultz 		errno = ERANGE;
280cc36ccd1SDavid Schultz #endif
281cc36ccd1SDavid Schultz 		b->wds = inex = 0;
282cc36ccd1SDavid Schultz 		}
283cc36ccd1SDavid Schultz 	*exp = e;
284cc36ccd1SDavid Schultz 	copybits(bits, nb, b);
285cc36ccd1SDavid Schultz 	*irv |= inex;
286cc36ccd1SDavid Schultz 	rv = 1;
287cc36ccd1SDavid Schultz  ret:
288cc36ccd1SDavid Schultz 	Bfree(b);
289cc36ccd1SDavid Schultz 	return rv;
290cc36ccd1SDavid Schultz 	}
291cc36ccd1SDavid Schultz 
292cc36ccd1SDavid Schultz  static int
293cc36ccd1SDavid Schultz #ifdef KR_headers
mantbits(d)29450dad48bSDavid Schultz mantbits(d) U *d;
295cc36ccd1SDavid Schultz #else
29650dad48bSDavid Schultz mantbits(U *d)
297cc36ccd1SDavid Schultz #endif
298cc36ccd1SDavid Schultz {
299cc36ccd1SDavid Schultz 	ULong L;
300cc36ccd1SDavid Schultz #ifdef VAX
301cc36ccd1SDavid Schultz 	L = word1(d) << 16 | word1(d) >> 16;
302cc36ccd1SDavid Schultz 	if (L)
303cc36ccd1SDavid Schultz #else
304cc36ccd1SDavid Schultz 	if ( (L = word1(d)) !=0)
305cc36ccd1SDavid Schultz #endif
306cc36ccd1SDavid Schultz 		return P - lo0bits(&L);
307cc36ccd1SDavid Schultz #ifdef VAX
308cc36ccd1SDavid Schultz 	L = word0(d) << 16 | word0(d) >> 16 | Exp_msk11;
309cc36ccd1SDavid Schultz #else
310cc36ccd1SDavid Schultz 	L = word0(d) | Exp_msk1;
311cc36ccd1SDavid Schultz #endif
312cc36ccd1SDavid Schultz 	return P - 32 - lo0bits(&L);
313cc36ccd1SDavid Schultz 	}
314cc36ccd1SDavid Schultz 
315cc36ccd1SDavid Schultz  int
strtodg_l(s00,se,fpi,exp,bits,loc)316*3c87aa1dSDavid Chisnall strtodg_l
317cc36ccd1SDavid Schultz #ifdef KR_headers
318*3c87aa1dSDavid Chisnall 	(s00, se, fpi, exp, bits, loc)
319*3c87aa1dSDavid Chisnall 	CONST char *s00; char **se; FPI *fpi; Long *exp; ULong *bits; locale_t loc;
320cc36ccd1SDavid Schultz #else
321*3c87aa1dSDavid Chisnall 	(CONST char *s00, char **se, FPI *fpi, Long *exp, ULong *bits, locale_t loc)
322cc36ccd1SDavid Schultz #endif
323cc36ccd1SDavid Schultz {
324cc36ccd1SDavid Schultz 	int abe, abits, asub;
325c88250a5SDavid Schultz 	int bb0, bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, decpt, denorm;
326c88250a5SDavid Schultz 	int dsign, e, e1, e2, emin, esign, finished, i, inex, irv;
327cc36ccd1SDavid Schultz 	int j, k, nbits, nd, nd0, nf, nz, nz0, rd, rvbits, rve, rve1, sign;
328cc36ccd1SDavid Schultz 	int sudden_underflow;
329cc36ccd1SDavid Schultz 	CONST char *s, *s0, *s1;
33050dad48bSDavid Schultz 	double adj0, tol;
331cc36ccd1SDavid Schultz 	Long L;
33250dad48bSDavid Schultz 	U adj, rv;
333ae2cbf4cSDavid Schultz 	ULong *b, *be, y, z;
334cc36ccd1SDavid Schultz 	Bigint *ab, *bb, *bb1, *bd, *bd0, *bs, *delta, *rvb, *rvb0;
3354848dd08SDavid Schultz #ifdef USE_LOCALE /*{{*/
3364848dd08SDavid Schultz #ifdef NO_LOCALE_CACHE
337*3c87aa1dSDavid Chisnall 	char *decimalpoint = localeconv_l(loc)->decimal_point;
3384848dd08SDavid Schultz 	int dplen = strlen(decimalpoint);
3394848dd08SDavid Schultz #else
3404848dd08SDavid Schultz 	char *decimalpoint;
3414848dd08SDavid Schultz 	static char *decimalpoint_cache;
3424848dd08SDavid Schultz 	static int dplen;
3434848dd08SDavid Schultz 	if (!(s0 = decimalpoint_cache)) {
344*3c87aa1dSDavid Chisnall 		s0 = localeconv_l(loc)->decimal_point;
34550dad48bSDavid Schultz 		if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) {
3464848dd08SDavid Schultz 			strcpy(decimalpoint_cache, s0);
3474848dd08SDavid Schultz 			s0 = decimalpoint_cache;
3484848dd08SDavid Schultz 			}
3494848dd08SDavid Schultz 		dplen = strlen(s0);
3504848dd08SDavid Schultz 		}
3514848dd08SDavid Schultz 	decimalpoint = (char*)s0;
3524848dd08SDavid Schultz #endif /*NO_LOCALE_CACHE*/
3534848dd08SDavid Schultz #else  /*USE_LOCALE}{*/
3544848dd08SDavid Schultz #define dplen 1
3554848dd08SDavid Schultz #endif /*USE_LOCALE}}*/
356cc36ccd1SDavid Schultz 
357cc36ccd1SDavid Schultz 	irv = STRTOG_Zero;
358cc36ccd1SDavid Schultz 	denorm = sign = nz0 = nz = 0;
35950dad48bSDavid Schultz 	dval(&rv) = 0.;
360cc36ccd1SDavid Schultz 	rvb = 0;
361cc36ccd1SDavid Schultz 	nbits = fpi->nbits;
362cc36ccd1SDavid Schultz 	for(s = s00;;s++) switch(*s) {
363cc36ccd1SDavid Schultz 		case '-':
364cc36ccd1SDavid Schultz 			sign = 1;
365cc36ccd1SDavid Schultz 			/* no break */
366cc36ccd1SDavid Schultz 		case '+':
367cc36ccd1SDavid Schultz 			if (*++s)
368cc36ccd1SDavid Schultz 				goto break2;
369cc36ccd1SDavid Schultz 			/* no break */
370cc36ccd1SDavid Schultz 		case 0:
371cc36ccd1SDavid Schultz 			sign = 0;
372cc36ccd1SDavid Schultz 			irv = STRTOG_NoNumber;
373cc36ccd1SDavid Schultz 			s = s00;
374cc36ccd1SDavid Schultz 			goto ret;
375cc36ccd1SDavid Schultz 		case '\t':
376cc36ccd1SDavid Schultz 		case '\n':
377cc36ccd1SDavid Schultz 		case '\v':
378cc36ccd1SDavid Schultz 		case '\f':
379cc36ccd1SDavid Schultz 		case '\r':
380cc36ccd1SDavid Schultz 		case ' ':
381cc36ccd1SDavid Schultz 			continue;
382cc36ccd1SDavid Schultz 		default:
383cc36ccd1SDavid Schultz 			goto break2;
384cc36ccd1SDavid Schultz 		}
385cc36ccd1SDavid Schultz  break2:
386cc36ccd1SDavid Schultz 	if (*s == '0') {
387cc36ccd1SDavid Schultz #ifndef NO_HEX_FP
388cc36ccd1SDavid Schultz 		switch(s[1]) {
389cc36ccd1SDavid Schultz 		  case 'x':
390cc36ccd1SDavid Schultz 		  case 'X':
391cc36ccd1SDavid Schultz 			irv = gethex(&s, fpi, exp, &rvb, sign);
392cc36ccd1SDavid Schultz 			if (irv == STRTOG_NoNumber) {
393cc36ccd1SDavid Schultz 				s = s00;
394cc36ccd1SDavid Schultz 				sign = 0;
395cc36ccd1SDavid Schultz 				}
396cc36ccd1SDavid Schultz 			goto ret;
397cc36ccd1SDavid Schultz 		  }
398cc36ccd1SDavid Schultz #endif
399cc36ccd1SDavid Schultz 		nz0 = 1;
400cc36ccd1SDavid Schultz 		while(*++s == '0') ;
401cc36ccd1SDavid Schultz 		if (!*s)
402cc36ccd1SDavid Schultz 			goto ret;
403cc36ccd1SDavid Schultz 		}
404cc36ccd1SDavid Schultz 	sudden_underflow = fpi->sudden_underflow;
405cc36ccd1SDavid Schultz 	s0 = s;
406cc36ccd1SDavid Schultz 	y = z = 0;
407c88250a5SDavid Schultz 	for(decpt = nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++)
408cc36ccd1SDavid Schultz 		if (nd < 9)
409cc36ccd1SDavid Schultz 			y = 10*y + c - '0';
410cc36ccd1SDavid Schultz 		else if (nd < 16)
411cc36ccd1SDavid Schultz 			z = 10*z + c - '0';
412cc36ccd1SDavid Schultz 	nd0 = nd;
413cc36ccd1SDavid Schultz #ifdef USE_LOCALE
4144848dd08SDavid Schultz 	if (c == *decimalpoint) {
4154848dd08SDavid Schultz 		for(i = 1; decimalpoint[i]; ++i)
4164848dd08SDavid Schultz 			if (s[i] != decimalpoint[i])
4174848dd08SDavid Schultz 				goto dig_done;
4184848dd08SDavid Schultz 		s += i;
4194848dd08SDavid Schultz 		c = *s;
42084781d47SDavid Schultz #else
4214848dd08SDavid Schultz 	if (c == '.') {
422cc36ccd1SDavid Schultz 		c = *++s;
4234848dd08SDavid Schultz #endif
4244848dd08SDavid Schultz 		decpt = 1;
425cc36ccd1SDavid Schultz 		if (!nd) {
426cc36ccd1SDavid Schultz 			for(; c == '0'; c = *++s)
427cc36ccd1SDavid Schultz 				nz++;
428cc36ccd1SDavid Schultz 			if (c > '0' && c <= '9') {
429cc36ccd1SDavid Schultz 				s0 = s;
430cc36ccd1SDavid Schultz 				nf += nz;
431cc36ccd1SDavid Schultz 				nz = 0;
432cc36ccd1SDavid Schultz 				goto have_dig;
433cc36ccd1SDavid Schultz 				}
434cc36ccd1SDavid Schultz 			goto dig_done;
435cc36ccd1SDavid Schultz 			}
436cc36ccd1SDavid Schultz 		for(; c >= '0' && c <= '9'; c = *++s) {
437cc36ccd1SDavid Schultz  have_dig:
438cc36ccd1SDavid Schultz 			nz++;
439cc36ccd1SDavid Schultz 			if (c -= '0') {
440cc36ccd1SDavid Schultz 				nf += nz;
441cc36ccd1SDavid Schultz 				for(i = 1; i < nz; i++)
442cc36ccd1SDavid Schultz 					if (nd++ < 9)
443cc36ccd1SDavid Schultz 						y *= 10;
444cc36ccd1SDavid Schultz 					else if (nd <= DBL_DIG + 1)
445cc36ccd1SDavid Schultz 						z *= 10;
446cc36ccd1SDavid Schultz 				if (nd++ < 9)
447cc36ccd1SDavid Schultz 					y = 10*y + c;
448cc36ccd1SDavid Schultz 				else if (nd <= DBL_DIG + 1)
449cc36ccd1SDavid Schultz 					z = 10*z + c;
450cc36ccd1SDavid Schultz 				nz = 0;
451cc36ccd1SDavid Schultz 				}
452cc36ccd1SDavid Schultz 			}
4534848dd08SDavid Schultz 		}/*}*/
454cc36ccd1SDavid Schultz  dig_done:
455cc36ccd1SDavid Schultz 	e = 0;
456cc36ccd1SDavid Schultz 	if (c == 'e' || c == 'E') {
457cc36ccd1SDavid Schultz 		if (!nd && !nz && !nz0) {
458cc36ccd1SDavid Schultz 			irv = STRTOG_NoNumber;
459cc36ccd1SDavid Schultz 			s = s00;
460cc36ccd1SDavid Schultz 			goto ret;
461cc36ccd1SDavid Schultz 			}
462cc36ccd1SDavid Schultz 		s00 = s;
463cc36ccd1SDavid Schultz 		esign = 0;
464cc36ccd1SDavid Schultz 		switch(c = *++s) {
465cc36ccd1SDavid Schultz 			case '-':
466cc36ccd1SDavid Schultz 				esign = 1;
467cc36ccd1SDavid Schultz 			case '+':
468cc36ccd1SDavid Schultz 				c = *++s;
469cc36ccd1SDavid Schultz 			}
470cc36ccd1SDavid Schultz 		if (c >= '0' && c <= '9') {
471cc36ccd1SDavid Schultz 			while(c == '0')
472cc36ccd1SDavid Schultz 				c = *++s;
473cc36ccd1SDavid Schultz 			if (c > '0' && c <= '9') {
474cc36ccd1SDavid Schultz 				L = c - '0';
475cc36ccd1SDavid Schultz 				s1 = s;
476cc36ccd1SDavid Schultz 				while((c = *++s) >= '0' && c <= '9')
477cc36ccd1SDavid Schultz 					L = 10*L + c - '0';
478cc36ccd1SDavid Schultz 				if (s - s1 > 8 || L > 19999)
479cc36ccd1SDavid Schultz 					/* Avoid confusion from exponents
480cc36ccd1SDavid Schultz 					 * so large that e might overflow.
481cc36ccd1SDavid Schultz 					 */
482cc36ccd1SDavid Schultz 					e = 19999; /* safe for 16 bit ints */
483cc36ccd1SDavid Schultz 				else
484cc36ccd1SDavid Schultz 					e = (int)L;
485cc36ccd1SDavid Schultz 				if (esign)
486cc36ccd1SDavid Schultz 					e = -e;
487cc36ccd1SDavid Schultz 				}
488cc36ccd1SDavid Schultz 			else
489cc36ccd1SDavid Schultz 				e = 0;
490cc36ccd1SDavid Schultz 			}
491cc36ccd1SDavid Schultz 		else
492cc36ccd1SDavid Schultz 			s = s00;
493cc36ccd1SDavid Schultz 		}
494cc36ccd1SDavid Schultz 	if (!nd) {
495cc36ccd1SDavid Schultz 		if (!nz && !nz0) {
496cc36ccd1SDavid Schultz #ifdef INFNAN_CHECK
497cc36ccd1SDavid Schultz 			/* Check for Nan and Infinity */
498c88250a5SDavid Schultz 			if (!decpt)
499cc36ccd1SDavid Schultz 			 switch(c) {
500cc36ccd1SDavid Schultz 			  case 'i':
501cc36ccd1SDavid Schultz 			  case 'I':
502cc36ccd1SDavid Schultz 				if (match(&s,"nf")) {
503cc36ccd1SDavid Schultz 					--s;
504cc36ccd1SDavid Schultz 					if (!match(&s,"inity"))
505cc36ccd1SDavid Schultz 						++s;
506cc36ccd1SDavid Schultz 					irv = STRTOG_Infinite;
507cc36ccd1SDavid Schultz 					goto infnanexp;
508cc36ccd1SDavid Schultz 					}
509cc36ccd1SDavid Schultz 				break;
510cc36ccd1SDavid Schultz 			  case 'n':
511cc36ccd1SDavid Schultz 			  case 'N':
512cc36ccd1SDavid Schultz 				if (match(&s, "an")) {
513cc36ccd1SDavid Schultz 					irv = STRTOG_NaN;
514cc36ccd1SDavid Schultz 					*exp = fpi->emax + 1;
515cc36ccd1SDavid Schultz #ifndef No_Hex_NaN
516cc36ccd1SDavid Schultz 					if (*s == '(') /*)*/
517cc36ccd1SDavid Schultz 						irv = hexnan(&s, fpi, bits);
518cc36ccd1SDavid Schultz #endif
519cc36ccd1SDavid Schultz 					goto infnanexp;
520cc36ccd1SDavid Schultz 					}
521cc36ccd1SDavid Schultz 			  }
522cc36ccd1SDavid Schultz #endif /* INFNAN_CHECK */
523cc36ccd1SDavid Schultz 			irv = STRTOG_NoNumber;
524cc36ccd1SDavid Schultz 			s = s00;
525cc36ccd1SDavid Schultz 			}
526cc36ccd1SDavid Schultz 		goto ret;
527cc36ccd1SDavid Schultz 		}
528cc36ccd1SDavid Schultz 
529cc36ccd1SDavid Schultz 	irv = STRTOG_Normal;
530cc36ccd1SDavid Schultz 	e1 = e -= nf;
531cc36ccd1SDavid Schultz 	rd = 0;
532cc36ccd1SDavid Schultz 	switch(fpi->rounding & 3) {
533cc36ccd1SDavid Schultz 	  case FPI_Round_up:
534cc36ccd1SDavid Schultz 		rd = 2 - sign;
535cc36ccd1SDavid Schultz 		break;
536cc36ccd1SDavid Schultz 	  case FPI_Round_zero:
537cc36ccd1SDavid Schultz 		rd = 1;
538cc36ccd1SDavid Schultz 		break;
539cc36ccd1SDavid Schultz 	  case FPI_Round_down:
540cc36ccd1SDavid Schultz 		rd = 1 + sign;
541cc36ccd1SDavid Schultz 	  }
542cc36ccd1SDavid Schultz 
543cc36ccd1SDavid Schultz 	/* Now we have nd0 digits, starting at s0, followed by a
544cc36ccd1SDavid Schultz 	 * decimal point, followed by nd-nd0 digits.  The number we're
545cc36ccd1SDavid Schultz 	 * after is the integer represented by those digits times
546cc36ccd1SDavid Schultz 	 * 10**e */
547cc36ccd1SDavid Schultz 
548cc36ccd1SDavid Schultz 	if (!nd0)
549cc36ccd1SDavid Schultz 		nd0 = nd;
550cc36ccd1SDavid Schultz 	k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
55150dad48bSDavid Schultz 	dval(&rv) = y;
552cc36ccd1SDavid Schultz 	if (k > 9)
55350dad48bSDavid Schultz 		dval(&rv) = tens[k - 9] * dval(&rv) + z;
554cc36ccd1SDavid Schultz 	bd0 = 0;
555cc36ccd1SDavid Schultz 	if (nbits <= P && nd <= DBL_DIG) {
556cc36ccd1SDavid Schultz 		if (!e) {
55750dad48bSDavid Schultz 			if (rvOK(&rv, fpi, exp, bits, 1, rd, &irv))
558cc36ccd1SDavid Schultz 				goto ret;
559cc36ccd1SDavid Schultz 			}
560cc36ccd1SDavid Schultz 		else if (e > 0) {
561cc36ccd1SDavid Schultz 			if (e <= Ten_pmax) {
562cc36ccd1SDavid Schultz #ifdef VAX
563cc36ccd1SDavid Schultz 				goto vax_ovfl_check;
564cc36ccd1SDavid Schultz #else
56550dad48bSDavid Schultz 				i = fivesbits[e] + mantbits(&rv) <= P;
56650dad48bSDavid Schultz 				/* rv = */ rounded_product(dval(&rv), tens[e]);
56750dad48bSDavid Schultz 				if (rvOK(&rv, fpi, exp, bits, i, rd, &irv))
568cc36ccd1SDavid Schultz 					goto ret;
569cc36ccd1SDavid Schultz 				e1 -= e;
570cc36ccd1SDavid Schultz 				goto rv_notOK;
571cc36ccd1SDavid Schultz #endif
572cc36ccd1SDavid Schultz 				}
573cc36ccd1SDavid Schultz 			i = DBL_DIG - nd;
574cc36ccd1SDavid Schultz 			if (e <= Ten_pmax + i) {
575cc36ccd1SDavid Schultz 				/* A fancier test would sometimes let us do
576cc36ccd1SDavid Schultz 				 * this for larger i values.
577cc36ccd1SDavid Schultz 				 */
578cc36ccd1SDavid Schultz 				e2 = e - i;
579cc36ccd1SDavid Schultz 				e1 -= i;
58050dad48bSDavid Schultz 				dval(&rv) *= tens[i];
581cc36ccd1SDavid Schultz #ifdef VAX
582cc36ccd1SDavid Schultz 				/* VAX exponent range is so narrow we must
583cc36ccd1SDavid Schultz 				 * worry about overflow here...
584cc36ccd1SDavid Schultz 				 */
585cc36ccd1SDavid Schultz  vax_ovfl_check:
58650dad48bSDavid Schultz 				dval(&adj) = dval(&rv);
58750dad48bSDavid Schultz 				word0(&adj) -= P*Exp_msk1;
58850dad48bSDavid Schultz 				/* adj = */ rounded_product(dval(&adj), tens[e2]);
58950dad48bSDavid Schultz 				if ((word0(&adj) & Exp_mask)
590cc36ccd1SDavid Schultz 				 > Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
591cc36ccd1SDavid Schultz 					goto rv_notOK;
59250dad48bSDavid Schultz 				word0(&adj) += P*Exp_msk1;
59350dad48bSDavid Schultz 				dval(&rv) = dval(&adj);
594cc36ccd1SDavid Schultz #else
59550dad48bSDavid Schultz 				/* rv = */ rounded_product(dval(&rv), tens[e2]);
596cc36ccd1SDavid Schultz #endif
59750dad48bSDavid Schultz 				if (rvOK(&rv, fpi, exp, bits, 0, rd, &irv))
598cc36ccd1SDavid Schultz 					goto ret;
599cc36ccd1SDavid Schultz 				e1 -= e2;
600cc36ccd1SDavid Schultz 				}
601cc36ccd1SDavid Schultz 			}
602cc36ccd1SDavid Schultz #ifndef Inaccurate_Divide
603cc36ccd1SDavid Schultz 		else if (e >= -Ten_pmax) {
60450dad48bSDavid Schultz 			/* rv = */ rounded_quotient(dval(&rv), tens[-e]);
60550dad48bSDavid Schultz 			if (rvOK(&rv, fpi, exp, bits, 0, rd, &irv))
606cc36ccd1SDavid Schultz 				goto ret;
607cc36ccd1SDavid Schultz 			e1 -= e;
608cc36ccd1SDavid Schultz 			}
609cc36ccd1SDavid Schultz #endif
610cc36ccd1SDavid Schultz 		}
611cc36ccd1SDavid Schultz  rv_notOK:
612cc36ccd1SDavid Schultz 	e1 += nd - k;
613cc36ccd1SDavid Schultz 
614cc36ccd1SDavid Schultz 	/* Get starting approximation = rv * 10**e1 */
615cc36ccd1SDavid Schultz 
616cc36ccd1SDavid Schultz 	e2 = 0;
617cc36ccd1SDavid Schultz 	if (e1 > 0) {
618cc36ccd1SDavid Schultz 		if ( (i = e1 & 15) !=0)
61950dad48bSDavid Schultz 			dval(&rv) *= tens[i];
620cc36ccd1SDavid Schultz 		if (e1 &= ~15) {
621cc36ccd1SDavid Schultz 			e1 >>= 4;
62250dad48bSDavid Schultz 			while(e1 >= (1 << (n_bigtens-1))) {
62350dad48bSDavid Schultz 				e2 += ((word0(&rv) & Exp_mask)
624cc36ccd1SDavid Schultz 					>> Exp_shift1) - Bias;
62550dad48bSDavid Schultz 				word0(&rv) &= ~Exp_mask;
62650dad48bSDavid Schultz 				word0(&rv) |= Bias << Exp_shift1;
62750dad48bSDavid Schultz 				dval(&rv) *= bigtens[n_bigtens-1];
62850dad48bSDavid Schultz 				e1 -= 1 << (n_bigtens-1);
629cc36ccd1SDavid Schultz 				}
63050dad48bSDavid Schultz 			e2 += ((word0(&rv) & Exp_mask) >> Exp_shift1) - Bias;
63150dad48bSDavid Schultz 			word0(&rv) &= ~Exp_mask;
63250dad48bSDavid Schultz 			word0(&rv) |= Bias << Exp_shift1;
633cc36ccd1SDavid Schultz 			for(j = 0; e1 > 0; j++, e1 >>= 1)
634cc36ccd1SDavid Schultz 				if (e1 & 1)
63550dad48bSDavid Schultz 					dval(&rv) *= bigtens[j];
636cc36ccd1SDavid Schultz 			}
637cc36ccd1SDavid Schultz 		}
638cc36ccd1SDavid Schultz 	else if (e1 < 0) {
639cc36ccd1SDavid Schultz 		e1 = -e1;
640cc36ccd1SDavid Schultz 		if ( (i = e1 & 15) !=0)
64150dad48bSDavid Schultz 			dval(&rv) /= tens[i];
642cc36ccd1SDavid Schultz 		if (e1 &= ~15) {
643cc36ccd1SDavid Schultz 			e1 >>= 4;
64450dad48bSDavid Schultz 			while(e1 >= (1 << (n_bigtens-1))) {
64550dad48bSDavid Schultz 				e2 += ((word0(&rv) & Exp_mask)
646cc36ccd1SDavid Schultz 					>> Exp_shift1) - Bias;
64750dad48bSDavid Schultz 				word0(&rv) &= ~Exp_mask;
64850dad48bSDavid Schultz 				word0(&rv) |= Bias << Exp_shift1;
64950dad48bSDavid Schultz 				dval(&rv) *= tinytens[n_bigtens-1];
65050dad48bSDavid Schultz 				e1 -= 1 << (n_bigtens-1);
651cc36ccd1SDavid Schultz 				}
65250dad48bSDavid Schultz 			e2 += ((word0(&rv) & Exp_mask) >> Exp_shift1) - Bias;
65350dad48bSDavid Schultz 			word0(&rv) &= ~Exp_mask;
65450dad48bSDavid Schultz 			word0(&rv) |= Bias << Exp_shift1;
655cc36ccd1SDavid Schultz 			for(j = 0; e1 > 0; j++, e1 >>= 1)
656cc36ccd1SDavid Schultz 				if (e1 & 1)
65750dad48bSDavid Schultz 					dval(&rv) *= tinytens[j];
658cc36ccd1SDavid Schultz 			}
659cc36ccd1SDavid Schultz 		}
660c88250a5SDavid Schultz #ifdef IBM
661c88250a5SDavid Schultz 	/* e2 is a correction to the (base 2) exponent of the return
662c88250a5SDavid Schultz 	 * value, reflecting adjustments above to avoid overflow in the
663c88250a5SDavid Schultz 	 * native arithmetic.  For native IBM (base 16) arithmetic, we
664c88250a5SDavid Schultz 	 * must multiply e2 by 4 to change from base 16 to 2.
665c88250a5SDavid Schultz 	 */
666c88250a5SDavid Schultz 	e2 <<= 2;
667c88250a5SDavid Schultz #endif
66850dad48bSDavid Schultz 	rvb = d2b(dval(&rv), &rve, &rvbits);	/* rv = rvb * 2^rve */
669cc36ccd1SDavid Schultz 	rve += e2;
670cc36ccd1SDavid Schultz 	if ((j = rvbits - nbits) > 0) {
671cc36ccd1SDavid Schultz 		rshift(rvb, j);
672cc36ccd1SDavid Schultz 		rvbits = nbits;
673cc36ccd1SDavid Schultz 		rve += j;
674cc36ccd1SDavid Schultz 		}
675cc36ccd1SDavid Schultz 	bb0 = 0;	/* trailing zero bits in rvb */
676cc36ccd1SDavid Schultz 	e2 = rve + rvbits - nbits;
677c88250a5SDavid Schultz 	if (e2 > fpi->emax + 1)
678c88250a5SDavid Schultz 		goto huge;
679cc36ccd1SDavid Schultz 	rve1 = rve + rvbits - nbits;
680cc36ccd1SDavid Schultz 	if (e2 < (emin = fpi->emin)) {
681cc36ccd1SDavid Schultz 		denorm = 1;
682cc36ccd1SDavid Schultz 		j = rve - emin;
683cc36ccd1SDavid Schultz 		if (j > 0) {
684cc36ccd1SDavid Schultz 			rvb = lshift(rvb, j);
685cc36ccd1SDavid Schultz 			rvbits += j;
686cc36ccd1SDavid Schultz 			}
687cc36ccd1SDavid Schultz 		else if (j < 0) {
688cc36ccd1SDavid Schultz 			rvbits += j;
689cc36ccd1SDavid Schultz 			if (rvbits <= 0) {
690cc36ccd1SDavid Schultz 				if (rvbits < -1) {
691cc36ccd1SDavid Schultz  ufl:
692cc36ccd1SDavid Schultz 					rvb->wds = 0;
693cc36ccd1SDavid Schultz 					rvb->x[0] = 0;
694cc36ccd1SDavid Schultz 					*exp = emin;
695cc36ccd1SDavid Schultz 					irv = STRTOG_Underflow | STRTOG_Inexlo;
696cc36ccd1SDavid Schultz 					goto ret;
697cc36ccd1SDavid Schultz 					}
698cc36ccd1SDavid Schultz 				rvb->x[0] = rvb->wds = rvbits = 1;
699cc36ccd1SDavid Schultz 				}
700cc36ccd1SDavid Schultz 			else
701cc36ccd1SDavid Schultz 				rshift(rvb, -j);
702cc36ccd1SDavid Schultz 			}
703cc36ccd1SDavid Schultz 		rve = rve1 = emin;
704cc36ccd1SDavid Schultz 		if (sudden_underflow && e2 + 1 < emin)
705cc36ccd1SDavid Schultz 			goto ufl;
706cc36ccd1SDavid Schultz 		}
707cc36ccd1SDavid Schultz 
708cc36ccd1SDavid Schultz 	/* Now the hard part -- adjusting rv to the correct value.*/
709cc36ccd1SDavid Schultz 
710cc36ccd1SDavid Schultz 	/* Put digits into bd: true value = bd * 10^e */
711cc36ccd1SDavid Schultz 
7124848dd08SDavid Schultz 	bd0 = s2b(s0, nd0, nd, y, dplen);
713cc36ccd1SDavid Schultz 
714cc36ccd1SDavid Schultz 	for(;;) {
715cc36ccd1SDavid Schultz 		bd = Balloc(bd0->k);
716cc36ccd1SDavid Schultz 		Bcopy(bd, bd0);
717cc36ccd1SDavid Schultz 		bb = Balloc(rvb->k);
718cc36ccd1SDavid Schultz 		Bcopy(bb, rvb);
719cc36ccd1SDavid Schultz 		bbbits = rvbits - bb0;
720cc36ccd1SDavid Schultz 		bbe = rve + bb0;
721cc36ccd1SDavid Schultz 		bs = i2b(1);
722cc36ccd1SDavid Schultz 
723cc36ccd1SDavid Schultz 		if (e >= 0) {
724cc36ccd1SDavid Schultz 			bb2 = bb5 = 0;
725cc36ccd1SDavid Schultz 			bd2 = bd5 = e;
726cc36ccd1SDavid Schultz 			}
727cc36ccd1SDavid Schultz 		else {
728cc36ccd1SDavid Schultz 			bb2 = bb5 = -e;
729cc36ccd1SDavid Schultz 			bd2 = bd5 = 0;
730cc36ccd1SDavid Schultz 			}
731cc36ccd1SDavid Schultz 		if (bbe >= 0)
732cc36ccd1SDavid Schultz 			bb2 += bbe;
733cc36ccd1SDavid Schultz 		else
734cc36ccd1SDavid Schultz 			bd2 -= bbe;
735cc36ccd1SDavid Schultz 		bs2 = bb2;
736cc36ccd1SDavid Schultz 		j = nbits + 1 - bbbits;
737cc36ccd1SDavid Schultz 		i = bbe + bbbits - nbits;
738cc36ccd1SDavid Schultz 		if (i < emin)	/* denormal */
739cc36ccd1SDavid Schultz 			j += i - emin;
740cc36ccd1SDavid Schultz 		bb2 += j;
741cc36ccd1SDavid Schultz 		bd2 += j;
742cc36ccd1SDavid Schultz 		i = bb2 < bd2 ? bb2 : bd2;
743cc36ccd1SDavid Schultz 		if (i > bs2)
744cc36ccd1SDavid Schultz 			i = bs2;
745cc36ccd1SDavid Schultz 		if (i > 0) {
746cc36ccd1SDavid Schultz 			bb2 -= i;
747cc36ccd1SDavid Schultz 			bd2 -= i;
748cc36ccd1SDavid Schultz 			bs2 -= i;
749cc36ccd1SDavid Schultz 			}
750cc36ccd1SDavid Schultz 		if (bb5 > 0) {
751cc36ccd1SDavid Schultz 			bs = pow5mult(bs, bb5);
752cc36ccd1SDavid Schultz 			bb1 = mult(bs, bb);
753cc36ccd1SDavid Schultz 			Bfree(bb);
754cc36ccd1SDavid Schultz 			bb = bb1;
755cc36ccd1SDavid Schultz 			}
756cc36ccd1SDavid Schultz 		bb2 -= bb0;
757cc36ccd1SDavid Schultz 		if (bb2 > 0)
758cc36ccd1SDavid Schultz 			bb = lshift(bb, bb2);
759cc36ccd1SDavid Schultz 		else if (bb2 < 0)
760cc36ccd1SDavid Schultz 			rshift(bb, -bb2);
761cc36ccd1SDavid Schultz 		if (bd5 > 0)
762cc36ccd1SDavid Schultz 			bd = pow5mult(bd, bd5);
763cc36ccd1SDavid Schultz 		if (bd2 > 0)
764cc36ccd1SDavid Schultz 			bd = lshift(bd, bd2);
765cc36ccd1SDavid Schultz 		if (bs2 > 0)
766cc36ccd1SDavid Schultz 			bs = lshift(bs, bs2);
767cc36ccd1SDavid Schultz 		asub = 1;
768cc36ccd1SDavid Schultz 		inex = STRTOG_Inexhi;
769cc36ccd1SDavid Schultz 		delta = diff(bb, bd);
770cc36ccd1SDavid Schultz 		if (delta->wds <= 1 && !delta->x[0])
771cc36ccd1SDavid Schultz 			break;
772cc36ccd1SDavid Schultz 		dsign = delta->sign;
773cc36ccd1SDavid Schultz 		delta->sign = finished = 0;
774cc36ccd1SDavid Schultz 		L = 0;
775cc36ccd1SDavid Schultz 		i = cmp(delta, bs);
776cc36ccd1SDavid Schultz 		if (rd && i <= 0) {
777cc36ccd1SDavid Schultz 			irv = STRTOG_Normal;
778cc36ccd1SDavid Schultz 			if ( (finished = dsign ^ (rd&1)) !=0) {
779cc36ccd1SDavid Schultz 				if (dsign != 0) {
780cc36ccd1SDavid Schultz 					irv |= STRTOG_Inexhi;
781cc36ccd1SDavid Schultz 					goto adj1;
782cc36ccd1SDavid Schultz 					}
783cc36ccd1SDavid Schultz 				irv |= STRTOG_Inexlo;
784cc36ccd1SDavid Schultz 				if (rve1 == emin)
785cc36ccd1SDavid Schultz 					goto adj1;
786cc36ccd1SDavid Schultz 				for(i = 0, j = nbits; j >= ULbits;
787cc36ccd1SDavid Schultz 						i++, j -= ULbits) {
788cc36ccd1SDavid Schultz 					if (rvb->x[i] & ALL_ON)
789cc36ccd1SDavid Schultz 						goto adj1;
790cc36ccd1SDavid Schultz 					}
791cc36ccd1SDavid Schultz 				if (j > 1 && lo0bits(rvb->x + i) < j - 1)
792cc36ccd1SDavid Schultz 					goto adj1;
793cc36ccd1SDavid Schultz 				rve = rve1 - 1;
794cc36ccd1SDavid Schultz 				rvb = set_ones(rvb, rvbits = nbits);
795cc36ccd1SDavid Schultz 				break;
796cc36ccd1SDavid Schultz 				}
797cc36ccd1SDavid Schultz 			irv |= dsign ? STRTOG_Inexlo : STRTOG_Inexhi;
798cc36ccd1SDavid Schultz 			break;
799cc36ccd1SDavid Schultz 			}
800cc36ccd1SDavid Schultz 		if (i < 0) {
801cc36ccd1SDavid Schultz 			/* Error is less than half an ulp -- check for
802cc36ccd1SDavid Schultz 			 * special case of mantissa a power of two.
803cc36ccd1SDavid Schultz 			 */
804cc36ccd1SDavid Schultz 			irv = dsign
805cc36ccd1SDavid Schultz 				? STRTOG_Normal | STRTOG_Inexlo
806cc36ccd1SDavid Schultz 				: STRTOG_Normal | STRTOG_Inexhi;
807cc36ccd1SDavid Schultz 			if (dsign || bbbits > 1 || denorm || rve1 == emin)
808cc36ccd1SDavid Schultz 				break;
809cc36ccd1SDavid Schultz 			delta = lshift(delta,1);
810cc36ccd1SDavid Schultz 			if (cmp(delta, bs) > 0) {
811cc36ccd1SDavid Schultz 				irv = STRTOG_Normal | STRTOG_Inexlo;
812cc36ccd1SDavid Schultz 				goto drop_down;
813cc36ccd1SDavid Schultz 				}
814cc36ccd1SDavid Schultz 			break;
815cc36ccd1SDavid Schultz 			}
816cc36ccd1SDavid Schultz 		if (i == 0) {
817cc36ccd1SDavid Schultz 			/* exactly half-way between */
818cc36ccd1SDavid Schultz 			if (dsign) {
819cc36ccd1SDavid Schultz 				if (denorm && all_on(rvb, rvbits)) {
820cc36ccd1SDavid Schultz 					/*boundary case -- increment exponent*/
821cc36ccd1SDavid Schultz 					rvb->wds = 1;
822cc36ccd1SDavid Schultz 					rvb->x[0] = 1;
823cc36ccd1SDavid Schultz 					rve = emin + nbits - (rvbits = 1);
824cc36ccd1SDavid Schultz 					irv = STRTOG_Normal | STRTOG_Inexhi;
825cc36ccd1SDavid Schultz 					denorm = 0;
826cc36ccd1SDavid Schultz 					break;
827cc36ccd1SDavid Schultz 					}
828cc36ccd1SDavid Schultz 				irv = STRTOG_Normal | STRTOG_Inexlo;
829cc36ccd1SDavid Schultz 				}
830cc36ccd1SDavid Schultz 			else if (bbbits == 1) {
831cc36ccd1SDavid Schultz 				irv = STRTOG_Normal;
832cc36ccd1SDavid Schultz  drop_down:
833cc36ccd1SDavid Schultz 				/* boundary case -- decrement exponent */
834cc36ccd1SDavid Schultz 				if (rve1 == emin) {
835cc36ccd1SDavid Schultz 					irv = STRTOG_Normal | STRTOG_Inexhi;
836cc36ccd1SDavid Schultz 					if (rvb->wds == 1 && rvb->x[0] == 1)
837cc36ccd1SDavid Schultz 						sudden_underflow = 1;
838cc36ccd1SDavid Schultz 					break;
839cc36ccd1SDavid Schultz 					}
840cc36ccd1SDavid Schultz 				rve -= nbits;
841cc36ccd1SDavid Schultz 				rvb = set_ones(rvb, rvbits = nbits);
842cc36ccd1SDavid Schultz 				break;
843cc36ccd1SDavid Schultz 				}
844cc36ccd1SDavid Schultz 			else
845cc36ccd1SDavid Schultz 				irv = STRTOG_Normal | STRTOG_Inexhi;
84650dad48bSDavid Schultz 			if ((bbbits < nbits && !denorm) || !(rvb->x[0] & 1))
847cc36ccd1SDavid Schultz 				break;
848cc36ccd1SDavid Schultz 			if (dsign) {
849cc36ccd1SDavid Schultz 				rvb = increment(rvb);
850ae2cbf4cSDavid Schultz 				j = kmask & (ULbits - (rvbits & kmask));
851ae2cbf4cSDavid Schultz 				if (hi0bits(rvb->x[rvb->wds - 1]) != j)
852cc36ccd1SDavid Schultz 					rvbits++;
853cc36ccd1SDavid Schultz 				irv = STRTOG_Normal | STRTOG_Inexhi;
854cc36ccd1SDavid Schultz 				}
855cc36ccd1SDavid Schultz 			else {
856cc36ccd1SDavid Schultz 				if (bbbits == 1)
857cc36ccd1SDavid Schultz 					goto undfl;
858cc36ccd1SDavid Schultz 				decrement(rvb);
859cc36ccd1SDavid Schultz 				irv = STRTOG_Normal | STRTOG_Inexlo;
860cc36ccd1SDavid Schultz 				}
861cc36ccd1SDavid Schultz 			break;
862cc36ccd1SDavid Schultz 			}
86350dad48bSDavid Schultz 		if ((dval(&adj) = ratio(delta, bs)) <= 2.) {
864cc36ccd1SDavid Schultz  adj1:
865cc36ccd1SDavid Schultz 			inex = STRTOG_Inexlo;
866cc36ccd1SDavid Schultz 			if (dsign) {
867cc36ccd1SDavid Schultz 				asub = 0;
868cc36ccd1SDavid Schultz 				inex = STRTOG_Inexhi;
869cc36ccd1SDavid Schultz 				}
870cc36ccd1SDavid Schultz 			else if (denorm && bbbits <= 1) {
871cc36ccd1SDavid Schultz  undfl:
872cc36ccd1SDavid Schultz 				rvb->wds = 0;
873cc36ccd1SDavid Schultz 				rve = emin;
874cc36ccd1SDavid Schultz 				irv = STRTOG_Underflow | STRTOG_Inexlo;
875cc36ccd1SDavid Schultz 				break;
876cc36ccd1SDavid Schultz 				}
87750dad48bSDavid Schultz 			adj0 = dval(&adj) = 1.;
878cc36ccd1SDavid Schultz 			}
879cc36ccd1SDavid Schultz 		else {
88050dad48bSDavid Schultz 			adj0 = dval(&adj) *= 0.5;
881cc36ccd1SDavid Schultz 			if (dsign) {
882cc36ccd1SDavid Schultz 				asub = 0;
883cc36ccd1SDavid Schultz 				inex = STRTOG_Inexlo;
884cc36ccd1SDavid Schultz 				}
88550dad48bSDavid Schultz 			if (dval(&adj) < 2147483647.) {
886cc36ccd1SDavid Schultz 				L = adj0;
887cc36ccd1SDavid Schultz 				adj0 -= L;
888cc36ccd1SDavid Schultz 				switch(rd) {
889cc36ccd1SDavid Schultz 				  case 0:
890cc36ccd1SDavid Schultz 					if (adj0 >= .5)
891cc36ccd1SDavid Schultz 						goto inc_L;
892cc36ccd1SDavid Schultz 					break;
893cc36ccd1SDavid Schultz 				  case 1:
894cc36ccd1SDavid Schultz 					if (asub && adj0 > 0.)
895cc36ccd1SDavid Schultz 						goto inc_L;
896cc36ccd1SDavid Schultz 					break;
897cc36ccd1SDavid Schultz 				  case 2:
898cc36ccd1SDavid Schultz 					if (!asub && adj0 > 0.) {
899cc36ccd1SDavid Schultz  inc_L:
900cc36ccd1SDavid Schultz 						L++;
901cc36ccd1SDavid Schultz 						inex = STRTOG_Inexact - inex;
902cc36ccd1SDavid Schultz 						}
903cc36ccd1SDavid Schultz 				  }
90450dad48bSDavid Schultz 				dval(&adj) = L;
905cc36ccd1SDavid Schultz 				}
906cc36ccd1SDavid Schultz 			}
907cc36ccd1SDavid Schultz 		y = rve + rvbits;
908cc36ccd1SDavid Schultz 
90950dad48bSDavid Schultz 		/* adj *= ulp(dval(&rv)); */
910cc36ccd1SDavid Schultz 		/* if (asub) rv -= adj; else rv += adj; */
911cc36ccd1SDavid Schultz 
912cc36ccd1SDavid Schultz 		if (!denorm && rvbits < nbits) {
913cc36ccd1SDavid Schultz 			rvb = lshift(rvb, j = nbits - rvbits);
914cc36ccd1SDavid Schultz 			rve -= j;
915cc36ccd1SDavid Schultz 			rvbits = nbits;
916cc36ccd1SDavid Schultz 			}
91750dad48bSDavid Schultz 		ab = d2b(dval(&adj), &abe, &abits);
918cc36ccd1SDavid Schultz 		if (abe < 0)
919cc36ccd1SDavid Schultz 			rshift(ab, -abe);
920cc36ccd1SDavid Schultz 		else if (abe > 0)
921cc36ccd1SDavid Schultz 			ab = lshift(ab, abe);
922cc36ccd1SDavid Schultz 		rvb0 = rvb;
923cc36ccd1SDavid Schultz 		if (asub) {
924cc36ccd1SDavid Schultz 			/* rv -= adj; */
925cc36ccd1SDavid Schultz 			j = hi0bits(rvb->x[rvb->wds-1]);
926cc36ccd1SDavid Schultz 			rvb = diff(rvb, ab);
927cc36ccd1SDavid Schultz 			k = rvb0->wds - 1;
928cc36ccd1SDavid Schultz 			if (denorm)
929cc36ccd1SDavid Schultz 				/* do nothing */;
930cc36ccd1SDavid Schultz 			else if (rvb->wds <= k
931cc36ccd1SDavid Schultz 				|| hi0bits( rvb->x[k]) >
932cc36ccd1SDavid Schultz 				   hi0bits(rvb0->x[k])) {
933cc36ccd1SDavid Schultz 				/* unlikely; can only have lost 1 high bit */
934cc36ccd1SDavid Schultz 				if (rve1 == emin) {
935cc36ccd1SDavid Schultz 					--rvbits;
936cc36ccd1SDavid Schultz 					denorm = 1;
937cc36ccd1SDavid Schultz 					}
938cc36ccd1SDavid Schultz 				else {
939cc36ccd1SDavid Schultz 					rvb = lshift(rvb, 1);
940cc36ccd1SDavid Schultz 					--rve;
941cc36ccd1SDavid Schultz 					--rve1;
942cc36ccd1SDavid Schultz 					L = finished = 0;
943cc36ccd1SDavid Schultz 					}
944cc36ccd1SDavid Schultz 				}
945cc36ccd1SDavid Schultz 			}
946cc36ccd1SDavid Schultz 		else {
947cc36ccd1SDavid Schultz 			rvb = sum(rvb, ab);
948cc36ccd1SDavid Schultz 			k = rvb->wds - 1;
949cc36ccd1SDavid Schultz 			if (k >= rvb0->wds
950cc36ccd1SDavid Schultz 			 || hi0bits(rvb->x[k]) < hi0bits(rvb0->x[k])) {
951cc36ccd1SDavid Schultz 				if (denorm) {
952cc36ccd1SDavid Schultz 					if (++rvbits == nbits)
953cc36ccd1SDavid Schultz 						denorm = 0;
954cc36ccd1SDavid Schultz 					}
955cc36ccd1SDavid Schultz 				else {
956cc36ccd1SDavid Schultz 					rshift(rvb, 1);
957cc36ccd1SDavid Schultz 					rve++;
958cc36ccd1SDavid Schultz 					rve1++;
959cc36ccd1SDavid Schultz 					L = 0;
960cc36ccd1SDavid Schultz 					}
961cc36ccd1SDavid Schultz 				}
962cc36ccd1SDavid Schultz 			}
963cc36ccd1SDavid Schultz 		Bfree(ab);
964cc36ccd1SDavid Schultz 		Bfree(rvb0);
965cc36ccd1SDavid Schultz 		if (finished)
966cc36ccd1SDavid Schultz 			break;
967cc36ccd1SDavid Schultz 
968cc36ccd1SDavid Schultz 		z = rve + rvbits;
969cc36ccd1SDavid Schultz 		if (y == z && L) {
970cc36ccd1SDavid Schultz 			/* Can we stop now? */
97150dad48bSDavid Schultz 			tol = dval(&adj) * 5e-16; /* > max rel error */
97250dad48bSDavid Schultz 			dval(&adj) = adj0 - .5;
97350dad48bSDavid Schultz 			if (dval(&adj) < -tol) {
974cc36ccd1SDavid Schultz 				if (adj0 > tol) {
975cc36ccd1SDavid Schultz 					irv |= inex;
976cc36ccd1SDavid Schultz 					break;
977cc36ccd1SDavid Schultz 					}
978cc36ccd1SDavid Schultz 				}
97950dad48bSDavid Schultz 			else if (dval(&adj) > tol && adj0 < 1. - tol) {
980cc36ccd1SDavid Schultz 				irv |= inex;
981cc36ccd1SDavid Schultz 				break;
982cc36ccd1SDavid Schultz 				}
983cc36ccd1SDavid Schultz 			}
984cc36ccd1SDavid Schultz 		bb0 = denorm ? 0 : trailz(rvb);
985cc36ccd1SDavid Schultz 		Bfree(bb);
986cc36ccd1SDavid Schultz 		Bfree(bd);
987cc36ccd1SDavid Schultz 		Bfree(bs);
988cc36ccd1SDavid Schultz 		Bfree(delta);
989cc36ccd1SDavid Schultz 		}
990c88250a5SDavid Schultz 	if (!denorm && (j = nbits - rvbits)) {
991c88250a5SDavid Schultz 		if (j > 0)
992cc36ccd1SDavid Schultz 			rvb = lshift(rvb, j);
993c88250a5SDavid Schultz 		else
994c88250a5SDavid Schultz 			rshift(rvb, -j);
995cc36ccd1SDavid Schultz 		rve -= j;
996cc36ccd1SDavid Schultz 		}
997cc36ccd1SDavid Schultz 	*exp = rve;
998cc36ccd1SDavid Schultz 	Bfree(bb);
999cc36ccd1SDavid Schultz 	Bfree(bd);
1000cc36ccd1SDavid Schultz 	Bfree(bs);
1001cc36ccd1SDavid Schultz 	Bfree(bd0);
1002cc36ccd1SDavid Schultz 	Bfree(delta);
1003c88250a5SDavid Schultz 	if (rve > fpi->emax) {
1004ae2cbf4cSDavid Schultz 		switch(fpi->rounding & 3) {
1005ae2cbf4cSDavid Schultz 		  case FPI_Round_near:
1006ae2cbf4cSDavid Schultz 			goto huge;
1007ae2cbf4cSDavid Schultz 		  case FPI_Round_up:
1008ae2cbf4cSDavid Schultz 			if (!sign)
1009ae2cbf4cSDavid Schultz 				goto huge;
1010ae2cbf4cSDavid Schultz 			break;
1011ae2cbf4cSDavid Schultz 		  case FPI_Round_down:
1012ae2cbf4cSDavid Schultz 			if (sign)
1013ae2cbf4cSDavid Schultz 				goto huge;
1014ae2cbf4cSDavid Schultz 		  }
1015ae2cbf4cSDavid Schultz 		/* Round to largest representable magnitude */
1016ae2cbf4cSDavid Schultz 		Bfree(rvb);
1017ae2cbf4cSDavid Schultz 		rvb = 0;
1018ae2cbf4cSDavid Schultz 		irv = STRTOG_Normal | STRTOG_Inexlo;
1019ae2cbf4cSDavid Schultz 		*exp = fpi->emax;
1020ae2cbf4cSDavid Schultz 		b = bits;
10214848dd08SDavid Schultz 		be = b + ((fpi->nbits + 31) >> 5);
1022ae2cbf4cSDavid Schultz 		while(b < be)
1023ae2cbf4cSDavid Schultz 			*b++ = -1;
1024ae2cbf4cSDavid Schultz 		if ((j = fpi->nbits & 0x1f))
1025ae2cbf4cSDavid Schultz 			*--be >>= (32 - j);
1026ae2cbf4cSDavid Schultz 		goto ret;
1027c88250a5SDavid Schultz  huge:
1028c88250a5SDavid Schultz 		rvb->wds = 0;
1029c88250a5SDavid Schultz 		irv = STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
1030c88250a5SDavid Schultz #ifndef NO_ERRNO
1031c88250a5SDavid Schultz 		errno = ERANGE;
1032c88250a5SDavid Schultz #endif
1033c88250a5SDavid Schultz  infnanexp:
1034c88250a5SDavid Schultz 		*exp = fpi->emax + 1;
1035c88250a5SDavid Schultz 		}
1036cc36ccd1SDavid Schultz  ret:
1037cc36ccd1SDavid Schultz 	if (denorm) {
1038cc36ccd1SDavid Schultz 		if (sudden_underflow) {
1039cc36ccd1SDavid Schultz 			rvb->wds = 0;
1040cc36ccd1SDavid Schultz 			irv = STRTOG_Underflow | STRTOG_Inexlo;
1041ae2cbf4cSDavid Schultz #ifndef NO_ERRNO
1042ae2cbf4cSDavid Schultz 			errno = ERANGE;
1043ae2cbf4cSDavid Schultz #endif
1044cc36ccd1SDavid Schultz 			}
1045cc36ccd1SDavid Schultz 		else  {
1046cc36ccd1SDavid Schultz 			irv = (irv & ~STRTOG_Retmask) |
1047cc36ccd1SDavid Schultz 				(rvb->wds > 0 ? STRTOG_Denormal : STRTOG_Zero);
1048ae2cbf4cSDavid Schultz 			if (irv & STRTOG_Inexact) {
1049cc36ccd1SDavid Schultz 				irv |= STRTOG_Underflow;
1050ae2cbf4cSDavid Schultz #ifndef NO_ERRNO
1051ae2cbf4cSDavid Schultz 				errno = ERANGE;
1052ae2cbf4cSDavid Schultz #endif
1053ae2cbf4cSDavid Schultz 				}
1054cc36ccd1SDavid Schultz 			}
1055cc36ccd1SDavid Schultz 		}
1056cc36ccd1SDavid Schultz 	if (se)
1057cc36ccd1SDavid Schultz 		*se = (char *)s;
1058cc36ccd1SDavid Schultz 	if (sign)
1059cc36ccd1SDavid Schultz 		irv |= STRTOG_Neg;
1060cc36ccd1SDavid Schultz 	if (rvb) {
1061cc36ccd1SDavid Schultz 		copybits(bits, nbits, rvb);
1062cc36ccd1SDavid Schultz 		Bfree(rvb);
1063cc36ccd1SDavid Schultz 		}
1064cc36ccd1SDavid Schultz 	return irv;
1065cc36ccd1SDavid Schultz 	}
1066