1*ce099b40Smartin/* $NetBSD: softfloat-specialize,v 1.2 2008/04/28 20:23:04 martin Exp $ */ 20cdd4f95Sross 30cdd4f95Sross/* This is a derivative work. */ 40cdd4f95Sross 50cdd4f95Sross/*- 60cdd4f95Sross * Copyright (c) 2001 The NetBSD Foundation, Inc. 70cdd4f95Sross * All rights reserved. 80cdd4f95Sross * 90cdd4f95Sross * This code is derived from software contributed to The NetBSD Foundation 100cdd4f95Sross * by Ross Harvey. 110cdd4f95Sross * 120cdd4f95Sross * Redistribution and use in source and binary forms, with or without 130cdd4f95Sross * modification, are permitted provided that the following conditions 140cdd4f95Sross * are met: 150cdd4f95Sross * 1. Redistributions of source code must retain the above copyright 160cdd4f95Sross * notice, this list of conditions and the following disclaimer. 170cdd4f95Sross * 2. Redistributions in binary form must reproduce the above copyright 180cdd4f95Sross * notice, this list of conditions and the following disclaimer in the 190cdd4f95Sross * documentation and/or other materials provided with the distribution. 200cdd4f95Sross * 210cdd4f95Sross * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 220cdd4f95Sross * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 230cdd4f95Sross * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 240cdd4f95Sross * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 250cdd4f95Sross * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 260cdd4f95Sross * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 270cdd4f95Sross * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 280cdd4f95Sross * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 290cdd4f95Sross * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 300cdd4f95Sross * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 310cdd4f95Sross * POSSIBILITY OF SUCH DAMAGE. 320cdd4f95Sross */ 330cdd4f95Sross 340cdd4f95Sross/* 350cdd4f95Sross=============================================================================== 360cdd4f95Sross 370cdd4f95SrossThis C source fragment is part of the SoftFloat IEC/IEEE Floating-point 380cdd4f95SrossArithmetic Package, Release 2a. 390cdd4f95Sross 400cdd4f95SrossWritten by John R. Hauser. This work was made possible in part by the 410cdd4f95SrossInternational Computer Science Institute, located at Suite 600, 1947 Center 420cdd4f95SrossStreet, Berkeley, California 94704. Funding was partially provided by the 430cdd4f95SrossNational Science Foundation under grant MIP-9311980. The original version 440cdd4f95Srossof this code was written as part of a project to build a fixed-point vector 450cdd4f95Srossprocessor in collaboration with the University of California at Berkeley, 460cdd4f95Srossoverseen by Profs. Nelson Morgan and John Wawrzynek. More information 470cdd4f95Srossis available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/ 480cdd4f95Srossarithmetic/SoftFloat.html'. 490cdd4f95Sross 500cdd4f95SrossTHIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort 510cdd4f95Srosshas been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT 520cdd4f95SrossTIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO 530cdd4f95SrossPERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY 540cdd4f95SrossAND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. 550cdd4f95Sross 560cdd4f95SrossDerivative works are acceptable, even for commercial purposes, so long as 570cdd4f95Sross(1) they include prominent notice that the work is derivative, and (2) they 580cdd4f95Srossinclude prominent notice akin to these four paragraphs for those parts of 590cdd4f95Srossthis code that are retained. 600cdd4f95Sross 610cdd4f95Sross=============================================================================== 620cdd4f95Sross*/ 630cdd4f95Sross 640cdd4f95Sross/* 650cdd4f95Sross------------------------------------------------------------------------------- 660cdd4f95SrossUnderflow tininess-detection mode, statically initialized to default value. 670cdd4f95Sross------------------------------------------------------------------------------- 680cdd4f95Sross*/ 690cdd4f95Srossint float_detect_tininess = float_tininess_after_rounding; 700cdd4f95Sross 710cdd4f95Sross/* 720cdd4f95Sross------------------------------------------------------------------------------- 730cdd4f95SrossRaises the exceptions specified by `flags'. Floating-point traps can be 740cdd4f95Srossdefined here if desired. It is currently not possible for such a trap 750cdd4f95Srossto substitute a result value. If traps are not implemented, this routine 760cdd4f95Srossshould be simply `float_exception_flags |= flags;'. 770cdd4f95Sross------------------------------------------------------------------------------- 780cdd4f95Sross*/ 790cdd4f95Srossvoid float_raise( int flags ) 800cdd4f95Sross{ 810cdd4f95Sross 820cdd4f95Sross float_exception_flags |= flags; 830cdd4f95Sross 840cdd4f95Sross} 850cdd4f95Sross 860cdd4f95Sross/* 870cdd4f95Sross------------------------------------------------------------------------------- 880cdd4f95SrossInternal canonical NaN format. 890cdd4f95Sross------------------------------------------------------------------------------- 900cdd4f95Sross*/ 910cdd4f95Srosstypedef struct { 920cdd4f95Sross flag sign; 930cdd4f95Sross bits64 high, low; 940cdd4f95Sross} commonNaNT; 950cdd4f95Sross 960cdd4f95Sross/* 970cdd4f95Sross------------------------------------------------------------------------------- 980cdd4f95SrossThe pattern for a default generated single-precision NaN. 990cdd4f95Sross------------------------------------------------------------------------------- 1000cdd4f95Sross*/ 1010cdd4f95Sross#define float32_default_nan 0xFFC00000 1020cdd4f95Sross 1030cdd4f95Sross/* 1040cdd4f95Sross------------------------------------------------------------------------------- 1050cdd4f95SrossReturns 1 if the single-precision floating-point value `a' is a NaN; 1060cdd4f95Srossotherwise returns 0. 1070cdd4f95Sross------------------------------------------------------------------------------- 1080cdd4f95Sross*/ 1090cdd4f95Srossstatic flag float32_is_nan( float32 a ) 1100cdd4f95Sross{ 1110cdd4f95Sross 1120cdd4f95Sross return ( 0xFF000000 < (bits32) ( a<<1 ) ); 1130cdd4f95Sross 1140cdd4f95Sross} 1150cdd4f95Sross 1160cdd4f95Sross/* 1170cdd4f95Sross------------------------------------------------------------------------------- 1180cdd4f95SrossReturns 1 if the single-precision floating-point value `a' is a signaling 1190cdd4f95SrossNaN; otherwise returns 0. 1200cdd4f95Sross------------------------------------------------------------------------------- 1210cdd4f95Sross*/ 1220cdd4f95Srossflag float32_is_signaling_nan( float32 a ) 1230cdd4f95Sross{ 1240cdd4f95Sross 1250cdd4f95Sross return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); 1260cdd4f95Sross 1270cdd4f95Sross} 1280cdd4f95Sross 1290cdd4f95Sross/* 1300cdd4f95Sross------------------------------------------------------------------------------- 1310cdd4f95SrossReturns the result of converting the single-precision floating-point NaN 1320cdd4f95Sross`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 1330cdd4f95Srossexception is raised. 1340cdd4f95Sross------------------------------------------------------------------------------- 1350cdd4f95Sross*/ 1360cdd4f95Srossstatic commonNaNT float32ToCommonNaN( float32 a ) 1370cdd4f95Sross{ 1380cdd4f95Sross commonNaNT z; 1390cdd4f95Sross 1400cdd4f95Sross if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 1410cdd4f95Sross z.sign = a>>31; 1420cdd4f95Sross z.low = 0; 1430cdd4f95Sross z.high = ( (bits64) a )<<41; 1440cdd4f95Sross return z; 1450cdd4f95Sross 1460cdd4f95Sross} 1470cdd4f95Sross 1480cdd4f95Sross/* 1490cdd4f95Sross------------------------------------------------------------------------------- 1500cdd4f95SrossReturns the result of converting the canonical NaN `a' to the single- 1510cdd4f95Srossprecision floating-point format. 1520cdd4f95Sross------------------------------------------------------------------------------- 1530cdd4f95Sross*/ 1540cdd4f95Srossstatic float32 commonNaNToFloat32( commonNaNT a ) 1550cdd4f95Sross{ 1560cdd4f95Sross 1570cdd4f95Sross return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 ); 1580cdd4f95Sross 1590cdd4f95Sross} 1600cdd4f95Sross 1610cdd4f95Sross/* 1620cdd4f95Sross------------------------------------------------------------------------------- 1630cdd4f95SrossTakes two single-precision floating-point values `a' and `b', one of which 1640cdd4f95Srossis a NaN, and returns the appropriate NaN result. If either `a' or `b' is a 1650cdd4f95Srosssignaling NaN, the invalid exception is raised. 1660cdd4f95Sross------------------------------------------------------------------------------- 1670cdd4f95Sross*/ 1680cdd4f95Srossstatic float32 propagateFloat32NaN( float32 a, float32 b ) 1690cdd4f95Sross{ 1700cdd4f95Sross flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 1710cdd4f95Sross 1720cdd4f95Sross aIsNaN = float32_is_nan( a ); 1730cdd4f95Sross aIsSignalingNaN = float32_is_signaling_nan( a ); 1740cdd4f95Sross bIsNaN = float32_is_nan( b ); 1750cdd4f95Sross bIsSignalingNaN = float32_is_signaling_nan( b ); 1760cdd4f95Sross a |= 0x00400000; 1770cdd4f95Sross b |= 0x00400000; 1780cdd4f95Sross if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 1790cdd4f95Sross if ( aIsSignalingNaN ) { 1800cdd4f95Sross if ( bIsSignalingNaN ) goto returnLargerSignificand; 1810cdd4f95Sross return bIsNaN ? b : a; 1820cdd4f95Sross } 1830cdd4f95Sross else if ( aIsNaN ) { 1840cdd4f95Sross if ( bIsSignalingNaN | ! bIsNaN ) return a; 1850cdd4f95Sross returnLargerSignificand: 1860cdd4f95Sross if ( (bits32) ( a<<1 ) < (bits32) ( b<<1 ) ) return b; 1870cdd4f95Sross if ( (bits32) ( b<<1 ) < (bits32) ( a<<1 ) ) return a; 1880cdd4f95Sross return ( a < b ) ? a : b; 1890cdd4f95Sross } 1900cdd4f95Sross else { 1910cdd4f95Sross return b; 1920cdd4f95Sross } 1930cdd4f95Sross 1940cdd4f95Sross} 1950cdd4f95Sross 1960cdd4f95Sross/* 1970cdd4f95Sross------------------------------------------------------------------------------- 1980cdd4f95SrossThe pattern for a default generated double-precision NaN. 1990cdd4f95Sross------------------------------------------------------------------------------- 2000cdd4f95Sross*/ 2010cdd4f95Sross#define float64_default_nan LIT64( 0xFFF8000000000000 ) 2020cdd4f95Sross 2030cdd4f95Sross/* 2040cdd4f95Sross------------------------------------------------------------------------------- 2050cdd4f95SrossReturns 1 if the double-precision floating-point value `a' is a NaN; 2060cdd4f95Srossotherwise returns 0. 2070cdd4f95Sross------------------------------------------------------------------------------- 2080cdd4f95Sross*/ 2090cdd4f95Srossstatic flag float64_is_nan( float64 a ) 2100cdd4f95Sross{ 2110cdd4f95Sross 2120cdd4f95Sross return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) ); 2130cdd4f95Sross 2140cdd4f95Sross} 2150cdd4f95Sross 2160cdd4f95Sross/* 2170cdd4f95Sross------------------------------------------------------------------------------- 2180cdd4f95SrossReturns 1 if the double-precision floating-point value `a' is a signaling 2190cdd4f95SrossNaN; otherwise returns 0. 2200cdd4f95Sross------------------------------------------------------------------------------- 2210cdd4f95Sross*/ 2220cdd4f95Srossflag float64_is_signaling_nan( float64 a ) 2230cdd4f95Sross{ 2240cdd4f95Sross 2250cdd4f95Sross return 2260cdd4f95Sross ( ( ( a>>51 ) & 0xFFF ) == 0xFFE ) 2270cdd4f95Sross && ( a & LIT64( 0x0007FFFFFFFFFFFF ) ); 2280cdd4f95Sross 2290cdd4f95Sross} 2300cdd4f95Sross 2310cdd4f95Sross/* 2320cdd4f95Sross------------------------------------------------------------------------------- 2330cdd4f95SrossReturns the result of converting the double-precision floating-point NaN 2340cdd4f95Sross`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 2350cdd4f95Srossexception is raised. 2360cdd4f95Sross------------------------------------------------------------------------------- 2370cdd4f95Sross*/ 2380cdd4f95Srossstatic commonNaNT float64ToCommonNaN( float64 a ) 2390cdd4f95Sross{ 2400cdd4f95Sross commonNaNT z; 2410cdd4f95Sross 2420cdd4f95Sross if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 2430cdd4f95Sross z.sign = a>>63; 2440cdd4f95Sross z.low = 0; 2450cdd4f95Sross z.high = a<<12; 2460cdd4f95Sross return z; 2470cdd4f95Sross 2480cdd4f95Sross} 2490cdd4f95Sross 2500cdd4f95Sross/* 2510cdd4f95Sross------------------------------------------------------------------------------- 2520cdd4f95SrossReturns the result of converting the canonical NaN `a' to the double- 2530cdd4f95Srossprecision floating-point format. 2540cdd4f95Sross------------------------------------------------------------------------------- 2550cdd4f95Sross*/ 2560cdd4f95Srossstatic float64 commonNaNToFloat64( commonNaNT a ) 2570cdd4f95Sross{ 2580cdd4f95Sross 2590cdd4f95Sross return 2600cdd4f95Sross ( ( (bits64) a.sign )<<63 ) 2610cdd4f95Sross | LIT64( 0x7FF8000000000000 ) 2620cdd4f95Sross | ( a.high>>12 ); 2630cdd4f95Sross 2640cdd4f95Sross} 2650cdd4f95Sross 2660cdd4f95Sross/* 2670cdd4f95Sross------------------------------------------------------------------------------- 2680cdd4f95SrossTakes two double-precision floating-point values `a' and `b', one of which 2690cdd4f95Srossis a NaN, and returns the appropriate NaN result. If either `a' or `b' is a 2700cdd4f95Srosssignaling NaN, the invalid exception is raised. 2710cdd4f95Sross------------------------------------------------------------------------------- 2720cdd4f95Sross*/ 2730cdd4f95Srossstatic float64 propagateFloat64NaN( float64 a, float64 b ) 2740cdd4f95Sross{ 2750cdd4f95Sross flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 2760cdd4f95Sross 2770cdd4f95Sross aIsNaN = float64_is_nan( a ); 2780cdd4f95Sross aIsSignalingNaN = float64_is_signaling_nan( a ); 2790cdd4f95Sross bIsNaN = float64_is_nan( b ); 2800cdd4f95Sross bIsSignalingNaN = float64_is_signaling_nan( b ); 2810cdd4f95Sross a |= LIT64( 0x0008000000000000 ); 2820cdd4f95Sross b |= LIT64( 0x0008000000000000 ); 2830cdd4f95Sross if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 2840cdd4f95Sross if ( aIsSignalingNaN ) { 2850cdd4f95Sross if ( bIsSignalingNaN ) goto returnLargerSignificand; 2860cdd4f95Sross return bIsNaN ? b : a; 2870cdd4f95Sross } 2880cdd4f95Sross else if ( aIsNaN ) { 2890cdd4f95Sross if ( bIsSignalingNaN | ! bIsNaN ) return a; 2900cdd4f95Sross returnLargerSignificand: 2910cdd4f95Sross if ( (bits64) ( a<<1 ) < (bits64) ( b<<1 ) ) return b; 2920cdd4f95Sross if ( (bits64) ( b<<1 ) < (bits64) ( a<<1 ) ) return a; 2930cdd4f95Sross return ( a < b ) ? a : b; 2940cdd4f95Sross } 2950cdd4f95Sross else { 2960cdd4f95Sross return b; 2970cdd4f95Sross } 2980cdd4f95Sross 2990cdd4f95Sross} 3000cdd4f95Sross 3010cdd4f95Sross#ifdef FLOATX80 3020cdd4f95Sross 3030cdd4f95Sross/* 3040cdd4f95Sross------------------------------------------------------------------------------- 3050cdd4f95SrossThe pattern for a default generated extended double-precision NaN. The 3060cdd4f95Sross`high' and `low' values hold the most- and least-significant bits, 3070cdd4f95Srossrespectively. 3080cdd4f95Sross------------------------------------------------------------------------------- 3090cdd4f95Sross*/ 3100cdd4f95Sross#define floatx80_default_nan_high 0xFFFF 3110cdd4f95Sross#define floatx80_default_nan_low LIT64( 0xC000000000000000 ) 3120cdd4f95Sross 3130cdd4f95Sross/* 3140cdd4f95Sross------------------------------------------------------------------------------- 3150cdd4f95SrossReturns 1 if the extended double-precision floating-point value `a' is a 3160cdd4f95SrossNaN; otherwise returns 0. 3170cdd4f95Sross------------------------------------------------------------------------------- 3180cdd4f95Sross*/ 3190cdd4f95Srossstatic flag floatx80_is_nan( floatx80 a ) 3200cdd4f95Sross{ 3210cdd4f95Sross 3220cdd4f95Sross return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 ); 3230cdd4f95Sross 3240cdd4f95Sross} 3250cdd4f95Sross 3260cdd4f95Sross/* 3270cdd4f95Sross------------------------------------------------------------------------------- 3280cdd4f95SrossReturns 1 if the extended double-precision floating-point value `a' is a 3290cdd4f95Srosssignaling NaN; otherwise returns 0. 3300cdd4f95Sross------------------------------------------------------------------------------- 3310cdd4f95Sross*/ 3320cdd4f95Srossflag floatx80_is_signaling_nan( floatx80 a ) 3330cdd4f95Sross{ 3340cdd4f95Sross bits64 aLow; 3350cdd4f95Sross 3360cdd4f95Sross aLow = a.low & ~ LIT64( 0x4000000000000000 ); 3370cdd4f95Sross return 3380cdd4f95Sross ( ( a.high & 0x7FFF ) == 0x7FFF ) 3390cdd4f95Sross && (bits64) ( aLow<<1 ) 3400cdd4f95Sross && ( a.low == aLow ); 3410cdd4f95Sross 3420cdd4f95Sross} 3430cdd4f95Sross 3440cdd4f95Sross/* 3450cdd4f95Sross------------------------------------------------------------------------------- 3460cdd4f95SrossReturns the result of converting the extended double-precision floating- 3470cdd4f95Srosspoint NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the 3480cdd4f95Srossinvalid exception is raised. 3490cdd4f95Sross------------------------------------------------------------------------------- 3500cdd4f95Sross*/ 3510cdd4f95Srossstatic commonNaNT floatx80ToCommonNaN( floatx80 a ) 3520cdd4f95Sross{ 3530cdd4f95Sross commonNaNT z; 3540cdd4f95Sross 3550cdd4f95Sross if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 3560cdd4f95Sross z.sign = a.high>>15; 3570cdd4f95Sross z.low = 0; 3580cdd4f95Sross z.high = a.low<<1; 3590cdd4f95Sross return z; 3600cdd4f95Sross 3610cdd4f95Sross} 3620cdd4f95Sross 3630cdd4f95Sross/* 3640cdd4f95Sross------------------------------------------------------------------------------- 3650cdd4f95SrossReturns the result of converting the canonical NaN `a' to the extended 3660cdd4f95Srossdouble-precision floating-point format. 3670cdd4f95Sross------------------------------------------------------------------------------- 3680cdd4f95Sross*/ 3690cdd4f95Srossstatic floatx80 commonNaNToFloatx80( commonNaNT a ) 3700cdd4f95Sross{ 3710cdd4f95Sross floatx80 z; 3720cdd4f95Sross 3730cdd4f95Sross z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 ); 3740cdd4f95Sross z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF; 3750cdd4f95Sross return z; 3760cdd4f95Sross 3770cdd4f95Sross} 3780cdd4f95Sross 3790cdd4f95Sross/* 3800cdd4f95Sross------------------------------------------------------------------------------- 3810cdd4f95SrossTakes two extended double-precision floating-point values `a' and `b', one 3820cdd4f95Srossof which is a NaN, and returns the appropriate NaN result. If either `a' or 3830cdd4f95Sross`b' is a signaling NaN, the invalid exception is raised. 3840cdd4f95Sross------------------------------------------------------------------------------- 3850cdd4f95Sross*/ 3860cdd4f95Srossstatic floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b ) 3870cdd4f95Sross{ 3880cdd4f95Sross flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 3890cdd4f95Sross 3900cdd4f95Sross aIsNaN = floatx80_is_nan( a ); 3910cdd4f95Sross aIsSignalingNaN = floatx80_is_signaling_nan( a ); 3920cdd4f95Sross bIsNaN = floatx80_is_nan( b ); 3930cdd4f95Sross bIsSignalingNaN = floatx80_is_signaling_nan( b ); 3940cdd4f95Sross a.low |= LIT64( 0xC000000000000000 ); 3950cdd4f95Sross b.low |= LIT64( 0xC000000000000000 ); 3960cdd4f95Sross if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 3970cdd4f95Sross if ( aIsSignalingNaN ) { 3980cdd4f95Sross if ( bIsSignalingNaN ) goto returnLargerSignificand; 3990cdd4f95Sross return bIsNaN ? b : a; 4000cdd4f95Sross } 4010cdd4f95Sross else if ( aIsNaN ) { 4020cdd4f95Sross if ( bIsSignalingNaN | ! bIsNaN ) return a; 4030cdd4f95Sross returnLargerSignificand: 4040cdd4f95Sross if ( a.low < b.low ) return b; 4050cdd4f95Sross if ( b.low < a.low ) return a; 4060cdd4f95Sross return ( a.high < b.high ) ? a : b; 4070cdd4f95Sross } 4080cdd4f95Sross else { 4090cdd4f95Sross return b; 4100cdd4f95Sross } 4110cdd4f95Sross 4120cdd4f95Sross} 4130cdd4f95Sross 4140cdd4f95Sross#endif 4150cdd4f95Sross 4160cdd4f95Sross#ifdef FLOAT128 4170cdd4f95Sross 4180cdd4f95Sross/* 4190cdd4f95Sross------------------------------------------------------------------------------- 4200cdd4f95SrossThe pattern for a default generated quadruple-precision NaN. The `high' and 4210cdd4f95Sross`low' values hold the most- and least-significant bits, respectively. 4220cdd4f95Sross------------------------------------------------------------------------------- 4230cdd4f95Sross*/ 4240cdd4f95Sross#define float128_default_nan_high LIT64( 0xFFFF800000000000 ) 4250cdd4f95Sross#define float128_default_nan_low LIT64( 0x0000000000000000 ) 4260cdd4f95Sross 4270cdd4f95Sross/* 4280cdd4f95Sross------------------------------------------------------------------------------- 4290cdd4f95SrossReturns 1 if the quadruple-precision floating-point value `a' is a NaN; 4300cdd4f95Srossotherwise returns 0. 4310cdd4f95Sross------------------------------------------------------------------------------- 4320cdd4f95Sross*/ 4330cdd4f95Srossflag float128_is_nan( float128 a ) 4340cdd4f95Sross{ 4350cdd4f95Sross 4360cdd4f95Sross return 4370cdd4f95Sross ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) ) 4380cdd4f95Sross && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) ); 4390cdd4f95Sross 4400cdd4f95Sross} 4410cdd4f95Sross 4420cdd4f95Sross/* 4430cdd4f95Sross------------------------------------------------------------------------------- 4440cdd4f95SrossReturns 1 if the quadruple-precision floating-point value `a' is a 4450cdd4f95Srosssignaling NaN; otherwise returns 0. 4460cdd4f95Sross------------------------------------------------------------------------------- 4470cdd4f95Sross*/ 4480cdd4f95Srossflag float128_is_signaling_nan( float128 a ) 4490cdd4f95Sross{ 4500cdd4f95Sross 4510cdd4f95Sross return 4520cdd4f95Sross ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE ) 4530cdd4f95Sross && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) ); 4540cdd4f95Sross 4550cdd4f95Sross} 4560cdd4f95Sross 4570cdd4f95Sross/* 4580cdd4f95Sross------------------------------------------------------------------------------- 4590cdd4f95SrossReturns the result of converting the quadruple-precision floating-point NaN 4600cdd4f95Sross`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 4610cdd4f95Srossexception is raised. 4620cdd4f95Sross------------------------------------------------------------------------------- 4630cdd4f95Sross*/ 4640cdd4f95Srossstatic commonNaNT float128ToCommonNaN( float128 a ) 4650cdd4f95Sross{ 4660cdd4f95Sross commonNaNT z; 4670cdd4f95Sross 4680cdd4f95Sross if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 4690cdd4f95Sross z.sign = a.high>>63; 4700cdd4f95Sross shortShift128Left( a.high, a.low, 16, &z.high, &z.low ); 4710cdd4f95Sross return z; 4720cdd4f95Sross 4730cdd4f95Sross} 4740cdd4f95Sross 4750cdd4f95Sross/* 4760cdd4f95Sross------------------------------------------------------------------------------- 4770cdd4f95SrossReturns the result of converting the canonical NaN `a' to the quadruple- 4780cdd4f95Srossprecision floating-point format. 4790cdd4f95Sross------------------------------------------------------------------------------- 4800cdd4f95Sross*/ 4810cdd4f95Srossstatic float128 commonNaNToFloat128( commonNaNT a ) 4820cdd4f95Sross{ 4830cdd4f95Sross float128 z; 4840cdd4f95Sross 4850cdd4f95Sross shift128Right( a.high, a.low, 16, &z.high, &z.low ); 4860cdd4f95Sross z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 ); 4870cdd4f95Sross return z; 4880cdd4f95Sross 4890cdd4f95Sross} 4900cdd4f95Sross 4910cdd4f95Sross/* 4920cdd4f95Sross------------------------------------------------------------------------------- 4930cdd4f95SrossTakes two quadruple-precision floating-point values `a' and `b', one of 4940cdd4f95Srosswhich is a NaN, and returns the appropriate NaN result. If either `a' or 4950cdd4f95Sross`b' is a signaling NaN, the invalid exception is raised. 4960cdd4f95Sross------------------------------------------------------------------------------- 4970cdd4f95Sross*/ 4980cdd4f95Srossstatic float128 propagateFloat128NaN( float128 a, float128 b ) 4990cdd4f95Sross{ 5000cdd4f95Sross flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 5010cdd4f95Sross 5020cdd4f95Sross aIsNaN = float128_is_nan( a ); 5030cdd4f95Sross aIsSignalingNaN = float128_is_signaling_nan( a ); 5040cdd4f95Sross bIsNaN = float128_is_nan( b ); 5050cdd4f95Sross bIsSignalingNaN = float128_is_signaling_nan( b ); 5060cdd4f95Sross a.high |= LIT64( 0x0000800000000000 ); 5070cdd4f95Sross b.high |= LIT64( 0x0000800000000000 ); 5080cdd4f95Sross if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 5090cdd4f95Sross if ( aIsSignalingNaN ) { 5100cdd4f95Sross if ( bIsSignalingNaN ) goto returnLargerSignificand; 5110cdd4f95Sross return bIsNaN ? b : a; 5120cdd4f95Sross } 5130cdd4f95Sross else if ( aIsNaN ) { 5140cdd4f95Sross if ( bIsSignalingNaN | ! bIsNaN ) return a; 5150cdd4f95Sross returnLargerSignificand: 5160cdd4f95Sross if ( lt128( a.high<<1, a.low, b.high<<1, b.low ) ) return b; 5170cdd4f95Sross if ( lt128( b.high<<1, b.low, a.high<<1, a.low ) ) return a; 5180cdd4f95Sross return ( a.high < b.high ) ? a : b; 5190cdd4f95Sross } 5200cdd4f95Sross else { 5210cdd4f95Sross return b; 5220cdd4f95Sross } 5230cdd4f95Sross 5240cdd4f95Sross} 5250cdd4f95Sross 5260cdd4f95Sross#endif 5270cdd4f95Sross 528