From 784cd670c3bb50162ed8ccdd17e7bc9a43af2b90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Mar=C3=ADn?= Date: Thu, 24 Sep 2026 19:09:51 +0200 Subject: [PATCH] Parse the integer part with one subtraction per digit As in the fraction tail and the exponent: clang computed the digit twice, once for the test and once for the value. Co-Authored-By: Claude Opus 5.5 (1M context) --- include/fast_float/ascii_number.h | 33 ++++++++++++++++++------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/include/fast_float/ascii_number.h b/include/fast_float/ascii_number.h index 6636379..82da77c 100644 --- a/include/fast_float/ascii_number.h +++ b/include/fast_float/ascii_number.h @@ -475,27 +475,32 @@ parse_number_string_impl(UC const *p, UC const *pend, // Straight-line unroll of the integer-part scan: most integer parts are // 1-5 digits, so peeling the first iterations eliminates the loop back-edge // for the common case. Semantics are identical to the original `while` loop: - // i = 10*i + digit, advancing p. - if ((p != pend) && is_integer(*p)) { - i = uint64_t(*p - UC('0')); + // i = 10*i + int_digit, advancing p. Each int_digit is tested and used + // through one subtraction, as in the fraction tail (clang otherwise computes + // it twice). + uint64_t int_digit; + if ((p != pend) && (int_digit = uint64_t(*p) - uint64_t(UC('0'))) <= 9) { + i = int_digit; ++p; - if ((p != pend) && is_integer(*p)) { - i = 10 * i + uint64_t(*p - UC('0')); + if ((p != pend) && (int_digit = uint64_t(*p) - uint64_t(UC('0'))) <= 9) { + i = 10 * i + int_digit; ++p; - if ((p != pend) && is_integer(*p)) { - i = 10 * i + uint64_t(*p - UC('0')); + if ((p != pend) && (int_digit = uint64_t(*p) - uint64_t(UC('0'))) <= 9) { + i = 10 * i + int_digit; ++p; - if ((p != pend) && is_integer(*p)) { - i = 10 * i + uint64_t(*p - UC('0')); + if ((p != pend) && + (int_digit = uint64_t(*p) - uint64_t(UC('0'))) <= 9) { + i = 10 * i + int_digit; ++p; - if ((p != pend) && is_integer(*p)) { - i = 10 * i + uint64_t(*p - UC('0')); + if ((p != pend) && + (int_digit = uint64_t(*p) - uint64_t(UC('0'))) <= 9) { + i = 10 * i + int_digit; ++p; - while ((p != pend) && is_integer(*p)) { + while ((p != pend) && + (int_digit = uint64_t(*p) - uint64_t(UC('0'))) <= 9) { // a multiplication by 10 is cheaper than an arbitrary integer // multiplication - i = 10 * i + - uint64_t(*p - UC('0')); // might overflow, handled later + i = 10 * i + int_digit; // might overflow, handled later ++p; } }