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