float16_t f128M_to_f16( const float128_t *aPtr ) { const uint32_t *aWPtr; uint32_t uiA96; bool sign; int32_t exp; uint32_t frac32; struct commonNaN commonNaN; uint16_t uiZ, frac16; union ui16_f16 uZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ aWPtr = (const uint32_t *) aPtr; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiA96 = aWPtr[indexWordHi( 4 )]; sign = signF128UI96( uiA96 ); exp = expF128UI96( uiA96 ); frac32 = fracF128UI96( uiA96 ) | ((aWPtr[indexWord( 4, 2 )] | aWPtr[indexWord( 4, 1 )] | aWPtr[indexWord( 4, 0 )]) != 0); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( exp == 0x7FFF ) { if ( frac32 ) { softfloat_f128MToCommonNaN( aWPtr, &commonNaN ); uiZ = softfloat_commonNaNToF16UI( &commonNaN ); } else { uiZ = packToF16UI( sign, 0x1F, 0 ); } goto uiZ; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ frac16 = frac32>>2 | (frac32 & 3); if ( ! (exp | frac16) ) { uiZ = packToF16UI( sign, 0, 0 ); goto uiZ; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ exp -= 0x3FF1; if ( sizeof (int_fast16_t) < sizeof (int32_t) ) { if ( exp < -0x40 ) exp = -0x40; } return softfloat_roundPackToF16( sign, exp, frac16 | 0x4000 ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiZ: uZ.ui = uiZ; return uZ.f; }
float16_t i64_to_f16( int64_t a ) { bool sign; uint_fast64_t absA; int_fast8_t shiftDist; union ui16_f16 u; uint_fast16_t sig; sign = (a < 0); absA = sign ? -(uint_fast64_t) a : (uint_fast64_t) a; shiftDist = softfloat_countLeadingZeros64( absA ) - 53; if ( 0 <= shiftDist ) { u.ui = a ? packToF16UI( sign, 0x18 - shiftDist, (uint_fast16_t) absA<<shiftDist ) : 0; return u.f; } else { shiftDist += 4; sig = (shiftDist < 0) ? softfloat_shortShiftRightJam64( absA, -shiftDist ) : (uint_fast16_t) absA<<shiftDist; return softfloat_roundPackToF16( sign, 0x1C - shiftDist, sig ); } }
float16_t i32_to_f16( int32_t a ) { bool sign; uint_fast32_t absA; int_fast8_t shiftDist; union ui16_f16 u; uint_fast16_t sig; sign = (a < 0); absA = sign ? -(uint_fast32_t) a : (uint_fast32_t) a; shiftDist = softfloat_countLeadingZeros32( absA ) - 21; if ( 0 <= shiftDist ) { u.ui = a ? packToF16UI( sign, 0x18 - shiftDist, (uint_fast16_t) absA<<shiftDist ) : 0; return u.f; } else { shiftDist += 4; sig = (shiftDist < 0) ? absA>>(-shiftDist) | ((uint32_t) (absA<<(shiftDist & 31)) != 0) : (uint_fast16_t) absA<<shiftDist; return softfloat_roundPackToF16( sign, 0x1C - shiftDist, sig ); } }
float16_t f32_to_f16( float32_t a ) { union ui32_f32 uA; uint_fast32_t uiA; bool sign; int_fast16_t exp; uint_fast32_t frac; struct commonNaN commonNaN; uint_fast16_t uiZ, frac16; union ui16_f16 uZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uA.f = a; uiA = uA.ui; sign = signF32UI( uiA ); exp = expF32UI( uiA ); frac = fracF32UI( uiA ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( exp == 0xFF ) { if ( frac ) { softfloat_f32UIToCommonNaN( uiA, &commonNaN ); uiZ = softfloat_commonNaNToF16UI( &commonNaN ); } else { uiZ = packToF16UI( sign, 0x1F, 0 ); } goto uiZ; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ frac16 = frac>>9 | ((frac & 0x1FF) != 0); if ( ! (exp | frac16) ) { uiZ = packToF16UI( sign, 0, 0 ); goto uiZ; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ return softfloat_roundPackToF16( sign, exp - 0x71, frac16 | 0x4000 ); uiZ: uZ.ui = uiZ; return uZ.f; }
float16_t f64_to_f16( float64_t a ) { union ui64_f64 uA; uint_fast64_t uiA; bool sign; int_fast16_t exp; uint_fast64_t frac; struct commonNaN commonNaN; uint_fast16_t uiZ, frac16; union ui16_f16 uZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uA.f = a; uiA = uA.ui; sign = signF64UI( uiA ); exp = expF64UI( uiA ); frac = fracF64UI( uiA ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( exp == 0x7FF ) { if ( frac ) { softfloat_f64UIToCommonNaN( uiA, &commonNaN ); uiZ = softfloat_commonNaNToF16UI( &commonNaN ); } else { uiZ = packToF16UI( sign, 0x1F, 0 ); } goto uiZ; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ frac16 = softfloat_shortShiftRightJam64( frac, 38 ); if ( ! (exp | frac16) ) { uiZ = packToF16UI( sign, 0, 0 ); goto uiZ; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ return softfloat_roundPackToF16( sign, exp - 0x3F1, frac16 | 0x4000 ); uiZ: uZ.ui = uiZ; return uZ.f; }
float16_t softfloat_normRoundPackToF16( bool sign, int_fast16_t exp, uint_fast16_t sig ) { int_fast8_t shiftDist; union ui16_f16 uZ; shiftDist = softfloat_countLeadingZeros16( sig ) - 1; exp -= shiftDist; if ( (4 <= shiftDist) && ((unsigned int) exp < 0x1D) ) { uZ.ui = packToF16UI( sign, sig ? exp : 0, sig<<(shiftDist - 4) ); return uZ.f; } else { return softfloat_roundPackToF16( sign, exp, sig<<shiftDist ); } }
float16_t f16_mul( float16_t a, float16_t b ) { union ui16_f16 uA; uint_fast16_t uiA; bool signA; int_fast8_t expA; uint_fast16_t sigA; union ui16_f16 uB; uint_fast16_t uiB; bool signB; int_fast8_t expB; uint_fast16_t sigB; bool signZ; uint_fast16_t magBits; struct exp8_sig16 normExpSig; int_fast8_t expZ; uint_fast32_t sig32Z; uint_fast16_t sigZ, uiZ; union ui16_f16 uZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uA.f = a; uiA = uA.ui; signA = signF16UI( uiA ); expA = expF16UI( uiA ); sigA = fracF16UI( uiA ); uB.f = b; uiB = uB.ui; signB = signF16UI( uiB ); expB = expF16UI( uiB ); sigB = fracF16UI( uiB ); signZ = signA ^ signB; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( expA == 0x1F ) { if ( sigA || ((expB == 0x1F) && sigB) ) goto propagateNaN; magBits = expB | sigB; goto infArg; } if ( expB == 0x1F ) { if ( sigB ) goto propagateNaN; magBits = expA | sigA; goto infArg; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ! expA ) { if ( ! sigA ) goto zero; normExpSig = softfloat_normSubnormalF16Sig( sigA ); expA = normExpSig.exp; sigA = normExpSig.sig; } if ( ! expB ) { if ( ! sigB ) goto zero; normExpSig = softfloat_normSubnormalF16Sig( sigB ); expB = normExpSig.exp; sigB = normExpSig.sig; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expZ = expA + expB - 0xF; sigA = (sigA | 0x0400)<<4; sigB = (sigB | 0x0400)<<5; sig32Z = (uint_fast32_t) sigA * sigB; sigZ = sig32Z>>16; if ( sig32Z & 0xFFFF ) sigZ |= 1; if ( sigZ < 0x4000 ) { --expZ; sigZ <<= 1; } return softfloat_roundPackToF16( signZ, expZ, sigZ ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ propagateNaN: uiZ = softfloat_propagateNaNF16UI( uiA, uiB ); goto uiZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ infArg: if ( ! magBits ) { softfloat_raiseFlags( softfloat_flag_invalid ); uiZ = defaultNaNF16UI; } else { uiZ = packToF16UI( signZ, 0x1F, 0 ); } goto uiZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ zero: uiZ = packToF16UI( signZ, 0, 0 ); uiZ: uZ.ui = uiZ; return uZ.f; }