mirror of
https://github.com/fastfloat/fast_float.git
synced 2026-11-09 22:59:51 +08:00
EXP-050: straight-line nested-if integer-part scan (ported from ffc EXP-026/028)
Peel the first 5 iterations of the integer-part digit loop into nested ifs, eliminating the loop back-edge for the common 1-5 digit integer case. Identical semantics (i = 10*i + digit). Biggest win on inputs with multi-digit integer parts (mesh 3D coordinates). ARM Graviton4 (canonical MB/s, vs upstream 7790aa6 baseline): GCC: random +0.05%, canada +4.0%, mesh +34.3% (c/f 55.7->41.4) Clang: random +4.9%, canada +2.8%, mesh +5.1% Correctness: 14/14 core+supplemental pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
7790aa6231
commit
8db9edbc18
@ -354,13 +354,36 @@ parse_number_string(UC const *p, UC const *pend,
|
|||||||
|
|
||||||
uint64_t i = 0; // an unsigned int avoids signed overflows (which are bad)
|
uint64_t i = 0; // an unsigned int avoids signed overflows (which are bad)
|
||||||
|
|
||||||
while ((p != pend) && is_integer(*p)) {
|
// Straight-line unroll of the integer-part scan: most integer parts are
|
||||||
// a multiplication by 10 is cheaper than an arbitrary integer
|
// 1-5 digits, so peeling the first iterations eliminates the loop back-edge
|
||||||
// multiplication
|
// for the common case (ported from ffc EXP-026/028). Semantics are identical
|
||||||
i = 10 * i +
|
// to the original `while` loop: i = 10*i + digit, advancing p.
|
||||||
uint64_t(*p -
|
if ((p != pend) && is_integer(*p)) {
|
||||||
UC('0')); // might overflow, we will handle the overflow later
|
i = uint64_t(*p - UC('0'));
|
||||||
++p;
|
++p;
|
||||||
|
if ((p != pend) && is_integer(*p)) {
|
||||||
|
i = 10 * i + uint64_t(*p - UC('0'));
|
||||||
|
++p;
|
||||||
|
if ((p != pend) && is_integer(*p)) {
|
||||||
|
i = 10 * i + uint64_t(*p - UC('0'));
|
||||||
|
++p;
|
||||||
|
if ((p != pend) && is_integer(*p)) {
|
||||||
|
i = 10 * i + uint64_t(*p - UC('0'));
|
||||||
|
++p;
|
||||||
|
if ((p != pend) && is_integer(*p)) {
|
||||||
|
i = 10 * i + uint64_t(*p - UC('0'));
|
||||||
|
++p;
|
||||||
|
while ((p != pend) && is_integer(*p)) {
|
||||||
|
// a multiplication by 10 is cheaper than an arbitrary integer
|
||||||
|
// multiplication
|
||||||
|
i = 10 * i +
|
||||||
|
uint64_t(*p - UC('0')); // might overflow, handled later
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
UC const *const end_of_integer_part = p;
|
UC const *const end_of_integer_part = p;
|
||||||
int64_t digit_count = int64_t(end_of_integer_part - start_digits);
|
int64_t digit_count = int64_t(end_of_integer_part - start_digits);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user