Automatic Differentiation
 
Loading...
Searching...
No Matches
integrate_1d_gauss_kronrod.hpp
Go to the documentation of this file.
1#ifndef STAN_MATH_PRIM_FUNCTOR_INTEGRATE_1D_GAUSS_KRONROD_HPP
2#define STAN_MATH_PRIM_FUNCTOR_INTEGRATE_1D_GAUSS_KRONROD_HPP
3
8#include <boost/math/quadrature/gauss_kronrod.hpp>
9#include <algorithm>
10#include <cmath>
11#include <ostream>
12
13namespace stan {
14namespace math {
15
22constexpr unsigned int INTEGRATE_1D_GAUSS_KRONROD_ORDER = 21;
23
29
72template <typename F>
73inline double integrate_gk(const F& f, double a, double b,
74 double relative_tolerance, double absolute_tolerance,
75 int max_depth) {
76 static constexpr const char* function = "integrate_1d_gauss_kronrod";
77 double error = 0.0;
78 double L1 = 0.0;
79
80 // Gauss-Kronrod does not pass a distance-to-boundary; the user functor
81 // still takes (x, xc) for signature compatibility with integrate_1d, but
82 // xc is unused here.
83 auto f_wrap = [&f](double x) { return f(x, NOT_A_NUMBER); };
84
85 using boost::math::quadrature::gauss_kronrod;
86 const unsigned int depth
87 = max_depth < 0 ? 0u : static_cast<unsigned int>(max_depth);
88 double Q = gauss_kronrod<double, INTEGRATE_1D_GAUSS_KRONROD_ORDER>::integrate(
89 f_wrap, a, b, depth, relative_tolerance, &error, &L1);
90
91 // QUADPACK-style mixed convergence: throw only if the Boost error
92 // exceeds both the relative-tolerance target (rel_tol * L1) and the
93 // user-supplied absolute floor. With absolute_tolerance = 0 (default)
94 // this reduces to the strict pure-relative test.
95 const double convergence_threshold
96 = std::max(relative_tolerance * L1, absolute_tolerance);
97 if (error > convergence_threshold) {
98 [error]() STAN_COLD_PATH {
100 function, "error estimate of integral", error, "",
101 " exceeds max(relative_tolerance * L1, absolute_tolerance)");
102 }();
103 }
104 return Q;
105}
106
125template <typename F, typename... Args,
126 require_all_st_arithmetic<Args...>* = nullptr>
127inline double integrate_1d_gauss_kronrod_tol(const F& f, double a, double b,
128 double relative_tolerance,
129 double absolute_tolerance,
130 int max_depth, std::ostream* msgs,
131 const Args&... args) {
132 static constexpr const char* function = "integrate_1d_gauss_kronrod";
133 check_less_or_equal(function, "lower limit", a, b);
134 check_nonnegative(function, "max_depth", max_depth);
135 check_nonnegative(function, "absolute_tolerance", absolute_tolerance);
136 if (unlikely(a == b)) {
137 if (std::isinf(a)) {
138 throw_domain_error(function, "Integration endpoints are both", a, "", "");
139 }
140 return 0.0;
141 } else {
142 return integrate_gk(
143 [&](auto&& x, auto&& xc) { return f(x, xc, msgs, args...); }, a, b,
144 relative_tolerance, absolute_tolerance, max_depth);
145 }
146}
147
180template <typename F, typename... Args,
181 require_all_st_arithmetic<Args...>* = nullptr>
182inline double integrate_1d_gauss_kronrod(const F& f, double a, double b,
183 std::ostream* msgs,
184 const Args&... args) {
185 return integrate_1d_gauss_kronrod_tol(f, a, b, std::sqrt(EPSILON), 0.0,
187 msgs, args...);
188}
189
190} // namespace math
191} // namespace stan
192
193#endif
#define STAN_COLD_PATH
#define unlikely(x)
require_all_t< std::is_arithmetic< scalar_type_t< std::decay_t< Types > > >... > require_all_st_arithmetic
Require all of the scalar types satisfy std::is_arithmetic.
void check_less_or_equal(const char *function, const char *name, const T_y &y, const T_high &high, Idxs... idxs)
Throw an exception if y is not less than high.
static constexpr double NOT_A_NUMBER
(Quiet) not-a-number value.
Definition constants.hpp:56
void check_nonnegative(const char *function, const char *name, const T_y &y)
Check if y is non-negative.
static constexpr double EPSILON
Smallest positive value.
Definition constants.hpp:41
return_type_t< T_a, T_b, Args... > integrate_1d_gauss_kronrod_tol(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)
Return the integral of f from a to b using adaptive Gauss-Kronrod (G21,K21) quadrature,...
constexpr unsigned int INTEGRATE_1D_GAUSS_KRONROD_ORDER
Default Kronrod order used by integrate_1d_gauss_kronrod.
constexpr int INTEGRATE_1D_GAUSS_KRONROD_MAX_DEPTH
Default recursive bisection depth used by integrate_1d_gauss_kronrod when the user does not pass one ...
void throw_domain_error(const char *function, const char *name, const T &y, const char *msg1, const char *msg2)
Throw a domain error with a consistently formatted message.
return_type_t< T_a, T_b, Args... > integrate_1d_gauss_kronrod(const F &f, const T_a &a, const T_b &b, std::ostream *msgs, const Args &... args)
Return the integral of f from a to b using adaptive Gauss-Kronrod (G21,K21) quadrature,...
double integrate_gk(const F &f, double a, double b, double relative_tolerance, double absolute_tolerance, int max_depth)
Integrate a single variable function f from a to b using Boost's adaptive Gauss-Kronrod (G21,...
The lgamma implementation in stan-math is based on either the reentrant safe lgamma_r implementation ...
bool isinf(const stan::math::var &a)
Return 1 if the specified argument is positive infinity or negative infinity and 0 otherwise.
Definition std_isinf.hpp:16