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