Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions stan/math/fwd/functor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#include <stan/math/fwd/functor/finite_diff.hpp>
#include <stan/math/fwd/functor/hessian.hpp>
#include <stan/math/fwd/functor/integrate_1d.hpp>
#include <stan/math/fwd/functor/integrate_1d_double_exponential.hpp>
#include <stan/math/fwd/functor/integrate_1d_gauss_kronrod.hpp>
#include <stan/math/fwd/functor/jacobian.hpp>
#include <stan/math/fwd/functor/operands_and_partials.hpp>
#include <stan/math/fwd/functor/partials_propagator.hpp>
Expand Down
113 changes: 113 additions & 0 deletions stan/math/fwd/functor/integrate_1d_double_exponential.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
#ifndef STAN_MATH_FWD_FUNCTOR_INTEGRATE_1D_DOUBLE_EXPONENTIAL_HPP
#define STAN_MATH_FWD_FUNCTOR_INTEGRATE_1D_DOUBLE_EXPONENTIAL_HPP

#include <stan/math/fwd/meta.hpp>
#include <stan/math/prim/functor/integrate_1d_double_exponential.hpp>
#include <stan/math/prim/fun/value_of.hpp>
#include <stan/math/prim/meta/forward_as.hpp>
#include <stan/math/prim/functor/apply.hpp>
#include <stan/math/fwd/functor/finite_diff.hpp>

namespace stan {
namespace math {
/**
* Return the integral of f from a to b using adaptive double-exponential
* quadrature, with tangents computed via finite differences over the
* integrand parameters.
*
* @tparam F Type of f
* @tparam T_a type of first limit
* @tparam T_b type of second limit
* @tparam Args types of parameter pack arguments
*
* @param f the functor to integrate
* @param a lower limit of integration
* @param b upper limit of integration
* @param relative_tolerance relative tolerance passed to Boost quadrature
* @param absolute_tolerance absolute-error floor on the convergence test
* @param max_refinements maximum refinement level passed to the Boost
* quadrature class constructor
* @param[in, out] msgs the print stream for warning messages
* @param args additional arguments to pass to f
* @return numeric integral of function f
*/
template <typename F, typename T_a, typename T_b, typename... Args,
require_any_st_fvar<T_a, T_b, Args...> * = nullptr>
inline return_type_t<T_a, T_b, Args...> integrate_1d_double_exponential_impl(
const F &f, const T_a &a, const T_b &b, double relative_tolerance,
double absolute_tolerance, int max_refinements, std::ostream *msgs,
const Args &... args) {
using FvarT = scalar_type_t<return_type_t<T_a, T_b, Args...>>;

auto a_val = value_of(a);
auto b_val = value_of(b);
auto func = [f, msgs, relative_tolerance, absolute_tolerance, max_refinements,
a_val, b_val](const auto &... args_var) {
return integrate_1d_double_exponential_impl(
f, a_val, b_val, relative_tolerance, absolute_tolerance,
max_refinements, msgs, args_var...);
};
FvarT ret = finite_diff(func, args...);

if constexpr (is_fvar<T_a>::value || is_fvar<T_b>::value) {
auto val_args = std::make_tuple(value_of(args)...);
if constexpr (is_fvar<T_a>::value) {
ret.d_ += a.d_
* math::apply(
[&](auto &&... tuple_args) {
return -f(a_val, 0.0, msgs, tuple_args...);
},
val_args);
}
if constexpr (is_fvar<T_b>::value) {
ret.d_ += b.d_
* math::apply(
[&](auto &&... tuple_args) {
return f(b_val, 0.0, msgs, tuple_args...);
},
val_args);
}
}
return ret;
}

/**
* Compute the integral of the single variable function f from a to b using
* adaptive double-exponential quadrature. a and b can be finite or
* infinite.
*
* @tparam T_a type of first limit
* @tparam T_b type of second limit
* @tparam T_theta type of parameters
* @tparam F Type of f
*
* @param f the functor to integrate
* @param a lower limit of integration
* @param b upper limit of integration
* @param theta additional parameters to be passed to f
* @param x_r additional data to be passed to f
* @param x_i additional integer data to be passed to f
* @param[in, out] msgs the print stream for warning messages
* @param relative_tolerance relative tolerance passed to Boost quadrature
* @param absolute_tolerance absolute-error floor on the convergence test
* @param max_refinements maximum refinement level passed to the Boost
* quadrature class constructor
* @return numeric integral of function f
*/
template <typename F, typename T_a, typename T_b, typename T_theta,
require_any_fvar_t<T_a, T_b, T_theta> * = nullptr>
inline return_type_t<T_a, T_b, T_theta> integrate_1d_double_exponential(
const F &f, const T_a &a, const T_b &b, const std::vector<T_theta> &theta,
const std::vector<double> &x_r, const std::vector<int> &x_i,
std::ostream *msgs, const double relative_tolerance,
const double absolute_tolerance = 0.0,
const int max_refinements
= INTEGRATE_1D_DOUBLE_EXPONENTIAL_MAX_REFINEMENTS) {
return integrate_1d_double_exponential_impl(
integrate_1d_adapter<F>(f), a, b, relative_tolerance, absolute_tolerance,
max_refinements, msgs, theta, x_r, x_i);
}

} // namespace math
} // namespace stan
#endif
115 changes: 115 additions & 0 deletions stan/math/fwd/functor/integrate_1d_gauss_kronrod.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
#ifndef STAN_MATH_FWD_FUNCTOR_INTEGRATE_1D_GAUSS_KRONROD_HPP
#define STAN_MATH_FWD_FUNCTOR_INTEGRATE_1D_GAUSS_KRONROD_HPP

