xref: /plan9/sys/src/ape/lib/ap/stdio/_dtoa.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
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 
923e12c5d1SDavid du Colombier 	d.d = darg;
933e12c5d1SDavid du Colombier 	if (result) {
943e12c5d1SDavid du Colombier 		result->k = result_k;
953e12c5d1SDavid du Colombier 		result->maxwds = 1 << result_k;
963e12c5d1SDavid du Colombier 		Bfree(result);
973e12c5d1SDavid du Colombier 		result = 0;
983e12c5d1SDavid du Colombier 		}
993e12c5d1SDavid du Colombier 
1003e12c5d1SDavid du Colombier 	if (word0(d) & Sign_bit) {
1013e12c5d1SDavid du Colombier 		/* set sign for everything, including 0's and NaNs */
1023e12c5d1SDavid du Colombier 		*sign = 1;
1033e12c5d1SDavid du Colombier 		word0(d) &= ~Sign_bit;	/* clear sign bit */
1043e12c5d1SDavid du Colombier 		}
1053e12c5d1SDavid du Colombier 	else
1063e12c5d1SDavid du Colombier 		*sign = 0;
1073e12c5d1SDavid du Colombier 
1083e12c5d1SDavid du Colombier #if defined(IEEE_Arith) + defined(VAX)
1093e12c5d1SDavid du Colombier #ifdef IEEE_Arith
1103e12c5d1SDavid du Colombier 	if ((word0(d) & Exp_mask) == Exp_mask)
1113e12c5d1SDavid du Colombier #else
1123e12c5d1SDavid du Colombier 	if (word0(d)  == 0x8000)
1133e12c5d1SDavid du Colombier #endif
1143e12c5d1SDavid du Colombier 		{
1153e12c5d1SDavid du Colombier 		/* Infinity or NaN */
1163e12c5d1SDavid du Colombier 		*decpt = 9999;
1173e12c5d1SDavid du Colombier 		s =
1183e12c5d1SDavid du Colombier #ifdef IEEE_Arith
1193e12c5d1SDavid du Colombier 			!word1(d) && !(word0(d) & 0xfffff) ? "Infinity" :
1203e12c5d1SDavid du Colombier #endif
1213e12c5d1SDavid du Colombier 				"NaN";
1223e12c5d1SDavid du Colombier 		if (rve)
1233e12c5d1SDavid du Colombier 			*rve =
1243e12c5d1SDavid du Colombier #ifdef IEEE_Arith
1253e12c5d1SDavid du Colombier 				s[3] ? s + 8 :
1263e12c5d1SDavid du Colombier #endif
1273e12c5d1SDavid du Colombier 						s + 3;
1283e12c5d1SDavid du Colombier 		return s;
1293e12c5d1SDavid du Colombier 		}
1303e12c5d1SDavid du Colombier #endif
1313e12c5d1SDavid du Colombier #ifdef IBM
1323e12c5d1SDavid du Colombier 	d.d += 0; /* normalize */
1333e12c5d1SDavid du Colombier #endif
1343e12c5d1SDavid du Colombier 	if (!d.d) {
1353e12c5d1SDavid du Colombier 		*decpt = 1;
1363e12c5d1SDavid du Colombier 		s = "0";
1373e12c5d1SDavid du Colombier 		if (rve)
1383e12c5d1SDavid du Colombier 			*rve = s + 1;
1393e12c5d1SDavid du Colombier 		return s;
1403e12c5d1SDavid du Colombier 		}
1413e12c5d1SDavid du Colombier 
1423e12c5d1SDavid du Colombier 	b = d2b(d.d, &be, &bbits);
1433e12c5d1SDavid du Colombier #ifdef Sudden_Underflow
1443e12c5d1SDavid du Colombier 	i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1));
1453e12c5d1SDavid du Colombier #else
1463e12c5d1SDavid du Colombier 	if (i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1))) {
1473e12c5d1SDavid du Colombier #endif
1483e12c5d1SDavid du Colombier 		d2.d = d.d;
1493e12c5d1SDavid du Colombier 		word0(d2) &= Frac_mask1;
1503e12c5d1SDavid du Colombier 		word0(d2) |= Exp_11;
1513e12c5d1SDavid du Colombier #ifdef IBM
1523e12c5d1SDavid du Colombier 		if (j = 11 - hi0bits(word0(d2) & Frac_mask))
1533e12c5d1SDavid du Colombier 			d2.d /= 1 << j;
1543e12c5d1SDavid du Colombier #endif
1553e12c5d1SDavid du Colombier 
1563e12c5d1SDavid du Colombier 		/* log(x)	~=~ log(1.5) + (x-1.5)/1.5
1573e12c5d1SDavid du Colombier 		 * log10(x)	 =  log(x) / log(10)
1583e12c5d1SDavid du Colombier 		 *		~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))
1593e12c5d1SDavid du Colombier 		 * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2)
1603e12c5d1SDavid du Colombier 		 *
1613e12c5d1SDavid du Colombier 		 * This suggests computing an approximation k to log10(d) by
1623e12c5d1SDavid du Colombier 		 *
1633e12c5d1SDavid du Colombier 		 * k = (i - Bias)*0.301029995663981
1643e12c5d1SDavid du Colombier 		 *	+ ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
1653e12c5d1SDavid du Colombier 		 *
1663e12c5d1SDavid du Colombier 		 * We want k to be too large rather than too small.
1673e12c5d1SDavid du Colombier 		 * The error in the first-order Taylor series approximation
1683e12c5d1SDavid du Colombier 		 * is in our favor, so we just round up the constant enough
1693e12c5d1SDavid du Colombier 		 * to compensate for any error in the multiplication of
1703e12c5d1SDavid du Colombier 		 * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077,
1713e12c5d1SDavid du Colombier 		 * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14,
1723e12c5d1SDavid du Colombier 		 * adding 1e-13 to the constant term more than suffices.
1733e12c5d1SDavid du Colombier 		 * Hence we adjust the constant term to 0.1760912590558.
1743e12c5d1SDavid du Colombier 		 * (We could get a more accurate k by invoking log10,
1753e12c5d1SDavid du Colombier 		 *  but this is probably not worthwhile.)
1763e12c5d1SDavid du Colombier 		 */
1773e12c5d1SDavid du Colombier 
1783e12c5d1SDavid du Colombier 		i -= Bias;
1793e12c5d1SDavid du Colombier #ifdef IBM
1803e12c5d1SDavid du Colombier 		i <<= 2;
1813e12c5d1SDavid du Colombier 		i += j;
1823e12c5d1SDavid du Colombier #endif
1833e12c5d1SDavid du Colombier #ifndef Sudden_Underflow
1843e12c5d1SDavid du Colombier 		denorm = 0;
1853e12c5d1SDavid du Colombier 		}
1863e12c5d1SDavid du Colombier 	else {
1873e12c5d1SDavid du Colombier 		/* d is denormalized */
1883e12c5d1SDavid du Colombier 
1893e12c5d1SDavid du Colombier 		i = bbits + be + (Bias + (P-1) - 1);
1903e12c5d1SDavid du Colombier 		x = i > 32  ? word0(d) << 64 - i | word1(d) >> i - 32
1913e12c5d1SDavid du Colombier 			    : word1(d) << 32 - i;
1923e12c5d1SDavid du Colombier 		d2.d = x;
1933e12c5d1SDavid du Colombier 		word0(d2) -= 31*Exp_msk1; /* adjust exponent */
1943e12c5d1SDavid du Colombier 		i -= (Bias + (P-1) - 1) + 1;
1953e12c5d1SDavid du Colombier 		denorm = 1;
1963e12c5d1SDavid du Colombier 		}
1973e12c5d1SDavid du Colombier #endif
1983e12c5d1SDavid du Colombier 	ds = (d2.d-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
1993e12c5d1SDavid du Colombier 	k = floor(ds);
2003e12c5d1SDavid du Colombier 	k_check = 1;
2013e12c5d1SDavid du Colombier 	if (k >= 0 && k <= Ten_pmax) {
2023e12c5d1SDavid du Colombier 		if (d.d < tens[k])
2033e12c5d1SDavid du Colombier 			k--;
2043e12c5d1SDavid du Colombier 		k_check = 0;
2053e12c5d1SDavid du Colombier 		}
2063e12c5d1SDavid du Colombier 	j = bbits - i - 1;
2073e12c5d1SDavid du Colombier 	if (j >= 0) {
2083e12c5d1SDavid du Colombier 		b2 = 0;
2093e12c5d1SDavid du Colombier 		s2 = j;
2103e12c5d1SDavid du Colombier 		}
2113e12c5d1SDavid du Colombier 	else {
2123e12c5d1SDavid du Colombier 		b2 = -j;
2133e12c5d1SDavid du Colombier 		s2 = 0;
2143e12c5d1SDavid du Colombier 		}
2153e12c5d1SDavid du Colombier 	if (k >= 0) {
2163e12c5d1SDavid du Colombier 		b5 = 0;
2173e12c5d1SDavid du Colombier 		s5 = k;
2183e12c5d1SDavid du Colombier 		s2 += k;
2193e12c5d1SDavid du Colombier 		}
2203e12c5d1SDavid du Colombier 	else {
2213e12c5d1SDavid du Colombier 		b2 -= k;
2223e12c5d1SDavid du Colombier 		b5 = -k;
2233e12c5d1SDavid du Colombier 		s5 = 0;
2243e12c5d1SDavid du Colombier 		}
2253e12c5d1SDavid du Colombier 	if (mode < 0 || mode > 9)
2263e12c5d1SDavid du Colombier 		mode = 0;
2273e12c5d1SDavid du Colombier 	try_quick = 1;
2283e12c5d1SDavid du Colombier 	if (mode > 5) {
2293e12c5d1SDavid du Colombier 		mode -= 4;
2303e12c5d1SDavid du Colombier 		try_quick = 0;
2313e12c5d1SDavid du Colombier 		}
2323e12c5d1SDavid du Colombier 	leftright = 1;
2333e12c5d1SDavid du Colombier 	switch(mode) {
2343e12c5d1SDavid du Colombier 		case 0:
2353e12c5d1SDavid du Colombier 		case 1:
2363e12c5d1SDavid du Colombier 			ilim = ilim1 = -1;
2373e12c5d1SDavid du Colombier 			i = 18;
2383e12c5d1SDavid du Colombier 			ndigits = 0;
2393e12c5d1SDavid du Colombier 			break;
2403e12c5d1SDavid du Colombier 		case 2:
2413e12c5d1SDavid du Colombier 			leftright = 0;
2423e12c5d1SDavid du Colombier 			/* no break */
2433e12c5d1SDavid du Colombier 		case 4:
2443e12c5d1SDavid du Colombier 			if (ndigits <= 0)
2453e12c5d1SDavid du Colombier 				ndigits = 1;
2463e12c5d1SDavid du Colombier 			ilim = ilim1 = i = ndigits;
2473e12c5d1SDavid du Colombier 			break;
2483e12c5d1SDavid du Colombier 		case 3:
2493e12c5d1SDavid du Colombier 			leftright = 0;
2503e12c5d1SDavid du Colombier 			/* no break */
2513e12c5d1SDavid du Colombier 		case 5:
2523e12c5d1SDavid du Colombier 			i = ndigits + k + 1;
2533e12c5d1SDavid du Colombier 			ilim = i;
2543e12c5d1SDavid du Colombier 			ilim1 = i - 1;
2553e12c5d1SDavid du Colombier 			if (i <= 0)
2563e12c5d1SDavid du Colombier 				i = 1;
2573e12c5d1SDavid du Colombier 		}
2583e12c5d1SDavid du Colombier 	j = sizeof(unsigned long);
259*219b2ee8SDavid du Colombier 	for(result_k = 0; sizeof(Bigint) - sizeof(unsigned long) + j <= i;
2603e12c5d1SDavid du Colombier 		j <<= 1) result_k++;
2613e12c5d1SDavid du Colombier 	result = Balloc(result_k);
2623e12c5d1SDavid du Colombier 	s = s0 = (char *)result;
2633e12c5d1SDavid du Colombier 
2643e12c5d1SDavid du Colombier 	if (ilim >= 0 && ilim <= Quick_max && try_quick) {
2653e12c5d1SDavid du Colombier 
2663e12c5d1SDavid du Colombier 		/* Try to get by with floating-point arithmetic. */
2673e12c5d1SDavid du Colombier 
2683e12c5d1SDavid du Colombier 		i = 0;
2693e12c5d1SDavid du Colombier 		d2.d = d.d;
2703e12c5d1SDavid du Colombier 		k0 = k;
2713e12c5d1SDavid du Colombier 		ilim0 = ilim;
2723e12c5d1SDavid du Colombier 		ieps = 2; /* conservative */
2733e12c5d1SDavid du Colombier 		if (k > 0) {
2743e12c5d1SDavid du Colombier 			ds = tens[k&0xf];
2753e12c5d1SDavid du Colombier 			j = k >> 4;
2763e12c5d1SDavid du Colombier 			if (j & Bletch) {
2773e12c5d1SDavid du Colombier 				/* prevent overflows */
2783e12c5d1SDavid du Colombier 				j &= Bletch - 1;
2793e12c5d1SDavid du Colombier 				d.d /= bigtens[n_bigtens-1];
2803e12c5d1SDavid du Colombier 				ieps++;
2813e12c5d1SDavid du Colombier 				}
2823e12c5d1SDavid du Colombier 			for(; j; j >>= 1, i++)
2833e12c5d1SDavid du Colombier 				if (j & 1) {
2843e12c5d1SDavid du Colombier 					ieps++;
2853e12c5d1SDavid du Colombier 					ds *= bigtens[i];
2863e12c5d1SDavid du Colombier 					}
2873e12c5d1SDavid du Colombier 			d.d /= ds;
2883e12c5d1SDavid du Colombier 			}
2893e12c5d1SDavid du Colombier 		else if (j1 = -k) {
2903e12c5d1SDavid du Colombier 			d.d *= tens[j1 & 0xf];
2913e12c5d1SDavid du Colombier 			for(j = j1 >> 4; j; j >>= 1, i++)
2923e12c5d1SDavid du Colombier 				if (j & 1) {
2933e12c5d1SDavid du Colombier 					ieps++;
2943e12c5d1SDavid du Colombier 					d.d *= bigtens[i];
2953e12c5d1SDavid du Colombier 					}
2963e12c5d1SDavid du Colombier 			}
2973e12c5d1SDavid du Colombier 		if (k_check && d.d < 1. && ilim > 0) {
2983e12c5d1SDavid du Colombier 			if (ilim1 <= 0)
2993e12c5d1SDavid du Colombier 				goto fast_failed;
3003e12c5d1SDavid du Colombier 			ilim = ilim1;
3013e12c5d1SDavid du Colombier 			k--;
3023e12c5d1SDavid du Colombier 			d.d *= 10.;
3033e12c5d1SDavid du Colombier 			ieps++;
3043e12c5d1SDavid du Colombier 			}
3053e12c5d1SDavid du Colombier 		eps.d = ieps*d.d + 7.;
3063e12c5d1SDavid du Colombier 		word0(eps) -= (P-1)*Exp_msk1;
3073e12c5d1SDavid du Colombier 		if (ilim == 0) {
3083e12c5d1SDavid du Colombier 			S = mhi = 0;
3093e12c5d1SDavid du Colombier 			d.d -= 5.;
3103e12c5d1SDavid du Colombier 			if (d.d > eps.d)
3113e12c5d1SDavid du Colombier 				goto one_digit;
3123e12c5d1SDavid du Colombier 			if (d.d < -eps.d)
3133e12c5d1SDavid du Colombier 				goto no_digits;
3143e12c5d1SDavid du Colombier 			goto fast_failed;
3153e12c5d1SDavid du Colombier 			}
3163e12c5d1SDavid du Colombier #ifndef No_leftright
3173e12c5d1SDavid du Colombier 		if (leftright) {
3183e12c5d1SDavid du Colombier 			/* Use Steele & White method of only
3193e12c5d1SDavid du Colombier 			 * generating digits needed.
3203e12c5d1SDavid du Colombier 			 */
3213e12c5d1SDavid du Colombier 			eps.d = 0.5/tens[ilim-1] - eps.d;
3223e12c5d1SDavid du Colombier 			for(i = 0;;) {
3233e12c5d1SDavid du Colombier 				L = floor(d.d);
3243e12c5d1SDavid du Colombier 				d.d -= L;
3253e12c5d1SDavid du Colombier 				*s++ = '0' + (int)L;
3263e12c5d1SDavid du Colombier 				if (d.d < eps.d)
3273e12c5d1SDavid du Colombier 					goto ret1;
3283e12c5d1SDavid du Colombier 				if (1. - d.d < eps.d)
3293e12c5d1SDavid du Colombier 					goto bump_up;
3303e12c5d1SDavid du Colombier 				if (++i >= ilim)
3313e12c5d1SDavid du Colombier 					break;
3323e12c5d1SDavid du Colombier 				eps.d *= 10.;
3333e12c5d1SDavid du Colombier 				d.d *= 10.;
3343e12c5d1SDavid du Colombier 				}
3353e12c5d1SDavid du Colombier 			}
3363e12c5d1SDavid du Colombier 		else {
3373e12c5d1SDavid du Colombier #endif
3383e12c5d1SDavid du Colombier 			/* Generate ilim digits, then fix them up. */
3393e12c5d1SDavid du Colombier 			eps.d *= tens[ilim-1];
3403e12c5d1SDavid du Colombier 			for(i = 1;; i++, d.d *= 10.) {
3413e12c5d1SDavid du Colombier 				L = floor(d.d);
3423e12c5d1SDavid du Colombier 				d.d -= L;
3433e12c5d1SDavid du Colombier 				*s++ = '0' + (int)L;
3443e12c5d1SDavid du Colombier 				if (i == ilim) {
3453e12c5d1SDavid du Colombier 					if (d.d > 0.5 + eps.d)
3463e12c5d1SDavid du Colombier 						goto bump_up;
3473e12c5d1SDavid du Colombier 					else if (d.d < 0.5 - eps.d) {
3483e12c5d1SDavid du Colombier 						while(*--s == '0');
3493e12c5d1SDavid du Colombier 						s++;
3503e12c5d1SDavid du Colombier 						goto ret1;
3513e12c5d1SDavid du Colombier 						}
3523e12c5d1SDavid du Colombier 					break;
3533e12c5d1SDavid du Colombier 					}
3543e12c5d1SDavid du Colombier 				}
3553e12c5d1SDavid du Colombier #ifndef No_leftright
3563e12c5d1SDavid du Colombier 			}
3573e12c5d1SDavid du Colombier #endif
3583e12c5d1SDavid du Colombier  fast_failed:
3593e12c5d1SDavid du Colombier 		s = s0;
3603e12c5d1SDavid du Colombier 		d.d = d2.d;
3613e12c5d1SDavid du Colombier 		k = k0;
3623e12c5d1SDavid du Colombier 		ilim = ilim0;
3633e12c5d1SDavid du Colombier 		}
3643e12c5d1SDavid du Colombier 
3653e12c5d1SDavid du Colombier 	/* Do we have a "small" integer? */
3663e12c5d1SDavid du Colombier 
3673e12c5d1SDavid du Colombier 	if (be >= 0 && k <= Int_max) {
3683e12c5d1SDavid du Colombier 		/* Yes. */
3693e12c5d1SDavid du Colombier 		ds = tens[k];
3703e12c5d1SDavid du Colombier 		if (ndigits < 0 && ilim <= 0) {
3713e12c5d1SDavid du Colombier 			S = mhi = 0;
3723e12c5d1SDavid du Colombier 			if (ilim < 0 || d.d <= 5*ds)
3733e12c5d1SDavid du Colombier 				goto no_digits;
3743e12c5d1SDavid du Colombier 			goto one_digit;
3753e12c5d1SDavid du Colombier 			}
3763e12c5d1SDavid du Colombier 		for(i = 1;; i++) {
3773e12c5d1SDavid du Colombier 			L = floor(d.d / ds);
3783e12c5d1SDavid du Colombier 			d.d -= L*ds;
3793e12c5d1SDavid du Colombier #ifdef Check_FLT_ROUNDS
3803e12c5d1SDavid du Colombier 			/* If FLT_ROUNDS == 2, L will usually be high by 1 */
3813e12c5d1SDavid du Colombier 			if (d.d < 0) {
3823e12c5d1SDavid du Colombier 				L--;
3833e12c5d1SDavid du Colombier 				d.d += ds;
3843e12c5d1SDavid du Colombier 				}
3853e12c5d1SDavid du Colombier #endif
3863e12c5d1SDavid du Colombier 			*s++ = '0' + (int)L;
3873e12c5d1SDavid du Colombier 			if (i == ilim) {
3883e12c5d1SDavid du Colombier 				d.d += d.d;
3893e12c5d1SDavid du Colombier 				if (d.d > ds || d.d == ds && L & 1) {
3903e12c5d1SDavid du Colombier  bump_up:
3913e12c5d1SDavid du Colombier 					while(*--s == '9')
3923e12c5d1SDavid du Colombier 						if (s == s0) {
3933e12c5d1SDavid du Colombier 							k++;
3943e12c5d1SDavid du Colombier 							*s = '0';
3953e12c5d1SDavid du Colombier 							break;
3963e12c5d1SDavid du Colombier 							}
3973e12c5d1SDavid du Colombier 					++*s++;
3983e12c5d1SDavid du Colombier 					}
3993e12c5d1SDavid du Colombier 				break;
4003e12c5d1SDavid du Colombier 				}
4013e12c5d1SDavid du Colombier 			d.d *= 10.;
4023e12c5d1SDavid du Colombier 			if (d.d == 0.)
4033e12c5d1SDavid du Colombier 				break;
4043e12c5d1SDavid du Colombier 			}
4053e12c5d1SDavid du Colombier 		goto ret1;
4063e12c5d1SDavid du Colombier 		}
4073e12c5d1SDavid du Colombier 
4083e12c5d1SDavid du Colombier 	m2 = b2;
4093e12c5d1SDavid du Colombier 	m5 = b5;
4103e12c5d1SDavid du Colombier 	mhi = mlo = 0;
4113e12c5d1SDavid du Colombier 	if (leftright) {
4123e12c5d1SDavid du Colombier 		if (mode < 2) {
4133e12c5d1SDavid du Colombier 			i =
4143e12c5d1SDavid du Colombier #ifndef Sudden_Underflow
4153e12c5d1SDavid du Colombier 				denorm ? be + (Bias + (P-1) - 1 + 1) :
4163e12c5d1SDavid du Colombier #endif
4173e12c5d1SDavid du Colombier #ifdef IBM
4183e12c5d1SDavid du Colombier 				1 + 4*P - 3 - bbits + ((bbits + be - 1) & 3);
4193e12c5d1SDavid du Colombier #else
4203e12c5d1SDavid du Colombier 				1 + P - bbits;
4213e12c5d1SDavid du Colombier #endif
4223e12c5d1SDavid du Colombier 			}
4233e12c5d1SDavid du Colombier 		else {
4243e12c5d1SDavid du Colombier 			j = ilim - 1;
4253e12c5d1SDavid du Colombier 			if (m5 >= j)
4263e12c5d1SDavid du Colombier 				m5 -= j;
4273e12c5d1SDavid du Colombier 			else {
4283e12c5d1SDavid du Colombier 				s5 += j -= m5;
4293e12c5d1SDavid du Colombier 				b5 += j;
4303e12c5d1SDavid du Colombier 				m5 = 0;
4313e12c5d1SDavid du Colombier 				}
4323e12c5d1SDavid du Colombier 			if ((i = ilim) < 0) {
4333e12c5d1SDavid du Colombier 				m2 -= i;
4343e12c5d1SDavid du Colombier 				i = 0;
4353e12c5d1SDavid du Colombier 				}
4363e12c5d1SDavid du Colombier 			}
4373e12c5d1SDavid du Colombier 		b2 += i;
4383e12c5d1SDavid du Colombier 		s2 += i;
4393e12c5d1SDavid du Colombier 		mhi = i2b(1);
4403e12c5d1SDavid du Colombier 		}
4413e12c5d1SDavid du Colombier 	if (m2 > 0 && s2 > 0) {
4423e12c5d1SDavid du Colombier 		i = m2 < s2 ? m2 : s2;
4433e12c5d1SDavid du Colombier 		b2 -= i;
4443e12c5d1SDavid du Colombier 		m2 -= i;
4453e12c5d1SDavid du Colombier 		s2 -= i;
4463e12c5d1SDavid du Colombier 		}
4473e12c5d1SDavid du Colombier 	if (b5 > 0) {
4483e12c5d1SDavid du Colombier 		if (leftright) {
4493e12c5d1SDavid du Colombier 			if (m5 > 0) {
4503e12c5d1SDavid du Colombier 				mhi = pow5mult(mhi, m5);
4513e12c5d1SDavid du Colombier 				b1 = mult(mhi, b);
4523e12c5d1SDavid du Colombier 				Bfree(b);
4533e12c5d1SDavid du Colombier 				b = b1;
4543e12c5d1SDavid du Colombier 				}
4553e12c5d1SDavid du Colombier 			if (j = b5 - m5)
4563e12c5d1SDavid du Colombier 				b = pow5mult(b, j);
4573e12c5d1SDavid du Colombier 			}
4583e12c5d1SDavid du Colombier 		else
4593e12c5d1SDavid du Colombier 			b = pow5mult(b, b5);
4603e12c5d1SDavid du Colombier 		}
4613e12c5d1SDavid du Colombier 	S = i2b(1);
4623e12c5d1SDavid du Colombier 	if (s5 > 0)
4633e12c5d1SDavid du Colombier 		S = pow5mult(S, s5);
4643e12c5d1SDavid du Colombier 
4653e12c5d1SDavid du Colombier 	/* Check for special case that d is a normalized power of 2. */
4663e12c5d1SDavid du Colombier 
4673e12c5d1SDavid du Colombier 	if (mode < 2) {
4683e12c5d1SDavid du Colombier 		if (!word1(d) && !(word0(d) & Bndry_mask)
4693e12c5d1SDavid du Colombier #ifndef Sudden_Underflow
4703e12c5d1SDavid du Colombier 		 && word0(d) & Exp_mask
4713e12c5d1SDavid du Colombier #endif
4723e12c5d1SDavid du Colombier 				) {
4733e12c5d1SDavid du Colombier 			/* The special case */
4743e12c5d1SDavid du Colombier 			b2 += Log2P;
4753e12c5d1SDavid du Colombier 			s2 += Log2P;
4763e12c5d1SDavid du Colombier 			spec_case = 1;
4773e12c5d1SDavid du Colombier 			}
4783e12c5d1SDavid du Colombier 		else
4793e12c5d1SDavid du Colombier 			spec_case = 0;
4803e12c5d1SDavid du Colombier 		}
4813e12c5d1SDavid du Colombier 
4823e12c5d1SDavid du Colombier 	/* Arrange for convenient computation of quotients:
4833e12c5d1SDavid du Colombier 	 * shift left if necessary so divisor has 4 leading 0 bits.
4843e12c5d1SDavid du Colombier 	 *
4853e12c5d1SDavid du Colombier 	 * Perhaps we should just compute leading 28 bits of S once
4863e12c5d1SDavid du Colombier 	 * and for all and pass them and a shift to quorem, so it
4873e12c5d1SDavid du Colombier 	 * can do shifts and ors to compute the numerator for q.
4883e12c5d1SDavid du Colombier 	 */
4893e12c5d1SDavid du Colombier #ifdef Pack_32
4903e12c5d1SDavid du Colombier 	if (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f)
4913e12c5d1SDavid du Colombier 		i = 32 - i;
4923e12c5d1SDavid du Colombier #else
4933e12c5d1SDavid du Colombier 	if (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf)
4943e12c5d1SDavid du Colombier 		i = 16 - i;
4953e12c5d1SDavid du Colombier #endif
4963e12c5d1SDavid du Colombier 	if (i > 4) {
4973e12c5d1SDavid du Colombier 		i -= 4;
4983e12c5d1SDavid du Colombier 		b2 += i;
4993e12c5d1SDavid du Colombier 		m2 += i;
5003e12c5d1SDavid du Colombier 		s2 += i;
5013e12c5d1SDavid du Colombier 		}
5023e12c5d1SDavid du Colombier 	else if (i < 4) {
5033e12c5d1SDavid du Colombier 		i += 28;
5043e12c5d1SDavid du Colombier 		b2 += i;
5053e12c5d1SDavid du Colombier 		m2 += i;
5063e12c5d1SDavid du Colombier 		s2 += i;
5073e12c5d1SDavid du Colombier 		}
5083e12c5d1SDavid du Colombier 	if (b2 > 0)
5093e12c5d1SDavid du Colombier 		b = lshift(b, b2);
5103e12c5d1SDavid du Colombier 	if (s2 > 0)
5113e12c5d1SDavid du Colombier 		S = lshift(S, s2);
5123e12c5d1SDavid du Colombier 	if (k_check) {
5133e12c5d1SDavid du Colombier 		if (cmp(b,S) < 0) {
5143e12c5d1SDavid du Colombier 			k--;
5153e12c5d1SDavid du Colombier 			b = multadd(b, 10, 0);	/* we botched the k estimate */
5163e12c5d1SDavid du Colombier 			if (leftright)
5173e12c5d1SDavid du Colombier 				mhi = multadd(mhi, 10, 0);
5183e12c5d1SDavid du Colombier 			ilim = ilim1;
5193e12c5d1SDavid du Colombier 			}
5203e12c5d1SDavid du Colombier 		}
5213e12c5d1SDavid du Colombier 	if (ilim <= 0 && mode > 2) {
5223e12c5d1SDavid du Colombier 		if (ilim < 0 || cmp(b,S = multadd(S,5,0)) <= 0) {
5233e12c5d1SDavid du Colombier 			/* no digits, fcvt style */
5243e12c5d1SDavid du Colombier  no_digits:
5253e12c5d1SDavid du Colombier 			k = -1 - ndigits;
5263e12c5d1SDavid du Colombier 			goto ret;
5273e12c5d1SDavid du Colombier 			}
5283e12c5d1SDavid du Colombier  one_digit:
5293e12c5d1SDavid du Colombier 		*s++ = '1';
5303e12c5d1SDavid du Colombier 		k++;
5313e12c5d1SDavid du Colombier 		goto ret;
5323e12c5d1SDavid du Colombier 		}
5333e12c5d1SDavid du Colombier 	if (leftright) {
5343e12c5d1SDavid du Colombier 		if (m2 > 0)
5353e12c5d1SDavid du Colombier 			mhi = lshift(mhi, m2);
5363e12c5d1SDavid du Colombier 
5373e12c5d1SDavid du Colombier 		/* Compute mlo -- check for special case
5383e12c5d1SDavid du Colombier 		 * that d is a normalized power of 2.
5393e12c5d1SDavid du Colombier 		 */
5403e12c5d1SDavid du Colombier 
5413e12c5d1SDavid du Colombier 		mlo = mhi;
5423e12c5d1SDavid du Colombier 		if (spec_case) {
5433e12c5d1SDavid du Colombier 			mhi = Balloc(mhi->k);
5443e12c5d1SDavid du Colombier 			Bcopy(mhi, mlo);
5453e12c5d1SDavid du Colombier 			mhi = lshift(mhi, Log2P);
5463e12c5d1SDavid du Colombier 			}
5473e12c5d1SDavid du Colombier 
5483e12c5d1SDavid du Colombier 		for(i = 1;;i++) {
5493e12c5d1SDavid du Colombier 			dig = quorem(b,S) + '0';
5503e12c5d1SDavid du Colombier 			/* Do we yet have the shortest decimal string
5513e12c5d1SDavid du Colombier 			 * that will round to d?
5523e12c5d1SDavid du Colombier 			 */
5533e12c5d1SDavid du Colombier 			j = cmp(b, mlo);
5543e12c5d1SDavid du Colombier 			delta = diff(S, mhi);
5553e12c5d1SDavid du Colombier 			j1 = delta->sign ? 1 : cmp(b, delta);
5563e12c5d1SDavid du Colombier 			Bfree(delta);
5573e12c5d1SDavid du Colombier #ifndef ROUND_BIASED
5583e12c5d1SDavid du Colombier 			if (j1 == 0 && !mode && !(word1(d) & 1)) {
5593e12c5d1SDavid du Colombier 				if (dig == '9')
5603e12c5d1SDavid du Colombier 					goto round_9_up;
5613e12c5d1SDavid du Colombier 				if (j > 0)
5623e12c5d1SDavid du Colombier 					dig++;
5633e12c5d1SDavid du Colombier 				*s++ = dig;
5643e12c5d1SDavid du Colombier 				goto ret;
5653e12c5d1SDavid du Colombier 				}
5663e12c5d1SDavid du Colombier #endif
5673e12c5d1SDavid du Colombier 			if (j < 0 || j == 0 && !mode
5683e12c5d1SDavid du Colombier #ifndef ROUND_BIASED
5693e12c5d1SDavid du Colombier 							&& !(word1(d) & 1)
5703e12c5d1SDavid du Colombier #endif
5713e12c5d1SDavid du Colombier 					) {
5723e12c5d1SDavid du Colombier 				if (j1 > 0) {
5733e12c5d1SDavid du Colombier 					b = lshift(b, 1);
5743e12c5d1SDavid du Colombier 					j1 = cmp(b, S);
5753e12c5d1SDavid du Colombier 					if ((j1 > 0 || j1 == 0 && dig & 1)
5763e12c5d1SDavid du Colombier 					&& dig++ == '9')
5773e12c5d1SDavid du Colombier 						goto round_9_up;
5783e12c5d1SDavid du Colombier 					}
5793e12c5d1SDavid du Colombier 				*s++ = dig;
5803e12c5d1SDavid du Colombier 				goto ret;
5813e12c5d1SDavid du Colombier 				}
5823e12c5d1SDavid du Colombier 			if (j1 > 0) {
5833e12c5d1SDavid du Colombier 				if (dig == '9') { /* possible if i == 1 */
5843e12c5d1SDavid du Colombier  round_9_up:
5853e12c5d1SDavid du Colombier 					*s++ = '9';
5863e12c5d1SDavid du Colombier 					goto roundoff;
5873e12c5d1SDavid du Colombier 					}
5883e12c5d1SDavid du Colombier 				*s++ = dig + 1;
5893e12c5d1SDavid du Colombier 				goto ret;
5903e12c5d1SDavid du Colombier 				}
5913e12c5d1SDavid du Colombier 			*s++ = dig;
5923e12c5d1SDavid du Colombier 			if (i == ilim)
5933e12c5d1SDavid du Colombier 				break;
5943e12c5d1SDavid du Colombier 			b = multadd(b, 10, 0);
5953e12c5d1SDavid du Colombier 			if (mlo == mhi)
5963e12c5d1SDavid du Colombier 				mlo = mhi = multadd(mhi, 10, 0);
5973e12c5d1SDavid du Colombier 			else {
5983e12c5d1SDavid du Colombier 				mlo = multadd(mlo, 10, 0);
5993e12c5d1SDavid du Colombier 				mhi = multadd(mhi, 10, 0);
6003e12c5d1SDavid du Colombier 				}
6013e12c5d1SDavid du Colombier 			}
6023e12c5d1SDavid du Colombier 		}
6033e12c5d1SDavid du Colombier 	else
6043e12c5d1SDavid du Colombier 		for(i = 1;; i++) {
6053e12c5d1SDavid du Colombier 			*s++ = dig = quorem(b,S) + '0';
6063e12c5d1SDavid du Colombier 			if (i >= ilim)
6073e12c5d1SDavid du Colombier 				break;
6083e12c5d1SDavid du Colombier 			b = multadd(b, 10, 0);
6093e12c5d1SDavid du Colombier 			}
6103e12c5d1SDavid du Colombier 
6113e12c5d1SDavid du Colombier 	/* Round off last digit */
6123e12c5d1SDavid du Colombier 
6133e12c5d1SDavid du Colombier 	b = lshift(b, 1);
6143e12c5d1SDavid du Colombier 	j = cmp(b, S);
6153e12c5d1SDavid du Colombier 	if (j > 0 || j == 0 && dig & 1) {
6163e12c5d1SDavid du Colombier  roundoff:
6173e12c5d1SDavid du Colombier 		while(*--s == '9')
6183e12c5d1SDavid du Colombier 			if (s == s0) {
6193e12c5d1SDavid du Colombier 				k++;
6203e12c5d1SDavid du Colombier 				*s++ = '1';
6213e12c5d1SDavid du Colombier 				goto ret;
6223e12c5d1SDavid du Colombier 				}
6233e12c5d1SDavid du Colombier 		++*s++;
6243e12c5d1SDavid du Colombier 		}
6253e12c5d1SDavid du Colombier 	else {
6263e12c5d1SDavid du Colombier 		while(*--s == '0');
6273e12c5d1SDavid du Colombier 		s++;
6283e12c5d1SDavid du Colombier 		}
6293e12c5d1SDavid du Colombier  ret:
6303e12c5d1SDavid du Colombier 	Bfree(S);
6313e12c5d1SDavid du Colombier 	if (mhi) {
6323e12c5d1SDavid du Colombier 		if (mlo && mlo != mhi)
6333e12c5d1SDavid du Colombier 			Bfree(mlo);
6343e12c5d1SDavid du Colombier 		Bfree(mhi);
6353e12c5d1SDavid du Colombier 		}
6363e12c5d1SDavid du Colombier  ret1:
6373e12c5d1SDavid du Colombier 	Bfree(b);
6383e12c5d1SDavid du Colombier 	*s = 0;
6393e12c5d1SDavid du Colombier 	*decpt = k + 1;
6403e12c5d1SDavid du Colombier 	if (rve)
6413e12c5d1SDavid du Colombier 		*rve = s;
6423e12c5d1SDavid du Colombier 	return s0;
6433e12c5d1SDavid du Colombier 	}
6443e12c5d1SDavid du Colombier 
6453e12c5d1SDavid du Colombier  static int
quorem(Bigint * b,Bigint * S)6463e12c5d1SDavid du Colombier quorem(Bigint *b, Bigint *S)
6473e12c5d1SDavid du Colombier {
6483e12c5d1SDavid du Colombier 	int n;
6493e12c5d1SDavid du Colombier 	long borrow, y;
6503e12c5d1SDavid du Colombier 	unsigned long carry, q, ys;
6513e12c5d1SDavid du Colombier 	unsigned long *bx, *bxe, *sx, *sxe;
6523e12c5d1SDavid du Colombier #ifdef Pack_32
6533e12c5d1SDavid du Colombier 	long z;
6543e12c5d1SDavid du Colombier 	unsigned long si, zs;
6553e12c5d1SDavid du Colombier #endif
6563e12c5d1SDavid du Colombier 
6573e12c5d1SDavid du Colombier 	n = S->wds;
6583e12c5d1SDavid du Colombier #ifdef DEBUG
6593e12c5d1SDavid du Colombier 	/*debug*/ if (b->wds > n)
6603e12c5d1SDavid du Colombier 	/*debug*/	Bug("oversize b in quorem");
6613e12c5d1SDavid du Colombier #endif
6623e12c5d1SDavid du Colombier 	if (b->wds < n)
6633e12c5d1SDavid du Colombier 		return 0;
6643e12c5d1SDavid du Colombier 	sx = S->x;
6653e12c5d1SDavid du Colombier 	sxe = sx + --n;
6663e12c5d1SDavid du Colombier 	bx = b->x;
6673e12c5d1SDavid du Colombier 	bxe = bx + n;
6683e12c5d1SDavid du Colombier 	q = *bxe / (*sxe + 1);	/* ensure q <= true quotient */
6693e12c5d1SDavid du Colombier #ifdef DEBUG
6703e12c5d1SDavid du Colombier 	/*debug*/ if (q > 9)
6713e12c5d1SDavid du Colombier 	/*debug*/	Bug("oversized quotient in quorem");
6723e12c5d1SDavid du Colombier #endif
6733e12c5d1SDavid du Colombier 	if (q) {
6743e12c5d1SDavid du Colombier 		borrow = 0;
6753e12c5d1SDavid du Colombier 		carry = 0;
6763e12c5d1SDavid du Colombier 		do {
6773e12c5d1SDavid du Colombier #ifdef Pack_32
6783e12c5d1SDavid du Colombier 			si = *sx++;
6793e12c5d1SDavid du Colombier 			ys = (si & 0xffff) * q + carry;
6803e12c5d1SDavid du Colombier 			zs = (si >> 16) * q + (ys >> 16);
6813e12c5d1SDavid du Colombier 			carry = zs >> 16;
6823e12c5d1SDavid du Colombier 			y = (*bx & 0xffff) - (ys & 0xffff) + borrow;
6833e12c5d1SDavid du Colombier 			borrow = y >> 16;
6843e12c5d1SDavid du Colombier 			Sign_Extend(borrow, y);
6853e12c5d1SDavid du Colombier 			z = (*bx >> 16) - (zs & 0xffff) + borrow;
6863e12c5d1SDavid du Colombier 			borrow = z >> 16;
6873e12c5d1SDavid du Colombier 			Sign_Extend(borrow, z);
6883e12c5d1SDavid du Colombier 			Storeinc(bx, z, y);
6893e12c5d1SDavid du Colombier #else
6903e12c5d1SDavid du Colombier 			ys = *sx++ * q + carry;
6913e12c5d1SDavid du Colombier 			carry = ys >> 16;
6923e12c5d1SDavid du Colombier 			y = *bx - (ys & 0xffff) + borrow;
6933e12c5d1SDavid du Colombier 			borrow = y >> 16;
6943e12c5d1SDavid du Colombier 			Sign_Extend(borrow, y);
6953e12c5d1SDavid du Colombier 			*bx++ = y & 0xffff;
6963e12c5d1SDavid du Colombier #endif
6973e12c5d1SDavid du Colombier 			}
6983e12c5d1SDavid du Colombier 			while(sx <= sxe);
6993e12c5d1SDavid du Colombier 		if (!*bxe) {
7003e12c5d1SDavid du Colombier 			bx = b->x;
7013e12c5d1SDavid du Colombier 			while(--bxe > bx && !*bxe)
7023e12c5d1SDavid du Colombier 				--n;
7033e12c5d1SDavid du Colombier 			b->wds = n;
7043e12c5d1SDavid du Colombier 			}
7053e12c5d1SDavid du Colombier 		}
7063e12c5d1SDavid du Colombier 	if (cmp(b, S) >= 0) {
7073e12c5d1SDavid du Colombier 		q++;
7083e12c5d1SDavid du Colombier 		borrow = 0;
7093e12c5d1SDavid du Colombier 		carry = 0;
7103e12c5d1SDavid du Colombier 		bx = b->x;
7113e12c5d1SDavid du Colombier 		sx = S->x;
7123e12c5d1SDavid du Colombier 		do {
7133e12c5d1SDavid du Colombier #ifdef Pack_32
7143e12c5d1SDavid du Colombier 			si = *sx++;
7153e12c5d1SDavid du Colombier 			ys = (si & 0xffff) + carry;
7163e12c5d1SDavid du Colombier 			zs = (si >> 16) + (ys >> 16);
7173e12c5d1SDavid du Colombier 			carry = zs >> 16;
7183e12c5d1SDavid du Colombier 			y = (*bx & 0xffff) - (ys & 0xffff) + borrow;
7193e12c5d1SDavid du Colombier 			borrow = y >> 16;
7203e12c5d1SDavid du Colombier 			Sign_Extend(borrow, y);
7213e12c5d1SDavid du Colombier 			z = (*bx >> 16) - (zs & 0xffff) + borrow;
7223e12c5d1SDavid du Colombier 			borrow = z >> 16;
7233e12c5d1SDavid du Colombier 			Sign_Extend(borrow, z);
7243e12c5d1SDavid du Colombier 			Storeinc(bx, z, y);
7253e12c5d1SDavid du Colombier #else
7263e12c5d1SDavid du Colombier 			ys = *sx++ + carry;
7273e12c5d1SDavid du Colombier 			carry = ys >> 16;
7283e12c5d1SDavid du Colombier 			y = *bx - (ys & 0xffff) + borrow;
7293e12c5d1SDavid du Colombier 			borrow = y >> 16;
7303e12c5d1SDavid du Colombier 			Sign_Extend(borrow, y);
7313e12c5d1SDavid du Colombier 			*bx++ = y & 0xffff;
7323e12c5d1SDavid du Colombier #endif
7333e12c5d1SDavid du Colombier 			}
7343e12c5d1SDavid du Colombier 			while(sx <= sxe);
7353e12c5d1SDavid du Colombier 		bx = b->x;
7363e12c5d1SDavid du Colombier 		bxe = bx + n;
7373e12c5d1SDavid du Colombier 		if (!*bxe) {
7383e12c5d1SDavid du Colombier 			while(--bxe > bx && !*bxe)
7393e12c5d1SDavid du Colombier 				--n;
7403e12c5d1SDavid du Colombier 			b->wds = n;
7413e12c5d1SDavid du Colombier 			}
7423e12c5d1SDavid du Colombier 		}
7433e12c5d1SDavid du Colombier 	return q;
7443e12c5d1SDavid du Colombier 	}
745