Initial commit
This commit is contained in:
160
code_ordonnee/boost/math/special_functions/detail/airy_ai_bi_zero.hpp
Executable file
160
code_ordonnee/boost/math/special_functions/detail/airy_ai_bi_zero.hpp
Executable file
@@ -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_
|
||||
665
code_ordonnee/boost/math/special_functions/detail/bernoulli_details.hpp
Executable file
665
code_ordonnee/boost/math/special_functions/detail/bernoulli_details.hpp
Executable file
@@ -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
|
||||
@@ -0,0 +1,87 @@
|
||||
// Copyright (c) 2013 Anton Bikineev
|
||||
// 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!!!
|
||||
//
|
||||
// Linear combination for bessel derivatives are defined here
|
||||
#ifndef BOOST_MATH_SF_DETAIL_BESSEL_DERIVATIVES_LINEAR_HPP
|
||||
#define BOOST_MATH_SF_DETAIL_BESSEL_DERIVATIVES_LINEAR_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
namespace boost{ namespace math{ namespace detail{
|
||||
|
||||
template <class T, class Tag, class Policy>
|
||||
inline T bessel_j_derivative_linear(T v, T x, Tag tag, Policy pol)
|
||||
{
|
||||
return (boost::math::detail::cyl_bessel_j_imp<T>(v-1, x, tag, pol) - boost::math::detail::cyl_bessel_j_imp<T>(v+1, x, tag, pol)) / 2;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T bessel_j_derivative_linear(T v, T x, const bessel_int_tag& tag, Policy pol)
|
||||
{
|
||||
return (boost::math::detail::cyl_bessel_j_imp<T>(itrunc(v-1), x, tag, pol) - boost::math::detail::cyl_bessel_j_imp<T>(itrunc(v+1), x, tag, pol)) / 2;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T sph_bessel_j_derivative_linear(unsigned v, T x, Policy pol)
|
||||
{
|
||||
return (v / x) * boost::math::detail::sph_bessel_j_imp<T>(v, x, pol) - boost::math::detail::sph_bessel_j_imp<T>(v+1, x, pol);
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T bessel_i_derivative_linear(T v, T x, Policy pol)
|
||||
{
|
||||
T result = boost::math::detail::cyl_bessel_i_imp<T>(v - 1, x, pol);
|
||||
if(result >= tools::max_value<T>())
|
||||
return result; // result is infinite
|
||||
T result2 = boost::math::detail::cyl_bessel_i_imp<T>(v + 1, x, pol);
|
||||
if(result2 >= tools::max_value<T>() - result)
|
||||
return result2; // result is infinite
|
||||
return (result + result2) / 2;
|
||||
}
|
||||
|
||||
template <class T, class Tag, class Policy>
|
||||
inline T bessel_k_derivative_linear(T v, T x, Tag tag, Policy pol)
|
||||
{
|
||||
T result = boost::math::detail::cyl_bessel_k_imp<T>(v - 1, x, tag, pol);
|
||||
if(result >= tools::max_value<T>())
|
||||
return -result; // result is infinite
|
||||
T result2 = boost::math::detail::cyl_bessel_k_imp<T>(v + 1, x, tag, pol);
|
||||
if(result2 >= tools::max_value<T>() - result)
|
||||
return -result2; // result is infinite
|
||||
return (result + result2) / -2;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T bessel_k_derivative_linear(T v, T x, const bessel_int_tag& tag, Policy pol)
|
||||
{
|
||||
return (boost::math::detail::cyl_bessel_k_imp<T>(itrunc(v-1), x, tag, pol) + boost::math::detail::cyl_bessel_k_imp<T>(itrunc(v+1), x, tag, pol)) / -2;
|
||||
}
|
||||
|
||||
template <class T, class Tag, class Policy>
|
||||
inline T bessel_y_derivative_linear(T v, T x, Tag tag, Policy pol)
|
||||
{
|
||||
return (boost::math::detail::cyl_neumann_imp<T>(v-1, x, tag, pol) - boost::math::detail::cyl_neumann_imp<T>(v+1, x, tag, pol)) / 2;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T bessel_y_derivative_linear(T v, T x, const bessel_int_tag& tag, Policy pol)
|
||||
{
|
||||
return (boost::math::detail::cyl_neumann_imp<T>(itrunc(v-1), x, tag, pol) - boost::math::detail::cyl_neumann_imp<T>(itrunc(v+1), x, tag, pol)) / 2;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T sph_neumann_derivative_linear(unsigned v, T x, Policy pol)
|
||||
{
|
||||
return (v / x) * boost::math::detail::sph_neumann_imp<T>(v, x, pol) - boost::math::detail::sph_neumann_imp<T>(v+1, x, pol);
|
||||
}
|
||||
|
||||
}}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_SF_DETAIL_BESSEL_DERIVATIVES_LINEAR_HPP
|
||||
554
code_ordonnee/boost/math/special_functions/detail/bessel_i0.hpp
Executable file
554
code_ordonnee/boost/math/special_functions/detail/bessel_i0.hpp
Executable file
@@ -0,0 +1,554 @@
|
||||
// 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>
|
||||
|
||||
// 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
|
||||
|
||||
582
code_ordonnee/boost/math/special_functions/detail/bessel_i1.hpp
Executable file
582
code_ordonnee/boost/math/special_functions/detail/bessel_i1.hpp
Executable file
@@ -0,0 +1,582 @@
|
||||
// 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>
|
||||
|
||||
// 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
|
||||
|
||||
451
code_ordonnee/boost/math/special_functions/detail/bessel_ik.hpp
Executable file
451
code_ordonnee/boost/math/special_functions/detail/bessel_ik.hpp
Executable file
@@ -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
|
||||
|
||||
193
code_ordonnee/boost/math/special_functions/detail/bessel_j0.hpp
Executable file
193
code_ordonnee/boost/math/special_functions/detail/bessel_j0.hpp
Executable file
@@ -0,0 +1,193 @@
|
||||
// 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>
|
||||
|
||||
// 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
|
||||
|
||||
199
code_ordonnee/boost/math/special_functions/detail/bessel_j1.hpp
Executable file
199
code_ordonnee/boost/math/special_functions/detail/bessel_j1.hpp
Executable file
@@ -0,0 +1,199 @@
|
||||
// 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>
|
||||
|
||||
// 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
|
||||
|
||||
133
code_ordonnee/boost/math/special_functions/detail/bessel_jn.hpp
Executable file
133
code_ordonnee/boost/math/special_functions/detail/bessel_jn.hpp
Executable file
@@ -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
|
||||
|
||||
589
code_ordonnee/boost/math/special_functions/detail/bessel_jy.hpp
Executable file
589
code_ordonnee/boost/math/special_functions/detail/bessel_jy.hpp
Executable file
@@ -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
|
||||
|
||||
223
code_ordonnee/boost/math/special_functions/detail/bessel_jy_asym.hpp
Executable file
223
code_ordonnee/boost/math/special_functions/detail/bessel_jy_asym.hpp
Executable file
@@ -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
|
||||
|
||||
141
code_ordonnee/boost/math/special_functions/detail/bessel_jy_derivatives_asym.hpp
Executable file
141
code_ordonnee/boost/math/special_functions/detail/bessel_jy_derivatives_asym.hpp
Executable file
@@ -0,0 +1,141 @@
|
||||
// Copyright (c) 2013 Anton Bikineev
|
||||
// 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 derivatives of Bessel J(v,x) and Y(v,x)
|
||||
// functions, as x -> INF.
|
||||
#ifndef BOOST_MATH_SF_DETAIL_BESSEL_JY_DERIVATIVES_ASYM_HPP
|
||||
#define BOOST_MATH_SF_DETAIL_BESSEL_JY_DERIVATIVES_ASYM_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
namespace boost{ namespace math{ namespace detail{
|
||||
|
||||
template <class T>
|
||||
inline T asymptotic_bessel_derivative_amplitude(T v, T x)
|
||||
{
|
||||
// Calculate the amplitude for J'(v,x) and I'(v,x)
|
||||
// for large x: see A&S 9.2.30.
|
||||
BOOST_MATH_STD_USING
|
||||
T s = 1;
|
||||
const T mu = 4 * v * v;
|
||||
T txq = 2 * x;
|
||||
txq *= txq;
|
||||
|
||||
s -= (mu - 3) / (2 * txq);
|
||||
s -= ((mu - 1) * (mu - 45)) / (txq * txq * 8);
|
||||
|
||||
return sqrt(s * 2 / (boost::math::constants::pi<T>() * x));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T asymptotic_bessel_derivative_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.31.
|
||||
// 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:
|
||||
const T mu = 4 * v * v;
|
||||
const T mu2 = mu * mu;
|
||||
const T mu3 = mu2 * mu;
|
||||
T denom = 4 * x;
|
||||
T denom_mult = denom * denom;
|
||||
|
||||
T s = 0;
|
||||
s += (mu + 3) / (2 * denom);
|
||||
denom *= denom_mult;
|
||||
s += (mu2 + (46 * mu) - 63) / (6 * denom);
|
||||
denom *= denom_mult;
|
||||
s += (mu3 + (185 * mu2) - (2053 * mu) + 1899) / (5 * denom);
|
||||
return s;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T asymptotic_bessel_y_derivative_large_x_2(T v, T x)
|
||||
{
|
||||
// See A&S 9.2.20.
|
||||
BOOST_MATH_STD_USING
|
||||
// Get the phase and amplitude:
|
||||
const T ampl = asymptotic_bessel_derivative_amplitude(v, x);
|
||||
const T phase = asymptotic_bessel_derivative_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.
|
||||
//
|
||||
const T cx = cos(x);
|
||||
const T sx = sin(x);
|
||||
const T vd2shifted = (v / 2) - 0.25f;
|
||||
const T ci = cos_pi(vd2shifted);
|
||||
const T si = sin_pi(vd2shifted);
|
||||
const 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_derivative_large_x_2(T v, T x)
|
||||
{
|
||||
// See A&S 9.2.20.
|
||||
BOOST_MATH_STD_USING
|
||||
// Get the phase and amplitude:
|
||||
const T ampl = asymptotic_bessel_derivative_amplitude(v, x);
|
||||
const T phase = asymptotic_bessel_derivative_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));
|
||||
const T cx = cos(x);
|
||||
const T sx = sin(x);
|
||||
const T vd2shifted = (v / 2) - 0.25f;
|
||||
const T ci = cos_pi(vd2shifted);
|
||||
const T si = sin_pi(vd2shifted);
|
||||
const 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_derivative_large_x_limit(const T& v, const T& x)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
//
|
||||
// This function is the copy of math::asymptotic_bessel_large_x_limit
|
||||
// It means that we use the same rules for determining how x is large
|
||||
// compared to v.
|
||||
//
|
||||
// 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(boost::math::tools::forth_root_epsilon<T>());
|
||||
}
|
||||
|
||||
}}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_SF_DETAIL_BESSEL_JY_DERIVATIVES_ASYM_HPP
|
||||
@@ -0,0 +1,221 @@
|
||||
// Copyright (c) 2013 Anton Bikineev
|
||||
// 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_DERIVATIVES_SERIES_HPP
|
||||
#define BOOST_MATH_BESSEL_JY_DERIVATIVES_SERIES_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
namespace boost{ namespace math{ namespace detail{
|
||||
|
||||
template <class T, class Policy>
|
||||
struct bessel_j_derivative_small_z_series_term
|
||||
{
|
||||
typedef T result_type;
|
||||
|
||||
bessel_j_derivative_small_z_series_term(T v_, T x)
|
||||
: N(0), v(v_), term(1), mult(x / 2)
|
||||
{
|
||||
mult *= -mult;
|
||||
// iterate if v == 0; otherwise result of
|
||||
// first term is 0 and tools::sum_series stops
|
||||
if (v == 0)
|
||||
iterate();
|
||||
}
|
||||
T operator()()
|
||||
{
|
||||
T r = term * (v + 2 * N);
|
||||
iterate();
|
||||
return r;
|
||||
}
|
||||
private:
|
||||
void iterate()
|
||||
{
|
||||
++N;
|
||||
term *= mult / (N * (N + v));
|
||||
}
|
||||
unsigned N;
|
||||
T v;
|
||||
T term;
|
||||
T mult;
|
||||
};
|
||||
//
|
||||
// Series evaluation for BesselJ'(v, z) as z -> 0.
|
||||
// It's derivative of 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_derivative_small_z_series(T v, T x, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
T prefix;
|
||||
if (v < boost::math::max_factorial<T>::value)
|
||||
{
|
||||
prefix = pow(x / 2, v - 1) / 2 / boost::math::tgamma(v + 1, pol);
|
||||
}
|
||||
else
|
||||
{
|
||||
prefix = (v - 1) * log(x / 2) - constants::ln_two<T>() - boost::math::lgamma(v + 1, pol);
|
||||
prefix = exp(prefix);
|
||||
}
|
||||
if (0 == prefix)
|
||||
return prefix;
|
||||
|
||||
bessel_j_derivative_small_z_series_term<T, Policy> s(v, x);
|
||||
boost::uintmax_t max_iter = boost::math::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
|
||||
boost::math::policies::check_series_iterations<T>("boost::math::bessel_j_derivative_small_z_series<%1%>(%1%,%1%)", max_iter, pol);
|
||||
return prefix * result;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
struct bessel_y_derivative_small_z_series_term_a
|
||||
{
|
||||
typedef T result_type;
|
||||
|
||||
bessel_y_derivative_small_z_series_term_a(T v_, T x)
|
||||
: N(0), v(v_)
|
||||
{
|
||||
mult = x / 2;
|
||||
mult *= -mult;
|
||||
term = 1;
|
||||
}
|
||||
T operator()()
|
||||
{
|
||||
T r = term * (-v + 2 * N);
|
||||
++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_derivative_small_z_series_term_b
|
||||
{
|
||||
typedef T result_type;
|
||||
|
||||
bessel_y_derivative_small_z_series_term_b(T v_, T x)
|
||||
: N(0), v(v_)
|
||||
{
|
||||
mult = x / 2;
|
||||
mult *= -mult;
|
||||
term = 1;
|
||||
}
|
||||
T operator()()
|
||||
{
|
||||
T r = term * (v + 2 * N);
|
||||
++N;
|
||||
term *= mult / (N * (N + v));
|
||||
return r;
|
||||
}
|
||||
private:
|
||||
unsigned N;
|
||||
T v;
|
||||
T mult;
|
||||
T term;
|
||||
};
|
||||
//
|
||||
// Series form for BesselY' as z -> 0,
|
||||
// It's derivative of 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_derivative_small_z_series(T v, T x, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
static const char* function = "bessel_y_derivative_small_z_series<%1%>(%1%,%1%)";
|
||||
T prefix;
|
||||
T gam;
|
||||
T p = log(x / 2);
|
||||
T scale = 1;
|
||||
bool need_logs = (v >= boost::math::max_factorial<T>::value) || (boost::math::tools::log_max_value<T>() / v < fabs(p));
|
||||
if (!need_logs)
|
||||
{
|
||||
gam = boost::math::tgamma(v, pol);
|
||||
p = pow(x / 2, v + 1) * 2;
|
||||
if (boost::math::tools::max_value<T>() * p < gam)
|
||||
{
|
||||
scale /= gam;
|
||||
gam = 1;
|
||||
if (boost::math::tools::max_value<T>() * p < gam)
|
||||
{
|
||||
// This term will overflow to -INF, when combined with the series below it becomes +INF:
|
||||
return boost::math::policies::raise_overflow_error<T>(function, 0, pol);
|
||||
}
|
||||
}
|
||||
prefix = -gam / (boost::math::constants::pi<T>() * p);
|
||||
}
|
||||
else
|
||||
{
|
||||
gam = boost::math::lgamma(v, pol);
|
||||
p = (v + 1) * p + constants::ln_two<T>();
|
||||
prefix = gam - log(boost::math::constants::pi<T>()) - p;
|
||||
if (boost::math::tools::log_max_value<T>() < prefix)
|
||||
{
|
||||
prefix -= log(boost::math::tools::max_value<T>() / 4);
|
||||
scale /= (boost::math::tools::max_value<T>() / 4);
|
||||
if (boost::math::tools::log_max_value<T>() < prefix)
|
||||
{
|
||||
return boost::math::policies::raise_overflow_error<T>(function, 0, pol);
|
||||
}
|
||||
}
|
||||
prefix = -exp(prefix);
|
||||
}
|
||||
bessel_y_derivative_small_z_series_term_a<T, Policy> s(v, x);
|
||||
boost::uintmax_t max_iter = boost::math::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
|
||||
boost::math::policies::check_series_iterations<T>("boost::math::bessel_y_derivative_small_z_series<%1%>(%1%,%1%)", max_iter, pol);
|
||||
result *= prefix;
|
||||
|
||||
p = pow(x / 2, v - 1) / 2;
|
||||
if (!need_logs)
|
||||
{
|
||||
prefix = boost::math::tgamma(-v, pol) * boost::math::cos_pi(v) * p / boost::math::constants::pi<T>();
|
||||
}
|
||||
else
|
||||
{
|
||||
int sgn;
|
||||
prefix = boost::math::lgamma(-v, &sgn, pol) + (v - 1) * log(x / 2) - constants::ln_two<T>();
|
||||
prefix = exp(prefix) * sgn / boost::math::constants::pi<T>();
|
||||
}
|
||||
bessel_y_derivative_small_z_series_term_b<T, Policy> s2(v, x);
|
||||
max_iter = boost::math::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;
|
||||
}
|
||||
|
||||
// Calculating of BesselY'(v,x) with small x (x < epsilon) and integer x using derivatives
|
||||
// of formulas in http://functions.wolfram.com/Bessel-TypeFunctions/BesselY/06/01/04/01/02/
|
||||
// seems to lose precision. Instead using linear combination of regular Bessel is preferred.
|
||||
|
||||
}}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_BESSEL_JY_DERIVATVIES_SERIES_HPP
|
||||
261
code_ordonnee/boost/math/special_functions/detail/bessel_jy_series.hpp
Executable file
261
code_ordonnee/boost/math/special_functions/detail/bessel_jy_series.hpp
Executable file
@@ -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
|
||||
|
||||
617
code_ordonnee/boost/math/special_functions/detail/bessel_jy_zero.hpp
Executable file
617
code_ordonnee/boost/math/special_functions/detail/bessel_jy_zero.hpp
Executable file
@@ -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_
|
||||
509
code_ordonnee/boost/math/special_functions/detail/bessel_k0.hpp
Executable file
509
code_ordonnee/boost/math/special_functions/detail/bessel_k0.hpp
Executable file
@@ -0,0 +1,509 @@
|
||||
// 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>
|
||||
|
||||
// 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
|
||||
|
||||
551
code_ordonnee/boost/math/special_functions/detail/bessel_k1.hpp
Executable file
551
code_ordonnee/boost/math/special_functions/detail/bessel_k1.hpp
Executable file
@@ -0,0 +1,551 @@
|
||||
// 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>
|
||||
|
||||
// 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
|
||||
|
||||
86
code_ordonnee/boost/math/special_functions/detail/bessel_kn.hpp
Executable file
86
code_ordonnee/boost/math/special_functions/detail/bessel_kn.hpp
Executable file
@@ -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
|
||||
|
||||
230
code_ordonnee/boost/math/special_functions/detail/bessel_y0.hpp
Executable file
230
code_ordonnee/boost/math/special_functions/detail/bessel_y0.hpp
Executable file
@@ -0,0 +1,230 @@
|
||||
// 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>
|
||||
|
||||
// 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
|
||||
|
||||
202
code_ordonnee/boost/math/special_functions/detail/bessel_y1.hpp
Executable file
202
code_ordonnee/boost/math/special_functions/detail/bessel_y1.hpp
Executable file
@@ -0,0 +1,202 @@
|
||||
// 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>
|
||||
|
||||
// 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
|
||||
|
||||
112
code_ordonnee/boost/math/special_functions/detail/bessel_yn.hpp
Executable file
112
code_ordonnee/boost/math/special_functions/detail/bessel_yn.hpp
Executable file
@@ -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
|
||||
|
||||
549
code_ordonnee/boost/math/special_functions/detail/erf_inv.hpp
Executable file
549
code_ordonnee/boost/math/special_functions/detail/erf_inv.hpp
Executable file
@@ -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
|
||||
|
||||
581
code_ordonnee/boost/math/special_functions/detail/fp_traits.hpp
Executable file
581
code_ordonnee/boost/math/special_functions/detail/fp_traits.hpp
Executable file
@@ -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
|
||||
233
code_ordonnee/boost/math/special_functions/detail/gamma_inva.hpp
Executable file
233
code_ordonnee/boost/math/special_functions/detail/gamma_inva.hpp
Executable file
@@ -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
|
||||
|
||||
|
||||
|
||||
328
code_ordonnee/boost/math/special_functions/detail/ibeta_inv_ab.hpp
Executable file
328
code_ordonnee/boost/math/special_functions/detail/ibeta_inv_ab.hpp
Executable file
@@ -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
|
||||
|
||||
|
||||
|
||||
993
code_ordonnee/boost/math/special_functions/detail/ibeta_inverse.hpp
Executable file
993
code_ordonnee/boost/math/special_functions/detail/ibeta_inverse.hpp
Executable file
@@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
42
code_ordonnee/boost/math/special_functions/detail/iconv.hpp
Executable file
42
code_ordonnee/boost/math/special_functions/detail/iconv.hpp
Executable file
@@ -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
|
||||
|
||||
551
code_ordonnee/boost/math/special_functions/detail/igamma_inverse.hpp
Executable file
551
code_ordonnee/boost/math/special_functions/detail/igamma_inverse.hpp
Executable file
@@ -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
|
||||
|
||||
|
||||
|
||||
768
code_ordonnee/boost/math/special_functions/detail/igamma_large.hpp
Executable file
768
code_ordonnee/boost/math/special_functions/detail/igamma_large.hpp
Executable file
@@ -0,0 +1,768 @@
|
||||
// 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
|
||||
|
||||
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
|
||||
|
||||
134
code_ordonnee/boost/math/special_functions/detail/lambert_w_lookup_table.ipp
Executable file
134
code_ordonnee/boost/math/special_functions/detail/lambert_w_lookup_table.ipp
Executable file
@@ -0,0 +1,134 @@
|
||||
// Copyright Paul A. Bristow 2017.
|
||||
// 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)
|
||||
|
||||
// I:/modular-boost/libs/math/include/boost/math/special_functions/lambert_w_lookup_table.ipp
|
||||
|
||||
// A collection of 128-bit precision integral z argument Lambert W values computed using 37 decimal digits precision.
|
||||
// C++ floating-point precision is 128-bit long double.
|
||||
// Output as 53 decimal digits, suffixed L.
|
||||
|
||||
// C++ floating-point type is provided by lambert_w.hpp typedef.
|
||||
// For example: typedef lookup_t double; (or float or long double)
|
||||
|
||||
// Written by I:\modular-boost\libs\math\test\lambert_w_lookup_table_generator.cpp Thu Jan 25 16:52:07 2018
|
||||
|
||||
// Sizes of arrays of z values for Lambert W[0], W[1] ... W[64]" and W[-1], W[-2] ... W[-64].
|
||||
|
||||
namespace boost {
|
||||
namespace math {
|
||||
namespace lambert_w_detail {
|
||||
namespace lambert_w_lookup
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR std::size_t noof_sqrts = 12;
|
||||
BOOST_STATIC_CONSTEXPR std::size_t noof_halves = 12;
|
||||
BOOST_STATIC_CONSTEXPR std::size_t noof_w0es = 65;
|
||||
BOOST_STATIC_CONSTEXPR std::size_t noof_w0zs = 65;
|
||||
BOOST_STATIC_CONSTEXPR std::size_t noof_wm1es = 64;
|
||||
BOOST_STATIC_CONSTEXPR std::size_t noof_wm1zs = 64;
|
||||
|
||||
BOOST_STATIC_CONSTEXPR lookup_t halves[noof_halves] =
|
||||
{ // Common to Lambert W0 and W-1 (and exactly representable).
|
||||
0.5L, 0.25L, 0.125L, 0.0625L, 0.03125L, 0.015625L, 0.0078125L, 0.00390625L, 0.001953125L, 0.0009765625L, 0.00048828125L, 0.000244140625L
|
||||
}; // halves, 0.5, 0.25, ... 0.000244140625, common to W0 and W-1.
|
||||
|
||||
BOOST_STATIC_CONSTEXPR lookup_t sqrtw0s[noof_sqrts] =
|
||||
{ // For Lambert W0 only.
|
||||
0.6065306597126334242631173765403218567L, 0.77880078307140486866846070009071995L, 0.882496902584595403104717592968701829L, 0.9394130628134757862473572557999761753L, 0.9692332344763440819139583751755278177L, 0.9844964370054084060204319075254540376L, 0.9922179382602435121227899136829802692L, 0.996101369470117490071323985506950379L, 0.9980487811074754727142805899944244847L, 0.9990239141819756622368328253791383317L, 0.9995118379398893653889967919448497792L, 0.9997558891748972165136242351259789505L
|
||||
}; // sqrtw0s
|
||||
|
||||
BOOST_STATIC_CONSTEXPR lookup_t sqrtwm1s[noof_sqrts] =
|
||||
{ // For Lambert W-1 only.
|
||||
1.648721270700128146848650787814163572L, 1.284025416687741484073420568062436458L, 1.133148453066826316829007227811793873L, 1.064494458917859429563390594642889673L, 1.031743407499102670938747815281507144L, 1.015747708586685747458535072082351749L, 1.007843097206447977693453559760123579L, 1.003913889338347573443609603903460282L, 1.001955033591002812046518898047477216L, 1.000977039492416535242845292611606506L, 1.000488400478694473126173623807163354L, 1.000244170429747854937005233924135774L
|
||||
}; // sqrtwm1s
|
||||
|
||||
BOOST_STATIC_CONSTEXPR lookup_t w0es[noof_w0zs] =
|
||||
{ // Fukushima e powers array e[0] = 2.718, 1., e[2] = e^-1 = 0.135, e[3] = e^-2 = 0.133 ... e[64] = 4.3596100000630809736231248158884615452e-28.
|
||||
2.7182818284590452353602874713526624978e+00L,
|
||||
1.0000000000000000000000000000000000000e+00L, 3.6787944117144232159552377016146086745e-01L, 1.3533528323661269189399949497248440341e-01L, 4.9787068367863942979342415650061776632e-02L,
|
||||
1.8315638888734180293718021273241242212e-02L, 6.7379469990854670966360484231484242488e-03L, 2.4787521766663584230451674308166678915e-03L, 9.1188196555451620800313608440928262647e-04L,
|
||||
3.3546262790251183882138912578086101931e-04L, 1.2340980408667954949763669073003382607e-04L, 4.5399929762484851535591515560550610238e-05L, 1.6701700790245659312635517360580879078e-05L,
|
||||
6.1442123533282097586823081788055323112e-06L, 2.2603294069810543257852772905386894694e-06L, 8.3152871910356788406398514256526229461e-07L, 3.0590232050182578837147949770228963937e-07L,
|
||||
1.1253517471925911451377517906012719164e-07L, 4.1399377187851666596510277189552806229e-08L, 1.5229979744712628436136629233517431862e-08L, 5.6027964375372675400129828162064630798e-09L,
|
||||
2.0611536224385578279659403801558209764e-09L, 7.5825604279119067279417432412681264430e-10L, 2.7894680928689248077189130306442932077e-10L, 1.0261879631701890303927527840612497760e-10L,
|
||||
3.7751345442790977516449695475234067792e-11L, 1.3887943864964020594661763746086856910e-11L, 5.1090890280633247198744001934792157666e-12L, 1.8795288165390832947582704184221926212e-12L,
|
||||
6.9144001069402030094125846587414092712e-13L, 2.5436656473769229103033856148576816666e-13L, 9.3576229688401746049158322233787067450e-14L, 3.4424771084699764583923893328515572846e-14L,
|
||||
1.2664165549094175723120904155965096382e-14L, 4.6588861451033973641842455436101684114e-15L, 1.7139084315420129663027203425760492412e-15L, 6.3051167601469893856390211922465427614e-16L,
|
||||
2.3195228302435693883122636097380800411e-16L, 8.5330476257440657942780498229412441658e-17L, 3.1391327920480296287089646522319196491e-17L, 1.1548224173015785986262442063323868655e-17L,
|
||||
4.2483542552915889953292347828586580179e-18L, 1.5628821893349887680908829951058341550e-18L, 5.7495222642935598066643808805734234249e-19L, 2.1151310375910804866314010070226514702e-19L,
|
||||
7.7811322411337965157133167292798981918e-20L, 2.8625185805493936444701216291839372068e-20L, 1.0530617357553812378763324449428108806e-20L, 3.8739976286871871129314774972691278293e-21L,
|
||||
1.4251640827409351062853210280340602263e-21L, 5.2428856633634639371718053028323436716e-22L, 1.9287498479639177830173428165270125748e-22L, 7.0954741622847041389832693878080734877e-23L,
|
||||
2.6102790696677048047026953153318648093e-23L, 9.6026800545086760302307696700074909076e-24L, 3.5326285722008070297353928101772088374e-24L, 1.2995814250075030736007134060714855303e-24L,
|
||||
4.7808928838854690812771770423179628939e-25L, 1.7587922024243116489558751288034363178e-25L, 6.4702349256454603261540395529264893765e-26L, 2.3802664086944006058943245888024963309e-26L,
|
||||
8.7565107626965203384887328007391660366e-27L, 3.2213402859925160890012477758489437534e-27L, 1.1850648642339810062850307390972809891e-27L, 4.3596100000630809736231248158884596428e-28L,
|
||||
|
||||
}; // w0es
|
||||
|
||||
BOOST_STATIC_CONSTEXPR lookup_t w0zs[noof_w0zs] =
|
||||
{ // z values for W[0], W[1], W[2] ... W[64] (Fukushima array Fk).
|
||||
0.0000000000000000000000000000000000000e+00L,
|
||||
2.7182818284590452353602874713526624978e+00L, 1.4778112197861300454460854921150015626e+01L, 6.0256610769563003222785588963745153691e+01L, 2.1839260013257695631244104481144351361e+02L,
|
||||
7.4206579551288301710557790020276139812e+02L, 2.4205727609564107356503230832603296776e+03L, 7.6764321089992101948460416680168500271e+03L, 2.3847663896333826197948736795623109390e+04L,
|
||||
7.2927755348178456069389970204894839685e+04L, 2.2026465794806716516957900645284244366e+05L, 6.5861555886717600300859134371483559776e+05L, 1.9530574970280470496960624587818413980e+06L,
|
||||
5.7513740961159665432393360873381476632e+06L, 1.6836459978306874888489314790750032292e+07L, 4.9035260587081659589527825691375819733e+07L, 1.4217776832812596218820837985250320561e+08L,
|
||||
4.1063419681078006965118239806655900596e+08L, 1.1818794444719492004981570586630806042e+09L, 3.3911637183005579560532906419857313738e+09L, 9.7033039081958055593821366108308111737e+09L,
|
||||
2.7695130424147508641409976558651358487e+10L, 7.8868082614895014356985518811525255163e+10L, 2.2413047926372475980079655175092843139e+11L, 6.3573893111624333505933989166748517618e+11L,
|
||||
1.8001224834346468131040337866531539479e+12L, 5.0889698451498078710141863447784789126e+12L, 1.4365302496248562650461177217211790925e+13L, 4.0495197800161304862957327843914007993e+13L,
|
||||
1.1400869461717722015726999684446230289e+14L, 3.2059423744573386440971405952224204950e+14L, 9.0051433962267018216365614546207459567e+14L, 2.5268147258457822451512967243234631750e+15L,
|
||||
7.0832381329352301326018261305316090522e+15L, 1.9837699245933465967698692976753294646e+16L, 5.5510470830970075484537561902113104381e+16L, 1.5520433569614702817608320254284931407e+17L,
|
||||
4.3360826779369661842459877227403719730e+17L, 1.2105254067703227363724895246493485480e+18L, 3.3771426165357561311906703760513324357e+18L, 9.4154106734807994163159964299613921804e+18L,
|
||||
2.6233583234732252918129199544138403574e+19L, 7.3049547543861043990576614751671879498e+19L, 2.0329709713386190214340167519800405595e+20L, 5.6547040503180956413560918381429636734e+20L,
|
||||
1.5720421975868292906615658755032744790e+21L, 4.3682149334771264822761478593874428627e+21L, 1.2132170565093316762294432610117848880e+22L, 3.3680332378068632345542636794533635462e+22L,
|
||||
9.3459982052259884835729892206738573922e+22L, 2.5923527642935362320437266614667426924e+23L, 7.1876803203773878618909930893087860822e+23L, 1.9921241603726199616378561653688236827e+24L,
|
||||
5.5192924995054165325072406547517121131e+24L, 1.5286067837683347062387143159276002521e+25L, 4.2321318958281094260005100745711666956e+25L, 1.1713293177672778461879598480402173158e+26L,
|
||||
3.2408603996214813669049988277609543829e+26L, 8.9641258264226027960478448084812796397e+26L, 2.4787141382364034104243901241243054434e+27L, 6.8520443388941057019777430988685937812e+27L,
|
||||
1.8936217407781711443114787060753312270e+28L, 5.2317811346197017832254642778313331353e+28L, 1.4450833904658542238325922893692265683e+29L, 3.9904954117194348050619127737142206367e+29L
|
||||
|
||||
}; // w0zs
|
||||
|
||||
BOOST_STATIC_CONSTEXPR lookup_t wm1es[noof_wm1es] =
|
||||
{ // Fukushima e array e[0] = e^1 = 2.718, e[1] = e^2 = 7.39 ... e[64] = 4.60718e+28.
|
||||
2.7182818284590452353602874713526624978e+00L,
|
||||
7.3890560989306502272304274605750078132e+00L, 2.0085536923187667740928529654581717897e+01L, 5.4598150033144239078110261202860878403e+01L, 1.4841315910257660342111558004055227962e+02L,
|
||||
4.0342879349273512260838718054338827961e+02L, 1.0966331584284585992637202382881214324e+03L, 2.9809579870417282747435920994528886738e+03L, 8.1030839275753840077099966894327599650e+03L,
|
||||
2.2026465794806716516957900645284244366e+04L, 5.9874141715197818455326485792257781614e+04L, 1.6275479141900392080800520489848678317e+05L, 4.4241339200892050332610277594908828178e+05L,
|
||||
1.2026042841647767777492367707678594494e+06L, 3.2690173724721106393018550460917213155e+06L, 8.8861105205078726367630237407814503508e+06L, 2.4154952753575298214775435180385823880e+07L,
|
||||
6.5659969137330511138786503259060033569e+07L, 1.7848230096318726084491003378872270388e+08L, 4.8516519540979027796910683054154055868e+08L, 1.3188157344832146972099988837453027851e+09L,
|
||||
3.5849128461315915616811599459784206892e+09L, 9.7448034462489026000346326848229752776e+09L, 2.6489122129843472294139162152811882341e+10L, 7.2004899337385872524161351466126157915e+10L,
|
||||
1.9572960942883876426977639787609534279e+11L, 5.3204824060179861668374730434117744166e+11L, 1.4462570642914751736770474229969288569e+12L, 3.9313342971440420743886205808435276858e+12L,
|
||||
1.0686474581524462146990468650741401650e+13L, 2.9048849665247425231085682111679825667e+13L, 7.8962960182680695160978022635108224220e+13L, 2.1464357978591606462429776153126088037e+14L,
|
||||
5.8346174252745488140290273461039101900e+14L, 1.5860134523134307281296446257746601252e+15L, 4.3112315471151952271134222928569253908e+15L, 1.1719142372802611308772939791190194522e+16L,
|
||||
3.1855931757113756220328671701298646000e+16L, 8.6593400423993746953606932719264934250e+16L, 2.3538526683701998540789991074903480451e+17L, 6.3984349353005494922266340351557081888e+17L,
|
||||
1.7392749415205010473946813036112352261e+18L, 4.7278394682293465614744575627442803708e+18L, 1.2851600114359308275809299632143099258e+19L, 3.4934271057485095348034797233406099533e+19L,
|
||||
9.4961194206024488745133649117118323102e+19L, 2.5813128861900673962328580021527338043e+20L, 7.0167359120976317386547159988611740546e+20L, 1.9073465724950996905250998409538484474e+21L,
|
||||
5.1847055285870724640874533229334853848e+21L, 1.4093490824269387964492143312370168789e+22L, 3.8310080007165768493035695487861993899e+22L, 1.0413759433029087797183472933493796440e+23L,
|
||||
2.8307533032746939004420635480140745409e+23L, 7.6947852651420171381827455901293939921e+23L, 2.0916594960129961539070711572146737782e+24L, 5.6857199993359322226403488206332533034e+24L,
|
||||
1.5455389355901039303530766911174620068e+25L, 4.2012104037905142549565934307191617684e+25L, 1.1420073898156842836629571831447656302e+26L, 3.1042979357019199087073421411071003721e+26L,
|
||||
8.4383566687414544890733294803731179601e+26L, 2.2937831594696098790993528402686136005e+27L, 6.2351490808116168829092387089284697448e+27L
|
||||
}; // wm1es
|
||||
|
||||
BOOST_STATIC_CONSTEXPR lookup_t wm1zs[noof_wm1zs] =
|
||||
{ // Fukushima G array of z values for integral K, (Fukushima Gk) g[0] (k = -1) = 1 ... g[64] = -1.0264389699511303e-26.
|
||||
-3.6787944117144232159552377016146086745e-01L,
|
||||
-2.7067056647322538378799898994496880682e-01L, -1.4936120510359182893802724695018532990e-01L, -7.3262555554936721174872085092964968848e-02L, -3.3689734995427335483180242115742121244e-02L,
|
||||
-1.4872513059998150538271004584900007349e-02L, -6.3831737588816134560219525908649783853e-03L, -2.6837010232200947105711130062468881545e-03L, -1.1106882367801159454787302165703044346e-03L,
|
||||
-4.5399929762484851535591515560550610238e-04L, -1.8371870869270225243899069096638966986e-04L, -7.3730548239938517104187698145666387735e-05L, -2.9384282290753706235208604777002963102e-05L,
|
||||
-1.1641402067449950376895791995913672125e-05L, -4.5885348075273868255721924655343445906e-06L, -1.8005627955081458322204028649620350662e-06L, -7.0378941219347833214067471222239770590e-07L,
|
||||
-2.7413963540482731185045932620331377352e-07L, -1.0645313231320808326024667350792279852e-07L, -4.1223072448771156559318807603116419528e-08L, -1.5923376898615004128677660806663065530e-08L,
|
||||
-6.1368298043116345769816086674174450569e-09L, -2.3602323152914347699033314033408744848e-09L, -9.0603229062698346039479269140561762700e-10L, -3.4719859662410051486654409365217142276e-10L,
|
||||
-1.3283631472964644271673440503045960993e-10L, -5.0747278046555248958473301297399200773e-11L, -1.9360320299432568426355237044475945959e-11L, -7.3766303773930764398798182830872768331e-12L,
|
||||
-2.8072868906520523814747496670136120235e-12L, -1.0671679036256927021016406931839827582e-12L, -4.0525329757101362313986893299088308423e-13L, -1.5374324278841211301808010293913555758e-13L,
|
||||
-5.8272886672428440854292491647585674200e-14L, -2.2067908660514462849736574172862899665e-14L, -8.3502821888768497979241489950570881481e-15L, -3.1572276215253043438828784344882603413e-15L,
|
||||
-1.1928704609782512589094065678481294667e-15L, -4.5038074274761565346423524046963087756e-16L, -1.6993417021166355981316939131434632072e-16L, -6.4078169762734539491726202799339200356e-17L,
|
||||
-2.4147993510032951187990399698408378385e-17L, -9.0950634616416460925150243301974013218e-18L, -3.4236981860988704669138593608831552044e-18L, -1.2881333612472271400115547331327717431e-18L,
|
||||
-4.8440839844747536942311292467369300505e-19L, -1.8207788854829779430777944237164900798e-19L, -6.8407875971564885101695409345634890862e-20L, -2.5690139750480973292141845983878483991e-20L,
|
||||
-9.6437492398195889150867140826350628738e-21L, -3.6186918227651991108814673877821174787e-21L, -1.3573451162272064984454015639725697008e-21L, -5.0894204288895982960223079251039701810e-22L,
|
||||
-1.9076194289884357960571121174956927722e-22L, -7.1476978375412669048039237333931704166e-23L, -2.6773000149758626855152191436980592206e-23L, -1.0025115553818576399048488234179587012e-23L,
|
||||
-3.7527362568743669891693429406973638384e-24L, -1.4043571811296963574776515073934728352e-24L, -5.2539064576179122030932396804434996219e-25L, -1.9650175744554348142907611432678556896e-25L,
|
||||
-7.3474021582506822389671905824031421322e-26L, -2.7465543000397410133825686340097295749e-26L, -1.0264389699511282259046957018510946438e-26L
|
||||
}; // wm1zs
|
||||
} // namespace lambert_w_lookup
|
||||
} // namespace detail
|
||||
} // namespace math
|
||||
} // namespace boost
|
||||
220
code_ordonnee/boost/math/special_functions/detail/lanczos_sse2.hpp
Executable file
220
code_ordonnee/boost/math/special_functions/detail/lanczos_sse2.hpp
Executable file
@@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
522
code_ordonnee/boost/math/special_functions/detail/lgamma_small.hpp
Executable file
522
code_ordonnee/boost/math/special_functions/detail/lgamma_small.hpp
Executable file
@@ -0,0 +1,522 @@
|
||||
// (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>
|
||||
|
||||
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
|
||||
|
||||
558
code_ordonnee/boost/math/special_functions/detail/polygamma.hpp
Executable file
558
code_ordonnee/boost/math/special_functions/detail/polygamma.hpp
Executable file
@@ -0,0 +1,558 @@
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright 2013 Nikhar Agrawal
|
||||
// Copyright 2013 Christopher Kormanyos
|
||||
// Copyright 2014 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_POLYGAMMA_DETAIL_2013_07_30_HPP_
|
||||
#define _BOOST_POLYGAMMA_DETAIL_2013_07_30_HPP_
|
||||
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/math/policies/policy.hpp>
|
||||
#include <boost/math/special_functions/bernoulli.hpp>
|
||||
#include <boost/math/special_functions/trunc.hpp>
|
||||
#include <boost/math/special_functions/zeta.hpp>
|
||||
#include <boost/math/special_functions/digamma.hpp>
|
||||
#include <boost/math/special_functions/sin_pi.hpp>
|
||||
#include <boost/math/special_functions/cos_pi.hpp>
|
||||
#include <boost/math/special_functions/pow.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/int.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4702) // Unreachable code (release mode only warning)
|
||||
#endif
|
||||
|
||||
namespace boost { namespace math { namespace detail{
|
||||
|
||||
template<class T, class Policy>
|
||||
T polygamma_atinfinityplus(const int n, const T& x, const Policy& pol, const char* function) // for large values of x such as for x> 400
|
||||
{
|
||||
// See http://functions.wolfram.com/GammaBetaErf/PolyGamma2/06/02/0001/
|
||||
BOOST_MATH_STD_USING
|
||||
//
|
||||
// sum == current value of accumulated sum.
|
||||
// term == value of current term to be added to sum.
|
||||
// part_term == value of current term excluding the Bernoulli number part
|
||||
//
|
||||
if(n + x == x)
|
||||
{
|
||||
// x is crazy large, just concentrate on the first part of the expression and use logs:
|
||||
if(n == 1) return 1 / x;
|
||||
T nlx = n * log(x);
|
||||
if((nlx < tools::log_max_value<T>()) && (n < (int)max_factorial<T>::value))
|
||||
return ((n & 1) ? 1 : -1) * boost::math::factorial<T>(n - 1) * pow(x, -n);
|
||||
else
|
||||
return ((n & 1) ? 1 : -1) * exp(boost::math::lgamma(T(n), pol) - n * log(x));
|
||||
}
|
||||
T term, sum, part_term;
|
||||
T x_squared = x * x;
|
||||
//
|
||||
// Start by setting part_term to:
|
||||
//
|
||||
// (n-1)! / x^(n+1)
|
||||
//
|
||||
// which is common to both the first term of the series (with k = 1)
|
||||
// and to the leading part.
|
||||
// We can then get to the leading term by:
|
||||
//
|
||||
// part_term * (n + 2 * x) / 2
|
||||
//
|
||||
// and to the first term in the series
|
||||
// (excluding the Bernoulli number) by:
|
||||
//
|
||||
// part_term n * (n + 1) / (2x)
|
||||
//
|
||||
// If either the factorial would overflow,
|
||||
// or the power term underflows, this just gets set to 0 and then we
|
||||
// know that we have to use logs for the initial terms:
|
||||
//
|
||||
part_term = ((n > (int)boost::math::max_factorial<T>::value) && (T(n) * n > tools::log_max_value<T>()))
|
||||
? T(0) : static_cast<T>(boost::math::factorial<T>(n - 1, pol) * pow(x, -n - 1));
|
||||
if(part_term == 0)
|
||||
{
|
||||
// Either n is very large, or the power term underflows,
|
||||
// set the initial values of part_term, term and sum via logs:
|
||||
part_term = static_cast<T>(boost::math::lgamma(n, pol) - (n + 1) * log(x));
|
||||
sum = exp(part_term + log(n + 2 * x) - boost::math::constants::ln_two<T>());
|
||||
part_term += log(T(n) * (n + 1)) - boost::math::constants::ln_two<T>() - log(x);
|
||||
part_term = exp(part_term);
|
||||
}
|
||||
else
|
||||
{
|
||||
sum = part_term * (n + 2 * x) / 2;
|
||||
part_term *= (T(n) * (n + 1)) / 2;
|
||||
part_term /= x;
|
||||
}
|
||||
//
|
||||
// If the leading term is 0, so is the result:
|
||||
//
|
||||
if(sum == 0)
|
||||
return sum;
|
||||
|
||||
for(unsigned k = 1;;)
|
||||
{
|
||||
term = part_term * boost::math::bernoulli_b2n<T>(k, pol);
|
||||
sum += term;
|
||||
//
|
||||
// Normal termination condition:
|
||||
//
|
||||
if(fabs(term / sum) < tools::epsilon<T>())
|
||||
break;
|
||||
//
|
||||
// Increment our counter, and move part_term on to the next value:
|
||||
//
|
||||
++k;
|
||||
part_term *= T(n + 2 * k - 2) * (n - 1 + 2 * k);
|
||||
part_term /= (2 * k - 1) * 2 * k;
|
||||
part_term /= x_squared;
|
||||
//
|
||||
// Emergency get out termination condition:
|
||||
//
|
||||
if(k > policies::get_max_series_iterations<Policy>())
|
||||
{
|
||||
return policies::raise_evaluation_error(function, "Series did not converge, closest value was %1%", sum, pol);
|
||||
}
|
||||
}
|
||||
|
||||
if((n - 1) & 1)
|
||||
sum = -sum;
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
template<class T, class Policy>
|
||||
T polygamma_attransitionplus(const int n, const T& x, const Policy& pol, const char* function)
|
||||
{
|
||||
// See: http://functions.wolfram.com/GammaBetaErf/PolyGamma2/16/01/01/0017/
|
||||
|
||||
// Use N = (0.4 * digits) + (4 * n) for target value for x:
|
||||
BOOST_MATH_STD_USING
|
||||
const int d4d = static_cast<int>(0.4F * policies::digits_base10<T, Policy>());
|
||||
const int N = d4d + (4 * n);
|
||||
const int m = n;
|
||||
const int iter = N - itrunc(x);
|
||||
|
||||
if(iter > (int)policies::get_max_series_iterations<Policy>())
|
||||
return policies::raise_evaluation_error<T>(function, ("Exceeded maximum series evaluations evaluating at n = " + boost::lexical_cast<std::string>(n) + " and x = %1%").c_str(), x, pol);
|
||||
|
||||
const int minus_m_minus_one = -m - 1;
|
||||
|
||||
T z(x);
|
||||
T sum0(0);
|
||||
T z_plus_k_pow_minus_m_minus_one(0);
|
||||
|
||||
// Forward recursion to larger x, need to check for overflow first though:
|
||||
if(log(z + iter) * minus_m_minus_one > -tools::log_max_value<T>())
|
||||
{
|
||||
for(int k = 1; k <= iter; ++k)
|
||||
{
|
||||
z_plus_k_pow_minus_m_minus_one = pow(z, minus_m_minus_one);
|
||||
sum0 += z_plus_k_pow_minus_m_minus_one;
|
||||
z += 1;
|
||||
}
|
||||
sum0 *= boost::math::factorial<T>(n);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int k = 1; k <= iter; ++k)
|
||||
{
|
||||
T log_term = log(z) * minus_m_minus_one + boost::math::lgamma(T(n + 1), pol);
|
||||
sum0 += exp(log_term);
|
||||
z += 1;
|
||||
}
|
||||
}
|
||||
if((n - 1) & 1)
|
||||
sum0 = -sum0;
|
||||
|
||||
return sum0 + polygamma_atinfinityplus(n, z, pol, function);
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
T polygamma_nearzero(int n, T x, const Policy& pol, const char* function)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
//
|
||||
// If we take this expansion for polygamma: http://functions.wolfram.com/06.15.06.0003.02
|
||||
// and substitute in this expression for polygamma(n, 1): http://functions.wolfram.com/06.15.03.0009.01
|
||||
// we get an alternating series for polygamma when x is small in terms of zeta functions of
|
||||
// integer arguments (which are easy to evaluate, at least when the integer is even).
|
||||
//
|
||||
// In order to avoid spurious overflow, save the n! term for later, and rescale at the end:
|
||||
//
|
||||
T scale = boost::math::factorial<T>(n, pol);
|
||||
//
|
||||
// "factorial_part" contains everything except the zeta function
|
||||
// evaluations in each term:
|
||||
//
|
||||
T factorial_part = 1;
|
||||
//
|
||||
// "prefix" is what we'll be adding the accumulated sum to, it will
|
||||
// be n! / z^(n+1), but since we're scaling by n! it's just
|
||||
// 1 / z^(n+1) for now:
|
||||
//
|
||||
T prefix = pow(x, n + 1);
|
||||
if(prefix == 0)
|
||||
return boost::math::policies::raise_overflow_error<T>(function, 0, pol);
|
||||
prefix = 1 / prefix;
|
||||
//
|
||||
// First term in the series is necessarily < zeta(2) < 2, so
|
||||
// ignore the sum if it will have no effect on the result anyway:
|
||||
//
|
||||
if(prefix > 2 / policies::get_epsilon<T, Policy>())
|
||||
return ((n & 1) ? 1 : -1) *
|
||||
(tools::max_value<T>() / prefix < scale ? policies::raise_overflow_error<T>(function, 0, pol) : prefix * scale);
|
||||
//
|
||||
// As this is an alternating series we could accelerate it using
|
||||
// "Convergence Acceleration of Alternating Series",
|
||||
// Henri Cohen, Fernando Rodriguez Villegas, and Don Zagier, Experimental Mathematics, 1999.
|
||||
// In practice however, it appears not to make any difference to the number of terms
|
||||
// required except in some edge cases which are filtered out anyway before we get here.
|
||||
//
|
||||
T sum = prefix;
|
||||
for(unsigned k = 0;;)
|
||||
{
|
||||
// Get the k'th term:
|
||||
T term = factorial_part * boost::math::zeta(T(k + n + 1), pol);
|
||||
sum += term;
|
||||
// Termination condition:
|
||||
if(fabs(term) < fabs(sum * boost::math::policies::get_epsilon<T, Policy>()))
|
||||
break;
|
||||
//
|
||||
// Move on k and factorial_part:
|
||||
//
|
||||
++k;
|
||||
factorial_part *= (-x * (n + k)) / k;
|
||||
//
|
||||
// Last chance exit:
|
||||
//
|
||||
if(k > policies::get_max_series_iterations<Policy>())
|
||||
return policies::raise_evaluation_error<T>(function, "Series did not converge, best value is %1%", sum, pol);
|
||||
}
|
||||
//
|
||||
// We need to multiply by the scale, at each stage checking for oveflow:
|
||||
//
|
||||
if(boost::math::tools::max_value<T>() / scale < sum)
|
||||
return boost::math::policies::raise_overflow_error<T>(function, 0, pol);
|
||||
sum *= scale;
|
||||
return n & 1 ? sum : T(-sum);
|
||||
}
|
||||
|
||||
//
|
||||
// Helper function which figures out which slot our coefficient is in
|
||||
// given an angle multiplier for the cosine term of power:
|
||||
//
|
||||
template <class Table>
|
||||
typename Table::value_type::reference dereference_table(Table& table, unsigned row, unsigned power)
|
||||
{
|
||||
return table[row][power / 2];
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <class T, class Policy>
|
||||
T poly_cot_pi(int n, T x, T xc, const Policy& pol, const char* function)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
// Return n'th derivative of cot(pi*x) at x, these are simply
|
||||
// tabulated for up to n = 9, beyond that it is possible to
|
||||
// calculate coefficients as follows:
|
||||
//
|
||||
// The general form of each derivative is:
|
||||
//
|
||||
// pi^n * SUM{k=0, n} C[k,n] * cos^k(pi * x) * csc^(n+1)(pi * x)
|
||||
//
|
||||
// With constant C[0,1] = -1 and all other C[k,n] = 0;
|
||||
// Then for each k < n+1:
|
||||
// C[k-1, n+1] -= k * C[k, n];
|
||||
// C[k+1, n+1] += (k-n-1) * C[k, n];
|
||||
//
|
||||
// Note that there are many different ways of representing this derivative thanks to
|
||||
// the many trigomonetric identies available. In particular, the sum of powers of
|
||||
// cosines could be replaced by a sum of cosine multiple angles, and indeed if you
|
||||
// plug the derivative into Mathematica this is the form it will give. The two
|
||||
// forms are related via the Chebeshev polynomials of the first kind and
|
||||
// T_n(cos(x)) = cos(n x). The polynomial form has the great advantage that
|
||||
// all the cosine terms are zero at half integer arguments - right where this
|
||||
// function has it's minumum - thus avoiding cancellation error in this region.
|
||||
//
|
||||
// And finally, since every other term in the polynomials is zero, we can save
|
||||
// space by only storing the non-zero terms. This greatly complexifies
|
||||
// subscripting the tables in the calculation, but halves the storage space
|
||||
// (and complexity for that matter).
|
||||
//
|
||||
T s = fabs(x) < fabs(xc) ? boost::math::sin_pi(x, pol) : boost::math::sin_pi(xc, pol);
|
||||
T c = boost::math::cos_pi(x, pol);
|
||||
switch(n)
|
||||
{
|
||||
case 1:
|
||||
return -constants::pi<T, Policy>() / (s * s);
|
||||
case 2:
|
||||
{
|
||||
return 2 * constants::pi<T, Policy>() * constants::pi<T, Policy>() * c / boost::math::pow<3>(s, pol);
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
int P[] = { -2, -4 };
|
||||
return boost::math::pow<3>(constants::pi<T, Policy>(), pol) * tools::evaluate_even_polynomial(P, c) / boost::math::pow<4>(s, pol);
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
int P[] = { 16, 8 };
|
||||
return boost::math::pow<4>(constants::pi<T, Policy>(), pol) * c * tools::evaluate_even_polynomial(P, c) / boost::math::pow<5>(s, pol);
|
||||
}
|
||||
case 5:
|
||||
{
|
||||
int P[] = { -16, -88, -16 };
|
||||
return boost::math::pow<5>(constants::pi<T, Policy>(), pol) * tools::evaluate_even_polynomial(P, c) / boost::math::pow<6>(s, pol);
|
||||
}
|
||||
case 6:
|
||||
{
|
||||
int P[] = { 272, 416, 32 };
|
||||
return boost::math::pow<6>(constants::pi<T, Policy>(), pol) * c * tools::evaluate_even_polynomial(P, c) / boost::math::pow<7>(s, pol);
|
||||
}
|
||||
case 7:
|
||||
{
|
||||
int P[] = { -272, -2880, -1824, -64 };
|
||||
return boost::math::pow<7>(constants::pi<T, Policy>(), pol) * tools::evaluate_even_polynomial(P, c) / boost::math::pow<8>(s, pol);
|
||||
}
|
||||
case 8:
|
||||
{
|
||||
int P[] = { 7936, 24576, 7680, 128 };
|
||||
return boost::math::pow<8>(constants::pi<T, Policy>(), pol) * c * tools::evaluate_even_polynomial(P, c) / boost::math::pow<9>(s, pol);
|
||||
}
|
||||
case 9:
|
||||
{
|
||||
int P[] = { -7936, -137216, -185856, -31616, -256 };
|
||||
return boost::math::pow<9>(constants::pi<T, Policy>(), pol) * tools::evaluate_even_polynomial(P, c) / boost::math::pow<10>(s, pol);
|
||||
}
|
||||
case 10:
|
||||
{
|
||||
int P[] = { 353792, 1841152, 1304832, 128512, 512 };
|
||||
return boost::math::pow<10>(constants::pi<T, Policy>(), pol) * c * tools::evaluate_even_polynomial(P, c) / boost::math::pow<11>(s, pol);
|
||||
}
|
||||
case 11:
|
||||
{
|
||||
int P[] = { -353792, -9061376, -21253376, -8728576, -518656, -1024};
|
||||
return boost::math::pow<11>(constants::pi<T, Policy>(), pol) * tools::evaluate_even_polynomial(P, c) / boost::math::pow<12>(s, pol);
|
||||
}
|
||||
case 12:
|
||||
{
|
||||
int P[] = { 22368256, 175627264, 222398464, 56520704, 2084864, 2048 };
|
||||
return boost::math::pow<12>(constants::pi<T, Policy>(), pol) * c * tools::evaluate_even_polynomial(P, c) / boost::math::pow<13>(s, pol);
|
||||
}
|
||||
#ifndef BOOST_NO_LONG_LONG
|
||||
case 13:
|
||||
{
|
||||
long long P[] = { -22368256LL, -795300864LL, -2868264960LL, -2174832640LL, -357888000LL, -8361984LL, -4096 };
|
||||
return boost::math::pow<13>(constants::pi<T, Policy>(), pol) * tools::evaluate_even_polynomial(P, c) / boost::math::pow<14>(s, pol);
|
||||
}
|
||||
case 14:
|
||||
{
|
||||
long long P[] = { 1903757312LL, 21016670208LL, 41731645440LL, 20261765120LL, 2230947840LL, 33497088LL, 8192 };
|
||||
return boost::math::pow<14>(constants::pi<T, Policy>(), pol) * c * tools::evaluate_even_polynomial(P, c) / boost::math::pow<15>(s, pol);
|
||||
}
|
||||
case 15:
|
||||
{
|
||||
long long P[] = { -1903757312LL, -89702612992LL, -460858269696LL, -559148810240LL, -182172651520LL, -13754155008LL, -134094848LL, -16384 };
|
||||
return boost::math::pow<15>(constants::pi<T, Policy>(), pol) * tools::evaluate_even_polynomial(P, c) / boost::math::pow<16>(s, pol);
|
||||
}
|
||||
case 16:
|
||||
{
|
||||
long long P[] = { 209865342976LL, 3099269660672LL, 8885192097792LL, 7048869314560LL, 1594922762240LL, 84134068224LL, 536608768LL, 32768 };
|
||||
return boost::math::pow<16>(constants::pi<T, Policy>(), pol) * c * tools::evaluate_even_polynomial(P, c) / boost::math::pow<17>(s, pol);
|
||||
}
|
||||
case 17:
|
||||
{
|
||||
long long P[] = { -209865342976LL, -12655654469632LL, -87815735738368LL, -155964390375424LL, -84842998005760LL, -13684856848384LL, -511780323328LL, -2146926592LL, -65536 };
|
||||
return boost::math::pow<17>(constants::pi<T, Policy>(), pol) * tools::evaluate_even_polynomial(P, c) / boost::math::pow<18>(s, pol);
|
||||
}
|
||||
case 18:
|
||||
{
|
||||
long long P[] = { 29088885112832LL, 553753414467584LL, 2165206642589696LL, 2550316668551168LL, 985278548541440LL, 115620218667008LL, 3100738912256LL, 8588754944LL, 131072 };
|
||||
return boost::math::pow<18>(constants::pi<T, Policy>(), pol) * c * tools::evaluate_even_polynomial(P, c) / boost::math::pow<19>(s, pol);
|
||||
}
|
||||
case 19:
|
||||
{
|
||||
long long P[] = { -29088885112832LL, -2184860175433728LL, -19686087844429824LL, -48165109676113920LL, -39471306959486976LL, -11124607890751488LL, -965271355195392LL, -18733264797696LL, -34357248000LL, -262144 };
|
||||
return boost::math::pow<19>(constants::pi<T, Policy>(), pol) * tools::evaluate_even_polynomial(P, c) / boost::math::pow<20>(s, pol);
|
||||
}
|
||||
case 20:
|
||||
{
|
||||
long long P[] = { 4951498053124096LL, 118071834535526400LL, 603968063567560704LL, 990081991141490688LL, 584901762421358592LL, 122829335169859584LL, 7984436548730880LL, 112949304754176LL, 137433710592LL, 524288 };
|
||||
return boost::math::pow<20>(constants::pi<T, Policy>(), pol) * c * tools::evaluate_even_polynomial(P, c) / boost::math::pow<21>(s, pol);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
// We'll have to compute the coefficients up to n,
|
||||
// complexity is O(n^2) which we don't worry about for now
|
||||
// as the values are computed once and then cached.
|
||||
// However, if the final evaluation would have too many
|
||||
// terms just bail out right away:
|
||||
//
|
||||
if((unsigned)n / 2u > policies::get_max_series_iterations<Policy>())
|
||||
return policies::raise_evaluation_error<T>(function, "The value of n is so large that we're unable to compute the result in reasonable time, best guess is %1%", 0, pol);
|
||||
#ifdef BOOST_HAS_THREADS
|
||||
static boost::detail::lightweight_mutex m;
|
||||
boost::detail::lightweight_mutex::scoped_lock l(m);
|
||||
#endif
|
||||
static int digits = tools::digits<T>();
|
||||
static std::vector<std::vector<T> > table(1, std::vector<T>(1, T(-1)));
|
||||
|
||||
int current_digits = tools::digits<T>();
|
||||
|
||||
if(digits != current_digits)
|
||||
{
|
||||
// Oh my... our precision has changed!
|
||||
table = std::vector<std::vector<T> >(1, std::vector<T>(1, T(-1)));
|
||||
digits = current_digits;
|
||||
}
|
||||
|
||||
int index = n - 1;
|
||||
|
||||
if(index >= (int)table.size())
|
||||
{
|
||||
for(int i = (int)table.size() - 1; i < index; ++i)
|
||||
{
|
||||
int offset = i & 1; // 1 if the first cos power is 0, otherwise 0.
|
||||
int sin_order = i + 2; // order of the sin term
|
||||
int max_cos_order = sin_order - 1; // largest order of the polynomial of cos terms
|
||||
int max_columns = (max_cos_order - offset) / 2; // How many entries there are in the current row.
|
||||
int next_offset = offset ? 0 : 1;
|
||||
int next_max_columns = (max_cos_order + 1 - next_offset) / 2; // How many entries there will be in the next row
|
||||
table.push_back(std::vector<T>(next_max_columns + 1, T(0)));
|
||||
|
||||
for(int column = 0; column <= max_columns; ++column)
|
||||
{
|
||||
int cos_order = 2 * column + offset; // order of the cosine term in entry "column"
|
||||
BOOST_ASSERT(column < (int)table[i].size());
|
||||
BOOST_ASSERT((cos_order + 1) / 2 < (int)table[i + 1].size());
|
||||
table[i + 1][(cos_order + 1) / 2] += ((cos_order - sin_order) * table[i][column]) / (sin_order - 1);
|
||||
if(cos_order)
|
||||
table[i + 1][(cos_order - 1) / 2] += (-cos_order * table[i][column]) / (sin_order - 1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
T sum = boost::math::tools::evaluate_even_polynomial(&table[index][0], c, table[index].size());
|
||||
if(index & 1)
|
||||
sum *= c; // First coeffient is order 1, and really an odd polynomial.
|
||||
if(sum == 0)
|
||||
return sum;
|
||||
//
|
||||
// The remaining terms are computed using logs since the powers and factorials
|
||||
// get real large real quick:
|
||||
//
|
||||
T power_terms = n * log(boost::math::constants::pi<T>());
|
||||
if(s == 0)
|
||||
return sum * boost::math::policies::raise_overflow_error<T>(function, 0, pol);
|
||||
power_terms -= log(fabs(s)) * (n + 1);
|
||||
power_terms += boost::math::lgamma(T(n));
|
||||
power_terms += log(fabs(sum));
|
||||
|
||||
if(power_terms > boost::math::tools::log_max_value<T>())
|
||||
return sum * boost::math::policies::raise_overflow_error<T>(function, 0, pol);
|
||||
|
||||
return exp(power_terms) * ((s < 0) && ((n + 1) & 1) ? -1 : 1) * boost::math::sign(sum);
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
struct polygamma_initializer
|
||||
{
|
||||
struct init
|
||||
{
|
||||
init()
|
||||
{
|
||||
// Forces initialization of our table of coefficients and mutex:
|
||||
boost::math::polygamma(30, T(-2.5f), Policy());
|
||||
}
|
||||
void force_instantiate()const{}
|
||||
};
|
||||
static const init initializer;
|
||||
static void force_instantiate()
|
||||
{
|
||||
initializer.force_instantiate();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class Policy>
|
||||
const typename polygamma_initializer<T, Policy>::init polygamma_initializer<T, Policy>::initializer;
|
||||
|
||||
template<class T, class Policy>
|
||||
inline T polygamma_imp(const int n, T x, const Policy &pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
static const char* function = "boost::math::polygamma<%1%>(int, %1%)";
|
||||
polygamma_initializer<T, Policy>::initializer.force_instantiate();
|
||||
if(n < 0)
|
||||
return policies::raise_domain_error<T>(function, "Order must be >= 0, but got %1%", static_cast<T>(n), pol);
|
||||
if(x < 0)
|
||||
{
|
||||
if(floor(x) == x)
|
||||
{
|
||||
//
|
||||
// Result is infinity if x is odd, and a pole error if x is even.
|
||||
//
|
||||
if(lltrunc(x) & 1)
|
||||
return policies::raise_overflow_error<T>(function, 0, pol);
|
||||
else
|
||||
return policies::raise_pole_error<T>(function, "Evaluation at negative integer %1%", x, pol);
|
||||
}
|
||||
T z = 1 - x;
|
||||
T result = polygamma_imp(n, z, pol) + constants::pi<T, Policy>() * poly_cot_pi(n, z, x, pol, function);
|
||||
return n & 1 ? T(-result) : result;
|
||||
}
|
||||
//
|
||||
// Limit for use of small-x-series is chosen
|
||||
// so that the series doesn't go too divergent
|
||||
// in the first few terms. Ordinarily this
|
||||
// would mean setting the limit to ~ 1 / n,
|
||||
// but we can tolerate a small amount of divergence:
|
||||
//
|
||||
T small_x_limit = (std::min)(T(T(5) / n), T(0.25f));
|
||||
if(x < small_x_limit)
|
||||
{
|
||||
return polygamma_nearzero(n, x, pol, function);
|
||||
}
|
||||
else if(x > 0.4F * policies::digits_base10<T, Policy>() + 4.0f * n)
|
||||
{
|
||||
return polygamma_atinfinityplus(n, x, pol, function);
|
||||
}
|
||||
else if(x == 1)
|
||||
{
|
||||
return (n & 1 ? 1 : -1) * boost::math::factorial<T>(n, pol) * boost::math::zeta(T(n + 1), pol);
|
||||
}
|
||||
else if(x == 0.5f)
|
||||
{
|
||||
T result = (n & 1 ? 1 : -1) * boost::math::factorial<T>(n, pol) * boost::math::zeta(T(n + 1), pol);
|
||||
if(fabs(result) >= ldexp(tools::max_value<T>(), -n - 1))
|
||||
return boost::math::sign(result) * policies::raise_overflow_error<T>(function, 0, pol);
|
||||
result *= ldexp(T(1), n + 1) - 1;
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return polygamma_attransitionplus(n, x, pol, function);
|
||||
}
|
||||
}
|
||||
|
||||
} } } // namespace boost::math::detail
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif // _BOOST_POLYGAMMA_DETAIL_2013_07_30_HPP_
|
||||
|
||||
93
code_ordonnee/boost/math/special_functions/detail/round_fwd.hpp
Executable file
93
code_ordonnee/boost/math/special_functions/detail/round_fwd.hpp
Executable file
@@ -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
|
||||
|
||||
549
code_ordonnee/boost/math/special_functions/detail/t_distribution_inv.hpp
Executable file
549
code_ordonnee/boost/math/special_functions/detail/t_distribution_inv.hpp
Executable file
@@ -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
|
||||
|
||||
|
||||
|
||||
727
code_ordonnee/boost/math/special_functions/detail/unchecked_bernoulli.hpp
Executable file
727
code_ordonnee/boost/math/special_functions/detail/unchecked_bernoulli.hpp
Executable file
File diff suppressed because one or more lines are too long
805
code_ordonnee/boost/math/special_functions/detail/unchecked_factorial.hpp
Executable file
805
code_ordonnee/boost/math/special_functions/detail/unchecked_factorial.hpp
Executable file
@@ -0,0 +1,805 @@
|
||||
// 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
|
||||
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user