diff options
author | AlexSm <alex@ydb.tech> | 2024-01-04 15:09:05 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-01-04 15:09:05 +0100 |
commit | dab291146f6cd7d35684e3a1150e5bb1c412982c (patch) | |
tree | 36ef35f6cacb6432845a4a33f940c95871036b32 /contrib/restricted/fast_float | |
parent | 63660ad5e7512029fd0218e7a636580695a24e1f (diff) | |
download | ydb-dab291146f6cd7d35684e3a1150e5bb1c412982c.tar.gz |
Library import 5, delete go dependencies (#832)
* Library import 5, delete go dependencies
* Fix yt client
Diffstat (limited to 'contrib/restricted/fast_float')
6 files changed, 264 insertions, 22 deletions
diff --git a/contrib/restricted/fast_float/README.md b/contrib/restricted/fast_float/README.md index d2ad1d874b..79ebedbd72 100644 --- a/contrib/restricted/fast_float/README.md +++ b/contrib/restricted/fast_float/README.md @@ -1,21 +1,24 @@ ## fast_float number parsing library: 4x faster than strtod [](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:fast_float) -[](https://github.com/fastfloat/fast_float/actions/workflows/vs17-ci.yml) [](https://github.com/fastfloat/fast_float/actions/workflows/ubuntu22.yml) The fast_float library provides fast header-only implementations for the C++ from_chars -functions for `float` and `double` types. These functions convert ASCII strings representing -decimal values (e.g., `1.3e10`) into binary types. We provide exact rounding (including +functions for `float` and `double` types as well as integer types. These functions convert ASCII strings representing decimal values (e.g., `1.3e10`) into binary types. We provide exact rounding (including round to even). In our experience, these `fast_float` functions many times faster than comparable number-parsing functions from existing C++ standard libraries. -Specifically, `fast_float` provides the following two functions with a C++17-like syntax (the library itself only requires C++11): +Specifically, `fast_float` provides the following two functions to parse floating-point numbers with a C++17-like syntax (the library itself only requires C++11): ```C++ from_chars_result from_chars(const char* first, const char* last, float& value, ...); from_chars_result from_chars(const char* first, const char* last, double& value, ...); ``` +You can also parse integer types: + + + + The return type (`from_chars_result`) is defined as the struct: ```C++ struct from_chars_result { @@ -104,6 +107,43 @@ We support Visual Studio, macOS, Linux, freeBSD. We support big and little endia We assume that the rounding mode is set to nearest (`std::fegetround() == FE_TONEAREST`). + +## Integer types + +You can also parse integer types using different bases (e.g., 2, 10, 16). The following code will +print the number 22250738585072012 three times: + + +```C++ + uint64_t i; + const char str[] = "22250738585072012"; + auto answer = fast_float::from_chars(str, str + strlen(str), i); + if (answer.ec != std::errc()) { + std::cerr << "parsing failure\n"; + return EXIT_FAILURE; + } + std::cout << "parsed the number "<< i << std::endl; + + const char binstr[] = "1001111000011001110110111001001010110100111000110001100"; + + answer = fast_float::from_chars(binstr, binstr + strlen(binstr), i, 2); + if (answer.ec != std::errc()) { + std::cerr << "parsing failure\n"; + return EXIT_FAILURE; + } + std::cout << "parsed the number "<< i << std::endl; + + + const char hexstr[] = "4f0cedc95a718c"; + + answer = fast_float::from_chars(hexstr, hexstr + strlen(hexstr), i, 16); + if (answer.ec != std::errc()) { + std::cerr << "parsing failure\n"; + return EXIT_FAILURE; + } + std::cout << "parsed the number "<< i << std::endl; +``` + ## C++20: compile-time evaluation (constexpr) In C++20, you may use `fast_float::from_chars` to parse strings @@ -331,7 +371,7 @@ the command line help. You may directly download automatically generated single-header files: -https://github.com/fastfloat/fast_float/releases/download/v5.3.0/fast_float.h +https://github.com/fastfloat/fast_float/releases/download/v6.0.0/fast_float.h ## Credit diff --git a/contrib/restricted/fast_float/include/fast_float/ascii_number.h b/contrib/restricted/fast_float/include/fast_float/ascii_number.h index d18e3d5360..5d3eac9df5 100644 --- a/contrib/restricted/fast_float/include/fast_float/ascii_number.h +++ b/contrib/restricted/fast_float/include/fast_float/ascii_number.h @@ -5,6 +5,7 @@ #include <cstdint> #include <cstring> #include <iterator> +#include <limits> #include <type_traits> #include "float_common.h" @@ -115,7 +116,7 @@ FASTFLOAT_SIMD_RESTORE_WARNINGS #if defined(_MSC_VER) && _MSC_VER <= 1900 template <typename UC> #else -template <typename UC, FASTFLOAT_ENABLE_IF(!has_simd_opt<UC>())> +template <typename UC, FASTFLOAT_ENABLE_IF(!has_simd_opt<UC>()) = 0> #endif // dummy for compile uint64_t simd_read8_to_u64(UC const*) { @@ -223,7 +224,7 @@ FASTFLOAT_SIMD_RESTORE_WARNINGS #if defined(_MSC_VER) && _MSC_VER <= 1900 template <typename UC> #else -template <typename UC, FASTFLOAT_ENABLE_IF(!has_simd_opt<UC>())> +template <typename UC, FASTFLOAT_ENABLE_IF(!has_simd_opt<UC>()) = 0> #endif // dummy for compile bool simd_parse_if_eight_digits_unrolled(UC const*, uint64_t&) { @@ -231,7 +232,7 @@ bool simd_parse_if_eight_digits_unrolled(UC const*, uint64_t&) { } -template <typename UC, FASTFLOAT_ENABLE_IF(!std::is_same<UC, char>::value)> +template <typename UC, FASTFLOAT_ENABLE_IF(!std::is_same<UC, char>::value) = 0> fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void loop_parse_if_eight_digits(const UC*& p, const UC* const pend, uint64_t& i) { if (!has_simd_opt<UC>()) { @@ -439,6 +440,106 @@ parsed_number_string_t<UC> parse_number_string(UC const *p, UC const * pend, par return answer; } +template <typename T, typename UC> +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 +from_chars_result_t<UC> parse_int_string(UC const* p, UC const* pend, T& value, int base) +{ + from_chars_result_t<UC> answer; + + UC const* const first = p; + + bool negative = (*p == UC('-')); + if (!std::is_signed<T>::value && negative) { + answer.ec = std::errc::invalid_argument; + answer.ptr = first; + return answer; + } +#ifdef FASTFLOAT_ALLOWS_LEADING_PLUS // disabled by default + if ((*p == UC('-')) || (*p == UC('+'))) { +#else + if (*p == UC('-')) { +#endif + ++p; + } + + UC const* const start_num = p; + while (*p == UC('0')) { + ++p; + } + const bool has_leading_zeros = p > start_num; + + UC const* const start_digits = p; + + uint64_t i = 0; + if (base == 10) { + loop_parse_if_eight_digits(p, pend, i); // use SIMD if possible + } + while (p != pend) { + uint8_t digit = ch_to_digit(*p); + if (digit >= base) { + break; + } + i = uint64_t(base) * i + digit; // might overflow, check this later + p++; + } + + size_t digit_count = size_t(p - start_digits); + + if (digit_count == 0) { + if (has_leading_zeros) { + value = 0; + answer.ec = std::errc(); + answer.ptr = p; + } + else { + answer.ec = std::errc::invalid_argument; + answer.ptr = first; + } + return answer; + } + + answer.ptr = p; + + // check u64 overflow + size_t max_digits = max_digits_u64(base); + if (digit_count > max_digits) { + answer.ec = std::errc::result_out_of_range; + return answer; + } + // this check can be eliminated for all other types, but they will all require a max_digits(base) equivalent + if (digit_count == max_digits && i < min_safe_u64(base)) { + answer.ec = std::errc::result_out_of_range; + return answer; + } + + // check other types overflow + if (!std::is_same<T, uint64_t>::value) { + if (i > uint64_t(std::numeric_limits<T>::max()) + uint64_t(negative)) { + answer.ec = std::errc::result_out_of_range; + return answer; + } + } + + if (negative) { +#ifdef FASTFLOAT_VISUAL_STUDIO +#pragma warning(push) +#pragma warning(disable: 4146) +#endif + // this weird workaround is required because: + // - converting unsigned to signed when its value is greater than signed max is UB pre-C++23. + // - reinterpret_casting (~i + 1) would work, but it is not constexpr + // this is always optimized into a neg instruction. + value = T(-std::numeric_limits<T>::max() - T(i - std::numeric_limits<T>::max())); +#ifdef FASTFLOAT_VISUAL_STUDIO +#pragma warning(pop) +#endif + } + else { value = T(i); } + + answer.ec = std::errc(); + return answer; +} + } // namespace fast_float #endif diff --git a/contrib/restricted/fast_float/include/fast_float/fast_float.h b/contrib/restricted/fast_float/include/fast_float/fast_float.h index 04efa877ee..9b1b9b4ff4 100644 --- a/contrib/restricted/fast_float/include/fast_float/fast_float.h +++ b/contrib/restricted/fast_float/include/fast_float/fast_float.h @@ -24,7 +24,7 @@ namespace fast_float { * to determine whether we allow the fixed point and scientific notation respectively. * The default is `fast_float::chars_format::general` which allows both `fixed` and `scientific`. */ -template<typename T, typename UC = char> +template<typename T, typename UC = char, typename = FASTFLOAT_ENABLE_IF(is_supported_float_type<T>())> FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC> from_chars(UC const * first, UC const * last, T &value, chars_format fmt = chars_format::general) noexcept; @@ -36,6 +36,12 @@ template<typename T, typename UC = char> FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC> from_chars_advanced(UC const * first, UC const * last, T &value, parse_options_t<UC> options) noexcept; +/** +* from_chars for integer types. +*/ +template <typename T, typename UC = char, typename = FASTFLOAT_ENABLE_IF(!is_supported_float_type<T>())> +FASTFLOAT_CONSTEXPR20 +from_chars_result_t<UC> from_chars(UC const * first, UC const * last, T& value, int base = 10) noexcept; } // namespace fast_float #include "parse_number.h" diff --git a/contrib/restricted/fast_float/include/fast_float/float_common.h b/contrib/restricted/fast_float/include/fast_float/float_common.h index bee8821520..b5a357b124 100644 --- a/contrib/restricted/fast_float/include/fast_float/float_common.h +++ b/contrib/restricted/fast_float/include/fast_float/float_common.h @@ -134,7 +134,7 @@ using parse_options = parse_options_t<char>; #define FASTFLOAT_NEON 1 #endif -#if defined(FASTFLOAT_SSE2) || defined(FASTFLOAT_ARM64) +#if defined(FASTFLOAT_SSE2) || defined(FASTFLOAT_NEON) #define FASTFLOAT_HAS_SIMD 1 #endif @@ -173,7 +173,7 @@ using parse_options = parse_options_t<char>; // rust style `try!()` macro, or `?` operator #define FASTFLOAT_TRY(x) { if (!(x)) return false; } -#define FASTFLOAT_ENABLE_IF(...) typename std::enable_if<(__VA_ARGS__), int>::type = 0 +#define FASTFLOAT_ENABLE_IF(...) typename std::enable_if<(__VA_ARGS__), int>::type namespace fast_float { @@ -186,6 +186,20 @@ fastfloat_really_inline constexpr bool cpp20_and_in_constexpr() { #endif } +template <typename T> +fastfloat_really_inline constexpr bool is_supported_float_type() { + return std::is_same<T, float>::value || std::is_same<T, double>::value; +} + +template <typename UC> +fastfloat_really_inline constexpr bool is_supported_char_type() { + return + std::is_same<UC, char>::value || + std::is_same<UC, wchar_t>::value || + std::is_same<UC, char16_t>::value || + std::is_same<UC, char32_t>::value; +} + // Compares two ASCII strings in a case insensitive manner. template <typename UC> inline FASTFLOAT_CONSTEXPR14 bool @@ -234,7 +248,7 @@ int leading_zeroes_generic(uint64_t input_num, int last_bit = 0) { if(input_num & uint64_t( 0xff00)) { input_num >>= 8; last_bit |= 8; } if(input_num & uint64_t( 0xf0)) { input_num >>= 4; last_bit |= 4; } if(input_num & uint64_t( 0xc)) { input_num >>= 2; last_bit |= 2; } - if(input_num & uint64_t( 0x2)) { input_num >>= 1; last_bit |= 1; } + if(input_num & uint64_t( 0x2)) { /* input_num >>= 1; */ last_bit |= 1; } return 63 - last_bit; } @@ -674,6 +688,69 @@ constexpr char32_t const * str_const_inf<char32_t>() { return U"infinity"; } + + +template <typename = void> +struct int_luts { + 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, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255, + 255, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 255, 255, 255, 255, 255, + 255, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 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, 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, 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, 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, 255, 255, 255, 255, 255, 255, 255, 255, 255 + }; + + static constexpr size_t maxdigits_u64[] = { + 64, 41, 32, 28, 25, 23, 22, 21, + 20, 19, 18, 18, 17, 17, 16, 16, + 16, 16, 15, 15, 15, 15, 14, 14, + 14, 14, 14, 14, 14, 13, 13, 13, + 13, 13, 13 + }; + + static constexpr uint64_t min_safe_u64[] = { + 9223372036854775808ull, 12157665459056928801ull, 4611686018427387904, 7450580596923828125, 4738381338321616896, + 3909821048582988049, 9223372036854775808ull, 12157665459056928801ull, 10000000000000000000ull, 5559917313492231481, + 2218611106740436992, 8650415919381337933, 2177953337809371136, 6568408355712890625, 1152921504606846976, + 2862423051509815793, 6746640616477458432, 15181127029874798299ull, 1638400000000000000, 3243919932521508681, + 6221821273427820544, 11592836324538749809ull, 876488338465357824, 1490116119384765625, 2481152873203736576, + 4052555153018976267, 6502111422497947648, 10260628712958602189ull, 15943230000000000000ull, 787662783788549761, + 1152921504606846976, 1667889514952984961, 2386420683693101056, 3379220508056640625, 4738381338321616896 + }; +}; + +template <typename T> +constexpr uint8_t int_luts<T>::chdigit[]; + +template <typename T> +constexpr size_t int_luts<T>::maxdigits_u64[]; + +template <typename T> +constexpr uint64_t int_luts<T>::min_safe_u64[]; + +template <typename UC> +fastfloat_really_inline +constexpr uint8_t ch_to_digit(UC c) { return int_luts<>::chdigit[static_cast<unsigned char>(c)]; } + +fastfloat_really_inline +constexpr size_t max_digits_u64(int base) { return int_luts<>::maxdigits_u64[base - 2]; } + +// If a u64 is exactly max_digits_u64() in length, this is +// the value below which it has definitely overflowed. +fastfloat_really_inline +constexpr uint64_t min_safe_u64(int base) { return int_luts<>::min_safe_u64[base - 2]; } + } // namespace fast_float #endif diff --git a/contrib/restricted/fast_float/include/fast_float/parse_number.h b/contrib/restricted/fast_float/include/fast_float/parse_number.h index a011a8cbf4..1fd587bb9a 100644 --- a/contrib/restricted/fast_float/include/fast_float/parse_number.h +++ b/contrib/restricted/fast_float/include/fast_float/parse_number.h @@ -133,7 +133,7 @@ fastfloat_really_inline bool rounds_to_nearest() noexcept { } // namespace detail -template<typename T, typename UC> +template<typename T, typename UC, typename> FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC> from_chars(UC const * first, UC const * last, T &value, chars_format fmt /*= chars_format::general*/) noexcept { @@ -145,11 +145,8 @@ FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC> from_chars_advanced(UC const * first, UC const * last, T &value, parse_options_t<UC> options) noexcept { - static_assert (std::is_same<T, double>::value || std::is_same<T, float>::value, "only float and double are supported"); - static_assert (std::is_same<UC, char>::value || - std::is_same<UC, wchar_t>::value || - std::is_same<UC, char16_t>::value || - std::is_same<UC, char32_t>::value , "only char, wchar_t, char16_t and char32_t are supported"); + static_assert (is_supported_float_type<T>(), "only float and double are supported"); + static_assert (is_supported_char_type<UC>(), "only char, wchar_t, char16_t and char32_t are supported"); from_chars_result_t<UC> answer; #ifdef FASTFLOAT_SKIP_WHITE_SPACE // disabled by default @@ -202,10 +199,10 @@ from_chars_result_t<UC> from_chars_advanced(UC const * first, UC const * last, // We do not have that fegetround() == FE_TONEAREST. // Next is a modified Clinger's fast path, inspired by Jakub JelĂnek's proposal if (pns.exponent >= 0 && pns.mantissa <=binary_format<T>::max_mantissa_fast_path(pns.exponent)) { -#if defined(__clang__) +#if defined(__clang__) || defined(FASTFLOAT_32BIT) // Clang may map 0 to -0.0 when fegetround() == FE_DOWNWARD if(pns.mantissa == 0) { - value = pns.negative ? -0. : 0.; + value = pns.negative ? T(-0.) : T(0.); return answer; } #endif @@ -232,6 +229,27 @@ from_chars_result_t<UC> from_chars_advanced(UC const * first, UC const * last, return answer; } + +template <typename T, typename UC, typename> +FASTFLOAT_CONSTEXPR20 +from_chars_result_t<UC> from_chars(UC const* first, UC const* last, T& value, int base) noexcept +{ + static_assert (is_supported_char_type<UC>(), "only char, wchar_t, char16_t and char32_t are supported"); + + from_chars_result_t<UC> answer; +#ifdef FASTFLOAT_SKIP_WHITE_SPACE // disabled by default + while ((first != last) && fast_float::is_space(uint8_t(*first))) { + first++; + } +#endif + if (first == last || base < 2 || base > 36) { + answer.ec = std::errc::invalid_argument; + answer.ptr = first; + return answer; + } + return parse_int_string(first, last, value, base); +} + } // namespace fast_float #endif diff --git a/contrib/restricted/fast_float/ya.make b/contrib/restricted/fast_float/ya.make index dba751fb8a..acc85b8fc0 100644 --- a/contrib/restricted/fast_float/ya.make +++ b/contrib/restricted/fast_float/ya.make @@ -10,9 +10,9 @@ LICENSE( LICENSE_TEXTS(.yandex_meta/licenses.list.txt) -VERSION(5.3.0) +VERSION(6.0.0) -ORIGINAL_SOURCE(https://github.com/fastfloat/fast_float/archive/v5.3.0.tar.gz) +ORIGINAL_SOURCE(https://github.com/fastfloat/fast_float/archive/v6.0.0.tar.gz) NO_COMPILER_WARNINGS() |