|
|
1.1 ! root 1: ! 2: /*============================================================================ ! 3: ! 4: This C source file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic ! 5: Package, Release 2b. ! 6: ! 7: Written by John R. Hauser. This work was made possible in part by the ! 8: International Computer Science Institute, located at Suite 600, 1947 Center ! 9: Street, Berkeley, California 94704. Funding was partially provided by the ! 10: National Science Foundation under grant MIP-9311980. The original version ! 11: of this code was written as part of a project to build a fixed-point vector ! 12: processor in collaboration with the University of California at Berkeley, ! 13: overseen by Profs. Nelson Morgan and John Wawrzynek. More information ! 14: is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ ! 15: arithmetic/SoftFloat.html'. ! 16: ! 17: THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has ! 18: been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES ! 19: RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS ! 20: AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, ! 21: COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE ! 22: EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE ! 23: INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR ! 24: OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. ! 25: ! 26: Derivative works are acceptable, even for commercial purposes, so long as ! 27: (1) the source code for the derivative work includes prominent notice that ! 28: the work is derivative, and (2) the source code includes prominent notice with ! 29: these four paragraphs for those parts of this code that are retained. ! 30: ! 31: =============================================================================*/ ! 32: ! 33: #include "softfloat.h" ! 34: ! 35: /*---------------------------------------------------------------------------- ! 36: | Primitive arithmetic functions, including multi-word arithmetic, and ! 37: | division and square root approximations. (Can be specialized to target if ! 38: | desired.) ! 39: *----------------------------------------------------------------------------*/ ! 40: #include "softfloat-macros.h" ! 41: ! 42: /*---------------------------------------------------------------------------- ! 43: | Functions and definitions to determine: (1) whether tininess for underflow ! 44: | is detected before or after rounding by default, (2) what (if anything) ! 45: | happens when exceptions are raised, (3) how signaling NaNs are distinguished ! 46: | from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs ! 47: | are propagated from function inputs to output. These details are target- ! 48: | specific. ! 49: *----------------------------------------------------------------------------*/ ! 50: #include "softfloat-specialize.h" ! 51: ! 52: void set_float_rounding_mode(int val STATUS_PARAM) ! 53: { ! 54: STATUS(float_rounding_mode) = val; ! 55: } ! 56: ! 57: void set_float_exception_flags(int val STATUS_PARAM) ! 58: { ! 59: STATUS(float_exception_flags) = val; ! 60: } ! 61: ! 62: #ifdef FLOATX80 ! 63: void set_floatx80_rounding_precision(int val STATUS_PARAM) ! 64: { ! 65: STATUS(floatx80_rounding_precision) = val; ! 66: } ! 67: #endif ! 68: ! 69: /*---------------------------------------------------------------------------- ! 70: | Takes a 64-bit fixed-point value `absZ' with binary point between bits 6 ! 71: | and 7, and returns the properly rounded 32-bit integer corresponding to the ! 72: | input. If `zSign' is 1, the input is negated before being converted to an ! 73: | integer. Bit 63 of `absZ' must be zero. Ordinarily, the fixed-point input ! 74: | is simply rounded to an integer, with the inexact exception raised if the ! 75: | input cannot be represented exactly as an integer. However, if the fixed- ! 76: | point input is too large, the invalid exception is raised and the largest ! 77: | positive or negative integer is returned. ! 78: *----------------------------------------------------------------------------*/ ! 79: ! 80: static int32 roundAndPackInt32( flag zSign, bits64 absZ STATUS_PARAM) ! 81: { ! 82: int8 roundingMode; ! 83: flag roundNearestEven; ! 84: int8 roundIncrement, roundBits; ! 85: int32 z; ! 86: ! 87: roundingMode = STATUS(float_rounding_mode); ! 88: roundNearestEven = ( roundingMode == float_round_nearest_even ); ! 89: roundIncrement = 0x40; ! 90: if ( ! roundNearestEven ) { ! 91: if ( roundingMode == float_round_to_zero ) { ! 92: roundIncrement = 0; ! 93: } ! 94: else { ! 95: roundIncrement = 0x7F; ! 96: if ( zSign ) { ! 97: if ( roundingMode == float_round_up ) roundIncrement = 0; ! 98: } ! 99: else { ! 100: if ( roundingMode == float_round_down ) roundIncrement = 0; ! 101: } ! 102: } ! 103: } ! 104: roundBits = absZ & 0x7F; ! 105: absZ = ( absZ + roundIncrement )>>7; ! 106: absZ &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven ); ! 107: z = absZ; ! 108: if ( zSign ) z = - z; ! 109: if ( ( absZ>>32 ) || ( z && ( ( z < 0 ) ^ zSign ) ) ) { ! 110: float_raise( float_flag_invalid STATUS_VAR); ! 111: return zSign ? (sbits32) 0x80000000 : 0x7FFFFFFF; ! 112: } ! 113: if ( roundBits ) STATUS(float_exception_flags) |= float_flag_inexact; ! 114: return z; ! 115: ! 116: } ! 117: ! 118: /*---------------------------------------------------------------------------- ! 119: | Takes the 128-bit fixed-point value formed by concatenating `absZ0' and ! 120: | `absZ1', with binary point between bits 63 and 64 (between the input words), ! 121: | and returns the properly rounded 64-bit integer corresponding to the input. ! 122: | If `zSign' is 1, the input is negated before being converted to an integer. ! 123: | Ordinarily, the fixed-point input is simply rounded to an integer, with ! 124: | the inexact exception raised if the input cannot be represented exactly as ! 125: | an integer. However, if the fixed-point input is too large, the invalid ! 126: | exception is raised and the largest positive or negative integer is ! 127: | returned. ! 128: *----------------------------------------------------------------------------*/ ! 129: ! 130: static int64 roundAndPackInt64( flag zSign, bits64 absZ0, bits64 absZ1 STATUS_PARAM) ! 131: { ! 132: int8 roundingMode; ! 133: flag roundNearestEven, increment; ! 134: int64 z; ! 135: ! 136: roundingMode = STATUS(float_rounding_mode); ! 137: roundNearestEven = ( roundingMode == float_round_nearest_even ); ! 138: increment = ( (sbits64) absZ1 < 0 ); ! 139: if ( ! roundNearestEven ) { ! 140: if ( roundingMode == float_round_to_zero ) { ! 141: increment = 0; ! 142: } ! 143: else { ! 144: if ( zSign ) { ! 145: increment = ( roundingMode == float_round_down ) && absZ1; ! 146: } ! 147: else { ! 148: increment = ( roundingMode == float_round_up ) && absZ1; ! 149: } ! 150: } ! 151: } ! 152: if ( increment ) { ! 153: ++absZ0; ! 154: if ( absZ0 == 0 ) goto overflow; ! 155: absZ0 &= ~ ( ( (bits64) ( absZ1<<1 ) == 0 ) & roundNearestEven ); ! 156: } ! 157: z = absZ0; ! 158: if ( zSign ) z = - z; ! 159: if ( z && ( ( z < 0 ) ^ zSign ) ) { ! 160: overflow: ! 161: float_raise( float_flag_invalid STATUS_VAR); ! 162: return ! 163: zSign ? (sbits64) LIT64( 0x8000000000000000 ) ! 164: : LIT64( 0x7FFFFFFFFFFFFFFF ); ! 165: } ! 166: if ( absZ1 ) STATUS(float_exception_flags) |= float_flag_inexact; ! 167: return z; ! 168: ! 169: } ! 170: ! 171: /*---------------------------------------------------------------------------- ! 172: | Returns the fraction bits of the single-precision floating-point value `a'. ! 173: *----------------------------------------------------------------------------*/ ! 174: ! 175: INLINE bits32 extractFloat32Frac( float32 a ) ! 176: { ! 177: ! 178: return a & 0x007FFFFF; ! 179: ! 180: } ! 181: ! 182: /*---------------------------------------------------------------------------- ! 183: | Returns the exponent bits of the single-precision floating-point value `a'. ! 184: *----------------------------------------------------------------------------*/ ! 185: ! 186: INLINE int16 extractFloat32Exp( float32 a ) ! 187: { ! 188: ! 189: return ( a>>23 ) & 0xFF; ! 190: ! 191: } ! 192: ! 193: /*---------------------------------------------------------------------------- ! 194: | Returns the sign bit of the single-precision floating-point value `a'. ! 195: *----------------------------------------------------------------------------*/ ! 196: ! 197: INLINE flag extractFloat32Sign( float32 a ) ! 198: { ! 199: ! 200: return a>>31; ! 201: ! 202: } ! 203: ! 204: /*---------------------------------------------------------------------------- ! 205: | Normalizes the subnormal single-precision floating-point value represented ! 206: | by the denormalized significand `aSig'. The normalized exponent and ! 207: | significand are stored at the locations pointed to by `zExpPtr' and ! 208: | `zSigPtr', respectively. ! 209: *----------------------------------------------------------------------------*/ ! 210: ! 211: static void ! 212: normalizeFloat32Subnormal( bits32 aSig, int16 *zExpPtr, bits32 *zSigPtr ) ! 213: { ! 214: int8 shiftCount; ! 215: ! 216: shiftCount = countLeadingZeros32( aSig ) - 8; ! 217: *zSigPtr = aSig<<shiftCount; ! 218: *zExpPtr = 1 - shiftCount; ! 219: ! 220: } ! 221: ! 222: /*---------------------------------------------------------------------------- ! 223: | Packs the sign `zSign', exponent `zExp', and significand `zSig' into a ! 224: | single-precision floating-point value, returning the result. After being ! 225: | shifted into the proper positions, the three fields are simply added ! 226: | together to form the result. This means that any integer portion of `zSig' ! 227: | will be added into the exponent. Since a properly normalized significand ! 228: | will have an integer portion equal to 1, the `zExp' input should be 1 less ! 229: | than the desired result exponent whenever `zSig' is a complete, normalized ! 230: | significand. ! 231: *----------------------------------------------------------------------------*/ ! 232: ! 233: INLINE float32 packFloat32( flag zSign, int16 zExp, bits32 zSig ) ! 234: { ! 235: ! 236: return ( ( (bits32) zSign )<<31 ) + ( ( (bits32) zExp )<<23 ) + zSig; ! 237: ! 238: } ! 239: ! 240: /*---------------------------------------------------------------------------- ! 241: | Takes an abstract floating-point value having sign `zSign', exponent `zExp', ! 242: | and significand `zSig', and returns the proper single-precision floating- ! 243: | point value corresponding to the abstract input. Ordinarily, the abstract ! 244: | value is simply rounded and packed into the single-precision format, with ! 245: | the inexact exception raised if the abstract input cannot be represented ! 246: | exactly. However, if the abstract value is too large, the overflow and ! 247: | inexact exceptions are raised and an infinity or maximal finite value is ! 248: | returned. If the abstract value is too small, the input value is rounded to ! 249: | a subnormal number, and the underflow and inexact exceptions are raised if ! 250: | the abstract input cannot be represented exactly as a subnormal single- ! 251: | precision floating-point number. ! 252: | The input significand `zSig' has its binary point between bits 30 ! 253: | and 29, which is 7 bits to the left of the usual location. This shifted ! 254: | significand must be normalized or smaller. If `zSig' is not normalized, ! 255: | `zExp' must be 0; in that case, the result returned is a subnormal number, ! 256: | and it must not require rounding. In the usual case that `zSig' is ! 257: | normalized, `zExp' must be 1 less than the ``true'' floating-point exponent. ! 258: | The handling of underflow and overflow follows the IEC/IEEE Standard for ! 259: | Binary Floating-Point Arithmetic. ! 260: *----------------------------------------------------------------------------*/ ! 261: ! 262: static float32 roundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig STATUS_PARAM) ! 263: { ! 264: int8 roundingMode; ! 265: flag roundNearestEven; ! 266: int8 roundIncrement, roundBits; ! 267: flag isTiny; ! 268: ! 269: roundingMode = STATUS(float_rounding_mode); ! 270: roundNearestEven = ( roundingMode == float_round_nearest_even ); ! 271: roundIncrement = 0x40; ! 272: if ( ! roundNearestEven ) { ! 273: if ( roundingMode == float_round_to_zero ) { ! 274: roundIncrement = 0; ! 275: } ! 276: else { ! 277: roundIncrement = 0x7F; ! 278: if ( zSign ) { ! 279: if ( roundingMode == float_round_up ) roundIncrement = 0; ! 280: } ! 281: else { ! 282: if ( roundingMode == float_round_down ) roundIncrement = 0; ! 283: } ! 284: } ! 285: } ! 286: roundBits = zSig & 0x7F; ! 287: if ( 0xFD <= (bits16) zExp ) { ! 288: if ( ( 0xFD < zExp ) ! 289: || ( ( zExp == 0xFD ) ! 290: && ( (sbits32) ( zSig + roundIncrement ) < 0 ) ) ! 291: ) { ! 292: float_raise( float_flag_overflow | float_flag_inexact STATUS_VAR); ! 293: return packFloat32( zSign, 0xFF, 0 ) - ( roundIncrement == 0 ); ! 294: } ! 295: if ( zExp < 0 ) { ! 296: isTiny = ! 297: ( STATUS(float_detect_tininess) == float_tininess_before_rounding ) ! 298: || ( zExp < -1 ) ! 299: || ( zSig + roundIncrement < 0x80000000 ); ! 300: shift32RightJamming( zSig, - zExp, &zSig ); ! 301: zExp = 0; ! 302: roundBits = zSig & 0x7F; ! 303: if ( isTiny && roundBits ) float_raise( float_flag_underflow STATUS_VAR); ! 304: } ! 305: } ! 306: if ( roundBits ) STATUS(float_exception_flags) |= float_flag_inexact; ! 307: zSig = ( zSig + roundIncrement )>>7; ! 308: zSig &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven ); ! 309: if ( zSig == 0 ) zExp = 0; ! 310: return packFloat32( zSign, zExp, zSig ); ! 311: ! 312: } ! 313: ! 314: /*---------------------------------------------------------------------------- ! 315: | Takes an abstract floating-point value having sign `zSign', exponent `zExp', ! 316: | and significand `zSig', and returns the proper single-precision floating- ! 317: | point value corresponding to the abstract input. This routine is just like ! 318: | `roundAndPackFloat32' except that `zSig' does not have to be normalized. ! 319: | Bit 31 of `zSig' must be zero, and `zExp' must be 1 less than the ``true'' ! 320: | floating-point exponent. ! 321: *----------------------------------------------------------------------------*/ ! 322: ! 323: static float32 ! 324: normalizeRoundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig STATUS_PARAM) ! 325: { ! 326: int8 shiftCount; ! 327: ! 328: shiftCount = countLeadingZeros32( zSig ) - 1; ! 329: return roundAndPackFloat32( zSign, zExp - shiftCount, zSig<<shiftCount STATUS_VAR); ! 330: ! 331: } ! 332: ! 333: /*---------------------------------------------------------------------------- ! 334: | Returns the fraction bits of the double-precision floating-point value `a'. ! 335: *----------------------------------------------------------------------------*/ ! 336: ! 337: INLINE bits64 extractFloat64Frac( float64 a ) ! 338: { ! 339: ! 340: return a & LIT64( 0x000FFFFFFFFFFFFF ); ! 341: ! 342: } ! 343: ! 344: /*---------------------------------------------------------------------------- ! 345: | Returns the exponent bits of the double-precision floating-point value `a'. ! 346: *----------------------------------------------------------------------------*/ ! 347: ! 348: INLINE int16 extractFloat64Exp( float64 a ) ! 349: { ! 350: ! 351: return ( a>>52 ) & 0x7FF; ! 352: ! 353: } ! 354: ! 355: /*---------------------------------------------------------------------------- ! 356: | Returns the sign bit of the double-precision floating-point value `a'. ! 357: *----------------------------------------------------------------------------*/ ! 358: ! 359: INLINE flag extractFloat64Sign( float64 a ) ! 360: { ! 361: ! 362: return a>>63; ! 363: ! 364: } ! 365: ! 366: /*---------------------------------------------------------------------------- ! 367: | Normalizes the subnormal double-precision floating-point value represented ! 368: | by the denormalized significand `aSig'. The normalized exponent and ! 369: | significand are stored at the locations pointed to by `zExpPtr' and ! 370: | `zSigPtr', respectively. ! 371: *----------------------------------------------------------------------------*/ ! 372: ! 373: static void ! 374: normalizeFloat64Subnormal( bits64 aSig, int16 *zExpPtr, bits64 *zSigPtr ) ! 375: { ! 376: int8 shiftCount; ! 377: ! 378: shiftCount = countLeadingZeros64( aSig ) - 11; ! 379: *zSigPtr = aSig<<shiftCount; ! 380: *zExpPtr = 1 - shiftCount; ! 381: ! 382: } ! 383: ! 384: /*---------------------------------------------------------------------------- ! 385: | Packs the sign `zSign', exponent `zExp', and significand `zSig' into a ! 386: | double-precision floating-point value, returning the result. After being ! 387: | shifted into the proper positions, the three fields are simply added ! 388: | together to form the result. This means that any integer portion of `zSig' ! 389: | will be added into the exponent. Since a properly normalized significand ! 390: | will have an integer portion equal to 1, the `zExp' input should be 1 less ! 391: | than the desired result exponent whenever `zSig' is a complete, normalized ! 392: | significand. ! 393: *----------------------------------------------------------------------------*/ ! 394: ! 395: INLINE float64 packFloat64( flag zSign, int16 zExp, bits64 zSig ) ! 396: { ! 397: ! 398: return ( ( (bits64) zSign )<<63 ) + ( ( (bits64) zExp )<<52 ) + zSig; ! 399: ! 400: } ! 401: ! 402: /*---------------------------------------------------------------------------- ! 403: | Takes an abstract floating-point value having sign `zSign', exponent `zExp', ! 404: | and significand `zSig', and returns the proper double-precision floating- ! 405: | point value corresponding to the abstract input. Ordinarily, the abstract ! 406: | value is simply rounded and packed into the double-precision format, with ! 407: | the inexact exception raised if the abstract input cannot be represented ! 408: | exactly. However, if the abstract value is too large, the overflow and ! 409: | inexact exceptions are raised and an infinity or maximal finite value is ! 410: | returned. If the abstract value is too small, the input value is rounded ! 411: | to a subnormal number, and the underflow and inexact exceptions are raised ! 412: | if the abstract input cannot be represented exactly as a subnormal double- ! 413: | precision floating-point number. ! 414: | The input significand `zSig' has its binary point between bits 62 ! 415: | and 61, which is 10 bits to the left of the usual location. This shifted ! 416: | significand must be normalized or smaller. If `zSig' is not normalized, ! 417: | `zExp' must be 0; in that case, the result returned is a subnormal number, ! 418: | and it must not require rounding. In the usual case that `zSig' is ! 419: | normalized, `zExp' must be 1 less than the ``true'' floating-point exponent. ! 420: | The handling of underflow and overflow follows the IEC/IEEE Standard for ! 421: | Binary Floating-Point Arithmetic. ! 422: *----------------------------------------------------------------------------*/ ! 423: ! 424: static float64 roundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig STATUS_PARAM) ! 425: { ! 426: int8 roundingMode; ! 427: flag roundNearestEven; ! 428: int16 roundIncrement, roundBits; ! 429: flag isTiny; ! 430: ! 431: roundingMode = STATUS(float_rounding_mode); ! 432: roundNearestEven = ( roundingMode == float_round_nearest_even ); ! 433: roundIncrement = 0x200; ! 434: if ( ! roundNearestEven ) { ! 435: if ( roundingMode == float_round_to_zero ) { ! 436: roundIncrement = 0; ! 437: } ! 438: else { ! 439: roundIncrement = 0x3FF; ! 440: if ( zSign ) { ! 441: if ( roundingMode == float_round_up ) roundIncrement = 0; ! 442: } ! 443: else { ! 444: if ( roundingMode == float_round_down ) roundIncrement = 0; ! 445: } ! 446: } ! 447: } ! 448: roundBits = zSig & 0x3FF; ! 449: if ( 0x7FD <= (bits16) zExp ) { ! 450: if ( ( 0x7FD < zExp ) ! 451: || ( ( zExp == 0x7FD ) ! 452: && ( (sbits64) ( zSig + roundIncrement ) < 0 ) ) ! 453: ) { ! 454: float_raise( float_flag_overflow | float_flag_inexact STATUS_VAR); ! 455: return packFloat64( zSign, 0x7FF, 0 ) - ( roundIncrement == 0 ); ! 456: } ! 457: if ( zExp < 0 ) { ! 458: isTiny = ! 459: ( STATUS(float_detect_tininess) == float_tininess_before_rounding ) ! 460: || ( zExp < -1 ) ! 461: || ( zSig + roundIncrement < LIT64( 0x8000000000000000 ) ); ! 462: shift64RightJamming( zSig, - zExp, &zSig ); ! 463: zExp = 0; ! 464: roundBits = zSig & 0x3FF; ! 465: if ( isTiny && roundBits ) float_raise( float_flag_underflow STATUS_VAR); ! 466: } ! 467: } ! 468: if ( roundBits ) STATUS(float_exception_flags) |= float_flag_inexact; ! 469: zSig = ( zSig + roundIncrement )>>10; ! 470: zSig &= ~ ( ( ( roundBits ^ 0x200 ) == 0 ) & roundNearestEven ); ! 471: if ( zSig == 0 ) zExp = 0; ! 472: return packFloat64( zSign, zExp, zSig ); ! 473: ! 474: } ! 475: ! 476: /*---------------------------------------------------------------------------- ! 477: | Takes an abstract floating-point value having sign `zSign', exponent `zExp', ! 478: | and significand `zSig', and returns the proper double-precision floating- ! 479: | point value corresponding to the abstract input. This routine is just like ! 480: | `roundAndPackFloat64' except that `zSig' does not have to be normalized. ! 481: | Bit 63 of `zSig' must be zero, and `zExp' must be 1 less than the ``true'' ! 482: | floating-point exponent. ! 483: *----------------------------------------------------------------------------*/ ! 484: ! 485: static float64 ! 486: normalizeRoundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig STATUS_PARAM) ! 487: { ! 488: int8 shiftCount; ! 489: ! 490: shiftCount = countLeadingZeros64( zSig ) - 1; ! 491: return roundAndPackFloat64( zSign, zExp - shiftCount, zSig<<shiftCount STATUS_VAR); ! 492: ! 493: } ! 494: ! 495: #ifdef FLOATX80 ! 496: ! 497: /*---------------------------------------------------------------------------- ! 498: | Returns the fraction bits of the extended double-precision floating-point ! 499: | value `a'. ! 500: *----------------------------------------------------------------------------*/ ! 501: ! 502: INLINE bits64 extractFloatx80Frac( floatx80 a ) ! 503: { ! 504: ! 505: return a.low; ! 506: ! 507: } ! 508: ! 509: /*---------------------------------------------------------------------------- ! 510: | Returns the exponent bits of the extended double-precision floating-point ! 511: | value `a'. ! 512: *----------------------------------------------------------------------------*/ ! 513: ! 514: INLINE int32 extractFloatx80Exp( floatx80 a ) ! 515: { ! 516: ! 517: return a.high & 0x7FFF; ! 518: ! 519: } ! 520: ! 521: /*---------------------------------------------------------------------------- ! 522: | Returns the sign bit of the extended double-precision floating-point value ! 523: | `a'. ! 524: *----------------------------------------------------------------------------*/ ! 525: ! 526: INLINE flag extractFloatx80Sign( floatx80 a ) ! 527: { ! 528: ! 529: return a.high>>15; ! 530: ! 531: } ! 532: ! 533: /*---------------------------------------------------------------------------- ! 534: | Normalizes the subnormal extended double-precision floating-point value ! 535: | represented by the denormalized significand `aSig'. The normalized exponent ! 536: | and significand are stored at the locations pointed to by `zExpPtr' and ! 537: | `zSigPtr', respectively. ! 538: *----------------------------------------------------------------------------*/ ! 539: ! 540: static void ! 541: normalizeFloatx80Subnormal( bits64 aSig, int32 *zExpPtr, bits64 *zSigPtr ) ! 542: { ! 543: int8 shiftCount; ! 544: ! 545: shiftCount = countLeadingZeros64( aSig ); ! 546: *zSigPtr = aSig<<shiftCount; ! 547: *zExpPtr = 1 - shiftCount; ! 548: ! 549: } ! 550: ! 551: /*---------------------------------------------------------------------------- ! 552: | Packs the sign `zSign', exponent `zExp', and significand `zSig' into an ! 553: | extended double-precision floating-point value, returning the result. ! 554: *----------------------------------------------------------------------------*/ ! 555: ! 556: INLINE floatx80 packFloatx80( flag zSign, int32 zExp, bits64 zSig ) ! 557: { ! 558: floatx80 z; ! 559: ! 560: z.low = zSig; ! 561: z.high = ( ( (bits16) zSign )<<15 ) + zExp; ! 562: return z; ! 563: ! 564: } ! 565: ! 566: /*---------------------------------------------------------------------------- ! 567: | Takes an abstract floating-point value having sign `zSign', exponent `zExp', ! 568: | and extended significand formed by the concatenation of `zSig0' and `zSig1', ! 569: | and returns the proper extended double-precision floating-point value ! 570: | corresponding to the abstract input. Ordinarily, the abstract value is ! 571: | rounded and packed into the extended double-precision format, with the ! 572: | inexact exception raised if the abstract input cannot be represented ! 573: | exactly. However, if the abstract value is too large, the overflow and ! 574: | inexact exceptions are raised and an infinity or maximal finite value is ! 575: | returned. If the abstract value is too small, the input value is rounded to ! 576: | a subnormal number, and the underflow and inexact exceptions are raised if ! 577: | the abstract input cannot be represented exactly as a subnormal extended ! 578: | double-precision floating-point number. ! 579: | If `roundingPrecision' is 32 or 64, the result is rounded to the same ! 580: | number of bits as single or double precision, respectively. Otherwise, the ! 581: | result is rounded to the full precision of the extended double-precision ! 582: | format. ! 583: | The input significand must be normalized or smaller. If the input ! 584: | significand is not normalized, `zExp' must be 0; in that case, the result ! 585: | returned is a subnormal number, and it must not require rounding. The ! 586: | handling of underflow and overflow follows the IEC/IEEE Standard for Binary ! 587: | Floating-Point Arithmetic. ! 588: *----------------------------------------------------------------------------*/ ! 589: ! 590: static floatx80 ! 591: roundAndPackFloatx80( ! 592: int8 roundingPrecision, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1 ! 593: STATUS_PARAM) ! 594: { ! 595: int8 roundingMode; ! 596: flag roundNearestEven, increment, isTiny; ! 597: int64 roundIncrement, roundMask, roundBits; ! 598: ! 599: roundingMode = STATUS(float_rounding_mode); ! 600: roundNearestEven = ( roundingMode == float_round_nearest_even ); ! 601: if ( roundingPrecision == 80 ) goto precision80; ! 602: if ( roundingPrecision == 64 ) { ! 603: roundIncrement = LIT64( 0x0000000000000400 ); ! 604: roundMask = LIT64( 0x00000000000007FF ); ! 605: } ! 606: else if ( roundingPrecision == 32 ) { ! 607: roundIncrement = LIT64( 0x0000008000000000 ); ! 608: roundMask = LIT64( 0x000000FFFFFFFFFF ); ! 609: } ! 610: else { ! 611: goto precision80; ! 612: } ! 613: zSig0 |= ( zSig1 != 0 ); ! 614: if ( ! roundNearestEven ) { ! 615: if ( roundingMode == float_round_to_zero ) { ! 616: roundIncrement = 0; ! 617: } ! 618: else { ! 619: roundIncrement = roundMask; ! 620: if ( zSign ) { ! 621: if ( roundingMode == float_round_up ) roundIncrement = 0; ! 622: } ! 623: else { ! 624: if ( roundingMode == float_round_down ) roundIncrement = 0; ! 625: } ! 626: } ! 627: } ! 628: roundBits = zSig0 & roundMask; ! 629: if ( 0x7FFD <= (bits32) ( zExp - 1 ) ) { ! 630: if ( ( 0x7FFE < zExp ) ! 631: || ( ( zExp == 0x7FFE ) && ( zSig0 + roundIncrement < zSig0 ) ) ! 632: ) { ! 633: goto overflow; ! 634: } ! 635: if ( zExp <= 0 ) { ! 636: isTiny = ! 637: ( STATUS(float_detect_tininess) == float_tininess_before_rounding ) ! 638: || ( zExp < 0 ) ! 639: || ( zSig0 <= zSig0 + roundIncrement ); ! 640: shift64RightJamming( zSig0, 1 - zExp, &zSig0 ); ! 641: zExp = 0; ! 642: roundBits = zSig0 & roundMask; ! 643: if ( isTiny && roundBits ) float_raise( float_flag_underflow STATUS_VAR); ! 644: if ( roundBits ) STATUS(float_exception_flags) |= float_flag_inexact; ! 645: zSig0 += roundIncrement; ! 646: if ( (sbits64) zSig0 < 0 ) zExp = 1; ! 647: roundIncrement = roundMask + 1; ! 648: if ( roundNearestEven && ( roundBits<<1 == roundIncrement ) ) { ! 649: roundMask |= roundIncrement; ! 650: } ! 651: zSig0 &= ~ roundMask; ! 652: return packFloatx80( zSign, zExp, zSig0 ); ! 653: } ! 654: } ! 655: if ( roundBits ) STATUS(float_exception_flags) |= float_flag_inexact; ! 656: zSig0 += roundIncrement; ! 657: if ( zSig0 < roundIncrement ) { ! 658: ++zExp; ! 659: zSig0 = LIT64( 0x8000000000000000 ); ! 660: } ! 661: roundIncrement = roundMask + 1; ! 662: if ( roundNearestEven && ( roundBits<<1 == roundIncrement ) ) { ! 663: roundMask |= roundIncrement; ! 664: } ! 665: zSig0 &= ~ roundMask; ! 666: if ( zSig0 == 0 ) zExp = 0; ! 667: return packFloatx80( zSign, zExp, zSig0 ); ! 668: precision80: ! 669: increment = ( (sbits64) zSig1 < 0 ); ! 670: if ( ! roundNearestEven ) { ! 671: if ( roundingMode == float_round_to_zero ) { ! 672: increment = 0; ! 673: } ! 674: else { ! 675: if ( zSign ) { ! 676: increment = ( roundingMode == float_round_down ) && zSig1; ! 677: } ! 678: else { ! 679: increment = ( roundingMode == float_round_up ) && zSig1; ! 680: } ! 681: } ! 682: } ! 683: if ( 0x7FFD <= (bits32) ( zExp - 1 ) ) { ! 684: if ( ( 0x7FFE < zExp ) ! 685: || ( ( zExp == 0x7FFE ) ! 686: && ( zSig0 == LIT64( 0xFFFFFFFFFFFFFFFF ) ) ! 687: && increment ! 688: ) ! 689: ) { ! 690: roundMask = 0; ! 691: overflow: ! 692: float_raise( float_flag_overflow | float_flag_inexact STATUS_VAR); ! 693: if ( ( roundingMode == float_round_to_zero ) ! 694: || ( zSign && ( roundingMode == float_round_up ) ) ! 695: || ( ! zSign && ( roundingMode == float_round_down ) ) ! 696: ) { ! 697: return packFloatx80( zSign, 0x7FFE, ~ roundMask ); ! 698: } ! 699: return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); ! 700: } ! 701: if ( zExp <= 0 ) { ! 702: isTiny = ! 703: ( STATUS(float_detect_tininess) == float_tininess_before_rounding ) ! 704: || ( zExp < 0 ) ! 705: || ! increment ! 706: || ( zSig0 < LIT64( 0xFFFFFFFFFFFFFFFF ) ); ! 707: shift64ExtraRightJamming( zSig0, zSig1, 1 - zExp, &zSig0, &zSig1 ); ! 708: zExp = 0; ! 709: if ( isTiny && zSig1 ) float_raise( float_flag_underflow STATUS_VAR); ! 710: if ( zSig1 ) STATUS(float_exception_flags) |= float_flag_inexact; ! 711: if ( roundNearestEven ) { ! 712: increment = ( (sbits64) zSig1 < 0 ); ! 713: } ! 714: else { ! 715: if ( zSign ) { ! 716: increment = ( roundingMode == float_round_down ) && zSig1; ! 717: } ! 718: else { ! 719: increment = ( roundingMode == float_round_up ) && zSig1; ! 720: } ! 721: } ! 722: if ( increment ) { ! 723: ++zSig0; ! 724: zSig0 &= ! 725: ~ ( ( (bits64) ( zSig1<<1 ) == 0 ) & roundNearestEven ); ! 726: if ( (sbits64) zSig0 < 0 ) zExp = 1; ! 727: } ! 728: return packFloatx80( zSign, zExp, zSig0 ); ! 729: } ! 730: } ! 731: if ( zSig1 ) STATUS(float_exception_flags) |= float_flag_inexact; ! 732: if ( increment ) { ! 733: ++zSig0; ! 734: if ( zSig0 == 0 ) { ! 735: ++zExp; ! 736: zSig0 = LIT64( 0x8000000000000000 ); ! 737: } ! 738: else { ! 739: zSig0 &= ~ ( ( (bits64) ( zSig1<<1 ) == 0 ) & roundNearestEven ); ! 740: } ! 741: } ! 742: else { ! 743: if ( zSig0 == 0 ) zExp = 0; ! 744: } ! 745: return packFloatx80( zSign, zExp, zSig0 ); ! 746: ! 747: } ! 748: ! 749: /*---------------------------------------------------------------------------- ! 750: | Takes an abstract floating-point value having sign `zSign', exponent ! 751: | `zExp', and significand formed by the concatenation of `zSig0' and `zSig1', ! 752: | and returns the proper extended double-precision floating-point value ! 753: | corresponding to the abstract input. This routine is just like ! 754: | `roundAndPackFloatx80' except that the input significand does not have to be ! 755: | normalized. ! 756: *----------------------------------------------------------------------------*/ ! 757: ! 758: static floatx80 ! 759: normalizeRoundAndPackFloatx80( ! 760: int8 roundingPrecision, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1 ! 761: STATUS_PARAM) ! 762: { ! 763: int8 shiftCount; ! 764: ! 765: if ( zSig0 == 0 ) { ! 766: zSig0 = zSig1; ! 767: zSig1 = 0; ! 768: zExp -= 64; ! 769: } ! 770: shiftCount = countLeadingZeros64( zSig0 ); ! 771: shortShift128Left( zSig0, zSig1, shiftCount, &zSig0, &zSig1 ); ! 772: zExp -= shiftCount; ! 773: return ! 774: roundAndPackFloatx80( roundingPrecision, zSign, zExp, zSig0, zSig1 STATUS_VAR); ! 775: ! 776: } ! 777: ! 778: #endif ! 779: ! 780: #ifdef FLOAT128 ! 781: ! 782: /*---------------------------------------------------------------------------- ! 783: | Returns the least-significant 64 fraction bits of the quadruple-precision ! 784: | floating-point value `a'. ! 785: *----------------------------------------------------------------------------*/ ! 786: ! 787: INLINE bits64 extractFloat128Frac1( float128 a ) ! 788: { ! 789: ! 790: return a.low; ! 791: ! 792: } ! 793: ! 794: /*---------------------------------------------------------------------------- ! 795: | Returns the most-significant 48 fraction bits of the quadruple-precision ! 796: | floating-point value `a'. ! 797: *----------------------------------------------------------------------------*/ ! 798: ! 799: INLINE bits64 extractFloat128Frac0( float128 a ) ! 800: { ! 801: ! 802: return a.high & LIT64( 0x0000FFFFFFFFFFFF ); ! 803: ! 804: } ! 805: ! 806: /*---------------------------------------------------------------------------- ! 807: | Returns the exponent bits of the quadruple-precision floating-point value ! 808: | `a'. ! 809: *----------------------------------------------------------------------------*/ ! 810: ! 811: INLINE int32 extractFloat128Exp( float128 a ) ! 812: { ! 813: ! 814: return ( a.high>>48 ) & 0x7FFF; ! 815: ! 816: } ! 817: ! 818: /*---------------------------------------------------------------------------- ! 819: | Returns the sign bit of the quadruple-precision floating-point value `a'. ! 820: *----------------------------------------------------------------------------*/ ! 821: ! 822: INLINE flag extractFloat128Sign( float128 a ) ! 823: { ! 824: ! 825: return a.high>>63; ! 826: ! 827: } ! 828: ! 829: /*---------------------------------------------------------------------------- ! 830: | Normalizes the subnormal quadruple-precision floating-point value ! 831: | represented by the denormalized significand formed by the concatenation of ! 832: | `aSig0' and `aSig1'. The normalized exponent is stored at the location ! 833: | pointed to by `zExpPtr'. The most significant 49 bits of the normalized ! 834: | significand are stored at the location pointed to by `zSig0Ptr', and the ! 835: | least significant 64 bits of the normalized significand are stored at the ! 836: | location pointed to by `zSig1Ptr'. ! 837: *----------------------------------------------------------------------------*/ ! 838: ! 839: static void ! 840: normalizeFloat128Subnormal( ! 841: bits64 aSig0, ! 842: bits64 aSig1, ! 843: int32 *zExpPtr, ! 844: bits64 *zSig0Ptr, ! 845: bits64 *zSig1Ptr ! 846: ) ! 847: { ! 848: int8 shiftCount; ! 849: ! 850: if ( aSig0 == 0 ) { ! 851: shiftCount = countLeadingZeros64( aSig1 ) - 15; ! 852: if ( shiftCount < 0 ) { ! 853: *zSig0Ptr = aSig1>>( - shiftCount ); ! 854: *zSig1Ptr = aSig1<<( shiftCount & 63 ); ! 855: } ! 856: else { ! 857: *zSig0Ptr = aSig1<<shiftCount; ! 858: *zSig1Ptr = 0; ! 859: } ! 860: *zExpPtr = - shiftCount - 63; ! 861: } ! 862: else { ! 863: shiftCount = countLeadingZeros64( aSig0 ) - 15; ! 864: shortShift128Left( aSig0, aSig1, shiftCount, zSig0Ptr, zSig1Ptr ); ! 865: *zExpPtr = 1 - shiftCount; ! 866: } ! 867: ! 868: } ! 869: ! 870: /*---------------------------------------------------------------------------- ! 871: | Packs the sign `zSign', the exponent `zExp', and the significand formed ! 872: | by the concatenation of `zSig0' and `zSig1' into a quadruple-precision ! 873: | floating-point value, returning the result. After being shifted into the ! 874: | proper positions, the three fields `zSign', `zExp', and `zSig0' are simply ! 875: | added together to form the most significant 32 bits of the result. This ! 876: | means that any integer portion of `zSig0' will be added into the exponent. ! 877: | Since a properly normalized significand will have an integer portion equal ! 878: | to 1, the `zExp' input should be 1 less than the desired result exponent ! 879: | whenever `zSig0' and `zSig1' concatenated form a complete, normalized ! 880: | significand. ! 881: *----------------------------------------------------------------------------*/ ! 882: ! 883: INLINE float128 ! 884: packFloat128( flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1 ) ! 885: { ! 886: float128 z; ! 887: ! 888: z.low = zSig1; ! 889: z.high = ( ( (bits64) zSign )<<63 ) + ( ( (bits64) zExp )<<48 ) + zSig0; ! 890: return z; ! 891: ! 892: } ! 893: ! 894: /*---------------------------------------------------------------------------- ! 895: | Takes an abstract floating-point value having sign `zSign', exponent `zExp', ! 896: | and extended significand formed by the concatenation of `zSig0', `zSig1', ! 897: | and `zSig2', and returns the proper quadruple-precision floating-point value ! 898: | corresponding to the abstract input. Ordinarily, the abstract value is ! 899: | simply rounded and packed into the quadruple-precision format, with the ! 900: | inexact exception raised if the abstract input cannot be represented ! 901: | exactly. However, if the abstract value is too large, the overflow and ! 902: | inexact exceptions are raised and an infinity or maximal finite value is ! 903: | returned. If the abstract value is too small, the input value is rounded to ! 904: | a subnormal number, and the underflow and inexact exceptions are raised if ! 905: | the abstract input cannot be represented exactly as a subnormal quadruple- ! 906: | precision floating-point number. ! 907: | The input significand must be normalized or smaller. If the input ! 908: | significand is not normalized, `zExp' must be 0; in that case, the result ! 909: | returned is a subnormal number, and it must not require rounding. In the ! 910: | usual case that the input significand is normalized, `zExp' must be 1 less ! 911: | than the ``true'' floating-point exponent. The handling of underflow and ! 912: | overflow follows the IEC/IEEE Standard for Binary Floating-Point Arithmetic. ! 913: *----------------------------------------------------------------------------*/ ! 914: ! 915: static float128 ! 916: roundAndPackFloat128( ! 917: flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1, bits64 zSig2 STATUS_PARAM) ! 918: { ! 919: int8 roundingMode; ! 920: flag roundNearestEven, increment, isTiny; ! 921: ! 922: roundingMode = STATUS(float_rounding_mode); ! 923: roundNearestEven = ( roundingMode == float_round_nearest_even ); ! 924: increment = ( (sbits64) zSig2 < 0 ); ! 925: if ( ! roundNearestEven ) { ! 926: if ( roundingMode == float_round_to_zero ) { ! 927: increment = 0; ! 928: } ! 929: else { ! 930: if ( zSign ) { ! 931: increment = ( roundingMode == float_round_down ) && zSig2; ! 932: } ! 933: else { ! 934: increment = ( roundingMode == float_round_up ) && zSig2; ! 935: } ! 936: } ! 937: } ! 938: if ( 0x7FFD <= (bits32) zExp ) { ! 939: if ( ( 0x7FFD < zExp ) ! 940: || ( ( zExp == 0x7FFD ) ! 941: && eq128( ! 942: LIT64( 0x0001FFFFFFFFFFFF ), ! 943: LIT64( 0xFFFFFFFFFFFFFFFF ), ! 944: zSig0, ! 945: zSig1 ! 946: ) ! 947: && increment ! 948: ) ! 949: ) { ! 950: float_raise( float_flag_overflow | float_flag_inexact STATUS_VAR); ! 951: if ( ( roundingMode == float_round_to_zero ) ! 952: || ( zSign && ( roundingMode == float_round_up ) ) ! 953: || ( ! zSign && ( roundingMode == float_round_down ) ) ! 954: ) { ! 955: return ! 956: packFloat128( ! 957: zSign, ! 958: 0x7FFE, ! 959: LIT64( 0x0000FFFFFFFFFFFF ), ! 960: LIT64( 0xFFFFFFFFFFFFFFFF ) ! 961: ); ! 962: } ! 963: return packFloat128( zSign, 0x7FFF, 0, 0 ); ! 964: } ! 965: if ( zExp < 0 ) { ! 966: isTiny = ! 967: ( STATUS(float_detect_tininess) == float_tininess_before_rounding ) ! 968: || ( zExp < -1 ) ! 969: || ! increment ! 970: || lt128( ! 971: zSig0, ! 972: zSig1, ! 973: LIT64( 0x0001FFFFFFFFFFFF ), ! 974: LIT64( 0xFFFFFFFFFFFFFFFF ) ! 975: ); ! 976: shift128ExtraRightJamming( ! 977: zSig0, zSig1, zSig2, - zExp, &zSig0, &zSig1, &zSig2 ); ! 978: zExp = 0; ! 979: if ( isTiny && zSig2 ) float_raise( float_flag_underflow STATUS_VAR); ! 980: if ( roundNearestEven ) { ! 981: increment = ( (sbits64) zSig2 < 0 ); ! 982: } ! 983: else { ! 984: if ( zSign ) { ! 985: increment = ( roundingMode == float_round_down ) && zSig2; ! 986: } ! 987: else { ! 988: increment = ( roundingMode == float_round_up ) && zSig2; ! 989: } ! 990: } ! 991: } ! 992: } ! 993: if ( zSig2 ) STATUS(float_exception_flags) |= float_flag_inexact; ! 994: if ( increment ) { ! 995: add128( zSig0, zSig1, 0, 1, &zSig0, &zSig1 ); ! 996: zSig1 &= ~ ( ( zSig2 + zSig2 == 0 ) & roundNearestEven ); ! 997: } ! 998: else { ! 999: if ( ( zSig0 | zSig1 ) == 0 ) zExp = 0; ! 1000: } ! 1001: return packFloat128( zSign, zExp, zSig0, zSig1 ); ! 1002: ! 1003: } ! 1004: ! 1005: /*---------------------------------------------------------------------------- ! 1006: | Takes an abstract floating-point value having sign `zSign', exponent `zExp', ! 1007: | and significand formed by the concatenation of `zSig0' and `zSig1', and ! 1008: | returns the proper quadruple-precision floating-point value corresponding ! 1009: | to the abstract input. This routine is just like `roundAndPackFloat128' ! 1010: | except that the input significand has fewer bits and does not have to be ! 1011: | normalized. In all cases, `zExp' must be 1 less than the ``true'' floating- ! 1012: | point exponent. ! 1013: *----------------------------------------------------------------------------*/ ! 1014: ! 1015: static float128 ! 1016: normalizeRoundAndPackFloat128( ! 1017: flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1 STATUS_PARAM) ! 1018: { ! 1019: int8 shiftCount; ! 1020: bits64 zSig2; ! 1021: ! 1022: if ( zSig0 == 0 ) { ! 1023: zSig0 = zSig1; ! 1024: zSig1 = 0; ! 1025: zExp -= 64; ! 1026: } ! 1027: shiftCount = countLeadingZeros64( zSig0 ) - 15; ! 1028: if ( 0 <= shiftCount ) { ! 1029: zSig2 = 0; ! 1030: shortShift128Left( zSig0, zSig1, shiftCount, &zSig0, &zSig1 ); ! 1031: } ! 1032: else { ! 1033: shift128ExtraRightJamming( ! 1034: zSig0, zSig1, 0, - shiftCount, &zSig0, &zSig1, &zSig2 ); ! 1035: } ! 1036: zExp -= shiftCount; ! 1037: return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 STATUS_VAR); ! 1038: ! 1039: } ! 1040: ! 1041: #endif ! 1042: ! 1043: /*---------------------------------------------------------------------------- ! 1044: | Returns the result of converting the 32-bit two's complement integer `a' ! 1045: | to the single-precision floating-point format. The conversion is performed ! 1046: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. ! 1047: *----------------------------------------------------------------------------*/ ! 1048: ! 1049: float32 int32_to_float32( int32 a STATUS_PARAM ) ! 1050: { ! 1051: flag zSign; ! 1052: ! 1053: if ( a == 0 ) return 0; ! 1054: if ( a == (sbits32) 0x80000000 ) return packFloat32( 1, 0x9E, 0 ); ! 1055: zSign = ( a < 0 ); ! 1056: return normalizeRoundAndPackFloat32( zSign, 0x9C, zSign ? - a : a STATUS_VAR ); ! 1057: ! 1058: } ! 1059: ! 1060: /*---------------------------------------------------------------------------- ! 1061: | Returns the result of converting the 32-bit two's complement integer `a' ! 1062: | to the double-precision floating-point format. The conversion is performed ! 1063: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. ! 1064: *----------------------------------------------------------------------------*/ ! 1065: ! 1066: float64 int32_to_float64( int32 a STATUS_PARAM ) ! 1067: { ! 1068: flag zSign; ! 1069: uint32 absA; ! 1070: int8 shiftCount; ! 1071: bits64 zSig; ! 1072: ! 1073: if ( a == 0 ) return 0; ! 1074: zSign = ( a < 0 ); ! 1075: absA = zSign ? - a : a; ! 1076: shiftCount = countLeadingZeros32( absA ) + 21; ! 1077: zSig = absA; ! 1078: return packFloat64( zSign, 0x432 - shiftCount, zSig<<shiftCount ); ! 1079: ! 1080: } ! 1081: ! 1082: #ifdef FLOATX80 ! 1083: ! 1084: /*---------------------------------------------------------------------------- ! 1085: | Returns the result of converting the 32-bit two's complement integer `a' ! 1086: | to the extended double-precision floating-point format. The conversion ! 1087: | is performed according to the IEC/IEEE Standard for Binary Floating-Point ! 1088: | Arithmetic. ! 1089: *----------------------------------------------------------------------------*/ ! 1090: ! 1091: floatx80 int32_to_floatx80( int32 a STATUS_PARAM ) ! 1092: { ! 1093: flag zSign; ! 1094: uint32 absA; ! 1095: int8 shiftCount; ! 1096: bits64 zSig; ! 1097: ! 1098: if ( a == 0 ) return packFloatx80( 0, 0, 0 ); ! 1099: zSign = ( a < 0 ); ! 1100: absA = zSign ? - a : a; ! 1101: shiftCount = countLeadingZeros32( absA ) + 32; ! 1102: zSig = absA; ! 1103: return packFloatx80( zSign, 0x403E - shiftCount, zSig<<shiftCount ); ! 1104: ! 1105: } ! 1106: ! 1107: #endif ! 1108: ! 1109: #ifdef FLOAT128 ! 1110: ! 1111: /*---------------------------------------------------------------------------- ! 1112: | Returns the result of converting the 32-bit two's complement integer `a' to ! 1113: | the quadruple-precision floating-point format. The conversion is performed ! 1114: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. ! 1115: *----------------------------------------------------------------------------*/ ! 1116: ! 1117: float128 int32_to_float128( int32 a STATUS_PARAM ) ! 1118: { ! 1119: flag zSign; ! 1120: uint32 absA; ! 1121: int8 shiftCount; ! 1122: bits64 zSig0; ! 1123: ! 1124: if ( a == 0 ) return packFloat128( 0, 0, 0, 0 ); ! 1125: zSign = ( a < 0 ); ! 1126: absA = zSign ? - a : a; ! 1127: shiftCount = countLeadingZeros32( absA ) + 17; ! 1128: zSig0 = absA; ! 1129: return packFloat128( zSign, 0x402E - shiftCount, zSig0<<shiftCount, 0 ); ! 1130: ! 1131: } ! 1132: ! 1133: #endif ! 1134: ! 1135: /*---------------------------------------------------------------------------- ! 1136: | Returns the result of converting the 64-bit two's complement integer `a' ! 1137: | to the single-precision floating-point format. The conversion is performed ! 1138: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. ! 1139: *----------------------------------------------------------------------------*/ ! 1140: ! 1141: float32 int64_to_float32( int64 a STATUS_PARAM ) ! 1142: { ! 1143: flag zSign; ! 1144: uint64 absA; ! 1145: int8 shiftCount; ! 1146: ! 1147: if ( a == 0 ) return 0; ! 1148: zSign = ( a < 0 ); ! 1149: absA = zSign ? - a : a; ! 1150: shiftCount = countLeadingZeros64( absA ) - 40; ! 1151: if ( 0 <= shiftCount ) { ! 1152: return packFloat32( zSign, 0x95 - shiftCount, absA<<shiftCount ); ! 1153: } ! 1154: else { ! 1155: shiftCount += 7; ! 1156: if ( shiftCount < 0 ) { ! 1157: shift64RightJamming( absA, - shiftCount, &absA ); ! 1158: } ! 1159: else { ! 1160: absA <<= shiftCount; ! 1161: } ! 1162: return roundAndPackFloat32( zSign, 0x9C - shiftCount, absA STATUS_VAR ); ! 1163: } ! 1164: ! 1165: } ! 1166: ! 1167: /*---------------------------------------------------------------------------- ! 1168: | Returns the result of converting the 64-bit two's complement integer `a' ! 1169: | to the double-precision floating-point format. The conversion is performed ! 1170: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. ! 1171: *----------------------------------------------------------------------------*/ ! 1172: ! 1173: float64 int64_to_float64( int64 a STATUS_PARAM ) ! 1174: { ! 1175: flag zSign; ! 1176: ! 1177: if ( a == 0 ) return 0; ! 1178: if ( a == (sbits64) LIT64( 0x8000000000000000 ) ) { ! 1179: return packFloat64( 1, 0x43E, 0 ); ! 1180: } ! 1181: zSign = ( a < 0 ); ! 1182: return normalizeRoundAndPackFloat64( zSign, 0x43C, zSign ? - a : a STATUS_VAR ); ! 1183: ! 1184: } ! 1185: ! 1186: #ifdef FLOATX80 ! 1187: ! 1188: /*---------------------------------------------------------------------------- ! 1189: | Returns the result of converting the 64-bit two's complement integer `a' ! 1190: | to the extended double-precision floating-point format. The conversion ! 1191: | is performed according to the IEC/IEEE Standard for Binary Floating-Point ! 1192: | Arithmetic. ! 1193: *----------------------------------------------------------------------------*/ ! 1194: ! 1195: floatx80 int64_to_floatx80( int64 a STATUS_PARAM ) ! 1196: { ! 1197: flag zSign; ! 1198: uint64 absA; ! 1199: int8 shiftCount; ! 1200: ! 1201: if ( a == 0 ) return packFloatx80( 0, 0, 0 ); ! 1202: zSign = ( a < 0 ); ! 1203: absA = zSign ? - a : a; ! 1204: shiftCount = countLeadingZeros64( absA ); ! 1205: return packFloatx80( zSign, 0x403E - shiftCount, absA<<shiftCount ); ! 1206: ! 1207: } ! 1208: ! 1209: #endif ! 1210: ! 1211: #ifdef FLOAT128 ! 1212: ! 1213: /*---------------------------------------------------------------------------- ! 1214: | Returns the result of converting the 64-bit two's complement integer `a' to ! 1215: | the quadruple-precision floating-point format. The conversion is performed ! 1216: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. ! 1217: *----------------------------------------------------------------------------*/ ! 1218: ! 1219: float128 int64_to_float128( int64 a STATUS_PARAM ) ! 1220: { ! 1221: flag zSign; ! 1222: uint64 absA; ! 1223: int8 shiftCount; ! 1224: int32 zExp; ! 1225: bits64 zSig0, zSig1; ! 1226: ! 1227: if ( a == 0 ) return packFloat128( 0, 0, 0, 0 ); ! 1228: zSign = ( a < 0 ); ! 1229: absA = zSign ? - a : a; ! 1230: shiftCount = countLeadingZeros64( absA ) + 49; ! 1231: zExp = 0x406E - shiftCount; ! 1232: if ( 64 <= shiftCount ) { ! 1233: zSig1 = 0; ! 1234: zSig0 = absA; ! 1235: shiftCount -= 64; ! 1236: } ! 1237: else { ! 1238: zSig1 = absA; ! 1239: zSig0 = 0; ! 1240: } ! 1241: shortShift128Left( zSig0, zSig1, shiftCount, &zSig0, &zSig1 ); ! 1242: return packFloat128( zSign, zExp, zSig0, zSig1 ); ! 1243: ! 1244: } ! 1245: ! 1246: #endif ! 1247: ! 1248: /*---------------------------------------------------------------------------- ! 1249: | Returns the result of converting the single-precision floating-point value ! 1250: | `a' to the 32-bit two's complement integer format. The conversion is ! 1251: | performed according to the IEC/IEEE Standard for Binary Floating-Point ! 1252: | Arithmetic---which means in particular that the conversion is rounded ! 1253: | according to the current rounding mode. If `a' is a NaN, the largest ! 1254: | positive integer is returned. Otherwise, if the conversion overflows, the ! 1255: | largest integer with the same sign as `a' is returned. ! 1256: *----------------------------------------------------------------------------*/ ! 1257: ! 1258: int32 float32_to_int32( float32 a STATUS_PARAM ) ! 1259: { ! 1260: flag aSign; ! 1261: int16 aExp, shiftCount; ! 1262: bits32 aSig; ! 1263: bits64 aSig64; ! 1264: ! 1265: aSig = extractFloat32Frac( a ); ! 1266: aExp = extractFloat32Exp( a ); ! 1267: aSign = extractFloat32Sign( a ); ! 1268: if ( ( aExp == 0xFF ) && aSig ) aSign = 0; ! 1269: if ( aExp ) aSig |= 0x00800000; ! 1270: shiftCount = 0xAF - aExp; ! 1271: aSig64 = aSig; ! 1272: aSig64 <<= 32; ! 1273: if ( 0 < shiftCount ) shift64RightJamming( aSig64, shiftCount, &aSig64 ); ! 1274: return roundAndPackInt32( aSign, aSig64 STATUS_VAR ); ! 1275: ! 1276: } ! 1277: ! 1278: /*---------------------------------------------------------------------------- ! 1279: | Returns the result of converting the single-precision floating-point value ! 1280: | `a' to the 32-bit two's complement integer format. The conversion is ! 1281: | performed according to the IEC/IEEE Standard for Binary Floating-Point ! 1282: | Arithmetic, except that the conversion is always rounded toward zero. ! 1283: | If `a' is a NaN, the largest positive integer is returned. Otherwise, if ! 1284: | the conversion overflows, the largest integer with the same sign as `a' is ! 1285: | returned. ! 1286: *----------------------------------------------------------------------------*/ ! 1287: ! 1288: int32 float32_to_int32_round_to_zero( float32 a STATUS_PARAM ) ! 1289: { ! 1290: flag aSign; ! 1291: int16 aExp, shiftCount; ! 1292: bits32 aSig; ! 1293: int32 z; ! 1294: ! 1295: aSig = extractFloat32Frac( a ); ! 1296: aExp = extractFloat32Exp( a ); ! 1297: aSign = extractFloat32Sign( a ); ! 1298: shiftCount = aExp - 0x9E; ! 1299: if ( 0 <= shiftCount ) { ! 1300: if ( a != 0xCF000000 ) { ! 1301: float_raise( float_flag_invalid STATUS_VAR); ! 1302: if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) return 0x7FFFFFFF; ! 1303: } ! 1304: return (sbits32) 0x80000000; ! 1305: } ! 1306: else if ( aExp <= 0x7E ) { ! 1307: if ( aExp | aSig ) STATUS(float_exception_flags) |= float_flag_inexact; ! 1308: return 0; ! 1309: } ! 1310: aSig = ( aSig | 0x00800000 )<<8; ! 1311: z = aSig>>( - shiftCount ); ! 1312: if ( (bits32) ( aSig<<( shiftCount & 31 ) ) ) { ! 1313: STATUS(float_exception_flags) |= float_flag_inexact; ! 1314: } ! 1315: if ( aSign ) z = - z; ! 1316: return z; ! 1317: ! 1318: } ! 1319: ! 1320: /*---------------------------------------------------------------------------- ! 1321: | Returns the result of converting the single-precision floating-point value ! 1322: | `a' to the 64-bit two's complement integer format. The conversion is ! 1323: | performed according to the IEC/IEEE Standard for Binary Floating-Point ! 1324: | Arithmetic---which means in particular that the conversion is rounded ! 1325: | according to the current rounding mode. If `a' is a NaN, the largest ! 1326: | positive integer is returned. Otherwise, if the conversion overflows, the ! 1327: | largest integer with the same sign as `a' is returned. ! 1328: *----------------------------------------------------------------------------*/ ! 1329: ! 1330: int64 float32_to_int64( float32 a STATUS_PARAM ) ! 1331: { ! 1332: flag aSign; ! 1333: int16 aExp, shiftCount; ! 1334: bits32 aSig; ! 1335: bits64 aSig64, aSigExtra; ! 1336: ! 1337: aSig = extractFloat32Frac( a ); ! 1338: aExp = extractFloat32Exp( a ); ! 1339: aSign = extractFloat32Sign( a ); ! 1340: shiftCount = 0xBE - aExp; ! 1341: if ( shiftCount < 0 ) { ! 1342: float_raise( float_flag_invalid STATUS_VAR); ! 1343: if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) { ! 1344: return LIT64( 0x7FFFFFFFFFFFFFFF ); ! 1345: } ! 1346: return (sbits64) LIT64( 0x8000000000000000 ); ! 1347: } ! 1348: if ( aExp ) aSig |= 0x00800000; ! 1349: aSig64 = aSig; ! 1350: aSig64 <<= 40; ! 1351: shift64ExtraRightJamming( aSig64, 0, shiftCount, &aSig64, &aSigExtra ); ! 1352: return roundAndPackInt64( aSign, aSig64, aSigExtra STATUS_VAR ); ! 1353: ! 1354: } ! 1355: ! 1356: /*---------------------------------------------------------------------------- ! 1357: | Returns the result of converting the single-precision floating-point value ! 1358: | `a' to the 64-bit two's complement integer format. The conversion is ! 1359: | performed according to the IEC/IEEE Standard for Binary Floating-Point ! 1360: | Arithmetic, except that the conversion is always rounded toward zero. If ! 1361: | `a' is a NaN, the largest positive integer is returned. Otherwise, if the ! 1362: | conversion overflows, the largest integer with the same sign as `a' is ! 1363: | returned. ! 1364: *----------------------------------------------------------------------------*/ ! 1365: ! 1366: int64 float32_to_int64_round_to_zero( float32 a STATUS_PARAM ) ! 1367: { ! 1368: flag aSign; ! 1369: int16 aExp, shiftCount; ! 1370: bits32 aSig; ! 1371: bits64 aSig64; ! 1372: int64 z; ! 1373: ! 1374: aSig = extractFloat32Frac( a ); ! 1375: aExp = extractFloat32Exp( a ); ! 1376: aSign = extractFloat32Sign( a ); ! 1377: shiftCount = aExp - 0xBE; ! 1378: if ( 0 <= shiftCount ) { ! 1379: if ( a != 0xDF000000 ) { ! 1380: float_raise( float_flag_invalid STATUS_VAR); ! 1381: if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) { ! 1382: return LIT64( 0x7FFFFFFFFFFFFFFF ); ! 1383: } ! 1384: } ! 1385: return (sbits64) LIT64( 0x8000000000000000 ); ! 1386: } ! 1387: else if ( aExp <= 0x7E ) { ! 1388: if ( aExp | aSig ) STATUS(float_exception_flags) |= float_flag_inexact; ! 1389: return 0; ! 1390: } ! 1391: aSig64 = aSig | 0x00800000; ! 1392: aSig64 <<= 40; ! 1393: z = aSig64>>( - shiftCount ); ! 1394: if ( (bits64) ( aSig64<<( shiftCount & 63 ) ) ) { ! 1395: STATUS(float_exception_flags) |= float_flag_inexact; ! 1396: } ! 1397: if ( aSign ) z = - z; ! 1398: return z; ! 1399: ! 1400: } ! 1401: ! 1402: /*---------------------------------------------------------------------------- ! 1403: | Returns the result of converting the single-precision floating-point value ! 1404: | `a' to the double-precision floating-point format. The conversion is ! 1405: | performed according to the IEC/IEEE Standard for Binary Floating-Point ! 1406: | Arithmetic. ! 1407: *----------------------------------------------------------------------------*/ ! 1408: ! 1409: float64 float32_to_float64( float32 a STATUS_PARAM ) ! 1410: { ! 1411: flag aSign; ! 1412: int16 aExp; ! 1413: bits32 aSig; ! 1414: ! 1415: aSig = extractFloat32Frac( a ); ! 1416: aExp = extractFloat32Exp( a ); ! 1417: aSign = extractFloat32Sign( a ); ! 1418: if ( aExp == 0xFF ) { ! 1419: if ( aSig ) return commonNaNToFloat64( float32ToCommonNaN( a STATUS_VAR )); ! 1420: return packFloat64( aSign, 0x7FF, 0 ); ! 1421: } ! 1422: if ( aExp == 0 ) { ! 1423: if ( aSig == 0 ) return packFloat64( aSign, 0, 0 ); ! 1424: normalizeFloat32Subnormal( aSig, &aExp, &aSig ); ! 1425: --aExp; ! 1426: } ! 1427: return packFloat64( aSign, aExp + 0x380, ( (bits64) aSig )<<29 ); ! 1428: ! 1429: } ! 1430: ! 1431: #ifdef FLOATX80 ! 1432: ! 1433: /*---------------------------------------------------------------------------- ! 1434: | Returns the result of converting the single-precision floating-point value ! 1435: | `a' to the extended double-precision floating-point format. The conversion ! 1436: | is performed according to the IEC/IEEE Standard for Binary Floating-Point ! 1437: | Arithmetic. ! 1438: *----------------------------------------------------------------------------*/ ! 1439: ! 1440: floatx80 float32_to_floatx80( float32 a STATUS_PARAM ) ! 1441: { ! 1442: flag aSign; ! 1443: int16 aExp; ! 1444: bits32 aSig; ! 1445: ! 1446: aSig = extractFloat32Frac( a ); ! 1447: aExp = extractFloat32Exp( a ); ! 1448: aSign = extractFloat32Sign( a ); ! 1449: if ( aExp == 0xFF ) { ! 1450: if ( aSig ) return commonNaNToFloatx80( float32ToCommonNaN( a STATUS_VAR ) ); ! 1451: return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); ! 1452: } ! 1453: if ( aExp == 0 ) { ! 1454: if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 ); ! 1455: normalizeFloat32Subnormal( aSig, &aExp, &aSig ); ! 1456: } ! 1457: aSig |= 0x00800000; ! 1458: return packFloatx80( aSign, aExp + 0x3F80, ( (bits64) aSig )<<40 ); ! 1459: ! 1460: } ! 1461: ! 1462: #endif ! 1463: ! 1464: #ifdef FLOAT128 ! 1465: ! 1466: /*---------------------------------------------------------------------------- ! 1467: | Returns the result of converting the single-precision floating-point value ! 1468: | `a' to the double-precision floating-point format. The conversion is ! 1469: | performed according to the IEC/IEEE Standard for Binary Floating-Point ! 1470: | Arithmetic. ! 1471: *----------------------------------------------------------------------------*/ ! 1472: ! 1473: float128 float32_to_float128( float32 a STATUS_PARAM ) ! 1474: { ! 1475: flag aSign; ! 1476: int16 aExp; ! 1477: bits32 aSig; ! 1478: ! 1479: aSig = extractFloat32Frac( a ); ! 1480: aExp = extractFloat32Exp( a ); ! 1481: aSign = extractFloat32Sign( a ); ! 1482: if ( aExp == 0xFF ) { ! 1483: if ( aSig ) return commonNaNToFloat128( float32ToCommonNaN( a STATUS_VAR ) ); ! 1484: return packFloat128( aSign, 0x7FFF, 0, 0 ); ! 1485: } ! 1486: if ( aExp == 0 ) { ! 1487: if ( aSig == 0 ) return packFloat128( aSign, 0, 0, 0 ); ! 1488: normalizeFloat32Subnormal( aSig, &aExp, &aSig ); ! 1489: --aExp; ! 1490: } ! 1491: return packFloat128( aSign, aExp + 0x3F80, ( (bits64) aSig )<<25, 0 ); ! 1492: ! 1493: } ! 1494: ! 1495: #endif ! 1496: ! 1497: /*---------------------------------------------------------------------------- ! 1498: | Rounds the single-precision floating-point value `a' to an integer, and ! 1499: | returns the result as a single-precision floating-point value. The ! 1500: | operation is performed according to the IEC/IEEE Standard for Binary ! 1501: | Floating-Point Arithmetic. ! 1502: *----------------------------------------------------------------------------*/ ! 1503: ! 1504: float32 float32_round_to_int( float32 a STATUS_PARAM) ! 1505: { ! 1506: flag aSign; ! 1507: int16 aExp; ! 1508: bits32 lastBitMask, roundBitsMask; ! 1509: int8 roundingMode; ! 1510: float32 z; ! 1511: ! 1512: aExp = extractFloat32Exp( a ); ! 1513: if ( 0x96 <= aExp ) { ! 1514: if ( ( aExp == 0xFF ) && extractFloat32Frac( a ) ) { ! 1515: return propagateFloat32NaN( a, a STATUS_VAR ); ! 1516: } ! 1517: return a; ! 1518: } ! 1519: if ( aExp <= 0x7E ) { ! 1520: if ( (bits32) ( a<<1 ) == 0 ) return a; ! 1521: STATUS(float_exception_flags) |= float_flag_inexact; ! 1522: aSign = extractFloat32Sign( a ); ! 1523: switch ( STATUS(float_rounding_mode) ) { ! 1524: case float_round_nearest_even: ! 1525: if ( ( aExp == 0x7E ) && extractFloat32Frac( a ) ) { ! 1526: return packFloat32( aSign, 0x7F, 0 ); ! 1527: } ! 1528: break; ! 1529: case float_round_down: ! 1530: return aSign ? 0xBF800000 : 0; ! 1531: case float_round_up: ! 1532: return aSign ? 0x80000000 : 0x3F800000; ! 1533: } ! 1534: return packFloat32( aSign, 0, 0 ); ! 1535: } ! 1536: lastBitMask = 1; ! 1537: lastBitMask <<= 0x96 - aExp; ! 1538: roundBitsMask = lastBitMask - 1; ! 1539: z = a; ! 1540: roundingMode = STATUS(float_rounding_mode); ! 1541: if ( roundingMode == float_round_nearest_even ) { ! 1542: z += lastBitMask>>1; ! 1543: if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask; ! 1544: } ! 1545: else if ( roundingMode != float_round_to_zero ) { ! 1546: if ( extractFloat32Sign( z ) ^ ( roundingMode == float_round_up ) ) { ! 1547: z += roundBitsMask; ! 1548: } ! 1549: } ! 1550: z &= ~ roundBitsMask; ! 1551: if ( z != a ) STATUS(float_exception_flags) |= float_flag_inexact; ! 1552: return z; ! 1553: ! 1554: } ! 1555: ! 1556: /*---------------------------------------------------------------------------- ! 1557: | Returns the result of adding the absolute values of the single-precision ! 1558: | floating-point values `a' and `b'. If `zSign' is 1, the sum is negated ! 1559: | before being returned. `zSign' is ignored if the result is a NaN. ! 1560: | The addition is performed according to the IEC/IEEE Standard for Binary ! 1561: | Floating-Point Arithmetic. ! 1562: *----------------------------------------------------------------------------*/ ! 1563: ! 1564: static float32 addFloat32Sigs( float32 a, float32 b, flag zSign STATUS_PARAM) ! 1565: { ! 1566: int16 aExp, bExp, zExp; ! 1567: bits32 aSig, bSig, zSig; ! 1568: int16 expDiff; ! 1569: ! 1570: aSig = extractFloat32Frac( a ); ! 1571: aExp = extractFloat32Exp( a ); ! 1572: bSig = extractFloat32Frac( b ); ! 1573: bExp = extractFloat32Exp( b ); ! 1574: expDiff = aExp - bExp; ! 1575: aSig <<= 6; ! 1576: bSig <<= 6; ! 1577: if ( 0 < expDiff ) { ! 1578: if ( aExp == 0xFF ) { ! 1579: if ( aSig ) return propagateFloat32NaN( a, b STATUS_VAR ); ! 1580: return a; ! 1581: } ! 1582: if ( bExp == 0 ) { ! 1583: --expDiff; ! 1584: } ! 1585: else { ! 1586: bSig |= 0x20000000; ! 1587: } ! 1588: shift32RightJamming( bSig, expDiff, &bSig ); ! 1589: zExp = aExp; ! 1590: } ! 1591: else if ( expDiff < 0 ) { ! 1592: if ( bExp == 0xFF ) { ! 1593: if ( bSig ) return propagateFloat32NaN( a, b STATUS_VAR ); ! 1594: return packFloat32( zSign, 0xFF, 0 ); ! 1595: } ! 1596: if ( aExp == 0 ) { ! 1597: ++expDiff; ! 1598: } ! 1599: else { ! 1600: aSig |= 0x20000000; ! 1601: } ! 1602: shift32RightJamming( aSig, - expDiff, &aSig ); ! 1603: zExp = bExp; ! 1604: } ! 1605: else { ! 1606: if ( aExp == 0xFF ) { ! 1607: if ( aSig | bSig ) return propagateFloat32NaN( a, b STATUS_VAR ); ! 1608: return a; ! 1609: } ! 1610: if ( aExp == 0 ) return packFloat32( zSign, 0, ( aSig + bSig )>>6 ); ! 1611: zSig = 0x40000000 + aSig + bSig; ! 1612: zExp = aExp; ! 1613: goto roundAndPack; ! 1614: } ! 1615: aSig |= 0x20000000; ! 1616: zSig = ( aSig + bSig )<<1; ! 1617: --zExp; ! 1618: if ( (sbits32) zSig < 0 ) { ! 1619: zSig = aSig + bSig; ! 1620: ++zExp; ! 1621: } ! 1622: roundAndPack: ! 1623: return roundAndPackFloat32( zSign, zExp, zSig STATUS_VAR ); ! 1624: ! 1625: } ! 1626: ! 1627: /*---------------------------------------------------------------------------- ! 1628: | Returns the result of subtracting the absolute values of the single- ! 1629: | precision floating-point values `a' and `b'. If `zSign' is 1, the ! 1630: | difference is negated before being returned. `zSign' is ignored if the ! 1631: | result is a NaN. The subtraction is performed according to the IEC/IEEE ! 1632: | Standard for Binary Floating-Point Arithmetic. ! 1633: *----------------------------------------------------------------------------*/ ! 1634: ! 1635: static float32 subFloat32Sigs( float32 a, float32 b, flag zSign STATUS_PARAM) ! 1636: { ! 1637: int16 aExp, bExp, zExp; ! 1638: bits32 aSig, bSig, zSig; ! 1639: int16 expDiff; ! 1640: ! 1641: aSig = extractFloat32Frac( a ); ! 1642: aExp = extractFloat32Exp( a ); ! 1643: bSig = extractFloat32Frac( b ); ! 1644: bExp = extractFloat32Exp( b ); ! 1645: expDiff = aExp - bExp; ! 1646: aSig <<= 7; ! 1647: bSig <<= 7; ! 1648: if ( 0 < expDiff ) goto aExpBigger; ! 1649: if ( expDiff < 0 ) goto bExpBigger; ! 1650: if ( aExp == 0xFF ) { ! 1651: if ( aSig | bSig ) return propagateFloat32NaN( a, b STATUS_VAR ); ! 1652: float_raise( float_flag_invalid STATUS_VAR); ! 1653: return float32_default_nan; ! 1654: } ! 1655: if ( aExp == 0 ) { ! 1656: aExp = 1; ! 1657: bExp = 1; ! 1658: } ! 1659: if ( bSig < aSig ) goto aBigger; ! 1660: if ( aSig < bSig ) goto bBigger; ! 1661: return packFloat32( STATUS(float_rounding_mode) == float_round_down, 0, 0 ); ! 1662: bExpBigger: ! 1663: if ( bExp == 0xFF ) { ! 1664: if ( bSig ) return propagateFloat32NaN( a, b STATUS_VAR ); ! 1665: return packFloat32( zSign ^ 1, 0xFF, 0 ); ! 1666: } ! 1667: if ( aExp == 0 ) { ! 1668: ++expDiff; ! 1669: } ! 1670: else { ! 1671: aSig |= 0x40000000; ! 1672: } ! 1673: shift32RightJamming( aSig, - expDiff, &aSig ); ! 1674: bSig |= 0x40000000; ! 1675: bBigger: ! 1676: zSig = bSig - aSig; ! 1677: zExp = bExp; ! 1678: zSign ^= 1; ! 1679: goto normalizeRoundAndPack; ! 1680: aExpBigger: ! 1681: if ( aExp == 0xFF ) { ! 1682: if ( aSig ) return propagateFloat32NaN( a, b STATUS_VAR ); ! 1683: return a; ! 1684: } ! 1685: if ( bExp == 0 ) { ! 1686: --expDiff; ! 1687: } ! 1688: else { ! 1689: bSig |= 0x40000000; ! 1690: } ! 1691: shift32RightJamming( bSig, expDiff, &bSig ); ! 1692: aSig |= 0x40000000; ! 1693: aBigger: ! 1694: zSig = aSig - bSig; ! 1695: zExp = aExp; ! 1696: normalizeRoundAndPack: ! 1697: --zExp; ! 1698: return normalizeRoundAndPackFloat32( zSign, zExp, zSig STATUS_VAR ); ! 1699: ! 1700: } ! 1701: ! 1702: /*---------------------------------------------------------------------------- ! 1703: | Returns the result of adding the single-precision floating-point values `a' ! 1704: | and `b'. The operation is performed according to the IEC/IEEE Standard for ! 1705: | Binary Floating-Point Arithmetic. ! 1706: *----------------------------------------------------------------------------*/ ! 1707: ! 1708: float32 float32_add( float32 a, float32 b STATUS_PARAM ) ! 1709: { ! 1710: flag aSign, bSign; ! 1711: ! 1712: aSign = extractFloat32Sign( a ); ! 1713: bSign = extractFloat32Sign( b ); ! 1714: if ( aSign == bSign ) { ! 1715: return addFloat32Sigs( a, b, aSign STATUS_VAR); ! 1716: } ! 1717: else { ! 1718: return subFloat32Sigs( a, b, aSign STATUS_VAR ); ! 1719: } ! 1720: ! 1721: } ! 1722: ! 1723: /*---------------------------------------------------------------------------- ! 1724: | Returns the result of subtracting the single-precision floating-point values ! 1725: | `a' and `b'. The operation is performed according to the IEC/IEEE Standard ! 1726: | for Binary Floating-Point Arithmetic. ! 1727: *----------------------------------------------------------------------------*/ ! 1728: ! 1729: float32 float32_sub( float32 a, float32 b STATUS_PARAM ) ! 1730: { ! 1731: flag aSign, bSign; ! 1732: ! 1733: aSign = extractFloat32Sign( a ); ! 1734: bSign = extractFloat32Sign( b ); ! 1735: if ( aSign == bSign ) { ! 1736: return subFloat32Sigs( a, b, aSign STATUS_VAR ); ! 1737: } ! 1738: else { ! 1739: return addFloat32Sigs( a, b, aSign STATUS_VAR ); ! 1740: } ! 1741: ! 1742: } ! 1743: ! 1744: /*---------------------------------------------------------------------------- ! 1745: | Returns the result of multiplying the single-precision floating-point values ! 1746: | `a' and `b'. The operation is performed according to the IEC/IEEE Standard ! 1747: | for Binary Floating-Point Arithmetic. ! 1748: *----------------------------------------------------------------------------*/ ! 1749: ! 1750: float32 float32_mul( float32 a, float32 b STATUS_PARAM ) ! 1751: { ! 1752: flag aSign, bSign, zSign; ! 1753: int16 aExp, bExp, zExp; ! 1754: bits32 aSig, bSig; ! 1755: bits64 zSig64; ! 1756: bits32 zSig; ! 1757: ! 1758: aSig = extractFloat32Frac( a ); ! 1759: aExp = extractFloat32Exp( a ); ! 1760: aSign = extractFloat32Sign( a ); ! 1761: bSig = extractFloat32Frac( b ); ! 1762: bExp = extractFloat32Exp( b ); ! 1763: bSign = extractFloat32Sign( b ); ! 1764: zSign = aSign ^ bSign; ! 1765: if ( aExp == 0xFF ) { ! 1766: if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) { ! 1767: return propagateFloat32NaN( a, b STATUS_VAR ); ! 1768: } ! 1769: if ( ( bExp | bSig ) == 0 ) { ! 1770: float_raise( float_flag_invalid STATUS_VAR); ! 1771: return float32_default_nan; ! 1772: } ! 1773: return packFloat32( zSign, 0xFF, 0 ); ! 1774: } ! 1775: if ( bExp == 0xFF ) { ! 1776: if ( bSig ) return propagateFloat32NaN( a, b STATUS_VAR ); ! 1777: if ( ( aExp | aSig ) == 0 ) { ! 1778: float_raise( float_flag_invalid STATUS_VAR); ! 1779: return float32_default_nan; ! 1780: } ! 1781: return packFloat32( zSign, 0xFF, 0 ); ! 1782: } ! 1783: if ( aExp == 0 ) { ! 1784: if ( aSig == 0 ) return packFloat32( zSign, 0, 0 ); ! 1785: normalizeFloat32Subnormal( aSig, &aExp, &aSig ); ! 1786: } ! 1787: if ( bExp == 0 ) { ! 1788: if ( bSig == 0 ) return packFloat32( zSign, 0, 0 ); ! 1789: normalizeFloat32Subnormal( bSig, &bExp, &bSig ); ! 1790: } ! 1791: zExp = aExp + bExp - 0x7F; ! 1792: aSig = ( aSig | 0x00800000 )<<7; ! 1793: bSig = ( bSig | 0x00800000 )<<8; ! 1794: shift64RightJamming( ( (bits64) aSig ) * bSig, 32, &zSig64 ); ! 1795: zSig = zSig64; ! 1796: if ( 0 <= (sbits32) ( zSig<<1 ) ) { ! 1797: zSig <<= 1; ! 1798: --zExp; ! 1799: } ! 1800: return roundAndPackFloat32( zSign, zExp, zSig STATUS_VAR ); ! 1801: ! 1802: } ! 1803: ! 1804: /*---------------------------------------------------------------------------- ! 1805: | Returns the result of dividing the single-precision floating-point value `a' ! 1806: | by the corresponding value `b'. The operation is performed according to the ! 1807: | IEC/IEEE Standard for Binary Floating-Point Arithmetic. ! 1808: *----------------------------------------------------------------------------*/ ! 1809: ! 1810: float32 float32_div( float32 a, float32 b STATUS_PARAM ) ! 1811: { ! 1812: flag aSign, bSign, zSign; ! 1813: int16 aExp, bExp, zExp; ! 1814: bits32 aSig, bSig, zSig; ! 1815: ! 1816: aSig = extractFloat32Frac( a ); ! 1817: aExp = extractFloat32Exp( a ); ! 1818: aSign = extractFloat32Sign( a ); ! 1819: bSig = extractFloat32Frac( b ); ! 1820: bExp = extractFloat32Exp( b ); ! 1821: bSign = extractFloat32Sign( b ); ! 1822: zSign = aSign ^ bSign; ! 1823: if ( aExp == 0xFF ) { ! 1824: if ( aSig ) return propagateFloat32NaN( a, b STATUS_VAR ); ! 1825: if ( bExp == 0xFF ) { ! 1826: if ( bSig ) return propagateFloat32NaN( a, b STATUS_VAR ); ! 1827: float_raise( float_flag_invalid STATUS_VAR); ! 1828: return float32_default_nan; ! 1829: } ! 1830: return packFloat32( zSign, 0xFF, 0 ); ! 1831: } ! 1832: if ( bExp == 0xFF ) { ! 1833: if ( bSig ) return propagateFloat32NaN( a, b STATUS_VAR ); ! 1834: return packFloat32( zSign, 0, 0 ); ! 1835: } ! 1836: if ( bExp == 0 ) { ! 1837: if ( bSig == 0 ) { ! 1838: if ( ( aExp | aSig ) == 0 ) { ! 1839: float_raise( float_flag_invalid STATUS_VAR); ! 1840: return float32_default_nan; ! 1841: } ! 1842: float_raise( float_flag_divbyzero STATUS_VAR); ! 1843: return packFloat32( zSign, 0xFF, 0 ); ! 1844: } ! 1845: normalizeFloat32Subnormal( bSig, &bExp, &bSig ); ! 1846: } ! 1847: if ( aExp == 0 ) { ! 1848: if ( aSig == 0 ) return packFloat32( zSign, 0, 0 ); ! 1849: normalizeFloat32Subnormal( aSig, &aExp, &aSig ); ! 1850: } ! 1851: zExp = aExp - bExp + 0x7D; ! 1852: aSig = ( aSig | 0x00800000 )<<7; ! 1853: bSig = ( bSig | 0x00800000 )<<8; ! 1854: if ( bSig <= ( aSig + aSig ) ) { ! 1855: aSig >>= 1; ! 1856: ++zExp; ! 1857: } ! 1858: zSig = ( ( (bits64) aSig )<<32 ) / bSig; ! 1859: if ( ( zSig & 0x3F ) == 0 ) { ! 1860: zSig |= ( (bits64) bSig * zSig != ( (bits64) aSig )<<32 ); ! 1861: } ! 1862: return roundAndPackFloat32( zSign, zExp, zSig STATUS_VAR ); ! 1863: ! 1864: } ! 1865: ! 1866: /*---------------------------------------------------------------------------- ! 1867: | Returns the remainder of the single-precision floating-point value `a' ! 1868: | with respect to the corresponding value `b'. The operation is performed ! 1869: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. ! 1870: *----------------------------------------------------------------------------*/ ! 1871: ! 1872: float32 float32_rem( float32 a, float32 b STATUS_PARAM ) ! 1873: { ! 1874: flag aSign, bSign, zSign; ! 1875: int16 aExp, bExp, expDiff; ! 1876: bits32 aSig, bSig; ! 1877: bits32 q; ! 1878: bits64 aSig64, bSig64, q64; ! 1879: bits32 alternateASig; ! 1880: sbits32 sigMean; ! 1881: ! 1882: aSig = extractFloat32Frac( a ); ! 1883: aExp = extractFloat32Exp( a ); ! 1884: aSign = extractFloat32Sign( a ); ! 1885: bSig = extractFloat32Frac( b ); ! 1886: bExp = extractFloat32Exp( b ); ! 1887: bSign = extractFloat32Sign( b ); ! 1888: if ( aExp == 0xFF ) { ! 1889: if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) { ! 1890: return propagateFloat32NaN( a, b STATUS_VAR ); ! 1891: } ! 1892: float_raise( float_flag_invalid STATUS_VAR); ! 1893: return float32_default_nan; ! 1894: } ! 1895: if ( bExp == 0xFF ) { ! 1896: if ( bSig ) return propagateFloat32NaN( a, b STATUS_VAR ); ! 1897: return a; ! 1898: } ! 1899: if ( bExp == 0 ) { ! 1900: if ( bSig == 0 ) { ! 1901: float_raise( float_flag_invalid STATUS_VAR); ! 1902: return float32_default_nan; ! 1903: } ! 1904: normalizeFloat32Subnormal( bSig, &bExp, &bSig ); ! 1905: } ! 1906: if ( aExp == 0 ) { ! 1907: if ( aSig == 0 ) return a; ! 1908: normalizeFloat32Subnormal( aSig, &aExp, &aSig ); ! 1909: } ! 1910: expDiff = aExp - bExp; ! 1911: aSig |= 0x00800000; ! 1912: bSig |= 0x00800000; ! 1913: if ( expDiff < 32 ) { ! 1914: aSig <<= 8; ! 1915: bSig <<= 8; ! 1916: if ( expDiff < 0 ) { ! 1917: if ( expDiff < -1 ) return a; ! 1918: aSig >>= 1; ! 1919: } ! 1920: q = ( bSig <= aSig ); ! 1921: if ( q ) aSig -= bSig; ! 1922: if ( 0 < expDiff ) { ! 1923: q = ( ( (bits64) aSig )<<32 ) / bSig; ! 1924: q >>= 32 - expDiff; ! 1925: bSig >>= 2; ! 1926: aSig = ( ( aSig>>1 )<<( expDiff - 1 ) ) - bSig * q; ! 1927: } ! 1928: else { ! 1929: aSig >>= 2; ! 1930: bSig >>= 2; ! 1931: } ! 1932: } ! 1933: else { ! 1934: if ( bSig <= aSig ) aSig -= bSig; ! 1935: aSig64 = ( (bits64) aSig )<<40; ! 1936: bSig64 = ( (bits64) bSig )<<40; ! 1937: expDiff -= 64; ! 1938: while ( 0 < expDiff ) { ! 1939: q64 = estimateDiv128To64( aSig64, 0, bSig64 ); ! 1940: q64 = ( 2 < q64 ) ? q64 - 2 : 0; ! 1941: aSig64 = - ( ( bSig * q64 )<<38 ); ! 1942: expDiff -= 62; ! 1943: } ! 1944: expDiff += 64; ! 1945: q64 = estimateDiv128To64( aSig64, 0, bSig64 ); ! 1946: q64 = ( 2 < q64 ) ? q64 - 2 : 0; ! 1947: q = q64>>( 64 - expDiff ); ! 1948: bSig <<= 6; ! 1949: aSig = ( ( aSig64>>33 )<<( expDiff - 1 ) ) - bSig * q; ! 1950: } ! 1951: do { ! 1952: alternateASig = aSig; ! 1953: ++q; ! 1954: aSig -= bSig; ! 1955: } while ( 0 <= (sbits32) aSig ); ! 1956: sigMean = aSig + alternateASig; ! 1957: if ( ( sigMean < 0 ) || ( ( sigMean == 0 ) && ( q & 1 ) ) ) { ! 1958: aSig = alternateASig; ! 1959: } ! 1960: zSign = ( (sbits32) aSig < 0 ); ! 1961: if ( zSign ) aSig = - aSig; ! 1962: return normalizeRoundAndPackFloat32( aSign ^ zSign, bExp, aSig STATUS_VAR ); ! 1963: ! 1964: } ! 1965: ! 1966: /*---------------------------------------------------------------------------- ! 1967: | Returns the square root of the single-precision floating-point value `a'. ! 1968: | The operation is performed according to the IEC/IEEE Standard for Binary ! 1969: | Floating-Point Arithmetic. ! 1970: *----------------------------------------------------------------------------*/ ! 1971: ! 1972: float32 float32_sqrt( float32 a STATUS_PARAM ) ! 1973: { ! 1974: flag aSign; ! 1975: int16 aExp, zExp; ! 1976: bits32 aSig, zSig; ! 1977: bits64 rem, term; ! 1978: ! 1979: aSig = extractFloat32Frac( a ); ! 1980: aExp = extractFloat32Exp( a ); ! 1981: aSign = extractFloat32Sign( a ); ! 1982: if ( aExp == 0xFF ) { ! 1983: if ( aSig ) return propagateFloat32NaN( a, 0 STATUS_VAR ); ! 1984: if ( ! aSign ) return a; ! 1985: float_raise( float_flag_invalid STATUS_VAR); ! 1986: return float32_default_nan; ! 1987: } ! 1988: if ( aSign ) { ! 1989: if ( ( aExp | aSig ) == 0 ) return a; ! 1990: float_raise( float_flag_invalid STATUS_VAR); ! 1991: return float32_default_nan; ! 1992: } ! 1993: if ( aExp == 0 ) { ! 1994: if ( aSig == 0 ) return 0; ! 1995: normalizeFloat32Subnormal( aSig, &aExp, &aSig ); ! 1996: } ! 1997: zExp = ( ( aExp - 0x7F )>>1 ) + 0x7E; ! 1998: aSig = ( aSig | 0x00800000 )<<8; ! 1999: zSig = estimateSqrt32( aExp, aSig ) + 2; ! 2000: if ( ( zSig & 0x7F ) <= 5 ) { ! 2001: if ( zSig < 2 ) { ! 2002: zSig = 0x7FFFFFFF; ! 2003: goto roundAndPack; ! 2004: } ! 2005: aSig >>= aExp & 1; ! 2006: term = ( (bits64) zSig ) * zSig; ! 2007: rem = ( ( (bits64) aSig )<<32 ) - term; ! 2008: while ( (sbits64) rem < 0 ) { ! 2009: --zSig; ! 2010: rem += ( ( (bits64) zSig )<<1 ) | 1; ! 2011: } ! 2012: zSig |= ( rem != 0 ); ! 2013: } ! 2014: shift32RightJamming( zSig, 1, &zSig ); ! 2015: roundAndPack: ! 2016: return roundAndPackFloat32( 0, zExp, zSig STATUS_VAR ); ! 2017: ! 2018: } ! 2019: ! 2020: /*---------------------------------------------------------------------------- ! 2021: | Returns 1 if the single-precision floating-point value `a' is equal to ! 2022: | the corresponding value `b', and 0 otherwise. The comparison is performed ! 2023: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. ! 2024: *----------------------------------------------------------------------------*/ ! 2025: ! 2026: flag float32_eq( float32 a, float32 b STATUS_PARAM ) ! 2027: { ! 2028: ! 2029: if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) ! 2030: || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) ! 2031: ) { ! 2032: if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) { ! 2033: float_raise( float_flag_invalid STATUS_VAR); ! 2034: } ! 2035: return 0; ! 2036: } ! 2037: return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 ); ! 2038: ! 2039: } ! 2040: ! 2041: /*---------------------------------------------------------------------------- ! 2042: | Returns 1 if the single-precision floating-point value `a' is less than ! 2043: | or equal to the corresponding value `b', and 0 otherwise. The comparison ! 2044: | is performed according to the IEC/IEEE Standard for Binary Floating-Point ! 2045: | Arithmetic. ! 2046: *----------------------------------------------------------------------------*/ ! 2047: ! 2048: flag float32_le( float32 a, float32 b STATUS_PARAM ) ! 2049: { ! 2050: flag aSign, bSign; ! 2051: ! 2052: if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) ! 2053: || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) ! 2054: ) { ! 2055: float_raise( float_flag_invalid STATUS_VAR); ! 2056: return 0; ! 2057: } ! 2058: aSign = extractFloat32Sign( a ); ! 2059: bSign = extractFloat32Sign( b ); ! 2060: if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 ); ! 2061: return ( a == b ) || ( aSign ^ ( a < b ) ); ! 2062: ! 2063: } ! 2064: ! 2065: /*---------------------------------------------------------------------------- ! 2066: | Returns 1 if the single-precision floating-point value `a' is less than ! 2067: | the corresponding value `b', and 0 otherwise. The comparison is performed ! 2068: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. ! 2069: *----------------------------------------------------------------------------*/ ! 2070: ! 2071: flag float32_lt( float32 a, float32 b STATUS_PARAM ) ! 2072: { ! 2073: flag aSign, bSign; ! 2074: ! 2075: if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) ! 2076: || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) ! 2077: ) { ! 2078: float_raise( float_flag_invalid STATUS_VAR); ! 2079: return 0; ! 2080: } ! 2081: aSign = extractFloat32Sign( a ); ! 2082: bSign = extractFloat32Sign( b ); ! 2083: if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 ); ! 2084: return ( a != b ) && ( aSign ^ ( a < b ) ); ! 2085: ! 2086: } ! 2087: ! 2088: /*---------------------------------------------------------------------------- ! 2089: | Returns 1 if the single-precision floating-point value `a' is equal to ! 2090: | the corresponding value `b', and 0 otherwise. The invalid exception is ! 2091: | raised if either operand is a NaN. Otherwise, the comparison is performed ! 2092: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. ! 2093: *----------------------------------------------------------------------------*/ ! 2094: ! 2095: flag float32_eq_signaling( float32 a, float32 b STATUS_PARAM ) ! 2096: { ! 2097: ! 2098: if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) ! 2099: || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) ! 2100: ) { ! 2101: float_raise( float_flag_invalid STATUS_VAR); ! 2102: return 0; ! 2103: } ! 2104: return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 ); ! 2105: ! 2106: } ! 2107: ! 2108: /*---------------------------------------------------------------------------- ! 2109: | Returns 1 if the single-precision floating-point value `a' is less than or ! 2110: | equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not ! 2111: | cause an exception. Otherwise, the comparison is performed according to the ! 2112: | IEC/IEEE Standard for Binary Floating-Point Arithmetic. ! 2113: *----------------------------------------------------------------------------*/ ! 2114: ! 2115: flag float32_le_quiet( float32 a, float32 b STATUS_PARAM ) ! 2116: { ! 2117: flag aSign, bSign; ! 2118: ! 2119: if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) ! 2120: || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) ! 2121: ) { ! 2122: if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) { ! 2123: float_raise( float_flag_invalid STATUS_VAR); ! 2124: } ! 2125: return 0; ! 2126: } ! 2127: aSign = extractFloat32Sign( a ); ! 2128: bSign = extractFloat32Sign( b ); ! 2129: if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 ); ! 2130: return ( a == b ) || ( aSign ^ ( a < b ) ); ! 2131: ! 2132: } ! 2133: ! 2134: /*---------------------------------------------------------------------------- ! 2135: | Returns 1 if the single-precision floating-point value `a' is less than ! 2136: | the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an ! 2137: | exception. Otherwise, the comparison is performed according to the IEC/IEEE ! 2138: | Standard for Binary Floating-Point Arithmetic. ! 2139: *----------------------------------------------------------------------------*/ ! 2140: ! 2141: flag float32_lt_quiet( float32 a, float32 b STATUS_PARAM ) ! 2142: { ! 2143: flag aSign, bSign; ! 2144: ! 2145: if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) ! 2146: || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) ! 2147: ) { ! 2148: if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) { ! 2149: float_raise( float_flag_invalid STATUS_VAR); ! 2150: } ! 2151: return 0; ! 2152: } ! 2153: aSign = extractFloat32Sign( a ); ! 2154: bSign = extractFloat32Sign( b ); ! 2155: if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 ); ! 2156: return ( a != b ) && ( aSign ^ ( a < b ) ); ! 2157: ! 2158: } ! 2159: ! 2160: /*---------------------------------------------------------------------------- ! 2161: | Returns the result of converting the double-precision floating-point value ! 2162: | `a' to the 32-bit two's complement integer format. The conversion is ! 2163: | performed according to the IEC/IEEE Standard for Binary Floating-Point ! 2164: | Arithmetic---which means in particular that the conversion is rounded ! 2165: | according to the current rounding mode. If `a' is a NaN, the largest ! 2166: | positive integer is returned. Otherwise, if the conversion overflows, the ! 2167: | largest integer with the same sign as `a' is returned. ! 2168: *----------------------------------------------------------------------------*/ ! 2169: ! 2170: int32 float64_to_int32( float64 a STATUS_PARAM ) ! 2171: { ! 2172: flag aSign; ! 2173: int16 aExp, shiftCount; ! 2174: bits64 aSig; ! 2175: ! 2176: aSig = extractFloat64Frac( a ); ! 2177: aExp = extractFloat64Exp( a ); ! 2178: aSign = extractFloat64Sign( a ); ! 2179: if ( ( aExp == 0x7FF ) && aSig ) aSign = 0; ! 2180: if ( aExp ) aSig |= LIT64( 0x0010000000000000 ); ! 2181: shiftCount = 0x42C - aExp; ! 2182: if ( 0 < shiftCount ) shift64RightJamming( aSig, shiftCount, &aSig ); ! 2183: return roundAndPackInt32( aSign, aSig STATUS_VAR ); ! 2184: ! 2185: } ! 2186: ! 2187: /*---------------------------------------------------------------------------- ! 2188: | Returns the result of converting the double-precision floating-point value ! 2189: | `a' to the 32-bit two's complement integer format. The conversion is ! 2190: | performed according to the IEC/IEEE Standard for Binary Floating-Point ! 2191: | Arithmetic, except that the conversion is always rounded toward zero. ! 2192: | If `a' is a NaN, the largest positive integer is returned. Otherwise, if ! 2193: | the conversion overflows, the largest integer with the same sign as `a' is ! 2194: | returned. ! 2195: *----------------------------------------------------------------------------*/ ! 2196: ! 2197: int32 float64_to_int32_round_to_zero( float64 a STATUS_PARAM ) ! 2198: { ! 2199: flag aSign; ! 2200: int16 aExp, shiftCount; ! 2201: bits64 aSig, savedASig; ! 2202: int32 z; ! 2203: ! 2204: aSig = extractFloat64Frac( a ); ! 2205: aExp = extractFloat64Exp( a ); ! 2206: aSign = extractFloat64Sign( a ); ! 2207: if ( 0x41E < aExp ) { ! 2208: if ( ( aExp == 0x7FF ) && aSig ) aSign = 0; ! 2209: goto invalid; ! 2210: } ! 2211: else if ( aExp < 0x3FF ) { ! 2212: if ( aExp || aSig ) STATUS(float_exception_flags) |= float_flag_inexact; ! 2213: return 0; ! 2214: } ! 2215: aSig |= LIT64( 0x0010000000000000 ); ! 2216: shiftCount = 0x433 - aExp; ! 2217: savedASig = aSig; ! 2218: aSig >>= shiftCount; ! 2219: z = aSig; ! 2220: if ( aSign ) z = - z; ! 2221: if ( ( z < 0 ) ^ aSign ) { ! 2222: invalid: ! 2223: float_raise( float_flag_invalid STATUS_VAR); ! 2224: return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF; ! 2225: } ! 2226: if ( ( aSig<<shiftCount ) != savedASig ) { ! 2227: STATUS(float_exception_flags) |= float_flag_inexact; ! 2228: } ! 2229: return z; ! 2230: ! 2231: } ! 2232: ! 2233: /*---------------------------------------------------------------------------- ! 2234: | Returns the result of converting the double-precision floating-point value ! 2235: | `a' to the 64-bit two's complement integer format. The conversion is ! 2236: | performed according to the IEC/IEEE Standard for Binary Floating-Point ! 2237: | Arithmetic---which means in particular that the conversion is rounded ! 2238: | according to the current rounding mode. If `a' is a NaN, the largest ! 2239: | positive integer is returned. Otherwise, if the conversion overflows, the ! 2240: | largest integer with the same sign as `a' is returned. ! 2241: *----------------------------------------------------------------------------*/ ! 2242: ! 2243: int64 float64_to_int64( float64 a STATUS_PARAM ) ! 2244: { ! 2245: flag aSign; ! 2246: int16 aExp, shiftCount; ! 2247: bits64 aSig, aSigExtra; ! 2248: ! 2249: aSig = extractFloat64Frac( a ); ! 2250: aExp = extractFloat64Exp( a ); ! 2251: aSign = extractFloat64Sign( a ); ! 2252: if ( aExp ) aSig |= LIT64( 0x0010000000000000 ); ! 2253: shiftCount = 0x433 - aExp; ! 2254: if ( shiftCount <= 0 ) { ! 2255: if ( 0x43E < aExp ) { ! 2256: float_raise( float_flag_invalid STATUS_VAR); ! 2257: if ( ! aSign ! 2258: || ( ( aExp == 0x7FF ) ! 2259: && ( aSig != LIT64( 0x0010000000000000 ) ) ) ! 2260: ) { ! 2261: return LIT64( 0x7FFFFFFFFFFFFFFF ); ! 2262: } ! 2263: return (sbits64) LIT64( 0x8000000000000000 ); ! 2264: } ! 2265: aSigExtra = 0; ! 2266: aSig <<= - shiftCount; ! 2267: } ! 2268: else { ! 2269: shift64ExtraRightJamming( aSig, 0, shiftCount, &aSig, &aSigExtra ); ! 2270: } ! 2271: return roundAndPackInt64( aSign, aSig, aSigExtra STATUS_VAR ); ! 2272: ! 2273: } ! 2274: ! 2275: /*---------------------------------------------------------------------------- ! 2276: | Returns the result of converting the double-precision floating-point value ! 2277: | `a' to the 64-bit two's complement integer format. The conversion is ! 2278: | performed according to the IEC/IEEE Standard for Binary Floating-Point ! 2279: | Arithmetic, except that the conversion is always rounded toward zero. ! 2280: | If `a' is a NaN, the largest positive integer is returned. Otherwise, if ! 2281: | the conversion overflows, the largest integer with the same sign as `a' is ! 2282: | returned. ! 2283: *----------------------------------------------------------------------------*/ ! 2284: ! 2285: int64 float64_to_int64_round_to_zero( float64 a STATUS_PARAM ) ! 2286: { ! 2287: flag aSign; ! 2288: int16 aExp, shiftCount; ! 2289: bits64 aSig; ! 2290: int64 z; ! 2291: ! 2292: aSig = extractFloat64Frac( a ); ! 2293: aExp = extractFloat64Exp( a ); ! 2294: aSign = extractFloat64Sign( a ); ! 2295: if ( aExp ) aSig |= LIT64( 0x0010000000000000 ); ! 2296: shiftCount = aExp - 0x433; ! 2297: if ( 0 <= shiftCount ) { ! 2298: if ( 0x43E <= aExp ) { ! 2299: if ( a != LIT64( 0xC3E0000000000000 ) ) { ! 2300: float_raise( float_flag_invalid STATUS_VAR); ! 2301: if ( ! aSign ! 2302: || ( ( aExp == 0x7FF ) ! 2303: && ( aSig != LIT64( 0x0010000000000000 ) ) ) ! 2304: ) { ! 2305: return LIT64( 0x7FFFFFFFFFFFFFFF ); ! 2306: } ! 2307: } ! 2308: return (sbits64) LIT64( 0x8000000000000000 ); ! 2309: } ! 2310: z = aSig<<shiftCount; ! 2311: } ! 2312: else { ! 2313: if ( aExp < 0x3FE ) { ! 2314: if ( aExp | aSig ) STATUS(float_exception_flags) |= float_flag_inexact; ! 2315: return 0; ! 2316: } ! 2317: z = aSig>>( - shiftCount ); ! 2318: if ( (bits64) ( aSig<<( shiftCount & 63 ) ) ) { ! 2319: STATUS(float_exception_flags) |= float_flag_inexact; ! 2320: } ! 2321: } ! 2322: if ( aSign ) z = - z; ! 2323: return z; ! 2324: ! 2325: } ! 2326: ! 2327: /*---------------------------------------------------------------------------- ! 2328: | Returns the result of converting the double-precision floating-point value ! 2329: | `a' to the single-precision floating-point format. The conversion is ! 2330: | performed according to the IEC/IEEE Standard for Binary Floating-Point ! 2331: | Arithmetic. ! 2332: *----------------------------------------------------------------------------*/ ! 2333: ! 2334: float32 float64_to_float32( float64 a STATUS_PARAM ) ! 2335: { ! 2336: flag aSign; ! 2337: int16 aExp; ! 2338: bits64 aSig; ! 2339: bits32 zSig; ! 2340: ! 2341: aSig = extractFloat64Frac( a ); ! 2342: aExp = extractFloat64Exp( a ); ! 2343: aSign = extractFloat64Sign( a ); ! 2344: if ( aExp == 0x7FF ) { ! 2345: if ( aSig ) return commonNaNToFloat32( float64ToCommonNaN( a STATUS_VAR ) ); ! 2346: return packFloat32( aSign, 0xFF, 0 ); ! 2347: } ! 2348: shift64RightJamming( aSig, 22, &aSig ); ! 2349: zSig = aSig; ! 2350: if ( aExp || zSig ) { ! 2351: zSig |= 0x40000000; ! 2352: aExp -= 0x381; ! 2353: } ! 2354: return roundAndPackFloat32( aSign, aExp, zSig STATUS_VAR ); ! 2355: ! 2356: } ! 2357: ! 2358: #ifdef FLOATX80 ! 2359: ! 2360: /*---------------------------------------------------------------------------- ! 2361: | Returns the result of converting the double-precision floating-point value ! 2362: | `a' to the extended double-precision floating-point format. The conversion ! 2363: | is performed according to the IEC/IEEE Standard for Binary Floating-Point ! 2364: | Arithmetic. ! 2365: *----------------------------------------------------------------------------*/ ! 2366: ! 2367: floatx80 float64_to_floatx80( float64 a STATUS_PARAM ) ! 2368: { ! 2369: flag aSign; ! 2370: int16 aExp; ! 2371: bits64 aSig; ! 2372: ! 2373: aSig = extractFloat64Frac( a ); ! 2374: aExp = extractFloat64Exp( a ); ! 2375: aSign = extractFloat64Sign( a ); ! 2376: if ( aExp == 0x7FF ) { ! 2377: if ( aSig ) return commonNaNToFloatx80( float64ToCommonNaN( a STATUS_VAR ) ); ! 2378: return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); ! 2379: } ! 2380: if ( aExp == 0 ) { ! 2381: if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 ); ! 2382: normalizeFloat64Subnormal( aSig, &aExp, &aSig ); ! 2383: } ! 2384: return ! 2385: packFloatx80( ! 2386: aSign, aExp + 0x3C00, ( aSig | LIT64( 0x0010000000000000 ) )<<11 ); ! 2387: ! 2388: } ! 2389: ! 2390: #endif ! 2391: ! 2392: #ifdef FLOAT128 ! 2393: ! 2394: /*---------------------------------------------------------------------------- ! 2395: | Returns the result of converting the double-precision floating-point value ! 2396: | `a' to the quadruple-precision floating-point format. The conversion is ! 2397: | performed according to the IEC/IEEE Standard for Binary Floating-Point ! 2398: | Arithmetic. ! 2399: *----------------------------------------------------------------------------*/ ! 2400: ! 2401: float128 float64_to_float128( float64 a STATUS_PARAM ) ! 2402: { ! 2403: flag aSign; ! 2404: int16 aExp; ! 2405: bits64 aSig, zSig0, zSig1; ! 2406: ! 2407: aSig = extractFloat64Frac( a ); ! 2408: aExp = extractFloat64Exp( a ); ! 2409: aSign = extractFloat64Sign( a ); ! 2410: if ( aExp == 0x7FF ) { ! 2411: if ( aSig ) return commonNaNToFloat128( float64ToCommonNaN( a STATUS_VAR ) ); ! 2412: return packFloat128( aSign, 0x7FFF, 0, 0 ); ! 2413: } ! 2414: if ( aExp == 0 ) { ! 2415: if ( aSig == 0 ) return packFloat128( aSign, 0, 0, 0 ); ! 2416: normalizeFloat64Subnormal( aSig, &aExp, &aSig ); ! 2417: --aExp; ! 2418: } ! 2419: shift128Right( aSig, 0, 4, &zSig0, &zSig1 ); ! 2420: return packFloat128( aSign, aExp + 0x3C00, zSig0, zSig1 ); ! 2421: ! 2422: } ! 2423: ! 2424: #endif ! 2425: ! 2426: /*---------------------------------------------------------------------------- ! 2427: | Rounds the double-precision floating-point value `a' to an integer, and ! 2428: | returns the result as a double-precision floating-point value. The ! 2429: | operation is performed according to the IEC/IEEE Standard for Binary ! 2430: | Floating-Point Arithmetic. ! 2431: *----------------------------------------------------------------------------*/ ! 2432: ! 2433: float64 float64_round_to_int( float64 a STATUS_PARAM ) ! 2434: { ! 2435: flag aSign; ! 2436: int16 aExp; ! 2437: bits64 lastBitMask, roundBitsMask; ! 2438: int8 roundingMode; ! 2439: float64 z; ! 2440: ! 2441: aExp = extractFloat64Exp( a ); ! 2442: if ( 0x433 <= aExp ) { ! 2443: if ( ( aExp == 0x7FF ) && extractFloat64Frac( a ) ) { ! 2444: return propagateFloat64NaN( a, a STATUS_VAR ); ! 2445: } ! 2446: return a; ! 2447: } ! 2448: if ( aExp < 0x3FF ) { ! 2449: if ( (bits64) ( a<<1 ) == 0 ) return a; ! 2450: STATUS(float_exception_flags) |= float_flag_inexact; ! 2451: aSign = extractFloat64Sign( a ); ! 2452: switch ( STATUS(float_rounding_mode) ) { ! 2453: case float_round_nearest_even: ! 2454: if ( ( aExp == 0x3FE ) && extractFloat64Frac( a ) ) { ! 2455: return packFloat64( aSign, 0x3FF, 0 ); ! 2456: } ! 2457: break; ! 2458: case float_round_down: ! 2459: return aSign ? LIT64( 0xBFF0000000000000 ) : 0; ! 2460: case float_round_up: ! 2461: return ! 2462: aSign ? LIT64( 0x8000000000000000 ) : LIT64( 0x3FF0000000000000 ); ! 2463: } ! 2464: return packFloat64( aSign, 0, 0 ); ! 2465: } ! 2466: lastBitMask = 1; ! 2467: lastBitMask <<= 0x433 - aExp; ! 2468: roundBitsMask = lastBitMask - 1; ! 2469: z = a; ! 2470: roundingMode = STATUS(float_rounding_mode); ! 2471: if ( roundingMode == float_round_nearest_even ) { ! 2472: z += lastBitMask>>1; ! 2473: if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask; ! 2474: } ! 2475: else if ( roundingMode != float_round_to_zero ) { ! 2476: if ( extractFloat64Sign( z ) ^ ( roundingMode == float_round_up ) ) { ! 2477: z += roundBitsMask; ! 2478: } ! 2479: } ! 2480: z &= ~ roundBitsMask; ! 2481: if ( z != a ) STATUS(float_exception_flags) |= float_flag_inexact; ! 2482: return z; ! 2483: ! 2484: } ! 2485: ! 2486: /*---------------------------------------------------------------------------- ! 2487: | Returns the result of adding the absolute values of the double-precision ! 2488: | floating-point values `a' and `b'. If `zSign' is 1, the sum is negated ! 2489: | before being returned. `zSign' is ignored if the result is a NaN. ! 2490: | The addition is performed according to the IEC/IEEE Standard for Binary ! 2491: | Floating-Point Arithmetic. ! 2492: *----------------------------------------------------------------------------*/ ! 2493: ! 2494: static float64 addFloat64Sigs( float64 a, float64 b, flag zSign STATUS_PARAM ) ! 2495: { ! 2496: int16 aExp, bExp, zExp; ! 2497: bits64 aSig, bSig, zSig; ! 2498: int16 expDiff; ! 2499: ! 2500: aSig = extractFloat64Frac( a ); ! 2501: aExp = extractFloat64Exp( a ); ! 2502: bSig = extractFloat64Frac( b ); ! 2503: bExp = extractFloat64Exp( b ); ! 2504: expDiff = aExp - bExp; ! 2505: aSig <<= 9; ! 2506: bSig <<= 9; ! 2507: if ( 0 < expDiff ) { ! 2508: if ( aExp == 0x7FF ) { ! 2509: if ( aSig ) return propagateFloat64NaN( a, b STATUS_VAR ); ! 2510: return a; ! 2511: } ! 2512: if ( bExp == 0 ) { ! 2513: --expDiff; ! 2514: } ! 2515: else { ! 2516: bSig |= LIT64( 0x2000000000000000 ); ! 2517: } ! 2518: shift64RightJamming( bSig, expDiff, &bSig ); ! 2519: zExp = aExp; ! 2520: } ! 2521: else if ( expDiff < 0 ) { ! 2522: if ( bExp == 0x7FF ) { ! 2523: if ( bSig ) return propagateFloat64NaN( a, b STATUS_VAR ); ! 2524: return packFloat64( zSign, 0x7FF, 0 ); ! 2525: } ! 2526: if ( aExp == 0 ) { ! 2527: ++expDiff; ! 2528: } ! 2529: else { ! 2530: aSig |= LIT64( 0x2000000000000000 ); ! 2531: } ! 2532: shift64RightJamming( aSig, - expDiff, &aSig ); ! 2533: zExp = bExp; ! 2534: } ! 2535: else { ! 2536: if ( aExp == 0x7FF ) { ! 2537: if ( aSig | bSig ) return propagateFloat64NaN( a, b STATUS_VAR ); ! 2538: return a; ! 2539: } ! 2540: if ( aExp == 0 ) return packFloat64( zSign, 0, ( aSig + bSig )>>9 ); ! 2541: zSig = LIT64( 0x4000000000000000 ) + aSig + bSig; ! 2542: zExp = aExp; ! 2543: goto roundAndPack; ! 2544: } ! 2545: aSig |= LIT64( 0x2000000000000000 ); ! 2546: zSig = ( aSig + bSig )<<1; ! 2547: --zExp; ! 2548: if ( (sbits64) zSig < 0 ) { ! 2549: zSig = aSig + bSig; ! 2550: ++zExp; ! 2551: } ! 2552: roundAndPack: ! 2553: return roundAndPackFloat64( zSign, zExp, zSig STATUS_VAR ); ! 2554: ! 2555: } ! 2556: ! 2557: /*---------------------------------------------------------------------------- ! 2558: | Returns the result of subtracting the absolute values of the double- ! 2559: | precision floating-point values `a' and `b'. If `zSign' is 1, the ! 2560: | difference is negated before being returned. `zSign' is ignored if the ! 2561: | result is a NaN. The subtraction is performed according to the IEC/IEEE ! 2562: | Standard for Binary Floating-Point Arithmetic. ! 2563: *----------------------------------------------------------------------------*/ ! 2564: ! 2565: static float64 subFloat64Sigs( float64 a, float64 b, flag zSign STATUS_PARAM ) ! 2566: { ! 2567: int16 aExp, bExp, zExp; ! 2568: bits64 aSig, bSig, zSig; ! 2569: int16 expDiff; ! 2570: ! 2571: aSig = extractFloat64Frac( a ); ! 2572: aExp = extractFloat64Exp( a ); ! 2573: bSig = extractFloat64Frac( b ); ! 2574: bExp = extractFloat64Exp( b ); ! 2575: expDiff = aExp - bExp; ! 2576: aSig <<= 10; ! 2577: bSig <<= 10; ! 2578: if ( 0 < expDiff ) goto aExpBigger; ! 2579: if ( expDiff < 0 ) goto bExpBigger; ! 2580: if ( aExp == 0x7FF ) { ! 2581: if ( aSig | bSig ) return propagateFloat64NaN( a, b STATUS_VAR ); ! 2582: float_raise( float_flag_invalid STATUS_VAR); ! 2583: return float64_default_nan; ! 2584: } ! 2585: if ( aExp == 0 ) { ! 2586: aExp = 1; ! 2587: bExp = 1; ! 2588: } ! 2589: if ( bSig < aSig ) goto aBigger; ! 2590: if ( aSig < bSig ) goto bBigger; ! 2591: return packFloat64( STATUS(float_rounding_mode) == float_round_down, 0, 0 ); ! 2592: bExpBigger: ! 2593: if ( bExp == 0x7FF ) { ! 2594: if ( bSig ) return propagateFloat64NaN( a, b STATUS_VAR ); ! 2595: return packFloat64( zSign ^ 1, 0x7FF, 0 ); ! 2596: } ! 2597: if ( aExp == 0 ) { ! 2598: ++expDiff; ! 2599: } ! 2600: else { ! 2601: aSig |= LIT64( 0x4000000000000000 ); ! 2602: } ! 2603: shift64RightJamming( aSig, - expDiff, &aSig ); ! 2604: bSig |= LIT64( 0x4000000000000000 ); ! 2605: bBigger: ! 2606: zSig = bSig - aSig; ! 2607: zExp = bExp; ! 2608: zSign ^= 1; ! 2609: goto normalizeRoundAndPack; ! 2610: aExpBigger: ! 2611: if ( aExp == 0x7FF ) { ! 2612: if ( aSig ) return propagateFloat64NaN( a, b STATUS_VAR ); ! 2613: return a; ! 2614: } ! 2615: if ( bExp == 0 ) { ! 2616: --expDiff; ! 2617: } ! 2618: else { ! 2619: bSig |= LIT64( 0x4000000000000000 ); ! 2620: } ! 2621: shift64RightJamming( bSig, expDiff, &bSig ); ! 2622: aSig |= LIT64( 0x4000000000000000 ); ! 2623: aBigger: ! 2624: zSig = aSig - bSig; ! 2625: zExp = aExp; ! 2626: normalizeRoundAndPack: ! 2627: --zExp; ! 2628: return normalizeRoundAndPackFloat64( zSign, zExp, zSig STATUS_VAR ); ! 2629: ! 2630: } ! 2631: ! 2632: /*---------------------------------------------------------------------------- ! 2633: | Returns the result of adding the double-precision floating-point values `a' ! 2634: | and `b'. The operation is performed according to the IEC/IEEE Standard for ! 2635: | Binary Floating-Point Arithmetic. ! 2636: *----------------------------------------------------------------------------*/ ! 2637: ! 2638: float64 float64_add( float64 a, float64 b STATUS_PARAM ) ! 2639: { ! 2640: flag aSign, bSign; ! 2641: ! 2642: aSign = extractFloat64Sign( a ); ! 2643: bSign = extractFloat64Sign( b ); ! 2644: if ( aSign == bSign ) { ! 2645: return addFloat64Sigs( a, b, aSign STATUS_VAR ); ! 2646: } ! 2647: else { ! 2648: return subFloat64Sigs( a, b, aSign STATUS_VAR ); ! 2649: } ! 2650: ! 2651: } ! 2652: ! 2653: /*---------------------------------------------------------------------------- ! 2654: | Returns the result of subtracting the double-precision floating-point values ! 2655: | `a' and `b'. The operation is performed according to the IEC/IEEE Standard ! 2656: | for Binary Floating-Point Arithmetic. ! 2657: *----------------------------------------------------------------------------*/ ! 2658: ! 2659: float64 float64_sub( float64 a, float64 b STATUS_PARAM ) ! 2660: { ! 2661: flag aSign, bSign; ! 2662: ! 2663: aSign = extractFloat64Sign( a ); ! 2664: bSign = extractFloat64Sign( b ); ! 2665: if ( aSign == bSign ) { ! 2666: return subFloat64Sigs( a, b, aSign STATUS_VAR ); ! 2667: } ! 2668: else { ! 2669: return addFloat64Sigs( a, b, aSign STATUS_VAR ); ! 2670: } ! 2671: ! 2672: } ! 2673: ! 2674: /*---------------------------------------------------------------------------- ! 2675: | Returns the result of multiplying the double-precision floating-point values ! 2676: | `a' and `b'. The operation is performed according to the IEC/IEEE Standard ! 2677: | for Binary Floating-Point Arithmetic. ! 2678: *----------------------------------------------------------------------------*/ ! 2679: ! 2680: float64 float64_mul( float64 a, float64 b STATUS_PARAM ) ! 2681: { ! 2682: flag aSign, bSign, zSign; ! 2683: int16 aExp, bExp, zExp; ! 2684: bits64 aSig, bSig, zSig0, zSig1; ! 2685: ! 2686: aSig = extractFloat64Frac( a ); ! 2687: aExp = extractFloat64Exp( a ); ! 2688: aSign = extractFloat64Sign( a ); ! 2689: bSig = extractFloat64Frac( b ); ! 2690: bExp = extractFloat64Exp( b ); ! 2691: bSign = extractFloat64Sign( b ); ! 2692: zSign = aSign ^ bSign; ! 2693: if ( aExp == 0x7FF ) { ! 2694: if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) { ! 2695: return propagateFloat64NaN( a, b STATUS_VAR ); ! 2696: } ! 2697: if ( ( bExp | bSig ) == 0 ) { ! 2698: float_raise( float_flag_invalid STATUS_VAR); ! 2699: return float64_default_nan; ! 2700: } ! 2701: return packFloat64( zSign, 0x7FF, 0 ); ! 2702: } ! 2703: if ( bExp == 0x7FF ) { ! 2704: if ( bSig ) return propagateFloat64NaN( a, b STATUS_VAR ); ! 2705: if ( ( aExp | aSig ) == 0 ) { ! 2706: float_raise( float_flag_invalid STATUS_VAR); ! 2707: return float64_default_nan; ! 2708: } ! 2709: return packFloat64( zSign, 0x7FF, 0 ); ! 2710: } ! 2711: if ( aExp == 0 ) { ! 2712: if ( aSig == 0 ) return packFloat64( zSign, 0, 0 ); ! 2713: normalizeFloat64Subnormal( aSig, &aExp, &aSig ); ! 2714: } ! 2715: if ( bExp == 0 ) { ! 2716: if ( bSig == 0 ) return packFloat64( zSign, 0, 0 ); ! 2717: normalizeFloat64Subnormal( bSig, &bExp, &bSig ); ! 2718: } ! 2719: zExp = aExp + bExp - 0x3FF; ! 2720: aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<10; ! 2721: bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11; ! 2722: mul64To128( aSig, bSig, &zSig0, &zSig1 ); ! 2723: zSig0 |= ( zSig1 != 0 ); ! 2724: if ( 0 <= (sbits64) ( zSig0<<1 ) ) { ! 2725: zSig0 <<= 1; ! 2726: --zExp; ! 2727: } ! 2728: return roundAndPackFloat64( zSign, zExp, zSig0 STATUS_VAR ); ! 2729: ! 2730: } ! 2731: ! 2732: /*---------------------------------------------------------------------------- ! 2733: | Returns the result of dividing the double-precision floating-point value `a' ! 2734: | by the corresponding value `b'. The operation is performed according to ! 2735: | the IEC/IEEE Standard for Binary Floating-Point Arithmetic. ! 2736: *----------------------------------------------------------------------------*/ ! 2737: ! 2738: float64 float64_div( float64 a, float64 b STATUS_PARAM ) ! 2739: { ! 2740: flag aSign, bSign, zSign; ! 2741: int16 aExp, bExp, zExp; ! 2742: bits64 aSig, bSig, zSig; ! 2743: bits64 rem0, rem1; ! 2744: bits64 term0, term1; ! 2745: ! 2746: aSig = extractFloat64Frac( a ); ! 2747: aExp = extractFloat64Exp( a ); ! 2748: aSign = extractFloat64Sign( a ); ! 2749: bSig = extractFloat64Frac( b ); ! 2750: bExp = extractFloat64Exp( b ); ! 2751: bSign = extractFloat64Sign( b ); ! 2752: zSign = aSign ^ bSign; ! 2753: if ( aExp == 0x7FF ) { ! 2754: if ( aSig ) return propagateFloat64NaN( a, b STATUS_VAR ); ! 2755: if ( bExp == 0x7FF ) { ! 2756: if ( bSig ) return propagateFloat64NaN( a, b STATUS_VAR ); ! 2757: float_raise( float_flag_invalid STATUS_VAR); ! 2758: return float64_default_nan; ! 2759: } ! 2760: return packFloat64( zSign, 0x7FF, 0 ); ! 2761: } ! 2762: if ( bExp == 0x7FF ) { ! 2763: if ( bSig ) return propagateFloat64NaN( a, b STATUS_VAR ); ! 2764: return packFloat64( zSign, 0, 0 ); ! 2765: } ! 2766: if ( bExp == 0 ) { ! 2767: if ( bSig == 0 ) { ! 2768: if ( ( aExp | aSig ) == 0 ) { ! 2769: float_raise( float_flag_invalid STATUS_VAR); ! 2770: return float64_default_nan; ! 2771: } ! 2772: float_raise( float_flag_divbyzero STATUS_VAR); ! 2773: return packFloat64( zSign, 0x7FF, 0 ); ! 2774: } ! 2775: normalizeFloat64Subnormal( bSig, &bExp, &bSig ); ! 2776: } ! 2777: if ( aExp == 0 ) { ! 2778: if ( aSig == 0 ) return packFloat64( zSign, 0, 0 ); ! 2779: normalizeFloat64Subnormal( aSig, &aExp, &aSig ); ! 2780: } ! 2781: zExp = aExp - bExp + 0x3FD; ! 2782: aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<10; ! 2783: bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11; ! 2784: if ( bSig <= ( aSig + aSig ) ) { ! 2785: aSig >>= 1; ! 2786: ++zExp; ! 2787: } ! 2788: zSig = estimateDiv128To64( aSig, 0, bSig ); ! 2789: if ( ( zSig & 0x1FF ) <= 2 ) { ! 2790: mul64To128( bSig, zSig, &term0, &term1 ); ! 2791: sub128( aSig, 0, term0, term1, &rem0, &rem1 ); ! 2792: while ( (sbits64) rem0 < 0 ) { ! 2793: --zSig; ! 2794: add128( rem0, rem1, 0, bSig, &rem0, &rem1 ); ! 2795: } ! 2796: zSig |= ( rem1 != 0 ); ! 2797: } ! 2798: return roundAndPackFloat64( zSign, zExp, zSig STATUS_VAR ); ! 2799: ! 2800: } ! 2801: ! 2802: /*---------------------------------------------------------------------------- ! 2803: | Returns the remainder of the double-precision floating-point value `a' ! 2804: | with respect to the corresponding value `b'. The operation is performed ! 2805: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. ! 2806: *----------------------------------------------------------------------------*/ ! 2807: ! 2808: float64 float64_rem( float64 a, float64 b STATUS_PARAM ) ! 2809: { ! 2810: flag aSign, bSign, zSign; ! 2811: int16 aExp, bExp, expDiff; ! 2812: bits64 aSig, bSig; ! 2813: bits64 q, alternateASig; ! 2814: sbits64 sigMean; ! 2815: ! 2816: aSig = extractFloat64Frac( a ); ! 2817: aExp = extractFloat64Exp( a ); ! 2818: aSign = extractFloat64Sign( a ); ! 2819: bSig = extractFloat64Frac( b ); ! 2820: bExp = extractFloat64Exp( b ); ! 2821: bSign = extractFloat64Sign( b ); ! 2822: if ( aExp == 0x7FF ) { ! 2823: if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) { ! 2824: return propagateFloat64NaN( a, b STATUS_VAR ); ! 2825: } ! 2826: float_raise( float_flag_invalid STATUS_VAR); ! 2827: return float64_default_nan; ! 2828: } ! 2829: if ( bExp == 0x7FF ) { ! 2830: if ( bSig ) return propagateFloat64NaN( a, b STATUS_VAR ); ! 2831: return a; ! 2832: } ! 2833: if ( bExp == 0 ) { ! 2834: if ( bSig == 0 ) { ! 2835: float_raise( float_flag_invalid STATUS_VAR); ! 2836: return float64_default_nan; ! 2837: } ! 2838: normalizeFloat64Subnormal( bSig, &bExp, &bSig ); ! 2839: } ! 2840: if ( aExp == 0 ) { ! 2841: if ( aSig == 0 ) return a; ! 2842: normalizeFloat64Subnormal( aSig, &aExp, &aSig ); ! 2843: } ! 2844: expDiff = aExp - bExp; ! 2845: aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<11; ! 2846: bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11; ! 2847: if ( expDiff < 0 ) { ! 2848: if ( expDiff < -1 ) return a; ! 2849: aSig >>= 1; ! 2850: } ! 2851: q = ( bSig <= aSig ); ! 2852: if ( q ) aSig -= bSig; ! 2853: expDiff -= 64; ! 2854: while ( 0 < expDiff ) { ! 2855: q = estimateDiv128To64( aSig, 0, bSig ); ! 2856: q = ( 2 < q ) ? q - 2 : 0; ! 2857: aSig = - ( ( bSig>>2 ) * q ); ! 2858: expDiff -= 62; ! 2859: } ! 2860: expDiff += 64; ! 2861: if ( 0 < expDiff ) { ! 2862: q = estimateDiv128To64( aSig, 0, bSig ); ! 2863: q = ( 2 < q ) ? q - 2 : 0; ! 2864: q >>= 64 - expDiff; ! 2865: bSig >>= 2; ! 2866: aSig = ( ( aSig>>1 )<<( expDiff - 1 ) ) - bSig * q; ! 2867: } ! 2868: else { ! 2869: aSig >>= 2; ! 2870: bSig >>= 2; ! 2871: } ! 2872: do { ! 2873: alternateASig = aSig; ! 2874: ++q; ! 2875: aSig -= bSig; ! 2876: } while ( 0 <= (sbits64) aSig ); ! 2877: sigMean = aSig + alternateASig; ! 2878: if ( ( sigMean < 0 ) || ( ( sigMean == 0 ) && ( q & 1 ) ) ) { ! 2879: aSig = alternateASig; ! 2880: } ! 2881: zSign = ( (sbits64) aSig < 0 ); ! 2882: if ( zSign ) aSig = - aSig; ! 2883: return normalizeRoundAndPackFloat64( aSign ^ zSign, bExp, aSig STATUS_VAR ); ! 2884: ! 2885: } ! 2886: ! 2887: /*---------------------------------------------------------------------------- ! 2888: | Returns the square root of the double-precision floating-point value `a'. ! 2889: | The operation is performed according to the IEC/IEEE Standard for Binary ! 2890: | Floating-Point Arithmetic. ! 2891: *----------------------------------------------------------------------------*/ ! 2892: ! 2893: float64 float64_sqrt( float64 a STATUS_PARAM ) ! 2894: { ! 2895: flag aSign; ! 2896: int16 aExp, zExp; ! 2897: bits64 aSig, zSig, doubleZSig; ! 2898: bits64 rem0, rem1, term0, term1; ! 2899: ! 2900: aSig = extractFloat64Frac( a ); ! 2901: aExp = extractFloat64Exp( a ); ! 2902: aSign = extractFloat64Sign( a ); ! 2903: if ( aExp == 0x7FF ) { ! 2904: if ( aSig ) return propagateFloat64NaN( a, a STATUS_VAR ); ! 2905: if ( ! aSign ) return a; ! 2906: float_raise( float_flag_invalid STATUS_VAR); ! 2907: return float64_default_nan; ! 2908: } ! 2909: if ( aSign ) { ! 2910: if ( ( aExp | aSig ) == 0 ) return a; ! 2911: float_raise( float_flag_invalid STATUS_VAR); ! 2912: return float64_default_nan; ! 2913: } ! 2914: if ( aExp == 0 ) { ! 2915: if ( aSig == 0 ) return 0; ! 2916: normalizeFloat64Subnormal( aSig, &aExp, &aSig ); ! 2917: } ! 2918: zExp = ( ( aExp - 0x3FF )>>1 ) + 0x3FE; ! 2919: aSig |= LIT64( 0x0010000000000000 ); ! 2920: zSig = estimateSqrt32( aExp, aSig>>21 ); ! 2921: aSig <<= 9 - ( aExp & 1 ); ! 2922: zSig = estimateDiv128To64( aSig, 0, zSig<<32 ) + ( zSig<<30 ); ! 2923: if ( ( zSig & 0x1FF ) <= 5 ) { ! 2924: doubleZSig = zSig<<1; ! 2925: mul64To128( zSig, zSig, &term0, &term1 ); ! 2926: sub128( aSig, 0, term0, term1, &rem0, &rem1 ); ! 2927: while ( (sbits64) rem0 < 0 ) { ! 2928: --zSig; ! 2929: doubleZSig -= 2; ! 2930: add128( rem0, rem1, zSig>>63, doubleZSig | 1, &rem0, &rem1 ); ! 2931: } ! 2932: zSig |= ( ( rem0 | rem1 ) != 0 ); ! 2933: } ! 2934: return roundAndPackFloat64( 0, zExp, zSig STATUS_VAR ); ! 2935: ! 2936: } ! 2937: ! 2938: /*---------------------------------------------------------------------------- ! 2939: | Returns 1 if the double-precision floating-point value `a' is equal to the ! 2940: | corresponding value `b', and 0 otherwise. The comparison is performed ! 2941: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. ! 2942: *----------------------------------------------------------------------------*/ ! 2943: ! 2944: flag float64_eq( float64 a, float64 b STATUS_PARAM ) ! 2945: { ! 2946: ! 2947: if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) ! 2948: || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) ! 2949: ) { ! 2950: if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) { ! 2951: float_raise( float_flag_invalid STATUS_VAR); ! 2952: } ! 2953: return 0; ! 2954: } ! 2955: return ( a == b ) || ( (bits64) ( ( a | b )<<1 ) == 0 ); ! 2956: ! 2957: } ! 2958: ! 2959: /*---------------------------------------------------------------------------- ! 2960: | Returns 1 if the double-precision floating-point value `a' is less than or ! 2961: | equal to the corresponding value `b', and 0 otherwise. The comparison is ! 2962: | performed according to the IEC/IEEE Standard for Binary Floating-Point ! 2963: | Arithmetic. ! 2964: *----------------------------------------------------------------------------*/ ! 2965: ! 2966: flag float64_le( float64 a, float64 b STATUS_PARAM ) ! 2967: { ! 2968: flag aSign, bSign; ! 2969: ! 2970: if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) ! 2971: || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) ! 2972: ) { ! 2973: float_raise( float_flag_invalid STATUS_VAR); ! 2974: return 0; ! 2975: } ! 2976: aSign = extractFloat64Sign( a ); ! 2977: bSign = extractFloat64Sign( b ); ! 2978: if ( aSign != bSign ) return aSign || ( (bits64) ( ( a | b )<<1 ) == 0 ); ! 2979: return ( a == b ) || ( aSign ^ ( a < b ) ); ! 2980: ! 2981: } ! 2982: ! 2983: /*---------------------------------------------------------------------------- ! 2984: | Returns 1 if the double-precision floating-point value `a' is less than ! 2985: | the corresponding value `b', and 0 otherwise. The comparison is performed ! 2986: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. ! 2987: *----------------------------------------------------------------------------*/ ! 2988: ! 2989: flag float64_lt( float64 a, float64 b STATUS_PARAM ) ! 2990: { ! 2991: flag aSign, bSign; ! 2992: ! 2993: if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) ! 2994: || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) ! 2995: ) { ! 2996: float_raise( float_flag_invalid STATUS_VAR); ! 2997: return 0; ! 2998: } ! 2999: aSign = extractFloat64Sign( a ); ! 3000: bSign = extractFloat64Sign( b ); ! 3001: if ( aSign != bSign ) return aSign && ( (bits64) ( ( a | b )<<1 ) != 0 ); ! 3002: return ( a != b ) && ( aSign ^ ( a < b ) ); ! 3003: ! 3004: } ! 3005: ! 3006: /*---------------------------------------------------------------------------- ! 3007: | Returns 1 if the double-precision floating-point value `a' is equal to the ! 3008: | corresponding value `b', and 0 otherwise. The invalid exception is raised ! 3009: | if either operand is a NaN. Otherwise, the comparison is performed ! 3010: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. ! 3011: *----------------------------------------------------------------------------*/ ! 3012: ! 3013: flag float64_eq_signaling( float64 a, float64 b STATUS_PARAM ) ! 3014: { ! 3015: ! 3016: if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) ! 3017: || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) ! 3018: ) { ! 3019: float_raise( float_flag_invalid STATUS_VAR); ! 3020: return 0; ! 3021: } ! 3022: return ( a == b ) || ( (bits64) ( ( a | b )<<1 ) == 0 ); ! 3023: ! 3024: } ! 3025: ! 3026: /*---------------------------------------------------------------------------- ! 3027: | Returns 1 if the double-precision floating-point value `a' is less than or ! 3028: | equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not ! 3029: | cause an exception. Otherwise, the comparison is performed according to the ! 3030: | IEC/IEEE Standard for Binary Floating-Point Arithmetic. ! 3031: *----------------------------------------------------------------------------*/ ! 3032: ! 3033: flag float64_le_quiet( float64 a, float64 b STATUS_PARAM ) ! 3034: { ! 3035: flag aSign, bSign; ! 3036: ! 3037: if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) ! 3038: || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) ! 3039: ) { ! 3040: if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) { ! 3041: float_raise( float_flag_invalid STATUS_VAR); ! 3042: } ! 3043: return 0; ! 3044: } ! 3045: aSign = extractFloat64Sign( a ); ! 3046: bSign = extractFloat64Sign( b ); ! 3047: if ( aSign != bSign ) return aSign || ( (bits64) ( ( a | b )<<1 ) == 0 ); ! 3048: return ( a == b ) || ( aSign ^ ( a < b ) ); ! 3049: ! 3050: } ! 3051: ! 3052: /*---------------------------------------------------------------------------- ! 3053: | Returns 1 if the double-precision floating-point value `a' is less than ! 3054: | the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an ! 3055: | exception. Otherwise, the comparison is performed according to the IEC/IEEE ! 3056: | Standard for Binary Floating-Point Arithmetic. ! 3057: *----------------------------------------------------------------------------*/ ! 3058: ! 3059: flag float64_lt_quiet( float64 a, float64 b STATUS_PARAM ) ! 3060: { ! 3061: flag aSign, bSign; ! 3062: ! 3063: if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) ! 3064: || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) ! 3065: ) { ! 3066: if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) { ! 3067: float_raise( float_flag_invalid STATUS_VAR); ! 3068: } ! 3069: return 0; ! 3070: } ! 3071: aSign = extractFloat64Sign( a ); ! 3072: bSign = extractFloat64Sign( b ); ! 3073: if ( aSign != bSign ) return aSign && ( (bits64) ( ( a | b )<<1 ) != 0 ); ! 3074: return ( a != b ) && ( aSign ^ ( a < b ) ); ! 3075: ! 3076: } ! 3077: ! 3078: #ifdef FLOATX80 ! 3079: ! 3080: /*---------------------------------------------------------------------------- ! 3081: | Returns the result of converting the extended double-precision floating- ! 3082: | point value `a' to the 32-bit two's complement integer format. The ! 3083: | conversion is performed according to the IEC/IEEE Standard for Binary ! 3084: | Floating-Point Arithmetic---which means in particular that the conversion ! 3085: | is rounded according to the current rounding mode. If `a' is a NaN, the ! 3086: | largest positive integer is returned. Otherwise, if the conversion ! 3087: | overflows, the largest integer with the same sign as `a' is returned. ! 3088: *----------------------------------------------------------------------------*/ ! 3089: ! 3090: int32 floatx80_to_int32( floatx80 a STATUS_PARAM ) ! 3091: { ! 3092: flag aSign; ! 3093: int32 aExp, shiftCount; ! 3094: bits64 aSig; ! 3095: ! 3096: aSig = extractFloatx80Frac( a ); ! 3097: aExp = extractFloatx80Exp( a ); ! 3098: aSign = extractFloatx80Sign( a ); ! 3099: if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) aSign = 0; ! 3100: shiftCount = 0x4037 - aExp; ! 3101: if ( shiftCount <= 0 ) shiftCount = 1; ! 3102: shift64RightJamming( aSig, shiftCount, &aSig ); ! 3103: return roundAndPackInt32( aSign, aSig STATUS_VAR ); ! 3104: ! 3105: } ! 3106: ! 3107: /*---------------------------------------------------------------------------- ! 3108: | Returns the result of converting the extended double-precision floating- ! 3109: | point value `a' to the 32-bit two's complement integer format. The ! 3110: | conversion is performed according to the IEC/IEEE Standard for Binary ! 3111: | Floating-Point Arithmetic, except that the conversion is always rounded ! 3112: | toward zero. If `a' is a NaN, the largest positive integer is returned. ! 3113: | Otherwise, if the conversion overflows, the largest integer with the same ! 3114: | sign as `a' is returned. ! 3115: *----------------------------------------------------------------------------*/ ! 3116: ! 3117: int32 floatx80_to_int32_round_to_zero( floatx80 a STATUS_PARAM ) ! 3118: { ! 3119: flag aSign; ! 3120: int32 aExp, shiftCount; ! 3121: bits64 aSig, savedASig; ! 3122: int32 z; ! 3123: ! 3124: aSig = extractFloatx80Frac( a ); ! 3125: aExp = extractFloatx80Exp( a ); ! 3126: aSign = extractFloatx80Sign( a ); ! 3127: if ( 0x401E < aExp ) { ! 3128: if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) aSign = 0; ! 3129: goto invalid; ! 3130: } ! 3131: else if ( aExp < 0x3FFF ) { ! 3132: if ( aExp || aSig ) STATUS(float_exception_flags) |= float_flag_inexact; ! 3133: return 0; ! 3134: } ! 3135: shiftCount = 0x403E - aExp; ! 3136: savedASig = aSig; ! 3137: aSig >>= shiftCount; ! 3138: z = aSig; ! 3139: if ( aSign ) z = - z; ! 3140: if ( ( z < 0 ) ^ aSign ) { ! 3141: invalid: ! 3142: float_raise( float_flag_invalid STATUS_VAR); ! 3143: return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF; ! 3144: } ! 3145: if ( ( aSig<<shiftCount ) != savedASig ) { ! 3146: STATUS(float_exception_flags) |= float_flag_inexact; ! 3147: } ! 3148: return z; ! 3149: ! 3150: } ! 3151: ! 3152: /*---------------------------------------------------------------------------- ! 3153: | Returns the result of converting the extended double-precision floating- ! 3154: | point value `a' to the 64-bit two's complement integer format. The ! 3155: | conversion is performed according to the IEC/IEEE Standard for Binary ! 3156: | Floating-Point Arithmetic---which means in particular that the conversion ! 3157: | is rounded according to the current rounding mode. If `a' is a NaN, ! 3158: | the largest positive integer is returned. Otherwise, if the conversion ! 3159: | overflows, the largest integer with the same sign as `a' is returned. ! 3160: *----------------------------------------------------------------------------*/ ! 3161: ! 3162: int64 floatx80_to_int64( floatx80 a STATUS_PARAM ) ! 3163: { ! 3164: flag aSign; ! 3165: int32 aExp, shiftCount; ! 3166: bits64 aSig, aSigExtra; ! 3167: ! 3168: aSig = extractFloatx80Frac( a ); ! 3169: aExp = extractFloatx80Exp( a ); ! 3170: aSign = extractFloatx80Sign( a ); ! 3171: shiftCount = 0x403E - aExp; ! 3172: if ( shiftCount <= 0 ) { ! 3173: if ( shiftCount ) { ! 3174: float_raise( float_flag_invalid STATUS_VAR); ! 3175: if ( ! aSign ! 3176: || ( ( aExp == 0x7FFF ) ! 3177: && ( aSig != LIT64( 0x8000000000000000 ) ) ) ! 3178: ) { ! 3179: return LIT64( 0x7FFFFFFFFFFFFFFF ); ! 3180: } ! 3181: return (sbits64) LIT64( 0x8000000000000000 ); ! 3182: } ! 3183: aSigExtra = 0; ! 3184: } ! 3185: else { ! 3186: shift64ExtraRightJamming( aSig, 0, shiftCount, &aSig, &aSigExtra ); ! 3187: } ! 3188: return roundAndPackInt64( aSign, aSig, aSigExtra STATUS_VAR ); ! 3189: ! 3190: } ! 3191: ! 3192: /*---------------------------------------------------------------------------- ! 3193: | Returns the result of converting the extended double-precision floating- ! 3194: | point value `a' to the 64-bit two's complement integer format. The ! 3195: | conversion is performed according to the IEC/IEEE Standard for Binary ! 3196: | Floating-Point Arithmetic, except that the conversion is always rounded ! 3197: | toward zero. If `a' is a NaN, the largest positive integer is returned. ! 3198: | Otherwise, if the conversion overflows, the largest integer with the same ! 3199: | sign as `a' is returned. ! 3200: *----------------------------------------------------------------------------*/ ! 3201: ! 3202: int64 floatx80_to_int64_round_to_zero( floatx80 a STATUS_PARAM ) ! 3203: { ! 3204: flag aSign; ! 3205: int32 aExp, shiftCount; ! 3206: bits64 aSig; ! 3207: int64 z; ! 3208: ! 3209: aSig = extractFloatx80Frac( a ); ! 3210: aExp = extractFloatx80Exp( a ); ! 3211: aSign = extractFloatx80Sign( a ); ! 3212: shiftCount = aExp - 0x403E; ! 3213: if ( 0 <= shiftCount ) { ! 3214: aSig &= LIT64( 0x7FFFFFFFFFFFFFFF ); ! 3215: if ( ( a.high != 0xC03E ) || aSig ) { ! 3216: float_raise( float_flag_invalid STATUS_VAR); ! 3217: if ( ! aSign || ( ( aExp == 0x7FFF ) && aSig ) ) { ! 3218: return LIT64( 0x7FFFFFFFFFFFFFFF ); ! 3219: } ! 3220: } ! 3221: return (sbits64) LIT64( 0x8000000000000000 ); ! 3222: } ! 3223: else if ( aExp < 0x3FFF ) { ! 3224: if ( aExp | aSig ) STATUS(float_exception_flags) |= float_flag_inexact; ! 3225: return 0; ! 3226: } ! 3227: z = aSig>>( - shiftCount ); ! 3228: if ( (bits64) ( aSig<<( shiftCount & 63 ) ) ) { ! 3229: STATUS(float_exception_flags) |= float_flag_inexact; ! 3230: } ! 3231: if ( aSign ) z = - z; ! 3232: return z; ! 3233: ! 3234: } ! 3235: ! 3236: /*---------------------------------------------------------------------------- ! 3237: | Returns the result of converting the extended double-precision floating- ! 3238: | point value `a' to the single-precision floating-point format. The ! 3239: | conversion is performed according to the IEC/IEEE Standard for Binary ! 3240: | Floating-Point Arithmetic. ! 3241: *----------------------------------------------------------------------------*/ ! 3242: ! 3243: float32 floatx80_to_float32( floatx80 a STATUS_PARAM ) ! 3244: { ! 3245: flag aSign; ! 3246: int32 aExp; ! 3247: bits64 aSig; ! 3248: ! 3249: aSig = extractFloatx80Frac( a ); ! 3250: aExp = extractFloatx80Exp( a ); ! 3251: aSign = extractFloatx80Sign( a ); ! 3252: if ( aExp == 0x7FFF ) { ! 3253: if ( (bits64) ( aSig<<1 ) ) { ! 3254: return commonNaNToFloat32( floatx80ToCommonNaN( a STATUS_VAR ) ); ! 3255: } ! 3256: return packFloat32( aSign, 0xFF, 0 ); ! 3257: } ! 3258: shift64RightJamming( aSig, 33, &aSig ); ! 3259: if ( aExp || aSig ) aExp -= 0x3F81; ! 3260: return roundAndPackFloat32( aSign, aExp, aSig STATUS_VAR ); ! 3261: ! 3262: } ! 3263: ! 3264: /*---------------------------------------------------------------------------- ! 3265: | Returns the result of converting the extended double-precision floating- ! 3266: | point value `a' to the double-precision floating-point format. The ! 3267: | conversion is performed according to the IEC/IEEE Standard for Binary ! 3268: | Floating-Point Arithmetic. ! 3269: *----------------------------------------------------------------------------*/ ! 3270: ! 3271: float64 floatx80_to_float64( floatx80 a STATUS_PARAM ) ! 3272: { ! 3273: flag aSign; ! 3274: int32 aExp; ! 3275: bits64 aSig, zSig; ! 3276: ! 3277: aSig = extractFloatx80Frac( a ); ! 3278: aExp = extractFloatx80Exp( a ); ! 3279: aSign = extractFloatx80Sign( a ); ! 3280: if ( aExp == 0x7FFF ) { ! 3281: if ( (bits64) ( aSig<<1 ) ) { ! 3282: return commonNaNToFloat64( floatx80ToCommonNaN( a STATUS_VAR ) ); ! 3283: } ! 3284: return packFloat64( aSign, 0x7FF, 0 ); ! 3285: } ! 3286: shift64RightJamming( aSig, 1, &zSig ); ! 3287: if ( aExp || aSig ) aExp -= 0x3C01; ! 3288: return roundAndPackFloat64( aSign, aExp, zSig STATUS_VAR ); ! 3289: ! 3290: } ! 3291: ! 3292: #ifdef FLOAT128 ! 3293: ! 3294: /*---------------------------------------------------------------------------- ! 3295: | Returns the result of converting the extended double-precision floating- ! 3296: | point value `a' to the quadruple-precision floating-point format. The ! 3297: | conversion is performed according to the IEC/IEEE Standard for Binary ! 3298: | Floating-Point Arithmetic. ! 3299: *----------------------------------------------------------------------------*/ ! 3300: ! 3301: float128 floatx80_to_float128( floatx80 a STATUS_PARAM ) ! 3302: { ! 3303: flag aSign; ! 3304: int16 aExp; ! 3305: bits64 aSig, zSig0, zSig1; ! 3306: ! 3307: aSig = extractFloatx80Frac( a ); ! 3308: aExp = extractFloatx80Exp( a ); ! 3309: aSign = extractFloatx80Sign( a ); ! 3310: if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) { ! 3311: return commonNaNToFloat128( floatx80ToCommonNaN( a STATUS_VAR ) ); ! 3312: } ! 3313: shift128Right( aSig<<1, 0, 16, &zSig0, &zSig1 ); ! 3314: return packFloat128( aSign, aExp, zSig0, zSig1 ); ! 3315: ! 3316: } ! 3317: ! 3318: #endif ! 3319: ! 3320: /*---------------------------------------------------------------------------- ! 3321: | Rounds the extended double-precision floating-point value `a' to an integer, ! 3322: | and returns the result as an extended quadruple-precision floating-point ! 3323: | value. The operation is performed according to the IEC/IEEE Standard for ! 3324: | Binary Floating-Point Arithmetic. ! 3325: *----------------------------------------------------------------------------*/ ! 3326: ! 3327: floatx80 floatx80_round_to_int( floatx80 a STATUS_PARAM ) ! 3328: { ! 3329: flag aSign; ! 3330: int32 aExp; ! 3331: bits64 lastBitMask, roundBitsMask; ! 3332: int8 roundingMode; ! 3333: floatx80 z; ! 3334: ! 3335: aExp = extractFloatx80Exp( a ); ! 3336: if ( 0x403E <= aExp ) { ! 3337: if ( ( aExp == 0x7FFF ) && (bits64) ( extractFloatx80Frac( a )<<1 ) ) { ! 3338: return propagateFloatx80NaN( a, a STATUS_VAR ); ! 3339: } ! 3340: return a; ! 3341: } ! 3342: if ( aExp < 0x3FFF ) { ! 3343: if ( ( aExp == 0 ) ! 3344: && ( (bits64) ( extractFloatx80Frac( a )<<1 ) == 0 ) ) { ! 3345: return a; ! 3346: } ! 3347: STATUS(float_exception_flags) |= float_flag_inexact; ! 3348: aSign = extractFloatx80Sign( a ); ! 3349: switch ( STATUS(float_rounding_mode) ) { ! 3350: case float_round_nearest_even: ! 3351: if ( ( aExp == 0x3FFE ) && (bits64) ( extractFloatx80Frac( a )<<1 ) ! 3352: ) { ! 3353: return ! 3354: packFloatx80( aSign, 0x3FFF, LIT64( 0x8000000000000000 ) ); ! 3355: } ! 3356: break; ! 3357: case float_round_down: ! 3358: return ! 3359: aSign ? ! 3360: packFloatx80( 1, 0x3FFF, LIT64( 0x8000000000000000 ) ) ! 3361: : packFloatx80( 0, 0, 0 ); ! 3362: case float_round_up: ! 3363: return ! 3364: aSign ? packFloatx80( 1, 0, 0 ) ! 3365: : packFloatx80( 0, 0x3FFF, LIT64( 0x8000000000000000 ) ); ! 3366: } ! 3367: return packFloatx80( aSign, 0, 0 ); ! 3368: } ! 3369: lastBitMask = 1; ! 3370: lastBitMask <<= 0x403E - aExp; ! 3371: roundBitsMask = lastBitMask - 1; ! 3372: z = a; ! 3373: roundingMode = STATUS(float_rounding_mode); ! 3374: if ( roundingMode == float_round_nearest_even ) { ! 3375: z.low += lastBitMask>>1; ! 3376: if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask; ! 3377: } ! 3378: else if ( roundingMode != float_round_to_zero ) { ! 3379: if ( extractFloatx80Sign( z ) ^ ( roundingMode == float_round_up ) ) { ! 3380: z.low += roundBitsMask; ! 3381: } ! 3382: } ! 3383: z.low &= ~ roundBitsMask; ! 3384: if ( z.low == 0 ) { ! 3385: ++z.high; ! 3386: z.low = LIT64( 0x8000000000000000 ); ! 3387: } ! 3388: if ( z.low != a.low ) STATUS(float_exception_flags) |= float_flag_inexact; ! 3389: return z; ! 3390: ! 3391: } ! 3392: ! 3393: /*---------------------------------------------------------------------------- ! 3394: | Returns the result of adding the absolute values of the extended double- ! 3395: | precision floating-point values `a' and `b'. If `zSign' is 1, the sum is ! 3396: | negated before being returned. `zSign' is ignored if the result is a NaN. ! 3397: | The addition is performed according to the IEC/IEEE Standard for Binary ! 3398: | Floating-Point Arithmetic. ! 3399: *----------------------------------------------------------------------------*/ ! 3400: ! 3401: static floatx80 addFloatx80Sigs( floatx80 a, floatx80 b, flag zSign STATUS_PARAM) ! 3402: { ! 3403: int32 aExp, bExp, zExp; ! 3404: bits64 aSig, bSig, zSig0, zSig1; ! 3405: int32 expDiff; ! 3406: ! 3407: aSig = extractFloatx80Frac( a ); ! 3408: aExp = extractFloatx80Exp( a ); ! 3409: bSig = extractFloatx80Frac( b ); ! 3410: bExp = extractFloatx80Exp( b ); ! 3411: expDiff = aExp - bExp; ! 3412: if ( 0 < expDiff ) { ! 3413: if ( aExp == 0x7FFF ) { ! 3414: if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR ); ! 3415: return a; ! 3416: } ! 3417: if ( bExp == 0 ) --expDiff; ! 3418: shift64ExtraRightJamming( bSig, 0, expDiff, &bSig, &zSig1 ); ! 3419: zExp = aExp; ! 3420: } ! 3421: else if ( expDiff < 0 ) { ! 3422: if ( bExp == 0x7FFF ) { ! 3423: if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR ); ! 3424: return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); ! 3425: } ! 3426: if ( aExp == 0 ) ++expDiff; ! 3427: shift64ExtraRightJamming( aSig, 0, - expDiff, &aSig, &zSig1 ); ! 3428: zExp = bExp; ! 3429: } ! 3430: else { ! 3431: if ( aExp == 0x7FFF ) { ! 3432: if ( (bits64) ( ( aSig | bSig )<<1 ) ) { ! 3433: return propagateFloatx80NaN( a, b STATUS_VAR ); ! 3434: } ! 3435: return a; ! 3436: } ! 3437: zSig1 = 0; ! 3438: zSig0 = aSig + bSig; ! 3439: if ( aExp == 0 ) { ! 3440: normalizeFloatx80Subnormal( zSig0, &zExp, &zSig0 ); ! 3441: goto roundAndPack; ! 3442: } ! 3443: zExp = aExp; ! 3444: goto shiftRight1; ! 3445: } ! 3446: zSig0 = aSig + bSig; ! 3447: if ( (sbits64) zSig0 < 0 ) goto roundAndPack; ! 3448: shiftRight1: ! 3449: shift64ExtraRightJamming( zSig0, zSig1, 1, &zSig0, &zSig1 ); ! 3450: zSig0 |= LIT64( 0x8000000000000000 ); ! 3451: ++zExp; ! 3452: roundAndPack: ! 3453: return ! 3454: roundAndPackFloatx80( ! 3455: STATUS(floatx80_rounding_precision), zSign, zExp, zSig0, zSig1 STATUS_VAR ); ! 3456: ! 3457: } ! 3458: ! 3459: /*---------------------------------------------------------------------------- ! 3460: | Returns the result of subtracting the absolute values of the extended ! 3461: | double-precision floating-point values `a' and `b'. If `zSign' is 1, the ! 3462: | difference is negated before being returned. `zSign' is ignored if the ! 3463: | result is a NaN. The subtraction is performed according to the IEC/IEEE ! 3464: | Standard for Binary Floating-Point Arithmetic. ! 3465: *----------------------------------------------------------------------------*/ ! 3466: ! 3467: static floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign STATUS_PARAM ) ! 3468: { ! 3469: int32 aExp, bExp, zExp; ! 3470: bits64 aSig, bSig, zSig0, zSig1; ! 3471: int32 expDiff; ! 3472: floatx80 z; ! 3473: ! 3474: aSig = extractFloatx80Frac( a ); ! 3475: aExp = extractFloatx80Exp( a ); ! 3476: bSig = extractFloatx80Frac( b ); ! 3477: bExp = extractFloatx80Exp( b ); ! 3478: expDiff = aExp - bExp; ! 3479: if ( 0 < expDiff ) goto aExpBigger; ! 3480: if ( expDiff < 0 ) goto bExpBigger; ! 3481: if ( aExp == 0x7FFF ) { ! 3482: if ( (bits64) ( ( aSig | bSig )<<1 ) ) { ! 3483: return propagateFloatx80NaN( a, b STATUS_VAR ); ! 3484: } ! 3485: float_raise( float_flag_invalid STATUS_VAR); ! 3486: z.low = floatx80_default_nan_low; ! 3487: z.high = floatx80_default_nan_high; ! 3488: return z; ! 3489: } ! 3490: if ( aExp == 0 ) { ! 3491: aExp = 1; ! 3492: bExp = 1; ! 3493: } ! 3494: zSig1 = 0; ! 3495: if ( bSig < aSig ) goto aBigger; ! 3496: if ( aSig < bSig ) goto bBigger; ! 3497: return packFloatx80( STATUS(float_rounding_mode) == float_round_down, 0, 0 ); ! 3498: bExpBigger: ! 3499: if ( bExp == 0x7FFF ) { ! 3500: if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR ); ! 3501: return packFloatx80( zSign ^ 1, 0x7FFF, LIT64( 0x8000000000000000 ) ); ! 3502: } ! 3503: if ( aExp == 0 ) ++expDiff; ! 3504: shift128RightJamming( aSig, 0, - expDiff, &aSig, &zSig1 ); ! 3505: bBigger: ! 3506: sub128( bSig, 0, aSig, zSig1, &zSig0, &zSig1 ); ! 3507: zExp = bExp; ! 3508: zSign ^= 1; ! 3509: goto normalizeRoundAndPack; ! 3510: aExpBigger: ! 3511: if ( aExp == 0x7FFF ) { ! 3512: if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR ); ! 3513: return a; ! 3514: } ! 3515: if ( bExp == 0 ) --expDiff; ! 3516: shift128RightJamming( bSig, 0, expDiff, &bSig, &zSig1 ); ! 3517: aBigger: ! 3518: sub128( aSig, 0, bSig, zSig1, &zSig0, &zSig1 ); ! 3519: zExp = aExp; ! 3520: normalizeRoundAndPack: ! 3521: return ! 3522: normalizeRoundAndPackFloatx80( ! 3523: STATUS(floatx80_rounding_precision), zSign, zExp, zSig0, zSig1 STATUS_VAR ); ! 3524: ! 3525: } ! 3526: ! 3527: /*---------------------------------------------------------------------------- ! 3528: | Returns the result of adding the extended double-precision floating-point ! 3529: | values `a' and `b'. The operation is performed according to the IEC/IEEE ! 3530: | Standard for Binary Floating-Point Arithmetic. ! 3531: *----------------------------------------------------------------------------*/ ! 3532: ! 3533: floatx80 floatx80_add( floatx80 a, floatx80 b STATUS_PARAM ) ! 3534: { ! 3535: flag aSign, bSign; ! 3536: ! 3537: aSign = extractFloatx80Sign( a ); ! 3538: bSign = extractFloatx80Sign( b ); ! 3539: if ( aSign == bSign ) { ! 3540: return addFloatx80Sigs( a, b, aSign STATUS_VAR ); ! 3541: } ! 3542: else { ! 3543: return subFloatx80Sigs( a, b, aSign STATUS_VAR ); ! 3544: } ! 3545: ! 3546: } ! 3547: ! 3548: /*---------------------------------------------------------------------------- ! 3549: | Returns the result of subtracting the extended double-precision floating- ! 3550: | point values `a' and `b'. The operation is performed according to the ! 3551: | IEC/IEEE Standard for Binary Floating-Point Arithmetic. ! 3552: *----------------------------------------------------------------------------*/ ! 3553: ! 3554: floatx80 floatx80_sub( floatx80 a, floatx80 b STATUS_PARAM ) ! 3555: { ! 3556: flag aSign, bSign; ! 3557: ! 3558: aSign = extractFloatx80Sign( a ); ! 3559: bSign = extractFloatx80Sign( b ); ! 3560: if ( aSign == bSign ) { ! 3561: return subFloatx80Sigs( a, b, aSign STATUS_VAR ); ! 3562: } ! 3563: else { ! 3564: return addFloatx80Sigs( a, b, aSign STATUS_VAR ); ! 3565: } ! 3566: ! 3567: } ! 3568: ! 3569: /*---------------------------------------------------------------------------- ! 3570: | Returns the result of multiplying the extended double-precision floating- ! 3571: | point values `a' and `b'. The operation is performed according to the ! 3572: | IEC/IEEE Standard for Binary Floating-Point Arithmetic. ! 3573: *----------------------------------------------------------------------------*/ ! 3574: ! 3575: floatx80 floatx80_mul( floatx80 a, floatx80 b STATUS_PARAM ) ! 3576: { ! 3577: flag aSign, bSign, zSign; ! 3578: int32 aExp, bExp, zExp; ! 3579: bits64 aSig, bSig, zSig0, zSig1; ! 3580: floatx80 z; ! 3581: ! 3582: aSig = extractFloatx80Frac( a ); ! 3583: aExp = extractFloatx80Exp( a ); ! 3584: aSign = extractFloatx80Sign( a ); ! 3585: bSig = extractFloatx80Frac( b ); ! 3586: bExp = extractFloatx80Exp( b ); ! 3587: bSign = extractFloatx80Sign( b ); ! 3588: zSign = aSign ^ bSign; ! 3589: if ( aExp == 0x7FFF ) { ! 3590: if ( (bits64) ( aSig<<1 ) ! 3591: || ( ( bExp == 0x7FFF ) && (bits64) ( bSig<<1 ) ) ) { ! 3592: return propagateFloatx80NaN( a, b STATUS_VAR ); ! 3593: } ! 3594: if ( ( bExp | bSig ) == 0 ) goto invalid; ! 3595: return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); ! 3596: } ! 3597: if ( bExp == 0x7FFF ) { ! 3598: if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR ); ! 3599: if ( ( aExp | aSig ) == 0 ) { ! 3600: invalid: ! 3601: float_raise( float_flag_invalid STATUS_VAR); ! 3602: z.low = floatx80_default_nan_low; ! 3603: z.high = floatx80_default_nan_high; ! 3604: return z; ! 3605: } ! 3606: return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); ! 3607: } ! 3608: if ( aExp == 0 ) { ! 3609: if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 ); ! 3610: normalizeFloatx80Subnormal( aSig, &aExp, &aSig ); ! 3611: } ! 3612: if ( bExp == 0 ) { ! 3613: if ( bSig == 0 ) return packFloatx80( zSign, 0, 0 ); ! 3614: normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); ! 3615: } ! 3616: zExp = aExp + bExp - 0x3FFE; ! 3617: mul64To128( aSig, bSig, &zSig0, &zSig1 ); ! 3618: if ( 0 < (sbits64) zSig0 ) { ! 3619: shortShift128Left( zSig0, zSig1, 1, &zSig0, &zSig1 ); ! 3620: --zExp; ! 3621: } ! 3622: return ! 3623: roundAndPackFloatx80( ! 3624: STATUS(floatx80_rounding_precision), zSign, zExp, zSig0, zSig1 STATUS_VAR ); ! 3625: ! 3626: } ! 3627: ! 3628: /*---------------------------------------------------------------------------- ! 3629: | Returns the result of dividing the extended double-precision floating-point ! 3630: | value `a' by the corresponding value `b'. The operation is performed ! 3631: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. ! 3632: *----------------------------------------------------------------------------*/ ! 3633: ! 3634: floatx80 floatx80_div( floatx80 a, floatx80 b STATUS_PARAM ) ! 3635: { ! 3636: flag aSign, bSign, zSign; ! 3637: int32 aExp, bExp, zExp; ! 3638: bits64 aSig, bSig, zSig0, zSig1; ! 3639: bits64 rem0, rem1, rem2, term0, term1, term2; ! 3640: floatx80 z; ! 3641: ! 3642: aSig = extractFloatx80Frac( a ); ! 3643: aExp = extractFloatx80Exp( a ); ! 3644: aSign = extractFloatx80Sign( a ); ! 3645: bSig = extractFloatx80Frac( b ); ! 3646: bExp = extractFloatx80Exp( b ); ! 3647: bSign = extractFloatx80Sign( b ); ! 3648: zSign = aSign ^ bSign; ! 3649: if ( aExp == 0x7FFF ) { ! 3650: if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR ); ! 3651: if ( bExp == 0x7FFF ) { ! 3652: if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR ); ! 3653: goto invalid; ! 3654: } ! 3655: return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); ! 3656: } ! 3657: if ( bExp == 0x7FFF ) { ! 3658: if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR ); ! 3659: return packFloatx80( zSign, 0, 0 ); ! 3660: } ! 3661: if ( bExp == 0 ) { ! 3662: if ( bSig == 0 ) { ! 3663: if ( ( aExp | aSig ) == 0 ) { ! 3664: invalid: ! 3665: float_raise( float_flag_invalid STATUS_VAR); ! 3666: z.low = floatx80_default_nan_low; ! 3667: z.high = floatx80_default_nan_high; ! 3668: return z; ! 3669: } ! 3670: float_raise( float_flag_divbyzero STATUS_VAR); ! 3671: return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); ! 3672: } ! 3673: normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); ! 3674: } ! 3675: if ( aExp == 0 ) { ! 3676: if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 ); ! 3677: normalizeFloatx80Subnormal( aSig, &aExp, &aSig ); ! 3678: } ! 3679: zExp = aExp - bExp + 0x3FFE; ! 3680: rem1 = 0; ! 3681: if ( bSig <= aSig ) { ! 3682: shift128Right( aSig, 0, 1, &aSig, &rem1 ); ! 3683: ++zExp; ! 3684: } ! 3685: zSig0 = estimateDiv128To64( aSig, rem1, bSig ); ! 3686: mul64To128( bSig, zSig0, &term0, &term1 ); ! 3687: sub128( aSig, rem1, term0, term1, &rem0, &rem1 ); ! 3688: while ( (sbits64) rem0 < 0 ) { ! 3689: --zSig0; ! 3690: add128( rem0, rem1, 0, bSig, &rem0, &rem1 ); ! 3691: } ! 3692: zSig1 = estimateDiv128To64( rem1, 0, bSig ); ! 3693: if ( (bits64) ( zSig1<<1 ) <= 8 ) { ! 3694: mul64To128( bSig, zSig1, &term1, &term2 ); ! 3695: sub128( rem1, 0, term1, term2, &rem1, &rem2 ); ! 3696: while ( (sbits64) rem1 < 0 ) { ! 3697: --zSig1; ! 3698: add128( rem1, rem2, 0, bSig, &rem1, &rem2 ); ! 3699: } ! 3700: zSig1 |= ( ( rem1 | rem2 ) != 0 ); ! 3701: } ! 3702: return ! 3703: roundAndPackFloatx80( ! 3704: STATUS(floatx80_rounding_precision), zSign, zExp, zSig0, zSig1 STATUS_VAR ); ! 3705: ! 3706: } ! 3707: ! 3708: /*---------------------------------------------------------------------------- ! 3709: | Returns the remainder of the extended double-precision floating-point value ! 3710: | `a' with respect to the corresponding value `b'. The operation is performed ! 3711: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. ! 3712: *----------------------------------------------------------------------------*/ ! 3713: ! 3714: floatx80 floatx80_rem( floatx80 a, floatx80 b STATUS_PARAM ) ! 3715: { ! 3716: flag aSign, bSign, zSign; ! 3717: int32 aExp, bExp, expDiff; ! 3718: bits64 aSig0, aSig1, bSig; ! 3719: bits64 q, term0, term1, alternateASig0, alternateASig1; ! 3720: floatx80 z; ! 3721: ! 3722: aSig0 = extractFloatx80Frac( a ); ! 3723: aExp = extractFloatx80Exp( a ); ! 3724: aSign = extractFloatx80Sign( a ); ! 3725: bSig = extractFloatx80Frac( b ); ! 3726: bExp = extractFloatx80Exp( b ); ! 3727: bSign = extractFloatx80Sign( b ); ! 3728: if ( aExp == 0x7FFF ) { ! 3729: if ( (bits64) ( aSig0<<1 ) ! 3730: || ( ( bExp == 0x7FFF ) && (bits64) ( bSig<<1 ) ) ) { ! 3731: return propagateFloatx80NaN( a, b STATUS_VAR ); ! 3732: } ! 3733: goto invalid; ! 3734: } ! 3735: if ( bExp == 0x7FFF ) { ! 3736: if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR ); ! 3737: return a; ! 3738: } ! 3739: if ( bExp == 0 ) { ! 3740: if ( bSig == 0 ) { ! 3741: invalid: ! 3742: float_raise( float_flag_invalid STATUS_VAR); ! 3743: z.low = floatx80_default_nan_low; ! 3744: z.high = floatx80_default_nan_high; ! 3745: return z; ! 3746: } ! 3747: normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); ! 3748: } ! 3749: if ( aExp == 0 ) { ! 3750: if ( (bits64) ( aSig0<<1 ) == 0 ) return a; ! 3751: normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 ); ! 3752: } ! 3753: bSig |= LIT64( 0x8000000000000000 ); ! 3754: zSign = aSign; ! 3755: expDiff = aExp - bExp; ! 3756: aSig1 = 0; ! 3757: if ( expDiff < 0 ) { ! 3758: if ( expDiff < -1 ) return a; ! 3759: shift128Right( aSig0, 0, 1, &aSig0, &aSig1 ); ! 3760: expDiff = 0; ! 3761: } ! 3762: q = ( bSig <= aSig0 ); ! 3763: if ( q ) aSig0 -= bSig; ! 3764: expDiff -= 64; ! 3765: while ( 0 < expDiff ) { ! 3766: q = estimateDiv128To64( aSig0, aSig1, bSig ); ! 3767: q = ( 2 < q ) ? q - 2 : 0; ! 3768: mul64To128( bSig, q, &term0, &term1 ); ! 3769: sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); ! 3770: shortShift128Left( aSig0, aSig1, 62, &aSig0, &aSig1 ); ! 3771: expDiff -= 62; ! 3772: } ! 3773: expDiff += 64; ! 3774: if ( 0 < expDiff ) { ! 3775: q = estimateDiv128To64( aSig0, aSig1, bSig ); ! 3776: q = ( 2 < q ) ? q - 2 : 0; ! 3777: q >>= 64 - expDiff; ! 3778: mul64To128( bSig, q<<( 64 - expDiff ), &term0, &term1 ); ! 3779: sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); ! 3780: shortShift128Left( 0, bSig, 64 - expDiff, &term0, &term1 ); ! 3781: while ( le128( term0, term1, aSig0, aSig1 ) ) { ! 3782: ++q; ! 3783: sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); ! 3784: } ! 3785: } ! 3786: else { ! 3787: term1 = 0; ! 3788: term0 = bSig; ! 3789: } ! 3790: sub128( term0, term1, aSig0, aSig1, &alternateASig0, &alternateASig1 ); ! 3791: if ( lt128( alternateASig0, alternateASig1, aSig0, aSig1 ) ! 3792: || ( eq128( alternateASig0, alternateASig1, aSig0, aSig1 ) ! 3793: && ( q & 1 ) ) ! 3794: ) { ! 3795: aSig0 = alternateASig0; ! 3796: aSig1 = alternateASig1; ! 3797: zSign = ! zSign; ! 3798: } ! 3799: return ! 3800: normalizeRoundAndPackFloatx80( ! 3801: 80, zSign, bExp + expDiff, aSig0, aSig1 STATUS_VAR ); ! 3802: ! 3803: } ! 3804: ! 3805: /*---------------------------------------------------------------------------- ! 3806: | Returns the square root of the extended double-precision floating-point ! 3807: | value `a'. The operation is performed according to the IEC/IEEE Standard ! 3808: | for Binary Floating-Point Arithmetic. ! 3809: *----------------------------------------------------------------------------*/ ! 3810: ! 3811: floatx80 floatx80_sqrt( floatx80 a STATUS_PARAM ) ! 3812: { ! 3813: flag aSign; ! 3814: int32 aExp, zExp; ! 3815: bits64 aSig0, aSig1, zSig0, zSig1, doubleZSig0; ! 3816: bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3; ! 3817: floatx80 z; ! 3818: ! 3819: aSig0 = extractFloatx80Frac( a ); ! 3820: aExp = extractFloatx80Exp( a ); ! 3821: aSign = extractFloatx80Sign( a ); ! 3822: if ( aExp == 0x7FFF ) { ! 3823: if ( (bits64) ( aSig0<<1 ) ) return propagateFloatx80NaN( a, a STATUS_VAR ); ! 3824: if ( ! aSign ) return a; ! 3825: goto invalid; ! 3826: } ! 3827: if ( aSign ) { ! 3828: if ( ( aExp | aSig0 ) == 0 ) return a; ! 3829: invalid: ! 3830: float_raise( float_flag_invalid STATUS_VAR); ! 3831: z.low = floatx80_default_nan_low; ! 3832: z.high = floatx80_default_nan_high; ! 3833: return z; ! 3834: } ! 3835: if ( aExp == 0 ) { ! 3836: if ( aSig0 == 0 ) return packFloatx80( 0, 0, 0 ); ! 3837: normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 ); ! 3838: } ! 3839: zExp = ( ( aExp - 0x3FFF )>>1 ) + 0x3FFF; ! 3840: zSig0 = estimateSqrt32( aExp, aSig0>>32 ); ! 3841: shift128Right( aSig0, 0, 2 + ( aExp & 1 ), &aSig0, &aSig1 ); ! 3842: zSig0 = estimateDiv128To64( aSig0, aSig1, zSig0<<32 ) + ( zSig0<<30 ); ! 3843: doubleZSig0 = zSig0<<1; ! 3844: mul64To128( zSig0, zSig0, &term0, &term1 ); ! 3845: sub128( aSig0, aSig1, term0, term1, &rem0, &rem1 ); ! 3846: while ( (sbits64) rem0 < 0 ) { ! 3847: --zSig0; ! 3848: doubleZSig0 -= 2; ! 3849: add128( rem0, rem1, zSig0>>63, doubleZSig0 | 1, &rem0, &rem1 ); ! 3850: } ! 3851: zSig1 = estimateDiv128To64( rem1, 0, doubleZSig0 ); ! 3852: if ( ( zSig1 & LIT64( 0x3FFFFFFFFFFFFFFF ) ) <= 5 ) { ! 3853: if ( zSig1 == 0 ) zSig1 = 1; ! 3854: mul64To128( doubleZSig0, zSig1, &term1, &term2 ); ! 3855: sub128( rem1, 0, term1, term2, &rem1, &rem2 ); ! 3856: mul64To128( zSig1, zSig1, &term2, &term3 ); ! 3857: sub192( rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3 ); ! 3858: while ( (sbits64) rem1 < 0 ) { ! 3859: --zSig1; ! 3860: shortShift128Left( 0, zSig1, 1, &term2, &term3 ); ! 3861: term3 |= 1; ! 3862: term2 |= doubleZSig0; ! 3863: add192( rem1, rem2, rem3, 0, term2, term3, &rem1, &rem2, &rem3 ); ! 3864: } ! 3865: zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 ); ! 3866: } ! 3867: shortShift128Left( 0, zSig1, 1, &zSig0, &zSig1 ); ! 3868: zSig0 |= doubleZSig0; ! 3869: return ! 3870: roundAndPackFloatx80( ! 3871: STATUS(floatx80_rounding_precision), 0, zExp, zSig0, zSig1 STATUS_VAR ); ! 3872: ! 3873: } ! 3874: ! 3875: /*---------------------------------------------------------------------------- ! 3876: | Returns 1 if the extended double-precision floating-point value `a' is ! 3877: | equal to the corresponding value `b', and 0 otherwise. The comparison is ! 3878: | performed according to the IEC/IEEE Standard for Binary Floating-Point ! 3879: | Arithmetic. ! 3880: *----------------------------------------------------------------------------*/ ! 3881: ! 3882: flag floatx80_eq( floatx80 a, floatx80 b STATUS_PARAM ) ! 3883: { ! 3884: ! 3885: if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) ! 3886: && (bits64) ( extractFloatx80Frac( a )<<1 ) ) ! 3887: || ( ( extractFloatx80Exp( b ) == 0x7FFF ) ! 3888: && (bits64) ( extractFloatx80Frac( b )<<1 ) ) ! 3889: ) { ! 3890: if ( floatx80_is_signaling_nan( a ) ! 3891: || floatx80_is_signaling_nan( b ) ) { ! 3892: float_raise( float_flag_invalid STATUS_VAR); ! 3893: } ! 3894: return 0; ! 3895: } ! 3896: return ! 3897: ( a.low == b.low ) ! 3898: && ( ( a.high == b.high ) ! 3899: || ( ( a.low == 0 ) ! 3900: && ( (bits16) ( ( a.high | b.high )<<1 ) == 0 ) ) ! 3901: ); ! 3902: ! 3903: } ! 3904: ! 3905: /*---------------------------------------------------------------------------- ! 3906: | Returns 1 if the extended double-precision floating-point value `a' is ! 3907: | less than or equal to the corresponding value `b', and 0 otherwise. The ! 3908: | comparison is performed according to the IEC/IEEE Standard for Binary ! 3909: | Floating-Point Arithmetic. ! 3910: *----------------------------------------------------------------------------*/ ! 3911: ! 3912: flag floatx80_le( floatx80 a, floatx80 b STATUS_PARAM ) ! 3913: { ! 3914: flag aSign, bSign; ! 3915: ! 3916: if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) ! 3917: && (bits64) ( extractFloatx80Frac( a )<<1 ) ) ! 3918: || ( ( extractFloatx80Exp( b ) == 0x7FFF ) ! 3919: && (bits64) ( extractFloatx80Frac( b )<<1 ) ) ! 3920: ) { ! 3921: float_raise( float_flag_invalid STATUS_VAR); ! 3922: return 0; ! 3923: } ! 3924: aSign = extractFloatx80Sign( a ); ! 3925: bSign = extractFloatx80Sign( b ); ! 3926: if ( aSign != bSign ) { ! 3927: return ! 3928: aSign ! 3929: || ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) ! 3930: == 0 ); ! 3931: } ! 3932: return ! 3933: aSign ? le128( b.high, b.low, a.high, a.low ) ! 3934: : le128( a.high, a.low, b.high, b.low ); ! 3935: ! 3936: } ! 3937: ! 3938: /*---------------------------------------------------------------------------- ! 3939: | Returns 1 if the extended double-precision floating-point value `a' is ! 3940: | less than the corresponding value `b', and 0 otherwise. The comparison ! 3941: | is performed according to the IEC/IEEE Standard for Binary Floating-Point ! 3942: | Arithmetic. ! 3943: *----------------------------------------------------------------------------*/ ! 3944: ! 3945: flag floatx80_lt( floatx80 a, floatx80 b STATUS_PARAM ) ! 3946: { ! 3947: flag aSign, bSign; ! 3948: ! 3949: if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) ! 3950: && (bits64) ( extractFloatx80Frac( a )<<1 ) ) ! 3951: || ( ( extractFloatx80Exp( b ) == 0x7FFF ) ! 3952: && (bits64) ( extractFloatx80Frac( b )<<1 ) ) ! 3953: ) { ! 3954: float_raise( float_flag_invalid STATUS_VAR); ! 3955: return 0; ! 3956: } ! 3957: aSign = extractFloatx80Sign( a ); ! 3958: bSign = extractFloatx80Sign( b ); ! 3959: if ( aSign != bSign ) { ! 3960: return ! 3961: aSign ! 3962: && ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) ! 3963: != 0 ); ! 3964: } ! 3965: return ! 3966: aSign ? lt128( b.high, b.low, a.high, a.low ) ! 3967: : lt128( a.high, a.low, b.high, b.low ); ! 3968: ! 3969: } ! 3970: ! 3971: /*---------------------------------------------------------------------------- ! 3972: | Returns 1 if the extended double-precision floating-point value `a' is equal ! 3973: | to the corresponding value `b', and 0 otherwise. The invalid exception is ! 3974: | raised if either operand is a NaN. Otherwise, the comparison is performed ! 3975: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. ! 3976: *----------------------------------------------------------------------------*/ ! 3977: ! 3978: flag floatx80_eq_signaling( floatx80 a, floatx80 b STATUS_PARAM ) ! 3979: { ! 3980: ! 3981: if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) ! 3982: && (bits64) ( extractFloatx80Frac( a )<<1 ) ) ! 3983: || ( ( extractFloatx80Exp( b ) == 0x7FFF ) ! 3984: && (bits64) ( extractFloatx80Frac( b )<<1 ) ) ! 3985: ) { ! 3986: float_raise( float_flag_invalid STATUS_VAR); ! 3987: return 0; ! 3988: } ! 3989: return ! 3990: ( a.low == b.low ) ! 3991: && ( ( a.high == b.high ) ! 3992: || ( ( a.low == 0 ) ! 3993: && ( (bits16) ( ( a.high | b.high )<<1 ) == 0 ) ) ! 3994: ); ! 3995: ! 3996: } ! 3997: ! 3998: /*---------------------------------------------------------------------------- ! 3999: | Returns 1 if the extended double-precision floating-point value `a' is less ! 4000: | than or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs ! 4001: | do not cause an exception. Otherwise, the comparison is performed according ! 4002: | to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. ! 4003: *----------------------------------------------------------------------------*/ ! 4004: ! 4005: flag floatx80_le_quiet( floatx80 a, floatx80 b STATUS_PARAM ) ! 4006: { ! 4007: flag aSign, bSign; ! 4008: ! 4009: if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) ! 4010: && (bits64) ( extractFloatx80Frac( a )<<1 ) ) ! 4011: || ( ( extractFloatx80Exp( b ) == 0x7FFF ) ! 4012: && (bits64) ( extractFloatx80Frac( b )<<1 ) ) ! 4013: ) { ! 4014: if ( floatx80_is_signaling_nan( a ) ! 4015: || floatx80_is_signaling_nan( b ) ) { ! 4016: float_raise( float_flag_invalid STATUS_VAR); ! 4017: } ! 4018: return 0; ! 4019: } ! 4020: aSign = extractFloatx80Sign( a ); ! 4021: bSign = extractFloatx80Sign( b ); ! 4022: if ( aSign != bSign ) { ! 4023: return ! 4024: aSign ! 4025: || ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) ! 4026: == 0 ); ! 4027: } ! 4028: return ! 4029: aSign ? le128( b.high, b.low, a.high, a.low ) ! 4030: : le128( a.high, a.low, b.high, b.low ); ! 4031: ! 4032: } ! 4033: ! 4034: /*---------------------------------------------------------------------------- ! 4035: | Returns 1 if the extended double-precision floating-point value `a' is less ! 4036: | than the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause ! 4037: | an exception. Otherwise, the comparison is performed according to the ! 4038: | IEC/IEEE Standard for Binary Floating-Point Arithmetic. ! 4039: *----------------------------------------------------------------------------*/ ! 4040: ! 4041: flag floatx80_lt_quiet( floatx80 a, floatx80 b STATUS_PARAM ) ! 4042: { ! 4043: flag aSign, bSign; ! 4044: ! 4045: if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) ! 4046: && (bits64) ( extractFloatx80Frac( a )<<1 ) ) ! 4047: || ( ( extractFloatx80Exp( b ) == 0x7FFF ) ! 4048: && (bits64) ( extractFloatx80Frac( b )<<1 ) ) ! 4049: ) { ! 4050: if ( floatx80_is_signaling_nan( a ) ! 4051: || floatx80_is_signaling_nan( b ) ) { ! 4052: float_raise( float_flag_invalid STATUS_VAR); ! 4053: } ! 4054: return 0; ! 4055: } ! 4056: aSign = extractFloatx80Sign( a ); ! 4057: bSign = extractFloatx80Sign( b ); ! 4058: if ( aSign != bSign ) { ! 4059: return ! 4060: aSign ! 4061: && ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) ! 4062: != 0 ); ! 4063: } ! 4064: return ! 4065: aSign ? lt128( b.high, b.low, a.high, a.low ) ! 4066: : lt128( a.high, a.low, b.high, b.low ); ! 4067: ! 4068: } ! 4069: ! 4070: #endif ! 4071: ! 4072: #ifdef FLOAT128 ! 4073: ! 4074: /*---------------------------------------------------------------------------- ! 4075: | Returns the result of converting the quadruple-precision floating-point ! 4076: | value `a' to the 32-bit two's complement integer format. The conversion ! 4077: | is performed according to the IEC/IEEE Standard for Binary Floating-Point ! 4078: | Arithmetic---which means in particular that the conversion is rounded ! 4079: | according to the current rounding mode. If `a' is a NaN, the largest ! 4080: | positive integer is returned. Otherwise, if the conversion overflows, the ! 4081: | largest integer with the same sign as `a' is returned. ! 4082: *----------------------------------------------------------------------------*/ ! 4083: ! 4084: int32 float128_to_int32( float128 a STATUS_PARAM ) ! 4085: { ! 4086: flag aSign; ! 4087: int32 aExp, shiftCount; ! 4088: bits64 aSig0, aSig1; ! 4089: ! 4090: aSig1 = extractFloat128Frac1( a ); ! 4091: aSig0 = extractFloat128Frac0( a ); ! 4092: aExp = extractFloat128Exp( a ); ! 4093: aSign = extractFloat128Sign( a ); ! 4094: if ( ( aExp == 0x7FFF ) && ( aSig0 | aSig1 ) ) aSign = 0; ! 4095: if ( aExp ) aSig0 |= LIT64( 0x0001000000000000 ); ! 4096: aSig0 |= ( aSig1 != 0 ); ! 4097: shiftCount = 0x4028 - aExp; ! 4098: if ( 0 < shiftCount ) shift64RightJamming( aSig0, shiftCount, &aSig0 ); ! 4099: return roundAndPackInt32( aSign, aSig0 STATUS_VAR ); ! 4100: ! 4101: } ! 4102: ! 4103: /*---------------------------------------------------------------------------- ! 4104: | Returns the result of converting the quadruple-precision floating-point ! 4105: | value `a' to the 32-bit two's complement integer format. The conversion ! 4106: | is performed according to the IEC/IEEE Standard for Binary Floating-Point ! 4107: | Arithmetic, except that the conversion is always rounded toward zero. If ! 4108: | `a' is a NaN, the largest positive integer is returned. Otherwise, if the ! 4109: | conversion overflows, the largest integer with the same sign as `a' is ! 4110: | returned. ! 4111: *----------------------------------------------------------------------------*/ ! 4112: ! 4113: int32 float128_to_int32_round_to_zero( float128 a STATUS_PARAM ) ! 4114: { ! 4115: flag aSign; ! 4116: int32 aExp, shiftCount; ! 4117: bits64 aSig0, aSig1, savedASig; ! 4118: int32 z; ! 4119: ! 4120: aSig1 = extractFloat128Frac1( a ); ! 4121: aSig0 = extractFloat128Frac0( a ); ! 4122: aExp = extractFloat128Exp( a ); ! 4123: aSign = extractFloat128Sign( a ); ! 4124: aSig0 |= ( aSig1 != 0 ); ! 4125: if ( 0x401E < aExp ) { ! 4126: if ( ( aExp == 0x7FFF ) && aSig0 ) aSign = 0; ! 4127: goto invalid; ! 4128: } ! 4129: else if ( aExp < 0x3FFF ) { ! 4130: if ( aExp || aSig0 ) STATUS(float_exception_flags) |= float_flag_inexact; ! 4131: return 0; ! 4132: } ! 4133: aSig0 |= LIT64( 0x0001000000000000 ); ! 4134: shiftCount = 0x402F - aExp; ! 4135: savedASig = aSig0; ! 4136: aSig0 >>= shiftCount; ! 4137: z = aSig0; ! 4138: if ( aSign ) z = - z; ! 4139: if ( ( z < 0 ) ^ aSign ) { ! 4140: invalid: ! 4141: float_raise( float_flag_invalid STATUS_VAR); ! 4142: return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF; ! 4143: } ! 4144: if ( ( aSig0<<shiftCount ) != savedASig ) { ! 4145: STATUS(float_exception_flags) |= float_flag_inexact; ! 4146: } ! 4147: return z; ! 4148: ! 4149: } ! 4150: ! 4151: /*---------------------------------------------------------------------------- ! 4152: | Returns the result of converting the quadruple-precision floating-point ! 4153: | value `a' to the 64-bit two's complement integer format. The conversion ! 4154: | is performed according to the IEC/IEEE Standard for Binary Floating-Point ! 4155: | Arithmetic---which means in particular that the conversion is rounded ! 4156: | according to the current rounding mode. If `a' is a NaN, the largest ! 4157: | positive integer is returned. Otherwise, if the conversion overflows, the ! 4158: | largest integer with the same sign as `a' is returned. ! 4159: *----------------------------------------------------------------------------*/ ! 4160: ! 4161: int64 float128_to_int64( float128 a STATUS_PARAM ) ! 4162: { ! 4163: flag aSign; ! 4164: int32 aExp, shiftCount; ! 4165: bits64 aSig0, aSig1; ! 4166: ! 4167: aSig1 = extractFloat128Frac1( a ); ! 4168: aSig0 = extractFloat128Frac0( a ); ! 4169: aExp = extractFloat128Exp( a ); ! 4170: aSign = extractFloat128Sign( a ); ! 4171: if ( aExp ) aSig0 |= LIT64( 0x0001000000000000 ); ! 4172: shiftCount = 0x402F - aExp; ! 4173: if ( shiftCount <= 0 ) { ! 4174: if ( 0x403E < aExp ) { ! 4175: float_raise( float_flag_invalid STATUS_VAR); ! 4176: if ( ! aSign ! 4177: || ( ( aExp == 0x7FFF ) ! 4178: && ( aSig1 || ( aSig0 != LIT64( 0x0001000000000000 ) ) ) ! 4179: ) ! 4180: ) { ! 4181: return LIT64( 0x7FFFFFFFFFFFFFFF ); ! 4182: } ! 4183: return (sbits64) LIT64( 0x8000000000000000 ); ! 4184: } ! 4185: shortShift128Left( aSig0, aSig1, - shiftCount, &aSig0, &aSig1 ); ! 4186: } ! 4187: else { ! 4188: shift64ExtraRightJamming( aSig0, aSig1, shiftCount, &aSig0, &aSig1 ); ! 4189: } ! 4190: return roundAndPackInt64( aSign, aSig0, aSig1 STATUS_VAR ); ! 4191: ! 4192: } ! 4193: ! 4194: /*---------------------------------------------------------------------------- ! 4195: | Returns the result of converting the quadruple-precision floating-point ! 4196: | value `a' to the 64-bit two's complement integer format. The conversion ! 4197: | is performed according to the IEC/IEEE Standard for Binary Floating-Point ! 4198: | Arithmetic, except that the conversion is always rounded toward zero. ! 4199: | If `a' is a NaN, the largest positive integer is returned. Otherwise, if ! 4200: | the conversion overflows, the largest integer with the same sign as `a' is ! 4201: | returned. ! 4202: *----------------------------------------------------------------------------*/ ! 4203: ! 4204: int64 float128_to_int64_round_to_zero( float128 a STATUS_PARAM ) ! 4205: { ! 4206: flag aSign; ! 4207: int32 aExp, shiftCount; ! 4208: bits64 aSig0, aSig1; ! 4209: int64 z; ! 4210: ! 4211: aSig1 = extractFloat128Frac1( a ); ! 4212: aSig0 = extractFloat128Frac0( a ); ! 4213: aExp = extractFloat128Exp( a ); ! 4214: aSign = extractFloat128Sign( a ); ! 4215: if ( aExp ) aSig0 |= LIT64( 0x0001000000000000 ); ! 4216: shiftCount = aExp - 0x402F; ! 4217: if ( 0 < shiftCount ) { ! 4218: if ( 0x403E <= aExp ) { ! 4219: aSig0 &= LIT64( 0x0000FFFFFFFFFFFF ); ! 4220: if ( ( a.high == LIT64( 0xC03E000000000000 ) ) ! 4221: && ( aSig1 < LIT64( 0x0002000000000000 ) ) ) { ! 4222: if ( aSig1 ) STATUS(float_exception_flags) |= float_flag_inexact; ! 4223: } ! 4224: else { ! 4225: float_raise( float_flag_invalid STATUS_VAR); ! 4226: if ( ! aSign || ( ( aExp == 0x7FFF ) && ( aSig0 | aSig1 ) ) ) { ! 4227: return LIT64( 0x7FFFFFFFFFFFFFFF ); ! 4228: } ! 4229: } ! 4230: return (sbits64) LIT64( 0x8000000000000000 ); ! 4231: } ! 4232: z = ( aSig0<<shiftCount ) | ( aSig1>>( ( - shiftCount ) & 63 ) ); ! 4233: if ( (bits64) ( aSig1<<shiftCount ) ) { ! 4234: STATUS(float_exception_flags) |= float_flag_inexact; ! 4235: } ! 4236: } ! 4237: else { ! 4238: if ( aExp < 0x3FFF ) { ! 4239: if ( aExp | aSig0 | aSig1 ) { ! 4240: STATUS(float_exception_flags) |= float_flag_inexact; ! 4241: } ! 4242: return 0; ! 4243: } ! 4244: z = aSig0>>( - shiftCount ); ! 4245: if ( aSig1 ! 4246: || ( shiftCount && (bits64) ( aSig0<<( shiftCount & 63 ) ) ) ) { ! 4247: STATUS(float_exception_flags) |= float_flag_inexact; ! 4248: } ! 4249: } ! 4250: if ( aSign ) z = - z; ! 4251: return z; ! 4252: ! 4253: } ! 4254: ! 4255: /*---------------------------------------------------------------------------- ! 4256: | Returns the result of converting the quadruple-precision floating-point ! 4257: | value `a' to the single-precision floating-point format. The conversion ! 4258: | is performed according to the IEC/IEEE Standard for Binary Floating-Point ! 4259: | Arithmetic. ! 4260: *----------------------------------------------------------------------------*/ ! 4261: ! 4262: float32 float128_to_float32( float128 a STATUS_PARAM ) ! 4263: { ! 4264: flag aSign; ! 4265: int32 aExp; ! 4266: bits64 aSig0, aSig1; ! 4267: bits32 zSig; ! 4268: ! 4269: aSig1 = extractFloat128Frac1( a ); ! 4270: aSig0 = extractFloat128Frac0( a ); ! 4271: aExp = extractFloat128Exp( a ); ! 4272: aSign = extractFloat128Sign( a ); ! 4273: if ( aExp == 0x7FFF ) { ! 4274: if ( aSig0 | aSig1 ) { ! 4275: return commonNaNToFloat32( float128ToCommonNaN( a STATUS_VAR ) ); ! 4276: } ! 4277: return packFloat32( aSign, 0xFF, 0 ); ! 4278: } ! 4279: aSig0 |= ( aSig1 != 0 ); ! 4280: shift64RightJamming( aSig0, 18, &aSig0 ); ! 4281: zSig = aSig0; ! 4282: if ( aExp || zSig ) { ! 4283: zSig |= 0x40000000; ! 4284: aExp -= 0x3F81; ! 4285: } ! 4286: return roundAndPackFloat32( aSign, aExp, zSig STATUS_VAR ); ! 4287: ! 4288: } ! 4289: ! 4290: /*---------------------------------------------------------------------------- ! 4291: | Returns the result of converting the quadruple-precision floating-point ! 4292: | value `a' to the double-precision floating-point format. The conversion ! 4293: | is performed according to the IEC/IEEE Standard for Binary Floating-Point ! 4294: | Arithmetic. ! 4295: *----------------------------------------------------------------------------*/ ! 4296: ! 4297: float64 float128_to_float64( float128 a STATUS_PARAM ) ! 4298: { ! 4299: flag aSign; ! 4300: int32 aExp; ! 4301: bits64 aSig0, aSig1; ! 4302: ! 4303: aSig1 = extractFloat128Frac1( a ); ! 4304: aSig0 = extractFloat128Frac0( a ); ! 4305: aExp = extractFloat128Exp( a ); ! 4306: aSign = extractFloat128Sign( a ); ! 4307: if ( aExp == 0x7FFF ) { ! 4308: if ( aSig0 | aSig1 ) { ! 4309: return commonNaNToFloat64( float128ToCommonNaN( a STATUS_VAR ) ); ! 4310: } ! 4311: return packFloat64( aSign, 0x7FF, 0 ); ! 4312: } ! 4313: shortShift128Left( aSig0, aSig1, 14, &aSig0, &aSig1 ); ! 4314: aSig0 |= ( aSig1 != 0 ); ! 4315: if ( aExp || aSig0 ) { ! 4316: aSig0 |= LIT64( 0x4000000000000000 ); ! 4317: aExp -= 0x3C01; ! 4318: } ! 4319: return roundAndPackFloat64( aSign, aExp, aSig0 STATUS_VAR ); ! 4320: ! 4321: } ! 4322: ! 4323: #ifdef FLOATX80 ! 4324: ! 4325: /*---------------------------------------------------------------------------- ! 4326: | Returns the result of converting the quadruple-precision floating-point ! 4327: | value `a' to the extended double-precision floating-point format. The ! 4328: | conversion is performed according to the IEC/IEEE Standard for Binary ! 4329: | Floating-Point Arithmetic. ! 4330: *----------------------------------------------------------------------------*/ ! 4331: ! 4332: floatx80 float128_to_floatx80( float128 a STATUS_PARAM ) ! 4333: { ! 4334: flag aSign; ! 4335: int32 aExp; ! 4336: bits64 aSig0, aSig1; ! 4337: ! 4338: aSig1 = extractFloat128Frac1( a ); ! 4339: aSig0 = extractFloat128Frac0( a ); ! 4340: aExp = extractFloat128Exp( a ); ! 4341: aSign = extractFloat128Sign( a ); ! 4342: if ( aExp == 0x7FFF ) { ! 4343: if ( aSig0 | aSig1 ) { ! 4344: return commonNaNToFloatx80( float128ToCommonNaN( a STATUS_VAR ) ); ! 4345: } ! 4346: return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); ! 4347: } ! 4348: if ( aExp == 0 ) { ! 4349: if ( ( aSig0 | aSig1 ) == 0 ) return packFloatx80( aSign, 0, 0 ); ! 4350: normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); ! 4351: } ! 4352: else { ! 4353: aSig0 |= LIT64( 0x0001000000000000 ); ! 4354: } ! 4355: shortShift128Left( aSig0, aSig1, 15, &aSig0, &aSig1 ); ! 4356: return roundAndPackFloatx80( 80, aSign, aExp, aSig0, aSig1 STATUS_VAR ); ! 4357: ! 4358: } ! 4359: ! 4360: #endif ! 4361: ! 4362: /*---------------------------------------------------------------------------- ! 4363: | Rounds the quadruple-precision floating-point value `a' to an integer, and ! 4364: | returns the result as a quadruple-precision floating-point value. The ! 4365: | operation is performed according to the IEC/IEEE Standard for Binary ! 4366: | Floating-Point Arithmetic. ! 4367: *----------------------------------------------------------------------------*/ ! 4368: ! 4369: float128 float128_round_to_int( float128 a STATUS_PARAM ) ! 4370: { ! 4371: flag aSign; ! 4372: int32 aExp; ! 4373: bits64 lastBitMask, roundBitsMask; ! 4374: int8 roundingMode; ! 4375: float128 z; ! 4376: ! 4377: aExp = extractFloat128Exp( a ); ! 4378: if ( 0x402F <= aExp ) { ! 4379: if ( 0x406F <= aExp ) { ! 4380: if ( ( aExp == 0x7FFF ) ! 4381: && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ! 4382: ) { ! 4383: return propagateFloat128NaN( a, a STATUS_VAR ); ! 4384: } ! 4385: return a; ! 4386: } ! 4387: lastBitMask = 1; ! 4388: lastBitMask = ( lastBitMask<<( 0x406E - aExp ) )<<1; ! 4389: roundBitsMask = lastBitMask - 1; ! 4390: z = a; ! 4391: roundingMode = STATUS(float_rounding_mode); ! 4392: if ( roundingMode == float_round_nearest_even ) { ! 4393: if ( lastBitMask ) { ! 4394: add128( z.high, z.low, 0, lastBitMask>>1, &z.high, &z.low ); ! 4395: if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask; ! 4396: } ! 4397: else { ! 4398: if ( (sbits64) z.low < 0 ) { ! 4399: ++z.high; ! 4400: if ( (bits64) ( z.low<<1 ) == 0 ) z.high &= ~1; ! 4401: } ! 4402: } ! 4403: } ! 4404: else if ( roundingMode != float_round_to_zero ) { ! 4405: if ( extractFloat128Sign( z ) ! 4406: ^ ( roundingMode == float_round_up ) ) { ! 4407: add128( z.high, z.low, 0, roundBitsMask, &z.high, &z.low ); ! 4408: } ! 4409: } ! 4410: z.low &= ~ roundBitsMask; ! 4411: } ! 4412: else { ! 4413: if ( aExp < 0x3FFF ) { ! 4414: if ( ( ( (bits64) ( a.high<<1 ) ) | a.low ) == 0 ) return a; ! 4415: STATUS(float_exception_flags) |= float_flag_inexact; ! 4416: aSign = extractFloat128Sign( a ); ! 4417: switch ( STATUS(float_rounding_mode) ) { ! 4418: case float_round_nearest_even: ! 4419: if ( ( aExp == 0x3FFE ) ! 4420: && ( extractFloat128Frac0( a ) ! 4421: | extractFloat128Frac1( a ) ) ! 4422: ) { ! 4423: return packFloat128( aSign, 0x3FFF, 0, 0 ); ! 4424: } ! 4425: break; ! 4426: case float_round_down: ! 4427: return ! 4428: aSign ? packFloat128( 1, 0x3FFF, 0, 0 ) ! 4429: : packFloat128( 0, 0, 0, 0 ); ! 4430: case float_round_up: ! 4431: return ! 4432: aSign ? packFloat128( 1, 0, 0, 0 ) ! 4433: : packFloat128( 0, 0x3FFF, 0, 0 ); ! 4434: } ! 4435: return packFloat128( aSign, 0, 0, 0 ); ! 4436: } ! 4437: lastBitMask = 1; ! 4438: lastBitMask <<= 0x402F - aExp; ! 4439: roundBitsMask = lastBitMask - 1; ! 4440: z.low = 0; ! 4441: z.high = a.high; ! 4442: roundingMode = STATUS(float_rounding_mode); ! 4443: if ( roundingMode == float_round_nearest_even ) { ! 4444: z.high += lastBitMask>>1; ! 4445: if ( ( ( z.high & roundBitsMask ) | a.low ) == 0 ) { ! 4446: z.high &= ~ lastBitMask; ! 4447: } ! 4448: } ! 4449: else if ( roundingMode != float_round_to_zero ) { ! 4450: if ( extractFloat128Sign( z ) ! 4451: ^ ( roundingMode == float_round_up ) ) { ! 4452: z.high |= ( a.low != 0 ); ! 4453: z.high += roundBitsMask; ! 4454: } ! 4455: } ! 4456: z.high &= ~ roundBitsMask; ! 4457: } ! 4458: if ( ( z.low != a.low ) || ( z.high != a.high ) ) { ! 4459: STATUS(float_exception_flags) |= float_flag_inexact; ! 4460: } ! 4461: return z; ! 4462: ! 4463: } ! 4464: ! 4465: /*---------------------------------------------------------------------------- ! 4466: | Returns the result of adding the absolute values of the quadruple-precision ! 4467: | floating-point values `a' and `b'. If `zSign' is 1, the sum is negated ! 4468: | before being returned. `zSign' is ignored if the result is a NaN. ! 4469: | The addition is performed according to the IEC/IEEE Standard for Binary ! 4470: | Floating-Point Arithmetic. ! 4471: *----------------------------------------------------------------------------*/ ! 4472: ! 4473: static float128 addFloat128Sigs( float128 a, float128 b, flag zSign STATUS_PARAM) ! 4474: { ! 4475: int32 aExp, bExp, zExp; ! 4476: bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2; ! 4477: int32 expDiff; ! 4478: ! 4479: aSig1 = extractFloat128Frac1( a ); ! 4480: aSig0 = extractFloat128Frac0( a ); ! 4481: aExp = extractFloat128Exp( a ); ! 4482: bSig1 = extractFloat128Frac1( b ); ! 4483: bSig0 = extractFloat128Frac0( b ); ! 4484: bExp = extractFloat128Exp( b ); ! 4485: expDiff = aExp - bExp; ! 4486: if ( 0 < expDiff ) { ! 4487: if ( aExp == 0x7FFF ) { ! 4488: if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b STATUS_VAR ); ! 4489: return a; ! 4490: } ! 4491: if ( bExp == 0 ) { ! 4492: --expDiff; ! 4493: } ! 4494: else { ! 4495: bSig0 |= LIT64( 0x0001000000000000 ); ! 4496: } ! 4497: shift128ExtraRightJamming( ! 4498: bSig0, bSig1, 0, expDiff, &bSig0, &bSig1, &zSig2 ); ! 4499: zExp = aExp; ! 4500: } ! 4501: else if ( expDiff < 0 ) { ! 4502: if ( bExp == 0x7FFF ) { ! 4503: if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b STATUS_VAR ); ! 4504: return packFloat128( zSign, 0x7FFF, 0, 0 ); ! 4505: } ! 4506: if ( aExp == 0 ) { ! 4507: ++expDiff; ! 4508: } ! 4509: else { ! 4510: aSig0 |= LIT64( 0x0001000000000000 ); ! 4511: } ! 4512: shift128ExtraRightJamming( ! 4513: aSig0, aSig1, 0, - expDiff, &aSig0, &aSig1, &zSig2 ); ! 4514: zExp = bExp; ! 4515: } ! 4516: else { ! 4517: if ( aExp == 0x7FFF ) { ! 4518: if ( aSig0 | aSig1 | bSig0 | bSig1 ) { ! 4519: return propagateFloat128NaN( a, b STATUS_VAR ); ! 4520: } ! 4521: return a; ! 4522: } ! 4523: add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); ! 4524: if ( aExp == 0 ) return packFloat128( zSign, 0, zSig0, zSig1 ); ! 4525: zSig2 = 0; ! 4526: zSig0 |= LIT64( 0x0002000000000000 ); ! 4527: zExp = aExp; ! 4528: goto shiftRight1; ! 4529: } ! 4530: aSig0 |= LIT64( 0x0001000000000000 ); ! 4531: add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); ! 4532: --zExp; ! 4533: if ( zSig0 < LIT64( 0x0002000000000000 ) ) goto roundAndPack; ! 4534: ++zExp; ! 4535: shiftRight1: ! 4536: shift128ExtraRightJamming( ! 4537: zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 ); ! 4538: roundAndPack: ! 4539: return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 STATUS_VAR ); ! 4540: ! 4541: } ! 4542: ! 4543: /*---------------------------------------------------------------------------- ! 4544: | Returns the result of subtracting the absolute values of the quadruple- ! 4545: | precision floating-point values `a' and `b'. If `zSign' is 1, the ! 4546: | difference is negated before being returned. `zSign' is ignored if the ! 4547: | result is a NaN. The subtraction is performed according to the IEC/IEEE ! 4548: | Standard for Binary Floating-Point Arithmetic. ! 4549: *----------------------------------------------------------------------------*/ ! 4550: ! 4551: static float128 subFloat128Sigs( float128 a, float128 b, flag zSign STATUS_PARAM) ! 4552: { ! 4553: int32 aExp, bExp, zExp; ! 4554: bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1; ! 4555: int32 expDiff; ! 4556: float128 z; ! 4557: ! 4558: aSig1 = extractFloat128Frac1( a ); ! 4559: aSig0 = extractFloat128Frac0( a ); ! 4560: aExp = extractFloat128Exp( a ); ! 4561: bSig1 = extractFloat128Frac1( b ); ! 4562: bSig0 = extractFloat128Frac0( b ); ! 4563: bExp = extractFloat128Exp( b ); ! 4564: expDiff = aExp - bExp; ! 4565: shortShift128Left( aSig0, aSig1, 14, &aSig0, &aSig1 ); ! 4566: shortShift128Left( bSig0, bSig1, 14, &bSig0, &bSig1 ); ! 4567: if ( 0 < expDiff ) goto aExpBigger; ! 4568: if ( expDiff < 0 ) goto bExpBigger; ! 4569: if ( aExp == 0x7FFF ) { ! 4570: if ( aSig0 | aSig1 | bSig0 | bSig1 ) { ! 4571: return propagateFloat128NaN( a, b STATUS_VAR ); ! 4572: } ! 4573: float_raise( float_flag_invalid STATUS_VAR); ! 4574: z.low = float128_default_nan_low; ! 4575: z.high = float128_default_nan_high; ! 4576: return z; ! 4577: } ! 4578: if ( aExp == 0 ) { ! 4579: aExp = 1; ! 4580: bExp = 1; ! 4581: } ! 4582: if ( bSig0 < aSig0 ) goto aBigger; ! 4583: if ( aSig0 < bSig0 ) goto bBigger; ! 4584: if ( bSig1 < aSig1 ) goto aBigger; ! 4585: if ( aSig1 < bSig1 ) goto bBigger; ! 4586: return packFloat128( STATUS(float_rounding_mode) == float_round_down, 0, 0, 0 ); ! 4587: bExpBigger: ! 4588: if ( bExp == 0x7FFF ) { ! 4589: if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b STATUS_VAR ); ! 4590: return packFloat128( zSign ^ 1, 0x7FFF, 0, 0 ); ! 4591: } ! 4592: if ( aExp == 0 ) { ! 4593: ++expDiff; ! 4594: } ! 4595: else { ! 4596: aSig0 |= LIT64( 0x4000000000000000 ); ! 4597: } ! 4598: shift128RightJamming( aSig0, aSig1, - expDiff, &aSig0, &aSig1 ); ! 4599: bSig0 |= LIT64( 0x4000000000000000 ); ! 4600: bBigger: ! 4601: sub128( bSig0, bSig1, aSig0, aSig1, &zSig0, &zSig1 ); ! 4602: zExp = bExp; ! 4603: zSign ^= 1; ! 4604: goto normalizeRoundAndPack; ! 4605: aExpBigger: ! 4606: if ( aExp == 0x7FFF ) { ! 4607: if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b STATUS_VAR ); ! 4608: return a; ! 4609: } ! 4610: if ( bExp == 0 ) { ! 4611: --expDiff; ! 4612: } ! 4613: else { ! 4614: bSig0 |= LIT64( 0x4000000000000000 ); ! 4615: } ! 4616: shift128RightJamming( bSig0, bSig1, expDiff, &bSig0, &bSig1 ); ! 4617: aSig0 |= LIT64( 0x4000000000000000 ); ! 4618: aBigger: ! 4619: sub128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); ! 4620: zExp = aExp; ! 4621: normalizeRoundAndPack: ! 4622: --zExp; ! 4623: return normalizeRoundAndPackFloat128( zSign, zExp - 14, zSig0, zSig1 STATUS_VAR ); ! 4624: ! 4625: } ! 4626: ! 4627: /*---------------------------------------------------------------------------- ! 4628: | Returns the result of adding the quadruple-precision floating-point values ! 4629: | `a' and `b'. The operation is performed according to the IEC/IEEE Standard ! 4630: | for Binary Floating-Point Arithmetic. ! 4631: *----------------------------------------------------------------------------*/ ! 4632: ! 4633: float128 float128_add( float128 a, float128 b STATUS_PARAM ) ! 4634: { ! 4635: flag aSign, bSign; ! 4636: ! 4637: aSign = extractFloat128Sign( a ); ! 4638: bSign = extractFloat128Sign( b ); ! 4639: if ( aSign == bSign ) { ! 4640: return addFloat128Sigs( a, b, aSign STATUS_VAR ); ! 4641: } ! 4642: else { ! 4643: return subFloat128Sigs( a, b, aSign STATUS_VAR ); ! 4644: } ! 4645: ! 4646: } ! 4647: ! 4648: /*---------------------------------------------------------------------------- ! 4649: | Returns the result of subtracting the quadruple-precision floating-point ! 4650: | values `a' and `b'. The operation is performed according to the IEC/IEEE ! 4651: | Standard for Binary Floating-Point Arithmetic. ! 4652: *----------------------------------------------------------------------------*/ ! 4653: ! 4654: float128 float128_sub( float128 a, float128 b STATUS_PARAM ) ! 4655: { ! 4656: flag aSign, bSign; ! 4657: ! 4658: aSign = extractFloat128Sign( a ); ! 4659: bSign = extractFloat128Sign( b ); ! 4660: if ( aSign == bSign ) { ! 4661: return subFloat128Sigs( a, b, aSign STATUS_VAR ); ! 4662: } ! 4663: else { ! 4664: return addFloat128Sigs( a, b, aSign STATUS_VAR ); ! 4665: } ! 4666: ! 4667: } ! 4668: ! 4669: /*---------------------------------------------------------------------------- ! 4670: | Returns the result of multiplying the quadruple-precision floating-point ! 4671: | values `a' and `b'. The operation is performed according to the IEC/IEEE ! 4672: | Standard for Binary Floating-Point Arithmetic. ! 4673: *----------------------------------------------------------------------------*/ ! 4674: ! 4675: float128 float128_mul( float128 a, float128 b STATUS_PARAM ) ! 4676: { ! 4677: flag aSign, bSign, zSign; ! 4678: int32 aExp, bExp, zExp; ! 4679: bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3; ! 4680: float128 z; ! 4681: ! 4682: aSig1 = extractFloat128Frac1( a ); ! 4683: aSig0 = extractFloat128Frac0( a ); ! 4684: aExp = extractFloat128Exp( a ); ! 4685: aSign = extractFloat128Sign( a ); ! 4686: bSig1 = extractFloat128Frac1( b ); ! 4687: bSig0 = extractFloat128Frac0( b ); ! 4688: bExp = extractFloat128Exp( b ); ! 4689: bSign = extractFloat128Sign( b ); ! 4690: zSign = aSign ^ bSign; ! 4691: if ( aExp == 0x7FFF ) { ! 4692: if ( ( aSig0 | aSig1 ) ! 4693: || ( ( bExp == 0x7FFF ) && ( bSig0 | bSig1 ) ) ) { ! 4694: return propagateFloat128NaN( a, b STATUS_VAR ); ! 4695: } ! 4696: if ( ( bExp | bSig0 | bSig1 ) == 0 ) goto invalid; ! 4697: return packFloat128( zSign, 0x7FFF, 0, 0 ); ! 4698: } ! 4699: if ( bExp == 0x7FFF ) { ! 4700: if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b STATUS_VAR ); ! 4701: if ( ( aExp | aSig0 | aSig1 ) == 0 ) { ! 4702: invalid: ! 4703: float_raise( float_flag_invalid STATUS_VAR); ! 4704: z.low = float128_default_nan_low; ! 4705: z.high = float128_default_nan_high; ! 4706: return z; ! 4707: } ! 4708: return packFloat128( zSign, 0x7FFF, 0, 0 ); ! 4709: } ! 4710: if ( aExp == 0 ) { ! 4711: if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 ); ! 4712: normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); ! 4713: } ! 4714: if ( bExp == 0 ) { ! 4715: if ( ( bSig0 | bSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 ); ! 4716: normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 ); ! 4717: } ! 4718: zExp = aExp + bExp - 0x4000; ! 4719: aSig0 |= LIT64( 0x0001000000000000 ); ! 4720: shortShift128Left( bSig0, bSig1, 16, &bSig0, &bSig1 ); ! 4721: mul128To256( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1, &zSig2, &zSig3 ); ! 4722: add128( zSig0, zSig1, aSig0, aSig1, &zSig0, &zSig1 ); ! 4723: zSig2 |= ( zSig3 != 0 ); ! 4724: if ( LIT64( 0x0002000000000000 ) <= zSig0 ) { ! 4725: shift128ExtraRightJamming( ! 4726: zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 ); ! 4727: ++zExp; ! 4728: } ! 4729: return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 STATUS_VAR ); ! 4730: ! 4731: } ! 4732: ! 4733: /*---------------------------------------------------------------------------- ! 4734: | Returns the result of dividing the quadruple-precision floating-point value ! 4735: | `a' by the corresponding value `b'. The operation is performed according to ! 4736: | the IEC/IEEE Standard for Binary Floating-Point Arithmetic. ! 4737: *----------------------------------------------------------------------------*/ ! 4738: ! 4739: float128 float128_div( float128 a, float128 b STATUS_PARAM ) ! 4740: { ! 4741: flag aSign, bSign, zSign; ! 4742: int32 aExp, bExp, zExp; ! 4743: bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2; ! 4744: bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3; ! 4745: float128 z; ! 4746: ! 4747: aSig1 = extractFloat128Frac1( a ); ! 4748: aSig0 = extractFloat128Frac0( a ); ! 4749: aExp = extractFloat128Exp( a ); ! 4750: aSign = extractFloat128Sign( a ); ! 4751: bSig1 = extractFloat128Frac1( b ); ! 4752: bSig0 = extractFloat128Frac0( b ); ! 4753: bExp = extractFloat128Exp( b ); ! 4754: bSign = extractFloat128Sign( b ); ! 4755: zSign = aSign ^ bSign; ! 4756: if ( aExp == 0x7FFF ) { ! 4757: if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b STATUS_VAR ); ! 4758: if ( bExp == 0x7FFF ) { ! 4759: if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b STATUS_VAR ); ! 4760: goto invalid; ! 4761: } ! 4762: return packFloat128( zSign, 0x7FFF, 0, 0 ); ! 4763: } ! 4764: if ( bExp == 0x7FFF ) { ! 4765: if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b STATUS_VAR ); ! 4766: return packFloat128( zSign, 0, 0, 0 ); ! 4767: } ! 4768: if ( bExp == 0 ) { ! 4769: if ( ( bSig0 | bSig1 ) == 0 ) { ! 4770: if ( ( aExp | aSig0 | aSig1 ) == 0 ) { ! 4771: invalid: ! 4772: float_raise( float_flag_invalid STATUS_VAR); ! 4773: z.low = float128_default_nan_low; ! 4774: z.high = float128_default_nan_high; ! 4775: return z; ! 4776: } ! 4777: float_raise( float_flag_divbyzero STATUS_VAR); ! 4778: return packFloat128( zSign, 0x7FFF, 0, 0 ); ! 4779: } ! 4780: normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 ); ! 4781: } ! 4782: if ( aExp == 0 ) { ! 4783: if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 ); ! 4784: normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); ! 4785: } ! 4786: zExp = aExp - bExp + 0x3FFD; ! 4787: shortShift128Left( ! 4788: aSig0 | LIT64( 0x0001000000000000 ), aSig1, 15, &aSig0, &aSig1 ); ! 4789: shortShift128Left( ! 4790: bSig0 | LIT64( 0x0001000000000000 ), bSig1, 15, &bSig0, &bSig1 ); ! 4791: if ( le128( bSig0, bSig1, aSig0, aSig1 ) ) { ! 4792: shift128Right( aSig0, aSig1, 1, &aSig0, &aSig1 ); ! 4793: ++zExp; ! 4794: } ! 4795: zSig0 = estimateDiv128To64( aSig0, aSig1, bSig0 ); ! 4796: mul128By64To192( bSig0, bSig1, zSig0, &term0, &term1, &term2 ); ! 4797: sub192( aSig0, aSig1, 0, term0, term1, term2, &rem0, &rem1, &rem2 ); ! 4798: while ( (sbits64) rem0 < 0 ) { ! 4799: --zSig0; ! 4800: add192( rem0, rem1, rem2, 0, bSig0, bSig1, &rem0, &rem1, &rem2 ); ! 4801: } ! 4802: zSig1 = estimateDiv128To64( rem1, rem2, bSig0 ); ! 4803: if ( ( zSig1 & 0x3FFF ) <= 4 ) { ! 4804: mul128By64To192( bSig0, bSig1, zSig1, &term1, &term2, &term3 ); ! 4805: sub192( rem1, rem2, 0, term1, term2, term3, &rem1, &rem2, &rem3 ); ! 4806: while ( (sbits64) rem1 < 0 ) { ! 4807: --zSig1; ! 4808: add192( rem1, rem2, rem3, 0, bSig0, bSig1, &rem1, &rem2, &rem3 ); ! 4809: } ! 4810: zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 ); ! 4811: } ! 4812: shift128ExtraRightJamming( zSig0, zSig1, 0, 15, &zSig0, &zSig1, &zSig2 ); ! 4813: return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 STATUS_VAR ); ! 4814: ! 4815: } ! 4816: ! 4817: /*---------------------------------------------------------------------------- ! 4818: | Returns the remainder of the quadruple-precision floating-point value `a' ! 4819: | with respect to the corresponding value `b'. The operation is performed ! 4820: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. ! 4821: *----------------------------------------------------------------------------*/ ! 4822: ! 4823: float128 float128_rem( float128 a, float128 b STATUS_PARAM ) ! 4824: { ! 4825: flag aSign, bSign, zSign; ! 4826: int32 aExp, bExp, expDiff; ! 4827: bits64 aSig0, aSig1, bSig0, bSig1, q, term0, term1, term2; ! 4828: bits64 allZero, alternateASig0, alternateASig1, sigMean1; ! 4829: sbits64 sigMean0; ! 4830: float128 z; ! 4831: ! 4832: aSig1 = extractFloat128Frac1( a ); ! 4833: aSig0 = extractFloat128Frac0( a ); ! 4834: aExp = extractFloat128Exp( a ); ! 4835: aSign = extractFloat128Sign( a ); ! 4836: bSig1 = extractFloat128Frac1( b ); ! 4837: bSig0 = extractFloat128Frac0( b ); ! 4838: bExp = extractFloat128Exp( b ); ! 4839: bSign = extractFloat128Sign( b ); ! 4840: if ( aExp == 0x7FFF ) { ! 4841: if ( ( aSig0 | aSig1 ) ! 4842: || ( ( bExp == 0x7FFF ) && ( bSig0 | bSig1 ) ) ) { ! 4843: return propagateFloat128NaN( a, b STATUS_VAR ); ! 4844: } ! 4845: goto invalid; ! 4846: } ! 4847: if ( bExp == 0x7FFF ) { ! 4848: if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b STATUS_VAR ); ! 4849: return a; ! 4850: } ! 4851: if ( bExp == 0 ) { ! 4852: if ( ( bSig0 | bSig1 ) == 0 ) { ! 4853: invalid: ! 4854: float_raise( float_flag_invalid STATUS_VAR); ! 4855: z.low = float128_default_nan_low; ! 4856: z.high = float128_default_nan_high; ! 4857: return z; ! 4858: } ! 4859: normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 ); ! 4860: } ! 4861: if ( aExp == 0 ) { ! 4862: if ( ( aSig0 | aSig1 ) == 0 ) return a; ! 4863: normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); ! 4864: } ! 4865: expDiff = aExp - bExp; ! 4866: if ( expDiff < -1 ) return a; ! 4867: shortShift128Left( ! 4868: aSig0 | LIT64( 0x0001000000000000 ), ! 4869: aSig1, ! 4870: 15 - ( expDiff < 0 ), ! 4871: &aSig0, ! 4872: &aSig1 ! 4873: ); ! 4874: shortShift128Left( ! 4875: bSig0 | LIT64( 0x0001000000000000 ), bSig1, 15, &bSig0, &bSig1 ); ! 4876: q = le128( bSig0, bSig1, aSig0, aSig1 ); ! 4877: if ( q ) sub128( aSig0, aSig1, bSig0, bSig1, &aSig0, &aSig1 ); ! 4878: expDiff -= 64; ! 4879: while ( 0 < expDiff ) { ! 4880: q = estimateDiv128To64( aSig0, aSig1, bSig0 ); ! 4881: q = ( 4 < q ) ? q - 4 : 0; ! 4882: mul128By64To192( bSig0, bSig1, q, &term0, &term1, &term2 ); ! 4883: shortShift192Left( term0, term1, term2, 61, &term1, &term2, &allZero ); ! 4884: shortShift128Left( aSig0, aSig1, 61, &aSig0, &allZero ); ! 4885: sub128( aSig0, 0, term1, term2, &aSig0, &aSig1 ); ! 4886: expDiff -= 61; ! 4887: } ! 4888: if ( -64 < expDiff ) { ! 4889: q = estimateDiv128To64( aSig0, aSig1, bSig0 ); ! 4890: q = ( 4 < q ) ? q - 4 : 0; ! 4891: q >>= - expDiff; ! 4892: shift128Right( bSig0, bSig1, 12, &bSig0, &bSig1 ); ! 4893: expDiff += 52; ! 4894: if ( expDiff < 0 ) { ! 4895: shift128Right( aSig0, aSig1, - expDiff, &aSig0, &aSig1 ); ! 4896: } ! 4897: else { ! 4898: shortShift128Left( aSig0, aSig1, expDiff, &aSig0, &aSig1 ); ! 4899: } ! 4900: mul128By64To192( bSig0, bSig1, q, &term0, &term1, &term2 ); ! 4901: sub128( aSig0, aSig1, term1, term2, &aSig0, &aSig1 ); ! 4902: } ! 4903: else { ! 4904: shift128Right( aSig0, aSig1, 12, &aSig0, &aSig1 ); ! 4905: shift128Right( bSig0, bSig1, 12, &bSig0, &bSig1 ); ! 4906: } ! 4907: do { ! 4908: alternateASig0 = aSig0; ! 4909: alternateASig1 = aSig1; ! 4910: ++q; ! 4911: sub128( aSig0, aSig1, bSig0, bSig1, &aSig0, &aSig1 ); ! 4912: } while ( 0 <= (sbits64) aSig0 ); ! 4913: add128( ! 4914: aSig0, aSig1, alternateASig0, alternateASig1, &sigMean0, &sigMean1 ); ! 4915: if ( ( sigMean0 < 0 ) ! 4916: || ( ( ( sigMean0 | sigMean1 ) == 0 ) && ( q & 1 ) ) ) { ! 4917: aSig0 = alternateASig0; ! 4918: aSig1 = alternateASig1; ! 4919: } ! 4920: zSign = ( (sbits64) aSig0 < 0 ); ! 4921: if ( zSign ) sub128( 0, 0, aSig0, aSig1, &aSig0, &aSig1 ); ! 4922: return ! 4923: normalizeRoundAndPackFloat128( aSign ^ zSign, bExp - 4, aSig0, aSig1 STATUS_VAR ); ! 4924: ! 4925: } ! 4926: ! 4927: /*---------------------------------------------------------------------------- ! 4928: | Returns the square root of the quadruple-precision floating-point value `a'. ! 4929: | The operation is performed according to the IEC/IEEE Standard for Binary ! 4930: | Floating-Point Arithmetic. ! 4931: *----------------------------------------------------------------------------*/ ! 4932: ! 4933: float128 float128_sqrt( float128 a STATUS_PARAM ) ! 4934: { ! 4935: flag aSign; ! 4936: int32 aExp, zExp; ! 4937: bits64 aSig0, aSig1, zSig0, zSig1, zSig2, doubleZSig0; ! 4938: bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3; ! 4939: float128 z; ! 4940: ! 4941: aSig1 = extractFloat128Frac1( a ); ! 4942: aSig0 = extractFloat128Frac0( a ); ! 4943: aExp = extractFloat128Exp( a ); ! 4944: aSign = extractFloat128Sign( a ); ! 4945: if ( aExp == 0x7FFF ) { ! 4946: if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, a STATUS_VAR ); ! 4947: if ( ! aSign ) return a; ! 4948: goto invalid; ! 4949: } ! 4950: if ( aSign ) { ! 4951: if ( ( aExp | aSig0 | aSig1 ) == 0 ) return a; ! 4952: invalid: ! 4953: float_raise( float_flag_invalid STATUS_VAR); ! 4954: z.low = float128_default_nan_low; ! 4955: z.high = float128_default_nan_high; ! 4956: return z; ! 4957: } ! 4958: if ( aExp == 0 ) { ! 4959: if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( 0, 0, 0, 0 ); ! 4960: normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); ! 4961: } ! 4962: zExp = ( ( aExp - 0x3FFF )>>1 ) + 0x3FFE; ! 4963: aSig0 |= LIT64( 0x0001000000000000 ); ! 4964: zSig0 = estimateSqrt32( aExp, aSig0>>17 ); ! 4965: shortShift128Left( aSig0, aSig1, 13 - ( aExp & 1 ), &aSig0, &aSig1 ); ! 4966: zSig0 = estimateDiv128To64( aSig0, aSig1, zSig0<<32 ) + ( zSig0<<30 ); ! 4967: doubleZSig0 = zSig0<<1; ! 4968: mul64To128( zSig0, zSig0, &term0, &term1 ); ! 4969: sub128( aSig0, aSig1, term0, term1, &rem0, &rem1 ); ! 4970: while ( (sbits64) rem0 < 0 ) { ! 4971: --zSig0; ! 4972: doubleZSig0 -= 2; ! 4973: add128( rem0, rem1, zSig0>>63, doubleZSig0 | 1, &rem0, &rem1 ); ! 4974: } ! 4975: zSig1 = estimateDiv128To64( rem1, 0, doubleZSig0 ); ! 4976: if ( ( zSig1 & 0x1FFF ) <= 5 ) { ! 4977: if ( zSig1 == 0 ) zSig1 = 1; ! 4978: mul64To128( doubleZSig0, zSig1, &term1, &term2 ); ! 4979: sub128( rem1, 0, term1, term2, &rem1, &rem2 ); ! 4980: mul64To128( zSig1, zSig1, &term2, &term3 ); ! 4981: sub192( rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3 ); ! 4982: while ( (sbits64) rem1 < 0 ) { ! 4983: --zSig1; ! 4984: shortShift128Left( 0, zSig1, 1, &term2, &term3 ); ! 4985: term3 |= 1; ! 4986: term2 |= doubleZSig0; ! 4987: add192( rem1, rem2, rem3, 0, term2, term3, &rem1, &rem2, &rem3 ); ! 4988: } ! 4989: zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 ); ! 4990: } ! 4991: shift128ExtraRightJamming( zSig0, zSig1, 0, 14, &zSig0, &zSig1, &zSig2 ); ! 4992: return roundAndPackFloat128( 0, zExp, zSig0, zSig1, zSig2 STATUS_VAR ); ! 4993: ! 4994: } ! 4995: ! 4996: /*---------------------------------------------------------------------------- ! 4997: | Returns 1 if the quadruple-precision floating-point value `a' is equal to ! 4998: | the corresponding value `b', and 0 otherwise. The comparison is performed ! 4999: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. ! 5000: *----------------------------------------------------------------------------*/ ! 5001: ! 5002: flag float128_eq( float128 a, float128 b STATUS_PARAM ) ! 5003: { ! 5004: ! 5005: if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) ! 5006: && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) ! 5007: || ( ( extractFloat128Exp( b ) == 0x7FFF ) ! 5008: && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) ! 5009: ) { ! 5010: if ( float128_is_signaling_nan( a ) ! 5011: || float128_is_signaling_nan( b ) ) { ! 5012: float_raise( float_flag_invalid STATUS_VAR); ! 5013: } ! 5014: return 0; ! 5015: } ! 5016: return ! 5017: ( a.low == b.low ) ! 5018: && ( ( a.high == b.high ) ! 5019: || ( ( a.low == 0 ) ! 5020: && ( (bits64) ( ( a.high | b.high )<<1 ) == 0 ) ) ! 5021: ); ! 5022: ! 5023: } ! 5024: ! 5025: /*---------------------------------------------------------------------------- ! 5026: | Returns 1 if the quadruple-precision floating-point value `a' is less than ! 5027: | or equal to the corresponding value `b', and 0 otherwise. The comparison ! 5028: | is performed according to the IEC/IEEE Standard for Binary Floating-Point ! 5029: | Arithmetic. ! 5030: *----------------------------------------------------------------------------*/ ! 5031: ! 5032: flag float128_le( float128 a, float128 b STATUS_PARAM ) ! 5033: { ! 5034: flag aSign, bSign; ! 5035: ! 5036: if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) ! 5037: && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) ! 5038: || ( ( extractFloat128Exp( b ) == 0x7FFF ) ! 5039: && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) ! 5040: ) { ! 5041: float_raise( float_flag_invalid STATUS_VAR); ! 5042: return 0; ! 5043: } ! 5044: aSign = extractFloat128Sign( a ); ! 5045: bSign = extractFloat128Sign( b ); ! 5046: if ( aSign != bSign ) { ! 5047: return ! 5048: aSign ! 5049: || ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) ! 5050: == 0 ); ! 5051: } ! 5052: return ! 5053: aSign ? le128( b.high, b.low, a.high, a.low ) ! 5054: : le128( a.high, a.low, b.high, b.low ); ! 5055: ! 5056: } ! 5057: ! 5058: /*---------------------------------------------------------------------------- ! 5059: | Returns 1 if the quadruple-precision floating-point value `a' is less than ! 5060: | the corresponding value `b', and 0 otherwise. The comparison is performed ! 5061: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. ! 5062: *----------------------------------------------------------------------------*/ ! 5063: ! 5064: flag float128_lt( float128 a, float128 b STATUS_PARAM ) ! 5065: { ! 5066: flag aSign, bSign; ! 5067: ! 5068: if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) ! 5069: && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) ! 5070: || ( ( extractFloat128Exp( b ) == 0x7FFF ) ! 5071: && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) ! 5072: ) { ! 5073: float_raise( float_flag_invalid STATUS_VAR); ! 5074: return 0; ! 5075: } ! 5076: aSign = extractFloat128Sign( a ); ! 5077: bSign = extractFloat128Sign( b ); ! 5078: if ( aSign != bSign ) { ! 5079: return ! 5080: aSign ! 5081: && ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) ! 5082: != 0 ); ! 5083: } ! 5084: return ! 5085: aSign ? lt128( b.high, b.low, a.high, a.low ) ! 5086: : lt128( a.high, a.low, b.high, b.low ); ! 5087: ! 5088: } ! 5089: ! 5090: /*---------------------------------------------------------------------------- ! 5091: | Returns 1 if the quadruple-precision floating-point value `a' is equal to ! 5092: | the corresponding value `b', and 0 otherwise. The invalid exception is ! 5093: | raised if either operand is a NaN. Otherwise, the comparison is performed ! 5094: | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. ! 5095: *----------------------------------------------------------------------------*/ ! 5096: ! 5097: flag float128_eq_signaling( float128 a, float128 b STATUS_PARAM ) ! 5098: { ! 5099: ! 5100: if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) ! 5101: && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) ! 5102: || ( ( extractFloat128Exp( b ) == 0x7FFF ) ! 5103: && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) ! 5104: ) { ! 5105: float_raise( float_flag_invalid STATUS_VAR); ! 5106: return 0; ! 5107: } ! 5108: return ! 5109: ( a.low == b.low ) ! 5110: && ( ( a.high == b.high ) ! 5111: || ( ( a.low == 0 ) ! 5112: && ( (bits64) ( ( a.high | b.high )<<1 ) == 0 ) ) ! 5113: ); ! 5114: ! 5115: } ! 5116: ! 5117: /*---------------------------------------------------------------------------- ! 5118: | Returns 1 if the quadruple-precision floating-point value `a' is less than ! 5119: | or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not ! 5120: | cause an exception. Otherwise, the comparison is performed according to the ! 5121: | IEC/IEEE Standard for Binary Floating-Point Arithmetic. ! 5122: *----------------------------------------------------------------------------*/ ! 5123: ! 5124: flag float128_le_quiet( float128 a, float128 b STATUS_PARAM ) ! 5125: { ! 5126: flag aSign, bSign; ! 5127: ! 5128: if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) ! 5129: && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) ! 5130: || ( ( extractFloat128Exp( b ) == 0x7FFF ) ! 5131: && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) ! 5132: ) { ! 5133: if ( float128_is_signaling_nan( a ) ! 5134: || float128_is_signaling_nan( b ) ) { ! 5135: float_raise( float_flag_invalid STATUS_VAR); ! 5136: } ! 5137: return 0; ! 5138: } ! 5139: aSign = extractFloat128Sign( a ); ! 5140: bSign = extractFloat128Sign( b ); ! 5141: if ( aSign != bSign ) { ! 5142: return ! 5143: aSign ! 5144: || ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) ! 5145: == 0 ); ! 5146: } ! 5147: return ! 5148: aSign ? le128( b.high, b.low, a.high, a.low ) ! 5149: : le128( a.high, a.low, b.high, b.low ); ! 5150: ! 5151: } ! 5152: ! 5153: /*---------------------------------------------------------------------------- ! 5154: | Returns 1 if the quadruple-precision floating-point value `a' is less than ! 5155: | the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an ! 5156: | exception. Otherwise, the comparison is performed according to the IEC/IEEE ! 5157: | Standard for Binary Floating-Point Arithmetic. ! 5158: *----------------------------------------------------------------------------*/ ! 5159: ! 5160: flag float128_lt_quiet( float128 a, float128 b STATUS_PARAM ) ! 5161: { ! 5162: flag aSign, bSign; ! 5163: ! 5164: if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) ! 5165: && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) ! 5166: || ( ( extractFloat128Exp( b ) == 0x7FFF ) ! 5167: && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) ! 5168: ) { ! 5169: if ( float128_is_signaling_nan( a ) ! 5170: || float128_is_signaling_nan( b ) ) { ! 5171: float_raise( float_flag_invalid STATUS_VAR); ! 5172: } ! 5173: return 0; ! 5174: } ! 5175: aSign = extractFloat128Sign( a ); ! 5176: bSign = extractFloat128Sign( b ); ! 5177: if ( aSign != bSign ) { ! 5178: return ! 5179: aSign ! 5180: && ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) ! 5181: != 0 ); ! 5182: } ! 5183: return ! 5184: aSign ? lt128( b.high, b.low, a.high, a.low ) ! 5185: : lt128( a.high, a.low, b.high, b.low ); ! 5186: ! 5187: } ! 5188: ! 5189: #endif ! 5190: ! 5191: /* misc functions */ ! 5192: float32 uint32_to_float32( unsigned int a STATUS_PARAM ) ! 5193: { ! 5194: return int64_to_float32(a STATUS_VAR); ! 5195: } ! 5196: ! 5197: float64 uint32_to_float64( unsigned int a STATUS_PARAM ) ! 5198: { ! 5199: return int64_to_float64(a STATUS_VAR); ! 5200: } ! 5201: ! 5202: unsigned int float32_to_uint32( float32 a STATUS_PARAM ) ! 5203: { ! 5204: int64_t v; ! 5205: unsigned int res; ! 5206: ! 5207: v = float32_to_int64(a STATUS_VAR); ! 5208: if (v < 0) { ! 5209: res = 0; ! 5210: float_raise( float_flag_invalid STATUS_VAR); ! 5211: } else if (v > 0xffffffff) { ! 5212: res = 0xffffffff; ! 5213: float_raise( float_flag_invalid STATUS_VAR); ! 5214: } else { ! 5215: res = v; ! 5216: } ! 5217: return res; ! 5218: } ! 5219: ! 5220: unsigned int float32_to_uint32_round_to_zero( float32 a STATUS_PARAM ) ! 5221: { ! 5222: int64_t v; ! 5223: unsigned int res; ! 5224: ! 5225: v = float32_to_int64_round_to_zero(a STATUS_VAR); ! 5226: if (v < 0) { ! 5227: res = 0; ! 5228: float_raise( float_flag_invalid STATUS_VAR); ! 5229: } else if (v > 0xffffffff) { ! 5230: res = 0xffffffff; ! 5231: float_raise( float_flag_invalid STATUS_VAR); ! 5232: } else { ! 5233: res = v; ! 5234: } ! 5235: return res; ! 5236: } ! 5237: ! 5238: unsigned int float64_to_uint32( float64 a STATUS_PARAM ) ! 5239: { ! 5240: int64_t v; ! 5241: unsigned int res; ! 5242: ! 5243: v = float64_to_int64(a STATUS_VAR); ! 5244: if (v < 0) { ! 5245: res = 0; ! 5246: float_raise( float_flag_invalid STATUS_VAR); ! 5247: } else if (v > 0xffffffff) { ! 5248: res = 0xffffffff; ! 5249: float_raise( float_flag_invalid STATUS_VAR); ! 5250: } else { ! 5251: res = v; ! 5252: } ! 5253: return res; ! 5254: } ! 5255: ! 5256: unsigned int float64_to_uint32_round_to_zero( float64 a STATUS_PARAM ) ! 5257: { ! 5258: int64_t v; ! 5259: unsigned int res; ! 5260: ! 5261: v = float64_to_int64_round_to_zero(a STATUS_VAR); ! 5262: if (v < 0) { ! 5263: res = 0; ! 5264: float_raise( float_flag_invalid STATUS_VAR); ! 5265: } else if (v > 0xffffffff) { ! 5266: res = 0xffffffff; ! 5267: float_raise( float_flag_invalid STATUS_VAR); ! 5268: } else { ! 5269: res = v; ! 5270: } ! 5271: return res; ! 5272: } ! 5273: ! 5274: #define COMPARE(s, nan_exp) \ ! 5275: INLINE char float ## s ## _compare_internal( float ## s a, float ## s b, \ ! 5276: int is_quiet STATUS_PARAM ) \ ! 5277: { \ ! 5278: flag aSign, bSign; \ ! 5279: \ ! 5280: if (( ( extractFloat ## s ## Exp( a ) == nan_exp ) && \ ! 5281: extractFloat ## s ## Frac( a ) ) || \ ! 5282: ( ( extractFloat ## s ## Exp( b ) == nan_exp ) && \ ! 5283: extractFloat ## s ## Frac( b ) )) { \ ! 5284: if (!is_quiet || \ ! 5285: float ## s ## _is_signaling_nan( a ) || \ ! 5286: float ## s ## _is_signaling_nan( b ) ) { \ ! 5287: float_raise( float_flag_invalid STATUS_VAR); \ ! 5288: } \ ! 5289: return float_relation_unordered; \ ! 5290: } \ ! 5291: aSign = extractFloat ## s ## Sign( a ); \ ! 5292: bSign = extractFloat ## s ## Sign( b ); \ ! 5293: if ( aSign != bSign ) { \ ! 5294: if ( (bits ## s) ( ( a | b )<<1 ) == 0 ) { \ ! 5295: /* zero case */ \ ! 5296: return float_relation_equal; \ ! 5297: } else { \ ! 5298: return 1 - (2 * aSign); \ ! 5299: } \ ! 5300: } else { \ ! 5301: if (a == b) { \ ! 5302: return float_relation_equal; \ ! 5303: } else { \ ! 5304: return 1 - 2 * (aSign ^ ( a < b )); \ ! 5305: } \ ! 5306: } \ ! 5307: } \ ! 5308: \ ! 5309: char float ## s ## _compare( float ## s a, float ## s b STATUS_PARAM ) \ ! 5310: { \ ! 5311: return float ## s ## _compare_internal(a, b, 0 STATUS_VAR); \ ! 5312: } \ ! 5313: \ ! 5314: char float ## s ## _compare_quiet( float ## s a, float ## s b STATUS_PARAM ) \ ! 5315: { \ ! 5316: return float ## s ## _compare_internal(a, b, 1 STATUS_VAR); \ ! 5317: } ! 5318: ! 5319: COMPARE(32, 0xff) ! 5320: COMPARE(64, 0x7ff)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.