diff --git a/doc/sf/hypergeometric.qbk b/doc/sf/hypergeometric.qbk index 556e41d31..c4332c017 100644 --- a/doc/sf/hypergeometric.qbk +++ b/doc/sf/hypergeometric.qbk @@ -420,16 +420,16 @@ are destroyed by cancellation. namespace boost { namespace math { template - ``__sf_result`` hypergeometric_pFq(const Seq& aj, const Seq& bj, const Real& z, Real* pNorm, const Policy& pol); + ``__sf_result`` hypergeometric_pFq(const Seq& aj, const Seq& bj, const Real& z, Real* p_abs_error, const Policy& pol); template - ``__sf_result`` hypergeometric_pFq(const Seq& aj, const Seq& bj, const Real& z, Real* pNorm = 0) + ``__sf_result`` hypergeometric_pFq(const Seq& aj, const Seq& bj, const Real& z, Real* p_abs_error = 0) template - ``__sf_result`` hypergeometric_pFq(const std::initializer_list& aj, const std::initializer_list& bj, const Real& z, Real* pNorm, const Policy& pol); + ``__sf_result`` hypergeometric_pFq(const std::initializer_list& aj, const std::initializer_list& bj, const Real& z, Real* p_abs_error, const Policy& pol); template - ``__sf_result`` hypergeometric_pFq(const std::initializer_list& aj, const std::initializer_list& bj, const Real& z, Real* pNorm = 0) + ``__sf_result`` hypergeometric_pFq(const std::initializer_list& aj, const std::initializer_list& bj, const Real& z, Real* p_abs_error = 0) }} // namespaces @@ -444,10 +444,8 @@ It is most naturally used via initializer lists as in: double h = hypergeometric_pFq({2,3,4}, {5,6,7,8}, z); // Calculate 3F4 -The optional ['norm] argument calculates the norm of the sum and can be used for error estimation, which is to say the ['absolute error] -in the result is estimated to be: - - norm * std::numeric_limits::epsilon(); +The optional ['p_abs_error] argument calculates an estimate of the absolute error in the result from the +L1 norm of the sum, plus some other factors (see implementation below). You should divide this value by the result to get an estimate of ['relative error]. @@ -467,8 +465,9 @@ result. For other /p/ and /q/ values, predicting the exact locations of the max simply restart summation at the point where each b[sub j] passes the origin: this will eventually reach all the significant terms of the sum, but the key word may well be "eventually". -The error term /norm/ is normally simply the sum of the absolute values of each term. However, -if it was necessary for the summation to skip forward, then /norm/ is adjusted to account for the +The error term /p_abs_error/ is normally simply the sum of the absolute values of each term multiplied +by machine epsilon for type `Real`. However, +if it was necessary for the summation to skip forward, then /p_abs_error/ is adjusted to account for the error inherent in calculating the N'th term via logarithms. [endsect] diff --git a/include/boost/math/special_functions/hypergeometric_pFq.hpp b/include/boost/math/special_functions/hypergeometric_pFq.hpp index 055ddfcf0..69e28175a 100644 --- a/include/boost/math/special_functions/hypergeometric_pFq.hpp +++ b/include/boost/math/special_functions/hypergeometric_pFq.hpp @@ -8,8 +8,15 @@ #ifndef BOOST_MATH_HYPERGEOMETRIC_PFQ_HPP #define BOOST_MATH_HYPERGEOMETRIC_PFQ_HPP +#include + +#if defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) || defined(BOOST_NO_CXX11_LAMBDAS) || defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) || defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) +# error "hypergeometric_pFq requires a C++11 compiler" +#endif + #include #include +#include namespace boost { namespace math { @@ -42,7 +49,7 @@ namespace boost { } template - inline typename tools::promote_args::type hypergeometric_pFq(const Seq& aj, const Seq& bj, const Real& z, Real* pNorm, const Policy& pol) + inline typename tools::promote_args::type hypergeometric_pFq(const Seq& aj, const Seq& bj, const Real& z, Real* p_abs_error, const Policy& pol) { typedef typename tools::promote_args::type result_type; typedef typename policies::evaluation::type value_type; @@ -59,27 +66,27 @@ namespace boost { std::pair r = boost::math::detail::hypergeometric_pFq_checked_series_impl(aj, bj, value_type(z), pol, boost::math::detail::iteration_terminator(boost::math::policies::get_max_series_iterations()), scale); r.first *= exp(Real(scale)); r.second *= exp(Real(scale)); - if (pNorm) - *pNorm = static_cast(r.second); + if (p_abs_error) + *p_abs_error = static_cast(r.second) * boost::math::tools::epsilon(); return policies::checked_narrowing_cast(r.first, "boost::math::hypergeometric_pFq<%1%>(%1%,%1%,%1%)"); } template - inline typename tools::promote_args::type hypergeometric_pFq(const Seq& aj, const Seq& bj, const Real& z, Real* pNorm = 0) + inline typename tools::promote_args::type hypergeometric_pFq(const Seq& aj, const Seq& bj, const Real& z, Real* p_abs_error = 0) { - return hypergeometric_pFq(aj, bj, z, pNorm, boost::math::policies::policy<>()); + return hypergeometric_pFq(aj, bj, z, p_abs_error, boost::math::policies::policy<>()); } template - inline typename tools::promote_args::type hypergeometric_pFq(const std::initializer_list& aj, const std::initializer_list& bj, const Real& z, Real* pNorm, const Policy& pol) + inline typename tools::promote_args::type hypergeometric_pFq(const std::initializer_list& aj, const std::initializer_list& bj, const Real& z, Real* p_abs_error, const Policy& pol) { - return hypergeometric_pFq, Real, Policy>(aj, bj, z, pNorm, pol); + return hypergeometric_pFq, Real, Policy>(aj, bj, z, p_abs_error, pol); } template - inline typename tools::promote_args::type hypergeometric_pFq(const std::initializer_list& aj, const std::initializer_list& bj, const Real& z, Real* pNorm = 0) + inline typename tools::promote_args::type hypergeometric_pFq(const std::initializer_list& aj, const std::initializer_list& bj, const Real& z, Real* p_abs_error = 0) { - return hypergeometric_pFq, Real>(aj, bj, z, pNorm); + return hypergeometric_pFq, Real>(aj, bj, z, p_abs_error); } template