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