/*---------------------------------------------------------------------------- | Assuming at least one of the two 128-bit floating-point values pointed to by | `aWPtr' and `bWPtr' is a NaN, stores the combined NaN result at the location | pointed to by `zWPtr'. If either original floating-point value is a | signaling NaN, the invalid exception is raised. Each of `aWPtr', `bWPtr', | and `zWPtr' points to an array of four 32-bit elements that concatenate in | the platform's normal endian order to form a 128-bit floating-point value. *----------------------------------------------------------------------------*/ void softfloat_propagateNaNF128M( const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr ) { bool isSigNaNA; const uint32_t *ptr; bool isSigNaNB; uint32_t uiA96, uiB96, wordMagA, wordMagB; isSigNaNA = f128M_isSignalingNaN( (const float128_t *) aWPtr ); ptr = aWPtr; if ( ! bWPtr ) { if ( isSigNaNA ) softfloat_raiseFlags( softfloat_flag_invalid ); goto copy; } isSigNaNB = f128M_isSignalingNaN( (const float128_t *) bWPtr ); if ( isSigNaNA | isSigNaNB ) { softfloat_raiseFlags( softfloat_flag_invalid ); if ( isSigNaNA ) { if ( isSigNaNB ) goto returnLargerUIMag; if ( softfloat_isNaNF128M( bWPtr ) ) goto copyB; goto copy; } else { if ( softfloat_isNaNF128M( aWPtr ) ) goto copy; goto copyB; } } returnLargerUIMag: uiA96 = aWPtr[indexWordHi( 4 )]; uiB96 = bWPtr[indexWordHi( 4 )]; wordMagA = uiA96 & 0x7FFFFFFF; wordMagB = uiB96 & 0x7FFFFFFF; if ( wordMagA < wordMagB ) goto copyB; if ( wordMagB < wordMagA ) goto copy; wordMagA = aWPtr[indexWord( 4, 2 )]; wordMagB = bWPtr[indexWord( 4, 2 )]; if ( wordMagA < wordMagB ) goto copyB; if ( wordMagB < wordMagA ) goto copy; wordMagA = aWPtr[indexWord( 4, 1 )]; wordMagB = bWPtr[indexWord( 4, 1 )]; if ( wordMagA < wordMagB ) goto copyB; if ( wordMagB < wordMagA ) goto copy; wordMagA = aWPtr[indexWord( 4, 0 )]; wordMagB = bWPtr[indexWord( 4, 0 )]; if ( wordMagA < wordMagB ) goto copyB; if ( wordMagB < wordMagA ) goto copy; if ( uiA96 < uiB96 ) goto copy; copyB: ptr = bWPtr; copy: zWPtr[indexWordHi( 4 )] = ptr[indexWordHi( 4 )] | 0x00008000; zWPtr[indexWord( 4, 2 )] = ptr[indexWord( 4, 2 )]; zWPtr[indexWord( 4, 1 )] = ptr[indexWord( 4, 1 )]; zWPtr[indexWord( 4, 0 )] = ptr[indexWord( 4, 0 )]; }
int_fast64_t f64_to_i64( float64_t a, uint_fast8_t roundingMode, bool exact ) { union ui64_f64 uA; uint_fast64_t uiA; bool sign; int_fast16_t exp; uint_fast64_t sig; int_fast16_t shiftCount; #ifdef SOFTFLOAT_FAST_INT64 struct uint64_extra sigExtra; #else uint32_t extSig[3]; #endif uA.f = a; uiA = uA.ui; sign = signF64UI( uiA ); exp = expF64UI( uiA ); sig = fracF64UI( uiA ); if ( exp ) sig |= UINT64_C( 0x0010000000000000 ); shiftCount = 0x433 - exp; #ifdef SOFTFLOAT_FAST_INT64 if ( shiftCount <= 0 ) { if ( shiftCount < -11 ) { softfloat_raiseFlags( softfloat_flag_invalid ); return ! sign || ((exp == 0x7FF) && (sig != UINT64_C( 0x0010000000000000 ))) ? INT64_C( 0x7FFFFFFFFFFFFFFF ) : -INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1; } sigExtra.v = sig<<-shiftCount; sigExtra.extra = 0; } else { sigExtra = softfloat_shiftRightJam64Extra( sig, 0, shiftCount ); } return softfloat_roundPackToI64( sign, sigExtra.v, sigExtra.extra, roundingMode, exact ); #else extSig[indexWord( 3, 0 )] = 0; if ( shiftCount <= 0 ) { if ( shiftCount < -11 ) { softfloat_raiseFlags( softfloat_flag_invalid ); return ! sign || ((exp == 0x7FF) && (sig != UINT64_C( 0x0010000000000000 ))) ? INT64_C( 0x7FFFFFFFFFFFFFFF ) : -INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1; } sig <<= -shiftCount; extSig[indexWord( 3, 2 )] = sig>>32; extSig[indexWord( 3, 1 )] = sig; } else {
int_fast32_t f128_to_i32_r_minMag( float128_t a, bool exact ) { union ui128_f128 uA; uint_fast64_t uiA64, uiA0; int_fast32_t exp; uint_fast64_t sig64; int_fast32_t shiftDist; bool sign; int_fast32_t absZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uA.f = a; uiA64 = uA.ui.v64; uiA0 = uA.ui.v0; exp = expF128UI64( uiA64 ); sig64 = fracF128UI64( uiA64 ) | (uiA0 != 0); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ shiftDist = 0x402F - exp; if ( 49 <= shiftDist ) { if ( exact && (exp | sig64) ) { softfloat_raiseFlags( softfloat_flag_inexact ); } return 0; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ sign = signF128UI64( uiA64 ); if ( shiftDist < 18 ) { if ( sign && (shiftDist == 17) && (sig64 < UINT64_C( 0x0000000000020000 )) ) { if ( exact && sig64 ) { softfloat_raiseFlags( softfloat_flag_inexact ); } return -0x7FFFFFFF - 1; } softfloat_raiseFlags( softfloat_flag_invalid ); return (exp == 0x7FFF) && sig64 ? i32_fromNaN : sign ? i32_fromNegOverflow : i32_fromPosOverflow; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ sig64 |= UINT64_C( 0x0001000000000000 ); absZ = sig64>>shiftDist; if ( exact && ((uint_fast64_t) (uint_fast32_t) absZ<<shiftDist != sig64) ) { softfloat_raiseFlags( softfloat_flag_inexact ); } return sign ? -absZ : absZ; }
float64_t softfloat_roundPackToF64( bool sign, int_fast16_t exp, uint_fast64_t sig ) { uint_fast8_t roundingMode; bool roundNearEven; uint_fast16_t roundIncrement, roundBits; bool isTiny; uint_fast64_t uiZ; union ui64_f64 uZ; roundingMode = softfloat_roundingMode; roundNearEven = (roundingMode == softfloat_round_near_even); roundIncrement = 0x200; if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) { roundIncrement = (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) ? 0x3FF : 0; } roundBits = sig & 0x3FF; if ( 0x7FD <= (uint16_t) exp ) { if ( exp < 0 ) { isTiny = (softfloat_detectTininess == softfloat_tininess_beforeRounding) || (exp < -1) || (sig + roundIncrement < UINT64_C( 0x8000000000000000 )); sig = softfloat_shiftRightJam64( sig, -exp ); exp = 0; roundBits = sig & 0x3FF; if ( isTiny && roundBits ) { softfloat_raiseFlags( softfloat_flag_underflow ); } } else if ( (0x7FD < exp) || (UINT64_C( 0x8000000000000000 ) <= sig + roundIncrement) ) { softfloat_raiseFlags( softfloat_flag_overflow | softfloat_flag_inexact ); uiZ = packToF64UI( sign, 0x7FF, 0 ) - ! roundIncrement; goto uiZ; } } if ( roundBits ) softfloat_exceptionFlags |= softfloat_flag_inexact; sig = (sig + roundIncrement)>>10; sig &= ~(uint_fast64_t) (! (roundBits ^ 0x200) & roundNearEven); uiZ = packToF64UI( sign, sig ? exp : 0, sig ); uiZ: uZ.ui = uiZ; return uZ.f; }
/*---------------------------------------------------------------------------- | Interpreting 'uiA' and 'uiB' as the bit patterns of two 16-bit floating- | point values, at least one of which is a NaN, returns the bit pattern of | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ uint_fast16_t softfloat_propagateNaNF16UI( uint_fast16_t uiA, uint_fast16_t uiB ) { bool isSigNaNA, isSigNaNB; uint_fast16_t uiNonsigA, uiNonsigB, uiMagA, uiMagB; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ isSigNaNA = softfloat_isSigNaNF16UI( uiA ); isSigNaNB = softfloat_isSigNaNF16UI( uiB ); /*------------------------------------------------------------------------ | Make NaNs non-signaling. *------------------------------------------------------------------------*/ uiNonsigA = uiA | 0x0200; uiNonsigB = uiB | 0x0200; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( isSigNaNA | isSigNaNB ) { softfloat_raiseFlags( softfloat_flag_invalid ); if ( isSigNaNA ) { if ( isSigNaNB ) goto returnLargerMag; return isNaNF16UI( uiB ) ? uiNonsigB : uiNonsigA; } else { return isNaNF16UI( uiA ) ? uiNonsigA : uiNonsigB; } } returnLargerMag: uiMagA = uiA & 0x7FFF; uiMagB = uiB & 0x7FFF; if ( uiMagA < uiMagB ) return uiNonsigB; if ( uiMagB < uiMagA ) return uiNonsigA; return (uiNonsigA < uiNonsigB) ? uiNonsigA : uiNonsigB; }
bool f128M_eq_signaling( const float128_t *aPtr, const float128_t *bPtr ) { const uint32_t *aWPtr, *bWPtr; uint32_t wordA, wordB, uiA96, uiB96; bool possibleOppositeZeros; uint32_t mashWord; aWPtr = (const uint32_t *) aPtr; bWPtr = (const uint32_t *) bPtr; if ( softfloat_isNaNF128M( aWPtr ) || softfloat_isNaNF128M( bWPtr ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); return false; } wordA = aWPtr[indexWord( 4, 2 )]; wordB = bWPtr[indexWord( 4, 2 )]; if ( wordA != wordB ) return false; uiA96 = aWPtr[indexWordHi( 4 )]; uiB96 = bWPtr[indexWordHi( 4 )]; possibleOppositeZeros = false; if ( uiA96 != uiB96 ) { possibleOppositeZeros = (((uiA96 | uiB96) & 0x7FFFFFFF) == 0); if ( ! possibleOppositeZeros ) return false; } mashWord = wordA | wordB; wordA = aWPtr[indexWord( 4, 1 )]; wordB = bWPtr[indexWord( 4, 1 )]; if ( wordA != wordB ) return false; mashWord |= wordA | wordB; wordA = aWPtr[indexWord( 4, 0 )]; wordB = bWPtr[indexWord( 4, 0 )]; return (wordA == wordB) && (! possibleOppositeZeros || ((mashWord | wordA | wordB) == 0)); }
/*---------------------------------------------------------------------------- | Assuming at least one of the two 80-bit extended floating-point values | pointed to by 'aSPtr' and 'bSPtr' is a NaN, stores the combined NaN result | at the location pointed to by 'zSPtr'. If either original floating-point | value is a signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ void softfloat_propagateNaNExtF80M( const struct extFloat80M *aSPtr, const struct extFloat80M *bSPtr, struct extFloat80M *zSPtr ) { uint_fast16_t ui64; uint_fast64_t ui0; ui64 = aSPtr->signExp; ui0 = aSPtr->signif; if ( softfloat_isSigNaNExtF80UI( ui64, ui0 ) || (bSPtr && (ui64 = bSPtr->signExp, ui0 = bSPtr->signif, softfloat_isSigNaNExtF80UI( ui64, ui0 ))) ) { softfloat_raiseFlags( softfloat_flag_invalid ); } zSPtr->signExp = defaultNaNExtF80UI64; zSPtr->signif = defaultNaNExtF80UI0; }
uint_fast32_t extF80_to_ui32_r_minMag( extFloat80_t a, bool exact ) { union { struct extFloat80M s; extFloat80_t f; } uA; uint_fast16_t uiA64; int_fast32_t exp; uint_fast64_t sig; int_fast32_t shiftCount; uint_fast32_t z; uA.f = a; uiA64 = uA.s.signExp; exp = expExtF80UI64( uiA64 ); sig = uA.s.signif; shiftCount = 0x403E - exp; if ( 64 <= shiftCount ) { if ( exact && (exp | sig) ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } return 0; } if ( signExtF80UI64( uiA64 ) || (shiftCount < 32) ) { softfloat_raiseFlags( softfloat_flag_invalid ); return 0xFFFFFFFF; } z = sig>>shiftCount; if ( exact && ((uint_fast64_t) z<<shiftCount != sig) ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } return z; }
uint_fast64_t extF80_to_ui64( extFloat80_t a, uint_fast8_t roundingMode, bool exact ) { union { struct extFloat80M s; extFloat80_t f; } uA; uint_fast16_t uiA64; int_fast32_t exp, shiftCount; bool sign; uint_fast64_t sig, sigExtra; struct uint64_extra sig64Extra; uA.f = a; uiA64 = uA.s.signExp; exp = expExtF80UI64( uiA64 ); shiftCount = 0x403E - exp; if ( shiftCount < 0 ) { softfloat_raiseFlags( softfloat_flag_invalid ); return UINT64_C( 0xFFFFFFFFFFFFFFFF ); } sign = signExtF80UI64( uiA64 ); sig = uA.s.signif; sigExtra = 0; if ( shiftCount ) { sig64Extra = softfloat_shiftRightJam64Extra( sig, 0, shiftCount ); sig = sig64Extra.v; sigExtra = sig64Extra.extra; } return softfloat_roundPackToUI64( sign, sig, sigExtra, roundingMode, exact ); }
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 ))) ); }
bool f32_eq( float32_t a, float32_t b ) { union ui32_f32 uA; uint_fast32_t uiA; union ui32_f32 uB; uint_fast32_t uiB; uA.f = a; uiA = uA.ui; uB.f = b; uiB = uB.ui; if ( ( ( expF32UI( uiA ) == 0xFF ) && fracF32UI( uiA ) ) || ( ( expF32UI( uiB ) == 0xFF ) && fracF32UI( uiB ) ) ) { if ( softfloat_isSigNaNF32UI( uiA ) || softfloat_isSigNaNF32UI( uiB ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); } return false; } return ( uiA == uiB ) || ! (uint32_t) ( ( uiA | uiB )<<1 ); }
bool f32_le( float32_t a, float32_t b ) { union ui32_f32 uA; uint_fast32_t uiA; union ui32_f32 uB; uint_fast32_t uiB; bool signA, signB; uA.f = a; uiA = uA.ui; uB.f = b; uiB = uB.ui; if ( ( ( expF32UI( uiA ) == 0xFF ) && fracF32UI( uiA ) ) || ( ( expF32UI( uiB ) == 0xFF ) && fracF32UI( uiB ) ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); return false; } signA = signF32UI( uiA ); signB = signF32UI( uiB ); return ( signA != signB ) ? signA || ! (uint32_t) ( ( uiA | uiB )<<1 ) : ( uiA == uiB ) || ( signA ^ ( uiA < uiB ) ); }
uint_fast32_t f64_to_ui32_r_minMag( float64_t a, bool exact ) { union ui64_f64 uA; uint_fast64_t uiA; int_fast16_t exp; uint_fast64_t sig; int_fast16_t shiftCount; uint_fast32_t z; uA.f = a; uiA = uA.ui; exp = expF64UI( uiA ); sig = fracF64UI( uiA ); if ( exp < 0x3FF ) { if ( exact && ( exp | sig ) ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } return 0; } if ( signF64UI( uiA ) || ( 0x41E < exp ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); return 0xFFFFFFFF; } sig |= UINT64_C( 0x0010000000000000 ); shiftCount = 0x433 - exp; z = sig>>shiftCount; if ( exact && ( (uint_fast64_t) z<<shiftCount != sig ) ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } return z; }
uint_fast64_t f64_to_ui64( float64_t a, int_fast8_t roundingMode, bool exact ) { union ui64_f64 uA; uint_fast64_t uiA; bool sign; int_fast16_t exp; uint_fast64_t sig; int_fast16_t shiftCount; struct uint64_extra sigExtra; uA.f = a; uiA = uA.ui; sign = signF64UI( uiA ); exp = expF64UI( uiA ); sig = fracF64UI( uiA ); if ( exp ) sig |= UINT64_C( 0x0010000000000000 ); shiftCount = 0x433 - exp; if ( shiftCount <= 0 ) { if ( 0x43E < exp ) { softfloat_raiseFlags( softfloat_flag_invalid ); return UINT64_C( 0xFFFFFFFFFFFFFFFF ); } sigExtra.v = sig<<( - shiftCount ); sigExtra.extra = 0; } else { sigExtra = softfloat_shift64ExtraRightJam( sig, 0, shiftCount ); } return softfloat_roundPackToUI64( sign, sigExtra.v, sigExtra.extra, roundingMode, exact ); }
bool extF80_eq( extFloat80_t a, extFloat80_t b ) { union { struct extFloat80M s; extFloat80_t f; } uA; uint_fast16_t uiA64; uint_fast64_t uiA0; union { struct extFloat80M s; extFloat80_t f; } uB; uint_fast16_t uiB64; uint_fast64_t uiB0; uA.f = a; uiA64 = uA.s.signExp; uiA0 = uA.s.signif; uB.f = b; uiB64 = uB.s.signExp; uiB0 = uB.s.signif; if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) { if ( softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) || softfloat_isSigNaNExtF80UI( uiB64, uiB0 ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); } return false; } return (uiA0 == uiB0) && ((uiA64 == uiB64) || (! uiA0 && ! ((uiA64 | uiB64) & 0x7FFF))); }
int_fast64_t f32_to_i64( float32_t a, int_fast8_t roundingMode, bool exact ) { union ui32_f32 uA; uint_fast32_t uiA; bool sign; int_fast16_t exp; uint_fast32_t sig; int_fast16_t shiftCount; uint_fast64_t sig64, extra; struct uint64_extra sig64Extra; uA.f = a; uiA = uA.ui; sign = signF32UI( uiA ); exp = expF32UI( uiA ); sig = fracF32UI( uiA ); shiftCount = 0xBE - exp; if ( shiftCount < 0 ) { softfloat_raiseFlags( softfloat_flag_invalid ); if ( ! sign || ( ( exp == 0xFF ) && sig ) ) { return INT64_C( 0x7FFFFFFFFFFFFFFF ); } return - INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1; } if ( exp ) sig |= 0x00800000; sig64 = (uint_fast64_t) sig<<40; extra = 0; if ( shiftCount ) { sig64Extra = softfloat_shift64ExtraRightJam( sig64, 0, shiftCount ); sig64 = sig64Extra.v; extra = sig64Extra.extra; } return softfloat_roundPackToI64( sign, sig64, extra, roundingMode, exact ); }
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 )); }
uint_fast64_t extF80M_to_ui64( const extFloat80_t *aPtr, uint_fast8_t roundingMode, bool exact ) { const struct extFloat80M *aSPtr; uint_fast16_t uiA64; int32_t exp, shiftCount; bool sign; uint64_t sig; uint32_t extSig[3]; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ aSPtr = (const struct extFloat80M *) aPtr; uiA64 = aSPtr->signExp; exp = expExtF80UI64( uiA64 ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ shiftCount = 0x403E - exp; if ( shiftCount < 0 ) { softfloat_raiseFlags( softfloat_flag_invalid ); return UINT64_C( 0xFFFFFFFFFFFFFFFF ); } sign = signExtF80UI64( uiA64 ); sig = aSPtr->signif; extSig[indexWord( 3, 2 )] = sig>>32; extSig[indexWord( 3, 1 )] = sig; extSig[indexWord( 3, 0 )] = 0; if ( shiftCount ) softfloat_shiftRightJam96M( extSig, shiftCount, extSig ); return softfloat_roundPackMToUI64( sign, extSig, roundingMode, exact ); }
bool f32_le_quiet( float32_t a, float32_t b ) { union ui32_f32 uA; uint_fast32_t uiA; union ui32_f32 uB; uint_fast32_t uiB; bool signA, signB; uA.f = a; uiA = uA.ui; uB.f = b; uiB = uB.ui; if ( isNaNF32UI( uiA ) || isNaNF32UI( uiB ) ) { if ( softfloat_isSigNaNF32UI( uiA ) || softfloat_isSigNaNF32UI( uiB ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); } return false; } signA = signF32UI( uiA ); signB = signF32UI( uiB ); return (signA != signB) ? signA || ! (uint32_t) ((uiA | uiB)<<1) : (uiA == uiB) || (signA ^ (uiA < uiB)); }
uint_fast64_t f32_to_ui64_r_minMag( float32_t a, bool exact ) { union ui32_f32 uA; uint_fast32_t uiA; int_fast16_t exp; uint_fast32_t sig; int_fast16_t shiftCount; uint_fast64_t sig64, z; uA.f = a; uiA = uA.ui; exp = expF32UI( uiA ); sig = fracF32UI( uiA ); shiftCount = 0xBE - exp; if ( 64 <= shiftCount ) { if ( exact && (exp | sig) ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } return 0; } if ( signF32UI( uiA ) || (shiftCount < 0) ) goto invalid; sig |= 0x00800000; sig64 = (uint_fast64_t) sig<<40; z = sig64>>shiftCount; shiftCount = 40 - shiftCount; if ( exact && (shiftCount < 0) && (uint32_t) (sig<<(shiftCount & 31)) ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } return z; invalid: softfloat_raiseFlags( softfloat_flag_invalid ); return UINT64_C( 0xFFFFFFFFFFFFFFFF ); }
bool extF80_lt_quiet( extFloat80_t a, extFloat80_t b ) { union { struct extFloat80M s; extFloat80_t f; } uA; uint_fast16_t uiA64; uint_fast64_t uiA0; union { struct extFloat80M s; extFloat80_t f; } uB; uint_fast16_t uiB64; uint_fast64_t uiB0; bool signA, signB; uA.f = a; uiA64 = uA.s.signExp; uiA0 = uA.s.signif; uB.f = b; uiB64 = uB.s.signExp; uiB0 = uB.s.signif; if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) { if ( softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) || softfloat_isSigNaNExtF80UI( uiB64, uiB0 ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); } return false; } signA = signExtF80UI64( uiA64 ); signB = signExtF80UI64( uiB64 ); return (signA != signB) ? signA && (((uiA64 | uiB64) & 0x7FFF) | uiA0 | uiB0) : ((uiA64 != uiB64) || (uiA0 != uiB0)) && (signA ^ softfloat_lt128( uiA64, uiA0, uiB64, uiB0 )); }
/*---------------------------------------------------------------------------- | 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; }
bool f64_lt_quiet( float64_t a, float64_t b ) { union ui64_f64 uA; uint_fast64_t uiA; union ui64_f64 uB; uint_fast64_t uiB; bool signA, signB; uA.f = a; uiA = uA.ui; uB.f = b; uiB = uB.ui; if ( isNaNF64UI( uiA ) || isNaNF64UI( uiB ) ) { if ( softfloat_isSigNaNF64UI( uiA ) || softfloat_isSigNaNF64UI( uiB ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); } return false; } signA = signF64UI( uiA ); signB = signF64UI( uiB ); return (signA != signB) ? signA && ((uiA | uiB) & UINT64_C( 0x7FFFFFFFFFFFFFFF )) : (uiA != uiB) && (signA ^ (uiA < uiB)); }
void softfloat_invalidExtF80M( struct extFloat80M *zSPtr ) { softfloat_raiseFlags( softfloat_flag_invalid ); zSPtr->signExp = defaultNaNExtF80UI64; zSPtr->signif = defaultNaNExtF80UI0; }
uint_fast32_t f128_to_ui32_r_minMag( float128_t a, bool exact ) { union ui128_f128 uA; uint_fast64_t uiA64, uiA0; int_fast32_t exp; uint_fast64_t sig64; int_fast32_t shiftDist; bool sign; uint_fast32_t z; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uA.f = a; uiA64 = uA.ui.v64; uiA0 = uA.ui.v0; exp = expF128UI64( uiA64 ); sig64 = fracF128UI64( uiA64 ) | (uiA0 != 0); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ shiftDist = 0x402F - exp; if ( 49 <= shiftDist ) { if ( exact && (exp | sig64) ) { softfloat_raiseFlags( softfloat_flag_inexact ); } return 0; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ sign = signF128UI64( uiA64 ); if ( sign || (shiftDist < 17) ) { softfloat_raiseFlags( softfloat_flag_invalid ); return (exp == 0x7FFF) && sig64 ? ui32_fromNaN : sign ? ui32_fromNegOverflow : ui32_fromPosOverflow; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ sig64 |= UINT64_C( 0x0001000000000000 ); z = sig64>>shiftDist; if ( exact && ((uint_fast64_t) z<<shiftDist != sig64) ) { softfloat_raiseFlags( softfloat_flag_inexact ); } return z; }
uint_fast32_t extF80_to_ui32_r_minMag( extFloat80_t a, bool exact ) { union { struct extFloat80M s; extFloat80_t f; } uA; uint_fast16_t uiA64; int_fast32_t exp; uint_fast64_t sig; int_fast32_t shiftDist; bool sign; uint_fast32_t z; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uA.f = a; uiA64 = uA.s.signExp; exp = expExtF80UI64( uiA64 ); sig = uA.s.signif; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ shiftDist = 0x403E - exp; if ( 64 <= shiftDist ) { if ( exact && (exp | sig) ) { softfloat_raiseFlags( softfloat_flag_inexact ); } return 0; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ sign = signExtF80UI64( uiA64 ); if ( sign || (shiftDist < 32) ) { softfloat_raiseFlags( softfloat_flag_invalid ); return (exp == 0x7FFF) && (sig & UINT64_C( 0x7FFFFFFFFFFFFFFF )) ? ui32_fromNaN : sign ? ui32_fromNegOverflow : ui32_fromPosOverflow; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ z = sig>>shiftDist; if ( exact && ((uint_fast64_t) z<<shiftDist != sig) ) { softfloat_raiseFlags( softfloat_flag_inexact ); } return z; }
void softfloat_invalidF128M( uint32_t *zWPtr ) { softfloat_raiseFlags( softfloat_flag_invalid ); zWPtr[indexWord( 4, 3 )] = defaultNaNF128UI96; zWPtr[indexWord( 4, 2 )] = defaultNaNF128UI64; zWPtr[indexWord( 4, 1 )] = defaultNaNF128UI32; zWPtr[indexWord( 4, 0 )] = defaultNaNF128UI0; }
/*---------------------------------------------------------------------------- | Interpreting `uiA' and `uiB' as the bit patterns of two 16-bit floating- | point values, at least one of which is a NaN, returns the bit pattern of | the combined NaN result. If either `uiA' or `uiB' has the pattern of a | signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ uint_fast16_t softfloat_propagateNaNF16UI( uint_fast16_t uiA, uint_fast16_t uiB ) { if ( softfloat_isSigNaNF16UI( uiA ) || softfloat_isSigNaNF16UI( uiB ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); } return defaultNaNF16UI; }
uint_fast64_t f16_to_ui64_r_minMag( float16_t a, bool exact ) { union ui16_f16 uA; uint_fast16_t uiA; int_fast8_t exp; uint_fast16_t frac; int_fast8_t shiftDist; bool sign; uint_fast32_t alignedSig; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uA.f = a; uiA = uA.ui; exp = expF16UI( uiA ); frac = fracF16UI( uiA ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ shiftDist = exp - 0x0F; if ( shiftDist < 0 ) { if ( exact && (exp | frac) ) { softfloat_raiseFlags( softfloat_flag_inexact ); } return 0; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ sign = signF16UI( uiA ); if ( sign || (exp == 0x1F) ) { softfloat_raiseFlags( softfloat_flag_invalid ); return (exp == 0x1F) && frac ? ui64_fromNaN : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ alignedSig = (uint_fast32_t) (frac | 0x0400)<<shiftDist; if ( exact && (alignedSig & 0x3FF) ) { softfloat_raiseFlags( softfloat_flag_inexact ); } return alignedSig>>10; }
bool extF80M_lt_quiet( const extFloat80_t *aPtr, const extFloat80_t *bPtr ) { const struct extFloat80M *aSPtr, *bSPtr; uint_fast16_t uiA64; uint64_t uiA0; uint_fast16_t uiB64; uint64_t uiB0; bool signA, ltMags; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ aSPtr = (const struct extFloat80M *) aPtr; bSPtr = (const struct extFloat80M *) bPtr; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiA64 = aSPtr->signExp; uiA0 = aSPtr->signif; uiB64 = bSPtr->signExp; uiB0 = bSPtr->signif; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) { if ( softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) || softfloat_isSigNaNExtF80UI( uiB64, uiB0 ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); } return false; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ signA = signExtF80UI64( uiA64 ); if ( (uiA64 ^ uiB64) & 0x8000 ) { /*-------------------------------------------------------------------- | Signs are different. *--------------------------------------------------------------------*/ return signA && ((uiA0 | uiB0) != 0); } else { /*-------------------------------------------------------------------- | Signs are the same. *--------------------------------------------------------------------*/ if ( ! ((uiA0 & uiB0) & UINT64_C( 0x8000000000000000 )) ) { return (softfloat_compareNonnormExtF80M( aSPtr, bSPtr ) < 0); } if ( uiA64 == uiB64 ) { if ( uiA0 == uiB0 ) return false; ltMags = (uiA0 < uiB0); } else { ltMags = (uiA64 < uiB64); } return signA ^ ltMags; } }