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