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