float32_t i32_to_f32( int32_t a ) { bool sign; union ui32_f32 uZ; uint_fast32_t absA; sign = (a < 0); if ( ! (a & 0x7FFFFFFF) ) { uZ.ui = sign ? packToF32UI( 1, 0x9E, 0 ) : 0; return uZ.f; } absA = sign ? -(uint_fast32_t) a : (uint_fast32_t) a; return softfloat_normRoundPackToF32( sign, 0x9C, absA ); }
float32_t ui32_to_f32( uint_fast32_t a ) { union ui32_f32 uZ; if ( ! a ) { uZ.ui = 0; return uZ.f; } if ( a & 0x80000000 ) { return softfloat_roundPackToF32( 0, 0x9D, softfloat_shortShift32Right1Jam( a ) ); } else { return softfloat_normRoundPackToF32( 0, 0x9C, a ); } }
float32_t f32_rem( float32_t a, float32_t b ) { union ui32_f32 uA; uint_fast32_t uiA; bool signA; int_fast16_t expA; uint_fast32_t sigA; union ui32_f32 uB; uint_fast32_t uiB; int_fast16_t expB; uint_fast32_t sigB; struct exp16_sig32 normExpSig; uint32_t rem; int_fast16_t expDiff; uint32_t q, recip32, altRem, meanRem; bool signRem; uint_fast32_t uiZ; union ui32_f32 uZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uA.f = a; uiA = uA.ui; signA = signF32UI( uiA ); expA = expF32UI( uiA ); sigA = fracF32UI( uiA ); uB.f = b; uiB = uB.ui; expB = expF32UI( uiB ); sigB = fracF32UI( uiB ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( expA == 0xFF ) { if ( sigA || ((expB == 0xFF) && sigB) ) goto propagateNaN; goto invalid; } if ( expB == 0xFF ) { if ( sigB ) goto propagateNaN; return a; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ! expB ) { if ( ! sigB ) goto invalid; normExpSig = softfloat_normSubnormalF32Sig( sigB ); expB = normExpSig.exp; sigB = normExpSig.sig; } if ( ! expA ) { if ( ! sigA ) return a; normExpSig = softfloat_normSubnormalF32Sig( sigA ); expA = normExpSig.exp; sigA = normExpSig.sig; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ rem = sigA | 0x00800000; sigB |= 0x00800000; expDiff = expA - expB; if ( expDiff < 1 ) { if ( expDiff < -1 ) return a; sigB <<= 6; if ( expDiff ) { rem <<= 5; q = 0; } else { rem <<= 6; q = (sigB <= rem); if ( q ) rem -= sigB; } } else { recip32 = softfloat_approxRecip32_1( sigB<<8 ); /*-------------------------------------------------------------------- | Changing the shift of `rem' here requires also changing the initial | subtraction from `expDiff'. *--------------------------------------------------------------------*/ rem <<= 7; expDiff -= 31; /*-------------------------------------------------------------------- | The scale of `sigB' affects how many bits are obtained during each | cycle of the loop. Currently this is 29 bits per loop iteration, | which is believed to be the maximum possible. *--------------------------------------------------------------------*/ sigB <<= 6; for (;;) { q = (rem * (uint_fast64_t) recip32)>>32; if ( expDiff < 0 ) break; rem = -(q * (uint32_t) sigB); expDiff -= 29; } /*-------------------------------------------------------------------- | (`expDiff' cannot be less than -30 here.) *--------------------------------------------------------------------*/ q >>= ~expDiff & 31; rem = (rem<<(expDiff + 30)) - q * (uint32_t) sigB; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ do { altRem = rem; ++q; rem -= sigB; } while ( ! (rem & 0x80000000) ); meanRem = rem + altRem; if ( (meanRem & 0x80000000) || (! meanRem && (q & 1)) ) rem = altRem; signRem = signA; if ( 0x80000000 <= rem ) { signRem = ! signRem; rem = -rem; } return softfloat_normRoundPackToF32( signRem, expB, rem ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ propagateNaN: uiZ = softfloat_propagateNaNF32UI( uiA, uiB ); goto uiZ; invalid: softfloat_raiseFlags( softfloat_flag_invalid ); uiZ = defaultNaNF32UI; uiZ: uZ.ui = uiZ; return uZ.f; }
float32_t softfloat_subMagsF32( uint_fast32_t uiA, uint_fast32_t uiB ) { int_fast16_t expA; uint_fast32_t sigA; int_fast16_t expB; uint_fast32_t sigB; int_fast16_t expDiff; uint_fast32_t uiZ; int_fast32_t sigDiff; bool signZ; int_fast8_t shiftDist; int_fast16_t expZ; uint_fast32_t sigX, sigY; union ui32_f32 uZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expA = expF32UI( uiA ); sigA = fracF32UI( uiA ); expB = expF32UI( uiB ); sigB = fracF32UI( uiB ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expDiff = expA - expB; if ( ! expDiff ) { /*-------------------------------------------------------------------- *--------------------------------------------------------------------*/ if ( expA == 0xFF ) { if ( sigA | sigB ) goto propagateNaN; softfloat_raiseFlags( softfloat_flag_invalid ); uiZ = defaultNaNF32UI; goto uiZ; } sigDiff = sigA - sigB; if ( ! sigDiff ) { uiZ = packToF32UI( (softfloat_roundingMode == softfloat_round_min), 0, 0 ); goto uiZ; } if ( expA ) --expA; signZ = signF32UI( uiA ); if ( sigDiff < 0 ) { signZ = ! signZ; sigDiff = -sigDiff; } shiftDist = softfloat_countLeadingZeros32( sigDiff ) - 8; expZ = expA - shiftDist; if ( expZ < 0 ) { shiftDist = expA; expZ = 0; } uiZ = packToF32UI( signZ, expZ, sigDiff<<shiftDist ); goto uiZ; } else { /*-------------------------------------------------------------------- *--------------------------------------------------------------------*/ signZ = signF32UI( uiA ); sigA <<= 7; sigB <<= 7; if ( expDiff < 0 ) { /*---------------------------------------------------------------- *----------------------------------------------------------------*/ signZ = ! signZ; if ( expB == 0xFF ) { if ( sigB ) goto propagateNaN; uiZ = packToF32UI( signZ, 0xFF, 0 ); goto uiZ; } expZ = expB - 1; sigX = sigB | 0x40000000; sigY = sigA + (expA ? 0x40000000 : sigA); expDiff = -expDiff; } else { /*---------------------------------------------------------------- *----------------------------------------------------------------*/ if ( expA == 0xFF ) { if ( sigA ) goto propagateNaN; uiZ = uiA; goto uiZ; } expZ = expA - 1; sigX = sigA | 0x40000000; sigY = sigB + (expB ? 0x40000000 : sigB); } return softfloat_normRoundPackToF32( signZ, expZ, sigX - softfloat_shiftRightJam32( sigY, expDiff ) ); } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ propagateNaN: uiZ = softfloat_propagateNaNF32UI( uiA, uiB ); uiZ: uZ.ui = uiZ; return uZ.f; }
float32_t softfloat_subMagsF32( uint_fast32_t uiA, uint_fast32_t uiB, bool signZ ) { int_fast16_t expA; uint_fast32_t sigA; int_fast16_t expB; uint_fast32_t sigB; int_fast16_t expDiff; uint_fast32_t uiZ; int_fast16_t expZ; uint_fast32_t sigZ; union ui32_f32 uZ; expA = expF32UI( uiA ); sigA = fracF32UI( uiA ); expB = expF32UI( uiB ); sigB = fracF32UI( uiB ); expDiff = expA - expB; sigA <<= 7; sigB <<= 7; if ( 0 < expDiff ) goto expABigger; if ( expDiff < 0 ) goto expBBigger; if ( expA == 0xFF ) { if ( sigA | sigB ) goto propagateNaN; softfloat_raiseFlags( softfloat_flag_invalid ); uiZ = defaultNaNF32UI; goto uiZ; } if ( ! expA ) { expA = 1; expB = 1; } if ( sigB < sigA ) goto aBigger; if ( sigA < sigB ) goto bBigger; uiZ = packToF32UI( softfloat_roundingMode == softfloat_round_min, 0, 0 ); goto uiZ; expBBigger: if ( expB == 0xFF ) { if ( sigB ) goto propagateNaN; uiZ = packToF32UI( signZ ^ 1, 0xFF, 0 ); goto uiZ; } sigA += expA ? 0x40000000 : sigA; sigA = softfloat_shift32RightJam( sigA, - expDiff ); sigB |= 0x40000000; bBigger: signZ ^= 1; expZ = expB; sigZ = sigB - sigA; goto normRoundPack; expABigger: if ( expA == 0xFF ) { if ( sigA ) goto propagateNaN; uiZ = uiA; goto uiZ; } sigB += expB ? 0x40000000 : sigB; sigB = softfloat_shift32RightJam( sigB, expDiff ); sigA |= 0x40000000; aBigger: expZ = expA; sigZ = sigA - sigB; normRoundPack: return softfloat_normRoundPackToF32( signZ, expZ - 1, sigZ ); propagateNaN: uiZ = softfloat_propagateNaNF32UI( uiA, uiB ); uiZ: uZ.ui = uiZ; return uZ.f; }