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)); }
void ui64_to_f128M( uint64_t a, float128_t *zPtr ) { uint32_t *zWPtr, uiZ96, uiZ64; uint_fast8_t shiftCount; uint32_t *ptr; zWPtr = (uint32_t *) zPtr; uiZ96 = 0; uiZ64 = 0; zWPtr[indexWord( 4, 1 )] = 0; zWPtr[indexWord( 4, 0 )] = 0; if ( a ) { shiftCount = softfloat_countLeadingZeros64( a ) + 17; if ( shiftCount < 32 ) { ptr = zWPtr + indexMultiwordHi( 4, 3 ); ptr[indexWord( 3, 2 )] = 0; ptr[indexWord( 3, 1 )] = a>>32; ptr[indexWord( 3, 0 )] = a; softfloat_shortShiftLeft96M( ptr, shiftCount, ptr ); ptr[indexWordHi( 3 )] = packToF128UI96( 0, 0x404E - shiftCount, ptr[indexWordHi( 3 )] ); return; } a <<= shiftCount - 32; uiZ96 = packToF128UI96( 0, 0x404E - shiftCount, a>>32 ); uiZ64 = a; }
void extF80M_to_f128M( const extFloat80_t *aPtr, float128_t *zPtr ) { const struct extFloat80M *aSPtr; uint32_t *zWPtr; uint_fast16_t uiA64; bool sign; int32_t exp; uint64_t sig; struct commonNaN commonNaN; uint32_t uiZ96; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ aSPtr = (const struct extFloat80M *) aPtr; zWPtr = (uint32_t *) zPtr; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiA64 = aSPtr->signExp; sign = signExtF80UI64( uiA64 ); exp = expExtF80UI64( uiA64 ); sig = aSPtr->signif; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ zWPtr[indexWord( 4, 0 )] = 0; if ( exp == 0x7FFF ) { if ( sig & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) { softfloat_extF80MToCommonNaN( aSPtr, &commonNaN ); softfloat_commonNaNToF128M( &commonNaN, zWPtr ); return; } uiZ96 = packToF128UI96( sign, 0x7FFF, 0 ); goto uiZ; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( exp ) --exp; if ( ! (sig & UINT64_C( 0x8000000000000000 )) ) { if ( ! sig ) { uiZ96 = packToF128UI96( sign, 0, 0 ); goto uiZ; } exp += softfloat_normExtF80SigM( &sig ); } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ zWPtr[indexWord( 4, 1 )] = (uint32_t) sig<<17; sig >>= 15; zWPtr[indexWord( 4, 2 )] = sig; if ( exp < 0 ) { zWPtr[indexWordHi( 4 )] = sig>>32; softfloat_shiftRight96M( &zWPtr[indexMultiwordHi( 4, 3 )], -exp, &zWPtr[indexMultiwordHi( 4, 3 )] ); exp = 0; sig = (uint64_t) zWPtr[indexWordHi( 4 )]<<32; }
/*---------------------------------------------------------------------------- | 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 )]; }
void softfloat_shortShiftRightExtendM( uint_fast8_t size_words, const uint32_t *aPtr, uint_fast8_t count, uint32_t *zPtr ) { uint_fast8_t negCount; unsigned int indexA, lastIndexA; uint32_t partWordZ, wordA; negCount = -count; indexA = indexWordLo( size_words ); lastIndexA = indexWordHi( size_words ); zPtr += indexWordLo( size_words + 1 ); partWordZ = 0; for (;;) { wordA = aPtr[indexA]; *zPtr = wordA<<(negCount & 31) | partWordZ; zPtr += wordIncr; partWordZ = wordA>>count; if ( indexA == lastIndexA ) break; indexA += wordIncr; } *zPtr = partWordZ; }
void softfloat_subM( uint_fast8_t size_words, const uint32_t *aPtr, const uint32_t *bPtr, uint32_t *zPtr ) { unsigned int index, lastIndex; uint_fast8_t borrow; uint32_t wordA, wordB; index = indexWordLo( size_words ); lastIndex = indexWordHi( size_words ); borrow = 0; for (;;) { wordA = aPtr[index]; wordB = bPtr[index]; zPtr[index] = wordA - wordB - borrow; if ( index == lastIndex ) break; borrow = borrow ? (wordA <= wordB) : (wordA < wordB); index += wordIncr; } }
uint_fast8_t softfloat_addCarryM( uint_fast8_t size_words, const uint32_t *aPtr, const uint32_t *bPtr, uint_fast8_t carry, uint32_t *zPtr ) { unsigned int index, lastIndex; uint32_t wordA, wordZ; index = indexWordLo( size_words ); lastIndex = indexWordHi( size_words ); for (;;) { wordA = aPtr[index]; wordZ = wordA + bPtr[index] + carry; zPtr[index] = wordZ; carry = carry ? (wordZ <= wordA) : (wordZ < wordA); if ( index == lastIndex ) break; index += wordIncr; } return carry; }
void softfloat_shortShiftRightJamM( uint_fast8_t size_words, const uint32_t *aPtr, uint_fast8_t count, uint32_t *zPtr ) { uint_fast8_t negCount; unsigned int index, lastIndex; uint32_t partWordZ, wordA; negCount = -count; index = indexWordLo( size_words ); lastIndex = indexWordHi( size_words ); wordA = aPtr[index]; partWordZ = wordA>>count; if ( partWordZ<<count != wordA ) partWordZ |= 1; while ( index != lastIndex ) { wordA = aPtr[index + wordIncr]; zPtr[index] = wordA<<(negCount & 31) | partWordZ; index += wordIncr; partWordZ = wordA>>count; } zPtr[index] = partWordZ; }
void softfloat_shiftLeftM( uint_fast8_t size_words, const uint32_t *aPtr, uint32_t dist, uint32_t *zPtr ) { uint32_t wordDist; uint_fast8_t innerDist; uint32_t *destPtr; uint_fast8_t i; wordDist = dist>>5; if ( wordDist < size_words ) { aPtr += indexMultiwordLoBut( size_words, wordDist ); innerDist = dist & 31; if ( innerDist ) { softfloat_shortShiftLeftM( size_words - wordDist, aPtr, innerDist, zPtr + indexMultiwordHiBut( size_words, wordDist ) ); if ( ! wordDist ) return; } else { aPtr += indexWordHi( size_words - wordDist ); destPtr = zPtr + indexWordHi( size_words ); for ( i = size_words - wordDist; i; --i ) { *destPtr = *aPtr; aPtr -= wordIncr; destPtr -= wordIncr; } } zPtr += indexMultiwordLo( size_words, wordDist ); } else { wordDist = size_words; } do { *zPtr++ = 0; --wordDist; } while ( wordDist ); }
float16_t f128M_to_f16( const float128_t *aPtr ) { const uint32_t *aWPtr; uint32_t uiA96; bool sign; int32_t exp; uint32_t frac32; struct commonNaN commonNaN; uint16_t uiZ, frac16; union ui16_f16 uZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ aWPtr = (const uint32_t *) aPtr; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiA96 = aWPtr[indexWordHi( 4 )]; sign = signF128UI96( uiA96 ); exp = expF128UI96( uiA96 ); frac32 = fracF128UI96( uiA96 ) | ((aWPtr[indexWord( 4, 2 )] | aWPtr[indexWord( 4, 1 )] | aWPtr[indexWord( 4, 0 )]) != 0); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( exp == 0x7FFF ) { if ( frac32 ) { softfloat_f128MToCommonNaN( aWPtr, &commonNaN ); uiZ = softfloat_commonNaNToF16UI( &commonNaN ); } else { uiZ = packToF16UI( sign, 0x1F, 0 ); } goto uiZ; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ frac16 = frac32>>2 | (frac32 & 3); if ( ! (exp | frac16) ) { uiZ = packToF16UI( sign, 0, 0 ); goto uiZ; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ exp -= 0x3FF1; if ( sizeof (int_fast16_t) < sizeof (int32_t) ) { if ( exp < -0x40 ) exp = -0x40; } return softfloat_roundPackToF16( sign, exp, frac16 | 0x4000 ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiZ: uZ.ui = uiZ; return uZ.f; }
bool f128M_eq( 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; wordA = aWPtr[indexWord( 4, 2 )]; wordB = bWPtr[indexWord( 4, 2 )]; if ( wordA != wordB ) goto false_checkSigNaNs; uiA96 = aWPtr[indexWordHi( 4 )]; uiB96 = bWPtr[indexWordHi( 4 )]; possibleOppositeZeros = false; if ( uiA96 != uiB96 ) { possibleOppositeZeros = (((uiA96 | uiB96) & 0x7FFFFFFF) == 0); if ( ! possibleOppositeZeros ) goto false_checkSigNaNs; } mashWord = wordA | wordB; wordA = aWPtr[indexWord( 4, 1 )]; wordB = bWPtr[indexWord( 4, 1 )]; if ( wordA != wordB ) goto false_checkSigNaNs; mashWord |= wordA | wordB; wordA = aWPtr[indexWord( 4, 0 )]; wordB = bWPtr[indexWord( 4, 0 )]; if ( wordA != wordB ) goto false_checkSigNaNs; if ( possibleOppositeZeros && ((mashWord | wordA | wordB) != 0) ) { goto false_checkSigNaNs; } if ( ! softfloat_isNaNF128M( aWPtr ) && ! softfloat_isNaNF128M( bWPtr ) ) { return true; } false_checkSigNaNs: if ( f128M_isSignalingNaN( (const float128_t *) aWPtr ) || f128M_isSignalingNaN( (const float128_t *) bWPtr ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); } return false; }
/*---------------------------------------------------------------------------- | Assuming the 128-bit floating-point value pointed to by `aWPtr' is a NaN, | converts this NaN to the common NaN form, and stores the resulting common | NaN at the location pointed to by `zPtr'. If the NaN is a signaling NaN, | the invalid exception is raised. Argument `aWPtr' 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_f128MToCommonNaN( const uint32_t *aWPtr, struct commonNaN *zPtr ) { if ( f128M_isSignalingNaN( (const float128_t *) aWPtr ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); } zPtr->sign = aWPtr[indexWordHi( 4 )]>>31; softfloat_shortShiftLeft128M( aWPtr, 16, (uint32_t *) &zPtr->v0 ); }
float32_t f128M_to_f32( const float128_t *aPtr ) { const uint32_t *aWPtr; uint32_t uiA96; bool sign; int32_t exp; uint64_t frac64; struct commonNaN commonNaN; uint32_t uiZ, frac32; union ui32_f32 uZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ aWPtr = (const uint32_t *) aPtr; uiA96 = aWPtr[indexWordHi( 4 )]; sign = signF128UI96( uiA96 ); exp = expF128UI96( uiA96 ); frac64 = (uint64_t) fracF128UI96( uiA96 )<<32 | aWPtr[indexWord( 4, 2 )] | ((aWPtr[indexWord( 4, 1 )] | aWPtr[indexWord( 4, 0 )]) != 0); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( exp == 0x7FFF ) { if ( frac64 ) { softfloat_f128MToCommonNaN( aWPtr, &commonNaN ); uiZ = softfloat_commonNaNToF32UI( &commonNaN ); } else { uiZ = packToF32UI( sign, 0xFF, 0 ); } goto uiZ; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ frac32 = softfloat_shortShiftRightJam64( frac64, 18 ); if ( ! (exp | frac32) ) { uiZ = packToF32UI( sign, 0, 0 ); goto uiZ; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ exp -= 0x3F81; if ( sizeof (int_fast16_t) < sizeof (int32_t) ) { if ( exp < -0x1000 ) exp = -0x1000; } return softfloat_roundPackToF32( sign, exp, frac32 | 0x40000000 ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiZ: uZ.ui = uiZ; return uZ.f; }
/*---------------------------------------------------------------------------- *----------------------------------------------------------------------------*/ bool softfloat_isNaNF128M( const uint32_t *aWPtr ) { uint32_t uiA96; uiA96 = aWPtr[indexWordHi( 4 )]; if ( (uiA96 & 0x7FFF0000) != 0x7FFF0000 ) return false; return ((uiA96 & 0x0000FFFF) != 0) || ((aWPtr[indexWord( 4, 2 )] | aWPtr[indexWord( 4, 1 )] | aWPtr[indexWord( 4, 0 )]) != 0); }
bool f128M_lt( const float128_t *aPtr, const float128_t *bPtr ) { const uint32_t *aWPtr, *bWPtr; uint32_t uiA96, uiB96; bool signA, signB; uint32_t wordA, wordB; aWPtr = (const uint32_t *) aPtr; bWPtr = (const uint32_t *) bPtr; if ( softfloat_isNaNF128M( aWPtr ) || softfloat_isNaNF128M( bWPtr ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); return false; } uiA96 = aWPtr[indexWordHi( 4 )]; uiB96 = bWPtr[indexWordHi( 4 )]; signA = signF128UI96( uiA96 ); signB = signF128UI96( uiB96 ); if ( signA != signB ) { if ( signB ) return false; if ( (uiA96 | uiB96) & 0x7FFFFFFF ) return true; wordA = aWPtr[indexWord( 4, 2 )]; wordB = bWPtr[indexWord( 4, 2 )]; if ( wordA | wordB ) return true; wordA = aWPtr[indexWord( 4, 1 )]; wordB = bWPtr[indexWord( 4, 1 )]; if ( wordA | wordB ) return true; wordA = aWPtr[indexWord( 4, 0 )]; wordB = bWPtr[indexWord( 4, 0 )]; return ((wordA | wordB) != 0); } if ( signA ) { aWPtr = (const uint32_t *) bPtr; bWPtr = (const uint32_t *) aPtr; } return (softfloat_compare128M( aWPtr, bWPtr ) < 0); }
/*---------------------------------------------------------------------------- | 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; ptr = aWPtr; isSigNaNA = f128M_isSignalingNaN( (const float128_t *) aWPtr ); if ( isSigNaNA || (bWPtr && f128M_isSignalingNaN( (const float128_t *) bWPtr )) ) { softfloat_raiseFlags( softfloat_flag_invalid ); if ( isSigNaNA ) goto copy; } if ( ! softfloat_isNaNF128M( aWPtr ) ) 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 )]; }
/*---------------------------------------------------------------------------- *----------------------------------------------------------------------------*/ bool f128M_isSignalingNaN( const float128_t *aPtr ) { const uint32_t *aWPtr; uint32_t uiA96; aWPtr = (const uint32_t *) aPtr; uiA96 = aWPtr[indexWordHi( 4 )]; if ( (uiA96 & 0x7FFF8000) != 0x7FFF0000 ) return false; return ((uiA96 & 0x00007FFF) != 0) || ((aWPtr[indexWord( 4, 2 )] | aWPtr[indexWord( 4, 1 )] | aWPtr[indexWord( 4, 0 )]) != 0); }
void softfloat_sub1XM( uint_fast8_t size_words, uint32_t *zPtr ) { unsigned int index, lastIndex; uint32_t wordA; index = indexWordLo( size_words ); lastIndex = indexWordHi( size_words ); for (;;) { wordA = zPtr[index]; zPtr[index] = wordA - 1; if ( wordA || (index == lastIndex) ) break; index += wordIncr; } }
int_fast8_t softfloat_compare96M( const uint32_t *aPtr, const uint32_t *bPtr ) { unsigned int index, lastIndex; uint32_t wordA, wordB; index = indexWordHi( 3 ); lastIndex = indexWordLo( 3 ); for (;;) { wordA = aPtr[index]; wordB = bPtr[index]; if ( wordA != wordB ) return (wordA < wordB) ? -1 : 1; if ( index == lastIndex ) break; index -= wordIncr; } return 0; }
void softfloat_negXM( uint_fast8_t size_words, uint32_t *zPtr ) { unsigned int index, lastIndex; uint_fast8_t carry; uint32_t word; index = indexWordLo( size_words ); lastIndex = indexWordHi( size_words ); carry = 1; for (;;) { word = ~zPtr[index] + carry; zPtr[index] = word; if ( index == lastIndex ) break; index += wordIncr; if ( word ) carry = 0; } }
void f128M_to_extF80M( const float128_t *aPtr, extFloat80_t *zPtr ) { const uint32_t *aWPtr; struct extFloat80M *zSPtr; uint32_t uiA96; bool sign; int32_t exp; struct commonNaN commonNaN; uint32_t sig[4]; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ aWPtr = (const uint32_t *) aPtr; zSPtr = (struct extFloat80M *) zPtr; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiA96 = aWPtr[indexWordHi( 4 )]; sign = signF128UI96( uiA96 ); exp = expF128UI96( uiA96 ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( exp == 0x7FFF ) { if ( softfloat_isNaNF128M( aWPtr ) ) { softfloat_f128MToCommonNaN( aWPtr, &commonNaN ); softfloat_commonNaNToExtF80M( &commonNaN, zSPtr ); return; } zSPtr->signExp = packToExtF80UI64( sign, 0x7FFF ); zSPtr->signif = UINT64_C( 0x8000000000000000 ); return; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ exp = softfloat_shiftNormSigF128M( aWPtr, 15, sig ); if ( exp == -128 ) { zSPtr->signExp = packToExtF80UI64( sign, 0 ); zSPtr->signif = 0; return; } if ( sig[indexWord( 4, 0 )] ) sig[indexWord( 4, 1 )] |= 1; softfloat_roundPackMToExtF80M( sign, exp, &sig[indexMultiwordHi( 4, 3 )], 80, zSPtr ); }
uint_fast64_t f128M_to_ui64( const float128_t *aPtr, uint_fast8_t roundingMode, bool exact ) { const uint32_t *aWPtr; uint32_t uiA96; bool sign; int32_t exp; uint32_t sig96; int32_t shiftDist; uint32_t sig[4]; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ aWPtr = (const uint32_t *) aPtr; uiA96 = aWPtr[indexWordHi( 4 )]; sign = signF128UI96( uiA96 ); exp = expF128UI96( uiA96 ); sig96 = fracF128UI96( uiA96 ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ shiftDist = 0x404F - exp; if ( shiftDist < 17 ) { softfloat_raiseFlags( softfloat_flag_invalid ); return (exp == 0x7FFF) && (sig96 || (aWPtr[indexWord( 4, 2 )] | aWPtr[indexWord( 4, 1 )] | aWPtr[indexWord( 4, 0 )])) ? ui64_fromNaN : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( exp ) sig96 |= 0x00010000; sig[indexWord( 4, 3 )] = sig96; sig[indexWord( 4, 2 )] = aWPtr[indexWord( 4, 2 )]; sig[indexWord( 4, 1 )] = aWPtr[indexWord( 4, 1 )]; sig[indexWord( 4, 0 )] = aWPtr[indexWord( 4, 0 )]; softfloat_shiftRightJam128M( sig, shiftDist, sig ); return softfloat_roundMToUI64( sign, sig + indexMultiwordLo( 4, 3 ), roundingMode, exact ); }
int softfloat_normSubnormalF128SigM( uint32_t *sigPtr ) { const uint32_t *ptr; int_fast16_t shiftCount; uint32_t wordSig; ptr = sigPtr + indexWordHi( 4 ); shiftCount = 0; for (;;) { wordSig = *ptr; if ( wordSig ) break; shiftCount += 32; if ( 128 <= shiftCount ) return 1; ptr -= wordIncr; } shiftCount += softfloat_countLeadingZeros32( wordSig ) - 15; if ( shiftCount ) softfloat_shiftLeft128M( sigPtr, shiftCount, sigPtr ); return 1 - shiftCount; }
void softfloat_add256M( const uint64_t *aPtr, const uint64_t *bPtr, uint64_t *zPtr ) { unsigned int index; uint_fast8_t carry; uint64_t wordA, wordZ; index = indexWordLo( 4 ); carry = 0; for (;;) { wordA = aPtr[index]; wordZ = wordA + bPtr[index] + carry; zPtr[index] = wordZ; if ( index == indexWordHi( 4 ) ) break; if ( wordZ != wordA ) carry = (wordZ < wordA); index += wordIncr; } }
int_fast64_t f128M_to_i64( const float128_t *aPtr, uint_fast8_t roundingMode, bool exact ) { const uint32_t *aWPtr; uint32_t uiA96; int32_t exp; bool sign; uint32_t sig96; int32_t shiftCount; uint32_t sig[4]; aWPtr = (const uint32_t *) aPtr; uiA96 = aWPtr[indexWordHi( 4 )]; exp = expF128UI96( uiA96 ); sign = signF128UI96( uiA96 ); sig96 = fracF128UI96( uiA96 ); shiftCount = 0x404F - exp; if ( shiftCount < 17 ) { softfloat_raiseFlags( softfloat_flag_invalid ); return ! sign || ((exp == 0x7FFF) && (sig96 || ( aWPtr[indexWord( 4, 2 )] | aWPtr[indexWord( 4, 1 )] | aWPtr[indexWord( 4, 0 )] ))) ? INT64_C( 0x7FFFFFFFFFFFFFFF ) : -INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1; } if ( exp ) sig96 |= 0x00010000; sig[indexWord( 4, 3 )] = sig96; sig[indexWord( 4, 2 )] = aWPtr[indexWord( 4, 2 )]; sig[indexWord( 4, 1 )] = aWPtr[indexWord( 4, 1 )]; sig[indexWord( 4, 0 )] = aWPtr[indexWord( 4, 0 )]; softfloat_shiftRightJam128M( sig, shiftCount, sig ); return softfloat_roundPackMToI64( sign, sig + indexMultiwordLo( 4, 3 ), roundingMode, exact ); }
uint_fast32_t f128M_to_ui32( const float128_t *aPtr, uint_fast8_t roundingMode, bool exact ) { const uint32_t *aWPtr; uint32_t uiA96; bool sign; int32_t exp; uint64_t sig64; int32_t shiftDist; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ aWPtr = (const uint32_t *) aPtr; uiA96 = aWPtr[indexWordHi( 4 )]; sign = signF128UI96( uiA96 ); exp = expF128UI96( uiA96 ); sig64 = (uint64_t) fracF128UI96( uiA96 )<<32 | aWPtr[indexWord( 4, 2 )]; if ( aWPtr[indexWord( 4, 1 )] | aWPtr[indexWord( 4, 0 )] ) sig64 |= 1; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ #if (ui32_fromNaN != ui32_fromPosOverflow) || (ui32_fromNaN != ui32_fromNegOverflow) if ( (exp == 0x7FFF) && sig64 ) { #if (ui32_fromNaN == ui32_fromPosOverflow) sign = 0; #elif (ui32_fromNaN == ui32_fromNegOverflow) sign = 1; #else softfloat_raiseFlags( softfloat_flag_invalid ); return ui32_fromNaN; #endif } #endif /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( exp ) sig64 |= UINT64_C( 0x0001000000000000 ); shiftDist = 0x4028 - exp; if ( 0 < shiftDist ) sig64 = softfloat_shiftRightJam64( sig64, shiftDist ); return softfloat_roundPackToUI32( sign, sig64, roundingMode, exact ); }
uint_fast32_t f128M_to_ui32( const float128_t *aPtr, uint_fast8_t roundingMode, bool exact ) { const uint32_t *aWPtr; uint32_t uiA96; int32_t exp; uint64_t sig64; int32_t shiftCount; aWPtr = (const uint32_t *) aPtr; uiA96 = aWPtr[indexWordHi( 4 )]; exp = expF128UI96( uiA96 ); sig64 = (uint64_t) fracF128UI96( uiA96 )<<32 | aWPtr[indexWord( 4, 2 )]; if ( exp ) sig64 |= UINT64_C( 0x0001000000000000 ); if ( aWPtr[indexWord( 4, 1 )] | aWPtr[indexWord( 4, 0 )] ) sig64 |= 1; shiftCount = 0x4028 - exp; if ( 0 < shiftCount ) { sig64 = softfloat_shiftRightJam64( sig64, shiftCount ); } return softfloat_roundPackToUI32( signF128UI96( uiA96 ), sig64, roundingMode, exact ); }
void softfloat_roundPackMToF128M( bool sign, int32_t exp, uint32_t *extSigPtr, uint32_t *zWPtr ) { uint_fast8_t roundingMode; bool roundNearEven; uint32_t sigExtra; bool doIncrement, isTiny; static const uint32_t maxSig[4] = INIT_UINTM4( 0x0001FFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF ); uint32_t ui, uj; roundingMode = softfloat_roundingMode; roundNearEven = (roundingMode == softfloat_round_near_even); sigExtra = extSigPtr[indexWordLo( 5 )]; doIncrement = (0x80000000 <= sigExtra); if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) { doIncrement = (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) && sigExtra; } if ( 0x7FFD <= (uint32_t) exp ) { if ( exp < 0 ) { isTiny = (softfloat_detectTininess == softfloat_tininess_beforeRounding) || (exp < -1) || ! doIncrement || (softfloat_compare128M( extSigPtr + indexMultiwordHi( 5, 4 ), maxSig ) < 0); softfloat_shiftRightJam160M( extSigPtr, -exp, extSigPtr ); exp = 0; sigExtra = extSigPtr[indexWordLo( 5 )]; if ( isTiny && sigExtra ) { softfloat_raiseFlags( softfloat_flag_underflow ); } doIncrement = (0x80000000 <= sigExtra); if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) { doIncrement = (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) && sigExtra; } } else if ( (0x7FFD < exp) || ((exp == 0x7FFD) && doIncrement && (softfloat_compare128M( extSigPtr + indexMultiwordHi( 5, 4 ), maxSig ) == 0)) ) { softfloat_raiseFlags( softfloat_flag_overflow | softfloat_flag_inexact ); if ( roundNearEven || (roundingMode == softfloat_round_near_maxMag) || (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) ) { ui = packToF128UI96( sign, 0x7FFF, 0 ); uj = 0; } else { ui = packToF128UI96( sign, 0x7FFE, 0x0000FFFF ); uj = 0xFFFFFFFF; } zWPtr[indexWordHi( 4 )] = ui; zWPtr[indexWord( 4, 2 )] = uj; zWPtr[indexWord( 4, 1 )] = uj; zWPtr[indexWord( 4, 0 )] = uj; return; } } if ( sigExtra ) softfloat_exceptionFlags |= softfloat_flag_inexact; uj = extSigPtr[indexWord( 5, 1 )]; if ( doIncrement ) { ++uj; if ( uj ) { if ( ! (sigExtra & 0x7FFFFFFF) && roundNearEven ) uj &= ~1; zWPtr[indexWord( 4, 2 )] = extSigPtr[indexWord( 5, 3 )]; zWPtr[indexWord( 4, 1 )] = extSigPtr[indexWord( 5, 2 )]; zWPtr[indexWord( 4, 0 )] = uj; ui = extSigPtr[indexWordHi( 5 )]; } else { zWPtr[indexWord( 4, 0 )] = uj; ui = extSigPtr[indexWord( 5, 2 )] + 1; zWPtr[indexWord( 4, 1 )] = ui; uj = extSigPtr[indexWord( 5, 3 )]; if ( ui ) { zWPtr[indexWord( 4, 2 )] = uj; ui = extSigPtr[indexWordHi( 5 )]; } else { ++uj; zWPtr[indexWord( 4, 2 )] = uj; ui = extSigPtr[indexWordHi( 5 )]; if ( ! uj ) ++ui; } } } else { zWPtr[indexWord( 4, 0 )] = uj; ui = extSigPtr[indexWord( 5, 2 )]; zWPtr[indexWord( 4, 1 )] = ui; uj |= ui; ui = extSigPtr[indexWord( 5, 3 )]; zWPtr[indexWord( 4, 2 )] = ui; uj |= ui; ui = extSigPtr[indexWordHi( 5 )]; uj |= ui; if ( ! uj ) exp = 0; } zWPtr[indexWordHi( 4 )] = packToF128UI96( sign, exp, ui ); }
void f128M_mul( const float128_t *aPtr, const float128_t *bPtr, float128_t *zPtr ) { const uint32_t *aWPtr, *bWPtr; uint32_t *zWPtr; uint32_t uiA96; int32_t expA; uint32_t uiB96; int32_t expB; bool signZ; const uint32_t *ptr; uint32_t uiZ96, sigA[4]; uint_fast8_t shiftDist; uint32_t sigB[4]; int32_t expZ; uint32_t sigProd[8], *extSigZPtr; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ aWPtr = (const uint32_t *) aPtr; bWPtr = (const uint32_t *) bPtr; zWPtr = (uint32_t *) zPtr; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiA96 = aWPtr[indexWordHi( 4 )]; expA = expF128UI96( uiA96 ); uiB96 = bWPtr[indexWordHi( 4 )]; expB = expF128UI96( uiB96 ); signZ = signF128UI96( uiA96 ) ^ signF128UI96( uiB96 ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( (expA == 0x7FFF) || (expB == 0x7FFF) ) { if ( softfloat_tryPropagateNaNF128M( aWPtr, bWPtr, zWPtr ) ) return; ptr = aWPtr; if ( ! expA ) goto possiblyInvalid; if ( ! expB ) { ptr = bWPtr; possiblyInvalid: if ( ! fracF128UI96( ptr[indexWordHi( 4 )] ) && ! (ptr[indexWord( 4, 2 )] | ptr[indexWord( 4, 1 )] | ptr[indexWord( 4, 0 )]) ) { softfloat_invalidF128M( zWPtr ); return; } } uiZ96 = packToF128UI96( signZ, 0x7FFF, 0 ); goto uiZ96; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( expA ) { sigA[indexWordHi( 4 )] = fracF128UI96( uiA96 ) | 0x00010000; sigA[indexWord( 4, 2 )] = aWPtr[indexWord( 4, 2 )]; sigA[indexWord( 4, 1 )] = aWPtr[indexWord( 4, 1 )]; sigA[indexWord( 4, 0 )] = aWPtr[indexWord( 4, 0 )]; } else { expA = softfloat_shiftNormSigF128M( aWPtr, 0, sigA ); if ( expA == -128 ) goto zero; } if ( expB ) { sigB[indexWordHi( 4 )] = fracF128UI96( uiB96 ) | 0x00010000; sigB[indexWord( 4, 2 )] = bWPtr[indexWord( 4, 2 )]; sigB[indexWord( 4, 1 )] = bWPtr[indexWord( 4, 1 )]; sigB[indexWord( 4, 0 )] = bWPtr[indexWord( 4, 0 )]; } else { expB = softfloat_shiftNormSigF128M( bWPtr, 0, sigB ); if ( expB == -128 ) goto zero; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expZ = expA + expB - 0x4000; softfloat_mul128MTo256M( sigA, sigB, sigProd ); if ( sigProd[indexWord( 8, 2 )] || (sigProd[indexWord( 8, 1 )] | sigProd[indexWord( 8, 0 )]) ) { sigProd[indexWord( 8, 3 )] |= 1; } extSigZPtr = &sigProd[indexMultiwordHi( 8, 5 )]; shiftDist = 16; if ( extSigZPtr[indexWordHi( 5 )] & 2 ) { ++expZ; shiftDist = 15; } softfloat_shortShiftLeft160M( extSigZPtr, shiftDist, extSigZPtr ); softfloat_roundPackMToF128M( signZ, expZ, extSigZPtr, zWPtr ); return; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ zero: uiZ96 = packToF128UI96( signZ, 0, 0 ); uiZ96: zWPtr[indexWordHi( 4 )] = uiZ96; zWPtr[indexWord( 4, 2 )] = 0; zWPtr[indexWord( 4, 1 )] = 0; zWPtr[indexWord( 4, 0 )] = 0; }
void f128M_roundToInt( const float128_t *aPtr, uint_fast8_t roundingMode, bool exact, float128_t *zPtr ) { const uint32_t *aWPtr; uint32_t *zWPtr; uint32_t ui96; int32_t exp; uint32_t sigExtra; bool sign; uint_fast8_t bitPos; bool roundNear; unsigned int index, lastIndex; bool extra; uint32_t wordA, bit, wordZ; uint_fast8_t carry; uint32_t extrasMask; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ aWPtr = (const uint32_t *) aPtr; zWPtr = (uint32_t *) zPtr; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ ui96 = aWPtr[indexWordHi( 4 )]; exp = expF128UI96( ui96 ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( exp < 0x3FFF ) { zWPtr[indexWord( 4, 2 )] = 0; zWPtr[indexWord( 4, 1 )] = 0; zWPtr[indexWord( 4, 0 )] = 0; sigExtra = aWPtr[indexWord( 4, 2 )]; if ( ! sigExtra ) { sigExtra = aWPtr[indexWord( 4, 1 )] | aWPtr[indexWord( 4, 0 )]; } if ( ! sigExtra && ! (ui96 & 0x7FFFFFFF) ) goto ui96; if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact; sign = signF128UI96( ui96 ); switch ( roundingMode ) { case softfloat_round_near_even: if ( ! fracF128UI96( ui96 ) && ! sigExtra ) break; case softfloat_round_near_maxMag: if ( exp == 0x3FFE ) goto mag1; break; case softfloat_round_min: if ( sign ) goto mag1; break; case softfloat_round_max: if ( ! sign ) goto mag1; break; } ui96 = packToF128UI96( sign, 0, 0 ); goto ui96; mag1: ui96 = packToF128UI96( sign, 0x3FFF, 0 ); goto ui96; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( 0x406F <= exp ) { if ( (exp == 0x7FFF) && (fracF128UI96( ui96 ) || (aWPtr[indexWord( 4, 2 )] | aWPtr[indexWord( 4, 1 )] | aWPtr[indexWord( 4, 0 )])) ) { softfloat_propagateNaNF128M( aWPtr, 0, zWPtr ); return; } zWPtr[indexWord( 4, 2 )] = aWPtr[indexWord( 4, 2 )]; zWPtr[indexWord( 4, 1 )] = aWPtr[indexWord( 4, 1 )]; zWPtr[indexWord( 4, 0 )] = aWPtr[indexWord( 4, 0 )]; goto ui96; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ bitPos = 0x406F - exp; roundNear = (roundingMode == softfloat_round_near_maxMag) || (roundingMode == softfloat_round_near_even); bitPos -= roundNear; index = indexWordLo( 4 ); lastIndex = indexWordHi( 4 ); extra = 0; for (;;) { wordA = aWPtr[index]; if ( bitPos < 32 ) break; if ( wordA ) extra = 1; zWPtr[index] = 0; index += wordIncr; bitPos -= 32; } bit = (uint32_t) 1<<bitPos; if ( roundNear ) { wordZ = wordA + bit; carry = (wordZ < wordA); bit <<= 1; extrasMask = bit - 1; if ( (roundingMode == softfloat_round_near_even) && ! extra && ! (wordZ & extrasMask) ) { if ( ! bit ) { zWPtr[index] = wordZ; index += wordIncr; wordZ = aWPtr[index] + carry; carry &= ! wordZ; zWPtr[index] = wordZ & ~1; goto propagateCarry; } wordZ &= ~bit; } } else { extrasMask = bit - 1; wordZ = wordA; carry = 0; if ( (roundingMode != softfloat_round_minMag) && (signF128UI96( ui96 ) ^ (roundingMode == softfloat_round_max)) ) { if ( extra || (wordA & extrasMask) ) { wordZ += bit; carry = (wordZ < wordA); } } } wordZ &= ~extrasMask; zWPtr[index] = wordZ; propagateCarry: while ( index != lastIndex ) { index += wordIncr; wordZ = aWPtr[index] + carry; zWPtr[index] = wordZ; carry &= ! wordZ; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( exact && (softfloat_compare128M( aWPtr, zWPtr ) != 0) ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } return; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ ui96: zWPtr[indexWordHi( 4 )] = ui96; }