xref: /netbsd-src/lib/libc/gdtoa/dtoa.c (revision ace5b9b5feb0e7608bd2da7a617428d2e1cf8aa3)
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