123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 |
- #ifndef BOOST_MATH_QUADRATURE_TRAPEZOIDAL_HPP
- #define BOOST_MATH_QUADRATURE_TRAPEZOIDAL_HPP
- #include <cmath>
- #include <limits>
- #include <stdexcept>
- #include <boost/math/constants/constants.hpp>
- #include <boost/math/special_functions/fpclassify.hpp>
- #include <boost/math/policies/error_handling.hpp>
- #include <boost/math/tools/cxx03_warn.hpp>
- namespace boost{ namespace math{ namespace quadrature {
- template<class F, class Real, class Policy>
- auto trapezoidal(F f, Real a, Real b, Real tol, std::size_t max_refinements, Real* error_estimate, Real* L1, const Policy& pol)->decltype(std::declval<F>()(std::declval<Real>()))
- {
- static const char* function = "boost::math::quadrature::trapezoidal<%1%>(F, %1%, %1%, %1%)";
- using std::abs;
- using boost::math::constants::half;
-
-
- typedef decltype(f(a)) K;
- if (!(boost::math::isfinite)(a))
- {
- return static_cast<K>(boost::math::policies::raise_domain_error(function, "Left endpoint of integration must be finite for adaptive trapezoidal integration but got a = %1%.\n", a, pol));
- }
- if (!(boost::math::isfinite)(b))
- {
- return static_cast<K>(boost::math::policies::raise_domain_error(function, "Right endpoint of integration must be finite for adaptive trapezoidal integration but got b = %1%.\n", b, pol));
- }
- if (a == b)
- {
- return static_cast<K>(0);
- }
- if(a > b)
- {
- return -trapezoidal(f, b, a, tol, max_refinements, error_estimate, L1, pol);
- }
- K ya = f(a);
- K yb = f(b);
- Real h = (b - a)*half<Real>();
- K I0 = (ya + yb)*h;
- Real IL0 = (abs(ya) + abs(yb))*h;
- K yh = f(a + h);
- K I1;
- I1 = I0*half<Real>() + yh*h;
- Real IL1 = IL0*half<Real>() + abs(yh)*h;
-
-
- std::size_t k = 2;
-
-
-
- Real error = abs(I0 - I1);
-
-
-
- while (k < 5 || (k < max_refinements && error > tol*IL1) )
- {
- I0 = I1;
- IL0 = IL1;
- I1 = I0*half<Real>();
- IL1 = IL0*half<Real>();
- std::size_t p = static_cast<std::size_t>(1u) << k;
- h *= half<Real>();
- K sum = 0;
- Real absum = 0;
- for(std::size_t j = 1; j < p; j += 2)
- {
- K y = f(a + j*h);
- sum += y;
- absum += abs(y);
- }
- I1 += sum*h;
- IL1 += absum*h;
- ++k;
- error = abs(I0 - I1);
- }
- if (error_estimate)
- {
- *error_estimate = error;
- }
- if (L1)
- {
- *L1 = IL1;
- }
- return static_cast<K>(I1);
- }
- #if BOOST_WORKAROUND(BOOST_MSVC, < 1800)
- template<class F, class Real>
- auto trapezoidal(F f, Real a, Real b, Real tol = 0, std::size_t max_refinements = 12, Real* error_estimate = 0, Real* L1 = 0)->decltype(std::declval<F>()(std::declval<Real>()))
- #elif !defined(BOOST_NO_CXX11_NULLPTR)
- template<class F, class Real>
- auto trapezoidal(F f, Real a, Real b, Real tol = boost::math::tools::root_epsilon<Real>(), std::size_t max_refinements = 12, Real* error_estimate = nullptr, Real* L1 = nullptr)->decltype(std::declval<F>()(std::declval<Real>()))
- #else
- template<class F, class Real>
- auto trapezoidal(F f, Real a, Real b, Real tol = boost::math::tools::root_epsilon<Real>(), std::size_t max_refinements = 12, Real* error_estimate = 0, Real* L1 = 0)->decltype(std::declval<F>()(std::declval<Real>()))
- #endif
- {
- #if BOOST_WORKAROUND(BOOST_MSVC, <= 1600)
- if (tol == 0)
- tol = boost::math::tools::root_epsilon<Real>();
- #endif
- return trapezoidal(f, a, b, tol, max_refinements, error_estimate, L1, boost::math::policies::policy<>());
- }
- }}}
- #endif
|