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