mirror of
https://github.com/fastfloat/fast_float.git
synced 2026-06-16 00:46:06 +08:00
* documentation in the code updated, fixed errors with parsing some special very big exponent numbers.
This commit is contained in:
parent
6cefbb53ba
commit
3745f4b009
@ -435,7 +435,7 @@ parse_number_string(UC const *p, UC const *pend,
|
||||
} else {
|
||||
// Now let's parse the explicit exponent.
|
||||
while ((p != pend) && is_integer(*p)) {
|
||||
if (exp_number < std::numeric_limits<am_pow_t>::max()) {
|
||||
if (exp_number < am_bias_limit) {
|
||||
// check for exponent overflow if we have too many digits.
|
||||
auto const digit = uint8_t(*p - UC('0'));
|
||||
exp_number = 10 * exp_number + digit;
|
||||
@ -561,7 +561,7 @@ parse_int_string(UC const *p, UC const *pend, T &value,
|
||||
auto const *const start_digits = p;
|
||||
|
||||
FASTFLOAT_IF_CONSTEXPR17((std::is_same<T, std::uint8_t>::value)) {
|
||||
const size_t len = (size_t)(pend - p);
|
||||
const auto len = static_cast<am_digits>(pend - p);
|
||||
if (len == 0) {
|
||||
if (has_leading_zeros) {
|
||||
value = 0;
|
||||
@ -581,7 +581,7 @@ parse_int_string(UC const *p, UC const *pend, T &value,
|
||||
|
||||
if (cpp20_and_in_constexpr()) {
|
||||
digits.as_int = 0;
|
||||
for (size_t j = 0; j < 4 && j < len; ++j) {
|
||||
for (uint_fast8_t j = 0; j < 4 && j < len; ++j) {
|
||||
digits.as_str[j] = static_cast<uint8_t>(p[j]);
|
||||
}
|
||||
} else if (len >= 4) {
|
||||
@ -598,12 +598,13 @@ parse_int_string(UC const *p, UC const *pend, T &value,
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t magic =
|
||||
const uint32_t magic =
|
||||
((digits.as_int + 0x46464646u) | (digits.as_int - 0x30303030u)) &
|
||||
0x80808080u;
|
||||
uint32_t tz = (uint32_t)countr_zero_32(magic); // 7, 15, 23, 31, or 32
|
||||
const auto tz =
|
||||
static_cast<uint32_t>(countr_zero_32(magic)); // 7, 15, 23, 31, or 32
|
||||
uint32_t nd = (tz == 32) ? 4 : (tz >> 3);
|
||||
nd = (uint32_t)std::min((size_t)nd, len);
|
||||
nd = std::min(nd, len);
|
||||
if (nd == 0) {
|
||||
if (has_leading_zeros) {
|
||||
value = 0;
|
||||
@ -617,7 +618,7 @@ parse_int_string(UC const *p, UC const *pend, T &value,
|
||||
}
|
||||
if (nd > 3) {
|
||||
const UC *q = p + nd;
|
||||
size_t rem = len - nd;
|
||||
uint_fast8_t rem = len - nd;
|
||||
while (rem) {
|
||||
if (*q < UC('0') || *q > UC('9'))
|
||||
break;
|
||||
@ -632,15 +633,15 @@ parse_int_string(UC const *p, UC const *pend, T &value,
|
||||
digits.as_int ^= 0x30303030u;
|
||||
digits.as_int <<= ((4 - nd) * 8);
|
||||
|
||||
uint32_t check = ((digits.as_int >> 24) & 0xff) |
|
||||
((digits.as_int >> 8) & 0xff00) |
|
||||
((digits.as_int << 8) & 0xff0000);
|
||||
const uint32_t check = ((digits.as_int >> 24) & 0xff) |
|
||||
((digits.as_int >> 8) & 0xff00) |
|
||||
((digits.as_int << 8) & 0xff0000);
|
||||
if (check > 0x00020505) {
|
||||
answer.ec = std::errc::result_out_of_range;
|
||||
answer.ptr = p + nd;
|
||||
return answer;
|
||||
}
|
||||
value = (uint8_t)((0x640a01 * digits.as_int) >> 24);
|
||||
value = static_cast<uint8_t>((0x640a01 * digits.as_int) >> 24);
|
||||
answer.ec = std::errc();
|
||||
answer.ptr = p + nd;
|
||||
return answer;
|
||||
|
||||
@ -59,11 +59,11 @@ from_chars_advanced(UC const *first, UC const *last, T &value,
|
||||
* `new` or `malloc`).
|
||||
*/
|
||||
FASTFLOAT_CONSTEXPR20 inline double
|
||||
integer_times_pow10(uint64_t const mantissa,
|
||||
int_fast16_t const decimal_exponent) noexcept;
|
||||
integer_times_pow10(am_mant_t const mantissa,
|
||||
am_pow_t const decimal_exponent) noexcept;
|
||||
FASTFLOAT_CONSTEXPR20 inline double
|
||||
integer_times_pow10(int64_t const mantissa,
|
||||
int_fast16_t const decimal_exponent) noexcept;
|
||||
integer_times_pow10(am_sign_mant_t const mantissa,
|
||||
am_pow_t const decimal_exponent) noexcept;
|
||||
|
||||
/**
|
||||
* This function is a template overload of `integer_times_pow10()`
|
||||
@ -73,13 +73,13 @@ integer_times_pow10(int64_t const mantissa,
|
||||
template <typename T>
|
||||
FASTFLOAT_CONSTEXPR20
|
||||
typename std::enable_if<is_supported_float_type<T>::value, T>::type
|
||||
integer_times_pow10(uint64_t const mantissa,
|
||||
int_fast16_t const decimal_exponent) noexcept;
|
||||
integer_times_pow10(am_mant_t const mantissa,
|
||||
am_pow_t const decimal_exponent) noexcept;
|
||||
template <typename T>
|
||||
FASTFLOAT_CONSTEXPR20
|
||||
typename std::enable_if<is_supported_float_type<T>::value, T>::type
|
||||
integer_times_pow10(int64_t const mantissa,
|
||||
int_fast16_t const decimal_exponent) noexcept;
|
||||
integer_times_pow10(am_sign_mant_t const mantissa,
|
||||
am_pow_t const decimal_exponent) noexcept;
|
||||
|
||||
/**
|
||||
* from_chars for integer types.
|
||||
|
||||
@ -500,18 +500,24 @@ full_multiplication(uint64_t a, uint64_t b) noexcept {
|
||||
return answer;
|
||||
}
|
||||
|
||||
// Value of the mantissa. An unsigned int avoids signed overflows (which are
|
||||
// bad)
|
||||
// 64 bit integer is used because mantissa can be up to 53 bits for double.
|
||||
// Value of the int mantissa in the API.
|
||||
typedef int_fast64_t am_sign_mant_t;
|
||||
// An unsigned int avoids signed overflows (which are bad)
|
||||
typedef uint_fast64_t am_mant_t;
|
||||
|
||||
// Size of bits in the mantissa and path and rounding shifts
|
||||
typedef int_fast8_t am_bits_t;
|
||||
|
||||
// 16 bit signed integer is used for power to cover all double exponents.
|
||||
// Power bias is signed for handling a denormal float
|
||||
// or an invalid mantissa.
|
||||
typedef int_fast64_t am_pow_t;
|
||||
|
||||
typedef int_fast16_t am_pow_t;
|
||||
// Bias so we can get the real exponent with an invalid adjusted_mantissa.
|
||||
constexpr static am_pow_t invalid_am_bias = -0x8000;
|
||||
constexpr static am_pow_t invalid_am_bias =
|
||||
std::numeric_limits<int16_t>::min() + 1;
|
||||
constexpr static am_pow_t am_bias_limit =
|
||||
(std::numeric_limits<int16_t>::max() + 1) / 8;
|
||||
|
||||
struct alignas(16) adjusted_mantissa {
|
||||
am_mant_t mantissa;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user