diff options
author | robot-contrib <robot-contrib@yandex-team.com> | 2025-02-21 09:30:59 +0300 |
---|---|---|
committer | robot-contrib <robot-contrib@yandex-team.com> | 2025-02-21 09:48:00 +0300 |
commit | 669b571d35b21a81c584e96ef225e8decb190e8e (patch) | |
tree | ad9ab84115aeb16f7209f2f471d5546e2b768758 /contrib | |
parent | 6439b5a3fc32966be75de7839c2ca04246448589 (diff) | |
download | ydb-669b571d35b21a81c584e96ef225e8decb190e8e.tar.gz |
Update contrib/restricted/fast_float to 8.0.0
commit_hash:65d9b3d669fb4794d962c6233c5fe43eb098bb9d
Diffstat (limited to 'contrib')
12 files changed, 609 insertions, 174 deletions
diff --git a/contrib/restricted/fast_float/.yandex_meta/devtools.licenses.report b/contrib/restricted/fast_float/.yandex_meta/devtools.licenses.report index 8abcfe786e..2463628607 100644 --- a/contrib/restricted/fast_float/.yandex_meta/devtools.licenses.report +++ b/contrib/restricted/fast_float/.yandex_meta/devtools.licenses.report @@ -39,7 +39,7 @@ BELONGS ya.make Match type : TAG Links : http://opensource.org/licenses/mit-license.php, https://spdx.org/licenses/MIT Files with this license: - README.md [513:513] + README.md [535:535] KEEP BSL-1.0 2c7a3fa82e66676005cd4ee2608fd7d2 BELONGS ya.make @@ -76,7 +76,20 @@ FILE_INCLUDE AUTHORS found in files: LICENSE-MIT at line 23 Files with this license: LICENSE-MIT [5:27] -KEEP Apache-2.0 AND MIT 5eed35bbf652e4d32c909d95331a0c79 +KEEP Apache-2.0 79f65f9f30b137f9b03d455de6cfdac9 +BELONGS ya.make + License text: + Licensed under either of <a href="LICENSE-APACHE">Apache License, Version + 2.0</a> or <a href="LICENSE-MIT">MIT license</a> or <a + Scancode info: + Original SPDX id: Apache-2.0 + Score : 100.00 + Match type : REFERENCE + Links : http://www.apache.org/licenses/, http://www.apache.org/licenses/LICENSE-2.0, https://spdx.org/licenses/Apache-2.0 + Files with this license: + README.md [534:535] + +KEEP Apache-2.0 AND MIT a76785199b4beee1ba8a8173f3d43241 BELONGS ya.make Note: matched license text is too long. Read it in the source files. Scancode info: @@ -85,27 +98,14 @@ BELONGS ya.make Match type : NOTICE Links : http://www.apache.org/licenses/, http://www.apache.org/licenses/LICENSE-2.0, https://spdx.org/licenses/Apache-2.0 Files with this license: - README.md [507:520] + README.md [529:544] Scancode info: Original SPDX id: MIT Score : 49.30 Match type : NOTICE Links : http://opensource.org/licenses/mit-license.php, https://spdx.org/licenses/MIT Files with this license: - README.md [507:520] - -KEEP Apache-2.0 79f65f9f30b137f9b03d455de6cfdac9 -BELONGS ya.make - License text: - Licensed under either of <a href="LICENSE-APACHE">Apache License, Version - 2.0</a> or <a href="LICENSE-MIT">MIT license</a> or <a - Scancode info: - Original SPDX id: Apache-2.0 - Score : 100.00 - Match type : REFERENCE - Links : http://www.apache.org/licenses/, http://www.apache.org/licenses/LICENSE-2.0, https://spdx.org/licenses/Apache-2.0 - Files with this license: - README.md [512:513] + README.md [529:544] KEEP BSL-1.0 AND BSL-1.0 a8fd7a0ddc7793219e50dfdeb4742dfc BELONGS ya.make @@ -117,14 +117,14 @@ BELONGS ya.make Match type : REFERENCE Links : http://www.boost.org/LICENSE_1_0.txt, http://www.boost.org/users/license.html, https://spdx.org/licenses/BSL-1.0 Files with this license: - README.md [514:514] + README.md [536:536] Scancode info: Original SPDX id: BSL-1.0 Score : 99.00 Match type : REFERENCE Links : http://www.boost.org/LICENSE_1_0.txt, http://www.boost.org/users/license.html, https://spdx.org/licenses/BSL-1.0 Files with this license: - README.md [514:514] + README.md [536:536] KEEP Apache-2.0 c48d93dbb5419f7a8844879928a2fda7 BELONGS ya.make @@ -136,7 +136,7 @@ BELONGS ya.make Match type : NOTICE Links : http://www.apache.org/licenses/, http://www.apache.org/licenses/LICENSE-2.0, https://spdx.org/licenses/Apache-2.0 Files with this license: - README.md [507:507] + README.md [529:529] KEEP Apache-2.0 OR MIT OR BSL-1.0 dbfbb7aa50e4925e728f16d4a8adf7d9 BELONGS ya.make @@ -148,14 +148,14 @@ BELONGS ya.make Match type : INTRO Links : https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/licenses/unknown-license-reference.LICENSE Files with this license: - README.md [512:512] + README.md [534:534] Scancode info: Original SPDX id: Apache-2.0 Score : 90.00 Match type : TAG Links : http://www.apache.org/licenses/, http://www.apache.org/licenses/LICENSE-2.0, https://spdx.org/licenses/Apache-2.0 Files with this license: - README.md [512:512] + README.md [534:534] KEEP Apache-2.0 fb21a7d67961597593aefff800484f8d BELONGS ya.make diff --git a/contrib/restricted/fast_float/.yandex_meta/licenses.list.txt b/contrib/restricted/fast_float/.yandex_meta/licenses.list.txt index f59f716d84..9053f2a746 100644 --- a/contrib/restricted/fast_float/.yandex_meta/licenses.list.txt +++ b/contrib/restricted/fast_float/.yandex_meta/licenses.list.txt @@ -210,6 +210,8 @@ Licensed under either of <a href="LICENSE-APACHE">Apache License, Version href="LICENSE-BOOST">BOOST license</a>. </sup> +<br/> + <sub> Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this repository by you, as defined in the Apache-2.0 license, diff --git a/contrib/restricted/fast_float/.yandex_meta/override.nix b/contrib/restricted/fast_float/.yandex_meta/override.nix index c919ea16d6..7d5281172d 100644 --- a/contrib/restricted/fast_float/.yandex_meta/override.nix +++ b/contrib/restricted/fast_float/.yandex_meta/override.nix @@ -1,11 +1,11 @@ self: super: with self; rec { name = "fast_float"; - version = "7.0.0"; + version = "8.0.0"; src = fetchFromGitHub { owner = "fastfloat"; repo = "fast_float"; rev = "v${version}"; - hash = "sha256-CG5je117WYyemTe5PTqznDP0bvY5TeXn8Vu1Xh5yUzQ="; + hash = "sha256-shP+me3iqTRrsPGYrvcbnJNRZouQbW62T24xfkEgGSE="; }; } diff --git a/contrib/restricted/fast_float/README.md b/contrib/restricted/fast_float/README.md index bf8c3e3e59..3eb540b7b6 100644 --- a/contrib/restricted/fast_float/README.md +++ b/contrib/restricted/fast_float/README.md @@ -1,7 +1,6 @@ ## 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/ubuntu22.yml) The fast_float library provides fast header-only implementations for the C++ @@ -16,22 +15,22 @@ 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, ...); +from_chars_result from_chars(char const *first, char const *last, float &value, ...); +from_chars_result from_chars(char const *first, char const *last, double &value, ...); ``` You can also parse integer types: ```C++ -from_chars_result from_chars(const char* first, const char* last, int& value, ...); -from_chars_result from_chars(const char* first, const char* last, unsigned& value, ...); +from_chars_result from_chars(char const *first, char const *last, int &value, ...); +from_chars_result from_chars(char const *first, char const *last, unsigned &value, ...); ``` The return type (`from_chars_result`) is defined as the struct: ```C++ struct from_chars_result { - const char* ptr; + char const *ptr; std::errc ec; }; ``` @@ -60,7 +59,7 @@ Example: #include <iostream> int main() { - const std::string input = "3.1416 xyz "; + std::string input = "3.1416 xyz "; double result; auto answer = fast_float::from_chars(input.data(), input.data() + input.size(), result); if (answer.ec != std::errc()) { std::cerr << "parsing failure\n"; return EXIT_FAILURE; } @@ -72,7 +71,7 @@ int main() { You can parse delimited numbers: ```C++ - const std::string input = "234532.3426362,7869234.9823,324562.645"; + std::string input = "234532.3426362,7869234.9823,324562.645"; double result; auto answer = fast_float::from_chars(input.data(), input.data() + input.size(), result); if (answer.ec != std::errc()) { @@ -108,9 +107,9 @@ The library seeks to follow the C++17 (see [28.2.3.(6.1)](https://eel.is/c++draft/charconv.from.chars#6.1)) specification. * The `from_chars` function does not skip leading white-space characters (unless - `fast_float::chars_format::chars_format` is set). + `fast_float::chars_format::skip_white_space` is set). * [A leading `+` sign](https://en.cppreference.com/w/cpp/utility/from_chars) is - forbidden (unless `fast_float::chars_format::skip_white_space` is set). + forbidden (unless `fast_float::chars_format::allow_leading_plus` is set). * It is generally impossible to represent a decimal value exactly as binary floating-point number (`float` and `double` types). We seek the nearest value. We round to an even mantissa when we are in-between two binary floating-point @@ -119,8 +118,8 @@ The library seeks to follow the C++17 (see Furthermore, we have the following restrictions: * We support `float` and `double`, but not `long double`. We also support - fixed-width floating-point types such as `std::float32_t` and - `std::float64_t`. + fixed-width floating-point types such as `std::float64_t`, `std::float32_t`, + `std::float16_t`, and `std::bfloat16_t`. * We only support the decimal format: we do not support hexadecimal strings. * For values that are either very large or very small (e.g., `1e9999`), we represent it using the infinity or negative infinity value and the returned @@ -143,31 +142,31 @@ following code will print the number 22250738585072012 three times: int main() { uint64_t i; - const char str[] = "22250738585072012"; - auto answer = fast_float::from_chars(str, str + strlen(str), i); + std::string str = "22250738585072012"; + auto answer = fast_float::from_chars(str.data(), str.data() + str.size(), i); if (answer.ec != std::errc()) { std::cerr << "parsing failure\n"; return EXIT_FAILURE; } - std::cout << "parsed the number "<< i << std::endl; + std::cout << "parsed the number " << i << std::endl; - const char binstr[] = "1001111000011001110110111001001010110100111000110001100"; + std::string binstr = "1001111000011001110110111001001010110100111000110001100"; - answer = fast_float::from_chars(binstr, binstr + strlen(binstr), i, 2); + answer = fast_float::from_chars(binstr.data(), binstr.data() + binstr.size(), i, 2); if (answer.ec != std::errc()) { std::cerr << "parsing failure\n"; return EXIT_FAILURE; } - std::cout << "parsed the number "<< i << std::endl; + std::cout << "parsed the number " << i << std::endl; - const char hexstr[] = "4f0cedc95a718c"; + std::string hexstr = "4f0cedc95a718c"; - answer = fast_float::from_chars(hexstr, hexstr + strlen(hexstr), i, 16); + answer = fast_float::from_chars(hexstr.data(), hexstr.data() + hexstr.size(), i, 16); if (answer.ec != std::errc()) { std::cerr << "parsing failure\n"; return EXIT_FAILURE; } - std::cout << "parsed the number "<< i << std::endl; + std::cout << "parsed the number " << i << std::endl; return EXIT_SUCCESS; } ``` @@ -242,7 +241,8 @@ constexpr double constexptest() { ## C++23: Fixed width floating-point types The library also supports fixed-width floating-point types such as -`std::float32_t` and `std::float64_t`. E.g., you can write: +`std::float64_t`, `std::float32_t`, `std::float16_t`, and `std::bfloat16_t`. +E.g., you can write: ```C++ std::float32_t result; @@ -259,7 +259,7 @@ following example: #include <iostream> int main() { - const std::u16string input = u"3.1416 xyz "; + std::u16string input = u"3.1416 xyz "; double result; auto answer = fast_float::from_chars(input.data(), input.data() + input.size(), result); if (answer.ec != std::errc()) { std::cerr << "parsing failure\n"; return EXIT_FAILURE; } @@ -282,7 +282,7 @@ separator (e.g., the comma). You may use it as follows. #include <iostream> int main() { - const std::string input = "3,1416 xyz "; + std::string input = "3,1416 xyz "; double result; fast_float::parse_options options{fast_float::chars_format::general, ','}; auto answer = fast_float::from_chars_advanced(input.data(), input.data() + input.size(), result, options); @@ -299,9 +299,9 @@ int main() { #include <iostream> int main() { - const std::string input = "1d+4"; + std::string input = "1d+4"; double result; - fast_float::parse_options options{ fast_float::chars_format::fortran }; + fast_float::parse_options options{fast_float::chars_format::fortran}; auto answer = fast_float::from_chars_advanced(input.data(), input.data() + input.size(), result, options); if ((answer.ec != std::errc()) || ((result != 10000))) { std::cerr << "parsing failure\n"; return EXIT_FAILURE; } std::cout << "parsed the number " << result << std::endl; @@ -316,9 +316,9 @@ int main() { #include <iostream> int main() { - const std::string input = "+.1"; // not valid + std::string input = "+.1"; // not valid double result; - fast_float::parse_options options{ fast_float::chars_format::json }; + fast_float::parse_options options{fast_float::chars_format::json}; auto answer = fast_float::from_chars_advanced(input.data(), input.data() + input.size(), result, options); if (answer.ec == std::errc()) { std::cerr << "should have failed\n"; return EXIT_FAILURE; } return EXIT_SUCCESS; @@ -332,9 +332,9 @@ By default the JSON format does not allow `inf`: #include <iostream> int main() { - const std::string input = "inf"; // not valid in JSON + std::string input = "inf"; // not valid in JSON double result; - fast_float::parse_options options{ fast_float::chars_format::json }; + fast_float::parse_options options{fast_float::chars_format::json}; auto answer = fast_float::from_chars_advanced(input.data(), input.data() + input.size(), result, options); if (answer.ec == std::errc()) { std::cerr << "should have failed\n"; return EXIT_FAILURE; } return EXIT_SUCCESS; @@ -348,9 +348,9 @@ You can allow it with a non-standard `json_or_infnan` variant: #include <iostream> int main() { - const std::string input = "inf"; // not valid in JSON but we allow it with json_or_infnan + std::string input = "inf"; // not valid in JSON but we allow it with json_or_infnan double result; - fast_float::parse_options options{ fast_float::chars_format::json_or_infnan }; + fast_float::parse_options options{fast_float::chars_format::json_or_infnan}; auto answer = fast_float::from_chars_advanced(input.data(), input.data() + input.size(), result, options); if (answer.ec != std::errc() || (!std::isinf(result))) { std::cerr << "should have parsed infinity\n"; return EXIT_FAILURE; } return EXIT_SUCCESS; @@ -367,7 +367,7 @@ The fast_float library is part of: * [WebKit](https://github.com/WebKit/WebKit), the engine behind Safari (Apple's web browser), * [DuckDB](https://duckdb.org), -* [Redis](https://github.com/redis/redis), +* [Redis](https://github.com/redis/redis) and [Valkey](https://github.com/valkey-io/valkey), * [Apache Arrow](https://github.com/apache/arrow/pull/8494) where it multiplied the number parsing speed by two or three times, * [Google Jsonnet](https://github.com/google/jsonnet), @@ -429,8 +429,7 @@ abseil : 430.45 MB/s (+/- 2.2 %) 20.52 Mfl fastfloat : 1042.38 MB/s (+/- 9.9 %) 49.68 Mfloat/s ``` -See <https://github.com/lemire/simple_fastfloat_benchmark> for our benchmarking -code. +See the [Benchmarking](#benchmarking) Section for instructions on how to run our benchmarks. ## Video @@ -456,7 +455,7 @@ sufficiently recent version of CMake (3.11 or better at least): FetchContent_Declare( fast_float GIT_REPOSITORY https://github.com/fastfloat/fast_float.git - GIT_TAG tags/v6.1.6 + GIT_TAG tags/v8.0.0 GIT_SHALLOW TRUE) FetchContent_MakeAvailable(fast_float) @@ -472,7 +471,7 @@ You may also use [CPM](https://github.com/cpm-cmake/CPM.cmake), like so: CPMAddPackage( NAME fast_float GITHUB_REPOSITORY "fastfloat/fast_float" - GIT_TAG v6.1.6) + GIT_TAG v8.0.0) ``` ## Using as single header @@ -484,7 +483,30 @@ if desired as described in the command line help. You may directly download automatically generated single-header files: -<https://github.com/fastfloat/fast_float/releases/download/v7.0.0/fast_float.h> +<https://github.com/fastfloat/fast_float/releases/download/v8.0.0/fast_float.h> + +## Benchmarking + +The project has its own benchmarks with realistic data inputs. Under Linux or macOS, +you can use it as follows if your system supports C++17: + +``` +cmake -B build -D FASTFLOAT_BENCHMARKS=ON +cmake --build build +./build/benchmarks/realbenchmark +``` + +Importantly, by default, the benchmark is built in Release mode. + +The instructions are similar under Windows. + +Under Linux and macOS, it is recommended to run the benchmarks in a privileged manner to get access +to hardware performance counters. You may be able to do so with the `sudo` command +in some cases: + +``` +sudo ./build/benchmarks/realbenchmark +``` ## Packages @@ -514,6 +536,8 @@ Licensed under either of <a href="LICENSE-APACHE">Apache License, Version href="LICENSE-BOOST">BOOST license</a>. </sup> +<br/> + <sub> Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this repository by you, as defined in the Apache-2.0 license, 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 f2484e8486..9001016ac6 100644 --- a/contrib/restricted/fast_float/include/fast_float/ascii_number.h +++ b/contrib/restricted/fast_float/include/fast_float/ascii_number.h @@ -45,7 +45,7 @@ fastfloat_really_inline constexpr uint64_t byteswap(uint64_t val) { // Read 8 UC into a u64. Truncates UC if not char. template <typename UC> fastfloat_really_inline FASTFLOAT_CONSTEXPR20 uint64_t -read8_to_u64(const UC *chars) { +read8_to_u64(UC const *chars) { if (cpp20_and_in_constexpr() || !std::is_same<UC, char>::value) { uint64_t val = 0; for (int i = 0; i < 8; ++i) { @@ -65,9 +65,9 @@ read8_to_u64(const UC *chars) { #ifdef FASTFLOAT_SSE2 -fastfloat_really_inline uint64_t simd_read8_to_u64(const __m128i data) { +fastfloat_really_inline uint64_t simd_read8_to_u64(__m128i const data) { FASTFLOAT_SIMD_DISABLE_WARNINGS - const __m128i packed = _mm_packus_epi16(data, data); + __m128i const packed = _mm_packus_epi16(data, data); #ifdef FASTFLOAT_64BIT return uint64_t(_mm_cvtsi128_si64(packed)); #else @@ -79,26 +79,26 @@ fastfloat_really_inline uint64_t simd_read8_to_u64(const __m128i data) { FASTFLOAT_SIMD_RESTORE_WARNINGS } -fastfloat_really_inline uint64_t simd_read8_to_u64(const char16_t *chars) { +fastfloat_really_inline uint64_t simd_read8_to_u64(char16_t const *chars) { FASTFLOAT_SIMD_DISABLE_WARNINGS return simd_read8_to_u64( - _mm_loadu_si128(reinterpret_cast<const __m128i *>(chars))); + _mm_loadu_si128(reinterpret_cast<__m128i const *>(chars))); FASTFLOAT_SIMD_RESTORE_WARNINGS } #elif defined(FASTFLOAT_NEON) -fastfloat_really_inline uint64_t simd_read8_to_u64(const uint16x8_t data) { +fastfloat_really_inline uint64_t simd_read8_to_u64(uint16x8_t const data) { FASTFLOAT_SIMD_DISABLE_WARNINGS uint8x8_t utf8_packed = vmovn_u16(data); return vget_lane_u64(vreinterpret_u64_u8(utf8_packed), 0); FASTFLOAT_SIMD_RESTORE_WARNINGS } -fastfloat_really_inline uint64_t simd_read8_to_u64(const char16_t *chars) { +fastfloat_really_inline uint64_t simd_read8_to_u64(char16_t const *chars) { FASTFLOAT_SIMD_DISABLE_WARNINGS return simd_read8_to_u64( - vld1q_u16(reinterpret_cast<const uint16_t *>(chars))); + vld1q_u16(reinterpret_cast<uint16_t const *>(chars))); FASTFLOAT_SIMD_RESTORE_WARNINGS } @@ -118,9 +118,9 @@ uint64_t simd_read8_to_u64(UC const *) { // credit @aqrit fastfloat_really_inline FASTFLOAT_CONSTEXPR14 uint32_t parse_eight_digits_unrolled(uint64_t val) { - const uint64_t mask = 0x000000FF000000FF; - const uint64_t mul1 = 0x000F424000000064; // 100 + (1000000ULL << 32) - const uint64_t mul2 = 0x0000271000000001; // 1 + (10000ULL << 32) + uint64_t const mask = 0x000000FF000000FF; + uint64_t const mul1 = 0x000F424000000064; // 100 + (1000000ULL << 32) + uint64_t const mul2 = 0x0000271000000001; // 1 + (10000ULL << 32) val -= 0x3030303030303030; val = (val * 10) + (val >> 8); // val = (val * 2561) >> 8; val = (((val & mask) * mul1) + (((val >> 16) & mask) * mul2)) >> 32; @@ -150,20 +150,20 @@ is_made_of_eight_digits_fast(uint64_t val) noexcept { // Using this style (instead of is_made_of_eight_digits_fast() then // parse_eight_digits_unrolled()) ensures we don't load SIMD registers twice. fastfloat_really_inline FASTFLOAT_CONSTEXPR20 bool -simd_parse_if_eight_digits_unrolled(const char16_t *chars, +simd_parse_if_eight_digits_unrolled(char16_t const *chars, uint64_t &i) noexcept { if (cpp20_and_in_constexpr()) { return false; } #ifdef FASTFLOAT_SSE2 FASTFLOAT_SIMD_DISABLE_WARNINGS - const __m128i data = - _mm_loadu_si128(reinterpret_cast<const __m128i *>(chars)); + __m128i const data = + _mm_loadu_si128(reinterpret_cast<__m128i const *>(chars)); // (x - '0') <= 9 // http://0x80.pl/articles/simd-parsing-int-sequences.html - const __m128i t0 = _mm_add_epi16(data, _mm_set1_epi16(32720)); - const __m128i t1 = _mm_cmpgt_epi16(t0, _mm_set1_epi16(-32759)); + __m128i const t0 = _mm_add_epi16(data, _mm_set1_epi16(32720)); + __m128i const t1 = _mm_cmpgt_epi16(t0, _mm_set1_epi16(-32759)); if (_mm_movemask_epi8(t1) == 0) { i = i * 100000000 + parse_eight_digits_unrolled(simd_read8_to_u64(data)); @@ -173,12 +173,12 @@ simd_parse_if_eight_digits_unrolled(const char16_t *chars, FASTFLOAT_SIMD_RESTORE_WARNINGS #elif defined(FASTFLOAT_NEON) FASTFLOAT_SIMD_DISABLE_WARNINGS - const uint16x8_t data = vld1q_u16(reinterpret_cast<const uint16_t *>(chars)); + uint16x8_t const data = vld1q_u16(reinterpret_cast<uint16_t const *>(chars)); // (x - '0') <= 9 // http://0x80.pl/articles/simd-parsing-int-sequences.html - const uint16x8_t t0 = vsubq_u16(data, vmovq_n_u16('0')); - const uint16x8_t mask = vcltq_u16(t0, vmovq_n_u16('9' - '0' + 1)); + uint16x8_t const t0 = vsubq_u16(data, vmovq_n_u16('0')); + uint16x8_t const mask = vcltq_u16(t0, vmovq_n_u16('9' - '0' + 1)); if (vminvq_u16(mask) == 0xFFFF) { i = i * 100000000 + parse_eight_digits_unrolled(simd_read8_to_u64(data)); @@ -208,7 +208,7 @@ bool simd_parse_if_eight_digits_unrolled(UC const *, uint64_t &) { 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) { +loop_parse_if_eight_digits(UC const *&p, UC const *const pend, uint64_t &i) { if (!has_simd_opt<UC>()) { return; } @@ -220,7 +220,7 @@ loop_parse_if_eight_digits(const UC *&p, const UC *const pend, uint64_t &i) { } fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void -loop_parse_if_eight_digits(const char *&p, const char *const pend, +loop_parse_if_eight_digits(char const *&p, char const *const pend, uint64_t &i) { // optimizes better than parse_if_eight_digits_unrolled() for UC = char. while ((std::distance(p, pend) >= 8) && @@ -259,12 +259,12 @@ template <typename UC> struct parsed_number_string_t { bool valid{false}; bool too_many_digits{false}; // contains the range of the significant digits - span<const UC> integer{}; // non-nullable - span<const UC> fraction{}; // nullable + span<UC const> integer{}; // non-nullable + span<UC const> fraction{}; // nullable parse_error error{parse_error::no_error}; }; -using byte_span = span<const char>; +using byte_span = span<char const>; using parsed_number_string = parsed_number_string_t<char>; template <typename UC> @@ -328,7 +328,7 @@ parse_number_string(UC const *p, UC const *pend, } UC const *const end_of_integer_part = p; int64_t digit_count = int64_t(end_of_integer_part - start_digits); - answer.integer = span<const UC>(start_digits, size_t(digit_count)); + answer.integer = span<UC const>(start_digits, size_t(digit_count)); if (uint64_t(fmt & detail::basic_json_fmt)) { // at least 1 digit in integer part, without leading zeros if (digit_count == 0) { @@ -341,7 +341,7 @@ parse_number_string(UC const *p, UC const *pend, } int64_t exponent = 0; - const bool has_decimal_point = (p != pend) && (*p == decimal_point); + bool const has_decimal_point = (p != pend) && (*p == decimal_point); if (has_decimal_point) { ++p; UC const *before = p; @@ -355,7 +355,7 @@ parse_number_string(UC const *p, UC const *pend, i = i * 10 + digit; // in rare cases, this will overflow, but that's ok } exponent = before - p; - answer.fraction = span<const UC>(before, size_t(p - before)); + answer.fraction = span<UC const>(before, size_t(p - before)); digit_count -= exponent; } if (uint64_t(fmt & detail::basic_json_fmt)) { @@ -446,7 +446,7 @@ parse_number_string(UC const *p, UC const *pend, i = 0; p = answer.integer.ptr; UC const *int_end = p + answer.integer.len(); - const uint64_t minimal_nineteen_digit_integer{1000000000000000000}; + uint64_t const minimal_nineteen_digit_integer{1000000000000000000}; while ((i < minimal_nineteen_digit_integer) && (p != int_end)) { i = i * 10 + uint64_t(*p - UC('0')); ++p; @@ -482,7 +482,14 @@ parse_int_string(UC const *p, UC const *pend, T &value, UC const *const first = p; bool const negative = (*p == UC('-')); +#ifdef FASTFLOAT_VISUAL_STUDIO +#pragma warning(push) +#pragma warning(disable : 4127) +#endif if (!std::is_signed<T>::value && negative) { +#ifdef FASTFLOAT_VISUAL_STUDIO +#pragma warning(pop) +#endif answer.ec = std::errc::invalid_argument; answer.ptr = first; return answer; @@ -498,7 +505,7 @@ parse_int_string(UC const *p, UC const *pend, T &value, ++p; } - const bool has_leading_zeros = p > start_num; + bool const has_leading_zeros = p > start_num; UC const *const start_digits = p; diff --git a/contrib/restricted/fast_float/include/fast_float/bigint.h b/contrib/restricted/fast_float/include/fast_float/bigint.h index 03a5caa4a5..74901e3956 100644 --- a/contrib/restricted/fast_float/include/fast_float/bigint.h +++ b/contrib/restricted/fast_float/include/fast_float/bigint.h @@ -43,8 +43,8 @@ template <uint16_t size> struct stackvec { uint16_t length{0}; stackvec() = default; - stackvec(const stackvec &) = delete; - stackvec &operator=(const stackvec &) = delete; + stackvec(stackvec const &) = delete; + stackvec &operator=(stackvec const &) = delete; stackvec(stackvec &&) = delete; stackvec &operator=(stackvec &&other) = delete; @@ -57,10 +57,12 @@ template <uint16_t size> struct stackvec { FASTFLOAT_DEBUG_ASSERT(index < length); return data[index]; } + FASTFLOAT_CONSTEXPR14 const limb &operator[](size_t index) const noexcept { FASTFLOAT_DEBUG_ASSERT(index < length); return data[index]; } + // index from the end of the container FASTFLOAT_CONSTEXPR14 const limb &rindex(size_t index) const noexcept { FASTFLOAT_DEBUG_ASSERT(index < length); @@ -72,14 +74,19 @@ template <uint16_t size> struct stackvec { FASTFLOAT_CONSTEXPR14 void set_len(size_t len) noexcept { length = uint16_t(len); } + constexpr size_t len() const noexcept { return length; } + constexpr bool is_empty() const noexcept { return length == 0; } + constexpr size_t capacity() const noexcept { return size; } + // append item to vector, without bounds checking FASTFLOAT_CONSTEXPR14 void push_unchecked(limb value) noexcept { data[length] = value; length++; } + // append item to vector, returning if item was added FASTFLOAT_CONSTEXPR14 bool try_push(limb value) noexcept { if (len() < capacity()) { @@ -89,12 +96,14 @@ template <uint16_t size> struct stackvec { return false; } } + // add items to the vector, from a span, without bounds checking FASTFLOAT_CONSTEXPR20 void extend_unchecked(limb_span s) noexcept { limb *ptr = data + length; std::copy_n(s.ptr, s.len(), ptr); set_len(len() + s.len()); } + // try to add items to the vector, returning if items were added FASTFLOAT_CONSTEXPR20 bool try_extend(limb_span s) noexcept { if (len() + s.len() <= capacity()) { @@ -104,6 +113,7 @@ template <uint16_t size> struct stackvec { return false; } } + // resize the vector, without bounds checking // if the new size is longer than the vector, assign value to each // appended item. @@ -119,6 +129,7 @@ template <uint16_t size> struct stackvec { set_len(new_len); } } + // try to resize the vector, returning if the vector was resized. FASTFLOAT_CONSTEXPR20 bool try_resize(size_t new_len, limb value) noexcept { if (new_len > capacity()) { @@ -128,6 +139,7 @@ template <uint16_t size> struct stackvec { return true; } } + // check if any limbs are non-zero after the given index. // this needs to be done in reverse order, since the index // is relative to the most significant limbs. @@ -140,6 +152,7 @@ template <uint16_t size> struct stackvec { } return false; } + // normalize the big integer, so most-significant zero limbs are removed. FASTFLOAT_CONSTEXPR14 void normalize() noexcept { while (len() > 0 && rindex(0) == 0) { @@ -423,8 +436,9 @@ struct bigint : pow5_tables<> { stackvec<bigint_limbs> vec; FASTFLOAT_CONSTEXPR20 bigint() : vec() {} - bigint(const bigint &) = delete; - bigint &operator=(const bigint &) = delete; + + bigint(bigint const &) = delete; + bigint &operator=(bigint const &) = delete; bigint(bigint &&) = delete; bigint &operator=(bigint &&other) = delete; @@ -473,7 +487,7 @@ struct bigint : pow5_tables<> { // positive, this is larger, otherwise they are equal. // the limbs are stored in little-endian order, so we // must compare the limbs in ever order. - FASTFLOAT_CONSTEXPR20 int compare(const bigint &other) const noexcept { + FASTFLOAT_CONSTEXPR20 int compare(bigint const &other) const noexcept { if (vec.len() > other.vec.len()) { return 1; } else if (vec.len() < other.vec.len()) { @@ -527,7 +541,7 @@ struct bigint : pow5_tables<> { } else if (!vec.is_empty()) { // move limbs limb *dst = vec.data + n; - const limb *src = vec.data; + limb const *src = vec.data; std::copy_backward(src, src + vec.len(), dst + vec.len()); // fill in empty limbs limb *first = vec.data; diff --git a/contrib/restricted/fast_float/include/fast_float/decimal_to_binary.h b/contrib/restricted/fast_float/include/fast_float/decimal_to_binary.h index 70ecf73c8e..948768265e 100644 --- a/contrib/restricted/fast_float/include/fast_float/decimal_to_binary.h +++ b/contrib/restricted/fast_float/include/fast_float/decimal_to_binary.h @@ -20,7 +20,7 @@ namespace fast_float { template <int bit_precision> fastfloat_really_inline FASTFLOAT_CONSTEXPR20 value128 compute_product_approximation(int64_t q, uint64_t w) { - const int index = 2 * int(q - powers::smallest_power_of_five); + int const index = 2 * int(q - powers::smallest_power_of_five); // For small values of q, e.g., q in [0,27], the answer is always exact // because The line value128 firstproduct = full_multiplication(w, // power_of_five_128[index]); gives the exact answer. @@ -93,8 +93,8 @@ compute_error(int64_t q, uint64_t w) noexcept { return compute_error_scaled<binary>(q, product.high, lz); } -// w * 10 ** q -// The returned value should be a valid ieee64 number that simply need to be +// Computers w * 10 ** q. +// The returned value should be a valid number that simply needs to be // packed. However, in some very rare cases, the computation will fail. In such // cases, we return an adjusted_mantissa with a negative power of 2: the caller // should recompute in such cases. @@ -158,7 +158,8 @@ compute_float(int64_t q, uint64_t w) noexcept { // next line is safe because -answer.power2 + 1 < 64 answer.mantissa >>= -answer.power2 + 1; // Thankfully, we can't have both "round-to-even" and subnormals because - // "round-to-even" only occurs for powers close to 0. + // "round-to-even" only occurs for powers close to 0 in the 32-bit and + // and 64-bit case (with no more than 19 digits). answer.mantissa += (answer.mantissa & 1); // round up answer.mantissa >>= 1; // There is a weird scenario where we don't have a subnormal but just. diff --git a/contrib/restricted/fast_float/include/fast_float/digit_comparison.h b/contrib/restricted/fast_float/include/fast_float/digit_comparison.h index 303fff91eb..d7ef3d9acc 100644 --- a/contrib/restricted/fast_float/include/fast_float/digit_comparison.h +++ b/contrib/restricted/fast_float/include/fast_float/digit_comparison.h @@ -62,7 +62,7 @@ scientific_exponent(parsed_number_string_t<UC> &num) noexcept { template <typename T> fastfloat_really_inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa to_extended(T value) noexcept { - using equiv_uint = typename binary_format<T>::equiv_uint; + using equiv_uint = equiv_uint_t<T>; constexpr equiv_uint exponent_mask = binary_format<T>::exponent_mask(); constexpr equiv_uint mantissa_mask = binary_format<T>::mantissa_mask(); constexpr equiv_uint hidden_bit_mask = binary_format<T>::hidden_bit_mask(); @@ -143,8 +143,8 @@ template <typename callback> fastfloat_really_inline FASTFLOAT_CONSTEXPR14 void round_nearest_tie_even(adjusted_mantissa &am, int32_t shift, callback cb) noexcept { - const uint64_t mask = (shift == 64) ? UINT64_MAX : (uint64_t(1) << shift) - 1; - const uint64_t halfway = (shift == 0) ? 0 : uint64_t(1) << (shift - 1); + uint64_t const mask = (shift == 64) ? UINT64_MAX : (uint64_t(1) << shift) - 1; + uint64_t const halfway = (shift == 0) ? 0 : uint64_t(1) << (shift - 1); uint64_t truncated_bits = am.mantissa & mask; bool is_above = truncated_bits > halfway; bool is_halfway = truncated_bits == halfway; @@ -170,6 +170,7 @@ round_down(adjusted_mantissa &am, int32_t shift) noexcept { } am.power2 += shift; } + template <typename UC> fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void skip_zeros(UC const *&first, UC const *last) noexcept { @@ -213,15 +214,16 @@ is_truncated(UC const *first, UC const *last) noexcept { } return false; } + template <typename UC> fastfloat_really_inline FASTFLOAT_CONSTEXPR20 bool -is_truncated(span<const UC> s) noexcept { +is_truncated(span<UC const> s) noexcept { return is_truncated(s.ptr, s.ptr + s.len()); } template <typename UC> fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void -parse_eight_digits(const UC *&p, limb &value, size_t &counter, +parse_eight_digits(UC const *&p, limb &value, size_t &counter, size_t &count) noexcept { value = value * 100000000 + parse_eight_digits_unrolled(p); p += 8; 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 a812682b52..af65c96bde 100644 --- a/contrib/restricted/fast_float/include/fast_float/fast_float.h +++ b/contrib/restricted/fast_float/include/fast_float/fast_float.h @@ -31,7 +31,7 @@ namespace fast_float { * `scientific`. */ template <typename T, typename UC = char, - typename = FASTFLOAT_ENABLE_IF(is_supported_float_type<T>())> + typename = FASTFLOAT_ENABLE_IF(is_supported_float_type<T>::value)> FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC> from_chars(UC const *first, UC const *last, T &value, chars_format fmt = chars_format::general) noexcept; @@ -49,10 +49,11 @@ from_chars_advanced(UC const *first, UC const *last, T &value, * from_chars for integer types. */ template <typename T, typename UC = char, - typename = FASTFLOAT_ENABLE_IF(!is_supported_float_type<T>())> + typename = FASTFLOAT_ENABLE_IF(is_supported_integer_type<T>::value)> 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" #endif // FASTFLOAT_FAST_FLOAT_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 0753904b34..be5abb44ee 100644 --- a/contrib/restricted/fast_float/include/fast_float/float_common.h +++ b/contrib/restricted/fast_float/include/fast_float/float_common.h @@ -5,6 +5,7 @@ #include <cstdint> #include <cassert> #include <cstring> +#include <limits> #include <type_traits> #include <system_error> #ifdef __has_include @@ -14,6 +15,22 @@ #endif #include "constexpr_feature_detect.h" +#define FASTFLOAT_VERSION_MAJOR 8 +#define FASTFLOAT_VERSION_MINOR 0 +#define FASTFLOAT_VERSION_PATCH 0 + +#define FASTFLOAT_STRINGIZE_IMPL(x) #x +#define FASTFLOAT_STRINGIZE(x) FASTFLOAT_STRINGIZE_IMPL(x) + +#define FASTFLOAT_VERSION_STR \ + FASTFLOAT_STRINGIZE(FASTFLOAT_VERSION_MAJOR) \ + "." FASTFLOAT_STRINGIZE(FASTFLOAT_VERSION_MINOR) "." FASTFLOAT_STRINGIZE( \ + FASTFLOAT_VERSION_PATCH) + +#define FASTFLOAT_VERSION \ + (FASTFLOAT_VERSION_MAJOR * 10000 + FASTFLOAT_VERSION_MINOR * 100 + \ + FASTFLOAT_VERSION_PATCH) + namespace fast_float { enum class chars_format : uint64_t; @@ -42,6 +59,7 @@ template <typename UC> struct from_chars_result_t { UC const *ptr; std::errc ec; }; + using from_chars_result = from_chars_result_t<char>; template <typename UC> struct parse_options_t { @@ -56,6 +74,7 @@ template <typename UC> struct parse_options_t { /** The base used for integers */ int base; }; + using parse_options = parse_options_t<char>; } // namespace fast_float @@ -202,22 +221,45 @@ fastfloat_really_inline constexpr bool cpp20_and_in_constexpr() { } 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 -#if __STDCPP_FLOAT32_T__ - || std::is_same<T, std::float32_t>::value +struct is_supported_float_type + : std::integral_constant< + bool, std::is_same<T, double>::value || std::is_same<T, float>::value +#ifdef __STDCPP_FLOAT64_T__ + || std::is_same<T, std::float64_t>::value #endif -#if __STDCPP_FLOAT64_T__ - || std::is_same<T, std::float64_t>::value +#ifdef __STDCPP_FLOAT32_T__ + || std::is_same<T, std::float32_t>::value #endif - ; -} +#ifdef __STDCPP_FLOAT16_T__ + || std::is_same<T, std::float16_t>::value +#endif +#ifdef __STDCPP_BFLOAT16_T__ + || std::is_same<T, std::bfloat16_t>::value +#endif + > { +}; + +template <typename T> +using equiv_uint_t = typename std::conditional< + sizeof(T) == 1, uint8_t, + typename std::conditional< + sizeof(T) == 2, uint16_t, + typename std::conditional<sizeof(T) == 4, uint32_t, + uint64_t>::type>::type>::type; + +template <typename T> struct is_supported_integer_type : std::is_integral<T> {}; 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; -} +struct is_supported_char_type + : std::integral_constant<bool, 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 +#ifdef __cpp_char8_t + || std::is_same<UC, char8_t>::value +#endif + > { +}; // Compares two ASCII strings in a case insensitive manner. template <typename UC> @@ -239,9 +281,11 @@ fastfloat_strncasecmp(UC const *actual_mixedcase, UC const *expected_lowercase, // a pointer and a length to a contiguous block of memory template <typename T> struct span { - const T *ptr; + T const *ptr; size_t length; - constexpr span(const T *_ptr, size_t _length) : ptr(_ptr), length(_length) {} + + constexpr span(T const *_ptr, size_t _length) : ptr(_ptr), length(_length) {} + constexpr span() : ptr(nullptr), length(0) {} constexpr size_t len() const noexcept { return length; } @@ -255,7 +299,9 @@ template <typename T> struct span { struct value128 { uint64_t low; uint64_t high; + constexpr value128(uint64_t _low, uint64_t _high) : low(_low), high(_high) {} + constexpr value128() : low(0), high(0) {} }; @@ -371,10 +417,12 @@ struct adjusted_mantissa { uint64_t mantissa{0}; int32_t power2{0}; // a negative value indicates an invalid result adjusted_mantissa() = default; - constexpr bool operator==(const adjusted_mantissa &o) const { + + constexpr bool operator==(adjusted_mantissa const &o) const { return mantissa == o.mantissa && power2 == o.power2; } - constexpr bool operator!=(const adjusted_mantissa &o) const { + + constexpr bool operator!=(adjusted_mantissa const &o) const { return mantissa != o.mantissa || power2 != o.power2; } }; @@ -388,28 +436,27 @@ constexpr uint64_t constant_55555 = 5 * 5 * 5 * 5 * 5; template <typename T, typename U = void> struct binary_format_lookup_tables; template <typename T> struct binary_format : binary_format_lookup_tables<T> { - using equiv_uint = - typename std::conditional<sizeof(T) == 4, uint32_t, uint64_t>::type; - - static inline constexpr int mantissa_explicit_bits(); - static inline constexpr int minimum_exponent(); - static inline constexpr int infinite_power(); - static inline constexpr int sign_index(); - static inline constexpr int + using equiv_uint = equiv_uint_t<T>; + + static constexpr int mantissa_explicit_bits(); + static constexpr int minimum_exponent(); + static constexpr int infinite_power(); + static constexpr int sign_index(); + static constexpr int min_exponent_fast_path(); // used when fegetround() == FE_TONEAREST - static inline constexpr int max_exponent_fast_path(); - static inline constexpr int max_exponent_round_to_even(); - static inline constexpr int min_exponent_round_to_even(); - static inline constexpr uint64_t max_mantissa_fast_path(int64_t power); - static inline constexpr uint64_t + static constexpr int max_exponent_fast_path(); + static constexpr int max_exponent_round_to_even(); + static constexpr int min_exponent_round_to_even(); + static constexpr uint64_t max_mantissa_fast_path(int64_t power); + static constexpr uint64_t max_mantissa_fast_path(); // used when fegetround() == FE_TONEAREST - static inline constexpr int largest_power_of_ten(); - static inline constexpr int smallest_power_of_ten(); - static inline constexpr T exact_power_of_ten(int64_t power); - static inline constexpr size_t max_digits(); - static inline constexpr equiv_uint exponent_mask(); - static inline constexpr equiv_uint mantissa_mask(); - static inline constexpr equiv_uint hidden_bit_mask(); + static constexpr int largest_power_of_ten(); + static constexpr int smallest_power_of_ten(); + static constexpr T exact_power_of_ten(int64_t power); + static constexpr size_t max_digits(); + static constexpr equiv_uint exponent_mask(); + static constexpr equiv_uint mantissa_mask(); + static constexpr equiv_uint hidden_bit_mask(); }; template <typename U> struct binary_format_lookup_tables<double, U> { @@ -517,6 +564,7 @@ template <> inline constexpr int binary_format<double>::mantissa_explicit_bits() { return 52; } + template <> inline constexpr int binary_format<float>::mantissa_explicit_bits() { return 23; @@ -545,6 +593,7 @@ inline constexpr int binary_format<float>::min_exponent_round_to_even() { template <> inline constexpr int binary_format<double>::minimum_exponent() { return -1023; } + template <> inline constexpr int binary_format<float>::minimum_exponent() { return -127; } @@ -552,6 +601,7 @@ template <> inline constexpr int binary_format<float>::minimum_exponent() { template <> inline constexpr int binary_format<double>::infinite_power() { return 0x7FF; } + template <> inline constexpr int binary_format<float>::infinite_power() { return 0xFF; } @@ -559,6 +609,7 @@ template <> inline constexpr int binary_format<float>::infinite_power() { template <> inline constexpr int binary_format<double>::sign_index() { return 63; } + template <> inline constexpr int binary_format<float>::sign_index() { return 31; } @@ -567,6 +618,7 @@ template <> inline constexpr int binary_format<double>::max_exponent_fast_path() { return 22; } + template <> inline constexpr int binary_format<float>::max_exponent_fast_path() { return 10; @@ -576,19 +628,271 @@ template <> inline constexpr uint64_t binary_format<double>::max_mantissa_fast_path() { return uint64_t(2) << mantissa_explicit_bits(); } + +template <> +inline constexpr uint64_t binary_format<float>::max_mantissa_fast_path() { + return uint64_t(2) << mantissa_explicit_bits(); +} + +// credit: Jakub Jelínek +#ifdef __STDCPP_FLOAT16_T__ +template <typename U> struct binary_format_lookup_tables<std::float16_t, U> { + static constexpr std::float16_t powers_of_ten[] = {1e0f16, 1e1f16, 1e2f16, + 1e3f16, 1e4f16}; + + // Largest integer value v so that (5**index * v) <= 1<<11. + // 0x800 == 1<<11 + static constexpr uint64_t max_mantissa[] = {0x800, + 0x800 / 5, + 0x800 / (5 * 5), + 0x800 / (5 * 5 * 5), + 0x800 / (5 * 5 * 5 * 5), + 0x800 / (constant_55555)}; +}; + +#if FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE + +template <typename U> +constexpr std::float16_t + binary_format_lookup_tables<std::float16_t, U>::powers_of_ten[]; + +template <typename U> +constexpr uint64_t + binary_format_lookup_tables<std::float16_t, U>::max_mantissa[]; + +#endif + +template <> +inline constexpr std::float16_t +binary_format<std::float16_t>::exact_power_of_ten(int64_t power) { + // Work around clang bug https://godbolt.org/z/zedh7rrhc + return (void)powers_of_ten[0], powers_of_ten[power]; +} + +template <> +inline constexpr binary_format<std::float16_t>::equiv_uint +binary_format<std::float16_t>::exponent_mask() { + return 0x7C00; +} + +template <> +inline constexpr binary_format<std::float16_t>::equiv_uint +binary_format<std::float16_t>::mantissa_mask() { + return 0x03FF; +} + +template <> +inline constexpr binary_format<std::float16_t>::equiv_uint +binary_format<std::float16_t>::hidden_bit_mask() { + return 0x0400; +} + +template <> +inline constexpr int binary_format<std::float16_t>::max_exponent_fast_path() { + return 4; +} + +template <> +inline constexpr int binary_format<std::float16_t>::mantissa_explicit_bits() { + return 10; +} + template <> inline constexpr uint64_t -binary_format<double>::max_mantissa_fast_path(int64_t power) { +binary_format<std::float16_t>::max_mantissa_fast_path() { + return uint64_t(2) << mantissa_explicit_bits(); +} + +template <> +inline constexpr uint64_t +binary_format<std::float16_t>::max_mantissa_fast_path(int64_t power) { // caller is responsible to ensure that - // power >= 0 && power <= 22 + // power >= 0 && power <= 4 // // Work around clang bug https://godbolt.org/z/zedh7rrhc return (void)max_mantissa[0], max_mantissa[power]; } + template <> -inline constexpr uint64_t binary_format<float>::max_mantissa_fast_path() { +inline constexpr int binary_format<std::float16_t>::min_exponent_fast_path() { + return 0; +} + +template <> +inline constexpr int +binary_format<std::float16_t>::max_exponent_round_to_even() { + return 5; +} + +template <> +inline constexpr int +binary_format<std::float16_t>::min_exponent_round_to_even() { + return -22; +} + +template <> +inline constexpr int binary_format<std::float16_t>::minimum_exponent() { + return -15; +} + +template <> +inline constexpr int binary_format<std::float16_t>::infinite_power() { + return 0x1F; +} + +template <> inline constexpr int binary_format<std::float16_t>::sign_index() { + return 15; +} + +template <> +inline constexpr int binary_format<std::float16_t>::largest_power_of_ten() { + return 4; +} + +template <> +inline constexpr int binary_format<std::float16_t>::smallest_power_of_ten() { + return -27; +} + +template <> +inline constexpr size_t binary_format<std::float16_t>::max_digits() { + return 22; +} +#endif // __STDCPP_FLOAT16_T__ + +// credit: Jakub Jelínek +#ifdef __STDCPP_BFLOAT16_T__ +template <typename U> struct binary_format_lookup_tables<std::bfloat16_t, U> { + static constexpr std::bfloat16_t powers_of_ten[] = {1e0bf16, 1e1bf16, 1e2bf16, + 1e3bf16}; + + // Largest integer value v so that (5**index * v) <= 1<<8. + // 0x100 == 1<<8 + static constexpr uint64_t max_mantissa[] = {0x100, 0x100 / 5, 0x100 / (5 * 5), + 0x100 / (5 * 5 * 5), + 0x100 / (5 * 5 * 5 * 5)}; +}; + +#if FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE + +template <typename U> +constexpr std::bfloat16_t + binary_format_lookup_tables<std::bfloat16_t, U>::powers_of_ten[]; + +template <typename U> +constexpr uint64_t + binary_format_lookup_tables<std::bfloat16_t, U>::max_mantissa[]; + +#endif + +template <> +inline constexpr std::bfloat16_t +binary_format<std::bfloat16_t>::exact_power_of_ten(int64_t power) { + // Work around clang bug https://godbolt.org/z/zedh7rrhc + return (void)powers_of_ten[0], powers_of_ten[power]; +} + +template <> +inline constexpr int binary_format<std::bfloat16_t>::max_exponent_fast_path() { + return 3; +} + +template <> +inline constexpr binary_format<std::bfloat16_t>::equiv_uint +binary_format<std::bfloat16_t>::exponent_mask() { + return 0x7F80; +} + +template <> +inline constexpr binary_format<std::bfloat16_t>::equiv_uint +binary_format<std::bfloat16_t>::mantissa_mask() { + return 0x007F; +} + +template <> +inline constexpr binary_format<std::bfloat16_t>::equiv_uint +binary_format<std::bfloat16_t>::hidden_bit_mask() { + return 0x0080; +} + +template <> +inline constexpr int binary_format<std::bfloat16_t>::mantissa_explicit_bits() { + return 7; +} + +template <> +inline constexpr uint64_t +binary_format<std::bfloat16_t>::max_mantissa_fast_path() { return uint64_t(2) << mantissa_explicit_bits(); } + +template <> +inline constexpr uint64_t +binary_format<std::bfloat16_t>::max_mantissa_fast_path(int64_t power) { + // caller is responsible to ensure that + // power >= 0 && power <= 3 + // + // Work around clang bug https://godbolt.org/z/zedh7rrhc + return (void)max_mantissa[0], max_mantissa[power]; +} + +template <> +inline constexpr int binary_format<std::bfloat16_t>::min_exponent_fast_path() { + return 0; +} + +template <> +inline constexpr int +binary_format<std::bfloat16_t>::max_exponent_round_to_even() { + return 3; +} + +template <> +inline constexpr int +binary_format<std::bfloat16_t>::min_exponent_round_to_even() { + return -24; +} + +template <> +inline constexpr int binary_format<std::bfloat16_t>::minimum_exponent() { + return -127; +} + +template <> +inline constexpr int binary_format<std::bfloat16_t>::infinite_power() { + return 0xFF; +} + +template <> inline constexpr int binary_format<std::bfloat16_t>::sign_index() { + return 15; +} + +template <> +inline constexpr int binary_format<std::bfloat16_t>::largest_power_of_ten() { + return 38; +} + +template <> +inline constexpr int binary_format<std::bfloat16_t>::smallest_power_of_ten() { + return -60; +} + +template <> +inline constexpr size_t binary_format<std::bfloat16_t>::max_digits() { + return 98; +} +#endif // __STDCPP_BFLOAT16_T__ + +template <> +inline constexpr uint64_t +binary_format<double>::max_mantissa_fast_path(int64_t power) { + // caller is responsible to ensure that + // power >= 0 && power <= 22 + // + // Work around clang bug https://godbolt.org/z/zedh7rrhc + return (void)max_mantissa[0], max_mantissa[power]; +} + template <> inline constexpr uint64_t binary_format<float>::max_mantissa_fast_path(int64_t power) { @@ -605,6 +909,7 @@ binary_format<double>::exact_power_of_ten(int64_t power) { // Work around clang bug https://godbolt.org/z/zedh7rrhc return (void)powers_of_ten[0], powers_of_ten[power]; } + template <> inline constexpr float binary_format<float>::exact_power_of_ten(int64_t power) { // Work around clang bug https://godbolt.org/z/zedh7rrhc @@ -614,6 +919,7 @@ inline constexpr float binary_format<float>::exact_power_of_ten(int64_t power) { template <> inline constexpr int binary_format<double>::largest_power_of_ten() { return 308; } + template <> inline constexpr int binary_format<float>::largest_power_of_ten() { return 38; } @@ -622,6 +928,7 @@ template <> inline constexpr int binary_format<double>::smallest_power_of_ten() { return -342; } + template <> inline constexpr int binary_format<float>::smallest_power_of_ten() { return -64; } @@ -629,6 +936,7 @@ template <> inline constexpr int binary_format<float>::smallest_power_of_ten() { template <> inline constexpr size_t binary_format<double>::max_digits() { return 769; } + template <> inline constexpr size_t binary_format<float>::max_digits() { return 114; } @@ -638,6 +946,7 @@ inline constexpr binary_format<float>::equiv_uint binary_format<float>::exponent_mask() { return 0x7F800000; } + template <> inline constexpr binary_format<double>::equiv_uint binary_format<double>::exponent_mask() { @@ -649,6 +958,7 @@ inline constexpr binary_format<float>::equiv_uint binary_format<float>::mantissa_mask() { return 0x007FFFFF; } + template <> inline constexpr binary_format<double>::equiv_uint binary_format<double>::mantissa_mask() { @@ -660,6 +970,7 @@ inline constexpr binary_format<float>::equiv_uint binary_format<float>::hidden_bit_mask() { return 0x00800000; } + template <> inline constexpr binary_format<double>::equiv_uint binary_format<double>::hidden_bit_mask() { @@ -669,11 +980,12 @@ binary_format<double>::hidden_bit_mask() { template <typename T> fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void to_float(bool negative, adjusted_mantissa am, T &value) { - using fastfloat_uint = typename binary_format<T>::equiv_uint; - fastfloat_uint word = (fastfloat_uint)am.mantissa; - word |= fastfloat_uint(am.power2) - << binary_format<T>::mantissa_explicit_bits(); - word |= fastfloat_uint(negative) << binary_format<T>::sign_index(); + using equiv_uint = equiv_uint_t<T>; + equiv_uint word = equiv_uint(am.mantissa); + word = equiv_uint(word | equiv_uint(am.power2) + << binary_format<T>::mantissa_explicit_bits()); + word = + equiv_uint(word | equiv_uint(negative) << binary_format<T>::sign_index()); #if FASTFLOAT_HAS_BIT_CAST value = std::bit_cast<T>(word); #else @@ -715,34 +1027,53 @@ template <typename UC> static constexpr uint64_t int_cmp_zeros() { uint64_t(UC('0')) << 16 | UC('0')) : (uint64_t(UC('0')) << 32 | UC('0')); } + template <typename UC> static constexpr int int_cmp_len() { return sizeof(uint64_t) / sizeof(UC); } -template <typename UC> static constexpr UC const *str_const_nan() { - return nullptr; -} + +template <typename UC> constexpr UC const *str_const_nan(); + template <> constexpr char const *str_const_nan<char>() { return "nan"; } + template <> constexpr wchar_t const *str_const_nan<wchar_t>() { return L"nan"; } + template <> constexpr char16_t const *str_const_nan<char16_t>() { return u"nan"; } + template <> constexpr char32_t const *str_const_nan<char32_t>() { return U"nan"; } -template <typename UC> static constexpr UC const *str_const_inf() { - return nullptr; + +#ifdef __cpp_char8_t +template <> constexpr char8_t const *str_const_nan<char8_t>() { + return u8"nan"; } +#endif + +template <typename UC> constexpr UC const *str_const_inf(); + template <> constexpr char const *str_const_inf<char>() { return "infinity"; } + template <> constexpr wchar_t const *str_const_inf<wchar_t>() { return L"infinity"; } + template <> constexpr char16_t const *str_const_inf<char16_t>() { return u"infinity"; } + template <> constexpr char32_t const *str_const_inf<char32_t>() { return U"infinity"; } +#ifdef __cpp_char8_t +template <> constexpr char8_t const *str_const_inf<char8_t>() { + return u8"infinity"; +} +#endif + 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, @@ -808,6 +1139,50 @@ fastfloat_really_inline constexpr uint64_t min_safe_u64(int base) { return int_luts<>::min_safe_u64[base - 2]; } +static_assert(std::is_same<equiv_uint_t<double>, uint64_t>::value, + "equiv_uint should be uint64_t for double"); +static_assert(std::numeric_limits<double>::is_iec559, + "double must fulfill the requirements of IEC 559 (IEEE 754)"); + +static_assert(std::is_same<equiv_uint_t<float>, uint32_t>::value, + "equiv_uint should be uint32_t for float"); +static_assert(std::numeric_limits<float>::is_iec559, + "float must fulfill the requirements of IEC 559 (IEEE 754)"); + +#ifdef __STDCPP_FLOAT64_T__ +static_assert(std::is_same<equiv_uint_t<std::float64_t>, uint64_t>::value, + "equiv_uint should be uint64_t for std::float64_t"); +static_assert( + std::numeric_limits<std::float64_t>::is_iec559, + "std::float64_t must fulfill the requirements of IEC 559 (IEEE 754)"); +#endif // __STDCPP_FLOAT64_T__ + +#ifdef __STDCPP_FLOAT32_T__ +static_assert(std::is_same<equiv_uint_t<std::float32_t>, uint32_t>::value, + "equiv_uint should be uint32_t for std::float32_t"); +static_assert( + std::numeric_limits<std::float32_t>::is_iec559, + "std::float32_t must fulfill the requirements of IEC 559 (IEEE 754)"); +#endif // __STDCPP_FLOAT32_T__ + +#ifdef __STDCPP_FLOAT16_T__ +static_assert( + std::is_same<binary_format<std::float16_t>::equiv_uint, uint16_t>::value, + "equiv_uint should be uint16_t for std::float16_t"); +static_assert( + std::numeric_limits<std::float16_t>::is_iec559, + "std::float16_t must fulfill the requirements of IEC 559 (IEEE 754)"); +#endif // __STDCPP_FLOAT16_T__ + +#ifdef __STDCPP_BFLOAT16_T__ +static_assert( + std::is_same<binary_format<std::bfloat16_t>::equiv_uint, uint16_t>::value, + "equiv_uint should be uint16_t for std::bfloat16_t"); +static_assert( + std::numeric_limits<std::bfloat16_t>::is_iec559, + "std::bfloat16_t must fulfill the requirements of IEC 559 (IEEE 754)"); +#endif // __STDCPP_BFLOAT16_T__ + constexpr chars_format operator~(chars_format rhs) noexcept { using int_type = std::underlying_type<chars_format>::type; return static_cast<chars_format>(~static_cast<int_type>(rhs)); 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 28a23ee414..0dbb3a143a 100644 --- a/contrib/restricted/fast_float/include/fast_float/parse_number.h +++ b/contrib/restricted/fast_float/include/fast_float/parse_number.h @@ -10,6 +10,7 @@ #include <cstring> #include <limits> #include <system_error> + namespace fast_float { namespace detail { @@ -95,7 +96,7 @@ fastfloat_really_inline bool rounds_to_nearest() noexcept { // asm). The value does not need to be std::numeric_limits<float>::min(), any // small value so that 1 + x should round to 1 would do (after accounting for // excess precision, as in 387 instructions). - static volatile float fmin = std::numeric_limits<float>::min(); + static float volatile fmin = std::numeric_limits<float>::min(); float fmini = fmin; // we copy it so that it gets loaded at most once. // // Explanation: @@ -145,7 +146,7 @@ template <typename T> struct from_chars_caller { } }; -#if __STDCPP_FLOAT32_T__ == 1 +#ifdef __STDCPP_FLOAT32_T__ template <> struct from_chars_caller<std::float32_t> { template <typename UC> FASTFLOAT_CONSTEXPR20 static from_chars_result_t<UC> @@ -162,7 +163,7 @@ template <> struct from_chars_caller<std::float32_t> { }; #endif -#if __STDCPP_FLOAT64_T__ == 1 +#ifdef __STDCPP_FLOAT64_T__ template <> struct from_chars_caller<std::float64_t> { template <typename UC> FASTFLOAT_CONSTEXPR20 static from_chars_result_t<UC> @@ -196,9 +197,9 @@ template <typename T, typename UC> FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC> from_chars_advanced(parsed_number_string_t<UC> &pns, T &value) noexcept { - static_assert(is_supported_float_type<T>(), + static_assert(is_supported_float_type<T>::value, "only some floating-point types are supported"); - static_assert(is_supported_char_type<UC>(), + static_assert(is_supported_char_type<UC>::value, "only char, wchar_t, char16_t and char32_t are supported"); from_chars_result_t<UC> answer; @@ -285,9 +286,9 @@ FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC> from_chars_float_advanced(UC const *first, UC const *last, T &value, parse_options_t<UC> options) noexcept { - static_assert(is_supported_float_type<T>(), + static_assert(is_supported_float_type<T>::value, "only some floating-point types are supported"); - static_assert(is_supported_char_type<UC>(), + static_assert(is_supported_char_type<UC>::value, "only char, wchar_t, char16_t and char32_t are supported"); chars_format const fmt = detail::adjust_for_feature_macros(options.format); @@ -323,8 +324,9 @@ 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(std::is_integral<T>::value, "only integer types are supported"); - static_assert(is_supported_char_type<UC>(), + static_assert(is_supported_integer_type<T>::value, + "only integer types are supported"); + static_assert(is_supported_char_type<UC>::value, "only char, wchar_t, char16_t and char32_t are supported"); parse_options_t<UC> options; @@ -337,8 +339,9 @@ FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC> from_chars_int_advanced(UC const *first, UC const *last, T &value, parse_options_t<UC> options) noexcept { - static_assert(std::is_integral<T>::value, "only integer types are supported"); - static_assert(is_supported_char_type<UC>(), + static_assert(is_supported_integer_type<T>::value, + "only integer types are supported"); + static_assert(is_supported_char_type<UC>::value, "only char, wchar_t, char16_t and char32_t are supported"); chars_format const fmt = detail::adjust_for_feature_macros(options.format); @@ -359,7 +362,11 @@ from_chars_int_advanced(UC const *first, UC const *last, T &value, return parse_int_string(first, last, value, options); } -template <bool> struct from_chars_advanced_caller { +template <size_t TypeIx> struct from_chars_advanced_caller { + static_assert(TypeIx > 0, "unsupported type"); +}; + +template <> struct from_chars_advanced_caller<1> { template <typename T, typename UC> FASTFLOAT_CONSTEXPR20 static from_chars_result_t<UC> call(UC const *first, UC const *last, T &value, @@ -368,7 +375,7 @@ template <bool> struct from_chars_advanced_caller { } }; -template <> struct from_chars_advanced_caller<false> { +template <> struct from_chars_advanced_caller<2> { template <typename T, typename UC> FASTFLOAT_CONSTEXPR20 static from_chars_result_t<UC> call(UC const *first, UC const *last, T &value, @@ -381,8 +388,10 @@ template <typename T, typename UC> FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC> from_chars_advanced(UC const *first, UC const *last, T &value, parse_options_t<UC> options) noexcept { - return from_chars_advanced_caller<is_supported_float_type<T>()>::call( - first, last, value, options); + return from_chars_advanced_caller< + size_t(is_supported_float_type<T>::value) + + 2 * size_t(is_supported_integer_type<T>::value)>::call(first, last, value, + options); } } // namespace fast_float diff --git a/contrib/restricted/fast_float/ya.make b/contrib/restricted/fast_float/ya.make index 32da568f8b..bc3dddf9f5 100644 --- a/contrib/restricted/fast_float/ya.make +++ b/contrib/restricted/fast_float/ya.make @@ -11,9 +11,9 @@ LICENSE( LICENSE_TEXTS(.yandex_meta/licenses.list.txt) -VERSION(7.0.0) +VERSION(8.0.0) -ORIGINAL_SOURCE(https://github.com/fastfloat/fast_float/archive/v7.0.0.tar.gz) +ORIGINAL_SOURCE(https://github.com/fastfloat/fast_float/archive/v8.0.0.tar.gz) NO_COMPILER_WARNINGS() |