#include #include #include "platform.h" #include "primitives.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" float32_t f32_sqrt( float32_t a ) { union ui32_f32 uA; uint_fast32_t uiA; bool signA; int_fast16_t expA; uint_fast32_t sigA, uiZ; struct exp16_sig32 normExpSig; int_fast16_t expZ; uint_fast32_t sigZ; uint_fast64_t term, rem; union ui32_f32 uZ; uA.f = a; uiA = uA.ui; signA = signF32UI( uiA ); expA = expF32UI( uiA ); sigA = fracF32UI( uiA ); if ( expA == 0xFF ) { if ( sigA ) { uiZ = softfloat_propagateNaNF32UI( uiA, 0 ); goto uiZ; } if ( ! signA ) return a; goto invalid; } if ( signA ) { if ( ! ( expA | sigA ) ) return a; goto invalid; } if ( ! expA ) { if ( ! sigA ) return a; normExpSig = softfloat_normSubnormalF32Sig( sigA ); expA = normExpSig.exp; sigA = normExpSig.sig; } expZ = ( ( expA - 0x7F )>>1 ) + 0x7E; sigA = ( sigA | 0x00800000 )<<8; sigZ = softfloat_estimateSqrt32( expA, sigA ) + 2; if ( ( sigZ & 0x7F ) <= 5 ) { if ( sigZ < 2 ) { sigZ = 0x7FFFFFFF; goto roundPack; } sigA >>= expA & 1; term = (uint_fast64_t) sigZ * sigZ; rem = ( (uint_fast64_t) sigA<<32 ) - term; while ( UINT64_C( 0x8000000000000000 ) <= rem ) { --sigZ; rem += ( (uint_fast64_t) sigZ<<1 ) | 1; } sigZ |= ( rem != 0 ); } sigZ = softfloat_shortShift32Right1Jam( sigZ ); roundPack: return softfloat_roundPackToF32( 0, expZ, sigZ ); invalid: softfloat_raiseFlags( softfloat_flag_invalid ); uiZ = defaultNaNF32UI; uiZ: uZ.ui = uiZ; return uZ.f; }