mirror of
https://github.com/fastfloat/fast_float.git
synced 2025-12-06 16:56:57 +08:00
Replaces the existing decimal implementation, for substantial
performance improvements with near-halfway cases. This is especially
fast with a large number of digits.
**Big Integer Implementation**
A small subset of big-integer arithmetic has been added, with the
`bigint` struct. It uses a stack-allocated vector with enough bits to
store the float with the large number of significant digits. This is
log2(10^(769 + 342)), to account for the largest possible magnitude
exponent, and number of digits (3600 bits), and then rounded up to 4k bits.
The limb size is determined by the architecture: most 64-bit
architectures have efficient 128-bit multiplication, either by a single
hardware instruction or 2 native multiplications for the high and low
bits. This includes x86_64, mips64, s390x, aarch64, powerpc64, riscv64,
and the only known exception is sparcv8 and sparcv9. Therefore, we
define a limb size of 64-bits on 64-bit architectures except SPARC,
otherwise we fallback to 32-bit limbs.
A simple stackvector is used, which just has operations to add elements,
index, and truncate the vector.
`bigint` is then just a wrapper around this, with methods for
big-integer arithmetic. For our algorithms, we just need multiplication
by a power (x * b^N), multiplication by a bigint or scalar value, and
addition by a bigint or scalar value. Scalar addition and multiplication
uses compiler extensions when possible (__builtin_add_overflow and
__uint128_t), if not, then we implement simple logic shown to optimize
well on MSVC. Big-integer multiplication is done via grade school
multiplication, which is more efficient than any asymptotically faster
algorithms. Multiplication by a power is then done via bitshifts for
powers-of-two, and by iterative multiplications of a large and then
scalar value for powers-of-5.
**compute_float**
Compute float has been slightly modified so if the algorithm cannot
round correctly, it returns a normalized, extended-precision adjusted
mantissa with the power2 shifted by INT16_MIN so the exponent is always
negative. `compute_error` and `compute_error_scaled` have been added.
**Digit Optimiations**
To improve performance for numbers with many digits,
`parse_eight_digits_unrolled` is used for both integers and fractions,
and uses a while loop than two nested if statements. This adds no
noticeable performance cost for common floats, but dramatically improves
performance for numbers with large digits (without these optimizations,
~65% of the total runtime cost is in parse_number_string).
**Parsed Number**
Two fields have been added to `parsed_number_string`, which contains a
slice of the integer and fraction digits. This is extremely cheap, since
the work is already done, and the strings are pre-tokenized during
parsing. This allows us on overflow to re-parse these tokenized strings,
without checking if each character is an integer. Likewise, for the
big-integer algorithms, we can merely re-parse the pre-tokenized
strings.
**Slow Algorithm**
The new algorithm is `digit_comp`, which takes the parsed number string
and the `adjusted_mantissa` from `compute_float`. The significant digits
are parsed into a big integer, and the exponent relative to the
significant digits is calculated. If the exponent is >= 0, we use
`positive_digit_comp`, otherwise, we use `negative_digit_comp`.
`positive_digit_comp` is quite simple: we scale the significant digits
to the exponent, and then we get the high 64-bits for the native float,
determine if any lower bits were truncated, and use that to direct
rounding.
`negative_digit_comp` is a little more complex, but also quite trivial:
we use the parsed significant digits as the real digits, and calculate
the theoretical digits from `b+h`, the halfway point between `b` and
`b+u`, the next-positive float. To get `b`, we round the adjusted
mantissa down, create an extended-precision representation, and
calculate the halfway point. We now have a base-10 exponent for the real
digits, and a base-2 exponent for the theoretical digits. We scale these
two to the same exponent by multiplying the theoretixal digits by
`5**-real_exp`. We then get the base-2 exponent as `theor_exp -
real_exp`, and if this is positive, we multipy the theoretical digits by
it, otherwise, we multiply the real digits by it. Now, both are scaled
to the same magnitude, and we simply compare the digits in the big
integer, and use that to direct rounding.
**Rust-Isms**
A few Rust-isms have been added, since it simplifies logic assertions.
These can be trivially removed or reworked, as needed.
- a `slice` type has been added, which is a pointer and length.
- `FASTFLOAT_ASSERT`, `FASTFLOAT_DEBUG_ASSERT`, and `FASTFLOAT_TRY` have
been added
- `FASTFLOAT_ASSERT` aborts, even in release builds, if the condition
fails.
- `FASTFLOAT_DEBUG_ASSERT` defaults to `assert`, for logic errors.
- `FASTFLOAT_TRY` is like a Rust `Option` type, which propagates
errors.
Specifically, `FASTFLOAT_TRY` is useful in combination with
`FASTFLOAT_ASSERT` to ensure there are no memory corruption errors
possible in the big-integer arithmetic. Although the `bigint` type
ensures we have enough storage for all valid floats, memory issues are
quite a severe class of vulnerabilities, and due to the low performance
cost of checks, we abort if we would have out-of-bounds writes. This can
only occur when we are adding items to the vector, which is a very small
number of steps. Therefore, we abort if our memory safety guarantees
ever fail. lexical has never aborted, so it's unlikely we will ever fail
these guarantees.
727 lines
54 KiB
C++
727 lines
54 KiB
C++
#define DOCTEST_CONFIG_SUPER_FAST_ASSERTS
|
|
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
|
|
#include <doctest/doctest.h>
|
|
|
|
#include "fast_float/fast_float.h"
|
|
#include <iomanip>
|
|
#include <string>
|
|
|
|
#ifndef SUPPLEMENTAL_TEST_DATA_DIR
|
|
#define SUPPLEMENTAL_TEST_DATA_DIR "data/"
|
|
#endif
|
|
|
|
#ifndef __cplusplus
|
|
#error fastfloat requires a C++ compiler
|
|
#endif
|
|
|
|
#ifndef FASTFLOAT_CPLUSPLUS
|
|
#if defined(_MSVC_LANG) && !defined(__clang__)
|
|
#define FASTFLOAT_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG)
|
|
#else
|
|
#define FASTFLOAT_CPLUSPLUS __cplusplus
|
|
#endif
|
|
#endif
|
|
|
|
|
|
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun)
|
|
#define FASTFLOAT_ODDPLATFORM 1
|
|
#endif
|
|
#if defined __has_include
|
|
#if __has_include (<filesystem>)
|
|
#else
|
|
// filesystem is not available
|
|
#define FASTFLOAT_ODDPLATFORM 1
|
|
#endif
|
|
#else
|
|
// __has_include is not available
|
|
#define FASTFLOAT_ODDPLATFORM 1
|
|
#endif
|
|
|
|
#if HAS_CXX20_CONSTEXPR
|
|
#include <bit>
|
|
#include <string_view>
|
|
#endif
|
|
|
|
// C++ 17 because it is otherwise annoying to browse all files in a directory.
|
|
// We also only run these tests on little endian systems.
|
|
#if (FASTFLOAT_CPLUSPLUS >= 201703L) && (FASTFLOAT_IS_BIG_ENDIAN == 0) && !defined(FASTFLOAT_ODDPLATFORM)
|
|
|
|
#include <iostream>
|
|
#include <filesystem>
|
|
#include <charconv>
|
|
|
|
// return true on succcess
|
|
bool check_file(std::string file_name) {
|
|
std::cout << "Checking " << file_name << std::endl;
|
|
size_t number{0};
|
|
std::fstream newfile(file_name, std::ios::in);
|
|
if (newfile.is_open()) {
|
|
std::string str;
|
|
while (std::getline(newfile, str)) {
|
|
if (str.size() > 0) {
|
|
// Read 32-bit hex
|
|
uint32_t float32;
|
|
auto r32 = std::from_chars(str.data() + 5, str.data() + str.size(),
|
|
float32, 16);
|
|
if(r32.ec != std::errc()) { std::cerr << "32-bit parsing failure\n"; return false; }
|
|
// Read 64-bit hex
|
|
uint64_t float64;
|
|
auto r64 = std::from_chars(str.data() + 14, str.data() + str.size(),
|
|
float64, 16);
|
|
if(r64.ec != std::errc()) { std::cerr << "64-bit parsing failure\n"; return false; }
|
|
// The string to parse:
|
|
const char *number_string = str.data() + 31;
|
|
const char *end_of_string = str.data() + str.size();
|
|
// Parse as 32-bit float
|
|
float parsed_32;
|
|
auto fast_float_r32 = fast_float::from_chars(number_string, end_of_string, parsed_32);
|
|
if(fast_float_r32.ec != std::errc()) { std::cerr << "parsing failure\n"; return false; }
|
|
// Parse as 64-bit float
|
|
double parsed_64;
|
|
auto fast_float_r64 = fast_float::from_chars(number_string, end_of_string, parsed_64);
|
|
if(fast_float_r64.ec != std::errc()) { std::cerr << "parsing failure\n"; return false; }
|
|
// Convert the floats to unsigned ints.
|
|
uint32_t float32_parsed;
|
|
uint64_t float64_parsed;
|
|
::memcpy(&float32_parsed, &parsed_32, sizeof(parsed_32));
|
|
::memcpy(&float64_parsed, &parsed_64, sizeof(parsed_64));
|
|
// Compare with expected results
|
|
if (float32_parsed != float32) {
|
|
std::cout << "bad 32 " << str << std::endl;
|
|
return false;
|
|
}
|
|
if (float64_parsed != float64) {
|
|
std::cout << "bad 64 " << str << std::endl;
|
|
return false;
|
|
}
|
|
number++;
|
|
}
|
|
}
|
|
std::cout << "checked " << std::defaultfloat << number << " values" << std::endl;
|
|
newfile.close(); // close the file object
|
|
} else {
|
|
std::cout << "Could not read " << file_name << std::endl;
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
TEST_CASE("supplemental") {
|
|
std::string path = SUPPLEMENTAL_TEST_DATA_DIR;
|
|
for (const auto & entry : std::filesystem::directory_iterator(path)) {
|
|
CHECK(check_file(entry.path().string()));
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if HAS_CXX20_CONSTEXPR
|
|
|
|
constexpr double tryParse(std::string_view input)
|
|
{
|
|
double result{};
|
|
fast_float::from_chars_result parseResult = fast_float::from_chars(input.data(), input.data() + input.size(), result);
|
|
if (parseResult.ec != std::errc()) {
|
|
return std::numeric_limits<double>::quiet_NaN();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
static_assert(tryParse("1.0") == 1.0);
|
|
static_assert(tryParse("2.0") == 2.0);
|
|
static_assert(tryParse("3.14156") == 3.14156);
|
|
static_assert(tryParse("3.14156") != 3.1415600000001);
|
|
#if !defined(_MSVC_LANG)
|
|
static_assert(std::isnan(tryParse("hellothere"))); // technically isnan is not constexpr but GCC and clang allow it
|
|
#endif
|
|
|
|
#endif //#if HAS_CXX20_CONSTEXPR
|
|
|
|
TEST_CASE("leading_zeroes") {
|
|
constexpr const uint64_t bit = 1;
|
|
CHECK(fast_float::leading_zeroes(bit << 0) == 63);
|
|
CHECK(fast_float::leading_zeroes(bit << 1) == 62);
|
|
CHECK(fast_float::leading_zeroes(bit << 2) == 61);
|
|
CHECK(fast_float::leading_zeroes(bit << 61) == 2);
|
|
CHECK(fast_float::leading_zeroes(bit << 62) == 1);
|
|
CHECK(fast_float::leading_zeroes(bit << 63) == 0);
|
|
}
|
|
|
|
#define iHexAndDec(v) std::hex << "0x" << (v) << " (" << std::dec << (v) << ")"
|
|
#define fHexAndDec(v) std::hexfloat << (v) << " (" << std::defaultfloat << (v) << ")"
|
|
|
|
void test_full_multiplication(uint64_t lhs, uint64_t rhs, uint64_t expected_lo, uint64_t expected_hi) {
|
|
fast_float::value128 v;
|
|
v = fast_float::full_multiplication(lhs, rhs);
|
|
INFO("lhs=" << iHexAndDec(lhs) << " " << "rhs=" << iHexAndDec(rhs)
|
|
<< "\n actualLo=" << iHexAndDec(v.low) << " " << "actualHi=" << iHexAndDec(v.high)
|
|
<< "\n expectedLo=" << iHexAndDec(expected_lo) << " " << "expectedHi=" << iHexAndDec(expected_hi));
|
|
CHECK_EQ(v.low, expected_lo);
|
|
CHECK_EQ(v.high, expected_hi);
|
|
v = fast_float::full_multiplication(rhs, lhs);
|
|
CHECK_EQ(v.low, expected_lo);
|
|
CHECK_EQ(v.high, expected_hi);
|
|
}
|
|
|
|
TEST_CASE("full_multiplication") {
|
|
constexpr const uint64_t bit = 1;
|
|
// lhs rhs lo hi
|
|
test_full_multiplication(bit << 0 , bit << 0, 1u , 0u);
|
|
test_full_multiplication(bit << 0 , bit << 63, bit << 63, 0u);
|
|
test_full_multiplication(bit << 1 , bit << 63, 0u , 1u);
|
|
test_full_multiplication(bit << 63, bit << 0, bit << 63, 0u);
|
|
test_full_multiplication(bit << 63, bit << 1, 0u , 1u);
|
|
test_full_multiplication(bit << 63, bit << 2, 0u , 2u);
|
|
test_full_multiplication(bit << 63, bit << 63, 0u , bit << 62);
|
|
}
|
|
|
|
|
|
TEST_CASE("issue8") {
|
|
const char* s =
|
|
"3."
|
|
"141592653589793238462643383279502884197169399375105820974944592307816406"
|
|
"286208998628034825342117067982148086513282306647093844609550582231725359"
|
|
"408128481117450284102701938521105559644622948954930381964428810975665933"
|
|
"446128475648233786783165271201909145648566923460348610454326648213393607"
|
|
"260249141273724587006606315588174881520920962829254091715364367892590360"
|
|
"011330530548820466521384146951941511609433057270365759591953092186117381"
|
|
"932611793105118548074462379962749567351885752724891227938183011949129833"
|
|
"673362440656643086021394946395224737190702179860943702770539217176293176"
|
|
"752384674818467669405132000568127145263560827785771342757789609173637178"
|
|
"721468440901224953430146549585371050792279689258923542019956112129021960"
|
|
"864034418159813629774771309960518707211349999998372978";
|
|
for (int i = 0; i < 16; i++) {
|
|
// Parse all but the last i chars. We should still get 3.141ish.
|
|
double d = 0.0;
|
|
auto answer = fast_float::from_chars(s, s + strlen(s) - i, d);
|
|
CHECK_MESSAGE(answer.ec == std::errc(), "i=" << i);
|
|
CHECK_MESSAGE(d == 0x1.921fb54442d18p+1, "i=" << i << "\n"
|
|
<< std::string(s, strlen(s) - size_t(i)) << "\n"
|
|
<< std::hexfloat << d << "\n"
|
|
<< std::defaultfloat << "\n");
|
|
}
|
|
}
|
|
|
|
TEST_CASE("check_behavior") {
|
|
const std::string input = "abc";
|
|
double result;
|
|
auto answer = fast_float::from_chars(input.data(), input.data()+input.size(), result);
|
|
CHECK_MESSAGE(answer.ec != std::errc(), "expected parse failure");
|
|
CHECK_MESSAGE(answer.ptr == input.data(), "If there is no pattern match, we should have ptr equals first");
|
|
}
|
|
|
|
|
|
TEST_CASE("decimal_point_parsing") {
|
|
double result;
|
|
fast_float::parse_options options{};
|
|
{
|
|
const std::string input = "1,25";
|
|
auto answer = fast_float::from_chars_advanced(input.data(), input.data()+input.size(), result, options);
|
|
CHECK_MESSAGE(answer.ec == std::errc(), "expected parse success");
|
|
CHECK_MESSAGE(answer.ptr == input.data() + 1,
|
|
"Parsing should have stopped at comma");
|
|
CHECK_EQ(result, 1.0);
|
|
|
|
options.decimal_point = ',';
|
|
answer = fast_float::from_chars_advanced(input.data(), input.data()+input.size(), result, options);
|
|
CHECK_MESSAGE(answer.ec == std::errc(), "expected parse success");
|
|
CHECK_MESSAGE(answer.ptr == input.data() + input.size(),
|
|
"Parsing should have stopped at end");
|
|
CHECK_EQ(result, 1.25);
|
|
}
|
|
{
|
|
const std::string input = "1.25";
|
|
auto answer = fast_float::from_chars_advanced(input.data(), input.data()+input.size(), result, options);
|
|
CHECK_MESSAGE(answer.ec == std::errc(), "expected parse success");
|
|
CHECK_MESSAGE(answer.ptr == input.data() + 1,
|
|
"Parsing should have stopped at dot");
|
|
CHECK_EQ(result, 1.0);
|
|
|
|
options.decimal_point = '.';
|
|
answer = fast_float::from_chars_advanced(input.data(), input.data()+input.size(), result, options);
|
|
CHECK_MESSAGE(answer.ec == std::errc(), "expected parse success");
|
|
CHECK_MESSAGE(answer.ptr == input.data() + input.size(),
|
|
"Parsing should have stopped at end");
|
|
CHECK_EQ(result, 1.25);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("issue19") {
|
|
const std::string input = "3.14e";
|
|
double result;
|
|
auto answer = fast_float::from_chars(input.data(), input.data()+input.size(), result);
|
|
CHECK_MESSAGE(answer.ec == std::errc(), "We want to parse up to 3.14\n");
|
|
CHECK_MESSAGE(answer.ptr == input.data() + 4,
|
|
"Parsed the number " << result
|
|
<< " and stopped at the wrong character: after " << (answer.ptr - input.data()) << " characters");
|
|
}
|
|
|
|
|
|
TEST_CASE("scientific_only") {
|
|
// first, we try with something that should fail...
|
|
std::string input = "3.14";
|
|
double result;
|
|
auto answer = fast_float::from_chars(input.data(), input.data()+input.size(), result, fast_float::chars_format::scientific);
|
|
CHECK_MESSAGE(answer.ec != std::errc(), "It is not scientific! Parsed: " << result);
|
|
|
|
input = "3.14e10";
|
|
answer = fast_float::from_chars(input.data(), input.data()+input.size(), result, fast_float::chars_format::scientific);
|
|
CHECK_MESSAGE(answer.ec == std::errc(), "It is scientific! Parsed: " << result);
|
|
CHECK_MESSAGE(answer.ptr == input.data() + input.size(),
|
|
"Parsed the number " << result
|
|
<< " and stopped at the wrong character: after " << (answer.ptr - input.data()) << " characters");
|
|
}
|
|
|
|
|
|
TEST_CASE("test_fixed_only") {
|
|
const std::string input = "3.14e10";
|
|
double result;
|
|
auto answer = fast_float::from_chars(input.data(), input.data()+input.size(), result, fast_float::chars_format::fixed);
|
|
CHECK_MESSAGE(answer.ec == std::errc(), "We want to parse up to 3.14; parsed: " << result);
|
|
CHECK_MESSAGE(answer.ptr == input.data() + 4,
|
|
"Parsed the number " << result
|
|
<< " and stopped at the wrong character: after " << (answer.ptr - input.data()) << " characters");
|
|
}
|
|
|
|
|
|
static const double testing_power_of_ten[] = {
|
|
1e-307, 1e-306, 1e-305, 1e-304, 1e-303, 1e-302, 1e-301, 1e-300, 1e-299,
|
|
1e-298, 1e-297, 1e-296, 1e-295, 1e-294, 1e-293, 1e-292, 1e-291, 1e-290,
|
|
1e-289, 1e-288, 1e-287, 1e-286, 1e-285, 1e-284, 1e-283, 1e-282, 1e-281,
|
|
1e-280, 1e-279, 1e-278, 1e-277, 1e-276, 1e-275, 1e-274, 1e-273, 1e-272,
|
|
1e-271, 1e-270, 1e-269, 1e-268, 1e-267, 1e-266, 1e-265, 1e-264, 1e-263,
|
|
1e-262, 1e-261, 1e-260, 1e-259, 1e-258, 1e-257, 1e-256, 1e-255, 1e-254,
|
|
1e-253, 1e-252, 1e-251, 1e-250, 1e-249, 1e-248, 1e-247, 1e-246, 1e-245,
|
|
1e-244, 1e-243, 1e-242, 1e-241, 1e-240, 1e-239, 1e-238, 1e-237, 1e-236,
|
|
1e-235, 1e-234, 1e-233, 1e-232, 1e-231, 1e-230, 1e-229, 1e-228, 1e-227,
|
|
1e-226, 1e-225, 1e-224, 1e-223, 1e-222, 1e-221, 1e-220, 1e-219, 1e-218,
|
|
1e-217, 1e-216, 1e-215, 1e-214, 1e-213, 1e-212, 1e-211, 1e-210, 1e-209,
|
|
1e-208, 1e-207, 1e-206, 1e-205, 1e-204, 1e-203, 1e-202, 1e-201, 1e-200,
|
|
1e-199, 1e-198, 1e-197, 1e-196, 1e-195, 1e-194, 1e-193, 1e-192, 1e-191,
|
|
1e-190, 1e-189, 1e-188, 1e-187, 1e-186, 1e-185, 1e-184, 1e-183, 1e-182,
|
|
1e-181, 1e-180, 1e-179, 1e-178, 1e-177, 1e-176, 1e-175, 1e-174, 1e-173,
|
|
1e-172, 1e-171, 1e-170, 1e-169, 1e-168, 1e-167, 1e-166, 1e-165, 1e-164,
|
|
1e-163, 1e-162, 1e-161, 1e-160, 1e-159, 1e-158, 1e-157, 1e-156, 1e-155,
|
|
1e-154, 1e-153, 1e-152, 1e-151, 1e-150, 1e-149, 1e-148, 1e-147, 1e-146,
|
|
1e-145, 1e-144, 1e-143, 1e-142, 1e-141, 1e-140, 1e-139, 1e-138, 1e-137,
|
|
1e-136, 1e-135, 1e-134, 1e-133, 1e-132, 1e-131, 1e-130, 1e-129, 1e-128,
|
|
1e-127, 1e-126, 1e-125, 1e-124, 1e-123, 1e-122, 1e-121, 1e-120, 1e-119,
|
|
1e-118, 1e-117, 1e-116, 1e-115, 1e-114, 1e-113, 1e-112, 1e-111, 1e-110,
|
|
1e-109, 1e-108, 1e-107, 1e-106, 1e-105, 1e-104, 1e-103, 1e-102, 1e-101,
|
|
1e-100, 1e-99, 1e-98, 1e-97, 1e-96, 1e-95, 1e-94, 1e-93, 1e-92,
|
|
1e-91, 1e-90, 1e-89, 1e-88, 1e-87, 1e-86, 1e-85, 1e-84, 1e-83,
|
|
1e-82, 1e-81, 1e-80, 1e-79, 1e-78, 1e-77, 1e-76, 1e-75, 1e-74,
|
|
1e-73, 1e-72, 1e-71, 1e-70, 1e-69, 1e-68, 1e-67, 1e-66, 1e-65,
|
|
1e-64, 1e-63, 1e-62, 1e-61, 1e-60, 1e-59, 1e-58, 1e-57, 1e-56,
|
|
1e-55, 1e-54, 1e-53, 1e-52, 1e-51, 1e-50, 1e-49, 1e-48, 1e-47,
|
|
1e-46, 1e-45, 1e-44, 1e-43, 1e-42, 1e-41, 1e-40, 1e-39, 1e-38,
|
|
1e-37, 1e-36, 1e-35, 1e-34, 1e-33, 1e-32, 1e-31, 1e-30, 1e-29,
|
|
1e-28, 1e-27, 1e-26, 1e-25, 1e-24, 1e-23, 1e-22, 1e-21, 1e-20,
|
|
1e-19, 1e-18, 1e-17, 1e-16, 1e-15, 1e-14, 1e-13, 1e-12, 1e-11,
|
|
1e-10, 1e-9, 1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2,
|
|
1e-1, 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7,
|
|
1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16,
|
|
1e17, 1e18, 1e19, 1e20, 1e21, 1e22, 1e23, 1e24, 1e25,
|
|
1e26, 1e27, 1e28, 1e29, 1e30, 1e31, 1e32, 1e33, 1e34,
|
|
1e35, 1e36, 1e37, 1e38, 1e39, 1e40, 1e41, 1e42, 1e43,
|
|
1e44, 1e45, 1e46, 1e47, 1e48, 1e49, 1e50, 1e51, 1e52,
|
|
1e53, 1e54, 1e55, 1e56, 1e57, 1e58, 1e59, 1e60, 1e61,
|
|
1e62, 1e63, 1e64, 1e65, 1e66, 1e67, 1e68, 1e69, 1e70,
|
|
1e71, 1e72, 1e73, 1e74, 1e75, 1e76, 1e77, 1e78, 1e79,
|
|
1e80, 1e81, 1e82, 1e83, 1e84, 1e85, 1e86, 1e87, 1e88,
|
|
1e89, 1e90, 1e91, 1e92, 1e93, 1e94, 1e95, 1e96, 1e97,
|
|
1e98, 1e99, 1e100, 1e101, 1e102, 1e103, 1e104, 1e105, 1e106,
|
|
1e107, 1e108, 1e109, 1e110, 1e111, 1e112, 1e113, 1e114, 1e115,
|
|
1e116, 1e117, 1e118, 1e119, 1e120, 1e121, 1e122, 1e123, 1e124,
|
|
1e125, 1e126, 1e127, 1e128, 1e129, 1e130, 1e131, 1e132, 1e133,
|
|
1e134, 1e135, 1e136, 1e137, 1e138, 1e139, 1e140, 1e141, 1e142,
|
|
1e143, 1e144, 1e145, 1e146, 1e147, 1e148, 1e149, 1e150, 1e151,
|
|
1e152, 1e153, 1e154, 1e155, 1e156, 1e157, 1e158, 1e159, 1e160,
|
|
1e161, 1e162, 1e163, 1e164, 1e165, 1e166, 1e167, 1e168, 1e169,
|
|
1e170, 1e171, 1e172, 1e173, 1e174, 1e175, 1e176, 1e177, 1e178,
|
|
1e179, 1e180, 1e181, 1e182, 1e183, 1e184, 1e185, 1e186, 1e187,
|
|
1e188, 1e189, 1e190, 1e191, 1e192, 1e193, 1e194, 1e195, 1e196,
|
|
1e197, 1e198, 1e199, 1e200, 1e201, 1e202, 1e203, 1e204, 1e205,
|
|
1e206, 1e207, 1e208, 1e209, 1e210, 1e211, 1e212, 1e213, 1e214,
|
|
1e215, 1e216, 1e217, 1e218, 1e219, 1e220, 1e221, 1e222, 1e223,
|
|
1e224, 1e225, 1e226, 1e227, 1e228, 1e229, 1e230, 1e231, 1e232,
|
|
1e233, 1e234, 1e235, 1e236, 1e237, 1e238, 1e239, 1e240, 1e241,
|
|
1e242, 1e243, 1e244, 1e245, 1e246, 1e247, 1e248, 1e249, 1e250,
|
|
1e251, 1e252, 1e253, 1e254, 1e255, 1e256, 1e257, 1e258, 1e259,
|
|
1e260, 1e261, 1e262, 1e263, 1e264, 1e265, 1e266, 1e267, 1e268,
|
|
1e269, 1e270, 1e271, 1e272, 1e273, 1e274, 1e275, 1e276, 1e277,
|
|
1e278, 1e279, 1e280, 1e281, 1e282, 1e283, 1e284, 1e285, 1e286,
|
|
1e287, 1e288, 1e289, 1e290, 1e291, 1e292, 1e293, 1e294, 1e295,
|
|
1e296, 1e297, 1e298, 1e299, 1e300, 1e301, 1e302, 1e303, 1e304,
|
|
1e305, 1e306, 1e307, 1e308};
|
|
|
|
|
|
TEST_CASE("powers_of_ten") {
|
|
char buf[1024];
|
|
WARN_MESSAGE(1e-308 == std::pow(10, -308), "On your system, the pow function is busted. Sorry about that.");
|
|
bool is_pow_correct{1e-308 == std::pow(10,-308)};
|
|
// large negative values should be zero.
|
|
int start_point = is_pow_correct ? -1000 : -307;
|
|
for (int i = start_point; i <= 308; ++i) {
|
|
INFO("i=" << i);
|
|
size_t n = size_t(snprintf(buf, sizeof(buf), "1e%d", i));
|
|
REQUIRE(n < sizeof(buf)); // if false, fails the test and exits
|
|
double actual;
|
|
auto result = fast_float::from_chars(buf, buf + 1000, actual);
|
|
CHECK_MESSAGE(result.ec == std::errc(), " I could not parse " << buf);
|
|
double expected = ((i >= -307) ? testing_power_of_ten[i + 307] : std::pow(10, i));
|
|
CHECK_MESSAGE(actual == expected, "String '" << buf << "'parsed to " << actual);
|
|
}
|
|
}
|
|
|
|
|
|
template <typename T> std::string to_string(T d) {
|
|
std::string s(64, '\0');
|
|
auto written = std::snprintf(&s[0], s.size(), "%.*e",
|
|
std::numeric_limits<T>::max_digits10 - 1, d);
|
|
s.resize(size_t(written));
|
|
return s;
|
|
}
|
|
|
|
template <typename T> std::string to_long_string(T d) {
|
|
std::string s(4096, '\0');
|
|
auto written = std::snprintf(&s[0], s.size(), "%.*e",
|
|
std::numeric_limits<T>::max_digits10 * 10, d);
|
|
s.resize(size_t(written));
|
|
return s;
|
|
}
|
|
|
|
uint32_t get_mantissa(float f) {
|
|
uint32_t m;
|
|
memcpy(&m, &f, sizeof(f));
|
|
return (m & ((uint32_t(1)<<23)-1));
|
|
}
|
|
|
|
uint64_t get_mantissa(double f) {
|
|
uint64_t m;
|
|
memcpy(&m, &f, sizeof(f));
|
|
return (m & ((uint64_t(1)<<57)-1));
|
|
}
|
|
|
|
|
|
std::string append_zeros(std::string str, size_t number_of_zeros) {
|
|
std::string answer(str);
|
|
for(size_t i = 0; i < number_of_zeros; i++) { answer += "0"; }
|
|
return answer;
|
|
}
|
|
|
|
template<class T>
|
|
void check_basic_test_result(const std::string& str, fast_float::from_chars_result result,
|
|
T actual, T expected) {
|
|
INFO("str=" << str << "\n"
|
|
<< " expected=" << fHexAndDec(expected) << "\n"
|
|
<< " ..actual=" << fHexAndDec(actual) << "\n"
|
|
<< " expected mantissa=" << iHexAndDec(get_mantissa(expected)) << "\n"
|
|
<< " ..actual mantissa=" << iHexAndDec(get_mantissa(actual)));
|
|
CHECK_EQ(result.ec, std::errc());
|
|
CHECK_EQ(result.ptr, str.data() + str.size());
|
|
CHECK_EQ(copysign(1, actual), copysign(1, expected));
|
|
CHECK_EQ(std::isnan(actual), std::isnan(expected));
|
|
CHECK_EQ(actual, expected);
|
|
}
|
|
|
|
template<class T>
|
|
void basic_test(std::string str, T expected) {
|
|
T actual;
|
|
auto result = fast_float::from_chars(str.data(), str.data() + str.size(), actual);
|
|
check_basic_test_result(str, result, actual, expected);
|
|
}
|
|
|
|
template<class T>
|
|
void basic_test(std::string str, T expected, fast_float::parse_options options) {
|
|
T actual;
|
|
auto result = fast_float::from_chars_advanced(str.data(), str.data() + str.size(), actual, options);
|
|
check_basic_test_result(str, result, actual, expected);
|
|
}
|
|
|
|
void basic_test(float val) {
|
|
{
|
|
std::string long_vals = to_long_string(val);
|
|
INFO("long vals: " << long_vals);
|
|
basic_test<float>(long_vals, val);
|
|
}
|
|
{
|
|
std::string vals = to_string(val);
|
|
INFO("vals: " << vals);
|
|
basic_test<float>(vals, val);
|
|
}
|
|
}
|
|
|
|
#define verify(lhs, rhs) { INFO(lhs); basic_test(lhs, rhs); }
|
|
#define verify32(val) { INFO(#val); basic_test(val); }
|
|
|
|
#define verify_options(lhs, rhs) { INFO(lhs); basic_test(lhs, rhs, options); }
|
|
|
|
TEST_CASE("64bit.inf") {
|
|
verify("INF", std::numeric_limits<double>::infinity());
|
|
verify("-INF", -std::numeric_limits<double>::infinity());
|
|
verify("INFINITY", std::numeric_limits<double>::infinity());
|
|
verify("-INFINITY", -std::numeric_limits<double>::infinity());
|
|
verify("infinity", std::numeric_limits<double>::infinity());
|
|
verify("-infinity", -std::numeric_limits<double>::infinity());
|
|
verify("inf", std::numeric_limits<double>::infinity());
|
|
verify("-inf", -std::numeric_limits<double>::infinity());
|
|
verify("1234456789012345678901234567890e9999999999999999999999999999", std::numeric_limits<double>::infinity());
|
|
verify("-2139879401095466344511101915470454744.9813888656856943E+272", -std::numeric_limits<double>::infinity());
|
|
verify("1.8e308", std::numeric_limits<double>::infinity());
|
|
verify("1.832312213213213232132132143451234453123412321321312e308", std::numeric_limits<double>::infinity());
|
|
verify("2e30000000000000000", std::numeric_limits<double>::infinity());
|
|
verify("2e3000", std::numeric_limits<double>::infinity());
|
|
verify("1.9e308", std::numeric_limits<double>::infinity());
|
|
}
|
|
|
|
TEST_CASE("64bit.general") {
|
|
verify("-2.2222222222223e-322",-0x1.68p-1069);
|
|
verify("9007199254740993.0", 0x1p+53);
|
|
verify("860228122.6654514319E+90", 0x1.92bb20990715fp+328);
|
|
verify(append_zeros("9007199254740993.0",1000), 0x1p+53);
|
|
verify("10000000000000000000", 0x1.158e460913dp+63);
|
|
verify("10000000000000000000000000000001000000000000", 0x1.cb2d6f618c879p+142);
|
|
verify("10000000000000000000000000000000000000000001", 0x1.cb2d6f618c879p+142);
|
|
verify("1.1920928955078125e-07", 1.1920928955078125e-07);
|
|
verify("9355950000000000000.00000000000000000000000000000000001844674407370955161600000184467440737095516161844674407370955161407370955161618446744073709551616000184467440737095516166000001844674407370955161618446744073709551614073709551616184467440737095516160001844674407370955161601844674407370955674451616184467440737095516140737095516161844674407370955161600018446744073709551616018446744073709551611616000184467440737095001844674407370955161600184467440737095516160018446744073709551168164467440737095516160001844073709551616018446744073709551616184467440737095516160001844674407536910751601611616000184467440737095001844674407370955161600184467440737095516160018446744073709551616184467440737095516160001844955161618446744073709551616000184467440753691075160018446744073709",0x1.03ae05e8fca1cp+63);
|
|
verify("-0",-0.0);
|
|
verify("2.22507385850720212418870147920222032907240528279439037814303133837435107319244194686754406432563881851382188218502438069999947733013005649884107791928741341929297200970481951993067993290969042784064731682041565926728632933630474670123316852983422152744517260835859654566319282835244787787799894310779783833699159288594555213714181128458251145584319223079897504395086859412457230891738946169368372321191373658977977723286698840356390251044443035457396733706583981055420456693824658413747607155981176573877626747665912387199931904006317334709003012790188175203447190250028061277777916798391090578584006464715943810511489154282775041174682194133952466682503431306181587829379004205392375072083366693241580002758391118854188641513168478436313080237596295773983001708984375e-308", 0x1.0000000000002p-1022);
|
|
verify("1.0000000000000006661338147750939242541790008544921875",1.0000000000000007);
|
|
verify("1090544144181609348835077142190",0x1.b8779f2474dfbp+99);
|
|
verify("2.2250738585072013e-308", 2.2250738585072013e-308);
|
|
verify("-92666518056446206563E3", -92666518056446206563E3);
|
|
verify("-92666518056446206563E3", -92666518056446206563E3);
|
|
verify("-42823146028335318693e-128",-42823146028335318693e-128);
|
|
verify("90054602635948575728E72",90054602635948575728E72);
|
|
verify("1.00000000000000188558920870223463870174566020691753515394643550663070558368373221972569761144603605635692374830246134201063722058e-309", 1.00000000000000188558920870223463870174566020691753515394643550663070558368373221972569761144603605635692374830246134201063722058e-309);
|
|
verify("0e9999999999999999999999999999", 0.0);
|
|
verify("-2402844368454405395.2", -2402844368454405395.2);
|
|
verify("2402844368454405395.2", 2402844368454405395.2);
|
|
verify("7.0420557077594588669468784357561207962098443483187940792729600000e+59", 7.0420557077594588669468784357561207962098443483187940792729600000e+59);
|
|
verify("7.0420557077594588669468784357561207962098443483187940792729600000e+59", 7.0420557077594588669468784357561207962098443483187940792729600000e+59);
|
|
verify("-1.7339253062092163730578609458683877051596800000000000000000000000e+42", -1.7339253062092163730578609458683877051596800000000000000000000000e+42);
|
|
verify("-2.0972622234386619214559824785284023792871122537545728000000000000e+52", -2.0972622234386619214559824785284023792871122537545728000000000000e+52);
|
|
verify("-1.0001803374372191849407179462120053338028379051879898808320000000e+57", -1.0001803374372191849407179462120053338028379051879898808320000000e+57);
|
|
verify("-1.8607245283054342363818436991534856973992070520151142825984000000e+58", -1.8607245283054342363818436991534856973992070520151142825984000000e+58);
|
|
verify("-1.9189205311132686907264385602245237137907390376574976000000000000e+52", -1.9189205311132686907264385602245237137907390376574976000000000000e+52);
|
|
verify("-2.8184483231688951563253238886553506793085187889855201280000000000e+54", -2.8184483231688951563253238886553506793085187889855201280000000000e+54);
|
|
verify("-1.7664960224650106892054063261344555646357024359107788800000000000e+53", -1.7664960224650106892054063261344555646357024359107788800000000000e+53);
|
|
verify("-2.1470977154320536489471030463761883783915110400000000000000000000e+45", -2.1470977154320536489471030463761883783915110400000000000000000000e+45);
|
|
verify("-4.4900312744003159009338275160799498340862630046359789166919680000e+61", -4.4900312744003159009338275160799498340862630046359789166919680000e+61);
|
|
verify("1", 1.0);
|
|
verify("1.797693134862315700000000000000001e308", 1.7976931348623157e308);
|
|
verify("3e-324", 0x0.0000000000001p-1022);
|
|
verify("1.00000006e+09", 0x1.dcd651ep+29);
|
|
verify("4.9406564584124653e-324", 0x0.0000000000001p-1022);
|
|
verify("4.9406564584124654e-324", 0x0.0000000000001p-1022);
|
|
verify("2.2250738585072009e-308", 0x0.fffffffffffffp-1022);
|
|
verify("2.2250738585072014e-308", 0x1p-1022);
|
|
verify("1.7976931348623157e308", 0x1.fffffffffffffp+1023);
|
|
verify("1.7976931348623158e308", 0x1.fffffffffffffp+1023);
|
|
verify("4503599627370496.5", 4503599627370496.5);
|
|
verify("4503599627475352.5", 4503599627475352.5);
|
|
verify("4503599627475353.5", 4503599627475353.5);
|
|
verify("2251799813685248.25", 2251799813685248.25);
|
|
verify("1125899906842624.125", 1125899906842624.125);
|
|
verify("1125899906842901.875", 1125899906842901.875);
|
|
verify("2251799813685803.75", 2251799813685803.75);
|
|
verify("4503599627370497.5", 4503599627370497.5);
|
|
verify("45035996.273704995", 45035996.273704995);
|
|
verify("45035996.273704985", 45035996.273704985);
|
|
verify("0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044501477170144022721148195934182639518696390927032912960468522194496444440421538910330590478162701758282983178260792422137401728773891892910553144148156412434867599762821265346585071045737627442980259622449029037796981144446145705102663115100318287949527959668236039986479250965780342141637013812613333119898765515451440315261253813266652951306000184917766328660755595837392240989947807556594098101021612198814605258742579179000071675999344145086087205681577915435923018910334964869420614052182892431445797605163650903606514140377217442262561590244668525767372446430075513332450079650686719491377688478005309963967709758965844137894433796621993967316936280457084866613206797017728916080020698679408551343728867675409720757232455434770912461317493580281734466552734375", 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044501477170144022721148195934182639518696390927032912960468522194496444440421538910330590478162701758282983178260792422137401728773891892910553144148156412434867599762821265346585071045737627442980259622449029037796981144446145705102663115100318287949527959668236039986479250965780342141637013812613333119898765515451440315261253813266652951306000184917766328660755595837392240989947807556594098101021612198814605258742579179000071675999344145086087205681577915435923018910334964869420614052182892431445797605163650903606514140377217442262561590244668525767372446430075513332450079650686719491377688478005309963967709758965844137894433796621993967316936280457084866613206797017728916080020698679408551343728867675409720757232455434770912461317493580281734466552734375);
|
|
verify("0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022250738585072008890245868760858598876504231122409594654935248025624400092282356951787758888037591552642309780950434312085877387158357291821993020294379224223559819827501242041788969571311791082261043971979604000454897391938079198936081525613113376149842043271751033627391549782731594143828136275113838604094249464942286316695429105080201815926642134996606517803095075913058719846423906068637102005108723282784678843631944515866135041223479014792369585208321597621066375401613736583044193603714778355306682834535634005074073040135602968046375918583163124224521599262546494300836851861719422417646455137135420132217031370496583210154654068035397417906022589503023501937519773030945763173210852507299305089761582519159720757232455434770912461317493580281734466552734375", 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022250738585072008890245868760858598876504231122409594654935248025624400092282356951787758888037591552642309780950434312085877387158357291821993020294379224223559819827501242041788969571311791082261043971979604000454897391938079198936081525613113376149842043271751033627391549782731594143828136275113838604094249464942286316695429105080201815926642134996606517803095075913058719846423906068637102005108723282784678843631944515866135041223479014792369585208321597621066375401613736583044193603714778355306682834535634005074073040135602968046375918583163124224521599262546494300836851861719422417646455137135420132217031370496583210154654068035397417906022589503023501937519773030945763173210852507299305089761582519159720757232455434770912461317493580281734466552734375);
|
|
verify("1438456663141390273526118207642235581183227845246331231162636653790368152091394196930365828634687637948157940776599182791387527135353034738357134110310609455693900824193549772792016543182680519740580354365467985440183598701312257624545562331397018329928613196125590274187720073914818062530830316533158098624984118889298281371812288789537310599037529113415438738954894752124724983067241108764488346454376699018673078404751121414804937224240805993123816932326223683090770561597570457793932985826162604255884529134126396282202126526253389383421806727954588525596114379801269094096329805054803089299736996870951258573010877404407451953846698609198213926882692078557033228265259305481198526059813164469187586693257335779522020407645498684263339921905227556616698129967412891282231685504660671277927198290009824680186319750978665734576683784255802269708917361719466043175201158849097881370477111850171579869056016061666173029059588433776015644439705050377554277696143928278093453792803846252715966016733222646442382892123940052441346822429721593884378212558701004356924243030059517489346646577724622498919752597382095222500311124181823512251071356181769376577651390028297796156208815375089159128394945710515861334486267101797497111125909272505194792870889617179758703442608016143343262159998149700606597792535574457560429226974273443630323818747730771316763398572110874959981923732463076884528677392654150010269822239401993427482376513231389212353583573566376915572650916866553612366187378959554983566712767093372906030188976220169058025354973622211666504549316958271880975697143546564469806791358707318873075708383345004090151974068325838177531266954177406661392229801349994695941509935655355652985723782153570084089560139142231.738475042362596875449154552392299548947138162081694168675340677843807613129780449323363759027012972466987370921816813162658754726545121090545507240267000456594786540949605260722461937870630634874991729398208026467698131898691830012167897399682179601734569071423681e-733", std::numeric_limits<double>::infinity());
|
|
verify("-2240084132271013504.131248280843119943687942846658579428", -0x1.f1660a65b00bfp+60);
|
|
}
|
|
|
|
TEST_CASE("64bit.decimal_point") {
|
|
fast_float::parse_options options{};
|
|
options.decimal_point = ',';
|
|
|
|
// infinities
|
|
verify_options("1,8e308", std::numeric_limits<double>::infinity());
|
|
verify_options("1,832312213213213232132132143451234453123412321321312e308", std::numeric_limits<double>::infinity());
|
|
verify_options("2e30000000000000000", std::numeric_limits<double>::infinity());
|
|
verify_options("2e3000", std::numeric_limits<double>::infinity());
|
|
verify_options("1,9e308", std::numeric_limits<double>::infinity());
|
|
|
|
// finites
|
|
verify_options("-2,2222222222223e-322",-0x1.68p-1069);
|
|
verify_options("9007199254740993,0", 0x1p+53);
|
|
verify_options("860228122,6654514319E+90", 0x1.92bb20990715fp+328);
|
|
verify_options(append_zeros("9007199254740993,0",1000), 0x1p+53);
|
|
verify_options("1,1920928955078125e-07", 1.1920928955078125e-07);
|
|
verify_options("9355950000000000000,00000000000000000000000000000000001844674407370955161600000184467440737095516161844674407370955161407370955161618446744073709551616000184467440737095516166000001844674407370955161618446744073709551614073709551616184467440737095516160001844674407370955161601844674407370955674451616184467440737095516140737095516161844674407370955161600018446744073709551616018446744073709551611616000184467440737095001844674407370955161600184467440737095516160018446744073709551168164467440737095516160001844073709551616018446744073709551616184467440737095516160001844674407536910751601611616000184467440737095001844674407370955161600184467440737095516160018446744073709551616184467440737095516160001844955161618446744073709551616000184467440753691075160018446744073709",0x1.03ae05e8fca1cp+63);
|
|
verify_options("2,22507385850720212418870147920222032907240528279439037814303133837435107319244194686754406432563881851382188218502438069999947733013005649884107791928741341929297200970481951993067993290969042784064731682041565926728632933630474670123316852983422152744517260835859654566319282835244787787799894310779783833699159288594555213714181128458251145584319223079897504395086859412457230891738946169368372321191373658977977723286698840356390251044443035457396733706583981055420456693824658413747607155981176573877626747665912387199931904006317334709003012790188175203447190250028061277777916798391090578584006464715943810511489154282775041174682194133952466682503431306181587829379004205392375072083366693241580002758391118854188641513168478436313080237596295773983001708984375e-308", 0x1.0000000000002p-1022);
|
|
verify_options("1,0000000000000006661338147750939242541790008544921875",1.0000000000000007);
|
|
verify_options("2,2250738585072013e-308", 2.2250738585072013e-308);
|
|
verify_options("1,00000000000000188558920870223463870174566020691753515394643550663070558368373221972569761144603605635692374830246134201063722058e-309", 1.00000000000000188558920870223463870174566020691753515394643550663070558368373221972569761144603605635692374830246134201063722058e-309);
|
|
verify_options("-2402844368454405395,2", -2402844368454405395.2);
|
|
verify_options("2402844368454405395,2", 2402844368454405395.2);
|
|
verify_options("7,0420557077594588669468784357561207962098443483187940792729600000e+59", 7.0420557077594588669468784357561207962098443483187940792729600000e+59);
|
|
verify_options("7,0420557077594588669468784357561207962098443483187940792729600000e+59", 7.0420557077594588669468784357561207962098443483187940792729600000e+59);
|
|
verify_options("-1,7339253062092163730578609458683877051596800000000000000000000000e+42", -1.7339253062092163730578609458683877051596800000000000000000000000e+42);
|
|
verify_options("-2,0972622234386619214559824785284023792871122537545728000000000000e+52", -2.0972622234386619214559824785284023792871122537545728000000000000e+52);
|
|
verify_options("-1,0001803374372191849407179462120053338028379051879898808320000000e+57", -1.0001803374372191849407179462120053338028379051879898808320000000e+57);
|
|
verify_options("-1,8607245283054342363818436991534856973992070520151142825984000000e+58", -1.8607245283054342363818436991534856973992070520151142825984000000e+58);
|
|
verify_options("-1,9189205311132686907264385602245237137907390376574976000000000000e+52", -1.9189205311132686907264385602245237137907390376574976000000000000e+52);
|
|
verify_options("-2,8184483231688951563253238886553506793085187889855201280000000000e+54", -2.8184483231688951563253238886553506793085187889855201280000000000e+54);
|
|
verify_options("-1,7664960224650106892054063261344555646357024359107788800000000000e+53", -1.7664960224650106892054063261344555646357024359107788800000000000e+53);
|
|
verify_options("-2,1470977154320536489471030463761883783915110400000000000000000000e+45", -2.1470977154320536489471030463761883783915110400000000000000000000e+45);
|
|
verify_options("-4,4900312744003159009338275160799498340862630046359789166919680000e+61", -4.4900312744003159009338275160799498340862630046359789166919680000e+61);
|
|
verify_options("1", 1.0);
|
|
verify_options("1,797693134862315700000000000000001e308", 1.7976931348623157e308);
|
|
verify_options("3e-324", 0x0.0000000000001p-1022);
|
|
verify_options("1,00000006e+09", 0x1.dcd651ep+29);
|
|
verify_options("4,9406564584124653e-324", 0x0.0000000000001p-1022);
|
|
verify_options("4,9406564584124654e-324", 0x0.0000000000001p-1022);
|
|
verify_options("2,2250738585072009e-308", 0x0.fffffffffffffp-1022);
|
|
verify_options("2,2250738585072014e-308", 0x1p-1022);
|
|
verify_options("1,7976931348623157e308", 0x1.fffffffffffffp+1023);
|
|
verify_options("1,7976931348623158e308", 0x1.fffffffffffffp+1023);
|
|
verify_options("4503599627370496,5", 4503599627370496.5);
|
|
verify_options("4503599627475352,5", 4503599627475352.5);
|
|
verify_options("4503599627475353,5", 4503599627475353.5);
|
|
verify_options("2251799813685248,25", 2251799813685248.25);
|
|
verify_options("1125899906842624,125", 1125899906842624.125);
|
|
verify_options("1125899906842901,875", 1125899906842901.875);
|
|
verify_options("2251799813685803,75", 2251799813685803.75);
|
|
verify_options("4503599627370497,5", 4503599627370497.5);
|
|
verify_options("45035996,273704995", 45035996.273704995);
|
|
verify_options("45035996,273704985", 45035996.273704985);
|
|
verify_options("0,000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044501477170144022721148195934182639518696390927032912960468522194496444440421538910330590478162701758282983178260792422137401728773891892910553144148156412434867599762821265346585071045737627442980259622449029037796981144446145705102663115100318287949527959668236039986479250965780342141637013812613333119898765515451440315261253813266652951306000184917766328660755595837392240989947807556594098101021612198814605258742579179000071675999344145086087205681577915435923018910334964869420614052182892431445797605163650903606514140377217442262561590244668525767372446430075513332450079650686719491377688478005309963967709758965844137894433796621993967316936280457084866613206797017728916080020698679408551343728867675409720757232455434770912461317493580281734466552734375", 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044501477170144022721148195934182639518696390927032912960468522194496444440421538910330590478162701758282983178260792422137401728773891892910553144148156412434867599762821265346585071045737627442980259622449029037796981144446145705102663115100318287949527959668236039986479250965780342141637013812613333119898765515451440315261253813266652951306000184917766328660755595837392240989947807556594098101021612198814605258742579179000071675999344145086087205681577915435923018910334964869420614052182892431445797605163650903606514140377217442262561590244668525767372446430075513332450079650686719491377688478005309963967709758965844137894433796621993967316936280457084866613206797017728916080020698679408551343728867675409720757232455434770912461317493580281734466552734375);
|
|
verify_options("0,000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022250738585072008890245868760858598876504231122409594654935248025624400092282356951787758888037591552642309780950434312085877387158357291821993020294379224223559819827501242041788969571311791082261043971979604000454897391938079198936081525613113376149842043271751033627391549782731594143828136275113838604094249464942286316695429105080201815926642134996606517803095075913058719846423906068637102005108723282784678843631944515866135041223479014792369585208321597621066375401613736583044193603714778355306682834535634005074073040135602968046375918583163124224521599262546494300836851861719422417646455137135420132217031370496583210154654068035397417906022589503023501937519773030945763173210852507299305089761582519159720757232455434770912461317493580281734466552734375", 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022250738585072008890245868760858598876504231122409594654935248025624400092282356951787758888037591552642309780950434312085877387158357291821993020294379224223559819827501242041788969571311791082261043971979604000454897391938079198936081525613113376149842043271751033627391549782731594143828136275113838604094249464942286316695429105080201815926642134996606517803095075913058719846423906068637102005108723282784678843631944515866135041223479014792369585208321597621066375401613736583044193603714778355306682834535634005074073040135602968046375918583163124224521599262546494300836851861719422417646455137135420132217031370496583210154654068035397417906022589503023501937519773030945763173210852507299305089761582519159720757232455434770912461317493580281734466552734375);
|
|
}
|
|
|
|
|
|
TEST_CASE("32bit.inf") {
|
|
verify("INF", std::numeric_limits<float>::infinity());
|
|
verify("-INF", -std::numeric_limits<float>::infinity());
|
|
verify("INFINITY", std::numeric_limits<float>::infinity());
|
|
verify("-INFINITY", -std::numeric_limits<float>::infinity());
|
|
verify("infinity", std::numeric_limits<float>::infinity());
|
|
verify("-infinity", -std::numeric_limits<float>::infinity());
|
|
verify("inf", std::numeric_limits<float>::infinity());
|
|
verify("-inf", -std::numeric_limits<float>::infinity());
|
|
verify("1234456789012345678901234567890e9999999999999999999999999999", std::numeric_limits<float>::infinity());
|
|
verify("2e3000", std::numeric_limits<float>::infinity());
|
|
verify("3.5028234666e38", std::numeric_limits<float>::infinity());
|
|
}
|
|
|
|
TEST_CASE("32bit.general") {
|
|
verify("1.1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125", 0x1.2ced3p+0f);
|
|
verify("1.1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125e-38", 0x1.fffff8p-127f);
|
|
verify(append_zeros("1.1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125",655), 0x1.2ced3p+0f);
|
|
verify(append_zeros("1.1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125",656), 0x1.2ced3p+0f);
|
|
verify(append_zeros("1.1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125",1000), 0x1.2ced3p+0f);
|
|
std::string test_string;
|
|
test_string = append_zeros("1.1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125",655) + std::string("e-38");
|
|
verify(test_string, 0x1.fffff8p-127f);
|
|
test_string = append_zeros("1.1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125",656) + std::string("e-38");
|
|
verify(test_string, 0x1.fffff8p-127f);
|
|
test_string = append_zeros("1.1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125",1000) + std::string("e-38");
|
|
verify(test_string, 0x1.fffff8p-127f);
|
|
verify32(1.00000006e+09f);
|
|
verify32(1.4012984643e-45f);
|
|
verify32(1.1754942107e-38f);
|
|
verify32(1.1754943508e-45f);
|
|
verify("-0", -0.0f);
|
|
verify("1090544144181609348835077142190", 0x1.b877ap+99f);
|
|
verify("1.1754943508e-38", 1.1754943508e-38f);
|
|
verify("30219.0830078125", 30219.0830078125f);
|
|
verify("16252921.5", 16252921.5f);
|
|
verify("5322519.25", 5322519.25f);
|
|
verify("3900245.875", 3900245.875f);
|
|
verify("1510988.3125", 1510988.3125f);
|
|
verify("782262.28125", 782262.28125f);
|
|
verify("328381.484375", 328381.484375f);
|
|
verify("156782.0703125", 156782.0703125f);
|
|
verify("85003.24609375", 85003.24609375f);
|
|
verify("17419.6494140625", 17419.6494140625f);
|
|
verify("15498.36376953125", 15498.36376953125f);
|
|
verify("6318.580322265625", 6318.580322265625f);
|
|
verify("2525.2840576171875", 2525.2840576171875f);
|
|
verify("1370.9265747070312", 1370.9265747070312f);
|
|
verify("936.3702087402344", 936.3702087402344f);
|
|
verify("411.88682556152344", 411.88682556152344f);
|
|
verify("206.50310516357422", 206.50310516357422f);
|
|
verify("124.16878890991211", 124.16878890991211f);
|
|
verify("50.811574935913086", 50.811574935913086f);
|
|
verify("17.486443519592285", 17.486443519592285f);
|
|
verify("13.91745138168335", 13.91745138168335f);
|
|
verify("7.5464513301849365", 0x1.e2f90ep+2f);
|
|
verify("2.687217116355896", 2.687217116355896f);
|
|
verify("1.1877630352973938", 0x1.30113ep+0f);
|
|
verify("0.7622503340244293", 0.7622503340244293f);
|
|
verify("0.30531780421733856", 0x1.38a53ap-2f);
|
|
verify("0.21791061013936996", 0x1.be47eap-3f);
|
|
verify("0.09289376810193062", 0x1.7c7e2ep-4f);
|
|
verify("0.03706067614257336", 0.03706067614257336f);
|
|
verify("0.028068351559340954", 0.028068351559340954f);
|
|
verify("0.012114629615098238", 0x1.8cf8e2p-7f);
|
|
verify("0.004221370676532388", 0x1.14a6dap-8f);
|
|
verify("0.002153817447833717", 0.002153817447833717f);
|
|
verify("0.0015924838953651488", 0x1.a175cap-10f);
|
|
verify("0.0008602388261351734", 0.0008602388261351734f);
|
|
verify("0.00036393293703440577", 0x1.7d9c82p-12f);
|
|
verify("0.00013746770127909258", 0.00013746770127909258f);
|
|
verify("16407.9462890625", 16407.9462890625f);
|
|
verify("1.1754947011469036e-38", 0x1.000006p-126f);
|
|
verify("7.0064923216240854e-46", 0x1p-149f);
|
|
verify("8388614.5", 8388614.5f);
|
|
verify("0e9999999999999999999999999999", 0.f);
|
|
verify("4.7019774032891500318749461488889827112746622270883500860350068251e-38",4.7019774032891500318749461488889827112746622270883500860350068251e-38f);
|
|
verify("3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679", 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679f);
|
|
verify("2.3509887016445750159374730744444913556373311135441750430175034126e-38", 2.3509887016445750159374730744444913556373311135441750430175034126e-38f);
|
|
verify("1", 1.f);
|
|
verify("7.0060e-46", 0.f);
|
|
verify("3.4028234664e38", 0x1.fffffep+127f);
|
|
verify("3.4028234665e38", 0x1.fffffep+127f);
|
|
verify("3.4028234666e38", 0x1.fffffep+127f);
|
|
verify("0.000000000000000000000000000000000000011754943508222875079687365372222456778186655567720875215087517062784172594547271728515625", 0.000000000000000000000000000000000000011754943508222875079687365372222456778186655567720875215087517062784172594547271728515625);
|
|
verify("0.00000000000000000000000000000000000000000000140129846432481707092372958328991613128026194187651577175706828388979108268586060148663818836212158203125", 0.00000000000000000000000000000000000000000000140129846432481707092372958328991613128026194187651577175706828388979108268586060148663818836212158203125f);
|
|
verify("0.00000000000000000000000000000000000002350988561514728583455765982071533026645717985517980855365926236850006129930346077117064851336181163787841796875", 0.00000000000000000000000000000000000002350988561514728583455765982071533026645717985517980855365926236850006129930346077117064851336181163787841796875f);
|
|
verify("0.00000000000000000000000000000000000001175494210692441075487029444849287348827052428745893333857174530571588870475618904265502351336181163787841796875", 0.00000000000000000000000000000000000001175494210692441075487029444849287348827052428745893333857174530571588870475618904265502351336181163787841796875f);
|
|
}
|
|
|
|
TEST_CASE("32bit.decimal_point") {
|
|
fast_float::parse_options options{};
|
|
options.decimal_point = ',';
|
|
|
|
// infinity
|
|
verify_options("3,5028234666e38", std::numeric_limits<float>::infinity());
|
|
|
|
// finites
|
|
verify_options("1,1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125", 0x1.2ced3p+0f);
|
|
verify_options("1,1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125e-38", 0x1.fffff8p-127f);
|
|
verify_options(append_zeros("1,1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125",655), 0x1.2ced3p+0f);
|
|
verify_options(append_zeros("1,1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125",656), 0x1.2ced3p+0f);
|
|
verify_options(append_zeros("1,1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125",1000), 0x1.2ced3p+0f);
|
|
std::string test_string;
|
|
test_string = append_zeros("1,1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125",655) + std::string("e-38");
|
|
verify_options(test_string, 0x1.fffff8p-127f);
|
|
test_string = append_zeros("1,1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125",656) + std::string("e-38");
|
|
verify_options(test_string, 0x1.fffff8p-127f);
|
|
test_string = append_zeros("1,1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125",1000) + std::string("e-38");
|
|
verify_options(test_string, 0x1.fffff8p-127f);
|
|
verify_options("1,1754943508e-38", 1.1754943508e-38f);
|
|
verify_options("30219,0830078125", 30219.0830078125f);
|
|
verify_options("1,1754947011469036e-38", 0x1.000006p-126f);
|
|
verify_options("7,0064923216240854e-46", 0x1p-149f);
|
|
verify_options("8388614,5", 8388614.5f);
|
|
verify_options("0e9999999999999999999999999999", 0.f);
|
|
verify_options("4,7019774032891500318749461488889827112746622270883500860350068251e-38",4.7019774032891500318749461488889827112746622270883500860350068251e-38f);
|
|
verify_options("3,1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679", 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679f);
|
|
verify_options("2,3509887016445750159374730744444913556373311135441750430175034126e-38", 2.3509887016445750159374730744444913556373311135441750430175034126e-38f);
|
|
verify_options("1", 1.f);
|
|
verify_options("7,0060e-46", 0.f);
|
|
verify_options("3,4028234664e38", 0x1.fffffep+127f);
|
|
verify_options("3,4028234665e38", 0x1.fffffep+127f);
|
|
verify_options("3,4028234666e38", 0x1.fffffep+127f);
|
|
verify_options("0,000000000000000000000000000000000000011754943508222875079687365372222456778186655567720875215087517062784172594547271728515625", 0.000000000000000000000000000000000000011754943508222875079687365372222456778186655567720875215087517062784172594547271728515625);
|
|
verify_options("0,00000000000000000000000000000000000000000000140129846432481707092372958328991613128026194187651577175706828388979108268586060148663818836212158203125", 0.00000000000000000000000000000000000000000000140129846432481707092372958328991613128026194187651577175706828388979108268586060148663818836212158203125f);
|
|
verify_options("0,00000000000000000000000000000000000002350988561514728583455765982071533026645717985517980855365926236850006129930346077117064851336181163787841796875", 0.00000000000000000000000000000000000002350988561514728583455765982071533026645717985517980855365926236850006129930346077117064851336181163787841796875f);
|
|
verify_options("0,00000000000000000000000000000000000001175494210692441075487029444849287348827052428745893333857174530571588870475618904265502351336181163787841796875", 0.00000000000000000000000000000000000001175494210692441075487029444849287348827052428745893333857174530571588870475618904265502351336181163787841796875f);
|
|
}
|