Example #1
0
uint_fast32_t f32_to_ui32( 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;
    uint_fast64_t sig64;
    int_fast16_t shiftCount;

    uA.f = a;
    uiA = uA.ui;
    sign = signF32UI( uiA );
    exp = expF32UI( uiA );
    sig = fracF32UI( uiA );
    if ( exp ) sig |= 0x00800000;
    sig64 = (uint_fast64_t) sig<<32;
    shiftCount = 0xAF - exp;
    if ( 0 < shiftCount ) {
        sig64 = softfloat_shift64RightJam( sig64, shiftCount );
    }
    return softfloat_roundPackToUI32( sign, sig64, roundingMode, exact );

}
Example #2
0
float64_t
 softfloat_addMagsF64( uint_fast64_t uiA, uint_fast64_t uiB, bool signZ )
{
    int_fast16_t expA;
    uint_fast64_t sigA;
    int_fast16_t expB;
    uint_fast64_t sigB;
    int_fast16_t expDiff;
    uint_fast64_t uiZ;
    int_fast16_t expZ;
    uint_fast64_t sigZ;
    union ui64_f64 uZ;

    expA = expF64UI( uiA );
    sigA = fracF64UI( uiA );
    expB = expF64UI( uiB );
    sigB = fracF64UI( uiB );
    expDiff = expA - expB;
    sigA <<= 9;
    sigB <<= 9;
    if ( ! expDiff ) {
        if ( expA == 0x7FF ) {
            if ( sigA | sigB ) goto propagateNaN;
            uiZ = uiA;
            goto uiZ;
        }
        if ( ! expA ) {
            uiZ =
                packToF64UI(
                    signZ, 0, ( uiA + uiB ) & UINT64_C( 0x7FFFFFFFFFFFFFFF ) );
            goto uiZ;
        }
        expZ = expA;
        sigZ = UINT64_C( 0x4000000000000000 ) + sigA + sigB;
    } else {
        if ( expDiff < 0 ) {
            if ( expB == 0x7FF ) {
                if ( sigB ) goto propagateNaN;
                uiZ = packToF64UI( signZ, 0x7FF, 0 );
                goto uiZ;
            }
            expZ = expB;
            sigA += expA ? UINT64_C( 0x2000000000000000 ) : sigA;
            sigA = softfloat_shift64RightJam( sigA, - expDiff );
        } else {
            if ( expA == 0x7FF ) {
                if ( sigA ) goto propagateNaN;
                uiZ = uiA;
                goto uiZ;
            }
            expZ = expA;
            sigB += expB ? UINT64_C( 0x2000000000000000 ) : sigB;
            sigB = softfloat_shift64RightJam( sigB, expDiff );
        }
        sigZ = UINT64_C( 0x2000000000000000 ) + sigA + sigB;
        if ( sigZ < UINT64_C( 0x4000000000000000 ) ) {
            --expZ;
            sigZ <<= 1;
        }
    }
    return softfloat_roundPackToF64( signZ, expZ, sigZ );
 propagateNaN:
    uiZ = softfloat_propagateNaNF64UI( uiA, uiB );
 uiZ:
    uZ.ui = uiZ;
    return uZ.f;

}
Example #3
0
float32_t
 softfloat_mulAddF32(
     int op, uint_fast32_t uiA, uint_fast32_t uiB, uint_fast32_t uiC )
{
    bool signA;
    int_fast16_t expA;
    uint_fast32_t sigA;
    bool signB;
    int_fast16_t expB;
    uint_fast32_t sigB;
    bool signC;
    int_fast16_t expC;
    uint_fast32_t sigC;
    bool signProd;
    uint_fast32_t magBits, uiZ;
    struct exp16_sig32 normExpSig;
    int_fast16_t expProd;
    uint_fast64_t sigProd;
    bool signZ;
    int_fast16_t expZ;
    uint_fast32_t sigZ;
    int_fast16_t expDiff;
    uint_fast64_t sigZ64, sigC64;
    int shiftCount;
    union ui32_f32 uZ;

    signA = signF32UI( uiA );
    expA = expF32UI( uiA );
    sigA = fracF32UI( uiA );
    signB = signF32UI( uiB );
    expB = expF32UI( uiB );
    sigB = fracF32UI( uiB );
    signC = signF32UI( uiC ) ^ ( op == softfloat_mulAdd_subC );
    expC = expF32UI( uiC );
    sigC = fracF32UI( uiC );
    signProd = signA ^ signB ^ ( op == softfloat_mulAdd_subProd );
    if ( expA == 0xFF ) {
        if ( sigA || ( ( expB == 0xFF ) && sigB ) ) goto propagateNaN_ABC;
        magBits = expB | sigB;
        goto infProdArg;
    }
    if ( expB == 0xFF ) {
        if ( sigB ) goto propagateNaN_ABC;
        magBits = expA | sigA;
        goto infProdArg;
    }
    if ( expC == 0xFF ) {
        if ( sigC ) {
            uiZ = 0;
            goto propagateNaN_ZC;
        }
        uiZ = uiC;
        goto uiZ;
    }
    if ( ! expA ) {
        if ( ! sigA ) goto zeroProd;
        normExpSig = softfloat_normSubnormalF32Sig( sigA );
        expA = normExpSig.exp;
        sigA = normExpSig.sig;
    }
    if ( ! expB ) {
        if ( ! sigB ) goto zeroProd;
        normExpSig = softfloat_normSubnormalF32Sig( sigB );
        expB = normExpSig.exp;
        sigB = normExpSig.sig;
    }
    expProd = expA + expB - 0x7E;
    sigA = ( sigA | 0x00800000 )<<7;
    sigB = ( sigB | 0x00800000 )<<7;
    sigProd = (uint_fast64_t) sigA * sigB;
    if ( sigProd < UINT64_C( 0x2000000000000000 ) ) {
        --expProd;
        sigProd <<= 1;
    }
    signZ = signProd;
    if ( ! expC ) {
        if ( ! sigC ) {
            expZ = expProd - 1;
            sigZ = softfloat_shortShift64RightJam( sigProd, 31 );
            goto roundPack;
        }
        normExpSig = softfloat_normSubnormalF32Sig( sigC );
        expC = normExpSig.exp;
        sigC = normExpSig.sig;
    }
    sigC = ( sigC | 0x00800000 )<<6;
    expDiff = expProd - expC;
    if ( signProd == signC ) {
        if ( expDiff <= 0 ) {
            expZ = expC;
            sigZ = sigC + softfloat_shift64RightJam( sigProd, 32 - expDiff );
        } else {
            expZ = expProd;
            sigZ64 =
                sigProd
                    + softfloat_shift64RightJam(
                          (uint_fast64_t) sigC<<32, expDiff );
            sigZ = softfloat_shortShift64RightJam( sigZ64, 32 );
        }
        if ( sigZ < 0x40000000 ) {
            --expZ;
            sigZ <<= 1;
        }
    } else {
/*** OPTIMIZE BETTER? ***/
        sigC64 = (uint_fast64_t) sigC<<32;
        if ( expDiff < 0 ) {
            signZ = signC;
            expZ = expC;
            sigZ64 = sigC64 - softfloat_shift64RightJam( sigProd, - expDiff );
        } else if ( ! expDiff ) {
            expZ = expProd;
            sigZ64 = sigProd - sigC64;
            if ( ! sigZ64 ) goto completeCancellation;
            if ( sigZ64 & UINT64_C( 0x8000000000000000 ) ) {
                signZ ^= 1;
                sigZ64 = - sigZ64;
            }
        } else {
            expZ = expProd;
            sigZ64 = sigProd - softfloat_shift64RightJam( sigC64, expDiff );
        }
        shiftCount = softfloat_countLeadingZeros64( sigZ64 ) - 1;
        expZ -= shiftCount;
        shiftCount -= 32;
        if ( shiftCount < 0 ) {
            sigZ = softfloat_shortShift64RightJam( sigZ64, - shiftCount );
        } else {
            sigZ = (uint_fast32_t) sigZ64<<shiftCount;
        }
    }
 roundPack:
    return softfloat_roundPackToF32( signZ, expZ, sigZ );
 propagateNaN_ABC:
    uiZ = softfloat_propagateNaNF32UI( uiA, uiB );
    goto propagateNaN_ZC;
 infProdArg:
    if ( magBits ) {
        uiZ = packToF32UI( signProd, 0xFF, 0 );
        if ( expC != 0xFF ) goto uiZ;
        if ( sigC ) goto propagateNaN_ZC;
        if ( signProd == signC ) goto uiZ;
    }
// invalid:
    softfloat_raiseFlags( softfloat_flag_invalid );
    uiZ = defaultNaNF32UI;
 propagateNaN_ZC:
    uiZ = softfloat_propagateNaNF32UI( uiZ, uiC );
    goto uiZ;
 zeroProd:
    uiZ = uiC;
    if ( ! ( expC | sigC ) && ( signProd != signC ) ) {
 completeCancellation:
        uiZ =
            packToF32UI( softfloat_roundingMode == softfloat_round_min, 0, 0 );
    }
 uiZ:
    uZ.ui = uiZ;
    return uZ.f;

}
Example #4
0
float64_t
 softfloat_mulAddF64(
     int op, uint_fast64_t uiA, uint_fast64_t uiB, uint_fast64_t uiC )
{
    bool signA;
    int_fast16_t expA;
    uint_fast64_t sigA;
    bool signB;
    int_fast16_t expB;
    uint_fast64_t sigB;
    bool signC;
    int_fast16_t expC;
    uint_fast64_t sigC;
    bool signProd;
    uint_fast64_t magBits, uiZ;
    struct exp16_sig64 normExpSig;
    int_fast16_t expProd;
    struct uint128 sigProd;
    bool signZ;
    int_fast16_t expZ;
    uint_fast64_t sigZ;
    int_fast16_t expDiff;
    struct uint128 sigC128, sigZ128;
    int shiftCount;
    union ui64_f64 uZ;

    signA = signF64UI( uiA );
    expA = expF64UI( uiA );
    sigA = fracF64UI( uiA );
    signB = signF64UI( uiB );
    expB = expF64UI( uiB );
    sigB = fracF64UI( uiB );
    signC = signF64UI( uiC ) ^ (( op & softfloat_mulAdd_subC ) != 0);
    expC = expF64UI( uiC );
    sigC = fracF64UI( uiC );
    signProd = signA ^ signB ^ ( ( op & softfloat_mulAdd_subProd ) != 0);
    if ( expA == 0x7FF ) {
        if ( sigA || ( ( expB == 0x7FF ) && sigB ) ) goto propagateNaN_ABC;
        magBits = expB | sigB;
        goto infProdArg;
    }
    if ( expB == 0x7FF ) {
        if ( sigB ) goto propagateNaN_ABC;
        magBits = expA | sigA;
        goto infProdArg;
    }
    if ( expC == 0x7FF ) {
        if ( sigC ) {
            uiZ = 0;
            goto propagateNaN_ZC;
        }
        uiZ = uiC;
        goto uiZ;
    }
    if ( ! expA ) {
        if ( ! sigA ) goto zeroProd;
        normExpSig = softfloat_normSubnormalF64Sig( sigA );
        expA = normExpSig.exp;
        sigA = normExpSig.sig;
    }
    if ( ! expB ) {
        if ( ! sigB ) goto zeroProd;
        normExpSig = softfloat_normSubnormalF64Sig( sigB );
        expB = normExpSig.exp;
        sigB = normExpSig.sig;
    }
    expProd = expA + expB - 0x3FE;
    sigA = ( sigA | UINT64_C( 0x0010000000000000 ) )<<10;
    sigB = ( sigB | UINT64_C( 0x0010000000000000 ) )<<10;
    sigProd = softfloat_mul64To128( sigA, sigB );
    if ( sigProd.v64 < UINT64_C( 0x2000000000000000 ) ) {
        --expProd;
        sigProd = softfloat_shortShift128Left( sigProd.v64, sigProd.v0, 1 );
    }
    signZ = signProd;
    if ( ! expC ) {
        if ( ! sigC ) {
            expZ = expProd - 1;
            sigZ = sigProd.v64<<1 | ( sigProd.v0 != 0 );
            goto roundPack;
        }
        normExpSig = softfloat_normSubnormalF64Sig( sigC );
        expC = normExpSig.exp;
        sigC = normExpSig.sig;
    }
    sigC = ( sigC | UINT64_C( 0x0010000000000000 ) )<<9;
    expDiff = expProd - expC;
    if ( signProd == signC ) {
        if ( expDiff <= 0 ) {
            expZ = expC;
            if ( expDiff ) {
                sigProd.v64 =
                    softfloat_shift64RightJam( sigProd.v64, - expDiff );
            }
            sigZ = ( sigC + sigProd.v64 ) | ( sigProd.v0 != 0 );
        } else {
            expZ = expProd;
            sigC128 = softfloat_shift128RightJam( sigC, 0, expDiff );
            sigZ128 =
                softfloat_add128(
                    sigProd.v64, sigProd.v0, sigC128.v64, sigC128.v0 );
            sigZ = sigZ128.v64 | ( sigZ128.v0 != 0 );
        }
        if ( sigZ < UINT64_C( 0x4000000000000000 ) ) {
            --expZ;
            sigZ <<= 1;
        }
    } else {
/*** OPTIMIZE BETTER? ***/
        if ( expDiff < 0 ) {
            signZ = signC;
            expZ = expC;
            sigProd =
                softfloat_shift128RightJam(
                    sigProd.v64, sigProd.v0, - expDiff );
            sigZ128 = softfloat_sub128( sigC, 0, sigProd.v64, sigProd.v0 );
        } else if ( ! expDiff ) {
            expZ = expProd;
            sigZ128 = softfloat_sub128( sigProd.v64, sigProd.v0, sigC, 0 );
            if ( ! ( sigZ128.v64 | sigZ128.v0 ) ) goto completeCancellation;
            if ( sigZ128.v64 & UINT64_C( 0x8000000000000000 ) ) {
                signZ ^= 1;
                sigZ128 = softfloat_sub128( 0, 0, sigZ128.v64, sigZ128.v0 );
            }
        } else {
            expZ = expProd;
            sigC128 = softfloat_shift128RightJam( sigC, 0, expDiff );
            sigZ128 =
                softfloat_sub128(
                    sigProd.v64, sigProd.v0, sigC128.v64, sigC128.v0 );
        }
        if ( ! sigZ128.v64 ) {
            expZ -= 64;
            sigZ128.v64 = sigZ128.v0;
            sigZ128.v0 = 0;
        }
        shiftCount = softfloat_countLeadingZeros64( sigZ128.v64 ) - 1;
        expZ -= shiftCount;
        if ( shiftCount < 0 ) {
            sigZ = softfloat_shortShift64RightJam( sigZ128.v64, - shiftCount );
        } else {
            sigZ128 =
                softfloat_shortShift128Left(
                    sigZ128.v64, sigZ128.v0, shiftCount );
            sigZ = sigZ128.v64;
        }
        sigZ |= ( sigZ128.v0 != 0 );
    }
 roundPack:
    return softfloat_roundPackToF64( signZ, expZ, sigZ );
 propagateNaN_ABC:
    uiZ = softfloat_propagateNaNF64UI( uiA, uiB );
    goto propagateNaN_ZC;
 infProdArg:
    if ( magBits ) {
        uiZ = packToF64UI( signProd, 0x7FF, 0 );
        if ( expC != 0x7FF ) goto uiZ;
        if ( sigC ) goto propagateNaN_ZC;
        if ( signProd == signC ) goto uiZ;
    }
 invalid:
    softfloat_raiseFlags( softfloat_flag_invalid );
    uiZ = defaultNaNF64UI;
 propagateNaN_ZC:
    uiZ = softfloat_propagateNaNF64UI( uiZ, uiC );
    goto uiZ;
 zeroProd:
    uiZ = uiC;
    if ( ! ( expC | sigC ) && ( signProd != signC ) ) {
 completeCancellation:
        uiZ =
            packToF64UI( softfloat_roundingMode == softfloat_round_min, 0, 0 );
    }
 uiZ:
    uZ.ui = uiZ;
    return uZ.f;

}