#include <stan/math/fwd/meta.hpp>
#include <stan/math/prim/functor/integrate_1d_gauss_kronrod.hpp>
#include <stan/math/prim/fun/value_of.hpp>
#include <stan/math/prim/meta/forward_as.hpp>
#include <stan/math/prim/functor/apply.hpp>
#include <stan/math/fwd/functor/finite_diff.hpp>

namespace stan {
namespace math {
/**
* Return the integral of f from a to b using adaptive Gauss-Kronrod (G21,K21)
* quadrature, with tangents computed via finite differences over the
* integrand parameters.
*
* @tparam F Type of f
* @tparam T_a type of first limit
* @tparam T_b type of second limit
* @tparam Args types of parameter pack arguments
*
* @param f the functor to integrate
* @param a lower limit of integration
* @param b upper limit of integration
* @param relative_tolerance relative tolerance passed to Boost quadrature
* @param absolute_tolerance absolute-error floor on the convergence test
* @param max_depth maximum recursive bisection depth passed to Boost
* quadrature
* @param[in, out] msgs the print stream for warning messages
* @param args additional arguments to pass to f
* @return numeric integral of function f
*/
template <typename F, typename T_a, typename T_b, typename... Args,
require_any_st_fvar<T_a, T_b, Args...> * = nullptr>
inline return_type_t<T_a, T_b, Args...> integrate_1d_gauss_kronrod_impl(
const F &f, const T_a &a, const T_b &b, double relative_tolerance,
double absolute_tolerance, int max_depth, std::ostream *msgs,
const Args &... args) {
using FvarT = scalar_type_t<return_type_t<T_a, T_b, Args...>>;

// Wrap integrate_1d_gauss_kronrod call in a functor where the input
// arguments are only those for which tangents are needed.
auto a_val = value_of(a);
auto b_val = value_of(b);
auto func = [f, msgs, relative_tolerance, absolute_tolerance, max_depth,
a_val, b_val](const auto &... args_var) {
return integrate_1d_gauss_kronrod_impl(f, a_val, b_val, relative_tolerance,
absolute_tolerance, max_depth, msgs,
args_var...);
};
FvarT ret = finite_diff(func, args...);

// Calculate tangents w.r.t. integration bounds if needed
if constexpr (is_fvar<T_a>::value || is_fvar<T_b>::value) {
auto val_args = std::make_tuple(value_of(args)...);
if constexpr (is_fvar<T_a>::value) {
ret.d_ += a.d_
* math::apply(
[&](auto &&... tuple_args) {
return -f(a_val, 0.0, msgs, tuple_args...);
},
val_args);
}
if constexpr (is_fvar<T_b>::value) {
ret.d_ += b.d_
* math::apply(
[&](auto &&... tuple_args) {
return f(b_val, 0.0, msgs, tuple_args...);
},
val_args);
}
}
return ret;
}

/**
* Compute the integral of the single variable function f from a to b using
* adaptive Gauss-Kronrod (G21,K21) quadrature. a and b can be finite or
* infinite.
*
* @tparam T_a type of first limit
* @tparam T_b type of second limit
* @tparam T_theta type of parameters
* @tparam F Type of f
*
* @param f the functor to integrate
* @param a lower limit of integration
* @param b upper limit of integration
* @param theta additional parameters to be passed to f
* @param x_r additional data to be passed to f
* @param x_i additional integer data to be passed to f
* @param[in, out] msgs the print stream for warning messages
* @param relative_tolerance relative tolerance passed to Boost quadrature
* @param absolute_tolerance absolute-error floor on the convergence test
* @param max_depth maximum recursive bisection depth passed to Boost
* quadrature
* @return numeric integral of function f
*/
template <typename F, typename T_a, typename T_b, typename T_theta,
require_any_fvar_t<T_a, T_b, T_theta> * = nullptr>
inline return_type_t<T_a, T_b, T_theta> integrate_1d_gauss_kronrod(
const F &f, const T_a &a, const T_b &b, const std::vector<T_theta> &theta,
const std::vector<double> &x_r, const std::vector<int> &x_i,
std::ostream *msgs, const double relative_tolerance,
const double absolute_tolerance = 0.0,
const int max_depth = INTEGRATE_1D_GAUSS_KRONROD_MAX_DEPTH) {
return integrate_1d_gauss_kronrod_impl(integrate_1d_adapter<F>(f), a, b,
relative_tolerance, absolute_tolerance,
max_depth, msgs, theta, x_r, x_i);
}

} // namespace math
} // namespace stan
#endif
2 changes: 2 additions & 0 deletions stan/math/prim/functor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
#include <stan/math/prim/functor/hcubature.hpp>
#include <stan/math/prim/functor/integrate_1d.hpp>
#include <stan/math/prim/functor/integrate_1d_adapter.hpp>
#include <stan/math/prim/functor/integrate_1d_double_exponential.hpp>
#include <stan/math/prim/functor/integrate_1d_gauss_kronrod.hpp>
#include <stan/math/prim/functor/integrate_ode_rk45.hpp>
#include <stan/math/prim/functor/integrate_ode_std_vector_interface_adapter.hpp>
#include <stan/math/prim/functor/iter_tuple_nested.hpp>
Expand Down
Loading
Loading