Skip to content

Commit 3745f4b

Browse files
committed
* documentation in the code updated, fixed errors with parsing some special very big exponent numbers.
1 parent 6cefbb5 commit 3745f4b

File tree

3 files changed

+31
-24
lines changed

3 files changed

+31
-24
lines changed

include/fast_float/ascii_number.h

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,7 @@ parse_number_string(UC const *p, UC const *pend,
435435
} else {
436436
// Now let's parse the explicit exponent.
437437
while ((p != pend) && is_integer(*p)) {
438-
if (exp_number < std::numeric_limits<am_pow_t>::max()) {
438+
if (exp_number < am_bias_limit) {
439439
// check for exponent overflow if we have too many digits.
440440
auto const digit = uint8_t(*p - UC('0'));
441441
exp_number = 10 * exp_number + digit;
@@ -561,7 +561,7 @@ parse_int_string(UC const *p, UC const *pend, T &value,
561561
auto const *const start_digits = p;
562562

563563
FASTFLOAT_IF_CONSTEXPR17((std::is_same<T, std::uint8_t>::value)) {
564-
const size_t len = (size_t)(pend - p);
564+
const auto len = static_cast<am_digits>(pend - p);
565565
if (len == 0) {
566566
if (has_leading_zeros) {
567567
value = 0;
@@ -581,7 +581,7 @@ parse_int_string(UC const *p, UC const *pend, T &value,
581581

582582
if (cpp20_and_in_constexpr()) {
583583
digits.as_int = 0;
584-
for (size_t j = 0; j < 4 && j < len; ++j) {
584+
for (uint_fast8_t j = 0; j < 4 && j < len; ++j) {
585585
digits.as_str[j] = static_cast<uint8_t>(p[j]);
586586
}
587587
} else if (len >= 4) {
@@ -598,12 +598,13 @@ parse_int_string(UC const *p, UC const *pend, T &value,
598598
#endif
599599
}
600600

601-
uint32_t magic =
601+
const uint32_t magic =
602602
((digits.as_int + 0x46464646u) | (digits.as_int - 0x30303030u)) &
603603
0x80808080u;
604-
uint32_t tz = (uint32_t)countr_zero_32(magic); // 7, 15, 23, 31, or 32
604+
const auto tz =
605+
static_cast<uint32_t>(countr_zero_32(magic)); // 7, 15, 23, 31, or 32
605606
uint32_t nd = (tz == 32) ? 4 : (tz >> 3);
606-
nd = (uint32_t)std::min((size_t)nd, len);
607+
nd = std::min(nd, len);
607608
if (nd == 0) {
608609
if (has_leading_zeros) {
609610
value = 0;
@@ -617,7 +618,7 @@ parse_int_string(UC const *p, UC const *pend, T &value,
617618
}
618619
if (nd > 3) {
619620
const UC *q = p + nd;
620-
size_t rem = len - nd;
621+
uint_fast8_t rem = len - nd;
621622
while (rem) {
622623
if (*q < UC('0') || *q > UC('9'))
623624
break;
@@ -632,15 +633,15 @@ parse_int_string(UC const *p, UC const *pend, T &value,
632633
digits.as_int ^= 0x30303030u;
633634
digits.as_int <<= ((4 - nd) * 8);
634635

635-
uint32_t check = ((digits.as_int >> 24) & 0xff) |
636-
((digits.as_int >> 8) & 0xff00) |
637-
((digits.as_int << 8) & 0xff0000);
636+
const uint32_t check = ((digits.as_int >> 24) & 0xff) |
637+
((digits.as_int >> 8) & 0xff00) |
638+
((digits.as_int << 8) & 0xff0000);
638639
if (check > 0x00020505) {
639640
answer.ec = std::errc::result_out_of_range;
640641
answer.ptr = p + nd;
641642
return answer;
642643
}
643-
value = (uint8_t)((0x640a01 * digits.as_int) >> 24);
644+
value = static_cast<uint8_t>((0x640a01 * digits.as_int) >> 24);
644645
answer.ec = std::errc();
645646
answer.ptr = p + nd;
646647
return answer;

include/fast_float/fast_float.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,11 @@ from_chars_advanced(UC const *first, UC const *last, T &value,
5959
* `new` or `malloc`).
6060
*/
6161
FASTFLOAT_CONSTEXPR20 inline double
62-
integer_times_pow10(uint64_t const mantissa,
63-
int_fast16_t const decimal_exponent) noexcept;
62+
integer_times_pow10(am_mant_t const mantissa,
63+
am_pow_t const decimal_exponent) noexcept;
6464
FASTFLOAT_CONSTEXPR20 inline double
65-
integer_times_pow10(int64_t const mantissa,
66-
int_fast16_t const decimal_exponent) noexcept;
65+
integer_times_pow10(am_sign_mant_t const mantissa,
66+
am_pow_t const decimal_exponent) noexcept;
6767

6868
/**
6969
* This function is a template overload of `integer_times_pow10()`
@@ -73,13 +73,13 @@ integer_times_pow10(int64_t const mantissa,
7373
template <typename T>
7474
FASTFLOAT_CONSTEXPR20
7575
typename std::enable_if<is_supported_float_type<T>::value, T>::type
76-
integer_times_pow10(uint64_t const mantissa,
77-
int_fast16_t const decimal_exponent) noexcept;
76+
integer_times_pow10(am_mant_t const mantissa,
77+
am_pow_t const decimal_exponent) noexcept;
7878
template <typename T>
7979
FASTFLOAT_CONSTEXPR20
8080
typename std::enable_if<is_supported_float_type<T>::value, T>::type
81-
integer_times_pow10(int64_t const mantissa,
82-
int_fast16_t const decimal_exponent) noexcept;
81+
integer_times_pow10(am_sign_mant_t const mantissa,
82+
am_pow_t const decimal_exponent) noexcept;
8383

8484
/**
8585
* from_chars for integer types.

include/fast_float/float_common.h

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -500,18 +500,24 @@ full_multiplication(uint64_t a, uint64_t b) noexcept {
500500
return answer;
501501
}
502502

503-
// Value of the mantissa. An unsigned int avoids signed overflows (which are
504-
// bad)
503+
// 64 bit integer is used because mantissa can be up to 53 bits for double.
504+
// Value of the int mantissa in the API.
505+
typedef int_fast64_t am_sign_mant_t;
506+
// An unsigned int avoids signed overflows (which are bad)
505507
typedef uint_fast64_t am_mant_t;
508+
506509
// Size of bits in the mantissa and path and rounding shifts
507510
typedef int_fast8_t am_bits_t;
508511

512+
// 16 bit signed integer is used for power to cover all double exponents.
509513
// Power bias is signed for handling a denormal float
510514
// or an invalid mantissa.
511-
typedef int_fast64_t am_pow_t;
512-
515+
typedef int_fast16_t am_pow_t;
513516
// Bias so we can get the real exponent with an invalid adjusted_mantissa.
514-
constexpr static am_pow_t invalid_am_bias = -0x8000;
517+
constexpr static am_pow_t invalid_am_bias =
518+
std::numeric_limits<int16_t>::min() + 1;
519+
constexpr static am_pow_t am_bias_limit =
520+
(std::numeric_limits<int16_t>::max() + 1) / 8;
515521

516522
struct alignas(16) adjusted_mantissa {
517523
am_mant_t mantissa;

0 commit comments

Comments
 (0)