File indexing completed on 2025-01-18 09:39:57
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef BOOST_MATH_QUADRATURE_EXP_SINH_HPP
0016 #define BOOST_MATH_QUADRATURE_EXP_SINH_HPP
0017
0018 #include <cmath>
0019 #include <limits>
0020 #include <memory>
0021 #include <string>
0022 #include <boost/math/quadrature/detail/exp_sinh_detail.hpp>
0023
0024 namespace boost{ namespace math{ namespace quadrature {
0025
0026 template<class Real, class Policy = policies::policy<> >
0027 class exp_sinh
0028 {
0029 public:
0030 exp_sinh(size_t max_refinements = 9)
0031 : m_imp(std::make_shared<detail::exp_sinh_detail<Real, Policy>>(max_refinements)) {}
0032
0033 template<class F>
0034 auto integrate(const F& f, Real a, Real b, Real tol = boost::math::tools::root_epsilon<Real>(), Real* error = nullptr, Real* L1 = nullptr, std::size_t* levels = nullptr) const ->decltype(std::declval<F>()(std::declval<Real>()));
0035 template<class F>
0036 auto integrate(const F& f, Real tol = boost::math::tools::root_epsilon<Real>(), Real* error = nullptr, Real* L1 = nullptr, std::size_t* levels = nullptr) const ->decltype(std::declval<F>()(std::declval<Real>()));
0037
0038 private:
0039 std::shared_ptr<detail::exp_sinh_detail<Real, Policy>> m_imp;
0040 };
0041
0042 template<class Real, class Policy>
0043 template<class F>
0044 auto exp_sinh<Real, Policy>::integrate(const F& f, Real a, Real b, Real tolerance, Real* error, Real* L1, std::size_t* levels) const ->decltype(std::declval<F>()(std::declval<Real>()))
0045 {
0046 typedef decltype(f(a)) K;
0047 static_assert(!std::is_integral<K>::value,
0048 "The return type cannot be integral, it must be either a real or complex floating point type.");
0049 using std::abs;
0050 using boost::math::constants::half;
0051 using boost::math::quadrature::detail::exp_sinh_detail;
0052
0053 static const char* function = "boost::math::quadrature::exp_sinh<%1%>::integrate";
0054
0055
0056 if((boost::math::isnan)(a) || (boost::math::isnan)(b))
0057 {
0058 return static_cast<K>(policies::raise_domain_error(function, "NaN supplied as one limit of integration - sorry I don't know what to do", a, Policy()));
0059 }
0060
0061 if ((boost::math::isfinite)(a) && (b >= boost::math::tools::max_value<Real>()))
0062 {
0063
0064 if (a == static_cast<Real>(0))
0065 {
0066 return m_imp->integrate(f, error, L1, function, tolerance, levels);
0067 }
0068 const auto u = [&](Real t)->K { return f(t + a); };
0069 return m_imp->integrate(u, error, L1, function, tolerance, levels);
0070 }
0071
0072 if ((boost::math::isfinite)(b) && a <= -boost::math::tools::max_value<Real>())
0073 {
0074 const auto u = [&](Real t)->K { return f(b-t);};
0075 return m_imp->integrate(u, error, L1, function, tolerance, levels);
0076 }
0077
0078
0079 if ((a <= -boost::math::tools::max_value<Real>()) && (b >= boost::math::tools::max_value<Real>()))
0080 {
0081 return static_cast<K>(policies::raise_domain_error(function, "Use sinh_sinh quadrature for integration over the whole real line; exp_sinh is for half infinite integrals.", a, Policy()));
0082 }
0083
0084 return static_cast<K>(policies::raise_domain_error(function, "Use tanh_sinh quadrature for integration over finite domains; exp_sinh is for half infinite integrals.", a, Policy()));
0085 }
0086
0087 template<class Real, class Policy>
0088 template<class F>
0089 auto exp_sinh<Real, Policy>::integrate(const F& f, Real tolerance, Real* error, Real* L1, std::size_t* levels) const ->decltype(std::declval<F>()(std::declval<Real>()))
0090 {
0091 static const char* function = "boost::math::quadrature::exp_sinh<%1%>::integrate";
0092 using std::abs;
0093 if (abs(tolerance) > 1) {
0094 std::string msg = std::string(__FILE__) + ":" + std::to_string(__LINE__) + ":" + std::string(function) + ": The tolerance provided is unusually large; did you confuse it with a domain bound?";
0095 throw std::domain_error(msg);
0096 }
0097 return m_imp->integrate(f, error, L1, function, tolerance, levels);
0098 }
0099
0100
0101 }}}
0102 #endif