Home | History | Annotate | Line # | Download | only in libkern
      1  1.3  thorpej /* $NetBSD: softfloat-specialize.h,v 1.3 2020/09/02 03:41:56 thorpej Exp $ */
      2  1.1     ross 
      3  1.1     ross /* This is a derivative work. */
      4  1.1     ross 
      5  1.1     ross /*-
      6  1.1     ross  * Copyright (c) 2001 The NetBSD Foundation, Inc.
      7  1.1     ross  * All rights reserved.
      8  1.1     ross  *
      9  1.1     ross  * This code is derived from software contributed to The NetBSD Foundation
     10  1.1     ross  * by Ross Harvey.
     11  1.1     ross  *
     12  1.1     ross  * Redistribution and use in source and binary forms, with or without
     13  1.1     ross  * modification, are permitted provided that the following conditions
     14  1.1     ross  * are met:
     15  1.1     ross  * 1. Redistributions of source code must retain the above copyright
     16  1.1     ross  *    notice, this list of conditions and the following disclaimer.
     17  1.1     ross  * 2. Redistributions in binary form must reproduce the above copyright
     18  1.1     ross  *    notice, this list of conditions and the following disclaimer in the
     19  1.1     ross  *    documentation and/or other materials provided with the distribution.
     20  1.1     ross  *
     21  1.1     ross  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     22  1.1     ross  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     23  1.1     ross  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     24  1.1     ross  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     25  1.1     ross  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     26  1.1     ross  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     27  1.1     ross  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     28  1.1     ross  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     29  1.1     ross  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     30  1.1     ross  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     31  1.1     ross  * POSSIBILITY OF SUCH DAMAGE.
     32  1.1     ross  */
     33  1.1     ross 
     34  1.3  thorpej /*============================================================================
     35  1.1     ross 
     36  1.3  thorpej This C source fragment is part of the Berkeley SoftFloat IEEE Floating-Point
     37  1.3  thorpej Arithmetic Package, Release 2c, by John R. Hauser.
     38  1.1     ross 
     39  1.3  thorpej THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort has
     40  1.3  thorpej been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
     41  1.3  thorpej RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
     42  1.3  thorpej AND ORGANIZATIONS WHO CAN AND WILL TOLERATE ALL LOSSES, COSTS, OR OTHER
     43  1.3  thorpej PROBLEMS THEY INCUR DUE TO THE SOFTWARE WITHOUT RECOMPENSE FROM JOHN HAUSER OR
     44  1.3  thorpej THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE, AND WHO FURTHERMORE EFFECTIVELY
     45  1.3  thorpej INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE
     46  1.3  thorpej (possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR OTHER
     47  1.3  thorpej PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE, OR
     48  1.3  thorpej INCURRED BY ANYONE DUE TO A DERIVATIVE WORK THEY CREATE USING ANY PART OF THE
     49  1.3  thorpej SOFTWARE.
     50  1.3  thorpej 
     51  1.3  thorpej Derivative works require also that (1) the source code for the derivative work
     52  1.3  thorpej includes prominent notice that the work is derivative, and (2) the source code
     53  1.3  thorpej includes prominent notice of these three paragraphs for those parts of this
     54  1.3  thorpej code that are retained.
     55  1.3  thorpej 
     56  1.3  thorpej =============================================================================*/
     57  1.3  thorpej 
     58  1.3  thorpej /*----------------------------------------------------------------------------
     59  1.3  thorpej | Underflow tininess-detection mode, statically initialized to default value.
     60  1.3  thorpej | (The declaration in `softfloat.h' must match the `int8' type here.)
     61  1.3  thorpej *----------------------------------------------------------------------------*/
     62  1.1     ross /* [ MP safe, does not change dynamically ] */
     63  1.1     ross int float_detect_tininess = float_tininess_after_rounding;
     64  1.1     ross 
     65  1.3  thorpej /*----------------------------------------------------------------------------
     66  1.3  thorpej | Internal canonical NaN format.
     67  1.3  thorpej *----------------------------------------------------------------------------*/
     68  1.1     ross typedef struct {
     69  1.1     ross     flag sign;
     70  1.1     ross     bits64 high, low;
     71  1.1     ross } commonNaNT;
     72  1.1     ross 
     73  1.3  thorpej /*----------------------------------------------------------------------------
     74  1.3  thorpej | The pattern for a default generated single-precision NaN.
     75  1.3  thorpej *----------------------------------------------------------------------------*/
     76  1.1     ross #define float32_default_nan 0xFFC00000
     77  1.1     ross 
     78  1.3  thorpej /*----------------------------------------------------------------------------
     79  1.3  thorpej | Returns 1 if the single-precision floating-point value `a' is a NaN;
     80  1.3  thorpej | otherwise returns 0.
     81  1.3  thorpej *----------------------------------------------------------------------------*/
     82  1.3  thorpej 
     83  1.1     ross static flag float32_is_nan( float32 a )
     84  1.1     ross {
     85  1.1     ross 
     86  1.1     ross     return ( 0xFF000000 < (bits32) ( a<<1 ) );
     87  1.1     ross 
     88  1.1     ross }
     89  1.1     ross 
     90  1.3  thorpej /*----------------------------------------------------------------------------
     91  1.3  thorpej | Returns 1 if the single-precision floating-point value `a' is a signaling
     92  1.3  thorpej | NaN; otherwise returns 0.
     93  1.3  thorpej *----------------------------------------------------------------------------*/
     94  1.3  thorpej 
     95  1.1     ross flag float32_is_signaling_nan( float32 a )
     96  1.1     ross {
     97  1.1     ross 
     98  1.1     ross     return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
     99  1.1     ross 
    100  1.1     ross }
    101  1.1     ross 
    102  1.3  thorpej /*----------------------------------------------------------------------------
    103  1.3  thorpej | Returns the result of converting the single-precision floating-point NaN
    104  1.3  thorpej | `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
    105  1.3  thorpej | exception is raised.
    106  1.3  thorpej *----------------------------------------------------------------------------*/
    107  1.3  thorpej 
    108  1.1     ross static commonNaNT float32ToCommonNaN( float32 a )
    109  1.1     ross {
    110  1.1     ross     commonNaNT z;
    111  1.1     ross 
    112  1.1     ross     if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
    113  1.1     ross     z.sign = a>>31;
    114  1.1     ross     z.low = 0;
    115  1.1     ross     z.high = ( (bits64) a )<<41;
    116  1.1     ross     return z;
    117  1.1     ross 
    118  1.1     ross }
    119  1.1     ross 
    120  1.3  thorpej /*----------------------------------------------------------------------------
    121  1.3  thorpej | Returns the result of converting the canonical NaN `a' to the single-
    122  1.3  thorpej | precision floating-point format.
    123  1.3  thorpej *----------------------------------------------------------------------------*/
    124  1.3  thorpej 
    125  1.1     ross static float32 commonNaNToFloat32( commonNaNT a )
    126  1.1     ross {
    127  1.1     ross 
    128  1.1     ross     return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 );
    129  1.1     ross 
    130  1.1     ross }
    131  1.1     ross 
    132  1.3  thorpej /*----------------------------------------------------------------------------
    133  1.3  thorpej | Takes two single-precision floating-point values `a' and `b', one of which
    134  1.3  thorpej | is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
    135  1.3  thorpej | signaling NaN, the invalid exception is raised.
    136  1.3  thorpej *----------------------------------------------------------------------------*/
    137  1.3  thorpej 
    138  1.1     ross static float32 propagateFloat32NaN( float32 a, float32 b )
    139  1.1     ross {
    140  1.1     ross     flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
    141  1.1     ross 
    142  1.1     ross     aIsNaN = float32_is_nan( a );
    143  1.1     ross     aIsSignalingNaN = float32_is_signaling_nan( a );
    144  1.1     ross     bIsNaN = float32_is_nan( b );
    145  1.1     ross     bIsSignalingNaN = float32_is_signaling_nan( b );
    146  1.1     ross     a |= 0x00400000;
    147  1.1     ross     b |= 0x00400000;
    148  1.1     ross     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
    149  1.1     ross     if ( aIsSignalingNaN ) {
    150  1.1     ross         if ( bIsSignalingNaN ) goto returnLargerSignificand;
    151  1.1     ross         return bIsNaN ? b : a;
    152  1.1     ross     }
    153  1.1     ross     else if ( aIsNaN ) {
    154  1.1     ross         if ( bIsSignalingNaN | ! bIsNaN ) return a;
    155  1.1     ross  returnLargerSignificand:
    156  1.1     ross         if ( (bits32) ( a<<1 ) < (bits32) ( b<<1 ) ) return b;
    157  1.1     ross         if ( (bits32) ( b<<1 ) < (bits32) ( a<<1 ) ) return a;
    158  1.1     ross         return ( a < b ) ? a : b;
    159  1.1     ross     }
    160  1.1     ross     else {
    161  1.1     ross         return b;
    162  1.1     ross     }
    163  1.1     ross 
    164  1.1     ross }
    165  1.1     ross 
    166  1.3  thorpej /*
    167  1.3  thorpej  * float64_default_nan, float64_is_nan(), float64_is_signaling_nan()
    168  1.3  thorpej  * have moved to softfloat.h.
    169  1.3  thorpej  */
    170  1.3  thorpej 
    171  1.3  thorpej /*----------------------------------------------------------------------------
    172  1.3  thorpej | Returns the result of converting the double-precision floating-point NaN
    173  1.3  thorpej | `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
    174  1.3  thorpej | exception is raised.
    175  1.3  thorpej *----------------------------------------------------------------------------*/
    176  1.1     ross 
    177  1.1     ross static commonNaNT float64ToCommonNaN( float64 a )
    178  1.1     ross {
    179  1.1     ross     commonNaNT z;
    180  1.1     ross 
    181  1.1     ross     if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
    182  1.1     ross     z.sign = a>>63;
    183  1.1     ross     z.low = 0;
    184  1.1     ross     z.high = a<<12;
    185  1.1     ross     return z;
    186  1.1     ross 
    187  1.1     ross }
    188  1.1     ross 
    189  1.3  thorpej /*----------------------------------------------------------------------------
    190  1.3  thorpej | Returns the result of converting the canonical NaN `a' to the double-
    191  1.3  thorpej | precision floating-point format.
    192  1.3  thorpej *----------------------------------------------------------------------------*/
    193  1.3  thorpej 
    194  1.1     ross static float64 commonNaNToFloat64( commonNaNT a )
    195  1.1     ross {
    196  1.1     ross 
    197  1.1     ross     return
    198  1.1     ross           ( ( (bits64) a.sign )<<63 )
    199  1.1     ross         | LIT64( 0x7FF8000000000000 )
    200  1.1     ross         | ( a.high>>12 );
    201  1.1     ross 
    202  1.1     ross }
    203  1.1     ross 
    204  1.3  thorpej /*----------------------------------------------------------------------------
    205  1.3  thorpej | Takes two double-precision floating-point values `a' and `b', one of which
    206  1.3  thorpej | is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
    207  1.3  thorpej | signaling NaN, the invalid exception is raised.
    208  1.3  thorpej *----------------------------------------------------------------------------*/
    209  1.3  thorpej 
    210  1.1     ross static float64 propagateFloat64NaN( float64 a, float64 b )
    211  1.1     ross {
    212  1.1     ross     flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
    213  1.1     ross 
    214  1.1     ross     aIsNaN = float64_is_nan( a );
    215  1.1     ross     aIsSignalingNaN = float64_is_signaling_nan( a );
    216  1.1     ross     bIsNaN = float64_is_nan( b );
    217  1.1     ross     bIsSignalingNaN = float64_is_signaling_nan( b );
    218  1.1     ross     a |= LIT64( 0x0008000000000000 );
    219  1.1     ross     b |= LIT64( 0x0008000000000000 );
    220  1.1     ross     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
    221  1.1     ross     if ( aIsSignalingNaN ) {
    222  1.1     ross         if ( bIsSignalingNaN ) goto returnLargerSignificand;
    223  1.1     ross         return bIsNaN ? b : a;
    224  1.1     ross     }
    225  1.1     ross     else if ( aIsNaN ) {
    226  1.1     ross         if ( bIsSignalingNaN | ! bIsNaN ) return a;
    227  1.1     ross  returnLargerSignificand:
    228  1.1     ross         if ( (bits64) ( a<<1 ) < (bits64) ( b<<1 ) ) return b;
    229  1.1     ross         if ( (bits64) ( b<<1 ) < (bits64) ( a<<1 ) ) return a;
    230  1.1     ross         return ( a < b ) ? a : b;
    231  1.1     ross     }
    232  1.1     ross     else {
    233  1.1     ross         return b;
    234  1.1     ross     }
    235  1.1     ross 
    236  1.1     ross }
    237  1.1     ross 
    238  1.1     ross #ifdef FLOATX80
    239  1.1     ross 
    240  1.3  thorpej /*----------------------------------------------------------------------------
    241  1.3  thorpej | The pattern for a default generated double-extended-precision NaN.
    242  1.3  thorpej | The `high' and `low' values hold the most- and least-significant bits,
    243  1.3  thorpej | respectively.
    244  1.3  thorpej *----------------------------------------------------------------------------*/
    245  1.1     ross #define floatx80_default_nan_high 0xFFFF
    246  1.1     ross #define floatx80_default_nan_low  LIT64( 0xC000000000000000 )
    247  1.1     ross 
    248  1.3  thorpej /*----------------------------------------------------------------------------
    249  1.3  thorpej | Returns 1 if the double-extended-precision floating-point value `a' is a
    250  1.3  thorpej | NaN; otherwise returns 0.
    251  1.3  thorpej *----------------------------------------------------------------------------*/
    252  1.3  thorpej 
    253  1.1     ross static flag floatx80_is_nan( floatx80 a )
    254  1.1     ross {
    255  1.1     ross 
    256  1.1     ross     return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
    257  1.1     ross 
    258  1.1     ross }
    259  1.1     ross 
    260  1.3  thorpej /*----------------------------------------------------------------------------
    261  1.3  thorpej | Returns 1 if the double-extended-precision floating-point value `a' is a
    262  1.3  thorpej | signaling NaN; otherwise returns 0.
    263  1.3  thorpej *----------------------------------------------------------------------------*/
    264  1.3  thorpej 
    265  1.1     ross flag floatx80_is_signaling_nan( floatx80 a )
    266  1.1     ross {
    267  1.1     ross     bits64 aLow;
    268  1.1     ross 
    269  1.1     ross     aLow = a.low & ~ LIT64( 0x4000000000000000 );
    270  1.1     ross     return
    271  1.1     ross            ( ( a.high & 0x7FFF ) == 0x7FFF )
    272  1.1     ross         && (bits64) ( aLow<<1 )
    273  1.1     ross         && ( a.low == aLow );
    274  1.1     ross 
    275  1.1     ross }
    276  1.1     ross 
    277  1.3  thorpej /*----------------------------------------------------------------------------
    278  1.3  thorpej | Returns the result of converting the double-extended-precision floating-
    279  1.3  thorpej | point NaN `a' to the canonical NaN format.  If `a' is a signaling NaN, the
    280  1.3  thorpej | invalid exception is raised.
    281  1.3  thorpej *----------------------------------------------------------------------------*/
    282  1.3  thorpej 
    283  1.1     ross static commonNaNT floatx80ToCommonNaN( floatx80 a )
    284  1.1     ross {
    285  1.1     ross     commonNaNT z;
    286  1.1     ross 
    287  1.1     ross     if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
    288  1.1     ross     z.sign = a.high>>15;
    289  1.1     ross     z.low = 0;
    290  1.1     ross     z.high = a.low<<1;
    291  1.1     ross     return z;
    292  1.1     ross 
    293  1.1     ross }
    294  1.1     ross 
    295  1.3  thorpej /*----------------------------------------------------------------------------
    296  1.3  thorpej | Returns the result of converting the canonical NaN `a' to the double-
    297  1.3  thorpej | extended-precision floating-point format.
    298  1.3  thorpej *----------------------------------------------------------------------------*/
    299  1.3  thorpej 
    300  1.1     ross static floatx80 commonNaNToFloatx80( commonNaNT a )
    301  1.1     ross {
    302  1.1     ross     floatx80 z;
    303  1.1     ross 
    304  1.1     ross     z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
    305  1.1     ross     z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
    306  1.1     ross     return z;
    307  1.1     ross 
    308  1.1     ross }
    309  1.1     ross 
    310  1.3  thorpej /*----------------------------------------------------------------------------
    311  1.3  thorpej | Takes two double-extended-precision floating-point values `a' and `b', one
    312  1.3  thorpej | of which is a NaN, and returns the appropriate NaN result.  If either `a' or
    313  1.3  thorpej | `b' is a signaling NaN, the invalid exception is raised.
    314  1.3  thorpej *----------------------------------------------------------------------------*/
    315  1.3  thorpej 
    316  1.1     ross static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b )
    317  1.1     ross {
    318  1.1     ross     flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
    319  1.1     ross 
    320  1.1     ross     aIsNaN = floatx80_is_nan( a );
    321  1.1     ross     aIsSignalingNaN = floatx80_is_signaling_nan( a );
    322  1.1     ross     bIsNaN = floatx80_is_nan( b );
    323  1.1     ross     bIsSignalingNaN = floatx80_is_signaling_nan( b );
    324  1.1     ross     a.low |= LIT64( 0xC000000000000000 );
    325  1.1     ross     b.low |= LIT64( 0xC000000000000000 );
    326  1.1     ross     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
    327  1.1     ross     if ( aIsSignalingNaN ) {
    328  1.1     ross         if ( bIsSignalingNaN ) goto returnLargerSignificand;
    329  1.1     ross         return bIsNaN ? b : a;
    330  1.1     ross     }
    331  1.1     ross     else if ( aIsNaN ) {
    332  1.1     ross         if ( bIsSignalingNaN | ! bIsNaN ) return a;
    333  1.1     ross  returnLargerSignificand:
    334  1.1     ross         if ( a.low < b.low ) return b;
    335  1.1     ross         if ( b.low < a.low ) return a;
    336  1.1     ross         return ( a.high < b.high ) ? a : b;
    337  1.1     ross     }
    338  1.1     ross     else {
    339  1.1     ross         return b;
    340  1.1     ross     }
    341  1.1     ross 
    342  1.1     ross }
    343  1.1     ross 
    344  1.1     ross #endif
    345  1.1     ross 
    346  1.1     ross #ifdef FLOAT128
    347  1.1     ross 
    348  1.3  thorpej /*----------------------------------------------------------------------------
    349  1.3  thorpej | The pattern for a default generated quadruple-precision NaN.  The `high' and
    350  1.3  thorpej | `low' values hold the most- and least-significant bits, respectively.
    351  1.3  thorpej *----------------------------------------------------------------------------*/
    352  1.1     ross #define float128_default_nan_high LIT64( 0xFFFF800000000000 )
    353  1.1     ross #define float128_default_nan_low  LIT64( 0x0000000000000000 )
    354  1.1     ross 
    355  1.3  thorpej /*----------------------------------------------------------------------------
    356  1.3  thorpej | Returns 1 if the quadruple-precision floating-point value `a' is a NaN;
    357  1.3  thorpej | otherwise returns 0.
    358  1.3  thorpej *----------------------------------------------------------------------------*/
    359  1.3  thorpej 
    360  1.1     ross flag float128_is_nan( float128 a )
    361  1.1     ross {
    362  1.1     ross 
    363  1.1     ross     return
    364  1.1     ross            ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
    365  1.1     ross         && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
    366  1.1     ross 
    367  1.1     ross }
    368  1.1     ross 
    369  1.3  thorpej /*----------------------------------------------------------------------------
    370  1.3  thorpej | Returns 1 if the quadruple-precision floating-point value `a' is a
    371  1.3  thorpej | signaling NaN; otherwise returns 0.
    372  1.3  thorpej *----------------------------------------------------------------------------*/
    373  1.3  thorpej 
    374  1.1     ross flag float128_is_signaling_nan( float128 a )
    375  1.1     ross {
    376  1.1     ross 
    377  1.1     ross     return
    378  1.1     ross            ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
    379  1.1     ross         && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
    380  1.1     ross 
    381  1.1     ross }
    382  1.1     ross 
    383  1.3  thorpej /*----------------------------------------------------------------------------
    384  1.3  thorpej | Returns the result of converting the quadruple-precision floating-point NaN
    385  1.3  thorpej | `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
    386  1.3  thorpej | exception is raised.
    387  1.3  thorpej *----------------------------------------------------------------------------*/
    388  1.3  thorpej 
    389  1.1     ross static commonNaNT float128ToCommonNaN( float128 a )
    390  1.1     ross {
    391  1.1     ross     commonNaNT z;
    392  1.1     ross 
    393  1.1     ross     if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
    394  1.1     ross     z.sign = a.high>>63;
    395  1.1     ross     shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
    396  1.1     ross     return z;
    397  1.1     ross 
    398  1.1     ross }
    399  1.1     ross 
    400  1.3  thorpej /*----------------------------------------------------------------------------
    401  1.3  thorpej | Returns the result of converting the canonical NaN `a' to the quadruple-
    402  1.3  thorpej | precision floating-point format.
    403  1.3  thorpej *----------------------------------------------------------------------------*/
    404  1.3  thorpej 
    405  1.1     ross static float128 commonNaNToFloat128( commonNaNT a )
    406  1.1     ross {
    407  1.1     ross     float128 z;
    408  1.1     ross 
    409  1.1     ross     shift128Right( a.high, a.low, 16, &z.high, &z.low );
    410  1.1     ross     z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 );
    411  1.1     ross     return z;
    412  1.1     ross 
    413  1.1     ross }
    414  1.1     ross 
    415  1.3  thorpej /*----------------------------------------------------------------------------
    416  1.3  thorpej | Takes two quadruple-precision floating-point values `a' and `b', one of
    417  1.3  thorpej | which is a NaN, and returns the appropriate NaN result.  If either `a' or
    418  1.3  thorpej | `b' is a signaling NaN, the invalid exception is raised.
    419  1.3  thorpej *----------------------------------------------------------------------------*/
    420  1.3  thorpej 
    421  1.1     ross static float128 propagateFloat128NaN( float128 a, float128 b )
    422  1.1     ross {
    423  1.1     ross     flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
    424  1.1     ross 
    425  1.1     ross     aIsNaN = float128_is_nan( a );
    426  1.1     ross     aIsSignalingNaN = float128_is_signaling_nan( a );
    427  1.1     ross     bIsNaN = float128_is_nan( b );
    428  1.1     ross     bIsSignalingNaN = float128_is_signaling_nan( b );
    429  1.1     ross     a.high |= LIT64( 0x0000800000000000 );
    430  1.1     ross     b.high |= LIT64( 0x0000800000000000 );
    431  1.1     ross     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
    432  1.1     ross     if ( aIsSignalingNaN ) {
    433  1.1     ross         if ( bIsSignalingNaN ) goto returnLargerSignificand;
    434  1.1     ross         return bIsNaN ? b : a;
    435  1.1     ross     }
    436  1.1     ross     else if ( aIsNaN ) {
    437  1.1     ross         if ( bIsSignalingNaN | ! bIsNaN ) return a;
    438  1.1     ross  returnLargerSignificand:
    439  1.1     ross         if ( lt128( a.high<<1, a.low, b.high<<1, b.low ) ) return b;
    440  1.1     ross         if ( lt128( b.high<<1, b.low, a.high<<1, a.low ) ) return a;
    441  1.1     ross         return ( a.high < b.high ) ? a : b;
    442  1.1     ross     }
    443  1.1     ross     else {
    444  1.1     ross         return b;
    445  1.1     ross     }
    446  1.1     ross 
    447  1.1     ross }
    448  1.1     ross 
    449  1.1     ross #endif
    450  1.1     ross 
    451