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