Exemple #1
0
bool f128_le( float128_t a, float128_t b )
{
    union ui128_f128 uA;
    uint_fast64_t uiA64, uiA0;
    union ui128_f128 uB;
    uint_fast64_t uiB64, uiB0;
    bool signA, signB;

    uA.f = a;
    uiA64 = uA.ui.v64;
    uiA0  = uA.ui.v0;
    uB.f = b;
    uiB64 = uB.ui.v64;
    uiB0  = uB.ui.v0;
    if ( isNaNF128UI( uiA64, uiA0 ) || isNaNF128UI( uiB64, uiB0 ) ) {
        softfloat_raiseFlags( softfloat_flag_invalid );
        return false;
    }
    signA = signF128UI64( uiA64 );
    signB = signF128UI64( uiB64 );
    return
        (signA != signB)
            ? signA
                  || ! (((uiA64 | uiB64) & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
                            | uiA0 | uiB0)
            : ((uiA64 == uiB64) && (uiA0 == uiB0))
                  || (signA ^ softfloat_lt128( uiA64, uiA0, uiB64, uiB0 ));

}
Exemple #2
0
void
 f128M_sub( const float128_t *aPtr, const float128_t *bPtr, float128_t *zPtr )
{
    const uint64_t *aWPtr, *bWPtr;
    uint_fast64_t uiA64, uiA0;
    bool signA;
    uint_fast64_t uiB64, uiB0;
    bool signB;
#if ! defined INLINE_LEVEL || (INLINE_LEVEL < 2)
    float128_t
        (*magsFuncPtr)(
            uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool );
#endif

    aWPtr = (const uint64_t *) aPtr;
    bWPtr = (const uint64_t *) bPtr;
    uiA64 = aWPtr[indexWord( 2, 1 )];
    uiA0  = aWPtr[indexWord( 2, 0 )];
    signA = signF128UI64( uiA64 );
    uiB64 = bWPtr[indexWord( 2, 1 )];
    uiB0  = bWPtr[indexWord( 2, 0 )];
    signB = signF128UI64( uiB64 );
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
    if ( signA == signB ) {
        *zPtr = softfloat_subMagsF128( uiA64, uiA0, uiB64, uiB0, signA );
    } else {
        *zPtr = softfloat_addMagsF128( uiA64, uiA0, uiB64, uiB0, signA );
    }
#else
    magsFuncPtr =
        (signA == signB) ? softfloat_subMagsF128 : softfloat_addMagsF128;
    *zPtr = (*magsFuncPtr)( uiA64, uiA0, uiB64, uiB0, signA );
#endif

}
Exemple #3
0
float128_t f128_sub( float128_t a, float128_t b )
{
    union ui128_f128 uA;
    uint_fast64_t uiA64, uiA0;
    bool signA;
    union ui128_f128 uB;
    uint_fast64_t uiB64, uiB0;
    bool signB;
#if ! defined INLINE_LEVEL || (INLINE_LEVEL < 2)
    float128_t
        (*magsFuncPtr)(
            uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool );
#endif

    uA.f = a;
    uiA64 = uA.ui.v64;
    uiA0  = uA.ui.v0;
    signA = signF128UI64( uiA64 );
    uB.f = b;
    uiB64 = uB.ui.v64;
    uiB0  = uB.ui.v0;
    signB = signF128UI64( uiB64 );
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
    if ( signA == signB ) {
        return softfloat_subMagsF128( uiA64, uiA0, uiB64, uiB0, signA );
    } else {
        return softfloat_addMagsF128( uiA64, uiA0, uiB64, uiB0, signA );
    }
#else
    magsFuncPtr =
        (signA == signB) ? softfloat_subMagsF128 : softfloat_addMagsF128;
    return (*magsFuncPtr)( uiA64, uiA0, uiB64, uiB0, signA );
#endif

}
uint_fast32_t
 f128_to_ui32( float128_t a, uint_fast8_t roundingMode, bool exact )
{
    union ui128_f128 uA;
    uint_fast64_t uiA64, uiA0;
    bool sign;
    int_fast32_t exp;
    uint_fast64_t sig64, sig0;
    int_fast32_t shiftCount;

    uA.f = a;
    uiA64 = uA.ui.v64;
    uiA0  = uA.ui.v0;
    sign  = signF128UI64( uiA64 );
    exp   = expF128UI64( uiA64 );
    sig64 = fracF128UI64( uiA64 );
    sig0  = uiA0;
    if ( exp ) sig64 |= UINT64_C( 0x0001000000000000 );
    sig64 |= (sig0 != 0);
    shiftCount = 0x4028 - exp;
    if ( 0 < shiftCount ) {
        sig64 = softfloat_shiftRightJam64( sig64, shiftCount );
    }
    return softfloat_roundPackToUI32( sign, sig64, roundingMode, exact );

}
Exemple #5
0
uint_fast16_t f128_classify( float128_t a )
{
    union ui128_f128 uA;
    uint_fast64_t uiA64, uiA0;

    uA.f = a;
    uiA64 = uA.ui.v64;
    uiA0  = uA.ui.v0;

    uint_fast16_t infOrNaN = expF128UI64( uiA64 ) == 0x7FFF;
    uint_fast16_t subnormalOrZero = expF128UI64( uiA64 ) == 0;
    bool sign = signF128UI64( uiA64 );
    bool fracZero = fracF128UI64( uiA64 ) == 0 && uiA0 == 0;
    bool isNaN = isNaNF128UI( uiA64, uiA0 );
    bool isSNaN = softfloat_isSigNaNF128UI( uiA64, uiA0 );

    return
        (  sign && infOrNaN && fracZero )          << 0 |
        (  sign && !infOrNaN && !subnormalOrZero ) << 1 |
        (  sign && subnormalOrZero && !fracZero )  << 2 |
        (  sign && subnormalOrZero && fracZero )   << 3 |
        ( !sign && infOrNaN && fracZero )          << 7 |
        ( !sign && !infOrNaN && !subnormalOrZero ) << 6 |
        ( !sign && subnormalOrZero && !fracZero )  << 5 |
        ( !sign && subnormalOrZero && fracZero )   << 4 |
        ( isNaN &&  isSNaN )                       << 8 |
        ( isNaN && !isSNaN )                       << 9;
}
int_fast32_t f128_to_i32_r_minMag( float128_t a, bool exact )
{
    union ui128_f128 uA;
    uint_fast64_t uiA64, uiA0;
    int_fast32_t exp;
    uint_fast64_t sig64;
    int_fast32_t shiftDist;
    bool sign;
    int_fast32_t absZ;

    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    uA.f = a;
    uiA64 = uA.ui.v64;
    uiA0  = uA.ui.v0;
    exp   = expF128UI64( uiA64 );
    sig64 = fracF128UI64( uiA64 ) | (uiA0 != 0);
    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    shiftDist = 0x402F - exp;
    if ( 49 <= shiftDist ) {
        if ( exact && (exp | sig64) ) {
            softfloat_exceptionFlags |= softfloat_flag_inexact;
        }
        return 0;
    }
    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    sign = signF128UI64( uiA64 );
    if ( shiftDist < 18 ) {
        if (
            sign && (shiftDist == 17)
                && (sig64 < UINT64_C( 0x0000000000020000 ))
        ) {
            if ( exact && sig64 ) {
                softfloat_exceptionFlags |= softfloat_flag_inexact;
            }
            return -0x7FFFFFFF - 1;
        }
        softfloat_raiseFlags( softfloat_flag_invalid );
        return
            (exp == 0x7FFF) && sig64 ? i32_fromNaN
                : sign ? i32_fromNegOverflow : i32_fromPosOverflow;
    }
    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    sig64 |= UINT64_C( 0x0001000000000000 );
    absZ = sig64>>shiftDist;
    if (
        exact && ((uint_fast64_t) (uint_fast32_t) absZ<<shiftDist != sig64)
    ) {
        softfloat_exceptionFlags |= softfloat_flag_inexact;
    }
    return sign ? -absZ : absZ;

}
Exemple #7
0
float64_t f128_to_f64( float128_t a )
{
    union ui128_f128 uA;
    uint_fast64_t uiA64, uiA0;
    bool sign;
    int_fast32_t exp;
    uint_fast64_t frac64, frac0;
    struct commonNaN commonNaN;
    uint_fast64_t uiZ;
    struct uint128 frac128;
    union ui64_f64 uZ;

    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    uA.f = a;
    uiA64 = uA.ui.v64;
    uiA0  = uA.ui.v0;
    sign  = signF128UI64( uiA64 );
    exp   = expF128UI64( uiA64 );
    frac64 = fracF128UI64( uiA64 );
    frac0  = uiA0;
    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    if ( exp == 0x7FFF ) {
        if ( frac64 | frac0 ) {
            softfloat_f128UIToCommonNaN( uiA64, uiA0, &commonNaN );
            uiZ = softfloat_commonNaNToF64UI( &commonNaN );
        } else {
            uiZ = packToF64UI( sign, 0x7FF, 0 );
        }
        goto uiZ;
    }
    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    frac128 = softfloat_shortShiftLeft128( frac64, frac0, 14 );
    frac64 = frac128.v64 | (frac128.v0 != 0);
    if ( ! (exp | frac64) ) {
        uiZ = packToF64UI( sign, 0, 0 );
        goto uiZ;
    }
    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    exp -= 0x3C01;
    if ( sizeof (int_fast16_t) < sizeof (int_fast32_t) ) {
        if ( exp < -0x1000 ) exp = -0x1000;
    }
    return
        softfloat_roundPackToF64(
            sign, exp, frac64 | UINT64_C( 0x4000000000000000 ) );
    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
 uiZ:
    uZ.ui = uiZ;
    return uZ.f;

}
Exemple #8
0
extFloat80_t f128_to_extF80( float128_t a )
{
    union ui128_f128 uA;
    uint_fast64_t uiA64, uiA0;
    bool sign;
    int_fast32_t exp;
    uint_fast64_t sig64, sig0;
    struct commonNaN commonNaN;
    struct uint128 uiZ;
    uint_fast16_t uiZ64;
    uint_fast64_t uiZ0;
    struct exp32_sig128 normExpSig;
    struct uint128 sig128;
    union { struct extFloat80M s; extFloat80_t f; } uZ;

    uA.f = a;
    uiA64 = uA.ui.v64;
    uiA0  = uA.ui.v0;
    sign  = signF128UI64( uiA64 );
    exp   = expF128UI64( uiA64 );
    sig64 = fracF128UI64( uiA64 );
    sig0  = uiA0;
    if ( exp == 0x7FFF ) {
        if ( sig64 | sig0 ) {
            softfloat_f128UIToCommonNaN( uiA64, uiA0, &commonNaN );
            uiZ = softfloat_commonNaNToExtF80UI( &commonNaN );
            uiZ64 = uiZ.v64;
            uiZ0  = uiZ.v0;
        } else {
            uiZ64 = packToExtF80UI64( sign, 0x7FFF );
            uiZ0  = UINT64_C( 0x8000000000000000 );
        }
        goto uiZ;
    }
    if ( ! exp ) {
        if ( ! (sig64 | sig0) ) {
            uiZ64 = packToExtF80UI64( sign, 0 );
            uiZ0  = 0;
            goto uiZ;
        }
        normExpSig = softfloat_normSubnormalF128Sig( sig64, sig0 );
        exp   = normExpSig.exp;
        sig64 = normExpSig.sig.v64;
        sig0  = normExpSig.sig.v0;
    } else {
        sig64 |= UINT64_C( 0x0001000000000000 );
    }
    sig128 = softfloat_shortShiftLeft128( sig64, sig0, 15 );
    return softfloat_roundPackToExtF80( sign, exp, sig128.v64, sig128.v0, 80 );
 uiZ:
    uZ.s.signExp = uiZ64;
    uZ.s.signif  = uiZ0;
    return uZ.f;

}
Exemple #9
0
uint_fast64_t
 f128_to_ui64( float128_t a, uint_fast8_t roundingMode, bool exact )
{
    union ui128_f128 uA;
    uint_fast64_t uiA64, uiA0;
    bool sign;
    int_fast32_t exp;
    uint_fast64_t sig64, sig0;
    int_fast32_t shiftDist;
    struct uint128 sig128;
    struct uint64_extra sigExtra;

    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    uA.f = a;
    uiA64 = uA.ui.v64;
    uiA0  = uA.ui.v0;
    sign  = signF128UI64( uiA64 );
    exp   = expF128UI64( uiA64 );
    sig64 = fracF128UI64( uiA64 );
    sig0  = uiA0;
    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    shiftDist = 0x402F - exp;
    if ( shiftDist <= 0 ) {
        /*--------------------------------------------------------------------
        *--------------------------------------------------------------------*/
        if ( shiftDist < -15 ) {
            softfloat_raiseFlags( softfloat_flag_invalid );
            return
                (exp == 0x7FFF) && (sig64 | sig0) ? ui64_fromNaN
                    : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow;
        }
        /*--------------------------------------------------------------------
        *--------------------------------------------------------------------*/
        sig64 |= UINT64_C( 0x0001000000000000 );
        if ( shiftDist ) {
            sig128 = softfloat_shortShiftLeft128( sig64, sig0, -shiftDist );
            sig64 = sig128.v64;
            sig0  = sig128.v0;
        }
    } else {
        /*--------------------------------------------------------------------
        *--------------------------------------------------------------------*/
        if ( exp ) sig64 |= UINT64_C( 0x0001000000000000 );
        sigExtra = softfloat_shiftRightJam64Extra( sig64, sig0, shiftDist );
        sig64 = sigExtra.v;
        sig0  = sigExtra.extra;
    }
    return softfloat_roundToUI64( sign, sig64, sig0, roundingMode, exact );

}
Exemple #10
0
float32_t f128_to_f32( float128_t a )
{
    union ui128_f128 uA;
    uint_fast64_t uiA64, uiA0;
    bool sign;
    int_fast32_t exp;
    uint_fast64_t frac64;
    struct commonNaN commonNaN;
    uint_fast32_t uiZ, frac32;
    union ui32_f32 uZ;

    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    uA.f = a;
    uiA64 = uA.ui.v64;
    uiA0  = uA.ui.v0;
    sign  = signF128UI64( uiA64 );
    exp   = expF128UI64( uiA64 );
    frac64 = fracF128UI64( uiA64 ) | (uiA0 != 0);
    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    if ( exp == 0x7FFF ) {
        if ( frac64 ) {
            softfloat_f128UIToCommonNaN( uiA64, uiA0, &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 (int_fast32_t) ) {
        if ( exp < -0x1000 ) exp = -0x1000;
    }
    return softfloat_roundPackToF32( sign, exp, frac32 | 0x40000000 );
    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
 uiZ:
    uZ.ui = uiZ;
    return uZ.f;

}
uint_fast32_t f128_to_ui32_r_minMag( float128_t a, bool exact )
{
    union ui128_f128 uA;
    uint_fast64_t uiA64, uiA0;
    int_fast32_t exp;
    uint_fast64_t sig64;
    int_fast32_t shiftDist;
    bool sign;
    uint_fast32_t z;

    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    uA.f = a;
    uiA64 = uA.ui.v64;
    uiA0  = uA.ui.v0;
    exp   = expF128UI64( uiA64 );
    sig64 = fracF128UI64( uiA64 ) | (uiA0 != 0);
    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    shiftDist = 0x402F - exp;
    if ( 49 <= shiftDist ) {
        if ( exact && (exp | sig64) ) {
            softfloat_raiseFlags( softfloat_flag_inexact );
        }
        return 0;
    }
    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    sign = signF128UI64( uiA64 );
    if ( sign || (shiftDist < 17) ) {
        softfloat_raiseFlags( softfloat_flag_invalid );
        return
            (exp == 0x7FFF) && sig64 ? ui32_fromNaN
                : sign ? ui32_fromNegOverflow : ui32_fromPosOverflow;
    }
    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    sig64 |= UINT64_C( 0x0001000000000000 );
    z = sig64>>shiftDist;
    if ( exact && ((uint_fast64_t) z<<shiftDist != sig64) ) {
        softfloat_raiseFlags( softfloat_flag_inexact );
    }
    return z;

}
Exemple #12
0
int_fast64_t f128_to_i64( float128_t a, uint_fast8_t roundingMode, bool exact )
{
    union ui128_f128 uA;
    uint_fast64_t uiA64, uiA0;
    bool sign;
    int_fast32_t exp;
    uint_fast64_t sig64, sig0;
    int_fast32_t shiftCount;
    struct uint128 sig128;
    struct uint64_extra sigExtra;

    uA.f = a;
    uiA64 = uA.ui.v64;
    uiA0  = uA.ui.v0;
    sign  = signF128UI64( uiA64 );
    exp   = expF128UI64( uiA64 );
    sig64 = fracF128UI64( uiA64 );
    sig0  = uiA0;
    shiftCount = 0x402F - exp;
    if ( shiftCount <= 0 ) {
        if ( shiftCount < -15 ) {
            softfloat_raiseFlags( softfloat_flag_invalid );
            return
                ! sign || ((exp == 0x7FFF) && (sig64 | sig0))
                    ? INT64_C( 0x7FFFFFFFFFFFFFFF )
                    : -INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1;
        }
        sig64 |= UINT64_C( 0x0001000000000000 );
        if ( shiftCount ) {
            sig128 = softfloat_shortShiftLeft128( sig64, sig0, -shiftCount );
            sig64 = sig128.v64;
            sig0  = sig128.v0;
        }
    } else {
        if ( exp ) sig64 |= UINT64_C( 0x0001000000000000 );
        sigExtra = softfloat_shiftRightJam64Extra( sig64, sig0, shiftCount );
        sig64 = sigExtra.v;
        sig0  = sigExtra.extra;
    }
    return softfloat_roundPackToI64( sign, sig64, sig0, roundingMode, exact );

}
Exemple #13
0
uint_fast32_t
 f128_to_ui32( float128_t a, uint_fast8_t roundingMode, bool exact )
{
    union ui128_f128 uA;
    uint_fast64_t uiA64, uiA0;
    bool sign;
    int_fast32_t exp;
    uint_fast64_t sig64;
    int_fast32_t shiftDist;

    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    uA.f = a;
    uiA64 = uA.ui.v64;
    uiA0  = uA.ui.v0;
    sign  = signF128UI64( uiA64 );
    exp   = expF128UI64( uiA64 );
    sig64 = fracF128UI64( uiA64 ) | (uiA0 != 0);
    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
#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 = 0x4023 - exp;
    if ( 0 < shiftDist ) {
        sig64 = softfloat_shiftRightJam64( sig64, shiftDist );
    }
    return softfloat_roundToUI32( sign, sig64, roundingMode, exact );

}
Exemple #14
0
float128_t
f128_roundToInt( float128_t a, uint_fast8_t roundingMode, bool exact )
{
    union ui128_f128 uA;
    uint_fast64_t uiA64, uiA0;
    int_fast32_t exp;
    struct uint128 uiZ;
    uint_fast64_t lastBitMask, roundBitsMask;
    bool roundNearEven;
    union ui128_f128 uZ;

    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    uA.f = a;
    uiA64 = uA.ui.v64;
    uiA0  = uA.ui.v0;
    exp = expF128UI64( uiA64 );
    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    if ( 0x402F <= exp ) {
        /*--------------------------------------------------------------------
        *--------------------------------------------------------------------*/
        if ( 0x406F <= exp ) {
            if ( (exp == 0x7FFF) && (fracF128UI64( uiA64 ) | uiA0) ) {
                uiZ = softfloat_propagateNaNF128UI( uiA64, uiA0, 0, 0 );
                goto uiZ;
            }
            return a;
        }
        /*--------------------------------------------------------------------
        *--------------------------------------------------------------------*/
        lastBitMask = (uint_fast64_t) 2<<(0x406E - exp);
        roundBitsMask = lastBitMask - 1;
        uiZ.v64 = uiA64;
        uiZ.v0  = uiA0;
        roundNearEven = (roundingMode == softfloat_round_near_even);
        if ( roundNearEven || (roundingMode == softfloat_round_near_maxMag) ) {
            if ( exp == 0x402F ) {
                if ( UINT64_C( 0x8000000000000000 ) <= uiZ.v0 ) {
                    ++uiZ.v64;
                    if (
                        roundNearEven
                        && (uiZ.v0 == UINT64_C( 0x8000000000000000 ))
                    ) {
                        uiZ.v64 &= ~1;
                    }
                }
            } else {
                uiZ = softfloat_add128( uiZ.v64, uiZ.v0, 0, lastBitMask>>1 );
                if ( roundNearEven && ! (uiZ.v0 & roundBitsMask) ) {
                    uiZ.v0 &= ~lastBitMask;
                }
            }
        } else if ( roundingMode != softfloat_round_minMag ) {
            if (
                signF128UI64( uiZ.v64 ) ^ (roundingMode == softfloat_round_max)
            ) {
                uiZ = softfloat_add128( uiZ.v64, uiZ.v0, 0, roundBitsMask );
            }
        }
        uiZ.v0 &= ~roundBitsMask;
    } else {
Exemple #15
0
float128_t f128_mul( float128_t a, float128_t b )
{
    union ui128_f128 uA;
    uint_fast64_t uiA64, uiA0;
    bool signA;
    int_fast32_t expA;
    struct uint128 sigA;
    union ui128_f128 uB;
    uint_fast64_t uiB64, uiB0;
    bool signB;
    int_fast32_t expB;
    struct uint128 sigB;
    bool signZ;
    uint_fast64_t magBits;
    struct exp32_sig128 normExpSig;
    int_fast32_t expZ;
    uint64_t sig256Z[4];
    uint_fast64_t sigZExtra;
    struct uint128 sigZ;
    struct uint128_extra sig128Extra;
    struct uint128 uiZ;
    union ui128_f128 uZ;

    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    uA.f = a;
    uiA64 = uA.ui.v64;
    uiA0  = uA.ui.v0;
    signA = signF128UI64( uiA64 );
    expA  = expF128UI64( uiA64 );
    sigA.v64 = fracF128UI64( uiA64 );
    sigA.v0  = uiA0;
    uB.f = b;
    uiB64 = uB.ui.v64;
    uiB0  = uB.ui.v0;
    signB = signF128UI64( uiB64 );
    expB  = expF128UI64( uiB64 );
    sigB.v64 = fracF128UI64( uiB64 );
    sigB.v0  = uiB0;
    signZ = signA ^ signB;
    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    if ( expA == 0x7FFF ) {
        if (
            (sigA.v64 | sigA.v0) || ((expB == 0x7FFF) && (sigB.v64 | sigB.v0))
        ) {
            goto propagateNaN;
        }
        magBits = expB | sigB.v64 | sigB.v0;
        goto infArg;
    }
    if ( expB == 0x7FFF ) {
        if ( sigB.v64 | sigB.v0 ) goto propagateNaN;
        magBits = expA | sigA.v64 | sigA.v0;
        goto infArg;
    }
    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    if ( ! expA ) {
        if ( ! (sigA.v64 | sigA.v0) ) goto zero;
        normExpSig = softfloat_normSubnormalF128Sig( sigA.v64, sigA.v0 );
        expA = normExpSig.exp;
        sigA = normExpSig.sig;
    }
    if ( ! expB ) {
        if ( ! (sigB.v64 | sigB.v0) ) goto zero;
        normExpSig = softfloat_normSubnormalF128Sig( sigB.v64, sigB.v0 );
        expB = normExpSig.exp;
        sigB = normExpSig.sig;
    }
    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    expZ = expA + expB - 0x4000;
    sigA.v64 |= UINT64_C( 0x0001000000000000 );
    sigB = softfloat_shortShiftLeft128( sigB.v64, sigB.v0, 16 );
    softfloat_mul128To256M( sigA.v64, sigA.v0, sigB.v64, sigB.v0, sig256Z );
    sigZExtra = sig256Z[indexWord( 4, 1 )] | (sig256Z[indexWord( 4, 0 )] != 0);
    sigZ =
        softfloat_add128(
            sig256Z[indexWord( 4, 3 )], sig256Z[indexWord( 4, 2 )],
            sigA.v64, sigA.v0
        );
    if ( UINT64_C( 0x0002000000000000 ) <= sigZ.v64 ) {
        ++expZ;
        sig128Extra =
            softfloat_shortShiftRightJam128Extra(
                sigZ.v64, sigZ.v0, sigZExtra, 1 );
        sigZ = sig128Extra.v;
        sigZExtra = sig128Extra.extra;
    }
    return
        softfloat_roundPackToF128( signZ, expZ, sigZ.v64, sigZ.v0, sigZExtra );
    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
 propagateNaN:
    uiZ = softfloat_propagateNaNF128UI( uiA64, uiA0, uiB64, uiB0 );
    goto uiZ;
    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
 infArg:
    if ( ! magBits ) {
        softfloat_raiseFlags( softfloat_flag_invalid );
        uiZ.v64 = defaultNaNF128UI64;
        uiZ.v0  = defaultNaNF128UI0;
        goto uiZ;
    }
    uiZ.v64 = packToF128UI64( signZ, 0x7FFF, 0 );
    goto uiZ0;
    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
 zero:
    uiZ.v64 = packToF128UI64( signZ, 0, 0 );
 uiZ0:
    uiZ.v0 = 0;
 uiZ:
    uZ.ui = uiZ;
    return uZ.f;

}