1*d874cce4Sray /* $OpenBSD: softfloat-specialize.h,v 1.3 2008/06/26 05:42:20 ray Exp $ */
2433075b6Spvalchev /* $NetBSD: softfloat-specialize.h,v 1.1 2001/04/26 03:10:47 ross Exp $ */
3433075b6Spvalchev
4433075b6Spvalchev /* This is a derivative work. */
5433075b6Spvalchev
6433075b6Spvalchev /*-
7433075b6Spvalchev * Copyright (c) 2001 The NetBSD Foundation, Inc.
8433075b6Spvalchev * All rights reserved.
9433075b6Spvalchev *
10433075b6Spvalchev * This code is derived from software contributed to The NetBSD Foundation
11433075b6Spvalchev * by Ross Harvey.
12433075b6Spvalchev *
13433075b6Spvalchev * Redistribution and use in source and binary forms, with or without
14433075b6Spvalchev * modification, are permitted provided that the following conditions
15433075b6Spvalchev * are met:
16433075b6Spvalchev * 1. Redistributions of source code must retain the above copyright
17433075b6Spvalchev * notice, this list of conditions and the following disclaimer.
18433075b6Spvalchev * 2. Redistributions in binary form must reproduce the above copyright
19433075b6Spvalchev * notice, this list of conditions and the following disclaimer in the
20433075b6Spvalchev * documentation and/or other materials provided with the distribution.
21433075b6Spvalchev *
22433075b6Spvalchev * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
23433075b6Spvalchev * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24433075b6Spvalchev * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25433075b6Spvalchev * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
26433075b6Spvalchev * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27433075b6Spvalchev * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28433075b6Spvalchev * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29433075b6Spvalchev * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30433075b6Spvalchev * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31433075b6Spvalchev * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32433075b6Spvalchev * POSSIBILITY OF SUCH DAMAGE.
33433075b6Spvalchev */
34433075b6Spvalchev
35433075b6Spvalchev /*
36433075b6Spvalchev ===============================================================================
37433075b6Spvalchev
38433075b6Spvalchev This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
39433075b6Spvalchev Arithmetic Package, Release 2a.
40433075b6Spvalchev
41433075b6Spvalchev Written by John R. Hauser. This work was made possible in part by the
42433075b6Spvalchev International Computer Science Institute, located at Suite 600, 1947 Center
43433075b6Spvalchev Street, Berkeley, California 94704. Funding was partially provided by the
44433075b6Spvalchev National Science Foundation under grant MIP-9311980. The original version
45433075b6Spvalchev of this code was written as part of a project to build a fixed-point vector
46433075b6Spvalchev processor in collaboration with the University of California at Berkeley,
47433075b6Spvalchev overseen by Profs. Nelson Morgan and John Wawrzynek. More information
48433075b6Spvalchev is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
49433075b6Spvalchev arithmetic/SoftFloat.html'.
50433075b6Spvalchev
51433075b6Spvalchev THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable
52433075b6Spvalchev effort has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT
53433075b6Spvalchev WILL AT TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS
54433075b6Spvalchev RESTRICTED TO PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL
55433075b6Spvalchev RESPONSIBILITY FOR ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM
56433075b6Spvalchev THEIR OWN USE OF THE SOFTWARE, AND WHO ALSO EFFECTIVELY INDEMNIFY
57433075b6Spvalchev (possibly via similar legal warning) JOHN HAUSER AND THE INTERNATIONAL
58433075b6Spvalchev COMPUTER SCIENCE INSTITUTE AGAINST ALL LOSSES, COSTS, OR OTHER PROBLEMS
59433075b6Spvalchev ARISING FROM THE USE OF THE SOFTWARE BY THEIR CUSTOMERS AND CLIENTS.
60433075b6Spvalchev
61433075b6Spvalchev Derivative works are acceptable, even for commercial purposes, so long as
62433075b6Spvalchev (1) they include prominent notice that the work is derivative, and (2) they
63433075b6Spvalchev include prominent notice akin to these four paragraphs for those parts of
64433075b6Spvalchev this code that are retained.
65433075b6Spvalchev
66433075b6Spvalchev ===============================================================================
67433075b6Spvalchev */
68433075b6Spvalchev
69433075b6Spvalchev /*
70433075b6Spvalchev -------------------------------------------------------------------------------
71433075b6Spvalchev Underflow tininess-detection mode, statically initialized to default value.
72433075b6Spvalchev -------------------------------------------------------------------------------
73433075b6Spvalchev */
74433075b6Spvalchev
75433075b6Spvalchev /* [ MP safe, does not change dynamically ] */
76433075b6Spvalchev int float_detect_tininess = float_tininess_after_rounding;
77433075b6Spvalchev
78433075b6Spvalchev /*
79433075b6Spvalchev -------------------------------------------------------------------------------
80433075b6Spvalchev Internal canonical NaN format.
81433075b6Spvalchev -------------------------------------------------------------------------------
82433075b6Spvalchev */
83433075b6Spvalchev typedef struct {
84433075b6Spvalchev flag sign;
85433075b6Spvalchev bits64 high, low;
86433075b6Spvalchev } commonNaNT;
87433075b6Spvalchev
88433075b6Spvalchev /*
89433075b6Spvalchev -------------------------------------------------------------------------------
90433075b6Spvalchev The pattern for a default generated single-precision NaN.
91433075b6Spvalchev -------------------------------------------------------------------------------
92433075b6Spvalchev */
93433075b6Spvalchev #define float32_default_nan 0xFFC00000
94433075b6Spvalchev
95433075b6Spvalchev /*
96433075b6Spvalchev -------------------------------------------------------------------------------
97433075b6Spvalchev Returns 1 if the single-precision floating-point value `a' is a NaN;
98433075b6Spvalchev otherwise returns 0.
99433075b6Spvalchev -------------------------------------------------------------------------------
100433075b6Spvalchev */
float32_is_nan(float32 a)101433075b6Spvalchev static flag float32_is_nan( float32 a )
102433075b6Spvalchev {
103433075b6Spvalchev
104433075b6Spvalchev return ( 0xFF000000 < (bits32) ( a<<1 ) );
105433075b6Spvalchev
106433075b6Spvalchev }
107433075b6Spvalchev
108433075b6Spvalchev /*
109433075b6Spvalchev -------------------------------------------------------------------------------
110433075b6Spvalchev Returns 1 if the single-precision floating-point value `a' is a signaling
111433075b6Spvalchev NaN; otherwise returns 0.
112433075b6Spvalchev -------------------------------------------------------------------------------
113433075b6Spvalchev */
float32_is_signaling_nan(float32 a)114433075b6Spvalchev flag float32_is_signaling_nan( float32 a )
115433075b6Spvalchev {
116433075b6Spvalchev
117433075b6Spvalchev return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
118433075b6Spvalchev
119433075b6Spvalchev }
120433075b6Spvalchev
121433075b6Spvalchev /*
122433075b6Spvalchev -------------------------------------------------------------------------------
123433075b6Spvalchev Returns the result of converting the single-precision floating-point NaN
124433075b6Spvalchev `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
125433075b6Spvalchev exception is raised.
126433075b6Spvalchev -------------------------------------------------------------------------------
127433075b6Spvalchev */
float32ToCommonNaN(float32 a)128433075b6Spvalchev static commonNaNT float32ToCommonNaN( float32 a )
129433075b6Spvalchev {
130433075b6Spvalchev commonNaNT z;
131433075b6Spvalchev
132433075b6Spvalchev if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
133433075b6Spvalchev z.sign = a>>31;
134433075b6Spvalchev z.low = 0;
135433075b6Spvalchev z.high = ( (bits64) a )<<41;
136433075b6Spvalchev return z;
137433075b6Spvalchev
138433075b6Spvalchev }
139433075b6Spvalchev
140433075b6Spvalchev /*
141433075b6Spvalchev -------------------------------------------------------------------------------
142433075b6Spvalchev Returns the result of converting the canonical NaN `a' to the single-
143433075b6Spvalchev precision floating-point format.
144433075b6Spvalchev -------------------------------------------------------------------------------
145433075b6Spvalchev */
commonNaNToFloat32(commonNaNT a)146433075b6Spvalchev static float32 commonNaNToFloat32( commonNaNT a )
147433075b6Spvalchev {
148433075b6Spvalchev
149433075b6Spvalchev return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 );
150433075b6Spvalchev
151433075b6Spvalchev }
152433075b6Spvalchev
153433075b6Spvalchev /*
154433075b6Spvalchev -------------------------------------------------------------------------------
155433075b6Spvalchev Takes two single-precision floating-point values `a' and `b', one of which
156433075b6Spvalchev is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
157433075b6Spvalchev signaling NaN, the invalid exception is raised.
158433075b6Spvalchev -------------------------------------------------------------------------------
159433075b6Spvalchev */
propagateFloat32NaN(float32 a,float32 b)160433075b6Spvalchev static float32 propagateFloat32NaN( float32 a, float32 b )
161433075b6Spvalchev {
162433075b6Spvalchev flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
163433075b6Spvalchev
164433075b6Spvalchev aIsNaN = float32_is_nan( a );
165433075b6Spvalchev aIsSignalingNaN = float32_is_signaling_nan( a );
166433075b6Spvalchev bIsNaN = float32_is_nan( b );
167433075b6Spvalchev bIsSignalingNaN = float32_is_signaling_nan( b );
168433075b6Spvalchev a |= 0x00400000;
169433075b6Spvalchev b |= 0x00400000;
170433075b6Spvalchev if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
171433075b6Spvalchev if ( aIsSignalingNaN ) {
172433075b6Spvalchev if ( bIsSignalingNaN ) goto returnLargerSignificand;
173433075b6Spvalchev return bIsNaN ? b : a;
174433075b6Spvalchev }
175433075b6Spvalchev else if ( aIsNaN ) {
176433075b6Spvalchev if ( bIsSignalingNaN | ! bIsNaN ) return a;
177433075b6Spvalchev returnLargerSignificand:
178433075b6Spvalchev if ( (bits32) ( a<<1 ) < (bits32) ( b<<1 ) ) return b;
179433075b6Spvalchev if ( (bits32) ( b<<1 ) < (bits32) ( a<<1 ) ) return a;
180433075b6Spvalchev return ( a < b ) ? a : b;
181433075b6Spvalchev }
182433075b6Spvalchev else {
183433075b6Spvalchev return b;
184433075b6Spvalchev }
185433075b6Spvalchev
186433075b6Spvalchev }
187433075b6Spvalchev
188433075b6Spvalchev
189433075b6Spvalchev /*
190433075b6Spvalchev -------------------------------------------------------------------------------
191433075b6Spvalchev Returns the result of converting the double-precision floating-point NaN
192433075b6Spvalchev `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
193433075b6Spvalchev exception is raised.
194433075b6Spvalchev -------------------------------------------------------------------------------
195433075b6Spvalchev */
float64ToCommonNaN(float64 a)196433075b6Spvalchev static commonNaNT float64ToCommonNaN( float64 a )
197433075b6Spvalchev {
198433075b6Spvalchev commonNaNT z;
199433075b6Spvalchev
200433075b6Spvalchev if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
201433075b6Spvalchev z.sign = a>>63;
202433075b6Spvalchev z.low = 0;
203433075b6Spvalchev z.high = a<<12;
204433075b6Spvalchev return z;
205433075b6Spvalchev
206433075b6Spvalchev }
207433075b6Spvalchev
208433075b6Spvalchev /*
209433075b6Spvalchev -------------------------------------------------------------------------------
210433075b6Spvalchev Returns the result of converting the canonical NaN `a' to the double-
211433075b6Spvalchev precision floating-point format.
212433075b6Spvalchev -------------------------------------------------------------------------------
213433075b6Spvalchev */
commonNaNToFloat64(commonNaNT a)214433075b6Spvalchev static float64 commonNaNToFloat64( commonNaNT a )
215433075b6Spvalchev {
216433075b6Spvalchev
217433075b6Spvalchev return
218433075b6Spvalchev ( ( (bits64) a.sign )<<63 )
219433075b6Spvalchev | LIT64( 0x7FF8000000000000 )
220433075b6Spvalchev | ( a.high>>12 );
221433075b6Spvalchev
222433075b6Spvalchev }
223433075b6Spvalchev
224433075b6Spvalchev /*
225433075b6Spvalchev -------------------------------------------------------------------------------
226433075b6Spvalchev Takes two double-precision floating-point values `a' and `b', one of which
227433075b6Spvalchev is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
228433075b6Spvalchev signaling NaN, the invalid exception is raised.
229433075b6Spvalchev -------------------------------------------------------------------------------
230433075b6Spvalchev */
propagateFloat64NaN(float64 a,float64 b)231433075b6Spvalchev static float64 propagateFloat64NaN( float64 a, float64 b )
232433075b6Spvalchev {
233433075b6Spvalchev flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
234433075b6Spvalchev
235433075b6Spvalchev aIsNaN = float64_is_nan( a );
236433075b6Spvalchev aIsSignalingNaN = float64_is_signaling_nan( a );
237433075b6Spvalchev bIsNaN = float64_is_nan( b );
238433075b6Spvalchev bIsSignalingNaN = float64_is_signaling_nan( b );
239433075b6Spvalchev a |= LIT64( 0x0008000000000000 );
240433075b6Spvalchev b |= LIT64( 0x0008000000000000 );
241433075b6Spvalchev if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
242433075b6Spvalchev if ( aIsSignalingNaN ) {
243433075b6Spvalchev if ( bIsSignalingNaN ) goto returnLargerSignificand;
244433075b6Spvalchev return bIsNaN ? b : a;
245433075b6Spvalchev }
246433075b6Spvalchev else if ( aIsNaN ) {
247433075b6Spvalchev if ( bIsSignalingNaN | ! bIsNaN ) return a;
248433075b6Spvalchev returnLargerSignificand:
249433075b6Spvalchev if ( (bits64) ( a<<1 ) < (bits64) ( b<<1 ) ) return b;
250433075b6Spvalchev if ( (bits64) ( b<<1 ) < (bits64) ( a<<1 ) ) return a;
251433075b6Spvalchev return ( a < b ) ? a : b;
252433075b6Spvalchev }
253433075b6Spvalchev else {
254433075b6Spvalchev return b;
255433075b6Spvalchev }
256433075b6Spvalchev
257433075b6Spvalchev }
258433075b6Spvalchev
259433075b6Spvalchev #ifdef FLOATX80
260433075b6Spvalchev
261433075b6Spvalchev /*
262433075b6Spvalchev -------------------------------------------------------------------------------
263433075b6Spvalchev The pattern for a default generated extended double-precision NaN. The
264433075b6Spvalchev `high' and `low' values hold the most- and least-significant bits,
265433075b6Spvalchev respectively.
266433075b6Spvalchev -------------------------------------------------------------------------------
267433075b6Spvalchev */
268433075b6Spvalchev #define floatx80_default_nan_high 0xFFFF
269433075b6Spvalchev #define floatx80_default_nan_low LIT64( 0xC000000000000000 )
270433075b6Spvalchev
271433075b6Spvalchev /*
272433075b6Spvalchev -------------------------------------------------------------------------------
273433075b6Spvalchev Returns 1 if the extended double-precision floating-point value `a' is a
274433075b6Spvalchev NaN; otherwise returns 0.
275433075b6Spvalchev -------------------------------------------------------------------------------
276433075b6Spvalchev */
floatx80_is_nan(floatx80 a)277433075b6Spvalchev static flag floatx80_is_nan( floatx80 a )
278433075b6Spvalchev {
279433075b6Spvalchev
280433075b6Spvalchev return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
281433075b6Spvalchev
282433075b6Spvalchev }
283433075b6Spvalchev
284433075b6Spvalchev /*
285433075b6Spvalchev -------------------------------------------------------------------------------
286433075b6Spvalchev Returns 1 if the extended double-precision floating-point value `a' is a
287433075b6Spvalchev signaling NaN; otherwise returns 0.
288433075b6Spvalchev -------------------------------------------------------------------------------
289433075b6Spvalchev */
floatx80_is_signaling_nan(floatx80 a)290433075b6Spvalchev flag floatx80_is_signaling_nan( floatx80 a )
291433075b6Spvalchev {
292433075b6Spvalchev bits64 aLow;
293433075b6Spvalchev
294433075b6Spvalchev aLow = a.low & ~ LIT64( 0x4000000000000000 );
295433075b6Spvalchev return
296433075b6Spvalchev ( ( a.high & 0x7FFF ) == 0x7FFF )
297433075b6Spvalchev && (bits64) ( aLow<<1 )
298433075b6Spvalchev && ( a.low == aLow );
299433075b6Spvalchev
300433075b6Spvalchev }
301433075b6Spvalchev
302433075b6Spvalchev /*
303433075b6Spvalchev -------------------------------------------------------------------------------
304433075b6Spvalchev Returns the result of converting the extended double-precision floating-
305433075b6Spvalchev point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the
306433075b6Spvalchev invalid exception is raised.
307433075b6Spvalchev -------------------------------------------------------------------------------
308433075b6Spvalchev */
floatx80ToCommonNaN(floatx80 a)309433075b6Spvalchev static commonNaNT floatx80ToCommonNaN( floatx80 a )
310433075b6Spvalchev {
311433075b6Spvalchev commonNaNT z;
312433075b6Spvalchev
313433075b6Spvalchev if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
314433075b6Spvalchev z.sign = a.high>>15;
315433075b6Spvalchev z.low = 0;
316433075b6Spvalchev z.high = a.low<<1;
317433075b6Spvalchev return z;
318433075b6Spvalchev
319433075b6Spvalchev }
320433075b6Spvalchev
321433075b6Spvalchev /*
322433075b6Spvalchev -------------------------------------------------------------------------------
323433075b6Spvalchev Returns the result of converting the canonical NaN `a' to the extended
324433075b6Spvalchev double-precision floating-point format.
325433075b6Spvalchev -------------------------------------------------------------------------------
326433075b6Spvalchev */
commonNaNToFloatx80(commonNaNT a)327433075b6Spvalchev static floatx80 commonNaNToFloatx80( commonNaNT a )
328433075b6Spvalchev {
329433075b6Spvalchev floatx80 z;
330433075b6Spvalchev
331433075b6Spvalchev z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
332433075b6Spvalchev z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
333433075b6Spvalchev return z;
334433075b6Spvalchev
335433075b6Spvalchev }
336433075b6Spvalchev
337433075b6Spvalchev /*
338433075b6Spvalchev -------------------------------------------------------------------------------
339433075b6Spvalchev Takes two extended double-precision floating-point values `a' and `b', one
340433075b6Spvalchev of which is a NaN, and returns the appropriate NaN result. If either `a' or
341433075b6Spvalchev `b' is a signaling NaN, the invalid exception is raised.
342433075b6Spvalchev -------------------------------------------------------------------------------
343433075b6Spvalchev */
propagateFloatx80NaN(floatx80 a,floatx80 b)344433075b6Spvalchev static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b )
345433075b6Spvalchev {
346433075b6Spvalchev flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
347433075b6Spvalchev
348433075b6Spvalchev aIsNaN = floatx80_is_nan( a );
349433075b6Spvalchev aIsSignalingNaN = floatx80_is_signaling_nan( a );
350433075b6Spvalchev bIsNaN = floatx80_is_nan( b );
351433075b6Spvalchev bIsSignalingNaN = floatx80_is_signaling_nan( b );
352433075b6Spvalchev a.low |= LIT64( 0xC000000000000000 );
353433075b6Spvalchev b.low |= LIT64( 0xC000000000000000 );
354433075b6Spvalchev if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
355433075b6Spvalchev if ( aIsSignalingNaN ) {
356433075b6Spvalchev if ( bIsSignalingNaN ) goto returnLargerSignificand;
357433075b6Spvalchev return bIsNaN ? b : a;
358433075b6Spvalchev }
359433075b6Spvalchev else if ( aIsNaN ) {
360433075b6Spvalchev if ( bIsSignalingNaN | ! bIsNaN ) return a;
361433075b6Spvalchev returnLargerSignificand:
362433075b6Spvalchev if ( a.low < b.low ) return b;
363433075b6Spvalchev if ( b.low < a.low ) return a;
364433075b6Spvalchev return ( a.high < b.high ) ? a : b;
365433075b6Spvalchev }
366433075b6Spvalchev else {
367433075b6Spvalchev return b;
368433075b6Spvalchev }
369433075b6Spvalchev
370433075b6Spvalchev }
371433075b6Spvalchev
372433075b6Spvalchev #endif
373433075b6Spvalchev
374433075b6Spvalchev #ifdef FLOAT128
375433075b6Spvalchev
376433075b6Spvalchev /*
377433075b6Spvalchev -------------------------------------------------------------------------------
378433075b6Spvalchev The pattern for a default generated quadruple-precision NaN. The `high' and
379433075b6Spvalchev `low' values hold the most- and least-significant bits, respectively.
380433075b6Spvalchev -------------------------------------------------------------------------------
381433075b6Spvalchev */
382433075b6Spvalchev #define float128_default_nan_high LIT64( 0xFFFF800000000000 )
383433075b6Spvalchev #define float128_default_nan_low LIT64( 0x0000000000000000 )
384433075b6Spvalchev
385433075b6Spvalchev /*
386433075b6Spvalchev -------------------------------------------------------------------------------
387433075b6Spvalchev Returns 1 if the quadruple-precision floating-point value `a' is a NaN;
388433075b6Spvalchev otherwise returns 0.
389433075b6Spvalchev -------------------------------------------------------------------------------
390433075b6Spvalchev */
float128_is_nan(float128 a)391433075b6Spvalchev flag float128_is_nan( float128 a )
392433075b6Spvalchev {
393433075b6Spvalchev
394433075b6Spvalchev return
395433075b6Spvalchev ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
396433075b6Spvalchev && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
397433075b6Spvalchev
398433075b6Spvalchev }
399433075b6Spvalchev
400433075b6Spvalchev /*
401433075b6Spvalchev -------------------------------------------------------------------------------
402433075b6Spvalchev Returns 1 if the quadruple-precision floating-point value `a' is a
403433075b6Spvalchev signaling NaN; otherwise returns 0.
404433075b6Spvalchev -------------------------------------------------------------------------------
405433075b6Spvalchev */
float128_is_signaling_nan(float128 a)406433075b6Spvalchev flag float128_is_signaling_nan( float128 a )
407433075b6Spvalchev {
408433075b6Spvalchev
409433075b6Spvalchev return
410433075b6Spvalchev ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
411433075b6Spvalchev && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
412433075b6Spvalchev
413433075b6Spvalchev }
414433075b6Spvalchev
415433075b6Spvalchev /*
416433075b6Spvalchev -------------------------------------------------------------------------------
417433075b6Spvalchev Returns the result of converting the quadruple-precision floating-point NaN
418433075b6Spvalchev `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
419433075b6Spvalchev exception is raised.
420433075b6Spvalchev -------------------------------------------------------------------------------
421433075b6Spvalchev */
float128ToCommonNaN(float128 a)422433075b6Spvalchev static commonNaNT float128ToCommonNaN( float128 a )
423433075b6Spvalchev {
424433075b6Spvalchev commonNaNT z;
425433075b6Spvalchev
426433075b6Spvalchev if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
427433075b6Spvalchev z.sign = a.high>>63;
428433075b6Spvalchev shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
429433075b6Spvalchev return z;
430433075b6Spvalchev
431433075b6Spvalchev }
432433075b6Spvalchev
433433075b6Spvalchev /*
434433075b6Spvalchev -------------------------------------------------------------------------------
435433075b6Spvalchev Returns the result of converting the canonical NaN `a' to the quadruple-
436433075b6Spvalchev precision floating-point format.
437433075b6Spvalchev -------------------------------------------------------------------------------
438433075b6Spvalchev */
commonNaNToFloat128(commonNaNT a)439433075b6Spvalchev static float128 commonNaNToFloat128( commonNaNT a )
440433075b6Spvalchev {
441433075b6Spvalchev float128 z;
442433075b6Spvalchev
443433075b6Spvalchev shift128Right( a.high, a.low, 16, &z.high, &z.low );
444433075b6Spvalchev z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 );
445433075b6Spvalchev return z;
446433075b6Spvalchev
447433075b6Spvalchev }
448433075b6Spvalchev
449433075b6Spvalchev /*
450433075b6Spvalchev -------------------------------------------------------------------------------
451433075b6Spvalchev Takes two quadruple-precision floating-point values `a' and `b', one of
452433075b6Spvalchev which is a NaN, and returns the appropriate NaN result. If either `a' or
453433075b6Spvalchev `b' is a signaling NaN, the invalid exception is raised.
454433075b6Spvalchev -------------------------------------------------------------------------------
455433075b6Spvalchev */
propagateFloat128NaN(float128 a,float128 b)456433075b6Spvalchev static float128 propagateFloat128NaN( float128 a, float128 b )
457433075b6Spvalchev {
458433075b6Spvalchev flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
459433075b6Spvalchev
460433075b6Spvalchev aIsNaN = float128_is_nan( a );
461433075b6Spvalchev aIsSignalingNaN = float128_is_signaling_nan( a );
462433075b6Spvalchev bIsNaN = float128_is_nan( b );
463433075b6Spvalchev bIsSignalingNaN = float128_is_signaling_nan( b );
464433075b6Spvalchev a.high |= LIT64( 0x0000800000000000 );
465433075b6Spvalchev b.high |= LIT64( 0x0000800000000000 );
466433075b6Spvalchev if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
467433075b6Spvalchev if ( aIsSignalingNaN ) {
468433075b6Spvalchev if ( bIsSignalingNaN ) goto returnLargerSignificand;
469433075b6Spvalchev return bIsNaN ? b : a;
470433075b6Spvalchev }
471433075b6Spvalchev else if ( aIsNaN ) {
472433075b6Spvalchev if ( bIsSignalingNaN | ! bIsNaN ) return a;
473433075b6Spvalchev returnLargerSignificand:
474433075b6Spvalchev if ( lt128( a.high<<1, a.low, b.high<<1, b.low ) ) return b;
475433075b6Spvalchev if ( lt128( b.high<<1, b.low, a.high<<1, a.low ) ) return a;
476433075b6Spvalchev return ( a.high < b.high ) ? a : b;
477433075b6Spvalchev }
478433075b6Spvalchev else {
479433075b6Spvalchev return b;
480433075b6Spvalchev }
481433075b6Spvalchev
482433075b6Spvalchev }
483433075b6Spvalchev
484433075b6Spvalchev #endif
485