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