Ejemplo n.º 1
0
static int reduce_trig_arg(int expDiff, int &zSign, Bit64u &aSig0, Bit64u &aSig1)
{
    Bit64u term0, term1, q = 0;

    if (expDiff < 0) {
        shift128Right(aSig0, 0, 1, &aSig0, &aSig1);
        expDiff = 0;
    }
    if (expDiff > 0) {
        q = argument_reduction_kernel(aSig0, expDiff, &aSig0, &aSig1);
    }
    else {
        if (FLOAT_PI_HI <= aSig0) {
            aSig0 -= FLOAT_PI_HI;
            q = 1;
        }
    }

    shift128Right(FLOAT_PI_HI, FLOAT_PI_LO, 1, &term0, &term1);
    if (! lt128(aSig0, aSig1, term0, term1))
    {
        int lt = lt128(term0, term1, aSig0, aSig1);
        int eq = eq128(aSig0, aSig1, term0, term1);
              
        if ((eq && (q & 1)) || lt) {
            zSign = !zSign;
            ++q;
        }
        if (lt) sub128(FLOAT_PI_HI, FLOAT_PI_LO, aSig0, aSig1, &aSig0, &aSig1);
    }

    return (int)(q & 3);
}
Ejemplo n.º 2
0
void
float128_rem ()
{
  signed int expDiff;
  long long int aSig1;
  long long int sigMean1;
  if (-64 < expDiff)
    shift128Right (-expDiff, &aSig1);
  add128 (&sigMean1);
}
Ejemplo n.º 3
0
static floatx80 fyl2x(floatx80 a, floatx80 b)
{
    UINT64 aSig = extractFloatx80Frac(a);
    INT32 aExp = extractFloatx80Exp(a);
    int aSign = extractFloatx80Sign(a);
    UINT64 bSig = extractFloatx80Frac(b);
    INT32 bExp = extractFloatx80Exp(b);
    int bSign = extractFloatx80Sign(b);

    int zSign = bSign ^ 1;

    if (aExp == 0x7FFF) {
        if ((UINT64) (aSig<<1)
             || ((bExp == 0x7FFF) && (UINT64) (bSig<<1)))
        {
            return propagateFloatx80NaN(a, b);
        }
        if (aSign)
        {
invalid:
			float_raise(float_flag_invalid);
			return floatx80_default_nan;
    	}
        else {
            if (bExp == 0) {
                if (bSig == 0) goto invalid;
                float_raise(float_flag_denormal);
            }
            return packFloatx80(bSign, 0x7FFF, U64(0x8000000000000000));
        }
    }
    if (bExp == 0x7FFF)
    {
        if ((UINT64) (bSig<<1)) return propagateFloatx80NaN(a, b);
        if (aSign && (UINT64)(aExp | aSig)) goto invalid;
        if (aSig && (aExp == 0))
            float_raise(float_flag_denormal);
        if (aExp < 0x3FFF) {
            return packFloatx80(zSign, 0x7FFF, U64(0x8000000000000000));
        }
        if (aExp == 0x3FFF && ((UINT64) (aSig<<1) == 0)) goto invalid;
        return packFloatx80(bSign, 0x7FFF, U64(0x8000000000000000));
    }
    if (aExp == 0) {
        if (aSig == 0) {
            if ((bExp | bSig) == 0) goto invalid;
            float_raise(float_flag_divbyzero);
            return packFloatx80(zSign, 0x7FFF, U64(0x8000000000000000));
        }
        if (aSign) goto invalid;
        float_raise(float_flag_denormal);
        normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
    }
    if (aSign) goto invalid;
    if (bExp == 0) {
        if (bSig == 0) {
            if (aExp < 0x3FFF) return packFloatx80(zSign, 0, 0);
            return packFloatx80(bSign, 0, 0);
        }
        float_raise(float_flag_denormal);
        normalizeFloatx80Subnormal(bSig, &bExp, &bSig);
    }
    if (aExp == 0x3FFF && ((UINT64) (aSig<<1) == 0))
        return packFloatx80(bSign, 0, 0);

    float_raise(float_flag_inexact);

    int ExpDiff = aExp - 0x3FFF;
    aExp = 0;
    if (aSig >= SQRT2_HALF_SIG) {
        ExpDiff++;
        aExp--;
    }

    /* ******************************** */
    /* using float128 for approximation */
    /* ******************************** */

    UINT64 zSig0, zSig1;
    shift128Right(aSig<<1, 0, 16, &zSig0, &zSig1);
    float128 x = packFloat128(0, aExp+0x3FFF, zSig0, zSig1);
    x = poly_l2(x);
    x = float128_add(x, int64_to_float128((INT64) ExpDiff));
    return floatx80_mul(b, float128_to_floatx80(x));
}
Ejemplo n.º 4
0
floatx80 fyl2xp1(floatx80 a, floatx80 b)
{
    INT32 aExp, bExp;
    UINT64 aSig, bSig, zSig0, zSig1, zSig2;
    int aSign, bSign;

    aSig = extractFloatx80Frac(a);
    aExp = extractFloatx80Exp(a);
    aSign = extractFloatx80Sign(a);
    bSig = extractFloatx80Frac(b);
    bExp = extractFloatx80Exp(b);
    bSign = extractFloatx80Sign(b);
    int zSign = aSign ^ bSign;

    if (aExp == 0x7FFF) {
        if ((UINT64) (aSig<<1)
             || ((bExp == 0x7FFF) && (UINT64) (bSig<<1)))
        {
            return propagateFloatx80NaN(a, b);
        }
        if (aSign)
        {
invalid:
			float_raise(float_flag_invalid);
			return floatx80_default_nan;
    	}
         else {
            if (bExp == 0) {
                if (bSig == 0) goto invalid;
                float_raise(float_flag_denormal);
            }
            return packFloatx80(bSign, 0x7FFF, U64(0x8000000000000000));
        }
    }
    if (bExp == 0x7FFF)
    {
        if ((UINT64) (bSig<<1))
            return propagateFloatx80NaN(a, b);

        if (aExp == 0) {
            if (aSig == 0) goto invalid;
            float_raise(float_flag_denormal);
        }

        return packFloatx80(zSign, 0x7FFF, U64(0x8000000000000000));
    }
    if (aExp == 0) {
        if (aSig == 0) {
            if (bSig && (bExp == 0)) float_raise(float_flag_denormal);
            return packFloatx80(zSign, 0, 0);
        }
        float_raise(float_flag_denormal);
        normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
    }
    if (bExp == 0) {
        if (bSig == 0) return packFloatx80(zSign, 0, 0);
        float_raise(float_flag_denormal);
        normalizeFloatx80Subnormal(bSig, &bExp, &bSig);
    }

    float_raise(float_flag_inexact);

    if (aSign && aExp >= 0x3FFF)
        return a;

    if (aExp >= 0x3FFC) // big argument
    {
        return fyl2x(floatx80_add(a, floatx80_one), b);
    }

    // handle tiny argument
    if (aExp < EXP_BIAS-70)
    {
        // first order approximation, return (a*b)/ln(2)
        INT32 zExp = aExp + FLOAT_LN2INV_EXP - 0x3FFE;

	mul128By64To192(FLOAT_LN2INV_HI, FLOAT_LN2INV_LO, aSig, &zSig0, &zSig1, &zSig2);
        if (0 < (INT64) zSig0) {
            shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1);
            --zExp;
        }

        zExp = zExp + bExp - 0x3FFE;
	mul128By64To192(zSig0, zSig1, bSig, &zSig0, &zSig1, &zSig2);
        if (0 < (INT64) zSig0) {
            shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1);
            --zExp;
        }

        return
            roundAndPackFloatx80(80, aSign ^ bSign, zExp, zSig0, zSig1);
    }

    /* ******************************** */
    /* using float128 for approximation */
    /* ******************************** */

    shift128Right(aSig<<1, 0, 16, &zSig0, &zSig1);
    float128 x = packFloat128(aSign, aExp, zSig0, zSig1);
    x = poly_l2p1(x);
    return floatx80_mul(b, float128_to_floatx80(x));
}
Ejemplo n.º 5
0
static floatx80 do_fprem(floatx80 a, floatx80 b, Bit64u &q, int rounding_mode, float_status_t &status)
{
    Bit32s aExp, bExp, zExp, expDiff;
    Bit64u aSig0, aSig1, bSig;
    int aSign;
    q = 0;

    // handle unsupported extended double-precision floating encodings
    if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b))
    {
        float_raise(status, float_flag_invalid);
        return floatx80_default_nan;
    }

    aSig0 = extractFloatx80Frac(a);
    aExp = extractFloatx80Exp(a);
    aSign = extractFloatx80Sign(a);
    bSig = extractFloatx80Frac(b);
    bExp = extractFloatx80Exp(b);

    if (aExp == 0x7FFF) {
        if ((Bit64u) (aSig0<<1)
                || ((bExp == 0x7FFF) && (Bit64u) (bSig<<1)))
        {
            return propagateFloatx80NaN(a, b, status);
        }
        goto invalid;
    }
    if (bExp == 0x7FFF) {
        if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b, status);
        return a;
    }
    if (bExp == 0) {
        if (bSig == 0) {
invalid:
            float_raise(status, float_flag_invalid);
            return floatx80_default_nan;
        }
        float_raise(status, float_flag_denormal);
        normalizeFloatx80Subnormal(bSig, &bExp, &bSig);
    }
    if (aExp == 0) {
        if ((Bit64u) (aSig0<<1) == 0) return a;
        float_raise(status, float_flag_denormal);
        normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0);
    }
    expDiff = aExp - bExp;
    aSig1 = 0;

    if (expDiff >= 64) {
        int n = (expDiff & 0x1f) | 0x20;
        remainder_kernel(aSig0, bSig, n, &aSig0, &aSig1);
        zExp = aExp - n;
        q = (Bit64u) -1;
    }
    else {
        zExp = bExp;

        if (expDiff < 0) {
            if (expDiff < -1)
                return (a.fraction & BX_CONST64(0x8000000000000000)) ?
                       packFloatx80(aSign, aExp, aSig0) : a;
            shift128Right(aSig0, 0, 1, &aSig0, &aSig1);
            expDiff = 0;
        }

        if (expDiff > 0) {
            q = remainder_kernel(aSig0, bSig, expDiff, &aSig0, &aSig1);
        }
        else {
            if (bSig <= aSig0) {
                aSig0 -= bSig;
                q = 1;
            }
        }

        if (rounding_mode == float_round_nearest_even)
        {
            Bit64u term0, term1;
            shift128Right(bSig, 0, 1, &term0, &term1);

            if (! lt128(aSig0, aSig1, term0, term1))
            {
                int lt = lt128(term0, term1, aSig0, aSig1);
                int eq = eq128(aSig0, aSig1, term0, term1);

                if ((eq && (q & 1)) || lt) {
                    aSign = !aSign;
                    ++q;
                }
                if (lt) sub128(bSig, 0, aSig0, aSig1, &aSig0, &aSig1);
            }
        }
    }

    return normalizeRoundAndPackFloatx80(80, aSign, zExp, aSig0, aSig1, status);
}