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