diff --git a/.drone.star b/.drone.star index 5c4cc5db8a..7b773dda7d 100644 --- a/.drone.star +++ b/.drone.star @@ -16,6 +16,7 @@ windowsglobalimage="cppalliance/dronevs2019" def main(ctx): things_to_test = [ "special_fun", "distribution_tests", "mp", "misc", "interpolators", "quadrature", "autodiff", "long-running-tests", "float128_tests" ] + gcc13_things_to_test = [ "special_fun", "distribution_tests", "mp", "misc", "interpolators", "quadrature", "autodiff", "long-running-tests", "float128_tests", "new_floats" ] sanitizer_test = [ "special_fun", "distribution_tests", "misc", "interpolators", "quadrature", "float128_tests" ] gnu_5_stds = [ "gnu++14", "c++14" ] gnu_6_stds = [ "gnu++14", "c++14", "gnu++17", "c++17" ] @@ -23,6 +24,7 @@ def main(ctx): gnu_9_stds = [ "gnu++14", "c++14", "gnu++17", "c++17", "gnu++2a", "c++2a" ] clang_10_stds = [ "c++14", "c++17", "c++2a" ] gnu_non_native = [ "gnu++17" ] + gcc13_stds = [ "c++23" ] result = [] @@ -59,6 +61,9 @@ def main(ctx): result.append(linux_cxx("Ubuntu g++ ARM64" + cxx + " " + suite, "g++", packages="g++", buildtype="boost", image="cppalliance/droneubuntu2204:multiarch", arch="arm64", environment={'TOOLSET': 'gcc', 'COMPILER': 'g++', 'CXXSTD': cxx, 'TEST_SUITE': suite, }, globalenv=globalenv)) for cxx in gnu_non_native: result.append(osx_cxx("M1 Clang " + cxx + " " + suite, "clang++", buildscript="drone", buildtype="boost", xcode_version="14.1", environment={'TOOLSET': 'clang', 'CXXSTD': cxx, 'TEST_SUITE': suite, 'DEFINE': 'BOOST_MATH_NO_REAL_CONCEPT_TESTS,BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS,BOOST_MATH_MULTI_ARCH_CI_RUN', }, globalenv=globalenv)) + for suite in gcc13_things_to_test: + for cxx in gcc13_stds: + result.append(linux_cxx("Ubuntu g++-13 " + cxx + " " + suite, "g++-13", packages="g++-13", buildtype="boost", image="cppalliance/droneubuntu2304:1", environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-13', 'CXXSTD': cxx, 'TEST_SUITE': suite, }, globalenv=globalenv)) return result diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e295723c58..f446b5c48a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,6 +9,7 @@ on: branches: - master - develop + - feature/** pull_request: release: types: [published, created, edited] @@ -47,7 +48,7 @@ jobs: if: steps.retry1.outcome=='failure' run: sudo apt-add-repository -y "ppa:ubuntu-toolchain-r/test" - name: Install packages - run: sudo apt install g++-12 clang-14 libgmp-dev libmpfr-dev libfftw3-dev + run: sudo apt-get install -y g++-12 clang-14 libgmp-dev libmpfr-dev libfftw3-dev - name: Checkout main boost run: git clone -b develop --depth 1 https://github.com/boostorg/boost.git ../boost-root - name: Update tools/boostdep @@ -105,7 +106,7 @@ jobs: if: steps.retry1.outcome=='failure' run: sudo apt-add-repository -y "ppa:ubuntu-toolchain-r/test" - name: Install packages - run: sudo apt install g++-9 g++-11 clang-9 clang-10 libgmp-dev libmpfr-dev libfftw3-dev + run: sudo apt-get install -y g++-9 g++-11 clang-9 clang-10 libgmp-dev libmpfr-dev libfftw3-dev - name: Checkout main boost run: git clone -b develop --depth 1 https://github.com/boostorg/boost.git ../boost-root - name: Update tools/boostdep @@ -364,7 +365,7 @@ jobs: if: steps.retry1.outcome=='failure' run: sudo apt-add-repository -y "ppa:ubuntu-toolchain-r/test" - name: Install packages - run: sudo apt install g++-10 libgmp-dev libmpfr-dev libfftw3-dev + run: sudo apt-get install -y g++-10 libgmp-dev libmpfr-dev libfftw3-dev - name: Checkout main boost run: git clone -b develop --depth 1 https://github.com/boostorg/boost.git ../boost-root - name: Update tools/boostdep @@ -404,7 +405,7 @@ jobs: if: steps.retry1.outcome=='failure' run: sudo apt-add-repository -y "ppa:ubuntu-toolchain-r/test" - name: Install packages - run: sudo apt install clang-10 libgmp-dev libmpfr-dev libfftw3-dev + run: sudo apt-get install -y clang-10 libgmp-dev libmpfr-dev libfftw3-dev libtbb-dev - name: Checkout main boost run: git clone -b develop --depth 1 https://github.com/boostorg/boost.git ../boost-root - name: Update tools/boostdep @@ -448,7 +449,7 @@ jobs: if: steps.retry1.outcome=='failure' run: sudo apt-add-repository -y "ppa:ubuntu-toolchain-r/test" - name: Install packages - run: sudo apt install g++-10 libgmp-dev libmpfr-dev libfftw3-dev + run: sudo apt-get install -y g++-10 libgmp-dev libmpfr-dev libfftw3-dev - name: Checkout main boost run: git clone -b develop --depth 1 https://github.com/boostorg/boost.git ../boost-root - name: Update tools/boostdep diff --git a/doc/graphs/fourier_transform_daubechies.png b/doc/graphs/fourier_transform_daubechies.png new file mode 100644 index 0000000000..5027d9f538 Binary files /dev/null and b/doc/graphs/fourier_transform_daubechies.png differ diff --git a/doc/sf/daubechies.qbk b/doc/sf/daubechies.qbk index 2d280f81b7..e1e7f52539 100644 --- a/doc/sf/daubechies.qbk +++ b/doc/sf/daubechies.qbk @@ -127,6 +127,48 @@ The 2 vanishing moment scaling function. [$../graphs/daubechies_8_scaling.svg] The 8 vanishing moment scaling function. +Boost.Math also provides numerical evaluation of the Fourier transform of these functions. +This is useful in sparse recovery problems where the measurements are taken in the Fourier basis. +The usage is exhibited below: + + #include + using boost::math::fourier_transform_daubechies_scaling; + // Evaluate the Fourier transform of the 4-vanishing moment Daubechies scaling function at ω=1.8: + std::complex hat_phi = fourier_transform_daubechies_scaling(1.8f); + +The Fourier transform convention is unitary with the sign of the imaginary unit being given in Daubechies Ten Lectures. +In particular, this means that `fourier_transform_daubechies_scaling(0.0)` returns 1/sqrt(2π). + +The implementation computes an infinite product of trigonometric polynomials as can be found from recursive application of the identity 𝓕[φ](ω) = m(ω/2)𝓕[φ](ω/2). +This is neither particularly fast nor accurate, but there appears to be no literature on this extremely useful topic, and hence the naive method must suffice. + +[$../graphs/fourier_transform_daubechies.png] + +A benchmark can be found in `reporting/performance/fourier_transform_daubechies_performance.cpp`; the results on a ~2021 M1 Macbook pro are presented below: + + +Run on (10 X 24.1212 MHz CPU s) +CPU Caches: + L1 Data 64 KiB (x10) + L1 Instruction 128 KiB (x10) + L2 Unified 4096 KiB (x5) +Load Average: 1.33, 1.52, 1.62 +----------------------------------------------------------- +Benchmark Time +----------------------------------------------------------- +FourierTransformDaubechiesScaling 70.3 ns +FourierTransformDaubechiesScaling 330 ns +FourierTransformDaubechiesScaling 335 ns +FourierTransformDaubechiesScaling 364 ns +FourierTransformDaubechiesScaling 386 ns +FourierTransformDaubechiesScaling 436 ns +FourierTransformDaubechiesScaling 447 ns +FourierTransformDaubechiesScaling 473 ns +FourierTransformDaubechiesScaling 503 ns +FourierTransformDaubechiesScaling 554 ns + +Due to the low accuracy of this method, `float` precision is arg-promoted to `double`, and hence takes just as long as `double` precision to execute. + [heading References] * Daubechies, Ingrid. ['Ten Lectures on Wavelets.] Vol. 61. Siam, 1992. diff --git a/example/calculate_fourier_transform_daubechies_constants.cpp b/example/calculate_fourier_transform_daubechies_constants.cpp new file mode 100644 index 0000000000..d4ad1f3d18 --- /dev/null +++ b/example/calculate_fourier_transform_daubechies_constants.cpp @@ -0,0 +1,43 @@ +// (C) Copyright Nick Thompson 2023. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include +#include + +using std::pow; +using boost::multiprecision::cpp_bin_float_100; +using boost::math::filters::daubechies_scaling_filter; +using boost::math::tools::polynomial; +using boost::math::constants::half; +using boost::math::constants::root_two; + +template +std::vector get_constants() { + auto h = daubechies_scaling_filter(); + auto p = polynomial(h.begin(), h.end()); + + auto q = polynomial({half(), half()}); + q = pow(q, N); + auto l = p/q; + return l.data(); +} + +template +void print_constants(std::vector const & l) { + std::cout << std::setprecision(std::numeric_limits::digits10 -10); + std::cout << "return std::array{"; + for (size_t i = 0; i < l.size() - 1; ++i) { + std::cout << "BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, " << l[i]/root_two() << "), "; + } + std::cout << "BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, " << l.back()/root_two() << ")};\n"; +} + +int main() { + auto constants = get_constants(); + print_constants(constants); +} diff --git a/example/fourier_transform_daubechies_ulp_plot.cpp b/example/fourier_transform_daubechies_ulp_plot.cpp new file mode 100644 index 0000000000..3cde316708 --- /dev/null +++ b/example/fourier_transform_daubechies_ulp_plot.cpp @@ -0,0 +1,60 @@ +// boost-no-inspect +// (C) Copyright Nick Thompson 2023. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include + +using boost::math::fourier_transform_daubechies_scaling; +using boost::math::tools::ulps_plot; + +template +void real_part() { + auto phi_real_hi_acc = [](double omega) { + auto z = fourier_transform_daubechies_scaling(omega); + return z.real(); + }; + + auto phi_real_lo_acc = [](float omega) { + auto z = fourier_transform_daubechies_scaling(omega); + return z.real(); + }; + auto plot = ulps_plot(phi_real_hi_acc, float(0.0), float(100.0), 20000); + plot.ulp_envelope(false); + plot.add_fn(phi_real_lo_acc); + plot.clip(100); + plot.title("Accuracy of 𝔑(𝓕[𝜙](ω)) with " + std::to_string(p) + " vanishing moments."); + plot.write("real_ft_daub_scaling_" + std::to_string(p) + ".svg"); + +} + +template +void imaginary_part() { + auto phi_imag_hi_acc = [](double omega) { + auto z = fourier_transform_daubechies_scaling(omega); + return z.imag(); + }; + + auto phi_imag_lo_acc = [](float omega) { + auto z = fourier_transform_daubechies_scaling(omega); + return z.imag(); + }; + auto plot = ulps_plot(phi_imag_hi_acc, float(0.0), float(100.0), 20000); + plot.ulp_envelope(false); + plot.add_fn(phi_imag_lo_acc); + plot.clip(100); + plot.title("Accuracy of 𝕴(𝓕[𝜙](ω)) with " + std::to_string(p) + " vanishing moments."); + plot.write("imag_ft_daub_scaling_" + std::to_string(p) + ".svg"); + +} + + +int main() { + real_part<3>(); + imaginary_part<3>(); + real_part<6>(); + imaginary_part<6>(); + return 0; +} diff --git a/include/boost/math/concepts/real_concept.hpp b/include/boost/math/concepts/real_concept.hpp index 446bfa8d5a..56e4342e6b 100644 --- a/include/boost/math/concepts/real_concept.hpp +++ b/include/boost/math/concepts/real_concept.hpp @@ -45,6 +45,10 @@ # include #endif +#if __has_include() +# include +#endif + namespace boost{ namespace math{ namespace concepts @@ -79,6 +83,12 @@ class real_concept #ifdef BOOST_MATH_USE_FLOAT128 real_concept(BOOST_MATH_FLOAT128_TYPE c) : m_value(c){} #endif +#ifdef __STDCPP_FLOAT32_T__ + real_concept(std::float32_t c) : m_value(static_cast(c)){} +#endif +#ifdef __STDCPP_FLOAT64_T__ + real_concept(std::float64_t c) : m_value(static_cast(c)){} +#endif // Assignment: real_concept& operator=(char c) { m_value = c; return *this; } @@ -96,6 +106,12 @@ class real_concept real_concept& operator=(float c) { m_value = c; return *this; } real_concept& operator=(double c) { m_value = c; return *this; } real_concept& operator=(long double c) { m_value = c; return *this; } + #ifdef __STDCPP_FLOAT32_T__ + real_concept& operator=(std::float32_t c) { m_value = c; return *this; } + #endif + #ifdef __STDCPP_FLOAT64_T__ + real_concept& operator=(std::float64_t c) { m_value = c; return *this; } + #endif // Access: real_concept_base_type value()const{ return m_value; } diff --git a/include/boost/math/cstdfloat/cstdfloat_limits.hpp b/include/boost/math/cstdfloat/cstdfloat_limits.hpp index 43265424d9..9661ab6526 100644 --- a/include/boost/math/cstdfloat/cstdfloat_limits.hpp +++ b/include/boost/math/cstdfloat/cstdfloat_limits.hpp @@ -24,7 +24,7 @@ #pragma GCC system_header #endif - #if defined(BOOST_CSTDFLOAT_HAS_INTERNAL_FLOAT128_T) && defined(BOOST_MATH_USE_FLOAT128) && !defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT) + #if defined(BOOST_CSTDFLOAT_HAS_INTERNAL_FLOAT128_T) && defined(BOOST_MATH_USE_FLOAT128) && !defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT) && (!defined(__GNUC__) || (defined(__GNUC__) && __GNUC__ < 14)) #include #include diff --git a/include/boost/math/differentiation/autodiff.hpp b/include/boost/math/differentiation/autodiff.hpp index 1286326c2e..7cda196852 100644 --- a/include/boost/math/differentiation/autodiff.hpp +++ b/include/boost/math/differentiation/autodiff.hpp @@ -1491,7 +1491,7 @@ fvar sqrt(fvar const& cr) { BOOST_IF_CONSTEXPR (order == 0) return fvar(*derivatives); else { - root_type numerator = 0.5; + root_type numerator = root_type(0.5); root_type powers = 1; #ifndef BOOST_NO_CXX17_IF_CONSTEXPR derivatives[1] = numerator / *derivatives; diff --git a/include/boost/math/differentiation/finite_difference.hpp b/include/boost/math/differentiation/finite_difference.hpp index 5e4433e000..1375bac7ad 100644 --- a/include/boost/math/differentiation/finite_difference.hpp +++ b/include/boost/math/differentiation/finite_difference.hpp @@ -153,7 +153,7 @@ namespace detail { const Real eps = (numeric_limits::epsilon)(); // Error bound ~eps^4/5 - Real h = pow(11.25*eps, static_cast(1) / static_cast(5)); + Real h = pow(Real(11.25)*eps, static_cast(1) / static_cast(5)); h = detail::make_xph_representable(x, h); Real ymth = f(x - 2 * h); Real yth = f(x + 2 * h); @@ -222,7 +222,7 @@ namespace detail { // Mathematica code to get the error: // Series[(f[x+h]-f[x-h])*(4/5) + (1/5)*(f[x-2*h] - f[x+2*h]) + (4/105)*(f[x+3*h] - f[x-3*h]) + (1/280)*(f[x-4*h] - f[x+4*h]), {h, 0, 9}] // If we used Kahan summation, we could get the max error down to h^8|f^(9)(x)|/630 + |f(x)|eps/h. - Real h = pow(551.25*eps, static_cast(1) / static_cast(9)); + Real h = pow(Real(551.25)*eps, static_cast(1) / static_cast(9)); h = detail::make_xph_representable(x, h); Real yh = f(x + h); diff --git a/include/boost/math/differentiation/lanczos_smoothing.hpp b/include/boost/math/differentiation/lanczos_smoothing.hpp index 1f18c2f6d5..9406b302d7 100644 --- a/include/boost/math/differentiation/lanczos_smoothing.hpp +++ b/include/boost/math/differentiation/lanczos_smoothing.hpp @@ -10,6 +10,7 @@ #include // to nan initialize #include #include +#include #include #include #include diff --git a/include/boost/math/distributions/beta.hpp b/include/boost/math/distributions/beta.hpp index bbc0d6d6a3..6c17ffa1a2 100644 --- a/include/boost/math/distributions/beta.hpp +++ b/include/boost/math/distributions/beta.hpp @@ -2,6 +2,7 @@ // Copyright John Maddock 2006. // Copyright Paul A. Bristow 2006. +// Copyright Matt Borland 2023. // Use, modification and distribution are subject to the // Boost Software License, Version 1.0. @@ -241,7 +242,7 @@ namespace boost { return result; } - return ibeta_inva(beta, x, probability, Policy()); + return static_cast(ibeta_inva(beta, x, probability, Policy())); } // RealType find_alpha(beta, a, probability) static RealType find_beta( @@ -264,7 +265,7 @@ namespace boost { return result; } - return ibeta_invb(alpha, x, probability, Policy()); + return static_cast(ibeta_invb(alpha, x, probability, Policy())); } // RealType find_beta(alpha, x, probability) private: @@ -396,7 +397,7 @@ namespace boost { if (a == 1) { - return 1 / beta(a, b); + return static_cast(1 / beta(a, b)); } else if (a < 1) { @@ -411,7 +412,7 @@ namespace boost { if (b == 1) { - return 1 / beta(a, b); + return static_cast(1 / beta(a, b)); } else if (b < 1) { @@ -423,7 +424,7 @@ namespace boost } } - return ibeta_derivative(a, b, x, Policy()); + return static_cast(ibeta_derivative(a, b, x, Policy())); } // pdf template @@ -454,7 +455,7 @@ namespace boost { return 1; } - return ibeta(a, b, x, Policy()); + return static_cast(ibeta(a, b, x, Policy())); } // beta cdf template @@ -481,16 +482,16 @@ namespace boost } if (x == 0) { - return 1; + return RealType(1); } else if (x == 1) { - return 0; + return RealType(0); } // Calculate cdf beta using the incomplete beta function. // Use of ibeta here prevents cancellation errors in calculating // 1 - x if x is very small, perhaps smaller than machine epsilon. - return ibetac(a, b, x, Policy()); + return static_cast(ibetac(a, b, x, Policy())); } // beta cdf template @@ -519,13 +520,13 @@ namespace boost // Special cases: if (p == 0) { - return 0; + return RealType(0); } if (p == 1) { - return 1; + return RealType(1); } - return ibeta_inv(a, b, p, static_cast(nullptr), Policy()); + return static_cast(ibeta_inv(a, b, p, static_cast(nullptr), Policy())); } // quantile template @@ -555,14 +556,14 @@ namespace boost // Special cases: if(q == 1) { - return 0; + return RealType(0); } if(q == 0) { - return 1; + return RealType(1); } - return ibetac_inv(a, b, q, static_cast(nullptr), Policy()); + return static_cast(ibetac_inv(a, b, q, static_cast(nullptr), Policy())); } // Quantile Complement } // namespace math diff --git a/include/boost/math/distributions/cauchy.hpp b/include/boost/math/distributions/cauchy.hpp index 8588686c8f..d914cca77e 100644 --- a/include/boost/math/distributions/cauchy.hpp +++ b/include/boost/math/distributions/cauchy.hpp @@ -81,7 +81,7 @@ RealType cdf_imp(const cauchy_distribution& dist, const RealTy RealType mx = -fabs((x - location) / scale); // scale is > 0 if(mx > -tools::epsilon() / 8) { // special case first: x extremely close to location. - return 0.5; + return static_cast(0.5f); } result = -atan(1 / mx) / constants::pi(); return (((x > location) != complement) ? 1 - result : result); diff --git a/include/boost/math/distributions/detail/hypergeometric_pdf.hpp b/include/boost/math/distributions/detail/hypergeometric_pdf.hpp index b9e7a2c3b3..9eeef270d8 100644 --- a/include/boost/math/distributions/detail/hypergeometric_pdf.hpp +++ b/include/boost/math/distributions/detail/hypergeometric_pdf.hpp @@ -262,7 +262,7 @@ inline T integer_power(const T& x, int ex) #ifdef __SUNPRO_CC return pow(x, T(ex)); #else - return pow(x, ex); + return static_cast(pow(x, ex)); #endif } template diff --git a/include/boost/math/distributions/inverse_gaussian.hpp b/include/boost/math/distributions/inverse_gaussian.hpp index b057b4469e..c8e46913af 100644 --- a/include/boost/math/distributions/inverse_gaussian.hpp +++ b/include/boost/math/distributions/inverse_gaussian.hpp @@ -382,7 +382,7 @@ inline RealType quantile(const inverse_gaussian_distribution& RealType guess = detail::guess_ig(p, dist.mean(), dist.scale()); using boost::math::tools::max_value; - RealType min = 0.; // Minimum possible value is bottom of range of distribution. + RealType min = static_cast(0); // Minimum possible value is bottom of range of distribution. RealType max = max_value();// Maximum possible value is top of range. // int digits = std::numeric_limits::digits; // Maximum possible binary digits accuracy for type T. // digits used to control how accurate to try to make the result. @@ -454,7 +454,7 @@ inline RealType quantile(const complemented2_type(0); // Minimum possible value is bottom of range of distribution. RealType max = max_value();// Maximum possible value is top of range. // int digits = std::numeric_limits::digits; // Maximum possible binary digits accuracy for type T. // digits used to control how accurate to try to make the result. diff --git a/include/boost/math/distributions/skew_normal.hpp b/include/boost/math/distributions/skew_normal.hpp index 646965995b..c2843fea1c 100644 --- a/include/boost/math/distributions/skew_normal.hpp +++ b/include/boost/math/distributions/skew_normal.hpp @@ -486,7 +486,7 @@ namespace boost{ namespace math{ // 21 elements static const RealType shapes[] = { - 0.0, + static_cast(0.0), static_cast(1.000000000000000e-004), static_cast(2.069138081114790e-004), static_cast(4.281332398719396e-004), @@ -511,7 +511,7 @@ namespace boost{ namespace math{ // 21 elements static const RealType guess[] = { - 0.0, + static_cast(0.0), static_cast(5.000050000525391e-005), static_cast(1.500015000148736e-004), static_cast(3.500035000350010e-004), diff --git a/include/boost/math/interpolators/detail/cardinal_cubic_b_spline_detail.hpp b/include/boost/math/interpolators/detail/cardinal_cubic_b_spline_detail.hpp index 22491a70a4..2064caa515 100644 --- a/include/boost/math/interpolators/detail/cardinal_cubic_b_spline_detail.hpp +++ b/include/boost/math/interpolators/detail/cardinal_cubic_b_spline_detail.hpp @@ -225,7 +225,7 @@ cardinal_cubic_b_spline_imp::cardinal_cubic_b_spline_imp(BidiIterator f, B // mapsto // 1 0 -1 | r0 // 0 1 1/2| (r1 - r0)/4 - super_diagonal[1] = 0.5; + super_diagonal[1] = static_cast(0.5); rhs[1] = (rhs[1] - rhs[0])/4; // Now do a tridiagonal row reduction the standard way, until just before the last row: diff --git a/include/boost/math/policies/error_handling.hpp b/include/boost/math/policies/error_handling.hpp index a008157df0..d5e30c08f3 100644 --- a/include/boost/math/policies/error_handling.hpp +++ b/include/boost/math/policies/error_handling.hpp @@ -82,7 +82,7 @@ namespace detail { template -std::string prec_format(const T& val) +inline std::string prec_format(const T& val) { typedef typename boost::math::policies::precision >::type prec_type; std::stringstream ss; @@ -95,6 +95,18 @@ std::string prec_format(const T& val) return ss.str(); } +#ifdef BOOST_MATH_USE_CHARCONV_FOR_CONVERSION + +template <> +inline std::string prec_format(const std::float128_t& val) +{ + char buffer[128] {}; + const auto r = std::to_chars(buffer, buffer + sizeof(buffer), val); + return std::string(buffer, r.ptr); +} + +#endif + inline void replace_all_in_string(std::string& result, const char* what, const char* with) { std::string::size_type pos = 0; diff --git a/include/boost/math/quadrature/naive_monte_carlo.hpp b/include/boost/math/quadrature/naive_monte_carlo.hpp index 78c06a02aa..4ad95ad832 100644 --- a/include/boost/math/quadrature/naive_monte_carlo.hpp +++ b/include/boost/math/quadrature/naive_monte_carlo.hpp @@ -21,6 +21,11 @@ #include #include #include +#include + +#ifdef BOOST_NAIVE_MONTE_CARLO_DEBUG_FAILURES +# include +#endif namespace boost { namespace math { namespace quadrature { @@ -45,6 +50,8 @@ class naive_monte_carlo { using std::numeric_limits; using std::sqrt; + using boost::math::isinf; + uint64_t n = bounds.size(); m_lbs.resize(n); m_dxs.resize(n); @@ -58,9 +65,9 @@ class naive_monte_carlo boost::math::policies::raise_domain_error(function, "The upper bound is <= the lower bound.\n", bounds[i].second, Policy()); return; } - if (bounds[i].first == -numeric_limits::infinity()) + if (isinf(bounds[i].first)) { - if (bounds[i].second == numeric_limits::infinity()) + if (isinf(bounds[i].second)) { m_limit_types[i] = detail::limit_classification::DOUBLE_INFINITE; } @@ -72,7 +79,7 @@ class naive_monte_carlo m_dxs[i] = numeric_limits::quiet_NaN(); } } - else if (bounds[i].second == numeric_limits::infinity()) + else if (isinf(bounds[i].second)) { m_limit_types[i] = detail::limit_classification::UPPER_BOUND_INFINITE; if (singular) @@ -285,17 +292,17 @@ class naive_monte_carlo m_done = false; #ifdef BOOST_NAIVE_MONTE_CARLO_DEBUG_FAILURES - std::cout << "Failed to achieve required tolerance first time through..\n"; - std::cout << " variance = " << m_variance << std::endl; - std::cout << " average = " << m_avg << std::endl; - std::cout << " total calls = " << m_total_calls << std::endl; + std::cerr << "Failed to achieve required tolerance first time through..\n"; + std::cerr << " variance = " << m_variance << std::endl; + std::cerr << " average = " << m_avg << std::endl; + std::cerr << " total calls = " << m_total_calls << std::endl; for (std::size_t i = 0; i < m_num_threads; ++i) - std::cout << " thread_calls[" << i << "] = " << m_thread_calls[i] << std::endl; + std::cerr << " thread_calls[" << i << "] = " << m_thread_calls[i] << std::endl; for (std::size_t i = 0; i < m_num_threads; ++i) - std::cout << " thread_averages[" << i << "] = " << m_thread_averages[i] << std::endl; + std::cerr << " thread_averages[" << i << "] = " << m_thread_averages[i] << std::endl; for (std::size_t i = 0; i < m_num_threads; ++i) - std::cout << " thread_Ss[" << i << "] = " << m_thread_Ss[i] << std::endl; + std::cerr << " thread_Ss[" << i << "] = " << m_thread_Ss[i] << std::endl; #endif } diff --git a/include/boost/math/special_functions/bessel_prime.hpp b/include/boost/math/special_functions/bessel_prime.hpp index 9615d40644..6d8b466f2a 100644 --- a/include/boost/math/special_functions/bessel_prime.hpp +++ b/include/boost/math/special_functions/bessel_prime.hpp @@ -38,9 +38,9 @@ inline T cyl_bessel_j_prime_imp(T v, T x, const Policy& pol) if (x == 0) { if (v == 1) - return 0.5; + return static_cast(0.5); else if (v == -1) - return -0.5; + return static_cast(-0.5); else if (floor(v) == v || v > 1) return 0; else return boost::math::policies::raise_domain_error( @@ -126,7 +126,7 @@ inline T cyl_bessel_i_prime_imp(T v, T x, const Policy& pol) if (x == 0) { if (v == 1 || v == -1) - return 0.5; + return static_cast(0.5); else if (floor(v) == v || v > 1) return 0; else return boost::math::policies::raise_domain_error( diff --git a/include/boost/math/special_functions/beta.hpp b/include/boost/math/special_functions/beta.hpp index 77ca35dcd8..ec824daf72 100644 --- a/include/boost/math/special_functions/beta.hpp +++ b/include/boost/math/special_functions/beta.hpp @@ -586,7 +586,7 @@ T ibeta_series(T a, T b, T x, T s0, const Lanczos&, bool normalised, T* p_deriva if(a * b < bgh * 10) result *= exp((b - 0.5f) * boost::math::log1p(a / bgh, pol)); else - result *= pow(cgh / bgh, b - 0.5f); + result *= pow(cgh / bgh, T(b - T(0.5))); result *= pow(x * cgh / agh, a); result *= sqrt(agh / boost::math::constants::e()); @@ -963,14 +963,14 @@ T binomial_ccdf(T n, T k, T x, T y, const Policy& pol) int start = itrunc(n * x); if(start <= k + 1) start = itrunc(k + 2); - result = static_cast(pow(x, start) * pow(y, n - start) * boost::math::binomial_coefficient(itrunc(n), itrunc(start), pol)); + result = static_cast(pow(x, T(start)) * pow(y, n - T(start)) * boost::math::binomial_coefficient(itrunc(n), itrunc(start), pol)); if(result == 0) { // OK, starting slightly above the mode didn't work, // we'll have to sum the terms the old fashioned way: for(unsigned i = start - 1; i > k; --i) { - result += static_cast(pow(x, static_cast(i)) * pow(y, n - i) * boost::math::binomial_coefficient(itrunc(n), itrunc(i), pol)); + result += static_cast(pow(x, static_cast(i)) * pow(y, n - i) * boost::math::binomial_coefficient(itrunc(n), itrunc(i), pol)); } } else @@ -1501,8 +1501,9 @@ template inline typename tools::promote_args::type beta(RT1 a, RT2 b, A arg) { - typedef typename policies::is_policy::type tag; - return boost::math::detail::beta(a, b, arg, static_cast(nullptr)); + using tag = typename policies::is_policy::type; + using ReturnType = tools::promote_args_t; + return static_cast(boost::math::detail::beta(a, b, arg, static_cast(nullptr))); } template diff --git a/include/boost/math/special_functions/binomial.hpp b/include/boost/math/special_functions/binomial.hpp index f76b48cc13..20bcf3e8c6 100644 --- a/include/boost/math/special_functions/binomial.hpp +++ b/include/boost/math/special_functions/binomial.hpp @@ -46,9 +46,9 @@ T binomial_coefficient(unsigned n, unsigned k, const Policy& pol) { // Use the beta function: if(k < n - k) - result = k * beta(static_cast(k), static_cast(n-k+1), pol); + result = static_cast(k * beta(static_cast(k), static_cast(n-k+1), pol)); else - result = (n - k) * beta(static_cast(k+1), static_cast(n-k), pol); + result = static_cast((n - k) * beta(static_cast(k+1), static_cast(n-k), pol)); if(result == 0) return policies::raise_overflow_error(function, nullptr, pol); result = 1 / result; diff --git a/include/boost/math/special_functions/chebyshev.hpp b/include/boost/math/special_functions/chebyshev.hpp index d69fd9c50e..2c6695446b 100644 --- a/include/boost/math/special_functions/chebyshev.hpp +++ b/include/boost/math/special_functions/chebyshev.hpp @@ -6,6 +6,7 @@ #ifndef BOOST_MATH_SPECIAL_CHEBYSHEV_HPP #define BOOST_MATH_SPECIAL_CHEBYSHEV_HPP #include +#include #include #include #include @@ -30,6 +31,31 @@ inline tools::promote_args_t chebyshev_next(T1 const & x, T2 const & namespace detail { +// https://stackoverflow.com/questions/5625431/efficient-way-to-compute-pq-exponentiation-where-q-is-an-integer +template ::value, bool>::type = true> +T expt(T p, unsigned q) +{ + T r = 1; + + while (q != 0) { + if (q % 2 == 1) { // q is odd + r *= p; + q--; + } + p *= p; + q /= 2; + } + + return r; +} + +template ::value, bool>::type = true> +T expt(T p, unsigned q) +{ + using std::pow; + return pow(p, static_cast(q)); +} + template inline Real chebyshev_imp(unsigned n, Real const & x, const Policy&) { @@ -51,7 +77,7 @@ inline Real chebyshev_imp(unsigned n, Real const & x, const Policy&) if (x > 1 || x < -1) { Real t = sqrt(x*x -1); - return static_cast((pow(x+t, static_cast(n+1)) - pow(x-t, static_cast(n+1)))/(2*t)); + return static_cast((expt(static_cast(x+t), n+1) - expt(static_cast(x-t), n+1))/(2*t)); } T1 = 2*x; } @@ -84,7 +110,7 @@ inline Real chebyshev_imp(unsigned n, Real const & x, const Policy&) while(l < n) { std::swap(T0, T1); - T1 = boost::math::chebyshev_next(x, T0, T1); + T1 = static_cast(boost::math::chebyshev_next(x, T0, T1)); ++l; } return T1; diff --git a/include/boost/math/special_functions/cos_pi.hpp b/include/boost/math/special_functions/cos_pi.hpp index ab1cdf810c..e09700ec5e 100644 --- a/include/boost/math/special_functions/cos_pi.hpp +++ b/include/boost/math/special_functions/cos_pi.hpp @@ -26,7 +26,7 @@ T cos_pi_imp(T x, const Policy&) BOOST_MATH_STD_USING // ADL of std names // cos of pi*x: bool invert = false; - if(fabs(x) < 0.25) + if(fabs(x) < T(0.25)) return cos(constants::pi() * x); if(x < 0) diff --git a/include/boost/math/special_functions/daubechies_scaling.hpp b/include/boost/math/special_functions/daubechies_scaling.hpp index 069b35a0ed..40de7b5acf 100644 --- a/include/boost/math/special_functions/daubechies_scaling.hpp +++ b/include/boost/math/special_functions/daubechies_scaling.hpp @@ -7,12 +7,16 @@ #ifndef BOOST_MATH_SPECIAL_DAUBECHIES_SCALING_HPP #define BOOST_MATH_SPECIAL_DAUBECHIES_SCALING_HPP + +#include +#include +#include #include #include -#include #include #include #include +#include #include #include #include @@ -21,10 +25,10 @@ #include #ifndef BOOST_MATH_STANDALONE -#include -#ifdef BOOST_NO_CXX17_IF_CONSTEXPR -#error "The header can only be used in C++17 and later." -#endif +# include +# ifdef BOOST_NO_CXX17_IF_CONSTEXPR +# error "The header can only be used in C++17 and later." +# endif #endif namespace boost::math { @@ -207,12 +211,13 @@ class linear_interpolation { inline Real prime(Real x) const { using std::floor; + Real y = x*s_; Real k = floor(y); int64_t kk = static_cast(k); Real t = y - k; - return (1-t)*dydx_[kk] + t*dydx_[kk+1]; + return static_cast((Real(1)-t)*dydx_[kk] + t*dydx_[kk+1]); } int64_t bytes() const @@ -274,170 +279,170 @@ class linear_interpolation_aos { template struct daubechies_eval_type { - typedef T type; + using type = T; - static const std::vector& vector_cast(const std::vector& v) { return v; } + static const std::vector& vector_cast(const std::vector& v) { return v; } }; template <> struct daubechies_eval_type { - typedef double type; - - inline static std::vector vector_cast(const std::vector& v) - { - std::vector result(v.size()); - for (unsigned i = 0; i < v.size(); ++i) - result[i] = static_cast(v[i]); - return result; - } + using type = double; + + inline static std::vector vector_cast(const std::vector& v) + { + std::vector result(v.size()); + for (unsigned i = 0; i < v.size(); ++i) + result[i] = static_cast(v[i]); + return result; + } }; template <> struct daubechies_eval_type { - typedef long double type; - - inline static std::vector vector_cast(const std::vector& v) - { - std::vector result(v.size()); - for (unsigned i = 0; i < v.size(); ++i) - result[i] = static_cast(v[i]); - return result; - } + using type = long double; + + inline static std::vector vector_cast(const std::vector& v) + { + std::vector result(v.size()); + for (unsigned i = 0; i < v.size(); ++i) + result[i] = static_cast(v[i]); + return result; + } }; struct null_interpolator { - template - T operator()(const T&) - { - return 1; - } + template + T operator()(const T&) + { + return 1; + } }; } // namespace detail template class daubechies_scaling { - // - // Some type manipulation so we know the type of the interpolator, and the vector type it requires: - // - typedef std::vector> vector_type; - // - // List our interpolators: - // - typedef std::tuple< - detail::null_interpolator, detail::matched_holder_aos, detail::linear_interpolation_aos, - interpolators::detail::cardinal_cubic_hermite_detail_aos, interpolators::detail::cardinal_quintic_hermite_detail_aos, - interpolators::detail::cardinal_septic_hermite_detail_aos > interpolator_list; - // - // Select the one we need: - // - typedef std::tuple_element_t< - p == 1 ? 0 : - p == 2 ? 1 : - p == 3 ? 2 : - p <= 5 ? 3 : - p <= 9 ? 4 : 5, interpolator_list> interpolator_type; + // + // Some type manipulation so we know the type of the interpolator, and the vector type it requires: + // + using vector_type = std::vector>; + // + // List our interpolators: + // + using interpolator_list = std::tuple< + detail::null_interpolator, detail::matched_holder_aos, detail::linear_interpolation_aos, + interpolators::detail::cardinal_cubic_hermite_detail_aos, interpolators::detail::cardinal_quintic_hermite_detail_aos, + interpolators::detail::cardinal_septic_hermite_detail_aos >; + // + // Select the one we need: + // + using interpolator_type = std::tuple_element_t< + p == 1 ? 0 : + p == 2 ? 1 : + p == 3 ? 2 : + p <= 5 ? 3 : + p <= 9 ? 4 : 5, interpolator_list>; public: - daubechies_scaling(int grid_refinements = -1) - { - static_assert(p < 20, "Daubechies scaling functions are only implemented for p < 20."); - static_assert(p > 0, "Daubechies scaling functions must have at least 1 vanishing moment."); - if constexpr (p == 1) - { - return; - } - else { - if (grid_refinements < 0) - { - if (std::is_same_v) - { - if (grid_refinements == -2) - { - // Control absolute error: - // p= 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 - std::array r{ -1, -1, 18, 19, 16, 11, 8, 7, 7, 7, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3 }; - grid_refinements = r[p]; - } - else - { - // Control relative error: - // p= 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 - std::array r{ -1, -1, 21, 21, 21, 17, 16, 15, 14, 13, 12, 11, 11, 11, 11, 11, 11, 11, 11, 11 }; - grid_refinements = r[p]; - } - } - else if (std::is_same_v) - { - // p= 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 - std::array r{ -1, -1, 21, 21, 21, 21, 21, 21, 21, 21, 20, 20, 19, 19, 18, 18, 18, 18, 18, 18 }; - grid_refinements = r[p]; - } - else + daubechies_scaling(int grid_refinements = -1) + { + static_assert(p < 20, "Daubechies scaling functions are only implemented for p < 20."); + static_assert(p > 0, "Daubechies scaling functions must have at least 1 vanishing moment."); + if constexpr (p == 1) + { + return; + } + else { + if (grid_refinements < 0) { - grid_refinements = 21; + if (std::is_same_v) + { + if (grid_refinements == -2) + { + // Control absolute error: + // p= 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 + std::array r{ -1, -1, 18, 19, 16, 11, 8, 7, 7, 7, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3 }; + grid_refinements = r[p]; + } + else + { + // Control relative error: + // p= 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 + std::array r{ -1, -1, 21, 21, 21, 17, 16, 15, 14, 13, 12, 11, 11, 11, 11, 11, 11, 11, 11, 11 }; + grid_refinements = r[p]; + } + } + else if (std::is_same_v) + { + // p= 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 + std::array r{ -1, -1, 21, 21, 21, 21, 21, 21, 21, 21, 20, 20, 19, 19, 18, 18, 18, 18, 18, 18 }; + grid_refinements = r[p]; + } + else + { + grid_refinements = 21; + } } - } - - // Compute the refined grid: - // In fact for float precision I know the grid must be computed in double precision and then cast back down, or else parts of the support are systematically inaccurate. - std::future> t0 = std::async(std::launch::async, [&grid_refinements]() { - // Computing in higher precision and downcasting is essential for 1ULP evaluation in float precision: - auto v = daubechies_scaling_dyadic_grid::type, p, 0>(grid_refinements); - return detail::daubechies_eval_type::vector_cast(v); - }); - // Compute the derivative of the refined grid: - std::future> t1 = std::async(std::launch::async, [&grid_refinements]() { - auto v = daubechies_scaling_dyadic_grid::type, p, 1>(grid_refinements); - return detail::daubechies_eval_type::vector_cast(v); - }); - - // if necessary, compute the second and third derivative: - std::vector d2ydx2; - std::vector d3ydx3; - if constexpr (p >= 6) { - std::future> t3 = std::async(std::launch::async, [&grid_refinements]() { - auto v = daubechies_scaling_dyadic_grid::type, p, 2>(grid_refinements); - return detail::daubechies_eval_type::vector_cast(v); - }); - - if constexpr (p >= 10) { - std::future> t4 = std::async(std::launch::async, [&grid_refinements]() { - auto v = daubechies_scaling_dyadic_grid::type, p, 3>(grid_refinements); - return detail::daubechies_eval_type::vector_cast(v); - }); - d3ydx3 = t4.get(); + + // Compute the refined grid: + // In fact for float precision I know the grid must be computed in double precision and then cast back down, or else parts of the support are systematically inaccurate. + std::future> t0 = std::async(std::launch::async, [&grid_refinements]() { + // Computing in higher precision and downcasting is essential for 1ULP evaluation in float precision: + auto v = daubechies_scaling_dyadic_grid::type, p, 0>(grid_refinements); + return detail::daubechies_eval_type::vector_cast(v); + }); + // Compute the derivative of the refined grid: + std::future> t1 = std::async(std::launch::async, [&grid_refinements]() { + auto v = daubechies_scaling_dyadic_grid::type, p, 1>(grid_refinements); + return detail::daubechies_eval_type::vector_cast(v); + }); + + // if necessary, compute the second and third derivative: + std::vector d2ydx2; + std::vector d3ydx3; + if constexpr (p >= 6) { + std::future> t3 = std::async(std::launch::async, [&grid_refinements]() { + auto v = daubechies_scaling_dyadic_grid::type, p, 2>(grid_refinements); + return detail::daubechies_eval_type::vector_cast(v); + }); + + if constexpr (p >= 10) { + std::future> t4 = std::async(std::launch::async, [&grid_refinements]() { + auto v = daubechies_scaling_dyadic_grid::type, p, 3>(grid_refinements); + return detail::daubechies_eval_type::vector_cast(v); + }); + d3ydx3 = t4.get(); + } + d2ydx2 = t3.get(); } - d2ydx2 = t3.get(); - } - auto y = t0.get(); - auto dydx = t1.get(); + auto y = t0.get(); + auto dydx = t1.get(); - if constexpr (p >= 2) - { - vector_type data(y.size()); - for (size_t i = 0; i < y.size(); ++i) + if constexpr (p >= 2) { - data[i][0] = y[i]; - data[i][1] = dydx[i]; - if constexpr (p >= 6) - data[i][2] = d2ydx2[i]; - if constexpr (p >= 10) - data[i][3] = d3ydx3[i]; + vector_type data(y.size()); + for (size_t i = 0; i < y.size(); ++i) + { + data[i][0] = y[i]; + data[i][1] = dydx[i]; + if constexpr (p >= 6) + data[i][2] = d2ydx2[i]; + if constexpr (p >= 10) + data[i][3] = d3ydx3[i]; + } + if constexpr (p <= 3) + m_interpolator = std::make_shared(std::move(data), grid_refinements, Real(0)); + else + m_interpolator = std::make_shared(std::move(data), Real(0), Real(1) / (1 << grid_refinements)); } - if constexpr (p <= 3) - m_interpolator = std::make_shared(std::move(data), grid_refinements, Real(0)); else - m_interpolator = std::make_shared(std::move(data), Real(0), Real(1) / (1 << grid_refinements)); - } - else - m_interpolator = std::make_shared(); - } - } + m_interpolator = std::make_shared(); + } + } inline Real operator()(Real x) const { @@ -451,7 +456,7 @@ class daubechies_scaling { inline Real prime(Real x) const { static_assert(p > 2, "The 3-vanishing moment Daubechies scaling function is the first which is continuously differentiable."); - if (x <= 0 || x >= 2*p-1) + if (x <= Real(0) || x >= 2*p-1) { return 0; } @@ -475,7 +480,7 @@ class daubechies_scaling { int64_t bytes() const { - return m_interpolator->bytes() + sizeof(m_interpolator); + return m_interpolator->bytes() + sizeof(m_interpolator); } private: diff --git a/include/boost/math/special_functions/detail/bessel_jy_asym.hpp b/include/boost/math/special_functions/detail/bessel_jy_asym.hpp index f3198565ff..16b6543f90 100644 --- a/include/boost/math/special_functions/detail/bessel_jy_asym.hpp +++ b/include/boost/math/special_functions/detail/bessel_jy_asym.hpp @@ -175,7 +175,7 @@ void temme_asymptotic_y_small_x(T v, T x, T* Y, T* Y1, const Policy& pol) p /= k - v; q /= k + v; c *= c_mult / k; - T c1 = pow(-x * x / 4, k) / factorial(k, pol); + T c1 = pow(-x * x / 4, T(k)) / factorial(k, pol); g = f + g_prefix * q; h = -k * g + p; y += c * g; diff --git a/include/boost/math/special_functions/detail/bessel_jy_series.hpp b/include/boost/math/special_functions/detail/bessel_jy_series.hpp index 5e9ffea45b..a5fc7b832e 100644 --- a/include/boost/math/special_functions/detail/bessel_jy_series.hpp +++ b/include/boost/math/special_functions/detail/bessel_jy_series.hpp @@ -236,7 +236,12 @@ T bessel_yn_small_z(int n, T z, T* scale, const Policy& pol) } else { + #if (defined(__GNUC__) && __GNUC__ == 13) + auto p = static_cast(pow(z / 2, T(n))); + #else auto p = static_cast(pow(z / 2, n)); + #endif + T result = -((boost::math::factorial(n - 1, pol) / constants::pi())); if(p * tools::max_value() < result) { diff --git a/include/boost/math/special_functions/detail/hypergeometric_1F1_bessel.hpp b/include/boost/math/special_functions/detail/hypergeometric_1F1_bessel.hpp index c3febc6208..763b2fa1b1 100644 --- a/include/boost/math/special_functions/detail/hypergeometric_1F1_bessel.hpp +++ b/include/boost/math/special_functions/detail/hypergeometric_1F1_bessel.hpp @@ -184,7 +184,7 @@ // if ((j < cache_size - 2) && (tools::max_value() / fabs(64 * bessel_cache[j] / bessel_cache[j + 1]) < fabs(bessel_cache[j]))) { - T rescale = pow(fabs(bessel_cache[j] / bessel_cache[j + 1]), j + 1) * 2; + T rescale = static_cast(pow(fabs(bessel_cache[j] / bessel_cache[j + 1]), T(j + 1)) * 2); if (!((boost::math::isfinite)(rescale))) rescale = tools::max_value(); for (int k = j; k < cache_size; ++k) @@ -259,7 +259,7 @@ // if ((j < cache_size - 2) && (tools::max_value() / fabs(64 * bessel_cache[j] / bessel_cache[j + 1]) < fabs(bessel_cache[j]))) { - T rescale = pow(fabs(bessel_cache[j] / bessel_cache[j + 1]), j + 1) * 2; + T rescale = static_cast(pow(fabs(bessel_cache[j] / bessel_cache[j + 1]), T(j + 1)) * 2); if (!((boost::math::isfinite)(rescale))) rescale = tools::max_value(); for (int k = j; k < cache_size; ++k) @@ -558,7 +558,7 @@ // if((j < cache_size - 2) && (bessel_i_cache[j + 1] != 0) && (tools::max_value() / fabs(64 * bessel_i_cache[j] / bessel_i_cache[j + 1]) < fabs(bessel_i_cache[j]))) { - T rescale = pow(fabs(bessel_i_cache[j] / bessel_i_cache[j + 1]), j + 1) * 2; + T rescale = static_cast(pow(fabs(bessel_i_cache[j] / bessel_i_cache[j + 1]), T(j + 1)) * 2); if (rescale > tools::max_value()) rescale = tools::max_value(); for (int k = j; k < cache_size; ++k) @@ -591,7 +591,7 @@ std::uintmax_t max_iter = boost::math::policies::get_max_series_iterations(); T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon(), max_iter); boost::math::policies::check_series_iterations("boost::math::hypergeometric_1F1_AS_13_3_6<%1%>(%1%,%1%,%1%)", max_iter, pol); - result *= boost::math::tgamma(b_minus_a - 0.5f, pol) * pow(z / 4, -b_minus_a + 0.5f); + result *= boost::math::tgamma(b_minus_a - 0.5f, pol) * pow(z / 4, -b_minus_a + T(0.5f)); long long scale = lltrunc(z / 2); log_scaling += scale; log_scaling += s.scaling(); diff --git a/include/boost/math/special_functions/detail/hypergeometric_pFq_checked_series.hpp b/include/boost/math/special_functions/detail/hypergeometric_pFq_checked_series.hpp index 03b7af11a4..861d981a17 100644 --- a/include/boost/math/special_functions/detail/hypergeometric_pFq_checked_series.hpp +++ b/include/boost/math/special_functions/detail/hypergeometric_pFq_checked_series.hpp @@ -146,7 +146,13 @@ return std::make_pair(r, r); } std::pair r = hypergeometric_pFq_checked_series_impl(aj, bj, Real(1 / z), pol, termination, log_scale); + + #if (defined(__GNUC__) && __GNUC__ == 13) + Real mul = pow(-z, Real(-*aj.begin())); + #else Real mul = pow(-z, -*aj.begin()); + #endif + r.first *= mul; r.second *= mul; return r; diff --git a/include/boost/math/special_functions/detail/ibeta_inverse.hpp b/include/boost/math/special_functions/detail/ibeta_inverse.hpp index 79eb95c45f..be4bd95399 100644 --- a/include/boost/math/special_functions/detail/ibeta_inverse.hpp +++ b/include/boost/math/special_functions/detail/ibeta_inverse.hpp @@ -115,7 +115,7 @@ T temme_method_1_ibeta_inverse(T a, T b, T z, const Policy& pol) T c = -exp(-eta_2 / 2); T x; if(eta_2 == 0) - x = 0.5; + x = static_cast(0.5f); else x = (1 + eta * sqrt((1 + c) / eta_2)) / 2; // diff --git a/include/boost/math/special_functions/detail/igamma_inverse.hpp b/include/boost/math/special_functions/detail/igamma_inverse.hpp index 51c2b1c6c3..f6bbcd72d5 100644 --- a/include/boost/math/special_functions/detail/igamma_inverse.hpp +++ b/include/boost/math/special_functions/detail/igamma_inverse.hpp @@ -33,7 +33,7 @@ T find_inverse_s(T p, T q) // BOOST_MATH_STD_USING T t; - if(p < 0.5) + if(p < T(0.5)) { t = sqrt(-2 * log(p)); } @@ -44,7 +44,7 @@ T find_inverse_s(T p, T q) static const double a[4] = { 3.31125922108741, 11.6616720288968, 4.28342155967104, 0.213623493715853 }; static const double b[5] = { 1, 6.61053765625462, 6.40691597760039, 1.27364489782223, 0.3611708101884203e-1 }; T s = t - tools::evaluate_polynomial(a, t) / tools::evaluate_polynomial(b, t); - if(p < 0.5) + if(p < T(0.5)) s = -s; return s; } @@ -120,7 +120,7 @@ T find_inverse_gamma(T a, T p, T q, const Policy& pol, bool* p_has_10_digits) T b = q * g; BOOST_MATH_INSTRUMENT_VARIABLE(g); BOOST_MATH_INSTRUMENT_VARIABLE(b); - if((b > 0.6) || ((b >= 0.45) && (a >= 0.3))) + if((b >T(0.6)) || ((b >= T(0.45)) && (a >= T(0.3)))) { // DiDonato & Morris Eq 21: // @@ -130,7 +130,7 @@ T find_inverse_gamma(T a, T p, T q, const Policy& pol, bool* p_has_10_digits) // q. Fortunately the second form works perfectly well in this case. // T u; - if((b * q > 1e-8) && (q > 1e-5)) + if((b * q > T(1e-8)) && (q > T(1e-5))) { u = pow(p * g * a, 1 / a); BOOST_MATH_INSTRUMENT_VARIABLE(u); @@ -236,7 +236,7 @@ T find_inverse_gamma(T a, T p, T q, const Policy& pol, bool* p_has_10_digits) T D = (std::max)(T(2), T(a * (a - 1))); T lg = boost::math::lgamma(a, pol); T lb = log(q) + lg; - if(lb < -D * 2.3) + if(lb < -D * T(2.3)) { // DiDonato and Morris Eq 25: T y = -lb; @@ -293,7 +293,7 @@ T find_inverse_gamma(T a, T p, T q, const Policy& pol, bool* p_has_10_digits) if((z <= 0.01 * ap1) || (z > 0.7 * ap1)) { result = z; - if(z <= 0.002 * ap1) + if(z <= T(0.002) * ap1) *p_has_10_digits = true; BOOST_MATH_INSTRUMENT_VARIABLE(result); } @@ -326,7 +326,7 @@ struct gamma_p_inverse_func // be inaccurate anyway (because there's not enough information in p) // but at least we will converge on the (inaccurate) answer quickly. // - if(p > 0.9) + if(p > T(0.9)) { p = 1 - p; invert = !invert; @@ -437,7 +437,7 @@ T gamma_p_inv_imp(T a, T p, const Policy& pol) digits /= 2; digits -= 1; } - if((a < 0.125) && (fabs(gamma_p_derivative(a, guess, pol)) > 1 / sqrt(tools::epsilon()))) + if((a < T(0.125)) && (fabs(gamma_p_derivative(a, guess, pol)) > 1 / sqrt(tools::epsilon()))) digits = policies::digits() - 2; // // Go ahead and iterate: diff --git a/include/boost/math/special_functions/detail/lgamma_small.hpp b/include/boost/math/special_functions/detail/lgamma_small.hpp index 2d5a4b1017..6a4a9171fd 100644 --- a/include/boost/math/special_functions/detail/lgamma_small.hpp +++ b/include/boost/math/special_functions/detail/lgamma_small.hpp @@ -132,7 +132,7 @@ T lgamma_small_imp(T z, T zm1, T zm2, const std::integral_constant&, co // Two approximations, on for z in [1,1.5] and // one for z in [1.5,2]: // - if(z <= 1.5) + if(z <= T(1.5)) { // // Use the following form: diff --git a/include/boost/math/special_functions/detail/polygamma.hpp b/include/boost/math/special_functions/detail/polygamma.hpp index 3a7c984edc..8c11f40aed 100644 --- a/include/boost/math/special_functions/detail/polygamma.hpp +++ b/include/boost/math/special_functions/detail/polygamma.hpp @@ -53,7 +53,7 @@ namespace boost { namespace math { namespace detail{ if(n == 1) return 1 / x; T nlx = n * log(x); if((nlx < tools::log_max_value()) && (n < (int)max_factorial::value)) - return ((n & 1) ? 1 : -1) * boost::math::factorial(n - 1, pol) * pow(x, -n); + return ((n & 1) ? 1 : -1) * boost::math::factorial(n - 1, pol) * static_cast(pow(x, T(-n))); else return ((n & 1) ? 1 : -1) * exp(boost::math::lgamma(T(n), pol) - n * log(x)); } @@ -80,12 +80,12 @@ namespace boost { namespace math { namespace detail{ // know that we have to use logs for the initial terms: // part_term = ((n > (int)boost::math::max_factorial::value) && (T(n) * n > tools::log_max_value())) - ? T(0) : static_cast(boost::math::factorial(n - 1, pol) * pow(x, -n - 1)); + ? T(0) : static_cast(boost::math::factorial(n - 1, pol) * pow(x, T(-n - 1))); if(part_term == 0) { // Either n is very large, or the power term underflows, // set the initial values of part_term, term and sum via logs: - part_term = static_cast(boost::math::lgamma(n, pol) - (n + 1) * log(x)); + part_term = static_cast(T(boost::math::lgamma(n, pol)) - (n + 1) * log(x)); sum = exp(part_term + log(n + 2 * x) - boost::math::constants::ln_two()); part_term += log(T(n) * (n + 1)) - boost::math::constants::ln_two() - log(x); part_term = exp(part_term); @@ -159,7 +159,7 @@ namespace boost { namespace math { namespace detail{ { for(int k = 1; k <= iter; ++k) { - z_plus_k_pow_minus_m_minus_one = pow(z, minus_m_minus_one); + z_plus_k_pow_minus_m_minus_one = static_cast(pow(z, T(minus_m_minus_one))); sum0 += z_plus_k_pow_minus_m_minus_one; z += 1; } @@ -203,7 +203,7 @@ namespace boost { namespace math { namespace detail{ // be n! / z^(n+1), but since we're scaling by n! it's just // 1 / z^(n+1) for now: // - T prefix = pow(x, n + 1); + T prefix = static_cast(pow(x, T(n + 1))); // Warning supression: Integer power returns at least a double if(prefix == 0) return boost::math::policies::raise_overflow_error(function, nullptr, pol); prefix = 1 / prefix; diff --git a/include/boost/math/special_functions/digamma.hpp b/include/boost/math/special_functions/digamma.hpp index 92f916e113..86d5e2ffb9 100644 --- a/include/boost/math/special_functions/digamma.hpp +++ b/include/boost/math/special_functions/digamma.hpp @@ -379,7 +379,7 @@ inline T digamma_imp_1_2(T x, const std::integral_constant*) -0.61041765350579073e-1f }; static const T Q[] = { - 0.1e1, + 0.1e1f, 0.15890202430554952e1f, 0.65341249856146947e0f, 0.63851690523355715e-1f @@ -412,7 +412,7 @@ T digamma_imp(T x, const Tag* t, const Policy& pol) // Argument reduction for tan: T remainder = x - floor(x); // Shift to negative if > 0.5: - if(remainder > 0.5) + if(remainder > T(0.5)) { remainder -= 1; } @@ -478,7 +478,7 @@ T digamma_imp(T x, const std::integral_constant* t, const Policy& pol) // Argument reduction for tan: T remainder = x - floor(x); // Shift to negative if > 0.5: - if(remainder > 0.5) + if(remainder > T(0.5)) { remainder -= 1; } diff --git a/include/boost/math/special_functions/ellint_1.hpp b/include/boost/math/special_functions/ellint_1.hpp index a47ad76766..837963935c 100644 --- a/include/boost/math/special_functions/ellint_1.hpp +++ b/include/boost/math/special_functions/ellint_1.hpp @@ -98,7 +98,7 @@ T ellint_f_imp(T phi, T k, const Policy& pol) T m = boost::math::round((phi - rphi) / constants::half_pi()); BOOST_MATH_INSTRUMENT_VARIABLE(m); int s = 1; - if(boost::math::tools::fmod_workaround(m, T(2)) > 0.5) + if(boost::math::tools::fmod_workaround(m, T(2)) > T(0.5)) { m += 1; s = -1; @@ -202,20 +202,20 @@ BOOST_FORCEINLINE T ellint_k_imp(T k, const Policy& pol, std::integral_constant< { constexpr T coef[] = { - 1.591003453790792180, - 0.416000743991786912, - 0.245791514264103415, - 0.179481482914906162, - 0.144556057087555150, - 0.123200993312427711, - 0.108938811574293531, - 0.098853409871592910, - 0.091439629201749751, - 0.085842591595413900, - 0.081541118718303215, - 0.078199656811256481910 + static_cast(1.591003453790792180), + static_cast(0.416000743991786912), + static_cast(0.245791514264103415), + static_cast(0.179481482914906162), + static_cast(0.144556057087555150), + static_cast(0.123200993312427711), + static_cast(0.108938811574293531), + static_cast(0.098853409871592910), + static_cast(0.091439629201749751), + static_cast(0.085842591595413900), + static_cast(0.081541118718303215), + static_cast(0.078199656811256481910) }; - return boost::math::tools::evaluate_polynomial(coef, m - 0.05); + return boost::math::tools::evaluate_polynomial(coef, m - static_cast(0.05)); } case 2: case 3: @@ -223,20 +223,20 @@ BOOST_FORCEINLINE T ellint_k_imp(T k, const Policy& pol, std::integral_constant< { constexpr T coef[] = { - 1.635256732264579992, - 0.471190626148732291, - 0.309728410831499587, - 0.252208311773135699, - 0.226725623219684650, - 0.215774446729585976, - 0.213108771877348910, - 0.216029124605188282, - 0.223255831633057896, - 0.234180501294209925, - 0.248557682972264071, - 0.266363809892617521 + static_cast(1.635256732264579992), + static_cast(0.471190626148732291), + static_cast(0.309728410831499587), + static_cast(0.252208311773135699), + static_cast(0.226725623219684650), + static_cast(0.215774446729585976), + static_cast(0.213108771877348910), + static_cast(0.216029124605188282), + static_cast(0.223255831633057896), + static_cast(0.234180501294209925), + static_cast(0.248557682972264071), + static_cast(0.266363809892617521) }; - return boost::math::tools::evaluate_polynomial(coef, m - 0.15); + return boost::math::tools::evaluate_polynomial(coef, m - static_cast(0.15)); } case 4: case 5: @@ -244,20 +244,20 @@ BOOST_FORCEINLINE T ellint_k_imp(T k, const Policy& pol, std::integral_constant< { constexpr T coef[] = { - 1.685750354812596043, - 0.541731848613280329, - 0.401524438390690257, - 0.369642473420889090, - 0.376060715354583645, - 0.405235887085125919, - 0.453294381753999079, - 0.520518947651184205, - 0.609426039204995055, - 0.724263522282908870, - 0.871013847709812357, - 1.057652872753547036 + static_cast(1.685750354812596043), + static_cast(0.541731848613280329), + static_cast(0.401524438390690257), + static_cast(0.369642473420889090), + static_cast(0.376060715354583645), + static_cast(0.405235887085125919), + static_cast(0.453294381753999079), + static_cast(0.520518947651184205), + static_cast(0.609426039204995055), + static_cast(0.724263522282908870), + static_cast(0.871013847709812357), + static_cast(1.057652872753547036) }; - return boost::math::tools::evaluate_polynomial(coef, m - 0.25); + return boost::math::tools::evaluate_polynomial(coef, m - static_cast(0.25)); } case 6: case 7: @@ -265,21 +265,21 @@ BOOST_FORCEINLINE T ellint_k_imp(T k, const Policy& pol, std::integral_constant< { constexpr T coef[] = { - 1.744350597225613243, - 0.634864275371935304, - 0.539842564164445538, - 0.571892705193787391, - 0.670295136265406100, - 0.832586590010977199, - 1.073857448247933265, - 1.422091460675497751, - 1.920387183402304829, - 2.632552548331654201, - 3.652109747319039160, - 5.115867135558865806, - 7.224080007363877411 + static_cast(1.744350597225613243), + static_cast(0.634864275371935304), + static_cast(0.539842564164445538), + static_cast(0.571892705193787391), + static_cast(0.670295136265406100), + static_cast(0.832586590010977199), + static_cast(1.073857448247933265), + static_cast(1.422091460675497751), + static_cast(1.920387183402304829), + static_cast(2.632552548331654201), + static_cast(3.652109747319039160), + static_cast(5.115867135558865806), + static_cast(7.224080007363877411) }; - return boost::math::tools::evaluate_polynomial(coef, m - 0.35); + return boost::math::tools::evaluate_polynomial(coef, m - static_cast(0.35)); } case 8: case 9: @@ -287,22 +287,22 @@ BOOST_FORCEINLINE T ellint_k_imp(T k, const Policy& pol, std::integral_constant< { constexpr T coef[] = { - 1.813883936816982644, - 0.763163245700557246, - 0.761928605321595831, - 0.951074653668427927, - 1.315180671703161215, - 1.928560693477410941, - 2.937509342531378755, - 4.594894405442878062, - 7.330071221881720772, - 11.87151259742530180, - 19.45851374822937738, - 32.20638657246426863, - 53.73749198700554656, - 90.27388602940998849 + static_cast(1.813883936816982644), + static_cast(0.763163245700557246), + static_cast(0.761928605321595831), + static_cast(0.951074653668427927), + static_cast(1.315180671703161215), + static_cast(1.928560693477410941), + static_cast(2.937509342531378755), + static_cast(4.594894405442878062), + static_cast(7.330071221881720772), + static_cast(11.87151259742530180), + static_cast(19.45851374822937738), + static_cast(32.20638657246426863), + static_cast(53.73749198700554656), + static_cast(90.27388602940998849) }; - return boost::math::tools::evaluate_polynomial(coef, m - 0.45); + return boost::math::tools::evaluate_polynomial(coef, m - static_cast(0.45)); } case 10: case 11: @@ -310,23 +310,23 @@ BOOST_FORCEINLINE T ellint_k_imp(T k, const Policy& pol, std::integral_constant< { constexpr T coef[] = { - 1.898924910271553526, - 0.950521794618244435, - 1.151077589959015808, - 1.750239106986300540, - 2.952676812636875180, - 5.285800396121450889, - 9.832485716659979747, - 18.78714868327559562, - 36.61468615273698145, - 72.45292395127771801, - 145.1079577347069102, - 293.4786396308497026, - 598.3851815055010179, - 1228.420013075863451, - 2536.529755382764488 + static_cast(1.898924910271553526), + static_cast(0.950521794618244435), + static_cast(1.151077589959015808), + static_cast(1.750239106986300540), + static_cast(2.952676812636875180), + static_cast(5.285800396121450889), + static_cast(9.832485716659979747), + static_cast(18.78714868327559562), + static_cast(36.61468615273698145), + static_cast(72.45292395127771801), + static_cast(145.1079577347069102), + static_cast(293.4786396308497026), + static_cast(598.3851815055010179), + static_cast(1228.420013075863451), + static_cast(2536.529755382764488) }; - return boost::math::tools::evaluate_polynomial(coef, m - 0.55); + return boost::math::tools::evaluate_polynomial(coef, m - static_cast(0.55)); } case 12: case 13: @@ -334,106 +334,106 @@ BOOST_FORCEINLINE T ellint_k_imp(T k, const Policy& pol, std::integral_constant< { constexpr T coef[] = { - 2.007598398424376302, - 1.248457231212347337, - 1.926234657076479729, - 3.751289640087587680, - 8.119944554932045802, - 18.66572130873555361, - 44.60392484291437063, - 109.5092054309498377, - 274.2779548232413480, - 697.5598008606326163, - 1795.716014500247129, - 4668.381716790389910, - 12235.76246813664335, - 32290.17809718320818, - 85713.07608195964685, - 228672.1890493117096, - 612757.2711915852774 + static_cast(2.007598398424376302), + static_cast(1.248457231212347337), + static_cast(1.926234657076479729), + static_cast(3.751289640087587680), + static_cast(8.119944554932045802), + static_cast(18.66572130873555361), + static_cast(44.60392484291437063), + static_cast(109.5092054309498377), + static_cast(274.2779548232413480), + static_cast(697.5598008606326163), + static_cast(1795.716014500247129), + static_cast(4668.381716790389910), + static_cast(12235.76246813664335), + static_cast(32290.17809718320818), + static_cast(85713.07608195964685), + static_cast(228672.1890493117096), + static_cast(612757.2711915852774) }; - return boost::math::tools::evaluate_polynomial(coef, m - 0.65); + return boost::math::tools::evaluate_polynomial(coef, m - static_cast(0.65)); } case 14: case 15: - //else if (m < 0.8) + //else if (m < static_cast(0.8)) { constexpr T coef[] = { - 2.156515647499643235, - 1.791805641849463243, - 3.826751287465713147, - 10.38672468363797208, - 31.40331405468070290, - 100.9237039498695416, - 337.3268282632272897, - 1158.707930567827917, - 4060.990742193632092, - 14454.00184034344795, - 52076.66107599404803, - 189493.6591462156887, - 695184.5762413896145, - 2567994.048255284686, - 9541921.966748386322, - 35634927.44218076174, - 133669298.4612040871, - 503352186.6866284541, - 1901975729.538660119, - 7208915015.330103756 + static_cast(2.156515647499643235), + static_cast(1.791805641849463243), + static_cast(3.826751287465713147), + static_cast(10.38672468363797208), + static_cast(31.40331405468070290), + static_cast(100.9237039498695416), + static_cast(337.3268282632272897), + static_cast(1158.707930567827917), + static_cast(4060.990742193632092), + static_cast(14454.00184034344795), + static_cast(52076.66107599404803), + static_cast(189493.6591462156887), + static_cast(695184.5762413896145), + static_cast(2567994.048255284686), + static_cast(9541921.966748386322), + static_cast(35634927.44218076174), + static_cast(133669298.4612040871), + static_cast(503352186.6866284541), + static_cast(1901975729.538660119), + static_cast(7208915015.330103756) }; - return boost::math::tools::evaluate_polynomial(coef, m - 0.75); + return boost::math::tools::evaluate_polynomial(coef, m - static_cast(0.75)); } case 16: - //else if (m < 0.85) + //else if (m < static_cast(0.85)) { constexpr T coef[] = { - 2.318122621712510589, - 2.616920150291232841, - 7.897935075731355823, - 30.50239715446672327, - 131.4869365523528456, - 602.9847637356491617, - 2877.024617809972641, - 14110.51991915180325, - 70621.44088156540229, - 358977.2665825309926, - 1847238.263723971684, - 9600515.416049214109, - 50307677.08502366879, - 265444188.6527127967, - 1408862325.028702687, - 7515687935.373774627 + static_cast(2.318122621712510589), + static_cast(2.616920150291232841), + static_cast(7.897935075731355823), + static_cast(30.50239715446672327), + static_cast(131.4869365523528456), + static_cast(602.9847637356491617), + static_cast(2877.024617809972641), + static_cast(14110.51991915180325), + static_cast(70621.44088156540229), + static_cast(358977.2665825309926), + static_cast(1847238.263723971684), + static_cast(9600515.416049214109), + static_cast(50307677.08502366879), + static_cast(265444188.6527127967), + static_cast(1408862325.028702687), + static_cast(7515687935.373774627) }; - return boost::math::tools::evaluate_polynomial(coef, m - 0.825); + return boost::math::tools::evaluate_polynomial(coef, m - static_cast(0.825)); } case 17: - //else if (m < 0.90) + //else if (m < static_cast(0.90)) { constexpr T coef[] = { - 2.473596173751343912, - 3.727624244118099310, - 15.60739303554930496, - 84.12850842805887747, - 506.9818197040613935, - 3252.277058145123644, - 21713.24241957434256, - 149037.0451890932766, - 1043999.331089990839, - 7427974.817042038995, - 53503839.67558661151, - 389249886.9948708474, - 2855288351.100810619, - 21090077038.76684053, - 156699833947.7902014, - 1170222242422.439893, - 8777948323668.937971, - 66101242752484.95041, - 499488053713388.7989, - 37859743397240299.20 + static_cast(2.473596173751343912), + static_cast(3.727624244118099310), + static_cast(15.60739303554930496), + static_cast(84.12850842805887747), + static_cast(506.9818197040613935), + static_cast(3252.277058145123644), + static_cast(21713.24241957434256), + static_cast(149037.0451890932766), + static_cast(1043999.331089990839), + static_cast(7427974.817042038995), + static_cast(53503839.67558661151), + static_cast(389249886.9948708474), + static_cast(2855288351.100810619), + static_cast(21090077038.76684053), + static_cast(156699833947.7902014), + static_cast(1170222242422.439893), + static_cast(8777948323668.937971), + static_cast(66101242752484.95041), + static_cast(499488053713388.7989), + static_cast(37859743397240299.20) }; - return boost::math::tools::evaluate_polynomial(coef, m - 0.875); + return boost::math::tools::evaluate_polynomial(coef, m - static_cast(0.875)); } default: // diff --git a/include/boost/math/special_functions/ellint_2.hpp b/include/boost/math/special_functions/ellint_2.hpp index e135264ccf..81e82410b7 100644 --- a/include/boost/math/special_functions/ellint_2.hpp +++ b/include/boost/math/special_functions/ellint_2.hpp @@ -111,7 +111,7 @@ T ellint_e_imp(T phi, T k, const Policy& pol) T rphi = boost::math::tools::fmod_workaround(phi, T(constants::half_pi())); T m = boost::math::round((phi - rphi) / constants::half_pi()); int s = 1; - if(boost::math::tools::fmod_workaround(m, T(2)) > 0.5) + if(boost::math::tools::fmod_workaround(m, T(2)) > T(0.5)) { m += 1; s = -1; @@ -203,19 +203,19 @@ BOOST_FORCEINLINE T ellint_e_imp(T k, const Policy& pol, std::integral_constant< { constexpr T coef[] = { - 1.550973351780472328, - -0.400301020103198524, - -0.078498619442941939, - -0.034318853117591992, - -0.019718043317365499, - -0.013059507731993309, - -0.009442372874146547, - -0.007246728512402157, - -0.005807424012956090, - -0.004809187786009338, - -0.004086399233255150 + static_cast(1.550973351780472328), + -static_cast(0.400301020103198524), + -static_cast(0.078498619442941939), + -static_cast(0.034318853117591992), + -static_cast(0.019718043317365499), + -static_cast(0.013059507731993309), + -static_cast(0.009442372874146547), + -static_cast(0.007246728512402157), + -static_cast(0.005807424012956090), + -static_cast(0.004809187786009338), + -static_cast(0.004086399233255150) }; - return boost::math::tools::evaluate_polynomial(coef, m - 0.05); + return boost::math::tools::evaluate_polynomial(coef, m - static_cast(0.05)); } case 2: case 3: @@ -223,19 +223,19 @@ BOOST_FORCEINLINE T ellint_e_imp(T k, const Policy& pol, std::integral_constant< { constexpr T coef[] = { - 1.510121832092819728, - -0.417116333905867549, - -0.090123820404774569, - -0.043729944019084312, - -0.027965493064761785, - -0.020644781177568105, - -0.016650786739707238, - -0.014261960828842520, - -0.012759847429264803, - -0.011799303775587354, - -0.011197445703074968 + static_cast(1.510121832092819728), + -static_cast(0.417116333905867549), + -static_cast(0.090123820404774569), + -static_cast(0.043729944019084312), + -static_cast(0.027965493064761785), + -static_cast(0.020644781177568105), + -static_cast(0.016650786739707238), + -static_cast(0.014261960828842520), + -static_cast(0.012759847429264803), + -static_cast(0.011799303775587354), + -static_cast(0.011197445703074968) }; - return boost::math::tools::evaluate_polynomial(coef, m - 0.15); + return boost::math::tools::evaluate_polynomial(coef, m - static_cast(0.15)); } case 4: case 5: @@ -243,19 +243,19 @@ BOOST_FORCEINLINE T ellint_e_imp(T k, const Policy& pol, std::integral_constant< { constexpr T coef[] = { - 1.467462209339427155, - -0.436576290946337775, - -0.105155557666942554, - -0.057371843593241730, - -0.041391627727340220, - -0.034527728505280841, - -0.031495443512532783, - -0.030527000890325277, - -0.030916984019238900, - -0.032371395314758122, - -0.034789960386404158 + static_cast(1.467462209339427155), + -static_cast(0.436576290946337775), + -static_cast(0.105155557666942554), + -static_cast(0.057371843593241730), + -static_cast(0.041391627727340220), + -static_cast(0.034527728505280841), + -static_cast(0.031495443512532783), + -static_cast(0.030527000890325277), + -static_cast(0.030916984019238900), + -static_cast(0.032371395314758122), + -static_cast(0.034789960386404158) }; - return boost::math::tools::evaluate_polynomial(coef, m - 0.25); + return boost::math::tools::evaluate_polynomial(coef, m - static_cast(0.25)); } case 6: case 7: @@ -263,20 +263,20 @@ BOOST_FORCEINLINE T ellint_e_imp(T k, const Policy& pol, std::integral_constant< { constexpr T coef[] = { - 1.422691133490879171, - -0.459513519621048674, - -0.125250539822061878, - -0.078138545094409477, - -0.064714278472050002, - -0.062084339131730311, - -0.065197032815572477, - -0.072793895362578779, - -0.084959075171781003, - -0.102539850131045997, - -0.127053585157696036, - -0.160791120691274606 + static_cast(1.422691133490879171), + -static_cast(0.459513519621048674), + -static_cast(0.125250539822061878), + -static_cast(0.078138545094409477), + -static_cast(0.064714278472050002), + -static_cast(0.062084339131730311), + -static_cast(0.065197032815572477), + -static_cast(0.072793895362578779), + -static_cast(0.084959075171781003), + -static_cast(0.102539850131045997), + -static_cast(0.127053585157696036), + -static_cast(0.160791120691274606) }; - return boost::math::tools::evaluate_polynomial(coef, m - 0.35); + return boost::math::tools::evaluate_polynomial(coef, m - static_cast(0.35)); } case 8: case 9: @@ -284,21 +284,21 @@ BOOST_FORCEINLINE T ellint_e_imp(T k, const Policy& pol, std::integral_constant< { constexpr T coef[] = { - 1.375401971871116291, - -0.487202183273184837, - -0.153311701348540228, - -0.111849444917027833, - -0.108840952523135768, - -0.122954223120269076, - -0.152217163962035047, - -0.200495323642697339, - -0.276174333067751758, - -0.393513114304375851, - -0.575754406027879147, - -0.860523235727239756, - -1.308833205758540162 + static_cast(1.375401971871116291), + -static_cast(0.487202183273184837), + -static_cast(0.153311701348540228), + -static_cast(0.111849444917027833), + -static_cast(0.108840952523135768), + -static_cast(0.122954223120269076), + -static_cast(0.152217163962035047), + -static_cast(0.200495323642697339), + -static_cast(0.276174333067751758), + -static_cast(0.393513114304375851), + -static_cast(0.575754406027879147), + -static_cast(0.860523235727239756), + -static_cast(1.308833205758540162) }; - return boost::math::tools::evaluate_polynomial(coef, m - 0.45); + return boost::math::tools::evaluate_polynomial(coef, m - static_cast(0.45)); } case 10: case 11: @@ -306,21 +306,21 @@ BOOST_FORCEINLINE T ellint_e_imp(T k, const Policy& pol, std::integral_constant< { constexpr T coef[] = { - 1.325024497958230082, - -0.521727647557566767, - -0.194906430482126213, - -0.171623726822011264, - -0.202754652926419141, - -0.278798953118534762, - -0.420698457281005762, - -0.675948400853106021, - -1.136343121839229244, - -1.976721143954398261, - -3.531696773095722506, - -6.446753640156048150, - -11.97703130208884026 + static_cast(1.325024497958230082), + -static_cast(0.521727647557566767), + -static_cast(0.194906430482126213), + -static_cast(0.171623726822011264), + -static_cast(0.202754652926419141), + -static_cast(0.278798953118534762), + -static_cast(0.420698457281005762), + -static_cast(0.675948400853106021), + -static_cast(1.136343121839229244), + -static_cast(1.976721143954398261), + -static_cast(3.531696773095722506), + -static_cast(6.446753640156048150), + -static_cast(11.97703130208884026) }; - return boost::math::tools::evaluate_polynomial(coef, m - 0.55); + return boost::math::tools::evaluate_polynomial(coef, m - static_cast(0.55)); } case 12: case 13: @@ -328,23 +328,23 @@ BOOST_FORCEINLINE T ellint_e_imp(T k, const Policy& pol, std::integral_constant< { constexpr T coef[] = { - 1.270707479650149744, - -0.566839168287866583, - -0.262160793432492598, - -0.292244173533077419, - -0.440397840850423189, - -0.774947641381397458, - -1.498870837987561088, - -3.089708310445186667, - -6.667595903381001064, - -14.89436036517319078, - -34.18120574251449024, - -80.15895841905397306, - -191.3489480762984920, - -463.5938853480342030, - -1137.380822169360061 + static_cast(1.270707479650149744), + -static_cast(0.566839168287866583), + -static_cast(0.262160793432492598), + -static_cast(0.292244173533077419), + -static_cast(0.440397840850423189), + -static_cast(0.774947641381397458), + -static_cast(1.498870837987561088), + -static_cast(3.089708310445186667), + -static_cast(6.667595903381001064), + -static_cast(14.89436036517319078), + -static_cast(34.18120574251449024), + -static_cast(80.15895841905397306), + -static_cast(191.3489480762984920), + -static_cast(463.5938853480342030), + -static_cast(1137.380822169360061) }; - return boost::math::tools::evaluate_polynomial(coef, m - 0.65); + return boost::math::tools::evaluate_polynomial(coef, m - static_cast(0.65)); } case 14: case 15: @@ -352,72 +352,72 @@ BOOST_FORCEINLINE T ellint_e_imp(T k, const Policy& pol, std::integral_constant< { constexpr T coef[] = { - 1.211056027568459525, - -0.630306413287455807, - -0.387166409520669145, - -0.592278235311934603, - -1.237555584513049844, - -3.032056661745247199, - -8.181688221573590762, - -23.55507217389693250, - -71.04099935893064956, - -221.8796853192349888, - -712.1364793277635425, - -2336.125331440396407, - -7801.945954775964673, - -26448.19586059191933, - -90799.48341621365251, - -315126.0406449163424, - -1104011.344311591159 + static_cast(1.211056027568459525), + -static_cast(0.630306413287455807), + -static_cast(0.387166409520669145), + -static_cast(0.592278235311934603), + -static_cast(1.237555584513049844), + -static_cast(3.032056661745247199), + -static_cast(8.181688221573590762), + -static_cast(23.55507217389693250), + -static_cast(71.04099935893064956), + -static_cast(221.8796853192349888), + -static_cast(712.1364793277635425), + -static_cast(2336.125331440396407), + -static_cast(7801.945954775964673), + -static_cast(26448.19586059191933), + -static_cast(90799.48341621365251), + -static_cast(315126.0406449163424), + -static_cast(1104011.344311591159) }; - return boost::math::tools::evaluate_polynomial(coef, m - 0.75); + return boost::math::tools::evaluate_polynomial(coef, m - static_cast(0.75)); } case 16: //else if (m < 0.85) { constexpr T coef[] = { - 1.161307152196282836, - -0.701100284555289548, - -0.580551474465437362, - -1.243693061077786614, - -3.679383613496634879, - -12.81590924337895775, - -49.25672530759985272, - -202.1818735434090269, - -869.8602699308701437, - -3877.005847313289571, - -17761.70710170939814, - -83182.69029154232061, - -396650.4505013548170, - -1920033.413682634405 + static_cast(1.161307152196282836), + -static_cast(0.701100284555289548), + -static_cast(0.580551474465437362), + -static_cast(1.243693061077786614), + -static_cast(3.679383613496634879), + -static_cast(12.81590924337895775), + -static_cast(49.25672530759985272), + -static_cast(202.1818735434090269), + -static_cast(869.8602699308701437), + -static_cast(3877.005847313289571), + -static_cast(17761.70710170939814), + -static_cast(83182.69029154232061), + -static_cast(396650.4505013548170), + -static_cast(1920033.413682634405) }; - return boost::math::tools::evaluate_polynomial(coef, m - 0.825); + return boost::math::tools::evaluate_polynomial(coef, m - static_cast(0.825)); } case 17: //else if (m < 0.90) { constexpr T coef[] = { - 1.124617325119752213, - -0.770845056360909542, - -0.844794053644911362, - -2.490097309450394453, - -10.23971741154384360, - -49.74900546551479866, - -267.0986675195705196, - -1532.665883825229947, - -9222.313478526091951, - -57502.51612140314030, - -368596.1167416106063, - -2415611.088701091428, - -16120097.81581656797, - -109209938.5203089915, - -749380758.1942496220, - -5198725846.725541393, - -36409256888.12139973 + static_cast(1.124617325119752213), + -static_cast(0.770845056360909542), + -static_cast(0.844794053644911362), + -static_cast(2.490097309450394453), + -static_cast(10.23971741154384360), + -static_cast(49.74900546551479866), + -static_cast(267.0986675195705196), + -static_cast(1532.665883825229947), + -static_cast(9222.313478526091951), + -static_cast(57502.51612140314030), + -static_cast(368596.1167416106063), + -static_cast(2415611.088701091428), + -static_cast(16120097.81581656797), + -static_cast(109209938.5203089915), + -static_cast(749380758.1942496220), + -static_cast(5198725846.725541393), + -static_cast(36409256888.12139973) }; - return boost::math::tools::evaluate_polynomial(coef, m - 0.875); + return boost::math::tools::evaluate_polynomial(coef, m - static_cast(0.875)); } default: // diff --git a/include/boost/math/special_functions/ellint_3.hpp b/include/boost/math/special_functions/ellint_3.hpp index 5397f671cb..5c6c507b62 100644 --- a/include/boost/math/special_functions/ellint_3.hpp +++ b/include/boost/math/special_functions/ellint_3.hpp @@ -126,7 +126,7 @@ T ellint_pi_imp(T v, T phi, T k, T vc, const Policy& pol) { return policies::raise_domain_error(function, "Got k=1 and phi=%1% but the result is complex in that domain", phi, pol); } - if(boost::math::tools::fmod_workaround(m, T(2)) > 0.5) + if(boost::math::tools::fmod_workaround(m, T(2)) > T(0.5)) { m += 1; sign = -1; @@ -261,7 +261,7 @@ T ellint_pi_imp(T v, T phi, T k, T vc, const Policy& pol) t = sphi * sphi; y = 1 - k * k * t; z = 1; - if(v * t < 0.5) + if(v * t < T(0.5)) p = 1 - v * t; else p = x + vc * t; diff --git a/include/boost/math/special_functions/ellint_d.hpp b/include/boost/math/special_functions/ellint_d.hpp index d50029f5f4..67c3702c10 100644 --- a/include/boost/math/special_functions/ellint_d.hpp +++ b/include/boost/math/special_functions/ellint_d.hpp @@ -76,7 +76,7 @@ T ellint_d_imp(T phi, T k, const Policy& pol) T rphi = boost::math::tools::fmod_workaround(phi, T(constants::half_pi())); T m = boost::math::round((phi - rphi) / constants::half_pi()); int s = 1; - if(boost::math::tools::fmod_workaround(m, T(2)) > 0.5) + if(boost::math::tools::fmod_workaround(m, T(2)) > T(0.5)) { m += 1; s = -1; diff --git a/include/boost/math/special_functions/ellint_rc.hpp b/include/boost/math/special_functions/ellint_rc.hpp index 1fa7afc55c..c25f00cc59 100644 --- a/include/boost/math/special_functions/ellint_rc.hpp +++ b/include/boost/math/special_functions/ellint_rc.hpp @@ -74,7 +74,7 @@ T ellint_rc_imp(T x, T y, const Policy& pol) } else { - if(y / x > 0.5) + if(y / x > T(0.5)) { T arg = sqrt((x - y) / x); result = (boost::math::log1p(arg, pol) - boost::math::log1p(-arg, pol)) / (2 * sqrt(x - y)); diff --git a/include/boost/math/special_functions/ellint_rd.hpp b/include/boost/math/special_functions/ellint_rd.hpp index d7b9d22799..08cfecb040 100644 --- a/include/boost/math/special_functions/ellint_rd.hpp +++ b/include/boost/math/special_functions/ellint_rd.hpp @@ -74,14 +74,14 @@ T ellint_rd_imp(T x, T y, T z, const Policy& pol) } else { - if((std::min)(x, y) / (std::max)(x, y) > 1.3) + if((std::min)(x, y) / (std::max)(x, y) > T(1.3)) return 3 * (ellint_rc_imp(x, y, pol) - sqrt(x) / y) / (2 * (y - x)); // Otherwise fall through to avoid cancellation in the above (RC(x,y) -> 1/x^0.5 as x -> y) } } if(x == y) { - if((std::min)(x, z) / (std::max)(x, z) > 1.3) + if((std::min)(x, z) / (std::max)(x, z) > T(1.3)) return 3 * (ellint_rc_imp(z, x, pol) - 1 / sqrt(z)) / (z - x); // Otherwise fall through to avoid cancellation in the above (RC(x,y) -> 1/x^0.5 as x -> y) } @@ -100,7 +100,7 @@ T ellint_rd_imp(T x, T y, T z, const Policy& pol) T sum = 0; T sum_pow = 0.25f; - while(fabs(xn - yn) >= 2.7 * tools::root_epsilon() * fabs(xn)) + while(fabs(xn - yn) >= T(2.7) * tools::root_epsilon() * fabs(xn)) { T t = sqrt(xn * yn); xn = (xn + yn) / 2; diff --git a/include/boost/math/special_functions/ellint_rf.hpp b/include/boost/math/special_functions/ellint_rf.hpp index a8a7b4b217..5d5d73c258 100644 --- a/include/boost/math/special_functions/ellint_rf.hpp +++ b/include/boost/math/special_functions/ellint_rf.hpp @@ -97,7 +97,7 @@ namespace boost { namespace math { namespace detail{ T xn = sqrt(x); T yn = sqrt(y); - while(fabs(xn - yn) >= 2.7 * tools::root_epsilon() * fabs(xn)) + while(fabs(xn - yn) >= T(2.7) * tools::root_epsilon() * fabs(xn)) { T t = sqrt(xn * yn); xn = (xn + yn) / 2; diff --git a/include/boost/math/special_functions/ellint_rg.hpp b/include/boost/math/special_functions/ellint_rg.hpp index ddeb820586..96accdac02 100644 --- a/include/boost/math/special_functions/ellint_rg.hpp +++ b/include/boost/math/special_functions/ellint_rg.hpp @@ -92,7 +92,7 @@ namespace boost { namespace math { namespace detail{ T sum = 0; T sum_pow = 0.25f; - while(fabs(xn - yn) >= 2.7 * tools::root_epsilon() * fabs(xn)) + while(fabs(xn - yn) >= T(2.7) * tools::root_epsilon() * fabs(xn)) { T t = sqrt(xn * yn); xn = (xn + yn) / 2; diff --git a/include/boost/math/special_functions/ellint_rj.hpp b/include/boost/math/special_functions/ellint_rj.hpp index fdf1b3efc5..7142233219 100644 --- a/include/boost/math/special_functions/ellint_rj.hpp +++ b/include/boost/math/special_functions/ellint_rj.hpp @@ -62,7 +62,7 @@ T ellint_rc1p_imp(T y, const Policy& pol) } else { - if(y > -0.5) + if(y > T(-0.5)) { T arg = sqrt(-y); result = (boost::math::log1p(arg, pol) - boost::math::log1p(-arg, pol)) / (2 * sqrt(-y)); @@ -166,7 +166,7 @@ T ellint_rj_imp(T x, T y, T z, T p, const Policy& pol) { return ellint_rd_imp(x, y, y, pol); } - else if((std::max)(y, p) / (std::min)(y, p) > 1.2) + else if((std::max)(y, p) / (std::min)(y, p) > T(1.2)) { return 3 * (ellint_rc_imp(x, y, pol) - ellint_rc_imp(x, p, pol)) / (p - y); } @@ -180,7 +180,7 @@ T ellint_rj_imp(T x, T y, T z, T p, const Policy& pol) // y = z = p: return ellint_rd_imp(x, y, y, pol); } - else if((std::max)(y, p) / (std::min)(y, p) > 1.2) + else if((std::max)(y, p) / (std::min)(y, p) > T(1.2)) { // y = z: return 3 * (ellint_rc_imp(x, y, pol) - ellint_rc_imp(x, p, pol)) / (p - y); @@ -218,7 +218,7 @@ T ellint_rj_imp(T x, T y, T z, T p, const Policy& pol) Dn = (rp + rx) * (rp + ry) * (rp + rz); En = delta / Dn; En /= Dn; - if((En < -0.5) && (En > -1.5)) + if((En < T(-0.5)) && (En > T(-1.5))) { // // Occasionally En ~ -1, we then have no means of calculating diff --git a/include/boost/math/special_functions/erf.hpp b/include/boost/math/special_functions/erf.hpp index bcc53d1afc..5cc322ae4e 100644 --- a/include/boost/math/special_functions/erf.hpp +++ b/include/boost/math/special_functions/erf.hpp @@ -204,7 +204,7 @@ T erf_imp(T z, bool invert, const Policy& pol, const std::integral_constant& ta / tools::evaluate_polynomial(Q, t); t = (z - r1) - r2; result *= t; - if(fabs(t) < 0.1) + if(fabs(t) < T(0.1)) { result += boost::math::log1p(t / r, pol); } @@ -791,7 +791,7 @@ T expint_i_imp(T z, const Policy& pol, const std::integral_constant& ta / tools::evaluate_polynomial(Q, t); t = (z - r1) - r2; result *= t; - if(fabs(t) < 0.1) + if(fabs(t) < T(0.1)) { result += boost::math::log1p(t / r, pol); } diff --git a/include/boost/math/special_functions/factorials.hpp b/include/boost/math/special_functions/factorials.hpp index 02cca91a80..7229635cb9 100644 --- a/include/boost/math/special_functions/factorials.hpp +++ b/include/boost/math/special_functions/factorials.hpp @@ -145,13 +145,13 @@ T rising_factorial_imp(T x, int n, const Policy& pol) if(x == 0) { if(n < 0) - return -boost::math::tgamma_delta_ratio(x + 1, static_cast(-n), pol); + return static_cast(-boost::math::tgamma_delta_ratio(x + 1, static_cast(-n), pol)); else return 0; } if((x < 1) && (x + n < 0)) { - T val = boost::math::tgamma_delta_ratio(1 - x, static_cast(-n), pol); + const auto val = static_cast(boost::math::tgamma_delta_ratio(1 - x, static_cast(-n), pol)); return (n & 1) ? T(-val) : val; } // @@ -159,7 +159,7 @@ T rising_factorial_imp(T x, int n, const Policy& pol) // tgamma_delta_ratio is already optimised for that // use case: // - return 1 / boost::math::tgamma_delta_ratio(x, static_cast(n), pol); + return 1 / static_cast(boost::math::tgamma_delta_ratio(x, static_cast(n), pol)); } template @@ -206,7 +206,7 @@ inline T falling_factorial_imp(T x, unsigned n, const Policy& pol) unsigned n2 = itrunc((T)floor(xp1), pol); if(n2 == xp1) return 0; - T result = boost::math::tgamma_delta_ratio(xp1, -static_cast(n2), pol); + auto result = static_cast(boost::math::tgamma_delta_ratio(xp1, -static_cast(n2), pol)); x -= n2; result *= x; ++n2; @@ -221,7 +221,7 @@ inline T falling_factorial_imp(T x, unsigned n, const Policy& pol) // because tgamma_delta_ratio is already optimised // for that use case: // - return boost::math::tgamma_delta_ratio(x + 1, -static_cast(n), pol); + return static_cast(boost::math::tgamma_delta_ratio(x + 1, -static_cast(n), pol)); } } // namespace detail diff --git a/include/boost/math/special_functions/fourier_transform_daubechies.hpp b/include/boost/math/special_functions/fourier_transform_daubechies.hpp new file mode 100644 index 0000000000..982e740233 --- /dev/null +++ b/include/boost/math/special_functions/fourier_transform_daubechies.hpp @@ -0,0 +1,248 @@ +// boost-no-inspect +/* + * Copyright Nick Thompson, Matt Borland, 2023 + * Use, modification and distribution are subject to the + * Boost Software License, Version 1.0. (See accompanying file + * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ + +#ifndef BOOST_MATH_SPECIAL_FOURIER_TRANSFORM_DAUBECHIES_HPP +#define BOOST_MATH_SPECIAL_FOURIER_TRANSFORM_DAUBECHIES_HPP +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost::math { + +namespace detail { + +// See the Table 6.2 of Daubechies, Ten Lectures on Wavelets. +// These constants are precisely those divided by 1/sqrt(2), because otherwise +// we'd immediately just have to divide through by 1/sqrt(2). +// These numbers agree with Table 6.2, but are generated via example/calculate_fourier_transform_daubechies_constants.cpp +template constexpr std::array ft_daubechies_scaling_polynomial_coefficients() { + static_assert(N >= 1 && N <= 10, "Scaling function only implemented for 1-10 vanishing moments."); + if constexpr (N == 1) { + return std::array{static_cast(1)}; + } + if constexpr (N == 2) { + return {BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + 1.36602540378443864676372317075293618347140262690519031402790348972596650842632007803393058), + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + -0.366025403784438646763723170752936183471402626905190314027903489725966508441952115116994061)}; + } + if constexpr (N == 3) { + return std::array{ + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + 1.88186883113665472301331643028468183320710177910151845853383427363197699204347143889269703), + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + -1.08113883008418966599944677221635926685977756966260841342875242639629721931484516409937898), + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + 0.199269998947534942986130341931677433652675790561089954894918152764320227250084833874126086)}; + } + if constexpr (N == 4) { + return std::array{ + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + 2.60642742441038678619616138456320274846457112268350230103083547418823666924354637907021821), + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + -2.33814397690691624172277875654682595239896411009843420976312905955518655953831321619717516), + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + 0.851612467139421235087502761217605775743179492713667860409024360383174560120738199344383827), + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + -0.119895914642891779560885389233982571808786505298735951676730775016224669960397338539830347)}; + } + if constexpr (N == 5) { + return std::array{ + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + 3.62270372133693372237431371824382790538377237674943454540758419371854887218301659611796287), + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + -4.45042192340421529271926241961545172940077367856833333571968270791760393243895360839974479), + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + 2.41430351179889241160444590912469777504146155873489898274561148139247721271772284677196254), + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + -0.662064156756696785656360678859372223233256033099757083735935493062448802216759690564503751), + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + 0.0754788470250859443968634711062982722087957761837568913024225258690266500301041274151679859)}; + } + if constexpr (N == 6) { + return std::array{ + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + 5.04775782409284533508504459282823265081102702143912881539214595513121059428213452194161891), + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + -7.90242489414953082292172067801361411066690749603940036372954720647258482521355701761199), + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + 5.69062231972011992229557724635729642828799628244009852056657089766265949751788181912632318), + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + -2.29591465417352749013350971621495843275025605194376564457120763045109729714936982561585742), + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + 0.508712486289373262241383448555327418882885930043157873517278143590549199629822225076344289), + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + -0.0487530817792802065667748935122839545647456859392192011752401594607371693280512344274717466)}; + } + if constexpr (N == 7) { + return std::array{ + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + 7.0463635677199166580912954330590360004554457287730448872409828895500755049108034478397642), + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + -13.4339028220058085795120274851204982381087988043552711869584397724404274044947626280185946), + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + 12.0571882966390397563079887516068140052534768286900467252199152570563053103366694003818755), + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + -6.39124482303930285525880162640679389779540687632321120940980371544051534690730897661850842), + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + 2.07674879424918331569327229402057948161936796436510457676789758815816492768386639712643599), + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + -0.387167532162867697386347232520843525988806810788254462365009860280979111139408537312553398), + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + 0.0320145185998394020646198653617061745647219696385406695044576133973761206215673170563538)}; + } + if constexpr (N == 8) { + return std::array{ + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + 9.85031962984351656604584909868313752909650830419035084214249929687665775818153930511533915), + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + -22.1667494032601530437943449172929277733925779301673358406203340024653233856852379126537395), + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + 23.8272728452144265698978643079553442578633838793866258585693705776047828901217069807060715), + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + -15.6065825916019064469551268429136774427686552695820632173344334583910793479437661751737998), + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + 6.63923943761238270605338141020386331691362835005178161341935720370310013774320917891051914), + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + -1.81462830704498058848677549516134095104668450780318379608495409574150643627578462439190617), + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + 0.292393958692487086036895445298600849998803161432207979583488595754566344585039785927586499), + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + -0.0212655694557728487977430067729997866644059875083834396749941173411979591559303697954912042)}; + } + if constexpr (N == 9) { + return std::array{ + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + 13.7856894948673536752299497816200874595462540239049618127984616645562437295073582057283235), + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + -35.79362367743347676734569335180426263053917566987500206688713345532850076082533131311371), + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + 44.8271517576868325408174336351944130389504383168376658969692365144162452669941793147313), + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + -34.9081281226625998193992072777004811412863069972654446089639166067029872995118090115016879), + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + 18.2858070519930071738884732413420775324549836290768317032298177553411077249931094333824682), + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + -6.53714271572640296907117142447372145396492988681610221640307755553450246302777187366825001), + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + 1.5454286423270706293059630490222623728433659436325762803842722481655127844136128434034519), + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + -0.219427682644567750633335191213222483839627852234602683427115193605056655384931679751929029), + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + 0.0142452515927832872075875380128473058349984927391158822994546286919376896668596927857450578)}; + } + if constexpr (N == 10) { + return std::array{ + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + 19.3111846872275854185286532829110292444580572106276740012656292351880418629976266671349603), + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + -56.8572892818288577904562616825768121532988312416110097001327598719988644787442373891037268), + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + 81.3040184941182201969442916535886223134891624078921290339772790298979750863332417443823932), + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + -73.3067370305702272426402835488383512315892354877130132060680994033122368453226804355121917), + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + 45.5029913577892585869595005785056707790215969761054467083138479721524945862678794713356742), + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + -20.0048938122958245128650205249242185678760602333821352917865992073643758821417211689052482), + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + 6.18674372398711325312495154772282340531430890354257911422818567803548535981484584999007723), + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + -1.29022235346655645559407302793903682217361613280994725979138999393113139183198020070701239), + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + 0.16380852384056875506684562409582514726612462486206657238854671180228210790016298829595125), + BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits::digits, + -0.00960430880128020906860390254555211461150702751378997239464015046967050703218076318595987803)}; + } +} + +} // namespace detail + +/* + * Given ω∈ℝ, computes a numerical approximation to 𝓕[𝜙](ω), + * where 𝜙 is the Daubechies scaling function. + * Fast and accurate evaluation of these function seems to me to be a rather involved research project, + * which I have not endeavored to complete. + * In particular, recovering ~1ULP evaluation is not possible using the techniques + * employed here-you should use this with the understanding it is good enough for almost + * all uses with empirical data, but probably doesn't recover enough accuracy + * for pure mathematical uses (other than graphing-in which case it's fine). + * The implementation uses an infinite product of trigonometric polynomials. + * See Daubechies, 10 Lectures on Wavelets, equation 5.1.17, 5.1.18. + * It uses the factorization of m₀ shown in Corollary 5.5.4 and equation 5.5.5. + * See more discusion near equation 6.1.1, + * as well as efficiency gains from equation 7.1.4. + */ +template std::complex fourier_transform_daubechies_scaling(Real omega) { + // This arg promotion is kinda sad, but IMO the accuracy is not good enough in + // float precision using this method. Requesting a better algorithm! + if constexpr (std::is_same_v) { + return static_cast>(fourier_transform_daubechies_scaling(static_cast(omega))); + } + using boost::math::constants::one_div_root_two_pi; + using std::abs; + using std::exp; + using std::norm; + using std::pow; + using std::sqrt; + using std::cbrt; + // Equation 7.1.4 of 10 Lectures on Wavelets is singular at ω=0: + if (omega == 0) { + return std::complex(one_div_root_two_pi(), 0); + } + // For whatever reason, this starts returning NaNs rather than zero for |ω|≫1. + // But we know that this function decays rather quickly with |ω|, + // and hence it is "numerically zero", even if in actuality the function does not have compact support. + // Now, should we probably do a fairly involved, exhaustive calculation to see where exactly we should set this threshold + // and store them in a table? .... yes. + if (abs(omega) >= sqrt(std::numeric_limits::max())) { + return std::complex(0, 0); + } + auto const constexpr lxi = detail::ft_daubechies_scaling_polynomial_coefficients(); + auto xi = -omega / 2; + std::complex phi{one_div_root_two_pi(), 0}; + do { + std::complex arg{0, xi}; + auto z = exp(arg); + phi *= boost::math::tools::evaluate_polynomial_estrin(lxi, z); + xi /= 2; + } while (abs(xi) > std::numeric_limits::epsilon()); + std::complex arg{0, omega}; + // There is no std::expm1 for complex numbers. + // We may therefore be leaving accuracy gains on the table for small |ω|: + std::complex prefactor = (Real(1) - exp(-arg))/arg; + return phi * static_cast>(pow(prefactor, p)); +} + +template std::complex fourier_transform_daubechies_wavelet(Real omega) { + // See Daubechies, 10 Lectures on Wavelets, page 193, unlabelled equation in Theorem 6.3.6: + // 𝓕[ψ](ω) = -exp(-iω/2)m₀(ω/2 + π)^{*}𝓕[𝜙](ω/2) + if constexpr (std::is_same_v) { + return static_cast>(fourier_transform_daubechies_wavelet(static_cast(omega))); + } + + using std::exp; + using std::pow; + auto Fphi = fourier_transform_daubechies_scaling(omega/2); + auto phase = -exp(std::complex(0, -omega/2)); + // See Section 6.4 for the sign convention on the argument, + // as well as Table 6.2: + auto z = phase; // strange coincidence. + //auto z = exp(std::complex(0, -omega/2 - boost::math::constants::pi())); + auto constexpr lxi = detail::ft_daubechies_scaling_polynomial_coefficients(); + auto m0 = std::complex(pow((Real(1) + z)/Real(2), p))*boost::math::tools::evaluate_polynomial_estrin(lxi, z); + return Fphi*std::conj(m0)*phase; +} + +} // namespace boost::math +#endif diff --git a/include/boost/math/special_functions/gamma.hpp b/include/boost/math/special_functions/gamma.hpp index 68afe66e30..4af2ebdcfc 100644 --- a/include/boost/math/special_functions/gamma.hpp +++ b/include/boost/math/special_functions/gamma.hpp @@ -99,7 +99,7 @@ T sinpx(T z) dist = z - fl; } BOOST_MATH_ASSERT(fl >= 0); - if(dist > 0.5) + if(dist > T(0.5)) dist = 1 - dist; T result = sin(dist*boost::math::constants::pi()); return sign*z*result; @@ -175,7 +175,7 @@ T gamma_imp(T z, const Policy& pol, const Lanczos& l) BOOST_MATH_INSTRUMENT_VARIABLE(zgh); if(lzgh * z / 2 > tools::log_max_value()) return boost::math::sign(result) * policies::raise_overflow_error(function, "Result of tgamma is too large to represent.", pol); - T hp = pow(zgh, (z / 2) - T(0.25)); + T hp = pow(zgh, T((z / 2) - T(0.25))); BOOST_MATH_INSTRUMENT_VARIABLE(hp); result *= hp / exp(zgh); BOOST_MATH_INSTRUMENT_VARIABLE(result); @@ -187,9 +187,9 @@ T gamma_imp(T z, const Policy& pol, const Lanczos& l) else { BOOST_MATH_INSTRUMENT_VARIABLE(zgh); - BOOST_MATH_INSTRUMENT_VARIABLE(pow(zgh, z - boost::math::constants::half())); + BOOST_MATH_INSTRUMENT_VARIABLE(pow(zgh, T(z - boost::math::constants::half()))); BOOST_MATH_INSTRUMENT_VARIABLE(exp(zgh)); - result *= pow(zgh, z - boost::math::constants::half()) / exp(zgh); + result *= pow(zgh, T(z - boost::math::constants::half())) / exp(zgh); BOOST_MATH_INSTRUMENT_VARIABLE(result); } } @@ -264,7 +264,7 @@ T lgamma_imp(T z, const Policy& pol, const Lanczos& l, int* sign = nullptr) else { // regular evaluation: - T zgh = static_cast(z + Lanczos::g() - boost::math::constants::half()); + T zgh = static_cast(z + T(Lanczos::g()) - boost::math::constants::half()); result = log(zgh) - 1; result *= z - 0.5f; // @@ -735,7 +735,7 @@ T tgammap1m1_imp(T dz, Policy const& pol, const Lanczos& l) T result; if(dz < 0) { - if(dz < -0.5) + if(dz < T(-0.5)) { // Best method is simply to subtract 1 from tgamma: result = boost::math::tgamma(1+dz, pol) - 1; @@ -774,7 +774,7 @@ inline T tgammap1m1_imp(T z, Policy const& pol, { BOOST_MATH_STD_USING // ADL of std names - if(fabs(z) < 0.55) + if(fabs(z) < T(0.55)) { return boost::math::expm1(log_gamma_near_1(z, pol)); } @@ -826,7 +826,7 @@ T full_igamma_prefix(T a, T z, const Policy& pol) } else if(a >= 1) { - prefix = pow(z / exp(z/a), a); + prefix = pow(T(z / exp(z/a)), a); } else { @@ -841,7 +841,7 @@ T full_igamma_prefix(T a, T z, const Policy& pol) } else if(z/a < tools::log_max_value()) { - prefix = pow(z / exp(z/a), a); + prefix = pow(T(z / exp(z/a)), a); } else { @@ -927,7 +927,7 @@ T regularised_gamma_prefix(T a, T z, const Policy& pol, const Lanczos& l) } else if((amza > tools::log_min_value()) && (amza < tools::log_max_value())) { - prefix = pow((z * exp(amza)) / agh, a); + prefix = pow(T((z * exp(amza)) / agh), a); } else { @@ -936,7 +936,7 @@ T regularised_gamma_prefix(T a, T z, const Policy& pol, const Lanczos& l) } else { - prefix = pow(z / agh, a) * exp(amz); + prefix = pow(T(z / agh), a) * exp(amz); } } prefix *= sqrt(agh / boost::math::constants::e()) / Lanczos::lanczos_sum_expG_scaled(a); @@ -993,8 +993,8 @@ T regularised_gamma_prefix(T a, T z, const Policy& pol, const lanczos::undefined // as we go. And again recurse down to the result. // T scaled_gamma = scaled_tgamma_no_lanczos(T(a + shift), pol); - T power_term_1 = pow(z / (a + shift), a); - T power_term_2 = pow(a + shift, -shift); + T power_term_1 = pow(T(z / (a + shift)), a); + T power_term_2 = pow(T(a + shift), T(-shift)); T power_term_3 = exp(a + shift - z); if ((0 == power_term_1) || (0 == power_term_2) || (0 == power_term_3) || (fabs(a + shift - z) > tools::log_max_value())) { @@ -1258,12 +1258,12 @@ T gamma_incomplete_imp(T a, T x, bool normalised, bool invert, invert = !invert; eval_method = 7; } - else if(x < 0.5) + else if(x < T(0.5)) { // // Changeover criterion chosen to give a changeover at Q ~ 0.33 // - if(-0.4 / log(x) < a) + if(T(-0.4) / log(x) < a) { eval_method = 2; } @@ -1272,7 +1272,7 @@ T gamma_incomplete_imp(T a, T x, bool normalised, bool invert, eval_method = 3; } } - else if(x < 1.1) + else if(x < T(1.1)) { // // Changeover here occurs when P ~ 0.75 or Q ~ 0.25: @@ -1552,7 +1552,7 @@ T tgamma_delta_ratio_imp_lanczos(T z, T delta, const Policy& pol, const Lanczos& return 1 / (z * boost::math::tgamma(z + delta, pol)); } } - T zgh = static_cast(z + Lanczos::g() - constants::half()); + T zgh = static_cast(z + T(Lanczos::g()) - constants::half()); T result; if(z + delta == z) { @@ -1577,12 +1577,12 @@ T tgamma_delta_ratio_imp_lanczos(T z, T delta, const Policy& pol, const Lanczos& } else { - result = pow(zgh / (zgh + delta), z - constants::half()); + result = pow(T(zgh / (zgh + delta)), T(z - constants::half())); } // Split the calculation up to avoid spurious overflow: result *= Lanczos::lanczos_sum(z) / Lanczos::lanczos_sum(T(z + delta)); } - result *= pow(constants::e() / (zgh + delta), delta); + result *= pow(T(constants::e() / (zgh + delta)), delta); return result; } // @@ -1617,7 +1617,7 @@ T tgamma_delta_ratio_imp_lanczos(T z, T delta, const Policy& pol, const lanczos: T scaled_tgamma_num = scaled_tgamma_no_lanczos(z, pol); T scaled_tgamma_denom = scaled_tgamma_no_lanczos(T(z + delta), pol); T result = scaled_tgamma_num / scaled_tgamma_denom; - result *= exp(z * boost::math::log1p(-delta / (z + delta), pol)) * pow((delta + z) / constants::e(), -delta); + result *= exp(z * boost::math::log1p(-delta / (z + delta), pol)) * pow(T((delta + z) / constants::e()), -delta); return result; } // @@ -1917,11 +1917,11 @@ template const typename lgamma_initializer::init lgamma_initializer::initializer; template -inline typename tools::promote_args::type +inline tools::promote_args_t tgamma(T1 a, T2 z, const Policy&, const std::false_type) { BOOST_FPU_EXCEPTION_GUARD - typedef typename tools::promote_args::type result_type; + typedef tools::promote_args_t result_type; typedef typename policies::evaluation::type value_type; // typedef typename lanczos::lanczos::type evaluation_type; typedef typename policies::normalise< @@ -1940,7 +1940,7 @@ inline typename tools::promote_args::type } template -inline typename tools::promote_args::type +inline tools::promote_args_t tgamma(T1 a, T2 z, const std::false_type& tag) { return tgamma(a, z, policies::policy<>(), tag); @@ -2026,31 +2026,33 @@ inline typename tools::promote_args::type // Full upper incomplete gamma: // template -inline typename tools::promote_args::type +inline tools::promote_args_t tgamma(T1 a, T2 z) { // // Type T2 could be a policy object, or a value, select the // right overload based on T2: // - typedef typename policies::is_policy::type maybe_policy; - return detail::tgamma(a, z, maybe_policy()); + using maybe_policy = typename policies::is_policy::type; + using result_type = tools::promote_args_t; + return static_cast(detail::tgamma(a, z, maybe_policy())); } template -inline typename tools::promote_args::type +inline tools::promote_args_t tgamma(T1 a, T2 z, const Policy& pol) { - return detail::tgamma(a, z, pol, std::false_type()); + using result_type = tools::promote_args_t; + return static_cast(detail::tgamma(a, z, pol, std::false_type())); } // // Full lower incomplete gamma: // template -inline typename tools::promote_args::type +inline tools::promote_args_t tgamma_lower(T1 a, T2 z, const Policy&) { BOOST_FPU_EXCEPTION_GUARD - typedef typename tools::promote_args::type result_type; + typedef tools::promote_args_t result_type; typedef typename policies::evaluation::type value_type; // typedef typename lanczos::lanczos::type evaluation_type; typedef typename policies::normalise< @@ -2068,7 +2070,7 @@ inline typename tools::promote_args::type forwarding_policy(), static_cast(nullptr)), "tgamma_lower<%1%>(%1%, %1%)"); } template -inline typename tools::promote_args::type +inline tools::promote_args_t tgamma_lower(T1 a, T2 z) { return tgamma_lower(a, z, policies::policy<>()); @@ -2077,11 +2079,11 @@ inline typename tools::promote_args::type // Regularised upper incomplete gamma: // template -inline typename tools::promote_args::type +inline tools::promote_args_t gamma_q(T1 a, T2 z, const Policy& /* pol */) { BOOST_FPU_EXCEPTION_GUARD - typedef typename tools::promote_args::type result_type; + typedef tools::promote_args_t result_type; typedef typename policies::evaluation::type value_type; // typedef typename lanczos::lanczos::type evaluation_type; typedef typename policies::normalise< @@ -2099,7 +2101,7 @@ inline typename tools::promote_args::type forwarding_policy(), static_cast(nullptr)), "gamma_q<%1%>(%1%, %1%)"); } template -inline typename tools::promote_args::type +inline tools::promote_args_t gamma_q(T1 a, T2 z) { return gamma_q(a, z, policies::policy<>()); @@ -2108,11 +2110,11 @@ inline typename tools::promote_args::type // Regularised lower incomplete gamma: // template -inline typename tools::promote_args::type +inline tools::promote_args_t gamma_p(T1 a, T2 z, const Policy&) { BOOST_FPU_EXCEPTION_GUARD - typedef typename tools::promote_args::type result_type; + typedef tools::promote_args_t result_type; typedef typename policies::evaluation::type value_type; // typedef typename lanczos::lanczos::type evaluation_type; typedef typename policies::normalise< @@ -2130,7 +2132,7 @@ inline typename tools::promote_args::type forwarding_policy(), static_cast(nullptr)), "gamma_p<%1%>(%1%, %1%)"); } template -inline typename tools::promote_args::type +inline tools::promote_args_t gamma_p(T1 a, T2 z) { return gamma_p(a, z, policies::policy<>()); @@ -2138,11 +2140,11 @@ inline typename tools::promote_args::type // ratios of gamma functions: template -inline typename tools::promote_args::type +inline tools::promote_args_t tgamma_delta_ratio(T1 z, T2 delta, const Policy& /* pol */) { BOOST_FPU_EXCEPTION_GUARD - typedef typename tools::promote_args::type result_type; + typedef tools::promote_args_t result_type; typedef typename policies::evaluation::type value_type; typedef typename policies::normalise< Policy, @@ -2154,16 +2156,16 @@ inline typename tools::promote_args::type return policies::checked_narrowing_cast(detail::tgamma_delta_ratio_imp(static_cast(z), static_cast(delta), forwarding_policy()), "boost::math::tgamma_delta_ratio<%1%>(%1%, %1%)"); } template -inline typename tools::promote_args::type +inline tools::promote_args_t tgamma_delta_ratio(T1 z, T2 delta) { return tgamma_delta_ratio(z, delta, policies::policy<>()); } template -inline typename tools::promote_args::type +inline tools::promote_args_t tgamma_ratio(T1 a, T2 b, const Policy&) { - typedef typename tools::promote_args::type result_type; + typedef tools::promote_args_t result_type; typedef typename policies::evaluation::type value_type; typedef typename policies::normalise< Policy, @@ -2175,18 +2177,18 @@ inline typename tools::promote_args::type return policies::checked_narrowing_cast(detail::tgamma_ratio_imp(static_cast(a), static_cast(b), forwarding_policy()), "boost::math::tgamma_delta_ratio<%1%>(%1%, %1%)"); } template -inline typename tools::promote_args::type +inline tools::promote_args_t tgamma_ratio(T1 a, T2 b) { return tgamma_ratio(a, b, policies::policy<>()); } template -inline typename tools::promote_args::type +inline tools::promote_args_t gamma_p_derivative(T1 a, T2 x, const Policy&) { BOOST_FPU_EXCEPTION_GUARD - typedef typename tools::promote_args::type result_type; + typedef tools::promote_args_t result_type; typedef typename policies::evaluation::type value_type; typedef typename policies::normalise< Policy, @@ -2198,7 +2200,7 @@ inline typename tools::promote_args::type return policies::checked_narrowing_cast(detail::gamma_p_derivative_imp(static_cast(a), static_cast(x), forwarding_policy()), "boost::math::gamma_p_derivative<%1%>(%1%, %1%)"); } template -inline typename tools::promote_args::type +inline tools::promote_args_t gamma_p_derivative(T1 a, T2 x) { return gamma_p_derivative(a, x, policies::policy<>()); diff --git a/include/boost/math/special_functions/hermite.hpp b/include/boost/math/special_functions/hermite.hpp index dcc352f55f..81ccb2ac66 100644 --- a/include/boost/math/special_functions/hermite.hpp +++ b/include/boost/math/special_functions/hermite.hpp @@ -23,7 +23,8 @@ template inline typename tools::promote_args::type hermite_next(unsigned n, T1 x, T2 Hn, T3 Hnm1) { - return (2 * x * Hn - 2 * n * Hnm1); + using promoted_type = tools::promote_args_t; + return (2 * promoted_type(x) * promoted_type(Hn) - 2 * n * promoted_type(Hnm1)); } namespace detail{ @@ -43,7 +44,7 @@ T hermite_imp(unsigned n, T x) while(c < n) { std::swap(p0, p1); - p1 = hermite_next(c, x, p0, p1); + p1 = static_cast(hermite_next(c, x, p0, p1)); ++c; } return p1; diff --git a/include/boost/math/special_functions/hypergeometric_2F0.hpp b/include/boost/math/special_functions/hypergeometric_2F0.hpp index a8ebe2162e..d22e6a029d 100644 --- a/include/boost/math/special_functions/hypergeometric_2F0.hpp +++ b/include/boost/math/special_functions/hypergeometric_2F0.hpp @@ -94,7 +94,7 @@ namespace boost { namespace math { namespace detail { // http://functions.wolfram.com/07.31.03.0083.01 int n = static_cast(static_cast(boost::math::lltrunc(-2 * a1))); T smz = sqrt(-z); - return pow(2 / smz, -n) * boost::math::hermite(n, 1 / smz, pol); + return static_cast(pow(2 / smz, T(-n)) * boost::math::hermite(n, 1 / smz, pol)); // Warning suppression: integer power returns at least a double } if (is_a1_integer && is_a2_integer) diff --git a/include/boost/math/special_functions/jacobi_elliptic.hpp b/include/boost/math/special_functions/jacobi_elliptic.hpp index 88d8b9dac2..114b991d9c 100644 --- a/include/boost/math/special_functions/jacobi_elliptic.hpp +++ b/include/boost/math/special_functions/jacobi_elliptic.hpp @@ -107,7 +107,7 @@ T jacobi_imp(const T& x, const T& k, T* cn, T* dn, const Policy& pol, const char }*/ T T1; T kc = 1 - k; - T k_prime = k < 0.5 ? T(sqrt(1 - k * k)) : T(sqrt(2 * kc - kc * kc)); + T k_prime = k < T(0.5) ? T(sqrt(1 - k * k)) : T(sqrt(2 * kc - kc * kc)); T T0 = jacobi_recurse(x, k, T(1), k_prime, 0, &T1, pol); *cn = cos(T0); *dn = cos(T0) / cos(T1 - T0); diff --git a/include/boost/math/special_functions/laguerre.hpp b/include/boost/math/special_functions/laguerre.hpp index cd9aa31c46..d747274536 100644 --- a/include/boost/math/special_functions/laguerre.hpp +++ b/include/boost/math/special_functions/laguerre.hpp @@ -105,7 +105,7 @@ T laguerre_imp(unsigned n, unsigned m, T x, const Policy& pol) while(c < n) { std::swap(p0, p1); - p1 = laguerre_next(c, m, x, p0, p1); + p1 = static_cast(laguerre_next(c, m, x, p0, p1)); ++c; } return p1; diff --git a/include/boost/math/special_functions/lambert_w.hpp b/include/boost/math/special_functions/lambert_w.hpp index 9bc5bb29fa..c57ce1d5bd 100644 --- a/include/boost/math/special_functions/lambert_w.hpp +++ b/include/boost/math/special_functions/lambert_w.hpp @@ -48,6 +48,7 @@ BOOST_MATH_INSTRUMENT_LAMBERT_W_SMALL_Z_SERIES_ITERATIONS // Show evaluation of //] [/boost_math_instrument_lambert_w_macros] */ +#include #include #include #include @@ -184,7 +185,25 @@ template inline double must_reduce_to_double(const T& z, const std::false_type&) { // try a lexical_cast and hope for the best: #ifndef BOOST_MATH_STANDALONE + + #ifdef BOOST_MATH_USE_CHARCONV_FOR_CONVERSION + + // Catches the C++23 floating point types + if constexpr (std::is_arithmetic_v) + { + return static_cast(z); + } + else + { + return boost::lexical_cast(z); + } + + #else + return boost::lexical_cast(z); + + #endif + #else static_assert(sizeof(T) == 0, "Unsupported in standalone mode: don't know how to cast your number type to a double."); return 0.0; @@ -379,7 +398,7 @@ T lambert_w_singularity_series(const T p) } #endif // BOOST_MATH_INSTRUMENT_LAMBERT_W_TERMS - if (absp < 0.01159) + if (absp < T(0.01159)) { // Only 6 near-singularity series terms are useful. return -1 + @@ -391,7 +410,7 @@ T lambert_w_singularity_series(const T p) p * q[6] ))))); } - else if (absp < 0.0766) // Use 10 near-singularity series terms. + else if (absp < T(0.0766)) // Use 10 near-singularity series terms. { // Use 10 near-singularity series terms. return -1 + @@ -407,8 +426,7 @@ T lambert_w_singularity_series(const T p) p * q[10] ))))))))); } - else - { // Use all 20 near-singularity series terms. + // Use all 20 near-singularity series terms. return -1 + p * (1 + @@ -440,7 +458,7 @@ T lambert_w_singularity_series(const T p) // p*q[24] + // p*q[25] // ))))))))))))))))))); - } + } // template T lambert_w_singularity_series(const T p) @@ -817,7 +835,7 @@ struct lambert_w0_small_z_series_term ++k; term *= -z / k; //T t = pow(z, k) * pow(T(k), -1 + k) / factorial(k); // (z^k * k(k-1)^k) / k! - T result = term * pow(T(k), -1 + k); // term * k^(k-1) + T result = term * pow(T(k), T(-1 + k)); // term * k^(k-1) // std::cout << " k = " << k << ", term = " << term << ", result = " << result << std::endl; return result; // } @@ -1025,7 +1043,7 @@ T lambert_w_positive_rational_float(T z) BOOST_MATH_STD_USING if (z < 2) { - if (z < 0.5) + if (z < T(0.5)) { // 0.05 < z < 0.5 // Maximum Deviation Found: 2.993e-08 // Expected Error Term : 2.993e-08 @@ -1101,7 +1119,7 @@ T lambert_w_positive_rational_float(T z) }; return Y + boost::math::tools::evaluate_rational(P, Q, z); } - else if (z < 9897.12905874) // 2.8 < log(z) < 9.2 + else if (z < T(9897.12905874)) // 2.8 < log(z) < 9.2 { // Max error in interpolated form: 1.771e-08 static const T Y = -1.402973175e+00f; @@ -1121,7 +1139,7 @@ T lambert_w_positive_rational_float(T z) T log_w = log(z); return log_w + Y + boost::math::tools::evaluate_polynomial(P, log_w) / boost::math::tools::evaluate_polynomial(Q, log_w); } - else if (z < 7.896296e+13) // 9.2 < log(z) <= 32 + else if (z < T(7.896296e+13)) // 9.2 < log(z) <= 32 { // Max error in interpolated form: 5.821e-08 static const T Y = -2.735729218e+00f; @@ -1141,35 +1159,34 @@ T lambert_w_positive_rational_float(T z) T log_w = log(z); return log_w + Y + boost::math::tools::evaluate_polynomial(P, log_w) / boost::math::tools::evaluate_polynomial(Q, log_w); } - else // 32 < log(z) < 100 - { - // Max error in interpolated form: 1.491e-08 - static const T Y = -4.012863159e+00f; - static const T P[] = { - 4.431629226e+00f, - 2.756690487e-01f, - -2.992956930e-03f, - -4.912259384e-05f, - }; - static const T Q[] = { - 1.000000000e+00f, - 2.015434591e-01f, - 4.949426142e-03f, - 1.609659944e-05f, - -5.111523436e-09f, - }; - T log_w = log(z); - return log_w + Y + boost::math::tools::evaluate_polynomial(P, log_w) / boost::math::tools::evaluate_polynomial(Q, log_w); - } + + // Max error in interpolated form: 1.491e-08 + static const T Y = -4.012863159e+00f; + static const T P[] = { + 4.431629226e+00f, + 2.756690487e-01f, + -2.992956930e-03f, + -4.912259384e-05f, + }; + static const T Q[] = { + 1.000000000e+00f, + 2.015434591e-01f, + 4.949426142e-03f, + 1.609659944e-05f, + -5.111523436e-09f, + }; + T log_w = log(z); + return log_w + Y + boost::math::tools::evaluate_polynomial(P, log_w) / boost::math::tools::evaluate_polynomial(Q, log_w); + } template T lambert_w_negative_rational_float(T z, const Policy& pol) { BOOST_MATH_STD_USING - if (z > -0.27) + if (z > T(-0.27)) { - if (z < -0.051) + if (z < T(-0.051)) { // -0.27 < z < -0.051 // Max error in interpolated form: 5.080e-08 @@ -1194,7 +1211,7 @@ T lambert_w_negative_rational_float(T z, const Policy& pol) return lambert_w0_small_z(z, pol); } } - else if (z > -0.3578794411714423215955237701) + else if (z > T(-0.3578794411714423215955237701)) { // Very close to branch singularity. // Max error in interpolated form: 5.269e-08 static const T Y = 1.220928431e-01f; @@ -1214,11 +1231,8 @@ T lambert_w_negative_rational_float(T z, const Policy& pol) T d = z + 0.367879441171442321595523770161460867445811f; return -d / (Y + boost::math::tools::evaluate_polynomial(P, d) / boost::math::tools::evaluate_polynomial(Q, d)); } - else - { - // z is very close (within 0.01) of the singularity at e^-1. - return lambert_w_singularity_series(get_near_singularity_param(z, pol)); - } + + return lambert_w_singularity_series(get_near_singularity_param(z, pol)); } //! Lambert_w0 @b 'float' implementation, selected when T is 32-bit precision. @@ -1237,7 +1251,7 @@ inline T lambert_w0_imp(T z, const Policy& pol, const std::integral_constant(function, "Expected a finite value but got %1%.", z, pol); } - if (z >= 0.05) // Fukushima switch point. + if (z >= T(0.05)) // Fukushima switch point. // if (z >= 0.045) // 34 terms makes 128-bit 'exact' below 0.045. { // Normal ranges using several rational polynomials. return lambert_w_positive_rational_float(z); @@ -1248,10 +1262,8 @@ inline T lambert_w0_imp(T z, const Policy& pol, const std::integral_constant(function, "Expected z >= -e^-1 (-0.367879...) but got %1%.", z, pol); return -1; } - else // z < 0.05 - { - return lambert_w_negative_rational_float(z, pol); - } + + return lambert_w_negative_rational_float(z, pol); } // T lambert_w0_imp(T z, const Policy& pol, const std::integral_constant&) for 32-bit usually float. template @@ -1855,7 +1867,7 @@ T lambert_wm1_imp(const T z, const Policy& pol) // Check that z argument value is not smaller than lookup_table G[64] // std::cout << "(z > wm1zs[63]) = " << std::boolalpha << (z > wm1zs[63]) << std::endl; - if (z >= wm1zs[63]) // wm1zs[63] = -1.0264389699511282259046957018510946438e-26L W = 64.00000000000000000 + if (z >= T(wm1zs[63])) // wm1zs[63] = -1.0264389699511282259046957018510946438e-26L W = 64.00000000000000000 { // z >= -1.0264389699511303e-26 (but z != 0 and z >= std::numeric_limits::min() and so NOT denormalized). // Some info on Lambert W-1 values for extreme values of z. @@ -1940,14 +1952,14 @@ T lambert_wm1_imp(const T z, const Policy& pol) // Bracketing sequence n = (2, 4, 8, 16, 32, 64) for W-1 branch. (0 is -infinity) // Since z is probably quite small, start with lowest n (=2). int n = 2; - if (wm1zs[n - 1] > z) + if (T(wm1zs[n - 1]) > z) { goto bisect; } for (int j = 1; j <= 5; ++j) { n *= 2; - if (wm1zs[n - 1] > z) + if (T(wm1zs[n - 1]) > z) { goto overshot; } @@ -1967,7 +1979,7 @@ T lambert_wm1_imp(const T z, const Policy& pol) { break; // goto bisect; } - if (wm1zs[n - nh - 1] > z) + if (T(wm1zs[n - nh - 1]) > z) { n -= nh; } @@ -2011,7 +2023,7 @@ T lambert_wm1_imp(const T z, const Policy& pol) using calc_type = typename std::conditional::value, lookup_t, T>::type; calc_type w = -static_cast(n); // Equation 25, - calc_type y = static_cast(z * wm1es[n - 1]); // Equation 26, + calc_type y = static_cast(z * T(wm1es[n - 1])); // Equation 26, // Perform the bisections fractional bisections for necessary precision. for (int j = 0; j < bisections; ++j) { // Equation 27. diff --git a/include/boost/math/special_functions/legendre.hpp b/include/boost/math/special_functions/legendre.hpp index e8e90f580b..6af798e0d9 100644 --- a/include/boost/math/special_functions/legendre.hpp +++ b/include/boost/math/special_functions/legendre.hpp @@ -66,7 +66,7 @@ T legendre_imp(unsigned l, T x, const Policy& pol, bool second = false) while(n < l) { std::swap(p0, p1); - p1 = boost::math::legendre_next(n, x, p0, p1); + p1 = static_cast(boost::math::legendre_next(n, x, p0, p1)); ++n; } return p1; @@ -115,7 +115,7 @@ T legendre_p_prime_imp(unsigned l, T x, const Policy& pol, T* Pn while(n < l - 1) { std::swap(p0, p1); - p1 = boost::math::legendre_next(n, x, p0, p1); + p1 = static_cast(boost::math::legendre_next(n, x, p0, p1)); ++n; if (odd) { @@ -131,7 +131,7 @@ T legendre_p_prime_imp(unsigned l, T x, const Policy& pol, T* Pn if (Pn) { std::swap(p0, p1); - *Pn = boost::math::legendre_next(n, x, p0, p1); + *Pn = static_cast(boost::math::legendre_next(n, x, p0, p1)); } return p_prime; } @@ -322,7 +322,7 @@ T legendre_p_imp(int l, int m, T x, T sin_theta_power, const Policy& pol) } if (-m == l) { - return pow((1 - x * x) / 4, T(l) / 2) / boost::math::tgamma(l + 1, pol); + return pow((1 - x * x) / 4, T(l) / 2) / boost::math::tgamma(l + 1, pol); } if(m < 0) { diff --git a/include/boost/math/special_functions/log1p.hpp b/include/boost/math/special_functions/log1p.hpp index 8121a573cd..9b8a8e0eb7 100644 --- a/include/boost/math/special_functions/log1p.hpp +++ b/include/boost/math/special_functions/log1p.hpp @@ -136,24 +136,24 @@ T log1p_imp(T const& x, const Policy& pol, const std::integral_constant // Maximum Relative Change in Control Points: 8.138e-004 // Max Error found at double precision = 3.250766e-016 static const T P[] = { - 0.15141069795941984e-16L, - 0.35495104378055055e-15L, - 0.33333333333332835L, - 0.99249063543365859L, - 1.1143969784156509L, - 0.58052937949269651L, - 0.13703234928513215L, - 0.011294864812099712L + static_cast(0.15141069795941984e-16L), + static_cast(0.35495104378055055e-15L), + static_cast(0.33333333333332835L), + static_cast(0.99249063543365859L), + static_cast(1.1143969784156509L), + static_cast(0.58052937949269651L), + static_cast(0.13703234928513215L), + static_cast(0.011294864812099712L) }; static const T Q[] = { - 1L, - 3.7274719063011499L, - 5.5387948649720334L, - 4.159201143419005L, - 1.6423855110312755L, - 0.31706251443180914L, - 0.022665554431410243L, - -0.29252538135177773e-5L + static_cast(1L), + static_cast(3.7274719063011499L), + static_cast(5.5387948649720334L), + static_cast(4.159201143419005L), + static_cast(1.6423855110312755L), + static_cast(0.31706251443180914L), + static_cast(0.022665554431410243L), + static_cast(-0.29252538135177773e-5L) }; T result = 1 - x / 2 + tools::evaluate_polynomial(P, x) / tools::evaluate_polynomial(Q, x); diff --git a/include/boost/math/special_functions/math_fwd.hpp b/include/boost/math/special_functions/math_fwd.hpp index 6f9d739e1e..7b99651402 100644 --- a/include/boost/math/special_functions/math_fwd.hpp +++ b/include/boost/math/special_functions/math_fwd.hpp @@ -39,111 +39,111 @@ namespace boost // Beta functions. template - typename tools::promote_args::type + tools::promote_args_t beta(RT1 a, RT2 b); // Beta function (2 arguments). template - typename tools::promote_args::type + tools::promote_args_t beta(RT1 a, RT2 b, A x); // Beta function (3 arguments). template - typename tools::promote_args::type + tools::promote_args_t beta(RT1 a, RT2 b, RT3 x, const Policy& pol); // Beta function (3 arguments). template - typename tools::promote_args::type + tools::promote_args_t betac(RT1 a, RT2 b, RT3 x); template - typename tools::promote_args::type + tools::promote_args_t betac(RT1 a, RT2 b, RT3 x, const Policy& pol); template - typename tools::promote_args::type + tools::promote_args_t ibeta(RT1 a, RT2 b, RT3 x); // Incomplete beta function. template - typename tools::promote_args::type + tools::promote_args_t ibeta(RT1 a, RT2 b, RT3 x, const Policy& pol); // Incomplete beta function. template - typename tools::promote_args::type + tools::promote_args_t ibetac(RT1 a, RT2 b, RT3 x); // Incomplete beta complement function. template - typename tools::promote_args::type + tools::promote_args_t ibetac(RT1 a, RT2 b, RT3 x, const Policy& pol); // Incomplete beta complement function. template - typename tools::promote_args::type + tools::promote_args_t ibeta_inv(T1 a, T2 b, T3 p, T4* py); template - typename tools::promote_args::type + tools::promote_args_t ibeta_inv(T1 a, T2 b, T3 p, T4* py, const Policy& pol); template - typename tools::promote_args::type + tools::promote_args_t ibeta_inv(RT1 a, RT2 b, RT3 p); // Incomplete beta inverse function. template - typename tools::promote_args::type + tools::promote_args_t ibeta_inv(RT1 a, RT2 b, RT3 p, const Policy&); // Incomplete beta inverse function. template - typename tools::promote_args::type + tools::promote_args_t ibeta_inva(RT1 a, RT2 b, RT3 p); // Incomplete beta inverse function. template - typename tools::promote_args::type + tools::promote_args_t ibeta_inva(RT1 a, RT2 b, RT3 p, const Policy&); // Incomplete beta inverse function. template - typename tools::promote_args::type + tools::promote_args_t ibeta_invb(RT1 a, RT2 b, RT3 p); // Incomplete beta inverse function. template - typename tools::promote_args::type + tools::promote_args_t ibeta_invb(RT1 a, RT2 b, RT3 p, const Policy&); // Incomplete beta inverse function. template - typename tools::promote_args::type + tools::promote_args_t ibetac_inv(T1 a, T2 b, T3 q, T4* py); template - typename tools::promote_args::type + tools::promote_args_t ibetac_inv(T1 a, T2 b, T3 q, T4* py, const Policy& pol); template - typename tools::promote_args::type + tools::promote_args_t ibetac_inv(RT1 a, RT2 b, RT3 q); // Incomplete beta complement inverse function. template - typename tools::promote_args::type + tools::promote_args_t ibetac_inv(RT1 a, RT2 b, RT3 q, const Policy&); // Incomplete beta complement inverse function. template - typename tools::promote_args::type + tools::promote_args_t ibetac_inva(RT1 a, RT2 b, RT3 q); // Incomplete beta complement inverse function. template - typename tools::promote_args::type + tools::promote_args_t ibetac_inva(RT1 a, RT2 b, RT3 q, const Policy&); // Incomplete beta complement inverse function. template - typename tools::promote_args::type + tools::promote_args_t ibetac_invb(RT1 a, RT2 b, RT3 q); // Incomplete beta complement inverse function. template - typename tools::promote_args::type + tools::promote_args_t ibetac_invb(RT1 a, RT2 b, RT3 q, const Policy&); // Incomplete beta complement inverse function. template - typename tools::promote_args::type + tools::promote_args_t ibeta_derivative(RT1 a, RT2 b, RT3 x); // derivative of incomplete beta template - typename tools::promote_args::type + tools::promote_args_t ibeta_derivative(RT1 a, RT2 b, RT3 x, const Policy& pol); // derivative of incomplete beta // Binomial: @@ -154,35 +154,35 @@ namespace boost // erf & erfc error functions. template // Error function. - typename tools::promote_args::type erf(RT z); + tools::promote_args_t erf(RT z); template // Error function. - typename tools::promote_args::type erf(RT z, const Policy&); + tools::promote_args_t erf(RT z, const Policy&); template // Error function complement. - typename tools::promote_args::type erfc(RT z); + tools::promote_args_t erfc(RT z); template // Error function complement. - typename tools::promote_args::type erfc(RT z, const Policy&); + tools::promote_args_t erfc(RT z, const Policy&); template // Error function inverse. - typename tools::promote_args::type erf_inv(RT z); + tools::promote_args_t erf_inv(RT z); template // Error function inverse. - typename tools::promote_args::type erf_inv(RT z, const Policy& pol); + tools::promote_args_t erf_inv(RT z, const Policy& pol); template // Error function complement inverse. - typename tools::promote_args::type erfc_inv(RT z); + tools::promote_args_t erfc_inv(RT z); template // Error function complement inverse. - typename tools::promote_args::type erfc_inv(RT z, const Policy& pol); + tools::promote_args_t erfc_inv(RT z, const Policy& pol); // Polynomials: template - typename tools::promote_args::type + tools::promote_args_t legendre_next(unsigned l, T1 x, T2 Pl, T3 Plm1); template - typename tools::promote_args::type + tools::promote_args_t legendre_p(int l, T x); template - typename tools::promote_args::type + tools::promote_args_t legendre_p_prime(int l, T x); @@ -193,46 +193,46 @@ namespace boost inline std::vector legendre_p_zeros(int l); template - typename std::enable_if::value, typename tools::promote_args::type>::type + typename std::enable_if::value, tools::promote_args_t>::type legendre_p(int l, T x, const Policy& pol); template - inline typename std::enable_if::value, typename tools::promote_args::type>::type + inline typename std::enable_if::value, tools::promote_args_t>::type legendre_p_prime(int l, T x, const Policy& pol); template - typename tools::promote_args::type + tools::promote_args_t legendre_q(unsigned l, T x); template - typename std::enable_if::value, typename tools::promote_args::type>::type + typename std::enable_if::value, tools::promote_args_t>::type legendre_q(unsigned l, T x, const Policy& pol); template - typename tools::promote_args::type + tools::promote_args_t legendre_next(unsigned l, unsigned m, T1 x, T2 Pl, T3 Plm1); template - typename tools::promote_args::type + tools::promote_args_t legendre_p(int l, int m, T x); template - typename tools::promote_args::type + tools::promote_args_t legendre_p(int l, int m, T x, const Policy& pol); template - typename tools::promote_args::type + tools::promote_args_t laguerre_next(unsigned n, T1 x, T2 Ln, T3 Lnm1); template - typename tools::promote_args::type + tools::promote_args_t laguerre_next(unsigned n, unsigned l, T1 x, T2 Pl, T3 Plm1); template - typename tools::promote_args::type + tools::promote_args_t laguerre(unsigned n, T x); template - typename tools::promote_args::type + tools::promote_args_t laguerre(unsigned n, unsigned m, T x, const Policy& pol); template @@ -250,144 +250,144 @@ namespace boost laguerre(unsigned n, T1 m, T2 x); template - typename tools::promote_args::type + tools::promote_args_t hermite(unsigned n, T x); template - typename tools::promote_args::type + tools::promote_args_t hermite(unsigned n, T x, const Policy& pol); template - typename tools::promote_args::type + tools::promote_args_t hermite_next(unsigned n, T1 x, T2 Hn, T3 Hnm1); template - typename tools::promote_args::type chebyshev_next(T1 const & x, T2 const & Tn, T3 const & Tn_1); + tools::promote_args_t chebyshev_next(T1 const & x, T2 const & Tn, T3 const & Tn_1); template - typename tools::promote_args::type + tools::promote_args_t chebyshev_t(unsigned n, Real const & x, const Policy&); template - typename tools::promote_args::type chebyshev_t(unsigned n, Real const & x); + tools::promote_args_t chebyshev_t(unsigned n, Real const & x); template - typename tools::promote_args::type + tools::promote_args_t chebyshev_u(unsigned n, Real const & x, const Policy&); template - typename tools::promote_args::type chebyshev_u(unsigned n, Real const & x); + tools::promote_args_t chebyshev_u(unsigned n, Real const & x); template - typename tools::promote_args::type + tools::promote_args_t chebyshev_t_prime(unsigned n, Real const & x, const Policy&); template - typename tools::promote_args::type chebyshev_t_prime(unsigned n, Real const & x); + tools::promote_args_t chebyshev_t_prime(unsigned n, Real const & x); template Real chebyshev_clenshaw_recurrence(const Real* const c, size_t length, const T2& x); template - std::complex::type> + std::complex> spherical_harmonic(unsigned n, int m, T1 theta, T2 phi); template - std::complex::type> + std::complex> spherical_harmonic(unsigned n, int m, T1 theta, T2 phi, const Policy& pol); template - typename tools::promote_args::type + tools::promote_args_t spherical_harmonic_r(unsigned n, int m, T1 theta, T2 phi); template - typename tools::promote_args::type + tools::promote_args_t spherical_harmonic_r(unsigned n, int m, T1 theta, T2 phi, const Policy& pol); template - typename tools::promote_args::type + tools::promote_args_t spherical_harmonic_i(unsigned n, int m, T1 theta, T2 phi); template - typename tools::promote_args::type + tools::promote_args_t spherical_harmonic_i(unsigned n, int m, T1 theta, T2 phi, const Policy& pol); // Elliptic integrals: template - typename tools::promote_args::type + tools::promote_args_t ellint_rf(T1 x, T2 y, T3 z); template - typename tools::promote_args::type + tools::promote_args_t ellint_rf(T1 x, T2 y, T3 z, const Policy& pol); template - typename tools::promote_args::type + tools::promote_args_t ellint_rd(T1 x, T2 y, T3 z); template - typename tools::promote_args::type + tools::promote_args_t ellint_rd(T1 x, T2 y, T3 z, const Policy& pol); template - typename tools::promote_args::type + tools::promote_args_t ellint_rc(T1 x, T2 y); template - typename tools::promote_args::type + tools::promote_args_t ellint_rc(T1 x, T2 y, const Policy& pol); template - typename tools::promote_args::type + tools::promote_args_t ellint_rj(T1 x, T2 y, T3 z, T4 p); template - typename tools::promote_args::type + tools::promote_args_t ellint_rj(T1 x, T2 y, T3 z, T4 p, const Policy& pol); template - typename tools::promote_args::type + tools::promote_args_t ellint_rg(T1 x, T2 y, T3 z); template - typename tools::promote_args::type + tools::promote_args_t ellint_rg(T1 x, T2 y, T3 z, const Policy& pol); template - typename tools::promote_args::type ellint_2(T k); + tools::promote_args_t ellint_2(T k); template - typename tools::promote_args::type ellint_2(T1 k, T2 phi); + tools::promote_args_t ellint_2(T1 k, T2 phi); template - typename tools::promote_args::type ellint_2(T1 k, T2 phi, const Policy& pol); + tools::promote_args_t ellint_2(T1 k, T2 phi, const Policy& pol); template - typename tools::promote_args::type ellint_1(T k); + tools::promote_args_t ellint_1(T k); template - typename tools::promote_args::type ellint_1(T1 k, T2 phi); + tools::promote_args_t ellint_1(T1 k, T2 phi); template - typename tools::promote_args::type ellint_1(T1 k, T2 phi, const Policy& pol); + tools::promote_args_t ellint_1(T1 k, T2 phi, const Policy& pol); template - typename tools::promote_args::type ellint_d(T k); + tools::promote_args_t ellint_d(T k); template - typename tools::promote_args::type ellint_d(T1 k, T2 phi); + tools::promote_args_t ellint_d(T1 k, T2 phi); template - typename tools::promote_args::type ellint_d(T1 k, T2 phi, const Policy& pol); + tools::promote_args_t ellint_d(T1 k, T2 phi, const Policy& pol); template - typename tools::promote_args::type jacobi_zeta(T1 k, T2 phi); + tools::promote_args_t jacobi_zeta(T1 k, T2 phi); template - typename tools::promote_args::type jacobi_zeta(T1 k, T2 phi, const Policy& pol); + tools::promote_args_t jacobi_zeta(T1 k, T2 phi, const Policy& pol); template - typename tools::promote_args::type heuman_lambda(T1 k, T2 phi); + tools::promote_args_t heuman_lambda(T1 k, T2 phi); template - typename tools::promote_args::type heuman_lambda(T1 k, T2 phi, const Policy& pol); + tools::promote_args_t heuman_lambda(T1 k, T2 phi, const Policy& pol); namespace detail{ @@ -396,8 +396,8 @@ namespace boost { using type = typename std::conditional< policies::is_policy::value, - typename tools::promote_args::type, - typename tools::promote_args::type + tools::promote_args_t, + tools::promote_args_t >::type; }; @@ -408,10 +408,10 @@ namespace boost typename detail::ellint_3_result::type ellint_3(T1 k, T2 v, T3 phi); template - typename tools::promote_args::type ellint_3(T1 k, T2 v, T3 phi, const Policy& pol); + tools::promote_args_t ellint_3(T1 k, T2 v, T3 phi, const Policy& pol); template - typename tools::promote_args::type ellint_3(T1 k, T2 v); + tools::promote_args_t ellint_3(T1 k, T2 v); // Factorial functions. // Note: not for integral types, at present. @@ -429,211 +429,211 @@ namespace boost RT double_factorial(unsigned i, const Policy& pol); template - typename tools::promote_args::type falling_factorial(RT x, unsigned n); + tools::promote_args_t falling_factorial(RT x, unsigned n); template - typename tools::promote_args::type falling_factorial(RT x, unsigned n, const Policy& pol); + tools::promote_args_t falling_factorial(RT x, unsigned n, const Policy& pol); template - typename tools::promote_args::type rising_factorial(RT x, int n); + tools::promote_args_t rising_factorial(RT x, int n); template - typename tools::promote_args::type rising_factorial(RT x, int n, const Policy& pol); + tools::promote_args_t rising_factorial(RT x, int n, const Policy& pol); // Gamma functions. template - typename tools::promote_args::type tgamma(RT z); + tools::promote_args_t tgamma(RT z); template - typename tools::promote_args::type tgamma1pm1(RT z); + tools::promote_args_t tgamma1pm1(RT z); template - typename tools::promote_args::type tgamma1pm1(RT z, const Policy& pol); + tools::promote_args_t tgamma1pm1(RT z, const Policy& pol); template - typename tools::promote_args::type tgamma(RT1 a, RT2 z); + tools::promote_args_t tgamma(RT1 a, RT2 z); template - typename tools::promote_args::type tgamma(RT1 a, RT2 z, const Policy& pol); + tools::promote_args_t tgamma(RT1 a, RT2 z, const Policy& pol); template - typename tools::promote_args::type lgamma(RT z, int* sign); + tools::promote_args_t lgamma(RT z, int* sign); template - typename tools::promote_args::type lgamma(RT z, int* sign, const Policy& pol); + tools::promote_args_t lgamma(RT z, int* sign, const Policy& pol); template - typename tools::promote_args::type lgamma(RT x); + tools::promote_args_t lgamma(RT x); template - typename tools::promote_args::type lgamma(RT x, const Policy& pol); + tools::promote_args_t lgamma(RT x, const Policy& pol); template - typename tools::promote_args::type tgamma_lower(RT1 a, RT2 z); + tools::promote_args_t tgamma_lower(RT1 a, RT2 z); template - typename tools::promote_args::type tgamma_lower(RT1 a, RT2 z, const Policy&); + tools::promote_args_t tgamma_lower(RT1 a, RT2 z, const Policy&); template - typename tools::promote_args::type gamma_q(RT1 a, RT2 z); + tools::promote_args_t gamma_q(RT1 a, RT2 z); template - typename tools::promote_args::type gamma_q(RT1 a, RT2 z, const Policy&); + tools::promote_args_t gamma_q(RT1 a, RT2 z, const Policy&); template - typename tools::promote_args::type gamma_p(RT1 a, RT2 z); + tools::promote_args_t gamma_p(RT1 a, RT2 z); template - typename tools::promote_args::type gamma_p(RT1 a, RT2 z, const Policy&); + tools::promote_args_t gamma_p(RT1 a, RT2 z, const Policy&); template - typename tools::promote_args::type tgamma_delta_ratio(T1 z, T2 delta); + tools::promote_args_t tgamma_delta_ratio(T1 z, T2 delta); template - typename tools::promote_args::type tgamma_delta_ratio(T1 z, T2 delta, const Policy&); + tools::promote_args_t tgamma_delta_ratio(T1 z, T2 delta, const Policy&); template - typename tools::promote_args::type tgamma_ratio(T1 a, T2 b); + tools::promote_args_t tgamma_ratio(T1 a, T2 b); template - typename tools::promote_args::type tgamma_ratio(T1 a, T2 b, const Policy&); + tools::promote_args_t tgamma_ratio(T1 a, T2 b, const Policy&); template - typename tools::promote_args::type gamma_p_derivative(T1 a, T2 x); + tools::promote_args_t gamma_p_derivative(T1 a, T2 x); template - typename tools::promote_args::type gamma_p_derivative(T1 a, T2 x, const Policy&); + tools::promote_args_t gamma_p_derivative(T1 a, T2 x, const Policy&); // gamma inverse. template - typename tools::promote_args::type gamma_p_inv(T1 a, T2 p); + tools::promote_args_t gamma_p_inv(T1 a, T2 p); template - typename tools::promote_args::type gamma_p_inva(T1 a, T2 p, const Policy&); + tools::promote_args_t gamma_p_inva(T1 a, T2 p, const Policy&); template - typename tools::promote_args::type gamma_p_inva(T1 a, T2 p); + tools::promote_args_t gamma_p_inva(T1 a, T2 p); template - typename tools::promote_args::type gamma_p_inv(T1 a, T2 p, const Policy&); + tools::promote_args_t gamma_p_inv(T1 a, T2 p, const Policy&); template - typename tools::promote_args::type gamma_q_inv(T1 a, T2 q); + tools::promote_args_t gamma_q_inv(T1 a, T2 q); template - typename tools::promote_args::type gamma_q_inv(T1 a, T2 q, const Policy&); + tools::promote_args_t gamma_q_inv(T1 a, T2 q, const Policy&); template - typename tools::promote_args::type gamma_q_inva(T1 a, T2 q); + tools::promote_args_t gamma_q_inva(T1 a, T2 q); template - typename tools::promote_args::type gamma_q_inva(T1 a, T2 q, const Policy&); + tools::promote_args_t gamma_q_inva(T1 a, T2 q, const Policy&); // digamma: template - typename tools::promote_args::type digamma(T x); + tools::promote_args_t digamma(T x); template - typename tools::promote_args::type digamma(T x, const Policy&); + tools::promote_args_t digamma(T x, const Policy&); // trigamma: template - typename tools::promote_args::type trigamma(T x); + tools::promote_args_t trigamma(T x); template - typename tools::promote_args::type trigamma(T x, const Policy&); + tools::promote_args_t trigamma(T x, const Policy&); // polygamma: template - typename tools::promote_args::type polygamma(int n, T x); + tools::promote_args_t polygamma(int n, T x); template - typename tools::promote_args::type polygamma(int n, T x, const Policy&); + tools::promote_args_t polygamma(int n, T x, const Policy&); // Hypotenuse function sqrt(x ^ 2 + y ^ 2). template - typename tools::promote_args::type + tools::promote_args_t hypot(T1 x, T2 y); template - typename tools::promote_args::type + tools::promote_args_t hypot(T1 x, T2 y, const Policy&); // cbrt - cube root. template - typename tools::promote_args::type cbrt(RT z); + tools::promote_args_t cbrt(RT z); template - typename tools::promote_args::type cbrt(RT z, const Policy&); + tools::promote_args_t cbrt(RT z, const Policy&); // log1p is log(x + 1) template - typename tools::promote_args::type log1p(T); + tools::promote_args_t log1p(T); template - typename tools::promote_args::type log1p(T, const Policy&); + tools::promote_args_t log1p(T, const Policy&); // log1pmx is log(x + 1) - x template - typename tools::promote_args::type log1pmx(T); + tools::promote_args_t log1pmx(T); template - typename tools::promote_args::type log1pmx(T, const Policy&); + tools::promote_args_t log1pmx(T, const Policy&); // Exp (x) minus 1 functions. template - typename tools::promote_args::type expm1(T); + tools::promote_args_t expm1(T); template - typename tools::promote_args::type expm1(T, const Policy&); + tools::promote_args_t expm1(T, const Policy&); // Power - 1 template - typename tools::promote_args::type + tools::promote_args_t powm1(const T1 a, const T2 z); template - typename tools::promote_args::type + tools::promote_args_t powm1(const T1 a, const T2 z, const Policy&); // sqrt(1+x) - 1 template - typename tools::promote_args::type sqrt1pm1(const T& val); + tools::promote_args_t sqrt1pm1(const T& val); template - typename tools::promote_args::type sqrt1pm1(const T& val, const Policy&); + tools::promote_args_t sqrt1pm1(const T& val, const Policy&); // sinus cardinals: template - typename tools::promote_args::type sinc_pi(T x); + tools::promote_args_t sinc_pi(T x); template - typename tools::promote_args::type sinc_pi(T x, const Policy&); + tools::promote_args_t sinc_pi(T x, const Policy&); template - typename tools::promote_args::type sinhc_pi(T x); + tools::promote_args_t sinhc_pi(T x); template - typename tools::promote_args::type sinhc_pi(T x, const Policy&); + tools::promote_args_t sinhc_pi(T x, const Policy&); // inverse hyperbolics: template - typename tools::promote_args::type asinh(T x); + tools::promote_args_t asinh(T x); template - typename tools::promote_args::type asinh(T x, const Policy&); + tools::promote_args_t asinh(T x, const Policy&); template - typename tools::promote_args::type acosh(T x); + tools::promote_args_t acosh(T x); template - typename tools::promote_args::type acosh(T x, const Policy&); + tools::promote_args_t acosh(T x, const Policy&); template - typename tools::promote_args::type atanh(T x); + tools::promote_args_t atanh(T x); template - typename tools::promote_args::type atanh(T x, const Policy&); + tools::promote_args_t atanh(T x, const Policy&); namespace detail{ @@ -647,7 +647,7 @@ namespace boost using result_type = typename std::conditional< std::is_integral::value, typename tools::promote_args::type, - typename tools::promote_args::type + tools::promote_args_t >::type; typedef typename policies::precision::type precision_type; @@ -798,28 +798,28 @@ namespace boost std::complex >::result_type> sph_hankel_2(T1 v, T2 x); template - typename tools::promote_args::type airy_ai(T x, const Policy&); + tools::promote_args_t airy_ai(T x, const Policy&); template - typename tools::promote_args::type airy_ai(T x); + tools::promote_args_t airy_ai(T x); template - typename tools::promote_args::type airy_bi(T x, const Policy&); + tools::promote_args_t airy_bi(T x, const Policy&); template - typename tools::promote_args::type airy_bi(T x); + tools::promote_args_t airy_bi(T x); template - typename tools::promote_args::type airy_ai_prime(T x, const Policy&); + tools::promote_args_t airy_ai_prime(T x, const Policy&); template - typename tools::promote_args::type airy_ai_prime(T x); + tools::promote_args_t airy_ai_prime(T x); template - typename tools::promote_args::type airy_bi_prime(T x, const Policy&); + tools::promote_args_t airy_bi_prime(T x, const Policy&); template - typename tools::promote_args::type airy_bi_prime(T x); + tools::promote_args_t airy_bi_prime(T x); template T airy_ai_zero(int m); @@ -856,16 +856,16 @@ namespace boost const Policy&); template - typename tools::promote_args::type sin_pi(T x, const Policy&); + tools::promote_args_t sin_pi(T x, const Policy&); template - typename tools::promote_args::type sin_pi(T x); + tools::promote_args_t sin_pi(T x); template - typename tools::promote_args::type cos_pi(T x, const Policy&); + tools::promote_args_t cos_pi(T x, const Policy&); template - typename tools::promote_args::type cos_pi(T x); + tools::promote_args_t cos_pi(T x); template int fpclassify BOOST_NO_MACRO_EXPAND(T t); @@ -902,7 +902,7 @@ namespace boost { typedef typename std::conditional< policies::is_policy::value, - typename tools::promote_args::type, + tools::promote_args_t, typename tools::promote_args::type >::type type; }; @@ -910,219 +910,219 @@ namespace boost } // namespace detail template - typename tools::promote_args::type expint(unsigned n, T z, const Policy&); + tools::promote_args_t expint(unsigned n, T z, const Policy&); template typename detail::expint_result::type expint(T const z, U const u); template - typename tools::promote_args::type expint(T z); + tools::promote_args_t expint(T z); // Zeta: template - typename tools::promote_args::type zeta(T s, const Policy&); + tools::promote_args_t zeta(T s, const Policy&); // Owen's T function: template - typename tools::promote_args::type owens_t(T1 h, T2 a, const Policy& pol); + tools::promote_args_t owens_t(T1 h, T2 a, const Policy& pol); template - typename tools::promote_args::type owens_t(T1 h, T2 a); + tools::promote_args_t owens_t(T1 h, T2 a); // Jacobi Functions: template - typename tools::promote_args::type jacobi_elliptic(T k, U theta, V* pcn, V* pdn, const Policy&); + tools::promote_args_t jacobi_elliptic(T k, U theta, V* pcn, V* pdn, const Policy&); template - typename tools::promote_args::type jacobi_elliptic(T k, U theta, V* pcn = 0, V* pdn = 0); + tools::promote_args_t jacobi_elliptic(T k, U theta, V* pcn = 0, V* pdn = 0); template - typename tools::promote_args::type jacobi_sn(U k, T theta, const Policy& pol); + tools::promote_args_t jacobi_sn(U k, T theta, const Policy& pol); template - typename tools::promote_args::type jacobi_sn(U k, T theta); + tools::promote_args_t jacobi_sn(U k, T theta); template - typename tools::promote_args::type jacobi_cn(T k, U theta, const Policy& pol); + tools::promote_args_t jacobi_cn(T k, U theta, const Policy& pol); template - typename tools::promote_args::type jacobi_cn(T k, U theta); + tools::promote_args_t jacobi_cn(T k, U theta); template - typename tools::promote_args::type jacobi_dn(T k, U theta, const Policy& pol); + tools::promote_args_t jacobi_dn(T k, U theta, const Policy& pol); template - typename tools::promote_args::type jacobi_dn(T k, U theta); + tools::promote_args_t jacobi_dn(T k, U theta); template - typename tools::promote_args::type jacobi_cd(T k, U theta, const Policy& pol); + tools::promote_args_t jacobi_cd(T k, U theta, const Policy& pol); template - typename tools::promote_args::type jacobi_cd(T k, U theta); + tools::promote_args_t jacobi_cd(T k, U theta); template - typename tools::promote_args::type jacobi_dc(T k, U theta, const Policy& pol); + tools::promote_args_t jacobi_dc(T k, U theta, const Policy& pol); template - typename tools::promote_args::type jacobi_dc(T k, U theta); + tools::promote_args_t jacobi_dc(T k, U theta); template - typename tools::promote_args::type jacobi_ns(T k, U theta, const Policy& pol); + tools::promote_args_t jacobi_ns(T k, U theta, const Policy& pol); template - typename tools::promote_args::type jacobi_ns(T k, U theta); + tools::promote_args_t jacobi_ns(T k, U theta); template - typename tools::promote_args::type jacobi_sd(T k, U theta, const Policy& pol); + tools::promote_args_t jacobi_sd(T k, U theta, const Policy& pol); template - typename tools::promote_args::type jacobi_sd(T k, U theta); + tools::promote_args_t jacobi_sd(T k, U theta); template - typename tools::promote_args::type jacobi_ds(T k, U theta, const Policy& pol); + tools::promote_args_t jacobi_ds(T k, U theta, const Policy& pol); template - typename tools::promote_args::type jacobi_ds(T k, U theta); + tools::promote_args_t jacobi_ds(T k, U theta); template - typename tools::promote_args::type jacobi_nc(T k, U theta, const Policy& pol); + tools::promote_args_t jacobi_nc(T k, U theta, const Policy& pol); template - typename tools::promote_args::type jacobi_nc(T k, U theta); + tools::promote_args_t jacobi_nc(T k, U theta); template - typename tools::promote_args::type jacobi_nd(T k, U theta, const Policy& pol); + tools::promote_args_t jacobi_nd(T k, U theta, const Policy& pol); template - typename tools::promote_args::type jacobi_nd(T k, U theta); + tools::promote_args_t jacobi_nd(T k, U theta); template - typename tools::promote_args::type jacobi_sc(T k, U theta, const Policy& pol); + tools::promote_args_t jacobi_sc(T k, U theta, const Policy& pol); template - typename tools::promote_args::type jacobi_sc(T k, U theta); + tools::promote_args_t jacobi_sc(T k, U theta); template - typename tools::promote_args::type jacobi_cs(T k, U theta, const Policy& pol); + tools::promote_args_t jacobi_cs(T k, U theta, const Policy& pol); template - typename tools::promote_args::type jacobi_cs(T k, U theta); + tools::promote_args_t jacobi_cs(T k, U theta); // Jacobi Theta Functions: template - typename tools::promote_args::type jacobi_theta1(T z, U q, const Policy& pol); + tools::promote_args_t jacobi_theta1(T z, U q, const Policy& pol); template - typename tools::promote_args::type jacobi_theta1(T z, U q); + tools::promote_args_t jacobi_theta1(T z, U q); template - typename tools::promote_args::type jacobi_theta2(T z, U q, const Policy& pol); + tools::promote_args_t jacobi_theta2(T z, U q, const Policy& pol); template - typename tools::promote_args::type jacobi_theta2(T z, U q); + tools::promote_args_t jacobi_theta2(T z, U q); template - typename tools::promote_args::type jacobi_theta3(T z, U q, const Policy& pol); + tools::promote_args_t jacobi_theta3(T z, U q, const Policy& pol); template - typename tools::promote_args::type jacobi_theta3(T z, U q); + tools::promote_args_t jacobi_theta3(T z, U q); template - typename tools::promote_args::type jacobi_theta4(T z, U q, const Policy& pol); + tools::promote_args_t jacobi_theta4(T z, U q, const Policy& pol); template - typename tools::promote_args::type jacobi_theta4(T z, U q); + tools::promote_args_t jacobi_theta4(T z, U q); template - typename tools::promote_args::type jacobi_theta1tau(T z, U tau, const Policy& pol); + tools::promote_args_t jacobi_theta1tau(T z, U tau, const Policy& pol); template - typename tools::promote_args::type jacobi_theta1tau(T z, U tau); + tools::promote_args_t jacobi_theta1tau(T z, U tau); template - typename tools::promote_args::type jacobi_theta2tau(T z, U tau, const Policy& pol); + tools::promote_args_t jacobi_theta2tau(T z, U tau, const Policy& pol); template - typename tools::promote_args::type jacobi_theta2tau(T z, U tau); + tools::promote_args_t jacobi_theta2tau(T z, U tau); template - typename tools::promote_args::type jacobi_theta3tau(T z, U tau, const Policy& pol); + tools::promote_args_t jacobi_theta3tau(T z, U tau, const Policy& pol); template - typename tools::promote_args::type jacobi_theta3tau(T z, U tau); + tools::promote_args_t jacobi_theta3tau(T z, U tau); template - typename tools::promote_args::type jacobi_theta4tau(T z, U tau, const Policy& pol); + tools::promote_args_t jacobi_theta4tau(T z, U tau, const Policy& pol); template - typename tools::promote_args::type jacobi_theta4tau(T z, U tau); + tools::promote_args_t jacobi_theta4tau(T z, U tau); template - typename tools::promote_args::type jacobi_theta3m1(T z, U q, const Policy& pol); + tools::promote_args_t jacobi_theta3m1(T z, U q, const Policy& pol); template - typename tools::promote_args::type jacobi_theta3m1(T z, U q); + tools::promote_args_t jacobi_theta3m1(T z, U q); template - typename tools::promote_args::type jacobi_theta4m1(T z, U q, const Policy& pol); + tools::promote_args_t jacobi_theta4m1(T z, U q, const Policy& pol); template - typename tools::promote_args::type jacobi_theta4m1(T z, U q); + tools::promote_args_t jacobi_theta4m1(T z, U q); template - typename tools::promote_args::type jacobi_theta3m1tau(T z, U tau, const Policy& pol); + tools::promote_args_t jacobi_theta3m1tau(T z, U tau, const Policy& pol); template - typename tools::promote_args::type jacobi_theta3m1tau(T z, U tau); + tools::promote_args_t jacobi_theta3m1tau(T z, U tau); template - typename tools::promote_args::type jacobi_theta4m1tau(T z, U tau, const Policy& pol); + tools::promote_args_t jacobi_theta4m1tau(T z, U tau, const Policy& pol); template - typename tools::promote_args::type jacobi_theta4m1tau(T z, U tau); + tools::promote_args_t jacobi_theta4m1tau(T z, U tau); template - typename tools::promote_args::type zeta(T s); + tools::promote_args_t zeta(T s); // pow: template - BOOST_CXX14_CONSTEXPR typename tools::promote_args::type pow(T base, const Policy& policy); + BOOST_CXX14_CONSTEXPR tools::promote_args_t pow(T base, const Policy& policy); template - BOOST_CXX14_CONSTEXPR typename tools::promote_args::type pow(T base); + BOOST_CXX14_CONSTEXPR tools::promote_args_t pow(T base); // next: template - typename tools::promote_args::type nextafter(const T&, const U&, const Policy&); + tools::promote_args_t nextafter(const T&, const U&, const Policy&); template - typename tools::promote_args::type nextafter(const T&, const U&); + tools::promote_args_t nextafter(const T&, const U&); template - typename tools::promote_args::type float_next(const T&, const Policy&); + tools::promote_args_t float_next(const T&, const Policy&); template - typename tools::promote_args::type float_next(const T&); + tools::promote_args_t float_next(const T&); template - typename tools::promote_args::type float_prior(const T&, const Policy&); + tools::promote_args_t float_prior(const T&, const Policy&); template - typename tools::promote_args::type float_prior(const T&); + tools::promote_args_t float_prior(const T&); template - typename tools::promote_args::type float_distance(const T&, const U&, const Policy&); + tools::promote_args_t float_distance(const T&, const U&, const Policy&); template - typename tools::promote_args::type float_distance(const T&, const U&); + tools::promote_args_t float_distance(const T&, const U&); template - typename tools::promote_args::type float_advance(T val, int distance, const Policy& pol); + tools::promote_args_t float_advance(T val, int distance, const Policy& pol); template - typename tools::promote_args::type float_advance(const T& val, int distance); + tools::promote_args_t float_advance(const T& val, int distance); template - typename tools::promote_args::type ulp(const T& val, const Policy& pol); + tools::promote_args_t ulp(const T& val, const Policy& pol); template - typename tools::promote_args::type ulp(const T& val); + tools::promote_args_t ulp(const T& val); template - typename tools::promote_args::type relative_difference(const T&, const U&); + tools::promote_args_t relative_difference(const T&, const U&); template - typename tools::promote_args::type epsilon_difference(const T&, const U&); + tools::promote_args_t epsilon_difference(const T&, const U&); template BOOST_MATH_CONSTEXPR_TABLE_FUNCTION T unchecked_bernoulli_b2n(const std::size_t n); @@ -1155,34 +1155,34 @@ namespace boost // Lambert W: template - typename boost::math::tools::promote_args::type lambert_w0(T z, const Policy& pol); + boost::math::tools::promote_args_t lambert_w0(T z, const Policy& pol); template - typename boost::math::tools::promote_args::type lambert_w0(T z); + boost::math::tools::promote_args_t lambert_w0(T z); template - typename boost::math::tools::promote_args::type lambert_wm1(T z, const Policy& pol); + boost::math::tools::promote_args_t lambert_wm1(T z, const Policy& pol); template - typename boost::math::tools::promote_args::type lambert_wm1(T z); + boost::math::tools::promote_args_t lambert_wm1(T z); template - typename boost::math::tools::promote_args::type lambert_w0_prime(T z, const Policy& pol); + boost::math::tools::promote_args_t lambert_w0_prime(T z, const Policy& pol); template - typename boost::math::tools::promote_args::type lambert_w0_prime(T z); + boost::math::tools::promote_args_t lambert_w0_prime(T z); template - typename boost::math::tools::promote_args::type lambert_wm1_prime(T z, const Policy& pol); + boost::math::tools::promote_args_t lambert_wm1_prime(T z, const Policy& pol); template - typename boost::math::tools::promote_args::type lambert_wm1_prime(T z); + boost::math::tools::promote_args_t lambert_wm1_prime(T z); // Hypergeometrics: - template typename tools::promote_args::type hypergeometric_1F0(T1 a, T2 z); - template typename tools::promote_args::type hypergeometric_1F0(T1 a, T2 z, const Policy&); + template tools::promote_args_t hypergeometric_1F0(T1 a, T2 z); + template tools::promote_args_t hypergeometric_1F0(T1 a, T2 z, const Policy&); - template typename tools::promote_args::type hypergeometric_0F1(T1 b, T2 z); - template typename tools::promote_args::type hypergeometric_0F1(T1 b, T2 z, const Policy&); + template tools::promote_args_t hypergeometric_0F1(T1 b, T2 z); + template tools::promote_args_t hypergeometric_0F1(T1 b, T2 z, const Policy&); - template typename tools::promote_args::type hypergeometric_2F0(T1 a1, T2 a2, T3 z); - template typename tools::promote_args::type hypergeometric_2F0(T1 a1, T2 a2, T3 z, const Policy&); + template tools::promote_args_t hypergeometric_2F0(T1 a1, T2 a2, T3 z); + template tools::promote_args_t hypergeometric_2F0(T1 a1, T2 a2, T3 z, const Policy&); - template typename tools::promote_args::type hypergeometric_1F1(T1 a, T2 b, T3 z); - template typename tools::promote_args::type hypergeometric_1F1(T1 a, T2 b, T3 z, const Policy&); + template tools::promote_args_t hypergeometric_1F1(T1 a, T2 b, T3 z); + template tools::promote_args_t hypergeometric_1F1(T1 a, T2 b, T3 z, const Policy&); } // namespace math @@ -1201,7 +1201,7 @@ namespace boost # define BOOST_MATH_DETAIL_11_FUNC(Policy)\ template \ - inline typename boost::math::tools::promote_args::type hypergeometric_1F1(const T& a, const U& b, const V& z)\ + inline boost::math::tools::promote_args_t hypergeometric_1F1(const T& a, const U& b, const V& z)\ { return boost::math::hypergeometric_1F1(a, b, z, Policy()); }\ #define BOOST_MATH_DECLARE_SPECIAL_FUNCTIONS(Policy)\ @@ -1210,99 +1210,99 @@ namespace boost BOOST_MATH_DETAIL_11_FUNC(Policy)\ \ template \ - inline typename boost::math::tools::promote_args::type \ + inline boost::math::tools::promote_args_t \ beta(RT1 a, RT2 b) { return ::boost::math::beta(a, b, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type \ + inline boost::math::tools::promote_args_t \ beta(RT1 a, RT2 b, A x){ return ::boost::math::beta(a, b, x, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type \ + inline boost::math::tools::promote_args_t \ betac(RT1 a, RT2 b, RT3 x) { return ::boost::math::betac(a, b, x, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type \ + inline boost::math::tools::promote_args_t \ ibeta(RT1 a, RT2 b, RT3 x){ return ::boost::math::ibeta(a, b, x, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type \ + inline boost::math::tools::promote_args_t \ ibetac(RT1 a, RT2 b, RT3 x){ return ::boost::math::ibetac(a, b, x, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type \ + inline boost::math::tools::promote_args_t \ ibeta_inv(T1 a, T2 b, T3 p, T4* py){ return ::boost::math::ibeta_inv(a, b, p, py, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type \ + inline boost::math::tools::promote_args_t \ ibeta_inv(RT1 a, RT2 b, RT3 p){ return ::boost::math::ibeta_inv(a, b, p, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type \ + inline boost::math::tools::promote_args_t \ ibetac_inv(T1 a, T2 b, T3 q, T4* py){ return ::boost::math::ibetac_inv(a, b, q, py, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type \ + inline boost::math::tools::promote_args_t \ ibeta_inva(RT1 a, RT2 b, RT3 p){ return ::boost::math::ibeta_inva(a, b, p, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type \ + inline boost::math::tools::promote_args_t \ ibetac_inva(T1 a, T2 b, T3 q){ return ::boost::math::ibetac_inva(a, b, q, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type \ + inline boost::math::tools::promote_args_t \ ibeta_invb(RT1 a, RT2 b, RT3 p){ return ::boost::math::ibeta_invb(a, b, p, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type \ + inline boost::math::tools::promote_args_t \ ibetac_invb(T1 a, T2 b, T3 q){ return ::boost::math::ibetac_invb(a, b, q, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type \ + inline boost::math::tools::promote_args_t \ ibetac_inv(RT1 a, RT2 b, RT3 q){ return ::boost::math::ibetac_inv(a, b, q, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type \ + inline boost::math::tools::promote_args_t \ ibeta_derivative(RT1 a, RT2 b, RT3 x){ return ::boost::math::ibeta_derivative(a, b, x, Policy()); }\ \ template T binomial_coefficient(unsigned n, unsigned k){ return ::boost::math::binomial_coefficient(n, k, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type erf(RT z) { return ::boost::math::erf(z, Policy()); }\ + inline boost::math::tools::promote_args_t erf(RT z) { return ::boost::math::erf(z, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type erfc(RT z){ return ::boost::math::erfc(z, Policy()); }\ + inline boost::math::tools::promote_args_t erfc(RT z){ return ::boost::math::erfc(z, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type erf_inv(RT z) { return ::boost::math::erf_inv(z, Policy()); }\ + inline boost::math::tools::promote_args_t erf_inv(RT z) { return ::boost::math::erf_inv(z, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type erfc_inv(RT z){ return ::boost::math::erfc_inv(z, Policy()); }\ + inline boost::math::tools::promote_args_t erfc_inv(RT z){ return ::boost::math::erfc_inv(z, Policy()); }\ \ using boost::math::legendre_next;\ \ template \ - inline typename boost::math::tools::promote_args::type \ + inline boost::math::tools::promote_args_t \ legendre_p(int l, T x){ return ::boost::math::legendre_p(l, x, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type \ + inline boost::math::tools::promote_args_t \ legendre_p_prime(int l, T x){ return ::boost::math::legendre_p(l, x, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type \ + inline boost::math::tools::promote_args_t \ legendre_q(unsigned l, T x){ return ::boost::math::legendre_q(l, x, Policy()); }\ \ using ::boost::math::legendre_next;\ \ template \ - inline typename boost::math::tools::promote_args::type \ + inline boost::math::tools::promote_args_t \ legendre_p(int l, int m, T x){ return ::boost::math::legendre_p(l, m, x, Policy()); }\ \ using ::boost::math::laguerre_next;\ \ template \ - inline typename boost::math::tools::promote_args::type \ + inline boost::math::tools::promote_args_t \ laguerre(unsigned n, T x){ return ::boost::math::laguerre(n, x, Policy()); }\ \ template \ @@ -1310,7 +1310,7 @@ namespace boost laguerre(unsigned n, T1 m, T2 x) { return ::boost::math::laguerre(n, m, x, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type \ + inline boost::math::tools::promote_args_t \ hermite(unsigned n, T x){ return ::boost::math::hermite(n, x, Policy()); }\ \ using boost::math::hermite_next;\ @@ -1329,70 +1329,70 @@ namespace boost using ::boost::math::chebyshev_clenshaw_recurrence;\ \ template \ - inline std::complex::type> \ + inline std::complex> \ spherical_harmonic(unsigned n, int m, T1 theta, T2 phi){ return boost::math::spherical_harmonic(n, m, theta, phi, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type \ + inline boost::math::tools::promote_args_t \ spherical_harmonic_r(unsigned n, int m, T1 theta, T2 phi){ return ::boost::math::spherical_harmonic_r(n, m, theta, phi, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type \ + inline boost::math::tools::promote_args_t \ spherical_harmonic_i(unsigned n, int m, T1 theta, T2 phi){ return boost::math::spherical_harmonic_i(n, m, theta, phi, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type \ + inline boost::math::tools::promote_args_t \ spherical_harmonic_i(unsigned n, int m, T1 theta, T2 phi, const Policy& pol);\ \ template \ - inline typename boost::math::tools::promote_args::type \ + inline boost::math::tools::promote_args_t \ ellint_rf(T1 x, T2 y, T3 z){ return ::boost::math::ellint_rf(x, y, z, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type \ + inline boost::math::tools::promote_args_t \ ellint_rd(T1 x, T2 y, T3 z){ return ::boost::math::ellint_rd(x, y, z, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type \ + inline boost::math::tools::promote_args_t \ ellint_rc(T1 x, T2 y){ return ::boost::math::ellint_rc(x, y, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type \ + inline boost::math::tools::promote_args_t \ ellint_rj(T1 x, T2 y, T3 z, T4 p){ return boost::math::ellint_rj(x, y, z, p, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type \ + inline boost::math::tools::promote_args_t \ ellint_rg(T1 x, T2 y, T3 z){ return ::boost::math::ellint_rg(x, y, z, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type ellint_2(T k){ return boost::math::ellint_2(k, Policy()); }\ + inline boost::math::tools::promote_args_t ellint_2(T k){ return boost::math::ellint_2(k, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type ellint_2(T1 k, T2 phi){ return boost::math::ellint_2(k, phi, Policy()); }\ + inline boost::math::tools::promote_args_t ellint_2(T1 k, T2 phi){ return boost::math::ellint_2(k, phi, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type ellint_d(T k){ return boost::math::ellint_d(k, Policy()); }\ + inline boost::math::tools::promote_args_t ellint_d(T k){ return boost::math::ellint_d(k, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type ellint_d(T1 k, T2 phi){ return boost::math::ellint_d(k, phi, Policy()); }\ + inline boost::math::tools::promote_args_t ellint_d(T1 k, T2 phi){ return boost::math::ellint_d(k, phi, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type jacobi_zeta(T1 k, T2 phi){ return boost::math::jacobi_zeta(k, phi, Policy()); }\ + inline boost::math::tools::promote_args_t jacobi_zeta(T1 k, T2 phi){ return boost::math::jacobi_zeta(k, phi, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type heuman_lambda(T1 k, T2 phi){ return boost::math::heuman_lambda(k, phi, Policy()); }\ + inline boost::math::tools::promote_args_t heuman_lambda(T1 k, T2 phi){ return boost::math::heuman_lambda(k, phi, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type ellint_1(T k){ return boost::math::ellint_1(k, Policy()); }\ + inline boost::math::tools::promote_args_t ellint_1(T k){ return boost::math::ellint_1(k, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type ellint_1(T1 k, T2 phi){ return boost::math::ellint_1(k, phi, Policy()); }\ + inline boost::math::tools::promote_args_t ellint_1(T1 k, T2 phi){ return boost::math::ellint_1(k, phi, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type ellint_3(T1 k, T2 v, T3 phi){ return boost::math::ellint_3(k, v, phi, Policy()); }\ + inline boost::math::tools::promote_args_t ellint_3(T1 k, T2 v, T3 phi){ return boost::math::ellint_3(k, v, phi, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type ellint_3(T1 k, T2 v){ return boost::math::ellint_3(k, v, Policy()); }\ + inline boost::math::tools::promote_args_t ellint_3(T1 k, T2 v){ return boost::math::ellint_3(k, v, Policy()); }\ \ using boost::math::max_factorial;\ template \ @@ -1401,101 +1401,101 @@ namespace boost template \ inline RT double_factorial(unsigned i){ return boost::math::double_factorial(i, Policy()); }\ template \ - inline typename boost::math::tools::promote_args::type falling_factorial(RT x, unsigned n){ return boost::math::falling_factorial(x, n, Policy()); }\ + inline boost::math::tools::promote_args_t falling_factorial(RT x, unsigned n){ return boost::math::falling_factorial(x, n, Policy()); }\ template \ - inline typename boost::math::tools::promote_args::type rising_factorial(RT x, unsigned n){ return boost::math::rising_factorial(x, n, Policy()); }\ + inline boost::math::tools::promote_args_t rising_factorial(RT x, unsigned n){ return boost::math::rising_factorial(x, n, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type tgamma(RT z){ return boost::math::tgamma(z, Policy()); }\ + inline boost::math::tools::promote_args_t tgamma(RT z){ return boost::math::tgamma(z, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type tgamma1pm1(RT z){ return boost::math::tgamma1pm1(z, Policy()); }\ + inline boost::math::tools::promote_args_t tgamma1pm1(RT z){ return boost::math::tgamma1pm1(z, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type tgamma(RT1 a, RT2 z){ return boost::math::tgamma(a, z, Policy()); }\ + inline boost::math::tools::promote_args_t tgamma(RT1 a, RT2 z){ return boost::math::tgamma(a, z, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type lgamma(RT z, int* sign){ return boost::math::lgamma(z, sign, Policy()); }\ + inline boost::math::tools::promote_args_t lgamma(RT z, int* sign){ return boost::math::lgamma(z, sign, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type lgamma(RT x){ return boost::math::lgamma(x, Policy()); }\ + inline boost::math::tools::promote_args_t lgamma(RT x){ return boost::math::lgamma(x, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type tgamma_lower(RT1 a, RT2 z){ return boost::math::tgamma_lower(a, z, Policy()); }\ + inline boost::math::tools::promote_args_t tgamma_lower(RT1 a, RT2 z){ return boost::math::tgamma_lower(a, z, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type gamma_q(RT1 a, RT2 z){ return boost::math::gamma_q(a, z, Policy()); }\ + inline boost::math::tools::promote_args_t gamma_q(RT1 a, RT2 z){ return boost::math::gamma_q(a, z, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type gamma_p(RT1 a, RT2 z){ return boost::math::gamma_p(a, z, Policy()); }\ + inline boost::math::tools::promote_args_t gamma_p(RT1 a, RT2 z){ return boost::math::gamma_p(a, z, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type tgamma_delta_ratio(T1 z, T2 delta){ return boost::math::tgamma_delta_ratio(z, delta, Policy()); }\ + inline boost::math::tools::promote_args_t tgamma_delta_ratio(T1 z, T2 delta){ return boost::math::tgamma_delta_ratio(z, delta, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type tgamma_ratio(T1 a, T2 b) { return boost::math::tgamma_ratio(a, b, Policy()); }\ + inline boost::math::tools::promote_args_t tgamma_ratio(T1 a, T2 b) { return boost::math::tgamma_ratio(a, b, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type gamma_p_derivative(T1 a, T2 x){ return boost::math::gamma_p_derivative(a, x, Policy()); }\ + inline boost::math::tools::promote_args_t gamma_p_derivative(T1 a, T2 x){ return boost::math::gamma_p_derivative(a, x, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type gamma_p_inv(T1 a, T2 p){ return boost::math::gamma_p_inv(a, p, Policy()); }\ + inline boost::math::tools::promote_args_t gamma_p_inv(T1 a, T2 p){ return boost::math::gamma_p_inv(a, p, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type gamma_p_inva(T1 a, T2 p){ return boost::math::gamma_p_inva(a, p, Policy()); }\ + inline boost::math::tools::promote_args_t gamma_p_inva(T1 a, T2 p){ return boost::math::gamma_p_inva(a, p, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type gamma_q_inv(T1 a, T2 q){ return boost::math::gamma_q_inv(a, q, Policy()); }\ + inline boost::math::tools::promote_args_t gamma_q_inv(T1 a, T2 q){ return boost::math::gamma_q_inv(a, q, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type gamma_q_inva(T1 a, T2 q){ return boost::math::gamma_q_inva(a, q, Policy()); }\ + inline boost::math::tools::promote_args_t gamma_q_inva(T1 a, T2 q){ return boost::math::gamma_q_inva(a, q, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type digamma(T x){ return boost::math::digamma(x, Policy()); }\ + inline boost::math::tools::promote_args_t digamma(T x){ return boost::math::digamma(x, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type trigamma(T x){ return boost::math::trigamma(x, Policy()); }\ + inline boost::math::tools::promote_args_t trigamma(T x){ return boost::math::trigamma(x, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type polygamma(int n, T x){ return boost::math::polygamma(n, x, Policy()); }\ + inline boost::math::tools::promote_args_t polygamma(int n, T x){ return boost::math::polygamma(n, x, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type \ + inline boost::math::tools::promote_args_t \ hypot(T1 x, T2 y){ return boost::math::hypot(x, y, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type cbrt(RT z){ return boost::math::cbrt(z, Policy()); }\ + inline boost::math::tools::promote_args_t cbrt(RT z){ return boost::math::cbrt(z, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type log1p(T x){ return boost::math::log1p(x, Policy()); }\ + inline boost::math::tools::promote_args_t log1p(T x){ return boost::math::log1p(x, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type log1pmx(T x){ return boost::math::log1pmx(x, Policy()); }\ + inline boost::math::tools::promote_args_t log1pmx(T x){ return boost::math::log1pmx(x, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type expm1(T x){ return boost::math::expm1(x, Policy()); }\ + inline boost::math::tools::promote_args_t expm1(T x){ return boost::math::expm1(x, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type \ + inline boost::math::tools::promote_args_t \ powm1(const T1 a, const T2 z){ return boost::math::powm1(a, z, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type sqrt1pm1(const T& val){ return boost::math::sqrt1pm1(val, Policy()); }\ + inline boost::math::tools::promote_args_t sqrt1pm1(const T& val){ return boost::math::sqrt1pm1(val, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type sinc_pi(T x){ return boost::math::sinc_pi(x, Policy()); }\ + inline boost::math::tools::promote_args_t sinc_pi(T x){ return boost::math::sinc_pi(x, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type sinhc_pi(T x){ return boost::math::sinhc_pi(x, Policy()); }\ + inline boost::math::tools::promote_args_t sinhc_pi(T x){ return boost::math::sinhc_pi(x, Policy()); }\ \ template\ - inline typename boost::math::tools::promote_args::type asinh(const T x){ return boost::math::asinh(x, Policy()); }\ + inline boost::math::tools::promote_args_t asinh(const T x){ return boost::math::asinh(x, Policy()); }\ \ template\ - inline typename boost::math::tools::promote_args::type acosh(const T x){ return boost::math::acosh(x, Policy()); }\ + inline boost::math::tools::promote_args_t acosh(const T x){ return boost::math::acosh(x, Policy()); }\ \ template\ - inline typename boost::math::tools::promote_args::type atanh(const T x){ return boost::math::atanh(x, Policy()); }\ + inline boost::math::tools::promote_args_t atanh(const T x){ return boost::math::atanh(x, Policy()); }\ \ template \ inline typename boost::math::detail::bessel_traits::result_type cyl_bessel_j(T1 v, T2 x)\ @@ -1568,10 +1568,10 @@ template \ { boost::math::cyl_neumann_zero(v, start_index, number_of_zeros, out_it, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type sin_pi(T x){ return boost::math::sin_pi(x, Policy()); }\ + inline boost::math::tools::promote_args_t sin_pi(T x){ return boost::math::sin_pi(x, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type cos_pi(T x){ return boost::math::cos_pi(x, Policy()); }\ + inline boost::math::tools::promote_args_t cos_pi(T x){ return boost::math::cos_pi(x, Policy()); }\ \ using boost::math::fpclassify;\ using boost::math::isfinite;\ @@ -1584,14 +1584,14 @@ template \ using boost::math::changesign;\ \ template \ - inline typename boost::math::tools::promote_args::type expint(T const& z, U const& u)\ + inline typename boost::math::tools::promote_args_t expint(T const& z, U const& u)\ { return boost::math::expint(z, u, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type expint(T z){ return boost::math::expint(z, Policy()); }\ + inline boost::math::tools::promote_args_t expint(T z){ return boost::math::expint(z, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type zeta(T s){ return boost::math::zeta(s, Policy()); }\ + inline boost::math::tools::promote_args_t zeta(T s){ return boost::math::zeta(s, Policy()); }\ \ template \ inline T round(const T& v){ using boost::math::round; return round(v, Policy()); }\ @@ -1621,16 +1621,16 @@ template \ inline T modf(const T& v, long* ipart){ using boost::math::modf; return modf(v, ipart, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type pow(T v){ return boost::math::pow(v, Policy()); }\ + inline boost::math::tools::promote_args_t pow(T v){ return boost::math::pow(v, Policy()); }\ \ - template T nextafter(const T& a, const T& b){ return boost::math::nextafter(a, b, Policy()); }\ - template T float_next(const T& a){ return boost::math::float_next(a, Policy()); }\ - template T float_prior(const T& a){ return boost::math::float_prior(a, Policy()); }\ - template T float_distance(const T& a, const T& b){ return boost::math::float_distance(a, b, Policy()); }\ - template T ulp(const T& a){ return boost::math::ulp(a, Policy()); }\ + template T nextafter(const T& a, const T& b){ return static_cast(boost::math::nextafter(a, b, Policy())); }\ + template T float_next(const T& a){ return static_cast(boost::math::float_next(a, Policy())); }\ + template T float_prior(const T& a){ return static_cast(boost::math::float_prior(a, Policy())); }\ + template T float_distance(const T& a, const T& b){ return static_cast(boost::math::float_distance(a, b, Policy())); }\ + template T ulp(const T& a){ return static_cast(boost::math::ulp(a, Policy())); }\ \ template \ - inline typename boost::math::tools::promote_args::type owens_t(RT1 a, RT2 z){ return boost::math::owens_t(a, z, Policy()); }\ + inline boost::math::tools::promote_args_t owens_t(RT1 a, RT2 z){ return boost::math::owens_t(a, z, Policy()); }\ \ template \ inline std::complex::result_type> cyl_hankel_1(T1 v, T2 x)\ @@ -1649,119 +1649,119 @@ template \ { return boost::math::sph_hankel_2(v, x, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type jacobi_elliptic(T k, T theta, T* pcn, T* pdn)\ - { return boost::math::jacobi_elliptic(k, theta, pcn, pdn, Policy()); }\ + inline boost::math::tools::promote_args_t jacobi_elliptic(T k, T theta, T* pcn, T* pdn)\ + { return static_cast>(boost::math::jacobi_elliptic(k, theta, pcn, pdn, Policy())); }\ \ template \ - inline typename boost::math::tools::promote_args::type jacobi_sn(U k, T theta)\ + inline boost::math::tools::promote_args_t jacobi_sn(U k, T theta)\ { return boost::math::jacobi_sn(k, theta, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type jacobi_cn(T k, U theta)\ + inline boost::math::tools::promote_args_t jacobi_cn(T k, U theta)\ { return boost::math::jacobi_cn(k, theta, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type jacobi_dn(T k, U theta)\ + inline boost::math::tools::promote_args_t jacobi_dn(T k, U theta)\ { return boost::math::jacobi_dn(k, theta, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type jacobi_cd(T k, U theta)\ + inline boost::math::tools::promote_args_t jacobi_cd(T k, U theta)\ { return boost::math::jacobi_cd(k, theta, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type jacobi_dc(T k, U theta)\ + inline boost::math::tools::promote_args_t jacobi_dc(T k, U theta)\ { return boost::math::jacobi_dc(k, theta, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type jacobi_ns(T k, U theta)\ + inline boost::math::tools::promote_args_t jacobi_ns(T k, U theta)\ { return boost::math::jacobi_ns(k, theta, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type jacobi_sd(T k, U theta)\ + inline boost::math::tools::promote_args_t jacobi_sd(T k, U theta)\ { return boost::math::jacobi_sd(k, theta, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type jacobi_ds(T k, U theta)\ + inline boost::math::tools::promote_args_t jacobi_ds(T k, U theta)\ { return boost::math::jacobi_ds(k, theta, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type jacobi_nc(T k, U theta)\ + inline boost::math::tools::promote_args_t jacobi_nc(T k, U theta)\ { return boost::math::jacobi_nc(k, theta, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type jacobi_nd(T k, U theta)\ + inline boost::math::tools::promote_args_t jacobi_nd(T k, U theta)\ { return boost::math::jacobi_nd(k, theta, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type jacobi_sc(T k, U theta)\ + inline boost::math::tools::promote_args_t jacobi_sc(T k, U theta)\ { return boost::math::jacobi_sc(k, theta, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type jacobi_cs(T k, U theta)\ + inline boost::math::tools::promote_args_t jacobi_cs(T k, U theta)\ { return boost::math::jacobi_cs(k, theta, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type jacobi_theta1(T z, U q)\ + inline boost::math::tools::promote_args_t jacobi_theta1(T z, U q)\ { return boost::math::jacobi_theta1(z, q, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type jacobi_theta2(T z, U q)\ + inline boost::math::tools::promote_args_t jacobi_theta2(T z, U q)\ { return boost::math::jacobi_theta2(z, q, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type jacobi_theta3(T z, U q)\ + inline boost::math::tools::promote_args_t jacobi_theta3(T z, U q)\ { return boost::math::jacobi_theta3(z, q, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type jacobi_theta4(T z, U q)\ + inline boost::math::tools::promote_args_t jacobi_theta4(T z, U q)\ { return boost::math::jacobi_theta4(z, q, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type jacobi_theta1tau(T z, U q)\ + inline boost::math::tools::promote_args_t jacobi_theta1tau(T z, U q)\ { return boost::math::jacobi_theta1tau(z, q, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type jacobi_theta2tau(T z, U q)\ + inline boost::math::tools::promote_args_t jacobi_theta2tau(T z, U q)\ { return boost::math::jacobi_theta2tau(z, q, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type jacobi_theta3tau(T z, U q)\ + inline boost::math::tools::promote_args_t jacobi_theta3tau(T z, U q)\ { return boost::math::jacobi_theta3tau(z, q, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type jacobi_theta4tau(T z, U q)\ + inline boost::math::tools::promote_args_t jacobi_theta4tau(T z, U q)\ { return boost::math::jacobi_theta4tau(z, q, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type jacobi_theta3m1(T z, U q)\ + inline boost::math::tools::promote_args_t jacobi_theta3m1(T z, U q)\ { return boost::math::jacobi_theta3m1(z, q, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type jacobi_theta4m1(T z, U q)\ + inline boost::math::tools::promote_args_t jacobi_theta4m1(T z, U q)\ { return boost::math::jacobi_theta4m1(z, q, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type jacobi_theta3m1tau(T z, U q)\ + inline boost::math::tools::promote_args_t jacobi_theta3m1tau(T z, U q)\ { return boost::math::jacobi_theta3m1tau(z, q, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type jacobi_theta4m1tau(T z, U q)\ + inline boost::math::tools::promote_args_t jacobi_theta4m1tau(T z, U q)\ { return boost::math::jacobi_theta4m1tau(z, q, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type airy_ai(T x)\ + inline boost::math::tools::promote_args_t airy_ai(T x)\ { return boost::math::airy_ai(x, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type airy_bi(T x)\ + inline boost::math::tools::promote_args_t airy_bi(T x)\ { return boost::math::airy_bi(x, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type airy_ai_prime(T x)\ + inline boost::math::tools::promote_args_t airy_ai_prime(T x)\ { return boost::math::airy_ai_prime(x, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type airy_bi_prime(T x)\ + inline boost::math::tools::promote_args_t airy_bi_prime(T x)\ { return boost::math::airy_bi_prime(x, Policy()); }\ \ template \ @@ -1792,21 +1792,21 @@ template \ OutputIterator tangent_t2n(int start_index, unsigned number_of_bernoullis_b2n, OutputIterator out_it)\ { return boost::math::tangent_t2n(start_index, number_of_bernoullis_b2n, out_it, Policy()); }\ \ - template inline typename boost::math::tools::promote_args::type lambert_w0(T z) { return boost::math::lambert_w0(z, Policy()); }\ - template inline typename boost::math::tools::promote_args::type lambert_wm1(T z) { return boost::math::lambert_w0(z, Policy()); }\ - template inline typename boost::math::tools::promote_args::type lambert_w0_prime(T z) { return boost::math::lambert_w0(z, Policy()); }\ - template inline typename boost::math::tools::promote_args::type lambert_wm1_prime(T z) { return boost::math::lambert_w0(z, Policy()); }\ + template inline boost::math::tools::promote_args_t lambert_w0(T z) { return boost::math::lambert_w0(z, Policy()); }\ + template inline boost::math::tools::promote_args_t lambert_wm1(T z) { return boost::math::lambert_w0(z, Policy()); }\ + template inline boost::math::tools::promote_args_t lambert_w0_prime(T z) { return boost::math::lambert_w0(z, Policy()); }\ + template inline boost::math::tools::promote_args_t lambert_wm1_prime(T z) { return boost::math::lambert_w0(z, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type hypergeometric_1F0(const T& a, const U& z)\ + inline boost::math::tools::promote_args_t hypergeometric_1F0(const T& a, const U& z)\ { return boost::math::hypergeometric_1F0(a, z, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type hypergeometric_0F1(const T& a, const U& z)\ + inline boost::math::tools::promote_args_t hypergeometric_0F1(const T& a, const U& z)\ { return boost::math::hypergeometric_0F1(a, z, Policy()); }\ \ template \ - inline typename boost::math::tools::promote_args::type hypergeometric_2F0(const T& a1, const U& a2, const V& z)\ + inline boost::math::tools::promote_args_t hypergeometric_2F0(const T& a1, const U& a2, const V& z)\ { return boost::math::hypergeometric_2F0(a1, a2, z, Policy()); }\ \ diff --git a/include/boost/math/special_functions/owens_t.hpp b/include/boost/math/special_functions/owens_t.hpp index 152b5cbdda..7a93246eee 100644 --- a/include/boost/math/special_functions/owens_t.hpp +++ b/include/boost/math/special_functions/owens_t.hpp @@ -588,7 +588,7 @@ namespace boost } #endif n = (std::min)(n, 1500); - T d = pow(3 + sqrt(T(8)), n); + T d = pow(3 + sqrt(T(8)), T(n)); d = (d + 1 / d) / 2; T b = -1; T c = -d; @@ -706,7 +706,7 @@ namespace boost } #endif n = (std::min)(n, 1500); - RealType d = pow(3 + sqrt(RealType(8)), n); + RealType d = pow(3 + sqrt(RealType(8)), RealType(n)); d = (d + 1 / d) / 2; RealType b = -1; RealType c = -d; @@ -949,7 +949,7 @@ namespace boost // Now look back at the results from T1 and T2 and see if either gave better // results than we could get from the 64-bit precision versions. // - if((std::min)(p1.second, p2.second) < 1e-20) + if((std::min)(p1.second, p2.second) < RealType(1e-20)) { return p1.second < p2.second ? p1.first : p2.first; } @@ -993,7 +993,7 @@ namespace boost const RealType fabs_a = fabs(a); const RealType fabs_ah = fabs_a*h; - RealType val = 0.0; // avoid compiler warnings, 0.0 will be overwritten in any case + RealType val = static_cast(0.0f); // avoid compiler warnings, 0.0 will be overwritten in any case if(fabs_a <= 1) { @@ -1001,7 +1001,7 @@ namespace boost } // if(fabs_a <= 1.0) else { - if( h <= 0.67 ) + if( h <= RealType(0.67) ) { const RealType normh = owens_t_znorm1(h, pol); const RealType normah = owens_t_znorm1(fabs_ah, pol); diff --git a/include/boost/math/special_functions/powm1.hpp b/include/boost/math/special_functions/powm1.hpp index 05b5a5d3fa..e52277b16d 100644 --- a/include/boost/math/special_functions/powm1.hpp +++ b/include/boost/math/special_functions/powm1.hpp @@ -28,12 +28,12 @@ inline T powm1_imp(const T x, const T y, const Policy& pol) static const char* function = "boost::math::powm1<%1%>(%1%, %1%)"; if (x > 0) { - if ((fabs(y * (x - 1)) < 0.5) || (fabs(y) < 0.2)) + if ((fabs(y * (x - 1)) < T(0.5)) || (fabs(y) < T(0.2))) { // We don't have any good/quick approximation for log(x) * y // so just try it and see: T l = y * log(x); - if (l < 0.5) + if (l < T(0.5)) return boost::math::expm1(l, pol); if (l > boost::math::tools::log_max_value()) return boost::math::policies::raise_overflow_error(function, nullptr, pol); diff --git a/include/boost/math/special_functions/round.hpp b/include/boost/math/special_functions/round.hpp index be9d661bae..b32c8e4347 100644 --- a/include/boost/math/special_functions/round.hpp +++ b/include/boost/math/special_functions/round.hpp @@ -44,7 +44,7 @@ inline tools::promote_args_t round(const T& v, const Policy& pol, const std:: // The logic here is rather convoluted, but avoids a number of traps, // see discussion here https://github.com/boostorg/math/pull/8 // - if (-0.5 < v && v < 0.5) + if (T(-0.5) < v && v < T(0.5)) { // special case to avoid rounding error on the direct // predecessor of +0.5 resp. the direct successor of -0.5 in @@ -56,13 +56,13 @@ inline tools::promote_args_t round(const T& v, const Policy& pol, const std:: // subtract v from ceil(v) first in order to avoid rounding // errors on largest representable integer numbers result_type c(ceil(v)); - return 0.5 < c - v ? c - 1 : c; + return T(0.5) < c - v ? c - 1 : c; } else { // see former branch result_type f(floor(v)); - return 0.5 < v - f ? f + 1 : f; + return T(0.5) < v - f ? f + 1 : f; } } template diff --git a/include/boost/math/special_functions/rsqrt.hpp b/include/boost/math/special_functions/rsqrt.hpp index 438d16fb0c..fec6468e28 100644 --- a/include/boost/math/special_functions/rsqrt.hpp +++ b/include/boost/math/special_functions/rsqrt.hpp @@ -11,10 +11,10 @@ #include #ifndef BOOST_MATH_STANDALONE -#include -#ifdef BOOST_NO_CXX17_IF_CONSTEXPR -#error "The header can only be used in C++17 and later." -#endif +# include +# ifdef BOOST_NO_CXX17_IF_CONSTEXPR +# error "The header can only be used in C++17 and later." +# endif #endif namespace boost::math { @@ -23,7 +23,7 @@ template inline Real rsqrt(Real const & x) { using std::sqrt; - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + if constexpr (std::is_arithmetic_v && !std::is_integral_v) { return 1/sqrt(x); } diff --git a/include/boost/math/special_functions/sin_pi.hpp b/include/boost/math/special_functions/sin_pi.hpp index 78e9c4ea07..5b8eb6fcf2 100644 --- a/include/boost/math/special_functions/sin_pi.hpp +++ b/include/boost/math/special_functions/sin_pi.hpp @@ -27,7 +27,7 @@ inline T sin_pi_imp(T x, const Policy& pol) if(x < 0) return -sin_pi_imp(T(-x), pol); // sin of pi*x: - if(x < 0.5) + if(x < T(0.5)) return sin(constants::pi() * x); bool invert; if(x < 1) diff --git a/include/boost/math/special_functions/sqrt1pm1.hpp b/include/boost/math/special_functions/sqrt1pm1.hpp index 293a9d97b3..041916a53f 100644 --- a/include/boost/math/special_functions/sqrt1pm1.hpp +++ b/include/boost/math/special_functions/sqrt1pm1.hpp @@ -26,7 +26,7 @@ inline typename tools::promote_args::type sqrt1pm1(const T& val, const Policy typedef typename tools::promote_args::type result_type; BOOST_MATH_STD_USING - if(fabs(result_type(val)) > 0.75) + if(fabs(result_type(val)) > result_type(0.75)) return sqrt(1 + result_type(val)) - 1; return boost::math::expm1(boost::math::log1p(val, pol) / 2, pol); } diff --git a/include/boost/math/special_functions/zeta.hpp b/include/boost/math/special_functions/zeta.hpp index 0f3136d00f..118aa7d352 100644 --- a/include/boost/math/special_functions/zeta.hpp +++ b/include/boost/math/special_functions/zeta.hpp @@ -956,9 +956,9 @@ T zeta_imp(T s, T sc, const Policy& pol, const Tag& tag) else if((v & 1) == 0) { if(((v / 2) <= (int)boost::math::max_bernoulli_b2n::value) && (v <= (int)boost::math::max_factorial::value)) - return T(((v / 2 - 1) & 1) ? -1 : 1) * ldexp(T(1), v - 1) * pow(constants::pi(), v) * + return T(((v / 2 - 1) & 1) ? -1 : 1) * ldexp(T(1), v - 1) * static_cast(pow(constants::pi(), T(v))) * boost::math::unchecked_bernoulli_b2n(v / 2) / boost::math::unchecked_factorial(v); - return T(((v / 2 - 1) & 1) ? -1 : 1) * ldexp(T(1), v - 1) * pow(constants::pi(), v) * + return T(((v / 2 - 1) & 1) ? -1 : 1) * ldexp(T(1), v - 1) * static_cast(pow(constants::pi(), T(v))) * boost::math::bernoulli_b2n(v / 2) / boost::math::factorial(v, pol); } else diff --git a/include/boost/math/statistics/univariate_statistics.hpp b/include/boost/math/statistics/univariate_statistics.hpp index 082517d650..898ecb0c7b 100644 --- a/include/boost/math/statistics/univariate_statistics.hpp +++ b/include/boost/math/statistics/univariate_statistics.hpp @@ -505,14 +505,14 @@ auto median_absolute_deviation(ExecutionPolicy&& exec, RandomAccessIterator firs { auto middle = first + (num_elems - 1)/2; std::nth_element(exec, first, middle, last, comparator); - return abs(*middle); + return abs(*middle-center); } else { auto middle = first + num_elems/2 - 1; std::nth_element(exec, first, middle, last, comparator); std::nth_element(exec, middle, middle+1, last, comparator); - return (abs(*middle) + abs(*(middle+1)))/abs(static_cast(2)); + return (abs(*middle-center) + abs(*(middle+1)-center))/abs(static_cast(2)); } } @@ -1043,14 +1043,14 @@ Real median_absolute_deviation(RandomAccessIterator first, RandomAccessIterator { auto middle = first + (num_elems - 1)/2; std::nth_element(first, middle, last, comparator); - return abs(*middle); + return abs(*middle-center); } else { auto middle = first + num_elems/2 - 1; std::nth_element(first, middle, last, comparator); std::nth_element(middle, middle+1, last, comparator); - return (abs(*middle) + abs(*(middle+1)))/abs(static_cast(2)); + return (abs(*middle-center) + abs(*(middle+1)-center))/abs(static_cast(2)); } } diff --git a/include/boost/math/tools/cohen_acceleration.hpp b/include/boost/math/tools/cohen_acceleration.hpp index 716245f724..2e76a75f8b 100644 --- a/include/boost/math/tools/cohen_acceleration.hpp +++ b/include/boost/math/tools/cohen_acceleration.hpp @@ -23,17 +23,18 @@ auto cohen_acceleration(G& generator, std::int64_t n = -1) using std::pow; using std::ceil; using std::sqrt; + auto n_ = static_cast(n); if (n < 0) { // relative error grows as 2*5.828^-n; take 5.828^-n < eps/4 => -nln(5.828) < ln(eps/4) => n > ln(4/eps)/ln(5.828). // Is there a way to do it rapidly with std::log2? (Yes, of course; but for primitive types it's computed at compile-time anyway.) - n_ = static_cast(ceil(log(4/std::numeric_limits::epsilon())*0.5672963285532555)); + n_ = static_cast(ceil(log(Real(4)/std::numeric_limits::epsilon())*Real(0.5672963285532555))); n = static_cast(n_); } // d can get huge and overflow if you pick n too large: - auto d = static_cast(pow(3 + sqrt(Real(8)), n)); - d = (d + 1/d)/2; + auto d = static_cast(pow(Real(3 + sqrt(Real(8))), n_)); + d = (d + Real(1)/d)/2; Real b = -1; Real c = -d; Real s = 0; diff --git a/include/boost/math/tools/config.hpp b/include/boost/math/tools/config.hpp index a52393e7bb..66e7da52ab 100644 --- a/include/boost/math/tools/config.hpp +++ b/include/boost/math/tools/config.hpp @@ -156,13 +156,27 @@ # endif #endif -#endif +#endif // Standalone config // If attributes are not defined make sure we don't have compiler errors #ifndef BOOST_MATH_MAYBE_UNUSED # define BOOST_MATH_MAYBE_UNUSED #endif +// C++23 +#if __cplusplus > 202002L || _MSVC_LANG > 202002L +# if __GNUC__ >= 13 + // libstdc++3 only defines to/from_chars for std::float128_t when one of these defines are set + // otherwise we're right out of luck... +# if defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128) || defined(_GLIBCXX_HAVE_FLOAT128_MATH) +# include // std::strlen is used with from_chars +# include +# include +# define BOOST_MATH_USE_CHARCONV_FOR_CONVERSION +#endif +# endif +#endif + #include // for min and max #include #include diff --git a/include/boost/math/tools/convert_from_string.hpp b/include/boost/math/tools/convert_from_string.hpp index 4a0a25144c..f6fe08aeeb 100644 --- a/include/boost/math/tools/convert_from_string.hpp +++ b/include/boost/math/tools/convert_from_string.hpp @@ -1,4 +1,5 @@ // Copyright John Maddock 2016. +// Copyright Matt Borland 2023. // Use, modification and distribution are subject to the // Boost Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -10,6 +11,7 @@ #pragma once #endif +#include #include #ifndef BOOST_MATH_STANDALONE #include @@ -26,14 +28,32 @@ namespace boost{ namespace math{ namespace tools{ template Real convert_from_string(const char* p, const std::false_type&) { -#ifdef BOOST_MATH_NO_LEXICAL_CAST + #ifdef BOOST_MATH_NO_LEXICAL_CAST + // This function should not compile, we don't have the necessary functionality to support it: static_assert(sizeof(Real) == 0, "boost.lexical_cast is not supported in standalone mode."); (void)p; // Suppresses -Wunused-parameter return Real(0); -#else + + #elif defined(BOOST_MATH_USE_CHARCONV_FOR_CONVERSION) + + if constexpr (std::is_arithmetic_v) + { + Real v {}; + std::from_chars(p, p + std::strlen(p), v); + + return v; + } + else + { + return boost::lexical_cast(p); + } + + #else + return boost::lexical_cast(p); -#endif + + #endif } template constexpr const char* convert_from_string(const char* p, const std::true_type&) noexcept diff --git a/include/boost/math/tools/luroth_expansion.hpp b/include/boost/math/tools/luroth_expansion.hpp index 6cc6f9abdc..f98594251e 100644 --- a/include/boost/math/tools/luroth_expansion.hpp +++ b/include/boost/math/tools/luroth_expansion.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include diff --git a/include/boost/math/tools/promotion.hpp b/include/boost/math/tools/promotion.hpp index 55ba064c71..68127efb04 100644 --- a/include/boost/math/tools/promotion.hpp +++ b/include/boost/math/tools/promotion.hpp @@ -2,6 +2,7 @@ // Copyright John Maddock 2006. // Copyright Paul A. Bristow 2006. +// Copyright Matt Borland 2023. // Use, modification and distribution are subject to the // Boost Software License, Version 1.0. @@ -25,6 +26,10 @@ #include #include +#if __has_include() +# include +#endif + namespace boost { namespace math @@ -63,6 +68,19 @@ namespace boost template <> struct promote_arg { using type = long double; }; template <> struct promote_arg { using type = double; }; + #ifdef __STDCPP_FLOAT16_T__ + template <> struct promote_arg { using type = std::float16_t; }; + #endif + #ifdef __STDCPP_FLOAT32_T__ + template <> struct promote_arg { using type = std::float32_t; }; + #endif + #ifdef __STDCPP_FLOAT64_T__ + template <> struct promote_arg { using type = std::float64_t; }; + #endif + #ifdef __STDCPP_FLOAT128_T__ + template <> struct promote_arg { using type = std::float128_t; }; + #endif + template using promote_arg_t = typename promote_arg::type; @@ -72,25 +90,52 @@ namespace boost // for both parameter types, if integral promote to double. using T1P = typename promote_arg::type; // T1 perhaps promoted. using T2P = typename promote_arg::type; // T2 perhaps promoted. - - using type = typename std::conditional< + using intermediate_type = typename std::conditional< std::is_floating_point::value && std::is_floating_point::value, // both T1P and T2P are floating-point? +#ifdef __STDCPP_FLOAT128_T__ + typename std::conditional::value || std::is_same::value, // either long double? + std::float128_t, +#endif #ifdef BOOST_MATH_USE_FLOAT128 typename std::conditional::value || std::is_same<__float128, T2P>::value, // either long double? __float128, -#endif +#endif typename std::conditional::value || std::is_same::value, // either long double? long double, // then result type is long double. +#ifdef __STDCPP_FLOAT64_T__ + typename std::conditional::value || std::is_same::value, // either float64? + std::float64_t, // then result type is float64_t. +#endif typename std::conditional::value || std::is_same::value, // either double? double, // result type is double. +#ifdef __STDCPP_FLOAT32_T__ + typename std::conditional::value || std::is_same::value, // either float32? + std::float32_t, // then result type is float32_t. +#endif float // else result type is float. >::type #ifdef BOOST_MATH_USE_FLOAT128 >::type +#endif +#ifdef __STDCPP_FLOAT128_T__ + >::type +#endif +#ifdef __STDCPP_FLOAT64_T__ + >::type +#endif +#ifdef __STDCPP_FLOAT32_T__ + >::type #endif >::type, // else one or the other is a user-defined type: typename std::conditional::value && std::is_convertible::value, T2P, T1P>::type>::type; + +#ifdef __STDCPP_FLOAT64_T__ + // If long doubles are doubles then we should prefer to use std::float64_t when available + using type = std::conditional_t<(sizeof(double) == sizeof(long double) && std::is_same::value), std::float64_t, intermediate_type>; +#else + using type = intermediate_type; +#endif }; // promote_arg2 // These full specialisations reduce std::conditional usage and speed up // compilation: @@ -111,6 +156,88 @@ namespace boost template <> struct promote_args_2 { using type = long double; }; template <> struct promote_args_2 { using type = long double; }; + #ifdef __STDCPP_FLOAT128_T__ + template <> struct promote_args_2 { using type = std::float128_t; }; + template <> struct promote_args_2 { using type = std::float128_t; }; + template <> struct promote_args_2 { using type = std::float128_t; }; + template <> struct promote_args_2 { using type = std::float128_t; }; + template <> struct promote_args_2 { using type = std::float128_t; }; + template <> struct promote_args_2 { using type = std::float128_t; }; + template <> struct promote_args_2 { using type = std::float128_t; }; + template <> struct promote_args_2 { using type = std::float128_t; }; + + #ifdef __STDCPP_FLOAT16_T__ + template <> struct promote_args_2 { using type = std::float128_t; }; + template <> struct promote_args_2 { using type = std::float128_t; }; + #endif + + #ifdef __STDCPP_FLOAT32_T__ + template <> struct promote_args_2 { using type = std::float128_t; }; + template <> struct promote_args_2 { using type = std::float128_t; }; + #endif + + #ifdef __STDCPP_FLOAT64_T__ + template <> struct promote_args_2 { using type = std::float128_t; }; + template <> struct promote_args_2 { using type = std::float128_t; }; + #endif + + template <> struct promote_args_2 { using type = std::float128_t; }; + #endif + + #ifdef __STDCPP_FLOAT64_T__ + template <> struct promote_args_2 { using type = std::float64_t; }; + template <> struct promote_args_2 { using type = std::float64_t; }; + template <> struct promote_args_2 { using type = std::float64_t; }; + template <> struct promote_args_2 { using type = std::float64_t; }; + template <> struct promote_args_2 { using type = std::float64_t; }; + template <> struct promote_args_2 { using type = std::float64_t; }; + template <> struct promote_args_2 { using type = long double; }; + template <> struct promote_args_2 { using type = long double; }; + + #ifdef __STDCPP_FLOAT16_T__ + template <> struct promote_args_2 { using type = std::float64_t; }; + template <> struct promote_args_2 { using type = std::float64_t; }; + #endif + + #ifdef __STDCPP_FLOAT32_T__ + template <> struct promote_args_2 { using type = std::float64_t; }; + template <> struct promote_args_2 { using type = std::float64_t; }; + #endif + + template <> struct promote_args_2 { using type = std::float64_t; }; + #endif + + #ifdef __STDCPP_FLOAT32_T__ + template <> struct promote_args_2 { using type = std::float32_t; }; + template <> struct promote_args_2 { using type = std::float32_t; }; + template <> struct promote_args_2 { using type = std::float32_t; }; + template <> struct promote_args_2 { using type = std::float32_t; }; + template <> struct promote_args_2 { using type = double; }; + template <> struct promote_args_2 { using type = double; }; + template <> struct promote_args_2 { using type = long double; }; + template <> struct promote_args_2 { using type = long double; }; + + #ifdef __STDCPP_FLOAT16_T__ + template <> struct promote_args_2 { using type = std::float32_t; }; + template <> struct promote_args_2 { using type = std::float32_t; }; + #endif + + template <> struct promote_args_2 { using type = std::float32_t; }; + #endif + + #ifdef __STDCPP_FLOAT16_T__ + template <> struct promote_args_2 { using type = std::float16_t; }; + template <> struct promote_args_2 { using type = std::float16_t; }; + template <> struct promote_args_2 { using type = float; }; + template <> struct promote_args_2 { using type = float; }; + template <> struct promote_args_2 { using type = double; }; + template <> struct promote_args_2 { using type = double; }; + template <> struct promote_args_2 { using type = long double; }; + template <> struct promote_args_2 { using type = long double; }; + + template <> struct promote_args_2 { using type = std::float16_t; }; + #endif + template using promote_args_2_t = typename promote_args_2::type; diff --git a/include/boost/math/tools/series.hpp b/include/boost/math/tools/series.hpp index 1809dfab11..a4822fea43 100644 --- a/include/boost/math/tools/series.hpp +++ b/include/boost/math/tools/series.hpp @@ -131,7 +131,7 @@ inline typename Functor::result_type kahan_sum_series(Functor& func, int bits) n typedef typename Functor::result_type result_type; - result_type factor = pow(result_type(2), bits); + result_type factor = pow(result_type(2), result_type(bits)); result_type result = func(); result_type next_term, y, t; result_type carry = 0; diff --git a/include/boost/math/tools/simple_continued_fraction.hpp b/include/boost/math/tools/simple_continued_fraction.hpp index 0fe17fc59d..790f98462e 100644 --- a/include/boost/math/tools/simple_continued_fraction.hpp +++ b/include/boost/math/tools/simple_continued_fraction.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include diff --git a/meta/libraries.json b/meta/libraries.json index 31c0994f87..617de2df04 100644 --- a/meta/libraries.json +++ b/meta/libraries.json @@ -5,82 +5,15 @@ "authors": [ "various" ], - "description": "Boost.Math includes several contributions in the domain of mathematics: The Greatest Common Divisor and Least Common Multiple library provides run-time and compile-time evaluation of the greatest common divisor (GCD) or least common multiple (LCM) of two integers. The Special Functions library currently provides eight templated special functions, in namespace boost. The Complex Number Inverse Trigonometric Functions are the inverses of trigonometric functions currently present in the C++ standard. Quaternions are a relative of complex numbers often used to parameterise rotations in three dimensional space. Octonions, like quaternions, are a relative of complex numbers.", + "description": "Boost.Math includes several contributions in the domain of mathematics: Floating Point Utilities, Specific Width Floating Point Types, Mathematical Constants, Statistical Distributions, Special Functions, Root Finding and Function Minimization, Polynomials and Rational Functions, Interpolation, and Numerical Integration and Differentiation. Many of these features are templated to support both built-in, and extended width types (e.g. Boost.Multiprecision)", "category": [ "Math" ], "maintainers": [ - "Hubert Holin ", - "John Maddock " - ], - "cxxstd": "14" - }, - { - "key": "math/common_factor", - "name": "Math Common Factor", - "authors": [ - "Daryle Walker" - ], - "description": "Greatest common divisor and least common multiple.", - "documentation": "doc/html/gcd_lcm.html", - "category": [ - "Math" - ], - "cxxstd": "14" - }, - { - "key": "math/octonion", - "name": "Math Octonion", - "authors": [ - "Hubert Holin" - ], - "description": "Octonions.", - "documentation": "doc/html/octonions.html", - "category": [ - "Math" - ], - "cxxstd": "14" - }, - { - "key": "math/quaternion", - "name": "Math Quaternion", - "authors": [ - "Hubert Holin" - ], - "description": "Quaternions.", - "documentation": "doc/html/quaternions.html", - "category": [ - "Math" - ], - "cxxstd": "14" - }, - { - "key": "math/special_functions", - "name": "Math/Special Functions", - "authors": [ - "John Maddock", - "Paul Bristow", - "Hubert Holin", - "Xiaogang Zhang" - ], - "description": "A wide selection of mathematical special functions.", - "documentation": "doc/html/special.html", - "category": [ - "Math" - ], - "cxxstd": "14" - }, - { - "key": "math/statistical_distributions", - "name": "Math/Statistical Distributions", - "authors": [ - "John Maddock", - "Paul Bristow" - ], - "description": "A wide selection of univariate statistical distributions and functions that operate on them.", - "documentation": "doc/html/dist.html", - "category": [ - "Math" + "John Maddock ", + "Chris Kormanyos ", + "Nick Thompson ", + "Matt Borland " ], "cxxstd": "14" } diff --git a/reporting/performance/fourier_transform_daubechies_performance.cpp b/reporting/performance/fourier_transform_daubechies_performance.cpp new file mode 100644 index 0000000000..a0aa3afb0b --- /dev/null +++ b/reporting/performance/fourier_transform_daubechies_performance.cpp @@ -0,0 +1,51 @@ +// (C) Copyright Nick Thompson 2023. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include +#include +#include + +using boost::math::fourier_transform_daubechies_scaling; + +template +void FourierTransformDaubechiesScaling(benchmark::State& state) +{ + std::random_device rd; + auto seed = rd(); + std::mt19937_64 mt(seed); + std::uniform_real_distribution unif(0, 10); + + for (auto _ : state) + { + benchmark::DoNotOptimize(fourier_transform_daubechies_scaling(unif(mt))); + } +} +BENCHMARK_TEMPLATE(FourierTransformDaubechiesScaling, float, 1); +BENCHMARK_TEMPLATE(FourierTransformDaubechiesScaling, float, 2); +BENCHMARK_TEMPLATE(FourierTransformDaubechiesScaling, float, 3); +BENCHMARK_TEMPLATE(FourierTransformDaubechiesScaling, float, 4); +BENCHMARK_TEMPLATE(FourierTransformDaubechiesScaling, float, 5); +BENCHMARK_TEMPLATE(FourierTransformDaubechiesScaling, float, 6); +BENCHMARK_TEMPLATE(FourierTransformDaubechiesScaling, float, 7); +BENCHMARK_TEMPLATE(FourierTransformDaubechiesScaling, float, 8); +BENCHMARK_TEMPLATE(FourierTransformDaubechiesScaling, float, 9); +BENCHMARK_TEMPLATE(FourierTransformDaubechiesScaling, float, 10); + +BENCHMARK_TEMPLATE(FourierTransformDaubechiesScaling, double, 1); +BENCHMARK_TEMPLATE(FourierTransformDaubechiesScaling, double, 2); +BENCHMARK_TEMPLATE(FourierTransformDaubechiesScaling, double, 3); +BENCHMARK_TEMPLATE(FourierTransformDaubechiesScaling, double, 4); +BENCHMARK_TEMPLATE(FourierTransformDaubechiesScaling, double, 5); +BENCHMARK_TEMPLATE(FourierTransformDaubechiesScaling, double, 6); +BENCHMARK_TEMPLATE(FourierTransformDaubechiesScaling, double, 7); +BENCHMARK_TEMPLATE(FourierTransformDaubechiesScaling, double, 8); +BENCHMARK_TEMPLATE(FourierTransformDaubechiesScaling, double, 9); +BENCHMARK_TEMPLATE(FourierTransformDaubechiesScaling, double, 10); + + +BENCHMARK_MAIN(); diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 487578b574..7885649f71 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -882,6 +882,7 @@ test-suite distribution_tests : [ run compile_test/dist_arcsine_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] [ compile compile_test/dist_empirical_cumulative_dist_func_incl_test.cpp : [ requires cxx17_if_constexpr cxx17_std_apply ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] [ run compile_test/dist_inv_gaussian_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_promote_args.cpp : [ requires cpp_lib_type_trait_variable_templates ] ] [ run test_legacy_nonfinite.cpp ../../test/build//boost_unit_test_framework ] [ run test_basic_nonfinite.cpp ../../test/build//boost_unit_test_framework ] @@ -903,6 +904,12 @@ test-suite distribution_tests : [ run scipy_issue_18511.cpp ../../test/build//boost_unit_test_framework ] ; +test-suite new_floats : + [ compile compile_test/float32.cpp ] + [ compile compile_test/float64.cpp ] + [ compile compile_test/float128.cpp ] +; + test-suite mp : [ run test_nc_t_quad.cpp pch ../../test/build//boost_unit_test_framework : : : release [ check-target-builds ../config//has_float128 "GCC libquadmath and __float128 support" : -lquadmath ] ] @@ -1220,6 +1227,7 @@ test-suite interpolators : [ run gegenbauer_test.cpp : : : [ requires cxx11_auto_declarations cxx11_constexpr cxx11_smart_ptr cxx11_defaulted_functions ] [ check-target-builds ../config//has_float128 "GCC libquadmath and __float128 support" : -lquadmath ] ] [ run daubechies_scaling_test.cpp : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj [ requires cxx17_if_constexpr cxx17_std_apply ] [ check-target-builds ../config//has_float128 "GCC libquadmath and __float128 support" : -lquadmath ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] [ check-target-builds ../config//is_cygwin_run "Cygwin CI run" : no ] ] [ run daubechies_wavelet_test.cpp : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj [ requires cxx17_if_constexpr cxx17_std_apply ] [ check-target-builds ../config//has_float128 "GCC libquadmath and __float128 support" : -lquadmath ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] [ check-target-builds ../config//is_cygwin_run "Cygwin CI run" : no ] ] + [ run fourier_transform_daubechies_test.cpp : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj [ requires cxx17_if_constexpr cxx17_std_apply ] [ check-target-builds ../config//has_float128 "GCC libquadmath and __float128 support" : -lquadmath ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] [ check-target-builds ../config//is_cygwin_run "Cygwin CI run" : no ] ] [ run wavelet_transform_test.cpp : : : msvc:/bigobj [ requires cxx17_if_constexpr cxx17_std_apply ] [ check-target-builds ../config//has_float128 "GCC libquadmath and __float128 support" : -lquadmath ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] [ run agm_test.cpp : : : msvc:/bigobj [ requires cxx17_if_constexpr cxx17_std_apply ] [ check-target-builds ../config//has_float128 "GCC libquadmath and __float128 support" : -lquadmath ] ] [ run rsqrt_test.cpp : : : msvc:/bigobj [ requires cxx17_if_constexpr cxx17_std_apply ] [ check-target-builds ../config//has_float128 "GCC libquadmath and __float128 support" : -lquadmath ] ] diff --git a/test/adaptive_gauss_kronrod_quadrature_test.cpp b/test/adaptive_gauss_kronrod_quadrature_test.cpp index 04cefb9e10..f2c703e92a 100644 --- a/test/adaptive_gauss_kronrod_quadrature_test.cpp +++ b/test/adaptive_gauss_kronrod_quadrature_test.cpp @@ -9,6 +9,10 @@ #include #include +#if __has_include() +# include +#endif + #if !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) && !defined(BOOST_NO_SFINAE_EXPR) #include @@ -258,6 +262,17 @@ BOOST_AUTO_TEST_CASE(gauss_quadrature_test) test_integration_over_real_line(); test_right_limit_infinite(); test_left_limit_infinite(); + + #ifdef __STDCPP_FLOAT64_T__ + test_linear(); + test_quadratic(); + test_ca(); + test_three_quadrature_schemes_examples(); + test_integration_over_real_line(); + test_right_limit_infinite(); + test_left_limit_infinite(); + #endif + #endif #ifdef TEST1A #if LDBL_MANT_DIG < 100 // If we have too many digits in a long double, we get build errors due to a constexpr issue. diff --git a/test/agm_test.cpp b/test/agm_test.cpp index 6013d5cdbf..623a6d88e8 100644 --- a/test/agm_test.cpp +++ b/test/agm_test.cpp @@ -13,6 +13,11 @@ #include #include #include + +#if __has_include() +# include +#endif + #ifdef BOOST_HAS_FLOAT128 #include using boost::multiprecision::float128; @@ -91,13 +96,24 @@ void test_scaling() int main() { + #ifdef __STDCPP_FLOAT32_T__ + test_gauss_constant(); + test_scaling(); + #else test_gauss_constant(); - test_gauss_constant(); - test_gauss_constant(); - test_scaling(); + #endif + + #ifdef __STDCPP_FLOAT64_T__ + test_scaling(); + test_gauss_constant(); + #else test_scaling(); + test_gauss_constant(); + #endif + test_scaling(); + test_gauss_constant(); #ifdef BOOST_HAS_FLOAT128 test_gauss_constant(); diff --git a/test/bezier_polynomial_test.cpp b/test/bezier_polynomial_test.cpp index 4e7a11748c..05ee13ecf8 100644 --- a/test/bezier_polynomial_test.cpp +++ b/test/bezier_polynomial_test.cpp @@ -18,14 +18,18 @@ using boost::multiprecision::float128; #endif +#if __has_include() +# include +#endif + using boost::math::interpolators::bezier_polynomial; template void test_linear() { std::vector> control_points(2); - control_points[0] = {0.0, 0.0}; - control_points[1] = {1.0, 1.0}; + control_points[0] = {Real(0), Real(0)}; + control_points[1] = {Real(1), Real(1)}; auto control_points_copy = control_points; auto bp = bezier_polynomial(std::move(control_points_copy)); @@ -54,9 +58,9 @@ template void test_quadratic() { std::vector> control_points(3); - control_points[0] = {0.0, 0.0}; - control_points[1] = {1.0, 1.0}; - control_points[2] = {2.0, 2.0}; + control_points[0] = {Real(0), Real(0)}; + control_points[1] = {Real(1), Real(1)}; + control_points[2] = {Real(2), Real(2)}; auto control_points_copy = control_points; auto bp = bezier_polynomial(std::move(control_points_copy)); @@ -79,10 +83,10 @@ template void test_convex_hull() { std::vector> control_points(4); - control_points[0] = {0.0, 0.0}; - control_points[1] = {0.0, 1.0}; - control_points[2] = {1.0, 1.0}; - control_points[3] = {1.0, 0.0}; + control_points[0] = {Real(0), Real(0)}; + control_points[1] = {Real(0), Real(1)}; + control_points[2] = {Real(1), Real(1)}; + control_points[3] = {Real(1), Real(0)}; auto bp = bezier_polynomial(std::move(control_points)); for (Real t = 0; t <= 1; t += Real(1)/32) { @@ -133,9 +137,9 @@ void test_reversal_symmetry() CHECK_ULP_CLOSE(control_points.back()[1], P1[1], 3); CHECK_ULP_CLOSE(control_points.back()[2], P1[2], 3); - for (Real t = 0; t <= 1; t += 1.0) { + for (Real t = 0; t <= 1; t += Real(1.0)) { auto P0 = bp0(t); - auto P1 = bp1(1.0-t); + auto P1 = bp1(Real(1.0)-t); if (!CHECK_ULP_CLOSE(P0[0], P1[0], 3)) { std::cerr << " Error at t = " << t << "\n"; } @@ -184,21 +188,40 @@ void test_linear_precision() int main() { + #ifdef __STDCPP_FLOAT32_T__ + test_linear(); + test_quadratic(); + test_convex_hull(); + test_linear_precision(); + test_reversal_symmetry(); + #else test_linear(); - test_linear(); test_quadratic(); - test_quadratic(); test_convex_hull(); - test_convex_hull(); test_linear_precision(); - test_linear_precision(); test_reversal_symmetry(); + #endif + + #ifdef __STDCPP_FLOAT64_T__ + test_linear(); + test_quadratic(); + test_convex_hull(); + test_linear_precision(); + test_reversal_symmetry(); + #else + test_linear(); + test_quadratic(); + test_convex_hull(); + test_linear_precision(); test_reversal_symmetry(); -#ifdef BOOST_HAS_FLOAT128 + #endif + + #ifdef BOOST_HAS_FLOAT128 test_linear(); test_quadratic(); test_convex_hull(); -#endif + #endif + return boost::math::test::report_errors(); } diff --git a/test/bilinear_uniform_test.cpp b/test/bilinear_uniform_test.cpp index fb1d3d502e..f592c1a84a 100644 --- a/test/bilinear_uniform_test.cpp +++ b/test/bilinear_uniform_test.cpp @@ -16,6 +16,10 @@ using boost::multiprecision::float128; #endif +#if __has_include() +# include +#endif + using boost::math::interpolators::bilinear_uniform; template @@ -25,7 +29,7 @@ void test_four_values() Real y0 = 0; Real dx = 1; Real dy = 1; - Real value = 1.5; + Real value = Real(1.5); std::vector v(2*2, value); auto v_copy = v; auto ub = bilinear_uniform(std::move(v_copy), 2, 2, dx, dy, x0, y0); @@ -101,9 +105,21 @@ void test_linear() int main() { + #ifdef __STDCPP_FLOAT32_T__ + test_four_values(); + #else test_four_values(); + #endif + + #ifdef __STDCPP_FLOAT64_T__ + test_four_values(); + test_linear(); + #else test_four_values(); - test_four_values(); test_linear(); + #endif + + test_four_values(); + return boost::math::test::report_errors(); } diff --git a/test/cardinal_cubic_b_spline_test.cpp b/test/cardinal_cubic_b_spline_test.cpp index 9dcef343b2..90452d6e5d 100644 --- a/test/cardinal_cubic_b_spline_test.cpp +++ b/test/cardinal_cubic_b_spline_test.cpp @@ -14,8 +14,13 @@ #include #include #include +#include #include +#if __has_include() +# include +#endif + using boost::multiprecision::cpp_bin_float_50; using boost::math::constants::third; using boost::math::constants::half; @@ -26,12 +31,12 @@ void test_b3_spline() std::cout << "Testing evaluation of spline basis functions on type " << boost::typeindex::type_id().pretty_name() << "\n"; // Outside the support: Real eps = std::numeric_limits::epsilon(); - BOOST_CHECK_SMALL(boost::math::interpolators::detail::b3_spline(2.5), (Real) 0); - BOOST_CHECK_SMALL(boost::math::interpolators::detail::b3_spline(-2.5), (Real) 0); - BOOST_CHECK_SMALL(boost::math::interpolators::detail::b3_spline_prime(2.5), (Real) 0); - BOOST_CHECK_SMALL(boost::math::interpolators::detail::b3_spline_prime(-2.5), (Real) 0); - BOOST_CHECK_SMALL(boost::math::interpolators::detail::b3_spline_double_prime(2.5), (Real) 0); - BOOST_CHECK_SMALL(boost::math::interpolators::detail::b3_spline_double_prime(-2.5), (Real) 0); + BOOST_CHECK_SMALL(boost::math::interpolators::detail::b3_spline(Real(2.5)), (Real) 0); + BOOST_CHECK_SMALL(boost::math::interpolators::detail::b3_spline(Real(-2.5)), (Real) 0); + BOOST_CHECK_SMALL(boost::math::interpolators::detail::b3_spline_prime(Real(2.5)), (Real) 0); + BOOST_CHECK_SMALL(boost::math::interpolators::detail::b3_spline_prime(Real(-2.5)), (Real) 0); + BOOST_CHECK_SMALL(boost::math::interpolators::detail::b3_spline_double_prime(Real(2.5)), (Real) 0); + BOOST_CHECK_SMALL(boost::math::interpolators::detail::b3_spline_double_prime(Real(-2.5)), (Real) 0); // On the boundary of support: @@ -52,7 +57,7 @@ void test_b3_spline() // Properties: B3 is an even function, B3' is an odd function. for (size_t i = 1; i < 200; ++i) { - Real arg = i*0.01; + Real arg = i*Real(0.01); BOOST_CHECK_CLOSE(boost::math::interpolators::detail::b3_spline(arg), boost::math::interpolators::detail::b3_spline(arg), eps); BOOST_CHECK_CLOSE(boost::math::interpolators::detail::b3_spline_prime(-arg), -boost::math::interpolators::detail::b3_spline_prime(arg), eps); BOOST_CHECK_CLOSE(boost::math::interpolators::detail::b3_spline_double_prime(-arg), boost::math::interpolators::detail::b3_spline_double_prime(arg), eps); @@ -76,8 +81,8 @@ void test_interpolation_condition() v[i] = dis(gen); } - Real step = 0.01; - Real a = 5; + Real step = static_cast(0.01); + Real a = Real(5); boost::math::interpolators::cardinal_cubic_b_spline spline(v.data(), v.size(), a, step); for (size_t i = 0; i < v.size(); ++i) @@ -99,21 +104,21 @@ void test_constant_function() Real constant = 50.2; for (size_t i = 0; i < v.size(); ++i) { - v[i] = 50.2; + v[i] = Real(50.2); } - Real step = 0.02; + Real step = static_cast(0.02); Real a = 5; boost::math::interpolators::cardinal_cubic_b_spline spline(v.data(), v.size(), a, step); for (size_t i = 0; i < v.size(); ++i) { // Do not test at interpolation point; we already know it works there: - Real y = spline(i*step + a + 0.001); + Real y = spline(i*step + a + Real(0.001)); BOOST_CHECK_CLOSE(y, constant, 10*std::numeric_limits::epsilon()); - Real y_prime = spline.prime(i*step + a + 0.002); + Real y_prime = spline.prime(i*step + a + Real(0.002)); BOOST_CHECK_SMALL(y_prime, 5000*std::numeric_limits::epsilon()); - Real y_double_prime = spline.double_prime(i*step + a + 0.002); + Real y_double_prime = spline.double_prime(i*step + a + Real(0.002)); BOOST_CHECK_SMALL(y_double_prime, 5000*std::numeric_limits::epsilon()); } @@ -123,9 +128,9 @@ void test_constant_function() for (size_t i = 0; i < v.size(); ++i) { - Real y = spline(i*step + a + 0.002); + Real y = spline(i*step + a + Real(0.002)); BOOST_CHECK_CLOSE(y, constant, std::numeric_limits::epsilon()); - Real y_prime = spline.prime(i*step + a + 0.002); + Real y_prime = spline.prime(i*step + a + Real(0.002)); BOOST_CHECK_SMALL(y_prime, std::numeric_limits::epsilon()); } @@ -137,9 +142,9 @@ void test_constant_function() for (size_t i = 0; i < v.size(); ++i) { // Do not test at interpolation point; we already know it works there: - Real y = spline2(i*step + a + 0.001); + Real y = spline2(i*step + a + Real(0.001)); BOOST_CHECK_CLOSE(y, constant, 10 * std::numeric_limits::epsilon()); - Real y_prime = spline2.prime(i*step + a + 0.002); + Real y_prime = spline2.prime(i*step + a + Real(0.002)); BOOST_CHECK_SMALL(y_prime, 5000 * std::numeric_limits::epsilon()); } @@ -148,9 +153,9 @@ void test_constant_function() for (size_t i = 0; i < v.size(); ++i) { - Real y = spline2(i*step + a + 0.002); + Real y = spline2(i*step + a + Real(0.002)); BOOST_CHECK_CLOSE(y, constant, std::numeric_limits::epsilon()); - Real y_prime = spline2.prime(i*step + a + 0.002); + Real y_prime = spline2.prime(i*step + a + Real(0.002)); BOOST_CHECK_SMALL(y_prime, std::numeric_limits::epsilon()); } } @@ -164,7 +169,7 @@ void test_affine_function() std::vector v(500); Real a = 10; Real b = 8; - Real step = 0.005; + Real step = static_cast(0.005); auto f = [a, b](Real x) { return a*x + b; }; for (size_t i = 0; i < v.size(); ++i) @@ -176,7 +181,7 @@ void test_affine_function() for (size_t i = 0; i < v.size() - 1; ++i) { - Real arg = i*step + 0.0001; + Real arg = static_cast(i*step + Real(0.0001)); Real y = spline(arg); BOOST_CHECK_CLOSE(y, f(arg), sqrt(std::numeric_limits::epsilon())); Real y_prime = spline.prime(arg); @@ -188,7 +193,7 @@ void test_affine_function() for (size_t i = 0; i < v.size() - 1; ++i) { - Real arg = i*step + 0.0001; + Real arg = static_cast(i*step + Real(0.0001)); Real y = spline(arg); BOOST_CHECK_CLOSE(y, f(arg), sqrt(std::numeric_limits::epsilon())); Real y_prime = spline.prime(arg); @@ -203,10 +208,10 @@ void test_quadratic_function() using std::sqrt; std::cout << "Testing that quadratic functions are interpolated correctly by cubic b splines on type " << boost::typeindex::type_id().pretty_name() << "\n"; std::vector v(500); - Real a = 1.2; - Real b = -3.4; - Real c = -8.6; - Real step = 0.01; + Real a = static_cast(1.2); + Real b = static_cast(-3.4); + Real c = static_cast(-8.6); + Real step = static_cast(0.01); auto f = [a, b, c](Real x) { return a*x*x + b*x + c; }; for (size_t i = 0; i < v.size(); ++i) @@ -218,11 +223,11 @@ void test_quadratic_function() for (size_t i = 0; i < v.size() -1; ++i) { - Real arg = i*step + 0.001; + Real arg = static_cast(i*step + Real(0.001)); Real y = spline(arg); - BOOST_CHECK_CLOSE(y, f(arg), 0.1); + BOOST_CHECK_CLOSE(y, f(arg), Real(0.1)); Real y_prime = spline.prime(arg); - BOOST_CHECK_CLOSE(y_prime, 2*a*arg + b, 2.0); + BOOST_CHECK_CLOSE(y_prime, 2*a*arg + b, Real(2.0)); } } @@ -233,9 +238,9 @@ void test_circ_conic_function() using std::sqrt; std::cout << "Testing that conic section of a circle is interpolated correctly by cubic b splines on type " << boost::typeindex::type_id().pretty_name() << '\n'; std::vector v(500); - Real cv = 0.1; - Real w = 2.0; - Real step = 2 * w / (v.size() - 1); + Real cv = Real(0.1); + Real w = Real(2.0); + Real step = Real(2 * w / (v.size() - 1)); auto f = [cv](Real x) { return cv * x * x / (1 + sqrt(1 - cv * cv * x * x)); }; auto df = [cv](Real x) { return cv * x / sqrt(1 - cv * cv * x * x); }; @@ -256,11 +261,11 @@ void test_circ_conic_function() for (size_t i = 0; i < v.size() - 1; ++i) { - Real arg = -w + i * step + 0.001; + Real arg = -w + i * step + Real(0.001); Real y = spline(arg); - BOOST_CHECK_CLOSE(y, f(arg), 2.0); + BOOST_CHECK_CLOSE(y, f(arg), Real(2.0)); Real y_prime = spline.prime(arg); - BOOST_CHECK_CLOSE(y_prime, df(arg), 1.0); + BOOST_CHECK_CLOSE(y_prime, df(arg), Real(1.0)); } } @@ -272,7 +277,7 @@ void test_trig_function() std::mt19937 gen; std::vector v(500); Real x0 = 1; - Real step = 0.125; + Real step = Real(0.125); for (size_t i = 0; i < v.size(); ++i) { @@ -287,9 +292,9 @@ void test_trig_function() { Real x = abscissa(gen); Real y = spline(x); - BOOST_CHECK_CLOSE(y, sin(x), 1.0); + BOOST_CHECK_CLOSE(y, Real(sin(x)), Real(1.0)); auto y_prime = spline.prime(x); - BOOST_CHECK_CLOSE(y_prime, cos(x), 2.0); + BOOST_CHECK_CLOSE(y_prime, Real(cos(x)), Real(2.0)); } } @@ -299,7 +304,8 @@ void test_copy_move() std::cout << "Testing that copy/move operation succeed on cubic b spline\n"; std::vector v(500); Real x0 = 1; - Real step = 0.125; + Real step = static_cast(0.125); + constexpr Real tol = Real(0.01); for (size_t i = 0; i < v.size(); ++i) { @@ -312,22 +318,22 @@ void test_copy_move() // Default constructor should compile so that splines can be member variables: boost::math::interpolators::cardinal_cubic_b_spline d; d = boost::math::interpolators::cardinal_cubic_b_spline(v.data(), v.size(), x0, step); - BOOST_CHECK_CLOSE(d(x0), sin(x0), 0.01); + BOOST_CHECK_CLOSE(d(x0), Real(sin(x0)), tol); // Passing to lambda should compile: auto f = [=](Real x) { return d(x); }; // Make sure this variable is used. - BOOST_CHECK_CLOSE(f(x0), sin(x0), 0.01); + BOOST_CHECK_CLOSE(f(x0), Real(sin(x0)), tol); // Move operations should compile. auto s = std::move(spline); // Copy operations should compile: boost::math::interpolators::cardinal_cubic_b_spline c = d; - BOOST_CHECK_CLOSE(c(x0), sin(x0), 0.01); + BOOST_CHECK_CLOSE(c(x0), Real(sin(x0)), tol); // Test with std::bind: - auto h = std::bind(&boost::math::interpolators::cardinal_cubic_b_spline::operator(), &s, std::placeholders::_1); - BOOST_CHECK_CLOSE(h(x0), sin(x0), 0.01); + auto h = std::bind(&boost::math::interpolators::cardinal_cubic_b_spline::operator(), &s, std::placeholders::_1); + BOOST_CHECK_CLOSE(h(x0), Real(sin(x0)), tol); } template @@ -336,7 +342,7 @@ void test_outside_interval() std::cout << "Testing that the spline can be evaluated outside the interpolation interval\n"; std::vector v(400); Real x0 = 1; - Real step = 0.125; + Real step = Real(0.125); for (size_t i = 0; i < v.size(); ++i) { @@ -354,54 +360,70 @@ void test_outside_interval() BOOST_AUTO_TEST_CASE(test_cubic_b_spline) { + #ifdef __STDCPP_FLOAT32_T__ + + test_b3_spline(); + test_interpolation_condition(); + test_constant_function(); + test_affine_function(); + test_quadratic_function(); + test_circ_conic_function(); + test_trig_function(); + + #else + test_b3_spline(); - test_b3_spline(); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - test_b3_spline(); -#endif - test_b3_spline(); - test_interpolation_condition(); - test_interpolation_condition(); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - test_interpolation_condition(); -#endif - test_interpolation_condition(); - test_constant_function(); - test_constant_function(); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - test_constant_function(); -#endif - test_constant_function(); - test_affine_function(); - test_affine_function(); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - test_affine_function(); -#endif - test_affine_function(); - test_quadratic_function(); - test_quadratic_function(); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - test_quadratic_function(); -#endif - test_quadratic_function(); - test_circ_conic_function(); - test_circ_conic_function(); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - test_circ_conic_function(); -#endif - test_trig_function(); - test_trig_function(); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - test_trig_function(); -#endif - test_trig_function(); + #endif + + #ifdef __STDCPP_FLOAT64_T__ + + test_b3_spline(); + test_interpolation_condition(); + test_constant_function(); + test_affine_function(); + test_quadratic_function(); + test_circ_conic_function(); + test_trig_function(); + test_copy_move(); + test_outside_interval(); + + #else + + test_b3_spline(); + test_interpolation_condition(); + test_constant_function(); + test_affine_function(); + test_quadratic_function(); + test_circ_conic_function(); + test_trig_function(); test_copy_move(); test_outside_interval(); + + #endif + + #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + + test_b3_spline(); + test_interpolation_condition(); + test_constant_function(); + test_affine_function(); + test_quadratic_function(); + test_circ_conic_function(); + test_trig_function(); + + #endif + + test_b3_spline(); + test_interpolation_condition(); + test_constant_function(); + test_affine_function(); + test_quadratic_function(); + test_trig_function(); } diff --git a/test/cardinal_quadratic_b_spline_test.cpp b/test/cardinal_quadratic_b_spline_test.cpp index 6f9637d242..3955d4f572 100644 --- a/test/cardinal_quadratic_b_spline_test.cpp +++ b/test/cardinal_quadratic_b_spline_test.cpp @@ -6,15 +6,22 @@ */ #include "math_unit_test.hpp" +#include #include #include +#include +#include #include using boost::math::interpolators::cardinal_quadratic_b_spline; +#if __has_include() +# include +#endif + template void test_constant() { - Real c = 7.2; + Real c = Real(7.2); Real t0 = 0; Real h = Real(1)/Real(16); size_t n = 512; @@ -44,8 +51,8 @@ void test_constant() template void test_linear() { - Real m = 8.3; - Real b = 7.2; + Real m = Real(8.3); + Real b = Real(7.2); Real t0 = 0; Real h = Real(1)/Real(16); size_t n = 512; @@ -79,9 +86,9 @@ void test_linear() template void test_quadratic() { - Real a = 8.2; - Real b = 7.2; - Real c = -9.2; + Real a = Real(8.2); + Real b = Real(7.2); + Real c = Real(-9.2); Real t0 = 0; Real h = Real(1)/Real(16); size_t n = 513; @@ -115,21 +122,29 @@ void test_quadratic() int main() { + #ifdef __STDCPP_FLOAT32_T__ + test_constant(); + test_linear(); + #else test_constant(); - test_constant(); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - test_constant(); -#endif - test_linear(); - test_linear(); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - test_linear(); -#endif + #endif + #ifdef __STDCPP_FLOAT64_T__ + test_constant(); + test_linear(); + test_quadratic(); + #else + test_constant(); + test_linear(); test_quadratic(); + #endif + #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + test_constant(); + test_linear(); test_quadratic(); #endif + return boost::math::test::report_errors(); } diff --git a/test/cardinal_quintic_b_spline_test.cpp b/test/cardinal_quintic_b_spline_test.cpp index de2d87f15d..7ab3a28924 100644 --- a/test/cardinal_quintic_b_spline_test.cpp +++ b/test/cardinal_quintic_b_spline_test.cpp @@ -6,8 +6,11 @@ */ #include "math_unit_test.hpp" +#include #include #include +#include +#include #include #ifdef BOOST_HAS_FLOAT128 #include @@ -15,10 +18,14 @@ using boost::multiprecision::float128; #endif using boost::math::interpolators::cardinal_quintic_b_spline; +#if __has_include() +# include +#endif + template void test_constant() { - Real c = 7.5; + Real c = Real(7.5); Real t0 = 0; Real h = Real(1)/Real(16); size_t n = 513; @@ -53,7 +60,7 @@ void test_constant() template void test_constant_estimate_derivatives() { - Real c = 7.5; + Real c = Real(7.5); Real t0 = 0; Real h = Real(1)/Real(16); size_t n = 513; @@ -88,8 +95,8 @@ template void test_linear() { using std::abs; - Real m = 8.3; - Real b = 7.2; + Real m = Real(8.3); + Real b = Real(7.2); Real t0 = 0; Real h = Real(1)/Real(16); size_t n = 512; @@ -137,8 +144,8 @@ template void test_linear_estimate_derivatives() { using std::abs; - Real m = 8.3; - Real b = 7.2; + Real m = Real(8.3); + Real b = Real(7.2); Real t0 = 0; Real h = Real(1)/Real(16); size_t n = 512; @@ -186,8 +193,8 @@ template void test_quadratic() { Real a = Real(1)/Real(16); - Real b = -3.5; - Real c = -9; + Real b = Real(-3.5); + Real c = Real(-9); Real t0 = 0; Real h = Real(1)/Real(16); size_t n = 513; @@ -229,8 +236,8 @@ template void test_quadratic_estimate_derivatives() { Real a = Real(1)/Real(16); - Real b = -3.5; - Real c = -9; + Real b = Real(-3.5); + Real c = Real(-9); Real t0 = 0; Real h = Real(1)/Real(16); size_t n = 513; @@ -266,41 +273,41 @@ void test_quadratic_estimate_derivatives() int main() { + #ifdef __STDCPP_FLOAT32_T__ + test_linear(); + #else + test_linear(); + #endif + + #ifdef __STDCPP_FLOAT64_T__ + test_constant(); + test_linear(); + test_constant_estimate_derivatives(); + test_linear_estimate_derivatives(); + test_quadratic(); + test_quadratic_estimate_derivatives(); + #else test_constant(); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - test_constant(); -#endif - + test_linear(); test_constant_estimate_derivatives(); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - test_constant_estimate_derivatives(); -#endif + test_linear_estimate_derivatives(); + test_quadratic(); + test_quadratic_estimate_derivatives(); + #endif - test_linear(); - test_linear(); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + test_constant(); + test_constant_estimate_derivatives(); test_linear(); -#endif - - test_linear_estimate_derivatives(); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS test_linear_estimate_derivatives(); -#endif - - test_quadratic(); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS test_quadratic(); -#endif - - test_quadratic_estimate_derivatives(); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS test_quadratic_estimate_derivatives(); -#endif + #endif #ifdef BOOST_HAS_FLOAT128 - test_constant(); - test_linear(); - test_linear_estimate_derivatives(); + test_constant(); + test_linear(); + test_linear_estimate_derivatives(); #endif return boost::math::test::report_errors(); diff --git a/test/catmull_rom_test.cpp b/test/catmull_rom_test.cpp index 8648b16869..71ea96dc43 100644 --- a/test/catmull_rom_test.cpp +++ b/test/catmull_rom_test.cpp @@ -18,6 +18,10 @@ #include #include +#if __has_include() +# include +#endif + using std::abs; using boost::multiprecision::cpp_bin_float_50; using boost::math::catmull_rom; @@ -158,7 +162,7 @@ void test_circle() } Real max_s = circle.max_parameter(); - for(Real s = 0; s < max_s; s += 0.01) + for(Real s = 0; s < max_s; s += Real(0.01)) { auto p = circle(s); Real x = p[0]; @@ -259,11 +263,11 @@ void test_helix() Real y = p[1]; if (abs(x) < tol) { - BOOST_CHECK_SMALL(cos(t), tol); + BOOST_CHECK_SMALL(Real(cos(t)), tol); } if (abs(y) < tol) { - BOOST_CHECK_SMALL(sin(t), tol); + BOOST_CHECK_SMALL(Real(sin(t)), tol); } else { @@ -282,16 +286,16 @@ void test_helix() BOOST_CHECK_CLOSE_FRACTION(x*x+y*y, (Real) 1, (Real) 0.01); if (abs(x) < 0.01) { - BOOST_CHECK_SMALL(cos(t), (Real) 0.05); + BOOST_CHECK_SMALL(Real(cos(t)), (Real) 0.05); } if (abs(y) < 0.01) { - BOOST_CHECK_SMALL(sin(t), (Real) 0.05); + BOOST_CHECK_SMALL(Real(sin(t)), (Real) 0.05); } else { - BOOST_CHECK_CLOSE_FRACTION(x, cos(t), (Real) 0.05); - BOOST_CHECK_CLOSE_FRACTION(y, sin(t), (Real) 0.05); + BOOST_CHECK_CLOSE_FRACTION(x, Real(cos(t)), (Real) 0.05); + BOOST_CHECK_CLOSE_FRACTION(y, Real(sin(t)), (Real) 0.05); } } } @@ -344,18 +348,18 @@ template void test_data_representations() { std::cout << "Testing that the Catmull-Rom spline works with multiple data representations.\n"; - mypoint3d p0(0.1, 0.2, 0.3); - mypoint3d p1(0.2, 0.3, 0.4); - mypoint3d p2(0.3, 0.4, 0.5); - mypoint3d p3(0.4, 0.5, 0.6); - mypoint3d p4(0.5, 0.6, 0.7); - mypoint3d p5(0.6, 0.7, 0.8); + mypoint3d p0(Real(0.1), Real(0.2), Real(0.3)); + mypoint3d p1(Real(0.2), Real(0.3), Real(0.4)); + mypoint3d p2(Real(0.3), Real(0.4), Real(0.5)); + mypoint3d p3(Real(0.4), Real(0.5), Real(0.6)); + mypoint3d p4(Real(0.5), Real(0.6), Real(0.7)); + mypoint3d p5(Real(0.6), Real(0.7), Real(0.8)); // Tests initializer_list: catmull_rom> cat({p0, p1, p2, p3, p4, p5}); - Real tol = 0.001; + Real tol = Real(0.001); auto p = cat(cat.parameter_at_point(0)); BOOST_CHECK_CLOSE_FRACTION(p[0], p0[0], tol); BOOST_CHECK_CLOSE_FRACTION(p[1], p0[1], tol); @@ -388,7 +392,7 @@ void test_random_access_container() // Tests initializer_list: catmull_rom, decltype(u)> cat(std::move(u)); - Real tol = 0.001; + Real tol = Real(0.001); auto p = cat(cat.parameter_at_point(0)); BOOST_CHECK_CLOSE_FRACTION(p[0], p0[0], tol); BOOST_CHECK_CLOSE_FRACTION(p[1], p0[1], tol); @@ -402,27 +406,51 @@ void test_random_access_container() BOOST_AUTO_TEST_CASE(catmull_rom_test) { #if !defined(TEST) || (TEST == 1) + + #ifdef __STDCPP_FLOAT32_T__ + test_circle(); + test_data_representations(); + #else + test_circle(); test_data_representations(); - test_alpha_distance(); + #endif + #ifdef __STDCPP_FLOAT64_T__ + test_alpha_distance(); + test_linear(); + test_circle(); + #else + test_alpha_distance(); test_linear(); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + test_circle(); + #endif + + #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS test_linear(); -#endif + #endif - test_circle(); - test_circle(); #endif + #if !defined(TEST) || (TEST == 2) - test_helix(); + #ifdef __STDCPP_FLOAT64_T__ + test_helix(); + test_affine_invariance(); + test_affine_invariance(); + test_affine_invariance(); + test_affine_invariance(); + test_random_access_container(); + #else + test_helix(); test_affine_invariance(); test_affine_invariance(); test_affine_invariance(); test_affine_invariance(); - test_random_access_container(); + #endif + #endif + #if !defined(TEST) || (TEST == 3) test_affine_invariance(); #endif diff --git a/test/cohen_acceleration_test.cpp b/test/cohen_acceleration_test.cpp index f300bdad6a..ad70c3f825 100644 --- a/test/cohen_acceleration_test.cpp +++ b/test/cohen_acceleration_test.cpp @@ -15,6 +15,10 @@ using boost::multiprecision::float128; #include #include +#if __has_include() +# include +#endif + using boost::math::tools::cohen_acceleration; using boost::multiprecision::cpp_bin_float_100; using boost::math::constants::pi; @@ -72,17 +76,29 @@ void test_divergent() int main() { + #ifdef __STDCPP_FLOAT32_T__ + test_pisq_div12(); + test_divergent(); + #else test_pisq_div12(); - test_pisq_div12(); - test_pisq_div12(); - test_divergent(); + #endif + + #ifdef __STDCPP_FLOAT64_T__ + test_pisq_div12(); + test_divergent(); + #else test_divergent(); + test_pisq_div12(); + #endif + test_divergent(); + test_pisq_div12(); #ifdef BOOST_HAS_FLOAT128 test_pisq_div12(); test_divergent(); #endif + return boost::math::test::report_errors(); } diff --git a/test/compile_test/float128.cpp b/test/compile_test/float128.cpp new file mode 100644 index 0000000000..da32e60793 --- /dev/null +++ b/test/compile_test/float128.cpp @@ -0,0 +1,32 @@ +// Copyright Matt Borland 2023. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#if __has_include() +# include +#endif + +#ifdef __STDCPP_FLOAT128_T__ + +#define TEST_COMPLEX + +#include "instantiate.hpp" + +int main(int argc, char* []) +{ + if(argc > 10000) + { + instantiate(0.0F128); + instantiate_mixed(0.0F128); + } +} + +#else + +int main(int, char*[]) +{ + return 0; +} + +#endif diff --git a/test/compile_test/float32.cpp b/test/compile_test/float32.cpp new file mode 100644 index 0000000000..a757b0bb4d --- /dev/null +++ b/test/compile_test/float32.cpp @@ -0,0 +1,32 @@ +// Copyright Matt Borland 2023. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#if __has_include() +# include +#endif + +#ifdef __STDCPP_FLOAT32_T__ + +#define TEST_COMPLEX + +#include "instantiate.hpp" + +int main(int argc, char* []) +{ + if(argc > 10000) + { + instantiate(0.0F32); + instantiate_mixed(0.0F32); + } +} + +#else + +int main(int, char*[]) +{ + return 0; +} + +#endif diff --git a/test/compile_test/float64.cpp b/test/compile_test/float64.cpp new file mode 100644 index 0000000000..a989b93350 --- /dev/null +++ b/test/compile_test/float64.cpp @@ -0,0 +1,32 @@ +// Copyright Matt Borland 2023. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#if __has_include() +# include +#endif + +#ifdef __STDCPP_FLOAT64_T__ + +#define TEST_COMPLEX + +#include "instantiate.hpp" + +int main(int argc, char* []) +{ + if(argc > 10000) + { + instantiate(0.0F64); + instantiate_mixed(0.0F64); + } +} + +#else + +int main(int, char*[]) +{ + return 0; +} + +#endif diff --git a/test/compile_test/instantiate.hpp b/test/compile_test/instantiate.hpp index 024e79c5d6..33939a25ad 100644 --- a/test/compile_test/instantiate.hpp +++ b/test/compile_test/instantiate.hpp @@ -181,7 +181,9 @@ void instantiate(RealType) int i = 1; // Deal with unused variable warnings: (void)i; - RealType v1(0.5), v2(0.5), v3(0.5); + auto v1(static_cast(0.5)); + auto v2(static_cast(0.5)); + auto v3(static_cast(0.5)); boost::detail::dummy_constructor dc; boost::output_iterator_archetype oi(dc); #ifdef TEST_GROUP_4 diff --git a/test/compile_test/test_promote_args.cpp b/test/compile_test/test_promote_args.cpp new file mode 100644 index 0000000000..2281aa7115 --- /dev/null +++ b/test/compile_test/test_promote_args.cpp @@ -0,0 +1,188 @@ +// Copyright John Maddock 2023. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#ifndef BOOST_MATH_STANDALONE +#include +#endif +#include + +#if __has_include() +# include +#endif + +int main() +{ + using boost::math::tools::promote_args_t; + +#if defined(__cpp_lib_type_trait_variable_templates) && (__cpp_lib_type_trait_variable_templates >= 201510L) && defined(__cpp_static_assert) && (__cpp_static_assert >= 201411L) + + static_assert(std::is_same_v, long double>); + static_assert(std::is_same_v, long double>); + static_assert(std::is_same_v, long double>); +#ifdef __STDCPP_FLOAT16_T__ + static_assert(std::is_same_v, long double>); +#endif +#ifdef __STDCPP_FLOAT32_T__ + static_assert(std::is_same_v, long double>); +#endif +#ifdef __STDCPP_FLOAT64_T__ +#if LDBL_MANT_DIG > 53 + static_assert(std::is_same_v, long double>); +#else + static_assert(std::is_same_v, std::float64_t>); +#endif +#endif +#ifdef __STDCPP_FLOAT128_T__ +#if LDBL_MANT_DIG > 113 + static_assert(std::is_same_v, long double>); +#else + static_assert(std::is_same_v, std::float128_t>); +#endif +#endif + + static_assert(std::is_same_v, double>); + static_assert(std::is_same_v, double>); + static_assert(std::is_same_v, long double>); +#ifdef __STDCPP_FLOAT16_T__ + static_assert(std::is_same_v, double>); +#endif +#ifdef __STDCPP_FLOAT32_T__ + static_assert(std::is_same_v, double>); +#endif +#ifdef __STDCPP_FLOAT64_T__ +#if DBL_MANT_DIG > 53 + static_assert(std::is_same_v, double>); +#else + static_assert(std::is_same_v, std::float64_t>); +#endif +#endif +#ifdef __STDCPP_FLOAT128_T__ +#if DBL_MANT_DIG > 113 + static_assert(std::is_same_v, double>); +#else + static_assert(std::is_same_v, std::float128_t>); +#endif +#endif + + static_assert(std::is_same_v, float>); + static_assert(std::is_same_v, double>); + static_assert(std::is_same_v, long double>); +#ifdef __STDCPP_FLOAT16_T__ + static_assert(std::is_same_v, float>); +#endif +#ifdef __STDCPP_FLOAT32_T__ + static_assert(std::is_same_v, std::float32_t>); +#endif +#ifdef __STDCPP_FLOAT64_T__ + static_assert(std::is_same_v, std::float64_t>); +#endif +#ifdef __STDCPP_FLOAT128_T__ + static_assert(std::is_same_v, std::float128_t>); +#endif + +#ifdef __STDCPP_FLOAT16_T__ + static_assert(std::is_same_v, float>); + static_assert(std::is_same_v, double>); + static_assert(std::is_same_v, long double>); +#ifdef __STDCPP_FLOAT16_T__ + static_assert(std::is_same_v, float>); +#endif +#ifdef __STDCPP_FLOAT32_T__ + static_assert(std::is_same_v, std::float32_t>); +#endif +#ifdef __STDCPP_FLOAT64_T__ + static_assert(std::is_same_v, std::float64_t>); +#endif +#ifdef __STDCPP_FLOAT128_T__ + static_assert(std::is_same_v, std::float128_t>); +#endif +#endif + +#ifdef __STDCPP_FLOAT32_T__ + static_assert(std::is_same_v, std::float32_t>); + static_assert(std::is_same_v, double>); + static_assert(std::is_same_v, long double>); +#ifdef __STDCPP_FLOAT16_T__ + static_assert(std::is_same_v, std::float32_t>); +#endif +#ifdef __STDCPP_FLOAT32_T__ + static_assert(std::is_same_v, std::float32_t>); +#endif +#ifdef __STDCPP_FLOAT64_T__ + static_assert(std::is_same_v, std::float64_t>); +#endif +#ifdef __STDCPP_FLOAT128_T__ + static_assert(std::is_same_v, std::float128_t>); +#endif +#endif + +#ifdef __STDCPP_FLOAT64_T__ + static_assert(std::is_same_v, std::float64_t>); + static_assert(std::is_same_v, std::float64_t>); +#if LDBL_MANT_DIG > 53 + static_assert(std::is_same_v, long double>); +#else + static_assert(std::is_same_v, std::float64_t>); +#endif +#ifdef __STDCPP_FLOAT16_T__ + static_assert(std::is_same_v, std::float64_t>); +#endif +#ifdef __STDCPP_FLOAT32_T__ + static_assert(std::is_same_v, std::float64_t>); +#endif +#ifdef __STDCPP_FLOAT64_T__ + static_assert(std::is_same_v, std::float64_t>); +#endif +#ifdef __STDCPP_FLOAT128_T__ + static_assert(std::is_same_v, std::float128_t>); +#endif +#endif + +#ifdef __STDCPP_FLOAT128_T__ + static_assert(std::is_same_v, std::float128_t>); + static_assert(std::is_same_v, std::float128_t>); +#if LDBL_MANT_DIG > 113 + static_assert(std::is_same_v, long double>); +#else + static_assert(std::is_same_v, std::float128_t>); +#endif +#ifdef __STDCPP_FLOAT16_T__ + static_assert(std::is_same_v, std::float128_t>); +#endif +#ifdef __STDCPP_FLOAT32_T__ + static_assert(std::is_same_v, std::float128_t>); +#endif +#ifdef __STDCPP_FLOAT64_T__ + static_assert(std::is_same_v, std::float128_t>); +#endif +#ifdef __STDCPP_FLOAT128_T__ + static_assert(std::is_same_v, std::float128_t>); +#endif +#endif + +#ifndef BOOST_MATH_STANDALONE + static_assert(std::is_same_v, boost::multiprecision::cpp_bin_float_50>); + static_assert(std::is_same_v, boost::multiprecision::cpp_bin_float_50>); + static_assert(std::is_same_v, boost::multiprecision::cpp_bin_float_50>); +#ifdef __STDCPP_FLOAT16_T__ + static_assert(std::is_same_v, boost::multiprecision::cpp_bin_float_50>); +#endif +#ifdef __STDCPP_FLOAT32_T__ + static_assert(std::is_same_v, boost::multiprecision::cpp_bin_float_50>); +#endif +#ifdef __STDCPP_FLOAT64_T__ + static_assert(std::is_same_v, boost::multiprecision::cpp_bin_float_50>); +#endif +#ifdef __STDCPP_FLOAT128_T__ + static_assert(std::is_same_v, boost::multiprecision::cpp_bin_float_50>); +#endif +#endif // BOOST_MATH_STANDALONE + +#endif + + return 0; +} diff --git a/test/cubic_hermite_test.cpp b/test/cubic_hermite_test.cpp index a8ded39904..ec515c2914 100644 --- a/test/cubic_hermite_test.cpp +++ b/test/cubic_hermite_test.cpp @@ -19,6 +19,9 @@ using boost::multiprecision::float128; #endif +#if __has_include() +# include +#endif using boost::math::interpolators::cubic_hermite; using boost::math::interpolators::cardinal_cubic_hermite; @@ -74,7 +77,7 @@ void test_constant() auto circular_hermite_spline = cubic_hermite(std::move(x_buf), std::move(y_buf), std::move(dydx_buf)); - for (Real t = x[0]; t <= x.back(); t += 0.25) { + for (Real t = x[0]; t <= x.back(); t += Real(0.25)) { CHECK_ULP_CLOSE(Real(7), circular_hermite_spline(t), 2); CHECK_ULP_CLOSE(Real(0), circular_hermite_spline.prime(t), 2); } @@ -117,7 +120,7 @@ void test_linear() y_copy = y; dydx_copy = dydx; hermite_spline = cubic_hermite(std::move(x_copy), std::move(y_copy), std::move(dydx_copy)); - for (Real t = 0; t < x.back(); t += 0.5) { + for (Real t = 0; t < x.back(); t += Real(0.5)) { CHECK_ULP_CLOSE(t, hermite_spline(t), 0); CHECK_ULP_CLOSE(Real(1), hermite_spline.prime(t), 0); } @@ -139,7 +142,7 @@ void test_linear() auto circular_hermite_spline = cubic_hermite(std::move(x_buf), std::move(y_buf), std::move(dydx_buf)); - for (Real t = x[0]; t <= x.back(); t += 0.25) { + for (Real t = x[0]; t <= x.back(); t += Real(0.25)) { CHECK_ULP_CLOSE(t, circular_hermite_spline(t), 2); CHECK_ULP_CLOSE(Real(1), circular_hermite_spline.prime(t), 2); } @@ -156,7 +159,7 @@ void test_quadratic() { std::vector x(50); std::default_random_engine rd; - std::uniform_real_distribution dis(0.1,1); + std::uniform_real_distribution dis(Real(0.1), Real(1)); Real x0 = dis(rd); x[0] = x0; for (size_t i = 1; i < x.size(); ++i) { @@ -172,7 +175,7 @@ void test_quadratic() } auto s = cubic_hermite(std::move(x), std::move(y), std::move(dydx)); - for (Real t = x0; t <= xmax; t+= 0.0125) + for (Real t = x0; t <= xmax; t+= Real(0.0125)) { CHECK_ULP_CLOSE(t*t/2, s(t), 5); CHECK_ULP_CLOSE(t, s.prime(t), 138); @@ -223,7 +226,7 @@ void test_cardinal_constant() auto hermite_spline = cardinal_cubic_hermite(std::move(y), std::move(dydx), x0, dx); - for (Real t = x0; t <= x0 + 24*dx; t += 0.25) { + for (Real t = x0; t <= x0 + 24*dx; t += Real(0.25)) { CHECK_ULP_CLOSE(Real(7), hermite_spline(t), 2); CHECK_ULP_CLOSE(Real(0), hermite_spline.prime(t), 2); } @@ -237,7 +240,7 @@ void test_cardinal_constant() } auto hermite_spline_aos = cardinal_cubic_hermite_aos(std::move(data), x0, dx); - for (Real t = x0; t <= x0 + 24*dx; t += 0.25) { + for (Real t = x0; t <= x0 + 24*dx; t += Real(0.25)) { if (!CHECK_ULP_CLOSE(Real(7), hermite_spline_aos(t), 2)) { std::cerr << " Wrong evaluation at t = " << t << "\n"; } @@ -297,7 +300,7 @@ void test_cardinal_linear() } hermite_spline = cardinal_cubic_hermite(std::move(y), std::move(dydx), x0, dx); - for (Real t = 0; t < 44; t += 0.5) { + for (Real t = 0; t < 44; t += Real(0.5)) { CHECK_ULP_CLOSE(t, hermite_spline(t), 0); CHECK_ULP_CLOSE(Real(1), hermite_spline.prime(t), 0); } @@ -309,7 +312,7 @@ void test_cardinal_linear() } auto hermite_spline_aos = cardinal_cubic_hermite_aos(std::move(data), x0, dx); - for (Real t = 0; t < 44; t += 0.5) { + for (Real t = 0; t < 44; t += Real(0.5)) { CHECK_ULP_CLOSE(t, hermite_spline_aos(t), 0); CHECK_ULP_CLOSE(Real(1), hermite_spline_aos.prime(t), 0); } @@ -352,7 +355,7 @@ void test_cardinal_quadratic() } auto s = cardinal_cubic_hermite(std::move(y), std::move(dydx), x0, dx); - for (Real t = x0; t <= x0 + 49*dx; t+= 0.0125) + for (Real t = x0; t <= x0 + 49*dx; t+= Real(0.0125)) { CHECK_ULP_CLOSE(t*t/2, s(t), 12); CHECK_ULP_CLOSE(t, s.prime(t), 70); @@ -367,7 +370,7 @@ void test_cardinal_quadratic() auto saos = cardinal_cubic_hermite_aos(std::move(data), x0, dx); - for (Real t = x0; t <= x0 + 49*dx; t+= 0.0125) + for (Real t = x0; t <= x0 + 49*dx; t+= Real(0.0125)) { CHECK_ULP_CLOSE(t*t/2, saos(t), 12); CHECK_ULP_CLOSE(t, saos.prime(t), 70); @@ -400,7 +403,7 @@ void test_cardinal_interpolation_condition() std::vector y(n); std::vector dydx(n); std::default_random_engine rd; - std::uniform_real_distribution dis(0.1,1); + std::uniform_real_distribution dis(Real(0.1), Real(1)); Real x0 = Real(2); Real dx = Real(1)/Real(128); for (size_t i = 0; i < n; ++i) { @@ -422,6 +425,16 @@ void test_cardinal_interpolation_condition() int main() { + #ifdef __STDCPP_FLOAT32_T__ + test_constant(); + test_linear(); + test_quadratic(); + test_interpolation_condition(); + test_cardinal_constant(); + test_cardinal_linear(); + test_cardinal_quadratic(); + test_cardinal_interpolation_condition(); + #else test_constant(); test_linear(); test_quadratic(); @@ -430,7 +443,18 @@ int main() test_cardinal_linear(); test_cardinal_quadratic(); test_cardinal_interpolation_condition(); - + #endif + + #ifdef __STDCPP_FLOAT64_T__ + test_constant(); + test_linear(); + test_quadratic(); + test_interpolation_condition(); + test_cardinal_constant(); + test_cardinal_linear(); + test_cardinal_quadratic(); + test_cardinal_interpolation_condition(); + #else test_constant(); test_linear(); test_quadratic(); @@ -439,6 +463,7 @@ int main() test_cardinal_linear(); test_cardinal_quadratic(); test_cardinal_interpolation_condition(); + #endif test_constant(); test_linear(); @@ -450,12 +475,12 @@ int main() test_cardinal_interpolation_condition(); -#ifdef BOOST_HAS_FLOAT128 + #ifdef BOOST_HAS_FLOAT128 test_constant(); test_linear(); test_cardinal_constant(); test_cardinal_linear(); -#endif + #endif return boost::math::test::report_errors(); } diff --git a/test/exp_sinh_quadrature_test.cpp b/test/exp_sinh_quadrature_test.cpp index da0c3a5483..d39ec4c5dc 100644 --- a/test/exp_sinh_quadrature_test.cpp +++ b/test/exp_sinh_quadrature_test.cpp @@ -29,6 +29,10 @@ #include #endif +#if __has_include() +# include +#endif + using std::exp; using std::cos; using std::tan; @@ -586,17 +590,35 @@ BOOST_AUTO_TEST_CASE(exp_sinh_quadrature_test) */ #ifdef TEST1 + +#ifdef __STDCPP_FLOAT32_T__ + test_left_limit_infinite(); + test_right_limit_infinite(); + test_nr_examples(); + test_crc(); +#else test_left_limit_infinite(); test_right_limit_infinite(); test_nr_examples(); test_crc(); #endif + +#endif #ifdef TEST2 + +#ifdef __STDCPP_FLOAT64_T__ + test_left_limit_infinite(); + test_right_limit_infinite(); + test_nr_examples(); + test_crc(); +#else test_left_limit_infinite(); test_right_limit_infinite(); test_nr_examples(); test_crc(); #endif + +#endif #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS #ifdef TEST3 #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS diff --git a/test/fourier_transform_daubechies_test.cpp b/test/fourier_transform_daubechies_test.cpp new file mode 100644 index 0000000000..2efce921db --- /dev/null +++ b/test/fourier_transform_daubechies_test.cpp @@ -0,0 +1,220 @@ +// boost-no-inspect +/* + * Copyright Nick Thompson, 2023 + * Use, modification and distribution are subject to the + * Boost Software License, Version 1.0. (See accompanying file + * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ + +#include "math_unit_test.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_FLOAT128 +#include +using boost::multiprecision::float128; +#endif + +using boost::math::fourier_transform_daubechies_scaling; +using boost::math::fourier_transform_daubechies_wavelet; +using boost::math::tools::summation_condition_number; +using boost::math::constants::two_pi; +using boost::math::constants::pi; +using boost::math::constants::one_div_root_two_pi; +using boost::math::quadrature::trapezoidal; +// 𝓕[φ](-ω) = 𝓕[φ](ω)* +template +void test_evaluation_symmetry() { + std::cout << "Testing evaluation symmetry on the " << p << " vanishing moment scaling function.\n"; + auto phi = fourier_transform_daubechies_scaling(0.0); + CHECK_ULP_CLOSE(one_div_root_two_pi(), phi.real(), 3); + CHECK_ULP_CLOSE(static_cast(0), phi.imag(), 3); + + Real domega = Real(1)/128; + for (Real omega = domega; omega < 10; omega += domega) { + auto phi1 = fourier_transform_daubechies_scaling(-omega); + auto phi2 = fourier_transform_daubechies_scaling(omega); + CHECK_ULP_CLOSE(phi1.real(), phi2.real(), 3); + CHECK_ULP_CLOSE(phi1.imag(), -phi2.imag(), 3); + + auto psi1 = fourier_transform_daubechies_wavelet(-omega); + auto psi2 = fourier_transform_daubechies_wavelet(omega); + CHECK_ULP_CLOSE(psi1.real(), psi2.real(), 3); + CHECK_ULP_CLOSE(psi1.imag(), -psi2.imag(), 3); + } + + for (Real omega = 10; omega < std::cbrt(std::numeric_limits::max()); omega *= 10) { + auto phi1 = fourier_transform_daubechies_scaling(-omega); + auto phi2 = fourier_transform_daubechies_scaling(omega); + CHECK_ULP_CLOSE(phi1.real(), phi2.real(), 3); + CHECK_ULP_CLOSE(phi1.imag(), -phi2.imag(), 3); + } + return; +} + +template +void test_roots() { + std::cout << "Testing roots on the " << p << " vanishing moment scaling function.\n"; + for (long n = 1; n < 100; ++n) { + // All arguments of the form 2πn are roots of the complex function: + // See Daubechies, 10 Lectures on Wavelets, Section 6.2: + Real omega = n*two_pi(); + Real residual = std::norm(fourier_transform_daubechies_scaling(omega)); + CHECK_LE(residual, std::numeric_limits::epsilon()*std::numeric_limits::epsilon()); + } + std::cout << "Testing roots on the " << p << " vanishing moment wavelet.\n"; + // If ωₙ is a root of the 𝓕[𝜙], then 2ωₙ is a root of 𝓕[ψ]. + // In addition, m₀(π) = 0, and m₀ is 2π periodic. + // Recalling 𝓕[ψ](ω) = exp(iω/2)m₀(ω/2 + π)^{*}𝓕[𝜙](ω/2)*phase, + // ω=4nπ are also roots: + for (long n = 0; n < 100; ++n) { + Real omega = 4*n*pi(); + Real residual = std::norm(fourier_transform_daubechies_wavelet(omega)); + CHECK_LE(residual, std::numeric_limits::epsilon()*std::numeric_limits::epsilon()); + } +} + +template +void test_scaling_quadrature() { + std::cout << "Testing numerical quadrature of the scaling function with " << p << " vanishing moments matches numerical evaluation.\n"; + auto phi = boost::math::daubechies_scaling(); + auto [tmin, tmax] = phi.support(); + double domega = 1/8.0; + for (double omega = domega; omega < 10; omega += domega) { + // I suspect the quadrature is less accurate than special function evaluation, so this is just a sanity check: + auto f = [&](double t) { + return phi(t)*std::exp(std::complex(0, -omega*t))*one_div_root_two_pi(); + }; + auto expected = trapezoidal(f, tmin, tmax, 2*std::numeric_limits::epsilon()); + auto computed = fourier_transform_daubechies_scaling(static_cast(omega)); + CHECK_MOLLIFIED_CLOSE(static_cast(expected.real()), computed.real(), 1e-4); + CHECK_MOLLIFIED_CLOSE(static_cast(expected.imag()), computed.imag(), 1e-4); + } +} + +template +void test_wavelet_quadrature() { + std::cout << "Testing numerical quadrature of the wavelet with " << p << " vanishing moments matches numerical evaluation.\n"; + auto psi = boost::math::daubechies_wavelet(); + auto [tmin, tmax] = psi.support(); + double domega = 1/8.0; + // There is a root at at ω=0, so skip this one because we can't recover the phase of a root. + for (double omega = 2*domega; omega < 10; omega += domega) { + // I suspect the quadrature is less accurate than special function evaluation, so this is just a sanity check: + auto f = [&](double t) { + return psi(t)*std::exp(std::complex(0, -omega*t))*one_div_root_two_pi(); + }; + auto expected = trapezoidal(f, tmin, tmax, std::numeric_limits::epsilon()); + auto computed = fourier_transform_daubechies_wavelet(omega); + if(!CHECK_ABSOLUTE_ERROR(std::abs(expected), std::abs(computed), 1e-9)) { + std::cerr << " |𝓕[ψ](" << omega << ")| is incorrect.\n"; + } + // Again, lots of evidence that the quadrature is less accurate than what we've implemented. + // Graph of the quadrature phase is super janky; graph of the implementation phase is pretty good. + if(!CHECK_ABSOLUTE_ERROR(std::arg(expected), std::arg(computed), 1e-2)) { + std::cerr << " arg(𝓕[ψ](" << omega << ")) is incorrect.\n"; + } + } +} + + +// Tests Daubechies "Ten Lectures on Wavelets", equation 5.1.19: +template +void test_ten_lectures_eq_5_1_19() { + std::cout << "Testing Ten Lectures equation 5.1.19 on " << p << " vanishing moments.\n"; + Real domega = Real(1)/Real(16); + for (Real omega = 0; omega < 1; omega += domega) { + Real term = std::norm(fourier_transform_daubechies_scaling(omega)); + auto sum = summation_condition_number(term); + int64_t l = 1; + while (l < 10000 && term > 2*std::numeric_limits::epsilon()) { + Real tpl = std::norm(fourier_transform_daubechies_scaling(omega + two_pi()*l)); + Real tml = std::norm(fourier_transform_daubechies_scaling(omega - two_pi()*l)); + + sum += tpl; + sum += tml; + Real term = tpl + tml; + ++l; + } + // With arg promotion, I can get this to 13 ULPS: + if (!CHECK_ULP_CLOSE(1/two_pi(), sum.sum(), 125)) { + std::cerr << " Failure with occurs on " << p << " vanishing moments.\n"; + } + } +} + +// Tests Daubechies "Ten Lectures on Wavelets", equation 5.1.38: +template +void test_ten_lectures_eq_5_1_38() { + std::cout << "Testing Ten Lectures equation 5.1.38 on " << p << " vanishing moments.\n"; + Real domega = Real(1)/Real(16); + for (Real omega = 0; omega < 1; omega += domega) { + Real phi_omega_sq = std::norm(fourier_transform_daubechies_scaling(omega)); + Real psi_omega_sq = std::norm(fourier_transform_daubechies_wavelet(omega)); + Real phi_half_omega_sq = std::norm(fourier_transform_daubechies_scaling(omega/2)); + + if (!CHECK_ULP_CLOSE(phi_half_omega_sq, phi_omega_sq + psi_omega_sq, 125)) { + std::cerr << " Failure with occurs on " << p << " vanishing moments at omega = " << omega << "\n"; + } + } +} + + +int main() +{ + test_roots(); + test_roots(); + test_roots(); + test_roots(); + test_roots(); + test_roots(); + test_roots(); + test_roots(); + test_roots(); + test_roots(); + + test_evaluation_symmetry(); + test_evaluation_symmetry(); + test_evaluation_symmetry(); + test_evaluation_symmetry(); + test_evaluation_symmetry(); + test_evaluation_symmetry(); + test_evaluation_symmetry(); + test_evaluation_symmetry(); + test_evaluation_symmetry(); + test_evaluation_symmetry(); + + // Slow tests: + test_scaling_quadrature<9>(); + test_scaling_quadrature<10>(); + + // This one converges really slowly: + //test_ten_lectures_eq_5_1_19(); + test_ten_lectures_eq_5_1_19(); + test_ten_lectures_eq_5_1_19(); + test_ten_lectures_eq_5_1_19(); + test_ten_lectures_eq_5_1_19(); + test_ten_lectures_eq_5_1_19(); + test_ten_lectures_eq_5_1_19(); + test_ten_lectures_eq_5_1_19(); + test_ten_lectures_eq_5_1_19(); + test_ten_lectures_eq_5_1_19(); + + test_ten_lectures_eq_5_1_38(); + test_ten_lectures_eq_5_1_38(); + test_ten_lectures_eq_5_1_38(); + test_ten_lectures_eq_5_1_38(); + + test_wavelet_quadrature<9>(); + + return boost::math::test::report_errors(); +} diff --git a/test/gauss_kronrod_quadrature_test.cpp b/test/gauss_kronrod_quadrature_test.cpp index 3ee9c85740..5877146d71 100644 --- a/test/gauss_kronrod_quadrature_test.cpp +++ b/test/gauss_kronrod_quadrature_test.cpp @@ -38,6 +38,10 @@ #pragma warning(disable:4127) // Conditional expression is constant #endif +#if __has_include() +# include +#endif + using std::expm1; using std::atan; using std::tan; @@ -456,6 +460,16 @@ BOOST_AUTO_TEST_CASE(gauss_quadrature_test) { #ifdef TEST1 std::cout << "Testing 15 point approximation:\n"; + +#ifdef __STDCPP_FLOAT64_T__ + test_linear(); + test_quadratic(); + test_ca(); + test_three_quadrature_schemes_examples(); + test_integration_over_real_line(); + test_right_limit_infinite(); + test_left_limit_infinite(); +#else test_linear(); test_quadratic(); test_ca(); @@ -463,9 +477,20 @@ BOOST_AUTO_TEST_CASE(gauss_quadrature_test) test_integration_over_real_line(); test_right_limit_infinite(); test_left_limit_infinite(); +#endif // test one case where we do not have pre-computed constants: std::cout << "Testing 17 point approximation:\n"; + +#ifdef __STDCPP_FLOAT64_T__ + test_linear(); + test_quadratic(); + test_ca(); + test_three_quadrature_schemes_examples(); + test_integration_over_real_line(); + test_right_limit_infinite(); + test_left_limit_infinite(); +#else test_linear(); test_quadratic(); test_ca(); @@ -473,6 +498,8 @@ BOOST_AUTO_TEST_CASE(gauss_quadrature_test) test_integration_over_real_line(); test_right_limit_infinite(); test_left_limit_infinite(); +#endif + test_complex_lambert_w>(); test_complex_lambert_w>(); #endif diff --git a/test/gauss_quadrature_test.cpp b/test/gauss_quadrature_test.cpp index e1d61243e9..91eca9ec20 100644 --- a/test/gauss_quadrature_test.cpp +++ b/test/gauss_quadrature_test.cpp @@ -31,6 +31,10 @@ #pragma warning(disable:4127) // Conditional expression is constant #endif +#if __has_include() +# include +#endif + #if !defined(TEST1) && !defined(TEST2) && !defined(TEST3) # define TEST1 # define TEST2 @@ -445,6 +449,24 @@ BOOST_AUTO_TEST_CASE(gauss_quadrature_test) { #ifdef TEST1 + +#ifdef __STDCPP_FLOAT64_T__ + test_linear(); + test_quadratic(); + test_ca(); + test_three_quadrature_schemes_examples(); + test_integration_over_real_line(); + test_right_limit_infinite(); + test_left_limit_infinite(); + + test_linear(); + test_quadratic(); + test_ca(); + test_three_quadrature_schemes_examples(); + test_integration_over_real_line(); + test_right_limit_infinite(); + test_left_limit_infinite(); +#else test_linear(); test_quadratic(); test_ca(); @@ -460,6 +482,7 @@ BOOST_AUTO_TEST_CASE(gauss_quadrature_test) test_integration_over_real_line(); test_right_limit_infinite(); test_left_limit_infinite(); +#endif #if LDBL_MANT_DIG < 100 && defined(BOOST_MATH_RUN_MP_TESTS) test_linear(); diff --git a/test/gegenbauer_test.cpp b/test/gegenbauer_test.cpp index aa684cea8f..7349bfe675 100644 --- a/test/gegenbauer_test.cpp +++ b/test/gegenbauer_test.cpp @@ -17,6 +17,10 @@ using boost::multiprecision::float128; #endif +#if __has_include() +# include +#endif + using std::abs; using boost::math::gegenbauer; using boost::math::gegenbauer_derivative; @@ -26,7 +30,7 @@ void test_parity() { std::mt19937 gen(323723); std::uniform_real_distribution xdis(-1, +1); - std::uniform_real_distribution lambdadis(-0.5, 1); + std::uniform_real_distribution lambdadis(Real(-0.5), 1); for(unsigned n = 0; n < 50; ++n) { unsigned calls = 50; @@ -79,7 +83,7 @@ void test_cubic() template void test_derivative() { - Real lambda = 0.5; + Real lambda = Real(0.5); auto c3_prime = [&](Real x) { return 2*lambda*(lambda+1)*(-1 + 2*(lambda+2)*x*x); }; auto c3_double_prime = [&](Real x) { return 8*lambda*(lambda+1)*(lambda+2)*x; }; Real x = -1; @@ -102,33 +106,51 @@ void test_derivative() int main() { - test_parity(); - test_parity(); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - test_parity(); -#endif + #ifdef __STDCPP_FLOAT32_T__ + test_parity(); + test_quadratic(); + test_derivative(); + + #else + + test_parity(); test_quadratic(); - test_quadratic(); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - test_quadratic(); -#endif + test_derivative(); - test_cubic(); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - test_cubic(); -#endif + #endif - test_derivative(); + #ifdef __STDCPP_FLOAT64_T__ + + test_parity(); + test_quadratic(); + test_cubic(); + test_derivative(); + + #else + + test_parity(); + test_quadratic(); + test_cubic(); test_derivative(); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + + #endif + + #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + + test_parity(); + test_quadratic(); + test_cubic(); test_derivative(); -#endif + + #endif -#ifdef BOOST_HAS_FLOAT128 + #ifdef BOOST_HAS_FLOAT128 + test_quadratic(); test_cubic(); -#endif + + #endif return boost::math::test::report_errors(); } diff --git a/test/jacobi_test.cpp b/test/jacobi_test.cpp index cb994cd040..e6c85ec98f 100644 --- a/test/jacobi_test.cpp +++ b/test/jacobi_test.cpp @@ -16,6 +16,10 @@ using boost::multiprecision::float128; #endif +#if __has_include() +# include +#endif + using std::abs; using boost::math::jacobi; using boost::math::jacobi_derivative; @@ -95,28 +99,47 @@ void test_derivative() int main() { - test_to_quadratic(); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - test_to_quadratic(); -#endif + #ifdef __STDCPP_FLOAT32_T__ + + test_symmetry(); + test_derivative(); - test_symmetry(); - test_symmetry(); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - test_symmetry(); -#endif + #else + test_symmetry(); test_derivative(); + + #endif + + #ifdef __STDCPP_FLOAT64_T__ + + test_to_quadratic(); + test_symmetry(); + test_derivative(); + + #else + + test_to_quadratic(); + test_symmetry(); test_derivative(); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + + #endif + + #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + + test_to_quadratic(); + test_symmetry(); test_derivative(); -#endif + + #endif -#ifdef BOOST_HAS_FLOAT128 + #ifdef BOOST_HAS_FLOAT128 + test_to_quadratic(); test_symmetry(); test_derivative(); -#endif + + #endif return boost::math::test::report_errors(); } diff --git a/test/makima_test.cpp b/test/makima_test.cpp index dac617eaea..393c15da3a 100644 --- a/test/makima_test.cpp +++ b/test/makima_test.cpp @@ -16,6 +16,9 @@ using boost::multiprecision::float128; #endif +#if __has_include() +# include +#endif using boost::math::interpolators::makima; @@ -33,7 +36,7 @@ void test_constant() auto y_copy = y; auto akima = makima(std::move(x_copy), std::move(y_copy)); - for (Real t = x[0]; t <= x.back(); t += 0.25) { + for (Real t = x[0]; t <= x.back(); t += Real(0.25)) { CHECK_ULP_CLOSE(Real(7), akima(t), 2); CHECK_ULP_CLOSE(Real(0), akima.prime(t), 2); } @@ -50,7 +53,7 @@ void test_constant() auto circular_akima = makima(std::move(x_buf), std::move(y_buf)); - for (Real t = x[0]; t <= x.back(); t += 0.25) { + for (Real t = x[0]; t <= x.back(); t += Real(0.25)) { CHECK_ULP_CLOSE(Real(7), circular_akima(t), 2); CHECK_ULP_CLOSE(Real(0), akima.prime(t), 2); } @@ -88,7 +91,7 @@ void test_linear() x_copy = x; y_copy = y; akima = makima(std::move(x_copy), std::move(y_copy)); - for (Real t = 0; t < x.back(); t += 0.5) { + for (Real t = 0; t < x.back(); t += Real(0.5)) { CHECK_ULP_CLOSE(t, akima(t), 0); CHECK_ULP_CLOSE(Real(1), akima.prime(t), 0); } @@ -97,7 +100,7 @@ void test_linear() y_copy = y; // Test endpoint derivatives: akima = makima(std::move(x_copy), std::move(y_copy), Real(1), Real(1)); - for (Real t = 0; t < x.back(); t += 0.5) { + for (Real t = 0; t < x.back(); t += Real(0.5)) { CHECK_ULP_CLOSE(t, akima(t), 0); CHECK_ULP_CLOSE(Real(1), akima.prime(t), 0); } @@ -115,7 +118,7 @@ void test_linear() auto circular_akima = makima(std::move(x_buf), std::move(y_buf)); - for (Real t = x[0]; t <= x.back(); t += 0.25) { + for (Real t = x[0]; t <= x.back(); t += Real(0.25)) { CHECK_ULP_CLOSE(t, circular_akima(t), 2); CHECK_ULP_CLOSE(Real(1), circular_akima.prime(t), 2); } @@ -166,13 +169,26 @@ void test_interpolation_condition() int main() { #if (__GNUC__ > 7) || defined(_MSC_VER) || defined(__clang__) + + #ifdef __STDCPP_FLOAT32_T__ + test_constant(); + test_linear(); + test_interpolation_condition(); + #else test_constant(); test_linear(); test_interpolation_condition(); + #endif + #ifdef __STDCPP_FLOAT64_T__ + test_constant(); + test_linear(); + test_interpolation_condition(); + #else test_constant(); test_linear(); test_interpolation_condition(); + #endif test_constant(); test_linear(); diff --git a/test/math_unit_test.hpp b/test/math_unit_test.hpp index 0a526a15a3..786943305e 100644 --- a/test/math_unit_test.hpp +++ b/test/math_unit_test.hpp @@ -90,7 +90,11 @@ bool check_ulp_close(PreciseReal expected1, Real computed, size_t ulps, std::str using boost::math::lltrunc; // Of course integers can be expected values, and they are exact: if (!std::is_integral::value) { - BOOST_MATH_ASSERT_MSG(!isnan(expected1), "Expected value cannot be a nan."); + if (boost::math::isnan(expected1)) { + std::ostringstream oss; + oss << "Error in CHECK_ULP_CLOSE: Expected value cannot be a nan. Callsite: " << filename << ":" << function << ":" << line << "."; + throw std::domain_error(oss.str()); + } if (sizeof(PreciseReal) < sizeof(Real)) { std::ostringstream err; err << "\n\tThe expected number must be computed in higher (or equal) precision than the number being tested.\n"; @@ -100,7 +104,7 @@ bool check_ulp_close(PreciseReal expected1, Real computed, size_t ulps, std::str } } - if (isnan(computed)) + if (boost::math::isnan(computed)) { std::ios_base::fmtflags f( std::cerr.flags() ); std::cerr << std::setprecision(3); diff --git a/test/naive_monte_carlo_test.cpp b/test/naive_monte_carlo_test.cpp index 358ebdd0a9..54f364515f 100644 --- a/test/naive_monte_carlo_test.cpp +++ b/test/naive_monte_carlo_test.cpp @@ -16,6 +16,10 @@ #include #include +#if __has_include() +# include +#endif + using std::abs; using std::vector; using std::pair; @@ -148,9 +152,9 @@ void test_cancel_and_restart() auto task = mc.integrate(); mc.cancel(); - double y = task.get(); + Real y = task.get(); // Super low tolerance; because it got canceled so fast: - BOOST_CHECK_CLOSE_FRACTION(y, exact, 1.0); + BOOST_CHECK_CLOSE_FRACTION(y, exact, static_cast(1.0)); mc.update_target_error((Real) 0.01); task = mc.integrate(); @@ -164,11 +168,13 @@ void test_finite_singular_boundary() std::cout << "Testing that finite singular boundaries work on naive Monte-Carlo integration on type " << boost::typeindex::type_id().pretty_name() << "\n"; using std::pow; using std::log; + using std::log1p; + auto g = [](std::vector const & x)->Real { // The first term is singular at x = 0. // The second at x = 1: - return pow(log(1.0/x[0]), 2) + log1p(-x[0]); + return pow(log(Real(1)/x[0]), Real(2)) + log1p(-x[0]); }; vector> bounds{{Real(0), Real(1)}}; naive_monte_carlo mc(g, bounds, (Real) 0.01, true, 1, 1922); @@ -211,7 +217,7 @@ void test_variance() auto task = mc.integrate(); Real y = task.get(); - BOOST_CHECK_CLOSE_FRACTION(y, 0.5, 0.01); + BOOST_CHECK_CLOSE_FRACTION(y, static_cast(0.5), static_cast(0.01)); BOOST_CHECK_CLOSE_FRACTION(mc.variance(), exact_variance, 0.05); } @@ -452,93 +458,249 @@ BOOST_AUTO_TEST_CASE(naive_monte_carlo_test) { std::cout << "Default hardware concurrency = " << std::thread::hardware_concurrency() << std::endl; #if !defined(TEST) || TEST == 1 + +#if defined(__STDCPP_FLOAT32_T__) && defined(__STDCPP_FLOAT64_T__) + test_finite_singular_boundary(); + test_finite_singular_boundary(); +#else test_finite_singular_boundary(); test_finite_singular_boundary(); #endif + +#endif #if !defined(TEST) || TEST == 2 + +#if defined(__STDCPP_FLOAT32_T__) && defined(__STDCPP_FLOAT64_T__) + test_pi(); + test_pi(); +#else test_pi(); test_pi(); #endif + +#endif #if !defined(TEST) || TEST == 3 + +#ifdef __STDCPP_FLOAT32_T__ + test_pi_multithreaded(); + test_constant(); +#else test_pi_multithreaded(); test_constant(); +#endif + #endif //test_pi(); #if !defined(TEST) || TEST == 4 + +#if defined(__STDCPP_FLOAT32_T__) && defined(__STDCPP_FLOAT64_T__) + test_constant(); + test_cancel_and_restart(); +#else test_constant(); //test_constant(); test_cancel_and_restart(); #endif + +#endif #if !defined(TEST) || TEST == 5 + +#ifdef __STDCPP_FLOAT32_T__ + test_exception_from_integrand(); + test_variance(); +#else test_exception_from_integrand(); test_variance(); #endif + +#endif #if !defined(TEST) || TEST == 6 + +#ifdef __STDCPP_FLOAT64_T__ + test_variance(); + test_multithreaded_variance(); +#else test_variance(); test_multithreaded_variance(); #endif + +#endif #if !defined(TEST) || TEST == 7 + +#ifdef __STDCPP_FLOAT32_T__ + test_product(); + test_product(); +#else test_product(); test_product(); #endif + +#endif #if !defined(TEST) || TEST == 8 + +#ifdef __STDCPP_FLOAT32_T__ + test_product(); + test_product(); + test_product(); +#else test_product(); test_product(); test_product(); #endif + +#endif #if !defined(TEST) || TEST == 9 + +#if defined(__STDCPP_FLOAT32_T__) && defined(__STDCPP_FLOAT64_T__) + test_product(); + test_product(); +#else test_product(); test_product(); #endif + +#endif #if !defined(TEST) || TEST == 10 + +#ifdef __STDCPP_FLOAT64_T__ + test_product(); +#else test_product(); #endif + +#endif #if !defined(TEST) || TEST == 11 + +#ifdef __STDCPP_FLOAT64_T__ + test_product(); + test_product(); +#else test_product(); test_product(); #endif + +#endif #if !defined(TEST) || TEST == 12 + +#if defined(__STDCPP_FLOAT32_T__) && defined(__STDCPP_FLOAT64_T__) + test_upper_bound_infinite(); + test_upper_bound_infinite(); +#else test_upper_bound_infinite(); test_upper_bound_infinite(); #endif + +#endif #if !defined(TEST) || TEST == 13 + +#if defined(__STDCPP_FLOAT32_T__) && defined(__STDCPP_FLOAT64_T__) + test_lower_bound_infinite(); + test_lower_bound_infinite(); +#else test_lower_bound_infinite(); test_lower_bound_infinite(); #endif + +#endif #if !defined(TEST) || TEST == 14 + +#ifdef __STDCPP_FLOAT32_T__ + test_lower_bound_infinite2(); +#else test_lower_bound_infinite2(); #endif + +#endif #if !defined(TEST) || TEST == 15 + +#if defined(__STDCPP_FLOAT32_T__) && defined(__STDCPP_FLOAT64_T__) + test_double_infinite(); + test_double_infinite(); +#else test_double_infinite(); test_double_infinite(); #endif + +#endif #if !defined(TEST) || TEST == 16 + +#ifdef __STDCPP_FLOAT32_T__ + test_radovic(); + test_radovic(); +#else test_radovic(); test_radovic(); #endif + +#endif #if !defined(TEST) || TEST == 17 + +#if defined(__STDCPP_FLOAT32_T__) && defined(__STDCPP_FLOAT64_T__) + test_radovic(); + test_radovic(); +#else test_radovic(); test_radovic(); #endif + +#endif #if !defined(TEST) || TEST == 18 + +#ifdef __STDCPP_FLOAT64_T__ + test_radovic(); + test_radovic(); +#else test_radovic(); test_radovic(); #endif + +#endif #if !defined(TEST) || TEST == 19 + +#ifdef __STDCPP_FLOAT64_T__ + test_radovic(); + test_radovic(); +#else test_radovic(); test_radovic(); #endif + +#endif #if !defined(TEST) || TEST == 20 + +#ifdef __STDCPP_FLOAT32_T__ + test_alternative_rng_1(); +#else test_alternative_rng_1(); #endif + +#endif #if !defined(TEST) || TEST == 21 + +#ifdef __STDCPP_FLOAT64_T__ + test_alternative_rng_1(); +#else test_alternative_rng_1(); #endif + +#endif #if !defined(TEST) || TEST == 22 + +#ifdef __STDCPP_FLOAT32_T__ + test_alternative_rng_2(); +#else test_alternative_rng_2(); #endif + +#endif #if !defined(TEST) || TEST == 23 + +#ifdef __STDCPP_FLOAT64_T__ + test_alternative_rng_2(); +#else test_alternative_rng_2(); #endif +#endif + } diff --git a/test/pchip_test.cpp b/test/pchip_test.cpp index 17db19a332..6e8ea235bf 100644 --- a/test/pchip_test.cpp +++ b/test/pchip_test.cpp @@ -17,6 +17,9 @@ using boost::multiprecision::float128; #endif +#if __has_include() +# include +#endif using boost::math::interpolators::pchip; @@ -35,7 +38,7 @@ void test_constant() auto pchip_spline = pchip(std::move(x_copy), std::move(y_copy)); //std::cout << "Constant value pchip spline = " << pchip_spline << "\n"; - for (Real t = x[0]; t <= x.back(); t += 0.25) { + for (Real t = x[0]; t <= x.back(); t += Real(0.25)) { CHECK_ULP_CLOSE(Real(7), pchip_spline(t), 2); CHECK_ULP_CLOSE(Real(0), pchip_spline.prime(t), 2); } @@ -52,7 +55,7 @@ void test_constant() auto circular_pchip_spline = pchip(std::move(x_buf), std::move(y_buf)); - for (Real t = x[0]; t <= x.back(); t += 0.25) { + for (Real t = x[0]; t <= x.back(); t += Real(0.25)) { CHECK_ULP_CLOSE(Real(7), circular_pchip_spline(t), 2); CHECK_ULP_CLOSE(Real(0), pchip_spline.prime(t), 2); } @@ -90,7 +93,7 @@ void test_linear() x_copy = x; y_copy = y; pchip_spline = pchip(std::move(x_copy), std::move(y_copy)); - for (Real t = 0; t < x.back(); t += 0.5) { + for (Real t = 0; t < x.back(); t += Real(0.5)) { CHECK_ULP_CLOSE(t, pchip_spline(t), 0); CHECK_ULP_CLOSE(Real(1), pchip_spline.prime(t), 0); } @@ -99,7 +102,7 @@ void test_linear() y_copy = y; // Test endpoint derivatives: pchip_spline = pchip(std::move(x_copy), std::move(y_copy), Real(1), Real(1)); - for (Real t = 0; t < x.back(); t += 0.5) { + for (Real t = 0; t < x.back(); t += Real(0.5)) { CHECK_ULP_CLOSE(t, pchip_spline(t), 0); CHECK_ULP_CLOSE(Real(1), pchip_spline.prime(t), 0); } @@ -117,7 +120,7 @@ void test_linear() auto circular_pchip_spline = pchip(std::move(x_buf), std::move(y_buf)); - for (Real t = x[0]; t <= x.back(); t += 0.25) { + for (Real t = x[0]; t <= x.back(); t += Real(0.25)) { CHECK_ULP_CLOSE(t, circular_pchip_spline(t), 2); CHECK_ULP_CLOSE(Real(1), circular_pchip_spline.prime(t), 2); } @@ -230,25 +233,40 @@ void test_monotonicity() int main() { #if (__GNUC__ > 7) || defined(_MSC_VER) || defined(__clang__) + + #ifdef __STDCPP_FLOAT32_T__ + test_constant(); + test_linear(); + test_interpolation_condition(); + test_monotonicity(); + #else test_constant(); test_linear(); test_interpolation_condition(); test_monotonicity(); - + #endif + + #ifdef __STDCPP_FLOAT64_T__ + test_constant(); + test_linear(); + test_interpolation_condition(); + test_monotonicity(); + #else test_constant(); test_linear(); test_interpolation_condition(); test_monotonicity(); + #endif test_constant(); test_linear(); test_interpolation_condition(); test_monotonicity(); -#ifdef BOOST_HAS_FLOAT128 + #ifdef BOOST_HAS_FLOAT128 test_constant(); test_linear(); -#endif + #endif #endif return boost::math::test::report_errors(); } diff --git a/test/quintic_hermite_test.cpp b/test/quintic_hermite_test.cpp index 5dfb1f5270..d2deec7709 100644 --- a/test/quintic_hermite_test.cpp +++ b/test/quintic_hermite_test.cpp @@ -20,6 +20,9 @@ using boost::multiprecision::float128; #endif +#if __has_include() +# include +#endif using boost::math::interpolators::quintic_hermite; using boost::math::interpolators::cardinal_quintic_hermite; @@ -38,7 +41,7 @@ void test_constant() } auto qh = quintic_hermite(std::move(x), std::move(y), std::move(dydx), std::move(d2ydx2)); - for (Real t = 0; t <= 81; t += 0.25) + for (Real t = 0; t <= 81; t += Real(0.25)) { CHECK_ULP_CLOSE(Real(7), qh(t), 24); CHECK_ULP_CLOSE(Real(0), qh.prime(t), 24); @@ -57,7 +60,7 @@ void test_linear() auto qh = quintic_hermite(std::move(x), std::move(y), std::move(dydx), std::move(d2ydx2)); - for (Real t = 0; t <= 9; t += 0.25) + for (Real t = 0; t <= 9; t += Real(0.25)) { CHECK_ULP_CLOSE(Real(t), qh(t), 2); CHECK_ULP_CLOSE(Real(1), qh.prime(t), 2); @@ -65,7 +68,7 @@ void test_linear() } boost::random::mt19937 rng; - boost::random::uniform_real_distribution dis(0.5,1); + boost::random::uniform_real_distribution dis(Real(0.5), Real(1)); x.resize(512); x[0] = dis(rng); Real xmin = x[0]; @@ -81,7 +84,7 @@ void test_linear() qh = quintic_hermite(std::move(x), std::move(y), std::move(dydx), std::move(d2ydx2)); - for (Real t = xmin; t <= xmax; t += 0.125) + for (Real t = xmin; t <= xmax; t += Real(0.125)) { CHECK_ULP_CLOSE(t, qh(t), 2); CHECK_ULP_CLOSE(Real(1), qh.prime(t), 100); @@ -109,7 +112,7 @@ void test_quadratic() auto qh = quintic_hermite(std::move(x), std::move(y), std::move(dydx), std::move(d2ydx2)); - for (Real t = 0; t <= 9; t += 0.0078125) + for (Real t = 0; t <= 9; t += Real(0.0078125)) { CHECK_ULP_CLOSE(Real(t*t)/2, qh(t), 2); CHECK_ULP_CLOSE(t, qh.prime(t), 12); @@ -117,7 +120,7 @@ void test_quadratic() } boost::random::mt19937 rng; - boost::random::uniform_real_distribution dis(0.5,1); + boost::random::uniform_real_distribution dis(Real(0.5), Real(1)); x.resize(8); x[0] = dis(rng); Real xmin = x[0]; @@ -143,7 +146,7 @@ void test_quadratic() qh = quintic_hermite(std::move(x), std::move(y), std::move(dydx), std::move(d2ydx2)); - for (Real t = xmin; t <= xmax; t += 0.125) + for (Real t = xmin; t <= xmax; t += Real(0.125)) { CHECK_ULP_CLOSE(Real(t*t)/2, qh(t), 4); CHECK_ULP_CLOSE(t, qh.prime(t), 53); @@ -175,7 +178,7 @@ void test_cubic() auto qh = quintic_hermite(std::move(x), std::move(y), std::move(dydx), std::move(d2ydx2)); - for (Real t = 0; t <= 9; t += 0.0078125) + for (Real t = 0; t <= 9; t += Real(0.0078125)) { CHECK_ULP_CLOSE(t*t*t, qh(t), 10); CHECK_ULP_CLOSE(3*t*t, qh.prime(t), 15); @@ -208,7 +211,7 @@ void test_quartic() auto qh = quintic_hermite(std::move(x), std::move(y), std::move(dydx), std::move(d2ydx2)); - for (Real t = 1; t <= 11; t += 0.0078125) + for (Real t = 1; t <= 11; t += Real(0.0078125)) { CHECK_ULP_CLOSE(t*t*t*t, qh(t), 100); CHECK_ULP_CLOSE(4*t*t*t, qh.prime(t), 100); @@ -266,7 +269,7 @@ void test_cardinal_constant() auto qh = cardinal_quintic_hermite(std::move(y), std::move(dydx), std::move(d2ydx2), x0, dx); - for (Real t = x0; t <= x0 + 24*dx; t += 0.25) + for (Real t = x0; t <= x0 + 24*dx; t += Real(0.25)) { CHECK_ULP_CLOSE(Real(7), qh(t), 24); CHECK_ULP_CLOSE(Real(0), qh.prime(t), 24); @@ -282,7 +285,7 @@ void test_cardinal_constant() } auto qh_aos = cardinal_quintic_hermite_aos(std::move(data), x0, dx); - for (Real t = x0; t <= x0 + 24*dx; t += 0.25) + for (Real t = x0; t <= x0 + 24*dx; t += Real(0.25)) { CHECK_ULP_CLOSE(Real(7), qh_aos(t), 24); CHECK_ULP_CLOSE(Real(0), qh_aos.prime(t), 24); @@ -321,7 +324,7 @@ void test_cardinal_linear() auto qh = cardinal_quintic_hermite(std::move(y), std::move(dydx), std::move(d2ydx2), x0, dx); - for (Real t = 0; t <= 9; t += 0.25) { + for (Real t = 0; t <= 9; t += Real(0.25)) { CHECK_ULP_CLOSE(Real(t), qh(t), 2); CHECK_ULP_CLOSE(Real(1), qh.prime(t), 2); CHECK_ULP_CLOSE(Real(0), qh.double_prime(t), 2); @@ -336,7 +339,7 @@ void test_cardinal_linear() auto qh_aos = cardinal_quintic_hermite_aos(std::move(data), x0, dx); - for (Real t = 0; t <= 9; t += 0.25) { + for (Real t = 0; t <= 9; t += Real(0.25)) { CHECK_ULP_CLOSE(Real(t), qh_aos(t), 2); CHECK_ULP_CLOSE(Real(1), qh_aos.prime(t), 2); CHECK_ULP_CLOSE(Real(0), qh_aos.double_prime(t), 2); @@ -382,7 +385,7 @@ void test_cardinal_quadratic() auto qh = cardinal_quintic_hermite(std::move(y), std::move(dydx), std::move(d2ydx2), x0, dx); - for (Real t = 0; t <= 9; t += 0.0078125) { + for (Real t = 0; t <= 9; t += Real(0.0078125)) { Real computed = qh(t); CHECK_ULP_CLOSE(Real(t*t)/2, computed, 2); CHECK_ULP_CLOSE(t, qh.prime(t), 15); @@ -397,7 +400,7 @@ void test_cardinal_quadratic() } auto qh_aos = cardinal_quintic_hermite_aos(std::move(data), x0, dx); - for (Real t = 0; t <= 9; t += 0.0078125) + for (Real t = 0; t <= 9; t += Real(0.0078125)) { Real computed = qh_aos(t); CHECK_ULP_CLOSE(Real(t*t)/2, computed, 2); @@ -448,7 +451,7 @@ void test_cardinal_cubic() auto qh = cardinal_quintic_hermite(std::move(y), std::move(dydx), std::move(d2ydx2), x0, dx); - for (Real t = 0; t <= 9; t += 0.0078125) + for (Real t = 0; t <= 9; t += Real(0.0078125)) { Real computed = qh(t); CHECK_ULP_CLOSE(t*t*t, computed, 10); @@ -464,7 +467,7 @@ void test_cardinal_cubic() } auto qh_aos = cardinal_quintic_hermite_aos(std::move(data), x0, dx); - for (Real t = 0; t <= 9; t += 0.0078125) + for (Real t = 0; t <= 9; t += Real(0.0078125)) { Real computed = qh_aos(t); CHECK_ULP_CLOSE(t*t*t, computed, 10); @@ -496,7 +499,7 @@ void test_cardinal_quartic() auto qh = cardinal_quintic_hermite(std::move(y), std::move(dydx), std::move(d2ydx2), x0, dx); - for (Real t = 0; t <= 6; t += 0.0078125) + for (Real t = 0; t <= 6; t += Real(0.0078125)) { CHECK_ULP_CLOSE(Real(t*t*t*t), qh(t), 250); CHECK_ULP_CLOSE(4*t*t*t, qh.prime(t), 250); @@ -511,7 +514,7 @@ void test_cardinal_quartic() } auto qh_aos = cardinal_quintic_hermite_aos(std::move(data), x0, dx); - for (Real t = 0; t <= 6; t += 0.0078125) + for (Real t = 0; t <= 6; t += Real(0.0078125)) { Real computed = qh_aos(t); CHECK_ULP_CLOSE(t*t*t*t, computed, 10); @@ -523,6 +526,20 @@ void test_cardinal_quartic() int main() { + #ifdef __STDCPP_FLOAT32_T__ + test_constant(); + test_linear(); + test_quadratic(); + test_cubic(); + test_quartic(); + test_interpolation_condition(); + + test_cardinal_constant(); + test_cardinal_linear(); + test_cardinal_quadratic(); + test_cardinal_cubic(); + test_cardinal_quartic(); + #else test_constant(); test_linear(); test_quadratic(); @@ -535,7 +552,22 @@ int main() test_cardinal_quadratic(); test_cardinal_cubic(); test_cardinal_quartic(); - + #endif + + #ifdef __STDCPP_FLOAT64_T__ + test_constant(); + test_linear(); + test_quadratic(); + test_cubic(); + test_quartic(); + test_interpolation_condition(); + + test_cardinal_constant(); + test_cardinal_linear(); + test_cardinal_quadratic(); + test_cardinal_cubic(); + test_cardinal_quartic(); + #else test_constant(); test_linear(); test_quadratic(); @@ -548,6 +580,7 @@ int main() test_cardinal_quadratic(); test_cardinal_cubic(); test_cardinal_quartic(); + #endif test_constant(); test_linear(); @@ -562,7 +595,7 @@ int main() test_cardinal_cubic(); test_cardinal_quartic(); -#ifdef BOOST_HAS_FLOAT128 + #ifdef BOOST_HAS_FLOAT128 test_constant(); //test_linear(); test_quadratic(); @@ -574,7 +607,7 @@ int main() test_cardinal_quadratic(); test_cardinal_cubic(); test_cardinal_quartic(); -#endif + #endif return boost::math::test::report_errors(); } diff --git a/test/rsqrt_test.cpp b/test/rsqrt_test.cpp index f41402f150..53852289c4 100644 --- a/test/rsqrt_test.cpp +++ b/test/rsqrt_test.cpp @@ -13,6 +13,11 @@ #include #include #include + +#if __has_include() +# include +#endif + #ifdef BOOST_HAS_FLOAT128 #include using boost::multiprecision::float128; @@ -27,7 +32,7 @@ void test_rsqrt() using std::sqrt; Real x = (std::numeric_limits::min)(); while (x < 10000*std::numeric_limits::epsilon()) { - Real expected = 1/sqrt(x); + Real expected = Real(1)/sqrt(x); Real computed = rsqrt(x); if(!CHECK_ULP_CLOSE(expected, computed, 2)) { std::cerr << " 1/sqrt(" << x << ") is computed incorrectly.\n"; @@ -38,7 +43,7 @@ void test_rsqrt() // x ~ 1: x = 1; while (x < 1 + 1000*std::numeric_limits::epsilon()) { - Real expected = 1/sqrt(x); + Real expected = Real(1)/sqrt(x); Real computed = rsqrt(x); if(!CHECK_ULP_CLOSE(expected, computed, 2)) { std::cerr << " 1/sqrt(" << x << ") is computed incorrectly.\n"; @@ -49,7 +54,7 @@ void test_rsqrt() // x ~ 1000: x = 1000; while (x < 1000 + 1000*1000*std::numeric_limits::epsilon()) { - Real expected = 1/sqrt(x); + Real expected = Real(1)/sqrt(x); Real computed = rsqrt(x); if(!CHECK_ULP_CLOSE(expected, computed, 2)) { std::cerr << " 1/sqrt(" << x << ") is computed incorrectly.\n"; @@ -58,14 +63,14 @@ void test_rsqrt() } x = std::numeric_limits::infinity(); - Real expected = 1/sqrt(x); + Real expected = Real(1)/sqrt(x); Real computed = rsqrt(x); if (!CHECK_ULP_CLOSE(expected, computed, 0)) { std::cerr << "Reciprocal square root of infinity not correctly computed.\n"; } x = (std::numeric_limits::max)(); - expected = 1/sqrt(x); + expected = Real(1)/sqrt(x); computed = rsqrt(x); if (!CHECK_EQUAL(expected, computed)) { std::cerr << "Reciprocal square root of std::numeric_limits::max() not correctly computed.\n"; @@ -79,8 +84,18 @@ void test_rsqrt() int main() { + #ifdef __STDCPP_FLOAT32_T__ + test_rsqrt(); + #else test_rsqrt(); + #endif + + #ifdef __STDCPP_FLOAT64_T__ + test_rsqrt(); + #else test_rsqrt(); + #endif + test_rsqrt(); test_rsqrt(); test_rsqrt(); diff --git a/test/septic_hermite_test.cpp b/test/septic_hermite_test.cpp index a7bd81f9df..119e626191 100644 --- a/test/septic_hermite_test.cpp +++ b/test/septic_hermite_test.cpp @@ -18,6 +18,9 @@ using boost::multiprecision::float128; #endif +#if __has_include() +# include +#endif using boost::math::interpolators::septic_hermite; using boost::math::interpolators::cardinal_septic_hermite; @@ -39,7 +42,7 @@ void test_constant() auto sh = septic_hermite(std::move(x), std::move(y), std::move(dydx), std::move(d2ydx2), std::move(d3ydx3)); - for (Real t = 0; t <= 81; t += 0.25) + for (Real t = 0; t <= 81; t += Real(0.25)) { CHECK_ULP_CLOSE(Real(7), sh(t), 24); CHECK_ULP_CLOSE(Real(0), sh.prime(t), 24); @@ -52,7 +55,7 @@ void test_constant() d2ydx2.resize(128, 0); d3ydx3.resize(128, 0); auto csh = cardinal_septic_hermite(std::move(y), std::move(dydx), std::move(d2ydx2), std::move(d3ydx3), x0, dx); - for (Real t = x0; t <= 127; t += 0.25) + for (Real t = x0; t <= 127; t += Real(0.25)) { CHECK_ULP_CLOSE(Real(7), csh(t), 24); CHECK_ULP_CLOSE(Real(0), csh.prime(t), 24); @@ -68,7 +71,7 @@ void test_constant() data[i][3] = 0; } auto csh_aos = cardinal_septic_hermite_aos(std::move(data), x0, dx); - for (Real t = x0; t <= 127; t += 0.25) + for (Real t = x0; t <= 127; t += Real(0.25)) { CHECK_ULP_CLOSE(Real(7), csh_aos(t), 24); CHECK_ULP_CLOSE(Real(0), csh_aos.prime(t), 24); @@ -112,14 +115,14 @@ void test_linear() auto sh = septic_hermite(std::move(x), std::move(y), std::move(dydx), std::move(d2ydx2), std::move(d3ydx3)); - for (Real t = 0; t <= 9; t += 0.25) + for (Real t = 0; t <= 9; t += Real(0.25)) { CHECK_ULP_CLOSE(Real(t), sh(t), 2); CHECK_ULP_CLOSE(Real(1), sh.prime(t), 2); } boost::random::mt19937 rng; - boost::random::uniform_real_distribution dis(0.5,1); + boost::random::uniform_real_distribution dis(Real(0.5), Real(1)); x.resize(512); x[0] = dis(rng); Real xmin = x[0]; @@ -136,7 +139,7 @@ void test_linear() sh = septic_hermite(std::move(x), std::move(y), std::move(dydx), std::move(d2ydx2), std::move(d3ydx3)); - for (Real t = xmin; t <= xmax; t += 0.125) + for (Real t = xmin; t <= xmax; t += Real(0.125)) { CHECK_ULP_CLOSE(t, sh(t), 25); CHECK_ULP_CLOSE(Real(1), sh.prime(t), 850); @@ -153,7 +156,7 @@ void test_linear() y[i] = i; } auto csh = cardinal_septic_hermite(std::move(y), std::move(dydx), std::move(d2ydx2), std::move(d3ydx3), x0, dx); - for (Real t = 0; t <= 9; t += 0.125) + for (Real t = 0; t <= 9; t += Real(0.125)) { CHECK_ULP_CLOSE(t, csh(t), 15); CHECK_ULP_CLOSE(Real(1), csh.prime(t), 15); @@ -169,7 +172,7 @@ void test_linear() data[i][3] = 0; } auto csh_aos = cardinal_septic_hermite_aos(std::move(data), x0, dx); - for (Real t = 0; t <= 9; t += 0.125) + for (Real t = 0; t <= 9; t += Real(0.125)) { CHECK_ULP_CLOSE(t, csh_aos(t), 15); CHECK_ULP_CLOSE(Real(1), csh_aos.prime(t), 15); @@ -222,14 +225,14 @@ void test_quadratic() auto sh = septic_hermite(std::move(x), std::move(y), std::move(dydx), std::move(d2ydx2), std::move(d3ydx3)); - for (Real t = 0; t <= 9; t += 0.0078125) + for (Real t = 0; t <= 9; t += Real(0.0078125)) { CHECK_ULP_CLOSE(t*t/2, sh(t), 100); CHECK_ULP_CLOSE(t, sh.prime(t), 32); } boost::random::mt19937 rng; - boost::random::uniform_real_distribution dis(0.5,1); + boost::random::uniform_real_distribution dis(Real(0.5), Real(1)); x.resize(8); x[0] = dis(rng); Real xmin = x[0]; @@ -256,7 +259,7 @@ void test_quadratic() sh = septic_hermite(std::move(x), std::move(y), std::move(dydx), std::move(d2ydx2), std::move(d3ydx3)); - for (Real t = xmin; t <= xmax; t += 0.125) + for (Real t = xmin; t <= xmax; t += Real(0.125)) { CHECK_ULP_CLOSE(t*t/2, sh(t), 50); CHECK_ULP_CLOSE(t, sh.prime(t), 300); @@ -280,7 +283,7 @@ void test_quadratic() Real x0 = 0; Real dx = 1; auto csh = cardinal_septic_hermite(std::move(y), std::move(dydx), std::move(d2ydx2), std::move(d3ydx3), x0, dx); - for (Real t = x0; t <= 9; t += 0.125) + for (Real t = x0; t <= 9; t += Real(0.125)) { CHECK_ULP_CLOSE(t*t/2, csh(t), 24); CHECK_ULP_CLOSE(t, csh.prime(t), 24); @@ -296,7 +299,7 @@ void test_quadratic() data[i][3] = 0; } auto csh_aos = cardinal_septic_hermite_aos(std::move(data), x0, dx); - for (Real t = x0; t <= 9; t += 0.125) + for (Real t = x0; t <= 9; t += Real(0.125)) { CHECK_ULP_CLOSE(t*t/2, csh_aos(t), 24); CHECK_ULP_CLOSE(t, csh_aos.prime(t), 24); @@ -333,7 +336,7 @@ void test_cubic() auto sh = septic_hermite(std::move(x), std::move(y), std::move(dydx), std::move(d2ydx2), std::move(d3ydx3)); - for (Real t = 0; t <= xmax; t += 0.0078125) + for (Real t = 0; t <= xmax; t += Real(0.0078125)) { CHECK_ULP_CLOSE(t*t*t, sh(t), 151); CHECK_ULP_CLOSE(3*t*t, sh.prime(t), 151); @@ -354,7 +357,7 @@ void test_cubic() auto csh = cardinal_septic_hermite(std::move(y), std::move(dydx), std::move(d2ydx2), std::move(d3ydx3), x0, dx); - for (Real t = 0; t <= xmax; t += 0.0078125) + for (Real t = 0; t <= xmax; t += Real(0.0078125)) { CHECK_ULP_CLOSE(t*t*t, csh(t), 151); CHECK_ULP_CLOSE(3*t*t, csh.prime(t), 151); @@ -371,7 +374,7 @@ void test_cubic() auto csh_aos = cardinal_septic_hermite_aos(std::move(data), x0, dx); - for (Real t = 0; t <= xmax; t += 0.0078125) + for (Real t = 0; t <= xmax; t += Real(0.0078125)) { CHECK_ULP_CLOSE(t*t*t, csh_aos(t), 151); CHECK_ULP_CLOSE(3*t*t, csh_aos.prime(t), 151); @@ -411,7 +414,7 @@ void test_quartic() auto sh = septic_hermite(std::move(x), std::move(y), std::move(dydx), std::move(d2ydx2), std::move(d3ydx3)); - for (Real t = 1; t <= xmax; t += 0.0078125) { + for (Real t = 1; t <= xmax; t += Real(0.0078125)) { CHECK_ULP_CLOSE(t*t*t*t, sh(t), 117); CHECK_ULP_CLOSE(4*t*t*t, sh.prime(t), 117); } @@ -430,7 +433,7 @@ void test_quartic() auto csh = cardinal_septic_hermite(std::move(y), std::move(dydx), std::move(d2ydx2), std::move(d3ydx3), Real(0), Real(1)); - for (Real t = 1; t <= xmax; t += 0.0078125) + for (Real t = 1; t <= xmax; t += Real(0.0078125)) { CHECK_ULP_CLOSE(t*t*t*t, csh(t), 117); CHECK_ULP_CLOSE(4*t*t*t, csh.prime(t), 117); @@ -447,7 +450,7 @@ void test_quartic() } auto csh_aos = cardinal_septic_hermite_aos(std::move(data), Real(0), Real(1)); - for (Real t = 1; t <= xmax; t += 0.0078125) + for (Real t = 1; t <= xmax; t += Real(0.0078125)) { CHECK_ULP_CLOSE(t*t*t*t, csh_aos(t), 117); CHECK_ULP_CLOSE(4*t*t*t, csh_aos.prime(t), 117); @@ -496,19 +499,37 @@ void test_interpolation_condition() int main() { + #ifdef __STDCPP_FLOAT32_T__ + test_constant(); + test_linear(); + test_quadratic(); + test_cubic(); + test_quartic(); + test_interpolation_condition(); + #else test_constant(); test_linear(); test_quadratic(); test_cubic(); test_quartic(); test_interpolation_condition(); - + #endif + + #ifdef __STDCPP_FLOAT64_T__ + test_constant(); + test_linear(); + test_quadratic(); + test_cubic(); + test_quartic(); + test_interpolation_condition(); + #else test_constant(); test_linear(); test_quadratic(); test_cubic(); test_quartic(); test_interpolation_condition(); + #endif test_constant(); test_linear(); @@ -517,14 +538,14 @@ int main() test_quartic(); test_interpolation_condition(); -#ifdef BOOST_HAS_FLOAT128 + #ifdef BOOST_HAS_FLOAT128 test_constant(); test_linear(); test_quadratic(); test_cubic(); test_quartic(); test_interpolation_condition(); -#endif + #endif return boost::math::test::report_errors(); } diff --git a/test/tanh_sinh_quadrature_test.cpp b/test/tanh_sinh_quadrature_test.cpp index e06c3cfd49..ceccb29ebb 100644 --- a/test/tanh_sinh_quadrature_test.cpp +++ b/test/tanh_sinh_quadrature_test.cpp @@ -26,6 +26,10 @@ #include #include +#if __has_include() +# include +#endif + #ifdef BOOST_HAS_FLOAT128 #include #endif @@ -229,12 +233,12 @@ void test_linear() Real error; Real L1; Real Q = integrator.integrate(f, (Real) 0, (Real) 1, get_convergence_tolerance(), &error, &L1); - BOOST_CHECK_CLOSE_FRACTION(Q, 9.5, tol); - BOOST_CHECK_CLOSE_FRACTION(L1, 9.5, tol); - Q = integrator.integrate(f, (Real) 1, (Real) 0, get_convergence_tolerance(), &error, &L1); - BOOST_CHECK_CLOSE_FRACTION(Q, -9.5, tol); - BOOST_CHECK_CLOSE_FRACTION(L1, 9.5, tol); - Q = integrator.integrate(f, (Real) 1, (Real) 1, get_convergence_tolerance(), &error, &L1); + BOOST_CHECK_CLOSE_FRACTION(Q, static_cast(9.5), tol); + BOOST_CHECK_CLOSE_FRACTION(L1, static_cast(9.5), tol); + Q = integrator.integrate(f, static_cast(1), static_cast(0), get_convergence_tolerance(), &error, &L1); + BOOST_CHECK_CLOSE_FRACTION(Q, static_cast(-9.5), tol); + BOOST_CHECK_CLOSE_FRACTION(L1, static_cast(9.5), tol); + Q = integrator.integrate(f, static_cast(1), static_cast(1), get_convergence_tolerance(), &error, &L1); BOOST_CHECK_EQUAL(Q, Real(0)); } @@ -318,8 +322,14 @@ void test_ca() // Slightly higher tolerance for type float, this marginal change was // caused by no more than changing the order in which the terms are summed: // - if (std::is_same::value) - tol *= 1.5; + BOOST_IF_CONSTEXPR (std::is_same::value + #ifdef __STDCPP_FLOAT32_T__ + || std::is_same::value + #endif + ) + { + tol *= static_cast(1.5); + } BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); BOOST_CHECK_CLOSE_FRACTION(L1, Q_expected, tol); @@ -896,6 +906,20 @@ BOOST_AUTO_TEST_CASE(tanh_sinh_quadrature_test) test_horrible(); test_integration_over_real_line(); test_nr_examples(); + + #ifdef __STDCPP_FLOAT32_T__ + test_right_limit_infinite(); + test_left_limit_infinite(); + test_linear(); + test_quadratic(); + test_singular(); + test_ca(); + test_three_quadrature_schemes_examples(); + test_horrible(); + test_integration_over_real_line(); + test_nr_examples(); + #endif + #endif #ifdef TEST1A test_early_termination(); diff --git a/test/test_autodiff.hpp b/test/test_autodiff.hpp index 7f3c98b203..3a53827262 100644 --- a/test/test_autodiff.hpp +++ b/test/test_autodiff.hpp @@ -31,16 +31,24 @@ #include #include +#if __has_include() +# include +#endif + namespace mp11 = boost::mp11; namespace bmp = boost::multiprecision; namespace diff = boost::math::differentiation::autodiff_v1::detail; + #if defined(BOOST_USE_VALGRIND) || defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS) using bin_float_types = mp11::mp_list; +#elif defined(__STDCPP_FLOAT32_T__) && defined(__STDCPP_FLOAT64_T__) +using bin_float_types = mp11::mp_list; #else using bin_float_types = mp11::mp_list; #endif + // cpp_dec_float_50 cannot be used with close_at_tolerance /*using multiprecision_float_types = mp_list;*/ diff --git a/test/test_autodiff_1.cpp b/test/test_autodiff_1.cpp index 9417d78bff..144f610516 100644 --- a/test/test_autodiff_1.cpp +++ b/test/test_autodiff_1.cpp @@ -22,7 +22,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(constructors, T, all_float_types) { } } // Single variable - const T cx = 10.0; + const T cx = 10; const auto x = make_fvar(cx); for (auto i : boost::irange(m + 1)) { if (i == 0u) { @@ -44,16 +44,16 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(constructors, T, all_float_types) { } } // Second independent variable - const T cy = 100.0; + const T cy = 100; const auto y = make_fvar(cy); for (auto i : boost::irange(m + 1)) { for (auto j : boost::irange(n + 1)) { if (i == 0 && j == 0) { BOOST_CHECK_EQUAL(y.derivative(i, j), cy); } else if (i == 0 && j == 1) { - BOOST_CHECK_EQUAL(y.derivative(i, j), 1.0); + BOOST_CHECK_EQUAL(y.derivative(i, j), static_cast(1.0)); } else { - BOOST_CHECK_EQUAL(y.derivative(i, j), 0.0); + BOOST_CHECK_EQUAL(y.derivative(i, j), static_cast(0.0)); } } } @@ -64,16 +64,16 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(implicit_constructors, T, all_float_types) { const autodiff_fvar x = 3; const autodiff_fvar one = uncast_return(x); const autodiff_fvar two_and_a_half = 2.5; - BOOST_CHECK_EQUAL(static_cast(x), 3.0); - BOOST_CHECK_EQUAL(static_cast(one), 1.0); - BOOST_CHECK_EQUAL(static_cast(two_and_a_half), 2.5); + BOOST_CHECK_EQUAL(static_cast(x), static_cast(3.0)); + BOOST_CHECK_EQUAL(static_cast(one), static_cast(1.0)); + BOOST_CHECK_EQUAL(static_cast(two_and_a_half), static_cast(2.5)); } BOOST_AUTO_TEST_CASE_TEMPLATE(assignment, T, all_float_types) { constexpr std::size_t m = 3; constexpr std::size_t n = 4; - const T cx = 10.0; - const T cy = 10.0; + const T cx = 10; + const T cy = 10; autodiff_fvar empty; // Uninitialized variable<> may have non-zero values. // Single variable @@ -132,7 +132,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(ostream, T, all_float_types) { BOOST_AUTO_TEST_CASE_TEMPLATE(addition_assignment, T, all_float_types) { constexpr std::size_t m = 3; constexpr std::size_t n = 4; - const T cx = 10.0; + const T cx = 10; auto sum = autodiff_fvar(); // zero-initialized // Single variable const auto x = make_fvar(cx); @@ -142,14 +142,14 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(addition_assignment, T, all_float_types) { if (i == 0 && j == 0) { BOOST_CHECK_EQUAL(sum.derivative(i, j), cx); } else if (i == 1 && j == 0) { - BOOST_CHECK_EQUAL(sum.derivative(i, j), 1.0); + BOOST_CHECK_EQUAL(sum.derivative(i, j), T(1)); } else { - BOOST_CHECK_EQUAL(sum.derivative(i, j), 0.0); + BOOST_CHECK_EQUAL(sum.derivative(i, j), T(0)); } } } // Arithmetic constant - const T cy = 11.0; + const T cy = 11; sum = 0; sum += cy; for (auto i : boost::irange(m + 1)) { @@ -157,7 +157,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(addition_assignment, T, all_float_types) { if (i == 0 && j == 0) { BOOST_CHECK_EQUAL(sum.derivative(i, j), cy); } else { - BOOST_CHECK_EQUAL(sum.derivative(i, j), 0.0); + BOOST_CHECK_EQUAL(sum.derivative(i, j), T(0)); } } } @@ -166,7 +166,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(addition_assignment, T, all_float_types) { BOOST_AUTO_TEST_CASE_TEMPLATE(subtraction_assignment, T, all_float_types) { constexpr std::size_t m = 3; constexpr std::size_t n = 4; - const T cx = 10.0; + const T cx = 10; auto sum = autodiff_fvar(); // zero-initialized // Single variable const auto x = make_fvar(cx); @@ -176,14 +176,14 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(subtraction_assignment, T, all_float_types) { if (i == 0 && j == 0) { BOOST_CHECK_EQUAL(sum.derivative(i, j), -cx); } else if (i == 1 && j == 0) { - BOOST_CHECK_EQUAL(sum.derivative(i, j), -1.0); + BOOST_CHECK_EQUAL(sum.derivative(i, j), T(-1)); } else { - BOOST_CHECK_EQUAL(sum.derivative(i, j), 0.0); + BOOST_CHECK_EQUAL(sum.derivative(i, j), T(0)); } } } // Arithmetic constant - const T cy = 11.0; + const T cy = 11; sum = 0; sum -= cy; for (auto i : boost::irange(m + 1)) { @@ -191,7 +191,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(subtraction_assignment, T, all_float_types) { if (i == 0 && j == 0) { BOOST_CHECK_EQUAL(sum.derivative(i, j), -cy); } else { - BOOST_CHECK_EQUAL(sum.derivative(i, j), 0.0); + BOOST_CHECK_EQUAL(sum.derivative(i, j), T(0)); } } } @@ -202,7 +202,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(multiplication_assignment, T, all_float_types) { // extra lines. constexpr std::size_t m = 3; constexpr std::size_t n = 4; - const T cx = 10.0; + const T cx = 10; auto product = autodiff_fvar(1); // unit constant // Single variable auto x = make_fvar(cx); @@ -212,14 +212,14 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(multiplication_assignment, T, all_float_types) { if (i == 0 && j == 0) { BOOST_CHECK_EQUAL(product.derivative(i, j), cx); } else if (i == 1 && j == 0) { - BOOST_CHECK_EQUAL(product.derivative(i, j), 1.0); + BOOST_CHECK_EQUAL(product.derivative(i, j), T(1)); } else { - BOOST_CHECK_EQUAL(product.derivative(i, j), 0.0); + BOOST_CHECK_EQUAL(product.derivative(i, j), T(0)); } } } // Arithmetic constant - const T cy = 11.0; + const T cy = 11; product = 1; product *= cy; for (auto i : boost::irange(m + 1)) { @@ -227,12 +227,12 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(multiplication_assignment, T, all_float_types) { if (i == 0 && j == 0) { BOOST_CHECK_EQUAL(product.derivative(i, j), cy); } else { - BOOST_CHECK_EQUAL(product.derivative(i, j), 0.0); + BOOST_CHECK_EQUAL(product.derivative(i, j), T(0)); } } } // 0 * inf = nan - x = make_fvar(0.0); + x = make_fvar(T(0.0)); x *= std::numeric_limits::infinity(); // std::cout << "x = " << x << std::endl; for (auto i : boost::irange(m + 1)) { @@ -251,7 +251,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(multiplication_assignment, T, all_float_types) { BOOST_AUTO_TEST_CASE_TEMPLATE(division_assignment, T, all_float_types) { constexpr std::size_t m = 3; constexpr std::size_t n = 4; - const T cx = 16.0; + const T cx = 16; auto quotient = autodiff_fvar(1); // unit constant // Single variable const auto x = make_fvar(cx); @@ -262,11 +262,11 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(division_assignment, T, all_float_types) { BOOST_CHECK_EQUAL(quotient.derivative(3, 0), -6 / pow(cx, 4)); for (auto i : boost::irange(m + 1)) { for (auto j : boost::irange(std::size_t(1), n + 1)) { - BOOST_CHECK_EQUAL(quotient.derivative(i, j), 0.0); + BOOST_CHECK_EQUAL(quotient.derivative(i, j), T(0)); } } // Arithmetic constant - const T cy = 32.0; + const T cy = 32; quotient = 1; quotient /= cy; for (auto i : boost::irange(m + 1)) { @@ -274,7 +274,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(division_assignment, T, all_float_types) { if (i == 0 && j == 0) { BOOST_CHECK_EQUAL(quotient.derivative(i, j), 1 / cy); } else { - BOOST_CHECK_EQUAL(quotient.derivative(i, j), 0.0); + BOOST_CHECK_EQUAL(quotient.derivative(i, j), T(0)); } } } @@ -283,7 +283,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(division_assignment, T, all_float_types) { BOOST_AUTO_TEST_CASE_TEMPLATE(unary_signs, T, all_float_types) { constexpr std::size_t m = 3; constexpr std::size_t n = 4; - const T cx = 16.0; + const T cx = 16; autodiff_fvar lhs; // Single variable const auto x = make_fvar(cx); @@ -293,9 +293,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(unary_signs, T, all_float_types) { if (i == 0 && j == 0) { BOOST_CHECK_EQUAL(lhs.derivative(i, j), -cx); } else if (i == 1 && j == 0) { - BOOST_CHECK_EQUAL(lhs.derivative(i, j), -1.0); + BOOST_CHECK_EQUAL(lhs.derivative(i, j), T(-1)); } else { - BOOST_CHECK_EQUAL(lhs.derivative(i, j), 0.0); + BOOST_CHECK_EQUAL(lhs.derivative(i, j), T(0)); } } } @@ -305,9 +305,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(unary_signs, T, all_float_types) { if (i == 0 && j == 0) { BOOST_CHECK_EQUAL(lhs.derivative(i, j), cx); } else if (i == 1 && j == 0) { - BOOST_CHECK_EQUAL(lhs.derivative(i, j), 1.0); + BOOST_CHECK_EQUAL(lhs.derivative(i, j), T(1)); } else { - BOOST_CHECK_EQUAL(lhs.derivative(i, j), 0.0); + BOOST_CHECK_EQUAL(lhs.derivative(i, j), T(0)); } } } @@ -324,7 +324,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(cast_double, T, all_float_types) { } BOOST_AUTO_TEST_CASE_TEMPLATE(int_double_casting, T, all_float_types) { - const T ca = 3.0; + const T ca = 3; const auto x0 = make_fvar(ca); BOOST_CHECK_EQUAL(static_cast(x0), ca); const auto x1 = make_fvar(ca); @@ -334,8 +334,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(int_double_casting, T, all_float_types) { } BOOST_AUTO_TEST_CASE_TEMPLATE(scalar_addition, T, all_float_types) { - const T ca = 3.0; - const T cb = 4.0; + const T ca = 3; + const T cb = 4; const auto sum0 = autodiff_fvar(ca) + autodiff_fvar(cb); BOOST_CHECK_EQUAL(ca + cb, static_cast(sum0)); const auto sum1 = autodiff_fvar(ca) + cb; @@ -346,7 +346,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(scalar_addition, T, all_float_types) { BOOST_AUTO_TEST_CASE_TEMPLATE(power8, T, all_float_types) { constexpr std::size_t n = 8u; - const T ca = 3.0; + const T ca = 3; auto x = make_fvar(ca); // Test operator*=() x *= x; @@ -366,10 +366,10 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(power8, T, all_float_types) { x = x * x * x * x * x * x * x * x; for (auto i : boost::irange(n + 1)) { BOOST_CHECK_CLOSE( - x.derivative(i), - power_factorial / + static_cast(x.derivative(i)), + static_cast(power_factorial / boost::math::factorial(static_cast(n - i)) * - pow(ca, n - i), + pow(ca, n - i)), std::numeric_limits::epsilon()); } } @@ -377,14 +377,14 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(power8, T, all_float_types) { BOOST_AUTO_TEST_CASE_TEMPLATE(dim1_multiplication, T, all_float_types) { constexpr std::size_t m = 2; constexpr std::size_t n = 3; - const T cy = 4.0; + const T cy = 4; auto y0 = make_fvar(cy); auto y = make_fvar(cy); y *= y0; BOOST_CHECK_EQUAL(y.derivative(0), cy * cy); BOOST_CHECK_EQUAL(y.derivative(1), 2 * cy); - BOOST_CHECK_EQUAL(y.derivative(2), 2.0); - BOOST_CHECK_EQUAL(y.derivative(3), 0.0); + BOOST_CHECK_EQUAL(y.derivative(2), T(2)); + BOOST_CHECK_EQUAL(y.derivative(3), T(0)); y = y * cy; BOOST_CHECK_EQUAL(y.derivative(0), cy * cy * cy); BOOST_CHECK_EQUAL(y.derivative(1), 2 * cy * cy); @@ -395,21 +395,21 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(dim1_multiplication, T, all_float_types) { BOOST_AUTO_TEST_CASE_TEMPLATE(dim1and2_multiplication, T, all_float_types) { constexpr std::size_t m = 2; constexpr std::size_t n = 3; - const T cx = 3.0; - const T cy = 4.0; + const T cx = 3; + const T cy = 4; auto x = make_fvar(cx); auto y = make_fvar(cy); y *= x; BOOST_CHECK_EQUAL(y.derivative(0, 0), cx * cy); BOOST_CHECK_EQUAL(y.derivative(0, 1), cx); BOOST_CHECK_EQUAL(y.derivative(1, 0), cy); - BOOST_CHECK_EQUAL(y.derivative(1, 1), 1.0); + BOOST_CHECK_EQUAL(y.derivative(1, 1), T(1)); for (auto i : boost::irange(std::size_t(1), m)) { for (auto j : boost::irange(std::size_t(1), n)) { if (i == 1 && j == 1) { - BOOST_CHECK_EQUAL(y.derivative(i, j), 1.0); + BOOST_CHECK_EQUAL(y.derivative(i, j), T(1)); } else { - BOOST_CHECK_EQUAL(y.derivative(i, j), 0.0); + BOOST_CHECK_EQUAL(y.derivative(i, j), T(0)); } } } @@ -418,89 +418,89 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(dim1and2_multiplication, T, all_float_types) { BOOST_AUTO_TEST_CASE_TEMPLATE(dim2_addition, T, all_float_types) { constexpr std::size_t m = 2; constexpr std::size_t n = 3; - const T cx = 3.0; + const T cx = 3; const auto x = make_fvar(cx); BOOST_CHECK_EQUAL(x.derivative(0), cx); - BOOST_CHECK_EQUAL(x.derivative(1), 1.0); + BOOST_CHECK_EQUAL(x.derivative(1), T(1)); BOOST_CHECK_EQUAL(x.derivative(2), 0.0); - const T cy = 4.0; + const T cy = 4; const auto y = make_fvar(cy); BOOST_CHECK_EQUAL(static_cast(y.derivative(0)), cy); BOOST_CHECK_EQUAL(static_cast(y.derivative(1)), 0.0); // partial of y w.r.t. x. BOOST_CHECK_EQUAL(y.derivative(0, 0), cy); - BOOST_CHECK_EQUAL(y.derivative(0, 1), 1.0); + BOOST_CHECK_EQUAL(y.derivative(0, 1), T(1)); BOOST_CHECK_EQUAL(y.derivative(1, 0), 0.0); BOOST_CHECK_EQUAL(y.derivative(1, 1), 0.0); const auto z = x + y; BOOST_CHECK_EQUAL(z.derivative(0, 0), cx + cy); - BOOST_CHECK_EQUAL(z.derivative(0, 1), 1.0); - BOOST_CHECK_EQUAL(z.derivative(1, 0), 1.0); + BOOST_CHECK_EQUAL(z.derivative(0, 1), T(1)); + BOOST_CHECK_EQUAL(z.derivative(1, 0), T(1)); BOOST_CHECK_EQUAL(z.derivative(1, 1), 0.0); // The following 4 are unnecessarily more expensive than the previous 4. BOOST_CHECK_EQUAL(z.derivative(0).derivative(0), cx + cy); - BOOST_CHECK_EQUAL(z.derivative(0).derivative(1), 1.0); - BOOST_CHECK_EQUAL(z.derivative(1).derivative(0), 1.0); + BOOST_CHECK_EQUAL(z.derivative(0).derivative(1), T(1)); + BOOST_CHECK_EQUAL(z.derivative(1).derivative(0), T(1)); BOOST_CHECK_EQUAL(z.derivative(1).derivative(1), 0.0); } BOOST_AUTO_TEST_CASE_TEMPLATE(dim2_multiplication, T, all_float_types) { constexpr std::size_t m = 3; constexpr std::size_t n = 4; - const T cx = 6.0; + const T cx = 6; const auto x = make_fvar(cx); - const T cy = 5.0; + const T cy = 5; const auto y = make_fvar(cy); const auto z = x * x * y * y * y; BOOST_CHECK_EQUAL(z.derivative(0, 0), cx * cx * cy * cy * cy); // x^2 * y^3 BOOST_CHECK_EQUAL(z.derivative(0, 1), cx * cx * 3 * cy * cy); // x^2 * 3y^2 BOOST_CHECK_EQUAL(z.derivative(0, 2), cx * cx * 6 * cy); // x^2 * 6y BOOST_CHECK_EQUAL(z.derivative(0, 3), cx * cx * 6); // x^2 * 6 - BOOST_CHECK_EQUAL(z.derivative(0, 4), 0.0); // x^2 * 0 + BOOST_CHECK_EQUAL(z.derivative(0, 4), T(0)); // x^2 * 0 BOOST_CHECK_EQUAL(z.derivative(1, 0), 2 * cx * cy * cy * cy); // 2x * y^3 BOOST_CHECK_EQUAL(z.derivative(1, 1), 2 * cx * 3 * cy * cy); // 2x * 3y^2 BOOST_CHECK_EQUAL(z.derivative(1, 2), 2 * cx * 6 * cy); // 2x * 6y BOOST_CHECK_EQUAL(z.derivative(1, 3), 2 * cx * 6); // 2x * 6 - BOOST_CHECK_EQUAL(z.derivative(1, 4), 0.0); // 2x * 0 + BOOST_CHECK_EQUAL(z.derivative(1, 4), T(0)); // 2x * 0 BOOST_CHECK_EQUAL(z.derivative(2, 0), 2 * cy * cy * cy); // 2 * y^3 BOOST_CHECK_EQUAL(z.derivative(2, 1), 2 * 3 * cy * cy); // 2 * 3y^2 BOOST_CHECK_EQUAL(z.derivative(2, 2), 2 * 6 * cy); // 2 * 6y BOOST_CHECK_EQUAL(z.derivative(2, 3), 2 * 6); // 2 * 6 - BOOST_CHECK_EQUAL(z.derivative(2, 4), 0.0); // 2 * 0 - BOOST_CHECK_EQUAL(z.derivative(3, 0), 0.0); // 0 * y^3 - BOOST_CHECK_EQUAL(z.derivative(3, 1), 0.0); // 0 * 3y^2 - BOOST_CHECK_EQUAL(z.derivative(3, 2), 0.0); // 0 * 6y - BOOST_CHECK_EQUAL(z.derivative(3, 3), 0.0); // 0 * 6 - BOOST_CHECK_EQUAL(z.derivative(3, 4), 0.0); // 0 * 0 + BOOST_CHECK_EQUAL(z.derivative(2, 4), T(0)); // 2 * 0 + BOOST_CHECK_EQUAL(z.derivative(3, 0), T(0)); // 0 * y^3 + BOOST_CHECK_EQUAL(z.derivative(3, 1), T(0)); // 0 * 3y^2 + BOOST_CHECK_EQUAL(z.derivative(3, 2), T(0)); // 0 * 6y + BOOST_CHECK_EQUAL(z.derivative(3, 3), T(0)); // 0 * 6 + BOOST_CHECK_EQUAL(z.derivative(3, 4), T(0)); // 0 * 0 } BOOST_AUTO_TEST_CASE_TEMPLATE(dim2_multiplication_and_subtraction, T, all_float_types) { constexpr std::size_t m = 3; constexpr std::size_t n = 4; - const T cx = 6.0; + const T cx = 6; const auto x = make_fvar(cx); - const T cy = 5.0; + const T cy = 5; const auto y = make_fvar(cy); const auto z = x * x - y * y; BOOST_CHECK_EQUAL(z.derivative(0, 0), cx * cx - cy * cy); BOOST_CHECK_EQUAL(z.derivative(0, 1), -2 * cy); - BOOST_CHECK_EQUAL(z.derivative(0, 2), -2.0); - BOOST_CHECK_EQUAL(z.derivative(0, 3), 0.0); - BOOST_CHECK_EQUAL(z.derivative(0, 4), 0.0); + BOOST_CHECK_EQUAL(z.derivative(0, 2), T(-2)); + BOOST_CHECK_EQUAL(z.derivative(0, 3), T(0)); + BOOST_CHECK_EQUAL(z.derivative(0, 4), T(0)); BOOST_CHECK_EQUAL(z.derivative(1, 0), 2 * cx); - BOOST_CHECK_EQUAL(z.derivative(2, 0), 2.0); + BOOST_CHECK_EQUAL(z.derivative(2, 0), T(2)); for (auto i : boost::irange(std::size_t(1), m + 1)) { for (auto j : boost::irange(std::size_t(1), n + 1)) { - BOOST_CHECK_EQUAL(z.derivative(i, j), 0.0); + BOOST_CHECK_EQUAL(z.derivative(i, j), T(0)); } } } BOOST_AUTO_TEST_CASE_TEMPLATE(inverse, T, all_float_types) { constexpr std::size_t m = 3; - const T cx = 4.0; + const T cx = 4; const auto x = make_fvar(cx); const auto xinv = x.inverse(); BOOST_CHECK_EQUAL(xinv.derivative(0), 1 / cx); @@ -519,9 +519,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(inverse, T, all_float_types) { BOOST_AUTO_TEST_CASE_TEMPLATE(division, T, all_float_types) { constexpr std::size_t m = 3; constexpr std::size_t n = 4; - const T cx = 16.0; + const T cx = 16; auto x = make_fvar(cx); - const T cy = 4.0; + const T cy = 4; auto y = make_fvar(cy); auto z = x * x / (y * y); BOOST_CHECK_EQUAL(z.derivative(0, 0), cx * cx / (cy * cy)); // x^2 * y^-2 @@ -581,8 +581,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(division, T, all_float_types) { BOOST_AUTO_TEST_CASE_TEMPLATE(equality, T, all_float_types) { constexpr std::size_t m = 3; constexpr std::size_t n = 4; - const T cx = 10.0; - const T cy = 10.0; + const T cx = 10; + const T cy = 10; const auto x = make_fvar(cx); const auto y = make_fvar(cy); BOOST_CHECK_EQUAL(x, y); @@ -595,8 +595,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(equality, T, all_float_types) { BOOST_AUTO_TEST_CASE_TEMPLATE(inequality, T, all_float_types) { constexpr std::size_t m = 3; constexpr std::size_t n = 4; - const T cx = 10.0; - const T cy = 11.0; + const T cx = 10; + const T cy = 11; const auto x = make_fvar(cx); const auto y = make_fvar(cy); BOOST_CHECK_NE(x, y); @@ -609,8 +609,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(inequality, T, all_float_types) { BOOST_AUTO_TEST_CASE_TEMPLATE(less_than_or_equal_to, T, all_float_types) { constexpr std::size_t m = 3; constexpr std::size_t n = 4; - const T cx = 10.0; - const T cy = 11.0; + const T cx = 10; + const T cy = 11; const auto x = make_fvar(cx); const auto y = make_fvar(cy); BOOST_CHECK_LE(x, y); @@ -627,8 +627,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(less_than_or_equal_to, T, all_float_types) { BOOST_AUTO_TEST_CASE_TEMPLATE(greater_than_or_equal_to, T, all_float_types) { constexpr std::size_t m = 3; constexpr std::size_t n = 4; - const T cx = 11.0; - const T cy = 10.0; + const T cx = 11; + const T cy = 10; const auto x = make_fvar(cx); const auto y = make_fvar(cy); BOOST_CHECK_GE(x, y); @@ -647,28 +647,28 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(fabs_test, T, all_float_types) { using detail::fabs; using std::fabs; constexpr std::size_t m = 3; - const T cx = 11.0; + const T cx = 11; const auto x = make_fvar(cx); auto a = fabs(x); BOOST_CHECK_EQUAL(a.derivative(0), fabs(cx)); - BOOST_CHECK_EQUAL(a.derivative(1), 1.0); - BOOST_CHECK_EQUAL(a.derivative(2), 0.0); - BOOST_CHECK_EQUAL(a.derivative(3), 0.0); + BOOST_CHECK_EQUAL(a.derivative(1), T(1)); + BOOST_CHECK_EQUAL(a.derivative(2), T(0)); + BOOST_CHECK_EQUAL(a.derivative(3), T(0)); a = fabs(-x); BOOST_CHECK_EQUAL(a.derivative(0), fabs(cx)); - BOOST_CHECK_EQUAL(a.derivative(1), 1.0); // fabs(-x) = fabs(x) - BOOST_CHECK_EQUAL(a.derivative(2), 0.0); - BOOST_CHECK_EQUAL(a.derivative(3), 0.0); + BOOST_CHECK_EQUAL(a.derivative(1), T(1)); // fabs(-x) = fabs(x) + BOOST_CHECK_EQUAL(a.derivative(2), T(0)); + BOOST_CHECK_EQUAL(a.derivative(3), T(0)); const auto xneg = make_fvar(-cx); a = fabs(xneg); BOOST_CHECK_EQUAL(a.derivative(0), fabs(cx)); - BOOST_CHECK_EQUAL(a.derivative(1), -1.0); - BOOST_CHECK_EQUAL(a.derivative(2), 0.0); - BOOST_CHECK_EQUAL(a.derivative(3), 0.0); + BOOST_CHECK_EQUAL(a.derivative(1), -T(1)); + BOOST_CHECK_EQUAL(a.derivative(2), T(0)); + BOOST_CHECK_EQUAL(a.derivative(3), T(0)); const auto zero = make_fvar(0); a = fabs(zero); for (auto i : boost::irange(m + 1)) { - BOOST_CHECK_EQUAL(a.derivative(i), 0.0); + BOOST_CHECK_EQUAL(a.derivative(i), T(0)); } } @@ -678,7 +678,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(ceil_and_floor, T, all_float_types) { using std::ceil; using std::floor; constexpr std::size_t m = 3; - T tests[]{-1.5, 0.0, 1.5}; + T tests[]{T(-1.5), T(0.0), T(1.5)}; for (T &test : tests) { const auto x = make_fvar(test); auto c = ceil(x); @@ -686,8 +686,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(ceil_and_floor, T, all_float_types) { BOOST_CHECK_EQUAL(c.derivative(0), ceil(test)); BOOST_CHECK_EQUAL(f.derivative(0), floor(test)); for (auto i : boost::irange(std::size_t(1), m + 1)) { - BOOST_CHECK_EQUAL(c.derivative(i), 0.0); - BOOST_CHECK_EQUAL(f.derivative(i), 0.0); + BOOST_CHECK_EQUAL(c.derivative(i), T(0)); + BOOST_CHECK_EQUAL(f.derivative(i), T(0)); } } } diff --git a/test/test_autodiff_2.cpp b/test/test_autodiff_2.cpp index 30b517fed6..79ee24ba0d 100644 --- a/test/test_autodiff_2.cpp +++ b/test/test_autodiff_2.cpp @@ -15,9 +15,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(one_over_one_plus_x_squared, T, all_float_types) { f *= f; f += T(1); f = f.inverse(); - BOOST_CHECK_EQUAL(f.derivative(0u), 0.5); - BOOST_CHECK_EQUAL(f.derivative(1u), -0.5); - BOOST_CHECK_EQUAL(f.derivative(2u), 0.5); + BOOST_CHECK_EQUAL(f.derivative(0u), T(0.5)); + BOOST_CHECK_EQUAL(f.derivative(1u), T(-0.5)); + BOOST_CHECK_EQUAL(f.derivative(2u), T(0.5)); BOOST_CHECK_EQUAL(f.derivative(3u), 0); BOOST_CHECK_EQUAL(f.derivative(4u), -3); } @@ -25,14 +25,14 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(one_over_one_plus_x_squared, T, all_float_types) { BOOST_AUTO_TEST_CASE_TEMPLATE(exp_test, T, all_float_types) { using std::exp; constexpr std::size_t m = 4; - const T cx = 2.0; + const T cx = 2; const auto x = make_fvar(cx); auto y = exp(x); for (auto i : boost::irange(m + 1)) { // std::cout.precision(100); // std::cout << "y.derivative("<() * 10; @@ -527,7 +539,14 @@ void test_spots(RealType) } // has_infinity // Error handling checks: + #ifdef __STDCPP_FLOAT16_T__ + if constexpr (!std::is_same_v) + { + check_out_of_range >(1, 1); // (All) valid constructor parameter values. + } + #else check_out_of_range >(1, 1); // (All) valid constructor parameter values. + #endif // and range and non-finite. // Not needed?????? @@ -631,6 +650,17 @@ BOOST_AUTO_TEST_CASE( test_main ) test_spots(boost::math::concepts::real_concept(0.)); // Test real concept. #endif #endif + +#ifdef __STDCPP_FLOAT64_T__ + test_spots(0.0F64); +#endif +#ifdef __STDCPP_FLOAT32_T__ + test_spots(0.0F32); +#endif +#ifdef __STDCPP_FLOAT16_T__ + test_spots(0.0F16); +#endif + } // BOOST_AUTO_TEST_CASE( test_main ) /* diff --git a/test/test_constants.cpp b/test/test_constants.cpp index 3017722056..c072a9c0f7 100644 --- a/test/test_constants.cpp +++ b/test/test_constants.cpp @@ -27,6 +27,10 @@ #include #include +#if __has_include() +# include +#endif + #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900) #include // Check at compile time that the construction method for constants of type float, is "construct from a float", or "construct from a double", ... @@ -347,6 +351,128 @@ void test_float_spots() CHECK_ULP_CLOSE(4.66920160910299067185320382046620161725F, first_feigenbaum, 1); } // template void test_spots(RealType) +#ifdef __STDCPP_FLOAT32_T__ + +void test_f32_spots() +{ + // Basic sanity checks for constants in boost::math::float_constants:: + // for example: boost::math::float_constants::pi + // (rather than boost::math::constants::pi() ). + using namespace boost::math::float_constants; + BOOST_MATH_STD_USING + + CHECK_ULP_CLOSE(static_cast(3.14159265358979323846264338327950288419716939937510F32), pi, 2); + CHECK_ULP_CLOSE(static_cast(sqrt(3.14159265358979323846264338327950288419716939937510F32)), root_pi, 2); + CHECK_ULP_CLOSE(static_cast(sqrt(3.14159265358979323846264338327950288419716939937510F32/2)), root_half_pi, 2); + CHECK_ULP_CLOSE(static_cast(sqrt(3.14159265358979323846264338327950288419716939937510F32 * 2)), root_two_pi, 2); + CHECK_ULP_CLOSE(static_cast(sqrt(log(4.0F32))), root_ln_four, 2); + CHECK_ULP_CLOSE(static_cast(2.71828182845904523536028747135266249775724709369995F32), e, 2); + CHECK_ULP_CLOSE(static_cast(0.5), half, 2); + CHECK_ULP_CLOSE(static_cast(0.57721566490153286060651209008240243104259335F32), euler, 2); + CHECK_ULP_CLOSE(static_cast(sqrt(2.0F32)), root_two, 2); + CHECK_ULP_CLOSE(static_cast(log(2.0F32)), ln_two, 2); + CHECK_ULP_CLOSE(static_cast(log(log(2.0F32))), ln_ln_two, 2); + CHECK_ULP_CLOSE(static_cast(1)/3, third, 2); + CHECK_ULP_CLOSE(static_cast(2)/3, twothirds, 2); + CHECK_ULP_CLOSE(static_cast(0.14159265358979323846264338327950288419716939937510F32), pi_minus_three, 2); + CHECK_ULP_CLOSE(static_cast(4.F32 - 3.14159265358979323846264338327950288419716939937510F32), four_minus_pi, 2); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + CHECK_ULP_CLOSE(static_cast(pow((3.14159265358979323846264338327950288419716939937510F32), 2.71828182845904523536028747135266249775724709369995F32)), pi_pow_e, 2); + CHECK_ULP_CLOSE(static_cast(pow((3.14159265358979323846264338327950288419716939937510F32), 0.33333333333333333333333333333333333333333333333333F32)), cbrt_pi, 2); + CHECK_ULP_CLOSE(static_cast(exp(-0.5F32)), exp_minus_half, 2); + CHECK_ULP_CLOSE(static_cast(pow(2.71828182845904523536028747135266249775724709369995F32, 3.14159265358979323846264338327950288419716939937510F32)), e_pow_pi, 2); + + +#else // Only double, so no suffix F32. + CHECK_ULP_CLOSE(static_cast(pow((3.14159265358979323846264338327950288419716939937510), 2.71828182845904523536028747135266249775724709369995)), pi_pow_e, 2); + CHECK_ULP_CLOSE(static_cast(pow((3.14159265358979323846264338327950288419716939937510), 0.33333333333333333333333333333333333333333333333333)), cbrt_pi, 2); + CHECK_ULP_CLOSE(static_cast(exp(-0.5)), exp_minus_half, 2); +#endif + // Rational fractions. + CHECK_ULP_CLOSE(static_cast(0.333333333333333333333333333333333333333F32), third, 2); + CHECK_ULP_CLOSE(static_cast(0.666666666666666666666666666666666666667F32), two_thirds, 2); + CHECK_ULP_CLOSE(static_cast(0.75F32), three_quarters, 2); + // Two and related. + CHECK_ULP_CLOSE(static_cast(sqrt(2.F32)), root_two, 2); + CHECK_ULP_CLOSE(static_cast(sqrt(3.F32)), root_three, 2); + CHECK_ULP_CLOSE(static_cast(sqrt(2.F32)/2), half_root_two, 2); + CHECK_ULP_CLOSE(static_cast(log(2.F32)), ln_two, 2); + CHECK_ULP_CLOSE(static_cast(log(log(2.0F32))), ln_ln_two, 2); + CHECK_ULP_CLOSE(static_cast(sqrt(log(4.0F32))), root_ln_four, 2); + CHECK_ULP_CLOSE(static_cast(1/sqrt(2.0F32)), one_div_root_two, 2); + + // pi. + CHECK_ULP_CLOSE(static_cast(3.14159265358979323846264338327950288419716939937510F32), pi, 2); + CHECK_ULP_CLOSE(static_cast(3.14159265358979323846264338327950288419716939937510F32/2), half_pi, 2); + CHECK_ULP_CLOSE(static_cast(3.14159265358979323846264338327950288419716939937510F32/4), quarter_pi, 2); + CHECK_ULP_CLOSE(static_cast(3.14159265358979323846264338327950288419716939937510F32/3), third_pi, 2); + CHECK_ULP_CLOSE(static_cast(3.14159265358979323846264338327950288419716939937510F32/6), sixth_pi, 2); + CHECK_ULP_CLOSE(static_cast(2 * 3.14159265358979323846264338327950288419716939937510F32), two_pi, 2); + CHECK_ULP_CLOSE(static_cast(3 * 3.14159265358979323846264338327950288419716939937510F32 / 4), three_quarters_pi, 2); + CHECK_ULP_CLOSE(static_cast(4 * 3.14159265358979323846264338327950288419716939937510F32 / 3), four_thirds_pi, 2); + CHECK_ULP_CLOSE(static_cast(1 / (3.14159265358979323846264338327950288419716939937510F32)), one_div_pi, 2); + CHECK_ULP_CLOSE(static_cast(2 / (3.14159265358979323846264338327950288419716939937510F32)), two_div_pi, 2); + CHECK_ULP_CLOSE(static_cast(1 / (2 * 3.14159265358979323846264338327950288419716939937510F32)), one_div_two_pi, 2); + CHECK_ULP_CLOSE(static_cast(sqrt(3.14159265358979323846264338327950288419716939937510F32)), root_pi, 2); + CHECK_ULP_CLOSE(static_cast(sqrt(3.14159265358979323846264338327950288419716939937510F32 / 2)), root_half_pi, 2); + CHECK_ULP_CLOSE(static_cast(sqrt(2 * 3.14159265358979323846264338327950288419716939937510F32)), root_two_pi, 2); + CHECK_ULP_CLOSE(static_cast(1 / sqrt(3.14159265358979323846264338327950288419716939937510F32)), one_div_root_pi, 2); + CHECK_ULP_CLOSE(static_cast(2 / sqrt(3.14159265358979323846264338327950288419716939937510F32)), two_div_root_pi, 2); + CHECK_ULP_CLOSE(static_cast(1 / sqrt(2 * 3.14159265358979323846264338327950288419716939937510F32)), one_div_root_two_pi, 2); + CHECK_ULP_CLOSE(static_cast(sqrt(1. / 3.14159265358979323846264338327950288419716939937510F32)), root_one_div_pi, 2); + CHECK_ULP_CLOSE(static_cast(3.14159265358979323846264338327950288419716939937510L - 3.L), pi_minus_three, 4 * 2 ); // 4 * 2 because of cancellation loss. + CHECK_ULP_CLOSE(static_cast(4.L - 3.14159265358979323846264338327950288419716939937510L), four_minus_pi, 4 ); + // + CHECK_ULP_CLOSE(static_cast(pow((3.14159265358979323846264338327950288419716939937510F32), 2.71828182845904523536028747135266249775724709369995F32)), pi_pow_e, 2); // See above. + CHECK_ULP_CLOSE(static_cast(3.14159265358979323846264338327950288419716939937510F32 * 3.14159265358979323846264338327950288419716939937510F32), pi_sqr, 2); // See above. + CHECK_ULP_CLOSE(static_cast(3.14159265358979323846264338327950288419716939937510F32 * 3.14159265358979323846264338327950288419716939937510F32/6), pi_sqr_div_six, 2); // See above. + CHECK_ULP_CLOSE(static_cast(3.14159265358979323846264338327950288419716939937510F32 * 3.14159265358979323846264338327950288419716939937510F32 * 3.14159265358979323846264338327950288419716939937510F32), pi_cubed, 2); // See above. + + // CHECK_ULP_CLOSE(static_cast(3.14159265358979323846264338327950288419716939937510F32 * 3.14159265358979323846264338327950288419716939937510F32), cbrt_pi, 2); // See above. + CHECK_ULP_CLOSE(cbrt_pi * cbrt_pi * cbrt_pi, pi, 2); + CHECK_ULP_CLOSE((static_cast(1)/cbrt_pi), one_div_cbrt_pi, 2); + + // Euler + CHECK_ULP_CLOSE(static_cast(2.71828182845904523536028747135266249775724709369995F32), e, 2); + + //CHECK_ULP_CLOSE(static_cast(exp(-0.5F32)), exp_minus_half, 2); // See above. + CHECK_ULP_CLOSE(pow(e, pi), e_pow_pi, 2); // See also above. + CHECK_ULP_CLOSE(sqrt(e), root_e, 2); + CHECK_ULP_CLOSE(log10(e), log10_e, 2); + CHECK_ULP_CLOSE(static_cast(1)/log10(e), one_div_log10_e, 2); + + // Trigonometric + CHECK_ULP_CLOSE(pi/180, degree, 2); + CHECK_ULP_CLOSE(180 / pi, radian, 2); + CHECK_ULP_CLOSE(sin(1.F32), sin_one, 2); + CHECK_ULP_CLOSE(cos(1.F32), cos_one, 2); + CHECK_ULP_CLOSE(sinh(1.F32), sinh_one, 2); + CHECK_ULP_CLOSE(cosh(1.F32), cosh_one, 2); + + // Phi + CHECK_ULP_CLOSE((1.F32 + sqrt(5.F32)) /2, phi, 2); + CHECK_ULP_CLOSE(log((1.F32 + sqrt(5.F32)) /2), ln_phi, 2); + CHECK_ULP_CLOSE(1.F32 / log((1.F32 + sqrt(5.F32)) /2), one_div_ln_phi, 2); + + // Euler's Gamma + CHECK_ULP_CLOSE(0.57721566490153286060651209008240243104215933593992F32, euler, 2); // (sequence A001620 in OEIS). + CHECK_ULP_CLOSE(1.F32/ 0.57721566490153286060651209008240243104215933593992F32, one_div_euler, 2); // (from sequence A001620 in OEIS). + CHECK_ULP_CLOSE(0.57721566490153286060651209008240243104215933593992F32 * 0.57721566490153286060651209008240243104215933593992F32, euler_sqr, 2); // (from sequence A001620 in OEIS). + + // Misc + CHECK_ULP_CLOSE(1.644934066848226436472415166646025189218949901206F32, zeta_two, 2); // A013661 as a constant (usually base 10) in OEIS. + CHECK_ULP_CLOSE(1.20205690315959428539973816151144999076498629234049888179227F32, zeta_three, 2); // (sequence A002117 in OEIS) + CHECK_ULP_CLOSE(.91596559417721901505460351493238411077414937428167213F32, catalan, 2); // A006752 as a constant in OEIS. + CHECK_ULP_CLOSE(1.1395470994046486574927930193898461120875997958365518247216557100852480077060706857071875468869385150F32, extreme_value_skewness, 2); // Mathematica: N[12 Sqrt[6] Zeta[3]/Pi^3, 1101] + CHECK_ULP_CLOSE(0.6311106578189371381918993515442277798440422031347194976580945856929268196174737254599050270325373067F32, rayleigh_skewness, 2); // Mathematica: N[2 Sqrt[Pi] (Pi - 3)/((4 - Pi)^(3/2)), 1100] + CHECK_ULP_CLOSE(2.450893006876380628486604106197544154e-01F32, rayleigh_kurtosis_excess, 2); + CHECK_ULP_CLOSE(2.68545200106530644530971483548179569382038229399446295305115234555721885953715200280114117493184769799515F32, khinchin, 4 ); // A002210 as a constant https://oeis.org/A002210/constant + CHECK_ULP_CLOSE(1.2824271291006226368753425688697917277676889273250011F32, glaisher, 4 ); // https://oeis.org/A074962/constant + CHECK_ULP_CLOSE(4.66920160910299067185320382046620161725F32, first_feigenbaum, 1); +} // template void test_spots(RealType) + +#endif + void test_double_spots() { // Basic sanity checks for constants in boost::math::double_constants:: @@ -465,6 +591,126 @@ void test_double_spots() } // template void test_spots(RealType) +#ifdef __STDCPP_FLOAT64_T__ +void test_f64_spots() +{ + // Basic sanity checks for constants in boost::math::double_constants:: + // for example: boost::math::double_constants::pi + // (rather than boost::math::constants::pi() ). + using namespace boost::math::double_constants; + BOOST_MATH_STD_USING + + CHECK_ULP_CLOSE(static_cast(3.14159265358979323846264338327950288419716939937510F64), pi, 2); + CHECK_ULP_CLOSE(static_cast(sqrt(3.14159265358979323846264338327950288419716939937510F64)), root_pi, 2); + CHECK_ULP_CLOSE(static_cast(sqrt(3.14159265358979323846264338327950288419716939937510F64/2)), root_half_pi, 2); + CHECK_ULP_CLOSE(static_cast(sqrt(3.14159265358979323846264338327950288419716939937510F64 * 2)), root_two_pi, 2); + CHECK_ULP_CLOSE(static_cast(sqrt(log(4.0F64))), root_ln_four, 2); + CHECK_ULP_CLOSE(static_cast(2.71828182845904523536028747135266249775724709369995F64), e, 2); + CHECK_ULP_CLOSE(static_cast(0.5F64), half, 2); + CHECK_ULP_CLOSE(static_cast(0.57721566490153286060651209008240243104259335F64), euler, 2); + CHECK_ULP_CLOSE(static_cast(sqrt(2.0F64)), root_two, 2); + CHECK_ULP_CLOSE(static_cast(log(2.0F64)), ln_two, 2); + CHECK_ULP_CLOSE(static_cast(log(log(2.0F64))), ln_ln_two, 2); + CHECK_ULP_CLOSE(static_cast(1)/3, third, 2); + CHECK_ULP_CLOSE(static_cast(2)/3, twothirds, 2); + CHECK_ULP_CLOSE(static_cast(0.14159265358979323846264338327950288419716939937510F64), pi_minus_three, 2); + CHECK_ULP_CLOSE(static_cast(4.F64 - 3.14159265358979323846264338327950288419716939937510F64), four_minus_pi, 2); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + CHECK_ULP_CLOSE(static_cast(pow((3.14159265358979323846264338327950288419716939937510F64), 2.71828182845904523536028747135266249775724709369995F64)), pi_pow_e, 2); + CHECK_ULP_CLOSE(static_cast(pow((3.14159265358979323846264338327950288419716939937510F64), 0.33333333333333333333333333333333333333333333333333F64)), cbrt_pi, 2); + CHECK_ULP_CLOSE(static_cast(exp(-0.5F64)), exp_minus_half, 2); + CHECK_ULP_CLOSE(static_cast(pow(2.71828182845904523536028747135266249775724709369995F64, 3.14159265358979323846264338327950288419716939937510F64)), e_pow_pi, 2); + + +#else // Only double, so no suffix . + CHECK_ULP_CLOSE(static_cast(pow((3.14159265358979323846264338327950288419716939937510F64), 2.71828182845904523536028747135266249775724709369995F64)), pi_pow_e, 2); + CHECK_ULP_CLOSE(static_cast(pow((3.14159265358979323846264338327950288419716939937510F64), 0.33333333333333333333333333333333333333333333333333F64)), cbrt_pi, 2); + CHECK_ULP_CLOSE(static_cast(exp(-0.5)), exp_minus_half, 2); +#endif + // Rational fractions. + CHECK_ULP_CLOSE(static_cast(0.333333333333333333333333333333333333333F64), third, 2); + CHECK_ULP_CLOSE(static_cast(0.666666666666666666666666666666666666667F64), two_thirds, 2); + CHECK_ULP_CLOSE(static_cast(0.75), three_quarters, 2); + // Two and related. + CHECK_ULP_CLOSE(static_cast(sqrt(2.F64)), root_two, 2); + CHECK_ULP_CLOSE(static_cast(sqrt(3.F64)), root_three, 2); + CHECK_ULP_CLOSE(static_cast(sqrt(2.F64)/2), half_root_two, 2); + CHECK_ULP_CLOSE(static_cast(log(2.F64)), ln_two, 2); + CHECK_ULP_CLOSE(static_cast(log(log(2.0F64))), ln_ln_two, 2); + CHECK_ULP_CLOSE(static_cast(sqrt(log(4.0F64))), root_ln_four, 2); + CHECK_ULP_CLOSE(static_cast(1/sqrt(2.0F64)), one_div_root_two, 2); + + // pi. + CHECK_ULP_CLOSE(static_cast(3.14159265358979323846264338327950288419716939937510F64), pi, 2); + CHECK_ULP_CLOSE(static_cast(3.14159265358979323846264338327950288419716939937510F64/2), half_pi, 2); + CHECK_ULP_CLOSE(static_cast(3.14159265358979323846264338327950288419716939937510F64/4), quarter_pi, 2); + CHECK_ULP_CLOSE(static_cast(3.14159265358979323846264338327950288419716939937510F64/3), third_pi, 2); + CHECK_ULP_CLOSE(static_cast(3.14159265358979323846264338327950288419716939937510F64/6), sixth_pi, 2); + CHECK_ULP_CLOSE(static_cast(2 * 3.14159265358979323846264338327950288419716939937510F64), two_pi, 2); + CHECK_ULP_CLOSE(static_cast(3 * 3.14159265358979323846264338327950288419716939937510F64 / 4), three_quarters_pi, 2); + CHECK_ULP_CLOSE(static_cast(4 * 3.14159265358979323846264338327950288419716939937510F64 / 3), four_thirds_pi, 2); + CHECK_ULP_CLOSE(static_cast(1 / (3.14159265358979323846264338327950288419716939937510F64)), one_div_pi, 2); + CHECK_ULP_CLOSE(static_cast(2 / (3.14159265358979323846264338327950288419716939937510F64)), two_div_pi, 2); + CHECK_ULP_CLOSE(static_cast(1 / (2 * 3.14159265358979323846264338327950288419716939937510F64)), one_div_two_pi, 2); + CHECK_ULP_CLOSE(static_cast(sqrt(3.14159265358979323846264338327950288419716939937510F64)), root_pi, 2); + CHECK_ULP_CLOSE(static_cast(sqrt(3.14159265358979323846264338327950288419716939937510F64 / 2)), root_half_pi, 2); + CHECK_ULP_CLOSE(static_cast(sqrt(2 * 3.14159265358979323846264338327950288419716939937510F64)), root_two_pi, 2); + CHECK_ULP_CLOSE(static_cast(1 / sqrt(3.14159265358979323846264338327950288419716939937510F64)), one_div_root_pi, 2); + CHECK_ULP_CLOSE(static_cast(2 / sqrt(3.14159265358979323846264338327950288419716939937510F64)), two_div_root_pi, 2); + CHECK_ULP_CLOSE(static_cast(1 / sqrt(2 * 3.14159265358979323846264338327950288419716939937510F64)), one_div_root_two_pi, 2); + CHECK_ULP_CLOSE(static_cast(sqrt(1. / 3.14159265358979323846264338327950288419716939937510F64)), root_one_div_pi, 2); + CHECK_ULP_CLOSE(static_cast(3.14159265358979323846264338327950288419716939937510F64 - 3.F64), pi_minus_three, 4 * 2 ); // 4 * 2 because of cancellation loss. + CHECK_ULP_CLOSE(static_cast(4.F64 - 3.14159265358979323846264338327950288419716939937510F64), four_minus_pi, 4 ); + // + CHECK_ULP_CLOSE(static_cast(pow((3.14159265358979323846264338327950288419716939937510F64), 2.71828182845904523536028747135266249775724709369995F64)), pi_pow_e, 2); // See above. + CHECK_ULP_CLOSE(static_cast(3.14159265358979323846264338327950288419716939937510F64 * 3.14159265358979323846264338327950288419716939937510F64), pi_sqr, 2); // See above. + CHECK_ULP_CLOSE(static_cast(3.14159265358979323846264338327950288419716939937510F64 * 3.14159265358979323846264338327950288419716939937510F64/6), pi_sqr_div_six, 2); // See above. + CHECK_ULP_CLOSE(static_cast(3.14159265358979323846264338327950288419716939937510F64 * 3.14159265358979323846264338327950288419716939937510F64 * 3.14159265358979323846264338327950288419716939937510F64), pi_cubed, 2); // See above. + + // CHECK_ULP_CLOSE(static_cast(3.14159265358979323846264338327950288419716939937510 * 3.14159265358979323846264338327950288419716939937510), cbrt_pi, 2); // See above. + CHECK_ULP_CLOSE(cbrt_pi * cbrt_pi * cbrt_pi, pi, 2); + CHECK_ULP_CLOSE((static_cast(1)/cbrt_pi), one_div_cbrt_pi, 2); + + // Euler + CHECK_ULP_CLOSE(static_cast(2.71828182845904523536028747135266249775724709369995), e, 2); + + //CHECK_ULP_CLOSE(static_cast(exp(-0.5)), exp_minus_half, 2); // See above. + CHECK_ULP_CLOSE(pow(e, pi), e_pow_pi, 2); // See also above. + CHECK_ULP_CLOSE(sqrt(e), root_e, 2); + CHECK_ULP_CLOSE(log10(e), log10_e, 2); + CHECK_ULP_CLOSE(static_cast(1)/log10(e), one_div_log10_e, 2); + + // Trigonometric + CHECK_ULP_CLOSE(pi/180, degree, 2); + CHECK_ULP_CLOSE(180 / pi, radian, 2); + CHECK_ULP_CLOSE(sin(1.F64), sin_one, 2); + CHECK_ULP_CLOSE(cos(1.F64), cos_one, 2); + CHECK_ULP_CLOSE(sinh(1.F64), sinh_one, 2); + CHECK_ULP_CLOSE(cosh(1.F64), cosh_one, 2); + + // Phi + CHECK_ULP_CLOSE((1.F64 + sqrt(5.F64)) /2, phi, 2); + CHECK_ULP_CLOSE(log((1.F64 + sqrt(5.F64)) /2), ln_phi, 2); + CHECK_ULP_CLOSE(1.F64 / log((1.F64 + sqrt(5.F64)) /2), one_div_ln_phi, 2); + + //Euler's Gamma + CHECK_ULP_CLOSE(0.57721566490153286060651209008240243104215933593992F64, euler, 2); // (sequence A001620 in OEIS). + CHECK_ULP_CLOSE(1.F64/ 0.57721566490153286060651209008240243104215933593992F64, one_div_euler, 2); // (from sequence A001620 in OEIS). + CHECK_ULP_CLOSE(0.57721566490153286060651209008240243104215933593992F64 * 0.57721566490153286060651209008240243104215933593992F64, euler_sqr, 2); // (from sequence A001620 in OEIS). + + // Misc + CHECK_ULP_CLOSE(1.644934066848226436472415166646025189218949901206F64, zeta_two, 2); // A013661 as a constant (usually base 10) in OEIS. + CHECK_ULP_CLOSE(1.20205690315959428539973816151144999076498629234049888179227F64, zeta_three, 2); // (sequence A002117 in OEIS) + CHECK_ULP_CLOSE(.91596559417721901505460351493238411077414937428167213F64, catalan, 2); // A006752 as a constant in OEIS. + CHECK_ULP_CLOSE(1.1395470994046486574927930193898461120875997958365518247216557100852480077060706857071875468869385150F64, extreme_value_skewness, 2); // Mathematica: N[12 Sqrt[6] Zeta[3]/Pi^3, 1101] + CHECK_ULP_CLOSE(0.6311106578189371381918993515442277798440422031347194976580945856929268196174737254599050270325373067F64, rayleigh_skewness, 2); // Mathematica: N[2 Sqrt[Pi] (Pi - 3)/((4 - Pi)^(3/2)), 1100] + CHECK_ULP_CLOSE(2.450893006876380628486604106197544154e-01F64, rayleigh_kurtosis_excess, 2); + CHECK_ULP_CLOSE(2.68545200106530644530971483548179569382038229399446295305115234555721885953715200280114117493184769799515F64, khinchin, 4 ); // A002210 as a constant https://oeis.org/A002210/constant + CHECK_ULP_CLOSE(1.2824271291006226368753425688697917277676889273250011F64, glaisher, 4 ); // https://oeis.org/A074962/constant + +} // template void test_spots(RealType) +#endif + void test_long_double_spots() { // Basic sanity checks for constants in boost::math::long double_constants:: @@ -829,9 +1075,20 @@ void test_laplace_limit() int main() { // Basic sanity-check spot values. + #ifdef __STDCPP_FLOAT32_T__ + test_f32_spots(); + #else test_float_spots(); // Test float_constants, like boost::math::float_constants::pi; + #endif + + #ifdef __STDCPP_FLOAT64_T__ + test_f64_spots(); + #else test_double_spots(); // Test double_constants. + #endif + test_long_double_spots(); // Test long_double_constants. + #ifdef BOOST_MATH_HAS_FLOAT128 test_float128(); #endif @@ -841,6 +1098,12 @@ int main() test_spots(0.0F); // Test float. test_spots(0.0); // Test double. test_spots(0.0L); // Test long double. + #ifdef __STDCPP_FLOAT32_T__ + test_spots(0.0F32); + #endif + #ifdef __STDCPP_FLOAT64_T__ + test_spots(0.0F64); + #endif #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900) test_feigenbaum(); diff --git a/test/test_exponential_dist.cpp b/test/test_exponential_dist.cpp index c659b91c2b..d1898fa7c4 100644 --- a/test/test_exponential_dist.cpp +++ b/test/test_exponential_dist.cpp @@ -26,6 +26,10 @@ using std::setprecision; using std::log; +#if __has_include() +# include +#endif + template void test_spot(RealType l, RealType x, RealType p, RealType q, RealType logp, RealType logq, RealType tolerance, RealType logtolerance) { @@ -208,7 +212,11 @@ void test_spots(RealType T) static_cast(-9.210390371559516069440021374287500922116L), // log(p), static_cast(-0.000100000000000000000000000000000000000L), // log(q) tolerance, - std::is_same::value ? tolerance * 10 : tolerance); + std::is_same::value + #ifdef __STDCPP_FLOAT32_T__ + || std::is_same::value + #endif + ? tolerance * 10 : tolerance); /* // This test data appears to be erroneous, MathCad appears // to suffer from cancellation error as x -> 0 @@ -375,6 +383,13 @@ BOOST_AUTO_TEST_CASE( test_main ) "to pass." << std::endl; #endif + #ifdef __STDCPP_FLOAT32_T__ + test_spots(0.0F32); + #endif + #ifdef __STDCPP_FLOAT64_T__ + test_spots(0.0F64); + #endif + } // BOOST_AUTO_TEST_CASE( test_main ) /* diff --git a/test/test_ibeta_derivative.cpp b/test/test_ibeta_derivative.cpp index 5e600b630f..f722e95198 100644 --- a/test/test_ibeta_derivative.cpp +++ b/test/test_ibeta_derivative.cpp @@ -2,7 +2,7 @@ // Use, modification and distribution are subject to the // Boost Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -#if defined(__GNUC__) +#if defined(__GNUC__) && __GNUC__ <= 12 #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wliteral-range" #endif diff --git a/test/test_numerical_differentiation.cpp b/test/test_numerical_differentiation.cpp index 1b2f539624..0f2489a61a 100644 --- a/test/test_numerical_differentiation.cpp +++ b/test/test_numerical_differentiation.cpp @@ -16,6 +16,10 @@ #include #include +#if __has_include() +# include +#endif + using std::abs; using std::pow; using boost::math::differentiation::finite_difference_derivative; @@ -31,7 +35,7 @@ void test_order(size_t points_to_test) std::cout << std::setprecision(std::numeric_limits::digits10); //std::cout << std::fixed << std::scientific; auto f = [](Real t) { return boost::math::cyl_bessel_j(1, t); }; - Real min = -100000.0; + Real min = Real(-100000.0); Real max = -min; Real x = min; Real max_error = 0; @@ -95,7 +99,7 @@ void test_bessel() Real computed = finite_difference_derivative(f, x); Real expected = cyl_bessel_j_prime(12, x); - Real error_estimate = 4*abs(f(x))*sqrt(eps); + Real error_estimate = Real(4*abs(f(x))*sqrt(eps)); //std::cout << std::setprecision(std::numeric_limits::digits10); //std::cout << "cyl_bessel_j_prime: " << expected << std::endl; //std::cout << "First order fd : " << computed << std::endl; @@ -218,28 +222,41 @@ void test_complex_step() BOOST_AUTO_TEST_CASE(numerical_differentiation_test) { + constexpr size_t points_to_test = 1000; + + #ifdef __STDCPP_FLOAT32_T__ + test_complex_step(); + test_bessel(); + test_order(points_to_test); + test_order(points_to_test); + test_order(points_to_test); + test_order(points_to_test); + test_order(points_to_test); + #else test_complex_step(); - test_complex_step(); - test_bessel(); - test_bessel(); - - - size_t points_to_test = 1000; test_order(points_to_test); - test_order(points_to_test); - - test_order(points_to_test); - test_order(points_to_test); - test_order(points_to_test); - test_order(points_to_test); - test_order(points_to_test); - test_order(points_to_test); - test_order(points_to_test); + #endif + + #ifdef __STDCPP_FLOAT64_T__ + test_complex_step(); + test_bessel(); + test_order(points_to_test); + test_order(points_to_test); + test_order(points_to_test); + test_order(points_to_test); + test_order(points_to_test); + #else + test_complex_step(); + test_bessel(); + test_order(points_to_test); + test_order(points_to_test); + test_order(points_to_test); + test_order(points_to_test); test_order(points_to_test); - + #endif } diff --git a/test/test_trapezoidal.cpp b/test/test_trapezoidal.cpp index dc5eb88ac5..236d6d8848 100644 --- a/test/test_trapezoidal.cpp +++ b/test/test_trapezoidal.cpp @@ -21,6 +21,11 @@ #ifdef BOOST_HAS_FLOAT128 #include #endif + +#if __has_include() +# include +#endif + using boost::multiprecision::cpp_bin_float_50; using boost::multiprecision::cpp_bin_float_100; using boost::math::quadrature::trapezoidal; @@ -130,13 +135,13 @@ void test_constant() std::cout << "Testing constants are integrated correctly by the adaptive trapezoidal routine on type " << boost::typeindex::type_id().pretty_name() << "\n"; auto f = [](Real)->Real { return boost::math::constants::half(); }; - Real Q = trapezoidal(f, (Real) 0.0, (Real) 10.0); - BOOST_CHECK_CLOSE(Q, 5.0, 100*std::numeric_limits::epsilon()); - Q = trapezoidal(f, (Real) 10.0, (Real) 0.0); - BOOST_CHECK_CLOSE(Q, -5.0, 100*std::numeric_limits::epsilon()); + Real Q = trapezoidal(f, static_cast(0.0), static_cast(10.0)); + BOOST_CHECK_CLOSE(Q, static_cast(5.0), 100*std::numeric_limits::epsilon()); + Q = trapezoidal(f, static_cast(10.0), static_cast(0.0)); + BOOST_CHECK_CLOSE(Q, static_cast(-5.0), 100*std::numeric_limits::epsilon()); - Q = trapezoidal(f, (Real) 10.0, (Real) 10.0); - BOOST_CHECK_CLOSE(Q, Real(0), 100*std::numeric_limits::epsilon()); + Q = trapezoidal(f, static_cast(10.0), static_cast(10.0)); + BOOST_CHECK_CLOSE(Q, static_cast(0), 100*std::numeric_limits::epsilon()); } @@ -230,8 +235,14 @@ void test_rational_sin() BOOST_AUTO_TEST_CASE(trapezoidal_quadrature) { + +#if defined(__STDCPP_FLOAT32_T__) && defined(__STDCPP_FLOAT64_T__) + test_constant(); + test_constant(); +#else test_constant(); test_constant(); +#endif #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS test_constant(); #endif @@ -241,8 +252,13 @@ BOOST_AUTO_TEST_CASE(trapezoidal_quadrature) test_constant(); test_constant(); +#if defined(__STDCPP_FLOAT32_T__) && defined(__STDCPP_FLOAT64_T__) + test_rational_periodic(); + test_rational_periodic(); +#else test_rational_periodic(); test_rational_periodic(); +#endif #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS test_rational_periodic(); #endif @@ -255,8 +271,13 @@ BOOST_AUTO_TEST_CASE(trapezoidal_quadrature) test_rational_periodic(); #endif +#if defined(__STDCPP_FLOAT32_T__) && defined(__STDCPP_FLOAT64_T__) + test_bump_function(); + test_bump_function(); +#else test_bump_function(); test_bump_function(); +#endif #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS test_bump_function(); #endif @@ -268,8 +289,13 @@ BOOST_AUTO_TEST_CASE(trapezoidal_quadrature) test_rational_periodic(); #endif +#if defined(__STDCPP_FLOAT32_T__) && defined(__STDCPP_FLOAT64_T__) + test_zero_function(); + test_zero_function(); +#else test_zero_function(); test_zero_function(); +#endif #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS test_zero_function(); #endif @@ -282,8 +308,13 @@ BOOST_AUTO_TEST_CASE(trapezoidal_quadrature) test_zero_function(); #endif +#if defined(__STDCPP_FLOAT32_T__) && defined(__STDCPP_FLOAT64_T__) + test_sinsq(); + test_sinsq(); +#else test_sinsq(); test_sinsq(); +#endif #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS test_sinsq(); #endif @@ -296,8 +327,13 @@ BOOST_AUTO_TEST_CASE(trapezoidal_quadrature) test_sinsq(); #endif +#if defined(__STDCPP_FLOAT32_T__) && defined(__STDCPP_FLOAT64_T__) + test_slowly_converging(); + test_slowly_converging(); +#else test_slowly_converging(); test_slowly_converging(); +#endif #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS test_slowly_converging(); #endif @@ -305,8 +341,13 @@ BOOST_AUTO_TEST_CASE(trapezoidal_quadrature) test_slowly_converging(); #endif +#if defined(__STDCPP_FLOAT32_T__) && defined(__STDCPP_FLOAT64_T__) + test_rational_sin(); + test_rational_sin(); +#else test_rational_sin(); test_rational_sin(); +#endif #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS test_rational_sin(); #endif diff --git a/test/test_vector_barycentric_rational.cpp b/test/test_vector_barycentric_rational.cpp index f8050d2427..1a58a454e9 100644 --- a/test/test_vector_barycentric_rational.cpp +++ b/test/test_vector_barycentric_rational.cpp @@ -18,6 +18,10 @@ #include #include +#if __has_include() +# include +#endif + using std::sqrt; using std::abs; using std::numeric_limits; @@ -373,6 +377,20 @@ void test_weights() BOOST_AUTO_TEST_CASE(vector_barycentric_rational) { + #ifdef __STDCPP_FLOAT64_T__ + + test_weights(); + test_constant_eigen(); + test_constant_std_array(); + test_constant_high_order(); + test_interpolation_condition_eigen(); + test_interpolation_condition_ublas(); + test_interpolation_condition_std_array(); + test_interpolation_condition_high_order(); + test_agreement_with_1d(); + + #else + test_weights(); test_constant_eigen(); test_constant_std_array(); @@ -382,4 +400,6 @@ BOOST_AUTO_TEST_CASE(vector_barycentric_rational) test_interpolation_condition_std_array(); test_interpolation_condition_high_order(); test_agreement_with_1d(); + + #endif } diff --git a/test/univariate_statistics_backwards_compatible_test.cpp b/test/univariate_statistics_backwards_compatible_test.cpp index dfb8f30c26..9c50d6f2dc 100644 --- a/test/univariate_statistics_backwards_compatible_test.cpp +++ b/test/univariate_statistics_backwards_compatible_test.cpp @@ -612,11 +612,7 @@ void test_median_absolute_deviation() v = {-1, 1}; m = boost::math::statistics::median_absolute_deviation(v.begin(), v.end(), 0); BOOST_TEST_EQ(m, 1); - // The median is zero, so coincides with the default: - m = boost::math::statistics::median_absolute_deviation(v.begin(), v.end()); - BOOST_TEST_EQ(m, 1); - - m = boost::math::statistics::median_absolute_deviation(v); + m = boost::math::statistics::median_absolute_deviation(v, 0); BOOST_TEST_EQ(m, 1); @@ -649,6 +645,65 @@ void test_median_absolute_deviation() u[5] = -3; m = boost::math::statistics::median_absolute_deviation(u, 0); BOOST_TEST_EQ(m, 2); + + + v = {-1, 2, -3, 4, -5, 6, -7}; + m = boost::math::statistics::median_absolute_deviation(v.begin(), v.end()); + BOOST_TEST_EQ(m, 4); + + g = std::mt19937(12); + std::shuffle(v.begin(), v.end(), g); + m = boost::math::statistics::median_absolute_deviation(v); + BOOST_TEST_EQ(m, 4); + + v = {1, -2, -3, 3, -4, -5}; + m = boost::math::statistics::median_absolute_deviation(v.begin(), v.end()); + BOOST_TEST_EQ(m, 2); + std::shuffle(v.begin(), v.end(), g); + m = boost::math::statistics::median_absolute_deviation(v.begin(), v.end()); + BOOST_TEST_EQ(m, 2); + + v = {-1}; + m = boost::math::statistics::median_absolute_deviation(v.begin(), v.end()); + BOOST_TEST_EQ(m, 0); + + v = {-1, 1}; + m = boost::math::statistics::median_absolute_deviation(v.begin(), v.end()); + BOOST_TEST_EQ(m, 1); + + m = boost::math::statistics::median_absolute_deviation(v); + BOOST_TEST_EQ(m, 1); + + + v = {2, -4}; + m = boost::math::statistics::median_absolute_deviation(v.begin(), v.end()); + BOOST_TEST_EQ(m, 3); + + v = {1, -1, 1}; + m = boost::math::statistics::median_absolute_deviation(v.begin(), v.end()); + BOOST_TEST_EQ(m, 0); + + v = {1, 2, -3}; + m = boost::math::statistics::median_absolute_deviation(v.begin(), v.end()); + BOOST_TEST_EQ(m, 1); + std::shuffle(v.begin(), v.end(), g); + m = boost::math::statistics::median_absolute_deviation(v.begin(), v.end()); + BOOST_TEST_EQ(m, 1); + + w = {1, 2, -3}; + m = boost::math::statistics::median_absolute_deviation(w); + BOOST_TEST_EQ(m, 1); + + // boost.ublas vector? + boost::numeric::ublas::vector u2(6); + u2[0] = 1; + u2[1] = 2; + u2[2] = -3; + u2[3] = 1; + u2[4] = 2; + u2[5] = -3; + m = boost::math::statistics::median_absolute_deviation(u2); + BOOST_TEST_EQ(m, 1); } diff --git a/test/univariate_statistics_test.cpp b/test/univariate_statistics_test.cpp index 68cfc71621..77b8e8fc09 100644 --- a/test/univariate_statistics_test.cpp +++ b/test/univariate_statistics_test.cpp @@ -577,11 +577,7 @@ void test_median_absolute_deviation(ExecutionPolicy&& exec) v = {-1, 1}; m = boost::math::statistics::median_absolute_deviation(exec, v.begin(), v.end(), 0); BOOST_TEST_EQ(m, 1); - // The median is zero, so coincides with the default: - m = boost::math::statistics::median_absolute_deviation(exec, v.begin(), v.end()); - BOOST_TEST_EQ(m, 1); - - m = boost::math::statistics::median_absolute_deviation(exec, v); + m = boost::math::statistics::median_absolute_deviation(exec, v, 0); BOOST_TEST_EQ(m, 1); @@ -614,6 +610,65 @@ void test_median_absolute_deviation(ExecutionPolicy&& exec) u[5] = -3; m = boost::math::statistics::median_absolute_deviation(exec, u, 0); BOOST_TEST_EQ(m, 2); + + + v = {-1, 2, -3, 4, -5, 6, -7}; + m = boost::math::statistics::median_absolute_deviation(exec, v.begin(), v.end()); + BOOST_TEST_EQ(m, 4); + + g = std::mt19937(12); + std::shuffle(v.begin(), v.end(), g); + m = boost::math::statistics::median_absolute_deviation(exec, v); + BOOST_TEST_EQ(m, 4); + + v = {1, -2, -3, 3, -4, -5}; + m = boost::math::statistics::median_absolute_deviation(exec, v.begin(), v.end()); + BOOST_TEST_EQ(m, 2); + std::shuffle(v.begin(), v.end(), g); + m = boost::math::statistics::median_absolute_deviation(exec, v.begin(), v.end()); + BOOST_TEST_EQ(m, 2); + + v = {-1}; + m = boost::math::statistics::median_absolute_deviation(exec, v.begin(), v.end()); + BOOST_TEST_EQ(m, 0); + + v = {-1, 1}; + m = boost::math::statistics::median_absolute_deviation(exec, v.begin(), v.end()); + BOOST_TEST_EQ(m, 1); + + m = boost::math::statistics::median_absolute_deviation(exec, v); + BOOST_TEST_EQ(m, 1); + + + v = {2, -4}; + m = boost::math::statistics::median_absolute_deviation(exec, v.begin(), v.end()); + BOOST_TEST_EQ(m, 3); + + v = {1, -1, 1}; + m = boost::math::statistics::median_absolute_deviation(exec, v.begin(), v.end()); + BOOST_TEST_EQ(m, 0); + + v = {1, 2, -3}; + m = boost::math::statistics::median_absolute_deviation(exec, v.begin(), v.end()); + BOOST_TEST_EQ(m, 1); + std::shuffle(v.begin(), v.end(), g); + m = boost::math::statistics::median_absolute_deviation(exec, v.begin(), v.end()); + BOOST_TEST_EQ(m, 1); + + w = {1, 2, -3}; + m = boost::math::statistics::median_absolute_deviation(exec, w); + BOOST_TEST_EQ(m, 1); + + // boost.ublas vector? + boost::numeric::ublas::vector u2(6); + u2[0] = 1; + u2[1] = 2; + u2[2] = -3; + u2[3] = 1; + u2[4] = 2; + u2[5] = -3; + m = boost::math::statistics::median_absolute_deviation(exec, u2); + BOOST_TEST_EQ(m, 1); } diff --git a/test/wavelet_transform_test.cpp b/test/wavelet_transform_test.cpp index 7a0fa16480..c49090957a 100644 --- a/test/wavelet_transform_test.cpp +++ b/test/wavelet_transform_test.cpp @@ -19,6 +19,10 @@ #include #include +#if __has_include() +# include +#endif + #ifdef BOOST_HAS_FLOAT128 #include using boost::multiprecision::float128; @@ -118,7 +122,7 @@ void test_wavelet_transform() for (double t = -10; t < 10; t+= 0.1) { Real w = Wg(s, t); - if (!CHECK_LE(abs(w), 10*sqrt(std::numeric_limits::epsilon()))) + if (!CHECK_LE(abs(w), Real(10*sqrt(std::numeric_limits::epsilon())))) { std::cerr << " Wavelet transform of constant with respect to " << p << " vanishing moment Daubechies wavelet is insufficiently small\n"; } @@ -127,7 +131,7 @@ void test_wavelet_transform() } // Wavelet transform of psi evaluated at s = 1, t = 0 is L2 norm of psi: auto Wpsi = daubechies_wavelet_transform(psi, psi); - CHECK_MOLLIFIED_CLOSE(Real(1), Wpsi(1,0), 2*sqrt(std::numeric_limits::epsilon())); + CHECK_MOLLIFIED_CLOSE(Real(1), Wpsi(1,0), Real(2*sqrt(std::numeric_limits::epsilon()))); } } @@ -135,9 +139,15 @@ void test_wavelet_transform() int main() { try{ + #ifdef __STDCPP_FLOAT64_T__ + test_wavelet_transform(); + test_wavelet_transform(); + test_wavelet_transform(); + #else test_wavelet_transform(); test_wavelet_transform(); test_wavelet_transform(); + #endif // All these tests pass, but the compilation takes too long on CI: //boost::hana::for_each(std::make_index_sequence<17>(), [&](auto i) { // test_wavelet_transform(); diff --git a/test/whittaker_shannon_test.cpp b/test/whittaker_shannon_test.cpp index 605b2694ac..0ca97daaec 100644 --- a/test/whittaker_shannon_test.cpp +++ b/test/whittaker_shannon_test.cpp @@ -12,6 +12,10 @@ #include #include +#if __has_include() +# include +#endif + using boost::math::interpolators::whittaker_shannon; template @@ -19,7 +23,7 @@ void test_trivial() { Real t0 = 0; Real h = Real(1)/Real(16); - std::vector v{1.5}; + std::vector v{Real(1.5)}; std::vector v_copy = v; auto ws = whittaker_shannon(std::move(v), t0, h); @@ -43,7 +47,7 @@ void test_knots() size_t n = 512; std::vector v(n); std::mt19937 gen(323723); - std::uniform_real_distribution dis(1.0, 2.0); + std::uniform_real_distribution dis(Real(1.0), Real(2.0)); for(size_t i = 0; i < n; ++i) { v[i] = static_cast(dis(gen)); @@ -125,21 +129,32 @@ void test_bump() int main() { + #ifdef __STDCPP_FLOAT32_T__ + test_trivial(); + test_knots(); + #else + test_trivial(); test_knots(); + #endif + + #ifdef __STDCPP_FLOAT64_T__ + test_trivial(); + test_knots(); + test_bump(); + #else + test_trivial(); test_knots(); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - test_knots(); -#endif - test_bump(); + #endif + + #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + test_knots(); #if LDBL_MANT_DIG <= 64 // Anything more precise than this fails for unknown reasons test_bump(); #endif #endif - test_trivial(); - test_trivial(); return boost::math::test::report_errors(); }