xref: /netbsd-src/lib/libc/gdtoa/strtodg.c (revision 9feb722ead58d8a751d6d81d917a158e180ce5c0)
1*9feb722eSchristos /* $NetBSD: strtodg.c,v 1.13 2021/05/06 16:15:33 christos Exp $ */
27684d5e0Skleink 
37684d5e0Skleink /****************************************************************
47684d5e0Skleink 
57684d5e0Skleink The author of this software is David M. Gay.
67684d5e0Skleink 
77684d5e0Skleink Copyright (C) 1998-2001 by Lucent Technologies
87684d5e0Skleink All Rights Reserved
97684d5e0Skleink 
107684d5e0Skleink Permission to use, copy, modify, and distribute this software and
117684d5e0Skleink its documentation for any purpose and without fee is hereby
127684d5e0Skleink granted, provided that the above copyright notice appear in all
137684d5e0Skleink copies and that both that the copyright notice and this
147684d5e0Skleink permission notice and warranty disclaimer appear in supporting
157684d5e0Skleink documentation, and that the name of Lucent or any of its entities
167684d5e0Skleink not be used in advertising or publicity pertaining to
177684d5e0Skleink distribution of the software without specific, written prior
187684d5e0Skleink permission.
197684d5e0Skleink 
207684d5e0Skleink LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
217684d5e0Skleink INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
227684d5e0Skleink IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
237684d5e0Skleink SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
247684d5e0Skleink WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
257684d5e0Skleink IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
267684d5e0Skleink ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
277684d5e0Skleink THIS SOFTWARE.
287684d5e0Skleink 
297684d5e0Skleink ****************************************************************/
307684d5e0Skleink 
317684d5e0Skleink /* Please send bug reports to David M. Gay (dmg at acm dot org,
327684d5e0Skleink  * with " at " changed at "@" and " dot " changed to ".").	*/
337684d5e0Skleink 
347684d5e0Skleink #include "gdtoaimp.h"
357684d5e0Skleink 
367684d5e0Skleink #ifdef USE_LOCALE
377684d5e0Skleink #include "locale.h"
387684d5e0Skleink #endif
397684d5e0Skleink 
40648512f8She #ifndef VAX
417684d5e0Skleink  static CONST int
427684d5e0Skleink fivesbits[] = {	 0,  3,  5,  7, 10, 12, 14, 17, 19, 21,
437684d5e0Skleink 		24, 26, 28, 31, 33, 35, 38, 40, 42, 45,
447684d5e0Skleink 		47, 49, 52
457684d5e0Skleink 		};
46648512f8She #endif
477684d5e0Skleink 
487684d5e0Skleink  Bigint *
497684d5e0Skleink #ifdef KR_headers
increment(b)507684d5e0Skleink increment(b) Bigint *b;
517684d5e0Skleink #else
527684d5e0Skleink increment(Bigint *b)
537684d5e0Skleink #endif
547684d5e0Skleink {
557684d5e0Skleink 	ULong *x, *xe;
567684d5e0Skleink 	Bigint *b1;
577684d5e0Skleink #ifdef Pack_16
587684d5e0Skleink 	ULong carry = 1, y;
597684d5e0Skleink #endif
607684d5e0Skleink 
617684d5e0Skleink 	x = b->x;
627684d5e0Skleink 	xe = x + b->wds;
637684d5e0Skleink #ifdef Pack_32
647684d5e0Skleink 	do {
657684d5e0Skleink 		if (*x < (ULong)0xffffffffL) {
667684d5e0Skleink 			++*x;
677684d5e0Skleink 			return b;
687684d5e0Skleink 			}
697684d5e0Skleink 		*x++ = 0;
707684d5e0Skleink 		} while(x < xe);
717684d5e0Skleink #else
727684d5e0Skleink 	do {
737684d5e0Skleink 		y = *x + carry;
747684d5e0Skleink 		carry = y >> 16;
757684d5e0Skleink 		*x++ = y & 0xffff;
767684d5e0Skleink 		if (!carry)
777684d5e0Skleink 			return b;
787684d5e0Skleink 		} while(x < xe);
797684d5e0Skleink 	if (carry)
807684d5e0Skleink #endif
817684d5e0Skleink 	{
827684d5e0Skleink 		if (b->wds >= b->maxwds) {
837684d5e0Skleink 			b1 = Balloc(b->k+1);
84ab625449Schristos 			if (b1 == NULL)
85ab625449Schristos 				return NULL;
867684d5e0Skleink 			Bcopy(b1,b);
877684d5e0Skleink 			Bfree(b);
887684d5e0Skleink 			b = b1;
897684d5e0Skleink 			}
907684d5e0Skleink 		b->x[b->wds++] = 1;
917684d5e0Skleink 		}
927684d5e0Skleink 	return b;
937684d5e0Skleink 	}
947684d5e0Skleink 
9561e56760Schristos  void
967684d5e0Skleink #ifdef KR_headers
decrement(b)977684d5e0Skleink decrement(b) Bigint *b;
987684d5e0Skleink #else
997684d5e0Skleink decrement(Bigint *b)
1007684d5e0Skleink #endif
1017684d5e0Skleink {
1027684d5e0Skleink 	ULong *x, *xe;
1037684d5e0Skleink #ifdef Pack_16
1047684d5e0Skleink 	ULong borrow = 1, y;
1057684d5e0Skleink #endif
1067684d5e0Skleink 
1077684d5e0Skleink 	x = b->x;
1087684d5e0Skleink 	xe = x + b->wds;
1097684d5e0Skleink #ifdef Pack_32
1107684d5e0Skleink 	do {
1117684d5e0Skleink 		if (*x) {
1127684d5e0Skleink 			--*x;
1137684d5e0Skleink 			break;
1147684d5e0Skleink 			}
115ac898a26Skleink 		*x++ = 0xffffffffUL;
1167684d5e0Skleink 		}
1177684d5e0Skleink 		while(x < xe);
1187684d5e0Skleink #else
1197684d5e0Skleink 	do {
1207684d5e0Skleink 		y = *x - borrow;
1217684d5e0Skleink 		borrow = (y & 0x10000) >> 16;
1227684d5e0Skleink 		*x++ = y & 0xffff;
1237684d5e0Skleink 		} while(borrow && x < xe);
1247684d5e0Skleink #endif
1257684d5e0Skleink 	}
1267684d5e0Skleink 
1277684d5e0Skleink  static int
1287684d5e0Skleink #ifdef KR_headers
all_on(b,n)129f8228ce4Skleink all_on(b, n) CONST Bigint *b; int n;
1307684d5e0Skleink #else
131f8228ce4Skleink all_on(CONST Bigint *b, int n)
1327684d5e0Skleink #endif
1337684d5e0Skleink {
134f8228ce4Skleink 	CONST ULong *x, *xe;
1357684d5e0Skleink 
1367684d5e0Skleink 	x = b->x;
137ac898a26Skleink 	xe = x + ((unsigned int)n >> kshift);
1387684d5e0Skleink 	while(x < xe)
1397684d5e0Skleink 		if ((*x++ & ALL_ON) != ALL_ON)
1407684d5e0Skleink 			return 0;
1417684d5e0Skleink 	if (n &= kmask)
1427684d5e0Skleink 		return ((*x | (ALL_ON << n)) & ALL_ON) == ALL_ON;
1437684d5e0Skleink 	return 1;
1447684d5e0Skleink 	}
1457684d5e0Skleink 
1467684d5e0Skleink  Bigint *
1477684d5e0Skleink #ifdef KR_headers
set_ones(b,n)1487684d5e0Skleink set_ones(b, n) Bigint *b; int n;
1497684d5e0Skleink #else
1507684d5e0Skleink set_ones(Bigint *b, int n)
1517684d5e0Skleink #endif
1527684d5e0Skleink {
1537684d5e0Skleink 	int k;
1547684d5e0Skleink 	ULong *x, *xe;
1557684d5e0Skleink 
156ac898a26Skleink 	k = (unsigned int)(n + ((1 << kshift) - 1)) >> kshift;
1577684d5e0Skleink 	if (b->k < k) {
1587684d5e0Skleink 		Bfree(b);
1597684d5e0Skleink 		b = Balloc(k);
160ab625449Schristos 		if (b == NULL)
161ab625449Schristos 			return NULL;
1627684d5e0Skleink 		}
163ac898a26Skleink 	k = (unsigned int)n >> kshift;
1647684d5e0Skleink 	if (n &= kmask)
1657684d5e0Skleink 		k++;
1667684d5e0Skleink 	b->wds = k;
1677684d5e0Skleink 	x = b->x;
1687684d5e0Skleink 	xe = x + k;
1697684d5e0Skleink 	while(x < xe)
1707684d5e0Skleink 		*x++ = ALL_ON;
1717684d5e0Skleink 	if (n)
1727684d5e0Skleink 		x[-1] >>= ULbits - n;
1737684d5e0Skleink 	return b;
1747684d5e0Skleink 	}
1757684d5e0Skleink 
1767684d5e0Skleink  static int
rvOK(d,fpi,expt,bits,exact,rd,irv)1777684d5e0Skleink rvOK
1787684d5e0Skleink #ifdef KR_headers
179ac898a26Skleink  (d, fpi, expt, bits, exact, rd, irv)
18061e56760Schristos  U *d; CONST FPI *fpi; Long *expt; ULong *bits; int exact, rd, *irv;
1817684d5e0Skleink #else
18261e56760Schristos  (U *d, CONST FPI *fpi, Long *expt, ULong *bits, int exact, int rd, int *irv)
1837684d5e0Skleink #endif
1847684d5e0Skleink {
1857684d5e0Skleink 	Bigint *b;
1867684d5e0Skleink 	ULong carry, inex, lostbits;
1877684d5e0Skleink 	int bdif, e, j, k, k1, nb, rv;
1887684d5e0Skleink 
1897684d5e0Skleink 	carry = rv = 0;
19061e56760Schristos 	b = d2b(dval(d), &e, &bdif);
1917684d5e0Skleink 	bdif -= nb = fpi->nbits;
1927684d5e0Skleink 	e += bdif;
1937684d5e0Skleink 	if (bdif <= 0) {
1947684d5e0Skleink 		if (exact)
1957684d5e0Skleink 			goto trunc;
1967684d5e0Skleink 		goto ret;
1977684d5e0Skleink 		}
1987684d5e0Skleink 	if (P == nb) {
1997684d5e0Skleink 		if (
2007684d5e0Skleink #ifndef IMPRECISE_INEXACT
2017684d5e0Skleink 			exact &&
2027684d5e0Skleink #endif
2037684d5e0Skleink 			fpi->rounding ==
2047684d5e0Skleink #ifdef RND_PRODQUOT
2057684d5e0Skleink 					FPI_Round_near
2067684d5e0Skleink #else
2077684d5e0Skleink 					Flt_Rounds
2087684d5e0Skleink #endif
2097684d5e0Skleink 			) goto trunc;
2107684d5e0Skleink 		goto ret;
2117684d5e0Skleink 		}
2127684d5e0Skleink 	switch(rd) {
21361e56760Schristos 	  case 1: /* round down (toward -Infinity) */
2147684d5e0Skleink 		goto trunc;
21561e56760Schristos 	  case 2: /* round up (toward +Infinity) */
2167684d5e0Skleink 		break;
2177684d5e0Skleink 	  default: /* round near */
2187684d5e0Skleink 		k = bdif - 1;
2197684d5e0Skleink 		if (!k) {
2207684d5e0Skleink 			if (!exact)
2217684d5e0Skleink 				goto ret;
2227684d5e0Skleink 			if (b->x[0] & 2)
2237684d5e0Skleink 				break;
2247684d5e0Skleink 			goto trunc;
2257684d5e0Skleink 			}
226ac898a26Skleink 		if (b->x[(unsigned int)k>>kshift] & ((ULong)1 << (k & kmask)))
2277684d5e0Skleink 			break;
2287684d5e0Skleink 		goto trunc;
2297684d5e0Skleink 	  }
2307684d5e0Skleink 	/* "break" cases: round up 1 bit, then truncate; bdif > 0 */
2317684d5e0Skleink 	carry = 1;
2327684d5e0Skleink  trunc:
2337684d5e0Skleink 	inex = lostbits = 0;
2347684d5e0Skleink 	if (bdif > 0) {
2357684d5e0Skleink 		if ( (lostbits = any_on(b, bdif)) !=0)
2367684d5e0Skleink 			inex = STRTOG_Inexlo;
2377684d5e0Skleink 		rshift(b, bdif);
2387684d5e0Skleink 		if (carry) {
2397684d5e0Skleink 			inex = STRTOG_Inexhi;
2407684d5e0Skleink 			b = increment(b);
2417684d5e0Skleink 			if ( (j = nb & kmask) !=0)
2427684d5e0Skleink 				j = ULbits - j;
2437684d5e0Skleink 			if (hi0bits(b->x[b->wds - 1]) != j) {
2447684d5e0Skleink 				if (!lostbits)
2457684d5e0Skleink 					lostbits = b->x[0] & 1;
2467684d5e0Skleink 				rshift(b, 1);
2477684d5e0Skleink 				e++;
2487684d5e0Skleink 				}
2497684d5e0Skleink 			}
2507684d5e0Skleink 		}
251*9feb722eSchristos 	else if (bdif < 0) {
2527684d5e0Skleink 		b = lshift(b, -bdif);
253*9feb722eSchristos 		if (b == NULL)
254*9feb722eSchristos 			return STRTOG_NoMemory;
255*9feb722eSchristos 		}
2567684d5e0Skleink 	if (e < fpi->emin) {
2577684d5e0Skleink 		k = fpi->emin - e;
2587684d5e0Skleink 		e = fpi->emin;
2597684d5e0Skleink 		if (k > nb || fpi->sudden_underflow) {
2607684d5e0Skleink 			b->wds = inex = 0;
2617684d5e0Skleink 			*irv = STRTOG_Underflow | STRTOG_Inexlo;
2627684d5e0Skleink 			}
2637684d5e0Skleink 		else {
2647684d5e0Skleink 			k1 = k - 1;
2657684d5e0Skleink 			if (k1 > 0 && !lostbits)
2667684d5e0Skleink 				lostbits = any_on(b, k1);
2677684d5e0Skleink 			if (!lostbits && !exact)
2687684d5e0Skleink 				goto ret;
2697684d5e0Skleink 			lostbits |=
270ac898a26Skleink 			  carry = b->x[(unsigned int)k1>>kshift] &
271ac898a26Skleink 			               (1 << (k1 & kmask));
2727684d5e0Skleink 			rshift(b, k);
2737684d5e0Skleink 			*irv = STRTOG_Denormal;
2747684d5e0Skleink 			if (carry) {
2757684d5e0Skleink 				b = increment(b);
2767684d5e0Skleink 				inex = STRTOG_Inexhi | STRTOG_Underflow;
2777684d5e0Skleink 				}
2787684d5e0Skleink 			else if (lostbits)
2797684d5e0Skleink 				inex = STRTOG_Inexlo | STRTOG_Underflow;
2807684d5e0Skleink 			}
2817684d5e0Skleink 		}
2827684d5e0Skleink 	else if (e > fpi->emax) {
2837684d5e0Skleink 		e = fpi->emax + 1;
2847684d5e0Skleink 		*irv = STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
2857684d5e0Skleink #ifndef NO_ERRNO
2867684d5e0Skleink 		errno = ERANGE;
2877684d5e0Skleink #endif
2887684d5e0Skleink 		b->wds = inex = 0;
2897684d5e0Skleink 		}
290ac898a26Skleink 	*expt = e;
2917684d5e0Skleink 	copybits(bits, nb, b);
2927684d5e0Skleink 	*irv |= inex;
2937684d5e0Skleink 	rv = 1;
2947684d5e0Skleink  ret:
2957684d5e0Skleink 	Bfree(b);
2967684d5e0Skleink 	return rv;
2977684d5e0Skleink 	}
2987684d5e0Skleink 
299ac898a26Skleink #ifndef VAX
3007684d5e0Skleink  static int
3017684d5e0Skleink #ifdef KR_headers
mantbits(d)30261e56760Schristos mantbits(d) U *d;
3037684d5e0Skleink #else
30461e56760Schristos mantbits(U *d)
3057684d5e0Skleink #endif
3067684d5e0Skleink {
3077684d5e0Skleink 	ULong L;
3087684d5e0Skleink #ifdef VAX
3097684d5e0Skleink 	L = word1(d) << 16 | word1(d) >> 16;
3107684d5e0Skleink 	if (L)
3117684d5e0Skleink #else
3127684d5e0Skleink 	if ( (L = word1(d)) !=0)
3137684d5e0Skleink #endif
3147684d5e0Skleink 		return P - lo0bits(&L);
3157684d5e0Skleink #ifdef VAX
3167684d5e0Skleink 	L = word0(d) << 16 | word0(d) >> 16 | Exp_msk11;
3177684d5e0Skleink #else
3187684d5e0Skleink 	L = word0(d) | Exp_msk1;
3197684d5e0Skleink #endif
3207684d5e0Skleink 	return P - 32 - lo0bits(&L);
3217684d5e0Skleink 	}
322ac898a26Skleink #endif /* !VAX */
3237684d5e0Skleink 
3247684d5e0Skleink  int
strtodg(CONST char * s00,char ** se,CONST FPI * fpi,Long * expt,ULong * bits,locale_t loc)325c99aac45Sjoerg strtodg(CONST char *s00, char **se, CONST FPI *fpi, Long *expt, ULong *bits,
326c99aac45Sjoerg 	locale_t loc)
3277684d5e0Skleink {
3287684d5e0Skleink 	int abe, abits, asub;
329648512f8She #ifdef INFNAN_CHECK
330648512f8She 	int decpt;
331648512f8She #endif
332648512f8She 	int bb0, bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, denorm;
3337684d5e0Skleink 	int dsign, e, e1, e2, emin, esign, finished, i, inex, irv;
3347684d5e0Skleink 	int j, k, nbits, nd, nd0, nf, nz, nz0, rd, rvbits, rve, rve1, sign;
335ac898a26Skleink 	int sudden_underflow = 0; /* pacify gcc */
3367684d5e0Skleink 	CONST char *s, *s0, *s1;
33761e56760Schristos 	double adj0, tol;
3387684d5e0Skleink 	Long L;
33961e56760Schristos 	U adj, rv;
34061e56760Schristos 	ULong *b, *be, y, z;
3417684d5e0Skleink 	Bigint *ab, *bb, *bb1, *bd, *bd0, *bs, *delta, *rvb, *rvb0;
34261e56760Schristos #ifdef USE_LOCALE /*{{*/
343c99aac45Sjoerg 	char *decimalpoint = localeconv_l(loc)->decimal_point;
34461e56760Schristos 	size_t dplen = strlen(decimalpoint);
34561e56760Schristos #endif /*USE_LOCALE}}*/
3467684d5e0Skleink 
347da78757bSmrg 	e2 = 0;	/* XXX gcc */
348da78757bSmrg 
3497684d5e0Skleink 	irv = STRTOG_Zero;
3507684d5e0Skleink 	denorm = sign = nz0 = nz = 0;
35161e56760Schristos 	dval(&rv) = 0.;
3527684d5e0Skleink 	rvb = 0;
3537684d5e0Skleink 	nbits = fpi->nbits;
3547684d5e0Skleink 	for(s = s00;;s++) switch(*s) {
3557684d5e0Skleink 		case '-':
3567684d5e0Skleink 			sign = 1;
357ac898a26Skleink 			/* FALLTHROUGH */
3587684d5e0Skleink 		case '+':
3597684d5e0Skleink 			if (*++s)
3607684d5e0Skleink 				goto break2;
361ac898a26Skleink 			/* FALLTHROUGH */
3627684d5e0Skleink 		case 0:
3637684d5e0Skleink 			sign = 0;
3647684d5e0Skleink 			irv = STRTOG_NoNumber;
3657684d5e0Skleink 			s = s00;
3667684d5e0Skleink 			goto ret;
3677684d5e0Skleink 		case '\t':
3687684d5e0Skleink 		case '\n':
3697684d5e0Skleink 		case '\v':
3707684d5e0Skleink 		case '\f':
3717684d5e0Skleink 		case '\r':
3727684d5e0Skleink 		case ' ':
3737684d5e0Skleink 			continue;
3747684d5e0Skleink 		default:
3757684d5e0Skleink 			goto break2;
3767684d5e0Skleink 		}
3777684d5e0Skleink  break2:
3787684d5e0Skleink 	if (*s == '0') {
3797684d5e0Skleink #ifndef NO_HEX_FP
3807684d5e0Skleink 		switch(s[1]) {
3817684d5e0Skleink 		  case 'x':
3827684d5e0Skleink 		  case 'X':
3830feb0f12Sjoerg 			irv = gethex(&s, fpi, expt, &rvb, sign, loc);
3847684d5e0Skleink 			if (irv == STRTOG_NoNumber) {
3857684d5e0Skleink 				s = s00;
3867684d5e0Skleink 				sign = 0;
3877684d5e0Skleink 				}
3887684d5e0Skleink 			goto ret;
3897684d5e0Skleink 		  }
3907684d5e0Skleink #endif
3917684d5e0Skleink 		nz0 = 1;
3927684d5e0Skleink 		while(*++s == '0') ;
3937684d5e0Skleink 		if (!*s)
3947684d5e0Skleink 			goto ret;
3957684d5e0Skleink 		}
3967684d5e0Skleink 	sudden_underflow = fpi->sudden_underflow;
3977684d5e0Skleink 	s0 = s;
3987684d5e0Skleink 	y = z = 0;
399648512f8She #ifdef INFNAN_CHECK
400648512f8She 	decpt = 0;
401648512f8She #endif
402648512f8She 	for(nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++)
4037684d5e0Skleink 		if (nd < 9)
4047684d5e0Skleink 			y = 10*y + c - '0';
4057684d5e0Skleink 		else if (nd < 16)
4067684d5e0Skleink 			z = 10*z + c - '0';
4077684d5e0Skleink 	nd0 = nd;
4087684d5e0Skleink #ifdef USE_LOCALE
40961e56760Schristos 	if (c == *decimalpoint) {
41061e56760Schristos 		for(i = 1; decimalpoint[i]; ++i)
41161e56760Schristos 			if (s[i] != decimalpoint[i])
41261e56760Schristos 				goto dig_done;
41361e56760Schristos 		s += i;
41461e56760Schristos 		c = *s;
4157684d5e0Skleink #else
41661e56760Schristos 	if (c == '.') {
4177684d5e0Skleink 		c = *++s;
41861e56760Schristos #endif
419648512f8She #ifdef INFNAN_CHECK
42061e56760Schristos 		decpt = 1;
421648512f8She #endif
4227684d5e0Skleink 		if (!nd) {
4237684d5e0Skleink 			for(; c == '0'; c = *++s)
4247684d5e0Skleink 				nz++;
4257684d5e0Skleink 			if (c > '0' && c <= '9') {
4267684d5e0Skleink 				s0 = s;
4277684d5e0Skleink 				nf += nz;
4287684d5e0Skleink 				nz = 0;
4297684d5e0Skleink 				goto have_dig;
4307684d5e0Skleink 				}
4317684d5e0Skleink 			goto dig_done;
4327684d5e0Skleink 			}
4337684d5e0Skleink 		for(; c >= '0' && c <= '9'; c = *++s) {
4347684d5e0Skleink  have_dig:
4357684d5e0Skleink 			nz++;
4367684d5e0Skleink 			if (c -= '0') {
4377684d5e0Skleink 				nf += nz;
4387684d5e0Skleink 				for(i = 1; i < nz; i++)
4397684d5e0Skleink 					if (nd++ < 9)
4407684d5e0Skleink 						y *= 10;
4417684d5e0Skleink 					else if (nd <= DBL_DIG + 1)
4427684d5e0Skleink 						z *= 10;
4437684d5e0Skleink 				if (nd++ < 9)
4447684d5e0Skleink 					y = 10*y + c;
4457684d5e0Skleink 				else if (nd <= DBL_DIG + 1)
4467684d5e0Skleink 					z = 10*z + c;
4477684d5e0Skleink 				nz = 0;
4487684d5e0Skleink 				}
4497684d5e0Skleink 			}
45061e56760Schristos 		}/*}*/
4517684d5e0Skleink  dig_done:
4527684d5e0Skleink 	e = 0;
4537684d5e0Skleink 	if (c == 'e' || c == 'E') {
4547684d5e0Skleink 		if (!nd && !nz && !nz0) {
4557684d5e0Skleink 			irv = STRTOG_NoNumber;
4567684d5e0Skleink 			s = s00;
4577684d5e0Skleink 			goto ret;
4587684d5e0Skleink 			}
4597684d5e0Skleink 		s00 = s;
4607684d5e0Skleink 		esign = 0;
4617684d5e0Skleink 		switch(c = *++s) {
4627684d5e0Skleink 			case '-':
4637684d5e0Skleink 				esign = 1;
464ac898a26Skleink 				/* FALLTHROUGH */
4657684d5e0Skleink 			case '+':
4667684d5e0Skleink 				c = *++s;
4677684d5e0Skleink 			}
4687684d5e0Skleink 		if (c >= '0' && c <= '9') {
4697684d5e0Skleink 			while(c == '0')
4707684d5e0Skleink 				c = *++s;
4717684d5e0Skleink 			if (c > '0' && c <= '9') {
4727684d5e0Skleink 				L = c - '0';
4737684d5e0Skleink 				s1 = s;
4747684d5e0Skleink 				while((c = *++s) >= '0' && c <= '9')
4757684d5e0Skleink 					L = 10*L + c - '0';
4767684d5e0Skleink 				if (s - s1 > 8 || L > 19999)
4777684d5e0Skleink 					/* Avoid confusion from exponents
4787684d5e0Skleink 					 * so large that e might overflow.
4797684d5e0Skleink 					 */
4807684d5e0Skleink 					e = 19999; /* safe for 16 bit ints */
4817684d5e0Skleink 				else
4827684d5e0Skleink 					e = (int)L;
4837684d5e0Skleink 				if (esign)
4847684d5e0Skleink 					e = -e;
4857684d5e0Skleink 				}
4867684d5e0Skleink 			else
4877684d5e0Skleink 				e = 0;
4887684d5e0Skleink 			}
4897684d5e0Skleink 		else
4907684d5e0Skleink 			s = s00;
4917684d5e0Skleink 		}
4927684d5e0Skleink 	if (!nd) {
4937684d5e0Skleink 		if (!nz && !nz0) {
4947684d5e0Skleink #ifdef INFNAN_CHECK
4957684d5e0Skleink 			/* Check for Nan and Infinity */
4967684d5e0Skleink 			if (!decpt)
4977684d5e0Skleink 			 switch(c) {
4987684d5e0Skleink 			  case 'i':
4997684d5e0Skleink 			  case 'I':
5007684d5e0Skleink 				if (match(&s,"nf")) {
5017684d5e0Skleink 					--s;
5027684d5e0Skleink 					if (!match(&s,"inity"))
5037684d5e0Skleink 						++s;
5047684d5e0Skleink 					irv = STRTOG_Infinite;
5057684d5e0Skleink 					goto infnanexp;
5067684d5e0Skleink 					}
5077684d5e0Skleink 				break;
5087684d5e0Skleink 			  case 'n':
5097684d5e0Skleink 			  case 'N':
5107684d5e0Skleink 				if (match(&s, "an")) {
5117684d5e0Skleink 					irv = STRTOG_NaN;
512ac898a26Skleink 					*expt = fpi->emax + 1;
5137684d5e0Skleink #ifndef No_Hex_NaN
5147684d5e0Skleink 					if (*s == '(') /*)*/
5157684d5e0Skleink 						irv = hexnan(&s, fpi, bits);
5167684d5e0Skleink #endif
5177684d5e0Skleink 					goto infnanexp;
5187684d5e0Skleink 					}
5197684d5e0Skleink 			  }
5207684d5e0Skleink #endif /* INFNAN_CHECK */
5217684d5e0Skleink 			irv = STRTOG_NoNumber;
5227684d5e0Skleink 			s = s00;
5237684d5e0Skleink 			}
5247684d5e0Skleink 		goto ret;
5257684d5e0Skleink 		}
5267684d5e0Skleink 
5277684d5e0Skleink 	irv = STRTOG_Normal;
5287684d5e0Skleink 	e1 = e -= nf;
5297684d5e0Skleink 	rd = 0;
5307684d5e0Skleink 	switch(fpi->rounding & 3) {
5317684d5e0Skleink 	  case FPI_Round_up:
5327684d5e0Skleink 		rd = 2 - sign;
5337684d5e0Skleink 		break;
5347684d5e0Skleink 	  case FPI_Round_zero:
5357684d5e0Skleink 		rd = 1;
5367684d5e0Skleink 		break;
5377684d5e0Skleink 	  case FPI_Round_down:
5387684d5e0Skleink 		rd = 1 + sign;
5397684d5e0Skleink 	  }
5407684d5e0Skleink 
5417684d5e0Skleink 	/* Now we have nd0 digits, starting at s0, followed by a
5427684d5e0Skleink 	 * decimal point, followed by nd-nd0 digits.  The number we're
5437684d5e0Skleink 	 * after is the integer represented by those digits times
5447684d5e0Skleink 	 * 10**e */
5457684d5e0Skleink 
5467684d5e0Skleink 	if (!nd0)
5477684d5e0Skleink 		nd0 = nd;
5487684d5e0Skleink 	k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
54961e56760Schristos 	dval(&rv) = y;
5507684d5e0Skleink 	if (k > 9)
55161e56760Schristos 		dval(&rv) = tens[k - 9] * dval(&rv) + z;
5527684d5e0Skleink 	bd0 = 0;
5537684d5e0Skleink 	if (nbits <= P && nd <= DBL_DIG) {
5547684d5e0Skleink 		if (!e) {
55561e56760Schristos 			if (rvOK(&rv, fpi, expt, bits, 1, rd, &irv))
5567684d5e0Skleink 				goto ret;
5577684d5e0Skleink 			}
5587684d5e0Skleink 		else if (e > 0) {
5597684d5e0Skleink 			if (e <= Ten_pmax) {
5607684d5e0Skleink #ifdef VAX
5617684d5e0Skleink 				goto vax_ovfl_check;
5627684d5e0Skleink #else
56361e56760Schristos 				i = fivesbits[e] + mantbits(&rv) <= P;
56461e56760Schristos 				/* rv = */ rounded_product(dval(&rv), tens[e]);
56561e56760Schristos 				if (rvOK(&rv, fpi, expt, bits, i, rd, &irv))
5667684d5e0Skleink 					goto ret;
5677684d5e0Skleink 				e1 -= e;
5687684d5e0Skleink 				goto rv_notOK;
5697684d5e0Skleink #endif
5707684d5e0Skleink 				}
5717684d5e0Skleink 			i = DBL_DIG - nd;
5727684d5e0Skleink 			if (e <= Ten_pmax + i) {
5737684d5e0Skleink 				/* A fancier test would sometimes let us do
5747684d5e0Skleink 				 * this for larger i values.
5757684d5e0Skleink 				 */
5767684d5e0Skleink 				e2 = e - i;
5777684d5e0Skleink 				e1 -= i;
57861e56760Schristos 				dval(&rv) *= tens[i];
5797684d5e0Skleink #ifdef VAX
5807684d5e0Skleink 				/* VAX exponent range is so narrow we must
5817684d5e0Skleink 				 * worry about overflow here...
5827684d5e0Skleink 				 */
5837684d5e0Skleink  vax_ovfl_check:
58461e56760Schristos 				dval(&adj) = dval(&rv);
58561e56760Schristos 				word0(&adj) -= P*Exp_msk1;
58661e56760Schristos 				/* adj = */ rounded_product(dval(&adj), tens[e2]);
58761e56760Schristos 				if ((word0(&adj) & Exp_mask)
5887684d5e0Skleink 				 > Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
5897684d5e0Skleink 					goto rv_notOK;
59061e56760Schristos 				word0(&adj) += P*Exp_msk1;
59161e56760Schristos 				dval(&rv) = dval(&adj);
5927684d5e0Skleink #else
59361e56760Schristos 				/* rv = */ rounded_product(dval(&rv), tens[e2]);
5947684d5e0Skleink #endif
59561e56760Schristos 				if (rvOK(&rv, fpi, expt, bits, 0, rd, &irv))
5967684d5e0Skleink 					goto ret;
5977684d5e0Skleink 				e1 -= e2;
5987684d5e0Skleink 				}
5997684d5e0Skleink 			}
6007684d5e0Skleink #ifndef Inaccurate_Divide
6017684d5e0Skleink 		else if (e >= -Ten_pmax) {
60261e56760Schristos 			/* rv = */ rounded_quotient(dval(&rv), tens[-e]);
60361e56760Schristos 			if (rvOK(&rv, fpi, expt, bits, 0, rd, &irv))
6047684d5e0Skleink 				goto ret;
6057684d5e0Skleink 			e1 -= e;
6067684d5e0Skleink 			}
6077684d5e0Skleink #endif
6087684d5e0Skleink 		}
6097684d5e0Skleink  rv_notOK:
6107684d5e0Skleink 	e1 += nd - k;
6117684d5e0Skleink 
6127684d5e0Skleink 	/* Get starting approximation = rv * 10**e1 */
6137684d5e0Skleink 
6147684d5e0Skleink 	e2 = 0;
6157684d5e0Skleink 	if (e1 > 0) {
6167684d5e0Skleink 		if ( (i = e1 & 15) !=0)
61761e56760Schristos 			dval(&rv) *= tens[i];
6187684d5e0Skleink 		if (e1 &= ~15) {
619ac898a26Skleink 			e1 = (unsigned int)e1 >> 4;
620ac898a26Skleink 			while(e1 >= (1 << (n_bigtens-1))) {
62161e56760Schristos 				e2 += ((word0(&rv) & Exp_mask)
6227684d5e0Skleink 					>> Exp_shift1) - Bias;
62361e56760Schristos 				word0(&rv) &= ~Exp_mask;
62461e56760Schristos 				word0(&rv) |= Bias << Exp_shift1;
62561e56760Schristos 				dval(&rv) *= bigtens[n_bigtens-1];
626ac898a26Skleink 				e1 -= 1 << (n_bigtens-1);
6277684d5e0Skleink 				}
62861e56760Schristos 			e2 += ((word0(&rv) & Exp_mask) >> Exp_shift1) - Bias;
62961e56760Schristos 			word0(&rv) &= ~Exp_mask;
63061e56760Schristos 			word0(&rv) |= Bias << Exp_shift1;
631374ecd4bSchristos 			for(j = 0; e1 > 0; j++, e1 = (unsigned int)e1 >> 1)
6327684d5e0Skleink 				if (e1 & 1)
63361e56760Schristos 					dval(&rv) *= bigtens[j];
6347684d5e0Skleink 			}
6357684d5e0Skleink 		}
6367684d5e0Skleink 	else if (e1 < 0) {
6377684d5e0Skleink 		e1 = -e1;
6387684d5e0Skleink 		if ( (i = e1 & 15) !=0)
63961e56760Schristos 			dval(&rv) /= tens[i];
6407684d5e0Skleink 		if (e1 &= ~15) {
641ac898a26Skleink 			e1 = (unsigned int)e1 >> 4;
642ac898a26Skleink 			while(e1 >= (1 << (n_bigtens-1))) {
64361e56760Schristos 				e2 += ((word0(&rv) & Exp_mask)
6447684d5e0Skleink 					>> Exp_shift1) - Bias;
64561e56760Schristos 				word0(&rv) &= ~Exp_mask;
64661e56760Schristos 				word0(&rv) |= Bias << Exp_shift1;
64761e56760Schristos 				dval(&rv) *= tinytens[n_bigtens-1];
648ac898a26Skleink 				e1 -= 1 << (n_bigtens-1);
6497684d5e0Skleink 				}
65061e56760Schristos 			e2 += ((word0(&rv) & Exp_mask) >> Exp_shift1) - Bias;
65161e56760Schristos 			word0(&rv) &= ~Exp_mask;
65261e56760Schristos 			word0(&rv) |= Bias << Exp_shift1;
653374ecd4bSchristos 			for(j = 0; e1 > 0; j++, e1 = (unsigned int)e1 >> 1)
6547684d5e0Skleink 				if (e1 & 1)
65561e56760Schristos 					dval(&rv) *= tinytens[j];
6567684d5e0Skleink 			}
6577684d5e0Skleink 		}
6587684d5e0Skleink #ifdef IBM
6597684d5e0Skleink 	/* e2 is a correction to the (base 2) exponent of the return
6607684d5e0Skleink 	 * value, reflecting adjustments above to avoid overflow in the
6617684d5e0Skleink 	 * native arithmetic.  For native IBM (base 16) arithmetic, we
6627684d5e0Skleink 	 * must multiply e2 by 4 to change from base 16 to 2.
6637684d5e0Skleink 	 */
6647684d5e0Skleink 	e2 <<= 2;
6657684d5e0Skleink #endif
66661e56760Schristos 	rvb = d2b(dval(&rv), &rve, &rvbits);	/* rv = rvb * 2^rve */
667ab625449Schristos 	if (rvb == NULL)
668ab625449Schristos 		return STRTOG_NoMemory;
6697684d5e0Skleink 	rve += e2;
6707684d5e0Skleink 	if ((j = rvbits - nbits) > 0) {
6717684d5e0Skleink 		rshift(rvb, j);
6727684d5e0Skleink 		rvbits = nbits;
6737684d5e0Skleink 		rve += j;
6747684d5e0Skleink 		}
6757684d5e0Skleink 	bb0 = 0;	/* trailing zero bits in rvb */
6767684d5e0Skleink 	e2 = rve + rvbits - nbits;
6777684d5e0Skleink 	if (e2 > fpi->emax + 1)
6787684d5e0Skleink 		goto huge;
6797684d5e0Skleink 	rve1 = rve + rvbits - nbits;
6807684d5e0Skleink 	if (e2 < (emin = fpi->emin)) {
6817684d5e0Skleink 		denorm = 1;
6827684d5e0Skleink 		j = rve - emin;
6837684d5e0Skleink 		if (j > 0) {
6847684d5e0Skleink 			rvb = lshift(rvb, j);
685*9feb722eSchristos 			if (rvb == NULL)
686*9feb722eSchristos 				return STRTOG_NoMemory;
6877684d5e0Skleink 			rvbits += j;
6887684d5e0Skleink 			}
6897684d5e0Skleink 		else if (j < 0) {
6907684d5e0Skleink 			rvbits += j;
6917684d5e0Skleink 			if (rvbits <= 0) {
6927684d5e0Skleink 				if (rvbits < -1) {
6937684d5e0Skleink  ufl:
6947684d5e0Skleink 					rvb->wds = 0;
6957684d5e0Skleink 					rvb->x[0] = 0;
696ac898a26Skleink 					*expt = emin;
6977684d5e0Skleink 					irv = STRTOG_Underflow | STRTOG_Inexlo;
6987684d5e0Skleink 					goto ret;
6997684d5e0Skleink 					}
7007684d5e0Skleink 				rvb->x[0] = rvb->wds = rvbits = 1;
7017684d5e0Skleink 				}
7027684d5e0Skleink 			else
7037684d5e0Skleink 				rshift(rvb, -j);
7047684d5e0Skleink 			}
7057684d5e0Skleink 		rve = rve1 = emin;
7067684d5e0Skleink 		if (sudden_underflow && e2 + 1 < emin)
7077684d5e0Skleink 			goto ufl;
7087684d5e0Skleink 		}
7097684d5e0Skleink 
7107684d5e0Skleink 	/* Now the hard part -- adjusting rv to the correct value.*/
7117684d5e0Skleink 
7127684d5e0Skleink 	/* Put digits into bd: true value = bd * 10^e */
7137684d5e0Skleink 
71461e56760Schristos 	bd0 = s2b(s0, nd0, nd, y, dplen);
7157684d5e0Skleink 
7167684d5e0Skleink 	for(;;) {
7177684d5e0Skleink 		bd = Balloc(bd0->k);
718ab625449Schristos 		if (bd == NULL)
719ab625449Schristos 			return STRTOG_NoMemory;
7207684d5e0Skleink 		Bcopy(bd, bd0);
7217684d5e0Skleink 		bb = Balloc(rvb->k);
722ab625449Schristos 		if (bb == NULL)
723ab625449Schristos 			return STRTOG_NoMemory;
7247684d5e0Skleink 		Bcopy(bb, rvb);
7257684d5e0Skleink 		bbbits = rvbits - bb0;
7267684d5e0Skleink 		bbe = rve + bb0;
7277684d5e0Skleink 		bs = i2b(1);
728ab625449Schristos 		if (bs == NULL)
729ab625449Schristos 			return STRTOG_NoMemory;
7307684d5e0Skleink 
7317684d5e0Skleink 		if (e >= 0) {
7327684d5e0Skleink 			bb2 = bb5 = 0;
7337684d5e0Skleink 			bd2 = bd5 = e;
7347684d5e0Skleink 			}
7357684d5e0Skleink 		else {
7367684d5e0Skleink 			bb2 = bb5 = -e;
7377684d5e0Skleink 			bd2 = bd5 = 0;
7387684d5e0Skleink 			}
7397684d5e0Skleink 		if (bbe >= 0)
7407684d5e0Skleink 			bb2 += bbe;
7417684d5e0Skleink 		else
7427684d5e0Skleink 			bd2 -= bbe;
7437684d5e0Skleink 		bs2 = bb2;
7447684d5e0Skleink 		j = nbits + 1 - bbbits;
7457684d5e0Skleink 		i = bbe + bbbits - nbits;
7467684d5e0Skleink 		if (i < emin)	/* denormal */
7477684d5e0Skleink 			j += i - emin;
7487684d5e0Skleink 		bb2 += j;
7497684d5e0Skleink 		bd2 += j;
7507684d5e0Skleink 		i = bb2 < bd2 ? bb2 : bd2;
7517684d5e0Skleink 		if (i > bs2)
7527684d5e0Skleink 			i = bs2;
7537684d5e0Skleink 		if (i > 0) {
7547684d5e0Skleink 			bb2 -= i;
7557684d5e0Skleink 			bd2 -= i;
7567684d5e0Skleink 			bs2 -= i;
7577684d5e0Skleink 			}
7587684d5e0Skleink 		if (bb5 > 0) {
7597684d5e0Skleink 			bs = pow5mult(bs, bb5);
760ab625449Schristos 			if (bs == NULL)
761ab625449Schristos 				return STRTOG_NoMemory;
7627684d5e0Skleink 			bb1 = mult(bs, bb);
763ab625449Schristos 			if (bb1 == NULL)
764ab625449Schristos 				return STRTOG_NoMemory;
7657684d5e0Skleink 			Bfree(bb);
7667684d5e0Skleink 			bb = bb1;
7677684d5e0Skleink 			}
7687684d5e0Skleink 		bb2 -= bb0;
769ab625449Schristos 		if (bb2 > 0) {
7707684d5e0Skleink 			bb = lshift(bb, bb2);
771ab625449Schristos 			if (bb == NULL)
772ab625449Schristos 				return STRTOG_NoMemory;
773ab625449Schristos 			}
7747684d5e0Skleink 		else if (bb2 < 0)
7757684d5e0Skleink 			rshift(bb, -bb2);
776ab625449Schristos 		if (bd5 > 0) {
7777684d5e0Skleink 			bd = pow5mult(bd, bd5);
778ab625449Schristos 			if (bd == NULL)
779ab625449Schristos 				return STRTOG_NoMemory;
780ab625449Schristos 			}
781ab625449Schristos 		if (bd2 > 0) {
7827684d5e0Skleink 			bd = lshift(bd, bd2);
783ab625449Schristos 			if (bd == NULL)
784ab625449Schristos 				return STRTOG_NoMemory;
785ab625449Schristos 			}
786ab625449Schristos 		if (bs2 > 0) {
7877684d5e0Skleink 			bs = lshift(bs, bs2);
788ab625449Schristos 			if (bs == NULL)
789ab625449Schristos 				return STRTOG_NoMemory;
790ab625449Schristos 			}
7917684d5e0Skleink 		asub = 1;
7927684d5e0Skleink 		inex = STRTOG_Inexhi;
7937684d5e0Skleink 		delta = diff(bb, bd);
794ab625449Schristos 		if (delta == NULL)
795ab625449Schristos 			return STRTOG_NoMemory;
7967684d5e0Skleink 		if (delta->wds <= 1 && !delta->x[0])
7977684d5e0Skleink 			break;
7987684d5e0Skleink 		dsign = delta->sign;
7997684d5e0Skleink 		delta->sign = finished = 0;
8007684d5e0Skleink 		L = 0;
8017684d5e0Skleink 		i = cmp(delta, bs);
8027684d5e0Skleink 		if (rd && i <= 0) {
8037684d5e0Skleink 			irv = STRTOG_Normal;
8047684d5e0Skleink 			if ( (finished = dsign ^ (rd&1)) !=0) {
8057684d5e0Skleink 				if (dsign != 0) {
8067684d5e0Skleink 					irv |= STRTOG_Inexhi;
8077684d5e0Skleink 					goto adj1;
8087684d5e0Skleink 					}
8097684d5e0Skleink 				irv |= STRTOG_Inexlo;
8107684d5e0Skleink 				if (rve1 == emin)
8117684d5e0Skleink 					goto adj1;
8127684d5e0Skleink 				for(i = 0, j = nbits; j >= ULbits;
8137684d5e0Skleink 						i++, j -= ULbits) {
8147684d5e0Skleink 					if (rvb->x[i] & ALL_ON)
8157684d5e0Skleink 						goto adj1;
8167684d5e0Skleink 					}
8177684d5e0Skleink 				if (j > 1 && lo0bits(rvb->x + i) < j - 1)
8187684d5e0Skleink 					goto adj1;
8197684d5e0Skleink 				rve = rve1 - 1;
8207684d5e0Skleink 				rvb = set_ones(rvb, rvbits = nbits);
821ab625449Schristos 				if (rvb == NULL)
822ab625449Schristos 					return STRTOG_NoMemory;
8237684d5e0Skleink 				break;
8247684d5e0Skleink 				}
8257684d5e0Skleink 			irv |= dsign ? STRTOG_Inexlo : STRTOG_Inexhi;
8267684d5e0Skleink 			break;
8277684d5e0Skleink 			}
8287684d5e0Skleink 		if (i < 0) {
8297684d5e0Skleink 			/* Error is less than half an ulp -- check for
8307684d5e0Skleink 			 * special case of mantissa a power of two.
8317684d5e0Skleink 			 */
8327684d5e0Skleink 			irv = dsign
8337684d5e0Skleink 				? STRTOG_Normal | STRTOG_Inexlo
8347684d5e0Skleink 				: STRTOG_Normal | STRTOG_Inexhi;
8357684d5e0Skleink 			if (dsign || bbbits > 1 || denorm || rve1 == emin)
8367684d5e0Skleink 				break;
8377684d5e0Skleink 			delta = lshift(delta,1);
838ab625449Schristos 			if (delta == NULL)
839ab625449Schristos 				return STRTOG_NoMemory;
8407684d5e0Skleink 			if (cmp(delta, bs) > 0) {
8417684d5e0Skleink 				irv = STRTOG_Normal | STRTOG_Inexlo;
8427684d5e0Skleink 				goto drop_down;
8437684d5e0Skleink 				}
8447684d5e0Skleink 			break;
8457684d5e0Skleink 			}
8467684d5e0Skleink 		if (i == 0) {
8477684d5e0Skleink 			/* exactly half-way between */
8487684d5e0Skleink 			if (dsign) {
8497684d5e0Skleink 				if (denorm && all_on(rvb, rvbits)) {
8507684d5e0Skleink 					/*boundary case -- increment exponent*/
8517684d5e0Skleink 					rvb->wds = 1;
8527684d5e0Skleink 					rvb->x[0] = 1;
8537684d5e0Skleink 					rve = emin + nbits - (rvbits = 1);
8547684d5e0Skleink 					irv = STRTOG_Normal | STRTOG_Inexhi;
8557684d5e0Skleink 					denorm = 0;
8567684d5e0Skleink 					break;
8577684d5e0Skleink 					}
8587684d5e0Skleink 				irv = STRTOG_Normal | STRTOG_Inexlo;
8597684d5e0Skleink 				}
8607684d5e0Skleink 			else if (bbbits == 1) {
8617684d5e0Skleink 				irv = STRTOG_Normal;
8627684d5e0Skleink  drop_down:
8637684d5e0Skleink 				/* boundary case -- decrement exponent */
8647684d5e0Skleink 				if (rve1 == emin) {
8657684d5e0Skleink 					irv = STRTOG_Normal | STRTOG_Inexhi;
8667684d5e0Skleink 					if (rvb->wds == 1 && rvb->x[0] == 1)
8677684d5e0Skleink 						sudden_underflow = 1;
8687684d5e0Skleink 					break;
8697684d5e0Skleink 					}
8707684d5e0Skleink 				rve -= nbits;
8717684d5e0Skleink 				rvb = set_ones(rvb, rvbits = nbits);
872ab625449Schristos 				if (rvb == NULL)
873ab625449Schristos 					return STRTOG_NoMemory;
8747684d5e0Skleink 				break;
8757684d5e0Skleink 				}
8767684d5e0Skleink 			else
8777684d5e0Skleink 				irv = STRTOG_Normal | STRTOG_Inexhi;
878ac898a26Skleink 			if ((bbbits < nbits && !denorm) || !(rvb->x[0] & 1))
8797684d5e0Skleink 				break;
8807684d5e0Skleink 			if (dsign) {
8817684d5e0Skleink 				rvb = increment(rvb);
882ab625449Schristos 				if (rvb == NULL)
883ab625449Schristos 					return STRTOG_NoMemory;
88461e56760Schristos 				j = kmask & (ULbits - (rvbits & kmask));
88561e56760Schristos 				if (hi0bits(rvb->x[rvb->wds - 1]) != j)
8867684d5e0Skleink 					rvbits++;
8877684d5e0Skleink 				irv = STRTOG_Normal | STRTOG_Inexhi;
8887684d5e0Skleink 				}
8897684d5e0Skleink 			else {
8907684d5e0Skleink 				if (bbbits == 1)
8917684d5e0Skleink 					goto undfl;
8927684d5e0Skleink 				decrement(rvb);
8937684d5e0Skleink 				irv = STRTOG_Normal | STRTOG_Inexlo;
8947684d5e0Skleink 				}
8957684d5e0Skleink 			break;
8967684d5e0Skleink 			}
89761e56760Schristos 		if ((dval(&adj) = ratio(delta, bs)) <= 2.) {
8987684d5e0Skleink  adj1:
8997684d5e0Skleink 			inex = STRTOG_Inexlo;
9007684d5e0Skleink 			if (dsign) {
9017684d5e0Skleink 				asub = 0;
9027684d5e0Skleink 				inex = STRTOG_Inexhi;
9037684d5e0Skleink 				}
9047684d5e0Skleink 			else if (denorm && bbbits <= 1) {
9057684d5e0Skleink  undfl:
9067684d5e0Skleink 				rvb->wds = 0;
9077684d5e0Skleink 				rve = emin;
9087684d5e0Skleink 				irv = STRTOG_Underflow | STRTOG_Inexlo;
9097684d5e0Skleink 				break;
9107684d5e0Skleink 				}
91161e56760Schristos 			adj0 = dval(&adj) = 1.;
9127684d5e0Skleink 			}
9137684d5e0Skleink 		else {
91461e56760Schristos 			adj0 = dval(&adj) *= 0.5;
9157684d5e0Skleink 			if (dsign) {
9167684d5e0Skleink 				asub = 0;
9177684d5e0Skleink 				inex = STRTOG_Inexlo;
9187684d5e0Skleink 				}
91961e56760Schristos 			if (dval(&adj) < 2147483647.) {
9207684d5e0Skleink 				L = adj0;
9217684d5e0Skleink 				adj0 -= L;
9227684d5e0Skleink 				switch(rd) {
9237684d5e0Skleink 				  case 0:
9247684d5e0Skleink 					if (adj0 >= .5)
9257684d5e0Skleink 						goto inc_L;
9267684d5e0Skleink 					break;
9277684d5e0Skleink 				  case 1:
9287684d5e0Skleink 					if (asub && adj0 > 0.)
9297684d5e0Skleink 						goto inc_L;
9307684d5e0Skleink 					break;
9317684d5e0Skleink 				  case 2:
9327684d5e0Skleink 					if (!asub && adj0 > 0.) {
9337684d5e0Skleink  inc_L:
9347684d5e0Skleink 						L++;
9357684d5e0Skleink 						inex = STRTOG_Inexact - inex;
9367684d5e0Skleink 						}
9377684d5e0Skleink 				  }
93861e56760Schristos 				dval(&adj) = L;
9397684d5e0Skleink 				}
9407684d5e0Skleink 			}
9417684d5e0Skleink 		y = rve + rvbits;
9427684d5e0Skleink 
94361e56760Schristos 		/* adj *= ulp(dval(&rv)); */
9447684d5e0Skleink 		/* if (asub) rv -= adj; else rv += adj; */
9457684d5e0Skleink 
9467684d5e0Skleink 		if (!denorm && rvbits < nbits) {
9477684d5e0Skleink 			rvb = lshift(rvb, j = nbits - rvbits);
948ab625449Schristos 			if (rvb == NULL)
949ab625449Schristos 				return STRTOG_NoMemory;
9507684d5e0Skleink 			rve -= j;
9517684d5e0Skleink 			rvbits = nbits;
9527684d5e0Skleink 			}
95361e56760Schristos 		ab = d2b(dval(&adj), &abe, &abits);
954ab625449Schristos 		if (ab == NULL)
955ab625449Schristos 			return STRTOG_NoMemory;
9567684d5e0Skleink 		if (abe < 0)
9577684d5e0Skleink 			rshift(ab, -abe);
958*9feb722eSchristos 		else if (abe > 0) {
9597684d5e0Skleink 			ab = lshift(ab, abe);
960*9feb722eSchristos 			if (ab == NULL)
961*9feb722eSchristos 				return STRTOG_NoMemory;
962*9feb722eSchristos 			}
9637684d5e0Skleink 		rvb0 = rvb;
9647684d5e0Skleink 		if (asub) {
9657684d5e0Skleink 			/* rv -= adj; */
9667684d5e0Skleink 			j = hi0bits(rvb->x[rvb->wds-1]);
9677684d5e0Skleink 			rvb = diff(rvb, ab);
968ab625449Schristos 			if (rvb == NULL)
969ab625449Schristos 				return STRTOG_NoMemory;
9707684d5e0Skleink 			k = rvb0->wds - 1;
9717684d5e0Skleink 			if (denorm)
9727684d5e0Skleink 				/* do nothing */;
9737684d5e0Skleink 			else if (rvb->wds <= k
9747684d5e0Skleink 				|| hi0bits( rvb->x[k]) >
9757684d5e0Skleink 				   hi0bits(rvb0->x[k])) {
9767684d5e0Skleink 				/* unlikely; can only have lost 1 high bit */
9777684d5e0Skleink 				if (rve1 == emin) {
9787684d5e0Skleink 					--rvbits;
9797684d5e0Skleink 					denorm = 1;
9807684d5e0Skleink 					}
9817684d5e0Skleink 				else {
9827684d5e0Skleink 					rvb = lshift(rvb, 1);
983ab625449Schristos 					if (rvb == NULL)
984ab625449Schristos 						return STRTOG_NoMemory;
9857684d5e0Skleink 					--rve;
9867684d5e0Skleink 					--rve1;
9877684d5e0Skleink 					L = finished = 0;
9887684d5e0Skleink 					}
9897684d5e0Skleink 				}
9907684d5e0Skleink 			}
9917684d5e0Skleink 		else {
9927684d5e0Skleink 			rvb = sum(rvb, ab);
993ab625449Schristos 			if (rvb == NULL)
994ab625449Schristos 				return STRTOG_NoMemory;
9957684d5e0Skleink 			k = rvb->wds - 1;
9967684d5e0Skleink 			if (k >= rvb0->wds
9977684d5e0Skleink 			 || hi0bits(rvb->x[k]) < hi0bits(rvb0->x[k])) {
9987684d5e0Skleink 				if (denorm) {
9997684d5e0Skleink 					if (++rvbits == nbits)
10007684d5e0Skleink 						denorm = 0;
10017684d5e0Skleink 					}
10027684d5e0Skleink 				else {
10037684d5e0Skleink 					rshift(rvb, 1);
10047684d5e0Skleink 					rve++;
10057684d5e0Skleink 					rve1++;
10067684d5e0Skleink 					L = 0;
10077684d5e0Skleink 					}
10087684d5e0Skleink 				}
10097684d5e0Skleink 			}
10107684d5e0Skleink 		Bfree(ab);
10117684d5e0Skleink 		Bfree(rvb0);
10127684d5e0Skleink 		if (finished)
10137684d5e0Skleink 			break;
10147684d5e0Skleink 
10157684d5e0Skleink 		z = rve + rvbits;
10167684d5e0Skleink 		if (y == z && L) {
10177684d5e0Skleink 			/* Can we stop now? */
101861e56760Schristos 			tol = dval(&adj) * 5e-16; /* > max rel error */
101961e56760Schristos 			dval(&adj) = adj0 - .5;
102061e56760Schristos 			if (dval(&adj) < -tol) {
10217684d5e0Skleink 				if (adj0 > tol) {
10227684d5e0Skleink 					irv |= inex;
10237684d5e0Skleink 					break;
10247684d5e0Skleink 					}
10257684d5e0Skleink 				}
102661e56760Schristos 			else if (dval(&adj) > tol && adj0 < 1. - tol) {
10277684d5e0Skleink 				irv |= inex;
10287684d5e0Skleink 				break;
10297684d5e0Skleink 				}
10307684d5e0Skleink 			}
10317684d5e0Skleink 		bb0 = denorm ? 0 : trailz(rvb);
10327684d5e0Skleink 		Bfree(bb);
10337684d5e0Skleink 		Bfree(bd);
10347684d5e0Skleink 		Bfree(bs);
10357684d5e0Skleink 		Bfree(delta);
10367684d5e0Skleink 		}
10377684d5e0Skleink 	if (!denorm && (j = nbits - rvbits)) {
1038*9feb722eSchristos 		if (j > 0) {
10397684d5e0Skleink 			rvb = lshift(rvb, j);
1040*9feb722eSchristos 			if (rvb == NULL)
1041*9feb722eSchristos 				return STRTOG_NoMemory;
1042*9feb722eSchristos 			}
10437684d5e0Skleink 		else
10447684d5e0Skleink 			rshift(rvb, -j);
10457684d5e0Skleink 		rve -= j;
10467684d5e0Skleink 		}
1047ac898a26Skleink 	*expt = rve;
10487684d5e0Skleink 	Bfree(bb);
10497684d5e0Skleink 	Bfree(bd);
10507684d5e0Skleink 	Bfree(bs);
10517684d5e0Skleink 	Bfree(bd0);
10527684d5e0Skleink 	Bfree(delta);
10537684d5e0Skleink 	if (rve > fpi->emax) {
105461e56760Schristos 		switch(fpi->rounding & 3) {
105561e56760Schristos 		  case FPI_Round_near:
105661e56760Schristos 			goto huge;
105761e56760Schristos 		  case FPI_Round_up:
105861e56760Schristos 			if (!sign)
105961e56760Schristos 				goto huge;
106061e56760Schristos 			break;
106161e56760Schristos 		  case FPI_Round_down:
106261e56760Schristos 			if (sign)
106361e56760Schristos 				goto huge;
106461e56760Schristos 		  }
106561e56760Schristos 		/* Round to largest representable magnitude */
106661e56760Schristos 		Bfree(rvb);
106761e56760Schristos 		rvb = 0;
106861e56760Schristos 		irv = STRTOG_Normal | STRTOG_Inexlo;
106961e56760Schristos 		*expt = fpi->emax;
107061e56760Schristos 		b = bits;
1071374ecd4bSchristos 		be = b + ((unsigned int)(fpi->nbits + 31) >> 5);
107261e56760Schristos 		while(b < be)
1073374ecd4bSchristos 			*b++ = (unsigned int)-1;
1074374ecd4bSchristos 		if ((j = fpi->nbits & 0x1f) != 0)
107561e56760Schristos 			*--be >>= (32 - j);
107661e56760Schristos 		goto ret;
10777684d5e0Skleink  huge:
10787684d5e0Skleink 		rvb->wds = 0;
10797684d5e0Skleink 		irv = STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
10807684d5e0Skleink #ifndef NO_ERRNO
10817684d5e0Skleink 		errno = ERANGE;
10827684d5e0Skleink #endif
1083ac898a26Skleink #ifdef INFNAN_CHECK
10847684d5e0Skleink  infnanexp:
1085ac898a26Skleink #endif
1086ac898a26Skleink 		*expt = fpi->emax + 1;
10877684d5e0Skleink 		}
10887684d5e0Skleink  ret:
10897684d5e0Skleink 	if (denorm) {
10907684d5e0Skleink 		if (sudden_underflow) {
10917684d5e0Skleink 			rvb->wds = 0;
10927684d5e0Skleink 			irv = STRTOG_Underflow | STRTOG_Inexlo;
109361e56760Schristos #ifndef NO_ERRNO
109461e56760Schristos 			errno = ERANGE;
109561e56760Schristos #endif
10967684d5e0Skleink 			}
10977684d5e0Skleink 		else  {
10987684d5e0Skleink 			irv = (irv & ~STRTOG_Retmask) |
10997684d5e0Skleink 				(rvb->wds > 0 ? STRTOG_Denormal : STRTOG_Zero);
110061e56760Schristos 			if (irv & STRTOG_Inexact) {
11017684d5e0Skleink 				irv |= STRTOG_Underflow;
110261e56760Schristos #ifndef NO_ERRNO
110361e56760Schristos 				errno = ERANGE;
110461e56760Schristos #endif
110561e56760Schristos 				}
11067684d5e0Skleink 			}
11077684d5e0Skleink 		}
11087684d5e0Skleink 	if (se)
1109ac898a26Skleink 		*se = __UNCONST(s);
11107684d5e0Skleink 	if (sign)
11117684d5e0Skleink 		irv |= STRTOG_Neg;
11127684d5e0Skleink 	if (rvb) {
11137684d5e0Skleink 		copybits(bits, nbits, rvb);
11147684d5e0Skleink 		Bfree(rvb);
11157684d5e0Skleink 		}
11167684d5e0Skleink 	return irv;
11177684d5e0Skleink 	}
1118