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