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:
149
example/autodiff_reverse_black_scholes.cpp
Normal file
149
example/autodiff_reverse_black_scholes.cpp
Normal 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;
|
||||
}
|
||||
@@ -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})
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 ;
|
||||
|
||||
@@ -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();
|
||||
@@ -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);
|
||||
@@ -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();
|
||||
@@ -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()
|
||||
|
||||
@@ -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]);
|
||||
}
|
||||
@@ -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();
|
||||
Reference in New Issue
Block a user