Skip to content

Commit 08108bf

Browse files
committed
Updating to fix some issues.
1 parent 3d83d19 commit 08108bf

File tree

2 files changed

+53
-36
lines changed

2 files changed

+53
-36
lines changed

include/fast_float/ascii_number.h

Lines changed: 47 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,9 @@ uint64_t simd_read8_to_u64(UC const *) {
118118
// credit @aqrit
119119
fastfloat_really_inline FASTFLOAT_CONSTEXPR14 uint32_t
120120
parse_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 &) {
209224
template <typename UC, FASTFLOAT_ENABLE_IF(!std::is_same<UC, char>::value) = 0>
210225
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void
211226
loop_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
223238
loop_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

include/fast_float/constexpr_feature_detect.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@
1414
#define FASTFLOAT_CONSTEXPR14
1515
#endif
1616

17+
#if __cplusplus >= 201703L
18+
#define FASTFLOAT_IF_CONSTEXPR if constexpr
19+
#else
20+
#define FASTFLOAT_IF_CONSTEXPR if
21+
#endif
22+
1723
#if defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806L
1824
#define FASTFLOAT_HAS_BIT_CAST 1
1925
#else

0 commit comments

Comments
 (0)