@@ -118,9 +118,9 @@ uint64_t simd_read8_to_u64(UC const *) {
118118// credit @aqrit
119119fastfloat_really_inline FASTFLOAT_CONSTEXPR14 uint32_t
120120parse_eight_digits_unrolled (uint64_t val) {
121- uint64_t const mask = 0x000000FF000000FF ;
122- uint64_t const mul1 = 0x000F424000000064 ; // 100 + (1000000ULL << 32)
123- uint64_t const mul2 = 0x0000271000000001 ; // 1 + (10000ULL << 32)
121+ constexpr uint64_t mask = 0x000000FF000000FF ;
122+ constexpr uint64_t mul1 = 0x000F424000000064 ; // 100 + (1000000ULL << 32)
123+ constexpr uint64_t mul2 = 0x0000271000000001 ; // 1 + (10000ULL << 32)
124124 val -= 0x3030303030303030 ;
125125 val = (val * 10 ) + (val >> 8 ); // val = (val * 2561) >> 8;
126126 val = (((val & mask) * mul1) + (((val >> 16 ) & mask) * mul2)) >> 32 ;
@@ -144,6 +144,21 @@ is_made_of_eight_digits_fast(uint64_t val) noexcept {
144144 0x8080808080808080 ));
145145}
146146
147+ fastfloat_really_inline constexpr bool
148+ is_made_of_eight_digits_no_sub (uint64_t val) noexcept {
149+ return !((((val + 0x7676767676767676 ) | (val)) & 0x8080808080808080 ));
150+ }
151+
152+ fastfloat_really_inline FASTFLOAT_CONSTEXPR14 uint32_t
153+ parse_eight_digits_unrolled_no_sub (uint64_t val) {
154+ constexpr uint64_t mask = 0x000000FF000000FF ;
155+ constexpr uint64_t mul1 = 0x000F424000000064 ; // 100 + (1000000ULL << 32)
156+ constexpr uint64_t mul2 = 0x0000271000000001 ; // 1 + (10000ULL << 32)
157+ val = (val * 10 ) + (val >> 8 ); // val = (val * 2561) >> 8;
158+ val = (((val & mask) * mul1) + (((val >> 16 ) & mask) * mul2)) >> 32 ;
159+ return uint32_t (val);
160+ }
161+
147162#ifdef FASTFLOAT_HAS_SIMD
148163
149164// Call this if chars might not be 8 digits.
@@ -209,10 +224,10 @@ bool simd_parse_if_eight_digits_unrolled(UC const *, uint64_t &) {
209224template <typename UC, FASTFLOAT_ENABLE_IF(!std::is_same<UC, char >::value) = 0 >
210225fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void
211226loop_parse_if_eight_digits (UC const *&p, UC const *const pend, uint64_t &i) {
212- if (!has_simd_opt<UC>()) {
227+ FASTFLOAT_IF_CONSTEXPR (!has_simd_opt<UC>()) {
213228 return ;
214229 }
215- while ((std::distance (p, pend) >= 8 ) &&
230+ while ((( pend - p ) >= 8 ) &&
216231 simd_parse_if_eight_digits_unrolled (
217232 p, i)) { // in rare cases, this will overflow, but that's ok
218233 p += 8 ;
@@ -223,45 +238,34 @@ fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void
223238loop_parse_if_eight_digits (char const *&p, char const *const pend,
224239 uint64_t &i) {
225240 // optimizes better than parse_if_eight_digits_unrolled() for UC = char.
226- while ((std::distance (p, pend) >= 8 ) &&
227- is_made_of_eight_digits_fast (read8_to_u64 (p))) {
241+ while (((pend - p) >= 8 ) && is_made_of_eight_digits_fast (read8_to_u64 (p))) {
228242 i = i * 100000000 +
229243 parse_eight_digits_unrolled (read8_to_u64 (
230244 p)); // in rare cases, this will overflow, but that's ok
231245 p += 8 ;
232246 }
233247}
234248
235- // credit @realtimechris
236- fastfloat_really_inline constexpr bool
237- parse_if_eight_digits_unrolled (const char *&string, size_t &value) {
238- constexpr size_t byte_mask = ~size_t (0 ) / 255ull ;
239- constexpr size_t msb_mask = byte_mask * 128ull ;
240- constexpr size_t threshold_byte_mask = byte_mask * (127ull - 9ull );
241- constexpr size_t mask = 0x000000FF000000FFull ;
242- constexpr size_t mul1 = 0x000F424000000064ull ;
243- constexpr size_t mul2 = 0x0000271000000001ull ;
244- size_t value_new = read8_to_u64 (string) - 0x3030303030303030 ;
245- if (!(((value_new + threshold_byte_mask) | value_new) & msb_mask)) {
246- value_new = (value_new * 10 ) + (value_new >> 8 );
247- value =
248- value * 100000000 +
249- ((((value_new & mask) * mul1) + (((value_new >> 16 ) & mask) * mul2)) >>
250- 32 );
251- string += 8 ;
252- return true ;
249+ template <typename UC, FASTFLOAT_ENABLE_IF(!std::is_same<UC, char >::value) = 0 >
250+ fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void
251+ loop_parse_if_digits (UC const *&p, UC const *const pend, uint64_t &i) {
252+ FASTFLOAT_IF_CONSTEXPR (!has_simd_opt<UC>()) {
253+ return ;
254+ }
255+ while (((pend - p) >= 8 ) &&
256+ simd_parse_if_eight_digits_unrolled (
257+ p, i)) { // in rare cases, this will overflow, but that's ok
258+ p += 8 ;
253259 }
254- return false ;
255260}
256261
257- fastfloat_really_inline constexpr void
258- loop_parse_if_digits (const char *&p, const char *const pend,
259- size_t &i) noexcept {
260- while (pend - p >= 8 && parse_if_eight_digits_unrolled (p, i)) {
261- }
262- while (p < pend && is_integer (*p)) {
263- i = i * 10 + static_cast <uint8_t >(*p - ' 0' );
264- ++p;
262+ fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void
263+ loop_parse_if_digits (char const *&p, char const *const pend, uint64_t &i) {
264+ uint64_t val;
265+ while ((pend - p) >= 8 && (val = read8_to_u64 (p) - 0x3030303030303030 ,
266+ is_made_of_eight_digits_no_sub (val))) {
267+ i = i * 100000000 + parse_eight_digits_unrolled_no_sub (val);
268+ p += 8 ;
265269 }
266270}
267271
@@ -381,6 +385,13 @@ parse_number_string(UC const *p, UC const *pend,
381385 // can occur at most twice without overflowing, but let it occur more, since
382386 // for integers with many digits, digit parsing is the primary bottleneck.
383387 loop_parse_if_digits (p, pend, i);
388+
389+ while ((p != pend) && is_integer (*p)) {
390+ uint8_t digit = uint8_t (*p - UC (' 0' ));
391+ ++p;
392+ i = i * 10 + digit; // in rare cases, this will overflow, but that's ok
393+ }
394+
384395 exponent = before - p;
385396 answer.fraction = span<UC const >(before, size_t (p - before));
386397 digit_count -= exponent;
@@ -473,7 +484,7 @@ parse_number_string(UC const *p, UC const *pend,
473484 i = 0 ;
474485 p = answer.integer .ptr ;
475486 UC const *int_end = p + answer.integer .len ();
476- uint64_t const minimal_nineteen_digit_integer{1000000000000000000 };
487+ constexpr uint64_t minimal_nineteen_digit_integer{1000000000000000000 };
477488 while ((i < minimal_nineteen_digit_integer) && (p != int_end)) {
478489 i = i * 10 + uint64_t (*p - UC (' 0' ));
479490 ++p;
@@ -605,4 +616,4 @@ parse_int_string(UC const *p, UC const *pend, T &value,
605616
606617} // namespace fast_float
607618
608- #endif
619+ #endif
0 commit comments