mirror of
https://github.com/fastfloat/fast_float.git
synced 2026-02-07 02:09:52 +08:00
Separate verify and verify_runtime macros, extend constexpr checks
`verify` runs both runtime and constexpr checks if the constexpr checks are enabled in cmake. `verify_runtime` only runs the runtime checks.
This commit is contained in:
parent
264414c0b0
commit
24b2fdaad0
@ -13,6 +13,10 @@
|
|||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <cfenv>
|
#include <cfenv>
|
||||||
|
|
||||||
|
#if FASTFLOAT_HAS_BIT_CAST
|
||||||
|
#include <bit>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef SUPPLEMENTAL_TEST_DATA_DIR
|
#ifndef SUPPLEMENTAL_TEST_DATA_DIR
|
||||||
#define SUPPLEMENTAL_TEST_DATA_DIR "data/"
|
#define SUPPLEMENTAL_TEST_DATA_DIR "data/"
|
||||||
#endif
|
#endif
|
||||||
@ -573,55 +577,105 @@ std::string append_zeros(std::string str, size_t number_of_zeros) {
|
|||||||
return answer;
|
return answer;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
namespace {
|
||||||
void check_basic_test_result(const std::string& str, fast_float::from_chars_result result,
|
|
||||||
T actual, T expected) {
|
enum class Diag { runtime, comptime };
|
||||||
INFO("str=" << str << "\n"
|
|
||||||
<< " expected=" << fHexAndDec(expected) << "\n"
|
} // anonymous namespace
|
||||||
<< " ..actual=" << fHexAndDec(actual) << "\n"
|
|
||||||
<< " expected mantissa=" << iHexAndDec(get_mantissa(expected)) << "\n"
|
template <Diag diag, class T>
|
||||||
<< " ..actual mantissa=" << iHexAndDec(get_mantissa(actual)));
|
constexpr void check_basic_test_result(std::string_view str,
|
||||||
CHECK_EQ(result.ec, std::errc());
|
fast_float::from_chars_result result,
|
||||||
CHECK_EQ(result.ptr, str.data() + str.size());
|
T actual, T expected) {
|
||||||
CHECK_EQ(copysign(1, actual), copysign(1, expected));
|
if constexpr (diag == Diag::runtime) {
|
||||||
CHECK_EQ(std::isnan(actual), std::isnan(expected));
|
INFO(
|
||||||
CHECK_EQ(actual, expected);
|
"str=" << str << "\n"
|
||||||
|
<< " expected=" << fHexAndDec(expected) << "\n"
|
||||||
|
<< " ..actual=" << fHexAndDec(actual) << "\n"
|
||||||
|
<< " expected mantissa=" << iHexAndDec(get_mantissa(expected))
|
||||||
|
<< "\n"
|
||||||
|
<< " ..actual mantissa=" << iHexAndDec(get_mantissa(actual)));
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ComptimeDiag {
|
||||||
|
// Purposely not constexpr
|
||||||
|
static void error_not_equal() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
#define FASTFLOAT_CHECK_EQ(...) \
|
||||||
|
if constexpr (diag == Diag::runtime) { \
|
||||||
|
CHECK_EQ(__VA_ARGS__); \
|
||||||
|
} else { \
|
||||||
|
if ([](const auto &lhs, const auto &rhs) { \
|
||||||
|
return lhs != rhs; \
|
||||||
|
}(__VA_ARGS__)) { \
|
||||||
|
ComptimeDiag::error_not_equal(); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
auto copysign = [](double x, double y) -> double {
|
||||||
|
#if FASTFLOAT_HAS_BIT_CAST
|
||||||
|
if (fast_float::cpp20_and_in_constexpr()) {
|
||||||
|
using equiv_int = std::make_signed_t<
|
||||||
|
typename fast_float::binary_format<double>::equiv_uint>;
|
||||||
|
const auto i = std::bit_cast<equiv_int>(y);
|
||||||
|
if (i < 0) {
|
||||||
|
return -x;
|
||||||
|
}
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return std::copysign(x, y);
|
||||||
|
};
|
||||||
|
|
||||||
|
FASTFLOAT_CHECK_EQ(result.ec, std::errc());
|
||||||
|
FASTFLOAT_CHECK_EQ(result.ptr, str.data() + str.size());
|
||||||
|
FASTFLOAT_CHECK_EQ(copysign(1, actual), copysign(1, expected));
|
||||||
|
FASTFLOAT_CHECK_EQ(std::isnan(actual), std::isnan(expected));
|
||||||
|
FASTFLOAT_CHECK_EQ(actual, expected);
|
||||||
|
|
||||||
|
#undef FASTFLOAT_CHECK_EQ
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<Diag diag, class T>
|
||||||
void basic_test(std::string str, T expected) {
|
constexpr void basic_test(std::string_view str, T expected) {
|
||||||
T actual;
|
T actual;
|
||||||
auto result = fast_float::from_chars(str.data(), str.data() + str.size(), actual);
|
auto result = fast_float::from_chars(str.data(), str.data() + str.size(), actual);
|
||||||
check_basic_test_result(str, result, actual, expected);
|
check_basic_test_result<diag>(str, result, actual, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<Diag diag, class T>
|
||||||
void basic_test(std::string str, T expected, fast_float::parse_options options) {
|
constexpr void basic_test(std::string_view str, T expected, fast_float::parse_options options) {
|
||||||
T actual;
|
T actual;
|
||||||
auto result = fast_float::from_chars_advanced(str.data(), str.data() + str.size(), actual, options);
|
auto result = fast_float::from_chars_advanced(str.data(), str.data() + str.size(), actual, options);
|
||||||
check_basic_test_result(str, result, actual, expected);
|
check_basic_test_result<diag>(str, result, actual, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
void basic_test(float val) {
|
void basic_test(float val) {
|
||||||
{
|
{
|
||||||
std::string long_vals = to_long_string(val);
|
std::string long_vals = to_long_string(val);
|
||||||
INFO("long vals: " << long_vals);
|
INFO("long vals: " << long_vals);
|
||||||
basic_test<float>(long_vals, val);
|
basic_test<Diag::runtime, float>(long_vals, val);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::string vals = to_string(val);
|
std::string vals = to_string(val);
|
||||||
INFO("vals: " << vals);
|
INFO("vals: " << vals);
|
||||||
basic_test<float>(vals, val);
|
basic_test<Diag::runtime, float>(vals, val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
#define verify_runtime(lhs, rhs) \
|
||||||
template <int>
|
do { \
|
||||||
struct dummy {};
|
INFO(lhs); \
|
||||||
|
basic_test<Diag::runtime>(lhs, rhs); \
|
||||||
|
} while (false)
|
||||||
|
|
||||||
template <auto val>
|
#define verify_comptime(lhs, rhs) \
|
||||||
struct verify_error;
|
do { \
|
||||||
} //anonymous namespace
|
constexpr int verify_comptime_var = \
|
||||||
|
(basic_test<Diag::comptime>(lhs, rhs), 0); \
|
||||||
|
(void)verify_comptime_var; \
|
||||||
|
} while (false)
|
||||||
|
|
||||||
#if defined(FASTFLOAT_CONSTEXPR_TESTS)
|
#if defined(FASTFLOAT_CONSTEXPR_TESTS)
|
||||||
#if !FASTFLOAT_IS_CONSTEXPR
|
#if !FASTFLOAT_IS_CONSTEXPR
|
||||||
@ -630,32 +684,17 @@ struct verify_error;
|
|||||||
|
|
||||||
// Add constexpr testing to verify when the arguments are constant expressions
|
// Add constexpr testing to verify when the arguments are constant expressions
|
||||||
#define verify(lhs, rhs) \
|
#define verify(lhs, rhs) \
|
||||||
{ \
|
do { \
|
||||||
INFO(lhs); \
|
verify_runtime(lhs, rhs); \
|
||||||
basic_test(lhs, rhs); \
|
verify_comptime(lhs, rhs); \
|
||||||
[&]<typename T>() { \
|
} while (false)
|
||||||
if constexpr (requires { \
|
|
||||||
typename ::dummy<(T(lhs), 0)>; \
|
|
||||||
typename ::dummy<((void)(rhs), 0)>; \
|
|
||||||
}) { \
|
|
||||||
constexpr auto sv = T(lhs); \
|
|
||||||
constexpr auto val = [&sv=sv] { \
|
|
||||||
::std::remove_cvref_t<decltype(rhs)> ret; \
|
|
||||||
(void)::fast_float::from_chars(sv.data(), sv.data() + sv.size(), \
|
|
||||||
ret); \
|
|
||||||
return ret; \
|
|
||||||
}(); \
|
|
||||||
static_assert(val == (rhs)); \
|
|
||||||
} \
|
|
||||||
}.operator()<::std::string_view>(); \
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
#define verify(lhs, rhs) { INFO(lhs); basic_test(lhs, rhs); }
|
#define verify verify_runtime
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define verify32(val) { INFO(#val); basic_test(val); }
|
#define verify32(val) { INFO(#val); basic_test(val); }
|
||||||
|
|
||||||
#define verify_options(lhs, rhs) { INFO(lhs); basic_test(lhs, rhs, options); }
|
#define verify_options(lhs, rhs) { INFO(lhs); basic_test<Diag::runtime>(lhs, rhs, options); }
|
||||||
|
|
||||||
TEST_CASE("64bit.inf") {
|
TEST_CASE("64bit.inf") {
|
||||||
verify("INF", std::numeric_limits<double>::infinity());
|
verify("INF", std::numeric_limits<double>::infinity());
|
||||||
@ -682,7 +721,7 @@ TEST_CASE("64bit.general") {
|
|||||||
verify("-2.2222222222223e-322",-0x1.68p-1069);
|
verify("-2.2222222222223e-322",-0x1.68p-1069);
|
||||||
verify("9007199254740993.0", 0x1p+53);
|
verify("9007199254740993.0", 0x1p+53);
|
||||||
verify("860228122.6654514319E+90", 0x1.92bb20990715fp+328);
|
verify("860228122.6654514319E+90", 0x1.92bb20990715fp+328);
|
||||||
verify(append_zeros("9007199254740993.0",1000), 0x1p+53);
|
verify_runtime(append_zeros("9007199254740993.0",1000), 0x1p+53);
|
||||||
verify("10000000000000000000", 0x1.158e460913dp+63);
|
verify("10000000000000000000", 0x1.158e460913dp+63);
|
||||||
verify("10000000000000000000000000000001000000000000", 0x1.cb2d6f618c879p+142);
|
verify("10000000000000000000000000000001000000000000", 0x1.cb2d6f618c879p+142);
|
||||||
verify("10000000000000000000000000000000000000000001", 0x1.cb2d6f618c879p+142);
|
verify("10000000000000000000000000000000000000000001", 0x1.cb2d6f618c879p+142);
|
||||||
@ -816,16 +855,16 @@ TEST_CASE("32bit.general") {
|
|||||||
verify("-1e-999",-0.0f);
|
verify("-1e-999",-0.0f);
|
||||||
verify("1.1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125", 0x1.2ced3p+0f);
|
verify("1.1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125", 0x1.2ced3p+0f);
|
||||||
verify("1.1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125e-38", 0x1.fffff8p-127f);
|
verify("1.1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125e-38", 0x1.fffff8p-127f);
|
||||||
verify(append_zeros("1.1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125",655), 0x1.2ced3p+0f);
|
verify_runtime(append_zeros("1.1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125",655), 0x1.2ced3p+0f);
|
||||||
verify(append_zeros("1.1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125",656), 0x1.2ced3p+0f);
|
verify_runtime(append_zeros("1.1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125",656), 0x1.2ced3p+0f);
|
||||||
verify(append_zeros("1.1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125",1000), 0x1.2ced3p+0f);
|
verify_runtime(append_zeros("1.1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125",1000), 0x1.2ced3p+0f);
|
||||||
std::string test_string;
|
std::string test_string;
|
||||||
test_string = append_zeros("1.1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125",655) + std::string("e-38");
|
test_string = append_zeros("1.1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125",655) + std::string("e-38");
|
||||||
verify(test_string, 0x1.fffff8p-127f);
|
verify_runtime(test_string, 0x1.fffff8p-127f);
|
||||||
test_string = append_zeros("1.1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125",656) + std::string("e-38");
|
test_string = append_zeros("1.1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125",656) + std::string("e-38");
|
||||||
verify(test_string, 0x1.fffff8p-127f);
|
verify_runtime(test_string, 0x1.fffff8p-127f);
|
||||||
test_string = append_zeros("1.1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125",1000) + std::string("e-38");
|
test_string = append_zeros("1.1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125",1000) + std::string("e-38");
|
||||||
verify(test_string, 0x1.fffff8p-127f);
|
verify_runtime(test_string, 0x1.fffff8p-127f);
|
||||||
verify32(1.00000006e+09f);
|
verify32(1.00000006e+09f);
|
||||||
verify32(1.4012984643e-45f);
|
verify32(1.4012984643e-45f);
|
||||||
verify32(1.1754942107e-38f);
|
verify32(1.1754942107e-38f);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user