2
0
mirror of https://github.com/boostorg/math.git synced 2026-01-19 04:22:09 +00:00

fixed failining tests and added test support to jamfile

This commit is contained in:
mzhelyez
2025-08-16 14:51:00 +02:00
parent bacc88b309
commit 0f26461e59
17 changed files with 395 additions and 112 deletions

View File

@@ -0,0 +1,149 @@
#include <boost/math/differentiation/autodiff_reverse.hpp>
using namespace boost::math::differentiation::reverse_mode;
using namespace boost::math::constants;
template<typename X>
X phi(X const& x)
{
return one_div_root_two_pi<double>() * exp(-0.5 * x * x);
}
template<typename X>
X Phi(X const& x)
{
return 0.5 * erfc(-one_div_root_two<double>() * x);
}
enum class CP { call, put };
template<typename T>
T black_scholes_option_price(CP cp, double K, T const& S, T const& sigma, T const& tau, T const& r)
{
using namespace std;
auto const d1 = (log(S / K) + (r + sigma * sigma / 2) * tau) / (sigma * sqrt(tau));
auto const d2 = (log(S / K) + (r - sigma * sigma / 2) * tau) / (sigma * sqrt(tau));
switch (cp) {
case CP::call:
return S * Phi<T>(d1) - exp(-r * tau) * K * Phi<T>(d2);
case CP::put:
return exp(-r * tau) * K * Phi<T>(-d2) - S * Phi<T>(-d1);
default:
throw std::runtime_error("Invalid CP value.");
}
}
int main()
{
double const K = 100.0;
double S_val = 105.0;
double sigma_val = 5.0;
double tau_val = 30.0 / 365;
double r_val = 1.25 / 100;
rvar<double, 3> S = make_rvar<double, 3>(S_val);
rvar<double, 3> sigma = make_rvar<double, 3>(sigma_val);
rvar<double, 3> tau = make_rvar<double, 3>(tau_val);
rvar<double, 3> r = make_rvar<double, 3>(r_val);
rvar<double, 3> call_price
= black_scholes_option_price<rvar<double, 3>>(CP::call, K, S, sigma, tau, r);
rvar<double, 3> put_price
= black_scholes_option_price<rvar<double, 3>>(CP::put, K, S, sigma, tau, r);
double const d1 = ((log(S_val / K) + (r_val + sigma_val * sigma_val / 2) * tau_val)
/ (sigma_val * sqrt(tau_val)));
double const d2 = ((log(S_val / K) + (r_val - sigma_val * sigma_val / 2) * tau_val)
/ (sigma_val * sqrt(tau_val)));
double const formula_call_delta = +Phi(+d1);
double const formula_put_delta = -Phi(-d1);
double const formula_vega = (S_val * phi(d1) * sqrt(tau_val));
double const formula_call_theta = (-S_val * phi(d1) * sigma_val / (2 * sqrt(tau_val))
- r_val * K * exp(-r_val * tau_val) * Phi(+d2));
double const formula_put_theta = (-S_val * phi(d1) * sigma_val / (2 * sqrt(tau_val))
+ r_val * K * exp(-r_val * tau_val) * Phi(-d2));
double const formula_call_rho = (+K * tau_val * exp(-r_val * tau_val) * Phi(+d2));
double const formula_put_rho = (-K * tau_val * exp(-r_val * tau_val) * Phi(-d2));
double const formula_gamma = (phi(d1) / (S_val * sigma_val * sqrt(tau_val)));
double const formula_vanna = (-phi(d1) * d2 / sigma_val);
double const formula_charm = (phi(d1) * (d2 * sigma_val * sqrt(tau_val) - 2 * r_val * tau_val)
/ (2 * tau_val * sigma_val * sqrt(tau_val)));
double const formula_vomma = (S_val * phi(d1) * sqrt(tau_val) * d1 * d2 / sigma_val);
double const formula_veta = (-S_val * phi(d1) * sqrt(tau_val)
* (r_val * d1 / (sigma_val * sqrt(tau_val))
- (1 + d1 * d2) / (2 * tau_val)));
double const formula_speed = (-phi(d1) * (d1 / (sigma_val * sqrt(tau_val)) + 1)
/ (S_val * S_val * sigma_val * sqrt(tau_val)));
double const formula_zomma = (phi(d1) * (d1 * d2 - 1)
/ (S_val * sigma_val * sigma_val * sqrt(tau_val)));
double const formula_color = (-phi(d1) / (2 * S_val * tau_val * sigma_val * sqrt(tau_val))
* (1
+ (2 * r_val * tau_val - d2 * sigma_val * sqrt(tau_val)) * d1
/ (sigma_val * sqrt(tau_val))));
double const formula_ultima = -formula_vega
* ((d1 * d2 * (1 - d1 * d2) + d1 * d1 + d2 * d2)
/ (sigma_val * sigma_val));
auto call_greeks = grad(call_price, &S, &sigma, &tau, &r);
auto put_greeks = grad(put_price, &S, &sigma, &tau, &r);
auto call_greeks_2nd_order = grad_nd<2>(call_price, &S, &sigma, &tau, &r);
auto put_greeks_2nd_order = grad_nd<2>(put_price, &S, &sigma, &tau, &r);
auto call_greeks_3rd_order = grad_nd<3>(call_price, &S, &sigma, &tau, &r);
auto put_greeks_3rd_order = grad_nd<3>(put_price, &S, &sigma, &tau, &r);
std::cout << std::setprecision(std::numeric_limits<double>::digits10)
<< "autodiff black-scholes call price = " << call_price.item() << "\n"
<< "autodiff black-scholes put price = " << put_price.item() << "\n"
<< "\n ## First-order Greeks \n"
<< "autodiff call delta = " << call_greeks[0].item() << "\n"
<< "formula call delta = " << formula_call_delta << "\n"
<< "autodiff call vega = " << call_greeks[1].item() << '\n'
<< " formula call vega = " << formula_vega << '\n'
<< "autodiff call theta = " << call_greeks[2].item() << '\n'
<< " formula call theta = " << formula_call_theta << '\n'
<< "autodiff call rho = " << call_greeks[3].item() << 'n'
<< " formula call rho = " << formula_call_rho << '\n'
<< '\n'
<< "autodiff put delta = " << put_greeks[0].item() << 'n'
<< " formula put delta = " << formula_put_delta << '\n'
<< "autodiff put vega = " << put_greeks[1].item() << '\n'
<< " formula put vega = " << formula_vega << '\n'
<< "autodiff put theta = " << -put_greeks[2].item() << '\n'
<< " formula put theta = " << formula_put_theta << '\n'
<< "autodiff put rho = " << put_greeks[3].item() << '\n'
<< " formula put rho = " << formula_put_rho << '\n'
<< "\n## Second-order Greeks\n"
<< "autodiff call gamma = " << call_greeks_2nd_order[0][0].item() << '\n'
<< "autodiff put gamma = " << put_greeks_2nd_order[0][0].item() << '\n'
<< " formula gamma = " << formula_gamma << '\n'
<< "autodiff call vanna = " << call_greeks_2nd_order[0][1].item() << '\n'
<< "autodiff put vanna = " << put_greeks_2nd_order[0][1].item() << '\n'
<< " formula vanna = " << formula_vanna << '\n'
<< "autodiff call charm = " << -call_greeks_2nd_order[0][2].item() << '\n'
<< "autodiff put charm = " << -put_greeks_2nd_order[0][2].item() << '\n'
<< " formula charm = " << formula_charm << '\n'
<< "autodiff call vomma = " << call_greeks_2nd_order[1][1].item() << '\n'
<< "autodiff put vomma = " << put_greeks_2nd_order[1][1].item() << '\n'
<< " formula vomma = " << formula_vomma << '\n'
<< "autodiff call veta = " << call_greeks_2nd_order[1][2].item() << '\n'
<< "autodiff put veta = " << put_greeks_2nd_order[1][2].item() << '\n'
<< " formula veta = " << formula_veta << '\n'
<< "\n## Third-order Greeks\n"
<< "autodiff call speed = " << call_greeks_3rd_order[0][0][0] << '\n'
<< "autodiff put speed = " << put_greeks_3rd_order[0][0][0] << '\n'
<< " formula speed = " << formula_speed << '\n'
<< "autodiff call zomma = " << call_greeks_3rd_order[0][0][1] << '\n'
<< "autodiff put zomma = " << put_greeks_3rd_order[0][0][1] << '\n'
<< " formula zomma = " << formula_zomma << '\n'
<< "autodiff call color = " << call_greeks_3rd_order[0][0][2] << '\n'
<< "autodiff put color = " << put_greeks_3rd_order[0][0][2] << '\n'
<< " formula color = " << formula_color << '\n'
<< "autodiff call ultima = " << call_greeks_3rd_order[1][1][1] << '\n'
<< "autodiff put ultima = " << put_greeks_3rd_order[1][1][1] << '\n'
<< " formula ultima = " << formula_ultima << '\n';
return 0;
}

