|
|
1.1 ! root 1: ! 2: /*============================================================================ ! 3: ! 4: This C source file is an extension to the SoftFloat IEC/IEEE Floating-point ! 5: Arithmetic Package, Release 2a. ! 6: ! 7: Written by Andreas Grabher for Previous, NeXT Computer Emulator. ! 8: ! 9: =============================================================================*/ ! 10: ! 11: #include "softfloat.h" ! 12: #include "softfloat_fpsp_tables.h" ! 13: ! 14: ! 15: /*---------------------------------------------------------------------------- ! 16: | Algorithms for transcendental functions supported by MC68881 and MC68882 ! 17: | mathematical coprocessors. The functions are derived from FPSP library. ! 18: *----------------------------------------------------------------------------*/ ! 19: ! 20: #define pi_sig LIT64(0xc90fdaa22168c235) ! 21: #define pi_sig0 LIT64(0xc90fdaa22168c234) ! 22: #define pi_sig1 LIT64(0xc4c6628b80dc1cd1) ! 23: ! 24: #define pi_exp 0x4000 ! 25: #define piby2_exp 0x3FFF ! 26: #define piby4_exp 0x3FFE ! 27: ! 28: #define one_exp 0x3FFF ! 29: #define one_sig LIT64(0x8000000000000000) ! 30: ! 31: ! 32: /*---------------------------------------------------------------------------- ! 33: | Function for compactifying extended double-precision floating point values. ! 34: *----------------------------------------------------------------------------*/ ! 35: ! 36: int32 floatx80_make_compact(int32 aExp, bits64 aSig) ! 37: { ! 38: return (aExp<<16)|(aSig>>48); ! 39: } ! 40: ! 41: ! 42: /*---------------------------------------------------------------------------- ! 43: | Arc cosine ! 44: *----------------------------------------------------------------------------*/ ! 45: ! 46: floatx80 floatx80_acos(floatx80 a) ! 47: { ! 48: flag aSign; ! 49: int32 aExp; ! 50: bits64 aSig; ! 51: ! 52: int8 user_rnd_mode, user_rnd_prec; ! 53: ! 54: int32 compact; ! 55: floatx80 fp0, fp1, one; ! 56: ! 57: aSig = extractFloatx80Frac(a); ! 58: aExp = extractFloatx80Exp(a); ! 59: aSign = extractFloatx80Sign(a); ! 60: ! 61: if (aExp == 0x7FFF && (bits64) (aSig<<1)) { ! 62: return propagateFloatx80NaNOneArg(a); ! 63: } ! 64: if (aExp == 0 && aSig == 0) { ! 65: float_raise(float_flag_inexact); ! 66: return roundAndPackFloatx80(floatx80_rounding_precision, 0, piby2_exp, pi_sig, 0); ! 67: } ! 68: ! 69: compact = floatx80_make_compact(aExp, aSig); ! 70: ! 71: if (compact >= 0x3FFF8000) { // |X| >= 1 ! 72: if (aExp == one_exp && aSig == one_sig) { // |X| == 1 ! 73: if (aSign) { // X == -1 ! 74: a = packFloatx80(0, pi_exp, pi_sig); ! 75: float_raise(float_flag_inexact); ! 76: return floatx80_move(a); ! 77: } else { // X == +1 ! 78: return packFloatx80(0, 0, 0); ! 79: } ! 80: } else { // |X| > 1 ! 81: float_raise(float_flag_invalid); ! 82: a.low = floatx80_default_nan_low; ! 83: a.high = floatx80_default_nan_high; ! 84: return a; ! 85: } ! 86: } // |X| < 1 ! 87: ! 88: user_rnd_mode = float_rounding_mode; ! 89: user_rnd_prec = floatx80_rounding_precision; ! 90: float_rounding_mode = float_round_nearest_even; ! 91: floatx80_rounding_precision = 80; ! 92: ! 93: one = packFloatx80(0, one_exp, one_sig); ! 94: fp0 = a; ! 95: ! 96: fp1 = floatx80_add(one, fp0); // 1 + X ! 97: fp0 = floatx80_sub(one, fp0); // 1 - X ! 98: fp0 = floatx80_div(fp0, fp1); // (1-X)/(1+X) ! 99: fp0 = floatx80_sqrt(fp0); // SQRT((1-X)/(1+X)) ! 100: fp0 = floatx80_atan(fp0); // ATAN(SQRT((1-X)/(1+X))) ! 101: ! 102: float_rounding_mode = user_rnd_mode; ! 103: floatx80_rounding_precision = user_rnd_prec; ! 104: ! 105: a = floatx80_add(fp0, fp0); // 2 * ATAN(SQRT((1-X)/(1+X))) ! 106: ! 107: float_raise(float_flag_inexact); ! 108: ! 109: return a; ! 110: } ! 111: ! 112: /*---------------------------------------------------------------------------- ! 113: | Arc sine ! 114: *----------------------------------------------------------------------------*/ ! 115: ! 116: floatx80 floatx80_asin(floatx80 a) ! 117: { ! 118: flag aSign; ! 119: int32 aExp; ! 120: bits64 aSig; ! 121: ! 122: int8 user_rnd_mode, user_rnd_prec; ! 123: ! 124: int32 compact; ! 125: floatx80 fp0, fp1, fp2, one; ! 126: ! 127: aSig = extractFloatx80Frac(a); ! 128: aExp = extractFloatx80Exp(a); ! 129: aSign = extractFloatx80Sign(a); ! 130: ! 131: if (aExp == 0x7FFF && (bits64) (aSig<<1)) { ! 132: return propagateFloatx80NaNOneArg(a); ! 133: } ! 134: ! 135: if (aExp == 0 && aSig == 0) { ! 136: return packFloatx80(aSign, 0, 0); ! 137: } ! 138: ! 139: compact = floatx80_make_compact(aExp, aSig); ! 140: ! 141: if (compact >= 0x3FFF8000) { // |X| >= 1 ! 142: if (aExp == one_exp && aSig == one_sig) { // |X| == 1 ! 143: float_raise(float_flag_inexact); ! 144: a = packFloatx80(aSign, piby2_exp, pi_sig); ! 145: return floatx80_move(a); ! 146: } else { // |X| > 1 ! 147: float_raise(float_flag_invalid); ! 148: a.low = floatx80_default_nan_low; ! 149: a.high = floatx80_default_nan_high; ! 150: return a; ! 151: } ! 152: ! 153: } // |X| < 1 ! 154: ! 155: user_rnd_mode = float_rounding_mode; ! 156: user_rnd_prec = floatx80_rounding_precision; ! 157: float_rounding_mode = float_round_nearest_even; ! 158: floatx80_rounding_precision = 80; ! 159: ! 160: one = packFloatx80(0, one_exp, one_sig); ! 161: fp0 = a; ! 162: ! 163: fp1 = floatx80_sub(one, fp0); // 1 - X ! 164: fp2 = floatx80_add(one, fp0); // 1 + X ! 165: fp1 = floatx80_mul(fp2, fp1); // (1+X)*(1-X) ! 166: fp1 = floatx80_sqrt(fp1); // SQRT((1+X)*(1-X)) ! 167: fp0 = floatx80_div(fp0, fp1); // X/SQRT((1+X)*(1-X)) ! 168: ! 169: float_rounding_mode = user_rnd_mode; ! 170: floatx80_rounding_precision = user_rnd_prec; ! 171: ! 172: a = floatx80_atan(fp0); // ATAN(X/SQRT((1+X)*(1-X))) ! 173: ! 174: float_raise(float_flag_inexact); ! 175: ! 176: return a; ! 177: } ! 178: ! 179: /*---------------------------------------------------------------------------- ! 180: | Arc tangent ! 181: *----------------------------------------------------------------------------*/ ! 182: ! 183: floatx80 floatx80_atan(floatx80 a) ! 184: { ! 185: flag aSign; ! 186: int32 aExp; ! 187: bits64 aSig; ! 188: ! 189: int8 user_rnd_mode, user_rnd_prec; ! 190: ! 191: int32 compact, tbl_index; ! 192: floatx80 fp0, fp1, fp2, fp3, xsave; ! 193: ! 194: aSig = extractFloatx80Frac(a); ! 195: aExp = extractFloatx80Exp(a); ! 196: aSign = extractFloatx80Sign(a); ! 197: ! 198: if (aExp == 0x7FFF) { ! 199: if ((bits64) (aSig<<1)) return propagateFloatx80NaNOneArg(a); ! 200: a = packFloatx80(aSign, piby2_exp, pi_sig); ! 201: float_raise(float_flag_inexact); ! 202: return floatx80_move(a); ! 203: } ! 204: ! 205: if (aExp == 0 && aSig == 0) { ! 206: return packFloatx80(aSign, 0, 0); ! 207: } ! 208: ! 209: compact = floatx80_make_compact(aExp, aSig); ! 210: ! 211: user_rnd_mode = float_rounding_mode; ! 212: user_rnd_prec = floatx80_rounding_precision; ! 213: float_rounding_mode = float_round_nearest_even; ! 214: floatx80_rounding_precision = 80; ! 215: ! 216: if (compact < 0x3FFB8000 || compact > 0x4002FFFF) { // |X| >= 16 or |X| < 1/16 ! 217: if (compact > 0x3FFF8000) { // |X| >= 16 ! 218: if (compact > 0x40638000) { // |X| > 2^(100) ! 219: fp0 = packFloatx80(aSign, piby2_exp, pi_sig); ! 220: fp1 = packFloatx80(aSign, 0x0001, one_sig); ! 221: ! 222: float_rounding_mode = user_rnd_mode; ! 223: floatx80_rounding_precision = user_rnd_prec; ! 224: ! 225: a = floatx80_sub(fp0, fp1); ! 226: ! 227: float_raise(float_flag_inexact); ! 228: ! 229: return a; ! 230: } else { ! 231: fp0 = a; ! 232: fp1 = packFloatx80(1, one_exp, one_sig); // -1 ! 233: fp1 = floatx80_div(fp1, fp0); // X' = -1/X ! 234: xsave = fp1; ! 235: fp0 = floatx80_mul(fp1, fp1); // Y = X'*X' ! 236: fp1 = floatx80_mul(fp0, fp0); // Z = Y*Y ! 237: fp3 = float64_to_floatx80(LIT64(0xBFB70BF398539E6A)); // C5 ! 238: fp2 = float64_to_floatx80(LIT64(0x3FBC7187962D1D7D)); // C4 ! 239: fp3 = floatx80_mul(fp3, fp1); // Z*C5 ! 240: fp2 = floatx80_mul(fp2, fp1); // Z*C4 ! 241: fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0xBFC24924827107B8))); // C3+Z*C5 ! 242: fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3FC999999996263E))); // C2+Z*C4 ! 243: fp1 = floatx80_mul(fp1, fp3); // Z*(C3+Z*C5) ! 244: fp2 = floatx80_mul(fp2, fp0); // Y*(C2+Z*C4) ! 245: fp1 = floatx80_add(fp1, float64_to_floatx80(LIT64(0xBFD5555555555536))); // C1+Z*(C3+Z*C5) ! 246: fp0 = floatx80_mul(fp0, xsave); // X'*Y ! 247: fp1 = floatx80_add(fp1, fp2); // [Y*(C2+Z*C4)]+[C1+Z*(C3+Z*C5)] ! 248: fp0 = floatx80_mul(fp0, fp1); // X'*Y*([B1+Z*(B3+Z*B5)]+[Y*(B2+Z*(B4+Z*B6))]) ?? ! 249: fp0 = floatx80_add(fp0, xsave); ! 250: fp1 = packFloatx80(aSign, piby2_exp, pi_sig); ! 251: ! 252: float_rounding_mode = user_rnd_mode; ! 253: floatx80_rounding_precision = user_rnd_prec; ! 254: ! 255: a = floatx80_add(fp0, fp1); ! 256: ! 257: float_raise(float_flag_inexact); ! 258: ! 259: return a; ! 260: } ! 261: } else { // |X| < 1/16 ! 262: if (compact < 0x3FD78000) { // |X| < 2^(-40) ! 263: float_rounding_mode = user_rnd_mode; ! 264: floatx80_rounding_precision = user_rnd_prec; ! 265: ! 266: a = floatx80_move(a); ! 267: ! 268: float_raise(float_flag_inexact); ! 269: ! 270: return a; ! 271: } else { ! 272: fp0 = a; ! 273: xsave = a; ! 274: fp0 = floatx80_mul(fp0, fp0); // Y = X*X ! 275: fp1 = floatx80_mul(fp0, fp0); // Z = Y*Y ! 276: fp2 = float64_to_floatx80(LIT64(0x3FB344447F876989)); // B6 ! 277: fp3 = float64_to_floatx80(LIT64(0xBFB744EE7FAF45DB)); // B5 ! 278: fp2 = floatx80_mul(fp2, fp1); // Z*B6 ! 279: fp3 = floatx80_mul(fp3, fp1); // Z*B5 ! 280: fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3FBC71C646940220))); // B4+Z*B6 ! 281: fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0xBFC24924921872F9))); // B3+Z*B5 ! 282: fp2 = floatx80_mul(fp2, fp1); // Z*(B4+Z*B6) ! 283: fp1 = floatx80_mul(fp1, fp3); // Z*(B3+Z*B5) ! 284: fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3FC9999999998FA9))); // B2+Z*(B4+Z*B6) ! 285: fp1 = floatx80_add(fp1, float64_to_floatx80(LIT64(0xBFD5555555555555))); // B1+Z*(B3+Z*B5) ! 286: fp2 = floatx80_mul(fp2, fp0); // Y*(B2+Z*(B4+Z*B6)) ! 287: fp0 = floatx80_mul(fp0, xsave); // X*Y ! 288: fp1 = floatx80_add(fp1, fp2); // [B1+Z*(B3+Z*B5)]+[Y*(B2+Z*(B4+Z*B6))] ! 289: fp0 = floatx80_mul(fp0, fp1); // X*Y*([B1+Z*(B3+Z*B5)]+[Y*(B2+Z*(B4+Z*B6))]) ! 290: ! 291: float_rounding_mode = user_rnd_mode; ! 292: floatx80_rounding_precision = user_rnd_prec; ! 293: ! 294: a = floatx80_add(fp0, xsave); ! 295: ! 296: float_raise(float_flag_inexact); ! 297: ! 298: return a; ! 299: } ! 300: } ! 301: } else { ! 302: aSig &= LIT64(0xF800000000000000); ! 303: aSig |= LIT64(0x0400000000000000); ! 304: xsave = packFloatx80(aSign, aExp, aSig); // F ! 305: fp0 = a; ! 306: fp1 = a; // X ! 307: fp2 = packFloatx80(0, one_exp, one_sig); // 1 ! 308: fp1 = floatx80_mul(fp1, xsave); // X*F ! 309: fp0 = floatx80_sub(fp0, xsave); // X-F ! 310: fp1 = floatx80_add(fp1, fp2); // 1 + X*F ! 311: fp0 = floatx80_div(fp0, fp1); // U = (X-F)/(1+X*F) ! 312: ! 313: tbl_index = compact; ! 314: ! 315: tbl_index &= 0x7FFF0000; ! 316: tbl_index -= 0x3FFB0000; ! 317: tbl_index >>= 1; ! 318: tbl_index += compact&0x00007800; ! 319: tbl_index >>= 11; ! 320: ! 321: fp3 = atan_tbl[tbl_index]; ! 322: ! 323: fp3.high |= aSign ? 0x8000 : 0; // ATAN(F) ! 324: ! 325: fp1 = floatx80_mul(fp0, fp0); // V = U*U ! 326: fp2 = float64_to_floatx80(LIT64(0xBFF6687E314987D8)); // A3 ! 327: fp2 = floatx80_add(fp2, fp1); // A3+V ! 328: fp2 = floatx80_mul(fp2, fp1); // V*(A3+V) ! 329: fp1 = floatx80_mul(fp1, fp0); // U*V ! 330: fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x4002AC6934A26DB3))); // A2+V*(A3+V) ! 331: fp1 = floatx80_mul(fp1, float64_to_floatx80(LIT64(0xBFC2476F4E1DA28E))); // A1+U*V ! 332: fp1 = floatx80_mul(fp1, fp2); // A1*U*V*(A2+V*(A3+V)) ! 333: fp0 = floatx80_add(fp0, fp1); // ATAN(U) ! 334: ! 335: float_rounding_mode = user_rnd_mode; ! 336: floatx80_rounding_precision = user_rnd_prec; ! 337: ! 338: a = floatx80_add(fp0, fp3); // ATAN(X) ! 339: ! 340: float_raise(float_flag_inexact); ! 341: ! 342: return a; ! 343: } ! 344: } ! 345: ! 346: /*---------------------------------------------------------------------------- ! 347: | Hyperbolic arc tangent ! 348: *----------------------------------------------------------------------------*/ ! 349: ! 350: floatx80 floatx80_atanh(floatx80 a) ! 351: { ! 352: flag aSign; ! 353: int32 aExp; ! 354: bits64 aSig; ! 355: ! 356: int8 user_rnd_mode, user_rnd_prec; ! 357: ! 358: int32 compact; ! 359: floatx80 fp0, fp1, fp2, one; ! 360: ! 361: aSig = extractFloatx80Frac(a); ! 362: aExp = extractFloatx80Exp(a); ! 363: aSign = extractFloatx80Sign(a); ! 364: ! 365: if (aExp == 0x7FFF && (bits64) (aSig<<1)) { ! 366: return propagateFloatx80NaNOneArg(a); ! 367: } ! 368: ! 369: if (aExp == 0 && aSig == 0) { ! 370: return packFloatx80(aSign, 0, 0); ! 371: } ! 372: ! 373: compact = floatx80_make_compact(aExp, aSig); ! 374: ! 375: if (compact >= 0x3FFF8000) { // |X| >= 1 ! 376: if (aExp == one_exp && aSig == one_sig) { // |X| == 1 ! 377: float_raise(float_flag_divbyzero); ! 378: return packFloatx80(aSign, 0x7FFF, floatx80_default_infinity_low); ! 379: } else { // |X| > 1 ! 380: float_raise(float_flag_invalid); ! 381: a.low = floatx80_default_nan_low; ! 382: a.high = floatx80_default_nan_high; ! 383: return a; ! 384: } ! 385: } // |X| < 1 ! 386: ! 387: user_rnd_mode = float_rounding_mode; ! 388: user_rnd_prec = floatx80_rounding_precision; ! 389: float_rounding_mode = float_round_nearest_even; ! 390: floatx80_rounding_precision = 80; ! 391: ! 392: one = packFloatx80(0, one_exp, one_sig); ! 393: fp2 = packFloatx80(aSign, 0x3FFE, one_sig); // SIGN(X) * (1/2) ! 394: fp0 = packFloatx80(0, aExp, aSig); // Y = |X| ! 395: fp1 = packFloatx80(1, aExp, aSig); // -Y ! 396: fp0 = floatx80_add(fp0, fp0); // 2Y ! 397: fp1 = floatx80_add(fp1, one); // 1-Y ! 398: fp0 = floatx80_div(fp0, fp1); // Z = 2Y/(1-Y) ! 399: fp0 = floatx80_lognp1(fp0); // LOG1P(Z) ! 400: ! 401: float_rounding_mode = user_rnd_mode; ! 402: floatx80_rounding_precision = user_rnd_prec; ! 403: ! 404: a = floatx80_mul(fp0, fp2); // ATANH(X) = SIGN(X) * (1/2) * LOG1P(Z) ! 405: ! 406: float_raise(float_flag_inexact); ! 407: ! 408: return a; ! 409: } ! 410: ! 411: /*---------------------------------------------------------------------------- ! 412: | Cosine ! 413: *----------------------------------------------------------------------------*/ ! 414: ! 415: floatx80 floatx80_cos(floatx80 a) ! 416: { ! 417: flag aSign, xSign; ! 418: int32 aExp, xExp; ! 419: bits64 aSig, xSig; ! 420: ! 421: int8 user_rnd_mode, user_rnd_prec; ! 422: ! 423: int32 compact, l, n, j; ! 424: floatx80 fp0, fp1, fp2, fp3, fp4, fp5, x, invtwopi, twopi1, twopi2; ! 425: float32 posneg1, twoto63; ! 426: flag adjn, endflag; ! 427: ! 428: aSig = extractFloatx80Frac(a); ! 429: aExp = extractFloatx80Exp(a); ! 430: aSign = extractFloatx80Sign(a); ! 431: ! 432: if (aExp == 0x7FFF) { ! 433: if ((bits64) (aSig<<1)) return propagateFloatx80NaNOneArg(a); ! 434: float_raise(float_flag_invalid); ! 435: a.low = floatx80_default_nan_low; ! 436: a.high = floatx80_default_nan_high; ! 437: return a; ! 438: } ! 439: ! 440: if (aExp == 0 && aSig == 0) { ! 441: return packFloatx80(0, one_exp, one_sig); ! 442: } ! 443: ! 444: adjn = 1; ! 445: ! 446: user_rnd_mode = float_rounding_mode; ! 447: user_rnd_prec = floatx80_rounding_precision; ! 448: float_rounding_mode = float_round_nearest_even; ! 449: floatx80_rounding_precision = 80; ! 450: ! 451: compact = floatx80_make_compact(aExp, aSig); ! 452: ! 453: fp0 = a; ! 454: ! 455: if (compact < 0x3FD78000 || compact > 0x4004BC7E) { // 2^(-40) > |X| > 15 PI ! 456: if (compact > 0x3FFF8000) { // |X| >= 15 PI ! 457: // REDUCEX ! 458: fp1 = packFloatx80(0, 0, 0); ! 459: if (compact == 0x7FFEFFFF) { ! 460: twopi1 = packFloatx80(aSign ^ 1, 0x7FFE, LIT64(0xC90FDAA200000000)); ! 461: twopi2 = packFloatx80(aSign ^ 1, 0x7FDC, LIT64(0x85A308D300000000)); ! 462: fp0 = floatx80_add(fp0, twopi1); ! 463: fp1 = fp0; ! 464: fp0 = floatx80_add(fp0, twopi2); ! 465: fp1 = floatx80_sub(fp1, fp0); ! 466: fp1 = floatx80_add(fp1, twopi2); ! 467: } ! 468: loop: ! 469: xSign = extractFloatx80Sign(fp0); ! 470: xExp = extractFloatx80Exp(fp0); ! 471: xExp -= 0x3FFF; ! 472: if (xExp <= 28) { ! 473: l = 0; ! 474: endflag = 1; ! 475: } else { ! 476: l = xExp - 27; ! 477: endflag = 0; ! 478: } ! 479: invtwopi = packFloatx80(0, 0x3FFE - l, LIT64(0xA2F9836E4E44152A)); // INVTWOPI ! 480: twopi1 = packFloatx80(0, 0x3FFF + l, LIT64(0xC90FDAA200000000)); ! 481: twopi2 = packFloatx80(0, 0x3FDD + l, LIT64(0x85A308D300000000)); ! 482: ! 483: twoto63 = 0x5F000000; ! 484: twoto63 |= xSign ? 0x80000000 : 0x00000000; // SIGN(INARG)*2^63 IN SGL ! 485: ! 486: fp2 = floatx80_mul(fp0, invtwopi); ! 487: fp2 = floatx80_add(fp2, float32_to_floatx80(twoto63)); // THE FRACTIONAL PART OF FP2 IS ROUNDED ! 488: fp2 = floatx80_sub(fp2, float32_to_floatx80(twoto63)); // FP2 is N ! 489: fp4 = floatx80_mul(twopi1, fp2); // W = N*P1 ! 490: fp5 = floatx80_mul(twopi2, fp2); // w = N*P2 ! 491: fp3 = floatx80_add(fp4, fp5); // FP3 is P ! 492: fp4 = floatx80_sub(fp4, fp3); // W-P ! 493: fp0 = floatx80_sub(fp0, fp3); // FP0 is A := R - P ! 494: fp4 = floatx80_add(fp4, fp5); // FP4 is p = (W-P)+w ! 495: fp3 = fp0; // FP3 is A ! 496: fp1 = floatx80_sub(fp1, fp4); // FP1 is a := r - p ! 497: fp0 = floatx80_add(fp0, fp1); // FP0 is R := A+a ! 498: ! 499: if (endflag > 0) { ! 500: n = floatx80_to_int32(fp2); ! 501: goto sincont; ! 502: } ! 503: fp3 = floatx80_sub(fp3, fp0); // A-R ! 504: fp1 = floatx80_add(fp1, fp3); // FP1 is r := (A-R)+a ! 505: goto loop; ! 506: } else { ! 507: // SINSM ! 508: fp0 = float32_to_floatx80(0x3F800000); // 1 ! 509: ! 510: float_rounding_mode = user_rnd_mode; ! 511: floatx80_rounding_precision = user_rnd_prec; ! 512: ! 513: if (adjn) { ! 514: // COSTINY ! 515: a = floatx80_sub(fp0, float32_to_floatx80(0x00800000)); ! 516: } else { ! 517: // SINTINY ! 518: a = floatx80_move(a); ! 519: } ! 520: float_raise(float_flag_inexact); ! 521: ! 522: return a; ! 523: } ! 524: } else { ! 525: fp1 = floatx80_mul(fp0, float64_to_floatx80(LIT64(0x3FE45F306DC9C883))); // X*2/PI ! 526: ! 527: n = floatx80_to_int32(fp1); ! 528: j = 32 + n; ! 529: ! 530: fp0 = floatx80_sub(fp0, pi_tbl[j]); // X-Y1 ! 531: fp0 = floatx80_sub(fp0, float32_to_floatx80(pi_tbl2[j])); // FP0 IS R = (X-Y1)-Y2 ! 532: ! 533: sincont: ! 534: if ((n + adjn) & 1) { ! 535: // COSPOLY ! 536: fp0 = floatx80_mul(fp0, fp0); // FP0 IS S ! 537: fp1 = floatx80_mul(fp0, fp0); // FP1 IS T ! 538: fp2 = float64_to_floatx80(LIT64(0x3D2AC4D0D6011EE3)); // B8 ! 539: fp3 = float64_to_floatx80(LIT64(0xBDA9396F9F45AC19)); // B7 ! 540: ! 541: xSign = extractFloatx80Sign(fp0); // X IS S ! 542: xExp = extractFloatx80Exp(fp0); ! 543: xSig = extractFloatx80Frac(fp0); ! 544: ! 545: if (((n + adjn) >> 1) & 1) { ! 546: xSign ^= 1; ! 547: posneg1 = 0xBF800000; // -1 ! 548: } else { ! 549: xSign ^= 0; ! 550: posneg1 = 0x3F800000; // 1 ! 551: } // X IS NOW R'= SGN*R ! 552: ! 553: fp2 = floatx80_mul(fp2, fp1); // TB8 ! 554: fp3 = floatx80_mul(fp3, fp1); // TB7 ! 555: fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3E21EED90612C972))); // B6+TB8 ! 556: fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0xBE927E4FB79D9FCF))); // B5+TB7 ! 557: fp2 = floatx80_mul(fp2, fp1); // T(B6+TB8) ! 558: fp3 = floatx80_mul(fp3, fp1); // T(B5+TB7) ! 559: fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3EFA01A01A01D423))); // B4+T(B6+TB8) ! 560: fp4 = packFloatx80(1, 0x3FF5, LIT64(0xB60B60B60B61D438)); ! 561: fp3 = floatx80_add(fp3, fp4); // B3+T(B5+TB7) ! 562: fp2 = floatx80_mul(fp2, fp1); // T(B4+T(B6+TB8)) ! 563: fp1 = floatx80_mul(fp1, fp3); // T(B3+T(B5+TB7)) ! 564: fp4 = packFloatx80(0, 0x3FFA, LIT64(0xAAAAAAAAAAAAAB5E)); ! 565: fp2 = floatx80_add(fp2, fp4); // B2+T(B4+T(B6+TB8)) ! 566: fp1 = floatx80_add(fp1, float32_to_floatx80(0xBF000000)); // B1+T(B3+T(B5+TB7)) ! 567: fp0 = floatx80_mul(fp0, fp2); // S(B2+T(B4+T(B6+TB8))) ! 568: fp0 = floatx80_add(fp0, fp1); // [B1+T(B3+T(B5+TB7))]+[S(B2+T(B4+T(B6+TB8)))] ! 569: ! 570: x = packFloatx80(xSign, xExp, xSig); ! 571: fp0 = floatx80_mul(fp0, x); ! 572: ! 573: float_rounding_mode = user_rnd_mode; ! 574: floatx80_rounding_precision = user_rnd_prec; ! 575: ! 576: a = floatx80_add(fp0, float32_to_floatx80(posneg1)); ! 577: ! 578: float_raise(float_flag_inexact); ! 579: ! 580: return a; ! 581: } else { ! 582: // SINPOLY ! 583: xSign = extractFloatx80Sign(fp0); // X IS R ! 584: xExp = extractFloatx80Exp(fp0); ! 585: xSig = extractFloatx80Frac(fp0); ! 586: ! 587: xSign ^= ((n + adjn) >> 1) & 1; // X IS NOW R'= SGN*R ! 588: ! 589: fp0 = floatx80_mul(fp0, fp0); // FP0 IS S ! 590: fp1 = floatx80_mul(fp0, fp0); // FP1 IS T ! 591: fp3 = float64_to_floatx80(LIT64(0xBD6AAA77CCC994F5)); // A7 ! 592: fp2 = float64_to_floatx80(LIT64(0x3DE612097AAE8DA1)); // A6 ! 593: fp3 = floatx80_mul(fp3, fp1); // T*A7 ! 594: fp2 = floatx80_mul(fp2, fp1); // T*A6 ! 595: fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0xBE5AE6452A118AE4))); // A5+T*A7 ! 596: fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3EC71DE3A5341531))); // A4+T*A6 ! 597: fp3 = floatx80_mul(fp3, fp1); // T(A5+TA7) ! 598: fp2 = floatx80_mul(fp2, fp1); // T(A4+TA6) ! 599: fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0xBF2A01A01A018B59))); // A3+T(A5+TA7) ! 600: fp4 = packFloatx80(0, 0x3FF8, LIT64(0x88888888888859AF)); ! 601: fp2 = floatx80_add(fp2, fp4); // A2+T(A4+TA6) ! 602: fp1 = floatx80_mul(fp1, fp3); // T(A3+T(A5+TA7)) ! 603: fp2 = floatx80_mul(fp2, fp0); // S(A2+T(A4+TA6)) ! 604: fp4 = packFloatx80(1, 0x3FFC, LIT64(0xAAAAAAAAAAAAAA99)); ! 605: fp1 = floatx80_add(fp1, fp4); // A1+T(A3+T(A5+TA7)) ! 606: fp1 = floatx80_add(fp1, fp2); // [A1+T(A3+T(A5+TA7))]+[S(A2+T(A4+TA6))] ! 607: ! 608: x = packFloatx80(xSign, xExp, xSig); ! 609: fp0 = floatx80_mul(fp0, x); // R'*S ! 610: fp0 = floatx80_mul(fp0, fp1); // SIN(R')-R' ! 611: ! 612: float_rounding_mode = user_rnd_mode; ! 613: floatx80_rounding_precision = user_rnd_prec; ! 614: ! 615: a = floatx80_add(fp0, x); ! 616: ! 617: float_raise(float_flag_inexact); ! 618: ! 619: return a; ! 620: } ! 621: } ! 622: } ! 623: ! 624: /*---------------------------------------------------------------------------- ! 625: | Hyperbolic cosine ! 626: *----------------------------------------------------------------------------*/ ! 627: ! 628: floatx80 floatx80_cosh(floatx80 a) ! 629: { ! 630: flag aSign; ! 631: int32 aExp; ! 632: bits64 aSig; ! 633: ! 634: int8 user_rnd_mode, user_rnd_prec; ! 635: ! 636: int32 compact; ! 637: floatx80 fp0, fp1; ! 638: ! 639: aSig = extractFloatx80Frac(a); ! 640: aExp = extractFloatx80Exp(a); ! 641: aSign = extractFloatx80Sign(a); ! 642: ! 643: if (aExp == 0x7FFF) { ! 644: if ((bits64) (aSig<<1)) return propagateFloatx80NaNOneArg(a); ! 645: return packFloatx80(0, 0x7FFF, floatx80_default_infinity_low); ! 646: } ! 647: ! 648: if (aExp == 0 && aSig == 0) { ! 649: return packFloatx80(0, one_exp, one_sig); ! 650: } ! 651: ! 652: user_rnd_mode = float_rounding_mode; ! 653: user_rnd_prec = floatx80_rounding_precision; ! 654: float_rounding_mode = float_round_nearest_even; ! 655: floatx80_rounding_precision = 80; ! 656: ! 657: compact = floatx80_make_compact(aExp, aSig); ! 658: ! 659: if (compact > 0x400CB167) { ! 660: if (compact > 0x400CB2B3) { ! 661: float_rounding_mode = user_rnd_mode; ! 662: floatx80_rounding_precision = user_rnd_prec; ! 663: return roundAndPackFloatx80(floatx80_rounding_precision, 0, 0x8000, one_sig, 0); ! 664: } else { ! 665: fp0 = packFloatx80(0, aExp, aSig); ! 666: fp0 = floatx80_sub(fp0, float64_to_floatx80(LIT64(0x40C62D38D3D64634))); ! 667: fp0 = floatx80_sub(fp0, float64_to_floatx80(LIT64(0x3D6F90AEB1E75CC7))); ! 668: fp0 = floatx80_etox(fp0); ! 669: fp1 = packFloatx80(0, 0x7FFB, one_sig); ! 670: ! 671: float_rounding_mode = user_rnd_mode; ! 672: floatx80_rounding_precision = user_rnd_prec; ! 673: ! 674: a = floatx80_mul(fp0, fp1); ! 675: ! 676: float_raise(float_flag_inexact); ! 677: ! 678: return a; ! 679: } ! 680: } ! 681: ! 682: fp0 = packFloatx80(0, aExp, aSig); // |X| ! 683: fp0 = floatx80_etox(fp0); // EXP(|X|) ! 684: fp0 = floatx80_mul(fp0, float32_to_floatx80(0x3F000000)); // (1/2)*EXP(|X|) ! 685: fp1 = float32_to_floatx80(0x3E800000); // 1/4 ! 686: fp1 = floatx80_div(fp1, fp0); // 1/(2*EXP(|X|)) ! 687: ! 688: float_rounding_mode = user_rnd_mode; ! 689: floatx80_rounding_precision = user_rnd_prec; ! 690: ! 691: a = floatx80_add(fp0, fp1); ! 692: ! 693: float_raise(float_flag_inexact); ! 694: ! 695: return a; ! 696: } ! 697: ! 698: /*---------------------------------------------------------------------------- ! 699: | e to x ! 700: *----------------------------------------------------------------------------*/ ! 701: ! 702: floatx80 floatx80_etox(floatx80 a) ! 703: { ! 704: flag aSign; ! 705: int32 aExp; ! 706: bits64 aSig; ! 707: ! 708: int8 user_rnd_mode, user_rnd_prec; ! 709: ! 710: int32 compact, n, j, k, m, m1; ! 711: floatx80 fp0, fp1, fp2, fp3, l2, scale, adjscale; ! 712: flag adjflag; ! 713: ! 714: aSig = extractFloatx80Frac(a); ! 715: aExp = extractFloatx80Exp(a); ! 716: aSign = extractFloatx80Sign(a); ! 717: ! 718: if (aExp == 0x7FFF) { ! 719: if ((bits64) (aSig<<1)) return propagateFloatx80NaNOneArg(a); ! 720: if (aSign) return packFloatx80(0, 0, 0); ! 721: return packFloatx80(0, 0x7FFF, floatx80_default_infinity_low); ! 722: } ! 723: ! 724: if (aExp == 0 && aSig == 0) { ! 725: return packFloatx80(0, one_exp, one_sig); ! 726: } ! 727: ! 728: user_rnd_mode = float_rounding_mode; ! 729: user_rnd_prec = floatx80_rounding_precision; ! 730: float_rounding_mode = float_round_nearest_even; ! 731: floatx80_rounding_precision = 80; ! 732: ! 733: adjflag = 0; ! 734: ! 735: if (aExp >= 0x3FBE) { // |X| >= 2^(-65) ! 736: compact = floatx80_make_compact(aExp, aSig); ! 737: ! 738: if (compact < 0x400CB167) { // |X| < 16380 log2 ! 739: fp0 = a; ! 740: fp1 = a; ! 741: fp0 = floatx80_mul(fp0, float32_to_floatx80(0x42B8AA3B)); // 64/log2 * X ! 742: adjflag = 0; ! 743: n = floatx80_to_int32(fp0); // int(64/log2*X) ! 744: fp0 = int32_to_floatx80(n); ! 745: ! 746: j = n & 0x3F; // J = N mod 64 ! 747: m = n / 64; // NOTE: this is really arithmetic right shift by 6 ! 748: if (n < 0 && j) { // arithmetic right shift is division and round towards minus infinity ! 749: m--; ! 750: } ! 751: m += 0x3FFF; // biased exponent of 2^(M) ! 752: ! 753: expcont1: ! 754: fp2 = fp0; // N ! 755: fp0 = floatx80_mul(fp0, float32_to_floatx80(0xBC317218)); // N * L1, L1 = lead(-log2/64) ! 756: l2 = packFloatx80(0, 0x3FDC, LIT64(0x82E308654361C4C6)); ! 757: fp2 = floatx80_mul(fp2, l2); // N * L2, L1+L2 = -log2/64 ! 758: fp0 = floatx80_add(fp0, fp1); // X + N*L1 ! 759: fp0 = floatx80_add(fp0, fp2); // R ! 760: ! 761: fp1 = floatx80_mul(fp0, fp0); // S = R*R ! 762: fp2 = float32_to_floatx80(0x3AB60B70); // A5 ! 763: fp2 = floatx80_mul(fp2, fp1); // fp2 is S*A5 ! 764: fp3 = floatx80_mul(float32_to_floatx80(0x3C088895), fp1); // fp3 is S*A4 ! 765: fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3FA5555555554431))); // fp2 is A3+S*A5 ! 766: fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0x3FC5555555554018))); // fp3 is A2+S*A4 ! 767: fp2 = floatx80_mul(fp2, fp1); // fp2 is S*(A3+S*A5) ! 768: fp3 = floatx80_mul(fp3, fp1); // fp3 is S*(A2+S*A4) ! 769: fp2 = floatx80_add(fp2, float32_to_floatx80(0x3F000000)); // fp2 is A1+S*(A3+S*A5) ! 770: fp3 = floatx80_mul(fp3, fp0); // fp3 IS R*S*(A2+S*A4) ! 771: fp2 = floatx80_mul(fp2, fp1); // fp2 IS S*(A1+S*(A3+S*A5)) ! 772: fp0 = floatx80_add(fp0, fp3); // fp0 IS R+R*S*(A2+S*A4) ! 773: fp0 = floatx80_add(fp0, fp2); // fp0 IS EXP(R) - 1 ! 774: ! 775: fp1 = exp_tbl[j]; ! 776: fp0 = floatx80_mul(fp0, fp1); // 2^(J/64)*(Exp(R)-1) ! 777: fp0 = floatx80_add(fp0, float32_to_floatx80(exp_tbl2[j])); // accurate 2^(J/64) ! 778: fp0 = floatx80_add(fp0, fp1); // 2^(J/64) + 2^(J/64)*(Exp(R)-1) ! 779: ! 780: scale = packFloatx80(0, m, one_sig); ! 781: if (adjflag) { ! 782: adjscale = packFloatx80(0, m1, one_sig); ! 783: fp0 = floatx80_mul(fp0, adjscale); ! 784: } ! 785: ! 786: float_rounding_mode = user_rnd_mode; ! 787: floatx80_rounding_precision = user_rnd_prec; ! 788: ! 789: a = floatx80_mul(fp0, scale); ! 790: ! 791: float_raise(float_flag_inexact); ! 792: ! 793: return a; ! 794: } else { // |X| >= 16380 log2 ! 795: if (compact > 0x400CB27C) { // |X| >= 16480 log2 ! 796: float_rounding_mode = user_rnd_mode; ! 797: floatx80_rounding_precision = user_rnd_prec; ! 798: if (aSign) { ! 799: a = roundAndPackFloatx80(floatx80_rounding_precision, 0, -0x1000, aSig, 0); ! 800: } else { ! 801: a = roundAndPackFloatx80(floatx80_rounding_precision, 0, 0x8000, aSig, 0); ! 802: } ! 803: float_raise(float_flag_inexact); ! 804: ! 805: return a; ! 806: } else { ! 807: fp0 = a; ! 808: fp1 = a; ! 809: fp0 = floatx80_mul(fp0, float32_to_floatx80(0x42B8AA3B)); // 64/log2 * X ! 810: adjflag = 1; ! 811: n = floatx80_to_int32(fp0); // int(64/log2*X) ! 812: fp0 = int32_to_floatx80(n); ! 813: ! 814: j = n & 0x3F; // J = N mod 64 ! 815: k = n / 64; // NOTE: this is really arithmetic right shift by 6 ! 816: if (n < 0 && j) { // arithmetic right shift is division and round towards minus infinity ! 817: k--; ! 818: } ! 819: m1 = k / 2; // NOTE: this is really arithmetic right shift by 1 ! 820: if (k < 0 && (k & 1)) { // arithmetic right shift is division and round towards minus infinity ! 821: m1--; ! 822: } ! 823: m = k - m1; ! 824: m1 += 0x3FFF; // biased exponent of 2^(M1) ! 825: m += 0x3FFF; // biased exponent of 2^(M) ! 826: ! 827: goto expcont1; ! 828: } ! 829: } ! 830: } else { // |X| < 2^(-65) ! 831: float_rounding_mode = user_rnd_mode; ! 832: floatx80_rounding_precision = user_rnd_prec; ! 833: ! 834: a = floatx80_add(a, float32_to_floatx80(0x3F800000)); // 1 + X ! 835: ! 836: float_raise(float_flag_inexact); ! 837: ! 838: return a; ! 839: } ! 840: } ! 841: ! 842: /*---------------------------------------------------------------------------- ! 843: | e to x minus 1 ! 844: *----------------------------------------------------------------------------*/ ! 845: ! 846: floatx80 floatx80_etoxm1(floatx80 a) ! 847: { ! 848: flag aSign; ! 849: int32 aExp; ! 850: bits64 aSig; ! 851: ! 852: int8 user_rnd_mode, user_rnd_prec; ! 853: ! 854: int32 compact, n, j, m, m1; ! 855: floatx80 fp0, fp1, fp2, fp3, l2, sc, onebysc; ! 856: ! 857: aSig = extractFloatx80Frac(a); ! 858: aExp = extractFloatx80Exp(a); ! 859: aSign = extractFloatx80Sign(a); ! 860: ! 861: if (aExp == 0x7FFF) { ! 862: if ((bits64) (aSig<<1)) return propagateFloatx80NaNOneArg(a); ! 863: if (aSign) return packFloatx80(aSign, one_exp, one_sig); ! 864: return packFloatx80(0, 0x7FFF, floatx80_default_infinity_low); ! 865: } ! 866: ! 867: if (aExp == 0 && aSig == 0) { ! 868: return packFloatx80(aSign, 0, 0); ! 869: } ! 870: ! 871: user_rnd_mode = float_rounding_mode; ! 872: user_rnd_prec = floatx80_rounding_precision; ! 873: float_rounding_mode = float_round_nearest_even; ! 874: floatx80_rounding_precision = 80; ! 875: ! 876: if (aExp >= 0x3FFD) { // |X| >= 1/4 ! 877: compact = floatx80_make_compact(aExp, aSig); ! 878: ! 879: if (compact <= 0x4004C215) { // |X| <= 70 log2 ! 880: fp0 = a; ! 881: fp1 = a; ! 882: fp0 = floatx80_mul(fp0, float32_to_floatx80(0x42B8AA3B)); // 64/log2 * X ! 883: n = floatx80_to_int32(fp0); // int(64/log2*X) ! 884: fp0 = int32_to_floatx80(n); ! 885: ! 886: j = n & 0x3F; // J = N mod 64 ! 887: m = n / 64; // NOTE: this is really arithmetic right shift by 6 ! 888: if (n < 0 && j) { // arithmetic right shift is division and round towards minus infinity ! 889: m--; ! 890: } ! 891: m1 = -m; ! 892: //m += 0x3FFF; // biased exponent of 2^(M) ! 893: //m1 += 0x3FFF; // biased exponent of -2^(-M) ! 894: ! 895: fp2 = fp0; // N ! 896: fp0 = floatx80_mul(fp0, float32_to_floatx80(0xBC317218)); // N * L1, L1 = lead(-log2/64) ! 897: l2 = packFloatx80(0, 0x3FDC, LIT64(0x82E308654361C4C6)); ! 898: fp2 = floatx80_mul(fp2, l2); // N * L2, L1+L2 = -log2/64 ! 899: fp0 = floatx80_add(fp0, fp1); // X + N*L1 ! 900: fp0 = floatx80_add(fp0, fp2); // R ! 901: ! 902: fp1 = floatx80_mul(fp0, fp0); // S = R*R ! 903: fp2 = float32_to_floatx80(0x3950097B); // A6 ! 904: fp2 = floatx80_mul(fp2, fp1); // fp2 is S*A6 ! 905: fp3 = floatx80_mul(float32_to_floatx80(0x3AB60B6A), fp1); // fp3 is S*A5 ! 906: fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3F81111111174385))); // fp2 IS A4+S*A6 ! 907: fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0x3FA5555555554F5A))); // fp3 is A3+S*A5 ! 908: fp2 = floatx80_mul(fp2, fp1); // fp2 IS S*(A4+S*A6) ! 909: fp3 = floatx80_mul(fp3, fp1); // fp3 IS S*(A3+S*A5) ! 910: fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3FC5555555555555))); // fp2 IS A2+S*(A4+S*A6) ! 911: fp3 = floatx80_add(fp3, float32_to_floatx80(0x3F000000)); // fp3 IS A1+S*(A3+S*A5) ! 912: fp2 = floatx80_mul(fp2, fp1); // fp2 IS S*(A2+S*(A4+S*A6)) ! 913: fp1 = floatx80_mul(fp1, fp3); // fp1 IS S*(A1+S*(A3+S*A5)) ! 914: fp2 = floatx80_mul(fp2, fp0); // fp2 IS R*S*(A2+S*(A4+S*A6)) ! 915: fp0 = floatx80_add(fp0, fp1); // fp0 IS R+S*(A1+S*(A3+S*A5)) ! 916: fp0 = floatx80_add(fp0, fp2); // fp0 IS EXP(R) - 1 ! 917: ! 918: fp0 = floatx80_mul(fp0, exp_tbl[j]); // 2^(J/64)*(Exp(R)-1) ! 919: ! 920: if (m >= 64) { ! 921: fp1 = float32_to_floatx80(exp_tbl2[j]); ! 922: onebysc = packFloatx80(1, m1 + 0x3FFF, one_sig); // -2^(-M) ! 923: fp1 = floatx80_add(fp1, onebysc); ! 924: fp0 = floatx80_add(fp0, fp1); ! 925: fp0 = floatx80_add(fp0, exp_tbl[j]); ! 926: } else if (m < -3) { ! 927: fp0 = floatx80_add(fp0, float32_to_floatx80(exp_tbl2[j])); ! 928: fp0 = floatx80_add(fp0, exp_tbl[j]); ! 929: onebysc = packFloatx80(1, m1 + 0x3FFF, one_sig); // -2^(-M) ! 930: fp0 = floatx80_add(fp0, onebysc); ! 931: } else { // -3 <= m <= 63 ! 932: fp1 = exp_tbl[j]; ! 933: fp0 = floatx80_add(fp0, float32_to_floatx80(exp_tbl2[j])); ! 934: onebysc = packFloatx80(1, m1 + 0x3FFF, one_sig); // -2^(-M) ! 935: fp1 = floatx80_add(fp1, onebysc); ! 936: fp0 = floatx80_add(fp0, fp1); ! 937: } ! 938: ! 939: sc = packFloatx80(0, m + 0x3FFF, one_sig); ! 940: ! 941: float_rounding_mode = user_rnd_mode; ! 942: floatx80_rounding_precision = user_rnd_prec; ! 943: ! 944: a = floatx80_mul(fp0, sc); ! 945: ! 946: float_raise(float_flag_inexact); ! 947: ! 948: return a; ! 949: } else { // |X| > 70 log2 ! 950: if (aSign) { ! 951: fp0 = float32_to_floatx80(0xBF800000); // -1 ! 952: ! 953: float_rounding_mode = user_rnd_mode; ! 954: floatx80_rounding_precision = user_rnd_prec; ! 955: ! 956: a = floatx80_add(fp0, float32_to_floatx80(0x00800000)); // -1 + 2^(-126) ! 957: ! 958: float_raise(float_flag_inexact); ! 959: ! 960: return a; ! 961: } else { ! 962: float_rounding_mode = user_rnd_mode; ! 963: floatx80_rounding_precision = user_rnd_prec; ! 964: ! 965: return floatx80_etox(a); ! 966: } ! 967: } ! 968: } else { // |X| < 1/4 ! 969: if (aExp >= 0x3FBE) { ! 970: fp0 = a; ! 971: fp0 = floatx80_mul(fp0, fp0); // S = X*X ! 972: fp1 = float32_to_floatx80(0x2F30CAA8); // B12 ! 973: fp1 = floatx80_mul(fp1, fp0); // S * B12 ! 974: fp2 = float32_to_floatx80(0x310F8290); // B11 ! 975: fp1 = floatx80_add(fp1, float32_to_floatx80(0x32D73220)); // B10 ! 976: fp2 = floatx80_mul(fp2, fp0); ! 977: fp1 = floatx80_mul(fp1, fp0); ! 978: fp2 = floatx80_add(fp2, float32_to_floatx80(0x3493F281)); // B9 ! 979: fp1 = floatx80_add(fp1, float64_to_floatx80(LIT64(0x3EC71DE3A5774682))); // B8 ! 980: fp2 = floatx80_mul(fp2, fp0); ! 981: fp1 = floatx80_mul(fp1, fp0); ! 982: fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3EFA01A019D7CB68))); // B7 ! 983: fp1 = floatx80_add(fp1, float64_to_floatx80(LIT64(0x3F2A01A01A019DF3))); // B6 ! 984: fp2 = floatx80_mul(fp2, fp0); ! 985: fp1 = floatx80_mul(fp1, fp0); ! 986: fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3F56C16C16C170E2))); // B5 ! 987: fp1 = floatx80_add(fp1, float64_to_floatx80(LIT64(0x3F81111111111111))); // B4 ! 988: fp2 = floatx80_mul(fp2, fp0); ! 989: fp1 = floatx80_mul(fp1, fp0); ! 990: fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3FA5555555555555))); // B3 ! 991: fp3 = packFloatx80(0, 0x3FFC, LIT64(0xAAAAAAAAAAAAAAAB)); ! 992: fp1 = floatx80_add(fp1, fp3); // B2 ! 993: fp2 = floatx80_mul(fp2, fp0); ! 994: fp1 = floatx80_mul(fp1, fp0); ! 995: ! 996: fp2 = floatx80_mul(fp2, fp0); ! 997: fp1 = floatx80_mul(fp1, a); ! 998: ! 999: fp0 = floatx80_mul(fp0, float32_to_floatx80(0x3F000000)); // S*B1 ! 1000: fp1 = floatx80_add(fp1, fp2); // Q ! 1001: fp0 = floatx80_add(fp0, fp1); // S*B1+Q ! 1002: ! 1003: float_rounding_mode = user_rnd_mode; ! 1004: floatx80_rounding_precision = user_rnd_prec; ! 1005: ! 1006: a = floatx80_add(fp0, a); ! 1007: ! 1008: float_raise(float_flag_inexact); ! 1009: ! 1010: return a; ! 1011: } else { // |X| < 2^(-65) ! 1012: sc = packFloatx80(1, 1, one_sig); ! 1013: fp0 = a; ! 1014: ! 1015: if (aExp < 0x0033) { // |X| < 2^(-16382) ! 1016: fp0 = floatx80_mul(fp0, float64_to_floatx80(LIT64(0x48B0000000000000))); ! 1017: fp0 = floatx80_add(fp0, sc); ! 1018: ! 1019: float_rounding_mode = user_rnd_mode; ! 1020: floatx80_rounding_precision = user_rnd_prec; ! 1021: ! 1022: a = floatx80_mul(fp0, float64_to_floatx80(LIT64(0x3730000000000000))); ! 1023: } else { ! 1024: float_rounding_mode = user_rnd_mode; ! 1025: floatx80_rounding_precision = user_rnd_prec; ! 1026: ! 1027: a = floatx80_add(fp0, sc); ! 1028: } ! 1029: ! 1030: float_raise(float_flag_inexact); ! 1031: ! 1032: return a; ! 1033: } ! 1034: } ! 1035: } ! 1036: ! 1037: /*---------------------------------------------------------------------------- ! 1038: | Log base 10 ! 1039: *----------------------------------------------------------------------------*/ ! 1040: ! 1041: floatx80 floatx80_log10(floatx80 a) ! 1042: { ! 1043: flag aSign; ! 1044: int32 aExp; ! 1045: bits64 aSig; ! 1046: ! 1047: int8 user_rnd_mode, user_rnd_prec; ! 1048: ! 1049: floatx80 fp0, fp1; ! 1050: ! 1051: aSig = extractFloatx80Frac(a); ! 1052: aExp = extractFloatx80Exp(a); ! 1053: aSign = extractFloatx80Sign(a); ! 1054: ! 1055: if (aExp == 0x7FFF) { ! 1056: if ((bits64) (aSig<<1)) propagateFloatx80NaNOneArg(a); ! 1057: if (aSign == 0) ! 1058: return packFloatx80(0, 0x7FFF, floatx80_default_infinity_low); ! 1059: } ! 1060: ! 1061: if (aExp == 0 && aSig == 0) { ! 1062: float_raise(float_flag_divbyzero); ! 1063: return packFloatx80(1, 0x7FFF, floatx80_default_infinity_low); ! 1064: } ! 1065: ! 1066: if (aSign) { ! 1067: float_raise(float_flag_invalid); ! 1068: a.low = floatx80_default_nan_low; ! 1069: a.high = floatx80_default_nan_high; ! 1070: return a; ! 1071: } ! 1072: ! 1073: user_rnd_mode = float_rounding_mode; ! 1074: user_rnd_prec = floatx80_rounding_precision; ! 1075: float_rounding_mode = float_round_nearest_even; ! 1076: floatx80_rounding_precision = 80; ! 1077: ! 1078: fp0 = floatx80_logn(a); ! 1079: fp1 = packFloatx80(0, 0x3FFD, LIT64(0xDE5BD8A937287195)); // INV_L10 ! 1080: ! 1081: float_rounding_mode = user_rnd_mode; ! 1082: floatx80_rounding_precision = user_rnd_prec; ! 1083: ! 1084: a = floatx80_mul(fp0, fp1); // LOGN(X)*INV_L10 ! 1085: ! 1086: float_raise(float_flag_inexact); ! 1087: ! 1088: return a; ! 1089: } ! 1090: ! 1091: /*---------------------------------------------------------------------------- ! 1092: | Log base 2 ! 1093: *----------------------------------------------------------------------------*/ ! 1094: ! 1095: floatx80 floatx80_log2(floatx80 a) ! 1096: { ! 1097: flag aSign; ! 1098: int32 aExp; ! 1099: bits64 aSig; ! 1100: ! 1101: int8 user_rnd_mode, user_rnd_prec; ! 1102: ! 1103: floatx80 fp0, fp1; ! 1104: ! 1105: aSig = extractFloatx80Frac(a); ! 1106: aExp = extractFloatx80Exp(a); ! 1107: aSign = extractFloatx80Sign(a); ! 1108: ! 1109: if (aExp == 0x7FFF) { ! 1110: if ((bits64) (aSig<<1)) propagateFloatx80NaNOneArg(a); ! 1111: if (aSign == 0) ! 1112: return packFloatx80(0, 0x7FFF, floatx80_default_infinity_low); ! 1113: } ! 1114: ! 1115: if (aExp == 0) { ! 1116: if (aSig == 0) { ! 1117: float_raise(float_flag_divbyzero); ! 1118: return packFloatx80(1, 0x7FFF, floatx80_default_infinity_low); ! 1119: } ! 1120: normalizeFloatx80Subnormal(aSig, &aExp, &aSig); ! 1121: } ! 1122: ! 1123: if (aSign) { ! 1124: float_raise(float_flag_invalid); ! 1125: a.low = floatx80_default_nan_low; ! 1126: a.high = floatx80_default_nan_high; ! 1127: return a; ! 1128: } ! 1129: ! 1130: user_rnd_mode = float_rounding_mode; ! 1131: user_rnd_prec = floatx80_rounding_precision; ! 1132: float_rounding_mode = float_round_nearest_even; ! 1133: floatx80_rounding_precision = 80; ! 1134: ! 1135: if (aSig == one_sig) { // X is 2^k ! 1136: float_rounding_mode = user_rnd_mode; ! 1137: floatx80_rounding_precision = user_rnd_prec; ! 1138: ! 1139: a = int32_to_floatx80(aExp-0x3FFF); ! 1140: } else { ! 1141: fp0 = floatx80_logn(a); ! 1142: fp1 = packFloatx80(0, 0x3FFF, LIT64(0xB8AA3B295C17F0BC)); // INV_L2 ! 1143: ! 1144: float_rounding_mode = user_rnd_mode; ! 1145: floatx80_rounding_precision = user_rnd_prec; ! 1146: ! 1147: a = floatx80_mul(fp0, fp1); // LOGN(X)*INV_L2 ! 1148: } ! 1149: ! 1150: float_raise(float_flag_inexact); ! 1151: ! 1152: return a; ! 1153: } ! 1154: ! 1155: /*---------------------------------------------------------------------------- ! 1156: | Log base e ! 1157: *----------------------------------------------------------------------------*/ ! 1158: ! 1159: floatx80 floatx80_logn(floatx80 a) ! 1160: { ! 1161: flag aSign; ! 1162: int32 aExp; ! 1163: bits64 aSig, fSig; ! 1164: ! 1165: int8 user_rnd_mode, user_rnd_prec; ! 1166: ! 1167: int32 compact, j, k, adjk; ! 1168: floatx80 fp0, fp1, fp2, fp3, f, logof2, klog2, saveu; ! 1169: ! 1170: aSig = extractFloatx80Frac(a); ! 1171: aExp = extractFloatx80Exp(a); ! 1172: aSign = extractFloatx80Sign(a); ! 1173: ! 1174: if (aExp == 0x7FFF) { ! 1175: if ((bits64) (aSig<<1)) propagateFloatx80NaNOneArg(a); ! 1176: if (aSign == 0) ! 1177: return packFloatx80(0, 0x7FFF, floatx80_default_infinity_low); ! 1178: } ! 1179: ! 1180: adjk = 0; ! 1181: ! 1182: if (aExp == 0) { ! 1183: if (aSig == 0) { // zero ! 1184: float_raise(float_flag_divbyzero); ! 1185: return packFloatx80(1, 0x7FFF, floatx80_default_infinity_low); ! 1186: } ! 1187: #if 1 ! 1188: if ((aSig & one_sig) == 0) { // denormal ! 1189: normalizeFloatx80Subnormal(aSig, &aExp, &aSig); ! 1190: adjk = -100; ! 1191: aExp += 100; ! 1192: a = packFloatx80(aSign, aExp, aSig); ! 1193: } ! 1194: #else ! 1195: normalizeFloatx80Subnormal(aSig, &aExp, &aSig); ! 1196: #endif ! 1197: } ! 1198: ! 1199: if (aSign) { ! 1200: float_raise(float_flag_invalid); ! 1201: a.low = floatx80_default_nan_low; ! 1202: a.high = floatx80_default_nan_high; ! 1203: return a; ! 1204: } ! 1205: ! 1206: user_rnd_mode = float_rounding_mode; ! 1207: user_rnd_prec = floatx80_rounding_precision; ! 1208: float_rounding_mode = float_round_nearest_even; ! 1209: floatx80_rounding_precision = 80; ! 1210: ! 1211: compact = floatx80_make_compact(aExp, aSig); ! 1212: ! 1213: if (compact < 0x3FFEF07D || compact > 0x3FFF8841) { // |X| < 15/16 or |X| > 17/16 ! 1214: k = aExp - 0x3FFF; ! 1215: k += adjk; ! 1216: fp1 = int32_to_floatx80(k); ! 1217: ! 1218: fSig = (aSig & LIT64(0xFE00000000000000)) | LIT64(0x0100000000000000); ! 1219: j = (fSig >> 56) & 0x7E; // DISPLACEMENT FOR 1/F ! 1220: ! 1221: f = packFloatx80(0, 0x3FFF, fSig); // F ! 1222: fp0 = packFloatx80(0, 0x3FFF, aSig); // Y ! 1223: ! 1224: fp0 = floatx80_sub(fp0, f); // Y-F ! 1225: ! 1226: // LP1CONT1 ! 1227: fp0 = floatx80_mul(fp0, log_tbl[j]); // FP0 IS U = (Y-F)/F ! 1228: logof2 = packFloatx80(0, 0x3FFE, LIT64(0xB17217F7D1CF79AC)); ! 1229: klog2 = floatx80_mul(fp1, logof2); // FP1 IS K*LOG2 ! 1230: fp2 = floatx80_mul(fp0, fp0); // FP2 IS V=U*U ! 1231: ! 1232: fp3 = fp2; ! 1233: fp1 = fp2; ! 1234: ! 1235: fp1 = floatx80_mul(fp1, float64_to_floatx80(LIT64(0x3FC2499AB5E4040B))); // V*A6 ! 1236: fp2 = floatx80_mul(fp2, float64_to_floatx80(LIT64(0xBFC555B5848CB7DB))); // V*A5 ! 1237: fp1 = floatx80_add(fp1, float64_to_floatx80(LIT64(0x3FC99999987D8730))); // A4+V*A6 ! 1238: fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0xBFCFFFFFFF6F7E97))); // A3+V*A5 ! 1239: fp1 = floatx80_mul(fp1, fp3); // V*(A4+V*A6) ! 1240: fp2 = floatx80_mul(fp2, fp3); // V*(A3+V*A5) ! 1241: fp1 = floatx80_add(fp1, float64_to_floatx80(LIT64(0x3FD55555555555A4))); // A2+V*(A4+V*A6) ! 1242: fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0xBFE0000000000008))); // A1+V*(A3+V*A5) ! 1243: fp1 = floatx80_mul(fp1, fp3); // V*(A2+V*(A4+V*A6)) ! 1244: fp2 = floatx80_mul(fp2, fp3); // V*(A1+V*(A3+V*A5)) ! 1245: fp1 = floatx80_mul(fp1, fp0); // U*V*(A2+V*(A4+V*A6)) ! 1246: fp0 = floatx80_add(fp0, fp2); // U+V*(A1+V*(A3+V*A5)) ! 1247: ! 1248: fp1 = floatx80_add(fp1, log_tbl[j+1]); // LOG(F)+U*V*(A2+V*(A4+V*A6)) ! 1249: fp0 = floatx80_add(fp0, fp1); // FP0 IS LOG(F) + LOG(1+U) ! 1250: ! 1251: float_rounding_mode = user_rnd_mode; ! 1252: floatx80_rounding_precision = user_rnd_prec; ! 1253: ! 1254: a = floatx80_add(fp0, klog2); ! 1255: ! 1256: float_raise(float_flag_inexact); ! 1257: ! 1258: return a; ! 1259: } else { // |X-1| >= 1/16 ! 1260: fp0 = a; ! 1261: fp1 = a; ! 1262: fp1 = floatx80_sub(fp1, float32_to_floatx80(0x3F800000)); // FP1 IS X-1 ! 1263: fp0 = floatx80_add(fp0, float32_to_floatx80(0x3F800000)); // FP0 IS X+1 ! 1264: fp1 = floatx80_add(fp1, fp1); // FP1 IS 2(X-1) ! 1265: ! 1266: // LP1CONT2 ! 1267: fp1 = floatx80_div(fp1, fp0); // U ! 1268: saveu = fp1; ! 1269: fp0 = floatx80_mul(fp1, fp1); // FP0 IS V = U*U ! 1270: fp1 = floatx80_mul(fp0, fp0); // FP1 IS W = V*V ! 1271: ! 1272: fp3 = float64_to_floatx80(LIT64(0x3F175496ADD7DAD6)); // B5 ! 1273: fp2 = float64_to_floatx80(LIT64(0x3F3C71C2FE80C7E0)); // B4 ! 1274: fp3 = floatx80_mul(fp3, fp1); // W*B5 ! 1275: fp2 = floatx80_mul(fp2, fp1); // W*B4 ! 1276: fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0x3F624924928BCCFF))); // B3+W*B5 ! 1277: fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3F899999999995EC))); // B2+W*B4 ! 1278: fp1 = floatx80_mul(fp1, fp3); // W*(B3+W*B5) ! 1279: fp2 = floatx80_mul(fp2, fp0); // V*(B2+W*B4) ! 1280: fp1 = floatx80_add(fp1, float64_to_floatx80(LIT64(0x3FB5555555555555))); // B1+W*(B3+W*B5) ! 1281: ! 1282: fp0 = floatx80_mul(fp0, saveu); // FP0 IS U*V ! 1283: fp1 = floatx80_add(fp1, fp2); // B1+W*(B3+W*B5) + V*(B2+W*B4) ! 1284: fp0 = floatx80_mul(fp0, fp1); // U*V*( [B1+W*(B3+W*B5)] + [V*(B2+W*B4)] ) ! 1285: ! 1286: float_rounding_mode = user_rnd_mode; ! 1287: floatx80_rounding_precision = user_rnd_prec; ! 1288: ! 1289: a = floatx80_add(fp0, saveu); ! 1290: ! 1291: //if (!floatx80_is_zero(a)) { ! 1292: float_raise(float_flag_inexact); ! 1293: //} ! 1294: ! 1295: return a; ! 1296: } ! 1297: } ! 1298: ! 1299: /*---------------------------------------------------------------------------- ! 1300: | Log base e of x plus 1 ! 1301: *----------------------------------------------------------------------------*/ ! 1302: ! 1303: floatx80 floatx80_lognp1(floatx80 a) ! 1304: { ! 1305: flag aSign; ! 1306: int32 aExp; ! 1307: bits64 aSig, fSig; ! 1308: ! 1309: int8 user_rnd_mode, user_rnd_prec; ! 1310: ! 1311: int32 compact, j, k; ! 1312: floatx80 fp0, fp1, fp2, fp3, f, logof2, klog2, saveu; ! 1313: ! 1314: aSig = extractFloatx80Frac(a); ! 1315: aExp = extractFloatx80Exp(a); ! 1316: aSign = extractFloatx80Sign(a); ! 1317: ! 1318: if (aExp == 0x7FFF) { ! 1319: if ((bits64) (aSig<<1)) propagateFloatx80NaNOneArg(a); ! 1320: if (aSign) { ! 1321: float_raise(float_flag_invalid); ! 1322: a.low = floatx80_default_nan_low; ! 1323: a.high = floatx80_default_nan_high; ! 1324: return a; ! 1325: } ! 1326: return packFloatx80(0, 0x7FFF, floatx80_default_infinity_low); ! 1327: } ! 1328: ! 1329: if (aExp == 0 && aSig == 0) { ! 1330: return packFloatx80(aSign, 0, 0); ! 1331: } ! 1332: ! 1333: if (aSign && aExp >= one_exp) { ! 1334: if (aExp == one_exp && aSig == one_sig) { ! 1335: float_raise(float_flag_divbyzero); ! 1336: packFloatx80(aSign, 0x7FFF, floatx80_default_infinity_low); ! 1337: } ! 1338: float_raise(float_flag_invalid); ! 1339: a.low = floatx80_default_nan_low; ! 1340: a.high = floatx80_default_nan_high; ! 1341: return a; ! 1342: } ! 1343: ! 1344: if (aExp < 0x3f99 || (aExp == 0x3f99 && aSig == one_sig)) { // <= min threshold ! 1345: float_raise(float_flag_inexact); ! 1346: return floatx80_move(a); ! 1347: } ! 1348: ! 1349: user_rnd_mode = float_rounding_mode; ! 1350: user_rnd_prec = floatx80_rounding_precision; ! 1351: float_rounding_mode = float_round_nearest_even; ! 1352: floatx80_rounding_precision = 80; ! 1353: ! 1354: compact = floatx80_make_compact(aExp, aSig); ! 1355: ! 1356: fp0 = a; // Z ! 1357: fp1 = a; ! 1358: ! 1359: fp0 = floatx80_add(fp0, float32_to_floatx80(0x3F800000)); // X = (1+Z) ! 1360: ! 1361: aExp = extractFloatx80Exp(fp0); ! 1362: aSig = extractFloatx80Frac(fp0); ! 1363: ! 1364: compact = floatx80_make_compact(aExp, aSig); ! 1365: ! 1366: if (compact < 0x3FFE8000 || compact > 0x3FFFC000) { // |X| < 1/2 or |X| > 3/2 ! 1367: k = aExp - 0x3FFF; ! 1368: fp1 = int32_to_floatx80(k); ! 1369: ! 1370: fSig = (aSig & LIT64(0xFE00000000000000)) | LIT64(0x0100000000000000); ! 1371: j = (fSig >> 56) & 0x7E; // DISPLACEMENT FOR 1/F ! 1372: ! 1373: f = packFloatx80(0, 0x3FFF, fSig); // F ! 1374: fp0 = packFloatx80(0, 0x3FFF, aSig); // Y ! 1375: ! 1376: fp0 = floatx80_sub(fp0, f); // Y-F ! 1377: ! 1378: lp1cont1: ! 1379: // LP1CONT1 ! 1380: fp0 = floatx80_mul(fp0, log_tbl[j]); // FP0 IS U = (Y-F)/F ! 1381: logof2 = packFloatx80(0, 0x3FFE, LIT64(0xB17217F7D1CF79AC)); ! 1382: klog2 = floatx80_mul(fp1, logof2); // FP1 IS K*LOG2 ! 1383: fp2 = floatx80_mul(fp0, fp0); // FP2 IS V=U*U ! 1384: ! 1385: fp3 = fp2; ! 1386: fp1 = fp2; ! 1387: ! 1388: fp1 = floatx80_mul(fp1, float64_to_floatx80(LIT64(0x3FC2499AB5E4040B))); // V*A6 ! 1389: fp2 = floatx80_mul(fp2, float64_to_floatx80(LIT64(0xBFC555B5848CB7DB))); // V*A5 ! 1390: fp1 = floatx80_add(fp1, float64_to_floatx80(LIT64(0x3FC99999987D8730))); // A4+V*A6 ! 1391: fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0xBFCFFFFFFF6F7E97))); // A3+V*A5 ! 1392: fp1 = floatx80_mul(fp1, fp3); // V*(A4+V*A6) ! 1393: fp2 = floatx80_mul(fp2, fp3); // V*(A3+V*A5) ! 1394: fp1 = floatx80_add(fp1, float64_to_floatx80(LIT64(0x3FD55555555555A4))); // A2+V*(A4+V*A6) ! 1395: fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0xBFE0000000000008))); // A1+V*(A3+V*A5) ! 1396: fp1 = floatx80_mul(fp1, fp3); // V*(A2+V*(A4+V*A6)) ! 1397: fp2 = floatx80_mul(fp2, fp3); // V*(A1+V*(A3+V*A5)) ! 1398: fp1 = floatx80_mul(fp1, fp0); // U*V*(A2+V*(A4+V*A6)) ! 1399: fp0 = floatx80_add(fp0, fp2); // U+V*(A1+V*(A3+V*A5)) ! 1400: ! 1401: fp1 = floatx80_add(fp1, log_tbl[j+1]); // LOG(F)+U*V*(A2+V*(A4+V*A6)) ! 1402: fp0 = floatx80_add(fp0, fp1); // FP0 IS LOG(F) + LOG(1+U) ! 1403: ! 1404: float_rounding_mode = user_rnd_mode; ! 1405: floatx80_rounding_precision = user_rnd_prec; ! 1406: ! 1407: a = floatx80_add(fp0, klog2); ! 1408: ! 1409: float_raise(float_flag_inexact); ! 1410: ! 1411: return a; ! 1412: } else if (compact < 0x3FFEF07D || compact > 0x3FFF8841) { // |X| < 1/16 or |X| > -1/16 ! 1413: // LP1CARE ! 1414: fSig = (aSig & LIT64(0xFE00000000000000)) | LIT64(0x0100000000000000); ! 1415: f = packFloatx80(0, 0x3FFF, fSig); // F ! 1416: j = (fSig >> 56) & 0x7E; // DISPLACEMENT FOR 1/F ! 1417: ! 1418: if (compact >= 0x3FFF8000) { // 1+Z >= 1 ! 1419: // KISZERO ! 1420: fp0 = floatx80_sub(float32_to_floatx80(0x3F800000), f); // 1-F ! 1421: fp0 = floatx80_add(fp0, fp1); // FP0 IS Y-F = (1-F)+Z ! 1422: fp1 = packFloatx80(0, 0, 0); // K = 0 ! 1423: } else { ! 1424: // KISNEG ! 1425: fp0 = floatx80_sub(float32_to_floatx80(0x40000000), f); // 2-F ! 1426: fp1 = floatx80_add(fp1, fp1); // 2Z ! 1427: fp0 = floatx80_add(fp0, fp1); // FP0 IS Y-F = (2-F)+2Z ! 1428: fp1 = packFloatx80(1, one_exp, one_sig); // K = -1 ! 1429: } ! 1430: goto lp1cont1; ! 1431: } else { ! 1432: // LP1ONE16 ! 1433: fp1 = floatx80_add(fp1, fp1); // FP1 IS 2Z ! 1434: fp0 = floatx80_add(fp0, float32_to_floatx80(0x3F800000)); // FP0 IS 1+X ! 1435: ! 1436: // LP1CONT2 ! 1437: fp1 = floatx80_div(fp1, fp0); // U ! 1438: saveu = fp1; ! 1439: fp0 = floatx80_mul(fp1, fp1); // FP0 IS V = U*U ! 1440: fp1 = floatx80_mul(fp0, fp0); // FP1 IS W = V*V ! 1441: ! 1442: fp3 = float64_to_floatx80(LIT64(0x3F175496ADD7DAD6)); // B5 ! 1443: fp2 = float64_to_floatx80(LIT64(0x3F3C71C2FE80C7E0)); // B4 ! 1444: fp3 = floatx80_mul(fp3, fp1); // W*B5 ! 1445: fp2 = floatx80_mul(fp2, fp1); // W*B4 ! 1446: fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0x3F624924928BCCFF))); // B3+W*B5 ! 1447: fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3F899999999995EC))); // B2+W*B4 ! 1448: fp1 = floatx80_mul(fp1, fp3); // W*(B3+W*B5) ! 1449: fp2 = floatx80_mul(fp2, fp0); // V*(B2+W*B4) ! 1450: fp1 = floatx80_add(fp1, float64_to_floatx80(LIT64(0x3FB5555555555555))); // B1+W*(B3+W*B5) ! 1451: ! 1452: fp0 = floatx80_mul(fp0, saveu); // FP0 IS U*V ! 1453: fp1 = floatx80_add(fp1, fp2); // B1+W*(B3+W*B5) + V*(B2+W*B4) ! 1454: fp0 = floatx80_mul(fp0, fp1); // U*V*( [B1+W*(B3+W*B5)] + [V*(B2+W*B4)] ) ! 1455: ! 1456: float_rounding_mode = user_rnd_mode; ! 1457: floatx80_rounding_precision = user_rnd_prec; ! 1458: ! 1459: a = floatx80_add(fp0, saveu); ! 1460: ! 1461: //if (!floatx80_is_zero(a)) { ! 1462: float_raise(float_flag_inexact); ! 1463: //} ! 1464: ! 1465: return a; ! 1466: } ! 1467: } ! 1468: ! 1469: /*---------------------------------------------------------------------------- ! 1470: | Sine ! 1471: *----------------------------------------------------------------------------*/ ! 1472: ! 1473: floatx80 floatx80_sin(floatx80 a) ! 1474: { ! 1475: flag aSign, xSign; ! 1476: int32 aExp, xExp; ! 1477: bits64 aSig, xSig; ! 1478: ! 1479: int8 user_rnd_mode, user_rnd_prec; ! 1480: ! 1481: int32 compact, l, n, j; ! 1482: floatx80 fp0, fp1, fp2, fp3, fp4, fp5, x, invtwopi, twopi1, twopi2; ! 1483: float32 posneg1, twoto63; ! 1484: flag adjn, endflag; ! 1485: ! 1486: aSig = extractFloatx80Frac(a); ! 1487: aExp = extractFloatx80Exp(a); ! 1488: aSign = extractFloatx80Sign(a); ! 1489: ! 1490: if (aExp == 0x7FFF) { ! 1491: if ((bits64) (aSig<<1)) return propagateFloatx80NaNOneArg(a); ! 1492: float_raise(float_flag_invalid); ! 1493: a.low = floatx80_default_nan_low; ! 1494: a.high = floatx80_default_nan_high; ! 1495: return a; ! 1496: } ! 1497: ! 1498: if (aExp == 0 && aSig == 0) { ! 1499: return packFloatx80(aSign, 0, 0); ! 1500: } ! 1501: ! 1502: adjn = 0; ! 1503: ! 1504: user_rnd_mode = float_rounding_mode; ! 1505: user_rnd_prec = floatx80_rounding_precision; ! 1506: float_rounding_mode = float_round_nearest_even; ! 1507: floatx80_rounding_precision = 80; ! 1508: ! 1509: compact = floatx80_make_compact(aExp, aSig); ! 1510: ! 1511: fp0 = a; ! 1512: ! 1513: if (compact < 0x3FD78000 || compact > 0x4004BC7E) { // 2^(-40) > |X| > 15 PI ! 1514: if (compact > 0x3FFF8000) { // |X| >= 15 PI ! 1515: // REDUCEX ! 1516: fp1 = packFloatx80(0, 0, 0); ! 1517: if (compact == 0x7FFEFFFF) { ! 1518: twopi1 = packFloatx80(aSign ^ 1, 0x7FFE, LIT64(0xC90FDAA200000000)); ! 1519: twopi2 = packFloatx80(aSign ^ 1, 0x7FDC, LIT64(0x85A308D300000000)); ! 1520: fp0 = floatx80_add(fp0, twopi1); ! 1521: fp1 = fp0; ! 1522: fp0 = floatx80_add(fp0, twopi2); ! 1523: fp1 = floatx80_sub(fp1, fp0); ! 1524: fp1 = floatx80_add(fp1, twopi2); ! 1525: } ! 1526: loop: ! 1527: xSign = extractFloatx80Sign(fp0); ! 1528: xExp = extractFloatx80Exp(fp0); ! 1529: xExp -= 0x3FFF; ! 1530: if (xExp <= 28) { ! 1531: l = 0; ! 1532: endflag = 1; ! 1533: } else { ! 1534: l = xExp - 27; ! 1535: endflag = 0; ! 1536: } ! 1537: invtwopi = packFloatx80(0, 0x3FFE - l, LIT64(0xA2F9836E4E44152A)); // INVTWOPI ! 1538: twopi1 = packFloatx80(0, 0x3FFF + l, LIT64(0xC90FDAA200000000)); ! 1539: twopi2 = packFloatx80(0, 0x3FDD + l, LIT64(0x85A308D300000000)); ! 1540: ! 1541: twoto63 = 0x5F000000; ! 1542: twoto63 |= xSign ? 0x80000000 : 0x00000000; // SIGN(INARG)*2^63 IN SGL ! 1543: ! 1544: fp2 = floatx80_mul(fp0, invtwopi); ! 1545: fp2 = floatx80_add(fp2, float32_to_floatx80(twoto63)); // THE FRACTIONAL PART OF FP2 IS ROUNDED ! 1546: fp2 = floatx80_sub(fp2, float32_to_floatx80(twoto63)); // FP2 is N ! 1547: fp4 = floatx80_mul(twopi1, fp2); // W = N*P1 ! 1548: fp5 = floatx80_mul(twopi2, fp2); // w = N*P2 ! 1549: fp3 = floatx80_add(fp4, fp5); // FP3 is P ! 1550: fp4 = floatx80_sub(fp4, fp3); // W-P ! 1551: fp0 = floatx80_sub(fp0, fp3); // FP0 is A := R - P ! 1552: fp4 = floatx80_add(fp4, fp5); // FP4 is p = (W-P)+w ! 1553: fp3 = fp0; // FP3 is A ! 1554: fp1 = floatx80_sub(fp1, fp4); // FP1 is a := r - p ! 1555: fp0 = floatx80_add(fp0, fp1); // FP0 is R := A+a ! 1556: ! 1557: if (endflag > 0) { ! 1558: n = floatx80_to_int32(fp2); ! 1559: goto sincont; ! 1560: } ! 1561: fp3 = floatx80_sub(fp3, fp0); // A-R ! 1562: fp1 = floatx80_add(fp1, fp3); // FP1 is r := (A-R)+a ! 1563: goto loop; ! 1564: } else { ! 1565: // SINSM ! 1566: fp0 = float32_to_floatx80(0x3F800000); // 1 ! 1567: ! 1568: float_rounding_mode = user_rnd_mode; ! 1569: floatx80_rounding_precision = user_rnd_prec; ! 1570: ! 1571: if (adjn) { ! 1572: // COSTINY ! 1573: a = floatx80_sub(fp0, float32_to_floatx80(0x00800000)); ! 1574: } else { ! 1575: // SINTINY ! 1576: a = floatx80_move(a); ! 1577: } ! 1578: float_raise(float_flag_inexact); ! 1579: ! 1580: return a; ! 1581: } ! 1582: } else { ! 1583: fp1 = floatx80_mul(fp0, float64_to_floatx80(LIT64(0x3FE45F306DC9C883))); // X*2/PI ! 1584: ! 1585: n = floatx80_to_int32(fp1); ! 1586: j = 32 + n; ! 1587: ! 1588: fp0 = floatx80_sub(fp0, pi_tbl[j]); // X-Y1 ! 1589: fp0 = floatx80_sub(fp0, float32_to_floatx80(pi_tbl2[j])); // FP0 IS R = (X-Y1)-Y2 ! 1590: ! 1591: sincont: ! 1592: if ((n + adjn) & 1) { ! 1593: // COSPOLY ! 1594: fp0 = floatx80_mul(fp0, fp0); // FP0 IS S ! 1595: fp1 = floatx80_mul(fp0, fp0); // FP1 IS T ! 1596: fp2 = float64_to_floatx80(LIT64(0x3D2AC4D0D6011EE3)); // B8 ! 1597: fp3 = float64_to_floatx80(LIT64(0xBDA9396F9F45AC19)); // B7 ! 1598: ! 1599: xSign = extractFloatx80Sign(fp0); // X IS S ! 1600: xExp = extractFloatx80Exp(fp0); ! 1601: xSig = extractFloatx80Frac(fp0); ! 1602: ! 1603: if (((n + adjn) >> 1) & 1) { ! 1604: xSign ^= 1; ! 1605: posneg1 = 0xBF800000; // -1 ! 1606: } else { ! 1607: xSign ^= 0; ! 1608: posneg1 = 0x3F800000; // 1 ! 1609: } // X IS NOW R'= SGN*R ! 1610: ! 1611: fp2 = floatx80_mul(fp2, fp1); // TB8 ! 1612: fp3 = floatx80_mul(fp3, fp1); // TB7 ! 1613: fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3E21EED90612C972))); // B6+TB8 ! 1614: fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0xBE927E4FB79D9FCF))); // B5+TB7 ! 1615: fp2 = floatx80_mul(fp2, fp1); // T(B6+TB8) ! 1616: fp3 = floatx80_mul(fp3, fp1); // T(B5+TB7) ! 1617: fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3EFA01A01A01D423))); // B4+T(B6+TB8) ! 1618: fp4 = packFloatx80(1, 0x3FF5, LIT64(0xB60B60B60B61D438)); ! 1619: fp3 = floatx80_add(fp3, fp4); // B3+T(B5+TB7) ! 1620: fp2 = floatx80_mul(fp2, fp1); // T(B4+T(B6+TB8)) ! 1621: fp1 = floatx80_mul(fp1, fp3); // T(B3+T(B5+TB7)) ! 1622: fp4 = packFloatx80(0, 0x3FFA, LIT64(0xAAAAAAAAAAAAAB5E)); ! 1623: fp2 = floatx80_add(fp2, fp4); // B2+T(B4+T(B6+TB8)) ! 1624: fp1 = floatx80_add(fp1, float32_to_floatx80(0xBF000000)); // B1+T(B3+T(B5+TB7)) ! 1625: fp0 = floatx80_mul(fp0, fp2); // S(B2+T(B4+T(B6+TB8))) ! 1626: fp0 = floatx80_add(fp0, fp1); // [B1+T(B3+T(B5+TB7))]+[S(B2+T(B4+T(B6+TB8)))] ! 1627: ! 1628: x = packFloatx80(xSign, xExp, xSig); ! 1629: fp0 = floatx80_mul(fp0, x); ! 1630: ! 1631: float_rounding_mode = user_rnd_mode; ! 1632: floatx80_rounding_precision = user_rnd_prec; ! 1633: ! 1634: a = floatx80_add(fp0, float32_to_floatx80(posneg1)); ! 1635: ! 1636: float_raise(float_flag_inexact); ! 1637: ! 1638: return a; ! 1639: } else { ! 1640: // SINPOLY ! 1641: xSign = extractFloatx80Sign(fp0); // X IS R ! 1642: xExp = extractFloatx80Exp(fp0); ! 1643: xSig = extractFloatx80Frac(fp0); ! 1644: ! 1645: xSign ^= ((n + adjn) >> 1) & 1; // X IS NOW R'= SGN*R ! 1646: ! 1647: fp0 = floatx80_mul(fp0, fp0); // FP0 IS S ! 1648: fp1 = floatx80_mul(fp0, fp0); // FP1 IS T ! 1649: fp3 = float64_to_floatx80(LIT64(0xBD6AAA77CCC994F5)); // A7 ! 1650: fp2 = float64_to_floatx80(LIT64(0x3DE612097AAE8DA1)); // A6 ! 1651: fp3 = floatx80_mul(fp3, fp1); // T*A7 ! 1652: fp2 = floatx80_mul(fp2, fp1); // T*A6 ! 1653: fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0xBE5AE6452A118AE4))); // A5+T*A7 ! 1654: fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3EC71DE3A5341531))); // A4+T*A6 ! 1655: fp3 = floatx80_mul(fp3, fp1); // T(A5+TA7) ! 1656: fp2 = floatx80_mul(fp2, fp1); // T(A4+TA6) ! 1657: fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0xBF2A01A01A018B59))); // A3+T(A5+TA7) ! 1658: fp4 = packFloatx80(0, 0x3FF8, LIT64(0x88888888888859AF)); ! 1659: fp2 = floatx80_add(fp2, fp4); // A2+T(A4+TA6) ! 1660: fp1 = floatx80_mul(fp1, fp3); // T(A3+T(A5+TA7)) ! 1661: fp2 = floatx80_mul(fp2, fp0); // S(A2+T(A4+TA6)) ! 1662: fp4 = packFloatx80(1, 0x3FFC, LIT64(0xAAAAAAAAAAAAAA99)); ! 1663: fp1 = floatx80_add(fp1, fp4); // A1+T(A3+T(A5+TA7)) ! 1664: fp1 = floatx80_add(fp1, fp2); // [A1+T(A3+T(A5+TA7))]+[S(A2+T(A4+TA6))] ! 1665: ! 1666: x = packFloatx80(xSign, xExp, xSig); ! 1667: fp0 = floatx80_mul(fp0, x); // R'*S ! 1668: fp0 = floatx80_mul(fp0, fp1); // SIN(R')-R' ! 1669: ! 1670: float_rounding_mode = user_rnd_mode; ! 1671: floatx80_rounding_precision = user_rnd_prec; ! 1672: ! 1673: a = floatx80_add(fp0, x); ! 1674: ! 1675: float_raise(float_flag_inexact); ! 1676: ! 1677: return a; ! 1678: } ! 1679: } ! 1680: } ! 1681: ! 1682: /*---------------------------------------------------------------------------- ! 1683: | Hyperbolic sine ! 1684: *----------------------------------------------------------------------------*/ ! 1685: ! 1686: floatx80 floatx80_sinh(floatx80 a) ! 1687: { ! 1688: flag aSign; ! 1689: int32 aExp; ! 1690: bits64 aSig; ! 1691: ! 1692: int8 user_rnd_mode, user_rnd_prec; ! 1693: ! 1694: int32 compact; ! 1695: floatx80 fp0, fp1, fp2; ! 1696: float32 fact; ! 1697: ! 1698: aSig = extractFloatx80Frac(a); ! 1699: aExp = extractFloatx80Exp(a); ! 1700: aSign = extractFloatx80Sign(a); ! 1701: ! 1702: if (aExp == 0x7FFF) { ! 1703: if ((bits64) (aSig<<1)) return propagateFloatx80NaNOneArg(a); ! 1704: return packFloatx80(aSign, 0x7FFF, floatx80_default_infinity_low); ! 1705: } ! 1706: ! 1707: if (aExp == 0 && aSig == 0) { ! 1708: return packFloatx80(aSign, 0, 0); ! 1709: } ! 1710: ! 1711: user_rnd_mode = float_rounding_mode; ! 1712: user_rnd_prec = floatx80_rounding_precision; ! 1713: float_rounding_mode = float_round_nearest_even; ! 1714: floatx80_rounding_precision = 80; ! 1715: ! 1716: compact = floatx80_make_compact(aExp, aSig); ! 1717: ! 1718: if (compact > 0x400CB167) { ! 1719: // SINHBIG ! 1720: if (compact > 0x400CB2B3) { ! 1721: float_rounding_mode = user_rnd_mode; ! 1722: floatx80_rounding_precision = user_rnd_prec; ! 1723: ! 1724: return roundAndPackFloatx80(floatx80_rounding_precision, aSign, 0x8000, aSig, 0); ! 1725: } else { ! 1726: fp0 = floatx80_abs(a); // Y = |X| ! 1727: fp0 = floatx80_sub(fp0, float64_to_floatx80(LIT64(0x40C62D38D3D64634))); // (|X|-16381LOG2_LEAD) ! 1728: fp0 = floatx80_sub(fp0, float64_to_floatx80(LIT64(0x3D6F90AEB1E75CC7))); // |X| - 16381 LOG2, ACCURATE ! 1729: fp0 = floatx80_etox(fp0); ! 1730: fp2 = packFloatx80(aSign, 0x7FFB, one_sig); ! 1731: ! 1732: float_rounding_mode = user_rnd_mode; ! 1733: floatx80_rounding_precision = user_rnd_prec; ! 1734: ! 1735: a = floatx80_mul(fp0, fp2); ! 1736: ! 1737: float_raise(float_flag_inexact); ! 1738: ! 1739: return a; ! 1740: } ! 1741: } else { // |X| < 16380 LOG2 ! 1742: fp0 = floatx80_abs(a); // Y = |X| ! 1743: fp0 = floatx80_etoxm1(fp0); // FP0 IS Z = EXPM1(Y) ! 1744: fp1 = floatx80_add(fp0, float32_to_floatx80(0x3F800000)); // 1+Z ! 1745: fp2 = fp0; ! 1746: fp0 = floatx80_div(fp0, fp1); // Z/(1+Z) ! 1747: fp0 = floatx80_add(fp0, fp2); ! 1748: ! 1749: fact = 0x3F000000; ! 1750: fact |= aSign ? 0x80000000 : 0x00000000; ! 1751: ! 1752: float_rounding_mode = user_rnd_mode; ! 1753: floatx80_rounding_precision = user_rnd_prec; ! 1754: ! 1755: a = floatx80_mul(fp0, float32_to_floatx80(fact)); ! 1756: ! 1757: float_raise(float_flag_inexact); ! 1758: ! 1759: return a; ! 1760: } ! 1761: } ! 1762: ! 1763: /*---------------------------------------------------------------------------- ! 1764: | Tangent ! 1765: *----------------------------------------------------------------------------*/ ! 1766: ! 1767: floatx80 floatx80_tan(floatx80 a) ! 1768: { ! 1769: flag aSign, xSign; ! 1770: int32 aExp, xExp; ! 1771: bits64 aSig, xSig; ! 1772: ! 1773: int8 user_rnd_mode, user_rnd_prec; ! 1774: ! 1775: int32 compact, l, n, j; ! 1776: floatx80 fp0, fp1, fp2, fp3, fp4, fp5, invtwopi, twopi1, twopi2; ! 1777: float32 twoto63; ! 1778: flag endflag; ! 1779: ! 1780: aSig = extractFloatx80Frac(a); ! 1781: aExp = extractFloatx80Exp(a); ! 1782: aSign = extractFloatx80Sign(a); ! 1783: ! 1784: if (aExp == 0x7FFF) { ! 1785: if ((bits64) (aSig<<1)) return propagateFloatx80NaNOneArg(a); ! 1786: float_raise(float_flag_invalid); ! 1787: a.low = floatx80_default_nan_low; ! 1788: a.high = floatx80_default_nan_high; ! 1789: return a; ! 1790: } ! 1791: ! 1792: if (aExp == 0 && aSig == 0) { ! 1793: return packFloatx80(aSign, 0, 0); ! 1794: } ! 1795: ! 1796: user_rnd_mode = float_rounding_mode; ! 1797: user_rnd_prec = floatx80_rounding_precision; ! 1798: float_rounding_mode = float_round_nearest_even; ! 1799: floatx80_rounding_precision = 80; ! 1800: ! 1801: compact = floatx80_make_compact(aExp, aSig); ! 1802: ! 1803: fp0 = a; ! 1804: ! 1805: if (compact < 0x3FD78000 || compact > 0x4004BC7E) { // 2^(-40) > |X| > 15 PI ! 1806: if (compact > 0x3FFF8000) { // |X| >= 15 PI ! 1807: // REDUCEX ! 1808: fp1 = packFloatx80(0, 0, 0); ! 1809: if (compact == 0x7FFEFFFF) { ! 1810: twopi1 = packFloatx80(aSign ^ 1, 0x7FFE, LIT64(0xC90FDAA200000000)); ! 1811: twopi2 = packFloatx80(aSign ^ 1, 0x7FDC, LIT64(0x85A308D300000000)); ! 1812: fp0 = floatx80_add(fp0, twopi1); ! 1813: fp1 = fp0; ! 1814: fp0 = floatx80_add(fp0, twopi2); ! 1815: fp1 = floatx80_sub(fp1, fp0); ! 1816: fp1 = floatx80_add(fp1, twopi2); ! 1817: } ! 1818: loop: ! 1819: xSign = extractFloatx80Sign(fp0); ! 1820: xExp = extractFloatx80Exp(fp0); ! 1821: xExp -= 0x3FFF; ! 1822: if (xExp <= 28) { ! 1823: l = 0; ! 1824: endflag = 1; ! 1825: } else { ! 1826: l = xExp - 27; ! 1827: endflag = 0; ! 1828: } ! 1829: invtwopi = packFloatx80(0, 0x3FFE - l, LIT64(0xA2F9836E4E44152A)); // INVTWOPI ! 1830: twopi1 = packFloatx80(0, 0x3FFF + l, LIT64(0xC90FDAA200000000)); ! 1831: twopi2 = packFloatx80(0, 0x3FDD + l, LIT64(0x85A308D300000000)); ! 1832: ! 1833: twoto63 = 0x5F000000; ! 1834: twoto63 |= xSign ? 0x80000000 : 0x00000000; // SIGN(INARG)*2^63 IN SGL ! 1835: ! 1836: fp2 = floatx80_mul(fp0, invtwopi); ! 1837: fp2 = floatx80_add(fp2, float32_to_floatx80(twoto63)); // THE FRACTIONAL PART OF FP2 IS ROUNDED ! 1838: fp2 = floatx80_sub(fp2, float32_to_floatx80(twoto63)); // FP2 is N ! 1839: fp4 = floatx80_mul(twopi1, fp2); // W = N*P1 ! 1840: fp5 = floatx80_mul(twopi2, fp2); // w = N*P2 ! 1841: fp3 = floatx80_add(fp4, fp5); // FP3 is P ! 1842: fp4 = floatx80_sub(fp4, fp3); // W-P ! 1843: fp0 = floatx80_sub(fp0, fp3); // FP0 is A := R - P ! 1844: fp4 = floatx80_add(fp4, fp5); // FP4 is p = (W-P)+w ! 1845: fp3 = fp0; // FP3 is A ! 1846: fp1 = floatx80_sub(fp1, fp4); // FP1 is a := r - p ! 1847: fp0 = floatx80_add(fp0, fp1); // FP0 is R := A+a ! 1848: ! 1849: if (endflag > 0) { ! 1850: n = floatx80_to_int32(fp2); ! 1851: goto tancont; ! 1852: } ! 1853: fp3 = floatx80_sub(fp3, fp0); // A-R ! 1854: fp1 = floatx80_add(fp1, fp3); // FP1 is r := (A-R)+a ! 1855: goto loop; ! 1856: } else { ! 1857: float_rounding_mode = user_rnd_mode; ! 1858: floatx80_rounding_precision = user_rnd_prec; ! 1859: ! 1860: a = floatx80_move(a); ! 1861: ! 1862: float_raise(float_flag_inexact); ! 1863: ! 1864: return a; ! 1865: } ! 1866: } else { ! 1867: fp1 = floatx80_mul(fp0, float64_to_floatx80(LIT64(0x3FE45F306DC9C883))); // X*2/PI ! 1868: ! 1869: n = floatx80_to_int32(fp1); ! 1870: j = 32 + n; ! 1871: ! 1872: fp0 = floatx80_sub(fp0, pi_tbl[j]); // X-Y1 ! 1873: fp0 = floatx80_sub(fp0, float32_to_floatx80(pi_tbl2[j])); // FP0 IS R = (X-Y1)-Y2 ! 1874: ! 1875: tancont: ! 1876: if (n & 1) { ! 1877: // NODD ! 1878: fp1 = fp0; // R ! 1879: fp0 = floatx80_mul(fp0, fp0); // S = R*R ! 1880: fp3 = float64_to_floatx80(LIT64(0x3EA0B759F50F8688)); // Q4 ! 1881: fp2 = float64_to_floatx80(LIT64(0xBEF2BAA5A8924F04)); // P3 ! 1882: fp3 = floatx80_mul(fp3, fp0); // SQ4 ! 1883: fp2 = floatx80_mul(fp2, fp0); // SP3 ! 1884: fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0xBF346F59B39BA65F))); // Q3+SQ4 ! 1885: fp4 = packFloatx80(0, 0x3FF6, LIT64(0xE073D3FC199C4A00)); ! 1886: fp2 = floatx80_add(fp2, fp4); // P2+SP3 ! 1887: fp3 = floatx80_mul(fp3, fp0); // S(Q3+SQ4) ! 1888: fp2 = floatx80_mul(fp2, fp0); // S(P2+SP3) ! 1889: fp4 = packFloatx80(0, 0x3FF9, LIT64(0xD23CD68415D95FA1)); ! 1890: fp3 = floatx80_add(fp3, fp4); // Q2+S(Q3+SQ4) ! 1891: fp4 = packFloatx80(1, 0x3FFC, LIT64(0x8895A6C5FB423BCA)); ! 1892: fp2 = floatx80_add(fp2, fp4); // P1+S(P2+SP3) ! 1893: fp3 = floatx80_mul(fp3, fp0); // S(Q2+S(Q3+SQ4)) ! 1894: fp2 = floatx80_mul(fp2, fp0); // S(P1+S(P2+SP3)) ! 1895: fp4 = packFloatx80(1, 0x3FFD, LIT64(0xEEF57E0DA84BC8CE)); ! 1896: fp3 = floatx80_add(fp3, fp4); // Q1+S(Q2+S(Q3+SQ4)) ! 1897: fp2 = floatx80_mul(fp2, fp1); // RS(P1+S(P2+SP3)) ! 1898: fp0 = floatx80_mul(fp0, fp3); // S(Q1+S(Q2+S(Q3+SQ4))) ! 1899: fp1 = floatx80_add(fp1, fp2); // R+RS(P1+S(P2+SP3)) ! 1900: fp0 = floatx80_add(fp0, float32_to_floatx80(0x3F800000)); // 1+S(Q1+S(Q2+S(Q3+SQ4))) ! 1901: ! 1902: xSign = extractFloatx80Sign(fp1); ! 1903: xExp = extractFloatx80Exp(fp1); ! 1904: xSig = extractFloatx80Frac(fp1); ! 1905: xSign ^= 1; ! 1906: fp1 = packFloatx80(xSign, xExp, xSig); ! 1907: ! 1908: float_rounding_mode = user_rnd_mode; ! 1909: floatx80_rounding_precision = user_rnd_prec; ! 1910: ! 1911: a = floatx80_div(fp0, fp1); ! 1912: ! 1913: float_raise(float_flag_inexact); ! 1914: ! 1915: return a; ! 1916: } else { ! 1917: fp1 = floatx80_mul(fp0, fp0); // S = R*R ! 1918: fp3 = float64_to_floatx80(LIT64(0x3EA0B759F50F8688)); // Q4 ! 1919: fp2 = float64_to_floatx80(LIT64(0xBEF2BAA5A8924F04)); // P3 ! 1920: fp3 = floatx80_mul(fp3, fp1); // SQ4 ! 1921: fp2 = floatx80_mul(fp2, fp1); // SP3 ! 1922: fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0xBF346F59B39BA65F))); // Q3+SQ4 ! 1923: fp4 = packFloatx80(0, 0x3FF6, LIT64(0xE073D3FC199C4A00)); ! 1924: fp2 = floatx80_add(fp2, fp4); // P2+SP3 ! 1925: fp3 = floatx80_mul(fp3, fp1); // S(Q3+SQ4) ! 1926: fp2 = floatx80_mul(fp2, fp1); // S(P2+SP3) ! 1927: fp4 = packFloatx80(0, 0x3FF9, LIT64(0xD23CD68415D95FA1)); ! 1928: fp3 = floatx80_add(fp3, fp4); // Q2+S(Q3+SQ4) ! 1929: fp4 = packFloatx80(1, 0x3FFC, LIT64(0x8895A6C5FB423BCA)); ! 1930: fp2 = floatx80_add(fp2, fp4); // P1+S(P2+SP3) ! 1931: fp3 = floatx80_mul(fp3, fp1); // S(Q2+S(Q3+SQ4)) ! 1932: fp2 = floatx80_mul(fp2, fp1); // S(P1+S(P2+SP3)) ! 1933: fp4 = packFloatx80(1, 0x3FFD, LIT64(0xEEF57E0DA84BC8CE)); ! 1934: fp3 = floatx80_add(fp3, fp4); // Q1+S(Q2+S(Q3+SQ4)) ! 1935: fp2 = floatx80_mul(fp2, fp0); // RS(P1+S(P2+SP3)) ! 1936: fp1 = floatx80_mul(fp1, fp3); // S(Q1+S(Q2+S(Q3+SQ4))) ! 1937: fp0 = floatx80_add(fp0, fp2); // R+RS(P1+S(P2+SP3)) ! 1938: fp1 = floatx80_add(fp1, float32_to_floatx80(0x3F800000)); // 1+S(Q1+S(Q2+S(Q3+SQ4))) ! 1939: ! 1940: float_rounding_mode = user_rnd_mode; ! 1941: floatx80_rounding_precision = user_rnd_prec; ! 1942: ! 1943: a = floatx80_div(fp0, fp1); ! 1944: ! 1945: float_raise(float_flag_inexact); ! 1946: ! 1947: return a; ! 1948: } ! 1949: } ! 1950: } ! 1951: ! 1952: /*---------------------------------------------------------------------------- ! 1953: | Hyperbolic tangent ! 1954: *----------------------------------------------------------------------------*/ ! 1955: ! 1956: floatx80 floatx80_tanh(floatx80 a) ! 1957: { ! 1958: flag aSign, vSign; ! 1959: int32 aExp, vExp; ! 1960: bits64 aSig, vSig; ! 1961: ! 1962: int8 user_rnd_mode, user_rnd_prec; ! 1963: ! 1964: int32 compact; ! 1965: floatx80 fp0, fp1; ! 1966: float32 sign; ! 1967: ! 1968: aSig = extractFloatx80Frac(a); ! 1969: aExp = extractFloatx80Exp(a); ! 1970: aSign = extractFloatx80Sign(a); ! 1971: ! 1972: if (aExp == 0x7FFF) { ! 1973: if ((bits64) (aSig<<1)) return propagateFloatx80NaNOneArg(a); ! 1974: return packFloatx80(aSign, one_exp, one_sig); ! 1975: } ! 1976: ! 1977: if (aExp == 0 && aSig == 0) { ! 1978: return packFloatx80(aSign, 0, 0); ! 1979: } ! 1980: ! 1981: user_rnd_mode = float_rounding_mode; ! 1982: user_rnd_prec = floatx80_rounding_precision; ! 1983: float_rounding_mode = float_round_nearest_even; ! 1984: floatx80_rounding_precision = 80; ! 1985: ! 1986: compact = floatx80_make_compact(aExp, aSig); ! 1987: ! 1988: if (compact < 0x3FD78000 || compact > 0x3FFFDDCE) { ! 1989: // TANHBORS ! 1990: if (compact < 0x3FFF8000) { ! 1991: // TANHSM ! 1992: float_rounding_mode = user_rnd_mode; ! 1993: floatx80_rounding_precision = user_rnd_prec; ! 1994: ! 1995: a = floatx80_move(a); ! 1996: ! 1997: float_raise(float_flag_inexact); ! 1998: ! 1999: return a; ! 2000: } else { ! 2001: if (compact > 0x40048AA1) { ! 2002: // TANHHUGE ! 2003: sign = 0x3F800000; ! 2004: sign |= aSign ? 0x80000000 : 0x00000000; ! 2005: fp0 = float32_to_floatx80(sign); ! 2006: sign &= 0x80000000; ! 2007: sign ^= 0x80800000; // -SIGN(X)*EPS ! 2008: ! 2009: float_rounding_mode = user_rnd_mode; ! 2010: floatx80_rounding_precision = user_rnd_prec; ! 2011: ! 2012: a = floatx80_add(fp0, float32_to_floatx80(sign)); ! 2013: ! 2014: float_raise(float_flag_inexact); ! 2015: ! 2016: return a; ! 2017: } else { ! 2018: fp0 = packFloatx80(0, aExp+1, aSig); // Y = 2|X| ! 2019: fp0 = floatx80_etox(fp0); // FP0 IS EXP(Y) ! 2020: fp0 = floatx80_add(fp0, float32_to_floatx80(0x3F800000)); // EXP(Y)+1 ! 2021: sign = aSign ? 0x80000000 : 0x00000000; ! 2022: fp1 = floatx80_div(float32_to_floatx80(sign^0xC0000000), fp0); // -SIGN(X)*2 / [EXP(Y)+1] ! 2023: fp0 = float32_to_floatx80(sign | 0x3F800000); // SIGN ! 2024: ! 2025: float_rounding_mode = user_rnd_mode; ! 2026: floatx80_rounding_precision = user_rnd_prec; ! 2027: ! 2028: a = floatx80_add(fp1, fp0); ! 2029: ! 2030: float_raise(float_flag_inexact); ! 2031: ! 2032: return a; ! 2033: } ! 2034: } ! 2035: } else { // 2**(-40) < |X| < (5/2)LOG2 ! 2036: fp0 = packFloatx80(0, aExp+1, aSig); // Y = 2|X| ! 2037: fp0 = floatx80_etoxm1(fp0); // FP0 IS Z = EXPM1(Y) ! 2038: fp1 = floatx80_add(fp0, float32_to_floatx80(0x40000000)); // Z+2 ! 2039: ! 2040: vSign = extractFloatx80Sign(fp1); ! 2041: vExp = extractFloatx80Exp(fp1); ! 2042: vSig = extractFloatx80Frac(fp1); ! 2043: ! 2044: fp1 = packFloatx80(vSign ^ aSign, vExp, vSig); ! 2045: ! 2046: float_rounding_mode = user_rnd_mode; ! 2047: floatx80_rounding_precision = user_rnd_prec; ! 2048: ! 2049: a = floatx80_div(fp0, fp1); ! 2050: ! 2051: float_raise(float_flag_inexact); ! 2052: ! 2053: return a; ! 2054: } ! 2055: } ! 2056: ! 2057: /*---------------------------------------------------------------------------- ! 2058: | 10 to x ! 2059: *----------------------------------------------------------------------------*/ ! 2060: ! 2061: floatx80 floatx80_tentox(floatx80 a) ! 2062: { ! 2063: flag aSign; ! 2064: int32 aExp; ! 2065: bits64 aSig; ! 2066: ! 2067: int8 user_rnd_mode, user_rnd_prec; ! 2068: ! 2069: int32 compact, n, j, l, m, m1; ! 2070: floatx80 fp0, fp1, fp2, fp3, adjfact, fact1, fact2; ! 2071: ! 2072: aSig = extractFloatx80Frac(a); ! 2073: aExp = extractFloatx80Exp(a); ! 2074: aSign = extractFloatx80Sign(a); ! 2075: ! 2076: if (aExp == 0x7FFF) { ! 2077: if ((bits64) (aSig<<1)) return propagateFloatx80NaNOneArg(a); ! 2078: if (aSign) return packFloatx80(0, 0, 0); ! 2079: return packFloatx80(0, 0x7FFF, floatx80_default_infinity_low); ! 2080: } ! 2081: ! 2082: if (aExp == 0 && aSig == 0) { ! 2083: return packFloatx80(0, one_exp, one_sig); ! 2084: } ! 2085: ! 2086: user_rnd_mode = float_rounding_mode; ! 2087: user_rnd_prec = floatx80_rounding_precision; ! 2088: float_rounding_mode = float_round_nearest_even; ! 2089: floatx80_rounding_precision = 80; ! 2090: ! 2091: fp0 = a; ! 2092: ! 2093: compact = floatx80_make_compact(aExp, aSig); ! 2094: ! 2095: if (compact < 0x3FB98000 || compact > 0x400B9B07) { // |X| > 16480 LOG2/LOG10 or |X| < 2^(-70) ! 2096: if (compact > 0x3FFF8000) { // |X| > 16480 ! 2097: float_rounding_mode = user_rnd_mode; ! 2098: floatx80_rounding_precision = user_rnd_prec; ! 2099: ! 2100: if (aSign) { ! 2101: return roundAndPackFloatx80(floatx80_rounding_precision, 0, -0x1000, aSig, 0); ! 2102: } else { ! 2103: return roundAndPackFloatx80(floatx80_rounding_precision, 0, 0x8000, aSig, 0); ! 2104: } ! 2105: } else { // |X| < 2^(-70) ! 2106: float_rounding_mode = user_rnd_mode; ! 2107: floatx80_rounding_precision = user_rnd_prec; ! 2108: ! 2109: a = floatx80_add(fp0, float32_to_floatx80(0x3F800000)); // 1 + X ! 2110: ! 2111: float_raise(float_flag_inexact); ! 2112: ! 2113: return a; ! 2114: } ! 2115: } else { // 2^(-70) <= |X| <= 16480 LOG 2 / LOG 10 ! 2116: fp1 = fp0; // X ! 2117: fp1 = floatx80_mul(fp1, float64_to_floatx80(LIT64(0x406A934F0979A371))); // X*64*LOG10/LOG2 ! 2118: n = floatx80_to_int32(fp1); // N=INT(X*64*LOG10/LOG2) ! 2119: fp1 = int32_to_floatx80(n); ! 2120: ! 2121: j = n & 0x3F; ! 2122: l = n / 64; // NOTE: this is really arithmetic right shift by 6 ! 2123: if (n < 0 && j) { // arithmetic right shift is division and round towards minus infinity ! 2124: l--; ! 2125: } ! 2126: m = l / 2; // NOTE: this is really arithmetic right shift by 1 ! 2127: if (l < 0 && (l & 1)) { // arithmetic right shift is division and round towards minus infinity ! 2128: m--; ! 2129: } ! 2130: m1 = l - m; ! 2131: m1 += 0x3FFF; // ADJFACT IS 2^(M') ! 2132: ! 2133: adjfact = packFloatx80(0, m1, one_sig); ! 2134: fact1 = exp2_tbl[j]; ! 2135: fact1.high += m; ! 2136: fact2.high = exp2_tbl2[j]>>16; ! 2137: fact2.high += m; ! 2138: fact2.low = (bits64)(exp2_tbl2[j] & 0xFFFF); ! 2139: fact2.low <<= 48; ! 2140: ! 2141: fp2 = fp1; // N ! 2142: fp1 = floatx80_mul(fp1, float64_to_floatx80(LIT64(0x3F734413509F8000))); // N*(LOG2/64LOG10)_LEAD ! 2143: fp3 = packFloatx80(1, 0x3FCD, LIT64(0xC0219DC1DA994FD2)); ! 2144: fp2 = floatx80_mul(fp2, fp3); // N*(LOG2/64LOG10)_TRAIL ! 2145: fp0 = floatx80_sub(fp0, fp1); // X - N L_LEAD ! 2146: fp0 = floatx80_sub(fp0, fp2); // X - N L_TRAIL ! 2147: fp2 = packFloatx80(0, 0x4000, LIT64(0x935D8DDDAAA8AC17)); // LOG10 ! 2148: fp0 = floatx80_mul(fp0, fp2); // R ! 2149: ! 2150: // EXPR ! 2151: fp1 = floatx80_mul(fp0, fp0); // S = R*R ! 2152: fp2 = float64_to_floatx80(LIT64(0x3F56C16D6F7BD0B2)); // A5 ! 2153: fp3 = float64_to_floatx80(LIT64(0x3F811112302C712C)); // A4 ! 2154: fp2 = floatx80_mul(fp2, fp1); // S*A5 ! 2155: fp3 = floatx80_mul(fp3, fp1); // S*A4 ! 2156: fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3FA5555555554CC1))); // A3+S*A5 ! 2157: fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0x3FC5555555554A54))); // A2+S*A4 ! 2158: fp2 = floatx80_mul(fp2, fp1); // S*(A3+S*A5) ! 2159: fp3 = floatx80_mul(fp3, fp1); // S*(A2+S*A4) ! 2160: fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3FE0000000000000))); // A1+S*(A3+S*A5) ! 2161: fp3 = floatx80_mul(fp3, fp0); // R*S*(A2+S*A4) ! 2162: ! 2163: fp2 = floatx80_mul(fp2, fp1); // S*(A1+S*(A3+S*A5)) ! 2164: fp0 = floatx80_add(fp0, fp3); // R+R*S*(A2+S*A4) ! 2165: fp0 = floatx80_add(fp0, fp2); // EXP(R) - 1 ! 2166: ! 2167: fp0 = floatx80_mul(fp0, fact1); ! 2168: fp0 = floatx80_add(fp0, fact2); ! 2169: fp0 = floatx80_add(fp0, fact1); ! 2170: ! 2171: float_rounding_mode = user_rnd_mode; ! 2172: floatx80_rounding_precision = user_rnd_prec; ! 2173: ! 2174: a = floatx80_mul(fp0, adjfact); ! 2175: ! 2176: float_raise(float_flag_inexact); ! 2177: ! 2178: return a; ! 2179: } ! 2180: } ! 2181: ! 2182: /*---------------------------------------------------------------------------- ! 2183: | 2 to x ! 2184: *----------------------------------------------------------------------------*/ ! 2185: ! 2186: floatx80 floatx80_twotox(floatx80 a) ! 2187: { ! 2188: flag aSign; ! 2189: int32 aExp; ! 2190: bits64 aSig; ! 2191: ! 2192: int8 user_rnd_mode, user_rnd_prec; ! 2193: ! 2194: int32 compact, n, j, l, m, m1; ! 2195: floatx80 fp0, fp1, fp2, fp3, adjfact, fact1, fact2; ! 2196: ! 2197: aSig = extractFloatx80Frac(a); ! 2198: aExp = extractFloatx80Exp(a); ! 2199: aSign = extractFloatx80Sign(a); ! 2200: ! 2201: if (aExp == 0x7FFF) { ! 2202: if ((bits64) (aSig<<1)) return propagateFloatx80NaNOneArg(a); ! 2203: if (aSign) return packFloatx80(0, 0, 0); ! 2204: return packFloatx80(0, 0x7FFF, floatx80_default_infinity_low); ! 2205: } ! 2206: ! 2207: if (aExp == 0 && aSig == 0) { ! 2208: return packFloatx80(0, one_exp, one_sig); ! 2209: } ! 2210: ! 2211: user_rnd_mode = float_rounding_mode; ! 2212: user_rnd_prec = floatx80_rounding_precision; ! 2213: float_rounding_mode = float_round_nearest_even; ! 2214: floatx80_rounding_precision = 80; ! 2215: ! 2216: fp0 = a; ! 2217: ! 2218: compact = floatx80_make_compact(aExp, aSig); ! 2219: ! 2220: if (compact < 0x3FB98000 || compact > 0x400D80C0) { // |X| > 16480 or |X| < 2^(-70) ! 2221: if (compact > 0x3FFF8000) { // |X| > 16480 ! 2222: float_rounding_mode = user_rnd_mode; ! 2223: floatx80_rounding_precision = user_rnd_prec; ! 2224: ! 2225: if (aSign) { ! 2226: return roundAndPackFloatx80(floatx80_rounding_precision, 0, -0x1000, aSig, 0); ! 2227: } else { ! 2228: return roundAndPackFloatx80(floatx80_rounding_precision, 0, 0x8000, aSig, 0); ! 2229: } ! 2230: } else { // |X| < 2^(-70) ! 2231: float_rounding_mode = user_rnd_mode; ! 2232: floatx80_rounding_precision = user_rnd_prec; ! 2233: ! 2234: a = floatx80_add(fp0, float32_to_floatx80(0x3F800000)); // 1 + X ! 2235: ! 2236: float_raise(float_flag_inexact); ! 2237: ! 2238: return a; ! 2239: } ! 2240: } else { // 2^(-70) <= |X| <= 16480 ! 2241: fp1 = fp0; // X ! 2242: fp1 = floatx80_mul(fp1, float32_to_floatx80(0x42800000)); // X * 64 ! 2243: n = floatx80_to_int32(fp1); ! 2244: fp1 = int32_to_floatx80(n); ! 2245: j = n & 0x3F; ! 2246: l = n / 64; // NOTE: this is really arithmetic right shift by 6 ! 2247: if (n < 0 && j) { // arithmetic right shift is division and round towards minus infinity ! 2248: l--; ! 2249: } ! 2250: m = l / 2; // NOTE: this is really arithmetic right shift by 1 ! 2251: if (l < 0 && (l & 1)) { // arithmetic right shift is division and round towards minus infinity ! 2252: m--; ! 2253: } ! 2254: m1 = l - m; ! 2255: m1 += 0x3FFF; // ADJFACT IS 2^(M') ! 2256: ! 2257: adjfact = packFloatx80(0, m1, one_sig); ! 2258: fact1 = exp2_tbl[j]; ! 2259: fact1.high += m; ! 2260: fact2.high = exp2_tbl2[j]>>16; ! 2261: fact2.high += m; ! 2262: fact2.low = (bits64)(exp2_tbl2[j] & 0xFFFF); ! 2263: fact2.low <<= 48; ! 2264: ! 2265: fp1 = floatx80_mul(fp1, float32_to_floatx80(0x3C800000)); // (1/64)*N ! 2266: fp0 = floatx80_sub(fp0, fp1); // X - (1/64)*INT(64 X) ! 2267: fp2 = packFloatx80(0, 0x3FFE, LIT64(0xB17217F7D1CF79AC)); // LOG2 ! 2268: fp0 = floatx80_mul(fp0, fp2); // R ! 2269: ! 2270: // EXPR ! 2271: fp1 = floatx80_mul(fp0, fp0); // S = R*R ! 2272: fp2 = float64_to_floatx80(LIT64(0x3F56C16D6F7BD0B2)); // A5 ! 2273: fp3 = float64_to_floatx80(LIT64(0x3F811112302C712C)); // A4 ! 2274: fp2 = floatx80_mul(fp2, fp1); // S*A5 ! 2275: fp3 = floatx80_mul(fp3, fp1); // S*A4 ! 2276: fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3FA5555555554CC1))); // A3+S*A5 ! 2277: fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0x3FC5555555554A54))); // A2+S*A4 ! 2278: fp2 = floatx80_mul(fp2, fp1); // S*(A3+S*A5) ! 2279: fp3 = floatx80_mul(fp3, fp1); // S*(A2+S*A4) ! 2280: fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3FE0000000000000))); // A1+S*(A3+S*A5) ! 2281: fp3 = floatx80_mul(fp3, fp0); // R*S*(A2+S*A4) ! 2282: ! 2283: fp2 = floatx80_mul(fp2, fp1); // S*(A1+S*(A3+S*A5)) ! 2284: fp0 = floatx80_add(fp0, fp3); // R+R*S*(A2+S*A4) ! 2285: fp0 = floatx80_add(fp0, fp2); // EXP(R) - 1 ! 2286: ! 2287: fp0 = floatx80_mul(fp0, fact1); ! 2288: fp0 = floatx80_add(fp0, fact2); ! 2289: fp0 = floatx80_add(fp0, fact1); ! 2290: ! 2291: float_rounding_mode = user_rnd_mode; ! 2292: floatx80_rounding_precision = user_rnd_prec; ! 2293: ! 2294: a = floatx80_mul(fp0, adjfact); ! 2295: ! 2296: float_raise(float_flag_inexact); ! 2297: ! 2298: return a; ! 2299: } ! 2300: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.