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); }
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; }
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 ); }