diff options
Diffstat (limited to 'src/third_party/boost-1.70.0/boost/math/special_functions/detail')
32 files changed, 13388 insertions, 0 deletions
diff --git a/src/third_party/boost-1.70.0/boost/math/special_functions/detail/airy_ai_bi_zero.hpp b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/airy_ai_bi_zero.hpp new file mode 100644 index 00000000000..b5a71c78eb2 --- /dev/null +++ b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/airy_ai_bi_zero.hpp @@ -0,0 +1,160 @@ +// Copyright (c) 2013 Christopher Kormanyos +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// This work is based on an earlier work: +// "Algorithm 910: A Portable C++ Multiple-Precision System for Special-Function Calculations", +// in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. http://doi.acm.org/10.1145/1916461.1916469 +// +// This header contains implementation details for estimating the zeros +// of the Airy functions airy_ai and airy_bi on the negative real axis. +// +#ifndef _AIRY_AI_BI_ZERO_2013_01_20_HPP_ + #define _AIRY_AI_BI_ZERO_2013_01_20_HPP_ + + #include <boost/math/constants/constants.hpp> + #include <boost/math/special_functions/cbrt.hpp> + + namespace boost { namespace math { + namespace detail + { + // Forward declarations of the needed Airy function implementations. + template <class T, class Policy> + T airy_ai_imp(T x, const Policy& pol); + template <class T, class Policy> + T airy_bi_imp(T x, const Policy& pol); + template <class T, class Policy> + T airy_ai_prime_imp(T x, const Policy& pol); + template <class T, class Policy> + T airy_bi_prime_imp(T x, const Policy& pol); + + namespace airy_zero + { + template<class T> + T equation_as_10_4_105(const T& z) + { + const T one_over_z (T(1) / z); + const T one_over_z_squared(one_over_z * one_over_z); + + const T z_pow_third (boost::math::cbrt(z)); + const T z_pow_two_thirds(z_pow_third * z_pow_third); + + // Implement the top line of Eq. 10.4.105. + const T fz(z_pow_two_thirds * ((((( + (T(162375596875.0) / 334430208UL) + * one_over_z_squared - ( T(108056875.0) / 6967296UL)) + * one_over_z_squared + ( T(77125UL) / 82944UL)) + * one_over_z_squared - ( T(5U) / 36U)) + * one_over_z_squared + ( T(5U) / 48U)) + * one_over_z_squared + (1))); + + return fz; + } + + namespace airy_ai_zero_detail + { + template<class T> + T initial_guess(const int m) + { + T guess; + + switch(m) + { + case 0: { guess = T(0); break; } + case 1: { guess = T(-2.33810741045976703849); break; } + case 2: { guess = T(-4.08794944413097061664); break; } + case 3: { guess = T(-5.52055982809555105913); break; } + case 4: { guess = T(-6.78670809007175899878); break; } + case 5: { guess = T(-7.94413358712085312314); break; } + case 6: { guess = T(-9.02265085334098038016); break; } + case 7: { guess = T(-10.0401743415580859306); break; } + case 8: { guess = T(-11.0085243037332628932); break; } + case 9: { guess = T(-11.9360155632362625170); break; } + case 10:{ guess = T(-12.8287767528657572004); break; } + default: + { + const T t(((boost::math::constants::pi<T>() * 3) * ((T(m) * 4) - 1)) / 8); + guess = -boost::math::detail::airy_zero::equation_as_10_4_105(t); + break; + } + } + + return guess; + } + + template<class T, class Policy> + class function_object_ai_and_ai_prime + { + public: + function_object_ai_and_ai_prime(const Policy& pol) : my_pol(pol) { } + + boost::math::tuple<T, T> operator()(const T& x) const + { + // Return a tuple containing both Ai(x) and Ai'(x). + return boost::math::make_tuple( + boost::math::detail::airy_ai_imp (x, my_pol), + boost::math::detail::airy_ai_prime_imp(x, my_pol)); + } + + private: + const Policy& my_pol; + const function_object_ai_and_ai_prime& operator=(const function_object_ai_and_ai_prime&); + }; + } // namespace airy_ai_zero_detail + + namespace airy_bi_zero_detail + { + template<class T> + T initial_guess(const int m) + { + T guess; + + switch(m) + { + case 0: { guess = T(0); break; } + case 1: { guess = T(-1.17371322270912792492); break; } + case 2: { guess = T(-3.27109330283635271568); break; } + case 3: { guess = T(-4.83073784166201593267); break; } + case 4: { guess = T(-6.16985212831025125983); break; } + case 5: { guess = T(-7.37676207936776371360); break; } + case 6: { guess = T(-8.49194884650938801345); break; } + case 7: { guess = T(-9.53819437934623888663); break; } + case 8: { guess = T(-10.5299135067053579244); break; } + case 9: { guess = T(-11.4769535512787794379); break; } + case 10: { guess = T(-12.3864171385827387456); break; } + default: + { + const T t(((boost::math::constants::pi<T>() * 3) * ((T(m) * 4) - 3)) / 8); + guess = -boost::math::detail::airy_zero::equation_as_10_4_105(t); + break; + } + } + + return guess; + } + + template<class T, class Policy> + class function_object_bi_and_bi_prime + { + public: + function_object_bi_and_bi_prime(const Policy& pol) : my_pol(pol) { } + + boost::math::tuple<T, T> operator()(const T& x) const + { + // Return a tuple containing both Bi(x) and Bi'(x). + return boost::math::make_tuple( + boost::math::detail::airy_bi_imp (x, my_pol), + boost::math::detail::airy_bi_prime_imp(x, my_pol)); + } + + private: + const Policy& my_pol; + const function_object_bi_and_bi_prime& operator=(const function_object_bi_and_bi_prime&); + }; + } // namespace airy_bi_zero_detail + } // namespace airy_zero + } // namespace detail + } // namespace math + } // namespaces boost + +#endif // _AIRY_AI_BI_ZERO_2013_01_20_HPP_ diff --git a/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bernoulli_details.hpp b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bernoulli_details.hpp new file mode 100644 index 00000000000..75fadbf34ae --- /dev/null +++ b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bernoulli_details.hpp @@ -0,0 +1,665 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2013 John Maddock +// Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_BERNOULLI_DETAIL_HPP +#define BOOST_MATH_BERNOULLI_DETAIL_HPP + +#include <boost/config.hpp> +#include <boost/detail/lightweight_mutex.hpp> +#include <boost/math/tools/atomic.hpp> +#include <boost/utility/enable_if.hpp> +#include <boost/math/tools/toms748_solve.hpp> +#include <vector> + +namespace boost{ namespace math{ namespace detail{ +// +// Asymptotic expansion for B2n due to +// Luschny LogB3 formula (http://www.luschny.de/math/primes/bernincl.html) +// +template <class T, class Policy> +T b2n_asymptotic(int n) +{ + BOOST_MATH_STD_USING + const T nx = static_cast<T>(n); + const T nx2(nx * nx); + + const T approximate_log_of_bernoulli_bn = + ((boost::math::constants::half<T>() + nx) * log(nx)) + + ((boost::math::constants::half<T>() - nx) * log(boost::math::constants::pi<T>())) + + (((T(3) / 2) - nx) * boost::math::constants::ln_two<T>()) + + ((nx * (T(2) - (nx2 * 7) * (1 + ((nx2 * 30) * ((nx2 * 12) - 1))))) / (((nx2 * nx2) * nx2) * 2520)); + return ((n / 2) & 1 ? 1 : -1) * (approximate_log_of_bernoulli_bn > tools::log_max_value<T>() + ? policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, nx, Policy()) + : static_cast<T>(exp(approximate_log_of_bernoulli_bn))); +} + +template <class T, class Policy> +T t2n_asymptotic(int n) +{ + BOOST_MATH_STD_USING + // Just get B2n and convert to a Tangent number: + T t2n = fabs(b2n_asymptotic<T, Policy>(2 * n)) / (2 * n); + T p2 = ldexp(T(1), n); + if(tools::max_value<T>() / p2 < t2n) + return policies::raise_overflow_error<T>("boost::math::tangent_t2n<%1%>(std::size_t)", 0, T(n), Policy()); + t2n *= p2; + p2 -= 1; + if(tools::max_value<T>() / p2 < t2n) + return policies::raise_overflow_error<T>("boost::math::tangent_t2n<%1%>(std::size_t)", 0, Policy()); + t2n *= p2; + return t2n; +} +// +// We need to know the approximate value of /n/ which will +// cause bernoulli_b2n<T>(n) to return infinity - this allows +// us to elude a great deal of runtime checking for values below +// n, and only perform the full overflow checks when we know that we're +// getting close to the point where our calculations will overflow. +// We use Luschny's LogB3 formula (http://www.luschny.de/math/primes/bernincl.html) +// to find the limit, and since we're dealing with the log of the Bernoulli numbers +// we need only perform the calculation at double precision and not with T +// (which may be a multiprecision type). The limit returned is within 1 of the true +// limit for all the types tested. Note that although the code below is basically +// the same as b2n_asymptotic above, it has been recast as a continuous real-valued +// function as this makes the root finding go smoother/faster. It also omits the +// sign of the Bernoulli number. +// +struct max_bernoulli_root_functor +{ + max_bernoulli_root_functor(long long t) : target(static_cast<double>(t)) {} + double operator()(double n) + { + BOOST_MATH_STD_USING + + // Luschny LogB3(n) formula. + + const double nx2(n * n); + + const double approximate_log_of_bernoulli_bn + = ((boost::math::constants::half<double>() + n) * log(n)) + + ((boost::math::constants::half<double>() - n) * log(boost::math::constants::pi<double>())) + + (((double(3) / 2) - n) * boost::math::constants::ln_two<double>()) + + ((n * (2 - (nx2 * 7) * (1 + ((nx2 * 30) * ((nx2 * 12) - 1))))) / (((nx2 * nx2) * nx2) * 2520)); + + return approximate_log_of_bernoulli_bn - target; + } +private: + double target; +}; + +template <class T, class Policy> +inline std::size_t find_bernoulli_overflow_limit(const mpl::false_&) +{ + long long t = lltrunc(boost::math::tools::log_max_value<T>()); + max_bernoulli_root_functor fun(t); + boost::math::tools::equal_floor tol; + boost::uintmax_t max_iter = boost::math::policies::get_max_root_iterations<Policy>(); + return static_cast<std::size_t>(boost::math::tools::toms748_solve(fun, sqrt(double(t)), double(t), tol, max_iter).first) / 2; +} + +template <class T, class Policy> +inline std::size_t find_bernoulli_overflow_limit(const mpl::true_&) +{ + return max_bernoulli_index<bernoulli_imp_variant<T>::value>::value; +} + +template <class T, class Policy> +std::size_t b2n_overflow_limit() +{ + // This routine is called at program startup if it's called at all: + // that guarantees safe initialization of the static variable. + typedef mpl::bool_<(bernoulli_imp_variant<T>::value >= 1) && (bernoulli_imp_variant<T>::value <= 3)> tag_type; + static const std::size_t lim = find_bernoulli_overflow_limit<T, Policy>(tag_type()); + return lim; +} + +// +// The tangent numbers grow larger much more rapidly than the Bernoulli numbers do.... +// so to compute the Bernoulli numbers from the tangent numbers, we need to avoid spurious +// overflow in the calculation, we can do this by scaling all the tangent number by some scale factor: +// +template <class T> +inline typename enable_if_c<std::numeric_limits<T>::is_specialized && (std::numeric_limits<T>::radix == 2), T>::type tangent_scale_factor() +{ + BOOST_MATH_STD_USING + return ldexp(T(1), std::numeric_limits<T>::min_exponent + 5); +} +template <class T> +inline typename disable_if_c<std::numeric_limits<T>::is_specialized && (std::numeric_limits<T>::radix == 2), T>::type tangent_scale_factor() +{ + return tools::min_value<T>() * 16; +} +// +// Initializer: ensure all our constants are initialized prior to the first call of main: +// +template <class T, class Policy> +struct bernoulli_initializer +{ + struct init + { + init() + { + // + // We call twice, once to initialize our static table, and once to + // initialize our dymanic table: + // + boost::math::bernoulli_b2n<T>(2, Policy()); +#ifndef BOOST_NO_EXCEPTIONS + try{ +#endif + boost::math::bernoulli_b2n<T>(max_bernoulli_b2n<T>::value + 1, Policy()); +#ifndef BOOST_NO_EXCEPTIONS + } catch(const std::overflow_error&){} +#endif + boost::math::tangent_t2n<T>(2, Policy()); + } + void force_instantiate()const{} + }; + static const init initializer; + static void force_instantiate() + { + initializer.force_instantiate(); + } +}; + +template <class T, class Policy> +const typename bernoulli_initializer<T, Policy>::init bernoulli_initializer<T, Policy>::initializer; + +// +// We need something to act as a cache for our calculated Bernoulli numbers. In order to +// ensure both fast access and thread safety, we need a stable table which may be extended +// in size, but which never reallocates: that way values already calculated may be accessed +// concurrently with another thread extending the table with new values. +// +// Very very simple vector class that will never allocate more than once, we could use +// boost::container::static_vector here, but that allocates on the stack, which may well +// cause issues for the amount of memory we want in the extreme case... +// +template <class T> +struct fixed_vector : private std::allocator<T> +{ + typedef unsigned size_type; + typedef T* iterator; + typedef const T* const_iterator; + fixed_vector() : m_used(0) + { + std::size_t overflow_limit = 5 + b2n_overflow_limit<T, policies::policy<> >(); + m_capacity = static_cast<unsigned>((std::min)(overflow_limit, static_cast<std::size_t>(100000u))); + m_data = this->allocate(m_capacity); + } + ~fixed_vector() + { +#ifdef BOOST_NO_CXX11_ALLOCATOR + for(unsigned i = 0; i < m_used; ++i) + this->destroy(&m_data[i]); + this->deallocate(m_data, m_capacity); +#else + typedef std::allocator<T> allocator_type; + typedef std::allocator_traits<allocator_type> allocator_traits; + allocator_type& alloc = *this; + for(unsigned i = 0; i < m_used; ++i) + allocator_traits::destroy(alloc, &m_data[i]); + allocator_traits::deallocate(alloc, m_data, m_capacity); +#endif + } + T& operator[](unsigned n) { BOOST_ASSERT(n < m_used); return m_data[n]; } + const T& operator[](unsigned n)const { BOOST_ASSERT(n < m_used); return m_data[n]; } + unsigned size()const { return m_used; } + unsigned size() { return m_used; } + void resize(unsigned n, const T& val) + { + if(n > m_capacity) + { + BOOST_THROW_EXCEPTION(std::runtime_error("Exhausted storage for Bernoulli numbers.")); + } + for(unsigned i = m_used; i < n; ++i) + new (m_data + i) T(val); + m_used = n; + } + void resize(unsigned n) { resize(n, T()); } + T* begin() { return m_data; } + T* end() { return m_data + m_used; } + T* begin()const { return m_data; } + T* end()const { return m_data + m_used; } + unsigned capacity()const { return m_capacity; } + void clear() { m_used = 0; } +private: + T* m_data; + unsigned m_used, m_capacity; +}; + +template <class T, class Policy> +class bernoulli_numbers_cache +{ +public: + bernoulli_numbers_cache() : m_overflow_limit((std::numeric_limits<std::size_t>::max)()) +#if defined(BOOST_HAS_THREADS) && !defined(BOOST_MATH_NO_ATOMIC_INT) + , m_counter(0) +#endif + , m_current_precision(boost::math::tools::digits<T>()) + {} + + typedef fixed_vector<T> container_type; + + void tangent(std::size_t m) + { + static const std::size_t min_overflow_index = b2n_overflow_limit<T, Policy>() - 1; + tn.resize(static_cast<typename container_type::size_type>(m), T(0U)); + + BOOST_MATH_INSTRUMENT_VARIABLE(min_overflow_index); + + std::size_t prev_size = m_intermediates.size(); + m_intermediates.resize(m, T(0U)); + + if(prev_size == 0) + { + m_intermediates[1] = tangent_scale_factor<T>() /*T(1U)*/; + tn[0U] = T(0U); + tn[1U] = tangent_scale_factor<T>()/* T(1U)*/; + BOOST_MATH_INSTRUMENT_VARIABLE(tn[0]); + BOOST_MATH_INSTRUMENT_VARIABLE(tn[1]); + } + + for(std::size_t i = std::max<size_t>(2, prev_size); i < m; i++) + { + bool overflow_check = false; + if(i >= min_overflow_index && (boost::math::tools::max_value<T>() / (i-1) < m_intermediates[1]) ) + { + std::fill(tn.begin() + i, tn.end(), boost::math::tools::max_value<T>()); + break; + } + m_intermediates[1] = m_intermediates[1] * (i-1); + for(std::size_t j = 2; j <= i; j++) + { + overflow_check = + (i >= min_overflow_index) && ( + (boost::math::tools::max_value<T>() / (i - j) < m_intermediates[j]) + || (boost::math::tools::max_value<T>() / (i - j + 2) < m_intermediates[j-1]) + || (boost::math::tools::max_value<T>() - m_intermediates[j] * (i - j) < m_intermediates[j-1] * (i - j + 2)) + || ((boost::math::isinf)(m_intermediates[j])) + ); + + if(overflow_check) + { + std::fill(tn.begin() + i, tn.end(), boost::math::tools::max_value<T>()); + break; + } + m_intermediates[j] = m_intermediates[j] * (i - j) + m_intermediates[j-1] * (i - j + 2); + } + if(overflow_check) + break; // already filled the tn... + tn[static_cast<typename container_type::size_type>(i)] = m_intermediates[i]; + BOOST_MATH_INSTRUMENT_VARIABLE(i); + BOOST_MATH_INSTRUMENT_VARIABLE(tn[static_cast<typename container_type::size_type>(i)]); + } + } + + void tangent_numbers_series(const std::size_t m) + { + BOOST_MATH_STD_USING + static const std::size_t min_overflow_index = b2n_overflow_limit<T, Policy>() - 1; + + typename container_type::size_type old_size = bn.size(); + + tangent(m); + bn.resize(static_cast<typename container_type::size_type>(m)); + + if(!old_size) + { + bn[0] = 1; + old_size = 1; + } + + T power_two(ldexp(T(1), static_cast<int>(2 * old_size))); + + for(std::size_t i = old_size; i < m; i++) + { + T b(static_cast<T>(i * 2)); + // + // Not only do we need to take care to avoid spurious over/under flow in + // the calculation, but we also need to avoid overflow altogether in case + // we're calculating with a type where "bad things" happen in that case: + // + b = b / (power_two * tangent_scale_factor<T>()); + b /= (power_two - 1); + bool overflow_check = (i >= min_overflow_index) && (tools::max_value<T>() / tn[static_cast<typename container_type::size_type>(i)] < b); + if(overflow_check) + { + m_overflow_limit = i; + while(i < m) + { + b = std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity() : tools::max_value<T>(); + bn[static_cast<typename container_type::size_type>(i)] = ((i % 2U) ? b : T(-b)); + ++i; + } + break; + } + else + { + b *= tn[static_cast<typename container_type::size_type>(i)]; + } + + power_two = ldexp(power_two, 2); + + const bool b_neg = i % 2 == 0; + + bn[static_cast<typename container_type::size_type>(i)] = ((!b_neg) ? b : T(-b)); + } + } + + template <class OutputIterator> + OutputIterator copy_bernoulli_numbers(OutputIterator out, std::size_t start, std::size_t n, const Policy& pol) + { + // + // There are basically 3 thread safety options: + // + // 1) There are no threads (BOOST_HAS_THREADS is not defined). + // 2) There are threads, but we do not have a true atomic integer type, + // in this case we just use a mutex to guard against race conditions. + // 3) There are threads, and we have an atomic integer: in this case we can + // use the double-checked locking pattern to avoid thread synchronisation + // when accessing values already in the cache. + // + // First off handle the common case for overflow and/or asymptotic expansion: + // + if(start + n > bn.capacity()) + { + if(start < bn.capacity()) + { + out = copy_bernoulli_numbers(out, start, bn.capacity() - start, pol); + n -= bn.capacity() - start; + start = static_cast<std::size_t>(bn.capacity()); + } + if(start < b2n_overflow_limit<T, Policy>() + 2u) + { + for(; n; ++start, --n) + { + *out = b2n_asymptotic<T, Policy>(static_cast<typename container_type::size_type>(start * 2U)); + ++out; + } + } + for(; n; ++start, --n) + { + *out = policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(start), pol); + ++out; + } + return out; + } + #if !defined(BOOST_HAS_THREADS) + // + // Single threaded code, very simple: + // + if(m_current_precision < boost::math::tools::digits<T>()) + { + bn.clear(); + tn.clear(); + m_intermediates.clear(); + m_current_precision = boost::math::tools::digits<T>(); + } + if(start + n >= bn.size()) + { + std::size_t new_size = (std::min)((std::max)((std::max)(std::size_t(start + n), std::size_t(bn.size() + 20)), std::size_t(50)), std::size_t(bn.capacity())); + tangent_numbers_series(new_size); + } + + for(std::size_t i = (std::max)(std::size_t(max_bernoulli_b2n<T>::value + 1), start); i < start + n; ++i) + { + *out = (i >= m_overflow_limit) ? policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol) : bn[i]; + ++out; + } + #elif defined(BOOST_MATH_NO_ATOMIC_INT) + // + // We need to grab a mutex every time we get here, for both readers and writers: + // + boost::detail::lightweight_mutex::scoped_lock l(m_mutex); + if(m_current_precision < boost::math::tools::digits<T>()) + { + bn.clear(); + tn.clear(); + m_intermediates.clear(); + m_current_precision = boost::math::tools::digits<T>(); + } + if(start + n >= bn.size()) + { + std::size_t new_size = (std::min)((std::max)((std::max)(std::size_t(start + n), std::size_t(bn.size() + 20)), std::size_t(50)), std::size_t(bn.capacity())); + tangent_numbers_series(new_size); + } + + for(std::size_t i = (std::max)(std::size_t(max_bernoulli_b2n<T>::value + 1), start); i < start + n; ++i) + { + *out = (i >= m_overflow_limit) ? policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol) : bn[i]; + ++out; + } + + #else + // + // Double-checked locking pattern, lets us access cached already cached values + // without locking: + // + // Get the counter and see if we need to calculate more constants: + // + if((static_cast<std::size_t>(m_counter.load(BOOST_MATH_ATOMIC_NS::memory_order_consume)) < start + n) + || (static_cast<int>(m_current_precision.load(BOOST_MATH_ATOMIC_NS::memory_order_consume)) < boost::math::tools::digits<T>())) + { + boost::detail::lightweight_mutex::scoped_lock l(m_mutex); + + if((static_cast<std::size_t>(m_counter.load(BOOST_MATH_ATOMIC_NS::memory_order_consume)) < start + n) + || (static_cast<int>(m_current_precision.load(BOOST_MATH_ATOMIC_NS::memory_order_consume)) < boost::math::tools::digits<T>())) + { + if(static_cast<int>(m_current_precision.load(BOOST_MATH_ATOMIC_NS::memory_order_consume)) < boost::math::tools::digits<T>()) + { + bn.clear(); + tn.clear(); + m_intermediates.clear(); + m_counter.store(0, BOOST_MATH_ATOMIC_NS::memory_order_release); + m_current_precision = boost::math::tools::digits<T>(); + } + if(start + n >= bn.size()) + { + std::size_t new_size = (std::min)((std::max)((std::max)(std::size_t(start + n), std::size_t(bn.size() + 20)), std::size_t(50)), std::size_t(bn.capacity())); + tangent_numbers_series(new_size); + } + m_counter.store(static_cast<atomic_integer_type>(bn.size()), BOOST_MATH_ATOMIC_NS::memory_order_release); + } + } + + for(std::size_t i = (std::max)(static_cast<std::size_t>(max_bernoulli_b2n<T>::value + 1), start); i < start + n; ++i) + { + *out = (i >= m_overflow_limit) ? policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol) : bn[static_cast<typename container_type::size_type>(i)]; + ++out; + } + + #endif + return out; + } + + template <class OutputIterator> + OutputIterator copy_tangent_numbers(OutputIterator out, std::size_t start, std::size_t n, const Policy& pol) + { + // + // There are basically 3 thread safety options: + // + // 1) There are no threads (BOOST_HAS_THREADS is not defined). + // 2) There are threads, but we do not have a true atomic integer type, + // in this case we just use a mutex to guard against race conditions. + // 3) There are threads, and we have an atomic integer: in this case we can + // use the double-checked locking pattern to avoid thread synchronisation + // when accessing values already in the cache. + // + // + // First off handle the common case for overflow and/or asymptotic expansion: + // + if(start + n > bn.capacity()) + { + if(start < bn.capacity()) + { + out = copy_tangent_numbers(out, start, bn.capacity() - start, pol); + n -= bn.capacity() - start; + start = static_cast<std::size_t>(bn.capacity()); + } + if(start < b2n_overflow_limit<T, Policy>() + 2u) + { + for(; n; ++start, --n) + { + *out = t2n_asymptotic<T, Policy>(static_cast<typename container_type::size_type>(start)); + ++out; + } + } + for(; n; ++start, --n) + { + *out = policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(start), pol); + ++out; + } + return out; + } + #if !defined(BOOST_HAS_THREADS) + // + // Single threaded code, very simple: + // + if(m_current_precision < boost::math::tools::digits<T>()) + { + bn.clear(); + tn.clear(); + m_intermediates.clear(); + m_current_precision = boost::math::tools::digits<T>(); + } + if(start + n >= bn.size()) + { + std::size_t new_size = (std::min)((std::max)((std::max)(start + n, std::size_t(bn.size() + 20)), std::size_t(50)), std::size_t(bn.capacity())); + tangent_numbers_series(new_size); + } + + for(std::size_t i = start; i < start + n; ++i) + { + if(i >= m_overflow_limit) + *out = policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol); + else + { + if(tools::max_value<T>() * tangent_scale_factor<T>() < tn[static_cast<typename container_type::size_type>(i)]) + *out = policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol); + else + *out = tn[static_cast<typename container_type::size_type>(i)] / tangent_scale_factor<T>(); + } + ++out; + } + #elif defined(BOOST_MATH_NO_ATOMIC_INT) + // + // We need to grab a mutex every time we get here, for both readers and writers: + // + boost::detail::lightweight_mutex::scoped_lock l(m_mutex); + if(m_current_precision < boost::math::tools::digits<T>()) + { + bn.clear(); + tn.clear(); + m_intermediates.clear(); + m_current_precision = boost::math::tools::digits<T>(); + } + if(start + n >= bn.size()) + { + std::size_t new_size = (std::min)((std::max)((std::max)(start + n, std::size_t(bn.size() + 20)), std::size_t(50)), std::size_t(bn.capacity())); + tangent_numbers_series(new_size); + } + + for(std::size_t i = start; i < start + n; ++i) + { + if(i >= m_overflow_limit) + *out = policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol); + else + { + if(tools::max_value<T>() * tangent_scale_factor<T>() < tn[static_cast<typename container_type::size_type>(i)]) + *out = policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol); + else + *out = tn[static_cast<typename container_type::size_type>(i)] / tangent_scale_factor<T>(); + } + ++out; + } + + #else + // + // Double-checked locking pattern, lets us access cached already cached values + // without locking: + // + // Get the counter and see if we need to calculate more constants: + // + if((static_cast<std::size_t>(m_counter.load(BOOST_MATH_ATOMIC_NS::memory_order_consume)) < start + n) + || (static_cast<int>(m_current_precision.load(BOOST_MATH_ATOMIC_NS::memory_order_consume)) < boost::math::tools::digits<T>())) + { + boost::detail::lightweight_mutex::scoped_lock l(m_mutex); + + if((static_cast<std::size_t>(m_counter.load(BOOST_MATH_ATOMIC_NS::memory_order_consume)) < start + n) + || (static_cast<int>(m_current_precision.load(BOOST_MATH_ATOMIC_NS::memory_order_consume)) < boost::math::tools::digits<T>())) + { + if(static_cast<int>(m_current_precision.load(BOOST_MATH_ATOMIC_NS::memory_order_consume)) < boost::math::tools::digits<T>()) + { + bn.clear(); + tn.clear(); + m_intermediates.clear(); + m_counter.store(0, BOOST_MATH_ATOMIC_NS::memory_order_release); + m_current_precision = boost::math::tools::digits<T>(); + } + if(start + n >= bn.size()) + { + std::size_t new_size = (std::min)((std::max)((std::max)(start + n, std::size_t(bn.size() + 20)), std::size_t(50)), std::size_t(bn.capacity())); + tangent_numbers_series(new_size); + } + m_counter.store(static_cast<atomic_integer_type>(bn.size()), BOOST_MATH_ATOMIC_NS::memory_order_release); + } + } + + for(std::size_t i = start; i < start + n; ++i) + { + if(i >= m_overflow_limit) + *out = policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol); + else + { + if(tools::max_value<T>() * tangent_scale_factor<T>() < tn[static_cast<typename container_type::size_type>(i)]) + *out = policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol); + else + *out = tn[static_cast<typename container_type::size_type>(i)] / tangent_scale_factor<T>(); + } + ++out; + } + + #endif + return out; + } + +private: + // + // The caches for Bernoulli and tangent numbers, once allocated, + // these must NEVER EVER reallocate as it breaks our thread + // safety guarantees: + // + fixed_vector<T> bn, tn; + std::vector<T> m_intermediates; + // The value at which we know overflow has already occurred for the Bn: + std::size_t m_overflow_limit; +#if !defined(BOOST_HAS_THREADS) + int m_current_precision; +#elif defined(BOOST_MATH_NO_ATOMIC_INT) + boost::detail::lightweight_mutex m_mutex; + int m_current_precision; +#else + boost::detail::lightweight_mutex m_mutex; + atomic_counter_type m_counter, m_current_precision; +#endif +}; + +template <class T, class Policy> +inline bernoulli_numbers_cache<T, Policy>& get_bernoulli_numbers_cache() +{ + // + // Force this function to be called at program startup so all the static variables + // get initailzed then (thread safety). + // + bernoulli_initializer<T, Policy>::force_instantiate(); + static bernoulli_numbers_cache<T, Policy> data; + return data; +} + +}}} + +#endif // BOOST_MATH_BERNOULLI_DETAIL_HPP diff --git a/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_i0.hpp b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_i0.hpp new file mode 100644 index 00000000000..30b89e6a473 --- /dev/null +++ b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_i0.hpp @@ -0,0 +1,564 @@ +// Copyright (c) 2006 Xiaogang Zhang +// Copyright (c) 2017 John Maddock +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_BESSEL_I0_HPP +#define BOOST_MATH_BESSEL_I0_HPP + +#ifdef _MSC_VER +#pragma once +#endif + +#include <boost/math/tools/rational.hpp> +#include <boost/math/tools/big_constant.hpp> +#include <boost/assert.hpp> + +#if defined(__GNUC__) && defined(BOOST_MATH_USE_FLOAT128) +// +// This is the only way we can avoid +// warning: non-standard suffix on floating constant [-Wpedantic] +// when building with -Wall -pedantic. Neither __extension__ +// nor #pragma dianostic ignored work :( +// +#pragma GCC system_header +#endif + +// Modified Bessel function of the first kind of order zero +// we use the approximating forms derived in: +// "Rational Approximations for the Modified Bessel Function of the First Kind - I0(x) for Computations with Double Precision" +// by Pavel Holoborodko, +// see http://www.advanpix.com/2015/11/11/rational-approximations-for-the-modified-bessel-function-of-the-first-kind-i0-computations-double-precision +// The actual coefficients used are our own, and extend Pavel's work to precision's other than double. + +namespace boost { namespace math { namespace detail{ + +template <typename T> +T bessel_i0(const T& x); + +template <class T, class tag> +struct bessel_i0_initializer +{ + struct init + { + init() + { + do_init(tag()); + } + static void do_init(const mpl::int_<64>&) + { + bessel_i0(T(1)); + bessel_i0(T(8)); + bessel_i0(T(12)); + bessel_i0(T(40)); + bessel_i0(T(101)); + } + static void do_init(const mpl::int_<113>&) + { + bessel_i0(T(1)); + bessel_i0(T(10)); + bessel_i0(T(20)); + bessel_i0(T(40)); + bessel_i0(T(101)); + } + template <class U> + static void do_init(const U&) {} + void force_instantiate()const {} + }; + static const init initializer; + static void force_instantiate() + { + initializer.force_instantiate(); + } +}; + +template <class T, class tag> +const typename bessel_i0_initializer<T, tag>::init bessel_i0_initializer<T, tag>::initializer; + +template <typename T, int N> +T bessel_i0_imp(const T&, const mpl::int_<N>&) +{ + BOOST_ASSERT(0); + return 0; +} + +template <typename T> +T bessel_i0_imp(const T& x, const mpl::int_<24>&) +{ + BOOST_MATH_STD_USING + if(x < 7.75) + { + // Max error in interpolated form: 3.929e-08 + // Max Error found at float precision = Poly: 1.991226e-07 + static const float P[] = { + 1.00000003928615375e+00f, + 2.49999576572179639e-01f, + 2.77785268558399407e-02f, + 1.73560257755821695e-03f, + 6.96166518788906424e-05f, + 1.89645733877137904e-06f, + 4.29455004657565361e-08f, + 3.90565476357034480e-10f, + 1.48095934745267240e-11f + }; + T a = x * x / 4; + return a * boost::math::tools::evaluate_polynomial(P, a) + 1; + } + else if(x < 50) + { + // Max error in interpolated form: 5.195e-08 + // Max Error found at float precision = Poly: 8.502534e-08 + static const float P[] = { + 3.98942651588301770e-01f, + 4.98327234176892844e-02f, + 2.91866904423115499e-02f, + 1.35614940793742178e-02f, + 1.31409251787866793e-01f + }; + return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); + } + else + { + // Max error in interpolated form: 1.782e-09 + // Max Error found at float precision = Poly: 6.473568e-08 + static const float P[] = { + 3.98942391532752700e-01f, + 4.98455950638200020e-02f, + 2.94835666900682535e-02f + }; + T ex = exp(x / 2); + T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); + result *= ex; + return result; + } +} + +template <typename T> +T bessel_i0_imp(const T& x, const mpl::int_<53>&) +{ + BOOST_MATH_STD_USING + if(x < 7.75) + { + // Bessel I0 over[10 ^ -16, 7.75] + // Max error in interpolated form : 3.042e-18 + // Max Error found at double precision = Poly : 5.106609e-16 Cheb : 5.239199e-16 + static const double P[] = { + 1.00000000000000000e+00, + 2.49999999999999909e-01, + 2.77777777777782257e-02, + 1.73611111111023792e-03, + 6.94444444453352521e-05, + 1.92901234513219920e-06, + 3.93675991102510739e-08, + 6.15118672704439289e-10, + 7.59407002058973446e-12, + 7.59389793369836367e-14, + 6.27767773636292611e-16, + 4.34709704153272287e-18, + 2.63417742690109154e-20, + 1.13943037744822825e-22, + 9.07926920085624812e-25 + }; + T a = x * x / 4; + return a * boost::math::tools::evaluate_polynomial(P, a) + 1; + } + else if(x < 500) + { + // Max error in interpolated form : 1.685e-16 + // Max Error found at double precision = Poly : 2.575063e-16 Cheb : 2.247615e+00 + static const double P[] = { + 3.98942280401425088e-01, + 4.98677850604961985e-02, + 2.80506233928312623e-02, + 2.92211225166047873e-02, + 4.44207299493659561e-02, + 1.30970574605856719e-01, + -3.35052280231727022e+00, + 2.33025711583514727e+02, + -1.13366350697172355e+04, + 4.24057674317867331e+05, + -1.23157028595698731e+07, + 2.80231938155267516e+08, + -5.01883999713777929e+09, + 7.08029243015109113e+10, + -7.84261082124811106e+11, + 6.76825737854096565e+12, + -4.49034849696138065e+13, + 2.24155239966958995e+14, + -8.13426467865659318e+14, + 2.02391097391687777e+15, + -3.08675715295370878e+15, + 2.17587543863819074e+15 + }; + return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); + } + else + { + // Max error in interpolated form : 2.437e-18 + // Max Error found at double precision = Poly : 1.216719e-16 + static const double P[] = { + 3.98942280401432905e-01, + 4.98677850491434560e-02, + 2.80506308916506102e-02, + 2.92179096853915176e-02, + 4.53371208762579442e-02 + }; + T ex = exp(x / 2); + T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); + result *= ex; + return result; + } +} + +template <typename T> +T bessel_i0_imp(const T& x, const mpl::int_<64>&) +{ + BOOST_MATH_STD_USING + if(x < 7.75) + { + // Bessel I0 over[10 ^ -16, 7.75] + // Max error in interpolated form : 3.899e-20 + // Max Error found at float80 precision = Poly : 1.770840e-19 + static const T P[] = { + BOOST_MATH_BIG_CONSTANT(T, 64, 9.99999999999999999961011629e-01), + BOOST_MATH_BIG_CONSTANT(T, 64, 2.50000000000000001321873912e-01), + BOOST_MATH_BIG_CONSTANT(T, 64, 2.77777777777777703400424216e-02), + BOOST_MATH_BIG_CONSTANT(T, 64, 1.73611111111112764793802701e-03), + BOOST_MATH_BIG_CONSTANT(T, 64, 6.94444444444251461247253525e-05), + BOOST_MATH_BIG_CONSTANT(T, 64, 1.92901234569262206386118739e-06), + BOOST_MATH_BIG_CONSTANT(T, 64, 3.93675988851131457141005209e-08), + BOOST_MATH_BIG_CONSTANT(T, 64, 6.15118734688297476454205352e-10), + BOOST_MATH_BIG_CONSTANT(T, 64, 7.59405797058091016449222685e-12), + BOOST_MATH_BIG_CONSTANT(T, 64, 7.59406599631719800679835140e-14), + BOOST_MATH_BIG_CONSTANT(T, 64, 6.27598961062070013516660425e-16), + BOOST_MATH_BIG_CONSTANT(T, 64, 4.35920318970387940278362992e-18), + BOOST_MATH_BIG_CONSTANT(T, 64, 2.57372492687715452949437981e-20), + BOOST_MATH_BIG_CONSTANT(T, 64, 1.33908663475949906992942204e-22), + BOOST_MATH_BIG_CONSTANT(T, 64, 5.15976668870980234582896010e-25), + BOOST_MATH_BIG_CONSTANT(T, 64, 3.46240478946376069211156548e-27) + }; + T a = x * x / 4; + return a * boost::math::tools::evaluate_polynomial(P, a) + 1; + } + else if(x < 10) + { + // Maximum Deviation Found: 6.906e-21 + // Expected Error Term : -6.903e-21 + // Maximum Relative Change in Control Points : 1.631e-04 + // Max Error found at float80 precision = Poly : 7.811948e-21 + static const T Y = 4.051098823547363281250e-01f; + static const T P[] = { + BOOST_MATH_BIG_CONSTANT(T, 64, -6.158081780620616479492e-03), + BOOST_MATH_BIG_CONSTANT(T, 64, 4.883635969834048766148e-02), + BOOST_MATH_BIG_CONSTANT(T, 64, 7.892782002476195771920e-02), + BOOST_MATH_BIG_CONSTANT(T, 64, -1.478784996478070170327e+00), + BOOST_MATH_BIG_CONSTANT(T, 64, 2.988611837308006851257e+01), + BOOST_MATH_BIG_CONSTANT(T, 64, -4.140133766747436806179e+02), + BOOST_MATH_BIG_CONSTANT(T, 64, 4.117316447921276453271e+03), + BOOST_MATH_BIG_CONSTANT(T, 64, -2.942353667455141676001e+04), + BOOST_MATH_BIG_CONSTANT(T, 64, 1.493482682461387081534e+05), + BOOST_MATH_BIG_CONSTANT(T, 64, -5.228100538921466124653e+05), + BOOST_MATH_BIG_CONSTANT(T, 64, 1.195279248600467989454e+06), + BOOST_MATH_BIG_CONSTANT(T, 64, -1.601530760654337045917e+06), + BOOST_MATH_BIG_CONSTANT(T, 64, 9.504921137873298402679e+05) + }; + return exp(x) * (boost::math::tools::evaluate_polynomial(P, T(1 / x)) + Y) / sqrt(x); + } + else if(x < 15) + { + // Maximum Deviation Found: 4.083e-21 + // Expected Error Term : -4.025e-21 + // Maximum Relative Change in Control Points : 1.304e-03 + // Max Error found at float80 precision = Poly : 2.303527e-20 + static const T Y = 4.033188819885253906250e-01f; + static const T P[] = { + BOOST_MATH_BIG_CONSTANT(T, 64, -4.376373876116109401062e-03), + BOOST_MATH_BIG_CONSTANT(T, 64, 4.982899138682911273321e-02), + BOOST_MATH_BIG_CONSTANT(T, 64, 3.109477529533515397644e-02), + BOOST_MATH_BIG_CONSTANT(T, 64, -1.163760580110576407673e-01), + BOOST_MATH_BIG_CONSTANT(T, 64, 4.776501832837367371883e+00), + BOOST_MATH_BIG_CONSTANT(T, 64, -1.101478069227776656318e+02), + BOOST_MATH_BIG_CONSTANT(T, 64, 1.892071912448960299773e+03), + BOOST_MATH_BIG_CONSTANT(T, 64, -2.417739279982328117483e+04), + BOOST_MATH_BIG_CONSTANT(T, 64, 2.296963447724067390552e+05), + BOOST_MATH_BIG_CONSTANT(T, 64, -1.598589306710589358747e+06), + BOOST_MATH_BIG_CONSTANT(T, 64, 7.903662411851774878322e+06), + BOOST_MATH_BIG_CONSTANT(T, 64, -2.622677059040339516093e+07), + BOOST_MATH_BIG_CONSTANT(T, 64, 5.227776578828667629347e+07), + BOOST_MATH_BIG_CONSTANT(T, 64, -4.727797957441040896878e+07) + }; + return exp(x) * (boost::math::tools::evaluate_polynomial(P, T(1 / x)) + Y) / sqrt(x); + } + else if(x < 50) + { + // Max error in interpolated form: 1.035e-21 + // Max Error found at float80 precision = Poly: 1.885872e-21 + static const T Y = 4.011702537536621093750e-01f; + static const T P[] = { + BOOST_MATH_BIG_CONSTANT(T, 64, -2.227973351806078464328e-03), + BOOST_MATH_BIG_CONSTANT(T, 64, 4.986778486088017419036e-02), + BOOST_MATH_BIG_CONSTANT(T, 64, 2.805066823812285310011e-02), + BOOST_MATH_BIG_CONSTANT(T, 64, 2.921443721160964964623e-02), + BOOST_MATH_BIG_CONSTANT(T, 64, 4.517504941996594744052e-02), + BOOST_MATH_BIG_CONSTANT(T, 64, 6.316922639868793684401e-02), + BOOST_MATH_BIG_CONSTANT(T, 64, 1.535891099168810015433e+00), + BOOST_MATH_BIG_CONSTANT(T, 64, -4.706078229522448308087e+01), + BOOST_MATH_BIG_CONSTANT(T, 64, 1.351015763079160914632e+03), + BOOST_MATH_BIG_CONSTANT(T, 64, -2.948809013999277355098e+04), + BOOST_MATH_BIG_CONSTANT(T, 64, 4.967598958582595361757e+05), + BOOST_MATH_BIG_CONSTANT(T, 64, -6.346924657995383019558e+06), + BOOST_MATH_BIG_CONSTANT(T, 64, 5.998794574259956613472e+07), + BOOST_MATH_BIG_CONSTANT(T, 64, -4.016371355801690142095e+08), + BOOST_MATH_BIG_CONSTANT(T, 64, 1.768791455631826490838e+09), + BOOST_MATH_BIG_CONSTANT(T, 64, -4.441995678177349895640e+09), + BOOST_MATH_BIG_CONSTANT(T, 64, 4.482292669974971387738e+09) + }; + return exp(x) * (boost::math::tools::evaluate_polynomial(P, T(1 / x)) + Y) / sqrt(x); + } + else + { + // Bessel I0 over[50, INF] + // Max error in interpolated form : 5.587e-20 + // Max Error found at float80 precision = Poly : 8.776852e-20 + static const T P[] = { + BOOST_MATH_BIG_CONSTANT(T, 64, 3.98942280401432677955074061e-01), + BOOST_MATH_BIG_CONSTANT(T, 64, 4.98677850501789875615574058e-02), + BOOST_MATH_BIG_CONSTANT(T, 64, 2.80506290908675604202206833e-02), + BOOST_MATH_BIG_CONSTANT(T, 64, 2.92194052159035901631494784e-02), + BOOST_MATH_BIG_CONSTANT(T, 64, 4.47422430732256364094681137e-02), + BOOST_MATH_BIG_CONSTANT(T, 64, 9.05971614435738691235525172e-02), + BOOST_MATH_BIG_CONSTANT(T, 64, 2.29180522595459823234266708e-01), + BOOST_MATH_BIG_CONSTANT(T, 64, 6.15122547776140254569073131e-01), + BOOST_MATH_BIG_CONSTANT(T, 64, 7.48491812136365376477357324e+00), + BOOST_MATH_BIG_CONSTANT(T, 64, -2.45569740166506688169730713e+02), + BOOST_MATH_BIG_CONSTANT(T, 64, 9.66857566379480730407063170e+03), + BOOST_MATH_BIG_CONSTANT(T, 64, -2.71924083955641197750323901e+05), + BOOST_MATH_BIG_CONSTANT(T, 64, 5.74276685704579268845870586e+06), + BOOST_MATH_BIG_CONSTANT(T, 64, -8.89753803265734681907148778e+07), + BOOST_MATH_BIG_CONSTANT(T, 64, 9.82590905134996782086242180e+08), + BOOST_MATH_BIG_CONSTANT(T, 64, -7.30623197145529889358596301e+09), + BOOST_MATH_BIG_CONSTANT(T, 64, 3.27310000726207055200805893e+10), + BOOST_MATH_BIG_CONSTANT(T, 64, -6.64365417189215599168817064e+10) + }; + T ex = exp(x / 2); + T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); + result *= ex; + return result; + } +} + +template <typename T> +T bessel_i0_imp(const T& x, const mpl::int_<113>&) +{ + BOOST_MATH_STD_USING + if(x < 7.75) + { + // Bessel I0 over[10 ^ -34, 7.75] + // Max error in interpolated form : 1.274e-34 + // Max Error found at float128 precision = Poly : 3.096091e-34 + static const T P[] = { + BOOST_MATH_BIG_CONSTANT(T, 113, 1.0000000000000000000000000000000001273856e+00), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.4999999999999999999999999999999107477496e-01), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.7777777777777777777777777777881795230918e-02), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.7361111111111111111111111106290091648808e-03), + BOOST_MATH_BIG_CONSTANT(T, 113, 6.9444444444444444444444445629960334523101e-05), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.9290123456790123456790105563456483249753e-06), + BOOST_MATH_BIG_CONSTANT(T, 113, 3.9367598891408415217940836339080514004844e-08), + BOOST_MATH_BIG_CONSTANT(T, 113, 6.1511873267825648777900014857992724731476e-10), + BOOST_MATH_BIG_CONSTANT(T, 113, 7.5940584281266233066162999610732449709209e-12), + BOOST_MATH_BIG_CONSTANT(T, 113, 7.5940584281266232783124723601470051895304e-14), + BOOST_MATH_BIG_CONSTANT(T, 113, 6.2760813455591936763439337059117957836078e-16), + BOOST_MATH_BIG_CONSTANT(T, 113, 4.3583898233049738471136482147779094353096e-18), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.5789288895299965395422423848480340736308e-20), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.3157800456718804437960453545507623434606e-22), + BOOST_MATH_BIG_CONSTANT(T, 113, 5.8479113149412360748032684260932041506493e-25), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.2843403488398038539283241944594140493394e-27), + BOOST_MATH_BIG_CONSTANT(T, 113, 7.9042925594356556196790242908697582021825e-30), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.4395919891312152120710245152115597111101e-32), + BOOST_MATH_BIG_CONSTANT(T, 113, 6.7580986145276689333214547502373003196707e-35), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.6886514018062348877723837017198859723889e-37), + BOOST_MATH_BIG_CONSTANT(T, 113, 3.8540558465757554512570197585002702777999e-40), + BOOST_MATH_BIG_CONSTANT(T, 113, 7.4684706070226893763741850944911705726436e-43), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.0210715309399646335858150349406935414314e-45) + }; + T a = x * x / 4; + return a * boost::math::tools::evaluate_polynomial(P, a) + 1; + } + else if(x < 15) + { + // Bessel I0 over[7.75, 15] + // Max error in interpolated form : 7.534e-35 + // Max Error found at float128 precision = Poly : 6.123912e-34 + static const T P[] = { + BOOST_MATH_BIG_CONSTANT(T, 113, 9.9999999999999999992388573069504617493518e-01), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.5000000000000000007304739268173096975340e-01), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.7777777777777777744261405400543564492074e-02), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.7361111111111111209006987259719750726867e-03), + BOOST_MATH_BIG_CONSTANT(T, 113, 6.9444444444444442399703186871329381908321e-05), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.9290123456790126709286741580242189785431e-06), + BOOST_MATH_BIG_CONSTANT(T, 113, 3.9367598891408374246503061422528266924389e-08), + BOOST_MATH_BIG_CONSTANT(T, 113, 6.1511873267826068395343047827801353170966e-10), + BOOST_MATH_BIG_CONSTANT(T, 113, 7.5940584281262673459688011737168286944521e-12), + BOOST_MATH_BIG_CONSTANT(T, 113, 7.5940584281291583769928563167645746144508e-14), + BOOST_MATH_BIG_CONSTANT(T, 113, 6.2760813455438840231126529638737436950274e-16), + BOOST_MATH_BIG_CONSTANT(T, 113, 4.3583898233839583885132809584770578894948e-18), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.5789288891798658971960571838369339742994e-20), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.3157800470129311623308216856009970266088e-22), + BOOST_MATH_BIG_CONSTANT(T, 113, 5.8479112701534604520063520412207286692581e-25), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.2843404822552330714586265081801727491890e-27), + BOOST_MATH_BIG_CONSTANT(T, 113, 7.9042888166225242675881424439818162458179e-30), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.4396027771820721384198604723320045236973e-32), + BOOST_MATH_BIG_CONSTANT(T, 113, 6.7577659910606076328136207973456511895030e-35), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.6896548123724136624716224328803899914646e-37), + BOOST_MATH_BIG_CONSTANT(T, 113, 3.8285850162160539150210466453921758781984e-40), + BOOST_MATH_BIG_CONSTANT(T, 113, 7.9419071894227736216423562425429524883562e-43), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.4720374049498608905571855665134539425038e-45), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.7763533278527958112907118930154738930378e-48), + BOOST_MATH_BIG_CONSTANT(T, 113, 3.1213839473168678646697528580511702663617e-51), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.0648035313124146852372607519737686740964e-53), + -BOOST_MATH_BIG_CONSTANT(T, 113, 5.1255595184052024349371058585102280860878e-57), + BOOST_MATH_BIG_CONSTANT(T, 113, 3.4652470895944157957727948355523715335882e-59) + }; + T a = x * x / 4; + return a * boost::math::tools::evaluate_polynomial(P, a) + 1; + } + else if(x < 30) + { + // Max error in interpolated form : 1.808e-34 + // Max Error found at float128 precision = Poly : 2.399403e-34 + static const T P[] = { + BOOST_MATH_BIG_CONSTANT(T, 113, 3.9894228040870793650581242239624530714032e-01), + BOOST_MATH_BIG_CONSTANT(T, 113, 4.9867780576714783790784348982178607842250e-02), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.8051948347934462928487999569249907599510e-02), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.8971143420388958551176254291160976367263e-02), + BOOST_MATH_BIG_CONSTANT(T, 113, 7.8197359701715582763961322341827341098897e-02), + BOOST_MATH_BIG_CONSTANT(T, 113, -3.3430484862908317377522273217643346601271e+00), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.7884507603213662610604413960838990199224e+02), + BOOST_MATH_BIG_CONSTANT(T, 113, -1.8304926482356755790062999202373909300514e+04), + BOOST_MATH_BIG_CONSTANT(T, 113, 9.8867173178574875515293357145875120137676e+05), + BOOST_MATH_BIG_CONSTANT(T, 113, -4.4261178812193528551544261731796888257644e+07), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.6453010340778116475788083817762403540097e+09), + BOOST_MATH_BIG_CONSTANT(T, 113, -5.0432401330113978669454035365747869477960e+10), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.2462165331309799059332310595587606836357e+12), + BOOST_MATH_BIG_CONSTANT(T, 113, -2.3299800389951335932792950236410844978273e+13), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.5748218240248714177527965706790413406639e+14), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.8330014378766930869945511450377736037385e+15), + BOOST_MATH_BIG_CONSTANT(T, 113, -1.8494610073827453236940544799030787866218e+17), + BOOST_MATH_BIG_CONSTANT(T, 113, 5.7244661371420647691301043350229977856476e+18), + BOOST_MATH_BIG_CONSTANT(T, 113, -1.2386378807889388140099109087465781254321e+20), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.1104000573102013529518477353943384110982e+21), + BOOST_MATH_BIG_CONSTANT(T, 113, -2.9426541092239879262282594572224300191016e+22), + BOOST_MATH_BIG_CONSTANT(T, 113, 3.4061439136301913488512592402635688101020e+23), + BOOST_MATH_BIG_CONSTANT(T, 113, -3.2836554760521986358980180942859101564671e+24), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.6270285589905206294944214795661236766988e+25), + BOOST_MATH_BIG_CONSTANT(T, 113, -1.7278631455211972017740134341610659484259e+26), + BOOST_MATH_BIG_CONSTANT(T, 113, 9.1971734473772196124736986948034978906801e+26), + BOOST_MATH_BIG_CONSTANT(T, 113, -3.8669270707172568763908838463689093500098e+27), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.2368879358870281916900125550129211146626e+28), + BOOST_MATH_BIG_CONSTANT(T, 113, -2.8296235063297831758204519071113999839858e+28), + BOOST_MATH_BIG_CONSTANT(T, 113, 4.1253861666023020670144616019148954773662e+28), + BOOST_MATH_BIG_CONSTANT(T, 113, -2.8809536950051955163648980306847791014734e+28) }; + return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); + } + else if(x < 100) + { + // Bessel I0 over[30, 100] + // Max error in interpolated form : 1.487e-34 + // Max Error found at float128 precision = Poly : 1.929924e-34 + static const T P[] = { + BOOST_MATH_BIG_CONSTANT(T, 113, 3.9894228040143267793996798658172135362278e-01), + BOOST_MATH_BIG_CONSTANT(T, 113, 4.9867785050179084714910130342157246539820e-02), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.8050629090725751585266360464766768437048e-02), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.9219405302833158254515212437025679637597e-02), + BOOST_MATH_BIG_CONSTANT(T, 113, 4.4742214371598631578107310396249912330627e-02), + BOOST_MATH_BIG_CONSTANT(T, 113, 9.0602983776478659136184969363625092585520e-02), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.2839507231977478205885469900971893734770e-01), + BOOST_MATH_BIG_CONSTANT(T, 113, 6.8925739165733823730525449511456529001868e-01), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.4238082222874015159424842335385854632223e+00), + BOOST_MATH_BIG_CONSTANT(T, 113, 9.6759648427182491050716309699208988458050e+00), + BOOST_MATH_BIG_CONSTANT(T, 113, 4.7292246491169360014875196108746167872215e+01), + BOOST_MATH_BIG_CONSTANT(T, 113, 3.1001411442786230340015781205680362993575e+01), + BOOST_MATH_BIG_CONSTANT(T, 113, 9.8277628835804873490331739499978938078848e+03), + BOOST_MATH_BIG_CONSTANT(T, 113, -3.1208326312801432038715638596517882759639e+05), + BOOST_MATH_BIG_CONSTANT(T, 113, 9.4813611580683862051838126076298945680803e+06), + BOOST_MATH_BIG_CONSTANT(T, 113, -2.1278197693321821164135890132925119054391e+08), + BOOST_MATH_BIG_CONSTANT(T, 113, 3.3190303792682886967459489059860595063574e+09), + BOOST_MATH_BIG_CONSTANT(T, 113, -2.1580767338646580750893606158043485767644e+10), + BOOST_MATH_BIG_CONSTANT(T, 113, -5.0256008808415702780816006134784995506549e+11), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.9044186472918017896554580836514681614475e+13), + BOOST_MATH_BIG_CONSTANT(T, 113, -3.2521078890073151875661384381880225635135e+14), + BOOST_MATH_BIG_CONSTANT(T, 113, 3.3620352486836976842181057590770636605454e+15), + BOOST_MATH_BIG_CONSTANT(T, 113, -2.0375525734060401555856465179734887312420e+16), + BOOST_MATH_BIG_CONSTANT(T, 113, 5.6392664899881014534361728644608549445131e+16) + }; + return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); + } + else + { + // Bessel I0 over[100, INF] + // Max error in interpolated form : 5.459e-35 + // Max Error found at float128 precision = Poly : 1.472240e-34 + static const T P[] = { + BOOST_MATH_BIG_CONSTANT(T, 113, 3.9894228040143267793994605993438166526772e-01), + BOOST_MATH_BIG_CONSTANT(T, 113, 4.9867785050179084742493257495245185241487e-02), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.8050629090725735167652437695397756897920e-02), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.9219405302839307466358297347675795965363e-02), + BOOST_MATH_BIG_CONSTANT(T, 113, 4.4742214369972689474366968442268908028204e-02), + BOOST_MATH_BIG_CONSTANT(T, 113, 9.0602984099194778006610058410222616383078e-02), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.2839502241666629677015839125593079416327e-01), + BOOST_MATH_BIG_CONSTANT(T, 113, 6.8926354981801627920292655818232972385750e-01), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.4231921590621824187100989532173995000655e+00), + BOOST_MATH_BIG_CONSTANT(T, 113, 9.7264260959693775207585700654645245723497e+00), + BOOST_MATH_BIG_CONSTANT(T, 113, 4.3890136225398811195878046856373030127018e+01), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.1999720924619285464910452647408431234369e+02), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.2076909538525038580501368530598517194748e+03), + BOOST_MATH_BIG_CONSTANT(T, 113, 7.5684635141332367730007149159063086133399e+03), + BOOST_MATH_BIG_CONSTANT(T, 113, 3.5178192543258299267923025833141286569141e+04), + BOOST_MATH_BIG_CONSTANT(T, 113, 6.2966297919851965784482163987240461837728e+05) }; + T ex = exp(x / 2); + T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); + result *= ex; + return result; + } +} + +template <typename T> +T bessel_i0_imp(const T& x, const mpl::int_<0>&) +{ + if(boost::math::tools::digits<T>() <= 24) + return bessel_i0_imp(x, mpl::int_<24>()); + else if(boost::math::tools::digits<T>() <= 53) + return bessel_i0_imp(x, mpl::int_<53>()); + else if(boost::math::tools::digits<T>() <= 64) + return bessel_i0_imp(x, mpl::int_<64>()); + else if(boost::math::tools::digits<T>() <= 113) + return bessel_i0_imp(x, mpl::int_<113>()); + BOOST_ASSERT(0); + return 0; +} + +template <typename T> +inline T bessel_i0(const T& x) +{ + typedef mpl::int_< + ((std::numeric_limits<T>::digits == 0) || (std::numeric_limits<T>::radix != 2)) ? + 0 : + std::numeric_limits<T>::digits <= 24 ? + 24 : + std::numeric_limits<T>::digits <= 53 ? + 53 : + std::numeric_limits<T>::digits <= 64 ? + 64 : + std::numeric_limits<T>::digits <= 113 ? + 113 : -1 + > tag_type; + + bessel_i0_initializer<T, tag_type>::force_instantiate(); + return bessel_i0_imp(x, tag_type()); +} + +}}} // namespaces + +#endif // BOOST_MATH_BESSEL_I0_HPP + diff --git a/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_i1.hpp b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_i1.hpp new file mode 100644 index 00000000000..460efbd4610 --- /dev/null +++ b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_i1.hpp @@ -0,0 +1,592 @@ +// Copyright (c) 2017 John Maddock +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// Modified Bessel function of the first kind of order zero +// we use the approximating forms derived in: +// "Rational Approximations for the Modified Bessel Function of the First Kind - I1(x) for Computations with Double Precision" +// by Pavel Holoborodko, +// see http://www.advanpix.com/2015/11/12/rational-approximations-for-the-modified-bessel-function-of-the-first-kind-i1-for-computations-with-double-precision/ +// The actual coefficients used are our own, and extend Pavel's work to precision's other than double. + +#ifndef BOOST_MATH_BESSEL_I1_HPP +#define BOOST_MATH_BESSEL_I1_HPP + +#ifdef _MSC_VER +#pragma once +#endif + +#include <boost/math/tools/rational.hpp> +#include <boost/math/tools/big_constant.hpp> +#include <boost/assert.hpp> + +#if defined(__GNUC__) && defined(BOOST_MATH_USE_FLOAT128) +// +// This is the only way we can avoid +// warning: non-standard suffix on floating constant [-Wpedantic] +// when building with -Wall -pedantic. Neither __extension__ +// nor #pragma dianostic ignored work :( +// +#pragma GCC system_header +#endif + +// Modified Bessel function of the first kind of order one +// minimax rational approximations on intervals, see +// Blair and Edwards, Chalk River Report AECL-4928, 1974 + +namespace boost { namespace math { namespace detail{ + +template <typename T> +T bessel_i1(const T& x); + +template <class T, class tag> +struct bessel_i1_initializer +{ + struct init + { + init() + { + do_init(tag()); + } + static void do_init(const mpl::int_<64>&) + { + bessel_i1(T(1)); + bessel_i1(T(15)); + bessel_i1(T(80)); + bessel_i1(T(101)); + } + static void do_init(const mpl::int_<113>&) + { + bessel_i1(T(1)); + bessel_i1(T(10)); + bessel_i1(T(14)); + bessel_i1(T(19)); + bessel_i1(T(34)); + bessel_i1(T(99)); + bessel_i1(T(101)); + } + template <class U> + static void do_init(const U&) {} + void force_instantiate()const{} + }; + static const init initializer; + static void force_instantiate() + { + initializer.force_instantiate(); + } +}; + +template <class T, class tag> +const typename bessel_i1_initializer<T, tag>::init bessel_i1_initializer<T, tag>::initializer; + +template <typename T, int N> +T bessel_i1_imp(const T&, const mpl::int_<N>&) +{ + BOOST_ASSERT(0); + return 0; +} + +template <typename T> +T bessel_i1_imp(const T& x, const mpl::int_<24>&) +{ + BOOST_MATH_STD_USING + if(x < 7.75) + { + //Max error in interpolated form : 1.348e-08 + // Max Error found at float precision = Poly : 1.469121e-07 + static const float P[] = { + 8.333333221e-02f, + 6.944453712e-03f, + 3.472097211e-04f, + 1.158047174e-05f, + 2.739745142e-07f, + 5.135884609e-09f, + 5.262251502e-11f, + 1.331933703e-12f + }; + T a = x * x / 4; + T Q[3] = { 1, 0.5f, boost::math::tools::evaluate_polynomial(P, a) }; + return x * boost::math::tools::evaluate_polynomial(Q, a) / 2; + } + else + { + // Max error in interpolated form: 9.000e-08 + // Max Error found at float precision = Poly: 1.044345e-07 + + static const float P[] = { + 3.98942115977513013e-01f, + -1.49581264836620262e-01f, + -4.76475741878486795e-02f, + -2.65157315524784407e-02f, + -1.47148600683672014e-01f + }; + T ex = exp(x / 2); + T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); + result *= ex; + return result; + } +} + +template <typename T> +T bessel_i1_imp(const T& x, const mpl::int_<53>&) +{ + BOOST_MATH_STD_USING + if(x < 7.75) + { + // Bessel I0 over[10 ^ -16, 7.75] + // Max error in interpolated form: 5.639e-17 + // Max Error found at double precision = Poly: 1.795559e-16 + + static const double P[] = { + 8.333333333333333803e-02, + 6.944444444444341983e-03, + 3.472222222225921045e-04, + 1.157407407354987232e-05, + 2.755731926254790268e-07, + 4.920949692800671435e-09, + 6.834657311305621830e-11, + 7.593969849687574339e-13, + 6.904822652741917551e-15, + 5.220157095351373194e-17, + 3.410720494727771276e-19, + 1.625212890947171108e-21, + 1.332898928162290861e-23 + }; + T a = x * x / 4; + T Q[3] = { 1, 0.5f, boost::math::tools::evaluate_polynomial(P, a) }; + return x * boost::math::tools::evaluate_polynomial(Q, a) / 2; + } + else if(x < 500) + { + // Max error in interpolated form: 1.796e-16 + // Max Error found at double precision = Poly: 2.898731e-16 + + static const double P[] = { + 3.989422804014406054e-01, + -1.496033551613111533e-01, + -4.675104253598537322e-02, + -4.090895951581637791e-02, + -5.719036414430205390e-02, + -1.528189554374492735e-01, + 3.458284470977172076e+00, + -2.426181371595021021e+02, + 1.178785865993440669e+04, + -4.404655582443487334e+05, + 1.277677779341446497e+07, + -2.903390398236656519e+08, + 5.192386898222206474e+09, + -7.313784438967834057e+10, + 8.087824484994859552e+11, + -6.967602516005787001e+12, + 4.614040809616582764e+13, + -2.298849639457172489e+14, + 8.325554073334618015e+14, + -2.067285045778906105e+15, + 3.146401654361325073e+15, + -2.213318202179221945e+15 + }; + return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); + } + else + { + // Max error in interpolated form: 1.320e-19 + // Max Error found at double precision = Poly: 7.065357e-17 + static const double P[] = { + 3.989422804014314820e-01, + -1.496033551467584157e-01, + -4.675105322571775911e-02, + -4.090421597376992892e-02, + -5.843630344778927582e-02 + }; + T ex = exp(x / 2); + T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); + result *= ex; + return result; + } +} + +template <typename T> +T bessel_i1_imp(const T& x, const mpl::int_<64>&) +{ + BOOST_MATH_STD_USING + if(x < 7.75) + { + // Bessel I0 over[10 ^ -16, 7.75] + // Max error in interpolated form: 8.086e-21 + // Max Error found at float80 precision = Poly: 7.225090e-20 + static const T P[] = { + BOOST_MATH_BIG_CONSTANT(T, 64, 8.33333333333333333340071817e-02), + BOOST_MATH_BIG_CONSTANT(T, 64, 6.94444444444444442462728070e-03), + BOOST_MATH_BIG_CONSTANT(T, 64, 3.47222222222222318886683883e-04), + BOOST_MATH_BIG_CONSTANT(T, 64, 1.15740740740738880709555060e-05), + BOOST_MATH_BIG_CONSTANT(T, 64, 2.75573192240046222242685145e-07), + BOOST_MATH_BIG_CONSTANT(T, 64, 4.92094986131253986838697503e-09), + BOOST_MATH_BIG_CONSTANT(T, 64, 6.83465258979924922633502182e-11), + BOOST_MATH_BIG_CONSTANT(T, 64, 7.59405830675154933645967137e-13), + BOOST_MATH_BIG_CONSTANT(T, 64, 6.90369179710633344508897178e-15), + BOOST_MATH_BIG_CONSTANT(T, 64, 5.23003610041709452814262671e-17), + BOOST_MATH_BIG_CONSTANT(T, 64, 3.35291901027762552549170038e-19), + BOOST_MATH_BIG_CONSTANT(T, 64, 1.83991379419781823063672109e-21), + BOOST_MATH_BIG_CONSTANT(T, 64, 8.87732714140192556332037815e-24), + BOOST_MATH_BIG_CONSTANT(T, 64, 3.32120654663773147206454247e-26), + BOOST_MATH_BIG_CONSTANT(T, 64, 1.95294659305369207813486871e-28) + }; + T a = x * x / 4; + T Q[3] = { 1, 0.5f, boost::math::tools::evaluate_polynomial(P, a) }; + return x * boost::math::tools::evaluate_polynomial(Q, a) / 2; + } + else if(x < 20) + { + // Max error in interpolated form: 4.258e-20 + // Max Error found at float80 precision = Poly: 2.851105e-19 + // Maximum Deviation Found : 3.887e-20 + // Expected Error Term : 3.887e-20 + // Maximum Relative Change in Control Points : 1.681e-04 + static const T P[] = { + BOOST_MATH_BIG_CONSTANT(T, 64, 3.98942260530218897338680e-01), + BOOST_MATH_BIG_CONSTANT(T, 64, -1.49599542849073670179540e-01), + BOOST_MATH_BIG_CONSTANT(T, 64, -4.70492865454119188276875e-02), + BOOST_MATH_BIG_CONSTANT(T, 64, -3.12389893307392002405869e-02), + BOOST_MATH_BIG_CONSTANT(T, 64, 1.49696126385202602071197e-01), + BOOST_MATH_BIG_CONSTANT(T, 64, -3.84206507612717711565967e+01), + BOOST_MATH_BIG_CONSTANT(T, 64, 2.14748094784412558689584e+03), + BOOST_MATH_BIG_CONSTANT(T, 64, -7.70652726663596993005669e+04), + BOOST_MATH_BIG_CONSTANT(T, 64, 2.01659736164815617174439e+06), + BOOST_MATH_BIG_CONSTANT(T, 64, -4.04740659606466305607544e+07), + BOOST_MATH_BIG_CONSTANT(T, 64, 6.38383394696382837263656e+08), + BOOST_MATH_BIG_CONSTANT(T, 64, -8.00779638649147623107378e+09), + BOOST_MATH_BIG_CONSTANT(T, 64, 8.02338237858684714480491e+10), + BOOST_MATH_BIG_CONSTANT(T, 64, -6.41198553664947312995879e+11), + BOOST_MATH_BIG_CONSTANT(T, 64, 4.05915186909564986897554e+12), + BOOST_MATH_BIG_CONSTANT(T, 64, -2.00907636964168581116181e+13), + BOOST_MATH_BIG_CONSTANT(T, 64, 7.60855263982359981275199e+13), + BOOST_MATH_BIG_CONSTANT(T, 64, -2.12901817219239205393806e+14), + BOOST_MATH_BIG_CONSTANT(T, 64, 4.14861794397709807823575e+14), + BOOST_MATH_BIG_CONSTANT(T, 64, -5.02808138522587680348583e+14), + BOOST_MATH_BIG_CONSTANT(T, 64, 2.85505477056514919387171e+14) + }; + return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); + } + else if(x < 100) + { + // Bessel I0 over [15, 50] + // Maximum Deviation Found: 2.444e-20 + // Expected Error Term : 2.438e-20 + // Maximum Relative Change in Control Points : 2.101e-03 + // Max Error found at float80 precision = Poly : 6.029974e-20 + + static const T P[] = { + BOOST_MATH_BIG_CONSTANT(T, 64, 3.98942280401431675205845e-01), + BOOST_MATH_BIG_CONSTANT(T, 64, -1.49603355149968887210170e-01), + BOOST_MATH_BIG_CONSTANT(T, 64, -4.67510486284376330257260e-02), + BOOST_MATH_BIG_CONSTANT(T, 64, -4.09071458907089270559464e-02), + BOOST_MATH_BIG_CONSTANT(T, 64, -5.75278280327696940044714e-02), + BOOST_MATH_BIG_CONSTANT(T, 64, -1.10591299500956620739254e-01), + BOOST_MATH_BIG_CONSTANT(T, 64, -2.77061766699949309115618e-01), + BOOST_MATH_BIG_CONSTANT(T, 64, -5.42683771801837596371638e-01), + BOOST_MATH_BIG_CONSTANT(T, 64, -9.17021412070404158464316e+00), + BOOST_MATH_BIG_CONSTANT(T, 64, 1.04154379346763380543310e+02), + BOOST_MATH_BIG_CONSTANT(T, 64, -1.43462345357478348323006e+03), + BOOST_MATH_BIG_CONSTANT(T, 64, 9.98109660274422449523837e+03), + BOOST_MATH_BIG_CONSTANT(T, 64, -3.74438822767781410362757e+04) + }; + return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); + } + else + { + // Bessel I0 over[100, INF] + // Max error in interpolated form: 2.456e-20 + // Max Error found at float80 precision = Poly: 5.446356e-20 + static const T P[] = { + BOOST_MATH_BIG_CONSTANT(T, 64, 3.98942280401432677958445e-01), + BOOST_MATH_BIG_CONSTANT(T, 64, -1.49603355150537411254359e-01), + BOOST_MATH_BIG_CONSTANT(T, 64, -4.67510484842456251368526e-02), + BOOST_MATH_BIG_CONSTANT(T, 64, -4.09071676503922479645155e-02), + BOOST_MATH_BIG_CONSTANT(T, 64, -5.75256179814881566010606e-02), + BOOST_MATH_BIG_CONSTANT(T, 64, -1.10754910257965227825040e-01), + BOOST_MATH_BIG_CONSTANT(T, 64, -2.67858639515616079840294e-01), + BOOST_MATH_BIG_CONSTANT(T, 64, -9.17266479586791298924367e-01) + }; + T ex = exp(x / 2); + T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); + result *= ex; + return result; + } +} + +template <typename T> +T bessel_i1_imp(const T& x, const mpl::int_<113>&) +{ + BOOST_MATH_STD_USING + if(x < 7.75) + { + // Bessel I0 over[10 ^ -34, 7.75] + // Max error in interpolated form: 1.835e-35 + // Max Error found at float128 precision = Poly: 1.645036e-34 + + static const T P[] = { + BOOST_MATH_BIG_CONSTANT(T, 113, 8.3333333333333333333333333333333331804098e-02), + BOOST_MATH_BIG_CONSTANT(T, 113, 6.9444444444444444444444444444445418303082e-03), + BOOST_MATH_BIG_CONSTANT(T, 113, 3.4722222222222222222222222222119082346591e-04), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.1574074074074074074074074078415867655987e-05), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.7557319223985890652557318255143448192453e-07), + BOOST_MATH_BIG_CONSTANT(T, 113, 4.9209498614260519022423916850415000626427e-09), + BOOST_MATH_BIG_CONSTANT(T, 113, 6.8346525853139609753354247043900442393686e-11), + BOOST_MATH_BIG_CONSTANT(T, 113, 7.5940584281266233060080535940234144302217e-13), + BOOST_MATH_BIG_CONSTANT(T, 113, 6.9036894801151120925605467963949641957095e-15), + BOOST_MATH_BIG_CONSTANT(T, 113, 5.2300677879659941472662086395055636394839e-17), + BOOST_MATH_BIG_CONSTANT(T, 113, 3.3526075563884539394691458717439115962233e-19), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.8420920639497841692288943167036233338434e-21), + BOOST_MATH_BIG_CONSTANT(T, 113, 8.7718669711748690065381181691546032291365e-24), + BOOST_MATH_BIG_CONSTANT(T, 113, 3.6549445715236427401845636880769861424730e-26), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.3437296196812697924703896979250126739676e-28), + BOOST_MATH_BIG_CONSTANT(T, 113, 4.3912734588619073883015937023564978854893e-31), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.2839967682792395867255384448052781306897e-33), + BOOST_MATH_BIG_CONSTANT(T, 113, 3.3790094235693528861015312806394354114982e-36), + BOOST_MATH_BIG_CONSTANT(T, 113, 8.0423861671932104308662362292359563970482e-39), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.7493858979396446292135661268130281652945e-41), + BOOST_MATH_BIG_CONSTANT(T, 113, 3.2786079392547776769387921361408303035537e-44), + BOOST_MATH_BIG_CONSTANT(T, 113, 8.2335693685833531118863552173880047183822e-47) + }; + T a = x * x / 4; + T Q[3] = { 1, 0.5f, boost::math::tools::evaluate_polynomial(P, a) }; + return x * boost::math::tools::evaluate_polynomial(Q, a) / 2; + } + else if(x < 11) + { + // Max error in interpolated form: 8.574e-36 + // Maximum Deviation Found : 4.689e-36 + // Expected Error Term : 3.760e-36 + // Maximum Relative Change in Control Points : 5.204e-03 + // Max Error found at float128 precision = Poly : 2.882561e-34 + + static const T P[] = { + BOOST_MATH_BIG_CONSTANT(T, 113, 8.333333333333333326889717360850080939e-02), + BOOST_MATH_BIG_CONSTANT(T, 113, 6.944444444444444511272790848815114507e-03), + BOOST_MATH_BIG_CONSTANT(T, 113, 3.472222222222221892451965054394153443e-04), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.157407407407408437378868534321538798e-05), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.755731922398566216824909767320161880e-07), + BOOST_MATH_BIG_CONSTANT(T, 113, 4.920949861426434829568192525456800388e-09), + BOOST_MATH_BIG_CONSTANT(T, 113, 6.834652585308926245465686943255486934e-11), + BOOST_MATH_BIG_CONSTANT(T, 113, 7.594058428179852047689599244015979196e-13), + BOOST_MATH_BIG_CONSTANT(T, 113, 6.903689479655006062822949671528763738e-15), + BOOST_MATH_BIG_CONSTANT(T, 113, 5.230067791254403974475987777406992984e-17), + BOOST_MATH_BIG_CONSTANT(T, 113, 3.352607536815161679702105115200693346e-19), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.842092161364672561828681848278567885e-21), + BOOST_MATH_BIG_CONSTANT(T, 113, 8.771862912600611801856514076709932773e-24), + BOOST_MATH_BIG_CONSTANT(T, 113, 3.654958704184380914803366733193713605e-26), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.343688672071130980471207297730607625e-28), + BOOST_MATH_BIG_CONSTANT(T, 113, 4.392252844664709532905868749753463950e-31), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.282086786672692641959912811902298600e-33), + BOOST_MATH_BIG_CONSTANT(T, 113, 3.408812012322547015191398229942864809e-36), + BOOST_MATH_BIG_CONSTANT(T, 113, 7.681220437734066258673404589233009892e-39), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.072417451640733785626701738789290055e-41), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.352218520142636864158849446833681038e-44), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.407918492276267527897751358794783640e-46) + }; + T a = x * x / 4; + T Q[3] = { 1, 0.5f, boost::math::tools::evaluate_polynomial(P, a) }; + return x * boost::math::tools::evaluate_polynomial(Q, a) / 2; + } + else if(x < 15) + { + //Max error in interpolated form: 7.599e-36 + // Maximum Deviation Found : 1.766e-35 + // Expected Error Term : 1.021e-35 + // Maximum Relative Change in Control Points : 6.228e-03 + static const T P[] = { + BOOST_MATH_BIG_CONSTANT(T, 113, 8.333333333333255774414858563409941233e-02), + BOOST_MATH_BIG_CONSTANT(T, 113, 6.944444444444897867884955912228700291e-03), + BOOST_MATH_BIG_CONSTANT(T, 113, 3.472222222220954970397343617150959467e-04), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.157407407409660682751155024932538578e-05), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.755731922369973706427272809014190998e-07), + BOOST_MATH_BIG_CONSTANT(T, 113, 4.920949861702265600960449699129258153e-09), + BOOST_MATH_BIG_CONSTANT(T, 113, 6.834652583208361401197752793379677147e-11), + BOOST_MATH_BIG_CONSTANT(T, 113, 7.594058441128280500819776168239988143e-13), + BOOST_MATH_BIG_CONSTANT(T, 113, 6.903689413939268702265479276217647209e-15), + BOOST_MATH_BIG_CONSTANT(T, 113, 5.230068069012898202890718644753625569e-17), + BOOST_MATH_BIG_CONSTANT(T, 113, 3.352606552027491657204243201021677257e-19), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.842095100698532984651921750204843362e-21), + BOOST_MATH_BIG_CONSTANT(T, 113, 8.771789051329870174925649852681844169e-24), + BOOST_MATH_BIG_CONSTANT(T, 113, 3.655114381199979536997025497438385062e-26), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.343415732516712339472538688374589373e-28), + BOOST_MATH_BIG_CONSTANT(T, 113, 4.396177019032432392793591204647901390e-31), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.277563309255167951005939802771456315e-33), + BOOST_MATH_BIG_CONSTANT(T, 113, 3.449201419305514579791370198046544736e-36), + BOOST_MATH_BIG_CONSTANT(T, 113, 7.415430703400740634202379012388035255e-39), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.195458831864936225409005027914934499e-41), + BOOST_MATH_BIG_CONSTANT(T, 113, 8.829726762743879793396637797534668039e-45), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.698302711685624490806751012380215488e-46), + BOOST_MATH_BIG_CONSTANT(T, 113, -2.062520475425422618494185821587228317e-49), + BOOST_MATH_BIG_CONSTANT(T, 113, 6.732372906742845717148185173723304360e-52) + }; + T a = x * x / 4; + T Q[3] = { 1, 0.5f, boost::math::tools::evaluate_polynomial(P, a) }; + return x * boost::math::tools::evaluate_polynomial(Q, a) / 2; + } + else if(x < 20) + { + // Max error in interpolated form: 8.864e-36 + // Max Error found at float128 precision = Poly: 8.522841e-35 + static const T P[] = { + BOOST_MATH_BIG_CONSTANT(T, 113, 3.989422793693152031514179994954750043e-01), + BOOST_MATH_BIG_CONSTANT(T, 113, -1.496029423752889591425633234009799670e-01), + BOOST_MATH_BIG_CONSTANT(T, 113, -4.682975926820553021482820043377990241e-02), + BOOST_MATH_BIG_CONSTANT(T, 113, -3.138871171577224532369979905856458929e-02), + BOOST_MATH_BIG_CONSTANT(T, 113, -8.765350219426341341990447005798111212e-01), + BOOST_MATH_BIG_CONSTANT(T, 113, 5.321389275507714530941178258122955540e+01), + BOOST_MATH_BIG_CONSTANT(T, 113, -2.727748393898888756515271847678850411e+03), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.123040820686242586086564998713862335e+05), + BOOST_MATH_BIG_CONSTANT(T, 113, -3.784112378374753535335272752884808068e+06), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.054920416060932189433079126269416563e+08), + BOOST_MATH_BIG_CONSTANT(T, 113, -2.450129415468060676827180524327749553e+09), + BOOST_MATH_BIG_CONSTANT(T, 113, 4.758831882046487398739784498047935515e+10), + BOOST_MATH_BIG_CONSTANT(T, 113, -7.736936520262204842199620784338052937e+11), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.051128683324042629513978256179115439e+13), + BOOST_MATH_BIG_CONSTANT(T, 113, -1.188008285959794869092624343537262342e+14), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.108530004906954627420484180793165669e+15), + BOOST_MATH_BIG_CONSTANT(T, 113, -8.441516828490144766650287123765318484e+15), + BOOST_MATH_BIG_CONSTANT(T, 113, 5.158251664797753450664499268756393535e+16), + BOOST_MATH_BIG_CONSTANT(T, 113, -2.467314522709016832128790443932896401e+17), + BOOST_MATH_BIG_CONSTANT(T, 113, 8.896222045367960462945885220710294075e+17), + BOOST_MATH_BIG_CONSTANT(T, 113, -2.273382139594876997203657902425653079e+18), + BOOST_MATH_BIG_CONSTANT(T, 113, 3.669871448568623680543943144842394531e+18), + BOOST_MATH_BIG_CONSTANT(T, 113, -2.813923031370708069940575240509912588e+18) + }; + return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); + } + else if(x < 35) + { + // Max error in interpolated form: 6.028e-35 + // Max Error found at float128 precision = Poly: 1.368313e-34 + + static const T P[] = { + BOOST_MATH_BIG_CONSTANT(T, 113, 3.989422804012941975429616956496046931e-01), + BOOST_MATH_BIG_CONSTANT(T, 113, -1.496033550576049830976679315420681402e-01), + BOOST_MATH_BIG_CONSTANT(T, 113, -4.675107835141866009896710750800622147e-02), + BOOST_MATH_BIG_CONSTANT(T, 113, -4.090104965125365961928716504473692957e-02), + BOOST_MATH_BIG_CONSTANT(T, 113, -5.842241652296980863361375208605487570e-02), + BOOST_MATH_BIG_CONSTANT(T, 113, -1.063604828033747303936724279018650633e-02), + BOOST_MATH_BIG_CONSTANT(T, 113, -9.113375972811586130949401996332817152e+00), + BOOST_MATH_BIG_CONSTANT(T, 113, 6.334748570425075872639817839399823709e+02), + BOOST_MATH_BIG_CONSTANT(T, 113, -3.759150758768733692594821032784124765e+04), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.863672813448915255286274382558526321e+06), + BOOST_MATH_BIG_CONSTANT(T, 113, -7.798248643371718775489178767529282534e+07), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.769963173932801026451013022000669267e+09), + BOOST_MATH_BIG_CONSTANT(T, 113, -8.381780137198278741566746511015220011e+10), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.163891337116820832871382141011952931e+12), + BOOST_MATH_BIG_CONSTANT(T, 113, -4.764325864671438675151635117936912390e+13), + BOOST_MATH_BIG_CONSTANT(T, 113, 8.925668307403332887856809510525154955e+14), + BOOST_MATH_BIG_CONSTANT(T, 113, -1.416692606589060039334938090985713641e+16), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.892398600219306424294729851605944429e+17), + BOOST_MATH_BIG_CONSTANT(T, 113, -2.107232903741874160308537145391245060e+18), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.930223393531877588898224144054112045e+19), + BOOST_MATH_BIG_CONSTANT(T, 113, -1.427759576167665663373350433236061007e+20), + BOOST_MATH_BIG_CONSTANT(T, 113, 8.306019279465532835530812122374386654e+20), + BOOST_MATH_BIG_CONSTANT(T, 113, -3.653753000392125229440044977239174472e+21), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.140760686989511568435076842569804906e+22), + BOOST_MATH_BIG_CONSTANT(T, 113, -2.249149337812510200795436107962504749e+22), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.101619088427348382058085685849420866e+22) + }; + return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); + } + else if(x < 100) + { + // Max error in interpolated form: 5.494e-35 + // Max Error found at float128 precision = Poly: 1.214651e-34 + + static const T P[] = { + BOOST_MATH_BIG_CONSTANT(T, 113, 3.989422804014326779399307367861631577e-01), + BOOST_MATH_BIG_CONSTANT(T, 113, -1.496033551505372542086590873271571919e-01), + BOOST_MATH_BIG_CONSTANT(T, 113, -4.675104848454290286276466276677172664e-02), + BOOST_MATH_BIG_CONSTANT(T, 113, -4.090716742397105403027549796269213215e-02), + BOOST_MATH_BIG_CONSTANT(T, 113, -5.752570419098513588311026680089351230e-02), + BOOST_MATH_BIG_CONSTANT(T, 113, -1.107369803696534592906420980901195808e-01), + BOOST_MATH_BIG_CONSTANT(T, 113, -2.699214194000085622941721628134575121e-01), + BOOST_MATH_BIG_CONSTANT(T, 113, -7.953006169077813678478720427604462133e-01), + BOOST_MATH_BIG_CONSTANT(T, 113, -2.746618809476524091493444128605380593e+00), + BOOST_MATH_BIG_CONSTANT(T, 113, -1.084446249943196826652788161656973391e+01), + BOOST_MATH_BIG_CONSTANT(T, 113, -5.020325182518980633783194648285500554e+01), + BOOST_MATH_BIG_CONSTANT(T, 113, -1.510195971266257573425196228564489134e+02), + BOOST_MATH_BIG_CONSTANT(T, 113, -5.241661863814900938075696173192225056e+03), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.323374362891993686413568398575539777e+05), + BOOST_MATH_BIG_CONSTANT(T, 113, -4.112838452096066633754042734723911040e+06), + BOOST_MATH_BIG_CONSTANT(T, 113, 9.369270194978310081563767560113534023e+07), + BOOST_MATH_BIG_CONSTANT(T, 113, -1.704295412488936504389347368131134993e+09), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.320829576277038198439987439508754886e+10), + BOOST_MATH_BIG_CONSTANT(T, 113, -2.258818139077875493434420764260185306e+11), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.396791306321498426110315039064592443e+12), + BOOST_MATH_BIG_CONSTANT(T, 113, -4.217617301585849875301440316301068439e+12) + }; + return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); + } + else + { + // Bessel I0 over[100, INF] + // Max error in interpolated form: 6.081e-35 + // Max Error found at float128 precision = Poly: 1.407151e-34 + static const T P[] = { + BOOST_MATH_BIG_CONSTANT(T, 113, 3.9894228040143267793994605993438200208417e-01), + BOOST_MATH_BIG_CONSTANT(T, 113, -1.4960335515053725422747977247811372936584e-01), + BOOST_MATH_BIG_CONSTANT(T, 113, -4.6751048484542891946087411826356811991039e-02), + BOOST_MATH_BIG_CONSTANT(T, 113, -4.0907167423975030452875828826630006305665e-02), + BOOST_MATH_BIG_CONSTANT(T, 113, -5.7525704189964886494791082898669060345483e-02), + BOOST_MATH_BIG_CONSTANT(T, 113, -1.1073698056568248642163476807108190176386e-01), + BOOST_MATH_BIG_CONSTANT(T, 113, -2.6992139012879749064623499618582631684228e-01), + BOOST_MATH_BIG_CONSTANT(T, 113, -7.9530409594026597988098934027440110587905e-01), + BOOST_MATH_BIG_CONSTANT(T, 113, -2.7462844478733532517044536719240098183686e+00), + BOOST_MATH_BIG_CONSTANT(T, 113, -1.0870711340681926669381449306654104739256e+01), + BOOST_MATH_BIG_CONSTANT(T, 113, -4.8510175413216969245241059608553222505228e+01), + BOOST_MATH_BIG_CONSTANT(T, 113, -2.4094682286011573747064907919522894740063e+02), + BOOST_MATH_BIG_CONSTANT(T, 113, -1.3128845936764406865199641778959502795443e+03), + BOOST_MATH_BIG_CONSTANT(T, 113, -8.1655901321962541203257516341266838487359e+03), + BOOST_MATH_BIG_CONSTANT(T, 113, -3.8019591025686295090160445920753823994556e+04), + BOOST_MATH_BIG_CONSTANT(T, 113, -6.7008089049178178697338128837158732831105e+05) + }; + T ex = exp(x / 2); + T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); + result *= ex; + return result; + } +} + +template <typename T> +T bessel_i1_imp(const T& x, const mpl::int_<0>&) +{ + if(boost::math::tools::digits<T>() <= 24) + return bessel_i1_imp(x, mpl::int_<24>()); + else if(boost::math::tools::digits<T>() <= 53) + return bessel_i1_imp(x, mpl::int_<53>()); + else if(boost::math::tools::digits<T>() <= 64) + return bessel_i1_imp(x, mpl::int_<64>()); + else if(boost::math::tools::digits<T>() <= 113) + return bessel_i1_imp(x, mpl::int_<113>()); + BOOST_ASSERT(0); + return 0; +} + +template <typename T> +inline T bessel_i1(const T& x) +{ + typedef mpl::int_< + ((std::numeric_limits<T>::digits == 0) || (std::numeric_limits<T>::radix != 2)) ? + 0 : + std::numeric_limits<T>::digits <= 24 ? + 24 : + std::numeric_limits<T>::digits <= 53 ? + 53 : + std::numeric_limits<T>::digits <= 64 ? + 64 : + std::numeric_limits<T>::digits <= 113 ? + 113 : -1 + > tag_type; + + bessel_i1_initializer<T, tag_type>::force_instantiate(); + return bessel_i1_imp(x, tag_type()); +} + +}}} // namespaces + +#endif // BOOST_MATH_BESSEL_I1_HPP + diff --git a/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_ik.hpp b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_ik.hpp new file mode 100644 index 00000000000..aac1781e10d --- /dev/null +++ b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_ik.hpp @@ -0,0 +1,451 @@ +// Copyright (c) 2006 Xiaogang Zhang +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_BESSEL_IK_HPP +#define BOOST_MATH_BESSEL_IK_HPP + +#ifdef _MSC_VER +#pragma once +#endif + +#include <boost/math/special_functions/round.hpp> +#include <boost/math/special_functions/gamma.hpp> +#include <boost/math/special_functions/sin_pi.hpp> +#include <boost/math/constants/constants.hpp> +#include <boost/math/policies/error_handling.hpp> +#include <boost/math/tools/config.hpp> + +// Modified Bessel functions of the first and second kind of fractional order + +namespace boost { namespace math { + +namespace detail { + +template <class T, class Policy> +struct cyl_bessel_i_small_z +{ + typedef T result_type; + + cyl_bessel_i_small_z(T v_, T z_) : k(0), v(v_), mult(z_*z_/4) + { + BOOST_MATH_STD_USING + term = 1; + } + + T operator()() + { + T result = term; + ++k; + term *= mult / k; + term /= k + v; + return result; + } +private: + unsigned k; + T v; + T term; + T mult; +}; + +template <class T, class Policy> +inline T bessel_i_small_z_series(T v, T x, const Policy& pol) +{ + BOOST_MATH_STD_USING + T prefix; + if(v < max_factorial<T>::value) + { + prefix = pow(x / 2, v) / boost::math::tgamma(v + 1, pol); + } + else + { + prefix = v * log(x / 2) - boost::math::lgamma(v + 1, pol); + prefix = exp(prefix); + } + if(prefix == 0) + return prefix; + + cyl_bessel_i_small_z<T, Policy> s(v, x); + boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>(); +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) + T zero = 0; + T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon<T, Policy>(), max_iter, zero); +#else + T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon<T, Policy>(), max_iter); +#endif + policies::check_series_iterations<T>("boost::math::bessel_j_small_z_series<%1%>(%1%,%1%)", max_iter, pol); + return prefix * result; +} + +// Calculate K(v, x) and K(v+1, x) by method analogous to +// Temme, Journal of Computational Physics, vol 21, 343 (1976) +template <typename T, typename Policy> +int temme_ik(T v, T x, T* K, T* K1, const Policy& pol) +{ + T f, h, p, q, coef, sum, sum1, tolerance; + T a, b, c, d, sigma, gamma1, gamma2; + unsigned long k; + + BOOST_MATH_STD_USING + using namespace boost::math::tools; + using namespace boost::math::constants; + + + // |x| <= 2, Temme series converge rapidly + // |x| > 2, the larger the |x|, the slower the convergence + BOOST_ASSERT(abs(x) <= 2); + BOOST_ASSERT(abs(v) <= 0.5f); + + T gp = boost::math::tgamma1pm1(v, pol); + T gm = boost::math::tgamma1pm1(-v, pol); + + a = log(x / 2); + b = exp(v * a); + sigma = -a * v; + c = abs(v) < tools::epsilon<T>() ? + T(1) : T(boost::math::sin_pi(v) / (v * pi<T>())); + d = abs(sigma) < tools::epsilon<T>() ? + T(1) : T(sinh(sigma) / sigma); + gamma1 = abs(v) < tools::epsilon<T>() ? + T(-euler<T>()) : T((0.5f / v) * (gp - gm) * c); + gamma2 = (2 + gp + gm) * c / 2; + + // initial values + p = (gp + 1) / (2 * b); + q = (1 + gm) * b / 2; + f = (cosh(sigma) * gamma1 + d * (-a) * gamma2) / c; + h = p; + coef = 1; + sum = coef * f; + sum1 = coef * h; + + BOOST_MATH_INSTRUMENT_VARIABLE(p); + BOOST_MATH_INSTRUMENT_VARIABLE(q); + BOOST_MATH_INSTRUMENT_VARIABLE(f); + BOOST_MATH_INSTRUMENT_VARIABLE(sigma); + BOOST_MATH_INSTRUMENT_CODE(sinh(sigma)); + BOOST_MATH_INSTRUMENT_VARIABLE(gamma1); + BOOST_MATH_INSTRUMENT_VARIABLE(gamma2); + BOOST_MATH_INSTRUMENT_VARIABLE(c); + BOOST_MATH_INSTRUMENT_VARIABLE(d); + BOOST_MATH_INSTRUMENT_VARIABLE(a); + + // series summation + tolerance = tools::epsilon<T>(); + for (k = 1; k < policies::get_max_series_iterations<Policy>(); k++) + { + f = (k * f + p + q) / (k*k - v*v); + p /= k - v; + q /= k + v; + h = p - k * f; + coef *= x * x / (4 * k); + sum += coef * f; + sum1 += coef * h; + if (abs(coef * f) < abs(sum) * tolerance) + { + break; + } + } + policies::check_series_iterations<T>("boost::math::bessel_ik<%1%>(%1%,%1%) in temme_ik", k, pol); + + *K = sum; + *K1 = 2 * sum1 / x; + + return 0; +} + +// Evaluate continued fraction fv = I_(v+1) / I_v, derived from +// Abramowitz and Stegun, Handbook of Mathematical Functions, 1972, 9.1.73 +template <typename T, typename Policy> +int CF1_ik(T v, T x, T* fv, const Policy& pol) +{ + T C, D, f, a, b, delta, tiny, tolerance; + unsigned long k; + + BOOST_MATH_STD_USING + + // |x| <= |v|, CF1_ik converges rapidly + // |x| > |v|, CF1_ik needs O(|x|) iterations to converge + + // modified Lentz's method, see + // Lentz, Applied Optics, vol 15, 668 (1976) + tolerance = 2 * tools::epsilon<T>(); + BOOST_MATH_INSTRUMENT_VARIABLE(tolerance); + tiny = sqrt(tools::min_value<T>()); + BOOST_MATH_INSTRUMENT_VARIABLE(tiny); + C = f = tiny; // b0 = 0, replace with tiny + D = 0; + for (k = 1; k < policies::get_max_series_iterations<Policy>(); k++) + { + a = 1; + b = 2 * (v + k) / x; + C = b + a / C; + D = b + a * D; + if (C == 0) { C = tiny; } + if (D == 0) { D = tiny; } + D = 1 / D; + delta = C * D; + f *= delta; + BOOST_MATH_INSTRUMENT_VARIABLE(delta-1); + if (abs(delta - 1) <= tolerance) + { + break; + } + } + BOOST_MATH_INSTRUMENT_VARIABLE(k); + policies::check_series_iterations<T>("boost::math::bessel_ik<%1%>(%1%,%1%) in CF1_ik", k, pol); + + *fv = f; + + return 0; +} + +// Calculate K(v, x) and K(v+1, x) by evaluating continued fraction +// z1 / z0 = U(v+1.5, 2v+1, 2x) / U(v+0.5, 2v+1, 2x), see +// Thompson and Barnett, Computer Physics Communications, vol 47, 245 (1987) +template <typename T, typename Policy> +int CF2_ik(T v, T x, T* Kv, T* Kv1, const Policy& pol) +{ + BOOST_MATH_STD_USING + using namespace boost::math::constants; + + T S, C, Q, D, f, a, b, q, delta, tolerance, current, prev; + unsigned long k; + + // |x| >= |v|, CF2_ik converges rapidly + // |x| -> 0, CF2_ik fails to converge + + BOOST_ASSERT(abs(x) > 1); + + // Steed's algorithm, see Thompson and Barnett, + // Journal of Computational Physics, vol 64, 490 (1986) + tolerance = tools::epsilon<T>(); + a = v * v - 0.25f; + b = 2 * (x + 1); // b1 + D = 1 / b; // D1 = 1 / b1 + f = delta = D; // f1 = delta1 = D1, coincidence + prev = 0; // q0 + current = 1; // q1 + Q = C = -a; // Q1 = C1 because q1 = 1 + S = 1 + Q * delta; // S1 + BOOST_MATH_INSTRUMENT_VARIABLE(tolerance); + BOOST_MATH_INSTRUMENT_VARIABLE(a); + BOOST_MATH_INSTRUMENT_VARIABLE(b); + BOOST_MATH_INSTRUMENT_VARIABLE(D); + BOOST_MATH_INSTRUMENT_VARIABLE(f); + + for (k = 2; k < policies::get_max_series_iterations<Policy>(); k++) // starting from 2 + { + // continued fraction f = z1 / z0 + a -= 2 * (k - 1); + b += 2; + D = 1 / (b + a * D); + delta *= b * D - 1; + f += delta; + + // series summation S = 1 + \sum_{n=1}^{\infty} C_n * z_n / z_0 + q = (prev - (b - 2) * current) / a; + prev = current; + current = q; // forward recurrence for q + C *= -a / k; + Q += C * q; + S += Q * delta; + // + // Under some circumstances q can grow very small and C very + // large, leading to under/overflow. This is particularly an + // issue for types which have many digits precision but a narrow + // exponent range. A typical example being a "double double" type. + // To avoid this situation we can normalise q (and related prev/current) + // and C. All other variables remain unchanged in value. A typical + // test case occurs when x is close to 2, for example cyl_bessel_k(9.125, 2.125). + // + if(q < tools::epsilon<T>()) + { + C *= q; + prev /= q; + current /= q; + q = 1; + } + + // S converges slower than f + BOOST_MATH_INSTRUMENT_VARIABLE(Q * delta); + BOOST_MATH_INSTRUMENT_VARIABLE(abs(S) * tolerance); + BOOST_MATH_INSTRUMENT_VARIABLE(S); + if (abs(Q * delta) < abs(S) * tolerance) + { + break; + } + } + policies::check_series_iterations<T>("boost::math::bessel_ik<%1%>(%1%,%1%) in CF2_ik", k, pol); + + if(x >= tools::log_max_value<T>()) + *Kv = exp(0.5f * log(pi<T>() / (2 * x)) - x - log(S)); + else + *Kv = sqrt(pi<T>() / (2 * x)) * exp(-x) / S; + *Kv1 = *Kv * (0.5f + v + x + (v * v - 0.25f) * f) / x; + BOOST_MATH_INSTRUMENT_VARIABLE(*Kv); + BOOST_MATH_INSTRUMENT_VARIABLE(*Kv1); + + return 0; +} + +enum{ + need_i = 1, + need_k = 2 +}; + +// Compute I(v, x) and K(v, x) simultaneously by Temme's method, see +// Temme, Journal of Computational Physics, vol 19, 324 (1975) +template <typename T, typename Policy> +int bessel_ik(T v, T x, T* I, T* K, int kind, const Policy& pol) +{ + // Kv1 = K_(v+1), fv = I_(v+1) / I_v + // Ku1 = K_(u+1), fu = I_(u+1) / I_u + T u, Iv, Kv, Kv1, Ku, Ku1, fv; + T W, current, prev, next; + bool reflect = false; + unsigned n, k; + int org_kind = kind; + BOOST_MATH_INSTRUMENT_VARIABLE(v); + BOOST_MATH_INSTRUMENT_VARIABLE(x); + BOOST_MATH_INSTRUMENT_VARIABLE(kind); + + BOOST_MATH_STD_USING + using namespace boost::math::tools; + using namespace boost::math::constants; + + static const char* function = "boost::math::bessel_ik<%1%>(%1%,%1%)"; + + if (v < 0) + { + reflect = true; + v = -v; // v is non-negative from here + kind |= need_k; + } + n = iround(v, pol); + u = v - n; // -1/2 <= u < 1/2 + BOOST_MATH_INSTRUMENT_VARIABLE(n); + BOOST_MATH_INSTRUMENT_VARIABLE(u); + + if (x < 0) + { + *I = *K = policies::raise_domain_error<T>(function, + "Got x = %1% but real argument x must be non-negative, complex number result not supported.", x, pol); + return 1; + } + if (x == 0) + { + Iv = (v == 0) ? static_cast<T>(1) : static_cast<T>(0); + if(kind & need_k) + { + Kv = policies::raise_overflow_error<T>(function, 0, pol); + } + else + { + Kv = std::numeric_limits<T>::quiet_NaN(); // any value will do + } + + if(reflect && (kind & need_i)) + { + T z = (u + n % 2); + Iv = boost::math::sin_pi(z, pol) == 0 ? + Iv : + policies::raise_overflow_error<T>(function, 0, pol); // reflection formula + } + + *I = Iv; + *K = Kv; + return 0; + } + + // x is positive until reflection + W = 1 / x; // Wronskian + if (x <= 2) // x in (0, 2] + { + temme_ik(u, x, &Ku, &Ku1, pol); // Temme series + } + else // x in (2, \infty) + { + CF2_ik(u, x, &Ku, &Ku1, pol); // continued fraction CF2_ik + } + BOOST_MATH_INSTRUMENT_VARIABLE(Ku); + BOOST_MATH_INSTRUMENT_VARIABLE(Ku1); + prev = Ku; + current = Ku1; + T scale = 1; + T scale_sign = 1; + for (k = 1; k <= n; k++) // forward recurrence for K + { + T fact = 2 * (u + k) / x; + if((tools::max_value<T>() - fabs(prev)) / fact < fabs(current)) + { + prev /= current; + scale /= current; + scale_sign *= boost::math::sign(current); + current = 1; + } + next = fact * current + prev; + prev = current; + current = next; + } + Kv = prev; + Kv1 = current; + BOOST_MATH_INSTRUMENT_VARIABLE(Kv); + BOOST_MATH_INSTRUMENT_VARIABLE(Kv1); + if(kind & need_i) + { + T lim = (4 * v * v + 10) / (8 * x); + lim *= lim; + lim *= lim; + lim /= 24; + if((lim < tools::epsilon<T>() * 10) && (x > 100)) + { + // x is huge compared to v, CF1 may be very slow + // to converge so use asymptotic expansion for large + // x case instead. Note that the asymptotic expansion + // isn't very accurate - so it's deliberately very hard + // to get here - probably we're going to overflow: + Iv = asymptotic_bessel_i_large_x(v, x, pol); + } + else if((v > 0) && (x / v < 0.25)) + { + Iv = bessel_i_small_z_series(v, x, pol); + } + else + { + CF1_ik(v, x, &fv, pol); // continued fraction CF1_ik + Iv = scale * W / (Kv * fv + Kv1); // Wronskian relation + } + } + else + Iv = std::numeric_limits<T>::quiet_NaN(); // any value will do + + if (reflect) + { + T z = (u + n % 2); + T fact = (2 / pi<T>()) * (boost::math::sin_pi(z) * Kv); + if(fact == 0) + *I = Iv; + else if(tools::max_value<T>() * scale < fact) + *I = (org_kind & need_i) ? T(sign(fact) * scale_sign * policies::raise_overflow_error<T>(function, 0, pol)) : T(0); + else + *I = Iv + fact / scale; // reflection formula + } + else + { + *I = Iv; + } + if(tools::max_value<T>() * scale < Kv) + *K = (org_kind & need_k) ? T(sign(Kv) * scale_sign * policies::raise_overflow_error<T>(function, 0, pol)) : T(0); + else + *K = Kv / scale; + BOOST_MATH_INSTRUMENT_VARIABLE(*I); + BOOST_MATH_INSTRUMENT_VARIABLE(*K); + return 0; +} + +}}} // namespaces + +#endif // BOOST_MATH_BESSEL_IK_HPP + diff --git a/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_j0.hpp b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_j0.hpp new file mode 100644 index 00000000000..f7c381c47eb --- /dev/null +++ b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_j0.hpp @@ -0,0 +1,203 @@ +// Copyright (c) 2006 Xiaogang Zhang +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_BESSEL_J0_HPP +#define BOOST_MATH_BESSEL_J0_HPP + +#ifdef _MSC_VER +#pragma once +#endif + +#include <boost/math/constants/constants.hpp> +#include <boost/math/tools/rational.hpp> +#include <boost/math/tools/big_constant.hpp> +#include <boost/assert.hpp> + +#if defined(__GNUC__) && defined(BOOST_MATH_USE_FLOAT128) +// +// This is the only way we can avoid +// warning: non-standard suffix on floating constant [-Wpedantic] +// when building with -Wall -pedantic. Neither __extension__ +// nor #pragma dianostic ignored work :( +// +#pragma GCC system_header +#endif + +// Bessel function of the first kind of order zero +// x <= 8, minimax rational approximations on root-bracketing intervals +// x > 8, Hankel asymptotic expansion in Hart, Computer Approximations, 1968 + +namespace boost { namespace math { namespace detail{ + +template <typename T> +T bessel_j0(T x); + +template <class T> +struct bessel_j0_initializer +{ + struct init + { + init() + { + do_init(); + } + static void do_init() + { + bessel_j0(T(1)); + } + void force_instantiate()const{} + }; + static const init initializer; + static void force_instantiate() + { + initializer.force_instantiate(); + } +}; + +template <class T> +const typename bessel_j0_initializer<T>::init bessel_j0_initializer<T>::initializer; + +template <typename T> +T bessel_j0(T x) +{ + bessel_j0_initializer<T>::force_instantiate(); + + static const T P1[] = { + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -4.1298668500990866786e+11)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.7282507878605942706e+10)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -6.2140700423540120665e+08)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 6.6302997904833794242e+06)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -3.6629814655107086448e+04)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0344222815443188943e+02)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.2117036164593528341e-01)) + }; + static const T Q1[] = { + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.3883787996332290397e+12)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.6328198300859648632e+10)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.3985097372263433271e+08)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.5612696224219938200e+05)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 9.3614022392337710626e+02)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.0)) + }; + static const T P2[] = { + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.8319397969392084011e+03)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.2254078161378989535e+04)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -7.2879702464464618998e+03)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0341910641583726701e+04)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.1725046279757103576e+04)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.4176707025325087628e+03)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 7.4321196680624245801e+02)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.8591703355916499363e+01)) + }; + static const T Q2[] = { + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -3.5783478026152301072e+05)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.4599102262586308984e+05)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -8.4055062591169562211e+04)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.8680990008359188352e+04)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -2.9458766545509337327e+03)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.3307310774649071172e+02)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -2.5258076240801555057e+01)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0)) + }; + static const T PC[] = { + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.2779090197304684302e+04)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.1345386639580765797e+04)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.1170523380864944322e+04)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.4806486443249270347e+03)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.5376201909008354296e+02)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 8.8961548424210455236e-01)) + }; + static const T QC[] = { + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.2779090197304684318e+04)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.1370412495510416640e+04)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.1215350561880115730e+04)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.5028735138235608207e+03)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.5711159858080893649e+02)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0)) + }; + static const T PS[] = { + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -8.9226600200800094098e+01)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.8591953644342993800e+02)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.1183429920482737611e+02)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -2.2300261666214198472e+01)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.2441026745835638459e+00)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -8.8033303048680751817e-03)) + }; + static const T QS[] = { + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 5.7105024128512061905e+03)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.1951131543434613647e+04)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 7.2642780169211018836e+03)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.4887231232283756582e+03)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 9.0593769594993125859e+01)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0)) + }; + static const T x1 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.4048255576957727686e+00)), + x2 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 5.5200781102863106496e+00)), + x11 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 6.160e+02)), + x12 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.42444230422723137837e-03)), + x21 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.4130e+03)), + x22 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 5.46860286310649596604e-04)); + + T value, factor, r, rc, rs; + + BOOST_MATH_STD_USING + using namespace boost::math::tools; + using namespace boost::math::constants; + + if (x < 0) + { + x = -x; // even function + } + if (x == 0) + { + return static_cast<T>(1); + } + if (x <= 4) // x in (0, 4] + { + T y = x * x; + BOOST_ASSERT(sizeof(P1) == sizeof(Q1)); + r = evaluate_rational(P1, Q1, y); + factor = (x + x1) * ((x - x11/256) - x12); + value = factor * r; + } + else if (x <= 8.0) // x in (4, 8] + { + T y = 1 - (x * x)/64; + BOOST_ASSERT(sizeof(P2) == sizeof(Q2)); + r = evaluate_rational(P2, Q2, y); + factor = (x + x2) * ((x - x21/256) - x22); + value = factor * r; + } + else // x in (8, \infty) + { + T y = 8 / x; + T y2 = y * y; + BOOST_ASSERT(sizeof(PC) == sizeof(QC)); + BOOST_ASSERT(sizeof(PS) == sizeof(QS)); + rc = evaluate_rational(PC, QC, y2); + rs = evaluate_rational(PS, QS, y2); + factor = constants::one_div_root_pi<T>() / sqrt(x); + // + // What follows is really just: + // + // T z = x - pi/4; + // value = factor * (rc * cos(z) - y * rs * sin(z)); + // + // But using the addition formulae for sin and cos, plus + // the special values for sin/cos of pi/4. + // + T sx = sin(x); + T cx = cos(x); + value = factor * (rc * (cx + sx) - y * rs * (sx - cx)); + } + + return value; +} + +}}} // namespaces + +#endif // BOOST_MATH_BESSEL_J0_HPP + diff --git a/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_j1.hpp b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_j1.hpp new file mode 100644 index 00000000000..05cf40f0d78 --- /dev/null +++ b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_j1.hpp @@ -0,0 +1,209 @@ +// Copyright (c) 2006 Xiaogang Zhang +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_BESSEL_J1_HPP +#define BOOST_MATH_BESSEL_J1_HPP + +#ifdef _MSC_VER +#pragma once +#endif + +#include <boost/math/constants/constants.hpp> +#include <boost/math/tools/rational.hpp> +#include <boost/math/tools/big_constant.hpp> +#include <boost/assert.hpp> + +#if defined(__GNUC__) && defined(BOOST_MATH_USE_FLOAT128) +// +// This is the only way we can avoid +// warning: non-standard suffix on floating constant [-Wpedantic] +// when building with -Wall -pedantic. Neither __extension__ +// nor #pragma dianostic ignored work :( +// +#pragma GCC system_header +#endif + +// Bessel function of the first kind of order one +// x <= 8, minimax rational approximations on root-bracketing intervals +// x > 8, Hankel asymptotic expansion in Hart, Computer Approximations, 1968 + +namespace boost { namespace math{ namespace detail{ + +template <typename T> +T bessel_j1(T x); + +template <class T> +struct bessel_j1_initializer +{ + struct init + { + init() + { + do_init(); + } + static void do_init() + { + bessel_j1(T(1)); + } + void force_instantiate()const{} + }; + static const init initializer; + static void force_instantiate() + { + initializer.force_instantiate(); + } +}; + +template <class T> +const typename bessel_j1_initializer<T>::init bessel_j1_initializer<T>::initializer; + +template <typename T> +T bessel_j1(T x) +{ + bessel_j1_initializer<T>::force_instantiate(); + + static const T P1[] = { + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.4258509801366645672e+11)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 6.6781041261492395835e+09)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.1548696764841276794e+08)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 9.8062904098958257677e+05)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -4.4615792982775076130e+03)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0650724020080236441e+01)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.0767857011487300348e-02)) + }; + static const T Q1[] = { + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.1868604460820175290e+12)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.2091902282580133541e+10)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.0228375140097033958e+08)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 5.9117614494174794095e+05)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0742272239517380498e+03)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.0)) + }; + static const T P2[] = { + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.7527881995806511112e+16)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.6608531731299018674e+15)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -3.6658018905416665164e+13)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.5580665670910619166e+11)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.8113931269860667829e+09)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 5.0793266148011179143e+06)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -7.5023342220781607561e+03)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.6179191852758252278e+00)) + }; + static const T Q2[] = { + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.7253905888447681194e+18)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.7128800897135812012e+16)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 8.4899346165481429307e+13)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.7622777286244082666e+11)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 6.4872502899596389593e+08)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.1267125065029138050e+06)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.3886978985861357615e+03)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0)) + }; + static const T PC[] = { + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -4.4357578167941278571e+06)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -9.9422465050776411957e+06)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -6.6033732483649391093e+06)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.5235293511811373833e+06)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.0982405543459346727e+05)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.6116166443246101165e+03)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.0)) + }; + static const T QC[] = { + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -4.4357578167941278568e+06)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -9.9341243899345856590e+06)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -6.5853394797230870728e+06)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.5118095066341608816e+06)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.0726385991103820119e+05)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.4550094401904961825e+03)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0)) + }; + static const T PS[] = { + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.3220913409857223519e+04)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 8.5145160675335701966e+04)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 6.6178836581270835179e+04)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.8494262873223866797e+04)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.7063754290207680021e+03)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.5265133846636032186e+01)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.0)) + }; + static const T QS[] = { + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 7.0871281941028743574e+05)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.8194580422439972989e+06)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.4194606696037208929e+06)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.0029443582266975117e+05)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.7890229745772202641e+04)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 8.6383677696049909675e+02)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0)) + }; + static const T x1 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.8317059702075123156e+00)), + x2 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 7.0155866698156187535e+00)), + x11 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 9.810e+02)), + x12 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -3.2527979248768438556e-04)), + x21 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.7960e+03)), + x22 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -3.8330184381246462950e-05)); + + T value, factor, r, rc, rs, w; + + BOOST_MATH_STD_USING + using namespace boost::math::tools; + using namespace boost::math::constants; + + w = abs(x); + if (x == 0) + { + return static_cast<T>(0); + } + if (w <= 4) // w in (0, 4] + { + T y = x * x; + BOOST_ASSERT(sizeof(P1) == sizeof(Q1)); + r = evaluate_rational(P1, Q1, y); + factor = w * (w + x1) * ((w - x11/256) - x12); + value = factor * r; + } + else if (w <= 8) // w in (4, 8] + { + T y = x * x; + BOOST_ASSERT(sizeof(P2) == sizeof(Q2)); + r = evaluate_rational(P2, Q2, y); + factor = w * (w + x2) * ((w - x21/256) - x22); + value = factor * r; + } + else // w in (8, \infty) + { + T y = 8 / w; + T y2 = y * y; + BOOST_ASSERT(sizeof(PC) == sizeof(QC)); + BOOST_ASSERT(sizeof(PS) == sizeof(QS)); + rc = evaluate_rational(PC, QC, y2); + rs = evaluate_rational(PS, QS, y2); + factor = 1 / (sqrt(w) * constants::root_pi<T>()); + // + // What follows is really just: + // + // T z = w - 0.75f * pi<T>(); + // value = factor * (rc * cos(z) - y * rs * sin(z)); + // + // but using the sin/cos addition rules plus constants + // for the values of sin/cos of 3PI/4 which then cancel + // out with corresponding terms in "factor". + // + T sx = sin(x); + T cx = cos(x); + value = factor * (rc * (sx - cx) + y * rs * (sx + cx)); + } + + if (x < 0) + { + value *= -1; // odd function + } + return value; +} + +}}} // namespaces + +#endif // BOOST_MATH_BESSEL_J1_HPP + diff --git a/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_jn.hpp b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_jn.hpp new file mode 100644 index 00000000000..2413630637f --- /dev/null +++ b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_jn.hpp @@ -0,0 +1,133 @@ +// Copyright (c) 2006 Xiaogang Zhang +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_BESSEL_JN_HPP +#define BOOST_MATH_BESSEL_JN_HPP + +#ifdef _MSC_VER +#pragma once +#endif + +#include <boost/math/special_functions/detail/bessel_j0.hpp> +#include <boost/math/special_functions/detail/bessel_j1.hpp> +#include <boost/math/special_functions/detail/bessel_jy.hpp> +#include <boost/math/special_functions/detail/bessel_jy_asym.hpp> +#include <boost/math/special_functions/detail/bessel_jy_series.hpp> + +// Bessel function of the first kind of integer order +// J_n(z) is the minimal solution +// n < abs(z), forward recurrence stable and usable +// n >= abs(z), forward recurrence unstable, use Miller's algorithm + +namespace boost { namespace math { namespace detail{ + +template <typename T, typename Policy> +T bessel_jn(int n, T x, const Policy& pol) +{ + T value(0), factor, current, prev, next; + + BOOST_MATH_STD_USING + + // + // Reflection has to come first: + // + if (n < 0) + { + factor = static_cast<T>((n & 0x1) ? -1 : 1); // J_{-n}(z) = (-1)^n J_n(z) + n = -n; + } + else + { + factor = 1; + } + if(x < 0) + { + factor *= (n & 0x1) ? -1 : 1; // J_{n}(-z) = (-1)^n J_n(z) + x = -x; + } + // + // Special cases: + // + if(asymptotic_bessel_large_x_limit(T(n), x)) + return factor * asymptotic_bessel_j_large_x_2<T>(T(n), x); + if (n == 0) + { + return factor * bessel_j0(x); + } + if (n == 1) + { + return factor * bessel_j1(x); + } + + if (x == 0) // n >= 2 + { + return static_cast<T>(0); + } + + BOOST_ASSERT(n > 1); + T scale = 1; + if (n < abs(x)) // forward recurrence + { + prev = bessel_j0(x); + current = bessel_j1(x); + policies::check_series_iterations<T>("boost::math::bessel_j_n<%1%>(%1%,%1%)", n, pol); + for (int k = 1; k < n; k++) + { + T fact = 2 * k / x; + // + // rescale if we would overflow or underflow: + // + if((fabs(fact) > 1) && ((tools::max_value<T>() - fabs(prev)) / fabs(fact) < fabs(current))) + { + scale /= current; + prev /= current; + current = 1; + } + value = fact * current - prev; + prev = current; + current = value; + } + } + else if((x < 1) || (n > x * x / 4) || (x < 5)) + { + return factor * bessel_j_small_z_series(T(n), x, pol); + } + else // backward recurrence + { + T fn; int s; // fn = J_(n+1) / J_n + // |x| <= n, fast convergence for continued fraction CF1 + boost::math::detail::CF1_jy(static_cast<T>(n), x, &fn, &s, pol); + prev = fn; + current = 1; + // Check recursion won't go on too far: + policies::check_series_iterations<T>("boost::math::bessel_j_n<%1%>(%1%,%1%)", n, pol); + for (int k = n; k > 0; k--) + { + T fact = 2 * k / x; + if((fabs(fact) > 1) && ((tools::max_value<T>() - fabs(prev)) / fabs(fact) < fabs(current))) + { + prev /= current; + scale /= current; + current = 1; + } + next = fact * current - prev; + prev = current; + current = next; + } + value = bessel_j0(x) / current; // normalization + scale = 1 / scale; + } + value *= factor; + + if(tools::max_value<T>() * scale < fabs(value)) + return policies::raise_overflow_error<T>("boost::math::bessel_jn<%1%>(%1%,%1%)", 0, pol); + + return value / scale; +} + +}}} // namespaces + +#endif // BOOST_MATH_BESSEL_JN_HPP + diff --git a/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_jy.hpp b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_jy.hpp new file mode 100644 index 00000000000..b67d989b689 --- /dev/null +++ b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_jy.hpp @@ -0,0 +1,589 @@ +// Copyright (c) 2006 Xiaogang Zhang +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_BESSEL_JY_HPP +#define BOOST_MATH_BESSEL_JY_HPP + +#ifdef _MSC_VER +#pragma once +#endif + +#include <boost/math/tools/config.hpp> +#include <boost/math/special_functions/gamma.hpp> +#include <boost/math/special_functions/sign.hpp> +#include <boost/math/special_functions/hypot.hpp> +#include <boost/math/special_functions/sin_pi.hpp> +#include <boost/math/special_functions/cos_pi.hpp> +#include <boost/math/special_functions/detail/bessel_jy_asym.hpp> +#include <boost/math/special_functions/detail/bessel_jy_series.hpp> +#include <boost/math/constants/constants.hpp> +#include <boost/math/policies/error_handling.hpp> +#include <boost/mpl/if.hpp> +#include <boost/type_traits/is_floating_point.hpp> +#include <complex> + +// Bessel functions of the first and second kind of fractional order + +namespace boost { namespace math { + + namespace detail { + + // + // Simultaneous calculation of A&S 9.2.9 and 9.2.10 + // for use in A&S 9.2.5 and 9.2.6. + // This series is quick to evaluate, but divergent unless + // x is very large, in fact it's pretty hard to figure out + // with any degree of precision when this series actually + // *will* converge!! Consequently, we may just have to + // try it and see... + // + template <class T, class Policy> + bool hankel_PQ(T v, T x, T* p, T* q, const Policy& ) + { + BOOST_MATH_STD_USING + T tolerance = 2 * policies::get_epsilon<T, Policy>(); + *p = 1; + *q = 0; + T k = 1; + T z8 = 8 * x; + T sq = 1; + T mu = 4 * v * v; + T term = 1; + bool ok = true; + do + { + term *= (mu - sq * sq) / (k * z8); + *q += term; + k += 1; + sq += 2; + T mult = (sq * sq - mu) / (k * z8); + ok = fabs(mult) < 0.5f; + term *= mult; + *p += term; + k += 1; + sq += 2; + } + while((fabs(term) > tolerance * *p) && ok); + return ok; + } + + // Calculate Y(v, x) and Y(v+1, x) by Temme's method, see + // Temme, Journal of Computational Physics, vol 21, 343 (1976) + template <typename T, typename Policy> + int temme_jy(T v, T x, T* Y, T* Y1, const Policy& pol) + { + T g, h, p, q, f, coef, sum, sum1, tolerance; + T a, d, e, sigma; + unsigned long k; + + BOOST_MATH_STD_USING + using namespace boost::math::tools; + using namespace boost::math::constants; + + BOOST_ASSERT(fabs(v) <= 0.5f); // precondition for using this routine + + T gp = boost::math::tgamma1pm1(v, pol); + T gm = boost::math::tgamma1pm1(-v, pol); + T spv = boost::math::sin_pi(v, pol); + T spv2 = boost::math::sin_pi(v/2, pol); + T xp = pow(x/2, v); + + a = log(x / 2); + sigma = -a * v; + d = abs(sigma) < tools::epsilon<T>() ? + T(1) : sinh(sigma) / sigma; + e = abs(v) < tools::epsilon<T>() ? T(v*pi<T>()*pi<T>() / 2) + : T(2 * spv2 * spv2 / v); + + T g1 = (v == 0) ? T(-euler<T>()) : T((gp - gm) / ((1 + gp) * (1 + gm) * 2 * v)); + T g2 = (2 + gp + gm) / ((1 + gp) * (1 + gm) * 2); + T vspv = (fabs(v) < tools::epsilon<T>()) ? T(1/constants::pi<T>()) : T(v / spv); + f = (g1 * cosh(sigma) - g2 * a * d) * 2 * vspv; + + p = vspv / (xp * (1 + gm)); + q = vspv * xp / (1 + gp); + + g = f + e * q; + h = p; + coef = 1; + sum = coef * g; + sum1 = coef * h; + + T v2 = v * v; + T coef_mult = -x * x / 4; + + // series summation + tolerance = policies::get_epsilon<T, Policy>(); + for (k = 1; k < policies::get_max_series_iterations<Policy>(); k++) + { + f = (k * f + p + q) / (k*k - v2); + p /= k - v; + q /= k + v; + g = f + e * q; + h = p - k * g; + coef *= coef_mult / k; + sum += coef * g; + sum1 += coef * h; + if (abs(coef * g) < abs(sum) * tolerance) + { + break; + } + } + policies::check_series_iterations<T>("boost::math::bessel_jy<%1%>(%1%,%1%) in temme_jy", k, pol); + *Y = -sum; + *Y1 = -2 * sum1 / x; + + return 0; + } + + // Evaluate continued fraction fv = J_(v+1) / J_v, see + // Abramowitz and Stegun, Handbook of Mathematical Functions, 1972, 9.1.73 + template <typename T, typename Policy> + int CF1_jy(T v, T x, T* fv, int* sign, const Policy& pol) + { + T C, D, f, a, b, delta, tiny, tolerance; + unsigned long k; + int s = 1; + + BOOST_MATH_STD_USING + + // |x| <= |v|, CF1_jy converges rapidly + // |x| > |v|, CF1_jy needs O(|x|) iterations to converge + + // modified Lentz's method, see + // Lentz, Applied Optics, vol 15, 668 (1976) + tolerance = 2 * policies::get_epsilon<T, Policy>();; + tiny = sqrt(tools::min_value<T>()); + C = f = tiny; // b0 = 0, replace with tiny + D = 0; + for (k = 1; k < policies::get_max_series_iterations<Policy>() * 100; k++) + { + a = -1; + b = 2 * (v + k) / x; + C = b + a / C; + D = b + a * D; + if (C == 0) { C = tiny; } + if (D == 0) { D = tiny; } + D = 1 / D; + delta = C * D; + f *= delta; + if (D < 0) { s = -s; } + if (abs(delta - 1) < tolerance) + { break; } + } + policies::check_series_iterations<T>("boost::math::bessel_jy<%1%>(%1%,%1%) in CF1_jy", k / 100, pol); + *fv = -f; + *sign = s; // sign of denominator + + return 0; + } + // + // This algorithm was originally written by Xiaogang Zhang + // using std::complex to perform the complex arithmetic. + // However, that turns out to 10x or more slower than using + // all real-valued arithmetic, so it's been rewritten using + // real values only. + // + template <typename T, typename Policy> + int CF2_jy(T v, T x, T* p, T* q, const Policy& pol) + { + BOOST_MATH_STD_USING + + T Cr, Ci, Dr, Di, fr, fi, a, br, bi, delta_r, delta_i, temp; + T tiny; + unsigned long k; + + // |x| >= |v|, CF2_jy converges rapidly + // |x| -> 0, CF2_jy fails to converge + BOOST_ASSERT(fabs(x) > 1); + + // modified Lentz's method, complex numbers involved, see + // Lentz, Applied Optics, vol 15, 668 (1976) + T tolerance = 2 * policies::get_epsilon<T, Policy>(); + tiny = sqrt(tools::min_value<T>()); + Cr = fr = -0.5f / x; + Ci = fi = 1; + //Dr = Di = 0; + T v2 = v * v; + a = (0.25f - v2) / x; // Note complex this one time only! + br = 2 * x; + bi = 2; + temp = Cr * Cr + 1; + Ci = bi + a * Cr / temp; + Cr = br + a / temp; + Dr = br; + Di = bi; + if (fabs(Cr) + fabs(Ci) < tiny) { Cr = tiny; } + if (fabs(Dr) + fabs(Di) < tiny) { Dr = tiny; } + temp = Dr * Dr + Di * Di; + Dr = Dr / temp; + Di = -Di / temp; + delta_r = Cr * Dr - Ci * Di; + delta_i = Ci * Dr + Cr * Di; + temp = fr; + fr = temp * delta_r - fi * delta_i; + fi = temp * delta_i + fi * delta_r; + for (k = 2; k < policies::get_max_series_iterations<Policy>(); k++) + { + a = k - 0.5f; + a *= a; + a -= v2; + bi += 2; + temp = Cr * Cr + Ci * Ci; + Cr = br + a * Cr / temp; + Ci = bi - a * Ci / temp; + Dr = br + a * Dr; + Di = bi + a * Di; + if (fabs(Cr) + fabs(Ci) < tiny) { Cr = tiny; } + if (fabs(Dr) + fabs(Di) < tiny) { Dr = tiny; } + temp = Dr * Dr + Di * Di; + Dr = Dr / temp; + Di = -Di / temp; + delta_r = Cr * Dr - Ci * Di; + delta_i = Ci * Dr + Cr * Di; + temp = fr; + fr = temp * delta_r - fi * delta_i; + fi = temp * delta_i + fi * delta_r; + if (fabs(delta_r - 1) + fabs(delta_i) < tolerance) + break; + } + policies::check_series_iterations<T>("boost::math::bessel_jy<%1%>(%1%,%1%) in CF2_jy", k, pol); + *p = fr; + *q = fi; + + return 0; + } + + static const int need_j = 1; + static const int need_y = 2; + + // Compute J(v, x) and Y(v, x) simultaneously by Steed's method, see + // Barnett et al, Computer Physics Communications, vol 8, 377 (1974) + template <typename T, typename Policy> + int bessel_jy(T v, T x, T* J, T* Y, int kind, const Policy& pol) + { + BOOST_ASSERT(x >= 0); + + T u, Jv, Ju, Yv, Yv1, Yu, Yu1(0), fv, fu; + T W, p, q, gamma, current, prev, next; + bool reflect = false; + unsigned n, k; + int s; + int org_kind = kind; + T cp = 0; + T sp = 0; + + static const char* function = "boost::math::bessel_jy<%1%>(%1%,%1%)"; + + BOOST_MATH_STD_USING + using namespace boost::math::tools; + using namespace boost::math::constants; + + if (v < 0) + { + reflect = true; + v = -v; // v is non-negative from here + } + if (v > static_cast<T>((std::numeric_limits<int>::max)())) + { + *J = *Y = policies::raise_evaluation_error<T>(function, "Order of Bessel function is too large to evaluate: got %1%", v, pol); + return 1; + } + n = iround(v, pol); + u = v - n; // -1/2 <= u < 1/2 + + if(reflect) + { + T z = (u + n % 2); + cp = boost::math::cos_pi(z, pol); + sp = boost::math::sin_pi(z, pol); + if(u != 0) + kind = need_j|need_y; // need both for reflection formula + } + + if(x == 0) + { + if(v == 0) + *J = 1; + else if((u == 0) || !reflect) + *J = 0; + else if(kind & need_j) + *J = policies::raise_domain_error<T>(function, "Value of Bessel J_v(x) is complex-infinity at %1%", x, pol); // complex infinity + else + *J = std::numeric_limits<T>::quiet_NaN(); // any value will do, not using J. + + if((kind & need_y) == 0) + *Y = std::numeric_limits<T>::quiet_NaN(); // any value will do, not using Y. + else if(v == 0) + *Y = -policies::raise_overflow_error<T>(function, 0, pol); + else + *Y = policies::raise_domain_error<T>(function, "Value of Bessel Y_v(x) is complex-infinity at %1%", x, pol); // complex infinity + return 1; + } + + // x is positive until reflection + W = T(2) / (x * pi<T>()); // Wronskian + T Yv_scale = 1; + if(((kind & need_y) == 0) && ((x < 1) || (v > x * x / 4) || (x < 5))) + { + // + // This series will actually converge rapidly for all small + // x - say up to x < 20 - but the first few terms are large + // and divergent which leads to large errors :-( + // + Jv = bessel_j_small_z_series(v, x, pol); + Yv = std::numeric_limits<T>::quiet_NaN(); + } + else if((x < 1) && (u != 0) && (log(policies::get_epsilon<T, Policy>() / 2) > v * log((x/2) * (x/2) / v))) + { + // Evaluate using series representations. + // This is particularly important for x << v as in this + // area temme_jy may be slow to converge, if it converges at all. + // Requires x is not an integer. + if(kind&need_j) + Jv = bessel_j_small_z_series(v, x, pol); + else + Jv = std::numeric_limits<T>::quiet_NaN(); + if((org_kind&need_y && (!reflect || (cp != 0))) + || (org_kind & need_j && (reflect && (sp != 0)))) + { + // Only calculate if we need it, and if the reflection formula will actually use it: + Yv = bessel_y_small_z_series(v, x, &Yv_scale, pol); + } + else + Yv = std::numeric_limits<T>::quiet_NaN(); + } + else if((u == 0) && (x < policies::get_epsilon<T, Policy>())) + { + // Truncated series evaluation for small x and v an integer, + // much quicker in this area than temme_jy below. + if(kind&need_j) + Jv = bessel_j_small_z_series(v, x, pol); + else + Jv = std::numeric_limits<T>::quiet_NaN(); + if((org_kind&need_y && (!reflect || (cp != 0))) + || (org_kind & need_j && (reflect && (sp != 0)))) + { + // Only calculate if we need it, and if the reflection formula will actually use it: + Yv = bessel_yn_small_z(n, x, &Yv_scale, pol); + } + else + Yv = std::numeric_limits<T>::quiet_NaN(); + } + else if(asymptotic_bessel_large_x_limit(v, x)) + { + if(kind&need_y) + { + Yv = asymptotic_bessel_y_large_x_2(v, x); + } + else + Yv = std::numeric_limits<T>::quiet_NaN(); // any value will do, we're not using it. + if(kind&need_j) + { + Jv = asymptotic_bessel_j_large_x_2(v, x); + } + else + Jv = std::numeric_limits<T>::quiet_NaN(); // any value will do, we're not using it. + } + else if((x > 8) && hankel_PQ(v, x, &p, &q, pol)) + { + // + // Hankel approximation: note that this method works best when x + // is large, but in that case we end up calculating sines and cosines + // of large values, with horrendous resulting accuracy. It is fast though + // when it works.... + // + // Normally we calculate sin/cos(chi) where: + // + // chi = x - fmod(T(v / 2 + 0.25f), T(2)) * boost::math::constants::pi<T>(); + // + // But this introduces large errors, so use sin/cos addition formulae to + // improve accuracy: + // + T mod_v = fmod(T(v / 2 + 0.25f), T(2)); + T sx = sin(x); + T cx = cos(x); + T sv = sin_pi(mod_v); + T cv = cos_pi(mod_v); + + T sc = sx * cv - sv * cx; // == sin(chi); + T cc = cx * cv + sx * sv; // == cos(chi); + T chi = boost::math::constants::root_two<T>() / (boost::math::constants::root_pi<T>() * sqrt(x)); //sqrt(2 / (boost::math::constants::pi<T>() * x)); + Yv = chi * (p * sc + q * cc); + Jv = chi * (p * cc - q * sc); + } + else if (x <= 2) // x in (0, 2] + { + if(temme_jy(u, x, &Yu, &Yu1, pol)) // Temme series + { + // domain error: + *J = *Y = Yu; + return 1; + } + prev = Yu; + current = Yu1; + T scale = 1; + policies::check_series_iterations<T>(function, n, pol); + for (k = 1; k <= n; k++) // forward recurrence for Y + { + T fact = 2 * (u + k) / x; + if((tools::max_value<T>() - fabs(prev)) / fact < fabs(current)) + { + scale /= current; + prev /= current; + current = 1; + } + next = fact * current - prev; + prev = current; + current = next; + } + Yv = prev; + Yv1 = current; + if(kind&need_j) + { + CF1_jy(v, x, &fv, &s, pol); // continued fraction CF1_jy + Jv = scale * W / (Yv * fv - Yv1); // Wronskian relation + } + else + Jv = std::numeric_limits<T>::quiet_NaN(); // any value will do, we're not using it. + Yv_scale = scale; + } + else // x in (2, \infty) + { + // Get Y(u, x): + + T ratio; + CF1_jy(v, x, &fv, &s, pol); + // tiny initial value to prevent overflow + T init = sqrt(tools::min_value<T>()); + BOOST_MATH_INSTRUMENT_VARIABLE(init); + prev = fv * s * init; + current = s * init; + if(v < max_factorial<T>::value) + { + policies::check_series_iterations<T>(function, n, pol); + for (k = n; k > 0; k--) // backward recurrence for J + { + next = 2 * (u + k) * current / x - prev; + prev = current; + current = next; + } + ratio = (s * init) / current; // scaling ratio + // can also call CF1_jy() to get fu, not much difference in precision + fu = prev / current; + } + else + { + // + // When v is large we may get overflow in this calculation + // leading to NaN's and other nasty surprises: + // + policies::check_series_iterations<T>(function, n, pol); + bool over = false; + for (k = n; k > 0; k--) // backward recurrence for J + { + T t = 2 * (u + k) / x; + if((t > 1) && (tools::max_value<T>() / t < current)) + { + over = true; + break; + } + next = t * current - prev; + prev = current; + current = next; + } + if(!over) + { + ratio = (s * init) / current; // scaling ratio + // can also call CF1_jy() to get fu, not much difference in precision + fu = prev / current; + } + else + { + ratio = 0; + fu = 1; + } + } + CF2_jy(u, x, &p, &q, pol); // continued fraction CF2_jy + T t = u / x - fu; // t = J'/J + gamma = (p - t) / q; + // + // We can't allow gamma to cancel out to zero competely as it messes up + // the subsequent logic. So pretend that one bit didn't cancel out + // and set to a suitably small value. The only test case we've been able to + // find for this, is when v = 8.5 and x = 4*PI. + // + if(gamma == 0) + { + gamma = u * tools::epsilon<T>() / x; + } + BOOST_MATH_INSTRUMENT_VARIABLE(current); + BOOST_MATH_INSTRUMENT_VARIABLE(W); + BOOST_MATH_INSTRUMENT_VARIABLE(q); + BOOST_MATH_INSTRUMENT_VARIABLE(gamma); + BOOST_MATH_INSTRUMENT_VARIABLE(p); + BOOST_MATH_INSTRUMENT_VARIABLE(t); + Ju = sign(current) * sqrt(W / (q + gamma * (p - t))); + BOOST_MATH_INSTRUMENT_VARIABLE(Ju); + + Jv = Ju * ratio; // normalization + + Yu = gamma * Ju; + Yu1 = Yu * (u/x - p - q/gamma); + + if(kind&need_y) + { + // compute Y: + prev = Yu; + current = Yu1; + policies::check_series_iterations<T>(function, n, pol); + for (k = 1; k <= n; k++) // forward recurrence for Y + { + T fact = 2 * (u + k) / x; + if((tools::max_value<T>() - fabs(prev)) / fact < fabs(current)) + { + prev /= current; + Yv_scale /= current; + current = 1; + } + next = fact * current - prev; + prev = current; + current = next; + } + Yv = prev; + } + else + Yv = std::numeric_limits<T>::quiet_NaN(); // any value will do, we're not using it. + } + + if (reflect) + { + if((sp != 0) && (tools::max_value<T>() * fabs(Yv_scale) < fabs(sp * Yv))) + *J = org_kind & need_j ? T(-sign(sp) * sign(Yv) * sign(Yv_scale) * policies::raise_overflow_error<T>(function, 0, pol)) : T(0); + else + *J = cp * Jv - (sp == 0 ? T(0) : T((sp * Yv) / Yv_scale)); // reflection formula + if((cp != 0) && (tools::max_value<T>() * fabs(Yv_scale) < fabs(cp * Yv))) + *Y = org_kind & need_y ? T(-sign(cp) * sign(Yv) * sign(Yv_scale) * policies::raise_overflow_error<T>(function, 0, pol)) : T(0); + else + *Y = (sp != 0 ? sp * Jv : T(0)) + (cp == 0 ? T(0) : T((cp * Yv) / Yv_scale)); + } + else + { + *J = Jv; + if(tools::max_value<T>() * fabs(Yv_scale) < fabs(Yv)) + *Y = org_kind & need_y ? T(sign(Yv) * sign(Yv_scale) * policies::raise_overflow_error<T>(function, 0, pol)) : T(0); + else + *Y = Yv / Yv_scale; + } + + return 0; + } + + } // namespace detail + +}} // namespaces + +#endif // BOOST_MATH_BESSEL_JY_HPP + diff --git a/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_jy_asym.hpp b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_jy_asym.hpp new file mode 100644 index 00000000000..4d7ac485ad6 --- /dev/null +++ b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_jy_asym.hpp @@ -0,0 +1,223 @@ +// Copyright (c) 2007 John Maddock +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// +// This is a partial header, do not include on it's own!!! +// +// Contains asymptotic expansions for Bessel J(v,x) and Y(v,x) +// functions, as x -> INF. +// +#ifndef BOOST_MATH_SF_DETAIL_BESSEL_JY_ASYM_HPP +#define BOOST_MATH_SF_DETAIL_BESSEL_JY_ASYM_HPP + +#ifdef _MSC_VER +#pragma once +#endif + +#include <boost/math/special_functions/factorials.hpp> + +namespace boost{ namespace math{ namespace detail{ + +template <class T> +inline T asymptotic_bessel_amplitude(T v, T x) +{ + // Calculate the amplitude of J(v, x) and Y(v, x) for large + // x: see A&S 9.2.28. + BOOST_MATH_STD_USING + T s = 1; + T mu = 4 * v * v; + T txq = 2 * x; + txq *= txq; + + s += (mu - 1) / (2 * txq); + s += 3 * (mu - 1) * (mu - 9) / (txq * txq * 8); + s += 15 * (mu - 1) * (mu - 9) * (mu - 25) / (txq * txq * txq * 8 * 6); + + return sqrt(s * 2 / (constants::pi<T>() * x)); +} + +template <class T> +T asymptotic_bessel_phase_mx(T v, T x) +{ + // + // Calculate the phase of J(v, x) and Y(v, x) for large x. + // See A&S 9.2.29. + // Note that the result returned is the phase less (x - PI(v/2 + 1/4)) + // which we'll factor in later when we calculate the sines/cosines of the result: + // + T mu = 4 * v * v; + T denom = 4 * x; + T denom_mult = denom * denom; + + T s = 0; + s += (mu - 1) / (2 * denom); + denom *= denom_mult; + s += (mu - 1) * (mu - 25) / (6 * denom); + denom *= denom_mult; + s += (mu - 1) * (mu * mu - 114 * mu + 1073) / (5 * denom); + denom *= denom_mult; + s += (mu - 1) * (5 * mu * mu * mu - 1535 * mu * mu + 54703 * mu - 375733) / (14 * denom); + return s; +} + +template <class T> +inline T asymptotic_bessel_y_large_x_2(T v, T x) +{ + // See A&S 9.2.19. + BOOST_MATH_STD_USING + // Get the phase and amplitude: + T ampl = asymptotic_bessel_amplitude(v, x); + T phase = asymptotic_bessel_phase_mx(v, x); + BOOST_MATH_INSTRUMENT_VARIABLE(ampl); + BOOST_MATH_INSTRUMENT_VARIABLE(phase); + // + // Calculate the sine of the phase, using + // sine/cosine addition rules to factor in + // the x - PI(v/2 + 1/4) term not added to the + // phase when we calculated it. + // + T cx = cos(x); + T sx = sin(x); + T ci = cos_pi(v / 2 + 0.25f); + T si = sin_pi(v / 2 + 0.25f); + T sin_phase = sin(phase) * (cx * ci + sx * si) + cos(phase) * (sx * ci - cx * si); + BOOST_MATH_INSTRUMENT_CODE(sin(phase)); + BOOST_MATH_INSTRUMENT_CODE(cos(x)); + BOOST_MATH_INSTRUMENT_CODE(cos(phase)); + BOOST_MATH_INSTRUMENT_CODE(sin(x)); + return sin_phase * ampl; +} + +template <class T> +inline T asymptotic_bessel_j_large_x_2(T v, T x) +{ + // See A&S 9.2.19. + BOOST_MATH_STD_USING + // Get the phase and amplitude: + T ampl = asymptotic_bessel_amplitude(v, x); + T phase = asymptotic_bessel_phase_mx(v, x); + BOOST_MATH_INSTRUMENT_VARIABLE(ampl); + BOOST_MATH_INSTRUMENT_VARIABLE(phase); + // + // Calculate the sine of the phase, using + // sine/cosine addition rules to factor in + // the x - PI(v/2 + 1/4) term not added to the + // phase when we calculated it. + // + BOOST_MATH_INSTRUMENT_CODE(cos(phase)); + BOOST_MATH_INSTRUMENT_CODE(cos(x)); + BOOST_MATH_INSTRUMENT_CODE(sin(phase)); + BOOST_MATH_INSTRUMENT_CODE(sin(x)); + T cx = cos(x); + T sx = sin(x); + T ci = cos_pi(v / 2 + 0.25f); + T si = sin_pi(v / 2 + 0.25f); + T sin_phase = cos(phase) * (cx * ci + sx * si) - sin(phase) * (sx * ci - cx * si); + BOOST_MATH_INSTRUMENT_VARIABLE(sin_phase); + return sin_phase * ampl; +} + +template <class T> +inline bool asymptotic_bessel_large_x_limit(int v, const T& x) +{ + BOOST_MATH_STD_USING + // + // Determines if x is large enough compared to v to take the asymptotic + // forms above. From A&S 9.2.28 we require: + // v < x * eps^1/8 + // and from A&S 9.2.29 we require: + // v^12/10 < 1.5 * x * eps^1/10 + // using the former seems to work OK in practice with broadly similar + // error rates either side of the divide for v < 10000. + // At double precision eps^1/8 ~= 0.01. + // + BOOST_ASSERT(v >= 0); + return (v ? v : 1) < x * 0.004f; +} + +template <class T> +inline bool asymptotic_bessel_large_x_limit(const T& v, const T& x) +{ + BOOST_MATH_STD_USING + // + // Determines if x is large enough compared to v to take the asymptotic + // forms above. From A&S 9.2.28 we require: + // v < x * eps^1/8 + // and from A&S 9.2.29 we require: + // v^12/10 < 1.5 * x * eps^1/10 + // using the former seems to work OK in practice with broadly similar + // error rates either side of the divide for v < 10000. + // At double precision eps^1/8 ~= 0.01. + // + return (std::max)(T(fabs(v)), T(1)) < x * sqrt(tools::forth_root_epsilon<T>()); +} + +template <class T, class Policy> +void temme_asyptotic_y_small_x(T v, T x, T* Y, T* Y1, const Policy& pol) +{ + T c = 1; + T p = (v / boost::math::sin_pi(v, pol)) * pow(x / 2, -v) / boost::math::tgamma(1 - v, pol); + T q = (v / boost::math::sin_pi(v, pol)) * pow(x / 2, v) / boost::math::tgamma(1 + v, pol); + T f = (p - q) / v; + T g_prefix = boost::math::sin_pi(v / 2, pol); + g_prefix *= g_prefix * 2 / v; + T g = f + g_prefix * q; + T h = p; + T c_mult = -x * x / 4; + + T y(c * g), y1(c * h); + + for(int k = 1; k < policies::get_max_series_iterations<Policy>(); ++k) + { + f = (k * f + p + q) / (k*k - v*v); + p /= k - v; + q /= k + v; + c *= c_mult / k; + T c1 = pow(-x * x / 4, k) / factorial<T>(k, pol); + g = f + g_prefix * q; + h = -k * g + p; + y += c * g; + y1 += c * h; + if(c * g / tools::epsilon<T>() < y) + break; + } + + *Y = -y; + *Y1 = (-2 / x) * y1; +} + +template <class T, class Policy> +T asymptotic_bessel_i_large_x(T v, T x, const Policy& pol) +{ + BOOST_MATH_STD_USING // ADL of std names + T s = 1; + T mu = 4 * v * v; + T ex = 8 * x; + T num = mu - 1; + T denom = ex; + + s -= num / denom; + + num *= mu - 9; + denom *= ex * 2; + s += num / denom; + + num *= mu - 25; + denom *= ex * 3; + s -= num / denom; + + // Try and avoid overflow to the last minute: + T e = exp(x/2); + + s = e * (e * s / sqrt(2 * x * constants::pi<T>())); + + return (boost::math::isfinite)(s) ? + s : policies::raise_overflow_error<T>("boost::math::asymptotic_bessel_i_large_x<%1%>(%1%,%1%)", 0, pol); +} + +}}} // namespaces + +#endif + diff --git a/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_jy_series.hpp b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_jy_series.hpp new file mode 100644 index 00000000000..d50bef84e81 --- /dev/null +++ b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_jy_series.hpp @@ -0,0 +1,261 @@ +// Copyright (c) 2011 John Maddock +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_BESSEL_JN_SERIES_HPP +#define BOOST_MATH_BESSEL_JN_SERIES_HPP + +#ifdef _MSC_VER +#pragma once +#endif + +namespace boost { namespace math { namespace detail{ + +template <class T, class Policy> +struct bessel_j_small_z_series_term +{ + typedef T result_type; + + bessel_j_small_z_series_term(T v_, T x) + : N(0), v(v_) + { + BOOST_MATH_STD_USING + mult = x / 2; + mult *= -mult; + term = 1; + } + T operator()() + { + T r = term; + ++N; + term *= mult / (N * (N + v)); + return r; + } +private: + unsigned N; + T v; + T mult; + T term; +}; +// +// Series evaluation for BesselJ(v, z) as z -> 0. +// See http://functions.wolfram.com/Bessel-TypeFunctions/BesselJ/06/01/04/01/01/0003/ +// Converges rapidly for all z << v. +// +template <class T, class Policy> +inline T bessel_j_small_z_series(T v, T x, const Policy& pol) +{ + BOOST_MATH_STD_USING + T prefix; + if(v < max_factorial<T>::value) + { + prefix = pow(x / 2, v) / boost::math::tgamma(v+1, pol); + } + else + { + prefix = v * log(x / 2) - boost::math::lgamma(v+1, pol); + prefix = exp(prefix); + } + if(0 == prefix) + return prefix; + + bessel_j_small_z_series_term<T, Policy> s(v, x); + boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>(); +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) + T zero = 0; + T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon<T, Policy>(), max_iter, zero); +#else + T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon<T, Policy>(), max_iter); +#endif + policies::check_series_iterations<T>("boost::math::bessel_j_small_z_series<%1%>(%1%,%1%)", max_iter, pol); + return prefix * result; +} + +template <class T, class Policy> +struct bessel_y_small_z_series_term_a +{ + typedef T result_type; + + bessel_y_small_z_series_term_a(T v_, T x) + : N(0), v(v_) + { + BOOST_MATH_STD_USING + mult = x / 2; + mult *= -mult; + term = 1; + } + T operator()() + { + BOOST_MATH_STD_USING + T r = term; + ++N; + term *= mult / (N * (N - v)); + return r; + } +private: + unsigned N; + T v; + T mult; + T term; +}; + +template <class T, class Policy> +struct bessel_y_small_z_series_term_b +{ + typedef T result_type; + + bessel_y_small_z_series_term_b(T v_, T x) + : N(0), v(v_) + { + BOOST_MATH_STD_USING + mult = x / 2; + mult *= -mult; + term = 1; + } + T operator()() + { + T r = term; + ++N; + term *= mult / (N * (N + v)); + return r; + } +private: + unsigned N; + T v; + T mult; + T term; +}; +// +// Series form for BesselY as z -> 0, +// see: http://functions.wolfram.com/Bessel-TypeFunctions/BesselY/06/01/04/01/01/0003/ +// This series is only useful when the second term is small compared to the first +// otherwise we get catestrophic cancellation errors. +// +// Approximating tgamma(v) by v^v, and assuming |tgamma(-z)| < eps we end up requiring: +// eps/2 * v^v(x/2)^-v > (x/2)^v or log(eps/2) > v log((x/2)^2/v) +// +template <class T, class Policy> +inline T bessel_y_small_z_series(T v, T x, T* pscale, const Policy& pol) +{ + BOOST_MATH_STD_USING + static const char* function = "bessel_y_small_z_series<%1%>(%1%,%1%)"; + T prefix; + T gam; + T p = log(x / 2); + T scale = 1; + bool need_logs = (v >= max_factorial<T>::value) || (tools::log_max_value<T>() / v < fabs(p)); + if(!need_logs) + { + gam = boost::math::tgamma(v, pol); + p = pow(x / 2, v); + if(tools::max_value<T>() * p < gam) + { + scale /= gam; + gam = 1; + if(tools::max_value<T>() * p < gam) + { + return -policies::raise_overflow_error<T>(function, 0, pol); + } + } + prefix = -gam / (constants::pi<T>() * p); + } + else + { + gam = boost::math::lgamma(v, pol); + p = v * p; + prefix = gam - log(constants::pi<T>()) - p; + if(tools::log_max_value<T>() < prefix) + { + prefix -= log(tools::max_value<T>() / 4); + scale /= (tools::max_value<T>() / 4); + if(tools::log_max_value<T>() < prefix) + { + return -policies::raise_overflow_error<T>(function, 0, pol); + } + } + prefix = -exp(prefix); + } + bessel_y_small_z_series_term_a<T, Policy> s(v, x); + boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>(); + *pscale = scale; +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) + T zero = 0; + T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon<T, Policy>(), max_iter, zero); +#else + T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon<T, Policy>(), max_iter); +#endif + policies::check_series_iterations<T>("boost::math::bessel_y_small_z_series<%1%>(%1%,%1%)", max_iter, pol); + result *= prefix; + + if(!need_logs) + { + prefix = boost::math::tgamma(-v, pol) * boost::math::cos_pi(v) * p / constants::pi<T>(); + } + else + { + int sgn; + prefix = boost::math::lgamma(-v, &sgn, pol) + p; + prefix = exp(prefix) * sgn / constants::pi<T>(); + } + bessel_y_small_z_series_term_b<T, Policy> s2(v, x); + max_iter = policies::get_max_series_iterations<Policy>(); +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) + T b = boost::math::tools::sum_series(s2, boost::math::policies::get_epsilon<T, Policy>(), max_iter, zero); +#else + T b = boost::math::tools::sum_series(s2, boost::math::policies::get_epsilon<T, Policy>(), max_iter); +#endif + result -= scale * prefix * b; + return result; +} + +template <class T, class Policy> +T bessel_yn_small_z(int n, T z, T* scale, const Policy& pol) +{ + // + // See http://functions.wolfram.com/Bessel-TypeFunctions/BesselY/06/01/04/01/02/ + // + // Note that when called we assume that x < epsilon and n is a positive integer. + // + BOOST_MATH_STD_USING + BOOST_ASSERT(n >= 0); + BOOST_ASSERT((z < policies::get_epsilon<T, Policy>())); + + if(n == 0) + { + return (2 / constants::pi<T>()) * (log(z / 2) + constants::euler<T>()); + } + else if(n == 1) + { + return (z / constants::pi<T>()) * log(z / 2) + - 2 / (constants::pi<T>() * z) + - (z / (2 * constants::pi<T>())) * (1 - 2 * constants::euler<T>()); + } + else if(n == 2) + { + return (z * z) / (4 * constants::pi<T>()) * log(z / 2) + - (4 / (constants::pi<T>() * z * z)) + - ((z * z) / (8 * constants::pi<T>())) * (T(3)/2 - 2 * constants::euler<T>()); + } + else + { + T p = pow(z / 2, n); + T result = -((boost::math::factorial<T>(n - 1) / constants::pi<T>())); + if(p * tools::max_value<T>() < result) + { + T div = tools::max_value<T>() / 8; + result /= div; + *scale /= div; + if(p * tools::max_value<T>() < result) + { + return -policies::raise_overflow_error<T>("bessel_yn_small_z<%1%>(%1%,%1%)", 0, pol); + } + } + return result / p; + } +} + +}}} // namespaces + +#endif // BOOST_MATH_BESSEL_JN_SERIES_HPP + diff --git a/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_jy_zero.hpp b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_jy_zero.hpp new file mode 100644 index 00000000000..ecd8696eeeb --- /dev/null +++ b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_jy_zero.hpp @@ -0,0 +1,617 @@ +// Copyright (c) 2013 Christopher Kormanyos +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// This work is based on an earlier work: +// "Algorithm 910: A Portable C++ Multiple-Precision System for Special-Function Calculations", +// in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. http://doi.acm.org/10.1145/1916461.1916469 +// +// This header contains implementation details for estimating the zeros +// of cylindrical Bessel and Neumann functions on the positive real axis. +// Support is included for both positive as well as negative order. +// Various methods are used to estimate the roots. These include +// empirical curve fitting and McMahon's asymptotic approximation +// for small order, uniform asymptotic expansion for large order, +// and iteration and root interlacing for negative order. +// +#ifndef _BESSEL_JY_ZERO_2013_01_18_HPP_ + #define _BESSEL_JY_ZERO_2013_01_18_HPP_ + + #include <algorithm> + #include <boost/math/constants/constants.hpp> + #include <boost/math/special_functions/math_fwd.hpp> + #include <boost/math/special_functions/cbrt.hpp> + #include <boost/math/special_functions/detail/airy_ai_bi_zero.hpp> + + namespace boost { namespace math { + namespace detail + { + namespace bessel_zero + { + template<class T> + T equation_nist_10_21_19(const T& v, const T& a) + { + // Get the initial estimate of the m'th root of Jv or Yv. + // This subroutine is used for the order m with m > 1. + // The order m has been used to create the input parameter a. + + // This is Eq. 10.21.19 in the NIST Handbook. + const T mu = (v * v) * 4U; + const T mu_minus_one = mu - T(1); + const T eight_a_inv = T(1) / (a * 8U); + const T eight_a_inv_squared = eight_a_inv * eight_a_inv; + + const T term3 = ((mu_minus_one * 4U) * ((mu * 7U) - T(31U) )) / 3U; + const T term5 = ((mu_minus_one * 32U) * ((((mu * 83U) - T(982U) ) * mu) + T(3779U) )) / 15U; + const T term7 = ((mu_minus_one * 64U) * ((((((mu * 6949U) - T(153855UL)) * mu) + T(1585743UL)) * mu) - T(6277237UL))) / 105U; + + return a + (((( - term7 + * eight_a_inv_squared - term5) + * eight_a_inv_squared - term3) + * eight_a_inv_squared - mu_minus_one) + * eight_a_inv); + } + + template<typename T> + class equation_as_9_3_39_and_its_derivative + { + public: + equation_as_9_3_39_and_its_derivative(const T& zt) : zeta(zt) { } + + boost::math::tuple<T, T> operator()(const T& z) const + { + BOOST_MATH_STD_USING // ADL of std names, needed for acos, sqrt. + + // Return the function of zeta that is implicitly defined + // in A&S Eq. 9.3.39 as a function of z. The function is + // returned along with its derivative with respect to z. + + const T zsq_minus_one_sqrt = sqrt((z * z) - T(1)); + + const T the_function( + zsq_minus_one_sqrt + - ( acos(T(1) / z) + ((T(2) / 3U) * (zeta * sqrt(zeta))))); + + const T its_derivative(zsq_minus_one_sqrt / z); + + return boost::math::tuple<T, T>(the_function, its_derivative); + } + + private: + const equation_as_9_3_39_and_its_derivative& operator=(const equation_as_9_3_39_and_its_derivative&); + const T zeta; + }; + + template<class T> + static T equation_as_9_5_26(const T& v, const T& ai_bi_root) + { + BOOST_MATH_STD_USING // ADL of std names, needed for log, sqrt. + + // Obtain the estimate of the m'th zero of Jv or Yv. + // The order m has been used to create the input parameter ai_bi_root. + // Here, v is larger than about 2.2. The estimate is computed + // from Abramowitz and Stegun Eqs. 9.5.22 and 9.5.26, page 371. + // + // The inversion of z as a function of zeta is mentioned in the text + // following A&S Eq. 9.5.26. Here, we accomplish the inversion by + // performing a Taylor expansion of Eq. 9.3.39 for large z to order 2 + // and solving the resulting quadratic equation, thereby taking + // the positive root of the quadratic. + // In other words: (2/3)(-zeta)^(3/2) approx = z + 1/(2z) - pi/2. + // This leads to: z^2 - [(2/3)(-zeta)^(3/2) + pi/2]z + 1/2 = 0. + // + // With this initial estimate, Newton-Raphson iteration is used + // to refine the value of the estimate of the root of z + // as a function of zeta. + + const T v_pow_third(boost::math::cbrt(v)); + const T v_pow_minus_two_thirds(T(1) / (v_pow_third * v_pow_third)); + + // Obtain zeta using the order v combined with the m'th root of + // an airy function, as shown in A&S Eq. 9.5.22. + const T zeta = v_pow_minus_two_thirds * (-ai_bi_root); + + const T zeta_sqrt = sqrt(zeta); + + // Set up a quadratic equation based on the Taylor series + // expansion mentioned above. + const T b = -((((zeta * zeta_sqrt) * 2U) / 3U) + boost::math::constants::half_pi<T>()); + + // Solve the quadratic equation, taking the positive root. + const T z_estimate = (-b + sqrt((b * b) - T(2))) / 2U; + + // Establish the range, the digits, and the iteration limit + // for the upcoming root-finding. + const T range_zmin = (std::max<T>)(z_estimate - T(1), T(1)); + const T range_zmax = z_estimate + T(1); + + const int my_digits10 = static_cast<int>(static_cast<float>(boost::math::tools::digits<T>() * 0.301F)); + + // Select the maximum allowed iterations based on the number + // of decimal digits in the numeric type T, being at least 12. + const boost::uintmax_t iterations_allowed = static_cast<boost::uintmax_t>((std::max)(12, my_digits10 * 2)); + + boost::uintmax_t iterations_used = iterations_allowed; + + // Calculate the root of z as a function of zeta. + const T z = boost::math::tools::newton_raphson_iterate( + boost::math::detail::bessel_zero::equation_as_9_3_39_and_its_derivative<T>(zeta), + z_estimate, + range_zmin, + range_zmax, + (std::min)(boost::math::tools::digits<T>(), boost::math::tools::digits<float>()), + iterations_used); + + static_cast<void>(iterations_used); + + // Continue with the implementation of A&S Eq. 9.3.39. + const T zsq_minus_one = (z * z) - T(1); + const T zsq_minus_one_sqrt = sqrt(zsq_minus_one); + + // This is A&S Eq. 9.3.42. + const T b0_term_5_24 = T(5) / ((zsq_minus_one * zsq_minus_one_sqrt) * 24U); + const T b0_term_1_8 = T(1) / ( zsq_minus_one_sqrt * 8U); + const T b0_term_5_48 = T(5) / ((zeta * zeta) * 48U); + + const T b0 = -b0_term_5_48 + ((b0_term_5_24 + b0_term_1_8) / zeta_sqrt); + + // This is the second line of A&S Eq. 9.5.26 for f_k with k = 1. + const T f1 = ((z * zeta_sqrt) * b0) / zsq_minus_one_sqrt; + + // This is A&S Eq. 9.5.22 expanded to k = 1 (i.e., one term in the series). + return (v * z) + (f1 / v); + } + + namespace cyl_bessel_j_zero_detail + { + template<class T> + T equation_nist_10_21_40_a(const T& v) + { + const T v_pow_third(boost::math::cbrt(v)); + const T v_pow_minus_two_thirds(T(1) / (v_pow_third * v_pow_third)); + + return v * ((((( + T(0.043) + * v_pow_minus_two_thirds - T(0.0908)) + * v_pow_minus_two_thirds - T(0.00397)) + * v_pow_minus_two_thirds + T(1.033150)) + * v_pow_minus_two_thirds + T(1.8557571)) + * v_pow_minus_two_thirds + T(1)); + } + + template<class T, class Policy> + class function_object_jv + { + public: + function_object_jv(const T& v, + const Policy& pol) : my_v(v), + my_pol(pol) { } + + T operator()(const T& x) const + { + return boost::math::cyl_bessel_j(my_v, x, my_pol); + } + + private: + const T my_v; + const Policy& my_pol; + const function_object_jv& operator=(const function_object_jv&); + }; + + template<class T, class Policy> + class function_object_jv_and_jv_prime + { + public: + function_object_jv_and_jv_prime(const T& v, + const bool order_is_zero, + const Policy& pol) : my_v(v), + my_order_is_zero(order_is_zero), + my_pol(pol) { } + + boost::math::tuple<T, T> operator()(const T& x) const + { + // Obtain Jv(x) and Jv'(x). + // Chris's original code called the Bessel function implementation layer direct, + // but that circumvented optimizations for integer-orders. Call the documented + // top level functions instead, and let them sort out which implementation to use. + T j_v; + T j_v_prime; + + if(my_order_is_zero) + { + j_v = boost::math::cyl_bessel_j(0, x, my_pol); + j_v_prime = -boost::math::cyl_bessel_j(1, x, my_pol); + } + else + { + j_v = boost::math::cyl_bessel_j( my_v, x, my_pol); + const T j_v_m1 (boost::math::cyl_bessel_j(T(my_v - 1), x, my_pol)); + j_v_prime = j_v_m1 - ((my_v * j_v) / x); + } + + // Return a tuple containing both Jv(x) and Jv'(x). + return boost::math::make_tuple(j_v, j_v_prime); + } + + private: + const T my_v; + const bool my_order_is_zero; + const Policy& my_pol; + const function_object_jv_and_jv_prime& operator=(const function_object_jv_and_jv_prime&); + }; + + template<class T> bool my_bisection_unreachable_tolerance(const T&, const T&) { return false; } + + template<class T, class Policy> + T initial_guess(const T& v, const int m, const Policy& pol) + { + BOOST_MATH_STD_USING // ADL of std names, needed for floor. + + // Compute an estimate of the m'th root of cyl_bessel_j. + + T guess; + + // There is special handling for negative order. + if(v < 0) + { + if((m == 1) && (v > -0.5F)) + { + // For small, negative v, use the results of empirical curve fitting. + // Mathematica(R) session for the coefficients: + // Table[{n, BesselJZero[n, 1]}, {n, -(1/2), 0, 1/10}] + // N[%, 20] + // Fit[%, {n^0, n^1, n^2, n^3, n^4, n^5, n^6}, n] + guess = ((((( - T(0.2321156900729) + * v - T(0.1493247777488)) + * v - T(0.15205419167239)) + * v + T(0.07814930561249)) + * v - T(0.17757573537688)) + * v + T(1.542805677045663)) + * v + T(2.40482555769577277); + + return guess; + } + + // Create the positive order and extract its positive floor integer part. + const T vv(-v); + const T vv_floor(floor(vv)); + + // The to-be-found root is bracketed by the roots of the + // Bessel function whose reflected, positive integer order + // is less than, but nearest to vv. + + T root_hi = boost::math::detail::bessel_zero::cyl_bessel_j_zero_detail::initial_guess(vv_floor, m, pol); + T root_lo; + + if(m == 1) + { + // The estimate of the first root for negative order is found using + // an adaptive range-searching algorithm. + root_lo = T(root_hi - 0.1F); + + const bool hi_end_of_bracket_is_negative = (boost::math::cyl_bessel_j(v, root_hi, pol) < 0); + + while((root_lo > boost::math::tools::epsilon<T>())) + { + const bool lo_end_of_bracket_is_negative = (boost::math::cyl_bessel_j(v, root_lo, pol) < 0); + + if(hi_end_of_bracket_is_negative != lo_end_of_bracket_is_negative) + { + break; + } + + root_hi = root_lo; + + // Decrease the lower end of the bracket using an adaptive algorithm. + if(root_lo > 0.5F) + { + root_lo -= 0.5F; + } + else + { + root_lo *= 0.75F; + } + } + } + else + { + root_lo = boost::math::detail::bessel_zero::cyl_bessel_j_zero_detail::initial_guess(vv_floor, m - 1, pol); + } + + // Perform several steps of bisection iteration to refine the guess. + boost::uintmax_t number_of_iterations(12U); + + // Do the bisection iteration. + const boost::math::tuple<T, T> guess_pair = + boost::math::tools::bisect( + boost::math::detail::bessel_zero::cyl_bessel_j_zero_detail::function_object_jv<T, Policy>(v, pol), + root_lo, + root_hi, + boost::math::detail::bessel_zero::cyl_bessel_j_zero_detail::my_bisection_unreachable_tolerance<T>, + number_of_iterations); + + return (boost::math::get<0>(guess_pair) + boost::math::get<1>(guess_pair)) / 2U; + } + + if(m == 1U) + { + // Get the initial estimate of the first root. + + if(v < 2.2F) + { + // For small v, use the results of empirical curve fitting. + // Mathematica(R) session for the coefficients: + // Table[{n, BesselJZero[n, 1]}, {n, 0, 22/10, 1/10}] + // N[%, 20] + // Fit[%, {n^0, n^1, n^2, n^3, n^4, n^5, n^6}, n] + guess = ((((( - T(0.0008342379046010) + * v + T(0.007590035637410)) + * v - T(0.030640914772013)) + * v + T(0.078232088020106)) + * v - T(0.169668712590620)) + * v + T(1.542187960073750)) + * v + T(2.4048359915254634); + } + else + { + // For larger v, use the first line of Eqs. 10.21.40 in the NIST Handbook. + guess = boost::math::detail::bessel_zero::cyl_bessel_j_zero_detail::equation_nist_10_21_40_a(v); + } + } + else + { + if(v < 2.2F) + { + // Use Eq. 10.21.19 in the NIST Handbook. + const T a(((v + T(m * 2U)) - T(0.5)) * boost::math::constants::half_pi<T>()); + + guess = boost::math::detail::bessel_zero::equation_nist_10_21_19(v, a); + } + else + { + // Get an estimate of the m'th root of airy_ai. + const T airy_ai_root(boost::math::detail::airy_zero::airy_ai_zero_detail::initial_guess<T>(m)); + + // Use Eq. 9.5.26 in the A&S Handbook. + guess = boost::math::detail::bessel_zero::equation_as_9_5_26(v, airy_ai_root); + } + } + + return guess; + } + } // namespace cyl_bessel_j_zero_detail + + namespace cyl_neumann_zero_detail + { + template<class T> + T equation_nist_10_21_40_b(const T& v) + { + const T v_pow_third(boost::math::cbrt(v)); + const T v_pow_minus_two_thirds(T(1) / (v_pow_third * v_pow_third)); + + return v * ((((( - T(0.001) + * v_pow_minus_two_thirds - T(0.0060)) + * v_pow_minus_two_thirds + T(0.01198)) + * v_pow_minus_two_thirds + T(0.260351)) + * v_pow_minus_two_thirds + T(0.9315768)) + * v_pow_minus_two_thirds + T(1)); + } + + template<class T, class Policy> + class function_object_yv + { + public: + function_object_yv(const T& v, + const Policy& pol) : my_v(v), + my_pol(pol) { } + + T operator()(const T& x) const + { + return boost::math::cyl_neumann(my_v, x, my_pol); + } + + private: + const T my_v; + const Policy& my_pol; + const function_object_yv& operator=(const function_object_yv&); + }; + + template<class T, class Policy> + class function_object_yv_and_yv_prime + { + public: + function_object_yv_and_yv_prime(const T& v, + const Policy& pol) : my_v(v), + my_pol(pol) { } + + boost::math::tuple<T, T> operator()(const T& x) const + { + const T half_epsilon(boost::math::tools::epsilon<T>() / 2U); + + const bool order_is_zero = ((my_v > -half_epsilon) && (my_v < +half_epsilon)); + + // Obtain Yv(x) and Yv'(x). + // Chris's original code called the Bessel function implementation layer direct, + // but that circumvented optimizations for integer-orders. Call the documented + // top level functions instead, and let them sort out which implementation to use. + T y_v; + T y_v_prime; + + if(order_is_zero) + { + y_v = boost::math::cyl_neumann(0, x, my_pol); + y_v_prime = -boost::math::cyl_neumann(1, x, my_pol); + } + else + { + y_v = boost::math::cyl_neumann( my_v, x, my_pol); + const T y_v_m1 (boost::math::cyl_neumann(T(my_v - 1), x, my_pol)); + y_v_prime = y_v_m1 - ((my_v * y_v) / x); + } + + // Return a tuple containing both Yv(x) and Yv'(x). + return boost::math::make_tuple(y_v, y_v_prime); + } + + private: + const T my_v; + const Policy& my_pol; + const function_object_yv_and_yv_prime& operator=(const function_object_yv_and_yv_prime&); + }; + + template<class T> bool my_bisection_unreachable_tolerance(const T&, const T&) { return false; } + + template<class T, class Policy> + T initial_guess(const T& v, const int m, const Policy& pol) + { + BOOST_MATH_STD_USING // ADL of std names, needed for floor. + + // Compute an estimate of the m'th root of cyl_neumann. + + T guess; + + // There is special handling for negative order. + if(v < 0) + { + // Create the positive order and extract its positive floor and ceiling integer parts. + const T vv(-v); + const T vv_floor(floor(vv)); + + // The to-be-found root is bracketed by the roots of the + // Bessel function whose reflected, positive integer order + // is less than, but nearest to vv. + + // The special case of negative, half-integer order uses + // the relation between Yv and spherical Bessel functions + // in order to obtain the bracket for the root. + // In these special cases, cyl_neumann(-n/2, x) = sph_bessel_j(+n/2, x) + // for v = -n/2. + + T root_hi; + T root_lo; + + if(m == 1) + { + // The estimate of the first root for negative order is found using + // an adaptive range-searching algorithm. + // Take special precautions for the discontinuity at negative, + // half-integer orders and use different brackets above and below these. + if(T(vv - vv_floor) < 0.5F) + { + root_hi = boost::math::detail::bessel_zero::cyl_neumann_zero_detail::initial_guess(vv_floor, m, pol); + } + else + { + root_hi = boost::math::detail::bessel_zero::cyl_bessel_j_zero_detail::initial_guess(T(vv_floor + 0.5F), m, pol); + } + + root_lo = T(root_hi - 0.1F); + + const bool hi_end_of_bracket_is_negative = (boost::math::cyl_neumann(v, root_hi, pol) < 0); + + while((root_lo > boost::math::tools::epsilon<T>())) + { + const bool lo_end_of_bracket_is_negative = (boost::math::cyl_neumann(v, root_lo, pol) < 0); + + if(hi_end_of_bracket_is_negative != lo_end_of_bracket_is_negative) + { + break; + } + + root_hi = root_lo; + + // Decrease the lower end of the bracket using an adaptive algorithm. + if(root_lo > 0.5F) + { + root_lo -= 0.5F; + } + else + { + root_lo *= 0.75F; + } + } + } + else + { + if(T(vv - vv_floor) < 0.5F) + { + root_lo = boost::math::detail::bessel_zero::cyl_neumann_zero_detail::initial_guess(vv_floor, m - 1, pol); + root_hi = boost::math::detail::bessel_zero::cyl_neumann_zero_detail::initial_guess(vv_floor, m, pol); + root_lo += 0.01F; + root_hi += 0.01F; + } + else + { + root_lo = boost::math::detail::bessel_zero::cyl_bessel_j_zero_detail::initial_guess(T(vv_floor + 0.5F), m - 1, pol); + root_hi = boost::math::detail::bessel_zero::cyl_bessel_j_zero_detail::initial_guess(T(vv_floor + 0.5F), m, pol); + root_lo += 0.01F; + root_hi += 0.01F; + } + } + + // Perform several steps of bisection iteration to refine the guess. + boost::uintmax_t number_of_iterations(12U); + + // Do the bisection iteration. + const boost::math::tuple<T, T> guess_pair = + boost::math::tools::bisect( + boost::math::detail::bessel_zero::cyl_neumann_zero_detail::function_object_yv<T, Policy>(v, pol), + root_lo, + root_hi, + boost::math::detail::bessel_zero::cyl_neumann_zero_detail::my_bisection_unreachable_tolerance<T>, + number_of_iterations); + + return (boost::math::get<0>(guess_pair) + boost::math::get<1>(guess_pair)) / 2U; + } + + if(m == 1U) + { + // Get the initial estimate of the first root. + + if(v < 2.2F) + { + // For small v, use the results of empirical curve fitting. + // Mathematica(R) session for the coefficients: + // Table[{n, BesselYZero[n, 1]}, {n, 0, 22/10, 1/10}] + // N[%, 20] + // Fit[%, {n^0, n^1, n^2, n^3, n^4, n^5, n^6}, n] + guess = ((((( - T(0.0025095909235652) + * v + T(0.021291887049053)) + * v - T(0.076487785486526)) + * v + T(0.159110268115362)) + * v - T(0.241681668765196)) + * v + T(1.4437846310885244)) + * v + T(0.89362115190200490); + } + else + { + // For larger v, use the second line of Eqs. 10.21.40 in the NIST Handbook. + guess = boost::math::detail::bessel_zero::cyl_neumann_zero_detail::equation_nist_10_21_40_b(v); + } + } + else + { + if(v < 2.2F) + { + // Use Eq. 10.21.19 in the NIST Handbook. + const T a(((v + T(m * 2U)) - T(1.5)) * boost::math::constants::half_pi<T>()); + + guess = boost::math::detail::bessel_zero::equation_nist_10_21_19(v, a); + } + else + { + // Get an estimate of the m'th root of airy_bi. + const T airy_bi_root(boost::math::detail::airy_zero::airy_bi_zero_detail::initial_guess<T>(m)); + + // Use Eq. 9.5.26 in the A&S Handbook. + guess = boost::math::detail::bessel_zero::equation_as_9_5_26(v, airy_bi_root); + } + } + + return guess; + } + } // namespace cyl_neumann_zero_detail + } // namespace bessel_zero + } } } // namespace boost::math::detail + +#endif // _BESSEL_JY_ZERO_2013_01_18_HPP_ diff --git a/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_k0.hpp b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_k0.hpp new file mode 100644 index 00000000000..c24d89093cc --- /dev/null +++ b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_k0.hpp @@ -0,0 +1,519 @@ +// Copyright (c) 2006 Xiaogang Zhang +// Copyright (c) 2017 John Maddock +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_BESSEL_K0_HPP +#define BOOST_MATH_BESSEL_K0_HPP + +#ifdef _MSC_VER +#pragma once +#pragma warning(push) +#pragma warning(disable:4702) // Unreachable code (release mode only warning) +#endif + +#include <boost/math/tools/rational.hpp> +#include <boost/math/tools/big_constant.hpp> +#include <boost/math/policies/error_handling.hpp> +#include <boost/assert.hpp> + +#if defined(__GNUC__) && defined(BOOST_MATH_USE_FLOAT128) +// +// This is the only way we can avoid +// warning: non-standard suffix on floating constant [-Wpedantic] +// when building with -Wall -pedantic. Neither __extension__ +// nor #pragma dianostic ignored work :( +// +#pragma GCC system_header +#endif + +// Modified Bessel function of the second kind of order zero +// minimax rational approximations on intervals, see +// Russon and Blair, Chalk River Report AECL-3461, 1969, +// as revised by Pavel Holoborodko in "Rational Approximations +// for the Modified Bessel Function of the Second Kind - K0(x) +// for Computations with Double Precision", see +// http://www.advanpix.com/2015/11/25/rational-approximations-for-the-modified-bessel-function-of-the-second-kind-k0-for-computations-with-double-precision/ +// +// The actual coefficients used are our own derivation (by JM) +// since we extend to both greater and lesser precision than the +// references above. We can also improve performance WRT to +// Holoborodko without loss of precision. + +namespace boost { namespace math { namespace detail{ + +template <typename T> +T bessel_k0(const T& x); + +template <class T, class tag> +struct bessel_k0_initializer +{ + struct init + { + init() + { + do_init(tag()); + } + static void do_init(const mpl::int_<113>&) + { + bessel_k0(T(0.5)); + bessel_k0(T(1.5)); + } + static void do_init(const mpl::int_<64>&) + { + bessel_k0(T(0.5)); + bessel_k0(T(1.5)); + } + template <class U> + static void do_init(const U&){} + void force_instantiate()const{} + }; + static const init initializer; + static void force_instantiate() + { + initializer.force_instantiate(); + } +}; + +template <class T, class tag> +const typename bessel_k0_initializer<T, tag>::init bessel_k0_initializer<T, tag>::initializer; + + +template <typename T, int N> +T bessel_k0_imp(const T& x, const mpl::int_<N>&) +{ + BOOST_ASSERT(0); + return 0; +} + +template <typename T> +T bessel_k0_imp(const T& x, const mpl::int_<24>&) +{ + BOOST_MATH_STD_USING + if(x <= 1) + { + // Maximum Deviation Found : 2.358e-09 + // Expected Error Term : -2.358e-09 + // Maximum Relative Change in Control Points : 9.552e-02 + // Max Error found at float precision = Poly : 4.448220e-08 + static const T Y = 1.137250900268554688f; + static const T P[] = + { + -1.372508979104259711e-01f, + 2.622545986273687617e-01f, + 5.047103728247919836e-03f + }; + static const T Q[] = + { + 1.000000000000000000e+00f, + -8.928694018000029415e-02f, + 2.985980684180969241e-03f + }; + T a = x * x / 4; + a = (tools::evaluate_rational(P, Q, a) + Y) * a + 1; + + // Maximum Deviation Found: 1.346e-09 + // Expected Error Term : -1.343e-09 + // Maximum Relative Change in Control Points : 2.405e-02 + // Max Error found at float precision = Poly : 1.354814e-07 + static const T P2[] = { + 1.159315158e-01f, + 2.789828686e-01f, + 2.524902861e-02f, + 8.457241514e-04f, + 1.530051997e-05f + }; + return tools::evaluate_polynomial(P2, T(x * x)) - log(x) * a; + } + else + { + // Maximum Deviation Found: 1.587e-08 + // Expected Error Term : 1.531e-08 + // Maximum Relative Change in Control Points : 9.064e-02 + // Max Error found at float precision = Poly : 5.065020e-08 + + static const T P[] = + { + 2.533141220e-01, + 5.221502603e-01, + 6.380180669e-02, + -5.934976547e-02 + }; + static const T Q[] = + { + 1.000000000e+00, + 2.679722431e+00, + 1.561635813e+00, + 1.573660661e-01 + }; + if(x < tools::log_max_value<T>()) + return ((tools::evaluate_rational(P, Q, T(1 / x)) + 1) * exp(-x) / sqrt(x)); + else + { + T ex = exp(-x / 2); + return ((tools::evaluate_rational(P, Q, T(1 / x)) + 1) * ex / sqrt(x)) * ex; + } + } +} + +template <typename T> +T bessel_k0_imp(const T& x, const mpl::int_<53>&) +{ + BOOST_MATH_STD_USING + if(x <= 1) + { + // Maximum Deviation Found: 6.077e-17 + // Expected Error Term : -6.077e-17 + // Maximum Relative Change in Control Points : 7.797e-02 + // Max Error found at double precision = Poly : 1.003156e-16 + static const T Y = 1.137250900268554688; + static const T P[] = + { + -1.372509002685546267e-01, + 2.574916117833312855e-01, + 1.395474602146869316e-02, + 5.445476986653926759e-04, + 7.125159422136622118e-06 + }; + static const T Q[] = + { + 1.000000000000000000e+00, + -5.458333438017788530e-02, + 1.291052816975251298e-03, + -1.367653946978586591e-05 + }; + + T a = x * x / 4; + a = (tools::evaluate_polynomial(P, a) / tools::evaluate_polynomial(Q, a) + Y) * a + 1; + + // Maximum Deviation Found: 3.429e-18 + // Expected Error Term : 3.392e-18 + // Maximum Relative Change in Control Points : 2.041e-02 + // Max Error found at double precision = Poly : 2.513112e-16 + static const T P2[] = + { + 1.159315156584124484e-01, + 2.789828789146031732e-01, + 2.524892993216121934e-02, + 8.460350907213637784e-04, + 1.491471924309617534e-05, + 1.627106892422088488e-07, + 1.208266102392756055e-09, + 6.611686391749704310e-12 + }; + + return tools::evaluate_polynomial(P2, T(x * x)) - log(x) * a; + } + else + { + // Maximum Deviation Found: 4.316e-17 + // Expected Error Term : 9.570e-18 + // Maximum Relative Change in Control Points : 2.757e-01 + // Max Error found at double precision = Poly : 1.001560e-16 + + static const T Y = 1; + static const T P[] = + { + 2.533141373155002416e-01, + 3.628342133984595192e+00, + 1.868441889406606057e+01, + 4.306243981063412784e+01, + 4.424116209627428189e+01, + 1.562095339356220468e+01, + -1.810138978229410898e+00, + -1.414237994269995877e+00, + -9.369168119754924625e-02 + }; + static const T Q[] = + { + 1.000000000000000000e+00, + 1.494194694879908328e+01, + 8.265296455388554217e+01, + 2.162779506621866970e+02, + 2.845145155184222157e+02, + 1.851714491916334995e+02, + 5.486540717439723515e+01, + 6.118075837628957015e+00, + 1.586261269326235053e-01 + }; + if(x < tools::log_max_value<T>()) + return ((tools::evaluate_rational(P, Q, T(1 / x)) + Y) * exp(-x) / sqrt(x)); + else + { + T ex = exp(-x / 2); + return ((tools::evaluate_rational(P, Q, T(1 / x)) + Y) * ex / sqrt(x)) * ex; + } + } +} + +template <typename T> +T bessel_k0_imp(const T& x, const mpl::int_<64>&) +{ + BOOST_MATH_STD_USING + if(x <= 1) + { + // Maximum Deviation Found: 2.180e-22 + // Expected Error Term : 2.180e-22 + // Maximum Relative Change in Control Points : 2.943e-01 + // Max Error found at float80 precision = Poly : 3.923207e-20 + static const T Y = 1.137250900268554687500e+00; + static const T P[] = + { + BOOST_MATH_BIG_CONSTANT(T, 64, -1.372509002685546875002e-01), + BOOST_MATH_BIG_CONSTANT(T, 64, 2.566481981037407600436e-01), + BOOST_MATH_BIG_CONSTANT(T, 64, 1.551881122448948854873e-02), + BOOST_MATH_BIG_CONSTANT(T, 64, 6.646112454323276529650e-04), + BOOST_MATH_BIG_CONSTANT(T, 64, 1.213747930378196492543e-05), + BOOST_MATH_BIG_CONSTANT(T, 64, 9.423709328020389560844e-08) + }; + static const T Q[] = + { + BOOST_MATH_BIG_CONSTANT(T, 64, 1.000000000000000000000e+00), + BOOST_MATH_BIG_CONSTANT(T, 64, -4.843828412587773008342e-02), + BOOST_MATH_BIG_CONSTANT(T, 64, 1.088484822515098936140e-03), + BOOST_MATH_BIG_CONSTANT(T, 64, -1.374724008530702784829e-05), + BOOST_MATH_BIG_CONSTANT(T, 64, 8.452665455952581680339e-08) + }; + + + T a = x * x / 4; + a = (tools::evaluate_polynomial(P, a) / tools::evaluate_polynomial(Q, a) + Y) * a + 1; + + // Maximum Deviation Found: 2.440e-21 + // Expected Error Term : -2.434e-21 + // Maximum Relative Change in Control Points : 2.459e-02 + // Max Error found at float80 precision = Poly : 1.482487e-19 + static const T P2[] = + { + BOOST_MATH_BIG_CONSTANT(T, 64, 1.159315156584124488110e-01), + BOOST_MATH_BIG_CONSTANT(T, 64, 2.764832791416047889734e-01), + BOOST_MATH_BIG_CONSTANT(T, 64, 1.926062887220923354112e-02), + BOOST_MATH_BIG_CONSTANT(T, 64, 3.660777862036966089410e-04), + BOOST_MATH_BIG_CONSTANT(T, 64, 2.094942446930673386849e-06) + }; + static const T Q2[] = + { + BOOST_MATH_BIG_CONSTANT(T, 64, 1.000000000000000000000e+00), + BOOST_MATH_BIG_CONSTANT(T, 64, -2.156100313881251616320e-02), + BOOST_MATH_BIG_CONSTANT(T, 64, 2.315993873344905957033e-04), + BOOST_MATH_BIG_CONSTANT(T, 64, -1.529444499350703363451e-06), + BOOST_MATH_BIG_CONSTANT(T, 64, 5.524988589917857531177e-09) + }; + return tools::evaluate_rational(P2, Q2, T(x * x)) - log(x) * a; + } + else + { + // Maximum Deviation Found: 4.291e-20 + // Expected Error Term : 2.236e-21 + // Maximum Relative Change in Control Points : 3.021e-01 + //Max Error found at float80 precision = Poly : 8.727378e-20 + static const T Y = 1; + static const T P[] = + { + BOOST_MATH_BIG_CONSTANT(T, 64, 2.533141373155002512056e-01), + BOOST_MATH_BIG_CONSTANT(T, 64, 5.417942070721928652715e+00), + BOOST_MATH_BIG_CONSTANT(T, 64, 4.477464607463971754433e+01), + BOOST_MATH_BIG_CONSTANT(T, 64, 1.838745728725943889876e+02), + BOOST_MATH_BIG_CONSTANT(T, 64, 4.009736314927811202517e+02), + BOOST_MATH_BIG_CONSTANT(T, 64, 4.557411293123609803452e+02), + BOOST_MATH_BIG_CONSTANT(T, 64, 2.360222564015361268955e+02), + BOOST_MATH_BIG_CONSTANT(T, 64, 2.385435333168505701022e+01), + BOOST_MATH_BIG_CONSTANT(T, 64, -1.750195760942181592050e+01), + BOOST_MATH_BIG_CONSTANT(T, 64, -4.059789241612946683713e+00), + BOOST_MATH_BIG_CONSTANT(T, 64, -1.612783121537333908889e-01) + }; + static const T Q[] = + { + BOOST_MATH_BIG_CONSTANT(T, 64, 1.000000000000000000000e+00), + BOOST_MATH_BIG_CONSTANT(T, 64, 2.200669254769325861404e+01), + BOOST_MATH_BIG_CONSTANT(T, 64, 1.900177593527144126549e+02), + BOOST_MATH_BIG_CONSTANT(T, 64, 8.361003989965786932682e+02), + BOOST_MATH_BIG_CONSTANT(T, 64, 2.041319870804843395893e+03), + BOOST_MATH_BIG_CONSTANT(T, 64, 2.828491555113790345068e+03), + BOOST_MATH_BIG_CONSTANT(T, 64, 2.190342229261529076624e+03), + BOOST_MATH_BIG_CONSTANT(T, 64, 9.003330795963812219852e+02), + BOOST_MATH_BIG_CONSTANT(T, 64, 1.773371397243777891569e+02), + BOOST_MATH_BIG_CONSTANT(T, 64, 1.368634935531158398439e+01), + BOOST_MATH_BIG_CONSTANT(T, 64, 2.543310879400359967327e-01) + }; + if(x < tools::log_max_value<T>()) + return ((tools::evaluate_rational(P, Q, T(1 / x)) + Y) * exp(-x) / sqrt(x)); + else + { + T ex = exp(-x / 2); + return ((tools::evaluate_rational(P, Q, T(1 / x)) + Y) * ex / sqrt(x)) * ex; + } + } +} + +template <typename T> +T bessel_k0_imp(const T& x, const mpl::int_<113>&) +{ + BOOST_MATH_STD_USING + if(x <= 1) + { + // Maximum Deviation Found: 5.682e-37 + // Expected Error Term : 5.682e-37 + // Maximum Relative Change in Control Points : 6.094e-04 + // Max Error found at float128 precision = Poly : 5.338213e-35 + static const T Y = 1.137250900268554687500000000000000000e+00f; + static const T P[] = + { + BOOST_MATH_BIG_CONSTANT(T, 113, -1.372509002685546875000000000000000006e-01), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.556212905071072782462974351698081303e-01), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.742459135264203478530904179889103929e-02), + BOOST_MATH_BIG_CONSTANT(T, 113, 8.077860530453688571555479526961318918e-04), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.868173911669241091399374307788635148e-05), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.496405768838992243478709145123306602e-07), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.752489221949580551692915881999762125e-09), + BOOST_MATH_BIG_CONSTANT(T, 113, 5.243010555737173524710512824955368526e-12) + }; + static const T Q[] = + { + BOOST_MATH_BIG_CONSTANT(T, 113, 1.000000000000000000000000000000000000e+00), + BOOST_MATH_BIG_CONSTANT(T, 113, -4.095631064064621099785696980653193721e-02), + BOOST_MATH_BIG_CONSTANT(T, 113, 8.313880983725212151967078809725835532e-04), + BOOST_MATH_BIG_CONSTANT(T, 113, -1.095229912293480063501285562382835142e-05), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.022828799511943141130509410251996277e-07), + BOOST_MATH_BIG_CONSTANT(T, 113, -6.860874007419812445494782795829046836e-10), + BOOST_MATH_BIG_CONSTANT(T, 113, 3.107297802344970725756092082686799037e-12), + BOOST_MATH_BIG_CONSTANT(T, 113, -7.460529579244623559164763757787600944e-15) + }; + T a = x * x / 4; + a = (tools::evaluate_rational(P, Q, a) + Y) * a + 1; + + // Maximum Deviation Found: 5.173e-38 + // Expected Error Term : 5.105e-38 + // Maximum Relative Change in Control Points : 9.734e-03 + // Max Error found at float128 precision = Poly : 1.688806e-34 + static const T P2[] = + { + BOOST_MATH_BIG_CONSTANT(T, 113, 1.159315156584124488107200313757741370e-01), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.789828789146031122026800078439435369e-01), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.524892993216269451266750049024628432e-02), + BOOST_MATH_BIG_CONSTANT(T, 113, 8.460350907082229957222453839935101823e-04), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.491471929926042875260452849503857976e-05), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.627105610481598430816014719558896866e-07), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.208426165007797264194914898538250281e-09), + BOOST_MATH_BIG_CONSTANT(T, 113, 6.508697838747354949164182457073784117e-12), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.659784680639805301101014383907273109e-14), + BOOST_MATH_BIG_CONSTANT(T, 113, 8.531090131964391104248859415958109654e-17), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.205195117066478034260323124669936314e-19), + BOOST_MATH_BIG_CONSTANT(T, 113, 4.692219280289030165761119775783115426e-22), + BOOST_MATH_BIG_CONSTANT(T, 113, 8.362350161092532344171965861545860747e-25), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.277990623924628999539014980773738258e-27) + }; + + return tools::evaluate_polynomial(P2, T(x * x)) - log(x) * a; + } + else + { + // Maximum Deviation Found: 1.462e-34 + // Expected Error Term : 4.917e-40 + // Maximum Relative Change in Control Points : 3.385e-01 + // Max Error found at float128 precision = Poly : 1.567573e-34 + static const T Y = 1; + static const T P[] = + { + BOOST_MATH_BIG_CONSTANT(T, 113, 2.533141373155002512078826424055226265e-01), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.001949740768235770078339977110749204e+01), + BOOST_MATH_BIG_CONSTANT(T, 113, 6.991516715983883248363351472378349986e+02), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.429587951594593159075690819360687720e+04), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.911933815201948768044660065771258450e+05), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.769943016204926614862175317962439875e+06), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.170866154649560750500954150401105606e+07), + BOOST_MATH_BIG_CONSTANT(T, 113, 5.634687099724383996792011977705727661e+07), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.989524036456492581597607246664394014e+08), + BOOST_MATH_BIG_CONSTANT(T, 113, 5.160394785715328062088529400178080360e+08), + BOOST_MATH_BIG_CONSTANT(T, 113, 9.778173054417826368076483100902201433e+08), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.335667778588806892764139643950439733e+09), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.283635100080306980206494425043706838e+09), + BOOST_MATH_BIG_CONSTANT(T, 113, 8.300616188213640626577036321085025855e+08), + BOOST_MATH_BIG_CONSTANT(T, 113, 3.277591957076162984986406540894621482e+08), + BOOST_MATH_BIG_CONSTANT(T, 113, 5.564360536834214058158565361486115932e+07), + BOOST_MATH_BIG_CONSTANT(T, 113, -1.043505161612403359098596828115690596e+07), + BOOST_MATH_BIG_CONSTANT(T, 113, -7.217035248223503605127967970903027314e+06), + BOOST_MATH_BIG_CONSTANT(T, 113, -1.422938158797326748375799596769964430e+06), + BOOST_MATH_BIG_CONSTANT(T, 113, -1.229125746200586805278634786674745210e+05), + BOOST_MATH_BIG_CONSTANT(T, 113, -4.201632288615609937883545928660649813e+03), + BOOST_MATH_BIG_CONSTANT(T, 113, -3.690820607338480548346746717311811406e+01) + }; + static const T Q[] = + { + BOOST_MATH_BIG_CONSTANT(T, 113, 1.000000000000000000000000000000000000e+00), + BOOST_MATH_BIG_CONSTANT(T, 113, 7.964877874035741452203497983642653107e+01), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.808929943826193766839360018583294769e+03), + BOOST_MATH_BIG_CONSTANT(T, 113, 5.814524004679994110944366890912384139e+04), + BOOST_MATH_BIG_CONSTANT(T, 113, 7.897794522506725610540209610337355118e+05), + BOOST_MATH_BIG_CONSTANT(T, 113, 7.456339470955813675629523617440433672e+06), + BOOST_MATH_BIG_CONSTANT(T, 113, 5.057818717813969772198911392875127212e+07), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.513821619536852436424913886081133209e+08), + BOOST_MATH_BIG_CONSTANT(T, 113, 9.255938846873380596038513316919990776e+08), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.537077551699028079347581816919572141e+09), + BOOST_MATH_BIG_CONSTANT(T, 113, 5.176769339768120752974843214652367321e+09), + BOOST_MATH_BIG_CONSTANT(T, 113, 7.828722317390455845253191337207432060e+09), + BOOST_MATH_BIG_CONSTANT(T, 113, 8.698864296569996402006511705803675890e+09), + BOOST_MATH_BIG_CONSTANT(T, 113, 7.007803261356636409943826918468544629e+09), + BOOST_MATH_BIG_CONSTANT(T, 113, 4.016564631288740308993071395104715469e+09), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.595893010619754750655947035567624730e+09), + BOOST_MATH_BIG_CONSTANT(T, 113, 4.241241839120481076862742189989406856e+08), + BOOST_MATH_BIG_CONSTANT(T, 113, 7.168778094393076220871007550235840858e+07), + BOOST_MATH_BIG_CONSTANT(T, 113, 7.156200301360388147635052029404211109e+06), + BOOST_MATH_BIG_CONSTANT(T, 113, 3.752130382550379886741949463587008794e+05), + BOOST_MATH_BIG_CONSTANT(T, 113, 8.370574966987293592457152146806662562e+03), + BOOST_MATH_BIG_CONSTANT(T, 113, 4.871254714311063594080644835895740323e+01) + }; + if(x < tools::log_max_value<T>()) + return ((tools::evaluate_rational(P, Q, T(1 / x)) + Y) * exp(-x) / sqrt(x)); + else + { + T ex = exp(-x / 2); + return ((tools::evaluate_rational(P, Q, T(1 / x)) + Y) * ex / sqrt(x)) * ex; + } + } +} + +template <typename T> +T bessel_k0_imp(const T& x, const mpl::int_<0>&) +{ + if(boost::math::tools::digits<T>() <= 24) + return bessel_k0_imp(x, mpl::int_<24>()); + else if(boost::math::tools::digits<T>() <= 53) + return bessel_k0_imp(x, mpl::int_<53>()); + else if(boost::math::tools::digits<T>() <= 64) + return bessel_k0_imp(x, mpl::int_<64>()); + else if(boost::math::tools::digits<T>() <= 113) + return bessel_k0_imp(x, mpl::int_<113>()); + BOOST_ASSERT(0); + return 0; +} + +template <typename T> +inline T bessel_k0(const T& x) +{ + typedef mpl::int_< + ((std::numeric_limits<T>::digits == 0) || (std::numeric_limits<T>::radix != 2)) ? + 0 : + std::numeric_limits<T>::digits <= 24 ? + 24 : + std::numeric_limits<T>::digits <= 53 ? + 53 : + std::numeric_limits<T>::digits <= 64 ? + 64 : + std::numeric_limits<T>::digits <= 113 ? + 113 : -1 + > tag_type; + + bessel_k0_initializer<T, tag_type>::force_instantiate(); + return bessel_k0_imp(x, tag_type()); +} + +}}} // namespaces + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#endif // BOOST_MATH_BESSEL_K0_HPP + diff --git a/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_k1.hpp b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_k1.hpp new file mode 100644 index 00000000000..4a851a67d26 --- /dev/null +++ b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_k1.hpp @@ -0,0 +1,561 @@ +// Copyright (c) 2006 Xiaogang Zhang +// Copyright (c) 2017 John Maddock +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_BESSEL_K1_HPP +#define BOOST_MATH_BESSEL_K1_HPP + +#ifdef _MSC_VER +#pragma once +#pragma warning(push) +#pragma warning(disable:4702) // Unreachable code (release mode only warning) +#endif + +#include <boost/math/tools/rational.hpp> +#include <boost/math/tools/big_constant.hpp> +#include <boost/math/policies/error_handling.hpp> +#include <boost/assert.hpp> + +#if defined(__GNUC__) && defined(BOOST_MATH_USE_FLOAT128) +// +// This is the only way we can avoid +// warning: non-standard suffix on floating constant [-Wpedantic] +// when building with -Wall -pedantic. Neither __extension__ +// nor #pragma dianostic ignored work :( +// +#pragma GCC system_header +#endif + +// Modified Bessel function of the second kind of order zero +// minimax rational approximations on intervals, see +// Russon and Blair, Chalk River Report AECL-3461, 1969, +// as revised by Pavel Holoborodko in "Rational Approximations +// for the Modified Bessel Function of the Second Kind - K0(x) +// for Computations with Double Precision", see +// http://www.advanpix.com/2016/01/05/rational-approximations-for-the-modified-bessel-function-of-the-second-kind-k1-for-computations-with-double-precision/ +// +// The actual coefficients used are our own derivation (by JM) +// since we extend to both greater and lesser precision than the +// references above. We can also improve performance WRT to +// Holoborodko without loss of precision. + +namespace boost { namespace math { namespace detail{ + + template <typename T> + T bessel_k1(const T& x); + + template <class T, class tag> + struct bessel_k1_initializer + { + struct init + { + init() + { + do_init(tag()); + } + static void do_init(const mpl::int_<113>&) + { + bessel_k1(T(0.5)); + bessel_k1(T(2)); + bessel_k1(T(6)); + } + static void do_init(const mpl::int_<64>&) + { + bessel_k1(T(0.5)); + bessel_k1(T(6)); + } + template <class U> + static void do_init(const U&) {} + void force_instantiate()const {} + }; + static const init initializer; + static void force_instantiate() + { + initializer.force_instantiate(); + } + }; + + template <class T, class tag> + const typename bessel_k1_initializer<T, tag>::init bessel_k1_initializer<T, tag>::initializer; + + + template <typename T, int N> + inline T bessel_k1_imp(const T& x, const mpl::int_<N>&) + { + BOOST_ASSERT(0); + return 0; + } + + template <typename T> + T bessel_k1_imp(const T& x, const mpl::int_<24>&) + { + BOOST_MATH_STD_USING + if(x <= 1) + { + // Maximum Deviation Found: 3.090e-12 + // Expected Error Term : -3.053e-12 + // Maximum Relative Change in Control Points : 4.927e-02 + // Max Error found at float precision = Poly : 7.918347e-10 + static const T Y = 8.695471287e-02f; + static const T P[] = + { + -3.621379531e-03f, + 7.131781976e-03f, + -1.535278300e-05f + }; + static const T Q[] = + { + 1.000000000e+00f, + -5.173102701e-02f, + 9.203530671e-04f + }; + + T a = x * x / 4; + a = ((tools::evaluate_rational(P, Q, a) + Y) * a * a + a / 2 + 1) * x / 2; + + // Maximum Deviation Found: 3.556e-08 + // Expected Error Term : -3.541e-08 + // Maximum Relative Change in Control Points : 8.203e-02 + static const T P2[] = + { + -3.079657469e-01f, + -8.537108913e-02f, + -4.640275408e-03f, + -1.156442414e-04f + }; + + return tools::evaluate_polynomial(P2, T(x * x)) * x + 1 / x + log(x) * a; + } + else + { + // Maximum Deviation Found: 3.369e-08 + // Expected Error Term : -3.227e-08 + // Maximum Relative Change in Control Points : 9.917e-02 + // Max Error found at float precision = Poly : 6.084411e-08 + static const T Y = 1.450342178f; + static const T P[] = + { + -1.970280088e-01f, + 2.188747807e-02f, + 7.270394756e-01f, + 2.490678196e-01f + }; + static const T Q[] = + { + 1.000000000e+00f, + 2.274292882e+00f, + 9.904984851e-01f, + 4.585534549e-02f + }; + if(x < tools::log_max_value<T>()) + return ((tools::evaluate_rational(P, Q, T(1 / x)) + Y) * exp(-x) / sqrt(x)); + else + { + T ex = exp(-x / 2); + return ((tools::evaluate_rational(P, Q, T(1 / x)) + Y) * ex / sqrt(x)) * ex; + } + } + } + + template <typename T> + T bessel_k1_imp(const T& x, const mpl::int_<53>&) + { + BOOST_MATH_STD_USING + if(x <= 1) + { + // Maximum Deviation Found: 1.922e-17 + // Expected Error Term : 1.921e-17 + // Maximum Relative Change in Control Points : 5.287e-03 + // Max Error found at double precision = Poly : 2.004747e-17 + static const T Y = 8.69547128677368164e-02f; + static const T P[] = + { + -3.62137953440350228e-03, + 7.11842087490330300e-03, + 1.00302560256614306e-05, + 1.77231085381040811e-06 + }; + static const T Q[] = + { + 1.00000000000000000e+00, + -4.80414794429043831e-02, + 9.85972641934416525e-04, + -8.91196859397070326e-06 + }; + + T a = x * x / 4; + a = ((tools::evaluate_rational(P, Q, a) + Y) * a * a + a / 2 + 1) * x / 2; + + // Maximum Deviation Found: 4.053e-17 + // Expected Error Term : -4.053e-17 + // Maximum Relative Change in Control Points : 3.103e-04 + // Max Error found at double precision = Poly : 1.246698e-16 + + static const T P2[] = + { + -3.07965757829206184e-01, + -7.80929703673074907e-02, + -2.70619343754051620e-03, + -2.49549522229072008e-05 + }; + static const T Q2[] = + { + 1.00000000000000000e+00, + -2.36316836412163098e-02, + 2.64524577525962719e-04, + -1.49749618004162787e-06 + }; + + return tools::evaluate_rational(P2, Q2, T(x * x)) * x + 1 / x + log(x) * a; + } + else + { + // Maximum Deviation Found: 8.883e-17 + // Expected Error Term : -1.641e-17 + // Maximum Relative Change in Control Points : 2.786e-01 + // Max Error found at double precision = Poly : 1.258798e-16 + + static const T Y = 1.45034217834472656f; + static const T P[] = + { + -1.97028041029226295e-01, + -2.32408961548087617e+00, + -7.98269784507699938e+00, + -2.39968410774221632e+00, + 3.28314043780858713e+01, + 5.67713761158496058e+01, + 3.30907788466509823e+01, + 6.62582288933739787e+00, + 3.08851840645286691e-01 + }; + static const T Q[] = + { + 1.00000000000000000e+00, + 1.41811409298826118e+01, + 7.35979466317556420e+01, + 1.77821793937080859e+02, + 2.11014501598705982e+02, + 1.19425262951064454e+02, + 2.88448064302447607e+01, + 2.27912927104139732e+00, + 2.50358186953478678e-02 + }; + if(x < tools::log_max_value<T>()) + return ((tools::evaluate_rational(P, Q, T(1 / x)) + Y) * exp(-x) / sqrt(x)); + else + { + T ex = exp(-x / 2); + return ((tools::evaluate_rational(P, Q, T(1 / x)) + Y) * ex / sqrt(x)) * ex; + } + } + } + + template <typename T> + T bessel_k1_imp(const T& x, const mpl::int_<64>&) + { + BOOST_MATH_STD_USING + if(x <= 1) + { + // Maximum Deviation Found: 5.549e-23 + // Expected Error Term : -5.548e-23 + // Maximum Relative Change in Control Points : 2.002e-03 + // Max Error found at float80 precision = Poly : 9.352785e-22 + static const T Y = 8.695471286773681640625e-02f; + static const T P[] = + { + BOOST_MATH_BIG_CONSTANT(T, 64, -3.621379534403483072861e-03), + BOOST_MATH_BIG_CONSTANT(T, 64, 7.102135866103952705932e-03), + BOOST_MATH_BIG_CONSTANT(T, 64, 4.167545240236717601167e-05), + BOOST_MATH_BIG_CONSTANT(T, 64, 2.537484002571894870830e-06), + BOOST_MATH_BIG_CONSTANT(T, 64, 6.603228256820000135990e-09) + }; + static const T Q[] = + { + BOOST_MATH_BIG_CONSTANT(T, 64, 1.000000000000000000000e+00), + BOOST_MATH_BIG_CONSTANT(T, 64, -4.354457194045068370363e-02), + BOOST_MATH_BIG_CONSTANT(T, 64, 8.709137201220209072820e-04), + BOOST_MATH_BIG_CONSTANT(T, 64, -9.676151796359590545143e-06), + BOOST_MATH_BIG_CONSTANT(T, 64, 5.162715192766245311659e-08) + }; + + T a = x * x / 4; + a = ((tools::evaluate_rational(P, Q, a) + Y) * a * a + a / 2 + 1) * x / 2; + + // Maximum Deviation Found: 1.995e-23 + // Expected Error Term : 1.995e-23 + // Maximum Relative Change in Control Points : 8.174e-04 + // Max Error found at float80 precision = Poly : 4.137325e-20 + static const T P2[] = + { + BOOST_MATH_BIG_CONSTANT(T, 64, -3.079657578292062244054e-01), + BOOST_MATH_BIG_CONSTANT(T, 64, -7.963049154965966503231e-02), + BOOST_MATH_BIG_CONSTANT(T, 64, -3.103277523735639924895e-03), + BOOST_MATH_BIG_CONSTANT(T, 64, -4.023052834702215699504e-05), + BOOST_MATH_BIG_CONSTANT(T, 64, -1.719459155018493821839e-07) + }; + static const T Q2[] = + { + BOOST_MATH_BIG_CONSTANT(T, 64, 1.000000000000000000000e+00), + BOOST_MATH_BIG_CONSTANT(T, 64, -1.863917670410152669768e-02), + BOOST_MATH_BIG_CONSTANT(T, 64, 1.699367098849735298090e-04), + BOOST_MATH_BIG_CONSTANT(T, 64, -9.309358790546076298429e-07), + BOOST_MATH_BIG_CONSTANT(T, 64, 2.708893480271612711933e-09) + }; + + return tools::evaluate_rational(P2, Q2, T(x * x)) * x + 1 / x + log(x) * a; + } + else + { + // Maximum Deviation Found: 9.785e-20 + // Expected Error Term : -3.302e-21 + // Maximum Relative Change in Control Points : 3.432e-01 + // Max Error found at float80 precision = Poly : 1.083755e-19 + static const T Y = 1.450342178344726562500e+00f; + static const T P[] = + { + BOOST_MATH_BIG_CONSTANT(T, 64, -1.970280410292263112917e-01), + BOOST_MATH_BIG_CONSTANT(T, 64, -4.058564803062959169322e+00), + BOOST_MATH_BIG_CONSTANT(T, 64, -3.036658174194917777473e+01), + BOOST_MATH_BIG_CONSTANT(T, 64, -9.576825392332820142173e+01), + BOOST_MATH_BIG_CONSTANT(T, 64, -6.706969489248020941949e+01), + BOOST_MATH_BIG_CONSTANT(T, 64, 3.264572499406168221382e+02), + BOOST_MATH_BIG_CONSTANT(T, 64, 8.584972047303151034100e+02), + BOOST_MATH_BIG_CONSTANT(T, 64, 8.422082733280017909550e+02), + BOOST_MATH_BIG_CONSTANT(T, 64, 3.738005441471368178383e+02), + BOOST_MATH_BIG_CONSTANT(T, 64, 7.016938390144121276609e+01), + BOOST_MATH_BIG_CONSTANT(T, 64, 4.319614662598089438939e+00), + BOOST_MATH_BIG_CONSTANT(T, 64, 3.710715864316521856193e-02) + }; + static const T Q[] = + { + BOOST_MATH_BIG_CONSTANT(T, 64, 1.000000000000000000000e+00), + BOOST_MATH_BIG_CONSTANT(T, 64, 2.298433045824439052398e+01), + BOOST_MATH_BIG_CONSTANT(T, 64, 2.082047745067709230037e+02), + BOOST_MATH_BIG_CONSTANT(T, 64, 9.662367854250262046592e+02), + BOOST_MATH_BIG_CONSTANT(T, 64, 2.504148628460454004686e+03), + BOOST_MATH_BIG_CONSTANT(T, 64, 3.712730364911389908905e+03), + BOOST_MATH_BIG_CONSTANT(T, 64, 3.108002081150068641112e+03), + BOOST_MATH_BIG_CONSTANT(T, 64, 1.400149940532448553143e+03), + BOOST_MATH_BIG_CONSTANT(T, 64, 3.083303048095846226299e+02), + BOOST_MATH_BIG_CONSTANT(T, 64, 2.748706060530351833346e+01), + BOOST_MATH_BIG_CONSTANT(T, 64, 6.321900849331506946977e-01), + }; + if(x < tools::log_max_value<T>()) + return ((tools::evaluate_polynomial(P, T(1 / x)) / tools::evaluate_polynomial(Q, T(1 / x)) + Y) * exp(-x) / sqrt(x)); + else + { + T ex = exp(-x / 2); + return ((tools::evaluate_polynomial(P, T(1 / x)) / tools::evaluate_polynomial(Q, T(1 / x)) + Y) * ex / sqrt(x)) * ex; + } + } + } + + template <typename T> + T bessel_k1_imp(const T& x, const mpl::int_<113>&) + { + BOOST_MATH_STD_USING + if(x <= 1) + { + // Maximum Deviation Found: 7.120e-35 + // Expected Error Term : -7.119e-35 + // Maximum Relative Change in Control Points : 1.207e-03 + // Max Error found at float128 precision = Poly : 7.143688e-35 + static const T Y = 8.695471286773681640625000000000000000e-02f; + static const T P[] = + { + BOOST_MATH_BIG_CONSTANT(T, 113, -3.621379534403483072916666666666595475e-03), + BOOST_MATH_BIG_CONSTANT(T, 113, 7.074117676930975433219826471336547627e-03), + BOOST_MATH_BIG_CONSTANT(T, 113, 9.631337631362776369069668419033041661e-05), + BOOST_MATH_BIG_CONSTANT(T, 113, 3.468935967870048731821071646104412775e-06), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.956705020559599861444492614737168261e-08), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.347140307321161346703214099534250263e-10), + BOOST_MATH_BIG_CONSTANT(T, 113, 5.569608494081482873946791086435679661e-13) + }; + static const T Q[] = + { + BOOST_MATH_BIG_CONSTANT(T, 113, 1.000000000000000000000000000000000000e+00), + BOOST_MATH_BIG_CONSTANT(T, 113, -3.580768910152105375615558920428350204e-02), + BOOST_MATH_BIG_CONSTANT(T, 113, 6.197467671701485365363068445534557369e-04), + BOOST_MATH_BIG_CONSTANT(T, 113, -6.707466533308630411966030561446666237e-06), + BOOST_MATH_BIG_CONSTANT(T, 113, 4.846687802282250112624373388491123527e-08), + BOOST_MATH_BIG_CONSTANT(T, 113, -2.248493131151981569517383040323900343e-10), + BOOST_MATH_BIG_CONSTANT(T, 113, 5.319279786372775264555728921709381080e-13) + }; + + T a = x * x / 4; + a = ((tools::evaluate_rational(P, Q, a) + Y) * a * a + a / 2 + 1) * x / 2; + + // Maximum Deviation Found: 4.473e-37 + // Expected Error Term : 4.473e-37 + // Maximum Relative Change in Control Points : 8.550e-04 + // Max Error found at float128 precision = Poly : 8.167701e-35 + static const T P2[] = + { + BOOST_MATH_BIG_CONSTANT(T, 113, -3.079657578292062244053600156878870690e-01), + BOOST_MATH_BIG_CONSTANT(T, 113, -8.133183745732467770755578848987414875e-02), + BOOST_MATH_BIG_CONSTANT(T, 113, -3.548968792764174773125420229299431951e-03), + BOOST_MATH_BIG_CONSTANT(T, 113, -5.886125468718182876076972186152445490e-05), + BOOST_MATH_BIG_CONSTANT(T, 113, -4.506712111733707245745396404449639865e-07), + BOOST_MATH_BIG_CONSTANT(T, 113, -1.632502325880313239698965376754406011e-09), + BOOST_MATH_BIG_CONSTANT(T, 113, -2.311973065898784812266544485665624227e-12) + }; + static const T Q2[] = + { + BOOST_MATH_BIG_CONSTANT(T, 113, 1.000000000000000000000000000000000000e+00), + BOOST_MATH_BIG_CONSTANT(T, 113, -1.311471216733781016657962995723287450e-02), + BOOST_MATH_BIG_CONSTANT(T, 113, 8.571876054797365417068164018709472969e-05), + BOOST_MATH_BIG_CONSTANT(T, 113, -3.630181215268238731442496851497901293e-07), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.070176111227805048604885986867484807e-09), + BOOST_MATH_BIG_CONSTANT(T, 113, -2.129046580769872602793220056461084761e-12), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.294906469421390890762001971790074432e-15) + }; + + return tools::evaluate_rational(P2, Q2, T(x * x)) * x + 1 / x + log(x) * a; + } + else if(x < 4) + { + // Max error in interpolated form: 5.307e-37 + // Max Error found at float128 precision = Poly: 7.087862e-35 + static const T Y = 1.5023040771484375f; + static const T P[] = + { + BOOST_MATH_BIG_CONSTANT(T, 113, -2.489899398329369710528254347931380044e-01), + BOOST_MATH_BIG_CONSTANT(T, 113, -6.819080211203854781858815596508456873e+00), + BOOST_MATH_BIG_CONSTANT(T, 113, -7.599915699069767382647695624952723034e+01), + BOOST_MATH_BIG_CONSTANT(T, 113, -4.450211910821295507926582231071300718e+02), + BOOST_MATH_BIG_CONSTANT(T, 113, -1.451374687870925175794150513723956533e+03), + BOOST_MATH_BIG_CONSTANT(T, 113, -2.405805746895098802803503988539098226e+03), + BOOST_MATH_BIG_CONSTANT(T, 113, -5.638808326778389656403861103277220518e+02), + BOOST_MATH_BIG_CONSTANT(T, 113, 5.513958744081268456191778822780865708e+03), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.121301640926540743072258116122834804e+04), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.080094900175649541266613109971296190e+04), + BOOST_MATH_BIG_CONSTANT(T, 113, 5.896531083639613332407534434915552429e+03), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.856602122319645694042555107114028437e+03), + BOOST_MATH_BIG_CONSTANT(T, 113, 3.237121918853145421414003823957537419e+02), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.842072954561323076230238664623893504e+01), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.039705646510167437971862966128055524e+00), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.008418100718254816100425022904039530e-02) + }; + static const T Q[] = + { + BOOST_MATH_BIG_CONSTANT(T, 113, 1.000000000000000000000000000000000000e+00), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.927456835239137986889227412815459529e+01), + BOOST_MATH_BIG_CONSTANT(T, 113, 3.598985593265577043711382994516531273e+02), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.449897377085510281395819892689690579e+03), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.025555887684561913263090023158085327e+04), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.774140447181062463181892531100679195e+04), + BOOST_MATH_BIG_CONSTANT(T, 113, 4.962055507843204417243602332246120418e+04), + BOOST_MATH_BIG_CONSTANT(T, 113, 5.908269326976180183216954452196772931e+04), + BOOST_MATH_BIG_CONSTANT(T, 113, 4.655160454422016855911700790722577942e+04), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.383586885019548163464418964577684608e+04), + BOOST_MATH_BIG_CONSTANT(T, 113, 7.679920375586960324298491662159976419e+03), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.478586421028842906987799049804565008e+03), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.565384974896746094224942654383537090e+02), + BOOST_MATH_BIG_CONSTANT(T, 113, 7.902617937084010911005732488607114511e+00), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.429293010387921526110949911029094926e-01), + BOOST_MATH_BIG_CONSTANT(T, 113, 3.880342607911083143560111853491047663e-04) + }; + return ((tools::evaluate_polynomial(P, T(1 / x)) / tools::evaluate_polynomial(Q, T(1 / x)) + Y) * exp(-x) / sqrt(x)); + } + else + { + // Maximum Deviation Found: 4.359e-37 + // Expected Error Term : -6.565e-40 + // Maximum Relative Change in Control Points : 1.880e-01 + // Max Error found at float128 precision = Poly : 2.943572e-35 + static const T Y = 1.308816909790039062500000000000000000f; + static const T P[] = + { + BOOST_MATH_BIG_CONSTANT(T, 113, -5.550277247453881129211735759447737350e-02), + BOOST_MATH_BIG_CONSTANT(T, 113, -3.485883080219574328217554864956175929e+00), + BOOST_MATH_BIG_CONSTANT(T, 113, -8.903760658131484239300875153154881958e+01), + BOOST_MATH_BIG_CONSTANT(T, 113, -1.144813672213626237418235110712293337e+03), + BOOST_MATH_BIG_CONSTANT(T, 113, -6.498400501156131446691826557494158173e+03), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.573531831870363502604119835922166116e+04), + BOOST_MATH_BIG_CONSTANT(T, 113, 5.417416550054632009958262596048841154e+05), + BOOST_MATH_BIG_CONSTANT(T, 113, 4.271266450613557412825896604269130661e+06), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.898386013314389952534433455681107783e+07), + BOOST_MATH_BIG_CONSTANT(T, 113, 5.353798784656436259250791761023512750e+07), + BOOST_MATH_BIG_CONSTANT(T, 113, 9.839619195427352438957774052763490067e+07), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.169246368651532232388152442538005637e+08), + BOOST_MATH_BIG_CONSTANT(T, 113, 8.696368884166831199967845883371116431e+07), + BOOST_MATH_BIG_CONSTANT(T, 113, 3.810226630422736458064005843327500169e+07), + BOOST_MATH_BIG_CONSTANT(T, 113, 8.854996610560406127438950635716757614e+06), + BOOST_MATH_BIG_CONSTANT(T, 113, 8.981057433937398731355768088809437625e+05), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.519440069856232098711793483639792952e+04) + }; + static const T Q[] = + { + BOOST_MATH_BIG_CONSTANT(T, 113, 1.000000000000000000000000000000000000e+00), + BOOST_MATH_BIG_CONSTANT(T, 113, 7.127348248283623146544565916604103560e+01), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.205092684176906740104488180754982065e+03), + BOOST_MATH_BIG_CONSTANT(T, 113, 3.911249195069050636298346469740075758e+04), + BOOST_MATH_BIG_CONSTANT(T, 113, 4.426103406579046249654548481377792614e+05), + BOOST_MATH_BIG_CONSTANT(T, 113, 3.365861555422488771286500241966208541e+06), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.765377714160383676864913709252529840e+07), + BOOST_MATH_BIG_CONSTANT(T, 113, 6.453822726931857253365138260720815246e+07), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.643207885048369990391975749439783892e+08), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.882540678243694621895816336640877878e+08), + BOOST_MATH_BIG_CONSTANT(T, 113, 3.410120808992380266174106812005338148e+08), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.628138016559335882019310900426773027e+08), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.250794693811010646965360198541047961e+08), + BOOST_MATH_BIG_CONSTANT(T, 113, 3.378723408195485594610593014072950078e+07), + BOOST_MATH_BIG_CONSTANT(T, 113, 4.488253856312453816451380319061865560e+06), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.202167197882689873967723350537104582e+05), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.673233230356966539460728211412989843e+03) + }; + if(x < tools::log_max_value<T>()) + return ((tools::evaluate_polynomial(P, T(1 / x)) / tools::evaluate_polynomial(Q, T(1 / x)) + Y) * exp(-x) / sqrt(x)); + else + { + T ex = exp(-x / 2); + return ((tools::evaluate_polynomial(P, T(1 / x)) / tools::evaluate_polynomial(Q, T(1 / x)) + Y) * ex / sqrt(x)) * ex; + } + } + } + + template <typename T> + T bessel_k1_imp(const T& x, const mpl::int_<0>&) + { + if(boost::math::tools::digits<T>() <= 24) + return bessel_k1_imp(x, mpl::int_<24>()); + else if(boost::math::tools::digits<T>() <= 53) + return bessel_k1_imp(x, mpl::int_<53>()); + else if(boost::math::tools::digits<T>() <= 64) + return bessel_k1_imp(x, mpl::int_<64>()); + else if(boost::math::tools::digits<T>() <= 113) + return bessel_k1_imp(x, mpl::int_<113>()); + BOOST_ASSERT(0); + return 0; + } + + template <typename T> + inline T bessel_k1(const T& x) + { + typedef mpl::int_< + ((std::numeric_limits<T>::digits == 0) || (std::numeric_limits<T>::radix != 2)) ? + 0 : + std::numeric_limits<T>::digits <= 24 ? + 24 : + std::numeric_limits<T>::digits <= 53 ? + 53 : + std::numeric_limits<T>::digits <= 64 ? + 64 : + std::numeric_limits<T>::digits <= 113 ? + 113 : -1 + > tag_type; + + bessel_k1_initializer<T, tag_type>::force_instantiate(); + return bessel_k1_imp(x, tag_type()); + } + +}}} // namespaces + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#endif // BOOST_MATH_BESSEL_K1_HPP + diff --git a/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_kn.hpp b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_kn.hpp new file mode 100644 index 00000000000..54c4a1cfa7a --- /dev/null +++ b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_kn.hpp @@ -0,0 +1,86 @@ +// Copyright (c) 2006 Xiaogang Zhang +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_BESSEL_KN_HPP +#define BOOST_MATH_BESSEL_KN_HPP + +#ifdef _MSC_VER +#pragma once +#endif + +#include <boost/math/special_functions/detail/bessel_k0.hpp> +#include <boost/math/special_functions/detail/bessel_k1.hpp> +#include <boost/math/policies/error_handling.hpp> + +// Modified Bessel function of the second kind of integer order +// K_n(z) is the dominant solution, forward recurrence always OK (though unstable) + +namespace boost { namespace math { namespace detail{ + +template <typename T, typename Policy> +T bessel_kn(int n, T x, const Policy& pol) +{ + BOOST_MATH_STD_USING + T value, current, prev; + + using namespace boost::math::tools; + + static const char* function = "boost::math::bessel_kn<%1%>(%1%,%1%)"; + + if (x < 0) + { + return policies::raise_domain_error<T>(function, + "Got x = %1%, but argument x must be non-negative, complex number result not supported.", x, pol); + } + if (x == 0) + { + return policies::raise_overflow_error<T>(function, 0, pol); + } + + if (n < 0) + { + n = -n; // K_{-n}(z) = K_n(z) + } + if (n == 0) + { + value = bessel_k0(x); + } + else if (n == 1) + { + value = bessel_k1(x); + } + else + { + prev = bessel_k0(x); + current = bessel_k1(x); + int k = 1; + BOOST_ASSERT(k < n); + T scale = 1; + do + { + T fact = 2 * k / x; + if((tools::max_value<T>() - fabs(prev)) / fact < fabs(current)) + { + scale /= current; + prev /= current; + current = 1; + } + value = fact * current + prev; + prev = current; + current = value; + ++k; + } + while(k < n); + if(tools::max_value<T>() * scale < fabs(value)) + return sign(scale) * sign(value) * policies::raise_overflow_error<T>(function, 0, pol); + value /= scale; + } + return value; +} + +}}} // namespaces + +#endif // BOOST_MATH_BESSEL_KN_HPP + diff --git a/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_y0.hpp b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_y0.hpp new file mode 100644 index 00000000000..fb93edd1c86 --- /dev/null +++ b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_y0.hpp @@ -0,0 +1,240 @@ +// Copyright (c) 2006 Xiaogang Zhang +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_BESSEL_Y0_HPP +#define BOOST_MATH_BESSEL_Y0_HPP + +#ifdef _MSC_VER +#pragma once +#pragma warning(push) +#pragma warning(disable:4702) // Unreachable code (release mode only warning) +#endif + +#include <boost/math/special_functions/detail/bessel_j0.hpp> +#include <boost/math/constants/constants.hpp> +#include <boost/math/tools/rational.hpp> +#include <boost/math/tools/big_constant.hpp> +#include <boost/math/policies/error_handling.hpp> +#include <boost/assert.hpp> + +#if defined(__GNUC__) && defined(BOOST_MATH_USE_FLOAT128) +// +// This is the only way we can avoid +// warning: non-standard suffix on floating constant [-Wpedantic] +// when building with -Wall -pedantic. Neither __extension__ +// nor #pragma dianostic ignored work :( +// +#pragma GCC system_header +#endif + +// Bessel function of the second kind of order zero +// x <= 8, minimax rational approximations on root-bracketing intervals +// x > 8, Hankel asymptotic expansion in Hart, Computer Approximations, 1968 + +namespace boost { namespace math { namespace detail{ + +template <typename T, typename Policy> +T bessel_y0(T x, const Policy&); + +template <class T, class Policy> +struct bessel_y0_initializer +{ + struct init + { + init() + { + do_init(); + } + static void do_init() + { + bessel_y0(T(1), Policy()); + } + void force_instantiate()const{} + }; + static const init initializer; + static void force_instantiate() + { + initializer.force_instantiate(); + } +}; + +template <class T, class Policy> +const typename bessel_y0_initializer<T, Policy>::init bessel_y0_initializer<T, Policy>::initializer; + +template <typename T, typename Policy> +T bessel_y0(T x, const Policy& pol) +{ + bessel_y0_initializer<T, Policy>::force_instantiate(); + + static const T P1[] = { + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0723538782003176831e+11)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -8.3716255451260504098e+09)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.0422274357376619816e+08)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -2.1287548474401797963e+06)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0102532948020907590e+04)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.8402381979244993524e+01)), + }; + static const T Q1[] = { + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 5.8873865738997033405e+11)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 8.1617187777290363573e+09)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 5.5662956624278251596e+07)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.3889393209447253406e+05)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 6.6475986689240190091e+02)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0)), + }; + static const T P2[] = { + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -2.2213976967566192242e+13)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -5.5107435206722644429e+11)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.3600098638603061642e+10)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -6.9590439394619619534e+08)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.6905288611678631510e+06)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.4566865832663635920e+04)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.7427031242901594547e+01)), + }; + static const T Q2[] = { + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.3386146580707264428e+14)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 5.4266824419412347550e+12)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.4015103849971240096e+10)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.3960202770986831075e+08)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.0669982352539552018e+05)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 8.3030857612070288823e+02)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0)), + }; + static const T P3[] = { + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -8.0728726905150210443e+15)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 6.7016641869173237784e+14)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.2829912364088687306e+11)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.9363051266772083678e+11)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.1958827170518100757e+09)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.0085539923498211426e+07)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.1363534169313901632e+04)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.7439661319197499338e+01)), + }; + static const T Q3[] = { + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.4563724628846457519e+17)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.9272425569640309819e+15)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.2598377924042897629e+13)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 8.6926121104209825246e+10)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.4727219475672302327e+08)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 5.3924739209768057030e+05)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 8.7903362168128450017e+02)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0)), + }; + static const T PC[] = { + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.2779090197304684302e+04)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.1345386639580765797e+04)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.1170523380864944322e+04)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.4806486443249270347e+03)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.5376201909008354296e+02)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 8.8961548424210455236e-01)), + }; + static const T QC[] = { + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.2779090197304684318e+04)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.1370412495510416640e+04)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.1215350561880115730e+04)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.5028735138235608207e+03)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.5711159858080893649e+02)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0)), + }; + static const T PS[] = { + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -8.9226600200800094098e+01)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.8591953644342993800e+02)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.1183429920482737611e+02)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -2.2300261666214198472e+01)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.2441026745835638459e+00)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -8.8033303048680751817e-03)), + }; + static const T QS[] = { + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 5.7105024128512061905e+03)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.1951131543434613647e+04)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 7.2642780169211018836e+03)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.4887231232283756582e+03)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 9.0593769594993125859e+01)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0)), + }; + static const T x1 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 8.9357696627916752158e-01)), + x2 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.9576784193148578684e+00)), + x3 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 7.0860510603017726976e+00)), + x11 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.280e+02)), + x12 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.9519662791675215849e-03)), + x21 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0130e+03)), + x22 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 6.4716931485786837568e-04)), + x31 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.8140e+03)), + x32 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.1356030177269762362e-04)) + ; + T value, factor, r, rc, rs; + + BOOST_MATH_STD_USING + using namespace boost::math::tools; + using namespace boost::math::constants; + + static const char* function = "boost::math::bessel_y0<%1%>(%1%,%1%)"; + + if (x < 0) + { + return policies::raise_domain_error<T>(function, + "Got x = %1% but x must be non-negative, complex result not supported.", x, pol); + } + if (x == 0) + { + return -policies::raise_overflow_error<T>(function, 0, pol); + } + if (x <= 3) // x in (0, 3] + { + T y = x * x; + T z = 2 * log(x/x1) * bessel_j0(x) / pi<T>(); + r = evaluate_rational(P1, Q1, y); + factor = (x + x1) * ((x - x11/256) - x12); + value = z + factor * r; + } + else if (x <= 5.5f) // x in (3, 5.5] + { + T y = x * x; + T z = 2 * log(x/x2) * bessel_j0(x) / pi<T>(); + r = evaluate_rational(P2, Q2, y); + factor = (x + x2) * ((x - x21/256) - x22); + value = z + factor * r; + } + else if (x <= 8) // x in (5.5, 8] + { + T y = x * x; + T z = 2 * log(x/x3) * bessel_j0(x) / pi<T>(); + r = evaluate_rational(P3, Q3, y); + factor = (x + x3) * ((x - x31/256) - x32); + value = z + factor * r; + } + else // x in (8, \infty) + { + T y = 8 / x; + T y2 = y * y; + rc = evaluate_rational(PC, QC, y2); + rs = evaluate_rational(PS, QS, y2); + factor = constants::one_div_root_pi<T>() / sqrt(x); + // + // The following code is really just: + // + // T z = x - 0.25f * pi<T>(); + // value = factor * (rc * sin(z) + y * rs * cos(z)); + // + // But using the sin/cos addition formulae and constant values for + // sin/cos of PI/4 which then cancel part of the "factor" term as they're all + // 1 / sqrt(2): + // + T sx = sin(x); + T cx = cos(x); + value = factor * (rc * (sx - cx) + y * rs * (cx + sx)); + } + + return value; +} + +}}} // namespaces + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#endif // BOOST_MATH_BESSEL_Y0_HPP + diff --git a/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_y1.hpp b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_y1.hpp new file mode 100644 index 00000000000..98389a90e68 --- /dev/null +++ b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_y1.hpp @@ -0,0 +1,212 @@ +// Copyright (c) 2006 Xiaogang Zhang +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_BESSEL_Y1_HPP +#define BOOST_MATH_BESSEL_Y1_HPP + +#ifdef _MSC_VER +#pragma once +#pragma warning(push) +#pragma warning(disable:4702) // Unreachable code (release mode only warning) +#endif + +#include <boost/math/special_functions/detail/bessel_j1.hpp> +#include <boost/math/constants/constants.hpp> +#include <boost/math/tools/rational.hpp> +#include <boost/math/tools/big_constant.hpp> +#include <boost/math/policies/error_handling.hpp> +#include <boost/assert.hpp> + +#if defined(__GNUC__) && defined(BOOST_MATH_USE_FLOAT128) +// +// This is the only way we can avoid +// warning: non-standard suffix on floating constant [-Wpedantic] +// when building with -Wall -pedantic. Neither __extension__ +// nor #pragma dianostic ignored work :( +// +#pragma GCC system_header +#endif + +// Bessel function of the second kind of order one +// x <= 8, minimax rational approximations on root-bracketing intervals +// x > 8, Hankel asymptotic expansion in Hart, Computer Approximations, 1968 + +namespace boost { namespace math { namespace detail{ + +template <typename T, typename Policy> +T bessel_y1(T x, const Policy&); + +template <class T, class Policy> +struct bessel_y1_initializer +{ + struct init + { + init() + { + do_init(); + } + static void do_init() + { + bessel_y1(T(1), Policy()); + } + void force_instantiate()const{} + }; + static const init initializer; + static void force_instantiate() + { + initializer.force_instantiate(); + } +}; + +template <class T, class Policy> +const typename bessel_y1_initializer<T, Policy>::init bessel_y1_initializer<T, Policy>::initializer; + +template <typename T, typename Policy> +T bessel_y1(T x, const Policy& pol) +{ + bessel_y1_initializer<T, Policy>::force_instantiate(); + + static const T P1[] = { + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.0535726612579544093e+13)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 5.4708611716525426053e+12)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -3.7595974497819597599e+11)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 7.2144548214502560419e+09)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -5.9157479997408395984e+07)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.2157953222280260820e+05)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -3.1714424660046133456e+02)), + }; + static const T Q1[] = { + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.0737873921079286084e+14)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.1272286200406461981e+12)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.7800352738690585613e+10)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.2250435122182963220e+08)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.8136470753052572164e+05)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 8.2079908168393867438e+02)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0)), + }; + static const T P2[] = { + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.1514276357909013326e+19)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -5.6808094574724204577e+18)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -2.3638408497043134724e+16)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.0686275289804744814e+15)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -5.9530713129741981618e+13)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.7453673962438488783e+11)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.1957961912070617006e+09)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.9153806858264202986e+06)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.2337180442012953128e+03)), + }; + static const T Q2[] = { + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 5.3321844313316185697e+20)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 5.6968198822857178911e+18)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.0837179548112881950e+16)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.1187010065856971027e+14)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.0221766852960403645e+11)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 6.3550318087088919566e+08)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0453748201934079734e+06)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.2855164849321609336e+03)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0)), + }; + static const T PC[] = { + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -4.4357578167941278571e+06)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -9.9422465050776411957e+06)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -6.6033732483649391093e+06)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.5235293511811373833e+06)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.0982405543459346727e+05)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.6116166443246101165e+03)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.0)), + }; + static const T QC[] = { + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -4.4357578167941278568e+06)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -9.9341243899345856590e+06)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -6.5853394797230870728e+06)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.5118095066341608816e+06)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.0726385991103820119e+05)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.4550094401904961825e+03)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0)), + }; + static const T PS[] = { + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.3220913409857223519e+04)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 8.5145160675335701966e+04)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 6.6178836581270835179e+04)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.8494262873223866797e+04)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.7063754290207680021e+03)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.5265133846636032186e+01)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.0)), + }; + static const T QS[] = { + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 7.0871281941028743574e+05)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.8194580422439972989e+06)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.4194606696037208929e+06)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.0029443582266975117e+05)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.7890229745772202641e+04)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 8.6383677696049909675e+02)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0)), + }; + static const T x1 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.1971413260310170351e+00)), + x2 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 5.4296810407941351328e+00)), + x11 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 5.620e+02)), + x12 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.8288260310170351490e-03)), + x21 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.3900e+03)), + x22 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -6.4592058648672279948e-06)) + ; + T value, factor, r, rc, rs; + + BOOST_MATH_STD_USING + using namespace boost::math::tools; + using namespace boost::math::constants; + + if (x <= 0) + { + return policies::raise_domain_error<T>("bost::math::bessel_y1<%1%>(%1%,%1%)", + "Got x == %1%, but x must be > 0, complex result not supported.", x, pol); + } + if (x <= 4) // x in (0, 4] + { + T y = x * x; + T z = 2 * log(x/x1) * bessel_j1(x) / pi<T>(); + r = evaluate_rational(P1, Q1, y); + factor = (x + x1) * ((x - x11/256) - x12) / x; + value = z + factor * r; + } + else if (x <= 8) // x in (4, 8] + { + T y = x * x; + T z = 2 * log(x/x2) * bessel_j1(x) / pi<T>(); + r = evaluate_rational(P2, Q2, y); + factor = (x + x2) * ((x - x21/256) - x22) / x; + value = z + factor * r; + } + else // x in (8, \infty) + { + T y = 8 / x; + T y2 = y * y; + rc = evaluate_rational(PC, QC, y2); + rs = evaluate_rational(PS, QS, y2); + factor = 1 / (sqrt(x) * root_pi<T>()); + // + // This code is really just: + // + // T z = x - 0.75f * pi<T>(); + // value = factor * (rc * sin(z) + y * rs * cos(z)); + // + // But using the sin/cos addition rules, plus constants for sin/cos of 3PI/4 + // which then cancel out with corresponding terms in "factor". + // + T sx = sin(x); + T cx = cos(x); + value = factor * (y * rs * (sx - cx) - rc * (sx + cx)); + } + + return value; +} + +}}} // namespaces + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#endif // BOOST_MATH_BESSEL_Y1_HPP + diff --git a/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_yn.hpp b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_yn.hpp new file mode 100644 index 00000000000..62d7377e4ff --- /dev/null +++ b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/bessel_yn.hpp @@ -0,0 +1,112 @@ +// Copyright (c) 2006 Xiaogang Zhang +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_BESSEL_YN_HPP +#define BOOST_MATH_BESSEL_YN_HPP + +#ifdef _MSC_VER +#pragma once +#endif + +#include <boost/math/special_functions/detail/bessel_y0.hpp> +#include <boost/math/special_functions/detail/bessel_y1.hpp> +#include <boost/math/special_functions/detail/bessel_jy_series.hpp> +#include <boost/math/policies/error_handling.hpp> + +// Bessel function of the second kind of integer order +// Y_n(z) is the dominant solution, forward recurrence always OK (though unstable) + +namespace boost { namespace math { namespace detail{ + +template <typename T, typename Policy> +T bessel_yn(int n, T x, const Policy& pol) +{ + BOOST_MATH_STD_USING + T value, factor, current, prev; + + using namespace boost::math::tools; + + static const char* function = "boost::math::bessel_yn<%1%>(%1%,%1%)"; + + if ((x == 0) && (n == 0)) + { + return -policies::raise_overflow_error<T>(function, 0, pol); + } + if (x <= 0) + { + return policies::raise_domain_error<T>(function, + "Got x = %1%, but x must be > 0, complex result not supported.", x, pol); + } + + // + // Reflection comes first: + // + if (n < 0) + { + factor = static_cast<T>((n & 0x1) ? -1 : 1); // Y_{-n}(z) = (-1)^n Y_n(z) + n = -n; + } + else + { + factor = 1; + } + if(x < policies::get_epsilon<T, Policy>()) + { + T scale = 1; + value = bessel_yn_small_z(n, x, &scale, pol); + if(tools::max_value<T>() * fabs(scale) < fabs(value)) + return boost::math::sign(scale) * boost::math::sign(value) * policies::raise_overflow_error<T>(function, 0, pol); + value /= scale; + } + else if(asymptotic_bessel_large_x_limit(n, x)) + { + value = factor * asymptotic_bessel_y_large_x_2(static_cast<T>(abs(n)), x); + } + else if (n == 0) + { + value = bessel_y0(x, pol); + } + else if (n == 1) + { + value = factor * bessel_y1(x, pol); + } + else + { + prev = bessel_y0(x, pol); + current = bessel_y1(x, pol); + int k = 1; + BOOST_ASSERT(k < n); + policies::check_series_iterations<T>("boost::math::bessel_y_n<%1%>(%1%,%1%)", n, pol); + T mult = 2 * k / x; + value = mult * current - prev; + prev = current; + current = value; + ++k; + if((mult > 1) && (fabs(current) > 1)) + { + prev /= current; + factor /= current; + value /= current; + current = 1; + } + while(k < n) + { + mult = 2 * k / x; + value = mult * current - prev; + prev = current; + current = value; + ++k; + } + if(fabs(tools::max_value<T>() * factor) < fabs(value)) + return sign(value) * sign(factor) * policies::raise_overflow_error<T>(function, 0, pol); + value /= factor; + } + return value; +} + +}}} // namespaces + +#endif // BOOST_MATH_BESSEL_YN_HPP + diff --git a/src/third_party/boost-1.70.0/boost/math/special_functions/detail/erf_inv.hpp b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/erf_inv.hpp new file mode 100644 index 00000000000..4e483005216 --- /dev/null +++ b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/erf_inv.hpp @@ -0,0 +1,549 @@ +// (C) Copyright John Maddock 2006. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_SF_ERF_INV_HPP +#define BOOST_MATH_SF_ERF_INV_HPP + +#ifdef _MSC_VER +#pragma once +#pragma warning(push) +#pragma warning(disable:4127) // Conditional expression is constant +#pragma warning(disable:4702) // Unreachable code: optimization warning +#endif + +namespace boost{ namespace math{ + +namespace detail{ +// +// The inverse erf and erfc functions share a common implementation, +// this version is for 80-bit long double's and smaller: +// +template <class T, class Policy> +T erf_inv_imp(const T& p, const T& q, const Policy&, const boost::mpl::int_<64>*) +{ + BOOST_MATH_STD_USING // for ADL of std names. + + T result = 0; + + if(p <= 0.5) + { + // + // Evaluate inverse erf using the rational approximation: + // + // x = p(p+10)(Y+R(p)) + // + // Where Y is a constant, and R(p) is optimised for a low + // absolute error compared to |Y|. + // + // double: Max error found: 2.001849e-18 + // long double: Max error found: 1.017064e-20 + // Maximum Deviation Found (actual error term at infinite precision) 8.030e-21 + // + static const float Y = 0.0891314744949340820313f; + static const T P[] = { + BOOST_MATH_BIG_CONSTANT(T, 64, -0.000508781949658280665617), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.00836874819741736770379), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.0334806625409744615033), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.0126926147662974029034), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.0365637971411762664006), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.0219878681111168899165), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.00822687874676915743155), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.00538772965071242932965) + }; + static const T Q[] = { + BOOST_MATH_BIG_CONSTANT(T, 64, 1.0), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.970005043303290640362), + BOOST_MATH_BIG_CONSTANT(T, 64, -1.56574558234175846809), + BOOST_MATH_BIG_CONSTANT(T, 64, 1.56221558398423026363), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.662328840472002992063), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.71228902341542847553), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.0527396382340099713954), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.0795283687341571680018), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.00233393759374190016776), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.000886216390456424707504) + }; + T g = p * (p + 10); + T r = tools::evaluate_polynomial(P, p) / tools::evaluate_polynomial(Q, p); + result = g * Y + g * r; + } + else if(q >= 0.25) + { + // + // Rational approximation for 0.5 > q >= 0.25 + // + // x = sqrt(-2*log(q)) / (Y + R(q)) + // + // Where Y is a constant, and R(q) is optimised for a low + // absolute error compared to Y. + // + // double : Max error found: 7.403372e-17 + // long double : Max error found: 6.084616e-20 + // Maximum Deviation Found (error term) 4.811e-20 + // + static const float Y = 2.249481201171875f; + static const T P[] = { + BOOST_MATH_BIG_CONSTANT(T, 64, -0.202433508355938759655), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.105264680699391713268), + BOOST_MATH_BIG_CONSTANT(T, 64, 8.37050328343119927838), + BOOST_MATH_BIG_CONSTANT(T, 64, 17.6447298408374015486), + BOOST_MATH_BIG_CONSTANT(T, 64, -18.8510648058714251895), + BOOST_MATH_BIG_CONSTANT(T, 64, -44.6382324441786960818), + BOOST_MATH_BIG_CONSTANT(T, 64, 17.445385985570866523), + BOOST_MATH_BIG_CONSTANT(T, 64, 21.1294655448340526258), + BOOST_MATH_BIG_CONSTANT(T, 64, -3.67192254707729348546) + }; + static const T Q[] = { + BOOST_MATH_BIG_CONSTANT(T, 64, 1.0), + BOOST_MATH_BIG_CONSTANT(T, 64, 6.24264124854247537712), + BOOST_MATH_BIG_CONSTANT(T, 64, 3.9713437953343869095), + BOOST_MATH_BIG_CONSTANT(T, 64, -28.6608180499800029974), + BOOST_MATH_BIG_CONSTANT(T, 64, -20.1432634680485188801), + BOOST_MATH_BIG_CONSTANT(T, 64, 48.5609213108739935468), + BOOST_MATH_BIG_CONSTANT(T, 64, 10.8268667355460159008), + BOOST_MATH_BIG_CONSTANT(T, 64, -22.6436933413139721736), + BOOST_MATH_BIG_CONSTANT(T, 64, 1.72114765761200282724) + }; + T g = sqrt(-2 * log(q)); + T xs = q - 0.25f; + T r = tools::evaluate_polynomial(P, xs) / tools::evaluate_polynomial(Q, xs); + result = g / (Y + r); + } + else + { + // + // For q < 0.25 we have a series of rational approximations all + // of the general form: + // + // let: x = sqrt(-log(q)) + // + // Then the result is given by: + // + // x(Y+R(x-B)) + // + // where Y is a constant, B is the lowest value of x for which + // the approximation is valid, and R(x-B) is optimised for a low + // absolute error compared to Y. + // + // Note that almost all code will really go through the first + // or maybe second approximation. After than we're dealing with very + // small input values indeed: 80 and 128 bit long double's go all the + // way down to ~ 1e-5000 so the "tail" is rather long... + // + T x = sqrt(-log(q)); + if(x < 3) + { + // Max error found: 1.089051e-20 + static const float Y = 0.807220458984375f; + static const T P[] = { + BOOST_MATH_BIG_CONSTANT(T, 64, -0.131102781679951906451), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.163794047193317060787), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.117030156341995252019), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.387079738972604337464), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.337785538912035898924), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.142869534408157156766), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.0290157910005329060432), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.00214558995388805277169), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.679465575181126350155e-6), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.285225331782217055858e-7), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.681149956853776992068e-9) + }; + static const T Q[] = { + BOOST_MATH_BIG_CONSTANT(T, 64, 1.0), + BOOST_MATH_BIG_CONSTANT(T, 64, 3.46625407242567245975), + BOOST_MATH_BIG_CONSTANT(T, 64, 5.38168345707006855425), + BOOST_MATH_BIG_CONSTANT(T, 64, 4.77846592945843778382), + BOOST_MATH_BIG_CONSTANT(T, 64, 2.59301921623620271374), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.848854343457902036425), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.152264338295331783612), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.01105924229346489121) + }; + T xs = x - 1.125f; + T R = tools::evaluate_polynomial(P, xs) / tools::evaluate_polynomial(Q, xs); + result = Y * x + R * x; + } + else if(x < 6) + { + // Max error found: 8.389174e-21 + static const float Y = 0.93995571136474609375f; + static const T P[] = { + BOOST_MATH_BIG_CONSTANT(T, 64, -0.0350353787183177984712), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.00222426529213447927281), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.0185573306514231072324), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.00950804701325919603619), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.00187123492819559223345), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.000157544617424960554631), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.460469890584317994083e-5), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.230404776911882601748e-9), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.266339227425782031962e-11) + }; + static const T Q[] = { + BOOST_MATH_BIG_CONSTANT(T, 64, 1.0), + BOOST_MATH_BIG_CONSTANT(T, 64, 1.3653349817554063097), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.762059164553623404043), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.220091105764131249824), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.0341589143670947727934), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.00263861676657015992959), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.764675292302794483503e-4) + }; + T xs = x - 3; + T R = tools::evaluate_polynomial(P, xs) / tools::evaluate_polynomial(Q, xs); + result = Y * x + R * x; + } + else if(x < 18) + { + // Max error found: 1.481312e-19 + static const float Y = 0.98362827301025390625f; + static const T P[] = { + BOOST_MATH_BIG_CONSTANT(T, 64, -0.0167431005076633737133), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.00112951438745580278863), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.00105628862152492910091), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.000209386317487588078668), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.149624783758342370182e-4), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.449696789927706453732e-6), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.462596163522878599135e-8), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.281128735628831791805e-13), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.99055709973310326855e-16) + }; + static const T Q[] = { + BOOST_MATH_BIG_CONSTANT(T, 64, 1.0), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.591429344886417493481), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.138151865749083321638), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.0160746087093676504695), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.000964011807005165528527), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.275335474764726041141e-4), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.282243172016108031869e-6) + }; + T xs = x - 6; + T R = tools::evaluate_polynomial(P, xs) / tools::evaluate_polynomial(Q, xs); + result = Y * x + R * x; + } + else if(x < 44) + { + // Max error found: 5.697761e-20 + static const float Y = 0.99714565277099609375f; + static const T P[] = { + BOOST_MATH_BIG_CONSTANT(T, 64, -0.0024978212791898131227), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.779190719229053954292e-5), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.254723037413027451751e-4), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.162397777342510920873e-5), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.396341011304801168516e-7), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.411632831190944208473e-9), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.145596286718675035587e-11), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.116765012397184275695e-17) + }; + static const T Q[] = { + BOOST_MATH_BIG_CONSTANT(T, 64, 1.0), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.207123112214422517181), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.0169410838120975906478), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.000690538265622684595676), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.145007359818232637924e-4), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.144437756628144157666e-6), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.509761276599778486139e-9) + }; + T xs = x - 18; + T R = tools::evaluate_polynomial(P, xs) / tools::evaluate_polynomial(Q, xs); + result = Y * x + R * x; + } + else + { + // Max error found: 1.279746e-20 + static const float Y = 0.99941349029541015625f; + static const T P[] = { + BOOST_MATH_BIG_CONSTANT(T, 64, -0.000539042911019078575891), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.28398759004727721098e-6), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.899465114892291446442e-6), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.229345859265920864296e-7), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.225561444863500149219e-9), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.947846627503022684216e-12), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.135880130108924861008e-14), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.348890393399948882918e-21) + }; + static const T Q[] = { + BOOST_MATH_BIG_CONSTANT(T, 64, 1.0), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.0845746234001899436914), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.00282092984726264681981), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.468292921940894236786e-4), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.399968812193862100054e-6), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.161809290887904476097e-8), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.231558608310259605225e-11) + }; + T xs = x - 44; + T R = tools::evaluate_polynomial(P, xs) / tools::evaluate_polynomial(Q, xs); + result = Y * x + R * x; + } + } + return result; +} + +template <class T, class Policy> +struct erf_roots +{ + boost::math::tuple<T,T,T> operator()(const T& guess) + { + BOOST_MATH_STD_USING + T derivative = sign * (2 / sqrt(constants::pi<T>())) * exp(-(guess * guess)); + T derivative2 = -2 * guess * derivative; + return boost::math::make_tuple(((sign > 0) ? static_cast<T>(boost::math::erf(guess, Policy()) - target) : static_cast<T>(boost::math::erfc(guess, Policy())) - target), derivative, derivative2); + } + erf_roots(T z, int s) : target(z), sign(s) {} +private: + T target; + int sign; +}; + +template <class T, class Policy> +T erf_inv_imp(const T& p, const T& q, const Policy& pol, const boost::mpl::int_<0>*) +{ + // + // Generic version, get a guess that's accurate to 64-bits (10^-19) + // + T guess = erf_inv_imp(p, q, pol, static_cast<mpl::int_<64> const*>(0)); + T result; + // + // If T has more bit's than 64 in it's mantissa then we need to iterate, + // otherwise we can just return the result: + // + if(policies::digits<T, Policy>() > 64) + { + boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>(); + if(p <= 0.5) + { + result = tools::halley_iterate(detail::erf_roots<typename remove_cv<T>::type, Policy>(p, 1), guess, static_cast<T>(0), tools::max_value<T>(), (policies::digits<T, Policy>() * 2) / 3, max_iter); + } + else + { + result = tools::halley_iterate(detail::erf_roots<typename remove_cv<T>::type, Policy>(q, -1), guess, static_cast<T>(0), tools::max_value<T>(), (policies::digits<T, Policy>() * 2) / 3, max_iter); + } + policies::check_root_iterations<T>("boost::math::erf_inv<%1%>", max_iter, pol); + } + else + { + result = guess; + } + return result; +} + +template <class T, class Policy> +struct erf_inv_initializer +{ + struct init + { + init() + { + do_init(); + } + static bool is_value_non_zero(T); + static void do_init() + { + // If std::numeric_limits<T>::digits is zero, we must not call + // our inituialization code here as the precision presumably + // varies at runtime, and will not have been set yet. + if(std::numeric_limits<T>::digits) + { + boost::math::erf_inv(static_cast<T>(0.25), Policy()); + boost::math::erf_inv(static_cast<T>(0.55), Policy()); + boost::math::erf_inv(static_cast<T>(0.95), Policy()); + boost::math::erfc_inv(static_cast<T>(1e-15), Policy()); + // These following initializations must not be called if + // type T can not hold the relevant values without + // underflow to zero. We check this at runtime because + // some tools such as valgrind silently change the precision + // of T at runtime, and numeric_limits basically lies! + if(is_value_non_zero(static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1e-130)))) + boost::math::erfc_inv(static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1e-130)), Policy()); + + // Some compilers choke on constants that would underflow, even in code that isn't instantiated + // so try and filter these cases out in the preprocessor: +#if LDBL_MAX_10_EXP >= 800 + if(is_value_non_zero(static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1e-800)))) + boost::math::erfc_inv(static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1e-800)), Policy()); + if(is_value_non_zero(static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1e-900)))) + boost::math::erfc_inv(static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1e-900)), Policy()); +#else + if(is_value_non_zero(static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 64, 1e-800)))) + boost::math::erfc_inv(static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 64, 1e-800)), Policy()); + if(is_value_non_zero(static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 64, 1e-900)))) + boost::math::erfc_inv(static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 64, 1e-900)), Policy()); +#endif + } + } + void force_instantiate()const{} + }; + static const init initializer; + static void force_instantiate() + { + initializer.force_instantiate(); + } +}; + +template <class T, class Policy> +const typename erf_inv_initializer<T, Policy>::init erf_inv_initializer<T, Policy>::initializer; + +template <class T, class Policy> +bool erf_inv_initializer<T, Policy>::init::is_value_non_zero(T v) +{ + // This needs to be non-inline to detect whether v is non zero at runtime + // rather than at compile time, only relevant when running under valgrind + // which changes long double's to double's on the fly. + return v != 0; +} + +} // namespace detail + +template <class T, class Policy> +typename tools::promote_args<T>::type erfc_inv(T z, const Policy& pol) +{ + typedef typename tools::promote_args<T>::type result_type; + + // + // Begin by testing for domain errors, and other special cases: + // + static const char* function = "boost::math::erfc_inv<%1%>(%1%, %1%)"; + if((z < 0) || (z > 2)) + return policies::raise_domain_error<result_type>(function, "Argument outside range [0,2] in inverse erfc function (got p=%1%).", z, pol); + if(z == 0) + return policies::raise_overflow_error<result_type>(function, 0, pol); + if(z == 2) + return -policies::raise_overflow_error<result_type>(function, 0, pol); + // + // Normalise the input, so it's in the range [0,1], we will + // negate the result if z is outside that range. This is a simple + // application of the erfc reflection formula: erfc(-z) = 2 - erfc(z) + // + result_type p, q, s; + if(z > 1) + { + q = 2 - z; + p = 1 - q; + s = -1; + } + else + { + p = 1 - z; + q = z; + s = 1; + } + // + // A bit of meta-programming to figure out which implementation + // to use, based on the number of bits in the mantissa of T: + // + typedef typename policies::precision<result_type, Policy>::type precision_type; + typedef typename mpl::if_< + mpl::or_<mpl::less_equal<precision_type, mpl::int_<0> >, mpl::greater<precision_type, mpl::int_<64> > >, + mpl::int_<0>, + mpl::int_<64> + >::type tag_type; + // + // Likewise use internal promotion, so we evaluate at a higher + // precision internally if it's appropriate: + // + typedef typename policies::evaluation<result_type, Policy>::type eval_type; + typedef typename policies::normalise< + Policy, + policies::promote_float<false>, + policies::promote_double<false>, + policies::discrete_quantile<>, + policies::assert_undefined<> >::type forwarding_policy; + + detail::erf_inv_initializer<eval_type, forwarding_policy>::force_instantiate(); + + // + // And get the result, negating where required: + // + return s * policies::checked_narrowing_cast<result_type, forwarding_policy>( + detail::erf_inv_imp(static_cast<eval_type>(p), static_cast<eval_type>(q), forwarding_policy(), static_cast<tag_type const*>(0)), function); +} + +template <class T, class Policy> +typename tools::promote_args<T>::type erf_inv(T z, const Policy& pol) +{ + typedef typename tools::promote_args<T>::type result_type; + + // + // Begin by testing for domain errors, and other special cases: + // + static const char* function = "boost::math::erf_inv<%1%>(%1%, %1%)"; + if((z < -1) || (z > 1)) + return policies::raise_domain_error<result_type>(function, "Argument outside range [-1, 1] in inverse erf function (got p=%1%).", z, pol); + if(z == 1) + return policies::raise_overflow_error<result_type>(function, 0, pol); + if(z == -1) + return -policies::raise_overflow_error<result_type>(function, 0, pol); + if(z == 0) + return 0; + // + // Normalise the input, so it's in the range [0,1], we will + // negate the result if z is outside that range. This is a simple + // application of the erf reflection formula: erf(-z) = -erf(z) + // + result_type p, q, s; + if(z < 0) + { + p = -z; + q = 1 - p; + s = -1; + } + else + { + p = z; + q = 1 - z; + s = 1; + } + // + // A bit of meta-programming to figure out which implementation + // to use, based on the number of bits in the mantissa of T: + // + typedef typename policies::precision<result_type, Policy>::type precision_type; + typedef typename mpl::if_< + mpl::or_<mpl::less_equal<precision_type, mpl::int_<0> >, mpl::greater<precision_type, mpl::int_<64> > >, + mpl::int_<0>, + mpl::int_<64> + >::type tag_type; + // + // Likewise use internal promotion, so we evaluate at a higher + // precision internally if it's appropriate: + // + typedef typename policies::evaluation<result_type, Policy>::type eval_type; + typedef typename policies::normalise< + Policy, + policies::promote_float<false>, + policies::promote_double<false>, + policies::discrete_quantile<>, + policies::assert_undefined<> >::type forwarding_policy; + // + // Likewise use internal promotion, so we evaluate at a higher + // precision internally if it's appropriate: + // + typedef typename policies::evaluation<result_type, Policy>::type eval_type; + + detail::erf_inv_initializer<eval_type, forwarding_policy>::force_instantiate(); + // + // And get the result, negating where required: + // + return s * policies::checked_narrowing_cast<result_type, forwarding_policy>( + detail::erf_inv_imp(static_cast<eval_type>(p), static_cast<eval_type>(q), forwarding_policy(), static_cast<tag_type const*>(0)), function); +} + +template <class T> +inline typename tools::promote_args<T>::type erfc_inv(T z) +{ + return erfc_inv(z, policies::policy<>()); +} + +template <class T> +inline typename tools::promote_args<T>::type erf_inv(T z) +{ + return erf_inv(z, policies::policy<>()); +} + +} // namespace math +} // namespace boost + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#endif // BOOST_MATH_SF_ERF_INV_HPP + diff --git a/src/third_party/boost-1.70.0/boost/math/special_functions/detail/fp_traits.hpp b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/fp_traits.hpp new file mode 100644 index 00000000000..013f830bcad --- /dev/null +++ b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/fp_traits.hpp @@ -0,0 +1,581 @@ +// fp_traits.hpp + +#ifndef BOOST_MATH_FP_TRAITS_HPP +#define BOOST_MATH_FP_TRAITS_HPP + +// Copyright (c) 2006 Johan Rade + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +/* +To support old compilers, care has been taken to avoid partial template +specialization and meta function forwarding. +With these techniques, the code could be simplified. +*/ + +#if defined(__vms) && defined(__DECCXX) && !__IEEE_FLOAT +// The VAX floating point formats are used (for float and double) +# define BOOST_FPCLASSIFY_VAX_FORMAT +#endif + +#include <cstring> + +#include <boost/assert.hpp> +#include <boost/cstdint.hpp> +#include <boost/predef/other/endian.h> +#include <boost/static_assert.hpp> +#include <boost/type_traits/is_floating_point.hpp> + +#ifdef BOOST_NO_STDC_NAMESPACE + namespace std{ using ::memcpy; } +#endif + +#ifndef FP_NORMAL + +#define FP_ZERO 0 +#define FP_NORMAL 1 +#define FP_INFINITE 2 +#define FP_NAN 3 +#define FP_SUBNORMAL 4 + +#else + +#define BOOST_HAS_FPCLASSIFY + +#ifndef fpclassify +# if (defined(__GLIBCPP__) || defined(__GLIBCXX__)) \ + && defined(_GLIBCXX_USE_C99_MATH) \ + && !(defined(_GLIBCXX_USE_C99_FP_MACROS_DYNAMIC) \ + && (_GLIBCXX_USE_C99_FP_MACROS_DYNAMIC != 0)) +# ifdef _STLP_VENDOR_CSTD +# if _STLPORT_VERSION >= 0x520 +# define BOOST_FPCLASSIFY_PREFIX ::__std_alias:: +# else +# define BOOST_FPCLASSIFY_PREFIX ::_STLP_VENDOR_CSTD:: +# endif +# else +# define BOOST_FPCLASSIFY_PREFIX ::std:: +# endif +# else +# undef BOOST_HAS_FPCLASSIFY +# define BOOST_FPCLASSIFY_PREFIX +# endif +#elif (defined(__HP_aCC) && !defined(__hppa)) +// aCC 6 appears to do "#define fpclassify fpclassify" which messes us up a bit! +# define BOOST_FPCLASSIFY_PREFIX :: +#else +# define BOOST_FPCLASSIFY_PREFIX +#endif + +#ifdef __MINGW32__ +# undef BOOST_HAS_FPCLASSIFY +#endif + +#endif + + +//------------------------------------------------------------------------------ + +namespace boost { +namespace math { +namespace detail { + +//------------------------------------------------------------------------------ + +/* +The following classes are used to tag the different methods that are used +for floating point classification +*/ + +struct native_tag {}; +template <bool has_limits> +struct generic_tag {}; +struct ieee_tag {}; +struct ieee_copy_all_bits_tag : public ieee_tag {}; +struct ieee_copy_leading_bits_tag : public ieee_tag {}; + +#ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS +// +// These helper functions are used only when numeric_limits<> +// members are not compile time constants: +// +inline bool is_generic_tag_false(const generic_tag<false>*) +{ + return true; +} +inline bool is_generic_tag_false(const void*) +{ + return false; +} +#endif + +//------------------------------------------------------------------------------ + +/* +Most processors support three different floating point precisions: +single precision (32 bits), double precision (64 bits) +and extended double precision (80 - 128 bits, depending on the processor) + +Note that the C++ type long double can be implemented +both as double precision and extended double precision. +*/ + +struct unknown_precision{}; +struct single_precision {}; +struct double_precision {}; +struct extended_double_precision {}; + +// native_tag version -------------------------------------------------------------- + +template<class T> struct fp_traits_native +{ + typedef native_tag method; +}; + +// generic_tag version ------------------------------------------------------------- + +template<class T, class U> struct fp_traits_non_native +{ +#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS + typedef generic_tag<std::numeric_limits<T>::is_specialized> method; +#else + typedef generic_tag<false> method; +#endif +}; + +// ieee_tag versions --------------------------------------------------------------- + +/* +These specializations of fp_traits_non_native contain information needed +to "parse" the binary representation of a floating point number. + +Typedef members: + + bits -- the target type when copying the leading bytes of a floating + point number. It is a typedef for uint32_t or uint64_t. + + method -- tells us whether all bytes are copied or not. + It is a typedef for ieee_copy_all_bits_tag or ieee_copy_leading_bits_tag. + +Static data members: + + sign, exponent, flag, significand -- bit masks that give the meaning of the + bits in the leading bytes. + +Static function members: + + get_bits(), set_bits() -- provide access to the leading bytes. + +*/ + +// ieee_tag version, float (32 bits) ----------------------------------------------- + +#ifndef BOOST_FPCLASSIFY_VAX_FORMAT + +template<> struct fp_traits_non_native<float, single_precision> +{ + typedef ieee_copy_all_bits_tag method; + + BOOST_STATIC_CONSTANT(uint32_t, sign = 0x80000000u); + BOOST_STATIC_CONSTANT(uint32_t, exponent = 0x7f800000); + BOOST_STATIC_CONSTANT(uint32_t, flag = 0x00000000); + BOOST_STATIC_CONSTANT(uint32_t, significand = 0x007fffff); + + typedef uint32_t bits; + static void get_bits(float x, uint32_t& a) { std::memcpy(&a, &x, 4); } + static void set_bits(float& x, uint32_t a) { std::memcpy(&x, &a, 4); } +}; + +// ieee_tag version, double (64 bits) ---------------------------------------------- + +#if defined(BOOST_NO_INT64_T) || defined(BOOST_NO_INCLASS_MEMBER_INITIALIZATION) \ + || defined(__BORLANDC__) || defined(__CODEGEAR__) + +template<> struct fp_traits_non_native<double, double_precision> +{ + typedef ieee_copy_leading_bits_tag method; + + BOOST_STATIC_CONSTANT(uint32_t, sign = 0x80000000u); + BOOST_STATIC_CONSTANT(uint32_t, exponent = 0x7ff00000); + BOOST_STATIC_CONSTANT(uint32_t, flag = 0); + BOOST_STATIC_CONSTANT(uint32_t, significand = 0x000fffff); + + typedef uint32_t bits; + + static void get_bits(double x, uint32_t& a) + { + std::memcpy(&a, reinterpret_cast<const unsigned char*>(&x) + offset_, 4); + } + + static void set_bits(double& x, uint32_t a) + { + std::memcpy(reinterpret_cast<unsigned char*>(&x) + offset_, &a, 4); + } + +private: + +#if BOOST_ENDIAN_BIG_BYTE + BOOST_STATIC_CONSTANT(int, offset_ = 0); +#elif BOOST_ENDIAN_LITTLE_BYTE + BOOST_STATIC_CONSTANT(int, offset_ = 4); +#else + BOOST_STATIC_ASSERT(false); +#endif +}; + +//.............................................................................. + +#else + +template<> struct fp_traits_non_native<double, double_precision> +{ + typedef ieee_copy_all_bits_tag method; + + static const uint64_t sign = ((uint64_t)0x80000000u) << 32; + static const uint64_t exponent = ((uint64_t)0x7ff00000) << 32; + static const uint64_t flag = 0; + static const uint64_t significand + = (((uint64_t)0x000fffff) << 32) + ((uint64_t)0xffffffffu); + + typedef uint64_t bits; + static void get_bits(double x, uint64_t& a) { std::memcpy(&a, &x, 8); } + static void set_bits(double& x, uint64_t a) { std::memcpy(&x, &a, 8); } +}; + +#endif + +#endif // #ifndef BOOST_FPCLASSIFY_VAX_FORMAT + +// long double (64 bits) ------------------------------------------------------- + +#if defined(BOOST_NO_INT64_T) || defined(BOOST_NO_INCLASS_MEMBER_INITIALIZATION)\ + || defined(__BORLANDC__) || defined(__CODEGEAR__) + +template<> struct fp_traits_non_native<long double, double_precision> +{ + typedef ieee_copy_leading_bits_tag method; + + BOOST_STATIC_CONSTANT(uint32_t, sign = 0x80000000u); + BOOST_STATIC_CONSTANT(uint32_t, exponent = 0x7ff00000); + BOOST_STATIC_CONSTANT(uint32_t, flag = 0); + BOOST_STATIC_CONSTANT(uint32_t, significand = 0x000fffff); + + typedef uint32_t bits; + + static void get_bits(long double x, uint32_t& a) + { + std::memcpy(&a, reinterpret_cast<const unsigned char*>(&x) + offset_, 4); + } + + static void set_bits(long double& x, uint32_t a) + { + std::memcpy(reinterpret_cast<unsigned char*>(&x) + offset_, &a, 4); + } + +private: + +#if BOOST_ENDIAN_BIG_BYTE + BOOST_STATIC_CONSTANT(int, offset_ = 0); +#elif BOOST_ENDIAN_LITTLE_BYTE + BOOST_STATIC_CONSTANT(int, offset_ = 4); +#else + BOOST_STATIC_ASSERT(false); +#endif +}; + +//.............................................................................. + +#else + +template<> struct fp_traits_non_native<long double, double_precision> +{ + typedef ieee_copy_all_bits_tag method; + + static const uint64_t sign = (uint64_t)0x80000000u << 32; + static const uint64_t exponent = (uint64_t)0x7ff00000 << 32; + static const uint64_t flag = 0; + static const uint64_t significand + = ((uint64_t)0x000fffff << 32) + (uint64_t)0xffffffffu; + + typedef uint64_t bits; + static void get_bits(long double x, uint64_t& a) { std::memcpy(&a, &x, 8); } + static void set_bits(long double& x, uint64_t a) { std::memcpy(&x, &a, 8); } +}; + +#endif + + +// long double (>64 bits), x86 and x64 ----------------------------------------- + +#if defined(__i386) || defined(__i386__) || defined(_M_IX86) \ + || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) \ + || defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) + +// Intel extended double precision format (80 bits) + +template<> +struct fp_traits_non_native<long double, extended_double_precision> +{ + typedef ieee_copy_leading_bits_tag method; + + BOOST_STATIC_CONSTANT(uint32_t, sign = 0x80000000u); + BOOST_STATIC_CONSTANT(uint32_t, exponent = 0x7fff0000); + BOOST_STATIC_CONSTANT(uint32_t, flag = 0x00008000); + BOOST_STATIC_CONSTANT(uint32_t, significand = 0x00007fff); + + typedef uint32_t bits; + + static void get_bits(long double x, uint32_t& a) + { + std::memcpy(&a, reinterpret_cast<const unsigned char*>(&x) + 6, 4); + } + + static void set_bits(long double& x, uint32_t a) + { + std::memcpy(reinterpret_cast<unsigned char*>(&x) + 6, &a, 4); + } +}; + + +// long double (>64 bits), Itanium --------------------------------------------- + +#elif defined(__ia64) || defined(__ia64__) || defined(_M_IA64) + +// The floating point format is unknown at compile time +// No template specialization is provided. +// The generic_tag definition is used. + +// The Itanium supports both +// the Intel extended double precision format (80 bits) and +// the IEEE extended double precision format with 15 exponent bits (128 bits). + +#elif defined(__GNUC__) && (LDBL_MANT_DIG == 106) + +// +// Define nothing here and fall though to generic_tag: +// We have GCC's "double double" in effect, and any attempt +// to handle it via bit-fiddling is pretty much doomed to fail... +// + +// long double (>64 bits), PowerPC --------------------------------------------- + +#elif defined(__powerpc) || defined(__powerpc__) || defined(__POWERPC__) \ + || defined(__ppc) || defined(__ppc__) || defined(__PPC__) + +// PowerPC extended double precision format (128 bits) + +template<> +struct fp_traits_non_native<long double, extended_double_precision> +{ + typedef ieee_copy_leading_bits_tag method; + + BOOST_STATIC_CONSTANT(uint32_t, sign = 0x80000000u); + BOOST_STATIC_CONSTANT(uint32_t, exponent = 0x7ff00000); + BOOST_STATIC_CONSTANT(uint32_t, flag = 0x00000000); + BOOST_STATIC_CONSTANT(uint32_t, significand = 0x000fffff); + + typedef uint32_t bits; + + static void get_bits(long double x, uint32_t& a) + { + std::memcpy(&a, reinterpret_cast<const unsigned char*>(&x) + offset_, 4); + } + + static void set_bits(long double& x, uint32_t a) + { + std::memcpy(reinterpret_cast<unsigned char*>(&x) + offset_, &a, 4); + } + +private: + +#if BOOST_ENDIAN_BIG_BYTE + BOOST_STATIC_CONSTANT(int, offset_ = 0); +#elif BOOST_ENDIAN_LITTLE_BYTE + BOOST_STATIC_CONSTANT(int, offset_ = 12); +#else + BOOST_STATIC_ASSERT(false); +#endif +}; + + +// long double (>64 bits), Motorola 68K ---------------------------------------- + +#elif defined(__m68k) || defined(__m68k__) \ + || defined(__mc68000) || defined(__mc68000__) \ + +// Motorola extended double precision format (96 bits) + +// It is the same format as the Intel extended double precision format, +// except that 1) it is big-endian, 2) the 3rd and 4th byte are padding, and +// 3) the flag bit is not set for infinity + +template<> +struct fp_traits_non_native<long double, extended_double_precision> +{ + typedef ieee_copy_leading_bits_tag method; + + BOOST_STATIC_CONSTANT(uint32_t, sign = 0x80000000u); + BOOST_STATIC_CONSTANT(uint32_t, exponent = 0x7fff0000); + BOOST_STATIC_CONSTANT(uint32_t, flag = 0x00008000); + BOOST_STATIC_CONSTANT(uint32_t, significand = 0x00007fff); + + // copy 1st, 2nd, 5th and 6th byte. 3rd and 4th byte are padding. + + typedef uint32_t bits; + + static void get_bits(long double x, uint32_t& a) + { + std::memcpy(&a, &x, 2); + std::memcpy(reinterpret_cast<unsigned char*>(&a) + 2, + reinterpret_cast<const unsigned char*>(&x) + 4, 2); + } + + static void set_bits(long double& x, uint32_t a) + { + std::memcpy(&x, &a, 2); + std::memcpy(reinterpret_cast<unsigned char*>(&x) + 4, + reinterpret_cast<const unsigned char*>(&a) + 2, 2); + } +}; + + +// long double (>64 bits), All other processors -------------------------------- + +#else + +// IEEE extended double precision format with 15 exponent bits (128 bits) + +template<> +struct fp_traits_non_native<long double, extended_double_precision> +{ + typedef ieee_copy_leading_bits_tag method; + + BOOST_STATIC_CONSTANT(uint32_t, sign = 0x80000000u); + BOOST_STATIC_CONSTANT(uint32_t, exponent = 0x7fff0000); + BOOST_STATIC_CONSTANT(uint32_t, flag = 0x00000000); + BOOST_STATIC_CONSTANT(uint32_t, significand = 0x0000ffff); + + typedef uint32_t bits; + + static void get_bits(long double x, uint32_t& a) + { + std::memcpy(&a, reinterpret_cast<const unsigned char*>(&x) + offset_, 4); + } + + static void set_bits(long double& x, uint32_t a) + { + std::memcpy(reinterpret_cast<unsigned char*>(&x) + offset_, &a, 4); + } + +private: + +#if BOOST_ENDIAN_BIG_BYTE + BOOST_STATIC_CONSTANT(int, offset_ = 0); +#elif BOOST_ENDIAN_LITTLE_BYTE + BOOST_STATIC_CONSTANT(int, offset_ = 12); +#else + BOOST_STATIC_ASSERT(false); +#endif +}; + +#endif + +//------------------------------------------------------------------------------ + +// size_to_precision is a type switch for converting a C++ floating point type +// to the corresponding precision type. + +template<int n, bool fp> struct size_to_precision +{ + typedef unknown_precision type; +}; + +template<> struct size_to_precision<4, true> +{ + typedef single_precision type; +}; + +template<> struct size_to_precision<8, true> +{ + typedef double_precision type; +}; + +template<> struct size_to_precision<10, true> +{ + typedef extended_double_precision type; +}; + +template<> struct size_to_precision<12, true> +{ + typedef extended_double_precision type; +}; + +template<> struct size_to_precision<16, true> +{ + typedef extended_double_precision type; +}; + +//------------------------------------------------------------------------------ +// +// Figure out whether to use native classification functions based on +// whether T is a built in floating point type or not: +// +template <class T> +struct select_native +{ + typedef BOOST_DEDUCED_TYPENAME size_to_precision<sizeof(T), ::boost::is_floating_point<T>::value>::type precision; + typedef fp_traits_non_native<T, precision> type; +}; +template<> +struct select_native<float> +{ + typedef fp_traits_native<float> type; +}; +template<> +struct select_native<double> +{ + typedef fp_traits_native<double> type; +}; +template<> +struct select_native<long double> +{ + typedef fp_traits_native<long double> type; +}; + +//------------------------------------------------------------------------------ + +// fp_traits is a type switch that selects the right fp_traits_non_native + +#if (defined(BOOST_MATH_USE_C99) && !(defined(__GNUC__) && (__GNUC__ < 4))) \ + && !defined(__hpux) \ + && !defined(__DECCXX)\ + && !defined(__osf__) \ + && !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION)\ + && !defined(__FAST_MATH__)\ + && !defined(BOOST_MATH_DISABLE_STD_FPCLASSIFY)\ + && !defined(BOOST_INTEL)\ + && !defined(sun)\ + && !defined(__VXWORKS__) +# define BOOST_MATH_USE_STD_FPCLASSIFY +#endif + +template<class T> struct fp_traits +{ + typedef BOOST_DEDUCED_TYPENAME size_to_precision<sizeof(T), ::boost::is_floating_point<T>::value>::type precision; +#if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && !defined(BOOST_MATH_DISABLE_STD_FPCLASSIFY) + typedef typename select_native<T>::type type; +#else + typedef fp_traits_non_native<T, precision> type; +#endif + typedef fp_traits_non_native<T, precision> sign_change_type; +}; + +//------------------------------------------------------------------------------ + +} // namespace detail +} // namespace math +} // namespace boost + +#endif diff --git a/src/third_party/boost-1.70.0/boost/math/special_functions/detail/gamma_inva.hpp b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/gamma_inva.hpp new file mode 100644 index 00000000000..7c32d2946c0 --- /dev/null +++ b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/gamma_inva.hpp @@ -0,0 +1,233 @@ +// (C) Copyright John Maddock 2006. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// +// This is not a complete header file, it is included by gamma.hpp +// after it has defined it's definitions. This inverts the incomplete +// gamma functions P and Q on the first parameter "a" using a generic +// root finding algorithm (TOMS Algorithm 748). +// + +#ifndef BOOST_MATH_SP_DETAIL_GAMMA_INVA +#define BOOST_MATH_SP_DETAIL_GAMMA_INVA + +#ifdef _MSC_VER +#pragma once +#endif + +#include <boost/math/tools/toms748_solve.hpp> +#include <boost/cstdint.hpp> + +namespace boost{ namespace math{ namespace detail{ + +template <class T, class Policy> +struct gamma_inva_t +{ + gamma_inva_t(T z_, T p_, bool invert_) : z(z_), p(p_), invert(invert_) {} + T operator()(T a) + { + return invert ? p - boost::math::gamma_q(a, z, Policy()) : boost::math::gamma_p(a, z, Policy()) - p; + } +private: + T z, p; + bool invert; +}; + +template <class T, class Policy> +T inverse_poisson_cornish_fisher(T lambda, T p, T q, const Policy& pol) +{ + BOOST_MATH_STD_USING + // mean: + T m = lambda; + // standard deviation: + T sigma = sqrt(lambda); + // skewness + T sk = 1 / sigma; + // kurtosis: + // T k = 1/lambda; + // Get the inverse of a std normal distribution: + T x = boost::math::erfc_inv(p > q ? 2 * q : 2 * p, pol) * constants::root_two<T>(); + // Set the sign: + if(p < 0.5) + x = -x; + T x2 = x * x; + // w is correction term due to skewness + T w = x + sk * (x2 - 1) / 6; + /* + // Add on correction due to kurtosis. + // Disabled for now, seems to make things worse? + // + if(lambda >= 10) + w += k * x * (x2 - 3) / 24 + sk * sk * x * (2 * x2 - 5) / -36; + */ + w = m + sigma * w; + return w > tools::min_value<T>() ? w : tools::min_value<T>(); +} + +template <class T, class Policy> +T gamma_inva_imp(const T& z, const T& p, const T& q, const Policy& pol) +{ + BOOST_MATH_STD_USING // for ADL of std lib math functions + // + // Special cases first: + // + if(p == 0) + { + return policies::raise_overflow_error<T>("boost::math::gamma_p_inva<%1%>(%1%, %1%)", 0, Policy()); + } + if(q == 0) + { + return tools::min_value<T>(); + } + // + // Function object, this is the functor whose root + // we have to solve: + // + gamma_inva_t<T, Policy> f(z, (p < q) ? p : q, (p < q) ? false : true); + // + // Tolerance: full precision. + // + tools::eps_tolerance<T> tol(policies::digits<T, Policy>()); + // + // Now figure out a starting guess for what a may be, + // we'll start out with a value that'll put p or q + // right bang in the middle of their range, the functions + // are quite sensitive so we should need too many steps + // to bracket the root from there: + // + T guess; + T factor = 8; + if(z >= 1) + { + // + // We can use the relationship between the incomplete + // gamma function and the poisson distribution to + // calculate an approximate inverse, for large z + // this is actually pretty accurate, but it fails badly + // when z is very small. Also set our step-factor according + // to how accurate we think the result is likely to be: + // + guess = 1 + inverse_poisson_cornish_fisher(z, q, p, pol); + if(z > 5) + { + if(z > 1000) + factor = 1.01f; + else if(z > 50) + factor = 1.1f; + else if(guess > 10) + factor = 1.25f; + else + factor = 2; + if(guess < 1.1) + factor = 8; + } + } + else if(z > 0.5) + { + guess = z * 1.2f; + } + else + { + guess = -0.4f / log(z); + } + // + // Max iterations permitted: + // + boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>(); + // + // Use our generic derivative-free root finding procedure. + // We could use Newton steps here, taking the PDF of the + // Poisson distribution as our derivative, but that's + // even worse performance-wise than the generic method :-( + // + std::pair<T, T> r = bracket_and_solve_root(f, guess, factor, false, tol, max_iter, pol); + if(max_iter >= policies::get_max_root_iterations<Policy>()) + return policies::raise_evaluation_error<T>("boost::math::gamma_p_inva<%1%>(%1%, %1%)", "Unable to locate the root within a reasonable number of iterations, closest approximation so far was %1%", r.first, pol); + return (r.first + r.second) / 2; +} + +} // namespace detail + +template <class T1, class T2, class Policy> +inline typename tools::promote_args<T1, T2>::type + gamma_p_inva(T1 x, T2 p, const Policy& pol) +{ + typedef typename tools::promote_args<T1, T2>::type result_type; + typedef typename policies::evaluation<result_type, Policy>::type value_type; + typedef typename policies::normalise< + Policy, + policies::promote_float<false>, + policies::promote_double<false>, + policies::discrete_quantile<>, + policies::assert_undefined<> >::type forwarding_policy; + + if(p == 0) + { + policies::raise_overflow_error<result_type>("boost::math::gamma_p_inva<%1%>(%1%, %1%)", 0, Policy()); + } + if(p == 1) + { + return tools::min_value<result_type>(); + } + + return policies::checked_narrowing_cast<result_type, forwarding_policy>( + detail::gamma_inva_imp( + static_cast<value_type>(x), + static_cast<value_type>(p), + static_cast<value_type>(1 - static_cast<value_type>(p)), + pol), "boost::math::gamma_p_inva<%1%>(%1%, %1%)"); +} + +template <class T1, class T2, class Policy> +inline typename tools::promote_args<T1, T2>::type + gamma_q_inva(T1 x, T2 q, const Policy& pol) +{ + typedef typename tools::promote_args<T1, T2>::type result_type; + typedef typename policies::evaluation<result_type, Policy>::type value_type; + typedef typename policies::normalise< + Policy, + policies::promote_float<false>, + policies::promote_double<false>, + policies::discrete_quantile<>, + policies::assert_undefined<> >::type forwarding_policy; + + if(q == 1) + { + policies::raise_overflow_error<result_type>("boost::math::gamma_q_inva<%1%>(%1%, %1%)", 0, Policy()); + } + if(q == 0) + { + return tools::min_value<result_type>(); + } + + return policies::checked_narrowing_cast<result_type, forwarding_policy>( + detail::gamma_inva_imp( + static_cast<value_type>(x), + static_cast<value_type>(1 - static_cast<value_type>(q)), + static_cast<value_type>(q), + pol), "boost::math::gamma_q_inva<%1%>(%1%, %1%)"); +} + +template <class T1, class T2> +inline typename tools::promote_args<T1, T2>::type + gamma_p_inva(T1 x, T2 p) +{ + return boost::math::gamma_p_inva(x, p, policies::policy<>()); +} + +template <class T1, class T2> +inline typename tools::promote_args<T1, T2>::type + gamma_q_inva(T1 x, T2 q) +{ + return boost::math::gamma_q_inva(x, q, policies::policy<>()); +} + +} // namespace math +} // namespace boost + +#endif // BOOST_MATH_SP_DETAIL_GAMMA_INVA + + + diff --git a/src/third_party/boost-1.70.0/boost/math/special_functions/detail/ibeta_inv_ab.hpp b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/ibeta_inv_ab.hpp new file mode 100644 index 00000000000..f5735a84956 --- /dev/null +++ b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/ibeta_inv_ab.hpp @@ -0,0 +1,328 @@ +// (C) Copyright John Maddock 2006. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// +// This is not a complete header file, it is included by beta.hpp +// after it has defined it's definitions. This inverts the incomplete +// beta functions ibeta and ibetac on the first parameters "a" +// and "b" using a generic root finding algorithm (TOMS Algorithm 748). +// + +#ifndef BOOST_MATH_SP_DETAIL_BETA_INV_AB +#define BOOST_MATH_SP_DETAIL_BETA_INV_AB + +#ifdef _MSC_VER +#pragma once +#endif + +#include <boost/math/tools/toms748_solve.hpp> +#include <boost/cstdint.hpp> + +namespace boost{ namespace math{ namespace detail{ + +template <class T, class Policy> +struct beta_inv_ab_t +{ + beta_inv_ab_t(T b_, T z_, T p_, bool invert_, bool swap_ab_) : b(b_), z(z_), p(p_), invert(invert_), swap_ab(swap_ab_) {} + T operator()(T a) + { + return invert ? + p - boost::math::ibetac(swap_ab ? b : a, swap_ab ? a : b, z, Policy()) + : boost::math::ibeta(swap_ab ? b : a, swap_ab ? a : b, z, Policy()) - p; + } +private: + T b, z, p; + bool invert, swap_ab; +}; + +template <class T, class Policy> +T inverse_negative_binomial_cornish_fisher(T n, T sf, T sfc, T p, T q, const Policy& pol) +{ + BOOST_MATH_STD_USING + // mean: + T m = n * (sfc) / sf; + T t = sqrt(n * (sfc)); + // standard deviation: + T sigma = t / sf; + // skewness + T sk = (1 + sfc) / t; + // kurtosis: + T k = (6 - sf * (5+sfc)) / (n * (sfc)); + // Get the inverse of a std normal distribution: + T x = boost::math::erfc_inv(p > q ? 2 * q : 2 * p, pol) * constants::root_two<T>(); + // Set the sign: + if(p < 0.5) + x = -x; + T x2 = x * x; + // w is correction term due to skewness + T w = x + sk * (x2 - 1) / 6; + // + // Add on correction due to kurtosis. + // + if(n >= 10) + w += k * x * (x2 - 3) / 24 + sk * sk * x * (2 * x2 - 5) / -36; + + w = m + sigma * w; + if(w < tools::min_value<T>()) + return tools::min_value<T>(); + return w; +} + +template <class T, class Policy> +T ibeta_inv_ab_imp(const T& b, const T& z, const T& p, const T& q, bool swap_ab, const Policy& pol) +{ + BOOST_MATH_STD_USING // for ADL of std lib math functions + // + // Special cases first: + // + BOOST_MATH_INSTRUMENT_CODE("b = " << b << " z = " << z << " p = " << p << " q = " << " swap = " << swap_ab); + if(p == 0) + { + return swap_ab ? tools::min_value<T>() : tools::max_value<T>(); + } + if(q == 0) + { + return swap_ab ? tools::max_value<T>() : tools::min_value<T>(); + } + // + // Function object, this is the functor whose root + // we have to solve: + // + beta_inv_ab_t<T, Policy> f(b, z, (p < q) ? p : q, (p < q) ? false : true, swap_ab); + // + // Tolerance: full precision. + // + tools::eps_tolerance<T> tol(policies::digits<T, Policy>()); + // + // Now figure out a starting guess for what a may be, + // we'll start out with a value that'll put p or q + // right bang in the middle of their range, the functions + // are quite sensitive so we should need too many steps + // to bracket the root from there: + // + T guess = 0; + T factor = 5; + // + // Convert variables to parameters of a negative binomial distribution: + // + T n = b; + T sf = swap_ab ? z : 1-z; + T sfc = swap_ab ? 1-z : z; + T u = swap_ab ? p : q; + T v = swap_ab ? q : p; + if(u <= pow(sf, n)) + { + // + // Result is less than 1, negative binomial approximation + // is useless.... + // + if((p < q) != swap_ab) + { + guess = (std::min)(T(b * 2), T(1)); + } + else + { + guess = (std::min)(T(b / 2), T(1)); + } + } + if(n * n * n * u * sf > 0.005) + guess = 1 + inverse_negative_binomial_cornish_fisher(n, sf, sfc, u, v, pol); + + if(guess < 10) + { + // + // Negative binomial approximation not accurate in this area: + // + if((p < q) != swap_ab) + { + guess = (std::min)(T(b * 2), T(10)); + } + else + { + guess = (std::min)(T(b / 2), T(10)); + } + } + else + factor = (v < sqrt(tools::epsilon<T>())) ? 2 : (guess < 20 ? 1.2f : 1.1f); + BOOST_MATH_INSTRUMENT_CODE("guess = " << guess); + // + // Max iterations permitted: + // + boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>(); + std::pair<T, T> r = bracket_and_solve_root(f, guess, factor, swap_ab ? true : false, tol, max_iter, pol); + if(max_iter >= policies::get_max_root_iterations<Policy>()) + return policies::raise_evaluation_error<T>("boost::math::ibeta_invab_imp<%1%>(%1%,%1%,%1%)", "Unable to locate the root within a reasonable number of iterations, closest approximation so far was %1%", r.first, pol); + return (r.first + r.second) / 2; +} + +} // namespace detail + +template <class RT1, class RT2, class RT3, class Policy> +typename tools::promote_args<RT1, RT2, RT3>::type + ibeta_inva(RT1 b, RT2 x, RT3 p, const Policy& pol) +{ + typedef typename tools::promote_args<RT1, RT2, RT3>::type result_type; + typedef typename policies::evaluation<result_type, Policy>::type value_type; + typedef typename policies::normalise< + Policy, + policies::promote_float<false>, + policies::promote_double<false>, + policies::discrete_quantile<>, + policies::assert_undefined<> >::type forwarding_policy; + + static const char* function = "boost::math::ibeta_inva<%1%>(%1%,%1%,%1%)"; + if(p == 0) + { + return policies::raise_overflow_error<result_type>(function, 0, Policy()); + } + if(p == 1) + { + return tools::min_value<result_type>(); + } + + return policies::checked_narrowing_cast<result_type, forwarding_policy>( + detail::ibeta_inv_ab_imp( + static_cast<value_type>(b), + static_cast<value_type>(x), + static_cast<value_type>(p), + static_cast<value_type>(1 - static_cast<value_type>(p)), + false, pol), + function); +} + +template <class RT1, class RT2, class RT3, class Policy> +typename tools::promote_args<RT1, RT2, RT3>::type + ibetac_inva(RT1 b, RT2 x, RT3 q, const Policy& pol) +{ + typedef typename tools::promote_args<RT1, RT2, RT3>::type result_type; + typedef typename policies::evaluation<result_type, Policy>::type value_type; + typedef typename policies::normalise< + Policy, + policies::promote_float<false>, + policies::promote_double<false>, + policies::discrete_quantile<>, + policies::assert_undefined<> >::type forwarding_policy; + + static const char* function = "boost::math::ibetac_inva<%1%>(%1%,%1%,%1%)"; + if(q == 1) + { + return policies::raise_overflow_error<result_type>(function, 0, Policy()); + } + if(q == 0) + { + return tools::min_value<result_type>(); + } + + return policies::checked_narrowing_cast<result_type, forwarding_policy>( + detail::ibeta_inv_ab_imp( + static_cast<value_type>(b), + static_cast<value_type>(x), + static_cast<value_type>(1 - static_cast<value_type>(q)), + static_cast<value_type>(q), + false, pol), + function); +} + +template <class RT1, class RT2, class RT3, class Policy> +typename tools::promote_args<RT1, RT2, RT3>::type + ibeta_invb(RT1 a, RT2 x, RT3 p, const Policy& pol) +{ + typedef typename tools::promote_args<RT1, RT2, RT3>::type result_type; + typedef typename policies::evaluation<result_type, Policy>::type value_type; + typedef typename policies::normalise< + Policy, + policies::promote_float<false>, + policies::promote_double<false>, + policies::discrete_quantile<>, + policies::assert_undefined<> >::type forwarding_policy; + + static const char* function = "boost::math::ibeta_invb<%1%>(%1%,%1%,%1%)"; + if(p == 0) + { + return tools::min_value<result_type>(); + } + if(p == 1) + { + return policies::raise_overflow_error<result_type>(function, 0, Policy()); + } + + return policies::checked_narrowing_cast<result_type, forwarding_policy>( + detail::ibeta_inv_ab_imp( + static_cast<value_type>(a), + static_cast<value_type>(x), + static_cast<value_type>(p), + static_cast<value_type>(1 - static_cast<value_type>(p)), + true, pol), + function); +} + +template <class RT1, class RT2, class RT3, class Policy> +typename tools::promote_args<RT1, RT2, RT3>::type + ibetac_invb(RT1 a, RT2 x, RT3 q, const Policy& pol) +{ + static const char* function = "boost::math::ibeta_invb<%1%>(%1%, %1%, %1%)"; + typedef typename tools::promote_args<RT1, RT2, RT3>::type result_type; + typedef typename policies::evaluation<result_type, Policy>::type value_type; + typedef typename policies::normalise< + Policy, + policies::promote_float<false>, + policies::promote_double<false>, + policies::discrete_quantile<>, + policies::assert_undefined<> >::type forwarding_policy; + + if(q == 1) + { + return tools::min_value<result_type>(); + } + if(q == 0) + { + return policies::raise_overflow_error<result_type>(function, 0, Policy()); + } + + return policies::checked_narrowing_cast<result_type, forwarding_policy>( + detail::ibeta_inv_ab_imp( + static_cast<value_type>(a), + static_cast<value_type>(x), + static_cast<value_type>(1 - static_cast<value_type>(q)), + static_cast<value_type>(q), + true, pol), + function); +} + +template <class RT1, class RT2, class RT3> +inline typename tools::promote_args<RT1, RT2, RT3>::type + ibeta_inva(RT1 b, RT2 x, RT3 p) +{ + return boost::math::ibeta_inva(b, x, p, policies::policy<>()); +} + +template <class RT1, class RT2, class RT3> +inline typename tools::promote_args<RT1, RT2, RT3>::type + ibetac_inva(RT1 b, RT2 x, RT3 q) +{ + return boost::math::ibetac_inva(b, x, q, policies::policy<>()); +} + +template <class RT1, class RT2, class RT3> +inline typename tools::promote_args<RT1, RT2, RT3>::type + ibeta_invb(RT1 a, RT2 x, RT3 p) +{ + return boost::math::ibeta_invb(a, x, p, policies::policy<>()); +} + +template <class RT1, class RT2, class RT3> +inline typename tools::promote_args<RT1, RT2, RT3>::type + ibetac_invb(RT1 a, RT2 x, RT3 q) +{ + return boost::math::ibetac_invb(a, x, q, policies::policy<>()); +} + +} // namespace math +} // namespace boost + +#endif // BOOST_MATH_SP_DETAIL_BETA_INV_AB + + + diff --git a/src/third_party/boost-1.70.0/boost/math/special_functions/detail/ibeta_inverse.hpp b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/ibeta_inverse.hpp new file mode 100644 index 00000000000..a9fe8cd49cb --- /dev/null +++ b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/ibeta_inverse.hpp @@ -0,0 +1,993 @@ +// Copyright John Maddock 2006. +// Copyright Paul A. Bristow 2007 +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_SPECIAL_FUNCTIONS_IBETA_INVERSE_HPP +#define BOOST_MATH_SPECIAL_FUNCTIONS_IBETA_INVERSE_HPP + +#ifdef _MSC_VER +#pragma once +#endif + +#include <boost/math/special_functions/beta.hpp> +#include <boost/math/special_functions/erf.hpp> +#include <boost/math/tools/roots.hpp> +#include <boost/math/special_functions/detail/t_distribution_inv.hpp> + +namespace boost{ namespace math{ namespace detail{ + +// +// Helper object used by root finding +// code to convert eta to x. +// +template <class T> +struct temme_root_finder +{ + temme_root_finder(const T t_, const T a_) : t(t_), a(a_) {} + + boost::math::tuple<T, T> operator()(T x) + { + BOOST_MATH_STD_USING // ADL of std names + + T y = 1 - x; + if(y == 0) + { + T big = tools::max_value<T>() / 4; + return boost::math::make_tuple(static_cast<T>(-big), static_cast<T>(-big)); + } + if(x == 0) + { + T big = tools::max_value<T>() / 4; + return boost::math::make_tuple(static_cast<T>(-big), big); + } + T f = log(x) + a * log(y) + t; + T f1 = (1 / x) - (a / (y)); + return boost::math::make_tuple(f, f1); + } +private: + T t, a; +}; +// +// See: +// "Asymptotic Inversion of the Incomplete Beta Function" +// N.M. Temme +// Journal of Computation and Applied Mathematics 41 (1992) 145-157. +// Section 2. +// +template <class T, class Policy> +T temme_method_1_ibeta_inverse(T a, T b, T z, const Policy& pol) +{ + BOOST_MATH_STD_USING // ADL of std names + + const T r2 = sqrt(T(2)); + // + // get the first approximation for eta from the inverse + // error function (Eq: 2.9 and 2.10). + // + T eta0 = boost::math::erfc_inv(2 * z, pol); + eta0 /= -sqrt(a / 2); + + T terms[4] = { eta0 }; + T workspace[7]; + // + // calculate powers: + // + T B = b - a; + T B_2 = B * B; + T B_3 = B_2 * B; + // + // Calculate correction terms: + // + + // See eq following 2.15: + workspace[0] = -B * r2 / 2; + workspace[1] = (1 - 2 * B) / 8; + workspace[2] = -(B * r2 / 48); + workspace[3] = T(-1) / 192; + workspace[4] = -B * r2 / 3840; + terms[1] = tools::evaluate_polynomial(workspace, eta0, 5); + // Eq Following 2.17: + workspace[0] = B * r2 * (3 * B - 2) / 12; + workspace[1] = (20 * B_2 - 12 * B + 1) / 128; + workspace[2] = B * r2 * (20 * B - 1) / 960; + workspace[3] = (16 * B_2 + 30 * B - 15) / 4608; + workspace[4] = B * r2 * (21 * B + 32) / 53760; + workspace[5] = (-32 * B_2 + 63) / 368640; + workspace[6] = -B * r2 * (120 * B + 17) / 25804480; + terms[2] = tools::evaluate_polynomial(workspace, eta0, 7); + // Eq Following 2.17: + workspace[0] = B * r2 * (-75 * B_2 + 80 * B - 16) / 480; + workspace[1] = (-1080 * B_3 + 868 * B_2 - 90 * B - 45) / 9216; + workspace[2] = B * r2 * (-1190 * B_2 + 84 * B + 373) / 53760; + workspace[3] = (-2240 * B_3 - 2508 * B_2 + 2100 * B - 165) / 368640; + terms[3] = tools::evaluate_polynomial(workspace, eta0, 4); + // + // Bring them together to get a final estimate for eta: + // + T eta = tools::evaluate_polynomial(terms, T(1/a), 4); + // + // now we need to convert eta to x, by solving the appropriate + // quadratic equation: + // + T eta_2 = eta * eta; + T c = -exp(-eta_2 / 2); + T x; + if(eta_2 == 0) + x = 0.5; + else + x = (1 + eta * sqrt((1 + c) / eta_2)) / 2; + + BOOST_ASSERT(x >= 0); + BOOST_ASSERT(x <= 1); + BOOST_ASSERT(eta * (x - 0.5) >= 0); +#ifdef BOOST_INSTRUMENT + std::cout << "Estimating x with Temme method 1: " << x << std::endl; +#endif + return x; +} +// +// See: +// "Asymptotic Inversion of the Incomplete Beta Function" +// N.M. Temme +// Journal of Computation and Applied Mathematics 41 (1992) 145-157. +// Section 3. +// +template <class T, class Policy> +T temme_method_2_ibeta_inverse(T /*a*/, T /*b*/, T z, T r, T theta, const Policy& pol) +{ + BOOST_MATH_STD_USING // ADL of std names + + // + // Get first estimate for eta, see Eq 3.9 and 3.10, + // but note there is a typo in Eq 3.10: + // + T eta0 = boost::math::erfc_inv(2 * z, pol); + eta0 /= -sqrt(r / 2); + + T s = sin(theta); + T c = cos(theta); + // + // Now we need to purturb eta0 to get eta, which we do by + // evaluating the polynomial in 1/r at the bottom of page 151, + // to do this we first need the error terms e1, e2 e3 + // which we'll fill into the array "terms". Since these + // terms are themselves polynomials, we'll need another + // array "workspace" to calculate those... + // + T terms[4] = { eta0 }; + T workspace[6]; + // + // some powers of sin(theta)cos(theta) that we'll need later: + // + T sc = s * c; + T sc_2 = sc * sc; + T sc_3 = sc_2 * sc; + T sc_4 = sc_2 * sc_2; + T sc_5 = sc_2 * sc_3; + T sc_6 = sc_3 * sc_3; + T sc_7 = sc_4 * sc_3; + // + // Calculate e1 and put it in terms[1], see the middle of page 151: + // + workspace[0] = (2 * s * s - 1) / (3 * s * c); + static const BOOST_MATH_INT_TABLE_TYPE(T, int) co1[] = { -1, -5, 5 }; + workspace[1] = -tools::evaluate_even_polynomial(co1, s, 3) / (36 * sc_2); + static const BOOST_MATH_INT_TABLE_TYPE(T, int) co2[] = { 1, 21, -69, 46 }; + workspace[2] = tools::evaluate_even_polynomial(co2, s, 4) / (1620 * sc_3); + static const BOOST_MATH_INT_TABLE_TYPE(T, int) co3[] = { 7, -2, 33, -62, 31 }; + workspace[3] = -tools::evaluate_even_polynomial(co3, s, 5) / (6480 * sc_4); + static const BOOST_MATH_INT_TABLE_TYPE(T, int) co4[] = { 25, -52, -17, 88, -115, 46 }; + workspace[4] = tools::evaluate_even_polynomial(co4, s, 6) / (90720 * sc_5); + terms[1] = tools::evaluate_polynomial(workspace, eta0, 5); + // + // Now evaluate e2 and put it in terms[2]: + // + static const BOOST_MATH_INT_TABLE_TYPE(T, int) co5[] = { 7, 12, -78, 52 }; + workspace[0] = -tools::evaluate_even_polynomial(co5, s, 4) / (405 * sc_3); + static const BOOST_MATH_INT_TABLE_TYPE(T, int) co6[] = { -7, 2, 183, -370, 185 }; + workspace[1] = tools::evaluate_even_polynomial(co6, s, 5) / (2592 * sc_4); + static const BOOST_MATH_INT_TABLE_TYPE(T, int) co7[] = { -533, 776, -1835, 10240, -13525, 5410 }; + workspace[2] = -tools::evaluate_even_polynomial(co7, s, 6) / (204120 * sc_5); + static const BOOST_MATH_INT_TABLE_TYPE(T, int) co8[] = { -1579, 3747, -3372, -15821, 45588, -45213, 15071 }; + workspace[3] = -tools::evaluate_even_polynomial(co8, s, 7) / (2099520 * sc_6); + terms[2] = tools::evaluate_polynomial(workspace, eta0, 4); + // + // And e3, and put it in terms[3]: + // + static const BOOST_MATH_INT_TABLE_TYPE(T, int) co9[] = {449, -1259, -769, 6686, -9260, 3704 }; + workspace[0] = tools::evaluate_even_polynomial(co9, s, 6) / (102060 * sc_5); + static const BOOST_MATH_INT_TABLE_TYPE(T, int) co10[] = { 63149, -151557, 140052, -727469, 2239932, -2251437, 750479 }; + workspace[1] = -tools::evaluate_even_polynomial(co10, s, 7) / (20995200 * sc_6); + static const BOOST_MATH_INT_TABLE_TYPE(T, int) co11[] = { 29233, -78755, 105222, 146879, -1602610, 3195183, -2554139, 729754 }; + workspace[2] = tools::evaluate_even_polynomial(co11, s, 8) / (36741600 * sc_7); + terms[3] = tools::evaluate_polynomial(workspace, eta0, 3); + // + // Bring the correction terms together to evaluate eta, + // this is the last equation on page 151: + // + T eta = tools::evaluate_polynomial(terms, T(1/r), 4); + // + // Now that we have eta we need to back solve for x, + // we seek the value of x that gives eta in Eq 3.2. + // The two methods used are described in section 5. + // + // Begin by defining a few variables we'll need later: + // + T x; + T s_2 = s * s; + T c_2 = c * c; + T alpha = c / s; + alpha *= alpha; + T lu = (-(eta * eta) / (2 * s_2) + log(s_2) + c_2 * log(c_2) / s_2); + // + // Temme doesn't specify what value to switch on here, + // but this seems to work pretty well: + // + if(fabs(eta) < 0.7) + { + // + // Small eta use the expansion Temme gives in the second equation + // of section 5, it's a polynomial in eta: + // + workspace[0] = s * s; + workspace[1] = s * c; + workspace[2] = (1 - 2 * workspace[0]) / 3; + static const BOOST_MATH_INT_TABLE_TYPE(T, int) co12[] = { 1, -13, 13 }; + workspace[3] = tools::evaluate_polynomial(co12, workspace[0], 3) / (36 * s * c); + static const BOOST_MATH_INT_TABLE_TYPE(T, int) co13[] = { 1, 21, -69, 46 }; + workspace[4] = tools::evaluate_polynomial(co13, workspace[0], 4) / (270 * workspace[0] * c * c); + x = tools::evaluate_polynomial(workspace, eta, 5); +#ifdef BOOST_INSTRUMENT + std::cout << "Estimating x with Temme method 2 (small eta): " << x << std::endl; +#endif + } + else + { + // + // If eta is large we need to solve Eq 3.2 more directly, + // begin by getting an initial approximation for x from + // the last equation on page 155, this is a polynomial in u: + // + T u = exp(lu); + workspace[0] = u; + workspace[1] = alpha; + workspace[2] = 0; + workspace[3] = 3 * alpha * (3 * alpha + 1) / 6; + workspace[4] = 4 * alpha * (4 * alpha + 1) * (4 * alpha + 2) / 24; + workspace[5] = 5 * alpha * (5 * alpha + 1) * (5 * alpha + 2) * (5 * alpha + 3) / 120; + x = tools::evaluate_polynomial(workspace, u, 6); + // + // At this point we may or may not have the right answer, Eq-3.2 has + // two solutions for x for any given eta, however the mapping in 3.2 + // is 1:1 with the sign of eta and x-sin^2(theta) being the same. + // So we can check if we have the right root of 3.2, and if not + // switch x for 1-x. This transformation is motivated by the fact + // that the distribution is *almost* symetric so 1-x will be in the right + // ball park for the solution: + // + if((x - s_2) * eta < 0) + x = 1 - x; +#ifdef BOOST_INSTRUMENT + std::cout << "Estimating x with Temme method 2 (large eta): " << x << std::endl; +#endif + } + // + // The final step is a few Newton-Raphson iterations to + // clean up our approximation for x, this is pretty cheap + // in general, and very cheap compared to an incomplete beta + // evaluation. The limits set on x come from the observation + // that the sign of eta and x-sin^2(theta) are the same. + // + T lower, upper; + if(eta < 0) + { + lower = 0; + upper = s_2; + } + else + { + lower = s_2; + upper = 1; + } + // + // If our initial approximation is out of bounds then bisect: + // + if((x < lower) || (x > upper)) + x = (lower+upper) / 2; + // + // And iterate: + // + x = tools::newton_raphson_iterate( + temme_root_finder<T>(-lu, alpha), x, lower, upper, policies::digits<T, Policy>() / 2); + + return x; +} +// +// See: +// "Asymptotic Inversion of the Incomplete Beta Function" +// N.M. Temme +// Journal of Computation and Applied Mathematics 41 (1992) 145-157. +// Section 4. +// +template <class T, class Policy> +T temme_method_3_ibeta_inverse(T a, T b, T p, T q, const Policy& pol) +{ + BOOST_MATH_STD_USING // ADL of std names + + // + // Begin by getting an initial approximation for the quantity + // eta from the dominant part of the incomplete beta: + // + T eta0; + if(p < q) + eta0 = boost::math::gamma_q_inv(b, p, pol); + else + eta0 = boost::math::gamma_p_inv(b, q, pol); + eta0 /= a; + // + // Define the variables and powers we'll need later on: + // + T mu = b / a; + T w = sqrt(1 + mu); + T w_2 = w * w; + T w_3 = w_2 * w; + T w_4 = w_2 * w_2; + T w_5 = w_3 * w_2; + T w_6 = w_3 * w_3; + T w_7 = w_4 * w_3; + T w_8 = w_4 * w_4; + T w_9 = w_5 * w_4; + T w_10 = w_5 * w_5; + T d = eta0 - mu; + T d_2 = d * d; + T d_3 = d_2 * d; + T d_4 = d_2 * d_2; + T w1 = w + 1; + T w1_2 = w1 * w1; + T w1_3 = w1 * w1_2; + T w1_4 = w1_2 * w1_2; + // + // Now we need to compute the purturbation error terms that + // convert eta0 to eta, these are all polynomials of polynomials. + // Probably these should be re-written to use tabulated data + // (see examples above), but it's less of a win in this case as we + // need to calculate the individual powers for the denominator terms + // anyway, so we might as well use them for the numerator-polynomials + // as well.... + // + // Refer to p154-p155 for the details of these expansions: + // + T e1 = (w + 2) * (w - 1) / (3 * w); + e1 += (w_3 + 9 * w_2 + 21 * w + 5) * d / (36 * w_2 * w1); + e1 -= (w_4 - 13 * w_3 + 69 * w_2 + 167 * w + 46) * d_2 / (1620 * w1_2 * w_3); + e1 -= (7 * w_5 + 21 * w_4 + 70 * w_3 + 26 * w_2 - 93 * w - 31) * d_3 / (6480 * w1_3 * w_4); + e1 -= (75 * w_6 + 202 * w_5 + 188 * w_4 - 888 * w_3 - 1345 * w_2 + 118 * w + 138) * d_4 / (272160 * w1_4 * w_5); + + T e2 = (28 * w_4 + 131 * w_3 + 402 * w_2 + 581 * w + 208) * (w - 1) / (1620 * w1 * w_3); + e2 -= (35 * w_6 - 154 * w_5 - 623 * w_4 - 1636 * w_3 - 3983 * w_2 - 3514 * w - 925) * d / (12960 * w1_2 * w_4); + e2 -= (2132 * w_7 + 7915 * w_6 + 16821 * w_5 + 35066 * w_4 + 87490 * w_3 + 141183 * w_2 + 95993 * w + 21640) * d_2 / (816480 * w_5 * w1_3); + e2 -= (11053 * w_8 + 53308 * w_7 + 117010 * w_6 + 163924 * w_5 + 116188 * w_4 - 258428 * w_3 - 677042 * w_2 - 481940 * w - 105497) * d_3 / (14696640 * w1_4 * w_6); + + T e3 = -((3592 * w_7 + 8375 * w_6 - 1323 * w_5 - 29198 * w_4 - 89578 * w_3 - 154413 * w_2 - 116063 * w - 29632) * (w - 1)) / (816480 * w_5 * w1_2); + e3 -= (442043 * w_9 + 2054169 * w_8 + 3803094 * w_7 + 3470754 * w_6 + 2141568 * w_5 - 2393568 * w_4 - 19904934 * w_3 - 34714674 * w_2 - 23128299 * w - 5253353) * d / (146966400 * w_6 * w1_3); + e3 -= (116932 * w_10 + 819281 * w_9 + 2378172 * w_8 + 4341330 * w_7 + 6806004 * w_6 + 10622748 * w_5 + 18739500 * w_4 + 30651894 * w_3 + 30869976 * w_2 + 15431867 * w + 2919016) * d_2 / (146966400 * w1_4 * w_7); + // + // Combine eta0 and the error terms to compute eta (Second eqaution p155): + // + T eta = eta0 + e1 / a + e2 / (a * a) + e3 / (a * a * a); + // + // Now we need to solve Eq 4.2 to obtain x. For any given value of + // eta there are two solutions to this equation, and since the distribtion + // may be very skewed, these are not related by x ~ 1-x we used when + // implementing section 3 above. However we know that: + // + // cross < x <= 1 ; iff eta < mu + // x == cross ; iff eta == mu + // 0 <= x < cross ; iff eta > mu + // + // Where cross == 1 / (1 + mu) + // Many thanks to Prof Temme for clarifying this point. + // + // Therefore we'll just jump straight into Newton iterations + // to solve Eq 4.2 using these bounds, and simple bisection + // as the first guess, in practice this converges pretty quickly + // and we only need a few digits correct anyway: + // + if(eta <= 0) + eta = tools::min_value<T>(); + T u = eta - mu * log(eta) + (1 + mu) * log(1 + mu) - mu; + T cross = 1 / (1 + mu); + T lower = eta < mu ? cross : 0; + T upper = eta < mu ? 1 : cross; + T x = (lower + upper) / 2; + x = tools::newton_raphson_iterate( + temme_root_finder<T>(u, mu), x, lower, upper, policies::digits<T, Policy>() / 2); +#ifdef BOOST_INSTRUMENT + std::cout << "Estimating x with Temme method 3: " << x << std::endl; +#endif + return x; +} + +template <class T, class Policy> +struct ibeta_roots +{ + ibeta_roots(T _a, T _b, T t, bool inv = false) + : a(_a), b(_b), target(t), invert(inv) {} + + boost::math::tuple<T, T, T> operator()(T x) + { + BOOST_MATH_STD_USING // ADL of std names + + BOOST_FPU_EXCEPTION_GUARD + + T f1; + T y = 1 - x; + T f = ibeta_imp(a, b, x, Policy(), invert, true, &f1) - target; + if(invert) + f1 = -f1; + if(y == 0) + y = tools::min_value<T>() * 64; + if(x == 0) + x = tools::min_value<T>() * 64; + + T f2 = f1 * (-y * a + (b - 2) * x + 1); + if(fabs(f2) < y * x * tools::max_value<T>()) + f2 /= (y * x); + if(invert) + f2 = -f2; + + // make sure we don't have a zero derivative: + if(f1 == 0) + f1 = (invert ? -1 : 1) * tools::min_value<T>() * 64; + + return boost::math::make_tuple(f, f1, f2); + } +private: + T a, b, target; + bool invert; +}; + +template <class T, class Policy> +T ibeta_inv_imp(T a, T b, T p, T q, const Policy& pol, T* py) +{ + BOOST_MATH_STD_USING // For ADL of math functions. + + // + // The flag invert is set to true if we swap a for b and p for q, + // in which case the result has to be subtracted from 1: + // + bool invert = false; + // + // Handle trivial cases first: + // + if(q == 0) + { + if(py) *py = 0; + return 1; + } + else if(p == 0) + { + if(py) *py = 1; + return 0; + } + else if(a == 1) + { + if(b == 1) + { + if(py) *py = 1 - p; + return p; + } + // Change things around so we can handle as b == 1 special case below: + std::swap(a, b); + std::swap(p, q); + invert = true; + } + // + // Depending upon which approximation method we use, we may end up + // calculating either x or y initially (where y = 1-x): + // + T x = 0; // Set to a safe zero to avoid a + // MSVC 2005 warning C4701: potentially uninitialized local variable 'x' used + // But code inspection appears to ensure that x IS assigned whatever the code path. + T y; + + // For some of the methods we can put tighter bounds + // on the result than simply [0,1]: + // + T lower = 0; + T upper = 1; + // + // Student's T with b = 0.5 gets handled as a special case, swap + // around if the arguments are in the "wrong" order: + // + if(a == 0.5f) + { + if(b == 0.5f) + { + x = sin(p * constants::half_pi<T>()); + x *= x; + if(py) + { + *py = sin(q * constants::half_pi<T>()); + *py *= *py; + } + return x; + } + else if(b > 0.5f) + { + std::swap(a, b); + std::swap(p, q); + invert = !invert; + } + } + // + // Select calculation method for the initial estimate: + // + if((b == 0.5f) && (a >= 0.5f) && (p != 1)) + { + // + // We have a Student's T distribution: + x = find_ibeta_inv_from_t_dist(a, p, q, &y, pol); + } + else if(b == 1) + { + if(p < q) + { + if(a > 1) + { + x = pow(p, 1 / a); + y = -boost::math::expm1(log(p) / a, pol); + } + else + { + x = pow(p, 1 / a); + y = 1 - x; + } + } + else + { + x = exp(boost::math::log1p(-q, pol) / a); + y = -boost::math::expm1(boost::math::log1p(-q, pol) / a, pol); + } + if(invert) + std::swap(x, y); + if(py) + *py = y; + return x; + } + else if(a + b > 5) + { + // + // When a+b is large then we can use one of Prof Temme's + // asymptotic expansions, begin by swapping things around + // so that p < 0.5, we do this to avoid cancellations errors + // when p is large. + // + if(p > 0.5) + { + std::swap(a, b); + std::swap(p, q); + invert = !invert; + } + T minv = (std::min)(a, b); + T maxv = (std::max)(a, b); + if((sqrt(minv) > (maxv - minv)) && (minv > 5)) + { + // + // When a and b differ by a small amount + // the curve is quite symmetrical and we can use an error + // function to approximate the inverse. This is the cheapest + // of the three Temme expantions, and the calculated value + // for x will never be much larger than p, so we don't have + // to worry about cancellation as long as p is small. + // + x = temme_method_1_ibeta_inverse(a, b, p, pol); + y = 1 - x; + } + else + { + T r = a + b; + T theta = asin(sqrt(a / r)); + T lambda = minv / r; + if((lambda >= 0.2) && (lambda <= 0.8) && (r >= 10)) + { + // + // The second error function case is the next cheapest + // to use, it brakes down when the result is likely to be + // very small, if a+b is also small, but we can use a + // cheaper expansion there in any case. As before x won't + // be much larger than p, so as long as p is small we should + // be free of cancellation error. + // + T ppa = pow(p, 1/a); + if((ppa < 0.0025) && (a + b < 200)) + { + x = ppa * pow(a * boost::math::beta(a, b, pol), 1/a); + } + else + x = temme_method_2_ibeta_inverse(a, b, p, r, theta, pol); + y = 1 - x; + } + else + { + // + // If we get here then a and b are very different in magnitude + // and we need to use the third of Temme's methods which + // involves inverting the incomplete gamma. This is much more + // expensive than the other methods. We also can only use this + // method when a > b, which can lead to cancellation errors + // if we really want y (as we will when x is close to 1), so + // a different expansion is used in that case. + // + if(a < b) + { + std::swap(a, b); + std::swap(p, q); + invert = !invert; + } + // + // Try and compute the easy way first: + // + T bet = 0; + if(b < 2) + bet = boost::math::beta(a, b, pol); + if(bet != 0) + { + y = pow(b * q * bet, 1/b); + x = 1 - y; + } + else + y = 1; + if(y > 1e-5) + { + x = temme_method_3_ibeta_inverse(a, b, p, q, pol); + y = 1 - x; + } + } + } + } + else if((a < 1) && (b < 1)) + { + // + // Both a and b less than 1, + // there is a point of inflection at xs: + // + T xs = (1 - a) / (2 - a - b); + // + // Now we need to ensure that we start our iteration from the + // right side of the inflection point: + // + T fs = boost::math::ibeta(a, b, xs, pol) - p; + if(fabs(fs) / p < tools::epsilon<T>() * 3) + { + // The result is at the point of inflection, best just return it: + *py = invert ? xs : 1 - xs; + return invert ? 1-xs : xs; + } + if(fs < 0) + { + std::swap(a, b); + std::swap(p, q); + invert = !invert; + xs = 1 - xs; + } + T xg = pow(a * p * boost::math::beta(a, b, pol), 1/a); + x = xg / (1 + xg); + y = 1 / (1 + xg); + // + // And finally we know that our result is below the inflection + // point, so set an upper limit on our search: + // + if(x > xs) + x = xs; + upper = xs; + } + else if((a > 1) && (b > 1)) + { + // + // Small a and b, both greater than 1, + // there is a point of inflection at xs, + // and it's complement is xs2, we must always + // start our iteration from the right side of the + // point of inflection. + // + T xs = (a - 1) / (a + b - 2); + T xs2 = (b - 1) / (a + b - 2); + T ps = boost::math::ibeta(a, b, xs, pol) - p; + + if(ps < 0) + { + std::swap(a, b); + std::swap(p, q); + std::swap(xs, xs2); + invert = !invert; + } + // + // Estimate x and y, using expm1 to get a good estimate + // for y when it's very small: + // + T lx = log(p * a * boost::math::beta(a, b, pol)) / a; + x = exp(lx); + y = x < 0.9 ? T(1 - x) : (T)(-boost::math::expm1(lx, pol)); + + if((b < a) && (x < 0.2)) + { + // + // Under a limited range of circumstances we can improve + // our estimate for x, frankly it's clear if this has much effect! + // + T ap1 = a - 1; + T bm1 = b - 1; + T a_2 = a * a; + T a_3 = a * a_2; + T b_2 = b * b; + T terms[5] = { 0, 1 }; + terms[2] = bm1 / ap1; + ap1 *= ap1; + terms[3] = bm1 * (3 * a * b + 5 * b + a_2 - a - 4) / (2 * (a + 2) * ap1); + ap1 *= (a + 1); + terms[4] = bm1 * (33 * a * b_2 + 31 * b_2 + 8 * a_2 * b_2 - 30 * a * b - 47 * b + 11 * a_2 * b + 6 * a_3 * b + 18 + 4 * a - a_3 + a_2 * a_2 - 10 * a_2) + / (3 * (a + 3) * (a + 2) * ap1); + x = tools::evaluate_polynomial(terms, x, 5); + } + // + // And finally we know that our result is below the inflection + // point, so set an upper limit on our search: + // + if(x > xs) + x = xs; + upper = xs; + } + else /*if((a <= 1) != (b <= 1))*/ + { + // + // If all else fails we get here, only one of a and b + // is above 1, and a+b is small. Start by swapping + // things around so that we have a concave curve with b > a + // and no points of inflection in [0,1]. As long as we expect + // x to be small then we can use the simple (and cheap) power + // term to estimate x, but when we expect x to be large then + // this greatly underestimates x and leaves us trying to + // iterate "round the corner" which may take almost forever... + // + // We could use Temme's inverse gamma function case in that case, + // this works really rather well (albeit expensively) even though + // strictly speaking we're outside it's defined range. + // + // However it's expensive to compute, and an alternative approach + // which models the curve as a distorted quarter circle is much + // cheaper to compute, and still keeps the number of iterations + // required down to a reasonable level. With thanks to Prof Temme + // for this suggestion. + // + if(b < a) + { + std::swap(a, b); + std::swap(p, q); + invert = !invert; + } + if(pow(p, 1/a) < 0.5) + { + x = pow(p * a * boost::math::beta(a, b, pol), 1 / a); + if(x == 0) + x = boost::math::tools::min_value<T>(); + y = 1 - x; + } + else /*if(pow(q, 1/b) < 0.1)*/ + { + // model a distorted quarter circle: + y = pow(1 - pow(p, b * boost::math::beta(a, b, pol)), 1/b); + if(y == 0) + y = boost::math::tools::min_value<T>(); + x = 1 - y; + } + } + + // + // Now we have a guess for x (and for y) we can set things up for + // iteration. If x > 0.5 it pays to swap things round: + // + if(x > 0.5) + { + std::swap(a, b); + std::swap(p, q); + std::swap(x, y); + invert = !invert; + T l = 1 - upper; + T u = 1 - lower; + lower = l; + upper = u; + } + // + // lower bound for our search: + // + // We're not interested in denormalised answers as these tend to + // these tend to take up lots of iterations, given that we can't get + // accurate derivatives in this area (they tend to be infinite). + // + if(lower == 0) + { + if(invert && (py == 0)) + { + // + // We're not interested in answers smaller than machine epsilon: + // + lower = boost::math::tools::epsilon<T>(); + if(x < lower) + x = lower; + } + else + lower = boost::math::tools::min_value<T>(); + if(x < lower) + x = lower; + } + // + // Figure out how many digits to iterate towards: + // + int digits = boost::math::policies::digits<T, Policy>() / 2; + if((x < 1e-50) && ((a < 1) || (b < 1))) + { + // + // If we're in a region where the first derivative is very + // large, then we have to take care that the root-finder + // doesn't terminate prematurely. We'll bump the precision + // up to avoid this, but we have to take care not to set the + // precision too high or the last few iterations will just + // thrash around and convergence may be slow in this case. + // Try 3/4 of machine epsilon: + // + digits *= 3; + digits /= 2; + } + // + // Now iterate, we can use either p or q as the target here + // depending on which is smaller: + // + boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>(); + x = boost::math::tools::halley_iterate( + boost::math::detail::ibeta_roots<T, Policy>(a, b, (p < q ? p : q), (p < q ? false : true)), x, lower, upper, digits, max_iter); + policies::check_root_iterations<T>("boost::math::ibeta<%1%>(%1%, %1%, %1%)", max_iter, pol); + // + // We don't really want these asserts here, but they are useful for sanity + // checking that we have the limits right, uncomment if you suspect bugs *only*. + // + //BOOST_ASSERT(x != upper); + //BOOST_ASSERT((x != lower) || (x == boost::math::tools::min_value<T>()) || (x == boost::math::tools::epsilon<T>())); + // + // Tidy up, if we "lower" was too high then zero is the best answer we have: + // + if(x == lower) + x = 0; + if(py) + *py = invert ? x : 1 - x; + return invert ? 1-x : x; +} + +} // namespace detail + +template <class T1, class T2, class T3, class T4, class Policy> +inline typename tools::promote_args<T1, T2, T3, T4>::type + ibeta_inv(T1 a, T2 b, T3 p, T4* py, const Policy& pol) +{ + static const char* function = "boost::math::ibeta_inv<%1%>(%1%,%1%,%1%)"; + BOOST_FPU_EXCEPTION_GUARD + typedef typename tools::promote_args<T1, T2, T3, T4>::type result_type; + typedef typename policies::evaluation<result_type, Policy>::type value_type; + typedef typename policies::normalise< + Policy, + policies::promote_float<false>, + policies::promote_double<false>, + policies::discrete_quantile<>, + policies::assert_undefined<> >::type forwarding_policy; + + if(a <= 0) + return policies::raise_domain_error<result_type>(function, "The argument a to the incomplete beta function inverse must be greater than zero (got a=%1%).", a, pol); + if(b <= 0) + return policies::raise_domain_error<result_type>(function, "The argument b to the incomplete beta function inverse must be greater than zero (got b=%1%).", b, pol); + if((p < 0) || (p > 1)) + return policies::raise_domain_error<result_type>(function, "Argument p outside the range [0,1] in the incomplete beta function inverse (got p=%1%).", p, pol); + + value_type rx, ry; + + rx = detail::ibeta_inv_imp( + static_cast<value_type>(a), + static_cast<value_type>(b), + static_cast<value_type>(p), + static_cast<value_type>(1 - p), + forwarding_policy(), &ry); + + if(py) *py = policies::checked_narrowing_cast<T4, forwarding_policy>(ry, function); + return policies::checked_narrowing_cast<result_type, forwarding_policy>(rx, function); +} + +template <class T1, class T2, class T3, class T4> +inline typename tools::promote_args<T1, T2, T3, T4>::type + ibeta_inv(T1 a, T2 b, T3 p, T4* py) +{ + return ibeta_inv(a, b, p, py, policies::policy<>()); +} + +template <class T1, class T2, class T3> +inline typename tools::promote_args<T1, T2, T3>::type + ibeta_inv(T1 a, T2 b, T3 p) +{ + typedef typename tools::promote_args<T1, T2, T3>::type result_type; + return ibeta_inv(a, b, p, static_cast<result_type*>(0), policies::policy<>()); +} + +template <class T1, class T2, class T3, class Policy> +inline typename tools::promote_args<T1, T2, T3>::type + ibeta_inv(T1 a, T2 b, T3 p, const Policy& pol) +{ + typedef typename tools::promote_args<T1, T2, T3>::type result_type; + return ibeta_inv(a, b, p, static_cast<result_type*>(0), pol); +} + +template <class T1, class T2, class T3, class T4, class Policy> +inline typename tools::promote_args<T1, T2, T3, T4>::type + ibetac_inv(T1 a, T2 b, T3 q, T4* py, const Policy& pol) +{ + static const char* function = "boost::math::ibetac_inv<%1%>(%1%,%1%,%1%)"; + BOOST_FPU_EXCEPTION_GUARD + typedef typename tools::promote_args<T1, T2, T3, T4>::type result_type; + typedef typename policies::evaluation<result_type, Policy>::type value_type; + typedef typename policies::normalise< + Policy, + policies::promote_float<false>, + policies::promote_double<false>, + policies::discrete_quantile<>, + policies::assert_undefined<> >::type forwarding_policy; + + if(a <= 0) + return policies::raise_domain_error<result_type>(function, "The argument a to the incomplete beta function inverse must be greater than zero (got a=%1%).", a, pol); + if(b <= 0) + return policies::raise_domain_error<result_type>(function, "The argument b to the incomplete beta function inverse must be greater than zero (got b=%1%).", b, pol); + if((q < 0) || (q > 1)) + return policies::raise_domain_error<result_type>(function, "Argument q outside the range [0,1] in the incomplete beta function inverse (got q=%1%).", q, pol); + + value_type rx, ry; + + rx = detail::ibeta_inv_imp( + static_cast<value_type>(a), + static_cast<value_type>(b), + static_cast<value_type>(1 - q), + static_cast<value_type>(q), + forwarding_policy(), &ry); + + if(py) *py = policies::checked_narrowing_cast<T4, forwarding_policy>(ry, function); + return policies::checked_narrowing_cast<result_type, forwarding_policy>(rx, function); +} + +template <class T1, class T2, class T3, class T4> +inline typename tools::promote_args<T1, T2, T3, T4>::type + ibetac_inv(T1 a, T2 b, T3 q, T4* py) +{ + return ibetac_inv(a, b, q, py, policies::policy<>()); +} + +template <class RT1, class RT2, class RT3> +inline typename tools::promote_args<RT1, RT2, RT3>::type + ibetac_inv(RT1 a, RT2 b, RT3 q) +{ + typedef typename tools::promote_args<RT1, RT2, RT3>::type result_type; + return ibetac_inv(a, b, q, static_cast<result_type*>(0), policies::policy<>()); +} + +template <class RT1, class RT2, class RT3, class Policy> +inline typename tools::promote_args<RT1, RT2, RT3>::type + ibetac_inv(RT1 a, RT2 b, RT3 q, const Policy& pol) +{ + typedef typename tools::promote_args<RT1, RT2, RT3>::type result_type; + return ibetac_inv(a, b, q, static_cast<result_type*>(0), pol); +} + +} // namespace math +} // namespace boost + +#endif // BOOST_MATH_SPECIAL_FUNCTIONS_IGAMMA_INVERSE_HPP + + + + diff --git a/src/third_party/boost-1.70.0/boost/math/special_functions/detail/iconv.hpp b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/iconv.hpp new file mode 100644 index 00000000000..4256ffcc88e --- /dev/null +++ b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/iconv.hpp @@ -0,0 +1,42 @@ +// Copyright (c) 2009 John Maddock +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_ICONV_HPP +#define BOOST_MATH_ICONV_HPP + +#ifdef _MSC_VER +#pragma once +#endif + +#include <boost/math/special_functions/round.hpp> +#include <boost/type_traits/is_convertible.hpp> + +namespace boost { namespace math { namespace detail{ + +template <class T, class Policy> +inline int iconv_imp(T v, Policy const&, mpl::true_ const&) +{ + return static_cast<int>(v); +} + +template <class T, class Policy> +inline int iconv_imp(T v, Policy const& pol, mpl::false_ const&) +{ + BOOST_MATH_STD_USING + return iround(v, pol); +} + +template <class T, class Policy> +inline int iconv(T v, Policy const& pol) +{ + typedef typename boost::is_convertible<T, int>::type tag_type; + return iconv_imp(v, pol, tag_type()); +} + + +}}} // namespaces + +#endif // BOOST_MATH_ICONV_HPP + diff --git a/src/third_party/boost-1.70.0/boost/math/special_functions/detail/igamma_inverse.hpp b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/igamma_inverse.hpp new file mode 100644 index 00000000000..fd0189ca6d5 --- /dev/null +++ b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/igamma_inverse.hpp @@ -0,0 +1,551 @@ +// (C) Copyright John Maddock 2006. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_SPECIAL_FUNCTIONS_IGAMMA_INVERSE_HPP +#define BOOST_MATH_SPECIAL_FUNCTIONS_IGAMMA_INVERSE_HPP + +#ifdef _MSC_VER +#pragma once +#endif + +#include <boost/math/tools/tuple.hpp> +#include <boost/math/special_functions/gamma.hpp> +#include <boost/math/special_functions/sign.hpp> +#include <boost/math/tools/roots.hpp> +#include <boost/math/policies/error_handling.hpp> + +namespace boost{ namespace math{ + +namespace detail{ + +template <class T> +T find_inverse_s(T p, T q) +{ + // + // Computation of the Incomplete Gamma Function Ratios and their Inverse + // ARMIDO R. DIDONATO and ALFRED H. MORRIS, JR. + // ACM Transactions on Mathematical Software, Vol. 12, No. 4, + // December 1986, Pages 377-393. + // + // See equation 32. + // + BOOST_MATH_STD_USING + T t; + if(p < 0.5) + { + t = sqrt(-2 * log(p)); + } + else + { + t = sqrt(-2 * log(q)); + } + static const double a[4] = { 3.31125922108741, 11.6616720288968, 4.28342155967104, 0.213623493715853 }; + static const double b[5] = { 1, 6.61053765625462, 6.40691597760039, 1.27364489782223, 0.3611708101884203e-1 }; + T s = t - tools::evaluate_polynomial(a, t) / tools::evaluate_polynomial(b, t); + if(p < 0.5) + s = -s; + return s; +} + +template <class T> +T didonato_SN(T a, T x, unsigned N, T tolerance = 0) +{ + // + // Computation of the Incomplete Gamma Function Ratios and their Inverse + // ARMIDO R. DIDONATO and ALFRED H. MORRIS, JR. + // ACM Transactions on Mathematical Software, Vol. 12, No. 4, + // December 1986, Pages 377-393. + // + // See equation 34. + // + T sum = 1; + if(N >= 1) + { + T partial = x / (a + 1); + sum += partial; + for(unsigned i = 2; i <= N; ++i) + { + partial *= x / (a + i); + sum += partial; + if(partial < tolerance) + break; + } + } + return sum; +} + +template <class T, class Policy> +inline T didonato_FN(T p, T a, T x, unsigned N, T tolerance, const Policy& pol) +{ + // + // Computation of the Incomplete Gamma Function Ratios and their Inverse + // ARMIDO R. DIDONATO and ALFRED H. MORRIS, JR. + // ACM Transactions on Mathematical Software, Vol. 12, No. 4, + // December 1986, Pages 377-393. + // + // See equation 34. + // + BOOST_MATH_STD_USING + T u = log(p) + boost::math::lgamma(a + 1, pol); + return exp((u + x - log(didonato_SN(a, x, N, tolerance))) / a); +} + +template <class T, class Policy> +T find_inverse_gamma(T a, T p, T q, const Policy& pol, bool* p_has_10_digits) +{ + // + // In order to understand what's going on here, you will + // need to refer to: + // + // Computation of the Incomplete Gamma Function Ratios and their Inverse + // ARMIDO R. DIDONATO and ALFRED H. MORRIS, JR. + // ACM Transactions on Mathematical Software, Vol. 12, No. 4, + // December 1986, Pages 377-393. + // + BOOST_MATH_STD_USING + + T result; + *p_has_10_digits = false; + + if(a == 1) + { + result = -log(q); + BOOST_MATH_INSTRUMENT_VARIABLE(result); + } + else if(a < 1) + { + T g = boost::math::tgamma(a, pol); + T b = q * g; + BOOST_MATH_INSTRUMENT_VARIABLE(g); + BOOST_MATH_INSTRUMENT_VARIABLE(b); + if((b > 0.6) || ((b >= 0.45) && (a >= 0.3))) + { + // DiDonato & Morris Eq 21: + // + // There is a slight variation from DiDonato and Morris here: + // the first form given here is unstable when p is close to 1, + // making it impossible to compute the inverse of Q(a,x) for small + // q. Fortunately the second form works perfectly well in this case. + // + T u; + if((b * q > 1e-8) && (q > 1e-5)) + { + u = pow(p * g * a, 1 / a); + BOOST_MATH_INSTRUMENT_VARIABLE(u); + } + else + { + u = exp((-q / a) - constants::euler<T>()); + BOOST_MATH_INSTRUMENT_VARIABLE(u); + } + result = u / (1 - (u / (a + 1))); + BOOST_MATH_INSTRUMENT_VARIABLE(result); + } + else if((a < 0.3) && (b >= 0.35)) + { + // DiDonato & Morris Eq 22: + T t = exp(-constants::euler<T>() - b); + T u = t * exp(t); + result = t * exp(u); + BOOST_MATH_INSTRUMENT_VARIABLE(result); + } + else if((b > 0.15) || (a >= 0.3)) + { + // DiDonato & Morris Eq 23: + T y = -log(b); + T u = y - (1 - a) * log(y); + result = y - (1 - a) * log(u) - log(1 + (1 - a) / (1 + u)); + BOOST_MATH_INSTRUMENT_VARIABLE(result); + } + else if (b > 0.1) + { + // DiDonato & Morris Eq 24: + T y = -log(b); + T u = y - (1 - a) * log(y); + result = y - (1 - a) * log(u) - log((u * u + 2 * (3 - a) * u + (2 - a) * (3 - a)) / (u * u + (5 - a) * u + 2)); + BOOST_MATH_INSTRUMENT_VARIABLE(result); + } + else + { + // DiDonato & Morris Eq 25: + T y = -log(b); + T c1 = (a - 1) * log(y); + T c1_2 = c1 * c1; + T c1_3 = c1_2 * c1; + T c1_4 = c1_2 * c1_2; + T a_2 = a * a; + T a_3 = a_2 * a; + + T c2 = (a - 1) * (1 + c1); + T c3 = (a - 1) * (-(c1_2 / 2) + (a - 2) * c1 + (3 * a - 5) / 2); + T c4 = (a - 1) * ((c1_3 / 3) - (3 * a - 5) * c1_2 / 2 + (a_2 - 6 * a + 7) * c1 + (11 * a_2 - 46 * a + 47) / 6); + T c5 = (a - 1) * (-(c1_4 / 4) + + (11 * a - 17) * c1_3 / 6 + + (-3 * a_2 + 13 * a -13) * c1_2 + + (2 * a_3 - 25 * a_2 + 72 * a - 61) * c1 / 2 + + (25 * a_3 - 195 * a_2 + 477 * a - 379) / 12); + + T y_2 = y * y; + T y_3 = y_2 * y; + T y_4 = y_2 * y_2; + result = y + c1 + (c2 / y) + (c3 / y_2) + (c4 / y_3) + (c5 / y_4); + BOOST_MATH_INSTRUMENT_VARIABLE(result); + if(b < 1e-28f) + *p_has_10_digits = true; + } + } + else + { + // DiDonato and Morris Eq 31: + T s = find_inverse_s(p, q); + + BOOST_MATH_INSTRUMENT_VARIABLE(s); + + T s_2 = s * s; + T s_3 = s_2 * s; + T s_4 = s_2 * s_2; + T s_5 = s_4 * s; + T ra = sqrt(a); + + BOOST_MATH_INSTRUMENT_VARIABLE(ra); + + T w = a + s * ra + (s * s -1) / 3; + w += (s_3 - 7 * s) / (36 * ra); + w -= (3 * s_4 + 7 * s_2 - 16) / (810 * a); + w += (9 * s_5 + 256 * s_3 - 433 * s) / (38880 * a * ra); + + BOOST_MATH_INSTRUMENT_VARIABLE(w); + + if((a >= 500) && (fabs(1 - w / a) < 1e-6)) + { + result = w; + *p_has_10_digits = true; + BOOST_MATH_INSTRUMENT_VARIABLE(result); + } + else if (p > 0.5) + { + if(w < 3 * a) + { + result = w; + BOOST_MATH_INSTRUMENT_VARIABLE(result); + } + else + { + T D = (std::max)(T(2), T(a * (a - 1))); + T lg = boost::math::lgamma(a, pol); + T lb = log(q) + lg; + if(lb < -D * 2.3) + { + // DiDonato and Morris Eq 25: + T y = -lb; + T c1 = (a - 1) * log(y); + T c1_2 = c1 * c1; + T c1_3 = c1_2 * c1; + T c1_4 = c1_2 * c1_2; + T a_2 = a * a; + T a_3 = a_2 * a; + + T c2 = (a - 1) * (1 + c1); + T c3 = (a - 1) * (-(c1_2 / 2) + (a - 2) * c1 + (3 * a - 5) / 2); + T c4 = (a - 1) * ((c1_3 / 3) - (3 * a - 5) * c1_2 / 2 + (a_2 - 6 * a + 7) * c1 + (11 * a_2 - 46 * a + 47) / 6); + T c5 = (a - 1) * (-(c1_4 / 4) + + (11 * a - 17) * c1_3 / 6 + + (-3 * a_2 + 13 * a -13) * c1_2 + + (2 * a_3 - 25 * a_2 + 72 * a - 61) * c1 / 2 + + (25 * a_3 - 195 * a_2 + 477 * a - 379) / 12); + + T y_2 = y * y; + T y_3 = y_2 * y; + T y_4 = y_2 * y_2; + result = y + c1 + (c2 / y) + (c3 / y_2) + (c4 / y_3) + (c5 / y_4); + BOOST_MATH_INSTRUMENT_VARIABLE(result); + } + else + { + // DiDonato and Morris Eq 33: + T u = -lb + (a - 1) * log(w) - log(1 + (1 - a) / (1 + w)); + result = -lb + (a - 1) * log(u) - log(1 + (1 - a) / (1 + u)); + BOOST_MATH_INSTRUMENT_VARIABLE(result); + } + } + } + else + { + T z = w; + T ap1 = a + 1; + T ap2 = a + 2; + if(w < 0.15f * ap1) + { + // DiDonato and Morris Eq 35: + T v = log(p) + boost::math::lgamma(ap1, pol); + z = exp((v + w) / a); + s = boost::math::log1p(z / ap1 * (1 + z / ap2), pol); + z = exp((v + z - s) / a); + s = boost::math::log1p(z / ap1 * (1 + z / ap2), pol); + z = exp((v + z - s) / a); + s = boost::math::log1p(z / ap1 * (1 + z / ap2 * (1 + z / (a + 3))), pol); + z = exp((v + z - s) / a); + BOOST_MATH_INSTRUMENT_VARIABLE(z); + } + + if((z <= 0.01 * ap1) || (z > 0.7 * ap1)) + { + result = z; + if(z <= 0.002 * ap1) + *p_has_10_digits = true; + BOOST_MATH_INSTRUMENT_VARIABLE(result); + } + else + { + // DiDonato and Morris Eq 36: + T ls = log(didonato_SN(a, z, 100, T(1e-4))); + T v = log(p) + boost::math::lgamma(ap1, pol); + z = exp((v + z - ls) / a); + result = z * (1 - (a * log(z) - z - v + ls) / (a - z)); + + BOOST_MATH_INSTRUMENT_VARIABLE(result); + } + } + } + return result; +} + +template <class T, class Policy> +struct gamma_p_inverse_func +{ + gamma_p_inverse_func(T a_, T p_, bool inv) : a(a_), p(p_), invert(inv) + { + // + // If p is too near 1 then P(x) - p suffers from cancellation + // errors causing our root-finding algorithms to "thrash", better + // to invert in this case and calculate Q(x) - (1-p) instead. + // + // Of course if p is *very* close to 1, then the answer we get will + // be inaccurate anyway (because there's not enough information in p) + // but at least we will converge on the (inaccurate) answer quickly. + // + if(p > 0.9) + { + p = 1 - p; + invert = !invert; + } + } + + boost::math::tuple<T, T, T> operator()(const T& x)const + { + BOOST_FPU_EXCEPTION_GUARD + // + // Calculate P(x) - p and the first two derivates, or if the invert + // flag is set, then Q(x) - q and it's derivatives. + // + typedef typename policies::evaluation<T, Policy>::type value_type; + // typedef typename lanczos::lanczos<T, Policy>::type evaluation_type; + typedef typename policies::normalise< + Policy, + policies::promote_float<false>, + policies::promote_double<false>, + policies::discrete_quantile<>, + policies::assert_undefined<> >::type forwarding_policy; + + BOOST_MATH_STD_USING // For ADL of std functions. + + T f, f1; + value_type ft; + f = static_cast<T>(boost::math::detail::gamma_incomplete_imp( + static_cast<value_type>(a), + static_cast<value_type>(x), + true, invert, + forwarding_policy(), &ft)); + f1 = static_cast<T>(ft); + T f2; + T div = (a - x - 1) / x; + f2 = f1; + if((fabs(div) > 1) && (tools::max_value<T>() / fabs(div) < f2)) + { + // overflow: + f2 = -tools::max_value<T>() / 2; + } + else + { + f2 *= div; + } + + if(invert) + { + f1 = -f1; + f2 = -f2; + } + + return boost::math::make_tuple(static_cast<T>(f - p), f1, f2); + } +private: + T a, p; + bool invert; +}; + +template <class T, class Policy> +T gamma_p_inv_imp(T a, T p, const Policy& pol) +{ + BOOST_MATH_STD_USING // ADL of std functions. + + static const char* function = "boost::math::gamma_p_inv<%1%>(%1%, %1%)"; + + BOOST_MATH_INSTRUMENT_VARIABLE(a); + BOOST_MATH_INSTRUMENT_VARIABLE(p); + + if(a <= 0) + return policies::raise_domain_error<T>(function, "Argument a in the incomplete gamma function inverse must be >= 0 (got a=%1%).", a, pol); + if((p < 0) || (p > 1)) + return policies::raise_domain_error<T>(function, "Probabilty must be in the range [0,1] in the incomplete gamma function inverse (got p=%1%).", p, pol); + if(p == 1) + return policies::raise_overflow_error<T>(function, 0, Policy()); + if(p == 0) + return 0; + bool has_10_digits; + T guess = detail::find_inverse_gamma<T>(a, p, 1 - p, pol, &has_10_digits); + if((policies::digits<T, Policy>() <= 36) && has_10_digits) + return guess; + T lower = tools::min_value<T>(); + if(guess <= lower) + guess = tools::min_value<T>(); + BOOST_MATH_INSTRUMENT_VARIABLE(guess); + // + // Work out how many digits to converge to, normally this is + // 2/3 of the digits in T, but if the first derivative is very + // large convergence is slow, so we'll bump it up to full + // precision to prevent premature termination of the root-finding routine. + // + unsigned digits = policies::digits<T, Policy>(); + if(digits < 30) + { + digits *= 2; + digits /= 3; + } + else + { + digits /= 2; + digits -= 1; + } + if((a < 0.125) && (fabs(gamma_p_derivative(a, guess, pol)) > 1 / sqrt(tools::epsilon<T>()))) + digits = policies::digits<T, Policy>() - 2; + // + // Go ahead and iterate: + // + boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>(); + guess = tools::halley_iterate( + detail::gamma_p_inverse_func<T, Policy>(a, p, false), + guess, + lower, + tools::max_value<T>(), + digits, + max_iter); + policies::check_root_iterations<T>(function, max_iter, pol); + BOOST_MATH_INSTRUMENT_VARIABLE(guess); + if(guess == lower) + guess = policies::raise_underflow_error<T>(function, "Expected result known to be non-zero, but is smaller than the smallest available number.", pol); + return guess; +} + +template <class T, class Policy> +T gamma_q_inv_imp(T a, T q, const Policy& pol) +{ + BOOST_MATH_STD_USING // ADL of std functions. + + static const char* function = "boost::math::gamma_q_inv<%1%>(%1%, %1%)"; + + if(a <= 0) + return policies::raise_domain_error<T>(function, "Argument a in the incomplete gamma function inverse must be >= 0 (got a=%1%).", a, pol); + if((q < 0) || (q > 1)) + return policies::raise_domain_error<T>(function, "Probabilty must be in the range [0,1] in the incomplete gamma function inverse (got q=%1%).", q, pol); + if(q == 0) + return policies::raise_overflow_error<T>(function, 0, Policy()); + if(q == 1) + return 0; + bool has_10_digits; + T guess = detail::find_inverse_gamma<T>(a, 1 - q, q, pol, &has_10_digits); + if((policies::digits<T, Policy>() <= 36) && has_10_digits) + return guess; + T lower = tools::min_value<T>(); + if(guess <= lower) + guess = tools::min_value<T>(); + // + // Work out how many digits to converge to, normally this is + // 2/3 of the digits in T, but if the first derivative is very + // large convergence is slow, so we'll bump it up to full + // precision to prevent premature termination of the root-finding routine. + // + unsigned digits = policies::digits<T, Policy>(); + if(digits < 30) + { + digits *= 2; + digits /= 3; + } + else + { + digits /= 2; + digits -= 1; + } + if((a < 0.125) && (fabs(gamma_p_derivative(a, guess, pol)) > 1 / sqrt(tools::epsilon<T>()))) + digits = policies::digits<T, Policy>(); + // + // Go ahead and iterate: + // + boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>(); + guess = tools::halley_iterate( + detail::gamma_p_inverse_func<T, Policy>(a, q, true), + guess, + lower, + tools::max_value<T>(), + digits, + max_iter); + policies::check_root_iterations<T>(function, max_iter, pol); + if(guess == lower) + guess = policies::raise_underflow_error<T>(function, "Expected result known to be non-zero, but is smaller than the smallest available number.", pol); + return guess; +} + +} // namespace detail + +template <class T1, class T2, class Policy> +inline typename tools::promote_args<T1, T2>::type + gamma_p_inv(T1 a, T2 p, const Policy& pol) +{ + typedef typename tools::promote_args<T1, T2>::type result_type; + return detail::gamma_p_inv_imp( + static_cast<result_type>(a), + static_cast<result_type>(p), pol); +} + +template <class T1, class T2, class Policy> +inline typename tools::promote_args<T1, T2>::type + gamma_q_inv(T1 a, T2 p, const Policy& pol) +{ + typedef typename tools::promote_args<T1, T2>::type result_type; + return detail::gamma_q_inv_imp( + static_cast<result_type>(a), + static_cast<result_type>(p), pol); +} + +template <class T1, class T2> +inline typename tools::promote_args<T1, T2>::type + gamma_p_inv(T1 a, T2 p) +{ + return gamma_p_inv(a, p, policies::policy<>()); +} + +template <class T1, class T2> +inline typename tools::promote_args<T1, T2>::type + gamma_q_inv(T1 a, T2 p) +{ + return gamma_q_inv(a, p, policies::policy<>()); +} + +} // namespace math +} // namespace boost + +#endif // BOOST_MATH_SPECIAL_FUNCTIONS_IGAMMA_INVERSE_HPP + + + diff --git a/src/third_party/boost-1.70.0/boost/math/special_functions/detail/igamma_large.hpp b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/igamma_large.hpp new file mode 100644 index 00000000000..59a75b14333 --- /dev/null +++ b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/igamma_large.hpp @@ -0,0 +1,778 @@ +// Copyright John Maddock 2006. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// This file implements the asymptotic expansions of the incomplete +// gamma functions P(a, x) and Q(a, x), used when a is large and +// x ~ a. +// +// The primary reference is: +// +// "The Asymptotic Expansion of the Incomplete Gamma Functions" +// N. M. Temme. +// Siam J. Math Anal. Vol 10 No 4, July 1979, p757. +// +// A different way of evaluating these expansions, +// plus a lot of very useful background information is in: +// +// "A Set of Algorithms For the Incomplete Gamma Functions." +// N. M. Temme. +// Probability in the Engineering and Informational Sciences, +// 8, 1994, 291. +// +// An alternative implementation is in: +// +// "Computation of the Incomplete Gamma Function Ratios and their Inverse." +// A. R. Didonato and A. H. Morris. +// ACM TOMS, Vol 12, No 4, Dec 1986, p377. +// +// There are various versions of the same code below, each accurate +// to a different precision. To understand the code, refer to Didonato +// and Morris, from Eq 17 and 18 onwards. +// +// The coefficients used here are not taken from Didonato and Morris: +// the domain over which these expansions are used is slightly different +// to theirs, and their constants are not quite accurate enough for +// 128-bit long double's. Instead the coefficients were calculated +// using the methods described by Temme p762 from Eq 3.8 onwards. +// The values obtained agree with those obtained by Didonato and Morris +// (at least to the first 30 digits that they provide). +// At double precision the degrees of polynomial required for full +// machine precision are close to those recomended to Didonato and Morris, +// but of course many more terms are needed for larger types. +// +#ifndef BOOST_MATH_DETAIL_IGAMMA_LARGE +#define BOOST_MATH_DETAIL_IGAMMA_LARGE + +#ifdef _MSC_VER +#pragma once +#endif + +#if defined(__GNUC__) && defined(BOOST_MATH_USE_FLOAT128) +// +// This is the only way we can avoid +// warning: non-standard suffix on floating constant [-Wpedantic] +// when building with -Wall -pedantic. Neither __extension__ +// nor #pragma dianostic ignored work :( +// +#pragma GCC system_header +#endif + +namespace boost{ namespace math{ namespace detail{ + +// This version will never be called (at runtime), it's a stub used +// when T is unsuitable to be passed to these routines: +// +template <class T, class Policy> +inline T igamma_temme_large(T, T, const Policy& /* pol */, mpl::int_<0> const *) +{ + // stub function, should never actually be called + BOOST_ASSERT(0); + return 0; +} +// +// This version is accurate for up to 64-bit mantissa's, +// (80-bit long double, or 10^-20). +// +template <class T, class Policy> +T igamma_temme_large(T a, T x, const Policy& pol, mpl::int_<64> const *) +{ + BOOST_MATH_STD_USING // ADL of std functions + T sigma = (x - a) / a; + T phi = -boost::math::log1pmx(sigma, pol); + T y = a * phi; + T z = sqrt(2 * phi); + if(x < a) + z = -z; + + T workspace[13]; + + static const T C0[] = { + BOOST_MATH_BIG_CONSTANT(T, 64, -0.333333333333333333333), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.0833333333333333333333), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.0148148148148148148148), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.00115740740740740740741), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.000352733686067019400353), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.0001787551440329218107), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.39192631785224377817e-4), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.218544851067999216147e-5), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.18540622107151599607e-5), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.829671134095308600502e-6), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.176659527368260793044e-6), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.670785354340149858037e-8), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.102618097842403080426e-7), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.438203601845335318655e-8), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.914769958223679023418e-9), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.255141939949462497669e-10), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.583077213255042506746e-10), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.243619480206674162437e-10), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.502766928011417558909e-11), + }; + workspace[0] = tools::evaluate_polynomial(C0, z); + + static const T C1[] = { + BOOST_MATH_BIG_CONSTANT(T, 64, -0.00185185185185185185185), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.00347222222222222222222), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.00264550264550264550265), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.000990226337448559670782), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.000205761316872427983539), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.40187757201646090535e-6), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.18098550334489977837e-4), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.764916091608111008464e-5), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.161209008945634460038e-5), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.464712780280743434226e-8), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.137863344691572095931e-6), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.575254560351770496402e-7), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.119516285997781473243e-7), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.175432417197476476238e-10), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.100915437106004126275e-8), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.416279299184258263623e-9), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.856390702649298063807e-10), + }; + workspace[1] = tools::evaluate_polynomial(C1, z); + + static const T C2[] = { + BOOST_MATH_BIG_CONSTANT(T, 64, 0.00413359788359788359788), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.00268132716049382716049), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.000771604938271604938272), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.200938786008230452675e-5), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.000107366532263651605215), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.529234488291201254164e-4), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.127606351886187277134e-4), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.342357873409613807419e-7), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.137219573090629332056e-5), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.629899213838005502291e-6), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.142806142060642417916e-6), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.204770984219908660149e-9), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.140925299108675210533e-7), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.622897408492202203356e-8), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.136704883966171134993e-8), + }; + workspace[2] = tools::evaluate_polynomial(C2, z); + + static const T C3[] = { + BOOST_MATH_BIG_CONSTANT(T, 64, 0.000649434156378600823045), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.000229472093621399176955), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.000469189494395255712128), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.000267720632062838852962), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.756180167188397641073e-4), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.239650511386729665193e-6), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.110826541153473023615e-4), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.56749528269915965675e-5), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.142309007324358839146e-5), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.278610802915281422406e-10), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.169584040919302772899e-6), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.809946490538808236335e-7), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.191111684859736540607e-7), + }; + workspace[3] = tools::evaluate_polynomial(C3, z); + + static const T C4[] = { + BOOST_MATH_BIG_CONSTANT(T, 64, -0.000861888290916711698605), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.000784039221720066627474), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.000299072480303190179733), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.146384525788434181781e-5), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.664149821546512218666e-4), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.396836504717943466443e-4), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.113757269706784190981e-4), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.250749722623753280165e-9), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.169541495365583060147e-5), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.890750753220530968883e-6), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.229293483400080487057e-6), + }; + workspace[4] = tools::evaluate_polynomial(C4, z); + + static const T C5[] = { + BOOST_MATH_BIG_CONSTANT(T, 64, -0.000336798553366358150309), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.697281375836585777429e-4), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.000277275324495939207873), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.000199325705161888477003), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.679778047793720783882e-4), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.141906292064396701483e-6), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.135940481897686932785e-4), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.801847025633420153972e-5), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.229148117650809517038e-5), + }; + workspace[5] = tools::evaluate_polynomial(C5, z); + + static const T C6[] = { + BOOST_MATH_BIG_CONSTANT(T, 64, 0.000531307936463992223166), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.000592166437353693882865), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.000270878209671804482771), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.790235323266032787212e-6), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.815396936756196875093e-4), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.561168275310624965004e-4), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.183291165828433755673e-4), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.307961345060330478256e-8), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.346515536880360908674e-5), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.20291327396058603727e-5), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.57887928631490037089e-6), + }; + workspace[6] = tools::evaluate_polynomial(C6, z); + + static const T C7[] = { + BOOST_MATH_BIG_CONSTANT(T, 64, 0.000344367606892377671254), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.517179090826059219337e-4), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.000334931610811422363117), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.000281269515476323702274), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.000109765822446847310235), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.127410090954844853795e-6), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.277444515115636441571e-4), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.182634888057113326614e-4), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.578769494973505239894e-5), + }; + workspace[7] = tools::evaluate_polynomial(C7, z); + + static const T C8[] = { + BOOST_MATH_BIG_CONSTANT(T, 64, -0.000652623918595309418922), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.000839498720672087279993), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.000438297098541721005061), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.696909145842055197137e-6), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.000166448466420675478374), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.000127835176797692185853), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.462995326369130429061e-4), + }; + workspace[8] = tools::evaluate_polynomial(C8, z); + + static const T C9[] = { + BOOST_MATH_BIG_CONSTANT(T, 64, -0.000596761290192746250124), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.720489541602001055909e-4), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.000678230883766732836162), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.0006401475260262758451), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.000277501076343287044992), + }; + workspace[9] = tools::evaluate_polynomial(C9, z); + + static const T C10[] = { + BOOST_MATH_BIG_CONSTANT(T, 64, 0.00133244544948006563713), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.0019144384985654775265), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.00110893691345966373396), + }; + workspace[10] = tools::evaluate_polynomial(C10, z); + + static const T C11[] = { + BOOST_MATH_BIG_CONSTANT(T, 64, 0.00157972766073083495909), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.000162516262783915816899), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.00206334210355432762645), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.00213896861856890981541), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.00101085593912630031708), + }; + workspace[11] = tools::evaluate_polynomial(C11, z); + + static const T C12[] = { + BOOST_MATH_BIG_CONSTANT(T, 64, -0.00407251211951401664727), + BOOST_MATH_BIG_CONSTANT(T, 64, 0.00640336283380806979482), + BOOST_MATH_BIG_CONSTANT(T, 64, -0.00404101610816766177474), + }; + workspace[12] = tools::evaluate_polynomial(C12, z); + + T result = tools::evaluate_polynomial<13, T, T>(workspace, 1/a); + result *= exp(-y) / sqrt(2 * constants::pi<T>() * a); + if(x < a) + result = -result; + + result += boost::math::erfc(sqrt(y), pol) / 2; + + return result; +} +// +// This one is accurate for 53-bit mantissa's +// (IEEE double precision or 10^-17). +// +template <class T, class Policy> +T igamma_temme_large(T a, T x, const Policy& pol, mpl::int_<53> const *) +{ + BOOST_MATH_STD_USING // ADL of std functions + T sigma = (x - a) / a; + T phi = -boost::math::log1pmx(sigma, pol); + T y = a * phi; + T z = sqrt(2 * phi); + if(x < a) + z = -z; + + T workspace[10]; + + static const T C0[] = { + static_cast<T>(-0.33333333333333333L), + static_cast<T>(0.083333333333333333L), + static_cast<T>(-0.014814814814814815L), + static_cast<T>(0.0011574074074074074L), + static_cast<T>(0.0003527336860670194L), + static_cast<T>(-0.00017875514403292181L), + static_cast<T>(0.39192631785224378e-4L), + static_cast<T>(-0.21854485106799922e-5L), + static_cast<T>(-0.185406221071516e-5L), + static_cast<T>(0.8296711340953086e-6L), + static_cast<T>(-0.17665952736826079e-6L), + static_cast<T>(0.67078535434014986e-8L), + static_cast<T>(0.10261809784240308e-7L), + static_cast<T>(-0.43820360184533532e-8L), + static_cast<T>(0.91476995822367902e-9L), + }; + workspace[0] = tools::evaluate_polynomial(C0, z); + + static const T C1[] = { + static_cast<T>(-0.0018518518518518519L), + static_cast<T>(-0.0034722222222222222L), + static_cast<T>(0.0026455026455026455L), + static_cast<T>(-0.00099022633744855967L), + static_cast<T>(0.00020576131687242798L), + static_cast<T>(-0.40187757201646091e-6L), + static_cast<T>(-0.18098550334489978e-4L), + static_cast<T>(0.76491609160811101e-5L), + static_cast<T>(-0.16120900894563446e-5L), + static_cast<T>(0.46471278028074343e-8L), + static_cast<T>(0.1378633446915721e-6L), + static_cast<T>(-0.5752545603517705e-7L), + static_cast<T>(0.11951628599778147e-7L), + }; + workspace[1] = tools::evaluate_polynomial(C1, z); + + static const T C2[] = { + static_cast<T>(0.0041335978835978836L), + static_cast<T>(-0.0026813271604938272L), + static_cast<T>(0.00077160493827160494L), + static_cast<T>(0.20093878600823045e-5L), + static_cast<T>(-0.00010736653226365161L), + static_cast<T>(0.52923448829120125e-4L), + static_cast<T>(-0.12760635188618728e-4L), + static_cast<T>(0.34235787340961381e-7L), + static_cast<T>(0.13721957309062933e-5L), + static_cast<T>(-0.6298992138380055e-6L), + static_cast<T>(0.14280614206064242e-6L), + }; + workspace[2] = tools::evaluate_polynomial(C2, z); + + static const T C3[] = { + static_cast<T>(0.00064943415637860082L), + static_cast<T>(0.00022947209362139918L), + static_cast<T>(-0.00046918949439525571L), + static_cast<T>(0.00026772063206283885L), + static_cast<T>(-0.75618016718839764e-4L), + static_cast<T>(-0.23965051138672967e-6L), + static_cast<T>(0.11082654115347302e-4L), + static_cast<T>(-0.56749528269915966e-5L), + static_cast<T>(0.14230900732435884e-5L), + }; + workspace[3] = tools::evaluate_polynomial(C3, z); + + static const T C4[] = { + static_cast<T>(-0.0008618882909167117L), + static_cast<T>(0.00078403922172006663L), + static_cast<T>(-0.00029907248030319018L), + static_cast<T>(-0.14638452578843418e-5L), + static_cast<T>(0.66414982154651222e-4L), + static_cast<T>(-0.39683650471794347e-4L), + static_cast<T>(0.11375726970678419e-4L), + }; + workspace[4] = tools::evaluate_polynomial(C4, z); + + static const T C5[] = { + static_cast<T>(-0.00033679855336635815L), + static_cast<T>(-0.69728137583658578e-4L), + static_cast<T>(0.00027727532449593921L), + static_cast<T>(-0.00019932570516188848L), + static_cast<T>(0.67977804779372078e-4L), + static_cast<T>(0.1419062920643967e-6L), + static_cast<T>(-0.13594048189768693e-4L), + static_cast<T>(0.80184702563342015e-5L), + static_cast<T>(-0.22914811765080952e-5L), + }; + workspace[5] = tools::evaluate_polynomial(C5, z); + + static const T C6[] = { + static_cast<T>(0.00053130793646399222L), + static_cast<T>(-0.00059216643735369388L), + static_cast<T>(0.00027087820967180448L), + static_cast<T>(0.79023532326603279e-6L), + static_cast<T>(-0.81539693675619688e-4L), + static_cast<T>(0.56116827531062497e-4L), + static_cast<T>(-0.18329116582843376e-4L), + }; + workspace[6] = tools::evaluate_polynomial(C6, z); + + static const T C7[] = { + static_cast<T>(0.00034436760689237767L), + static_cast<T>(0.51717909082605922e-4L), + static_cast<T>(-0.00033493161081142236L), + static_cast<T>(0.0002812695154763237L), + static_cast<T>(-0.00010976582244684731L), + }; + workspace[7] = tools::evaluate_polynomial(C7, z); + + static const T C8[] = { + static_cast<T>(-0.00065262391859530942L), + static_cast<T>(0.00083949872067208728L), + static_cast<T>(-0.00043829709854172101L), + }; + workspace[8] = tools::evaluate_polynomial(C8, z); + workspace[9] = static_cast<T>(-0.00059676129019274625L); + + T result = tools::evaluate_polynomial<10, T, T>(workspace, 1/a); + result *= exp(-y) / sqrt(2 * constants::pi<T>() * a); + if(x < a) + result = -result; + + result += boost::math::erfc(sqrt(y), pol) / 2; + + return result; +} +// +// This one is accurate for 24-bit mantissa's +// (IEEE float precision, or 10^-8) +// +template <class T, class Policy> +T igamma_temme_large(T a, T x, const Policy& pol, mpl::int_<24> const *) +{ + BOOST_MATH_STD_USING // ADL of std functions + T sigma = (x - a) / a; + T phi = -boost::math::log1pmx(sigma, pol); + T y = a * phi; + T z = sqrt(2 * phi); + if(x < a) + z = -z; + + T workspace[3]; + + static const T C0[] = { + static_cast<T>(-0.333333333L), + static_cast<T>(0.0833333333L), + static_cast<T>(-0.0148148148L), + static_cast<T>(0.00115740741L), + static_cast<T>(0.000352733686L), + static_cast<T>(-0.000178755144L), + static_cast<T>(0.391926318e-4L), + }; + workspace[0] = tools::evaluate_polynomial(C0, z); + + static const T C1[] = { + static_cast<T>(-0.00185185185L), + static_cast<T>(-0.00347222222L), + static_cast<T>(0.00264550265L), + static_cast<T>(-0.000990226337L), + static_cast<T>(0.000205761317L), + }; + workspace[1] = tools::evaluate_polynomial(C1, z); + + static const T C2[] = { + static_cast<T>(0.00413359788L), + static_cast<T>(-0.00268132716L), + static_cast<T>(0.000771604938L), + }; + workspace[2] = tools::evaluate_polynomial(C2, z); + + T result = tools::evaluate_polynomial(workspace, 1/a); + result *= exp(-y) / sqrt(2 * constants::pi<T>() * a); + if(x < a) + result = -result; + + result += boost::math::erfc(sqrt(y), pol) / 2; + + return result; +} +// +// And finally, a version for 113-bit mantissa's +// (128-bit long doubles, or 10^-34). +// Note this one has been optimised for a > 200 +// It's use for a < 200 is not recomended, that would +// require many more terms in the polynomials. +// +template <class T, class Policy> +T igamma_temme_large(T a, T x, const Policy& pol, mpl::int_<113> const *) +{ + BOOST_MATH_STD_USING // ADL of std functions + T sigma = (x - a) / a; + T phi = -boost::math::log1pmx(sigma, pol); + T y = a * phi; + T z = sqrt(2 * phi); + if(x < a) + z = -z; + + T workspace[14]; + + static const T C0[] = { + BOOST_MATH_BIG_CONSTANT(T, 113, -0.333333333333333333333333333333333333), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.0833333333333333333333333333333333333), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.0148148148148148148148148148148148148), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.00115740740740740740740740740740740741), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.0003527336860670194003527336860670194), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.000178755144032921810699588477366255144), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.391926317852243778169704095630021556e-4), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.218544851067999216147364295512443661e-5), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.185406221071515996070179883622956325e-5), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.829671134095308600501624213166443227e-6), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.17665952736826079304360054245742403e-6), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.670785354340149858036939710029613572e-8), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.102618097842403080425739573227252951e-7), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.438203601845335318655297462244719123e-8), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.914769958223679023418248817633113681e-9), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.255141939949462497668779537993887013e-10), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.583077213255042506746408945040035798e-10), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.243619480206674162436940696707789943e-10), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.502766928011417558909054985925744366e-11), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.110043920319561347708374174497293411e-12), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.337176326240098537882769884169200185e-12), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.13923887224181620659193661848957998e-12), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.285348938070474432039669099052828299e-13), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.513911183424257261899064580300494205e-15), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.197522882943494428353962401580710912e-14), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.809952115670456133407115668702575255e-15), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.165225312163981618191514820265351162e-15), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.253054300974788842327061090060267385e-17), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.116869397385595765888230876507793475e-16), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.477003704982048475822167804084816597e-17), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.969912605905623712420709685898585354e-18), + }; + workspace[0] = tools::evaluate_polynomial(C0, z); + + static const T C1[] = { + BOOST_MATH_BIG_CONSTANT(T, 113, -0.00185185185185185185185185185185185185), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.00347222222222222222222222222222222222), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.0026455026455026455026455026455026455), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.000990226337448559670781893004115226337), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.000205761316872427983539094650205761317), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.401877572016460905349794238683127572e-6), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.180985503344899778370285914867533523e-4), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.76491609160811100846374214980916921e-5), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.16120900894563446003775221882217767e-5), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.464712780280743434226135033938722401e-8), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.137863344691572095931187533077488877e-6), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.575254560351770496402194531835048307e-7), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.119516285997781473243076536699698169e-7), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.175432417197476476237547551202312502e-10), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.100915437106004126274577504686681675e-8), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.416279299184258263623372347219858628e-9), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.856390702649298063807431562579670208e-10), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.606721510160475861512701762169919581e-13), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.716249896481148539007961017165545733e-11), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.293318664377143711740636683615595403e-11), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.599669636568368872330374527568788909e-12), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.216717865273233141017100472779701734e-15), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.497833997236926164052815522048108548e-13), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.202916288237134247736694804325894226e-13), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.413125571381061004935108332558187111e-14), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.828651623988309644380188591057589316e-18), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.341003088693333279336339355910600992e-15), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.138541953028939715357034547426313703e-15), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.281234665322887466568860332727259483e-16), + }; + workspace[1] = tools::evaluate_polynomial(C1, z); + + static const T C2[] = { + BOOST_MATH_BIG_CONSTANT(T, 113, 0.0041335978835978835978835978835978836), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.00268132716049382716049382716049382716), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.000771604938271604938271604938271604938), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.200938786008230452674897119341563786e-5), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.000107366532263651605215391223621676297), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.529234488291201254164217127180090143e-4), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.127606351886187277133779191392360117e-4), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.34235787340961380741902003904747389e-7), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.137219573090629332055943852926020279e-5), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.629899213838005502290672234278391876e-6), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.142806142060642417915846008822771748e-6), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.204770984219908660149195854409200226e-9), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.140925299108675210532930244154315272e-7), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.622897408492202203356394293530327112e-8), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.136704883966171134992724380284402402e-8), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.942835615901467819547711211663208075e-12), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.128722524000893180595479368872770442e-9), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.556459561343633211465414765894951439e-10), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.119759355463669810035898150310311343e-10), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.416897822518386350403836626692480096e-14), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.109406404278845944099299008640802908e-11), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.4662239946390135746326204922464679e-12), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.990510576390690597844122258212382301e-13), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.189318767683735145056885183170630169e-16), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.885922187259112726176031067028740667e-14), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.373782039804640545306560251777191937e-14), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.786883363903515525774088394065960751e-15), + }; + workspace[2] = tools::evaluate_polynomial(C2, z); + + static const T C3[] = { + BOOST_MATH_BIG_CONSTANT(T, 113, 0.000649434156378600823045267489711934156), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.000229472093621399176954732510288065844), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.000469189494395255712128140111679206329), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.000267720632062838852962309752433209223), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.756180167188397641072538191879755666e-4), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.239650511386729665193314027333231723e-6), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.110826541153473023614770299726861227e-4), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.567495282699159656749963105701560205e-5), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.14230900732435883914551894470580433e-5), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.278610802915281422405802158211174452e-10), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.16958404091930277289864168795820267e-6), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.809946490538808236335278504852724081e-7), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.191111684859736540606728140872727635e-7), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.239286204398081179686413514022282056e-11), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.206201318154887984369925818486654549e-8), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.946049666185513217375417988510192814e-9), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.215410497757749078380130268468744512e-9), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.138882333681390304603424682490735291e-13), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.218947616819639394064123400466489455e-10), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.979099895117168512568262802255883368e-11), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.217821918801809621153859472011393244e-11), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.62088195734079014258166361684972205e-16), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.212697836327973697696702537114614471e-12), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.934468879151743333127396765626749473e-13), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.204536712267828493249215913063207436e-13), + }; + workspace[3] = tools::evaluate_polynomial(C3, z); + + static const T C4[] = { + BOOST_MATH_BIG_CONSTANT(T, 113, -0.000861888290916711698604702719929057378), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.00078403922172006662747403488144228885), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.000299072480303190179733389609932819809), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.146384525788434181781232535690697556e-5), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.664149821546512218665853782451862013e-4), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.396836504717943466443123507595386882e-4), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.113757269706784190980552042885831759e-4), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.250749722623753280165221942390057007e-9), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.169541495365583060147164356781525752e-5), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.890750753220530968882898422505515924e-6), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.229293483400080487057216364891158518e-6), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.295679413754404904696572852500004588e-10), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.288658297427087836297341274604184504e-7), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.141897394378032193894774303903982717e-7), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.344635804994648970659527720474194356e-8), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.230245171745280671320192735850147087e-12), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.394092330280464052750697640085291799e-9), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.186023389685045019134258533045185639e-9), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.435632300505661804380678327446262424e-10), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.127860010162962312660550463349930726e-14), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.467927502665791946200382739991760062e-11), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.214924647061348285410535341910721086e-11), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.490881561480965216323649688463984082e-12), + }; + workspace[4] = tools::evaluate_polynomial(C4, z); + + static const T C5[] = { + BOOST_MATH_BIG_CONSTANT(T, 113, -0.000336798553366358150308767592718210002), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.697281375836585777429398828575783308e-4), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.00027727532449593920787336425196507501), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.000199325705161888477003360405280844238), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.679778047793720783881640176604435742e-4), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.141906292064396701483392727105575757e-6), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.135940481897686932784583938837504469e-4), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.80184702563342015397192571980419684e-5), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.229148117650809517038048790128781806e-5), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.325247355129845395166230137750005047e-9), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.346528464910852649559195496827579815e-6), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.184471871911713432765322367374920978e-6), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.482409670378941807563762631738989002e-7), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.179894667217435153025754291716644314e-13), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.630619450001352343517516981425944698e-8), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.316241762877456793773762181540969623e-8), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.784092425369742929000839303523267545e-9), + }; + workspace[5] = tools::evaluate_polynomial(C5, z); + + static const T C6[] = { + BOOST_MATH_BIG_CONSTANT(T, 113, 0.00053130793646399222316574854297762391), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.000592166437353693882864836225604401187), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.000270878209671804482771279183488328692), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.790235323266032787212032944390816666e-6), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.815396936756196875092890088464682624e-4), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.561168275310624965003775619041471695e-4), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.183291165828433755673259749374098313e-4), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.307961345060330478256414192546677006e-8), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.346515536880360908673728529745376913e-5), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.202913273960586037269527254582695285e-5), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.578879286314900370889997586203187687e-6), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.233863067382665698933480579231637609e-12), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.88286007463304835250508524317926246e-7), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.474359588804081278032150770595852426e-7), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.125454150207103824457130611214783073e-7), + }; + workspace[6] = tools::evaluate_polynomial(C6, z); + + static const T C7[] = { + BOOST_MATH_BIG_CONSTANT(T, 113, 0.000344367606892377671254279625108523655), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.517179090826059219337057843002058823e-4), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.000334931610811422363116635090580012327), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.000281269515476323702273722110707777978), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.000109765822446847310235396824500789005), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.127410090954844853794579954588107623e-6), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.277444515115636441570715073933712622e-4), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.182634888057113326614324442681892723e-4), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.578769494973505239894178121070843383e-5), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.493875893393627039981813418398565502e-9), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.105953670140260427338098566209633945e-5), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.616671437611040747858836254004890765e-6), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.175629733590604619378669693914265388e-6), + }; + workspace[7] = tools::evaluate_polynomial(C7, z); + + static const T C8[] = { + BOOST_MATH_BIG_CONSTANT(T, 113, -0.000652623918595309418922034919726622692), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.000839498720672087279993357516764983445), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.000438297098541721005061087953050560377), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.696909145842055197136911097362072702e-6), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.00016644846642067547837384572662326101), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.000127835176797692185853344001461664247), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.462995326369130429061361032704489636e-4), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.455790986792270771162749294232219616e-8), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.105952711258051954718238500312872328e-4), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.678334290486516662273073740749269432e-5), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.210754766662588042469972680229376445e-5), + }; + workspace[8] = tools::evaluate_polynomial(C8, z); + + static const T C9[] = { + BOOST_MATH_BIG_CONSTANT(T, 113, -0.000596761290192746250124390067179459605), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.720489541602001055908571930225015052e-4), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.000678230883766732836161951166000673426), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.000640147526026275845100045652582354779), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.000277501076343287044992374518205845463), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.181970083804651510461686554030325202e-6), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.847950711706850318239732559632810086e-4), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.610519208250153101764709122740859458e-4), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.210739201834048624082975255893773306e-4), + }; + workspace[9] = tools::evaluate_polynomial(C9, z); + + static const T C10[] = { + BOOST_MATH_BIG_CONSTANT(T, 113, 0.00133244544948006563712694993432717968), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.00191443849856547752650089885832852254), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.0011089369134596637339607446329267522), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.993240412264229896742295262075817566e-6), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.000508745012930931989848393025305956774), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.00042735056665392884328432271160040444), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.000168588537679107988033552814662382059), + }; + workspace[10] = tools::evaluate_polynomial(C10, z); + + static const T C11[] = { + BOOST_MATH_BIG_CONSTANT(T, 113, 0.00157972766073083495908785631307733022), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.000162516262783915816898635123980270998), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.00206334210355432762645284467690276817), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.00213896861856890981541061922797693947), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.00101085593912630031708085801712479376), + }; + workspace[11] = tools::evaluate_polynomial(C11, z); + + static const T C12[] = { + BOOST_MATH_BIG_CONSTANT(T, 113, -0.00407251211951401664727281097914544601), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.00640336283380806979482363809026579583), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.00404101610816766177473974858518094879), + }; + workspace[12] = tools::evaluate_polynomial(C12, z); + workspace[13] = -0.0059475779383993002845382844736066323L; + + T result = tools::evaluate_polynomial(workspace, T(1/a)); + result *= exp(-y) / sqrt(2 * constants::pi<T>() * a); + if(x < a) + result = -result; + + result += boost::math::erfc(sqrt(y), pol) / 2; + + return result; +} + +} // namespace detail +} // namespace math +} // namespace math + + +#endif // BOOST_MATH_DETAIL_IGAMMA_LARGE + diff --git a/src/third_party/boost-1.70.0/boost/math/special_functions/detail/lanczos_sse2.hpp b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/lanczos_sse2.hpp new file mode 100644 index 00000000000..df1a047435d --- /dev/null +++ b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/lanczos_sse2.hpp @@ -0,0 +1,220 @@ +// (C) Copyright John Maddock 2006. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_SPECIAL_FUNCTIONS_LANCZOS_SSE2 +#define BOOST_MATH_SPECIAL_FUNCTIONS_LANCZOS_SSE2 + +#ifdef _MSC_VER +#pragma once +#endif + +#include <emmintrin.h> + +#if defined(__GNUC__) || defined(__PGI) || defined(__SUNPRO_CC) +#define ALIGN16 __attribute__((__aligned__(16))) +#else +#define ALIGN16 __declspec(align(16)) +#endif + +namespace boost{ namespace math{ namespace lanczos{ + +template <> +inline double lanczos13m53::lanczos_sum<double>(const double& x) +{ + static const ALIGN16 double coeff[26] = { + static_cast<double>(2.506628274631000270164908177133837338626L), + static_cast<double>(1u), + static_cast<double>(210.8242777515793458725097339207133627117L), + static_cast<double>(66u), + static_cast<double>(8071.672002365816210638002902272250613822L), + static_cast<double>(1925u), + static_cast<double>(186056.2653952234950402949897160456992822L), + static_cast<double>(32670u), + static_cast<double>(2876370.628935372441225409051620849613599L), + static_cast<double>(357423u), + static_cast<double>(31426415.58540019438061423162831820536287L), + static_cast<double>(2637558u), + static_cast<double>(248874557.8620541565114603864132294232163L), + static_cast<double>(13339535u), + static_cast<double>(1439720407.311721673663223072794912393972L), + static_cast<double>(45995730u), + static_cast<double>(6039542586.35202800506429164430729792107L), + static_cast<double>(105258076u), + static_cast<double>(17921034426.03720969991975575445893111267L), + static_cast<double>(150917976u), + static_cast<double>(35711959237.35566804944018545154716670596L), + static_cast<double>(120543840u), + static_cast<double>(42919803642.64909876895789904700198885093L), + static_cast<double>(39916800u), + static_cast<double>(23531376880.41075968857200767445163675473L), + static_cast<double>(0u) + }; + __m128d vx = _mm_load1_pd(&x); + __m128d sum_even = _mm_load_pd(coeff); + __m128d sum_odd = _mm_load_pd(coeff+2); + __m128d nc_odd, nc_even; + __m128d vx2 = _mm_mul_pd(vx, vx); + + sum_even = _mm_mul_pd(sum_even, vx2); + nc_even = _mm_load_pd(coeff + 4); + sum_odd = _mm_mul_pd(sum_odd, vx2); + nc_odd = _mm_load_pd(coeff + 6); + sum_even = _mm_add_pd(sum_even, nc_even); + sum_odd = _mm_add_pd(sum_odd, nc_odd); + + sum_even = _mm_mul_pd(sum_even, vx2); + nc_even = _mm_load_pd(coeff + 8); + sum_odd = _mm_mul_pd(sum_odd, vx2); + nc_odd = _mm_load_pd(coeff + 10); + sum_even = _mm_add_pd(sum_even, nc_even); + sum_odd = _mm_add_pd(sum_odd, nc_odd); + + sum_even = _mm_mul_pd(sum_even, vx2); + nc_even = _mm_load_pd(coeff + 12); + sum_odd = _mm_mul_pd(sum_odd, vx2); + nc_odd = _mm_load_pd(coeff + 14); + sum_even = _mm_add_pd(sum_even, nc_even); + sum_odd = _mm_add_pd(sum_odd, nc_odd); + + sum_even = _mm_mul_pd(sum_even, vx2); + nc_even = _mm_load_pd(coeff + 16); + sum_odd = _mm_mul_pd(sum_odd, vx2); + nc_odd = _mm_load_pd(coeff + 18); + sum_even = _mm_add_pd(sum_even, nc_even); + sum_odd = _mm_add_pd(sum_odd, nc_odd); + + sum_even = _mm_mul_pd(sum_even, vx2); + nc_even = _mm_load_pd(coeff + 20); + sum_odd = _mm_mul_pd(sum_odd, vx2); + nc_odd = _mm_load_pd(coeff + 22); + sum_even = _mm_add_pd(sum_even, nc_even); + sum_odd = _mm_add_pd(sum_odd, nc_odd); + + sum_even = _mm_mul_pd(sum_even, vx2); + nc_even = _mm_load_pd(coeff + 24); + sum_odd = _mm_mul_pd(sum_odd, vx); + sum_even = _mm_add_pd(sum_even, nc_even); + sum_even = _mm_add_pd(sum_even, sum_odd); + + + double ALIGN16 t[2]; + _mm_store_pd(t, sum_even); + + return t[0] / t[1]; +} + +template <> +inline double lanczos13m53::lanczos_sum_expG_scaled<double>(const double& x) +{ + static const ALIGN16 double coeff[26] = { + static_cast<double>(0.006061842346248906525783753964555936883222L), + static_cast<double>(1u), + static_cast<double>(0.5098416655656676188125178644804694509993L), + static_cast<double>(66u), + static_cast<double>(19.51992788247617482847860966235652136208L), + static_cast<double>(1925u), + static_cast<double>(449.9445569063168119446858607650988409623L), + static_cast<double>(32670u), + static_cast<double>(6955.999602515376140356310115515198987526L), + static_cast<double>(357423u), + static_cast<double>(75999.29304014542649875303443598909137092L), + static_cast<double>(2637558u), + static_cast<double>(601859.6171681098786670226533699352302507L), + static_cast<double>(13339535u), + static_cast<double>(3481712.15498064590882071018964774556468L), + static_cast<double>(45995730u), + static_cast<double>(14605578.08768506808414169982791359218571L), + static_cast<double>(105258076u), + static_cast<double>(43338889.32467613834773723740590533316085L), + static_cast<double>(150917976u), + static_cast<double>(86363131.28813859145546927288977868422342L), + static_cast<double>(120543840u), + static_cast<double>(103794043.1163445451906271053616070238554L), + static_cast<double>(39916800u), + static_cast<double>(56906521.91347156388090791033559122686859L), + static_cast<double>(0u) + }; + __m128d vx = _mm_load1_pd(&x); + __m128d sum_even = _mm_load_pd(coeff); + __m128d sum_odd = _mm_load_pd(coeff+2); + __m128d nc_odd, nc_even; + __m128d vx2 = _mm_mul_pd(vx, vx); + + sum_even = _mm_mul_pd(sum_even, vx2); + nc_even = _mm_load_pd(coeff + 4); + sum_odd = _mm_mul_pd(sum_odd, vx2); + nc_odd = _mm_load_pd(coeff + 6); + sum_even = _mm_add_pd(sum_even, nc_even); + sum_odd = _mm_add_pd(sum_odd, nc_odd); + + sum_even = _mm_mul_pd(sum_even, vx2); + nc_even = _mm_load_pd(coeff + 8); + sum_odd = _mm_mul_pd(sum_odd, vx2); + nc_odd = _mm_load_pd(coeff + 10); + sum_even = _mm_add_pd(sum_even, nc_even); + sum_odd = _mm_add_pd(sum_odd, nc_odd); + + sum_even = _mm_mul_pd(sum_even, vx2); + nc_even = _mm_load_pd(coeff + 12); + sum_odd = _mm_mul_pd(sum_odd, vx2); + nc_odd = _mm_load_pd(coeff + 14); + sum_even = _mm_add_pd(sum_even, nc_even); + sum_odd = _mm_add_pd(sum_odd, nc_odd); + + sum_even = _mm_mul_pd(sum_even, vx2); + nc_even = _mm_load_pd(coeff + 16); + sum_odd = _mm_mul_pd(sum_odd, vx2); + nc_odd = _mm_load_pd(coeff + 18); + sum_even = _mm_add_pd(sum_even, nc_even); + sum_odd = _mm_add_pd(sum_odd, nc_odd); + + sum_even = _mm_mul_pd(sum_even, vx2); + nc_even = _mm_load_pd(coeff + 20); + sum_odd = _mm_mul_pd(sum_odd, vx2); + nc_odd = _mm_load_pd(coeff + 22); + sum_even = _mm_add_pd(sum_even, nc_even); + sum_odd = _mm_add_pd(sum_odd, nc_odd); + + sum_even = _mm_mul_pd(sum_even, vx2); + nc_even = _mm_load_pd(coeff + 24); + sum_odd = _mm_mul_pd(sum_odd, vx); + sum_even = _mm_add_pd(sum_even, nc_even); + sum_even = _mm_add_pd(sum_even, sum_odd); + + + double ALIGN16 t[2]; + _mm_store_pd(t, sum_even); + + return t[0] / t[1]; +} + +#ifdef _MSC_VER + +BOOST_STATIC_ASSERT(sizeof(double) == sizeof(long double)); + +template <> +inline long double lanczos13m53::lanczos_sum<long double>(const long double& x) +{ + return lanczos_sum<double>(static_cast<double>(x)); +} +template <> +inline long double lanczos13m53::lanczos_sum_expG_scaled<long double>(const long double& x) +{ + return lanczos_sum_expG_scaled<double>(static_cast<double>(x)); +} +#endif + +} // namespace lanczos +} // namespace math +} // namespace boost + +#undef ALIGN16 + +#endif // BOOST_MATH_SPECIAL_FUNCTIONS_LANCZOS + + + + + diff --git a/src/third_party/boost-1.70.0/boost/math/special_functions/detail/lgamma_small.hpp b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/lgamma_small.hpp new file mode 100644 index 00000000000..f4012d836b8 --- /dev/null +++ b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/lgamma_small.hpp @@ -0,0 +1,532 @@ +// (C) Copyright John Maddock 2006. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_SPECIAL_FUNCTIONS_DETAIL_LGAMMA_SMALL +#define BOOST_MATH_SPECIAL_FUNCTIONS_DETAIL_LGAMMA_SMALL + +#ifdef _MSC_VER +#pragma once +#endif + +#include <boost/math/tools/big_constant.hpp> + +#if defined(__GNUC__) && defined(BOOST_MATH_USE_FLOAT128) +// +// This is the only way we can avoid +// warning: non-standard suffix on floating constant [-Wpedantic] +// when building with -Wall -pedantic. Neither __extension__ +// nor #pragma dianostic ignored work :( +// +#pragma GCC system_header +#endif + +namespace boost{ namespace math{ namespace detail{ + +// +// These need forward declaring to keep GCC happy: +// +template <class T, class Policy, class Lanczos> +T gamma_imp(T z, const Policy& pol, const Lanczos& l); +template <class T, class Policy> +T gamma_imp(T z, const Policy& pol, const lanczos::undefined_lanczos& l); + +// +// lgamma for small arguments: +// +template <class T, class Policy, class Lanczos> +T lgamma_small_imp(T z, T zm1, T zm2, const mpl::int_<64>&, const Policy& /* l */, const Lanczos&) +{ + // This version uses rational approximations for small + // values of z accurate enough for 64-bit mantissas + // (80-bit long doubles), works well for 53-bit doubles as well. + // Lanczos is only used to select the Lanczos function. + + BOOST_MATH_STD_USING // for ADL of std names + T result = 0; + if(z < tools::epsilon<T>()) + { + result = -log(z); + } + else if((zm1 == 0) || (zm2 == 0)) + { + // nothing to do, result is zero.... + } + else if(z > 2) + { + // + // Begin by performing argument reduction until + // z is in [2,3): + // + if(z >= 3) + { + do + { + z -= 1; + zm2 -= 1; + result += log(z); + }while(z >= 3); + // Update zm2, we need it below: + zm2 = z - 2; + } + + // + // Use the following form: + // + // lgamma(z) = (z-2)(z+1)(Y + R(z-2)) + // + // where R(z-2) is a rational approximation optimised for + // low absolute error - as long as it's absolute error + // is small compared to the constant Y - then any rounding + // error in it's computation will get wiped out. + // + // R(z-2) has the following properties: + // + // At double: Max error found: 4.231e-18 + // At long double: Max error found: 1.987e-21 + // Maximum Deviation Found (approximation error): 5.900e-24 + // + static const T P[] = { + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -0.180355685678449379109e-1)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.25126649619989678683e-1)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.494103151567532234274e-1)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.172491608709613993966e-1)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -0.259453563205438108893e-3)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -0.541009869215204396339e-3)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -0.324588649825948492091e-4)) + }; + static const T Q[] = { + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.1e1)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.196202987197795200688e1)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.148019669424231326694e1)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.541391432071720958364e0)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.988504251128010129477e-1)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.82130967464889339326e-2)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.224936291922115757597e-3)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -0.223352763208617092964e-6)) + }; + + static const float Y = 0.158963680267333984375e0f; + + T r = zm2 * (z + 1); + T R = tools::evaluate_polynomial(P, zm2); + R /= tools::evaluate_polynomial(Q, zm2); + + result += r * Y + r * R; + } + else + { + // + // If z is less than 1 use recurrance to shift to + // z in the interval [1,2]: + // + if(z < 1) + { + result += -log(z); + zm2 = zm1; + zm1 = z; + z += 1; + } + // + // Two approximations, on for z in [1,1.5] and + // one for z in [1.5,2]: + // + if(z <= 1.5) + { + // + // Use the following form: + // + // lgamma(z) = (z-1)(z-2)(Y + R(z-1)) + // + // where R(z-1) is a rational approximation optimised for + // low absolute error - as long as it's absolute error + // is small compared to the constant Y - then any rounding + // error in it's computation will get wiped out. + // + // R(z-1) has the following properties: + // + // At double precision: Max error found: 1.230011e-17 + // At 80-bit long double precision: Max error found: 5.631355e-21 + // Maximum Deviation Found: 3.139e-021 + // Expected Error Term: 3.139e-021 + + // + static const float Y = 0.52815341949462890625f; + + static const T P[] = { + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.490622454069039543534e-1)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -0.969117530159521214579e-1)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -0.414983358359495381969e0)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -0.406567124211938417342e0)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -0.158413586390692192217e0)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -0.240149820648571559892e-1)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -0.100346687696279557415e-2)) + }; + static const T Q[] = { + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.1e1)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.302349829846463038743e1)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.348739585360723852576e1)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.191415588274426679201e1)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.507137738614363510846e0)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.577039722690451849648e-1)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.195768102601107189171e-2)) + }; + + T r = tools::evaluate_polynomial(P, zm1) / tools::evaluate_polynomial(Q, zm1); + T prefix = zm1 * zm2; + + result += prefix * Y + prefix * r; + } + else + { + // + // Use the following form: + // + // lgamma(z) = (2-z)(1-z)(Y + R(2-z)) + // + // where R(2-z) is a rational approximation optimised for + // low absolute error - as long as it's absolute error + // is small compared to the constant Y - then any rounding + // error in it's computation will get wiped out. + // + // R(2-z) has the following properties: + // + // At double precision, max error found: 1.797565e-17 + // At 80-bit long double precision, max error found: 9.306419e-21 + // Maximum Deviation Found: 2.151e-021 + // Expected Error Term: 2.150e-021 + // + static const float Y = 0.452017307281494140625f; + + static const T P[] = { + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -0.292329721830270012337e-1)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.144216267757192309184e0)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -0.142440390738631274135e0)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.542809694055053558157e-1)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -0.850535976868336437746e-2)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.431171342679297331241e-3)) + }; + static const T Q[] = { + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.1e1)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -0.150169356054485044494e1)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.846973248876495016101e0)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -0.220095151814995745555e0)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.25582797155975869989e-1)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -0.100666795539143372762e-2)), + static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -0.827193521891290553639e-6)) + }; + T r = zm2 * zm1; + T R = tools::evaluate_polynomial(P, T(-zm2)) / tools::evaluate_polynomial(Q, T(-zm2)); + + result += r * Y + r * R; + } + } + return result; +} +template <class T, class Policy, class Lanczos> +T lgamma_small_imp(T z, T zm1, T zm2, const mpl::int_<113>&, const Policy& /* l */, const Lanczos&) +{ + // + // This version uses rational approximations for small + // values of z accurate enough for 113-bit mantissas + // (128-bit long doubles). + // + BOOST_MATH_STD_USING // for ADL of std names + T result = 0; + if(z < tools::epsilon<T>()) + { + result = -log(z); + BOOST_MATH_INSTRUMENT_CODE(result); + } + else if((zm1 == 0) || (zm2 == 0)) + { + // nothing to do, result is zero.... + } + else if(z > 2) + { + // + // Begin by performing argument reduction until + // z is in [2,3): + // + if(z >= 3) + { + do + { + z -= 1; + result += log(z); + }while(z >= 3); + zm2 = z - 2; + } + BOOST_MATH_INSTRUMENT_CODE(zm2); + BOOST_MATH_INSTRUMENT_CODE(z); + BOOST_MATH_INSTRUMENT_CODE(result); + + // + // Use the following form: + // + // lgamma(z) = (z-2)(z+1)(Y + R(z-2)) + // + // where R(z-2) is a rational approximation optimised for + // low absolute error - as long as it's absolute error + // is small compared to the constant Y - then any rounding + // error in it's computation will get wiped out. + // + // Maximum Deviation Found (approximation error) 3.73e-37 + + static const T P[] = { + BOOST_MATH_BIG_CONSTANT(T, 113, -0.018035568567844937910504030027467476655), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.013841458273109517271750705401202404195), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.062031842739486600078866923383017722399), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.052518418329052161202007865149435256093), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.01881718142472784129191838493267755758), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.0025104830367021839316463675028524702846), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.00021043176101831873281848891452678568311), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.00010249622350908722793327719494037981166), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.11381479670982006841716879074288176994e-4), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.49999811718089980992888533630523892389e-6), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.70529798686542184668416911331718963364e-8) + }; + static const T Q[] = { + BOOST_MATH_BIG_CONSTANT(T, 113, 1.0), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.5877485070422317542808137697939233685), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.8797959228352591788629602533153837126), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.8030885955284082026405495275461180977), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.69774331297747390169238306148355428436), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.17261566063277623942044077039756583802), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.02729301254544230229429621192443000121), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.0026776425891195270663133581960016620433), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.00015244249160486584591370355730402168106), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.43997034032479866020546814475414346627e-5), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.46295080708455613044541885534408170934e-7), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.93326638207459533682980757982834180952e-11), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.42316456553164995177177407325292867513e-13) + }; + + T R = tools::evaluate_polynomial(P, zm2); + R /= tools::evaluate_polynomial(Q, zm2); + + static const float Y = 0.158963680267333984375F; + + T r = zm2 * (z + 1); + + result += r * Y + r * R; + BOOST_MATH_INSTRUMENT_CODE(result); + } + else + { + // + // If z is less than 1 use recurrance to shift to + // z in the interval [1,2]: + // + if(z < 1) + { + result += -log(z); + zm2 = zm1; + zm1 = z; + z += 1; + } + BOOST_MATH_INSTRUMENT_CODE(result); + BOOST_MATH_INSTRUMENT_CODE(z); + BOOST_MATH_INSTRUMENT_CODE(zm2); + // + // Three approximations, on for z in [1,1.35], [1.35,1.625] and [1.625,1] + // + if(z <= 1.35) + { + // + // Use the following form: + // + // lgamma(z) = (z-1)(z-2)(Y + R(z-1)) + // + // where R(z-1) is a rational approximation optimised for + // low absolute error - as long as it's absolute error + // is small compared to the constant Y - then any rounding + // error in it's computation will get wiped out. + // + // R(z-1) has the following properties: + // + // Maximum Deviation Found (approximation error) 1.659e-36 + // Expected Error Term (theoretical error) 1.343e-36 + // Max error found at 128-bit long double precision 1.007e-35 + // + static const float Y = 0.54076099395751953125f; + + static const T P[] = { + BOOST_MATH_BIG_CONSTANT(T, 113, 0.036454670944013329356512090082402429697), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.066235835556476033710068679907798799959), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.67492399795577182387312206593595565371), + BOOST_MATH_BIG_CONSTANT(T, 113, -1.4345555263962411429855341651960000166), + BOOST_MATH_BIG_CONSTANT(T, 113, -1.4894319559821365820516771951249649563), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.87210277668067964629483299712322411566), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.29602090537771744401524080430529369136), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.0561832587517836908929331992218879676), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.0053236785487328044334381502530383140443), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.00018629360291358130461736386077971890789), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.10164985672213178500790406939467614498e-6), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.13680157145361387405588201461036338274e-8) + }; + static const T Q[] = { + BOOST_MATH_BIG_CONSTANT(T, 113, 1.0), + BOOST_MATH_BIG_CONSTANT(T, 113, 4.9106336261005990534095838574132225599), + BOOST_MATH_BIG_CONSTANT(T, 113, 10.258804800866438510889341082793078432), + BOOST_MATH_BIG_CONSTANT(T, 113, 11.88588976846826108836629960537466889), + BOOST_MATH_BIG_CONSTANT(T, 113, 8.3455000546999704314454891036700998428), + BOOST_MATH_BIG_CONSTANT(T, 113, 3.6428823682421746343233362007194282703), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.97465989807254572142266753052776132252), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.15121052897097822172763084966793352524), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.012017363555383555123769849654484594893), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.0003583032812720649835431669893011257277) + }; + + T r = tools::evaluate_polynomial(P, zm1) / tools::evaluate_polynomial(Q, zm1); + T prefix = zm1 * zm2; + + result += prefix * Y + prefix * r; + BOOST_MATH_INSTRUMENT_CODE(result); + } + else if(z <= 1.625) + { + // + // Use the following form: + // + // lgamma(z) = (2-z)(1-z)(Y + R(2-z)) + // + // where R(2-z) is a rational approximation optimised for + // low absolute error - as long as it's absolute error + // is small compared to the constant Y - then any rounding + // error in it's computation will get wiped out. + // + // R(2-z) has the following properties: + // + // Max error found at 128-bit long double precision 9.634e-36 + // Maximum Deviation Found (approximation error) 1.538e-37 + // Expected Error Term (theoretical error) 2.350e-38 + // + static const float Y = 0.483787059783935546875f; + + static const T P[] = { + BOOST_MATH_BIG_CONSTANT(T, 113, -0.017977422421608624353488126610933005432), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.18484528905298309555089509029244135703), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.40401251514859546989565001431430884082), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.40277179799147356461954182877921388182), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.21993421441282936476709677700477598816), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.069595742223850248095697771331107571011), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.012681481427699686635516772923547347328), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.0012489322866834830413292771335113136034), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.57058739515423112045108068834668269608e-4), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.8207548771933585614380644961342925976e-6) + }; + static const T Q[] = { + BOOST_MATH_BIG_CONSTANT(T, 113, 1.0), + BOOST_MATH_BIG_CONSTANT(T, 113, -2.9629552288944259229543137757200262073), + BOOST_MATH_BIG_CONSTANT(T, 113, 3.7118380799042118987185957298964772755), + BOOST_MATH_BIG_CONSTANT(T, 113, -2.5569815272165399297600586376727357187), + BOOST_MATH_BIG_CONSTANT(T, 113, 1.0546764918220835097855665680632153367), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.26574021300894401276478730940980810831), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.03996289731752081380552901986471233462), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.0033398680924544836817826046380586480873), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.00013288854760548251757651556792598235735), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.17194794958274081373243161848194745111e-5) + }; + T r = zm2 * zm1; + T R = tools::evaluate_polynomial(P, T(0.625 - zm1)) / tools::evaluate_polynomial(Q, T(0.625 - zm1)); + + result += r * Y + r * R; + BOOST_MATH_INSTRUMENT_CODE(result); + } + else + { + // + // Same form as above. + // + // Max error found (at 128-bit long double precision) 1.831e-35 + // Maximum Deviation Found (approximation error) 8.588e-36 + // Expected Error Term (theoretical error) 1.458e-36 + // + static const float Y = 0.443811893463134765625f; + + static const T P[] = { + BOOST_MATH_BIG_CONSTANT(T, 113, -0.021027558364667626231512090082402429494), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.15128811104498736604523586803722368377), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.26249631480066246699388544451126410278), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.21148748610533489823742352180628489742), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.093964130697489071999873506148104370633), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.024292059227009051652542804957550866827), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.0036284453226534839926304745756906117066), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.0002939230129315195346843036254392485984), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.11088589183158123733132268042570710338e-4), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.13240510580220763969511741896361984162e-6) + }; + static const T Q[] = { + BOOST_MATH_BIG_CONSTANT(T, 113, 1.0), + BOOST_MATH_BIG_CONSTANT(T, 113, -2.4240003754444040525462170802796471996), + BOOST_MATH_BIG_CONSTANT(T, 113, 2.4868383476933178722203278602342786002), + BOOST_MATH_BIG_CONSTANT(T, 113, -1.4047068395206343375520721509193698547), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.47583809087867443858344765659065773369), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.09865724264554556400463655444270700132), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.012238223514176587501074150988445109735), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.00084625068418239194670614419707491797097), + BOOST_MATH_BIG_CONSTANT(T, 113, 0.2796574430456237061420839429225710602e-4), + BOOST_MATH_BIG_CONSTANT(T, 113, -0.30202973883316730694433702165188835331e-6) + }; + // (2 - x) * (1 - x) * (c + R(2 - x)) + T r = zm2 * zm1; + T R = tools::evaluate_polynomial(P, T(-zm2)) / tools::evaluate_polynomial(Q, T(-zm2)); + + result += r * Y + r * R; + BOOST_MATH_INSTRUMENT_CODE(result); + } + } + BOOST_MATH_INSTRUMENT_CODE(result); + return result; +} +template <class T, class Policy, class Lanczos> +T lgamma_small_imp(T z, T zm1, T zm2, const mpl::int_<0>&, const Policy& pol, const Lanczos&) +{ + // + // No rational approximations are available because either + // T has no numeric_limits support (so we can't tell how + // many digits it has), or T has more digits than we know + // what to do with.... we do have a Lanczos approximation + // though, and that can be used to keep errors under control. + // + BOOST_MATH_STD_USING // for ADL of std names + T result = 0; + if(z < tools::epsilon<T>()) + { + result = -log(z); + } + else if(z < 0.5) + { + // taking the log of tgamma reduces the error, no danger of overflow here: + result = log(gamma_imp(z, pol, Lanczos())); + } + else if(z >= 3) + { + // taking the log of tgamma reduces the error, no danger of overflow here: + result = log(gamma_imp(z, pol, Lanczos())); + } + else if(z >= 1.5) + { + // special case near 2: + T dz = zm2; + result = dz * log((z + Lanczos::g() - T(0.5)) / boost::math::constants::e<T>()); + result += boost::math::log1p(dz / (Lanczos::g() + T(1.5)), pol) * T(1.5); + result += boost::math::log1p(Lanczos::lanczos_sum_near_2(dz), pol); + } + else + { + // special case near 1: + T dz = zm1; + result = dz * log((z + Lanczos::g() - T(0.5)) / boost::math::constants::e<T>()); + result += boost::math::log1p(dz / (Lanczos::g() + T(0.5)), pol) / 2; + result += boost::math::log1p(Lanczos::lanczos_sum_near_1(dz), pol); + } + return result; +} + +}}} // namespaces + +#endif // BOOST_MATH_SPECIAL_FUNCTIONS_DETAIL_LGAMMA_SMALL + diff --git a/src/third_party/boost-1.70.0/boost/math/special_functions/detail/round_fwd.hpp b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/round_fwd.hpp new file mode 100644 index 00000000000..8c45a7d75a4 --- /dev/null +++ b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/round_fwd.hpp @@ -0,0 +1,93 @@ +// Copyright John Maddock 2008. + +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_SPECIAL_ROUND_FWD_HPP +#define BOOST_MATH_SPECIAL_ROUND_FWD_HPP + +#include <boost/config.hpp> +#include <boost/math/tools/promotion.hpp> + +#ifdef _MSC_VER +#pragma once +#endif + +namespace boost +{ + namespace math + { + + template <class T, class Policy> + typename tools::promote_args<T>::type trunc(const T& v, const Policy& pol); + template <class T> + typename tools::promote_args<T>::type trunc(const T& v); + template <class T, class Policy> + int itrunc(const T& v, const Policy& pol); + template <class T> + int itrunc(const T& v); + template <class T, class Policy> + long ltrunc(const T& v, const Policy& pol); + template <class T> + long ltrunc(const T& v); +#ifdef BOOST_HAS_LONG_LONG + template <class T, class Policy> + boost::long_long_type lltrunc(const T& v, const Policy& pol); + template <class T> + boost::long_long_type lltrunc(const T& v); +#endif + template <class T, class Policy> + typename tools::promote_args<T>::type round(const T& v, const Policy& pol); + template <class T> + typename tools::promote_args<T>::type round(const T& v); + template <class T, class Policy> + int iround(const T& v, const Policy& pol); + template <class T> + int iround(const T& v); + template <class T, class Policy> + long lround(const T& v, const Policy& pol); + template <class T> + long lround(const T& v); +#ifdef BOOST_HAS_LONG_LONG + template <class T, class Policy> + boost::long_long_type llround(const T& v, const Policy& pol); + template <class T> + boost::long_long_type llround(const T& v); +#endif + template <class T, class Policy> + T modf(const T& v, T* ipart, const Policy& pol); + template <class T> + T modf(const T& v, T* ipart); + template <class T, class Policy> + T modf(const T& v, int* ipart, const Policy& pol); + template <class T> + T modf(const T& v, int* ipart); + template <class T, class Policy> + T modf(const T& v, long* ipart, const Policy& pol); + template <class T> + T modf(const T& v, long* ipart); +#ifdef BOOST_HAS_LONG_LONG + template <class T, class Policy> + T modf(const T& v, boost::long_long_type* ipart, const Policy& pol); + template <class T> + T modf(const T& v, boost::long_long_type* ipart); +#endif + + } +} + +#undef BOOST_MATH_STD_USING +#define BOOST_MATH_STD_USING BOOST_MATH_STD_USING_CORE\ + using boost::math::round;\ + using boost::math::iround;\ + using boost::math::lround;\ + using boost::math::trunc;\ + using boost::math::itrunc;\ + using boost::math::ltrunc;\ + using boost::math::modf; + + +#endif // BOOST_MATH_SPECIAL_ROUND_FWD_HPP + diff --git a/src/third_party/boost-1.70.0/boost/math/special_functions/detail/t_distribution_inv.hpp b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/t_distribution_inv.hpp new file mode 100644 index 00000000000..ab5a8fbca69 --- /dev/null +++ b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/t_distribution_inv.hpp @@ -0,0 +1,549 @@ +// Copyright John Maddock 2007. +// Copyright Paul A. Bristow 2007 +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_SF_DETAIL_INV_T_HPP +#define BOOST_MATH_SF_DETAIL_INV_T_HPP + +#ifdef _MSC_VER +#pragma once +#endif + +#include <boost/math/special_functions/cbrt.hpp> +#include <boost/math/special_functions/round.hpp> +#include <boost/math/special_functions/trunc.hpp> + +namespace boost{ namespace math{ namespace detail{ + +// +// The main method used is due to Hill: +// +// G. W. Hill, Algorithm 396, Student's t-Quantiles, +// Communications of the ACM, 13(10): 619-620, Oct., 1970. +// +template <class T, class Policy> +T inverse_students_t_hill(T ndf, T u, const Policy& pol) +{ + BOOST_MATH_STD_USING + BOOST_ASSERT(u <= 0.5); + + T a, b, c, d, q, x, y; + + if (ndf > 1e20f) + return -boost::math::erfc_inv(2 * u, pol) * constants::root_two<T>(); + + a = 1 / (ndf - 0.5f); + b = 48 / (a * a); + c = ((20700 * a / b - 98) * a - 16) * a + 96.36f; + d = ((94.5f / (b + c) - 3) / b + 1) * sqrt(a * constants::pi<T>() / 2) * ndf; + y = pow(d * 2 * u, 2 / ndf); + + if (y > (0.05f + a)) + { + // + // Asymptotic inverse expansion about normal: + // + x = -boost::math::erfc_inv(2 * u, pol) * constants::root_two<T>(); + y = x * x; + + if (ndf < 5) + c += 0.3f * (ndf - 4.5f) * (x + 0.6f); + c += (((0.05f * d * x - 5) * x - 7) * x - 2) * x + b; + y = (((((0.4f * y + 6.3f) * y + 36) * y + 94.5f) / c - y - 3) / b + 1) * x; + y = boost::math::expm1(a * y * y, pol); + } + else + { + y = static_cast<T>(((1 / (((ndf + 6) / (ndf * y) - 0.089f * d - 0.822f) + * (ndf + 2) * 3) + 0.5 / (ndf + 4)) * y - 1) + * (ndf + 1) / (ndf + 2) + 1 / y); + } + q = sqrt(ndf * y); + + return -q; +} +// +// Tail and body series are due to Shaw: +// +// www.mth.kcl.ac.uk/~shaww/web_page/papers/Tdistribution06.pdf +// +// Shaw, W.T., 2006, "Sampling Student's T distribution - use of +// the inverse cumulative distribution function." +// Journal of Computational Finance, Vol 9 Issue 4, pp 37-73, Summer 2006 +// +template <class T, class Policy> +T inverse_students_t_tail_series(T df, T v, const Policy& pol) +{ + BOOST_MATH_STD_USING + // Tail series expansion, see section 6 of Shaw's paper. + // w is calculated using Eq 60: + T w = boost::math::tgamma_delta_ratio(df / 2, constants::half<T>(), pol) + * sqrt(df * constants::pi<T>()) * v; + // define some variables: + T np2 = df + 2; + T np4 = df + 4; + T np6 = df + 6; + // + // Calculate the coefficients d(k), these depend only on the + // number of degrees of freedom df, so at least in theory + // we could tabulate these for fixed df, see p15 of Shaw: + // + T d[7] = { 1, }; + d[1] = -(df + 1) / (2 * np2); + np2 *= (df + 2); + d[2] = -df * (df + 1) * (df + 3) / (8 * np2 * np4); + np2 *= df + 2; + d[3] = -df * (df + 1) * (df + 5) * (((3 * df) + 7) * df -2) / (48 * np2 * np4 * np6); + np2 *= (df + 2); + np4 *= (df + 4); + d[4] = -df * (df + 1) * (df + 7) * + ( (((((15 * df) + 154) * df + 465) * df + 286) * df - 336) * df + 64 ) + / (384 * np2 * np4 * np6 * (df + 8)); + np2 *= (df + 2); + d[5] = -df * (df + 1) * (df + 3) * (df + 9) + * (((((((35 * df + 452) * df + 1573) * df + 600) * df - 2020) * df) + 928) * df -128) + / (1280 * np2 * np4 * np6 * (df + 8) * (df + 10)); + np2 *= (df + 2); + np4 *= (df + 4); + np6 *= (df + 6); + d[6] = -df * (df + 1) * (df + 11) + * ((((((((((((945 * df) + 31506) * df + 425858) * df + 2980236) * df + 11266745) * df + 20675018) * df + 7747124) * df - 22574632) * df - 8565600) * df + 18108416) * df - 7099392) * df + 884736) + / (46080 * np2 * np4 * np6 * (df + 8) * (df + 10) * (df +12)); + // + // Now bring everthing together to provide the result, + // this is Eq 62 of Shaw: + // + T rn = sqrt(df); + T div = pow(rn * w, 1 / df); + T power = div * div; + T result = tools::evaluate_polynomial<7, T, T>(d, power); + result *= rn; + result /= div; + return -result; +} + +template <class T, class Policy> +T inverse_students_t_body_series(T df, T u, const Policy& pol) +{ + BOOST_MATH_STD_USING + // + // Body series for small N: + // + // Start with Eq 56 of Shaw: + // + T v = boost::math::tgamma_delta_ratio(df / 2, constants::half<T>(), pol) + * sqrt(df * constants::pi<T>()) * (u - constants::half<T>()); + // + // Workspace for the polynomial coefficients: + // + T c[11] = { 0, 1, }; + // + // Figure out what the coefficients are, note these depend + // only on the degrees of freedom (Eq 57 of Shaw): + // + T in = 1 / df; + c[2] = static_cast<T>(0.16666666666666666667 + 0.16666666666666666667 * in); + c[3] = static_cast<T>((0.0083333333333333333333 * in + + 0.066666666666666666667) * in + + 0.058333333333333333333); + c[4] = static_cast<T>(((0.00019841269841269841270 * in + + 0.0017857142857142857143) * in + + 0.026785714285714285714) * in + + 0.025198412698412698413); + c[5] = static_cast<T>((((2.7557319223985890653e-6 * in + + 0.00037477954144620811287) * in + - 0.0011078042328042328042) * in + + 0.010559964726631393298) * in + + 0.012039792768959435626); + c[6] = static_cast<T>(((((2.5052108385441718775e-8 * in + - 0.000062705427288760622094) * in + + 0.00059458674042007375341) * in + - 0.0016095979637646304313) * in + + 0.0061039211560044893378) * in + + 0.0038370059724226390893); + c[7] = static_cast<T>((((((1.6059043836821614599e-10 * in + + 0.000015401265401265401265) * in + - 0.00016376804137220803887) * in + + 0.00069084207973096861986) * in + - 0.0012579159844784844785) * in + + 0.0010898206731540064873) * in + + 0.0032177478835464946576); + c[8] = static_cast<T>(((((((7.6471637318198164759e-13 * in + - 3.9851014346715404916e-6) * in + + 0.000049255746366361445727) * in + - 0.00024947258047043099953) * in + + 0.00064513046951456342991) * in + - 0.00076245135440323932387) * in + + 0.000033530976880017885309) * in + + 0.0017438262298340009980); + c[9] = static_cast<T>((((((((2.8114572543455207632e-15 * in + + 1.0914179173496789432e-6) * in + - 0.000015303004486655377567) * in + + 0.000090867107935219902229) * in + - 0.00029133414466938067350) * in + + 0.00051406605788341121363) * in + - 0.00036307660358786885787) * in + - 0.00031101086326318780412) * in + + 0.00096472747321388644237); + c[10] = static_cast<T>(((((((((8.2206352466243297170e-18 * in + - 3.1239569599829868045e-7) * in + + 4.8903045291975346210e-6) * in + - 0.000033202652391372058698) * in + + 0.00012645437628698076975) * in + - 0.00028690924218514613987) * in + + 0.00035764655430568632777) * in + - 0.00010230378073700412687) * in + - 0.00036942667800009661203) * in + + 0.00054229262813129686486); + // + // The result is then a polynomial in v (see Eq 56 of Shaw): + // + return tools::evaluate_odd_polynomial<11, T, T>(c, v); +} + +template <class T, class Policy> +T inverse_students_t(T df, T u, T v, const Policy& pol, bool* pexact = 0) +{ + // + // df = number of degrees of freedom. + // u = probablity. + // v = 1 - u. + // l = lanczos type to use. + // + BOOST_MATH_STD_USING + bool invert = false; + T result = 0; + if(pexact) + *pexact = false; + if(u > v) + { + // function is symmetric, invert it: + std::swap(u, v); + invert = true; + } + if((floor(df) == df) && (df < 20)) + { + // + // we have integer degrees of freedom, try for the special + // cases first: + // + T tolerance = ldexp(1.0f, (2 * policies::digits<T, Policy>()) / 3); + + switch(itrunc(df, Policy())) + { + case 1: + { + // + // df = 1 is the same as the Cauchy distribution, see + // Shaw Eq 35: + // + if(u == 0.5) + result = 0; + else + result = -cos(constants::pi<T>() * u) / sin(constants::pi<T>() * u); + if(pexact) + *pexact = true; + break; + } + case 2: + { + // + // df = 2 has an exact result, see Shaw Eq 36: + // + result =(2 * u - 1) / sqrt(2 * u * v); + if(pexact) + *pexact = true; + break; + } + case 4: + { + // + // df = 4 has an exact result, see Shaw Eq 38 & 39: + // + T alpha = 4 * u * v; + T root_alpha = sqrt(alpha); + T r = 4 * cos(acos(root_alpha) / 3) / root_alpha; + T x = sqrt(r - 4); + result = u - 0.5f < 0 ? (T)-x : x; + if(pexact) + *pexact = true; + break; + } + case 6: + { + // + // We get numeric overflow in this area: + // + if(u < 1e-150) + return (invert ? -1 : 1) * inverse_students_t_hill(df, u, pol); + // + // Newton-Raphson iteration of a polynomial case, + // choice of seed value is taken from Shaw's online + // supplement: + // + T a = 4 * (u - u * u);//1 - 4 * (u - 0.5f) * (u - 0.5f); + T b = boost::math::cbrt(a); + static const T c = static_cast<T>(0.85498797333834849467655443627193); + T p = 6 * (1 + c * (1 / b - 1)); + T p0; + do{ + T p2 = p * p; + T p4 = p2 * p2; + T p5 = p * p4; + p0 = p; + // next term is given by Eq 41: + p = 2 * (8 * a * p5 - 270 * p2 + 2187) / (5 * (4 * a * p4 - 216 * p - 243)); + }while(fabs((p - p0) / p) > tolerance); + // + // Use Eq 45 to extract the result: + // + p = sqrt(p - df); + result = (u - 0.5f) < 0 ? (T)-p : p; + break; + } +#if 0 + // + // These are Shaw's "exact" but iterative solutions + // for even df, the numerical accuracy of these is + // rather less than Hill's method, so these are disabled + // for now, which is a shame because they are reasonably + // quick to evaluate... + // + case 8: + { + // + // Newton-Raphson iteration of a polynomial case, + // choice of seed value is taken from Shaw's online + // supplement: + // + static const T c8 = 0.85994765706259820318168359251872L; + T a = 4 * (u - u * u); //1 - 4 * (u - 0.5f) * (u - 0.5f); + T b = pow(a, T(1) / 4); + T p = 8 * (1 + c8 * (1 / b - 1)); + T p0 = p; + do{ + T p5 = p * p; + p5 *= p5 * p; + p0 = p; + // Next term is given by Eq 42: + p = 2 * (3 * p + (640 * (160 + p * (24 + p * (p + 4)))) / (-5120 + p * (-2048 - 960 * p + a * p5))) / 7; + }while(fabs((p - p0) / p) > tolerance); + // + // Use Eq 45 to extract the result: + // + p = sqrt(p - df); + result = (u - 0.5f) < 0 ? -p : p; + break; + } + case 10: + { + // + // Newton-Raphson iteration of a polynomial case, + // choice of seed value is taken from Shaw's online + // supplement: + // + static const T c10 = 0.86781292867813396759105692122285L; + T a = 4 * (u - u * u); //1 - 4 * (u - 0.5f) * (u - 0.5f); + T b = pow(a, T(1) / 5); + T p = 10 * (1 + c10 * (1 / b - 1)); + T p0; + do{ + T p6 = p * p; + p6 *= p6 * p6; + p0 = p; + // Next term given by Eq 43: + p = (8 * p) / 9 + (218750 * (21875 + 4 * p * (625 + p * (75 + 2 * p * (5 + p))))) / + (9 * (-68359375 + 8 * p * (-2343750 + p * (-546875 - 175000 * p + 8 * a * p6)))); + }while(fabs((p - p0) / p) > tolerance); + // + // Use Eq 45 to extract the result: + // + p = sqrt(p - df); + result = (u - 0.5f) < 0 ? -p : p; + break; + } +#endif + default: + goto calculate_real; + } + } + else + { +calculate_real: + if(df > 0x10000000) + { + result = -boost::math::erfc_inv(2 * u, pol) * constants::root_two<T>(); + if((pexact) && (df >= 1e20)) + *pexact = true; + } + else if(df < 3) + { + // + // Use a roughly linear scheme to choose between Shaw's + // tail series and body series: + // + T crossover = 0.2742f - df * 0.0242143f; + if(u > crossover) + { + result = boost::math::detail::inverse_students_t_body_series(df, u, pol); + } + else + { + result = boost::math::detail::inverse_students_t_tail_series(df, u, pol); + } + } + else + { + // + // Use Hill's method except in the exteme tails + // where we use Shaw's tail series. + // The crossover point is roughly exponential in -df: + // + T crossover = ldexp(1.0f, iround(T(df / -0.654f), typename policies::normalise<Policy, policies::rounding_error<policies::ignore_error> >::type())); + if(u > crossover) + { + result = boost::math::detail::inverse_students_t_hill(df, u, pol); + } + else + { + result = boost::math::detail::inverse_students_t_tail_series(df, u, pol); + } + } + } + return invert ? (T)-result : result; +} + +template <class T, class Policy> +inline T find_ibeta_inv_from_t_dist(T a, T p, T /*q*/, T* py, const Policy& pol) +{ + T u = p / 2; + T v = 1 - u; + T df = a * 2; + T t = boost::math::detail::inverse_students_t(df, u, v, pol); + *py = t * t / (df + t * t); + return df / (df + t * t); +} + +template <class T, class Policy> +inline T fast_students_t_quantile_imp(T df, T p, const Policy& pol, const mpl::false_*) +{ + BOOST_MATH_STD_USING + // + // Need to use inverse incomplete beta to get + // required precision so not so fast: + // + T probability = (p > 0.5) ? 1 - p : p; + T t, x, y(0); + x = ibeta_inv(df / 2, T(0.5), 2 * probability, &y, pol); + if(df * y > tools::max_value<T>() * x) + t = policies::raise_overflow_error<T>("boost::math::students_t_quantile<%1%>(%1%,%1%)", 0, pol); + else + t = sqrt(df * y / x); + // + // Figure out sign based on the size of p: + // + if(p < 0.5) + t = -t; + return t; +} + +template <class T, class Policy> +T fast_students_t_quantile_imp(T df, T p, const Policy& pol, const mpl::true_*) +{ + BOOST_MATH_STD_USING + bool invert = false; + if((df < 2) && (floor(df) != df)) + return boost::math::detail::fast_students_t_quantile_imp(df, p, pol, static_cast<mpl::false_*>(0)); + if(p > 0.5) + { + p = 1 - p; + invert = true; + } + // + // Get an estimate of the result: + // + bool exact; + T t = inverse_students_t(df, p, T(1-p), pol, &exact); + if((t == 0) || exact) + return invert ? -t : t; // can't do better! + // + // Change variables to inverse incomplete beta: + // + T t2 = t * t; + T xb = df / (df + t2); + T y = t2 / (df + t2); + T a = df / 2; + // + // t can be so large that x underflows, + // just return our estimate in that case: + // + if(xb == 0) + return t; + // + // Get incomplete beta and it's derivative: + // + T f1; + T f0 = xb < y ? ibeta_imp(a, constants::half<T>(), xb, pol, false, true, &f1) + : ibeta_imp(constants::half<T>(), a, y, pol, true, true, &f1); + + // Get cdf from incomplete beta result: + T p0 = f0 / 2 - p; + // Get pdf from derivative: + T p1 = f1 * sqrt(y * xb * xb * xb / df); + // + // Second derivative divided by p1: + // + // yacas gives: + // + // In> PrettyForm(Simplify(D(t) (1 + t^2/v) ^ (-(v+1)/2))) + // + // | | v + 1 | | + // | -| ----- + 1 | | + // | | 2 | | + // -| | 2 | | + // | | t | | + // | | -- + 1 | | + // | ( v + 1 ) * | v | * t | + // --------------------------------------------- + // v + // + // Which after some manipulation is: + // + // -p1 * t * (df + 1) / (t^2 + df) + // + T p2 = t * (df + 1) / (t * t + df); + // Halley step: + t = fabs(t); + t += p0 / (p1 + p0 * p2 / 2); + return !invert ? -t : t; +} + +template <class T, class Policy> +inline T fast_students_t_quantile(T df, T p, const Policy& pol) +{ + typedef typename policies::evaluation<T, Policy>::type value_type; + typedef typename policies::normalise< + Policy, + policies::promote_float<false>, + policies::promote_double<false>, + policies::discrete_quantile<>, + policies::assert_undefined<> >::type forwarding_policy; + + typedef mpl::bool_< + (std::numeric_limits<T>::digits <= 53) + && + (std::numeric_limits<T>::is_specialized) + && + (std::numeric_limits<T>::radix == 2) + > tag_type; + return policies::checked_narrowing_cast<T, forwarding_policy>(fast_students_t_quantile_imp(static_cast<value_type>(df), static_cast<value_type>(p), pol, static_cast<tag_type*>(0)), "boost::math::students_t_quantile<%1%>(%1%,%1%,%1%)"); +} + +}}} // namespaces + +#endif // BOOST_MATH_SF_DETAIL_INV_T_HPP + + + diff --git a/src/third_party/boost-1.70.0/boost/math/special_functions/detail/unchecked_bernoulli.hpp b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/unchecked_bernoulli.hpp new file mode 100644 index 00000000000..5a16d9df176 --- /dev/null +++ b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/unchecked_bernoulli.hpp @@ -0,0 +1,727 @@ + +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2013 Nikhar Agrawal +// Copyright 2013 Christopher Kormanyos +// Copyright 2013 John Maddock +// Copyright 2013 Paul Bristow +// Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_UNCHECKED_BERNOULLI_HPP +#define BOOST_MATH_UNCHECKED_BERNOULLI_HPP + +#include <limits> +#include <cmath> +#include <boost/math/policies/error_handling.hpp> +#include <boost/math/constants/constants.hpp> +#include <boost/math/special_functions/math_fwd.hpp> +#include <boost/mpl/int.hpp> +#include <boost/type_traits/is_convertible.hpp> + +#ifdef BOOST_MATH_HAVE_CONSTEXPR_TABLES +#include <array> +#else +#include <boost/array.hpp> +#endif + + +namespace boost { namespace math { + +namespace detail { + +template <unsigned N> +struct max_bernoulli_index +{ + BOOST_STATIC_CONSTANT(unsigned, value = 17); +}; + +template <> +struct max_bernoulli_index<1> +{ + BOOST_STATIC_CONSTANT(unsigned, value = 32); +}; + +template <> +struct max_bernoulli_index<2> +{ + BOOST_STATIC_CONSTANT(unsigned, value = 129); +}; + +template <> +struct max_bernoulli_index<3> +{ + BOOST_STATIC_CONSTANT(unsigned, value = 1156); +}; + +template <> +struct max_bernoulli_index<4> +{ + BOOST_STATIC_CONSTANT(unsigned, value = 11); +}; + +template <class T> +struct bernoulli_imp_variant +{ + static const unsigned value = + (std::numeric_limits<T>::max_exponent == 128) + && (std::numeric_limits<T>::radix == 2) + && (std::numeric_limits<T>::digits <= std::numeric_limits<float>::digits) + && (boost::is_convertible<float, T>::value) ? 1 : + ( + (std::numeric_limits<T>::max_exponent == 1024) + && (std::numeric_limits<T>::radix == 2) + && (std::numeric_limits<T>::digits <= std::numeric_limits<double>::digits) + && (boost::is_convertible<double, T>::value) ? 2 : + ( + (std::numeric_limits<T>::max_exponent == 16384) + && (std::numeric_limits<T>::radix == 2) + && (std::numeric_limits<T>::digits <= std::numeric_limits<long double>::digits) + && (boost::is_convertible<long double, T>::value) ? 3 : (!is_convertible<boost::int64_t, T>::value ? 4 : 0) + ) + ); +}; + +} // namespace detail + +template <class T> +struct max_bernoulli_b2n : public detail::max_bernoulli_index<detail::bernoulli_imp_variant<T>::value>{}; + +namespace detail{ + +template <class T> +inline BOOST_MATH_CONSTEXPR_TABLE_FUNCTION T unchecked_bernoulli_imp(std::size_t n, const mpl::int_<0>& ) +{ +#ifdef BOOST_MATH_HAVE_CONSTEXPR_TABLES + constexpr std::array<boost::int64_t, 1 + max_bernoulli_b2n<T>::value> numerators = +#else + static const boost::array<boost::int64_t, 1 + max_bernoulli_b2n<T>::value> numerators = +#endif + {{ + boost::int64_t( +1LL), + boost::int64_t( +1LL), + boost::int64_t( -1LL), + boost::int64_t( +1LL), + boost::int64_t( -1LL), + boost::int64_t( +5LL), + boost::int64_t( -691LL), + boost::int64_t( +7LL), + boost::int64_t( -3617LL), + boost::int64_t( +43867LL), + boost::int64_t( -174611LL), + boost::int64_t( +854513LL), + boost::int64_t( -236364091LL), + boost::int64_t( +8553103LL), + boost::int64_t( -23749461029LL), + boost::int64_t(+8615841276005LL), + boost::int64_t(-7709321041217LL), + boost::int64_t(+2577687858367LL) + }}; + +#ifdef BOOST_MATH_HAVE_CONSTEXPR_TABLES + constexpr std::array<boost::int64_t, 1 + max_bernoulli_b2n<T>::value> denominators = +#else + static const boost::array<boost::int64_t, 1 + max_bernoulli_b2n<T>::value> denominators = +#endif + {{ + boost::int64_t( 1LL), + boost::int64_t( 6LL), + boost::int64_t( 30LL), + boost::int64_t( 42LL), + boost::int64_t( 30LL), + boost::int64_t( 66LL), + boost::int64_t( 2730LL), + boost::int64_t( 6LL), + boost::int64_t( 510LL), + boost::int64_t( 798LL), + boost::int64_t( 330LL), + boost::int64_t( 138LL), + boost::int64_t( 2730LL), + boost::int64_t( 6LL), + boost::int64_t( 870LL), + boost::int64_t( 14322LL), + boost::int64_t( 510LL), + boost::int64_t( 6LL) + }}; + return T(numerators[n]) / denominators[n]; +} + +template <class T> +inline BOOST_MATH_CONSTEXPR_TABLE_FUNCTION T unchecked_bernoulli_imp(std::size_t n, const mpl::int_<1>& ) +{ +#ifdef BOOST_MATH_HAVE_CONSTEXPR_TABLES + constexpr std::array<float, 1 + max_bernoulli_b2n<T>::value> bernoulli_data = +#else + static const boost::array<float, 1 + max_bernoulli_b2n<T>::value> bernoulli_data = +#endif + {{ + +1.00000000000000000000000000000000000000000F, + +0.166666666666666666666666666666666666666667F, + -0.0333333333333333333333333333333333333333333F, + +0.0238095238095238095238095238095238095238095F, + -0.0333333333333333333333333333333333333333333F, + +0.0757575757575757575757575757575757575757576F, + -0.253113553113553113553113553113553113553114F, + +1.16666666666666666666666666666666666666667F, + -7.09215686274509803921568627450980392156863F, + +54.9711779448621553884711779448621553884712F, + -529.124242424242424242424242424242424242424F, + +6192.12318840579710144927536231884057971014F, + -86580.2531135531135531135531135531135531136F, + +1.42551716666666666666666666666666666666667e6F, + -2.72982310678160919540229885057471264367816e7F, + +6.01580873900642368384303868174835916771401e8F, + -1.51163157670921568627450980392156862745098e10F, + +4.29614643061166666666666666666666666666667e11F, + -1.37116552050883327721590879485616327721591e13F, + +4.88332318973593166666666666666666666666667e14F, + -1.92965793419400681486326681448632668144863e16F, + +8.41693047573682615000553709856035437430786e17F, + -4.03380718540594554130768115942028985507246e19F, + +2.11507486380819916056014539007092198581560e21F, + -1.20866265222965259346027311937082525317819e23F, + +7.50086674607696436685572007575757575757576e24F, + -5.03877810148106891413789303052201257861635e26F, + +3.65287764848181233351104308429711779448622e28F, + -2.84987693024508822262691464329106781609195e30F, + +2.38654274996836276446459819192192149717514e32F, + -2.13999492572253336658107447651910973926742e34F, + +2.05009757234780975699217330956723102516667e36F, + -2.09380059113463784090951852900279701847092e38F, + }}; + + return bernoulli_data[n]; +} + + +template <class T> +inline BOOST_MATH_CONSTEXPR_TABLE_FUNCTION T unchecked_bernoulli_imp(std::size_t n, const mpl::int_<2>& ) +{ +#ifdef BOOST_MATH_HAVE_CONSTEXPR_TABLES + constexpr std::array<double, 1 + max_bernoulli_b2n<T>::value> bernoulli_data = +#else + static const boost::array<double, 1 + max_bernoulli_b2n<T>::value> bernoulli_data = +#endif + {{ + +1.00000000000000000000000000000000000000000, + +0.166666666666666666666666666666666666666667, + -0.0333333333333333333333333333333333333333333, + +0.0238095238095238095238095238095238095238095, + -0.0333333333333333333333333333333333333333333, + +0.0757575757575757575757575757575757575757576, + -0.253113553113553113553113553113553113553114, + +1.16666666666666666666666666666666666666667, + -7.09215686274509803921568627450980392156863, + +54.9711779448621553884711779448621553884712, + -529.124242424242424242424242424242424242424, + +6192.12318840579710144927536231884057971014, + -86580.2531135531135531135531135531135531136, + +1.42551716666666666666666666666666666666667e6, + -2.72982310678160919540229885057471264367816e7, + +6.01580873900642368384303868174835916771401e8, + -1.51163157670921568627450980392156862745098e10, + +4.29614643061166666666666666666666666666667e11, + -1.37116552050883327721590879485616327721591e13, + +4.88332318973593166666666666666666666666667e14, + -1.92965793419400681486326681448632668144863e16, + +8.41693047573682615000553709856035437430786e17, + -4.03380718540594554130768115942028985507246e19, + +2.11507486380819916056014539007092198581560e21, + -1.20866265222965259346027311937082525317819e23, + +7.50086674607696436685572007575757575757576e24, + -5.03877810148106891413789303052201257861635e26, + +3.65287764848181233351104308429711779448622e28, + -2.84987693024508822262691464329106781609195e30, + +2.38654274996836276446459819192192149717514e32, + -2.13999492572253336658107447651910973926742e34, + +2.05009757234780975699217330956723102516667e36, + -2.09380059113463784090951852900279701847092e38, + +2.27526964884635155596492603527692645814700e40, + -2.62577102862395760473030497361582020814490e42, + +3.21250821027180325182047923042649852435219e44, + -4.15982781667947109139170744952623589366896e46, + +5.69206954820352800238834562191210586444805e48, + -8.21836294197845756922906534686173330145509e50, + +1.25029043271669930167323398297028955241772e53, + -2.00155832332483702749253291988132987687242e55, + +3.36749829153643742333966769033387530162196e57, + -5.94709705031354477186604968440515408405791e59, + +1.10119103236279775595641307904376916046305e62, + -2.13552595452535011886583850190410656789733e64, + +4.33288969866411924196166130593792062184514e66, + -9.18855282416693282262005552155018971389604e68, + +2.03468967763290744934550279902200200659751e71, + -4.70038339580357310785752555350060606545967e73, + +1.13180434454842492706751862577339342678904e76, + -2.83822495706937069592641563364817647382847e78, + +7.40642489796788506297508271409209841768797e80, + -2.00964548027566044834656196727153631868673e83, + +5.66571700508059414457193460305193569614195e85, + -1.65845111541362169158237133743199123014950e88, + +5.03688599504923774192894219151801548124424e90, + -1.58614682376581863693634015729664387827410e93, + +5.17567436175456269840732406825071225612408e95, + -1.74889218402171173396900258776181591451415e98, + +6.11605199949521852558245252642641677807677e100, + -2.21227769127078349422883234567129324455732e103, + +8.27227767987709698542210624599845957312047e105, + -3.19589251114157095835916343691808148735263e108, + +1.27500822233877929823100243029266798669572e111, + -5.25009230867741338994028246245651754469199e113, + +2.23018178942416252098692981988387281437383e116, + -9.76845219309552044386335133989802393011669e118, + +4.40983619784529542722726228748131691918758e121, + -2.05085708864640888397293377275830154864566e124, + +9.82144332797912771075729696020975210414919e126, + -4.84126007982088805087891967099634127611305e129, + +2.45530888014809826097834674040886903996737e132, + -1.28069268040847475487825132786017857218118e135, + +6.86761671046685811921018885984644004360924e137, + -3.78464685819691046949789954163795568144895e140, + +2.14261012506652915508713231351482720966602e143, + -1.24567271371836950070196429616376072194583e146, + +7.43457875510001525436796683940520613117807e148, + -4.55357953046417048940633332233212748767721e151, + +2.86121128168588683453638472510172325229190e154, + -1.84377235520338697276882026536287854875414e157, + +1.21811545362210466995013165065995213558174e160, + -8.24821871853141215484818457296893447301419e162, + +5.72258779378329433296516498142978615918685e165, + -4.06685305250591047267679693831158655602196e168, + +2.95960920646420500628752695815851870426379e171, + -2.20495225651894575090311752273445984836379e174, + +1.68125970728895998058311525151360665754464e177, + -1.31167362135569576486452806355817153004431e180, + +1.04678940094780380821832853929823089643829e183, + -8.54328935788337077185982546299082774593270e185, + +7.12878213224865423522884066771438224721245e188, + -6.08029314555358993000847118686477458461988e191, + +5.29967764248499239300942910043247266228490e194, + -4.71942591687458626443646229013379911103761e197, + +4.29284137914029810894168296541074669045521e200, + -3.98767449682322074434477655542938795106651e203, + +3.78197804193588827138944181161393327898220e206, + -3.66142336836811912436858082151197348755196e209, + +3.61760902723728623488554609298914089477541e212, + -3.64707726451913543621383088655499449048682e215, + +3.75087554364544090983452410104814189306842e218, + -3.93458672964390282694891288533713429355657e221, + +4.20882111481900820046571171111494898242731e224, + -4.59022962206179186559802940573325591059371e227, + +5.10317257726295759279198185106496768539760e230, + -5.78227623036569554015377271242917142512200e233, + +6.67624821678358810322637794412809363451080e236, + -7.85353076444504163225916259639312444428230e239, + +9.41068940670587255245443288258762485293948e242, + -1.14849338734651839938498599206805592548354e246, + +1.42729587428487856771416320087122499897180e249, + -1.80595595869093090142285728117654560926719e252, + +2.32615353076608052161297985184708876161736e255, + -3.04957517154995947681942819261542593785327e258, + +4.06858060764339734424012124124937318633684e261, + -5.52310313219743616252320044093186392324280e264, + +7.62772793964343924869949690204961215533859e267, + -1.07155711196978863132793524001065396932667e271, + +1.53102008959691884453440916153355334355847e274, + -2.22448916821798346676602348865048510824835e277, + +3.28626791906901391668189736436895275365183e280, + -4.93559289559603449020711938191575963496999e283, + +7.53495712008325067212266049779283956727824e286, + -1.16914851545841777278088924731655041783900e290, + +1.84352614678389394126646201597702232396492e293, + -2.95368261729680829728014917350525183485207e296, + +4.80793212775015697668878704043264072227967e299, + -7.95021250458852528538243631671158693036798e302, + +1.33527841873546338750122832017820518292039e306 + }}; + + return bernoulli_data[n]; +} + +template <class T> +inline BOOST_MATH_CONSTEXPR_TABLE_FUNCTION T unchecked_bernoulli_imp(std::size_t n, const mpl::int_<3>& ) +{ +#ifdef BOOST_MATH_HAVE_CONSTEXPR_TABLES + constexpr std::array<long double, 1 + max_bernoulli_b2n<T>::value> bernoulli_data = +#else + static const boost::array<long double, 1 + max_bernoulli_b2n<T>::value> bernoulli_data = +#endif + {{ + +1.00000000000000000000000000000000000000000L, + +0.166666666666666666666666666666666666666667L, + -0.0333333333333333333333333333333333333333333L, + +0.0238095238095238095238095238095238095238095L, + -0.0333333333333333333333333333333333333333333L, + +0.0757575757575757575757575757575757575757576L, + -0.253113553113553113553113553113553113553114L, + +1.16666666666666666666666666666666666666667L, + -7.09215686274509803921568627450980392156863L, + +54.9711779448621553884711779448621553884712L, + -529.124242424242424242424242424242424242424L, + +6192.12318840579710144927536231884057971014L, + -86580.2531135531135531135531135531135531136L, + +1.42551716666666666666666666666666666666667E6L, + -2.72982310678160919540229885057471264367816E7L, + +6.01580873900642368384303868174835916771401E8L, + -1.51163157670921568627450980392156862745098E10L, + +4.29614643061166666666666666666666666666667E11L, + -1.37116552050883327721590879485616327721591E13L, + +4.88332318973593166666666666666666666666667E14L, + -1.92965793419400681486326681448632668144863E16L, + +8.41693047573682615000553709856035437430786E17L, + -4.03380718540594554130768115942028985507246E19L, + +2.11507486380819916056014539007092198581560E21L, + -1.20866265222965259346027311937082525317819E23L, + +7.50086674607696436685572007575757575757576E24L, + -5.03877810148106891413789303052201257861635E26L, + +3.65287764848181233351104308429711779448622E28L, + -2.84987693024508822262691464329106781609195E30L, + +2.38654274996836276446459819192192149717514E32L, + -2.13999492572253336658107447651910973926742E34L, + +2.05009757234780975699217330956723102516667E36L, + -2.09380059113463784090951852900279701847092E38L, + +2.27526964884635155596492603527692645814700E40L, + -2.62577102862395760473030497361582020814490E42L, + +3.21250821027180325182047923042649852435219E44L, + -4.15982781667947109139170744952623589366896E46L, + +5.69206954820352800238834562191210586444805E48L, + -8.21836294197845756922906534686173330145509E50L, + +1.25029043271669930167323398297028955241772E53L, + -2.00155832332483702749253291988132987687242E55L, + +3.36749829153643742333966769033387530162196E57L, + -5.94709705031354477186604968440515408405791E59L, + +1.10119103236279775595641307904376916046305E62L, + -2.13552595452535011886583850190410656789733E64L, + +4.33288969866411924196166130593792062184514E66L, + -9.18855282416693282262005552155018971389604E68L, + +2.03468967763290744934550279902200200659751E71L, + -4.70038339580357310785752555350060606545967E73L, + +1.13180434454842492706751862577339342678904E76L, + -2.83822495706937069592641563364817647382847E78L, + +7.40642489796788506297508271409209841768797E80L, + -2.00964548027566044834656196727153631868673E83L, + +5.66571700508059414457193460305193569614195E85L, + -1.65845111541362169158237133743199123014950E88L, + +5.03688599504923774192894219151801548124424E90L, + -1.58614682376581863693634015729664387827410E93L, + +5.17567436175456269840732406825071225612408E95L, + -1.74889218402171173396900258776181591451415E98L, + +6.11605199949521852558245252642641677807677E100L, + -2.21227769127078349422883234567129324455732E103L, + +8.27227767987709698542210624599845957312047E105L, + -3.19589251114157095835916343691808148735263E108L, + +1.27500822233877929823100243029266798669572E111L, + -5.25009230867741338994028246245651754469199E113L, + +2.23018178942416252098692981988387281437383E116L, + -9.76845219309552044386335133989802393011669E118L, + +4.40983619784529542722726228748131691918758E121L, + -2.05085708864640888397293377275830154864566E124L, + +9.82144332797912771075729696020975210414919E126L, + -4.84126007982088805087891967099634127611305E129L, + +2.45530888014809826097834674040886903996737E132L, + -1.28069268040847475487825132786017857218118E135L, + +6.86761671046685811921018885984644004360924E137L, + -3.78464685819691046949789954163795568144895E140L, + +2.14261012506652915508713231351482720966602E143L, + -1.24567271371836950070196429616376072194583E146L, + +7.43457875510001525436796683940520613117807E148L, + -4.55357953046417048940633332233212748767721E151L, + +2.86121128168588683453638472510172325229190E154L, + -1.84377235520338697276882026536287854875414E157L, + +1.21811545362210466995013165065995213558174E160L, + -8.24821871853141215484818457296893447301419E162L, + +5.72258779378329433296516498142978615918685E165L, + -4.06685305250591047267679693831158655602196E168L, + +2.95960920646420500628752695815851870426379E171L, + -2.20495225651894575090311752273445984836379E174L, + +1.68125970728895998058311525151360665754464E177L, + -1.31167362135569576486452806355817153004431E180L, + +1.04678940094780380821832853929823089643829E183L, + -8.54328935788337077185982546299082774593270E185L, + +7.12878213224865423522884066771438224721245E188L, + -6.08029314555358993000847118686477458461988E191L, + +5.29967764248499239300942910043247266228490E194L, + -4.71942591687458626443646229013379911103761E197L, + +4.29284137914029810894168296541074669045521E200L, + -3.98767449682322074434477655542938795106651E203L, + +3.78197804193588827138944181161393327898220E206L, + -3.66142336836811912436858082151197348755196E209L, + +3.61760902723728623488554609298914089477541E212L, + -3.64707726451913543621383088655499449048682E215L, + +3.75087554364544090983452410104814189306842E218L, + -3.93458672964390282694891288533713429355657E221L, + +4.20882111481900820046571171111494898242731E224L, + -4.59022962206179186559802940573325591059371E227L, + +5.10317257726295759279198185106496768539760E230L, + -5.78227623036569554015377271242917142512200E233L, + +6.67624821678358810322637794412809363451080E236L, + -7.85353076444504163225916259639312444428230E239L, + +9.41068940670587255245443288258762485293948E242L, + -1.14849338734651839938498599206805592548354E246L, + +1.42729587428487856771416320087122499897180E249L, + -1.80595595869093090142285728117654560926719E252L, + +2.32615353076608052161297985184708876161736E255L, + -3.04957517154995947681942819261542593785327E258L, + +4.06858060764339734424012124124937318633684E261L, + -5.52310313219743616252320044093186392324280E264L, + +7.62772793964343924869949690204961215533859E267L, + -1.07155711196978863132793524001065396932667E271L, + +1.53102008959691884453440916153355334355847E274L, + -2.22448916821798346676602348865048510824835E277L, + +3.28626791906901391668189736436895275365183E280L, + -4.93559289559603449020711938191575963496999E283L, + +7.53495712008325067212266049779283956727824E286L, + -1.16914851545841777278088924731655041783900E290L, + +1.84352614678389394126646201597702232396492E293L, + -2.95368261729680829728014917350525183485207E296L, + +4.80793212775015697668878704043264072227967E299L, + -7.95021250458852528538243631671158693036798E302L, + +1.33527841873546338750122832017820518292039E306L, +#if LDBL_MAX_EXP == 16384 + // Entries 260 - 600 http://www.wolframalpha.com/input/?i=TABLE[N[Bernoulli[i]%2C40]%2C+{i%2C258%2C600%2C2}] + -2.277640649601959593875058983506938037019e309L, + 3.945184036046326234163525556422667595884e312L, + -6.938525772130602106071724989641405550473e315L, + 1.238896367577564823729057820219210929986e319L, + -2.245542599169309759499987966025604480745e322L, + 4.131213176073842359732511639489669404266e325L, + -7.713581346815269584960928069762882771369e328L, + 1.461536066837669600638613788471335541313e332L, + -2.809904606225532896862935642992712059631e335L, + 5.480957121318876639512096994413992284327e338L, + -1.084573284087686110518125291186079616320e342L, + 2.176980775647663539729165173863716459962e345L, + -4.431998786117553751947439433256752608068e348L, + 9.150625657715535047417756278073770096073e351L, + -1.915867353003157351316577579148683133613e355L, + 4.067256303542212258698836003682016040629e358L, + -8.754223791037736616228150209910348734629e361L, + 1.910173688735533667244373747124109379826e365L, + -4.225001320265091714631115064713174404607e368L, + 9.471959352547827678466770796787503034505e371L, + -2.152149973279986829719817376756088198573e375L, + 4.955485775334221051344839716507812871361e378L, + -1.156225941759134696630956889716381968142e382L, + 2.733406597646137698610991926705098514017e385L, + -6.546868135325176947099912523279938546333e388L, + 1.588524912441221472814692121069821695547e392L, + -3.904354800861715180218598151050191841308e395L, + 9.719938686092045781827273411668132975319e398L, + -2.450763621049522051234479737511375679283e402L, + 6.257892098396815305085674126334317095277e405L, + -1.618113552083806592527989531636955084420e409L, + 4.236528795217618357348618613216833722648e412L, + -1.123047068199051008086174989124136878992e416L, + 3.013971787525654770217283559392286666886e419L, + -8.188437573221553030375681429202969070420e422L, + 2.251910591336716809153958146725775718707e426L, + -6.268411292043789823075314151509139413399e429L, + 1.765990845202322642693572112511312471527e433L, + -5.035154436231331651259071296731160882240e436L, + 1.452779356460483245253765356664402207266e440L, + -4.241490890130137339052414960684151515166e443L, + 1.252966001692427774088293833338841893293e447L, + -3.744830047478272947978103227876747240343e450L, + 1.132315806695710930595876001089232216024e454L, + -3.463510845942701805991786197773934662578e457L, + 1.071643382649675572086865465873916611537e461L, + -3.353824475439933688957233489984711465335e464L, + 1.061594257145875875963152734129803268488e468L, + -3.398420969215528955528654193586189805265e471L, + 1.100192502000434096206138068020551065890e475L, + -3.601686379213993374332690210094863486472e478L, + 1.192235170430164900533187239994513019475e482L, + -3.990342751779668381699052942504119409180e485L, + 1.350281800938769780891258894167663309221e489L, + -4.619325443466054312873093650888507562249e492L, + 1.597522243968586548227514639959727696694e496L, + -5.584753729092155108530929002119620487652e499L, + 1.973443623104646193229794524759543752089e503L, + -7.048295441989615807045620880311201930244e506L, + 2.544236702499719094591873151590280263560e510L, + -9.281551595258615205927443367289948150345e513L, + 3.421757163154453657766296828520235351572e517L, + -1.274733639384538364282697627345068947433e521L, + 4.798524805311016034711205886780460173566e524L, + -1.825116948422858388787806917284878870034e528L, + 7.013667442807288452441777981425055613982e531L, + -2.723003862685989740898815670978399383114e535L, + 1.068014853917260290630122222858884658850e539L, + -4.231650952273697842269381683768681118533e542L, + 1.693650052202594386658903598564772900388e546L, + -6.846944855806453360616258582310883597678e549L, + 2.795809132238082267120232174243715559601e553L, + -1.153012972808983269106716828311318981951e557L, + 4.802368854268746357511997492039592697149e560L, + -2.019995255271910836389761734035403905781e564L, + 8.580207235032617856059250643095019760968e567L, + -3.680247942263468164408192134916355198549e571L, + 1.593924457586765331397457407661306895942e575L, + -6.970267175232643679233530367569943057501e578L, + 3.077528087427698518703282907890556154309e582L, + -1.371846760052887888926055417297342106614e586L, + 6.173627360829553396851763207025505289166e589L, + -2.804703130495506384463249394043486916669e593L, + 1.286250900087150126167490951216207186092e597L, + -5.954394420063617872366818601092036543220e600L, + 2.782297785278756426177542270854984091406e604L, + -1.312214674935307746141207680066262384215e608L, + 6.246299145383554153167974732783934504370e611L, + -3.000812007679574430883792565577444226490e615L, + 1.454904877136007844493861746476079537075e619L, + -7.118558521873800304612781121044077357278e622L, + 3.514739820897817389472822276832677887997e626L, + -1.751137068816377401163011262831890828437e630L, + 8.803498091818800678575314081978951179602e633L, + -4.465612911700593572269200981612564161010e637L, + 2.285494565287530681465757798517033542888e641L, + -1.180145168917737098025683613598595411329e645L, + 6.147941849198393232663105284575149616925e648L, + -3.231069156963603593233679426198974663352e652L, + 1.713042725635435041806895849197608270935e656L, + -9.161761363270648920537613435771882898051e659L, + 4.942675965960539112005679080810117766825e663L, + -2.689684712697383518131267222872386600031e667L, + 1.476320014229917759615308193449511534656e671L, + -8.173037740864781506597184122049453514594e674L, + 4.563462313190521363235182420178784459580e678L, + -2.569790015236158475703055501886439298708e682L, + 1.459410219452119981958355737832022375085e686L, + -8.358304882556983795372406183642486436653e689L, + 4.827305091483557818593092377664570208355e693L, + -2.811394311081493166793414157061950132403e697L, + 1.651026863340675349245561261339568827739e701L, + -9.776578579336866764167878646459810047899e704L, + 5.837207965197521880181236529616560780535e708L, + -3.513938957938032127105389702846371181520e712L, + 2.132747371360190507595748444536911078788e716L, + -1.305047363239192640729466563372665311602e720L, + 8.050825342678337497636292798039996484780e723L, + -5.006884161223862543665524155681082112689e727L, + 3.139016066011452177570812014513491361235e731L, + -1.983829535212711378291469356666001365873e735L, + 1.263822427649676371257598052486237628698e739L, + -8.115678659900522918802121684491754629503e742L, + 5.252995164972075271667364371449050412435e746L, + -3.427038125662404660056511738625477058135e750L, + 2.253446011834352733279946306835940729858e754L, + -1.493407341897034717876962786798831719683e758L, + 9.974681322653365118752729509398728354442e761L, + -6.714230142773850863927710112350816379426e765L, + 4.554668668931723346600337564274944733530e769L, + -3.113635386023220127834102980385275379533e773L, + 2.144945411287666204679363498162954050208e777L, + -1.488982121181387164932397544378555256016e781L, + 1.041537218854627455352298173588983048748e785L, + -7.341073881786613676177562822942175683993e788L, + 5.213524272587199574980117351016322518428e792L, + -3.730592531776514409283897139216167197989e796L, + 2.689592876341877079083449497724049500175e800L, + -1.953643788231947582529884602972233135002e804L, + 1.429691073080500563348668321308878246277e808L, + -1.054059177095488639836063073070536825675e812L, + 7.828919160938693948399336431565350676613e815L, + -5.857884457184396382550955498026762014753e819L, + 4.415401588264172474136969345712659422380e823L, + -3.352573884181287635796498822858109969161e827L, + 2.564210385719224000156548240934108974447e831L, + -1.975534392116037602837941409848663077528e835L, + 1.533062123975940045180943006948008486466e839L, + -1.198306160488763291730059994812781226903e843L, + 9.434034267770711698676321369174735725321e846L, + -7.480619200038505368468483892246806488879e850L, + 5.974161898439971564124576801455052907638e854L, + -4.805125663714699771668630995361572639386e858L, + 3.892332138028039952403812726744593073776e862L, + -3.175276505779699340738548328810180869575e866L, + 2.608608681939322393581069188271626122519e870L, + -2.158148554392732439392868052394994052628e874L, + 1.797993483301448477700600221980862686033e878L, + -1.508407575089108597171576068862286462909e882L, + 1.274273406242459482708930389008701147244e886L, + -1.083950475353171986748233157909397370193e890L, + 9.284292630726328432038470356821265395331e893L, + -8.007012115449516364480417355063446317414e897L, + 6.952871948429568933888979915833266241471e901L, + -6.078828929473797621198666799700739891205e905L, + 5.350908089710964244671334224708057812633e909L, + -4.742168072503284973969982758434401589090e913L, + 4.231149239401967697257534662010605751136e917L, + -3.800684612827828851942743291026898158947e921L, + 3.436984796314246158361599955909956583986e925L, + -3.128930718993658356398482705317381808301e929L, + // + // 602-1300: http://www.wolframalpha.com/input/?i=TABLE[N[Bernoulli[i]%2C40]%2C+{i%2C602%2C1300%2C2}] + 2.867524740577223817164663595437919813239e933L, -2.645462974939090580963101220449509725942e937L, 2.456800827789169780295419018499543141869e941L, -2.296690549725790064673528302231294870532e945L, 2.161174697699793265715182091764676666457e949L, -2.047023224586087259305754002882269123194e953L, 1.951604806042481282712736234132803700277e957L, -1.872785206668284042110390583158639495143e961L, 1.808847160923282257302788929692654262867e965L, -1.758427529634609613399327744595257497188e969L, 1.720468488019528147087036246754294757647e973L, -1.694180279355332648057740852839804839425e977L, 1.679013685251183870616469618951463869496e981L, -1.674640861433092946269144173974414945664e985L, 1.680943600147858322148767806987527412112e989L, -1.698008433134805056489370119323402510305e993L, 1.726128304411348354183882648263448448633e997L, -1.765810838736918108045764015629875016219e1001L, 1.817793526882665071123822455897912718293e1005L, -1.883066459765807128944897377914669600374e1009L, 1.962903588035940537938222992228124233567e1013L, -2.058903881920696086033171142046100185783e1017L, 2.173044241735786946064676598703393618281e1021L, -2.307746591425236218893160658331303115253e1025L, 2.465962312241418731528973526597433097256e1029L, -2.651278087802503406316742676403301581549e1033L, 2.868048395658440423778896607880692085708e1037L, -3.121561373094393453726645989392054731637e1041L, 3.418246710091027042099932753084126095820e1045L, -3.765936717592482928796920675282930034018e1049L, 4.174194967165213973474293718362757753877e1053L, -4.654731142471753017867105249805137855862e1057L, 5.221926310090434518253178454907900079787e1061L, -5.893500145664015254409680930288710794031e1065L, 6.691361332576333738130720616841706994101e1069L, -7.642695184575063524608775697714741180954e1073L, 8.781359617440634128952082759434723165820e1077L, -1.014968338800868135594698909567734048618e1082L, 1.180079105471061498849752479044520598414e1086L, -1.380162016721660241308046692646452732446e1090L, 1.623685158291375662775444238282343536948e1094L, -1.921404880943289359290531906131400049399e1098L, 2.287040419533950152851434188305457266969e1102L, -2.738162880206032093123060939173765335255e1106L, 3.297371307848643161532227459901386725801e1110L, -3.993854689967542662299211323085023297602e1114L, 4.865474805885735467044047308902313673643e1118L, -5.961554732739027308247618738765152679497e1122L, 7.346627151757492821447573639763873833441e1126L, -9.105493288459908620636712748727395637965e1130L, 1.135007867626164861991621396462821975167e1135L, -1.422876214067403769204874786137232627418e1139L, 1.793912271573925309173135913914667878908e1143L, -2.274542916104231188526120123855259514144e1147L, 2.900273688809987694128857655036783261991e1151L, -3.719022795563122339874875448447744493398e1155L, 4.795753420982845153626611023078973364321e1159L, -6.218937220186281310109009529226561379773e1163L, 8.109611247999584815668395828940708619394e1167L, -1.063412316303440216539797215354141158589e1172L, 1.402214363674117662460496032135704328989e1176L, -1.859223235464558752766840772026058694872e1180L, 2.478828203789903637835992128856742276028e1184L, -3.323169416193176673655321536761413885767e1188L, 4.479640207312477092938541546776915956580e1192L, -6.071721672924085739424644485636889518799e1196L, 8.274698015123579607850404326757887762270e1200L, -1.133855131459773018024052539697784205966e1205L, 1.562146222050424344025824344480153248984e1209L, -2.163904570724750459592352173471446831752e1213L, 3.013703210722669908901286635073603018696e1217L, -4.219903244242308803914269531001720703294e1221L, 5.940703220571043642186808904696174833998e1225L, -8.408147464216029127243257448169774333631e1229L, 1.196419999747411909144144315499654470715e1234L, -1.711518922741148710381740436694440587059e1238L, 2.461434539630850545757453894977350505251e1242L, -3.558748530932574002484841810677232366801e1246L, 5.172525606281917297657859608800373729529e1250L, -7.557850217376323621984784308774476917753e1254L, 1.110141075986004209769735296234549704181e1259L, -1.639216556732622481406083885926912451281e1263L, 2.433138328152562628385514545400044125983e1267L, -3.630476645219033020888837165221286413171e1271L, 5.445289518636306992942604775585977779418e1275L, -8.209806424989072060381590985042272020067e1279L, 1.244209849774134691374848390346442737613e1284L, -1.895384488692308848372754844910263931874e1288L, 2.902272596647764894203369746806169285113e1292L, -4.466944174025026625137032739317650862593e1296L, 6.910485739507636504313238347702354354916e1300L, -1.074550085668784170644854815272144687769e1305L, 1.679419258904938802199084915274175753529e1309L, -2.638155207645646220849795321076977230763e1313L, 4.165284786632654168563096850610185378233e1317L, -6.609774274649031371770290191295685774584e1321L, 1.054194100570841329575393359295845860860e1326L, -1.689822316104196916970708778265725885275e1330L, 2.722340957904912685605914893019783431164e1334L, -4.407776313964403233676810178851005163725e1338L, 7.172436210641903635864868181569129834361e1342L, -1.172947440100495955246356688225986736990e1347L, 1.927745674072824377954824961348211728006e1351L, -3.184013467435655962214317208087993711563e1355L, 5.285045125125832341263897233405196808096e1359L, -8.815883582819232027207118521581424783107e1363L, 1.477818368424505276711779171224799759099e1368L, -2.489482576496570159333357550363134602876e1372L, 4.214292881345076419678976329218843808204e1376L, -7.169068531615459070909644981451297906220e1380L, 1.225513133750594558180516896275774441895e1385L, -2.105160827387119480607950260289853896637e1389L, 3.633787605672960549893307203363402915249e1393L, -6.302830804027849515239463308430185990705e1397L, 1.098521433860299633481449685364914115468e1402L, -1.923858597401607622723144320370279518600e1406L, 3.385512828549942051667348582951554570164e1410L, -5.986286250836771248147827011780631183980e1414L, 1.063572794668186370728928272374836554300e1419L, -1.898666684876492795233907174493757572290e1423L, 3.405627002840442789235393111726609930533e1427L, -6.137724140284450036591063946055819333244e1431L, 1.111411024660941507986132154479364267486e1436L, -2.022060876221034821890406900217875915949e1440L, 3.696248025817144690840539132103538834108e1444L, -6.788448439024998306316860676030442691610e1448L, 1.252615233049059554031883468823648511657e1453L, -2.322190433141265975888955985950824418729e1457L, 4.325200102353909846882217732999001735342e1461L, -8.093531903011880118699218269369570178812e1465L, 1.521558881878323790120983450270946857209e1470L, -2.873780311010933807686415826253380907421e1474L, 5.452903697278823304173192839252276211670e1478L, -1.039457922537509500320638240809547113575e1483L, 1.990610112724715126895008793014214505760e1487L, -3.829667853173777076954453401761025071562e1491L, 7.401624504283011888971231756333356050310e1495L, -1.437075122764477911733220492562365990710e1500L, 2.802940275035867428066581228962104019228e1504L, -5.491938363067613321364335249495394164430e1508L, 1.080961960603953462180593404647115933651e1513L, -2.137290931892412298654741768897581319007e1517L, 4.245031321673807283498263276791307370788e1521L, -8.469499523038763989328773224520912663309e1525L, 1.697421812794203793865032206191322699261e1530L, -3.417217332563937242285349373774004020539e1534L, 6.910378594841763785923780822895851271770e1538L, -1.403696282437585785557998429691459557649e1543L, 2.864060533055333035232343601021192111053e1547L, -5.869818290384811353182423286543086530728e1551L, 1.208359745327224593486268988808338456906e1556L, -2.498576742140453770373914215325521001990e1560L, 5.189311407347546310078739863704346083861e1564L, -1.082537954843916294257278789980768336964e1569L, 2.268238255751421312559806122980932952706e1573L, -4.773557403917983369065731568732198697502e1577L, 1.009019097334998841920279535262007639746e1582L, -2.142181266523235177327239693359275472557e1586L, 4.567814904130855969979178320003286614868e1590L, -9.782550516204803195398428611221899469345e1594L, 2.104180123097086948576304557651398411373e1599L, -4.545658958087323864004652894518442709646e1603L, 9.862563944609427542603740078470901803131e1607L, -2.149105846582226970866569209122813809019e1612L, 4.703235567543888152049628411354542509156e1616L, -1.033719212601584878353206879472796545848e1621L, 2.281767401903848796732740825793310514456e1625L, -5.058236070813950229238666252351966279306e1629L, 1.126112519657857205642546937554224492775e1634L, -2.517766761987679577706779689880657777343e1638L, 5.653225190181653388317503182908983211029e1642L, -1.274735955461074142223278576503188429497e1647L, 2.886578974679460464298863945016671299242e1651L, -6.564203307141426181809363135003467581753e1655L, 1.499036144473064593308260681782048262301e1660L, -3.437714715599902386917108442954580869236e1664L, 7.916830957072777234152907034541325149479e1668L, -1.830850567422571420661248197094782575285e1673L, 4.251778280827419894527511469762091846660e1677L, -9.915182507286989818033146623995507108134e1681L, 2.321878208636697663781227497233334385222e1686L, -5.459879022461660582811365437190884471726e1690L, 1.289222044549922720398543474297554204559e1695L, -3.056819658344217799458557578658863826289e1699L, 7.277891759142725294172926258364455941365e1703L, -1.739928293433385104144012025546489673795e1708L, 4.176797408823713136137404972612780406904e1712L, -1.006788178307821554781930741698052910780e1717L, 2.436754569909644399766538111317379484511e1721L, -5.921896599028498715774458493117079340155e1725L, 1.445045688171565118619109316933316429671e1730L, -3.540547766876069233350621578795319652040e1734L, 8.710114552028472554054293344204504325978e1738L, -2.151484527880464463303897113553085899101e1743L, 5.335928195512405709733771642389502809087e1747L, -1.328726408335015910030370523083559660016e1752L, 3.322090527232917400247098823651437597786e1756L, -8.339387326241218096865362177688582376376e1760L, 2.101842203781264395369771906884644062395e1765L, -5.318704469415522036482913743767085545209e1769L, 1.351288005941730688647540059088127991581e1774L, -3.446853546858473171100748720136784228698e1778L, 8.827284762030783576089954173424852998700e1782L, -2.269642226090373319660782216907175419317e1787L, 5.858820683661708553422363777419430816755e1791L, -1.518385813684321665045387969920683656625e1796L, 3.950661327164595923092260035122668890334e1800L, -1.031976516347387969958181456058243183780e1805L, 2.706317892325103782207094286049104555552e1809L, -7.125140422584701175967252533378906957380e1813L, 1.883260203116768075569432925204868418472e1818L, -4.997193687108743666000994570700725873035e1822L, 1.331182722092654526185433799891693838871e1827L, -3.559930289076558484535632566755216035553e1831L, 9.557281027056970446117541983785660301558e1835L, -2.575805002229372523547972911961335317502e1840L, 6.969058431277067406841032797913179025984e1844L, -1.892842481279278678390672746902260183506e1849L, 5.160964211693777744707760614147460787285e1853L, -1.412602588198037643242529860614298968137e1858L, 3.881313379962387603749693387037174052146e1862L, -1.070542170988009009334148472388319844527e1867L, 2.964094312414144330805731101996829908435e1871L, -8.238350132106899955856124602934281976453e1875L, 2.298504171050560756192352106062598639825e1880L, -6.437303944649223478093890316531995121228e1884L, 1.809727811843121957353712606428292269805e1889L, -5.107047553992257935533518628886728031061e1893L, 1.446674478990385642488446075734631327506e1898L, -4.113513327511444762766719175770513771122e1902L, 1.174067517257431444028448391638451935667e1907L, -3.363630086409895071362533854123306097827e1911L, 9.672868956071838221096869293070568259792e1915L, -2.792101741911955365960369780457612630184e1920L, 8.089710604557382430162031502761771390568e1924L, -2.352650988877130983061761312962677887796e1929L, 6.867549079740051556501575104006222995568e1933L, -2.012161201632998475706904405535757516336e1938L, 5.917489529279588702317256137229398357271e1942L, -1.746718667239329545125902248821502764273e1947L, 5.175069416058975040990816515838893249437e1951L, -1.538913401594651457295303469904084052963e1956L, 4.593185746210984655636051293374195150815e1960L, -1.375981868450401919299150690829612124045e1965L, 4.137207965217520410530508053863759216958e1969L, -1.248518564582257710069294326648626362439e1974L, 3.781575291117895093413381897917341286951e1978L, -1.149575999691408110085856948595444100435e1983L, 3.507413095836612229403470531176947165451e1987L, -1.074032838410645352804690949680310176413e1992L, 3.300857202456564870338466973024760446263e1996L, -1.018149578840803516349758843017979498322e2001L, 3.151876950233613792531594490714752800621e2005L, -9.792574827376149360558532022944033224780e2009L, 3.053456145978161645823454710737904504036e2014L, -9.555442346102849014299990542596620094035e2018L, 3.001037449298122384017009412541525703002e2023L, -9.459120112371096268275049056229023773120e2027L, 2.992168042152196502453442556462819104060e2032L, -9.498922680869041470681858599915282791899e2036L, 3.026307717971075309746179763189393755074e2041L, -9.676079238806159594565350708123427510151e2045L, 3.104778286352798464772361361434013339088e2050L, -9.997786802782252742109475924344598057966e2054L, 3.230847952724856366943939804248186203776e2059L, -1.047769651900498931701604323213605884945e2064L, 3.409958102134053489747140426163802214042e2068L, -1.113687894644055086152064258459886518528e2073L, 3.650114509271160332136458711252217684956e2077L, -1.200536387553969483433239131469825141412e2082L, 3.962482337718333099498977337189304099484e2086L, -1.312441206957064803437100929905979391106e2091L, 4.362246723746013772563799740886664288515e2095L, -1.454975881895253548422481637083633839534e2100L, 4.869831412214692119172895822285084162147e2104L, -1.635618419512383251104125916207188960680e2109L, 5.512611314145041257838234038980389596534e2113L, -1.864392957231340288547618808749072127289e2118L, 6.327317613106621547060670091824665547127e2122L, -2.154772001506498703267302897994526372056e2127L, 7.363426139490286496267931634843475368903e2131L, -2.524950643808031915843604894357998905460e2136L, 8.687956390288096215918373666581638675156e2140L, -2.999656978200020459428228924242615592768e2145L, 1.039231328851609224822335039430898644149e2150L, -3.612742437616019936358910410005123924796e2154L, 1.260211309932738404790711574105022002093e2159L, -4.410916378453971105434385837025433805752e2163L, 1.549140617923265948720013792673729394719e2168L, -5.459173749226782924959103886664322964926e2172L, 1.930343307630952098252884031069043541182e2177L, -6.848749229218425353808144618581305978045e2181L, 2.438117138001365487681440577590059588102e2186L, -8.708873656769794358508423272379627581292e2190L, 3.121268068338199458891764932384819739714e2195L, -1.122430216307539309816165910733145404999e2200L, 4.049900779207199370582177687160985635615e2204L, -1.466167983141158219266077836130256565915e2209L, 5.325678718693772500250292767751070974887e2213L, -1.940955845102272053048140384364058448998e2218L, 7.097467198361219669927211698104447309186e2222L, -2.603968771680987683436428778397387110896e2227L, 9.585403285394812946713320044815117440444e2231L, -3.540176030547640510648455468270569908446e2236L, 1.311827683984025111744358347783996339730e2241L, -4.877124229155333857009747836542843294702e2245L, 1.819213075760490882591173222316749809951e2250L, -6.808221630329265915405178596748950929642e2254L, 2.556299969544109052724772800143396857058e2259L, -9.629763347675306704861859899230073979116e2263L, 3.639508580119285595844040783082958425575e2268L, -1.380037493555816309137481185927387732499e2273L, 5.249980712165216709135893538080020409581e2277L, -2.003737844109055078145975651407367170529e2282L, 7.672522280806944397358668566379646540213e2286L, -2.947454993639165318799389781921184991045e2291L, 1.135966912801707623489383623092951142963e2296L, -4.392293711194501621873299212059053651432e2300L, 1.703813210168560937608104155973968112409e2305L, -6.630636743874062041158387022015853902938e2309L, 2.588742636486379690203698247275411406029e2314L, -1.013959594068423546627946242481463893979e2319L, 3.984265821528043268586235974854766821078e2323L, -1.570614519682157047612769672066387881154e2328L, 6.211297381339606877062824459742129064477e2332L, -2.464246931985476159686671650962783785426e2337L, 9.807833742601662212615240518855757197483e2341L, -3.916036434571217691317276306031837539092e2346L, 1.568566392975837368624727722120313955274e2351L, -6.302885887601142677858008037129298948063e2355L, 2.540704455306077495480843691828334210014e2360L, -1.027412480318234348899627142408950111875e2365L, 4.167823618450297116765978030480648316769e2369L, -1.696076602731914277275203926124423530377e2374L, 6.923904505633301788461482786634220738504e2378L, -2.835463065742506394026733592206185459035e2383L, 1.164828772275756526225951620927486307632e2388L, -4.800242878545012539781545966693324656699e2392L, 1.984381759611877246529319121941597679107e2397L, -8.228979942542641498511023600269641046627e2401L, 3.423130231367101727862739208673375060101e2406L, -1.428418168129733054582191895023094524495e2411L, 5.979153801634459282232521647160044877770e2415L, -2.510581926948409809562349588087762800160e2420L, 1.057443785053915411991029410076722022815e2425L, -4.467723713549428749678277264414266162837e2429L, 1.893474116528533144079731251913008472748e2434L, -8.049601965052954947260081891142509464888e2438L, 3.432648527503971149009691133946275281368e2443L, -1.468324699963694393989960228042259134294e2448L, + // + // 1302-1600: http://www.wolframalpha.com/input/?i=TABLE[N[Bernoulli[i]%2C40]%2C+{i%2C1302%2C1600%2C2}] + 6.300146502435743791500010801885493871234e2452L, -2.711520667146768856688291798851999580833e2457L, 1.170595555513900137297344452318266434006e2462L, -5.069095411973246242900074508988493530542e2466L, 2.201819284807954055092117706033113168896e2471L, -9.593088725189386197503123561368325167085e2475L, 4.192362385909155628936230811010649614060e2480L, -1.837725836941968309866675158105812946762e2485L, 8.080201101491972605313807752565294881374e2489L, -3.563536075527215702966392543784039539240e2494L, 1.576361051321107275181955665159661781175e2499L, -6.994292466180175594372663323941761853364e2503L, 3.112744353537336702834647901141392426258e2508L, -1.389481328370627358752727485697345194612e2513L, 6.221134636655213696041740685131223999953e2517L, -2.793779613656947577224654924852010601105e2522L, 1.258399062987759035354039924686781081603e2527L, -5.685208194704131918461885165870560583895e2531L, 2.576167857759537340210434756292816456179e2536L, -1.170846052338591953257169251219597581763e2541L, 5.337296787116189575571202979672747140313e2545L, -2.440264475369219459038748840841422948951e2550L, 1.119037151526195093932933161706501865175e2555L, -5.146858829220973887154576240993607686435e2559L, 2.374259791963193693837576781321391741634e2564L, -1.098501215269400934956638118646657823799e2569L, 5.097500369683616795005376807036889542869e2573L, -2.372446971688020647583535886090779018865e2578L, 1.107430282014636546248612381377039463753e2583L, -5.184597227131050012643138079903381280471e2587L, 2.434392040100910394476893838832599310265e2592L, -1.146412753331162872665743308094817095949e2597L, 5.414578104816988124950636101250217797539e2601L, -2.564835392810685332173156758121489913946e2606L, 1.218495070518549208066544111736985586178e2611L, -5.805713573821806672815019495319510297824e2615L, 2.774298194574319430697819781128985128618e2620L, -1.329580186505564627453485444017911980430e2625L, 6.390545858902318479863947547243743500916e2629L, -3.080502542499571035376377703435361520427e2634L, 1.489236104239976282318361008292980814533e2639L, -7.220413839991892382038608955317126799684e2643L, 3.510874916591640642524021216241607185085e2648L, -1.712070118580404599831061485055269100525e2653L, 8.372956919832386730490070625622785478703e2657L, -4.106629146981883685523102256292669054596e2662L, 2.019945438530802964718619732330776495740e2667L, -9.964133277392242111939720494354938982970e2671L, 4.929278642971447854669801547226335041410e2676L, -2.445509657169810919463982615395074704130e2681L, 1.216734421265677299127016883839223226884e2686L, -6.071008437677720186241562251151490713584e2690L, 3.037824949882992896564570441252792097027e2695L, -1.524402878612630565501569310883356490225e2700L, 7.671320530781999359200097739951316234193e2704L, -3.871436167706734376478728954716915204399e2709L, 1.959313530432202158587932399068682252335e2714L, -9.944063618400630821320953821427307024297e2718L, 5.061161998202463346818982228476199873781e2723L, -2.583219090831132705328958245740715185448e2728L, 1.322193991367293532684189527174543501836e2733L, -6.786569982732483290873213417465458376706e2737L, 3.493212334804776543395067018414547811062e2742L, -1.803090099978261928508495412750404640933e2747L, 9.333100843930216567894508007158644926767e2751L, -4.844499031405982604449146511179496492045e2756L, 2.521648090959971240812330574936006906830e2761L, -1.316227870932708474838173333385377250286e2766L, 6.889488826832738674261056521130795910494e2770L, -3.616184242864384509259984293501533623932e2775L, 1.903356124758119137116543283603627028779e2780L, -1.004601544584640657081847200643996069583e2785L, 5.317043885597842225603585588404817559596e2789L, -2.821938866752488868682751438901900485500e2794L, 1.501842023003449590337997900945924161741e2799L, -8.014908048137216649348740300633172710524e2803L, 4.289126235121619907138036129192558937445e2808L, -2.301619137231461344870820700320913118444e2813L, 1.238485136850053215006962645111854705210e2818L, -6.682503731149007943059244518074044280490e2822L, 3.615572393938012932030234169574978859655e2827L, -1.961565108627429629104703146282982075623e2832L, 1.067123259692924564435881096382837264046e2837L, -5.821179870182035246401397327057170726418e2841L, 3.184127229476322727732208017279268211356e2846L, -1.746429902183019597973436257300843998825e2851L, 9.604873565299766333876882842813498685054e2855L, -5.296759978724702692134960752308186890356e2860L, 2.928906353338652198977536576170287112391e2865L, -1.623961162577704769945821804737884742792e2870L, 9.028574047002736235613238355032484299017e2874L, -5.033087486357905828950503441308068892610e2879L, 2.813325650062267479031371852434194635210e2884L, -1.576791132296320840138263753339056345362e2889L, 8.861258343945925667272164531504265693289e2893L, -4.993236404321511029440212686547068244002e2898L, 2.821192993950901287717082243608730217471e2903L, -1.598254169674379493385730199445427966752e2908L, 9.078617590346932363947095804057608979359e2912L, -5.170742114456472142154347566092068443393e2917L, 2.952866185102528847516095880416675972086e2922L, -1.690794578626103552690094140317813413244e2927L, 9.707168799669516048238542260085175133847e2931L, -5.587884732306715493795271931175883605707e2936L, 3.225179489154957423492905957887744116530e2941L, -1.866424419669188178697802576490431604300e2946L, 1.082967626854618222657109354056973072044e2951L, -6.300392007169862865282706277272018077291e2955L, 3.675066377245428685118763485986517510658e2960L, -2.149348371085132073107516253339849053182e2965L, 1.260349351812619395000600434630904474324e2970L, -7.409963623771231302980906971935254993610e2974L, 4.367980758467862686643231700861155889684e2979L, -2.581566823350789671250829457603555544100e2984L, 1.529757357568342629912560827243282062227e2989L, -9.088595394263364554625061567617375176719e2993L, 5.413829169254585648363594604231030415354e2998L, -3.233288119606092759447005827969216281573e3003L, 1.936042437734875803183915765854038424658e3008L, -1.162289934202291715747729318797398221667e3013L, 6.995870350500567071550614251287615697508e3017L, -4.221776496490106417392945233048068288503e3022L, 2.554309239868912570382343877718991746122e3027L, -1.549440871550119801225143558087410562418e3032L, 9.423199525954784955533959981278992475051e3036L, -5.745689660772387668861183913170050552119e3041L, 3.512407521007240798565045328376471603253e3046L, -2.152708113797517364614914569890010876143e3051L, 1.322761289733739440340237168659770154654e3056L, -8.148777388506488753591136948542248584098e3060L, 5.032880858479326069741729004270784264612e3065L, -3.116396010103058126269735274818345780360e3070L, 1.934634831148214353514796782480703021435e3075L, -1.204077166243116651938489240924641810276e3080L, 7.513065583444964704795707060501161621868e3084L, -4.699873512563164914493150520500838535415e3089L, 2.947541197349762411713872934523813866703e3094L, -1.853262416286420077763886100673646141885e3099L, 1.168196427912100545575264493997591040800e3104L, -7.382362285873345348505276546404015842875e3108L, 4.677071041058096429847797962954927487730e3113L, -2.970642034084362431442183248944824506476e3118L, 1.891572688282564476274920103912259755482e3123L, -1.207509963440193713810418554061532113326e3128L, 7.727731208240101791845515599659441557781e3132L, -4.957988488048495669466804712012179891532e3137L, 3.188965862446236259925047956715566822864e3142L, -2.056286895821370106507670239256782411337e3147L, 1.329246918771714093479509313343886287414e3152L, -8.614188519577835653765633797787633659253e3156L, + // + // 1602-1900: http://www.wolframalpha.com/input/?i=TABLE[N[Bernoulli[i]%2C40]%2C+{i%2C1602%2C1900%2C2}] + 5.596396533621874175909933615343145642161e3161L, -3.644908483469388437457938883454376864180e3166L, 2.379838409026860469990569665632800095988e3171L, -1.557720925267669865362152155022069166772e3176L, 1.022143420270029721682551084917730373739e3181L, -6.723767358891570842116651998814252095792e3185L, 4.433950491570308179905446963723780229747e3190L, -2.931196854668917448553150023532223509373e3195L, 1.942557068752664549549945921392100172355e3200L, -1.290553202978622786891265558106235068695e3205L, 8.595082329732118303768775883557789195136e3209L, -5.738453265222970049867280061719670658457e3214L, 3.840687915100689856736926915331157331684e3219L, -2.576862441955523551149886625900059307506e3224L, 1.733166107320377310388765047659987844208e3229L, -1.168569552450178559412843683052610870569e3234L, 7.898289836694980777809433306209459851871e3238L, -5.351485909164216694400535493924387979018e3243L, 3.634772439350395177931952925644409735777e3248L, -2.474801048002975145046569303233576339695e3253L, 1.689126939254790850063878942448569759390e3258L, -1.155691524500722774057997965355407962525e3263L, 7.926435404542361405718288670391575676323e3267L, -5.449654814183048796524718620178906854846e3272L, 3.755898589900254795894812942275711835138e3277L, -2.594843902682143854622514329649211211808e3282L, 1.797048752397789969347915328338360264536e3287L, -1.247551415074438712713815166107969504456e3292L, 8.681719521514448143910215886388510318746e3296L, -6.056203898213120922016159444227958572276e3301L, 4.234882876331814099029781995617143573641e3306L, -2.968432911643338866295929748049749932906e3311L, 2.085723508930484816454740610260790948864e3316L, -1.469023169879432026361623513301566735138e3321L, 1.037150346505052892302077637883522696572e3326L, -7.339977067836656769144838365069396168014e3330L, 5.206985412168234130596004552956337839140e3335L, -3.702673773319239583641029108403509825141e3340L, 2.639251227995760315076225206168354089692e3345L, -1.885736353072698581595150856674914203383e3350L, 1.350563292338261784288559687678302458996e3355L, -9.695749980998301526113046898985991802000e3359L, 6.977167462628398202151721319169989304520e3364L, -5.032768280399753942925624560483352299263e3369L, 3.638844963651800168080623511900705036698e3374L, -2.637228631269251606169613775399022890118e3379L, 1.915836351653767108720464847696767898597e3384L, -1.395064293615007319328267865803567670760e3389L, 1.018249052614943190644465556486933211307e3394L, -7.449662162606857550867922631658930320805e3398L, 5.463119632208085241594107781601567713991e3403L, -4.015736541676989144201935890497836963875e3408L, 2.958754190183866660901503059509579790900e3413L, -2.185096074054288399312733179064098492511e3418L, 1.617517444557020250864919655301189186103e3423L, -1.200170662015511746748935675940010250555e3428L, 8.925888349899029449015791684428724952411e3432L, -6.653851763691885517669938275618991145962e3437L, 4.971722031098457895973348076474071155918e3442L, -3.723500582577984967442020337848702786829e3447L, 2.795153783541721373364976034391375710110e3452L, -2.103141577212720698169118819883801186873e3457L, 1.586129575320959267959148073466004084241e3462L, -1.198988457279648730711646682156242973137e3467L, 9.084402368157025658430300252246526602197e3471L, -6.898927494435965163817354296023108913714e3476L, 5.251332286149361587885046891266325872375e3481L, -4.006442950956739933884502808470603581850e3486L, 3.063718202820270282280659950794978994604e3491L, -2.348215284130973783732145823834807395920e3496L, 1.803952490148087317330011096671019781340e3501L, -1.389022326803437345760911068933754707688e3506L, 1.071986115818329525986099441493200866389e3511L, -8.292085224650940719705699485423856363908e3515L, 6.428829064452939640541475198655560890344e3520L, -4.995654440302797445368056643032307686314e3525L, 3.890847042582299188849273838681034339406e3530L, -3.037288555751484681537442833929275697351e3535L, 2.376385803695694695338601696534348875191e3540L, -1.863527130251861900692886008704804849076e3545L, 1.464674913498036269270793715104706378182e3550L, -1.153804954579033578659954846698233083197e3555L, 9.109783835348935092264268296199541780964e3559L, -7.208869193983001804305451104827153729326e3564L, 5.717530734277611949162917337810749919265e3569L, -4.544970302634007326980094771330550661605e3574L, 3.621042850825283032134228901678636353355e3579L, -2.891447067949778492831490654980043715471e3584L, 2.314060419397710657435821461707043283167e3589L, -1.856140759923563235273220981623595304434e3594L, 1.492185412981476596273279338314204171587e3599L, -1.202290032627175365810126250991853594801e3604L, 9.708881154579770196658265042625239421053e3608L, -7.857809850747029705680072304049448493252e3613L, 6.373898598298513400228819113197728735438e3618L, -5.181780406472117449048907989647202286666e3623L, 4.222036621953044040518942750638183171221e3628L, -3.447728386429130175025813550845575613047e3633L, 2.821701521717856346224159586852612710800e3638L, -2.314488376711998526455043944505424906920e3643L, 1.902671298033180765286213227393060711096e3648L, -1.567603736821312488140289549008391847440e3653L, 1.294408945316538946551785312385509945367e3658L, -1.071194533081615830960091702262923009420e3663L, 8.884351908108581551151252566466606126397e3667L, -7.384866682828103669170236267589653324531e3672L, 6.152023838008155718180876735217718355563e3677L, -5.136304310431705506236573876510219357975e3682L, 4.297736808124296434723193397876220759378e3687L, -3.603994887745884762510172194982172483480e3692L, 3.028884745605031552399167746007361297342e3697L, -2.551141302205187365552982635794121855138e3702L, 2.153467982869535549299173317536193051608e3707L, -1.821769476343602094059466497311600827296e3712L, 1.544537580582347892980177956984101211006e3717L, -1.312358705945937257247030754517293537539e3722L, 1.117518229297781388884979995402355617235e3727L, -9.536820860779441793021624381677086661097e3731L, 8.156400668831968026931547065507466530546e3736L, -6.990984948728184142718575396052260691181e3741L, 6.005124901126818071638224144541102727563e3746L, -5.169500241880947716732682089328427995109e3751L, 4.459815478235310026240134567325749844182e3756L, -3.855902253361684187081283218890336962427e3761L, 3.340988024176995223515640815937037040546e3766L, -2.901099226680215736735094376078800376829e3771L, 2.524573363444334459448089563912567842927e3776L, -2.201659455716348555524529213295341212492e3781L, 1.924190302190936448078364755844591374353e3786L, -1.685313186099770223843319514432495898517e3791L, 1.479268235966730475749985741048766689808e3796L, -1.301205702893883803117530921635013780575e3801L, 1.147035071153450453405384269242743907426e3806L, -1.013300250456366849150496776951686112298e3811L, 8.970761720605591762300958007557533865346e3815L, -7.958829781488943084496783248922217392838e3820L, 7.076146954685024795720193943027902028642e3825L, -6.304798526260409199660290516451546966159e3830L, 5.629519616664188107056583939722984509867e3835L, -5.037281594099054092767959480843344929292e3840L, 4.516946091316834843581919268794683123349e3845L, -4.058975118925834202620358386772092359951e3850L, 3.655187798978978909014603682039470653549e3855L, -3.298555903041546671060101785513812175322e3860L, 2.983031738662727912016882399515879119620e3865L, -2.703403043317732979516341931451317866898e3870L, 2.455170460800096241793872443768546335444e3875L, -2.234443928432490538417605502448376856290e3880L, 2.037854924078003280537856980560782325730e3885L, -1.862482033918775734840779765743099458137e3890L, + // + // 1902-2200: http://www.wolframalpha.com/input/?i=TABLE[N[Bernoulli[i]%2C40]%2C+{i%2C1902%2C2200%2C2}] + 1.705787724951999960095629912416210969679e3895L, -1.565564556110550991891247404758895970376e3900L, 1.439889351869832939488618785632174464789e3905L, -1.327084102784257406218693901793045990520e3910L, 1.225682557296027075027021534960026145706e3915L, -1.134401635488994148555787301654561211982e3920L, 1.052116934052356802920509999705307165985e3925L, -9.778417073593082219082361206542342793584e3929L, 9.107088061888562704837019028349522303725e3934L, -8.499551364633102138471246155980056936129e3939L, 7.949082681085658044610890152056533167407e3944L, -7.449748809722797718736397140511396011691e3949L, 6.996307824769340144608141799981589288378e3954L, -6.584122718472954006131003060359621706243e3959L, 6.209086595833487707192492087176843233407e3964L, -5.867557793863165391821489909125720982339e3969L, 5.556303538475260373917478405626416604297e3974L, -5.272450955936249442242634142613834212778e3979L, 5.013444428433789818228792126117223030641e3984L, -4.777008429684552423800736200488532033034e3989L, 4.561115100786341787876705283291018781137e3994L, -4.363955932181992701667719449097126840439e3999L, 4.183917007557000586305945495258591147615e4004L, -4.019557342177353010692923286760895584096e4009L, 3.869589913635745758786275231296652917580e4014L, -3.732865038934070181861017140563175000872e4019L, 3.608355799736107390800162778737339576843e4024L, -3.495145258697474565347261083975193776541e4029L, 3.392415245050326563747729613872524362741e4034L, -3.299436517958948801426629481782413630714e4039L, 3.215560142306355508598119430378551642857e4044L, -3.140209934146377815556058799557727461298e4049L, 3.072875852591406752692761744649563131272e4054L, -3.013108231854799187724018548255922550991e4059L, 2.960512761914376268185064129600549308882e4064L, -2.914746139139036596123006476633770383901e4069L, 2.875512319506974985103149834921665445532e4074L, -2.842559316984704569380036093537576068104e4079L, 2.815676498441436148701483904115879856704e4084L, -2.794692334326268275058539147656334465534e4089L, 2.779472571396106785963004020814493340829e4094L, -2.769918800191406321625251621260024635680e4099L, 2.765967395840433013288935879837390099329e4104L, -2.767588816244119880300161388073836623878e4109L, 2.774787246856347651152278076466043136230e4114L, -2.787600586224957950622601135620189837948e4119L, 2.806100771288225169339048358106052817280e4124L, -2.830394446218080573456394167711739786431e4129L, 2.860623983452244712039094143642843717029e4134L, -2.896968870550611723525738907034588104300e4139L, 2.939647481737606306044335918078617963078e4144L, -2.988919258547518526076380181812161398808e4149L, 3.045087329976721023952450383837883029431e4154L, -3.108501609077197464748958150625867523408e4159L, 3.179562410123820875787052833975010965963e4164L, -3.258724638491880104953913719767939138170e4169L, 3.346502614347964869115073881474258766546e4174L, -3.443475601364631413158991572423086599816e4179L, 3.550294123121350747300886840907918182129e4184L, -3.667687162886053419715985091863398517145e4189L, 3.796470357354794420044278000297864085607e4194L, -3.937555311976846882455930574021795626971e4199L, 4.091960185075595842547638450930710467324e4204L, -4.260821710519620959138720129506770036460e4209L, 4.445408854703156440576808070360934740837e4214L, -4.647138333645908068599900650548418672065e4219L, 4.867592250805288922190809906525766574205e4224L, -5.108538156515551259475573296900660666192e4229L, 5.371951876776035157276013631113314852508e4234L, -5.660043513521220243900043448456234873940e4239L, 5.975287081834808618140945840817834710330e4244L, -6.320454323372684034118816565375206053746e4249L, 6.698653321371992324876559665938996023646e4254L, -7.113372643219128807424340495235606473967e4259L, 7.568531854202750881338746432078817214052e4264L, -8.068539383842553693076672384509126681464e4269L, 8.618358887685935324188596304168259394311e4274L, -9.223585437012291673660319256730398171887e4279L, 9.890533091606747031464718533600572123091e4284L, -1.062633567277107015128545384570274268438e4290L, 1.143906286231591191271274413511275981288e4295L, -1.233785411712565904499340744089870916842e4300L, 1.333307331840530219050170916015276125870e4305L, -1.443648758235403286296065629219598769529e4310L, 1.566147425967471851736562867318748510088e4315L, -1.702326086290842780634120184324081017286e4320L, 1.853920350455786350409148418966087344063e4325L, -2.022911043115598592197907512410632615740e4330L, 2.211561842992792253055716743938240466613e4335L, -2.422463130294011318178080247305407476096e4340L, 2.658583129381772791030436640519847627789e4345L, -2.923327636881988941081365085520742216540e4350L, 3.220609866329557159104267531058019683271e4355L, -3.554932228621330128152149026066400241546e4360L, 3.931482212643167323798366327390058684499e4365L, -4.356244944221399578650235478583297389113e4370L, 4.836135498303121165971331625888490168138e4375L, -5.379154636371461359750682662639062606297e4380L, 5.994572359716861309678596804350346692501e4385L, -6.693144535124290060793936095397161934045e4390L, 7.487368894313509797084395689517008597061e4395L, -8.391787970609807810531578161564037339793e4400L, 9.423348062978921203475110312003096820035e4405L, -1.060182516651648405903017734022504884319e4411L, 1.195033105063952979885086754342706651656e4416L, -1.349591538868673992167798923586925758429e4421L, 1.527028315253291113905307092657539132480e4426L, -1.731065051510920640409442255224015234974e4431L, 1.966076741510092840076264635935585216200e4436L, -2.237214093245750681191361238831105906202e4441L, 2.550550094903891445719729187215253324232e4446L, -2.913255853313667303707651906277658164129e4451L, 3.333811847072394764285817140850092324169e4456L, -3.822262084288044913490118858492563410392e4461L, 4.390520310533864198186202368026630430120e4466L, -5.052739449335052080092114976206610871466e4471L, 5.825757966350870043117899492954521458799e4476L, -6.729639942938203582008846884575881320532e4481L, 7.788329466816396015493306357116312471970e4486L, -9.030444674469025073047417528762134025409e4491L, 1.049024263381993629167658236142000524752e4497L, -1.220879351508964912255081664072251573277e4502L, 1.423541151220109512749655991050110438471e4507L, -1.662940118618541616964708044356967429362e4512L, 1.946219185900482116137855064775635250366e4517L, -2.281995008842006909631764011781911322493e4522L, 2.680678198213108543648324254258111216040e4527L, -3.154866427472784086389609599207759103500e4532L, 3.719827710160801797530420206201570269720e4537L, -4.394095404360277919140027580071549980218e4542L, 5.200201854779615608741690339830306148442e4547L, -6.165584312943608652377791415603277251516e4552L, 7.323705248531382981433751104158852636445e4557L, -8.715439846124090647163930834760361817820e4562L, 1.039079696609215651011736087603304766850e4568L, -1.241105689556982425619608247473478857800e4573L, 1.485143079696380339521658550262280772546e4578L, -1.780437412164973637340821168154300094802e4583L, 2.138372099157518882088209435171770222745e4588L, -2.572985071149069551034276570909360759588e4593L, 3.101615379617643734762997559011097203354e4598L, -3.745713657616368229906151946770042703357e4603L, 4.531859496161940719835150033082561700677e4608L, -5.493040495326927998321538336584233566465e4613L, 6.670262730603009306595018122252730741798e4618L, -8.114581584793494903775255213273982440688e4623L, 9.889666561810883044159054730371102725871e4628L, -1.207504541653929734716275932570097623330e4634L, 1.477021377885843688233899471354959308782e4639L, -1.809984912147908767583043524070645821179e4644L, + // + // 2202-2320: http://www.wolframalpha.com/input/?i=TABLE[N[Bernoulli[i]%2C40]%2C+{i%2C2202%2C2320%2C2}] + 2.222043594325228980916360265527780300093e4649L, -2.732869701246338361699515268224049951411e4654L, 3.367233945421922463553518272642397177145e4659L, -4.156377225041273602431272489314020150392e4664L, 5.139764368092890466235162431795350591151e4669L, -6.367329693760865476879589228002216011370e4674L, 7.902356742934106007362514378717026407839e4679L, -9.825176966314431712897976595483070301406e4684L, 1.223792760178593282435724837135946867088e4690L, -1.527068151452750404853140815207477555192e4695L, 1.908935682572268829496101580401263597905e4700L, -2.390593888616966248780378941331847473699e4705L, 2.999171106576893833644521002894489856321e4710L, -3.769440655453736670024798444784356437578e4715L, 4.746047769851891438576002047529258107351e4720L, -5.986405469241447720766576164546767533359e4725L, 7.564466155536872051712519119999711534616e4730L, -9.575641408047918720040356745796976488951e4735L, 1.214322951835035451699619713803395497423e4741L, -1.542682591979864353012093794301924196234e4746L, 1.963334539793192183270983986567556358603e4751L, -2.503148969013901182572118121398034622584e4756L, 3.197076711250102964526567664729089847162e4761L, -4.090653552025822488578293526174572934858e4766L, 5.243302769651520536759521264615159906699e4771L, -6.732697170903775309261288127044088674182e4776L, 8.660529543801770516930589210020128142543e4781L, -1.116015823611149634592870112730519454113e4787L, 1.440675306432920129218036927923030695520e4792L, -1.863078034853256227415397798026969938881e4797L, 2.413595413458810442409656314019115041699e4802L, -3.132317029597258599678590012779717945144e4807L, 4.072246763371584312534474102756137619716e4812L, -5.303577511521827157146305369181950467569e4817L, 6.919417518688636032335131253584331645491e4822L, -9.043473312934241153732087612484569398979e4827L, 1.184037400265044213826044590639924237359e4833L, -1.552956685415800894409743993367334099777e4838L, 2.040404893052952221581694807126473204625e4843L, -2.685565763841580219033402331219206776210e4848L, 3.540927057361929050327811875290025248120e4853L, -4.676912607538885419407656762767991163574e4858L, 6.188165903566760647569323704623433330229e4863L, -8.202087471895029964699042637255411806373e4868L, 1.089045274355389654614196651761310970580e4874L, -1.448524684976553869119447042300206226148e4879L, 1.930028100376784839502387280956424581974e4884L, -2.576074799096023589462128312524664980682e4889L, 3.444369635011990347297134928452972402038e4894L, -4.613354441299253694113609154769978684993e4899L, 6.189834306866879018555349507257537840922e4904L, -8.319470760665157534580593571258276368233e4909L, 1.120124240070996761986102680587384813245e4915L, -1.510740451399746828351090108638980398124e4920L, 2.041108231091323198877509959371257503819e4925L, -2.762447751447012472733302936575873838539e4930L, +#endif + }}; + + return bernoulli_data[n]; +} + +template <class T> +inline T unchecked_bernoulli_imp(std::size_t n, const mpl::int_<4>& ) +{ + // + // Special case added for multiprecision types that have no conversion from long long, + // there are very few such types, but mpfr_class is one. + // + static const boost::array<boost::int32_t, 1 + max_bernoulli_b2n<T>::value> numerators = + {{ + boost::int32_t( +1LL), + boost::int32_t( +1LL), + boost::int32_t( -1LL), + boost::int32_t( +1LL), + boost::int32_t( -1LL), + boost::int32_t( +5LL), + boost::int32_t( -691LL), + boost::int32_t( +7LL), + boost::int32_t( -3617LL), + boost::int32_t( +43867LL), + boost::int32_t( -174611LL), + boost::int32_t( +854513LL), + }}; + + static const boost::array<boost::int32_t, 1 + max_bernoulli_b2n<T>::value> denominators = + {{ + boost::int32_t( 1LL), + boost::int32_t( 6LL), + boost::int32_t( 30LL), + boost::int32_t( 42LL), + boost::int32_t( 30LL), + boost::int32_t( 66LL), + boost::int32_t( 2730LL), + boost::int32_t( 6LL), + boost::int32_t( 510LL), + boost::int32_t( 798LL), + boost::int32_t( 330LL), + boost::int32_t( 138LL), + }}; + return T(numerators[n]) / T(denominators[n]); +} + +} // namespace detail + +template<class T> +inline BOOST_MATH_CONSTEXPR_TABLE_FUNCTION T unchecked_bernoulli_b2n(const std::size_t n) +{ + typedef mpl::int_<detail::bernoulli_imp_variant<T>::value> tag_type; + + return detail::unchecked_bernoulli_imp<T>(n, tag_type()); +} + +}} // namespaces + +#endif // BOOST_MATH_UNCHECKED_BERNOULLI_HPP diff --git a/src/third_party/boost-1.70.0/boost/math/special_functions/detail/unchecked_factorial.hpp b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/unchecked_factorial.hpp new file mode 100644 index 00000000000..642df7ce504 --- /dev/null +++ b/src/third_party/boost-1.70.0/boost/math/special_functions/detail/unchecked_factorial.hpp @@ -0,0 +1,815 @@ +// Copyright John Maddock 2006. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_SP_UC_FACTORIALS_HPP +#define BOOST_MATH_SP_UC_FACTORIALS_HPP + +#ifdef _MSC_VER +#pragma once +#endif + +#ifdef BOOST_MSVC +#pragma warning(push) // Temporary until lexical cast fixed. +#pragma warning(disable: 4127 4701) +#endif +#ifndef BOOST_MATH_NO_LEXICAL_CAST +#include <boost/lexical_cast.hpp> +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +#include <cmath> +#include <boost/math/special_functions/math_fwd.hpp> + +#ifdef BOOST_MATH_HAVE_CONSTEXPR_TABLES +#include <array> +#else +#include <boost/array.hpp> +#endif + +#if defined(__GNUC__) && defined(BOOST_MATH_USE_FLOAT128) +// +// This is the only way we can avoid +// warning: non-standard suffix on floating constant [-Wpedantic] +// when building with -Wall -pedantic. Neither __extension__ +// nor #pragma dianostic ignored work :( +// +#pragma GCC system_header +#endif + +namespace boost { namespace math +{ +// Forward declarations: +template <class T> +struct max_factorial; + +// Definitions: +template <> +inline BOOST_MATH_CONSTEXPR_TABLE_FUNCTION float unchecked_factorial<float>(unsigned i BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(float)) +{ +#ifdef BOOST_MATH_HAVE_CONSTEXPR_TABLES + constexpr std::array<float, 35> factorials = { { +#else + static const boost::array<float, 35> factorials = {{ +#endif + 1.0F, + 1.0F, + 2.0F, + 6.0F, + 24.0F, + 120.0F, + 720.0F, + 5040.0F, + 40320.0F, + 362880.0F, + 3628800.0F, + 39916800.0F, + 479001600.0F, + 6227020800.0F, + 87178291200.0F, + 1307674368000.0F, + 20922789888000.0F, + 355687428096000.0F, + 6402373705728000.0F, + 121645100408832000.0F, + 0.243290200817664e19F, + 0.5109094217170944e20F, + 0.112400072777760768e22F, + 0.2585201673888497664e23F, + 0.62044840173323943936e24F, + 0.15511210043330985984e26F, + 0.403291461126605635584e27F, + 0.10888869450418352160768e29F, + 0.304888344611713860501504e30F, + 0.8841761993739701954543616e31F, + 0.26525285981219105863630848e33F, + 0.822283865417792281772556288e34F, + 0.26313083693369353016721801216e36F, + 0.868331761881188649551819440128e37F, + 0.29523279903960414084761860964352e39F, + }}; + + return factorials[i]; +} + +template <> +struct max_factorial<float> +{ + BOOST_STATIC_CONSTANT(unsigned, value = 34); +}; + + +template <> +inline BOOST_MATH_CONSTEXPR_TABLE_FUNCTION long double unchecked_factorial<long double>(unsigned i BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(long double)) +{ +#ifdef BOOST_MATH_HAVE_CONSTEXPR_TABLES + constexpr std::array<long double, 171> factorials = { { +#else + static const boost::array<long double, 171> factorials = {{ +#endif + 1L, + 1L, + 2L, + 6L, + 24L, + 120L, + 720L, + 5040L, + 40320L, + 362880.0L, + 3628800.0L, + 39916800.0L, + 479001600.0L, + 6227020800.0L, + 87178291200.0L, + 1307674368000.0L, + 20922789888000.0L, + 355687428096000.0L, + 6402373705728000.0L, + 121645100408832000.0L, + 0.243290200817664e19L, + 0.5109094217170944e20L, + 0.112400072777760768e22L, + 0.2585201673888497664e23L, + 0.62044840173323943936e24L, + 0.15511210043330985984e26L, + 0.403291461126605635584e27L, + 0.10888869450418352160768e29L, + 0.304888344611713860501504e30L, + 0.8841761993739701954543616e31L, + 0.26525285981219105863630848e33L, + 0.822283865417792281772556288e34L, + 0.26313083693369353016721801216e36L, + 0.868331761881188649551819440128e37L, + 0.29523279903960414084761860964352e39L, + 0.103331479663861449296666513375232e41L, + 0.3719933267899012174679994481508352e42L, + 0.137637530912263450463159795815809024e44L, + 0.5230226174666011117600072241000742912e45L, + 0.203978820811974433586402817399028973568e47L, + 0.815915283247897734345611269596115894272e48L, + 0.3345252661316380710817006205344075166515e50L, + 0.1405006117752879898543142606244511569936e52L, + 0.6041526306337383563735513206851399750726e53L, + 0.265827157478844876804362581101461589032e55L, + 0.1196222208654801945619631614956577150644e57L, + 0.5502622159812088949850305428800254892962e58L, + 0.2586232415111681806429643551536119799692e60L, + 0.1241391559253607267086228904737337503852e62L, + 0.6082818640342675608722521633212953768876e63L, + 0.3041409320171337804361260816606476884438e65L, + 0.1551118753287382280224243016469303211063e67L, + 0.8065817517094387857166063685640376697529e68L, + 0.427488328406002556429801375338939964969e70L, + 0.2308436973392413804720927426830275810833e72L, + 0.1269640335365827592596510084756651695958e74L, + 0.7109985878048634518540456474637249497365e75L, + 0.4052691950487721675568060190543232213498e77L, + 0.2350561331282878571829474910515074683829e79L, + 0.1386831185456898357379390197203894063459e81L, + 0.8320987112741390144276341183223364380754e82L, + 0.507580213877224798800856812176625227226e84L, + 0.3146997326038793752565312235495076408801e86L, + 0.1982608315404440064116146708361898137545e88L, + 0.1268869321858841641034333893351614808029e90L, + 0.8247650592082470666723170306785496252186e91L, + 0.5443449390774430640037292402478427526443e93L, + 0.3647111091818868528824985909660546442717e95L, + 0.2480035542436830599600990418569171581047e97L, + 0.1711224524281413113724683388812728390923e99L, + 0.1197857166996989179607278372168909873646e101L, + 0.8504785885678623175211676442399260102886e102L, + 0.6123445837688608686152407038527467274078e104L, + 0.4470115461512684340891257138125051110077e106L, + 0.3307885441519386412259530282212537821457e108L, + 0.2480914081139539809194647711659403366093e110L, + 0.188549470166605025498793226086114655823e112L, + 0.1451830920282858696340707840863082849837e114L, + 0.1132428117820629783145752115873204622873e116L, + 0.8946182130782975286851441715398316520698e117L, + 0.7156945704626380229481153372318653216558e119L, + 0.5797126020747367985879734231578109105412e121L, + 0.4753643337012841748421382069894049466438e123L, + 0.3945523969720658651189747118012061057144e125L, + 0.3314240134565353266999387579130131288001e127L, + 0.2817104114380550276949479442260611594801e129L, + 0.2422709538367273238176552320344125971528e131L, + 0.210775729837952771721360051869938959523e133L, + 0.1854826422573984391147968456455462843802e135L, + 0.1650795516090846108121691926245361930984e137L, + 0.1485715964481761497309522733620825737886e139L, + 0.1352001527678402962551665687594951421476e141L, + 0.1243841405464130725547532432587355307758e143L, + 0.1156772507081641574759205162306240436215e145L, + 0.1087366156656743080273652852567866010042e147L, + 0.103299784882390592625997020993947270954e149L, + 0.9916779348709496892095714015418938011582e150L, + 0.9619275968248211985332842594956369871234e152L, + 0.942689044888324774562618574305724247381e154L, + 0.9332621544394415268169923885626670049072e156L, + 0.9332621544394415268169923885626670049072e158L, + 0.9425947759838359420851623124482936749562e160L, + 0.9614466715035126609268655586972595484554e162L, + 0.990290071648618040754671525458177334909e164L, + 0.1029901674514562762384858386476504428305e167L, + 0.1081396758240290900504101305800329649721e169L, + 0.1146280563734708354534347384148349428704e171L, + 0.1226520203196137939351751701038733888713e173L, + 0.132464181945182897449989183712183259981e175L, + 0.1443859583202493582204882102462797533793e177L, + 0.1588245541522742940425370312709077287172e179L, + 0.1762952551090244663872161047107075788761e181L, + 0.1974506857221074023536820372759924883413e183L, + 0.2231192748659813646596607021218715118256e185L, + 0.2543559733472187557120132004189335234812e187L, + 0.2925093693493015690688151804817735520034e189L, + 0.339310868445189820119825609358857320324e191L, + 0.396993716080872089540195962949863064779e193L, + 0.4684525849754290656574312362808384164393e195L, + 0.5574585761207605881323431711741977155627e197L, + 0.6689502913449127057588118054090372586753e199L, + 0.8094298525273443739681622845449350829971e201L, + 0.9875044200833601362411579871448208012564e203L, + 0.1214630436702532967576624324188129585545e206L, + 0.1506141741511140879795014161993280686076e208L, + 0.1882677176888926099743767702491600857595e210L, + 0.237217324288004688567714730513941708057e212L, + 0.3012660018457659544809977077527059692324e214L, + 0.3856204823625804217356770659234636406175e216L, + 0.4974504222477287440390234150412680963966e218L, + 0.6466855489220473672507304395536485253155e220L, + 0.8471580690878820510984568758152795681634e222L, + 0.1118248651196004307449963076076169029976e225L, + 0.1487270706090685728908450891181304809868e227L, + 0.1992942746161518876737324194182948445223e229L, + 0.269047270731805048359538766214698040105e231L, + 0.3659042881952548657689727220519893345429e233L, + 0.5012888748274991661034926292112253883237e235L, + 0.6917786472619488492228198283114910358867e237L, + 0.9615723196941089004197195613529725398826e239L, + 0.1346201247571752460587607385894161555836e242L, + 0.1898143759076170969428526414110767793728e244L, + 0.2695364137888162776588507508037290267094e246L, + 0.3854370717180072770521565736493325081944e248L, + 0.5550293832739304789551054660550388118e250L, + 0.80479260574719919448490292577980627711e252L, + 0.1174997204390910823947958271638517164581e255L, + 0.1727245890454638911203498659308620231933e257L, + 0.2556323917872865588581178015776757943262e259L, + 0.380892263763056972698595524350736933546e261L, + 0.571338395644585459047893286526105400319e263L, + 0.8627209774233240431623188626544191544816e265L, + 0.1311335885683452545606724671234717114812e268L, + 0.2006343905095682394778288746989117185662e270L, + 0.308976961384735088795856467036324046592e272L, + 0.4789142901463393876335775239063022722176e274L, + 0.7471062926282894447083809372938315446595e276L, + 0.1172956879426414428192158071551315525115e279L, + 0.1853271869493734796543609753051078529682e281L, + 0.2946702272495038326504339507351214862195e283L, + 0.4714723635992061322406943211761943779512e285L, + 0.7590705053947218729075178570936729485014e287L, + 0.1229694218739449434110178928491750176572e290L, + 0.2004401576545302577599591653441552787813e292L, + 0.3287218585534296227263330311644146572013e294L, + 0.5423910666131588774984495014212841843822e296L, + 0.9003691705778437366474261723593317460744e298L, + 0.1503616514864999040201201707840084015944e301L, + 0.2526075744973198387538018869171341146786e303L, + 0.4269068009004705274939251888899566538069e305L, + 0.7257415615307998967396728211129263114717e307L, + }}; + + return factorials[i]; +} + +template <> +struct max_factorial<long double> +{ + BOOST_STATIC_CONSTANT(unsigned, value = 170); +}; + +#ifdef BOOST_MATH_USE_FLOAT128 + +template <> +inline BOOST_MATH_CONSTEXPR_TABLE_FUNCTION BOOST_MATH_FLOAT128_TYPE unchecked_factorial<BOOST_MATH_FLOAT128_TYPE>(unsigned i) +{ +#ifdef BOOST_MATH_HAVE_CONSTEXPR_TABLES + constexpr std::array<BOOST_MATH_FLOAT128_TYPE, 171> factorials = { { +#else + static const boost::array<BOOST_MATH_FLOAT128_TYPE, 171> factorials = { { +#endif + 1, + 1, + 2, + 6, + 24, + 120, + 720, + 5040, + 40320, + 362880.0Q, + 3628800.0Q, + 39916800.0Q, + 479001600.0Q, + 6227020800.0Q, + 87178291200.0Q, + 1307674368000.0Q, + 20922789888000.0Q, + 355687428096000.0Q, + 6402373705728000.0Q, + 121645100408832000.0Q, + 0.243290200817664e19Q, + 0.5109094217170944e20Q, + 0.112400072777760768e22Q, + 0.2585201673888497664e23Q, + 0.62044840173323943936e24Q, + 0.15511210043330985984e26Q, + 0.403291461126605635584e27Q, + 0.10888869450418352160768e29Q, + 0.304888344611713860501504e30Q, + 0.8841761993739701954543616e31Q, + 0.26525285981219105863630848e33Q, + 0.822283865417792281772556288e34Q, + 0.26313083693369353016721801216e36Q, + 0.868331761881188649551819440128e37Q, + 0.29523279903960414084761860964352e39Q, + 0.103331479663861449296666513375232e41Q, + 0.3719933267899012174679994481508352e42Q, + 0.137637530912263450463159795815809024e44Q, + 0.5230226174666011117600072241000742912e45Q, + 0.203978820811974433586402817399028973568e47Q, + 0.815915283247897734345611269596115894272e48Q, + 0.3345252661316380710817006205344075166515e50Q, + 0.1405006117752879898543142606244511569936e52Q, + 0.6041526306337383563735513206851399750726e53Q, + 0.265827157478844876804362581101461589032e55Q, + 0.1196222208654801945619631614956577150644e57Q, + 0.5502622159812088949850305428800254892962e58Q, + 0.2586232415111681806429643551536119799692e60Q, + 0.1241391559253607267086228904737337503852e62Q, + 0.6082818640342675608722521633212953768876e63Q, + 0.3041409320171337804361260816606476884438e65Q, + 0.1551118753287382280224243016469303211063e67Q, + 0.8065817517094387857166063685640376697529e68Q, + 0.427488328406002556429801375338939964969e70Q, + 0.2308436973392413804720927426830275810833e72Q, + 0.1269640335365827592596510084756651695958e74Q, + 0.7109985878048634518540456474637249497365e75Q, + 0.4052691950487721675568060190543232213498e77Q, + 0.2350561331282878571829474910515074683829e79Q, + 0.1386831185456898357379390197203894063459e81Q, + 0.8320987112741390144276341183223364380754e82Q, + 0.507580213877224798800856812176625227226e84Q, + 0.3146997326038793752565312235495076408801e86Q, + 0.1982608315404440064116146708361898137545e88Q, + 0.1268869321858841641034333893351614808029e90Q, + 0.8247650592082470666723170306785496252186e91Q, + 0.5443449390774430640037292402478427526443e93Q, + 0.3647111091818868528824985909660546442717e95Q, + 0.2480035542436830599600990418569171581047e97Q, + 0.1711224524281413113724683388812728390923e99Q, + 0.1197857166996989179607278372168909873646e101Q, + 0.8504785885678623175211676442399260102886e102Q, + 0.6123445837688608686152407038527467274078e104Q, + 0.4470115461512684340891257138125051110077e106Q, + 0.3307885441519386412259530282212537821457e108Q, + 0.2480914081139539809194647711659403366093e110Q, + 0.188549470166605025498793226086114655823e112Q, + 0.1451830920282858696340707840863082849837e114Q, + 0.1132428117820629783145752115873204622873e116Q, + 0.8946182130782975286851441715398316520698e117Q, + 0.7156945704626380229481153372318653216558e119Q, + 0.5797126020747367985879734231578109105412e121Q, + 0.4753643337012841748421382069894049466438e123Q, + 0.3945523969720658651189747118012061057144e125Q, + 0.3314240134565353266999387579130131288001e127Q, + 0.2817104114380550276949479442260611594801e129Q, + 0.2422709538367273238176552320344125971528e131Q, + 0.210775729837952771721360051869938959523e133Q, + 0.1854826422573984391147968456455462843802e135Q, + 0.1650795516090846108121691926245361930984e137Q, + 0.1485715964481761497309522733620825737886e139Q, + 0.1352001527678402962551665687594951421476e141Q, + 0.1243841405464130725547532432587355307758e143Q, + 0.1156772507081641574759205162306240436215e145Q, + 0.1087366156656743080273652852567866010042e147Q, + 0.103299784882390592625997020993947270954e149Q, + 0.9916779348709496892095714015418938011582e150Q, + 0.9619275968248211985332842594956369871234e152Q, + 0.942689044888324774562618574305724247381e154Q, + 0.9332621544394415268169923885626670049072e156Q, + 0.9332621544394415268169923885626670049072e158Q, + 0.9425947759838359420851623124482936749562e160Q, + 0.9614466715035126609268655586972595484554e162Q, + 0.990290071648618040754671525458177334909e164Q, + 0.1029901674514562762384858386476504428305e167Q, + 0.1081396758240290900504101305800329649721e169Q, + 0.1146280563734708354534347384148349428704e171Q, + 0.1226520203196137939351751701038733888713e173Q, + 0.132464181945182897449989183712183259981e175Q, + 0.1443859583202493582204882102462797533793e177Q, + 0.1588245541522742940425370312709077287172e179Q, + 0.1762952551090244663872161047107075788761e181Q, + 0.1974506857221074023536820372759924883413e183Q, + 0.2231192748659813646596607021218715118256e185Q, + 0.2543559733472187557120132004189335234812e187Q, + 0.2925093693493015690688151804817735520034e189Q, + 0.339310868445189820119825609358857320324e191Q, + 0.396993716080872089540195962949863064779e193Q, + 0.4684525849754290656574312362808384164393e195Q, + 0.5574585761207605881323431711741977155627e197Q, + 0.6689502913449127057588118054090372586753e199Q, + 0.8094298525273443739681622845449350829971e201Q, + 0.9875044200833601362411579871448208012564e203Q, + 0.1214630436702532967576624324188129585545e206Q, + 0.1506141741511140879795014161993280686076e208Q, + 0.1882677176888926099743767702491600857595e210Q, + 0.237217324288004688567714730513941708057e212Q, + 0.3012660018457659544809977077527059692324e214Q, + 0.3856204823625804217356770659234636406175e216Q, + 0.4974504222477287440390234150412680963966e218Q, + 0.6466855489220473672507304395536485253155e220Q, + 0.8471580690878820510984568758152795681634e222Q, + 0.1118248651196004307449963076076169029976e225Q, + 0.1487270706090685728908450891181304809868e227Q, + 0.1992942746161518876737324194182948445223e229Q, + 0.269047270731805048359538766214698040105e231Q, + 0.3659042881952548657689727220519893345429e233Q, + 0.5012888748274991661034926292112253883237e235Q, + 0.6917786472619488492228198283114910358867e237Q, + 0.9615723196941089004197195613529725398826e239Q, + 0.1346201247571752460587607385894161555836e242Q, + 0.1898143759076170969428526414110767793728e244Q, + 0.2695364137888162776588507508037290267094e246Q, + 0.3854370717180072770521565736493325081944e248Q, + 0.5550293832739304789551054660550388118e250Q, + 0.80479260574719919448490292577980627711e252Q, + 0.1174997204390910823947958271638517164581e255Q, + 0.1727245890454638911203498659308620231933e257Q, + 0.2556323917872865588581178015776757943262e259Q, + 0.380892263763056972698595524350736933546e261Q, + 0.571338395644585459047893286526105400319e263Q, + 0.8627209774233240431623188626544191544816e265Q, + 0.1311335885683452545606724671234717114812e268Q, + 0.2006343905095682394778288746989117185662e270Q, + 0.308976961384735088795856467036324046592e272Q, + 0.4789142901463393876335775239063022722176e274Q, + 0.7471062926282894447083809372938315446595e276Q, + 0.1172956879426414428192158071551315525115e279Q, + 0.1853271869493734796543609753051078529682e281Q, + 0.2946702272495038326504339507351214862195e283Q, + 0.4714723635992061322406943211761943779512e285Q, + 0.7590705053947218729075178570936729485014e287Q, + 0.1229694218739449434110178928491750176572e290Q, + 0.2004401576545302577599591653441552787813e292Q, + 0.3287218585534296227263330311644146572013e294Q, + 0.5423910666131588774984495014212841843822e296Q, + 0.9003691705778437366474261723593317460744e298Q, + 0.1503616514864999040201201707840084015944e301Q, + 0.2526075744973198387538018869171341146786e303Q, + 0.4269068009004705274939251888899566538069e305Q, + 0.7257415615307998967396728211129263114717e307Q, + } }; + + return factorials[i]; +} + +template <> +struct max_factorial<BOOST_MATH_FLOAT128_TYPE> +{ + BOOST_STATIC_CONSTANT(unsigned, value = 170); +}; + +#endif + +template <> +inline BOOST_MATH_CONSTEXPR_TABLE_FUNCTION double unchecked_factorial<double>(unsigned i BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(double)) +{ + return static_cast<double>(boost::math::unchecked_factorial<long double>(i)); +} + +template <> +struct max_factorial<double> +{ + BOOST_STATIC_CONSTANT(unsigned, + value = ::boost::math::max_factorial<long double>::value); +}; + +#ifndef BOOST_MATH_NO_LEXICAL_CAST + +template <class T> +struct unchecked_factorial_initializer +{ + struct init + { + init() + { + boost::math::unchecked_factorial<T>(3); + } + void force_instantiate()const {} + }; + static const init initializer; + static void force_instantiate() + { + initializer.force_instantiate(); + } +}; + +template <class T> +const typename unchecked_factorial_initializer<T>::init unchecked_factorial_initializer<T>::initializer; + + +template <class T, int N> +inline T unchecked_factorial_imp(unsigned i, const mpl::int_<N>&) +{ + BOOST_STATIC_ASSERT(!boost::is_integral<T>::value); + // factorial<unsigned int>(n) is not implemented + // because it would overflow integral type T for too small n + // to be useful. Use instead a floating-point type, + // and convert to an unsigned type if essential, for example: + // unsigned int nfac = static_cast<unsigned int>(factorial<double>(n)); + // See factorial documentation for more detail. + + unchecked_factorial_initializer<T>::force_instantiate(); + + static const boost::array<T, 101> factorials = {{ + T(boost::math::tools::convert_from_string<T>("1")), + T(boost::math::tools::convert_from_string<T>("1")), + T(boost::math::tools::convert_from_string<T>("2")), + T(boost::math::tools::convert_from_string<T>("6")), + T(boost::math::tools::convert_from_string<T>("24")), + T(boost::math::tools::convert_from_string<T>("120")), + T(boost::math::tools::convert_from_string<T>("720")), + T(boost::math::tools::convert_from_string<T>("5040")), + T(boost::math::tools::convert_from_string<T>("40320")), + T(boost::math::tools::convert_from_string<T>("362880")), + T(boost::math::tools::convert_from_string<T>("3628800")), + T(boost::math::tools::convert_from_string<T>("39916800")), + T(boost::math::tools::convert_from_string<T>("479001600")), + T(boost::math::tools::convert_from_string<T>("6227020800")), + T(boost::math::tools::convert_from_string<T>("87178291200")), + T(boost::math::tools::convert_from_string<T>("1307674368000")), + T(boost::math::tools::convert_from_string<T>("20922789888000")), + T(boost::math::tools::convert_from_string<T>("355687428096000")), + T(boost::math::tools::convert_from_string<T>("6402373705728000")), + T(boost::math::tools::convert_from_string<T>("121645100408832000")), + T(boost::math::tools::convert_from_string<T>("2432902008176640000")), + T(boost::math::tools::convert_from_string<T>("51090942171709440000")), + T(boost::math::tools::convert_from_string<T>("1124000727777607680000")), + T(boost::math::tools::convert_from_string<T>("25852016738884976640000")), + T(boost::math::tools::convert_from_string<T>("620448401733239439360000")), + T(boost::math::tools::convert_from_string<T>("15511210043330985984000000")), + T(boost::math::tools::convert_from_string<T>("403291461126605635584000000")), + T(boost::math::tools::convert_from_string<T>("10888869450418352160768000000")), + T(boost::math::tools::convert_from_string<T>("304888344611713860501504000000")), + T(boost::math::tools::convert_from_string<T>("8841761993739701954543616000000")), + T(boost::math::tools::convert_from_string<T>("265252859812191058636308480000000")), + T(boost::math::tools::convert_from_string<T>("8222838654177922817725562880000000")), + T(boost::math::tools::convert_from_string<T>("263130836933693530167218012160000000")), + T(boost::math::tools::convert_from_string<T>("8683317618811886495518194401280000000")), + T(boost::math::tools::convert_from_string<T>("295232799039604140847618609643520000000")), + T(boost::math::tools::convert_from_string<T>("10333147966386144929666651337523200000000")), + T(boost::math::tools::convert_from_string<T>("371993326789901217467999448150835200000000")), + T(boost::math::tools::convert_from_string<T>("13763753091226345046315979581580902400000000")), + T(boost::math::tools::convert_from_string<T>("523022617466601111760007224100074291200000000")), + T(boost::math::tools::convert_from_string<T>("20397882081197443358640281739902897356800000000")), + T(boost::math::tools::convert_from_string<T>("815915283247897734345611269596115894272000000000")), + T(boost::math::tools::convert_from_string<T>("33452526613163807108170062053440751665152000000000")), + T(boost::math::tools::convert_from_string<T>("1405006117752879898543142606244511569936384000000000")), + T(boost::math::tools::convert_from_string<T>("60415263063373835637355132068513997507264512000000000")), + T(boost::math::tools::convert_from_string<T>("2658271574788448768043625811014615890319638528000000000")), + T(boost::math::tools::convert_from_string<T>("119622220865480194561963161495657715064383733760000000000")), + T(boost::math::tools::convert_from_string<T>("5502622159812088949850305428800254892961651752960000000000")), + T(boost::math::tools::convert_from_string<T>("258623241511168180642964355153611979969197632389120000000000")), + T(boost::math::tools::convert_from_string<T>("12413915592536072670862289047373375038521486354677760000000000")), + T(boost::math::tools::convert_from_string<T>("608281864034267560872252163321295376887552831379210240000000000")), + T(boost::math::tools::convert_from_string<T>("30414093201713378043612608166064768844377641568960512000000000000")), + T(boost::math::tools::convert_from_string<T>("1551118753287382280224243016469303211063259720016986112000000000000")), + T(boost::math::tools::convert_from_string<T>("80658175170943878571660636856403766975289505440883277824000000000000")), + T(boost::math::tools::convert_from_string<T>("4274883284060025564298013753389399649690343788366813724672000000000000")), + T(boost::math::tools::convert_from_string<T>("230843697339241380472092742683027581083278564571807941132288000000000000")), + T(boost::math::tools::convert_from_string<T>("12696403353658275925965100847566516959580321051449436762275840000000000000")), + T(boost::math::tools::convert_from_string<T>("710998587804863451854045647463724949736497978881168458687447040000000000000")), + T(boost::math::tools::convert_from_string<T>("40526919504877216755680601905432322134980384796226602145184481280000000000000")), + T(boost::math::tools::convert_from_string<T>("2350561331282878571829474910515074683828862318181142924420699914240000000000000")), + T(boost::math::tools::convert_from_string<T>("138683118545689835737939019720389406345902876772687432540821294940160000000000000")), + T(boost::math::tools::convert_from_string<T>("8320987112741390144276341183223364380754172606361245952449277696409600000000000000")), + T(boost::math::tools::convert_from_string<T>("507580213877224798800856812176625227226004528988036003099405939480985600000000000000")), + T(boost::math::tools::convert_from_string<T>("31469973260387937525653122354950764088012280797258232192163168247821107200000000000000")), + T(boost::math::tools::convert_from_string<T>("1982608315404440064116146708361898137544773690227268628106279599612729753600000000000000")), + T(boost::math::tools::convert_from_string<T>("126886932185884164103433389335161480802865516174545192198801894375214704230400000000000000")), + T(boost::math::tools::convert_from_string<T>("8247650592082470666723170306785496252186258551345437492922123134388955774976000000000000000")), + T(boost::math::tools::convert_from_string<T>("544344939077443064003729240247842752644293064388798874532860126869671081148416000000000000000")), + T(boost::math::tools::convert_from_string<T>("36471110918188685288249859096605464427167635314049524593701628500267962436943872000000000000000")), + T(boost::math::tools::convert_from_string<T>("2480035542436830599600990418569171581047399201355367672371710738018221445712183296000000000000000")), + T(boost::math::tools::convert_from_string<T>("171122452428141311372468338881272839092270544893520369393648040923257279754140647424000000000000000")), + T(boost::math::tools::convert_from_string<T>("11978571669969891796072783721689098736458938142546425857555362864628009582789845319680000000000000000")), + T(boost::math::tools::convert_from_string<T>("850478588567862317521167644239926010288584608120796235886430763388588680378079017697280000000000000000")), + T(boost::math::tools::convert_from_string<T>("61234458376886086861524070385274672740778091784697328983823014963978384987221689274204160000000000000000")), + T(boost::math::tools::convert_from_string<T>("4470115461512684340891257138125051110076800700282905015819080092370422104067183317016903680000000000000000")), + T(boost::math::tools::convert_from_string<T>("330788544151938641225953028221253782145683251820934971170611926835411235700971565459250872320000000000000000")), + T(boost::math::tools::convert_from_string<T>("24809140811395398091946477116594033660926243886570122837795894512655842677572867409443815424000000000000000000")), + T(boost::math::tools::convert_from_string<T>("1885494701666050254987932260861146558230394535379329335672487982961844043495537923117729972224000000000000000000")), + T(boost::math::tools::convert_from_string<T>("145183092028285869634070784086308284983740379224208358846781574688061991349156420080065207861248000000000000000000")), + T(boost::math::tools::convert_from_string<T>("11324281178206297831457521158732046228731749579488251990048962825668835325234200766245086213177344000000000000000000")), + T(boost::math::tools::convert_from_string<T>("894618213078297528685144171539831652069808216779571907213868063227837990693501860533361810841010176000000000000000000")), + T(boost::math::tools::convert_from_string<T>("71569457046263802294811533723186532165584657342365752577109445058227039255480148842668944867280814080000000000000000000")), + T(boost::math::tools::convert_from_string<T>("5797126020747367985879734231578109105412357244731625958745865049716390179693892056256184534249745940480000000000000000000")), + T(boost::math::tools::convert_from_string<T>("475364333701284174842138206989404946643813294067993328617160934076743994734899148613007131808479167119360000000000000000000")), + T(boost::math::tools::convert_from_string<T>("39455239697206586511897471180120610571436503407643446275224357528369751562996629334879591940103770870906880000000000000000000")), + T(boost::math::tools::convert_from_string<T>("3314240134565353266999387579130131288000666286242049487118846032383059131291716864129885722968716753156177920000000000000000000")), + T(boost::math::tools::convert_from_string<T>("281710411438055027694947944226061159480056634330574206405101912752560026159795933451040286452340924018275123200000000000000000000")), + T(boost::math::tools::convert_from_string<T>("24227095383672732381765523203441259715284870552429381750838764496720162249742450276789464634901319465571660595200000000000000000000")), + T(boost::math::tools::convert_from_string<T>("2107757298379527717213600518699389595229783738061356212322972511214654115727593174080683423236414793504734471782400000000000000000000")), + T(boost::math::tools::convert_from_string<T>("185482642257398439114796845645546284380220968949399346684421580986889562184028199319100141244804501828416633516851200000000000000000000")), + T(boost::math::tools::convert_from_string<T>("16507955160908461081216919262453619309839666236496541854913520707833171034378509739399912570787600662729080382999756800000000000000000000")), + T(boost::math::tools::convert_from_string<T>("1485715964481761497309522733620825737885569961284688766942216863704985393094065876545992131370884059645617234469978112000000000000000000000")), + T(boost::math::tools::convert_from_string<T>("135200152767840296255166568759495142147586866476906677791741734597153670771559994765685283954750449427751168336768008192000000000000000000000")), + T(boost::math::tools::convert_from_string<T>("12438414054641307255475324325873553077577991715875414356840239582938137710983519518443046123837041347353107486982656753664000000000000000000000")), + T(boost::math::tools::convert_from_string<T>("1156772507081641574759205162306240436214753229576413535186142281213246807121467315215203289516844845303838996289387078090752000000000000000000000")), + T(boost::math::tools::convert_from_string<T>("108736615665674308027365285256786601004186803580182872307497374434045199869417927630229109214583415458560865651202385340530688000000000000000000000")), + T(boost::math::tools::convert_from_string<T>("10329978488239059262599702099394727095397746340117372869212250571234293987594703124871765375385424468563282236864226607350415360000000000000000000000")), + T(boost::math::tools::convert_from_string<T>("991677934870949689209571401541893801158183648651267795444376054838492222809091499987689476037000748982075094738965754305639874560000000000000000000000")), + T(boost::math::tools::convert_from_string<T>("96192759682482119853328425949563698712343813919172976158104477319333745612481875498805879175589072651261284189679678167647067832320000000000000000000000")), + T(boost::math::tools::convert_from_string<T>("9426890448883247745626185743057242473809693764078951663494238777294707070023223798882976159207729119823605850588608460429412647567360000000000000000000000")), + T(boost::math::tools::convert_from_string<T>("933262154439441526816992388562667004907159682643816214685929638952175999932299156089414639761565182862536979208272237582511852109168640000000000000000000000")), + T(boost::math::tools::convert_from_string<T>("93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000")), + }}; + + return factorials[i]; +} + +template <class T> +inline T unchecked_factorial_imp(unsigned i, const mpl::int_<0>&) +{ + BOOST_STATIC_ASSERT(!boost::is_integral<T>::value); + // factorial<unsigned int>(n) is not implemented + // because it would overflow integral type T for too small n + // to be useful. Use instead a floating-point type, + // and convert to an unsigned type if essential, for example: + // unsigned int nfac = static_cast<unsigned int>(factorial<double>(n)); + // See factorial documentation for more detail. +#ifdef BOOST_NO_CXX11_THREAD_LOCAL + unchecked_factorial_initializer<T>::force_instantiate(); +#endif + static const char* const factorial_strings[] = { + "1", + "1", + "2", + "6", + "24", + "120", + "720", + "5040", + "40320", + "362880", + "3628800", + "39916800", + "479001600", + "6227020800", + "87178291200", + "1307674368000", + "20922789888000", + "355687428096000", + "6402373705728000", + "121645100408832000", + "2432902008176640000", + "51090942171709440000", + "1124000727777607680000", + "25852016738884976640000", + "620448401733239439360000", + "15511210043330985984000000", + "403291461126605635584000000", + "10888869450418352160768000000", + "304888344611713860501504000000", + "8841761993739701954543616000000", + "265252859812191058636308480000000", + "8222838654177922817725562880000000", + "263130836933693530167218012160000000", + "8683317618811886495518194401280000000", + "295232799039604140847618609643520000000", + "10333147966386144929666651337523200000000", + "371993326789901217467999448150835200000000", + "13763753091226345046315979581580902400000000", + "523022617466601111760007224100074291200000000", + "20397882081197443358640281739902897356800000000", + "815915283247897734345611269596115894272000000000", + "33452526613163807108170062053440751665152000000000", + "1405006117752879898543142606244511569936384000000000", + "60415263063373835637355132068513997507264512000000000", + "2658271574788448768043625811014615890319638528000000000", + "119622220865480194561963161495657715064383733760000000000", + "5502622159812088949850305428800254892961651752960000000000", + "258623241511168180642964355153611979969197632389120000000000", + "12413915592536072670862289047373375038521486354677760000000000", + "608281864034267560872252163321295376887552831379210240000000000", + "30414093201713378043612608166064768844377641568960512000000000000", + "1551118753287382280224243016469303211063259720016986112000000000000", + "80658175170943878571660636856403766975289505440883277824000000000000", + "4274883284060025564298013753389399649690343788366813724672000000000000", + "230843697339241380472092742683027581083278564571807941132288000000000000", + "12696403353658275925965100847566516959580321051449436762275840000000000000", + "710998587804863451854045647463724949736497978881168458687447040000000000000", + "40526919504877216755680601905432322134980384796226602145184481280000000000000", + "2350561331282878571829474910515074683828862318181142924420699914240000000000000", + "138683118545689835737939019720389406345902876772687432540821294940160000000000000", + "8320987112741390144276341183223364380754172606361245952449277696409600000000000000", + "507580213877224798800856812176625227226004528988036003099405939480985600000000000000", + "31469973260387937525653122354950764088012280797258232192163168247821107200000000000000", + "1982608315404440064116146708361898137544773690227268628106279599612729753600000000000000", + "126886932185884164103433389335161480802865516174545192198801894375214704230400000000000000", + "8247650592082470666723170306785496252186258551345437492922123134388955774976000000000000000", + "544344939077443064003729240247842752644293064388798874532860126869671081148416000000000000000", + "36471110918188685288249859096605464427167635314049524593701628500267962436943872000000000000000", + "2480035542436830599600990418569171581047399201355367672371710738018221445712183296000000000000000", + "171122452428141311372468338881272839092270544893520369393648040923257279754140647424000000000000000", + "11978571669969891796072783721689098736458938142546425857555362864628009582789845319680000000000000000", + "850478588567862317521167644239926010288584608120796235886430763388588680378079017697280000000000000000", + "61234458376886086861524070385274672740778091784697328983823014963978384987221689274204160000000000000000", + "4470115461512684340891257138125051110076800700282905015819080092370422104067183317016903680000000000000000", + "330788544151938641225953028221253782145683251820934971170611926835411235700971565459250872320000000000000000", + "24809140811395398091946477116594033660926243886570122837795894512655842677572867409443815424000000000000000000", + "1885494701666050254987932260861146558230394535379329335672487982961844043495537923117729972224000000000000000000", + "145183092028285869634070784086308284983740379224208358846781574688061991349156420080065207861248000000000000000000", + "11324281178206297831457521158732046228731749579488251990048962825668835325234200766245086213177344000000000000000000", + "894618213078297528685144171539831652069808216779571907213868063227837990693501860533361810841010176000000000000000000", + "71569457046263802294811533723186532165584657342365752577109445058227039255480148842668944867280814080000000000000000000", + "5797126020747367985879734231578109105412357244731625958745865049716390179693892056256184534249745940480000000000000000000", + "475364333701284174842138206989404946643813294067993328617160934076743994734899148613007131808479167119360000000000000000000", + "39455239697206586511897471180120610571436503407643446275224357528369751562996629334879591940103770870906880000000000000000000", + "3314240134565353266999387579130131288000666286242049487118846032383059131291716864129885722968716753156177920000000000000000000", + "281710411438055027694947944226061159480056634330574206405101912752560026159795933451040286452340924018275123200000000000000000000", + "24227095383672732381765523203441259715284870552429381750838764496720162249742450276789464634901319465571660595200000000000000000000", + "2107757298379527717213600518699389595229783738061356212322972511214654115727593174080683423236414793504734471782400000000000000000000", + "185482642257398439114796845645546284380220968949399346684421580986889562184028199319100141244804501828416633516851200000000000000000000", + "16507955160908461081216919262453619309839666236496541854913520707833171034378509739399912570787600662729080382999756800000000000000000000", + "1485715964481761497309522733620825737885569961284688766942216863704985393094065876545992131370884059645617234469978112000000000000000000000", + "135200152767840296255166568759495142147586866476906677791741734597153670771559994765685283954750449427751168336768008192000000000000000000000", + "12438414054641307255475324325873553077577991715875414356840239582938137710983519518443046123837041347353107486982656753664000000000000000000000", + "1156772507081641574759205162306240436214753229576413535186142281213246807121467315215203289516844845303838996289387078090752000000000000000000000", + "108736615665674308027365285256786601004186803580182872307497374434045199869417927630229109214583415458560865651202385340530688000000000000000000000", + "10329978488239059262599702099394727095397746340117372869212250571234293987594703124871765375385424468563282236864226607350415360000000000000000000000", + "991677934870949689209571401541893801158183648651267795444376054838492222809091499987689476037000748982075094738965754305639874560000000000000000000000", + "96192759682482119853328425949563698712343813919172976158104477319333745612481875498805879175589072651261284189679678167647067832320000000000000000000000", + "9426890448883247745626185743057242473809693764078951663494238777294707070023223798882976159207729119823605850588608460429412647567360000000000000000000000", + "933262154439441526816992388562667004907159682643816214685929638952175999932299156089414639761565182862536979208272237582511852109168640000000000000000000000", + "93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000", + }; + + static BOOST_MATH_THREAD_LOCAL T factorials[sizeof(factorial_strings) / sizeof(factorial_strings[0])]; + static BOOST_MATH_THREAD_LOCAL int digits = 0; + + int current_digits = boost::math::tools::digits<T>(); + + if(digits != current_digits) + { + digits = current_digits; + for(unsigned k = 0; k < sizeof(factorials) / sizeof(factorials[0]); ++k) + factorials[k] = static_cast<T>(boost::math::tools::convert_from_string<T>(factorial_strings[k])); + } + + return factorials[i]; +} + +template <class T> +inline T unchecked_factorial(unsigned i) +{ + typedef typename boost::math::policies::precision<T, boost::math::policies::policy<> >::type tag_type; + return unchecked_factorial_imp<T>(i, tag_type()); +} + +template <class T> +struct max_factorial +{ + BOOST_STATIC_CONSTANT(unsigned, value = 100); +}; + +#else // BOOST_MATH_NO_LEXICAL_CAST + +template <class T> +inline T unchecked_factorial(unsigned i BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(T)) +{ + return 1; +} + +template <class T> +struct max_factorial +{ + BOOST_STATIC_CONSTANT(unsigned, value = 0); +}; + +#endif + +#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION +template <class T> +const unsigned max_factorial<T>::value; +#endif + +} // namespace math +} // namespace boost + +#endif // BOOST_MATH_SP_UC_FACTORIALS_HPP + |