View File

@@ -27,36 +27,38 @@ set(HEADERS
${CMAKE_SOURCE_DIR}/detail/reverse_mode_autodiff_expression_template_base.hpp
${CMAKE_SOURCE_DIR}/detail/reverse_mode_autodiff_utilities.hpp
${CMAKE_SOURCE_DIR}/detail/reverse_mode_autodiff_erf_overloads.hpp
${CMAKE_SOURCE_DIR}/detail/reverse_mode_autodiff_comparison_operator_overloads.hpp
${BOOST_MATH_TEST_DIRECTORY}test_autodiff_reverse.hpp
)
set(TEST_MEMORY_ALLOCATORS
${BOOST_MATH_TEST_DIRECTORY}test_autodiff_reverse_flat_linear_allocator.cpp
${BOOST_MATH_TEST_DIRECTORY}test_reverse_mode_autodiff_flat_linear_allocator.cpp
)
set(TEST_CONSTRUCTORS
${BOOST_MATH_TEST_DIRECTORY}test_rvar_constructors.cpp
${BOOST_MATH_TEST_DIRECTORY}test_reverse_mode_autodiff_constructors.cpp
)
set(TEST_COMPARISON_OPS
${BOOST_MATH_TEST_DIRECTORY}test_comparison_operators.cpp
${BOOST_MATH_TEST_DIRECTORY}test_reverse_mode_autodiff_comparison_operators.cpp
)
set(TEST_STL_SUPPORT
${BOOST_MATH_TEST_DIRECTORY}test_stl_support.cpp
${BOOST_MATH_TEST_DIRECTORY}test_reverse_mode_autodiff_stl_support.cpp
)
SET(TEST_BASIC_OPS ${BOOST_MATH_TEST_DIRECTORY}test_autodiff_basic_math_ops.cpp)
SET(TEST_BASIC_OPS ${BOOST_MATH_TEST_DIRECTORY}test_reverse_mode_autodiff_basic_math_ops.cpp)
SET(TEST_ADDITIONAL_BOOST_FUNCTIONS ${BOOST_MATH_TEST_DIRECTORY}test_autodiff_reverse_additional_boost_functions.cpp)
SET(LINEAR_REGRESSION_EXAMPLE ${BOOST_MATH_EXAMPLE_DIRECTORY}/reverse_mode_linear_regression_example.cpp)
set(TEST_ERF ${BOOST_MATH_TEST_DIRECTORY}/test_reverse_mode_autodiff_error_functions.cpp)
set(BLACK_SCHOLES_EXAMPLE ${BOOST_MATH_EXAMPLE_DIRECTORY}/autodiff_reverse_black_scholes.cpp)
# add_executable(autodiff_reverse_tests ${TEST_CONSTRUCTORS} ${HEADERS})
# add_executable(autodiff_reverse_tests ${TEST_MEMORY_ALLOCATORS} ${HEADERS})
# add_executable(autodiff_reverse_tests ${TEST_BASIC_OPS} ${HEADERS})
# add_executable(autodiff_reverse_tests ${TEST_COMPARISON_OPS} ${HEADERS}
# detail/reverse_mode_autodiff_comparison_operator_overloads.hpp)
# add_executable(autodiff_reverse_tests ${TEST_STL_SUPPORT} ${HEADERS})
# add_executable(autodiff_reverse_tests ${TEST_COMPARISON_OPS} ${HEADERS})
add_executable(autodiff_reverse_tests ${TEST_STL_SUPPORT} ${HEADERS})
# add_executable(autodiff_reverse_tests ${LINEAR_REGRESSION_EXAMPLE} ${HEADERS})
add_executable(autodiff_reverse_tests ${TEST_ERF} ${HEADERS})
# add_executable(autodiff_reverse_tests ${TEST_ERF} ${HEADERS})
# add_executable(autodiff_reverse_tests ${BLACK_SCHOLES_EXAMPLE} ${HEADERS})

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 13.0.0, 2025-08-14T12:58:05. -->
<!-- Written by QtCreator 13.0.0, 2025-08-16T11:15:54. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>

View File

@@ -9,7 +9,6 @@
#include <boost/math/differentiation/detail/reverse_mode_autodiff_expression_template_base.hpp>
#include <boost/math/differentiation/detail/reverse_mode_autodiff_memory_management.hpp>
#include <boost/math/differentiation/detail/reverse_mode_autodiff_stl_overloads.hpp>
#include <boost/math/special_functions/acosh.hpp>
#include <boost/math/special_functions/asinh.hpp>
#include <boost/math/special_functions/atanh.hpp>
@@ -567,6 +566,22 @@ namespace detail {
template<typename T, size_t order>
struct grad_op_impl
{
std::vector<rvar<T, order - 1>> operator()(rvar<T, order> &f, std::vector<rvar<T, order> *> &x)
{
auto &tape = get_active_tape<T, order>();
tape.zero_grad();
f.backward();
std::vector<rvar<T, order - 1>> gradient_vector;
gradient_vector.reserve(x.size());
for (auto xi : x) {
// make a new rvar<T,order-1> holding the adjoint value
gradient_vector.emplace_back(xi->adjoint());
}
return gradient_vector;
}
/*
std::vector<rvar_t<T, order - 1> *> operator()(rvar<T, order> &f,
std::vector<rvar<T, order> *> &x)
{
@@ -578,7 +593,7 @@ struct grad_op_impl
gradient_vector.push_back(&(xi->adjoint()));
}
return gradient_vector;
}
}*/
};
/** @brief helper overload for grad implementation.
* @return vector<T> of gradients of the autodiff graph.
@@ -607,6 +622,22 @@ struct grad_op_impl<T, 1>
template<size_t N, typename T, size_t order_1, size_t order_2, typename Enable = void>
struct grad_nd_impl
{
auto operator()(rvar<T, order_1> &f, std::vector<rvar<T, order_2> *> &x)
{
static_assert(N > 1, "N must be greater than 1 for this template");
auto current_grad = grad(f, x); // vector<rvar<T,order_1-1>> or vector<T>
std::vector<decltype(grad_nd_impl<N - 1, T, order_1 - 1, order_2>()(current_grad[0], x))>
result;
result.reserve(current_grad.size());
for (auto &g_i : current_grad) {
result.push_back(grad_nd_impl<N - 1, T, order_1 - 1, order_2>()(g_i, x));
}
return result;
}
/*
auto operator()(rvar<T, order_1> &f, std::vector<rvar<T, order_2> *> &x)
{
static_assert(N > 1, "N must be greater than 1 for this template");
@@ -617,7 +648,7 @@ struct grad_nd_impl
result.push_back(grad_nd_impl<N - 1, T, order_1 - 1, order_2>()(*g_i, x));
}
return result;
}
}*/
};
/** @brief spcialization for order = 1,
* @return vector<rvar<T,order_1-1>> gradients */

View File

