diff --git a/include/boost/multiprecision/cpp_double_fp.hpp b/include/boost/multiprecision/cpp_double_fp.hpp index f8bbd907..9265fea4 100644 --- a/include/boost/multiprecision/cpp_double_fp.hpp +++ b/include/boost/multiprecision/cpp_double_fp.hpp @@ -1528,7 +1528,6 @@ constexpr auto eval_pow(cpp_double_fp_backend& result, const constexpr double_float_type one { 1 }; const int fpc_x { eval_fpclassify(x) }; - const int fpc_a { eval_fpclassify(a) }; if (fpc_a == FP_ZERO) { @@ -1781,8 +1780,6 @@ constexpr auto eval_exp(cpp_double_fp_backend& result, const const double_float_type top = (n84 * r * (n7920 + (n240 + r2) * r2)); const double_float_type bot = (n665280 + r * (-n332640 + r * (n75600 + r * (-n10080 + r * (n840 + (-n42 + r) * r))))); - constexpr double_float_type one { 1 }; - result = one + (top / bot); // Rescale the result. @@ -1905,8 +1902,6 @@ constexpr auto eval_exp(cpp_double_fp_backend& result, const const double_float_type top = (n144 * r) * (n3603600 + r2 * (n120120 + r2 * (n770 + r2))); const double_float_type bot = (n518918400 + r * (-n259459200 + r * (n60540480 + r * (-n8648640 + r * (n831600 + r * (-n55440 + r * (n2520 + r * (-n72 + r)))))))); - constexpr double_float_type one { 1 }; - result = one + (top / bot); // Rescale the result. @@ -2011,7 +2006,7 @@ constexpr auto eval_exp(cpp_double_fp_backend& result, const double_float_type x_pow_n_div_n_fact(xh); - result = double_float_type(1U) + x_pow_n_div_n_fact; + result = one + x_pow_n_div_n_fact; double_float_type dummy { }; diff --git a/performance/performance_test_df.cpp b/performance/performance_test_df.cpp deleted file mode 100644 index 2e3157a8..00000000 --- a/performance/performance_test_df.cpp +++ /dev/null @@ -1,287 +0,0 @@ -/////////////////////////////////////////////////////////////// -// Copyright John Maddock 2019. -// Copyright Christopher Kormanyos 2021 - 2025. -// Distributed under the Boost -// Software License, Version 1.0. (See accompanying file -// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt - -// This version of "performance_test_df.cpp" is based almost entirely on -// the original "performance_test.cpp". But it has been specifically -// adapted to test various backends in small precision ranges in order -// to check the performance comparison with cpp_double_double. - -#include - -#if !defined(TEST_CPP_DOUBLE_FLOAT) -#define TEST_CPP_DOUBLE_FLOAT -#endif - -#if !defined(TEST_CPP_BIN_FLOAT) -#define TEST_CPP_BIN_FLOAT -#endif - -#if !defined(TEST_CPP_DEC_FLOAT) -#define TEST_CPP_DEC_FLOAT -#endif - -#if defined(BOOST_HAS_FLOAT128) -#if !defined(TEST_FLOAT128) -#define TEST_FLOAT128 -#endif -#endif - -#include - -#if defined(TEST_CPP_DOUBLE_FLOAT) -#include -#endif - -#if defined(TEST_CPP_BIN_FLOAT) -#include -#endif - -#if defined(TEST_CPP_BIN_FLOAT) -#include -#endif - -#if defined(TEST_FLOAT128) -#include -#endif - -#include "performance_test_df.hpp" - -// cd /mnt/c/Users/ckorm/Documents/Ks/PC_Software/Test -// g++ -std=gnu++14 -Wall -Wextra -O3 -I/mnt/c/ChrisGitRepos/modular_boost/multiprecision/performance -I/mnt/c/ChrisGitRepos/modular_boost/multiprecision/include -I/mnt/c/boost/boost_1_89_0 ./test.cpp -lquadmath -o test - -// -// Keys in order are: -// Category -// Operator -// Type -// Precision -// Time -// -std::map > > > result_table; - -unsigned bits_wanted; // for integer types - -void quickbook_results() -{ - // - // Keys in order are: - // Category - // Operator - // Type - // Precision - // Time - // - typedef std::map > > >::const_iterator category_iterator; - typedef std::map > >::const_iterator operator_iterator; - typedef std::map >::const_iterator type_iterator; - typedef std::map::const_iterator precision_iterator; - - for (category_iterator i = result_table.begin(); i != result_table.end(); ++i) - { - std::string cat = i->first; - cat[0] = (char)std::toupper((char)cat[0]); - std::cout << "[section:" << i->first << "_performance " << cat << " Type Perfomance]" << std::endl; - - for (operator_iterator j = i->second.begin(); j != i->second.end(); ++j) - { - std::string op = j->first; - std::cout << "[table Operator " << op << std::endl; - std::cout << "[[Backend]"; - - for (precision_iterator k = j->second.begin()->second.begin(); k != j->second.begin()->second.end(); ++k) - { - std::cout << "[" << k->first << " Bits]"; - } - std::cout << "]\n"; - - std::vector best_times(j->second.begin()->second.size(), (std::numeric_limits::max)()); - for (unsigned m = 0; m < j->second.begin()->second.size(); ++m) - { - for (type_iterator k = j->second.begin(); k != j->second.end(); ++k) - { - if (m < k->second.size()) - { - precision_iterator l = k->second.begin(); - std::advance(l, m); - if (best_times[m] > l->second) - best_times[m] = l->second ? l->second : best_times[m]; - } - } - } - - for (type_iterator k = j->second.begin(); k != j->second.end(); ++k) - { - std::cout << "[[" << k->first << "]"; - - unsigned m = 0; - for (precision_iterator l = k->second.begin(); l != k->second.end(); ++l) - { - double rel_time = l->second / best_times[m]; - if (rel_time == 1) - std::cout << "[[*" << rel_time << "]"; - else - std::cout << "[" << rel_time; - std::cout << " (" << l->second << "s)]"; - ++m; - } - - std::cout << "]\n"; - } - - std::cout << "]\n"; - } - - std::cout << "[endsect]" << std::endl; - } -} - -#if defined(__HAS_INCLUDE) -#if __has_include() -#define HAS_UTSNAME -#include -#endif -#endif -#ifdef _WIN32 -#include -#endif - -void quickbook_platform_details() -{ - std::cout << "[table:platform Platform Details\n[[Platform]["; -#ifdef HAS_UTSNAME - utsname name; - uname(&name); - std::cout << name.sysname << " " << name.release << ", version " << name.version << ", " << name.machine << "]]\n"; -#elif defined(_WIN32) - std::cout << "Windows "; -#ifdef _M_AMD64 - std::cout << "x64"; -#elif defined(_M_IX86) - std::cout << "x86"; -#endif - std::cout << "]]\n"; -#endif - std::cout << "[[Compiler][" << BOOST_COMPILER << "]]\n"; - std::cout << "[[Boost][" << BOOST_VERSION << "]]\n"; - std::cout << "[[Run date][" << __DATE__ << "]]\n"; - std::cout << "]\n\n"; -} - -namespace local { - -void test29(); -void test32(); -void test52(); -void test53(); - -#ifdef TEST_CPP_DOUBLE_FLOAT -template -constexpr inline auto (max)(T a, T b) noexcept -> T { return a > b ? a : b; } -#endif - -} // namespace local - -int main() -{ - quickbook_platform_details(); - - local::test29(); - local::test32(); - local::test52(); - #if defined(BOOST_MP_CPP_DOUBLE_FP_HAS_FLOAT128) - local::test53(); - #endif - - quickbook_results(); -} - -#ifdef TEST_CPP_DOUBLE_FLOAT -using double_float_of_double_type = boost::multiprecision::cpp_double_double; - -constexpr auto digits10_for_performance_test = (local::max)(std::numeric_limits::digits10, 32); -#else -constexpr auto digits10_for_performance_test = 32; -#endif - -void local::test29() -{ -#ifdef TEST_CPP_DEC_FLOAT - static_assert(digits10_for_performance_test >= 32, "Error: Too few digits for performance comparison"); - - using cpp_dec_float_type = - boost::multiprecision::number, - boost::multiprecision::et_off>; - - test("cpp_dec_float", digits10_for_performance_test); -#endif -} - -void local::test32() -{ -#ifdef TEST_CPP_BIN_FLOAT - static_assert(digits10_for_performance_test >= 32, "Error: Too few digits for performance comparison"); - - using cpp_bin_float_type = - boost::multiprecision::number, - boost::multiprecision::et_off>; - - test("cpp_bin_float", digits10_for_performance_test); -#endif -} - -void local::test52() -{ -#ifdef TEST_CPP_DOUBLE_FLOAT - test("cpp_double_fp_backend", digits10_for_performance_test); -#endif -} - -void local::test53() -{ -#if defined(BOOST_HAS_FLOAT128) -#ifdef TEST_FLOAT128 - using boost::multiprecision::float128; - - test("boost::multiprecision::float128(at)", std::numeric_limits::digits10); -#endif -#endif -} - -#if 0 - -See also: https://github.com/BoostGSoC21/multiprecision/issues/178#issuecomment-2580157139 - -## section:float_performance Float Type Perfomance - -| Operation | `float128` |`cpp_bin_float<32>` | `cpp_dec_float<32>` | `cpp_double_fp_backend` | -|---------------------------------|----------------------|------------------------|------------------------|---------------------------------| -| `*` | 1.45209 (0.0530208s) | 1.4866 (0.054281s) | 4.38403 (0.160076s) | [*1] (0.0365135s) | -| `*(int)` | 1.54876 (0.0396009s) | 2.08722 (0.0533689s) | 5.97016 (0.152653s) | [*1] (0.0255694s) | -| `*(unsigned long long)` | 1.66579 (0.083952s) | 1.109 (0.0558912s) | 3.64263 (0.18358s) | [*1] (0.0503976s) | -| `*=(unsigned long long)` | 1.70531 (0.0858822s) | 1.06861 (0.053817s) | 3.47129 (0.17482s) | [*1] (0.0503617s) | -| `+` | 2.4858 (0.0430852s) | 5.38736 (0.0933768s) | 3.06832 (0.0531818s) | [*1] (0.0173326s) | -| `+(int)` | 2.96871 (0.0360276s) | 7.95354 (0.0965222s) | 5.97545 (0.0725166s) | [*1] (0.0121358s) | -| `+(unsigned long long)` | 3.38383 (0.0739771s) | 5.51557 (0.120581s) | 4.42454 (0.0967292s) | [*1] (0.021862s) | -| `+=(unsigned long long)` | 3.3944 (0.0760423s) | 4.98724 (0.111726s) | 3.92369 (0.0878995s) | [*1] (0.0224023s) | -| `-` | 2.20087 (0.0389465s) | 5.40743 (0.0956897s) | 3.24191 (0.0573686s) | [*1] (0.0176959s) | -| `-(int)` | 3.21093 (0.0383358s) | 8.65589 (0.103344s) | 7.53768 (0.0899936s) | [*1] (0.0119392s) | -| `-(unsigned long long)` | 3.45536 (0.075553s) | 5.17747 (0.113208s) | 4.63221 (0.101285s) | [*1] (0.0218654s) | -| `-=(unsigned long long)` | 2.73635 (0.0764208s) | 3.773 (0.105372s) | 3.39784 (0.0948951s) | [*1] (0.027928s) | -| `/` | 1.38437 (0.148412s) | 7.55692 (0.810141s) | 23.5198 (2.52144s) | [*1] (0.107205s) | -| `/(int)` | 1.53126 (0.0384472s) | 6.85045 (0.172002s) | 49.004 (1.2304s) | [*1] (0.0251081s) | -| `/(unsigned long long)` | 2.41876 (0.098966s) | 9.80113 (0.401023s) | 30.6916 (1.25578s) | [*1] (0.040916s) | -| `/=(unsigned long long)` | 1.88263 (0.0994829s) | 7.33976 (0.387852s) | 23.6024 (1.24721s) | [*1] (0.0528426s) | -| `construct` | [*1] (0.000550501s) | 4.74042 (0.00260961s) | 13.0381 (0.00717748s) | 3.51129 (0.00193297s) | -| `construct(unsigned long long)` | 5.33373 (0.0401408s) | 2.82475 (0.0212586s) | 3.38482 (0.0254736s) | [*1] (0.00752583s) | -| `construct(unsigned)` | 23.3495 (0.0403851s) | 12.4928 (0.0216075s) | 14.3869 (0.0248834s) | [*1] (0.00172959s) | -| `exp` | 1.37724 (1.66978s) | 5.45487 (6.61357s) | 5.19473 (6.29817s) | [*1] (1.21242s) | -| `log` | [*1] (2.1149s) | 7.38874 (15.6264s) | 27.0206 (57.146s) | 1.10118 (2.32888s) | -| `sqrt` | 25.9413 (0.53951s) | 24.5484 (0.510541s) | 131.925 (2.74368s) | [*1] (0.0207973s) | -| `str` | [*1] (0.000419145s) | 1.50425 (0.000630497s) | 1.22795 (0.000514689s) | 1.82207 (0.000763711s) | -| `tan` | 1.3995 (1.69463s) | 5.46528 (6.61782s) | 5.20608 (6.30396s) | [*1] (1.21088s) | - -#endif diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 21cfc547..27862f93 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -512,6 +512,8 @@ test-suite functions_and_limits : [ run test_cpp_bin_float_tgamma.cpp ] [ run test_cpp_dec_float_tgamma.cpp ] + [ run test_cpp_double_float_tgamma.cpp : : : [ check-target-builds ../config//has_float128 : quadmath ] ] + [ run test_cpp_double_float_bessel_versus_bin_and_dec.cpp : : : [ check-target-builds ../config//has_float128 : quadmath ] ] [ run test_roots_10k_digits.cpp : # command line diff --git a/performance/performance_test_df_local.cpp b/test/test_cpp_double_float_bessel_versus_bin_and_dec.cpp similarity index 66% rename from performance/performance_test_df_local.cpp rename to test/test_cpp_double_float_bessel_versus_bin_and_dec.cpp index c833c0b4..ee2aea7e 100644 --- a/performance/performance_test_df_local.cpp +++ b/test/test_cpp_double_float_bessel_versus_bin_and_dec.cpp @@ -4,8 +4,9 @@ // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt -// This version of "performance_test_df_local.cpp" is intended -// for specific function-by-function comparisons with cpp_double_double. +// This test file is executes a specific function-by-function +// comparison of cpp_double_double with other backends having +// similar digit counts. #include #include @@ -15,7 +16,6 @@ #include #endif -#include #include #include #include @@ -25,10 +25,10 @@ #include #include -#if defined(_MSC_VER) && !defined(__GNUC__) +#if (defined(BOOST_MSVC) && !defined(BOOST_GCC)) #define STOPWATCH_NODISCARD #else -#if (defined(__cplusplus) && (__cplusplus >= 201703L)) +#if (defined(BOOST_CXX_VERSION) && (BOOST_CXX_VERSION >= 201703L)) #define STOPWATCH_NODISCARD [[nodiscard]] // NOLINT(cppcoreguidelines-macro-usage) #else #define STOPWATCH_NODISCARD @@ -50,7 +50,7 @@ public: } template - static auto elapsed_time(const stopwatch& my_stopwatch) noexcept -> RepresentationRequestedTimeType + static auto elapsed_time(const stopwatch& my_stopwatch) -> RepresentationRequestedTimeType { using local_time_type = RepresentationRequestedTimeType; @@ -107,14 +107,7 @@ private: #else - const time_point_type - elapsed_ns - { - static_cast - ( - stop - m_start - ) - }; + const time_point_type elapsed_ns { static_cast(stop - m_start) }; #endif @@ -126,18 +119,6 @@ private: namespace util { -template(UINT8_C(10)), - const bool UpperCase = true> -auto baselexical_cast(const UnsignedIntegerType& u, char* first, char* last) -> const char* -{ - constexpr auto my_base = static_cast(BaseRepresentation); - - const auto result = std::to_chars(first, last, u, my_base); - - return result.ptr; -} - template auto util_pseudorandom_time_point_seed() -> UnsignedIntegralType { @@ -151,48 +132,37 @@ auto util_pseudorandom_time_point_seed() -> UnsignedIntegralType std::uniform_int_distribution dist_sgn(UINT32_C( 0), UINT32_C( 1)); // NOLINT(cert-err58-cpp,cppcoreguidelines-avoid-non-const-global-variables) std::uniform_int_distribution dist_dig(UINT32_C(0x31), UINT32_C( 0x39)); // NOLINT(cert-err58-cpp,cppcoreguidelines-avoid-non-const-global-variables) -using eng_sgn_type = std::ranlux24; -using eng_dig_type = std::minstd_rand0; -using eng_exp_type = std::mt19937; +using eng_sgn_type = std::minstd_rand0; +using eng_dig_type = std::mt19937_64; eng_sgn_type eng_sgn; // NOLINT(cert-msc32-c,cert-msc51-cpp,cert-err58-cpp,cppcoreguidelines-avoid-non-const-global-variables) eng_dig_type eng_dig; // NOLINT(cert-msc32-c,cert-msc51-cpp,cert-err58-cpp,cppcoreguidelines-avoid-non-const-global-variables) -template -auto generate_wide_decimal_value(bool is_positive = false, - int digits10_to_get = std::numeric_limits::digits10 - 2) -> FloatingPointTypeWithStringConstruction +template +auto generate_wide_decimal_value(int digits10_to_get = std::numeric_limits::digits10 - 2) -> std::string { - using local_floating_point_type = FloatingPointTypeWithStringConstruction; + using local_floating_point_type = FloatingPointType; static_assert(std::numeric_limits::digits10 > static_cast(INT8_C(9)), "Error: Floating-point type destination does not have enough digits10"); - std::string str_x(static_cast(digits10_to_get), '0'); + std::string str_x(static_cast(digits10_to_get + 1), '0'); - std::generate(str_x.begin(), + // Get the leading digit before the decimal point. + str_x[std::string::size_type { UINT8_C(0) }] = static_cast(dist_dig(eng_dig)); + + // Insert a decimal point. + str_x[std::string::size_type { UINT8_C(1) }] = '.'; + + std::generate(str_x.begin() + std::string::size_type { UINT8_C(2) }, str_x.end(), []() // NOLINT(modernize-use-trailing-return-type,-warnings-as-errors) { return static_cast(dist_dig(eng_dig)); }); - // Insert a decimal point. - str_x.insert(static_cast(UINT8_C(1)), static_cast(UINT8_C(1)), '.'); - - // Insert either a positive sign or a negative sign - // (always one or the other) depending on the sign of x. - const auto sign_char_to_insert = - static_cast - ( - is_positive - ? '+' - : static_cast((dist_sgn(eng_sgn) != static_cast(UINT8_C(0))) ? '+' : '-') - ); - - str_x.insert(static_cast(UINT8_C(0)), static_cast(UINT8_C(1)), sign_char_to_insert); - - return local_floating_point_type(str_x.c_str()); -} + return str_x; +} // LCOV_EXCL_LINE template auto is_close_fraction(const NumericType& a, @@ -217,21 +187,31 @@ auto is_close_fraction(const NumericType& a, return result_is_ok; } -auto main() -> int +auto do_trials(const std::size_t trial_count) -> void { + static std::size_t heat_count { }; + + std::cout << "\nheat_count: " << ++heat_count << std::endl; + using dbl_float_type = boost::multiprecision::cpp_double_double; - using dec_float_type = boost::multiprecision::number, boost::multiprecision::et_off>; + + constexpr int local_digits10 = ((std::numeric_limits::digits10 < 32) ? 32 : std::numeric_limits::digits10); + + using dec_float_type = boost::multiprecision::number, boost::multiprecision::et_off>; + using bin_float_type = boost::multiprecision::number, boost::multiprecision::et_off>; #if defined(BOOST_HAS_FLOAT128) using flt_float_type = boost::multiprecision::float128; #endif - constexpr std::size_t trials { UINT32_C(100000) }; + const std::size_t trials { trial_count }; std::vector dbl_float_a_vec (trials); std::vector dbl_float_b_vec (dbl_float_a_vec.size()); std::vector dec_float_a_vec (dbl_float_a_vec.size()); std::vector dec_float_b_vec (dbl_float_a_vec.size()); + std::vector bin_float_a_vec (dbl_float_a_vec.size()); + std::vector bin_float_b_vec (dbl_float_a_vec.size()); #if defined(BOOST_HAS_FLOAT128) std::vector flt_float_a_vec (dbl_float_a_vec.size()); std::vector flt_float_b_vec (dbl_float_a_vec.size()); @@ -239,7 +219,7 @@ auto main() -> int for(std::size_t index { UINT8_C(0) }; index < dbl_float_a_vec.size(); ++index) { - if(std::size_t { index % unsigned { UINT32_C(0x800) } } == std::size_t { UINT8_C(0) }) + if(std::size_t { index % unsigned { UINT32_C(0x1000) } } == std::size_t { UINT8_C(0) }) { eng_sgn.seed(util::util_pseudorandom_time_point_seed()); eng_dig.seed(util::util_pseudorandom_time_point_seed()); @@ -252,25 +232,39 @@ auto main() -> int { dbl_float_type val { }; - if(is_positive && gate != 0) + if(gate != 0) { - while((val = generate_wide_decimal_value(true)) < gate) { ; } + while((val = dbl_float_type(generate_wide_decimal_value())) < gate) { ; } } else { - val = generate_wide_decimal_value(true); + val = dbl_float_type(generate_wide_decimal_value()); // LCOV_EXCL_LINE } - return val; + if(is_positive) + { + return val; + } + // LCOV_EXCL_START + else + { + const bool next_positive { (dist_sgn(eng_sgn) != static_cast(UINT8_C(0))) }; + + return (next_positive ? val : -val); // LCOV_EXCL_LINE + } + // LCOV_EXCL_STOP } }; - dbl_float_a_vec[index] = dbl_float_type { gen(true, dbl_float_type { 9 } / 8) }; - dbl_float_b_vec[index] = dbl_float_type { gen(true, dbl_float_type { 9 } / 8) }; + dbl_float_a_vec[index] = dbl_float_type { gen(true, dbl_float_type { 11 } / 10) }; + dbl_float_b_vec[index] = dbl_float_type { gen(true, dbl_float_type { 11 } / 10) }; dec_float_a_vec[index] = dec_float_type { dbl_float_a_vec[index] }; dec_float_b_vec[index] = dec_float_type { dbl_float_b_vec[index] }; + bin_float_a_vec[index] = bin_float_type { dbl_float_a_vec[index] }; + bin_float_b_vec[index] = bin_float_type { dbl_float_b_vec[index] }; + #if defined(BOOST_HAS_FLOAT128) flt_float_a_vec[index] = flt_float_type { dbl_float_a_vec[index] }; flt_float_b_vec[index] = flt_float_type { dbl_float_b_vec[index] }; @@ -279,6 +273,7 @@ auto main() -> int std::vector dbl_float_c_vec (dbl_float_a_vec.size()); std::vector dec_float_c_vec (dbl_float_a_vec.size()); + std::vector bin_float_c_vec (dbl_float_a_vec.size()); #if defined(BOOST_HAS_FLOAT128) std::vector flt_float_c_vec (dbl_float_a_vec.size()); #endif @@ -289,7 +284,7 @@ auto main() -> int for(std::size_t count { UINT8_C(0) }; count < trials; ++count) { - dbl_float_c_vec[count] = boost::multiprecision::cyl_bessel_j(dbl_float_a_vec[count], dbl_float_b_vec[count]); + dbl_float_c_vec[count] = boost::math::cyl_bessel_j(dbl_float_a_vec[count], dbl_float_b_vec[count]); } const double elapsed_dbl { stopwatch_type::elapsed_time(my_stopwatch) }; @@ -298,17 +293,26 @@ auto main() -> int for(std::size_t count { UINT8_C(0) }; count < trials; ++count) { - dec_float_c_vec[count] = boost::multiprecision::cyl_bessel_j(dec_float_a_vec[count], dec_float_b_vec[count]); + dec_float_c_vec[count] = boost::math::cyl_bessel_j(dec_float_a_vec[count], dec_float_b_vec[count]); } const double elapsed_dec { stopwatch_type::elapsed_time(my_stopwatch) }; + my_stopwatch.reset(); + + for(std::size_t count { UINT8_C(0) }; count < trials; ++count) + { + bin_float_c_vec[count] = boost::math::cyl_bessel_j(bin_float_a_vec[count], bin_float_b_vec[count]); + } + + const double elapsed_bin { stopwatch_type::elapsed_time(my_stopwatch) }; + #if defined(BOOST_HAS_FLOAT128) my_stopwatch.reset(); for(std::size_t count { UINT8_C(0) }; count < trials; ++count) { - flt_float_c_vec[count] = boost::multiprecision::cyl_bessel_j(flt_float_a_vec[count], flt_float_b_vec[count]); + flt_float_c_vec[count] = boost::math::cyl_bessel_j(flt_float_a_vec[count], flt_float_b_vec[count]); } const double elapsed_flt { stopwatch_type::elapsed_time(my_stopwatch) }; @@ -318,37 +322,55 @@ auto main() -> int strm << std::fixed << std::setprecision(3) << "elapsed_dbl : " << elapsed_dbl << "s\n" << std::fixed << std::setprecision(3) << "elapsed_dec : " << elapsed_dec << "s\n" + << std::fixed << std::setprecision(3) << "elapsed_bin : " << elapsed_bin << "s\n" #if defined(BOOST_HAS_FLOAT128) << std::fixed << std::setprecision(3) << "elapsed_flt : " << elapsed_flt << "s\n" #endif << std::fixed << std::setprecision(3) << "ratio (dec/dbl) : " << elapsed_dec / elapsed_dbl << "\n" + << std::fixed << std::setprecision(3) << "ratio (bin/dbl) : " << elapsed_bin / elapsed_dbl << "\n" #if defined(BOOST_HAS_FLOAT128) << std::fixed << std::setprecision(3) << "ratio (flt/dbl) : " << elapsed_flt / elapsed_dbl << "\n" #endif ; + BOOST_TEST(elapsed_dec / elapsed_dbl > 1.0); + BOOST_TEST(elapsed_bin / elapsed_dbl > 1.0); + std::cout << strm.str() << std::endl; std::cout << "verifying results...\n"; std::size_t count { UINT8_C(0) }; - constexpr dbl_float_type tol_dbl { std::numeric_limits::epsilon() * 1024 }; + constexpr dbl_float_type tol_dbl { std::numeric_limits::epsilon() * 0x400000 }; for(const auto& lhs : dbl_float_c_vec) { const dbl_float_type ctrl_dec { dec_float_c_vec[count] }; - - BOOST_TEST(is_close_fraction(lhs, ctrl_dec, tol_dbl)); - + const dbl_float_type ctrl_bin { bin_float_c_vec[count] }; #if defined(BOOST_HAS_FLOAT128) const dbl_float_type ctrl_flt { flt_float_c_vec[count] }; + #endif + BOOST_TEST(is_close_fraction(lhs, ctrl_dec, tol_dbl)); + BOOST_TEST(is_close_fraction(lhs, ctrl_bin, tol_dbl)); + #if defined(BOOST_HAS_FLOAT128) BOOST_TEST(is_close_fraction(lhs, ctrl_flt, tol_dbl)); #endif ++count; } +} + +auto main() -> int +{ + constexpr std::size_t trials { UINT32_C(0x4000) }; + constexpr std::size_t heats { UINT32_C(0x4) }; + + for(std::size_t heat_count { UINT8_C(0) }; heat_count < heats; ++heat_count) + { + do_trials(trials); + } return boost::report_errors(); }