softfloat-specialize revision 1.2
11.2Smartin/* $NetBSD: softfloat-specialize,v 1.2 2008/04/28 20:23:04 martin Exp $ */ 21.1Sross 31.1Sross/* This is a derivative work. */ 41.1Sross 51.1Sross/*- 61.1Sross * Copyright (c) 2001 The NetBSD Foundation, Inc. 71.1Sross * All rights reserved. 81.1Sross * 91.1Sross * This code is derived from software contributed to The NetBSD Foundation 101.1Sross * by Ross Harvey. 111.1Sross * 121.1Sross * Redistribution and use in source and binary forms, with or without 131.1Sross * modification, are permitted provided that the following conditions 141.1Sross * are met: 151.1Sross * 1. Redistributions of source code must retain the above copyright 161.1Sross * notice, this list of conditions and the following disclaimer. 171.1Sross * 2. Redistributions in binary form must reproduce the above copyright 181.1Sross * notice, this list of conditions and the following disclaimer in the 191.1Sross * documentation and/or other materials provided with the distribution. 201.1Sross * 211.1Sross * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 221.1Sross * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 231.1Sross * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 241.1Sross * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 251.1Sross * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 261.1Sross * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 271.1Sross * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 281.1Sross * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 291.1Sross * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 301.1Sross * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 311.1Sross * POSSIBILITY OF SUCH DAMAGE. 321.1Sross */ 331.1Sross 341.1Sross/* 351.1Sross=============================================================================== 361.1Sross 371.1SrossThis C source fragment is part of the SoftFloat IEC/IEEE Floating-point 381.1SrossArithmetic Package, Release 2a. 391.1Sross 401.1SrossWritten by John R. Hauser. This work was made possible in part by the 411.1SrossInternational Computer Science Institute, located at Suite 600, 1947 Center 421.1SrossStreet, Berkeley, California 94704. Funding was partially provided by the 431.1SrossNational Science Foundation under grant MIP-9311980. The original version 441.1Srossof this code was written as part of a project to build a fixed-point vector 451.1Srossprocessor in collaboration with the University of California at Berkeley, 461.1Srossoverseen by Profs. Nelson Morgan and John Wawrzynek. More information 471.1Srossis available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/ 481.1Srossarithmetic/SoftFloat.html'. 491.1Sross 501.1SrossTHIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort 511.1Srosshas been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT 521.1SrossTIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO 531.1SrossPERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY 541.1SrossAND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. 551.1Sross 561.1SrossDerivative works are acceptable, even for commercial purposes, so long as 571.1Sross(1) they include prominent notice that the work is derivative, and (2) they 581.1Srossinclude prominent notice akin to these four paragraphs for those parts of 591.1Srossthis code that are retained. 601.1Sross 611.1Sross=============================================================================== 621.1Sross*/ 631.1Sross 641.1Sross/* 651.1Sross------------------------------------------------------------------------------- 661.1SrossUnderflow tininess-detection mode, statically initialized to default value. 671.1Sross------------------------------------------------------------------------------- 681.1Sross*/ 691.1Srossint float_detect_tininess = float_tininess_after_rounding; 701.1Sross 711.1Sross/* 721.1Sross------------------------------------------------------------------------------- 731.1SrossRaises the exceptions specified by `flags'. Floating-point traps can be 741.1Srossdefined here if desired. It is currently not possible for such a trap 751.1Srossto substitute a result value. If traps are not implemented, this routine 761.1Srossshould be simply `float_exception_flags |= flags;'. 771.1Sross------------------------------------------------------------------------------- 781.1Sross*/ 791.1Srossvoid float_raise( int flags ) 801.1Sross{ 811.1Sross 821.1Sross float_exception_flags |= flags; 831.1Sross 841.1Sross} 851.1Sross 861.1Sross/* 871.1Sross------------------------------------------------------------------------------- 881.1SrossInternal canonical NaN format. 891.1Sross------------------------------------------------------------------------------- 901.1Sross*/ 911.1Srosstypedef struct { 921.1Sross flag sign; 931.1Sross bits64 high, low; 941.1Sross} commonNaNT; 951.1Sross 961.1Sross/* 971.1Sross------------------------------------------------------------------------------- 981.1SrossThe pattern for a default generated single-precision NaN. 991.1Sross------------------------------------------------------------------------------- 1001.1Sross*/ 1011.1Sross#define float32_default_nan 0xFFC00000 1021.1Sross 1031.1Sross/* 1041.1Sross------------------------------------------------------------------------------- 1051.1SrossReturns 1 if the single-precision floating-point value `a' is a NaN; 1061.1Srossotherwise returns 0. 1071.1Sross------------------------------------------------------------------------------- 1081.1Sross*/ 1091.1Srossstatic flag float32_is_nan( float32 a ) 1101.1Sross{ 1111.1Sross 1121.1Sross return ( 0xFF000000 < (bits32) ( a<<1 ) ); 1131.1Sross 1141.1Sross} 1151.1Sross 1161.1Sross/* 1171.1Sross------------------------------------------------------------------------------- 1181.1SrossReturns 1 if the single-precision floating-point value `a' is a signaling 1191.1SrossNaN; otherwise returns 0. 1201.1Sross------------------------------------------------------------------------------- 1211.1Sross*/ 1221.1Srossflag float32_is_signaling_nan( float32 a ) 1231.1Sross{ 1241.1Sross 1251.1Sross return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); 1261.1Sross 1271.1Sross} 1281.1Sross 1291.1Sross/* 1301.1Sross------------------------------------------------------------------------------- 1311.1SrossReturns the result of converting the single-precision floating-point NaN 1321.1Sross`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 1331.1Srossexception is raised. 1341.1Sross------------------------------------------------------------------------------- 1351.1Sross*/ 1361.1Srossstatic commonNaNT float32ToCommonNaN( float32 a ) 1371.1Sross{ 1381.1Sross commonNaNT z; 1391.1Sross 1401.1Sross if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 1411.1Sross z.sign = a>>31; 1421.1Sross z.low = 0; 1431.1Sross z.high = ( (bits64) a )<<41; 1441.1Sross return z; 1451.1Sross 1461.1Sross} 1471.1Sross 1481.1Sross/* 1491.1Sross------------------------------------------------------------------------------- 1501.1SrossReturns the result of converting the canonical NaN `a' to the single- 1511.1Srossprecision floating-point format. 1521.1Sross------------------------------------------------------------------------------- 1531.1Sross*/ 1541.1Srossstatic float32 commonNaNToFloat32( commonNaNT a ) 1551.1Sross{ 1561.1Sross 1571.1Sross return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 ); 1581.1Sross 1591.1Sross} 1601.1Sross 1611.1Sross/* 1621.1Sross------------------------------------------------------------------------------- 1631.1SrossTakes two single-precision floating-point values `a' and `b', one of which 1641.1Srossis a NaN, and returns the appropriate NaN result. If either `a' or `b' is a 1651.1Srosssignaling NaN, the invalid exception is raised. 1661.1Sross------------------------------------------------------------------------------- 1671.1Sross*/ 1681.1Srossstatic float32 propagateFloat32NaN( float32 a, float32 b ) 1691.1Sross{ 1701.1Sross flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 1711.1Sross 1721.1Sross aIsNaN = float32_is_nan( a ); 1731.1Sross aIsSignalingNaN = float32_is_signaling_nan( a ); 1741.1Sross bIsNaN = float32_is_nan( b ); 1751.1Sross bIsSignalingNaN = float32_is_signaling_nan( b ); 1761.1Sross a |= 0x00400000; 1771.1Sross b |= 0x00400000; 1781.1Sross if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 1791.1Sross if ( aIsSignalingNaN ) { 1801.1Sross if ( bIsSignalingNaN ) goto returnLargerSignificand; 1811.1Sross return bIsNaN ? b : a; 1821.1Sross } 1831.1Sross else if ( aIsNaN ) { 1841.1Sross if ( bIsSignalingNaN | ! bIsNaN ) return a; 1851.1Sross returnLargerSignificand: 1861.1Sross if ( (bits32) ( a<<1 ) < (bits32) ( b<<1 ) ) return b; 1871.1Sross if ( (bits32) ( b<<1 ) < (bits32) ( a<<1 ) ) return a; 1881.1Sross return ( a < b ) ? a : b; 1891.1Sross } 1901.1Sross else { 1911.1Sross return b; 1921.1Sross } 1931.1Sross 1941.1Sross} 1951.1Sross 1961.1Sross/* 1971.1Sross------------------------------------------------------------------------------- 1981.1SrossThe pattern for a default generated double-precision NaN. 1991.1Sross------------------------------------------------------------------------------- 2001.1Sross*/ 2011.1Sross#define float64_default_nan LIT64( 0xFFF8000000000000 ) 2021.1Sross 2031.1Sross/* 2041.1Sross------------------------------------------------------------------------------- 2051.1SrossReturns 1 if the double-precision floating-point value `a' is a NaN; 2061.1Srossotherwise returns 0. 2071.1Sross------------------------------------------------------------------------------- 2081.1Sross*/ 2091.1Srossstatic flag float64_is_nan( float64 a ) 2101.1Sross{ 2111.1Sross 2121.1Sross return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) ); 2131.1Sross 2141.1Sross} 2151.1Sross 2161.1Sross/* 2171.1Sross------------------------------------------------------------------------------- 2181.1SrossReturns 1 if the double-precision floating-point value `a' is a signaling 2191.1SrossNaN; otherwise returns 0. 2201.1Sross------------------------------------------------------------------------------- 2211.1Sross*/ 2221.1Srossflag float64_is_signaling_nan( float64 a ) 2231.1Sross{ 2241.1Sross 2251.1Sross return 2261.1Sross ( ( ( a>>51 ) & 0xFFF ) == 0xFFE ) 2271.1Sross && ( a & LIT64( 0x0007FFFFFFFFFFFF ) ); 2281.1Sross 2291.1Sross} 2301.1Sross 2311.1Sross/* 2321.1Sross------------------------------------------------------------------------------- 2331.1SrossReturns the result of converting the double-precision floating-point NaN 2341.1Sross`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 2351.1Srossexception is raised. 2361.1Sross------------------------------------------------------------------------------- 2371.1Sross*/ 2381.1Srossstatic commonNaNT float64ToCommonNaN( float64 a ) 2391.1Sross{ 2401.1Sross commonNaNT z; 2411.1Sross 2421.1Sross if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 2431.1Sross z.sign = a>>63; 2441.1Sross z.low = 0; 2451.1Sross z.high = a<<12; 2461.1Sross return z; 2471.1Sross 2481.1Sross} 2491.1Sross 2501.1Sross/* 2511.1Sross------------------------------------------------------------------------------- 2521.1SrossReturns the result of converting the canonical NaN `a' to the double- 2531.1Srossprecision floating-point format. 2541.1Sross------------------------------------------------------------------------------- 2551.1Sross*/ 2561.1Srossstatic float64 commonNaNToFloat64( commonNaNT a ) 2571.1Sross{ 2581.1Sross 2591.1Sross return 2601.1Sross ( ( (bits64) a.sign )<<63 ) 2611.1Sross | LIT64( 0x7FF8000000000000 ) 2621.1Sross | ( a.high>>12 ); 2631.1Sross 2641.1Sross} 2651.1Sross 2661.1Sross/* 2671.1Sross------------------------------------------------------------------------------- 2681.1SrossTakes two double-precision floating-point values `a' and `b', one of which 2691.1Srossis a NaN, and returns the appropriate NaN result. If either `a' or `b' is a 2701.1Srosssignaling NaN, the invalid exception is raised. 2711.1Sross------------------------------------------------------------------------------- 2721.1Sross*/ 2731.1Srossstatic float64 propagateFloat64NaN( float64 a, float64 b ) 2741.1Sross{ 2751.1Sross flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 2761.1Sross 2771.1Sross aIsNaN = float64_is_nan( a ); 2781.1Sross aIsSignalingNaN = float64_is_signaling_nan( a ); 2791.1Sross bIsNaN = float64_is_nan( b ); 2801.1Sross bIsSignalingNaN = float64_is_signaling_nan( b ); 2811.1Sross a |= LIT64( 0x0008000000000000 ); 2821.1Sross b |= LIT64( 0x0008000000000000 ); 2831.1Sross if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 2841.1Sross if ( aIsSignalingNaN ) { 2851.1Sross if ( bIsSignalingNaN ) goto returnLargerSignificand; 2861.1Sross return bIsNaN ? b : a; 2871.1Sross } 2881.1Sross else if ( aIsNaN ) { 2891.1Sross if ( bIsSignalingNaN | ! bIsNaN ) return a; 2901.1Sross returnLargerSignificand: 2911.1Sross if ( (bits64) ( a<<1 ) < (bits64) ( b<<1 ) ) return b; 2921.1Sross if ( (bits64) ( b<<1 ) < (bits64) ( a<<1 ) ) return a; 2931.1Sross return ( a < b ) ? a : b; 2941.1Sross } 2951.1Sross else { 2961.1Sross return b; 2971.1Sross } 2981.1Sross 2991.1Sross} 3001.1Sross 3011.1Sross#ifdef FLOATX80 3021.1Sross 3031.1Sross/* 3041.1Sross------------------------------------------------------------------------------- 3051.1SrossThe pattern for a default generated extended double-precision NaN. The 3061.1Sross`high' and `low' values hold the most- and least-significant bits, 3071.1Srossrespectively. 3081.1Sross------------------------------------------------------------------------------- 3091.1Sross*/ 3101.1Sross#define floatx80_default_nan_high 0xFFFF 3111.1Sross#define floatx80_default_nan_low LIT64( 0xC000000000000000 ) 3121.1Sross 3131.1Sross/* 3141.1Sross------------------------------------------------------------------------------- 3151.1SrossReturns 1 if the extended double-precision floating-point value `a' is a 3161.1SrossNaN; otherwise returns 0. 3171.1Sross------------------------------------------------------------------------------- 3181.1Sross*/ 3191.1Srossstatic flag floatx80_is_nan( floatx80 a ) 3201.1Sross{ 3211.1Sross 3221.1Sross return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 ); 3231.1Sross 3241.1Sross} 3251.1Sross 3261.1Sross/* 3271.1Sross------------------------------------------------------------------------------- 3281.1SrossReturns 1 if the extended double-precision floating-point value `a' is a 3291.1Srosssignaling NaN; otherwise returns 0. 3301.1Sross------------------------------------------------------------------------------- 3311.1Sross*/ 3321.1Srossflag floatx80_is_signaling_nan( floatx80 a ) 3331.1Sross{ 3341.1Sross bits64 aLow; 3351.1Sross 3361.1Sross aLow = a.low & ~ LIT64( 0x4000000000000000 ); 3371.1Sross return 3381.1Sross ( ( a.high & 0x7FFF ) == 0x7FFF ) 3391.1Sross && (bits64) ( aLow<<1 ) 3401.1Sross && ( a.low == aLow ); 3411.1Sross 3421.1Sross} 3431.1Sross 3441.1Sross/* 3451.1Sross------------------------------------------------------------------------------- 3461.1SrossReturns the result of converting the extended double-precision floating- 3471.1Srosspoint NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the 3481.1Srossinvalid exception is raised. 3491.1Sross------------------------------------------------------------------------------- 3501.1Sross*/ 3511.1Srossstatic commonNaNT floatx80ToCommonNaN( floatx80 a ) 3521.1Sross{ 3531.1Sross commonNaNT z; 3541.1Sross 3551.1Sross if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 3561.1Sross z.sign = a.high>>15; 3571.1Sross z.low = 0; 3581.1Sross z.high = a.low<<1; 3591.1Sross return z; 3601.1Sross 3611.1Sross} 3621.1Sross 3631.1Sross/* 3641.1Sross------------------------------------------------------------------------------- 3651.1SrossReturns the result of converting the canonical NaN `a' to the extended 3661.1Srossdouble-precision floating-point format. 3671.1Sross------------------------------------------------------------------------------- 3681.1Sross*/ 3691.1Srossstatic floatx80 commonNaNToFloatx80( commonNaNT a ) 3701.1Sross{ 3711.1Sross floatx80 z; 3721.1Sross 3731.1Sross z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 ); 3741.1Sross z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF; 3751.1Sross return z; 3761.1Sross 3771.1Sross} 3781.1Sross 3791.1Sross/* 3801.1Sross------------------------------------------------------------------------------- 3811.1SrossTakes two extended double-precision floating-point values `a' and `b', one 3821.1Srossof which is a NaN, and returns the appropriate NaN result. If either `a' or 3831.1Sross`b' is a signaling NaN, the invalid exception is raised. 3841.1Sross------------------------------------------------------------------------------- 3851.1Sross*/ 3861.1Srossstatic floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b ) 3871.1Sross{ 3881.1Sross flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 3891.1Sross 3901.1Sross aIsNaN = floatx80_is_nan( a ); 3911.1Sross aIsSignalingNaN = floatx80_is_signaling_nan( a ); 3921.1Sross bIsNaN = floatx80_is_nan( b ); 3931.1Sross bIsSignalingNaN = floatx80_is_signaling_nan( b ); 3941.1Sross a.low |= LIT64( 0xC000000000000000 ); 3951.1Sross b.low |= LIT64( 0xC000000000000000 ); 3961.1Sross if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 3971.1Sross if ( aIsSignalingNaN ) { 3981.1Sross if ( bIsSignalingNaN ) goto returnLargerSignificand; 3991.1Sross return bIsNaN ? b : a; 4001.1Sross } 4011.1Sross else if ( aIsNaN ) { 4021.1Sross if ( bIsSignalingNaN | ! bIsNaN ) return a; 4031.1Sross returnLargerSignificand: 4041.1Sross if ( a.low < b.low ) return b; 4051.1Sross if ( b.low < a.low ) return a; 4061.1Sross return ( a.high < b.high ) ? a : b; 4071.1Sross } 4081.1Sross else { 4091.1Sross return b; 4101.1Sross } 4111.1Sross 4121.1Sross} 4131.1Sross 4141.1Sross#endif 4151.1Sross 4161.1Sross#ifdef FLOAT128 4171.1Sross 4181.1Sross/* 4191.1Sross------------------------------------------------------------------------------- 4201.1SrossThe pattern for a default generated quadruple-precision NaN. The `high' and 4211.1Sross`low' values hold the most- and least-significant bits, respectively. 4221.1Sross------------------------------------------------------------------------------- 4231.1Sross*/ 4241.1Sross#define float128_default_nan_high LIT64( 0xFFFF800000000000 ) 4251.1Sross#define float128_default_nan_low LIT64( 0x0000000000000000 ) 4261.1Sross 4271.1Sross/* 4281.1Sross------------------------------------------------------------------------------- 4291.1SrossReturns 1 if the quadruple-precision floating-point value `a' is a NaN; 4301.1Srossotherwise returns 0. 4311.1Sross------------------------------------------------------------------------------- 4321.1Sross*/ 4331.1Srossflag float128_is_nan( float128 a ) 4341.1Sross{ 4351.1Sross 4361.1Sross return 4371.1Sross ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) ) 4381.1Sross && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) ); 4391.1Sross 4401.1Sross} 4411.1Sross 4421.1Sross/* 4431.1Sross------------------------------------------------------------------------------- 4441.1SrossReturns 1 if the quadruple-precision floating-point value `a' is a 4451.1Srosssignaling NaN; otherwise returns 0. 4461.1Sross------------------------------------------------------------------------------- 4471.1Sross*/ 4481.1Srossflag float128_is_signaling_nan( float128 a ) 4491.1Sross{ 4501.1Sross 4511.1Sross return 4521.1Sross ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE ) 4531.1Sross && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) ); 4541.1Sross 4551.1Sross} 4561.1Sross 4571.1Sross/* 4581.1Sross------------------------------------------------------------------------------- 4591.1SrossReturns the result of converting the quadruple-precision floating-point NaN 4601.1Sross`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 4611.1Srossexception is raised. 4621.1Sross------------------------------------------------------------------------------- 4631.1Sross*/ 4641.1Srossstatic commonNaNT float128ToCommonNaN( float128 a ) 4651.1Sross{ 4661.1Sross commonNaNT z; 4671.1Sross 4681.1Sross if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 4691.1Sross z.sign = a.high>>63; 4701.1Sross shortShift128Left( a.high, a.low, 16, &z.high, &z.low ); 4711.1Sross return z; 4721.1Sross 4731.1Sross} 4741.1Sross 4751.1Sross/* 4761.1Sross------------------------------------------------------------------------------- 4771.1SrossReturns the result of converting the canonical NaN `a' to the quadruple- 4781.1Srossprecision floating-point format. 4791.1Sross------------------------------------------------------------------------------- 4801.1Sross*/ 4811.1Srossstatic float128 commonNaNToFloat128( commonNaNT a ) 4821.1Sross{ 4831.1Sross float128 z; 4841.1Sross 4851.1Sross shift128Right( a.high, a.low, 16, &z.high, &z.low ); 4861.1Sross z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 ); 4871.1Sross return z; 4881.1Sross 4891.1Sross} 4901.1Sross 4911.1Sross/* 4921.1Sross------------------------------------------------------------------------------- 4931.1SrossTakes two quadruple-precision floating-point values `a' and `b', one of 4941.1Srosswhich is a NaN, and returns the appropriate NaN result. If either `a' or 4951.1Sross`b' is a signaling NaN, the invalid exception is raised. 4961.1Sross------------------------------------------------------------------------------- 4971.1Sross*/ 4981.1Srossstatic float128 propagateFloat128NaN( float128 a, float128 b ) 4991.1Sross{ 5001.1Sross flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 5011.1Sross 5021.1Sross aIsNaN = float128_is_nan( a ); 5031.1Sross aIsSignalingNaN = float128_is_signaling_nan( a ); 5041.1Sross bIsNaN = float128_is_nan( b ); 5051.1Sross bIsSignalingNaN = float128_is_signaling_nan( b ); 5061.1Sross a.high |= LIT64( 0x0000800000000000 ); 5071.1Sross b.high |= LIT64( 0x0000800000000000 ); 5081.1Sross if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 5091.1Sross if ( aIsSignalingNaN ) { 5101.1Sross if ( bIsSignalingNaN ) goto returnLargerSignificand; 5111.1Sross return bIsNaN ? b : a; 5121.1Sross } 5131.1Sross else if ( aIsNaN ) { 5141.1Sross if ( bIsSignalingNaN | ! bIsNaN ) return a; 5151.1Sross returnLargerSignificand: 5161.1Sross if ( lt128( a.high<<1, a.low, b.high<<1, b.low ) ) return b; 5171.1Sross if ( lt128( b.high<<1, b.low, a.high<<1, a.low ) ) return a; 5181.1Sross return ( a.high < b.high ) ? a : b; 5191.1Sross } 5201.1Sross else { 5211.1Sross return b; 5221.1Sross } 5231.1Sross 5241.1Sross} 5251.1Sross 5261.1Sross#endif 5271.1Sross 528