⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 floatconv.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
                        ys = (si & 0xffff) * q + carry;                        zs = (si >> 16) * q + (ys >> 16);                        carry = zs >> 16;                        y = (*bx & 0xffff) - (ys & 0xffff) + borrow;                        borrow = y >> 16;                        Sign_Extend(borrow, y);                        z = (*bx >> 16) - (zs & 0xffff) + borrow;                        borrow = z >> 16;                        Sign_Extend(borrow, z);                        Storeinc(bx, z, y);#else                        ys = *sx++ * q + carry;                        carry = ys >> 16;                        y = *bx - (ys & 0xffff) + borrow;                        borrow = y >> 16;                        Sign_Extend(borrow, y);                        *bx++ = y & 0xffff;#endif                        }                        while(sx <= sxe);                if (!*bxe) {                        bx = b->x;                        while(--bxe > bx && !*bxe)                                --n;                        b->wds = n;                        }                }        if (cmp(b, S) >= 0) {                q++;                borrow = 0;                carry = 0;                bx = b->x;                sx = S->x;                do {#ifdef Pack_32                        si = *sx++;                        ys = (si & 0xffff) + carry;                        zs = (si >> 16) + (ys >> 16);                        carry = zs >> 16;                        y = (*bx & 0xffff) - (ys & 0xffff) + borrow;                        borrow = y >> 16;                        Sign_Extend(borrow, y);                        z = (*bx >> 16) - (zs & 0xffff) + borrow;                        borrow = z >> 16;                        Sign_Extend(borrow, z);                        Storeinc(bx, z, y);#else                        ys = *sx++ + carry;                        carry = ys >> 16;                        y = *bx - (ys & 0xffff) + borrow;                        borrow = y >> 16;                        Sign_Extend(borrow, y);                        *bx++ = y & 0xffff;#endif                        }                        while(sx <= sxe);                bx = b->x;                bxe = bx + n;                if (!*bxe) {                        while(--bxe > bx && !*bxe)                                --n;                        b->wds = n;                        }                }        return q;        }/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string. * * Inspired by "How to Print Floating-Point Numbers Accurately" by * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 92-101]. * * Modifications: *      1. Rather than iterating, we use a simple numeric overestimate *         to determine k = floor(log10(d)).  We scale relevant *         quantities using O(log2(k)) rather than O(k) multiplications. *      2. For some modes > 2 (corresponding to ecvt and fcvt), we don't *         try to generate digits strictly left to right.  Instead, we *         compute with fewer bits and propagate the carry if necessary *         when rounding the final digit up.  This is often faster. *      3. Under the assumption that input will be rounded nearest, *         mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22. *         That is, we allow equality in stopping tests when the *         round-nearest rule will give the same floating-point value *         as would satisfaction of the stopping test with strict *         inequality. *      4. We remove common factors of powers of 2 from relevant *         quantities. *      5. When converting floating-point integers less than 1e16, *         we use floating-point arithmetic rather than resorting *         to multiple-precision integers. *      6. When asked to produce fewer than 15 digits, we first try *         to get by with floating-point arithmetic; we resort to *         multiple-precision integer arithmetic only if we cannot *         guarantee that the floating-point calculation has given *         the correctly rounded result.  For k requested digits and *         "uniformly" distributed input, the probability is *         something like 10^(k-15) that we must resort to the long *         calculation. */ char *dtoa#ifdef KR_headers        (d, mode, ndigits, decpt, sign, rve)        double d; int mode, ndigits, *decpt, *sign; char **rve;#else        (double d, int mode, int ndigits, int *decpt, int *sign, char **rve)#endif{ /*     Arguments ndigits, decpt, sign are similar to those        of ecvt and fcvt; trailing zeros are suppressed from        the returned string.  If not null, *rve is set to point        to the end of the return value.  If d is +-Infinity or NaN,        then *decpt is set to 9999.        mode:                0 ==> shortest string that yields d when read in                        and rounded to nearest.                1 ==> like 0, but with Steele & White stopping rule;                        e.g. with IEEE P754 arithmetic , mode 0 gives                        1e23 whereas mode 1 gives 9.999999999999999e22.                2 ==> max(1,ndigits) significant digits.  This gives a                        return value similar to that of ecvt, except                        that trailing zeros are suppressed.                3 ==> through ndigits past the decimal point.  This                        gives a return value similar to that from fcvt,                        except that trailing zeros are suppressed, and                        ndigits can be negative.                4-9 should give the same return values as 2-3, i.e.,                        4 <= mode <= 9 ==> same return as mode                        2 + (mode & 1).  These modes are mainly for                        debugging; often they run slower but sometimes                        faster than modes 2-3.                4,5,8,9 ==> left-to-right digit generation.                6-9 ==> don't try fast floating-point estimate                        (if applicable).                Values of mode other than 0-9 are treated as mode 0.                Sufficient space is allocated to the return value                to hold the suppressed trailing zeros.        */        int bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1,                j, j1, k, k0, k_check, leftright, m2, m5, s2, s5,                spec_case, try_quick;        long L;#ifndef Sudden_Underflow        int denorm;        unsigned long x;#endif        Bigint *b, *b1, *delta, *mlo, *mhi, *S;        double d2, ds, eps;        char *s, *s0;        static Bigint *result;        static int result_k;	TEST_ENDIANNESS;        if (result) {                result->k = result_k;                result->maxwds = 1 << result_k;                Bfree(result);                result = 0;                }        if (word0(d) & Sign_bit) {                /* set sign for everything, including 0's and NaNs */                *sign = 1;                word0(d) &= ~Sign_bit;  /* clear sign bit */                }        else                *sign = 0;#if defined(IEEE_Arith) + defined(VAX)#ifdef IEEE_Arith        if ((word0(d) & Exp_mask) == Exp_mask)#else        if (word0(d)  == 0x8000)#endif                {                /* Infinity or NaN */                *decpt = 9999;                s =#ifdef IEEE_Arith                        !word1(d) && !(word0(d) & 0xfffff) ? "Infinity" :#endif                                "NaN";                if (rve)                        *rve =#ifdef IEEE_Arith                                s[3] ? s + 8 :#endif                                                s + 3;                return s;                }#endif#ifdef IBM        d += 0; /* normalize */#endif        if (!d) {                *decpt = 1;                s = "0";                if (rve)                        *rve = s + 1;                return s;                }        b = d2b(d, &be, &bbits);#ifdef Sudden_Underflow        i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1));#else        if (i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1))) {#endif                d2 = d;                word0(d2) &= Frac_mask1;                word0(d2) |= Exp_11;#ifdef IBM                if (j = 11 - hi0bits(word0(d2) & Frac_mask))                        d2 /= 1 << j;#endif                /* log(x)       ~=~ log(1.5) + (x-1.5)/1.5                 * log10(x)      =  log(x) / log(10)                 *              ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))                 * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2)                 *                 * This suggests computing an approximation k to log10(d) by                 *                 * k = (i - Bias)*0.301029995663981                 *      + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );                 *                 * We want k to be too large rather than too small.                 * The error in the first-order Taylor series approximation                 * is in our favor, so we just round up the constant enough                 * to compensate for any error in the multiplication of                 * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077,                 * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14,                 * adding 1e-13 to the constant term more than suffices.                 * Hence we adjust the constant term to 0.1760912590558.                 * (We could get a more accurate k by invoking log10,                 *  but this is probably not worthwhile.)                 */                i -= Bias;#ifdef IBM                i <<= 2;                i += j;#endif#ifndef Sudden_Underflow                denorm = 0;                }        else {                /* d is denormalized */                i = bbits + be + (Bias + (P-1) - 1);                x = i > 32  ? word0(d) << 64 - i | word1(d) >> i - 32                            : word1(d) << 32 - i;                d2 = x;                word0(d2) -= 31*Exp_msk1; /* adjust exponent */                i -= (Bias + (P-1) - 1) + 1;                denorm = 1;                }#endif        ds = (d2-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;        k = (int)ds;        if (ds < 0. && ds != k)                k--;    /* want k = floor(ds) */        k_check = 1;        if (k >= 0 && k <= Ten_pmax) {                if (d < tens[k])                        k--;                k_check = 0;                }        j = bbits - i - 1;        if (j >= 0) {                b2 = 0;                s2 = j;                }        else {                b2 = -j;                s2 = 0;                }        if (k >= 0) {                b5 = 0;                s5 = k;                s2 += k;                }        else {                b2 -= k;                b5 = -k;                s5 = 0;                }        if (mode < 0 || mode > 9)                mode = 0;        try_quick = 1;        if (mode > 5) {                mode -= 4;                try_quick = 0;                }        leftright = 1;        switch(mode) {                case 0:                case 1:                        ilim = ilim1 = -1;                        i = 18;                        ndigits = 0;                        break;                case 2:                        leftright = 0;                        /* no break */                case 4:                        if (ndigits <= 0)                                ndigits = 1;                        ilim = ilim1 = i = ndigits;                        break;                case 3:                        leftright = 0;                        /* no break */                case 5:                        i = ndigits + k + 1;                        ilim = i;                        ilim1 = i - 1;                        if (i <= 0)                                i = 1;                }        j = sizeof(unsigned long);        for(result_k = 0; sizeof(Bigint) - sizeof(unsigned long) + j < i;                j <<= 1) result_k++;        result = Balloc(result_k);        s = s0 = (char *)result;        if (ilim >= 0 && ilim <= Quick_max && try_quick) {                /* Try to get by with floating-point arithmetic. */                i = 0;                d2 = d;                k0 = k;                ilim0 = ilim;                ieps = 2; /* conservative */                if (k > 0) {                        ds = tens[k&0xf];                        j = k >> 4;                        if (j & Bletch) {                                /* prevent overflows */                                j &= Bletch - 1;                                d /= bigtens[n_bigtens-1];                                ieps++;                                }                        for(; j; j >>= 1, i++)                                if (j & 1) {                                        ieps++;                                        ds *= bigtens[i];                                        }                        d /= ds;                        }                else if (j1 = -k) {                        d *= tens[j1 & 0xf];                        for(j = j1 >> 4; j; j >>= 1, i++)                                if (j & 1) {                                        ieps++;                                        d *= bigtens[i];                                        }                        }                if (k_check && d < 1. && ilim > 0) {                        if (ilim1 <= 0)                                goto fast_failed;                        ilim = ilim1;                        k--;                        d *= 10.;                        ieps++;                        }                eps = ieps*d + 7.;                word0(eps) -= (P-1)*Exp_msk1;                if (ilim == 0) {                        S = mhi = 0;                        d -= 5.;                        if (d > eps)                                goto one_digit;                        if (d < -eps)                                goto no_digits;                        goto fast_failed;                        }#ifndef No_leftright                if (leftright) {                        /* Use Steele & White method of only                         * generating digits needed.                         */                        eps = 0.5/tens[ilim-1] - eps;                        for(i = 0;;) {                                L = (long)d;                                d -= L;                                *s++ = '0' + (int)L;                                if (d < eps)                                        goto ret1;                                if (1. - d < eps)                                        goto bump_up;                                if (++i >= ilim)                                        break;                                eps *= 10.;                                d *= 10.;                                }                        }                else {#endif                        /* Generate ilim digits, then fix them up. */                        eps *= tens[ilim-1];                        for(i = 1;; i++, d *= 10.) {                                L = (long)d;                                d -= L;                                *s++ = '0' + (int)L;                                if (i == ilim) {                                        if (d > 0.5 + eps)                                                goto bump_up;                                        else if (d < 0.5 - eps) {                   

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -