xref: /openbsd-src/lib/libc/gdtoa/strtodg.c (revision 5b44245bdef731678c5654e8568ec9e08bd990f6)
17b36286aSmartynas /****************************************************************
27b36286aSmartynas 
37b36286aSmartynas The author of this software is David M. Gay.
47b36286aSmartynas 
57b36286aSmartynas Copyright (C) 1998-2001 by Lucent Technologies
67b36286aSmartynas All Rights Reserved
77b36286aSmartynas 
87b36286aSmartynas Permission to use, copy, modify, and distribute this software and
97b36286aSmartynas its documentation for any purpose and without fee is hereby
107b36286aSmartynas granted, provided that the above copyright notice appear in all
117b36286aSmartynas copies and that both that the copyright notice and this
127b36286aSmartynas permission notice and warranty disclaimer appear in supporting
137b36286aSmartynas documentation, and that the name of Lucent or any of its entities
147b36286aSmartynas not be used in advertising or publicity pertaining to
157b36286aSmartynas distribution of the software without specific, written prior
167b36286aSmartynas permission.
177b36286aSmartynas 
187b36286aSmartynas LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
197b36286aSmartynas INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
207b36286aSmartynas IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
217b36286aSmartynas SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
227b36286aSmartynas WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
237b36286aSmartynas IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
247b36286aSmartynas ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
257b36286aSmartynas THIS SOFTWARE.
267b36286aSmartynas 
277b36286aSmartynas ****************************************************************/
287b36286aSmartynas 
297b36286aSmartynas /* Please send bug reports to David M. Gay (dmg at acm dot org,
307b36286aSmartynas  * with " at " changed at "@" and " dot " changed to ".").	*/
317b36286aSmartynas 
327b36286aSmartynas #include "gdtoaimp.h"
337b36286aSmartynas 
347b36286aSmartynas #ifdef USE_LOCALE
357b36286aSmartynas #include "locale.h"
367b36286aSmartynas #endif
377b36286aSmartynas 
387b36286aSmartynas  static CONST int
397b36286aSmartynas fivesbits[] = {	 0,  3,  5,  7, 10, 12, 14, 17, 19, 21,
407b36286aSmartynas 		24, 26, 28, 31, 33, 35, 38, 40, 42, 45,
417b36286aSmartynas 		47, 49, 52
427b36286aSmartynas #ifdef VAX
437b36286aSmartynas 		, 54, 56
447b36286aSmartynas #endif
457b36286aSmartynas 		};
467b36286aSmartynas 
477b36286aSmartynas  Bigint *
487b36286aSmartynas #ifdef KR_headers
increment(b)497b36286aSmartynas increment(b) Bigint *b;
507b36286aSmartynas #else
517b36286aSmartynas increment(Bigint *b)
527b36286aSmartynas #endif
537b36286aSmartynas {
547b36286aSmartynas 	ULong *x, *xe;
557b36286aSmartynas 	Bigint *b1;
567b36286aSmartynas #ifdef Pack_16
577b36286aSmartynas 	ULong carry = 1, y;
587b36286aSmartynas #endif
597b36286aSmartynas 
607b36286aSmartynas 	x = b->x;
617b36286aSmartynas 	xe = x + b->wds;
627b36286aSmartynas #ifdef Pack_32
637b36286aSmartynas 	do {
647b36286aSmartynas 		if (*x < (ULong)0xffffffffL) {
657b36286aSmartynas 			++*x;
667b36286aSmartynas 			return b;
677b36286aSmartynas 			}
687b36286aSmartynas 		*x++ = 0;
697b36286aSmartynas 		} while(x < xe);
707b36286aSmartynas #else
717b36286aSmartynas 	do {
727b36286aSmartynas 		y = *x + carry;
737b36286aSmartynas 		carry = y >> 16;
747b36286aSmartynas 		*x++ = y & 0xffff;
757b36286aSmartynas 		if (!carry)
767b36286aSmartynas 			return b;
777b36286aSmartynas 		} while(x < xe);
787b36286aSmartynas 	if (carry)
797b36286aSmartynas #endif
807b36286aSmartynas 	{
817b36286aSmartynas 		if (b->wds >= b->maxwds) {
827b36286aSmartynas 			b1 = Balloc(b->k+1);
83384cfdc1Smartynas 			if (b1 == NULL)
84384cfdc1Smartynas 				return (NULL);
857b36286aSmartynas 			Bcopy(b1,b);
867b36286aSmartynas 			Bfree(b);
877b36286aSmartynas 			b = b1;
887b36286aSmartynas 			}
897b36286aSmartynas 		b->x[b->wds++] = 1;
907b36286aSmartynas 		}
917b36286aSmartynas 	return b;
927b36286aSmartynas 	}
937b36286aSmartynas 
94aad11945Smartynas  void
957b36286aSmartynas #ifdef KR_headers
decrement(b)967b36286aSmartynas decrement(b) Bigint *b;
977b36286aSmartynas #else
987b36286aSmartynas decrement(Bigint *b)
997b36286aSmartynas #endif
1007b36286aSmartynas {
1017b36286aSmartynas 	ULong *x, *xe;
1027b36286aSmartynas #ifdef Pack_16
1037b36286aSmartynas 	ULong borrow = 1, y;
1047b36286aSmartynas #endif
1057b36286aSmartynas 
1067b36286aSmartynas 	x = b->x;
1077b36286aSmartynas 	xe = x + b->wds;
1087b36286aSmartynas #ifdef Pack_32
1097b36286aSmartynas 	do {
1107b36286aSmartynas 		if (*x) {
1117b36286aSmartynas 			--*x;
1127b36286aSmartynas 			break;
1137b36286aSmartynas 			}
1147b36286aSmartynas 		*x++ = 0xffffffffL;
1157b36286aSmartynas 		}
1167b36286aSmartynas 		while(x < xe);
1177b36286aSmartynas #else
1187b36286aSmartynas 	do {
1197b36286aSmartynas 		y = *x - borrow;
1207b36286aSmartynas 		borrow = (y & 0x10000) >> 16;
1217b36286aSmartynas 		*x++ = y & 0xffff;
1227b36286aSmartynas 		} while(borrow && x < xe);
1237b36286aSmartynas #endif
1247b36286aSmartynas 	}
1257b36286aSmartynas 
1267b36286aSmartynas  static int
1277b36286aSmartynas #ifdef KR_headers
all_on(b,n)1287b36286aSmartynas all_on(b, n) Bigint *b; int n;
1297b36286aSmartynas #else
1307b36286aSmartynas all_on(Bigint *b, int n)
1317b36286aSmartynas #endif
1327b36286aSmartynas {
1337b36286aSmartynas 	ULong *x, *xe;
1347b36286aSmartynas 
1357b36286aSmartynas 	x = b->x;
1367b36286aSmartynas 	xe = x + (n >> kshift);
1377b36286aSmartynas 	while(x < xe)
1387b36286aSmartynas 		if ((*x++ & ALL_ON) != ALL_ON)
1397b36286aSmartynas 			return 0;
1407b36286aSmartynas 	if (n &= kmask)
1417b36286aSmartynas 		return ((*x | (ALL_ON << n)) & ALL_ON) == ALL_ON;
1427b36286aSmartynas 	return 1;
1437b36286aSmartynas 	}
1447b36286aSmartynas 
1457b36286aSmartynas  Bigint *
1467b36286aSmartynas #ifdef KR_headers
set_ones(b,n)1477b36286aSmartynas set_ones(b, n) Bigint *b; int n;
1487b36286aSmartynas #else
1497b36286aSmartynas set_ones(Bigint *b, int n)
1507b36286aSmartynas #endif
1517b36286aSmartynas {
1527b36286aSmartynas 	int k;
1537b36286aSmartynas 	ULong *x, *xe;
1547b36286aSmartynas 
1557b36286aSmartynas 	k = (n + ((1 << kshift) - 1)) >> kshift;
1567b36286aSmartynas 	if (b->k < k) {
1577b36286aSmartynas 		Bfree(b);
1587b36286aSmartynas 		b = Balloc(k);
159384cfdc1Smartynas 		if (b == NULL)
160384cfdc1Smartynas 			return (NULL);
1617b36286aSmartynas 		}
1627b36286aSmartynas 	k = n >> kshift;
1637b36286aSmartynas 	if (n &= kmask)
1647b36286aSmartynas 		k++;
1657b36286aSmartynas 	b->wds = k;
1667b36286aSmartynas 	x = b->x;
1677b36286aSmartynas 	xe = x + k;
1687b36286aSmartynas 	while(x < xe)
1697b36286aSmartynas 		*x++ = ALL_ON;
1707b36286aSmartynas 	if (n)
1717b36286aSmartynas 		x[-1] >>= ULbits - n;
1727b36286aSmartynas 	return b;
1737b36286aSmartynas 	}
1747b36286aSmartynas 
1757b36286aSmartynas  static int
rvOK(d,fpi,exp,bits,exact,rd,irv)1767b36286aSmartynas rvOK
1777b36286aSmartynas #ifdef KR_headers
1787b36286aSmartynas  (d, fpi, exp, bits, exact, rd, irv)
1791a653cbcSmartynas  U *d; FPI *fpi; Long *exp; ULong *bits; int exact, rd, *irv;
1807b36286aSmartynas #else
1811a653cbcSmartynas  (U *d, FPI *fpi, Long *exp, ULong *bits, int exact, int rd, int *irv)
1827b36286aSmartynas #endif
1837b36286aSmartynas {
1847b36286aSmartynas 	Bigint *b;
1857b36286aSmartynas 	ULong carry, inex, lostbits;
1867b36286aSmartynas 	int bdif, e, j, k, k1, nb, rv;
1877b36286aSmartynas 
1887b36286aSmartynas 	carry = rv = 0;
1891a653cbcSmartynas 	b = d2b(dval(d), &e, &bdif);
190384cfdc1Smartynas 	if (b == NULL) {
191384cfdc1Smartynas 		*irv = STRTOG_NoMemory;
1921a653cbcSmartynas 		return (1);
193384cfdc1Smartynas 	}
1947b36286aSmartynas 	bdif -= nb = fpi->nbits;
1957b36286aSmartynas 	e += bdif;
1967b36286aSmartynas 	if (bdif <= 0) {
1977b36286aSmartynas 		if (exact)
1987b36286aSmartynas 			goto trunc;
1997b36286aSmartynas 		goto ret;
2007b36286aSmartynas 		}
2017b36286aSmartynas 	if (P == nb) {
2027b36286aSmartynas 		if (
2037b36286aSmartynas #ifndef IMPRECISE_INEXACT
2047b36286aSmartynas 			exact &&
2057b36286aSmartynas #endif
2067b36286aSmartynas 			fpi->rounding ==
2077b36286aSmartynas #ifdef RND_PRODQUOT
2087b36286aSmartynas 					FPI_Round_near
2097b36286aSmartynas #else
2107b36286aSmartynas 					Flt_Rounds
2117b36286aSmartynas #endif
2127b36286aSmartynas 			) goto trunc;
2137b36286aSmartynas 		goto ret;
2147b36286aSmartynas 		}
2157b36286aSmartynas 	switch(rd) {
216aad11945Smartynas 	  case 1: /* round down (toward -Infinity) */
2177b36286aSmartynas 		goto trunc;
218aad11945Smartynas 	  case 2: /* round up (toward +Infinity) */
2197b36286aSmartynas 		break;
2207b36286aSmartynas 	  default: /* round near */
2217b36286aSmartynas 		k = bdif - 1;
2227b36286aSmartynas 		if (k < 0)
2237b36286aSmartynas 			goto trunc;
2247b36286aSmartynas 		if (!k) {
2257b36286aSmartynas 			if (!exact)
2267b36286aSmartynas 				goto ret;
2277b36286aSmartynas 			if (b->x[0] & 2)
2287b36286aSmartynas 				break;
2297b36286aSmartynas 			goto trunc;
2307b36286aSmartynas 			}
2317b36286aSmartynas 		if (b->x[k>>kshift] & ((ULong)1 << (k & kmask)))
2327b36286aSmartynas 			break;
2337b36286aSmartynas 		goto trunc;
2347b36286aSmartynas 	  }
2357b36286aSmartynas 	/* "break" cases: round up 1 bit, then truncate; bdif > 0 */
2367b36286aSmartynas 	carry = 1;
2377b36286aSmartynas  trunc:
2387b36286aSmartynas 	inex = lostbits = 0;
2397b36286aSmartynas 	if (bdif > 0) {
2407b36286aSmartynas 		if ( (lostbits = any_on(b, bdif)) !=0)
2417b36286aSmartynas 			inex = STRTOG_Inexlo;
2427b36286aSmartynas 		rshift(b, bdif);
2437b36286aSmartynas 		if (carry) {
2447b36286aSmartynas 			inex = STRTOG_Inexhi;
2457b36286aSmartynas 			b = increment(b);
246384cfdc1Smartynas 			if (b == NULL) {
247384cfdc1Smartynas 				*irv = STRTOG_NoMemory;
2481a653cbcSmartynas 				return (1);
249384cfdc1Smartynas 				}
2507b36286aSmartynas 			if ( (j = nb & kmask) !=0)
2517b36286aSmartynas 				j = ULbits - j;
2527b36286aSmartynas 			if (hi0bits(b->x[b->wds - 1]) != j) {
2537b36286aSmartynas 				if (!lostbits)
2547b36286aSmartynas 					lostbits = b->x[0] & 1;
2557b36286aSmartynas 				rshift(b, 1);
2567b36286aSmartynas 				e++;
2577b36286aSmartynas 				}
2587b36286aSmartynas 			}
2597b36286aSmartynas 		}
260384cfdc1Smartynas 	else if (bdif < 0) {
2617b36286aSmartynas 		b = lshift(b, -bdif);
262384cfdc1Smartynas 		if (b == NULL) {
263384cfdc1Smartynas 			*irv = STRTOG_NoMemory;
2641a653cbcSmartynas 			return (1);
265384cfdc1Smartynas 			}
266384cfdc1Smartynas 		}
2677b36286aSmartynas 	if (e < fpi->emin) {
2687b36286aSmartynas 		k = fpi->emin - e;
2697b36286aSmartynas 		e = fpi->emin;
2707b36286aSmartynas 		if (k > nb || fpi->sudden_underflow) {
2717b36286aSmartynas 			b->wds = inex = 0;
2727b36286aSmartynas 			*irv = STRTOG_Underflow | STRTOG_Inexlo;
2737b36286aSmartynas 			}
2747b36286aSmartynas 		else {
2757b36286aSmartynas 			k1 = k - 1;
2767b36286aSmartynas 			if (k1 > 0 && !lostbits)
2777b36286aSmartynas 				lostbits = any_on(b, k1);
2787b36286aSmartynas 			if (!lostbits && !exact)
2797b36286aSmartynas 				goto ret;
2807b36286aSmartynas 			lostbits |=
2817b36286aSmartynas 			  carry = b->x[k1>>kshift] & (1 << (k1 & kmask));
2827b36286aSmartynas 			rshift(b, k);
2837b36286aSmartynas 			*irv = STRTOG_Denormal;
2847b36286aSmartynas 			if (carry) {
2857b36286aSmartynas 				b = increment(b);
286384cfdc1Smartynas 				if (b == NULL) {
287384cfdc1Smartynas 					*irv = STRTOG_NoMemory;
2881a653cbcSmartynas 					return (1);
289384cfdc1Smartynas 					}
2907b36286aSmartynas 				inex = STRTOG_Inexhi | STRTOG_Underflow;
2917b36286aSmartynas 				}
2927b36286aSmartynas 			else if (lostbits)
2937b36286aSmartynas 				inex = STRTOG_Inexlo | STRTOG_Underflow;
2947b36286aSmartynas 			}
2957b36286aSmartynas 		}
2967b36286aSmartynas 	else if (e > fpi->emax) {
2977b36286aSmartynas 		e = fpi->emax + 1;
2987b36286aSmartynas 		*irv = STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
2997b36286aSmartynas #ifndef NO_ERRNO
3007b36286aSmartynas 		errno = ERANGE;
3017b36286aSmartynas #endif
3027b36286aSmartynas 		b->wds = inex = 0;
3037b36286aSmartynas 		}
3047b36286aSmartynas 	*exp = e;
3057b36286aSmartynas 	copybits(bits, nb, b);
3067b36286aSmartynas 	*irv |= inex;
3077b36286aSmartynas 	rv = 1;
3087b36286aSmartynas  ret:
3097b36286aSmartynas 	Bfree(b);
3107b36286aSmartynas 	return rv;
3117b36286aSmartynas 	}
3127b36286aSmartynas 
3137b36286aSmartynas  static int
3147b36286aSmartynas #ifdef KR_headers
mantbits(d)3151a653cbcSmartynas mantbits(d) U *d;
3167b36286aSmartynas #else
3171a653cbcSmartynas mantbits(U *d)
3187b36286aSmartynas #endif
3197b36286aSmartynas {
3207b36286aSmartynas 	ULong L;
3217b36286aSmartynas #ifdef VAX
3227b36286aSmartynas 	L = word1(d) << 16 | word1(d) >> 16;
3237b36286aSmartynas 	if (L)
3247b36286aSmartynas #else
3257b36286aSmartynas 	if ( (L = word1(d)) !=0)
3267b36286aSmartynas #endif
3277b36286aSmartynas 		return P - lo0bits(&L);
3287b36286aSmartynas #ifdef VAX
3297b36286aSmartynas 	L = word0(d) << 16 | word0(d) >> 16 | Exp_msk11;
3307b36286aSmartynas #else
3317b36286aSmartynas 	L = word0(d) | Exp_msk1;
3327b36286aSmartynas #endif
3337b36286aSmartynas 	return P - 32 - lo0bits(&L);
3347b36286aSmartynas 	}
3357b36286aSmartynas 
3367b36286aSmartynas  int
strtodg(s00,se,fpi,exp,bits)3377b36286aSmartynas strtodg
3387b36286aSmartynas #ifdef KR_headers
3397b36286aSmartynas 	(s00, se, fpi, exp, bits)
3407b36286aSmartynas 	CONST char *s00; char **se; FPI *fpi; Long *exp; ULong *bits;
3417b36286aSmartynas #else
3427b36286aSmartynas 	(CONST char *s00, char **se, FPI *fpi, Long *exp, ULong *bits)
3437b36286aSmartynas #endif
3447b36286aSmartynas {
3457b36286aSmartynas 	int abe, abits, asub;
3467b36286aSmartynas 	int bb0, bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, decpt, denorm;
3477b36286aSmartynas 	int dsign, e, e1, e2, emin, esign, finished, i, inex, irv;
3487b36286aSmartynas 	int j, k, nbits, nd, nd0, nf, nz, nz0, rd, rvbits, rve, rve1, sign;
3497b36286aSmartynas 	int sudden_underflow;
3507b36286aSmartynas 	CONST char *s, *s0, *s1;
3511a653cbcSmartynas 	double adj0, tol;
3527b36286aSmartynas 	Long L;
3531a653cbcSmartynas 	U adj, rv;
354aad11945Smartynas 	ULong *b, *be, y, z;
3557b36286aSmartynas 	Bigint *ab, *bb, *bb1, *bd, *bd0, *bs, *delta, *rvb, *rvb0;
3561a653cbcSmartynas #ifdef USE_LOCALE /*{{*/
357aad11945Smartynas #ifdef NO_LOCALE_CACHE
358aad11945Smartynas 	char *decimalpoint = localeconv()->decimal_point;
3591a653cbcSmartynas 	int dplen = strlen(decimalpoint);
360aad11945Smartynas #else
361aad11945Smartynas 	char *decimalpoint;
362aad11945Smartynas 	static char *decimalpoint_cache;
3631a653cbcSmartynas 	static int dplen;
364aad11945Smartynas 	if (!(s0 = decimalpoint_cache)) {
365aad11945Smartynas 		s0 = localeconv()->decimal_point;
366*5b44245bSderaadt 		decimalpoint_cache = strdup(s0);
3671a653cbcSmartynas 		dplen = strlen(s0);
368aad11945Smartynas 		}
369aad11945Smartynas 	decimalpoint = (char*)s0;
3701a653cbcSmartynas #endif /*NO_LOCALE_CACHE*/
3711a653cbcSmartynas #else  /*USE_LOCALE}{*/
3721a653cbcSmartynas #define dplen 1
3731a653cbcSmartynas #endif /*USE_LOCALE}}*/
3747b36286aSmartynas 
3757b36286aSmartynas 	irv = STRTOG_Zero;
3767b36286aSmartynas 	denorm = sign = nz0 = nz = 0;
3771a653cbcSmartynas 	dval(&rv) = 0.;
3787b36286aSmartynas 	rvb = 0;
3797b36286aSmartynas 	nbits = fpi->nbits;
3807b36286aSmartynas 	for(s = s00;;s++) switch(*s) {
3817b36286aSmartynas 		case '-':
3827b36286aSmartynas 			sign = 1;
3837b36286aSmartynas 			/* no break */
3847b36286aSmartynas 		case '+':
3857b36286aSmartynas 			if (*++s)
3867b36286aSmartynas 				goto break2;
3877b36286aSmartynas 			/* no break */
3887b36286aSmartynas 		case 0:
3897b36286aSmartynas 			sign = 0;
3907b36286aSmartynas 			irv = STRTOG_NoNumber;
3917b36286aSmartynas 			s = s00;
3927b36286aSmartynas 			goto ret;
3937b36286aSmartynas 		case '\t':
3947b36286aSmartynas 		case '\n':
3957b36286aSmartynas 		case '\v':
3967b36286aSmartynas 		case '\f':
3977b36286aSmartynas 		case '\r':
3987b36286aSmartynas 		case ' ':
3997b36286aSmartynas 			continue;
4007b36286aSmartynas 		default:
4017b36286aSmartynas 			goto break2;
4027b36286aSmartynas 		}
4037b36286aSmartynas  break2:
4047b36286aSmartynas 	if (*s == '0') {
4057b36286aSmartynas #ifndef NO_HEX_FP
4067b36286aSmartynas 		switch(s[1]) {
4077b36286aSmartynas 		  case 'x':
4087b36286aSmartynas 		  case 'X':
4097b36286aSmartynas 			irv = gethex(&s, fpi, exp, &rvb, sign);
410384cfdc1Smartynas 			if (irv == STRTOG_NoMemory)
411384cfdc1Smartynas 				return (STRTOG_NoMemory);
4127b36286aSmartynas 			if (irv == STRTOG_NoNumber) {
4137b36286aSmartynas 				s = s00;
4147b36286aSmartynas 				sign = 0;
4157b36286aSmartynas 				}
4167b36286aSmartynas 			goto ret;
4177b36286aSmartynas 		  }
4187b36286aSmartynas #endif
4197b36286aSmartynas 		nz0 = 1;
4207b36286aSmartynas 		while(*++s == '0') ;
4217b36286aSmartynas 		if (!*s)
4227b36286aSmartynas 			goto ret;
4237b36286aSmartynas 		}
4247b36286aSmartynas 	sudden_underflow = fpi->sudden_underflow;
4257b36286aSmartynas 	s0 = s;
4267b36286aSmartynas 	y = z = 0;
4277b36286aSmartynas 	for(decpt = nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++)
4287b36286aSmartynas 		if (nd < 9)
4297b36286aSmartynas 			y = 10*y + c - '0';
4307b36286aSmartynas 		else if (nd < 16)
4317b36286aSmartynas 			z = 10*z + c - '0';
4327b36286aSmartynas 	nd0 = nd;
4337b36286aSmartynas #ifdef USE_LOCALE
434aad11945Smartynas 	if (c == *decimalpoint) {
435aad11945Smartynas 		for(i = 1; decimalpoint[i]; ++i)
436aad11945Smartynas 			if (s[i] != decimalpoint[i])
437aad11945Smartynas 				goto dig_done;
438aad11945Smartynas 		s += i;
439aad11945Smartynas 		c = *s;
4407b36286aSmartynas #else
441aad11945Smartynas 	if (c == '.') {
4427b36286aSmartynas 		c = *++s;
443aad11945Smartynas #endif
444aad11945Smartynas 		decpt = 1;
4457b36286aSmartynas 		if (!nd) {
4467b36286aSmartynas 			for(; c == '0'; c = *++s)
4477b36286aSmartynas 				nz++;
4487b36286aSmartynas 			if (c > '0' && c <= '9') {
4497b36286aSmartynas 				s0 = s;
4507b36286aSmartynas 				nf += nz;
4517b36286aSmartynas 				nz = 0;
4527b36286aSmartynas 				goto have_dig;
4537b36286aSmartynas 				}
4547b36286aSmartynas 			goto dig_done;
4557b36286aSmartynas 			}
4567b36286aSmartynas 		for(; c >= '0' && c <= '9'; c = *++s) {
4577b36286aSmartynas  have_dig:
4587b36286aSmartynas 			nz++;
4597b36286aSmartynas 			if (c -= '0') {
4607b36286aSmartynas 				nf += nz;
4617b36286aSmartynas 				for(i = 1; i < nz; i++)
4627b36286aSmartynas 					if (nd++ < 9)
4637b36286aSmartynas 						y *= 10;
4647b36286aSmartynas 					else if (nd <= DBL_DIG + 1)
4657b36286aSmartynas 						z *= 10;
4667b36286aSmartynas 				if (nd++ < 9)
4677b36286aSmartynas 					y = 10*y + c;
4687b36286aSmartynas 				else if (nd <= DBL_DIG + 1)
4697b36286aSmartynas 					z = 10*z + c;
4707b36286aSmartynas 				nz = 0;
4717b36286aSmartynas 				}
4727b36286aSmartynas 			}
473aad11945Smartynas 		}/*}*/
4747b36286aSmartynas  dig_done:
4757b36286aSmartynas 	e = 0;
4767b36286aSmartynas 	if (c == 'e' || c == 'E') {
4777b36286aSmartynas 		if (!nd && !nz && !nz0) {
4787b36286aSmartynas 			irv = STRTOG_NoNumber;
4797b36286aSmartynas 			s = s00;
4807b36286aSmartynas 			goto ret;
4817b36286aSmartynas 			}
4827b36286aSmartynas 		s00 = s;
4837b36286aSmartynas 		esign = 0;
4847b36286aSmartynas 		switch(c = *++s) {
4857b36286aSmartynas 			case '-':
4867b36286aSmartynas 				esign = 1;
4877b36286aSmartynas 			case '+':
4887b36286aSmartynas 				c = *++s;
4897b36286aSmartynas 			}
4907b36286aSmartynas 		if (c >= '0' && c <= '9') {
4917b36286aSmartynas 			while(c == '0')
4927b36286aSmartynas 				c = *++s;
4937b36286aSmartynas 			if (c > '0' && c <= '9') {
4947b36286aSmartynas 				L = c - '0';
4957b36286aSmartynas 				s1 = s;
4967b36286aSmartynas 				while((c = *++s) >= '0' && c <= '9')
4977b36286aSmartynas 					L = 10*L + c - '0';
4987b36286aSmartynas 				if (s - s1 > 8 || L > 19999)
4997b36286aSmartynas 					/* Avoid confusion from exponents
5007b36286aSmartynas 					 * so large that e might overflow.
5017b36286aSmartynas 					 */
5027b36286aSmartynas 					e = 19999; /* safe for 16 bit ints */
5037b36286aSmartynas 				else
5047b36286aSmartynas 					e = (int)L;
5057b36286aSmartynas 				if (esign)
5067b36286aSmartynas 					e = -e;
5077b36286aSmartynas 				}
5087b36286aSmartynas 			else
5097b36286aSmartynas 				e = 0;
5107b36286aSmartynas 			}
5117b36286aSmartynas 		else
5127b36286aSmartynas 			s = s00;
5137b36286aSmartynas 		}
5147b36286aSmartynas 	if (!nd) {
5157b36286aSmartynas 		if (!nz && !nz0) {
5167b36286aSmartynas #ifdef INFNAN_CHECK
5177b36286aSmartynas 			/* Check for Nan and Infinity */
5187b36286aSmartynas 			if (!decpt)
5197b36286aSmartynas 			 switch(c) {
5207b36286aSmartynas 			  case 'i':
5217b36286aSmartynas 			  case 'I':
5227b36286aSmartynas 				if (match(&s,"nf")) {
5237b36286aSmartynas 					--s;
5247b36286aSmartynas 					if (!match(&s,"inity"))
5257b36286aSmartynas 						++s;
5267b36286aSmartynas 					irv = STRTOG_Infinite;
5277b36286aSmartynas 					goto infnanexp;
5287b36286aSmartynas 					}
5297b36286aSmartynas 				break;
5307b36286aSmartynas 			  case 'n':
5317b36286aSmartynas 			  case 'N':
5327b36286aSmartynas 				if (match(&s, "an")) {
5337b36286aSmartynas 					irv = STRTOG_NaN;
5347b36286aSmartynas 					*exp = fpi->emax + 1;
5357b36286aSmartynas #ifndef No_Hex_NaN
5367b36286aSmartynas 					if (*s == '(') /*)*/
5377b36286aSmartynas 						irv = hexnan(&s, fpi, bits);
5387b36286aSmartynas #endif
5397b36286aSmartynas 					goto infnanexp;
5407b36286aSmartynas 					}
5417b36286aSmartynas 			  }
5427b36286aSmartynas #endif /* INFNAN_CHECK */
5437b36286aSmartynas 			irv = STRTOG_NoNumber;
5447b36286aSmartynas 			s = s00;
5457b36286aSmartynas 			}
5467b36286aSmartynas 		goto ret;
5477b36286aSmartynas 		}
5487b36286aSmartynas 
5497b36286aSmartynas 	irv = STRTOG_Normal;
5507b36286aSmartynas 	e1 = e -= nf;
5517b36286aSmartynas 	rd = 0;
5527b36286aSmartynas 	switch(fpi->rounding & 3) {
5537b36286aSmartynas 	  case FPI_Round_up:
5547b36286aSmartynas 		rd = 2 - sign;
5557b36286aSmartynas 		break;
5567b36286aSmartynas 	  case FPI_Round_zero:
5577b36286aSmartynas 		rd = 1;
5587b36286aSmartynas 		break;
5597b36286aSmartynas 	  case FPI_Round_down:
5607b36286aSmartynas 		rd = 1 + sign;
5617b36286aSmartynas 	  }
5627b36286aSmartynas 
5637b36286aSmartynas 	/* Now we have nd0 digits, starting at s0, followed by a
5647b36286aSmartynas 	 * decimal point, followed by nd-nd0 digits.  The number we're
5657b36286aSmartynas 	 * after is the integer represented by those digits times
5667b36286aSmartynas 	 * 10**e */
5677b36286aSmartynas 
5687b36286aSmartynas 	if (!nd0)
5697b36286aSmartynas 		nd0 = nd;
5707b36286aSmartynas 	k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
5711a653cbcSmartynas 	dval(&rv) = y;
5727b36286aSmartynas 	if (k > 9)
5731a653cbcSmartynas 		dval(&rv) = tens[k - 9] * dval(&rv) + z;
5747b36286aSmartynas 	bd0 = 0;
5757b36286aSmartynas 	if (nbits <= P && nd <= DBL_DIG) {
5767b36286aSmartynas 		if (!e) {
5771a653cbcSmartynas 			if (rvOK(&rv, fpi, exp, bits, 1, rd, &irv)) {
578384cfdc1Smartynas 				if (irv == STRTOG_NoMemory)
579384cfdc1Smartynas 					return (STRTOG_NoMemory);
5807b36286aSmartynas 				goto ret;
5817b36286aSmartynas 				}
582384cfdc1Smartynas 			}
5837b36286aSmartynas 		else if (e > 0) {
5847b36286aSmartynas 			if (e <= Ten_pmax) {
5857b36286aSmartynas #ifdef VAX
5867b36286aSmartynas 				goto vax_ovfl_check;
5877b36286aSmartynas #else
5881a653cbcSmartynas 				i = fivesbits[e] + mantbits(&rv) <= P;
5891a653cbcSmartynas 				/* rv = */ rounded_product(dval(&rv), tens[e]);
5901a653cbcSmartynas 				if (rvOK(&rv, fpi, exp, bits, i, rd, &irv)) {
591384cfdc1Smartynas 					if (irv == STRTOG_NoMemory)
592384cfdc1Smartynas 						return (STRTOG_NoMemory);
5937b36286aSmartynas 					goto ret;
594384cfdc1Smartynas 					}
5957b36286aSmartynas 				e1 -= e;
5967b36286aSmartynas 				goto rv_notOK;
5977b36286aSmartynas #endif
5987b36286aSmartynas 				}
5997b36286aSmartynas 			i = DBL_DIG - nd;
6007b36286aSmartynas 			if (e <= Ten_pmax + i) {
6017b36286aSmartynas 				/* A fancier test would sometimes let us do
6027b36286aSmartynas 				 * this for larger i values.
6037b36286aSmartynas 				 */
6047b36286aSmartynas 				e2 = e - i;
6057b36286aSmartynas 				e1 -= i;
6061a653cbcSmartynas 				dval(&rv) *= tens[i];
6077b36286aSmartynas #ifdef VAX
6087b36286aSmartynas 				/* VAX exponent range is so narrow we must
6097b36286aSmartynas 				 * worry about overflow here...
6107b36286aSmartynas 				 */
6117b36286aSmartynas  vax_ovfl_check:
6121a653cbcSmartynas 				dval(&adj) = dval(&rv);
6131a653cbcSmartynas 				word0(&adj) -= P*Exp_msk1;
6141a653cbcSmartynas 				/* adj = */ rounded_product(dval(&adj), tens[e2]);
6151a653cbcSmartynas 				if ((word0(&adj) & Exp_mask)
6167b36286aSmartynas 				 > Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
6177b36286aSmartynas 					goto rv_notOK;
6181a653cbcSmartynas 				word0(&adj) += P*Exp_msk1;
6191a653cbcSmartynas 				dval(&rv) = dval(&adj);
6207b36286aSmartynas #else
6211a653cbcSmartynas 				/* rv = */ rounded_product(dval(&rv), tens[e2]);
6227b36286aSmartynas #endif
6231a653cbcSmartynas 				if (rvOK(&rv, fpi, exp, bits, 0, rd, &irv)) {
624384cfdc1Smartynas 					if (irv == STRTOG_NoMemory)
625384cfdc1Smartynas 						return (STRTOG_NoMemory);
6267b36286aSmartynas 					goto ret;
627384cfdc1Smartynas 					}
6287b36286aSmartynas 				e1 -= e2;
6297b36286aSmartynas 				}
6307b36286aSmartynas 			}
6317b36286aSmartynas #ifndef Inaccurate_Divide
6327b36286aSmartynas 		else if (e >= -Ten_pmax) {
6331a653cbcSmartynas 			/* rv = */ rounded_quotient(dval(&rv), tens[-e]);
6341a653cbcSmartynas 			if (rvOK(&rv, fpi, exp, bits, 0, rd, &irv)) {
635384cfdc1Smartynas 				if (irv == STRTOG_NoMemory)
636384cfdc1Smartynas 					return (STRTOG_NoMemory);
6377b36286aSmartynas 				goto ret;
638384cfdc1Smartynas 				}
6397b36286aSmartynas 			e1 -= e;
6407b36286aSmartynas 			}
6417b36286aSmartynas #endif
6427b36286aSmartynas 		}
6437b36286aSmartynas  rv_notOK:
6447b36286aSmartynas 	e1 += nd - k;
6457b36286aSmartynas 
6467b36286aSmartynas 	/* Get starting approximation = rv * 10**e1 */
6477b36286aSmartynas 
6487b36286aSmartynas 	e2 = 0;
6497b36286aSmartynas 	if (e1 > 0) {
6507b36286aSmartynas 		if ( (i = e1 & 15) !=0)
6511a653cbcSmartynas 			dval(&rv) *= tens[i];
6527b36286aSmartynas 		if (e1 &= ~15) {
6537b36286aSmartynas 			e1 >>= 4;
6541a653cbcSmartynas 			while(e1 >= (1 << (n_bigtens-1))) {
6551a653cbcSmartynas 				e2 += ((word0(&rv) & Exp_mask)
6567b36286aSmartynas 					>> Exp_shift1) - Bias;
6571a653cbcSmartynas 				word0(&rv) &= ~Exp_mask;
6581a653cbcSmartynas 				word0(&rv) |= Bias << Exp_shift1;
6591a653cbcSmartynas 				dval(&rv) *= bigtens[n_bigtens-1];
6601a653cbcSmartynas 				e1 -= 1 << (n_bigtens-1);
6617b36286aSmartynas 				}
6621a653cbcSmartynas 			e2 += ((word0(&rv) & Exp_mask) >> Exp_shift1) - Bias;
6631a653cbcSmartynas 			word0(&rv) &= ~Exp_mask;
6641a653cbcSmartynas 			word0(&rv) |= Bias << Exp_shift1;
6657b36286aSmartynas 			for(j = 0; e1 > 0; j++, e1 >>= 1)
6667b36286aSmartynas 				if (e1 & 1)
6671a653cbcSmartynas 					dval(&rv) *= bigtens[j];
6687b36286aSmartynas 			}
6697b36286aSmartynas 		}
6707b36286aSmartynas 	else if (e1 < 0) {
6717b36286aSmartynas 		e1 = -e1;
6727b36286aSmartynas 		if ( (i = e1 & 15) !=0)
6731a653cbcSmartynas 			dval(&rv) /= tens[i];
6747b36286aSmartynas 		if (e1 &= ~15) {
6757b36286aSmartynas 			e1 >>= 4;
6761a653cbcSmartynas 			while(e1 >= (1 << (n_bigtens-1))) {
6771a653cbcSmartynas 				e2 += ((word0(&rv) & Exp_mask)
6787b36286aSmartynas 					>> Exp_shift1) - Bias;
6791a653cbcSmartynas 				word0(&rv) &= ~Exp_mask;
6801a653cbcSmartynas 				word0(&rv) |= Bias << Exp_shift1;
6811a653cbcSmartynas 				dval(&rv) *= tinytens[n_bigtens-1];
6821a653cbcSmartynas 				e1 -= 1 << (n_bigtens-1);
6837b36286aSmartynas 				}
6841a653cbcSmartynas 			e2 += ((word0(&rv) & Exp_mask) >> Exp_shift1) - Bias;
6851a653cbcSmartynas 			word0(&rv) &= ~Exp_mask;
6861a653cbcSmartynas 			word0(&rv) |= Bias << Exp_shift1;
6877b36286aSmartynas 			for(j = 0; e1 > 0; j++, e1 >>= 1)
6887b36286aSmartynas 				if (e1 & 1)
6891a653cbcSmartynas 					dval(&rv) *= tinytens[j];
6907b36286aSmartynas 			}
6917b36286aSmartynas 		}
6927b36286aSmartynas #ifdef IBM
6937b36286aSmartynas 	/* e2 is a correction to the (base 2) exponent of the return
6947b36286aSmartynas 	 * value, reflecting adjustments above to avoid overflow in the
6957b36286aSmartynas 	 * native arithmetic.  For native IBM (base 16) arithmetic, we
6967b36286aSmartynas 	 * must multiply e2 by 4 to change from base 16 to 2.
6977b36286aSmartynas 	 */
6987b36286aSmartynas 	e2 <<= 2;
6997b36286aSmartynas #endif
7001a653cbcSmartynas 	rvb = d2b(dval(&rv), &rve, &rvbits);	/* rv = rvb * 2^rve */
701384cfdc1Smartynas 	if (rvb == NULL)
702384cfdc1Smartynas 		return (STRTOG_NoMemory);
7037b36286aSmartynas 	rve += e2;
7047b36286aSmartynas 	if ((j = rvbits - nbits) > 0) {
7057b36286aSmartynas 		rshift(rvb, j);
7067b36286aSmartynas 		rvbits = nbits;
7077b36286aSmartynas 		rve += j;
7087b36286aSmartynas 		}
7097b36286aSmartynas 	bb0 = 0;	/* trailing zero bits in rvb */
7107b36286aSmartynas 	e2 = rve + rvbits - nbits;
7117b36286aSmartynas 	if (e2 > fpi->emax + 1)
7127b36286aSmartynas 		goto huge;
7137b36286aSmartynas 	rve1 = rve + rvbits - nbits;
7147b36286aSmartynas 	if (e2 < (emin = fpi->emin)) {
7157b36286aSmartynas 		denorm = 1;
7167b36286aSmartynas 		j = rve - emin;
7177b36286aSmartynas 		if (j > 0) {
7187b36286aSmartynas 			rvb = lshift(rvb, j);
719384cfdc1Smartynas 			if (rvb == NULL)
720384cfdc1Smartynas 				return (STRTOG_NoMemory);
7217b36286aSmartynas 			rvbits += j;
7227b36286aSmartynas 			}
7237b36286aSmartynas 		else if (j < 0) {
7247b36286aSmartynas 			rvbits += j;
7257b36286aSmartynas 			if (rvbits <= 0) {
7267b36286aSmartynas 				if (rvbits < -1) {
7277b36286aSmartynas  ufl:
7287b36286aSmartynas 					rvb->wds = 0;
7297b36286aSmartynas 					rvb->x[0] = 0;
7307b36286aSmartynas 					*exp = emin;
7317b36286aSmartynas 					irv = STRTOG_Underflow | STRTOG_Inexlo;
7327b36286aSmartynas 					goto ret;
7337b36286aSmartynas 					}
7347b36286aSmartynas 				rvb->x[0] = rvb->wds = rvbits = 1;
7357b36286aSmartynas 				}
7367b36286aSmartynas 			else
7377b36286aSmartynas 				rshift(rvb, -j);
7387b36286aSmartynas 			}
7397b36286aSmartynas 		rve = rve1 = emin;
7407b36286aSmartynas 		if (sudden_underflow && e2 + 1 < emin)
7417b36286aSmartynas 			goto ufl;
7427b36286aSmartynas 		}
7437b36286aSmartynas 
7447b36286aSmartynas 	/* Now the hard part -- adjusting rv to the correct value.*/
7457b36286aSmartynas 
7467b36286aSmartynas 	/* Put digits into bd: true value = bd * 10^e */
7477b36286aSmartynas 
7481a653cbcSmartynas 	bd0 = s2b(s0, nd0, nd, y, dplen);
749384cfdc1Smartynas 	if (bd0 == NULL)
750384cfdc1Smartynas 		return (STRTOG_NoMemory);
7517b36286aSmartynas 
7527b36286aSmartynas 	for(;;) {
7537b36286aSmartynas 		bd = Balloc(bd0->k);
754384cfdc1Smartynas 		if (bd == NULL)
755384cfdc1Smartynas 			return (STRTOG_NoMemory);
7567b36286aSmartynas 		Bcopy(bd, bd0);
7577b36286aSmartynas 		bb = Balloc(rvb->k);
758384cfdc1Smartynas 		if (bb == NULL)
759384cfdc1Smartynas 			return (STRTOG_NoMemory);
7607b36286aSmartynas 		Bcopy(bb, rvb);
7617b36286aSmartynas 		bbbits = rvbits - bb0;
7627b36286aSmartynas 		bbe = rve + bb0;
7637b36286aSmartynas 		bs = i2b(1);
764384cfdc1Smartynas 		if (bs == NULL)
765384cfdc1Smartynas 			return (STRTOG_NoMemory);
7667b36286aSmartynas 
7677b36286aSmartynas 		if (e >= 0) {
7687b36286aSmartynas 			bb2 = bb5 = 0;
7697b36286aSmartynas 			bd2 = bd5 = e;
7707b36286aSmartynas 			}
7717b36286aSmartynas 		else {
7727b36286aSmartynas 			bb2 = bb5 = -e;
7737b36286aSmartynas 			bd2 = bd5 = 0;
7747b36286aSmartynas 			}
7757b36286aSmartynas 		if (bbe >= 0)
7767b36286aSmartynas 			bb2 += bbe;
7777b36286aSmartynas 		else
7787b36286aSmartynas 			bd2 -= bbe;
7797b36286aSmartynas 		bs2 = bb2;
7807b36286aSmartynas 		j = nbits + 1 - bbbits;
7817b36286aSmartynas 		i = bbe + bbbits - nbits;
7827b36286aSmartynas 		if (i < emin)	/* denormal */
7837b36286aSmartynas 			j += i - emin;
7847b36286aSmartynas 		bb2 += j;
7857b36286aSmartynas 		bd2 += j;
7867b36286aSmartynas 		i = bb2 < bd2 ? bb2 : bd2;
7877b36286aSmartynas 		if (i > bs2)
7887b36286aSmartynas 			i = bs2;
7897b36286aSmartynas 		if (i > 0) {
7907b36286aSmartynas 			bb2 -= i;
7917b36286aSmartynas 			bd2 -= i;
7927b36286aSmartynas 			bs2 -= i;
7937b36286aSmartynas 			}
7947b36286aSmartynas 		if (bb5 > 0) {
7957b36286aSmartynas 			bs = pow5mult(bs, bb5);
796384cfdc1Smartynas 			if (bs == NULL)
797384cfdc1Smartynas 				return (STRTOG_NoMemory);
7987b36286aSmartynas 			bb1 = mult(bs, bb);
799384cfdc1Smartynas 			if (bb1 == NULL)
800384cfdc1Smartynas 				return (STRTOG_NoMemory);
8017b36286aSmartynas 			Bfree(bb);
8027b36286aSmartynas 			bb = bb1;
8037b36286aSmartynas 			}
8047b36286aSmartynas 		bb2 -= bb0;
805384cfdc1Smartynas 		if (bb2 > 0) {
8067b36286aSmartynas 			bb = lshift(bb, bb2);
807384cfdc1Smartynas 			if (bb == NULL)
808384cfdc1Smartynas 				return (STRTOG_NoMemory);
809384cfdc1Smartynas 			}
8107b36286aSmartynas 		else if (bb2 < 0)
8117b36286aSmartynas 			rshift(bb, -bb2);
812384cfdc1Smartynas 		if (bd5 > 0) {
8137b36286aSmartynas 			bd = pow5mult(bd, bd5);
814384cfdc1Smartynas 			if (bd == NULL)
815384cfdc1Smartynas 				return (STRTOG_NoMemory);
816384cfdc1Smartynas 			}
817384cfdc1Smartynas 		if (bd2 > 0) {
8187b36286aSmartynas 			bd = lshift(bd, bd2);
819384cfdc1Smartynas 			if (bd == NULL)
820384cfdc1Smartynas 				return (STRTOG_NoMemory);
821384cfdc1Smartynas 			}
822384cfdc1Smartynas 		if (bs2 > 0) {
8237b36286aSmartynas 			bs = lshift(bs, bs2);
824384cfdc1Smartynas 			if (bs == NULL)
825384cfdc1Smartynas 				return (STRTOG_NoMemory);
826384cfdc1Smartynas 			}
8277b36286aSmartynas 		asub = 1;
8287b36286aSmartynas 		inex = STRTOG_Inexhi;
8297b36286aSmartynas 		delta = diff(bb, bd);
830384cfdc1Smartynas 		if (delta == NULL)
831384cfdc1Smartynas 			return (STRTOG_NoMemory);
8327b36286aSmartynas 		if (delta->wds <= 1 && !delta->x[0])
8337b36286aSmartynas 			break;
8347b36286aSmartynas 		dsign = delta->sign;
8357b36286aSmartynas 		delta->sign = finished = 0;
8367b36286aSmartynas 		L = 0;
8377b36286aSmartynas 		i = cmp(delta, bs);
8387b36286aSmartynas 		if (rd && i <= 0) {
8397b36286aSmartynas 			irv = STRTOG_Normal;
8407b36286aSmartynas 			if ( (finished = dsign ^ (rd&1)) !=0) {
8417b36286aSmartynas 				if (dsign != 0) {
8427b36286aSmartynas 					irv |= STRTOG_Inexhi;
8437b36286aSmartynas 					goto adj1;
8447b36286aSmartynas 					}
8457b36286aSmartynas 				irv |= STRTOG_Inexlo;
8467b36286aSmartynas 				if (rve1 == emin)
8477b36286aSmartynas 					goto adj1;
8487b36286aSmartynas 				for(i = 0, j = nbits; j >= ULbits;
8497b36286aSmartynas 						i++, j -= ULbits) {
8507b36286aSmartynas 					if (rvb->x[i] & ALL_ON)
8517b36286aSmartynas 						goto adj1;
8527b36286aSmartynas 					}
8537b36286aSmartynas 				if (j > 1 && lo0bits(rvb->x + i) < j - 1)
8547b36286aSmartynas 					goto adj1;
8557b36286aSmartynas 				rve = rve1 - 1;
8567b36286aSmartynas 				rvb = set_ones(rvb, rvbits = nbits);
857384cfdc1Smartynas 				if (rvb == NULL)
858384cfdc1Smartynas 					return (STRTOG_NoMemory);
8597b36286aSmartynas 				break;
8607b36286aSmartynas 				}
8617b36286aSmartynas 			irv |= dsign ? STRTOG_Inexlo : STRTOG_Inexhi;
8627b36286aSmartynas 			break;
8637b36286aSmartynas 			}
8647b36286aSmartynas 		if (i < 0) {
8657b36286aSmartynas 			/* Error is less than half an ulp -- check for
8667b36286aSmartynas 			 * special case of mantissa a power of two.
8677b36286aSmartynas 			 */
8687b36286aSmartynas 			irv = dsign
8697b36286aSmartynas 				? STRTOG_Normal | STRTOG_Inexlo
8707b36286aSmartynas 				: STRTOG_Normal | STRTOG_Inexhi;
8717b36286aSmartynas 			if (dsign || bbbits > 1 || denorm || rve1 == emin)
8727b36286aSmartynas 				break;
8737b36286aSmartynas 			delta = lshift(delta,1);
874384cfdc1Smartynas 			if (delta == NULL)
875384cfdc1Smartynas 				return (STRTOG_NoMemory);
8767b36286aSmartynas 			if (cmp(delta, bs) > 0) {
8777b36286aSmartynas 				irv = STRTOG_Normal | STRTOG_Inexlo;
8787b36286aSmartynas 				goto drop_down;
8797b36286aSmartynas 				}
8807b36286aSmartynas 			break;
8817b36286aSmartynas 			}
8827b36286aSmartynas 		if (i == 0) {
8837b36286aSmartynas 			/* exactly half-way between */
8847b36286aSmartynas 			if (dsign) {
8857b36286aSmartynas 				if (denorm && all_on(rvb, rvbits)) {
8867b36286aSmartynas 					/*boundary case -- increment exponent*/
8877b36286aSmartynas 					rvb->wds = 1;
8887b36286aSmartynas 					rvb->x[0] = 1;
8897b36286aSmartynas 					rve = emin + nbits - (rvbits = 1);
8907b36286aSmartynas 					irv = STRTOG_Normal | STRTOG_Inexhi;
8917b36286aSmartynas 					denorm = 0;
8927b36286aSmartynas 					break;
8937b36286aSmartynas 					}
8947b36286aSmartynas 				irv = STRTOG_Normal | STRTOG_Inexlo;
8957b36286aSmartynas 				}
8967b36286aSmartynas 			else if (bbbits == 1) {
8977b36286aSmartynas 				irv = STRTOG_Normal;
8987b36286aSmartynas  drop_down:
8997b36286aSmartynas 				/* boundary case -- decrement exponent */
9007b36286aSmartynas 				if (rve1 == emin) {
9017b36286aSmartynas 					irv = STRTOG_Normal | STRTOG_Inexhi;
9027b36286aSmartynas 					if (rvb->wds == 1 && rvb->x[0] == 1)
9037b36286aSmartynas 						sudden_underflow = 1;
9047b36286aSmartynas 					break;
9057b36286aSmartynas 					}
9067b36286aSmartynas 				rve -= nbits;
9077b36286aSmartynas 				rvb = set_ones(rvb, rvbits = nbits);
908384cfdc1Smartynas 				if (rvb == NULL)
909384cfdc1Smartynas 					return (STRTOG_NoMemory);
9107b36286aSmartynas 				break;
9117b36286aSmartynas 				}
9127b36286aSmartynas 			else
9137b36286aSmartynas 				irv = STRTOG_Normal | STRTOG_Inexhi;
9141a653cbcSmartynas 			if ((bbbits < nbits && !denorm) || !(rvb->x[0] & 1))
9157b36286aSmartynas 				break;
9167b36286aSmartynas 			if (dsign) {
9177b36286aSmartynas 				rvb = increment(rvb);
918384cfdc1Smartynas 				if (rvb == NULL)
919384cfdc1Smartynas 					return (STRTOG_NoMemory);
9207b36286aSmartynas 				j = kmask & (ULbits - (rvbits & kmask));
9217b36286aSmartynas 				if (hi0bits(rvb->x[rvb->wds - 1]) != j)
9227b36286aSmartynas 					rvbits++;
9237b36286aSmartynas 				irv = STRTOG_Normal | STRTOG_Inexhi;
9247b36286aSmartynas 				}
9257b36286aSmartynas 			else {
9267b36286aSmartynas 				if (bbbits == 1)
9277b36286aSmartynas 					goto undfl;
9287b36286aSmartynas 				decrement(rvb);
9297b36286aSmartynas 				irv = STRTOG_Normal | STRTOG_Inexlo;
9307b36286aSmartynas 				}
9317b36286aSmartynas 			break;
9327b36286aSmartynas 			}
9331a653cbcSmartynas 		if ((dval(&adj) = ratio(delta, bs)) <= 2.) {
9347b36286aSmartynas  adj1:
9357b36286aSmartynas 			inex = STRTOG_Inexlo;
9367b36286aSmartynas 			if (dsign) {
9377b36286aSmartynas 				asub = 0;
9387b36286aSmartynas 				inex = STRTOG_Inexhi;
9397b36286aSmartynas 				}
9407b36286aSmartynas 			else if (denorm && bbbits <= 1) {
9417b36286aSmartynas  undfl:
9427b36286aSmartynas 				rvb->wds = 0;
9437b36286aSmartynas 				rve = emin;
9447b36286aSmartynas 				irv = STRTOG_Underflow | STRTOG_Inexlo;
9457b36286aSmartynas 				break;
9467b36286aSmartynas 				}
9471a653cbcSmartynas 			adj0 = dval(&adj) = 1.;
9487b36286aSmartynas 			}
9497b36286aSmartynas 		else {
9501a653cbcSmartynas 			adj0 = dval(&adj) *= 0.5;
9517b36286aSmartynas 			if (dsign) {
9527b36286aSmartynas 				asub = 0;
9537b36286aSmartynas 				inex = STRTOG_Inexlo;
9547b36286aSmartynas 				}
9551a653cbcSmartynas 			if (dval(&adj) < 2147483647.) {
9567b36286aSmartynas 				L = adj0;
9577b36286aSmartynas 				adj0 -= L;
9587b36286aSmartynas 				switch(rd) {
9597b36286aSmartynas 				  case 0:
9607b36286aSmartynas 					if (adj0 >= .5)
9617b36286aSmartynas 						goto inc_L;
9627b36286aSmartynas 					break;
9637b36286aSmartynas 				  case 1:
9647b36286aSmartynas 					if (asub && adj0 > 0.)
9657b36286aSmartynas 						goto inc_L;
9667b36286aSmartynas 					break;
9677b36286aSmartynas 				  case 2:
9687b36286aSmartynas 					if (!asub && adj0 > 0.) {
9697b36286aSmartynas  inc_L:
9707b36286aSmartynas 						L++;
9717b36286aSmartynas 						inex = STRTOG_Inexact - inex;
9727b36286aSmartynas 						}
9737b36286aSmartynas 				  }
9741a653cbcSmartynas 				dval(&adj) = L;
9757b36286aSmartynas 				}
9767b36286aSmartynas 			}
9777b36286aSmartynas 		y = rve + rvbits;
9787b36286aSmartynas 
9791a653cbcSmartynas 		/* adj *= ulp(dval(&rv)); */
9807b36286aSmartynas 		/* if (asub) rv -= adj; else rv += adj; */
9817b36286aSmartynas 
9827b36286aSmartynas 		if (!denorm && rvbits < nbits) {
9837b36286aSmartynas 			rvb = lshift(rvb, j = nbits - rvbits);
984384cfdc1Smartynas 			if (rvb == NULL)
985384cfdc1Smartynas 				return (STRTOG_NoMemory);
9867b36286aSmartynas 			rve -= j;
9877b36286aSmartynas 			rvbits = nbits;
9887b36286aSmartynas 			}
9891a653cbcSmartynas 		ab = d2b(dval(&adj), &abe, &abits);
990384cfdc1Smartynas 		if (ab == NULL)
991384cfdc1Smartynas 			return (STRTOG_NoMemory);
9927b36286aSmartynas 		if (abe < 0)
9937b36286aSmartynas 			rshift(ab, -abe);
994384cfdc1Smartynas 		else if (abe > 0) {
9957b36286aSmartynas 			ab = lshift(ab, abe);
996384cfdc1Smartynas 			if (ab == NULL)
997384cfdc1Smartynas 				return (STRTOG_NoMemory);
998384cfdc1Smartynas 			}
9997b36286aSmartynas 		rvb0 = rvb;
10007b36286aSmartynas 		if (asub) {
10017b36286aSmartynas 			/* rv -= adj; */
10027b36286aSmartynas 			j = hi0bits(rvb->x[rvb->wds-1]);
10037b36286aSmartynas 			rvb = diff(rvb, ab);
1004384cfdc1Smartynas 			if (rvb == NULL)
1005384cfdc1Smartynas 				return (STRTOG_NoMemory);
10067b36286aSmartynas 			k = rvb0->wds - 1;
10077b36286aSmartynas 			if (denorm)
10087b36286aSmartynas 				/* do nothing */;
10097b36286aSmartynas 			else if (rvb->wds <= k
10107b36286aSmartynas 				|| hi0bits( rvb->x[k]) >
10117b36286aSmartynas 				   hi0bits(rvb0->x[k])) {
10127b36286aSmartynas 				/* unlikely; can only have lost 1 high bit */
10137b36286aSmartynas 				if (rve1 == emin) {
10147b36286aSmartynas 					--rvbits;
10157b36286aSmartynas 					denorm = 1;
10167b36286aSmartynas 					}
10177b36286aSmartynas 				else {
10187b36286aSmartynas 					rvb = lshift(rvb, 1);
1019384cfdc1Smartynas 					if (rvb == NULL)
1020384cfdc1Smartynas 						return (STRTOG_NoMemory);
10217b36286aSmartynas 					--rve;
10227b36286aSmartynas 					--rve1;
10237b36286aSmartynas 					L = finished = 0;
10247b36286aSmartynas 					}
10257b36286aSmartynas 				}
10267b36286aSmartynas 			}
10277b36286aSmartynas 		else {
10287b36286aSmartynas 			rvb = sum(rvb, ab);
1029384cfdc1Smartynas 			if (rvb == NULL)
1030384cfdc1Smartynas 				return (STRTOG_NoMemory);
10317b36286aSmartynas 			k = rvb->wds - 1;
10327b36286aSmartynas 			if (k >= rvb0->wds
10337b36286aSmartynas 			 || hi0bits(rvb->x[k]) < hi0bits(rvb0->x[k])) {
10347b36286aSmartynas 				if (denorm) {
10357b36286aSmartynas 					if (++rvbits == nbits)
10367b36286aSmartynas 						denorm = 0;
10377b36286aSmartynas 					}
10387b36286aSmartynas 				else {
10397b36286aSmartynas 					rshift(rvb, 1);
10407b36286aSmartynas 					rve++;
10417b36286aSmartynas 					rve1++;
10427b36286aSmartynas 					L = 0;
10437b36286aSmartynas 					}
10447b36286aSmartynas 				}
10457b36286aSmartynas 			}
10467b36286aSmartynas 		Bfree(ab);
10477b36286aSmartynas 		Bfree(rvb0);
10487b36286aSmartynas 		if (finished)
10497b36286aSmartynas 			break;
10507b36286aSmartynas 
10517b36286aSmartynas 		z = rve + rvbits;
10527b36286aSmartynas 		if (y == z && L) {
10537b36286aSmartynas 			/* Can we stop now? */
10541a653cbcSmartynas 			tol = dval(&adj) * 5e-16; /* > max rel error */
10551a653cbcSmartynas 			dval(&adj) = adj0 - .5;
10561a653cbcSmartynas 			if (dval(&adj) < -tol) {
10577b36286aSmartynas 				if (adj0 > tol) {
10587b36286aSmartynas 					irv |= inex;
10597b36286aSmartynas 					break;
10607b36286aSmartynas 					}
10617b36286aSmartynas 				}
10621a653cbcSmartynas 			else if (dval(&adj) > tol && adj0 < 1. - tol) {
10637b36286aSmartynas 				irv |= inex;
10647b36286aSmartynas 				break;
10657b36286aSmartynas 				}
10667b36286aSmartynas 			}
10677b36286aSmartynas 		bb0 = denorm ? 0 : trailz(rvb);
10687b36286aSmartynas 		Bfree(bb);
10697b36286aSmartynas 		Bfree(bd);
10707b36286aSmartynas 		Bfree(bs);
10717b36286aSmartynas 		Bfree(delta);
10727b36286aSmartynas 		}
10737b36286aSmartynas 	if (!denorm && (j = nbits - rvbits)) {
1074384cfdc1Smartynas 		if (j > 0) {
10757b36286aSmartynas 			rvb = lshift(rvb, j);
1076384cfdc1Smartynas 			if (rvb == NULL)
1077384cfdc1Smartynas 				return (STRTOG_NoMemory);
1078384cfdc1Smartynas 			}
10797b36286aSmartynas 		else
10807b36286aSmartynas 			rshift(rvb, -j);
10817b36286aSmartynas 		rve -= j;
10827b36286aSmartynas 		}
10837b36286aSmartynas 	*exp = rve;
10847b36286aSmartynas 	Bfree(bb);
10857b36286aSmartynas 	Bfree(bd);
10867b36286aSmartynas 	Bfree(bs);
10877b36286aSmartynas 	Bfree(bd0);
10887b36286aSmartynas 	Bfree(delta);
10897b36286aSmartynas 	if (rve > fpi->emax) {
1090aad11945Smartynas 		switch(fpi->rounding & 3) {
1091aad11945Smartynas 		  case FPI_Round_near:
1092aad11945Smartynas 			goto huge;
1093aad11945Smartynas 		  case FPI_Round_up:
1094aad11945Smartynas 			if (!sign)
1095aad11945Smartynas 				goto huge;
1096aad11945Smartynas 			break;
1097aad11945Smartynas 		  case FPI_Round_down:
1098aad11945Smartynas 			if (sign)
1099aad11945Smartynas 				goto huge;
1100aad11945Smartynas 		  }
1101aad11945Smartynas 		/* Round to largest representable magnitude */
1102aad11945Smartynas 		Bfree(rvb);
1103aad11945Smartynas 		rvb = 0;
1104aad11945Smartynas 		irv = STRTOG_Normal | STRTOG_Inexlo;
1105aad11945Smartynas 		*exp = fpi->emax;
1106aad11945Smartynas 		b = bits;
1107aad11945Smartynas 		be = b + ((fpi->nbits + 31) >> 5);
1108aad11945Smartynas 		while(b < be)
1109aad11945Smartynas 			*b++ = -1;
1110aad11945Smartynas 		if ((j = fpi->nbits & 0x1f))
1111aad11945Smartynas 			*--be >>= (32 - j);
1112aad11945Smartynas 		goto ret;
11137b36286aSmartynas  huge:
11147b36286aSmartynas 		rvb->wds = 0;
11157b36286aSmartynas 		irv = STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
11167b36286aSmartynas #ifndef NO_ERRNO
11177b36286aSmartynas 		errno = ERANGE;
11187b36286aSmartynas #endif
11197b36286aSmartynas  infnanexp:
11207b36286aSmartynas 		*exp = fpi->emax + 1;
11217b36286aSmartynas 		}
11227b36286aSmartynas  ret:
11237b36286aSmartynas 	if (denorm) {
11247b36286aSmartynas 		if (sudden_underflow) {
11257b36286aSmartynas 			rvb->wds = 0;
11267b36286aSmartynas 			irv = STRTOG_Underflow | STRTOG_Inexlo;
1127aad11945Smartynas #ifndef NO_ERRNO
1128aad11945Smartynas 			errno = ERANGE;
1129aad11945Smartynas #endif
11307b36286aSmartynas 			}
11317b36286aSmartynas 		else  {
11327b36286aSmartynas 			irv = (irv & ~STRTOG_Retmask) |
11337b36286aSmartynas 				(rvb->wds > 0 ? STRTOG_Denormal : STRTOG_Zero);
1134aad11945Smartynas 			if (irv & STRTOG_Inexact) {
11357b36286aSmartynas 				irv |= STRTOG_Underflow;
1136aad11945Smartynas #ifndef NO_ERRNO
1137aad11945Smartynas 				errno = ERANGE;
1138aad11945Smartynas #endif
1139aad11945Smartynas 				}
11407b36286aSmartynas 			}
11417b36286aSmartynas 		}
11427b36286aSmartynas 	if (se)
11437b36286aSmartynas 		*se = (char *)s;
11447b36286aSmartynas 	if (sign)
11457b36286aSmartynas 		irv |= STRTOG_Neg;
11467b36286aSmartynas 	if (rvb) {
11477b36286aSmartynas 		copybits(bits, nbits, rvb);
11487b36286aSmartynas 		Bfree(rvb);
11497b36286aSmartynas 		}
11507b36286aSmartynas 	return irv;
11517b36286aSmartynas 	}
1152