mirror of
https://github.com/fastfloat/fast_float.git
synced 2026-10-31 03:16:25 +08:00
Parse the fraction tail and the exponent with one subtraction per digit
GCC computed the digit twice, and the in-loop exponent saturation became a select on the path to the power of ten. Saturate only for more than 18 exponent digits. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
ef5797fa94
commit
1eac92b03f
@ -459,8 +459,13 @@ parse_number_string_impl(UC const *p, UC const *pend,
|
||||
// for integers with many digits, digit parsing is the primary bottleneck.
|
||||
loop_parse_if_eight_digits(p, pend, i);
|
||||
|
||||
while ((p != pend) && is_integer(*p)) {
|
||||
uint8_t digit = uint8_t(*p - UC('0'));
|
||||
// One subtraction serves the digit test and the digit (GCC computes it
|
||||
// twice when written separately); in 64 bits it needs no extension.
|
||||
while (p != pend) {
|
||||
uint64_t const digit = uint64_t(*p) - uint64_t(UC('0'));
|
||||
if (digit > 9) {
|
||||
break;
|
||||
}
|
||||
++p;
|
||||
i = i * 10 + digit; // in rare cases, this will overflow, but that's ok
|
||||
}
|
||||
@ -509,13 +514,28 @@ parse_number_string_impl(UC const *p, UC const *pend,
|
||||
// Otherwise, we will be ignoring the 'e'.
|
||||
p = location_of_e;
|
||||
} else {
|
||||
while ((p != pend) && is_integer(*p)) {
|
||||
uint8_t digit = uint8_t(*p - UC('0'));
|
||||
if (exp_number < 0x10000000) {
|
||||
exp_number = 10 * exp_number + digit;
|
||||
// Same digit test as the fraction tail. No saturation in the loop: it
|
||||
// would add a select per digit on the path to the power of ten, and 18
|
||||
// digits fit in int64_t.
|
||||
UC const *const exp_start = p;
|
||||
uint64_t exp_digits = 0;
|
||||
while (p != pend) {
|
||||
uint64_t const digit = uint64_t(*p) - uint64_t(UC('0'));
|
||||
if (digit > 9) {
|
||||
break;
|
||||
}
|
||||
exp_digits = 10 * exp_digits + digit;
|
||||
++p;
|
||||
}
|
||||
exp_number = int64_t(exp_digits);
|
||||
if fastfloat_unlikely (p - exp_start > 18) {
|
||||
exp_number = 0;
|
||||
for (UC const *q = exp_start; q != p; ++q) {
|
||||
if (exp_number < 0x10000000) {
|
||||
exp_number = 10 * exp_number + (*q - UC('0'));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (neg_exp) {
|
||||
exp_number = -exp_number;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user