bool f128_le( float128_t a, float128_t b ) { union ui128_f128 uA; uint_fast64_t uiA64, uiA0; union ui128_f128 uB; uint_fast64_t uiB64, uiB0; bool signA, signB; uA.f = a; uiA64 = uA.ui.v64; uiA0 = uA.ui.v0; uB.f = b; uiB64 = uB.ui.v64; uiB0 = uB.ui.v0; if ( isNaNF128UI( uiA64, uiA0 ) || isNaNF128UI( uiB64, uiB0 ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); return false; } signA = signF128UI64( uiA64 ); signB = signF128UI64( uiB64 ); return (signA != signB) ? signA || ! (((uiA64 | uiB64) & UINT64_C( 0x7FFFFFFFFFFFFFFF )) | uiA0 | uiB0) : ((uiA64 == uiB64) && (uiA0 == uiB0)) || (signA ^ softfloat_lt128( uiA64, uiA0, uiB64, uiB0 )); }
bool f128_eq( float128_t a, float128_t b ) { union ui128_f128 uA; uint_fast64_t uiA64, uiA0; union ui128_f128 uB; uint_fast64_t uiB64, uiB0; uA.f = a; uiA64 = uA.ui.v64; uiA0 = uA.ui.v0; uB.f = b; uiB64 = uB.ui.v64; uiB0 = uB.ui.v0; if ( isNaNF128UI( uiA64, uiA0 ) || isNaNF128UI( uiB64, uiB0 ) ) { if ( softfloat_isSigNaNF128UI( uiA64, uiA0 ) || softfloat_isSigNaNF128UI( uiB64, uiB0 ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); } return false; } return (uiA0 == uiB0) && ( (uiA64 == uiB64) || (! uiA0 && ! ((uiA64 | uiB64) & UINT64_C( 0x7FFFFFFFFFFFFFFF ))) ); }
/*---------------------------------------------------------------------------- | Interpreting the unsigned integer formed from concatenating 'uiA64' and | 'uiA0' as a 128-bit floating-point value, and likewise interpreting the | unsigned integer formed from concatenating 'uiB64' and 'uiB0' as another | 128-bit floating-point value, and assuming at least on of these floating- | point values is a NaN, returns the bit pattern of the combined NaN result. | If either original floating-point value is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ struct uint128 softfloat_propagateNaNF128UI( uint_fast64_t uiA64, uint_fast64_t uiA0, uint_fast64_t uiB64, uint_fast64_t uiB0 ) { bool isSigNaNA, isSigNaNB; uint_fast64_t uiNonsigA64, uiNonsigB64, uiMagA64, uiMagB64; struct uint128 uiZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ isSigNaNA = softfloat_isSigNaNF128UI( uiA64, uiA0 ); isSigNaNB = softfloat_isSigNaNF128UI( uiB64, uiB0 ); /*------------------------------------------------------------------------ | Make NaNs non-signaling. *------------------------------------------------------------------------*/ uiNonsigA64 = uiA64 | UINT64_C( 0x0000800000000000 ); uiNonsigB64 = uiB64 | UINT64_C( 0x0000800000000000 ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( isSigNaNA | isSigNaNB ) { softfloat_raiseFlags( softfloat_flag_invalid ); if ( isSigNaNA ) { if ( isSigNaNB ) goto returnLargerMag; if ( isNaNF128UI( uiB64, uiB0 ) ) goto returnB; goto returnA; } else { if ( isNaNF128UI( uiA64, uiA0 ) ) goto returnA; goto returnB; } } returnLargerMag: uiMagA64 = uiA64 & UINT64_C( 0x7FFFFFFFFFFFFFFF ); uiMagB64 = uiB64 & UINT64_C( 0x7FFFFFFFFFFFFFFF ); if ( uiMagA64 < uiMagB64 ) goto returnB; if ( uiMagB64 < uiMagA64 ) goto returnA; if ( uiA0 < uiB0 ) goto returnB; if ( uiB0 < uiA0 ) goto returnA; if ( uiNonsigA64 < uiNonsigB64 ) goto returnA; returnB: uiZ.v64 = uiNonsigB64; uiZ.v0 = uiB0; return uiZ; returnA: uiZ.v64 = uiNonsigA64; uiZ.v0 = uiA0; return uiZ; }
/*---------------------------------------------------------------------------- | Interpreting the unsigned integer formed from concatenating `uiA64' and | `uiA0' as a 128-bit floating-point value, and likewise interpreting the | unsigned integer formed from concatenating `uiB64' and `uiB0' as another | 128-bit floating-point value, and assuming at least on of these floating- | point values is a NaN, returns the bit pattern of the combined NaN result. | If either original floating-point value is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ struct uint128 softfloat_propagateNaNF128UI( uint_fast64_t uiA64, uint_fast64_t uiA0, uint_fast64_t uiB64, uint_fast64_t uiB0 ) { bool isSigNaNA; struct uint128 uiZ; isSigNaNA = softfloat_isSigNaNF128UI( uiA64, uiA0 ); if ( isSigNaNA || softfloat_isSigNaNF128UI( uiB64, uiB0 ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); if ( isSigNaNA ) goto returnNonsigA; } if ( isNaNF128UI( uiA64, uiA0 ) ) { returnNonsigA: uiZ.v64 = uiA64; uiZ.v0 = uiA0; } else { uiZ.v64 = uiB64; uiZ.v0 = uiB0; } uiZ.v64 |= UINT64_C( 0x0000800000000000 ); return uiZ; }
uint_fast16_t f128_classify( float128_t a ) { union ui128_f128 uA; uint_fast64_t uiA64, uiA0; uA.f = a; uiA64 = uA.ui.v64; uiA0 = uA.ui.v0; uint_fast16_t infOrNaN = expF128UI64( uiA64 ) == 0x7FFF; uint_fast16_t subnormalOrZero = expF128UI64( uiA64 ) == 0; bool sign = signF128UI64( uiA64 ); bool fracZero = fracF128UI64( uiA64 ) == 0 && uiA0 == 0; bool isNaN = isNaNF128UI( uiA64, uiA0 ); bool isSNaN = softfloat_isSigNaNF128UI( uiA64, uiA0 ); return ( sign && infOrNaN && fracZero ) << 0 | ( sign && !infOrNaN && !subnormalOrZero ) << 1 | ( sign && subnormalOrZero && !fracZero ) << 2 | ( sign && subnormalOrZero && fracZero ) << 3 | ( !sign && infOrNaN && fracZero ) << 7 | ( !sign && !infOrNaN && !subnormalOrZero ) << 6 | ( !sign && subnormalOrZero && !fracZero ) << 5 | ( !sign && subnormalOrZero && fracZero ) << 4 | ( isNaN && isSNaN ) << 8 | ( isNaN && !isSNaN ) << 9; }