From 5ef0e5eff7a2c8384a2cbd4dd4c7ff5977569c28 Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Sat, 15 Apr 2017 09:58:30 +0300 Subject: [PATCH] Precision cleanup and formatting. --- softfloat/softfloat_fpsp.cpp | 4062 ++++++++++++++--------------- softfloat/softfloat_fpsp_tables.h | 996 +++---- 2 files changed, 2481 insertions(+), 2577 deletions(-) diff --git a/softfloat/softfloat_fpsp.cpp b/softfloat/softfloat_fpsp.cpp index b2d69f39..61b6296e 100644 --- a/softfloat/softfloat_fpsp.cpp +++ b/softfloat/softfloat_fpsp.cpp @@ -32,14 +32,24 @@ #define one_exp 0x3FFF #define one_sig LIT64(0x8000000000000000) +#define SET_PREC \ + int8_t user_rnd_mode, user_rnd_prec; \ + user_rnd_mode = status->float_rounding_mode; \ + user_rnd_prec = status->floatx80_rounding_precision; \ + status->float_rounding_mode = float_round_nearest_even; \ + status->floatx80_rounding_precision = 80 + +#define RESET_PREC \ + status->float_rounding_mode = user_rnd_mode; \ + status->floatx80_rounding_precision = user_rnd_prec /*---------------------------------------------------------------------------- | Function for compactifying extended double-precision floating point values. *----------------------------------------------------------------------------*/ -int32_t floatx80_make_compact(int32_t aExp, uint64_t aSig) +static int32_t floatx80_make_compact(int32_t aExp, uint64_t aSig) { - return (aExp<<16)|(aSig>>48); + return (aExp<<16)|(aSig>>48); } @@ -49,66 +59,63 @@ int32_t floatx80_make_compact(int32_t aExp, uint64_t aSig) floatx80 floatx80_acos(floatx80 a, float_status *status) { - flag aSign; - int32_t aExp; - uint64_t aSig; - - int8_t user_rnd_mode, user_rnd_prec; - - int32_t compact; - floatx80 fp0, fp1, one; - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - - if (aExp == 0x7FFF && (uint64_t) (aSig<<1)) { - return propagateFloatx80NaNOneArg(a, status); - } - if (aExp == 0 && aSig == 0) { - float_raise(float_flag_inexact, status); - return roundAndPackFloatx80(status->floatx80_rounding_precision, 0, piby2_exp, pi_sig, 0, status); - } - - compact = floatx80_make_compact(aExp, aSig); - - if (compact >= 0x3FFF8000) { // |X| >= 1 - if (aExp == one_exp && aSig == one_sig) { // |X| == 1 - if (aSign) { // X == -1 - a = packFloatx80(0, pi_exp, pi_sig); - float_raise(float_flag_inexact, status); - return floatx80_move(a, status); - } else { // X == +1 - return packFloatx80(0, 0, 0); - } - } else { // |X| > 1 - float_raise(float_flag_invalid, status); - a.low = floatx80_default_nan_low; - a.high = floatx80_default_nan_high; - return a; - } - } // |X| < 1 - - user_rnd_mode = status->float_rounding_mode; - user_rnd_prec = status->floatx80_rounding_precision; - - one = packFloatx80(0, one_exp, one_sig); - fp0 = a; - - fp1 = floatx80_add(one, fp0, status); // 1 + X - fp0 = floatx80_sub(one, fp0, status); // 1 - X - fp0 = floatx80_div(fp0, fp1, status); // (1-X)/(1+X) - fp0 = floatx80_sqrt(fp0, status); // SQRT((1-X)/(1+X)) - fp0 = floatx80_atan(fp0, status); // ATAN(SQRT((1-X)/(1+X))) - - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - a = floatx80_add(fp0, fp0, status); // 2 * ATAN(SQRT((1-X)/(1+X))) - - float_raise(float_flag_inexact, status); - - return a; + flag aSign; + int32_t aExp; + uint64_t aSig; + + + int32_t compact; + floatx80 fp0, fp1, one; + + aSig = extractFloatx80Frac(a); + aExp = extractFloatx80Exp(a); + aSign = extractFloatx80Sign(a); + + if (aExp == 0x7FFF && (uint64_t) (aSig<<1)) { + return propagateFloatx80NaNOneArg(a, status); + } + if (aExp == 0 && aSig == 0) { + float_raise(float_flag_inexact, status); + return roundAndPackFloatx80(status->floatx80_rounding_precision, 0, piby2_exp, pi_sig, 0, status); + } + + compact = floatx80_make_compact(aExp, aSig); + + if (compact >= 0x3FFF8000) { // |X| >= 1 + if (aExp == one_exp && aSig == one_sig) { // |X| == 1 + if (aSign) { // X == -1 + a = packFloatx80(0, pi_exp, pi_sig); + float_raise(float_flag_inexact, status); + return floatx80_move(a, status); + } else { // X == +1 + return packFloatx80(0, 0, 0); + } + } else { // |X| > 1 + float_raise(float_flag_invalid, status); + a.low = floatx80_default_nan_low; + a.high = floatx80_default_nan_high; + return a; + } + } // |X| < 1 + + SET_PREC; + + one = packFloatx80(0, one_exp, one_sig); + fp0 = a; + + fp1 = floatx80_add(one, fp0, status); // 1 + X + fp0 = floatx80_sub(one, fp0, status); // 1 - X + fp0 = floatx80_div(fp0, fp1, status); // (1-X)/(1+X) + fp0 = floatx80_sqrt(fp0, status); // SQRT((1-X)/(1+X)) + fp0 = floatx80_atan(fp0, status); // ATAN(SQRT((1-X)/(1+X))) + + RESET_PREC; + + a = floatx80_add(fp0, fp0, status); // 2 * ATAN(SQRT((1-X)/(1+X))) + + float_raise(float_flag_inexact, status); + + return a; } /*---------------------------------------------------------------------------- @@ -117,63 +124,59 @@ floatx80 floatx80_acos(floatx80 a, float_status *status) floatx80 floatx80_asin(floatx80 a, float_status *status) { - flag aSign; - int32_t aExp; - uint64_t aSig; - - int8_t user_rnd_mode, user_rnd_prec; - - int32_t compact; - floatx80 fp0, fp1, fp2, one; - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - - if (aExp == 0x7FFF && (uint64_t) (aSig<<1)) { - return propagateFloatx80NaNOneArg(a, status); - } - - if (aExp == 0 && aSig == 0) { - return packFloatx80(aSign, 0, 0); - } - - compact = floatx80_make_compact(aExp, aSig); - - if (compact >= 0x3FFF8000) { // |X| >= 1 - if (aExp == one_exp && aSig == one_sig) { // |X| == 1 - float_raise(float_flag_inexact, status); - a = packFloatx80(aSign, piby2_exp, pi_sig); - return floatx80_move(a, status); - } else { // |X| > 1 - float_raise(float_flag_invalid, status); - a.low = floatx80_default_nan_low; - a.high = floatx80_default_nan_high; - return a; - } - - } // |X| < 1 - - user_rnd_mode = status->float_rounding_mode; - user_rnd_prec = status->floatx80_rounding_precision; - - one = packFloatx80(0, one_exp, one_sig); - fp0 = a; - - fp1 = floatx80_sub(one, fp0, status); // 1 - X - fp2 = floatx80_add(one, fp0, status); // 1 + X - fp1 = floatx80_mul(fp2, fp1, status); // (1+X)*(1-X) - fp1 = floatx80_sqrt(fp1, status); // SQRT((1+X)*(1-X)) - fp0 = floatx80_div(fp0, fp1, status); // X/SQRT((1+X)*(1-X)) - - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - a = floatx80_atan(fp0, status); // ATAN(X/SQRT((1+X)*(1-X))) - - float_raise(float_flag_inexact, status); - - return a; + flag aSign; + int32_t aExp; + uint64_t aSig; + + int32_t compact; + floatx80 fp0, fp1, fp2, one; + + aSig = extractFloatx80Frac(a); + aExp = extractFloatx80Exp(a); + aSign = extractFloatx80Sign(a); + + if (aExp == 0x7FFF && (uint64_t) (aSig<<1)) { + return propagateFloatx80NaNOneArg(a, status); + } + + if (aExp == 0 && aSig == 0) { + return packFloatx80(aSign, 0, 0); + } + + compact = floatx80_make_compact(aExp, aSig); + + if (compact >= 0x3FFF8000) { // |X| >= 1 + if (aExp == one_exp && aSig == one_sig) { // |X| == 1 + float_raise(float_flag_inexact, status); + a = packFloatx80(aSign, piby2_exp, pi_sig); + return floatx80_move(a, status); + } else { // |X| > 1 + float_raise(float_flag_invalid, status); + a.low = floatx80_default_nan_low; + a.high = floatx80_default_nan_high; + return a; + } + + } // |X| < 1 + + SET_PREC; + + one = packFloatx80(0, one_exp, one_sig); + fp0 = a; + + fp1 = floatx80_sub(one, fp0, status); // 1 - X + fp2 = floatx80_add(one, fp0, status); // 1 + X + fp1 = floatx80_mul(fp2, fp1, status); // (1+X)*(1-X) + fp1 = floatx80_sqrt(fp1, status); // SQRT((1+X)*(1-X)) + fp0 = floatx80_div(fp0, fp1, status); // X/SQRT((1+X)*(1-X)) + + RESET_PREC; + + a = floatx80_atan(fp0, status); // ATAN(X/SQRT((1+X)*(1-X))) + + float_raise(float_flag_inexact, status); + + return a; } /*---------------------------------------------------------------------------- @@ -182,163 +185,155 @@ floatx80 floatx80_asin(floatx80 a, float_status *status) floatx80 floatx80_atan(floatx80 a, float_status *status) { - flag aSign; - int32_t aExp; - uint64_t aSig; - - int8_t user_rnd_mode, user_rnd_prec; - - int32_t compact, tbl_index; - floatx80 fp0, fp1, fp2, fp3, xsave; - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - - if (aExp == 0x7FFF) { - if ((uint64_t) (aSig<<1)) return propagateFloatx80NaNOneArg(a, status); - a = packFloatx80(aSign, piby2_exp, pi_sig); - float_raise(float_flag_inexact, status); - return floatx80_move(a, status); - } - - if (aExp == 0 && aSig == 0) { - return packFloatx80(aSign, 0, 0); - } - - compact = floatx80_make_compact(aExp, aSig); - - user_rnd_mode = status->float_rounding_mode; - user_rnd_prec = status->floatx80_rounding_precision; - - if (compact < 0x3FFB8000 || compact > 0x4002FFFF) { // |X| >= 16 or |X| < 1/16 - if (compact > 0x3FFF8000) { // |X| >= 16 - if (compact > 0x40638000) { // |X| > 2^(100) - fp0 = packFloatx80(aSign, piby2_exp, pi_sig); - fp1 = packFloatx80(aSign, 0x0001, one_sig); - - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - a = floatx80_sub(fp0, fp1, status); - - float_raise(float_flag_inexact, status); - - return a; - } else { - fp0 = a; - fp1 = packFloatx80(1, one_exp, one_sig); // -1 - fp1 = floatx80_div(fp1, fp0, status); // X' = -1/X - xsave = fp1; - fp0 = floatx80_mul(fp1, fp1, status); // Y = X'*X' - fp1 = floatx80_mul(fp0, fp0, status); // Z = Y*Y - fp3 = float64_to_floatx80(LIT64(0xBFB70BF398539E6A), status); // C5 - fp2 = float64_to_floatx80(LIT64(0x3FBC7187962D1D7D), status); // C4 - fp3 = floatx80_mul(fp3, fp1, status); // Z*C5 - fp2 = floatx80_mul(fp2, fp1, status); // Z*C4 - fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0xBFC24924827107B8), status), status); // C3+Z*C5 - fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3FC999999996263E), status), status); // C2+Z*C4 - fp1 = floatx80_mul(fp1, fp3, status); // Z*(C3+Z*C5) - fp2 = floatx80_mul(fp2, fp0, status); // Y*(C2+Z*C4) - fp1 = floatx80_add(fp1, float64_to_floatx80(LIT64(0xBFD5555555555536), status), status); // C1+Z*(C3+Z*C5) - fp0 = floatx80_mul(fp0, xsave, status); // X'*Y - fp1 = floatx80_add(fp1, fp2, status); // [Y*(C2+Z*C4)]+[C1+Z*(C3+Z*C5)] - fp0 = floatx80_mul(fp0, fp1, status); // X'*Y*([B1+Z*(B3+Z*B5)]+[Y*(B2+Z*(B4+Z*B6))]) ?? - fp0 = floatx80_add(fp0, xsave, status); - fp1 = packFloatx80(aSign, piby2_exp, pi_sig); - - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - a = floatx80_add(fp0, fp1, status); - - float_raise(float_flag_inexact, status); - - return a; - } - } else { // |X| < 1/16 - if (compact < 0x3FD78000) { // |X| < 2^(-40) - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - a = floatx80_move(a, status); - - float_raise(float_flag_inexact, status); - - return a; - } else { - fp0 = a; - xsave = a; - fp0 = floatx80_mul(fp0, fp0, status); // Y = X*X - fp1 = floatx80_mul(fp0, fp0, status); // Z = Y*Y - fp2 = float64_to_floatx80(LIT64(0x3FB344447F876989), status); // B6 - fp3 = float64_to_floatx80(LIT64(0xBFB744EE7FAF45DB), status); // B5 - fp2 = floatx80_mul(fp2, fp1, status); // Z*B6 - fp3 = floatx80_mul(fp3, fp1, status); // Z*B5 - fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3FBC71C646940220), status), status); // B4+Z*B6 - fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0xBFC24924921872F9), status), status); // B3+Z*B5 - fp2 = floatx80_mul(fp2, fp1, status); // Z*(B4+Z*B6) - fp1 = floatx80_mul(fp1, fp3, status); // Z*(B3+Z*B5) - fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3FC9999999998FA9), status), status); // B2+Z*(B4+Z*B6) - fp1 = floatx80_add(fp1, float64_to_floatx80(LIT64(0xBFD5555555555555), status), status); // B1+Z*(B3+Z*B5) - fp2 = floatx80_mul(fp2, fp0, status); // Y*(B2+Z*(B4+Z*B6)) - fp0 = floatx80_mul(fp0, xsave, status); // X*Y - fp1 = floatx80_add(fp1, fp2, status); // [B1+Z*(B3+Z*B5)]+[Y*(B2+Z*(B4+Z*B6))] - fp0 = floatx80_mul(fp0, fp1, status); // X*Y*([B1+Z*(B3+Z*B5)]+[Y*(B2+Z*(B4+Z*B6))]) - - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - a = floatx80_add(fp0, xsave, status); - - float_raise(float_flag_inexact, status); - - return a; - } - } - } else { - aSig &= LIT64(0xF800000000000000); - aSig |= LIT64(0x0400000000000000); - xsave = packFloatx80(aSign, aExp, aSig); // F - fp0 = a; - fp1 = a; // X - fp2 = packFloatx80(0, one_exp, one_sig); // 1 - fp1 = floatx80_mul(fp1, xsave, status); // X*F - fp0 = floatx80_sub(fp0, xsave, status); // X-F - fp1 = floatx80_add(fp1, fp2, status); // 1 + X*F - fp0 = floatx80_div(fp0, fp1, status); // U = (X-F)/(1+X*F) - - tbl_index = compact; - - tbl_index &= 0x7FFF0000; - tbl_index -= 0x3FFB0000; - tbl_index >>= 1; - tbl_index += compact&0x00007800; - tbl_index >>= 11; - - fp3 = atan_tbl[tbl_index]; - - fp3.high |= aSign ? 0x8000 : 0; // ATAN(F) - - fp1 = floatx80_mul(fp0, fp0, status); // V = U*U - fp2 = float64_to_floatx80(LIT64(0xBFF6687E314987D8), status); // A3 - fp2 = floatx80_add(fp2, fp1, status); // A3+V - fp2 = floatx80_mul(fp2, fp1, status); // V*(A3+V) - fp1 = floatx80_mul(fp1, fp0, status); // U*V - fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x4002AC6934A26DB3), status), status); // A2+V*(A3+V) - fp1 = floatx80_mul(fp1, float64_to_floatx80(LIT64(0xBFC2476F4E1DA28E), status), status); // A1+U*V - fp1 = floatx80_mul(fp1, fp2, status); // A1*U*V*(A2+V*(A3+V)) - fp0 = floatx80_add(fp0, fp1, status); // ATAN(U) - - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - a = floatx80_add(fp0, fp3, status); // ATAN(X) - - float_raise(float_flag_inexact, status); - - return a; - } + flag aSign; + int32_t aExp; + uint64_t aSig; + + int32_t compact, tbl_index; + floatx80 fp0, fp1, fp2, fp3, xsave; + + aSig = extractFloatx80Frac(a); + aExp = extractFloatx80Exp(a); + aSign = extractFloatx80Sign(a); + + if (aExp == 0x7FFF) { + if ((uint64_t) (aSig<<1)) return propagateFloatx80NaNOneArg(a, status); + a = packFloatx80(aSign, piby2_exp, pi_sig); + float_raise(float_flag_inexact, status); + return floatx80_move(a, status); + } + + if (aExp == 0 && aSig == 0) { + return packFloatx80(aSign, 0, 0); + } + + compact = floatx80_make_compact(aExp, aSig); + + SET_PREC; + + if (compact < 0x3FFB8000 || compact > 0x4002FFFF) { // |X| >= 16 or |X| < 1/16 + if (compact > 0x3FFF8000) { // |X| >= 16 + if (compact > 0x40638000) { // |X| > 2^(100) + fp0 = packFloatx80(aSign, piby2_exp, pi_sig); + fp1 = packFloatx80(aSign, 0x0001, one_sig); + + RESET_PREC; + + a = floatx80_sub(fp0, fp1, status); + + float_raise(float_flag_inexact, status); + + return a; + } else { + fp0 = a; + fp1 = packFloatx80(1, one_exp, one_sig); // -1 + fp1 = floatx80_div(fp1, fp0, status); // X' = -1/X + xsave = fp1; + fp0 = floatx80_mul(fp1, fp1, status); // Y = X'*X' + fp1 = floatx80_mul(fp0, fp0, status); // Z = Y*Y + fp3 = float64_to_floatx80(LIT64(0xBFB70BF398539E6A), status); // C5 + fp2 = float64_to_floatx80(LIT64(0x3FBC7187962D1D7D), status); // C4 + fp3 = floatx80_mul(fp3, fp1, status); // Z*C5 + fp2 = floatx80_mul(fp2, fp1, status); // Z*C4 + fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0xBFC24924827107B8), status), status); // C3+Z*C5 + fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3FC999999996263E), status), status); // C2+Z*C4 + fp1 = floatx80_mul(fp1, fp3, status); // Z*(C3+Z*C5) + fp2 = floatx80_mul(fp2, fp0, status); // Y*(C2+Z*C4) + fp1 = floatx80_add(fp1, float64_to_floatx80(LIT64(0xBFD5555555555536), status), status); // C1+Z*(C3+Z*C5) + fp0 = floatx80_mul(fp0, xsave, status); // X'*Y + fp1 = floatx80_add(fp1, fp2, status); // [Y*(C2+Z*C4)]+[C1+Z*(C3+Z*C5)] + fp0 = floatx80_mul(fp0, fp1, status); // X'*Y*([B1+Z*(B3+Z*B5)]+[Y*(B2+Z*(B4+Z*B6))]) ?? + fp0 = floatx80_add(fp0, xsave, status); + fp1 = packFloatx80(aSign, piby2_exp, pi_sig); + + RESET_PREC; + + a = floatx80_add(fp0, fp1, status); + + float_raise(float_flag_inexact, status); + + return a; + } + } else { // |X| < 1/16 + if (compact < 0x3FD78000) { // |X| < 2^(-40) + RESET_PREC; + + a = floatx80_move(a, status); + + float_raise(float_flag_inexact, status); + + return a; + } else { + fp0 = a; + xsave = a; + fp0 = floatx80_mul(fp0, fp0, status); // Y = X*X + fp1 = floatx80_mul(fp0, fp0, status); // Z = Y*Y + fp2 = float64_to_floatx80(LIT64(0x3FB344447F876989), status); // B6 + fp3 = float64_to_floatx80(LIT64(0xBFB744EE7FAF45DB), status); // B5 + fp2 = floatx80_mul(fp2, fp1, status); // Z*B6 + fp3 = floatx80_mul(fp3, fp1, status); // Z*B5 + fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3FBC71C646940220), status), status); // B4+Z*B6 + fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0xBFC24924921872F9), status), status); // B3+Z*B5 + fp2 = floatx80_mul(fp2, fp1, status); // Z*(B4+Z*B6) + fp1 = floatx80_mul(fp1, fp3, status); // Z*(B3+Z*B5) + fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3FC9999999998FA9), status), status); // B2+Z*(B4+Z*B6) + fp1 = floatx80_add(fp1, float64_to_floatx80(LIT64(0xBFD5555555555555), status), status); // B1+Z*(B3+Z*B5) + fp2 = floatx80_mul(fp2, fp0, status); // Y*(B2+Z*(B4+Z*B6)) + fp0 = floatx80_mul(fp0, xsave, status); // X*Y + fp1 = floatx80_add(fp1, fp2, status); // [B1+Z*(B3+Z*B5)]+[Y*(B2+Z*(B4+Z*B6))] + fp0 = floatx80_mul(fp0, fp1, status); // X*Y*([B1+Z*(B3+Z*B5)]+[Y*(B2+Z*(B4+Z*B6))]) + + RESET_PREC; + + a = floatx80_add(fp0, xsave, status); + + float_raise(float_flag_inexact, status); + + return a; + } + } + } else { + aSig &= LIT64(0xF800000000000000); + aSig |= LIT64(0x0400000000000000); + xsave = packFloatx80(aSign, aExp, aSig); // F + fp0 = a; + fp1 = a; // X + fp2 = packFloatx80(0, one_exp, one_sig); // 1 + fp1 = floatx80_mul(fp1, xsave, status); // X*F + fp0 = floatx80_sub(fp0, xsave, status); // X-F + fp1 = floatx80_add(fp1, fp2, status); // 1 + X*F + fp0 = floatx80_div(fp0, fp1, status); // U = (X-F)/(1+X*F) + + tbl_index = compact; + + tbl_index &= 0x7FFF0000; + tbl_index -= 0x3FFB0000; + tbl_index >>= 1; + tbl_index += compact&0x00007800; + tbl_index >>= 11; + + fp3 = atan_tbl[tbl_index]; + + fp3.high |= aSign ? 0x8000 : 0; // ATAN(F) + + fp1 = floatx80_mul(fp0, fp0, status); // V = U*U + fp2 = float64_to_floatx80(LIT64(0xBFF6687E314987D8), status); // A3 + fp2 = floatx80_add(fp2, fp1, status); // A3+V + fp2 = floatx80_mul(fp2, fp1, status); // V*(A3+V) + fp1 = floatx80_mul(fp1, fp0, status); // U*V + fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x4002AC6934A26DB3), status), status); // A2+V*(A3+V) + fp1 = floatx80_mul(fp1, float64_to_floatx80(LIT64(0xBFC2476F4E1DA28E), status), status); // A1+U*V + fp1 = floatx80_mul(fp1, fp2, status); // A1*U*V*(A2+V*(A3+V)) + fp0 = floatx80_add(fp0, fp1, status); // ATAN(U) + + RESET_PREC; + + a = floatx80_add(fp0, fp3, status); // ATAN(X) + + float_raise(float_flag_inexact, status); + + return a; + } } /*---------------------------------------------------------------------------- @@ -347,61 +342,57 @@ floatx80 floatx80_atan(floatx80 a, float_status *status) floatx80 floatx80_atanh(floatx80 a, float_status *status) { - flag aSign; - int32_t aExp; - uint64_t aSig; - - int8_t user_rnd_mode, user_rnd_prec; - - int32_t compact; - floatx80 fp0, fp1, fp2, one; - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - - if (aExp == 0x7FFF && (uint64_t) (aSig<<1)) { - return propagateFloatx80NaNOneArg(a, status); - } - - if (aExp == 0 && aSig == 0) { - return packFloatx80(aSign, 0, 0); - } - - compact = floatx80_make_compact(aExp, aSig); - - if (compact >= 0x3FFF8000) { // |X| >= 1 - if (aExp == one_exp && aSig == one_sig) { // |X| == 1 - float_raise(float_flag_divbyzero, status); - return packFloatx80(aSign, 0x7FFF, floatx80_default_infinity_low); - } else { // |X| > 1 - float_raise(float_flag_invalid, status); - a.low = floatx80_default_nan_low; - a.high = floatx80_default_nan_high; - return a; - } - } // |X| < 1 - - user_rnd_mode = status->float_rounding_mode; - user_rnd_prec = status->floatx80_rounding_precision; - - one = packFloatx80(0, one_exp, one_sig); - fp2 = packFloatx80(aSign, 0x3FFE, one_sig); // SIGN(X) * (1/2) - fp0 = packFloatx80(0, aExp, aSig); // Y = |X| - fp1 = packFloatx80(1, aExp, aSig); // -Y - fp0 = floatx80_add(fp0, fp0, status); // 2Y - fp1 = floatx80_add(fp1, one, status); // 1-Y - fp0 = floatx80_div(fp0, fp1, status); // Z = 2Y/(1-Y) - fp0 = floatx80_lognp1(fp0, status); // LOG1P(Z) - - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - a = floatx80_mul(fp0, fp2, status); // ATANH(X) = SIGN(X) * (1/2) * LOG1P(Z) - - float_raise(float_flag_inexact, status); - - return a; + flag aSign; + int32_t aExp; + uint64_t aSig; + + int32_t compact; + floatx80 fp0, fp1, fp2, one; + + aSig = extractFloatx80Frac(a); + aExp = extractFloatx80Exp(a); + aSign = extractFloatx80Sign(a); + + if (aExp == 0x7FFF && (uint64_t) (aSig<<1)) { + return propagateFloatx80NaNOneArg(a, status); + } + + if (aExp == 0 && aSig == 0) { + return packFloatx80(aSign, 0, 0); + } + + compact = floatx80_make_compact(aExp, aSig); + + if (compact >= 0x3FFF8000) { // |X| >= 1 + if (aExp == one_exp && aSig == one_sig) { // |X| == 1 + float_raise(float_flag_divbyzero, status); + return packFloatx80(aSign, 0x7FFF, floatx80_default_infinity_low); + } else { // |X| > 1 + float_raise(float_flag_invalid, status); + a.low = floatx80_default_nan_low; + a.high = floatx80_default_nan_high; + return a; + } + } // |X| < 1 + + SET_PREC; + + one = packFloatx80(0, one_exp, one_sig); + fp2 = packFloatx80(aSign, 0x3FFE, one_sig); // SIGN(X) * (1/2) + fp0 = packFloatx80(0, aExp, aSig); // Y = |X| + fp1 = packFloatx80(1, aExp, aSig); // -Y + fp0 = floatx80_add(fp0, fp0, status); // 2Y + fp1 = floatx80_add(fp1, one, status); // 1-Y + fp0 = floatx80_div(fp0, fp1, status); // Z = 2Y/(1-Y) + fp0 = floatx80_lognp1(fp0, status); // LOG1P(Z) + + RESET_PREC; + + a = floatx80_mul(fp0, fp2, status); // ATANH(X) = SIGN(X) * (1/2) * LOG1P(Z) + + float_raise(float_flag_inexact, status); + + return a; } /*---------------------------------------------------------------------------- @@ -410,209 +401,203 @@ floatx80 floatx80_atanh(floatx80 a, float_status *status) floatx80 floatx80_cos(floatx80 a, float_status *status) { - flag aSign, xSign; - int32_t aExp, xExp; - uint64_t aSig, xSig; - - int8_t user_rnd_mode, user_rnd_prec; - - int32_t compact, l, n, j; - floatx80 fp0, fp1, fp2, fp3, fp4, fp5, x, invtwopi, twopi1, twopi2; - float32 posneg1, twoto63; - flag adjn, endflag; - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - - if (aExp == 0x7FFF) { - if ((uint64_t) (aSig<<1)) return propagateFloatx80NaNOneArg(a, status); - float_raise(float_flag_invalid, status); - a.low = floatx80_default_nan_low; - a.high = floatx80_default_nan_high; - return a; - } - - if (aExp == 0 && aSig == 0) { - return packFloatx80(0, one_exp, one_sig); - } - - adjn = 1; - - user_rnd_mode = status->float_rounding_mode; - user_rnd_prec = status->floatx80_rounding_precision; - - compact = floatx80_make_compact(aExp, aSig); - - fp0 = a; - - if (compact < 0x3FD78000 || compact > 0x4004BC7E) { // 2^(-40) > |X| > 15 PI - if (compact > 0x3FFF8000) { // |X| >= 15 PI - // REDUCEX - fp1 = packFloatx80(0, 0, 0); - if (compact == 0x7FFEFFFF) { - twopi1 = packFloatx80(aSign ^ 1, 0x7FFE, LIT64(0xC90FDAA200000000)); - twopi2 = packFloatx80(aSign ^ 1, 0x7FDC, LIT64(0x85A308D300000000)); - fp0 = floatx80_add(fp0, twopi1, status); - fp1 = fp0; - fp0 = floatx80_add(fp0, twopi2, status); - fp1 = floatx80_sub(fp1, fp0, status); - fp1 = floatx80_add(fp1, twopi2, status); - } - loop: - xSign = extractFloatx80Sign(fp0); - xExp = extractFloatx80Exp(fp0); - xExp -= 0x3FFF; - if (xExp <= 28) { - l = 0; - endflag = 1; - } else { - l = xExp - 27; - endflag = 0; - } - invtwopi = packFloatx80(0, 0x3FFE - l, LIT64(0xA2F9836E4E44152A)); // INVTWOPI - twopi1 = packFloatx80(0, 0x3FFF + l, LIT64(0xC90FDAA200000000)); - twopi2 = packFloatx80(0, 0x3FDD + l, LIT64(0x85A308D300000000)); - - twoto63 = 0x5F000000; - twoto63 |= xSign ? 0x80000000 : 0x00000000; // SIGN(INARG)*2^63 IN SGL - - fp2 = floatx80_mul(fp0, invtwopi, status); - fp2 = floatx80_add(fp2, float32_to_floatx80(twoto63, status), status); // THE FRACTIONAL PART OF FP2 IS ROUNDED - fp2 = floatx80_sub(fp2, float32_to_floatx80(twoto63, status), status); // FP2 is N - fp4 = floatx80_mul(twopi1, fp2, status); // W = N*P1 - fp5 = floatx80_mul(twopi2, fp2, status); // w = N*P2 - fp3 = floatx80_add(fp4, fp5, status); // FP3 is P - fp4 = floatx80_sub(fp4, fp3, status); // W-P - fp0 = floatx80_sub(fp0, fp3, status); // FP0 is A := R - P - fp4 = floatx80_add(fp4, fp5, status); // FP4 is p = (W-P)+w - fp3 = fp0; // FP3 is A - fp1 = floatx80_sub(fp1, fp4, status); // FP1 is a := r - p - fp0 = floatx80_add(fp0, fp1, status); // FP0 is R := A+a - - if (endflag > 0) { - n = floatx80_to_int32(fp2, status); - goto sincont; - } - fp3 = floatx80_sub(fp3, fp0, status); // A-R - fp1 = floatx80_add(fp1, fp3, status); // FP1 is r := (A-R)+a - goto loop; - } else { - // SINSM - fp0 = float32_to_floatx80(0x3F800000, status); // 1 - - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - if (adjn) { - // COSTINY - a = floatx80_sub(fp0, float32_to_floatx80(0x00800000, status), status); - } else { - // SINTINY - a = floatx80_move(a, status); - } - float_raise(float_flag_inexact, status); - - return a; - } - } else { - fp1 = floatx80_mul(fp0, float64_to_floatx80(LIT64(0x3FE45F306DC9C883), status), status); // X*2/PI - - n = floatx80_to_int32(fp1, status); - j = 32 + n; - - fp0 = floatx80_sub(fp0, pi_tbl[j], status); // X-Y1 - fp0 = floatx80_sub(fp0, float32_to_floatx80(pi_tbl2[j], status), status); // FP0 IS R = (X-Y1)-Y2 - - sincont: - if ((n + adjn) & 1) { - // COSPOLY - fp0 = floatx80_mul(fp0, fp0, status); // FP0 IS S - fp1 = floatx80_mul(fp0, fp0, status); // FP1 IS T - fp2 = float64_to_floatx80(LIT64(0x3D2AC4D0D6011EE3), status); // B8 - fp3 = float64_to_floatx80(LIT64(0xBDA9396F9F45AC19), status); // B7 - - xSign = extractFloatx80Sign(fp0); // X IS S - xExp = extractFloatx80Exp(fp0); - xSig = extractFloatx80Frac(fp0); - - if (((n + adjn) >> 1) & 1) { - xSign ^= 1; - posneg1 = 0xBF800000; // -1 - } else { - xSign ^= 0; - posneg1 = 0x3F800000; // 1 - } // X IS NOW R'= SGN*R - - fp2 = floatx80_mul(fp2, fp1, status); // TB8 - fp3 = floatx80_mul(fp3, fp1, status); // TB7 - fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3E21EED90612C972), status), status); // B6+TB8 - fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0xBE927E4FB79D9FCF), status), status); // B5+TB7 - fp2 = floatx80_mul(fp2, fp1, status); // T(B6+TB8) - fp3 = floatx80_mul(fp3, fp1, status); // T(B5+TB7) - fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3EFA01A01A01D423), status), status); // B4+T(B6+TB8) - fp4 = packFloatx80(1, 0x3FF5, LIT64(0xB60B60B60B61D438)); - fp3 = floatx80_add(fp3, fp4, status); // B3+T(B5+TB7) - fp2 = floatx80_mul(fp2, fp1, status); // T(B4+T(B6+TB8)) - fp1 = floatx80_mul(fp1, fp3, status); // T(B3+T(B5+TB7)) - fp4 = packFloatx80(0, 0x3FFA, LIT64(0xAAAAAAAAAAAAAB5E)); - fp2 = floatx80_add(fp2, fp4, status); // B2+T(B4+T(B6+TB8)) - fp1 = floatx80_add(fp1, float32_to_floatx80(0xBF000000, status), status); // B1+T(B3+T(B5+TB7)) - fp0 = floatx80_mul(fp0, fp2, status); // S(B2+T(B4+T(B6+TB8))) - fp0 = floatx80_add(fp0, fp1, status); // [B1+T(B3+T(B5+TB7))]+[S(B2+T(B4+T(B6+TB8)))] - - x = packFloatx80(xSign, xExp, xSig); - fp0 = floatx80_mul(fp0, x, status); - - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - a = floatx80_add(fp0, float32_to_floatx80(posneg1, status), status); - - float_raise(float_flag_inexact, status); - - return a; - } else { - // SINPOLY - xSign = extractFloatx80Sign(fp0); // X IS R - xExp = extractFloatx80Exp(fp0); - xSig = extractFloatx80Frac(fp0); - - xSign ^= ((n + adjn) >> 1) & 1; // X IS NOW R'= SGN*R - - fp0 = floatx80_mul(fp0, fp0, status); // FP0 IS S - fp1 = floatx80_mul(fp0, fp0, status); // FP1 IS T - fp3 = float64_to_floatx80(LIT64(0xBD6AAA77CCC994F5), status); // A7 - fp2 = float64_to_floatx80(LIT64(0x3DE612097AAE8DA1), status); // A6 - fp3 = floatx80_mul(fp3, fp1, status); // T*A7 - fp2 = floatx80_mul(fp2, fp1, status); // T*A6 - fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0xBE5AE6452A118AE4), status), status); // A5+T*A7 - fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3EC71DE3A5341531), status), status); // A4+T*A6 - fp3 = floatx80_mul(fp3, fp1, status); // T(A5+TA7) - fp2 = floatx80_mul(fp2, fp1, status); // T(A4+TA6) - fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0xBF2A01A01A018B59), status), status); // A3+T(A5+TA7) - fp4 = packFloatx80(0, 0x3FF8, LIT64(0x88888888888859AF)); - fp2 = floatx80_add(fp2, fp4, status); // A2+T(A4+TA6) - fp1 = floatx80_mul(fp1, fp3, status); // T(A3+T(A5+TA7)) - fp2 = floatx80_mul(fp2, fp0, status); // S(A2+T(A4+TA6)) - fp4 = packFloatx80(1, 0x3FFC, LIT64(0xAAAAAAAAAAAAAA99)); - fp1 = floatx80_add(fp1, fp4, status); // A1+T(A3+T(A5+TA7)) - fp1 = floatx80_add(fp1, fp2, status); // [A1+T(A3+T(A5+TA7))]+[S(A2+T(A4+TA6))] - - x = packFloatx80(xSign, xExp, xSig); - fp0 = floatx80_mul(fp0, x, status); // R'*S - fp0 = floatx80_mul(fp0, fp1, status); // SIN(R')-R' - - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - a = floatx80_add(fp0, x, status); - - float_raise(float_flag_inexact, status); - - return a; - } - } + flag aSign, xSign; + int32_t aExp, xExp; + uint64_t aSig, xSig; + + int32_t compact, l, n, j; + floatx80 fp0, fp1, fp2, fp3, fp4, fp5, x, invtwopi, twopi1, twopi2; + float32 posneg1, twoto63; + flag adjn, endflag; + + aSig = extractFloatx80Frac(a); + aExp = extractFloatx80Exp(a); + aSign = extractFloatx80Sign(a); + + if (aExp == 0x7FFF) { + if ((uint64_t) (aSig<<1)) return propagateFloatx80NaNOneArg(a, status); + float_raise(float_flag_invalid, status); + a.low = floatx80_default_nan_low; + a.high = floatx80_default_nan_high; + return a; + } + + if (aExp == 0 && aSig == 0) { + return packFloatx80(0, one_exp, one_sig); + } + + adjn = 1; + + SET_PREC; + + compact = floatx80_make_compact(aExp, aSig); + + fp0 = a; + + if (compact < 0x3FD78000 || compact > 0x4004BC7E) { // 2^(-40) > |X| > 15 PI + if (compact > 0x3FFF8000) { // |X| >= 15 PI + // REDUCEX + fp1 = packFloatx80(0, 0, 0); + if (compact == 0x7FFEFFFF) { + twopi1 = packFloatx80(aSign ^ 1, 0x7FFE, LIT64(0xC90FDAA200000000)); + twopi2 = packFloatx80(aSign ^ 1, 0x7FDC, LIT64(0x85A308D300000000)); + fp0 = floatx80_add(fp0, twopi1, status); + fp1 = fp0; + fp0 = floatx80_add(fp0, twopi2, status); + fp1 = floatx80_sub(fp1, fp0, status); + fp1 = floatx80_add(fp1, twopi2, status); + } + loop: + xSign = extractFloatx80Sign(fp0); + xExp = extractFloatx80Exp(fp0); + xExp -= 0x3FFF; + if (xExp <= 28) { + l = 0; + endflag = 1; + } else { + l = xExp - 27; + endflag = 0; + } + invtwopi = packFloatx80(0, 0x3FFE - l, LIT64(0xA2F9836E4E44152A)); // INVTWOPI + twopi1 = packFloatx80(0, 0x3FFF + l, LIT64(0xC90FDAA200000000)); + twopi2 = packFloatx80(0, 0x3FDD + l, LIT64(0x85A308D300000000)); + + twoto63 = 0x5F000000; + twoto63 |= xSign ? 0x80000000 : 0x00000000; // SIGN(INARG)*2^63 IN SGL + + fp2 = floatx80_mul(fp0, invtwopi, status); + fp2 = floatx80_add(fp2, float32_to_floatx80(twoto63, status), status); // THE FRACTIONAL PART OF FP2 IS ROUNDED + fp2 = floatx80_sub(fp2, float32_to_floatx80(twoto63, status), status); // FP2 is N + fp4 = floatx80_mul(twopi1, fp2, status); // W = N*P1 + fp5 = floatx80_mul(twopi2, fp2, status); // w = N*P2 + fp3 = floatx80_add(fp4, fp5, status); // FP3 is P + fp4 = floatx80_sub(fp4, fp3, status); // W-P + fp0 = floatx80_sub(fp0, fp3, status); // FP0 is A := R - P + fp4 = floatx80_add(fp4, fp5, status); // FP4 is p = (W-P)+w + fp3 = fp0; // FP3 is A + fp1 = floatx80_sub(fp1, fp4, status); // FP1 is a := r - p + fp0 = floatx80_add(fp0, fp1, status); // FP0 is R := A+a + + if (endflag > 0) { + n = floatx80_to_int32(fp2, status); + goto sincont; + } + fp3 = floatx80_sub(fp3, fp0, status); // A-R + fp1 = floatx80_add(fp1, fp3, status); // FP1 is r := (A-R)+a + goto loop; + } else { + // SINSM + fp0 = float32_to_floatx80(0x3F800000, status); // 1 + + RESET_PREC; + + if (adjn) { + // COSTINY + a = floatx80_sub(fp0, float32_to_floatx80(0x00800000, status), status); + } else { + // SINTINY + a = floatx80_move(a, status); + } + float_raise(float_flag_inexact, status); + + return a; + } + } else { + fp1 = floatx80_mul(fp0, float64_to_floatx80(LIT64(0x3FE45F306DC9C883), status), status); // X*2/PI + + n = floatx80_to_int32(fp1, status); + j = 32 + n; + + fp0 = floatx80_sub(fp0, pi_tbl[j], status); // X-Y1 + fp0 = floatx80_sub(fp0, float32_to_floatx80(pi_tbl2[j], status), status); // FP0 IS R = (X-Y1)-Y2 + + sincont: + if ((n + adjn) & 1) { + // COSPOLY + fp0 = floatx80_mul(fp0, fp0, status); // FP0 IS S + fp1 = floatx80_mul(fp0, fp0, status); // FP1 IS T + fp2 = float64_to_floatx80(LIT64(0x3D2AC4D0D6011EE3), status); // B8 + fp3 = float64_to_floatx80(LIT64(0xBDA9396F9F45AC19), status); // B7 + + xSign = extractFloatx80Sign(fp0); // X IS S + xExp = extractFloatx80Exp(fp0); + xSig = extractFloatx80Frac(fp0); + + if (((n + adjn) >> 1) & 1) { + xSign ^= 1; + posneg1 = 0xBF800000; // -1 + } else { + xSign ^= 0; + posneg1 = 0x3F800000; // 1 + } // X IS NOW R'= SGN*R + + fp2 = floatx80_mul(fp2, fp1, status); // TB8 + fp3 = floatx80_mul(fp3, fp1, status); // TB7 + fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3E21EED90612C972), status), status); // B6+TB8 + fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0xBE927E4FB79D9FCF), status), status); // B5+TB7 + fp2 = floatx80_mul(fp2, fp1, status); // T(B6+TB8) + fp3 = floatx80_mul(fp3, fp1, status); // T(B5+TB7) + fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3EFA01A01A01D423), status), status); // B4+T(B6+TB8) + fp4 = packFloatx80(1, 0x3FF5, LIT64(0xB60B60B60B61D438)); + fp3 = floatx80_add(fp3, fp4, status); // B3+T(B5+TB7) + fp2 = floatx80_mul(fp2, fp1, status); // T(B4+T(B6+TB8)) + fp1 = floatx80_mul(fp1, fp3, status); // T(B3+T(B5+TB7)) + fp4 = packFloatx80(0, 0x3FFA, LIT64(0xAAAAAAAAAAAAAB5E)); + fp2 = floatx80_add(fp2, fp4, status); // B2+T(B4+T(B6+TB8)) + fp1 = floatx80_add(fp1, float32_to_floatx80(0xBF000000, status), status); // B1+T(B3+T(B5+TB7)) + fp0 = floatx80_mul(fp0, fp2, status); // S(B2+T(B4+T(B6+TB8))) + fp0 = floatx80_add(fp0, fp1, status); // [B1+T(B3+T(B5+TB7))]+[S(B2+T(B4+T(B6+TB8)))] + + x = packFloatx80(xSign, xExp, xSig); + fp0 = floatx80_mul(fp0, x, status); + + RESET_PREC; + + a = floatx80_add(fp0, float32_to_floatx80(posneg1, status), status); + + float_raise(float_flag_inexact, status); + + return a; + } else { + // SINPOLY + xSign = extractFloatx80Sign(fp0); // X IS R + xExp = extractFloatx80Exp(fp0); + xSig = extractFloatx80Frac(fp0); + + xSign ^= ((n + adjn) >> 1) & 1; // X IS NOW R'= SGN*R + + fp0 = floatx80_mul(fp0, fp0, status); // FP0 IS S + fp1 = floatx80_mul(fp0, fp0, status); // FP1 IS T + fp3 = float64_to_floatx80(LIT64(0xBD6AAA77CCC994F5), status); // A7 + fp2 = float64_to_floatx80(LIT64(0x3DE612097AAE8DA1), status); // A6 + fp3 = floatx80_mul(fp3, fp1, status); // T*A7 + fp2 = floatx80_mul(fp2, fp1, status); // T*A6 + fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0xBE5AE6452A118AE4), status), status); // A5+T*A7 + fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3EC71DE3A5341531), status), status); // A4+T*A6 + fp3 = floatx80_mul(fp3, fp1, status); // T(A5+TA7) + fp2 = floatx80_mul(fp2, fp1, status); // T(A4+TA6) + fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0xBF2A01A01A018B59), status), status); // A3+T(A5+TA7) + fp4 = packFloatx80(0, 0x3FF8, LIT64(0x88888888888859AF)); + fp2 = floatx80_add(fp2, fp4, status); // A2+T(A4+TA6) + fp1 = floatx80_mul(fp1, fp3, status); // T(A3+T(A5+TA7)) + fp2 = floatx80_mul(fp2, fp0, status); // S(A2+T(A4+TA6)) + fp4 = packFloatx80(1, 0x3FFC, LIT64(0xAAAAAAAAAAAAAA99)); + fp1 = floatx80_add(fp1, fp4, status); // A1+T(A3+T(A5+TA7)) + fp1 = floatx80_add(fp1, fp2, status); // [A1+T(A3+T(A5+TA7))]+[S(A2+T(A4+TA6))] + + x = packFloatx80(xSign, xExp, xSig); + fp0 = floatx80_mul(fp0, x, status); // R'*S + fp0 = floatx80_mul(fp0, fp1, status); // SIN(R')-R' + + RESET_PREC; + + a = floatx80_add(fp0, x, status); + + float_raise(float_flag_inexact, status); + + return a; + } + } } /*---------------------------------------------------------------------------- @@ -621,70 +606,64 @@ floatx80 floatx80_cos(floatx80 a, float_status *status) floatx80 floatx80_cosh(floatx80 a, float_status *status) { - flag aSign; - int32_t aExp; - uint64_t aSig; - - int8_t user_rnd_mode, user_rnd_prec; - - int32_t compact; - floatx80 fp0, fp1; - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - - if (aExp == 0x7FFF) { - if ((uint64_t) (aSig<<1)) return propagateFloatx80NaNOneArg(a, status); - return packFloatx80(0, 0x7FFF, floatx80_default_infinity_low); - } - - if (aExp == 0 && aSig == 0) { - return packFloatx80(0, one_exp, one_sig); - } - - user_rnd_mode = status->float_rounding_mode; - user_rnd_prec = status->floatx80_rounding_precision; - - compact = floatx80_make_compact(aExp, aSig); - - if (compact > 0x400CB167) { - if (compact > 0x400CB2B3) { - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - return roundAndPackFloatx80(status->floatx80_rounding_precision, 0, 0x8000, one_sig, 0, status); - } else { - fp0 = packFloatx80(0, aExp, aSig); - fp0 = floatx80_sub(fp0, float64_to_floatx80(LIT64(0x40C62D38D3D64634), status), status); - fp0 = floatx80_sub(fp0, float64_to_floatx80(LIT64(0x3D6F90AEB1E75CC7), status), status); - fp0 = floatx80_etox(fp0, status); - fp1 = packFloatx80(0, 0x7FFB, one_sig); - - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - a = floatx80_mul(fp0, fp1, status); - - float_raise(float_flag_inexact, status); - - return a; - } - } - - fp0 = packFloatx80(0, aExp, aSig); // |X| - fp0 = floatx80_etox(fp0, status); // EXP(|X|) - fp0 = floatx80_mul(fp0, float32_to_floatx80(0x3F000000, status), status); // (1/2)*EXP(|X|) - fp1 = float32_to_floatx80(0x3E800000, status); // 1/4 - fp1 = floatx80_div(fp1, fp0, status); // 1/(2*EXP(|X|)) - - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - a = floatx80_add(fp0, fp1, status); - - float_raise(float_flag_inexact, status); - - return a; + flag aSign; + int32_t aExp; + uint64_t aSig; + + int32_t compact; + floatx80 fp0, fp1; + + aSig = extractFloatx80Frac(a); + aExp = extractFloatx80Exp(a); + aSign = extractFloatx80Sign(a); + + if (aExp == 0x7FFF) { + if ((uint64_t) (aSig<<1)) return propagateFloatx80NaNOneArg(a, status); + return packFloatx80(0, 0x7FFF, floatx80_default_infinity_low); + } + + if (aExp == 0 && aSig == 0) { + return packFloatx80(0, one_exp, one_sig); + } + + SET_PREC; + + compact = floatx80_make_compact(aExp, aSig); + + if (compact > 0x400CB167) { + if (compact > 0x400CB2B3) { + RESET_PREC; + return roundAndPackFloatx80(status->floatx80_rounding_precision, 0, 0x8000, one_sig, 0, status); + } else { + fp0 = packFloatx80(0, aExp, aSig); + fp0 = floatx80_sub(fp0, float64_to_floatx80(LIT64(0x40C62D38D3D64634), status), status); + fp0 = floatx80_sub(fp0, float64_to_floatx80(LIT64(0x3D6F90AEB1E75CC7), status), status); + fp0 = floatx80_etox(fp0, status); + fp1 = packFloatx80(0, 0x7FFB, one_sig); + + RESET_PREC; + + a = floatx80_mul(fp0, fp1, status); + + float_raise(float_flag_inexact, status); + + return a; + } + } + + fp0 = packFloatx80(0, aExp, aSig); // |X| + fp0 = floatx80_etox(fp0, status); // EXP(|X|) + fp0 = floatx80_mul(fp0, float32_to_floatx80(0x3F000000, status), status); // (1/2)*EXP(|X|) + fp1 = float32_to_floatx80(0x3E800000, status); // 1/4 + fp1 = floatx80_div(fp1, fp0, status); // 1/(2*EXP(|X|)) + + RESET_PREC; + + a = floatx80_add(fp0, fp1, status); + + float_raise(float_flag_inexact, status); + + return a; } /*---------------------------------------------------------------------------- @@ -693,140 +672,134 @@ floatx80 floatx80_cosh(floatx80 a, float_status *status) floatx80 floatx80_etox(floatx80 a, float_status *status) { - flag aSign; - int32_t aExp; - uint64_t aSig; - - int8_t user_rnd_mode, user_rnd_prec; - - int32_t compact, n, j, k, m, m1; - floatx80 fp0, fp1, fp2, fp3, l2, scale, adjscale; - flag adjflag; - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - - if (aExp == 0x7FFF) { - if ((uint64_t) (aSig<<1)) return propagateFloatx80NaNOneArg(a, status); - if (aSign) return packFloatx80(0, 0, 0); - return packFloatx80(0, 0x7FFF, floatx80_default_infinity_low); - } - - if (aExp == 0 && aSig == 0) { - return packFloatx80(0, one_exp, one_sig); - } - - user_rnd_mode = status->float_rounding_mode; - user_rnd_prec = status->floatx80_rounding_precision; - - adjflag = 0; - - if (aExp >= 0x3FBE) { // |X| >= 2^(-65) - compact = floatx80_make_compact(aExp, aSig); - - if (compact < 0x400CB167) { // |X| < 16380 log2 - fp0 = a; - fp1 = a; - fp0 = floatx80_mul(fp0, float32_to_floatx80(0x42B8AA3B, status), status); // 64/log2 * X - adjflag = 0; - n = floatx80_to_int32(fp0, status); // int(64/log2*X) - fp0 = int32_to_floatx80(n); - - j = n & 0x3F; // J = N mod 64 - m = n / 64; // NOTE: this is really arithmetic right shift by 6 - if (n < 0 && j) { // arithmetic right shift is division and round towards minus infinity - m--; - } - m += 0x3FFF; // biased exponent of 2^(M) - - expcont1: - fp2 = fp0; // N - fp0 = floatx80_mul(fp0, float32_to_floatx80(0xBC317218, status), status); // N * L1, L1 = lead(-log2/64) - l2 = packFloatx80(0, 0x3FDC, LIT64(0x82E308654361C4C6)); - fp2 = floatx80_mul(fp2, l2, status); // N * L2, L1+L2 = -log2/64 - fp0 = floatx80_add(fp0, fp1, status); // X + N*L1 - fp0 = floatx80_add(fp0, fp2, status); // R - - fp1 = floatx80_mul(fp0, fp0, status); // S = R*R - fp2 = float32_to_floatx80(0x3AB60B70, status); // A5 - fp2 = floatx80_mul(fp2, fp1, status); // fp2 is S*A5 - fp3 = floatx80_mul(float32_to_floatx80(0x3C088895, status), fp1, status); // fp3 is S*A4 - fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3FA5555555554431), status), status); // fp2 is A3+S*A5 - fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0x3FC5555555554018), status), status); // fp3 is A2+S*A4 - fp2 = floatx80_mul(fp2, fp1, status); // fp2 is S*(A3+S*A5) - fp3 = floatx80_mul(fp3, fp1, status); // fp3 is S*(A2+S*A4) - fp2 = floatx80_add(fp2, float32_to_floatx80(0x3F000000, status), status); // fp2 is A1+S*(A3+S*A5) - fp3 = floatx80_mul(fp3, fp0, status); // fp3 IS R*S*(A2+S*A4) - fp2 = floatx80_mul(fp2, fp1, status); // fp2 IS S*(A1+S*(A3+S*A5)) - fp0 = floatx80_add(fp0, fp3, status); // fp0 IS R+R*S*(A2+S*A4) - fp0 = floatx80_add(fp0, fp2, status); // fp0 IS EXP(R) - 1 - - fp1 = exp_tbl[j]; - fp0 = floatx80_mul(fp0, fp1, status); // 2^(J/64)*(Exp(R)-1) - fp0 = floatx80_add(fp0, float32_to_floatx80(exp_tbl2[j], status), status); // accurate 2^(J/64) - fp0 = floatx80_add(fp0, fp1, status); // 2^(J/64) + 2^(J/64)*(Exp(R)-1) - - scale = packFloatx80(0, m, one_sig); - if (adjflag) { - adjscale = packFloatx80(0, m1, one_sig); - fp0 = floatx80_mul(fp0, adjscale, status); - } - - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - a = floatx80_mul(fp0, scale, status); - - float_raise(float_flag_inexact, status); - - return a; - } else { // |X| >= 16380 log2 - if (compact > 0x400CB27C) { // |X| >= 16480 log2 - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - if (aSign) { - a = roundAndPackFloatx80(status->floatx80_rounding_precision, 0, -0x1000, aSig, 0, status); - } else { - a = roundAndPackFloatx80(status->floatx80_rounding_precision, 0, 0x8000, aSig, 0, status); - } - float_raise(float_flag_inexact, status); - - return a; - } else { - fp0 = a; - fp1 = a; - fp0 = floatx80_mul(fp0, float32_to_floatx80(0x42B8AA3B, status), status); // 64/log2 * X - adjflag = 1; - n = floatx80_to_int32(fp0, status); // int(64/log2*X) - fp0 = int32_to_floatx80(n); - - j = n & 0x3F; // J = N mod 64 - k = n / 64; // NOTE: this is really arithmetic right shift by 6 - if (n < 0 && j) { // arithmetic right shift is division and round towards minus infinity - k--; - } - m1 = k / 2; // NOTE: this is really arithmetic right shift by 1 - if (k < 0 && (k & 1)) { // arithmetic right shift is division and round towards minus infinity - m1--; - } - m = k - m1; - m1 += 0x3FFF; // biased exponent of 2^(M1) - m += 0x3FFF; // biased exponent of 2^(M) - - goto expcont1; - } - } - } else { // |X| < 2^(-65) - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - a = floatx80_add(a, float32_to_floatx80(0x3F800000, status), status); // 1 + X - - float_raise(float_flag_inexact, status); - - return a; - } + flag aSign; + int32_t aExp; + uint64_t aSig; + + int32_t compact, n, j, k, m, m1; + floatx80 fp0, fp1, fp2, fp3, l2, scale, adjscale; + flag adjflag; + + aSig = extractFloatx80Frac(a); + aExp = extractFloatx80Exp(a); + aSign = extractFloatx80Sign(a); + + if (aExp == 0x7FFF) { + if ((uint64_t) (aSig<<1)) return propagateFloatx80NaNOneArg(a, status); + if (aSign) return packFloatx80(0, 0, 0); + return packFloatx80(0, 0x7FFF, floatx80_default_infinity_low); + } + + if (aExp == 0 && aSig == 0) { + return packFloatx80(0, one_exp, one_sig); + } + + SET_PREC; + + adjflag = 0; + + if (aExp >= 0x3FBE) { // |X| >= 2^(-65) + compact = floatx80_make_compact(aExp, aSig); + + if (compact < 0x400CB167) { // |X| < 16380 log2 + fp0 = a; + fp1 = a; + fp0 = floatx80_mul(fp0, float32_to_floatx80(0x42B8AA3B, status), status); // 64/log2 * X + adjflag = 0; + n = floatx80_to_int32(fp0, status); // int(64/log2*X) + fp0 = int32_to_floatx80(n); + + j = n & 0x3F; // J = N mod 64 + m = n / 64; // NOTE: this is really arithmetic right shift by 6 + if (n < 0 && j) { // arithmetic right shift is division and round towards minus infinity + m--; + } + m += 0x3FFF; // biased exponent of 2^(M) + + expcont1: + fp2 = fp0; // N + fp0 = floatx80_mul(fp0, float32_to_floatx80(0xBC317218, status), status); // N * L1, L1 = lead(-log2/64) + l2 = packFloatx80(0, 0x3FDC, LIT64(0x82E308654361C4C6)); + fp2 = floatx80_mul(fp2, l2, status); // N * L2, L1+L2 = -log2/64 + fp0 = floatx80_add(fp0, fp1, status); // X + N*L1 + fp0 = floatx80_add(fp0, fp2, status); // R + + fp1 = floatx80_mul(fp0, fp0, status); // S = R*R + fp2 = float32_to_floatx80(0x3AB60B70, status); // A5 + fp2 = floatx80_mul(fp2, fp1, status); // fp2 is S*A5 + fp3 = floatx80_mul(float32_to_floatx80(0x3C088895, status), fp1, status); // fp3 is S*A4 + fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3FA5555555554431), status), status); // fp2 is A3+S*A5 + fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0x3FC5555555554018), status), status); // fp3 is A2+S*A4 + fp2 = floatx80_mul(fp2, fp1, status); // fp2 is S*(A3+S*A5) + fp3 = floatx80_mul(fp3, fp1, status); // fp3 is S*(A2+S*A4) + fp2 = floatx80_add(fp2, float32_to_floatx80(0x3F000000, status), status); // fp2 is A1+S*(A3+S*A5) + fp3 = floatx80_mul(fp3, fp0, status); // fp3 IS R*S*(A2+S*A4) + fp2 = floatx80_mul(fp2, fp1, status); // fp2 IS S*(A1+S*(A3+S*A5)) + fp0 = floatx80_add(fp0, fp3, status); // fp0 IS R+R*S*(A2+S*A4) + fp0 = floatx80_add(fp0, fp2, status); // fp0 IS EXP(R) - 1 + + fp1 = exp_tbl[j]; + fp0 = floatx80_mul(fp0, fp1, status); // 2^(J/64)*(Exp(R)-1) + fp0 = floatx80_add(fp0, float32_to_floatx80(exp_tbl2[j], status), status); // accurate 2^(J/64) + fp0 = floatx80_add(fp0, fp1, status); // 2^(J/64) + 2^(J/64)*(Exp(R)-1) + + scale = packFloatx80(0, m, one_sig); + if (adjflag) { + adjscale = packFloatx80(0, m1, one_sig); + fp0 = floatx80_mul(fp0, adjscale, status); + } + + RESET_PREC; + + a = floatx80_mul(fp0, scale, status); + + float_raise(float_flag_inexact, status); + + return a; + } else { // |X| >= 16380 log2 + if (compact > 0x400CB27C) { // |X| >= 16480 log2 + RESET_PREC; + if (aSign) { + a = roundAndPackFloatx80(status->floatx80_rounding_precision, 0, -0x1000, aSig, 0, status); + } else { + a = roundAndPackFloatx80(status->floatx80_rounding_precision, 0, 0x8000, aSig, 0, status); + } + float_raise(float_flag_inexact, status); + + return a; + } else { + fp0 = a; + fp1 = a; + fp0 = floatx80_mul(fp0, float32_to_floatx80(0x42B8AA3B, status), status); // 64/log2 * X + adjflag = 1; + n = floatx80_to_int32(fp0, status); // int(64/log2*X) + fp0 = int32_to_floatx80(n); + + j = n & 0x3F; // J = N mod 64 + k = n / 64; // NOTE: this is really arithmetic right shift by 6 + if (n < 0 && j) { // arithmetic right shift is division and round towards minus infinity + k--; + } + m1 = k / 2; // NOTE: this is really arithmetic right shift by 1 + if (k < 0 && (k & 1)) { // arithmetic right shift is division and round towards minus infinity + m1--; + } + m = k - m1; + m1 += 0x3FFF; // biased exponent of 2^(M1) + m += 0x3FFF; // biased exponent of 2^(M) + + goto expcont1; + } + } + } else { // |X| < 2^(-65) + RESET_PREC; + + a = floatx80_add(a, float32_to_floatx80(0x3F800000, status), status); // 1 + X + + float_raise(float_flag_inexact, status); + + return a; + } } /*---------------------------------------------------------------------------- @@ -835,191 +808,182 @@ floatx80 floatx80_etox(floatx80 a, float_status *status) floatx80 floatx80_etoxm1(floatx80 a, float_status *status) { - flag aSign; - int32_t aExp; - uint64_t aSig; - - int8_t user_rnd_mode, user_rnd_prec; - - int32_t compact, n, j, m, m1; - floatx80 fp0, fp1, fp2, fp3, l2, sc, onebysc; - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - - if (aExp == 0x7FFF) { - if ((uint64_t) (aSig<<1)) return propagateFloatx80NaNOneArg(a, status); - if (aSign) return packFloatx80(aSign, one_exp, one_sig); - return packFloatx80(0, 0x7FFF, floatx80_default_infinity_low); - } - - if (aExp == 0 && aSig == 0) { - return packFloatx80(aSign, 0, 0); - } - - user_rnd_mode = status->float_rounding_mode; - user_rnd_prec = status->floatx80_rounding_precision; - - if (aExp >= 0x3FFD) { // |X| >= 1/4 - compact = floatx80_make_compact(aExp, aSig); - - if (compact <= 0x4004C215) { // |X| <= 70 log2 - fp0 = a; - fp1 = a; - fp0 = floatx80_mul(fp0, float32_to_floatx80(0x42B8AA3B, status), status); // 64/log2 * X - n = floatx80_to_int32(fp0, status); // int(64/log2*X) - fp0 = int32_to_floatx80(n); - - j = n & 0x3F; // J = N mod 64 - m = n / 64; // NOTE: this is really arithmetic right shift by 6 - if (n < 0 && j) { // arithmetic right shift is division and round towards minus infinity - m--; - } - m1 = -m; - //m += 0x3FFF; // biased exponent of 2^(M) - //m1 += 0x3FFF; // biased exponent of -2^(-M) - - fp2 = fp0; // N - fp0 = floatx80_mul(fp0, float32_to_floatx80(0xBC317218, status), status); // N * L1, L1 = lead(-log2/64) - l2 = packFloatx80(0, 0x3FDC, LIT64(0x82E308654361C4C6)); - fp2 = floatx80_mul(fp2, l2, status); // N * L2, L1+L2 = -log2/64 - fp0 = floatx80_add(fp0, fp1, status); // X + N*L1 - fp0 = floatx80_add(fp0, fp2, status); // R - - fp1 = floatx80_mul(fp0, fp0, status); // S = R*R - fp2 = float32_to_floatx80(0x3950097B, status); // A6 - fp2 = floatx80_mul(fp2, fp1, status); // fp2 is S*A6 - fp3 = floatx80_mul(float32_to_floatx80(0x3AB60B6A, status), fp1, status); // fp3 is S*A5 - fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3F81111111174385), status), status); // fp2 IS A4+S*A6 - fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0x3FA5555555554F5A), status), status); // fp3 is A3+S*A5 - fp2 = floatx80_mul(fp2, fp1, status); // fp2 IS S*(A4+S*A6) - fp3 = floatx80_mul(fp3, fp1, status); // fp3 IS S*(A3+S*A5) - fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3FC5555555555555), status), status); // fp2 IS A2+S*(A4+S*A6) - fp3 = floatx80_add(fp3, float32_to_floatx80(0x3F000000, status), status); // fp3 IS A1+S*(A3+S*A5) - fp2 = floatx80_mul(fp2, fp1, status); // fp2 IS S*(A2+S*(A4+S*A6)) - fp1 = floatx80_mul(fp1, fp3, status); // fp1 IS S*(A1+S*(A3+S*A5)) - fp2 = floatx80_mul(fp2, fp0, status); // fp2 IS R*S*(A2+S*(A4+S*A6)) - fp0 = floatx80_add(fp0, fp1, status); // fp0 IS R+S*(A1+S*(A3+S*A5)) - fp0 = floatx80_add(fp0, fp2, status); // fp0 IS EXP(R) - 1 - - fp0 = floatx80_mul(fp0, exp_tbl[j], status); // 2^(J/64)*(Exp(R)-1) - - if (m >= 64) { - fp1 = float32_to_floatx80(exp_tbl2[j], status); - onebysc = packFloatx80(1, m1 + 0x3FFF, one_sig); // -2^(-M) - fp1 = floatx80_add(fp1, onebysc, status); - fp0 = floatx80_add(fp0, fp1, status); - fp0 = floatx80_add(fp0, exp_tbl[j], status); - } else if (m < -3) { - fp0 = floatx80_add(fp0, float32_to_floatx80(exp_tbl2[j], status), status); - fp0 = floatx80_add(fp0, exp_tbl[j], status); - onebysc = packFloatx80(1, m1 + 0x3FFF, one_sig); // -2^(-M) - fp0 = floatx80_add(fp0, onebysc, status); - } else { // -3 <= m <= 63 - fp1 = exp_tbl[j]; - fp0 = floatx80_add(fp0, float32_to_floatx80(exp_tbl2[j], status), status); - onebysc = packFloatx80(1, m1 + 0x3FFF, one_sig); // -2^(-M) - fp1 = floatx80_add(fp1, onebysc, status); - fp0 = floatx80_add(fp0, fp1, status); - } - - sc = packFloatx80(0, m + 0x3FFF, one_sig); - - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - a = floatx80_mul(fp0, sc, status); - - float_raise(float_flag_inexact, status); - - return a; - } else { // |X| > 70 log2 - if (aSign) { - fp0 = float32_to_floatx80(0xBF800000, status); // -1 - - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - a = floatx80_add(fp0, float32_to_floatx80(0x00800000, status), status); // -1 + 2^(-126) - - float_raise(float_flag_inexact, status); - - return a; - } else { - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - return floatx80_etox(a, status); - } - } - } else { // |X| < 1/4 - if (aExp >= 0x3FBE) { - fp0 = a; - fp0 = floatx80_mul(fp0, fp0, status); // S = X*X - fp1 = float32_to_floatx80(0x2F30CAA8, status); // B12 - fp1 = floatx80_mul(fp1, fp0, status); // S * B12 - fp2 = float32_to_floatx80(0x310F8290, status); // B11 - fp1 = floatx80_add(fp1, float32_to_floatx80(0x32D73220, status), status); // B10 - fp2 = floatx80_mul(fp2, fp0, status); - fp1 = floatx80_mul(fp1, fp0, status); - fp2 = floatx80_add(fp2, float32_to_floatx80(0x3493F281, status), status); // B9 - fp1 = floatx80_add(fp1, float64_to_floatx80(LIT64(0x3EC71DE3A5774682), status), status); // B8 - fp2 = floatx80_mul(fp2, fp0, status); - fp1 = floatx80_mul(fp1, fp0, status); - fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3EFA01A019D7CB68), status), status); // B7 - fp1 = floatx80_add(fp1, float64_to_floatx80(LIT64(0x3F2A01A01A019DF3), status), status); // B6 - fp2 = floatx80_mul(fp2, fp0, status); - fp1 = floatx80_mul(fp1, fp0, status); - fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3F56C16C16C170E2), status), status); // B5 - fp1 = floatx80_add(fp1, float64_to_floatx80(LIT64(0x3F81111111111111), status), status); // B4 - fp2 = floatx80_mul(fp2, fp0, status); - fp1 = floatx80_mul(fp1, fp0, status); - fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3FA5555555555555), status), status); // B3 - fp3 = packFloatx80(0, 0x3FFC, LIT64(0xAAAAAAAAAAAAAAAB)); - fp1 = floatx80_add(fp1, fp3, status); // B2 - fp2 = floatx80_mul(fp2, fp0, status); - fp1 = floatx80_mul(fp1, fp0, status); - - fp2 = floatx80_mul(fp2, fp0, status); - fp1 = floatx80_mul(fp1, a, status); - - fp0 = floatx80_mul(fp0, float32_to_floatx80(0x3F000000, status), status); // S*B1 - fp1 = floatx80_add(fp1, fp2, status); // Q - fp0 = floatx80_add(fp0, fp1, status); // S*B1+Q - - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - a = floatx80_add(fp0, a, status); - - float_raise(float_flag_inexact, status); - - return a; - } else { // |X| < 2^(-65) - sc = packFloatx80(1, 1, one_sig); - fp0 = a; - - if (aExp < 0x0033) { // |X| < 2^(-16382) - fp0 = floatx80_mul(fp0, float64_to_floatx80(LIT64(0x48B0000000000000), status), status); - fp0 = floatx80_add(fp0, sc, status); - - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - a = floatx80_mul(fp0, float64_to_floatx80(LIT64(0x3730000000000000), status), status); - } else { - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - a = floatx80_add(fp0, sc, status); - } - - float_raise(float_flag_inexact, status); - - return a; - } - } + flag aSign; + int32_t aExp; + uint64_t aSig; + + int32_t compact, n, j, m, m1; + floatx80 fp0, fp1, fp2, fp3, l2, sc, onebysc; + + aSig = extractFloatx80Frac(a); + aExp = extractFloatx80Exp(a); + aSign = extractFloatx80Sign(a); + + if (aExp == 0x7FFF) { + if ((uint64_t) (aSig<<1)) return propagateFloatx80NaNOneArg(a, status); + if (aSign) return packFloatx80(aSign, one_exp, one_sig); + return packFloatx80(0, 0x7FFF, floatx80_default_infinity_low); + } + + if (aExp == 0 && aSig == 0) { + return packFloatx80(aSign, 0, 0); + } + + SET_PREC; + + if (aExp >= 0x3FFD) { // |X| >= 1/4 + compact = floatx80_make_compact(aExp, aSig); + + if (compact <= 0x4004C215) { // |X| <= 70 log2 + fp0 = a; + fp1 = a; + fp0 = floatx80_mul(fp0, float32_to_floatx80(0x42B8AA3B, status), status); // 64/log2 * X + n = floatx80_to_int32(fp0, status); // int(64/log2*X) + fp0 = int32_to_floatx80(n); + + j = n & 0x3F; // J = N mod 64 + m = n / 64; // NOTE: this is really arithmetic right shift by 6 + if (n < 0 && j) { // arithmetic right shift is division and round towards minus infinity + m--; + } + m1 = -m; + //m += 0x3FFF; // biased exponent of 2^(M) + //m1 += 0x3FFF; // biased exponent of -2^(-M) + + fp2 = fp0; // N + fp0 = floatx80_mul(fp0, float32_to_floatx80(0xBC317218, status), status); // N * L1, L1 = lead(-log2/64) + l2 = packFloatx80(0, 0x3FDC, LIT64(0x82E308654361C4C6)); + fp2 = floatx80_mul(fp2, l2, status); // N * L2, L1+L2 = -log2/64 + fp0 = floatx80_add(fp0, fp1, status); // X + N*L1 + fp0 = floatx80_add(fp0, fp2, status); // R + + fp1 = floatx80_mul(fp0, fp0, status); // S = R*R + fp2 = float32_to_floatx80(0x3950097B, status); // A6 + fp2 = floatx80_mul(fp2, fp1, status); // fp2 is S*A6 + fp3 = floatx80_mul(float32_to_floatx80(0x3AB60B6A, status), fp1, status); // fp3 is S*A5 + fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3F81111111174385), status), status); // fp2 IS A4+S*A6 + fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0x3FA5555555554F5A), status), status); // fp3 is A3+S*A5 + fp2 = floatx80_mul(fp2, fp1, status); // fp2 IS S*(A4+S*A6) + fp3 = floatx80_mul(fp3, fp1, status); // fp3 IS S*(A3+S*A5) + fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3FC5555555555555), status), status); // fp2 IS A2+S*(A4+S*A6) + fp3 = floatx80_add(fp3, float32_to_floatx80(0x3F000000, status), status); // fp3 IS A1+S*(A3+S*A5) + fp2 = floatx80_mul(fp2, fp1, status); // fp2 IS S*(A2+S*(A4+S*A6)) + fp1 = floatx80_mul(fp1, fp3, status); // fp1 IS S*(A1+S*(A3+S*A5)) + fp2 = floatx80_mul(fp2, fp0, status); // fp2 IS R*S*(A2+S*(A4+S*A6)) + fp0 = floatx80_add(fp0, fp1, status); // fp0 IS R+S*(A1+S*(A3+S*A5)) + fp0 = floatx80_add(fp0, fp2, status); // fp0 IS EXP(R) - 1 + + fp0 = floatx80_mul(fp0, exp_tbl[j], status); // 2^(J/64)*(Exp(R)-1) + + if (m >= 64) { + fp1 = float32_to_floatx80(exp_tbl2[j], status); + onebysc = packFloatx80(1, m1 + 0x3FFF, one_sig); // -2^(-M) + fp1 = floatx80_add(fp1, onebysc, status); + fp0 = floatx80_add(fp0, fp1, status); + fp0 = floatx80_add(fp0, exp_tbl[j], status); + } else if (m < -3) { + fp0 = floatx80_add(fp0, float32_to_floatx80(exp_tbl2[j], status), status); + fp0 = floatx80_add(fp0, exp_tbl[j], status); + onebysc = packFloatx80(1, m1 + 0x3FFF, one_sig); // -2^(-M) + fp0 = floatx80_add(fp0, onebysc, status); + } else { // -3 <= m <= 63 + fp1 = exp_tbl[j]; + fp0 = floatx80_add(fp0, float32_to_floatx80(exp_tbl2[j], status), status); + onebysc = packFloatx80(1, m1 + 0x3FFF, one_sig); // -2^(-M) + fp1 = floatx80_add(fp1, onebysc, status); + fp0 = floatx80_add(fp0, fp1, status); + } + + sc = packFloatx80(0, m + 0x3FFF, one_sig); + + RESET_PREC; + + a = floatx80_mul(fp0, sc, status); + + float_raise(float_flag_inexact, status); + + return a; + } else { // |X| > 70 log2 + if (aSign) { + fp0 = float32_to_floatx80(0xBF800000, status); // -1 + + RESET_PREC; + + a = floatx80_add(fp0, float32_to_floatx80(0x00800000, status), status); // -1 + 2^(-126) + + float_raise(float_flag_inexact, status); + + return a; + } else { + RESET_PREC; + + return floatx80_etox(a, status); + } + } + } else { // |X| < 1/4 + if (aExp >= 0x3FBE) { + fp0 = a; + fp0 = floatx80_mul(fp0, fp0, status); // S = X*X + fp1 = float32_to_floatx80(0x2F30CAA8, status); // B12 + fp1 = floatx80_mul(fp1, fp0, status); // S * B12 + fp2 = float32_to_floatx80(0x310F8290, status); // B11 + fp1 = floatx80_add(fp1, float32_to_floatx80(0x32D73220, status), status); // B10 + fp2 = floatx80_mul(fp2, fp0, status); + fp1 = floatx80_mul(fp1, fp0, status); + fp2 = floatx80_add(fp2, float32_to_floatx80(0x3493F281, status), status); // B9 + fp1 = floatx80_add(fp1, float64_to_floatx80(LIT64(0x3EC71DE3A5774682), status), status); // B8 + fp2 = floatx80_mul(fp2, fp0, status); + fp1 = floatx80_mul(fp1, fp0, status); + fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3EFA01A019D7CB68), status), status); // B7 + fp1 = floatx80_add(fp1, float64_to_floatx80(LIT64(0x3F2A01A01A019DF3), status), status); // B6 + fp2 = floatx80_mul(fp2, fp0, status); + fp1 = floatx80_mul(fp1, fp0, status); + fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3F56C16C16C170E2), status), status); // B5 + fp1 = floatx80_add(fp1, float64_to_floatx80(LIT64(0x3F81111111111111), status), status); // B4 + fp2 = floatx80_mul(fp2, fp0, status); + fp1 = floatx80_mul(fp1, fp0, status); + fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3FA5555555555555), status), status); // B3 + fp3 = packFloatx80(0, 0x3FFC, LIT64(0xAAAAAAAAAAAAAAAB)); + fp1 = floatx80_add(fp1, fp3, status); // B2 + fp2 = floatx80_mul(fp2, fp0, status); + fp1 = floatx80_mul(fp1, fp0, status); + + fp2 = floatx80_mul(fp2, fp0, status); + fp1 = floatx80_mul(fp1, a, status); + + fp0 = floatx80_mul(fp0, float32_to_floatx80(0x3F000000, status), status); // S*B1 + fp1 = floatx80_add(fp1, fp2, status); // Q + fp0 = floatx80_add(fp0, fp1, status); // S*B1+Q + + RESET_PREC; + + a = floatx80_add(fp0, a, status); + + float_raise(float_flag_inexact, status); + + return a; + } else { // |X| < 2^(-65) + sc = packFloatx80(1, 1, one_sig); + fp0 = a; + + if (aExp < 0x0033) { // |X| < 2^(-16382) + fp0 = floatx80_mul(fp0, float64_to_floatx80(LIT64(0x48B0000000000000), status), status); + fp0 = floatx80_add(fp0, sc, status); + + RESET_PREC; + + a = floatx80_mul(fp0, float64_to_floatx80(LIT64(0x3730000000000000), status), status); + } else { + RESET_PREC; + + a = floatx80_add(fp0, sc, status); + } + + float_raise(float_flag_inexact, status); + + return a; + } + } } /*---------------------------------------------------------------------------- @@ -1028,50 +992,46 @@ floatx80 floatx80_etoxm1(floatx80 a, float_status *status) floatx80 floatx80_log10(floatx80 a, float_status *status) { - flag aSign; - int32_t aExp; - uint64_t aSig; - - int8_t user_rnd_mode, user_rnd_prec; - - floatx80 fp0, fp1; - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - - if (aExp == 0x7FFF) { - if ((uint64_t) (aSig<<1)) propagateFloatx80NaNOneArg(a, status); - if (aSign == 0) - return packFloatx80(0, 0x7FFF, floatx80_default_infinity_low); - } - - if (aExp == 0 && aSig == 0) { - float_raise(float_flag_divbyzero, status); - return packFloatx80(1, 0x7FFF, floatx80_default_infinity_low); - } - - if (aSign) { - float_raise(float_flag_invalid, status); - a.low = floatx80_default_nan_low; - a.high = floatx80_default_nan_high; - return a; - } - - user_rnd_mode = status->float_rounding_mode; - user_rnd_prec = status->floatx80_rounding_precision; - - fp0 = floatx80_logn(a, status); - fp1 = packFloatx80(0, 0x3FFD, LIT64(0xDE5BD8A937287195)); // INV_L10 - - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - a = floatx80_mul(fp0, fp1, status); // LOGN(X)*INV_L10 - - float_raise(float_flag_inexact, status); - - return a; + flag aSign; + int32_t aExp; + uint64_t aSig; + + floatx80 fp0, fp1; + + aSig = extractFloatx80Frac(a); + aExp = extractFloatx80Exp(a); + aSign = extractFloatx80Sign(a); + + if (aExp == 0x7FFF) { + if ((uint64_t) (aSig<<1)) propagateFloatx80NaNOneArg(a, status); + if (aSign == 0) + return packFloatx80(0, 0x7FFF, floatx80_default_infinity_low); + } + + if (aExp == 0 && aSig == 0) { + float_raise(float_flag_divbyzero, status); + return packFloatx80(1, 0x7FFF, floatx80_default_infinity_low); + } + + if (aSign) { + float_raise(float_flag_invalid, status); + a.low = floatx80_default_nan_low; + a.high = floatx80_default_nan_high; + return a; + } + + SET_PREC; + + fp0 = floatx80_logn(a, status); + fp1 = packFloatx80(0, 0x3FFD, LIT64(0xDE5BD8A937287195)); // INV_L10 + + RESET_PREC; + + a = floatx80_mul(fp0, fp1, status); // LOGN(X)*INV_L10 + + float_raise(float_flag_inexact, status); + + return a; } /*---------------------------------------------------------------------------- @@ -1080,60 +1040,55 @@ floatx80 floatx80_log10(floatx80 a, float_status *status) floatx80 floatx80_log2(floatx80 a, float_status *status) { - flag aSign; - int32_t aExp; - uint64_t aSig; - - int8_t user_rnd_mode, user_rnd_prec; - - floatx80 fp0, fp1; - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - - if (aExp == 0x7FFF) { - if ((uint64_t) (aSig<<1)) propagateFloatx80NaNOneArg(a, status); - if (aSign == 0) - return packFloatx80(0, 0x7FFF, floatx80_default_infinity_low); - } - - if (aExp == 0) { - if (aSig == 0) { - float_raise(float_flag_divbyzero, status); - return packFloatx80(1, 0x7FFF, floatx80_default_infinity_low); - } - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); - } - - if (aSign) { - float_raise(float_flag_invalid, status); - a.low = floatx80_default_nan_low; - a.high = floatx80_default_nan_high; - return a; - } - - user_rnd_mode = status->float_rounding_mode; - user_rnd_prec = status->floatx80_rounding_precision; - - if (aSig == one_sig) { // X is 2^k - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - a = int32_to_floatx80(aExp-0x3FFF); - } else { - fp0 = floatx80_logn(a, status); - fp1 = packFloatx80(0, 0x3FFF, LIT64(0xB8AA3B295C17F0BC)); // INV_L2 - - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - a = floatx80_mul(fp0, fp1, status); // LOGN(X)*INV_L2 - } - - float_raise(float_flag_inexact, status); - - return a; + flag aSign; + int32_t aExp; + uint64_t aSig; + + floatx80 fp0, fp1; + + aSig = extractFloatx80Frac(a); + aExp = extractFloatx80Exp(a); + aSign = extractFloatx80Sign(a); + + if (aExp == 0x7FFF) { + if ((uint64_t) (aSig<<1)) propagateFloatx80NaNOneArg(a, status); + if (aSign == 0) + return packFloatx80(0, 0x7FFF, floatx80_default_infinity_low); + } + + if (aExp == 0) { + if (aSig == 0) { + float_raise(float_flag_divbyzero, status); + return packFloatx80(1, 0x7FFF, floatx80_default_infinity_low); + } + normalizeFloatx80Subnormal(aSig, &aExp, &aSig); + } + + if (aSign) { + float_raise(float_flag_invalid, status); + a.low = floatx80_default_nan_low; + a.high = floatx80_default_nan_high; + return a; + } + + SET_PREC; + + if (aSig == one_sig) { // X is 2^k + RESET_PREC; + + a = int32_to_floatx80(aExp-0x3FFF); + } else { + fp0 = floatx80_logn(a, status); + fp1 = packFloatx80(0, 0x3FFF, LIT64(0xB8AA3B295C17F0BC)); // INV_L2 + + RESET_PREC; + + a = floatx80_mul(fp0, fp1, status); // LOGN(X)*INV_L2 + } + + float_raise(float_flag_inexact, status); + + return a; } /*---------------------------------------------------------------------------- @@ -1142,140 +1097,133 @@ floatx80 floatx80_log2(floatx80 a, float_status *status) floatx80 floatx80_logn(floatx80 a, float_status *status) { - flag aSign; - int32_t aExp; - uint64_t aSig, fSig; - - int8_t user_rnd_mode, user_rnd_prec; - - int32_t compact, j, k, adjk; - floatx80 fp0, fp1, fp2, fp3, f, logof2, klog2, saveu; - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - - if (aExp == 0x7FFF) { - if ((uint64_t) (aSig<<1)) propagateFloatx80NaNOneArg(a, status); - if (aSign == 0) - return packFloatx80(0, 0x7FFF, floatx80_default_infinity_low); - } - - adjk = 0; - - if (aExp == 0) { - if (aSig == 0) { // zero - float_raise(float_flag_divbyzero, status); - return packFloatx80(1, 0x7FFF, floatx80_default_infinity_low); - } + flag aSign; + int32_t aExp; + uint64_t aSig, fSig; + + int32_t compact, j, k, adjk; + floatx80 fp0, fp1, fp2, fp3, f, logof2, klog2, saveu; + + aSig = extractFloatx80Frac(a); + aExp = extractFloatx80Exp(a); + aSign = extractFloatx80Sign(a); + + if (aExp == 0x7FFF) { + if ((uint64_t) (aSig<<1)) propagateFloatx80NaNOneArg(a, status); + if (aSign == 0) + return packFloatx80(0, 0x7FFF, floatx80_default_infinity_low); + } + + adjk = 0; + + if (aExp == 0) { + if (aSig == 0) { // zero + float_raise(float_flag_divbyzero, status); + return packFloatx80(1, 0x7FFF, floatx80_default_infinity_low); + } #if 1 - if ((aSig & one_sig) == 0) { // denormal - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); - adjk = -100; - aExp += 100; - a = packFloatx80(aSign, aExp, aSig); - } + if ((aSig & one_sig) == 0) { // denormal + normalizeFloatx80Subnormal(aSig, &aExp, &aSig); + adjk = -100; + aExp += 100; + a = packFloatx80(aSign, aExp, aSig); + } #else - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); + normalizeFloatx80Subnormal(aSig, &aExp, &aSig); #endif - } - - if (aSign) { - float_raise(float_flag_invalid, status); - a.low = floatx80_default_nan_low; - a.high = floatx80_default_nan_high; - return a; - } - - user_rnd_mode = status->float_rounding_mode; - user_rnd_prec = status->floatx80_rounding_precision; - - compact = floatx80_make_compact(aExp, aSig); - - if (compact < 0x3FFEF07D || compact > 0x3FFF8841) { // |X| < 15/16 or |X| > 17/16 - k = aExp - 0x3FFF; - k += adjk; - fp1 = int32_to_floatx80(k); - - fSig = (aSig & LIT64(0xFE00000000000000)) | LIT64(0x0100000000000000); - j = (fSig >> 56) & 0x7E; // DISPLACEMENT FOR 1/F - - f = packFloatx80(0, 0x3FFF, fSig); // F - fp0 = packFloatx80(0, 0x3FFF, aSig); // Y - - fp0 = floatx80_sub(fp0, f, status); // Y-F - - // LP1CONT1 - fp0 = floatx80_mul(fp0, log_tbl[j], status); // FP0 IS U = (Y-F)/F - logof2 = packFloatx80(0, 0x3FFE, LIT64(0xB17217F7D1CF79AC)); - klog2 = floatx80_mul(fp1, logof2, status); // FP1 IS K*LOG2 - fp2 = floatx80_mul(fp0, fp0, status); // FP2 IS V=U*U - - fp3 = fp2; - fp1 = fp2; - - fp1 = floatx80_mul(fp1, float64_to_floatx80(LIT64(0x3FC2499AB5E4040B), status), status); // V*A6 - fp2 = floatx80_mul(fp2, float64_to_floatx80(LIT64(0xBFC555B5848CB7DB), status), status); // V*A5 - fp1 = floatx80_add(fp1, float64_to_floatx80(LIT64(0x3FC99999987D8730), status), status); // A4+V*A6 - fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0xBFCFFFFFFF6F7E97), status), status); // A3+V*A5 - fp1 = floatx80_mul(fp1, fp3, status); // V*(A4+V*A6) - fp2 = floatx80_mul(fp2, fp3, status); // V*(A3+V*A5) - fp1 = floatx80_add(fp1, float64_to_floatx80(LIT64(0x3FD55555555555A4), status), status); // A2+V*(A4+V*A6) - fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0xBFE0000000000008), status), status); // A1+V*(A3+V*A5) - fp1 = floatx80_mul(fp1, fp3, status); // V*(A2+V*(A4+V*A6)) - fp2 = floatx80_mul(fp2, fp3, status); // V*(A1+V*(A3+V*A5)) - fp1 = floatx80_mul(fp1, fp0, status); // U*V*(A2+V*(A4+V*A6)) - fp0 = floatx80_add(fp0, fp2, status); // U+V*(A1+V*(A3+V*A5)) - - fp1 = floatx80_add(fp1, log_tbl[j+1], status); // LOG(F)+U*V*(A2+V*(A4+V*A6)) - fp0 = floatx80_add(fp0, fp1, status); // FP0 IS LOG(F) + LOG(1+U) - - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - a = floatx80_add(fp0, klog2, status); - - float_raise(float_flag_inexact, status); - - return a; - } else { // |X-1| >= 1/16 - fp0 = a; - fp1 = a; - fp1 = floatx80_sub(fp1, float32_to_floatx80(0x3F800000, status), status); // FP1 IS X-1 - fp0 = floatx80_add(fp0, float32_to_floatx80(0x3F800000, status), status); // FP0 IS X+1 - fp1 = floatx80_add(fp1, fp1, status); // FP1 IS 2(X-1) - - // LP1CONT2 - fp1 = floatx80_div(fp1, fp0, status); // U - saveu = fp1; - fp0 = floatx80_mul(fp1, fp1, status); // FP0 IS V = U*U - fp1 = floatx80_mul(fp0, fp0, status); // FP1 IS W = V*V - - fp3 = float64_to_floatx80(LIT64(0x3F175496ADD7DAD6), status); // B5 - fp2 = float64_to_floatx80(LIT64(0x3F3C71C2FE80C7E0), status); // B4 - fp3 = floatx80_mul(fp3, fp1, status); // W*B5 - fp2 = floatx80_mul(fp2, fp1, status); // W*B4 - fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0x3F624924928BCCFF), status), status); // B3+W*B5 - fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3F899999999995EC), status), status); // B2+W*B4 - fp1 = floatx80_mul(fp1, fp3, status); // W*(B3+W*B5) - fp2 = floatx80_mul(fp2, fp0, status); // V*(B2+W*B4) - fp1 = floatx80_add(fp1, float64_to_floatx80(LIT64(0x3FB5555555555555), status), status); // B1+W*(B3+W*B5) - - fp0 = floatx80_mul(fp0, saveu, status); // FP0 IS U*V - fp1 = floatx80_add(fp1, fp2, status); // B1+W*(B3+W*B5) + V*(B2+W*B4) - fp0 = floatx80_mul(fp0, fp1, status); // U*V*( [B1+W*(B3+W*B5)] + [V*(B2+W*B4)] ) - - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - a = floatx80_add(fp0, saveu, status); - - if (!floatx80_is_zero(a)) { - float_raise(float_flag_inexact, status); - } - - return a; - } + } + + if (aSign) { + float_raise(float_flag_invalid, status); + a.low = floatx80_default_nan_low; + a.high = floatx80_default_nan_high; + return a; + } + + SET_PREC; + + compact = floatx80_make_compact(aExp, aSig); + + if (compact < 0x3FFEF07D || compact > 0x3FFF8841) { // |X| < 15/16 or |X| > 17/16 + k = aExp - 0x3FFF; + k += adjk; + fp1 = int32_to_floatx80(k); + + fSig = (aSig & LIT64(0xFE00000000000000)) | LIT64(0x0100000000000000); + j = (fSig >> 56) & 0x7E; // DISPLACEMENT FOR 1/F + + f = packFloatx80(0, 0x3FFF, fSig); // F + fp0 = packFloatx80(0, 0x3FFF, aSig); // Y + + fp0 = floatx80_sub(fp0, f, status); // Y-F + + // LP1CONT1 + fp0 = floatx80_mul(fp0, log_tbl[j], status); // FP0 IS U = (Y-F)/F + logof2 = packFloatx80(0, 0x3FFE, LIT64(0xB17217F7D1CF79AC)); + klog2 = floatx80_mul(fp1, logof2, status); // FP1 IS K*LOG2 + fp2 = floatx80_mul(fp0, fp0, status); // FP2 IS V=U*U + + fp3 = fp2; + fp1 = fp2; + + fp1 = floatx80_mul(fp1, float64_to_floatx80(LIT64(0x3FC2499AB5E4040B), status), status); // V*A6 + fp2 = floatx80_mul(fp2, float64_to_floatx80(LIT64(0xBFC555B5848CB7DB), status), status); // V*A5 + fp1 = floatx80_add(fp1, float64_to_floatx80(LIT64(0x3FC99999987D8730), status), status); // A4+V*A6 + fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0xBFCFFFFFFF6F7E97), status), status); // A3+V*A5 + fp1 = floatx80_mul(fp1, fp3, status); // V*(A4+V*A6) + fp2 = floatx80_mul(fp2, fp3, status); // V*(A3+V*A5) + fp1 = floatx80_add(fp1, float64_to_floatx80(LIT64(0x3FD55555555555A4), status), status); // A2+V*(A4+V*A6) + fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0xBFE0000000000008), status), status); // A1+V*(A3+V*A5) + fp1 = floatx80_mul(fp1, fp3, status); // V*(A2+V*(A4+V*A6)) + fp2 = floatx80_mul(fp2, fp3, status); // V*(A1+V*(A3+V*A5)) + fp1 = floatx80_mul(fp1, fp0, status); // U*V*(A2+V*(A4+V*A6)) + fp0 = floatx80_add(fp0, fp2, status); // U+V*(A1+V*(A3+V*A5)) + + fp1 = floatx80_add(fp1, log_tbl[j+1], status); // LOG(F)+U*V*(A2+V*(A4+V*A6)) + fp0 = floatx80_add(fp0, fp1, status); // FP0 IS LOG(F) + LOG(1+U) + + RESET_PREC; + + a = floatx80_add(fp0, klog2, status); + + float_raise(float_flag_inexact, status); + + return a; + } else { // |X-1| >= 1/16 + fp0 = a; + fp1 = a; + fp1 = floatx80_sub(fp1, float32_to_floatx80(0x3F800000, status), status); // FP1 IS X-1 + fp0 = floatx80_add(fp0, float32_to_floatx80(0x3F800000, status), status); // FP0 IS X+1 + fp1 = floatx80_add(fp1, fp1, status); // FP1 IS 2(X-1) + + // LP1CONT2 + fp1 = floatx80_div(fp1, fp0, status); // U + saveu = fp1; + fp0 = floatx80_mul(fp1, fp1, status); // FP0 IS V = U*U + fp1 = floatx80_mul(fp0, fp0, status); // FP1 IS W = V*V + + fp3 = float64_to_floatx80(LIT64(0x3F175496ADD7DAD6), status); // B5 + fp2 = float64_to_floatx80(LIT64(0x3F3C71C2FE80C7E0), status); // B4 + fp3 = floatx80_mul(fp3, fp1, status); // W*B5 + fp2 = floatx80_mul(fp2, fp1, status); // W*B4 + fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0x3F624924928BCCFF), status), status); // B3+W*B5 + fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3F899999999995EC), status), status); // B2+W*B4 + fp1 = floatx80_mul(fp1, fp3, status); // W*(B3+W*B5) + fp2 = floatx80_mul(fp2, fp0, status); // V*(B2+W*B4) + fp1 = floatx80_add(fp1, float64_to_floatx80(LIT64(0x3FB5555555555555), status), status); // B1+W*(B3+W*B5) + + fp0 = floatx80_mul(fp0, saveu, status); // FP0 IS U*V + fp1 = floatx80_add(fp1, fp2, status); // B1+W*(B3+W*B5) + V*(B2+W*B4) + fp0 = floatx80_mul(fp0, fp1, status); // U*V*( [B1+W*(B3+W*B5)] + [V*(B2+W*B4)] ) + + RESET_PREC; + + a = floatx80_add(fp0, saveu, status); + + float_raise(float_flag_inexact, status); + + return a; + } } /*---------------------------------------------------------------------------- @@ -1284,166 +1232,159 @@ floatx80 floatx80_logn(floatx80 a, float_status *status) floatx80 floatx80_lognp1(floatx80 a, float_status *status) { - flag aSign; - int32_t aExp; - uint64_t aSig, fSig; - - int8_t user_rnd_mode, user_rnd_prec; - - int32_t compact, j, k; - floatx80 fp0, fp1, fp2, fp3, f, logof2, klog2, saveu; - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - - if (aExp == 0x7FFF) { - if ((uint64_t) (aSig<<1)) propagateFloatx80NaNOneArg(a, status); - if (aSign) { - float_raise(float_flag_invalid, status); - a.low = floatx80_default_nan_low; - a.high = floatx80_default_nan_high; - return a; - } - return packFloatx80(0, 0x7FFF, floatx80_default_infinity_low); - } - - if (aExp == 0 && aSig == 0) { - return packFloatx80(aSign, 0, 0); - } - - if (aSign && aExp >= one_exp) { - if (aExp == one_exp && aSig == one_sig) { - float_raise(float_flag_divbyzero, status); - packFloatx80(aSign, 0x7FFF, floatx80_default_infinity_low); - } - float_raise(float_flag_invalid, status); - a.low = floatx80_default_nan_low; - a.high = floatx80_default_nan_high; - return a; - } - - if (aExp < 0x3f99 || (aExp == 0x3f99 && aSig == one_sig)) { // <= min threshold - float_raise(float_flag_inexact, status); - return floatx80_move(a, status); - } - - user_rnd_mode = status->float_rounding_mode; - user_rnd_prec = status->floatx80_rounding_precision; - - compact = floatx80_make_compact(aExp, aSig); - - fp0 = a; // Z - fp1 = a; - - fp0 = floatx80_add(fp0, float32_to_floatx80(0x3F800000, status), status); // X = (1+Z) - - aExp = extractFloatx80Exp(fp0); - aSig = extractFloatx80Frac(fp0); - - compact = floatx80_make_compact(aExp, aSig); - - if (compact < 0x3FFE8000 || compact > 0x3FFFC000) { // |X| < 1/2 or |X| > 3/2 - k = aExp - 0x3FFF; - fp1 = int32_to_floatx80(k); - - fSig = (aSig & LIT64(0xFE00000000000000)) | LIT64(0x0100000000000000); - j = (fSig >> 56) & 0x7E; // DISPLACEMENT FOR 1/F - - f = packFloatx80(0, 0x3FFF, fSig); // F - fp0 = packFloatx80(0, 0x3FFF, aSig); // Y - - fp0 = floatx80_sub(fp0, f, status); // Y-F - - lp1cont1: - // LP1CONT1 - fp0 = floatx80_mul(fp0, log_tbl[j], status); // FP0 IS U = (Y-F)/F - logof2 = packFloatx80(0, 0x3FFE, LIT64(0xB17217F7D1CF79AC)); - klog2 = floatx80_mul(fp1, logof2, status); // FP1 IS K*LOG2 - fp2 = floatx80_mul(fp0, fp0, status); // FP2 IS V=U*U - - fp3 = fp2; - fp1 = fp2; - - fp1 = floatx80_mul(fp1, float64_to_floatx80(LIT64(0x3FC2499AB5E4040B), status), status); // V*A6 - fp2 = floatx80_mul(fp2, float64_to_floatx80(LIT64(0xBFC555B5848CB7DB), status), status); // V*A5 - fp1 = floatx80_add(fp1, float64_to_floatx80(LIT64(0x3FC99999987D8730), status), status); // A4+V*A6 - fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0xBFCFFFFFFF6F7E97), status), status); // A3+V*A5 - fp1 = floatx80_mul(fp1, fp3, status); // V*(A4+V*A6) - fp2 = floatx80_mul(fp2, fp3, status); // V*(A3+V*A5) - fp1 = floatx80_add(fp1, float64_to_floatx80(LIT64(0x3FD55555555555A4), status), status); // A2+V*(A4+V*A6) - fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0xBFE0000000000008), status), status); // A1+V*(A3+V*A5) - fp1 = floatx80_mul(fp1, fp3, status); // V*(A2+V*(A4+V*A6)) - fp2 = floatx80_mul(fp2, fp3, status); // V*(A1+V*(A3+V*A5)) - fp1 = floatx80_mul(fp1, fp0, status); // U*V*(A2+V*(A4+V*A6)) - fp0 = floatx80_add(fp0, fp2, status); // U+V*(A1+V*(A3+V*A5)) - - fp1 = floatx80_add(fp1, log_tbl[j+1], status); // LOG(F)+U*V*(A2+V*(A4+V*A6)) - fp0 = floatx80_add(fp0, fp1, status); // FP0 IS LOG(F) + LOG(1+U) - - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - a = floatx80_add(fp0, klog2, status); - - float_raise(float_flag_inexact, status); - - return a; - } else if (compact < 0x3FFEF07D || compact > 0x3FFF8841) { // |X| < 1/16 or |X| > -1/16 - // LP1CARE - fSig = (aSig & LIT64(0xFE00000000000000)) | LIT64(0x0100000000000000); - f = packFloatx80(0, 0x3FFF, fSig); // F - j = (fSig >> 56) & 0x7E; // DISPLACEMENT FOR 1/F - - if (compact >= 0x3FFF8000) { // 1+Z >= 1 - // KISZERO - fp0 = floatx80_sub(float32_to_floatx80(0x3F800000, status), f, status); // 1-F - fp0 = floatx80_add(fp0, fp1, status); // FP0 IS Y-F = (1-F)+Z - fp1 = packFloatx80(0, 0, 0); // K = 0 - } else { - // KISNEG - fp0 = floatx80_sub(float32_to_floatx80(0x40000000, status), f, status); // 2-F - fp1 = floatx80_add(fp1, fp1, status); // 2Z - fp0 = floatx80_add(fp0, fp1, status); // FP0 IS Y-F = (2-F)+2Z - fp1 = packFloatx80(1, one_exp, one_sig); // K = -1 - } - goto lp1cont1; - } else { - // LP1ONE16 - fp1 = floatx80_add(fp1, fp1, status); // FP1 IS 2Z - fp0 = floatx80_add(fp0, float32_to_floatx80(0x3F800000, status), status); // FP0 IS 1+X - - // LP1CONT2 - fp1 = floatx80_div(fp1, fp0, status); // U - saveu = fp1; - fp0 = floatx80_mul(fp1, fp1, status); // FP0 IS V = U*U - fp1 = floatx80_mul(fp0, fp0, status); // FP1 IS W = V*V - - fp3 = float64_to_floatx80(LIT64(0x3F175496ADD7DAD6), status); // B5 - fp2 = float64_to_floatx80(LIT64(0x3F3C71C2FE80C7E0), status); // B4 - fp3 = floatx80_mul(fp3, fp1, status); // W*B5 - fp2 = floatx80_mul(fp2, fp1, status); // W*B4 - fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0x3F624924928BCCFF), status), status); // B3+W*B5 - fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3F899999999995EC), status), status); // B2+W*B4 - fp1 = floatx80_mul(fp1, fp3, status); // W*(B3+W*B5) - fp2 = floatx80_mul(fp2, fp0, status); // V*(B2+W*B4) - fp1 = floatx80_add(fp1, float64_to_floatx80(LIT64(0x3FB5555555555555), status), status); // B1+W*(B3+W*B5) - - fp0 = floatx80_mul(fp0, saveu, status); // FP0 IS U*V - fp1 = floatx80_add(fp1, fp2, status); // B1+W*(B3+W*B5) + V*(B2+W*B4) - fp0 = floatx80_mul(fp0, fp1, status); // U*V*( [B1+W*(B3+W*B5)] + [V*(B2+W*B4)] ) - - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - a = floatx80_add(fp0, saveu, status); - - if (!floatx80_is_zero(a)) { - float_raise(float_flag_inexact, status); - } - - return a; - } + flag aSign; + int32_t aExp; + uint64_t aSig, fSig; + + int32_t compact, j, k; + floatx80 fp0, fp1, fp2, fp3, f, logof2, klog2, saveu; + + aSig = extractFloatx80Frac(a); + aExp = extractFloatx80Exp(a); + aSign = extractFloatx80Sign(a); + + if (aExp == 0x7FFF) { + if ((uint64_t) (aSig<<1)) propagateFloatx80NaNOneArg(a, status); + if (aSign) { + float_raise(float_flag_invalid, status); + a.low = floatx80_default_nan_low; + a.high = floatx80_default_nan_high; + return a; + } + return packFloatx80(0, 0x7FFF, floatx80_default_infinity_low); + } + + if (aExp == 0 && aSig == 0) { + return packFloatx80(aSign, 0, 0); + } + + if (aSign && aExp >= one_exp) { + if (aExp == one_exp && aSig == one_sig) { + float_raise(float_flag_divbyzero, status); + packFloatx80(aSign, 0x7FFF, floatx80_default_infinity_low); + } + float_raise(float_flag_invalid, status); + a.low = floatx80_default_nan_low; + a.high = floatx80_default_nan_high; + return a; + } + + if (aExp < 0x3f99 || (aExp == 0x3f99 && aSig == one_sig)) { // <= min threshold + float_raise(float_flag_inexact, status); + return floatx80_move(a, status); + } + + SET_PREC; + + compact = floatx80_make_compact(aExp, aSig); + + fp0 = a; // Z + fp1 = a; + + fp0 = floatx80_add(fp0, float32_to_floatx80(0x3F800000, status), status); // X = (1+Z) + + aExp = extractFloatx80Exp(fp0); + aSig = extractFloatx80Frac(fp0); + + compact = floatx80_make_compact(aExp, aSig); + + if (compact < 0x3FFE8000 || compact > 0x3FFFC000) { // |X| < 1/2 or |X| > 3/2 + k = aExp - 0x3FFF; + fp1 = int32_to_floatx80(k); + + fSig = (aSig & LIT64(0xFE00000000000000)) | LIT64(0x0100000000000000); + j = (fSig >> 56) & 0x7E; // DISPLACEMENT FOR 1/F + + f = packFloatx80(0, 0x3FFF, fSig); // F + fp0 = packFloatx80(0, 0x3FFF, aSig); // Y + + fp0 = floatx80_sub(fp0, f, status); // Y-F + + lp1cont1: + // LP1CONT1 + fp0 = floatx80_mul(fp0, log_tbl[j], status); // FP0 IS U = (Y-F)/F + logof2 = packFloatx80(0, 0x3FFE, LIT64(0xB17217F7D1CF79AC)); + klog2 = floatx80_mul(fp1, logof2, status); // FP1 IS K*LOG2 + fp2 = floatx80_mul(fp0, fp0, status); // FP2 IS V=U*U + + fp3 = fp2; + fp1 = fp2; + + fp1 = floatx80_mul(fp1, float64_to_floatx80(LIT64(0x3FC2499AB5E4040B), status), status); // V*A6 + fp2 = floatx80_mul(fp2, float64_to_floatx80(LIT64(0xBFC555B5848CB7DB), status), status); // V*A5 + fp1 = floatx80_add(fp1, float64_to_floatx80(LIT64(0x3FC99999987D8730), status), status); // A4+V*A6 + fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0xBFCFFFFFFF6F7E97), status), status); // A3+V*A5 + fp1 = floatx80_mul(fp1, fp3, status); // V*(A4+V*A6) + fp2 = floatx80_mul(fp2, fp3, status); // V*(A3+V*A5) + fp1 = floatx80_add(fp1, float64_to_floatx80(LIT64(0x3FD55555555555A4), status), status); // A2+V*(A4+V*A6) + fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0xBFE0000000000008), status), status); // A1+V*(A3+V*A5) + fp1 = floatx80_mul(fp1, fp3, status); // V*(A2+V*(A4+V*A6)) + fp2 = floatx80_mul(fp2, fp3, status); // V*(A1+V*(A3+V*A5)) + fp1 = floatx80_mul(fp1, fp0, status); // U*V*(A2+V*(A4+V*A6)) + fp0 = floatx80_add(fp0, fp2, status); // U+V*(A1+V*(A3+V*A5)) + + fp1 = floatx80_add(fp1, log_tbl[j+1], status); // LOG(F)+U*V*(A2+V*(A4+V*A6)) + fp0 = floatx80_add(fp0, fp1, status); // FP0 IS LOG(F) + LOG(1+U) + + RESET_PREC; + + a = floatx80_add(fp0, klog2, status); + + float_raise(float_flag_inexact, status); + + return a; + } else if (compact < 0x3FFEF07D || compact > 0x3FFF8841) { // |X| < 1/16 or |X| > -1/16 + // LP1CARE + fSig = (aSig & LIT64(0xFE00000000000000)) | LIT64(0x0100000000000000); + f = packFloatx80(0, 0x3FFF, fSig); // F + j = (fSig >> 56) & 0x7E; // DISPLACEMENT FOR 1/F + + if (compact >= 0x3FFF8000) { // 1+Z >= 1 + // KISZERO + fp0 = floatx80_sub(float32_to_floatx80(0x3F800000, status), f, status); // 1-F + fp0 = floatx80_add(fp0, fp1, status); // FP0 IS Y-F = (1-F)+Z + fp1 = packFloatx80(0, 0, 0); // K = 0 + } else { + // KISNEG + fp0 = floatx80_sub(float32_to_floatx80(0x40000000, status), f, status); // 2-F + fp1 = floatx80_add(fp1, fp1, status); // 2Z + fp0 = floatx80_add(fp0, fp1, status); // FP0 IS Y-F = (2-F)+2Z + fp1 = packFloatx80(1, one_exp, one_sig); // K = -1 + } + goto lp1cont1; + } else { + // LP1ONE16 + fp1 = floatx80_add(fp1, fp1, status); // FP1 IS 2Z + fp0 = floatx80_add(fp0, float32_to_floatx80(0x3F800000, status), status); // FP0 IS 1+X + + // LP1CONT2 + fp1 = floatx80_div(fp1, fp0, status); // U + saveu = fp1; + fp0 = floatx80_mul(fp1, fp1, status); // FP0 IS V = U*U + fp1 = floatx80_mul(fp0, fp0, status); // FP1 IS W = V*V + + fp3 = float64_to_floatx80(LIT64(0x3F175496ADD7DAD6), status); // B5 + fp2 = float64_to_floatx80(LIT64(0x3F3C71C2FE80C7E0), status); // B4 + fp3 = floatx80_mul(fp3, fp1, status); // W*B5 + fp2 = floatx80_mul(fp2, fp1, status); // W*B4 + fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0x3F624924928BCCFF), status), status); // B3+W*B5 + fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3F899999999995EC), status), status); // B2+W*B4 + fp1 = floatx80_mul(fp1, fp3, status); // W*(B3+W*B5) + fp2 = floatx80_mul(fp2, fp0, status); // V*(B2+W*B4) + fp1 = floatx80_add(fp1, float64_to_floatx80(LIT64(0x3FB5555555555555), status), status); // B1+W*(B3+W*B5) + + fp0 = floatx80_mul(fp0, saveu, status); // FP0 IS U*V + fp1 = floatx80_add(fp1, fp2, status); // B1+W*(B3+W*B5) + V*(B2+W*B4) + fp0 = floatx80_mul(fp0, fp1, status); // U*V*( [B1+W*(B3+W*B5)] + [V*(B2+W*B4)] ) + + RESET_PREC; + + a = floatx80_add(fp0, saveu, status); + + float_raise(float_flag_inexact, status); + + return a; + } } /*---------------------------------------------------------------------------- @@ -1452,209 +1393,203 @@ floatx80 floatx80_lognp1(floatx80 a, float_status *status) floatx80 floatx80_sin(floatx80 a, float_status *status) { - flag aSign, xSign; - int32_t aExp, xExp; - uint64_t aSig, xSig; - - int8_t user_rnd_mode, user_rnd_prec; - - int32_t compact, l, n, j; - floatx80 fp0, fp1, fp2, fp3, fp4, fp5, x, invtwopi, twopi1, twopi2; - float32 posneg1, twoto63; - flag adjn, endflag; - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - - if (aExp == 0x7FFF) { - if ((uint64_t) (aSig<<1)) return propagateFloatx80NaNOneArg(a, status); - float_raise(float_flag_invalid, status); - a.low = floatx80_default_nan_low; - a.high = floatx80_default_nan_high; - return a; - } - - if (aExp == 0 && aSig == 0) { - return packFloatx80(aSign, 0, 0); - } - - adjn = 0; - - user_rnd_mode = status->float_rounding_mode; - user_rnd_prec = status->floatx80_rounding_precision; - - compact = floatx80_make_compact(aExp, aSig); - - fp0 = a; - - if (compact < 0x3FD78000 || compact > 0x4004BC7E) { // 2^(-40) > |X| > 15 PI - if (compact > 0x3FFF8000) { // |X| >= 15 PI - // REDUCEX - fp1 = packFloatx80(0, 0, 0); - if (compact == 0x7FFEFFFF) { - twopi1 = packFloatx80(aSign ^ 1, 0x7FFE, LIT64(0xC90FDAA200000000)); - twopi2 = packFloatx80(aSign ^ 1, 0x7FDC, LIT64(0x85A308D300000000)); - fp0 = floatx80_add(fp0, twopi1, status); - fp1 = fp0; - fp0 = floatx80_add(fp0, twopi2, status); - fp1 = floatx80_sub(fp1, fp0, status); - fp1 = floatx80_add(fp1, twopi2, status); - } - loop: - xSign = extractFloatx80Sign(fp0); - xExp = extractFloatx80Exp(fp0); - xExp -= 0x3FFF; - if (xExp <= 28) { - l = 0; - endflag = 1; - } else { - l = xExp - 27; - endflag = 0; - } - invtwopi = packFloatx80(0, 0x3FFE - l, LIT64(0xA2F9836E4E44152A)); // INVTWOPI - twopi1 = packFloatx80(0, 0x3FFF + l, LIT64(0xC90FDAA200000000)); - twopi2 = packFloatx80(0, 0x3FDD + l, LIT64(0x85A308D300000000)); - - twoto63 = 0x5F000000; - twoto63 |= xSign ? 0x80000000 : 0x00000000; // SIGN(INARG)*2^63 IN SGL - - fp2 = floatx80_mul(fp0, invtwopi, status); - fp2 = floatx80_add(fp2, float32_to_floatx80(twoto63, status), status); // THE FRACTIONAL PART OF FP2 IS ROUNDED - fp2 = floatx80_sub(fp2, float32_to_floatx80(twoto63, status), status); // FP2 is N - fp4 = floatx80_mul(twopi1, fp2, status); // W = N*P1 - fp5 = floatx80_mul(twopi2, fp2, status); // w = N*P2 - fp3 = floatx80_add(fp4, fp5, status); // FP3 is P - fp4 = floatx80_sub(fp4, fp3, status); // W-P - fp0 = floatx80_sub(fp0, fp3, status); // FP0 is A := R - P - fp4 = floatx80_add(fp4, fp5, status); // FP4 is p = (W-P)+w - fp3 = fp0; // FP3 is A - fp1 = floatx80_sub(fp1, fp4, status); // FP1 is a := r - p - fp0 = floatx80_add(fp0, fp1, status); // FP0 is R := A+a - - if (endflag > 0) { - n = floatx80_to_int32(fp2, status); - goto sincont; - } - fp3 = floatx80_sub(fp3, fp0, status); // A-R - fp1 = floatx80_add(fp1, fp3, status); // FP1 is r := (A-R)+a - goto loop; - } else { - // SINSM - fp0 = float32_to_floatx80(0x3F800000, status); // 1 - - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - if (adjn) { - // COSTINY - a = floatx80_sub(fp0, float32_to_floatx80(0x00800000, status), status); - } else { - // SINTINY - a = floatx80_move(a, status); - } - float_raise(float_flag_inexact, status); - - return a; - } - } else { - fp1 = floatx80_mul(fp0, float64_to_floatx80(LIT64(0x3FE45F306DC9C883), status), status); // X*2/PI - - n = floatx80_to_int32(fp1, status); - j = 32 + n; - - fp0 = floatx80_sub(fp0, pi_tbl[j], status); // X-Y1 - fp0 = floatx80_sub(fp0, float32_to_floatx80(pi_tbl2[j], status), status); // FP0 IS R = (X-Y1)-Y2 - - sincont: - if ((n + adjn) & 1) { - // COSPOLY - fp0 = floatx80_mul(fp0, fp0, status); // FP0 IS S - fp1 = floatx80_mul(fp0, fp0, status); // FP1 IS T - fp2 = float64_to_floatx80(LIT64(0x3D2AC4D0D6011EE3), status); // B8 - fp3 = float64_to_floatx80(LIT64(0xBDA9396F9F45AC19), status); // B7 - - xSign = extractFloatx80Sign(fp0); // X IS S - xExp = extractFloatx80Exp(fp0); - xSig = extractFloatx80Frac(fp0); - - if (((n + adjn) >> 1) & 1) { - xSign ^= 1; - posneg1 = 0xBF800000; // -1 - } else { - xSign ^= 0; - posneg1 = 0x3F800000; // 1 - } // X IS NOW R'= SGN*R - - fp2 = floatx80_mul(fp2, fp1, status); // TB8 - fp3 = floatx80_mul(fp3, fp1, status); // TB7 - fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3E21EED90612C972), status), status); // B6+TB8 - fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0xBE927E4FB79D9FCF), status), status); // B5+TB7 - fp2 = floatx80_mul(fp2, fp1, status); // T(B6+TB8) - fp3 = floatx80_mul(fp3, fp1, status); // T(B5+TB7) - fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3EFA01A01A01D423), status), status); // B4+T(B6+TB8) - fp4 = packFloatx80(1, 0x3FF5, LIT64(0xB60B60B60B61D438)); - fp3 = floatx80_add(fp3, fp4, status); // B3+T(B5+TB7) - fp2 = floatx80_mul(fp2, fp1, status); // T(B4+T(B6+TB8)) - fp1 = floatx80_mul(fp1, fp3, status); // T(B3+T(B5+TB7)) - fp4 = packFloatx80(0, 0x3FFA, LIT64(0xAAAAAAAAAAAAAB5E)); - fp2 = floatx80_add(fp2, fp4, status); // B2+T(B4+T(B6+TB8)) - fp1 = floatx80_add(fp1, float32_to_floatx80(0xBF000000, status), status); // B1+T(B3+T(B5+TB7)) - fp0 = floatx80_mul(fp0, fp2, status); // S(B2+T(B4+T(B6+TB8))) - fp0 = floatx80_add(fp0, fp1, status); // [B1+T(B3+T(B5+TB7))]+[S(B2+T(B4+T(B6+TB8)))] - - x = packFloatx80(xSign, xExp, xSig); - fp0 = floatx80_mul(fp0, x, status); - - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - a = floatx80_add(fp0, float32_to_floatx80(posneg1, status), status); - - float_raise(float_flag_inexact, status); - - return a; - } else { - // SINPOLY - xSign = extractFloatx80Sign(fp0); // X IS R - xExp = extractFloatx80Exp(fp0); - xSig = extractFloatx80Frac(fp0); - - xSign ^= ((n + adjn) >> 1) & 1; // X IS NOW R'= SGN*R - - fp0 = floatx80_mul(fp0, fp0, status); // FP0 IS S - fp1 = floatx80_mul(fp0, fp0, status); // FP1 IS T - fp3 = float64_to_floatx80(LIT64(0xBD6AAA77CCC994F5), status); // A7 - fp2 = float64_to_floatx80(LIT64(0x3DE612097AAE8DA1), status); // A6 - fp3 = floatx80_mul(fp3, fp1, status); // T*A7 - fp2 = floatx80_mul(fp2, fp1, status); // T*A6 - fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0xBE5AE6452A118AE4), status), status); // A5+T*A7 - fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3EC71DE3A5341531), status), status); // A4+T*A6 - fp3 = floatx80_mul(fp3, fp1, status); // T(A5+TA7) - fp2 = floatx80_mul(fp2, fp1, status); // T(A4+TA6) - fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0xBF2A01A01A018B59), status), status); // A3+T(A5+TA7) - fp4 = packFloatx80(0, 0x3FF8, LIT64(0x88888888888859AF)); - fp2 = floatx80_add(fp2, fp4, status); // A2+T(A4+TA6) - fp1 = floatx80_mul(fp1, fp3, status); // T(A3+T(A5+TA7)) - fp2 = floatx80_mul(fp2, fp0, status); // S(A2+T(A4+TA6)) - fp4 = packFloatx80(1, 0x3FFC, LIT64(0xAAAAAAAAAAAAAA99)); - fp1 = floatx80_add(fp1, fp4, status); // A1+T(A3+T(A5+TA7)) - fp1 = floatx80_add(fp1, fp2, status); // [A1+T(A3+T(A5+TA7))]+[S(A2+T(A4+TA6))] - - x = packFloatx80(xSign, xExp, xSig); - fp0 = floatx80_mul(fp0, x, status); // R'*S - fp0 = floatx80_mul(fp0, fp1, status); // SIN(R')-R' - - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - a = floatx80_add(fp0, x, status); - - float_raise(float_flag_inexact, status); - - return a; - } - } + flag aSign, xSign; + int32_t aExp, xExp; + uint64_t aSig, xSig; + + int32_t compact, l, n, j; + floatx80 fp0, fp1, fp2, fp3, fp4, fp5, x, invtwopi, twopi1, twopi2; + float32 posneg1, twoto63; + flag adjn, endflag; + + aSig = extractFloatx80Frac(a); + aExp = extractFloatx80Exp(a); + aSign = extractFloatx80Sign(a); + + if (aExp == 0x7FFF) { + if ((uint64_t) (aSig<<1)) return propagateFloatx80NaNOneArg(a, status); + float_raise(float_flag_invalid, status); + a.low = floatx80_default_nan_low; + a.high = floatx80_default_nan_high; + return a; + } + + if (aExp == 0 && aSig == 0) { + return packFloatx80(aSign, 0, 0); + } + + adjn = 0; + + SET_PREC; + + compact = floatx80_make_compact(aExp, aSig); + + fp0 = a; + + if (compact < 0x3FD78000 || compact > 0x4004BC7E) { // 2^(-40) > |X| > 15 PI + if (compact > 0x3FFF8000) { // |X| >= 15 PI + // REDUCEX + fp1 = packFloatx80(0, 0, 0); + if (compact == 0x7FFEFFFF) { + twopi1 = packFloatx80(aSign ^ 1, 0x7FFE, LIT64(0xC90FDAA200000000)); + twopi2 = packFloatx80(aSign ^ 1, 0x7FDC, LIT64(0x85A308D300000000)); + fp0 = floatx80_add(fp0, twopi1, status); + fp1 = fp0; + fp0 = floatx80_add(fp0, twopi2, status); + fp1 = floatx80_sub(fp1, fp0, status); + fp1 = floatx80_add(fp1, twopi2, status); + } + loop: + xSign = extractFloatx80Sign(fp0); + xExp = extractFloatx80Exp(fp0); + xExp -= 0x3FFF; + if (xExp <= 28) { + l = 0; + endflag = 1; + } else { + l = xExp - 27; + endflag = 0; + } + invtwopi = packFloatx80(0, 0x3FFE - l, LIT64(0xA2F9836E4E44152A)); // INVTWOPI + twopi1 = packFloatx80(0, 0x3FFF + l, LIT64(0xC90FDAA200000000)); + twopi2 = packFloatx80(0, 0x3FDD + l, LIT64(0x85A308D300000000)); + + twoto63 = 0x5F000000; + twoto63 |= xSign ? 0x80000000 : 0x00000000; // SIGN(INARG)*2^63 IN SGL + + fp2 = floatx80_mul(fp0, invtwopi, status); + fp2 = floatx80_add(fp2, float32_to_floatx80(twoto63, status), status); // THE FRACTIONAL PART OF FP2 IS ROUNDED + fp2 = floatx80_sub(fp2, float32_to_floatx80(twoto63, status), status); // FP2 is N + fp4 = floatx80_mul(twopi1, fp2, status); // W = N*P1 + fp5 = floatx80_mul(twopi2, fp2, status); // w = N*P2 + fp3 = floatx80_add(fp4, fp5, status); // FP3 is P + fp4 = floatx80_sub(fp4, fp3, status); // W-P + fp0 = floatx80_sub(fp0, fp3, status); // FP0 is A := R - P + fp4 = floatx80_add(fp4, fp5, status); // FP4 is p = (W-P)+w + fp3 = fp0; // FP3 is A + fp1 = floatx80_sub(fp1, fp4, status); // FP1 is a := r - p + fp0 = floatx80_add(fp0, fp1, status); // FP0 is R := A+a + + if (endflag > 0) { + n = floatx80_to_int32(fp2, status); + goto sincont; + } + fp3 = floatx80_sub(fp3, fp0, status); // A-R + fp1 = floatx80_add(fp1, fp3, status); // FP1 is r := (A-R)+a + goto loop; + } else { + // SINSM + fp0 = float32_to_floatx80(0x3F800000, status); // 1 + + RESET_PREC; + + if (adjn) { + // COSTINY + a = floatx80_sub(fp0, float32_to_floatx80(0x00800000, status), status); + } else { + // SINTINY + a = floatx80_move(a, status); + } + float_raise(float_flag_inexact, status); + + return a; + } + } else { + fp1 = floatx80_mul(fp0, float64_to_floatx80(LIT64(0x3FE45F306DC9C883), status), status); // X*2/PI + + n = floatx80_to_int32(fp1, status); + j = 32 + n; + + fp0 = floatx80_sub(fp0, pi_tbl[j], status); // X-Y1 + fp0 = floatx80_sub(fp0, float32_to_floatx80(pi_tbl2[j], status), status); // FP0 IS R = (X-Y1)-Y2 + + sincont: + if ((n + adjn) & 1) { + // COSPOLY + fp0 = floatx80_mul(fp0, fp0, status); // FP0 IS S + fp1 = floatx80_mul(fp0, fp0, status); // FP1 IS T + fp2 = float64_to_floatx80(LIT64(0x3D2AC4D0D6011EE3), status); // B8 + fp3 = float64_to_floatx80(LIT64(0xBDA9396F9F45AC19), status); // B7 + + xSign = extractFloatx80Sign(fp0); // X IS S + xExp = extractFloatx80Exp(fp0); + xSig = extractFloatx80Frac(fp0); + + if (((n + adjn) >> 1) & 1) { + xSign ^= 1; + posneg1 = 0xBF800000; // -1 + } else { + xSign ^= 0; + posneg1 = 0x3F800000; // 1 + } // X IS NOW R'= SGN*R + + fp2 = floatx80_mul(fp2, fp1, status); // TB8 + fp3 = floatx80_mul(fp3, fp1, status); // TB7 + fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3E21EED90612C972), status), status); // B6+TB8 + fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0xBE927E4FB79D9FCF), status), status); // B5+TB7 + fp2 = floatx80_mul(fp2, fp1, status); // T(B6+TB8) + fp3 = floatx80_mul(fp3, fp1, status); // T(B5+TB7) + fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3EFA01A01A01D423), status), status); // B4+T(B6+TB8) + fp4 = packFloatx80(1, 0x3FF5, LIT64(0xB60B60B60B61D438)); + fp3 = floatx80_add(fp3, fp4, status); // B3+T(B5+TB7) + fp2 = floatx80_mul(fp2, fp1, status); // T(B4+T(B6+TB8)) + fp1 = floatx80_mul(fp1, fp3, status); // T(B3+T(B5+TB7)) + fp4 = packFloatx80(0, 0x3FFA, LIT64(0xAAAAAAAAAAAAAB5E)); + fp2 = floatx80_add(fp2, fp4, status); // B2+T(B4+T(B6+TB8)) + fp1 = floatx80_add(fp1, float32_to_floatx80(0xBF000000, status), status); // B1+T(B3+T(B5+TB7)) + fp0 = floatx80_mul(fp0, fp2, status); // S(B2+T(B4+T(B6+TB8))) + fp0 = floatx80_add(fp0, fp1, status); // [B1+T(B3+T(B5+TB7))]+[S(B2+T(B4+T(B6+TB8)))] + + x = packFloatx80(xSign, xExp, xSig); + fp0 = floatx80_mul(fp0, x, status); + + RESET_PREC; + + a = floatx80_add(fp0, float32_to_floatx80(posneg1, status), status); + + float_raise(float_flag_inexact, status); + + return a; + } else { + // SINPOLY + xSign = extractFloatx80Sign(fp0); // X IS R + xExp = extractFloatx80Exp(fp0); + xSig = extractFloatx80Frac(fp0); + + xSign ^= ((n + adjn) >> 1) & 1; // X IS NOW R'= SGN*R + + fp0 = floatx80_mul(fp0, fp0, status); // FP0 IS S + fp1 = floatx80_mul(fp0, fp0, status); // FP1 IS T + fp3 = float64_to_floatx80(LIT64(0xBD6AAA77CCC994F5), status); // A7 + fp2 = float64_to_floatx80(LIT64(0x3DE612097AAE8DA1), status); // A6 + fp3 = floatx80_mul(fp3, fp1, status); // T*A7 + fp2 = floatx80_mul(fp2, fp1, status); // T*A6 + fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0xBE5AE6452A118AE4), status), status); // A5+T*A7 + fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3EC71DE3A5341531), status), status); // A4+T*A6 + fp3 = floatx80_mul(fp3, fp1, status); // T(A5+TA7) + fp2 = floatx80_mul(fp2, fp1, status); // T(A4+TA6) + fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0xBF2A01A01A018B59), status), status); // A3+T(A5+TA7) + fp4 = packFloatx80(0, 0x3FF8, LIT64(0x88888888888859AF)); + fp2 = floatx80_add(fp2, fp4, status); // A2+T(A4+TA6) + fp1 = floatx80_mul(fp1, fp3, status); // T(A3+T(A5+TA7)) + fp2 = floatx80_mul(fp2, fp0, status); // S(A2+T(A4+TA6)) + fp4 = packFloatx80(1, 0x3FFC, LIT64(0xAAAAAAAAAAAAAA99)); + fp1 = floatx80_add(fp1, fp4, status); // A1+T(A3+T(A5+TA7)) + fp1 = floatx80_add(fp1, fp2, status); // [A1+T(A3+T(A5+TA7))]+[S(A2+T(A4+TA6))] + + x = packFloatx80(xSign, xExp, xSig); + fp0 = floatx80_mul(fp0, x, status); // R'*S + fp0 = floatx80_mul(fp0, fp1, status); // SIN(R')-R' + + RESET_PREC; + + a = floatx80_add(fp0, x, status); + + float_raise(float_flag_inexact, status); + + return a; + } + } } /*---------------------------------------------------------------------------- @@ -1663,77 +1598,71 @@ floatx80 floatx80_sin(floatx80 a, float_status *status) floatx80 floatx80_sinh(floatx80 a, float_status *status) { - flag aSign; - int32_t aExp; - uint64_t aSig; - - int8_t user_rnd_mode, user_rnd_prec; - - int32_t compact; - floatx80 fp0, fp1, fp2; - float32 fact; - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - - if (aExp == 0x7FFF) { - if ((uint64_t) (aSig<<1)) return propagateFloatx80NaNOneArg(a, status); - return packFloatx80(aSign, 0x7FFF, floatx80_default_infinity_low); - } - - if (aExp == 0 && aSig == 0) { - return packFloatx80(aSign, 0, 0); - } - - user_rnd_mode = status->float_rounding_mode; - user_rnd_prec = status->floatx80_rounding_precision; - - compact = floatx80_make_compact(aExp, aSig); - - if (compact > 0x400CB167) { - // SINHBIG - if (compact > 0x400CB2B3) { - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - return roundAndPackFloatx80(status->floatx80_rounding_precision, aSign, 0x8000, aSig, 0, status); - } else { - fp0 = floatx80_abs(a, status); // Y = |X| - fp0 = floatx80_sub(fp0, float64_to_floatx80(LIT64(0x40C62D38D3D64634), status), status); // (|X|-16381LOG2_LEAD) - fp0 = floatx80_sub(fp0, float64_to_floatx80(LIT64(0x3D6F90AEB1E75CC7), status), status); // |X| - 16381 LOG2, ACCURATE - fp0 = floatx80_etox(fp0, status); - fp2 = packFloatx80(aSign, 0x7FFB, one_sig); - - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - a = floatx80_mul(fp0, fp2, status); - - float_raise(float_flag_inexact, status); - - return a; - } - } else { // |X| < 16380 LOG2 - fp0 = floatx80_abs(a, status); // Y = |X| - fp0 = floatx80_etoxm1(fp0, status); // FP0 IS Z = EXPM1(Y) - fp1 = floatx80_add(fp0, float32_to_floatx80(0x3F800000, status), status); // 1+Z - fp2 = fp0; - fp0 = floatx80_div(fp0, fp1, status); // Z/(1+Z) - fp0 = floatx80_add(fp0, fp2, status); - - fact = 0x3F000000; - fact |= aSign ? 0x80000000 : 0x00000000; - - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - a = floatx80_mul(fp0, float32_to_floatx80(fact, status), status); - - float_raise(float_flag_inexact, status); - - return a; - } + flag aSign; + int32_t aExp; + uint64_t aSig; + + int32_t compact; + floatx80 fp0, fp1, fp2; + float32 fact; + + aSig = extractFloatx80Frac(a); + aExp = extractFloatx80Exp(a); + aSign = extractFloatx80Sign(a); + + if (aExp == 0x7FFF) { + if ((uint64_t) (aSig<<1)) return propagateFloatx80NaNOneArg(a, status); + return packFloatx80(aSign, 0x7FFF, floatx80_default_infinity_low); + } + + if (aExp == 0 && aSig == 0) { + return packFloatx80(aSign, 0, 0); + } + + SET_PREC; + + compact = floatx80_make_compact(aExp, aSig); + + if (compact > 0x400CB167) { + // SINHBIG + if (compact > 0x400CB2B3) { + RESET_PREC; + + return roundAndPackFloatx80(status->floatx80_rounding_precision, aSign, 0x8000, aSig, 0, status); + } else { + fp0 = floatx80_abs(a, status); // Y = |X| + fp0 = floatx80_sub(fp0, float64_to_floatx80(LIT64(0x40C62D38D3D64634), status), status); // (|X|-16381LOG2_LEAD) + fp0 = floatx80_sub(fp0, float64_to_floatx80(LIT64(0x3D6F90AEB1E75CC7), status), status); // |X| - 16381 LOG2, ACCURATE + fp0 = floatx80_etox(fp0, status); + fp2 = packFloatx80(aSign, 0x7FFB, one_sig); + + RESET_PREC; + + a = floatx80_mul(fp0, fp2, status); + + float_raise(float_flag_inexact, status); + + return a; + } + } else { // |X| < 16380 LOG2 + fp0 = floatx80_abs(a, status); // Y = |X| + fp0 = floatx80_etoxm1(fp0, status); // FP0 IS Z = EXPM1(Y) + fp1 = floatx80_add(fp0, float32_to_floatx80(0x3F800000, status), status); // 1+Z + fp2 = fp0; + fp0 = floatx80_div(fp0, fp1, status); // Z/(1+Z) + fp0 = floatx80_add(fp0, fp2, status); + + fact = 0x3F000000; + fact |= aSign ? 0x80000000 : 0x00000000; + + RESET_PREC; + + a = floatx80_mul(fp0, float32_to_floatx80(fact, status), status); + + float_raise(float_flag_inexact, status); + + return a; + } } /*---------------------------------------------------------------------------- @@ -1742,185 +1671,179 @@ floatx80 floatx80_sinh(floatx80 a, float_status *status) floatx80 floatx80_tan(floatx80 a, float_status *status) { - flag aSign, xSign; - int32_t aExp, xExp; - uint64_t aSig, xSig; - - int8_t user_rnd_mode, user_rnd_prec; - - int32_t compact, l, n, j; - floatx80 fp0, fp1, fp2, fp3, fp4, fp5, invtwopi, twopi1, twopi2; - float32 twoto63; - flag endflag; - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - - if (aExp == 0x7FFF) { - if ((uint64_t) (aSig<<1)) return propagateFloatx80NaNOneArg(a, status); - float_raise(float_flag_invalid, status); - a.low = floatx80_default_nan_low; - a.high = floatx80_default_nan_high; - return a; - } - - if (aExp == 0 && aSig == 0) { - return packFloatx80(aSign, 0, 0); - } - - user_rnd_mode = status->float_rounding_mode; - user_rnd_prec = status->floatx80_rounding_precision; - - compact = floatx80_make_compact(aExp, aSig); - - fp0 = a; - - if (compact < 0x3FD78000 || compact > 0x4004BC7E) { // 2^(-40) > |X| > 15 PI - if (compact > 0x3FFF8000) { // |X| >= 15 PI - // REDUCEX - fp1 = packFloatx80(0, 0, 0); - if (compact == 0x7FFEFFFF) { - twopi1 = packFloatx80(aSign ^ 1, 0x7FFE, LIT64(0xC90FDAA200000000)); - twopi2 = packFloatx80(aSign ^ 1, 0x7FDC, LIT64(0x85A308D300000000)); - fp0 = floatx80_add(fp0, twopi1, status); - fp1 = fp0; - fp0 = floatx80_add(fp0, twopi2, status); - fp1 = floatx80_sub(fp1, fp0, status); - fp1 = floatx80_add(fp1, twopi2, status); - } - loop: - xSign = extractFloatx80Sign(fp0); - xExp = extractFloatx80Exp(fp0); - xExp -= 0x3FFF; - if (xExp <= 28) { - l = 0; - endflag = 1; - } else { - l = xExp - 27; - endflag = 0; - } - invtwopi = packFloatx80(0, 0x3FFE - l, LIT64(0xA2F9836E4E44152A)); // INVTWOPI - twopi1 = packFloatx80(0, 0x3FFF + l, LIT64(0xC90FDAA200000000)); - twopi2 = packFloatx80(0, 0x3FDD + l, LIT64(0x85A308D300000000)); - - twoto63 = 0x5F000000; - twoto63 |= xSign ? 0x80000000 : 0x00000000; // SIGN(INARG)*2^63 IN SGL - - fp2 = floatx80_mul(fp0, invtwopi, status); - fp2 = floatx80_add(fp2, float32_to_floatx80(twoto63, status), status); // THE FRACTIONAL PART OF FP2 IS ROUNDED - fp2 = floatx80_sub(fp2, float32_to_floatx80(twoto63, status), status); // FP2 is N - fp4 = floatx80_mul(twopi1, fp2, status); // W = N*P1 - fp5 = floatx80_mul(twopi2, fp2, status); // w = N*P2 - fp3 = floatx80_add(fp4, fp5, status); // FP3 is P - fp4 = floatx80_sub(fp4, fp3, status); // W-P - fp0 = floatx80_sub(fp0, fp3, status); // FP0 is A := R - P - fp4 = floatx80_add(fp4, fp5, status); // FP4 is p = (W-P)+w - fp3 = fp0; // FP3 is A - fp1 = floatx80_sub(fp1, fp4, status); // FP1 is a := r - p - fp0 = floatx80_add(fp0, fp1, status); // FP0 is R := A+a - - if (endflag > 0) { - n = floatx80_to_int32(fp2, status); - goto tancont; - } - fp3 = floatx80_sub(fp3, fp0, status); // A-R - fp1 = floatx80_add(fp1, fp3, status); // FP1 is r := (A-R)+a - goto loop; - } else { - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - a = floatx80_move(a, status); - - float_raise(float_flag_inexact, status); - - return a; - } - } else { - fp1 = floatx80_mul(fp0, float64_to_floatx80(LIT64(0x3FE45F306DC9C883), status), status); // X*2/PI - - n = floatx80_to_int32(fp1, status); - j = 32 + n; - - fp0 = floatx80_sub(fp0, pi_tbl[j], status); // X-Y1 - fp0 = floatx80_sub(fp0, float32_to_floatx80(pi_tbl2[j], status), status); // FP0 IS R = (X-Y1)-Y2 - - tancont: - if (n & 1) { - // NODD - fp1 = fp0; // R - fp0 = floatx80_mul(fp0, fp0, status); // S = R*R - fp3 = float64_to_floatx80(LIT64(0x3EA0B759F50F8688), status); // Q4 - fp2 = float64_to_floatx80(LIT64(0xBEF2BAA5A8924F04), status); // P3 - fp3 = floatx80_mul(fp3, fp0, status); // SQ4 - fp2 = floatx80_mul(fp2, fp0, status); // SP3 - fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0xBF346F59B39BA65F), status), status); // Q3+SQ4 - fp4 = packFloatx80(0, 0x3FF6, LIT64(0xE073D3FC199C4A00)); - fp2 = floatx80_add(fp2, fp4, status); // P2+SP3 - fp3 = floatx80_mul(fp3, fp0, status); // S(Q3+SQ4) - fp2 = floatx80_mul(fp2, fp0, status); // S(P2+SP3) - fp4 = packFloatx80(0, 0x3FF9, LIT64(0xD23CD68415D95FA1)); - fp3 = floatx80_add(fp3, fp4, status); // Q2+S(Q3+SQ4) - fp4 = packFloatx80(1, 0x3FFC, LIT64(0x8895A6C5FB423BCA)); - fp2 = floatx80_add(fp2, fp4, status); // P1+S(P2+SP3) - fp3 = floatx80_mul(fp3, fp0, status); // S(Q2+S(Q3+SQ4)) - fp2 = floatx80_mul(fp2, fp0, status); // S(P1+S(P2+SP3)) - fp4 = packFloatx80(1, 0x3FFD, LIT64(0xEEF57E0DA84BC8CE)); - fp3 = floatx80_add(fp3, fp4, status); // Q1+S(Q2+S(Q3+SQ4)) - fp2 = floatx80_mul(fp2, fp1, status); // RS(P1+S(P2+SP3)) - fp0 = floatx80_mul(fp0, fp3, status); // S(Q1+S(Q2+S(Q3+SQ4))) - fp1 = floatx80_add(fp1, fp2, status); // R+RS(P1+S(P2+SP3)) - fp0 = floatx80_add(fp0, float32_to_floatx80(0x3F800000, status), status); // 1+S(Q1+S(Q2+S(Q3+SQ4))) - - xSign = extractFloatx80Sign(fp1); - xExp = extractFloatx80Exp(fp1); - xSig = extractFloatx80Frac(fp1); - xSign ^= 1; - fp1 = packFloatx80(xSign, xExp, xSig); - - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - a = floatx80_div(fp0, fp1, status); - - float_raise(float_flag_inexact, status); - - return a; - } else { - fp1 = floatx80_mul(fp0, fp0, status); // S = R*R - fp3 = float64_to_floatx80(LIT64(0x3EA0B759F50F8688), status); // Q4 - fp2 = float64_to_floatx80(LIT64(0xBEF2BAA5A8924F04), status); // P3 - fp3 = floatx80_mul(fp3, fp1, status); // SQ4 - fp2 = floatx80_mul(fp2, fp1, status); // SP3 - fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0xBF346F59B39BA65F), status), status); // Q3+SQ4 - fp4 = packFloatx80(0, 0x3FF6, LIT64(0xE073D3FC199C4A00)); - fp2 = floatx80_add(fp2, fp4, status); // P2+SP3 - fp3 = floatx80_mul(fp3, fp1, status); // S(Q3+SQ4) - fp2 = floatx80_mul(fp2, fp1, status); // S(P2+SP3) - fp4 = packFloatx80(0, 0x3FF9, LIT64(0xD23CD68415D95FA1)); - fp3 = floatx80_add(fp3, fp4, status); // Q2+S(Q3+SQ4) - fp4 = packFloatx80(1, 0x3FFC, LIT64(0x8895A6C5FB423BCA)); - fp2 = floatx80_add(fp2, fp4, status); // P1+S(P2+SP3) - fp3 = floatx80_mul(fp3, fp1, status); // S(Q2+S(Q3+SQ4)) - fp2 = floatx80_mul(fp2, fp1, status); // S(P1+S(P2+SP3)) - fp4 = packFloatx80(1, 0x3FFD, LIT64(0xEEF57E0DA84BC8CE)); - fp3 = floatx80_add(fp3, fp4, status); // Q1+S(Q2+S(Q3+SQ4)) - fp2 = floatx80_mul(fp2, fp0, status); // RS(P1+S(P2+SP3)) - fp1 = floatx80_mul(fp1, fp3, status); // S(Q1+S(Q2+S(Q3+SQ4))) - fp0 = floatx80_add(fp0, fp2, status); // R+RS(P1+S(P2+SP3)) - fp1 = floatx80_add(fp1, float32_to_floatx80(0x3F800000, status), status); // 1+S(Q1+S(Q2+S(Q3+SQ4))) - - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - a = floatx80_div(fp0, fp1, status); - - float_raise(float_flag_inexact, status); - - return a; - } - } + flag aSign, xSign; + int32_t aExp, xExp; + uint64_t aSig, xSig; + + int32_t compact, l, n, j; + floatx80 fp0, fp1, fp2, fp3, fp4, fp5, invtwopi, twopi1, twopi2; + float32 twoto63; + flag endflag; + + aSig = extractFloatx80Frac(a); + aExp = extractFloatx80Exp(a); + aSign = extractFloatx80Sign(a); + + if (aExp == 0x7FFF) { + if ((uint64_t) (aSig<<1)) return propagateFloatx80NaNOneArg(a, status); + float_raise(float_flag_invalid, status); + a.low = floatx80_default_nan_low; + a.high = floatx80_default_nan_high; + return a; + } + + if (aExp == 0 && aSig == 0) { + return packFloatx80(aSign, 0, 0); + } + + SET_PREC; + + compact = floatx80_make_compact(aExp, aSig); + + fp0 = a; + + if (compact < 0x3FD78000 || compact > 0x4004BC7E) { // 2^(-40) > |X| > 15 PI + if (compact > 0x3FFF8000) { // |X| >= 15 PI + // REDUCEX + fp1 = packFloatx80(0, 0, 0); + if (compact == 0x7FFEFFFF) { + twopi1 = packFloatx80(aSign ^ 1, 0x7FFE, LIT64(0xC90FDAA200000000)); + twopi2 = packFloatx80(aSign ^ 1, 0x7FDC, LIT64(0x85A308D300000000)); + fp0 = floatx80_add(fp0, twopi1, status); + fp1 = fp0; + fp0 = floatx80_add(fp0, twopi2, status); + fp1 = floatx80_sub(fp1, fp0, status); + fp1 = floatx80_add(fp1, twopi2, status); + } + loop: + xSign = extractFloatx80Sign(fp0); + xExp = extractFloatx80Exp(fp0); + xExp -= 0x3FFF; + if (xExp <= 28) { + l = 0; + endflag = 1; + } else { + l = xExp - 27; + endflag = 0; + } + invtwopi = packFloatx80(0, 0x3FFE - l, LIT64(0xA2F9836E4E44152A)); // INVTWOPI + twopi1 = packFloatx80(0, 0x3FFF + l, LIT64(0xC90FDAA200000000)); + twopi2 = packFloatx80(0, 0x3FDD + l, LIT64(0x85A308D300000000)); + + twoto63 = 0x5F000000; + twoto63 |= xSign ? 0x80000000 : 0x00000000; // SIGN(INARG)*2^63 IN SGL + + fp2 = floatx80_mul(fp0, invtwopi, status); + fp2 = floatx80_add(fp2, float32_to_floatx80(twoto63, status), status); // THE FRACTIONAL PART OF FP2 IS ROUNDED + fp2 = floatx80_sub(fp2, float32_to_floatx80(twoto63, status), status); // FP2 is N + fp4 = floatx80_mul(twopi1, fp2, status); // W = N*P1 + fp5 = floatx80_mul(twopi2, fp2, status); // w = N*P2 + fp3 = floatx80_add(fp4, fp5, status); // FP3 is P + fp4 = floatx80_sub(fp4, fp3, status); // W-P + fp0 = floatx80_sub(fp0, fp3, status); // FP0 is A := R - P + fp4 = floatx80_add(fp4, fp5, status); // FP4 is p = (W-P)+w + fp3 = fp0; // FP3 is A + fp1 = floatx80_sub(fp1, fp4, status); // FP1 is a := r - p + fp0 = floatx80_add(fp0, fp1, status); // FP0 is R := A+a + + if (endflag > 0) { + n = floatx80_to_int32(fp2, status); + goto tancont; + } + fp3 = floatx80_sub(fp3, fp0, status); // A-R + fp1 = floatx80_add(fp1, fp3, status); // FP1 is r := (A-R)+a + goto loop; + } else { + RESET_PREC; + + a = floatx80_move(a, status); + + float_raise(float_flag_inexact, status); + + return a; + } + } else { + fp1 = floatx80_mul(fp0, float64_to_floatx80(LIT64(0x3FE45F306DC9C883), status), status); // X*2/PI + + n = floatx80_to_int32(fp1, status); + j = 32 + n; + + fp0 = floatx80_sub(fp0, pi_tbl[j], status); // X-Y1 + fp0 = floatx80_sub(fp0, float32_to_floatx80(pi_tbl2[j], status), status); // FP0 IS R = (X-Y1)-Y2 + + tancont: + if (n & 1) { + // NODD + fp1 = fp0; // R + fp0 = floatx80_mul(fp0, fp0, status); // S = R*R + fp3 = float64_to_floatx80(LIT64(0x3EA0B759F50F8688), status); // Q4 + fp2 = float64_to_floatx80(LIT64(0xBEF2BAA5A8924F04), status); // P3 + fp3 = floatx80_mul(fp3, fp0, status); // SQ4 + fp2 = floatx80_mul(fp2, fp0, status); // SP3 + fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0xBF346F59B39BA65F), status), status); // Q3+SQ4 + fp4 = packFloatx80(0, 0x3FF6, LIT64(0xE073D3FC199C4A00)); + fp2 = floatx80_add(fp2, fp4, status); // P2+SP3 + fp3 = floatx80_mul(fp3, fp0, status); // S(Q3+SQ4) + fp2 = floatx80_mul(fp2, fp0, status); // S(P2+SP3) + fp4 = packFloatx80(0, 0x3FF9, LIT64(0xD23CD68415D95FA1)); + fp3 = floatx80_add(fp3, fp4, status); // Q2+S(Q3+SQ4) + fp4 = packFloatx80(1, 0x3FFC, LIT64(0x8895A6C5FB423BCA)); + fp2 = floatx80_add(fp2, fp4, status); // P1+S(P2+SP3) + fp3 = floatx80_mul(fp3, fp0, status); // S(Q2+S(Q3+SQ4)) + fp2 = floatx80_mul(fp2, fp0, status); // S(P1+S(P2+SP3)) + fp4 = packFloatx80(1, 0x3FFD, LIT64(0xEEF57E0DA84BC8CE)); + fp3 = floatx80_add(fp3, fp4, status); // Q1+S(Q2+S(Q3+SQ4)) + fp2 = floatx80_mul(fp2, fp1, status); // RS(P1+S(P2+SP3)) + fp0 = floatx80_mul(fp0, fp3, status); // S(Q1+S(Q2+S(Q3+SQ4))) + fp1 = floatx80_add(fp1, fp2, status); // R+RS(P1+S(P2+SP3)) + fp0 = floatx80_add(fp0, float32_to_floatx80(0x3F800000, status), status); // 1+S(Q1+S(Q2+S(Q3+SQ4))) + + xSign = extractFloatx80Sign(fp1); + xExp = extractFloatx80Exp(fp1); + xSig = extractFloatx80Frac(fp1); + xSign ^= 1; + fp1 = packFloatx80(xSign, xExp, xSig); + + RESET_PREC; + + a = floatx80_div(fp0, fp1, status); + + float_raise(float_flag_inexact, status); + + return a; + } else { + fp1 = floatx80_mul(fp0, fp0, status); // S = R*R + fp3 = float64_to_floatx80(LIT64(0x3EA0B759F50F8688), status); // Q4 + fp2 = float64_to_floatx80(LIT64(0xBEF2BAA5A8924F04), status); // P3 + fp3 = floatx80_mul(fp3, fp1, status); // SQ4 + fp2 = floatx80_mul(fp2, fp1, status); // SP3 + fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0xBF346F59B39BA65F), status), status); // Q3+SQ4 + fp4 = packFloatx80(0, 0x3FF6, LIT64(0xE073D3FC199C4A00)); + fp2 = floatx80_add(fp2, fp4, status); // P2+SP3 + fp3 = floatx80_mul(fp3, fp1, status); // S(Q3+SQ4) + fp2 = floatx80_mul(fp2, fp1, status); // S(P2+SP3) + fp4 = packFloatx80(0, 0x3FF9, LIT64(0xD23CD68415D95FA1)); + fp3 = floatx80_add(fp3, fp4, status); // Q2+S(Q3+SQ4) + fp4 = packFloatx80(1, 0x3FFC, LIT64(0x8895A6C5FB423BCA)); + fp2 = floatx80_add(fp2, fp4, status); // P1+S(P2+SP3) + fp3 = floatx80_mul(fp3, fp1, status); // S(Q2+S(Q3+SQ4)) + fp2 = floatx80_mul(fp2, fp1, status); // S(P1+S(P2+SP3)) + fp4 = packFloatx80(1, 0x3FFD, LIT64(0xEEF57E0DA84BC8CE)); + fp3 = floatx80_add(fp3, fp4, status); // Q1+S(Q2+S(Q3+SQ4)) + fp2 = floatx80_mul(fp2, fp0, status); // RS(P1+S(P2+SP3)) + fp1 = floatx80_mul(fp1, fp3, status); // S(Q1+S(Q2+S(Q3+SQ4))) + fp0 = floatx80_add(fp0, fp2, status); // R+RS(P1+S(P2+SP3)) + fp1 = floatx80_add(fp1, float32_to_floatx80(0x3F800000, status), status); // 1+S(Q1+S(Q2+S(Q3+SQ4))) + + RESET_PREC; + + a = floatx80_div(fp0, fp1, status); + + float_raise(float_flag_inexact, status); + + return a; + } + } } /*---------------------------------------------------------------------------- @@ -1929,101 +1852,94 @@ floatx80 floatx80_tan(floatx80 a, float_status *status) floatx80 floatx80_tanh(floatx80 a, float_status *status) { - flag aSign, vSign; - int32_t aExp, vExp; - uint64_t aSig, vSig; - - int8_t user_rnd_mode, user_rnd_prec; - - int32_t compact; - floatx80 fp0, fp1; - float32 sign; - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - - if (aExp == 0x7FFF) { - if ((uint64_t) (aSig<<1)) return propagateFloatx80NaNOneArg(a, status); - return packFloatx80(aSign, one_exp, one_sig); - } - - if (aExp == 0 && aSig == 0) { - return packFloatx80(aSign, 0, 0); - } - - user_rnd_mode = status->float_rounding_mode; - user_rnd_prec = status->floatx80_rounding_precision; - - compact = floatx80_make_compact(aExp, aSig); - - if (compact < 0x3FD78000 || compact > 0x3FFFDDCE) { - // TANHBORS - if (compact < 0x3FFF8000) { - // TANHSM - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - a = floatx80_move(a, status); - - float_raise(float_flag_inexact, status); - - return a; - } else { - if (compact > 0x40048AA1) { - // TANHHUGE - sign = 0x3F800000; - sign |= aSign ? 0x80000000 : 0x00000000; - fp0 = float32_to_floatx80(sign, status); - sign &= 0x80000000; - sign ^= 0x80800000; // -SIGN(X)*EPS - - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - a = floatx80_add(fp0, float32_to_floatx80(sign, status), status); - - float_raise(float_flag_inexact, status); - - return a; - } else { - fp0 = packFloatx80(0, aExp+1, aSig); // Y = 2|X| - fp0 = floatx80_etox(fp0, status); // FP0 IS EXP(Y) - fp0 = floatx80_add(fp0, float32_to_floatx80(0x3F800000, status), status); // EXP(Y)+1 - sign = aSign ? 0x80000000 : 0x00000000; - fp1 = floatx80_div(float32_to_floatx80(sign^0xC0000000, status), fp0, status); // -SIGN(X)*2 / [EXP(Y)+1] - fp0 = float32_to_floatx80(sign | 0x3F800000, status); // SIGN - - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - a = floatx80_add(fp1, fp0, status); - - float_raise(float_flag_inexact, status); - - return a; - } - } - } else { // 2**(-40) < |X| < (5/2)LOG2 - fp0 = packFloatx80(0, aExp+1, aSig); // Y = 2|X| - fp0 = floatx80_etoxm1(fp0, status); // FP0 IS Z = EXPM1(Y) - fp1 = floatx80_add(fp0, float32_to_floatx80(0x40000000, status), status); // Z+2 - - vSign = extractFloatx80Sign(fp1); - vExp = extractFloatx80Exp(fp1); - vSig = extractFloatx80Frac(fp1); - - fp1 = packFloatx80(vSign ^ aSign, vExp, vSig); - - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - a = floatx80_div(fp0, fp1, status); - - float_raise(float_flag_inexact, status); - - return a; - } + flag aSign, vSign; + int32_t aExp, vExp; + uint64_t aSig, vSig; + + int32_t compact; + floatx80 fp0, fp1; + float32 sign; + + aSig = extractFloatx80Frac(a); + aExp = extractFloatx80Exp(a); + aSign = extractFloatx80Sign(a); + + if (aExp == 0x7FFF) { + if ((uint64_t) (aSig<<1)) return propagateFloatx80NaNOneArg(a, status); + return packFloatx80(aSign, one_exp, one_sig); + } + + if (aExp == 0 && aSig == 0) { + return packFloatx80(aSign, 0, 0); + } + + SET_PREC; + + compact = floatx80_make_compact(aExp, aSig); + + if (compact < 0x3FD78000 || compact > 0x3FFFDDCE) { + // TANHBORS + if (compact < 0x3FFF8000) { + // TANHSM + RESET_PREC; + + a = floatx80_move(a, status); + + float_raise(float_flag_inexact, status); + + return a; + } else { + if (compact > 0x40048AA1) { + // TANHHUGE + sign = 0x3F800000; + sign |= aSign ? 0x80000000 : 0x00000000; + fp0 = float32_to_floatx80(sign, status); + sign &= 0x80000000; + sign ^= 0x80800000; // -SIGN(X)*EPS + + RESET_PREC; + + a = floatx80_add(fp0, float32_to_floatx80(sign, status), status); + + float_raise(float_flag_inexact, status); + + return a; + } else { + fp0 = packFloatx80(0, aExp+1, aSig); // Y = 2|X| + fp0 = floatx80_etox(fp0, status); // FP0 IS EXP(Y) + fp0 = floatx80_add(fp0, float32_to_floatx80(0x3F800000, status), status); // EXP(Y)+1 + sign = aSign ? 0x80000000 : 0x00000000; + fp1 = floatx80_div(float32_to_floatx80(sign^0xC0000000, status), fp0, status); // -SIGN(X)*2 / [EXP(Y)+1] + fp0 = float32_to_floatx80(sign | 0x3F800000, status); // SIGN + + RESET_PREC; + + a = floatx80_add(fp1, fp0, status); + + float_raise(float_flag_inexact, status); + + return a; + } + } + } else { // 2**(-40) < |X| < (5/2)LOG2 + fp0 = packFloatx80(0, aExp+1, aSig); // Y = 2|X| + fp0 = floatx80_etoxm1(fp0, status); // FP0 IS Z = EXPM1(Y) + fp1 = floatx80_add(fp0, float32_to_floatx80(0x40000000, status), status); // Z+2 + + vSign = extractFloatx80Sign(fp1); + vExp = extractFloatx80Exp(fp1); + vSig = extractFloatx80Frac(fp1); + + fp1 = packFloatx80(vSign ^ aSign, vExp, vSig); + + RESET_PREC; + + a = floatx80_div(fp0, fp1, status); + + float_raise(float_flag_inexact, status); + + return a; + } } /*---------------------------------------------------------------------------- @@ -2032,121 +1948,115 @@ floatx80 floatx80_tanh(floatx80 a, float_status *status) floatx80 floatx80_tentox(floatx80 a, float_status *status) { - flag aSign; - int32_t aExp; - uint64_t aSig; - - int8_t user_rnd_mode, user_rnd_prec; - - int32_t compact, n, j, l, m, m1; - floatx80 fp0, fp1, fp2, fp3, adjfact, fact1, fact2; - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - - if (aExp == 0x7FFF) { - if ((uint64_t) (aSig<<1)) return propagateFloatx80NaNOneArg(a, status); - if (aSign) return packFloatx80(0, 0, 0); - return packFloatx80(0, 0x7FFF, floatx80_default_infinity_low); - } - - if (aExp == 0 && aSig == 0) { - return packFloatx80(0, one_exp, one_sig); - } - - user_rnd_mode = status->float_rounding_mode; - user_rnd_prec = status->floatx80_rounding_precision; - - fp0 = a; - - compact = floatx80_make_compact(aExp, aSig); - - if (compact < 0x3FB98000 || compact > 0x400B9B07) { // |X| > 16480 LOG2/LOG10 or |X| < 2^(-70) - if (compact > 0x3FFF8000) { // |X| > 16480 - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - if (aSign) { - return roundAndPackFloatx80(status->floatx80_rounding_precision, 0, -0x1000, aSig, 0, status); - } else { - return roundAndPackFloatx80(status->floatx80_rounding_precision, 0, 0x8000, aSig, 0, status); - } - } else { // |X| < 2^(-70) - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - a = floatx80_add(fp0, float32_to_floatx80(0x3F800000, status), status); // 1 + X - - float_raise(float_flag_inexact, status); - - return a; - } - } else { // 2^(-70) <= |X| <= 16480 LOG 2 / LOG 10 - fp1 = fp0; // X - fp1 = floatx80_mul(fp1, float64_to_floatx80(LIT64(0x406A934F0979A371), status), status); // X*64*LOG10/LOG2 - n = floatx80_to_int32(fp1, status); // N=INT(X*64*LOG10/LOG2) - fp1 = int32_to_floatx80(n); - - j = n & 0x3F; - l = n / 64; // NOTE: this is really arithmetic right shift by 6 - if (n < 0 && j) { // arithmetic right shift is division and round towards minus infinity - l--; - } - m = l / 2; // NOTE: this is really arithmetic right shift by 1 - if (l < 0 && (l & 1)) { // arithmetic right shift is division and round towards minus infinity - m--; - } - m1 = l - m; - m1 += 0x3FFF; // ADJFACT IS 2^(M') - - adjfact = packFloatx80(0, m1, one_sig); - fact1 = exp2_tbl[j]; - fact1.high += m; - fact2.high = exp2_tbl2[j]>>16; - fact2.high += m; - fact2.low = (uint64_t)(exp2_tbl2[j] & 0xFFFF); - fact2.low <<= 48; - - fp2 = fp1; // N - fp1 = floatx80_mul(fp1, float64_to_floatx80(LIT64(0x3F734413509F8000), status), status); // N*(LOG2/64LOG10)_LEAD - fp3 = packFloatx80(1, 0x3FCD, LIT64(0xC0219DC1DA994FD2)); - fp2 = floatx80_mul(fp2, fp3, status); // N*(LOG2/64LOG10)_TRAIL - fp0 = floatx80_sub(fp0, fp1, status); // X - N L_LEAD - fp0 = floatx80_sub(fp0, fp2, status); // X - N L_TRAIL - fp2 = packFloatx80(0, 0x4000, LIT64(0x935D8DDDAAA8AC17)); // LOG10 - fp0 = floatx80_mul(fp0, fp2, status); // R - - // EXPR - fp1 = floatx80_mul(fp0, fp0, status); // S = R*R - fp2 = float64_to_floatx80(LIT64(0x3F56C16D6F7BD0B2), status); // A5 - fp3 = float64_to_floatx80(LIT64(0x3F811112302C712C), status); // A4 - fp2 = floatx80_mul(fp2, fp1, status); // S*A5 - fp3 = floatx80_mul(fp3, fp1, status); // S*A4 - fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3FA5555555554CC1), status), status); // A3+S*A5 - fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0x3FC5555555554A54), status), status); // A2+S*A4 - fp2 = floatx80_mul(fp2, fp1, status); // S*(A3+S*A5) - fp3 = floatx80_mul(fp3, fp1, status); // S*(A2+S*A4) - fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3FE0000000000000), status), status); // A1+S*(A3+S*A5) - fp3 = floatx80_mul(fp3, fp0, status); // R*S*(A2+S*A4) - - fp2 = floatx80_mul(fp2, fp1, status); // S*(A1+S*(A3+S*A5)) - fp0 = floatx80_add(fp0, fp3, status); // R+R*S*(A2+S*A4) - fp0 = floatx80_add(fp0, fp2, status); // EXP(R) - 1 - - fp0 = floatx80_mul(fp0, fact1, status); - fp0 = floatx80_add(fp0, fact2, status); - fp0 = floatx80_add(fp0, fact1, status); - - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - a = floatx80_mul(fp0, adjfact, status); - - float_raise(float_flag_inexact, status); - - return a; - } + flag aSign; + int32_t aExp; + uint64_t aSig; + + int32_t compact, n, j, l, m, m1; + floatx80 fp0, fp1, fp2, fp3, adjfact, fact1, fact2; + + aSig = extractFloatx80Frac(a); + aExp = extractFloatx80Exp(a); + aSign = extractFloatx80Sign(a); + + if (aExp == 0x7FFF) { + if ((uint64_t) (aSig<<1)) return propagateFloatx80NaNOneArg(a, status); + if (aSign) return packFloatx80(0, 0, 0); + return packFloatx80(0, 0x7FFF, floatx80_default_infinity_low); + } + + if (aExp == 0 && aSig == 0) { + return packFloatx80(0, one_exp, one_sig); + } + + SET_PREC; + + fp0 = a; + + compact = floatx80_make_compact(aExp, aSig); + + if (compact < 0x3FB98000 || compact > 0x400B9B07) { // |X| > 16480 LOG2/LOG10 or |X| < 2^(-70) + if (compact > 0x3FFF8000) { // |X| > 16480 + RESET_PREC; + + if (aSign) { + return roundAndPackFloatx80(status->floatx80_rounding_precision, 0, -0x1000, aSig, 0, status); + } else { + return roundAndPackFloatx80(status->floatx80_rounding_precision, 0, 0x8000, aSig, 0, status); + } + } else { // |X| < 2^(-70) + RESET_PREC; + + a = floatx80_add(fp0, float32_to_floatx80(0x3F800000, status), status); // 1 + X + + float_raise(float_flag_inexact, status); + + return a; + } + } else { // 2^(-70) <= |X| <= 16480 LOG 2 / LOG 10 + fp1 = fp0; // X + fp1 = floatx80_mul(fp1, float64_to_floatx80(LIT64(0x406A934F0979A371), status), status); // X*64*LOG10/LOG2 + n = floatx80_to_int32(fp1, status); // N=INT(X*64*LOG10/LOG2) + fp1 = int32_to_floatx80(n); + + j = n & 0x3F; + l = n / 64; // NOTE: this is really arithmetic right shift by 6 + if (n < 0 && j) { // arithmetic right shift is division and round towards minus infinity + l--; + } + m = l / 2; // NOTE: this is really arithmetic right shift by 1 + if (l < 0 && (l & 1)) { // arithmetic right shift is division and round towards minus infinity + m--; + } + m1 = l - m; + m1 += 0x3FFF; // ADJFACT IS 2^(M') + + adjfact = packFloatx80(0, m1, one_sig); + fact1 = exp2_tbl[j]; + fact1.high += m; + fact2.high = exp2_tbl2[j]>>16; + fact2.high += m; + fact2.low = (uint64_t)(exp2_tbl2[j] & 0xFFFF); + fact2.low <<= 48; + + fp2 = fp1; // N + fp1 = floatx80_mul(fp1, float64_to_floatx80(LIT64(0x3F734413509F8000), status), status); // N*(LOG2/64LOG10)_LEAD + fp3 = packFloatx80(1, 0x3FCD, LIT64(0xC0219DC1DA994FD2)); + fp2 = floatx80_mul(fp2, fp3, status); // N*(LOG2/64LOG10)_TRAIL + fp0 = floatx80_sub(fp0, fp1, status); // X - N L_LEAD + fp0 = floatx80_sub(fp0, fp2, status); // X - N L_TRAIL + fp2 = packFloatx80(0, 0x4000, LIT64(0x935D8DDDAAA8AC17)); // LOG10 + fp0 = floatx80_mul(fp0, fp2, status); // R + + // EXPR + fp1 = floatx80_mul(fp0, fp0, status); // S = R*R + fp2 = float64_to_floatx80(LIT64(0x3F56C16D6F7BD0B2), status); // A5 + fp3 = float64_to_floatx80(LIT64(0x3F811112302C712C), status); // A4 + fp2 = floatx80_mul(fp2, fp1, status); // S*A5 + fp3 = floatx80_mul(fp3, fp1, status); // S*A4 + fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3FA5555555554CC1), status), status); // A3+S*A5 + fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0x3FC5555555554A54), status), status); // A2+S*A4 + fp2 = floatx80_mul(fp2, fp1, status); // S*(A3+S*A5) + fp3 = floatx80_mul(fp3, fp1, status); // S*(A2+S*A4) + fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3FE0000000000000), status), status); // A1+S*(A3+S*A5) + fp3 = floatx80_mul(fp3, fp0, status); // R*S*(A2+S*A4) + + fp2 = floatx80_mul(fp2, fp1, status); // S*(A1+S*(A3+S*A5)) + fp0 = floatx80_add(fp0, fp3, status); // R+R*S*(A2+S*A4) + fp0 = floatx80_add(fp0, fp2, status); // EXP(R) - 1 + + fp0 = floatx80_mul(fp0, fact1, status); + fp0 = floatx80_add(fp0, fact2, status); + fp0 = floatx80_add(fp0, fact1, status); + + RESET_PREC; + + a = floatx80_mul(fp0, adjfact, status); + + float_raise(float_flag_inexact, status); + + return a; + } } /*---------------------------------------------------------------------------- @@ -2155,114 +2065,108 @@ floatx80 floatx80_tentox(floatx80 a, float_status *status) floatx80 floatx80_twotox(floatx80 a, float_status *status) { - flag aSign; - int32_t aExp; - uint64_t aSig; - - int8_t user_rnd_mode, user_rnd_prec; - - int32_t compact, n, j, l, m, m1; - floatx80 fp0, fp1, fp2, fp3, adjfact, fact1, fact2; - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - - if (aExp == 0x7FFF) { - if ((uint64_t) (aSig<<1)) return propagateFloatx80NaNOneArg(a, status); - if (aSign) return packFloatx80(0, 0, 0); - return packFloatx80(0, 0x7FFF, floatx80_default_infinity_low); - } - - if (aExp == 0 && aSig == 0) { - return packFloatx80(0, one_exp, one_sig); - } - - user_rnd_mode = status->float_rounding_mode; - user_rnd_prec = status->floatx80_rounding_precision; - - fp0 = a; - - compact = floatx80_make_compact(aExp, aSig); - - if (compact < 0x3FB98000 || compact > 0x400D80C0) { // |X| > 16480 or |X| < 2^(-70) - if (compact > 0x3FFF8000) { // |X| > 16480 - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - if (aSign) { - return roundAndPackFloatx80(status->floatx80_rounding_precision, 0, -0x1000, aSig, 0, status); - } else { - return roundAndPackFloatx80(status->floatx80_rounding_precision, 0, 0x8000, aSig, 0, status); - } - } else { // |X| < 2^(-70) - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - a = floatx80_add(fp0, float32_to_floatx80(0x3F800000, status), status); // 1 + X - - float_raise(float_flag_inexact, status); - - return a; - } - } else { // 2^(-70) <= |X| <= 16480 - fp1 = fp0; // X - fp1 = floatx80_mul(fp1, float32_to_floatx80(0x42800000, status), status); // X * 64 - n = floatx80_to_int32(fp1, status); - fp1 = int32_to_floatx80(n); - j = n & 0x3F; - l = n / 64; // NOTE: this is really arithmetic right shift by 6 - if (n < 0 && j) { // arithmetic right shift is division and round towards minus infinity - l--; - } - m = l / 2; // NOTE: this is really arithmetic right shift by 1 - if (l < 0 && (l & 1)) { // arithmetic right shift is division and round towards minus infinity - m--; - } - m1 = l - m; - m1 += 0x3FFF; // ADJFACT IS 2^(M') - - adjfact = packFloatx80(0, m1, one_sig); - fact1 = exp2_tbl[j]; - fact1.high += m; - fact2.high = exp2_tbl2[j]>>16; - fact2.high += m; - fact2.low = (uint64_t)(exp2_tbl2[j] & 0xFFFF); - fact2.low <<= 48; - - fp1 = floatx80_mul(fp1, float32_to_floatx80(0x3C800000, status), status); // (1/64)*N - fp0 = floatx80_sub(fp0, fp1, status); // X - (1/64)*INT(64 X) - fp2 = packFloatx80(0, 0x3FFE, LIT64(0xB17217F7D1CF79AC)); // LOG2 - fp0 = floatx80_mul(fp0, fp2, status); // R - - // EXPR - fp1 = floatx80_mul(fp0, fp0, status); // S = R*R - fp2 = float64_to_floatx80(LIT64(0x3F56C16D6F7BD0B2), status); // A5 - fp3 = float64_to_floatx80(LIT64(0x3F811112302C712C), status); // A4 - fp2 = floatx80_mul(fp2, fp1, status); // S*A5 - fp3 = floatx80_mul(fp3, fp1, status); // S*A4 - fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3FA5555555554CC1), status), status); // A3+S*A5 - fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0x3FC5555555554A54), status), status); // A2+S*A4 - fp2 = floatx80_mul(fp2, fp1, status); // S*(A3+S*A5) - fp3 = floatx80_mul(fp3, fp1, status); // S*(A2+S*A4) - fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3FE0000000000000), status), status); // A1+S*(A3+S*A5) - fp3 = floatx80_mul(fp3, fp0, status); // R*S*(A2+S*A4) - - fp2 = floatx80_mul(fp2, fp1, status); // S*(A1+S*(A3+S*A5)) - fp0 = floatx80_add(fp0, fp3, status); // R+R*S*(A2+S*A4) - fp0 = floatx80_add(fp0, fp2, status); // EXP(R) - 1 - - fp0 = floatx80_mul(fp0, fact1, status); - fp0 = floatx80_add(fp0, fact2, status); - fp0 = floatx80_add(fp0, fact1, status); - - status->float_rounding_mode = user_rnd_mode; - status->floatx80_rounding_precision = user_rnd_prec; - - a = floatx80_mul(fp0, adjfact, status); - - float_raise(float_flag_inexact, status); - - return a; - } + flag aSign; + int32_t aExp; + uint64_t aSig; + + int32_t compact, n, j, l, m, m1; + floatx80 fp0, fp1, fp2, fp3, adjfact, fact1, fact2; + + aSig = extractFloatx80Frac(a); + aExp = extractFloatx80Exp(a); + aSign = extractFloatx80Sign(a); + + if (aExp == 0x7FFF) { + if ((uint64_t) (aSig<<1)) return propagateFloatx80NaNOneArg(a, status); + if (aSign) return packFloatx80(0, 0, 0); + return packFloatx80(0, 0x7FFF, floatx80_default_infinity_low); + } + + if (aExp == 0 && aSig == 0) { + return packFloatx80(0, one_exp, one_sig); + } + + SET_PREC; + + fp0 = a; + + compact = floatx80_make_compact(aExp, aSig); + + if (compact < 0x3FB98000 || compact > 0x400D80C0) { // |X| > 16480 or |X| < 2^(-70) + if (compact > 0x3FFF8000) { // |X| > 16480 + RESET_PREC;; + + if (aSign) { + return roundAndPackFloatx80(status->floatx80_rounding_precision, 0, -0x1000, aSig, 0, status); + } else { + return roundAndPackFloatx80(status->floatx80_rounding_precision, 0, 0x8000, aSig, 0, status); + } + } else { // |X| < 2^(-70) + RESET_PREC;; + + a = floatx80_add(fp0, float32_to_floatx80(0x3F800000, status), status); // 1 + X + + float_raise(float_flag_inexact, status); + + return a; + } + } else { // 2^(-70) <= |X| <= 16480 + fp1 = fp0; // X + fp1 = floatx80_mul(fp1, float32_to_floatx80(0x42800000, status), status); // X * 64 + n = floatx80_to_int32(fp1, status); + fp1 = int32_to_floatx80(n); + j = n & 0x3F; + l = n / 64; // NOTE: this is really arithmetic right shift by 6 + if (n < 0 && j) { // arithmetic right shift is division and round towards minus infinity + l--; + } + m = l / 2; // NOTE: this is really arithmetic right shift by 1 + if (l < 0 && (l & 1)) { // arithmetic right shift is division and round towards minus infinity + m--; + } + m1 = l - m; + m1 += 0x3FFF; // ADJFACT IS 2^(M') + + adjfact = packFloatx80(0, m1, one_sig); + fact1 = exp2_tbl[j]; + fact1.high += m; + fact2.high = exp2_tbl2[j]>>16; + fact2.high += m; + fact2.low = (uint64_t)(exp2_tbl2[j] & 0xFFFF); + fact2.low <<= 48; + + fp1 = floatx80_mul(fp1, float32_to_floatx80(0x3C800000, status), status); // (1/64)*N + fp0 = floatx80_sub(fp0, fp1, status); // X - (1/64)*INT(64 X) + fp2 = packFloatx80(0, 0x3FFE, LIT64(0xB17217F7D1CF79AC)); // LOG2 + fp0 = floatx80_mul(fp0, fp2, status); // R + + // EXPR + fp1 = floatx80_mul(fp0, fp0, status); // S = R*R + fp2 = float64_to_floatx80(LIT64(0x3F56C16D6F7BD0B2), status); // A5 + fp3 = float64_to_floatx80(LIT64(0x3F811112302C712C), status); // A4 + fp2 = floatx80_mul(fp2, fp1, status); // S*A5 + fp3 = floatx80_mul(fp3, fp1, status); // S*A4 + fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3FA5555555554CC1), status), status); // A3+S*A5 + fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0x3FC5555555554A54), status), status); // A2+S*A4 + fp2 = floatx80_mul(fp2, fp1, status); // S*(A3+S*A5) + fp3 = floatx80_mul(fp3, fp1, status); // S*(A2+S*A4) + fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3FE0000000000000), status), status); // A1+S*(A3+S*A5) + fp3 = floatx80_mul(fp3, fp0, status); // R*S*(A2+S*A4) + + fp2 = floatx80_mul(fp2, fp1, status); // S*(A1+S*(A3+S*A5)) + fp0 = floatx80_add(fp0, fp3, status); // R+R*S*(A2+S*A4) + fp0 = floatx80_add(fp0, fp2, status); // EXP(R) - 1 + + fp0 = floatx80_mul(fp0, fact1, status); + fp0 = floatx80_add(fp0, fact2, status); + fp0 = floatx80_add(fp0, fact1, status); + + RESET_PREC; + + a = floatx80_mul(fp0, adjfact, status); + + float_raise(float_flag_inexact, status); + + return a; + } } diff --git a/softfloat/softfloat_fpsp_tables.h b/softfloat/softfloat_fpsp_tables.h index 4f860132..b2b29527 100644 --- a/softfloat/softfloat_fpsp_tables.h +++ b/softfloat/softfloat_fpsp_tables.h @@ -1,528 +1,528 @@ static const floatx80 atan_tbl[128] = { - {0x3FFB, LIT64(0x83D152C5060B7A51)}, - {0x3FFB, LIT64(0x8BC8544565498B8B)}, - {0x3FFB, LIT64(0x93BE406017626B0D)}, - {0x3FFB, LIT64(0x9BB3078D35AEC202)}, - {0x3FFB, LIT64(0xA3A69A525DDCE7DE)}, - {0x3FFB, LIT64(0xAB98E94362765619)}, - {0x3FFB, LIT64(0xB389E502F9C59862)}, - {0x3FFB, LIT64(0xBB797E436B09E6FB)}, - {0x3FFB, LIT64(0xC367A5C739E5F446)}, - {0x3FFB, LIT64(0xCB544C61CFF7D5C6)}, - {0x3FFB, LIT64(0xD33F62F82488533E)}, - {0x3FFB, LIT64(0xDB28DA8162404C77)}, - {0x3FFB, LIT64(0xE310A4078AD34F18)}, - {0x3FFB, LIT64(0xEAF6B0A8188EE1EB)}, - {0x3FFB, LIT64(0xF2DAF1949DBE79D5)}, - {0x3FFB, LIT64(0xFABD581361D47E3E)}, - {0x3FFC, LIT64(0x8346AC210959ECC4)}, - {0x3FFC, LIT64(0x8B232A08304282D8)}, - {0x3FFC, LIT64(0x92FB70B8D29AE2F9)}, - {0x3FFC, LIT64(0x9ACF476F5CCD1CB4)}, - {0x3FFC, LIT64(0xA29E76304954F23F)}, - {0x3FFC, LIT64(0xAA68C5D08AB85230)}, - {0x3FFC, LIT64(0xB22DFFFD9D539F83)}, - {0x3FFC, LIT64(0xB9EDEF453E900EA5)}, - {0x3FFC, LIT64(0xC1A85F1CC75E3EA5)}, - {0x3FFC, LIT64(0xC95D1BE828138DE6)}, - {0x3FFC, LIT64(0xD10BF300840D2DE4)}, - {0x3FFC, LIT64(0xD8B4B2BA6BC05E7A)}, - {0x3FFC, LIT64(0xE0572A6BB42335F6)}, - {0x3FFC, LIT64(0xE7F32A70EA9CAA8F)}, - {0x3FFC, LIT64(0xEF88843264ECEFAA)}, - {0x3FFC, LIT64(0xF7170A28ECC06666)}, - {0x3FFD, LIT64(0x812FD288332DAD32)}, - {0x3FFD, LIT64(0x88A8D1B1218E4D64)}, - {0x3FFD, LIT64(0x9012AB3F23E4AEE8)}, - {0x3FFD, LIT64(0x976CC3D411E7F1B9)}, - {0x3FFD, LIT64(0x9EB689493889A227)}, - {0x3FFD, LIT64(0xA5EF72C34487361B)}, - {0x3FFD, LIT64(0xAD1700BAF07A7227)}, - {0x3FFD, LIT64(0xB42CBCFAFD37EFB7)}, - {0x3FFD, LIT64(0xBB303A940BA80F89)}, - {0x3FFD, LIT64(0xC22115C6FCAEBBAF)}, - {0x3FFD, LIT64(0xC8FEF3E686331221)}, - {0x3FFD, LIT64(0xCFC98330B4000C70)}, - {0x3FFD, LIT64(0xD6807AA1102C5BF9)}, - {0x3FFD, LIT64(0xDD2399BC31252AA3)}, - {0x3FFD, LIT64(0xE3B2A8556B8FC517)}, - {0x3FFD, LIT64(0xEA2D764F64315989)}, - {0x3FFD, LIT64(0xF3BF5BF8BAD1A21D)}, - {0x3FFE, LIT64(0x801CE39E0D205C9A)}, - {0x3FFE, LIT64(0x8630A2DADA1ED066)}, - {0x3FFE, LIT64(0x8C1AD445F3E09B8C)}, - {0x3FFE, LIT64(0x91DB8F1664F350E2)}, - {0x3FFE, LIT64(0x97731420365E538C)}, - {0x3FFE, LIT64(0x9CE1C8E6A0B8CDBA)}, - {0x3FFE, LIT64(0xA22832DBCADAAE09)}, - {0x3FFE, LIT64(0xA746F2DDB7602294)}, - {0x3FFE, LIT64(0xAC3EC0FB997DD6A2)}, - {0x3FFE, LIT64(0xB110688AEBDC6F6A)}, - {0x3FFE, LIT64(0xB5BCC49059ECC4B0)}, - {0x3FFE, LIT64(0xBA44BC7DD470782F)}, - {0x3FFE, LIT64(0xBEA94144FD049AAC)}, - {0x3FFE, LIT64(0xC2EB4ABB661628B6)}, - {0x3FFE, LIT64(0xC70BD54CE602EE14)}, - {0x3FFE, LIT64(0xCD000549ADEC7159)}, - {0x3FFE, LIT64(0xD48457D2D8EA4EA3)}, - {0x3FFE, LIT64(0xDB948DA712DECE3B)}, - {0x3FFE, LIT64(0xE23855F969E8096A)}, - {0x3FFE, LIT64(0xE8771129C4353259)}, - {0x3FFE, LIT64(0xEE57C16E0D379C0D)}, - {0x3FFE, LIT64(0xF3E10211A87C3779)}, - {0x3FFE, LIT64(0xF919039D758B8D41)}, - {0x3FFE, LIT64(0xFE058B8F64935FB3)}, - {0x3FFF, LIT64(0x8155FB497B685D04)}, - {0x3FFF, LIT64(0x83889E3549D108E1)}, - {0x3FFF, LIT64(0x859CFA76511D724B)}, - {0x3FFF, LIT64(0x87952ECFFF8131E7)}, - {0x3FFF, LIT64(0x89732FD19557641B)}, - {0x3FFF, LIT64(0x8B38CAD101932A35)}, - {0x3FFF, LIT64(0x8CE7A8D8301EE6B5)}, - {0x3FFF, LIT64(0x8F46A39E2EAE5281)}, - {0x3FFF, LIT64(0x922DA7D791888487)}, - {0x3FFF, LIT64(0x94D19FCBDEDF5241)}, - {0x3FFF, LIT64(0x973AB94419D2A08B)}, - {0x3FFF, LIT64(0x996FF00E08E10B96)}, - {0x3FFF, LIT64(0x9B773F9512321DA7)}, - {0x3FFF, LIT64(0x9D55CC320F935624)}, - {0x3FFF, LIT64(0x9F100575006CC571)}, - {0x3FFF, LIT64(0xA0A9C290D97CC06C)}, - {0x3FFF, LIT64(0xA22659EBEBC0630A)}, - {0x3FFF, LIT64(0xA388B4AFF6EF0EC9)}, - {0x3FFF, LIT64(0xA4D35F1061D292C4)}, - {0x3FFF, LIT64(0xA60895DCFBE3187E)}, - {0x3FFF, LIT64(0xA72A51DC7367BEAC)}, - {0x3FFF, LIT64(0xA83A51530956168F)}, - {0x3FFF, LIT64(0xA93A20077539546E)}, - {0x3FFF, LIT64(0xAA9E7245023B2605)}, - {0x3FFF, LIT64(0xAC4C84BA6FE4D58F)}, - {0x3FFF, LIT64(0xADCE4A4A606B9712)}, - {0x3FFF, LIT64(0xAF2A2DCD8D263C9C)}, - {0x3FFF, LIT64(0xB0656F81F22265C7)}, - {0x3FFF, LIT64(0xB18465150F71496A)}, - {0x3FFF, LIT64(0xB28AAA156F9ADA35)}, - {0x3FFF, LIT64(0xB37B44FF3766B895)}, - {0x3FFF, LIT64(0xB458C3DCE9630433)}, - {0x3FFF, LIT64(0xB525529D562246BD)}, - {0x3FFF, LIT64(0xB5E2CCA95F9D88CC)}, - {0x3FFF, LIT64(0xB692CADA7ACA1ADA)}, - {0x3FFF, LIT64(0xB736AEA7A6925838)}, - {0x3FFF, LIT64(0xB7CFAB287E9F7B36)}, - {0x3FFF, LIT64(0xB85ECC66CB219835)}, - {0x3FFF, LIT64(0xB8E4FD5A20A593DA)}, - {0x3FFF, LIT64(0xB99F41F64AFF9BB5)}, - {0x3FFF, LIT64(0xBA7F1E17842BBE7B)}, - {0x3FFF, LIT64(0xBB4712857637E17D)}, - {0x3FFF, LIT64(0xBBFABE8A4788DF6F)}, - {0x3FFF, LIT64(0xBC9D0FAD2B689D79)}, - {0x3FFF, LIT64(0xBD306A39471ECD86)}, - {0x3FFF, LIT64(0xBDB6C731856AF18A)}, - {0x3FFF, LIT64(0xBE31CAC502E80D70)}, - {0x3FFF, LIT64(0xBEA2D55CE33194E2)}, - {0x3FFF, LIT64(0xBF0B10B7C03128F0)}, - {0x3FFF, LIT64(0xBF6B7A18DACB778D)}, - {0x3FFF, LIT64(0xBFC4EA4663FA18F6)}, - {0x3FFF, LIT64(0xC0181BDE8B89A454)}, - {0x3FFF, LIT64(0xC065B066CFBF6439)}, - {0x3FFF, LIT64(0xC0AE345F56340AE6)}, - {0x3FFF, LIT64(0xC0F222919CB9E6A7)} + {0x3FFB, LIT64(0x83D152C5060B7A51)}, + {0x3FFB, LIT64(0x8BC8544565498B8B)}, + {0x3FFB, LIT64(0x93BE406017626B0D)}, + {0x3FFB, LIT64(0x9BB3078D35AEC202)}, + {0x3FFB, LIT64(0xA3A69A525DDCE7DE)}, + {0x3FFB, LIT64(0xAB98E94362765619)}, + {0x3FFB, LIT64(0xB389E502F9C59862)}, + {0x3FFB, LIT64(0xBB797E436B09E6FB)}, + {0x3FFB, LIT64(0xC367A5C739E5F446)}, + {0x3FFB, LIT64(0xCB544C61CFF7D5C6)}, + {0x3FFB, LIT64(0xD33F62F82488533E)}, + {0x3FFB, LIT64(0xDB28DA8162404C77)}, + {0x3FFB, LIT64(0xE310A4078AD34F18)}, + {0x3FFB, LIT64(0xEAF6B0A8188EE1EB)}, + {0x3FFB, LIT64(0xF2DAF1949DBE79D5)}, + {0x3FFB, LIT64(0xFABD581361D47E3E)}, + {0x3FFC, LIT64(0x8346AC210959ECC4)}, + {0x3FFC, LIT64(0x8B232A08304282D8)}, + {0x3FFC, LIT64(0x92FB70B8D29AE2F9)}, + {0x3FFC, LIT64(0x9ACF476F5CCD1CB4)}, + {0x3FFC, LIT64(0xA29E76304954F23F)}, + {0x3FFC, LIT64(0xAA68C5D08AB85230)}, + {0x3FFC, LIT64(0xB22DFFFD9D539F83)}, + {0x3FFC, LIT64(0xB9EDEF453E900EA5)}, + {0x3FFC, LIT64(0xC1A85F1CC75E3EA5)}, + {0x3FFC, LIT64(0xC95D1BE828138DE6)}, + {0x3FFC, LIT64(0xD10BF300840D2DE4)}, + {0x3FFC, LIT64(0xD8B4B2BA6BC05E7A)}, + {0x3FFC, LIT64(0xE0572A6BB42335F6)}, + {0x3FFC, LIT64(0xE7F32A70EA9CAA8F)}, + {0x3FFC, LIT64(0xEF88843264ECEFAA)}, + {0x3FFC, LIT64(0xF7170A28ECC06666)}, + {0x3FFD, LIT64(0x812FD288332DAD32)}, + {0x3FFD, LIT64(0x88A8D1B1218E4D64)}, + {0x3FFD, LIT64(0x9012AB3F23E4AEE8)}, + {0x3FFD, LIT64(0x976CC3D411E7F1B9)}, + {0x3FFD, LIT64(0x9EB689493889A227)}, + {0x3FFD, LIT64(0xA5EF72C34487361B)}, + {0x3FFD, LIT64(0xAD1700BAF07A7227)}, + {0x3FFD, LIT64(0xB42CBCFAFD37EFB7)}, + {0x3FFD, LIT64(0xBB303A940BA80F89)}, + {0x3FFD, LIT64(0xC22115C6FCAEBBAF)}, + {0x3FFD, LIT64(0xC8FEF3E686331221)}, + {0x3FFD, LIT64(0xCFC98330B4000C70)}, + {0x3FFD, LIT64(0xD6807AA1102C5BF9)}, + {0x3FFD, LIT64(0xDD2399BC31252AA3)}, + {0x3FFD, LIT64(0xE3B2A8556B8FC517)}, + {0x3FFD, LIT64(0xEA2D764F64315989)}, + {0x3FFD, LIT64(0xF3BF5BF8BAD1A21D)}, + {0x3FFE, LIT64(0x801CE39E0D205C9A)}, + {0x3FFE, LIT64(0x8630A2DADA1ED066)}, + {0x3FFE, LIT64(0x8C1AD445F3E09B8C)}, + {0x3FFE, LIT64(0x91DB8F1664F350E2)}, + {0x3FFE, LIT64(0x97731420365E538C)}, + {0x3FFE, LIT64(0x9CE1C8E6A0B8CDBA)}, + {0x3FFE, LIT64(0xA22832DBCADAAE09)}, + {0x3FFE, LIT64(0xA746F2DDB7602294)}, + {0x3FFE, LIT64(0xAC3EC0FB997DD6A2)}, + {0x3FFE, LIT64(0xB110688AEBDC6F6A)}, + {0x3FFE, LIT64(0xB5BCC49059ECC4B0)}, + {0x3FFE, LIT64(0xBA44BC7DD470782F)}, + {0x3FFE, LIT64(0xBEA94144FD049AAC)}, + {0x3FFE, LIT64(0xC2EB4ABB661628B6)}, + {0x3FFE, LIT64(0xC70BD54CE602EE14)}, + {0x3FFE, LIT64(0xCD000549ADEC7159)}, + {0x3FFE, LIT64(0xD48457D2D8EA4EA3)}, + {0x3FFE, LIT64(0xDB948DA712DECE3B)}, + {0x3FFE, LIT64(0xE23855F969E8096A)}, + {0x3FFE, LIT64(0xE8771129C4353259)}, + {0x3FFE, LIT64(0xEE57C16E0D379C0D)}, + {0x3FFE, LIT64(0xF3E10211A87C3779)}, + {0x3FFE, LIT64(0xF919039D758B8D41)}, + {0x3FFE, LIT64(0xFE058B8F64935FB3)}, + {0x3FFF, LIT64(0x8155FB497B685D04)}, + {0x3FFF, LIT64(0x83889E3549D108E1)}, + {0x3FFF, LIT64(0x859CFA76511D724B)}, + {0x3FFF, LIT64(0x87952ECFFF8131E7)}, + {0x3FFF, LIT64(0x89732FD19557641B)}, + {0x3FFF, LIT64(0x8B38CAD101932A35)}, + {0x3FFF, LIT64(0x8CE7A8D8301EE6B5)}, + {0x3FFF, LIT64(0x8F46A39E2EAE5281)}, + {0x3FFF, LIT64(0x922DA7D791888487)}, + {0x3FFF, LIT64(0x94D19FCBDEDF5241)}, + {0x3FFF, LIT64(0x973AB94419D2A08B)}, + {0x3FFF, LIT64(0x996FF00E08E10B96)}, + {0x3FFF, LIT64(0x9B773F9512321DA7)}, + {0x3FFF, LIT64(0x9D55CC320F935624)}, + {0x3FFF, LIT64(0x9F100575006CC571)}, + {0x3FFF, LIT64(0xA0A9C290D97CC06C)}, + {0x3FFF, LIT64(0xA22659EBEBC0630A)}, + {0x3FFF, LIT64(0xA388B4AFF6EF0EC9)}, + {0x3FFF, LIT64(0xA4D35F1061D292C4)}, + {0x3FFF, LIT64(0xA60895DCFBE3187E)}, + {0x3FFF, LIT64(0xA72A51DC7367BEAC)}, + {0x3FFF, LIT64(0xA83A51530956168F)}, + {0x3FFF, LIT64(0xA93A20077539546E)}, + {0x3FFF, LIT64(0xAA9E7245023B2605)}, + {0x3FFF, LIT64(0xAC4C84BA6FE4D58F)}, + {0x3FFF, LIT64(0xADCE4A4A606B9712)}, + {0x3FFF, LIT64(0xAF2A2DCD8D263C9C)}, + {0x3FFF, LIT64(0xB0656F81F22265C7)}, + {0x3FFF, LIT64(0xB18465150F71496A)}, + {0x3FFF, LIT64(0xB28AAA156F9ADA35)}, + {0x3FFF, LIT64(0xB37B44FF3766B895)}, + {0x3FFF, LIT64(0xB458C3DCE9630433)}, + {0x3FFF, LIT64(0xB525529D562246BD)}, + {0x3FFF, LIT64(0xB5E2CCA95F9D88CC)}, + {0x3FFF, LIT64(0xB692CADA7ACA1ADA)}, + {0x3FFF, LIT64(0xB736AEA7A6925838)}, + {0x3FFF, LIT64(0xB7CFAB287E9F7B36)}, + {0x3FFF, LIT64(0xB85ECC66CB219835)}, + {0x3FFF, LIT64(0xB8E4FD5A20A593DA)}, + {0x3FFF, LIT64(0xB99F41F64AFF9BB5)}, + {0x3FFF, LIT64(0xBA7F1E17842BBE7B)}, + {0x3FFF, LIT64(0xBB4712857637E17D)}, + {0x3FFF, LIT64(0xBBFABE8A4788DF6F)}, + {0x3FFF, LIT64(0xBC9D0FAD2B689D79)}, + {0x3FFF, LIT64(0xBD306A39471ECD86)}, + {0x3FFF, LIT64(0xBDB6C731856AF18A)}, + {0x3FFF, LIT64(0xBE31CAC502E80D70)}, + {0x3FFF, LIT64(0xBEA2D55CE33194E2)}, + {0x3FFF, LIT64(0xBF0B10B7C03128F0)}, + {0x3FFF, LIT64(0xBF6B7A18DACB778D)}, + {0x3FFF, LIT64(0xBFC4EA4663FA18F6)}, + {0x3FFF, LIT64(0xC0181BDE8B89A454)}, + {0x3FFF, LIT64(0xC065B066CFBF6439)}, + {0x3FFF, LIT64(0xC0AE345F56340AE6)}, + {0x3FFF, LIT64(0xC0F222919CB9E6A7)} }; static const floatx80 exp_tbl[64] = { - {0x3FFF, LIT64(0x8000000000000000)}, - {0x3FFF, LIT64(0x8164D1F3BC030774)}, - {0x3FFF, LIT64(0x82CD8698AC2BA1D8)}, - {0x3FFF, LIT64(0x843A28C3ACDE4048)}, - {0x3FFF, LIT64(0x85AAC367CC487B14)}, - {0x3FFF, LIT64(0x871F61969E8D1010)}, - {0x3FFF, LIT64(0x88980E8092DA8528)}, - {0x3FFF, LIT64(0x8A14D575496EFD9C)}, - {0x3FFF, LIT64(0x8B95C1E3EA8BD6E8)}, - {0x3FFF, LIT64(0x8D1ADF5B7E5BA9E4)}, - {0x3FFF, LIT64(0x8EA4398B45CD53C0)}, - {0x3FFF, LIT64(0x9031DC431466B1DC)}, - {0x3FFF, LIT64(0x91C3D373AB11C338)}, - {0x3FFF, LIT64(0x935A2B2F13E6E92C)}, - {0x3FFF, LIT64(0x94F4EFA8FEF70960)}, - {0x3FFF, LIT64(0x96942D3720185A00)}, - {0x3FFF, LIT64(0x9837F0518DB8A970)}, - {0x3FFF, LIT64(0x99E0459320B7FA64)}, - {0x3FFF, LIT64(0x9B8D39B9D54E5538)}, - {0x3FFF, LIT64(0x9D3ED9A72CFFB750)}, - {0x3FFF, LIT64(0x9EF5326091A111AC)}, - {0x3FFF, LIT64(0xA0B0510FB9714FC4)}, - {0x3FFF, LIT64(0xA27043030C496818)}, - {0x3FFF, LIT64(0xA43515AE09E680A0)}, - {0x3FFF, LIT64(0xA5FED6A9B15138EC)}, - {0x3FFF, LIT64(0xA7CD93B4E9653568)}, - {0x3FFF, LIT64(0xA9A15AB4EA7C0EF8)}, - {0x3FFF, LIT64(0xAB7A39B5A93ED338)}, - {0x3FFF, LIT64(0xAD583EEA42A14AC8)}, - {0x3FFF, LIT64(0xAF3B78AD690A4374)}, - {0x3FFF, LIT64(0xB123F581D2AC2590)}, - {0x3FFF, LIT64(0xB311C412A9112488)}, - {0x3FFF, LIT64(0xB504F333F9DE6484)}, - {0x3FFF, LIT64(0xB6FD91E328D17790)}, - {0x3FFF, LIT64(0xB8FBAF4762FB9EE8)}, - {0x3FFF, LIT64(0xBAFF5AB2133E45FC)}, - {0x3FFF, LIT64(0xBD08A39F580C36C0)}, - {0x3FFF, LIT64(0xBF1799B67A731084)}, - {0x3FFF, LIT64(0xC12C4CCA66709458)}, - {0x3FFF, LIT64(0xC346CCDA24976408)}, - {0x3FFF, LIT64(0xC5672A115506DADC)}, - {0x3FFF, LIT64(0xC78D74C8ABB9B15C)}, - {0x3FFF, LIT64(0xC9B9BD866E2F27A4)}, - {0x3FFF, LIT64(0xCBEC14FEF2727C5C)}, - {0x3FFF, LIT64(0xCE248C151F8480E4)}, - {0x3FFF, LIT64(0xD06333DAEF2B2594)}, - {0x3FFF, LIT64(0xD2A81D91F12AE45C)}, - {0x3FFF, LIT64(0xD4F35AABCFEDFA20)}, - {0x3FFF, LIT64(0xD744FCCAD69D6AF4)}, - {0x3FFF, LIT64(0xD99D15C278AFD7B4)}, - {0x3FFF, LIT64(0xDBFBB797DAF23754)}, - {0x3FFF, LIT64(0xDE60F4825E0E9124)}, - {0x3FFF, LIT64(0xE0CCDEEC2A94E110)}, - {0x3FFF, LIT64(0xE33F8972BE8A5A50)}, - {0x3FFF, LIT64(0xE5B906E77C8348A8)}, - {0x3FFF, LIT64(0xE8396A503C4BDC68)}, - {0x3FFF, LIT64(0xEAC0C6E7DD243930)}, - {0x3FFF, LIT64(0xED4F301ED9942B84)}, - {0x3FFF, LIT64(0xEFE4B99BDCDAF5CC)}, - {0x3FFF, LIT64(0xF281773C59FFB138)}, - {0x3FFF, LIT64(0xF5257D152486CC2C)}, - {0x3FFF, LIT64(0xF7D0DF730AD13BB8)}, - {0x3FFF, LIT64(0xFA83B2DB722A033C)}, - {0x3FFF, LIT64(0xFD3E0C0CF486C174)} + {0x3FFF, LIT64(0x8000000000000000)}, + {0x3FFF, LIT64(0x8164D1F3BC030774)}, + {0x3FFF, LIT64(0x82CD8698AC2BA1D8)}, + {0x3FFF, LIT64(0x843A28C3ACDE4048)}, + {0x3FFF, LIT64(0x85AAC367CC487B14)}, + {0x3FFF, LIT64(0x871F61969E8D1010)}, + {0x3FFF, LIT64(0x88980E8092DA8528)}, + {0x3FFF, LIT64(0x8A14D575496EFD9C)}, + {0x3FFF, LIT64(0x8B95C1E3EA8BD6E8)}, + {0x3FFF, LIT64(0x8D1ADF5B7E5BA9E4)}, + {0x3FFF, LIT64(0x8EA4398B45CD53C0)}, + {0x3FFF, LIT64(0x9031DC431466B1DC)}, + {0x3FFF, LIT64(0x91C3D373AB11C338)}, + {0x3FFF, LIT64(0x935A2B2F13E6E92C)}, + {0x3FFF, LIT64(0x94F4EFA8FEF70960)}, + {0x3FFF, LIT64(0x96942D3720185A00)}, + {0x3FFF, LIT64(0x9837F0518DB8A970)}, + {0x3FFF, LIT64(0x99E0459320B7FA64)}, + {0x3FFF, LIT64(0x9B8D39B9D54E5538)}, + {0x3FFF, LIT64(0x9D3ED9A72CFFB750)}, + {0x3FFF, LIT64(0x9EF5326091A111AC)}, + {0x3FFF, LIT64(0xA0B0510FB9714FC4)}, + {0x3FFF, LIT64(0xA27043030C496818)}, + {0x3FFF, LIT64(0xA43515AE09E680A0)}, + {0x3FFF, LIT64(0xA5FED6A9B15138EC)}, + {0x3FFF, LIT64(0xA7CD93B4E9653568)}, + {0x3FFF, LIT64(0xA9A15AB4EA7C0EF8)}, + {0x3FFF, LIT64(0xAB7A39B5A93ED338)}, + {0x3FFF, LIT64(0xAD583EEA42A14AC8)}, + {0x3FFF, LIT64(0xAF3B78AD690A4374)}, + {0x3FFF, LIT64(0xB123F581D2AC2590)}, + {0x3FFF, LIT64(0xB311C412A9112488)}, + {0x3FFF, LIT64(0xB504F333F9DE6484)}, + {0x3FFF, LIT64(0xB6FD91E328D17790)}, + {0x3FFF, LIT64(0xB8FBAF4762FB9EE8)}, + {0x3FFF, LIT64(0xBAFF5AB2133E45FC)}, + {0x3FFF, LIT64(0xBD08A39F580C36C0)}, + {0x3FFF, LIT64(0xBF1799B67A731084)}, + {0x3FFF, LIT64(0xC12C4CCA66709458)}, + {0x3FFF, LIT64(0xC346CCDA24976408)}, + {0x3FFF, LIT64(0xC5672A115506DADC)}, + {0x3FFF, LIT64(0xC78D74C8ABB9B15C)}, + {0x3FFF, LIT64(0xC9B9BD866E2F27A4)}, + {0x3FFF, LIT64(0xCBEC14FEF2727C5C)}, + {0x3FFF, LIT64(0xCE248C151F8480E4)}, + {0x3FFF, LIT64(0xD06333DAEF2B2594)}, + {0x3FFF, LIT64(0xD2A81D91F12AE45C)}, + {0x3FFF, LIT64(0xD4F35AABCFEDFA20)}, + {0x3FFF, LIT64(0xD744FCCAD69D6AF4)}, + {0x3FFF, LIT64(0xD99D15C278AFD7B4)}, + {0x3FFF, LIT64(0xDBFBB797DAF23754)}, + {0x3FFF, LIT64(0xDE60F4825E0E9124)}, + {0x3FFF, LIT64(0xE0CCDEEC2A94E110)}, + {0x3FFF, LIT64(0xE33F8972BE8A5A50)}, + {0x3FFF, LIT64(0xE5B906E77C8348A8)}, + {0x3FFF, LIT64(0xE8396A503C4BDC68)}, + {0x3FFF, LIT64(0xEAC0C6E7DD243930)}, + {0x3FFF, LIT64(0xED4F301ED9942B84)}, + {0x3FFF, LIT64(0xEFE4B99BDCDAF5CC)}, + {0x3FFF, LIT64(0xF281773C59FFB138)}, + {0x3FFF, LIT64(0xF5257D152486CC2C)}, + {0x3FFF, LIT64(0xF7D0DF730AD13BB8)}, + {0x3FFF, LIT64(0xFA83B2DB722A033C)}, + {0x3FFF, LIT64(0xFD3E0C0CF486C174)} }; static const float32 exp_tbl2[64] = { - 0x00000000, 0x9F841A9B, 0x9FC1D5B9, 0xA0728369, - 0x1FC5C95C, 0x1EE85C9F, 0x9FA20729, 0xA07BF9AF, - 0xA0020DCF, 0x205A63DA, 0x1EB70051, 0x1F6EB029, - 0xA0781494, 0x9EB319B0, 0x2017457D, 0x1F11D537, - 0x9FB952DD, 0x1FE43087, 0x1FA2A818, 0x1FDE494D, - 0x20504890, 0xA073691C, 0x1F9B7A05, 0xA0797126, - 0xA071A140, 0x204F62DA, 0x1F283C4A, 0x9F9A7FDC, - 0xA05B3FAC, 0x1FDF2610, 0x9F705F90, 0x201F678A, - 0x1F32FB13, 0x20038B30, 0x200DC3CC, 0x9F8B2AE6, - 0xA02BBF70, 0xA00BF518, 0xA041DD41, 0x9FDF137B, - 0x201F1568, 0x1FC13A2E, 0xA03F8F03, 0x1FF4907D, - 0x9E6E53E4, 0x1FD6D45C, 0xA076EDB9, 0x9FA6DE21, - 0x1EE69A2F, 0x207F439F, 0x201EC207, 0x9E8BE175, - 0x20032C4B, 0x2004DFF5, 0x1E72F47A, 0x1F722F22, - 0xA017E945, 0x1F401A5B, 0x9FB9A9E3, 0x20744C05, - 0x1F773A19, 0x1FFE90D5, 0xA041ED22, 0x1F853F3A + 0x00000000, 0x9F841A9B, 0x9FC1D5B9, 0xA0728369, + 0x1FC5C95C, 0x1EE85C9F, 0x9FA20729, 0xA07BF9AF, + 0xA0020DCF, 0x205A63DA, 0x1EB70051, 0x1F6EB029, + 0xA0781494, 0x9EB319B0, 0x2017457D, 0x1F11D537, + 0x9FB952DD, 0x1FE43087, 0x1FA2A818, 0x1FDE494D, + 0x20504890, 0xA073691C, 0x1F9B7A05, 0xA0797126, + 0xA071A140, 0x204F62DA, 0x1F283C4A, 0x9F9A7FDC, + 0xA05B3FAC, 0x1FDF2610, 0x9F705F90, 0x201F678A, + 0x1F32FB13, 0x20038B30, 0x200DC3CC, 0x9F8B2AE6, + 0xA02BBF70, 0xA00BF518, 0xA041DD41, 0x9FDF137B, + 0x201F1568, 0x1FC13A2E, 0xA03F8F03, 0x1FF4907D, + 0x9E6E53E4, 0x1FD6D45C, 0xA076EDB9, 0x9FA6DE21, + 0x1EE69A2F, 0x207F439F, 0x201EC207, 0x9E8BE175, + 0x20032C4B, 0x2004DFF5, 0x1E72F47A, 0x1F722F22, + 0xA017E945, 0x1F401A5B, 0x9FB9A9E3, 0x20744C05, + 0x1F773A19, 0x1FFE90D5, 0xA041ED22, 0x1F853F3A }; static const floatx80 exp2_tbl[64] = { - {0x3FFF, LIT64(0x8000000000000000)}, - {0x3FFF, LIT64(0x8164D1F3BC030773)}, - {0x3FFF, LIT64(0x82CD8698AC2BA1D7)}, - {0x3FFF, LIT64(0x843A28C3ACDE4046)}, - {0x3FFF, LIT64(0x85AAC367CC487B15)}, - {0x3FFF, LIT64(0x871F61969E8D1010)}, - {0x3FFF, LIT64(0x88980E8092DA8527)}, - {0x3FFF, LIT64(0x8A14D575496EFD9A)}, - {0x3FFF, LIT64(0x8B95C1E3EA8BD6E7)}, - {0x3FFF, LIT64(0x8D1ADF5B7E5BA9E6)}, - {0x3FFF, LIT64(0x8EA4398B45CD53C0)}, - {0x3FFF, LIT64(0x9031DC431466B1DC)}, - {0x3FFF, LIT64(0x91C3D373AB11C336)}, - {0x3FFF, LIT64(0x935A2B2F13E6E92C)}, - {0x3FFF, LIT64(0x94F4EFA8FEF70961)}, - {0x3FFF, LIT64(0x96942D3720185A00)}, - {0x3FFF, LIT64(0x9837F0518DB8A96F)}, - {0x3FFF, LIT64(0x99E0459320B7FA65)}, - {0x3FFF, LIT64(0x9B8D39B9D54E5539)}, - {0x3FFF, LIT64(0x9D3ED9A72CFFB751)}, - {0x3FFF, LIT64(0x9EF5326091A111AE)}, - {0x3FFF, LIT64(0xA0B0510FB9714FC2)}, - {0x3FFF, LIT64(0xA27043030C496819)}, - {0x3FFF, LIT64(0xA43515AE09E6809E)}, - {0x3FFF, LIT64(0xA5FED6A9B15138EA)}, - {0x3FFF, LIT64(0xA7CD93B4E965356A)}, - {0x3FFF, LIT64(0xA9A15AB4EA7C0EF8)}, - {0x3FFF, LIT64(0xAB7A39B5A93ED337)}, - {0x3FFF, LIT64(0xAD583EEA42A14AC6)}, - {0x3FFF, LIT64(0xAF3B78AD690A4375)}, - {0x3FFF, LIT64(0xB123F581D2AC2590)}, - {0x3FFF, LIT64(0xB311C412A9112489)}, - {0x3FFF, LIT64(0xB504F333F9DE6484)}, - {0x3FFF, LIT64(0xB6FD91E328D17791)}, - {0x3FFF, LIT64(0xB8FBAF4762FB9EE9)}, - {0x3FFF, LIT64(0xBAFF5AB2133E45FB)}, - {0x3FFF, LIT64(0xBD08A39F580C36BF)}, - {0x3FFF, LIT64(0xBF1799B67A731083)}, - {0x3FFF, LIT64(0xC12C4CCA66709456)}, - {0x3FFF, LIT64(0xC346CCDA24976407)}, - {0x3FFF, LIT64(0xC5672A115506DADD)}, - {0x3FFF, LIT64(0xC78D74C8ABB9B15D)}, - {0x3FFF, LIT64(0xC9B9BD866E2F27A3)}, - {0x3FFF, LIT64(0xCBEC14FEF2727C5D)}, - {0x3FFF, LIT64(0xCE248C151F8480E4)}, - {0x3FFF, LIT64(0xD06333DAEF2B2595)}, - {0x3FFF, LIT64(0xD2A81D91F12AE45A)}, - {0x3FFF, LIT64(0xD4F35AABCFEDFA1F)}, - {0x3FFF, LIT64(0xD744FCCAD69D6AF4)}, - {0x3FFF, LIT64(0xD99D15C278AFD7B6)}, - {0x3FFF, LIT64(0xDBFBB797DAF23755)}, - {0x3FFF, LIT64(0xDE60F4825E0E9124)}, - {0x3FFF, LIT64(0xE0CCDEEC2A94E111)}, - {0x3FFF, LIT64(0xE33F8972BE8A5A51)}, - {0x3FFF, LIT64(0xE5B906E77C8348A8)}, - {0x3FFF, LIT64(0xE8396A503C4BDC68)}, - {0x3FFF, LIT64(0xEAC0C6E7DD24392F)}, - {0x3FFF, LIT64(0xED4F301ED9942B84)}, - {0x3FFF, LIT64(0xEFE4B99BDCDAF5CB)}, - {0x3FFF, LIT64(0xF281773C59FFB13A)}, - {0x3FFF, LIT64(0xF5257D152486CC2C)}, - {0x3FFF, LIT64(0xF7D0DF730AD13BB9)}, - {0x3FFF, LIT64(0xFA83B2DB722A033A)}, - {0x3FFF, LIT64(0xFD3E0C0CF486C175)} + {0x3FFF, LIT64(0x8000000000000000)}, + {0x3FFF, LIT64(0x8164D1F3BC030773)}, + {0x3FFF, LIT64(0x82CD8698AC2BA1D7)}, + {0x3FFF, LIT64(0x843A28C3ACDE4046)}, + {0x3FFF, LIT64(0x85AAC367CC487B15)}, + {0x3FFF, LIT64(0x871F61969E8D1010)}, + {0x3FFF, LIT64(0x88980E8092DA8527)}, + {0x3FFF, LIT64(0x8A14D575496EFD9A)}, + {0x3FFF, LIT64(0x8B95C1E3EA8BD6E7)}, + {0x3FFF, LIT64(0x8D1ADF5B7E5BA9E6)}, + {0x3FFF, LIT64(0x8EA4398B45CD53C0)}, + {0x3FFF, LIT64(0x9031DC431466B1DC)}, + {0x3FFF, LIT64(0x91C3D373AB11C336)}, + {0x3FFF, LIT64(0x935A2B2F13E6E92C)}, + {0x3FFF, LIT64(0x94F4EFA8FEF70961)}, + {0x3FFF, LIT64(0x96942D3720185A00)}, + {0x3FFF, LIT64(0x9837F0518DB8A96F)}, + {0x3FFF, LIT64(0x99E0459320B7FA65)}, + {0x3FFF, LIT64(0x9B8D39B9D54E5539)}, + {0x3FFF, LIT64(0x9D3ED9A72CFFB751)}, + {0x3FFF, LIT64(0x9EF5326091A111AE)}, + {0x3FFF, LIT64(0xA0B0510FB9714FC2)}, + {0x3FFF, LIT64(0xA27043030C496819)}, + {0x3FFF, LIT64(0xA43515AE09E6809E)}, + {0x3FFF, LIT64(0xA5FED6A9B15138EA)}, + {0x3FFF, LIT64(0xA7CD93B4E965356A)}, + {0x3FFF, LIT64(0xA9A15AB4EA7C0EF8)}, + {0x3FFF, LIT64(0xAB7A39B5A93ED337)}, + {0x3FFF, LIT64(0xAD583EEA42A14AC6)}, + {0x3FFF, LIT64(0xAF3B78AD690A4375)}, + {0x3FFF, LIT64(0xB123F581D2AC2590)}, + {0x3FFF, LIT64(0xB311C412A9112489)}, + {0x3FFF, LIT64(0xB504F333F9DE6484)}, + {0x3FFF, LIT64(0xB6FD91E328D17791)}, + {0x3FFF, LIT64(0xB8FBAF4762FB9EE9)}, + {0x3FFF, LIT64(0xBAFF5AB2133E45FB)}, + {0x3FFF, LIT64(0xBD08A39F580C36BF)}, + {0x3FFF, LIT64(0xBF1799B67A731083)}, + {0x3FFF, LIT64(0xC12C4CCA66709456)}, + {0x3FFF, LIT64(0xC346CCDA24976407)}, + {0x3FFF, LIT64(0xC5672A115506DADD)}, + {0x3FFF, LIT64(0xC78D74C8ABB9B15D)}, + {0x3FFF, LIT64(0xC9B9BD866E2F27A3)}, + {0x3FFF, LIT64(0xCBEC14FEF2727C5D)}, + {0x3FFF, LIT64(0xCE248C151F8480E4)}, + {0x3FFF, LIT64(0xD06333DAEF2B2595)}, + {0x3FFF, LIT64(0xD2A81D91F12AE45A)}, + {0x3FFF, LIT64(0xD4F35AABCFEDFA1F)}, + {0x3FFF, LIT64(0xD744FCCAD69D6AF4)}, + {0x3FFF, LIT64(0xD99D15C278AFD7B6)}, + {0x3FFF, LIT64(0xDBFBB797DAF23755)}, + {0x3FFF, LIT64(0xDE60F4825E0E9124)}, + {0x3FFF, LIT64(0xE0CCDEEC2A94E111)}, + {0x3FFF, LIT64(0xE33F8972BE8A5A51)}, + {0x3FFF, LIT64(0xE5B906E77C8348A8)}, + {0x3FFF, LIT64(0xE8396A503C4BDC68)}, + {0x3FFF, LIT64(0xEAC0C6E7DD24392F)}, + {0x3FFF, LIT64(0xED4F301ED9942B84)}, + {0x3FFF, LIT64(0xEFE4B99BDCDAF5CB)}, + {0x3FFF, LIT64(0xF281773C59FFB13A)}, + {0x3FFF, LIT64(0xF5257D152486CC2C)}, + {0x3FFF, LIT64(0xF7D0DF730AD13BB9)}, + {0x3FFF, LIT64(0xFA83B2DB722A033A)}, + {0x3FFF, LIT64(0xFD3E0C0CF486C175)} }; static const float32 exp2_tbl2[64] = { - 0x3F738000, 0x3FBEF7CA, 0x3FBDF8A9, 0x3FBCD7C9, - 0xBFBDE8DA, 0x3FBDE85C, 0x3FBEBBF1, 0x3FBB80CA, - 0xBFBA8373, 0xBFBE9670, 0x3FBDB700, 0x3FBEEEB0, - 0x3FBBFD6D, 0xBFBDB319, 0x3FBDBA2B, 0x3FBE91D5, - 0x3FBE8D5A, 0xBFBCDE7B, 0xBFBEBAAF, 0xBFBD86DA, - 0xBFBEBEDD, 0x3FBCC96E, 0xBFBEC90B, 0x3FBBD1DB, - 0x3FBCE5EB, 0xBFBEC274, 0x3FBEA83C, 0x3FBECB00, - 0x3FBE9301, 0xBFBD8367, 0xBFBEF05F, 0x3FBDFB3C, - 0x3FBEB2FB, 0x3FBAE2CB, 0x3FBCDC3C, 0x3FBEE9AA, - 0xBFBEAEFD, 0xBFBCBF51, 0x3FBEF88A, 0x3FBD83B2, - 0x3FBDF8AB, 0xBFBDFB17, 0xBFBEFE3C, 0xBFBBB6F8, - 0xBFBCEE53, 0xBFBDA4AE, 0x3FBC9124, 0x3FBEB243, - 0x3FBDE69A, 0xBFB8BC61, 0x3FBDF610, 0xBFBD8BE1, - 0x3FBACB12, 0x3FBB9BFE, 0x3FBCF2F4, 0x3FBEF22F, - 0xBFBDBF4A, 0x3FBEC01A, 0x3FBE8CAC, 0xBFBCBB3F, - 0x3FBEF73A, 0xBFB8B795, 0x3FBEF84B, 0xBFBEF581 + 0x3F738000, 0x3FBEF7CA, 0x3FBDF8A9, 0x3FBCD7C9, + 0xBFBDE8DA, 0x3FBDE85C, 0x3FBEBBF1, 0x3FBB80CA, + 0xBFBA8373, 0xBFBE9670, 0x3FBDB700, 0x3FBEEEB0, + 0x3FBBFD6D, 0xBFBDB319, 0x3FBDBA2B, 0x3FBE91D5, + 0x3FBE8D5A, 0xBFBCDE7B, 0xBFBEBAAF, 0xBFBD86DA, + 0xBFBEBEDD, 0x3FBCC96E, 0xBFBEC90B, 0x3FBBD1DB, + 0x3FBCE5EB, 0xBFBEC274, 0x3FBEA83C, 0x3FBECB00, + 0x3FBE9301, 0xBFBD8367, 0xBFBEF05F, 0x3FBDFB3C, + 0x3FBEB2FB, 0x3FBAE2CB, 0x3FBCDC3C, 0x3FBEE9AA, + 0xBFBEAEFD, 0xBFBCBF51, 0x3FBEF88A, 0x3FBD83B2, + 0x3FBDF8AB, 0xBFBDFB17, 0xBFBEFE3C, 0xBFBBB6F8, + 0xBFBCEE53, 0xBFBDA4AE, 0x3FBC9124, 0x3FBEB243, + 0x3FBDE69A, 0xBFB8BC61, 0x3FBDF610, 0xBFBD8BE1, + 0x3FBACB12, 0x3FBB9BFE, 0x3FBCF2F4, 0x3FBEF22F, + 0xBFBDBF4A, 0x3FBEC01A, 0x3FBE8CAC, 0xBFBCBB3F, + 0x3FBEF73A, 0xBFB8B795, 0x3FBEF84B, 0xBFBEF581 }; static const floatx80 log_tbl[128] = { - {0x3FFE, LIT64(0xFE03F80FE03F80FE)}, - {0x3FF7, LIT64(0xFF015358833C47E2)}, - {0x3FFE, LIT64(0xFA232CF252138AC0)}, - {0x3FF9, LIT64(0xBDC8D83EAD88D549)}, - {0x3FFE, LIT64(0xF6603D980F6603DA)}, - {0x3FFA, LIT64(0x9CF43DCFF5EAFD48)}, - {0x3FFE, LIT64(0xF2B9D6480F2B9D65)}, - {0x3FFA, LIT64(0xDA16EB88CB8DF614)}, - {0x3FFE, LIT64(0xEF2EB71FC4345238)}, - {0x3FFB, LIT64(0x8B29B7751BD70743)}, - {0x3FFE, LIT64(0xEBBDB2A5C1619C8C)}, - {0x3FFB, LIT64(0xA8D839F830C1FB49)}, - {0x3FFE, LIT64(0xE865AC7B7603A197)}, - {0x3FFB, LIT64(0xC61A2EB18CD907AD)}, - {0x3FFE, LIT64(0xE525982AF70C880E)}, - {0x3FFB, LIT64(0xE2F2A47ADE3A18AF)}, - {0x3FFE, LIT64(0xE1FC780E1FC780E2)}, - {0x3FFB, LIT64(0xFF64898EDF55D551)}, - {0x3FFE, LIT64(0xDEE95C4CA037BA57)}, - {0x3FFC, LIT64(0x8DB956A97B3D0148)}, - {0x3FFE, LIT64(0xDBEB61EED19C5958)}, - {0x3FFC, LIT64(0x9B8FE100F47BA1DE)}, - {0x3FFE, LIT64(0xD901B2036406C80E)}, - {0x3FFC, LIT64(0xA9372F1D0DA1BD17)}, - {0x3FFE, LIT64(0xD62B80D62B80D62C)}, - {0x3FFC, LIT64(0xB6B07F38CE90E46B)}, - {0x3FFE, LIT64(0xD3680D3680D3680D)}, - {0x3FFC, LIT64(0xC3FD032906488481)}, - {0x3FFE, LIT64(0xD0B69FCBD2580D0B)}, - {0x3FFC, LIT64(0xD11DE0FF15AB18CA)}, - {0x3FFE, LIT64(0xCE168A7725080CE1)}, - {0x3FFC, LIT64(0xDE1433A16C66B150)}, - {0x3FFE, LIT64(0xCB8727C065C393E0)}, - {0x3FFC, LIT64(0xEAE10B5A7DDC8ADD)}, - {0x3FFE, LIT64(0xC907DA4E871146AD)}, - {0x3FFC, LIT64(0xF7856E5EE2C9B291)}, - {0x3FFE, LIT64(0xC6980C6980C6980C)}, - {0x3FFD, LIT64(0x82012CA5A68206D7)}, - {0x3FFE, LIT64(0xC4372F855D824CA6)}, - {0x3FFD, LIT64(0x882C5FCD7256A8C5)}, - {0x3FFE, LIT64(0xC1E4BBD595F6E947)}, - {0x3FFD, LIT64(0x8E44C60B4CCFD7DE)}, - {0x3FFE, LIT64(0xBFA02FE80BFA02FF)}, - {0x3FFD, LIT64(0x944AD09EF4351AF6)}, - {0x3FFE, LIT64(0xBD69104707661AA3)}, - {0x3FFD, LIT64(0x9A3EECD4C3EAA6B2)}, - {0x3FFE, LIT64(0xBB3EE721A54D880C)}, - {0x3FFD, LIT64(0xA0218434353F1DE8)}, - {0x3FFE, LIT64(0xB92143FA36F5E02E)}, - {0x3FFD, LIT64(0xA5F2FCABBBC506DA)}, - {0x3FFE, LIT64(0xB70FBB5A19BE3659)}, - {0x3FFD, LIT64(0xABB3B8BA2AD362A5)}, - {0x3FFE, LIT64(0xB509E68A9B94821F)}, - {0x3FFD, LIT64(0xB1641795CE3CA97B)}, - {0x3FFE, LIT64(0xB30F63528917C80B)}, - {0x3FFD, LIT64(0xB70475515D0F1C61)}, - {0x3FFE, LIT64(0xB11FD3B80B11FD3C)}, - {0x3FFD, LIT64(0xBC952AFEEA3D13E1)}, - {0x3FFE, LIT64(0xAF3ADDC680AF3ADE)}, - {0x3FFD, LIT64(0xC2168ED0F458BA4A)}, - {0x3FFE, LIT64(0xAD602B580AD602B6)}, - {0x3FFD, LIT64(0xC788F439B3163BF1)}, - {0x3FFE, LIT64(0xAB8F69E28359CD11)}, - {0x3FFD, LIT64(0xCCECAC08BF04565D)}, - {0x3FFE, LIT64(0xA9C84A47A07F5638)}, - {0x3FFD, LIT64(0xD24204872DD85160)}, - {0x3FFE, LIT64(0xA80A80A80A80A80B)}, - {0x3FFD, LIT64(0xD78949923BC3588A)}, - {0x3FFE, LIT64(0xA655C4392D7B73A8)}, - {0x3FFD, LIT64(0xDCC2C4B49887DACC)}, - {0x3FFE, LIT64(0xA4A9CF1D96833751)}, - {0x3FFD, LIT64(0xE1EEBD3E6D6A6B9E)}, - {0x3FFE, LIT64(0xA3065E3FAE7CD0E0)}, - {0x3FFD, LIT64(0xE70D785C2F9F5BDC)}, - {0x3FFE, LIT64(0xA16B312EA8FC377D)}, - {0x3FFD, LIT64(0xEC1F392C5179F283)}, - {0x3FFE, LIT64(0x9FD809FD809FD80A)}, - {0x3FFD, LIT64(0xF12440D3E36130E6)}, - {0x3FFE, LIT64(0x9E4CAD23DD5F3A20)}, - {0x3FFD, LIT64(0xF61CCE92346600BB)}, - {0x3FFE, LIT64(0x9CC8E160C3FB19B9)}, - {0x3FFD, LIT64(0xFB091FD38145630A)}, - {0x3FFE, LIT64(0x9B4C6F9EF03A3CAA)}, - {0x3FFD, LIT64(0xFFE97042BFA4C2AD)}, - {0x3FFE, LIT64(0x99D722DABDE58F06)}, - {0x3FFE, LIT64(0x825EFCED49369330)}, - {0x3FFE, LIT64(0x9868C809868C8098)}, - {0x3FFE, LIT64(0x84C37A7AB9A905C9)}, - {0x3FFE, LIT64(0x97012E025C04B809)}, - {0x3FFE, LIT64(0x87224C2E8E645FB7)}, - {0x3FFE, LIT64(0x95A02568095A0257)}, - {0x3FFE, LIT64(0x897B8CAC9F7DE298)}, - {0x3FFE, LIT64(0x9445809445809446)}, - {0x3FFE, LIT64(0x8BCF55DEC4CD05FE)}, - {0x3FFE, LIT64(0x92F113840497889C)}, - {0x3FFE, LIT64(0x8E1DC0FB89E125E5)}, - {0x3FFE, LIT64(0x91A2B3C4D5E6F809)}, - {0x3FFE, LIT64(0x9066E68C955B6C9B)}, - {0x3FFE, LIT64(0x905A38633E06C43B)}, - {0x3FFE, LIT64(0x92AADE74C7BE59E0)}, - {0x3FFE, LIT64(0x8F1779D9FDC3A219)}, - {0x3FFE, LIT64(0x94E9BFF615845643)}, - {0x3FFE, LIT64(0x8DDA520237694809)}, - {0x3FFE, LIT64(0x9723A1B720134203)}, - {0x3FFE, LIT64(0x8CA29C046514E023)}, - {0x3FFE, LIT64(0x995899C890EB8990)}, - {0x3FFE, LIT64(0x8B70344A139BC75A)}, - {0x3FFE, LIT64(0x9B88BDAA3A3DAE2F)}, - {0x3FFE, LIT64(0x8A42F8705669DB46)}, - {0x3FFE, LIT64(0x9DB4224FFFE1157C)}, - {0x3FFE, LIT64(0x891AC73AE9819B50)}, - {0x3FFE, LIT64(0x9FDADC268B7A12DA)}, - {0x3FFE, LIT64(0x87F78087F78087F8)}, - {0x3FFE, LIT64(0xA1FCFF17CE733BD4)}, - {0x3FFE, LIT64(0x86D905447A34ACC6)}, - {0x3FFE, LIT64(0xA41A9E8F5446FB9F)}, - {0x3FFE, LIT64(0x85BF37612CEE3C9B)}, - {0x3FFE, LIT64(0xA633CD7E6771CD8B)}, - {0x3FFE, LIT64(0x84A9F9C8084A9F9D)}, - {0x3FFE, LIT64(0xA8489E600B435A5E)}, - {0x3FFE, LIT64(0x839930523FBE3368)}, - {0x3FFE, LIT64(0xAA59233CCCA4BD49)}, - {0x3FFE, LIT64(0x828CBFBEB9A020A3)}, - {0x3FFE, LIT64(0xAC656DAE6BCC4985)}, - {0x3FFE, LIT64(0x81848DA8FAF0D277)}, - {0x3FFE, LIT64(0xAE6D8EE360BB2468)}, - {0x3FFE, LIT64(0x8080808080808081)}, - {0x3FFE, LIT64(0xB07197A23C46C654)} + {0x3FFE, LIT64(0xFE03F80FE03F80FE)}, + {0x3FF7, LIT64(0xFF015358833C47E2)}, + {0x3FFE, LIT64(0xFA232CF252138AC0)}, + {0x3FF9, LIT64(0xBDC8D83EAD88D549)}, + {0x3FFE, LIT64(0xF6603D980F6603DA)}, + {0x3FFA, LIT64(0x9CF43DCFF5EAFD48)}, + {0x3FFE, LIT64(0xF2B9D6480F2B9D65)}, + {0x3FFA, LIT64(0xDA16EB88CB8DF614)}, + {0x3FFE, LIT64(0xEF2EB71FC4345238)}, + {0x3FFB, LIT64(0x8B29B7751BD70743)}, + {0x3FFE, LIT64(0xEBBDB2A5C1619C8C)}, + {0x3FFB, LIT64(0xA8D839F830C1FB49)}, + {0x3FFE, LIT64(0xE865AC7B7603A197)}, + {0x3FFB, LIT64(0xC61A2EB18CD907AD)}, + {0x3FFE, LIT64(0xE525982AF70C880E)}, + {0x3FFB, LIT64(0xE2F2A47ADE3A18AF)}, + {0x3FFE, LIT64(0xE1FC780E1FC780E2)}, + {0x3FFB, LIT64(0xFF64898EDF55D551)}, + {0x3FFE, LIT64(0xDEE95C4CA037BA57)}, + {0x3FFC, LIT64(0x8DB956A97B3D0148)}, + {0x3FFE, LIT64(0xDBEB61EED19C5958)}, + {0x3FFC, LIT64(0x9B8FE100F47BA1DE)}, + {0x3FFE, LIT64(0xD901B2036406C80E)}, + {0x3FFC, LIT64(0xA9372F1D0DA1BD17)}, + {0x3FFE, LIT64(0xD62B80D62B80D62C)}, + {0x3FFC, LIT64(0xB6B07F38CE90E46B)}, + {0x3FFE, LIT64(0xD3680D3680D3680D)}, + {0x3FFC, LIT64(0xC3FD032906488481)}, + {0x3FFE, LIT64(0xD0B69FCBD2580D0B)}, + {0x3FFC, LIT64(0xD11DE0FF15AB18CA)}, + {0x3FFE, LIT64(0xCE168A7725080CE1)}, + {0x3FFC, LIT64(0xDE1433A16C66B150)}, + {0x3FFE, LIT64(0xCB8727C065C393E0)}, + {0x3FFC, LIT64(0xEAE10B5A7DDC8ADD)}, + {0x3FFE, LIT64(0xC907DA4E871146AD)}, + {0x3FFC, LIT64(0xF7856E5EE2C9B291)}, + {0x3FFE, LIT64(0xC6980C6980C6980C)}, + {0x3FFD, LIT64(0x82012CA5A68206D7)}, + {0x3FFE, LIT64(0xC4372F855D824CA6)}, + {0x3FFD, LIT64(0x882C5FCD7256A8C5)}, + {0x3FFE, LIT64(0xC1E4BBD595F6E947)}, + {0x3FFD, LIT64(0x8E44C60B4CCFD7DE)}, + {0x3FFE, LIT64(0xBFA02FE80BFA02FF)}, + {0x3FFD, LIT64(0x944AD09EF4351AF6)}, + {0x3FFE, LIT64(0xBD69104707661AA3)}, + {0x3FFD, LIT64(0x9A3EECD4C3EAA6B2)}, + {0x3FFE, LIT64(0xBB3EE721A54D880C)}, + {0x3FFD, LIT64(0xA0218434353F1DE8)}, + {0x3FFE, LIT64(0xB92143FA36F5E02E)}, + {0x3FFD, LIT64(0xA5F2FCABBBC506DA)}, + {0x3FFE, LIT64(0xB70FBB5A19BE3659)}, + {0x3FFD, LIT64(0xABB3B8BA2AD362A5)}, + {0x3FFE, LIT64(0xB509E68A9B94821F)}, + {0x3FFD, LIT64(0xB1641795CE3CA97B)}, + {0x3FFE, LIT64(0xB30F63528917C80B)}, + {0x3FFD, LIT64(0xB70475515D0F1C61)}, + {0x3FFE, LIT64(0xB11FD3B80B11FD3C)}, + {0x3FFD, LIT64(0xBC952AFEEA3D13E1)}, + {0x3FFE, LIT64(0xAF3ADDC680AF3ADE)}, + {0x3FFD, LIT64(0xC2168ED0F458BA4A)}, + {0x3FFE, LIT64(0xAD602B580AD602B6)}, + {0x3FFD, LIT64(0xC788F439B3163BF1)}, + {0x3FFE, LIT64(0xAB8F69E28359CD11)}, + {0x3FFD, LIT64(0xCCECAC08BF04565D)}, + {0x3FFE, LIT64(0xA9C84A47A07F5638)}, + {0x3FFD, LIT64(0xD24204872DD85160)}, + {0x3FFE, LIT64(0xA80A80A80A80A80B)}, + {0x3FFD, LIT64(0xD78949923BC3588A)}, + {0x3FFE, LIT64(0xA655C4392D7B73A8)}, + {0x3FFD, LIT64(0xDCC2C4B49887DACC)}, + {0x3FFE, LIT64(0xA4A9CF1D96833751)}, + {0x3FFD, LIT64(0xE1EEBD3E6D6A6B9E)}, + {0x3FFE, LIT64(0xA3065E3FAE7CD0E0)}, + {0x3FFD, LIT64(0xE70D785C2F9F5BDC)}, + {0x3FFE, LIT64(0xA16B312EA8FC377D)}, + {0x3FFD, LIT64(0xEC1F392C5179F283)}, + {0x3FFE, LIT64(0x9FD809FD809FD80A)}, + {0x3FFD, LIT64(0xF12440D3E36130E6)}, + {0x3FFE, LIT64(0x9E4CAD23DD5F3A20)}, + {0x3FFD, LIT64(0xF61CCE92346600BB)}, + {0x3FFE, LIT64(0x9CC8E160C3FB19B9)}, + {0x3FFD, LIT64(0xFB091FD38145630A)}, + {0x3FFE, LIT64(0x9B4C6F9EF03A3CAA)}, + {0x3FFD, LIT64(0xFFE97042BFA4C2AD)}, + {0x3FFE, LIT64(0x99D722DABDE58F06)}, + {0x3FFE, LIT64(0x825EFCED49369330)}, + {0x3FFE, LIT64(0x9868C809868C8098)}, + {0x3FFE, LIT64(0x84C37A7AB9A905C9)}, + {0x3FFE, LIT64(0x97012E025C04B809)}, + {0x3FFE, LIT64(0x87224C2E8E645FB7)}, + {0x3FFE, LIT64(0x95A02568095A0257)}, + {0x3FFE, LIT64(0x897B8CAC9F7DE298)}, + {0x3FFE, LIT64(0x9445809445809446)}, + {0x3FFE, LIT64(0x8BCF55DEC4CD05FE)}, + {0x3FFE, LIT64(0x92F113840497889C)}, + {0x3FFE, LIT64(0x8E1DC0FB89E125E5)}, + {0x3FFE, LIT64(0x91A2B3C4D5E6F809)}, + {0x3FFE, LIT64(0x9066E68C955B6C9B)}, + {0x3FFE, LIT64(0x905A38633E06C43B)}, + {0x3FFE, LIT64(0x92AADE74C7BE59E0)}, + {0x3FFE, LIT64(0x8F1779D9FDC3A219)}, + {0x3FFE, LIT64(0x94E9BFF615845643)}, + {0x3FFE, LIT64(0x8DDA520237694809)}, + {0x3FFE, LIT64(0x9723A1B720134203)}, + {0x3FFE, LIT64(0x8CA29C046514E023)}, + {0x3FFE, LIT64(0x995899C890EB8990)}, + {0x3FFE, LIT64(0x8B70344A139BC75A)}, + {0x3FFE, LIT64(0x9B88BDAA3A3DAE2F)}, + {0x3FFE, LIT64(0x8A42F8705669DB46)}, + {0x3FFE, LIT64(0x9DB4224FFFE1157C)}, + {0x3FFE, LIT64(0x891AC73AE9819B50)}, + {0x3FFE, LIT64(0x9FDADC268B7A12DA)}, + {0x3FFE, LIT64(0x87F78087F78087F8)}, + {0x3FFE, LIT64(0xA1FCFF17CE733BD4)}, + {0x3FFE, LIT64(0x86D905447A34ACC6)}, + {0x3FFE, LIT64(0xA41A9E8F5446FB9F)}, + {0x3FFE, LIT64(0x85BF37612CEE3C9B)}, + {0x3FFE, LIT64(0xA633CD7E6771CD8B)}, + {0x3FFE, LIT64(0x84A9F9C8084A9F9D)}, + {0x3FFE, LIT64(0xA8489E600B435A5E)}, + {0x3FFE, LIT64(0x839930523FBE3368)}, + {0x3FFE, LIT64(0xAA59233CCCA4BD49)}, + {0x3FFE, LIT64(0x828CBFBEB9A020A3)}, + {0x3FFE, LIT64(0xAC656DAE6BCC4985)}, + {0x3FFE, LIT64(0x81848DA8FAF0D277)}, + {0x3FFE, LIT64(0xAE6D8EE360BB2468)}, + {0x3FFE, LIT64(0x8080808080808081)}, + {0x3FFE, LIT64(0xB07197A23C46C654)} }; static const floatx80 pi_tbl[65] = { - {0xC004, LIT64(0xC90FDAA22168C235)}, - {0xC004, LIT64(0xC2C75BCD105D7C23)}, - {0xC004, LIT64(0xBC7EDCF7FF523611)}, - {0xC004, LIT64(0xB6365E22EE46F000)}, - {0xC004, LIT64(0xAFEDDF4DDD3BA9EE)}, - {0xC004, LIT64(0xA9A56078CC3063DD)}, - {0xC004, LIT64(0xA35CE1A3BB251DCB)}, - {0xC004, LIT64(0x9D1462CEAA19D7B9)}, - {0xC004, LIT64(0x96CBE3F9990E91A8)}, - {0xC004, LIT64(0x9083652488034B96)}, - {0xC004, LIT64(0x8A3AE64F76F80584)}, - {0xC004, LIT64(0x83F2677A65ECBF73)}, - {0xC003, LIT64(0xFB53D14AA9C2F2C2)}, - {0xC003, LIT64(0xEEC2D3A087AC669F)}, - {0xC003, LIT64(0xE231D5F66595DA7B)}, - {0xC003, LIT64(0xD5A0D84C437F4E58)}, - {0xC003, LIT64(0xC90FDAA22168C235)}, - {0xC003, LIT64(0xBC7EDCF7FF523611)}, - {0xC003, LIT64(0xAFEDDF4DDD3BA9EE)}, - {0xC003, LIT64(0xA35CE1A3BB251DCB)}, - {0xC003, LIT64(0x96CBE3F9990E91A8)}, - {0xC003, LIT64(0x8A3AE64F76F80584)}, - {0xC002, LIT64(0xFB53D14AA9C2F2C2)}, - {0xC002, LIT64(0xE231D5F66595DA7B)}, - {0xC002, LIT64(0xC90FDAA22168C235)}, - {0xC002, LIT64(0xAFEDDF4DDD3BA9EE)}, - {0xC002, LIT64(0x96CBE3F9990E91A8)}, - {0xC001, LIT64(0xFB53D14AA9C2F2C2)}, - {0xC001, LIT64(0xC90FDAA22168C235)}, - {0xC001, LIT64(0x96CBE3F9990E91A8)}, - {0xC000, LIT64(0xC90FDAA22168C235)}, - {0xBFFF, LIT64(0xC90FDAA22168C235)}, - {0x0000, LIT64(0x0000000000000000)}, - {0x3FFF, LIT64(0xC90FDAA22168C235)}, - {0x4000, LIT64(0xC90FDAA22168C235)}, - {0x4001, LIT64(0x96CBE3F9990E91A8)}, - {0x4001, LIT64(0xC90FDAA22168C235)}, - {0x4001, LIT64(0xFB53D14AA9C2F2C2)}, - {0x4002, LIT64(0x96CBE3F9990E91A8)}, - {0x4002, LIT64(0xAFEDDF4DDD3BA9EE)}, - {0x4002, LIT64(0xC90FDAA22168C235)}, - {0x4002, LIT64(0xE231D5F66595DA7B)}, - {0x4002, LIT64(0xFB53D14AA9C2F2C2)}, - {0x4003, LIT64(0x8A3AE64F76F80584)}, - {0x4003, LIT64(0x96CBE3F9990E91A8)}, - {0x4003, LIT64(0xA35CE1A3BB251DCB)}, - {0x4003, LIT64(0xAFEDDF4DDD3BA9EE)}, - {0x4003, LIT64(0xBC7EDCF7FF523611)}, - {0x4003, LIT64(0xC90FDAA22168C235)}, - {0x4003, LIT64(0xD5A0D84C437F4E58)}, - {0x4003, LIT64(0xE231D5F66595DA7B)}, - {0x4003, LIT64(0xEEC2D3A087AC669F)}, - {0x4003, LIT64(0xFB53D14AA9C2F2C2)}, - {0x4004, LIT64(0x83F2677A65ECBF73)}, - {0x4004, LIT64(0x8A3AE64F76F80584)}, - {0x4004, LIT64(0x9083652488034B96)}, - {0x4004, LIT64(0x96CBE3F9990E91A8)}, - {0x4004, LIT64(0x9D1462CEAA19D7B9)}, - {0x4004, LIT64(0xA35CE1A3BB251DCB)}, - {0x4004, LIT64(0xA9A56078CC3063DD)}, - {0x4004, LIT64(0xAFEDDF4DDD3BA9EE)}, - {0x4004, LIT64(0xB6365E22EE46F000)}, - {0x4004, LIT64(0xBC7EDCF7FF523611)}, - {0x4004, LIT64(0xC2C75BCD105D7C23)}, - {0x4004, LIT64(0xC90FDAA22168C235)} + {0xC004, LIT64(0xC90FDAA22168C235)}, + {0xC004, LIT64(0xC2C75BCD105D7C23)}, + {0xC004, LIT64(0xBC7EDCF7FF523611)}, + {0xC004, LIT64(0xB6365E22EE46F000)}, + {0xC004, LIT64(0xAFEDDF4DDD3BA9EE)}, + {0xC004, LIT64(0xA9A56078CC3063DD)}, + {0xC004, LIT64(0xA35CE1A3BB251DCB)}, + {0xC004, LIT64(0x9D1462CEAA19D7B9)}, + {0xC004, LIT64(0x96CBE3F9990E91A8)}, + {0xC004, LIT64(0x9083652488034B96)}, + {0xC004, LIT64(0x8A3AE64F76F80584)}, + {0xC004, LIT64(0x83F2677A65ECBF73)}, + {0xC003, LIT64(0xFB53D14AA9C2F2C2)}, + {0xC003, LIT64(0xEEC2D3A087AC669F)}, + {0xC003, LIT64(0xE231D5F66595DA7B)}, + {0xC003, LIT64(0xD5A0D84C437F4E58)}, + {0xC003, LIT64(0xC90FDAA22168C235)}, + {0xC003, LIT64(0xBC7EDCF7FF523611)}, + {0xC003, LIT64(0xAFEDDF4DDD3BA9EE)}, + {0xC003, LIT64(0xA35CE1A3BB251DCB)}, + {0xC003, LIT64(0x96CBE3F9990E91A8)}, + {0xC003, LIT64(0x8A3AE64F76F80584)}, + {0xC002, LIT64(0xFB53D14AA9C2F2C2)}, + {0xC002, LIT64(0xE231D5F66595DA7B)}, + {0xC002, LIT64(0xC90FDAA22168C235)}, + {0xC002, LIT64(0xAFEDDF4DDD3BA9EE)}, + {0xC002, LIT64(0x96CBE3F9990E91A8)}, + {0xC001, LIT64(0xFB53D14AA9C2F2C2)}, + {0xC001, LIT64(0xC90FDAA22168C235)}, + {0xC001, LIT64(0x96CBE3F9990E91A8)}, + {0xC000, LIT64(0xC90FDAA22168C235)}, + {0xBFFF, LIT64(0xC90FDAA22168C235)}, + {0x0000, LIT64(0x0000000000000000)}, + {0x3FFF, LIT64(0xC90FDAA22168C235)}, + {0x4000, LIT64(0xC90FDAA22168C235)}, + {0x4001, LIT64(0x96CBE3F9990E91A8)}, + {0x4001, LIT64(0xC90FDAA22168C235)}, + {0x4001, LIT64(0xFB53D14AA9C2F2C2)}, + {0x4002, LIT64(0x96CBE3F9990E91A8)}, + {0x4002, LIT64(0xAFEDDF4DDD3BA9EE)}, + {0x4002, LIT64(0xC90FDAA22168C235)}, + {0x4002, LIT64(0xE231D5F66595DA7B)}, + {0x4002, LIT64(0xFB53D14AA9C2F2C2)}, + {0x4003, LIT64(0x8A3AE64F76F80584)}, + {0x4003, LIT64(0x96CBE3F9990E91A8)}, + {0x4003, LIT64(0xA35CE1A3BB251DCB)}, + {0x4003, LIT64(0xAFEDDF4DDD3BA9EE)}, + {0x4003, LIT64(0xBC7EDCF7FF523611)}, + {0x4003, LIT64(0xC90FDAA22168C235)}, + {0x4003, LIT64(0xD5A0D84C437F4E58)}, + {0x4003, LIT64(0xE231D5F66595DA7B)}, + {0x4003, LIT64(0xEEC2D3A087AC669F)}, + {0x4003, LIT64(0xFB53D14AA9C2F2C2)}, + {0x4004, LIT64(0x83F2677A65ECBF73)}, + {0x4004, LIT64(0x8A3AE64F76F80584)}, + {0x4004, LIT64(0x9083652488034B96)}, + {0x4004, LIT64(0x96CBE3F9990E91A8)}, + {0x4004, LIT64(0x9D1462CEAA19D7B9)}, + {0x4004, LIT64(0xA35CE1A3BB251DCB)}, + {0x4004, LIT64(0xA9A56078CC3063DD)}, + {0x4004, LIT64(0xAFEDDF4DDD3BA9EE)}, + {0x4004, LIT64(0xB6365E22EE46F000)}, + {0x4004, LIT64(0xBC7EDCF7FF523611)}, + {0x4004, LIT64(0xC2C75BCD105D7C23)}, + {0x4004, LIT64(0xC90FDAA22168C235)} }; static const float32 pi_tbl2[65] = { - 0x21800000, 0xA0D00000, 0xA1E80000, 0x21480000, - 0xA1200000, 0x21FC0000, 0x21100000, 0xA1580000, - 0x21E00000, 0x20B00000, 0xA1880000, 0x21C40000, - 0x20000000, 0x21380000, 0xA1300000, 0x9FC00000, - 0x21000000, 0xA1680000, 0xA0A00000, 0x20900000, - 0x21600000, 0xA1080000, 0x1F800000, 0xA0B00000, - 0x20800000, 0xA0200000, 0x20E00000, 0x1F000000, - 0x20000000, 0x20600000, 0x1F800000, 0x1F000000, - 0x00000000, - 0x9F000000, 0x9F800000, 0xA0600000, 0xA0000000, - 0x9F000000, 0xA0E00000, 0x20200000, 0xA0800000, - 0x20B00000, 0x9F800000, 0x21080000, 0xA1600000, - 0xA0900000, 0x20A00000, 0x21680000, 0xA1000000, - 0x1FC00000, 0x21300000, 0xA1380000, 0xA0000000, - 0xA1C40000, 0x21880000, 0xA0B00000, 0xA1E00000, - 0x21580000, 0xA1100000, 0xA1FC0000, 0x21200000, - 0xA1480000, 0x21E80000, 0x20D00000, 0xA1800000 + 0x21800000, 0xA0D00000, 0xA1E80000, 0x21480000, + 0xA1200000, 0x21FC0000, 0x21100000, 0xA1580000, + 0x21E00000, 0x20B00000, 0xA1880000, 0x21C40000, + 0x20000000, 0x21380000, 0xA1300000, 0x9FC00000, + 0x21000000, 0xA1680000, 0xA0A00000, 0x20900000, + 0x21600000, 0xA1080000, 0x1F800000, 0xA0B00000, + 0x20800000, 0xA0200000, 0x20E00000, 0x1F000000, + 0x20000000, 0x20600000, 0x1F800000, 0x1F000000, + 0x00000000, + 0x9F000000, 0x9F800000, 0xA0600000, 0xA0000000, + 0x9F000000, 0xA0E00000, 0x20200000, 0xA0800000, + 0x20B00000, 0x9F800000, 0x21080000, 0xA1600000, + 0xA0900000, 0x20A00000, 0x21680000, 0xA1000000, + 0x1FC00000, 0x21300000, 0xA1380000, 0xA0000000, + 0xA1C40000, 0x21880000, 0xA0B00000, 0xA1E00000, + 0x21580000, 0xA1100000, 0xA1FC0000, 0x21200000, + 0xA1480000, 0x21E80000, 0x20D00000, 0xA1800000 }; -- 2.47.3