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