mirror of
https://github.com/boostorg/multiprecision.git
synced 2026-01-19 04:22:11 +00:00
Merge pull request #736 from boostorg/double_fp_warns_and_tests
Add more cpp_double_fp tests and handle warns
This commit is contained in:
@@ -1528,7 +1528,6 @@ constexpr auto eval_pow(cpp_double_fp_backend<FloatingPointType>& 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<FloatingPointType>& 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<FloatingPointType>& 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<FloatingPointType>& 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 { };
|
||||
|
||||
|
||||
@@ -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 <boost/config.hpp>
|
||||
|
||||
#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 <boost/version.hpp>
|
||||
|
||||
#if defined(TEST_CPP_DOUBLE_FLOAT)
|
||||
#include <boost/multiprecision/cpp_double_fp.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(TEST_CPP_BIN_FLOAT)
|
||||
#include <boost/multiprecision/cpp_bin_float.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(TEST_CPP_BIN_FLOAT)
|
||||
#include <boost/multiprecision/cpp_dec_float.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(TEST_FLOAT128)
|
||||
#include <boost/multiprecision/float128.hpp>
|
||||
#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<std::string, std::map<std::string, std::map<std::string, std::map<int, double> > > > result_table;
|
||||
|
||||
unsigned bits_wanted; // for integer types
|
||||
|
||||
void quickbook_results()
|
||||
{
|
||||
//
|
||||
// Keys in order are:
|
||||
// Category
|
||||
// Operator
|
||||
// Type
|
||||
// Precision
|
||||
// Time
|
||||
//
|
||||
typedef std::map<std::string, std::map<std::string, std::map<std::string, std::map<int, double> > > >::const_iterator category_iterator;
|
||||
typedef std::map<std::string, std::map<std::string, std::map<int, double> > >::const_iterator operator_iterator;
|
||||
typedef std::map<std::string, std::map<int, double> >::const_iterator type_iterator;
|
||||
typedef std::map<int, double>::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<double> best_times(j->second.begin()->second.size(), (std::numeric_limits<double>::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(<sys/utsname.h>)
|
||||
#define HAS_UTSNAME
|
||||
#include <sys/utsname.h>
|
||||
#endif
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#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<class T>
|
||||
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<double_float_of_double_type>::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::backends::cpp_dec_float<digits10_for_performance_test>,
|
||||
boost::multiprecision::et_off>;
|
||||
|
||||
test<cpp_dec_float_type>("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::backends::cpp_bin_float<digits10_for_performance_test>,
|
||||
boost::multiprecision::et_off>;
|
||||
|
||||
test<cpp_bin_float_type>("cpp_bin_float", digits10_for_performance_test);
|
||||
#endif
|
||||
}
|
||||
|
||||
void local::test52()
|
||||
{
|
||||
#ifdef TEST_CPP_DOUBLE_FLOAT
|
||||
test<double_float_of_double_type>("cpp_double_fp_backend<double>", digits10_for_performance_test);
|
||||
#endif
|
||||
}
|
||||
|
||||
void local::test53()
|
||||
{
|
||||
#if defined(BOOST_HAS_FLOAT128)
|
||||
#ifdef TEST_FLOAT128
|
||||
using boost::multiprecision::float128;
|
||||
|
||||
test<float128>("boost::multiprecision::float128(at)", std::numeric_limits<boost::multiprecision::float128>::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<double>` |
|
||||
|---------------------------------|----------------------|------------------------|------------------------|---------------------------------|
|
||||
| `*` | 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
|
||||
@@ -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 : <source>quadmath ] ]
|
||||
[ run test_cpp_double_float_bessel_versus_bin_and_dec.cpp : : : [ check-target-builds ../config//has_float128 : <source>quadmath ] ]
|
||||
|
||||
[ run test_roots_10k_digits.cpp
|
||||
: # command line
|
||||
|
||||
@@ -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 <boost/core/lightweight_test.hpp>
|
||||
#include <boost/math/special_functions/bessel.hpp>
|
||||
@@ -15,7 +16,6 @@
|
||||
#include <boost/multiprecision/float128.hpp>
|
||||
#endif
|
||||
|
||||
#include <charconv>
|
||||
#include <cstdint>
|
||||
#include <ctime>
|
||||
#include <limits>
|
||||
@@ -25,10 +25,10 @@
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
#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<typename RepresentationRequestedTimeType>
|
||||
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<time_point_type>
|
||||
(
|
||||
stop - m_start
|
||||
)
|
||||
};
|
||||
const time_point_type elapsed_ns { static_cast<time_point_type>(stop - m_start) };
|
||||
|
||||
#endif
|
||||
|
||||
@@ -126,18 +119,6 @@ private:
|
||||
|
||||
namespace util {
|
||||
|
||||
template<typename UnsignedIntegerType,
|
||||
const std::uint_fast8_t BaseRepresentation = static_cast<std::uint_fast8_t>(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<int>(BaseRepresentation);
|
||||
|
||||
const auto result = std::to_chars(first, last, u, my_base);
|
||||
|
||||
return result.ptr;
|
||||
}
|
||||
|
||||
template<typename UnsignedIntegralType>
|
||||
auto util_pseudorandom_time_point_seed() -> UnsignedIntegralType
|
||||
{
|
||||
@@ -151,48 +132,37 @@ auto util_pseudorandom_time_point_seed() -> UnsignedIntegralType
|
||||
std::uniform_int_distribution<std::uint32_t> dist_sgn(UINT32_C( 0), UINT32_C( 1)); // NOLINT(cert-err58-cpp,cppcoreguidelines-avoid-non-const-global-variables)
|
||||
std::uniform_int_distribution<std::uint32_t> 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<typename FloatingPointTypeWithStringConstruction>
|
||||
auto generate_wide_decimal_value(bool is_positive = false,
|
||||
int digits10_to_get = std::numeric_limits<FloatingPointTypeWithStringConstruction>::digits10 - 2) -> FloatingPointTypeWithStringConstruction
|
||||
template<typename FloatingPointType>
|
||||
auto generate_wide_decimal_value(int digits10_to_get = std::numeric_limits<FloatingPointType>::digits10 - 2) -> std::string
|
||||
{
|
||||
using local_floating_point_type = FloatingPointTypeWithStringConstruction;
|
||||
using local_floating_point_type = FloatingPointType;
|
||||
|
||||
static_assert(std::numeric_limits<local_floating_point_type>::digits10 > static_cast<int>(INT8_C(9)),
|
||||
"Error: Floating-point type destination does not have enough digits10");
|
||||
|
||||
std::string str_x(static_cast<std::size_t>(digits10_to_get), '0');
|
||||
std::string str_x(static_cast<std::size_t>(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<char>(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<char>(dist_dig(eng_dig));
|
||||
});
|
||||
|
||||
// Insert a decimal point.
|
||||
str_x.insert(static_cast<std::size_t>(UINT8_C(1)), static_cast<std::size_t>(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<char>
|
||||
(
|
||||
is_positive
|
||||
? '+'
|
||||
: static_cast<char>((dist_sgn(eng_sgn) != static_cast<std::uint32_t>(UINT8_C(0))) ? '+' : '-')
|
||||
);
|
||||
|
||||
str_x.insert(static_cast<std::size_t>(UINT8_C(0)), static_cast<std::size_t>(UINT8_C(1)), sign_char_to_insert);
|
||||
|
||||
return local_floating_point_type(str_x.c_str());
|
||||
}
|
||||
return str_x;
|
||||
} // LCOV_EXCL_LINE
|
||||
|
||||
template<typename NumericType>
|
||||
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::cpp_dec_float<31>, boost::multiprecision::et_off>;
|
||||
|
||||
constexpr int local_digits10 = ((std::numeric_limits<dbl_float_type>::digits10 < 32) ? 32 : std::numeric_limits<dbl_float_type>::digits10);
|
||||
|
||||
using dec_float_type = boost::multiprecision::number<boost::multiprecision::cpp_dec_float<local_digits10>, boost::multiprecision::et_off>;
|
||||
using bin_float_type = boost::multiprecision::number<boost::multiprecision::cpp_bin_float<local_digits10>, 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_type> dbl_float_a_vec (trials);
|
||||
std::vector<dbl_float_type> dbl_float_b_vec (dbl_float_a_vec.size());
|
||||
|
||||
std::vector<dec_float_type> dec_float_a_vec (dbl_float_a_vec.size());
|
||||
std::vector<dec_float_type> dec_float_b_vec (dbl_float_a_vec.size());
|
||||
std::vector<bin_float_type> bin_float_a_vec (dbl_float_a_vec.size());
|
||||
std::vector<bin_float_type> bin_float_b_vec (dbl_float_a_vec.size());
|
||||
#if defined(BOOST_HAS_FLOAT128)
|
||||
std::vector<flt_float_type> flt_float_a_vec (dbl_float_a_vec.size());
|
||||
std::vector<flt_float_type> 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<typename eng_sgn_type::result_type>());
|
||||
eng_dig.seed(util::util_pseudorandom_time_point_seed<typename eng_dig_type::result_type>());
|
||||
@@ -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<dbl_float_type>(true)) < gate) { ; }
|
||||
while((val = dbl_float_type(generate_wide_decimal_value<dbl_float_type>())) < gate) { ; }
|
||||
}
|
||||
else
|
||||
{
|
||||
val = generate_wide_decimal_value<dbl_float_type>(true);
|
||||
val = dbl_float_type(generate_wide_decimal_value<dbl_float_type>()); // LCOV_EXCL_LINE
|
||||
}
|
||||
|
||||
return val;
|
||||
if(is_positive)
|
||||
{
|
||||
return val;
|
||||
}
|
||||
// LCOV_EXCL_START
|
||||
else
|
||||
{
|
||||
const bool next_positive { (dist_sgn(eng_sgn) != static_cast<std::uint32_t>(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_type> dbl_float_c_vec (dbl_float_a_vec.size());
|
||||
std::vector<dec_float_type> dec_float_c_vec (dbl_float_a_vec.size());
|
||||
std::vector<bin_float_type> bin_float_c_vec (dbl_float_a_vec.size());
|
||||
#if defined(BOOST_HAS_FLOAT128)
|
||||
std::vector<flt_float_type> 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<double>(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<double>(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<double>(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<double>(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<dbl_float_type>::epsilon() * 1024 };
|
||||
constexpr dbl_float_type tol_dbl { std::numeric_limits<dbl_float_type>::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();
|
||||
}
|
||||
Reference in New Issue
Block a user