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