|
|
1.1 ! root 1: ! 2: /*============================================================================ ! 3: ! 4: This C source fragment is part of the SoftFloat IEC/IEEE Floating-point ! 5: Arithmetic Package, Release 2b. ! 6: ! 7: Written by John R. Hauser. This work was made possible in part by the ! 8: International Computer Science Institute, located at Suite 600, 1947 Center ! 9: Street, Berkeley, California 94704. Funding was partially provided by the ! 10: National Science Foundation under grant MIP-9311980. The original version ! 11: of this code was written as part of a project to build a fixed-point vector ! 12: processor in collaboration with the University of California at Berkeley, ! 13: overseen by Profs. Nelson Morgan and John Wawrzynek. More information ! 14: is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ ! 15: arithmetic/SoftFloat.html'. ! 16: ! 17: THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has ! 18: been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES ! 19: RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS ! 20: AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, ! 21: COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE ! 22: EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE ! 23: INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR ! 24: OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. ! 25: ! 26: Derivative works are acceptable, even for commercial purposes, so long as ! 27: (1) the source code for the derivative work includes prominent notice that ! 28: the work is derivative, and (2) the source code includes prominent notice with ! 29: these four paragraphs for those parts of this code that are retained. ! 30: ! 31: =============================================================================*/ ! 32: ! 33: /*---------------------------------------------------------------------------- ! 34: | Underflow tininess-detection mode, statically initialized to default value. ! 35: | (The declaration in `softfloat.h' must match the `int8' type here.) ! 36: *----------------------------------------------------------------------------*/ ! 37: int8 float_detect_tininess = float_tininess_after_rounding; ! 38: ! 39: /*---------------------------------------------------------------------------- ! 40: | Raises the exceptions specified by `flags'. Floating-point traps can be ! 41: | defined here if desired. It is currently not possible for such a trap ! 42: | to substitute a result value. If traps are not implemented, this routine ! 43: | should be simply `float_exception_flags |= flags;'. ! 44: *----------------------------------------------------------------------------*/ ! 45: ! 46: void float_raise( int8 flags STATUS_PARAM ) ! 47: { ! 48: ! 49: STATUS(float_exception_flags) |= flags; ! 50: ! 51: } ! 52: ! 53: /*---------------------------------------------------------------------------- ! 54: | Internal canonical NaN format. ! 55: *----------------------------------------------------------------------------*/ ! 56: typedef struct { ! 57: flag sign; ! 58: bits64 high, low; ! 59: } commonNaNT; ! 60: ! 61: /*---------------------------------------------------------------------------- ! 62: | The pattern for a default generated single-precision NaN. ! 63: *----------------------------------------------------------------------------*/ ! 64: #define float32_default_nan 0xFFC00000 ! 65: ! 66: /*---------------------------------------------------------------------------- ! 67: | Returns 1 if the single-precision floating-point value `a' is a NaN; ! 68: | otherwise returns 0. ! 69: *----------------------------------------------------------------------------*/ ! 70: ! 71: flag float32_is_nan( float32 a ) ! 72: { ! 73: ! 74: return ( 0xFF000000 < (bits32) ( a<<1 ) ); ! 75: ! 76: } ! 77: ! 78: /*---------------------------------------------------------------------------- ! 79: | Returns 1 if the single-precision floating-point value `a' is a signaling ! 80: | NaN; otherwise returns 0. ! 81: *----------------------------------------------------------------------------*/ ! 82: ! 83: flag float32_is_signaling_nan( float32 a ) ! 84: { ! 85: ! 86: return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); ! 87: ! 88: } ! 89: ! 90: /*---------------------------------------------------------------------------- ! 91: | Returns the result of converting the single-precision floating-point NaN ! 92: | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid ! 93: | exception is raised. ! 94: *----------------------------------------------------------------------------*/ ! 95: ! 96: static commonNaNT float32ToCommonNaN( float32 a STATUS_PARAM ) ! 97: { ! 98: commonNaNT z; ! 99: ! 100: if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR ); ! 101: z.sign = a>>31; ! 102: z.low = 0; ! 103: z.high = ( (bits64) a )<<41; ! 104: return z; ! 105: ! 106: } ! 107: ! 108: /*---------------------------------------------------------------------------- ! 109: | Returns the result of converting the canonical NaN `a' to the single- ! 110: | precision floating-point format. ! 111: *----------------------------------------------------------------------------*/ ! 112: ! 113: static float32 commonNaNToFloat32( commonNaNT a ) ! 114: { ! 115: ! 116: return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 ); ! 117: ! 118: } ! 119: ! 120: /*---------------------------------------------------------------------------- ! 121: | Takes two single-precision floating-point values `a' and `b', one of which ! 122: | is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a ! 123: | signaling NaN, the invalid exception is raised. ! 124: *----------------------------------------------------------------------------*/ ! 125: ! 126: static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM) ! 127: { ! 128: flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; ! 129: ! 130: aIsNaN = float32_is_nan( a ); ! 131: aIsSignalingNaN = float32_is_signaling_nan( a ); ! 132: bIsNaN = float32_is_nan( b ); ! 133: bIsSignalingNaN = float32_is_signaling_nan( b ); ! 134: a |= 0x00400000; ! 135: b |= 0x00400000; ! 136: if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR); ! 137: if ( aIsSignalingNaN ) { ! 138: if ( bIsSignalingNaN ) goto returnLargerSignificand; ! 139: return bIsNaN ? b : a; ! 140: } ! 141: else if ( aIsNaN ) { ! 142: if ( bIsSignalingNaN | ! bIsNaN ) return a; ! 143: returnLargerSignificand: ! 144: if ( (bits32) ( a<<1 ) < (bits32) ( b<<1 ) ) return b; ! 145: if ( (bits32) ( b<<1 ) < (bits32) ( a<<1 ) ) return a; ! 146: return ( a < b ) ? a : b; ! 147: } ! 148: else { ! 149: return b; ! 150: } ! 151: ! 152: } ! 153: ! 154: /*---------------------------------------------------------------------------- ! 155: | The pattern for a default generated double-precision NaN. ! 156: *----------------------------------------------------------------------------*/ ! 157: #define float64_default_nan LIT64( 0xFFF8000000000000 ) ! 158: ! 159: /*---------------------------------------------------------------------------- ! 160: | Returns 1 if the double-precision floating-point value `a' is a NaN; ! 161: | otherwise returns 0. ! 162: *----------------------------------------------------------------------------*/ ! 163: ! 164: flag float64_is_nan( float64 a ) ! 165: { ! 166: ! 167: return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) ); ! 168: ! 169: } ! 170: ! 171: /*---------------------------------------------------------------------------- ! 172: | Returns 1 if the double-precision floating-point value `a' is a signaling ! 173: | NaN; otherwise returns 0. ! 174: *----------------------------------------------------------------------------*/ ! 175: ! 176: flag float64_is_signaling_nan( float64 a ) ! 177: { ! 178: ! 179: return ! 180: ( ( ( a>>51 ) & 0xFFF ) == 0xFFE ) ! 181: && ( a & LIT64( 0x0007FFFFFFFFFFFF ) ); ! 182: ! 183: } ! 184: ! 185: /*---------------------------------------------------------------------------- ! 186: | Returns the result of converting the double-precision floating-point NaN ! 187: | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid ! 188: | exception is raised. ! 189: *----------------------------------------------------------------------------*/ ! 190: ! 191: static commonNaNT float64ToCommonNaN( float64 a STATUS_PARAM) ! 192: { ! 193: commonNaNT z; ! 194: ! 195: if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR); ! 196: z.sign = a>>63; ! 197: z.low = 0; ! 198: z.high = a<<12; ! 199: return z; ! 200: ! 201: } ! 202: ! 203: /*---------------------------------------------------------------------------- ! 204: | Returns the result of converting the canonical NaN `a' to the double- ! 205: | precision floating-point format. ! 206: *----------------------------------------------------------------------------*/ ! 207: ! 208: static float64 commonNaNToFloat64( commonNaNT a ) ! 209: { ! 210: ! 211: return ! 212: ( ( (bits64) a.sign )<<63 ) ! 213: | LIT64( 0x7FF8000000000000 ) ! 214: | ( a.high>>12 ); ! 215: ! 216: } ! 217: ! 218: /*---------------------------------------------------------------------------- ! 219: | Takes two double-precision floating-point values `a' and `b', one of which ! 220: | is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a ! 221: | signaling NaN, the invalid exception is raised. ! 222: *----------------------------------------------------------------------------*/ ! 223: ! 224: static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM) ! 225: { ! 226: flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; ! 227: ! 228: aIsNaN = float64_is_nan( a ); ! 229: aIsSignalingNaN = float64_is_signaling_nan( a ); ! 230: bIsNaN = float64_is_nan( b ); ! 231: bIsSignalingNaN = float64_is_signaling_nan( b ); ! 232: a |= LIT64( 0x0008000000000000 ); ! 233: b |= LIT64( 0x0008000000000000 ); ! 234: if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR); ! 235: if ( aIsSignalingNaN ) { ! 236: if ( bIsSignalingNaN ) goto returnLargerSignificand; ! 237: return bIsNaN ? b : a; ! 238: } ! 239: else if ( aIsNaN ) { ! 240: if ( bIsSignalingNaN | ! bIsNaN ) return a; ! 241: returnLargerSignificand: ! 242: if ( (bits64) ( a<<1 ) < (bits64) ( b<<1 ) ) return b; ! 243: if ( (bits64) ( b<<1 ) < (bits64) ( a<<1 ) ) return a; ! 244: return ( a < b ) ? a : b; ! 245: } ! 246: else { ! 247: return b; ! 248: } ! 249: ! 250: } ! 251: ! 252: #ifdef FLOATX80 ! 253: ! 254: /*---------------------------------------------------------------------------- ! 255: | The pattern for a default generated extended double-precision NaN. The ! 256: | `high' and `low' values hold the most- and least-significant bits, ! 257: | respectively. ! 258: *----------------------------------------------------------------------------*/ ! 259: #define floatx80_default_nan_high 0xFFFF ! 260: #define floatx80_default_nan_low LIT64( 0xC000000000000000 ) ! 261: ! 262: /*---------------------------------------------------------------------------- ! 263: | Returns 1 if the extended double-precision floating-point value `a' is a ! 264: | NaN; otherwise returns 0. ! 265: *----------------------------------------------------------------------------*/ ! 266: ! 267: flag floatx80_is_nan( floatx80 a ) ! 268: { ! 269: ! 270: return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 ); ! 271: ! 272: } ! 273: ! 274: /*---------------------------------------------------------------------------- ! 275: | Returns 1 if the extended double-precision floating-point value `a' is a ! 276: | signaling NaN; otherwise returns 0. ! 277: *----------------------------------------------------------------------------*/ ! 278: ! 279: flag floatx80_is_signaling_nan( floatx80 a ) ! 280: { ! 281: bits64 aLow; ! 282: ! 283: aLow = a.low & ~ LIT64( 0x4000000000000000 ); ! 284: return ! 285: ( ( a.high & 0x7FFF ) == 0x7FFF ) ! 286: && (bits64) ( aLow<<1 ) ! 287: && ( a.low == aLow ); ! 288: ! 289: } ! 290: ! 291: /*---------------------------------------------------------------------------- ! 292: | Returns the result of converting the extended double-precision floating- ! 293: | point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the ! 294: | invalid exception is raised. ! 295: *----------------------------------------------------------------------------*/ ! 296: ! 297: static commonNaNT floatx80ToCommonNaN( floatx80 a STATUS_PARAM) ! 298: { ! 299: commonNaNT z; ! 300: ! 301: if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR); ! 302: z.sign = a.high>>15; ! 303: z.low = 0; ! 304: z.high = a.low<<1; ! 305: return z; ! 306: ! 307: } ! 308: ! 309: /*---------------------------------------------------------------------------- ! 310: | Returns the result of converting the canonical NaN `a' to the extended ! 311: | double-precision floating-point format. ! 312: *----------------------------------------------------------------------------*/ ! 313: ! 314: static floatx80 commonNaNToFloatx80( commonNaNT a ) ! 315: { ! 316: floatx80 z; ! 317: ! 318: z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 ); ! 319: z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF; ! 320: return z; ! 321: ! 322: } ! 323: ! 324: /*---------------------------------------------------------------------------- ! 325: | Takes two extended double-precision floating-point values `a' and `b', one ! 326: | of which is a NaN, and returns the appropriate NaN result. If either `a' or ! 327: | `b' is a signaling NaN, the invalid exception is raised. ! 328: *----------------------------------------------------------------------------*/ ! 329: ! 330: static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b STATUS_PARAM) ! 331: { ! 332: flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; ! 333: ! 334: aIsNaN = floatx80_is_nan( a ); ! 335: aIsSignalingNaN = floatx80_is_signaling_nan( a ); ! 336: bIsNaN = floatx80_is_nan( b ); ! 337: bIsSignalingNaN = floatx80_is_signaling_nan( b ); ! 338: a.low |= LIT64( 0xC000000000000000 ); ! 339: b.low |= LIT64( 0xC000000000000000 ); ! 340: if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR); ! 341: if ( aIsSignalingNaN ) { ! 342: if ( bIsSignalingNaN ) goto returnLargerSignificand; ! 343: return bIsNaN ? b : a; ! 344: } ! 345: else if ( aIsNaN ) { ! 346: if ( bIsSignalingNaN | ! bIsNaN ) return a; ! 347: returnLargerSignificand: ! 348: if ( a.low < b.low ) return b; ! 349: if ( b.low < a.low ) return a; ! 350: return ( a.high < b.high ) ? a : b; ! 351: } ! 352: else { ! 353: return b; ! 354: } ! 355: ! 356: } ! 357: ! 358: #endif ! 359: ! 360: #ifdef FLOAT128 ! 361: ! 362: /*---------------------------------------------------------------------------- ! 363: | The pattern for a default generated quadruple-precision NaN. The `high' and ! 364: | `low' values hold the most- and least-significant bits, respectively. ! 365: *----------------------------------------------------------------------------*/ ! 366: #define float128_default_nan_high LIT64( 0xFFFF800000000000 ) ! 367: #define float128_default_nan_low LIT64( 0x0000000000000000 ) ! 368: ! 369: /*---------------------------------------------------------------------------- ! 370: | Returns 1 if the quadruple-precision floating-point value `a' is a NaN; ! 371: | otherwise returns 0. ! 372: *----------------------------------------------------------------------------*/ ! 373: ! 374: flag float128_is_nan( float128 a ) ! 375: { ! 376: ! 377: return ! 378: ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) ) ! 379: && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) ); ! 380: ! 381: } ! 382: ! 383: /*---------------------------------------------------------------------------- ! 384: | Returns 1 if the quadruple-precision floating-point value `a' is a ! 385: | signaling NaN; otherwise returns 0. ! 386: *----------------------------------------------------------------------------*/ ! 387: ! 388: flag float128_is_signaling_nan( float128 a ) ! 389: { ! 390: ! 391: return ! 392: ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE ) ! 393: && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) ); ! 394: ! 395: } ! 396: ! 397: /*---------------------------------------------------------------------------- ! 398: | Returns the result of converting the quadruple-precision floating-point NaN ! 399: | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid ! 400: | exception is raised. ! 401: *----------------------------------------------------------------------------*/ ! 402: ! 403: static commonNaNT float128ToCommonNaN( float128 a STATUS_PARAM) ! 404: { ! 405: commonNaNT z; ! 406: ! 407: if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR); ! 408: z.sign = a.high>>63; ! 409: shortShift128Left( a.high, a.low, 16, &z.high, &z.low ); ! 410: return z; ! 411: ! 412: } ! 413: ! 414: /*---------------------------------------------------------------------------- ! 415: | Returns the result of converting the canonical NaN `a' to the quadruple- ! 416: | precision floating-point format. ! 417: *----------------------------------------------------------------------------*/ ! 418: ! 419: static float128 commonNaNToFloat128( commonNaNT a ) ! 420: { ! 421: float128 z; ! 422: ! 423: shift128Right( a.high, a.low, 16, &z.high, &z.low ); ! 424: z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 ); ! 425: return z; ! 426: ! 427: } ! 428: ! 429: /*---------------------------------------------------------------------------- ! 430: | Takes two quadruple-precision floating-point values `a' and `b', one of ! 431: | which is a NaN, and returns the appropriate NaN result. If either `a' or ! 432: | `b' is a signaling NaN, the invalid exception is raised. ! 433: *----------------------------------------------------------------------------*/ ! 434: ! 435: static float128 propagateFloat128NaN( float128 a, float128 b STATUS_PARAM) ! 436: { ! 437: flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; ! 438: ! 439: aIsNaN = float128_is_nan( a ); ! 440: aIsSignalingNaN = float128_is_signaling_nan( a ); ! 441: bIsNaN = float128_is_nan( b ); ! 442: bIsSignalingNaN = float128_is_signaling_nan( b ); ! 443: a.high |= LIT64( 0x0000800000000000 ); ! 444: b.high |= LIT64( 0x0000800000000000 ); ! 445: if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR); ! 446: if ( aIsSignalingNaN ) { ! 447: if ( bIsSignalingNaN ) goto returnLargerSignificand; ! 448: return bIsNaN ? b : a; ! 449: } ! 450: else if ( aIsNaN ) { ! 451: if ( bIsSignalingNaN | ! bIsNaN ) return a; ! 452: returnLargerSignificand: ! 453: if ( lt128( a.high<<1, a.low, b.high<<1, b.low ) ) return b; ! 454: if ( lt128( b.high<<1, b.low, a.high<<1, a.low ) ) return a; ! 455: return ( a.high < b.high ) ? a : b; ! 456: } ! 457: else { ! 458: return b; ! 459: } ! 460: ! 461: } ! 462: ! 463: #endif ! 464:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.