From ade489a163755dd54578a58e97bfbd87ccd682c3 Mon Sep 17 00:00:00 2001 From: Ryan Date: Fri, 25 Aug 2023 21:33:18 -0400 Subject: [PATCH 1/4] initial commit --- include/boost/math/tools/promotion.hpp | 313 ++++++------------------- 1 file changed, 76 insertions(+), 237 deletions(-) diff --git a/include/boost/math/tools/promotion.hpp b/include/boost/math/tools/promotion.hpp index 68127efb04..7894d05e61 100644 --- a/include/boost/math/tools/promotion.hpp +++ b/include/boost/math/tools/promotion.hpp @@ -26,9 +26,6 @@ #include #include -#if __has_include() -# include -#endif namespace boost { @@ -36,230 +33,90 @@ namespace boost { namespace tools { + ///// This promotion system works as follows: + // + // Rule (one argument promotion rule): + // - Promotes `T` to `double` if `T` is an integer type as identified by + // `std::is_integral`, otherwise is `T` + // + // Rule (two or more argument promotion rule): + // - 1. Calculates type using applying Rule. + // - 2. Calculates type using applying Rule + // - If the type calculated in 1 and 2 are both floating point types, as + // identified by `std::is_floating_point`, then return the type + // determined by `std::common_type`. Otherwise return the type using + // an asymmetric convertibility rule. + // + ///// Discussion: + // // If either T1 or T2 is an integer type, // pretend it was a double (for the purposes of further analysis). // Then pick the wider of the two floating-point types // as the actual signature to forward to. // For example: - // foo(int, short) -> double foo(double, double); - // foo(int, float) -> double foo(double, double); - // Note: NOT float foo(float, float) - // foo(int, double) -> foo(double, double); - // foo(double, float) -> double foo(double, double); - // foo(double, float) -> double foo(double, double); - // foo(any-int-or-float-type, long double) -> foo(long double, long double); - // but ONLY float foo(float, float) is unchanged. - // So the only way to get an entirely float version is to call foo(1.F, 2.F), - // But since most (all?) the math functions convert to double internally, - // probably there would not be the hoped-for gain by using float here. - + // foo(int, short) -> double foo(double, double); // ***NOT*** float foo(float, float) + // foo(int, float) -> double foo(double, double); // ***NOT*** float foo(float, float) + // foo(int, double) -> foo(double, double); + // foo(double, float) -> double foo(double, double); + // foo(double, float) -> double foo(double, double); + // foo(any-int-or-float-type, long double) -> foo(long double, long double); + // ONLY float foo(float, float) is unchanged, so the only way to get an + // entirely float version is to call foo(1.F, 2.F). But since most (all?) the + // math functions convert to double internally, probably there would not be the + // hoped-for gain by using float here. + // // This follows the C-compatible conversion rules of pow, etc // where pow(int, float) is converted to pow(double, double). + + // Promotes a single argument to double if it is an integer type template - struct promote_arg - { // If T is integral type, then promote to double. - using type = typename std::conditional::value, double, T>::type; + struct promote_arg { + using type = typename std::conditional::value, double, T>::type; }; - // These full specialisations reduce std::conditional usage and speed up - // compilation: - template <> struct promote_arg { using type = float; }; - template <> struct promote_arg{ using type = double; }; - 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; + // Promotes two arguments, neither of which is an integer type using an asymmetric + // convertibility rule. + template ::value && std::is_floating_point::value)> + struct pa2_integral_already_removed { + using type = typename std::conditional< + !std::is_floating_point::value && std::is_convertible::value, + T2, T1>::type; + }; + // For two floating point types, promotes using `std::common_type` functionality template - struct promote_args_2 - { // Promote, if necessary, & pick the wider of the two floating-point types. - // 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 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 - 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: - template <> struct promote_args_2 { using type = float; }; - template <> struct promote_args_2{ using type = double; }; - template <> struct promote_args_2 { using type = long double; }; - template <> struct promote_args_2 { using type = double; }; - template <> struct promote_args_2 { using type = double; }; - template <> struct promote_args_2 { using type = double; }; - 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 = 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 = 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 + struct pa2_integral_already_removed { + using type = std::common_type_t; + }; - #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 definition for promote_args_permissive + template + struct promote_args_permissive; + // Specialization for one argument + template + struct promote_args_permissive { + using type = typename promote_arg::type>::type; + }; + // Specialization for two or more arguments + template + struct promote_args_permissive { + using type = typename pa2_integral_already_removed< + typename promote_args_permissive::type, + typename promote_args_permissive::type + >::type; + }; - template - using promote_args_2_t = typename promote_args_2::type; + template + using promote_args_permissive_t = typename promote_args_permissive::type; - template - struct promote_args - { - using type = typename promote_args_2< - typename std::remove_cv::type, - typename promote_args_2< - typename std::remove_cv::type, - typename promote_args_2< - typename std::remove_cv::type, - typename promote_args_2< - typename std::remove_cv::type, - typename promote_args_2< - typename std::remove_cv::type, typename std::remove_cv::type - >::type - >::type - >::type - >::type - >::type; + // Same as `promote_args_permissive` but with a static assertion that the promoted type + // is not `long double` if `BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS` is defined + template + struct promote_args { + using type = typename promote_args_permissive::type; #if defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS) // // Guard against use of long double if it's not supported: @@ -268,40 +125,22 @@ namespace boost #endif }; - template - using promote_args_t = typename promote_args::type; + template + using promote_args_t = typename promote_args::type; - // - // This struct is the same as above, but has no static assert on long double usage, - // it should be used only on functions that can be implemented for long double - // even when std lib support is missing or broken for that type. - // - template - struct promote_args_permissive - { - using type = typename promote_args_2< - typename std::remove_cv::type, - typename promote_args_2< - typename std::remove_cv::type, - typename promote_args_2< - typename std::remove_cv::type, - typename promote_args_2< - typename std::remove_cv::type, - typename promote_args_2< - typename std::remove_cv::type, typename std::remove_cv::type - >::type - >::type - >::type - >::type - >::type; + + // Used by autodiff and files in ccmath + template + struct promote_args_2 { + using type = typename promote_args_permissive::type; }; - template - using promote_args_permissive_t = typename promote_args_permissive::type; + template + using promote_args_2_t = typename promote_args_2::type; + } // namespace tools } // namespace math } // namespace boost #endif // BOOST_MATH_PROMOTION_HPP - From de16b832d30b1c5cc881d4369e6de255a00ecb9e Mon Sep 17 00:00:00 2001 From: Ryan Date: Sat, 26 Aug 2023 14:57:20 -0400 Subject: [PATCH 2/4] test fix for float16_t --- include/boost/math/policies/policy.hpp | 40 +++++++++++++++++-------- test/compile_test/test_promote_args.cpp | 2 +- 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/include/boost/math/policies/policy.hpp b/include/boost/math/policies/policy.hpp index 6daebaa64f..8d6b020f54 100644 --- a/include/boost/math/policies/policy.hpp +++ b/include/boost/math/policies/policy.hpp @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -723,22 +724,35 @@ inline constexpr typename normalise, A1, A2, A3, A4, A5, A6, A7, A8, A9 // // Traits class to handle internal promotion: // + template -struct evaluation -{ - typedef Real type; -}; +struct evaluation { + // Operation specific minimum float type + struct min_policy_allowed_float_type { + using type = float; + }; -template -struct evaluation -{ - using type = typename std::conditional::type; -}; + // Minimum type returned after applying double promotion rules + struct min_promote_with_float_type { + using type = typename std::conditional::type; + }; -template -struct evaluation -{ - using type = typename std::conditional::type; + // Minimum type returned after applying long double promotion rules + struct min_promote_with_double_type { + using type = typename std::conditional::type; + }; + + // Minimum type returned after applying double and long double promotion rules + struct min_evaluation_float_type { + using type = typename tools::promote_args::type; + }; + + using type = typename tools::promote_args::type; }; template diff --git a/test/compile_test/test_promote_args.cpp b/test/compile_test/test_promote_args.cpp index 2281aa7115..3205f139a3 100644 --- a/test/compile_test/test_promote_args.cpp +++ b/test/compile_test/test_promote_args.cpp @@ -89,7 +89,7 @@ int main() 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>); + static_assert(std::is_same_v, std::float16_t>); #endif #ifdef __STDCPP_FLOAT32_T__ static_assert(std::is_same_v, std::float32_t>); From a47822f72be660a9fcc8e769dde04a956cf677e4 Mon Sep 17 00:00:00 2001 From: Ryan Date: Sat, 26 Aug 2023 17:05:21 -0400 Subject: [PATCH 3/4] fix autodiff tests --- include/boost/math/tools/promotion.hpp | 1 + test/test_autodiff.hpp | 14 ++-- test/test_autodiff_3.cpp | 2 +- test/test_autodiff_6.cpp | 4 +- test/test_autodiff_8.cpp | 102 ++++++++++++------------- 5 files changed, 62 insertions(+), 61 deletions(-) diff --git a/include/boost/math/tools/promotion.hpp b/include/boost/math/tools/promotion.hpp index 7894d05e61..2a58a31660 100644 --- a/include/boost/math/tools/promotion.hpp +++ b/include/boost/math/tools/promotion.hpp @@ -3,6 +3,7 @@ // Copyright John Maddock 2006. // Copyright Paul A. Bristow 2006. // Copyright Matt Borland 2023. +// Copyright Ryan Elandt 2023. // Use, modification and distribution are subject to the // Boost Software License, Version 1.0. diff --git a/test/test_autodiff.hpp b/test/test_autodiff.hpp index 3a53827262..5f68e5577a 100644 --- a/test/test_autodiff.hpp +++ b/test/test_autodiff.hpp @@ -161,8 +161,8 @@ static_assert(std::is_same::dist_t, } // namespace test_detail -template -auto isNearZero(const T& t) noexcept -> typename std::enable_if::value, bool>::type +template +auto isNearZero(const T2& t) noexcept -> typename std::enable_if::value, bool>::type { using std::sqrt; using bmp::sqrt; @@ -172,14 +172,14 @@ auto isNearZero(const T& t) noexcept -> typename std::enable_if::epsilon())); + return fpclassify(fabs(t)) == FP_ZERO || fpclassify(fabs(t)) == FP_SUBNORMAL || boost::math::fpc::is_small(fabs(t), sqrt(std::numeric_limits::epsilon())); } -template -auto isNearZero(const T& t) noexcept -> typename std::enable_if::value, bool>::type +template +auto isNearZero(const T2& t) noexcept -> typename std::enable_if::value, bool>::type { - using root_type = typename T::root_type; - return isNearZero(static_cast(t)); + using root_type = typename T2::root_type; + return isNearZero(static_cast(t)); } template diff --git a/test/test_autodiff_3.cpp b/test/test_autodiff_3.cpp index e4d8590673..b44e055179 100644 --- a/test/test_autodiff_3.cpp +++ b/test/test_autodiff_3.cpp @@ -134,7 +134,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(tanh_test, T, all_float_types) { auto x = make_fvar(cx); auto t = tanh(x); for (auto i : boost::irange(tanh_derivatives.size())) { - BOOST_TEST_WARN(isNearZero(t.derivative(i) - tanh_derivatives[i])); + BOOST_TEST_WARN(isNearZero(t.derivative(i) - tanh_derivatives[i])); } } #endif diff --git a/test/test_autodiff_6.cpp b/test/test_autodiff_6.cpp index 7cbc11d0f3..0d8c80e92b 100644 --- a/test/test_autodiff_6.cpp +++ b/test/test_autodiff_6.cpp @@ -252,9 +252,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(erf_hpp, T, all_float_types) { std::ignore = i; auto x = x_sampler.next(); - BOOST_CHECK(isNearZero(erf(make_fvar(x)).derivative(0u) - + BOOST_CHECK(isNearZero(erf(make_fvar(x)).derivative(0u) - boost::math::erf(x))); - BOOST_CHECK(isNearZero(erfc(make_fvar(x)).derivative(0u) - + BOOST_CHECK(isNearZero(erfc(make_fvar(x)).derivative(0u) - boost::math::erfc(x))); } } diff --git a/test/test_autodiff_8.cpp b/test/test_autodiff_8.cpp index ecbf3fdc3b..e1776e2d5a 100644 --- a/test/test_autodiff_8.cpp +++ b/test/test_autodiff_8.cpp @@ -16,7 +16,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(hermite_hpp, T, all_float_types) { auto x = x_sampler.next(); auto autodiff_v = boost::math::hermite(i, make_fvar(x)); auto anchor_v = boost::math::hermite(i, x); - BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); + BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); } } @@ -33,7 +33,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(heuman_lambda_hpp, T, all_float_types) { auto autodiff_v = boost::math::heuman_lambda(make_fvar(x), make_fvar(phi)); auto anchor_v = boost::math::heuman_lambda(x, phi); - BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); + BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); } } @@ -49,7 +49,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(hypot_hpp, T, all_float_types) { auto autodiff_v = boost::math::hypot(make_fvar(x), make_fvar(y)); auto anchor_v = boost::math::hypot(x, y); - BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); + BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); } } @@ -62,51 +62,51 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(jacobi_elliptic_hpp, T, all_float_types) { std::ignore = i; auto k = k_sampler.next(); auto theta = theta_sampler.next(); - BOOST_CHECK(isNearZero( + BOOST_CHECK(isNearZero( boost::math::jacobi_cd(make_fvar(k), make_fvar(theta)) .derivative(0u) - boost::math::jacobi_cd(k, theta))); - BOOST_CHECK(isNearZero( + BOOST_CHECK(isNearZero( boost::math::jacobi_cn(make_fvar(k), make_fvar(theta)) .derivative(0u) - boost::math::jacobi_cn(k, theta))); - BOOST_CHECK(isNearZero( + BOOST_CHECK(isNearZero( boost::math::jacobi_cs(make_fvar(k), make_fvar(theta)) .derivative(0u) - boost::math::jacobi_cs(k, theta))); - BOOST_CHECK(isNearZero( + BOOST_CHECK(isNearZero( boost::math::jacobi_dc(make_fvar(k), make_fvar(theta)) .derivative(0u) - boost::math::jacobi_dc(k, theta))); - BOOST_CHECK(isNearZero( + BOOST_CHECK(isNearZero( boost::math::jacobi_dn(make_fvar(k), make_fvar(theta)) .derivative(0u) - boost::math::jacobi_dn(k, theta))); - BOOST_CHECK(isNearZero( + BOOST_CHECK(isNearZero( boost::math::jacobi_ds(make_fvar(k), make_fvar(theta)) .derivative(0u) - boost::math::jacobi_ds(k, theta))); - BOOST_CHECK(isNearZero( + BOOST_CHECK(isNearZero( boost::math::jacobi_nc(make_fvar(k), make_fvar(theta)) .derivative(0u) - boost::math::jacobi_nc(k, theta))); - BOOST_CHECK(isNearZero( + BOOST_CHECK(isNearZero( boost::math::jacobi_nd(make_fvar(k), make_fvar(theta)) .derivative(0u) - boost::math::jacobi_nd(k, theta))); - BOOST_CHECK(isNearZero( + BOOST_CHECK(isNearZero( boost::math::jacobi_ns(make_fvar(k), make_fvar(theta)) .derivative(0u) - boost::math::jacobi_ns(k, theta))); - BOOST_CHECK(isNearZero( + BOOST_CHECK(isNearZero( boost::math::jacobi_sc(make_fvar(k), make_fvar(theta)) .derivative(0u) - boost::math::jacobi_sc(k, theta))); - BOOST_CHECK(isNearZero( + BOOST_CHECK(isNearZero( boost::math::jacobi_sd(make_fvar(k), make_fvar(theta)) .derivative(0u) - boost::math::jacobi_sd(k, theta))); - BOOST_CHECK(isNearZero( + BOOST_CHECK(isNearZero( boost::math::jacobi_sn(make_fvar(k), make_fvar(theta)) .derivative(0u) - boost::math::jacobi_sn(k, theta))); @@ -123,7 +123,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(jacobi_zeta_hpp, T, all_float_types) { std::ignore = i; auto x = x_sampler.next(); auto phi = phi_sampler.next(); - BOOST_CHECK(isNearZero( + BOOST_CHECK(isNearZero( boost::math::jacobi_zeta(make_fvar(x), make_fvar(phi)) .derivative(0u) - boost::math::jacobi_zeta(x, phi))); @@ -149,12 +149,12 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(laguerre_hpp, T, all_float_types) { { auto autodiff_v = boost::math::laguerre(n, make_fvar(x)); auto anchor_v = boost::math::laguerre(n, x); - BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); + BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); } { auto autodiff_v = boost::math::laguerre(n, r, make_fvar(x)); auto anchor_v = boost::math::laguerre(n, r, x); - BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); + BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); } } } @@ -185,12 +185,12 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(lambert_w_hpp, T, all_float_types) { { auto autodiff_v = boost::math::lambert_w0(make_fvar(x_)); auto anchor_v = boost::math::lambert_w0(x_); - BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); + BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); } { auto autodiff_v = boost::math::lambert_w0_prime(make_fvar(x_)); auto anchor_v = boost::math::lambert_w0_prime(x_); - BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); + BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); } } @@ -201,10 +201,10 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(lambert_w_hpp, T, all_float_types) { ((std::numeric_limits::max))())), ((std::numeric_limits::max))()); x_ = (max)(static_cast(-0.36), x_); - BOOST_CHECK(isNearZero( + BOOST_CHECK(isNearZero( boost::math::lambert_wm1(make_fvar(x_)).derivative(0u) - boost::math::lambert_wm1(x_))); - BOOST_CHECK(isNearZero( + BOOST_CHECK(isNearZero( boost::math::lambert_wm1_prime(make_fvar(x_)).derivative(0u) - boost::math::lambert_wm1_prime(x_))); } @@ -222,7 +222,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(log1p_hpp, T, all_float_types) { std::ignore = i; auto x = x_sampler.next(); BOOST_CHECK( - isNearZero(log1p(make_fvar(x)).derivative(0u) - log1p(x))); + isNearZero(log1p(make_fvar(x)).derivative(0u) - log1p(x))); } } @@ -239,59 +239,59 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(next_hpp, T, all_float_types) { for (auto i : boost::irange(test_constants::n_samples)) { const auto j = static_cast(i); auto fvar_j = make_fvar(j); - BOOST_CHECK(isNearZero(float_next(fvar_j).derivative(0u) - float_next(j))); + BOOST_CHECK(isNearZero(float_next(fvar_j).derivative(0u) - float_next(j))); BOOST_CHECK( - isNearZero(float_prior(fvar_j).derivative(0u) - float_prior(j))); + isNearZero(float_prior(fvar_j).derivative(0u) - float_prior(j))); - BOOST_CHECK(isNearZero( + BOOST_CHECK(isNearZero( nextafter(fvar_j, make_fvar(static_cast(1))).derivative(0u) - nextafter(j, static_cast(1)))); BOOST_CHECK( - isNearZero(nextafter(fvar_j, make_fvar(static_cast(i + 2))) - + isNearZero(nextafter(fvar_j, make_fvar(static_cast(i + 2))) - nextafter(j, static_cast(i + 2)))); BOOST_CHECK( - isNearZero(nextafter(fvar_j, make_fvar(static_cast(i + 1))) + isNearZero(nextafter(fvar_j, make_fvar(static_cast(i + 1))) .derivative(0u) - nextafter(j, static_cast(i + 2)))); - BOOST_CHECK(isNearZero( + BOOST_CHECK(isNearZero( nextafter(fvar_j, make_fvar(static_cast(-1))).derivative(0u) - nextafter(j, static_cast(-1)))); - BOOST_CHECK(isNearZero( + BOOST_CHECK(isNearZero( nextafter(fvar_j, make_fvar(static_cast(-1 * (i + 2)))) .derivative(0u) - nextafter(j, -1 * static_cast(i + 2)))); - BOOST_CHECK(isNearZero( + BOOST_CHECK(isNearZero( nextafter(fvar_j, make_fvar(static_cast(-1 * (i + 1)))) .derivative(0u) - nextafter(j, -1 * static_cast(i + 2)))); - BOOST_CHECK(isNearZero(nextafter(fvar_j, fvar_j) - fvar_j)); + BOOST_CHECK(isNearZero(nextafter(fvar_j, fvar_j) - fvar_j)); - BOOST_CHECK(isNearZero(float_advance(fvar_j, 1).derivative(0u) - + BOOST_CHECK(isNearZero(float_advance(fvar_j, 1).derivative(0u) - float_advance(j, 1))); - BOOST_CHECK(isNearZero(float_advance(fvar_j, i + 2).derivative(0u) - + BOOST_CHECK(isNearZero(float_advance(fvar_j, i + 2).derivative(0u) - float_advance(j, i + 2))); - BOOST_CHECK(isNearZero( + BOOST_CHECK(isNearZero( float_advance(fvar_j, i + 1).derivative(0u) - float_advance(float_advance(fvar_j, i + 2), -1).derivative(0u))); - BOOST_CHECK(isNearZero(float_advance(fvar_j, -1).derivative(0u) - + BOOST_CHECK(isNearZero(float_advance(fvar_j, -1).derivative(0u) - float_advance(j, -1))); - BOOST_CHECK(isNearZero( + BOOST_CHECK(isNearZero( float_advance(fvar_j, -i - 1).derivative(0u) - float_advance(float_advance(fvar_j, -i - 2), 1).derivative(0u))); - BOOST_CHECK(isNearZero(float_advance(fvar_j, 0) - fvar_j)); + BOOST_CHECK(isNearZero(float_advance(fvar_j, 0) - fvar_j)); - BOOST_CHECK(isNearZero(float_distance(fvar_j, j).derivative(0u) - + BOOST_CHECK(isNearZero(float_distance(fvar_j, j).derivative(0u) - static_cast(0))); BOOST_CHECK( - isNearZero(float_distance(float_next(fvar_j), fvar_j).derivative(0u) - + isNearZero(float_distance(float_next(fvar_j), fvar_j).derivative(0u) - ((make_fvar(-1))).derivative(0u))); BOOST_CHECK( - isNearZero(float_distance(float_prior(fvar_j), fvar_j).derivative(0u) - + isNearZero(float_distance(float_prior(fvar_j), fvar_j).derivative(0u) - (make_fvar(1)).derivative(0u))); } } @@ -309,7 +309,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(owens_t_hpp, T, bin_float_types) { auto autodiff_v = boost::math::owens_t(make_fvar(h), make_fvar(a)); auto anchor_v = boost::math::owens_t(h, a); - BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); + BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); } } @@ -360,7 +360,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(polygamma_hpp, T, all_float_types) { try { auto autodiff_v = boost::math::polygamma(i, make_fvar(x)); auto anchor_v = boost::math::polygamma(i, x); - BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); + BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); } catch (const std::overflow_error &) { std::cout << "Overflow Error thrown with inputs i: " << i << " x: " << x << std::endl; @@ -406,7 +406,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(powm1_hpp, T, all_float_types) { auto autodiff_v = boost::math::powm1(make_fvar(x), make_fvar(y)); auto anchor_v = boost::math::powm1(x, y); - BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); + BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); } } @@ -420,7 +420,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(sin_pi_hpp, T, all_float_types) { std::ignore = i; auto x = x_sampler.next(); BOOST_CHECK( - isNearZero(boost::math::sin_pi(make_fvar(x)).derivative(0u) - + isNearZero(boost::math::sin_pi(make_fvar(x)).derivative(0u) - boost::math::sin_pi(x))); } } @@ -459,23 +459,23 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(spherical_harmonic_hpp, T, all_float_types) { n, r, make_fvar(theta), make_fvar(phi)); auto anchor_v = boost::math::spherical_harmonic(n, r, theta, phi); BOOST_CHECK( - isNearZero(autodiff_v.real().derivative(0u) - anchor_v.real())); + isNearZero(autodiff_v.real().derivative(0u) - anchor_v.real())); BOOST_CHECK( - isNearZero(autodiff_v.imag().derivative(0u) - anchor_v.imag())); + isNearZero(autodiff_v.imag().derivative(0u) - anchor_v.imag())); } { auto autodiff_v = boost::math::spherical_harmonic_r( n, r, make_fvar(theta), make_fvar(phi)); auto anchor_v = boost::math::spherical_harmonic_r(n, r, theta, phi); - BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); + BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); } { auto autodiff_v = boost::math::spherical_harmonic_i( n, r, make_fvar(theta), make_fvar(phi)); auto anchor_v = boost::math::spherical_harmonic_i(n, r, theta, phi); - BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); + BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); } } } @@ -488,7 +488,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(sqrt1pm1_hpp, T, all_float_types) { std::ignore = i; auto x = x_sampler.next(); BOOST_CHECK( - isNearZero(boost::math::sqrt1pm1(make_fvar(x)).derivative(0u) - + isNearZero(boost::math::sqrt1pm1(make_fvar(x)).derivative(0u) - boost::math::sqrt1pm1(x))); } } @@ -501,7 +501,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(trigamma_hpp, T, all_float_types) { std::ignore = i; auto x = x_sampler.next(); BOOST_CHECK( - isNearZero(boost::math::trigamma(make_fvar(x)).derivative(0u) - + isNearZero(boost::math::trigamma(make_fvar(x)).derivative(0u) - boost::math::trigamma(x))); } } From 024d56cc38ac86d3dc62752f90f5633fef40ed62 Mon Sep 17 00:00:00 2001 From: Ryan Date: Sat, 26 Aug 2023 17:58:49 -0400 Subject: [PATCH 4/4] specialize promote_args for autodiff --- include/boost/math/ccmath/copysign.hpp | 2 +- include/boost/math/ccmath/fdim.hpp | 2 +- include/boost/math/ccmath/fmax.hpp | 2 +- include/boost/math/ccmath/fmin.hpp | 2 +- include/boost/math/ccmath/hypot.hpp | 2 +- .../boost/math/differentiation/autodiff.hpp | 14 +-- include/boost/math/tools/promotion.hpp | 11 -- test/test_autodiff.hpp | 14 +-- test/test_autodiff_3.cpp | 2 +- test/test_autodiff_6.cpp | 4 +- test/test_autodiff_8.cpp | 102 +++++++++--------- 11 files changed, 73 insertions(+), 84 deletions(-) diff --git a/include/boost/math/ccmath/copysign.hpp b/include/boost/math/ccmath/copysign.hpp index 90a58102b1..e117e57faa 100644 --- a/include/boost/math/ccmath/copysign.hpp +++ b/include/boost/math/ccmath/copysign.hpp @@ -54,7 +54,7 @@ constexpr auto copysign(T1 mag, T2 sgn) noexcept { if (BOOST_MATH_IS_CONSTANT_EVALUATED(mag)) { - using promoted_type = boost::math::tools::promote_args_2_t; + using promoted_type = boost::math::tools::promote_args_t; return boost::math::ccmath::copysign(static_cast(mag), static_cast(sgn)); } else diff --git a/include/boost/math/ccmath/fdim.hpp b/include/boost/math/ccmath/fdim.hpp index 024eb9c934..3aeddda9b5 100644 --- a/include/boost/math/ccmath/fdim.hpp +++ b/include/boost/math/ccmath/fdim.hpp @@ -64,7 +64,7 @@ constexpr auto fdim(T1 x, T2 y) noexcept { if (BOOST_MATH_IS_CONSTANT_EVALUATED(x)) { - using promoted_type = boost::math::tools::promote_args_2_t; + using promoted_type = boost::math::tools::promote_args_t; return boost::math::ccmath::fdim(promoted_type(x), promoted_type(y)); } else diff --git a/include/boost/math/ccmath/fmax.hpp b/include/boost/math/ccmath/fmax.hpp index 0eb1ecbaae..e477b41dc6 100644 --- a/include/boost/math/ccmath/fmax.hpp +++ b/include/boost/math/ccmath/fmax.hpp @@ -60,7 +60,7 @@ constexpr auto fmax(T1 x, T2 y) noexcept { if (BOOST_MATH_IS_CONSTANT_EVALUATED(x)) { - using promoted_type = boost::math::tools::promote_args_2_t; + using promoted_type = boost::math::tools::promote_args_t; return boost::math::ccmath::fmax(static_cast(x), static_cast(y)); } else diff --git a/include/boost/math/ccmath/fmin.hpp b/include/boost/math/ccmath/fmin.hpp index 3de0b7e434..d2a8570755 100644 --- a/include/boost/math/ccmath/fmin.hpp +++ b/include/boost/math/ccmath/fmin.hpp @@ -60,7 +60,7 @@ constexpr auto fmin(T1 x, T2 y) noexcept { if (BOOST_MATH_IS_CONSTANT_EVALUATED(x)) { - using promoted_type = boost::math::tools::promote_args_2_t; + using promoted_type = boost::math::tools::promote_args_t; return boost::math::ccmath::fmin(static_cast(x), static_cast(y)); } else diff --git a/include/boost/math/ccmath/hypot.hpp b/include/boost/math/ccmath/hypot.hpp index 613b2681ac..9f866dbb70 100644 --- a/include/boost/math/ccmath/hypot.hpp +++ b/include/boost/math/ccmath/hypot.hpp @@ -87,7 +87,7 @@ constexpr auto hypot(T1 x, T2 y) noexcept { if(BOOST_MATH_IS_CONSTANT_EVALUATED(x)) { - using promoted_type = boost::math::tools::promote_args_2_t; + using promoted_type = boost::math::tools::promote_args_t; return boost::math::ccmath::hypot(static_cast(x), static_cast(y)); } else diff --git a/include/boost/math/differentiation/autodiff.hpp b/include/boost/math/differentiation/autodiff.hpp index 7cda196852..9ee5bdcd63 100644 --- a/include/boost/math/differentiation/autodiff.hpp +++ b/include/boost/math/differentiation/autodiff.hpp @@ -39,7 +39,7 @@ namespace detail { template struct promote_args_n { - using type = typename tools::promote_args_2::type>::type; + using type = typename tools::promote_args::type>::type; }; template @@ -2002,9 +2002,9 @@ using autodiff_root_type = typename autodiff_fvar_type::root_ty // See boost/math/tools/promotion.hpp template -struct promote_args_2, +struct promote_args, detail::autodiff_fvar_type> { - using type = detail::autodiff_fvar_type::type, + using type = detail::autodiff_fvar_type::type, #ifndef BOOST_NO_CXX14_CONSTEXPR (std::max)(Order0, Order1)>; #else @@ -2018,13 +2018,13 @@ struct promote_args> { }; template -struct promote_args_2, RealType1> { - using type = detail::autodiff_fvar_type::type, Order0>; +struct promote_args, RealType1> { + using type = detail::autodiff_fvar_type::type, Order0>; }; template -struct promote_args_2> { - using type = detail::autodiff_fvar_type::type, Order1>; +struct promote_args> { + using type = detail::autodiff_fvar_type::type, Order1>; }; template diff --git a/include/boost/math/tools/promotion.hpp b/include/boost/math/tools/promotion.hpp index 2a58a31660..54920b4628 100644 --- a/include/boost/math/tools/promotion.hpp +++ b/include/boost/math/tools/promotion.hpp @@ -129,17 +129,6 @@ namespace boost template using promote_args_t = typename promote_args::type; - - // Used by autodiff and files in ccmath - template - struct promote_args_2 { - using type = typename promote_args_permissive::type; - }; - - template - using promote_args_2_t = typename promote_args_2::type; - - } // namespace tools } // namespace math } // namespace boost diff --git a/test/test_autodiff.hpp b/test/test_autodiff.hpp index 5f68e5577a..3a53827262 100644 --- a/test/test_autodiff.hpp +++ b/test/test_autodiff.hpp @@ -161,8 +161,8 @@ static_assert(std::is_same::dist_t, } // namespace test_detail -template -auto isNearZero(const T2& t) noexcept -> typename std::enable_if::value, bool>::type +template +auto isNearZero(const T& t) noexcept -> typename std::enable_if::value, bool>::type { using std::sqrt; using bmp::sqrt; @@ -172,14 +172,14 @@ auto isNearZero(const T2& t) noexcept -> typename std::enable_if::epsilon())); + return fpclassify(fabs(t)) == FP_ZERO || fpclassify(fabs(t)) == FP_SUBNORMAL || boost::math::fpc::is_small(fabs(t), sqrt(std::numeric_limits::epsilon())); } -template -auto isNearZero(const T2& t) noexcept -> typename std::enable_if::value, bool>::type +template +auto isNearZero(const T& t) noexcept -> typename std::enable_if::value, bool>::type { - using root_type = typename T2::root_type; - return isNearZero(static_cast(t)); + using root_type = typename T::root_type; + return isNearZero(static_cast(t)); } template diff --git a/test/test_autodiff_3.cpp b/test/test_autodiff_3.cpp index b44e055179..e4d8590673 100644 --- a/test/test_autodiff_3.cpp +++ b/test/test_autodiff_3.cpp @@ -134,7 +134,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(tanh_test, T, all_float_types) { auto x = make_fvar(cx); auto t = tanh(x); for (auto i : boost::irange(tanh_derivatives.size())) { - BOOST_TEST_WARN(isNearZero(t.derivative(i) - tanh_derivatives[i])); + BOOST_TEST_WARN(isNearZero(t.derivative(i) - tanh_derivatives[i])); } } #endif diff --git a/test/test_autodiff_6.cpp b/test/test_autodiff_6.cpp index 0d8c80e92b..7cbc11d0f3 100644 --- a/test/test_autodiff_6.cpp +++ b/test/test_autodiff_6.cpp @@ -252,9 +252,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(erf_hpp, T, all_float_types) { std::ignore = i; auto x = x_sampler.next(); - BOOST_CHECK(isNearZero(erf(make_fvar(x)).derivative(0u) - + BOOST_CHECK(isNearZero(erf(make_fvar(x)).derivative(0u) - boost::math::erf(x))); - BOOST_CHECK(isNearZero(erfc(make_fvar(x)).derivative(0u) - + BOOST_CHECK(isNearZero(erfc(make_fvar(x)).derivative(0u) - boost::math::erfc(x))); } } diff --git a/test/test_autodiff_8.cpp b/test/test_autodiff_8.cpp index e1776e2d5a..ecbf3fdc3b 100644 --- a/test/test_autodiff_8.cpp +++ b/test/test_autodiff_8.cpp @@ -16,7 +16,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(hermite_hpp, T, all_float_types) { auto x = x_sampler.next(); auto autodiff_v = boost::math::hermite(i, make_fvar(x)); auto anchor_v = boost::math::hermite(i, x); - BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); + BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); } } @@ -33,7 +33,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(heuman_lambda_hpp, T, all_float_types) { auto autodiff_v = boost::math::heuman_lambda(make_fvar(x), make_fvar(phi)); auto anchor_v = boost::math::heuman_lambda(x, phi); - BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); + BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); } } @@ -49,7 +49,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(hypot_hpp, T, all_float_types) { auto autodiff_v = boost::math::hypot(make_fvar(x), make_fvar(y)); auto anchor_v = boost::math::hypot(x, y); - BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); + BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); } } @@ -62,51 +62,51 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(jacobi_elliptic_hpp, T, all_float_types) { std::ignore = i; auto k = k_sampler.next(); auto theta = theta_sampler.next(); - BOOST_CHECK(isNearZero( + BOOST_CHECK(isNearZero( boost::math::jacobi_cd(make_fvar(k), make_fvar(theta)) .derivative(0u) - boost::math::jacobi_cd(k, theta))); - BOOST_CHECK(isNearZero( + BOOST_CHECK(isNearZero( boost::math::jacobi_cn(make_fvar(k), make_fvar(theta)) .derivative(0u) - boost::math::jacobi_cn(k, theta))); - BOOST_CHECK(isNearZero( + BOOST_CHECK(isNearZero( boost::math::jacobi_cs(make_fvar(k), make_fvar(theta)) .derivative(0u) - boost::math::jacobi_cs(k, theta))); - BOOST_CHECK(isNearZero( + BOOST_CHECK(isNearZero( boost::math::jacobi_dc(make_fvar(k), make_fvar(theta)) .derivative(0u) - boost::math::jacobi_dc(k, theta))); - BOOST_CHECK(isNearZero( + BOOST_CHECK(isNearZero( boost::math::jacobi_dn(make_fvar(k), make_fvar(theta)) .derivative(0u) - boost::math::jacobi_dn(k, theta))); - BOOST_CHECK(isNearZero( + BOOST_CHECK(isNearZero( boost::math::jacobi_ds(make_fvar(k), make_fvar(theta)) .derivative(0u) - boost::math::jacobi_ds(k, theta))); - BOOST_CHECK(isNearZero( + BOOST_CHECK(isNearZero( boost::math::jacobi_nc(make_fvar(k), make_fvar(theta)) .derivative(0u) - boost::math::jacobi_nc(k, theta))); - BOOST_CHECK(isNearZero( + BOOST_CHECK(isNearZero( boost::math::jacobi_nd(make_fvar(k), make_fvar(theta)) .derivative(0u) - boost::math::jacobi_nd(k, theta))); - BOOST_CHECK(isNearZero( + BOOST_CHECK(isNearZero( boost::math::jacobi_ns(make_fvar(k), make_fvar(theta)) .derivative(0u) - boost::math::jacobi_ns(k, theta))); - BOOST_CHECK(isNearZero( + BOOST_CHECK(isNearZero( boost::math::jacobi_sc(make_fvar(k), make_fvar(theta)) .derivative(0u) - boost::math::jacobi_sc(k, theta))); - BOOST_CHECK(isNearZero( + BOOST_CHECK(isNearZero( boost::math::jacobi_sd(make_fvar(k), make_fvar(theta)) .derivative(0u) - boost::math::jacobi_sd(k, theta))); - BOOST_CHECK(isNearZero( + BOOST_CHECK(isNearZero( boost::math::jacobi_sn(make_fvar(k), make_fvar(theta)) .derivative(0u) - boost::math::jacobi_sn(k, theta))); @@ -123,7 +123,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(jacobi_zeta_hpp, T, all_float_types) { std::ignore = i; auto x = x_sampler.next(); auto phi = phi_sampler.next(); - BOOST_CHECK(isNearZero( + BOOST_CHECK(isNearZero( boost::math::jacobi_zeta(make_fvar(x), make_fvar(phi)) .derivative(0u) - boost::math::jacobi_zeta(x, phi))); @@ -149,12 +149,12 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(laguerre_hpp, T, all_float_types) { { auto autodiff_v = boost::math::laguerre(n, make_fvar(x)); auto anchor_v = boost::math::laguerre(n, x); - BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); + BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); } { auto autodiff_v = boost::math::laguerre(n, r, make_fvar(x)); auto anchor_v = boost::math::laguerre(n, r, x); - BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); + BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); } } } @@ -185,12 +185,12 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(lambert_w_hpp, T, all_float_types) { { auto autodiff_v = boost::math::lambert_w0(make_fvar(x_)); auto anchor_v = boost::math::lambert_w0(x_); - BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); + BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); } { auto autodiff_v = boost::math::lambert_w0_prime(make_fvar(x_)); auto anchor_v = boost::math::lambert_w0_prime(x_); - BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); + BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); } } @@ -201,10 +201,10 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(lambert_w_hpp, T, all_float_types) { ((std::numeric_limits::max))())), ((std::numeric_limits::max))()); x_ = (max)(static_cast(-0.36), x_); - BOOST_CHECK(isNearZero( + BOOST_CHECK(isNearZero( boost::math::lambert_wm1(make_fvar(x_)).derivative(0u) - boost::math::lambert_wm1(x_))); - BOOST_CHECK(isNearZero( + BOOST_CHECK(isNearZero( boost::math::lambert_wm1_prime(make_fvar(x_)).derivative(0u) - boost::math::lambert_wm1_prime(x_))); } @@ -222,7 +222,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(log1p_hpp, T, all_float_types) { std::ignore = i; auto x = x_sampler.next(); BOOST_CHECK( - isNearZero(log1p(make_fvar(x)).derivative(0u) - log1p(x))); + isNearZero(log1p(make_fvar(x)).derivative(0u) - log1p(x))); } } @@ -239,59 +239,59 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(next_hpp, T, all_float_types) { for (auto i : boost::irange(test_constants::n_samples)) { const auto j = static_cast(i); auto fvar_j = make_fvar(j); - BOOST_CHECK(isNearZero(float_next(fvar_j).derivative(0u) - float_next(j))); + BOOST_CHECK(isNearZero(float_next(fvar_j).derivative(0u) - float_next(j))); BOOST_CHECK( - isNearZero(float_prior(fvar_j).derivative(0u) - float_prior(j))); + isNearZero(float_prior(fvar_j).derivative(0u) - float_prior(j))); - BOOST_CHECK(isNearZero( + BOOST_CHECK(isNearZero( nextafter(fvar_j, make_fvar(static_cast(1))).derivative(0u) - nextafter(j, static_cast(1)))); BOOST_CHECK( - isNearZero(nextafter(fvar_j, make_fvar(static_cast(i + 2))) - + isNearZero(nextafter(fvar_j, make_fvar(static_cast(i + 2))) - nextafter(j, static_cast(i + 2)))); BOOST_CHECK( - isNearZero(nextafter(fvar_j, make_fvar(static_cast(i + 1))) + isNearZero(nextafter(fvar_j, make_fvar(static_cast(i + 1))) .derivative(0u) - nextafter(j, static_cast(i + 2)))); - BOOST_CHECK(isNearZero( + BOOST_CHECK(isNearZero( nextafter(fvar_j, make_fvar(static_cast(-1))).derivative(0u) - nextafter(j, static_cast(-1)))); - BOOST_CHECK(isNearZero( + BOOST_CHECK(isNearZero( nextafter(fvar_j, make_fvar(static_cast(-1 * (i + 2)))) .derivative(0u) - nextafter(j, -1 * static_cast(i + 2)))); - BOOST_CHECK(isNearZero( + BOOST_CHECK(isNearZero( nextafter(fvar_j, make_fvar(static_cast(-1 * (i + 1)))) .derivative(0u) - nextafter(j, -1 * static_cast(i + 2)))); - BOOST_CHECK(isNearZero(nextafter(fvar_j, fvar_j) - fvar_j)); + BOOST_CHECK(isNearZero(nextafter(fvar_j, fvar_j) - fvar_j)); - BOOST_CHECK(isNearZero(float_advance(fvar_j, 1).derivative(0u) - + BOOST_CHECK(isNearZero(float_advance(fvar_j, 1).derivative(0u) - float_advance(j, 1))); - BOOST_CHECK(isNearZero(float_advance(fvar_j, i + 2).derivative(0u) - + BOOST_CHECK(isNearZero(float_advance(fvar_j, i + 2).derivative(0u) - float_advance(j, i + 2))); - BOOST_CHECK(isNearZero( + BOOST_CHECK(isNearZero( float_advance(fvar_j, i + 1).derivative(0u) - float_advance(float_advance(fvar_j, i + 2), -1).derivative(0u))); - BOOST_CHECK(isNearZero(float_advance(fvar_j, -1).derivative(0u) - + BOOST_CHECK(isNearZero(float_advance(fvar_j, -1).derivative(0u) - float_advance(j, -1))); - BOOST_CHECK(isNearZero( + BOOST_CHECK(isNearZero( float_advance(fvar_j, -i - 1).derivative(0u) - float_advance(float_advance(fvar_j, -i - 2), 1).derivative(0u))); - BOOST_CHECK(isNearZero(float_advance(fvar_j, 0) - fvar_j)); + BOOST_CHECK(isNearZero(float_advance(fvar_j, 0) - fvar_j)); - BOOST_CHECK(isNearZero(float_distance(fvar_j, j).derivative(0u) - + BOOST_CHECK(isNearZero(float_distance(fvar_j, j).derivative(0u) - static_cast(0))); BOOST_CHECK( - isNearZero(float_distance(float_next(fvar_j), fvar_j).derivative(0u) - + isNearZero(float_distance(float_next(fvar_j), fvar_j).derivative(0u) - ((make_fvar(-1))).derivative(0u))); BOOST_CHECK( - isNearZero(float_distance(float_prior(fvar_j), fvar_j).derivative(0u) - + isNearZero(float_distance(float_prior(fvar_j), fvar_j).derivative(0u) - (make_fvar(1)).derivative(0u))); } } @@ -309,7 +309,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(owens_t_hpp, T, bin_float_types) { auto autodiff_v = boost::math::owens_t(make_fvar(h), make_fvar(a)); auto anchor_v = boost::math::owens_t(h, a); - BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); + BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); } } @@ -360,7 +360,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(polygamma_hpp, T, all_float_types) { try { auto autodiff_v = boost::math::polygamma(i, make_fvar(x)); auto anchor_v = boost::math::polygamma(i, x); - BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); + BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); } catch (const std::overflow_error &) { std::cout << "Overflow Error thrown with inputs i: " << i << " x: " << x << std::endl; @@ -406,7 +406,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(powm1_hpp, T, all_float_types) { auto autodiff_v = boost::math::powm1(make_fvar(x), make_fvar(y)); auto anchor_v = boost::math::powm1(x, y); - BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); + BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); } } @@ -420,7 +420,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(sin_pi_hpp, T, all_float_types) { std::ignore = i; auto x = x_sampler.next(); BOOST_CHECK( - isNearZero(boost::math::sin_pi(make_fvar(x)).derivative(0u) - + isNearZero(boost::math::sin_pi(make_fvar(x)).derivative(0u) - boost::math::sin_pi(x))); } } @@ -459,23 +459,23 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(spherical_harmonic_hpp, T, all_float_types) { n, r, make_fvar(theta), make_fvar(phi)); auto anchor_v = boost::math::spherical_harmonic(n, r, theta, phi); BOOST_CHECK( - isNearZero(autodiff_v.real().derivative(0u) - anchor_v.real())); + isNearZero(autodiff_v.real().derivative(0u) - anchor_v.real())); BOOST_CHECK( - isNearZero(autodiff_v.imag().derivative(0u) - anchor_v.imag())); + isNearZero(autodiff_v.imag().derivative(0u) - anchor_v.imag())); } { auto autodiff_v = boost::math::spherical_harmonic_r( n, r, make_fvar(theta), make_fvar(phi)); auto anchor_v = boost::math::spherical_harmonic_r(n, r, theta, phi); - BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); + BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); } { auto autodiff_v = boost::math::spherical_harmonic_i( n, r, make_fvar(theta), make_fvar(phi)); auto anchor_v = boost::math::spherical_harmonic_i(n, r, theta, phi); - BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); + BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); } } } @@ -488,7 +488,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(sqrt1pm1_hpp, T, all_float_types) { std::ignore = i; auto x = x_sampler.next(); BOOST_CHECK( - isNearZero(boost::math::sqrt1pm1(make_fvar(x)).derivative(0u) - + isNearZero(boost::math::sqrt1pm1(make_fvar(x)).derivative(0u) - boost::math::sqrt1pm1(x))); } } @@ -501,7 +501,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(trigamma_hpp, T, all_float_types) { std::ignore = i; auto x = x_sampler.next(); BOOST_CHECK( - isNearZero(boost::math::trigamma(make_fvar(x)).derivative(0u) - + isNearZero(boost::math::trigamma(make_fvar(x)).derivative(0u) - boost::math::trigamma(x))); } }