// Copyright Maksym Zhelyeznyakov 2025-2026. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // https://www.boost.org/LICENSE_1_0.txt) #ifndef TEST_AUTODIFF_REVERSE_HPP #define TEST_AUTODIFF_REVERSE_HPP #ifndef BOOST_TEST_MODULE #define BOOST_TEST_MODULE test_autodiff #endif #define BOOST_MP_NO_QUAD #define BOOST_MATH_DISABLE_FLOAT128 #include #include // always safe #if __has_include() #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include using boost::multiprecision::cpp_bin_float_50; namespace mp11 = boost::mp11; namespace bmp = boost::multiprecision; namespace rdiff_detail = boost::math::differentiation::reverse_mode::detail; namespace rdiff = boost::math::differentiation::reverse_mode; #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 #if !defined(BOOST_VERSION) || BOOST_VERSION < 107000 || defined(BOOST_USE_VALGRIND) \ || defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS) || defined(BOOST_NO_STRESS_TEST) \ || defined(BOOST_MATH_STANDALONE) using multiprecision_float_types = mp11::mp_list<>; #else #define BOOST_AUTODIFF_TESTING_INCLUDE_MULTIPRECISION using multiprecision_float_types = mp11::mp_list; #endif using all_float_types = mp11::mp_append; using namespace boost::math::differentiation; #endif // TEST_AUTODIFF_REVERSE_HPP template using is_multiprecision_t = mp11::mp_or, bmp::is_number_expression>; template using if_c = mp11::mp_eval_if_c; template using if_t = if_c; /** * struct to emit pseudo-random values from a given interval. * Endpoints are closed or open depending on whether or not they're infinite). */ /** * Simple struct to hold constants that are used in each test * since BOOST_AUTO_TEST_CASE_TEMPLATE doesn't support fixtures. */ template struct test_constants_t { static constexpr auto n_samples = if_t, bmp::is_number_expression>, mp11::mp_int<10>, mp11::mp_int<25>>::value; static constexpr auto order = OrderValue; static constexpr T pct_epsilon() noexcept { return (is_multiprecision_t::value ? 2 : 1) * std::numeric_limits::epsilon() * 100; } }; template using test_constants = test_constants_t; template struct RandomSample { using numeric_limits_t = std::numeric_limits; using is_integer_t = mp11::mp_bool::is_integer>; using distribution_param_t = if_t, if_t, long double>, T>; static_assert((std::numeric_limits::is_integer && std::numeric_limits::is_integer) || (!std::numeric_limits::is_integer && !std::numeric_limits::is_integer), "T and distribution_param_t must either both be integral or " "both be not integral"); using dist_t = if_t, std::uniform_real_distribution>; struct get_integral_endpoint { template constexpr distribution_param_t operator()(V finish) const noexcept { return static_cast(finish); } }; struct get_real_endpoint { template constexpr distribution_param_t operator()(V finish) const noexcept { return std::nextafter(static_cast(finish), (std::numeric_limits::max)()); } }; using get_endpoint_t = if_t; template RandomSample(U start, V finish) : rng_(std::random_device{}()) , dist_(static_cast(start), get_endpoint_t{}(finish)) {} T next() noexcept { return static_cast(dist_(rng_)); } T normalize(const T& x) noexcept { return x / ((dist_.max)() - (dist_.min)()); } std::mt19937 rng_; dist_t dist_; }; static_assert( std::is_same::dist_t, std::uniform_real_distribution>::value, ""); static_assert( std::is_same::dist_t, std::uniform_int_distribution>::value, ""); static_assert(std::is_same::dist_t, std::uniform_int_distribution>::value, ""); static_assert(std::is_same::dist_t, std::uniform_real_distribution>::value, ""); template constexpr T boost_close_tol(T scale_factor = 1e5) { return 0.01; }