2
0
mirror of https://github.com/boostorg/math.git synced 2026-01-29 19:52:08 +00:00
Files
math/test/test_autodiff_7.cpp
pulver 95defb67df Add make_ftuple(), digamma(), lgamma(), tgamma(), doc/test updates. (#218)
Improve tests and coverage. C++11/14 support. (@kedarbhat)
2019-06-25 17:31:48 -07:00

333 lines
14 KiB
C++

// Copyright Matthew Pulver 2018 - 2019.
// 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)
#include "test_autodiff.hpp"
BOOST_AUTO_TEST_SUITE(test_autodiff_7)
BOOST_AUTO_TEST_CASE_TEMPLATE(expm1_hpp, T, all_float_types) {
using boost::math::differentiation::detail::log;
using boost::multiprecision::log;
using std::log;
using test_constants = test_constants_t<T>;
static constexpr auto m = test_constants::order;
test_detail::RandomSample<T> x_sampler{-log(T(2000)), log(T(2000))};
for (auto i : boost::irange(test_constants::n_samples)) {
std::ignore = i;
auto x = x_sampler.next();
BOOST_CHECK_CLOSE(boost::math::expm1(make_fvar<T, m>(x)).derivative(0u),
boost::math::expm1(x),
50 * test_constants::pct_epsilon());
}
}
BOOST_AUTO_TEST_CASE_TEMPLATE(factorials_hpp, T, all_float_types) {
using test_constants = test_constants_t<T>;
static constexpr auto m = test_constants::order;
test_detail::RandomSample<T> x_sampler{0, 28};
for (auto i :
boost::irange(static_cast<unsigned>(test_constants::n_samples))) {
{
auto fact_i = boost::math::factorial<T>(i);
auto autodiff_v = boost::math::factorial<autodiff_fvar<T, m>>(i);
BOOST_CHECK_CLOSE(autodiff_v.derivative(0u), fact_i,
50 * test_constants::pct_epsilon());
}
{
auto fact_i = boost::math::unchecked_factorial<T>(i);
auto autodiff_v =
boost::math::unchecked_factorial<autodiff_fvar<T, m>>(i);
BOOST_CHECK_CLOSE(autodiff_v.derivative(0u), fact_i,
50 * test_constants::pct_epsilon());
}
{
auto fact_i = boost::math::unchecked_factorial<T>(i);
auto autodiff_v =
boost::math::unchecked_factorial<autodiff_fvar<T, m>>(i);
BOOST_CHECK_CLOSE(autodiff_v.derivative(0u), fact_i,
50 * test_constants::pct_epsilon());
}
{
auto fact_i = boost::math::double_factorial<T>(i);
auto autodiff_v = boost::math::double_factorial<autodiff_fvar<T, m>>(i);
BOOST_CHECK_CLOSE(autodiff_v.derivative(0u), fact_i,
50 * test_constants::pct_epsilon());
}
auto x = x_sampler.next();
{
auto fact_i = boost::math::rising_factorial<T>(x, static_cast<int>(i));
auto autodiff_v = make_fvar<T, m>(fact_i);
BOOST_CHECK_CLOSE(autodiff_v.derivative(0u), fact_i,
50 * test_constants::pct_epsilon());
}
{
auto fact_i =
boost::math::falling_factorial<T>(x, test_constants::n_samples - i);
auto autodiff_v = make_fvar<T, m>(fact_i);
BOOST_CHECK_CLOSE(autodiff_v.derivative(0u), fact_i,
50 * test_constants::pct_epsilon());
}
}
}
BOOST_AUTO_TEST_CASE_TEMPLATE(fpclassify_hpp, T, all_float_types) {
using boost::math::fpclassify;
using boost::math::isfinite;
using boost::math::isinf;
using boost::math::isnan;
using boost::math::isnormal;
using boost::multiprecision::fpclassify;
using boost::multiprecision::isfinite;
using boost::multiprecision::isinf;
using boost::multiprecision::isnan;
using boost::multiprecision::isnormal;
using test_constants = test_constants_t<T>;
static constexpr auto m = test_constants::order;
test_detail::RandomSample<T> x_sampler{-1000, 1000};
for (auto i : boost::irange(test_constants::n_samples)) {
std::ignore = i;
BOOST_CHECK_EQUAL(fpclassify(make_fvar<T, m>(0)), FP_ZERO);
BOOST_CHECK_EQUAL(fpclassify(make_fvar<T, m>(10)), FP_NORMAL);
BOOST_CHECK_EQUAL(
fpclassify(make_fvar<T, m>(std::numeric_limits<T>::infinity())),
FP_INFINITE);
BOOST_CHECK_EQUAL(
fpclassify(make_fvar<T, m>(std::numeric_limits<T>::quiet_NaN())),
FP_NAN);
if (std::numeric_limits<T>::has_denorm != std::denorm_absent) {
BOOST_CHECK_EQUAL(
fpclassify(make_fvar<T, m>(std::numeric_limits<T>::denorm_min())),
FP_SUBNORMAL);
}
BOOST_CHECK(isfinite(make_fvar<T, m>(0)));
BOOST_CHECK(isnormal(make_fvar<T, m>((std::numeric_limits<T>::min)())));
BOOST_CHECK(
!isnormal(make_fvar<T, m>(std::numeric_limits<T>::denorm_min())));
BOOST_CHECK(isinf(make_fvar<T, m>(std::numeric_limits<T>::infinity())));
BOOST_CHECK(isnan(make_fvar<T, m>(std::numeric_limits<T>::quiet_NaN())));
}
}
// multiprecision types are breaking in here due to a lexical_cast error
BOOST_AUTO_TEST_CASE_TEMPLATE(gamma_hpp, T, bin_float_types) {
using boost::math::nextafter;
using boost::multiprecision::nextafter;
using test_constants = test_constants_t<T>;
static constexpr auto m = test_constants::order;
test_detail::RandomSample<T> z_sampler{0, 34};
test_detail::RandomSample<T> a_sampler{0, 34};
for (auto i : boost::irange(test_constants::n_samples)) {
std::ignore = i;
auto z = z_sampler.next();
{
using boost::math::tgamma;
using boost::multiprecision::tgamma;
auto autodiff_v = tgamma(make_fvar<T, m>(z));
auto anchor_v = tgamma(z);
BOOST_CHECK_CLOSE(autodiff_v.derivative(0u), anchor_v,
2.5e5 * test_constants::pct_epsilon());
}
{
using boost::math::tgamma1pm1;
auto autodiff_v = tgamma1pm1(make_fvar<T, m>(z));
auto anchor_v = tgamma1pm1(z);
BOOST_CHECK_CLOSE(autodiff_v.derivative(0u), anchor_v,
2.5e5 * test_constants::pct_epsilon());
}
{
int s1 = 0;
int s2 = 0;
using boost::math::lgamma;
using boost::multiprecision::lgamma;
BOOST_CHECK_CLOSE(
lgamma(make_fvar<T, m>(z).derivative(0u), std::addressof(s1)),
lgamma(z, std::addressof(s2)), 2.5e5 * test_constants::pct_epsilon());
BOOST_CHECK(
(std::addressof(s1) == nullptr && std::addressof(s2) == nullptr) ||
(s1 == s2));
}
{
using boost::math::tgamma_lower;
auto a = nextafter(a_sampler.next(), ((std::numeric_limits<T>::max))());
auto autodiff_v = tgamma_lower(make_fvar<T, m>(a), make_fvar<T, m>(z));
auto anchor_v = tgamma_lower(a, z);
BOOST_CHECK_CLOSE(autodiff_v.derivative(0u), anchor_v,
2.5e5 * test_constants::pct_epsilon());
}
{
using boost::math::gamma_q;
auto a = nextafter(a_sampler.next(), ((std::numeric_limits<T>::max))());
auto autodiff_v = gamma_q(make_fvar<T, m>(a), make_fvar<T, m>(z));
auto anchor_v = gamma_q(a, z);
BOOST_CHECK_CLOSE(autodiff_v.derivative(0u), anchor_v,
2.5e5 * test_constants::pct_epsilon());
}
{
using boost::math::gamma_p;
auto a = nextafter(a_sampler.next(), ((std::numeric_limits<T>::max))());
auto autodiff_v = gamma_p(make_fvar<T, m>(a), make_fvar<T, m>(z));
auto anchor_v = gamma_p(a, z);
BOOST_CHECK_CLOSE(autodiff_v.derivative(0u), anchor_v,
2.5e5 * test_constants::pct_epsilon());
}
auto z_normalized = z_sampler.normalize(z);
{
using boost::math::gamma_p_inv;
auto a_normalized = a_sampler.normalize(a_sampler.next());
auto autodiff_v = gamma_p_inv(make_fvar<T, m>(a_normalized),
make_fvar<T, m>(z_normalized));
auto anchor_v = gamma_p_inv(a_normalized, z_normalized);
BOOST_CHECK_CLOSE(autodiff_v.derivative(0u), anchor_v,
2.5e5 * test_constants::pct_epsilon());
}
{
using boost::math::gamma_q_inv;
auto a_normalized = a_sampler.normalize(a_sampler.next());
auto autodiff_v = gamma_q_inv(make_fvar<T, m>(a_normalized),
make_fvar<T, m>(z_normalized));
auto anchor_v = gamma_q_inv(a_normalized, z_normalized);
BOOST_CHECK_CLOSE(autodiff_v.derivative(0u), anchor_v,
2.5e5 * test_constants::pct_epsilon());
}
{
using boost::math::gamma_p_inva;
auto a_normalized = a_sampler.normalize(a_sampler.next());
auto autodiff_v = gamma_p_inva(make_fvar<T, m>(a_normalized),
make_fvar<T, m>(z_normalized));
auto anchor_v = gamma_p_inva(a_normalized, z_normalized);
BOOST_CHECK_CLOSE(autodiff_v.derivative(0u), anchor_v,
2.5e5 * test_constants::pct_epsilon());
}
{
using boost::math::gamma_q_inva;
auto a_normalized = a_sampler.normalize(a_sampler.next());
auto autodiff_v = gamma_q_inva(make_fvar<T, m>(a_normalized),
make_fvar<T, m>(z_normalized));
auto anchor_v = gamma_q_inva(a_normalized, z_normalized);
BOOST_CHECK_CLOSE(autodiff_v.derivative(0u), anchor_v,
2.5e5 * test_constants::pct_epsilon());
}
{
using boost::math::gamma_p_derivative;
auto a_normalized = a_sampler.normalize(a_sampler.next());
auto autodiff_v = gamma_p_derivative(make_fvar<T, m>(a_normalized),
make_fvar<T, m>(z_normalized));
auto anchor_v = gamma_p_derivative(a_normalized, z_normalized);
BOOST_CHECK_CLOSE(autodiff_v.derivative(0u), anchor_v,
2.5e5 * test_constants::pct_epsilon());
}
}
}
// Requires pow(complex<autodiff_fvar<T,m>>, T)
/* BOOST_AUTO_TEST_CASE_TEMPLATE(hankel_hpp, T, all_float_types) {
using test_constants = test_constants_t<T>;
static constexpr auto m = test_constants::order;
test_detail::RandomSample<T> v_sampler{-200, 200};
test_detail::RandomSample<T> x_sampler{-200, 200};
for (auto i : boost::irange(test_constants::n_samples)) {
std::ignore = i;
auto v = v_sampler.next();
auto x = x_sampler.next();
try {
auto autodiff_v = boost::math::cyl_hankel_1(make_fvar<T,m>(v),
make_fvar<T,m>(x)); auto anchor_v = boost::math::cyl_hankel_1(v, x);
BOOST_CHECK_CLOSE(autodiff_v.real(), anchor_v.real(),
test_constants::pct_epsilon());
BOOST_CHECK_CLOSE(autodiff_v.imag(), anchor_v.imag(),
test_constants::pct_epsilon());
} catch (const std::domain_error &) {
BOOST_CHECK_THROW(boost::math::cyl_hankel_1(make_fvar<T,m>(v),
make_fvar<T,m>(x)), boost::wrapexcept<std::domain_error>);
BOOST_CHECK_THROW(boost::math::cyl_hankel_1(v, x),
boost::wrapexcept<std::domain_error>); } catch (const std::overflow_error &) {
BOOST_CHECK_THROW(boost::math::cyl_hankel_1(make_fvar<T,m>(v),
make_fvar<T,m>(x)), boost::wrapexcept<std::overflow_error>);
BOOST_CHECK_THROW(boost::math::cyl_hankel_1(v, x),
boost::wrapexcept<std::overflow_error>); } catch (...) { std::cout <<
std::setprecision(20) << "Input: x: " << x<< " max: "<<
std::numeric_limits<T>::max() << std::endl;
std::rethrow_exception(std::exception_ptr(std::current_exception()));
}
try {
auto autodiff_v = boost::math::cyl_hankel_2(make_fvar<T,m>(v),
make_fvar<T,m>(x)); auto anchor_v = boost::math::cyl_hankel_2(v, x);
BOOST_CHECK_CLOSE(autodiff_v.real(), anchor_v.real(),
test_constants::pct_epsilon());
BOOST_CHECK_CLOSE(autodiff_v.imag(), anchor_v.imag(),
test_constants::pct_epsilon());
} catch (const std::domain_error &) {
BOOST_CHECK_THROW(boost::math::cyl_hankel_2(make_fvar<T,m>(v),
make_fvar<T,m>(x)), boost::wrapexcept<std::domain_error>);
BOOST_CHECK_THROW(boost::math::cyl_hankel_2(v, x),
boost::wrapexcept<std::domain_error>); } catch (const std::overflow_error &) {
BOOST_CHECK_THROW(boost::math::cyl_hankel_2(make_fvar<T,m>(v),
make_fvar<T,m>(x)), boost::wrapexcept<std::overflow_error>);
BOOST_CHECK_THROW(boost::math::cyl_hankel_2(v, x),
boost::wrapexcept<std::overflow_error>); } catch (...) { std::cout <<
std::setprecision(20) << "Input: x: " << x<< " max: "<<
std::numeric_limits<T>::max() << std::endl;
std::rethrow_exception(std::exception_ptr(std::current_exception()));
}
try {
auto autodiff_v = boost::math::sph_hankel_1(make_fvar<T,m>(v),
make_fvar<T,m>(x)); auto anchor_v = boost::math::sph_hankel_1(v, x);
BOOST_CHECK_CLOSE(autodiff_v.derivative(0u), anchor_v,
test_constants::pct_epsilon());
} catch (const std::domain_error &) {
BOOST_CHECK_THROW(boost::math::sph_hankel_1(make_fvar<T,m>(v),
make_fvar<T,m>(x)), boost::wrapexcept<std::domain_error>);
BOOST_CHECK_THROW(boost::math::sph_hankel_1(v, x),
boost::wrapexcept<std::domain_error>); } catch (const std::overflow_error &) {
BOOST_CHECK_THROW(boost::math::sph_hankel_1(make_fvar<T,m>(v),
make_fvar<T,m>(x)), boost::wrapexcept<std::overflow_error>);
BOOST_CHECK_THROW(boost::math::sph_hankel_1(v, x),
boost::wrapexcept<std::overflow_error>); } catch (...) { std::cout <<
std::setprecision(20) << "Input: x: " << x<< " max: "<<
std::numeric_limits<T>::max() << std::endl;
std::rethrow_exception(std::exception_ptr(std::current_exception()));
}
try {
auto autodiff_v = boost::math::sph_hankel_2(make_fvar<T,m>(v),
make_fvar<T,m>(x)); auto anchor_v = boost::math::sph_hankel_2(v, x);
BOOST_CHECK_CLOSE(autodiff_v.derivative(0u), anchor_v,
test_constants::pct_epsilon());
} catch (const std::domain_error &) {
BOOST_CHECK_THROW(boost::math::sph_hankel_2(make_fvar<T,m>(v),
make_fvar<T,m>(x)), boost::wrapexcept<std::domain_error>);
BOOST_CHECK_THROW(boost::math::sph_hankel_2(v, x),
boost::wrapexcept<std::domain_error>); } catch (const std::overflow_error &) {
BOOST_CHECK_THROW(boost::math::sph_hankel_2(make_fvar<T,m>(v),
make_fvar<T,m>(x)), boost::wrapexcept<std::overflow_error>);
BOOST_CHECK_THROW(boost::math::sph_hankel_2(v, x),
boost::wrapexcept<std::overflow_error>); } catch (...) { std::cout <<
std::setprecision(20) << "Input: x: " << x<< " max: "<<
std::numeric_limits<T>::max() << std::endl;
std::rethrow_exception(std::exception_ptr(std::current_exception()));
}
}
} */
BOOST_AUTO_TEST_SUITE_END()