diff --git a/README.md b/README.md index 6af9cf7..3746a6a 100644 --- a/README.md +++ b/README.md @@ -383,13 +383,15 @@ int main() { There is a really common use case in mathematical and other abstract syntax tree (AST)-like parsers that already processes the sign and all other symbols before any number by itself. In this case you can use FastFloat to only parse positive numbers in all supported formats with macros `FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN`, which significantly reduce the code size -and improve performance. You also can use macros `FASTFLOAT_ISNOT_CHECKED_BOUNDS` if your code already checks bounds; -it's very likely because all parsers need to check the first character by itself before parsing. Additionally, you can use -macros `FASTFLOAT_ONLY_ROUNDS_TO_NEAREST_SUPPORTED` if you only need `FE_TONEAREST` rounding mode in the parsing; -this option also improves performance a bit and reduces code size. - +and improve performance. An additional option for high performance and very fast processing is +`FASTFLOAT_TABLE_HACK_CHAR_DIGIT_LUT_DISABLED`; it reduces data size and speeds up parsing because a data cache is used for your +real data, not for a 256-byte table that flushes out at least 3 cache lines on x86. You also can use macros +`FASTFLOAT_ISNOT_CHECKED_BOUNDS` if your code already checks bounds; it's very likely because all parsers need to check the first +character by itself before parsing. Additionally, you can use macros `FASTFLOAT_ONLY_ROUNDS_TO_NEAREST_SUPPORTED` if you only need +`FE_TONEAREST` rounding mode in the parsing; this option also improves performance a bit and reduces code size. ```C++ #define FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN +#define FASTFLOAT_TABLE_HACK_CHAR_DIGIT_LUT_DISABLED #define FASTFLOAT_ISNOT_CHECKED_BOUNDS #define FASTFLOAT_ONLY_ROUNDS_TO_NEAREST_SUPPORTED #include "fast_float/fast_float.h" diff --git a/benchmarks/benchmark.cpp b/benchmarks/benchmark.cpp index 66a2fd8..030ebcc 100644 --- a/benchmarks/benchmark.cpp +++ b/benchmarks/benchmark.cpp @@ -1,5 +1,6 @@ // #define FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN +// #define FASTFLOAT_TABLE_HACK_CHAR_DIGIT_LUT_DISABLED // #define FASTFLOAT_ONLY_ROUNDS_TO_NEAREST_SUPPORTED // #define FASTFLOAT_ISNOT_CHECKED_BOUNDS @@ -234,6 +235,10 @@ int main(int argc, char **argv) { std::cout << "# FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN is enabled" << std::endl; #endif +#ifdef FASTFLOAT_TABLE_HACK_CHAR_DIGIT_LUT_DISABLED + std::cout << "# FASTFLOAT_TABLE_HACK_CHAR_DIGIT_LUT_DISABLED is enabled" + << std::endl; +#endif #ifdef FASTFLOAT_ONLY_ROUNDS_TO_NEAREST_SUPPORTED std::cout << "# FASTFLOAT_ONLY_ROUNDS_TO_NEAREST_SUPPORTED is enabled" << std::endl; diff --git a/include/fast_float/ascii_number.h b/include/fast_float/ascii_number.h index f77c516..7ff36ec 100644 --- a/include/fast_float/ascii_number.h +++ b/include/fast_float/ascii_number.h @@ -642,7 +642,14 @@ parse_int_string(UC const *p, UC const *pend, T &value, loop_parse_if_eight_digits(p, pend, i); // use SIMD if possible } while (p != pend) { +#ifdef FASTFLOAT_TABLE_HACK_CHAR_DIGIT_LUT_DISABLED + const auto digit = *p; + if (!is_integer(digit)) { + break; + } +#else auto const digit = ch_to_digit(*p); +#endif if (digit >= options.base) { break; } diff --git a/include/fast_float/float_common.h b/include/fast_float/float_common.h index 3d7f46a..b3393e0 100644 --- a/include/fast_float/float_common.h +++ b/include/fast_float/float_common.h @@ -513,7 +513,7 @@ typedef int_fast16_t am_pow_t; // Bias so we can get the real exponent with an invalid adjusted_mantissa. constexpr static am_pow_t invalid_am_bias = -0x8000; -struct adjusted_mantissa { +struct alignas(16) adjusted_mantissa { am_mant_t mantissa; am_pow_t power2; adjusted_mantissa() noexcept = default; @@ -1201,6 +1201,7 @@ template <> constexpr char8_t const *str_const_inf() { #endif template struct int_luts { +#ifndef FASTFLOAT_TABLE_HACK_CHAR_DIGIT_LUT_DISABLED static constexpr uint8_t chdigit[] = { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, @@ -1220,6 +1221,7 @@ template struct int_luts { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}; +#endif static constexpr uint_fast8_t maxdigits_u64[] = { 64, 41, 32, 28, 25, 23, 22, 21, 20, 19, 18, 18, 17, 17, 16, 16, 16, 16, @@ -1250,6 +1252,7 @@ template constexpr uint64_t int_luts::min_safe_u64[]; #endif +#ifndef FASTFLOAT_TABLE_HACK_CHAR_DIGIT_LUT_DISABLED template fastfloat_really_inline constexpr uint_fast8_t ch_to_digit(UC c) noexcept { // wchar_t and char can be signed, so we need to be careful. @@ -1259,6 +1262,7 @@ fastfloat_really_inline constexpr uint_fast8_t ch_to_digit(UC c) noexcept { static_cast( -((static_cast(c) & ~0xFFull) == 0)))]; } +#endif fastfloat_really_inline constexpr uint_fast8_t max_digits_u64(uint_fast8_t base) noexcept {