mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-10-07 10:54:01 +00:00
[libc] Add get_explicit_exponent to fpbits
In the same way that get_explicit_mantissa is used to get the mantissa with all the implicit bits spelled out, get_explicit_exponent gives you the exponent with the special cases handled. Mainly it handles the cases where the exponent is zero, which causes the exponent to either be 1 higher than expected, or just 0. Reviewed By: lntue Differential Revision: https://reviews.llvm.org/D157156
This commit is contained in:
parent
95ab1cd712
commit
455d678019
@ -128,6 +128,23 @@ template <typename T> struct FPBits {
|
||||
return int(get_unbiased_exponent()) - EXPONENT_BIAS;
|
||||
}
|
||||
|
||||
// If the number is subnormal, the exponent is treated as if it were the
|
||||
// minimum exponent for a normal number. This is to keep continuity between
|
||||
// the normal and subnormal ranges, but it causes problems for functions where
|
||||
// values are calculated from the exponent, since just subtracting the bias
|
||||
// will give a slightly incorrect result. Additionally, zero has an exponent
|
||||
// of zero, and that should actually be treated as zero.
|
||||
LIBC_INLINE int get_explicit_exponent() const {
|
||||
const int unbiased_exp = int(get_unbiased_exponent());
|
||||
if (is_zero()) {
|
||||
return 0;
|
||||
} else if (unbiased_exp == 0) {
|
||||
return 1 - EXPONENT_BIAS;
|
||||
} else {
|
||||
return unbiased_exp - EXPONENT_BIAS;
|
||||
}
|
||||
}
|
||||
|
||||
LIBC_INLINE bool is_zero() const {
|
||||
// Remove sign bit by shift
|
||||
return (bits << 1) == 0;
|
||||
|
@ -60,7 +60,7 @@ LIBC_INLINE long double sqrt(long double x) {
|
||||
// sqrt( negative numbers ) = NaN
|
||||
return FPBits<long double>::build_quiet_nan(ONE >> 1);
|
||||
} else {
|
||||
int x_exp = bits.get_exponent();
|
||||
int x_exp = bits.get_explicit_exponent();
|
||||
UIntType x_mant = bits.get_mantissa();
|
||||
|
||||
// Step 1a: Normalize denormal input
|
||||
|
@ -135,11 +135,26 @@ template <> struct FPBits<long double> {
|
||||
}
|
||||
|
||||
LIBC_INLINE int get_exponent() const {
|
||||
if (get_unbiased_exponent() == 0)
|
||||
return int(1) - EXPONENT_BIAS;
|
||||
return int(get_unbiased_exponent()) - EXPONENT_BIAS;
|
||||
}
|
||||
|
||||
// If the number is subnormal, the exponent is treated as if it were the
|
||||
// minimum exponent for a normal number. This is to keep continuity between
|
||||
// the normal and subnormal ranges, but it causes problems for functions where
|
||||
// values are calculated from the exponent, since just subtracting the bias
|
||||
// will give a slightly incorrect result. Additionally, zero has an exponent
|
||||
// of zero, and that should actually be treated as zero.
|
||||
LIBC_INLINE int get_explicit_exponent() const {
|
||||
const int unbiased_exp = int(get_unbiased_exponent());
|
||||
if (is_zero()) {
|
||||
return 0;
|
||||
} else if (unbiased_exp == 0) {
|
||||
return 1 - EXPONENT_BIAS;
|
||||
} else {
|
||||
return unbiased_exp - EXPONENT_BIAS;
|
||||
}
|
||||
}
|
||||
|
||||
LIBC_INLINE bool is_zero() const {
|
||||
return get_unbiased_exponent() == 0 && get_mantissa() == 0 &&
|
||||
get_implicit_bit() == 0;
|
||||
|
@ -423,18 +423,9 @@ class FloatToString {
|
||||
public:
|
||||
LIBC_INLINE constexpr FloatToString(T init_float) : float_bits(init_float) {
|
||||
is_negative = float_bits.get_sign();
|
||||
exponent = float_bits.get_exponent();
|
||||
exponent = float_bits.get_explicit_exponent();
|
||||
mantissa = float_bits.get_explicit_mantissa();
|
||||
|
||||
// Handle the exponent for numbers with a 0 exponent.
|
||||
if (exponent == -EXP_BIAS) {
|
||||
if (mantissa > 0) { // Subnormals
|
||||
++exponent;
|
||||
} else { // Zeroes
|
||||
exponent = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Adjust for the width of the mantissa.
|
||||
exponent -= MANT_WIDTH;
|
||||
|
||||
|
@ -483,7 +483,7 @@ LIBC_INLINE int convert_float_decimal_typed(Writer *writer,
|
||||
// signed because later we use -MANT_WIDTH
|
||||
constexpr int32_t MANT_WIDTH = fputil::MantissaWidth<T>::VALUE;
|
||||
bool is_negative = float_bits.get_sign();
|
||||
int exponent = float_bits.get_exponent();
|
||||
int exponent = float_bits.get_explicit_exponent();
|
||||
|
||||
char sign_char = 0;
|
||||
|
||||
@ -626,7 +626,7 @@ LIBC_INLINE int convert_float_dec_exp_typed(Writer *writer,
|
||||
// signed because later we use -MANT_WIDTH
|
||||
constexpr int32_t MANT_WIDTH = fputil::MantissaWidth<T>::VALUE;
|
||||
bool is_negative = float_bits.get_sign();
|
||||
int exponent = float_bits.get_exponent();
|
||||
int exponent = float_bits.get_explicit_exponent();
|
||||
MantissaInt mantissa = float_bits.get_explicit_mantissa();
|
||||
|
||||
const char a = (to_conv.conv_name & 32) | 'A';
|
||||
@ -787,7 +787,7 @@ LIBC_INLINE int convert_float_dec_auto_typed(Writer *writer,
|
||||
// signed because later we use -MANT_WIDTH
|
||||
constexpr int32_t MANT_WIDTH = fputil::MantissaWidth<T>::VALUE;
|
||||
bool is_negative = float_bits.get_sign();
|
||||
int exponent = float_bits.get_exponent();
|
||||
int exponent = float_bits.get_explicit_exponent();
|
||||
MantissaInt mantissa = float_bits.get_explicit_mantissa();
|
||||
|
||||
// From the standard: Let P (init_precision) equal the precision if nonzero, 6
|
||||
|
@ -39,24 +39,21 @@ LIBC_INLINE int convert_float_hex_exp(Writer *writer,
|
||||
MantissaInt mantissa;
|
||||
bool is_inf_or_nan;
|
||||
uint32_t mantissa_width;
|
||||
int exponent_bias;
|
||||
if (to_conv.length_modifier == LengthModifier::L) {
|
||||
mantissa_width = fputil::MantissaWidth<long double>::VALUE;
|
||||
exponent_bias = fputil::FPBits<long double>::EXPONENT_BIAS;
|
||||
fputil::FPBits<long double>::UIntType float_raw = to_conv.conv_val_raw;
|
||||
fputil::FPBits<long double> float_bits(float_raw);
|
||||
is_negative = float_bits.get_sign();
|
||||
exponent = float_bits.get_exponent();
|
||||
exponent = float_bits.get_explicit_exponent();
|
||||
mantissa = float_bits.get_explicit_mantissa();
|
||||
is_inf_or_nan = float_bits.is_inf_or_nan();
|
||||
} else {
|
||||
mantissa_width = fputil::MantissaWidth<double>::VALUE;
|
||||
exponent_bias = fputil::FPBits<double>::EXPONENT_BIAS;
|
||||
fputil::FPBits<double>::UIntType float_raw =
|
||||
static_cast<fputil::FPBits<double>::UIntType>(to_conv.conv_val_raw);
|
||||
fputil::FPBits<double> float_bits(float_raw);
|
||||
is_negative = float_bits.get_sign();
|
||||
exponent = float_bits.get_exponent();
|
||||
exponent = float_bits.get_explicit_exponent();
|
||||
mantissa = float_bits.get_explicit_mantissa();
|
||||
is_inf_or_nan = float_bits.is_inf_or_nan();
|
||||
}
|
||||
@ -74,14 +71,6 @@ LIBC_INLINE int convert_float_hex_exp(Writer *writer,
|
||||
FormatFlags::SPACE_PREFIX)
|
||||
sign_char = ' ';
|
||||
|
||||
// Handle the exponent for numbers with a 0 exponent
|
||||
if (exponent == -exponent_bias) {
|
||||
if (mantissa > 0) // Subnormals
|
||||
++exponent;
|
||||
else // Zeroes
|
||||
exponent = 0;
|
||||
}
|
||||
|
||||
constexpr size_t BITS_IN_HEX_DIGIT = 4;
|
||||
|
||||
// This is to handle situations where the mantissa isn't an even number of hex
|
||||
|
Loading…
Reference in New Issue
Block a user