|
@@ -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
|