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