Added boost header
This commit is contained in:
101
test/external/boost/math/special_functions/detail/bessel_i0.hpp
vendored
Normal file
101
test/external/boost/math/special_functions/detail/bessel_i0.hpp
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
// 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_I0_HPP
|
||||
#define BOOST_MATH_BESSEL_I0_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/tools/rational.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
// Modified Bessel function of the first kind of order zero
|
||||
// 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_i0(T x)
|
||||
{
|
||||
static const T P1[] = {
|
||||
static_cast<T>(-2.2335582639474375249e+15L),
|
||||
static_cast<T>(-5.5050369673018427753e+14L),
|
||||
static_cast<T>(-3.2940087627407749166e+13L),
|
||||
static_cast<T>(-8.4925101247114157499e+11L),
|
||||
static_cast<T>(-1.1912746104985237192e+10L),
|
||||
static_cast<T>(-1.0313066708737980747e+08L),
|
||||
static_cast<T>(-5.9545626019847898221e+05L),
|
||||
static_cast<T>(-2.4125195876041896775e+03L),
|
||||
static_cast<T>(-7.0935347449210549190e+00L),
|
||||
static_cast<T>(-1.5453977791786851041e-02L),
|
||||
static_cast<T>(-2.5172644670688975051e-05L),
|
||||
static_cast<T>(-3.0517226450451067446e-08L),
|
||||
static_cast<T>(-2.6843448573468483278e-11L),
|
||||
static_cast<T>(-1.5982226675653184646e-14L),
|
||||
static_cast<T>(-5.2487866627945699800e-18L),
|
||||
};
|
||||
static const T Q1[] = {
|
||||
static_cast<T>(-2.2335582639474375245e+15L),
|
||||
static_cast<T>(7.8858692566751002988e+12L),
|
||||
static_cast<T>(-1.2207067397808979846e+10L),
|
||||
static_cast<T>(1.0377081058062166144e+07L),
|
||||
static_cast<T>(-4.8527560179962773045e+03L),
|
||||
static_cast<T>(1.0L),
|
||||
};
|
||||
static const T P2[] = {
|
||||
static_cast<T>(-2.2210262233306573296e-04L),
|
||||
static_cast<T>(1.3067392038106924055e-02L),
|
||||
static_cast<T>(-4.4700805721174453923e-01L),
|
||||
static_cast<T>(5.5674518371240761397e+00L),
|
||||
static_cast<T>(-2.3517945679239481621e+01L),
|
||||
static_cast<T>(3.1611322818701131207e+01L),
|
||||
static_cast<T>(-9.6090021968656180000e+00L),
|
||||
};
|
||||
static const T Q2[] = {
|
||||
static_cast<T>(-5.5194330231005480228e-04L),
|
||||
static_cast<T>(3.2547697594819615062e-02L),
|
||||
static_cast<T>(-1.1151759188741312645e+00L),
|
||||
static_cast<T>(1.3982595353892851542e+01L),
|
||||
static_cast<T>(-6.0228002066743340583e+01L),
|
||||
static_cast<T>(8.5539563258012929600e+01L),
|
||||
static_cast<T>(-3.1446690275135491500e+01L),
|
||||
static_cast<T>(1.0L),
|
||||
};
|
||||
T value, factor, r;
|
||||
|
||||
BOOST_MATH_STD_USING
|
||||
using namespace boost::math::tools;
|
||||
|
||||
if (x < 0)
|
||||
{
|
||||
x = -x; // even function
|
||||
}
|
||||
if (x == 0)
|
||||
{
|
||||
return static_cast<T>(1);
|
||||
}
|
||||
if (x <= 15) // x in (0, 15]
|
||||
{
|
||||
T y = x * x;
|
||||
value = evaluate_polynomial(P1, y) / evaluate_polynomial(Q1, y);
|
||||
}
|
||||
else // x in (15, \infty)
|
||||
{
|
||||
T y = 1 / x - T(1) / 15;
|
||||
r = evaluate_polynomial(P2, y) / evaluate_polynomial(Q2, y);
|
||||
factor = exp(x) / sqrt(x);
|
||||
value = factor * r;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
}}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_BESSEL_I0_HPP
|
||||
|
||||
104
test/external/boost/math/special_functions/detail/bessel_i1.hpp
vendored
Normal file
104
test/external/boost/math/special_functions/detail/bessel_i1.hpp
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
// 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_I1_HPP
|
||||
#define BOOST_MATH_BESSEL_I1_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/tools/rational.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(T x)
|
||||
{
|
||||
static const T P1[] = {
|
||||
static_cast<T>(-1.4577180278143463643e+15L),
|
||||
static_cast<T>(-1.7732037840791591320e+14L),
|
||||
static_cast<T>(-6.9876779648010090070e+12L),
|
||||
static_cast<T>(-1.3357437682275493024e+11L),
|
||||
static_cast<T>(-1.4828267606612366099e+09L),
|
||||
static_cast<T>(-1.0588550724769347106e+07L),
|
||||
static_cast<T>(-5.1894091982308017540e+04L),
|
||||
static_cast<T>(-1.8225946631657315931e+02L),
|
||||
static_cast<T>(-4.7207090827310162436e-01L),
|
||||
static_cast<T>(-9.1746443287817501309e-04L),
|
||||
static_cast<T>(-1.3466829827635152875e-06L),
|
||||
static_cast<T>(-1.4831904935994647675e-09L),
|
||||
static_cast<T>(-1.1928788903603238754e-12L),
|
||||
static_cast<T>(-6.5245515583151902910e-16L),
|
||||
static_cast<T>(-1.9705291802535139930e-19L),
|
||||
};
|
||||
static const T Q1[] = {
|
||||
static_cast<T>(-2.9154360556286927285e+15L),
|
||||
static_cast<T>(9.7887501377547640438e+12L),
|
||||
static_cast<T>(-1.4386907088588283434e+10L),
|
||||
static_cast<T>(1.1594225856856884006e+07L),
|
||||
static_cast<T>(-5.1326864679904189920e+03L),
|
||||
static_cast<T>(1.0L),
|
||||
};
|
||||
static const T P2[] = {
|
||||
static_cast<T>(1.4582087408985668208e-05L),
|
||||
static_cast<T>(-8.9359825138577646443e-04L),
|
||||
static_cast<T>(2.9204895411257790122e-02L),
|
||||
static_cast<T>(-3.4198728018058047439e-01L),
|
||||
static_cast<T>(1.3960118277609544334e+00L),
|
||||
static_cast<T>(-1.9746376087200685843e+00L),
|
||||
static_cast<T>(8.5591872901933459000e-01L),
|
||||
static_cast<T>(-6.0437159056137599999e-02L),
|
||||
};
|
||||
static const T Q2[] = {
|
||||
static_cast<T>(3.7510433111922824643e-05L),
|
||||
static_cast<T>(-2.2835624489492512649e-03L),
|
||||
static_cast<T>(7.4212010813186530069e-02L),
|
||||
static_cast<T>(-8.5017476463217924408e-01L),
|
||||
static_cast<T>(3.2593714889036996297e+00L),
|
||||
static_cast<T>(-3.8806586721556593450e+00L),
|
||||
static_cast<T>(1.0L),
|
||||
};
|
||||
T value, factor, r, w;
|
||||
|
||||
BOOST_MATH_STD_USING
|
||||
using namespace boost::math::tools;
|
||||
|
||||
w = abs(x);
|
||||
if (x == 0)
|
||||
{
|
||||
return static_cast<T>(0);
|
||||
}
|
||||
if (w <= 15) // w in (0, 15]
|
||||
{
|
||||
T y = x * x;
|
||||
r = evaluate_polynomial(P1, y) / evaluate_polynomial(Q1, y);
|
||||
factor = w;
|
||||
value = factor * r;
|
||||
}
|
||||
else // w in (15, \infty)
|
||||
{
|
||||
T y = 1 / w - T(1) / 15;
|
||||
r = evaluate_polynomial(P2, y) / evaluate_polynomial(Q2, y);
|
||||
factor = exp(w) / sqrt(w);
|
||||
value = factor * r;
|
||||
}
|
||||
|
||||
if (x < 0)
|
||||
{
|
||||
value *= -value; // odd function
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
}}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_BESSEL_I1_HPP
|
||||
|
||||
413
test/external/boost/math/special_functions/detail/bessel_ik.hpp
vendored
Normal file
413
test/external/boost/math/special_functions/detail/bessel_ik.hpp
vendored
Normal file
@@ -0,0 +1,413 @@
|
||||
// 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;
|
||||
|
||||
// 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;
|
||||
|
||||
// S converges slower than f
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(Q * delta);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(abs(S) * tolerance);
|
||||
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);
|
||||
|
||||
*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
|
||||
}
|
||||
prev = Ku;
|
||||
current = Ku1;
|
||||
T scale = 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;
|
||||
current = 1;
|
||||
}
|
||||
next = fact * current + prev;
|
||||
prev = current;
|
||||
current = next;
|
||||
}
|
||||
Kv = prev;
|
||||
Kv1 = current;
|
||||
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((x / v < 0.25) && (v > 0))
|
||||
{
|
||||
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) * sign(scale) * 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) * sign(scale) * 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
|
||||
|
||||
152
test/external/boost/math/special_functions/detail/bessel_j0.hpp
vendored
Normal file
152
test/external/boost/math/special_functions/detail/bessel_j0.hpp
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
// 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/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)
|
||||
{
|
||||
static const T P1[] = {
|
||||
static_cast<T>(-4.1298668500990866786e+11L),
|
||||
static_cast<T>(2.7282507878605942706e+10L),
|
||||
static_cast<T>(-6.2140700423540120665e+08L),
|
||||
static_cast<T>(6.6302997904833794242e+06L),
|
||||
static_cast<T>(-3.6629814655107086448e+04L),
|
||||
static_cast<T>(1.0344222815443188943e+02L),
|
||||
static_cast<T>(-1.2117036164593528341e-01L)
|
||||
};
|
||||
static const T Q1[] = {
|
||||
static_cast<T>(2.3883787996332290397e+12L),
|
||||
static_cast<T>(2.6328198300859648632e+10L),
|
||||
static_cast<T>(1.3985097372263433271e+08L),
|
||||
static_cast<T>(4.5612696224219938200e+05L),
|
||||
static_cast<T>(9.3614022392337710626e+02L),
|
||||
static_cast<T>(1.0L),
|
||||
static_cast<T>(0.0L)
|
||||
};
|
||||
static const T P2[] = {
|
||||
static_cast<T>(-1.8319397969392084011e+03L),
|
||||
static_cast<T>(-1.2254078161378989535e+04L),
|
||||
static_cast<T>(-7.2879702464464618998e+03L),
|
||||
static_cast<T>(1.0341910641583726701e+04L),
|
||||
static_cast<T>(1.1725046279757103576e+04L),
|
||||
static_cast<T>(4.4176707025325087628e+03L),
|
||||
static_cast<T>(7.4321196680624245801e+02L),
|
||||
static_cast<T>(4.8591703355916499363e+01L)
|
||||
};
|
||||
static const T Q2[] = {
|
||||
static_cast<T>(-3.5783478026152301072e+05L),
|
||||
static_cast<T>(2.4599102262586308984e+05L),
|
||||
static_cast<T>(-8.4055062591169562211e+04L),
|
||||
static_cast<T>(1.8680990008359188352e+04L),
|
||||
static_cast<T>(-2.9458766545509337327e+03L),
|
||||
static_cast<T>(3.3307310774649071172e+02L),
|
||||
static_cast<T>(-2.5258076240801555057e+01L),
|
||||
static_cast<T>(1.0L)
|
||||
};
|
||||
static const T PC[] = {
|
||||
static_cast<T>(2.2779090197304684302e+04L),
|
||||
static_cast<T>(4.1345386639580765797e+04L),
|
||||
static_cast<T>(2.1170523380864944322e+04L),
|
||||
static_cast<T>(3.4806486443249270347e+03L),
|
||||
static_cast<T>(1.5376201909008354296e+02L),
|
||||
static_cast<T>(8.8961548424210455236e-01L)
|
||||
};
|
||||
static const T QC[] = {
|
||||
static_cast<T>(2.2779090197304684318e+04L),
|
||||
static_cast<T>(4.1370412495510416640e+04L),
|
||||
static_cast<T>(2.1215350561880115730e+04L),
|
||||
static_cast<T>(3.5028735138235608207e+03L),
|
||||
static_cast<T>(1.5711159858080893649e+02L),
|
||||
static_cast<T>(1.0L)
|
||||
};
|
||||
static const T PS[] = {
|
||||
static_cast<T>(-8.9226600200800094098e+01L),
|
||||
static_cast<T>(-1.8591953644342993800e+02L),
|
||||
static_cast<T>(-1.1183429920482737611e+02L),
|
||||
static_cast<T>(-2.2300261666214198472e+01L),
|
||||
static_cast<T>(-1.2441026745835638459e+00L),
|
||||
static_cast<T>(-8.8033303048680751817e-03L)
|
||||
};
|
||||
static const T QS[] = {
|
||||
static_cast<T>(5.7105024128512061905e+03L),
|
||||
static_cast<T>(1.1951131543434613647e+04L),
|
||||
static_cast<T>(7.2642780169211018836e+03L),
|
||||
static_cast<T>(1.4887231232283756582e+03L),
|
||||
static_cast<T>(9.0593769594993125859e+01L),
|
||||
static_cast<T>(1.0L)
|
||||
};
|
||||
static const T x1 = static_cast<T>(2.4048255576957727686e+00L),
|
||||
x2 = static_cast<T>(5.5200781102863106496e+00L),
|
||||
x11 = static_cast<T>(6.160e+02L),
|
||||
x12 = static_cast<T>(-1.42444230422723137837e-03L),
|
||||
x21 = static_cast<T>(1.4130e+03L),
|
||||
x22 = static_cast<T>(5.46860286310649596604e-04L);
|
||||
|
||||
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;
|
||||
T z = x - 0.25f * pi<T>();
|
||||
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 = sqrt(2 / (x * pi<T>()));
|
||||
value = factor * (rc * cos(z) - y * rs * sin(z));
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
}}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_BESSEL_J0_HPP
|
||||
|
||||
157
test/external/boost/math/special_functions/detail/bessel_j1.hpp
vendored
Normal file
157
test/external/boost/math/special_functions/detail/bessel_j1.hpp
vendored
Normal file
@@ -0,0 +1,157 @@
|
||||
// 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/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)
|
||||
{
|
||||
static const T P1[] = {
|
||||
static_cast<T>(-1.4258509801366645672e+11L),
|
||||
static_cast<T>(6.6781041261492395835e+09L),
|
||||
static_cast<T>(-1.1548696764841276794e+08L),
|
||||
static_cast<T>(9.8062904098958257677e+05L),
|
||||
static_cast<T>(-4.4615792982775076130e+03L),
|
||||
static_cast<T>(1.0650724020080236441e+01L),
|
||||
static_cast<T>(-1.0767857011487300348e-02L)
|
||||
};
|
||||
static const T Q1[] = {
|
||||
static_cast<T>(4.1868604460820175290e+12L),
|
||||
static_cast<T>(4.2091902282580133541e+10L),
|
||||
static_cast<T>(2.0228375140097033958e+08L),
|
||||
static_cast<T>(5.9117614494174794095e+05L),
|
||||
static_cast<T>(1.0742272239517380498e+03L),
|
||||
static_cast<T>(1.0L),
|
||||
static_cast<T>(0.0L)
|
||||
};
|
||||
static const T P2[] = {
|
||||
static_cast<T>(-1.7527881995806511112e+16L),
|
||||
static_cast<T>(1.6608531731299018674e+15L),
|
||||
static_cast<T>(-3.6658018905416665164e+13L),
|
||||
static_cast<T>(3.5580665670910619166e+11L),
|
||||
static_cast<T>(-1.8113931269860667829e+09L),
|
||||
static_cast<T>(5.0793266148011179143e+06L),
|
||||
static_cast<T>(-7.5023342220781607561e+03L),
|
||||
static_cast<T>(4.6179191852758252278e+00L)
|
||||
};
|
||||
static const T Q2[] = {
|
||||
static_cast<T>(1.7253905888447681194e+18L),
|
||||
static_cast<T>(1.7128800897135812012e+16L),
|
||||
static_cast<T>(8.4899346165481429307e+13L),
|
||||
static_cast<T>(2.7622777286244082666e+11L),
|
||||
static_cast<T>(6.4872502899596389593e+08L),
|
||||
static_cast<T>(1.1267125065029138050e+06L),
|
||||
static_cast<T>(1.3886978985861357615e+03L),
|
||||
static_cast<T>(1.0L)
|
||||
};
|
||||
static const T PC[] = {
|
||||
static_cast<T>(-4.4357578167941278571e+06L),
|
||||
static_cast<T>(-9.9422465050776411957e+06L),
|
||||
static_cast<T>(-6.6033732483649391093e+06L),
|
||||
static_cast<T>(-1.5235293511811373833e+06L),
|
||||
static_cast<T>(-1.0982405543459346727e+05L),
|
||||
static_cast<T>(-1.6116166443246101165e+03L),
|
||||
static_cast<T>(0.0L)
|
||||
};
|
||||
static const T QC[] = {
|
||||
static_cast<T>(-4.4357578167941278568e+06L),
|
||||
static_cast<T>(-9.9341243899345856590e+06L),
|
||||
static_cast<T>(-6.5853394797230870728e+06L),
|
||||
static_cast<T>(-1.5118095066341608816e+06L),
|
||||
static_cast<T>(-1.0726385991103820119e+05L),
|
||||
static_cast<T>(-1.4550094401904961825e+03L),
|
||||
static_cast<T>(1.0L)
|
||||
};
|
||||
static const T PS[] = {
|
||||
static_cast<T>(3.3220913409857223519e+04L),
|
||||
static_cast<T>(8.5145160675335701966e+04L),
|
||||
static_cast<T>(6.6178836581270835179e+04L),
|
||||
static_cast<T>(1.8494262873223866797e+04L),
|
||||
static_cast<T>(1.7063754290207680021e+03L),
|
||||
static_cast<T>(3.5265133846636032186e+01L),
|
||||
static_cast<T>(0.0L)
|
||||
};
|
||||
static const T QS[] = {
|
||||
static_cast<T>(7.0871281941028743574e+05L),
|
||||
static_cast<T>(1.8194580422439972989e+06L),
|
||||
static_cast<T>(1.4194606696037208929e+06L),
|
||||
static_cast<T>(4.0029443582266975117e+05L),
|
||||
static_cast<T>(3.7890229745772202641e+04L),
|
||||
static_cast<T>(8.6383677696049909675e+02L),
|
||||
static_cast<T>(1.0L)
|
||||
};
|
||||
static const T x1 = static_cast<T>(3.8317059702075123156e+00L),
|
||||
x2 = static_cast<T>(7.0155866698156187535e+00L),
|
||||
x11 = static_cast<T>(9.810e+02L),
|
||||
x12 = static_cast<T>(-3.2527979248768438556e-04L),
|
||||
x21 = static_cast<T>(1.7960e+03L),
|
||||
x22 = static_cast<T>(-3.8330184381246462950e-05L);
|
||||
|
||||
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;
|
||||
T z = w - 0.75f * pi<T>();
|
||||
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 = sqrt(2 / (w * pi<T>()));
|
||||
value = factor * (rc * cos(z) - y * rs * sin(z));
|
||||
}
|
||||
|
||||
if (x < 0)
|
||||
{
|
||||
value *= -1; // odd function
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
}}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_BESSEL_J1_HPP
|
||||
|
||||
124
test/external/boost/math/special_functions/detail/bessel_jn.hpp
vendored
Normal file
124
test/external/boost/math/special_functions/detail/bessel_jn.hpp
vendored
Normal file
@@ -0,0 +1,124 @@
|
||||
// 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 = (n & 0x1) ? -1 : 1; // J_{-n}(z) = (-1)^n J_n(z)
|
||||
n = -n;
|
||||
}
|
||||
else
|
||||
{
|
||||
factor = 1;
|
||||
}
|
||||
//
|
||||
// Special cases:
|
||||
//
|
||||
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);
|
||||
}
|
||||
|
||||
typedef typename bessel_asymptotic_tag<T, Policy>::type tag_type;
|
||||
if(fabs(x) > asymptotic_bessel_j_limit<T>(n, tag_type()))
|
||||
return factor * asymptotic_bessel_j_large_x_2<T>(n, x);
|
||||
|
||||
BOOST_ASSERT(n > 1);
|
||||
T scale = 1;
|
||||
if (n < abs(x)) // forward recurrence
|
||||
{
|
||||
prev = bessel_j0(x);
|
||||
current = bessel_j1(x);
|
||||
for (int k = 1; k < n; k++)
|
||||
{
|
||||
T fact = 2 * k / x;
|
||||
if((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)
|
||||
{
|
||||
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;
|
||||
for (int k = n; k > 0; k--)
|
||||
{
|
||||
T fact = 2 * k / x;
|
||||
if((tools::max_value<T>() - fabs(prev)) / 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
|
||||
|
||||
553
test/external/boost/math/special_functions/detail/bessel_jy.hpp
vendored
Normal file
553
test/external/boost/math/special_functions/detail/bessel_jy.hpp
vendored
Normal file
@@ -0,0 +1,553 @@
|
||||
// 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;
|
||||
//std::cout << "C = " << Cr << " " << Ci << std::endl;
|
||||
//std::cout << "D = " << Dr << " " << Di << std::endl;
|
||||
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;
|
||||
//std::cout << fr << " " << fi << std::endl;
|
||||
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;
|
||||
//std::cout << "C = " << Cr << " " << Ci << std::endl;
|
||||
//std::cout << "D = " << Dr << " " << Di << std::endl;
|
||||
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;
|
||||
//std::cout << fr << " " << fi << std::endl;
|
||||
}
|
||||
policies::check_series_iterations<T>("boost::math::bessel_jy<%1%>(%1%,%1%) in CF2_jy", k, pol);
|
||||
*p = fr;
|
||||
*q = fi;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
need_j = 1, 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
|
||||
kind = need_j|need_y; // need both for reflection formula
|
||||
}
|
||||
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 (x == 0)
|
||||
{
|
||||
*J = *Y = policies::raise_overflow_error<T>(
|
||||
function, 0, pol);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// x is positive until reflection
|
||||
W = T(2) / (x * pi<T>()); // Wronskian
|
||||
T Yv_scale = 1;
|
||||
if((x > 8) && (x < 1000) && 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....
|
||||
//
|
||||
T chi = x - fmod(T(v / 2 + 0.25f), T(2)) * boost::math::constants::pi<T>();
|
||||
T sc = sin(chi);
|
||||
T cc = cos(chi);
|
||||
chi = sqrt(2 / (boost::math::constants::pi<T>() * x));
|
||||
Yv = chi * (p * sc + q * cc);
|
||||
Jv = chi * (p * cc - q * sc);
|
||||
}
|
||||
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 (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;
|
||||
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):
|
||||
// define tag type that will dispatch to right limits:
|
||||
typedef typename bessel_asymptotic_tag<T, Policy>::type tag_type;
|
||||
|
||||
T lim, ratio;
|
||||
switch(kind)
|
||||
{
|
||||
case need_j:
|
||||
lim = asymptotic_bessel_j_limit<T>(v, tag_type());
|
||||
break;
|
||||
case need_y:
|
||||
lim = asymptotic_bessel_y_limit<T>(tag_type());
|
||||
break;
|
||||
default:
|
||||
lim = (std::max)(
|
||||
asymptotic_bessel_j_limit<T>(v, tag_type()),
|
||||
asymptotic_bessel_y_limit<T>(tag_type()));
|
||||
break;
|
||||
}
|
||||
if(x > lim)
|
||||
{
|
||||
if(kind&need_y)
|
||||
{
|
||||
Yu = asymptotic_bessel_y_large_x_2(u, x);
|
||||
Yu1 = asymptotic_bessel_y_large_x_2(T(u + 1), x);
|
||||
}
|
||||
else
|
||||
Yu = 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
|
||||
{
|
||||
CF1_jy(v, x, &fv, &s, pol);
|
||||
// tiny initial value to prevent overflow
|
||||
T init = sqrt(tools::min_value<T>());
|
||||
prev = fv * s * init;
|
||||
current = s * init;
|
||||
if(v < max_factorial<T>::value)
|
||||
{
|
||||
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:
|
||||
//
|
||||
bool over = false;
|
||||
for (k = n; k > 0; k--) // backward recurrence for J
|
||||
{
|
||||
T t = 2 * (u + k) / x;
|
||||
if(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;
|
||||
Ju = sign(current) * sqrt(W / (q + gamma * (p - t)));
|
||||
|
||||
Jv = Ju * ratio; // normalization
|
||||
|
||||
Yu = gamma * Ju;
|
||||
Yu1 = Yu * (u/x - p - q/gamma);
|
||||
}
|
||||
if(kind&need_y)
|
||||
{
|
||||
// compute Y:
|
||||
prev = Yu;
|
||||
current = Yu1;
|
||||
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(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(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 * Jv + (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
|
||||
|
||||
302
test/external/boost/math/special_functions/detail/bessel_jy_asym.hpp
vendored
Normal file
302
test/external/boost/math/special_functions/detail/bessel_jy_asym.hpp
vendored
Normal file
@@ -0,0 +1,302 @@
|
||||
// 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_j_large_x_P(T v, T x)
|
||||
{
|
||||
// A&S 9.2.9
|
||||
T s = 1;
|
||||
T mu = 4 * v * v;
|
||||
T ez2 = 8 * x;
|
||||
ez2 *= ez2;
|
||||
s -= (mu-1) * (mu-9) / (2 * ez2);
|
||||
s += (mu-1) * (mu-9) * (mu-25) * (mu - 49) / (24 * ez2 * ez2);
|
||||
return s;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T asymptotic_bessel_j_large_x_Q(T v, T x)
|
||||
{
|
||||
// A&S 9.2.10
|
||||
T s = 0;
|
||||
T mu = 4 * v * v;
|
||||
T ez = 8*x;
|
||||
s += (mu-1) / ez;
|
||||
s -= (mu-1) * (mu-9) * (mu-25) / (6 * ez*ez*ez);
|
||||
return s;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T asymptotic_bessel_j_large_x(T v, T x)
|
||||
{
|
||||
//
|
||||
// See http://functions.wolfram.com/BesselAiryStruveFunctions/BesselJ/06/02/02/0001/
|
||||
//
|
||||
// Also A&S 9.2.5
|
||||
//
|
||||
BOOST_MATH_STD_USING // ADL of std names
|
||||
T chi = fabs(x) - constants::pi<T>() * (2 * v + 1) / 4;
|
||||
return sqrt(2 / (constants::pi<T>() * x))
|
||||
* (asymptotic_bessel_j_large_x_P(v, x) * cos(chi)
|
||||
- asymptotic_bessel_j_large_x_Q(v, x) * sin(chi));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T asymptotic_bessel_y_large_x(T v, T x)
|
||||
{
|
||||
//
|
||||
// See http://functions.wolfram.com/BesselAiryStruveFunctions/BesselJ/06/02/02/0001/
|
||||
//
|
||||
// Also A&S 9.2.5
|
||||
//
|
||||
BOOST_MATH_STD_USING // ADL of std names
|
||||
T chi = fabs(x) - constants::pi<T>() * (2 * v + 1) / 4;
|
||||
return sqrt(2 / (constants::pi<T>() * x))
|
||||
* (asymptotic_bessel_j_large_x_P(v, x) * sin(chi)
|
||||
- asymptotic_bessel_j_large_x_Q(v, x) * cos(chi));
|
||||
}
|
||||
|
||||
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.
|
||||
//
|
||||
T mu = 4 * v * v;
|
||||
T denom = 4 * x;
|
||||
T denom_mult = denom * denom;
|
||||
|
||||
T s = -constants::pi<T>() * (v / 2 + 0.25f);
|
||||
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);
|
||||
//
|
||||
// Calculate the sine of the phase, using:
|
||||
// sin(x+p) = sin(x)cos(p) + cos(x)sin(p)
|
||||
//
|
||||
T sin_phase = sin(phase) * cos(x) + cos(phase) * 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);
|
||||
//
|
||||
// Calculate the sine of the phase, using:
|
||||
// cos(x+p) = cos(x)cos(p) - sin(x)sin(p)
|
||||
//
|
||||
T sin_phase = cos(phase) * cos(x) - sin(phase) * sin(x);
|
||||
return sin_phase * ampl;
|
||||
}
|
||||
|
||||
//
|
||||
// Various limits for the J and Y asymptotics
|
||||
// (the asympotic expansions are safe to use if
|
||||
// x is less than the limit given).
|
||||
// We assume that if we don't use these expansions then the
|
||||
// error will likely be >100eps, so the limits given are chosen
|
||||
// to lead to < 100eps truncation error.
|
||||
//
|
||||
template <class T>
|
||||
inline T asymptotic_bessel_y_limit(const mpl::int_<0>&)
|
||||
{
|
||||
// default case:
|
||||
BOOST_MATH_STD_USING
|
||||
return 2.25 / pow(100 * tools::epsilon<T>() / T(0.001f), T(0.2f));
|
||||
}
|
||||
template <class T>
|
||||
inline T asymptotic_bessel_y_limit(const mpl::int_<53>&)
|
||||
{
|
||||
// double case:
|
||||
return 304 /*780*/;
|
||||
}
|
||||
template <class T>
|
||||
inline T asymptotic_bessel_y_limit(const mpl::int_<64>&)
|
||||
{
|
||||
// 80-bit extended-double case:
|
||||
return 1552 /*3500*/;
|
||||
}
|
||||
template <class T>
|
||||
inline T asymptotic_bessel_y_limit(const mpl::int_<113>&)
|
||||
{
|
||||
// 128-bit long double case:
|
||||
return 1245243 /*3128000*/;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
struct bessel_asymptotic_tag
|
||||
{
|
||||
typedef typename policies::precision<T, Policy>::type precision_type;
|
||||
typedef typename mpl::if_<
|
||||
mpl::or_<
|
||||
mpl::equal_to<precision_type, mpl::int_<0> >,
|
||||
mpl::greater<precision_type, mpl::int_<113> > >,
|
||||
mpl::int_<0>,
|
||||
typename mpl::if_<
|
||||
mpl::greater<precision_type, mpl::int_<64> >,
|
||||
mpl::int_<113>,
|
||||
typename mpl::if_<
|
||||
mpl::greater<precision_type, mpl::int_<53> >,
|
||||
mpl::int_<64>,
|
||||
mpl::int_<53>
|
||||
>::type
|
||||
>::type
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
inline T asymptotic_bessel_j_limit(const T& v, const mpl::int_<0>&)
|
||||
{
|
||||
// default case:
|
||||
BOOST_MATH_STD_USING
|
||||
T v2 = (std::max)(T(3), T(v * v));
|
||||
return v2 / pow(100 * tools::epsilon<T>() / T(2e-5f), T(0.17f));
|
||||
}
|
||||
template <class T>
|
||||
inline T asymptotic_bessel_j_limit(const T& v, const mpl::int_<53>&)
|
||||
{
|
||||
// double case:
|
||||
T v2 = (std::max)(T(3), v * v);
|
||||
return v2 * 33 /*73*/;
|
||||
}
|
||||
template <class T>
|
||||
inline T asymptotic_bessel_j_limit(const T& v, const mpl::int_<64>&)
|
||||
{
|
||||
// 80-bit extended-double case:
|
||||
T v2 = (std::max)(T(3), v * v);
|
||||
return v2 * 121 /*266*/;
|
||||
}
|
||||
template <class T>
|
||||
inline T asymptotic_bessel_j_limit(const T& v, const mpl::int_<113>&)
|
||||
{
|
||||
// 128-bit long double case:
|
||||
T v2 = (std::max)(T(3), v * v);
|
||||
return v2 * 39154 /*85700*/;
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
261
test/external/boost/math/special_functions/detail/bessel_jy_series.hpp
vendored
Normal file
261
test/external/boost/math/special_functions/detail/bessel_jy_series.hpp
vendored
Normal 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 s;
|
||||
prefix = boost::math::lgamma(-v, &s, pol) + p;
|
||||
prefix = exp(prefix) * s / 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>())) * (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
|
||||
|
||||
121
test/external/boost/math/special_functions/detail/bessel_k0.hpp
vendored
Normal file
121
test/external/boost/math/special_functions/detail/bessel_k0.hpp
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
// 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_K0_HPP
|
||||
#define BOOST_MATH_BESSEL_K0_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/tools/rational.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
|
||||
|
||||
namespace boost { namespace math { namespace detail{
|
||||
|
||||
template <typename T, typename Policy>
|
||||
T bessel_k0(T x, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_INSTRUMENT_CODE(x);
|
||||
|
||||
static const T P1[] = {
|
||||
static_cast<T>(2.4708152720399552679e+03L),
|
||||
static_cast<T>(5.9169059852270512312e+03L),
|
||||
static_cast<T>(4.6850901201934832188e+02L),
|
||||
static_cast<T>(1.1999463724910714109e+01L),
|
||||
static_cast<T>(1.3166052564989571850e-01L),
|
||||
static_cast<T>(5.8599221412826100000e-04L)
|
||||
};
|
||||
static const T Q1[] = {
|
||||
static_cast<T>(2.1312714303849120380e+04L),
|
||||
static_cast<T>(-2.4994418972832303646e+02L),
|
||||
static_cast<T>(1.0L)
|
||||
};
|
||||
static const T P2[] = {
|
||||
static_cast<T>(-1.6128136304458193998e+06L),
|
||||
static_cast<T>(-3.7333769444840079748e+05L),
|
||||
static_cast<T>(-1.7984434409411765813e+04L),
|
||||
static_cast<T>(-2.9501657892958843865e+02L),
|
||||
static_cast<T>(-1.6414452837299064100e+00L)
|
||||
};
|
||||
static const T Q2[] = {
|
||||
static_cast<T>(-1.6128136304458193998e+06L),
|
||||
static_cast<T>(2.9865713163054025489e+04L),
|
||||
static_cast<T>(-2.5064972445877992730e+02L),
|
||||
static_cast<T>(1.0L)
|
||||
};
|
||||
static const T P3[] = {
|
||||
static_cast<T>(1.1600249425076035558e+02L),
|
||||
static_cast<T>(2.3444738764199315021e+03L),
|
||||
static_cast<T>(1.8321525870183537725e+04L),
|
||||
static_cast<T>(7.1557062783764037541e+04L),
|
||||
static_cast<T>(1.5097646353289914539e+05L),
|
||||
static_cast<T>(1.7398867902565686251e+05L),
|
||||
static_cast<T>(1.0577068948034021957e+05L),
|
||||
static_cast<T>(3.1075408980684392399e+04L),
|
||||
static_cast<T>(3.6832589957340267940e+03L),
|
||||
static_cast<T>(1.1394980557384778174e+02L)
|
||||
};
|
||||
static const T Q3[] = {
|
||||
static_cast<T>(9.2556599177304839811e+01L),
|
||||
static_cast<T>(1.8821890840982713696e+03L),
|
||||
static_cast<T>(1.4847228371802360957e+04L),
|
||||
static_cast<T>(5.8824616785857027752e+04L),
|
||||
static_cast<T>(1.2689839587977598727e+05L),
|
||||
static_cast<T>(1.5144644673520157801e+05L),
|
||||
static_cast<T>(9.7418829762268075784e+04L),
|
||||
static_cast<T>(3.1474655750295278825e+04L),
|
||||
static_cast<T>(4.4329628889746408858e+03L),
|
||||
static_cast<T>(2.0013443064949242491e+02L),
|
||||
static_cast<T>(1.0L)
|
||||
};
|
||||
T value, factor, r, r1, r2;
|
||||
|
||||
BOOST_MATH_STD_USING
|
||||
using namespace boost::math::tools;
|
||||
|
||||
static const char* function = "boost::math::bessel_k0<%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 (x <= 1) // x in (0, 1]
|
||||
{
|
||||
T y = x * x;
|
||||
r1 = evaluate_polynomial(P1, y) / evaluate_polynomial(Q1, y);
|
||||
r2 = evaluate_polynomial(P2, y) / evaluate_polynomial(Q2, y);
|
||||
factor = log(x);
|
||||
value = r1 - factor * r2;
|
||||
}
|
||||
else // x in (1, \infty)
|
||||
{
|
||||
T y = 1 / x;
|
||||
r = evaluate_polynomial(P3, y) / evaluate_polynomial(Q3, y);
|
||||
factor = exp(-x) / sqrt(x);
|
||||
value = factor * r;
|
||||
BOOST_MATH_INSTRUMENT_CODE("y = " << y);
|
||||
BOOST_MATH_INSTRUMENT_CODE("r = " << r);
|
||||
BOOST_MATH_INSTRUMENT_CODE("factor = " << factor);
|
||||
BOOST_MATH_INSTRUMENT_CODE("value = " << value);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
}}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_BESSEL_K0_HPP
|
||||
|
||||
117
test/external/boost/math/special_functions/detail/bessel_k1.hpp
vendored
Normal file
117
test/external/boost/math/special_functions/detail/bessel_k1.hpp
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
// 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_K1_HPP
|
||||
#define BOOST_MATH_BESSEL_K1_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/tools/rational.hpp>
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
// Modified Bessel function of the second kind of order one
|
||||
// minimax rational approximations on intervals, see
|
||||
// Russon and Blair, Chalk River Report AECL-3461, 1969
|
||||
|
||||
namespace boost { namespace math { namespace detail{
|
||||
|
||||
template <typename T, typename Policy>
|
||||
T bessel_k1(T x, const Policy& pol)
|
||||
{
|
||||
static const T P1[] = {
|
||||
static_cast<T>(-2.2149374878243304548e+06L),
|
||||
static_cast<T>(7.1938920065420586101e+05L),
|
||||
static_cast<T>(1.7733324035147015630e+05L),
|
||||
static_cast<T>(7.1885382604084798576e+03L),
|
||||
static_cast<T>(9.9991373567429309922e+01L),
|
||||
static_cast<T>(4.8127070456878442310e-01L)
|
||||
};
|
||||
static const T Q1[] = {
|
||||
static_cast<T>(-2.2149374878243304548e+06L),
|
||||
static_cast<T>(3.7264298672067697862e+04L),
|
||||
static_cast<T>(-2.8143915754538725829e+02L),
|
||||
static_cast<T>(1.0L)
|
||||
};
|
||||
static const T P2[] = {
|
||||
static_cast<T>(0.0L),
|
||||
static_cast<T>(-1.3531161492785421328e+06L),
|
||||
static_cast<T>(-1.4758069205414222471e+05L),
|
||||
static_cast<T>(-4.5051623763436087023e+03L),
|
||||
static_cast<T>(-5.3103913335180275253e+01L),
|
||||
static_cast<T>(-2.2795590826955002390e-01L)
|
||||
};
|
||||
static const T Q2[] = {
|
||||
static_cast<T>(-2.7062322985570842656e+06L),
|
||||
static_cast<T>(4.3117653211351080007e+04L),
|
||||
static_cast<T>(-3.0507151578787595807e+02L),
|
||||
static_cast<T>(1.0L)
|
||||
};
|
||||
static const T P3[] = {
|
||||
static_cast<T>(2.2196792496874548962e+00L),
|
||||
static_cast<T>(4.4137176114230414036e+01L),
|
||||
static_cast<T>(3.4122953486801312910e+02L),
|
||||
static_cast<T>(1.3319486433183221990e+03L),
|
||||
static_cast<T>(2.8590657697910288226e+03L),
|
||||
static_cast<T>(3.4540675585544584407e+03L),
|
||||
static_cast<T>(2.3123742209168871550e+03L),
|
||||
static_cast<T>(8.1094256146537402173e+02L),
|
||||
static_cast<T>(1.3182609918569941308e+02L),
|
||||
static_cast<T>(7.5584584631176030810e+00L),
|
||||
static_cast<T>(6.4257745859173138767e-02L)
|
||||
};
|
||||
static const T Q3[] = {
|
||||
static_cast<T>(1.7710478032601086579e+00L),
|
||||
static_cast<T>(3.4552228452758912848e+01L),
|
||||
static_cast<T>(2.5951223655579051357e+02L),
|
||||
static_cast<T>(9.6929165726802648634e+02L),
|
||||
static_cast<T>(1.9448440788918006154e+03L),
|
||||
static_cast<T>(2.1181000487171943810e+03L),
|
||||
static_cast<T>(1.2082692316002348638e+03L),
|
||||
static_cast<T>(3.3031020088765390854e+02L),
|
||||
static_cast<T>(3.6001069306861518855e+01L),
|
||||
static_cast<T>(1.0L)
|
||||
};
|
||||
T value, factor, r, r1, r2;
|
||||
|
||||
BOOST_MATH_STD_USING
|
||||
using namespace boost::math::tools;
|
||||
|
||||
static const char* function = "boost::math::bessel_k1<%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 (x <= 1) // x in (0, 1]
|
||||
{
|
||||
T y = x * x;
|
||||
r1 = evaluate_polynomial(P1, y) / evaluate_polynomial(Q1, y);
|
||||
r2 = evaluate_polynomial(P2, y) / evaluate_polynomial(Q2, y);
|
||||
factor = log(x);
|
||||
value = (r1 + factor * r2) / x;
|
||||
}
|
||||
else // x in (1, \infty)
|
||||
{
|
||||
T y = 1 / x;
|
||||
r = evaluate_polynomial(P3, y) / evaluate_polynomial(Q3, y);
|
||||
factor = exp(-x) / sqrt(x);
|
||||
value = factor * r;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
}}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_BESSEL_K1_HPP
|
||||
|
||||
85
test/external/boost/math/special_functions/detail/bessel_kn.hpp
vendored
Normal file
85
test/external/boost/math/special_functions/detail/bessel_kn.hpp
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
// 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)
|
||||
{
|
||||
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, pol);
|
||||
}
|
||||
else if (n == 1)
|
||||
{
|
||||
value = bessel_k1(x, pol);
|
||||
}
|
||||
else
|
||||
{
|
||||
prev = bessel_k0(x, pol);
|
||||
current = bessel_k1(x, pol);
|
||||
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
|
||||
|
||||
182
test/external/boost/math/special_functions/detail/bessel_y0.hpp
vendored
Normal file
182
test/external/boost/math/special_functions/detail/bessel_y0.hpp
vendored
Normal file
@@ -0,0 +1,182 @@
|
||||
// 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
|
||||
#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/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& pol)
|
||||
{
|
||||
static const T P1[] = {
|
||||
static_cast<T>(1.0723538782003176831e+11L),
|
||||
static_cast<T>(-8.3716255451260504098e+09L),
|
||||
static_cast<T>(2.0422274357376619816e+08L),
|
||||
static_cast<T>(-2.1287548474401797963e+06L),
|
||||
static_cast<T>(1.0102532948020907590e+04L),
|
||||
static_cast<T>(-1.8402381979244993524e+01L),
|
||||
};
|
||||
static const T Q1[] = {
|
||||
static_cast<T>(5.8873865738997033405e+11L),
|
||||
static_cast<T>(8.1617187777290363573e+09L),
|
||||
static_cast<T>(5.5662956624278251596e+07L),
|
||||
static_cast<T>(2.3889393209447253406e+05L),
|
||||
static_cast<T>(6.6475986689240190091e+02L),
|
||||
static_cast<T>(1.0L),
|
||||
};
|
||||
static const T P2[] = {
|
||||
static_cast<T>(-2.2213976967566192242e+13L),
|
||||
static_cast<T>(-5.5107435206722644429e+11L),
|
||||
static_cast<T>(4.3600098638603061642e+10L),
|
||||
static_cast<T>(-6.9590439394619619534e+08L),
|
||||
static_cast<T>(4.6905288611678631510e+06L),
|
||||
static_cast<T>(-1.4566865832663635920e+04L),
|
||||
static_cast<T>(1.7427031242901594547e+01L),
|
||||
};
|
||||
static const T Q2[] = {
|
||||
static_cast<T>(4.3386146580707264428e+14L),
|
||||
static_cast<T>(5.4266824419412347550e+12L),
|
||||
static_cast<T>(3.4015103849971240096e+10L),
|
||||
static_cast<T>(1.3960202770986831075e+08L),
|
||||
static_cast<T>(4.0669982352539552018e+05L),
|
||||
static_cast<T>(8.3030857612070288823e+02L),
|
||||
static_cast<T>(1.0L),
|
||||
};
|
||||
static const T P3[] = {
|
||||
static_cast<T>(-8.0728726905150210443e+15L),
|
||||
static_cast<T>(6.7016641869173237784e+14L),
|
||||
static_cast<T>(-1.2829912364088687306e+11L),
|
||||
static_cast<T>(-1.9363051266772083678e+11L),
|
||||
static_cast<T>(2.1958827170518100757e+09L),
|
||||
static_cast<T>(-1.0085539923498211426e+07L),
|
||||
static_cast<T>(2.1363534169313901632e+04L),
|
||||
static_cast<T>(-1.7439661319197499338e+01L),
|
||||
};
|
||||
static const T Q3[] = {
|
||||
static_cast<T>(3.4563724628846457519e+17L),
|
||||
static_cast<T>(3.9272425569640309819e+15L),
|
||||
static_cast<T>(2.2598377924042897629e+13L),
|
||||
static_cast<T>(8.6926121104209825246e+10L),
|
||||
static_cast<T>(2.4727219475672302327e+08L),
|
||||
static_cast<T>(5.3924739209768057030e+05L),
|
||||
static_cast<T>(8.7903362168128450017e+02L),
|
||||
static_cast<T>(1.0L),
|
||||
};
|
||||
static const T PC[] = {
|
||||
static_cast<T>(2.2779090197304684302e+04L),
|
||||
static_cast<T>(4.1345386639580765797e+04L),
|
||||
static_cast<T>(2.1170523380864944322e+04L),
|
||||
static_cast<T>(3.4806486443249270347e+03L),
|
||||
static_cast<T>(1.5376201909008354296e+02L),
|
||||
static_cast<T>(8.8961548424210455236e-01L),
|
||||
};
|
||||
static const T QC[] = {
|
||||
static_cast<T>(2.2779090197304684318e+04L),
|
||||
static_cast<T>(4.1370412495510416640e+04L),
|
||||
static_cast<T>(2.1215350561880115730e+04L),
|
||||
static_cast<T>(3.5028735138235608207e+03L),
|
||||
static_cast<T>(1.5711159858080893649e+02L),
|
||||
static_cast<T>(1.0L),
|
||||
};
|
||||
static const T PS[] = {
|
||||
static_cast<T>(-8.9226600200800094098e+01L),
|
||||
static_cast<T>(-1.8591953644342993800e+02L),
|
||||
static_cast<T>(-1.1183429920482737611e+02L),
|
||||
static_cast<T>(-2.2300261666214198472e+01L),
|
||||
static_cast<T>(-1.2441026745835638459e+00L),
|
||||
static_cast<T>(-8.8033303048680751817e-03L),
|
||||
};
|
||||
static const T QS[] = {
|
||||
static_cast<T>(5.7105024128512061905e+03L),
|
||||
static_cast<T>(1.1951131543434613647e+04L),
|
||||
static_cast<T>(7.2642780169211018836e+03L),
|
||||
static_cast<T>(1.4887231232283756582e+03L),
|
||||
static_cast<T>(9.0593769594993125859e+01L),
|
||||
static_cast<T>(1.0L),
|
||||
};
|
||||
static const T x1 = static_cast<T>(8.9357696627916752158e-01L),
|
||||
x2 = static_cast<T>(3.9576784193148578684e+00L),
|
||||
x3 = static_cast<T>(7.0860510603017726976e+00L),
|
||||
x11 = static_cast<T>(2.280e+02L),
|
||||
x12 = static_cast<T>(2.9519662791675215849e-03L),
|
||||
x21 = static_cast<T>(1.0130e+03L),
|
||||
x22 = static_cast<T>(6.4716931485786837568e-04L),
|
||||
x31 = static_cast<T>(1.8140e+03L),
|
||||
x32 = static_cast<T>(1.1356030177269762362e-04L)
|
||||
;
|
||||
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;
|
||||
T z = x - 0.25f * pi<T>();
|
||||
rc = evaluate_rational(PC, QC, y2);
|
||||
rs = evaluate_rational(PS, QS, y2);
|
||||
factor = sqrt(2 / (x * pi<T>()));
|
||||
value = factor * (rc * sin(z) + y * rs * cos(z));
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
}}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_BESSEL_Y0_HPP
|
||||
|
||||
155
test/external/boost/math/special_functions/detail/bessel_y1.hpp
vendored
Normal file
155
test/external/boost/math/special_functions/detail/bessel_y1.hpp
vendored
Normal file
@@ -0,0 +1,155 @@
|
||||
// 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
|
||||
#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/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& pol)
|
||||
{
|
||||
static const T P1[] = {
|
||||
static_cast<T>(4.0535726612579544093e+13L),
|
||||
static_cast<T>(5.4708611716525426053e+12L),
|
||||
static_cast<T>(-3.7595974497819597599e+11L),
|
||||
static_cast<T>(7.2144548214502560419e+09L),
|
||||
static_cast<T>(-5.9157479997408395984e+07L),
|
||||
static_cast<T>(2.2157953222280260820e+05L),
|
||||
static_cast<T>(-3.1714424660046133456e+02L),
|
||||
};
|
||||
static const T Q1[] = {
|
||||
static_cast<T>(3.0737873921079286084e+14L),
|
||||
static_cast<T>(4.1272286200406461981e+12L),
|
||||
static_cast<T>(2.7800352738690585613e+10L),
|
||||
static_cast<T>(1.2250435122182963220e+08L),
|
||||
static_cast<T>(3.8136470753052572164e+05L),
|
||||
static_cast<T>(8.2079908168393867438e+02L),
|
||||
static_cast<T>(1.0L),
|
||||
};
|
||||
static const T P2[] = {
|
||||
static_cast<T>(1.1514276357909013326e+19L),
|
||||
static_cast<T>(-5.6808094574724204577e+18L),
|
||||
static_cast<T>(-2.3638408497043134724e+16L),
|
||||
static_cast<T>(4.0686275289804744814e+15L),
|
||||
static_cast<T>(-5.9530713129741981618e+13L),
|
||||
static_cast<T>(3.7453673962438488783e+11L),
|
||||
static_cast<T>(-1.1957961912070617006e+09L),
|
||||
static_cast<T>(1.9153806858264202986e+06L),
|
||||
static_cast<T>(-1.2337180442012953128e+03L),
|
||||
};
|
||||
static const T Q2[] = {
|
||||
static_cast<T>(5.3321844313316185697e+20L),
|
||||
static_cast<T>(5.6968198822857178911e+18L),
|
||||
static_cast<T>(3.0837179548112881950e+16L),
|
||||
static_cast<T>(1.1187010065856971027e+14L),
|
||||
static_cast<T>(3.0221766852960403645e+11L),
|
||||
static_cast<T>(6.3550318087088919566e+08L),
|
||||
static_cast<T>(1.0453748201934079734e+06L),
|
||||
static_cast<T>(1.2855164849321609336e+03L),
|
||||
static_cast<T>(1.0L),
|
||||
};
|
||||
static const T PC[] = {
|
||||
static_cast<T>(-4.4357578167941278571e+06L),
|
||||
static_cast<T>(-9.9422465050776411957e+06L),
|
||||
static_cast<T>(-6.6033732483649391093e+06L),
|
||||
static_cast<T>(-1.5235293511811373833e+06L),
|
||||
static_cast<T>(-1.0982405543459346727e+05L),
|
||||
static_cast<T>(-1.6116166443246101165e+03L),
|
||||
static_cast<T>(0.0L),
|
||||
};
|
||||
static const T QC[] = {
|
||||
static_cast<T>(-4.4357578167941278568e+06L),
|
||||
static_cast<T>(-9.9341243899345856590e+06L),
|
||||
static_cast<T>(-6.5853394797230870728e+06L),
|
||||
static_cast<T>(-1.5118095066341608816e+06L),
|
||||
static_cast<T>(-1.0726385991103820119e+05L),
|
||||
static_cast<T>(-1.4550094401904961825e+03L),
|
||||
static_cast<T>(1.0L),
|
||||
};
|
||||
static const T PS[] = {
|
||||
static_cast<T>(3.3220913409857223519e+04L),
|
||||
static_cast<T>(8.5145160675335701966e+04L),
|
||||
static_cast<T>(6.6178836581270835179e+04L),
|
||||
static_cast<T>(1.8494262873223866797e+04L),
|
||||
static_cast<T>(1.7063754290207680021e+03L),
|
||||
static_cast<T>(3.5265133846636032186e+01L),
|
||||
static_cast<T>(0.0L),
|
||||
};
|
||||
static const T QS[] = {
|
||||
static_cast<T>(7.0871281941028743574e+05L),
|
||||
static_cast<T>(1.8194580422439972989e+06L),
|
||||
static_cast<T>(1.4194606696037208929e+06L),
|
||||
static_cast<T>(4.0029443582266975117e+05L),
|
||||
static_cast<T>(3.7890229745772202641e+04L),
|
||||
static_cast<T>(8.6383677696049909675e+02L),
|
||||
static_cast<T>(1.0L),
|
||||
};
|
||||
static const T x1 = static_cast<T>(2.1971413260310170351e+00L),
|
||||
x2 = static_cast<T>(5.4296810407941351328e+00L),
|
||||
x11 = static_cast<T>(5.620e+02L),
|
||||
x12 = static_cast<T>(1.8288260310170351490e-03L),
|
||||
x21 = static_cast<T>(1.3900e+03L),
|
||||
x22 = static_cast<T>(-6.4592058648672279948e-06L)
|
||||
;
|
||||
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;
|
||||
T z = x - 0.75f * pi<T>();
|
||||
rc = evaluate_rational(PC, QC, y2);
|
||||
rs = evaluate_rational(PS, QS, y2);
|
||||
factor = sqrt(2 / (x * pi<T>()));
|
||||
value = factor * (rc * sin(z) + y * rs * cos(z));
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
}}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_BESSEL_Y1_HPP
|
||||
|
||||
103
test/external/boost/math/special_functions/detail/bessel_yn.hpp
vendored
Normal file
103
test/external/boost/math/special_functions/detail/bessel_yn.hpp
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
// 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 = (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 (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);
|
||||
do
|
||||
{
|
||||
T fact = 2 * k / x;
|
||||
if((tools::max_value<T>() - fabs(prev)) / fact < fabs(current))
|
||||
{
|
||||
prev /= current;
|
||||
factor /= current;
|
||||
current = 1;
|
||||
}
|
||||
value = fact * current - prev;
|
||||
prev = current;
|
||||
current = value;
|
||||
++k;
|
||||
}
|
||||
while(k < n);
|
||||
if(tools::max_value<T>() * factor < value)
|
||||
return sign(value) * sign(value) * policies::raise_overflow_error<T>(function, 0, pol);
|
||||
value /= factor;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
}}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_BESSEL_YN_HPP
|
||||
|
||||
471
test/external/boost/math/special_functions/detail/erf_inv.hpp
vendored
Normal file
471
test/external/boost/math/special_functions/detail/erf_inv.hpp
vendored
Normal file
@@ -0,0 +1,471 @@
|
||||
// (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
|
||||
#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[] = {
|
||||
-0.000508781949658280665617L,
|
||||
-0.00836874819741736770379L,
|
||||
0.0334806625409744615033L,
|
||||
-0.0126926147662974029034L,
|
||||
-0.0365637971411762664006L,
|
||||
0.0219878681111168899165L,
|
||||
0.00822687874676915743155L,
|
||||
-0.00538772965071242932965L
|
||||
};
|
||||
static const T Q[] = {
|
||||
1,
|
||||
-0.970005043303290640362L,
|
||||
-1.56574558234175846809L,
|
||||
1.56221558398423026363L,
|
||||
0.662328840472002992063L,
|
||||
-0.71228902341542847553L,
|
||||
-0.0527396382340099713954L,
|
||||
0.0795283687341571680018L,
|
||||
-0.00233393759374190016776L,
|
||||
0.000886216390456424707504L
|
||||
};
|
||||
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[] = {
|
||||
-0.202433508355938759655L,
|
||||
0.105264680699391713268L,
|
||||
8.37050328343119927838L,
|
||||
17.6447298408374015486L,
|
||||
-18.8510648058714251895L,
|
||||
-44.6382324441786960818L,
|
||||
17.445385985570866523L,
|
||||
21.1294655448340526258L,
|
||||
-3.67192254707729348546L
|
||||
};
|
||||
static const T Q[] = {
|
||||
1L,
|
||||
6.24264124854247537712L,
|
||||
3.9713437953343869095L,
|
||||
-28.6608180499800029974L,
|
||||
-20.1432634680485188801L,
|
||||
48.5609213108739935468L,
|
||||
10.8268667355460159008L,
|
||||
-22.6436933413139721736L,
|
||||
1.72114765761200282724L
|
||||
};
|
||||
T g = sqrt(-2 * log(q));
|
||||
T xs = q - 0.25;
|
||||
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[] = {
|
||||
-0.131102781679951906451L,
|
||||
-0.163794047193317060787L,
|
||||
0.117030156341995252019L,
|
||||
0.387079738972604337464L,
|
||||
0.337785538912035898924L,
|
||||
0.142869534408157156766L,
|
||||
0.0290157910005329060432L,
|
||||
0.00214558995388805277169L,
|
||||
-0.679465575181126350155e-6L,
|
||||
0.285225331782217055858e-7L,
|
||||
-0.681149956853776992068e-9L
|
||||
};
|
||||
static const T Q[] = {
|
||||
1,
|
||||
3.46625407242567245975L,
|
||||
5.38168345707006855425L,
|
||||
4.77846592945843778382L,
|
||||
2.59301921623620271374L,
|
||||
0.848854343457902036425L,
|
||||
0.152264338295331783612L,
|
||||
0.01105924229346489121L
|
||||
};
|
||||
T xs = x - 1.125;
|
||||
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[] = {
|
||||
-0.0350353787183177984712L,
|
||||
-0.00222426529213447927281L,
|
||||
0.0185573306514231072324L,
|
||||
0.00950804701325919603619L,
|
||||
0.00187123492819559223345L,
|
||||
0.000157544617424960554631L,
|
||||
0.460469890584317994083e-5L,
|
||||
-0.230404776911882601748e-9L,
|
||||
0.266339227425782031962e-11L
|
||||
};
|
||||
static const T Q[] = {
|
||||
1L,
|
||||
1.3653349817554063097L,
|
||||
0.762059164553623404043L,
|
||||
0.220091105764131249824L,
|
||||
0.0341589143670947727934L,
|
||||
0.00263861676657015992959L,
|
||||
0.764675292302794483503e-4L
|
||||
};
|
||||
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[] = {
|
||||
-0.0167431005076633737133L,
|
||||
-0.00112951438745580278863L,
|
||||
0.00105628862152492910091L,
|
||||
0.000209386317487588078668L,
|
||||
0.149624783758342370182e-4L,
|
||||
0.449696789927706453732e-6L,
|
||||
0.462596163522878599135e-8L,
|
||||
-0.281128735628831791805e-13L,
|
||||
0.99055709973310326855e-16L
|
||||
};
|
||||
static const T Q[] = {
|
||||
1L,
|
||||
0.591429344886417493481L,
|
||||
0.138151865749083321638L,
|
||||
0.0160746087093676504695L,
|
||||
0.000964011807005165528527L,
|
||||
0.275335474764726041141e-4L,
|
||||
0.282243172016108031869e-6L
|
||||
};
|
||||
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[] = {
|
||||
-0.0024978212791898131227L,
|
||||
-0.779190719229053954292e-5L,
|
||||
0.254723037413027451751e-4L,
|
||||
0.162397777342510920873e-5L,
|
||||
0.396341011304801168516e-7L,
|
||||
0.411632831190944208473e-9L,
|
||||
0.145596286718675035587e-11L,
|
||||
-0.116765012397184275695e-17L
|
||||
};
|
||||
static const T Q[] = {
|
||||
1L,
|
||||
0.207123112214422517181L,
|
||||
0.0169410838120975906478L,
|
||||
0.000690538265622684595676L,
|
||||
0.145007359818232637924e-4L,
|
||||
0.144437756628144157666e-6L,
|
||||
0.509761276599778486139e-9L
|
||||
};
|
||||
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[] = {
|
||||
-0.000539042911019078575891L,
|
||||
-0.28398759004727721098e-6L,
|
||||
0.899465114892291446442e-6L,
|
||||
0.229345859265920864296e-7L,
|
||||
0.225561444863500149219e-9L,
|
||||
0.947846627503022684216e-12L,
|
||||
0.135880130108924861008e-14L,
|
||||
-0.348890393399948882918e-21L
|
||||
};
|
||||
static const T Q[] = {
|
||||
1L,
|
||||
0.0845746234001899436914L,
|
||||
0.00282092984726264681981L,
|
||||
0.468292921940894236786e-4L,
|
||||
0.399968812193862100054e-6L,
|
||||
0.161809290887904476097e-8L,
|
||||
0.231558608310259605225e-11L
|
||||
};
|
||||
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) ? boost::math::erf(guess, Policy()) : 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;
|
||||
}
|
||||
|
||||
} // 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))
|
||||
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;
|
||||
|
||||
//
|
||||
// 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))
|
||||
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;
|
||||
//
|
||||
// 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
|
||||
|
||||
#endif // BOOST_MATH_SF_ERF_INV_HPP
|
||||
|
||||
570
test/external/boost/math/special_functions/detail/fp_traits.hpp
vendored
Normal file
570
test/external/boost/math/special_functions/detail/fp_traits.hpp
vendored
Normal file
@@ -0,0 +1,570 @@
|
||||
// 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/detail/endian.hpp>
|
||||
#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(...)
|
||||
{
|
||||
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 defined(BOOST_BIG_ENDIAN)
|
||||
BOOST_STATIC_CONSTANT(int, offset_ = 0);
|
||||
#elif defined(BOOST_LITTLE_ENDIAN)
|
||||
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 defined(BOOST_BIG_ENDIAN)
|
||||
BOOST_STATIC_CONSTANT(int, offset_ = 0);
|
||||
#elif defined(BOOST_LITTLE_ENDIAN)
|
||||
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).
|
||||
|
||||
|
||||
// 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 defined(BOOST_BIG_ENDIAN)
|
||||
BOOST_STATIC_CONSTANT(int, offset_ = 0);
|
||||
#elif defined(BOOST_LITTLE_ENDIAN)
|
||||
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 defined(BOOST_BIG_ENDIAN)
|
||||
BOOST_STATIC_CONSTANT(int, offset_ = 0);
|
||||
#elif defined(BOOST_LITTLE_ENDIAN)
|
||||
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(BOOST_MATH_DISABLE_STD_FPCLASSIFY)
|
||||
# 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
test/external/boost/math/special_functions/detail/gamma_inva.hpp
vendored
Normal file
233
test/external/boost/math/special_functions/detail/gamma_inva.hpp
vendored
Normal 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 tools::max_value<T>();
|
||||
}
|
||||
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>())
|
||||
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)
|
||||
{
|
||||
return tools::max_value<result_type>();
|
||||
}
|
||||
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)
|
||||
{
|
||||
return tools::max_value<result_type>();
|
||||
}
|
||||
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
|
||||
|
||||
|
||||
|
||||
324
test/external/boost/math/special_functions/detail/ibeta_inv_ab.hpp
vendored
Normal file
324
test/external/boost/math/special_functions/detail/ibeta_inv_ab.hpp
vendored
Normal file
@@ -0,0 +1,324 @@
|
||||
// (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>())
|
||||
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;
|
||||
|
||||
if(p == 0)
|
||||
{
|
||||
return tools::max_value<result_type>();
|
||||
}
|
||||
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),
|
||||
"boost::math::ibeta_inva<%1%>(%1%,%1%,%1%)");
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if(q == 1)
|
||||
{
|
||||
return tools::max_value<result_type>();
|
||||
}
|
||||
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),
|
||||
"boost::math::ibetac_inva<%1%>(%1%,%1%,%1%)");
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if(p == 0)
|
||||
{
|
||||
return tools::min_value<result_type>();
|
||||
}
|
||||
if(p == 1)
|
||||
{
|
||||
return tools::max_value<result_type>();
|
||||
}
|
||||
|
||||
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),
|
||||
"boost::math::ibeta_invb<%1%>(%1%,%1%,%1%)");
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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 tools::max_value<result_type>();
|
||||
}
|
||||
|
||||
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),
|
||||
"boost::math::ibetac_invb<%1%>(%1%,%1%,%1%)");
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
|
||||
|
||||
944
test/external/boost/math/special_functions/detail/ibeta_inverse.hpp
vendored
Normal file
944
test/external/boost/math/special_functions/detail/ibeta_inverse.hpp
vendored
Normal file
@@ -0,0 +1,944 @@
|
||||
// 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(-big, -big);
|
||||
}
|
||||
if(x == 0)
|
||||
{
|
||||
T big = tools::max_value<T>() / 4;
|
||||
return boost::math::make_tuple(-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.
|
||||
|
||||
//
|
||||
// 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) && (b == 1))
|
||||
{
|
||||
if(py) *py = 1 - p;
|
||||
return p;
|
||||
}
|
||||
//
|
||||
// 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;
|
||||
//
|
||||
// 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) && (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))
|
||||
{
|
||||
//
|
||||
// We have a Student's T distribution:
|
||||
x = find_ibeta_inv_from_t_dist(a, p, q, &y, pol);
|
||||
}
|
||||
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)
|
||||
{
|
||||
return ibeta_inv(a, b, p, static_cast<T1*>(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)
|
||||
{
|
||||
return ibeta_inv(a, b, p, static_cast<T1*>(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)
|
||||
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)
|
||||
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))
|
||||
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 remove_cv<RT1>::type dummy;
|
||||
return ibetac_inv(a, b, q, static_cast<dummy*>(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 remove_cv<RT1>::type dummy;
|
||||
return ibetac_inv(a, b, q, static_cast<dummy*>(0), pol);
|
||||
}
|
||||
|
||||
} // namespace math
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_MATH_SPECIAL_FUNCTIONS_IGAMMA_INVERSE_HPP
|
||||
|
||||
|
||||
|
||||
|
||||
42
test/external/boost/math/special_functions/detail/iconv.hpp
vendored
Normal file
42
test/external/boost/math/special_functions/detail/iconv.hpp
vendored
Normal 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);
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
552
test/external/boost/math/special_functions/detail/igamma_inverse.hpp
vendored
Normal file
552
test/external/boost/math/special_functions/detail/igamma_inverse.hpp
vendored
Normal file
@@ -0,0 +1,552 @@
|
||||
// (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);
|
||||
T s = 1;
|
||||
z = exp((v + w) / a);
|
||||
s = boost::math::log1p(z / ap1 * (1 + z / ap2));
|
||||
z = exp((v + z - s) / a);
|
||||
s = boost::math::log1p(z / ap1 * (1 + z / ap2));
|
||||
z = exp((v + z - s) / a);
|
||||
s = boost::math::log1p(z / ap1 * (1 + z / ap2 * (1 + z / (a + 3))));
|
||||
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(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)
|
||||
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))
|
||||
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 tools::max_value<T>();
|
||||
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)
|
||||
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))
|
||||
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 tools::max_value<T>();
|
||||
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
|
||||
|
||||
|
||||
|
||||
769
test/external/boost/math/special_functions/detail/igamma_large.hpp
vendored
Normal file
769
test/external/boost/math/special_functions/detail/igamma_large.hpp
vendored
Normal file
@@ -0,0 +1,769 @@
|
||||
// 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[] = {
|
||||
-0.333333333333333333333L,
|
||||
0.0833333333333333333333L,
|
||||
-0.0148148148148148148148L,
|
||||
0.00115740740740740740741L,
|
||||
0.000352733686067019400353L,
|
||||
-0.0001787551440329218107L,
|
||||
0.39192631785224377817e-4L,
|
||||
-0.218544851067999216147e-5L,
|
||||
-0.18540622107151599607e-5L,
|
||||
0.829671134095308600502e-6L,
|
||||
-0.176659527368260793044e-6L,
|
||||
0.670785354340149858037e-8L,
|
||||
0.102618097842403080426e-7L,
|
||||
-0.438203601845335318655e-8L,
|
||||
0.914769958223679023418e-9L,
|
||||
-0.255141939949462497669e-10L,
|
||||
-0.583077213255042506746e-10L,
|
||||
0.243619480206674162437e-10L,
|
||||
-0.502766928011417558909e-11L,
|
||||
};
|
||||
workspace[0] = tools::evaluate_polynomial(C0, z);
|
||||
|
||||
static const T C1[] = {
|
||||
-0.00185185185185185185185L,
|
||||
-0.00347222222222222222222L,
|
||||
0.00264550264550264550265L,
|
||||
-0.000990226337448559670782L,
|
||||
0.000205761316872427983539L,
|
||||
-0.40187757201646090535e-6L,
|
||||
-0.18098550334489977837e-4L,
|
||||
0.764916091608111008464e-5L,
|
||||
-0.161209008945634460038e-5L,
|
||||
0.464712780280743434226e-8L,
|
||||
0.137863344691572095931e-6L,
|
||||
-0.575254560351770496402e-7L,
|
||||
0.119516285997781473243e-7L,
|
||||
-0.175432417197476476238e-10L,
|
||||
-0.100915437106004126275e-8L,
|
||||
0.416279299184258263623e-9L,
|
||||
-0.856390702649298063807e-10L,
|
||||
};
|
||||
workspace[1] = tools::evaluate_polynomial(C1, z);
|
||||
|
||||
static const T C2[] = {
|
||||
0.00413359788359788359788L,
|
||||
-0.00268132716049382716049L,
|
||||
0.000771604938271604938272L,
|
||||
0.200938786008230452675e-5L,
|
||||
-0.000107366532263651605215L,
|
||||
0.529234488291201254164e-4L,
|
||||
-0.127606351886187277134e-4L,
|
||||
0.342357873409613807419e-7L,
|
||||
0.137219573090629332056e-5L,
|
||||
-0.629899213838005502291e-6L,
|
||||
0.142806142060642417916e-6L,
|
||||
-0.204770984219908660149e-9L,
|
||||
-0.140925299108675210533e-7L,
|
||||
0.622897408492202203356e-8L,
|
||||
-0.136704883966171134993e-8L,
|
||||
};
|
||||
workspace[2] = tools::evaluate_polynomial(C2, z);
|
||||
|
||||
static const T C3[] = {
|
||||
0.000649434156378600823045L,
|
||||
0.000229472093621399176955L,
|
||||
-0.000469189494395255712128L,
|
||||
0.000267720632062838852962L,
|
||||
-0.756180167188397641073e-4L,
|
||||
-0.239650511386729665193e-6L,
|
||||
0.110826541153473023615e-4L,
|
||||
-0.56749528269915965675e-5L,
|
||||
0.142309007324358839146e-5L,
|
||||
-0.278610802915281422406e-10L,
|
||||
-0.169584040919302772899e-6L,
|
||||
0.809946490538808236335e-7L,
|
||||
-0.191111684859736540607e-7L,
|
||||
};
|
||||
workspace[3] = tools::evaluate_polynomial(C3, z);
|
||||
|
||||
static const T C4[] = {
|
||||
-0.000861888290916711698605L,
|
||||
0.000784039221720066627474L,
|
||||
-0.000299072480303190179733L,
|
||||
-0.146384525788434181781e-5L,
|
||||
0.664149821546512218666e-4L,
|
||||
-0.396836504717943466443e-4L,
|
||||
0.113757269706784190981e-4L,
|
||||
0.250749722623753280165e-9L,
|
||||
-0.169541495365583060147e-5L,
|
||||
0.890750753220530968883e-6L,
|
||||
-0.229293483400080487057e-6L,
|
||||
};
|
||||
workspace[4] = tools::evaluate_polynomial(C4, z);
|
||||
|
||||
static const T C5[] = {
|
||||
-0.000336798553366358150309L,
|
||||
-0.697281375836585777429e-4L,
|
||||
0.000277275324495939207873L,
|
||||
-0.000199325705161888477003L,
|
||||
0.679778047793720783882e-4L,
|
||||
0.141906292064396701483e-6L,
|
||||
-0.135940481897686932785e-4L,
|
||||
0.801847025633420153972e-5L,
|
||||
-0.229148117650809517038e-5L,
|
||||
};
|
||||
workspace[5] = tools::evaluate_polynomial(C5, z);
|
||||
|
||||
static const T C6[] = {
|
||||
0.000531307936463992223166L,
|
||||
-0.000592166437353693882865L,
|
||||
0.000270878209671804482771L,
|
||||
0.790235323266032787212e-6L,
|
||||
-0.815396936756196875093e-4L,
|
||||
0.561168275310624965004e-4L,
|
||||
-0.183291165828433755673e-4L,
|
||||
-0.307961345060330478256e-8L,
|
||||
0.346515536880360908674e-5L,
|
||||
-0.20291327396058603727e-5L,
|
||||
0.57887928631490037089e-6L,
|
||||
};
|
||||
workspace[6] = tools::evaluate_polynomial(C6, z);
|
||||
|
||||
static const T C7[] = {
|
||||
0.000344367606892377671254L,
|
||||
0.517179090826059219337e-4L,
|
||||
-0.000334931610811422363117L,
|
||||
0.000281269515476323702274L,
|
||||
-0.000109765822446847310235L,
|
||||
-0.127410090954844853795e-6L,
|
||||
0.277444515115636441571e-4L,
|
||||
-0.182634888057113326614e-4L,
|
||||
0.578769494973505239894e-5L,
|
||||
};
|
||||
workspace[7] = tools::evaluate_polynomial(C7, z);
|
||||
|
||||
static const T C8[] = {
|
||||
-0.000652623918595309418922L,
|
||||
0.000839498720672087279993L,
|
||||
-0.000438297098541721005061L,
|
||||
-0.696909145842055197137e-6L,
|
||||
0.000166448466420675478374L,
|
||||
-0.000127835176797692185853L,
|
||||
0.462995326369130429061e-4L,
|
||||
};
|
||||
workspace[8] = tools::evaluate_polynomial(C8, z);
|
||||
|
||||
static const T C9[] = {
|
||||
-0.000596761290192746250124L,
|
||||
-0.720489541602001055909e-4L,
|
||||
0.000678230883766732836162L,
|
||||
-0.0006401475260262758451L,
|
||||
0.000277501076343287044992L,
|
||||
};
|
||||
workspace[9] = tools::evaluate_polynomial(C9, z);
|
||||
|
||||
static const T C10[] = {
|
||||
0.00133244544948006563713L,
|
||||
-0.0019144384985654775265L,
|
||||
0.00110893691345966373396L,
|
||||
};
|
||||
workspace[10] = tools::evaluate_polynomial(C10, z);
|
||||
|
||||
static const T C11[] = {
|
||||
0.00157972766073083495909L,
|
||||
0.000162516262783915816899L,
|
||||
-0.00206334210355432762645L,
|
||||
0.00213896861856890981541L,
|
||||
-0.00101085593912630031708L,
|
||||
};
|
||||
workspace[11] = tools::evaluate_polynomial(C11, z);
|
||||
|
||||
static const T C12[] = {
|
||||
-0.00407251211951401664727L,
|
||||
0.00640336283380806979482L,
|
||||
-0.00404101610816766177474L,
|
||||
};
|
||||
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[] = {
|
||||
-0.333333333333333333333333333333333333L,
|
||||
0.0833333333333333333333333333333333333L,
|
||||
-0.0148148148148148148148148148148148148L,
|
||||
0.00115740740740740740740740740740740741L,
|
||||
0.0003527336860670194003527336860670194L,
|
||||
-0.000178755144032921810699588477366255144L,
|
||||
0.391926317852243778169704095630021556e-4L,
|
||||
-0.218544851067999216147364295512443661e-5L,
|
||||
-0.185406221071515996070179883622956325e-5L,
|
||||
0.829671134095308600501624213166443227e-6L,
|
||||
-0.17665952736826079304360054245742403e-6L,
|
||||
0.670785354340149858036939710029613572e-8L,
|
||||
0.102618097842403080425739573227252951e-7L,
|
||||
-0.438203601845335318655297462244719123e-8L,
|
||||
0.914769958223679023418248817633113681e-9L,
|
||||
-0.255141939949462497668779537993887013e-10L,
|
||||
-0.583077213255042506746408945040035798e-10L,
|
||||
0.243619480206674162436940696707789943e-10L,
|
||||
-0.502766928011417558909054985925744366e-11L,
|
||||
0.110043920319561347708374174497293411e-12L,
|
||||
0.337176326240098537882769884169200185e-12L,
|
||||
-0.13923887224181620659193661848957998e-12L,
|
||||
0.285348938070474432039669099052828299e-13L,
|
||||
-0.513911183424257261899064580300494205e-15L,
|
||||
-0.197522882943494428353962401580710912e-14L,
|
||||
0.809952115670456133407115668702575255e-15L,
|
||||
-0.165225312163981618191514820265351162e-15L,
|
||||
0.253054300974788842327061090060267385e-17L,
|
||||
0.116869397385595765888230876507793475e-16L,
|
||||
-0.477003704982048475822167804084816597e-17L,
|
||||
0.969912605905623712420709685898585354e-18L,
|
||||
};
|
||||
workspace[0] = tools::evaluate_polynomial(C0, z);
|
||||
|
||||
static const T C1[] = {
|
||||
-0.00185185185185185185185185185185185185L,
|
||||
-0.00347222222222222222222222222222222222L,
|
||||
0.0026455026455026455026455026455026455L,
|
||||
-0.000990226337448559670781893004115226337L,
|
||||
0.000205761316872427983539094650205761317L,
|
||||
-0.401877572016460905349794238683127572e-6L,
|
||||
-0.180985503344899778370285914867533523e-4L,
|
||||
0.76491609160811100846374214980916921e-5L,
|
||||
-0.16120900894563446003775221882217767e-5L,
|
||||
0.464712780280743434226135033938722401e-8L,
|
||||
0.137863344691572095931187533077488877e-6L,
|
||||
-0.575254560351770496402194531835048307e-7L,
|
||||
0.119516285997781473243076536699698169e-7L,
|
||||
-0.175432417197476476237547551202312502e-10L,
|
||||
-0.100915437106004126274577504686681675e-8L,
|
||||
0.416279299184258263623372347219858628e-9L,
|
||||
-0.856390702649298063807431562579670208e-10L,
|
||||
0.606721510160475861512701762169919581e-13L,
|
||||
0.716249896481148539007961017165545733e-11L,
|
||||
-0.293318664377143711740636683615595403e-11L,
|
||||
0.599669636568368872330374527568788909e-12L,
|
||||
-0.216717865273233141017100472779701734e-15L,
|
||||
-0.497833997236926164052815522048108548e-13L,
|
||||
0.202916288237134247736694804325894226e-13L,
|
||||
-0.413125571381061004935108332558187111e-14L,
|
||||
0.828651623988309644380188591057589316e-18L,
|
||||
0.341003088693333279336339355910600992e-15L,
|
||||
-0.138541953028939715357034547426313703e-15L,
|
||||
0.281234665322887466568860332727259483e-16L,
|
||||
};
|
||||
workspace[1] = tools::evaluate_polynomial(C1, z);
|
||||
|
||||
static const T C2[] = {
|
||||
0.0041335978835978835978835978835978836L,
|
||||
-0.00268132716049382716049382716049382716L,
|
||||
0.000771604938271604938271604938271604938L,
|
||||
0.200938786008230452674897119341563786e-5L,
|
||||
-0.000107366532263651605215391223621676297L,
|
||||
0.529234488291201254164217127180090143e-4L,
|
||||
-0.127606351886187277133779191392360117e-4L,
|
||||
0.34235787340961380741902003904747389e-7L,
|
||||
0.137219573090629332055943852926020279e-5L,
|
||||
-0.629899213838005502290672234278391876e-6L,
|
||||
0.142806142060642417915846008822771748e-6L,
|
||||
-0.204770984219908660149195854409200226e-9L,
|
||||
-0.140925299108675210532930244154315272e-7L,
|
||||
0.622897408492202203356394293530327112e-8L,
|
||||
-0.136704883966171134992724380284402402e-8L,
|
||||
0.942835615901467819547711211663208075e-12L,
|
||||
0.128722524000893180595479368872770442e-9L,
|
||||
-0.556459561343633211465414765894951439e-10L,
|
||||
0.119759355463669810035898150310311343e-10L,
|
||||
-0.416897822518386350403836626692480096e-14L,
|
||||
-0.109406404278845944099299008640802908e-11L,
|
||||
0.4662239946390135746326204922464679e-12L,
|
||||
-0.990510576390690597844122258212382301e-13L,
|
||||
0.189318767683735145056885183170630169e-16L,
|
||||
0.885922187259112726176031067028740667e-14L,
|
||||
-0.373782039804640545306560251777191937e-14L,
|
||||
0.786883363903515525774088394065960751e-15L,
|
||||
};
|
||||
workspace[2] = tools::evaluate_polynomial(C2, z);
|
||||
|
||||
static const T C3[] = {
|
||||
0.000649434156378600823045267489711934156L,
|
||||
0.000229472093621399176954732510288065844L,
|
||||
-0.000469189494395255712128140111679206329L,
|
||||
0.000267720632062838852962309752433209223L,
|
||||
-0.756180167188397641072538191879755666e-4L,
|
||||
-0.239650511386729665193314027333231723e-6L,
|
||||
0.110826541153473023614770299726861227e-4L,
|
||||
-0.567495282699159656749963105701560205e-5L,
|
||||
0.14230900732435883914551894470580433e-5L,
|
||||
-0.278610802915281422405802158211174452e-10L,
|
||||
-0.16958404091930277289864168795820267e-6L,
|
||||
0.809946490538808236335278504852724081e-7L,
|
||||
-0.191111684859736540606728140872727635e-7L,
|
||||
0.239286204398081179686413514022282056e-11L,
|
||||
0.206201318154887984369925818486654549e-8L,
|
||||
-0.946049666185513217375417988510192814e-9L,
|
||||
0.215410497757749078380130268468744512e-9L,
|
||||
-0.138882333681390304603424682490735291e-13L,
|
||||
-0.218947616819639394064123400466489455e-10L,
|
||||
0.979099895117168512568262802255883368e-11L,
|
||||
-0.217821918801809621153859472011393244e-11L,
|
||||
0.62088195734079014258166361684972205e-16L,
|
||||
0.212697836327973697696702537114614471e-12L,
|
||||
-0.934468879151743333127396765626749473e-13L,
|
||||
0.204536712267828493249215913063207436e-13L,
|
||||
};
|
||||
workspace[3] = tools::evaluate_polynomial(C3, z);
|
||||
|
||||
static const T C4[] = {
|
||||
-0.000861888290916711698604702719929057378L,
|
||||
0.00078403922172006662747403488144228885L,
|
||||
-0.000299072480303190179733389609932819809L,
|
||||
-0.146384525788434181781232535690697556e-5L,
|
||||
0.664149821546512218665853782451862013e-4L,
|
||||
-0.396836504717943466443123507595386882e-4L,
|
||||
0.113757269706784190980552042885831759e-4L,
|
||||
0.250749722623753280165221942390057007e-9L,
|
||||
-0.169541495365583060147164356781525752e-5L,
|
||||
0.890750753220530968882898422505515924e-6L,
|
||||
-0.229293483400080487057216364891158518e-6L,
|
||||
0.295679413754404904696572852500004588e-10L,
|
||||
0.288658297427087836297341274604184504e-7L,
|
||||
-0.141897394378032193894774303903982717e-7L,
|
||||
0.344635804994648970659527720474194356e-8L,
|
||||
-0.230245171745280671320192735850147087e-12L,
|
||||
-0.394092330280464052750697640085291799e-9L,
|
||||
0.186023389685045019134258533045185639e-9L,
|
||||
-0.435632300505661804380678327446262424e-10L,
|
||||
0.127860010162962312660550463349930726e-14L,
|
||||
0.467927502665791946200382739991760062e-11L,
|
||||
-0.214924647061348285410535341910721086e-11L,
|
||||
0.490881561480965216323649688463984082e-12L,
|
||||
};
|
||||
workspace[4] = tools::evaluate_polynomial(C4, z);
|
||||
|
||||
static const T C5[] = {
|
||||
-0.000336798553366358150308767592718210002L,
|
||||
-0.697281375836585777429398828575783308e-4L,
|
||||
0.00027727532449593920787336425196507501L,
|
||||
-0.000199325705161888477003360405280844238L,
|
||||
0.679778047793720783881640176604435742e-4L,
|
||||
0.141906292064396701483392727105575757e-6L,
|
||||
-0.135940481897686932784583938837504469e-4L,
|
||||
0.80184702563342015397192571980419684e-5L,
|
||||
-0.229148117650809517038048790128781806e-5L,
|
||||
-0.325247355129845395166230137750005047e-9L,
|
||||
0.346528464910852649559195496827579815e-6L,
|
||||
-0.184471871911713432765322367374920978e-6L,
|
||||
0.482409670378941807563762631738989002e-7L,
|
||||
-0.179894667217435153025754291716644314e-13L,
|
||||
-0.630619450001352343517516981425944698e-8L,
|
||||
0.316241762877456793773762181540969623e-8L,
|
||||
-0.784092425369742929000839303523267545e-9L,
|
||||
};
|
||||
workspace[5] = tools::evaluate_polynomial(C5, z);
|
||||
|
||||
static const T C6[] = {
|
||||
0.00053130793646399222316574854297762391L,
|
||||
-0.000592166437353693882864836225604401187L,
|
||||
0.000270878209671804482771279183488328692L,
|
||||
0.790235323266032787212032944390816666e-6L,
|
||||
-0.815396936756196875092890088464682624e-4L,
|
||||
0.561168275310624965003775619041471695e-4L,
|
||||
-0.183291165828433755673259749374098313e-4L,
|
||||
-0.307961345060330478256414192546677006e-8L,
|
||||
0.346515536880360908673728529745376913e-5L,
|
||||
-0.202913273960586037269527254582695285e-5L,
|
||||
0.578879286314900370889997586203187687e-6L,
|
||||
0.233863067382665698933480579231637609e-12L,
|
||||
-0.88286007463304835250508524317926246e-7L,
|
||||
0.474359588804081278032150770595852426e-7L,
|
||||
-0.125454150207103824457130611214783073e-7L,
|
||||
};
|
||||
workspace[6] = tools::evaluate_polynomial(C6, z);
|
||||
|
||||
static const T C7[] = {
|
||||
0.000344367606892377671254279625108523655L,
|
||||
0.517179090826059219337057843002058823e-4L,
|
||||
-0.000334931610811422363116635090580012327L,
|
||||
0.000281269515476323702273722110707777978L,
|
||||
-0.000109765822446847310235396824500789005L,
|
||||
-0.127410090954844853794579954588107623e-6L,
|
||||
0.277444515115636441570715073933712622e-4L,
|
||||
-0.182634888057113326614324442681892723e-4L,
|
||||
0.578769494973505239894178121070843383e-5L,
|
||||
0.493875893393627039981813418398565502e-9L,
|
||||
-0.105953670140260427338098566209633945e-5L,
|
||||
0.616671437611040747858836254004890765e-6L,
|
||||
-0.175629733590604619378669693914265388e-6L,
|
||||
};
|
||||
workspace[7] = tools::evaluate_polynomial(C7, z);
|
||||
|
||||
static const T C8[] = {
|
||||
-0.000652623918595309418922034919726622692L,
|
||||
0.000839498720672087279993357516764983445L,
|
||||
-0.000438297098541721005061087953050560377L,
|
||||
-0.696909145842055197136911097362072702e-6L,
|
||||
0.00016644846642067547837384572662326101L,
|
||||
-0.000127835176797692185853344001461664247L,
|
||||
0.462995326369130429061361032704489636e-4L,
|
||||
0.455790986792270771162749294232219616e-8L,
|
||||
-0.105952711258051954718238500312872328e-4L,
|
||||
0.678334290486516662273073740749269432e-5L,
|
||||
-0.210754766662588042469972680229376445e-5L,
|
||||
};
|
||||
workspace[8] = tools::evaluate_polynomial(C8, z);
|
||||
|
||||
static const T C9[] = {
|
||||
-0.000596761290192746250124390067179459605L,
|
||||
-0.720489541602001055908571930225015052e-4L,
|
||||
0.000678230883766732836161951166000673426L,
|
||||
-0.000640147526026275845100045652582354779L,
|
||||
0.000277501076343287044992374518205845463L,
|
||||
0.181970083804651510461686554030325202e-6L,
|
||||
-0.847950711706850318239732559632810086e-4L,
|
||||
0.610519208250153101764709122740859458e-4L,
|
||||
-0.210739201834048624082975255893773306e-4L,
|
||||
};
|
||||
workspace[9] = tools::evaluate_polynomial(C9, z);
|
||||
|
||||
static const T C10[] = {
|
||||
0.00133244544948006563712694993432717968L,
|
||||
-0.00191443849856547752650089885832852254L,
|
||||
0.0011089369134596637339607446329267522L,
|
||||
0.993240412264229896742295262075817566e-6L,
|
||||
-0.000508745012930931989848393025305956774L,
|
||||
0.00042735056665392884328432271160040444L,
|
||||
-0.000168588537679107988033552814662382059L,
|
||||
};
|
||||
workspace[10] = tools::evaluate_polynomial(C10, z);
|
||||
|
||||
static const T C11[] = {
|
||||
0.00157972766073083495908785631307733022L,
|
||||
0.000162516262783915816898635123980270998L,
|
||||
-0.00206334210355432762645284467690276817L,
|
||||
0.00213896861856890981541061922797693947L,
|
||||
-0.00101085593912630031708085801712479376L,
|
||||
};
|
||||
workspace[11] = tools::evaluate_polynomial(C11, z);
|
||||
|
||||
static const T C12[] = {
|
||||
-0.00407251211951401664727281097914544601L,
|
||||
0.00640336283380806979482363809026579583L,
|
||||
-0.00404101610816766177473974858518094879L,
|
||||
};
|
||||
workspace[12] = tools::evaluate_polynomial(C12, z);
|
||||
workspace[13] = -0.0059475779383993002845382844736066323L;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
} // namespace detail
|
||||
} // namespace math
|
||||
} // namespace math
|
||||
|
||||
|
||||
#endif // BOOST_MATH_DETAIL_IGAMMA_LARGE
|
||||
|
||||
201
test/external/boost/math/special_functions/detail/lanczos_sse2.hpp
vendored
Normal file
201
test/external/boost/math/special_functions/detail/lanczos_sse2.hpp
vendored
Normal file
@@ -0,0 +1,201 @@
|
||||
// (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)
|
||||
#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)
|
||||
};
|
||||
register __m128d vx = _mm_load1_pd(&x);
|
||||
register __m128d sum_even = _mm_load_pd(coeff);
|
||||
register __m128d sum_odd = _mm_load_pd(coeff+2);
|
||||
register __m128d nc_odd, nc_even;
|
||||
register __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)
|
||||
};
|
||||
register __m128d vx = _mm_load1_pd(&x);
|
||||
register __m128d sum_even = _mm_load_pd(coeff);
|
||||
register __m128d sum_odd = _mm_load_pd(coeff+2);
|
||||
register __m128d nc_odd, nc_even;
|
||||
register __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];
|
||||
}
|
||||
|
||||
} // namespace lanczos
|
||||
} // namespace math
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_MATH_SPECIAL_FUNCTIONS_LANCZOS
|
||||
|
||||
|
||||
|
||||
|
||||
512
test/external/boost/math/special_functions/detail/lgamma_small.hpp
vendored
Normal file
512
test/external/boost/math/special_functions/detail/lgamma_small.hpp
vendored
Normal file
@@ -0,0 +1,512 @@
|
||||
// (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
|
||||
|
||||
namespace boost{ namespace math{ namespace detail{
|
||||
|
||||
//
|
||||
// lgamma for small arguments:
|
||||
//
|
||||
template <class T, class Policy, class L>
|
||||
T lgamma_small_imp(T z, T zm1, T zm2, const mpl::int_<64>&, const Policy& /* l */, const L&)
|
||||
{
|
||||
// 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.
|
||||
// L 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>(-0.180355685678449379109e-1L),
|
||||
static_cast<T>(0.25126649619989678683e-1L),
|
||||
static_cast<T>(0.494103151567532234274e-1L),
|
||||
static_cast<T>(0.172491608709613993966e-1L),
|
||||
static_cast<T>(-0.259453563205438108893e-3L),
|
||||
static_cast<T>(-0.541009869215204396339e-3L),
|
||||
static_cast<T>(-0.324588649825948492091e-4L)
|
||||
};
|
||||
static const T Q[] = {
|
||||
static_cast<T>(0.1e1),
|
||||
static_cast<T>(0.196202987197795200688e1L),
|
||||
static_cast<T>(0.148019669424231326694e1L),
|
||||
static_cast<T>(0.541391432071720958364e0L),
|
||||
static_cast<T>(0.988504251128010129477e-1L),
|
||||
static_cast<T>(0.82130967464889339326e-2L),
|
||||
static_cast<T>(0.224936291922115757597e-3L),
|
||||
static_cast<T>(-0.223352763208617092964e-6L)
|
||||
};
|
||||
|
||||
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>(0.490622454069039543534e-1L),
|
||||
static_cast<T>(-0.969117530159521214579e-1L),
|
||||
static_cast<T>(-0.414983358359495381969e0L),
|
||||
static_cast<T>(-0.406567124211938417342e0L),
|
||||
static_cast<T>(-0.158413586390692192217e0L),
|
||||
static_cast<T>(-0.240149820648571559892e-1L),
|
||||
static_cast<T>(-0.100346687696279557415e-2L)
|
||||
};
|
||||
static const T Q[] = {
|
||||
static_cast<T>(0.1e1L),
|
||||
static_cast<T>(0.302349829846463038743e1L),
|
||||
static_cast<T>(0.348739585360723852576e1L),
|
||||
static_cast<T>(0.191415588274426679201e1L),
|
||||
static_cast<T>(0.507137738614363510846e0L),
|
||||
static_cast<T>(0.577039722690451849648e-1L),
|
||||
static_cast<T>(0.195768102601107189171e-2L)
|
||||
};
|
||||
|
||||
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>(-0.292329721830270012337e-1L),
|
||||
static_cast<T>(0.144216267757192309184e0L),
|
||||
static_cast<T>(-0.142440390738631274135e0L),
|
||||
static_cast<T>(0.542809694055053558157e-1L),
|
||||
static_cast<T>(-0.850535976868336437746e-2L),
|
||||
static_cast<T>(0.431171342679297331241e-3L)
|
||||
};
|
||||
static const T Q[] = {
|
||||
static_cast<T>(0.1e1),
|
||||
static_cast<T>(-0.150169356054485044494e1L),
|
||||
static_cast<T>(0.846973248876495016101e0L),
|
||||
static_cast<T>(-0.220095151814995745555e0L),
|
||||
static_cast<T>(0.25582797155975869989e-1L),
|
||||
static_cast<T>(-0.100666795539143372762e-2L),
|
||||
static_cast<T>(-0.827193521891290553639e-6L)
|
||||
};
|
||||
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 L>
|
||||
T lgamma_small_imp(T z, T zm1, T zm2, const mpl::int_<113>&, const Policy& /* l */, const L&)
|
||||
{
|
||||
//
|
||||
// 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[] = {
|
||||
-0.018035568567844937910504030027467476655L,
|
||||
0.013841458273109517271750705401202404195L,
|
||||
0.062031842739486600078866923383017722399L,
|
||||
0.052518418329052161202007865149435256093L,
|
||||
0.01881718142472784129191838493267755758L,
|
||||
0.0025104830367021839316463675028524702846L,
|
||||
-0.00021043176101831873281848891452678568311L,
|
||||
-0.00010249622350908722793327719494037981166L,
|
||||
-0.11381479670982006841716879074288176994e-4L,
|
||||
-0.49999811718089980992888533630523892389e-6L,
|
||||
-0.70529798686542184668416911331718963364e-8L
|
||||
};
|
||||
static const T Q[] = {
|
||||
1L,
|
||||
2.5877485070422317542808137697939233685L,
|
||||
2.8797959228352591788629602533153837126L,
|
||||
1.8030885955284082026405495275461180977L,
|
||||
0.69774331297747390169238306148355428436L,
|
||||
0.17261566063277623942044077039756583802L,
|
||||
0.02729301254544230229429621192443000121L,
|
||||
0.0026776425891195270663133581960016620433L,
|
||||
0.00015244249160486584591370355730402168106L,
|
||||
0.43997034032479866020546814475414346627e-5L,
|
||||
0.46295080708455613044541885534408170934e-7L,
|
||||
-0.93326638207459533682980757982834180952e-11L,
|
||||
0.42316456553164995177177407325292867513e-13L
|
||||
};
|
||||
|
||||
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[] = {
|
||||
0.036454670944013329356512090082402429697L,
|
||||
-0.066235835556476033710068679907798799959L,
|
||||
-0.67492399795577182387312206593595565371L,
|
||||
-1.4345555263962411429855341651960000166L,
|
||||
-1.4894319559821365820516771951249649563L,
|
||||
-0.87210277668067964629483299712322411566L,
|
||||
-0.29602090537771744401524080430529369136L,
|
||||
-0.0561832587517836908929331992218879676L,
|
||||
-0.0053236785487328044334381502530383140443L,
|
||||
-0.00018629360291358130461736386077971890789L,
|
||||
-0.10164985672213178500790406939467614498e-6L,
|
||||
0.13680157145361387405588201461036338274e-8L
|
||||
};
|
||||
static const T Q[] = {
|
||||
1,
|
||||
4.9106336261005990534095838574132225599L,
|
||||
10.258804800866438510889341082793078432L,
|
||||
11.88588976846826108836629960537466889L,
|
||||
8.3455000546999704314454891036700998428L,
|
||||
3.6428823682421746343233362007194282703L,
|
||||
0.97465989807254572142266753052776132252L,
|
||||
0.15121052897097822172763084966793352524L,
|
||||
0.012017363555383555123769849654484594893L,
|
||||
0.0003583032812720649835431669893011257277L
|
||||
};
|
||||
|
||||
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[] = {
|
||||
-0.017977422421608624353488126610933005432L,
|
||||
0.18484528905298309555089509029244135703L,
|
||||
-0.40401251514859546989565001431430884082L,
|
||||
0.40277179799147356461954182877921388182L,
|
||||
-0.21993421441282936476709677700477598816L,
|
||||
0.069595742223850248095697771331107571011L,
|
||||
-0.012681481427699686635516772923547347328L,
|
||||
0.0012489322866834830413292771335113136034L,
|
||||
-0.57058739515423112045108068834668269608e-4L,
|
||||
0.8207548771933585614380644961342925976e-6L
|
||||
};
|
||||
static const T Q[] = {
|
||||
1,
|
||||
-2.9629552288944259229543137757200262073L,
|
||||
3.7118380799042118987185957298964772755L,
|
||||
-2.5569815272165399297600586376727357187L,
|
||||
1.0546764918220835097855665680632153367L,
|
||||
-0.26574021300894401276478730940980810831L,
|
||||
0.03996289731752081380552901986471233462L,
|
||||
-0.0033398680924544836817826046380586480873L,
|
||||
0.00013288854760548251757651556792598235735L,
|
||||
-0.17194794958274081373243161848194745111e-5L
|
||||
};
|
||||
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[] = {
|
||||
-0.021027558364667626231512090082402429494L,
|
||||
0.15128811104498736604523586803722368377L,
|
||||
-0.26249631480066246699388544451126410278L,
|
||||
0.21148748610533489823742352180628489742L,
|
||||
-0.093964130697489071999873506148104370633L,
|
||||
0.024292059227009051652542804957550866827L,
|
||||
-0.0036284453226534839926304745756906117066L,
|
||||
0.0002939230129315195346843036254392485984L,
|
||||
-0.11088589183158123733132268042570710338e-4L,
|
||||
0.13240510580220763969511741896361984162e-6L
|
||||
};
|
||||
static const T Q[] = {
|
||||
1,
|
||||
-2.4240003754444040525462170802796471996L,
|
||||
2.4868383476933178722203278602342786002L,
|
||||
-1.4047068395206343375520721509193698547L,
|
||||
0.47583809087867443858344765659065773369L,
|
||||
-0.09865724264554556400463655444270700132L,
|
||||
0.012238223514176587501074150988445109735L,
|
||||
-0.00084625068418239194670614419707491797097L,
|
||||
0.2796574430456237061420839429225710602e-4L,
|
||||
-0.30202973883316730694433702165188835331e-6L
|
||||
};
|
||||
// (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 L>
|
||||
T lgamma_small_imp(T z, T zm1, T zm2, const mpl::int_<0>&, const Policy& pol, const L&)
|
||||
{
|
||||
//
|
||||
// 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, L()));
|
||||
}
|
||||
else if(z >= 3)
|
||||
{
|
||||
// taking the log of tgamma reduces the error, no danger of overflow here:
|
||||
result = log(gamma_imp(z, pol, L()));
|
||||
}
|
||||
else if(z >= 1.5)
|
||||
{
|
||||
// special case near 2:
|
||||
T dz = zm2;
|
||||
result = dz * log((z + L::g() - T(0.5)) / boost::math::constants::e<T>());
|
||||
result += boost::math::log1p(dz / (L::g() + T(1.5)), pol) * T(1.5);
|
||||
result += boost::math::log1p(L::lanczos_sum_near_2(dz), pol);
|
||||
}
|
||||
else
|
||||
{
|
||||
// special case near 1:
|
||||
T dz = zm1;
|
||||
result = dz * log((z + L::g() - T(0.5)) / boost::math::constants::e<T>());
|
||||
result += boost::math::log1p(dz / (L::g() + T(0.5)), pol) / 2;
|
||||
result += boost::math::log1p(L::lanczos_sum_near_1(dz), pol);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_SPECIAL_FUNCTIONS_DETAIL_LGAMMA_SMALL
|
||||
|
||||
80
test/external/boost/math/special_functions/detail/round_fwd.hpp
vendored
Normal file
80
test/external/boost/math/special_functions/detail/round_fwd.hpp
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
// 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>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace math
|
||||
{
|
||||
|
||||
template <class T, class Policy>
|
||||
T trunc(const T& v, const Policy& pol);
|
||||
template <class T>
|
||||
T 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>
|
||||
T round(const T& v, const Policy& pol);
|
||||
template <class T>
|
||||
T 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
|
||||
|
||||
}
|
||||
}
|
||||
#endif // BOOST_MATH_SPECIAL_ROUND_FWD_HPP
|
||||
|
||||
544
test/external/boost/math/special_functions/detail/t_distribution_inv.hpp
vendored
Normal file
544
test/external/boost/math/special_functions/detail/t_distribution_inv.hpp
vendored
Normal file
@@ -0,0 +1,544 @@
|
||||
// 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 = ((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] = 0.16666666666666666667 + 0.16666666666666666667 * in;
|
||||
c[3] = (0.0083333333333333333333 * in
|
||||
+ 0.066666666666666666667) * in
|
||||
+ 0.058333333333333333333;
|
||||
c[4] = ((0.00019841269841269841270 * in
|
||||
+ 0.0017857142857142857143) * in
|
||||
+ 0.026785714285714285714) * in
|
||||
+ 0.025198412698412698413;
|
||||
c[5] = (((2.7557319223985890653e-6 * in
|
||||
+ 0.00037477954144620811287) * in
|
||||
- 0.0011078042328042328042) * in
|
||||
+ 0.010559964726631393298) * in
|
||||
+ 0.012039792768959435626;
|
||||
c[6] = ((((2.5052108385441718775e-8 * in
|
||||
- 0.000062705427288760622094) * in
|
||||
+ 0.00059458674042007375341) * in
|
||||
- 0.0016095979637646304313) * in
|
||||
+ 0.0061039211560044893378) * in
|
||||
+ 0.0038370059724226390893;
|
||||
c[7] = (((((1.6059043836821614599e-10 * in
|
||||
+ 0.000015401265401265401265) * in
|
||||
- 0.00016376804137220803887) * in
|
||||
+ 0.00069084207973096861986) * in
|
||||
- 0.0012579159844784844785) * in
|
||||
+ 0.0010898206731540064873) * in
|
||||
+ 0.0032177478835464946576;
|
||||
c[8] = ((((((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] = (((((((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] = ((((((((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 = 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 < 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), pol));
|
||||
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 > q) ? T(0.5f - q) / T(2) : T(p / 2);
|
||||
T v = 1 - u; // u < 0.5 so no cancellation error
|
||||
T df = a * 2;
|
||||
T t = boost::math::detail::inverse_students_t(df, u, v, pol);
|
||||
T x = df / (df + t * t);
|
||||
*py = t * t / (df + t * t);
|
||||
return x;
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
|
||||
|
||||
415
test/external/boost/math/special_functions/detail/unchecked_factorial.hpp
vendored
Normal file
415
test/external/boost/math/special_functions/detail/unchecked_factorial.hpp
vendored
Normal file
@@ -0,0 +1,415 @@
|
||||
// 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
|
||||
|
||||
#include <boost/array.hpp>
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(push) // Temporary until lexical cast fixed.
|
||||
#pragma warning(disable: 4127 4701)
|
||||
#endif
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
#include <boost/config/no_tr1/cmath.hpp>
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
|
||||
namespace boost { namespace math
|
||||
{
|
||||
// Forward declarations:
|
||||
template <class T>
|
||||
struct max_factorial;
|
||||
|
||||
// Definitions:
|
||||
template <>
|
||||
inline float unchecked_factorial<float>(unsigned i BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(float))
|
||||
{
|
||||
static const boost::array<float, 35> factorials = {{
|
||||
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 long double unchecked_factorial<long double>(unsigned i BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(long double))
|
||||
{
|
||||
static const boost::array<long double, 171> factorials = {{
|
||||
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);
|
||||
};
|
||||
|
||||
template <>
|
||||
inline 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);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
inline T unchecked_factorial(unsigned i BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(T))
|
||||
{
|
||||
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.
|
||||
|
||||
static const boost::array<T, 101> factorials = {{
|
||||
boost::lexical_cast<T>("1"),
|
||||
boost::lexical_cast<T>("1"),
|
||||
boost::lexical_cast<T>("2"),
|
||||
boost::lexical_cast<T>("6"),
|
||||
boost::lexical_cast<T>("24"),
|
||||
boost::lexical_cast<T>("120"),
|
||||
boost::lexical_cast<T>("720"),
|
||||
boost::lexical_cast<T>("5040"),
|
||||
boost::lexical_cast<T>("40320"),
|
||||
boost::lexical_cast<T>("362880"),
|
||||
boost::lexical_cast<T>("3628800"),
|
||||
boost::lexical_cast<T>("39916800"),
|
||||
boost::lexical_cast<T>("479001600"),
|
||||
boost::lexical_cast<T>("6227020800"),
|
||||
boost::lexical_cast<T>("87178291200"),
|
||||
boost::lexical_cast<T>("1307674368000"),
|
||||
boost::lexical_cast<T>("20922789888000"),
|
||||
boost::lexical_cast<T>("355687428096000"),
|
||||
boost::lexical_cast<T>("6402373705728000"),
|
||||
boost::lexical_cast<T>("121645100408832000"),
|
||||
boost::lexical_cast<T>("2432902008176640000"),
|
||||
boost::lexical_cast<T>("51090942171709440000"),
|
||||
boost::lexical_cast<T>("1124000727777607680000"),
|
||||
boost::lexical_cast<T>("25852016738884976640000"),
|
||||
boost::lexical_cast<T>("620448401733239439360000"),
|
||||
boost::lexical_cast<T>("15511210043330985984000000"),
|
||||
boost::lexical_cast<T>("403291461126605635584000000"),
|
||||
boost::lexical_cast<T>("10888869450418352160768000000"),
|
||||
boost::lexical_cast<T>("304888344611713860501504000000"),
|
||||
boost::lexical_cast<T>("8841761993739701954543616000000"),
|
||||
boost::lexical_cast<T>("265252859812191058636308480000000"),
|
||||
boost::lexical_cast<T>("8222838654177922817725562880000000"),
|
||||
boost::lexical_cast<T>("263130836933693530167218012160000000"),
|
||||
boost::lexical_cast<T>("8683317618811886495518194401280000000"),
|
||||
boost::lexical_cast<T>("295232799039604140847618609643520000000"),
|
||||
boost::lexical_cast<T>("10333147966386144929666651337523200000000"),
|
||||
boost::lexical_cast<T>("371993326789901217467999448150835200000000"),
|
||||
boost::lexical_cast<T>("13763753091226345046315979581580902400000000"),
|
||||
boost::lexical_cast<T>("523022617466601111760007224100074291200000000"),
|
||||
boost::lexical_cast<T>("20397882081197443358640281739902897356800000000"),
|
||||
boost::lexical_cast<T>("815915283247897734345611269596115894272000000000"),
|
||||
boost::lexical_cast<T>("33452526613163807108170062053440751665152000000000"),
|
||||
boost::lexical_cast<T>("1405006117752879898543142606244511569936384000000000"),
|
||||
boost::lexical_cast<T>("60415263063373835637355132068513997507264512000000000"),
|
||||
boost::lexical_cast<T>("2658271574788448768043625811014615890319638528000000000"),
|
||||
boost::lexical_cast<T>("119622220865480194561963161495657715064383733760000000000"),
|
||||
boost::lexical_cast<T>("5502622159812088949850305428800254892961651752960000000000"),
|
||||
boost::lexical_cast<T>("258623241511168180642964355153611979969197632389120000000000"),
|
||||
boost::lexical_cast<T>("12413915592536072670862289047373375038521486354677760000000000"),
|
||||
boost::lexical_cast<T>("608281864034267560872252163321295376887552831379210240000000000"),
|
||||
boost::lexical_cast<T>("30414093201713378043612608166064768844377641568960512000000000000"),
|
||||
boost::lexical_cast<T>("1551118753287382280224243016469303211063259720016986112000000000000"),
|
||||
boost::lexical_cast<T>("80658175170943878571660636856403766975289505440883277824000000000000"),
|
||||
boost::lexical_cast<T>("4274883284060025564298013753389399649690343788366813724672000000000000"),
|
||||
boost::lexical_cast<T>("230843697339241380472092742683027581083278564571807941132288000000000000"),
|
||||
boost::lexical_cast<T>("12696403353658275925965100847566516959580321051449436762275840000000000000"),
|
||||
boost::lexical_cast<T>("710998587804863451854045647463724949736497978881168458687447040000000000000"),
|
||||
boost::lexical_cast<T>("40526919504877216755680601905432322134980384796226602145184481280000000000000"),
|
||||
boost::lexical_cast<T>("2350561331282878571829474910515074683828862318181142924420699914240000000000000"),
|
||||
boost::lexical_cast<T>("138683118545689835737939019720389406345902876772687432540821294940160000000000000"),
|
||||
boost::lexical_cast<T>("8320987112741390144276341183223364380754172606361245952449277696409600000000000000"),
|
||||
boost::lexical_cast<T>("507580213877224798800856812176625227226004528988036003099405939480985600000000000000"),
|
||||
boost::lexical_cast<T>("31469973260387937525653122354950764088012280797258232192163168247821107200000000000000"),
|
||||
boost::lexical_cast<T>("1982608315404440064116146708361898137544773690227268628106279599612729753600000000000000"),
|
||||
boost::lexical_cast<T>("126886932185884164103433389335161480802865516174545192198801894375214704230400000000000000"),
|
||||
boost::lexical_cast<T>("8247650592082470666723170306785496252186258551345437492922123134388955774976000000000000000"),
|
||||
boost::lexical_cast<T>("544344939077443064003729240247842752644293064388798874532860126869671081148416000000000000000"),
|
||||
boost::lexical_cast<T>("36471110918188685288249859096605464427167635314049524593701628500267962436943872000000000000000"),
|
||||
boost::lexical_cast<T>("2480035542436830599600990418569171581047399201355367672371710738018221445712183296000000000000000"),
|
||||
boost::lexical_cast<T>("171122452428141311372468338881272839092270544893520369393648040923257279754140647424000000000000000"),
|
||||
boost::lexical_cast<T>("11978571669969891796072783721689098736458938142546425857555362864628009582789845319680000000000000000"),
|
||||
boost::lexical_cast<T>("850478588567862317521167644239926010288584608120796235886430763388588680378079017697280000000000000000"),
|
||||
boost::lexical_cast<T>("61234458376886086861524070385274672740778091784697328983823014963978384987221689274204160000000000000000"),
|
||||
boost::lexical_cast<T>("4470115461512684340891257138125051110076800700282905015819080092370422104067183317016903680000000000000000"),
|
||||
boost::lexical_cast<T>("330788544151938641225953028221253782145683251820934971170611926835411235700971565459250872320000000000000000"),
|
||||
boost::lexical_cast<T>("24809140811395398091946477116594033660926243886570122837795894512655842677572867409443815424000000000000000000"),
|
||||
boost::lexical_cast<T>("1885494701666050254987932260861146558230394535379329335672487982961844043495537923117729972224000000000000000000"),
|
||||
boost::lexical_cast<T>("145183092028285869634070784086308284983740379224208358846781574688061991349156420080065207861248000000000000000000"),
|
||||
boost::lexical_cast<T>("11324281178206297831457521158732046228731749579488251990048962825668835325234200766245086213177344000000000000000000"),
|
||||
boost::lexical_cast<T>("894618213078297528685144171539831652069808216779571907213868063227837990693501860533361810841010176000000000000000000"),
|
||||
boost::lexical_cast<T>("71569457046263802294811533723186532165584657342365752577109445058227039255480148842668944867280814080000000000000000000"),
|
||||
boost::lexical_cast<T>("5797126020747367985879734231578109105412357244731625958745865049716390179693892056256184534249745940480000000000000000000"),
|
||||
boost::lexical_cast<T>("475364333701284174842138206989404946643813294067993328617160934076743994734899148613007131808479167119360000000000000000000"),
|
||||
boost::lexical_cast<T>("39455239697206586511897471180120610571436503407643446275224357528369751562996629334879591940103770870906880000000000000000000"),
|
||||
boost::lexical_cast<T>("3314240134565353266999387579130131288000666286242049487118846032383059131291716864129885722968716753156177920000000000000000000"),
|
||||
boost::lexical_cast<T>("281710411438055027694947944226061159480056634330574206405101912752560026159795933451040286452340924018275123200000000000000000000"),
|
||||
boost::lexical_cast<T>("24227095383672732381765523203441259715284870552429381750838764496720162249742450276789464634901319465571660595200000000000000000000"),
|
||||
boost::lexical_cast<T>("2107757298379527717213600518699389595229783738061356212322972511214654115727593174080683423236414793504734471782400000000000000000000"),
|
||||
boost::lexical_cast<T>("185482642257398439114796845645546284380220968949399346684421580986889562184028199319100141244804501828416633516851200000000000000000000"),
|
||||
boost::lexical_cast<T>("16507955160908461081216919262453619309839666236496541854913520707833171034378509739399912570787600662729080382999756800000000000000000000"),
|
||||
boost::lexical_cast<T>("1485715964481761497309522733620825737885569961284688766942216863704985393094065876545992131370884059645617234469978112000000000000000000000"),
|
||||
boost::lexical_cast<T>("135200152767840296255166568759495142147586866476906677791741734597153670771559994765685283954750449427751168336768008192000000000000000000000"),
|
||||
boost::lexical_cast<T>("12438414054641307255475324325873553077577991715875414356840239582938137710983519518443046123837041347353107486982656753664000000000000000000000"),
|
||||
boost::lexical_cast<T>("1156772507081641574759205162306240436214753229576413535186142281213246807121467315215203289516844845303838996289387078090752000000000000000000000"),
|
||||
boost::lexical_cast<T>("108736615665674308027365285256786601004186803580182872307497374434045199869417927630229109214583415458560865651202385340530688000000000000000000000"),
|
||||
boost::lexical_cast<T>("10329978488239059262599702099394727095397746340117372869212250571234293987594703124871765375385424468563282236864226607350415360000000000000000000000"),
|
||||
boost::lexical_cast<T>("991677934870949689209571401541893801158183648651267795444376054838492222809091499987689476037000748982075094738965754305639874560000000000000000000000"),
|
||||
boost::lexical_cast<T>("96192759682482119853328425949563698712343813919172976158104477319333745612481875498805879175589072651261284189679678167647067832320000000000000000000000"),
|
||||
boost::lexical_cast<T>("9426890448883247745626185743057242473809693764078951663494238777294707070023223798882976159207729119823605850588608460429412647567360000000000000000000000"),
|
||||
boost::lexical_cast<T>("933262154439441526816992388562667004907159682643816214685929638952175999932299156089414639761565182862536979208272237582511852109168640000000000000000000000"),
|
||||
boost::lexical_cast<T>("93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000"),
|
||||
}};
|
||||
|
||||
return factorials[i];
|
||||
}
|
||||
|
||||
template <class T>
|
||||
struct max_factorial
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(unsigned, value = 100);
|
||||
};
|
||||
|
||||
#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