From 38fbe0c8e65ddc6f4a16f208f72f4beeeddc404a Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Mon, 19 Oct 2020 14:41:10 -0400 Subject: [PATCH] Tuning. --- CMakeLists.txt | 2 +- tests/CMakeLists.txt | 2 +- tests/basictest.cpp | 28 ++++----- tests/long_random64.cpp | 13 +++-- tests/random64.cpp | 14 +++-- tests/random_string.cpp | 21 ++++--- tests/test.cpp | 122 ---------------------------------------- 7 files changed, 45 insertions(+), 157 deletions(-) delete mode 100644 tests/test.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index ac129c6..76ecaa4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,4 +31,4 @@ endif() if(FASTFLOAT_TEST) enable_testing() add_subdirectory(tests) -endif(FASTFLOAT_SANITIZE) \ No newline at end of file +endif(FASTFLOAT_TEST) \ No newline at end of file diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 3eb4935..31b42a5 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -14,4 +14,4 @@ fast_float_add_cpp_test(long_exhaustive32_64) fast_float_add_cpp_test(long_random64) fast_float_add_cpp_test(random64) fast_float_add_cpp_test(basictest) -fast_float_add_cpp_test(example_test) +fast_float_add_cpp_test(example_test) \ No newline at end of file diff --git a/tests/basictest.cpp b/tests/basictest.cpp index 7542399..ee09314 100644 --- a/tests/basictest.cpp +++ b/tests/basictest.cpp @@ -185,25 +185,25 @@ int main() { Assert(basic_test_32bit("50.811574935913086",50.811574935913086f)); Assert(basic_test_32bit("17.486443519592285",17.486443519592285f)); Assert(basic_test_32bit("13.91745138168335",13.91745138168335f)); - Assert(basic_test_32bit("7.5464513301849365",7.5464513301849365f)); + Assert(basic_test_32bit("7.5464513301849365",0x1.e2f90ep+2f)); Assert(basic_test_32bit("2.687217116355896",2.687217116355896f)); - Assert(basic_test_32bit("1.1877630352973938",1.1877630352973938f)); + Assert(basic_test_32bit("1.1877630352973938",0x1.30113ep+0f)); Assert(basic_test_32bit("0.7622503340244293",0.7622503340244293f)); - Assert(basic_test_32bit("0.30531780421733856",0.30531780421733856f)); - Assert(basic_test_32bit("0.21791061013936996",0.21791061013936996f)); - Assert(basic_test_32bit("0.09289376810193062",0.09289376810193062f)); + Assert(basic_test_32bit("0.30531780421733856",0x1.38a53ap-2f)); + Assert(basic_test_32bit("0.21791061013936996",0x1.be47eap-3f)); + Assert(basic_test_32bit("0.09289376810193062",0x1.7c7e2ep-4f)); Assert(basic_test_32bit("0.03706067614257336",0.03706067614257336f)); Assert(basic_test_32bit("0.028068351559340954",0.028068351559340954f)); - Assert(basic_test_32bit("0.012114629615098238",0.012114629615098238f)); - Assert(basic_test_32bit("0.004221370676532388",0.004221370676532388f)); + Assert(basic_test_32bit("0.012114629615098238",0x1.8cf8e2p-7f)); + Assert(basic_test_32bit("0.004221370676532388",0x1.14a6dap-8f)); Assert(basic_test_32bit("0.002153817447833717",0.002153817447833717f)); - Assert(basic_test_32bit("0.0015924838953651488",0.0015924838953651488f)); + Assert(basic_test_32bit("0.0015924838953651488",0x1.a175cap-10f)); Assert(basic_test_32bit("0.0008602388261351734",0.0008602388261351734f)); - Assert(basic_test_32bit("0.00036393293703440577",0.00036393293703440577f)); + Assert(basic_test_32bit("0.00036393293703440577",0x1.7d9c82p-12f)); Assert(basic_test_32bit("0.00013746770127909258",0.00013746770127909258)); Assert(basic_test_32bit("16407.9462890625", 16407.9462890625f)); - Assert(basic_test_32bit("1.1754947011469036e-38", 1.1754947011469036e-38f)); - Assert(basic_test_32bit("7.0064923216240854e-46", 7.0064923216240854e-46f)); + Assert(basic_test_32bit("1.1754947011469036e-38", 0x1.000006p-126f)); + Assert(basic_test_32bit("7.0064923216240854e-46", 0x1p-149f)); Assert(basic_test_32bit("8388614.5", 8388614.5f)); Assert(basic_test_32bit("0e9999999999999999999999999999", 0)); Assert(basic_test_32bit("1234456789012345678901234567890e9999999999999999999999999999", std::numeric_limits::infinity())); @@ -218,9 +218,9 @@ int main() { Assert(basic_test_32bit(1.4012984643e-45f)); Assert(basic_test_32bit(1.1754942107e-38f)); Assert(basic_test_32bit(1.1754943508e-45f)); - Assert(basic_test_32bit(3.4028234664e38f)); - Assert(basic_test_32bit(3.4028234665e38f)); - Assert(basic_test_32bit(3.4028234666e38f)); + Assert(basic_test_32bit("3.4028234664e38", 0x1.fffffep+127f)); + Assert(basic_test_32bit("3.4028234665e38", 0x1.fffffep+127f)); + Assert(basic_test_32bit("3.4028234666e38", 0x1.fffffep+127f)); Assert(basic_test_32bit("0.000000000000000000000000000000000000011754943508222875079687365372222456778186655567720875215087517062784172594547271728515625", 0.000000000000000000000000000000000000011754943508222875079687365372222456778186655567720875215087517062784172594547271728515625)); Assert(basic_test_32bit("0.00000000000000000000000000000000000000000000140129846432481707092372958328991613128026194187651577175706828388979108268586060148663818836212158203125", 0.00000000000000000000000000000000000000000000140129846432481707092372958328991613128026194187651577175706828388979108268586060148663818836212158203125)); Assert(basic_test_32bit("0.00000000000000000000000000000000000002350988561514728583455765982071533026645717985517980855365926236850006129930346077117064851336181163787841796875", 0.00000000000000000000000000000000000002350988561514728583455765982071533026645717985517980855365926236850006129930346077117064851336181163787841796875)); diff --git a/tests/long_random64.cpp b/tests/long_random64.cpp index 10149dd..fbca91c 100644 --- a/tests/long_random64.cpp +++ b/tests/long_random64.cpp @@ -10,7 +10,7 @@ template char *to_string(T d, char *buffer) { return buffer + written; } -static __uint128_t g_lehmer64_state; +static fast_float::value128 g_lehmer64_state; /** * D. H. Lehmer, Mathematical methods in large-scale computing units. @@ -24,11 +24,16 @@ static __uint128_t g_lehmer64_state; * Society 68.225 (1999): 249-260. */ -static inline void lehmer64_seed(uint64_t seed) { g_lehmer64_state = seed; } +static inline void lehmer64_seed(uint64_t seed) { + g_lehmer64_state.high = 0; + g_lehmer64_state.low = seed; +} static inline uint64_t lehmer64() { - g_lehmer64_state *= UINT64_C(0xda942042e4dd58b5); - return uint64_t(g_lehmer64_state >> 64); + fast_float::value128 v = fast_float::full_multiplication(g_lehmer64_state.low,UINT64_C(0xda942042e4dd58b5)); + v.high += g_lehmer64_state.high * UINT64_C(0xda942042e4dd58b5); + g_lehmer64_state = v; + return v.high; } size_t errors; diff --git a/tests/random64.cpp b/tests/random64.cpp index c6489b9..aaaa5bd 100644 --- a/tests/random64.cpp +++ b/tests/random64.cpp @@ -10,7 +10,8 @@ template char *to_string(T d, char *buffer) { return buffer + written; } -static __uint128_t g_lehmer64_state; + +static fast_float::value128 g_lehmer64_state; /** * D. H. Lehmer, Mathematical methods in large-scale computing units. @@ -24,11 +25,16 @@ static __uint128_t g_lehmer64_state; * Society 68.225 (1999): 249-260. */ -static inline void lehmer64_seed(uint64_t seed) { g_lehmer64_state = seed; } +static inline void lehmer64_seed(uint64_t seed) { + g_lehmer64_state.high = 0; + g_lehmer64_state.low = seed; +} static inline uint64_t lehmer64() { - g_lehmer64_state *= UINT64_C(0xda942042e4dd58b5); - return uint64_t(g_lehmer64_state >> 64); + fast_float::value128 v = fast_float::full_multiplication(g_lehmer64_state.low,UINT64_C(0xda942042e4dd58b5)); + v.high += g_lehmer64_state.high * UINT64_C(0xda942042e4dd58b5); + g_lehmer64_state = v; + return v.high; } size_t errors; diff --git a/tests/random_string.cpp b/tests/random_string.cpp index c0ba992..b40eb07 100644 --- a/tests/random_string.cpp +++ b/tests/random_string.cpp @@ -11,11 +11,10 @@ public: // Inspired from // https://github.com/lemire/testingRNG/blob/master/source/wyhash.h wyhash64_x_ += UINT64_C(0x60bee2bee120fc15); - __uint128_t tmp; - tmp = (__uint128_t)wyhash64_x_ * UINT64_C(0xa3b195354a39b70d); - uint64_t m1 = (tmp >> 64) ^ tmp; - tmp = (__uint128_t)m1 * UINT64_C(0x1b03738712fad5c9); - uint64_t m2 = (tmp >> 64) ^ tmp; + fast_float::value128 tmp = fast_float::full_multiplication(wyhash64_x_, UINT64_C(0xa3b195354a39b70d)); + uint64_t m1 = (tmp.high) ^ tmp.low; + tmp = fast_float::full_multiplication(m1, UINT64_C(0x1b03738712fad5c9)); + uint64_t m2 = (tmp.high) ^ tmp.low; return m2; } bool next_bool() { return (next() & 1) == 1; } @@ -31,17 +30,17 @@ public: }*/ int s = max - min + 1; uint64_t x = next(); - __uint128_t m = (__uint128_t)x * (__uint128_t)s; - uint64_t l = (uint64_t)m; + fast_float::value128 m = fast_float::full_multiplication(x, s); + uint64_t l = m.low; if (l < s) { uint64_t t = -s % s; while (l < t) { x = next(); - m = (__uint128_t)x * (__uint128_t)s; - l = (uint64_t)m; + m = fast_float::full_multiplication(x, s); + l = m.low; } } - return (m >> 64) + min; + return (m.high) + min; } int next_digit() { return next_ranged_int(0, 9); } @@ -113,7 +112,7 @@ std::pair strtof_from_string(char *st) { #endif if (st == pr) { std::cerr << "strtof_l could not parse '" << st << std::endl; - return std::make_pair(0, false); + return std::make_pair(0.0f, false); } return std::make_pair(d, true); } diff --git a/tests/test.cpp b/tests/test.cpp deleted file mode 100644 index 93bc670..0000000 --- a/tests/test.cpp +++ /dev/null @@ -1,122 +0,0 @@ -#include "fast_float/fast_float.h" - -#include - -inline void Assert(bool Assertion) { - if (!Assertion) - throw std::runtime_error("bug"); -} - -template std::string to_string(T d) { - std::string s(64, '\0'); - auto written = std::snprintf(&s[0], s.size(), "%.*e", - std::numeric_limits::max_digits10 - 1, d); - s.resize(written); - return s; -} - -bool demo32(std::string vals) { - float result_value; - auto result = fast_float::from_chars(vals.data(), vals.data() + vals.size(), - result_value); - if (result.ec != std::errc()) { - std::cerr << " I could not parse " << vals << std::endl; - return false; - } - - std::cout << result_value << std::endl; - return true; -} - -bool demo32(std::string vals, float val) { - float result_value; - auto result = fast_float::from_chars(vals.data(), vals.data() + vals.size(), - result_value); - if (result.ec != std::errc()) { - std::cerr << " I could not parse " << vals << std::endl; - return false; - } - if (std::isnan(val)) { - if (!std::isnan(result_value)) { - std::cerr << "not nan" << result_value << std::endl; - return false; - } - } else if (result_value != val) { - std::cerr << "I got " << std::setprecision(15) << result_value << " but I was expecting " << val - << std::endl; - uint32_t word; - memcpy(&word, &result_value, sizeof(word)); - std::cout << "got mantissa = " << (word & ((1<<23)-1)) << std::endl; - memcpy(&word, &val, sizeof(word)); - std::cout << "wanted mantissa = " << (word & ((1<<23)-1)) << std::endl; - std::cerr << "string: " << vals << std::endl; - return false; - } - std::cout << result_value << " == " << val << std::endl; - return true; -} - -bool demo32(float val) { - std::string vals = to_string(val); - return demo32(vals, val); -} - -bool demo64(std::string vals, double val) { - double result_value; - auto result = fast_float::from_chars(vals.data(), vals.data() + vals.size(), - result_value); - if (result.ec != std::errc()) { - std::cerr << " I could not parse " << vals << std::endl; - return false; - } - if (std::isnan(val)) { - if (!std::isnan(result_value)) { - std::cerr << "not nan" << result_value << std::endl; - return false; - } - } else if (result_value != val) { - std::cerr << "I got " << std::setprecision(15) << result_value << " but I was expecting " << val - << std::endl; - std::cerr << "string: " << vals << std::endl; - return false; - } - std::cout << result_value << " == " << val << std::endl; - - return true; -} -bool demo64(double val) { - std::string vals = to_string(val); - return demo64(vals, val); -} - -int main() { - std::cout << "32 bits " << std::endl; - Assert(demo64("+1", 1)); - Assert(demo64("2e3000", std::numeric_limits::infinity())); - Assert(demo32("3.5028234666e38", std::numeric_limits::infinity())); - Assert(demo32("7.0060e-46", 0)); - Assert(demo32(1.00000006e+09f)); - Assert(demo32(1.4012984643e-45f)); - Assert(demo32(1.1754942107e-38f)); - Assert(demo32(1.1754943508e-45f)); - Assert(demo32(3.4028234664e38f)); - Assert(demo32(3.4028234665e38f)); - Assert(demo32(3.4028234666e38f)); - std::cout << std::endl; - - std::cout << "64 bits " << std::endl; - Assert(demo64("+1", 1)); - Assert(demo64("2e3000", std::numeric_limits::infinity())); - Assert(demo64("1.9e308", std::numeric_limits::infinity())); - Assert(demo64(3e-324)); - Assert(demo32(1.00000006e+09f)); - Assert(demo64(4.9406564584124653e-324)); - Assert(demo64(4.9406564584124654e-324)); - Assert(demo64(2.2250738585072009e-308)); - Assert(demo64(2.2250738585072014e-308)); - Assert(demo64(1.7976931348623157e308)); - Assert(demo64(1.7976931348623158e308)); - std::cout << std::endl; - std::cout << "All ok" << std::endl; - return EXIT_SUCCESS; -}