115144b0fSOlivier Houchard/* $NetBSD: softfloat-specialize,v 1.3 2002/05/12 13:12:45 bjh21 Exp $ */ 215144b0fSOlivier Houchard/* $FreeBSD$ */ 315144b0fSOlivier Houchard 415144b0fSOlivier Houchard/* This is a derivative work. */ 515144b0fSOlivier Houchard 615144b0fSOlivier Houchard/* 715144b0fSOlivier Houchard=============================================================================== 815144b0fSOlivier Houchard 915144b0fSOlivier HouchardThis C source fragment is part of the SoftFloat IEC/IEEE Floating-point 1015144b0fSOlivier HouchardArithmetic Package, Release 2a. 1115144b0fSOlivier Houchard 1215144b0fSOlivier HouchardWritten by John R. Hauser. This work was made possible in part by the 1315144b0fSOlivier HouchardInternational Computer Science Institute, located at Suite 600, 1947 Center 1415144b0fSOlivier HouchardStreet, Berkeley, California 94704. Funding was partially provided by the 1515144b0fSOlivier HouchardNational Science Foundation under grant MIP-9311980. The original version 1615144b0fSOlivier Houchardof this code was written as part of a project to build a fixed-point vector 1715144b0fSOlivier Houchardprocessor in collaboration with the University of California at Berkeley, 1815144b0fSOlivier Houchardoverseen by Profs. Nelson Morgan and John Wawrzynek. More information 1915144b0fSOlivier Houchardis available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/ 2015144b0fSOlivier Houchardarithmetic/SoftFloat.html'. 2115144b0fSOlivier Houchard 2215144b0fSOlivier HouchardTHIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort 2315144b0fSOlivier Houchardhas been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT 2415144b0fSOlivier HouchardTIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO 2515144b0fSOlivier HouchardPERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY 2615144b0fSOlivier HouchardAND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. 2715144b0fSOlivier Houchard 2815144b0fSOlivier HouchardDerivative works are acceptable, even for commercial purposes, so long as 2915144b0fSOlivier Houchard(1) they include prominent notice that the work is derivative, and (2) they 3015144b0fSOlivier Houchardinclude prominent notice akin to these four paragraphs for those parts of 3115144b0fSOlivier Houchardthis code that are retained. 3215144b0fSOlivier Houchard 3315144b0fSOlivier Houchard=============================================================================== 3415144b0fSOlivier Houchard*/ 3515144b0fSOlivier Houchard 3615144b0fSOlivier Houchard#include <signal.h> 3715144b0fSOlivier Houchard 3815144b0fSOlivier Houchard/* 3915144b0fSOlivier Houchard------------------------------------------------------------------------------- 4015144b0fSOlivier HouchardUnderflow tininess-detection mode, statically initialized to default value. 4115144b0fSOlivier Houchard(The declaration in `softfloat.h' must match the `int8' type here.) 4215144b0fSOlivier Houchard------------------------------------------------------------------------------- 4315144b0fSOlivier Houchard*/ 4415144b0fSOlivier Houchard#ifdef SOFTFLOAT_FOR_GCC 4515144b0fSOlivier Houchardstatic 4615144b0fSOlivier Houchard#endif 47b7e9bee7SMarius Strobl#ifdef __sparc64__ 48b7e9bee7SMarius Stroblint8 float_detect_tininess = float_tininess_before_rounding; 49b7e9bee7SMarius Strobl#else 5015144b0fSOlivier Houchardint8 float_detect_tininess = float_tininess_after_rounding; 5192cb9b05SMarius Strobl#endif 5215144b0fSOlivier Houchard 5315144b0fSOlivier Houchard/* 5415144b0fSOlivier Houchard------------------------------------------------------------------------------- 5515144b0fSOlivier HouchardRaises the exceptions specified by `flags'. Floating-point traps can be 5615144b0fSOlivier Houcharddefined here if desired. It is currently not possible for such a trap to 5715144b0fSOlivier Houchardsubstitute a result value. If traps are not implemented, this routine 5815144b0fSOlivier Houchardshould be simply `float_exception_flags |= flags;'. 5915144b0fSOlivier Houchard------------------------------------------------------------------------------- 6015144b0fSOlivier Houchard*/ 61*b1d04644SDavid Schultzint float_exception_mask = 0; 62*b1d04644SDavid Schultzvoid float_raise( int flags ) 6315144b0fSOlivier Houchard{ 6415144b0fSOlivier Houchard 6515144b0fSOlivier Houchard float_exception_flags |= flags; 6615144b0fSOlivier Houchard 6715144b0fSOlivier Houchard if ( flags & float_exception_mask ) { 6815144b0fSOlivier Houchard raise( SIGFPE ); 6915144b0fSOlivier Houchard } 7015144b0fSOlivier Houchard} 7115144b0fSOlivier Houchard 7215144b0fSOlivier Houchard/* 7315144b0fSOlivier Houchard------------------------------------------------------------------------------- 7415144b0fSOlivier HouchardInternal canonical NaN format. 7515144b0fSOlivier Houchard------------------------------------------------------------------------------- 7615144b0fSOlivier Houchard*/ 7715144b0fSOlivier Houchardtypedef struct { 7815144b0fSOlivier Houchard flag sign; 7915144b0fSOlivier Houchard bits64 high, low; 8015144b0fSOlivier Houchard} commonNaNT; 8115144b0fSOlivier Houchard 8215144b0fSOlivier Houchard/* 8315144b0fSOlivier Houchard------------------------------------------------------------------------------- 8415144b0fSOlivier HouchardThe pattern for a default generated single-precision NaN. 8515144b0fSOlivier Houchard------------------------------------------------------------------------------- 8615144b0fSOlivier Houchard*/ 8715144b0fSOlivier Houchard#define float32_default_nan 0xFFFFFFFF 8815144b0fSOlivier Houchard 8915144b0fSOlivier Houchard/* 9015144b0fSOlivier Houchard------------------------------------------------------------------------------- 9115144b0fSOlivier HouchardReturns 1 if the single-precision floating-point value `a' is a NaN; 9215144b0fSOlivier Houchardotherwise returns 0. 9315144b0fSOlivier Houchard------------------------------------------------------------------------------- 9415144b0fSOlivier Houchard*/ 9515144b0fSOlivier Houchard#ifdef SOFTFLOAT_FOR_GCC 9615144b0fSOlivier Houchardstatic 9715144b0fSOlivier Houchard#endif 9815144b0fSOlivier Houchardflag float32_is_nan( float32 a ) 9915144b0fSOlivier Houchard{ 10015144b0fSOlivier Houchard 10115144b0fSOlivier Houchard return ( 0xFF000000 < (bits32) ( a<<1 ) ); 10215144b0fSOlivier Houchard 10315144b0fSOlivier Houchard} 10415144b0fSOlivier Houchard 10515144b0fSOlivier Houchard/* 10615144b0fSOlivier Houchard------------------------------------------------------------------------------- 10715144b0fSOlivier HouchardReturns 1 if the single-precision floating-point value `a' is a signaling 10815144b0fSOlivier HouchardNaN; otherwise returns 0. 10915144b0fSOlivier Houchard------------------------------------------------------------------------------- 11015144b0fSOlivier Houchard*/ 11115144b0fSOlivier Houchard#if defined(SOFTFLOAT_FOR_GCC) && !defined(SOFTFLOATSPARC64_FOR_GCC) 11215144b0fSOlivier Houchardstatic 11315144b0fSOlivier Houchard#endif 11415144b0fSOlivier Houchardflag float32_is_signaling_nan( float32 a ) 11515144b0fSOlivier Houchard{ 11615144b0fSOlivier Houchard 11715144b0fSOlivier Houchard return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); 11815144b0fSOlivier Houchard 11915144b0fSOlivier Houchard} 12015144b0fSOlivier Houchard 12115144b0fSOlivier Houchard/* 12215144b0fSOlivier Houchard------------------------------------------------------------------------------- 12315144b0fSOlivier HouchardReturns the result of converting the single-precision floating-point NaN 12415144b0fSOlivier Houchard`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 12515144b0fSOlivier Houchardexception is raised. 12615144b0fSOlivier Houchard------------------------------------------------------------------------------- 12715144b0fSOlivier Houchard*/ 12815144b0fSOlivier Houchardstatic commonNaNT float32ToCommonNaN( float32 a ) 12915144b0fSOlivier Houchard{ 13015144b0fSOlivier Houchard commonNaNT z; 13115144b0fSOlivier Houchard 13215144b0fSOlivier Houchard if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 13315144b0fSOlivier Houchard z.sign = a>>31; 13415144b0fSOlivier Houchard z.low = 0; 13515144b0fSOlivier Houchard z.high = ( (bits64) a )<<41; 13615144b0fSOlivier Houchard return z; 13715144b0fSOlivier Houchard 13815144b0fSOlivier Houchard} 13915144b0fSOlivier Houchard 14015144b0fSOlivier Houchard/* 14115144b0fSOlivier Houchard------------------------------------------------------------------------------- 14215144b0fSOlivier HouchardReturns the result of converting the canonical NaN `a' to the single- 14315144b0fSOlivier Houchardprecision floating-point format. 14415144b0fSOlivier Houchard------------------------------------------------------------------------------- 14515144b0fSOlivier Houchard*/ 14615144b0fSOlivier Houchardstatic float32 commonNaNToFloat32( commonNaNT a ) 14715144b0fSOlivier Houchard{ 14815144b0fSOlivier Houchard 14915144b0fSOlivier Houchard return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 ); 15015144b0fSOlivier Houchard 15115144b0fSOlivier Houchard} 15215144b0fSOlivier Houchard 15315144b0fSOlivier Houchard/* 15415144b0fSOlivier Houchard------------------------------------------------------------------------------- 15515144b0fSOlivier HouchardTakes two single-precision floating-point values `a' and `b', one of which 15615144b0fSOlivier Houchardis a NaN, and returns the appropriate NaN result. If either `a' or `b' is a 15715144b0fSOlivier Houchardsignaling NaN, the invalid exception is raised. 15815144b0fSOlivier Houchard------------------------------------------------------------------------------- 15915144b0fSOlivier Houchard*/ 16015144b0fSOlivier Houchardstatic float32 propagateFloat32NaN( float32 a, float32 b ) 16115144b0fSOlivier Houchard{ 16215144b0fSOlivier Houchard flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 16315144b0fSOlivier Houchard 16415144b0fSOlivier Houchard aIsNaN = float32_is_nan( a ); 16515144b0fSOlivier Houchard aIsSignalingNaN = float32_is_signaling_nan( a ); 16615144b0fSOlivier Houchard bIsNaN = float32_is_nan( b ); 16715144b0fSOlivier Houchard bIsSignalingNaN = float32_is_signaling_nan( b ); 16815144b0fSOlivier Houchard a |= 0x00400000; 16915144b0fSOlivier Houchard b |= 0x00400000; 17015144b0fSOlivier Houchard if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 17115144b0fSOlivier Houchard if ( aIsNaN ) { 17215144b0fSOlivier Houchard return ( aIsSignalingNaN & bIsNaN ) ? b : a; 17315144b0fSOlivier Houchard } 17415144b0fSOlivier Houchard else { 17515144b0fSOlivier Houchard return b; 17615144b0fSOlivier Houchard } 17715144b0fSOlivier Houchard 17815144b0fSOlivier Houchard} 17915144b0fSOlivier Houchard 18015144b0fSOlivier Houchard/* 18115144b0fSOlivier Houchard------------------------------------------------------------------------------- 18215144b0fSOlivier HouchardThe pattern for a default generated double-precision NaN. 18315144b0fSOlivier Houchard------------------------------------------------------------------------------- 18415144b0fSOlivier Houchard*/ 18515144b0fSOlivier Houchard#define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF ) 18615144b0fSOlivier Houchard 18715144b0fSOlivier Houchard/* 18815144b0fSOlivier Houchard------------------------------------------------------------------------------- 18915144b0fSOlivier HouchardReturns 1 if the double-precision floating-point value `a' is a NaN; 19015144b0fSOlivier Houchardotherwise returns 0. 19115144b0fSOlivier Houchard------------------------------------------------------------------------------- 19215144b0fSOlivier Houchard*/ 19315144b0fSOlivier Houchard#ifdef SOFTFLOAT_FOR_GCC 19415144b0fSOlivier Houchardstatic 19515144b0fSOlivier Houchard#endif 19615144b0fSOlivier Houchardflag float64_is_nan( float64 a ) 19715144b0fSOlivier Houchard{ 19815144b0fSOlivier Houchard 19915144b0fSOlivier Houchard return ( LIT64( 0xFFE0000000000000 ) < 20015144b0fSOlivier Houchard (bits64) ( FLOAT64_DEMANGLE(a)<<1 ) ); 20115144b0fSOlivier Houchard 20215144b0fSOlivier Houchard} 20315144b0fSOlivier Houchard 20415144b0fSOlivier Houchard/* 20515144b0fSOlivier Houchard------------------------------------------------------------------------------- 20615144b0fSOlivier HouchardReturns 1 if the double-precision floating-point value `a' is a signaling 20715144b0fSOlivier HouchardNaN; otherwise returns 0. 20815144b0fSOlivier Houchard------------------------------------------------------------------------------- 20915144b0fSOlivier Houchard*/ 21015144b0fSOlivier Houchard#if defined(SOFTFLOAT_FOR_GCC) && !defined(SOFTFLOATSPARC64_FOR_GCC) 21115144b0fSOlivier Houchardstatic 21215144b0fSOlivier Houchard#endif 21315144b0fSOlivier Houchardflag float64_is_signaling_nan( float64 a ) 21415144b0fSOlivier Houchard{ 21515144b0fSOlivier Houchard 21615144b0fSOlivier Houchard return 21715144b0fSOlivier Houchard ( ( ( FLOAT64_DEMANGLE(a)>>51 ) & 0xFFF ) == 0xFFE ) 21815144b0fSOlivier Houchard && ( FLOAT64_DEMANGLE(a) & LIT64( 0x0007FFFFFFFFFFFF ) ); 21915144b0fSOlivier Houchard 22015144b0fSOlivier Houchard} 22115144b0fSOlivier Houchard 22215144b0fSOlivier Houchard/* 22315144b0fSOlivier Houchard------------------------------------------------------------------------------- 22415144b0fSOlivier HouchardReturns the result of converting the double-precision floating-point NaN 22515144b0fSOlivier Houchard`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 22615144b0fSOlivier Houchardexception is raised. 22715144b0fSOlivier Houchard------------------------------------------------------------------------------- 22815144b0fSOlivier Houchard*/ 22915144b0fSOlivier Houchardstatic commonNaNT float64ToCommonNaN( float64 a ) 23015144b0fSOlivier Houchard{ 23115144b0fSOlivier Houchard commonNaNT z; 23215144b0fSOlivier Houchard 23315144b0fSOlivier Houchard if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 23415144b0fSOlivier Houchard z.sign = FLOAT64_DEMANGLE(a)>>63; 23515144b0fSOlivier Houchard z.low = 0; 23615144b0fSOlivier Houchard z.high = FLOAT64_DEMANGLE(a)<<12; 23715144b0fSOlivier Houchard return z; 23815144b0fSOlivier Houchard 23915144b0fSOlivier Houchard} 24015144b0fSOlivier Houchard 24115144b0fSOlivier Houchard/* 24215144b0fSOlivier Houchard------------------------------------------------------------------------------- 24315144b0fSOlivier HouchardReturns the result of converting the canonical NaN `a' to the double- 24415144b0fSOlivier Houchardprecision floating-point format. 24515144b0fSOlivier Houchard------------------------------------------------------------------------------- 24615144b0fSOlivier Houchard*/ 24715144b0fSOlivier Houchardstatic float64 commonNaNToFloat64( commonNaNT a ) 24815144b0fSOlivier Houchard{ 24915144b0fSOlivier Houchard 25015144b0fSOlivier Houchard return FLOAT64_MANGLE( 25115144b0fSOlivier Houchard ( ( (bits64) a.sign )<<63 ) 25215144b0fSOlivier Houchard | LIT64( 0x7FF8000000000000 ) 25315144b0fSOlivier Houchard | ( a.high>>12 ) ); 25415144b0fSOlivier Houchard 25515144b0fSOlivier Houchard} 25615144b0fSOlivier Houchard 25715144b0fSOlivier Houchard/* 25815144b0fSOlivier Houchard------------------------------------------------------------------------------- 25915144b0fSOlivier HouchardTakes two double-precision floating-point values `a' and `b', one of which 26015144b0fSOlivier Houchardis a NaN, and returns the appropriate NaN result. If either `a' or `b' is a 26115144b0fSOlivier Houchardsignaling NaN, the invalid exception is raised. 26215144b0fSOlivier Houchard------------------------------------------------------------------------------- 26315144b0fSOlivier Houchard*/ 26415144b0fSOlivier Houchardstatic float64 propagateFloat64NaN( float64 a, float64 b ) 26515144b0fSOlivier Houchard{ 26615144b0fSOlivier Houchard flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 26715144b0fSOlivier Houchard 26815144b0fSOlivier Houchard aIsNaN = float64_is_nan( a ); 26915144b0fSOlivier Houchard aIsSignalingNaN = float64_is_signaling_nan( a ); 27015144b0fSOlivier Houchard bIsNaN = float64_is_nan( b ); 27115144b0fSOlivier Houchard bIsSignalingNaN = float64_is_signaling_nan( b ); 27215144b0fSOlivier Houchard a |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 )); 27315144b0fSOlivier Houchard b |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 )); 27415144b0fSOlivier Houchard if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 27515144b0fSOlivier Houchard if ( aIsNaN ) { 27615144b0fSOlivier Houchard return ( aIsSignalingNaN & bIsNaN ) ? b : a; 27715144b0fSOlivier Houchard } 27815144b0fSOlivier Houchard else { 27915144b0fSOlivier Houchard return b; 28015144b0fSOlivier Houchard } 28115144b0fSOlivier Houchard 28215144b0fSOlivier Houchard} 28315144b0fSOlivier Houchard 28415144b0fSOlivier Houchard#ifdef FLOATX80 28515144b0fSOlivier Houchard 28615144b0fSOlivier Houchard/* 28715144b0fSOlivier Houchard------------------------------------------------------------------------------- 28815144b0fSOlivier HouchardThe pattern for a default generated extended double-precision NaN. The 28915144b0fSOlivier Houchard`high' and `low' values hold the most- and least-significant bits, 29015144b0fSOlivier Houchardrespectively. 29115144b0fSOlivier Houchard------------------------------------------------------------------------------- 29215144b0fSOlivier Houchard*/ 29315144b0fSOlivier Houchard#define floatx80_default_nan_high 0xFFFF 29415144b0fSOlivier Houchard#define floatx80_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF ) 29515144b0fSOlivier Houchard 29615144b0fSOlivier Houchard/* 29715144b0fSOlivier Houchard------------------------------------------------------------------------------- 29815144b0fSOlivier HouchardReturns 1 if the extended double-precision floating-point value `a' is a 29915144b0fSOlivier HouchardNaN; otherwise returns 0. 30015144b0fSOlivier Houchard------------------------------------------------------------------------------- 30115144b0fSOlivier Houchard*/ 30215144b0fSOlivier Houchardflag floatx80_is_nan( floatx80 a ) 30315144b0fSOlivier Houchard{ 30415144b0fSOlivier Houchard 30515144b0fSOlivier Houchard return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 ); 30615144b0fSOlivier Houchard 30715144b0fSOlivier Houchard} 30815144b0fSOlivier Houchard 30915144b0fSOlivier Houchard/* 31015144b0fSOlivier Houchard------------------------------------------------------------------------------- 31115144b0fSOlivier HouchardReturns 1 if the extended double-precision floating-point value `a' is a 31215144b0fSOlivier Houchardsignaling NaN; otherwise returns 0. 31315144b0fSOlivier Houchard------------------------------------------------------------------------------- 31415144b0fSOlivier Houchard*/ 31515144b0fSOlivier Houchardflag floatx80_is_signaling_nan( floatx80 a ) 31615144b0fSOlivier Houchard{ 31715144b0fSOlivier Houchard bits64 aLow; 31815144b0fSOlivier Houchard 31915144b0fSOlivier Houchard aLow = a.low & ~ LIT64( 0x4000000000000000 ); 32015144b0fSOlivier Houchard return 32115144b0fSOlivier Houchard ( ( a.high & 0x7FFF ) == 0x7FFF ) 32215144b0fSOlivier Houchard && (bits64) ( aLow<<1 ) 32315144b0fSOlivier Houchard && ( a.low == aLow ); 32415144b0fSOlivier Houchard 32515144b0fSOlivier Houchard} 32615144b0fSOlivier Houchard 32715144b0fSOlivier Houchard/* 32815144b0fSOlivier Houchard------------------------------------------------------------------------------- 32915144b0fSOlivier HouchardReturns the result of converting the extended double-precision floating- 33015144b0fSOlivier Houchardpoint NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the 33115144b0fSOlivier Houchardinvalid exception is raised. 33215144b0fSOlivier Houchard------------------------------------------------------------------------------- 33315144b0fSOlivier Houchard*/ 33415144b0fSOlivier Houchardstatic commonNaNT floatx80ToCommonNaN( floatx80 a ) 33515144b0fSOlivier Houchard{ 33615144b0fSOlivier Houchard commonNaNT z; 33715144b0fSOlivier Houchard 33815144b0fSOlivier Houchard if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 33915144b0fSOlivier Houchard z.sign = a.high>>15; 34015144b0fSOlivier Houchard z.low = 0; 34115144b0fSOlivier Houchard z.high = a.low<<1; 34215144b0fSOlivier Houchard return z; 34315144b0fSOlivier Houchard 34415144b0fSOlivier Houchard} 34515144b0fSOlivier Houchard 34615144b0fSOlivier Houchard/* 34715144b0fSOlivier Houchard------------------------------------------------------------------------------- 34815144b0fSOlivier HouchardReturns the result of converting the canonical NaN `a' to the extended 34915144b0fSOlivier Houcharddouble-precision floating-point format. 35015144b0fSOlivier Houchard------------------------------------------------------------------------------- 35115144b0fSOlivier Houchard*/ 35215144b0fSOlivier Houchardstatic floatx80 commonNaNToFloatx80( commonNaNT a ) 35315144b0fSOlivier Houchard{ 35415144b0fSOlivier Houchard floatx80 z; 35515144b0fSOlivier Houchard 35615144b0fSOlivier Houchard z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 ); 35715144b0fSOlivier Houchard z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF; 35815144b0fSOlivier Houchard return z; 35915144b0fSOlivier Houchard 36015144b0fSOlivier Houchard} 36115144b0fSOlivier Houchard 36215144b0fSOlivier Houchard/* 36315144b0fSOlivier Houchard------------------------------------------------------------------------------- 36415144b0fSOlivier HouchardTakes two extended double-precision floating-point values `a' and `b', one 36515144b0fSOlivier Houchardof which is a NaN, and returns the appropriate NaN result. If either `a' or 36615144b0fSOlivier Houchard`b' is a signaling NaN, the invalid exception is raised. 36715144b0fSOlivier Houchard------------------------------------------------------------------------------- 36815144b0fSOlivier Houchard*/ 36915144b0fSOlivier Houchardstatic floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b ) 37015144b0fSOlivier Houchard{ 37115144b0fSOlivier Houchard flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 37215144b0fSOlivier Houchard 37315144b0fSOlivier Houchard aIsNaN = floatx80_is_nan( a ); 37415144b0fSOlivier Houchard aIsSignalingNaN = floatx80_is_signaling_nan( a ); 37515144b0fSOlivier Houchard bIsNaN = floatx80_is_nan( b ); 37615144b0fSOlivier Houchard bIsSignalingNaN = floatx80_is_signaling_nan( b ); 37715144b0fSOlivier Houchard a.low |= LIT64( 0xC000000000000000 ); 37815144b0fSOlivier Houchard b.low |= LIT64( 0xC000000000000000 ); 37915144b0fSOlivier Houchard if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 38015144b0fSOlivier Houchard if ( aIsNaN ) { 38115144b0fSOlivier Houchard return ( aIsSignalingNaN & bIsNaN ) ? b : a; 38215144b0fSOlivier Houchard } 38315144b0fSOlivier Houchard else { 38415144b0fSOlivier Houchard return b; 38515144b0fSOlivier Houchard } 38615144b0fSOlivier Houchard 38715144b0fSOlivier Houchard} 38815144b0fSOlivier Houchard 38915144b0fSOlivier Houchard#endif 39015144b0fSOlivier Houchard 39115144b0fSOlivier Houchard#ifdef FLOAT128 39215144b0fSOlivier Houchard 39315144b0fSOlivier Houchard/* 39415144b0fSOlivier Houchard------------------------------------------------------------------------------- 39515144b0fSOlivier HouchardThe pattern for a default generated quadruple-precision NaN. The `high' and 39615144b0fSOlivier Houchard`low' values hold the most- and least-significant bits, respectively. 39715144b0fSOlivier Houchard------------------------------------------------------------------------------- 39815144b0fSOlivier Houchard*/ 39915144b0fSOlivier Houchard#define float128_default_nan_high LIT64( 0xFFFFFFFFFFFFFFFF ) 40015144b0fSOlivier Houchard#define float128_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF ) 40115144b0fSOlivier Houchard 40215144b0fSOlivier Houchard/* 40315144b0fSOlivier Houchard------------------------------------------------------------------------------- 40415144b0fSOlivier HouchardReturns 1 if the quadruple-precision floating-point value `a' is a NaN; 40515144b0fSOlivier Houchardotherwise returns 0. 40615144b0fSOlivier Houchard------------------------------------------------------------------------------- 40715144b0fSOlivier Houchard*/ 40815144b0fSOlivier Houchardflag float128_is_nan( float128 a ) 40915144b0fSOlivier Houchard{ 41015144b0fSOlivier Houchard 41115144b0fSOlivier Houchard return 41215144b0fSOlivier Houchard ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) ) 41315144b0fSOlivier Houchard && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) ); 41415144b0fSOlivier Houchard 41515144b0fSOlivier Houchard} 41615144b0fSOlivier Houchard 41715144b0fSOlivier Houchard/* 41815144b0fSOlivier Houchard------------------------------------------------------------------------------- 41915144b0fSOlivier HouchardReturns 1 if the quadruple-precision floating-point value `a' is a 42015144b0fSOlivier Houchardsignaling NaN; otherwise returns 0. 42115144b0fSOlivier Houchard------------------------------------------------------------------------------- 42215144b0fSOlivier Houchard*/ 42315144b0fSOlivier Houchardflag float128_is_signaling_nan( float128 a ) 42415144b0fSOlivier Houchard{ 42515144b0fSOlivier Houchard 42615144b0fSOlivier Houchard return 42715144b0fSOlivier Houchard ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE ) 42815144b0fSOlivier Houchard && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) ); 42915144b0fSOlivier Houchard 43015144b0fSOlivier Houchard} 43115144b0fSOlivier Houchard 43215144b0fSOlivier Houchard/* 43315144b0fSOlivier Houchard------------------------------------------------------------------------------- 43415144b0fSOlivier HouchardReturns the result of converting the quadruple-precision floating-point NaN 43515144b0fSOlivier Houchard`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 43615144b0fSOlivier Houchardexception is raised. 43715144b0fSOlivier Houchard------------------------------------------------------------------------------- 43815144b0fSOlivier Houchard*/ 43915144b0fSOlivier Houchardstatic commonNaNT float128ToCommonNaN( float128 a ) 44015144b0fSOlivier Houchard{ 44115144b0fSOlivier Houchard commonNaNT z; 44215144b0fSOlivier Houchard 44315144b0fSOlivier Houchard if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 44415144b0fSOlivier Houchard z.sign = a.high>>63; 44515144b0fSOlivier Houchard shortShift128Left( a.high, a.low, 16, &z.high, &z.low ); 44615144b0fSOlivier Houchard return z; 44715144b0fSOlivier Houchard 44815144b0fSOlivier Houchard} 44915144b0fSOlivier Houchard 45015144b0fSOlivier Houchard/* 45115144b0fSOlivier Houchard------------------------------------------------------------------------------- 45215144b0fSOlivier HouchardReturns the result of converting the canonical NaN `a' to the quadruple- 45315144b0fSOlivier Houchardprecision floating-point format. 45415144b0fSOlivier Houchard------------------------------------------------------------------------------- 45515144b0fSOlivier Houchard*/ 45615144b0fSOlivier Houchardstatic float128 commonNaNToFloat128( commonNaNT a ) 45715144b0fSOlivier Houchard{ 45815144b0fSOlivier Houchard float128 z; 45915144b0fSOlivier Houchard 46015144b0fSOlivier Houchard shift128Right( a.high, a.low, 16, &z.high, &z.low ); 46115144b0fSOlivier Houchard z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 ); 46215144b0fSOlivier Houchard return z; 46315144b0fSOlivier Houchard 46415144b0fSOlivier Houchard} 46515144b0fSOlivier Houchard 46615144b0fSOlivier Houchard/* 46715144b0fSOlivier Houchard------------------------------------------------------------------------------- 46815144b0fSOlivier HouchardTakes two quadruple-precision floating-point values `a' and `b', one of 46915144b0fSOlivier Houchardwhich is a NaN, and returns the appropriate NaN result. If either `a' or 47015144b0fSOlivier Houchard`b' is a signaling NaN, the invalid exception is raised. 47115144b0fSOlivier Houchard------------------------------------------------------------------------------- 47215144b0fSOlivier Houchard*/ 47315144b0fSOlivier Houchardstatic float128 propagateFloat128NaN( float128 a, float128 b ) 47415144b0fSOlivier Houchard{ 47515144b0fSOlivier Houchard flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 47615144b0fSOlivier Houchard 47715144b0fSOlivier Houchard aIsNaN = float128_is_nan( a ); 47815144b0fSOlivier Houchard aIsSignalingNaN = float128_is_signaling_nan( a ); 47915144b0fSOlivier Houchard bIsNaN = float128_is_nan( b ); 48015144b0fSOlivier Houchard bIsSignalingNaN = float128_is_signaling_nan( b ); 48115144b0fSOlivier Houchard a.high |= LIT64( 0x0000800000000000 ); 48215144b0fSOlivier Houchard b.high |= LIT64( 0x0000800000000000 ); 48315144b0fSOlivier Houchard if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 48415144b0fSOlivier Houchard if ( aIsNaN ) { 48515144b0fSOlivier Houchard return ( aIsSignalingNaN & bIsNaN ) ? b : a; 48615144b0fSOlivier Houchard } 48715144b0fSOlivier Houchard else { 48815144b0fSOlivier Houchard return b; 48915144b0fSOlivier Houchard } 49015144b0fSOlivier Houchard 49115144b0fSOlivier Houchard} 49215144b0fSOlivier Houchard 49315144b0fSOlivier Houchard#endif 49415144b0fSOlivier Houchard 495