1*ace5b9b5Schristos /* $NetBSD: dtoa.c,v 1.12 2024/01/20 14:52:46 christos Exp $ */
27684d5e0Skleink
37684d5e0Skleink /****************************************************************
47684d5e0Skleink
57684d5e0Skleink The author of this software is David M. Gay.
67684d5e0Skleink
77684d5e0Skleink Copyright (C) 1998, 1999 by Lucent Technologies
87684d5e0Skleink All Rights Reserved
97684d5e0Skleink
107684d5e0Skleink Permission to use, copy, modify, and distribute this software and
117684d5e0Skleink its documentation for any purpose and without fee is hereby
127684d5e0Skleink granted, provided that the above copyright notice appear in all
137684d5e0Skleink copies and that both that the copyright notice and this
147684d5e0Skleink permission notice and warranty disclaimer appear in supporting
157684d5e0Skleink documentation, and that the name of Lucent or any of its entities
167684d5e0Skleink not be used in advertising or publicity pertaining to
177684d5e0Skleink distribution of the software without specific, written prior
187684d5e0Skleink permission.
197684d5e0Skleink
207684d5e0Skleink LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
217684d5e0Skleink INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
227684d5e0Skleink IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
237684d5e0Skleink SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
247684d5e0Skleink WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
257684d5e0Skleink IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
267684d5e0Skleink ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
277684d5e0Skleink THIS SOFTWARE.
287684d5e0Skleink
297684d5e0Skleink ****************************************************************/
307684d5e0Skleink
317684d5e0Skleink /* Please send bug reports to David M. Gay (dmg at acm dot org,
327684d5e0Skleink * with " at " changed at "@" and " dot " changed to "."). */
337684d5e0Skleink
347684d5e0Skleink #include "gdtoaimp.h"
357684d5e0Skleink
367684d5e0Skleink /* dtoa for IEEE arithmetic (dmg): convert double to ASCII string.
377684d5e0Skleink *
387684d5e0Skleink * Inspired by "How to Print Floating-Point Numbers Accurately" by
397684d5e0Skleink * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 112-126].
407684d5e0Skleink *
417684d5e0Skleink * Modifications:
427684d5e0Skleink * 1. Rather than iterating, we use a simple numeric overestimate
437684d5e0Skleink * to determine k = floor(log10(d)). We scale relevant
447684d5e0Skleink * quantities using O(log2(k)) rather than O(k) multiplications.
457684d5e0Skleink * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't
467684d5e0Skleink * try to generate digits strictly left to right. Instead, we
477684d5e0Skleink * compute with fewer bits and propagate the carry if necessary
487684d5e0Skleink * when rounding the final digit up. This is often faster.
497684d5e0Skleink * 3. Under the assumption that input will be rounded nearest,
507684d5e0Skleink * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22.
517684d5e0Skleink * That is, we allow equality in stopping tests when the
527684d5e0Skleink * round-nearest rule will give the same floating-point value
537684d5e0Skleink * as would satisfaction of the stopping test with strict
547684d5e0Skleink * inequality.
557684d5e0Skleink * 4. We remove common factors of powers of 2 from relevant
567684d5e0Skleink * quantities.
577684d5e0Skleink * 5. When converting floating-point integers less than 1e16,
587684d5e0Skleink * we use floating-point arithmetic rather than resorting
597684d5e0Skleink * to multiple-precision integers.
607684d5e0Skleink * 6. When asked to produce fewer than 15 digits, we first try
617684d5e0Skleink * to get by with floating-point arithmetic; we resort to
627684d5e0Skleink * multiple-precision integer arithmetic only if we cannot
637684d5e0Skleink * guarantee that the floating-point calculation has given
647684d5e0Skleink * the correctly rounded result. For k requested digits and
657684d5e0Skleink * "uniformly" distributed input, the probability is
667684d5e0Skleink * something like 10^(k-15) that we must resort to the Long
677684d5e0Skleink * calculation.
687684d5e0Skleink */
697684d5e0Skleink
707684d5e0Skleink #ifdef Honor_FLT_ROUNDS
717684d5e0Skleink #undef Check_FLT_ROUNDS
727684d5e0Skleink #define Check_FLT_ROUNDS
737684d5e0Skleink #else
747684d5e0Skleink #define Rounding Flt_Rounds
757684d5e0Skleink #endif
767684d5e0Skleink
777684d5e0Skleink char *
dtoa(d0,mode,ndigits,decpt,sign,rve)787684d5e0Skleink dtoa
797684d5e0Skleink #ifdef KR_headers
8061e56760Schristos (d0, mode, ndigits, decpt, sign, rve)
8161e56760Schristos double d0; int mode, ndigits, *decpt, *sign; char **rve;
827684d5e0Skleink #else
8361e56760Schristos (double d0, int mode, int ndigits, int *decpt, int *sign, char **rve)
847684d5e0Skleink #endif
857684d5e0Skleink {
867684d5e0Skleink /* Arguments ndigits, decpt, sign are similar to those
877684d5e0Skleink of ecvt and fcvt; trailing zeros are suppressed from
887684d5e0Skleink the returned string. If not null, *rve is set to point
897684d5e0Skleink to the end of the return value. If d is +-Infinity or NaN,
907684d5e0Skleink then *decpt is set to 9999.
917684d5e0Skleink
927684d5e0Skleink mode:
937684d5e0Skleink 0 ==> shortest string that yields d when read in
947684d5e0Skleink and rounded to nearest.
957684d5e0Skleink 1 ==> like 0, but with Steele & White stopping rule;
967684d5e0Skleink e.g. with IEEE P754 arithmetic , mode 0 gives
977684d5e0Skleink 1e23 whereas mode 1 gives 9.999999999999999e22.
987684d5e0Skleink 2 ==> max(1,ndigits) significant digits. This gives a
997684d5e0Skleink return value similar to that of ecvt, except
1007684d5e0Skleink that trailing zeros are suppressed.
1017684d5e0Skleink 3 ==> through ndigits past the decimal point. This
1027684d5e0Skleink gives a return value similar to that from fcvt,
1037684d5e0Skleink except that trailing zeros are suppressed, and
1047684d5e0Skleink ndigits can be negative.
1057684d5e0Skleink 4,5 ==> similar to 2 and 3, respectively, but (in
1067684d5e0Skleink round-nearest mode) with the tests of mode 0 to
1077684d5e0Skleink possibly return a shorter string that rounds to d.
1087684d5e0Skleink With IEEE arithmetic and compilation with
1097684d5e0Skleink -DHonor_FLT_ROUNDS, modes 4 and 5 behave the same
1107684d5e0Skleink as modes 2 and 3 when FLT_ROUNDS != 1.
1117684d5e0Skleink 6-9 ==> Debugging modes similar to mode - 4: don't try
1127684d5e0Skleink fast floating-point estimate (if applicable).
1137684d5e0Skleink
1147684d5e0Skleink Values of mode other than 0-9 are treated as mode 0.
1157684d5e0Skleink
1167684d5e0Skleink Sufficient space is allocated to the return value
1177684d5e0Skleink to hold the suppressed trailing zeros.
1187684d5e0Skleink */
1197684d5e0Skleink
120ac898a26Skleink int bbits, b2, b5, be, dig, i, ieps, ilim0,
121ac898a26Skleink j, jj1, k, k0, k_check, leftright, m2, m5, s2, s5,
1227684d5e0Skleink spec_case, try_quick;
123ac898a26Skleink int ilim = 0, ilim1 = 0; /* pacify gcc */
1247684d5e0Skleink Long L;
1257684d5e0Skleink #ifndef Sudden_Underflow
1267684d5e0Skleink int denorm;
1277684d5e0Skleink ULong x;
1287684d5e0Skleink #endif
129ac898a26Skleink Bigint *b, *b1, *delta, *mhi, *S;
130ac898a26Skleink Bigint *mlo = NULL; /* pacify gcc */
13161e56760Schristos U d, d2, eps;
13261e56760Schristos double ds;
1337684d5e0Skleink char *s, *s0;
1347684d5e0Skleink #ifdef SET_INEXACT
1357684d5e0Skleink int inexact, oldinexact;
1367684d5e0Skleink #endif
13761e56760Schristos #ifdef Honor_FLT_ROUNDS /*{*/
13861e56760Schristos int Rounding;
13961e56760Schristos #ifdef Trust_FLT_ROUNDS /*{{ only define this if FLT_ROUNDS really works! */
14061e56760Schristos Rounding = Flt_Rounds;
14161e56760Schristos #else /*}{*/
14261e56760Schristos Rounding = 1;
14361e56760Schristos switch(fegetround()) {
14461e56760Schristos case FE_TOWARDZERO: Rounding = 0; break;
14561e56760Schristos case FE_UPWARD: Rounding = 2; break;
14661e56760Schristos case FE_DOWNWARD: Rounding = 3;
14761e56760Schristos }
14861e56760Schristos #endif /*}}*/
14961e56760Schristos #endif /*}*/
1507684d5e0Skleink
1517684d5e0Skleink #ifndef MULTIPLE_THREADS
1527684d5e0Skleink if (dtoa_result) {
1537684d5e0Skleink freedtoa(dtoa_result);
1547684d5e0Skleink dtoa_result = 0;
1557684d5e0Skleink }
1567684d5e0Skleink #endif
15761e56760Schristos d.d = d0;
15861e56760Schristos if (word0(&d) & Sign_bit) {
1597684d5e0Skleink /* set sign for everything, including 0's and NaNs */
1607684d5e0Skleink *sign = 1;
16161e56760Schristos word0(&d) &= ~Sign_bit; /* clear sign bit */
1627684d5e0Skleink }
1637684d5e0Skleink else
1647684d5e0Skleink *sign = 0;
1657684d5e0Skleink
1667684d5e0Skleink #if defined(IEEE_Arith) + defined(VAX)
1677684d5e0Skleink #ifdef IEEE_Arith
16861e56760Schristos if ((word0(&d) & Exp_mask) == Exp_mask)
1697684d5e0Skleink #else
17061e56760Schristos if (word0(&d) == 0x8000)
1717684d5e0Skleink #endif
1727684d5e0Skleink {
1737684d5e0Skleink /* Infinity or NaN */
1747684d5e0Skleink *decpt = 9999;
1757684d5e0Skleink #ifdef IEEE_Arith
17661e56760Schristos if (!word1(&d) && !(word0(&d) & 0xfffff))
1777684d5e0Skleink return nrv_alloc("Infinity", rve, 8);
1787684d5e0Skleink #endif
1797684d5e0Skleink return nrv_alloc("NaN", rve, 3);
1807684d5e0Skleink }
1817684d5e0Skleink #endif
1827684d5e0Skleink #ifdef IBM
18361e56760Schristos dval(&d) += 0; /* normalize */
1847684d5e0Skleink #endif
18561e56760Schristos if (!dval(&d)) {
1867684d5e0Skleink *decpt = 1;
1877684d5e0Skleink return nrv_alloc("0", rve, 1);
1887684d5e0Skleink }
1897684d5e0Skleink
1907684d5e0Skleink #ifdef SET_INEXACT
1917684d5e0Skleink try_quick = oldinexact = get_inexact();
1927684d5e0Skleink inexact = 1;
1937684d5e0Skleink #endif
1947684d5e0Skleink #ifdef Honor_FLT_ROUNDS
19561e56760Schristos if (Rounding >= 2) {
1967684d5e0Skleink if (*sign)
19761e56760Schristos Rounding = Rounding == 2 ? 0 : 2;
1987684d5e0Skleink else
19961e56760Schristos if (Rounding != 2)
20061e56760Schristos Rounding = 0;
2017684d5e0Skleink }
2027684d5e0Skleink #endif
2037684d5e0Skleink
20461e56760Schristos b = d2b(dval(&d), &be, &bbits);
205ab625449Schristos if (b == NULL)
206ab625449Schristos return NULL;
2077684d5e0Skleink #ifdef Sudden_Underflow
20861e56760Schristos i = (int)(word0(&d) >> Exp_shift1 & (Exp_mask>>Exp_shift1));
2097684d5e0Skleink #else
21061e56760Schristos if (( i = (int)(word0(&d) >> Exp_shift1 & (Exp_mask>>Exp_shift1)) )!=0) {
2117684d5e0Skleink #endif
21261e56760Schristos dval(&d2) = dval(&d);
21361e56760Schristos word0(&d2) &= Frac_mask1;
21461e56760Schristos word0(&d2) |= Exp_11;
2157684d5e0Skleink #ifdef IBM
21661e56760Schristos if (( j = 11 - hi0bits(word0(&d2) & Frac_mask) )!=0)
21761e56760Schristos dval(&d2) /= 1 << j;
2187684d5e0Skleink #endif
2197684d5e0Skleink
2207684d5e0Skleink /* log(x) ~=~ log(1.5) + (x-1.5)/1.5
2217684d5e0Skleink * log10(x) = log(x) / log(10)
2227684d5e0Skleink * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))
22361e56760Schristos * log10(&d) = (i-Bias)*log(2)/log(10) + log10(&d2)
2247684d5e0Skleink *
22561e56760Schristos * This suggests computing an approximation k to log10(&d) by
2267684d5e0Skleink *
2277684d5e0Skleink * k = (i - Bias)*0.301029995663981
2287684d5e0Skleink * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
2297684d5e0Skleink *
2307684d5e0Skleink * We want k to be too large rather than too small.
2317684d5e0Skleink * The error in the first-order Taylor series approximation
2327684d5e0Skleink * is in our favor, so we just round up the constant enough
2337684d5e0Skleink * to compensate for any error in the multiplication of
2347684d5e0Skleink * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077,
2357684d5e0Skleink * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14,
2367684d5e0Skleink * adding 1e-13 to the constant term more than suffices.
2377684d5e0Skleink * Hence we adjust the constant term to 0.1760912590558.
2387684d5e0Skleink * (We could get a more accurate k by invoking log10,
2397684d5e0Skleink * but this is probably not worthwhile.)
2407684d5e0Skleink */
2417684d5e0Skleink
2427684d5e0Skleink i -= Bias;
2437684d5e0Skleink #ifdef IBM
2447684d5e0Skleink i <<= 2;
2457684d5e0Skleink i += j;
2467684d5e0Skleink #endif
2477684d5e0Skleink #ifndef Sudden_Underflow
2487684d5e0Skleink denorm = 0;
2497684d5e0Skleink }
2507684d5e0Skleink else {
2517684d5e0Skleink /* d is denormalized */
2527684d5e0Skleink
2537684d5e0Skleink i = bbits + be + (Bias + (P-1) - 1);
25461e56760Schristos x = i > 32 ? word0(&d) << (64 - i) | word1(&d) >> (i - 32)
25561e56760Schristos : word1(&d) << (32 - i);
25661e56760Schristos dval(&d2) = x;
25761e56760Schristos word0(&d2) -= 31*Exp_msk1; /* adjust exponent */
2587684d5e0Skleink i -= (Bias + (P-1) - 1) + 1;
2597684d5e0Skleink denorm = 1;
2607684d5e0Skleink }
2617684d5e0Skleink #endif
26261e56760Schristos ds = (dval(&d2)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
2637684d5e0Skleink k = (int)ds;
2647684d5e0Skleink if (ds < 0. && ds != k)
2657684d5e0Skleink k--; /* want k = floor(ds) */
2667684d5e0Skleink k_check = 1;
2677684d5e0Skleink if (k >= 0 && k <= Ten_pmax) {
26861e56760Schristos if (dval(&d) < tens[k])
2697684d5e0Skleink k--;
2707684d5e0Skleink k_check = 0;
2717684d5e0Skleink }
2727684d5e0Skleink j = bbits - i - 1;
2737684d5e0Skleink if (j >= 0) {
2747684d5e0Skleink b2 = 0;
2757684d5e0Skleink s2 = j;
2767684d5e0Skleink }
2777684d5e0Skleink else {
2787684d5e0Skleink b2 = -j;
2797684d5e0Skleink s2 = 0;
2807684d5e0Skleink }
2817684d5e0Skleink if (k >= 0) {
2827684d5e0Skleink b5 = 0;
2837684d5e0Skleink s5 = k;
2847684d5e0Skleink s2 += k;
2857684d5e0Skleink }
2867684d5e0Skleink else {
2877684d5e0Skleink b2 -= k;
2887684d5e0Skleink b5 = -k;
2897684d5e0Skleink s5 = 0;
2907684d5e0Skleink }
2917684d5e0Skleink if (mode < 0 || mode > 9)
2927684d5e0Skleink mode = 0;
2937684d5e0Skleink
2947684d5e0Skleink #ifndef SET_INEXACT
2957684d5e0Skleink #ifdef Check_FLT_ROUNDS
2967684d5e0Skleink try_quick = Rounding == 1;
2977684d5e0Skleink #else
2987684d5e0Skleink try_quick = 1;
2997684d5e0Skleink #endif
3007684d5e0Skleink #endif /*SET_INEXACT*/
3017684d5e0Skleink
3027684d5e0Skleink if (mode > 5) {
3037684d5e0Skleink mode -= 4;
3047684d5e0Skleink try_quick = 0;
3057684d5e0Skleink }
3067684d5e0Skleink leftright = 1;
30761e56760Schristos ilim = ilim1 = -1; /* Values for cases 0 and 1; done here to */
30861e56760Schristos /* silence erroneous "gcc -Wall" warning. */
3097684d5e0Skleink switch(mode) {
3107684d5e0Skleink case 0:
3117684d5e0Skleink case 1:
3127684d5e0Skleink i = 18;
3137684d5e0Skleink ndigits = 0;
3147684d5e0Skleink break;
3157684d5e0Skleink case 2:
3167684d5e0Skleink leftright = 0;
317ac898a26Skleink /* FALLTHROUGH */
3187684d5e0Skleink case 4:
3197684d5e0Skleink if (ndigits <= 0)
3207684d5e0Skleink ndigits = 1;
3217684d5e0Skleink ilim = ilim1 = i = ndigits;
3227684d5e0Skleink break;
3237684d5e0Skleink case 3:
3247684d5e0Skleink leftright = 0;
325ac898a26Skleink /* FALLTHROUGH */
3267684d5e0Skleink case 5:
3277684d5e0Skleink i = ndigits + k + 1;
3287684d5e0Skleink ilim = i;
3297684d5e0Skleink ilim1 = i - 1;
3307684d5e0Skleink if (i <= 0)
3317684d5e0Skleink i = 1;
3327684d5e0Skleink }
333c8e7c687Schristos s = s0 = rv_alloc((size_t)i);
334ab625449Schristos if (s == NULL)
335ab625449Schristos return NULL;
3367684d5e0Skleink
3377684d5e0Skleink #ifdef Honor_FLT_ROUNDS
33861e56760Schristos if (mode > 1 && Rounding != 1)
3397684d5e0Skleink leftright = 0;
3407684d5e0Skleink #endif
3417684d5e0Skleink
3427684d5e0Skleink if (ilim >= 0 && ilim <= Quick_max && try_quick) {
3437684d5e0Skleink
3447684d5e0Skleink /* Try to get by with floating-point arithmetic. */
3457684d5e0Skleink
3467684d5e0Skleink i = 0;
34761e56760Schristos dval(&d2) = dval(&d);
3487684d5e0Skleink k0 = k;
3497684d5e0Skleink ilim0 = ilim;
3507684d5e0Skleink ieps = 2; /* conservative */
3517684d5e0Skleink if (k > 0) {
3527684d5e0Skleink ds = tens[k&0xf];
353ac898a26Skleink j = (unsigned int)k >> 4;
3547684d5e0Skleink if (j & Bletch) {
3557684d5e0Skleink /* prevent overflows */
3567684d5e0Skleink j &= Bletch - 1;
35761e56760Schristos dval(&d) /= bigtens[n_bigtens-1];
3587684d5e0Skleink ieps++;
3597684d5e0Skleink }
360ac898a26Skleink for(; j; j = (unsigned int)j >> 1, i++)
3617684d5e0Skleink if (j & 1) {
3627684d5e0Skleink ieps++;
3637684d5e0Skleink ds *= bigtens[i];
3647684d5e0Skleink }
36561e56760Schristos dval(&d) /= ds;
3667684d5e0Skleink }
367ac898a26Skleink else if (( jj1 = -k )!=0) {
36861e56760Schristos dval(&d) *= tens[jj1 & 0xf];
369*ace5b9b5Schristos for(j = (unsigned int)jj1 >> 4; j; j = (unsigned int)j >> 1, i++)
3707684d5e0Skleink if (j & 1) {
3717684d5e0Skleink ieps++;
37261e56760Schristos dval(&d) *= bigtens[i];
3737684d5e0Skleink }
3747684d5e0Skleink }
37561e56760Schristos if (k_check && dval(&d) < 1. && ilim > 0) {
3767684d5e0Skleink if (ilim1 <= 0)
3777684d5e0Skleink goto fast_failed;
3787684d5e0Skleink ilim = ilim1;
3797684d5e0Skleink k--;
38061e56760Schristos dval(&d) *= 10.;
3817684d5e0Skleink ieps++;
3827684d5e0Skleink }
38361e56760Schristos dval(&eps) = ieps*dval(&d) + 7.;
38461e56760Schristos word0(&eps) -= (P-1)*Exp_msk1;
3857684d5e0Skleink if (ilim == 0) {
3867684d5e0Skleink S = mhi = 0;
38761e56760Schristos dval(&d) -= 5.;
38861e56760Schristos if (dval(&d) > dval(&eps))
3897684d5e0Skleink goto one_digit;
39061e56760Schristos if (dval(&d) < -dval(&eps))
3917684d5e0Skleink goto no_digits;
3927684d5e0Skleink goto fast_failed;
3937684d5e0Skleink }
3947684d5e0Skleink #ifndef No_leftright
3957684d5e0Skleink if (leftright) {
3967684d5e0Skleink /* Use Steele & White method of only
3977684d5e0Skleink * generating digits needed.
3987684d5e0Skleink */
39961e56760Schristos dval(&eps) = 0.5/tens[ilim-1] - dval(&eps);
4007684d5e0Skleink for(i = 0;;) {
40161e56760Schristos L = dval(&d);
40261e56760Schristos dval(&d) -= L;
4037684d5e0Skleink *s++ = '0' + (int)L;
40461e56760Schristos if (dval(&d) < dval(&eps))
4057684d5e0Skleink goto ret1;
40661e56760Schristos if (1. - dval(&d) < dval(&eps))
4077684d5e0Skleink goto bump_up;
4087684d5e0Skleink if (++i >= ilim)
4097684d5e0Skleink break;
41061e56760Schristos dval(&eps) *= 10.;
41161e56760Schristos dval(&d) *= 10.;
4127684d5e0Skleink }
4137684d5e0Skleink }
4147684d5e0Skleink else {
4157684d5e0Skleink #endif
4167684d5e0Skleink /* Generate ilim digits, then fix them up. */
41761e56760Schristos dval(&eps) *= tens[ilim-1];
41861e56760Schristos for(i = 1;; i++, dval(&d) *= 10.) {
41961e56760Schristos L = (Long)(dval(&d));
42061e56760Schristos if (!(dval(&d) -= L))
4217684d5e0Skleink ilim = i;
4227684d5e0Skleink *s++ = '0' + (int)L;
4237684d5e0Skleink if (i == ilim) {
42461e56760Schristos if (dval(&d) > 0.5 + dval(&eps))
4257684d5e0Skleink goto bump_up;
42661e56760Schristos else if (dval(&d) < 0.5 - dval(&eps)) {
4277684d5e0Skleink while(*--s == '0');
4287684d5e0Skleink s++;
4297684d5e0Skleink goto ret1;
4307684d5e0Skleink }
4317684d5e0Skleink break;
4327684d5e0Skleink }
4337684d5e0Skleink }
4347684d5e0Skleink #ifndef No_leftright
4357684d5e0Skleink }
4367684d5e0Skleink #endif
4377684d5e0Skleink fast_failed:
4387684d5e0Skleink s = s0;
43961e56760Schristos dval(&d) = dval(&d2);
4407684d5e0Skleink k = k0;
4417684d5e0Skleink ilim = ilim0;
4427684d5e0Skleink }
4437684d5e0Skleink
4447684d5e0Skleink /* Do we have a "small" integer? */
4457684d5e0Skleink
4467684d5e0Skleink if (be >= 0 && k <= Int_max) {
4477684d5e0Skleink /* Yes. */
4487684d5e0Skleink ds = tens[k];
4497684d5e0Skleink if (ndigits < 0 && ilim <= 0) {
4507684d5e0Skleink S = mhi = 0;
45161e56760Schristos if (ilim < 0 || dval(&d) <= 5*ds)
4527684d5e0Skleink goto no_digits;
4537684d5e0Skleink goto one_digit;
4547684d5e0Skleink }
45561e56760Schristos for(i = 1;; i++, dval(&d) *= 10.) {
45661e56760Schristos L = (Long)(dval(&d) / ds);
45761e56760Schristos dval(&d) -= L*ds;
4587684d5e0Skleink #ifdef Check_FLT_ROUNDS
4597684d5e0Skleink /* If FLT_ROUNDS == 2, L will usually be high by 1 */
46061e56760Schristos if (dval(&d) < 0) {
4617684d5e0Skleink L--;
46261e56760Schristos dval(&d) += ds;
4637684d5e0Skleink }
4647684d5e0Skleink #endif
4657684d5e0Skleink *s++ = '0' + (int)L;
46661e56760Schristos if (!dval(&d)) {
4677684d5e0Skleink #ifdef SET_INEXACT
4687684d5e0Skleink inexact = 0;
4697684d5e0Skleink #endif
4707684d5e0Skleink break;
4717684d5e0Skleink }
4727684d5e0Skleink if (i == ilim) {
4737684d5e0Skleink #ifdef Honor_FLT_ROUNDS
4747684d5e0Skleink if (mode > 1)
47561e56760Schristos switch(Rounding) {
4767684d5e0Skleink case 0: goto ret1;
4777684d5e0Skleink case 2: goto bump_up;
4787684d5e0Skleink }
4797684d5e0Skleink #endif
48061e56760Schristos dval(&d) += dval(&d);
48161e56760Schristos #ifdef ROUND_BIASED
48261e56760Schristos if (dval(&d) >= ds)
48361e56760Schristos #else
48461e56760Schristos if (dval(&d) > ds || (dval(&d) == ds && L & 1))
48561e56760Schristos #endif
48661e56760Schristos {
4877684d5e0Skleink bump_up:
4887684d5e0Skleink while(*--s == '9')
4897684d5e0Skleink if (s == s0) {
4907684d5e0Skleink k++;
4917684d5e0Skleink *s = '0';
4927684d5e0Skleink break;
4937684d5e0Skleink }
4947684d5e0Skleink ++*s++;
4957684d5e0Skleink }
4967684d5e0Skleink break;
4977684d5e0Skleink }
4987684d5e0Skleink }
4997684d5e0Skleink goto ret1;
5007684d5e0Skleink }
5017684d5e0Skleink
5027684d5e0Skleink m2 = b2;
5037684d5e0Skleink m5 = b5;
5047684d5e0Skleink mhi = mlo = 0;
5057684d5e0Skleink if (leftright) {
5067684d5e0Skleink i =
5077684d5e0Skleink #ifndef Sudden_Underflow
5087684d5e0Skleink denorm ? be + (Bias + (P-1) - 1 + 1) :
5097684d5e0Skleink #endif
5107684d5e0Skleink #ifdef IBM
5117684d5e0Skleink 1 + 4*P - 3 - bbits + ((bbits + be - 1) & 3);
5127684d5e0Skleink #else
5137684d5e0Skleink 1 + P - bbits;
5147684d5e0Skleink #endif
5157684d5e0Skleink b2 += i;
5167684d5e0Skleink s2 += i;
5177684d5e0Skleink mhi = i2b(1);
518ab625449Schristos if (mhi == NULL)
519ab625449Schristos return NULL;
5207684d5e0Skleink }
5217684d5e0Skleink if (m2 > 0 && s2 > 0) {
5227684d5e0Skleink i = m2 < s2 ? m2 : s2;
5237684d5e0Skleink b2 -= i;
5247684d5e0Skleink m2 -= i;
5257684d5e0Skleink s2 -= i;
5267684d5e0Skleink }
5277684d5e0Skleink if (b5 > 0) {
5287684d5e0Skleink if (leftright) {
5297684d5e0Skleink if (m5 > 0) {
5307684d5e0Skleink mhi = pow5mult(mhi, m5);
531ab625449Schristos if (mhi == NULL)
532ab625449Schristos return NULL;
5337684d5e0Skleink b1 = mult(mhi, b);
534ab625449Schristos if (b1 == NULL)
535ab625449Schristos return NULL;
5367684d5e0Skleink Bfree(b);
5377684d5e0Skleink b = b1;
5387684d5e0Skleink }
539d829b852Salnsn if (( j = b5 - m5 )!=0) {
5407684d5e0Skleink b = pow5mult(b, j);
541ab625449Schristos if (b == NULL)
542ab625449Schristos return NULL;
5437684d5e0Skleink }
544d829b852Salnsn }
545d829b852Salnsn else {
5467684d5e0Skleink b = pow5mult(b, b5);
547ab625449Schristos if (b == NULL)
548ab625449Schristos return NULL;
5497684d5e0Skleink }
550d829b852Salnsn }
5517684d5e0Skleink S = i2b(1);
552ab625449Schristos if (S == NULL)
553ab625449Schristos return NULL;
554ab625449Schristos if (s5 > 0) {
5557684d5e0Skleink S = pow5mult(S, s5);
556ab625449Schristos if (S == NULL)
557ab625449Schristos return NULL;
558ab625449Schristos }
5597684d5e0Skleink
5607684d5e0Skleink /* Check for special case that d is a normalized power of 2. */
5617684d5e0Skleink
5627684d5e0Skleink spec_case = 0;
5637684d5e0Skleink if ((mode < 2 || leftright)
5647684d5e0Skleink #ifdef Honor_FLT_ROUNDS
56561e56760Schristos && Rounding == 1
5667684d5e0Skleink #endif
5677684d5e0Skleink ) {
56861e56760Schristos if (!word1(&d) && !(word0(&d) & Bndry_mask)
5697684d5e0Skleink #ifndef Sudden_Underflow
57061e56760Schristos && word0(&d) & (Exp_mask & ~Exp_msk1)
5717684d5e0Skleink #endif
5727684d5e0Skleink ) {
5737684d5e0Skleink /* The special case */
5747684d5e0Skleink b2 += Log2P;
5757684d5e0Skleink s2 += Log2P;
5767684d5e0Skleink spec_case = 1;
5777684d5e0Skleink }
5787684d5e0Skleink }
5797684d5e0Skleink
5807684d5e0Skleink /* Arrange for convenient computation of quotients:
5817684d5e0Skleink * shift left if necessary so divisor has 4 leading 0 bits.
5827684d5e0Skleink *
5837684d5e0Skleink * Perhaps we should just compute leading 28 bits of S once
5847684d5e0Skleink * and for all and pass them and a shift to quorem, so it
5857684d5e0Skleink * can do shifts and ors to compute the numerator for q.
5867684d5e0Skleink */
5877684d5e0Skleink #ifdef Pack_32
5887684d5e0Skleink if (( i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f )!=0)
5897684d5e0Skleink i = 32 - i;
5907684d5e0Skleink #else
5917684d5e0Skleink if (( i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf )!=0)
5927684d5e0Skleink i = 16 - i;
5937684d5e0Skleink #endif
5947684d5e0Skleink if (i > 4) {
5957684d5e0Skleink i -= 4;
5967684d5e0Skleink b2 += i;
5977684d5e0Skleink m2 += i;
5987684d5e0Skleink s2 += i;
5997684d5e0Skleink }
6007684d5e0Skleink else if (i < 4) {
6017684d5e0Skleink i += 28;
6027684d5e0Skleink b2 += i;
6037684d5e0Skleink m2 += i;
6047684d5e0Skleink s2 += i;
6057684d5e0Skleink }
606ab625449Schristos if (b2 > 0) {
6077684d5e0Skleink b = lshift(b, b2);
608ab625449Schristos if (b == NULL)
609ab625449Schristos return NULL;
610ab625449Schristos }
611ab625449Schristos if (s2 > 0) {
6127684d5e0Skleink S = lshift(S, s2);
613ab625449Schristos if (S == NULL)
614ab625449Schristos return NULL;
615ab625449Schristos }
6167684d5e0Skleink if (k_check) {
6177684d5e0Skleink if (cmp(b,S) < 0) {
6187684d5e0Skleink k--;
6197684d5e0Skleink b = multadd(b, 10, 0); /* we botched the k estimate */
620ab625449Schristos if (b == NULL)
621ab625449Schristos return NULL;
622ab625449Schristos if (leftright) {
6237684d5e0Skleink mhi = multadd(mhi, 10, 0);
624ab625449Schristos if (mhi == NULL)
625ab625449Schristos return NULL;
626ab625449Schristos }
6277684d5e0Skleink ilim = ilim1;
6287684d5e0Skleink }
6297684d5e0Skleink }
6307684d5e0Skleink if (ilim <= 0 && (mode == 3 || mode == 5)) {
6317684d5e0Skleink if (ilim < 0 || cmp(b,S = multadd(S,5,0)) <= 0) {
6327684d5e0Skleink /* no digits, fcvt style */
6337684d5e0Skleink no_digits:
6347684d5e0Skleink k = -1 - ndigits;
6357684d5e0Skleink goto ret;
6367684d5e0Skleink }
6377684d5e0Skleink one_digit:
6387684d5e0Skleink *s++ = '1';
6397684d5e0Skleink k++;
6407684d5e0Skleink goto ret;
6417684d5e0Skleink }
6427684d5e0Skleink if (leftright) {
643ab625449Schristos if (m2 > 0) {
6447684d5e0Skleink mhi = lshift(mhi, m2);
645ab625449Schristos if (mhi == NULL)
646ab625449Schristos return NULL;
647ab625449Schristos }
6487684d5e0Skleink
6497684d5e0Skleink /* Compute mlo -- check for special case
6507684d5e0Skleink * that d is a normalized power of 2.
6517684d5e0Skleink */
6527684d5e0Skleink
6537684d5e0Skleink mlo = mhi;
6547684d5e0Skleink if (spec_case) {
6557684d5e0Skleink mhi = Balloc(mhi->k);
656ab625449Schristos if (mhi == NULL)
657ab625449Schristos return NULL;
6587684d5e0Skleink Bcopy(mhi, mlo);
6597684d5e0Skleink mhi = lshift(mhi, Log2P);
660ab625449Schristos if (mhi == NULL)
661ab625449Schristos return NULL;
6627684d5e0Skleink }
6637684d5e0Skleink
6647684d5e0Skleink for(i = 1;;i++) {
6657684d5e0Skleink dig = quorem(b,S) + '0';
6667684d5e0Skleink /* Do we yet have the shortest decimal string
6677684d5e0Skleink * that will round to d?
6687684d5e0Skleink */
6697684d5e0Skleink j = cmp(b, mlo);
6707684d5e0Skleink delta = diff(S, mhi);
671ab625449Schristos if (delta == NULL)
672ab625449Schristos return NULL;
673ac898a26Skleink jj1 = delta->sign ? 1 : cmp(b, delta);
6747684d5e0Skleink Bfree(delta);
6757684d5e0Skleink #ifndef ROUND_BIASED
67661e56760Schristos if (jj1 == 0 && mode != 1 && !(word1(&d) & 1)
6777684d5e0Skleink #ifdef Honor_FLT_ROUNDS
67861e56760Schristos && Rounding >= 1
6797684d5e0Skleink #endif
6807684d5e0Skleink ) {
6817684d5e0Skleink if (dig == '9')
6827684d5e0Skleink goto round_9_up;
6837684d5e0Skleink if (j > 0)
6847684d5e0Skleink dig++;
6857684d5e0Skleink #ifdef SET_INEXACT
6867684d5e0Skleink else if (!b->x[0] && b->wds <= 1)
6877684d5e0Skleink inexact = 0;
6887684d5e0Skleink #endif
6897684d5e0Skleink *s++ = dig;
6907684d5e0Skleink goto ret;
6917684d5e0Skleink }
6927684d5e0Skleink #endif
693ac898a26Skleink if (j < 0 || (j == 0 && mode != 1
6947684d5e0Skleink #ifndef ROUND_BIASED
69561e56760Schristos && !(word1(&d) & 1)
6967684d5e0Skleink #endif
697ac898a26Skleink )) {
6987684d5e0Skleink if (!b->x[0] && b->wds <= 1) {
6997684d5e0Skleink #ifdef SET_INEXACT
7007684d5e0Skleink inexact = 0;
7017684d5e0Skleink #endif
7027684d5e0Skleink goto accept_dig;
7037684d5e0Skleink }
7047684d5e0Skleink #ifdef Honor_FLT_ROUNDS
7057684d5e0Skleink if (mode > 1)
70661e56760Schristos switch(Rounding) {
7077684d5e0Skleink case 0: goto accept_dig;
7087684d5e0Skleink case 2: goto keep_dig;
7097684d5e0Skleink }
7107684d5e0Skleink #endif /*Honor_FLT_ROUNDS*/
711ac898a26Skleink if (jj1 > 0) {
7127684d5e0Skleink b = lshift(b, 1);
713ab625449Schristos if (b == NULL)
714ab625449Schristos return NULL;
715ac898a26Skleink jj1 = cmp(b, S);
71661e56760Schristos #ifdef ROUND_BIASED
717ab9f1e36Schristos if (jj1 >= 0 /*)*/
71861e56760Schristos #else
719ac898a26Skleink if ((jj1 > 0 || (jj1 == 0 && dig & 1))
72061e56760Schristos #endif
7217684d5e0Skleink && dig++ == '9')
7227684d5e0Skleink goto round_9_up;
7237684d5e0Skleink }
7247684d5e0Skleink accept_dig:
7257684d5e0Skleink *s++ = dig;
7267684d5e0Skleink goto ret;
7277684d5e0Skleink }
728ac898a26Skleink if (jj1 > 0) {
7297684d5e0Skleink #ifdef Honor_FLT_ROUNDS
73061e56760Schristos if (!Rounding)
7317684d5e0Skleink goto accept_dig;
7327684d5e0Skleink #endif
7337684d5e0Skleink if (dig == '9') { /* possible if i == 1 */
7347684d5e0Skleink round_9_up:
7357684d5e0Skleink *s++ = '9';
7367684d5e0Skleink goto roundoff;
7377684d5e0Skleink }
7387684d5e0Skleink *s++ = dig + 1;
7397684d5e0Skleink goto ret;
7407684d5e0Skleink }
7417684d5e0Skleink #ifdef Honor_FLT_ROUNDS
7427684d5e0Skleink keep_dig:
7437684d5e0Skleink #endif
7447684d5e0Skleink *s++ = dig;
7457684d5e0Skleink if (i == ilim)
7467684d5e0Skleink break;
7477684d5e0Skleink b = multadd(b, 10, 0);
748ab625449Schristos if (b == NULL)
749ab625449Schristos return NULL;
750ab625449Schristos if (mlo == mhi) {
7517684d5e0Skleink mlo = mhi = multadd(mhi, 10, 0);
752ab625449Schristos if (mlo == NULL)
753ab625449Schristos return NULL;
754ab625449Schristos }
7557684d5e0Skleink else {
7567684d5e0Skleink mlo = multadd(mlo, 10, 0);
757ab625449Schristos if (mlo == NULL)
758ab625449Schristos return NULL;
7597684d5e0Skleink mhi = multadd(mhi, 10, 0);
760ab625449Schristos if (mhi == NULL)
761ab625449Schristos return NULL;
7627684d5e0Skleink }
7637684d5e0Skleink }
7647684d5e0Skleink }
7657684d5e0Skleink else
7667684d5e0Skleink for(i = 1;; i++) {
7677684d5e0Skleink *s++ = dig = quorem(b,S) + '0';
7687684d5e0Skleink if (!b->x[0] && b->wds <= 1) {
7697684d5e0Skleink #ifdef SET_INEXACT
7707684d5e0Skleink inexact = 0;
7717684d5e0Skleink #endif
7727684d5e0Skleink goto ret;
7737684d5e0Skleink }
7747684d5e0Skleink if (i >= ilim)
7757684d5e0Skleink break;
7767684d5e0Skleink b = multadd(b, 10, 0);
777ab625449Schristos if (b == NULL)
778ab625449Schristos return NULL;
7797684d5e0Skleink }
7807684d5e0Skleink
7817684d5e0Skleink /* Round off last digit */
7827684d5e0Skleink
7837684d5e0Skleink #ifdef Honor_FLT_ROUNDS
78461e56760Schristos switch(Rounding) {
7857684d5e0Skleink case 0: goto trimzeros;
7867684d5e0Skleink case 2: goto roundoff;
7877684d5e0Skleink }
7887684d5e0Skleink #endif
7897684d5e0Skleink b = lshift(b, 1);
7909feb722eSchristos if (b == NULL)
7919feb722eSchristos return NULL;
7927684d5e0Skleink j = cmp(b, S);
79361e56760Schristos #ifdef ROUND_BIASED
79461e56760Schristos if (j >= 0)
79561e56760Schristos #else
79661e56760Schristos if (j > 0 || (j == 0 && dig & 1))
79761e56760Schristos #endif
79861e56760Schristos {
7997684d5e0Skleink roundoff:
8007684d5e0Skleink while(*--s == '9')
8017684d5e0Skleink if (s == s0) {
8027684d5e0Skleink k++;
8037684d5e0Skleink *s++ = '1';
8047684d5e0Skleink goto ret;
8057684d5e0Skleink }
8067684d5e0Skleink ++*s++;
8077684d5e0Skleink }
8087684d5e0Skleink else {
809ac898a26Skleink #ifdef Honor_FLT_ROUNDS
8107684d5e0Skleink trimzeros:
811ac898a26Skleink #endif
8127684d5e0Skleink while(*--s == '0');
8137684d5e0Skleink s++;
8147684d5e0Skleink }
8157684d5e0Skleink ret:
8167684d5e0Skleink Bfree(S);
8177684d5e0Skleink if (mhi) {
8187684d5e0Skleink if (mlo && mlo != mhi)
8197684d5e0Skleink Bfree(mlo);
8207684d5e0Skleink Bfree(mhi);
8217684d5e0Skleink }
8227684d5e0Skleink ret1:
8237684d5e0Skleink #ifdef SET_INEXACT
8247684d5e0Skleink if (inexact) {
8257684d5e0Skleink if (!oldinexact) {
82661e56760Schristos word0(&d) = Exp_1 + (70 << Exp_shift);
82761e56760Schristos word1(&d) = 0;
82861e56760Schristos dval(&d) += 1.;
8297684d5e0Skleink }
8307684d5e0Skleink }
8317684d5e0Skleink else if (!oldinexact)
8327684d5e0Skleink clear_inexact();
8337684d5e0Skleink #endif
8347684d5e0Skleink Bfree(b);
83511ef0797Skleink if (s == s0) { /* don't return empty string */
83611ef0797Skleink *s++ = '0';
83711ef0797Skleink k = 0;
83811ef0797Skleink }
8397684d5e0Skleink *s = 0;
8407684d5e0Skleink *decpt = k + 1;
8417684d5e0Skleink if (rve)
8427684d5e0Skleink *rve = s;
8437684d5e0Skleink return s0;
8447684d5e0Skleink }
845