Exemple #1
0
float128 EvalPoly(float128 x, float128 *arr, unsigned n)
{
	float128 x2 = float128_mul(x, x);
	unsigned i;

	assert(n > 1);

	float128 r1 = arr[--n];
	i = n;
	while(i >= 2) {
		r1 = float128_mul(r1, x2);
		i -= 2;
		r1 = float128_add(r1, arr[i]);
	}
	if (i) r1 = float128_mul(r1, x);

	float128 r2 = arr[--n];
	i = n;
	while(i >= 2) {
		r2 = float128_mul(r2, x2);
		i -= 2;
		r2 = float128_add(r2, arr[i]);
	}
	if (i) r2 = float128_mul(r2, x);

	return float128_add(r1, r2);
}
Exemple #2
0
long_double __mulxf3(long_double A, long_double B)
{
#if __SIZEOF_LONG_DOUBLE__ == 12
	return floatx80_mul(A, B);
#else
	return float128_mul(A, B);
#endif
}
Exemple #3
0
static float128 poly_l2p1(float128 x)
{
    /* using float128 for approximation */
    float128 x_p2 = float128_add(x, float128_two);
    x = float128_div(x, x_p2);
    x = poly_ln(x);
    x = float128_mul(x, float128_ln2inv2);
    return x;
}
Exemple #4
0
/* required sqrt(2)/2 < x < sqrt(2) */
static float128 poly_l2(float128 x)
{
    /* using float128 for approximation */
    float128 x_p1 = float128_add(x, float128_one);
    float128 x_m1 = float128_sub(x, float128_one);
    x = float128_div(x_m1, x_p1);
    x = poly_ln(x);
    x = float128_mul(x, float128_ln2inv2);
    return x;
}
Exemple #5
0
/* 128-bit FP multiplication RR */
void HELPER(mxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
{
    CPU_QuadU v1;
    CPU_QuadU v2;
    CPU_QuadU res;

    v1.ll.upper = env->fregs[f1].ll;
    v1.ll.lower = env->fregs[f1 + 2].ll;
    v2.ll.upper = env->fregs[f2].ll;
    v2.ll.lower = env->fregs[f2 + 2].ll;
    res.q = float128_mul(v1.q, v2.q, &env->fpu_status);
    env->fregs[f1].ll = res.ll.upper;
    env->fregs[f1 + 2].ll = res.ll.lower;
}
Exemple #6
0
float128 OddPoly(float128 x, float128 *arr, unsigned n)
{
		return float128_mul(x, EvenPoly(x, arr, n));
}
Exemple #7
0
float128 EvenPoly(float128 x, float128 *arr, unsigned n)
{
		return EvalPoly(float128_mul(x, x), arr, n);
}
Exemple #8
0
floatx80 fpatan(floatx80 a, floatx80 b, float_status_t &status)
{
    // 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;
    }

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

    int zSign = aSign ^ bSign;

    if (bExp == 0x7FFF)
    {
        if ((Bit64u) (bSig<<1))
            return propagateFloatx80NaN(a, b, status);

        if (aExp == 0x7FFF) {
            if ((Bit64u) (aSig<<1))
                return propagateFloatx80NaN(a, b, status);

            if (aSign) {   /* return 3PI/4 */
                return roundAndPackFloatx80(80, bSign,
                        FLOATX80_3PI4_EXP, FLOAT_3PI4_HI, FLOAT_3PI4_LO, status);
            }
            else {         /* return  PI/4 */
                return roundAndPackFloatx80(80, bSign,
                        FLOATX80_PI4_EXP, FLOAT_PI_HI, FLOAT_PI_LO, status);
            }
        }

        if (aSig && (aExp == 0))
            float_raise(status, float_flag_denormal);

        /* return PI/2 */
        return roundAndPackFloatx80(80, bSign, FLOATX80_PI2_EXP, FLOAT_PI_HI, FLOAT_PI_LO, status);
    }
    if (aExp == 0x7FFF)
    {
        if ((Bit64u) (aSig<<1))
            return propagateFloatx80NaN(a, b, status);

        if (bSig && (bExp == 0))
            float_raise(status, float_flag_denormal);

return_PI_or_ZERO:

        if (aSign) {   /* return PI */
            return roundAndPackFloatx80(80, bSign, FLOATX80_PI_EXP, FLOAT_PI_HI, FLOAT_PI_LO, status);
        } else {       /* return  0 */
            return packFloatx80(bSign, 0, 0);
        }
    }
    if (bExp == 0)
    {
        if (bSig == 0) {
             if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal);
             goto return_PI_or_ZERO;
        }

        float_raise(status, float_flag_denormal);
        normalizeFloatx80Subnormal(bSig, &bExp, &bSig);
    }
    if (aExp == 0)
    {
        if (aSig == 0)   /* return PI/2 */
            return roundAndPackFloatx80(80, bSign, FLOATX80_PI2_EXP, FLOAT_PI_HI, FLOAT_PI_LO, status);

        float_raise(status, float_flag_denormal);
        normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
    }

    float_raise(status, float_flag_inexact);

    /* |a| = |b| ==> return PI/4 */
    if (aSig == bSig && aExp == bExp)
        return roundAndPackFloatx80(80, bSign, FLOATX80_PI4_EXP, FLOAT_PI_HI, FLOAT_PI_LO, status);

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

    float128 a128 = normalizeRoundAndPackFloat128(0, aExp-0x10, aSig, 0, status);
    float128 b128 = normalizeRoundAndPackFloat128(0, bExp-0x10, bSig, 0, status);
    float128 x;
    int swap = 0, add_pi6 = 0, add_pi4 = 0;

    if (aExp > bExp || (aExp == bExp && aSig > bSig))
    {
        x = float128_div(b128, a128, status);
    }
    else {
        x = float128_div(a128, b128, status);
        swap = 1;
    }

    Bit32s xExp = extractFloat128Exp(x);

    if (xExp <= EXP_BIAS-40)
        goto approximation_completed;

    if (x.hi >= BX_CONST64(0x3ffe800000000000))        // 3/4 < x < 1
    {
        /*
        arctan(x) = arctan((x-1)/(x+1)) + pi/4
        */
        float128 t1 = float128_sub(x, float128_one, status);
        float128 t2 = float128_add(x, float128_one, status);
        x = float128_div(t1, t2, status);
        add_pi4 = 1;
    }
    else
    {
        /* argument correction */
        if (xExp >= 0x3FFD)                     // 1/4 < x < 3/4
        {
            /*
            arctan(x) = arctan((x*sqrt(3)-1)/(x+sqrt(3))) + pi/6
            */
            float128 t1 = float128_mul(x, float128_sqrt3, status);
            float128 t2 = float128_add(x, float128_sqrt3, status);
            x = float128_sub(t1, float128_one, status);
            x = float128_div(x, t2, status);
            add_pi6 = 1;
        }
    }

    x = poly_atan(x, status);
    if (add_pi6) x = float128_add(x, float128_pi6, status);
    if (add_pi4) x = float128_add(x, float128_pi4, status);

approximation_completed:
    if (swap) x = float128_sub(float128_pi2, x, status);
    floatx80 result = float128_to_floatx80(x, status);
    if (zSign) floatx80_chs(result);
    int rSign = extractFloatx80Sign(result);
    if (!bSign && rSign)
        return floatx80_add(result, floatx80_pi, status);
    if (bSign && !rSign)
        return floatx80_sub(result, floatx80_pi, status);
    return result;
}