1*ace5b9b5Schristos /* $NetBSD: gdtoa.c,v 1.11 2024/01/20 14:52:47 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 static Bigint *
377684d5e0Skleink #ifdef KR_headers
bitstob(bits,nbits,bbits)387684d5e0Skleink bitstob(bits, nbits, bbits) ULong *bits; int nbits; int *bbits;
397684d5e0Skleink #else
407684d5e0Skleink bitstob(ULong *bits, int nbits, int *bbits)
417684d5e0Skleink #endif
427684d5e0Skleink {
437684d5e0Skleink int i, k;
447684d5e0Skleink Bigint *b;
457684d5e0Skleink ULong *be, *x, *x0;
467684d5e0Skleink
477684d5e0Skleink i = ULbits;
487684d5e0Skleink k = 0;
497684d5e0Skleink while(i < nbits) {
507684d5e0Skleink i <<= 1;
517684d5e0Skleink k++;
527684d5e0Skleink }
537684d5e0Skleink #ifndef Pack_32
547684d5e0Skleink if (!k)
557684d5e0Skleink k = 1;
567684d5e0Skleink #endif
577684d5e0Skleink b = Balloc(k);
58ab625449Schristos if (b == NULL)
59ab625449Schristos return NULL;
601634560eSchristos be = bits + (((unsigned int)nbits - 1) >> kshift);
617684d5e0Skleink x = x0 = b->x;
627684d5e0Skleink do {
637684d5e0Skleink *x++ = *bits & ALL_ON;
647684d5e0Skleink #ifdef Pack_16
657684d5e0Skleink *x++ = (*bits >> 16) & ALL_ON;
667684d5e0Skleink #endif
677684d5e0Skleink } while(++bits <= be);
68c5e820caSchristos ptrdiff_t td = x - x0;
69c5e820caSchristos _DIAGASSERT(__type_fit(int, td));
70c5e820caSchristos i = (int)td;
717684d5e0Skleink while(!x0[--i])
727684d5e0Skleink if (!i) {
737684d5e0Skleink b->wds = 0;
747684d5e0Skleink *bbits = 0;
757684d5e0Skleink goto ret;
767684d5e0Skleink }
777684d5e0Skleink b->wds = i + 1;
787684d5e0Skleink *bbits = i*ULbits + 32 - hi0bits(b->x[i]);
797684d5e0Skleink ret:
807684d5e0Skleink return b;
817684d5e0Skleink }
827684d5e0Skleink
837684d5e0Skleink /* dtoa for IEEE arithmetic (dmg): convert double to ASCII string.
847684d5e0Skleink *
857684d5e0Skleink * Inspired by "How to Print Floating-Point Numbers Accurately" by
867684d5e0Skleink * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 112-126].
877684d5e0Skleink *
887684d5e0Skleink * Modifications:
897684d5e0Skleink * 1. Rather than iterating, we use a simple numeric overestimate
907684d5e0Skleink * to determine k = floor(log10(d)). We scale relevant
917684d5e0Skleink * quantities using O(log2(k)) rather than O(k) multiplications.
927684d5e0Skleink * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't
937684d5e0Skleink * try to generate digits strictly left to right. Instead, we
947684d5e0Skleink * compute with fewer bits and propagate the carry if necessary
957684d5e0Skleink * when rounding the final digit up. This is often faster.
967684d5e0Skleink * 3. Under the assumption that input will be rounded nearest,
977684d5e0Skleink * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22.
987684d5e0Skleink * That is, we allow equality in stopping tests when the
997684d5e0Skleink * round-nearest rule will give the same floating-point value
1007684d5e0Skleink * as would satisfaction of the stopping test with strict
1017684d5e0Skleink * inequality.
1027684d5e0Skleink * 4. We remove common factors of powers of 2 from relevant
1037684d5e0Skleink * quantities.
1047684d5e0Skleink * 5. When converting floating-point integers less than 1e16,
1057684d5e0Skleink * we use floating-point arithmetic rather than resorting
1067684d5e0Skleink * to multiple-precision integers.
1077684d5e0Skleink * 6. When asked to produce fewer than 15 digits, we first try
1087684d5e0Skleink * to get by with floating-point arithmetic; we resort to
1097684d5e0Skleink * multiple-precision integer arithmetic only if we cannot
1107684d5e0Skleink * guarantee that the floating-point calculation has given
1117684d5e0Skleink * the correctly rounded result. For k requested digits and
1127684d5e0Skleink * "uniformly" distributed input, the probability is
1137684d5e0Skleink * something like 10^(k-15) that we must resort to the Long
1147684d5e0Skleink * calculation.
1157684d5e0Skleink */
1167684d5e0Skleink
1177684d5e0Skleink char *
gdtoa(fpi,be,bits,kindp,mode,ndigits,decpt,rve)1187684d5e0Skleink gdtoa
1197684d5e0Skleink #ifdef KR_headers
1207684d5e0Skleink (fpi, be, bits, kindp, mode, ndigits, decpt, rve)
1219a9a4122Sriastradh CONST FPI *fpi; int be; ULong *bits;
1227684d5e0Skleink int *kindp, mode, ndigits, *decpt; char **rve;
1237684d5e0Skleink #else
1249a9a4122Sriastradh (CONST FPI *fpi, int be, ULong *bits, int *kindp, int mode, int ndigits, int *decpt, char **rve)
1257684d5e0Skleink #endif
1267684d5e0Skleink {
1277684d5e0Skleink /* Arguments ndigits and decpt are similar to the second and third
1287684d5e0Skleink arguments of ecvt and fcvt; trailing zeros are suppressed from
1297684d5e0Skleink the returned string. If not null, *rve is set to point
1307684d5e0Skleink to the end of the return value. If d is +-Infinity or NaN,
131d3728fecSdholland then *decpt is set to -32768.
13261e56760Schristos be = exponent: value = (integer represented by bits) * (2 to the power of be).
1337684d5e0Skleink
1347684d5e0Skleink mode:
1357684d5e0Skleink 0 ==> shortest string that yields d when read in
1367684d5e0Skleink and rounded to nearest.
1377684d5e0Skleink 1 ==> like 0, but with Steele & White stopping rule;
1387684d5e0Skleink e.g. with IEEE P754 arithmetic , mode 0 gives
1397684d5e0Skleink 1e23 whereas mode 1 gives 9.999999999999999e22.
1407684d5e0Skleink 2 ==> max(1,ndigits) significant digits. This gives a
1417684d5e0Skleink return value similar to that of ecvt, except
1427684d5e0Skleink that trailing zeros are suppressed.
1437684d5e0Skleink 3 ==> through ndigits past the decimal point. This
1447684d5e0Skleink gives a return value similar to that from fcvt,
1457684d5e0Skleink except that trailing zeros are suppressed, and
1467684d5e0Skleink ndigits can be negative.
1477684d5e0Skleink 4-9 should give the same return values as 2-3, i.e.,
1487684d5e0Skleink 4 <= mode <= 9 ==> same return as mode
1497684d5e0Skleink 2 + (mode & 1). These modes are mainly for
1507684d5e0Skleink debugging; often they run slower but sometimes
1517684d5e0Skleink faster than modes 2-3.
1527684d5e0Skleink 4,5,8,9 ==> left-to-right digit generation.
1537684d5e0Skleink 6-9 ==> don't try fast floating-point estimate
1547684d5e0Skleink (if applicable).
1557684d5e0Skleink
1567684d5e0Skleink Values of mode other than 0-9 are treated as mode 0.
1577684d5e0Skleink
1587684d5e0Skleink Sufficient space is allocated to the return value
1597684d5e0Skleink to hold the suppressed trailing zeros.
1607684d5e0Skleink */
1617684d5e0Skleink
1621634560eSchristos int bbits, b2, b5, be0, dig, i, ieps, ilim = 0, ilim0, ilim1 = 0, inex;
1631634560eSchristos int j, jj1, k, k0, k_check, kind, leftright, m2, m5, nbits;
1647684d5e0Skleink int rdir, s2, s5, spec_case, try_quick;
1657684d5e0Skleink Long L;
1667684d5e0Skleink Bigint *b, *b1, *delta, *mlo, *mhi, *mhi1, *S;
16761e56760Schristos double d2, ds;
1687684d5e0Skleink char *s, *s0;
16961e56760Schristos U d, eps;
1707684d5e0Skleink
1717684d5e0Skleink #ifndef MULTIPLE_THREADS
1727684d5e0Skleink if (dtoa_result) {
1737684d5e0Skleink freedtoa(dtoa_result);
1747684d5e0Skleink dtoa_result = 0;
1757684d5e0Skleink }
1767684d5e0Skleink #endif
1777684d5e0Skleink inex = 0;
178ab625449Schristos if (*kindp & STRTOG_NoMemory)
179ab625449Schristos return NULL;
1807684d5e0Skleink kind = *kindp &= ~STRTOG_Inexact;
1817684d5e0Skleink switch(kind & STRTOG_Retmask) {
1827684d5e0Skleink case STRTOG_Zero:
1837684d5e0Skleink goto ret_zero;
1847684d5e0Skleink case STRTOG_Normal:
1857684d5e0Skleink case STRTOG_Denormal:
1867684d5e0Skleink break;
1877684d5e0Skleink case STRTOG_Infinite:
1887684d5e0Skleink *decpt = -32768;
1897684d5e0Skleink return nrv_alloc("Infinity", rve, 8);
1907684d5e0Skleink case STRTOG_NaN:
1917684d5e0Skleink *decpt = -32768;
1927684d5e0Skleink return nrv_alloc("NaN", rve, 3);
1937684d5e0Skleink default:
1947684d5e0Skleink return 0;
1957684d5e0Skleink }
1967684d5e0Skleink b = bitstob(bits, nbits = fpi->nbits, &bbits);
197ab625449Schristos if (b == NULL)
198ab625449Schristos return NULL;
1997684d5e0Skleink be0 = be;
2007684d5e0Skleink if ( (i = trailz(b)) !=0) {
2017684d5e0Skleink rshift(b, i);
2027684d5e0Skleink be += i;
2037684d5e0Skleink bbits -= i;
2047684d5e0Skleink }
2057684d5e0Skleink if (!b->wds) {
2067684d5e0Skleink Bfree(b);
2077684d5e0Skleink ret_zero:
2087684d5e0Skleink *decpt = 1;
2097684d5e0Skleink return nrv_alloc("0", rve, 1);
2107684d5e0Skleink }
2117684d5e0Skleink
21261e56760Schristos dval(&d) = b2d(b, &i);
2137684d5e0Skleink i = be + bbits - 1;
21461e56760Schristos word0(&d) &= Frac_mask1;
21561e56760Schristos word0(&d) |= Exp_11;
2167684d5e0Skleink #ifdef IBM
21761e56760Schristos if ( (j = 11 - hi0bits(word0(&d) & Frac_mask)) !=0)
21861e56760Schristos dval(&d) /= 1 << j;
2197684d5e0Skleink #endif
2207684d5e0Skleink
2217684d5e0Skleink /* log(x) ~=~ log(1.5) + (x-1.5)/1.5
2227684d5e0Skleink * log10(x) = log(x) / log(10)
2237684d5e0Skleink * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))
22461e56760Schristos * log10(&d) = (i-Bias)*log(2)/log(10) + log10(d2)
2257684d5e0Skleink *
22661e56760Schristos * This suggests computing an approximation k to log10(&d) by
2277684d5e0Skleink *
2287684d5e0Skleink * k = (i - Bias)*0.301029995663981
2297684d5e0Skleink * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
2307684d5e0Skleink *
2317684d5e0Skleink * We want k to be too large rather than too small.
2327684d5e0Skleink * The error in the first-order Taylor series approximation
2337684d5e0Skleink * is in our favor, so we just round up the constant enough
2347684d5e0Skleink * to compensate for any error in the multiplication of
2357684d5e0Skleink * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077,
2367684d5e0Skleink * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14,
2377684d5e0Skleink * adding 1e-13 to the constant term more than suffices.
2387684d5e0Skleink * Hence we adjust the constant term to 0.1760912590558.
2397684d5e0Skleink * (We could get a more accurate k by invoking log10,
2407684d5e0Skleink * but this is probably not worthwhile.)
2417684d5e0Skleink */
2427684d5e0Skleink #ifdef IBM
2437684d5e0Skleink i <<= 2;
2447684d5e0Skleink i += j;
2457684d5e0Skleink #endif
24661e56760Schristos ds = (dval(&d)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
2477684d5e0Skleink
2487684d5e0Skleink /* correct assumption about exponent range */
2497684d5e0Skleink if ((j = i) < 0)
2507684d5e0Skleink j = -j;
2517684d5e0Skleink if ((j -= 1077) > 0)
2527684d5e0Skleink ds += j * 7e-17;
2537684d5e0Skleink
2547684d5e0Skleink k = (int)ds;
2557684d5e0Skleink if (ds < 0. && ds != k)
2567684d5e0Skleink k--; /* want k = floor(ds) */
2577684d5e0Skleink k_check = 1;
2587684d5e0Skleink #ifdef IBM
2597684d5e0Skleink j = be + bbits - 1;
2601634560eSchristos if ( (jj1 = j & 3) !=0)
26161e56760Schristos dval(&d) *= 1 << jj1;
26261e56760Schristos word0(&d) += j << Exp_shift - 2 & Exp_mask;
2637684d5e0Skleink #else
26461e56760Schristos word0(&d) += (be + bbits - 1) << Exp_shift;
2657684d5e0Skleink #endif
2667684d5e0Skleink if (k >= 0 && k <= Ten_pmax) {
26761e56760Schristos if (dval(&d) < tens[k])
2687684d5e0Skleink k--;
2697684d5e0Skleink k_check = 0;
2707684d5e0Skleink }
2717684d5e0Skleink j = bbits - i - 1;
2727684d5e0Skleink if (j >= 0) {
2737684d5e0Skleink b2 = 0;
2747684d5e0Skleink s2 = j;
2757684d5e0Skleink }
2767684d5e0Skleink else {
2777684d5e0Skleink b2 = -j;
2787684d5e0Skleink s2 = 0;
2797684d5e0Skleink }
2807684d5e0Skleink if (k >= 0) {
2817684d5e0Skleink b5 = 0;
2827684d5e0Skleink s5 = k;
2837684d5e0Skleink s2 += k;
2847684d5e0Skleink }
2857684d5e0Skleink else {
2867684d5e0Skleink b2 -= k;
2877684d5e0Skleink b5 = -k;
2887684d5e0Skleink s5 = 0;
2897684d5e0Skleink }
2907684d5e0Skleink if (mode < 0 || mode > 9)
2917684d5e0Skleink mode = 0;
2927684d5e0Skleink try_quick = 1;
2937684d5e0Skleink if (mode > 5) {
2947684d5e0Skleink mode -= 4;
2957684d5e0Skleink try_quick = 0;
2967684d5e0Skleink }
29761e56760Schristos else if (i >= -4 - Emin || i < Emin)
29861e56760Schristos try_quick = 0;
2997684d5e0Skleink leftright = 1;
30061e56760Schristos ilim = ilim1 = -1; /* Values for cases 0 and 1; done here to */
30161e56760Schristos /* silence erroneous "gcc -Wall" warning. */
3027684d5e0Skleink switch(mode) {
3037684d5e0Skleink case 0:
3047684d5e0Skleink case 1:
3057684d5e0Skleink i = (int)(nbits * .30103) + 3;
3067684d5e0Skleink ndigits = 0;
3077684d5e0Skleink break;
3087684d5e0Skleink case 2:
3097684d5e0Skleink leftright = 0;
3101634560eSchristos /*FALLTHROUGH*/
3117684d5e0Skleink case 4:
3127684d5e0Skleink if (ndigits <= 0)
3137684d5e0Skleink ndigits = 1;
3147684d5e0Skleink ilim = ilim1 = i = ndigits;
3157684d5e0Skleink break;
3167684d5e0Skleink case 3:
3177684d5e0Skleink leftright = 0;
3181634560eSchristos /*FALLTHROUGH*/
3197684d5e0Skleink case 5:
3207684d5e0Skleink i = ndigits + k + 1;
3217684d5e0Skleink ilim = i;
3227684d5e0Skleink ilim1 = i - 1;
3237684d5e0Skleink if (i <= 0)
3247684d5e0Skleink i = 1;
3257684d5e0Skleink }
326c8e7c687Schristos s = s0 = rv_alloc((size_t)i);
327ab625449Schristos if (s == NULL)
328ab625449Schristos return NULL;
3297684d5e0Skleink
3307684d5e0Skleink if ( (rdir = fpi->rounding - 1) !=0) {
3317684d5e0Skleink if (rdir < 0)
3327684d5e0Skleink rdir = 2;
3337684d5e0Skleink if (kind & STRTOG_Neg)
3347684d5e0Skleink rdir = 3 - rdir;
3357684d5e0Skleink }
3367684d5e0Skleink
3377684d5e0Skleink /* Now rdir = 0 ==> round near, 1 ==> round up, 2 ==> round down. */
3387684d5e0Skleink
3397684d5e0Skleink if (ilim >= 0 && ilim <= Quick_max && try_quick && !rdir
3407684d5e0Skleink #ifndef IMPRECISE_INEXACT
3417684d5e0Skleink && k == 0
3427684d5e0Skleink #endif
3437684d5e0Skleink ) {
3447684d5e0Skleink
3457684d5e0Skleink /* Try to get by with floating-point arithmetic. */
3467684d5e0Skleink
3477684d5e0Skleink i = 0;
34861e56760Schristos d2 = dval(&d);
3497684d5e0Skleink #ifdef IBM
35061e56760Schristos if ( (j = 11 - hi0bits(word0(&d) & Frac_mask)) !=0)
35161e56760Schristos dval(&d) /= 1 << j;
3527684d5e0Skleink #endif
3537684d5e0Skleink k0 = k;
3547684d5e0Skleink ilim0 = ilim;
3557684d5e0Skleink ieps = 2; /* conservative */
3567684d5e0Skleink if (k > 0) {
3577684d5e0Skleink ds = tens[k&0xf];
3581634560eSchristos j = (unsigned int)k >> 4;
3597684d5e0Skleink if (j & Bletch) {
3607684d5e0Skleink /* prevent overflows */
3617684d5e0Skleink j &= Bletch - 1;
36261e56760Schristos dval(&d) /= bigtens[n_bigtens-1];
3637684d5e0Skleink ieps++;
3647684d5e0Skleink }
3651634560eSchristos for(; j; j /= 2, i++)
3667684d5e0Skleink if (j & 1) {
3677684d5e0Skleink ieps++;
3687684d5e0Skleink ds *= bigtens[i];
3697684d5e0Skleink }
3707684d5e0Skleink }
3717684d5e0Skleink else {
3727684d5e0Skleink ds = 1.;
3731634560eSchristos if ( (jj1 = -k) !=0) {
37461e56760Schristos dval(&d) *= tens[jj1 & 0xf];
375*ace5b9b5Schristos for(j = (unsigned int)jj1 >> 4; j; j = (unsigned int)j >> 1, i++)
3767684d5e0Skleink if (j & 1) {
3777684d5e0Skleink ieps++;
37861e56760Schristos dval(&d) *= bigtens[i];
3797684d5e0Skleink }
3807684d5e0Skleink }
3817684d5e0Skleink }
38261e56760Schristos if (k_check && dval(&d) < 1. && ilim > 0) {
3837684d5e0Skleink if (ilim1 <= 0)
3847684d5e0Skleink goto fast_failed;
3857684d5e0Skleink ilim = ilim1;
3867684d5e0Skleink k--;
38761e56760Schristos dval(&d) *= 10.;
3887684d5e0Skleink ieps++;
3897684d5e0Skleink }
39061e56760Schristos dval(&eps) = ieps*dval(&d) + 7.;
39161e56760Schristos word0(&eps) -= (P-1)*Exp_msk1;
3927684d5e0Skleink if (ilim == 0) {
3937684d5e0Skleink S = mhi = 0;
39461e56760Schristos dval(&d) -= 5.;
39561e56760Schristos if (dval(&d) > dval(&eps))
3967684d5e0Skleink goto one_digit;
39761e56760Schristos if (dval(&d) < -dval(&eps))
3987684d5e0Skleink goto no_digits;
3997684d5e0Skleink goto fast_failed;
4007684d5e0Skleink }
4017684d5e0Skleink #ifndef No_leftright
4027684d5e0Skleink if (leftright) {
4037684d5e0Skleink /* Use Steele & White method of only
4047684d5e0Skleink * generating digits needed.
4057684d5e0Skleink */
40661e56760Schristos dval(&eps) = ds*0.5/tens[ilim-1] - dval(&eps);
4077684d5e0Skleink for(i = 0;;) {
40861e56760Schristos L = (Long)(dval(&d)/ds);
40961e56760Schristos dval(&d) -= L*ds;
4107684d5e0Skleink *s++ = '0' + (int)L;
41161e56760Schristos if (dval(&d) < dval(&eps)) {
41261e56760Schristos if (dval(&d))
4137684d5e0Skleink inex = STRTOG_Inexlo;
4147684d5e0Skleink goto ret1;
4157684d5e0Skleink }
41661e56760Schristos if (ds - dval(&d) < dval(&eps))
4177684d5e0Skleink goto bump_up;
4187684d5e0Skleink if (++i >= ilim)
4197684d5e0Skleink break;
42061e56760Schristos dval(&eps) *= 10.;
42161e56760Schristos dval(&d) *= 10.;
4227684d5e0Skleink }
4237684d5e0Skleink }
4247684d5e0Skleink else {
4257684d5e0Skleink #endif
4267684d5e0Skleink /* Generate ilim digits, then fix them up. */
42761e56760Schristos dval(&eps) *= tens[ilim-1];
42861e56760Schristos for(i = 1;; i++, dval(&d) *= 10.) {
42961e56760Schristos if ( (L = (Long)(dval(&d)/ds)) !=0)
43061e56760Schristos dval(&d) -= L*ds;
4317684d5e0Skleink *s++ = '0' + (int)L;
4327684d5e0Skleink if (i == ilim) {
4337684d5e0Skleink ds *= 0.5;
43461e56760Schristos if (dval(&d) > ds + dval(&eps))
4357684d5e0Skleink goto bump_up;
43661e56760Schristos else if (dval(&d) < ds - dval(&eps)) {
43761e56760Schristos if (dval(&d))
4387684d5e0Skleink inex = STRTOG_Inexlo;
43961e56760Schristos goto clear_trailing0;
4407684d5e0Skleink }
4417684d5e0Skleink break;
4427684d5e0Skleink }
4437684d5e0Skleink }
4447684d5e0Skleink #ifndef No_leftright
4457684d5e0Skleink }
4467684d5e0Skleink #endif
4477684d5e0Skleink fast_failed:
4487684d5e0Skleink s = s0;
44961e56760Schristos dval(&d) = d2;
4507684d5e0Skleink k = k0;
4517684d5e0Skleink ilim = ilim0;
4527684d5e0Skleink }
4537684d5e0Skleink
4547684d5e0Skleink /* Do we have a "small" integer? */
4557684d5e0Skleink
4567684d5e0Skleink if (be >= 0 && k <= Int_max) {
4577684d5e0Skleink /* Yes. */
4587684d5e0Skleink ds = tens[k];
4597684d5e0Skleink if (ndigits < 0 && ilim <= 0) {
4607684d5e0Skleink S = mhi = 0;
46161e56760Schristos if (ilim < 0 || dval(&d) <= 5*ds)
4627684d5e0Skleink goto no_digits;
4637684d5e0Skleink goto one_digit;
4647684d5e0Skleink }
46561e56760Schristos for(i = 1;; i++, dval(&d) *= 10.) {
46661e56760Schristos L = dval(&d) / ds;
46761e56760Schristos dval(&d) -= L*ds;
4687684d5e0Skleink #ifdef Check_FLT_ROUNDS
4697684d5e0Skleink /* If FLT_ROUNDS == 2, L will usually be high by 1 */
47061e56760Schristos if (dval(&d) < 0) {
4717684d5e0Skleink L--;
47261e56760Schristos dval(&d) += ds;
4737684d5e0Skleink }
4747684d5e0Skleink #endif
4757684d5e0Skleink *s++ = '0' + (int)L;
47661e56760Schristos if (dval(&d) == 0.)
4777684d5e0Skleink break;
4787684d5e0Skleink if (i == ilim) {
4797684d5e0Skleink if (rdir) {
4807684d5e0Skleink if (rdir == 1)
4817684d5e0Skleink goto bump_up;
4827684d5e0Skleink inex = STRTOG_Inexlo;
4837684d5e0Skleink goto ret1;
4847684d5e0Skleink }
48561e56760Schristos dval(&d) += dval(&d);
48661e56760Schristos #ifdef ROUND_BIASED
48761e56760Schristos if (dval(&d) >= ds)
48861e56760Schristos #else
48961e56760Schristos if (dval(&d) > ds || (dval(&d) == ds && L & 1))
49061e56760Schristos #endif
49161e56760Schristos {
4927684d5e0Skleink bump_up:
4937684d5e0Skleink inex = STRTOG_Inexhi;
4947684d5e0Skleink while(*--s == '9')
4957684d5e0Skleink if (s == s0) {
4967684d5e0Skleink k++;
4977684d5e0Skleink *s = '0';
4987684d5e0Skleink break;
4997684d5e0Skleink }
5007684d5e0Skleink ++*s++;
5017684d5e0Skleink }
50261e56760Schristos else {
5037684d5e0Skleink inex = STRTOG_Inexlo;
50461e56760Schristos clear_trailing0:
50561e56760Schristos while(*--s == '0'){}
50661e56760Schristos ++s;
50761e56760Schristos }
5087684d5e0Skleink break;
5097684d5e0Skleink }
5107684d5e0Skleink }
5117684d5e0Skleink goto ret1;
5127684d5e0Skleink }
5137684d5e0Skleink
5147684d5e0Skleink m2 = b2;
5157684d5e0Skleink m5 = b5;
5167684d5e0Skleink mhi = mlo = 0;
5177684d5e0Skleink if (leftright) {
5187684d5e0Skleink i = nbits - bbits;
51961e56760Schristos if (be - i++ < fpi->emin && mode != 3 && mode != 5) {
5207684d5e0Skleink /* denormal */
5217684d5e0Skleink i = be - fpi->emin + 1;
52261e56760Schristos if (mode >= 2 && ilim > 0 && ilim < i)
52361e56760Schristos goto small_ilim;
5247684d5e0Skleink }
52561e56760Schristos else if (mode >= 2) {
52661e56760Schristos small_ilim:
5277684d5e0Skleink j = ilim - 1;
5287684d5e0Skleink if (m5 >= j)
5297684d5e0Skleink m5 -= j;
5307684d5e0Skleink else {
5317684d5e0Skleink s5 += j -= m5;
5327684d5e0Skleink b5 += j;
5337684d5e0Skleink m5 = 0;
5347684d5e0Skleink }
5357684d5e0Skleink if ((i = ilim) < 0) {
5367684d5e0Skleink m2 -= i;
5377684d5e0Skleink i = 0;
5387684d5e0Skleink }
5397684d5e0Skleink }
5407684d5e0Skleink b2 += i;
5417684d5e0Skleink s2 += i;
5427684d5e0Skleink mhi = i2b(1);
5437684d5e0Skleink }
5447684d5e0Skleink if (m2 > 0 && s2 > 0) {
5457684d5e0Skleink i = m2 < s2 ? m2 : s2;
5467684d5e0Skleink b2 -= i;
5477684d5e0Skleink m2 -= i;
5487684d5e0Skleink s2 -= i;
5497684d5e0Skleink }
5507684d5e0Skleink if (b5 > 0) {
5517684d5e0Skleink if (leftright) {
5527684d5e0Skleink if (m5 > 0) {
5537684d5e0Skleink mhi = pow5mult(mhi, m5);
554ab625449Schristos if (mhi == NULL)
555ab625449Schristos return NULL;
5567684d5e0Skleink b1 = mult(mhi, b);
557ab625449Schristos if (b1 == NULL)
558ab625449Schristos return NULL;
5597684d5e0Skleink Bfree(b);
5607684d5e0Skleink b = b1;
5617684d5e0Skleink }
562ab625449Schristos if ( (j = b5 - m5) !=0) {
5637684d5e0Skleink b = pow5mult(b, j);
564ab625449Schristos if (b == NULL)
565ab625449Schristos return NULL;
5667684d5e0Skleink }
567ab625449Schristos }
568ab625449Schristos else {
5697684d5e0Skleink b = pow5mult(b, b5);
570ab625449Schristos if (b == NULL)
571ab625449Schristos return NULL;
572ab625449Schristos }
5737684d5e0Skleink }
5747684d5e0Skleink S = i2b(1);
575ab625449Schristos if (S == NULL)
576ab625449Schristos return NULL;
577ab625449Schristos if (s5 > 0) {
5787684d5e0Skleink S = pow5mult(S, s5);
579ab625449Schristos if (S == NULL)
580ab625449Schristos return NULL;
581ab625449Schristos }
5827684d5e0Skleink
5837684d5e0Skleink /* Check for special case that d is a normalized power of 2. */
5847684d5e0Skleink
5857684d5e0Skleink spec_case = 0;
5867684d5e0Skleink if (mode < 2) {
5877684d5e0Skleink if (bbits == 1 && be0 > fpi->emin + 1) {
5887684d5e0Skleink /* The special case */
5897684d5e0Skleink b2++;
5907684d5e0Skleink s2++;
5917684d5e0Skleink spec_case = 1;
5927684d5e0Skleink }
5937684d5e0Skleink }
5947684d5e0Skleink
5957684d5e0Skleink /* Arrange for convenient computation of quotients:
5967684d5e0Skleink * shift left if necessary so divisor has 4 leading 0 bits.
5977684d5e0Skleink *
5987684d5e0Skleink * Perhaps we should just compute leading 28 bits of S once
5997684d5e0Skleink * and for all and pass them and a shift to quorem, so it
6007684d5e0Skleink * can do shifts and ors to compute the numerator for q.
6017684d5e0Skleink */
60261e56760Schristos i = ((s5 ? hi0bits(S->x[S->wds-1]) : ULbits - 1) - s2 - 4) & kmask;
6037684d5e0Skleink m2 += i;
6049feb722eSchristos if ((b2 += i) > 0) {
6057684d5e0Skleink b = lshift(b, b2);
6069feb722eSchristos if (b == NULL)
6079feb722eSchristos return NULL;
6089feb722eSchristos }
6099feb722eSchristos if ((s2 += i) > 0) {
6107684d5e0Skleink S = lshift(S, s2);
6119feb722eSchristos if (S == NULL)
6129feb722eSchristos return NULL;
6139feb722eSchristos }
6147684d5e0Skleink if (k_check) {
6157684d5e0Skleink if (cmp(b,S) < 0) {
6167684d5e0Skleink k--;
6177684d5e0Skleink b = multadd(b, 10, 0); /* we botched the k estimate */
618ab625449Schristos if (b == NULL)
619ab625449Schristos return NULL;
620ab625449Schristos if (leftright) {
6217684d5e0Skleink mhi = multadd(mhi, 10, 0);
622ab625449Schristos if (mhi == NULL)
623ab625449Schristos return NULL;
624ab625449Schristos }
6257684d5e0Skleink ilim = ilim1;
6267684d5e0Skleink }
6277684d5e0Skleink }
6287684d5e0Skleink if (ilim <= 0 && mode > 2) {
6297684d5e0Skleink if (ilim < 0 || cmp(b,S = multadd(S,5,0)) <= 0) {
6307684d5e0Skleink /* no digits, fcvt style */
6317684d5e0Skleink no_digits:
6327684d5e0Skleink k = -1 - ndigits;
6337684d5e0Skleink inex = STRTOG_Inexlo;
6347684d5e0Skleink goto ret;
6357684d5e0Skleink }
6367684d5e0Skleink one_digit:
6377684d5e0Skleink inex = STRTOG_Inexhi;
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, 1);
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;
6731634560eSchristos jj1 = delta->sign ? 1 : cmp(b, delta);
6747684d5e0Skleink Bfree(delta);
6757684d5e0Skleink #ifndef ROUND_BIASED
6761634560eSchristos if (jj1 == 0 && !mode && !(bits[0] & 1) && !rdir) {
6777684d5e0Skleink if (dig == '9')
6787684d5e0Skleink goto round_9_up;
6797684d5e0Skleink if (j <= 0) {
6807684d5e0Skleink if (b->wds > 1 || b->x[0])
6817684d5e0Skleink inex = STRTOG_Inexlo;
6827684d5e0Skleink }
6837684d5e0Skleink else {
6847684d5e0Skleink dig++;
6857684d5e0Skleink inex = STRTOG_Inexhi;
6867684d5e0Skleink }
6877684d5e0Skleink *s++ = dig;
6887684d5e0Skleink goto ret;
6897684d5e0Skleink }
6907684d5e0Skleink #endif
6911634560eSchristos if (j < 0 || (j == 0 && !mode
6927684d5e0Skleink #ifndef ROUND_BIASED
6937684d5e0Skleink && !(bits[0] & 1)
6947684d5e0Skleink #endif
6951634560eSchristos )) {
6967684d5e0Skleink if (rdir && (b->wds > 1 || b->x[0])) {
6977684d5e0Skleink if (rdir == 2) {
6987684d5e0Skleink inex = STRTOG_Inexlo;
6997684d5e0Skleink goto accept;
7007684d5e0Skleink }
7017684d5e0Skleink while (cmp(S,mhi) > 0) {
7027684d5e0Skleink *s++ = dig;
7037684d5e0Skleink mhi1 = multadd(mhi, 10, 0);
704ab625449Schristos if (mhi1 == NULL)
705ab625449Schristos return NULL;
7067684d5e0Skleink if (mlo == mhi)
7077684d5e0Skleink mlo = mhi1;
7087684d5e0Skleink mhi = mhi1;
7097684d5e0Skleink b = multadd(b, 10, 0);
710ab625449Schristos if (b == NULL)
711ab625449Schristos return NULL;
7127684d5e0Skleink dig = quorem(b,S) + '0';
7137684d5e0Skleink }
7147684d5e0Skleink if (dig++ == '9')
7157684d5e0Skleink goto round_9_up;
7167684d5e0Skleink inex = STRTOG_Inexhi;
7177684d5e0Skleink goto accept;
7187684d5e0Skleink }
7191634560eSchristos if (jj1 > 0) {
7207684d5e0Skleink b = lshift(b, 1);
721ab625449Schristos if (b == NULL)
722ab625449Schristos return NULL;
7231634560eSchristos jj1 = cmp(b, S);
72461e56760Schristos #ifdef ROUND_BIASED
72561e56760Schristos if (jj1 >= 0 /*)*/
72661e56760Schristos #else
7271634560eSchristos if ((jj1 > 0 || (jj1 == 0 && dig & 1))
72861e56760Schristos #endif
7297684d5e0Skleink && dig++ == '9')
7307684d5e0Skleink goto round_9_up;
7317684d5e0Skleink inex = STRTOG_Inexhi;
7327684d5e0Skleink }
7337684d5e0Skleink if (b->wds > 1 || b->x[0])
7347684d5e0Skleink inex = STRTOG_Inexlo;
7357684d5e0Skleink accept:
7367684d5e0Skleink *s++ = dig;
7377684d5e0Skleink goto ret;
7387684d5e0Skleink }
7391634560eSchristos if (jj1 > 0 && rdir != 2) {
7407684d5e0Skleink if (dig == '9') { /* possible if i == 1 */
7417684d5e0Skleink round_9_up:
7427684d5e0Skleink *s++ = '9';
7437684d5e0Skleink inex = STRTOG_Inexhi;
7447684d5e0Skleink goto roundoff;
7457684d5e0Skleink }
7467684d5e0Skleink inex = STRTOG_Inexhi;
7477684d5e0Skleink *s++ = dig + 1;
7487684d5e0Skleink goto ret;
7497684d5e0Skleink }
7507684d5e0Skleink *s++ = dig;
7517684d5e0Skleink if (i == ilim)
7527684d5e0Skleink break;
7537684d5e0Skleink b = multadd(b, 10, 0);
754ab625449Schristos if (b == NULL)
755ab625449Schristos return NULL;
756ab625449Schristos if (mlo == mhi) {
7577684d5e0Skleink mlo = mhi = multadd(mhi, 10, 0);
758ab625449Schristos if (mlo == NULL)
759ab625449Schristos return NULL;
760ab625449Schristos }
7617684d5e0Skleink else {
7627684d5e0Skleink mlo = multadd(mlo, 10, 0);
763ab625449Schristos if (mlo == NULL)
764ab625449Schristos return NULL;
7657684d5e0Skleink mhi = multadd(mhi, 10, 0);
766ab625449Schristos if (mhi == NULL)
767ab625449Schristos return NULL;
7687684d5e0Skleink }
7697684d5e0Skleink }
7707684d5e0Skleink }
7717684d5e0Skleink else
7727684d5e0Skleink for(i = 1;; i++) {
7737684d5e0Skleink *s++ = dig = quorem(b,S) + '0';
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 if (rdir) {
7841634560eSchristos if (rdir == 2 || (b->wds <= 1 && !b->x[0]))
7857684d5e0Skleink goto chopzeros;
7867684d5e0Skleink goto roundoff;
7877684d5e0Skleink }
7887684d5e0Skleink b = lshift(b, 1);
789ab625449Schristos if (b == NULL)
790ab625449Schristos return NULL;
7917684d5e0Skleink j = cmp(b, S);
79261e56760Schristos #ifdef ROUND_BIASED
79361e56760Schristos if (j >= 0)
79461e56760Schristos #else
79561e56760Schristos if (j > 0 || (j == 0 && dig & 1))
79661e56760Schristos #endif
79761e56760Schristos {
7987684d5e0Skleink roundoff:
7997684d5e0Skleink inex = STRTOG_Inexhi;
8007684d5e0Skleink while(*--s == '9')
8017684d5e0Skleink if (s == s0) {
8027684d5e0Skleink k++;
8037684d5e0Skleink *s++ = '1';
8047684d5e0Skleink goto ret;
8057684d5e0Skleink }
8067684d5e0Skleink ++*s++;
8077684d5e0Skleink }
8087684d5e0Skleink else {
8097684d5e0Skleink chopzeros:
8107684d5e0Skleink if (b->wds > 1 || b->x[0])
8117684d5e0Skleink inex = STRTOG_Inexlo;
8127684d5e0Skleink while(*--s == '0'){}
81361e56760Schristos ++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 Bfree(b);
8247684d5e0Skleink *s = 0;
8257684d5e0Skleink *decpt = k + 1;
8267684d5e0Skleink if (rve)
8277684d5e0Skleink *rve = s;
8287684d5e0Skleink *kindp |= inex;
8297684d5e0Skleink return s0;
8307684d5e0Skleink }
831