mirror of
https://github.com/PCSX2/pcsx2.git
synced 2025-12-16 04:08:48 +00:00
3rdparty: Update fast_float to v8.1.0
Signed-off-by: SternXD <stern@sidestore.io>
This commit is contained in:
parent
98c74b939a
commit
746174d73d
70
3rdparty/fast_float/README.md
vendored
70
3rdparty/fast_float/README.md
vendored
@ -57,6 +57,7 @@ Example:
|
|||||||
```C++
|
```C++
|
||||||
#include "fast_float/fast_float.h"
|
#include "fast_float/fast_float.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
std::string input = "3.1416 xyz ";
|
std::string input = "3.1416 xyz ";
|
||||||
@ -68,6 +69,25 @@ int main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Though the C++17 standard has you do a comparison with `std::errc()` to check whether the conversion worked, you can avoid it by casting the result to a `bool` like so:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include "fast_float/fast_float.h"
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
std::string input = "3.1416 xyz ";
|
||||||
|
double result;
|
||||||
|
if(auto answer = fast_float::from_chars(input.data(), input.data() + input.size(), result)) {
|
||||||
|
std::cout << "parsed the number " << result << std::endl;
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
std::cerr << "failed to parse " << result << std::endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
You can parse delimited numbers:
|
You can parse delimited numbers:
|
||||||
|
|
||||||
```C++
|
```C++
|
||||||
@ -357,6 +377,34 @@ int main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Multiplication of an integer by a power of 10
|
||||||
|
An integer `W` can be multiplied by a power of ten `10^Q` and
|
||||||
|
converted to `double` with correctly rounded value
|
||||||
|
(in "round to nearest, tie to even" fashion) using
|
||||||
|
`fast_float::integer_times_pow10()`, e.g.:
|
||||||
|
```C++
|
||||||
|
const uint64_t W = 12345678901234567;
|
||||||
|
const int Q = 23;
|
||||||
|
const double result = fast_float::integer_times_pow10(W, Q);
|
||||||
|
std::cout.precision(17);
|
||||||
|
std::cout << W << " * 10^" << Q << " = " << result << " ("
|
||||||
|
<< (result == 12345678901234567e23 ? "==" : "!=") << "expected)\n";
|
||||||
|
```
|
||||||
|
outputs
|
||||||
|
```
|
||||||
|
12345678901234567 * 10^23 = 1.2345678901234567e+39 (==expected)
|
||||||
|
```
|
||||||
|
`fast_float::integer_times_pow10()` gives the same result as
|
||||||
|
using `fast_float::from_chars()` when parsing the string `"WeQ"`
|
||||||
|
(in this example `"12345678901234567e23"`),
|
||||||
|
except `fast_float::integer_times_pow10()` does not report out-of-range errors, and
|
||||||
|
underflows to zero or overflows to infinity when the resulting value is
|
||||||
|
out of range.
|
||||||
|
|
||||||
|
Overloads of `fast_float::integer_times_pow10()` are provided for
|
||||||
|
signed and unsigned integer types: `int64_t`, `uint64_t`, etc.
|
||||||
|
|
||||||
|
|
||||||
## Users and Related Work
|
## Users and Related Work
|
||||||
|
|
||||||
The fast_float library is part of:
|
The fast_float library is part of:
|
||||||
@ -364,6 +412,8 @@ The fast_float library is part of:
|
|||||||
* GCC (as of version 12): the `from_chars` function in GCC relies on fast_float,
|
* GCC (as of version 12): the `from_chars` function in GCC relies on fast_float,
|
||||||
* [Chromium](https://github.com/Chromium/Chromium), the engine behind Google
|
* [Chromium](https://github.com/Chromium/Chromium), the engine behind Google
|
||||||
Chrome, Microsoft Edge, and Opera,
|
Chrome, Microsoft Edge, and Opera,
|
||||||
|
* Boost JSON, MySQL, etc.
|
||||||
|
* Blender
|
||||||
* [WebKit](https://github.com/WebKit/WebKit), the engine behind Safari (Apple's
|
* [WebKit](https://github.com/WebKit/WebKit), the engine behind Safari (Apple's
|
||||||
web browser),
|
web browser),
|
||||||
* [DuckDB](https://duckdb.org),
|
* [DuckDB](https://duckdb.org),
|
||||||
@ -376,7 +426,10 @@ The fast_float library is part of:
|
|||||||
The fastfloat algorithm is part of the [LLVM standard
|
The fastfloat algorithm is part of the [LLVM standard
|
||||||
libraries](https://github.com/llvm/llvm-project/commit/87c016078ad72c46505461e4ff8bfa04819fe7ba).
|
libraries](https://github.com/llvm/llvm-project/commit/87c016078ad72c46505461e4ff8bfa04819fe7ba).
|
||||||
There is a [derived implementation part of
|
There is a [derived implementation part of
|
||||||
AdaCore](https://github.com/AdaCore/VSS).
|
AdaCore](https://github.com/AdaCore/VSS). The [SerenityOS operating
|
||||||
|
system](https://github.com/SerenityOS/serenity/commit/53b7f5e6a11e663c83df8030c3171c5945cb75ec)
|
||||||
|
has a derived implementation that is inherited by the [Ladybird
|
||||||
|
Browser](https://github.com/LadybirdBrowser/ladybird).
|
||||||
|
|
||||||
The fast_float library provides a performance similar to that of the
|
The fast_float library provides a performance similar to that of the
|
||||||
[fast_double_parser](https://github.com/lemire/fast_double_parser) library but
|
[fast_double_parser](https://github.com/lemire/fast_double_parser) library but
|
||||||
@ -385,6 +438,14 @@ API more in line with the expectations of C++ programmers. The
|
|||||||
fast_double_parser library is part of the [Microsoft LightGBM machine-learning
|
fast_double_parser library is part of the [Microsoft LightGBM machine-learning
|
||||||
framework](https://github.com/microsoft/LightGBM).
|
framework](https://github.com/microsoft/LightGBM).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Packages
|
||||||
|
------
|
||||||
|
|
||||||
|
[](https://repology.org/project/fastfloat/versions)
|
||||||
|
|
||||||
|
|
||||||
## References
|
## References
|
||||||
|
|
||||||
* Daniel Lemire, [Number Parsing at a Gigabyte per
|
* Daniel Lemire, [Number Parsing at a Gigabyte per
|
||||||
@ -455,7 +516,7 @@ sufficiently recent version of CMake (3.11 or better at least):
|
|||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
fast_float
|
fast_float
|
||||||
GIT_REPOSITORY https://github.com/fastfloat/fast_float.git
|
GIT_REPOSITORY https://github.com/fastfloat/fast_float.git
|
||||||
GIT_TAG tags/v8.0.2
|
GIT_TAG tags/v8.1.0
|
||||||
GIT_SHALLOW TRUE)
|
GIT_SHALLOW TRUE)
|
||||||
|
|
||||||
FetchContent_MakeAvailable(fast_float)
|
FetchContent_MakeAvailable(fast_float)
|
||||||
@ -471,7 +532,7 @@ You may also use [CPM](https://github.com/cpm-cmake/CPM.cmake), like so:
|
|||||||
CPMAddPackage(
|
CPMAddPackage(
|
||||||
NAME fast_float
|
NAME fast_float
|
||||||
GITHUB_REPOSITORY "fastfloat/fast_float"
|
GITHUB_REPOSITORY "fastfloat/fast_float"
|
||||||
GIT_TAG v8.0.2)
|
GIT_TAG v8.1.0)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Using as single header
|
## Using as single header
|
||||||
@ -483,7 +544,7 @@ if desired as described in the command line help.
|
|||||||
|
|
||||||
You may directly download automatically generated single-header files:
|
You may directly download automatically generated single-header files:
|
||||||
|
|
||||||
<https://github.com/fastfloat/fast_float/releases/download/v8.0.2/fast_float.h>
|
<https://github.com/fastfloat/fast_float/releases/download/v8.1.0/fast_float.h>
|
||||||
|
|
||||||
## Benchmarking
|
## Benchmarking
|
||||||
|
|
||||||
@ -522,6 +583,7 @@ cmake --build build
|
|||||||
manager](https://conan.io/center/recipes/fast_float).
|
manager](https://conan.io/center/recipes/fast_float).
|
||||||
* It is part of the [brew package
|
* It is part of the [brew package
|
||||||
manager](https://formulae.brew.sh/formula/fast_float).
|
manager](https://formulae.brew.sh/formula/fast_float).
|
||||||
|
* fast_float is available on [xmake](https://xmake.io) repository.
|
||||||
* Some Linux distribution like Fedora include fast_float (e.g., as
|
* Some Linux distribution like Fedora include fast_float (e.g., as
|
||||||
`fast_float-devel`).
|
`fast_float-devel`).
|
||||||
|
|
||||||
|
|||||||
@ -441,7 +441,7 @@ parse_number_string(UC const *p, UC const *pend,
|
|||||||
if (digit_count > 19) {
|
if (digit_count > 19) {
|
||||||
answer.too_many_digits = true;
|
answer.too_many_digits = true;
|
||||||
// Let us start again, this time, avoiding overflows.
|
// Let us start again, this time, avoiding overflows.
|
||||||
// We don't need to check if is_integer, since we use the
|
// We don't need to call if is_integer, since we use the
|
||||||
// pre-tokenized spans from above.
|
// pre-tokenized spans from above.
|
||||||
i = 0;
|
i = 0;
|
||||||
p = answer.integer.ptr;
|
p = answer.integer.ptr;
|
||||||
@ -451,7 +451,7 @@ parse_number_string(UC const *p, UC const *pend,
|
|||||||
i = i * 10 + uint64_t(*p - UC('0'));
|
i = i * 10 + uint64_t(*p - UC('0'));
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
if (i >= minimal_nineteen_digit_integer) { // We have a big integers
|
if (i >= minimal_nineteen_digit_integer) { // We have a big integer
|
||||||
exponent = end_of_integer_part - p + exp_number;
|
exponent = end_of_integer_part - p + exp_number;
|
||||||
} else { // We have a value with a fractional component.
|
} else { // We have a value with a fractional component.
|
||||||
p = answer.fraction.ptr;
|
p = answer.fraction.ptr;
|
||||||
|
|||||||
@ -45,6 +45,24 @@ FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
|
|||||||
from_chars_advanced(UC const *first, UC const *last, T &value,
|
from_chars_advanced(UC const *first, UC const *last, T &value,
|
||||||
parse_options_t<UC> options) noexcept;
|
parse_options_t<UC> options) noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function multiplies an integer number by a power of 10 and returns
|
||||||
|
* the result as a double precision floating-point value that is correctly
|
||||||
|
* rounded. The resulting floating-point value is the closest floating-point
|
||||||
|
* value, using the "round to nearest, tie to even" convention for values that
|
||||||
|
* would otherwise fall right in-between two values. That is, we provide exact
|
||||||
|
* conversion according to the IEEE standard.
|
||||||
|
*
|
||||||
|
* On overflow infinity is returned, on underflow 0 is returned.
|
||||||
|
*
|
||||||
|
* The implementation does not throw and does not allocate memory (e.g., with
|
||||||
|
* `new` or `malloc`).
|
||||||
|
*/
|
||||||
|
FASTFLOAT_CONSTEXPR20 inline double
|
||||||
|
integer_times_pow10(uint64_t mantissa, int decimal_exponent) noexcept;
|
||||||
|
FASTFLOAT_CONSTEXPR20 inline double
|
||||||
|
integer_times_pow10(int64_t mantissa, int decimal_exponent) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* from_chars for integer types.
|
* from_chars for integer types.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -16,8 +16,8 @@
|
|||||||
#include "constexpr_feature_detect.h"
|
#include "constexpr_feature_detect.h"
|
||||||
|
|
||||||
#define FASTFLOAT_VERSION_MAJOR 8
|
#define FASTFLOAT_VERSION_MAJOR 8
|
||||||
#define FASTFLOAT_VERSION_MINOR 0
|
#define FASTFLOAT_VERSION_MINOR 1
|
||||||
#define FASTFLOAT_VERSION_PATCH 2
|
#define FASTFLOAT_VERSION_PATCH 0
|
||||||
|
|
||||||
#define FASTFLOAT_STRINGIZE_IMPL(x) #x
|
#define FASTFLOAT_STRINGIZE_IMPL(x) #x
|
||||||
#define FASTFLOAT_STRINGIZE(x) FASTFLOAT_STRINGIZE_IMPL(x)
|
#define FASTFLOAT_STRINGIZE(x) FASTFLOAT_STRINGIZE_IMPL(x)
|
||||||
@ -58,6 +58,11 @@ enum class chars_format : uint64_t {
|
|||||||
template <typename UC> struct from_chars_result_t {
|
template <typename UC> struct from_chars_result_t {
|
||||||
UC const *ptr;
|
UC const *ptr;
|
||||||
std::errc ec;
|
std::errc ec;
|
||||||
|
|
||||||
|
// https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2497r0.html
|
||||||
|
constexpr explicit operator bool() const noexcept {
|
||||||
|
return ec == std::errc();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
using from_chars_result = from_chars_result_t<char>;
|
using from_chars_result = from_chars_result_t<char>;
|
||||||
@ -88,11 +93,12 @@ using parse_options = parse_options_t<char>;
|
|||||||
defined(__MINGW64__) || defined(__s390x__) || \
|
defined(__MINGW64__) || defined(__s390x__) || \
|
||||||
(defined(__ppc64__) || defined(__PPC64__) || defined(__ppc64le__) || \
|
(defined(__ppc64__) || defined(__PPC64__) || defined(__ppc64le__) || \
|
||||||
defined(__PPC64LE__)) || \
|
defined(__PPC64LE__)) || \
|
||||||
defined(__loongarch64))
|
defined(__loongarch64) || (defined(__riscv) && __riscv_xlen == 64))
|
||||||
#define FASTFLOAT_64BIT 1
|
#define FASTFLOAT_64BIT 1
|
||||||
#elif (defined(__i386) || defined(__i386__) || defined(_M_IX86) || \
|
#elif (defined(__i386) || defined(__i386__) || defined(_M_IX86) || \
|
||||||
defined(__arm__) || defined(_M_ARM) || defined(__ppc__) || \
|
defined(__arm__) || defined(_M_ARM) || defined(__ppc__) || \
|
||||||
defined(__MINGW32__) || defined(__EMSCRIPTEN__))
|
defined(__MINGW32__) || defined(__EMSCRIPTEN__) || \
|
||||||
|
(defined(__riscv) && __riscv_xlen == 32))
|
||||||
#define FASTFLOAT_32BIT 1
|
#define FASTFLOAT_32BIT 1
|
||||||
#else
|
#else
|
||||||
// Need to check incrementally, since SIZE_MAX is a size_t, avoid overflow.
|
// Need to check incrementally, since SIZE_MAX is a size_t, avoid overflow.
|
||||||
@ -1126,7 +1132,12 @@ template <typename T> constexpr uint64_t int_luts<T>::min_safe_u64[];
|
|||||||
|
|
||||||
template <typename UC>
|
template <typename UC>
|
||||||
fastfloat_really_inline constexpr uint8_t ch_to_digit(UC c) {
|
fastfloat_really_inline constexpr uint8_t ch_to_digit(UC c) {
|
||||||
return int_luts<>::chdigit[static_cast<unsigned char>(c)];
|
// wchar_t and char can be signed, so we need to be careful.
|
||||||
|
using UnsignedUC = typename std::make_unsigned<UC>::type;
|
||||||
|
return int_luts<>::chdigit[static_cast<unsigned char>(
|
||||||
|
static_cast<UnsignedUC>(c) &
|
||||||
|
static_cast<UnsignedUC>(
|
||||||
|
-((static_cast<UnsignedUC>(c) & ~0xFFull) == 0)))];
|
||||||
}
|
}
|
||||||
|
|
||||||
fastfloat_really_inline constexpr size_t max_digits_u64(int base) {
|
fastfloat_really_inline constexpr size_t max_digits_u64(int base) {
|
||||||
|
|||||||
@ -188,32 +188,17 @@ from_chars(UC const *first, UC const *last, T &value,
|
|||||||
parse_options_t<UC>(fmt));
|
parse_options_t<UC>(fmt));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
template <typename T>
|
||||||
* This function overload takes parsed_number_string_t structure that is created
|
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 bool
|
||||||
* and populated either by from_chars_advanced function taking chars range and
|
clinger_fast_path_impl(uint64_t mantissa, int64_t exponent, bool is_negative,
|
||||||
* parsing options or other parsing custom function implemented by user.
|
T &value) noexcept {
|
||||||
*/
|
|
||||||
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>::value,
|
|
||||||
"only some floating-point types are supported");
|
|
||||||
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;
|
|
||||||
|
|
||||||
answer.ec = std::errc(); // be optimistic
|
|
||||||
answer.ptr = pns.lastmatch;
|
|
||||||
// The implementation of the Clinger's fast path is convoluted because
|
// The implementation of the Clinger's fast path is convoluted because
|
||||||
// we want round-to-nearest in all cases, irrespective of the rounding mode
|
// we want round-to-nearest in all cases, irrespective of the rounding mode
|
||||||
// selected on the thread.
|
// selected on the thread.
|
||||||
// We proceed optimistically, assuming that detail::rounds_to_nearest()
|
// We proceed optimistically, assuming that detail::rounds_to_nearest()
|
||||||
// returns true.
|
// returns true.
|
||||||
if (binary_format<T>::min_exponent_fast_path() <= pns.exponent &&
|
if (binary_format<T>::min_exponent_fast_path() <= exponent &&
|
||||||
pns.exponent <= binary_format<T>::max_exponent_fast_path() &&
|
exponent <= binary_format<T>::max_exponent_fast_path()) {
|
||||||
!pns.too_many_digits) {
|
|
||||||
// Unfortunately, the conventional Clinger's fast path is only possible
|
// Unfortunately, the conventional Clinger's fast path is only possible
|
||||||
// when the system rounds to the nearest float.
|
// when the system rounds to the nearest float.
|
||||||
//
|
//
|
||||||
@ -224,41 +209,64 @@ from_chars_advanced(parsed_number_string_t<UC> &pns, T &value) noexcept {
|
|||||||
if (!cpp20_and_in_constexpr() && detail::rounds_to_nearest()) {
|
if (!cpp20_and_in_constexpr() && detail::rounds_to_nearest()) {
|
||||||
// We have that fegetround() == FE_TONEAREST.
|
// We have that fegetround() == FE_TONEAREST.
|
||||||
// Next is Clinger's fast path.
|
// Next is Clinger's fast path.
|
||||||
if (pns.mantissa <= binary_format<T>::max_mantissa_fast_path()) {
|
if (mantissa <= binary_format<T>::max_mantissa_fast_path()) {
|
||||||
value = T(pns.mantissa);
|
value = T(mantissa);
|
||||||
if (pns.exponent < 0) {
|
if (exponent < 0) {
|
||||||
value = value / binary_format<T>::exact_power_of_ten(-pns.exponent);
|
value = value / binary_format<T>::exact_power_of_ten(-exponent);
|
||||||
} else {
|
} else {
|
||||||
value = value * binary_format<T>::exact_power_of_ten(pns.exponent);
|
value = value * binary_format<T>::exact_power_of_ten(exponent);
|
||||||
}
|
}
|
||||||
if (pns.negative) {
|
if (is_negative) {
|
||||||
value = -value;
|
value = -value;
|
||||||
}
|
}
|
||||||
return answer;
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// We do not have that fegetround() == FE_TONEAREST.
|
// We do not have that fegetround() == FE_TONEAREST.
|
||||||
// Next is a modified Clinger's fast path, inspired by Jakub Jelínek's
|
// Next is a modified Clinger's fast path, inspired by Jakub Jelínek's
|
||||||
// proposal
|
// proposal
|
||||||
if (pns.exponent >= 0 &&
|
if (exponent >= 0 &&
|
||||||
pns.mantissa <=
|
mantissa <= binary_format<T>::max_mantissa_fast_path(exponent)) {
|
||||||
binary_format<T>::max_mantissa_fast_path(pns.exponent)) {
|
|
||||||
#if defined(__clang__) || defined(FASTFLOAT_32BIT)
|
#if defined(__clang__) || defined(FASTFLOAT_32BIT)
|
||||||
// Clang may map 0 to -0.0 when fegetround() == FE_DOWNWARD
|
// Clang may map 0 to -0.0 when fegetround() == FE_DOWNWARD
|
||||||
if (pns.mantissa == 0) {
|
if (mantissa == 0) {
|
||||||
value = pns.negative ? T(-0.) : T(0.);
|
value = is_negative ? T(-0.) : T(0.);
|
||||||
return answer;
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
value = T(pns.mantissa) *
|
value = T(mantissa) * binary_format<T>::exact_power_of_ten(exponent);
|
||||||
binary_format<T>::exact_power_of_ten(pns.exponent);
|
if (is_negative) {
|
||||||
if (pns.negative) {
|
|
||||||
value = -value;
|
value = -value;
|
||||||
}
|
}
|
||||||
return answer;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function overload takes parsed_number_string_t structure that is created
|
||||||
|
* and populated either by from_chars_advanced function taking chars range and
|
||||||
|
* parsing options or other parsing custom function implemented by user.
|
||||||
|
*/
|
||||||
|
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>::value,
|
||||||
|
"only some floating-point types are supported");
|
||||||
|
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;
|
||||||
|
|
||||||
|
answer.ec = std::errc(); // be optimistic
|
||||||
|
answer.ptr = pns.lastmatch;
|
||||||
|
|
||||||
|
if (!pns.too_many_digits &&
|
||||||
|
clinger_fast_path_impl(pns.mantissa, pns.exponent, pns.negative, value))
|
||||||
|
return answer;
|
||||||
|
|
||||||
adjusted_mantissa am =
|
adjusted_mantissa am =
|
||||||
compute_float<binary_format<T>>(pns.exponent, pns.mantissa);
|
compute_float<binary_format<T>>(pns.exponent, pns.mantissa);
|
||||||
if (pns.too_many_digits && am.power2 >= 0) {
|
if (pns.too_many_digits && am.power2 >= 0) {
|
||||||
@ -336,6 +344,49 @@ from_chars(UC const *first, UC const *last, T &value, int base) noexcept {
|
|||||||
return from_chars_advanced(first, last, value, options);
|
return from_chars_advanced(first, last, value, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FASTFLOAT_CONSTEXPR20 inline double
|
||||||
|
integer_times_pow10(uint64_t mantissa, int decimal_exponent) noexcept {
|
||||||
|
double value;
|
||||||
|
if (clinger_fast_path_impl(mantissa, decimal_exponent, false, value))
|
||||||
|
return value;
|
||||||
|
|
||||||
|
adjusted_mantissa am =
|
||||||
|
compute_float<binary_format<double>>(decimal_exponent, mantissa);
|
||||||
|
to_float(false, am, value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
FASTFLOAT_CONSTEXPR20 inline double
|
||||||
|
integer_times_pow10(int64_t mantissa, int decimal_exponent) noexcept {
|
||||||
|
const bool is_negative = mantissa < 0;
|
||||||
|
const uint64_t m = static_cast<uint64_t>(is_negative ? -mantissa : mantissa);
|
||||||
|
|
||||||
|
double value;
|
||||||
|
if (clinger_fast_path_impl(m, decimal_exponent, is_negative, value))
|
||||||
|
return value;
|
||||||
|
|
||||||
|
adjusted_mantissa am =
|
||||||
|
compute_float<binary_format<double>>(decimal_exponent, m);
|
||||||
|
to_float(is_negative, am, value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// the following overloads are here to avoid surprising ambiguity for int,
|
||||||
|
// unsigned, etc.
|
||||||
|
template <typename Int>
|
||||||
|
FASTFLOAT_CONSTEXPR20 inline typename std::enable_if<
|
||||||
|
std::is_integral<Int>::value && !std::is_signed<Int>::value, double>::type
|
||||||
|
integer_times_pow10(Int mantissa, int decimal_exponent) noexcept {
|
||||||
|
return integer_times_pow10(static_cast<uint64_t>(mantissa), decimal_exponent);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Int>
|
||||||
|
FASTFLOAT_CONSTEXPR20 inline typename std::enable_if<
|
||||||
|
std::is_integral<Int>::value && std::is_signed<Int>::value, double>::type
|
||||||
|
integer_times_pow10(Int mantissa, int decimal_exponent) noexcept {
|
||||||
|
return integer_times_pow10(static_cast<int64_t>(mantissa), decimal_exponent);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T, typename UC>
|
template <typename T, typename UC>
|
||||||
FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
|
FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
|
||||||
from_chars_int_advanced(UC const *first, UC const *last, T &value,
|
from_chars_int_advanced(UC const *first, UC const *last, T &value,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user