1#ifndef STAN_MATH_PRIM_FUNCTOR_INTEGRATE_1D_DOUBLE_EXPONENTIAL_HPP
2#define STAN_MATH_PRIM_FUNCTOR_INTEGRATE_1D_DOUBLE_EXPONENTIAL_HPP
8#include <boost/math/quadrature/exp_sinh.hpp>
9#include <boost/math/quadrature/sinh_sinh.hpp>
10#include <boost/math/quadrature/tanh_sinh.hpp>
82 double relative_tolerance,
double absolute_tolerance,
83 int max_refinements) {
84 static constexpr const char* function =
"integrate_1d_double_exponential";
92 = max_refinements < 0 ? 0u : static_cast<size_t>(max_refinements);
94 auto one_integral_convergence_check
95 = [&](
double e,
double rel_tol,
double abs_tol,
double L) {
96 const double threshold = std::max(rel_tol * L, abs_tol);
100 function,
"error estimate of integral",
e,
"",
101 " exceeds max(relative_tolerance * L1, absolute_tolerance)");
105 auto two_integral_convergence_check = [&](
double e1,
double e2,
106 double rel_tol,
double abs_tol,
107 double La,
double Lb) {
108 const double threshold_a = std::max(rel_tol * La, abs_tol);
109 const double threshold_b = std::max(rel_tol * Lb, abs_tol);
110 if (e1 > threshold_a) {
113 function,
"error estimate of integral below zero", e1,
"",
114 " exceeds max(relative_tolerance * L1, absolute_tolerance) for "
115 "the lower piece of the split");
118 if (e2 > threshold_b) {
121 function,
"error estimate of integral above zero", e2,
"",
122 " exceeds max(relative_tolerance * L1, absolute_tolerance) for "
123 "the upper piece of the split");
129 auto f_wrap = [&f](
double x) {
return f(x,
NOT_A_NUMBER); };
131 boost::math::quadrature::sinh_sinh<double> integrator(mr);
132 double Q = integrator.integrate(f_wrap, relative_tolerance, &error1, &L1,
134 one_integral_convergence_check(error1, relative_tolerance,
135 absolute_tolerance, L1);
138 boost::math::quadrature::exp_sinh<double> integrator(mr);
142 double Q = integrator.integrate(f_wrap, a, b, relative_tolerance, &error1,
144 one_integral_convergence_check(error1, relative_tolerance,
145 absolute_tolerance, L1);
148 boost::math::quadrature::tanh_sinh<double> integrator_right(mr);
149 double Q = integrator.integrate(f_wrap, a, 0.0, relative_tolerance,
150 &error1, &L1, &levels)
151 + integrator_right.integrate(
152 f_wrap, 0.0, b, relative_tolerance, &error2, &L2, &levels);
153 two_integral_convergence_check(error1, error2, relative_tolerance,
154 absolute_tolerance, L1, L2);
158 boost::math::quadrature::exp_sinh<double> integrator(mr);
160 double Q = integrator.integrate(f_wrap, a, b, relative_tolerance, &error1,
162 one_integral_convergence_check(error1, relative_tolerance,
163 absolute_tolerance, L1);
166 boost::math::quadrature::tanh_sinh<double> integrator_left(mr);
167 double Q = integrator_left.integrate(f_wrap, a, 0, relative_tolerance,
168 &error1, &L1, &levels)
169 + integrator.integrate(f_wrap, relative_tolerance, &error2,
171 two_integral_convergence_check(error1, error2, relative_tolerance,
172 absolute_tolerance, L1, L2);
176 auto f_wrap = [&f](
double x,
double xc) {
return f(x, xc); };
177 boost::math::quadrature::tanh_sinh<double> integrator(mr);
178 if (a < 0.0 && b > 0.0) {
179 double Q = integrator.integrate(f_wrap, a, 0.0, relative_tolerance,
180 &error1, &L1, &levels)
181 + integrator.integrate(f_wrap, 0.0, b, relative_tolerance,
182 &error2, &L2, &levels);
183 two_integral_convergence_check(error1, error2, relative_tolerance,
184 absolute_tolerance, L1, L2);
187 double Q = integrator.integrate(f_wrap, a, b, relative_tolerance, &error1,
189 one_integral_convergence_check(error1, relative_tolerance,
190 absolute_tolerance, L1);
214template <
typename F,
typename... Args,
217 const F& f,
double a,
double b,
double relative_tolerance,
218 double absolute_tolerance,
int max_refinements, std::ostream* msgs,
219 const Args&... args) {
220 static constexpr const char* function =
"integrate_1d_double_exponential";
231 [&](
auto&& x,
auto&& xc) {
return f(x, xc, msgs, args...); }, a, b,
232 relative_tolerance, absolute_tolerance, max_refinements);
266template <
typename F,
typename... Args,
270 const Args&... args) {
272 f, a, b, std::sqrt(
EPSILON), 0.0,
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.
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.
static constexpr double e()
Return the base of the natural logarithm.
return_type_t< T_a, T_b, Args... > integrate_1d_double_exponential_tol(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)
Return the integral of f from a to b using adaptive double-exponential quadrature,...
double integrate_1d_double_exponential(const F &f, double a, double b, std::ostream *msgs, const Args &... args)
Compute the integral of the single variable function f from a to b using adaptive double-exponential ...
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.
double integrate_de(const F &f, double a, double b, double relative_tolerance, double absolute_tolerance, int max_refinements)
Integrate a single variable function f from a to b using Boost's adaptive double-exponential quadratu...
constexpr int INTEGRATE_1D_DOUBLE_EXPONENTIAL_MAX_REFINEMENTS
Default maximum refinement count used by integrate_1d_double_exponential when the user does not pass ...
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.