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
81template <typename F>
82inline double integrate_gk(const F& f, double a, double b,
83 double relative_tolerance, double absolute_tolerance,
84 int max_depth) {
85 static constexpr const char* function = "integrate_1d_gauss_kronrod";
86 double error = 0.0;
87 double L1 = 0.0;
88
89 // Gauss-Kronrod does not pass a distance-to-boundary; the user functor
90 // still takes (x, xc) for signature compatibility with integrate_1d, but
91 // xc is unused here.
92 auto f_wrap = [&f](double x) { return f(x, NOT_A_NUMBER); };
93
94 using boost::math::quadrature::gauss_kronrod;
95 const unsigned int depth
96 = max_depth < 0 ? 0u : static_cast<unsigned int>(max_depth);
97 double Q = gauss_kronrod<double, INTEGRATE_1D_GAUSS_KRONROD_ORDER>::integrate(
98 f_wrap, a, b, depth, relative_tolerance, &error, &L1, absolute_tolerance);
99
100 // QUADPACK-style mixed convergence: throw only if the Boost error
101 // exceeds both the relative-tolerance target (rel_tol * L1) and the
102 // user-supplied absolute floor. With absolute_tolerance = 0 (default)
103 // this reduces to the strict pure-relative test.
104 const double convergence_threshold
105 = std::max(relative_tolerance * L1, absolute_tolerance);
106 if (error > convergence_threshold) {
107 [error]() STAN_COLD_PATH {
109 function, "error estimate of integral", error, "",
110 " exceeds max(relative_tolerance * L1, absolute_tolerance)");
111 }();
112 }
113 return Q;
114}
115
134template <typename F, typename... Args,
135 require_all_st_arithmetic<Args...>* = nullptr>
136inline double integrate_1d_gauss_kronrod_tol(const F& f, double a, double b,
137 double relative_tolerance,
138 double absolute_tolerance,
139 int max_depth, std::ostream* msgs,
140 const Args&... args) {
141 static constexpr const char* function = "integrate_1d_gauss_kronrod";
142 check_less_or_equal(function, "lower limit", a, b);
143 check_nonnegative(function, "max_depth", max_depth);
144 check_nonnegative(function, "absolute_tolerance", absolute_tolerance);
145 if (unlikely(a == b)) {
146 if (std::isinf(a)) {
147 throw_domain_error(function, "Integration endpoints are both", a, "", "");
148 }
149 return 0.0;
150 } else {
151 return integrate_gk(
152 [&](auto&& x, auto&& xc) { return f(x, xc, msgs, args...); }, a, b,
153 relative_tolerance, absolute_tolerance, max_depth);
154 }
155}
156
189template <typename F, typename... Args,
190 require_all_st_arithmetic<Args...>* = nullptr>
191inline double integrate_1d_gauss_kronrod(const F& f, double a, double b,
192 std::ostream* msgs,
193 const Args&... args) {
194 return integrate_1d_gauss_kronrod_tol(f, a, b, std::sqrt(EPSILON), 0.0,
196 msgs, args...);
197}
198
199} // namespace math
200} // namespace stan
201
202#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 (G10,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 (G10,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 (G10,...
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