fold.cpp
/*
 * Takes an abstract value having sign `sign_z', exponent `exp_z', and significand
 * `sig_z' and returns the appropriate value corresponding to the abstract input.
 *
 * The abstract value is simply rounded and packed into the format. If the abstract
 * input cannot be represented exactly an inexact exception is raised. If the
 * abstract input is too large, the overflow and inexact exceptions are both raised
 * and an infinity or maximal finite value is returned. If the abstract value is
 * too small, the value is rounded to a subnormal and the underflow and inexact
 * exceptions are only raised if the value cannot be represented exactly with
 * a subnormal.
 *
 * The input significand `sig_z' has it's binary point between bits 30 and 29,
 * this is seven bits to the left of its usual location. The shifted significand
 * must be normalized or smaller than this. If it's not normalized then the exponent
 * `exp_z' must be zero; in that case, the result returned is a subnormal number
 * which must not require rounding. In the more usual case where the significand
 * is normalized, the exponent must be one less than the *true* exponent.
 *
 * The handling of underflow and overflow is otherwise in alignment with IEC/IEEE.
 */
Takes an abstract value having sign `sign_z', exponent `exp_z', and significand
`sig_z' and returns the appropriate value corresponding to the abstract input.

The abstract value is simply rounded and packed into the format. If the abstract
input cannot be represented exactly an inexact exception is raised. If the
abstract input is too large, the overflow and inexact exceptions are both raised
and an infinity or maximal finite value is returned. If the abstract value is
too small, the value is rounded to a subnormal and the underflow and inexact
exceptions are only raised if the value cannot be represented exactly with
a subnormal.

The input significand `sig_z' has it's binary point between bits 30 and 29,
this is seven bits to the left of its usual location. The shifted significand
must be normalized or smaller than this. If it's not normalized then the exponent
`exp_z' must be zero; in that case, the result returned is a subnormal number
which must not require rounding. In the more usual case where the significand
is normalized, the exponent must be one less than the *true* exponent.

The handling of underflow and overflow is otherwise in alignment with IEC/IEEE.
Takes an abstract value having sign ` sign_z ' exponent ` exp_z ' and significand ` sig_z ' and returns the appropriate value corresponding to the abstract input . The abstract value is simply rounded and packed into the format . If the abstract input cannot be represented exactly an inexact exception is raised . If the abstract input is too large the overflow and inexact exceptions are both raised and an infinity or maximal finite value is returned . If the abstract value is too small the value is rounded to a subnormal and the underflow and inexact exceptions are only raised if the value cannot be represented exactly with a subnormal . The input significand ` sig_z ' has it ' s binary point between bits 30 and 29 this is seven bits to the left of its usual location . The shifted significand must be normalized or smaller than this . If it ' s not normalized then the exponent ` exp_z ' must be zero ; in that case the result returned is a subnormal number which must not require rounding . In the more usual case where the significand is normalized the exponent must be one less than the * true * exponent . The handling of underflow and overflow is otherwise in alignment with IEC / IEEE .
static sfloat_t SFLOAT_PACK_round(sfloat_state_t *state, bool sign_z, int16_t exp_z, uint32_t sig_z) {
    sfloat_roundingmode_t mode      = state->roundingmode;
    bool                  even      = !!(mode == SFLOAT_ROUND_NEAREST_EVEN);
    unsigned char         increment = 0x40;
    unsigned char         bits      = sig_z & 0x7F;
    if (!even) {
        if (mode == SFLOAT_ROUND_TO_ZERO)
            increment = 0;
        else {
            increment = 0x7F;
            if (sign_z) {
                if (mode == SFLOAT_ROUND_UP)
                    increment = 0;
            } else {
                if (mode == SFLOAT_ROUND_DOWN)
                    increment = 0;
            }
        }
    }
    if (0xFD <= (uint16_t)exp_z) {
        if ((0xFD < exp_z) || ((exp_z == 0xFD) && ((int32_t)(sig_z + increment) < 0))) {
            SFLOAT_RAISE(state, SFLOAT_OVERFLOW | SFLOAT_INEXACT);
            return SFLOAT_PACK(sign_z, 0xFF, 0) - (increment == 0);
        }
        if (exp_z < 0) {
            bool tiny = (state->tiny == SFLOAT_TBEFORE) || (exp_z < -1) || (sig_z + increment < 0x80000000);
            SFLOAT_SHIFT(32, sig_z, -exp_z, &sig_z);
            exp_z = 0;
            bits = sig_z & 0x7F;
            if (tiny && bits)
                SFLOAT_RAISE(state, SFLOAT_UNDERFLOW);
        }
    }
    if (bits)
        SFLOAT_RAISE(state, SFLOAT_INEXACT);
    sig_z = (sig_z + increment) >> 7;
    sig_z &= ~(((bits ^ 0x40) == 0) & even);
    if (sig_z == 0)
        exp_z = 0;
    return SFLOAT_PACK(sign_z, exp_z, sig_z);
}
static sfloat_t SFLOAT_PACK_round ( sfloat_state_t * state , bool sign_z , int16_t exp_z , uint32_t sig_z ) { sfloat_roundingmode_t mode = state -> roundingmode ; bool even = ! ! ( mode == SFLOAT_ROUND_NEAREST_EVEN ) ; unsigned char increment = 0x40 ; unsigned char bits = sig_z & 0x7F ; if ( ! even ) { if ( mode == SFLOAT_ROUND_TO_ZERO ) increment = 0 ; else { increment = 0x7F ; if ( sign_z ) { if ( mode == SFLOAT_ROUND_UP ) increment = 0 ; } else { if ( mode == SFLOAT_ROUND_DOWN ) increment = 0 ; } } } if ( 0xFD <= ( uint16_t ) exp_z ) { if ( ( 0xFD < exp_z ) || ( ( exp_z == 0xFD ) && ( ( int32_t ) ( sig_z + increment ) < 0 ) ) ) { SFLOAT_RAISE ( state , SFLOAT_OVERFLOW | SFLOAT_INEXACT ) ; return SFLOAT_PACK ( sign_z , 0xFF , 0 ) - ( increment == 0 ) ; } if ( exp_z < 0 ) { bool tiny = ( state -> tiny == SFLOAT_TBEFORE ) || ( exp_z < -1 ) || ( sig_z + increment < 0x80000000 ) ; SFLOAT_SHIFT ( 32 , sig_z , - exp_z , & sig_z ) ; exp_z = 0 ; bits = sig_z & 0x7F ; if ( tiny && bits ) SFLOAT_RAISE ( state , SFLOAT_UNDERFLOW ) ; } } if ( bits ) SFLOAT_RAISE ( state , SFLOAT_INEXACT ) ; sig_z = ( sig_z + increment ) >> 7 ; sig_z &= ~ ( ( ( bits ^ 0x40 ) == 0 ) & even ) ; if ( sig_z == 0 ) exp_z = 0 ; return SFLOAT_PACK ( sign_z , exp_z , sig_z ) ; }
Takes an abstract value having sign `sign_z', exponent `exp_z', and significand
 `sig_z' and returns the appropriate value corresponding to the abstract input.
Takes an abstract value having sign ` sign_z ' exponent ` exp_z ' and significand ` sig_z ' and returns the appropriate value corresponding to the abstract input .
/* Check for underflow */