xref: /dflybsd-src/contrib/gdtoa/strtodg.c (revision 0d5acd7467c4e95f792ef49fceb3ab8e917ce86b)
11181b21fSPeter Avalos /****************************************************************
21181b21fSPeter Avalos 
31181b21fSPeter Avalos The author of this software is David M. Gay.
41181b21fSPeter Avalos 
51181b21fSPeter Avalos Copyright (C) 1998-2001 by Lucent Technologies
61181b21fSPeter Avalos All Rights Reserved
71181b21fSPeter Avalos 
81181b21fSPeter Avalos Permission to use, copy, modify, and distribute this software and
91181b21fSPeter Avalos its documentation for any purpose and without fee is hereby
101181b21fSPeter Avalos granted, provided that the above copyright notice appear in all
111181b21fSPeter Avalos copies and that both that the copyright notice and this
121181b21fSPeter Avalos permission notice and warranty disclaimer appear in supporting
131181b21fSPeter Avalos documentation, and that the name of Lucent or any of its entities
141181b21fSPeter Avalos not be used in advertising or publicity pertaining to
151181b21fSPeter Avalos distribution of the software without specific, written prior
161181b21fSPeter Avalos permission.
171181b21fSPeter Avalos 
181181b21fSPeter Avalos LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
191181b21fSPeter Avalos INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
201181b21fSPeter Avalos IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
211181b21fSPeter Avalos SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
221181b21fSPeter Avalos WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
231181b21fSPeter Avalos IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
241181b21fSPeter Avalos ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
251181b21fSPeter Avalos THIS SOFTWARE.
261181b21fSPeter Avalos 
271181b21fSPeter Avalos ****************************************************************/
281181b21fSPeter Avalos 
291181b21fSPeter Avalos /* Please send bug reports to David M. Gay (dmg at acm dot org,
301181b21fSPeter Avalos  * with " at " changed at "@" and " dot " changed to ".").	*/
311181b21fSPeter Avalos 
321181b21fSPeter Avalos #include "gdtoaimp.h"
331181b21fSPeter Avalos 
341181b21fSPeter Avalos #ifdef USE_LOCALE
351181b21fSPeter Avalos #include "locale.h"
361181b21fSPeter Avalos #endif
371181b21fSPeter Avalos 
381181b21fSPeter Avalos  static CONST int
391181b21fSPeter Avalos fivesbits[] = {	 0,  3,  5,  7, 10, 12, 14, 17, 19, 21,
401181b21fSPeter Avalos 		24, 26, 28, 31, 33, 35, 38, 40, 42, 45,
411181b21fSPeter Avalos 		47, 49, 52
421181b21fSPeter Avalos #ifdef VAX
431181b21fSPeter Avalos 		, 54, 56
441181b21fSPeter Avalos #endif
451181b21fSPeter Avalos 		};
461181b21fSPeter Avalos 
471181b21fSPeter Avalos  Bigint *
481181b21fSPeter Avalos #ifdef KR_headers
increment(b)491181b21fSPeter Avalos increment(b) Bigint *b;
501181b21fSPeter Avalos #else
511181b21fSPeter Avalos increment(Bigint *b)
521181b21fSPeter Avalos #endif
531181b21fSPeter Avalos {
541181b21fSPeter Avalos 	ULong *x, *xe;
551181b21fSPeter Avalos 	Bigint *b1;
561181b21fSPeter Avalos #ifdef Pack_16
571181b21fSPeter Avalos 	ULong carry = 1, y;
581181b21fSPeter Avalos #endif
591181b21fSPeter Avalos 
601181b21fSPeter Avalos 	x = b->x;
611181b21fSPeter Avalos 	xe = x + b->wds;
621181b21fSPeter Avalos #ifdef Pack_32
631181b21fSPeter Avalos 	do {
641181b21fSPeter Avalos 		if (*x < (ULong)0xffffffffL) {
651181b21fSPeter Avalos 			++*x;
661181b21fSPeter Avalos 			return b;
671181b21fSPeter Avalos 			}
681181b21fSPeter Avalos 		*x++ = 0;
691181b21fSPeter Avalos 		} while(x < xe);
701181b21fSPeter Avalos #else
711181b21fSPeter Avalos 	do {
721181b21fSPeter Avalos 		y = *x + carry;
731181b21fSPeter Avalos 		carry = y >> 16;
741181b21fSPeter Avalos 		*x++ = y & 0xffff;
751181b21fSPeter Avalos 		if (!carry)
761181b21fSPeter Avalos 			return b;
771181b21fSPeter Avalos 		} while(x < xe);
781181b21fSPeter Avalos 	if (carry)
791181b21fSPeter Avalos #endif
801181b21fSPeter Avalos 	{
811181b21fSPeter Avalos 		if (b->wds >= b->maxwds) {
821181b21fSPeter Avalos 			b1 = Balloc(b->k+1);
831181b21fSPeter Avalos 			Bcopy(b1,b);
841181b21fSPeter Avalos 			Bfree(b);
851181b21fSPeter Avalos 			b = b1;
861181b21fSPeter Avalos 			}
871181b21fSPeter Avalos 		b->x[b->wds++] = 1;
881181b21fSPeter Avalos 		}
891181b21fSPeter Avalos 	return b;
901181b21fSPeter Avalos 	}
911181b21fSPeter Avalos 
921181b21fSPeter Avalos  void
931181b21fSPeter Avalos #ifdef KR_headers
decrement(b)941181b21fSPeter Avalos decrement(b) Bigint *b;
951181b21fSPeter Avalos #else
961181b21fSPeter Avalos decrement(Bigint *b)
971181b21fSPeter Avalos #endif
981181b21fSPeter Avalos {
991181b21fSPeter Avalos 	ULong *x, *xe;
1001181b21fSPeter Avalos #ifdef Pack_16
1011181b21fSPeter Avalos 	ULong borrow = 1, y;
1021181b21fSPeter Avalos #endif
1031181b21fSPeter Avalos 
1041181b21fSPeter Avalos 	x = b->x;
1051181b21fSPeter Avalos 	xe = x + b->wds;
1061181b21fSPeter Avalos #ifdef Pack_32
1071181b21fSPeter Avalos 	do {
1081181b21fSPeter Avalos 		if (*x) {
1091181b21fSPeter Avalos 			--*x;
1101181b21fSPeter Avalos 			break;
1111181b21fSPeter Avalos 			}
1121181b21fSPeter Avalos 		*x++ = 0xffffffffL;
1131181b21fSPeter Avalos 		}
1141181b21fSPeter Avalos 		while(x < xe);
1151181b21fSPeter Avalos #else
1161181b21fSPeter Avalos 	do {
1171181b21fSPeter Avalos 		y = *x - borrow;
1181181b21fSPeter Avalos 		borrow = (y & 0x10000) >> 16;
1191181b21fSPeter Avalos 		*x++ = y & 0xffff;
1201181b21fSPeter Avalos 		} while(borrow && x < xe);
1211181b21fSPeter Avalos #endif
1221181b21fSPeter Avalos 	}
1231181b21fSPeter Avalos 
1241181b21fSPeter Avalos  static int
1251181b21fSPeter Avalos #ifdef KR_headers
all_on(b,n)1261181b21fSPeter Avalos all_on(b, n) Bigint *b; int n;
1271181b21fSPeter Avalos #else
1281181b21fSPeter Avalos all_on(Bigint *b, int n)
1291181b21fSPeter Avalos #endif
1301181b21fSPeter Avalos {
1311181b21fSPeter Avalos 	ULong *x, *xe;
1321181b21fSPeter Avalos 
1331181b21fSPeter Avalos 	x = b->x;
1341181b21fSPeter Avalos 	xe = x + (n >> kshift);
1351181b21fSPeter Avalos 	while(x < xe)
1361181b21fSPeter Avalos 		if ((*x++ & ALL_ON) != ALL_ON)
1371181b21fSPeter Avalos 			return 0;
1381181b21fSPeter Avalos 	if (n &= kmask)
1391181b21fSPeter Avalos 		return ((*x | (ALL_ON << n)) & ALL_ON) == ALL_ON;
1401181b21fSPeter Avalos 	return 1;
1411181b21fSPeter Avalos 	}
1421181b21fSPeter Avalos 
1431181b21fSPeter Avalos  Bigint *
1441181b21fSPeter Avalos #ifdef KR_headers
set_ones(b,n)1451181b21fSPeter Avalos set_ones(b, n) Bigint *b; int n;
1461181b21fSPeter Avalos #else
1471181b21fSPeter Avalos set_ones(Bigint *b, int n)
1481181b21fSPeter Avalos #endif
1491181b21fSPeter Avalos {
1501181b21fSPeter Avalos 	int k;
1511181b21fSPeter Avalos 	ULong *x, *xe;
1521181b21fSPeter Avalos 
1531181b21fSPeter Avalos 	k = (n + ((1 << kshift) - 1)) >> kshift;
1541181b21fSPeter Avalos 	if (b->k < k) {
1551181b21fSPeter Avalos 		Bfree(b);
1561181b21fSPeter Avalos 		b = Balloc(k);
1571181b21fSPeter Avalos 		}
1581181b21fSPeter Avalos 	k = n >> kshift;
1591181b21fSPeter Avalos 	if (n &= kmask)
1601181b21fSPeter Avalos 		k++;
1611181b21fSPeter Avalos 	b->wds = k;
1621181b21fSPeter Avalos 	x = b->x;
1631181b21fSPeter Avalos 	xe = x + k;
1641181b21fSPeter Avalos 	while(x < xe)
1651181b21fSPeter Avalos 		*x++ = ALL_ON;
1661181b21fSPeter Avalos 	if (n)
1671181b21fSPeter Avalos 		x[-1] >>= ULbits - n;
1681181b21fSPeter Avalos 	return b;
1691181b21fSPeter Avalos 	}
1701181b21fSPeter Avalos 
1711181b21fSPeter Avalos  static int
rvOK(d,fpi,exp,bits,exact,rd,irv)1721181b21fSPeter Avalos rvOK
1731181b21fSPeter Avalos #ifdef KR_headers
1741181b21fSPeter Avalos  (d, fpi, exp, bits, exact, rd, irv)
1752a5b511eSPeter Avalos  U *d; FPI *fpi; Long *exp; ULong *bits; int exact, rd, *irv;
1761181b21fSPeter Avalos #else
1772a5b511eSPeter Avalos  (U *d, FPI *fpi, Long *exp, ULong *bits, int exact, int rd, int *irv)
1781181b21fSPeter Avalos #endif
1791181b21fSPeter Avalos {
1801181b21fSPeter Avalos 	Bigint *b;
1811181b21fSPeter Avalos 	ULong carry, inex, lostbits;
1821181b21fSPeter Avalos 	int bdif, e, j, k, k1, nb, rv;
1831181b21fSPeter Avalos 
1841181b21fSPeter Avalos 	carry = rv = 0;
1852a5b511eSPeter Avalos 	b = d2b(dval(d), &e, &bdif);
1861181b21fSPeter Avalos 	bdif -= nb = fpi->nbits;
1871181b21fSPeter Avalos 	e += bdif;
1881181b21fSPeter Avalos 	if (bdif <= 0) {
1891181b21fSPeter Avalos 		if (exact)
1901181b21fSPeter Avalos 			goto trunc;
1911181b21fSPeter Avalos 		goto ret;
1921181b21fSPeter Avalos 		}
1931181b21fSPeter Avalos 	if (P == nb) {
1941181b21fSPeter Avalos 		if (
1951181b21fSPeter Avalos #ifndef IMPRECISE_INEXACT
1961181b21fSPeter Avalos 			exact &&
1971181b21fSPeter Avalos #endif
1981181b21fSPeter Avalos 			fpi->rounding ==
1991181b21fSPeter Avalos #ifdef RND_PRODQUOT
2001181b21fSPeter Avalos 					FPI_Round_near
2011181b21fSPeter Avalos #else
2021181b21fSPeter Avalos 					Flt_Rounds
2031181b21fSPeter Avalos #endif
2041181b21fSPeter Avalos 			) goto trunc;
2051181b21fSPeter Avalos 		goto ret;
2061181b21fSPeter Avalos 		}
2071181b21fSPeter Avalos 	switch(rd) {
2081181b21fSPeter Avalos 	  case 1: /* round down (toward -Infinity) */
2091181b21fSPeter Avalos 		goto trunc;
2101181b21fSPeter Avalos 	  case 2: /* round up (toward +Infinity) */
2111181b21fSPeter Avalos 		break;
2121181b21fSPeter Avalos 	  default: /* round near */
2131181b21fSPeter Avalos 		k = bdif - 1;
2141181b21fSPeter Avalos 		if (k < 0)
2151181b21fSPeter Avalos 			goto trunc;
2161181b21fSPeter Avalos 		if (!k) {
2171181b21fSPeter Avalos 			if (!exact)
2181181b21fSPeter Avalos 				goto ret;
2191181b21fSPeter Avalos 			if (b->x[0] & 2)
2201181b21fSPeter Avalos 				break;
2211181b21fSPeter Avalos 			goto trunc;
2221181b21fSPeter Avalos 			}
2231181b21fSPeter Avalos 		if (b->x[k>>kshift] & ((ULong)1 << (k & kmask)))
2241181b21fSPeter Avalos 			break;
2251181b21fSPeter Avalos 		goto trunc;
2261181b21fSPeter Avalos 	  }
2271181b21fSPeter Avalos 	/* "break" cases: round up 1 bit, then truncate; bdif > 0 */
2281181b21fSPeter Avalos 	carry = 1;
2291181b21fSPeter Avalos  trunc:
2301181b21fSPeter Avalos 	inex = lostbits = 0;
2311181b21fSPeter Avalos 	if (bdif > 0) {
2321181b21fSPeter Avalos 		if ( (lostbits = any_on(b, bdif)) !=0)
2331181b21fSPeter Avalos 			inex = STRTOG_Inexlo;
2341181b21fSPeter Avalos 		rshift(b, bdif);
2351181b21fSPeter Avalos 		if (carry) {
2361181b21fSPeter Avalos 			inex = STRTOG_Inexhi;
2371181b21fSPeter Avalos 			b = increment(b);
2381181b21fSPeter Avalos 			if ( (j = nb & kmask) !=0)
2391181b21fSPeter Avalos 				j = ULbits - j;
2401181b21fSPeter Avalos 			if (hi0bits(b->x[b->wds - 1]) != j) {
2411181b21fSPeter Avalos 				if (!lostbits)
2421181b21fSPeter Avalos 					lostbits = b->x[0] & 1;
2431181b21fSPeter Avalos 				rshift(b, 1);
2441181b21fSPeter Avalos 				e++;
2451181b21fSPeter Avalos 				}
2461181b21fSPeter Avalos 			}
2471181b21fSPeter Avalos 		}
2481181b21fSPeter Avalos 	else if (bdif < 0)
2491181b21fSPeter Avalos 		b = lshift(b, -bdif);
2501181b21fSPeter Avalos 	if (e < fpi->emin) {
2511181b21fSPeter Avalos 		k = fpi->emin - e;
2521181b21fSPeter Avalos 		e = fpi->emin;
2531181b21fSPeter Avalos 		if (k > nb || fpi->sudden_underflow) {
2541181b21fSPeter Avalos 			b->wds = inex = 0;
2551181b21fSPeter Avalos 			*irv = STRTOG_Underflow | STRTOG_Inexlo;
2561181b21fSPeter Avalos 			}
2571181b21fSPeter Avalos 		else {
2581181b21fSPeter Avalos 			k1 = k - 1;
2591181b21fSPeter Avalos 			if (k1 > 0 && !lostbits)
2601181b21fSPeter Avalos 				lostbits = any_on(b, k1);
2611181b21fSPeter Avalos 			if (!lostbits && !exact)
2621181b21fSPeter Avalos 				goto ret;
2631181b21fSPeter Avalos 			lostbits |=
2641181b21fSPeter Avalos 			  carry = b->x[k1>>kshift] & (1 << (k1 & kmask));
2651181b21fSPeter Avalos 			rshift(b, k);
2661181b21fSPeter Avalos 			*irv = STRTOG_Denormal;
2671181b21fSPeter Avalos 			if (carry) {
2681181b21fSPeter Avalos 				b = increment(b);
2691181b21fSPeter Avalos 				inex = STRTOG_Inexhi | STRTOG_Underflow;
2701181b21fSPeter Avalos 				}
2711181b21fSPeter Avalos 			else if (lostbits)
2721181b21fSPeter Avalos 				inex = STRTOG_Inexlo | STRTOG_Underflow;
2731181b21fSPeter Avalos 			}
2741181b21fSPeter Avalos 		}
2751181b21fSPeter Avalos 	else if (e > fpi->emax) {
2761181b21fSPeter Avalos 		e = fpi->emax + 1;
2771181b21fSPeter Avalos 		*irv = STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
2781181b21fSPeter Avalos #ifndef NO_ERRNO
2791181b21fSPeter Avalos 		errno = ERANGE;
2801181b21fSPeter Avalos #endif
2811181b21fSPeter Avalos 		b->wds = inex = 0;
2821181b21fSPeter Avalos 		}
2831181b21fSPeter Avalos 	*exp = e;
2841181b21fSPeter Avalos 	copybits(bits, nb, b);
2851181b21fSPeter Avalos 	*irv |= inex;
2861181b21fSPeter Avalos 	rv = 1;
2871181b21fSPeter Avalos  ret:
2881181b21fSPeter Avalos 	Bfree(b);
2891181b21fSPeter Avalos 	return rv;
2901181b21fSPeter Avalos 	}
2911181b21fSPeter Avalos 
2921181b21fSPeter Avalos  static int
2931181b21fSPeter Avalos #ifdef KR_headers
mantbits(d)2942a5b511eSPeter Avalos mantbits(d) U *d;
2951181b21fSPeter Avalos #else
2962a5b511eSPeter Avalos mantbits(U *d)
2971181b21fSPeter Avalos #endif
2981181b21fSPeter Avalos {
2991181b21fSPeter Avalos 	ULong L;
3001181b21fSPeter Avalos #ifdef VAX
3011181b21fSPeter Avalos 	L = word1(d) << 16 | word1(d) >> 16;
3021181b21fSPeter Avalos 	if (L)
3031181b21fSPeter Avalos #else
3041181b21fSPeter Avalos 	if ( (L = word1(d)) !=0)
3051181b21fSPeter Avalos #endif
3061181b21fSPeter Avalos 		return P - lo0bits(&L);
3071181b21fSPeter Avalos #ifdef VAX
3081181b21fSPeter Avalos 	L = word0(d) << 16 | word0(d) >> 16 | Exp_msk11;
3091181b21fSPeter Avalos #else
3101181b21fSPeter Avalos 	L = word0(d) | Exp_msk1;
3111181b21fSPeter Avalos #endif
3121181b21fSPeter Avalos 	return P - 32 - lo0bits(&L);
3131181b21fSPeter Avalos 	}
3141181b21fSPeter Avalos 
3151181b21fSPeter Avalos  int
strtodg_l(s00,se,fpi,exp,bits,loc)316*0d5acd74SJohn Marino strtodg_l
3171181b21fSPeter Avalos #ifdef KR_headers
318*0d5acd74SJohn Marino 	(s00, se, fpi, exp, bits, loc)
319*0d5acd74SJohn Marino 	CONST char *s00; char **se; FPI *fpi; Long *exp; ULong *bits; locale_t loc;
3201181b21fSPeter Avalos #else
321*0d5acd74SJohn Marino 	(CONST char *s00, char **se, FPI *fpi, Long *exp, ULong *bits, locale_t loc)
3221181b21fSPeter Avalos #endif
3231181b21fSPeter Avalos {
3241181b21fSPeter Avalos 	int abe, abits, asub;
3251181b21fSPeter Avalos 	int bb0, bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, decpt, denorm;
3261181b21fSPeter Avalos 	int dsign, e, e1, e2, emin, esign, finished, i, inex, irv;
3271181b21fSPeter Avalos 	int j, k, nbits, nd, nd0, nf, nz, nz0, rd, rvbits, rve, rve1, sign;
3281181b21fSPeter Avalos 	int sudden_underflow;
3291181b21fSPeter Avalos 	CONST char *s, *s0, *s1;
3302a5b511eSPeter Avalos 	double adj0, tol;
3311181b21fSPeter Avalos 	Long L;
3322a5b511eSPeter Avalos 	U adj, rv;
3331181b21fSPeter Avalos 	ULong *b, *be, y, z;
3341181b21fSPeter Avalos 	Bigint *ab, *bb, *bb1, *bd, *bd0, *bs, *delta, *rvb, *rvb0;
3351181b21fSPeter Avalos #ifdef USE_LOCALE /*{{*/
3361181b21fSPeter Avalos #ifdef NO_LOCALE_CACHE
337*0d5acd74SJohn Marino 	char *decimalpoint = localeconv_l(loc)->decimal_point;
3381181b21fSPeter Avalos 	int dplen = strlen(decimalpoint);
3391181b21fSPeter Avalos #else
3401181b21fSPeter Avalos 	char *decimalpoint;
3411181b21fSPeter Avalos 	static char *decimalpoint_cache;
3421181b21fSPeter Avalos 	static int dplen;
3431181b21fSPeter Avalos 	if (!(s0 = decimalpoint_cache)) {
344*0d5acd74SJohn Marino 		s0 = localeconv_l(loc)->decimal_point;
3452a5b511eSPeter Avalos 		if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) {
3461181b21fSPeter Avalos 			strcpy(decimalpoint_cache, s0);
3471181b21fSPeter Avalos 			s0 = decimalpoint_cache;
3481181b21fSPeter Avalos 			}
3491181b21fSPeter Avalos 		dplen = strlen(s0);
3501181b21fSPeter Avalos 		}
3511181b21fSPeter Avalos 	decimalpoint = (char*)s0;
3521181b21fSPeter Avalos #endif /*NO_LOCALE_CACHE*/
3531181b21fSPeter Avalos #else  /*USE_LOCALE}{*/
3541181b21fSPeter Avalos #define dplen 1
3551181b21fSPeter Avalos #endif /*USE_LOCALE}}*/
3561181b21fSPeter Avalos 
3571181b21fSPeter Avalos 	irv = STRTOG_Zero;
3581181b21fSPeter Avalos 	denorm = sign = nz0 = nz = 0;
3592a5b511eSPeter Avalos 	dval(&rv) = 0.;
3601181b21fSPeter Avalos 	rvb = 0;
3611181b21fSPeter Avalos 	nbits = fpi->nbits;
3621181b21fSPeter Avalos 	for(s = s00;;s++) switch(*s) {
3631181b21fSPeter Avalos 		case '-':
3641181b21fSPeter Avalos 			sign = 1;
3651181b21fSPeter Avalos 			/* no break */
3661181b21fSPeter Avalos 		case '+':
3671181b21fSPeter Avalos 			if (*++s)
3681181b21fSPeter Avalos 				goto break2;
3691181b21fSPeter Avalos 			/* no break */
3701181b21fSPeter Avalos 		case 0:
3711181b21fSPeter Avalos 			sign = 0;
3721181b21fSPeter Avalos 			irv = STRTOG_NoNumber;
3731181b21fSPeter Avalos 			s = s00;
3741181b21fSPeter Avalos 			goto ret;
3751181b21fSPeter Avalos 		case '\t':
3761181b21fSPeter Avalos 		case '\n':
3771181b21fSPeter Avalos 		case '\v':
3781181b21fSPeter Avalos 		case '\f':
3791181b21fSPeter Avalos 		case '\r':
3801181b21fSPeter Avalos 		case ' ':
3811181b21fSPeter Avalos 			continue;
3821181b21fSPeter Avalos 		default:
3831181b21fSPeter Avalos 			goto break2;
3841181b21fSPeter Avalos 		}
3851181b21fSPeter Avalos  break2:
3861181b21fSPeter Avalos 	if (*s == '0') {
3871181b21fSPeter Avalos #ifndef NO_HEX_FP
3881181b21fSPeter Avalos 		switch(s[1]) {
3891181b21fSPeter Avalos 		  case 'x':
3901181b21fSPeter Avalos 		  case 'X':
3911181b21fSPeter Avalos 			irv = gethex(&s, fpi, exp, &rvb, sign);
3921181b21fSPeter Avalos 			if (irv == STRTOG_NoNumber) {
3931181b21fSPeter Avalos 				s = s00;
3941181b21fSPeter Avalos 				sign = 0;
3951181b21fSPeter Avalos 				}
3961181b21fSPeter Avalos 			goto ret;
3971181b21fSPeter Avalos 		  }
3981181b21fSPeter Avalos #endif
3991181b21fSPeter Avalos 		nz0 = 1;
4001181b21fSPeter Avalos 		while(*++s == '0') ;
4011181b21fSPeter Avalos 		if (!*s)
4021181b21fSPeter Avalos 			goto ret;
4031181b21fSPeter Avalos 		}
4041181b21fSPeter Avalos 	sudden_underflow = fpi->sudden_underflow;
4051181b21fSPeter Avalos 	s0 = s;
4061181b21fSPeter Avalos 	y = z = 0;
4071181b21fSPeter Avalos 	for(decpt = nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++)
4081181b21fSPeter Avalos 		if (nd < 9)
4091181b21fSPeter Avalos 			y = 10*y + c - '0';
4101181b21fSPeter Avalos 		else if (nd < 16)
4111181b21fSPeter Avalos 			z = 10*z + c - '0';
4121181b21fSPeter Avalos 	nd0 = nd;
4131181b21fSPeter Avalos #ifdef USE_LOCALE
4141181b21fSPeter Avalos 	if (c == *decimalpoint) {
4151181b21fSPeter Avalos 		for(i = 1; decimalpoint[i]; ++i)
4161181b21fSPeter Avalos 			if (s[i] != decimalpoint[i])
4171181b21fSPeter Avalos 				goto dig_done;
4181181b21fSPeter Avalos 		s += i;
4191181b21fSPeter Avalos 		c = *s;
4201181b21fSPeter Avalos #else
4211181b21fSPeter Avalos 	if (c == '.') {
4221181b21fSPeter Avalos 		c = *++s;
4231181b21fSPeter Avalos #endif
4241181b21fSPeter Avalos 		decpt = 1;
4251181b21fSPeter Avalos 		if (!nd) {
4261181b21fSPeter Avalos 			for(; c == '0'; c = *++s)
4271181b21fSPeter Avalos 				nz++;
4281181b21fSPeter Avalos 			if (c > '0' && c <= '9') {
4291181b21fSPeter Avalos 				s0 = s;
4301181b21fSPeter Avalos 				nf += nz;
4311181b21fSPeter Avalos 				nz = 0;
4321181b21fSPeter Avalos 				goto have_dig;
4331181b21fSPeter Avalos 				}
4341181b21fSPeter Avalos 			goto dig_done;
4351181b21fSPeter Avalos 			}
4361181b21fSPeter Avalos 		for(; c >= '0' && c <= '9'; c = *++s) {
4371181b21fSPeter Avalos  have_dig:
4381181b21fSPeter Avalos 			nz++;
4391181b21fSPeter Avalos 			if (c -= '0') {
4401181b21fSPeter Avalos 				nf += nz;
4411181b21fSPeter Avalos 				for(i = 1; i < nz; i++)
4421181b21fSPeter Avalos 					if (nd++ < 9)
4431181b21fSPeter Avalos 						y *= 10;
4441181b21fSPeter Avalos 					else if (nd <= DBL_DIG + 1)
4451181b21fSPeter Avalos 						z *= 10;
4461181b21fSPeter Avalos 				if (nd++ < 9)
4471181b21fSPeter Avalos 					y = 10*y + c;
4481181b21fSPeter Avalos 				else if (nd <= DBL_DIG + 1)
4491181b21fSPeter Avalos 					z = 10*z + c;
4501181b21fSPeter Avalos 				nz = 0;
4511181b21fSPeter Avalos 				}
4521181b21fSPeter Avalos 			}
4531181b21fSPeter Avalos 		}/*}*/
4541181b21fSPeter Avalos  dig_done:
4551181b21fSPeter Avalos 	e = 0;
4561181b21fSPeter Avalos 	if (c == 'e' || c == 'E') {
4571181b21fSPeter Avalos 		if (!nd && !nz && !nz0) {
4581181b21fSPeter Avalos 			irv = STRTOG_NoNumber;
4591181b21fSPeter Avalos 			s = s00;
4601181b21fSPeter Avalos 			goto ret;
4611181b21fSPeter Avalos 			}
4621181b21fSPeter Avalos 		s00 = s;
4631181b21fSPeter Avalos 		esign = 0;
4641181b21fSPeter Avalos 		switch(c = *++s) {
4651181b21fSPeter Avalos 			case '-':
4661181b21fSPeter Avalos 				esign = 1;
4671181b21fSPeter Avalos 			case '+':
4681181b21fSPeter Avalos 				c = *++s;
4691181b21fSPeter Avalos 			}
4701181b21fSPeter Avalos 		if (c >= '0' && c <= '9') {
4711181b21fSPeter Avalos 			while(c == '0')
4721181b21fSPeter Avalos 				c = *++s;
4731181b21fSPeter Avalos 			if (c > '0' && c <= '9') {
4741181b21fSPeter Avalos 				L = c - '0';
4751181b21fSPeter Avalos 				s1 = s;
4761181b21fSPeter Avalos 				while((c = *++s) >= '0' && c <= '9')
4771181b21fSPeter Avalos 					L = 10*L + c - '0';
4781181b21fSPeter Avalos 				if (s - s1 > 8 || L > 19999)
4791181b21fSPeter Avalos 					/* Avoid confusion from exponents
4801181b21fSPeter Avalos 					 * so large that e might overflow.
4811181b21fSPeter Avalos 					 */
4821181b21fSPeter Avalos 					e = 19999; /* safe for 16 bit ints */
4831181b21fSPeter Avalos 				else
4841181b21fSPeter Avalos 					e = (int)L;
4851181b21fSPeter Avalos 				if (esign)
4861181b21fSPeter Avalos 					e = -e;
4871181b21fSPeter Avalos 				}
4881181b21fSPeter Avalos 			else
4891181b21fSPeter Avalos 				e = 0;
4901181b21fSPeter Avalos 			}
4911181b21fSPeter Avalos 		else
4921181b21fSPeter Avalos 			s = s00;
4931181b21fSPeter Avalos 		}
4941181b21fSPeter Avalos 	if (!nd) {
4951181b21fSPeter Avalos 		if (!nz && !nz0) {
4961181b21fSPeter Avalos #ifdef INFNAN_CHECK
4971181b21fSPeter Avalos 			/* Check for Nan and Infinity */
4981181b21fSPeter Avalos 			if (!decpt)
4991181b21fSPeter Avalos 			 switch(c) {
5001181b21fSPeter Avalos 			  case 'i':
5011181b21fSPeter Avalos 			  case 'I':
5021181b21fSPeter Avalos 				if (match(&s,"nf")) {
5031181b21fSPeter Avalos 					--s;
5041181b21fSPeter Avalos 					if (!match(&s,"inity"))
5051181b21fSPeter Avalos 						++s;
5061181b21fSPeter Avalos 					irv = STRTOG_Infinite;
5071181b21fSPeter Avalos 					goto infnanexp;
5081181b21fSPeter Avalos 					}
5091181b21fSPeter Avalos 				break;
5101181b21fSPeter Avalos 			  case 'n':
5111181b21fSPeter Avalos 			  case 'N':
5121181b21fSPeter Avalos 				if (match(&s, "an")) {
5131181b21fSPeter Avalos 					irv = STRTOG_NaN;
5141181b21fSPeter Avalos 					*exp = fpi->emax + 1;
5151181b21fSPeter Avalos #ifndef No_Hex_NaN
5161181b21fSPeter Avalos 					if (*s == '(') /*)*/
5171181b21fSPeter Avalos 						irv = hexnan(&s, fpi, bits);
5181181b21fSPeter Avalos #endif
5191181b21fSPeter Avalos 					goto infnanexp;
5201181b21fSPeter Avalos 					}
5211181b21fSPeter Avalos 			  }
5221181b21fSPeter Avalos #endif /* INFNAN_CHECK */
5231181b21fSPeter Avalos 			irv = STRTOG_NoNumber;
5241181b21fSPeter Avalos 			s = s00;
5251181b21fSPeter Avalos 			}
5261181b21fSPeter Avalos 		goto ret;
5271181b21fSPeter Avalos 		}
5281181b21fSPeter Avalos 
5291181b21fSPeter Avalos 	irv = STRTOG_Normal;
5301181b21fSPeter Avalos 	e1 = e -= nf;
5311181b21fSPeter Avalos 	rd = 0;
5321181b21fSPeter Avalos 	switch(fpi->rounding & 3) {
5331181b21fSPeter Avalos 	  case FPI_Round_up:
5341181b21fSPeter Avalos 		rd = 2 - sign;
5351181b21fSPeter Avalos 		break;
5361181b21fSPeter Avalos 	  case FPI_Round_zero:
5371181b21fSPeter Avalos 		rd = 1;
5381181b21fSPeter Avalos 		break;
5391181b21fSPeter Avalos 	  case FPI_Round_down:
5401181b21fSPeter Avalos 		rd = 1 + sign;
5411181b21fSPeter Avalos 	  }
5421181b21fSPeter Avalos 
5431181b21fSPeter Avalos 	/* Now we have nd0 digits, starting at s0, followed by a
5441181b21fSPeter Avalos 	 * decimal point, followed by nd-nd0 digits.  The number we're
5451181b21fSPeter Avalos 	 * after is the integer represented by those digits times
5461181b21fSPeter Avalos 	 * 10**e */
5471181b21fSPeter Avalos 
5481181b21fSPeter Avalos 	if (!nd0)
5491181b21fSPeter Avalos 		nd0 = nd;
5501181b21fSPeter Avalos 	k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
5512a5b511eSPeter Avalos 	dval(&rv) = y;
5521181b21fSPeter Avalos 	if (k > 9)
5532a5b511eSPeter Avalos 		dval(&rv) = tens[k - 9] * dval(&rv) + z;
5541181b21fSPeter Avalos 	bd0 = 0;
5551181b21fSPeter Avalos 	if (nbits <= P && nd <= DBL_DIG) {
5561181b21fSPeter Avalos 		if (!e) {
5572a5b511eSPeter Avalos 			if (rvOK(&rv, fpi, exp, bits, 1, rd, &irv))
5581181b21fSPeter Avalos 				goto ret;
5591181b21fSPeter Avalos 			}
5601181b21fSPeter Avalos 		else if (e > 0) {
5611181b21fSPeter Avalos 			if (e <= Ten_pmax) {
5621181b21fSPeter Avalos #ifdef VAX
5631181b21fSPeter Avalos 				goto vax_ovfl_check;
5641181b21fSPeter Avalos #else
5652a5b511eSPeter Avalos 				i = fivesbits[e] + mantbits(&rv) <= P;
5662a5b511eSPeter Avalos 				/* rv = */ rounded_product(dval(&rv), tens[e]);
5672a5b511eSPeter Avalos 				if (rvOK(&rv, fpi, exp, bits, i, rd, &irv))
5681181b21fSPeter Avalos 					goto ret;
5691181b21fSPeter Avalos 				e1 -= e;
5701181b21fSPeter Avalos 				goto rv_notOK;
5711181b21fSPeter Avalos #endif
5721181b21fSPeter Avalos 				}
5731181b21fSPeter Avalos 			i = DBL_DIG - nd;
5741181b21fSPeter Avalos 			if (e <= Ten_pmax + i) {
5751181b21fSPeter Avalos 				/* A fancier test would sometimes let us do
5761181b21fSPeter Avalos 				 * this for larger i values.
5771181b21fSPeter Avalos 				 */
5781181b21fSPeter Avalos 				e2 = e - i;
5791181b21fSPeter Avalos 				e1 -= i;
5802a5b511eSPeter Avalos 				dval(&rv) *= tens[i];
5811181b21fSPeter Avalos #ifdef VAX
5821181b21fSPeter Avalos 				/* VAX exponent range is so narrow we must
5831181b21fSPeter Avalos 				 * worry about overflow here...
5841181b21fSPeter Avalos 				 */
5851181b21fSPeter Avalos  vax_ovfl_check:
5862a5b511eSPeter Avalos 				dval(&adj) = dval(&rv);
5872a5b511eSPeter Avalos 				word0(&adj) -= P*Exp_msk1;
5882a5b511eSPeter Avalos 				/* adj = */ rounded_product(dval(&adj), tens[e2]);
5892a5b511eSPeter Avalos 				if ((word0(&adj) & Exp_mask)
5901181b21fSPeter Avalos 				 > Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
5911181b21fSPeter Avalos 					goto rv_notOK;
5922a5b511eSPeter Avalos 				word0(&adj) += P*Exp_msk1;
5932a5b511eSPeter Avalos 				dval(&rv) = dval(&adj);
5941181b21fSPeter Avalos #else
5952a5b511eSPeter Avalos 				/* rv = */ rounded_product(dval(&rv), tens[e2]);
5961181b21fSPeter Avalos #endif
5972a5b511eSPeter Avalos 				if (rvOK(&rv, fpi, exp, bits, 0, rd, &irv))
5981181b21fSPeter Avalos 					goto ret;
5991181b21fSPeter Avalos 				e1 -= e2;
6001181b21fSPeter Avalos 				}
6011181b21fSPeter Avalos 			}
6021181b21fSPeter Avalos #ifndef Inaccurate_Divide
6031181b21fSPeter Avalos 		else if (e >= -Ten_pmax) {
6042a5b511eSPeter Avalos 			/* rv = */ rounded_quotient(dval(&rv), tens[-e]);
6052a5b511eSPeter Avalos 			if (rvOK(&rv, fpi, exp, bits, 0, rd, &irv))
6061181b21fSPeter Avalos 				goto ret;
6071181b21fSPeter Avalos 			e1 -= e;
6081181b21fSPeter Avalos 			}
6091181b21fSPeter Avalos #endif
6101181b21fSPeter Avalos 		}
6111181b21fSPeter Avalos  rv_notOK:
6121181b21fSPeter Avalos 	e1 += nd - k;
6131181b21fSPeter Avalos 
6141181b21fSPeter Avalos 	/* Get starting approximation = rv * 10**e1 */
6151181b21fSPeter Avalos 
6161181b21fSPeter Avalos 	e2 = 0;
6171181b21fSPeter Avalos 	if (e1 > 0) {
6181181b21fSPeter Avalos 		if ( (i = e1 & 15) !=0)
6192a5b511eSPeter Avalos 			dval(&rv) *= tens[i];
6201181b21fSPeter Avalos 		if (e1 &= ~15) {
6211181b21fSPeter Avalos 			e1 >>= 4;
6222a5b511eSPeter Avalos 			while(e1 >= (1 << (n_bigtens-1))) {
6232a5b511eSPeter Avalos 				e2 += ((word0(&rv) & Exp_mask)
6241181b21fSPeter Avalos 					>> Exp_shift1) - Bias;
6252a5b511eSPeter Avalos 				word0(&rv) &= ~Exp_mask;
6262a5b511eSPeter Avalos 				word0(&rv) |= Bias << Exp_shift1;
6272a5b511eSPeter Avalos 				dval(&rv) *= bigtens[n_bigtens-1];
6282a5b511eSPeter Avalos 				e1 -= 1 << (n_bigtens-1);
6291181b21fSPeter Avalos 				}
6302a5b511eSPeter Avalos 			e2 += ((word0(&rv) & Exp_mask) >> Exp_shift1) - Bias;
6312a5b511eSPeter Avalos 			word0(&rv) &= ~Exp_mask;
6322a5b511eSPeter Avalos 			word0(&rv) |= Bias << Exp_shift1;
6331181b21fSPeter Avalos 			for(j = 0; e1 > 0; j++, e1 >>= 1)
6341181b21fSPeter Avalos 				if (e1 & 1)
6352a5b511eSPeter Avalos 					dval(&rv) *= bigtens[j];
6361181b21fSPeter Avalos 			}
6371181b21fSPeter Avalos 		}
6381181b21fSPeter Avalos 	else if (e1 < 0) {
6391181b21fSPeter Avalos 		e1 = -e1;
6401181b21fSPeter Avalos 		if ( (i = e1 & 15) !=0)
6412a5b511eSPeter Avalos 			dval(&rv) /= tens[i];
6421181b21fSPeter Avalos 		if (e1 &= ~15) {
6431181b21fSPeter Avalos 			e1 >>= 4;
6442a5b511eSPeter Avalos 			while(e1 >= (1 << (n_bigtens-1))) {
6452a5b511eSPeter Avalos 				e2 += ((word0(&rv) & Exp_mask)
6461181b21fSPeter Avalos 					>> Exp_shift1) - Bias;
6472a5b511eSPeter Avalos 				word0(&rv) &= ~Exp_mask;
6482a5b511eSPeter Avalos 				word0(&rv) |= Bias << Exp_shift1;
6492a5b511eSPeter Avalos 				dval(&rv) *= tinytens[n_bigtens-1];
6502a5b511eSPeter Avalos 				e1 -= 1 << (n_bigtens-1);
6511181b21fSPeter Avalos 				}
6522a5b511eSPeter Avalos 			e2 += ((word0(&rv) & Exp_mask) >> Exp_shift1) - Bias;
6532a5b511eSPeter Avalos 			word0(&rv) &= ~Exp_mask;
6542a5b511eSPeter Avalos 			word0(&rv) |= Bias << Exp_shift1;
6551181b21fSPeter Avalos 			for(j = 0; e1 > 0; j++, e1 >>= 1)
6561181b21fSPeter Avalos 				if (e1 & 1)
6572a5b511eSPeter Avalos 					dval(&rv) *= tinytens[j];
6581181b21fSPeter Avalos 			}
6591181b21fSPeter Avalos 		}
6601181b21fSPeter Avalos #ifdef IBM
6611181b21fSPeter Avalos 	/* e2 is a correction to the (base 2) exponent of the return
6621181b21fSPeter Avalos 	 * value, reflecting adjustments above to avoid overflow in the
6631181b21fSPeter Avalos 	 * native arithmetic.  For native IBM (base 16) arithmetic, we
6641181b21fSPeter Avalos 	 * must multiply e2 by 4 to change from base 16 to 2.
6651181b21fSPeter Avalos 	 */
6661181b21fSPeter Avalos 	e2 <<= 2;
6671181b21fSPeter Avalos #endif
6682a5b511eSPeter Avalos 	rvb = d2b(dval(&rv), &rve, &rvbits);	/* rv = rvb * 2^rve */
6691181b21fSPeter Avalos 	rve += e2;
6701181b21fSPeter Avalos 	if ((j = rvbits - nbits) > 0) {
6711181b21fSPeter Avalos 		rshift(rvb, j);
6721181b21fSPeter Avalos 		rvbits = nbits;
6731181b21fSPeter Avalos 		rve += j;
6741181b21fSPeter Avalos 		}
6751181b21fSPeter Avalos 	bb0 = 0;	/* trailing zero bits in rvb */
6761181b21fSPeter Avalos 	e2 = rve + rvbits - nbits;
6771181b21fSPeter Avalos 	if (e2 > fpi->emax + 1)
6781181b21fSPeter Avalos 		goto huge;
6791181b21fSPeter Avalos 	rve1 = rve + rvbits - nbits;
6801181b21fSPeter Avalos 	if (e2 < (emin = fpi->emin)) {
6811181b21fSPeter Avalos 		denorm = 1;
6821181b21fSPeter Avalos 		j = rve - emin;
6831181b21fSPeter Avalos 		if (j > 0) {
6841181b21fSPeter Avalos 			rvb = lshift(rvb, j);
6851181b21fSPeter Avalos 			rvbits += j;
6861181b21fSPeter Avalos 			}
6871181b21fSPeter Avalos 		else if (j < 0) {
6881181b21fSPeter Avalos 			rvbits += j;
6891181b21fSPeter Avalos 			if (rvbits <= 0) {
6901181b21fSPeter Avalos 				if (rvbits < -1) {
6911181b21fSPeter Avalos  ufl:
6921181b21fSPeter Avalos 					rvb->wds = 0;
6931181b21fSPeter Avalos 					rvb->x[0] = 0;
6941181b21fSPeter Avalos 					*exp = emin;
6951181b21fSPeter Avalos 					irv = STRTOG_Underflow | STRTOG_Inexlo;
6961181b21fSPeter Avalos 					goto ret;
6971181b21fSPeter Avalos 					}
6981181b21fSPeter Avalos 				rvb->x[0] = rvb->wds = rvbits = 1;
6991181b21fSPeter Avalos 				}
7001181b21fSPeter Avalos 			else
7011181b21fSPeter Avalos 				rshift(rvb, -j);
7021181b21fSPeter Avalos 			}
7031181b21fSPeter Avalos 		rve = rve1 = emin;
7041181b21fSPeter Avalos 		if (sudden_underflow && e2 + 1 < emin)
7051181b21fSPeter Avalos 			goto ufl;
7061181b21fSPeter Avalos 		}
7071181b21fSPeter Avalos 
7081181b21fSPeter Avalos 	/* Now the hard part -- adjusting rv to the correct value.*/
7091181b21fSPeter Avalos 
7101181b21fSPeter Avalos 	/* Put digits into bd: true value = bd * 10^e */
7111181b21fSPeter Avalos 
7121181b21fSPeter Avalos 	bd0 = s2b(s0, nd0, nd, y, dplen);
7131181b21fSPeter Avalos 
7141181b21fSPeter Avalos 	for(;;) {
7151181b21fSPeter Avalos 		bd = Balloc(bd0->k);
7161181b21fSPeter Avalos 		Bcopy(bd, bd0);
7171181b21fSPeter Avalos 		bb = Balloc(rvb->k);
7181181b21fSPeter Avalos 		Bcopy(bb, rvb);
7191181b21fSPeter Avalos 		bbbits = rvbits - bb0;
7201181b21fSPeter Avalos 		bbe = rve + bb0;
7211181b21fSPeter Avalos 		bs = i2b(1);
7221181b21fSPeter Avalos 
7231181b21fSPeter Avalos 		if (e >= 0) {
7241181b21fSPeter Avalos 			bb2 = bb5 = 0;
7251181b21fSPeter Avalos 			bd2 = bd5 = e;
7261181b21fSPeter Avalos 			}
7271181b21fSPeter Avalos 		else {
7281181b21fSPeter Avalos 			bb2 = bb5 = -e;
7291181b21fSPeter Avalos 			bd2 = bd5 = 0;
7301181b21fSPeter Avalos 			}
7311181b21fSPeter Avalos 		if (bbe >= 0)
7321181b21fSPeter Avalos 			bb2 += bbe;
7331181b21fSPeter Avalos 		else
7341181b21fSPeter Avalos 			bd2 -= bbe;
7351181b21fSPeter Avalos 		bs2 = bb2;
7361181b21fSPeter Avalos 		j = nbits + 1 - bbbits;
7371181b21fSPeter Avalos 		i = bbe + bbbits - nbits;
7381181b21fSPeter Avalos 		if (i < emin)	/* denormal */
7391181b21fSPeter Avalos 			j += i - emin;
7401181b21fSPeter Avalos 		bb2 += j;
7411181b21fSPeter Avalos 		bd2 += j;
7421181b21fSPeter Avalos 		i = bb2 < bd2 ? bb2 : bd2;
7431181b21fSPeter Avalos 		if (i > bs2)
7441181b21fSPeter Avalos 			i = bs2;
7451181b21fSPeter Avalos 		if (i > 0) {
7461181b21fSPeter Avalos 			bb2 -= i;
7471181b21fSPeter Avalos 			bd2 -= i;
7481181b21fSPeter Avalos 			bs2 -= i;
7491181b21fSPeter Avalos 			}
7501181b21fSPeter Avalos 		if (bb5 > 0) {
7511181b21fSPeter Avalos 			bs = pow5mult(bs, bb5);
7521181b21fSPeter Avalos 			bb1 = mult(bs, bb);
7531181b21fSPeter Avalos 			Bfree(bb);
7541181b21fSPeter Avalos 			bb = bb1;
7551181b21fSPeter Avalos 			}
7561181b21fSPeter Avalos 		bb2 -= bb0;
7571181b21fSPeter Avalos 		if (bb2 > 0)
7581181b21fSPeter Avalos 			bb = lshift(bb, bb2);
7591181b21fSPeter Avalos 		else if (bb2 < 0)
7601181b21fSPeter Avalos 			rshift(bb, -bb2);
7611181b21fSPeter Avalos 		if (bd5 > 0)
7621181b21fSPeter Avalos 			bd = pow5mult(bd, bd5);
7631181b21fSPeter Avalos 		if (bd2 > 0)
7641181b21fSPeter Avalos 			bd = lshift(bd, bd2);
7651181b21fSPeter Avalos 		if (bs2 > 0)
7661181b21fSPeter Avalos 			bs = lshift(bs, bs2);
7671181b21fSPeter Avalos 		asub = 1;
7681181b21fSPeter Avalos 		inex = STRTOG_Inexhi;
7691181b21fSPeter Avalos 		delta = diff(bb, bd);
7701181b21fSPeter Avalos 		if (delta->wds <= 1 && !delta->x[0])
7711181b21fSPeter Avalos 			break;
7721181b21fSPeter Avalos 		dsign = delta->sign;
7731181b21fSPeter Avalos 		delta->sign = finished = 0;
7741181b21fSPeter Avalos 		L = 0;
7751181b21fSPeter Avalos 		i = cmp(delta, bs);
7761181b21fSPeter Avalos 		if (rd && i <= 0) {
7771181b21fSPeter Avalos 			irv = STRTOG_Normal;
7781181b21fSPeter Avalos 			if ( (finished = dsign ^ (rd&1)) !=0) {
7791181b21fSPeter Avalos 				if (dsign != 0) {
7801181b21fSPeter Avalos 					irv |= STRTOG_Inexhi;
7811181b21fSPeter Avalos 					goto adj1;
7821181b21fSPeter Avalos 					}
7831181b21fSPeter Avalos 				irv |= STRTOG_Inexlo;
7841181b21fSPeter Avalos 				if (rve1 == emin)
7851181b21fSPeter Avalos 					goto adj1;
7861181b21fSPeter Avalos 				for(i = 0, j = nbits; j >= ULbits;
7871181b21fSPeter Avalos 						i++, j -= ULbits) {
7881181b21fSPeter Avalos 					if (rvb->x[i] & ALL_ON)
7891181b21fSPeter Avalos 						goto adj1;
7901181b21fSPeter Avalos 					}
7911181b21fSPeter Avalos 				if (j > 1 && lo0bits(rvb->x + i) < j - 1)
7921181b21fSPeter Avalos 					goto adj1;
7931181b21fSPeter Avalos 				rve = rve1 - 1;
7941181b21fSPeter Avalos 				rvb = set_ones(rvb, rvbits = nbits);
7951181b21fSPeter Avalos 				break;
7961181b21fSPeter Avalos 				}
7971181b21fSPeter Avalos 			irv |= dsign ? STRTOG_Inexlo : STRTOG_Inexhi;
7981181b21fSPeter Avalos 			break;
7991181b21fSPeter Avalos 			}
8001181b21fSPeter Avalos 		if (i < 0) {
8011181b21fSPeter Avalos 			/* Error is less than half an ulp -- check for
8021181b21fSPeter Avalos 			 * special case of mantissa a power of two.
8031181b21fSPeter Avalos 			 */
8041181b21fSPeter Avalos 			irv = dsign
8051181b21fSPeter Avalos 				? STRTOG_Normal | STRTOG_Inexlo
8061181b21fSPeter Avalos 				: STRTOG_Normal | STRTOG_Inexhi;
8071181b21fSPeter Avalos 			if (dsign || bbbits > 1 || denorm || rve1 == emin)
8081181b21fSPeter Avalos 				break;
8091181b21fSPeter Avalos 			delta = lshift(delta,1);
8101181b21fSPeter Avalos 			if (cmp(delta, bs) > 0) {
8111181b21fSPeter Avalos 				irv = STRTOG_Normal | STRTOG_Inexlo;
8121181b21fSPeter Avalos 				goto drop_down;
8131181b21fSPeter Avalos 				}
8141181b21fSPeter Avalos 			break;
8151181b21fSPeter Avalos 			}
8161181b21fSPeter Avalos 		if (i == 0) {
8171181b21fSPeter Avalos 			/* exactly half-way between */
8181181b21fSPeter Avalos 			if (dsign) {
8191181b21fSPeter Avalos 				if (denorm && all_on(rvb, rvbits)) {
8201181b21fSPeter Avalos 					/*boundary case -- increment exponent*/
8211181b21fSPeter Avalos 					rvb->wds = 1;
8221181b21fSPeter Avalos 					rvb->x[0] = 1;
8231181b21fSPeter Avalos 					rve = emin + nbits - (rvbits = 1);
8241181b21fSPeter Avalos 					irv = STRTOG_Normal | STRTOG_Inexhi;
8251181b21fSPeter Avalos 					denorm = 0;
8261181b21fSPeter Avalos 					break;
8271181b21fSPeter Avalos 					}
8281181b21fSPeter Avalos 				irv = STRTOG_Normal | STRTOG_Inexlo;
8291181b21fSPeter Avalos 				}
8301181b21fSPeter Avalos 			else if (bbbits == 1) {
8311181b21fSPeter Avalos 				irv = STRTOG_Normal;
8321181b21fSPeter Avalos  drop_down:
8331181b21fSPeter Avalos 				/* boundary case -- decrement exponent */
8341181b21fSPeter Avalos 				if (rve1 == emin) {
8351181b21fSPeter Avalos 					irv = STRTOG_Normal | STRTOG_Inexhi;
8361181b21fSPeter Avalos 					if (rvb->wds == 1 && rvb->x[0] == 1)
8371181b21fSPeter Avalos 						sudden_underflow = 1;
8381181b21fSPeter Avalos 					break;
8391181b21fSPeter Avalos 					}
8401181b21fSPeter Avalos 				rve -= nbits;
8411181b21fSPeter Avalos 				rvb = set_ones(rvb, rvbits = nbits);
8421181b21fSPeter Avalos 				break;
8431181b21fSPeter Avalos 				}
8441181b21fSPeter Avalos 			else
8451181b21fSPeter Avalos 				irv = STRTOG_Normal | STRTOG_Inexhi;
8462a5b511eSPeter Avalos 			if ((bbbits < nbits && !denorm) || !(rvb->x[0] & 1))
8471181b21fSPeter Avalos 				break;
8481181b21fSPeter Avalos 			if (dsign) {
8491181b21fSPeter Avalos 				rvb = increment(rvb);
8501181b21fSPeter Avalos 				j = kmask & (ULbits - (rvbits & kmask));
8511181b21fSPeter Avalos 				if (hi0bits(rvb->x[rvb->wds - 1]) != j)
8521181b21fSPeter Avalos 					rvbits++;
8531181b21fSPeter Avalos 				irv = STRTOG_Normal | STRTOG_Inexhi;
8541181b21fSPeter Avalos 				}
8551181b21fSPeter Avalos 			else {
8561181b21fSPeter Avalos 				if (bbbits == 1)
8571181b21fSPeter Avalos 					goto undfl;
8581181b21fSPeter Avalos 				decrement(rvb);
8591181b21fSPeter Avalos 				irv = STRTOG_Normal | STRTOG_Inexlo;
8601181b21fSPeter Avalos 				}
8611181b21fSPeter Avalos 			break;
8621181b21fSPeter Avalos 			}
8632a5b511eSPeter Avalos 		if ((dval(&adj) = ratio(delta, bs)) <= 2.) {
8641181b21fSPeter Avalos  adj1:
8651181b21fSPeter Avalos 			inex = STRTOG_Inexlo;
8661181b21fSPeter Avalos 			if (dsign) {
8671181b21fSPeter Avalos 				asub = 0;
8681181b21fSPeter Avalos 				inex = STRTOG_Inexhi;
8691181b21fSPeter Avalos 				}
8701181b21fSPeter Avalos 			else if (denorm && bbbits <= 1) {
8711181b21fSPeter Avalos  undfl:
8721181b21fSPeter Avalos 				rvb->wds = 0;
8731181b21fSPeter Avalos 				rve = emin;
8741181b21fSPeter Avalos 				irv = STRTOG_Underflow | STRTOG_Inexlo;
8751181b21fSPeter Avalos 				break;
8761181b21fSPeter Avalos 				}
8772a5b511eSPeter Avalos 			adj0 = dval(&adj) = 1.;
8781181b21fSPeter Avalos 			}
8791181b21fSPeter Avalos 		else {
8802a5b511eSPeter Avalos 			adj0 = dval(&adj) *= 0.5;
8811181b21fSPeter Avalos 			if (dsign) {
8821181b21fSPeter Avalos 				asub = 0;
8831181b21fSPeter Avalos 				inex = STRTOG_Inexlo;
8841181b21fSPeter Avalos 				}
8852a5b511eSPeter Avalos 			if (dval(&adj) < 2147483647.) {
8861181b21fSPeter Avalos 				L = adj0;
8871181b21fSPeter Avalos 				adj0 -= L;
8881181b21fSPeter Avalos 				switch(rd) {
8891181b21fSPeter Avalos 				  case 0:
8901181b21fSPeter Avalos 					if (adj0 >= .5)
8911181b21fSPeter Avalos 						goto inc_L;
8921181b21fSPeter Avalos 					break;
8931181b21fSPeter Avalos 				  case 1:
8941181b21fSPeter Avalos 					if (asub && adj0 > 0.)
8951181b21fSPeter Avalos 						goto inc_L;
8961181b21fSPeter Avalos 					break;
8971181b21fSPeter Avalos 				  case 2:
8981181b21fSPeter Avalos 					if (!asub && adj0 > 0.) {
8991181b21fSPeter Avalos  inc_L:
9001181b21fSPeter Avalos 						L++;
9011181b21fSPeter Avalos 						inex = STRTOG_Inexact - inex;
9021181b21fSPeter Avalos 						}
9031181b21fSPeter Avalos 				  }
9042a5b511eSPeter Avalos 				dval(&adj) = L;
9051181b21fSPeter Avalos 				}
9061181b21fSPeter Avalos 			}
9071181b21fSPeter Avalos 		y = rve + rvbits;
9081181b21fSPeter Avalos 
9092a5b511eSPeter Avalos 		/* adj *= ulp(dval(&rv)); */
9101181b21fSPeter Avalos 		/* if (asub) rv -= adj; else rv += adj; */
9111181b21fSPeter Avalos 
9121181b21fSPeter Avalos 		if (!denorm && rvbits < nbits) {
9131181b21fSPeter Avalos 			rvb = lshift(rvb, j = nbits - rvbits);
9141181b21fSPeter Avalos 			rve -= j;
9151181b21fSPeter Avalos 			rvbits = nbits;
9161181b21fSPeter Avalos 			}
9172a5b511eSPeter Avalos 		ab = d2b(dval(&adj), &abe, &abits);
9181181b21fSPeter Avalos 		if (abe < 0)
9191181b21fSPeter Avalos 			rshift(ab, -abe);
9201181b21fSPeter Avalos 		else if (abe > 0)
9211181b21fSPeter Avalos 			ab = lshift(ab, abe);
9221181b21fSPeter Avalos 		rvb0 = rvb;
9231181b21fSPeter Avalos 		if (asub) {
9241181b21fSPeter Avalos 			/* rv -= adj; */
9251181b21fSPeter Avalos 			j = hi0bits(rvb->x[rvb->wds-1]);
9261181b21fSPeter Avalos 			rvb = diff(rvb, ab);
9271181b21fSPeter Avalos 			k = rvb0->wds - 1;
9281181b21fSPeter Avalos 			if (denorm)
9291181b21fSPeter Avalos 				/* do nothing */;
9301181b21fSPeter Avalos 			else if (rvb->wds <= k
9311181b21fSPeter Avalos 				|| hi0bits( rvb->x[k]) >
9321181b21fSPeter Avalos 				   hi0bits(rvb0->x[k])) {
9331181b21fSPeter Avalos 				/* unlikely; can only have lost 1 high bit */
9341181b21fSPeter Avalos 				if (rve1 == emin) {
9351181b21fSPeter Avalos 					--rvbits;
9361181b21fSPeter Avalos 					denorm = 1;
9371181b21fSPeter Avalos 					}
9381181b21fSPeter Avalos 				else {
9391181b21fSPeter Avalos 					rvb = lshift(rvb, 1);
9401181b21fSPeter Avalos 					--rve;
9411181b21fSPeter Avalos 					--rve1;
9421181b21fSPeter Avalos 					L = finished = 0;
9431181b21fSPeter Avalos 					}
9441181b21fSPeter Avalos 				}
9451181b21fSPeter Avalos 			}
9461181b21fSPeter Avalos 		else {
9471181b21fSPeter Avalos 			rvb = sum(rvb, ab);
9481181b21fSPeter Avalos 			k = rvb->wds - 1;
9491181b21fSPeter Avalos 			if (k >= rvb0->wds
9501181b21fSPeter Avalos 			 || hi0bits(rvb->x[k]) < hi0bits(rvb0->x[k])) {
9511181b21fSPeter Avalos 				if (denorm) {
9521181b21fSPeter Avalos 					if (++rvbits == nbits)
9531181b21fSPeter Avalos 						denorm = 0;
9541181b21fSPeter Avalos 					}
9551181b21fSPeter Avalos 				else {
9561181b21fSPeter Avalos 					rshift(rvb, 1);
9571181b21fSPeter Avalos 					rve++;
9581181b21fSPeter Avalos 					rve1++;
9591181b21fSPeter Avalos 					L = 0;
9601181b21fSPeter Avalos 					}
9611181b21fSPeter Avalos 				}
9621181b21fSPeter Avalos 			}
9631181b21fSPeter Avalos 		Bfree(ab);
9641181b21fSPeter Avalos 		Bfree(rvb0);
9651181b21fSPeter Avalos 		if (finished)
9661181b21fSPeter Avalos 			break;
9671181b21fSPeter Avalos 
9681181b21fSPeter Avalos 		z = rve + rvbits;
9691181b21fSPeter Avalos 		if (y == z && L) {
9701181b21fSPeter Avalos 			/* Can we stop now? */
9712a5b511eSPeter Avalos 			tol = dval(&adj) * 5e-16; /* > max rel error */
9722a5b511eSPeter Avalos 			dval(&adj) = adj0 - .5;
9732a5b511eSPeter Avalos 			if (dval(&adj) < -tol) {
9741181b21fSPeter Avalos 				if (adj0 > tol) {
9751181b21fSPeter Avalos 					irv |= inex;
9761181b21fSPeter Avalos 					break;
9771181b21fSPeter Avalos 					}
9781181b21fSPeter Avalos 				}
9792a5b511eSPeter Avalos 			else if (dval(&adj) > tol && adj0 < 1. - tol) {
9801181b21fSPeter Avalos 				irv |= inex;
9811181b21fSPeter Avalos 				break;
9821181b21fSPeter Avalos 				}
9831181b21fSPeter Avalos 			}
9841181b21fSPeter Avalos 		bb0 = denorm ? 0 : trailz(rvb);
9851181b21fSPeter Avalos 		Bfree(bb);
9861181b21fSPeter Avalos 		Bfree(bd);
9871181b21fSPeter Avalos 		Bfree(bs);
9881181b21fSPeter Avalos 		Bfree(delta);
9891181b21fSPeter Avalos 		}
9901181b21fSPeter Avalos 	if (!denorm && (j = nbits - rvbits)) {
9911181b21fSPeter Avalos 		if (j > 0)
9921181b21fSPeter Avalos 			rvb = lshift(rvb, j);
9931181b21fSPeter Avalos 		else
9941181b21fSPeter Avalos 			rshift(rvb, -j);
9951181b21fSPeter Avalos 		rve -= j;
9961181b21fSPeter Avalos 		}
9971181b21fSPeter Avalos 	*exp = rve;
9981181b21fSPeter Avalos 	Bfree(bb);
9991181b21fSPeter Avalos 	Bfree(bd);
10001181b21fSPeter Avalos 	Bfree(bs);
10011181b21fSPeter Avalos 	Bfree(bd0);
10021181b21fSPeter Avalos 	Bfree(delta);
10031181b21fSPeter Avalos 	if (rve > fpi->emax) {
10041181b21fSPeter Avalos 		switch(fpi->rounding & 3) {
10051181b21fSPeter Avalos 		  case FPI_Round_near:
10061181b21fSPeter Avalos 			goto huge;
10071181b21fSPeter Avalos 		  case FPI_Round_up:
10081181b21fSPeter Avalos 			if (!sign)
10091181b21fSPeter Avalos 				goto huge;
10101181b21fSPeter Avalos 			break;
10111181b21fSPeter Avalos 		  case FPI_Round_down:
10121181b21fSPeter Avalos 			if (sign)
10131181b21fSPeter Avalos 				goto huge;
10141181b21fSPeter Avalos 		  }
10151181b21fSPeter Avalos 		/* Round to largest representable magnitude */
10161181b21fSPeter Avalos 		Bfree(rvb);
10171181b21fSPeter Avalos 		rvb = 0;
10181181b21fSPeter Avalos 		irv = STRTOG_Normal | STRTOG_Inexlo;
10191181b21fSPeter Avalos 		*exp = fpi->emax;
10201181b21fSPeter Avalos 		b = bits;
10211181b21fSPeter Avalos 		be = b + ((fpi->nbits + 31) >> 5);
10221181b21fSPeter Avalos 		while(b < be)
10231181b21fSPeter Avalos 			*b++ = -1;
10241181b21fSPeter Avalos 		if ((j = fpi->nbits & 0x1f))
10251181b21fSPeter Avalos 			*--be >>= (32 - j);
10261181b21fSPeter Avalos 		goto ret;
10271181b21fSPeter Avalos  huge:
10281181b21fSPeter Avalos 		rvb->wds = 0;
10291181b21fSPeter Avalos 		irv = STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
10301181b21fSPeter Avalos #ifndef NO_ERRNO
10311181b21fSPeter Avalos 		errno = ERANGE;
10321181b21fSPeter Avalos #endif
10331181b21fSPeter Avalos  infnanexp:
10341181b21fSPeter Avalos 		*exp = fpi->emax + 1;
10351181b21fSPeter Avalos 		}
10361181b21fSPeter Avalos  ret:
10371181b21fSPeter Avalos 	if (denorm) {
10381181b21fSPeter Avalos 		if (sudden_underflow) {
10391181b21fSPeter Avalos 			rvb->wds = 0;
10401181b21fSPeter Avalos 			irv = STRTOG_Underflow | STRTOG_Inexlo;
10411181b21fSPeter Avalos #ifndef NO_ERRNO
10421181b21fSPeter Avalos 			errno = ERANGE;
10431181b21fSPeter Avalos #endif
10441181b21fSPeter Avalos 			}
10451181b21fSPeter Avalos 		else  {
10461181b21fSPeter Avalos 			irv = (irv & ~STRTOG_Retmask) |
10471181b21fSPeter Avalos 				(rvb->wds > 0 ? STRTOG_Denormal : STRTOG_Zero);
10481181b21fSPeter Avalos 			if (irv & STRTOG_Inexact) {
10491181b21fSPeter Avalos 				irv |= STRTOG_Underflow;
10501181b21fSPeter Avalos #ifndef NO_ERRNO
10511181b21fSPeter Avalos 				errno = ERANGE;
10521181b21fSPeter Avalos #endif
10531181b21fSPeter Avalos 				}
10541181b21fSPeter Avalos 			}
10551181b21fSPeter Avalos 		}
10561181b21fSPeter Avalos 	if (se)
10571181b21fSPeter Avalos 		*se = (char *)s;
10581181b21fSPeter Avalos 	if (sign)
10591181b21fSPeter Avalos 		irv |= STRTOG_Neg;
10601181b21fSPeter Avalos 	if (rvb) {
10611181b21fSPeter Avalos 		copybits(bits, nbits, rvb);
10621181b21fSPeter Avalos 		Bfree(rvb);
10631181b21fSPeter Avalos 		}
10641181b21fSPeter Avalos 	return irv;
10651181b21fSPeter Avalos 	}
1066