mirror of
https://github.com/boostorg/multiprecision.git
synced 2026-01-19 04:22:11 +00:00
Revert constexpr-ness efforts
This commit is contained in:
@@ -14,7 +14,7 @@
|
||||
namespace boost { namespace multiprecision { namespace backends { namespace cpp_df_qf_detail { namespace ccmath {
|
||||
|
||||
template <class Real>
|
||||
constexpr auto fabs(Real x) noexcept -> Real
|
||||
constexpr auto fabs(Real x) -> Real
|
||||
{
|
||||
return (cpp_df_qf_detail::ccmath::isnan(x)) ? cpp_df_qf_detail::ccmath::numeric_limits<Real>::quiet_NaN()
|
||||
: (x == static_cast<Real>(-0)) ? static_cast<Real>(0)
|
||||
|
||||
@@ -8,113 +8,30 @@
|
||||
#ifndef BOOST_MP_CPP_DF_QF_DETAIL_CCMATH_FLOOR_2024_12_30_HPP
|
||||
#define BOOST_MP_CPP_DF_QF_DETAIL_CCMATH_FLOOR_2024_12_30_HPP
|
||||
|
||||
#include <boost/multiprecision/cpp_df_qf/cpp_df_qf_detail_ccmath_limits.hpp>
|
||||
|
||||
#include <cmath>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost { namespace multiprecision { namespace backends { namespace cpp_df_qf_detail { namespace ccmath {
|
||||
|
||||
namespace unsafe {
|
||||
|
||||
namespace detail {
|
||||
|
||||
// LCOV_EXCL_START
|
||||
template <typename Real>
|
||||
constexpr auto floor_pos_impl(Real arg) noexcept -> Real
|
||||
template <class T>
|
||||
constexpr auto floor_impl(T x) -> T
|
||||
{
|
||||
constexpr auto
|
||||
max_comp_val
|
||||
{
|
||||
Real(1) / ::boost::multiprecision::backends::cpp_df_qf_detail::ccmath::numeric_limits<Real>::epsilon()
|
||||
};
|
||||
// Default to the regular floor function.
|
||||
using std::floor;
|
||||
|
||||
if (arg >= max_comp_val)
|
||||
{
|
||||
return arg;
|
||||
}
|
||||
|
||||
Real result { 1 };
|
||||
|
||||
if(result <= arg)
|
||||
{
|
||||
while(result < arg)
|
||||
{
|
||||
result *= 2;
|
||||
}
|
||||
|
||||
while(result > arg)
|
||||
{
|
||||
--result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Real(0);
|
||||
}
|
||||
return floor(x);
|
||||
}
|
||||
|
||||
template <typename Real>
|
||||
constexpr auto floor_neg_impl(Real arg) noexcept -> Real
|
||||
{
|
||||
Real result { -1 };
|
||||
|
||||
if(result > arg)
|
||||
{
|
||||
while(result > arg)
|
||||
{
|
||||
result *= 2;
|
||||
}
|
||||
|
||||
while(result < arg)
|
||||
{
|
||||
++result;
|
||||
}
|
||||
|
||||
if(result != arg)
|
||||
{
|
||||
--result;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Real>
|
||||
constexpr auto floor_impl(Real arg) noexcept -> Real
|
||||
{
|
||||
if(arg > 0)
|
||||
{
|
||||
return floor_pos_impl(arg);
|
||||
}
|
||||
else
|
||||
{
|
||||
return floor_neg_impl(arg);
|
||||
}
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename Real>
|
||||
constexpr auto floor(Real x) -> Real
|
||||
{
|
||||
if (BOOST_MP_IS_CONST_EVALUATED(x))
|
||||
{
|
||||
return detail::floor_impl<Real>(x); // LCOV_EXCL_LINE
|
||||
}
|
||||
else
|
||||
{
|
||||
using std::floor;
|
||||
|
||||
return floor(x);
|
||||
}
|
||||
return cpp_df_qf_detail::ccmath::detail::floor_impl<Real>(x);
|
||||
}
|
||||
|
||||
} // namespace unsafe
|
||||
|
||||
} } } } } // namespace boost::multiprecision::backends::cpp_df_qf_detail::ccmath
|
||||
|
||||
#endif // BOOST_MP_CPP_DF_QF_DETAIL_CCMATH_FLOOR_2024_12_30_HPP
|
||||
|
||||
@@ -17,45 +17,41 @@ namespace unsafe {
|
||||
|
||||
namespace detail {
|
||||
|
||||
// LCOV_EXCL_START
|
||||
template <typename Real>
|
||||
constexpr Real fma_impl(const Real x, const Real y, const Real z) noexcept
|
||||
template <class T>
|
||||
constexpr auto fma_impl(T x, T y, T z) noexcept -> T
|
||||
{
|
||||
#if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER) && !defined(__INTEL_LLVM_COMPILER)
|
||||
BOOST_IF_CONSTEXPR (std::is_same<Real, float>::value)
|
||||
{
|
||||
return __builtin_fmaf(x, y, z);
|
||||
}
|
||||
else BOOST_IF_CONSTEXPR (std::is_same<Real, double>::value)
|
||||
{
|
||||
return __builtin_fma(x, y, z);
|
||||
}
|
||||
else BOOST_IF_CONSTEXPR (std::is_same<Real, long double>::value)
|
||||
{
|
||||
return __builtin_fmal(x, y, z);
|
||||
}
|
||||
#endif
|
||||
// Default to the written-out operations ...
|
||||
// ... and hope the compiler chooses FMA if available).
|
||||
|
||||
// If we can't use compiler intrinsics hope that -fma flag optimizes this call to fma instruction
|
||||
return (x * y) + z;
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
#if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER) && !defined(__INTEL_LLVM_COMPILER)
|
||||
template <>
|
||||
constexpr auto fma_impl<float>(float x, float y, float z) noexcept -> float
|
||||
{
|
||||
return __builtin_fmaf(x, y, z);
|
||||
}
|
||||
|
||||
template <>
|
||||
constexpr auto fma_impl<double>(double x, double y, double z) noexcept -> double
|
||||
{
|
||||
return __builtin_fma(x, y, z);
|
||||
}
|
||||
|
||||
template <>
|
||||
constexpr auto fma_impl<long double>(long double x, long double y, long double z) noexcept -> long double
|
||||
{
|
||||
return __builtin_fmal(x, y, z);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename Real>
|
||||
constexpr auto fma(Real x, Real y, Real z) -> Real
|
||||
constexpr auto fma(Real x, Real y, Real z) noexcept -> Real
|
||||
{
|
||||
if (BOOST_MP_IS_CONST_EVALUATED(x) && BOOST_MP_IS_CONST_EVALUATED(y) && BOOST_MP_IS_CONST_EVALUATED(z))
|
||||
{
|
||||
return detail::fma_impl(x, y, z); // LCOV_EXCL_LINE
|
||||
}
|
||||
else
|
||||
{
|
||||
using std::fma;
|
||||
|
||||
return fma(x, y, z);
|
||||
}
|
||||
return detail::fma_impl(x, y, z);
|
||||
}
|
||||
|
||||
} // namespace unsafe
|
||||
|
||||
@@ -11,14 +11,13 @@
|
||||
#include <boost/multiprecision/cpp_df_qf/cpp_df_qf_detail_ccmath_fabs.hpp>
|
||||
#include <boost/multiprecision/cpp_df_qf/cpp_df_qf_detail_ccmath_isinf.hpp>
|
||||
#include <boost/multiprecision/cpp_df_qf/cpp_df_qf_detail_ccmath_isnan.hpp>
|
||||
#include <boost/multiprecision/cpp_df_qf/cpp_df_qf_detail_ccmath_limits.hpp>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace boost { namespace multiprecision { namespace backends { namespace cpp_df_qf_detail { namespace ccmath {
|
||||
|
||||
template <typename Real>
|
||||
constexpr auto fpclassify(Real x) noexcept -> int
|
||||
template <typename T>
|
||||
constexpr auto fpclassify(T x) -> int
|
||||
{
|
||||
if ((::boost::multiprecision::backends::cpp_df_qf_detail::ccmath::isnan)(x))
|
||||
{
|
||||
@@ -30,13 +29,13 @@ constexpr auto fpclassify(Real x) noexcept -> int
|
||||
}
|
||||
else
|
||||
{
|
||||
const Real fabs_x { ::boost::multiprecision::backends::cpp_df_qf_detail::ccmath::fabs(x) };
|
||||
const T fabs_x { ::boost::multiprecision::backends::cpp_df_qf_detail::ccmath::fabs(x) };
|
||||
|
||||
if (fabs_x == Real(0))
|
||||
if (fabs_x == T(0))
|
||||
{
|
||||
return FP_ZERO;
|
||||
}
|
||||
else if ((fabs_x > 0) && (fabs_x < (::boost::multiprecision::backends::cpp_df_qf_detail::ccmath::numeric_limits<Real>::min)()))
|
||||
else if ((fabs_x > 0) && (fabs_x < (::boost::multiprecision::backends::cpp_df_qf_detail::ccmath::numeric_limits<T>::min)()))
|
||||
{
|
||||
return FP_SUBNORMAL;
|
||||
}
|
||||
|
||||
@@ -13,85 +13,26 @@
|
||||
|
||||
namespace boost { namespace multiprecision { namespace backends { namespace cpp_df_qf_detail { namespace ccmath {
|
||||
|
||||
namespace unsafe {
|
||||
|
||||
namespace detail {
|
||||
|
||||
// LCOV_EXCL_START
|
||||
template <class Real>
|
||||
constexpr auto frexp_impl(Real arg, int* expptr) noexcept -> Real
|
||||
namespace detail
|
||||
{
|
||||
const bool negative_arg { (arg < static_cast<Real>(0)) };
|
||||
|
||||
Real f { negative_arg ? -arg : arg };
|
||||
template <class T>
|
||||
constexpr auto frexp_impl(T arg, int* expptr) -> T
|
||||
{
|
||||
// Default to the regular frexp function.
|
||||
using std::frexp;
|
||||
|
||||
int e2 { };
|
||||
|
||||
constexpr Real two_pow_16_plus { static_cast<Real>(INT32_C(0x10000)) };
|
||||
|
||||
while (f >= two_pow_16_plus)
|
||||
{
|
||||
f = f / two_pow_16_plus;
|
||||
e2 += 16;
|
||||
}
|
||||
|
||||
constexpr Real two_pow_16_minus { static_cast<Real>(0.0000152587890625L) };
|
||||
|
||||
while (f <= two_pow_16_minus)
|
||||
{
|
||||
f = f * two_pow_16_plus;
|
||||
e2 -= 16;
|
||||
}
|
||||
|
||||
while(f >= static_cast<Real>(INT8_C(1)))
|
||||
{
|
||||
f = f / static_cast<Real>(INT8_C(2));
|
||||
++e2;
|
||||
}
|
||||
|
||||
while(f < static_cast<Real>(0.5L))
|
||||
{
|
||||
f = f * static_cast<Real>(INT8_C(2));
|
||||
--e2;
|
||||
}
|
||||
|
||||
*expptr = e2;
|
||||
|
||||
return ((!negative_arg) ? f : -f);
|
||||
return frexp(arg, expptr);
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename Real>
|
||||
constexpr auto frexp(Real arg, int* expptr) -> Real
|
||||
{
|
||||
if (BOOST_MP_IS_CONST_EVALUATED(arg))
|
||||
{
|
||||
// LCOV_EXCL_START
|
||||
if (arg == static_cast<Real>(0))
|
||||
{
|
||||
*expptr = 0;
|
||||
|
||||
return arg;
|
||||
}
|
||||
else
|
||||
{
|
||||
return detail::frexp_impl(arg, expptr);
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
else
|
||||
{
|
||||
// Default to the regular frexp function.
|
||||
using std::frexp;
|
||||
|
||||
return frexp(arg, expptr);
|
||||
}
|
||||
return detail::frexp_impl(arg, expptr);
|
||||
}
|
||||
|
||||
} // namespace unsafe
|
||||
|
||||
} } } } } // namespace boost::multiprecision::backends::cpp_df_qf_detail::ccmath
|
||||
|
||||
#endif // BOOST_MP_CPP_DF_QF_DETAIL_CCMATH_FREXP_2023_01_07_HPP
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace boost { namespace multiprecision { namespace backends { namespace cpp_df_qf_detail { namespace ccmath {
|
||||
|
||||
template <class FloatingPointType>
|
||||
constexpr auto isnan(FloatingPointType x) noexcept -> bool
|
||||
constexpr auto isnan(FloatingPointType x) -> bool
|
||||
{
|
||||
return (x != x);
|
||||
}
|
||||
|
||||
@@ -13,65 +13,42 @@
|
||||
|
||||
namespace boost { namespace multiprecision { namespace backends { namespace cpp_df_qf_detail { namespace ccmath {
|
||||
|
||||
namespace unsafe {
|
||||
|
||||
namespace detail {
|
||||
|
||||
// LCOV_EXCL_START
|
||||
template <class Real>
|
||||
constexpr auto ldexp_impl(Real arg, int expval) noexcept -> Real
|
||||
template <class T>
|
||||
constexpr auto ldexp_impl(T arg, int expval) -> T
|
||||
{
|
||||
constexpr Real two_pow_16_plus { static_cast<Real>(INT32_C(0x10000)) };
|
||||
// Default to the regular ldexp function.
|
||||
using std::ldexp;
|
||||
|
||||
while(expval > 16)
|
||||
{
|
||||
arg *= two_pow_16_plus;
|
||||
expval -= 16;
|
||||
}
|
||||
|
||||
while(expval < -16)
|
||||
{
|
||||
arg /= two_pow_16_plus;
|
||||
expval += 16;
|
||||
}
|
||||
|
||||
while(expval > 0)
|
||||
{
|
||||
arg *= 2;
|
||||
--expval;
|
||||
}
|
||||
|
||||
while(expval < 0)
|
||||
{
|
||||
arg /= 2;
|
||||
++expval;
|
||||
}
|
||||
|
||||
return arg;
|
||||
return ldexp(arg, expval);
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
} // Namespace detail
|
||||
|
||||
template <typename Real>
|
||||
constexpr auto ldexp(Real arg, int expval) -> Real
|
||||
{
|
||||
if (BOOST_MP_IS_CONST_EVALUATED(arg))
|
||||
{
|
||||
return detail::ldexp_impl<Real>(arg, expval); // LCOV_EXCL_LINE
|
||||
}
|
||||
else
|
||||
{
|
||||
using std::ldexp;
|
||||
|
||||
return ldexp(arg, expval);
|
||||
}
|
||||
return detail::ldexp_impl(arg, expval);
|
||||
}
|
||||
|
||||
namespace unsafe {
|
||||
|
||||
template <typename Real>
|
||||
constexpr auto ldexp_constexpr(Real arg, int expval) -> Real
|
||||
constexpr auto ldexp(Real arg, int exp) noexcept -> Real
|
||||
{
|
||||
return detail::ldexp_impl<Real>(arg, expval);
|
||||
while(exp > 0)
|
||||
{
|
||||
arg *= 2;
|
||||
--exp;
|
||||
}
|
||||
while(exp < 0)
|
||||
{
|
||||
arg /= 2;
|
||||
++exp;
|
||||
}
|
||||
|
||||
return arg;
|
||||
}
|
||||
|
||||
} // namespace unsafe
|
||||
|
||||
@@ -8,182 +8,30 @@
|
||||
#ifndef BOOST_MP_CPP_DF_QF_DETAIL_CCMATH_LOG_2024_12_30_HPP
|
||||
#define BOOST_MP_CPP_DF_QF_DETAIL_CCMATH_LOG_2024_12_30_HPP
|
||||
|
||||
#include <boost/multiprecision/cpp_df_qf/cpp_df_qf_detail_ccmath_frexp.hpp>
|
||||
#include <boost/multiprecision/cpp_df_qf/cpp_df_qf_detail_ccmath_limits.hpp>
|
||||
|
||||
#include <cmath>
|
||||
#include <type_traits>
|
||||
|
||||
#if (defined(__GNUC__) && defined(BOOST_MP_CPP_DOUBLE_FP_HAS_FLOAT128))
|
||||
//
|
||||
// This is the only way we can avoid
|
||||
// warning: non-standard suffix on floating constant [-Wpedantic]
|
||||
// when building with -Wall -pedantic. Neither __extension__
|
||||
// nor #pragma diagnostic ignored work :(
|
||||
//
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
namespace boost { namespace multiprecision { namespace backends { namespace cpp_df_qf_detail { namespace ccmath {
|
||||
|
||||
namespace unsafe {
|
||||
|
||||
namespace detail {
|
||||
|
||||
// LCOV_EXCL_START
|
||||
template <class Real>
|
||||
constexpr auto exp_impl(Real x) noexcept -> Real
|
||||
template <class T>
|
||||
constexpr auto log_impl(T x) -> T
|
||||
{
|
||||
constexpr int
|
||||
my_digits_10
|
||||
{
|
||||
::boost::multiprecision::backends::cpp_df_qf_detail::ccmath::numeric_limits<Real>::digits10
|
||||
};
|
||||
// Default to the regular log function.
|
||||
using std::log;
|
||||
|
||||
constexpr int
|
||||
loop_count
|
||||
{
|
||||
my_digits_10 < 8 ? 7
|
||||
: my_digits_10 < 16 ? 15
|
||||
: my_digits_10 < 20 ? 19
|
||||
: 33
|
||||
};
|
||||
|
||||
// Scale the argument with a single factor of 2.
|
||||
// Then square the result upon return.
|
||||
x /= 2;
|
||||
|
||||
// Perform a simple Taylor series of the exponent function.
|
||||
Real term { x };
|
||||
Real sum { Real { 1 } + term };
|
||||
|
||||
for (int loop_index { INT8_C(2) }; loop_index < loop_count; ++loop_index)
|
||||
{
|
||||
term *= x;
|
||||
term /= static_cast<Real>(loop_index);
|
||||
sum += term;
|
||||
}
|
||||
|
||||
// Scale the result.
|
||||
return sum * sum;
|
||||
return log(x);
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
constexpr auto log_impl_pade(Real x) noexcept -> typename std::enable_if<(::boost::multiprecision::backends::cpp_df_qf_detail::ccmath::numeric_limits<Real>::digits < 54), Real>::type
|
||||
{
|
||||
// PadeApproximant[Log[x], {x, 1, {8, 8}}]
|
||||
// FullSimplify[%]
|
||||
|
||||
const Real
|
||||
top
|
||||
{
|
||||
((static_cast<Real>(-1.0L) + x) * (static_cast<Real>(1.0L) + x) * (static_cast<Real>(761.0L) + x * (static_cast<Real>(28544.0L) + x * (static_cast<Real>(209305.0L) + x * (static_cast<Real>(423680.0L) + x * (static_cast<Real>(209305.0L) + x * (static_cast<Real>(28544.0L) + static_cast<Real>(761.0L) * x)))))))
|
||||
};
|
||||
|
||||
const Real
|
||||
bot
|
||||
{
|
||||
(static_cast<Real>(140.0L) * (static_cast<Real>(1.0L) + x * (static_cast<Real>(64.0L) + x * (static_cast<Real>(784.0L) + x * (static_cast<Real>(3136.0L) + x * (static_cast<Real>(4900.0L) + x * (static_cast<Real>(3136.0L) + x * (static_cast<Real>(784.0L) + x * (static_cast<Real>(64.0L) + x)))))))))
|
||||
};
|
||||
|
||||
return top / bot;
|
||||
}
|
||||
|
||||
template<typename Real>
|
||||
constexpr auto log_impl_pade(Real x) noexcept -> typename std::enable_if<(!(::boost::multiprecision::backends::cpp_df_qf_detail::ccmath::numeric_limits<Real>::digits < 54)), Real>::type
|
||||
{
|
||||
// PadeApproximant[Log[x], {x, 1, {16, 16}}]
|
||||
// FullSimplify[%]
|
||||
|
||||
const Real
|
||||
top
|
||||
{
|
||||
(static_cast<Real>(17.0L) * (static_cast<Real>(-1.0L) + x) * (static_cast<Real>(1.0L) + x) * (static_cast<Real>(143327.0L) + x * (static_cast<Real>(25160192.0L) + x * (static_cast<Real>(1069458527.0L) + x * (static_cast<Real>(17931092992.0L) + x * (static_cast<Real>(144291009727.0L) + x * (static_cast<Real>(613705186816.0L) + x * (static_cast<Real>(1446475477311.0L) + x * (static_cast<Real>(1923749922816.0L) + x * (static_cast<Real>(1446475477311.0L) + x * (static_cast<Real>(613705186816.0L) + x * (static_cast<Real>(144291009727.0L) + x * (static_cast<Real>(17931092992.0L) + x * (static_cast<Real>(1069458527.0L) + x * (static_cast<Real>(25160192.0L) + static_cast<Real>(143327.0L) * x)))))))))))))))
|
||||
};
|
||||
|
||||
const Real
|
||||
bot
|
||||
{
|
||||
(static_cast<Real>(360360.0L) * (static_cast<Real>(1.0L) + x * (static_cast<Real>(256.0L) + x * (static_cast<Real>(14400.0L) + x * (static_cast<Real>(313600.0L) + x * (static_cast<Real>(3312400.0L) + x * (static_cast<Real>(19079424.0L) + x * (static_cast<Real>(64128064.0L) + x * (static_cast<Real>(130873600.0L) + x * (static_cast<Real>(165636900.0L) + x * (static_cast<Real>(130873600.0L) + x * (static_cast<Real>(64128064.0L) + x * (static_cast<Real>(19079424.0L) + x * (static_cast<Real>(3312400.0L) + x * (static_cast<Real>(313600.0L) + x * (static_cast<Real>(14400.0L) + x * (static_cast<Real>(256.0L) + x)))))))))))))))))
|
||||
};
|
||||
|
||||
return top / bot;
|
||||
}
|
||||
|
||||
// N[Log[2], 101]
|
||||
// 0.69314718055994530941723212145817656807550013436025525412068000949339362196969471560586332699641868754
|
||||
|
||||
template <typename FloatingPointType> constexpr auto constant_ln_two() noexcept -> typename ::std::enable_if<(::boost::multiprecision::backends::cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits == 24), FloatingPointType>::type { return static_cast<FloatingPointType>(0.69314718055994530941723212145817656807550013436025525412068L); }
|
||||
template <typename FloatingPointType> constexpr auto constant_ln_two() noexcept -> typename ::std::enable_if<(::boost::multiprecision::backends::cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits == 53), FloatingPointType>::type { return static_cast<FloatingPointType>(0.69314718055994530941723212145817656807550013436025525412068L); }
|
||||
template <typename FloatingPointType> constexpr auto constant_ln_two() noexcept -> typename ::std::enable_if<(::boost::multiprecision::backends::cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits == 64), FloatingPointType>::type { return static_cast<FloatingPointType>(0.69314718055994530941723212145817656807550013436025525412068L); }
|
||||
#if defined(BOOST_MP_CPP_DOUBLE_FP_HAS_FLOAT128)
|
||||
template <typename FloatingPointType> constexpr auto constant_ln_two() noexcept -> typename ::std::enable_if<(::boost::multiprecision::backends::cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits == 113), FloatingPointType>::type { return static_cast<FloatingPointType>(0.69314718055994530941723212145817656807550013436025525412068Q); }
|
||||
#else
|
||||
template <typename FloatingPointType> constexpr auto constant_ln_two() noexcept -> typename ::std::enable_if<(::boost::multiprecision::backends::cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits == 113), FloatingPointType>::type { return static_cast<FloatingPointType>(0.69314718055994530941723212145817656807550013436025525412068L); }
|
||||
#endif
|
||||
|
||||
template<typename Real>
|
||||
constexpr auto log_impl(Real x) noexcept -> Real
|
||||
{
|
||||
int n2 { };
|
||||
|
||||
Real x2 { ::boost::multiprecision::backends::cpp_df_qf_detail::ccmath::unsafe::frexp(x, &n2) };
|
||||
|
||||
if (x2 > static_cast<Real>(0.9L))
|
||||
{
|
||||
x2 /= 2;
|
||||
|
||||
++n2;
|
||||
}
|
||||
|
||||
Real s { log_impl_pade(x2) };
|
||||
|
||||
Real E { exp_impl(s) };
|
||||
|
||||
// Do one single step of Newton-Raphson iteration.
|
||||
s = s + ((x2 - E) / E);
|
||||
|
||||
Real xn2 { static_cast<Real>(n2) * constant_ln_two<Real>() };
|
||||
|
||||
s += xn2;
|
||||
|
||||
return s;
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename Real>
|
||||
constexpr auto log(Real x) -> Real
|
||||
{
|
||||
if (BOOST_MP_IS_CONST_EVALUATED(x))
|
||||
{
|
||||
return detail::log_impl<Real>(x); // LCOV_EXCL_LINE
|
||||
}
|
||||
else
|
||||
{
|
||||
using std::log;
|
||||
|
||||
return log(x);
|
||||
}
|
||||
return cpp_df_qf_detail::ccmath::detail::log_impl<Real>(x);
|
||||
}
|
||||
|
||||
template <typename Real>
|
||||
constexpr auto log_constexpr(Real x) -> Real
|
||||
{
|
||||
return detail::log_impl<Real>(x);
|
||||
}
|
||||
|
||||
template <typename Real>
|
||||
constexpr auto log_non_constexpr(Real x) -> Real
|
||||
{
|
||||
using std::log;
|
||||
|
||||
return log(x);
|
||||
}
|
||||
|
||||
} // namespace unsafe
|
||||
|
||||
} } } } } // namespace boost::multiprecision::backends::cpp_df_qf_detail::ccmath
|
||||
|
||||
#endif // BOOST_MP_CPP_DF_QF_DETAIL_CCMATH_LOG_2024_12_30_HPP
|
||||
|
||||
@@ -13,15 +13,33 @@
|
||||
|
||||
namespace boost { namespace multiprecision { namespace backends { namespace cpp_df_qf_detail { namespace ccmath {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <class T>
|
||||
constexpr auto sqrt_impl(T x) -> T
|
||||
{
|
||||
// Default to the regular sqrt function.
|
||||
using std::sqrt;
|
||||
|
||||
return sqrt(x);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename Real>
|
||||
constexpr auto sqrt(Real x) -> Real
|
||||
{
|
||||
return cpp_df_qf_detail::ccmath::detail::sqrt_impl<Real>(x);
|
||||
}
|
||||
|
||||
namespace unsafe {
|
||||
|
||||
namespace detail {
|
||||
|
||||
// LCOV_EXCL_START
|
||||
template <typename Real>
|
||||
constexpr auto sqrt_impl_2(Real x, Real s, Real s2) noexcept -> Real
|
||||
{
|
||||
return ((!(s < s2)) ? s2 : sqrt_impl_2(x, (x / s + s) / 2, s));
|
||||
return !(s < s2) ? s2 : sqrt_impl_2(x, (x / s + s) / 2, s);
|
||||
}
|
||||
|
||||
template <typename Real>
|
||||
@@ -35,27 +53,11 @@ constexpr auto sqrt_impl(Real x) noexcept -> Real
|
||||
{
|
||||
return sqrt_impl_1(x, x > 1 ? x : Real(1));
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename Real>
|
||||
constexpr auto sqrt(Real x) -> Real
|
||||
{
|
||||
if (BOOST_MP_IS_CONST_EVALUATED(x))
|
||||
{
|
||||
return detail::sqrt_impl<Real>(x); // LCOV_EXCL_LINE
|
||||
}
|
||||
else
|
||||
{
|
||||
using std::sqrt;
|
||||
|
||||
return sqrt(x);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Real>
|
||||
constexpr auto sqrt_constexpr(Real x) -> Real
|
||||
constexpr auto sqrt(Real x) noexcept -> Real
|
||||
{
|
||||
return detail::sqrt_impl<Real>(x);
|
||||
}
|
||||
|
||||
@@ -32,13 +32,13 @@
|
||||
// 3.14159265358979323851281, -5.01655761266833202345176e-20
|
||||
// 3.14159265358979323846264338327950279748, 8.67181013012378102479704402604335225411e-35
|
||||
|
||||
template <typename FloatingPointType> constexpr auto constant_df_pi() noexcept -> typename ::std::enable_if<(cpp_df_qf_detail::is_floating_point<FloatingPointType>::value && (cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits == 24)), cpp_double_fp_backend<FloatingPointType>>::type { return { static_cast<FloatingPointType>(3.14159250259L), static_cast<FloatingPointType>(1.50995788317e-07L) }; }
|
||||
template <typename FloatingPointType> constexpr auto constant_df_pi() noexcept -> typename ::std::enable_if<(cpp_df_qf_detail::is_floating_point<FloatingPointType>::value && (cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits == 53)), cpp_double_fp_backend<FloatingPointType>>::type { return { static_cast<FloatingPointType>(3.141592653589793116L), static_cast<FloatingPointType>(1.2246467991473529607e-16L) }; }
|
||||
template <typename FloatingPointType> constexpr auto constant_df_pi() noexcept -> typename ::std::enable_if<(cpp_df_qf_detail::is_floating_point<FloatingPointType>::value && (cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits == 64)), cpp_double_fp_backend<FloatingPointType>>::type { return { static_cast<FloatingPointType>(3.14159265358979323851281L), static_cast<FloatingPointType>(-5.01655761266833202345176e-20L) }; }
|
||||
template <typename FloatingPointType> constexpr auto constant_df_pi() -> typename ::std::enable_if<(cpp_df_qf_detail::is_floating_point<FloatingPointType>::value && (cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits == 24)), cpp_double_fp_backend<FloatingPointType>>::type { return { static_cast<FloatingPointType>(3.14159250259L), static_cast<FloatingPointType>(1.50995788317e-07L) }; }
|
||||
template <typename FloatingPointType> constexpr auto constant_df_pi() -> typename ::std::enable_if<(cpp_df_qf_detail::is_floating_point<FloatingPointType>::value && (cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits == 53)), cpp_double_fp_backend<FloatingPointType>>::type { return { static_cast<FloatingPointType>(3.141592653589793116L), static_cast<FloatingPointType>(1.2246467991473529607e-16L) }; }
|
||||
template <typename FloatingPointType> constexpr auto constant_df_pi() -> typename ::std::enable_if<(cpp_df_qf_detail::is_floating_point<FloatingPointType>::value && (cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits == 64)), cpp_double_fp_backend<FloatingPointType>>::type { return { static_cast<FloatingPointType>(3.14159265358979323851281L), static_cast<FloatingPointType>(-5.01655761266833202345176e-20L) }; }
|
||||
#if defined(BOOST_MP_CPP_DOUBLE_FP_HAS_FLOAT128)
|
||||
template <typename FloatingPointType> constexpr auto constant_df_pi() noexcept -> typename ::std::enable_if<(cpp_df_qf_detail::is_floating_point<FloatingPointType>::value && (cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits == 113)), cpp_double_fp_backend<FloatingPointType>>::type { return { static_cast<FloatingPointType>(3.14159265358979323846264338327950279748Q), static_cast<FloatingPointType>(8.67181013012378102479704402604335225411e-35Q) }; }
|
||||
template <typename FloatingPointType> constexpr auto constant_df_pi() -> typename ::std::enable_if<(cpp_df_qf_detail::is_floating_point<FloatingPointType>::value && (cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits == 113)), cpp_double_fp_backend<FloatingPointType>>::type { return { static_cast<FloatingPointType>(3.14159265358979323846264338327950279748Q), static_cast<FloatingPointType>(8.67181013012378102479704402604335225411e-35Q) }; }
|
||||
#else
|
||||
template <typename FloatingPointType> constexpr auto constant_df_pi() noexcept -> typename ::std::enable_if<(cpp_df_qf_detail::is_floating_point<FloatingPointType>::value && (cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits == 113)), cpp_double_fp_backend<FloatingPointType>>::type { return { static_cast<FloatingPointType>(3.14159265358979323846264338327950279748L), static_cast<FloatingPointType>(8.67181013012378102479704402604335225411e-35L) }; }
|
||||
template <typename FloatingPointType> constexpr auto constant_df_pi() -> typename ::std::enable_if<(cpp_df_qf_detail::is_floating_point<FloatingPointType>::value && (cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits == 113)), cpp_double_fp_backend<FloatingPointType>>::type { return { static_cast<FloatingPointType>(3.14159265358979323846264338327950279748L), static_cast<FloatingPointType>(8.67181013012378102479704402604335225411e-35L) }; }
|
||||
#endif
|
||||
|
||||
// N[Log[2], 101]
|
||||
@@ -49,13 +49,13 @@
|
||||
// 0.69314718055994530942869, -1.14583527267987328094768e-20
|
||||
// 0.693147180559945309417232121458176575084, -7.00813947454958516341266200877162272784e-36
|
||||
|
||||
template <typename FloatingPointType> constexpr auto constant_df_ln_two() noexcept -> typename ::std::enable_if<(cpp_df_qf_detail::is_floating_point<FloatingPointType>::value && (cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits == 24)), cpp_double_fp_backend<FloatingPointType>>::type { return { static_cast<FloatingPointType>(0.69314712286L), static_cast<FloatingPointType>(5.76999887869e-08L) }; }
|
||||
template <typename FloatingPointType> constexpr auto constant_df_ln_two() noexcept -> typename ::std::enable_if<(cpp_df_qf_detail::is_floating_point<FloatingPointType>::value && (cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits == 53)), cpp_double_fp_backend<FloatingPointType>>::type { return { static_cast<FloatingPointType>(0.6931471805599451752L), static_cast<FloatingPointType>(1.3421277060097865271e-16L) }; }
|
||||
template <typename FloatingPointType> constexpr auto constant_df_ln_two() noexcept -> typename ::std::enable_if<(cpp_df_qf_detail::is_floating_point<FloatingPointType>::value && (cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits == 64)), cpp_double_fp_backend<FloatingPointType>>::type { return { static_cast<FloatingPointType>(0.69314718055994530942869L), static_cast<FloatingPointType>(-1.14583527267987328094768e-20L) }; }
|
||||
template <typename FloatingPointType> constexpr auto constant_df_ln_two() -> typename ::std::enable_if<(cpp_df_qf_detail::is_floating_point<FloatingPointType>::value && (cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits == 24)), cpp_double_fp_backend<FloatingPointType>>::type { return { static_cast<FloatingPointType>(0.69314712286L), static_cast<FloatingPointType>(5.76999887869e-08L) }; }
|
||||
template <typename FloatingPointType> constexpr auto constant_df_ln_two() -> typename ::std::enable_if<(cpp_df_qf_detail::is_floating_point<FloatingPointType>::value && (cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits == 53)), cpp_double_fp_backend<FloatingPointType>>::type { return { static_cast<FloatingPointType>(0.6931471805599451752L), static_cast<FloatingPointType>(1.3421277060097865271e-16L) }; }
|
||||
template <typename FloatingPointType> constexpr auto constant_df_ln_two() -> typename ::std::enable_if<(cpp_df_qf_detail::is_floating_point<FloatingPointType>::value && (cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits == 64)), cpp_double_fp_backend<FloatingPointType>>::type { return { static_cast<FloatingPointType>(0.69314718055994530942869L), static_cast<FloatingPointType>(-1.14583527267987328094768e-20L) }; }
|
||||
#if defined(BOOST_MP_CPP_DOUBLE_FP_HAS_FLOAT128)
|
||||
template <typename FloatingPointType> constexpr auto constant_df_ln_two() noexcept -> typename ::std::enable_if<(cpp_df_qf_detail::is_floating_point<FloatingPointType>::value && (cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits == 113)), cpp_double_fp_backend<FloatingPointType>>::type { return { static_cast<FloatingPointType>(0.693147180559945309417232121458176575084Q), static_cast<FloatingPointType>(-7.00813947454958516341266200877162272784e-36Q) }; }
|
||||
template <typename FloatingPointType> constexpr auto constant_df_ln_two() -> typename ::std::enable_if<(cpp_df_qf_detail::is_floating_point<FloatingPointType>::value && (cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits == 113)), cpp_double_fp_backend<FloatingPointType>>::type { return { static_cast<FloatingPointType>(0.693147180559945309417232121458176575084Q), static_cast<FloatingPointType>(-7.00813947454958516341266200877162272784e-36Q) }; }
|
||||
#else
|
||||
template <typename FloatingPointType> constexpr auto constant_df_ln_two() noexcept -> typename ::std::enable_if<(cpp_df_qf_detail::is_floating_point<FloatingPointType>::value && (cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits == 113)), cpp_double_fp_backend<FloatingPointType>>::type { return { static_cast<FloatingPointType>(0.693147180559945309417232121458176575084L), static_cast<FloatingPointType>(-7.00813947454958516341266200877162272784e-36L) }; }
|
||||
template <typename FloatingPointType> constexpr auto constant_df_ln_two() -> typename ::std::enable_if<(cpp_df_qf_detail::is_floating_point<FloatingPointType>::value && (cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits == 113)), cpp_double_fp_backend<FloatingPointType>>::type { return { static_cast<FloatingPointType>(0.693147180559945309417232121458176575084L), static_cast<FloatingPointType>(-7.00813947454958516341266200877162272784e-36L) }; }
|
||||
#endif
|
||||
|
||||
// N[Exp[1], 101]
|
||||
@@ -66,13 +66,13 @@
|
||||
// 2.71828182845904523521133, 1.4895979785582304563159e-19
|
||||
// 2.71828182845904523536028747135266231436, 1.83398825226506410712297736767396397644e-34
|
||||
|
||||
template <typename FloatingPointType> constexpr auto constant_df_exp1()noexcept -> typename ::std::enable_if<(cpp_df_qf_detail::is_floating_point<FloatingPointType>::value && (cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits == 24)), cpp_double_fp_backend<FloatingPointType>>::type { return { static_cast<FloatingPointType>(2.71828174591L), static_cast<FloatingPointType>(8.25483965627e-08L) }; }
|
||||
template <typename FloatingPointType> constexpr auto constant_df_exp1()noexcept -> typename ::std::enable_if<(cpp_df_qf_detail::is_floating_point<FloatingPointType>::value && (cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits == 53)), cpp_double_fp_backend<FloatingPointType>>::type { return { static_cast<FloatingPointType>(2.7182818284590450908L), static_cast<FloatingPointType>(1.4456468917292501578e-16L) }; }
|
||||
template <typename FloatingPointType> constexpr auto constant_df_exp1()noexcept -> typename ::std::enable_if<(cpp_df_qf_detail::is_floating_point<FloatingPointType>::value && (cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits == 64)), cpp_double_fp_backend<FloatingPointType>>::type { return { static_cast<FloatingPointType>(2.71828182845904523521133L), static_cast<FloatingPointType>(1.4895979785582304563159e-19L) }; }
|
||||
template <typename FloatingPointType> constexpr auto constant_df_exp1() -> typename ::std::enable_if<(cpp_df_qf_detail::is_floating_point<FloatingPointType>::value && (cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits == 24)), cpp_double_fp_backend<FloatingPointType>>::type { return { static_cast<FloatingPointType>(2.71828174591L), static_cast<FloatingPointType>(8.25483965627e-08L) }; }
|
||||
template <typename FloatingPointType> constexpr auto constant_df_exp1() -> typename ::std::enable_if<(cpp_df_qf_detail::is_floating_point<FloatingPointType>::value && (cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits == 53)), cpp_double_fp_backend<FloatingPointType>>::type { return { static_cast<FloatingPointType>(2.7182818284590450908L), static_cast<FloatingPointType>(1.4456468917292501578e-16L) }; }
|
||||
template <typename FloatingPointType> constexpr auto constant_df_exp1() -> typename ::std::enable_if<(cpp_df_qf_detail::is_floating_point<FloatingPointType>::value && (cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits == 64)), cpp_double_fp_backend<FloatingPointType>>::type { return { static_cast<FloatingPointType>(2.71828182845904523521133L), static_cast<FloatingPointType>(1.4895979785582304563159e-19L) }; }
|
||||
#if defined(BOOST_MP_CPP_DOUBLE_FP_HAS_FLOAT128)
|
||||
template <typename FloatingPointType> constexpr auto constant_df_exp1() noexcept -> typename ::std::enable_if<(cpp_df_qf_detail::is_floating_point<FloatingPointType>::value && (cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits == 113)), cpp_double_fp_backend<FloatingPointType>>::type { return { static_cast<FloatingPointType>(2.71828182845904523536028747135266231436Q), static_cast<FloatingPointType>(1.83398825226506410712297736767396397644e-34Q) }; }
|
||||
template <typename FloatingPointType> constexpr auto constant_df_exp1() -> typename ::std::enable_if<(cpp_df_qf_detail::is_floating_point<FloatingPointType>::value && (cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits == 113)), cpp_double_fp_backend<FloatingPointType>>::type { return { static_cast<FloatingPointType>(2.71828182845904523536028747135266231436Q), static_cast<FloatingPointType>(1.83398825226506410712297736767396397644e-34Q) }; }
|
||||
#else
|
||||
template <typename FloatingPointType> constexpr auto constant_df_exp1() noexcept -> typename ::std::enable_if<(cpp_df_qf_detail::is_floating_point<FloatingPointType>::value && (cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits == 113)), cpp_double_fp_backend<FloatingPointType>>::type { return { static_cast<FloatingPointType>(2.71828182845904523536028747135266231436L), static_cast<FloatingPointType>(1.83398825226506410712297736767396397644e-34L) }; }
|
||||
template <typename FloatingPointType> constexpr auto constant_df_exp1() -> typename ::std::enable_if<(cpp_df_qf_detail::is_floating_point<FloatingPointType>::value && (cpp_df_qf_detail::ccmath::numeric_limits<FloatingPointType>::digits == 113)), cpp_double_fp_backend<FloatingPointType>>::type { return { static_cast<FloatingPointType>(2.71828182845904523536028747135266231436L), static_cast<FloatingPointType>(1.83398825226506410712297736767396397644e-34L) }; }
|
||||
#endif
|
||||
|
||||
} } } } // namespace boost::multiprecision::backends::cpp_df_qf_detail
|
||||
|
||||
@@ -739,9 +739,9 @@ class cpp_double_fp_backend
|
||||
// Handle overflow by scaling down (and then back up) with the split.
|
||||
|
||||
hc =
|
||||
cpp_df_qf_detail::ccmath::unsafe::ldexp
|
||||
cpp_df_qf_detail::ccmath::ldexp
|
||||
(
|
||||
C - float_type { C - cpp_df_qf_detail::ccmath::unsafe::ldexp(C, -cpp_df_qf_detail::split_maker<float_type>::n_shl) },
|
||||
C - float_type { C - cpp_df_qf_detail::ccmath::ldexp(C, -cpp_df_qf_detail::split_maker<float_type>::n_shl) },
|
||||
cpp_df_qf_detail::split_maker<float_type>::n_shl
|
||||
);
|
||||
}
|
||||
@@ -759,9 +759,9 @@ class cpp_double_fp_backend
|
||||
// Handle overflow by scaling down (and then back up) with the split.
|
||||
|
||||
hv =
|
||||
cpp_df_qf_detail::ccmath::unsafe::ldexp
|
||||
cpp_df_qf_detail::ccmath::ldexp
|
||||
(
|
||||
v.data.first - float_type { v.data.first - cpp_df_qf_detail::ccmath::unsafe::ldexp(v.data.first, -cpp_df_qf_detail::split_maker<float_type>::n_shl) },
|
||||
v.data.first - float_type { v.data.first - cpp_df_qf_detail::ccmath::ldexp(v.data.first, -cpp_df_qf_detail::split_maker<float_type>::n_shl) },
|
||||
cpp_df_qf_detail::split_maker<float_type>::n_shl
|
||||
);
|
||||
}
|
||||
@@ -949,35 +949,21 @@ class cpp_double_fp_backend
|
||||
(cpp_df_qf_detail::ccmath::numeric_limits<float_type>::max)()
|
||||
* (
|
||||
static_cast<float_type>(1.0F)
|
||||
- (
|
||||
static_cast<float_type>(1.5F)
|
||||
#if (defined(BOOST_GCC) && !defined(BOOST_CLANG) && (BOOST_GCC < 80000))
|
||||
* cpp_df_qf_detail::ccmath::unsafe::sqrt_constexpr
|
||||
#else
|
||||
* cpp_df_qf_detail::ccmath::unsafe::sqrt
|
||||
#endif
|
||||
(
|
||||
cpp_df_qf_detail::ccmath::numeric_limits<float_type>::epsilon()
|
||||
)
|
||||
)
|
||||
- static_cast<float_type>(1.5F) * cpp_df_qf_detail::ccmath::unsafe::sqrt(cpp_df_qf_detail::ccmath::numeric_limits<float_type>::epsilon())
|
||||
)
|
||||
};
|
||||
|
||||
constexpr float_type
|
||||
lo_part
|
||||
{
|
||||
#if (defined(BOOST_GCC) && !defined(BOOST_CLANG) && (BOOST_GCC < 80000))
|
||||
cpp_df_qf_detail::ccmath::unsafe::ldexp_constexpr
|
||||
#else
|
||||
cpp_df_qf_detail::ccmath::unsafe::ldexp
|
||||
#endif
|
||||
(
|
||||
(cpp_df_qf_detail::ccmath::numeric_limits<float_type>::max)(),
|
||||
-cpp_df_qf_detail::ccmath::numeric_limits<float_type>::digits
|
||||
)
|
||||
};
|
||||
|
||||
constexpr cpp_double_fp_backend my_value_max_constexpr(arithmetic::two_hilo_sum(hi_part, lo_part));
|
||||
constexpr cpp_double_fp_backend my_value_max_constexpr { arithmetic::two_hilo_sum(hi_part, lo_part) };
|
||||
|
||||
static_assert
|
||||
(
|
||||
@@ -993,25 +979,19 @@ class cpp_double_fp_backend
|
||||
// Use the non-normalized minimum value, where the lower value
|
||||
// is "shifted" left in the sense of floating-point ldexp.
|
||||
|
||||
constexpr float_type
|
||||
hi_part
|
||||
constexpr cpp_double_fp_backend
|
||||
my_value_min_constexpr
|
||||
{
|
||||
#if (defined(BOOST_GCC) && !defined(BOOST_CLANG) && (BOOST_GCC < 80000))
|
||||
cpp_df_qf_detail::ccmath::unsafe::ldexp_constexpr
|
||||
#else
|
||||
cpp_df_qf_detail::ccmath::unsafe::ldexp
|
||||
#endif
|
||||
(
|
||||
(cpp_df_qf_detail::ccmath::numeric_limits<float_type>::min)(),
|
||||
cpp_df_qf_detail::ccmath::numeric_limits<float_type>::digits
|
||||
)
|
||||
};
|
||||
|
||||
constexpr cpp_double_fp_backend my_value_min_constexpr { hi_part };
|
||||
|
||||
static_assert
|
||||
(
|
||||
eval_gt(my_value_min_constexpr, cpp_double_fp_backend((cpp_df_qf_detail::ccmath::numeric_limits<float_type>::min)())),
|
||||
eval_gt(my_value_min_constexpr, cpp_double_fp_backend { (cpp_df_qf_detail::ccmath::numeric_limits<float_type>::min)() }),
|
||||
"Error: minimum value is too small and must exceed the min of its constituent type"
|
||||
);
|
||||
|
||||
@@ -1023,19 +1003,12 @@ class cpp_double_fp_backend
|
||||
constexpr cpp_double_fp_backend
|
||||
my_value_eps_constexpr
|
||||
{
|
||||
#if (defined(BOOST_GCC) && !defined(BOOST_CLANG) && (BOOST_GCC < 80000))
|
||||
cpp_df_qf_detail::ccmath::unsafe::ldexp_constexpr
|
||||
#else
|
||||
cpp_df_qf_detail::ccmath::unsafe::ldexp
|
||||
#endif
|
||||
(
|
||||
float_type { 1 }, int { 3 - my_digits }
|
||||
)
|
||||
cpp_df_qf_detail::ccmath::unsafe::ldexp(float_type { 1 }, int { 3 - my_digits })
|
||||
};
|
||||
|
||||
static_assert
|
||||
(
|
||||
eval_lt(cpp_double_fp_backend(1) - my_value_eps_constexpr, cpp_double_fp_backend(1)),
|
||||
eval_lt(cpp_double_fp_backend { 1 } - my_value_eps_constexpr, cpp_double_fp_backend { 1 }),
|
||||
"Error: epsilon value is too small and must be large enough to differentiate (1 - epsilon) from 1"
|
||||
);
|
||||
|
||||
@@ -1052,36 +1025,6 @@ class cpp_double_fp_backend
|
||||
return cpp_double_fp_backend(static_cast<float_type>(HUGE_VAL), float_type { 0.0F }); // conversion from double infinity OK
|
||||
}
|
||||
|
||||
#if (defined(BOOST_GCC) && !defined(BOOST_CLANG) && (BOOST_GCC < 80000))
|
||||
static auto my_value_logmax() noexcept -> const cpp_double_fp_backend&
|
||||
#else
|
||||
static constexpr auto my_value_logmax() noexcept -> cpp_double_fp_backend
|
||||
#endif
|
||||
{
|
||||
#if (defined(BOOST_GCC) && !defined(BOOST_CLANG) && (BOOST_GCC < 80000))
|
||||
static const cpp_double_fp_backend my_value_logmax_non_constexpr = my_value_logmax_maker();
|
||||
|
||||
return my_value_logmax_non_constexpr;
|
||||
#else
|
||||
return my_value_logmax_maker();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if (defined(BOOST_GCC) && !defined(BOOST_CLANG) && (BOOST_GCC < 80000))
|
||||
static auto my_value_logmin() noexcept -> const cpp_double_fp_backend&
|
||||
#else
|
||||
static constexpr auto my_value_logmin() noexcept -> cpp_double_fp_backend
|
||||
#endif
|
||||
{
|
||||
#if (defined(BOOST_GCC) && !defined(BOOST_CLANG) && (BOOST_GCC < 80000))
|
||||
static const cpp_double_fp_backend my_value_logmin_non_constexpr = my_value_logmin_maker();
|
||||
|
||||
return my_value_logmin_non_constexpr;
|
||||
#else
|
||||
return my_value_logmin_maker();
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
rep_type data;
|
||||
|
||||
@@ -1092,130 +1035,6 @@ class cpp_double_fp_backend
|
||||
|
||||
auto rd_string(const char* pstr) -> bool;
|
||||
|
||||
#if (defined(BOOST_GCC) && !defined(BOOST_CLANG) && (BOOST_GCC < 80000))
|
||||
#else
|
||||
constexpr
|
||||
#endif
|
||||
static auto my_value_logmax_maker() noexcept -> cpp_double_fp_backend
|
||||
{
|
||||
// Here, we note that max is composed of (first + second),
|
||||
// which we refactor as first * (1 + second / first).
|
||||
|
||||
// We approximate log(first * (1 + second / first)) with
|
||||
// log(first) + log(1 + second/first), and use a value of
|
||||
// zero for the second logarithm.
|
||||
|
||||
#if (defined(BOOST_GCC) && !defined(BOOST_CLANG) && (BOOST_GCC < 80000))
|
||||
const
|
||||
#else
|
||||
constexpr
|
||||
#endif
|
||||
float_type
|
||||
first
|
||||
{
|
||||
(cpp_df_qf_detail::ccmath::numeric_limits<float_type>::max)()
|
||||
* (
|
||||
static_cast<float_type>(1.0F)
|
||||
- (
|
||||
static_cast<float_type>(1.5F)
|
||||
#if (defined(BOOST_GCC) && !defined(BOOST_CLANG) && (BOOST_GCC < 80000))
|
||||
* cpp_df_qf_detail::ccmath::unsafe::sqrt_constexpr
|
||||
#else
|
||||
* cpp_df_qf_detail::ccmath::unsafe::sqrt
|
||||
#endif
|
||||
(
|
||||
cpp_df_qf_detail::ccmath::numeric_limits<float_type>::epsilon()
|
||||
)
|
||||
)
|
||||
)
|
||||
};
|
||||
|
||||
#if (defined(BOOST_GCC) && !defined(BOOST_CLANG) && (BOOST_GCC < 80000))
|
||||
const
|
||||
#else
|
||||
constexpr
|
||||
#endif
|
||||
cpp_double_fp_backend
|
||||
my_value_logmax_constexpr_or_const
|
||||
(
|
||||
#if (defined(BOOST_GCC) && !defined(BOOST_CLANG) && (BOOST_GCC < 80000))
|
||||
cpp_double_fp_backend(cpp_df_qf_detail::ccmath::unsafe::log_non_constexpr(first))
|
||||
#else
|
||||
cpp_double_fp_backend(cpp_df_qf_detail::ccmath::unsafe::log(first))
|
||||
#endif
|
||||
);
|
||||
|
||||
#if (defined(BOOST_GCC) && !defined(BOOST_CLANG) && (BOOST_GCC < 80000))
|
||||
#else
|
||||
static_assert
|
||||
(
|
||||
eval_gt(my_value_logmax_constexpr_or_const, cpp_double_fp_backend(1)),
|
||||
"Error: logmax value is definitely incorrect"
|
||||
);
|
||||
#endif
|
||||
|
||||
return my_value_logmax_constexpr_or_const;
|
||||
}
|
||||
|
||||
#if (defined(BOOST_GCC) && !defined(BOOST_CLANG) && (BOOST_GCC < 80000))
|
||||
#else
|
||||
constexpr
|
||||
#endif
|
||||
static auto my_value_logmin_maker() noexcept -> cpp_double_fp_backend
|
||||
{
|
||||
// Here, we note that min is composed of (first + second),
|
||||
// which we refactor as first * (1 + second / first).
|
||||
|
||||
// We approximate log(first * (1 + second / first)) with
|
||||
// log(first) + log(1 + second/first), and use a value of
|
||||
// zero for the second logarithm.
|
||||
|
||||
#if (defined(BOOST_GCC) && !defined(BOOST_CLANG) && (BOOST_GCC < 80000))
|
||||
const
|
||||
#else
|
||||
constexpr
|
||||
#endif
|
||||
float_type
|
||||
first
|
||||
{
|
||||
#if (defined(BOOST_GCC) && !defined(BOOST_CLANG) && (BOOST_GCC < 80000))
|
||||
cpp_df_qf_detail::ccmath::unsafe::ldexp_constexpr
|
||||
#else
|
||||
cpp_df_qf_detail::ccmath::unsafe::ldexp
|
||||
#endif
|
||||
(
|
||||
(cpp_df_qf_detail::ccmath::numeric_limits<float_type>::min)(),
|
||||
cpp_df_qf_detail::ccmath::numeric_limits<float_type>::digits
|
||||
)
|
||||
};
|
||||
|
||||
#if (defined(BOOST_GCC) && !defined(BOOST_CLANG) && (BOOST_GCC < 80000))
|
||||
const
|
||||
#else
|
||||
constexpr
|
||||
#endif
|
||||
cpp_double_fp_backend
|
||||
my_value_logmin_constexpr_or_const
|
||||
(
|
||||
#if (defined(BOOST_GCC) && !defined(BOOST_CLANG) && (BOOST_GCC < 80000))
|
||||
cpp_double_fp_backend(cpp_df_qf_detail::ccmath::unsafe::log_non_constexpr(first))
|
||||
#else
|
||||
cpp_double_fp_backend(cpp_df_qf_detail::ccmath::unsafe::log(first))
|
||||
#endif
|
||||
);
|
||||
|
||||
#if (defined(BOOST_GCC) && !defined(BOOST_CLANG) && (BOOST_GCC < 80000))
|
||||
#else
|
||||
static_assert
|
||||
(
|
||||
eval_lt(my_value_logmin_constexpr_or_const, cpp_double_fp_backend(-1)),
|
||||
"Error: logmin value is definitely incorrect"
|
||||
);
|
||||
#endif
|
||||
|
||||
return my_value_logmin_constexpr_or_const;
|
||||
}
|
||||
|
||||
constexpr auto mul_unchecked(const cpp_double_fp_backend& v) -> void
|
||||
{
|
||||
// The multiplication algorithm has been taken from Victor Shoup,
|
||||
@@ -1232,9 +1051,9 @@ class cpp_double_fp_backend
|
||||
{
|
||||
// Handle overflow by scaling down (and then back up) with the split.
|
||||
|
||||
C = data.first - cpp_df_qf_detail::ccmath::unsafe::ldexp(data.first, -cpp_df_qf_detail::split_maker<float_type>::n_shl);
|
||||
C = data.first - cpp_df_qf_detail::ccmath::ldexp(data.first, -cpp_df_qf_detail::split_maker<float_type>::n_shl);
|
||||
|
||||
hu = cpp_df_qf_detail::ccmath::unsafe::ldexp(data.first - C, cpp_df_qf_detail::split_maker<float_type>::n_shl);
|
||||
hu = cpp_df_qf_detail::ccmath::ldexp(data.first - C, cpp_df_qf_detail::split_maker<float_type>::n_shl);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1266,9 +1085,9 @@ class cpp_double_fp_backend
|
||||
{
|
||||
// Handle overflow by scaling down (and then back up) with the split.
|
||||
|
||||
c = v.data.first - cpp_df_qf_detail::ccmath::unsafe::ldexp(v.data.first, -cpp_df_qf_detail::split_maker<float_type>::n_shl);
|
||||
c = v.data.first - cpp_df_qf_detail::ccmath::ldexp(v.data.first, -cpp_df_qf_detail::split_maker<float_type>::n_shl);
|
||||
|
||||
hv = cpp_df_qf_detail::ccmath::unsafe::ldexp(v.data.first - c, cpp_df_qf_detail::split_maker<float_type>::n_shl);
|
||||
hv = cpp_df_qf_detail::ccmath::ldexp(v.data.first - c, cpp_df_qf_detail::split_maker<float_type>::n_shl);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1507,8 +1326,8 @@ constexpr auto eval_frexp(cpp_double_fp_backend<FloatingPointType>& result, cons
|
||||
|
||||
int expptr { };
|
||||
|
||||
const local_float_type fhi { cpp_df_qf_detail::ccmath::unsafe::frexp(a.rep().first, &expptr) };
|
||||
const local_float_type flo { cpp_df_qf_detail::ccmath::unsafe::ldexp(a.rep().second, -expptr) };
|
||||
const local_float_type fhi { cpp_df_qf_detail::ccmath::frexp(a.rep().first, &expptr) };
|
||||
const local_float_type flo { cpp_df_qf_detail::ccmath::ldexp(a.rep().second, -expptr) };
|
||||
|
||||
if (v != nullptr)
|
||||
{
|
||||
@@ -1524,8 +1343,8 @@ constexpr auto eval_ldexp(cpp_double_fp_backend<FloatingPointType>& result, cons
|
||||
using local_backend_type = cpp_double_fp_backend<FloatingPointType>;
|
||||
using local_float_type = typename local_backend_type::float_type;
|
||||
|
||||
const local_float_type fhi { cpp_df_qf_detail::ccmath::unsafe::ldexp(a.crep().first, v) };
|
||||
const local_float_type flo { cpp_df_qf_detail::ccmath::unsafe::ldexp(a.crep().second, v) };
|
||||
const local_float_type fhi { cpp_df_qf_detail::ccmath::ldexp(a.crep().first, v) };
|
||||
const local_float_type flo { cpp_df_qf_detail::ccmath::ldexp(a.crep().second, v) };
|
||||
|
||||
result.rep() = local_backend_type::arithmetic::normalize(fhi, flo);
|
||||
}
|
||||
@@ -1536,7 +1355,7 @@ constexpr auto eval_floor(cpp_double_fp_backend<FloatingPointType>& result, cons
|
||||
using local_backend_type = cpp_double_fp_backend<FloatingPointType>;
|
||||
using local_float_type = typename local_backend_type::float_type;
|
||||
|
||||
const local_float_type fhi { cpp_df_qf_detail::ccmath::unsafe::floor(x.my_first()) };
|
||||
const local_float_type fhi { cpp_df_qf_detail::ccmath::floor(x.my_first()) };
|
||||
|
||||
if (fhi != x.my_first())
|
||||
{
|
||||
@@ -1545,7 +1364,7 @@ constexpr auto eval_floor(cpp_double_fp_backend<FloatingPointType>& result, cons
|
||||
}
|
||||
else
|
||||
{
|
||||
const local_float_type flo = { cpp_df_qf_detail::ccmath::unsafe::floor(x.my_second()) };
|
||||
const local_float_type flo = { cpp_df_qf_detail::ccmath::floor(x.my_second()) };
|
||||
|
||||
result.rep() = local_backend_type::arithmetic::normalize(fhi, flo);
|
||||
}
|
||||
@@ -1619,7 +1438,7 @@ constexpr auto eval_sqrt(cpp_double_fp_backend<FloatingPointType>& result, const
|
||||
// TBD: Do we need any overflow/underflow guards when multiplying
|
||||
// by the split or when multiplying (hx * tx) and/or (hx * hx)?
|
||||
|
||||
const local_float_type c { cpp_df_qf_detail::ccmath::unsafe::sqrt(o.crep().first) };
|
||||
const local_float_type c { cpp_df_qf_detail::ccmath::sqrt(o.crep().first) };
|
||||
|
||||
local_float_type p { cpp_df_qf_detail::split_maker<local_float_type>::value * c };
|
||||
|
||||
@@ -1863,15 +1682,42 @@ constexpr auto eval_exp(cpp_double_fp_backend<FloatingPointType>& result, const
|
||||
using local_float_type = typename double_float_type::float_type;
|
||||
|
||||
// Get a local copy of the argument and force it to be positive.
|
||||
const bool b_neg { x.isneg_unchecked() };
|
||||
|
||||
const double_float_type xx { (!b_neg) ? x : -x };
|
||||
|
||||
// Check the range of the input.
|
||||
if (eval_lt(x, double_float_type::my_value_logmin()))
|
||||
const double_float_type max_exp_input
|
||||
{
|
||||
[]() -> local_float_type
|
||||
{
|
||||
local_float_type mx { };
|
||||
eval_convert_to(&mx, double_float_type::my_value_max());
|
||||
|
||||
const local_float_type log_of_mx = cpp_df_qf_detail::ccmath::log(mx);
|
||||
|
||||
return log_of_mx;
|
||||
}()
|
||||
};
|
||||
|
||||
const double_float_type min_exp_input
|
||||
{
|
||||
[]() -> local_float_type
|
||||
{
|
||||
local_float_type mn { };
|
||||
eval_convert_to(&mn, double_float_type::my_value_min());
|
||||
|
||||
const local_float_type log_of_mn = cpp_df_qf_detail::ccmath::log(mn);
|
||||
|
||||
return log_of_mn;
|
||||
}()
|
||||
};
|
||||
|
||||
if (eval_lt(x, min_exp_input))
|
||||
{
|
||||
result = double_float_type(0U);
|
||||
}
|
||||
else if (eval_gt(xx, double_float_type::my_value_logmax()))
|
||||
else if (eval_gt(xx, max_exp_input))
|
||||
{
|
||||
result = double_float_type::my_value_inf();
|
||||
}
|
||||
@@ -1988,15 +1834,42 @@ constexpr auto eval_exp(cpp_double_fp_backend<FloatingPointType>& result, const
|
||||
using local_float_type = typename double_float_type::float_type;
|
||||
|
||||
// Get a local copy of the argument and force it to be positive.
|
||||
const bool b_neg { x.isneg_unchecked() };
|
||||
|
||||
const double_float_type xx { (!b_neg) ? x : -x };
|
||||
|
||||
// Check the range of the input.
|
||||
if (eval_lt(x, double_float_type::my_value_logmin()))
|
||||
const double_float_type max_exp_input
|
||||
{
|
||||
[]() -> local_float_type
|
||||
{
|
||||
local_float_type mx { };
|
||||
eval_convert_to(&mx, double_float_type::my_value_max());
|
||||
|
||||
const local_float_type log_of_mx = cpp_df_qf_detail::ccmath::log(mx);
|
||||
|
||||
return log_of_mx;
|
||||
}()
|
||||
};
|
||||
|
||||
const double_float_type min_exp_input
|
||||
{
|
||||
[]() -> local_float_type
|
||||
{
|
||||
local_float_type mn { };
|
||||
eval_convert_to(&mn, double_float_type::my_value_min());
|
||||
|
||||
const local_float_type log_of_mn = cpp_df_qf_detail::ccmath::log(mn);
|
||||
|
||||
return log_of_mn;
|
||||
}()
|
||||
};
|
||||
|
||||
if (eval_lt(x, min_exp_input))
|
||||
{
|
||||
result = double_float_type(0U);
|
||||
}
|
||||
else if (eval_gt(xx, double_float_type::my_value_logmax()))
|
||||
else if (eval_gt(xx, max_exp_input))
|
||||
{
|
||||
result = double_float_type::my_value_inf();
|
||||
}
|
||||
@@ -2118,11 +1991,37 @@ constexpr auto eval_exp(cpp_double_fp_backend<FloatingPointType>& result, const
|
||||
const double_float_type xx { (!b_neg) ? x : -x };
|
||||
|
||||
// Check the range of the input.
|
||||
if (eval_lt(x, double_float_type::my_value_logmin()))
|
||||
const double_float_type max_exp_input
|
||||
{
|
||||
[]() -> local_float_type
|
||||
{
|
||||
local_float_type mx { };
|
||||
eval_convert_to(&mx, double_float_type::my_value_max());
|
||||
|
||||
const local_float_type log_of_mx = cpp_df_qf_detail::ccmath::log(mx);
|
||||
|
||||
return log_of_mx;
|
||||
}()
|
||||
};
|
||||
|
||||
const double_float_type min_exp_input
|
||||
{
|
||||
[]() -> local_float_type
|
||||
{
|
||||
local_float_type mn { };
|
||||
eval_convert_to(&mn, double_float_type::my_value_min());
|
||||
|
||||
const local_float_type log_of_mn = cpp_df_qf_detail::ccmath::log(mn);
|
||||
|
||||
return log_of_mn;
|
||||
}()
|
||||
};
|
||||
|
||||
if (eval_lt(x, min_exp_input))
|
||||
{
|
||||
result = double_float_type(0U);
|
||||
}
|
||||
else if (eval_gt(xx, double_float_type::my_value_logmax()))
|
||||
else if (eval_gt(xx, max_exp_input))
|
||||
{
|
||||
result = double_float_type::my_value_inf();
|
||||
}
|
||||
@@ -2256,7 +2155,7 @@ constexpr auto eval_log(cpp_double_fp_backend<FloatingPointType>& result, const
|
||||
eval_frexp(x2, x, &n2);
|
||||
|
||||
// Get initial estimate using the self-written, detail math function log.
|
||||
const double_float_type s(cpp_df_qf_detail::ccmath::unsafe::log(x2.my_first()));
|
||||
const double_float_type s(cpp_df_qf_detail::ccmath::log(x2.my_first()));
|
||||
|
||||
double_float_type E { };
|
||||
|
||||
|
||||
@@ -13,47 +13,8 @@
|
||||
|
||||
#include "test_arithmetic.hpp"
|
||||
|
||||
void test_constexpr_ness()
|
||||
{
|
||||
using boost::multiprecision::cpp_double_double;
|
||||
|
||||
constexpr cpp_double_double one { 1 };
|
||||
|
||||
static_assert(static_cast<int>(one) == 1, "Error: constexpr cpp_double_double construction failed");
|
||||
|
||||
BOOST_CHECK(static_cast<int>(one) == 1);
|
||||
|
||||
constexpr cpp_double_double dd_a { 1.23 };
|
||||
constexpr cpp_double_double dd_b { 4.56 };
|
||||
constexpr cpp_double_double dd_c { dd_a * dd_b };
|
||||
|
||||
constexpr cpp_double_double dd_s { sqrt(dd_a) };
|
||||
constexpr cpp_double_double sqrt_hundred { sqrt(cpp_double_double(100)) };
|
||||
#if (defined(BOOST_GCC) && !defined(BOOST_CLANG) && (BOOST_GCC < 80000))
|
||||
const
|
||||
#else
|
||||
constexpr
|
||||
#endif
|
||||
cpp_double_double log_hundred { log(cpp_double_double(100)) };
|
||||
|
||||
static_assert(dd_c > 5, "Error in constexpr multiplication");
|
||||
static_assert(dd_s > 1, "Error in constexpr square root");
|
||||
static_assert(sqrt_hundred == 10, "Error in constexpr square root");
|
||||
#if (defined(BOOST_GCC) && !defined(BOOST_CLANG) && (BOOST_GCC < 80000))
|
||||
#else
|
||||
static_assert(log_hundred > 4.605, "Error in constexpr logarithm");
|
||||
#endif
|
||||
|
||||
BOOST_CHECK(dd_c > 5);
|
||||
BOOST_CHECK(dd_s > 1);
|
||||
BOOST_CHECK(sqrt_hundred == 10);
|
||||
BOOST_CHECK(log_hundred > 4.605);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
::test_constexpr_ness();
|
||||
|
||||
using boost::multiprecision::cpp_double_float;
|
||||
using boost::multiprecision::cpp_double_double;
|
||||
using boost::multiprecision::cpp_double_long_double;
|
||||
@@ -61,6 +22,10 @@ int main()
|
||||
using boost::multiprecision::cpp_double_float128;
|
||||
#endif
|
||||
|
||||
constexpr cpp_double_double one { 1 };
|
||||
|
||||
static_assert(static_cast<int>(one) == 1, "Error:constexpr-ness of cpp_double_double constructor failed");
|
||||
|
||||
test<cpp_double_float>();
|
||||
test<cpp_double_double>();
|
||||
test<cpp_double_long_double>();
|
||||
|
||||
@@ -510,15 +510,12 @@ int main()
|
||||
test<boost::multiprecision::float128>();
|
||||
#endif
|
||||
#ifdef TEST_CPP_DOUBLE_FLOAT
|
||||
#if (defined(BOOST_GCC) && !defined(BOOST_CLANG) && (BOOST_GCC < 80000))
|
||||
#else
|
||||
test<boost::multiprecision::cpp_double_float>();
|
||||
test<boost::multiprecision::cpp_double_double>();
|
||||
test<boost::multiprecision::cpp_double_long_double>();
|
||||
#if defined(BOOST_MP_CPP_DOUBLE_FP_HAS_FLOAT128)
|
||||
test<boost::multiprecision::cpp_double_float128>();
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
|
||||
@@ -1418,6 +1418,9 @@ namespace local
|
||||
}
|
||||
|
||||
#ifdef BOOST_HAS_INT128
|
||||
|
||||
#define BOOST_MP_TEST_DISABLE_INT128_NON_FINITE
|
||||
|
||||
constexpr bool is_24_digit_float { (std::numeric_limits<float>::digits == 24) };
|
||||
|
||||
constexpr bool is_cpp_double_float
|
||||
@@ -1427,7 +1430,6 @@ namespace local
|
||||
|
||||
BOOST_IF_CONSTEXPR(is_24_digit_float && is_cpp_double_float)
|
||||
{
|
||||
#if 0
|
||||
for(auto index = 0U; index < 8U; ++index)
|
||||
{
|
||||
using std::ldexp;
|
||||
@@ -1487,23 +1489,37 @@ namespace local
|
||||
const auto result_val_uinf_is_ok = (u128_inf == static_cast<boost::uint128_type>(std::numeric_limits<float>::infinity()));
|
||||
const auto result_val_uzer_is_ok = (u128_zer == static_cast<boost::uint128_type>(0));
|
||||
|
||||
#if defined(BOOST_MP_TEST_DISABLE_INT128_NON_FINITE)
|
||||
static_cast<void>(result_val_nan_is_ok);
|
||||
static_cast<void>(result_val_inf_is_ok);
|
||||
static_cast<void>(result_val_unan_is_ok);
|
||||
static_cast<void>(result_val_uinf_is_ok);
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_MP_TEST_DISABLE_INT128_NON_FINITE)
|
||||
BOOST_TEST(result_val_nan_is_ok);
|
||||
BOOST_TEST(result_val_inf_is_ok);
|
||||
#endif
|
||||
BOOST_TEST(result_val_zer_is_ok);
|
||||
|
||||
#if !defined(BOOST_MP_TEST_DISABLE_INT128_NON_FINITE)
|
||||
BOOST_TEST(result_val_unan_is_ok);
|
||||
BOOST_TEST(result_val_uinf_is_ok);
|
||||
#endif
|
||||
BOOST_TEST(result_val_uzer_is_ok);
|
||||
|
||||
#if !defined(BOOST_MP_TEST_DISABLE_INT128_NON_FINITE)
|
||||
result_is_ok = (result_val_nan_is_ok && result_is_ok);
|
||||
result_is_ok = (result_val_inf_is_ok && result_is_ok);
|
||||
#endif
|
||||
result_is_ok = (result_val_zer_is_ok && result_is_ok);
|
||||
|
||||
#if !defined(BOOST_MP_TEST_DISABLE_INT128_NON_FINITE)
|
||||
result_is_ok = (result_val_unan_is_ok && result_is_ok);
|
||||
result_is_ok = (result_val_uinf_is_ok && result_is_ok);
|
||||
#endif
|
||||
result_is_ok = (result_val_uzer_is_ok && result_is_ok);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1575,39 +1591,44 @@ namespace local
|
||||
const boost::int128_type n128_inf { static_cast<boost::int128_type>(flt_inf) };
|
||||
const boost::int128_type n128_zer { static_cast<boost::int128_type>(flt_zer) };
|
||||
|
||||
#define BOOST_MP_TEST_DISABLE_U128_NON_FINITE
|
||||
|
||||
#if !defined(BOOST_MP_TEST_DISABLE_U128_NON_FINITE)
|
||||
const boost::uint128_type u128_nan { static_cast<boost::uint128_type>(flt_nan) };
|
||||
const boost::uint128_type u128_inf { static_cast<boost::uint128_type>(flt_inf) };
|
||||
#endif
|
||||
const boost::uint128_type u128_zer { static_cast<boost::uint128_type>(flt_zer) };
|
||||
|
||||
const auto result_val_nan_is_ok = (n128_nan == static_cast<boost::int128_type>(std::numeric_limits<double>::quiet_NaN()));
|
||||
const auto result_val_inf_is_ok = (n128_inf == static_cast<boost::int128_type>(std::numeric_limits<double>::infinity()));
|
||||
const auto result_val_zer_is_ok = (n128_zer == static_cast<boost::int128_type>(0));
|
||||
|
||||
#if !defined(BOOST_MP_TEST_DISABLE_U128_NON_FINITE)
|
||||
const auto result_val_unan_is_ok = (u128_nan == static_cast<boost::uint128_type>(std::numeric_limits<double>::quiet_NaN()));
|
||||
const auto result_val_uinf_is_ok = (u128_inf == static_cast<boost::uint128_type>(std::numeric_limits<double>::infinity()));
|
||||
#endif
|
||||
const auto result_val_uzer_is_ok = (u128_zer == static_cast<boost::uint128_type>(0));
|
||||
|
||||
#if defined(BOOST_MP_TEST_DISABLE_INT128_NON_FINITE)
|
||||
static_cast<void>(result_val_nan_is_ok);
|
||||
static_cast<void>(result_val_inf_is_ok);
|
||||
static_cast<void>(result_val_unan_is_ok);
|
||||
static_cast<void>(result_val_uinf_is_ok);
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_MP_TEST_DISABLE_INT128_NON_FINITE)
|
||||
BOOST_TEST(result_val_nan_is_ok);
|
||||
BOOST_TEST(result_val_inf_is_ok);
|
||||
#endif
|
||||
BOOST_TEST(result_val_zer_is_ok);
|
||||
|
||||
#if !defined(BOOST_MP_TEST_DISABLE_U128_NON_FINITE)
|
||||
#if !defined(BOOST_MP_TEST_DISABLE_INT128_NON_FINITE)
|
||||
BOOST_TEST(result_val_unan_is_ok);
|
||||
BOOST_TEST(result_val_uinf_is_ok);
|
||||
#endif
|
||||
BOOST_TEST(result_val_uzer_is_ok);
|
||||
|
||||
#if !defined(BOOST_MP_TEST_DISABLE_INT128_NON_FINITE)
|
||||
result_is_ok = (result_val_nan_is_ok && result_is_ok);
|
||||
result_is_ok = (result_val_inf_is_ok && result_is_ok);
|
||||
#endif
|
||||
result_is_ok = (result_val_zer_is_ok && result_is_ok);
|
||||
|
||||
#if !defined(BOOST_MP_TEST_DISABLE_U128_NON_FINITE)
|
||||
#if !defined(BOOST_MP_TEST_DISABLE_INT128_NON_FINITE)
|
||||
result_is_ok = (result_val_unan_is_ok && result_is_ok);
|
||||
result_is_ok = (result_val_uinf_is_ok && result_is_ok);
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user