@@ -219,7 +219,7 @@ template<typename U,
typename T,
size_t order,
typename ARG,
typename = typename std::enable_if<std::is_arithmetic<U>::value>::type>
typename = typename std::enable_if<!detail::is_expression<U>::value>::type>
mult_const_expr<T, order, ARG> operator*(const expression<T, order, ARG> &arg, const U &v)
{
return mult_const_expr<T, order, ARG>(arg, static_cast<T>(v));
@@ -228,7 +228,7 @@ template<typename U,
typename T,
size_t order,
typename ARG,
typename = typename std::enable_if<std::is_arithmetic<U>::value>::type>
typename = typename std::enable_if<!detail::is_expression<U>::value>::type>
mult_const_expr<T, order, ARG> operator*(const U &v, const expression<T, order, ARG> &arg)
{
return mult_const_expr<T, order, ARG>(arg, static_cast<T>(v));
@@ -245,7 +245,7 @@ template<typename U,
typename T,
size_t order,
typename ARG,
typename = typename std::enable_if<std::is_arithmetic<U>::value>::type>
typename = typename std::enable_if<!detail::is_expression<U>::value>::type>
add_const_expr<T, order, ARG> operator+(const expression<T, order, ARG> &arg, const U &v)
{
return add_const_expr<T, order, ARG>(arg, static_cast<T>(v));
@@ -254,7 +254,7 @@ template<typename U,
typename T,
size_t order,
typename ARG,
typename = typename std::enable_if<std::is_arithmetic<U>::value>::type>
typename = typename std::enable_if<!detail::is_expression<U>::value>::type>
add_const_expr<T, order, ARG> operator+(const U &v, const expression<T, order, ARG> &arg)
{
return add_const_expr<T, order, ARG>(arg, static_cast<T>(v));
@@ -284,7 +284,7 @@ template<typename U,
typename T,
size_t order,
typename ARG,
typename = typename std::enable_if<std::is_arithmetic<U>::value>::type>
typename = typename std::enable_if<!detail::is_expression<U>::value>::type>
add_const_expr<T, order, ARG> operator-(const expression<T, order, ARG> &arg, const U &v)
{
/* rvar - float = rvar + (-float) */
@@ -299,7 +299,7 @@ template<typename U,
typename T,
size_t order,
typename ARG,
typename = typename std::enable_if<std::is_arithmetic<U>::value>::type>
typename = typename std::enable_if<!detail::is_expression<U>::value>::type>
auto operator-(const U &v, const expression<T, order, ARG> &arg)
{
auto neg = -arg;
@@ -318,7 +318,7 @@ template<typename U,
typename T,
size_t order,
typename ARG,
typename = typename std::enable_if<std::is_arithmetic<U>::value>::type>
typename = typename std::enable_if<!detail::is_expression<U>::value>::type>
const_div_by_expr<T, order, ARG> operator/(const U &v, const expression<T, order, ARG> &arg)
{
return const_div_by_expr<T, order, ARG>(arg, static_cast<T>(v));
@@ -328,7 +328,7 @@ template<typename U,
typename T,
size_t order,
typename ARG,
typename = typename std::enable_if<std::is_arithmetic<U>::value>::type>
typename = typename std::enable_if<!detail::is_expression<U>::value>::type>
div_by_const_expr<T, order, ARG> operator/(const expression<T, order, ARG> &arg, const U &v)
{
return div_by_const_expr<T, order, ARG>(arg, static_cast<T>(v));

View File

@@ -1,6 +1,5 @@
#ifndef REVERSE_MODE_AUTODIFF_COMPARISON_OPERATOR_OVERLOADS_HPP
#define REVERSE_MODE_AUTODIFF_COMPARISON_OPERATOR_OVERLOADS_HPP
#include <boost/math/differentiation/detail/reverse_mode_autodiff_expression_template_base.hpp>
namespace boost {
namespace math {
@@ -16,7 +15,7 @@ template<typename U,
typename T,
size_t order,
class E,
typename = typename std::enable_if<std::is_arithmetic<U>::value>::type>
typename = typename std::enable_if<!detail::is_expression<U>::value>::type>
bool operator==(const expression<T, order, E> &lhs, const U &rhs)
{
return lhs.evaluate() == static_cast<T>(rhs);
@@ -25,7 +24,7 @@ template<typename U,
typename T,
size_t order,
class E,
typename = typename std::enable_if<std::is_arithmetic<U>::value>::type>
typename = typename std::enable_if<!detail::is_expression<U>::value>::type>
bool operator==(const U &lhs, const expression<T, order, E> &rhs)
{
return lhs == rhs.evaluate();
@@ -40,7 +39,7 @@ template<typename U,
typename T,
size_t order,
class E,
typename = typename std::enable_if<std::is_arithmetic<U>::value>::type>
typename = typename std::enable_if<!detail::is_expression<U>::value>::type>
bool operator!=(const expression<T, order, E> &lhs, const U &rhs)
{
return lhs.evaluate() != rhs;
@@ -49,7 +48,7 @@ template<typename U,
typename T,
size_t order,
class E,
typename = typename std::enable_if<std::is_arithmetic<U>::value>::type>
typename = typename std::enable_if<!detail::is_expression<U>::value>::type>
bool operator!=(const U &lhs, const expression<T, order, E> &rhs)
{
return lhs != rhs.evaluate();
@@ -64,7 +63,7 @@ template<typename U,
typename T,
size_t order,
class E,
typename = typename std::enable_if<std::is_arithmetic<U>::value>::type>
typename = typename std::enable_if<!detail::is_expression<U>::value>::type>
bool operator<(const expression<T, order, E> &lhs, const U &rhs)
{
return lhs.evaluate() < rhs;
@@ -73,7 +72,7 @@ template<typename U,
typename T,
size_t order,
class E,
typename = typename std::enable_if<std::is_arithmetic<U>::value>::type>
typename = typename std::enable_if<!detail::is_expression<U>::value>::type>
bool operator<(const U &lhs, const expression<T, order, E> &rhs)
{
return lhs < rhs.evaluate();
@@ -88,7 +87,7 @@ template<typename U,
typename T,
size_t order,
class E,
typename = typename std::enable_if<std::is_arithmetic<U>::value>::type>
typename = typename std::enable_if<!detail::is_expression<U>::value>::type>
bool operator>(const expression<T, order, E> &lhs, const U &rhs)
{
return lhs.evaluate() > rhs;
@@ -97,7 +96,7 @@ template<typename U,
typename T,
size_t order,
class E,
typename = typename std::enable_if<std::is_arithmetic<U>::value>::type>
typename = typename std::enable_if<!detail::is_expression<U>::value>::type>
bool operator>(const U &lhs, const expression<T, order, E> &rhs)
{
return lhs > rhs.evaluate();
@@ -112,7 +111,7 @@ template<typename U,
typename T,
size_t order,
class E,
typename = typename std::enable_if<std::is_arithmetic<U>::value>::type>
typename = typename std::enable_if<!detail::is_expression<U>::value>::type>
bool operator<=(const expression<T, order, E> &lhs, const U &rhs)
{
return lhs.evaluate() <= rhs;
@@ -121,7 +120,7 @@ template<typename U,
typename T,
size_t order,
class E,
typename = typename std::enable_if<std::is_arithmetic<U>::value>::type>
typename = typename std::enable_if<!detail::is_expression<U>::value>::type>
bool operator<=(const U &lhs, const expression<T, order, E> &rhs)
{
return lhs <= rhs.evaluate();
@@ -136,7 +135,7 @@ template<typename U,
typename T,
size_t order,
class E,
typename = typename std::enable_if<std::is_arithmetic<U>::value>::type>
typename = typename std::enable_if<!detail::is_expression<U>::value>::type>
bool operator>=(const expression<T, order, E> &lhs, const U &rhs)
{
return lhs.evaluate() >= rhs;
@@ -145,7 +144,7 @@ template<typename U,
typename T,
size_t order,
class E,
typename = typename std::enable_if<std::is_arithmetic<U>::value>::type>
typename = typename std::enable_if<!detail::is_expression<U>::value>::type>
bool operator>=(const U &lhs, const expression<T, order, E> &rhs)
{
return lhs >= rhs.evaluate();

View File

@@ -6,7 +6,7 @@
#include <boost/math/differentiation/detail/reverse_mode_autodiff_stl_overloads.hpp>
#include <boost/math/differentiation/detail/reverse_mode_autodiff_utilities.hpp>
#include <boost/math/special_functions/erf.hpp>
#include <boost/multiprecision/cpp_bin_float.hpp>
namespace boost {
namespace math {
namespace differentiation {
@@ -72,8 +72,10 @@ struct erf_expr : public abstract_unary_expression<T, order, ARG, erf_expr<T, or
}
static const inner_t derivative(const inner_t &argv, const inner_t &v, const T &constant)
{
using multiprecision::sqrt;
using std::exp;
return 2 * exp(-argv * argv) / std::sqrt(constants::pi<T>());
using std::sqrt;
return 2 * exp(-argv * argv) / sqrt(constants::pi<T>());
}
};
@@ -101,8 +103,10 @@ struct erfc_expr : public abstract_unary_expression<T, order, ARG, erfc_expr<T,
}
static const inner_t derivative(const inner_t &argv, const inner_t &v, const T &constant)
{
using multiprecision::sqrt;
using std::exp;
return -2 * exp(-argv * argv) / std::sqrt(constants::pi<T>());
using std::sqrt;
return -2 * exp(-argv * argv) / sqrt(constants::pi<T>());
}
};
@@ -130,14 +134,19 @@ struct erf_inv_expr : public abstract_unary_expression<T, order, ARG, erf_inv_ex
}
static const inner_t derivative(const inner_t &argv, const inner_t &v, const T &constant)
{
using multiprecision::exp;
using multiprecision::pow;
using multiprecision::sqrt;
using std::exp;
using std::pow;
using std::sqrt;
return detail::if_functional_dispatch<(order > 1)>(
[](auto &&x) {
return 0.5 * std::sqrt(constants::pi<T>())
return 0.5 * sqrt(constants::pi<T>())
* reverse_mode::exp(reverse_mode::pow(reverse_mode::erf_inv(x), 2.0));
},
[](auto &&x) {
return 0.5 * std::sqrt(constants::pi<T>())
* std::exp(std::pow(boost::math::erf_inv(x), 2));
return 0.5 * sqrt(constants::pi<T>()) * exp(pow(boost::math::erf_inv(x), 2));
},
argv);
}
@@ -167,14 +176,19 @@ struct erfc_inv_expr : public abstract_unary_expression<T, order, ARG, erfc_inv_
}
static const inner_t derivative(const inner_t &argv, const inner_t &v, const T &constant)
{
using multiprecision::exp;
using multiprecision::pow;
using multiprecision::sqrt;
using std::exp;
using std::pow;
using std::sqrt;
return detail::if_functional_dispatch<(order > 1)>(
[](auto &&x) {
return -0.5 * std::sqrt(constants::pi<T>())
return -0.5 * sqrt(constants::pi<T>())
* reverse_mode::exp(reverse_mode::pow(reverse_mode::erfc_inv(x), 2.0));
},
[](auto &&x) {
return -0.5 * std::sqrt(constants::pi<T>())
* std::exp(std::pow(boost::math::erfc_inv(x), 2));
return -0.5 * sqrt(constants::pi<T>()) * exp(pow(boost::math::erfc_inv(x), 2));
},
argv);
}

View File

@@ -8,6 +8,9 @@ namespace differentiation {
namespace reverse_mode {
/* forward declarations for utitlity functions */
struct expression_base
{};
template<typename T, size_t order, class derived_expression>
struct expression;
@@ -82,14 +85,7 @@ template<typename T, size_t order>
constexpr std::size_t count_rvars = detail::count_rvar_impl<T, order>::value;
template<typename T>
struct is_expression : std::false_type
{};
template<typename T, size_t order, typename Derived>
struct is_expression<expression<T, order, Derived>> : std::true_type
{};
template<typename T, size_t order>
struct is_expression<rvar<T, order>> : std::true_type
struct is_expression : std::is_base_of<expression_base, typename std::decay<T>::type>
{};
template<typename T, size_t N>
@@ -109,9 +105,6 @@ struct rvar_type_impl<T, 0>
template<typename T, size_t N>
using rvar_t = typename detail::rvar_type_impl<T, N>::type;
struct expression_base
{};
template<typename T, size_t order, class derived_expression>
struct expression : expression_base
{

View File

@@ -32,10 +32,10 @@ public:
using difference_type = ptrdiff_t;
private:
size_t begin_ = 0;
size_t index_ = 0;
size_t end_ = 0;
const allocator_type *storage_ = nullptr;
size_t index_ = 0;
size_t begin_ = 0;
size_t end_ = 0;
public:
flat_linear_allocator_iterator() = default;

View File

@@ -119,6 +119,7 @@ struct trunc_expr : public abstract_unary_expression<T, order, ARG, trunc_expr<T
inner_t evaluate() const
{
using boost::math::trunc;
using std::trunc;
return trunc(this->arg.evaluate());
}
@@ -718,6 +719,89 @@ struct atanh_expr : public abstract_unary_expression<T, order, ARG, atanh_expr<T
return 1.0 / (1 - argv * argv);
}
};
template<typename T, size_t order, typename LHS, typename RHS>
struct fmod_expr
: public abstract_binary_expression<T, order, LHS, RHS, fmod_expr<T, order, LHS, RHS>>
{
/** @brief
* */
using lhs_type = LHS;
using rhs_type = RHS;
using value_type = T;
using inner_t = rvar_t<T, order - 1>;
// Explicitly define constructor to forward to base class
explicit fmod_expr(const expression<T, order, LHS> &left_hand_expr,
const expression<T, order, RHS> &right_hand_expr)
: abstract_binary_expression<T, order, LHS, RHS, fmod_expr<T, order, LHS, RHS>>(
left_hand_expr, right_hand_expr)
{}
inner_t evaluate() const
{
using std::fmod;
return fmod(this->lhs.evaluate(), this->rhs.evaluate());
};
static const inner_t left_derivative(const inner_t &l, const inner_t &r, const inner_t &v)
{
return inner_t{1.0};
};
static const inner_t right_derivative(const inner_t &l, const inner_t &r, const inner_t &v)
{
using std::trunc;
return -1.0 * trunc(l / r);
};
};
template<typename T, size_t order, typename ARG>
struct fmod_left_float_expr
: public abstract_unary_expression<T, order, ARG, fmod_left_float_expr<T, order, ARG>>
{
/** @brief
* */
using arg_type = ARG;
using value_type = T;
using inner_t = rvar_t<T, order - 1>;
explicit fmod_left_float_expr(const expression<T, order, ARG> &arg_expr, const T v)
: abstract_unary_expression<T, order, ARG, fmod_left_float_expr<T, order, ARG>>(arg_expr,
v){};
inner_t evaluate() const
{
using std::fmod;
return fmod(this->constant, this->arg.evaluate());
}
static const inner_t derivative(const inner_t &argv, const inner_t &v, const T &constant)
{
return -1.0 * trunc(constant / argv);
}
};
template<typename T, size_t order, typename ARG>
struct fmod_right_float_expr
: public abstract_unary_expression<T, order, ARG, fmod_right_float_expr<T, order, ARG>>
{
/** @brief
* */
using arg_type = ARG;
using value_type = T;
using inner_t = rvar_t<T, order - 1>;
explicit fmod_right_float_expr(const expression<T, order, ARG> &arg_expr, const T v)
: abstract_unary_expression<T, order, ARG, fmod_right_float_expr<T, order, ARG>>(arg_expr,
v){};
inner_t evaluate() const
{
using std::fmod;
return fmod(this->arg.evaluate(), this->constant);
}
static const inner_t derivative(const inner_t &argv, const inner_t &v, const T &constant)
{
return inner_t{1.0};
}
};
/**************************************************************************************************/
template<typename T, size_t order, typename ARG>
fabs_expr<T, order, ARG> fabs(const expression<T, order, ARG> &arg)
{
@@ -756,7 +840,7 @@ template<typename U,
typename T,
size_t order,
typename ARG,
typename = typename std::enable_if<std::is_arithmetic<U>::value>::type>
typename = typename std::enable_if<!detail::is_expression<U>::value>::type>
expr_pow_float_expr<T, order, ARG> pow(const expression<T, order, ARG> &arg, const U &v)
{
return expr_pow_float_expr<T, order, ARG>(arg, static_cast<T>(v));
@@ -785,7 +869,7 @@ auto frexp(const expression<T, order, ARG> &arg, int *i)
{
using std::frexp;
using std::pow;
T tmp = frexp(arg.evaluate(), i);
frexp(arg.evaluate(), i);
return arg / pow(2.0, *i);
}
@@ -861,19 +945,22 @@ trunc_expr<T, order, ARG> trunc(const expression<T, order, ARG> &arg)
template<typename T, size_t order, typename LHS, typename RHS>
auto fmod(const expression<T, order, LHS> &lhs, const expression<T, order, RHS> &rhs)
{
return lhs - trunc(lhs / rhs) * rhs;
//return lhs - trunc(lhs / rhs) * rhs;
return fmod_expr<T, order, LHS, RHS>(lhs, rhs);
}
template<typename T, size_t order, typename ARG>
auto fmod(const expression<T, order, ARG> &lhs, const T rhs)
{
return lhs - trunc(lhs / rhs) * rhs;
//return lhs - trunc(lhs / rhs) * rhs;
return fmod_right_float_expr<T, order, ARG>(lhs, rhs);
}
template<typename T, size_t order, typename ARG>
auto fmod(const T lhs, const expression<T, order, ARG> &rhs)
{
return lhs - trunc(lhs / rhs) * rhs;
//return lhs - trunc(lhs / rhs) * rhs;
return fmod_left_float_expr<T, order, ARG>(rhs, lhs);
}
template<typename T, size_t order, typename ARG>

View File

@@ -1382,11 +1382,19 @@ test-suite long-running-tests :
[ run test_pFq_precision.cpp ../tools//mpfr ../tools//gmp /boost/test//boost_unit_test_framework /boost/system//boost_system /boost/chrono//boost_chrono : : : [ check-target-builds ../config//has_mpfr : : <build>no ] [ requires cxx11_hdr_initializer_list cxx11_auto_declarations cxx11_lambdas cxx11_unified_initialization_syntax cxx11_smart_ptr ] release <toolset>clang:<cxxflags>-Wno-literal-range ]
[ run test_constant_generate.cpp : : : release <define>USE_CPP_FLOAT=1 <exception-handling>off:<build>no ]
;
build-project ../example ;
# Expect policy_ref_snips13 to fail (message about no Cauchy Mean).
test-suite "test_reverse_mode_autodiff"
:
[ run test_reverse_mode_autodiff_flat_linear_allocator.cpp ]
[ run test_reverse_mode_autodiff_constructors.cpp ]
[ run test_reverse_mode_autodiff_comparison_operators.cpp ]
[ run test_reverse_mode_autodiff_stl_support.cpp ]
[ run test_reverse_mode_autodiff_basic_math_ops.cpp ]
[ run test_reverse_mode_autodiff_error_functions.cpp ]
;
rule get_float128_tests
{
local result ;

View File

@@ -150,9 +150,6 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(division, T, all_float_types)
template<typename T>
T f(T x, T y)
{
//auto z1 = x / (y + x);
//auto z2 = y / (x - y);
//T f = z1 * z2;
return (x * y) / ((x + y) * (x - y));
}
@@ -293,7 +290,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(first_derivative, T, all_float_types)
rvar<T, 1> x_ad = x;
rvar<T, 1> y_ad = y;
T fv = f(x, y);
//T fv = f(x, y);
rvar<T, 1> f_ad = f(x_ad, y_ad);
auto grad_f_analytical = grad_f_a(x, y);
/* intended use case */
@@ -323,7 +320,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(second_derivative_and_hessian, T, all_float_types)
rvar<T, 2> x_ad = x;
rvar<T, 2> y_ad = y;
T fv = f(x, y);
//T fv = f(x, y);
rvar<T, 2> f_ad = f(x_ad, y_ad);
gradient_tape<T, 2, BOOST_MATH_BUFFER_SIZE>& tape = get_active_tape<T, 2>();
tape.zero_grad();
@@ -349,7 +346,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(order_3_der, T, all_float_types)
rvar<T, 3> x_ad = x;
rvar<T, 3> y_ad = y;
T fv = f(x, y);
//T fv = f(x, y);
rvar<T, 3> f_ad = f(x_ad, y_ad);
gradient_tape<T, 3, BOOST_MATH_BUFFER_SIZE>& tape = get_active_tape<T, 3>();
tape.zero_grad();

View File

@@ -171,7 +171,6 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(greater_than_rvar_and_scalar, T, all_float_types)
T a = T(3.14);
T b = T(3.14);
T c = T(2.71);
T d = T(4.0);
rvar<T, 1> var1 = rvar<T, 1>(a);
rvar<T, 2> var2 = rvar<T, 2>(a);
@@ -271,7 +270,6 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(greater_than_or_equal_rvar_and_scalar, T, all_floa
T a = T(3.14);
T b = T(3.14);
T c = T(2.71);
T d = T(4.0);
rvar<T, 1> var1 = rvar<T, 1>(a);
rvar<T, 2> var2 = rvar<T, 2>(a);

View File

@@ -16,7 +16,6 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(rvar_constructors_and_utils, T, all_float_types)
BOOST_CHECK_EQUAL(x_value, x1.evaluate().evaluate());
BOOST_CHECK_EQUAL(x_value, x2.evaluate().evaluate().evaluate());
auto v = x1.item();
/* get item helper */
BOOST_CHECK_EQUAL(x_value, x0.item());
BOOST_CHECK_EQUAL(x_value, x1.item());
@@ -251,8 +250,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(inplace_division, T, all_float_types)
BOOST_AUTO_TEST_CASE_TEMPLATE(test_rvar_ostream_output, T, all_float_types)
{
using namespace rdiff;
rvar<T, 1> x = 2.0;
rvar<T, 1> y = 3.0;
rvar<T, 1> x = T{2.0};
rvar<T, 1> y = T{3.0};
rvar<T, 1> z = x * y;
z.backward();

View File

@@ -26,9 +26,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_erf, T, all_float_types)
auto g4 = grad_nd<4>(y, &x);
BOOST_CHECK_CLOSE(y.item(), answers[0], eps);
BOOST_CHECK_CLOSE(g1[0]->item(), answers[1], eps);
BOOST_CHECK_CLOSE(g2[0][0]->item(), answers[2], eps);
BOOST_CHECK_CLOSE(g3[0][0][0]->item(), answers[3], eps);
BOOST_CHECK_CLOSE(g1[0], answers[1], eps);
BOOST_CHECK_CLOSE(g2[0][0], answers[2], eps);
BOOST_CHECK_CLOSE(g3[0][0][0], answers[3], eps);
BOOST_CHECK_CLOSE(g4[0][0][0][0], answers[4], eps);
}
@@ -52,9 +52,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_erfc, T, all_float_types)
auto g4 = grad_nd<4>(y, &x);
BOOST_CHECK_CLOSE(y.item(), answers[0], eps);
BOOST_CHECK_CLOSE(g1[0]->item(), answers[1], eps);
BOOST_CHECK_CLOSE(g2[0][0]->item(), answers[2], eps);
BOOST_CHECK_CLOSE(g3[0][0][0]->item(), answers[3], eps);
BOOST_CHECK_CLOSE(g1[0], answers[1], eps);
BOOST_CHECK_CLOSE(g2[0][0], answers[2], eps);
BOOST_CHECK_CLOSE(g3[0][0][0], answers[3], eps);
BOOST_CHECK_CLOSE(g4[0][0][0][0], answers[4], eps);
}
@@ -78,9 +78,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_erf_inv, T, all_float_types)
auto g4 = grad_nd<4>(y, &x);
BOOST_CHECK_CLOSE(y.item(), answers[0], eps);
BOOST_CHECK_CLOSE(g1[0]->item(), answers[1], eps);
BOOST_CHECK_CLOSE(g2[0][0]->item(), answers[2], eps);
BOOST_CHECK_CLOSE(g3[0][0][0]->item(), answers[3], eps);
BOOST_CHECK_CLOSE(g1[0], answers[1], eps);
BOOST_CHECK_CLOSE(g2[0][0], answers[2], eps);
BOOST_CHECK_CLOSE(g3[0][0][0], answers[3], eps);
BOOST_CHECK_CLOSE(g4[0][0][0][0], answers[4], eps);
}
BOOST_AUTO_TEST_CASE_TEMPLATE(test_erfc_inv, T, all_float_types)
@@ -102,9 +102,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_erfc_inv, T, all_float_types)
auto g4 = grad_nd<4>(y, &x);
BOOST_CHECK_CLOSE(y.item(), answers[0], eps);
BOOST_CHECK_CLOSE(g1[0]->item(), answers[1], eps);
BOOST_CHECK_CLOSE(g2[0][0]->item(), answers[2], eps);
BOOST_CHECK_CLOSE(g3[0][0][0]->item(), answers[3], eps);
BOOST_CHECK_CLOSE(g1[0], answers[1], eps);
BOOST_CHECK_CLOSE(g2[0][0], answers[2], eps);
BOOST_CHECK_CLOSE(g3[0][0][0], answers[3], eps);
BOOST_CHECK_CLOSE(g4[0][0][0][0], answers[4], eps);
}
BOOST_AUTO_TEST_SUITE_END()

View File

@@ -11,18 +11,19 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(flat_linear_allocator_constructors, T, all_float_t
float_allocator.emplace_back(rng.next());
}
BOOST_CHECK_EQUAL(float_allocator.size(), 2 * buffer_size - buffer_size / 2);
BOOST_CHECK_EQUAL(float_allocator.capacity(), 2 * buffer_size);
BOOST_CHECK_EQUAL(float_allocator.size(),
static_cast<size_t>(2 * buffer_size - buffer_size / 2));
BOOST_CHECK_EQUAL(float_allocator.capacity(), static_cast<size_t>(2 * buffer_size));
float_allocator.clear();
BOOST_CHECK_EQUAL(float_allocator.size(), 0);
BOOST_CHECK_EQUAL(float_allocator.size(), static_cast<size_t>(0));
BOOST_CHECK_EQUAL(float_allocator.capacity(), buffer_size);
for (size_t i = 0; i < 2 * buffer_size - buffer_size / 2; i++) {
float_allocator.emplace_back(rng.next());
}
float_allocator.reset();
BOOST_CHECK_EQUAL(float_allocator.size(), 0);
BOOST_CHECK_EQUAL(float_allocator.size(), static_cast<size_t>(0));
BOOST_CHECK_EQUAL(float_allocator.capacity(), 2 * buffer_size);
for (size_t i = 0; i < 2 * buffer_size - buffer_size / 2; i++) {
@@ -42,20 +43,20 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(flat_linear_allocator_test_emplace, T, all_float_t
rdiff_detail::flat_linear_allocator<T, 16> float_allocator{};
std::vector<T> test_vector;
for (int i = 0; i < 2 * buffer_size - 1; i++) {
for (size_t i = 0; i < 2 * buffer_size - 1; i++) {
test_vector.push_back(rng.next());
float_allocator.emplace_back(test_vector[i]);
}
auto it1 = float_allocator.template emplace_back_n<4>();
for (int i = 0; i < 4; i++) {
for (size_t i = 0; i < 4; i++) {
T literal = rng.next();
test_vector.push_back(literal);
*(it1 + i) = literal;
}
auto it2 = float_allocator.emplace_back_n(buffer_size);
for (int i = 0; i < buffer_size; i++) {
for (size_t i = 0; i < buffer_size; i++) {
T literal = rng.next();
test_vector.push_back(literal);
*(it2 + i) = literal;
@@ -69,7 +70,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(flat_linear_allocator_test_emplace, T, all_float_t
*alloc_it); // should be ok to check floats like this since they are expected to be the same.
}
for (int i = 0; i < test_vector.size(); i++) {
for (size_t i = 0; i < test_vector.size(); i++) {
BOOST_CHECK_EQUAL(test_vector[i], float_allocator[i]); // check random access aswell;
}
@@ -85,7 +86,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(flat_linear_allocator_test_checkpointing, T, all_f
std::vector<T> expected_value_at_checkpoint;
size_t ckp_id = 0;
for (int i = 0; i < 2 * buffer_size; i++) {
for (size_t i = 0; i < 2 * buffer_size; i++) {
T literal = rng.next();
float_allocator.emplace_back(literal);
if (ckp_id < checkpoint_indices.size() && i == checkpoint_indices[ckp_id]) {
@@ -94,7 +95,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(flat_linear_allocator_test_checkpointing, T, all_f
++ckp_id;
}
}
for (int i = 0; i < checkpoint_indices.size(); i++) {
for (size_t i = 0; i < checkpoint_indices.size(); i++) {
auto it = float_allocator.checkpoint_at(i);
BOOST_CHECK_EQUAL(*it, expected_value_at_checkpoint[i]);
}

View File

@@ -1,6 +1,8 @@
#include "test_autodiff_reverse.hpp"
#include <boost/math/tools/workaround.hpp>
#include <cmath>
#include <vector>
BOOST_AUTO_TEST_SUITE(test_stl_supported_functions)
using namespace rdiff;
@@ -263,10 +265,12 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_frexp, T, all_float_types)
tape.zero_grad();
x_func.backward();
int i3, i4;
// int i3, i4;
int i4;
frexp(x_v, &i4);
// T h = 0.001;
// T f1 = frexp(x_v + h, &i3);
T f2 = frexp(x_v, &i4);
// T f2 = frexp(x_v, &i4);
T expected_deriv = 1.0 / pow(2.0, i4);
BOOST_REQUIRE_CLOSE_FRACTION(x_rvar.adjoint(), expected_deriv, boost_close_tol<T>());
@@ -307,7 +311,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_sin, T, all_float_types)
rvar<T, 1> x_func = sin(x_rvar);
BOOST_REQUIRE_CLOSE_FRACTION(x_func.item(), test_func_v, 1 * boost_close_tol<T>());
BOOST_REQUIRE_CLOSE_FRACTION(x_func.item(), test_func_v, 10 * boost_close_tol<T>());
gradient_tape<T, 1>& tape = get_active_tape<T, 1>();
@@ -331,7 +335,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_tan, T, all_float_types)
rvar<T, 1> x_func = tan(x_rvar);
BOOST_REQUIRE_CLOSE_FRACTION(x_func.item(), test_func_v, boost_close_tol<T>());
BOOST_REQUIRE_CLOSE_FRACTION(x_func.item(), test_func_v, 10 * boost_close_tol<T>());
gradient_tape<T, 1>& tape = get_active_tape<T, 1>();
@@ -340,7 +344,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_tan, T, all_float_types)
T expected_deriv = 2 * x_v * 1 / (cos(x_v * x_v) * cos(x_v * x_v));
test_func_2.backward();
BOOST_REQUIRE_CLOSE_FRACTION(x_rvar.adjoint(), expected_deriv, 1 * boost_close_tol<T>());
BOOST_REQUIRE_CLOSE_FRACTION(x_rvar.adjoint(), expected_deriv, 10 * boost_close_tol<T>());
tape.clear();
}
@@ -496,6 +500,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_trunc, T, all_float_types)
BOOST_AUTO_TEST_CASE_TEMPLATE(test_fmod, T, all_float_types)
{
using boost::math::tools::fmod_workaround;
RandomSample<T> rng_x{-1, 1};
RandomSample<T> rng_y{-1, 1};
@@ -505,13 +510,13 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_fmod, T, all_float_types)
y_v = rng_y.next();
}
T expected_fmod = fmod(x_v, y_v);
T expected_fmod = fmod(x_v, y_v);
rvar<T, 1> x_rvar = x_v;
rvar<T, 1> y_rvar = y_v;
rvar<T, 1> fmod_rvar = fmod(x_rvar, y_rvar);
BOOST_REQUIRE_CLOSE_FRACTION(fmod_rvar.item(), expected_fmod, boost_close_tol<T>());
BOOST_REQUIRE_CLOSE_FRACTION(fmod_rvar.item(), expected_fmod, 10 * boost_close_tol<T>());
gradient_tape<T, 1>& tape = get_active_tape<T, 1>();
tape.zero_grad();
@@ -520,22 +525,22 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_fmod, T, all_float_types)
T dx_expected = 1.0;
T dy_expected = -1.0 * trunc(x_v / y_v);
BOOST_REQUIRE_CLOSE_FRACTION(x_rvar.adjoint(), dx_expected, boost_close_tol<T>());
BOOST_REQUIRE_CLOSE_FRACTION(y_rvar.adjoint(), dy_expected, boost_close_tol<T>());
BOOST_REQUIRE_CLOSE_FRACTION(x_rvar.adjoint(), dx_expected, 10 * boost_close_tol<T>());
BOOST_REQUIRE_CLOSE_FRACTION(y_rvar.adjoint(), dy_expected, 10 * boost_close_tol<T>());
rvar<T, 1> fmod_rvar_float = fmod(x_rvar, y_v);
BOOST_REQUIRE_CLOSE_FRACTION(fmod_rvar_float.item(), expected_fmod, boost_close_tol<T>());
BOOST_REQUIRE_CLOSE_FRACTION(fmod_rvar_float.item(), expected_fmod, 10 * boost_close_tol<T>());
tape.zero_grad();
fmod_rvar_float.backward();
BOOST_REQUIRE_CLOSE_FRACTION(x_rvar.adjoint(), dx_expected, boost_close_tol<T>());
BOOST_REQUIRE_CLOSE_FRACTION(x_rvar.adjoint(), dx_expected, 10 * boost_close_tol<T>());
rvar<T, 1> fmod_float_rvar = fmod(x_v, y_rvar);
BOOST_REQUIRE_CLOSE_FRACTION(fmod_float_rvar.item(), expected_fmod, boost_close_tol<T>());
BOOST_REQUIRE_CLOSE_FRACTION(fmod_float_rvar.item(), expected_fmod, 10 * boost_close_tol<T>());
tape.zero_grad();
fmod_float_rvar.backward();
BOOST_REQUIRE_CLOSE_FRACTION(y_rvar.adjoint(), dy_expected, boost_close_tol<T>());
BOOST_REQUIRE_CLOSE_FRACTION(y_rvar.adjoint(), dy_expected, 10 * boost_close_tol<T>());
tape.clear();
}
@@ -854,7 +859,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_func_1_first_derivative, T, all_float_types)
rvar<T, 1> x_ad = x;
rvar<T, 1> y_ad = y;
T fv = test_function_1(x, y);
//T fv = test_function_1(x, y);
rvar<T, 1> f_ad = test_function_1(x_ad, y_ad);
auto grad_f_analytical = grad_test_func_1_analytical(x, y);
/* intended use case */
@@ -888,7 +893,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_func_1_second_derivative_and_hessian, T, all_
rvar<T, 2> x_ad = x;
rvar<T, 2> y_ad = y;
T fv = test_function_1(x, y);
//T fv = test_function_1(x, y);
rvar<T, 2> f_ad = test_function_1(x_ad, y_ad);
gradient_tape<T, 2>& tape = get_active_tape<T, 2>();
tape.zero_grad();
@@ -918,7 +923,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_func_1_order_3_der, T, all_float_types)
rvar<T, 3> x_ad = x;
rvar<T, 3> y_ad = y;
T fv = test_function_1(x, y);
//T fv = test_function_1(x, y);
rvar<T, 3> f_ad = test_function_1(x_ad, y_ad);
gradient_tape<T, 3>& tape = get_active_tape<T, 3>();
tape.zero_grad();