float128_t extF80_to_f128( extFloat80_t a ) { union { struct extFloat80M s; extFloat80_t f; } uA; uint_fast16_t uiA64; uint_fast64_t uiA0; uint_fast16_t exp; uint_fast64_t frac; struct commonNaN commonNaN; struct uint128 uiZ; bool sign; struct uint128 frac128; union ui128_f128 uZ; uA.f = a; uiA64 = uA.s.signExp; uiA0 = uA.s.signif; exp = expExtF80UI64( uiA64 ); frac = uiA0 & UINT64_C( 0x7FFFFFFFFFFFFFFF ); if ( (exp == 0x7FFF) && frac ) { softfloat_extF80UIToCommonNaN( uiA64, uiA0, &commonNaN ); uiZ = softfloat_commonNaNToF128UI( &commonNaN ); } else { sign = signExtF80UI64( uiA64 ); frac128 = softfloat_shortShiftLeft128( 0, frac, 49 ); uiZ.v64 = packToF128UI64( sign, exp, frac128.v64 ); uiZ.v0 = frac128.v0; } uZ.ui = uiZ; return uZ.f; }
uint_fast32_t extF80_to_ui32_r_minMag( extFloat80_t a, bool exact ) { union { struct extFloat80M s; extFloat80_t f; } uA; uint_fast16_t uiA64; int_fast32_t exp; uint_fast64_t sig; int_fast32_t shiftCount; uint_fast32_t z; uA.f = a; uiA64 = uA.s.signExp; exp = expExtF80UI64( uiA64 ); sig = uA.s.signif; shiftCount = 0x403E - exp; if ( 64 <= shiftCount ) { if ( exact && (exp | sig) ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } return 0; } if ( signExtF80UI64( uiA64 ) || (shiftCount < 32) ) { softfloat_raiseFlags( softfloat_flag_invalid ); return 0xFFFFFFFF; } z = sig>>shiftCount; if ( exact && ((uint_fast64_t) z<<shiftCount != sig) ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } return z; }
uint_fast64_t extF80M_to_ui64( const extFloat80_t *aPtr, uint_fast8_t roundingMode, bool exact ) { const struct extFloat80M *aSPtr; uint_fast16_t uiA64; int32_t exp, shiftCount; bool sign; uint64_t sig; uint32_t extSig[3]; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ aSPtr = (const struct extFloat80M *) aPtr; uiA64 = aSPtr->signExp; exp = expExtF80UI64( uiA64 ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ shiftCount = 0x403E - exp; if ( shiftCount < 0 ) { softfloat_raiseFlags( softfloat_flag_invalid ); return UINT64_C( 0xFFFFFFFFFFFFFFFF ); } sign = signExtF80UI64( uiA64 ); sig = aSPtr->signif; extSig[indexWord( 3, 2 )] = sig>>32; extSig[indexWord( 3, 1 )] = sig; extSig[indexWord( 3, 0 )] = 0; if ( shiftCount ) softfloat_shiftRightJam96M( extSig, shiftCount, extSig ); return softfloat_roundPackMToUI64( sign, extSig, roundingMode, exact ); }
uint_fast64_t extF80_to_ui64( extFloat80_t a, uint_fast8_t roundingMode, bool exact ) { union { struct extFloat80M s; extFloat80_t f; } uA; uint_fast16_t uiA64; int_fast32_t exp, shiftCount; bool sign; uint_fast64_t sig, sigExtra; struct uint64_extra sig64Extra; uA.f = a; uiA64 = uA.s.signExp; exp = expExtF80UI64( uiA64 ); shiftCount = 0x403E - exp; if ( shiftCount < 0 ) { softfloat_raiseFlags( softfloat_flag_invalid ); return UINT64_C( 0xFFFFFFFFFFFFFFFF ); } sign = signExtF80UI64( uiA64 ); sig = uA.s.signif; sigExtra = 0; if ( shiftCount ) { sig64Extra = softfloat_shiftRightJam64Extra( sig, 0, shiftCount ); sig = sig64Extra.v; sigExtra = sig64Extra.extra; } return softfloat_roundPackToUI64( sign, sig, sigExtra, roundingMode, exact ); }
void extF80M_to_f128M( const extFloat80_t *aPtr, float128_t *zPtr ) { const struct extFloat80M *aSPtr; uint32_t *zWPtr; uint_fast16_t uiA64; bool sign; int32_t exp; uint64_t sig; struct commonNaN commonNaN; uint32_t uiZ96; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ aSPtr = (const struct extFloat80M *) aPtr; zWPtr = (uint32_t *) zPtr; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiA64 = aSPtr->signExp; sign = signExtF80UI64( uiA64 ); exp = expExtF80UI64( uiA64 ); sig = aSPtr->signif; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ zWPtr[indexWord( 4, 0 )] = 0; if ( exp == 0x7FFF ) { if ( sig & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) { softfloat_extF80MToCommonNaN( aSPtr, &commonNaN ); softfloat_commonNaNToF128M( &commonNaN, zWPtr ); return; } uiZ96 = packToF128UI96( sign, 0x7FFF, 0 ); goto uiZ; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( exp ) --exp; if ( ! (sig & UINT64_C( 0x8000000000000000 )) ) { if ( ! sig ) { uiZ96 = packToF128UI96( sign, 0, 0 ); goto uiZ; } exp += softfloat_normExtF80SigM( &sig ); } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ zWPtr[indexWord( 4, 1 )] = (uint32_t) sig<<17; sig >>= 15; zWPtr[indexWord( 4, 2 )] = sig; if ( exp < 0 ) { zWPtr[indexWordHi( 4 )] = sig>>32; softfloat_shiftRight96M( &zWPtr[indexMultiwordHi( 4, 3 )], -exp, &zWPtr[indexMultiwordHi( 4, 3 )] ); exp = 0; sig = (uint64_t) zWPtr[indexWordHi( 4 )]<<32; }
float32_t extF80M_to_f32( const extFloat80_t *aPtr ) { const struct extFloat80M *aSPtr; uint_fast16_t uiA64; bool sign; int32_t exp; uint64_t sig; struct commonNaN commonNaN; uint32_t uiZ, sig32; union ui32_f32 uZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ aSPtr = (const struct extFloat80M *) aPtr; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiA64 = aSPtr->signExp; sign = signExtF80UI64( uiA64 ); exp = expExtF80UI64( uiA64 ); sig = aSPtr->signif; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( exp == 0x7FFF ) { if ( sig & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) { softfloat_extF80MToCommonNaN( aSPtr, &commonNaN ); uiZ = softfloat_commonNaNToF32UI( &commonNaN ); } else { uiZ = packToF32UI( sign, 0xFF, 0 ); } goto uiZ; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ! (sig & UINT64_C( 0x8000000000000000 )) ) { if ( ! sig ) { uiZ = packToF32UI( sign, 0, 0 ); goto uiZ; } exp += softfloat_normExtF80SigM( &sig ); } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ sig32 = softfloat_shortShiftRightJam64( sig, 33 ); exp -= 0x3F81; if ( sizeof (int_fast16_t) < sizeof (int32_t) ) { if ( exp < -0x1000 ) exp = -0x1000; } return softfloat_roundPackToF32( sign, exp, sig32 ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiZ: uZ.ui = uiZ; return uZ.f; }
int_fast32_t extF80_to_i32_r_minMag( extFloat80_t a, bool exact ) { union { struct extFloat80M s; extFloat80_t f; } uA; uint_fast16_t uiA64; int_fast32_t exp; uint_fast64_t sig; int_fast32_t shiftDist; bool sign; int_fast32_t absZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uA.f = a; uiA64 = uA.s.signExp; exp = expExtF80UI64( uiA64 ); sig = uA.s.signif; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ shiftDist = 0x403E - exp; if ( 64 <= shiftDist ) { if ( exact && (exp | sig) ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } return 0; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ sign = signExtF80UI64( uiA64 ); if ( shiftDist < 33 ) { if ( (uiA64 == packToExtF80UI64( 1, 0x401E )) && (sig < UINT64_C( 0x8000000100000000 )) ) { if ( exact && (sig & UINT64_C( 0x00000000FFFFFFFF )) ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } return -0x7FFFFFFF - 1; } softfloat_raiseFlags( softfloat_flag_invalid ); return (exp == 0x7FFF) && (sig & UINT64_C( 0x7FFFFFFFFFFFFFFF )) ? i32_fromNaN : sign ? i32_fromNegOverflow : i32_fromPosOverflow; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ absZ = sig>>shiftDist; if ( exact && ((uint_fast64_t) (uint_fast32_t) absZ<<shiftDist != sig) ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } return sign ? -absZ : absZ; }
float64_t extF80_to_f64( extFloat80_t a ) { union { struct extFloat80M s; extFloat80_t f; } uA; uint_fast16_t uiA64; uint_fast64_t uiA0; bool sign; int_fast32_t exp; uint_fast64_t sig; struct commonNaN commonNaN; uint_fast64_t uiZ; union ui64_f64 uZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uA.f = a; uiA64 = uA.s.signExp; uiA0 = uA.s.signif; sign = signExtF80UI64( uiA64 ); exp = expExtF80UI64( uiA64 ); sig = uiA0; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ! (exp | sig) ) { uiZ = packToF64UI( sign, 0, 0 ); goto uiZ; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( exp == 0x7FFF ) { if ( sig & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) { softfloat_extF80UIToCommonNaN( uiA64, uiA0, &commonNaN ); uiZ = softfloat_commonNaNToF64UI( &commonNaN ); } else { uiZ = packToF64UI( sign, 0x7FF, 0 ); } goto uiZ; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ sig = softfloat_shortShiftRightJam64( sig, 1 ); exp -= 0x3C01; if ( sizeof (int_fast16_t) < sizeof (int_fast32_t) ) { if ( exp < -0x1000 ) exp = -0x1000; } return softfloat_roundPackToF64( sign, exp, sig ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiZ: uZ.ui = uiZ; return uZ.f; }
int_fast32_t extF80_to_i32_r_minMag( extFloat80_t a, bool exact ) { union { struct extFloat80M s; extFloat80_t f; } uA; uint_fast16_t uiA64; int_fast32_t exp; uint_fast64_t sig; int_fast32_t shiftCount; bool sign; int_fast32_t absZ; uA.f = a; uiA64 = uA.s.signExp; exp = expExtF80UI64( uiA64 ); sig = uA.s.signif; shiftCount = 0x403E - exp; if ( 64 <= shiftCount ) { if ( exact && (exp | sig) ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } return 0; } sign = signExtF80UI64( uiA64 ); if ( shiftCount < 33 ) { if ( (uiA64 == packToExtF80UI64( 1, 0x401E )) && (sig < UINT64_C( 0x8000000100000000 )) ) { if ( exact && (sig & UINT64_C( 0x00000000FFFFFFFF )) ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } } else { softfloat_raiseFlags( softfloat_flag_invalid ); if ( ! sign || ((exp == 0x7FFF) && (sig & UINT64_C( 0x7FFFFFFFFFFFFFFF ))) ) { return 0x7FFFFFFF; } } return -0x7FFFFFFF - 1; } absZ = sig>>shiftCount; if ( exact && ((uint_fast64_t) (uint_fast32_t) absZ<<shiftCount != sig) ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } return sign ? -absZ : absZ; }
int_fast64_t extF80_to_i64( extFloat80_t a, uint_fast8_t roundingMode, bool exact ) { union { struct extFloat80M s; extFloat80_t f; } uA; uint_fast16_t uiA64; bool sign; int_fast32_t exp; uint_fast64_t sig; int_fast32_t shiftDist; uint_fast64_t sigExtra; struct uint64_extra sig64Extra; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uA.f = a; uiA64 = uA.s.signExp; sign = signExtF80UI64( uiA64 ); exp = expExtF80UI64( uiA64 ); sig = uA.s.signif; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ shiftDist = 0x403E - exp; if ( shiftDist <= 0 ) { /*-------------------------------------------------------------------- *--------------------------------------------------------------------*/ if ( shiftDist ) { softfloat_raiseFlags( softfloat_flag_invalid ); return (exp == 0x7FFF) && (sig & UINT64_C( 0x7FFFFFFFFFFFFFFF )) ? i64_fromNaN : sign ? i64_fromNegOverflow : i64_fromPosOverflow; } /*-------------------------------------------------------------------- *--------------------------------------------------------------------*/ sigExtra = 0; } else { /*-------------------------------------------------------------------- *--------------------------------------------------------------------*/ sig64Extra = softfloat_shiftRightJam64Extra( sig, 0, shiftDist ); sig = sig64Extra.v; sigExtra = sig64Extra.extra; } return softfloat_roundPackToI64( sign, sig, sigExtra, roundingMode, exact ); }
uint_fast64_t extF80_to_ui64_r_minMag( extFloat80_t a, bool exact ) { union { struct extFloat80M s; extFloat80_t f; } uA; uint_fast16_t uiA64; int_fast32_t exp; uint_fast64_t sig; int_fast32_t shiftDist; bool sign; uint_fast64_t z; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uA.f = a; uiA64 = uA.s.signExp; exp = expExtF80UI64( uiA64 ); sig = uA.s.signif; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ shiftDist = 0x403E - exp; if ( 64 <= shiftDist ) { if ( exact && (exp | sig) ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } return 0; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ sign = signExtF80UI64( uiA64 ); if ( sign || (shiftDist < 0) ) { softfloat_raiseFlags( softfloat_flag_invalid ); return (exp == 0x7FFF) && (sig & UINT64_C( 0x7FFFFFFFFFFFFFFF )) ? ui64_fromNaN : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ z = sig>>shiftDist; if ( exact && (z<<shiftDist != sig) ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } return z; }
uint_fast32_t extF80_to_ui32( extFloat80_t a, uint_fast8_t roundingMode, bool exact ) { union { struct extFloat80M s; extFloat80_t f; } uA; uint_fast16_t uiA64; bool sign; int_fast32_t exp; uint_fast64_t sig; int_fast32_t shiftCount; uA.f = a; uiA64 = uA.s.signExp; sign = signExtF80UI64( uiA64 ); exp = expExtF80UI64( uiA64 ); sig = uA.s.signif; shiftCount = 0x4037 - exp; if ( shiftCount <= 0 ) shiftCount = 1; sig = softfloat_shiftRightJam64( sig, shiftCount ); return softfloat_roundPackToUI32( sign, sig, roundingMode, exact ); }
int_fast64_t extF80_to_i64( extFloat80_t a, uint_fast8_t roundingMode, bool exact ) { union { struct extFloat80M s; extFloat80_t f; } uA; uint_fast16_t uiA64; bool sign; int_fast32_t exp; uint_fast64_t sig; int_fast32_t shiftCount; uint_fast64_t sigExtra; struct uint64_extra sig64Extra; uA.f = a; uiA64 = uA.s.signExp; sign = signExtF80UI64( uiA64 ); exp = expExtF80UI64( uiA64 ); sig = uA.s.signif; shiftCount = 0x403E - exp; if ( shiftCount <= 0 ) { if ( shiftCount ) { softfloat_raiseFlags( softfloat_flag_invalid ); return ! sign || ((exp == 0x7FFF) && (sig & UINT64_C( 0x7FFFFFFFFFFFFFFF ))) ? INT64_C( 0x7FFFFFFFFFFFFFFF ) : -INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1; } sigExtra = 0; } else { sig64Extra = softfloat_shiftRightJam64Extra( sig, 0, shiftCount ); sig = sig64Extra.v; sigExtra = sig64Extra.extra; } return softfloat_roundPackToI64( sign, sig, sigExtra, roundingMode, exact ); }
uint_fast32_t extF80_to_ui32( extFloat80_t a, uint_fast8_t roundingMode, bool exact ) { union { struct extFloat80M s; extFloat80_t f; } uA; uint_fast16_t uiA64; bool sign; int_fast32_t exp; uint_fast64_t sig; int_fast32_t shiftDist; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uA.f = a; uiA64 = uA.s.signExp; sign = signExtF80UI64( uiA64 ); exp = expExtF80UI64( uiA64 ); sig = uA.s.signif; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ #if (ui32_fromNaN != ui32_fromPosOverflow) || (ui32_fromNaN != ui32_fromNegOverflow) if ( (exp == 0x7FFF) && (sig & UINT64_C( 0x7FFFFFFFFFFFFFFF )) ) { #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 /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ shiftDist = 0x4032 - exp; if ( shiftDist <= 0 ) shiftDist = 1; sig = softfloat_shiftRightJam64( sig, shiftDist ); return softfloat_roundPackToUI32( sign, sig, roundingMode, exact ); }
uint_fast64_t extF80M_to_ui64( const extFloat80_t *aPtr, uint_fast8_t roundingMode, bool exact ) { const struct extFloat80M *aSPtr; uint_fast16_t uiA64; bool sign; int32_t exp; uint64_t sig; int32_t shiftDist; uint32_t extSig[3]; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ aSPtr = (const struct extFloat80M *) aPtr; uiA64 = aSPtr->signExp; sign = signExtF80UI64( uiA64 ); exp = expExtF80UI64( uiA64 ); sig = aSPtr->signif; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ shiftDist = 0x403E - exp; if ( shiftDist < 0 ) { softfloat_raiseFlags( softfloat_flag_invalid ); return (exp == 0x7FFF) && (sig & UINT64_C( 0x7FFFFFFFFFFFFFFF )) ? ui64_fromNaN : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ extSig[indexWord( 3, 2 )] = sig>>32; extSig[indexWord( 3, 1 )] = sig; extSig[indexWord( 3, 0 )] = 0; if ( shiftDist ) softfloat_shiftRightJam96M( extSig, shiftDist, extSig ); return softfloat_roundMToUI64( sign, extSig, roundingMode, exact ); }
int softfloat_compareNonnormExtF80M( const struct extFloat80M *aSPtr, const struct extFloat80M *bSPtr ) { uint_fast16_t uiA64, uiB64; uint64_t sigA; bool signB; uint64_t sigB; int32_t expA, expB; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiA64 = aSPtr->signExp; uiB64 = bSPtr->signExp; sigA = aSPtr->signif; signB = signExtF80UI64( uiB64 ); sigB = bSPtr->signif; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( (uiA64 ^ uiB64) & 0x8000 ) { if ( ! (sigA | sigB) ) return 0; goto resultFromSignB; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expA = expExtF80UI64( uiA64 ); expB = expExtF80UI64( uiB64 ); if ( expA == 0x7FFF ) { if (expB == 0x7FFF) return 0; signB = ! signB; goto resultFromSignB; } if ( expB == 0x7FFF ) { goto resultFromSignB; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ! expA ) expA = 1; if ( ! (sigA & UINT64_C( 0x8000000000000000 )) ) { if ( sigA ) { expA += softfloat_normExtF80SigM( &sigA ); } else { expA = -128; } } if ( ! expB ) expB = 1; if ( ! (sigB & UINT64_C( 0x8000000000000000 )) ) { if ( sigB ) { expB += softfloat_normExtF80SigM( &sigB ); } else { expB = -128; } } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( signB ) { if ( expA < expB ) return 1; if ( (expB < expA) || (sigB < sigA) ) return -1; } else { if ( expB < expA ) return 1; if ( (expA < expB) || (sigA < sigB) ) return -1; } return (sigA != sigB); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ resultFromSignB: return signB ? 1 : -1; }
extFloat80_t extF80_mul( extFloat80_t a, extFloat80_t b ) { union { struct extFloat80M s; extFloat80_t f; } uA; uint_fast16_t uiA64; uint_fast64_t uiA0; bool signA; int_fast32_t expA; uint_fast64_t sigA; union { struct extFloat80M s; extFloat80_t f; } uB; uint_fast16_t uiB64; uint_fast64_t uiB0; bool signB; int_fast32_t expB; uint_fast64_t sigB; bool signZ; uint_fast64_t magBits; struct exp32_sig64 normExpSig; int_fast32_t expZ; struct uint128 sig128Z, uiZ; uint_fast16_t uiZ64; uint_fast64_t uiZ0; union { struct extFloat80M s; extFloat80_t f; } uZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uA.f = a; uiA64 = uA.s.signExp; uiA0 = uA.s.signif; signA = signExtF80UI64( uiA64 ); expA = expExtF80UI64( uiA64 ); sigA = uiA0; uB.f = b; uiB64 = uB.s.signExp; uiB0 = uB.s.signif; signB = signExtF80UI64( uiB64 ); expB = expExtF80UI64( uiB64 ); sigB = uiB0; signZ = signA ^ signB; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( expA == 0x7FFF ) { if ( (sigA & UINT64_C( 0x7FFFFFFFFFFFFFFF )) || ((expB == 0x7FFF) && (sigB & UINT64_C( 0x7FFFFFFFFFFFFFFF ))) ) { goto propagateNaN; } magBits = expB | sigB; goto infArg; } if ( expB == 0x7FFF ) { if ( sigB & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) goto propagateNaN; magBits = expA | sigA; goto infArg; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ! expA ) expA = 1; if ( ! (sigA & UINT64_C( 0x8000000000000000 )) ) { if ( ! sigA ) goto zero; normExpSig = softfloat_normSubnormalExtF80Sig( sigA ); expA += normExpSig.exp; sigA = normExpSig.sig; } if ( ! expB ) expB = 1; if ( ! (sigB & UINT64_C( 0x8000000000000000 )) ) { if ( ! sigB ) goto zero; normExpSig = softfloat_normSubnormalExtF80Sig( sigB ); expB += normExpSig.exp; sigB = normExpSig.sig; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expZ = expA + expB - 0x3FFE; sig128Z = softfloat_mul64To128( sigA, sigB ); if ( sig128Z.v64 < UINT64_C( 0x8000000000000000 ) ) { --expZ; sig128Z = softfloat_add128( sig128Z.v64, sig128Z.v0, sig128Z.v64, sig128Z.v0 ); } return softfloat_roundPackToExtF80( signZ, expZ, sig128Z.v64, sig128Z.v0, extF80_roundingPrecision ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ propagateNaN: uiZ = softfloat_propagateNaNExtF80UI( uiA64, uiA0, uiB64, uiB0 ); uiZ64 = uiZ.v64; uiZ0 = uiZ.v0; goto uiZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ infArg: if ( ! magBits ) { softfloat_raiseFlags( softfloat_flag_invalid ); uiZ64 = defaultNaNExtF80UI64; uiZ0 = defaultNaNExtF80UI0; } else { uiZ64 = packToExtF80UI64( signZ, 0x7FFF ); uiZ0 = UINT64_C( 0x8000000000000000 ); } goto uiZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ zero: uiZ64 = packToExtF80UI64( signZ, 0 ); uiZ0 = 0; uiZ: uZ.s.signExp = uiZ64; uZ.s.signif = uiZ0; return uZ.f; }
extFloat80_t softfloat_addMagsExtF80( uint_fast16_t uiA64, uint_fast64_t uiA0, uint_fast16_t uiB64, uint_fast64_t uiB0, bool signZ ) { int_fast32_t expA; uint_fast64_t sigA; int_fast32_t expB; uint_fast64_t sigB; int_fast32_t expDiff; uint_fast16_t uiZ64; uint_fast64_t uiZ0, sigZ, sigZExtra; struct exp32_sig64 normExpSig; int_fast32_t expZ; struct uint64_extra sig64Extra; struct uint128 uiZ; union { struct extFloat80M s; extFloat80_t f; } uZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expA = expExtF80UI64( uiA64 ); sigA = uiA0; expB = expExtF80UI64( uiB64 ); sigB = uiB0; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expDiff = expA - expB; if ( ! expDiff ) { if ( expA == 0x7FFF ) { if ( (sigA | sigB) & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) { goto propagateNaN; } uiZ64 = uiA64; uiZ0 = uiA0; goto uiZ; } sigZ = sigA + sigB; sigZExtra = 0; if ( ! expA ) { normExpSig = softfloat_normSubnormalExtF80Sig( sigZ ); expZ = normExpSig.exp + 1; sigZ = normExpSig.sig; goto roundAndPack; } expZ = expA; goto shiftRight1; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( expDiff < 0 ) { if ( expB == 0x7FFF ) { if ( sigB & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) goto propagateNaN; uiZ64 = packToExtF80UI64( signZ, 0x7FFF ); uiZ0 = uiB0; goto uiZ; } expZ = expB; if ( ! expA ) { ++expDiff; sigZExtra = 0; if ( ! expDiff ) goto newlyAligned; } sig64Extra = softfloat_shiftRightJam64Extra( sigA, 0, -expDiff ); sigA = sig64Extra.v; sigZExtra = sig64Extra.extra; } else { if ( expA == 0x7FFF ) { if ( sigA & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) goto propagateNaN; uiZ64 = uiA64; uiZ0 = uiA0; goto uiZ; } expZ = expA; if ( ! expB ) { --expDiff; sigZExtra = 0; if ( ! expDiff ) goto newlyAligned; } sig64Extra = softfloat_shiftRightJam64Extra( sigB, 0, expDiff ); sigB = sig64Extra.v; sigZExtra = sig64Extra.extra; } newlyAligned: sigZ = sigA + sigB; if ( sigZ & UINT64_C( 0x8000000000000000 ) ) goto roundAndPack; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ shiftRight1: sig64Extra = softfloat_shortShiftRightJam64Extra( sigZ, sigZExtra, 1 ); sigZ = sig64Extra.v | UINT64_C( 0x8000000000000000 ); sigZExtra = sig64Extra.extra; ++expZ; roundAndPack: return softfloat_roundPackToExtF80( signZ, expZ, sigZ, sigZExtra, extF80_roundingPrecision ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ propagateNaN: uiZ = softfloat_propagateNaNExtF80UI( uiA64, uiA0, uiB64, uiB0 ); uiZ64 = uiZ.v64; uiZ0 = uiZ.v0; uiZ: uZ.s.signExp = uiZ64; uZ.s.signif = uiZ0; return uZ.f; }
extFloat80_t extF80_roundToInt( extFloat80_t a, uint_fast8_t roundingMode, bool exact ) { union { struct extFloat80M s; extFloat80_t f; } uA; uint_fast16_t uiA64, signUI64; int_fast32_t exp; uint_fast64_t sigA; uint_fast16_t uiZ64; uint_fast64_t sigZ; struct exp32_sig64 normExpSig; struct uint128 uiZ; uint_fast64_t lastBitMask, roundBitsMask; union { struct extFloat80M s; extFloat80_t f; } uZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uA.f = a; uiA64 = uA.s.signExp; signUI64 = uiA64 & packToExtF80UI64( 1, 0 ); exp = expExtF80UI64( uiA64 ); sigA = uA.s.signif; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ! (sigA & UINT64_C( 0x8000000000000000 )) && (exp != 0x7FFF) ) { if ( ! sigA ) { uiZ64 = signUI64; sigZ = 0; goto uiZ; } normExpSig = softfloat_normSubnormalExtF80Sig( sigA ); exp += normExpSig.exp; sigA = normExpSig.sig; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( 0x403E <= exp ) { if ( exp == 0x7FFF ) { if ( sigA & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) { uiZ = softfloat_propagateNaNExtF80UI( uiA64, sigA, 0, 0 ); uiZ64 = uiZ.v64; sigZ = uiZ.v0; goto uiZ; } sigZ = UINT64_C( 0x8000000000000000 ); } else { sigZ = sigA; } uiZ64 = signUI64 | exp; goto uiZ; } if ( exp <= 0x3FFE ) { if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact; switch ( roundingMode ) { case softfloat_round_near_even: if ( ! (sigA & UINT64_C( 0x7FFFFFFFFFFFFFFF )) ) break; case softfloat_round_near_maxMag: if ( exp == 0x3FFE ) goto mag1; break; case softfloat_round_min: if ( signUI64 ) goto mag1; break; case softfloat_round_max: if ( ! signUI64 ) goto mag1; break; } uiZ64 = signUI64; sigZ = 0; goto uiZ; mag1: uiZ64 = signUI64 | 0x3FFF; sigZ = UINT64_C( 0x8000000000000000 ); goto uiZ; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiZ64 = signUI64 | exp; lastBitMask = (uint_fast64_t) 1<<(0x403E - exp); roundBitsMask = lastBitMask - 1; sigZ = sigA; if ( roundingMode == softfloat_round_near_maxMag ) { sigZ += lastBitMask>>1; } else if ( roundingMode == softfloat_round_near_even ) {
extFloat80_t softfloat_subMagsExtF80( uint_fast16_t uiA64, uint_fast64_t uiA0, uint_fast16_t uiB64, uint_fast64_t uiB0, bool signZ ) { int_fast32_t expA; uint_fast64_t sigA; int_fast32_t expB; uint_fast64_t sigB; int_fast32_t expDiff; uint_fast16_t uiZ64; uint_fast64_t uiZ0; int_fast32_t expZ; uint_fast64_t sigExtra; struct uint128 sig128, uiZ; union { struct extFloat80M s; extFloat80_t f; } uZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expA = expExtF80UI64( uiA64 ); sigA = uiA0; expB = expExtF80UI64( uiB64 ); sigB = uiB0; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expDiff = expA - expB; if ( 0 < expDiff ) goto expABigger; if ( expDiff < 0 ) goto expBBigger; if ( expA == 0x7FFF ) { if ( (sigA | sigB) & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) { goto propagateNaN; } softfloat_raiseFlags( softfloat_flag_invalid ); uiZ64 = defaultNaNExtF80UI64; uiZ0 = defaultNaNExtF80UI0; goto uiZ; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expZ = expA; if ( ! expZ ) expZ = 1; sigExtra = 0; if ( sigB < sigA ) goto aBigger; if ( sigA < sigB ) goto bBigger; uiZ64 = packToExtF80UI64( (softfloat_roundingMode == softfloat_round_min), 0 ); uiZ0 = 0; goto uiZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expBBigger: if ( expB == 0x7FFF ) { if ( sigB & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) goto propagateNaN; uiZ64 = packToExtF80UI64( signZ ^ 1, 0x7FFF ); uiZ0 = UINT64_C( 0x8000000000000000 ); goto uiZ; } if ( ! expA ) { ++expDiff; sigExtra = 0; if ( ! expDiff ) goto newlyAlignedBBigger; } sig128 = softfloat_shiftRightJam128( sigA, 0, -expDiff ); sigA = sig128.v64; sigExtra = sig128.v0; newlyAlignedBBigger: expZ = expB; bBigger: signZ ^= 1; sig128 = softfloat_sub128( sigB, 0, sigA, sigExtra ); goto normRoundPack; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expABigger: if ( expA == 0x7FFF ) { if ( sigA & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) goto propagateNaN; uiZ64 = uiA64; uiZ0 = uiA0; goto uiZ; } if ( ! expB ) { --expDiff; sigExtra = 0; if ( ! expDiff ) goto newlyAlignedABigger; } sig128 = softfloat_shiftRightJam128( sigB, 0, expDiff ); sigB = sig128.v64; sigExtra = sig128.v0; newlyAlignedABigger: expZ = expA; aBigger: sig128 = softfloat_sub128( sigA, 0, sigB, sigExtra ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ normRoundPack: return softfloat_normRoundPackToExtF80( signZ, expZ, sig128.v64, sig128.v0, extF80_roundingPrecision ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ propagateNaN: uiZ = softfloat_propagateNaNExtF80UI( uiA64, uiA0, uiB64, uiB0 ); uiZ64 = uiZ.v64; uiZ0 = uiZ.v0; uiZ: uZ.s.signExp = uiZ64; uZ.s.signif = uiZ0; return uZ.f; }
void extF80M_mul( const extFloat80_t *aPtr, const extFloat80_t *bPtr, extFloat80_t *zPtr ) { const struct extFloat80M *aSPtr, *bSPtr; struct extFloat80M *zSPtr; uint_fast16_t uiA64; int32_t expA; uint_fast16_t uiB64; int32_t expB; bool signZ; uint_fast16_t exp, uiZ64; uint64_t uiZ0, sigA, sigB; int32_t expZ; uint32_t sigProd[4], *extSigZPtr; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ aSPtr = (const struct extFloat80M *) aPtr; bSPtr = (const struct extFloat80M *) bPtr; zSPtr = (struct extFloat80M *) zPtr; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiA64 = aSPtr->signExp; expA = expExtF80UI64( uiA64 ); uiB64 = bSPtr->signExp; expB = expExtF80UI64( uiB64 ); signZ = signExtF80UI64( uiA64 ) ^ signExtF80UI64( uiB64 ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( (expA == 0x7FFF) || (expB == 0x7FFF) ) { if ( softfloat_tryPropagateNaNExtF80M( aSPtr, bSPtr, zSPtr ) ) return; if ( (! aSPtr->signif && (expA != 0x7FFF)) || (! bSPtr->signif && (expB != 0x7FFF)) ) { softfloat_invalidExtF80M( zSPtr ); return; } uiZ64 = packToExtF80UI64( signZ, 0x7FFF ); uiZ0 = UINT64_C( 0x8000000000000000 ); goto uiZ; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ! expA ) expA = 1; sigA = aSPtr->signif; if ( ! (sigA & UINT64_C( 0x8000000000000000 )) ) { if ( ! sigA ) goto zero; expA += softfloat_normExtF80SigM( &sigA ); } if ( ! expB ) expB = 1; sigB = bSPtr->signif; if ( ! (sigB & UINT64_C( 0x8000000000000000 )) ) { if ( ! sigB ) goto zero; expB += softfloat_normExtF80SigM( &sigB ); } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expZ = expA + expB - 0x3FFE; softfloat_mul64To128M( sigA, sigB, sigProd ); if ( sigProd[indexWordLo( 4 )] ) sigProd[indexWord( 4, 1 )] |= 1; extSigZPtr = &sigProd[indexMultiwordHi( 4, 3 )]; if ( sigProd[indexWordHi( 4 )] < 0x80000000 ) { --expZ; softfloat_add96M( extSigZPtr, extSigZPtr, extSigZPtr ); } softfloat_roundPackMToExtF80M( signZ, expZ, extSigZPtr, extF80_roundingPrecision, zSPtr ); return; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ zero: uiZ64 = packToExtF80UI64( signZ, 0 ); uiZ0 = 0; uiZ: zSPtr->signExp = uiZ64; zSPtr->signif = uiZ0; }