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