xref: /netbsd-src/sys/lib/libkern/softfloat-specialize.h (revision e450f2e45d724b0ec51c4cff35a6f0592db866ac)
1*e450f2e4Sthorpej /* $NetBSD: softfloat-specialize.h,v 1.3 2020/09/02 03:41:56 thorpej Exp $ */
22df695b1Sross 
32df695b1Sross /* This is a derivative work. */
42df695b1Sross 
52df695b1Sross /*-
62df695b1Sross  * Copyright (c) 2001 The NetBSD Foundation, Inc.
72df695b1Sross  * All rights reserved.
82df695b1Sross  *
92df695b1Sross  * This code is derived from software contributed to The NetBSD Foundation
102df695b1Sross  * by Ross Harvey.
112df695b1Sross  *
122df695b1Sross  * Redistribution and use in source and binary forms, with or without
132df695b1Sross  * modification, are permitted provided that the following conditions
142df695b1Sross  * are met:
152df695b1Sross  * 1. Redistributions of source code must retain the above copyright
162df695b1Sross  *    notice, this list of conditions and the following disclaimer.
172df695b1Sross  * 2. Redistributions in binary form must reproduce the above copyright
182df695b1Sross  *    notice, this list of conditions and the following disclaimer in the
192df695b1Sross  *    documentation and/or other materials provided with the distribution.
202df695b1Sross  *
212df695b1Sross  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
222df695b1Sross  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
232df695b1Sross  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
242df695b1Sross  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
252df695b1Sross  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
262df695b1Sross  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
272df695b1Sross  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
282df695b1Sross  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
292df695b1Sross  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
302df695b1Sross  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
312df695b1Sross  * POSSIBILITY OF SUCH DAMAGE.
322df695b1Sross  */
332df695b1Sross 
34*e450f2e4Sthorpej /*============================================================================
352df695b1Sross 
36*e450f2e4Sthorpej This C source fragment is part of the Berkeley SoftFloat IEEE Floating-Point
37*e450f2e4Sthorpej Arithmetic Package, Release 2c, by John R. Hauser.
382df695b1Sross 
39*e450f2e4Sthorpej THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort has
40*e450f2e4Sthorpej been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
41*e450f2e4Sthorpej RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
42*e450f2e4Sthorpej AND ORGANIZATIONS WHO CAN AND WILL TOLERATE ALL LOSSES, COSTS, OR OTHER
43*e450f2e4Sthorpej PROBLEMS THEY INCUR DUE TO THE SOFTWARE WITHOUT RECOMPENSE FROM JOHN HAUSER OR
44*e450f2e4Sthorpej THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE, AND WHO FURTHERMORE EFFECTIVELY
45*e450f2e4Sthorpej INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE
46*e450f2e4Sthorpej (possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR OTHER
47*e450f2e4Sthorpej PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE, OR
48*e450f2e4Sthorpej INCURRED BY ANYONE DUE TO A DERIVATIVE WORK THEY CREATE USING ANY PART OF THE
49*e450f2e4Sthorpej SOFTWARE.
502df695b1Sross 
51*e450f2e4Sthorpej Derivative works require also that (1) the source code for the derivative work
52*e450f2e4Sthorpej includes prominent notice that the work is derivative, and (2) the source code
53*e450f2e4Sthorpej includes prominent notice of these three paragraphs for those parts of this
54*e450f2e4Sthorpej code that are retained.
552df695b1Sross 
56*e450f2e4Sthorpej =============================================================================*/
572df695b1Sross 
58*e450f2e4Sthorpej /*----------------------------------------------------------------------------
59*e450f2e4Sthorpej | Underflow tininess-detection mode, statically initialized to default value.
60*e450f2e4Sthorpej | (The declaration in `softfloat.h' must match the `int8' type here.)
61*e450f2e4Sthorpej *----------------------------------------------------------------------------*/
622df695b1Sross /* [ MP safe, does not change dynamically ] */
632df695b1Sross int float_detect_tininess = float_tininess_after_rounding;
642df695b1Sross 
65*e450f2e4Sthorpej /*----------------------------------------------------------------------------
66*e450f2e4Sthorpej | Internal canonical NaN format.
67*e450f2e4Sthorpej *----------------------------------------------------------------------------*/
682df695b1Sross typedef struct {
692df695b1Sross     flag sign;
702df695b1Sross     bits64 high, low;
712df695b1Sross } commonNaNT;
722df695b1Sross 
73*e450f2e4Sthorpej /*----------------------------------------------------------------------------
74*e450f2e4Sthorpej | The pattern for a default generated single-precision NaN.
75*e450f2e4Sthorpej *----------------------------------------------------------------------------*/
762df695b1Sross #define float32_default_nan 0xFFC00000
772df695b1Sross 
78*e450f2e4Sthorpej /*----------------------------------------------------------------------------
79*e450f2e4Sthorpej | Returns 1 if the single-precision floating-point value `a' is a NaN;
80*e450f2e4Sthorpej | otherwise returns 0.
81*e450f2e4Sthorpej *----------------------------------------------------------------------------*/
82*e450f2e4Sthorpej 
float32_is_nan(float32 a)832df695b1Sross static flag float32_is_nan( float32 a )
842df695b1Sross {
852df695b1Sross 
862df695b1Sross     return ( 0xFF000000 < (bits32) ( a<<1 ) );
872df695b1Sross 
882df695b1Sross }
892df695b1Sross 
90*e450f2e4Sthorpej /*----------------------------------------------------------------------------
91*e450f2e4Sthorpej | Returns 1 if the single-precision floating-point value `a' is a signaling
92*e450f2e4Sthorpej | NaN; otherwise returns 0.
93*e450f2e4Sthorpej *----------------------------------------------------------------------------*/
94*e450f2e4Sthorpej 
float32_is_signaling_nan(float32 a)952df695b1Sross flag float32_is_signaling_nan( float32 a )
962df695b1Sross {
972df695b1Sross 
982df695b1Sross     return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
992df695b1Sross 
1002df695b1Sross }
1012df695b1Sross 
102*e450f2e4Sthorpej /*----------------------------------------------------------------------------
103*e450f2e4Sthorpej | Returns the result of converting the single-precision floating-point NaN
104*e450f2e4Sthorpej | `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
105*e450f2e4Sthorpej | exception is raised.
106*e450f2e4Sthorpej *----------------------------------------------------------------------------*/
107*e450f2e4Sthorpej 
float32ToCommonNaN(float32 a)1082df695b1Sross static commonNaNT float32ToCommonNaN( float32 a )
1092df695b1Sross {
1102df695b1Sross     commonNaNT z;
1112df695b1Sross 
1122df695b1Sross     if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
1132df695b1Sross     z.sign = a>>31;
1142df695b1Sross     z.low = 0;
1152df695b1Sross     z.high = ( (bits64) a )<<41;
1162df695b1Sross     return z;
1172df695b1Sross 
1182df695b1Sross }
1192df695b1Sross 
120*e450f2e4Sthorpej /*----------------------------------------------------------------------------
121*e450f2e4Sthorpej | Returns the result of converting the canonical NaN `a' to the single-
122*e450f2e4Sthorpej | precision floating-point format.
123*e450f2e4Sthorpej *----------------------------------------------------------------------------*/
124*e450f2e4Sthorpej 
commonNaNToFloat32(commonNaNT a)1252df695b1Sross static float32 commonNaNToFloat32( commonNaNT a )
1262df695b1Sross {
1272df695b1Sross 
1282df695b1Sross     return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 );
1292df695b1Sross 
1302df695b1Sross }
1312df695b1Sross 
132*e450f2e4Sthorpej /*----------------------------------------------------------------------------
133*e450f2e4Sthorpej | Takes two single-precision floating-point values `a' and `b', one of which
134*e450f2e4Sthorpej | is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
135*e450f2e4Sthorpej | signaling NaN, the invalid exception is raised.
136*e450f2e4Sthorpej *----------------------------------------------------------------------------*/
137*e450f2e4Sthorpej 
propagateFloat32NaN(float32 a,float32 b)1382df695b1Sross static float32 propagateFloat32NaN( float32 a, float32 b )
1392df695b1Sross {
1402df695b1Sross     flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
1412df695b1Sross 
1422df695b1Sross     aIsNaN = float32_is_nan( a );
1432df695b1Sross     aIsSignalingNaN = float32_is_signaling_nan( a );
1442df695b1Sross     bIsNaN = float32_is_nan( b );
1452df695b1Sross     bIsSignalingNaN = float32_is_signaling_nan( b );
1462df695b1Sross     a |= 0x00400000;
1472df695b1Sross     b |= 0x00400000;
1482df695b1Sross     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
1492df695b1Sross     if ( aIsSignalingNaN ) {
1502df695b1Sross         if ( bIsSignalingNaN ) goto returnLargerSignificand;
1512df695b1Sross         return bIsNaN ? b : a;
1522df695b1Sross     }
1532df695b1Sross     else if ( aIsNaN ) {
1542df695b1Sross         if ( bIsSignalingNaN | ! bIsNaN ) return a;
1552df695b1Sross  returnLargerSignificand:
1562df695b1Sross         if ( (bits32) ( a<<1 ) < (bits32) ( b<<1 ) ) return b;
1572df695b1Sross         if ( (bits32) ( b<<1 ) < (bits32) ( a<<1 ) ) return a;
1582df695b1Sross         return ( a < b ) ? a : b;
1592df695b1Sross     }
1602df695b1Sross     else {
1612df695b1Sross         return b;
1622df695b1Sross     }
1632df695b1Sross 
1642df695b1Sross }
1652df695b1Sross 
1662df695b1Sross /*
167*e450f2e4Sthorpej  * float64_default_nan, float64_is_nan(), float64_is_signaling_nan()
168*e450f2e4Sthorpej  * have moved to softfloat.h.
1692df695b1Sross  */
170*e450f2e4Sthorpej 
171*e450f2e4Sthorpej /*----------------------------------------------------------------------------
172*e450f2e4Sthorpej | Returns the result of converting the double-precision floating-point NaN
173*e450f2e4Sthorpej | `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
174*e450f2e4Sthorpej | exception is raised.
175*e450f2e4Sthorpej *----------------------------------------------------------------------------*/
176*e450f2e4Sthorpej 
float64ToCommonNaN(float64 a)1772df695b1Sross static commonNaNT float64ToCommonNaN( float64 a )
1782df695b1Sross {
1792df695b1Sross     commonNaNT z;
1802df695b1Sross 
1812df695b1Sross     if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
1822df695b1Sross     z.sign = a>>63;
1832df695b1Sross     z.low = 0;
1842df695b1Sross     z.high = a<<12;
1852df695b1Sross     return z;
1862df695b1Sross 
1872df695b1Sross }
1882df695b1Sross 
189*e450f2e4Sthorpej /*----------------------------------------------------------------------------
190*e450f2e4Sthorpej | Returns the result of converting the canonical NaN `a' to the double-
191*e450f2e4Sthorpej | precision floating-point format.
192*e450f2e4Sthorpej *----------------------------------------------------------------------------*/
193*e450f2e4Sthorpej 
commonNaNToFloat64(commonNaNT a)1942df695b1Sross static float64 commonNaNToFloat64( commonNaNT a )
1952df695b1Sross {
1962df695b1Sross 
1972df695b1Sross     return
1982df695b1Sross           ( ( (bits64) a.sign )<<63 )
1992df695b1Sross         | LIT64( 0x7FF8000000000000 )
2002df695b1Sross         | ( a.high>>12 );
2012df695b1Sross 
2022df695b1Sross }
2032df695b1Sross 
204*e450f2e4Sthorpej /*----------------------------------------------------------------------------
205*e450f2e4Sthorpej | Takes two double-precision floating-point values `a' and `b', one of which
206*e450f2e4Sthorpej | is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
207*e450f2e4Sthorpej | signaling NaN, the invalid exception is raised.
208*e450f2e4Sthorpej *----------------------------------------------------------------------------*/
209*e450f2e4Sthorpej 
propagateFloat64NaN(float64 a,float64 b)2102df695b1Sross static float64 propagateFloat64NaN( float64 a, float64 b )
2112df695b1Sross {
2122df695b1Sross     flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
2132df695b1Sross 
2142df695b1Sross     aIsNaN = float64_is_nan( a );
2152df695b1Sross     aIsSignalingNaN = float64_is_signaling_nan( a );
2162df695b1Sross     bIsNaN = float64_is_nan( b );
2172df695b1Sross     bIsSignalingNaN = float64_is_signaling_nan( b );
2182df695b1Sross     a |= LIT64( 0x0008000000000000 );
2192df695b1Sross     b |= LIT64( 0x0008000000000000 );
2202df695b1Sross     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
2212df695b1Sross     if ( aIsSignalingNaN ) {
2222df695b1Sross         if ( bIsSignalingNaN ) goto returnLargerSignificand;
2232df695b1Sross         return bIsNaN ? b : a;
2242df695b1Sross     }
2252df695b1Sross     else if ( aIsNaN ) {
2262df695b1Sross         if ( bIsSignalingNaN | ! bIsNaN ) return a;
2272df695b1Sross  returnLargerSignificand:
2282df695b1Sross         if ( (bits64) ( a<<1 ) < (bits64) ( b<<1 ) ) return b;
2292df695b1Sross         if ( (bits64) ( b<<1 ) < (bits64) ( a<<1 ) ) return a;
2302df695b1Sross         return ( a < b ) ? a : b;
2312df695b1Sross     }
2322df695b1Sross     else {
2332df695b1Sross         return b;
2342df695b1Sross     }
2352df695b1Sross 
2362df695b1Sross }
2372df695b1Sross 
2382df695b1Sross #ifdef FLOATX80
2392df695b1Sross 
240*e450f2e4Sthorpej /*----------------------------------------------------------------------------
241*e450f2e4Sthorpej | The pattern for a default generated double-extended-precision NaN.
242*e450f2e4Sthorpej | The `high' and `low' values hold the most- and least-significant bits,
243*e450f2e4Sthorpej | respectively.
244*e450f2e4Sthorpej *----------------------------------------------------------------------------*/
2452df695b1Sross #define floatx80_default_nan_high 0xFFFF
2462df695b1Sross #define floatx80_default_nan_low  LIT64( 0xC000000000000000 )
2472df695b1Sross 
248*e450f2e4Sthorpej /*----------------------------------------------------------------------------
249*e450f2e4Sthorpej | Returns 1 if the double-extended-precision floating-point value `a' is a
250*e450f2e4Sthorpej | NaN; otherwise returns 0.
251*e450f2e4Sthorpej *----------------------------------------------------------------------------*/
252*e450f2e4Sthorpej 
floatx80_is_nan(floatx80 a)2532df695b1Sross static flag floatx80_is_nan( floatx80 a )
2542df695b1Sross {
2552df695b1Sross 
2562df695b1Sross     return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
2572df695b1Sross 
2582df695b1Sross }
2592df695b1Sross 
260*e450f2e4Sthorpej /*----------------------------------------------------------------------------
261*e450f2e4Sthorpej | Returns 1 if the double-extended-precision floating-point value `a' is a
262*e450f2e4Sthorpej | signaling NaN; otherwise returns 0.
263*e450f2e4Sthorpej *----------------------------------------------------------------------------*/
264*e450f2e4Sthorpej 
floatx80_is_signaling_nan(floatx80 a)2652df695b1Sross flag floatx80_is_signaling_nan( floatx80 a )
2662df695b1Sross {
2672df695b1Sross     bits64 aLow;
2682df695b1Sross 
2692df695b1Sross     aLow = a.low & ~ LIT64( 0x4000000000000000 );
2702df695b1Sross     return
2712df695b1Sross            ( ( a.high & 0x7FFF ) == 0x7FFF )
2722df695b1Sross         && (bits64) ( aLow<<1 )
2732df695b1Sross         && ( a.low == aLow );
2742df695b1Sross 
2752df695b1Sross }
2762df695b1Sross 
277*e450f2e4Sthorpej /*----------------------------------------------------------------------------
278*e450f2e4Sthorpej | Returns the result of converting the double-extended-precision floating-
279*e450f2e4Sthorpej | point NaN `a' to the canonical NaN format.  If `a' is a signaling NaN, the
280*e450f2e4Sthorpej | invalid exception is raised.
281*e450f2e4Sthorpej *----------------------------------------------------------------------------*/
282*e450f2e4Sthorpej 
floatx80ToCommonNaN(floatx80 a)2832df695b1Sross static commonNaNT floatx80ToCommonNaN( floatx80 a )
2842df695b1Sross {
2852df695b1Sross     commonNaNT z;
2862df695b1Sross 
2872df695b1Sross     if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
2882df695b1Sross     z.sign = a.high>>15;
2892df695b1Sross     z.low = 0;
2902df695b1Sross     z.high = a.low<<1;
2912df695b1Sross     return z;
2922df695b1Sross 
2932df695b1Sross }
2942df695b1Sross 
295*e450f2e4Sthorpej /*----------------------------------------------------------------------------
296*e450f2e4Sthorpej | Returns the result of converting the canonical NaN `a' to the double-
297*e450f2e4Sthorpej | extended-precision floating-point format.
298*e450f2e4Sthorpej *----------------------------------------------------------------------------*/
299*e450f2e4Sthorpej 
commonNaNToFloatx80(commonNaNT a)3002df695b1Sross static floatx80 commonNaNToFloatx80( commonNaNT a )
3012df695b1Sross {
3022df695b1Sross     floatx80 z;
3032df695b1Sross 
3042df695b1Sross     z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
3052df695b1Sross     z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
3062df695b1Sross     return z;
3072df695b1Sross 
3082df695b1Sross }
3092df695b1Sross 
310*e450f2e4Sthorpej /*----------------------------------------------------------------------------
311*e450f2e4Sthorpej | Takes two double-extended-precision floating-point values `a' and `b', one
312*e450f2e4Sthorpej | of which is a NaN, and returns the appropriate NaN result.  If either `a' or
313*e450f2e4Sthorpej | `b' is a signaling NaN, the invalid exception is raised.
314*e450f2e4Sthorpej *----------------------------------------------------------------------------*/
315*e450f2e4Sthorpej 
propagateFloatx80NaN(floatx80 a,floatx80 b)3162df695b1Sross static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b )
3172df695b1Sross {
3182df695b1Sross     flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
3192df695b1Sross 
3202df695b1Sross     aIsNaN = floatx80_is_nan( a );
3212df695b1Sross     aIsSignalingNaN = floatx80_is_signaling_nan( a );
3222df695b1Sross     bIsNaN = floatx80_is_nan( b );
3232df695b1Sross     bIsSignalingNaN = floatx80_is_signaling_nan( b );
3242df695b1Sross     a.low |= LIT64( 0xC000000000000000 );
3252df695b1Sross     b.low |= LIT64( 0xC000000000000000 );
3262df695b1Sross     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
3272df695b1Sross     if ( aIsSignalingNaN ) {
3282df695b1Sross         if ( bIsSignalingNaN ) goto returnLargerSignificand;
3292df695b1Sross         return bIsNaN ? b : a;
3302df695b1Sross     }
3312df695b1Sross     else if ( aIsNaN ) {
3322df695b1Sross         if ( bIsSignalingNaN | ! bIsNaN ) return a;
3332df695b1Sross  returnLargerSignificand:
3342df695b1Sross         if ( a.low < b.low ) return b;
3352df695b1Sross         if ( b.low < a.low ) return a;
3362df695b1Sross         return ( a.high < b.high ) ? a : b;
3372df695b1Sross     }
3382df695b1Sross     else {
3392df695b1Sross         return b;
3402df695b1Sross     }
3412df695b1Sross 
3422df695b1Sross }
3432df695b1Sross 
3442df695b1Sross #endif
3452df695b1Sross 
3462df695b1Sross #ifdef FLOAT128
3472df695b1Sross 
348*e450f2e4Sthorpej /*----------------------------------------------------------------------------
349*e450f2e4Sthorpej | The pattern for a default generated quadruple-precision NaN.  The `high' and
350*e450f2e4Sthorpej | `low' values hold the most- and least-significant bits, respectively.
351*e450f2e4Sthorpej *----------------------------------------------------------------------------*/
3522df695b1Sross #define float128_default_nan_high LIT64( 0xFFFF800000000000 )
3532df695b1Sross #define float128_default_nan_low  LIT64( 0x0000000000000000 )
3542df695b1Sross 
355*e450f2e4Sthorpej /*----------------------------------------------------------------------------
356*e450f2e4Sthorpej | Returns 1 if the quadruple-precision floating-point value `a' is a NaN;
357*e450f2e4Sthorpej | otherwise returns 0.
358*e450f2e4Sthorpej *----------------------------------------------------------------------------*/
359*e450f2e4Sthorpej 
float128_is_nan(float128 a)3602df695b1Sross flag float128_is_nan( float128 a )
3612df695b1Sross {
3622df695b1Sross 
3632df695b1Sross     return
3642df695b1Sross            ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
3652df695b1Sross         && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
3662df695b1Sross 
3672df695b1Sross }
3682df695b1Sross 
369*e450f2e4Sthorpej /*----------------------------------------------------------------------------
370*e450f2e4Sthorpej | Returns 1 if the quadruple-precision floating-point value `a' is a
371*e450f2e4Sthorpej | signaling NaN; otherwise returns 0.
372*e450f2e4Sthorpej *----------------------------------------------------------------------------*/
373*e450f2e4Sthorpej 
float128_is_signaling_nan(float128 a)3742df695b1Sross flag float128_is_signaling_nan( float128 a )
3752df695b1Sross {
3762df695b1Sross 
3772df695b1Sross     return
3782df695b1Sross            ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
3792df695b1Sross         && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
3802df695b1Sross 
3812df695b1Sross }
3822df695b1Sross 
383*e450f2e4Sthorpej /*----------------------------------------------------------------------------
384*e450f2e4Sthorpej | Returns the result of converting the quadruple-precision floating-point NaN
385*e450f2e4Sthorpej | `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
386*e450f2e4Sthorpej | exception is raised.
387*e450f2e4Sthorpej *----------------------------------------------------------------------------*/
388*e450f2e4Sthorpej 
float128ToCommonNaN(float128 a)3892df695b1Sross static commonNaNT float128ToCommonNaN( float128 a )
3902df695b1Sross {
3912df695b1Sross     commonNaNT z;
3922df695b1Sross 
3932df695b1Sross     if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
3942df695b1Sross     z.sign = a.high>>63;
3952df695b1Sross     shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
3962df695b1Sross     return z;
3972df695b1Sross 
3982df695b1Sross }
3992df695b1Sross 
400*e450f2e4Sthorpej /*----------------------------------------------------------------------------
401*e450f2e4Sthorpej | Returns the result of converting the canonical NaN `a' to the quadruple-
402*e450f2e4Sthorpej | precision floating-point format.
403*e450f2e4Sthorpej *----------------------------------------------------------------------------*/
404*e450f2e4Sthorpej 
commonNaNToFloat128(commonNaNT a)4052df695b1Sross static float128 commonNaNToFloat128( commonNaNT a )
4062df695b1Sross {
4072df695b1Sross     float128 z;
4082df695b1Sross 
4092df695b1Sross     shift128Right( a.high, a.low, 16, &z.high, &z.low );
4102df695b1Sross     z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 );
4112df695b1Sross     return z;
4122df695b1Sross 
4132df695b1Sross }
4142df695b1Sross 
415*e450f2e4Sthorpej /*----------------------------------------------------------------------------
416*e450f2e4Sthorpej | Takes two quadruple-precision floating-point values `a' and `b', one of
417*e450f2e4Sthorpej | which is a NaN, and returns the appropriate NaN result.  If either `a' or
418*e450f2e4Sthorpej | `b' is a signaling NaN, the invalid exception is raised.
419*e450f2e4Sthorpej *----------------------------------------------------------------------------*/
420*e450f2e4Sthorpej 
propagateFloat128NaN(float128 a,float128 b)4212df695b1Sross static float128 propagateFloat128NaN( float128 a, float128 b )
4222df695b1Sross {
4232df695b1Sross     flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
4242df695b1Sross 
4252df695b1Sross     aIsNaN = float128_is_nan( a );
4262df695b1Sross     aIsSignalingNaN = float128_is_signaling_nan( a );
4272df695b1Sross     bIsNaN = float128_is_nan( b );
4282df695b1Sross     bIsSignalingNaN = float128_is_signaling_nan( b );
4292df695b1Sross     a.high |= LIT64( 0x0000800000000000 );
4302df695b1Sross     b.high |= LIT64( 0x0000800000000000 );
4312df695b1Sross     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
4322df695b1Sross     if ( aIsSignalingNaN ) {
4332df695b1Sross         if ( bIsSignalingNaN ) goto returnLargerSignificand;
4342df695b1Sross         return bIsNaN ? b : a;
4352df695b1Sross     }
4362df695b1Sross     else if ( aIsNaN ) {
4372df695b1Sross         if ( bIsSignalingNaN | ! bIsNaN ) return a;
4382df695b1Sross  returnLargerSignificand:
4392df695b1Sross         if ( lt128( a.high<<1, a.low, b.high<<1, b.low ) ) return b;
4402df695b1Sross         if ( lt128( b.high<<1, b.low, a.high<<1, a.low ) ) return a;
4412df695b1Sross         return ( a.high < b.high ) ? a : b;
4422df695b1Sross     }
4432df695b1Sross     else {
4442df695b1Sross         return b;
4452df695b1Sross     }
4462df695b1Sross 
4472df695b1Sross }
4482df695b1Sross 
4492df695b1Sross #endif
4502df695b1Sross 
451