xref: /plan9-contrib/sys/src/ape/lib/ap/stdio/_dtoa.c (revision 22df390c30710ddd2119f3e7bb6c92dc399cabb9)
13e12c5d1SDavid du Colombier #include "fconv.h"
23e12c5d1SDavid du Colombier 
33e12c5d1SDavid du Colombier static int quorem(Bigint *, Bigint *);
43e12c5d1SDavid du Colombier 
53e12c5d1SDavid du Colombier /* dtoa for IEEE arithmetic (dmg): convert double to ASCII string.
63e12c5d1SDavid du Colombier  *
73e12c5d1SDavid du Colombier  * Inspired by "How to Print Floating-Point Numbers Accurately" by
83e12c5d1SDavid du Colombier  * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 92-101].
93e12c5d1SDavid du Colombier  *
103e12c5d1SDavid du Colombier  * Modifications:
113e12c5d1SDavid du Colombier  *	1. Rather than iterating, we use a simple numeric overestimate
123e12c5d1SDavid du Colombier  *	   to determine k = floor(log10(d)).  We scale relevant
133e12c5d1SDavid du Colombier  *	   quantities using O(log2(k)) rather than O(k) multiplications.
143e12c5d1SDavid du Colombier  *	2. For some modes > 2 (corresponding to ecvt and fcvt), we don't
153e12c5d1SDavid du Colombier  *	   try to generate digits strictly left to right.  Instead, we
163e12c5d1SDavid du Colombier  *	   compute with fewer bits and propagate the carry if necessary
173e12c5d1SDavid du Colombier  *	   when rounding the final digit up.  This is often faster.
183e12c5d1SDavid du Colombier  *	3. Under the assumption that input will be rounded nearest,
193e12c5d1SDavid du Colombier  *	   mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22.
203e12c5d1SDavid du Colombier  *	   That is, we allow equality in stopping tests when the
213e12c5d1SDavid du Colombier  *	   round-nearest rule will give the same floating-point value
223e12c5d1SDavid du Colombier  *	   as would satisfaction of the stopping test with strict
233e12c5d1SDavid du Colombier  *	   inequality.
243e12c5d1SDavid du Colombier  *	4. We remove common factors of powers of 2 from relevant
253e12c5d1SDavid du Colombier  *	   quantities.
263e12c5d1SDavid du Colombier  *	5. When converting floating-point integers less than 1e16,
273e12c5d1SDavid du Colombier  *	   we use floating-point arithmetic rather than resorting
283e12c5d1SDavid du Colombier  *	   to multiple-precision integers.
293e12c5d1SDavid du Colombier  *	6. When asked to produce fewer than 15 digits, we first try
303e12c5d1SDavid du Colombier  *	   to get by with floating-point arithmetic; we resort to
313e12c5d1SDavid du Colombier  *	   multiple-precision integer arithmetic only if we cannot
323e12c5d1SDavid du Colombier  *	   guarantee that the floating-point calculation has given
333e12c5d1SDavid du Colombier  *	   the correctly rounded result.  For k requested digits and
343e12c5d1SDavid du Colombier  *	   "uniformly" distributed input, the probability is
353e12c5d1SDavid du Colombier  *	   something like 10^(k-15) that we must resort to the long
363e12c5d1SDavid du Colombier  *	   calculation.
373e12c5d1SDavid du Colombier  */
383e12c5d1SDavid du Colombier 
393e12c5d1SDavid du Colombier  char *
_dtoa(double darg,int mode,int ndigits,int * decpt,int * sign,char ** rve)403e12c5d1SDavid du Colombier _dtoa(double darg, int mode, int ndigits, int *decpt, int *sign, char **rve)
413e12c5d1SDavid du Colombier {
423e12c5d1SDavid du Colombier  /*	Arguments ndigits, decpt, sign are similar to those
433e12c5d1SDavid du Colombier 	of ecvt and fcvt; trailing zeros are suppressed from
443e12c5d1SDavid du Colombier 	the returned string.  If not null, *rve is set to point
453e12c5d1SDavid du Colombier 	to the end of the return value.  If d is +-Infinity or NaN,
463e12c5d1SDavid du Colombier 	then *decpt is set to 9999.
473e12c5d1SDavid du Colombier 
483e12c5d1SDavid du Colombier 	mode:
493e12c5d1SDavid du Colombier 		0 ==> shortest string that yields d when read in
503e12c5d1SDavid du Colombier 			and rounded to nearest.
513e12c5d1SDavid du Colombier 		1 ==> like 0, but with Steele & White stopping rule;
523e12c5d1SDavid du Colombier 			e.g. with IEEE P754 arithmetic , mode 0 gives
533e12c5d1SDavid du Colombier 			1e23 whereas mode 1 gives 9.999999999999999e22.
543e12c5d1SDavid du Colombier 		2 ==> max(1,ndigits) significant digits.  This gives a
553e12c5d1SDavid du Colombier 			return value similar to that of ecvt, except
563e12c5d1SDavid du Colombier 			that trailing zeros are suppressed.
573e12c5d1SDavid du Colombier 		3 ==> through ndigits past the decimal point.  This
583e12c5d1SDavid du Colombier 			gives a return value similar to that from fcvt,
593e12c5d1SDavid du Colombier 			except that trailing zeros are suppressed, and
603e12c5d1SDavid du Colombier 			ndigits can be negative.
613e12c5d1SDavid du Colombier 		4-9 should give the same return values as 2-3, i.e.,
623e12c5d1SDavid du Colombier 			4 <= mode <= 9 ==> same return as mode
633e12c5d1SDavid du Colombier 			2 + (mode & 1).  These modes are mainly for
643e12c5d1SDavid du Colombier 			debugging; often they run slower but sometimes
653e12c5d1SDavid du Colombier 			faster than modes 2-3.
663e12c5d1SDavid du Colombier 		4,5,8,9 ==> left-to-right digit generation.
673e12c5d1SDavid du Colombier 		6-9 ==> don't try fast floating-point estimate
683e12c5d1SDavid du Colombier 			(if applicable).
693e12c5d1SDavid du Colombier 
703e12c5d1SDavid du Colombier 		Values of mode other than 0-9 are treated as mode 0.
713e12c5d1SDavid du Colombier 
723e12c5d1SDavid du Colombier 		Sufficient space is allocated to the return value
733e12c5d1SDavid du Colombier 		to hold the suppressed trailing zeros.
743e12c5d1SDavid du Colombier 	*/
753e12c5d1SDavid du Colombier 
763e12c5d1SDavid du Colombier 	int bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1,
773e12c5d1SDavid du Colombier 		j, j1, k, k0, k_check, leftright, m2, m5, s2, s5,
783e12c5d1SDavid du Colombier 		spec_case, try_quick;
793e12c5d1SDavid du Colombier 	long L;
803e12c5d1SDavid du Colombier #ifndef Sudden_Underflow
813e12c5d1SDavid du Colombier 	int denorm;
823e12c5d1SDavid du Colombier 	unsigned long x;
833e12c5d1SDavid du Colombier #endif
843e12c5d1SDavid du Colombier 	Bigint *b, *b1, *delta, *mlo, *mhi, *S;
853e12c5d1SDavid du Colombier 	double ds;
863e12c5d1SDavid du Colombier 	Dul d2, eps;
873e12c5d1SDavid du Colombier 	char *s, *s0;
883e12c5d1SDavid du Colombier 	static Bigint *result;
893e12c5d1SDavid du Colombier 	static int result_k;
903e12c5d1SDavid du Colombier 	Dul d;
913e12c5d1SDavid du Colombier 
92*22df390cSDavid du Colombier 	mlo = 0;
933e12c5d1SDavid du Colombier 	d.d = darg;
943e12c5d1SDavid du Colombier 	if (result) {
953e12c5d1SDavid du Colombier 		result->k = result_k;
963e12c5d1SDavid du Colombier 		result->maxwds = 1 << result_k;
973e12c5d1SDavid du Colombier 		Bfree(result);
983e12c5d1SDavid du Colombier 		result = 0;
993e12c5d1SDavid du Colombier 		}
1003e12c5d1SDavid du Colombier 
1013e12c5d1SDavid du Colombier 	if (word0(d) & Sign_bit) {
1023e12c5d1SDavid du Colombier 		/* set sign for everything, including 0's and NaNs */
1033e12c5d1SDavid du Colombier 		*sign = 1;
1043e12c5d1SDavid du Colombier 		word0(d) &= ~Sign_bit;	/* clear sign bit */
1053e12c5d1SDavid du Colombier 		}
1063e12c5d1SDavid du Colombier 	else
1073e12c5d1SDavid du Colombier 		*sign = 0;
1083e12c5d1SDavid du Colombier 
1093e12c5d1SDavid du Colombier #if defined(IEEE_Arith) + defined(VAX)
1103e12c5d1SDavid du Colombier #ifdef IEEE_Arith
1113e12c5d1SDavid du Colombier 	if ((word0(d) & Exp_mask) == Exp_mask)
1123e12c5d1SDavid du Colombier #else
1133e12c5d1SDavid du Colombier 	if (word0(d)  == 0x8000)
1143e12c5d1SDavid du Colombier #endif
1153e12c5d1SDavid du Colombier 		{
1163e12c5d1SDavid du Colombier 		/* Infinity or NaN */
1173e12c5d1SDavid du Colombier 		*decpt = 9999;
1183e12c5d1SDavid du Colombier 		s =
1193e12c5d1SDavid du Colombier #ifdef IEEE_Arith
1203e12c5d1SDavid du Colombier 			!word1(d) && !(word0(d) & 0xfffff) ? "Infinity" :
1213e12c5d1SDavid du Colombier #endif
1223e12c5d1SDavid du Colombier 				"NaN";
1233e12c5d1SDavid du Colombier 		if (rve)
1243e12c5d1SDavid du Colombier 			*rve =
1253e12c5d1SDavid du Colombier #ifdef IEEE_Arith
1263e12c5d1SDavid du Colombier 				s[3] ? s + 8 :
1273e12c5d1SDavid du Colombier #endif
1283e12c5d1SDavid du Colombier 						s + 3;
1293e12c5d1SDavid du Colombier 		return s;
1303e12c5d1SDavid du Colombier 		}
1313e12c5d1SDavid du Colombier #endif
1323e12c5d1SDavid du Colombier #ifdef IBM
1333e12c5d1SDavid du Colombier 	d.d += 0; /* normalize */
1343e12c5d1SDavid du Colombier #endif
1353e12c5d1SDavid du Colombier 	if (!d.d) {
1363e12c5d1SDavid du Colombier 		*decpt = 1;
1373e12c5d1SDavid du Colombier 		s = "0";
1383e12c5d1SDavid du Colombier 		if (rve)
1393e12c5d1SDavid du Colombier 			*rve = s + 1;
1403e12c5d1SDavid du Colombier 		return s;
1413e12c5d1SDavid du Colombier 		}
1423e12c5d1SDavid du Colombier 
1433e12c5d1SDavid du Colombier 	b = d2b(d.d, &be, &bbits);
1443e12c5d1SDavid du Colombier #ifdef Sudden_Underflow
1453e12c5d1SDavid du Colombier 	i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1));
1463e12c5d1SDavid du Colombier #else
1473e12c5d1SDavid du Colombier 	if (i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1))) {
1483e12c5d1SDavid du Colombier #endif
1493e12c5d1SDavid du Colombier 		d2.d = d.d;
1503e12c5d1SDavid du Colombier 		word0(d2) &= Frac_mask1;
1513e12c5d1SDavid du Colombier 		word0(d2) |= Exp_11;
1523e12c5d1SDavid du Colombier #ifdef IBM
1533e12c5d1SDavid du Colombier 		if (j = 11 - hi0bits(word0(d2) & Frac_mask))
1543e12c5d1SDavid du Colombier 			d2.d /= 1 << j;
1553e12c5d1SDavid du Colombier #endif
1563e12c5d1SDavid du Colombier 
1573e12c5d1SDavid du Colombier 		/* log(x)	~=~ log(1.5) + (x-1.5)/1.5
1583e12c5d1SDavid du Colombier 		 * log10(x)	 =  log(x) / log(10)
1593e12c5d1SDavid du Colombier 		 *		~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))
1603e12c5d1SDavid du Colombier 		 * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2)
1613e12c5d1SDavid du Colombier 		 *
1623e12c5d1SDavid du Colombier 		 * This suggests computing an approximation k to log10(d) by
1633e12c5d1SDavid du Colombier 		 *
1643e12c5d1SDavid du Colombier 		 * k = (i - Bias)*0.301029995663981
1653e12c5d1SDavid du Colombier 		 *	+ ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
1663e12c5d1SDavid du Colombier 		 *
1673e12c5d1SDavid du Colombier 		 * We want k to be too large rather than too small.
1683e12c5d1SDavid du Colombier 		 * The error in the first-order Taylor series approximation
1693e12c5d1SDavid du Colombier 		 * is in our favor, so we just round up the constant enough
1703e12c5d1SDavid du Colombier 		 * to compensate for any error in the multiplication of
1713e12c5d1SDavid du Colombier 		 * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077,
1723e12c5d1SDavid du Colombier 		 * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14,
1733e12c5d1SDavid du Colombier 		 * adding 1e-13 to the constant term more than suffices.
1743e12c5d1SDavid du Colombier 		 * Hence we adjust the constant term to 0.1760912590558.
1753e12c5d1SDavid du Colombier 		 * (We could get a more accurate k by invoking log10,
1763e12c5d1SDavid du Colombier 		 *  but this is probably not worthwhile.)
1773e12c5d1SDavid du Colombier 		 */
1783e12c5d1SDavid du Colombier 
1793e12c5d1SDavid du Colombier 		i -= Bias;
1803e12c5d1SDavid du Colombier #ifdef IBM
1813e12c5d1SDavid du Colombier 		i <<= 2;
1823e12c5d1SDavid du Colombier 		i += j;
1833e12c5d1SDavid du Colombier #endif
1843e12c5d1SDavid du Colombier #ifndef Sudden_Underflow
1853e12c5d1SDavid du Colombier 		denorm = 0;
1863e12c5d1SDavid du Colombier 		}
1873e12c5d1SDavid du Colombier 	else {
1883e12c5d1SDavid du Colombier 		/* d is denormalized */
1893e12c5d1SDavid du Colombier 
1903e12c5d1SDavid du Colombier 		i = bbits + be + (Bias + (P-1) - 1);
1913e12c5d1SDavid du Colombier 		x = i > 32  ? word0(d) << 64 - i | word1(d) >> i - 32
1923e12c5d1SDavid du Colombier 			    : word1(d) << 32 - i;
1933e12c5d1SDavid du Colombier 		d2.d = x;
1943e12c5d1SDavid du Colombier 		word0(d2) -= 31*Exp_msk1; /* adjust exponent */
1953e12c5d1SDavid du Colombier 		i -= (Bias + (P-1) - 1) + 1;
1963e12c5d1SDavid du Colombier 		denorm = 1;
1973e12c5d1SDavid du Colombier 		}
1983e12c5d1SDavid du Colombier #endif
1993e12c5d1SDavid du Colombier 	ds = (d2.d-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
2003e12c5d1SDavid du Colombier 	k = floor(ds);
2013e12c5d1SDavid du Colombier 	k_check = 1;
2023e12c5d1SDavid du Colombier 	if (k >= 0 && k <= Ten_pmax) {
2033e12c5d1SDavid du Colombier 		if (d.d < tens[k])
2043e12c5d1SDavid du Colombier 			k--;
2053e12c5d1SDavid du Colombier 		k_check = 0;
2063e12c5d1SDavid du Colombier 		}
2073e12c5d1SDavid du Colombier 	j = bbits - i - 1;
2083e12c5d1SDavid du Colombier 	if (j >= 0) {
2093e12c5d1SDavid du Colombier 		b2 = 0;
2103e12c5d1SDavid du Colombier 		s2 = j;
2113e12c5d1SDavid du Colombier 		}
2123e12c5d1SDavid du Colombier 	else {
2133e12c5d1SDavid du Colombier 		b2 = -j;
2143e12c5d1SDavid du Colombier 		s2 = 0;
2153e12c5d1SDavid du Colombier 		}
2163e12c5d1SDavid du Colombier 	if (k >= 0) {
2173e12c5d1SDavid du Colombier 		b5 = 0;
2183e12c5d1SDavid du Colombier 		s5 = k;
2193e12c5d1SDavid du Colombier 		s2 += k;
2203e12c5d1SDavid du Colombier 		}
2213e12c5d1SDavid du Colombier 	else {
2223e12c5d1SDavid du Colombier 		b2 -= k;
2233e12c5d1SDavid du Colombier 		b5 = -k;
2243e12c5d1SDavid du Colombier 		s5 = 0;
2253e12c5d1SDavid du Colombier 		}
2263e12c5d1SDavid du Colombier 	if (mode < 0 || mode > 9)
2273e12c5d1SDavid du Colombier 		mode = 0;
2283e12c5d1SDavid du Colombier 	try_quick = 1;
2293e12c5d1SDavid du Colombier 	if (mode > 5) {
2303e12c5d1SDavid du Colombier 		mode -= 4;
2313e12c5d1SDavid du Colombier 		try_quick = 0;
2323e12c5d1SDavid du Colombier 		}
2333e12c5d1SDavid du Colombier 	leftright = 1;
234*22df390cSDavid du Colombier 	ilim = ilim1 = -1;
2353e12c5d1SDavid du Colombier 	switch(mode) {
2363e12c5d1SDavid du Colombier 		case 0:
2373e12c5d1SDavid du Colombier 		case 1:
2383e12c5d1SDavid du Colombier 			ilim = ilim1 = -1;
2393e12c5d1SDavid du Colombier 			i = 18;
2403e12c5d1SDavid du Colombier 			ndigits = 0;
2413e12c5d1SDavid du Colombier 			break;
2423e12c5d1SDavid du Colombier 		case 2:
2433e12c5d1SDavid du Colombier 			leftright = 0;
2443e12c5d1SDavid du Colombier 			/* no break */
2453e12c5d1SDavid du Colombier 		case 4:
2463e12c5d1SDavid du Colombier 			if (ndigits <= 0)
2473e12c5d1SDavid du Colombier 				ndigits = 1;
2483e12c5d1SDavid du Colombier 			ilim = ilim1 = i = ndigits;
2493e12c5d1SDavid du Colombier 			break;
2503e12c5d1SDavid du Colombier 		case 3:
2513e12c5d1SDavid du Colombier 			leftright = 0;
2523e12c5d1SDavid du Colombier 			/* no break */
2533e12c5d1SDavid du Colombier 		case 5:
2543e12c5d1SDavid du Colombier 			i = ndigits + k + 1;
2553e12c5d1SDavid du Colombier 			ilim = i;
2563e12c5d1SDavid du Colombier 			ilim1 = i - 1;
2573e12c5d1SDavid du Colombier 			if (i <= 0)
2583e12c5d1SDavid du Colombier 				i = 1;
2593e12c5d1SDavid du Colombier 		}
2603e12c5d1SDavid du Colombier 	j = sizeof(unsigned long);
261219b2ee8SDavid du Colombier 	for(result_k = 0; sizeof(Bigint) - sizeof(unsigned long) + j <= i;
2623e12c5d1SDavid du Colombier 		j <<= 1) result_k++;
2633e12c5d1SDavid du Colombier 	result = Balloc(result_k);
2643e12c5d1SDavid du Colombier 	s = s0 = (char *)result;
2653e12c5d1SDavid du Colombier 
2663e12c5d1SDavid du Colombier 	if (ilim >= 0 && ilim <= Quick_max && try_quick) {
2673e12c5d1SDavid du Colombier 
2683e12c5d1SDavid du Colombier 		/* Try to get by with floating-point arithmetic. */
2693e12c5d1SDavid du Colombier 
2703e12c5d1SDavid du Colombier 		i = 0;
2713e12c5d1SDavid du Colombier 		d2.d = d.d;
2723e12c5d1SDavid du Colombier 		k0 = k;
2733e12c5d1SDavid du Colombier 		ilim0 = ilim;
2743e12c5d1SDavid du Colombier 		ieps = 2; /* conservative */
2753e12c5d1SDavid du Colombier 		if (k > 0) {
2763e12c5d1SDavid du Colombier 			ds = tens[k&0xf];
2773e12c5d1SDavid du Colombier 			j = k >> 4;
2783e12c5d1SDavid du Colombier 			if (j & Bletch) {
2793e12c5d1SDavid du Colombier 				/* prevent overflows */
2803e12c5d1SDavid du Colombier 				j &= Bletch - 1;
2813e12c5d1SDavid du Colombier 				d.d /= bigtens[n_bigtens-1];
2823e12c5d1SDavid du Colombier 				ieps++;
2833e12c5d1SDavid du Colombier 				}
2843e12c5d1SDavid du Colombier 			for(; j; j >>= 1, i++)
2853e12c5d1SDavid du Colombier 				if (j & 1) {
2863e12c5d1SDavid du Colombier 					ieps++;
2873e12c5d1SDavid du Colombier 					ds *= bigtens[i];
2883e12c5d1SDavid du Colombier 					}
2893e12c5d1SDavid du Colombier 			d.d /= ds;
2903e12c5d1SDavid du Colombier 			}
2913e12c5d1SDavid du Colombier 		else if (j1 = -k) {
2923e12c5d1SDavid du Colombier 			d.d *= tens[j1 & 0xf];
2933e12c5d1SDavid du Colombier 			for(j = j1 >> 4; j; j >>= 1, i++)
2943e12c5d1SDavid du Colombier 				if (j & 1) {
2953e12c5d1SDavid du Colombier 					ieps++;
2963e12c5d1SDavid du Colombier 					d.d *= bigtens[i];
2973e12c5d1SDavid du Colombier 					}
2983e12c5d1SDavid du Colombier 			}
2993e12c5d1SDavid du Colombier 		if (k_check && d.d < 1. && ilim > 0) {
3003e12c5d1SDavid du Colombier 			if (ilim1 <= 0)
3013e12c5d1SDavid du Colombier 				goto fast_failed;
3023e12c5d1SDavid du Colombier 			ilim = ilim1;
3033e12c5d1SDavid du Colombier 			k--;
3043e12c5d1SDavid du Colombier 			d.d *= 10.;
3053e12c5d1SDavid du Colombier 			ieps++;
3063e12c5d1SDavid du Colombier 			}
3073e12c5d1SDavid du Colombier 		eps.d = ieps*d.d + 7.;
3083e12c5d1SDavid du Colombier 		word0(eps) -= (P-1)*Exp_msk1;
3093e12c5d1SDavid du Colombier 		if (ilim == 0) {
3103e12c5d1SDavid du Colombier 			S = mhi = 0;
3113e12c5d1SDavid du Colombier 			d.d -= 5.;
3123e12c5d1SDavid du Colombier 			if (d.d > eps.d)
3133e12c5d1SDavid du Colombier 				goto one_digit;
3143e12c5d1SDavid du Colombier 			if (d.d < -eps.d)
3153e12c5d1SDavid du Colombier 				goto no_digits;
3163e12c5d1SDavid du Colombier 			goto fast_failed;
3173e12c5d1SDavid du Colombier 			}
3183e12c5d1SDavid du Colombier #ifndef No_leftright
3193e12c5d1SDavid du Colombier 		if (leftright) {
3203e12c5d1SDavid du Colombier 			/* Use Steele & White method of only
3213e12c5d1SDavid du Colombier 			 * generating digits needed.
3223e12c5d1SDavid du Colombier 			 */
3233e12c5d1SDavid du Colombier 			eps.d = 0.5/tens[ilim-1] - eps.d;
3243e12c5d1SDavid du Colombier 			for(i = 0;;) {
3253e12c5d1SDavid du Colombier 				L = floor(d.d);
3263e12c5d1SDavid du Colombier 				d.d -= L;
3273e12c5d1SDavid du Colombier 				*s++ = '0' + (int)L;
3283e12c5d1SDavid du Colombier 				if (d.d < eps.d)
3293e12c5d1SDavid du Colombier 					goto ret1;
3303e12c5d1SDavid du Colombier 				if (1. - d.d < eps.d)
3313e12c5d1SDavid du Colombier 					goto bump_up;
3323e12c5d1SDavid du Colombier 				if (++i >= ilim)
3333e12c5d1SDavid du Colombier 					break;
3343e12c5d1SDavid du Colombier 				eps.d *= 10.;
3353e12c5d1SDavid du Colombier 				d.d *= 10.;
3363e12c5d1SDavid du Colombier 				}
3373e12c5d1SDavid du Colombier 			}
3383e12c5d1SDavid du Colombier 		else {
3393e12c5d1SDavid du Colombier #endif
3403e12c5d1SDavid du Colombier 			/* Generate ilim digits, then fix them up. */
3413e12c5d1SDavid du Colombier 			eps.d *= tens[ilim-1];
3423e12c5d1SDavid du Colombier 			for(i = 1;; i++, d.d *= 10.) {
3433e12c5d1SDavid du Colombier 				L = floor(d.d);
3443e12c5d1SDavid du Colombier 				d.d -= L;
3453e12c5d1SDavid du Colombier 				*s++ = '0' + (int)L;
3463e12c5d1SDavid du Colombier 				if (i == ilim) {
3473e12c5d1SDavid du Colombier 					if (d.d > 0.5 + eps.d)
3483e12c5d1SDavid du Colombier 						goto bump_up;
3493e12c5d1SDavid du Colombier 					else if (d.d < 0.5 - eps.d) {
3503e12c5d1SDavid du Colombier 						while(*--s == '0');
3513e12c5d1SDavid du Colombier 						s++;
3523e12c5d1SDavid du Colombier 						goto ret1;
3533e12c5d1SDavid du Colombier 						}
3543e12c5d1SDavid du Colombier 					break;
3553e12c5d1SDavid du Colombier 					}
3563e12c5d1SDavid du Colombier 				}
3573e12c5d1SDavid du Colombier #ifndef No_leftright
3583e12c5d1SDavid du Colombier 			}
3593e12c5d1SDavid du Colombier #endif
3603e12c5d1SDavid du Colombier  fast_failed:
3613e12c5d1SDavid du Colombier 		s = s0;
3623e12c5d1SDavid du Colombier 		d.d = d2.d;
3633e12c5d1SDavid du Colombier 		k = k0;
3643e12c5d1SDavid du Colombier 		ilim = ilim0;
3653e12c5d1SDavid du Colombier 		}
3663e12c5d1SDavid du Colombier 
3673e12c5d1SDavid du Colombier 	/* Do we have a "small" integer? */
3683e12c5d1SDavid du Colombier 
3693e12c5d1SDavid du Colombier 	if (be >= 0 && k <= Int_max) {
3703e12c5d1SDavid du Colombier 		/* Yes. */
3713e12c5d1SDavid du Colombier 		ds = tens[k];
3723e12c5d1SDavid du Colombier 		if (ndigits < 0 && ilim <= 0) {
3733e12c5d1SDavid du Colombier 			S = mhi = 0;
3743e12c5d1SDavid du Colombier 			if (ilim < 0 || d.d <= 5*ds)
3753e12c5d1SDavid du Colombier 				goto no_digits;
3763e12c5d1SDavid du Colombier 			goto one_digit;
3773e12c5d1SDavid du Colombier 			}
3783e12c5d1SDavid du Colombier 		for(i = 1;; i++) {
3793e12c5d1SDavid du Colombier 			L = floor(d.d / ds);
3803e12c5d1SDavid du Colombier 			d.d -= L*ds;
3813e12c5d1SDavid du Colombier #ifdef Check_FLT_ROUNDS
3823e12c5d1SDavid du Colombier 			/* If FLT_ROUNDS == 2, L will usually be high by 1 */
3833e12c5d1SDavid du Colombier 			if (d.d < 0) {
3843e12c5d1SDavid du Colombier 				L--;
3853e12c5d1SDavid du Colombier 				d.d += ds;
3863e12c5d1SDavid du Colombier 				}
3873e12c5d1SDavid du Colombier #endif
3883e12c5d1SDavid du Colombier 			*s++ = '0' + (int)L;
3893e12c5d1SDavid du Colombier 			if (i == ilim) {
3903e12c5d1SDavid du Colombier 				d.d += d.d;
3913e12c5d1SDavid du Colombier 				if (d.d > ds || d.d == ds && L & 1) {
3923e12c5d1SDavid du Colombier  bump_up:
3933e12c5d1SDavid du Colombier 					while(*--s == '9')
3943e12c5d1SDavid du Colombier 						if (s == s0) {
3953e12c5d1SDavid du Colombier 							k++;
3963e12c5d1SDavid du Colombier 							*s = '0';
3973e12c5d1SDavid du Colombier 							break;
3983e12c5d1SDavid du Colombier 							}
3993e12c5d1SDavid du Colombier 					++*s++;
4003e12c5d1SDavid du Colombier 					}
4013e12c5d1SDavid du Colombier 				break;
4023e12c5d1SDavid du Colombier 				}
4033e12c5d1SDavid du Colombier 			d.d *= 10.;
4043e12c5d1SDavid du Colombier 			if (d.d == 0.)
4053e12c5d1SDavid du Colombier 				break;
4063e12c5d1SDavid du Colombier 			}
4073e12c5d1SDavid du Colombier 		goto ret1;
4083e12c5d1SDavid du Colombier 		}
4093e12c5d1SDavid du Colombier 
4103e12c5d1SDavid du Colombier 	m2 = b2;
4113e12c5d1SDavid du Colombier 	m5 = b5;
4123e12c5d1SDavid du Colombier 	mhi = mlo = 0;
4133e12c5d1SDavid du Colombier 	if (leftright) {
4143e12c5d1SDavid du Colombier 		if (mode < 2) {
4153e12c5d1SDavid du Colombier 			i =
4163e12c5d1SDavid du Colombier #ifndef Sudden_Underflow
4173e12c5d1SDavid du Colombier 				denorm ? be + (Bias + (P-1) - 1 + 1) :
4183e12c5d1SDavid du Colombier #endif
4193e12c5d1SDavid du Colombier #ifdef IBM
4203e12c5d1SDavid du Colombier 				1 + 4*P - 3 - bbits + ((bbits + be - 1) & 3);
4213e12c5d1SDavid du Colombier #else
4223e12c5d1SDavid du Colombier 				1 + P - bbits;
4233e12c5d1SDavid du Colombier #endif
4243e12c5d1SDavid du Colombier 			}
4253e12c5d1SDavid du Colombier 		else {
4263e12c5d1SDavid du Colombier 			j = ilim - 1;
4273e12c5d1SDavid du Colombier 			if (m5 >= j)
4283e12c5d1SDavid du Colombier 				m5 -= j;
4293e12c5d1SDavid du Colombier 			else {
4303e12c5d1SDavid du Colombier 				s5 += j -= m5;
4313e12c5d1SDavid du Colombier 				b5 += j;
4323e12c5d1SDavid du Colombier 				m5 = 0;
4333e12c5d1SDavid du Colombier 				}
4343e12c5d1SDavid du Colombier 			if ((i = ilim) < 0) {
4353e12c5d1SDavid du Colombier 				m2 -= i;
4363e12c5d1SDavid du Colombier 				i = 0;
4373e12c5d1SDavid du Colombier 				}
4383e12c5d1SDavid du Colombier 			}
4393e12c5d1SDavid du Colombier 		b2 += i;
4403e12c5d1SDavid du Colombier 		s2 += i;
4413e12c5d1SDavid du Colombier 		mhi = i2b(1);
4423e12c5d1SDavid du Colombier 		}
4433e12c5d1SDavid du Colombier 	if (m2 > 0 && s2 > 0) {
4443e12c5d1SDavid du Colombier 		i = m2 < s2 ? m2 : s2;
4453e12c5d1SDavid du Colombier 		b2 -= i;
4463e12c5d1SDavid du Colombier 		m2 -= i;
4473e12c5d1SDavid du Colombier 		s2 -= i;
4483e12c5d1SDavid du Colombier 		}
4493e12c5d1SDavid du Colombier 	if (b5 > 0) {
4503e12c5d1SDavid du Colombier 		if (leftright) {
4513e12c5d1SDavid du Colombier 			if (m5 > 0) {
4523e12c5d1SDavid du Colombier 				mhi = pow5mult(mhi, m5);
4533e12c5d1SDavid du Colombier 				b1 = mult(mhi, b);
4543e12c5d1SDavid du Colombier 				Bfree(b);
4553e12c5d1SDavid du Colombier 				b = b1;
4563e12c5d1SDavid du Colombier 				}
4573e12c5d1SDavid du Colombier 			if (j = b5 - m5)
4583e12c5d1SDavid du Colombier 				b = pow5mult(b, j);
4593e12c5d1SDavid du Colombier 			}
4603e12c5d1SDavid du Colombier 		else
4613e12c5d1SDavid du Colombier 			b = pow5mult(b, b5);
4623e12c5d1SDavid du Colombier 		}
4633e12c5d1SDavid du Colombier 	S = i2b(1);
4643e12c5d1SDavid du Colombier 	if (s5 > 0)
4653e12c5d1SDavid du Colombier 		S = pow5mult(S, s5);
4663e12c5d1SDavid du Colombier 
4673e12c5d1SDavid du Colombier 	/* Check for special case that d is a normalized power of 2. */
468*22df390cSDavid du Colombier 	spec_case = 0;
4693e12c5d1SDavid du Colombier 	if (mode < 2) {
4703e12c5d1SDavid du Colombier 		if (!word1(d) && !(word0(d) & Bndry_mask)
4713e12c5d1SDavid du Colombier #ifndef Sudden_Underflow
4723e12c5d1SDavid du Colombier 		 && word0(d) & Exp_mask
4733e12c5d1SDavid du Colombier #endif
4743e12c5d1SDavid du Colombier 				) {
4753e12c5d1SDavid du Colombier 			/* The special case */
4763e12c5d1SDavid du Colombier 			b2 += Log2P;
4773e12c5d1SDavid du Colombier 			s2 += Log2P;
4783e12c5d1SDavid du Colombier 			spec_case = 1;
4793e12c5d1SDavid du Colombier 			}
4803e12c5d1SDavid du Colombier 		else
4813e12c5d1SDavid du Colombier 			spec_case = 0;
4823e12c5d1SDavid du Colombier 		}
4833e12c5d1SDavid du Colombier 
4843e12c5d1SDavid du Colombier 	/* Arrange for convenient computation of quotients:
4853e12c5d1SDavid du Colombier 	 * shift left if necessary so divisor has 4 leading 0 bits.
4863e12c5d1SDavid du Colombier 	 *
4873e12c5d1SDavid du Colombier 	 * Perhaps we should just compute leading 28 bits of S once
4883e12c5d1SDavid du Colombier 	 * and for all and pass them and a shift to quorem, so it
4893e12c5d1SDavid du Colombier 	 * can do shifts and ors to compute the numerator for q.
4903e12c5d1SDavid du Colombier 	 */
4913e12c5d1SDavid du Colombier #ifdef Pack_32
4923e12c5d1SDavid du Colombier 	if (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f)
4933e12c5d1SDavid du Colombier 		i = 32 - i;
4943e12c5d1SDavid du Colombier #else
4953e12c5d1SDavid du Colombier 	if (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf)
4963e12c5d1SDavid du Colombier 		i = 16 - i;
4973e12c5d1SDavid du Colombier #endif
4983e12c5d1SDavid du Colombier 	if (i > 4) {
4993e12c5d1SDavid du Colombier 		i -= 4;
5003e12c5d1SDavid du Colombier 		b2 += i;
5013e12c5d1SDavid du Colombier 		m2 += i;
5023e12c5d1SDavid du Colombier 		s2 += i;
5033e12c5d1SDavid du Colombier 		}
5043e12c5d1SDavid du Colombier 	else if (i < 4) {
5053e12c5d1SDavid du Colombier 		i += 28;
5063e12c5d1SDavid du Colombier 		b2 += i;
5073e12c5d1SDavid du Colombier 		m2 += i;
5083e12c5d1SDavid du Colombier 		s2 += i;
5093e12c5d1SDavid du Colombier 		}
5103e12c5d1SDavid du Colombier 	if (b2 > 0)
5113e12c5d1SDavid du Colombier 		b = lshift(b, b2);
5123e12c5d1SDavid du Colombier 	if (s2 > 0)
5133e12c5d1SDavid du Colombier 		S = lshift(S, s2);
5143e12c5d1SDavid du Colombier 	if (k_check) {
5153e12c5d1SDavid du Colombier 		if (cmp(b,S) < 0) {
5163e12c5d1SDavid du Colombier 			k--;
5173e12c5d1SDavid du Colombier 			b = multadd(b, 10, 0);	/* we botched the k estimate */
5183e12c5d1SDavid du Colombier 			if (leftright)
5193e12c5d1SDavid du Colombier 				mhi = multadd(mhi, 10, 0);
5203e12c5d1SDavid du Colombier 			ilim = ilim1;
5213e12c5d1SDavid du Colombier 			}
5223e12c5d1SDavid du Colombier 		}
5233e12c5d1SDavid du Colombier 	if (ilim <= 0 && mode > 2) {
5243e12c5d1SDavid du Colombier 		if (ilim < 0 || cmp(b,S = multadd(S,5,0)) <= 0) {
5253e12c5d1SDavid du Colombier 			/* no digits, fcvt style */
5263e12c5d1SDavid du Colombier  no_digits:
5273e12c5d1SDavid du Colombier 			k = -1 - ndigits;
5283e12c5d1SDavid du Colombier 			goto ret;
5293e12c5d1SDavid du Colombier 			}
5303e12c5d1SDavid du Colombier  one_digit:
5313e12c5d1SDavid du Colombier 		*s++ = '1';
5323e12c5d1SDavid du Colombier 		k++;
5333e12c5d1SDavid du Colombier 		goto ret;
5343e12c5d1SDavid du Colombier 		}
5353e12c5d1SDavid du Colombier 	if (leftright) {
5363e12c5d1SDavid du Colombier 		if (m2 > 0)
5373e12c5d1SDavid du Colombier 			mhi = lshift(mhi, m2);
5383e12c5d1SDavid du Colombier 
5393e12c5d1SDavid du Colombier 		/* Compute mlo -- check for special case
5403e12c5d1SDavid du Colombier 		 * that d is a normalized power of 2.
5413e12c5d1SDavid du Colombier 		 */
5423e12c5d1SDavid du Colombier 
5433e12c5d1SDavid du Colombier 		mlo = mhi;
5443e12c5d1SDavid du Colombier 		if (spec_case) {
5453e12c5d1SDavid du Colombier 			mhi = Balloc(mhi->k);
5463e12c5d1SDavid du Colombier 			Bcopy(mhi, mlo);
5473e12c5d1SDavid du Colombier 			mhi = lshift(mhi, Log2P);
5483e12c5d1SDavid du Colombier 			}
5493e12c5d1SDavid du Colombier 
5503e12c5d1SDavid du Colombier 		for(i = 1;;i++) {
5513e12c5d1SDavid du Colombier 			dig = quorem(b,S) + '0';
5523e12c5d1SDavid du Colombier 			/* Do we yet have the shortest decimal string
5533e12c5d1SDavid du Colombier 			 * that will round to d?
5543e12c5d1SDavid du Colombier 			 */
5553e12c5d1SDavid du Colombier 			j = cmp(b, mlo);
5563e12c5d1SDavid du Colombier 			delta = diff(S, mhi);
5573e12c5d1SDavid du Colombier 			j1 = delta->sign ? 1 : cmp(b, delta);
5583e12c5d1SDavid du Colombier 			Bfree(delta);
5593e12c5d1SDavid du Colombier #ifndef ROUND_BIASED
5603e12c5d1SDavid du Colombier 			if (j1 == 0 && !mode && !(word1(d) & 1)) {
5613e12c5d1SDavid du Colombier 				if (dig == '9')
5623e12c5d1SDavid du Colombier 					goto round_9_up;
5633e12c5d1SDavid du Colombier 				if (j > 0)
5643e12c5d1SDavid du Colombier 					dig++;
5653e12c5d1SDavid du Colombier 				*s++ = dig;
5663e12c5d1SDavid du Colombier 				goto ret;
5673e12c5d1SDavid du Colombier 				}
5683e12c5d1SDavid du Colombier #endif
5693e12c5d1SDavid du Colombier 			if (j < 0 || j == 0 && !mode
5703e12c5d1SDavid du Colombier #ifndef ROUND_BIASED
5713e12c5d1SDavid du Colombier 							&& !(word1(d) & 1)
5723e12c5d1SDavid du Colombier #endif
5733e12c5d1SDavid du Colombier 					) {
5743e12c5d1SDavid du Colombier 				if (j1 > 0) {
5753e12c5d1SDavid du Colombier 					b = lshift(b, 1);
5763e12c5d1SDavid du Colombier 					j1 = cmp(b, S);
5773e12c5d1SDavid du Colombier 					if ((j1 > 0 || j1 == 0 && dig & 1)
5783e12c5d1SDavid du Colombier 					&& dig++ == '9')
5793e12c5d1SDavid du Colombier 						goto round_9_up;
5803e12c5d1SDavid du Colombier 					}
5813e12c5d1SDavid du Colombier 				*s++ = dig;
5823e12c5d1SDavid du Colombier 				goto ret;
5833e12c5d1SDavid du Colombier 				}
5843e12c5d1SDavid du Colombier 			if (j1 > 0) {
5853e12c5d1SDavid du Colombier 				if (dig == '9') { /* possible if i == 1 */
5863e12c5d1SDavid du Colombier  round_9_up:
5873e12c5d1SDavid du Colombier 					*s++ = '9';
5883e12c5d1SDavid du Colombier 					goto roundoff;
5893e12c5d1SDavid du Colombier 					}
5903e12c5d1SDavid du Colombier 				*s++ = dig + 1;
5913e12c5d1SDavid du Colombier 				goto ret;
5923e12c5d1SDavid du Colombier 				}
5933e12c5d1SDavid du Colombier 			*s++ = dig;
5943e12c5d1SDavid du Colombier 			if (i == ilim)
5953e12c5d1SDavid du Colombier 				break;
5963e12c5d1SDavid du Colombier 			b = multadd(b, 10, 0);
5973e12c5d1SDavid du Colombier 			if (mlo == mhi)
5983e12c5d1SDavid du Colombier 				mlo = mhi = multadd(mhi, 10, 0);
5993e12c5d1SDavid du Colombier 			else {
6003e12c5d1SDavid du Colombier 				mlo = multadd(mlo, 10, 0);
6013e12c5d1SDavid du Colombier 				mhi = multadd(mhi, 10, 0);
6023e12c5d1SDavid du Colombier 				}
6033e12c5d1SDavid du Colombier 			}
6043e12c5d1SDavid du Colombier 		}
6053e12c5d1SDavid du Colombier 	else
6063e12c5d1SDavid du Colombier 		for(i = 1;; i++) {
6073e12c5d1SDavid du Colombier 			*s++ = dig = quorem(b,S) + '0';
6083e12c5d1SDavid du Colombier 			if (i >= ilim)
6093e12c5d1SDavid du Colombier 				break;
6103e12c5d1SDavid du Colombier 			b = multadd(b, 10, 0);
6113e12c5d1SDavid du Colombier 			}
6123e12c5d1SDavid du Colombier 
6133e12c5d1SDavid du Colombier 	/* Round off last digit */
6143e12c5d1SDavid du Colombier 
6153e12c5d1SDavid du Colombier 	b = lshift(b, 1);
6163e12c5d1SDavid du Colombier 	j = cmp(b, S);
6173e12c5d1SDavid du Colombier 	if (j > 0 || j == 0 && dig & 1) {
6183e12c5d1SDavid du Colombier  roundoff:
6193e12c5d1SDavid du Colombier 		while(*--s == '9')
6203e12c5d1SDavid du Colombier 			if (s == s0) {
6213e12c5d1SDavid du Colombier 				k++;
6223e12c5d1SDavid du Colombier 				*s++ = '1';
6233e12c5d1SDavid du Colombier 				goto ret;
6243e12c5d1SDavid du Colombier 				}
6253e12c5d1SDavid du Colombier 		++*s++;
6263e12c5d1SDavid du Colombier 		}
6273e12c5d1SDavid du Colombier 	else {
6283e12c5d1SDavid du Colombier 		while(*--s == '0');
6293e12c5d1SDavid du Colombier 		s++;
6303e12c5d1SDavid du Colombier 		}
6313e12c5d1SDavid du Colombier  ret:
6323e12c5d1SDavid du Colombier 	Bfree(S);
6333e12c5d1SDavid du Colombier 	if (mhi) {
6343e12c5d1SDavid du Colombier 		if (mlo && mlo != mhi)
6353e12c5d1SDavid du Colombier 			Bfree(mlo);
6363e12c5d1SDavid du Colombier 		Bfree(mhi);
6373e12c5d1SDavid du Colombier 		}
6383e12c5d1SDavid du Colombier  ret1:
6393e12c5d1SDavid du Colombier 	Bfree(b);
6403e12c5d1SDavid du Colombier 	*s = 0;
6413e12c5d1SDavid du Colombier 	*decpt = k + 1;
6423e12c5d1SDavid du Colombier 	if (rve)
6433e12c5d1SDavid du Colombier 		*rve = s;
6443e12c5d1SDavid du Colombier 	return s0;
6453e12c5d1SDavid du Colombier 	}
6463e12c5d1SDavid du Colombier 
6473e12c5d1SDavid du Colombier  static int
quorem(Bigint * b,Bigint * S)6483e12c5d1SDavid du Colombier quorem(Bigint *b, Bigint *S)
6493e12c5d1SDavid du Colombier {
6503e12c5d1SDavid du Colombier 	int n;
6513e12c5d1SDavid du Colombier 	long borrow, y;
6523e12c5d1SDavid du Colombier 	unsigned long carry, q, ys;
6533e12c5d1SDavid du Colombier 	unsigned long *bx, *bxe, *sx, *sxe;
6543e12c5d1SDavid du Colombier #ifdef Pack_32
6553e12c5d1SDavid du Colombier 	long z;
6563e12c5d1SDavid du Colombier 	unsigned long si, zs;
6573e12c5d1SDavid du Colombier #endif
6583e12c5d1SDavid du Colombier 
6593e12c5d1SDavid du Colombier 	n = S->wds;
6603e12c5d1SDavid du Colombier #ifdef DEBUG
6613e12c5d1SDavid du Colombier 	/*debug*/ if (b->wds > n)
6623e12c5d1SDavid du Colombier 	/*debug*/	Bug("oversize b in quorem");
6633e12c5d1SDavid du Colombier #endif
6643e12c5d1SDavid du Colombier 	if (b->wds < n)
6653e12c5d1SDavid du Colombier 		return 0;
6663e12c5d1SDavid du Colombier 	sx = S->x;
6673e12c5d1SDavid du Colombier 	sxe = sx + --n;
6683e12c5d1SDavid du Colombier 	bx = b->x;
6693e12c5d1SDavid du Colombier 	bxe = bx + n;
6703e12c5d1SDavid du Colombier 	q = *bxe / (*sxe + 1);	/* ensure q <= true quotient */
6713e12c5d1SDavid du Colombier #ifdef DEBUG
6723e12c5d1SDavid du Colombier 	/*debug*/ if (q > 9)
6733e12c5d1SDavid du Colombier 	/*debug*/	Bug("oversized quotient in quorem");
6743e12c5d1SDavid du Colombier #endif
6753e12c5d1SDavid du Colombier 	if (q) {
6763e12c5d1SDavid du Colombier 		borrow = 0;
6773e12c5d1SDavid du Colombier 		carry = 0;
6783e12c5d1SDavid du Colombier 		do {
6793e12c5d1SDavid du Colombier #ifdef Pack_32
6803e12c5d1SDavid du Colombier 			si = *sx++;
6813e12c5d1SDavid du Colombier 			ys = (si & 0xffff) * q + carry;
6823e12c5d1SDavid du Colombier 			zs = (si >> 16) * q + (ys >> 16);
6833e12c5d1SDavid du Colombier 			carry = zs >> 16;
6843e12c5d1SDavid du Colombier 			y = (*bx & 0xffff) - (ys & 0xffff) + borrow;
6853e12c5d1SDavid du Colombier 			borrow = y >> 16;
6863e12c5d1SDavid du Colombier 			Sign_Extend(borrow, y);
6873e12c5d1SDavid du Colombier 			z = (*bx >> 16) - (zs & 0xffff) + borrow;
6883e12c5d1SDavid du Colombier 			borrow = z >> 16;
6893e12c5d1SDavid du Colombier 			Sign_Extend(borrow, z);
6903e12c5d1SDavid du Colombier 			Storeinc(bx, z, y);
6913e12c5d1SDavid du Colombier #else
6923e12c5d1SDavid du Colombier 			ys = *sx++ * q + carry;
6933e12c5d1SDavid du Colombier 			carry = ys >> 16;
6943e12c5d1SDavid du Colombier 			y = *bx - (ys & 0xffff) + borrow;
6953e12c5d1SDavid du Colombier 			borrow = y >> 16;
6963e12c5d1SDavid du Colombier 			Sign_Extend(borrow, y);
6973e12c5d1SDavid du Colombier 			*bx++ = y & 0xffff;
6983e12c5d1SDavid du Colombier #endif
6993e12c5d1SDavid du Colombier 			}
7003e12c5d1SDavid du Colombier 			while(sx <= sxe);
7013e12c5d1SDavid du Colombier 		if (!*bxe) {
7023e12c5d1SDavid du Colombier 			bx = b->x;
7033e12c5d1SDavid du Colombier 			while(--bxe > bx && !*bxe)
7043e12c5d1SDavid du Colombier 				--n;
7053e12c5d1SDavid du Colombier 			b->wds = n;
7063e12c5d1SDavid du Colombier 			}
7073e12c5d1SDavid du Colombier 		}
7083e12c5d1SDavid du Colombier 	if (cmp(b, S) >= 0) {
7093e12c5d1SDavid du Colombier 		q++;
7103e12c5d1SDavid du Colombier 		borrow = 0;
7113e12c5d1SDavid du Colombier 		carry = 0;
7123e12c5d1SDavid du Colombier 		bx = b->x;
7133e12c5d1SDavid du Colombier 		sx = S->x;
7143e12c5d1SDavid du Colombier 		do {
7153e12c5d1SDavid du Colombier #ifdef Pack_32
7163e12c5d1SDavid du Colombier 			si = *sx++;
7173e12c5d1SDavid du Colombier 			ys = (si & 0xffff) + carry;
7183e12c5d1SDavid du Colombier 			zs = (si >> 16) + (ys >> 16);
7193e12c5d1SDavid du Colombier 			carry = zs >> 16;
7203e12c5d1SDavid du Colombier 			y = (*bx & 0xffff) - (ys & 0xffff) + borrow;
7213e12c5d1SDavid du Colombier 			borrow = y >> 16;
7223e12c5d1SDavid du Colombier 			Sign_Extend(borrow, y);
7233e12c5d1SDavid du Colombier 			z = (*bx >> 16) - (zs & 0xffff) + borrow;
7243e12c5d1SDavid du Colombier 			borrow = z >> 16;
7253e12c5d1SDavid du Colombier 			Sign_Extend(borrow, z);
7263e12c5d1SDavid du Colombier 			Storeinc(bx, z, y);
7273e12c5d1SDavid du Colombier #else
7283e12c5d1SDavid du Colombier 			ys = *sx++ + carry;
7293e12c5d1SDavid du Colombier 			carry = ys >> 16;
7303e12c5d1SDavid du Colombier 			y = *bx - (ys & 0xffff) + borrow;
7313e12c5d1SDavid du Colombier 			borrow = y >> 16;
7323e12c5d1SDavid du Colombier 			Sign_Extend(borrow, y);
7333e12c5d1SDavid du Colombier 			*bx++ = y & 0xffff;
7343e12c5d1SDavid du Colombier #endif
7353e12c5d1SDavid du Colombier 			}
7363e12c5d1SDavid du Colombier 			while(sx <= sxe);
7373e12c5d1SDavid du Colombier 		bx = b->x;
7383e12c5d1SDavid du Colombier 		bxe = bx + n;
7393e12c5d1SDavid du Colombier 		if (!*bxe) {
7403e12c5d1SDavid du Colombier 			while(--bxe > bx && !*bxe)
7413e12c5d1SDavid du Colombier 				--n;
7423e12c5d1SDavid du Colombier 			b->wds = n;
7433e12c5d1SDavid du Colombier 			}
7443e12c5d1SDavid du Colombier 		}
7453e12c5d1SDavid du Colombier 	return q;
7463e12c5d1SDavid du Colombier 	}
747