xref: /netbsd-src/lib/libc/gdtoa/strtod.c (revision 72f355ee42d82d742b9f4eeff1ad853d70949502)
1*72f355eeSchristos /* $NetBSD: strtod.c,v 1.20 2024/01/23 15:31:58 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 
34c99aac45Sjoerg #include "namespace.h"
357684d5e0Skleink #include "gdtoaimp.h"
367684d5e0Skleink #ifndef NO_FENV_H
377684d5e0Skleink #include <fenv.h>
387684d5e0Skleink #endif
397684d5e0Skleink 
407684d5e0Skleink #ifdef USE_LOCALE
41c99aac45Sjoerg #include <locale.h>
42c99aac45Sjoerg #include "setlocale_local.h"
437684d5e0Skleink #endif
447684d5e0Skleink 
457684d5e0Skleink #ifdef IEEE_Arith
467684d5e0Skleink #ifndef NO_IEEE_Scale
477684d5e0Skleink #define Avoid_Underflow
487684d5e0Skleink #undef tinytens
4961e56760Schristos /* The factor of 2^106 in tinytens[4] helps us avoid setting the underflow */
507684d5e0Skleink /* flag unnecessarily.  It leads to a song and dance at the end of strtod. */
517684d5e0Skleink static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128,
5261e56760Schristos 		9007199254740992.*9007199254740992.e-256
537684d5e0Skleink 		};
547684d5e0Skleink #endif
557684d5e0Skleink #endif
567684d5e0Skleink 
577684d5e0Skleink #ifdef Honor_FLT_ROUNDS
587684d5e0Skleink #undef Check_FLT_ROUNDS
597684d5e0Skleink #define Check_FLT_ROUNDS
607684d5e0Skleink #else
617684d5e0Skleink #define Rounding Flt_Rounds
627684d5e0Skleink #endif
637684d5e0Skleink 
64bc89c06cSkleink #ifndef __HAVE_LONG_DOUBLE
65bc89c06cSkleink __strong_alias(_strtold, strtod)
66bc89c06cSkleink __weak_alias(strtold, _strtold)
67c99aac45Sjoerg __strong_alias(_strtold_l, strtod_l)
68c99aac45Sjoerg __weak_alias(strtold_l, _strtold_l)
69bc89c06cSkleink #endif
70bc89c06cSkleink 
7161e56760Schristos #ifdef Avoid_Underflow /*{*/
7261e56760Schristos  static double
7361e56760Schristos sulp
7461e56760Schristos #ifdef KR_headers
7561e56760Schristos 	(x, scale) U *x; int scale;
7661e56760Schristos #else
7761e56760Schristos 	(U *x, int scale)
7861e56760Schristos #endif
7961e56760Schristos {
8061e56760Schristos 	U u;
8161e56760Schristos 	double rv;
8261e56760Schristos 	int i;
8361e56760Schristos 
8461e56760Schristos 	rv = ulp(x);
8561e56760Schristos 	if (!scale || (i = 2*P + 1 - ((word0(x) & Exp_mask) >> Exp_shift)) <= 0)
8661e56760Schristos 		return rv; /* Is there an example where i <= 0 ? */
8761e56760Schristos 	word0(&u) = Exp_1 + (i << Exp_shift);
8861e56760Schristos 	word1(&u) = 0;
8961e56760Schristos 	return rv * u.d;
9061e56760Schristos 	}
9161e56760Schristos #endif /*}*/
9261e56760Schristos 
93c99aac45Sjoerg static double
_int_strtod_l(CONST char * s00,char ** se,locale_t loc)94c99aac45Sjoerg _int_strtod_l(CONST char *s00, char **se, locale_t loc)
957684d5e0Skleink {
967684d5e0Skleink #ifdef Avoid_Underflow
977684d5e0Skleink 	int scale;
987684d5e0Skleink #endif
99*72f355eeSchristos 	int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign,
1007684d5e0Skleink 		 e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
1017684d5e0Skleink 	CONST char *s, *s0, *s1;
10261e56760Schristos 	double aadj;
1037684d5e0Skleink 	Long L;
10461e56760Schristos 	U adj, aadj1, rv, rv0;
1057684d5e0Skleink 	ULong y, z;
106da78757bSmrg 	Bigint *bb = NULL, *bb1, *bd0;
107ac898a26Skleink 	Bigint *bd = NULL, *bs = NULL, *delta = NULL; /* pacify gcc */
10861e56760Schristos #ifdef Avoid_Underflow
10961e56760Schristos 	ULong Lsb, Lsb1;
11061e56760Schristos #endif
1117684d5e0Skleink #ifdef SET_INEXACT
1127684d5e0Skleink 	int inexact, oldinexact;
1137684d5e0Skleink #endif
11461e56760Schristos #ifdef USE_LOCALE /*{{*/
115c99aac45Sjoerg 	char *decimalpoint = localeconv_l(loc)->decimal_point;
11661e56760Schristos 	size_t dplen = strlen(decimalpoint);
11761e56760Schristos #endif /*USE_LOCALE}}*/
11861e56760Schristos 
11961e56760Schristos #ifdef Honor_FLT_ROUNDS /*{*/
120*72f355eeSchristos 	int Rounding, decpt = 0;
12161e56760Schristos #ifdef Trust_FLT_ROUNDS /*{{ only define this if FLT_ROUNDS really works! */
12261e56760Schristos 	Rounding = Flt_Rounds;
12361e56760Schristos #else /*}{*/
12461e56760Schristos 	Rounding = 1;
12561e56760Schristos 	switch(fegetround()) {
12661e56760Schristos 	  case FE_TOWARDZERO:	Rounding = 0; break;
12761e56760Schristos 	  case FE_UPWARD:	Rounding = 2; break;
12861e56760Schristos 	  case FE_DOWNWARD:	Rounding = 3;
12961e56760Schristos 	  }
13061e56760Schristos #endif /*}}*/
13161e56760Schristos #endif /*}*/
1327684d5e0Skleink 
133*72f355eeSchristos 	sign = nz0 = nz = 0;
13461e56760Schristos 	dval(&rv) = 0.;
1357684d5e0Skleink 	for(s = s00;;s++) switch(*s) {
1367684d5e0Skleink 		case '-':
1377684d5e0Skleink 			sign = 1;
138ac898a26Skleink 			/* FALLTHROUGH */
1397684d5e0Skleink 		case '+':
1407684d5e0Skleink 			if (*++s)
1417684d5e0Skleink 				goto break2;
142ac898a26Skleink 			/* FALLTHROUGH */
1437684d5e0Skleink 		case 0:
1447684d5e0Skleink 			goto ret0;
1457684d5e0Skleink 		case '\t':
1467684d5e0Skleink 		case '\n':
1477684d5e0Skleink 		case '\v':
1487684d5e0Skleink 		case '\f':
1497684d5e0Skleink 		case '\r':
1507684d5e0Skleink 		case ' ':
1517684d5e0Skleink 			continue;
1527684d5e0Skleink 		default:
1537684d5e0Skleink 			goto break2;
1547684d5e0Skleink 		}
1557684d5e0Skleink  break2:
1567684d5e0Skleink 	if (*s == '0') {
15761e56760Schristos #ifndef NO_HEX_FP /*{*/
1587684d5e0Skleink 		{
1599a9a4122Sriastradh 		static CONST FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI };
160ac898a26Skleink 		Long expt;
1617684d5e0Skleink 		ULong bits[2];
1627684d5e0Skleink 		switch(s[1]) {
1637684d5e0Skleink 		  case 'x':
1647684d5e0Skleink 		  case 'X':
1657684d5e0Skleink 			{
16661e56760Schristos #ifdef Honor_FLT_ROUNDS
1677684d5e0Skleink 			FPI fpi1 = fpi;
16861e56760Schristos 			fpi1.rounding = Rounding;
1697684d5e0Skleink #else
1707684d5e0Skleink #define fpi1 fpi
1717684d5e0Skleink #endif
1720feb0f12Sjoerg 			switch((i = gethex(&s, &fpi1, &expt, &bb, sign, loc)) & STRTOG_Retmask) {
1737684d5e0Skleink 			  case STRTOG_NoNumber:
1747684d5e0Skleink 				s = s00;
1757684d5e0Skleink 				sign = 0;
176ac898a26Skleink 				/* FALLTHROUGH */
1777684d5e0Skleink 			  case STRTOG_Zero:
1787684d5e0Skleink 				break;
1797684d5e0Skleink 			  default:
1807684d5e0Skleink 				if (bb) {
1817684d5e0Skleink 					copybits(bits, fpi.nbits, bb);
1827684d5e0Skleink 					Bfree(bb);
1837684d5e0Skleink 					}
184ac898a26Skleink 				ULtod((/* LINTED */(U*)&rv)->L, bits, expt, i);
1857684d5e0Skleink 			  }}
1867684d5e0Skleink 			goto ret;
1877684d5e0Skleink 		  }
1887684d5e0Skleink 		}
18961e56760Schristos #endif /*}*/
1907684d5e0Skleink 		nz0 = 1;
1917684d5e0Skleink 		while(*++s == '0') ;
1927684d5e0Skleink 		if (!*s)
1937684d5e0Skleink 			goto ret;
1947684d5e0Skleink 		}
1957684d5e0Skleink 	s0 = s;
1967684d5e0Skleink 	y = z = 0;
1977684d5e0Skleink 	for(nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++)
1987684d5e0Skleink 		if (nd < 9)
1997684d5e0Skleink 			y = 10*y + c - '0';
2000068430eSchristos 		else if (nd < DBL_DIG + 2)
2017684d5e0Skleink 			z = 10*z + c - '0';
2027684d5e0Skleink 	nd0 = nd;
2037684d5e0Skleink #ifdef USE_LOCALE
20461e56760Schristos 	if (c == *decimalpoint) {
20561e56760Schristos 		for(i = 1; decimalpoint[i]; ++i)
20661e56760Schristos 			if (s[i] != decimalpoint[i])
20761e56760Schristos 				goto dig_done;
20861e56760Schristos 		s += i;
20961e56760Schristos 		c = *s;
2107684d5e0Skleink #else
21161e56760Schristos 	if (c == '.') {
2127684d5e0Skleink 		c = *++s;
21361e56760Schristos #endif
214*72f355eeSchristos #ifdef Honor_FLT_ROUNDS
21561e56760Schristos 		decpt = 1;
216*72f355eeSchristos #endif
2177684d5e0Skleink 		if (!nd) {
2187684d5e0Skleink 			for(; c == '0'; c = *++s)
2197684d5e0Skleink 				nz++;
2207684d5e0Skleink 			if (c > '0' && c <= '9') {
2217684d5e0Skleink 				s0 = s;
2227684d5e0Skleink 				nf += nz;
2237684d5e0Skleink 				nz = 0;
2247684d5e0Skleink 				goto have_dig;
2257684d5e0Skleink 				}
2267684d5e0Skleink 			goto dig_done;
2277684d5e0Skleink 			}
2287684d5e0Skleink 		for(; c >= '0' && c <= '9'; c = *++s) {
2297684d5e0Skleink  have_dig:
2307684d5e0Skleink 			nz++;
2317684d5e0Skleink 			if (c -= '0') {
2327684d5e0Skleink 				nf += nz;
2337684d5e0Skleink 				for(i = 1; i < nz; i++)
2347684d5e0Skleink 					if (nd++ < 9)
2357684d5e0Skleink 						y *= 10;
2360068430eSchristos 					else if (nd <= DBL_DIG + 2)
2377684d5e0Skleink 						z *= 10;
2387684d5e0Skleink 				if (nd++ < 9)
2397684d5e0Skleink 					y = 10*y + c;
2400068430eSchristos 				else if (nd <= DBL_DIG + 2)
2417684d5e0Skleink 					z = 10*z + c;
2427684d5e0Skleink 				nz = 0;
2437684d5e0Skleink 				}
2447684d5e0Skleink 			}
24561e56760Schristos 		}/*}*/
2467684d5e0Skleink  dig_done:
2477684d5e0Skleink 	e = 0;
2487684d5e0Skleink 	if (c == 'e' || c == 'E') {
2497684d5e0Skleink 		if (!nd && !nz && !nz0) {
2507684d5e0Skleink 			goto ret0;
2517684d5e0Skleink 			}
2527684d5e0Skleink 		s00 = s;
2537684d5e0Skleink 		esign = 0;
2547684d5e0Skleink 		switch(c = *++s) {
2557684d5e0Skleink 			case '-':
2567684d5e0Skleink 				esign = 1;
257ac898a26Skleink 				/* FALLTHROUGH */
2587684d5e0Skleink 			case '+':
2597684d5e0Skleink 				c = *++s;
2607684d5e0Skleink 			}
2617684d5e0Skleink 		if (c >= '0' && c <= '9') {
2627684d5e0Skleink 			while(c == '0')
2637684d5e0Skleink 				c = *++s;
2647684d5e0Skleink 			if (c > '0' && c <= '9') {
2657684d5e0Skleink 				L = c - '0';
2667684d5e0Skleink 				s1 = s;
2677684d5e0Skleink 				while((c = *++s) >= '0' && c <= '9')
2687684d5e0Skleink 					L = 10*L + c - '0';
2697684d5e0Skleink 				if (s - s1 > 8 || L > 19999)
2707684d5e0Skleink 					/* Avoid confusion from exponents
2717684d5e0Skleink 					 * so large that e might overflow.
2727684d5e0Skleink 					 */
2737684d5e0Skleink 					e = 19999; /* safe for 16 bit ints */
2747684d5e0Skleink 				else
2757684d5e0Skleink 					e = (int)L;
2767684d5e0Skleink 				if (esign)
2777684d5e0Skleink 					e = -e;
2787684d5e0Skleink 				}
2797684d5e0Skleink 			else
2807684d5e0Skleink 				e = 0;
2817684d5e0Skleink 			}
2827684d5e0Skleink 		else
2837684d5e0Skleink 			s = s00;
2847684d5e0Skleink 		}
2857684d5e0Skleink 	if (!nd) {
2867684d5e0Skleink 		if (!nz && !nz0) {
2877684d5e0Skleink #ifdef INFNAN_CHECK
2887684d5e0Skleink 			/* Check for Nan and Infinity */
2897684d5e0Skleink 			ULong bits[2];
2909a9a4122Sriastradh 			static CONST FPI fpinan = /* only 52 explicit bits */
2917684d5e0Skleink 				{ 52, 1-1023-53+1, 2046-1023-53+1, 1, SI };
2927684d5e0Skleink 			if (!decpt)
2937684d5e0Skleink 			 switch(c) {
2947684d5e0Skleink 			  case 'i':
2957684d5e0Skleink 			  case 'I':
2967684d5e0Skleink 				if (match(&s,"nf")) {
2977684d5e0Skleink 					--s;
2987684d5e0Skleink 					if (!match(&s,"inity"))
2997684d5e0Skleink 						++s;
30061e56760Schristos 					word0(&rv) = 0x7ff00000;
30161e56760Schristos 					word1(&rv) = 0;
3027684d5e0Skleink 					goto ret;
3037684d5e0Skleink 					}
3047684d5e0Skleink 				break;
3057684d5e0Skleink 			  case 'n':
3067684d5e0Skleink 			  case 'N':
3077684d5e0Skleink 				if (match(&s, "an")) {
3087684d5e0Skleink #ifndef No_Hex_NaN
3097684d5e0Skleink 					if (*s == '(' /*)*/
3107684d5e0Skleink 					 && hexnan(&s, &fpinan, bits)
3117684d5e0Skleink 							== STRTOG_NaNbits) {
31261e56760Schristos 						word0(&rv) = 0x7ff00000 | bits[1];
31361e56760Schristos 						word1(&rv) = bits[0];
3147684d5e0Skleink 						}
3157684d5e0Skleink 					else {
3167684d5e0Skleink #endif
31761e56760Schristos 						word0(&rv) = NAN_WORD0;
31861e56760Schristos 						word1(&rv) = NAN_WORD1;
3197684d5e0Skleink #ifndef No_Hex_NaN
3207684d5e0Skleink 						}
3217684d5e0Skleink #endif
3227684d5e0Skleink 					goto ret;
3237684d5e0Skleink 					}
3247684d5e0Skleink 			  }
3257684d5e0Skleink #endif /* INFNAN_CHECK */
3267684d5e0Skleink  ret0:
3277684d5e0Skleink 			s = s00;
3287684d5e0Skleink 			sign = 0;
3297684d5e0Skleink 			}
3307684d5e0Skleink 		goto ret;
3317684d5e0Skleink 		}
3327684d5e0Skleink 	e1 = e -= nf;
3337684d5e0Skleink 
3347684d5e0Skleink 	/* Now we have nd0 digits, starting at s0, followed by a
3357684d5e0Skleink 	 * decimal point, followed by nd-nd0 digits.  The number we're
3367684d5e0Skleink 	 * after is the integer represented by those digits times
3377684d5e0Skleink 	 * 10**e */
3387684d5e0Skleink 
3397684d5e0Skleink 	if (!nd0)
3407684d5e0Skleink 		nd0 = nd;
3410068430eSchristos 	k = nd < DBL_DIG + 2 ? nd : DBL_DIG + 2;
34261e56760Schristos 	dval(&rv) = y;
3437684d5e0Skleink 	if (k > 9) {
3447684d5e0Skleink #ifdef SET_INEXACT
3457684d5e0Skleink 		if (k > DBL_DIG)
3467684d5e0Skleink 			oldinexact = get_inexact();
3477684d5e0Skleink #endif
34861e56760Schristos 		dval(&rv) = tens[k - 9] * dval(&rv) + z;
3497684d5e0Skleink 		}
3507684d5e0Skleink 	bd0 = 0;
3517684d5e0Skleink 	if (nd <= DBL_DIG
3527684d5e0Skleink #ifndef RND_PRODQUOT
3537684d5e0Skleink #ifndef Honor_FLT_ROUNDS
354*72f355eeSchristos 	/*CONSTCOND*/
3557684d5e0Skleink 		&& Flt_Rounds == 1
3567684d5e0Skleink #endif
3577684d5e0Skleink #endif
3587684d5e0Skleink 			) {
3597684d5e0Skleink 		if (!e)
3607684d5e0Skleink 			goto ret;
36161e56760Schristos #ifndef ROUND_BIASED_without_Round_Up
3627684d5e0Skleink 		if (e > 0) {
3637684d5e0Skleink 			if (e <= Ten_pmax) {
3647684d5e0Skleink #ifdef VAX
3657684d5e0Skleink 				goto vax_ovfl_check;
3667684d5e0Skleink #else
3677684d5e0Skleink #ifdef Honor_FLT_ROUNDS
3687684d5e0Skleink 				/* round correctly FLT_ROUNDS = 2 or 3 */
3697684d5e0Skleink 				if (sign) {
37061e56760Schristos 					rv.d = -rv.d;
3717684d5e0Skleink 					sign = 0;
3727684d5e0Skleink 					}
3737684d5e0Skleink #endif
37461e56760Schristos 				/* rv = */ rounded_product(dval(&rv), tens[e]);
3757684d5e0Skleink 				goto ret;
3767684d5e0Skleink #endif
3777684d5e0Skleink 				}
3787684d5e0Skleink 			i = DBL_DIG - nd;
3797684d5e0Skleink 			if (e <= Ten_pmax + i) {
3807684d5e0Skleink 				/* A fancier test would sometimes let us do
3817684d5e0Skleink 				 * this for larger i values.
3827684d5e0Skleink 				 */
3837684d5e0Skleink #ifdef Honor_FLT_ROUNDS
3847684d5e0Skleink 				/* round correctly FLT_ROUNDS = 2 or 3 */
3857684d5e0Skleink 				if (sign) {
38661e56760Schristos 					rv.d = -rv.d;
3877684d5e0Skleink 					sign = 0;
3887684d5e0Skleink 					}
3897684d5e0Skleink #endif
3907684d5e0Skleink 				e -= i;
39161e56760Schristos 				dval(&rv) *= tens[i];
3927684d5e0Skleink #ifdef VAX
3937684d5e0Skleink 				/* VAX exponent range is so narrow we must
3947684d5e0Skleink 				 * worry about overflow here...
3957684d5e0Skleink 				 */
3967684d5e0Skleink  vax_ovfl_check:
39761e56760Schristos 				word0(&rv) -= P*Exp_msk1;
39861e56760Schristos 				/* rv = */ rounded_product(dval(&rv), tens[e]);
39961e56760Schristos 				if ((word0(&rv) & Exp_mask)
4007684d5e0Skleink 				 > Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
4017684d5e0Skleink 					goto ovfl;
40261e56760Schristos 				word0(&rv) += P*Exp_msk1;
4037684d5e0Skleink #else
40461e56760Schristos 				/* rv = */ rounded_product(dval(&rv), tens[e]);
4057684d5e0Skleink #endif
4067684d5e0Skleink 				goto ret;
4077684d5e0Skleink 				}
4087684d5e0Skleink 			}
4097684d5e0Skleink #ifndef Inaccurate_Divide
4107684d5e0Skleink 		else if (e >= -Ten_pmax) {
4117684d5e0Skleink #ifdef Honor_FLT_ROUNDS
4127684d5e0Skleink 			/* round correctly FLT_ROUNDS = 2 or 3 */
4137684d5e0Skleink 			if (sign) {
41461e56760Schristos 				rv.d = -rv.d;
4157684d5e0Skleink 				sign = 0;
4167684d5e0Skleink 				}
4177684d5e0Skleink #endif
41861e56760Schristos 			/* rv = */ rounded_quotient(dval(&rv), tens[-e]);
4197684d5e0Skleink 			goto ret;
4207684d5e0Skleink 			}
4217684d5e0Skleink #endif
42261e56760Schristos #endif /* ROUND_BIASED_without_Round_Up */
4237684d5e0Skleink 		}
4247684d5e0Skleink 	e1 += nd - k;
4257684d5e0Skleink 
4267684d5e0Skleink #ifdef IEEE_Arith
4277684d5e0Skleink #ifdef SET_INEXACT
4287684d5e0Skleink 	inexact = 1;
4297684d5e0Skleink 	if (k <= DBL_DIG)
4307684d5e0Skleink 		oldinexact = get_inexact();
4317684d5e0Skleink #endif
4327684d5e0Skleink #ifdef Avoid_Underflow
4337684d5e0Skleink 	scale = 0;
4347684d5e0Skleink #endif
4357684d5e0Skleink #ifdef Honor_FLT_ROUNDS
43661e56760Schristos 	if (Rounding >= 2) {
4377684d5e0Skleink 		if (sign)
43861e56760Schristos 			Rounding = Rounding == 2 ? 0 : 2;
4397684d5e0Skleink 		else
44061e56760Schristos 			if (Rounding != 2)
44161e56760Schristos 				Rounding = 0;
4427684d5e0Skleink 		}
4437684d5e0Skleink #endif
4447684d5e0Skleink #endif /*IEEE_Arith*/
4457684d5e0Skleink 
4467684d5e0Skleink 	/* Get starting approximation = rv * 10**e1 */
4477684d5e0Skleink 
4487684d5e0Skleink 	if (e1 > 0) {
4497684d5e0Skleink 		if ( (i = e1 & 15) !=0)
45061e56760Schristos 			dval(&rv) *= tens[i];
4517684d5e0Skleink 		if (e1 &= ~15) {
4527684d5e0Skleink 			if (e1 > DBL_MAX_10_EXP) {
4537684d5e0Skleink  ovfl:
4547684d5e0Skleink 				/* Can't trust HUGE_VAL */
4557684d5e0Skleink #ifdef IEEE_Arith
4567684d5e0Skleink #ifdef Honor_FLT_ROUNDS
45761e56760Schristos 				switch(Rounding) {
4587684d5e0Skleink 				  case 0: /* toward 0 */
4597684d5e0Skleink 				  case 3: /* toward -infinity */
46061e56760Schristos 					word0(&rv) = Big0;
46161e56760Schristos 					word1(&rv) = Big1;
4627684d5e0Skleink 					break;
4637684d5e0Skleink 				  default:
46461e56760Schristos 					word0(&rv) = Exp_mask;
46561e56760Schristos 					word1(&rv) = 0;
4667684d5e0Skleink 				  }
4677684d5e0Skleink #else /*Honor_FLT_ROUNDS*/
46861e56760Schristos 				word0(&rv) = Exp_mask;
46961e56760Schristos 				word1(&rv) = 0;
4707684d5e0Skleink #endif /*Honor_FLT_ROUNDS*/
4717684d5e0Skleink #ifdef SET_INEXACT
4727684d5e0Skleink 				/* set overflow bit */
47361e56760Schristos 				dval(&rv0) = 1e300;
47461e56760Schristos 				dval(&rv0) *= dval(&rv0);
4757684d5e0Skleink #endif
4767684d5e0Skleink #else /*IEEE_Arith*/
47761e56760Schristos 				word0(&rv) = Big0;
47861e56760Schristos 				word1(&rv) = Big1;
4797684d5e0Skleink #endif /*IEEE_Arith*/
48061e56760Schristos  range_err:
48161e56760Schristos 				if (bd0) {
48261e56760Schristos 					Bfree(bb);
48361e56760Schristos 					Bfree(bd);
48461e56760Schristos 					Bfree(bs);
48561e56760Schristos 					Bfree(bd0);
48661e56760Schristos 					Bfree(delta);
48761e56760Schristos 					}
48861e56760Schristos #ifndef NO_ERRNO
48961e56760Schristos 				errno = ERANGE;
49061e56760Schristos #endif
4917684d5e0Skleink 				goto ret;
4927684d5e0Skleink 				}
493ac898a26Skleink 			e1 = (unsigned int)e1 >> 4;
494ac898a26Skleink 			for(j = 0; e1 > 1; j++, e1 = (unsigned int)e1 >> 1)
4957684d5e0Skleink 				if (e1 & 1)
49661e56760Schristos 					dval(&rv) *= bigtens[j];
4977684d5e0Skleink 		/* The last multiplication could overflow. */
49861e56760Schristos 			word0(&rv) -= P*Exp_msk1;
49961e56760Schristos 			dval(&rv) *= bigtens[j];
50061e56760Schristos 			if ((z = word0(&rv) & Exp_mask)
5017684d5e0Skleink 			 > Exp_msk1*(DBL_MAX_EXP+Bias-P))
5027684d5e0Skleink 				goto ovfl;
5037684d5e0Skleink 			if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) {
5047684d5e0Skleink 				/* set to largest number */
5057684d5e0Skleink 				/* (Can't trust DBL_MAX) */
50661e56760Schristos 				word0(&rv) = Big0;
50761e56760Schristos 				word1(&rv) = Big1;
5087684d5e0Skleink 				}
5097684d5e0Skleink 			else
51061e56760Schristos 				word0(&rv) += P*Exp_msk1;
5117684d5e0Skleink 			}
5127684d5e0Skleink 		}
5137684d5e0Skleink 	else if (e1 < 0) {
5147684d5e0Skleink 		e1 = -e1;
5157684d5e0Skleink 		if ( (i = e1 & 15) !=0)
51661e56760Schristos 			dval(&rv) /= tens[i];
5177684d5e0Skleink 		if (e1 >>= 4) {
5187684d5e0Skleink 			if (e1 >= 1 << n_bigtens)
5197684d5e0Skleink 				goto undfl;
5207684d5e0Skleink #ifdef Avoid_Underflow
5217684d5e0Skleink 			if (e1 & Scale_Bit)
5227684d5e0Skleink 				scale = 2*P;
523ac898a26Skleink 			for(j = 0; e1 > 0; j++, e1 = (unsigned int)e1 >> 1)
5247684d5e0Skleink 				if (e1 & 1)
52561e56760Schristos 					dval(&rv) *= tinytens[j];
52661e56760Schristos 			if (scale && (j = 2*P + 1 - ((word0(&rv) & Exp_mask)
5277684d5e0Skleink 						>> Exp_shift)) > 0) {
5287684d5e0Skleink 				/* scaled rv is denormal; zap j low bits */
5297684d5e0Skleink 				if (j >= 32) {
53061e56760Schristos 					word1(&rv) = 0;
5317684d5e0Skleink 					if (j >= 53)
53261e56760Schristos 					 word0(&rv) = (P+2)*Exp_msk1;
5337684d5e0Skleink 					else
534c5142b6cSchristos 					 word0(&rv) &= 0xffffffffU << (j-32);
5357684d5e0Skleink 					}
5367684d5e0Skleink 				else
537c5142b6cSchristos 					word1(&rv) &= 0xffffffffU << j;
5387684d5e0Skleink 				}
5397684d5e0Skleink #else
5406f8da331She 			for(j = 0; e1 > 1; j++, e1 = (unsigned int)e1 >> 1)
5417684d5e0Skleink 				if (e1 & 1)
54261e56760Schristos 					dval(&rv) *= tinytens[j];
5437684d5e0Skleink 			/* The last multiplication could underflow. */
54461e56760Schristos 			dval(&rv0) = dval(&rv);
54561e56760Schristos 			dval(&rv) *= tinytens[j];
54661e56760Schristos 			if (!dval(&rv)) {
54761e56760Schristos 				dval(&rv) = 2.*dval(&rv0);
54861e56760Schristos 				dval(&rv) *= tinytens[j];
5497684d5e0Skleink #endif
55061e56760Schristos 				if (!dval(&rv)) {
5517684d5e0Skleink  undfl:
55261e56760Schristos 					dval(&rv) = 0.;
5530068430eSchristos #ifdef Honor_FLT_ROUNDS
5540068430eSchristos 					if (Rounding == 2)
5550068430eSchristos 						word1(&rv) = 1;
5560068430eSchristos #endif
55761e56760Schristos 					goto range_err;
5587684d5e0Skleink 					}
5597684d5e0Skleink #ifndef Avoid_Underflow
56061e56760Schristos 				word0(&rv) = Tiny0;
56161e56760Schristos 				word1(&rv) = Tiny1;
5627684d5e0Skleink 				/* The refinement below will clean
5637684d5e0Skleink 				 * this approximation up.
5647684d5e0Skleink 				 */
5657684d5e0Skleink 				}
5667684d5e0Skleink #endif
5677684d5e0Skleink 			}
5687684d5e0Skleink 		}
5697684d5e0Skleink 
5707684d5e0Skleink 	/* Now the hard part -- adjusting rv to the correct value.*/
5717684d5e0Skleink 
5727684d5e0Skleink 	/* Put digits into bd: true value = bd * 10^e */
5737684d5e0Skleink 
57461e56760Schristos 	bd0 = s2b(s0, nd0, nd, y, dplen);
575ab625449Schristos 	if (bd0 == NULL)
576ab625449Schristos 		goto ovfl;
5777684d5e0Skleink 
5787684d5e0Skleink 	for(;;) {
5797684d5e0Skleink 		bd = Balloc(bd0->k);
580ab625449Schristos 		if (bd == NULL)
581ab625449Schristos 			goto ovfl;
5827684d5e0Skleink 		Bcopy(bd, bd0);
58361e56760Schristos 		bb = d2b(dval(&rv), &bbe, &bbbits);	/* rv = bb * 2^bbe */
584ab625449Schristos 		if (bb == NULL)
585ab625449Schristos 			goto ovfl;
5867684d5e0Skleink 		bs = i2b(1);
587ab625449Schristos 		if (bs == NULL)
588ab625449Schristos 			goto ovfl;
5897684d5e0Skleink 
5907684d5e0Skleink 		if (e >= 0) {
5917684d5e0Skleink 			bb2 = bb5 = 0;
5927684d5e0Skleink 			bd2 = bd5 = e;
5937684d5e0Skleink 			}
5947684d5e0Skleink 		else {
5957684d5e0Skleink 			bb2 = bb5 = -e;
5967684d5e0Skleink 			bd2 = bd5 = 0;
5977684d5e0Skleink 			}
5987684d5e0Skleink 		if (bbe >= 0)
5997684d5e0Skleink 			bb2 += bbe;
6007684d5e0Skleink 		else
6017684d5e0Skleink 			bd2 -= bbe;
6027684d5e0Skleink 		bs2 = bb2;
6037684d5e0Skleink #ifdef Honor_FLT_ROUNDS
60461e56760Schristos 		if (Rounding != 1)
6057684d5e0Skleink 			bs2++;
6067684d5e0Skleink #endif
6077684d5e0Skleink #ifdef Avoid_Underflow
60861e56760Schristos 		Lsb = LSB;
60961e56760Schristos 		Lsb1 = 0;
6107684d5e0Skleink 		j = bbe - scale;
6117684d5e0Skleink 		i = j + bbbits - 1;	/* logb(rv) */
6127684d5e0Skleink 		j = P + 1 - bbbits;
61361e56760Schristos 		if (i < Emin) {	/* denormal */
61461e56760Schristos 			i = Emin - i;
61561e56760Schristos 			j -= i;
61661e56760Schristos 			if (i < 32)
61761e56760Schristos 				Lsb <<= i;
61861e56760Schristos 			else
61961e56760Schristos 				Lsb1 = Lsb << (i-32);
62061e56760Schristos 			}
6217684d5e0Skleink #else /*Avoid_Underflow*/
6227684d5e0Skleink #ifdef Sudden_Underflow
6237684d5e0Skleink #ifdef IBM
6247684d5e0Skleink 		j = 1 + 4*P - 3 - bbbits + ((bbe + bbbits - 1) & 3);
6257684d5e0Skleink #else
6267684d5e0Skleink 		j = P + 1 - bbbits;
6277684d5e0Skleink #endif
6287684d5e0Skleink #else /*Sudden_Underflow*/
6297684d5e0Skleink 		j = bbe;
63061e56760Schristos 		i = j + bbbits - 1;	/* logb(&rv) */
6317684d5e0Skleink 		if (i < Emin)	/* denormal */
6327684d5e0Skleink 			j += P - Emin;
6337684d5e0Skleink 		else
6347684d5e0Skleink 			j = P + 1 - bbbits;
6357684d5e0Skleink #endif /*Sudden_Underflow*/
6367684d5e0Skleink #endif /*Avoid_Underflow*/
6377684d5e0Skleink 		bb2 += j;
6387684d5e0Skleink 		bd2 += j;
6397684d5e0Skleink #ifdef Avoid_Underflow
6407684d5e0Skleink 		bd2 += scale;
6417684d5e0Skleink #endif
6427684d5e0Skleink 		i = bb2 < bd2 ? bb2 : bd2;
6437684d5e0Skleink 		if (i > bs2)
6447684d5e0Skleink 			i = bs2;
6457684d5e0Skleink 		if (i > 0) {
6467684d5e0Skleink 			bb2 -= i;
6477684d5e0Skleink 			bd2 -= i;
6487684d5e0Skleink 			bs2 -= i;
6497684d5e0Skleink 			}
6507684d5e0Skleink 		if (bb5 > 0) {
6517684d5e0Skleink 			bs = pow5mult(bs, bb5);
652ab625449Schristos 			if (bs == NULL)
653ab625449Schristos 				goto ovfl;
6547684d5e0Skleink 			bb1 = mult(bs, bb);
655ab625449Schristos 			if (bb1 == NULL)
656ab625449Schristos 				goto ovfl;
6577684d5e0Skleink 			Bfree(bb);
6587684d5e0Skleink 			bb = bb1;
6597684d5e0Skleink 			}
660ab625449Schristos 		if (bb2 > 0) {
6617684d5e0Skleink 			bb = lshift(bb, bb2);
662ab625449Schristos 			if (bb == NULL)
663ab625449Schristos 				goto ovfl;
664ab625449Schristos 			}
665ab625449Schristos 		if (bd5 > 0) {
6667684d5e0Skleink 			bd = pow5mult(bd, bd5);
667ab625449Schristos 			if (bd == NULL)
668ab625449Schristos 				goto ovfl;
669ab625449Schristos 			}
670ab625449Schristos 		if (bd2 > 0) {
6717684d5e0Skleink 			bd = lshift(bd, bd2);
672ab625449Schristos 			if (bd == NULL)
673ab625449Schristos 				goto ovfl;
674ab625449Schristos 			}
675ab625449Schristos 		if (bs2 > 0) {
6767684d5e0Skleink 			bs = lshift(bs, bs2);
677ab625449Schristos 			if (bs == NULL)
678ab625449Schristos 				goto ovfl;
679ab625449Schristos 			}
6807684d5e0Skleink 		delta = diff(bb, bd);
681ab625449Schristos 		if (delta == NULL)
682ab625449Schristos 			goto ovfl;
6837684d5e0Skleink 		dsign = delta->sign;
6847684d5e0Skleink 		delta->sign = 0;
6857684d5e0Skleink 		i = cmp(delta, bs);
6867684d5e0Skleink #ifdef Honor_FLT_ROUNDS
68761e56760Schristos 		if (Rounding != 1) {
6887684d5e0Skleink 			if (i < 0) {
6897684d5e0Skleink 				/* Error is less than an ulp */
6907684d5e0Skleink 				if (!delta->x[0] && delta->wds <= 1) {
6917684d5e0Skleink 					/* exact */
6927684d5e0Skleink #ifdef SET_INEXACT
6937684d5e0Skleink 					inexact = 0;
6947684d5e0Skleink #endif
6957684d5e0Skleink 					break;
6967684d5e0Skleink 					}
69761e56760Schristos 				if (Rounding) {
6987684d5e0Skleink 					if (dsign) {
69961e56760Schristos 						dval(&adj) = 1.;
7007684d5e0Skleink 						goto apply_adj;
7017684d5e0Skleink 						}
7027684d5e0Skleink 					}
7037684d5e0Skleink 				else if (!dsign) {
70461e56760Schristos 					dval(&adj) = -1.;
70561e56760Schristos 					if (!word1(&rv)
70661e56760Schristos 					 && !(word0(&rv) & Frac_mask)) {
70761e56760Schristos 						y = word0(&rv) & Exp_mask;
7087684d5e0Skleink #ifdef Avoid_Underflow
7097684d5e0Skleink 						if (!scale || y > 2*P*Exp_msk1)
7107684d5e0Skleink #else
7117684d5e0Skleink 						if (y)
7127684d5e0Skleink #endif
7137684d5e0Skleink 						  {
7147684d5e0Skleink 						  delta = lshift(delta,Log2P);
7159feb722eSchristos 						  if (delta == NULL)
7169feb722eSchristos 							goto ovfl;
7177684d5e0Skleink 						  if (cmp(delta, bs) <= 0)
71861e56760Schristos 							dval(&adj) = -0.5;
7197684d5e0Skleink 						  }
7207684d5e0Skleink 						}
7217684d5e0Skleink  apply_adj:
7227684d5e0Skleink #ifdef Avoid_Underflow
72361e56760Schristos 					if (scale && (y = word0(&rv) & Exp_mask)
7247684d5e0Skleink 						<= 2*P*Exp_msk1)
72561e56760Schristos 					  word0(&adj) += (2*P+1)*Exp_msk1 - y;
7267684d5e0Skleink #else
7277684d5e0Skleink #ifdef Sudden_Underflow
72861e56760Schristos 					if ((word0(&rv) & Exp_mask) <=
7297684d5e0Skleink 							P*Exp_msk1) {
73061e56760Schristos 						word0(&rv) += P*Exp_msk1;
73161e56760Schristos 						dval(&rv) += adj*ulp(&rv);
73261e56760Schristos 						word0(&rv) -= P*Exp_msk1;
7337684d5e0Skleink 						}
7347684d5e0Skleink 					else
7357684d5e0Skleink #endif /*Sudden_Underflow*/
7367684d5e0Skleink #endif /*Avoid_Underflow*/
73761e56760Schristos 					dval(&rv) += adj.d*ulp(&rv);
7387684d5e0Skleink 					}
7397684d5e0Skleink 				break;
7407684d5e0Skleink 				}
74161e56760Schristos 			dval(&adj) = ratio(delta, bs);
74261e56760Schristos 			if (adj.d < 1.)
74361e56760Schristos 				dval(&adj) = 1.;
74461e56760Schristos 			if (adj.d <= 0x7ffffffe) {
74561e56760Schristos 				/* dval(&adj) = Rounding ? ceil(&adj) : floor(&adj); */
74661e56760Schristos 				y = adj.d;
74761e56760Schristos 				if (y != adj.d) {
74885603243Schristos 					if (!(((unsigned int)Rounding>>1) ^ (unsigned int)dsign))
7497684d5e0Skleink 						y++;
75061e56760Schristos 					dval(&adj) = y;
7517684d5e0Skleink 					}
7527684d5e0Skleink 				}
7537684d5e0Skleink #ifdef Avoid_Underflow
75461e56760Schristos 			if (scale && (y = word0(&rv) & Exp_mask) <= 2*P*Exp_msk1)
75561e56760Schristos 				word0(&adj) += (2*P+1)*Exp_msk1 - y;
7567684d5e0Skleink #else
7577684d5e0Skleink #ifdef Sudden_Underflow
75861e56760Schristos 			if ((word0(&rv) & Exp_mask) <= P*Exp_msk1) {
75961e56760Schristos 				word0(&rv) += P*Exp_msk1;
76061e56760Schristos 				dval(&adj) *= ulp(&rv);
7617684d5e0Skleink 				if (dsign)
76261e56760Schristos 					dval(&rv) += adj;
7637684d5e0Skleink 				else
76461e56760Schristos 					dval(&rv) -= adj;
76561e56760Schristos 				word0(&rv) -= P*Exp_msk1;
7667684d5e0Skleink 				goto cont;
7677684d5e0Skleink 				}
7687684d5e0Skleink #endif /*Sudden_Underflow*/
7697684d5e0Skleink #endif /*Avoid_Underflow*/
77061e56760Schristos 			dval(&adj) *= ulp(&rv);
77161e56760Schristos 			if (dsign) {
77261e56760Schristos 				if (word0(&rv) == Big0 && word1(&rv) == Big1)
77361e56760Schristos 					goto ovfl;
77461e56760Schristos 				dval(&rv) += adj.d;
77561e56760Schristos 				}
7767684d5e0Skleink 			else
77761e56760Schristos 				dval(&rv) -= adj.d;
7787684d5e0Skleink 			goto cont;
7797684d5e0Skleink 			}
7807684d5e0Skleink #endif /*Honor_FLT_ROUNDS*/
7817684d5e0Skleink 
7827684d5e0Skleink 		if (i < 0) {
7837684d5e0Skleink 			/* Error is less than half an ulp -- check for
7847684d5e0Skleink 			 * special case of mantissa a power of two.
7857684d5e0Skleink 			 */
78661e56760Schristos 			if (dsign || word1(&rv) || word0(&rv) & Bndry_mask
7877684d5e0Skleink #ifdef IEEE_Arith
7887684d5e0Skleink #ifdef Avoid_Underflow
78961e56760Schristos 			 || (word0(&rv) & Exp_mask) <= (2*P+1)*Exp_msk1
7907684d5e0Skleink #else
79161e56760Schristos 			 || (word0(&rv) & Exp_mask) <= Exp_msk1
7927684d5e0Skleink #endif
7937684d5e0Skleink #endif
7947684d5e0Skleink 				) {
7957684d5e0Skleink #ifdef SET_INEXACT
7967684d5e0Skleink 				if (!delta->x[0] && delta->wds <= 1)
7977684d5e0Skleink 					inexact = 0;
7987684d5e0Skleink #endif
7997684d5e0Skleink 				break;
8007684d5e0Skleink 				}
8017684d5e0Skleink 			if (!delta->x[0] && delta->wds <= 1) {
8027684d5e0Skleink 				/* exact result */
8037684d5e0Skleink #ifdef SET_INEXACT
8047684d5e0Skleink 				inexact = 0;
8057684d5e0Skleink #endif
8067684d5e0Skleink 				break;
8077684d5e0Skleink 				}
8087684d5e0Skleink 			delta = lshift(delta,Log2P);
8099feb722eSchristos 			if (delta == NULL)
8109feb722eSchristos 				goto ovfl;
8117684d5e0Skleink 			if (cmp(delta, bs) > 0)
8127684d5e0Skleink 				goto drop_down;
8137684d5e0Skleink 			break;
8147684d5e0Skleink 			}
8157684d5e0Skleink 		if (i == 0) {
8167684d5e0Skleink 			/* exactly half-way between */
8177684d5e0Skleink 			if (dsign) {
81861e56760Schristos 				if ((word0(&rv) & Bndry_mask1) == Bndry_mask1
81961e56760Schristos 				 &&  word1(&rv) == (
8207684d5e0Skleink #ifdef Avoid_Underflow
82161e56760Schristos 			(scale && (y = word0(&rv) & Exp_mask) <= 2*P*Exp_msk1)
8227684d5e0Skleink 		? (0xffffffff & (0xffffffff << (2*P+1-(y>>Exp_shift)))) :
8237684d5e0Skleink #endif
8247684d5e0Skleink 						   0xffffffff)) {
8257684d5e0Skleink 					/*boundary case -- increment exponent*/
82661e56760Schristos 					if (word0(&rv) == Big0 && word1(&rv) == Big1)
82761e56760Schristos 						goto ovfl;
82861e56760Schristos 					word0(&rv) = (word0(&rv) & Exp_mask)
8297684d5e0Skleink 						+ Exp_msk1
8307684d5e0Skleink #ifdef IBM
8317684d5e0Skleink 						| Exp_msk1 >> 4
8327684d5e0Skleink #endif
8337684d5e0Skleink 						;
83461e56760Schristos 					word1(&rv) = 0;
8357684d5e0Skleink #ifdef Avoid_Underflow
8367684d5e0Skleink 					dsign = 0;
8377684d5e0Skleink #endif
8387684d5e0Skleink 					break;
8397684d5e0Skleink 					}
8407684d5e0Skleink 				}
84161e56760Schristos 			else if (!(word0(&rv) & Bndry_mask) && !word1(&rv)) {
8427684d5e0Skleink  drop_down:
8437684d5e0Skleink 				/* boundary case -- decrement exponent */
8447684d5e0Skleink #ifdef Sudden_Underflow /*{{*/
84561e56760Schristos 				L = word0(&rv) & Exp_mask;
8467684d5e0Skleink #ifdef IBM
8477684d5e0Skleink 				if (L <  Exp_msk1)
8487684d5e0Skleink #else
8497684d5e0Skleink #ifdef Avoid_Underflow
8507684d5e0Skleink 				if (L <= (scale ? (2*P+1)*Exp_msk1 : Exp_msk1))
8517684d5e0Skleink #else
8527684d5e0Skleink 				if (L <= Exp_msk1)
8537684d5e0Skleink #endif /*Avoid_Underflow*/
8547684d5e0Skleink #endif /*IBM*/
8557684d5e0Skleink 					goto undfl;
8567684d5e0Skleink 				L -= Exp_msk1;
8577684d5e0Skleink #else /*Sudden_Underflow}{*/
8587684d5e0Skleink #ifdef Avoid_Underflow
8597684d5e0Skleink 				if (scale) {
86061e56760Schristos 					L = word0(&rv) & Exp_mask;
8617684d5e0Skleink 					if (L <= (2*P+1)*Exp_msk1) {
8627684d5e0Skleink 						if (L > (P+2)*Exp_msk1)
8637684d5e0Skleink 							/* round even ==> */
8647684d5e0Skleink 							/* accept rv */
8657684d5e0Skleink 							break;
8667684d5e0Skleink 						/* rv = smallest denormal */
8677684d5e0Skleink 						goto undfl;
8687684d5e0Skleink 						}
8697684d5e0Skleink 					}
8707684d5e0Skleink #endif /*Avoid_Underflow*/
87161e56760Schristos 				L = (word0(&rv) & Exp_mask) - Exp_msk1;
87261e56760Schristos #endif /*Sudden_Underflow}}*/
87361e56760Schristos 				word0(&rv) = L | Bndry_mask1;
87461e56760Schristos 				word1(&rv) = 0xffffffff;
8757684d5e0Skleink #ifdef IBM
8767684d5e0Skleink 				goto cont;
8777684d5e0Skleink #else
8787684d5e0Skleink 				break;
8797684d5e0Skleink #endif
8807684d5e0Skleink 				}
8817684d5e0Skleink #ifndef ROUND_BIASED
88261e56760Schristos #ifdef Avoid_Underflow
88361e56760Schristos 			if (Lsb1) {
88461e56760Schristos 				if (!(word0(&rv) & Lsb1))
88561e56760Schristos 					break;
88661e56760Schristos 				}
88761e56760Schristos 			else if (!(word1(&rv) & Lsb))
88861e56760Schristos 				break;
88961e56760Schristos #else
89061e56760Schristos 			if (!(word1(&rv) & LSB))
8917684d5e0Skleink 				break;
8927684d5e0Skleink #endif
89361e56760Schristos #endif
8947684d5e0Skleink 			if (dsign)
89561e56760Schristos #ifdef Avoid_Underflow
89661e56760Schristos 				dval(&rv) += sulp(&rv, scale);
89761e56760Schristos #else
89861e56760Schristos 				dval(&rv) += ulp(&rv);
89961e56760Schristos #endif
9007684d5e0Skleink #ifndef ROUND_BIASED
9017684d5e0Skleink 			else {
90261e56760Schristos #ifdef Avoid_Underflow
90361e56760Schristos 				dval(&rv) -= sulp(&rv, scale);
90461e56760Schristos #else
90561e56760Schristos 				dval(&rv) -= ulp(&rv);
90661e56760Schristos #endif
9077684d5e0Skleink #ifndef Sudden_Underflow
90861e56760Schristos 				if (!dval(&rv))
9097684d5e0Skleink 					goto undfl;
9107684d5e0Skleink #endif
9117684d5e0Skleink 				}
9127684d5e0Skleink #ifdef Avoid_Underflow
9137684d5e0Skleink 			dsign = 1 - dsign;
9147684d5e0Skleink #endif
9157684d5e0Skleink #endif
9167684d5e0Skleink 			break;
9177684d5e0Skleink 			}
9187684d5e0Skleink 		if ((aadj = ratio(delta, bs)) <= 2.) {
9197684d5e0Skleink 			if (dsign)
92061e56760Schristos 				aadj = dval(&aadj1) = 1.;
92161e56760Schristos 			else if (word1(&rv) || word0(&rv) & Bndry_mask) {
9227684d5e0Skleink #ifndef Sudden_Underflow
92361e56760Schristos 				if (word1(&rv) == Tiny1 && !word0(&rv))
9247684d5e0Skleink 					goto undfl;
9257684d5e0Skleink #endif
9267684d5e0Skleink 				aadj = 1.;
92761e56760Schristos 				dval(&aadj1) = -1.;
9287684d5e0Skleink 				}
9297684d5e0Skleink 			else {
9307684d5e0Skleink 				/* special case -- power of FLT_RADIX to be */
9317684d5e0Skleink 				/* rounded down... */
9327684d5e0Skleink 
9337684d5e0Skleink 				if (aadj < 2./FLT_RADIX)
9347684d5e0Skleink 					aadj = 1./FLT_RADIX;
9357684d5e0Skleink 				else
9367684d5e0Skleink 					aadj *= 0.5;
93761e56760Schristos 				dval(&aadj1) = -aadj;
9387684d5e0Skleink 				}
9397684d5e0Skleink 			}
9407684d5e0Skleink 		else {
9417684d5e0Skleink 			aadj *= 0.5;
94261e56760Schristos 			dval(&aadj1) = dsign ? aadj : -aadj;
9437684d5e0Skleink #ifdef Check_FLT_ROUNDS
944c5142b6cSchristos 			/* CONSTCOND */
9457684d5e0Skleink 			switch(Rounding) {
9467684d5e0Skleink 				case 2: /* towards +infinity */
94761e56760Schristos 					dval(&aadj1) -= 0.5;
9487684d5e0Skleink 					break;
9497684d5e0Skleink 				case 0: /* towards 0 */
9507684d5e0Skleink 				case 3: /* towards -infinity */
95161e56760Schristos 					dval(&aadj1) += 0.5;
9527684d5e0Skleink 				}
9537684d5e0Skleink #else
9546f8da331She 			/* CONSTCOND */
9557684d5e0Skleink 			if (Flt_Rounds == 0)
95661e56760Schristos 				dval(&aadj1) += 0.5;
9577684d5e0Skleink #endif /*Check_FLT_ROUNDS*/
9587684d5e0Skleink 			}
95961e56760Schristos 		y = word0(&rv) & Exp_mask;
9607684d5e0Skleink 
9617684d5e0Skleink 		/* Check for overflow */
9627684d5e0Skleink 
9637684d5e0Skleink 		if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) {
96461e56760Schristos 			dval(&rv0) = dval(&rv);
96561e56760Schristos 			word0(&rv) -= P*Exp_msk1;
96661e56760Schristos 			dval(&adj) = dval(&aadj1) * ulp(&rv);
96761e56760Schristos 			dval(&rv) += dval(&adj);
96861e56760Schristos 			if ((word0(&rv) & Exp_mask) >=
9697684d5e0Skleink 					Exp_msk1*(DBL_MAX_EXP+Bias-P)) {
97061e56760Schristos 				if (word0(&rv0) == Big0 && word1(&rv0) == Big1)
9717684d5e0Skleink 					goto ovfl;
97261e56760Schristos 				word0(&rv) = Big0;
97361e56760Schristos 				word1(&rv) = Big1;
9747684d5e0Skleink 				goto cont;
9757684d5e0Skleink 				}
9767684d5e0Skleink 			else
97761e56760Schristos 				word0(&rv) += P*Exp_msk1;
9787684d5e0Skleink 			}
9797684d5e0Skleink 		else {
9807684d5e0Skleink #ifdef Avoid_Underflow
9817684d5e0Skleink 			if (scale && y <= 2*P*Exp_msk1) {
9827684d5e0Skleink 				if (aadj <= 0x7fffffff) {
98385603243Schristos 					if ((z = aadj) == 0)
9847684d5e0Skleink 						z = 1;
9857684d5e0Skleink 					aadj = z;
98661e56760Schristos 					dval(&aadj1) = dsign ? aadj : -aadj;
9877684d5e0Skleink 					}
98861e56760Schristos 				word0(&aadj1) += (2*P+1)*Exp_msk1 - y;
9897684d5e0Skleink 				}
99061e56760Schristos 			dval(&adj) = dval(&aadj1) * ulp(&rv);
99161e56760Schristos 			dval(&rv) += dval(&adj);
9927684d5e0Skleink #else
9937684d5e0Skleink #ifdef Sudden_Underflow
99461e56760Schristos 			if ((word0(&rv) & Exp_mask) <= P*Exp_msk1) {
99561e56760Schristos 				dval(&rv0) = dval(&rv);
99661e56760Schristos 				word0(&rv) += P*Exp_msk1;
99761e56760Schristos 				dval(&adj) = dval(&aadj1) * ulp(&rv);
99808a8bf52She 				dval(&rv) += dval(&adj);
9997684d5e0Skleink #ifdef IBM
100061e56760Schristos 				if ((word0(&rv) & Exp_mask) <  P*Exp_msk1)
10017684d5e0Skleink #else
100261e56760Schristos 				if ((word0(&rv) & Exp_mask) <= P*Exp_msk1)
10037684d5e0Skleink #endif
10047684d5e0Skleink 					{
100561e56760Schristos 					if (word0(&rv0) == Tiny0
100661e56760Schristos 					 && word1(&rv0) == Tiny1)
10077684d5e0Skleink 						goto undfl;
100861e56760Schristos 					word0(&rv) = Tiny0;
100961e56760Schristos 					word1(&rv) = Tiny1;
10107684d5e0Skleink 					goto cont;
10117684d5e0Skleink 					}
10127684d5e0Skleink 				else
101361e56760Schristos 					word0(&rv) -= P*Exp_msk1;
10147684d5e0Skleink 				}
10157684d5e0Skleink 			else {
101661e56760Schristos 				dval(&adj) = dval(&aadj1) * ulp(&rv);
101708a8bf52She 				dval(&rv) += dval(&adj);
10187684d5e0Skleink 				}
10197684d5e0Skleink #else /*Sudden_Underflow*/
102061e56760Schristos 			/* Compute dval(&adj) so that the IEEE rounding rules will
102161e56760Schristos 			 * correctly round rv + dval(&adj) in some half-way cases.
102261e56760Schristos 			 * If rv * ulp(&rv) is denormalized (i.e.,
10237684d5e0Skleink 			 * y <= (P-1)*Exp_msk1), we must adjust aadj to avoid
10247684d5e0Skleink 			 * trouble from bits lost to denormalization;
10257684d5e0Skleink 			 * example: 1.2e-307 .
10267684d5e0Skleink 			 */
10277684d5e0Skleink 			if (y <= (P-1)*Exp_msk1 && aadj > 1.) {
102861e56760Schristos 				dval(&aadj1) = (double)(int)(aadj + 0.5);
10297684d5e0Skleink 				if (!dsign)
103061e56760Schristos 					dval(&aadj1) = -dval(&aadj1);
10317684d5e0Skleink 				}
103261e56760Schristos 			dval(&adj) = dval(&aadj1) * ulp(&rv);
103361e56760Schristos 			dval(&rv) += adj;
10347684d5e0Skleink #endif /*Sudden_Underflow*/
10357684d5e0Skleink #endif /*Avoid_Underflow*/
10367684d5e0Skleink 			}
103761e56760Schristos 		z = word0(&rv) & Exp_mask;
10387684d5e0Skleink #ifndef SET_INEXACT
10397684d5e0Skleink #ifdef Avoid_Underflow
10407684d5e0Skleink 		if (!scale)
10417684d5e0Skleink #endif
10427684d5e0Skleink 		if (y == z) {
10437684d5e0Skleink 			/* Can we stop now? */
10447684d5e0Skleink 			L = (Long)aadj;
10457684d5e0Skleink 			aadj -= L;
10467684d5e0Skleink 			/* The tolerances below are conservative. */
104761e56760Schristos 			if (dsign || word1(&rv) || word0(&rv) & Bndry_mask) {
10487684d5e0Skleink 				if (aadj < .4999999 || aadj > .5000001)
10497684d5e0Skleink 					break;
10507684d5e0Skleink 				}
10517684d5e0Skleink 			else if (aadj < .4999999/FLT_RADIX)
10527684d5e0Skleink 				break;
10537684d5e0Skleink 			}
10547684d5e0Skleink #endif
10557684d5e0Skleink  cont:
10567684d5e0Skleink 		Bfree(bb);
10577684d5e0Skleink 		Bfree(bd);
10587684d5e0Skleink 		Bfree(bs);
10597684d5e0Skleink 		Bfree(delta);
10607684d5e0Skleink 		}
106161e56760Schristos 	Bfree(bb);
106261e56760Schristos 	Bfree(bd);
106361e56760Schristos 	Bfree(bs);
106461e56760Schristos 	Bfree(bd0);
106561e56760Schristos 	Bfree(delta);
10667684d5e0Skleink #ifdef SET_INEXACT
10677684d5e0Skleink 	if (inexact) {
10687684d5e0Skleink 		if (!oldinexact) {
106961e56760Schristos 			word0(&rv0) = Exp_1 + (70 << Exp_shift);
107061e56760Schristos 			word1(&rv0) = 0;
107161e56760Schristos 			dval(&rv0) += 1.;
10727684d5e0Skleink 			}
10737684d5e0Skleink 		}
10747684d5e0Skleink 	else if (!oldinexact)
10757684d5e0Skleink 		clear_inexact();
10767684d5e0Skleink #endif
10777684d5e0Skleink #ifdef Avoid_Underflow
10787684d5e0Skleink 	if (scale) {
107961e56760Schristos 		word0(&rv0) = Exp_1 - 2*P*Exp_msk1;
108061e56760Schristos 		word1(&rv0) = 0;
108161e56760Schristos 		dval(&rv) *= dval(&rv0);
10827684d5e0Skleink #ifndef NO_ERRNO
10837684d5e0Skleink 		/* try to avoid the bug of testing an 8087 register value */
108461e56760Schristos #ifdef IEEE_Arith
108561e56760Schristos 		if (!(word0(&rv) & Exp_mask))
108661e56760Schristos #else
108761e56760Schristos 		if (word0(&rv) == 0 && word1(&rv) == 0)
108861e56760Schristos #endif
10897684d5e0Skleink 			errno = ERANGE;
10907684d5e0Skleink #endif
10917684d5e0Skleink 		}
10927684d5e0Skleink #endif /* Avoid_Underflow */
10937684d5e0Skleink #ifdef SET_INEXACT
109461e56760Schristos 	if (inexact && !(word0(&rv) & Exp_mask)) {
10957684d5e0Skleink 		/* set underflow bit */
109661e56760Schristos 		dval(&rv0) = 1e-300;
109761e56760Schristos 		dval(&rv0) *= dval(&rv0);
10987684d5e0Skleink 		}
10997684d5e0Skleink #endif
11007684d5e0Skleink  ret:
11017684d5e0Skleink 	if (se)
1102ac898a26Skleink 		*se = __UNCONST(s);
110361e56760Schristos 	return sign ? -dval(&rv) : dval(&rv);
11047684d5e0Skleink 	}
11057684d5e0Skleink 
1106c99aac45Sjoerg double
1107c99aac45Sjoerg strtod(CONST char *s, char **sp)
1108c99aac45Sjoerg {
1109e0ac190eSjoerg 	return _int_strtod_l(s, sp, _current_locale());
1110c99aac45Sjoerg }
1111c99aac45Sjoerg 
1112c99aac45Sjoerg #ifdef __weak_alias
1113c99aac45Sjoerg __weak_alias(strtod_l, _strtod_l)
1114c99aac45Sjoerg #endif
1115c99aac45Sjoerg 
1116c99aac45Sjoerg double
1117c99aac45Sjoerg strtod_l(CONST char *s, char **sp, locale_t loc)
1118c99aac45Sjoerg {
1119c99aac45Sjoerg 	return _int_strtod_l(s, sp, loc);
1120c99aac45Sjoerg }
1121