xref: /netbsd-src/regress/lib/libc/ieeefp/testfloat/include/softfloat-specialize (revision ce099b40997c43048fb78bd578195f81d2456523)
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