aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/restricted/fast_float
diff options
context:
space:
mode:
authorrobot-contrib <robot-contrib@yandex-team.com>2023-06-09 11:27:03 +0300
committerrobot-contrib <robot-contrib@yandex-team.com>2023-06-09 11:27:03 +0300
commit5284a823d0ee2fff26807b65b8944450b3de632e (patch)
tree9e92978b7bcef0f7633bf8b983dba953e2191fcf /contrib/restricted/fast_float
parent083db20c17c2cf642bbac27c41ba1fa68645b4a8 (diff)
downloadydb-5284a823d0ee2fff26807b65b8944450b3de632e.tar.gz
Update contrib/restricted/fast_float to 5.0.0
Diffstat (limited to 'contrib/restricted/fast_float')
-rw-r--r--contrib/restricted/fast_float/LICENSE-BOOST23
-rw-r--r--contrib/restricted/fast_float/README.md36
-rw-r--r--contrib/restricted/fast_float/include/fast_float/ascii_number.h102
-rw-r--r--contrib/restricted/fast_float/include/fast_float/constexpr_feature_detect.h4
-rw-r--r--contrib/restricted/fast_float/include/fast_float/decimal_to_binary.h4
-rw-r--r--contrib/restricted/fast_float/include/fast_float/digit_comparison.h70
-rw-r--r--contrib/restricted/fast_float/include/fast_float/fast_float.h39
-rw-r--r--contrib/restricted/fast_float/include/fast_float/float_common.h230
-rw-r--r--contrib/restricted/fast_float/include/fast_float/parse_number.h56
9 files changed, 378 insertions, 186 deletions
diff --git a/contrib/restricted/fast_float/LICENSE-BOOST b/contrib/restricted/fast_float/LICENSE-BOOST
new file mode 100644
index 0000000000..127a5bc39b
--- /dev/null
+++ b/contrib/restricted/fast_float/LICENSE-BOOST
@@ -0,0 +1,23 @@
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE. \ No newline at end of file
diff --git a/contrib/restricted/fast_float/README.md b/contrib/restricted/fast_float/README.md
index 10cd01b041..4f3eb22d76 100644
--- a/contrib/restricted/fast_float/README.md
+++ b/contrib/restricted/fast_float/README.md
@@ -1,4 +1,8 @@
+
## fast_float number parsing library: 4x faster than strtod
+[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/fast_float.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:fast_float)
+[![VS17-CI](https://github.com/fastfloat/fast_float/actions/workflows/vs17-ci.yml/badge.svg)](https://github.com/fastfloat/fast_float/actions/workflows/vs17-ci.yml)
+[![Ubuntu 22.04 CI (GCC 11)](https://github.com/fastfloat/fast_float/actions/workflows/ubuntu22.yml/badge.svg)](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
@@ -93,6 +97,24 @@ constexpr double constexptest() {
}
```
+## Non-ASCII Inputs
+
+We also support UTF-16 and UTF-32 inputs, as well as ASCII/UTF-8, as in the following example:
+
+``` C++
+#include "fast_float/fast_float.h"
+#include <iostream>
+
+int main() {
+ const 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; }
+ std::cout << "parsed the number " << result << std::endl;
+ return EXIT_SUCCESS;
+}
+```
+
## Using commas as decimal separator
@@ -189,11 +211,11 @@ It can parse random floating-point numbers at a speed of 1 GB/s on some systems.
$ ./build/benchmarks/benchmark
# parsing random integers in the range [0,1)
volume = 2.09808 MB
-netlib : 271.18 MB/s (+/- 1.2 %) 12.93 Mfloat/s
-doubleconversion : 225.35 MB/s (+/- 1.2 %) 10.74 Mfloat/s
-strtod : 190.94 MB/s (+/- 1.6 %) 9.10 Mfloat/s
-abseil : 430.45 MB/s (+/- 2.2 %) 20.52 Mfloat/s
-fastfloat : 1042.38 MB/s (+/- 9.9 %) 49.68 Mfloat/s
+netlib : 271.18 MB/s (+/- 1.2 %) 12.93 Mfloat/s
+doubleconversion : 225.35 MB/s (+/- 1.2 %) 10.74 Mfloat/s
+strtod : 190.94 MB/s (+/- 1.6 %) 9.10 Mfloat/s
+abseil : 430.45 MB/s (+/- 2.2 %) 20.52 Mfloat/s
+fastfloat : 1042.38 MB/s (+/- 9.9 %) 49.68 Mfloat/s
```
See https://github.com/lemire/simple_fastfloat_benchmark for our benchmarking code.
@@ -257,7 +279,7 @@ under the Apache 2.0 license.
<sup>
Licensed under either of <a href="LICENSE-APACHE">Apache License, Version
-2.0</a> or <a href="LICENSE-MIT">MIT license</a> at your option.
+2.0</a> or <a href="LICENSE-MIT">MIT license</a> or <a href="LICENSE-BOOST">BOOST license</a> .
</sup>
<br>
@@ -265,5 +287,5 @@ Licensed under either of <a href="LICENSE-APACHE">Apache License, Version
<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,
-shall be dual licensed as above, without any additional terms or conditions.
+shall be triple licensed as above, without any additional terms or conditions.
</sub>
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 72b8098eda..d506326ec9 100644
--- a/contrib/restricted/fast_float/include/fast_float/ascii_number.h
+++ b/contrib/restricted/fast_float/include/fast_float/ascii_number.h
@@ -12,8 +12,9 @@ namespace fast_float {
// Next function can be micro-optimized, but compilers are entirely
// able to optimize it well.
-fastfloat_really_inline constexpr bool is_integer(char c) noexcept {
- return c >= '0' && c <= '9';
+template <typename UC>
+fastfloat_really_inline constexpr bool is_integer(UC c) noexcept {
+ return !(c > UC('9') || c < UC('0'));
}
fastfloat_really_inline constexpr uint64_t byteswap(uint64_t val) {
@@ -75,6 +76,16 @@ uint32_t parse_eight_digits_unrolled(uint64_t val) {
return uint32_t(val);
}
+fastfloat_really_inline constexpr
+uint32_t parse_eight_digits_unrolled(const char16_t *) noexcept {
+ return 0;
+}
+
+fastfloat_really_inline constexpr
+uint32_t parse_eight_digits_unrolled(const char32_t *) noexcept {
+ return 0;
+}
+
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
uint32_t parse_eight_digits_unrolled(const char *chars) noexcept {
return parse_eight_digits_unrolled(read_u64(chars));
@@ -86,40 +97,51 @@ fastfloat_really_inline constexpr bool is_made_of_eight_digits_fast(uint64_t val
0x8080808080808080));
}
+fastfloat_really_inline constexpr
+bool is_made_of_eight_digits_fast(const char16_t *) noexcept {
+ return false;
+}
+
+fastfloat_really_inline constexpr
+bool is_made_of_eight_digits_fast(const char32_t *) noexcept {
+ return false;
+}
+
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
bool is_made_of_eight_digits_fast(const char *chars) noexcept {
return is_made_of_eight_digits_fast(read_u64(chars));
}
-typedef span<const char> byte_span;
-
-struct parsed_number_string {
+template <typename UC>
+struct parsed_number_string_t {
int64_t exponent{0};
uint64_t mantissa{0};
- const char *lastmatch{nullptr};
+ UC const * lastmatch{nullptr};
bool negative{false};
bool valid{false};
bool too_many_digits{false};
// contains the range of the significant digits
- byte_span integer{}; // non-nullable
- byte_span fraction{}; // nullable
+ span<const UC> integer{}; // non-nullable
+ span<const UC> fraction{}; // nullable
};
-
+using byte_span = span<char>;
+using parsed_number_string = parsed_number_string_t<char>;
// Assuming that you use no more than 19 digits, this will
// parse an ASCII string.
+template <typename UC>
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
-parsed_number_string parse_number_string(const char *p, const char *pend, parse_options options) noexcept {
- const chars_format fmt = options.format;
- const char decimal_point = options.decimal_point;
+parsed_number_string_t<UC> parse_number_string(UC const *p, UC const * pend, parse_options_t<UC> options) noexcept {
+ chars_format const fmt = options.format;
+ UC const decimal_point = options.decimal_point;
- parsed_number_string answer;
+ parsed_number_string_t<UC> answer;
answer.valid = false;
answer.too_many_digits = false;
- answer.negative = (*p == '-');
-#if FASTFLOAT_ALLOWS_LEADING_PLUS // disabled by default
- if ((*p == '-') || (*p == '+')) {
+ answer.negative = (*p == UC('-'));
+#ifdef FASTFLOAT_ALLOWS_LEADING_PLUS // disabled by default
+ if ((*p == UC('-')) || (*p == UC('+'))) {
#else
- if (*p == '-') { // C++17 20.19.3.(7.1) explicitly forbids '+' sign here
+ if (*p == UC('-')) { // C++17 20.19.3.(7.1) explicitly forbids '+' sign here
#endif
++p;
if (p == pend) {
@@ -129,7 +151,7 @@ parsed_number_string parse_number_string(const char *p, const char *pend, parse_
return answer;
}
}
- const char *const start_digits = p;
+ UC const * const start_digits = p;
uint64_t i = 0; // an unsigned int avoids signed overflows (which are bad)
@@ -137,29 +159,31 @@ parsed_number_string parse_number_string(const char *p, const char *pend, parse_
// a multiplication by 10 is cheaper than an arbitrary integer
// multiplication
i = 10 * i +
- uint64_t(*p - '0'); // might overflow, we will handle the overflow later
+ uint64_t(*p - UC('0')); // might overflow, we will handle the overflow later
++p;
}
- const char *const end_of_integer_part = p;
+ UC const * const end_of_integer_part = p;
int64_t digit_count = int64_t(end_of_integer_part - start_digits);
- answer.integer = byte_span(start_digits, size_t(digit_count));
+ answer.integer = span<const UC>(start_digits, size_t(digit_count));
int64_t exponent = 0;
if ((p != pend) && (*p == decimal_point)) {
++p;
- const char* before = p;
+ UC const * before = p;
// can occur at most twice without overflowing, but let it occur more, since
// for integers with many digits, digit parsing is the primary bottleneck.
- while ((std::distance(p, pend) >= 8) && is_made_of_eight_digits_fast(p)) {
- i = i * 100000000 + parse_eight_digits_unrolled(p); // in rare cases, this will overflow, but that's ok
- p += 8;
+ if (std::is_same<UC,char>::value) {
+ while ((std::distance(p, pend) >= 8) && is_made_of_eight_digits_fast(p)) {
+ i = i * 100000000 + parse_eight_digits_unrolled(p); // in rare cases, this will overflow, but that's ok
+ p += 8;
+ }
}
while ((p != pend) && is_integer(*p)) {
- uint8_t digit = uint8_t(*p - '0');
+ uint8_t digit = uint8_t(*p - UC('0'));
++p;
i = i * 10 + digit; // in rare cases, this will overflow, but that's ok
}
exponent = before - p;
- answer.fraction = byte_span(before, size_t(p - before));
+ answer.fraction = span<const UC>(before, size_t(p - before));
digit_count -= exponent;
}
// we must have encountered at least one integer!
@@ -167,14 +191,14 @@ parsed_number_string parse_number_string(const char *p, const char *pend, parse_
return answer;
}
int64_t exp_number = 0; // explicit exponential part
- if ((fmt & chars_format::scientific) && (p != pend) && (('e' == *p) || ('E' == *p))) {
- const char * location_of_e = p;
+ if ((fmt & chars_format::scientific) && (p != pend) && ((UC('e') == *p) || (UC('E') == *p))) {
+ UC const * location_of_e = p;
++p;
bool neg_exp = false;
- if ((p != pend) && ('-' == *p)) {
+ if ((p != pend) && (UC('-') == *p)) {
neg_exp = true;
++p;
- } else if ((p != pend) && ('+' == *p)) { // '+' on exponent is allowed by C++17 20.19.3.(7.1)
+ } else if ((p != pend) && (UC('+') == *p)) { // '+' on exponent is allowed by C++17 20.19.3.(7.1)
++p;
}
if ((p == pend) || !is_integer(*p)) {
@@ -186,7 +210,7 @@ parsed_number_string parse_number_string(const char *p, const char *pend, parse_
p = location_of_e;
} else {
while ((p != pend) && is_integer(*p)) {
- uint8_t digit = uint8_t(*p - '0');
+ uint8_t digit = uint8_t(*p - UC('0'));
if (exp_number < 0x10000000) {
exp_number = 10 * exp_number + digit;
}
@@ -212,9 +236,9 @@ parsed_number_string parse_number_string(const char *p, const char *pend, parse_
// We have to handle the case where we have 0.0000somenumber.
// We need to be mindful of the case where we only have zeroes...
// E.g., 0.000000000...000.
- const char *start = start_digits;
- while ((start != pend) && (*start == '0' || *start == decimal_point)) {
- if(*start == '0') { digit_count --; }
+ UC const * start = start_digits;
+ while ((start != pend) && (*start == UC('0') || *start == decimal_point)) {
+ if(*start == UC('0')) { digit_count --; }
start++;
}
if (digit_count > 19) {
@@ -224,19 +248,19 @@ parsed_number_string parse_number_string(const char *p, const char *pend, parse_
// pre-tokenized spans from above.
i = 0;
p = answer.integer.ptr;
- const char* int_end = p + answer.integer.len();
+ UC const * int_end = p + answer.integer.len();
const uint64_t minimal_nineteen_digit_integer{1000000000000000000};
while((i < minimal_nineteen_digit_integer) && (p != int_end)) {
- i = i * 10 + uint64_t(*p - '0');
+ i = i * 10 + uint64_t(*p - UC('0'));
++p;
}
if (i >= minimal_nineteen_digit_integer) { // We have a big integers
exponent = end_of_integer_part - p + exp_number;
} else { // We have a value with a fractional component.
p = answer.fraction.ptr;
- const char* frac_end = p + answer.fraction.len();
+ UC const * frac_end = p + answer.fraction.len();
while((i < minimal_nineteen_digit_integer) && (p != frac_end)) {
- i = i * 10 + uint64_t(*p - '0');
+ i = i * 10 + uint64_t(*p - UC('0'));
++p;
}
exponent = answer.fraction.ptr - p + exp_number;
diff --git a/contrib/restricted/fast_float/include/fast_float/constexpr_feature_detect.h b/contrib/restricted/fast_float/include/fast_float/constexpr_feature_detect.h
index 9ec8611fd9..ba8b65c64a 100644
--- a/contrib/restricted/fast_float/include/fast_float/constexpr_feature_detect.h
+++ b/contrib/restricted/fast_float/include/fast_float/constexpr_feature_detect.h
@@ -14,13 +14,13 @@
#define FASTFLOAT_CONSTEXPR14
#endif
-#if __cpp_lib_bit_cast >= 201806L
+#if defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806L
#define FASTFLOAT_HAS_BIT_CAST 1
#else
#define FASTFLOAT_HAS_BIT_CAST 0
#endif
-#if __cpp_lib_is_constant_evaluated >= 201811L
+#if defined(__cpp_lib_is_constant_evaluated) && __cpp_lib_is_constant_evaluated >= 201811L
#define FASTFLOAT_HAS_IS_CONSTANT_EVALUATED 1
#else
#define FASTFLOAT_HAS_IS_CONSTANT_EVALUATED 0
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 6d0f73040f..fec916f3a0 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
@@ -48,9 +48,9 @@ namespace detail {
* where
* p = log(5**q)/log(2) = q * log(5)/log(2)
*
- * For negative values of q in (-400,0), we have that
+ * For negative values of q in (-400,0), we have that
* f = (((152170 + 65536) * q ) >> 16);
- * is equal to
+ * is equal to
* -ceil(p) + q
* where
* p = log(5**-q)/log(2) = -q * log(5)/log(2)
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 3959ba0ebd..f469f6b553 100644
--- a/contrib/restricted/fast_float/include/fast_float/digit_comparison.h
+++ b/contrib/restricted/fast_float/include/fast_float/digit_comparison.h
@@ -23,8 +23,9 @@ constexpr static uint64_t powers_of_ten_uint64[] = {
// this algorithm is not even close to optimized, but it has no practical
// effect on performance: in order to have a faster algorithm, we'd need
// to slow down performance for faster algorithms, and this is still fast.
+template <typename UC>
fastfloat_really_inline FASTFLOAT_CONSTEXPR14
-int32_t scientific_exponent(parsed_number_string& num) noexcept {
+int32_t scientific_exponent(parsed_number_string_t<UC> & num) noexcept {
uint64_t mantissa = num.mantissa;
int32_t exponent = int32_t(num.exponent);
while (mantissa >= 10000) {
@@ -153,19 +154,19 @@ void round_down(adjusted_mantissa& am, int32_t shift) noexcept {
}
am.power2 += shift;
}
-
+template <typename UC>
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
-void skip_zeros(const char*& first, const char* last) noexcept {
+void skip_zeros(UC const * & first, UC const * last) noexcept {
uint64_t val;
- while (!cpp20_and_in_constexpr() && std::distance(first, last) >= 8) {
+ while (!cpp20_and_in_constexpr() && std::distance(first, last) >= int_cmp_len<UC>()) {
::memcpy(&val, first, sizeof(uint64_t));
- if (val != 0x3030303030303030) {
+ if (val != int_cmp_zeros<UC>()) {
break;
}
- first += 8;
+ first += int_cmp_len<UC>();
}
while (first != last) {
- if (*first != '0') {
+ if (*first != UC('0')) {
break;
}
first++;
@@ -174,32 +175,43 @@ void skip_zeros(const char*& first, const char* last) noexcept {
// determine if any non-zero digits were truncated.
// all characters must be valid digits.
+template <typename UC>
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
-bool is_truncated(const char* first, const char* last) noexcept {
+bool is_truncated(UC const * first, UC const * last) noexcept {
// do 8-bit optimizations, can just compare to 8 literal 0s.
uint64_t val;
- while (!cpp20_and_in_constexpr() && std::distance(first, last) >= 8) {
+ while (!cpp20_and_in_constexpr() && std::distance(first, last) >= int_cmp_len<UC>()) {
::memcpy(&val, first, sizeof(uint64_t));
- if (val != 0x3030303030303030) {
+ if (val != int_cmp_zeros<UC>()) {
return true;
}
- first += 8;
+ first += int_cmp_len<UC>();
}
while (first != last) {
- if (*first != '0') {
+ if (*first != UC('0')) {
return true;
}
- first++;
+ ++first;
}
return false;
}
-
+template <typename UC>
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
-bool is_truncated(byte_span s) noexcept {
+bool is_truncated(span<const UC> s) noexcept {
return is_truncated(s.ptr, s.ptr + s.len());
}
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
+void parse_eight_digits(const char16_t*& , limb& , size_t& , size_t& ) noexcept {
+ // currently unused
+}
+
+fastfloat_really_inline FASTFLOAT_CONSTEXPR20
+void parse_eight_digits(const char32_t*& , limb& , size_t& , size_t& ) noexcept {
+ // currently unused
+}
+
+fastfloat_really_inline FASTFLOAT_CONSTEXPR20
void parse_eight_digits(const char*& p, limb& value, size_t& counter, size_t& count) noexcept {
value = value * 100000000 + parse_eight_digits_unrolled(p);
p += 8;
@@ -207,9 +219,10 @@ void parse_eight_digits(const char*& p, limb& value, size_t& counter, size_t& co
count += 8;
}
+template <typename UC>
fastfloat_really_inline FASTFLOAT_CONSTEXPR14
-void parse_one_digit(const char*& p, limb& value, size_t& counter, size_t& count) noexcept {
- value = value * 10 + limb(*p - '0');
+void parse_one_digit(UC const *& p, limb& value, size_t& counter, size_t& count) noexcept {
+ value = value * 10 + limb(*p - UC('0'));
p++;
counter++;
count++;
@@ -230,8 +243,9 @@ void round_up_bigint(bigint& big, size_t& count) noexcept {
}
// parse the significant digits into a big integer
+template <typename UC>
inline FASTFLOAT_CONSTEXPR20
-void parse_mantissa(bigint& result, parsed_number_string& num, size_t max_digits, size_t& digits) noexcept {
+void parse_mantissa(bigint& result, parsed_number_string_t<UC>& num, size_t max_digits, size_t& digits) noexcept {
// try to minimize the number of big integer and scalar multiplication.
// therefore, try to parse 8 digits at a time, and multiply by the largest
// scalar value (9 or 19 digits) for each step.
@@ -245,13 +259,15 @@ void parse_mantissa(bigint& result, parsed_number_string& num, size_t max_digits
#endif
// process all integer digits.
- const char* p = num.integer.ptr;
- const char* pend = p + num.integer.len();
+ UC const * p = num.integer.ptr;
+ UC const * pend = p + num.integer.len();
skip_zeros(p, pend);
// process all digits, in increments of step per loop
while (p != pend) {
- while ((std::distance(p, pend) >= 8) && (step - counter >= 8) && (max_digits - digits >= 8)) {
- parse_eight_digits(p, value, counter, digits);
+ if (std::is_same<UC,char>::value) {
+ while ((std::distance(p, pend) >= 8) && (step - counter >= 8) && (max_digits - digits >= 8)) {
+ parse_eight_digits(p, value, counter, digits);
+ }
}
while (counter < step && p != pend && digits < max_digits) {
parse_one_digit(p, value, counter, digits);
@@ -283,8 +299,10 @@ void parse_mantissa(bigint& result, parsed_number_string& num, size_t max_digits
}
// process all digits, in increments of step per loop
while (p != pend) {
- while ((std::distance(p, pend) >= 8) && (step - counter >= 8) && (max_digits - digits >= 8)) {
- parse_eight_digits(p, value, counter, digits);
+ if (std::is_same<UC,char>::value) {
+ while ((std::distance(p, pend) >= 8) && (step - counter >= 8) && (max_digits - digits >= 8)) {
+ parse_eight_digits(p, value, counter, digits);
+ }
}
while (counter < step && p != pend && digits < max_digits) {
parse_one_digit(p, value, counter, digits);
@@ -395,9 +413,9 @@ adjusted_mantissa negative_digit_comp(bigint& bigmant, adjusted_mantissa am, int
// `b` as a big-integer type, scaled to the same binary exponent as
// the actual digits. we then compare the big integer representations
// of both, and use that to direct rounding.
-template <typename T>
+template <typename T, typename UC>
inline FASTFLOAT_CONSTEXPR20
-adjusted_mantissa digit_comp(parsed_number_string& num, adjusted_mantissa am) noexcept {
+adjusted_mantissa digit_comp(parsed_number_string_t<UC>& num, adjusted_mantissa am) noexcept {
// remove the invalid exponent bias
am.power2 -= invalid_am_bias;
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 65704da4b5..04efa877ee 100644
--- a/contrib/restricted/fast_float/include/fast_float/fast_float.h
+++ b/contrib/restricted/fast_float/include/fast_float/fast_float.h
@@ -1,35 +1,10 @@
+
#ifndef FASTFLOAT_FAST_FLOAT_H
#define FASTFLOAT_FAST_FLOAT_H
-#include <system_error>
-
-#include "constexpr_feature_detect.h"
+#include "float_common.h"
namespace fast_float {
-enum chars_format {
- scientific = 1<<0,
- fixed = 1<<2,
- hex = 1<<3,
- general = fixed | scientific
-};
-
-
-struct from_chars_result {
- const char *ptr;
- std::errc ec;
-};
-
-struct parse_options {
- constexpr explicit parse_options(chars_format fmt = chars_format::general,
- char dot = '.')
- : format(fmt), decimal_point(dot) {}
-
- /** Which number formats are accepted */
- chars_format format;
- /** The character used as decimal point */
- char decimal_point;
-};
-
/**
* This function parses the character sequence [first,last) for a number. It parses floating-point numbers expecting
* a locale-indepent format equivalent to what is used by std::strtod in the default ("C") locale.
@@ -49,18 +24,18 @@ struct parse_options {
* 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>
+template<typename T, typename UC = char>
FASTFLOAT_CONSTEXPR20
-from_chars_result from_chars(const char *first, const char *last,
+from_chars_result_t<UC> from_chars(UC const * first, UC const * last,
T &value, chars_format fmt = chars_format::general) noexcept;
/**
* Like from_chars, but accepts an `options` argument to govern number parsing.
*/
-template<typename T>
+template<typename T, typename UC = char>
FASTFLOAT_CONSTEXPR20
-from_chars_result from_chars_advanced(const char *first, const char *last,
- T &value, parse_options options) noexcept;
+from_chars_result_t<UC> from_chars_advanced(UC const * first, UC const * last,
+ T &value, parse_options_t<UC> options) 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 c878486b9a..2465ea66a0 100644
--- a/contrib/restricted/fast_float/include/fast_float/float_common.h
+++ b/contrib/restricted/fast_float/include/fast_float/float_common.h
@@ -6,6 +6,40 @@
#include <cassert>
#include <cstring>
#include <type_traits>
+#include <system_error>
+
+#include "constexpr_feature_detect.h"
+
+namespace fast_float {
+
+enum chars_format {
+ scientific = 1 << 0,
+ fixed = 1 << 2,
+ hex = 1 << 3,
+ general = fixed | scientific
+};
+
+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 {
+ constexpr explicit parse_options_t(chars_format fmt = chars_format::general,
+ UC dot = UC('.'))
+ : format(fmt), decimal_point(dot) {}
+
+ /** Which number formats are accepted */
+ chars_format format;
+ /** The character used as decimal point */
+ UC decimal_point;
+};
+using parse_options = parse_options_t<char>;
+
+}
#if FASTFLOAT_HAS_BIT_CAST
#include <bit>
@@ -106,11 +140,12 @@ fastfloat_really_inline constexpr bool cpp20_and_in_constexpr() {
}
// Compares two ASCII strings in a case insensitive manner.
+template <typename UC>
inline FASTFLOAT_CONSTEXPR14 bool
-fastfloat_strncasecmp(const char *input1, const char *input2, size_t length) {
+fastfloat_strncasecmp(UC const * input1, UC const * input2, size_t length) {
char running_diff{0};
- for (size_t i = 0; i < length; i++) {
- running_diff |= (input1[i] ^ input2[i]);
+ for (size_t i = 0; i < length; ++i) {
+ running_diff |= (char(input1[i]) ^ char(input2[i]));
}
return (running_diff == 0) || (running_diff == 32);
}
@@ -251,16 +286,43 @@ struct adjusted_mantissa {
// Bias so we can get the real exponent with an invalid adjusted_mantissa.
constexpr static int32_t invalid_am_bias = -0x8000;
-constexpr static double powers_of_ten_double[] = {
- 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11,
- 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22};
-constexpr static float powers_of_ten_float[] = {1e0f, 1e1f, 1e2f, 1e3f, 1e4f, 1e5f,
- 1e6f, 1e7f, 1e8f, 1e9f, 1e10f};
-// used for max_mantissa_double and max_mantissa_float
+// used for binary_format_lookup_tables<T>::max_mantissa
constexpr uint64_t constant_55555 = 5 * 5 * 5 * 5 * 5;
-// Largest integer value v so that (5**index * v) <= 1<<53.
-// 0x10000000000000 == 1 << 53
-constexpr static uint64_t max_mantissa_double[] = {
+
+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 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 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();
+};
+
+template <typename U>
+struct binary_format_lookup_tables<double, U> {
+ static constexpr double powers_of_ten[] = {
+ 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11,
+ 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22};
+
+ // Largest integer value v so that (5**index * v) <= 1<<53.
+ // 0x10000000000000 == 1 << 53
+ static constexpr uint64_t max_mantissa[] = {
0x10000000000000,
0x10000000000000 / 5,
0x10000000000000 / (5 * 5),
@@ -285,44 +347,42 @@ constexpr static uint64_t max_mantissa_double[] = {
0x10000000000000 / (constant_55555 * constant_55555 * constant_55555 * constant_55555 * 5 * 5),
0x10000000000000 / (constant_55555 * constant_55555 * constant_55555 * constant_55555 * 5 * 5 * 5),
0x10000000000000 / (constant_55555 * constant_55555 * constant_55555 * constant_55555 * 5 * 5 * 5 * 5)};
+};
+
+template <typename U>
+constexpr double binary_format_lookup_tables<double, U>::powers_of_ten[];
+
+template <typename U>
+constexpr uint64_t binary_format_lookup_tables<double, U>::max_mantissa[];
+
+template <typename U>
+struct binary_format_lookup_tables<float, U> {
+ static constexpr float powers_of_ten[] = {1e0f, 1e1f, 1e2f, 1e3f, 1e4f, 1e5f,
+ 1e6f, 1e7f, 1e8f, 1e9f, 1e10f};
+
// Largest integer value v so that (5**index * v) <= 1<<24.
// 0x1000000 == 1<<24
- constexpr static uint64_t max_mantissa_float[] = {
- 0x1000000,
- 0x1000000 / 5,
- 0x1000000 / (5 * 5),
- 0x1000000 / (5 * 5 * 5),
- 0x1000000 / (5 * 5 * 5 * 5),
- 0x1000000 / (constant_55555),
- 0x1000000 / (constant_55555 * 5),
- 0x1000000 / (constant_55555 * 5 * 5),
- 0x1000000 / (constant_55555 * 5 * 5 * 5),
- 0x1000000 / (constant_55555 * 5 * 5 * 5 * 5),
- 0x1000000 / (constant_55555 * constant_55555),
- 0x1000000 / (constant_55555 * constant_55555 * 5)};
-
-template <typename T> struct binary_format {
- 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 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 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 uint64_t max_mantissa[] = {
+ 0x1000000,
+ 0x1000000 / 5,
+ 0x1000000 / (5 * 5),
+ 0x1000000 / (5 * 5 * 5),
+ 0x1000000 / (5 * 5 * 5 * 5),
+ 0x1000000 / (constant_55555),
+ 0x1000000 / (constant_55555 * 5),
+ 0x1000000 / (constant_55555 * 5 * 5),
+ 0x1000000 / (constant_55555 * 5 * 5 * 5),
+ 0x1000000 / (constant_55555 * 5 * 5 * 5 * 5),
+ 0x1000000 / (constant_55555 * constant_55555),
+ 0x1000000 / (constant_55555 * constant_55555 * 5)};
};
+template <typename U>
+constexpr float binary_format_lookup_tables<float, U>::powers_of_ten[];
+
+template <typename U>
+constexpr uint64_t binary_format_lookup_tables<float, U>::max_mantissa[];
+
template <> inline constexpr int binary_format<double>::min_exponent_fast_path() {
#if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0)
return 0;
@@ -385,6 +445,7 @@ template <> inline constexpr int binary_format<double>::max_exponent_fast_path()
template <> inline constexpr int binary_format<float>::max_exponent_fast_path() {
return 10;
}
+
template <> inline constexpr uint64_t binary_format<double>::max_mantissa_fast_path() {
return uint64_t(2) << mantissa_explicit_bits();
}
@@ -392,7 +453,8 @@ template <> inline constexpr uint64_t binary_format<double>::max_mantissa_fast_p
// caller is responsible to ensure that
// power >= 0 && power <= 22
//
- return max_mantissa_double[power];
+ // 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() {
return uint64_t(2) << mantissa_explicit_bits();
@@ -401,17 +463,19 @@ template <> inline constexpr uint64_t binary_format<float>::max_mantissa_fast_pa
// caller is responsible to ensure that
// power >= 0 && power <= 10
//
- return max_mantissa_float[power];
+ // Work around clang bug https://godbolt.org/z/zedh7rrhc
+ return (void)max_mantissa[0], max_mantissa[power];
}
template <>
inline constexpr double binary_format<double>::exact_power_of_ten(int64_t power) {
- return powers_of_ten_double[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) {
-
- return powers_of_ten_float[power];
+ // Work around clang bug https://godbolt.org/z/zedh7rrhc
+ return (void)powers_of_ten[0], powers_of_ten[power];
}
@@ -481,7 +545,7 @@ void to_float(bool negative, adjusted_mantissa am, T &value) {
#endif
}
-#if FASTFLOAT_SKIP_WHITE_SPACE // disabled by default
+#ifdef FASTFLOAT_SKIP_WHITE_SPACE // disabled by default
template <typename = void>
struct space_lut {
static constexpr bool value[] = {
@@ -503,6 +567,68 @@ constexpr bool space_lut<T>::value[];
inline constexpr bool is_space(uint8_t c) { return space_lut<>::value[c]; }
#endif
+
+template<typename UC>
+static constexpr uint64_t int_cmp_zeros()
+{
+ static_assert((sizeof(UC) == 1) || (sizeof(UC) == 2) || (sizeof(UC) == 4), "Unsupported character size");
+ return (sizeof(UC) == 1) ? 0x3030303030303030 : (sizeof(UC) == 2) ? (uint64_t(UC('0')) << 48 | uint64_t(UC('0')) << 32 | 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<>
+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;
+}
+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";
+}
} // 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 6e4f6eb833..4541d70262 100644
--- a/contrib/restricted/fast_float/include/fast_float/parse_number.h
+++ b/contrib/restricted/fast_float/include/fast_float/parse_number.h
@@ -4,6 +4,7 @@
#include "ascii_number.h"
#include "decimal_to_binary.h"
#include "digit_comparison.h"
+#include "float_common.h"
#include <cmath>
#include <cstring>
@@ -19,41 +20,41 @@ namespace detail {
* The case comparisons could be made much faster given that we know that the
* strings a null-free and fixed.
**/
-template <typename T>
-from_chars_result FASTFLOAT_CONSTEXPR14
-parse_infnan(const char *first, const char *last, T &value) noexcept {
- from_chars_result answer{};
+template <typename T, typename UC>
+from_chars_result_t<UC> FASTFLOAT_CONSTEXPR14
+parse_infnan(UC const * first, UC const * last, T &value) noexcept {
+ from_chars_result_t<UC> answer{};
answer.ptr = first;
answer.ec = std::errc(); // be optimistic
bool minusSign = false;
- if (*first == '-') { // assume first < last, so dereference without checks; C++17 20.19.3.(7.1) explicitly forbids '+' here
+ if (*first == UC('-')) { // assume first < last, so dereference without checks; C++17 20.19.3.(7.1) explicitly forbids '+' here
minusSign = true;
++first;
}
-#if FASTFLOAT_ALLOWS_LEADING_PLUS // disabled by default
- if (*first == '+') {
+#ifdef FASTFLOAT_ALLOWS_LEADING_PLUS // disabled by default
+ if (*first == UC('+')) {
++first;
}
#endif
if (last - first >= 3) {
- if (fastfloat_strncasecmp(first, "nan", 3)) {
+ if (fastfloat_strncasecmp(first, str_const_nan<UC>(), 3)) {
answer.ptr = (first += 3);
value = minusSign ? -std::numeric_limits<T>::quiet_NaN() : std::numeric_limits<T>::quiet_NaN();
// Check for possible nan(n-char-seq-opt), C++17 20.19.3.7, C11 7.20.1.3.3. At least MSVC produces nan(ind) and nan(snan).
- if(first != last && *first == '(') {
- for(const char* ptr = first + 1; ptr != last; ++ptr) {
- if (*ptr == ')') {
+ if(first != last && *first == UC('(')) {
+ for(UC const * ptr = first + 1; ptr != last; ++ptr) {
+ if (*ptr == UC(')')) {
answer.ptr = ptr + 1; // valid nan(n-char-seq-opt)
break;
}
- else if(!(('a' <= *ptr && *ptr <= 'z') || ('A' <= *ptr && *ptr <= 'Z') || ('0' <= *ptr && *ptr <= '9') || *ptr == '_'))
+ else if(!((UC('a') <= *ptr && *ptr <= UC('z')) || (UC('A') <= *ptr && *ptr <= UC('Z')) || (UC('0') <= *ptr && *ptr <= UC('9')) || *ptr == UC('_')))
break; // forbidden char, not nan(n-char-seq-opt)
}
}
return answer;
}
- if (fastfloat_strncasecmp(first, "inf", 3)) {
- if ((last - first >= 8) && fastfloat_strncasecmp(first + 3, "inity", 5)) {
+ if (fastfloat_strncasecmp(first, str_const_inf<UC>(), 3)) {
+ if ((last - first >= 8) && fastfloat_strncasecmp(first + 3, str_const_inf<UC>() + 3, 5)) {
answer.ptr = first + 8;
} else {
answer.ptr = first + 3;
@@ -109,7 +110,7 @@ fastfloat_really_inline bool rounds_to_nearest() noexcept {
//
// Note: This may fail to be accurate if fast-math has been
// enabled, as rounding conventions may not apply.
- #if FASTFLOAT_VISUAL_STUDIO
+ #ifdef FASTFLOAT_VISUAL_STUDIO
# pragma warning(push)
// todo: is there a VS warning?
// see https://stackoverflow.com/questions/46079446/is-there-a-warning-for-floating-point-equality-checking-in-visual-studio-2013
@@ -121,7 +122,7 @@ fastfloat_really_inline bool rounds_to_nearest() noexcept {
# pragma GCC diagnostic ignored "-Wfloat-equal"
#endif
return (fmini + 1.0f == 1.0f - fmini);
- #if FASTFLOAT_VISUAL_STUDIO
+ #ifdef FASTFLOAT_VISUAL_STUDIO
# pragma warning(pop)
#elif defined(__clang__)
# pragma clang diagnostic pop
@@ -132,23 +133,26 @@ fastfloat_really_inline bool rounds_to_nearest() noexcept {
} // namespace detail
-template<typename T>
+template<typename T, typename UC>
FASTFLOAT_CONSTEXPR20
-from_chars_result from_chars(const char *first, const char *last,
+from_chars_result_t<UC> from_chars(UC const * first, UC const * last,
T &value, chars_format fmt /*= chars_format::general*/) noexcept {
- return from_chars_advanced(first, last, value, parse_options{fmt});
+ return from_chars_advanced(first, last, value, parse_options_t<UC>{fmt});
}
-template<typename T>
+template<typename T, typename UC>
FASTFLOAT_CONSTEXPR20
-from_chars_result from_chars_advanced(const char *first, const char *last,
- T &value, parse_options options) noexcept {
+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");
-
- from_chars_result answer;
-#if FASTFLOAT_SKIP_WHITE_SPACE // disabled by default
+ 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++;
}
@@ -158,7 +162,7 @@ from_chars_result from_chars_advanced(const char *first, const char *last,
answer.ptr = first;
return answer;
}
- parsed_number_string pns = parse_number_string(first, last, options);
+ parsed_number_string_t<UC> pns = parse_number_string<UC>(first, last, options);
if (!pns.valid) {
return detail::parse_infnan(first, last, value);
}