Initial commit
This commit is contained in:
2
code_isotrope/README
Executable file
2
code_isotrope/README
Executable file
@@ -0,0 +1,2 @@
|
||||
Pour l'affichage python nécessite la librairie "matplotlib", pour l'installer : "sudo apt install pip-python ; pip install matplotlib" (pip se chargera des dépendances)
|
||||
Pour compiler et exécuter le programme taper la commande "make"
|
||||
89
code_isotrope/affichage_iso.py
Executable file
89
code_isotrope/affichage_iso.py
Executable file
@@ -0,0 +1,89 @@
|
||||
#!/usr/bin/python
|
||||
#-*- coding:utf-8 -*-
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
|
||||
A=np.loadtxt("data_iso.res")
|
||||
|
||||
xdata_v = A[:,0]
|
||||
xdata_l = 3e8/xdata_v
|
||||
ydata_vi = A[:,1]
|
||||
ydata_li = ydata_vi*3e8/(xdata_l**2)
|
||||
ydata_vp = A[:,2]
|
||||
ydata_lp = ydata_vp*3e8/(xdata_l**2)
|
||||
|
||||
fig,ax = plt.subplots(3,2,sharex='col',gridspec_kw={'height_ratios':[3,3,0.20]},figsize=(18,9))
|
||||
plt.subplots_adjust(left=0.06,bottom=0.07,right=0.98,top=0.9,wspace=0.2,hspace=0.3)
|
||||
|
||||
ax[0,0].plot(xdata_l,ydata_li,label="for B = 10^-4 T,\n gamma = 10^4,\n pitch = 45deg.")
|
||||
ax[0,0].set_xscale('log')
|
||||
ax[0,0].set_xlabel(r"$\lambda$ ($m$)")
|
||||
ax[0,0].set_yscale('log')
|
||||
ax[0,0].set_xlim(3e-9,3e-1)
|
||||
ax[0,0].set_ylabel(r"Emissivity ($W \cdot m^{-1}$)")
|
||||
#ax[0,0].legend()
|
||||
ax[0,0].set_title("Emissivity for one particle")
|
||||
|
||||
ax[0,1].plot(xdata_v,ydata_vi)
|
||||
ax[0,1].set_xscale('log')
|
||||
ax[0,1].set_yscale('log')
|
||||
ax[0,1].set_xlim(1e9,1e17)
|
||||
#ax[0,1].set_ylim(1e-8,1)
|
||||
ax[0,1].set_xlabel(r"$\nu$ ($Hz$)")
|
||||
ax[0,1].set_ylabel(r"Emissivity ($W \cdot Hz^{-1}$)")
|
||||
#ax[0,1].legend()
|
||||
ax[0,1].set_title("Emissivity for one particle")
|
||||
|
||||
ax[1,0].plot(xdata_l,ydata_lp)
|
||||
ax[1,0].set_xlabel(r"$\lambda$ ($m$)")
|
||||
ax[1,0].set_xscale('log')
|
||||
ax[1,0].set_yscale('log')
|
||||
ax[1,0].set_ylabel(r"Emissivity ($W \cdot m^{-1}$)")
|
||||
#ax[1,0].legend()
|
||||
ax[1,0].set_title("Emissivity for a population of particles")
|
||||
|
||||
ax[1,1].plot(xdata_v,ydata_vp)
|
||||
ax[1,1].set_xscale('log')
|
||||
ax[1,1].set_yscale('log')
|
||||
#ax[1,1].set_ylim(1e9,1e17)
|
||||
#ax[1,1].set_xlim(1e-2,1e2)
|
||||
ax[1,1].set_xlabel(r"$\nu$ ($Hz$)")
|
||||
ax[1,1].set_ylabel(r"Emissivity ($W \cdot Hz^{-1}$)")
|
||||
#ax[1,1].legend()
|
||||
ax[1,1].set_title("Emissivity for a population of particles")
|
||||
|
||||
def annotation_line(ax, xmin, xmax, y, text, ytext=0, linecolor='black', linewidth=1, fontsize=8):
|
||||
ax.annotate('', xy=(xmin, y), xytext=(xmax, y), xycoords='data', textcoords='data',arrowprops={'arrowstyle': '|-|', 'color':linecolor, 'linewidth':linewidth})
|
||||
xcenter = np.log10(xmin)+(np.log10(xmax)-np.log10(xmin))/2
|
||||
if ytext==0:
|
||||
ytext = y+(ax.get_ylim()[1]-ax.get_ylim()[0])/5
|
||||
ax.annotate( text, xy=(pow(10,xcenter),ytext), ha='center', va='center', fontsize=fontsize )
|
||||
|
||||
ax[2][1].set_ylim(-1,2)
|
||||
ax[2][1].tick_params(labelleft=False,left=False)
|
||||
#annotation_line(ax[2][1],1e7,3e8,0,"Radio Waves")
|
||||
annotation_line(ax[2][1],1e9,3e11,0,"Microwaves")
|
||||
annotation_line(ax[2][1],3e11,4e14,0,"IR")
|
||||
annotation_line(ax[2][1],4e14,7.5e14,0,"Visible")
|
||||
annotation_line(ax[2][1],7.5e14,2e16,0,"UV")
|
||||
annotation_line(ax[2][1],2e16,1e17,0,"X Rays")
|
||||
#annotation_line(ax[2][1],2e19,1e23,0,"Gamma Rays")
|
||||
ax[2,1].set_xlabel(r"$\nu$ ($Hz$)")
|
||||
|
||||
ax[2][0].set_ylim(-1,2)
|
||||
ax[2][0].tick_params(labelleft=False,left=False)
|
||||
#annotation_line(ax[2][0],1e0,1e3,0,"Radio Waves")
|
||||
annotation_line(ax[2][0],1e-3,3e-1,0,"Microwaves")
|
||||
annotation_line(ax[2][0],7.5e-7,1e-3,0,"IR")
|
||||
annotation_line(ax[2][0],4e-7,7.5e-7,0,"Visible")
|
||||
annotation_line(ax[2][0],8e-9,4e-7,0,"UV")
|
||||
annotation_line(ax[2][0],3e-9,8e-9,0,"X Rays")
|
||||
#annotation_line(ax[2][0],1e-12,1e-11,0,"Gamma Rays")
|
||||
ax[2,0].set_xlabel(r"$\lambda$ ($m$)")
|
||||
|
||||
fig.suptitle(r"Plots for an isotropic synchrotron radiation for $B = 10^{-4}T$, $p=2.0$, $\gamma = 10^{4}$, $\alpha_{p} = 45^{\circ}$.")
|
||||
|
||||
plt.savefig("isotropic_sed.png",bbox_inches='tight')
|
||||
|
||||
#plt.show()
|
||||
75
code_isotrope/boost/math/special_functions.hpp
Executable file
75
code_isotrope/boost/math/special_functions.hpp
Executable file
@@ -0,0 +1,75 @@
|
||||
// Copyright John Maddock 2006, 2007, 2012, 2014.
|
||||
// Copyright Paul A. Bristow 2006, 2007, 2012
|
||||
|
||||
// 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 includes *all* the special functions.
|
||||
// this may be useful if many are used
|
||||
// - to avoid including each function individually.
|
||||
|
||||
#ifndef BOOST_MATH_SPECIAL_FUNCTIONS_HPP
|
||||
#define BOOST_MATH_SPECIAL_FUNCTIONS_HPP
|
||||
|
||||
#include <boost/math/special_functions/airy.hpp>
|
||||
#include <boost/math/special_functions/acosh.hpp>
|
||||
#include <boost/math/special_functions/asinh.hpp>
|
||||
#include <boost/math/special_functions/atanh.hpp>
|
||||
#include <boost/math/special_functions/bernoulli.hpp>
|
||||
#include <boost/math/special_functions/bessel.hpp>
|
||||
#include <boost/math/special_functions/bessel_prime.hpp>
|
||||
#include <boost/math/special_functions/beta.hpp>
|
||||
#include <boost/math/special_functions/binomial.hpp>
|
||||
#include <boost/math/special_functions/cbrt.hpp>
|
||||
#include <boost/math/special_functions/cos_pi.hpp>
|
||||
#include <boost/math/special_functions/chebyshev.hpp>
|
||||
#include <boost/math/special_functions/digamma.hpp>
|
||||
#include <boost/math/special_functions/ellint_1.hpp>
|
||||
#include <boost/math/special_functions/ellint_2.hpp>
|
||||
#include <boost/math/special_functions/ellint_3.hpp>
|
||||
#include <boost/math/special_functions/ellint_d.hpp>
|
||||
#include <boost/math/special_functions/jacobi_zeta.hpp>
|
||||
#include <boost/math/special_functions/heuman_lambda.hpp>
|
||||
#include <boost/math/special_functions/ellint_rc.hpp>
|
||||
#include <boost/math/special_functions/ellint_rd.hpp>
|
||||
#include <boost/math/special_functions/ellint_rf.hpp>
|
||||
#include <boost/math/special_functions/ellint_rj.hpp>
|
||||
#include <boost/math/special_functions/ellint_rg.hpp>
|
||||
#include <boost/math/special_functions/erf.hpp>
|
||||
#include <boost/math/special_functions/expint.hpp>
|
||||
#include <boost/math/special_functions/expm1.hpp>
|
||||
#include <boost/math/special_functions/factorials.hpp>
|
||||
#include <boost/math/special_functions/fpclassify.hpp>
|
||||
#include <boost/math/special_functions/gamma.hpp>
|
||||
#include <boost/math/special_functions/hermite.hpp>
|
||||
#include <boost/math/special_functions/hypot.hpp>
|
||||
#include <boost/math/special_functions/jacobi_elliptic.hpp>
|
||||
#include <boost/math/special_functions/laguerre.hpp>
|
||||
#include <boost/math/special_functions/lanczos.hpp>
|
||||
#include <boost/math/special_functions/legendre.hpp>
|
||||
#include <boost/math/special_functions/log1p.hpp>
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/math/special_functions/next.hpp>
|
||||
#include <boost/math/special_functions/owens_t.hpp>
|
||||
#include <boost/math/special_functions/polygamma.hpp>
|
||||
#include <boost/math/special_functions/powm1.hpp>
|
||||
#include <boost/math/special_functions/sign.hpp>
|
||||
#include <boost/math/special_functions/sin_pi.hpp>
|
||||
#include <boost/math/special_functions/sinc.hpp>
|
||||
#include <boost/math/special_functions/sinhc.hpp>
|
||||
#include <boost/math/special_functions/spherical_harmonic.hpp>
|
||||
#include <boost/math/special_functions/sqrt1pm1.hpp>
|
||||
#include <boost/math/special_functions/zeta.hpp>
|
||||
#include <boost/math/special_functions/modf.hpp>
|
||||
#include <boost/math/special_functions/round.hpp>
|
||||
#include <boost/math/special_functions/trunc.hpp>
|
||||
#include <boost/math/special_functions/pow.hpp>
|
||||
#include <boost/math/special_functions/next.hpp>
|
||||
#include <boost/math/special_functions/owens_t.hpp>
|
||||
#include <boost/math/special_functions/hankel.hpp>
|
||||
#include <boost/math/special_functions/ulp.hpp>
|
||||
#include <boost/math/special_functions/relative_difference.hpp>
|
||||
#include <boost/math/special_functions/lambert_w.hpp>
|
||||
|
||||
#endif // BOOST_MATH_SPECIAL_FUNCTIONS_HPP
|
||||
104
code_isotrope/boost/math/special_functions/acosh.hpp
Executable file
104
code_isotrope/boost/math/special_functions/acosh.hpp
Executable file
@@ -0,0 +1,104 @@
|
||||
// boost asinh.hpp header file
|
||||
|
||||
// (C) Copyright Eric Ford 2001 & Hubert Holin.
|
||||
// (C) Copyright John Maddock 2008.
|
||||
// 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)
|
||||
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
#ifndef BOOST_ACOSH_HPP
|
||||
#define BOOST_ACOSH_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/config/no_tr1/cmath.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/math/tools/precision.hpp>
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/math/special_functions/log1p.hpp>
|
||||
#include <boost/math/constants/constants.hpp>
|
||||
|
||||
// This is the inverse of the hyperbolic cosine function.
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace math
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template<typename T, typename Policy>
|
||||
inline T acosh_imp(const T x, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
|
||||
if((x < 1) || (boost::math::isnan)(x))
|
||||
{
|
||||
return policies::raise_domain_error<T>(
|
||||
"boost::math::acosh<%1%>(%1%)",
|
||||
"acosh requires x >= 1, but got x = %1%.", x, pol);
|
||||
}
|
||||
else if ((x - 1) >= tools::root_epsilon<T>())
|
||||
{
|
||||
if (x > 1 / tools::root_epsilon<T>())
|
||||
{
|
||||
// http://functions.wolfram.com/ElementaryFunctions/ArcCosh/06/01/06/01/0001/
|
||||
// approximation by laurent series in 1/x at 0+ order from -1 to 0
|
||||
return log(x) + constants::ln_two<T>();
|
||||
}
|
||||
else if(x < 1.5f)
|
||||
{
|
||||
// This is just a rearrangement of the standard form below
|
||||
// devised to minimse loss of precision when x ~ 1:
|
||||
T y = x - 1;
|
||||
return boost::math::log1p(y + sqrt(y * y + 2 * y), pol);
|
||||
}
|
||||
else
|
||||
{
|
||||
// http://functions.wolfram.com/ElementaryFunctions/ArcCosh/02/
|
||||
return( log( x + sqrt(x * x - 1) ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// see http://functions.wolfram.com/ElementaryFunctions/ArcCosh/06/01/04/01/0001/
|
||||
T y = x - 1;
|
||||
|
||||
// approximation by taylor series in y at 0 up to order 2
|
||||
T result = sqrt(2 * y) * (1 - y /12 + 3 * y * y / 160);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, typename Policy>
|
||||
inline typename tools::promote_args<T>::type acosh(T x, const Policy&)
|
||||
{
|
||||
typedef typename tools::promote_args<T>::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;
|
||||
return policies::checked_narrowing_cast<result_type, forwarding_policy>(
|
||||
detail::acosh_imp(static_cast<value_type>(x), forwarding_policy()),
|
||||
"boost::math::acosh<%1%>(%1%)");
|
||||
}
|
||||
template<typename T>
|
||||
inline typename tools::promote_args<T>::type acosh(T x)
|
||||
{
|
||||
return boost::math::acosh(x, policies::policy<>());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* BOOST_ACOSH_HPP */
|
||||
|
||||
|
||||
469
code_isotrope/boost/math/special_functions/airy.hpp
Executable file
469
code_isotrope/boost/math/special_functions/airy.hpp
Executable file
@@ -0,0 +1,469 @@
|
||||
// Copyright John Maddock 2012.
|
||||
// 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_AIRY_HPP
|
||||
#define BOOST_MATH_AIRY_HPP
|
||||
|
||||
#include <limits>
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/math/special_functions/bessel.hpp>
|
||||
#include <boost/math/special_functions/cbrt.hpp>
|
||||
#include <boost/math/special_functions/detail/airy_ai_bi_zero.hpp>
|
||||
#include <boost/math/tools/roots.hpp>
|
||||
|
||||
namespace boost{ namespace math{
|
||||
|
||||
namespace detail{
|
||||
|
||||
template <class T, class Policy>
|
||||
T airy_ai_imp(T x, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
|
||||
if(x < 0)
|
||||
{
|
||||
T p = (-x * sqrt(-x) * 2) / 3;
|
||||
T v = T(1) / 3;
|
||||
T j1 = boost::math::cyl_bessel_j(v, p, pol);
|
||||
T j2 = boost::math::cyl_bessel_j(-v, p, pol);
|
||||
T ai = sqrt(-x) * (j1 + j2) / 3;
|
||||
//T bi = sqrt(-x / 3) * (j2 - j1);
|
||||
return ai;
|
||||
}
|
||||
else if(fabs(x * x * x) / 6 < tools::epsilon<T>())
|
||||
{
|
||||
T tg = boost::math::tgamma(constants::twothirds<T>(), pol);
|
||||
T ai = 1 / (pow(T(3), constants::twothirds<T>()) * tg);
|
||||
//T bi = 1 / (sqrt(boost::math::cbrt(T(3))) * tg);
|
||||
return ai;
|
||||
}
|
||||
else
|
||||
{
|
||||
T p = 2 * x * sqrt(x) / 3;
|
||||
T v = T(1) / 3;
|
||||
//T j1 = boost::math::cyl_bessel_i(-v, p, pol);
|
||||
//T j2 = boost::math::cyl_bessel_i(v, p, pol);
|
||||
//
|
||||
// Note that although we can calculate ai from j1 and j2, the accuracy is horrible
|
||||
// as we're subtracting two very large values, so use the Bessel K relation instead:
|
||||
//
|
||||
T ai = cyl_bessel_k(v, p, pol) * sqrt(x / 3) / boost::math::constants::pi<T>(); //sqrt(x) * (j1 - j2) / 3;
|
||||
//T bi = sqrt(x / 3) * (j1 + j2);
|
||||
return ai;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
T airy_bi_imp(T x, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
|
||||
if(x < 0)
|
||||
{
|
||||
T p = (-x * sqrt(-x) * 2) / 3;
|
||||
T v = T(1) / 3;
|
||||
T j1 = boost::math::cyl_bessel_j(v, p, pol);
|
||||
T j2 = boost::math::cyl_bessel_j(-v, p, pol);
|
||||
//T ai = sqrt(-x) * (j1 + j2) / 3;
|
||||
T bi = sqrt(-x / 3) * (j2 - j1);
|
||||
return bi;
|
||||
}
|
||||
else if(fabs(x * x * x) / 6 < tools::epsilon<T>())
|
||||
{
|
||||
T tg = boost::math::tgamma(constants::twothirds<T>(), pol);
|
||||
//T ai = 1 / (pow(T(3), constants::twothirds<T>()) * tg);
|
||||
T bi = 1 / (sqrt(boost::math::cbrt(T(3))) * tg);
|
||||
return bi;
|
||||
}
|
||||
else
|
||||
{
|
||||
T p = 2 * x * sqrt(x) / 3;
|
||||
T v = T(1) / 3;
|
||||
T j1 = boost::math::cyl_bessel_i(-v, p, pol);
|
||||
T j2 = boost::math::cyl_bessel_i(v, p, pol);
|
||||
T bi = sqrt(x / 3) * (j1 + j2);
|
||||
return bi;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
T airy_ai_prime_imp(T x, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
|
||||
if(x < 0)
|
||||
{
|
||||
T p = (-x * sqrt(-x) * 2) / 3;
|
||||
T v = T(2) / 3;
|
||||
T j1 = boost::math::cyl_bessel_j(v, p, pol);
|
||||
T j2 = boost::math::cyl_bessel_j(-v, p, pol);
|
||||
T aip = -x * (j1 - j2) / 3;
|
||||
return aip;
|
||||
}
|
||||
else if(fabs(x * x) / 2 < tools::epsilon<T>())
|
||||
{
|
||||
T tg = boost::math::tgamma(constants::third<T>(), pol);
|
||||
T aip = 1 / (boost::math::cbrt(T(3)) * tg);
|
||||
return -aip;
|
||||
}
|
||||
else
|
||||
{
|
||||
T p = 2 * x * sqrt(x) / 3;
|
||||
T v = T(2) / 3;
|
||||
//T j1 = boost::math::cyl_bessel_i(-v, p, pol);
|
||||
//T j2 = boost::math::cyl_bessel_i(v, p, pol);
|
||||
//
|
||||
// Note that although we can calculate ai from j1 and j2, the accuracy is horrible
|
||||
// as we're subtracting two very large values, so use the Bessel K relation instead:
|
||||
//
|
||||
T aip = -cyl_bessel_k(v, p, pol) * x / (boost::math::constants::root_three<T>() * boost::math::constants::pi<T>());
|
||||
return aip;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
T airy_bi_prime_imp(T x, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
|
||||
if(x < 0)
|
||||
{
|
||||
T p = (-x * sqrt(-x) * 2) / 3;
|
||||
T v = T(2) / 3;
|
||||
T j1 = boost::math::cyl_bessel_j(v, p, pol);
|
||||
T j2 = boost::math::cyl_bessel_j(-v, p, pol);
|
||||
T aip = -x * (j1 + j2) / constants::root_three<T>();
|
||||
return aip;
|
||||
}
|
||||
else if(fabs(x * x) / 2 < tools::epsilon<T>())
|
||||
{
|
||||
T tg = boost::math::tgamma(constants::third<T>(), pol);
|
||||
T bip = sqrt(boost::math::cbrt(T(3))) / tg;
|
||||
return bip;
|
||||
}
|
||||
else
|
||||
{
|
||||
T p = 2 * x * sqrt(x) / 3;
|
||||
T v = T(2) / 3;
|
||||
T j1 = boost::math::cyl_bessel_i(-v, p, pol);
|
||||
T j2 = boost::math::cyl_bessel_i(v, p, pol);
|
||||
T aip = x * (j1 + j2) / boost::math::constants::root_three<T>();
|
||||
return aip;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
T airy_ai_zero_imp(int m, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING // ADL of std names, needed for log, sqrt.
|
||||
|
||||
// Handle cases when a negative zero (negative rank) is requested.
|
||||
if(m < 0)
|
||||
{
|
||||
return policies::raise_domain_error<T>("boost::math::airy_ai_zero<%1%>(%1%, int)",
|
||||
"Requested the %1%'th zero, but the rank must be 1 or more !", static_cast<T>(m), pol);
|
||||
}
|
||||
|
||||
// Handle case when the zero'th zero is requested.
|
||||
if(m == 0U)
|
||||
{
|
||||
return policies::raise_domain_error<T>("boost::math::airy_ai_zero<%1%>(%1%,%1%)",
|
||||
"The requested rank of the zero is %1%, but must be 1 or more !", static_cast<T>(m), pol);
|
||||
}
|
||||
|
||||
// Set up the initial guess for the upcoming root-finding.
|
||||
const T guess_root = boost::math::detail::airy_zero::airy_ai_zero_detail::initial_guess<T>(m);
|
||||
|
||||
// Select the maximum allowed iterations based on the number
|
||||
// of decimal digits in the numeric type T, being at least 12.
|
||||
const int my_digits10 = static_cast<int>(static_cast<float>(policies::digits<T, Policy>() * 0.301F));
|
||||
|
||||
const boost::uintmax_t iterations_allowed = static_cast<boost::uintmax_t>((std::max)(12, my_digits10 * 2));
|
||||
|
||||
boost::uintmax_t iterations_used = iterations_allowed;
|
||||
|
||||
// Use a dynamic tolerance because the roots get closer the higher m gets.
|
||||
T tolerance;
|
||||
|
||||
if (m <= 10) { tolerance = T(0.3F); }
|
||||
else if(m <= 100) { tolerance = T(0.1F); }
|
||||
else if(m <= 1000) { tolerance = T(0.05F); }
|
||||
else { tolerance = T(1) / sqrt(T(m)); }
|
||||
|
||||
// Perform the root-finding using Newton-Raphson iteration from Boost.Math.
|
||||
const T am =
|
||||
boost::math::tools::newton_raphson_iterate(
|
||||
boost::math::detail::airy_zero::airy_ai_zero_detail::function_object_ai_and_ai_prime<T, Policy>(pol),
|
||||
guess_root,
|
||||
T(guess_root - tolerance),
|
||||
T(guess_root + tolerance),
|
||||
policies::digits<T, Policy>(),
|
||||
iterations_used);
|
||||
|
||||
static_cast<void>(iterations_used);
|
||||
|
||||
return am;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
T airy_bi_zero_imp(int m, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING // ADL of std names, needed for log, sqrt.
|
||||
|
||||
// Handle cases when a negative zero (negative rank) is requested.
|
||||
if(m < 0)
|
||||
{
|
||||
return policies::raise_domain_error<T>("boost::math::airy_bi_zero<%1%>(%1%, int)",
|
||||
"Requested the %1%'th zero, but the rank must 1 or more !", static_cast<T>(m), pol);
|
||||
}
|
||||
|
||||
// Handle case when the zero'th zero is requested.
|
||||
if(m == 0U)
|
||||
{
|
||||
return policies::raise_domain_error<T>("boost::math::airy_bi_zero<%1%>(%1%,%1%)",
|
||||
"The requested rank of the zero is %1%, but must be 1 or more !", static_cast<T>(m), pol);
|
||||
}
|
||||
// Set up the initial guess for the upcoming root-finding.
|
||||
const T guess_root = boost::math::detail::airy_zero::airy_bi_zero_detail::initial_guess<T>(m);
|
||||
|
||||
// Select the maximum allowed iterations based on the number
|
||||
// of decimal digits in the numeric type T, being at least 12.
|
||||
const int my_digits10 = static_cast<int>(static_cast<float>(policies::digits<T, Policy>() * 0.301F));
|
||||
|
||||
const boost::uintmax_t iterations_allowed = static_cast<boost::uintmax_t>((std::max)(12, my_digits10 * 2));
|
||||
|
||||
boost::uintmax_t iterations_used = iterations_allowed;
|
||||
|
||||
// Use a dynamic tolerance because the roots get closer the higher m gets.
|
||||
T tolerance;
|
||||
|
||||
if (m <= 10) { tolerance = T(0.3F); }
|
||||
else if(m <= 100) { tolerance = T(0.1F); }
|
||||
else if(m <= 1000) { tolerance = T(0.05F); }
|
||||
else { tolerance = T(1) / sqrt(T(m)); }
|
||||
|
||||
// Perform the root-finding using Newton-Raphson iteration from Boost.Math.
|
||||
const T bm =
|
||||
boost::math::tools::newton_raphson_iterate(
|
||||
boost::math::detail::airy_zero::airy_bi_zero_detail::function_object_bi_and_bi_prime<T, Policy>(pol),
|
||||
guess_root,
|
||||
T(guess_root - tolerance),
|
||||
T(guess_root + tolerance),
|
||||
policies::digits<T, Policy>(),
|
||||
iterations_used);
|
||||
|
||||
static_cast<void>(iterations_used);
|
||||
|
||||
return bm;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class T, class Policy>
|
||||
inline typename tools::promote_args<T>::type airy_ai(T x, const Policy&)
|
||||
{
|
||||
BOOST_FPU_EXCEPTION_GUARD
|
||||
typedef typename tools::promote_args<T>::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;
|
||||
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(detail::airy_ai_imp<value_type>(static_cast<value_type>(x), forwarding_policy()), "boost::math::airy<%1%>(%1%)");
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typename tools::promote_args<T>::type airy_ai(T x)
|
||||
{
|
||||
return airy_ai(x, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline typename tools::promote_args<T>::type airy_bi(T x, const Policy&)
|
||||
{
|
||||
BOOST_FPU_EXCEPTION_GUARD
|
||||
typedef typename tools::promote_args<T>::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;
|
||||
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(detail::airy_bi_imp<value_type>(static_cast<value_type>(x), forwarding_policy()), "boost::math::airy<%1%>(%1%)");
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typename tools::promote_args<T>::type airy_bi(T x)
|
||||
{
|
||||
return airy_bi(x, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline typename tools::promote_args<T>::type airy_ai_prime(T x, const Policy&)
|
||||
{
|
||||
BOOST_FPU_EXCEPTION_GUARD
|
||||
typedef typename tools::promote_args<T>::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;
|
||||
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(detail::airy_ai_prime_imp<value_type>(static_cast<value_type>(x), forwarding_policy()), "boost::math::airy<%1%>(%1%)");
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typename tools::promote_args<T>::type airy_ai_prime(T x)
|
||||
{
|
||||
return airy_ai_prime(x, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline typename tools::promote_args<T>::type airy_bi_prime(T x, const Policy&)
|
||||
{
|
||||
BOOST_FPU_EXCEPTION_GUARD
|
||||
typedef typename tools::promote_args<T>::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;
|
||||
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(detail::airy_bi_prime_imp<value_type>(static_cast<value_type>(x), forwarding_policy()), "boost::math::airy<%1%>(%1%)");
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typename tools::promote_args<T>::type airy_bi_prime(T x)
|
||||
{
|
||||
return airy_bi_prime(x, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T airy_ai_zero(int m, const Policy& /*pol*/)
|
||||
{
|
||||
BOOST_FPU_EXCEPTION_GUARD
|
||||
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;
|
||||
|
||||
BOOST_STATIC_ASSERT_MSG( false == std::numeric_limits<T>::is_specialized
|
||||
|| ( true == std::numeric_limits<T>::is_specialized
|
||||
&& false == std::numeric_limits<T>::is_integer),
|
||||
"Airy value type must be a floating-point type.");
|
||||
|
||||
return policies::checked_narrowing_cast<T, Policy>(detail::airy_ai_zero_imp<value_type>(m, forwarding_policy()), "boost::math::airy_ai_zero<%1%>(unsigned)");
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T airy_ai_zero(int m)
|
||||
{
|
||||
return airy_ai_zero<T>(m, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T, class OutputIterator, class Policy>
|
||||
inline OutputIterator airy_ai_zero(
|
||||
int start_index,
|
||||
unsigned number_of_zeros,
|
||||
OutputIterator out_it,
|
||||
const Policy& pol)
|
||||
{
|
||||
typedef T result_type;
|
||||
|
||||
BOOST_STATIC_ASSERT_MSG( false == std::numeric_limits<T>::is_specialized
|
||||
|| ( true == std::numeric_limits<T>::is_specialized
|
||||
&& false == std::numeric_limits<T>::is_integer),
|
||||
"Airy value type must be a floating-point type.");
|
||||
|
||||
for(unsigned i = 0; i < number_of_zeros; ++i)
|
||||
{
|
||||
*out_it = boost::math::airy_ai_zero<result_type>(start_index + i, pol);
|
||||
++out_it;
|
||||
}
|
||||
return out_it;
|
||||
}
|
||||
|
||||
template <class T, class OutputIterator>
|
||||
inline OutputIterator airy_ai_zero(
|
||||
int start_index,
|
||||
unsigned number_of_zeros,
|
||||
OutputIterator out_it)
|
||||
{
|
||||
return airy_ai_zero<T>(start_index, number_of_zeros, out_it, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T airy_bi_zero(int m, const Policy& /*pol*/)
|
||||
{
|
||||
BOOST_FPU_EXCEPTION_GUARD
|
||||
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;
|
||||
|
||||
BOOST_STATIC_ASSERT_MSG( false == std::numeric_limits<T>::is_specialized
|
||||
|| ( true == std::numeric_limits<T>::is_specialized
|
||||
&& false == std::numeric_limits<T>::is_integer),
|
||||
"Airy value type must be a floating-point type.");
|
||||
|
||||
return policies::checked_narrowing_cast<T, Policy>(detail::airy_bi_zero_imp<value_type>(m, forwarding_policy()), "boost::math::airy_bi_zero<%1%>(unsigned)");
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T airy_bi_zero(int m)
|
||||
{
|
||||
return airy_bi_zero<T>(m, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T, class OutputIterator, class Policy>
|
||||
inline OutputIterator airy_bi_zero(
|
||||
int start_index,
|
||||
unsigned number_of_zeros,
|
||||
OutputIterator out_it,
|
||||
const Policy& pol)
|
||||
{
|
||||
typedef T result_type;
|
||||
|
||||
BOOST_STATIC_ASSERT_MSG( false == std::numeric_limits<T>::is_specialized
|
||||
|| ( true == std::numeric_limits<T>::is_specialized
|
||||
&& false == std::numeric_limits<T>::is_integer),
|
||||
"Airy value type must be a floating-point type.");
|
||||
|
||||
for(unsigned i = 0; i < number_of_zeros; ++i)
|
||||
{
|
||||
*out_it = boost::math::airy_bi_zero<result_type>(start_index + i, pol);
|
||||
++out_it;
|
||||
}
|
||||
return out_it;
|
||||
}
|
||||
|
||||
template <class T, class OutputIterator>
|
||||
inline OutputIterator airy_bi_zero(
|
||||
int start_index,
|
||||
unsigned number_of_zeros,
|
||||
OutputIterator out_it)
|
||||
{
|
||||
return airy_bi_zero<T>(start_index, number_of_zeros, out_it, policies::policy<>());
|
||||
}
|
||||
|
||||
}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_AIRY_HPP
|
||||
112
code_isotrope/boost/math/special_functions/asinh.hpp
Executable file
112
code_isotrope/boost/math/special_functions/asinh.hpp
Executable file
@@ -0,0 +1,112 @@
|
||||
// boost asinh.hpp header file
|
||||
|
||||
// (C) Copyright Eric Ford & Hubert Holin 2001.
|
||||
// (C) Copyright John Maddock 2008.
|
||||
// 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)
|
||||
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
#ifndef BOOST_ASINH_HPP
|
||||
#define BOOST_ASINH_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
#include <boost/config/no_tr1/cmath.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/math/tools/precision.hpp>
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/math/special_functions/sqrt1pm1.hpp>
|
||||
#include <boost/math/special_functions/log1p.hpp>
|
||||
#include <boost/math/constants/constants.hpp>
|
||||
|
||||
// This is the inverse of the hyperbolic sine function.
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace math
|
||||
{
|
||||
namespace detail{
|
||||
template<typename T, class Policy>
|
||||
inline T asinh_imp(const T x, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
|
||||
if((boost::math::isnan)(x))
|
||||
{
|
||||
return policies::raise_domain_error<T>(
|
||||
"boost::math::asinh<%1%>(%1%)",
|
||||
"asinh requires a finite argument, but got x = %1%.", x, pol);
|
||||
}
|
||||
if (x >= tools::forth_root_epsilon<T>())
|
||||
{
|
||||
if (x > 1 / tools::root_epsilon<T>())
|
||||
{
|
||||
// http://functions.wolfram.com/ElementaryFunctions/ArcSinh/06/01/06/01/0001/
|
||||
// approximation by laurent series in 1/x at 0+ order from -1 to 1
|
||||
return constants::ln_two<T>() + log(x) + 1/ (4 * x * x);
|
||||
}
|
||||
else if(x < 0.5f)
|
||||
{
|
||||
// As below, but rearranged to preserve digits:
|
||||
return boost::math::log1p(x + boost::math::sqrt1pm1(x * x, pol), pol);
|
||||
}
|
||||
else
|
||||
{
|
||||
// http://functions.wolfram.com/ElementaryFunctions/ArcSinh/02/
|
||||
return( log( x + sqrt(x*x+1) ) );
|
||||
}
|
||||
}
|
||||
else if (x <= -tools::forth_root_epsilon<T>())
|
||||
{
|
||||
return(-asinh(-x, pol));
|
||||
}
|
||||
else
|
||||
{
|
||||
// http://functions.wolfram.com/ElementaryFunctions/ArcSinh/06/01/03/01/0001/
|
||||
// approximation by taylor series in x at 0 up to order 2
|
||||
T result = x;
|
||||
|
||||
if (abs(x) >= tools::root_epsilon<T>())
|
||||
{
|
||||
T x3 = x*x*x;
|
||||
|
||||
// approximation by taylor series in x at 0 up to order 4
|
||||
result -= x3/static_cast<T>(6);
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline typename tools::promote_args<T>::type asinh(T x)
|
||||
{
|
||||
return boost::math::asinh(x, policies::policy<>());
|
||||
}
|
||||
template<typename T, typename Policy>
|
||||
inline typename tools::promote_args<T>::type asinh(T x, const Policy&)
|
||||
{
|
||||
typedef typename tools::promote_args<T>::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;
|
||||
return policies::checked_narrowing_cast<result_type, forwarding_policy>(
|
||||
detail::asinh_imp(static_cast<value_type>(x), forwarding_policy()),
|
||||
"boost::math::asinh<%1%>(%1%)");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* BOOST_ASINH_HPP */
|
||||
|
||||
123
code_isotrope/boost/math/special_functions/atanh.hpp
Executable file
123
code_isotrope/boost/math/special_functions/atanh.hpp
Executable file
@@ -0,0 +1,123 @@
|
||||
// boost atanh.hpp header file
|
||||
|
||||
// (C) Copyright Hubert Holin 2001.
|
||||
// (C) Copyright John Maddock 2008.
|
||||
// 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)
|
||||
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
#ifndef BOOST_ATANH_HPP
|
||||
#define BOOST_ATANH_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
#include <boost/config/no_tr1/cmath.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/math/tools/precision.hpp>
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/math/special_functions/log1p.hpp>
|
||||
|
||||
// This is the inverse of the hyperbolic tangent function.
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace math
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
// This is the main fare
|
||||
|
||||
template<typename T, typename Policy>
|
||||
inline T atanh_imp(const T x, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
static const char* function = "boost::math::atanh<%1%>(%1%)";
|
||||
|
||||
if(x < -1)
|
||||
{
|
||||
return policies::raise_domain_error<T>(
|
||||
function,
|
||||
"atanh requires x >= -1, but got x = %1%.", x, pol);
|
||||
}
|
||||
else if(x > 1)
|
||||
{
|
||||
return policies::raise_domain_error<T>(
|
||||
function,
|
||||
"atanh requires x <= 1, but got x = %1%.", x, pol);
|
||||
}
|
||||
else if((boost::math::isnan)(x))
|
||||
{
|
||||
return policies::raise_domain_error<T>(
|
||||
function,
|
||||
"atanh requires -1 <= x <= 1, but got x = %1%.", x, pol);
|
||||
}
|
||||
else if(x < -1 + tools::epsilon<T>())
|
||||
{
|
||||
// -Infinity:
|
||||
return -policies::raise_overflow_error<T>(function, 0, pol);
|
||||
}
|
||||
else if(x > 1 - tools::epsilon<T>())
|
||||
{
|
||||
// Infinity:
|
||||
return policies::raise_overflow_error<T>(function, 0, pol);
|
||||
}
|
||||
else if(abs(x) >= tools::forth_root_epsilon<T>())
|
||||
{
|
||||
// http://functions.wolfram.com/ElementaryFunctions/ArcTanh/02/
|
||||
if(abs(x) < 0.5f)
|
||||
return (boost::math::log1p(x, pol) - boost::math::log1p(-x, pol)) / 2;
|
||||
return(log( (1 + x) / (1 - x) ) / 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
// http://functions.wolfram.com/ElementaryFunctions/ArcTanh/06/01/03/01/
|
||||
// approximation by taylor series in x at 0 up to order 2
|
||||
T result = x;
|
||||
|
||||
if (abs(x) >= tools::root_epsilon<T>())
|
||||
{
|
||||
T x3 = x*x*x;
|
||||
|
||||
// approximation by taylor series in x at 0 up to order 4
|
||||
result += x3/static_cast<T>(3);
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, typename Policy>
|
||||
inline typename tools::promote_args<T>::type atanh(T x, const Policy&)
|
||||
{
|
||||
typedef typename tools::promote_args<T>::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;
|
||||
return policies::checked_narrowing_cast<result_type, forwarding_policy>(
|
||||
detail::atanh_imp(static_cast<value_type>(x), forwarding_policy()),
|
||||
"boost::math::atanh<%1%>(%1%)");
|
||||
}
|
||||
template<typename T>
|
||||
inline typename tools::promote_args<T>::type atanh(T x)
|
||||
{
|
||||
return boost::math::atanh(x, policies::policy<>());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* BOOST_ATANH_HPP */
|
||||
|
||||
|
||||
|
||||
143
code_isotrope/boost/math/special_functions/bernoulli.hpp
Executable file
143
code_isotrope/boost/math/special_functions/bernoulli.hpp
Executable file
@@ -0,0 +1,143 @@
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright 2013 Nikhar Agrawal
|
||||
// Copyright 2013 Christopher Kormanyos
|
||||
// Copyright 2013 John Maddock
|
||||
// Copyright 2013 Paul Bristow
|
||||
// Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef _BOOST_BERNOULLI_B2N_2013_05_30_HPP_
|
||||
#define _BOOST_BERNOULLI_B2N_2013_05_30_HPP_
|
||||
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/math/special_functions/detail/unchecked_bernoulli.hpp>
|
||||
#include <boost/math/special_functions/detail/bernoulli_details.hpp>
|
||||
|
||||
namespace boost { namespace math {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <class T, class OutputIterator, class Policy, int N>
|
||||
OutputIterator bernoulli_number_imp(OutputIterator out, std::size_t start, std::size_t n, const Policy& pol, const mpl::int_<N>& tag)
|
||||
{
|
||||
for(std::size_t i = start; (i <= max_bernoulli_b2n<T>::value) && (i < start + n); ++i)
|
||||
{
|
||||
*out = unchecked_bernoulli_imp<T>(i, tag);
|
||||
++out;
|
||||
}
|
||||
|
||||
for(std::size_t i = (std::max)(static_cast<std::size_t>(max_bernoulli_b2n<T>::value + 1), start); i < start + n; ++i)
|
||||
{
|
||||
// We must overflow:
|
||||
*out = (i & 1 ? 1 : -1) * policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(n)", 0, T(i), pol);
|
||||
++out;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
template <class T, class OutputIterator, class Policy>
|
||||
OutputIterator bernoulli_number_imp(OutputIterator out, std::size_t start, std::size_t n, const Policy& pol, const mpl::int_<0>& tag)
|
||||
{
|
||||
for(std::size_t i = start; (i <= max_bernoulli_b2n<T>::value) && (i < start + n); ++i)
|
||||
{
|
||||
*out = unchecked_bernoulli_imp<T>(i, tag);
|
||||
++out;
|
||||
}
|
||||
//
|
||||
// Short circuit return so we don't grab the mutex below unless we have to:
|
||||
//
|
||||
if(start + n <= max_bernoulli_b2n<T>::value)
|
||||
return out;
|
||||
|
||||
return get_bernoulli_numbers_cache<T, Policy>().copy_bernoulli_numbers(out, start, n, pol);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T bernoulli_b2n(const int i, const Policy &pol)
|
||||
{
|
||||
typedef mpl::int_<detail::bernoulli_imp_variant<T>::value> tag_type;
|
||||
if(i < 0)
|
||||
return policies::raise_domain_error<T>("boost::math::bernoulli_b2n<%1%>", "Index should be >= 0 but got %1%", T(i), pol);
|
||||
|
||||
T result = static_cast<T>(0); // The = 0 is just to silence compiler warnings :-(
|
||||
boost::math::detail::bernoulli_number_imp<T>(&result, static_cast<std::size_t>(i), 1u, pol, tag_type());
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T bernoulli_b2n(const int i)
|
||||
{
|
||||
return boost::math::bernoulli_b2n<T>(i, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T, class OutputIterator, class Policy>
|
||||
inline OutputIterator bernoulli_b2n(const int start_index,
|
||||
const unsigned number_of_bernoullis_b2n,
|
||||
OutputIterator out_it,
|
||||
const Policy& pol)
|
||||
{
|
||||
typedef mpl::int_<detail::bernoulli_imp_variant<T>::value> tag_type;
|
||||
if(start_index < 0)
|
||||
{
|
||||
*out_it = policies::raise_domain_error<T>("boost::math::bernoulli_b2n<%1%>", "Index should be >= 0 but got %1%", T(start_index), pol);
|
||||
return ++out_it;
|
||||
}
|
||||
|
||||
return boost::math::detail::bernoulli_number_imp<T>(out_it, start_index, number_of_bernoullis_b2n, pol, tag_type());
|
||||
}
|
||||
|
||||
template <class T, class OutputIterator>
|
||||
inline OutputIterator bernoulli_b2n(const int start_index,
|
||||
const unsigned number_of_bernoullis_b2n,
|
||||
OutputIterator out_it)
|
||||
{
|
||||
return boost::math::bernoulli_b2n<T, OutputIterator>(start_index, number_of_bernoullis_b2n, out_it, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T tangent_t2n(const int i, const Policy &pol)
|
||||
{
|
||||
if(i < 0)
|
||||
return policies::raise_domain_error<T>("boost::math::tangent_t2n<%1%>", "Index should be >= 0 but got %1%", T(i), pol);
|
||||
|
||||
T result;
|
||||
boost::math::detail::get_bernoulli_numbers_cache<T, Policy>().copy_tangent_numbers(&result, i, 1, pol);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T tangent_t2n(const int i)
|
||||
{
|
||||
return boost::math::tangent_t2n<T>(i, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T, class OutputIterator, class Policy>
|
||||
inline OutputIterator tangent_t2n(const int start_index,
|
||||
const unsigned number_of_tangent_t2n,
|
||||
OutputIterator out_it,
|
||||
const Policy& pol)
|
||||
{
|
||||
if(start_index < 0)
|
||||
{
|
||||
*out_it = policies::raise_domain_error<T>("boost::math::tangent_t2n<%1%>", "Index should be >= 0 but got %1%", T(start_index), pol);
|
||||
return ++out_it;
|
||||
}
|
||||
|
||||
return boost::math::detail::get_bernoulli_numbers_cache<T, Policy>().copy_tangent_numbers(out_it, start_index, number_of_tangent_t2n, pol);
|
||||
}
|
||||
|
||||
template <class T, class OutputIterator>
|
||||
inline OutputIterator tangent_t2n(const int start_index,
|
||||
const unsigned number_of_tangent_t2n,
|
||||
OutputIterator out_it)
|
||||
{
|
||||
return boost::math::tangent_t2n<T, OutputIterator>(start_index, number_of_tangent_t2n, out_it, policies::policy<>());
|
||||
}
|
||||
|
||||
} } // namespace boost::math
|
||||
|
||||
#endif // _BOOST_BERNOULLI_B2N_2013_05_30_HPP_
|
||||
762
code_isotrope/boost/math/special_functions/bessel.hpp
Executable file
762
code_isotrope/boost/math/special_functions/bessel.hpp
Executable file
@@ -0,0 +1,762 @@
|
||||
// Copyright (c) 2007, 2013 John Maddock
|
||||
// Copyright Christopher Kormanyos 2013.
|
||||
// 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 header just defines the function entry points, and adds dispatch
|
||||
// to the right implementation method. Most of the implementation details
|
||||
// are in separate headers and copyright Xiaogang Zhang.
|
||||
//
|
||||
#ifndef BOOST_MATH_BESSEL_HPP
|
||||
#define BOOST_MATH_BESSEL_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <limits>
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/math/special_functions/detail/bessel_jy.hpp>
|
||||
#include <boost/math/special_functions/detail/bessel_jn.hpp>
|
||||
#include <boost/math/special_functions/detail/bessel_yn.hpp>
|
||||
#include <boost/math/special_functions/detail/bessel_jy_zero.hpp>
|
||||
#include <boost/math/special_functions/detail/bessel_ik.hpp>
|
||||
#include <boost/math/special_functions/detail/bessel_i0.hpp>
|
||||
#include <boost/math/special_functions/detail/bessel_i1.hpp>
|
||||
#include <boost/math/special_functions/detail/bessel_kn.hpp>
|
||||
#include <boost/math/special_functions/detail/iconv.hpp>
|
||||
#include <boost/math/special_functions/sin_pi.hpp>
|
||||
#include <boost/math/special_functions/cos_pi.hpp>
|
||||
#include <boost/math/special_functions/sinc.hpp>
|
||||
#include <boost/math/special_functions/trunc.hpp>
|
||||
#include <boost/math/special_functions/round.hpp>
|
||||
#include <boost/math/tools/rational.hpp>
|
||||
#include <boost/math/tools/promotion.hpp>
|
||||
#include <boost/math/tools/series.hpp>
|
||||
#include <boost/math/tools/roots.hpp>
|
||||
|
||||
namespace boost{ namespace math{
|
||||
|
||||
namespace detail{
|
||||
|
||||
template <class T, class Policy>
|
||||
struct sph_bessel_j_small_z_series_term
|
||||
{
|
||||
typedef T result_type;
|
||||
|
||||
sph_bessel_j_small_z_series_term(unsigned v_, T x)
|
||||
: N(0), v(v_)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
mult = x / 2;
|
||||
if(v + 3 > max_factorial<T>::value)
|
||||
{
|
||||
term = v * log(mult) - boost::math::lgamma(v+1+T(0.5f), Policy());
|
||||
term = exp(term);
|
||||
}
|
||||
else
|
||||
term = pow(mult, T(v)) / boost::math::tgamma(v+1+T(0.5f), Policy());
|
||||
mult *= -mult;
|
||||
}
|
||||
T operator()()
|
||||
{
|
||||
T r = term;
|
||||
++N;
|
||||
term *= mult / (N * T(N + v + 0.5f));
|
||||
return r;
|
||||
}
|
||||
private:
|
||||
unsigned N;
|
||||
unsigned v;
|
||||
T mult;
|
||||
T term;
|
||||
};
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T sph_bessel_j_small_z_series(unsigned v, T x, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING // ADL of std names
|
||||
sph_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::sph_bessel_j_small_z_series<%1%>(%1%,%1%)", max_iter, pol);
|
||||
return result * sqrt(constants::pi<T>() / 4);
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
T cyl_bessel_j_imp(T v, T x, const bessel_no_int_tag& t, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
static const char* function = "boost::math::bessel_j<%1%>(%1%,%1%)";
|
||||
if(x < 0)
|
||||
{
|
||||
// better have integer v:
|
||||
if(floor(v) == v)
|
||||
{
|
||||
T r = cyl_bessel_j_imp(v, T(-x), t, pol);
|
||||
if(iround(v, pol) & 1)
|
||||
r = -r;
|
||||
return r;
|
||||
}
|
||||
else
|
||||
return policies::raise_domain_error<T>(
|
||||
function,
|
||||
"Got x = %1%, but we need x >= 0", x, pol);
|
||||
}
|
||||
|
||||
T j, y;
|
||||
bessel_jy(v, x, &j, &y, need_j, pol);
|
||||
return j;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T cyl_bessel_j_imp(T v, T x, const bessel_maybe_int_tag&, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING // ADL of std names.
|
||||
int ival = detail::iconv(v, pol);
|
||||
// If v is an integer, use the integer recursion
|
||||
// method, both that and Steeds method are O(v):
|
||||
if((0 == v - ival))
|
||||
{
|
||||
return bessel_jn(ival, x, pol);
|
||||
}
|
||||
return cyl_bessel_j_imp(v, x, bessel_no_int_tag(), pol);
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T cyl_bessel_j_imp(int v, T x, const bessel_int_tag&, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
return bessel_jn(v, x, pol);
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T sph_bessel_j_imp(unsigned n, T x, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING // ADL of std names
|
||||
if(x < 0)
|
||||
return policies::raise_domain_error<T>(
|
||||
"boost::math::sph_bessel_j<%1%>(%1%,%1%)",
|
||||
"Got x = %1%, but function requires x > 0.", x, pol);
|
||||
//
|
||||
// Special case, n == 0 resolves down to the sinus cardinal of x:
|
||||
//
|
||||
if(n == 0)
|
||||
return boost::math::sinc_pi(x, pol);
|
||||
//
|
||||
// Special case for x == 0:
|
||||
//
|
||||
if(x == 0)
|
||||
return 0;
|
||||
//
|
||||
// When x is small we may end up with 0/0, use series evaluation
|
||||
// instead, especially as it converges rapidly:
|
||||
//
|
||||
if(x < 1)
|
||||
return sph_bessel_j_small_z_series(n, x, pol);
|
||||
//
|
||||
// Default case is just a naive evaluation of the definition:
|
||||
//
|
||||
return sqrt(constants::pi<T>() / (2 * x))
|
||||
* cyl_bessel_j_imp(T(T(n)+T(0.5f)), x, bessel_no_int_tag(), pol);
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
T cyl_bessel_i_imp(T v, T x, const Policy& pol)
|
||||
{
|
||||
//
|
||||
// This handles all the bessel I functions, note that we don't optimise
|
||||
// for integer v, other than the v = 0 or 1 special cases, as Millers
|
||||
// algorithm is at least as inefficient as the general case (the general
|
||||
// case has better error handling too).
|
||||
//
|
||||
BOOST_MATH_STD_USING
|
||||
if(x < 0)
|
||||
{
|
||||
// better have integer v:
|
||||
if(floor(v) == v)
|
||||
{
|
||||
T r = cyl_bessel_i_imp(v, T(-x), pol);
|
||||
if(iround(v, pol) & 1)
|
||||
r = -r;
|
||||
return r;
|
||||
}
|
||||
else
|
||||
return policies::raise_domain_error<T>(
|
||||
"boost::math::cyl_bessel_i<%1%>(%1%,%1%)",
|
||||
"Got x = %1%, but we need x >= 0", x, pol);
|
||||
}
|
||||
if(x == 0)
|
||||
{
|
||||
return (v == 0) ? static_cast<T>(1) : static_cast<T>(0);
|
||||
}
|
||||
if(v == 0.5f)
|
||||
{
|
||||
// common special case, note try and avoid overflow in exp(x):
|
||||
if(x >= tools::log_max_value<T>())
|
||||
{
|
||||
T e = exp(x / 2);
|
||||
return e * (e / sqrt(2 * x * constants::pi<T>()));
|
||||
}
|
||||
return sqrt(2 / (x * constants::pi<T>())) * sinh(x);
|
||||
}
|
||||
if(policies::digits<T, Policy>() <= 113)
|
||||
{
|
||||
if(v == 0)
|
||||
{
|
||||
return bessel_i0(x);
|
||||
}
|
||||
if(v == 1)
|
||||
{
|
||||
return bessel_i1(x);
|
||||
}
|
||||
}
|
||||
if((v > 0) && (x / v < 0.25))
|
||||
return bessel_i_small_z_series(v, x, pol);
|
||||
T I, K;
|
||||
bessel_ik(v, x, &I, &K, need_i, pol);
|
||||
return I;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T cyl_bessel_k_imp(T v, T x, const bessel_no_int_tag& /* t */, const Policy& pol)
|
||||
{
|
||||
static const char* function = "boost::math::cyl_bessel_k<%1%>(%1%,%1%)";
|
||||
BOOST_MATH_STD_USING
|
||||
if(x < 0)
|
||||
{
|
||||
return policies::raise_domain_error<T>(
|
||||
function,
|
||||
"Got x = %1%, but we need x > 0", x, pol);
|
||||
}
|
||||
if(x == 0)
|
||||
{
|
||||
return (v == 0) ? policies::raise_overflow_error<T>(function, 0, pol)
|
||||
: policies::raise_domain_error<T>(
|
||||
function,
|
||||
"Got x = %1%, but we need x > 0", x, pol);
|
||||
}
|
||||
T I, K;
|
||||
bessel_ik(v, x, &I, &K, need_k, pol);
|
||||
return K;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T cyl_bessel_k_imp(T v, T x, const bessel_maybe_int_tag&, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
if((floor(v) == v))
|
||||
{
|
||||
return bessel_kn(itrunc(v), x, pol);
|
||||
}
|
||||
return cyl_bessel_k_imp(v, x, bessel_no_int_tag(), pol);
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T cyl_bessel_k_imp(int v, T x, const bessel_int_tag&, const Policy& pol)
|
||||
{
|
||||
return bessel_kn(v, x, pol);
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T cyl_neumann_imp(T v, T x, const bessel_no_int_tag&, const Policy& pol)
|
||||
{
|
||||
static const char* function = "boost::math::cyl_neumann<%1%>(%1%,%1%)";
|
||||
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(v);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(x);
|
||||
|
||||
if(x <= 0)
|
||||
{
|
||||
return (v == 0) && (x == 0) ?
|
||||
policies::raise_overflow_error<T>(function, 0, pol)
|
||||
: policies::raise_domain_error<T>(
|
||||
function,
|
||||
"Got x = %1%, but result is complex for x <= 0", x, pol);
|
||||
}
|
||||
T j, y;
|
||||
bessel_jy(v, x, &j, &y, need_y, pol);
|
||||
//
|
||||
// Post evaluation check for internal overflow during evaluation,
|
||||
// can occur when x is small and v is large, in which case the result
|
||||
// is -INF:
|
||||
//
|
||||
if(!(boost::math::isfinite)(y))
|
||||
return -policies::raise_overflow_error<T>(function, 0, pol);
|
||||
return y;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T cyl_neumann_imp(T v, T x, const bessel_maybe_int_tag&, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(v);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(x);
|
||||
|
||||
if(floor(v) == v)
|
||||
{
|
||||
T r = bessel_yn(itrunc(v, pol), x, pol);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(r);
|
||||
return r;
|
||||
}
|
||||
T r = cyl_neumann_imp<T>(v, x, bessel_no_int_tag(), pol);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(r);
|
||||
return r;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T cyl_neumann_imp(int v, T x, const bessel_int_tag&, const Policy& pol)
|
||||
{
|
||||
return bessel_yn(v, x, pol);
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T sph_neumann_imp(unsigned v, T x, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING // ADL of std names
|
||||
static const char* function = "boost::math::sph_neumann<%1%>(%1%,%1%)";
|
||||
//
|
||||
// Nothing much to do here but check for errors, and
|
||||
// evaluate the function's definition directly:
|
||||
//
|
||||
if(x < 0)
|
||||
return policies::raise_domain_error<T>(
|
||||
function,
|
||||
"Got x = %1%, but function requires x > 0.", x, pol);
|
||||
|
||||
if(x < 2 * tools::min_value<T>())
|
||||
return -policies::raise_overflow_error<T>(function, 0, pol);
|
||||
|
||||
T result = cyl_neumann_imp(T(T(v)+0.5f), x, bessel_no_int_tag(), pol);
|
||||
T tx = sqrt(constants::pi<T>() / (2 * x));
|
||||
|
||||
if((tx > 1) && (tools::max_value<T>() / tx < result))
|
||||
return -policies::raise_overflow_error<T>(function, 0, pol);
|
||||
|
||||
return result * tx;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T cyl_bessel_j_zero_imp(T v, int m, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING // ADL of std names, needed for floor.
|
||||
|
||||
static const char* function = "boost::math::cyl_bessel_j_zero<%1%>(%1%, int)";
|
||||
|
||||
const T half_epsilon(boost::math::tools::epsilon<T>() / 2U);
|
||||
|
||||
// Handle non-finite order.
|
||||
if (!(boost::math::isfinite)(v) )
|
||||
{
|
||||
return policies::raise_domain_error<T>(function, "Order argument is %1%, but must be finite >= 0 !", v, pol);
|
||||
}
|
||||
|
||||
// Handle negative rank.
|
||||
if(m < 0)
|
||||
{
|
||||
// Zeros of Jv(x) with negative rank are not defined and requesting one raises a domain error.
|
||||
return policies::raise_domain_error<T>(function, "Requested the %1%'th zero, but the rank must be positive !", static_cast<T>(m), pol);
|
||||
}
|
||||
|
||||
// Get the absolute value of the order.
|
||||
const bool order_is_negative = (v < 0);
|
||||
const T vv((!order_is_negative) ? v : T(-v));
|
||||
|
||||
// Check if the order is very close to zero or very close to an integer.
|
||||
const bool order_is_zero = (vv < half_epsilon);
|
||||
const bool order_is_integer = ((vv - floor(vv)) < half_epsilon);
|
||||
|
||||
if(m == 0)
|
||||
{
|
||||
if(order_is_zero)
|
||||
{
|
||||
// The zero'th zero of J0(x) is not defined and requesting it raises a domain error.
|
||||
return policies::raise_domain_error<T>(function, "Requested the %1%'th zero of J0, but the rank must be > 0 !", static_cast<T>(m), pol);
|
||||
}
|
||||
|
||||
// The zero'th zero of Jv(x) for v < 0 is not defined
|
||||
// unless the order is a negative integer.
|
||||
if(order_is_negative && (!order_is_integer))
|
||||
{
|
||||
// For non-integer, negative order, requesting the zero'th zero raises a domain error.
|
||||
return policies::raise_domain_error<T>(function, "Requested the %1%'th zero of Jv for negative, non-integer order, but the rank must be > 0 !", static_cast<T>(m), pol);
|
||||
}
|
||||
|
||||
// The zero'th zero does exist and its value is zero.
|
||||
return T(0);
|
||||
}
|
||||
|
||||
// Set up the initial guess for the upcoming root-finding.
|
||||
// If the order is a negative integer, then use the corresponding
|
||||
// positive integer for the order.
|
||||
const T guess_root = boost::math::detail::bessel_zero::cyl_bessel_j_zero_detail::initial_guess<T, Policy>((order_is_integer ? vv : v), m, pol);
|
||||
|
||||
// Select the maximum allowed iterations from the policy.
|
||||
boost::uintmax_t number_of_iterations = policies::get_max_root_iterations<Policy>();
|
||||
|
||||
const T delta_lo = ((guess_root > 0.2F) ? T(0.2) : T(guess_root / 2U));
|
||||
|
||||
// Perform the root-finding using Newton-Raphson iteration from Boost.Math.
|
||||
const T jvm =
|
||||
boost::math::tools::newton_raphson_iterate(
|
||||
boost::math::detail::bessel_zero::cyl_bessel_j_zero_detail::function_object_jv_and_jv_prime<T, Policy>((order_is_integer ? vv : v), order_is_zero, pol),
|
||||
guess_root,
|
||||
T(guess_root - delta_lo),
|
||||
T(guess_root + 0.2F),
|
||||
policies::digits<T, Policy>(),
|
||||
number_of_iterations);
|
||||
|
||||
if(number_of_iterations >= policies::get_max_root_iterations<Policy>())
|
||||
{
|
||||
return policies::raise_evaluation_error<T>(function, "Unable to locate root in a reasonable time:"
|
||||
" Current best guess is %1%", jvm, Policy());
|
||||
}
|
||||
|
||||
return jvm;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T cyl_neumann_zero_imp(T v, int m, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING // ADL of std names, needed for floor.
|
||||
|
||||
static const char* function = "boost::math::cyl_neumann_zero<%1%>(%1%, int)";
|
||||
|
||||
// Handle non-finite order.
|
||||
if (!(boost::math::isfinite)(v) )
|
||||
{
|
||||
return policies::raise_domain_error<T>(function, "Order argument is %1%, but must be finite >= 0 !", v, pol);
|
||||
}
|
||||
|
||||
// Handle negative rank.
|
||||
if(m < 0)
|
||||
{
|
||||
return policies::raise_domain_error<T>(function, "Requested the %1%'th zero, but the rank must be positive !", static_cast<T>(m), pol);
|
||||
}
|
||||
|
||||
const T half_epsilon(boost::math::tools::epsilon<T>() / 2U);
|
||||
|
||||
// Get the absolute value of the order.
|
||||
const bool order_is_negative = (v < 0);
|
||||
const T vv((!order_is_negative) ? v : T(-v));
|
||||
|
||||
const bool order_is_integer = ((vv - floor(vv)) < half_epsilon);
|
||||
|
||||
// For negative integers, use reflection to positive integer order.
|
||||
if(order_is_negative && order_is_integer)
|
||||
return boost::math::detail::cyl_neumann_zero_imp(vv, m, pol);
|
||||
|
||||
// Check if the order is very close to a negative half-integer.
|
||||
const T delta_half_integer(vv - (floor(vv) + 0.5F));
|
||||
|
||||
const bool order_is_negative_half_integer =
|
||||
(order_is_negative && ((delta_half_integer > -half_epsilon) && (delta_half_integer < +half_epsilon)));
|
||||
|
||||
// The zero'th zero of Yv(x) for v < 0 is not defined
|
||||
// unless the order is a negative integer.
|
||||
if((m == 0) && (!order_is_negative_half_integer))
|
||||
{
|
||||
// For non-integer, negative order, requesting the zero'th zero raises a domain error.
|
||||
return policies::raise_domain_error<T>(function, "Requested the %1%'th zero of Yv for negative, non-half-integer order, but the rank must be > 0 !", static_cast<T>(m), pol);
|
||||
}
|
||||
|
||||
// For negative half-integers, use the corresponding
|
||||
// spherical Bessel function of positive half-integer order.
|
||||
if(order_is_negative_half_integer)
|
||||
return boost::math::detail::cyl_bessel_j_zero_imp(vv, m, pol);
|
||||
|
||||
// Set up the initial guess for the upcoming root-finding.
|
||||
// If the order is a negative integer, then use the corresponding
|
||||
// positive integer for the order.
|
||||
const T guess_root = boost::math::detail::bessel_zero::cyl_neumann_zero_detail::initial_guess<T, Policy>(v, m, pol);
|
||||
|
||||
// Select the maximum allowed iterations from the policy.
|
||||
boost::uintmax_t number_of_iterations = policies::get_max_root_iterations<Policy>();
|
||||
|
||||
const T delta_lo = ((guess_root > 0.2F) ? T(0.2) : T(guess_root / 2U));
|
||||
|
||||
// Perform the root-finding using Newton-Raphson iteration from Boost.Math.
|
||||
const T yvm =
|
||||
boost::math::tools::newton_raphson_iterate(
|
||||
boost::math::detail::bessel_zero::cyl_neumann_zero_detail::function_object_yv_and_yv_prime<T, Policy>(v, pol),
|
||||
guess_root,
|
||||
T(guess_root - delta_lo),
|
||||
T(guess_root + 0.2F),
|
||||
policies::digits<T, Policy>(),
|
||||
number_of_iterations);
|
||||
|
||||
if(number_of_iterations >= policies::get_max_root_iterations<Policy>())
|
||||
{
|
||||
return policies::raise_evaluation_error<T>(function, "Unable to locate root in a reasonable time:"
|
||||
" Current best guess is %1%", yvm, Policy());
|
||||
}
|
||||
|
||||
return yvm;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class T1, class T2, class Policy>
|
||||
inline typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_bessel_j(T1 v, T2 x, const Policy& /* pol */)
|
||||
{
|
||||
BOOST_FPU_EXCEPTION_GUARD
|
||||
typedef typename detail::bessel_traits<T1, T2, Policy>::result_type result_type;
|
||||
typedef typename detail::bessel_traits<T1, T2, Policy>::optimisation_tag tag_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;
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_bessel_j_imp<value_type>(v, static_cast<value_type>(x), tag_type(), forwarding_policy()), "boost::math::cyl_bessel_j<%1%>(%1%,%1%)");
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
inline typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type cyl_bessel_j(T1 v, T2 x)
|
||||
{
|
||||
return cyl_bessel_j(v, x, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline typename detail::bessel_traits<T, T, Policy>::result_type sph_bessel(unsigned v, T x, const Policy& /* pol */)
|
||||
{
|
||||
BOOST_FPU_EXCEPTION_GUARD
|
||||
typedef typename detail::bessel_traits<T, T, Policy>::result_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;
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(detail::sph_bessel_j_imp<value_type>(v, static_cast<value_type>(x), forwarding_policy()), "boost::math::sph_bessel<%1%>(%1%,%1%)");
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typename detail::bessel_traits<T, T, policies::policy<> >::result_type sph_bessel(unsigned v, T x)
|
||||
{
|
||||
return sph_bessel(v, x, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T1, class T2, class Policy>
|
||||
inline typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_bessel_i(T1 v, T2 x, const Policy& /* pol */)
|
||||
{
|
||||
BOOST_FPU_EXCEPTION_GUARD
|
||||
typedef typename detail::bessel_traits<T1, T2, Policy>::result_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;
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_bessel_i_imp<value_type>(static_cast<value_type>(v), static_cast<value_type>(x), forwarding_policy()), "boost::math::cyl_bessel_i<%1%>(%1%,%1%)");
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
inline typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type cyl_bessel_i(T1 v, T2 x)
|
||||
{
|
||||
return cyl_bessel_i(v, x, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T1, class T2, class Policy>
|
||||
inline typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_bessel_k(T1 v, T2 x, const Policy& /* pol */)
|
||||
{
|
||||
BOOST_FPU_EXCEPTION_GUARD
|
||||
typedef typename detail::bessel_traits<T1, T2, Policy>::result_type result_type;
|
||||
typedef typename detail::bessel_traits<T1, T2, Policy>::optimisation_tag128 tag_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;
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_bessel_k_imp<value_type>(v, static_cast<value_type>(x), tag_type(), forwarding_policy()), "boost::math::cyl_bessel_k<%1%>(%1%,%1%)");
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
inline typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type cyl_bessel_k(T1 v, T2 x)
|
||||
{
|
||||
return cyl_bessel_k(v, x, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T1, class T2, class Policy>
|
||||
inline typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_neumann(T1 v, T2 x, const Policy& /* pol */)
|
||||
{
|
||||
BOOST_FPU_EXCEPTION_GUARD
|
||||
typedef typename detail::bessel_traits<T1, T2, Policy>::result_type result_type;
|
||||
typedef typename detail::bessel_traits<T1, T2, Policy>::optimisation_tag tag_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;
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_neumann_imp<value_type>(v, static_cast<value_type>(x), tag_type(), forwarding_policy()), "boost::math::cyl_neumann<%1%>(%1%,%1%)");
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
inline typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type cyl_neumann(T1 v, T2 x)
|
||||
{
|
||||
return cyl_neumann(v, x, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline typename detail::bessel_traits<T, T, Policy>::result_type sph_neumann(unsigned v, T x, const Policy& /* pol */)
|
||||
{
|
||||
BOOST_FPU_EXCEPTION_GUARD
|
||||
typedef typename detail::bessel_traits<T, T, Policy>::result_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;
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(detail::sph_neumann_imp<value_type>(v, static_cast<value_type>(x), forwarding_policy()), "boost::math::sph_neumann<%1%>(%1%,%1%)");
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typename detail::bessel_traits<T, T, policies::policy<> >::result_type sph_neumann(unsigned v, T x)
|
||||
{
|
||||
return sph_neumann(v, x, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline typename detail::bessel_traits<T, T, Policy>::result_type cyl_bessel_j_zero(T v, int m, const Policy& /* pol */)
|
||||
{
|
||||
BOOST_FPU_EXCEPTION_GUARD
|
||||
typedef typename detail::bessel_traits<T, T, Policy>::result_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;
|
||||
|
||||
BOOST_STATIC_ASSERT_MSG( false == std::numeric_limits<T>::is_specialized
|
||||
|| ( true == std::numeric_limits<T>::is_specialized
|
||||
&& false == std::numeric_limits<T>::is_integer),
|
||||
"Order must be a floating-point type.");
|
||||
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_bessel_j_zero_imp<value_type>(v, m, forwarding_policy()), "boost::math::cyl_bessel_j_zero<%1%>(%1%,%1%)");
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typename detail::bessel_traits<T, T, policies::policy<> >::result_type cyl_bessel_j_zero(T v, int m)
|
||||
{
|
||||
BOOST_STATIC_ASSERT_MSG( false == std::numeric_limits<T>::is_specialized
|
||||
|| ( true == std::numeric_limits<T>::is_specialized
|
||||
&& false == std::numeric_limits<T>::is_integer),
|
||||
"Order must be a floating-point type.");
|
||||
|
||||
return cyl_bessel_j_zero<T, policies::policy<> >(v, m, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T, class OutputIterator, class Policy>
|
||||
inline OutputIterator cyl_bessel_j_zero(T v,
|
||||
int start_index,
|
||||
unsigned number_of_zeros,
|
||||
OutputIterator out_it,
|
||||
const Policy& pol)
|
||||
{
|
||||
BOOST_STATIC_ASSERT_MSG( false == std::numeric_limits<T>::is_specialized
|
||||
|| ( true == std::numeric_limits<T>::is_specialized
|
||||
&& false == std::numeric_limits<T>::is_integer),
|
||||
"Order must be a floating-point type.");
|
||||
|
||||
for(int i = 0; i < static_cast<int>(number_of_zeros); ++i)
|
||||
{
|
||||
*out_it = boost::math::cyl_bessel_j_zero(v, start_index + i, pol);
|
||||
++out_it;
|
||||
}
|
||||
return out_it;
|
||||
}
|
||||
|
||||
template <class T, class OutputIterator>
|
||||
inline OutputIterator cyl_bessel_j_zero(T v,
|
||||
int start_index,
|
||||
unsigned number_of_zeros,
|
||||
OutputIterator out_it)
|
||||
{
|
||||
return cyl_bessel_j_zero(v, start_index, number_of_zeros, out_it, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline typename detail::bessel_traits<T, T, Policy>::result_type cyl_neumann_zero(T v, int m, const Policy& /* pol */)
|
||||
{
|
||||
BOOST_FPU_EXCEPTION_GUARD
|
||||
typedef typename detail::bessel_traits<T, T, Policy>::result_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;
|
||||
|
||||
BOOST_STATIC_ASSERT_MSG( false == std::numeric_limits<T>::is_specialized
|
||||
|| ( true == std::numeric_limits<T>::is_specialized
|
||||
&& false == std::numeric_limits<T>::is_integer),
|
||||
"Order must be a floating-point type.");
|
||||
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_neumann_zero_imp<value_type>(v, m, forwarding_policy()), "boost::math::cyl_neumann_zero<%1%>(%1%,%1%)");
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typename detail::bessel_traits<T, T, policies::policy<> >::result_type cyl_neumann_zero(T v, int m)
|
||||
{
|
||||
BOOST_STATIC_ASSERT_MSG( false == std::numeric_limits<T>::is_specialized
|
||||
|| ( true == std::numeric_limits<T>::is_specialized
|
||||
&& false == std::numeric_limits<T>::is_integer),
|
||||
"Order must be a floating-point type.");
|
||||
|
||||
return cyl_neumann_zero<T, policies::policy<> >(v, m, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T, class OutputIterator, class Policy>
|
||||
inline OutputIterator cyl_neumann_zero(T v,
|
||||
int start_index,
|
||||
unsigned number_of_zeros,
|
||||
OutputIterator out_it,
|
||||
const Policy& pol)
|
||||
{
|
||||
BOOST_STATIC_ASSERT_MSG( false == std::numeric_limits<T>::is_specialized
|
||||
|| ( true == std::numeric_limits<T>::is_specialized
|
||||
&& false == std::numeric_limits<T>::is_integer),
|
||||
"Order must be a floating-point type.");
|
||||
|
||||
for(int i = 0; i < static_cast<int>(number_of_zeros); ++i)
|
||||
{
|
||||
*out_it = boost::math::cyl_neumann_zero(v, start_index + i, pol);
|
||||
++out_it;
|
||||
}
|
||||
return out_it;
|
||||
}
|
||||
|
||||
template <class T, class OutputIterator>
|
||||
inline OutputIterator cyl_neumann_zero(T v,
|
||||
int start_index,
|
||||
unsigned number_of_zeros,
|
||||
OutputIterator out_it)
|
||||
{
|
||||
return cyl_neumann_zero(v, start_index, number_of_zeros, out_it, policies::policy<>());
|
||||
}
|
||||
|
||||
} // namespace math
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_MATH_BESSEL_HPP
|
||||
|
||||
|
||||
359
code_isotrope/boost/math/special_functions/bessel_prime.hpp
Executable file
359
code_isotrope/boost/math/special_functions/bessel_prime.hpp
Executable file
@@ -0,0 +1,359 @@
|
||||
// Copyright (c) 2013 Anton Bikineev
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#ifndef BOOST_MATH_BESSEL_DERIVATIVES_HPP
|
||||
#define BOOST_MATH_BESSEL_DERIVATIVES_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/math/special_functions/bessel.hpp>
|
||||
#include <boost/math/special_functions/detail/bessel_jy_derivatives_asym.hpp>
|
||||
#include <boost/math/special_functions/detail/bessel_jy_derivatives_series.hpp>
|
||||
#include <boost/math/special_functions/detail/bessel_derivatives_linear.hpp>
|
||||
|
||||
namespace boost{ namespace math{
|
||||
|
||||
namespace detail{
|
||||
|
||||
template <class Tag, class T, class Policy>
|
||||
inline T cyl_bessel_j_prime_imp(T v, T x, const Policy& pol)
|
||||
{
|
||||
static const char* const function = "boost::math::cyl_bessel_j_prime<%1%>(%1%,%1%)";
|
||||
BOOST_MATH_STD_USING
|
||||
//
|
||||
// Prevent complex result:
|
||||
//
|
||||
if (x < 0 && floor(v) != v)
|
||||
return boost::math::policies::raise_domain_error<T>(
|
||||
function,
|
||||
"Got x = %1%, but function requires x >= 0", x, pol);
|
||||
//
|
||||
// Special cases for x == 0:
|
||||
//
|
||||
if (x == 0)
|
||||
{
|
||||
if (v == 1)
|
||||
return 0.5;
|
||||
else if (v == -1)
|
||||
return -0.5;
|
||||
else if (floor(v) == v || v > 1)
|
||||
return 0;
|
||||
else return boost::math::policies::raise_domain_error<T>(
|
||||
function,
|
||||
"Got x = %1%, but function is indeterminate for this order", x, pol);
|
||||
}
|
||||
//
|
||||
// Special case for large x: use asymptotic expansion:
|
||||
//
|
||||
if (boost::math::detail::asymptotic_bessel_derivative_large_x_limit(v, x))
|
||||
return boost::math::detail::asymptotic_bessel_j_derivative_large_x_2(v, x);
|
||||
//
|
||||
// Special case for small x: use Taylor series:
|
||||
//
|
||||
if ((abs(x) < 5) || (abs(v) > x * x / 4))
|
||||
{
|
||||
bool inversed = false;
|
||||
if (floor(v) == v && v < 0)
|
||||
{
|
||||
v = -v;
|
||||
if (itrunc(v, pol) & 1)
|
||||
inversed = true;
|
||||
}
|
||||
T r = boost::math::detail::bessel_j_derivative_small_z_series(v, x, pol);
|
||||
return inversed ? T(-r) : r;
|
||||
}
|
||||
//
|
||||
// Special case for v == 0:
|
||||
//
|
||||
if (v == 0)
|
||||
return -boost::math::detail::cyl_bessel_j_imp<T>(1, x, Tag(), pol);
|
||||
//
|
||||
// Default case:
|
||||
//
|
||||
return boost::math::detail::bessel_j_derivative_linear(v, x, Tag(), pol);
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T sph_bessel_j_prime_imp(unsigned v, T x, const Policy& pol)
|
||||
{
|
||||
static const char* const function = "boost::math::sph_bessel_prime<%1%>(%1%,%1%)";
|
||||
//
|
||||
// Prevent complex result:
|
||||
//
|
||||
if (x < 0)
|
||||
return boost::math::policies::raise_domain_error<T>(
|
||||
function,
|
||||
"Got x = %1%, but function requires x >= 0.", x, pol);
|
||||
//
|
||||
// Special case for v == 0:
|
||||
//
|
||||
if (v == 0)
|
||||
return (x == 0) ? boost::math::policies::raise_overflow_error<T>(function, 0, pol)
|
||||
: static_cast<T>(-boost::math::detail::sph_bessel_j_imp<T>(1, x, pol));
|
||||
//
|
||||
// Special case for x == 0 and v > 0:
|
||||
//
|
||||
if (x == 0)
|
||||
return boost::math::policies::raise_domain_error<T>(
|
||||
function,
|
||||
"Got x = %1%, but function is indeterminate for this order", x, pol);
|
||||
//
|
||||
// Default case:
|
||||
//
|
||||
return boost::math::detail::sph_bessel_j_derivative_linear(v, x, pol);
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T cyl_bessel_i_prime_imp(T v, T x, const Policy& pol)
|
||||
{
|
||||
static const char* const function = "boost::math::cyl_bessel_i_prime<%1%>(%1%,%1%)";
|
||||
BOOST_MATH_STD_USING
|
||||
//
|
||||
// Prevent complex result:
|
||||
//
|
||||
if (x < 0 && floor(v) != v)
|
||||
return boost::math::policies::raise_domain_error<T>(
|
||||
function,
|
||||
"Got x = %1%, but function requires x >= 0", x, pol);
|
||||
//
|
||||
// Special cases for x == 0:
|
||||
//
|
||||
if (x == 0)
|
||||
{
|
||||
if (v == 1 || v == -1)
|
||||
return 0.5;
|
||||
else if (floor(v) == v || v > 1)
|
||||
return 0;
|
||||
else return boost::math::policies::raise_domain_error<T>(
|
||||
function,
|
||||
"Got x = %1%, but function is indeterminate for this order", x, pol);
|
||||
}
|
||||
//
|
||||
// Special case for v == 0:
|
||||
//
|
||||
if (v == 0)
|
||||
return boost::math::detail::cyl_bessel_i_imp<T>(1, x, pol);
|
||||
//
|
||||
// Default case:
|
||||
//
|
||||
return boost::math::detail::bessel_i_derivative_linear(v, x, pol);
|
||||
}
|
||||
|
||||
template <class Tag, class T, class Policy>
|
||||
inline T cyl_bessel_k_prime_imp(T v, T x, const Policy& pol)
|
||||
{
|
||||
//
|
||||
// Prevent complex and indeterminate results:
|
||||
//
|
||||
if (x <= 0)
|
||||
return boost::math::policies::raise_domain_error<T>(
|
||||
"boost::math::cyl_bessel_k_prime<%1%>(%1%,%1%)",
|
||||
"Got x = %1%, but function requires x > 0", x, pol);
|
||||
//
|
||||
// Special case for v == 0:
|
||||
//
|
||||
if (v == 0)
|
||||
return -boost::math::detail::cyl_bessel_k_imp<T>(1, x, Tag(), pol);
|
||||
//
|
||||
// Default case:
|
||||
//
|
||||
return boost::math::detail::bessel_k_derivative_linear(v, x, Tag(), pol);
|
||||
}
|
||||
|
||||
template <class Tag, class T, class Policy>
|
||||
inline T cyl_neumann_prime_imp(T v, T x, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
//
|
||||
// Prevent complex and indeterminate results:
|
||||
//
|
||||
if (x <= 0)
|
||||
return boost::math::policies::raise_domain_error<T>(
|
||||
"boost::math::cyl_neumann_prime<%1%>(%1%,%1%)",
|
||||
"Got x = %1%, but function requires x > 0", x, pol);
|
||||
//
|
||||
// Special case for large x: use asymptotic expansion:
|
||||
//
|
||||
if (boost::math::detail::asymptotic_bessel_derivative_large_x_limit(v, x))
|
||||
return boost::math::detail::asymptotic_bessel_y_derivative_large_x_2(v, x);
|
||||
//
|
||||
// Special case for small x: use Taylor series:
|
||||
//
|
||||
if (v > 0 && floor(v) != v)
|
||||
{
|
||||
const T eps = boost::math::policies::get_epsilon<T, Policy>();
|
||||
if (log(eps / 2) > v * log((x * x) / (v * 4)))
|
||||
return boost::math::detail::bessel_y_derivative_small_z_series(v, x, pol);
|
||||
}
|
||||
//
|
||||
// Special case for v == 0:
|
||||
//
|
||||
if (v == 0)
|
||||
return -boost::math::detail::cyl_neumann_imp<T>(1, x, Tag(), pol);
|
||||
//
|
||||
// Default case:
|
||||
//
|
||||
return boost::math::detail::bessel_y_derivative_linear(v, x, Tag(), pol);
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T sph_neumann_prime_imp(unsigned v, T x, const Policy& pol)
|
||||
{
|
||||
//
|
||||
// Prevent complex and indeterminate result:
|
||||
//
|
||||
if (x <= 0)
|
||||
return boost::math::policies::raise_domain_error<T>(
|
||||
"boost::math::sph_neumann_prime<%1%>(%1%,%1%)",
|
||||
"Got x = %1%, but function requires x > 0.", x, pol);
|
||||
//
|
||||
// Special case for v == 0:
|
||||
//
|
||||
if (v == 0)
|
||||
return -boost::math::detail::sph_neumann_imp<T>(1, x, pol);
|
||||
//
|
||||
// Default case:
|
||||
//
|
||||
return boost::math::detail::sph_neumann_derivative_linear(v, x, pol);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class T1, class T2, class Policy>
|
||||
inline typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_bessel_j_prime(T1 v, T2 x, const Policy& /* pol */)
|
||||
{
|
||||
BOOST_FPU_EXCEPTION_GUARD
|
||||
typedef typename detail::bessel_traits<T1, T2, Policy>::result_type result_type;
|
||||
typedef typename detail::bessel_traits<T1, T2, Policy>::optimisation_tag tag_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;
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_bessel_j_prime_imp<tag_type, value_type>(static_cast<value_type>(v), static_cast<value_type>(x), forwarding_policy()), "boost::math::cyl_bessel_j_prime<%1%,%1%>(%1%,%1%)");
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
inline typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type cyl_bessel_j_prime(T1 v, T2 x)
|
||||
{
|
||||
return cyl_bessel_j_prime(v, x, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline typename detail::bessel_traits<T, T, Policy>::result_type sph_bessel_prime(unsigned v, T x, const Policy& /* pol */)
|
||||
{
|
||||
BOOST_FPU_EXCEPTION_GUARD
|
||||
typedef typename detail::bessel_traits<T, T, Policy>::result_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;
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(detail::sph_bessel_j_prime_imp<value_type>(v, static_cast<value_type>(x), forwarding_policy()), "boost::math::sph_bessel_j_prime<%1%>(%1%,%1%)");
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typename detail::bessel_traits<T, T, policies::policy<> >::result_type sph_bessel_prime(unsigned v, T x)
|
||||
{
|
||||
return sph_bessel_prime(v, x, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T1, class T2, class Policy>
|
||||
inline typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_bessel_i_prime(T1 v, T2 x, const Policy& /* pol */)
|
||||
{
|
||||
BOOST_FPU_EXCEPTION_GUARD
|
||||
typedef typename detail::bessel_traits<T1, T2, Policy>::result_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;
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_bessel_i_prime_imp<value_type>(static_cast<value_type>(v), static_cast<value_type>(x), forwarding_policy()), "boost::math::cyl_bessel_i_prime<%1%>(%1%,%1%)");
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
inline typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type cyl_bessel_i_prime(T1 v, T2 x)
|
||||
{
|
||||
return cyl_bessel_i_prime(v, x, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T1, class T2, class Policy>
|
||||
inline typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_bessel_k_prime(T1 v, T2 x, const Policy& /* pol */)
|
||||
{
|
||||
BOOST_FPU_EXCEPTION_GUARD
|
||||
typedef typename detail::bessel_traits<T1, T2, Policy>::result_type result_type;
|
||||
typedef typename detail::bessel_traits<T1, T2, Policy>::optimisation_tag tag_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;
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_bessel_k_prime_imp<tag_type, value_type>(static_cast<value_type>(v), static_cast<value_type>(x), forwarding_policy()), "boost::math::cyl_bessel_k_prime<%1%,%1%>(%1%,%1%)");
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
inline typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type cyl_bessel_k_prime(T1 v, T2 x)
|
||||
{
|
||||
return cyl_bessel_k_prime(v, x, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T1, class T2, class Policy>
|
||||
inline typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_neumann_prime(T1 v, T2 x, const Policy& /* pol */)
|
||||
{
|
||||
BOOST_FPU_EXCEPTION_GUARD
|
||||
typedef typename detail::bessel_traits<T1, T2, Policy>::result_type result_type;
|
||||
typedef typename detail::bessel_traits<T1, T2, Policy>::optimisation_tag tag_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;
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_neumann_prime_imp<tag_type, value_type>(static_cast<value_type>(v), static_cast<value_type>(x), forwarding_policy()), "boost::math::cyl_neumann_prime<%1%,%1%>(%1%,%1%)");
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
inline typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type cyl_neumann_prime(T1 v, T2 x)
|
||||
{
|
||||
return cyl_neumann_prime(v, x, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline typename detail::bessel_traits<T, T, Policy>::result_type sph_neumann_prime(unsigned v, T x, const Policy& /* pol */)
|
||||
{
|
||||
BOOST_FPU_EXCEPTION_GUARD
|
||||
typedef typename detail::bessel_traits<T, T, Policy>::result_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;
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(detail::sph_neumann_prime_imp<value_type>(v, static_cast<value_type>(x), forwarding_policy()), "boost::math::sph_neumann_prime<%1%>(%1%,%1%)");
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typename detail::bessel_traits<T, T, policies::policy<> >::result_type sph_neumann_prime(unsigned v, T x)
|
||||
{
|
||||
return sph_neumann_prime(v, x, policies::policy<>());
|
||||
}
|
||||
|
||||
} // namespace math
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_MATH_BESSEL_DERIVATIVES_HPP
|
||||
1596
code_isotrope/boost/math/special_functions/beta.hpp
Executable file
1596
code_isotrope/boost/math/special_functions/beta.hpp
Executable file
File diff suppressed because it is too large
Load Diff
82
code_isotrope/boost/math/special_functions/binomial.hpp
Executable file
82
code_isotrope/boost/math/special_functions/binomial.hpp
Executable file
@@ -0,0 +1,82 @@
|
||||
// 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_BINOMIAL_HPP
|
||||
#define BOOST_MATH_SF_BINOMIAL_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/math/special_functions/factorials.hpp>
|
||||
#include <boost/math/special_functions/beta.hpp>
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
|
||||
namespace boost{ namespace math{
|
||||
|
||||
template <class T, class Policy>
|
||||
T binomial_coefficient(unsigned n, unsigned k, const Policy& pol)
|
||||
{
|
||||
BOOST_STATIC_ASSERT(!boost::is_integral<T>::value);
|
||||
BOOST_MATH_STD_USING
|
||||
static const char* function = "boost::math::binomial_coefficient<%1%>(unsigned, unsigned)";
|
||||
if(k > n)
|
||||
return policies::raise_domain_error<T>(
|
||||
function,
|
||||
"The binomial coefficient is undefined for k > n, but got k = %1%.",
|
||||
static_cast<T>(k), pol);
|
||||
T result;
|
||||
if((k == 0) || (k == n))
|
||||
return static_cast<T>(1);
|
||||
if((k == 1) || (k == n-1))
|
||||
return static_cast<T>(n);
|
||||
|
||||
if(n <= max_factorial<T>::value)
|
||||
{
|
||||
// Use fast table lookup:
|
||||
result = unchecked_factorial<T>(n);
|
||||
result /= unchecked_factorial<T>(n-k);
|
||||
result /= unchecked_factorial<T>(k);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use the beta function:
|
||||
if(k < n - k)
|
||||
result = k * beta(static_cast<T>(k), static_cast<T>(n-k+1), pol);
|
||||
else
|
||||
result = (n - k) * beta(static_cast<T>(k+1), static_cast<T>(n-k), pol);
|
||||
if(result == 0)
|
||||
return policies::raise_overflow_error<T>(function, 0, pol);
|
||||
result = 1 / result;
|
||||
}
|
||||
// convert to nearest integer:
|
||||
return ceil(result - 0.5f);
|
||||
}
|
||||
//
|
||||
// Type float can only store the first 35 factorials, in order to
|
||||
// increase the chance that we can use a table driven implementation
|
||||
// we'll promote to double:
|
||||
//
|
||||
template <>
|
||||
inline float binomial_coefficient<float, policies::policy<> >(unsigned n, unsigned k, const policies::policy<>& pol)
|
||||
{
|
||||
return policies::checked_narrowing_cast<float, policies::policy<> >(binomial_coefficient<double>(n, k, pol), "boost::math::binomial_coefficient<%1%>(unsigned,unsigned)");
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T binomial_coefficient(unsigned n, unsigned k)
|
||||
{
|
||||
return binomial_coefficient<T>(n, k, policies::policy<>());
|
||||
}
|
||||
|
||||
} // namespace math
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif // BOOST_MATH_SF_BINOMIAL_HPP
|
||||
|
||||
|
||||
|
||||
179
code_isotrope/boost/math/special_functions/cbrt.hpp
Executable file
179
code_isotrope/boost/math/special_functions/cbrt.hpp
Executable file
@@ -0,0 +1,179 @@
|
||||
// (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_CBRT_HPP
|
||||
#define BOOST_MATH_SF_CBRT_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/tools/rational.hpp>
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/math/special_functions/fpclassify.hpp>
|
||||
#include <boost/mpl/divides.hpp>
|
||||
#include <boost/mpl/plus.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
|
||||
namespace boost{ namespace math{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
struct big_int_type
|
||||
{
|
||||
operator boost::uintmax_t()const;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct largest_cbrt_int_type
|
||||
{
|
||||
typedef typename mpl::if_<
|
||||
boost::is_convertible<big_int_type, T>,
|
||||
boost::uintmax_t,
|
||||
unsigned int
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template <class T, class Policy>
|
||||
T cbrt_imp(T z, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
//
|
||||
// cbrt approximation for z in the range [0.5,1]
|
||||
// It's hard to say what number of terms gives the optimum
|
||||
// trade off between precision and performance, this seems
|
||||
// to be about the best for double precision.
|
||||
//
|
||||
// Maximum Deviation Found: 1.231e-006
|
||||
// Expected Error Term: -1.231e-006
|
||||
// Maximum Relative Change in Control Points: 5.982e-004
|
||||
//
|
||||
static const T P[] = {
|
||||
static_cast<T>(0.37568269008611818),
|
||||
static_cast<T>(1.3304968705558024),
|
||||
static_cast<T>(-1.4897101632445036),
|
||||
static_cast<T>(1.2875573098219835),
|
||||
static_cast<T>(-0.6398703759826468),
|
||||
static_cast<T>(0.13584489959258635),
|
||||
};
|
||||
static const T correction[] = {
|
||||
static_cast<T>(0.62996052494743658238360530363911), // 2^-2/3
|
||||
static_cast<T>(0.79370052598409973737585281963615), // 2^-1/3
|
||||
static_cast<T>(1),
|
||||
static_cast<T>(1.2599210498948731647672106072782), // 2^1/3
|
||||
static_cast<T>(1.5874010519681994747517056392723), // 2^2/3
|
||||
};
|
||||
if((boost::math::isinf)(z) || (z == 0))
|
||||
return z;
|
||||
if(!(boost::math::isfinite)(z))
|
||||
{
|
||||
return policies::raise_domain_error("boost::math::cbrt<%1%>(%1%)", "Argument to function must be finite but got %1%.", z, pol);
|
||||
}
|
||||
|
||||
int i_exp, sign(1);
|
||||
if(z < 0)
|
||||
{
|
||||
z = -z;
|
||||
sign = -sign;
|
||||
}
|
||||
|
||||
T guess = frexp(z, &i_exp);
|
||||
int original_i_exp = i_exp; // save for later
|
||||
guess = tools::evaluate_polynomial(P, guess);
|
||||
int i_exp3 = i_exp / 3;
|
||||
|
||||
typedef typename largest_cbrt_int_type<T>::type shift_type;
|
||||
|
||||
BOOST_STATIC_ASSERT( ::std::numeric_limits<shift_type>::radix == 2);
|
||||
|
||||
if(abs(i_exp3) < std::numeric_limits<shift_type>::digits)
|
||||
{
|
||||
if(i_exp3 > 0)
|
||||
guess *= shift_type(1u) << i_exp3;
|
||||
else
|
||||
guess /= shift_type(1u) << -i_exp3;
|
||||
}
|
||||
else
|
||||
{
|
||||
guess = ldexp(guess, i_exp3);
|
||||
}
|
||||
i_exp %= 3;
|
||||
guess *= correction[i_exp + 2];
|
||||
//
|
||||
// Now inline Halley iteration.
|
||||
// We do this here rather than calling tools::halley_iterate since we can
|
||||
// simplify the expressions algebraically, and don't need most of the error
|
||||
// checking of the boilerplate version as we know in advance that the function
|
||||
// is well behaved...
|
||||
//
|
||||
typedef typename policies::precision<T, Policy>::type prec;
|
||||
typedef typename mpl::divides<prec, mpl::int_<3> >::type prec3;
|
||||
typedef typename mpl::plus<prec3, mpl::int_<3> >::type new_prec;
|
||||
typedef typename policies::normalise<Policy, policies::digits2<new_prec::value> >::type new_policy;
|
||||
//
|
||||
// Epsilon calculation uses compile time arithmetic when it's available for type T,
|
||||
// otherwise uses ldexp to calculate at runtime:
|
||||
//
|
||||
T eps = (new_prec::value > 3) ? policies::get_epsilon<T, new_policy>() : ldexp(T(1), -2 - tools::digits<T>() / 3);
|
||||
T diff;
|
||||
|
||||
if(original_i_exp < std::numeric_limits<T>::max_exponent - 3)
|
||||
{
|
||||
//
|
||||
// Safe from overflow, use the fast method:
|
||||
//
|
||||
do
|
||||
{
|
||||
T g3 = guess * guess * guess;
|
||||
diff = (g3 + z + z) / (g3 + g3 + z);
|
||||
guess *= diff;
|
||||
}
|
||||
while(fabs(1 - diff) > eps);
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Either we're ready to overflow, or we can't tell because numeric_limits isn't
|
||||
// available for type T:
|
||||
//
|
||||
do
|
||||
{
|
||||
T g2 = guess * guess;
|
||||
diff = (g2 - z / guess) / (2 * guess + z / g2);
|
||||
guess -= diff;
|
||||
}
|
||||
while((guess * eps) < fabs(diff));
|
||||
}
|
||||
|
||||
return sign * guess;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class T, class Policy>
|
||||
inline typename tools::promote_args<T>::type cbrt(T z, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
return static_cast<result_type>(detail::cbrt_imp(value_type(z), pol));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typename tools::promote_args<T>::type cbrt(T z)
|
||||
{
|
||||
return cbrt(z, policies::policy<>());
|
||||
}
|
||||
|
||||
} // namespace math
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_MATH_SF_CBRT_HPP
|
||||
|
||||
|
||||
|
||||
|
||||
169
code_isotrope/boost/math/special_functions/chebyshev.hpp
Executable file
169
code_isotrope/boost/math/special_functions/chebyshev.hpp
Executable file
@@ -0,0 +1,169 @@
|
||||
// (C) Copyright Nick Thompson 2017.
|
||||
// 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_CHEBYSHEV_HPP
|
||||
#define BOOST_MATH_SPECIAL_CHEBYSHEV_HPP
|
||||
#include <cmath>
|
||||
#include <boost/math/constants/constants.hpp>
|
||||
|
||||
#if (__cplusplus > 201103) || (defined(_CPPLIB_VER) && (_CPPLIB_VER >= 610))
|
||||
# define BOOST_MATH_CHEB_USE_STD_ACOSH
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_MATH_CHEB_USE_STD_ACOSH
|
||||
# include <boost/math/special_functions/acosh.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost { namespace math {
|
||||
|
||||
template<class T1, class T2, class T3>
|
||||
inline typename tools::promote_args<T1, T2, T3>::type chebyshev_next(T1 const & x, T2 const & Tn, T3 const & Tn_1)
|
||||
{
|
||||
return 2*x*Tn - Tn_1;
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<class Real, bool second>
|
||||
inline Real chebyshev_imp(unsigned n, Real const & x)
|
||||
{
|
||||
#ifdef BOOST_MATH_CHEB_USE_STD_ACOSH
|
||||
using std::acosh;
|
||||
#else
|
||||
using boost::math::acosh;
|
||||
#endif
|
||||
using std::cosh;
|
||||
using std::pow;
|
||||
using std::sqrt;
|
||||
Real T0 = 1;
|
||||
Real T1;
|
||||
if (second)
|
||||
{
|
||||
if (x > 1 || x < -1)
|
||||
{
|
||||
Real t = sqrt(x*x -1);
|
||||
return static_cast<Real>((pow(x+t, (int)(n+1)) - pow(x-t, (int)(n+1)))/(2*t));
|
||||
}
|
||||
T1 = 2*x;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (x > 1)
|
||||
{
|
||||
return cosh(n*acosh(x));
|
||||
}
|
||||
if (x < -1)
|
||||
{
|
||||
if (n & 1)
|
||||
{
|
||||
return -cosh(n*acosh(-x));
|
||||
}
|
||||
else
|
||||
{
|
||||
return cosh(n*acosh(-x));
|
||||
}
|
||||
}
|
||||
T1 = x;
|
||||
}
|
||||
|
||||
if (n == 0)
|
||||
{
|
||||
return T0;
|
||||
}
|
||||
|
||||
unsigned l = 1;
|
||||
while(l < n)
|
||||
{
|
||||
std::swap(T0, T1);
|
||||
T1 = boost::math::chebyshev_next(x, T0, T1);
|
||||
++l;
|
||||
}
|
||||
return T1;
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
template <class Real, class Policy>
|
||||
inline typename tools::promote_args<Real>::type
|
||||
chebyshev_t(unsigned n, Real const & x, const Policy&)
|
||||
{
|
||||
typedef typename tools::promote_args<Real>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(detail::chebyshev_imp<value_type, false>(n, static_cast<value_type>(x)), "boost::math::chebyshev_t<%1%>(unsigned, %1%)");
|
||||
}
|
||||
|
||||
template<class Real>
|
||||
inline typename tools::promote_args<Real>::type chebyshev_t(unsigned n, Real const & x)
|
||||
{
|
||||
return chebyshev_t(n, x, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class Real, class Policy>
|
||||
inline typename tools::promote_args<Real>::type
|
||||
chebyshev_u(unsigned n, Real const & x, const Policy&)
|
||||
{
|
||||
typedef typename tools::promote_args<Real>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(detail::chebyshev_imp<value_type, true>(n, static_cast<value_type>(x)), "boost::math::chebyshev_u<%1%>(unsigned, %1%)");
|
||||
}
|
||||
|
||||
template<class Real>
|
||||
inline typename tools::promote_args<Real>::type chebyshev_u(unsigned n, Real const & x)
|
||||
{
|
||||
return chebyshev_u(n, x, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class Real, class Policy>
|
||||
inline typename tools::promote_args<Real>::type
|
||||
chebyshev_t_prime(unsigned n, Real const & x, const Policy&)
|
||||
{
|
||||
typedef typename tools::promote_args<Real>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
if (n == 0)
|
||||
{
|
||||
return result_type(0);
|
||||
}
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(n * detail::chebyshev_imp<value_type, true>(n - 1, static_cast<value_type>(x)), "boost::math::chebyshev_t_prime<%1%>(unsigned, %1%)");
|
||||
}
|
||||
|
||||
template<class Real>
|
||||
inline typename tools::promote_args<Real>::type chebyshev_t_prime(unsigned n, Real const & x)
|
||||
{
|
||||
return chebyshev_t_prime(n, x, policies::policy<>());
|
||||
}
|
||||
|
||||
/*
|
||||
* This is Algorithm 3.1 of
|
||||
* Gil, Amparo, Javier Segura, and Nico M. Temme.
|
||||
* Numerical methods for special functions.
|
||||
* Society for Industrial and Applied Mathematics, 2007.
|
||||
* https://www.siam.org/books/ot99/OT99SampleChapter.pdf
|
||||
* However, our definition of c0 differs by a factor of 1/2, as stated in the docs. . .
|
||||
*/
|
||||
template<class Real, class T2>
|
||||
inline Real chebyshev_clenshaw_recurrence(const Real* const c, size_t length, const T2& x)
|
||||
{
|
||||
using boost::math::constants::half;
|
||||
if (length < 2)
|
||||
{
|
||||
if (length == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return c[0]/2;
|
||||
}
|
||||
Real b2 = 0;
|
||||
Real b1 = c[length -1];
|
||||
for(size_t j = length - 2; j >= 1; --j)
|
||||
{
|
||||
Real tmp = 2*x*b1 - b2 + c[j];
|
||||
b2 = b1;
|
||||
b1 = tmp;
|
||||
}
|
||||
return x*b1 - b2 + half<Real>()*c[0];
|
||||
}
|
||||
|
||||
|
||||
}}
|
||||
#endif
|
||||
237
code_isotrope/boost/math/special_functions/chebyshev_transform.hpp
Executable file
237
code_isotrope/boost/math/special_functions/chebyshev_transform.hpp
Executable file
@@ -0,0 +1,237 @@
|
||||
// (C) Copyright Nick Thompson 2017.
|
||||
// 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_CHEBYSHEV_TRANSFORM_HPP
|
||||
#define BOOST_MATH_SPECIAL_CHEBYSHEV_TRANSFORM_HPP
|
||||
#include <cmath>
|
||||
#include <type_traits>
|
||||
#include <fftw3.h>
|
||||
#include <boost/math/constants/constants.hpp>
|
||||
#include <boost/math/special_functions/chebyshev.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_FLOAT128
|
||||
#include <quadmath.h>
|
||||
#endif
|
||||
|
||||
namespace boost { namespace math {
|
||||
|
||||
namespace detail{
|
||||
|
||||
template <class T>
|
||||
struct fftw_cos_transform;
|
||||
|
||||
template<>
|
||||
struct fftw_cos_transform<double>
|
||||
{
|
||||
fftw_cos_transform(int n, double* data1, double* data2)
|
||||
{
|
||||
plan = fftw_plan_r2r_1d(n, data1, data2, FFTW_REDFT10, FFTW_ESTIMATE);
|
||||
}
|
||||
~fftw_cos_transform()
|
||||
{
|
||||
fftw_destroy_plan(plan);
|
||||
}
|
||||
void execute(double* data1, double* data2)
|
||||
{
|
||||
fftw_execute_r2r(plan, data1, data2);
|
||||
}
|
||||
static double cos(double x) { return std::cos(x); }
|
||||
static double fabs(double x) { return std::fabs(x); }
|
||||
private:
|
||||
fftw_plan plan;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct fftw_cos_transform<float>
|
||||
{
|
||||
fftw_cos_transform(int n, float* data1, float* data2)
|
||||
{
|
||||
plan = fftwf_plan_r2r_1d(n, data1, data2, FFTW_REDFT10, FFTW_ESTIMATE);
|
||||
}
|
||||
~fftw_cos_transform()
|
||||
{
|
||||
fftwf_destroy_plan(plan);
|
||||
}
|
||||
void execute(float* data1, float* data2)
|
||||
{
|
||||
fftwf_execute_r2r(plan, data1, data2);
|
||||
}
|
||||
static float cos(float x) { return std::cos(x); }
|
||||
static float fabs(float x) { return std::fabs(x); }
|
||||
private:
|
||||
fftwf_plan plan;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct fftw_cos_transform<long double>
|
||||
{
|
||||
fftw_cos_transform(int n, long double* data1, long double* data2)
|
||||
{
|
||||
plan = fftwl_plan_r2r_1d(n, data1, data2, FFTW_REDFT10, FFTW_ESTIMATE);
|
||||
}
|
||||
~fftw_cos_transform()
|
||||
{
|
||||
fftwl_destroy_plan(plan);
|
||||
}
|
||||
void execute(long double* data1, long double* data2)
|
||||
{
|
||||
fftwl_execute_r2r(plan, data1, data2);
|
||||
}
|
||||
static long double cos(long double x) { return std::cos(x); }
|
||||
static long double fabs(long double x) { return std::fabs(x); }
|
||||
private:
|
||||
fftwl_plan plan;
|
||||
};
|
||||
#ifdef BOOST_HAS_FLOAT128
|
||||
template<>
|
||||
struct fftw_cos_transform<__float128>
|
||||
{
|
||||
fftw_cos_transform(int n, __float128* data1, __float128* data2)
|
||||
{
|
||||
plan = fftwq_plan_r2r_1d(n, data1, data2, FFTW_REDFT10, FFTW_ESTIMATE);
|
||||
}
|
||||
~fftw_cos_transform()
|
||||
{
|
||||
fftwq_destroy_plan(plan);
|
||||
}
|
||||
void execute(__float128* data1, __float128* data2)
|
||||
{
|
||||
fftwq_execute_r2r(plan, data1, data2);
|
||||
}
|
||||
static __float128 cos(__float128 x) { return cosq(x); }
|
||||
static __float128 fabs(__float128 x) { return fabsq(x); }
|
||||
private:
|
||||
fftwq_plan plan;
|
||||
};
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class Real>
|
||||
class chebyshev_transform
|
||||
{
|
||||
public:
|
||||
template<class F>
|
||||
chebyshev_transform(const F& f, Real a, Real b,
|
||||
Real tol = 500 * std::numeric_limits<Real>::epsilon(),
|
||||
size_t max_refinements = 15) : m_a(a), m_b(b)
|
||||
{
|
||||
if (a >= b)
|
||||
{
|
||||
throw std::domain_error("a < b is required.\n");
|
||||
}
|
||||
using boost::math::constants::half;
|
||||
using boost::math::constants::pi;
|
||||
using std::cos;
|
||||
using std::abs;
|
||||
Real bma = (b-a)*half<Real>();
|
||||
Real bpa = (b+a)*half<Real>();
|
||||
size_t n = 256;
|
||||
std::vector<Real> vf;
|
||||
|
||||
size_t refinements = 0;
|
||||
while(refinements < max_refinements)
|
||||
{
|
||||
vf.resize(n);
|
||||
m_coeffs.resize(n);
|
||||
|
||||
detail::fftw_cos_transform<Real> plan(static_cast<int>(n), vf.data(), m_coeffs.data());
|
||||
Real inv_n = 1/static_cast<Real>(n);
|
||||
for(size_t j = 0; j < n/2; ++j)
|
||||
{
|
||||
// Use symmetry cos((j+1/2)pi/n) = - cos((n-1-j+1/2)pi/n)
|
||||
Real y = detail::fftw_cos_transform<Real>::cos(pi<Real>()*(j+half<Real>())*inv_n);
|
||||
vf[j] = f(y*bma + bpa)*inv_n;
|
||||
vf[n-1-j]= f(bpa-y*bma)*inv_n;
|
||||
}
|
||||
|
||||
plan.execute(vf.data(), m_coeffs.data());
|
||||
Real max_coeff = 0;
|
||||
for (auto const & coeff : m_coeffs)
|
||||
{
|
||||
if (detail::fftw_cos_transform<Real>::fabs(coeff) > max_coeff)
|
||||
{
|
||||
max_coeff = detail::fftw_cos_transform<Real>::fabs(coeff);
|
||||
}
|
||||
}
|
||||
size_t j = m_coeffs.size() - 1;
|
||||
while (abs(m_coeffs[j])/max_coeff < tol)
|
||||
{
|
||||
--j;
|
||||
}
|
||||
// If ten coefficients are eliminated, the we say we've done all
|
||||
// we need to do:
|
||||
if (n - j > 10)
|
||||
{
|
||||
m_coeffs.resize(j+1);
|
||||
return;
|
||||
}
|
||||
|
||||
n *= 2;
|
||||
++refinements;
|
||||
}
|
||||
}
|
||||
|
||||
Real operator()(Real x) const
|
||||
{
|
||||
using boost::math::constants::half;
|
||||
if (x > m_b || x < m_a)
|
||||
{
|
||||
throw std::domain_error("x not in [a, b]\n");
|
||||
}
|
||||
|
||||
Real z = (2*x - m_a - m_b)/(m_b - m_a);
|
||||
return chebyshev_clenshaw_recurrence(m_coeffs.data(), m_coeffs.size(), z);
|
||||
}
|
||||
|
||||
// Integral over entire domain [a, b]
|
||||
Real integrate() const
|
||||
{
|
||||
Real Q = m_coeffs[0]/2;
|
||||
for(size_t j = 2; j < m_coeffs.size(); j += 2)
|
||||
{
|
||||
Q += -m_coeffs[j]/((j+1)*(j-1));
|
||||
}
|
||||
return (m_b - m_a)*Q;
|
||||
}
|
||||
|
||||
const std::vector<Real>& coefficients() const
|
||||
{
|
||||
return m_coeffs;
|
||||
}
|
||||
|
||||
Real prime(Real x) const
|
||||
{
|
||||
Real z = (2*x - m_a - m_b)/(m_b - m_a);
|
||||
Real dzdx = 2/(m_b - m_a);
|
||||
if (m_coeffs.size() < 2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
Real b2 = 0;
|
||||
Real d2 = 0;
|
||||
Real b1 = m_coeffs[m_coeffs.size() -1];
|
||||
Real d1 = 0;
|
||||
for(size_t j = m_coeffs.size() - 2; j >= 1; --j)
|
||||
{
|
||||
Real tmp1 = 2*z*b1 - b2 + m_coeffs[j];
|
||||
Real tmp2 = 2*z*d1 - d2 + 2*b1;
|
||||
b2 = b1;
|
||||
b1 = tmp1;
|
||||
|
||||
d2 = d1;
|
||||
d1 = tmp2;
|
||||
}
|
||||
return dzdx*(z*d1 - d2 + b1);
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<Real> m_coeffs;
|
||||
Real m_a;
|
||||
Real m_b;
|
||||
};
|
||||
|
||||
}}
|
||||
#endif
|
||||
82
code_isotrope/boost/math/special_functions/cos_pi.hpp
Executable file
82
code_isotrope/boost/math/special_functions/cos_pi.hpp
Executable file
@@ -0,0 +1,82 @@
|
||||
// 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)
|
||||
|
||||
#ifndef BOOST_MATH_COS_PI_HPP
|
||||
#define BOOST_MATH_COS_PI_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/config/no_tr1/cmath.hpp>
|
||||
#include <boost/math/tools/config.hpp>
|
||||
#include <boost/math/special_functions/trunc.hpp>
|
||||
#include <boost/math/tools/promotion.hpp>
|
||||
#include <boost/math/constants/constants.hpp>
|
||||
|
||||
namespace boost{ namespace math{ namespace detail{
|
||||
|
||||
template <class T, class Policy>
|
||||
T cos_pi_imp(T x, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING // ADL of std names
|
||||
// cos of pi*x:
|
||||
bool invert = false;
|
||||
if(fabs(x) < 0.25)
|
||||
return cos(constants::pi<T>() * x);
|
||||
|
||||
if(x < 0)
|
||||
{
|
||||
x = -x;
|
||||
}
|
||||
T rem = floor(x);
|
||||
if(itrunc(rem, pol) & 1)
|
||||
invert = !invert;
|
||||
rem = x - rem;
|
||||
if(rem > 0.5f)
|
||||
{
|
||||
rem = 1 - rem;
|
||||
invert = !invert;
|
||||
}
|
||||
if(rem == 0.5f)
|
||||
return 0;
|
||||
|
||||
if(rem > 0.25f)
|
||||
{
|
||||
rem = 0.5f - rem;
|
||||
rem = sin(constants::pi<T>() * rem);
|
||||
}
|
||||
else
|
||||
rem = cos(constants::pi<T>() * rem);
|
||||
return invert ? T(-rem) : rem;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class T, class Policy>
|
||||
inline typename tools::promote_args<T>::type cos_pi(T x, const Policy&)
|
||||
{
|
||||
typedef typename tools::promote_args<T>::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;
|
||||
return policies::checked_narrowing_cast<result_type, forwarding_policy>(boost::math::detail::cos_pi_imp<value_type>(x, forwarding_policy()), "cos_pi");
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typename tools::promote_args<T>::type cos_pi(T x)
|
||||
{
|
||||
return boost::math::cos_pi(x, policies::policy<>());
|
||||
}
|
||||
|
||||
} // namespace math
|
||||
} // namespace boost
|
||||
#endif
|
||||
|
||||
160
code_isotrope/boost/math/special_functions/detail/airy_ai_bi_zero.hpp
Executable file
160
code_isotrope/boost/math/special_functions/detail/airy_ai_bi_zero.hpp
Executable file
@@ -0,0 +1,160 @@
|
||||
// Copyright (c) 2013 Christopher Kormanyos
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// This work is based on an earlier work:
|
||||
// "Algorithm 910: A Portable C++ Multiple-Precision System for Special-Function Calculations",
|
||||
// in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. http://doi.acm.org/10.1145/1916461.1916469
|
||||
//
|
||||
// This header contains implementation details for estimating the zeros
|
||||
// of the Airy functions airy_ai and airy_bi on the negative real axis.
|
||||
//
|
||||
#ifndef _AIRY_AI_BI_ZERO_2013_01_20_HPP_
|
||||
#define _AIRY_AI_BI_ZERO_2013_01_20_HPP_
|
||||
|
||||
#include <boost/math/constants/constants.hpp>
|
||||
#include <boost/math/special_functions/cbrt.hpp>
|
||||
|
||||
namespace boost { namespace math {
|
||||
namespace detail
|
||||
{
|
||||
// Forward declarations of the needed Airy function implementations.
|
||||
template <class T, class Policy>
|
||||
T airy_ai_imp(T x, const Policy& pol);
|
||||
template <class T, class Policy>
|
||||
T airy_bi_imp(T x, const Policy& pol);
|
||||
template <class T, class Policy>
|
||||
T airy_ai_prime_imp(T x, const Policy& pol);
|
||||
template <class T, class Policy>
|
||||
T airy_bi_prime_imp(T x, const Policy& pol);
|
||||
|
||||
namespace airy_zero
|
||||
{
|
||||
template<class T>
|
||||
T equation_as_10_4_105(const T& z)
|
||||
{
|
||||
const T one_over_z (T(1) / z);
|
||||
const T one_over_z_squared(one_over_z * one_over_z);
|
||||
|
||||
const T z_pow_third (boost::math::cbrt(z));
|
||||
const T z_pow_two_thirds(z_pow_third * z_pow_third);
|
||||
|
||||
// Implement the top line of Eq. 10.4.105.
|
||||
const T fz(z_pow_two_thirds * ((((( + (T(162375596875.0) / 334430208UL)
|
||||
* one_over_z_squared - ( T(108056875.0) / 6967296UL))
|
||||
* one_over_z_squared + ( T(77125UL) / 82944UL))
|
||||
* one_over_z_squared - ( T(5U) / 36U))
|
||||
* one_over_z_squared + ( T(5U) / 48U))
|
||||
* one_over_z_squared + (1)));
|
||||
|
||||
return fz;
|
||||
}
|
||||
|
||||
namespace airy_ai_zero_detail
|
||||
{
|
||||
template<class T>
|
||||
T initial_guess(const int m)
|
||||
{
|
||||
T guess;
|
||||
|
||||
switch(m)
|
||||
{
|
||||
case 0: { guess = T(0); break; }
|
||||
case 1: { guess = T(-2.33810741045976703849); break; }
|
||||
case 2: { guess = T(-4.08794944413097061664); break; }
|
||||
case 3: { guess = T(-5.52055982809555105913); break; }
|
||||
case 4: { guess = T(-6.78670809007175899878); break; }
|
||||
case 5: { guess = T(-7.94413358712085312314); break; }
|
||||
case 6: { guess = T(-9.02265085334098038016); break; }
|
||||
case 7: { guess = T(-10.0401743415580859306); break; }
|
||||
case 8: { guess = T(-11.0085243037332628932); break; }
|
||||
case 9: { guess = T(-11.9360155632362625170); break; }
|
||||
case 10:{ guess = T(-12.8287767528657572004); break; }
|
||||
default:
|
||||
{
|
||||
const T t(((boost::math::constants::pi<T>() * 3) * ((T(m) * 4) - 1)) / 8);
|
||||
guess = -boost::math::detail::airy_zero::equation_as_10_4_105(t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return guess;
|
||||
}
|
||||
|
||||
template<class T, class Policy>
|
||||
class function_object_ai_and_ai_prime
|
||||
{
|
||||
public:
|
||||
function_object_ai_and_ai_prime(const Policy& pol) : my_pol(pol) { }
|
||||
|
||||
boost::math::tuple<T, T> operator()(const T& x) const
|
||||
{
|
||||
// Return a tuple containing both Ai(x) and Ai'(x).
|
||||
return boost::math::make_tuple(
|
||||
boost::math::detail::airy_ai_imp (x, my_pol),
|
||||
boost::math::detail::airy_ai_prime_imp(x, my_pol));
|
||||
}
|
||||
|
||||
private:
|
||||
const Policy& my_pol;
|
||||
const function_object_ai_and_ai_prime& operator=(const function_object_ai_and_ai_prime&);
|
||||
};
|
||||
} // namespace airy_ai_zero_detail
|
||||
|
||||
namespace airy_bi_zero_detail
|
||||
{
|
||||
template<class T>
|
||||
T initial_guess(const int m)
|
||||
{
|
||||
T guess;
|
||||
|
||||
switch(m)
|
||||
{
|
||||
case 0: { guess = T(0); break; }
|
||||
case 1: { guess = T(-1.17371322270912792492); break; }
|
||||
case 2: { guess = T(-3.27109330283635271568); break; }
|
||||
case 3: { guess = T(-4.83073784166201593267); break; }
|
||||
case 4: { guess = T(-6.16985212831025125983); break; }
|
||||
case 5: { guess = T(-7.37676207936776371360); break; }
|
||||
case 6: { guess = T(-8.49194884650938801345); break; }
|
||||
case 7: { guess = T(-9.53819437934623888663); break; }
|
||||
case 8: { guess = T(-10.5299135067053579244); break; }
|
||||
case 9: { guess = T(-11.4769535512787794379); break; }
|
||||
case 10: { guess = T(-12.3864171385827387456); break; }
|
||||
default:
|
||||
{
|
||||
const T t(((boost::math::constants::pi<T>() * 3) * ((T(m) * 4) - 3)) / 8);
|
||||
guess = -boost::math::detail::airy_zero::equation_as_10_4_105(t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return guess;
|
||||
}
|
||||
|
||||
template<class T, class Policy>
|
||||
class function_object_bi_and_bi_prime
|
||||
{
|
||||
public:
|
||||
function_object_bi_and_bi_prime(const Policy& pol) : my_pol(pol) { }
|
||||
|
||||
boost::math::tuple<T, T> operator()(const T& x) const
|
||||
{
|
||||
// Return a tuple containing both Bi(x) and Bi'(x).
|
||||
return boost::math::make_tuple(
|
||||
boost::math::detail::airy_bi_imp (x, my_pol),
|
||||
boost::math::detail::airy_bi_prime_imp(x, my_pol));
|
||||
}
|
||||
|
||||
private:
|
||||
const Policy& my_pol;
|
||||
const function_object_bi_and_bi_prime& operator=(const function_object_bi_and_bi_prime&);
|
||||
};
|
||||
} // namespace airy_bi_zero_detail
|
||||
} // namespace airy_zero
|
||||
} // namespace detail
|
||||
} // namespace math
|
||||
} // namespaces boost
|
||||
|
||||
#endif // _AIRY_AI_BI_ZERO_2013_01_20_HPP_
|
||||
665
code_isotrope/boost/math/special_functions/detail/bernoulli_details.hpp
Executable file
665
code_isotrope/boost/math/special_functions/detail/bernoulli_details.hpp
Executable file
@@ -0,0 +1,665 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright 2013 John Maddock
|
||||
// Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_MATH_BERNOULLI_DETAIL_HPP
|
||||
#define BOOST_MATH_BERNOULLI_DETAIL_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/detail/lightweight_mutex.hpp>
|
||||
#include <boost/math/tools/atomic.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/math/tools/toms748_solve.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace boost{ namespace math{ namespace detail{
|
||||
//
|
||||
// Asymptotic expansion for B2n due to
|
||||
// Luschny LogB3 formula (http://www.luschny.de/math/primes/bernincl.html)
|
||||
//
|
||||
template <class T, class Policy>
|
||||
T b2n_asymptotic(int n)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
const T nx = static_cast<T>(n);
|
||||
const T nx2(nx * nx);
|
||||
|
||||
const T approximate_log_of_bernoulli_bn =
|
||||
((boost::math::constants::half<T>() + nx) * log(nx))
|
||||
+ ((boost::math::constants::half<T>() - nx) * log(boost::math::constants::pi<T>()))
|
||||
+ (((T(3) / 2) - nx) * boost::math::constants::ln_two<T>())
|
||||
+ ((nx * (T(2) - (nx2 * 7) * (1 + ((nx2 * 30) * ((nx2 * 12) - 1))))) / (((nx2 * nx2) * nx2) * 2520));
|
||||
return ((n / 2) & 1 ? 1 : -1) * (approximate_log_of_bernoulli_bn > tools::log_max_value<T>()
|
||||
? policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, nx, Policy())
|
||||
: static_cast<T>(exp(approximate_log_of_bernoulli_bn)));
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
T t2n_asymptotic(int n)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
// Just get B2n and convert to a Tangent number:
|
||||
T t2n = fabs(b2n_asymptotic<T, Policy>(2 * n)) / (2 * n);
|
||||
T p2 = ldexp(T(1), n);
|
||||
if(tools::max_value<T>() / p2 < t2n)
|
||||
return policies::raise_overflow_error<T>("boost::math::tangent_t2n<%1%>(std::size_t)", 0, T(n), Policy());
|
||||
t2n *= p2;
|
||||
p2 -= 1;
|
||||
if(tools::max_value<T>() / p2 < t2n)
|
||||
return policies::raise_overflow_error<T>("boost::math::tangent_t2n<%1%>(std::size_t)", 0, Policy());
|
||||
t2n *= p2;
|
||||
return t2n;
|
||||
}
|
||||
//
|
||||
// We need to know the approximate value of /n/ which will
|
||||
// cause bernoulli_b2n<T>(n) to return infinity - this allows
|
||||
// us to elude a great deal of runtime checking for values below
|
||||
// n, and only perform the full overflow checks when we know that we're
|
||||
// getting close to the point where our calculations will overflow.
|
||||
// We use Luschny's LogB3 formula (http://www.luschny.de/math/primes/bernincl.html)
|
||||
// to find the limit, and since we're dealing with the log of the Bernoulli numbers
|
||||
// we need only perform the calculation at double precision and not with T
|
||||
// (which may be a multiprecision type). The limit returned is within 1 of the true
|
||||
// limit for all the types tested. Note that although the code below is basically
|
||||
// the same as b2n_asymptotic above, it has been recast as a continuous real-valued
|
||||
// function as this makes the root finding go smoother/faster. It also omits the
|
||||
// sign of the Bernoulli number.
|
||||
//
|
||||
struct max_bernoulli_root_functor
|
||||
{
|
||||
max_bernoulli_root_functor(long long t) : target(static_cast<double>(t)) {}
|
||||
double operator()(double n)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
|
||||
// Luschny LogB3(n) formula.
|
||||
|
||||
const double nx2(n * n);
|
||||
|
||||
const double approximate_log_of_bernoulli_bn
|
||||
= ((boost::math::constants::half<double>() + n) * log(n))
|
||||
+ ((boost::math::constants::half<double>() - n) * log(boost::math::constants::pi<double>()))
|
||||
+ (((double(3) / 2) - n) * boost::math::constants::ln_two<double>())
|
||||
+ ((n * (2 - (nx2 * 7) * (1 + ((nx2 * 30) * ((nx2 * 12) - 1))))) / (((nx2 * nx2) * nx2) * 2520));
|
||||
|
||||
return approximate_log_of_bernoulli_bn - target;
|
||||
}
|
||||
private:
|
||||
double target;
|
||||
};
|
||||
|
||||
template <class T, class Policy>
|
||||
inline std::size_t find_bernoulli_overflow_limit(const mpl::false_&)
|
||||
{
|
||||
long long t = lltrunc(boost::math::tools::log_max_value<T>());
|
||||
max_bernoulli_root_functor fun(t);
|
||||
boost::math::tools::equal_floor tol;
|
||||
boost::uintmax_t max_iter = boost::math::policies::get_max_root_iterations<Policy>();
|
||||
return static_cast<std::size_t>(boost::math::tools::toms748_solve(fun, sqrt(double(t)), double(t), tol, max_iter).first) / 2;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline std::size_t find_bernoulli_overflow_limit(const mpl::true_&)
|
||||
{
|
||||
return max_bernoulli_index<bernoulli_imp_variant<T>::value>::value;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
std::size_t b2n_overflow_limit()
|
||||
{
|
||||
// This routine is called at program startup if it's called at all:
|
||||
// that guarantees safe initialization of the static variable.
|
||||
typedef mpl::bool_<(bernoulli_imp_variant<T>::value >= 1) && (bernoulli_imp_variant<T>::value <= 3)> tag_type;
|
||||
static const std::size_t lim = find_bernoulli_overflow_limit<T, Policy>(tag_type());
|
||||
return lim;
|
||||
}
|
||||
|
||||
//
|
||||
// The tangent numbers grow larger much more rapidly than the Bernoulli numbers do....
|
||||
// so to compute the Bernoulli numbers from the tangent numbers, we need to avoid spurious
|
||||
// overflow in the calculation, we can do this by scaling all the tangent number by some scale factor:
|
||||
//
|
||||
template <class T>
|
||||
inline typename enable_if_c<std::numeric_limits<T>::is_specialized && (std::numeric_limits<T>::radix == 2), T>::type tangent_scale_factor()
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
return ldexp(T(1), std::numeric_limits<T>::min_exponent + 5);
|
||||
}
|
||||
template <class T>
|
||||
inline typename disable_if_c<std::numeric_limits<T>::is_specialized && (std::numeric_limits<T>::radix == 2), T>::type tangent_scale_factor()
|
||||
{
|
||||
return tools::min_value<T>() * 16;
|
||||
}
|
||||
//
|
||||
// Initializer: ensure all our constants are initialized prior to the first call of main:
|
||||
//
|
||||
template <class T, class Policy>
|
||||
struct bernoulli_initializer
|
||||
{
|
||||
struct init
|
||||
{
|
||||
init()
|
||||
{
|
||||
//
|
||||
// We call twice, once to initialize our static table, and once to
|
||||
// initialize our dymanic table:
|
||||
//
|
||||
boost::math::bernoulli_b2n<T>(2, Policy());
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
try{
|
||||
#endif
|
||||
boost::math::bernoulli_b2n<T>(max_bernoulli_b2n<T>::value + 1, Policy());
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
} catch(const std::overflow_error&){}
|
||||
#endif
|
||||
boost::math::tangent_t2n<T>(2, Policy());
|
||||
}
|
||||
void force_instantiate()const{}
|
||||
};
|
||||
static const init initializer;
|
||||
static void force_instantiate()
|
||||
{
|
||||
initializer.force_instantiate();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class Policy>
|
||||
const typename bernoulli_initializer<T, Policy>::init bernoulli_initializer<T, Policy>::initializer;
|
||||
|
||||
//
|
||||
// We need something to act as a cache for our calculated Bernoulli numbers. In order to
|
||||
// ensure both fast access and thread safety, we need a stable table which may be extended
|
||||
// in size, but which never reallocates: that way values already calculated may be accessed
|
||||
// concurrently with another thread extending the table with new values.
|
||||
//
|
||||
// Very very simple vector class that will never allocate more than once, we could use
|
||||
// boost::container::static_vector here, but that allocates on the stack, which may well
|
||||
// cause issues for the amount of memory we want in the extreme case...
|
||||
//
|
||||
template <class T>
|
||||
struct fixed_vector : private std::allocator<T>
|
||||
{
|
||||
typedef unsigned size_type;
|
||||
typedef T* iterator;
|
||||
typedef const T* const_iterator;
|
||||
fixed_vector() : m_used(0)
|
||||
{
|
||||
std::size_t overflow_limit = 5 + b2n_overflow_limit<T, policies::policy<> >();
|
||||
m_capacity = static_cast<unsigned>((std::min)(overflow_limit, static_cast<std::size_t>(100000u)));
|
||||
m_data = this->allocate(m_capacity);
|
||||
}
|
||||
~fixed_vector()
|
||||
{
|
||||
#ifdef BOOST_NO_CXX11_ALLOCATOR
|
||||
for(unsigned i = 0; i < m_used; ++i)
|
||||
this->destroy(&m_data[i]);
|
||||
this->deallocate(m_data, m_capacity);
|
||||
#else
|
||||
typedef std::allocator<T> allocator_type;
|
||||
typedef std::allocator_traits<allocator_type> allocator_traits;
|
||||
allocator_type& alloc = *this;
|
||||
for(unsigned i = 0; i < m_used; ++i)
|
||||
allocator_traits::destroy(alloc, &m_data[i]);
|
||||
allocator_traits::deallocate(alloc, m_data, m_capacity);
|
||||
#endif
|
||||
}
|
||||
T& operator[](unsigned n) { BOOST_ASSERT(n < m_used); return m_data[n]; }
|
||||
const T& operator[](unsigned n)const { BOOST_ASSERT(n < m_used); return m_data[n]; }
|
||||
unsigned size()const { return m_used; }
|
||||
unsigned size() { return m_used; }
|
||||
void resize(unsigned n, const T& val)
|
||||
{
|
||||
if(n > m_capacity)
|
||||
{
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error("Exhausted storage for Bernoulli numbers."));
|
||||
}
|
||||
for(unsigned i = m_used; i < n; ++i)
|
||||
new (m_data + i) T(val);
|
||||
m_used = n;
|
||||
}
|
||||
void resize(unsigned n) { resize(n, T()); }
|
||||
T* begin() { return m_data; }
|
||||
T* end() { return m_data + m_used; }
|
||||
T* begin()const { return m_data; }
|
||||
T* end()const { return m_data + m_used; }
|
||||
unsigned capacity()const { return m_capacity; }
|
||||
void clear() { m_used = 0; }
|
||||
private:
|
||||
T* m_data;
|
||||
unsigned m_used, m_capacity;
|
||||
};
|
||||
|
||||
template <class T, class Policy>
|
||||
class bernoulli_numbers_cache
|
||||
{
|
||||
public:
|
||||
bernoulli_numbers_cache() : m_overflow_limit((std::numeric_limits<std::size_t>::max)())
|
||||
#if defined(BOOST_HAS_THREADS) && !defined(BOOST_MATH_NO_ATOMIC_INT)
|
||||
, m_counter(0)
|
||||
#endif
|
||||
, m_current_precision(boost::math::tools::digits<T>())
|
||||
{}
|
||||
|
||||
typedef fixed_vector<T> container_type;
|
||||
|
||||
void tangent(std::size_t m)
|
||||
{
|
||||
static const std::size_t min_overflow_index = b2n_overflow_limit<T, Policy>() - 1;
|
||||
tn.resize(static_cast<typename container_type::size_type>(m), T(0U));
|
||||
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(min_overflow_index);
|
||||
|
||||
std::size_t prev_size = m_intermediates.size();
|
||||
m_intermediates.resize(m, T(0U));
|
||||
|
||||
if(prev_size == 0)
|
||||
{
|
||||
m_intermediates[1] = tangent_scale_factor<T>() /*T(1U)*/;
|
||||
tn[0U] = T(0U);
|
||||
tn[1U] = tangent_scale_factor<T>()/* T(1U)*/;
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(tn[0]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(tn[1]);
|
||||
}
|
||||
|
||||
for(std::size_t i = std::max<size_t>(2, prev_size); i < m; i++)
|
||||
{
|
||||
bool overflow_check = false;
|
||||
if(i >= min_overflow_index && (boost::math::tools::max_value<T>() / (i-1) < m_intermediates[1]) )
|
||||
{
|
||||
std::fill(tn.begin() + i, tn.end(), boost::math::tools::max_value<T>());
|
||||
break;
|
||||
}
|
||||
m_intermediates[1] = m_intermediates[1] * (i-1);
|
||||
for(std::size_t j = 2; j <= i; j++)
|
||||
{
|
||||
overflow_check =
|
||||
(i >= min_overflow_index) && (
|
||||
(boost::math::tools::max_value<T>() / (i - j) < m_intermediates[j])
|
||||
|| (boost::math::tools::max_value<T>() / (i - j + 2) < m_intermediates[j-1])
|
||||
|| (boost::math::tools::max_value<T>() - m_intermediates[j] * (i - j) < m_intermediates[j-1] * (i - j + 2))
|
||||
|| ((boost::math::isinf)(m_intermediates[j]))
|
||||
);
|
||||
|
||||
if(overflow_check)
|
||||
{
|
||||
std::fill(tn.begin() + i, tn.end(), boost::math::tools::max_value<T>());
|
||||
break;
|
||||
}
|
||||
m_intermediates[j] = m_intermediates[j] * (i - j) + m_intermediates[j-1] * (i - j + 2);
|
||||
}
|
||||
if(overflow_check)
|
||||
break; // already filled the tn...
|
||||
tn[static_cast<typename container_type::size_type>(i)] = m_intermediates[i];
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(i);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(tn[static_cast<typename container_type::size_type>(i)]);
|
||||
}
|
||||
}
|
||||
|
||||
void tangent_numbers_series(const std::size_t m)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
static const std::size_t min_overflow_index = b2n_overflow_limit<T, Policy>() - 1;
|
||||
|
||||
typename container_type::size_type old_size = bn.size();
|
||||
|
||||
tangent(m);
|
||||
bn.resize(static_cast<typename container_type::size_type>(m));
|
||||
|
||||
if(!old_size)
|
||||
{
|
||||
bn[0] = 1;
|
||||
old_size = 1;
|
||||
}
|
||||
|
||||
T power_two(ldexp(T(1), static_cast<int>(2 * old_size)));
|
||||
|
||||
for(std::size_t i = old_size; i < m; i++)
|
||||
{
|
||||
T b(static_cast<T>(i * 2));
|
||||
//
|
||||
// Not only do we need to take care to avoid spurious over/under flow in
|
||||
// the calculation, but we also need to avoid overflow altogether in case
|
||||
// we're calculating with a type where "bad things" happen in that case:
|
||||
//
|
||||
b = b / (power_two * tangent_scale_factor<T>());
|
||||
b /= (power_two - 1);
|
||||
bool overflow_check = (i >= min_overflow_index) && (tools::max_value<T>() / tn[static_cast<typename container_type::size_type>(i)] < b);
|
||||
if(overflow_check)
|
||||
{
|
||||
m_overflow_limit = i;
|
||||
while(i < m)
|
||||
{
|
||||
b = std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity() : tools::max_value<T>();
|
||||
bn[static_cast<typename container_type::size_type>(i)] = ((i % 2U) ? b : T(-b));
|
||||
++i;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
b *= tn[static_cast<typename container_type::size_type>(i)];
|
||||
}
|
||||
|
||||
power_two = ldexp(power_two, 2);
|
||||
|
||||
const bool b_neg = i % 2 == 0;
|
||||
|
||||
bn[static_cast<typename container_type::size_type>(i)] = ((!b_neg) ? b : T(-b));
|
||||
}
|
||||
}
|
||||
|
||||
template <class OutputIterator>
|
||||
OutputIterator copy_bernoulli_numbers(OutputIterator out, std::size_t start, std::size_t n, const Policy& pol)
|
||||
{
|
||||
//
|
||||
// There are basically 3 thread safety options:
|
||||
//
|
||||
// 1) There are no threads (BOOST_HAS_THREADS is not defined).
|
||||
// 2) There are threads, but we do not have a true atomic integer type,
|
||||
// in this case we just use a mutex to guard against race conditions.
|
||||
// 3) There are threads, and we have an atomic integer: in this case we can
|
||||
// use the double-checked locking pattern to avoid thread synchronisation
|
||||
// when accessing values already in the cache.
|
||||
//
|
||||
// First off handle the common case for overflow and/or asymptotic expansion:
|
||||
//
|
||||
if(start + n > bn.capacity())
|
||||
{
|
||||
if(start < bn.capacity())
|
||||
{
|
||||
out = copy_bernoulli_numbers(out, start, bn.capacity() - start, pol);
|
||||
n -= bn.capacity() - start;
|
||||
start = static_cast<std::size_t>(bn.capacity());
|
||||
}
|
||||
if(start < b2n_overflow_limit<T, Policy>() + 2u)
|
||||
{
|
||||
for(; n; ++start, --n)
|
||||
{
|
||||
*out = b2n_asymptotic<T, Policy>(static_cast<typename container_type::size_type>(start * 2U));
|
||||
++out;
|
||||
}
|
||||
}
|
||||
for(; n; ++start, --n)
|
||||
{
|
||||
*out = policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(start), pol);
|
||||
++out;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
#if !defined(BOOST_HAS_THREADS)
|
||||
//
|
||||
// Single threaded code, very simple:
|
||||
//
|
||||
if(m_current_precision < boost::math::tools::digits<T>())
|
||||
{
|
||||
bn.clear();
|
||||
tn.clear();
|
||||
m_intermediates.clear();
|
||||
m_current_precision = boost::math::tools::digits<T>();
|
||||
}
|
||||
if(start + n >= bn.size())
|
||||
{
|
||||
std::size_t new_size = (std::min)((std::max)((std::max)(std::size_t(start + n), std::size_t(bn.size() + 20)), std::size_t(50)), std::size_t(bn.capacity()));
|
||||
tangent_numbers_series(new_size);
|
||||
}
|
||||
|
||||
for(std::size_t i = (std::max)(std::size_t(max_bernoulli_b2n<T>::value + 1), start); i < start + n; ++i)
|
||||
{
|
||||
*out = (i >= m_overflow_limit) ? policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol) : bn[i];
|
||||
++out;
|
||||
}
|
||||
#elif defined(BOOST_MATH_NO_ATOMIC_INT)
|
||||
//
|
||||
// We need to grab a mutex every time we get here, for both readers and writers:
|
||||
//
|
||||
boost::detail::lightweight_mutex::scoped_lock l(m_mutex);
|
||||
if(m_current_precision < boost::math::tools::digits<T>())
|
||||
{
|
||||
bn.clear();
|
||||
tn.clear();
|
||||
m_intermediates.clear();
|
||||
m_current_precision = boost::math::tools::digits<T>();
|
||||
}
|
||||
if(start + n >= bn.size())
|
||||
{
|
||||
std::size_t new_size = (std::min)((std::max)((std::max)(std::size_t(start + n), std::size_t(bn.size() + 20)), std::size_t(50)), std::size_t(bn.capacity()));
|
||||
tangent_numbers_series(new_size);
|
||||
}
|
||||
|
||||
for(std::size_t i = (std::max)(std::size_t(max_bernoulli_b2n<T>::value + 1), start); i < start + n; ++i)
|
||||
{
|
||||
*out = (i >= m_overflow_limit) ? policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol) : bn[i];
|
||||
++out;
|
||||
}
|
||||
|
||||
#else
|
||||
//
|
||||
// Double-checked locking pattern, lets us access cached already cached values
|
||||
// without locking:
|
||||
//
|
||||
// Get the counter and see if we need to calculate more constants:
|
||||
//
|
||||
if((static_cast<std::size_t>(m_counter.load(BOOST_MATH_ATOMIC_NS::memory_order_consume)) < start + n)
|
||||
|| (static_cast<int>(m_current_precision.load(BOOST_MATH_ATOMIC_NS::memory_order_consume)) < boost::math::tools::digits<T>()))
|
||||
{
|
||||
boost::detail::lightweight_mutex::scoped_lock l(m_mutex);
|
||||
|
||||
if((static_cast<std::size_t>(m_counter.load(BOOST_MATH_ATOMIC_NS::memory_order_consume)) < start + n)
|
||||
|| (static_cast<int>(m_current_precision.load(BOOST_MATH_ATOMIC_NS::memory_order_consume)) < boost::math::tools::digits<T>()))
|
||||
{
|
||||
if(static_cast<int>(m_current_precision.load(BOOST_MATH_ATOMIC_NS::memory_order_consume)) < boost::math::tools::digits<T>())
|
||||
{
|
||||
bn.clear();
|
||||
tn.clear();
|
||||
m_intermediates.clear();
|
||||
m_counter.store(0, BOOST_MATH_ATOMIC_NS::memory_order_release);
|
||||
m_current_precision = boost::math::tools::digits<T>();
|
||||
}
|
||||
if(start + n >= bn.size())
|
||||
{
|
||||
std::size_t new_size = (std::min)((std::max)((std::max)(std::size_t(start + n), std::size_t(bn.size() + 20)), std::size_t(50)), std::size_t(bn.capacity()));
|
||||
tangent_numbers_series(new_size);
|
||||
}
|
||||
m_counter.store(static_cast<atomic_integer_type>(bn.size()), BOOST_MATH_ATOMIC_NS::memory_order_release);
|
||||
}
|
||||
}
|
||||
|
||||
for(std::size_t i = (std::max)(static_cast<std::size_t>(max_bernoulli_b2n<T>::value + 1), start); i < start + n; ++i)
|
||||
{
|
||||
*out = (i >= m_overflow_limit) ? policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol) : bn[static_cast<typename container_type::size_type>(i)];
|
||||
++out;
|
||||
}
|
||||
|
||||
#endif
|
||||
return out;
|
||||
}
|
||||
|
||||
template <class OutputIterator>
|
||||
OutputIterator copy_tangent_numbers(OutputIterator out, std::size_t start, std::size_t n, const Policy& pol)
|
||||
{
|
||||
//
|
||||
// There are basically 3 thread safety options:
|
||||
//
|
||||
// 1) There are no threads (BOOST_HAS_THREADS is not defined).
|
||||
// 2) There are threads, but we do not have a true atomic integer type,
|
||||
// in this case we just use a mutex to guard against race conditions.
|
||||
// 3) There are threads, and we have an atomic integer: in this case we can
|
||||
// use the double-checked locking pattern to avoid thread synchronisation
|
||||
// when accessing values already in the cache.
|
||||
//
|
||||
//
|
||||
// First off handle the common case for overflow and/or asymptotic expansion:
|
||||
//
|
||||
if(start + n > bn.capacity())
|
||||
{
|
||||
if(start < bn.capacity())
|
||||
{
|
||||
out = copy_tangent_numbers(out, start, bn.capacity() - start, pol);
|
||||
n -= bn.capacity() - start;
|
||||
start = static_cast<std::size_t>(bn.capacity());
|
||||
}
|
||||
if(start < b2n_overflow_limit<T, Policy>() + 2u)
|
||||
{
|
||||
for(; n; ++start, --n)
|
||||
{
|
||||
*out = t2n_asymptotic<T, Policy>(static_cast<typename container_type::size_type>(start));
|
||||
++out;
|
||||
}
|
||||
}
|
||||
for(; n; ++start, --n)
|
||||
{
|
||||
*out = policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(start), pol);
|
||||
++out;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
#if !defined(BOOST_HAS_THREADS)
|
||||
//
|
||||
// Single threaded code, very simple:
|
||||
//
|
||||
if(m_current_precision < boost::math::tools::digits<T>())
|
||||
{
|
||||
bn.clear();
|
||||
tn.clear();
|
||||
m_intermediates.clear();
|
||||
m_current_precision = boost::math::tools::digits<T>();
|
||||
}
|
||||
if(start + n >= bn.size())
|
||||
{
|
||||
std::size_t new_size = (std::min)((std::max)((std::max)(start + n, std::size_t(bn.size() + 20)), std::size_t(50)), std::size_t(bn.capacity()));
|
||||
tangent_numbers_series(new_size);
|
||||
}
|
||||
|
||||
for(std::size_t i = start; i < start + n; ++i)
|
||||
{
|
||||
if(i >= m_overflow_limit)
|
||||
*out = policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol);
|
||||
else
|
||||
{
|
||||
if(tools::max_value<T>() * tangent_scale_factor<T>() < tn[static_cast<typename container_type::size_type>(i)])
|
||||
*out = policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol);
|
||||
else
|
||||
*out = tn[static_cast<typename container_type::size_type>(i)] / tangent_scale_factor<T>();
|
||||
}
|
||||
++out;
|
||||
}
|
||||
#elif defined(BOOST_MATH_NO_ATOMIC_INT)
|
||||
//
|
||||
// We need to grab a mutex every time we get here, for both readers and writers:
|
||||
//
|
||||
boost::detail::lightweight_mutex::scoped_lock l(m_mutex);
|
||||
if(m_current_precision < boost::math::tools::digits<T>())
|
||||
{
|
||||
bn.clear();
|
||||
tn.clear();
|
||||
m_intermediates.clear();
|
||||
m_current_precision = boost::math::tools::digits<T>();
|
||||
}
|
||||
if(start + n >= bn.size())
|
||||
{
|
||||
std::size_t new_size = (std::min)((std::max)((std::max)(start + n, std::size_t(bn.size() + 20)), std::size_t(50)), std::size_t(bn.capacity()));
|
||||
tangent_numbers_series(new_size);
|
||||
}
|
||||
|
||||
for(std::size_t i = start; i < start + n; ++i)
|
||||
{
|
||||
if(i >= m_overflow_limit)
|
||||
*out = policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol);
|
||||
else
|
||||
{
|
||||
if(tools::max_value<T>() * tangent_scale_factor<T>() < tn[static_cast<typename container_type::size_type>(i)])
|
||||
*out = policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol);
|
||||
else
|
||||
*out = tn[static_cast<typename container_type::size_type>(i)] / tangent_scale_factor<T>();
|
||||
}
|
||||
++out;
|
||||
}
|
||||
|
||||
#else
|
||||
//
|
||||
// Double-checked locking pattern, lets us access cached already cached values
|
||||
// without locking:
|
||||
//
|
||||
// Get the counter and see if we need to calculate more constants:
|
||||
//
|
||||
if((static_cast<std::size_t>(m_counter.load(BOOST_MATH_ATOMIC_NS::memory_order_consume)) < start + n)
|
||||
|| (static_cast<int>(m_current_precision.load(BOOST_MATH_ATOMIC_NS::memory_order_consume)) < boost::math::tools::digits<T>()))
|
||||
{
|
||||
boost::detail::lightweight_mutex::scoped_lock l(m_mutex);
|
||||
|
||||
if((static_cast<std::size_t>(m_counter.load(BOOST_MATH_ATOMIC_NS::memory_order_consume)) < start + n)
|
||||
|| (static_cast<int>(m_current_precision.load(BOOST_MATH_ATOMIC_NS::memory_order_consume)) < boost::math::tools::digits<T>()))
|
||||
{
|
||||
if(static_cast<int>(m_current_precision.load(BOOST_MATH_ATOMIC_NS::memory_order_consume)) < boost::math::tools::digits<T>())
|
||||
{
|
||||
bn.clear();
|
||||
tn.clear();
|
||||
m_intermediates.clear();
|
||||
m_counter.store(0, BOOST_MATH_ATOMIC_NS::memory_order_release);
|
||||
m_current_precision = boost::math::tools::digits<T>();
|
||||
}
|
||||
if(start + n >= bn.size())
|
||||
{
|
||||
std::size_t new_size = (std::min)((std::max)((std::max)(start + n, std::size_t(bn.size() + 20)), std::size_t(50)), std::size_t(bn.capacity()));
|
||||
tangent_numbers_series(new_size);
|
||||
}
|
||||
m_counter.store(static_cast<atomic_integer_type>(bn.size()), BOOST_MATH_ATOMIC_NS::memory_order_release);
|
||||
}
|
||||
}
|
||||
|
||||
for(std::size_t i = start; i < start + n; ++i)
|
||||
{
|
||||
if(i >= m_overflow_limit)
|
||||
*out = policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol);
|
||||
else
|
||||
{
|
||||
if(tools::max_value<T>() * tangent_scale_factor<T>() < tn[static_cast<typename container_type::size_type>(i)])
|
||||
*out = policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol);
|
||||
else
|
||||
*out = tn[static_cast<typename container_type::size_type>(i)] / tangent_scale_factor<T>();
|
||||
}
|
||||
++out;
|
||||
}
|
||||
|
||||
#endif
|
||||
return out;
|
||||
}
|
||||
|
||||
private:
|
||||
//
|
||||
// The caches for Bernoulli and tangent numbers, once allocated,
|
||||
// these must NEVER EVER reallocate as it breaks our thread
|
||||
// safety guarantees:
|
||||
//
|
||||
fixed_vector<T> bn, tn;
|
||||
std::vector<T> m_intermediates;
|
||||
// The value at which we know overflow has already occurred for the Bn:
|
||||
std::size_t m_overflow_limit;
|
||||
#if !defined(BOOST_HAS_THREADS)
|
||||
int m_current_precision;
|
||||
#elif defined(BOOST_MATH_NO_ATOMIC_INT)
|
||||
boost::detail::lightweight_mutex m_mutex;
|
||||
int m_current_precision;
|
||||
#else
|
||||
boost::detail::lightweight_mutex m_mutex;
|
||||
atomic_counter_type m_counter, m_current_precision;
|
||||
#endif
|
||||
};
|
||||
|
||||
template <class T, class Policy>
|
||||
inline bernoulli_numbers_cache<T, Policy>& get_bernoulli_numbers_cache()
|
||||
{
|
||||
//
|
||||
// Force this function to be called at program startup so all the static variables
|
||||
// get initailzed then (thread safety).
|
||||
//
|
||||
bernoulli_initializer<T, Policy>::force_instantiate();
|
||||
static bernoulli_numbers_cache<T, Policy> data;
|
||||
return data;
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
#endif // BOOST_MATH_BERNOULLI_DETAIL_HPP
|
||||
@@ -0,0 +1,87 @@
|
||||
// Copyright (c) 2013 Anton Bikineev
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
//
|
||||
// This is a partial header, do not include on it's own!!!
|
||||
//
|
||||
// Linear combination for bessel derivatives are defined here
|
||||
#ifndef BOOST_MATH_SF_DETAIL_BESSEL_DERIVATIVES_LINEAR_HPP
|
||||
#define BOOST_MATH_SF_DETAIL_BESSEL_DERIVATIVES_LINEAR_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
namespace boost{ namespace math{ namespace detail{
|
||||
|
||||
template <class T, class Tag, class Policy>
|
||||
inline T bessel_j_derivative_linear(T v, T x, Tag tag, Policy pol)
|
||||
{
|
||||
return (boost::math::detail::cyl_bessel_j_imp<T>(v-1, x, tag, pol) - boost::math::detail::cyl_bessel_j_imp<T>(v+1, x, tag, pol)) / 2;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T bessel_j_derivative_linear(T v, T x, const bessel_int_tag& tag, Policy pol)
|
||||
{
|
||||
return (boost::math::detail::cyl_bessel_j_imp<T>(itrunc(v-1), x, tag, pol) - boost::math::detail::cyl_bessel_j_imp<T>(itrunc(v+1), x, tag, pol)) / 2;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T sph_bessel_j_derivative_linear(unsigned v, T x, Policy pol)
|
||||
{
|
||||
return (v / x) * boost::math::detail::sph_bessel_j_imp<T>(v, x, pol) - boost::math::detail::sph_bessel_j_imp<T>(v+1, x, pol);
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T bessel_i_derivative_linear(T v, T x, Policy pol)
|
||||
{
|
||||
T result = boost::math::detail::cyl_bessel_i_imp<T>(v - 1, x, pol);
|
||||
if(result >= tools::max_value<T>())
|
||||
return result; // result is infinite
|
||||
T result2 = boost::math::detail::cyl_bessel_i_imp<T>(v + 1, x, pol);
|
||||
if(result2 >= tools::max_value<T>() - result)
|
||||
return result2; // result is infinite
|
||||
return (result + result2) / 2;
|
||||
}
|
||||
|
||||
template <class T, class Tag, class Policy>
|
||||
inline T bessel_k_derivative_linear(T v, T x, Tag tag, Policy pol)
|
||||
{
|
||||
T result = boost::math::detail::cyl_bessel_k_imp<T>(v - 1, x, tag, pol);
|
||||
if(result >= tools::max_value<T>())
|
||||
return -result; // result is infinite
|
||||
T result2 = boost::math::detail::cyl_bessel_k_imp<T>(v + 1, x, tag, pol);
|
||||
if(result2 >= tools::max_value<T>() - result)
|
||||
return -result2; // result is infinite
|
||||
return (result + result2) / -2;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T bessel_k_derivative_linear(T v, T x, const bessel_int_tag& tag, Policy pol)
|
||||
{
|
||||
return (boost::math::detail::cyl_bessel_k_imp<T>(itrunc(v-1), x, tag, pol) + boost::math::detail::cyl_bessel_k_imp<T>(itrunc(v+1), x, tag, pol)) / -2;
|
||||
}
|
||||
|
||||
template <class T, class Tag, class Policy>
|
||||
inline T bessel_y_derivative_linear(T v, T x, Tag tag, Policy pol)
|
||||
{
|
||||
return (boost::math::detail::cyl_neumann_imp<T>(v-1, x, tag, pol) - boost::math::detail::cyl_neumann_imp<T>(v+1, x, tag, pol)) / 2;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T bessel_y_derivative_linear(T v, T x, const bessel_int_tag& tag, Policy pol)
|
||||
{
|
||||
return (boost::math::detail::cyl_neumann_imp<T>(itrunc(v-1), x, tag, pol) - boost::math::detail::cyl_neumann_imp<T>(itrunc(v+1), x, tag, pol)) / 2;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T sph_neumann_derivative_linear(unsigned v, T x, Policy pol)
|
||||
{
|
||||
return (v / x) * boost::math::detail::sph_neumann_imp<T>(v, x, pol) - boost::math::detail::sph_neumann_imp<T>(v+1, x, pol);
|
||||
}
|
||||
|
||||
}}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_SF_DETAIL_BESSEL_DERIVATIVES_LINEAR_HPP
|
||||
554
code_isotrope/boost/math/special_functions/detail/bessel_i0.hpp
Executable file
554
code_isotrope/boost/math/special_functions/detail/bessel_i0.hpp
Executable file
@@ -0,0 +1,554 @@
|
||||
// Copyright (c) 2006 Xiaogang Zhang
|
||||
// Copyright (c) 2017 John Maddock
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_MATH_BESSEL_I0_HPP
|
||||
#define BOOST_MATH_BESSEL_I0_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/tools/rational.hpp>
|
||||
#include <boost/math/tools/big_constant.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
// Modified Bessel function of the first kind of order zero
|
||||
// we use the approximating forms derived in:
|
||||
// "Rational Approximations for the Modified Bessel Function of the First Kind - I0(x) for Computations with Double Precision"
|
||||
// by Pavel Holoborodko,
|
||||
// see http://www.advanpix.com/2015/11/11/rational-approximations-for-the-modified-bessel-function-of-the-first-kind-i0-computations-double-precision
|
||||
// The actual coefficients used are our own, and extend Pavel's work to precision's other than double.
|
||||
|
||||
namespace boost { namespace math { namespace detail{
|
||||
|
||||
template <typename T>
|
||||
T bessel_i0(const T& x);
|
||||
|
||||
template <class T, class tag>
|
||||
struct bessel_i0_initializer
|
||||
{
|
||||
struct init
|
||||
{
|
||||
init()
|
||||
{
|
||||
do_init(tag());
|
||||
}
|
||||
static void do_init(const mpl::int_<64>&)
|
||||
{
|
||||
bessel_i0(T(1));
|
||||
bessel_i0(T(8));
|
||||
bessel_i0(T(12));
|
||||
bessel_i0(T(40));
|
||||
bessel_i0(T(101));
|
||||
}
|
||||
static void do_init(const mpl::int_<113>&)
|
||||
{
|
||||
bessel_i0(T(1));
|
||||
bessel_i0(T(10));
|
||||
bessel_i0(T(20));
|
||||
bessel_i0(T(40));
|
||||
bessel_i0(T(101));
|
||||
}
|
||||
template <class U>
|
||||
static void do_init(const U&) {}
|
||||
void force_instantiate()const {}
|
||||
};
|
||||
static const init initializer;
|
||||
static void force_instantiate()
|
||||
{
|
||||
initializer.force_instantiate();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class tag>
|
||||
const typename bessel_i0_initializer<T, tag>::init bessel_i0_initializer<T, tag>::initializer;
|
||||
|
||||
template <typename T, int N>
|
||||
T bessel_i0_imp(const T&, const mpl::int_<N>&)
|
||||
{
|
||||
BOOST_ASSERT(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T bessel_i0_imp(const T& x, const mpl::int_<24>&)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
if(x < 7.75)
|
||||
{
|
||||
// Max error in interpolated form: 3.929e-08
|
||||
// Max Error found at float precision = Poly: 1.991226e-07
|
||||
static const float P[] = {
|
||||
1.00000003928615375e+00f,
|
||||
2.49999576572179639e-01f,
|
||||
2.77785268558399407e-02f,
|
||||
1.73560257755821695e-03f,
|
||||
6.96166518788906424e-05f,
|
||||
1.89645733877137904e-06f,
|
||||
4.29455004657565361e-08f,
|
||||
3.90565476357034480e-10f,
|
||||
1.48095934745267240e-11f
|
||||
};
|
||||
T a = x * x / 4;
|
||||
return a * boost::math::tools::evaluate_polynomial(P, a) + 1;
|
||||
}
|
||||
else if(x < 50)
|
||||
{
|
||||
// Max error in interpolated form: 5.195e-08
|
||||
// Max Error found at float precision = Poly: 8.502534e-08
|
||||
static const float P[] = {
|
||||
3.98942651588301770e-01f,
|
||||
4.98327234176892844e-02f,
|
||||
2.91866904423115499e-02f,
|
||||
1.35614940793742178e-02f,
|
||||
1.31409251787866793e-01f
|
||||
};
|
||||
return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Max error in interpolated form: 1.782e-09
|
||||
// Max Error found at float precision = Poly: 6.473568e-08
|
||||
static const float P[] = {
|
||||
3.98942391532752700e-01f,
|
||||
4.98455950638200020e-02f,
|
||||
2.94835666900682535e-02f
|
||||
};
|
||||
T ex = exp(x / 2);
|
||||
T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
|
||||
result *= ex;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T bessel_i0_imp(const T& x, const mpl::int_<53>&)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
if(x < 7.75)
|
||||
{
|
||||
// Bessel I0 over[10 ^ -16, 7.75]
|
||||
// Max error in interpolated form : 3.042e-18
|
||||
// Max Error found at double precision = Poly : 5.106609e-16 Cheb : 5.239199e-16
|
||||
static const double P[] = {
|
||||
1.00000000000000000e+00,
|
||||
2.49999999999999909e-01,
|
||||
2.77777777777782257e-02,
|
||||
1.73611111111023792e-03,
|
||||
6.94444444453352521e-05,
|
||||
1.92901234513219920e-06,
|
||||
3.93675991102510739e-08,
|
||||
6.15118672704439289e-10,
|
||||
7.59407002058973446e-12,
|
||||
7.59389793369836367e-14,
|
||||
6.27767773636292611e-16,
|
||||
4.34709704153272287e-18,
|
||||
2.63417742690109154e-20,
|
||||
1.13943037744822825e-22,
|
||||
9.07926920085624812e-25
|
||||
};
|
||||
T a = x * x / 4;
|
||||
return a * boost::math::tools::evaluate_polynomial(P, a) + 1;
|
||||
}
|
||||
else if(x < 500)
|
||||
{
|
||||
// Max error in interpolated form : 1.685e-16
|
||||
// Max Error found at double precision = Poly : 2.575063e-16 Cheb : 2.247615e+00
|
||||
static const double P[] = {
|
||||
3.98942280401425088e-01,
|
||||
4.98677850604961985e-02,
|
||||
2.80506233928312623e-02,
|
||||
2.92211225166047873e-02,
|
||||
4.44207299493659561e-02,
|
||||
1.30970574605856719e-01,
|
||||
-3.35052280231727022e+00,
|
||||
2.33025711583514727e+02,
|
||||
-1.13366350697172355e+04,
|
||||
4.24057674317867331e+05,
|
||||
-1.23157028595698731e+07,
|
||||
2.80231938155267516e+08,
|
||||
-5.01883999713777929e+09,
|
||||
7.08029243015109113e+10,
|
||||
-7.84261082124811106e+11,
|
||||
6.76825737854096565e+12,
|
||||
-4.49034849696138065e+13,
|
||||
2.24155239966958995e+14,
|
||||
-8.13426467865659318e+14,
|
||||
2.02391097391687777e+15,
|
||||
-3.08675715295370878e+15,
|
||||
2.17587543863819074e+15
|
||||
};
|
||||
return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Max error in interpolated form : 2.437e-18
|
||||
// Max Error found at double precision = Poly : 1.216719e-16
|
||||
static const double P[] = {
|
||||
3.98942280401432905e-01,
|
||||
4.98677850491434560e-02,
|
||||
2.80506308916506102e-02,
|
||||
2.92179096853915176e-02,
|
||||
4.53371208762579442e-02
|
||||
};
|
||||
T ex = exp(x / 2);
|
||||
T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
|
||||
result *= ex;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T bessel_i0_imp(const T& x, const mpl::int_<64>&)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
if(x < 7.75)
|
||||
{
|
||||
// Bessel I0 over[10 ^ -16, 7.75]
|
||||
// Max error in interpolated form : 3.899e-20
|
||||
// Max Error found at float80 precision = Poly : 1.770840e-19
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 9.99999999999999999961011629e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 2.50000000000000001321873912e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 2.77777777777777703400424216e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.73611111111112764793802701e-03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 6.94444444444251461247253525e-05),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.92901234569262206386118739e-06),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 3.93675988851131457141005209e-08),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 6.15118734688297476454205352e-10),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 7.59405797058091016449222685e-12),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 7.59406599631719800679835140e-14),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 6.27598961062070013516660425e-16),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 4.35920318970387940278362992e-18),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 2.57372492687715452949437981e-20),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.33908663475949906992942204e-22),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 5.15976668870980234582896010e-25),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 3.46240478946376069211156548e-27)
|
||||
};
|
||||
T a = x * x / 4;
|
||||
return a * boost::math::tools::evaluate_polynomial(P, a) + 1;
|
||||
}
|
||||
else if(x < 10)
|
||||
{
|
||||
// Maximum Deviation Found: 6.906e-21
|
||||
// Expected Error Term : -6.903e-21
|
||||
// Maximum Relative Change in Control Points : 1.631e-04
|
||||
// Max Error found at float80 precision = Poly : 7.811948e-21
|
||||
static const T Y = 4.051098823547363281250e-01f;
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -6.158081780620616479492e-03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 4.883635969834048766148e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 7.892782002476195771920e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -1.478784996478070170327e+00),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 2.988611837308006851257e+01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -4.140133766747436806179e+02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 4.117316447921276453271e+03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -2.942353667455141676001e+04),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.493482682461387081534e+05),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -5.228100538921466124653e+05),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.195279248600467989454e+06),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -1.601530760654337045917e+06),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 9.504921137873298402679e+05)
|
||||
};
|
||||
return exp(x) * (boost::math::tools::evaluate_polynomial(P, T(1 / x)) + Y) / sqrt(x);
|
||||
}
|
||||
else if(x < 15)
|
||||
{
|
||||
// Maximum Deviation Found: 4.083e-21
|
||||
// Expected Error Term : -4.025e-21
|
||||
// Maximum Relative Change in Control Points : 1.304e-03
|
||||
// Max Error found at float80 precision = Poly : 2.303527e-20
|
||||
static const T Y = 4.033188819885253906250e-01f;
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -4.376373876116109401062e-03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 4.982899138682911273321e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 3.109477529533515397644e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -1.163760580110576407673e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 4.776501832837367371883e+00),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -1.101478069227776656318e+02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.892071912448960299773e+03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -2.417739279982328117483e+04),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 2.296963447724067390552e+05),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -1.598589306710589358747e+06),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 7.903662411851774878322e+06),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -2.622677059040339516093e+07),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 5.227776578828667629347e+07),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -4.727797957441040896878e+07)
|
||||
};
|
||||
return exp(x) * (boost::math::tools::evaluate_polynomial(P, T(1 / x)) + Y) / sqrt(x);
|
||||
}
|
||||
else if(x < 50)
|
||||
{
|
||||
// Max error in interpolated form: 1.035e-21
|
||||
// Max Error found at float80 precision = Poly: 1.885872e-21
|
||||
static const T Y = 4.011702537536621093750e-01f;
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -2.227973351806078464328e-03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 4.986778486088017419036e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 2.805066823812285310011e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 2.921443721160964964623e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 4.517504941996594744052e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 6.316922639868793684401e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.535891099168810015433e+00),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -4.706078229522448308087e+01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.351015763079160914632e+03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -2.948809013999277355098e+04),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 4.967598958582595361757e+05),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -6.346924657995383019558e+06),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 5.998794574259956613472e+07),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -4.016371355801690142095e+08),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.768791455631826490838e+09),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -4.441995678177349895640e+09),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 4.482292669974971387738e+09)
|
||||
};
|
||||
return exp(x) * (boost::math::tools::evaluate_polynomial(P, T(1 / x)) + Y) / sqrt(x);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Bessel I0 over[50, INF]
|
||||
// Max error in interpolated form : 5.587e-20
|
||||
// Max Error found at float80 precision = Poly : 8.776852e-20
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 3.98942280401432677955074061e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 4.98677850501789875615574058e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 2.80506290908675604202206833e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 2.92194052159035901631494784e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 4.47422430732256364094681137e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 9.05971614435738691235525172e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 2.29180522595459823234266708e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 6.15122547776140254569073131e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 7.48491812136365376477357324e+00),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -2.45569740166506688169730713e+02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 9.66857566379480730407063170e+03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -2.71924083955641197750323901e+05),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 5.74276685704579268845870586e+06),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -8.89753803265734681907148778e+07),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 9.82590905134996782086242180e+08),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -7.30623197145529889358596301e+09),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 3.27310000726207055200805893e+10),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -6.64365417189215599168817064e+10)
|
||||
};
|
||||
T ex = exp(x / 2);
|
||||
T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
|
||||
result *= ex;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T bessel_i0_imp(const T& x, const mpl::int_<113>&)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
if(x < 7.75)
|
||||
{
|
||||
// Bessel I0 over[10 ^ -34, 7.75]
|
||||
// Max error in interpolated form : 1.274e-34
|
||||
// Max Error found at float128 precision = Poly : 3.096091e-34
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.0000000000000000000000000000000001273856e+00),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.4999999999999999999999999999999107477496e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.7777777777777777777777777777881795230918e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.7361111111111111111111111106290091648808e-03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 6.9444444444444444444444445629960334523101e-05),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.9290123456790123456790105563456483249753e-06),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.9367598891408415217940836339080514004844e-08),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 6.1511873267825648777900014857992724731476e-10),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 7.5940584281266233066162999610732449709209e-12),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 7.5940584281266232783124723601470051895304e-14),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 6.2760813455591936763439337059117957836078e-16),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 4.3583898233049738471136482147779094353096e-18),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.5789288895299965395422423848480340736308e-20),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.3157800456718804437960453545507623434606e-22),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 5.8479113149412360748032684260932041506493e-25),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.2843403488398038539283241944594140493394e-27),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 7.9042925594356556196790242908697582021825e-30),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.4395919891312152120710245152115597111101e-32),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 6.7580986145276689333214547502373003196707e-35),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.6886514018062348877723837017198859723889e-37),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.8540558465757554512570197585002702777999e-40),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 7.4684706070226893763741850944911705726436e-43),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.0210715309399646335858150349406935414314e-45)
|
||||
};
|
||||
T a = x * x / 4;
|
||||
return a * boost::math::tools::evaluate_polynomial(P, a) + 1;
|
||||
}
|
||||
else if(x < 15)
|
||||
{
|
||||
// Bessel I0 over[7.75, 15]
|
||||
// Max error in interpolated form : 7.534e-35
|
||||
// Max Error found at float128 precision = Poly : 6.123912e-34
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 9.9999999999999999992388573069504617493518e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.5000000000000000007304739268173096975340e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.7777777777777777744261405400543564492074e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.7361111111111111209006987259719750726867e-03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 6.9444444444444442399703186871329381908321e-05),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.9290123456790126709286741580242189785431e-06),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.9367598891408374246503061422528266924389e-08),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 6.1511873267826068395343047827801353170966e-10),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 7.5940584281262673459688011737168286944521e-12),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 7.5940584281291583769928563167645746144508e-14),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 6.2760813455438840231126529638737436950274e-16),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 4.3583898233839583885132809584770578894948e-18),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.5789288891798658971960571838369339742994e-20),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.3157800470129311623308216856009970266088e-22),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 5.8479112701534604520063520412207286692581e-25),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.2843404822552330714586265081801727491890e-27),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 7.9042888166225242675881424439818162458179e-30),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.4396027771820721384198604723320045236973e-32),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 6.7577659910606076328136207973456511895030e-35),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.6896548123724136624716224328803899914646e-37),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.8285850162160539150210466453921758781984e-40),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 7.9419071894227736216423562425429524883562e-43),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.4720374049498608905571855665134539425038e-45),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.7763533278527958112907118930154738930378e-48),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.1213839473168678646697528580511702663617e-51),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.0648035313124146852372607519737686740964e-53),
|
||||
-BOOST_MATH_BIG_CONSTANT(T, 113, 5.1255595184052024349371058585102280860878e-57),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.4652470895944157957727948355523715335882e-59)
|
||||
};
|
||||
T a = x * x / 4;
|
||||
return a * boost::math::tools::evaluate_polynomial(P, a) + 1;
|
||||
}
|
||||
else if(x < 30)
|
||||
{
|
||||
// Max error in interpolated form : 1.808e-34
|
||||
// Max Error found at float128 precision = Poly : 2.399403e-34
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.9894228040870793650581242239624530714032e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 4.9867780576714783790784348982178607842250e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.8051948347934462928487999569249907599510e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.8971143420388958551176254291160976367263e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 7.8197359701715582763961322341827341098897e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -3.3430484862908317377522273217643346601271e+00),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.7884507603213662610604413960838990199224e+02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -1.8304926482356755790062999202373909300514e+04),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 9.8867173178574875515293357145875120137676e+05),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -4.4261178812193528551544261731796888257644e+07),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.6453010340778116475788083817762403540097e+09),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -5.0432401330113978669454035365747869477960e+10),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.2462165331309799059332310595587606836357e+12),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -2.3299800389951335932792950236410844978273e+13),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.5748218240248714177527965706790413406639e+14),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.8330014378766930869945511450377736037385e+15),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -1.8494610073827453236940544799030787866218e+17),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 5.7244661371420647691301043350229977856476e+18),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -1.2386378807889388140099109087465781254321e+20),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.1104000573102013529518477353943384110982e+21),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -2.9426541092239879262282594572224300191016e+22),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.4061439136301913488512592402635688101020e+23),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -3.2836554760521986358980180942859101564671e+24),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.6270285589905206294944214795661236766988e+25),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -1.7278631455211972017740134341610659484259e+26),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 9.1971734473772196124736986948034978906801e+26),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -3.8669270707172568763908838463689093500098e+27),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.2368879358870281916900125550129211146626e+28),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -2.8296235063297831758204519071113999839858e+28),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 4.1253861666023020670144616019148954773662e+28),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -2.8809536950051955163648980306847791014734e+28) };
|
||||
return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
|
||||
}
|
||||
else if(x < 100)
|
||||
{
|
||||
// Bessel I0 over[30, 100]
|
||||
// Max error in interpolated form : 1.487e-34
|
||||
// Max Error found at float128 precision = Poly : 1.929924e-34
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.9894228040143267793996798658172135362278e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 4.9867785050179084714910130342157246539820e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.8050629090725751585266360464766768437048e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.9219405302833158254515212437025679637597e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 4.4742214371598631578107310396249912330627e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 9.0602983776478659136184969363625092585520e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.2839507231977478205885469900971893734770e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 6.8925739165733823730525449511456529001868e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.4238082222874015159424842335385854632223e+00),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 9.6759648427182491050716309699208988458050e+00),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 4.7292246491169360014875196108746167872215e+01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.1001411442786230340015781205680362993575e+01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 9.8277628835804873490331739499978938078848e+03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -3.1208326312801432038715638596517882759639e+05),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 9.4813611580683862051838126076298945680803e+06),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -2.1278197693321821164135890132925119054391e+08),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.3190303792682886967459489059860595063574e+09),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -2.1580767338646580750893606158043485767644e+10),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -5.0256008808415702780816006134784995506549e+11),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.9044186472918017896554580836514681614475e+13),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -3.2521078890073151875661384381880225635135e+14),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.3620352486836976842181057590770636605454e+15),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -2.0375525734060401555856465179734887312420e+16),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 5.6392664899881014534361728644608549445131e+16)
|
||||
};
|
||||
return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Bessel I0 over[100, INF]
|
||||
// Max error in interpolated form : 5.459e-35
|
||||
// Max Error found at float128 precision = Poly : 1.472240e-34
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.9894228040143267793994605993438166526772e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 4.9867785050179084742493257495245185241487e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.8050629090725735167652437695397756897920e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.9219405302839307466358297347675795965363e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 4.4742214369972689474366968442268908028204e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 9.0602984099194778006610058410222616383078e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.2839502241666629677015839125593079416327e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 6.8926354981801627920292655818232972385750e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.4231921590621824187100989532173995000655e+00),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 9.7264260959693775207585700654645245723497e+00),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 4.3890136225398811195878046856373030127018e+01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.1999720924619285464910452647408431234369e+02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.2076909538525038580501368530598517194748e+03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 7.5684635141332367730007149159063086133399e+03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.5178192543258299267923025833141286569141e+04),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 6.2966297919851965784482163987240461837728e+05) };
|
||||
T ex = exp(x / 2);
|
||||
T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
|
||||
result *= ex;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T bessel_i0_imp(const T& x, const mpl::int_<0>&)
|
||||
{
|
||||
if(boost::math::tools::digits<T>() <= 24)
|
||||
return bessel_i0_imp(x, mpl::int_<24>());
|
||||
else if(boost::math::tools::digits<T>() <= 53)
|
||||
return bessel_i0_imp(x, mpl::int_<53>());
|
||||
else if(boost::math::tools::digits<T>() <= 64)
|
||||
return bessel_i0_imp(x, mpl::int_<64>());
|
||||
else if(boost::math::tools::digits<T>() <= 113)
|
||||
return bessel_i0_imp(x, mpl::int_<113>());
|
||||
BOOST_ASSERT(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T bessel_i0(const T& x)
|
||||
{
|
||||
typedef mpl::int_<
|
||||
((std::numeric_limits<T>::digits == 0) || (std::numeric_limits<T>::radix != 2)) ?
|
||||
0 :
|
||||
std::numeric_limits<T>::digits <= 24 ?
|
||||
24 :
|
||||
std::numeric_limits<T>::digits <= 53 ?
|
||||
53 :
|
||||
std::numeric_limits<T>::digits <= 64 ?
|
||||
64 :
|
||||
std::numeric_limits<T>::digits <= 113 ?
|
||||
113 : -1
|
||||
> tag_type;
|
||||
|
||||
bessel_i0_initializer<T, tag_type>::force_instantiate();
|
||||
return bessel_i0_imp(x, tag_type());
|
||||
}
|
||||
|
||||
}}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_BESSEL_I0_HPP
|
||||
|
||||
582
code_isotrope/boost/math/special_functions/detail/bessel_i1.hpp
Executable file
582
code_isotrope/boost/math/special_functions/detail/bessel_i1.hpp
Executable file
@@ -0,0 +1,582 @@
|
||||
// Copyright (c) 2017 John Maddock
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// Modified Bessel function of the first kind of order zero
|
||||
// we use the approximating forms derived in:
|
||||
// "Rational Approximations for the Modified Bessel Function of the First Kind - I1(x) for Computations with Double Precision"
|
||||
// by Pavel Holoborodko,
|
||||
// see http://www.advanpix.com/2015/11/12/rational-approximations-for-the-modified-bessel-function-of-the-first-kind-i1-for-computations-with-double-precision/
|
||||
// The actual coefficients used are our own, and extend Pavel's work to precision's other than double.
|
||||
|
||||
#ifndef BOOST_MATH_BESSEL_I1_HPP
|
||||
#define BOOST_MATH_BESSEL_I1_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/tools/rational.hpp>
|
||||
#include <boost/math/tools/big_constant.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
// Modified Bessel function of the first kind of order one
|
||||
// minimax rational approximations on intervals, see
|
||||
// Blair and Edwards, Chalk River Report AECL-4928, 1974
|
||||
|
||||
namespace boost { namespace math { namespace detail{
|
||||
|
||||
template <typename T>
|
||||
T bessel_i1(const T& x);
|
||||
|
||||
template <class T, class tag>
|
||||
struct bessel_i1_initializer
|
||||
{
|
||||
struct init
|
||||
{
|
||||
init()
|
||||
{
|
||||
do_init(tag());
|
||||
}
|
||||
static void do_init(const mpl::int_<64>&)
|
||||
{
|
||||
bessel_i1(T(1));
|
||||
bessel_i1(T(15));
|
||||
bessel_i1(T(80));
|
||||
bessel_i1(T(101));
|
||||
}
|
||||
static void do_init(const mpl::int_<113>&)
|
||||
{
|
||||
bessel_i1(T(1));
|
||||
bessel_i1(T(10));
|
||||
bessel_i1(T(14));
|
||||
bessel_i1(T(19));
|
||||
bessel_i1(T(34));
|
||||
bessel_i1(T(99));
|
||||
bessel_i1(T(101));
|
||||
}
|
||||
template <class U>
|
||||
static void do_init(const U&) {}
|
||||
void force_instantiate()const{}
|
||||
};
|
||||
static const init initializer;
|
||||
static void force_instantiate()
|
||||
{
|
||||
initializer.force_instantiate();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class tag>
|
||||
const typename bessel_i1_initializer<T, tag>::init bessel_i1_initializer<T, tag>::initializer;
|
||||
|
||||
template <typename T, int N>
|
||||
T bessel_i1_imp(const T&, const mpl::int_<N>&)
|
||||
{
|
||||
BOOST_ASSERT(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T bessel_i1_imp(const T& x, const mpl::int_<24>&)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
if(x < 7.75)
|
||||
{
|
||||
//Max error in interpolated form : 1.348e-08
|
||||
// Max Error found at float precision = Poly : 1.469121e-07
|
||||
static const float P[] = {
|
||||
8.333333221e-02f,
|
||||
6.944453712e-03f,
|
||||
3.472097211e-04f,
|
||||
1.158047174e-05f,
|
||||
2.739745142e-07f,
|
||||
5.135884609e-09f,
|
||||
5.262251502e-11f,
|
||||
1.331933703e-12f
|
||||
};
|
||||
T a = x * x / 4;
|
||||
T Q[3] = { 1, 0.5f, boost::math::tools::evaluate_polynomial(P, a) };
|
||||
return x * boost::math::tools::evaluate_polynomial(Q, a) / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Max error in interpolated form: 9.000e-08
|
||||
// Max Error found at float precision = Poly: 1.044345e-07
|
||||
|
||||
static const float P[] = {
|
||||
3.98942115977513013e-01f,
|
||||
-1.49581264836620262e-01f,
|
||||
-4.76475741878486795e-02f,
|
||||
-2.65157315524784407e-02f,
|
||||
-1.47148600683672014e-01f
|
||||
};
|
||||
T ex = exp(x / 2);
|
||||
T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
|
||||
result *= ex;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T bessel_i1_imp(const T& x, const mpl::int_<53>&)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
if(x < 7.75)
|
||||
{
|
||||
// Bessel I0 over[10 ^ -16, 7.75]
|
||||
// Max error in interpolated form: 5.639e-17
|
||||
// Max Error found at double precision = Poly: 1.795559e-16
|
||||
|
||||
static const double P[] = {
|
||||
8.333333333333333803e-02,
|
||||
6.944444444444341983e-03,
|
||||
3.472222222225921045e-04,
|
||||
1.157407407354987232e-05,
|
||||
2.755731926254790268e-07,
|
||||
4.920949692800671435e-09,
|
||||
6.834657311305621830e-11,
|
||||
7.593969849687574339e-13,
|
||||
6.904822652741917551e-15,
|
||||
5.220157095351373194e-17,
|
||||
3.410720494727771276e-19,
|
||||
1.625212890947171108e-21,
|
||||
1.332898928162290861e-23
|
||||
};
|
||||
T a = x * x / 4;
|
||||
T Q[3] = { 1, 0.5f, boost::math::tools::evaluate_polynomial(P, a) };
|
||||
return x * boost::math::tools::evaluate_polynomial(Q, a) / 2;
|
||||
}
|
||||
else if(x < 500)
|
||||
{
|
||||
// Max error in interpolated form: 1.796e-16
|
||||
// Max Error found at double precision = Poly: 2.898731e-16
|
||||
|
||||
static const double P[] = {
|
||||
3.989422804014406054e-01,
|
||||
-1.496033551613111533e-01,
|
||||
-4.675104253598537322e-02,
|
||||
-4.090895951581637791e-02,
|
||||
-5.719036414430205390e-02,
|
||||
-1.528189554374492735e-01,
|
||||
3.458284470977172076e+00,
|
||||
-2.426181371595021021e+02,
|
||||
1.178785865993440669e+04,
|
||||
-4.404655582443487334e+05,
|
||||
1.277677779341446497e+07,
|
||||
-2.903390398236656519e+08,
|
||||
5.192386898222206474e+09,
|
||||
-7.313784438967834057e+10,
|
||||
8.087824484994859552e+11,
|
||||
-6.967602516005787001e+12,
|
||||
4.614040809616582764e+13,
|
||||
-2.298849639457172489e+14,
|
||||
8.325554073334618015e+14,
|
||||
-2.067285045778906105e+15,
|
||||
3.146401654361325073e+15,
|
||||
-2.213318202179221945e+15
|
||||
};
|
||||
return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Max error in interpolated form: 1.320e-19
|
||||
// Max Error found at double precision = Poly: 7.065357e-17
|
||||
static const double P[] = {
|
||||
3.989422804014314820e-01,
|
||||
-1.496033551467584157e-01,
|
||||
-4.675105322571775911e-02,
|
||||
-4.090421597376992892e-02,
|
||||
-5.843630344778927582e-02
|
||||
};
|
||||
T ex = exp(x / 2);
|
||||
T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
|
||||
result *= ex;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T bessel_i1_imp(const T& x, const mpl::int_<64>&)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
if(x < 7.75)
|
||||
{
|
||||
// Bessel I0 over[10 ^ -16, 7.75]
|
||||
// Max error in interpolated form: 8.086e-21
|
||||
// Max Error found at float80 precision = Poly: 7.225090e-20
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 8.33333333333333333340071817e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 6.94444444444444442462728070e-03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 3.47222222222222318886683883e-04),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.15740740740738880709555060e-05),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 2.75573192240046222242685145e-07),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 4.92094986131253986838697503e-09),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 6.83465258979924922633502182e-11),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 7.59405830675154933645967137e-13),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 6.90369179710633344508897178e-15),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 5.23003610041709452814262671e-17),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 3.35291901027762552549170038e-19),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.83991379419781823063672109e-21),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 8.87732714140192556332037815e-24),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 3.32120654663773147206454247e-26),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.95294659305369207813486871e-28)
|
||||
};
|
||||
T a = x * x / 4;
|
||||
T Q[3] = { 1, 0.5f, boost::math::tools::evaluate_polynomial(P, a) };
|
||||
return x * boost::math::tools::evaluate_polynomial(Q, a) / 2;
|
||||
}
|
||||
else if(x < 20)
|
||||
{
|
||||
// Max error in interpolated form: 4.258e-20
|
||||
// Max Error found at float80 precision = Poly: 2.851105e-19
|
||||
// Maximum Deviation Found : 3.887e-20
|
||||
// Expected Error Term : 3.887e-20
|
||||
// Maximum Relative Change in Control Points : 1.681e-04
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 3.98942260530218897338680e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -1.49599542849073670179540e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -4.70492865454119188276875e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -3.12389893307392002405869e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.49696126385202602071197e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -3.84206507612717711565967e+01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 2.14748094784412558689584e+03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -7.70652726663596993005669e+04),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 2.01659736164815617174439e+06),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -4.04740659606466305607544e+07),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 6.38383394696382837263656e+08),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -8.00779638649147623107378e+09),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 8.02338237858684714480491e+10),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -6.41198553664947312995879e+11),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 4.05915186909564986897554e+12),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -2.00907636964168581116181e+13),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 7.60855263982359981275199e+13),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -2.12901817219239205393806e+14),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 4.14861794397709807823575e+14),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -5.02808138522587680348583e+14),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 2.85505477056514919387171e+14)
|
||||
};
|
||||
return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
|
||||
}
|
||||
else if(x < 100)
|
||||
{
|
||||
// Bessel I0 over [15, 50]
|
||||
// Maximum Deviation Found: 2.444e-20
|
||||
// Expected Error Term : 2.438e-20
|
||||
// Maximum Relative Change in Control Points : 2.101e-03
|
||||
// Max Error found at float80 precision = Poly : 6.029974e-20
|
||||
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 3.98942280401431675205845e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -1.49603355149968887210170e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -4.67510486284376330257260e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -4.09071458907089270559464e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -5.75278280327696940044714e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -1.10591299500956620739254e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -2.77061766699949309115618e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -5.42683771801837596371638e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -9.17021412070404158464316e+00),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.04154379346763380543310e+02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -1.43462345357478348323006e+03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 9.98109660274422449523837e+03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -3.74438822767781410362757e+04)
|
||||
};
|
||||
return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Bessel I0 over[100, INF]
|
||||
// Max error in interpolated form: 2.456e-20
|
||||
// Max Error found at float80 precision = Poly: 5.446356e-20
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 3.98942280401432677958445e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -1.49603355150537411254359e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -4.67510484842456251368526e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -4.09071676503922479645155e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -5.75256179814881566010606e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -1.10754910257965227825040e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -2.67858639515616079840294e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -9.17266479586791298924367e-01)
|
||||
};
|
||||
T ex = exp(x / 2);
|
||||
T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
|
||||
result *= ex;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T bessel_i1_imp(const T& x, const mpl::int_<113>&)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
if(x < 7.75)
|
||||
{
|
||||
// Bessel I0 over[10 ^ -34, 7.75]
|
||||
// Max error in interpolated form: 1.835e-35
|
||||
// Max Error found at float128 precision = Poly: 1.645036e-34
|
||||
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 8.3333333333333333333333333333333331804098e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 6.9444444444444444444444444444445418303082e-03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.4722222222222222222222222222119082346591e-04),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.1574074074074074074074074078415867655987e-05),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.7557319223985890652557318255143448192453e-07),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 4.9209498614260519022423916850415000626427e-09),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 6.8346525853139609753354247043900442393686e-11),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 7.5940584281266233060080535940234144302217e-13),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 6.9036894801151120925605467963949641957095e-15),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 5.2300677879659941472662086395055636394839e-17),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.3526075563884539394691458717439115962233e-19),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.8420920639497841692288943167036233338434e-21),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 8.7718669711748690065381181691546032291365e-24),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.6549445715236427401845636880769861424730e-26),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.3437296196812697924703896979250126739676e-28),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 4.3912734588619073883015937023564978854893e-31),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.2839967682792395867255384448052781306897e-33),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.3790094235693528861015312806394354114982e-36),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 8.0423861671932104308662362292359563970482e-39),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.7493858979396446292135661268130281652945e-41),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.2786079392547776769387921361408303035537e-44),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 8.2335693685833531118863552173880047183822e-47)
|
||||
};
|
||||
T a = x * x / 4;
|
||||
T Q[3] = { 1, 0.5f, boost::math::tools::evaluate_polynomial(P, a) };
|
||||
return x * boost::math::tools::evaluate_polynomial(Q, a) / 2;
|
||||
}
|
||||
else if(x < 11)
|
||||
{
|
||||
// Max error in interpolated form: 8.574e-36
|
||||
// Maximum Deviation Found : 4.689e-36
|
||||
// Expected Error Term : 3.760e-36
|
||||
// Maximum Relative Change in Control Points : 5.204e-03
|
||||
// Max Error found at float128 precision = Poly : 2.882561e-34
|
||||
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 8.333333333333333326889717360850080939e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 6.944444444444444511272790848815114507e-03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.472222222222221892451965054394153443e-04),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.157407407407408437378868534321538798e-05),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.755731922398566216824909767320161880e-07),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 4.920949861426434829568192525456800388e-09),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 6.834652585308926245465686943255486934e-11),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 7.594058428179852047689599244015979196e-13),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 6.903689479655006062822949671528763738e-15),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 5.230067791254403974475987777406992984e-17),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.352607536815161679702105115200693346e-19),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.842092161364672561828681848278567885e-21),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 8.771862912600611801856514076709932773e-24),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.654958704184380914803366733193713605e-26),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.343688672071130980471207297730607625e-28),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 4.392252844664709532905868749753463950e-31),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.282086786672692641959912811902298600e-33),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.408812012322547015191398229942864809e-36),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 7.681220437734066258673404589233009892e-39),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.072417451640733785626701738789290055e-41),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.352218520142636864158849446833681038e-44),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.407918492276267527897751358794783640e-46)
|
||||
};
|
||||
T a = x * x / 4;
|
||||
T Q[3] = { 1, 0.5f, boost::math::tools::evaluate_polynomial(P, a) };
|
||||
return x * boost::math::tools::evaluate_polynomial(Q, a) / 2;
|
||||
}
|
||||
else if(x < 15)
|
||||
{
|
||||
//Max error in interpolated form: 7.599e-36
|
||||
// Maximum Deviation Found : 1.766e-35
|
||||
// Expected Error Term : 1.021e-35
|
||||
// Maximum Relative Change in Control Points : 6.228e-03
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 8.333333333333255774414858563409941233e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 6.944444444444897867884955912228700291e-03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.472222222220954970397343617150959467e-04),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.157407407409660682751155024932538578e-05),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.755731922369973706427272809014190998e-07),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 4.920949861702265600960449699129258153e-09),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 6.834652583208361401197752793379677147e-11),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 7.594058441128280500819776168239988143e-13),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 6.903689413939268702265479276217647209e-15),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 5.230068069012898202890718644753625569e-17),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.352606552027491657204243201021677257e-19),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.842095100698532984651921750204843362e-21),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 8.771789051329870174925649852681844169e-24),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.655114381199979536997025497438385062e-26),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.343415732516712339472538688374589373e-28),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 4.396177019032432392793591204647901390e-31),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.277563309255167951005939802771456315e-33),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.449201419305514579791370198046544736e-36),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 7.415430703400740634202379012388035255e-39),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.195458831864936225409005027914934499e-41),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 8.829726762743879793396637797534668039e-45),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.698302711685624490806751012380215488e-46),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -2.062520475425422618494185821587228317e-49),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 6.732372906742845717148185173723304360e-52)
|
||||
};
|
||||
T a = x * x / 4;
|
||||
T Q[3] = { 1, 0.5f, boost::math::tools::evaluate_polynomial(P, a) };
|
||||
return x * boost::math::tools::evaluate_polynomial(Q, a) / 2;
|
||||
}
|
||||
else if(x < 20)
|
||||
{
|
||||
// Max error in interpolated form: 8.864e-36
|
||||
// Max Error found at float128 precision = Poly: 8.522841e-35
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.989422793693152031514179994954750043e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -1.496029423752889591425633234009799670e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -4.682975926820553021482820043377990241e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -3.138871171577224532369979905856458929e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -8.765350219426341341990447005798111212e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 5.321389275507714530941178258122955540e+01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -2.727748393898888756515271847678850411e+03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.123040820686242586086564998713862335e+05),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -3.784112378374753535335272752884808068e+06),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.054920416060932189433079126269416563e+08),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -2.450129415468060676827180524327749553e+09),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 4.758831882046487398739784498047935515e+10),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -7.736936520262204842199620784338052937e+11),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.051128683324042629513978256179115439e+13),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -1.188008285959794869092624343537262342e+14),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.108530004906954627420484180793165669e+15),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -8.441516828490144766650287123765318484e+15),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 5.158251664797753450664499268756393535e+16),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -2.467314522709016832128790443932896401e+17),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 8.896222045367960462945885220710294075e+17),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -2.273382139594876997203657902425653079e+18),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.669871448568623680543943144842394531e+18),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -2.813923031370708069940575240509912588e+18)
|
||||
};
|
||||
return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
|
||||
}
|
||||
else if(x < 35)
|
||||
{
|
||||
// Max error in interpolated form: 6.028e-35
|
||||
// Max Error found at float128 precision = Poly: 1.368313e-34
|
||||
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.989422804012941975429616956496046931e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -1.496033550576049830976679315420681402e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -4.675107835141866009896710750800622147e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -4.090104965125365961928716504473692957e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -5.842241652296980863361375208605487570e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -1.063604828033747303936724279018650633e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -9.113375972811586130949401996332817152e+00),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 6.334748570425075872639817839399823709e+02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -3.759150758768733692594821032784124765e+04),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.863672813448915255286274382558526321e+06),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -7.798248643371718775489178767529282534e+07),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.769963173932801026451013022000669267e+09),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -8.381780137198278741566746511015220011e+10),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.163891337116820832871382141011952931e+12),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -4.764325864671438675151635117936912390e+13),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 8.925668307403332887856809510525154955e+14),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -1.416692606589060039334938090985713641e+16),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.892398600219306424294729851605944429e+17),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -2.107232903741874160308537145391245060e+18),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.930223393531877588898224144054112045e+19),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -1.427759576167665663373350433236061007e+20),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 8.306019279465532835530812122374386654e+20),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -3.653753000392125229440044977239174472e+21),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.140760686989511568435076842569804906e+22),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -2.249149337812510200795436107962504749e+22),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.101619088427348382058085685849420866e+22)
|
||||
};
|
||||
return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
|
||||
}
|
||||
else if(x < 100)
|
||||
{
|
||||
// Max error in interpolated form: 5.494e-35
|
||||
// Max Error found at float128 precision = Poly: 1.214651e-34
|
||||
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.989422804014326779399307367861631577e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -1.496033551505372542086590873271571919e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -4.675104848454290286276466276677172664e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -4.090716742397105403027549796269213215e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -5.752570419098513588311026680089351230e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -1.107369803696534592906420980901195808e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -2.699214194000085622941721628134575121e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -7.953006169077813678478720427604462133e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -2.746618809476524091493444128605380593e+00),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -1.084446249943196826652788161656973391e+01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -5.020325182518980633783194648285500554e+01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -1.510195971266257573425196228564489134e+02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -5.241661863814900938075696173192225056e+03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.323374362891993686413568398575539777e+05),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -4.112838452096066633754042734723911040e+06),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 9.369270194978310081563767560113534023e+07),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -1.704295412488936504389347368131134993e+09),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.320829576277038198439987439508754886e+10),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -2.258818139077875493434420764260185306e+11),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.396791306321498426110315039064592443e+12),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -4.217617301585849875301440316301068439e+12)
|
||||
};
|
||||
return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Bessel I0 over[100, INF]
|
||||
// Max error in interpolated form: 6.081e-35
|
||||
// Max Error found at float128 precision = Poly: 1.407151e-34
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.9894228040143267793994605993438200208417e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -1.4960335515053725422747977247811372936584e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -4.6751048484542891946087411826356811991039e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -4.0907167423975030452875828826630006305665e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -5.7525704189964886494791082898669060345483e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -1.1073698056568248642163476807108190176386e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -2.6992139012879749064623499618582631684228e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -7.9530409594026597988098934027440110587905e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -2.7462844478733532517044536719240098183686e+00),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -1.0870711340681926669381449306654104739256e+01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -4.8510175413216969245241059608553222505228e+01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -2.4094682286011573747064907919522894740063e+02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -1.3128845936764406865199641778959502795443e+03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -8.1655901321962541203257516341266838487359e+03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -3.8019591025686295090160445920753823994556e+04),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -6.7008089049178178697338128837158732831105e+05)
|
||||
};
|
||||
T ex = exp(x / 2);
|
||||
T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
|
||||
result *= ex;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T bessel_i1_imp(const T& x, const mpl::int_<0>&)
|
||||
{
|
||||
if(boost::math::tools::digits<T>() <= 24)
|
||||
return bessel_i1_imp(x, mpl::int_<24>());
|
||||
else if(boost::math::tools::digits<T>() <= 53)
|
||||
return bessel_i1_imp(x, mpl::int_<53>());
|
||||
else if(boost::math::tools::digits<T>() <= 64)
|
||||
return bessel_i1_imp(x, mpl::int_<64>());
|
||||
else if(boost::math::tools::digits<T>() <= 113)
|
||||
return bessel_i1_imp(x, mpl::int_<113>());
|
||||
BOOST_ASSERT(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T bessel_i1(const T& x)
|
||||
{
|
||||
typedef mpl::int_<
|
||||
((std::numeric_limits<T>::digits == 0) || (std::numeric_limits<T>::radix != 2)) ?
|
||||
0 :
|
||||
std::numeric_limits<T>::digits <= 24 ?
|
||||
24 :
|
||||
std::numeric_limits<T>::digits <= 53 ?
|
||||
53 :
|
||||
std::numeric_limits<T>::digits <= 64 ?
|
||||
64 :
|
||||
std::numeric_limits<T>::digits <= 113 ?
|
||||
113 : -1
|
||||
> tag_type;
|
||||
|
||||
bessel_i1_initializer<T, tag_type>::force_instantiate();
|
||||
return bessel_i1_imp(x, tag_type());
|
||||
}
|
||||
|
||||
}}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_BESSEL_I1_HPP
|
||||
|
||||
451
code_isotrope/boost/math/special_functions/detail/bessel_ik.hpp
Executable file
451
code_isotrope/boost/math/special_functions/detail/bessel_ik.hpp
Executable file
@@ -0,0 +1,451 @@
|
||||
// Copyright (c) 2006 Xiaogang Zhang
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_MATH_BESSEL_IK_HPP
|
||||
#define BOOST_MATH_BESSEL_IK_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/special_functions/round.hpp>
|
||||
#include <boost/math/special_functions/gamma.hpp>
|
||||
#include <boost/math/special_functions/sin_pi.hpp>
|
||||
#include <boost/math/constants/constants.hpp>
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
#include <boost/math/tools/config.hpp>
|
||||
|
||||
// Modified Bessel functions of the first and second kind of fractional order
|
||||
|
||||
namespace boost { namespace math {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <class T, class Policy>
|
||||
struct cyl_bessel_i_small_z
|
||||
{
|
||||
typedef T result_type;
|
||||
|
||||
cyl_bessel_i_small_z(T v_, T z_) : k(0), v(v_), mult(z_*z_/4)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
term = 1;
|
||||
}
|
||||
|
||||
T operator()()
|
||||
{
|
||||
T result = term;
|
||||
++k;
|
||||
term *= mult / k;
|
||||
term /= k + v;
|
||||
return result;
|
||||
}
|
||||
private:
|
||||
unsigned k;
|
||||
T v;
|
||||
T term;
|
||||
T mult;
|
||||
};
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T bessel_i_small_z_series(T v, T x, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
T prefix;
|
||||
if(v < max_factorial<T>::value)
|
||||
{
|
||||
prefix = pow(x / 2, v) / boost::math::tgamma(v + 1, pol);
|
||||
}
|
||||
else
|
||||
{
|
||||
prefix = v * log(x / 2) - boost::math::lgamma(v + 1, pol);
|
||||
prefix = exp(prefix);
|
||||
}
|
||||
if(prefix == 0)
|
||||
return prefix;
|
||||
|
||||
cyl_bessel_i_small_z<T, Policy> s(v, x);
|
||||
boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
|
||||
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
|
||||
T zero = 0;
|
||||
T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon<T, Policy>(), max_iter, zero);
|
||||
#else
|
||||
T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon<T, Policy>(), max_iter);
|
||||
#endif
|
||||
policies::check_series_iterations<T>("boost::math::bessel_j_small_z_series<%1%>(%1%,%1%)", max_iter, pol);
|
||||
return prefix * result;
|
||||
}
|
||||
|
||||
// Calculate K(v, x) and K(v+1, x) by method analogous to
|
||||
// Temme, Journal of Computational Physics, vol 21, 343 (1976)
|
||||
template <typename T, typename Policy>
|
||||
int temme_ik(T v, T x, T* K, T* K1, const Policy& pol)
|
||||
{
|
||||
T f, h, p, q, coef, sum, sum1, tolerance;
|
||||
T a, b, c, d, sigma, gamma1, gamma2;
|
||||
unsigned long k;
|
||||
|
||||
BOOST_MATH_STD_USING
|
||||
using namespace boost::math::tools;
|
||||
using namespace boost::math::constants;
|
||||
|
||||
|
||||
// |x| <= 2, Temme series converge rapidly
|
||||
// |x| > 2, the larger the |x|, the slower the convergence
|
||||
BOOST_ASSERT(abs(x) <= 2);
|
||||
BOOST_ASSERT(abs(v) <= 0.5f);
|
||||
|
||||
T gp = boost::math::tgamma1pm1(v, pol);
|
||||
T gm = boost::math::tgamma1pm1(-v, pol);
|
||||
|
||||
a = log(x / 2);
|
||||
b = exp(v * a);
|
||||
sigma = -a * v;
|
||||
c = abs(v) < tools::epsilon<T>() ?
|
||||
T(1) : T(boost::math::sin_pi(v) / (v * pi<T>()));
|
||||
d = abs(sigma) < tools::epsilon<T>() ?
|
||||
T(1) : T(sinh(sigma) / sigma);
|
||||
gamma1 = abs(v) < tools::epsilon<T>() ?
|
||||
T(-euler<T>()) : T((0.5f / v) * (gp - gm) * c);
|
||||
gamma2 = (2 + gp + gm) * c / 2;
|
||||
|
||||
// initial values
|
||||
p = (gp + 1) / (2 * b);
|
||||
q = (1 + gm) * b / 2;
|
||||
f = (cosh(sigma) * gamma1 + d * (-a) * gamma2) / c;
|
||||
h = p;
|
||||
coef = 1;
|
||||
sum = coef * f;
|
||||
sum1 = coef * h;
|
||||
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(p);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(q);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(f);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(sigma);
|
||||
BOOST_MATH_INSTRUMENT_CODE(sinh(sigma));
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(gamma1);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(gamma2);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(c);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(d);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(a);
|
||||
|
||||
// series summation
|
||||
tolerance = tools::epsilon<T>();
|
||||
for (k = 1; k < policies::get_max_series_iterations<Policy>(); k++)
|
||||
{
|
||||
f = (k * f + p + q) / (k*k - v*v);
|
||||
p /= k - v;
|
||||
q /= k + v;
|
||||
h = p - k * f;
|
||||
coef *= x * x / (4 * k);
|
||||
sum += coef * f;
|
||||
sum1 += coef * h;
|
||||
if (abs(coef * f) < abs(sum) * tolerance)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
policies::check_series_iterations<T>("boost::math::bessel_ik<%1%>(%1%,%1%) in temme_ik", k, pol);
|
||||
|
||||
*K = sum;
|
||||
*K1 = 2 * sum1 / x;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Evaluate continued fraction fv = I_(v+1) / I_v, derived from
|
||||
// Abramowitz and Stegun, Handbook of Mathematical Functions, 1972, 9.1.73
|
||||
template <typename T, typename Policy>
|
||||
int CF1_ik(T v, T x, T* fv, const Policy& pol)
|
||||
{
|
||||
T C, D, f, a, b, delta, tiny, tolerance;
|
||||
unsigned long k;
|
||||
|
||||
BOOST_MATH_STD_USING
|
||||
|
||||
// |x| <= |v|, CF1_ik converges rapidly
|
||||
// |x| > |v|, CF1_ik needs O(|x|) iterations to converge
|
||||
|
||||
// modified Lentz's method, see
|
||||
// Lentz, Applied Optics, vol 15, 668 (1976)
|
||||
tolerance = 2 * tools::epsilon<T>();
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(tolerance);
|
||||
tiny = sqrt(tools::min_value<T>());
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(tiny);
|
||||
C = f = tiny; // b0 = 0, replace with tiny
|
||||
D = 0;
|
||||
for (k = 1; k < policies::get_max_series_iterations<Policy>(); k++)
|
||||
{
|
||||
a = 1;
|
||||
b = 2 * (v + k) / x;
|
||||
C = b + a / C;
|
||||
D = b + a * D;
|
||||
if (C == 0) { C = tiny; }
|
||||
if (D == 0) { D = tiny; }
|
||||
D = 1 / D;
|
||||
delta = C * D;
|
||||
f *= delta;
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(delta-1);
|
||||
if (abs(delta - 1) <= tolerance)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(k);
|
||||
policies::check_series_iterations<T>("boost::math::bessel_ik<%1%>(%1%,%1%) in CF1_ik", k, pol);
|
||||
|
||||
*fv = f;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Calculate K(v, x) and K(v+1, x) by evaluating continued fraction
|
||||
// z1 / z0 = U(v+1.5, 2v+1, 2x) / U(v+0.5, 2v+1, 2x), see
|
||||
// Thompson and Barnett, Computer Physics Communications, vol 47, 245 (1987)
|
||||
template <typename T, typename Policy>
|
||||
int CF2_ik(T v, T x, T* Kv, T* Kv1, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
using namespace boost::math::constants;
|
||||
|
||||
T S, C, Q, D, f, a, b, q, delta, tolerance, current, prev;
|
||||
unsigned long k;
|
||||
|
||||
// |x| >= |v|, CF2_ik converges rapidly
|
||||
// |x| -> 0, CF2_ik fails to converge
|
||||
|
||||
BOOST_ASSERT(abs(x) > 1);
|
||||
|
||||
// Steed's algorithm, see Thompson and Barnett,
|
||||
// Journal of Computational Physics, vol 64, 490 (1986)
|
||||
tolerance = tools::epsilon<T>();
|
||||
a = v * v - 0.25f;
|
||||
b = 2 * (x + 1); // b1
|
||||
D = 1 / b; // D1 = 1 / b1
|
||||
f = delta = D; // f1 = delta1 = D1, coincidence
|
||||
prev = 0; // q0
|
||||
current = 1; // q1
|
||||
Q = C = -a; // Q1 = C1 because q1 = 1
|
||||
S = 1 + Q * delta; // S1
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(tolerance);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(a);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(b);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(D);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(f);
|
||||
|
||||
for (k = 2; k < policies::get_max_series_iterations<Policy>(); k++) // starting from 2
|
||||
{
|
||||
// continued fraction f = z1 / z0
|
||||
a -= 2 * (k - 1);
|
||||
b += 2;
|
||||
D = 1 / (b + a * D);
|
||||
delta *= b * D - 1;
|
||||
f += delta;
|
||||
|
||||
// series summation S = 1 + \sum_{n=1}^{\infty} C_n * z_n / z_0
|
||||
q = (prev - (b - 2) * current) / a;
|
||||
prev = current;
|
||||
current = q; // forward recurrence for q
|
||||
C *= -a / k;
|
||||
Q += C * q;
|
||||
S += Q * delta;
|
||||
//
|
||||
// Under some circumstances q can grow very small and C very
|
||||
// large, leading to under/overflow. This is particularly an
|
||||
// issue for types which have many digits precision but a narrow
|
||||
// exponent range. A typical example being a "double double" type.
|
||||
// To avoid this situation we can normalise q (and related prev/current)
|
||||
// and C. All other variables remain unchanged in value. A typical
|
||||
// test case occurs when x is close to 2, for example cyl_bessel_k(9.125, 2.125).
|
||||
//
|
||||
if(q < tools::epsilon<T>())
|
||||
{
|
||||
C *= q;
|
||||
prev /= q;
|
||||
current /= q;
|
||||
q = 1;
|
||||
}
|
||||
|
||||
// S converges slower than f
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(Q * delta);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(abs(S) * tolerance);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(S);
|
||||
if (abs(Q * delta) < abs(S) * tolerance)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
policies::check_series_iterations<T>("boost::math::bessel_ik<%1%>(%1%,%1%) in CF2_ik", k, pol);
|
||||
|
||||
if(x >= tools::log_max_value<T>())
|
||||
*Kv = exp(0.5f * log(pi<T>() / (2 * x)) - x - log(S));
|
||||
else
|
||||
*Kv = sqrt(pi<T>() / (2 * x)) * exp(-x) / S;
|
||||
*Kv1 = *Kv * (0.5f + v + x + (v * v - 0.25f) * f) / x;
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(*Kv);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(*Kv1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum{
|
||||
need_i = 1,
|
||||
need_k = 2
|
||||
};
|
||||
|
||||
// Compute I(v, x) and K(v, x) simultaneously by Temme's method, see
|
||||
// Temme, Journal of Computational Physics, vol 19, 324 (1975)
|
||||
template <typename T, typename Policy>
|
||||
int bessel_ik(T v, T x, T* I, T* K, int kind, const Policy& pol)
|
||||
{
|
||||
// Kv1 = K_(v+1), fv = I_(v+1) / I_v
|
||||
// Ku1 = K_(u+1), fu = I_(u+1) / I_u
|
||||
T u, Iv, Kv, Kv1, Ku, Ku1, fv;
|
||||
T W, current, prev, next;
|
||||
bool reflect = false;
|
||||
unsigned n, k;
|
||||
int org_kind = kind;
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(v);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(x);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(kind);
|
||||
|
||||
BOOST_MATH_STD_USING
|
||||
using namespace boost::math::tools;
|
||||
using namespace boost::math::constants;
|
||||
|
||||
static const char* function = "boost::math::bessel_ik<%1%>(%1%,%1%)";
|
||||
|
||||
if (v < 0)
|
||||
{
|
||||
reflect = true;
|
||||
v = -v; // v is non-negative from here
|
||||
kind |= need_k;
|
||||
}
|
||||
n = iround(v, pol);
|
||||
u = v - n; // -1/2 <= u < 1/2
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(n);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(u);
|
||||
|
||||
if (x < 0)
|
||||
{
|
||||
*I = *K = policies::raise_domain_error<T>(function,
|
||||
"Got x = %1% but real argument x must be non-negative, complex number result not supported.", x, pol);
|
||||
return 1;
|
||||
}
|
||||
if (x == 0)
|
||||
{
|
||||
Iv = (v == 0) ? static_cast<T>(1) : static_cast<T>(0);
|
||||
if(kind & need_k)
|
||||
{
|
||||
Kv = policies::raise_overflow_error<T>(function, 0, pol);
|
||||
}
|
||||
else
|
||||
{
|
||||
Kv = std::numeric_limits<T>::quiet_NaN(); // any value will do
|
||||
}
|
||||
|
||||
if(reflect && (kind & need_i))
|
||||
{
|
||||
T z = (u + n % 2);
|
||||
Iv = boost::math::sin_pi(z, pol) == 0 ?
|
||||
Iv :
|
||||
policies::raise_overflow_error<T>(function, 0, pol); // reflection formula
|
||||
}
|
||||
|
||||
*I = Iv;
|
||||
*K = Kv;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// x is positive until reflection
|
||||
W = 1 / x; // Wronskian
|
||||
if (x <= 2) // x in (0, 2]
|
||||
{
|
||||
temme_ik(u, x, &Ku, &Ku1, pol); // Temme series
|
||||
}
|
||||
else // x in (2, \infty)
|
||||
{
|
||||
CF2_ik(u, x, &Ku, &Ku1, pol); // continued fraction CF2_ik
|
||||
}
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(Ku);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(Ku1);
|
||||
prev = Ku;
|
||||
current = Ku1;
|
||||
T scale = 1;
|
||||
T scale_sign = 1;
|
||||
for (k = 1; k <= n; k++) // forward recurrence for K
|
||||
{
|
||||
T fact = 2 * (u + k) / x;
|
||||
if((tools::max_value<T>() - fabs(prev)) / fact < fabs(current))
|
||||
{
|
||||
prev /= current;
|
||||
scale /= current;
|
||||
scale_sign *= boost::math::sign(current);
|
||||
current = 1;
|
||||
}
|
||||
next = fact * current + prev;
|
||||
prev = current;
|
||||
current = next;
|
||||
}
|
||||
Kv = prev;
|
||||
Kv1 = current;
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(Kv);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(Kv1);
|
||||
if(kind & need_i)
|
||||
{
|
||||
T lim = (4 * v * v + 10) / (8 * x);
|
||||
lim *= lim;
|
||||
lim *= lim;
|
||||
lim /= 24;
|
||||
if((lim < tools::epsilon<T>() * 10) && (x > 100))
|
||||
{
|
||||
// x is huge compared to v, CF1 may be very slow
|
||||
// to converge so use asymptotic expansion for large
|
||||
// x case instead. Note that the asymptotic expansion
|
||||
// isn't very accurate - so it's deliberately very hard
|
||||
// to get here - probably we're going to overflow:
|
||||
Iv = asymptotic_bessel_i_large_x(v, x, pol);
|
||||
}
|
||||
else if((v > 0) && (x / v < 0.25))
|
||||
{
|
||||
Iv = bessel_i_small_z_series(v, x, pol);
|
||||
}
|
||||
else
|
||||
{
|
||||
CF1_ik(v, x, &fv, pol); // continued fraction CF1_ik
|
||||
Iv = scale * W / (Kv * fv + Kv1); // Wronskian relation
|
||||
}
|
||||
}
|
||||
else
|
||||
Iv = std::numeric_limits<T>::quiet_NaN(); // any value will do
|
||||
|
||||
if (reflect)
|
||||
{
|
||||
T z = (u + n % 2);
|
||||
T fact = (2 / pi<T>()) * (boost::math::sin_pi(z) * Kv);
|
||||
if(fact == 0)
|
||||
*I = Iv;
|
||||
else if(tools::max_value<T>() * scale < fact)
|
||||
*I = (org_kind & need_i) ? T(sign(fact) * scale_sign * policies::raise_overflow_error<T>(function, 0, pol)) : T(0);
|
||||
else
|
||||
*I = Iv + fact / scale; // reflection formula
|
||||
}
|
||||
else
|
||||
{
|
||||
*I = Iv;
|
||||
}
|
||||
if(tools::max_value<T>() * scale < Kv)
|
||||
*K = (org_kind & need_k) ? T(sign(Kv) * scale_sign * policies::raise_overflow_error<T>(function, 0, pol)) : T(0);
|
||||
else
|
||||
*K = Kv / scale;
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(*I);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(*K);
|
||||
return 0;
|
||||
}
|
||||
|
||||
}}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_BESSEL_IK_HPP
|
||||
|
||||
193
code_isotrope/boost/math/special_functions/detail/bessel_j0.hpp
Executable file
193
code_isotrope/boost/math/special_functions/detail/bessel_j0.hpp
Executable file
@@ -0,0 +1,193 @@
|
||||
// Copyright (c) 2006 Xiaogang Zhang
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_MATH_BESSEL_J0_HPP
|
||||
#define BOOST_MATH_BESSEL_J0_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/constants/constants.hpp>
|
||||
#include <boost/math/tools/rational.hpp>
|
||||
#include <boost/math/tools/big_constant.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
// Bessel function of the first kind of order zero
|
||||
// x <= 8, minimax rational approximations on root-bracketing intervals
|
||||
// x > 8, Hankel asymptotic expansion in Hart, Computer Approximations, 1968
|
||||
|
||||
namespace boost { namespace math { namespace detail{
|
||||
|
||||
template <typename T>
|
||||
T bessel_j0(T x);
|
||||
|
||||
template <class T>
|
||||
struct bessel_j0_initializer
|
||||
{
|
||||
struct init
|
||||
{
|
||||
init()
|
||||
{
|
||||
do_init();
|
||||
}
|
||||
static void do_init()
|
||||
{
|
||||
bessel_j0(T(1));
|
||||
}
|
||||
void force_instantiate()const{}
|
||||
};
|
||||
static const init initializer;
|
||||
static void force_instantiate()
|
||||
{
|
||||
initializer.force_instantiate();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
const typename bessel_j0_initializer<T>::init bessel_j0_initializer<T>::initializer;
|
||||
|
||||
template <typename T>
|
||||
T bessel_j0(T x)
|
||||
{
|
||||
bessel_j0_initializer<T>::force_instantiate();
|
||||
|
||||
static const T P1[] = {
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -4.1298668500990866786e+11)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.7282507878605942706e+10)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -6.2140700423540120665e+08)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 6.6302997904833794242e+06)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -3.6629814655107086448e+04)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0344222815443188943e+02)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.2117036164593528341e-01))
|
||||
};
|
||||
static const T Q1[] = {
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.3883787996332290397e+12)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.6328198300859648632e+10)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.3985097372263433271e+08)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.5612696224219938200e+05)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 9.3614022392337710626e+02)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.0))
|
||||
};
|
||||
static const T P2[] = {
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.8319397969392084011e+03)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.2254078161378989535e+04)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -7.2879702464464618998e+03)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0341910641583726701e+04)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.1725046279757103576e+04)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.4176707025325087628e+03)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 7.4321196680624245801e+02)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.8591703355916499363e+01))
|
||||
};
|
||||
static const T Q2[] = {
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -3.5783478026152301072e+05)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.4599102262586308984e+05)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -8.4055062591169562211e+04)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.8680990008359188352e+04)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -2.9458766545509337327e+03)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.3307310774649071172e+02)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -2.5258076240801555057e+01)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0))
|
||||
};
|
||||
static const T PC[] = {
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.2779090197304684302e+04)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.1345386639580765797e+04)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.1170523380864944322e+04)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.4806486443249270347e+03)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.5376201909008354296e+02)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 8.8961548424210455236e-01))
|
||||
};
|
||||
static const T QC[] = {
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.2779090197304684318e+04)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.1370412495510416640e+04)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.1215350561880115730e+04)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.5028735138235608207e+03)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.5711159858080893649e+02)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0))
|
||||
};
|
||||
static const T PS[] = {
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -8.9226600200800094098e+01)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.8591953644342993800e+02)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.1183429920482737611e+02)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -2.2300261666214198472e+01)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.2441026745835638459e+00)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -8.8033303048680751817e-03))
|
||||
};
|
||||
static const T QS[] = {
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 5.7105024128512061905e+03)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.1951131543434613647e+04)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 7.2642780169211018836e+03)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.4887231232283756582e+03)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 9.0593769594993125859e+01)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0))
|
||||
};
|
||||
static const T x1 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.4048255576957727686e+00)),
|
||||
x2 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 5.5200781102863106496e+00)),
|
||||
x11 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 6.160e+02)),
|
||||
x12 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.42444230422723137837e-03)),
|
||||
x21 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.4130e+03)),
|
||||
x22 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 5.46860286310649596604e-04));
|
||||
|
||||
T value, factor, r, rc, rs;
|
||||
|
||||
BOOST_MATH_STD_USING
|
||||
using namespace boost::math::tools;
|
||||
using namespace boost::math::constants;
|
||||
|
||||
if (x < 0)
|
||||
{
|
||||
x = -x; // even function
|
||||
}
|
||||
if (x == 0)
|
||||
{
|
||||
return static_cast<T>(1);
|
||||
}
|
||||
if (x <= 4) // x in (0, 4]
|
||||
{
|
||||
T y = x * x;
|
||||
BOOST_ASSERT(sizeof(P1) == sizeof(Q1));
|
||||
r = evaluate_rational(P1, Q1, y);
|
||||
factor = (x + x1) * ((x - x11/256) - x12);
|
||||
value = factor * r;
|
||||
}
|
||||
else if (x <= 8.0) // x in (4, 8]
|
||||
{
|
||||
T y = 1 - (x * x)/64;
|
||||
BOOST_ASSERT(sizeof(P2) == sizeof(Q2));
|
||||
r = evaluate_rational(P2, Q2, y);
|
||||
factor = (x + x2) * ((x - x21/256) - x22);
|
||||
value = factor * r;
|
||||
}
|
||||
else // x in (8, \infty)
|
||||
{
|
||||
T y = 8 / x;
|
||||
T y2 = y * y;
|
||||
BOOST_ASSERT(sizeof(PC) == sizeof(QC));
|
||||
BOOST_ASSERT(sizeof(PS) == sizeof(QS));
|
||||
rc = evaluate_rational(PC, QC, y2);
|
||||
rs = evaluate_rational(PS, QS, y2);
|
||||
factor = constants::one_div_root_pi<T>() / sqrt(x);
|
||||
//
|
||||
// What follows is really just:
|
||||
//
|
||||
// T z = x - pi/4;
|
||||
// value = factor * (rc * cos(z) - y * rs * sin(z));
|
||||
//
|
||||
// But using the addition formulae for sin and cos, plus
|
||||
// the special values for sin/cos of pi/4.
|
||||
//
|
||||
T sx = sin(x);
|
||||
T cx = cos(x);
|
||||
value = factor * (rc * (cx + sx) - y * rs * (sx - cx));
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
}}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_BESSEL_J0_HPP
|
||||
|
||||
199
code_isotrope/boost/math/special_functions/detail/bessel_j1.hpp
Executable file
199
code_isotrope/boost/math/special_functions/detail/bessel_j1.hpp
Executable file
@@ -0,0 +1,199 @@
|
||||
// Copyright (c) 2006 Xiaogang Zhang
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_MATH_BESSEL_J1_HPP
|
||||
#define BOOST_MATH_BESSEL_J1_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/constants/constants.hpp>
|
||||
#include <boost/math/tools/rational.hpp>
|
||||
#include <boost/math/tools/big_constant.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
// Bessel function of the first kind of order one
|
||||
// x <= 8, minimax rational approximations on root-bracketing intervals
|
||||
// x > 8, Hankel asymptotic expansion in Hart, Computer Approximations, 1968
|
||||
|
||||
namespace boost { namespace math{ namespace detail{
|
||||
|
||||
template <typename T>
|
||||
T bessel_j1(T x);
|
||||
|
||||
template <class T>
|
||||
struct bessel_j1_initializer
|
||||
{
|
||||
struct init
|
||||
{
|
||||
init()
|
||||
{
|
||||
do_init();
|
||||
}
|
||||
static void do_init()
|
||||
{
|
||||
bessel_j1(T(1));
|
||||
}
|
||||
void force_instantiate()const{}
|
||||
};
|
||||
static const init initializer;
|
||||
static void force_instantiate()
|
||||
{
|
||||
initializer.force_instantiate();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
const typename bessel_j1_initializer<T>::init bessel_j1_initializer<T>::initializer;
|
||||
|
||||
template <typename T>
|
||||
T bessel_j1(T x)
|
||||
{
|
||||
bessel_j1_initializer<T>::force_instantiate();
|
||||
|
||||
static const T P1[] = {
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.4258509801366645672e+11)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 6.6781041261492395835e+09)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.1548696764841276794e+08)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 9.8062904098958257677e+05)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -4.4615792982775076130e+03)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0650724020080236441e+01)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.0767857011487300348e-02))
|
||||
};
|
||||
static const T Q1[] = {
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.1868604460820175290e+12)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.2091902282580133541e+10)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.0228375140097033958e+08)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 5.9117614494174794095e+05)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0742272239517380498e+03)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.0))
|
||||
};
|
||||
static const T P2[] = {
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.7527881995806511112e+16)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.6608531731299018674e+15)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -3.6658018905416665164e+13)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.5580665670910619166e+11)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.8113931269860667829e+09)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 5.0793266148011179143e+06)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -7.5023342220781607561e+03)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.6179191852758252278e+00))
|
||||
};
|
||||
static const T Q2[] = {
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.7253905888447681194e+18)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.7128800897135812012e+16)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 8.4899346165481429307e+13)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.7622777286244082666e+11)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 6.4872502899596389593e+08)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.1267125065029138050e+06)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.3886978985861357615e+03)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0))
|
||||
};
|
||||
static const T PC[] = {
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -4.4357578167941278571e+06)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -9.9422465050776411957e+06)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -6.6033732483649391093e+06)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.5235293511811373833e+06)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.0982405543459346727e+05)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.6116166443246101165e+03)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.0))
|
||||
};
|
||||
static const T QC[] = {
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -4.4357578167941278568e+06)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -9.9341243899345856590e+06)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -6.5853394797230870728e+06)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.5118095066341608816e+06)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.0726385991103820119e+05)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.4550094401904961825e+03)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0))
|
||||
};
|
||||
static const T PS[] = {
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.3220913409857223519e+04)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 8.5145160675335701966e+04)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 6.6178836581270835179e+04)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.8494262873223866797e+04)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.7063754290207680021e+03)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.5265133846636032186e+01)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.0))
|
||||
};
|
||||
static const T QS[] = {
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 7.0871281941028743574e+05)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.8194580422439972989e+06)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.4194606696037208929e+06)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.0029443582266975117e+05)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.7890229745772202641e+04)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 8.6383677696049909675e+02)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0))
|
||||
};
|
||||
static const T x1 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.8317059702075123156e+00)),
|
||||
x2 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 7.0155866698156187535e+00)),
|
||||
x11 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 9.810e+02)),
|
||||
x12 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -3.2527979248768438556e-04)),
|
||||
x21 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.7960e+03)),
|
||||
x22 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -3.8330184381246462950e-05));
|
||||
|
||||
T value, factor, r, rc, rs, w;
|
||||
|
||||
BOOST_MATH_STD_USING
|
||||
using namespace boost::math::tools;
|
||||
using namespace boost::math::constants;
|
||||
|
||||
w = abs(x);
|
||||
if (x == 0)
|
||||
{
|
||||
return static_cast<T>(0);
|
||||
}
|
||||
if (w <= 4) // w in (0, 4]
|
||||
{
|
||||
T y = x * x;
|
||||
BOOST_ASSERT(sizeof(P1) == sizeof(Q1));
|
||||
r = evaluate_rational(P1, Q1, y);
|
||||
factor = w * (w + x1) * ((w - x11/256) - x12);
|
||||
value = factor * r;
|
||||
}
|
||||
else if (w <= 8) // w in (4, 8]
|
||||
{
|
||||
T y = x * x;
|
||||
BOOST_ASSERT(sizeof(P2) == sizeof(Q2));
|
||||
r = evaluate_rational(P2, Q2, y);
|
||||
factor = w * (w + x2) * ((w - x21/256) - x22);
|
||||
value = factor * r;
|
||||
}
|
||||
else // w in (8, \infty)
|
||||
{
|
||||
T y = 8 / w;
|
||||
T y2 = y * y;
|
||||
BOOST_ASSERT(sizeof(PC) == sizeof(QC));
|
||||
BOOST_ASSERT(sizeof(PS) == sizeof(QS));
|
||||
rc = evaluate_rational(PC, QC, y2);
|
||||
rs = evaluate_rational(PS, QS, y2);
|
||||
factor = 1 / (sqrt(w) * constants::root_pi<T>());
|
||||
//
|
||||
// What follows is really just:
|
||||
//
|
||||
// T z = w - 0.75f * pi<T>();
|
||||
// value = factor * (rc * cos(z) - y * rs * sin(z));
|
||||
//
|
||||
// but using the sin/cos addition rules plus constants
|
||||
// for the values of sin/cos of 3PI/4 which then cancel
|
||||
// out with corresponding terms in "factor".
|
||||
//
|
||||
T sx = sin(x);
|
||||
T cx = cos(x);
|
||||
value = factor * (rc * (sx - cx) + y * rs * (sx + cx));
|
||||
}
|
||||
|
||||
if (x < 0)
|
||||
{
|
||||
value *= -1; // odd function
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
}}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_BESSEL_J1_HPP
|
||||
|
||||
133
code_isotrope/boost/math/special_functions/detail/bessel_jn.hpp
Executable file
133
code_isotrope/boost/math/special_functions/detail/bessel_jn.hpp
Executable file
@@ -0,0 +1,133 @@
|
||||
// Copyright (c) 2006 Xiaogang Zhang
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_MATH_BESSEL_JN_HPP
|
||||
#define BOOST_MATH_BESSEL_JN_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/special_functions/detail/bessel_j0.hpp>
|
||||
#include <boost/math/special_functions/detail/bessel_j1.hpp>
|
||||
#include <boost/math/special_functions/detail/bessel_jy.hpp>
|
||||
#include <boost/math/special_functions/detail/bessel_jy_asym.hpp>
|
||||
#include <boost/math/special_functions/detail/bessel_jy_series.hpp>
|
||||
|
||||
// Bessel function of the first kind of integer order
|
||||
// J_n(z) is the minimal solution
|
||||
// n < abs(z), forward recurrence stable and usable
|
||||
// n >= abs(z), forward recurrence unstable, use Miller's algorithm
|
||||
|
||||
namespace boost { namespace math { namespace detail{
|
||||
|
||||
template <typename T, typename Policy>
|
||||
T bessel_jn(int n, T x, const Policy& pol)
|
||||
{
|
||||
T value(0), factor, current, prev, next;
|
||||
|
||||
BOOST_MATH_STD_USING
|
||||
|
||||
//
|
||||
// Reflection has to come first:
|
||||
//
|
||||
if (n < 0)
|
||||
{
|
||||
factor = static_cast<T>((n & 0x1) ? -1 : 1); // J_{-n}(z) = (-1)^n J_n(z)
|
||||
n = -n;
|
||||
}
|
||||
else
|
||||
{
|
||||
factor = 1;
|
||||
}
|
||||
if(x < 0)
|
||||
{
|
||||
factor *= (n & 0x1) ? -1 : 1; // J_{n}(-z) = (-1)^n J_n(z)
|
||||
x = -x;
|
||||
}
|
||||
//
|
||||
// Special cases:
|
||||
//
|
||||
if(asymptotic_bessel_large_x_limit(T(n), x))
|
||||
return factor * asymptotic_bessel_j_large_x_2<T>(T(n), x);
|
||||
if (n == 0)
|
||||
{
|
||||
return factor * bessel_j0(x);
|
||||
}
|
||||
if (n == 1)
|
||||
{
|
||||
return factor * bessel_j1(x);
|
||||
}
|
||||
|
||||
if (x == 0) // n >= 2
|
||||
{
|
||||
return static_cast<T>(0);
|
||||
}
|
||||
|
||||
BOOST_ASSERT(n > 1);
|
||||
T scale = 1;
|
||||
if (n < abs(x)) // forward recurrence
|
||||
{
|
||||
prev = bessel_j0(x);
|
||||
current = bessel_j1(x);
|
||||
policies::check_series_iterations<T>("boost::math::bessel_j_n<%1%>(%1%,%1%)", n, pol);
|
||||
for (int k = 1; k < n; k++)
|
||||
{
|
||||
T fact = 2 * k / x;
|
||||
//
|
||||
// rescale if we would overflow or underflow:
|
||||
//
|
||||
if((fabs(fact) > 1) && ((tools::max_value<T>() - fabs(prev)) / fabs(fact) < fabs(current)))
|
||||
{
|
||||
scale /= current;
|
||||
prev /= current;
|
||||
current = 1;
|
||||
}
|
||||
value = fact * current - prev;
|
||||
prev = current;
|
||||
current = value;
|
||||
}
|
||||
}
|
||||
else if((x < 1) || (n > x * x / 4) || (x < 5))
|
||||
{
|
||||
return factor * bessel_j_small_z_series(T(n), x, pol);
|
||||
}
|
||||
else // backward recurrence
|
||||
{
|
||||
T fn; int s; // fn = J_(n+1) / J_n
|
||||
// |x| <= n, fast convergence for continued fraction CF1
|
||||
boost::math::detail::CF1_jy(static_cast<T>(n), x, &fn, &s, pol);
|
||||
prev = fn;
|
||||
current = 1;
|
||||
// Check recursion won't go on too far:
|
||||
policies::check_series_iterations<T>("boost::math::bessel_j_n<%1%>(%1%,%1%)", n, pol);
|
||||
for (int k = n; k > 0; k--)
|
||||
{
|
||||
T fact = 2 * k / x;
|
||||
if((fabs(fact) > 1) && ((tools::max_value<T>() - fabs(prev)) / fabs(fact) < fabs(current)))
|
||||
{
|
||||
prev /= current;
|
||||
scale /= current;
|
||||
current = 1;
|
||||
}
|
||||
next = fact * current - prev;
|
||||
prev = current;
|
||||
current = next;
|
||||
}
|
||||
value = bessel_j0(x) / current; // normalization
|
||||
scale = 1 / scale;
|
||||
}
|
||||
value *= factor;
|
||||
|
||||
if(tools::max_value<T>() * scale < fabs(value))
|
||||
return policies::raise_overflow_error<T>("boost::math::bessel_jn<%1%>(%1%,%1%)", 0, pol);
|
||||
|
||||
return value / scale;
|
||||
}
|
||||
|
||||
}}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_BESSEL_JN_HPP
|
||||
|
||||
589
code_isotrope/boost/math/special_functions/detail/bessel_jy.hpp
Executable file
589
code_isotrope/boost/math/special_functions/detail/bessel_jy.hpp
Executable file
@@ -0,0 +1,589 @@
|
||||
// Copyright (c) 2006 Xiaogang Zhang
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_MATH_BESSEL_JY_HPP
|
||||
#define BOOST_MATH_BESSEL_JY_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/tools/config.hpp>
|
||||
#include <boost/math/special_functions/gamma.hpp>
|
||||
#include <boost/math/special_functions/sign.hpp>
|
||||
#include <boost/math/special_functions/hypot.hpp>
|
||||
#include <boost/math/special_functions/sin_pi.hpp>
|
||||
#include <boost/math/special_functions/cos_pi.hpp>
|
||||
#include <boost/math/special_functions/detail/bessel_jy_asym.hpp>
|
||||
#include <boost/math/special_functions/detail/bessel_jy_series.hpp>
|
||||
#include <boost/math/constants/constants.hpp>
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/type_traits/is_floating_point.hpp>
|
||||
#include <complex>
|
||||
|
||||
// Bessel functions of the first and second kind of fractional order
|
||||
|
||||
namespace boost { namespace math {
|
||||
|
||||
namespace detail {
|
||||
|
||||
//
|
||||
// Simultaneous calculation of A&S 9.2.9 and 9.2.10
|
||||
// for use in A&S 9.2.5 and 9.2.6.
|
||||
// This series is quick to evaluate, but divergent unless
|
||||
// x is very large, in fact it's pretty hard to figure out
|
||||
// with any degree of precision when this series actually
|
||||
// *will* converge!! Consequently, we may just have to
|
||||
// try it and see...
|
||||
//
|
||||
template <class T, class Policy>
|
||||
bool hankel_PQ(T v, T x, T* p, T* q, const Policy& )
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
T tolerance = 2 * policies::get_epsilon<T, Policy>();
|
||||
*p = 1;
|
||||
*q = 0;
|
||||
T k = 1;
|
||||
T z8 = 8 * x;
|
||||
T sq = 1;
|
||||
T mu = 4 * v * v;
|
||||
T term = 1;
|
||||
bool ok = true;
|
||||
do
|
||||
{
|
||||
term *= (mu - sq * sq) / (k * z8);
|
||||
*q += term;
|
||||
k += 1;
|
||||
sq += 2;
|
||||
T mult = (sq * sq - mu) / (k * z8);
|
||||
ok = fabs(mult) < 0.5f;
|
||||
term *= mult;
|
||||
*p += term;
|
||||
k += 1;
|
||||
sq += 2;
|
||||
}
|
||||
while((fabs(term) > tolerance * *p) && ok);
|
||||
return ok;
|
||||
}
|
||||
|
||||
// Calculate Y(v, x) and Y(v+1, x) by Temme's method, see
|
||||
// Temme, Journal of Computational Physics, vol 21, 343 (1976)
|
||||
template <typename T, typename Policy>
|
||||
int temme_jy(T v, T x, T* Y, T* Y1, const Policy& pol)
|
||||
{
|
||||
T g, h, p, q, f, coef, sum, sum1, tolerance;
|
||||
T a, d, e, sigma;
|
||||
unsigned long k;
|
||||
|
||||
BOOST_MATH_STD_USING
|
||||
using namespace boost::math::tools;
|
||||
using namespace boost::math::constants;
|
||||
|
||||
BOOST_ASSERT(fabs(v) <= 0.5f); // precondition for using this routine
|
||||
|
||||
T gp = boost::math::tgamma1pm1(v, pol);
|
||||
T gm = boost::math::tgamma1pm1(-v, pol);
|
||||
T spv = boost::math::sin_pi(v, pol);
|
||||
T spv2 = boost::math::sin_pi(v/2, pol);
|
||||
T xp = pow(x/2, v);
|
||||
|
||||
a = log(x / 2);
|
||||
sigma = -a * v;
|
||||
d = abs(sigma) < tools::epsilon<T>() ?
|
||||
T(1) : sinh(sigma) / sigma;
|
||||
e = abs(v) < tools::epsilon<T>() ? T(v*pi<T>()*pi<T>() / 2)
|
||||
: T(2 * spv2 * spv2 / v);
|
||||
|
||||
T g1 = (v == 0) ? T(-euler<T>()) : T((gp - gm) / ((1 + gp) * (1 + gm) * 2 * v));
|
||||
T g2 = (2 + gp + gm) / ((1 + gp) * (1 + gm) * 2);
|
||||
T vspv = (fabs(v) < tools::epsilon<T>()) ? T(1/constants::pi<T>()) : T(v / spv);
|
||||
f = (g1 * cosh(sigma) - g2 * a * d) * 2 * vspv;
|
||||
|
||||
p = vspv / (xp * (1 + gm));
|
||||
q = vspv * xp / (1 + gp);
|
||||
|
||||
g = f + e * q;
|
||||
h = p;
|
||||
coef = 1;
|
||||
sum = coef * g;
|
||||
sum1 = coef * h;
|
||||
|
||||
T v2 = v * v;
|
||||
T coef_mult = -x * x / 4;
|
||||
|
||||
// series summation
|
||||
tolerance = policies::get_epsilon<T, Policy>();
|
||||
for (k = 1; k < policies::get_max_series_iterations<Policy>(); k++)
|
||||
{
|
||||
f = (k * f + p + q) / (k*k - v2);
|
||||
p /= k - v;
|
||||
q /= k + v;
|
||||
g = f + e * q;
|
||||
h = p - k * g;
|
||||
coef *= coef_mult / k;
|
||||
sum += coef * g;
|
||||
sum1 += coef * h;
|
||||
if (abs(coef * g) < abs(sum) * tolerance)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
policies::check_series_iterations<T>("boost::math::bessel_jy<%1%>(%1%,%1%) in temme_jy", k, pol);
|
||||
*Y = -sum;
|
||||
*Y1 = -2 * sum1 / x;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Evaluate continued fraction fv = J_(v+1) / J_v, see
|
||||
// Abramowitz and Stegun, Handbook of Mathematical Functions, 1972, 9.1.73
|
||||
template <typename T, typename Policy>
|
||||
int CF1_jy(T v, T x, T* fv, int* sign, const Policy& pol)
|
||||
{
|
||||
T C, D, f, a, b, delta, tiny, tolerance;
|
||||
unsigned long k;
|
||||
int s = 1;
|
||||
|
||||
BOOST_MATH_STD_USING
|
||||
|
||||
// |x| <= |v|, CF1_jy converges rapidly
|
||||
// |x| > |v|, CF1_jy needs O(|x|) iterations to converge
|
||||
|
||||
// modified Lentz's method, see
|
||||
// Lentz, Applied Optics, vol 15, 668 (1976)
|
||||
tolerance = 2 * policies::get_epsilon<T, Policy>();;
|
||||
tiny = sqrt(tools::min_value<T>());
|
||||
C = f = tiny; // b0 = 0, replace with tiny
|
||||
D = 0;
|
||||
for (k = 1; k < policies::get_max_series_iterations<Policy>() * 100; k++)
|
||||
{
|
||||
a = -1;
|
||||
b = 2 * (v + k) / x;
|
||||
C = b + a / C;
|
||||
D = b + a * D;
|
||||
if (C == 0) { C = tiny; }
|
||||
if (D == 0) { D = tiny; }
|
||||
D = 1 / D;
|
||||
delta = C * D;
|
||||
f *= delta;
|
||||
if (D < 0) { s = -s; }
|
||||
if (abs(delta - 1) < tolerance)
|
||||
{ break; }
|
||||
}
|
||||
policies::check_series_iterations<T>("boost::math::bessel_jy<%1%>(%1%,%1%) in CF1_jy", k / 100, pol);
|
||||
*fv = -f;
|
||||
*sign = s; // sign of denominator
|
||||
|
||||
return 0;
|
||||
}
|
||||
//
|
||||
// This algorithm was originally written by Xiaogang Zhang
|
||||
// using std::complex to perform the complex arithmetic.
|
||||
// However, that turns out to 10x or more slower than using
|
||||
// all real-valued arithmetic, so it's been rewritten using
|
||||
// real values only.
|
||||
//
|
||||
template <typename T, typename Policy>
|
||||
int CF2_jy(T v, T x, T* p, T* q, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
|
||||
T Cr, Ci, Dr, Di, fr, fi, a, br, bi, delta_r, delta_i, temp;
|
||||
T tiny;
|
||||
unsigned long k;
|
||||
|
||||
// |x| >= |v|, CF2_jy converges rapidly
|
||||
// |x| -> 0, CF2_jy fails to converge
|
||||
BOOST_ASSERT(fabs(x) > 1);
|
||||
|
||||
// modified Lentz's method, complex numbers involved, see
|
||||
// Lentz, Applied Optics, vol 15, 668 (1976)
|
||||
T tolerance = 2 * policies::get_epsilon<T, Policy>();
|
||||
tiny = sqrt(tools::min_value<T>());
|
||||
Cr = fr = -0.5f / x;
|
||||
Ci = fi = 1;
|
||||
//Dr = Di = 0;
|
||||
T v2 = v * v;
|
||||
a = (0.25f - v2) / x; // Note complex this one time only!
|
||||
br = 2 * x;
|
||||
bi = 2;
|
||||
temp = Cr * Cr + 1;
|
||||
Ci = bi + a * Cr / temp;
|
||||
Cr = br + a / temp;
|
||||
Dr = br;
|
||||
Di = bi;
|
||||
if (fabs(Cr) + fabs(Ci) < tiny) { Cr = tiny; }
|
||||
if (fabs(Dr) + fabs(Di) < tiny) { Dr = tiny; }
|
||||
temp = Dr * Dr + Di * Di;
|
||||
Dr = Dr / temp;
|
||||
Di = -Di / temp;
|
||||
delta_r = Cr * Dr - Ci * Di;
|
||||
delta_i = Ci * Dr + Cr * Di;
|
||||
temp = fr;
|
||||
fr = temp * delta_r - fi * delta_i;
|
||||
fi = temp * delta_i + fi * delta_r;
|
||||
for (k = 2; k < policies::get_max_series_iterations<Policy>(); k++)
|
||||
{
|
||||
a = k - 0.5f;
|
||||
a *= a;
|
||||
a -= v2;
|
||||
bi += 2;
|
||||
temp = Cr * Cr + Ci * Ci;
|
||||
Cr = br + a * Cr / temp;
|
||||
Ci = bi - a * Ci / temp;
|
||||
Dr = br + a * Dr;
|
||||
Di = bi + a * Di;
|
||||
if (fabs(Cr) + fabs(Ci) < tiny) { Cr = tiny; }
|
||||
if (fabs(Dr) + fabs(Di) < tiny) { Dr = tiny; }
|
||||
temp = Dr * Dr + Di * Di;
|
||||
Dr = Dr / temp;
|
||||
Di = -Di / temp;
|
||||
delta_r = Cr * Dr - Ci * Di;
|
||||
delta_i = Ci * Dr + Cr * Di;
|
||||
temp = fr;
|
||||
fr = temp * delta_r - fi * delta_i;
|
||||
fi = temp * delta_i + fi * delta_r;
|
||||
if (fabs(delta_r - 1) + fabs(delta_i) < tolerance)
|
||||
break;
|
||||
}
|
||||
policies::check_series_iterations<T>("boost::math::bessel_jy<%1%>(%1%,%1%) in CF2_jy", k, pol);
|
||||
*p = fr;
|
||||
*q = fi;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const int need_j = 1;
|
||||
static const int need_y = 2;
|
||||
|
||||
// Compute J(v, x) and Y(v, x) simultaneously by Steed's method, see
|
||||
// Barnett et al, Computer Physics Communications, vol 8, 377 (1974)
|
||||
template <typename T, typename Policy>
|
||||
int bessel_jy(T v, T x, T* J, T* Y, int kind, const Policy& pol)
|
||||
{
|
||||
BOOST_ASSERT(x >= 0);
|
||||
|
||||
T u, Jv, Ju, Yv, Yv1, Yu, Yu1(0), fv, fu;
|
||||
T W, p, q, gamma, current, prev, next;
|
||||
bool reflect = false;
|
||||
unsigned n, k;
|
||||
int s;
|
||||
int org_kind = kind;
|
||||
T cp = 0;
|
||||
T sp = 0;
|
||||
|
||||
static const char* function = "boost::math::bessel_jy<%1%>(%1%,%1%)";
|
||||
|
||||
BOOST_MATH_STD_USING
|
||||
using namespace boost::math::tools;
|
||||
using namespace boost::math::constants;
|
||||
|
||||
if (v < 0)
|
||||
{
|
||||
reflect = true;
|
||||
v = -v; // v is non-negative from here
|
||||
}
|
||||
if (v > static_cast<T>((std::numeric_limits<int>::max)()))
|
||||
{
|
||||
*J = *Y = policies::raise_evaluation_error<T>(function, "Order of Bessel function is too large to evaluate: got %1%", v, pol);
|
||||
return 1;
|
||||
}
|
||||
n = iround(v, pol);
|
||||
u = v - n; // -1/2 <= u < 1/2
|
||||
|
||||
if(reflect)
|
||||
{
|
||||
T z = (u + n % 2);
|
||||
cp = boost::math::cos_pi(z, pol);
|
||||
sp = boost::math::sin_pi(z, pol);
|
||||
if(u != 0)
|
||||
kind = need_j|need_y; // need both for reflection formula
|
||||
}
|
||||
|
||||
if(x == 0)
|
||||
{
|
||||
if(v == 0)
|
||||
*J = 1;
|
||||
else if((u == 0) || !reflect)
|
||||
*J = 0;
|
||||
else if(kind & need_j)
|
||||
*J = policies::raise_domain_error<T>(function, "Value of Bessel J_v(x) is complex-infinity at %1%", x, pol); // complex infinity
|
||||
else
|
||||
*J = std::numeric_limits<T>::quiet_NaN(); // any value will do, not using J.
|
||||
|
||||
if((kind & need_y) == 0)
|
||||
*Y = std::numeric_limits<T>::quiet_NaN(); // any value will do, not using Y.
|
||||
else if(v == 0)
|
||||
*Y = -policies::raise_overflow_error<T>(function, 0, pol);
|
||||
else
|
||||
*Y = policies::raise_domain_error<T>(function, "Value of Bessel Y_v(x) is complex-infinity at %1%", x, pol); // complex infinity
|
||||
return 1;
|
||||
}
|
||||
|
||||
// x is positive until reflection
|
||||
W = T(2) / (x * pi<T>()); // Wronskian
|
||||
T Yv_scale = 1;
|
||||
if(((kind & need_y) == 0) && ((x < 1) || (v > x * x / 4) || (x < 5)))
|
||||
{
|
||||
//
|
||||
// This series will actually converge rapidly for all small
|
||||
// x - say up to x < 20 - but the first few terms are large
|
||||
// and divergent which leads to large errors :-(
|
||||
//
|
||||
Jv = bessel_j_small_z_series(v, x, pol);
|
||||
Yv = std::numeric_limits<T>::quiet_NaN();
|
||||
}
|
||||
else if((x < 1) && (u != 0) && (log(policies::get_epsilon<T, Policy>() / 2) > v * log((x/2) * (x/2) / v)))
|
||||
{
|
||||
// Evaluate using series representations.
|
||||
// This is particularly important for x << v as in this
|
||||
// area temme_jy may be slow to converge, if it converges at all.
|
||||
// Requires x is not an integer.
|
||||
if(kind&need_j)
|
||||
Jv = bessel_j_small_z_series(v, x, pol);
|
||||
else
|
||||
Jv = std::numeric_limits<T>::quiet_NaN();
|
||||
if((org_kind&need_y && (!reflect || (cp != 0)))
|
||||
|| (org_kind & need_j && (reflect && (sp != 0))))
|
||||
{
|
||||
// Only calculate if we need it, and if the reflection formula will actually use it:
|
||||
Yv = bessel_y_small_z_series(v, x, &Yv_scale, pol);
|
||||
}
|
||||
else
|
||||
Yv = std::numeric_limits<T>::quiet_NaN();
|
||||
}
|
||||
else if((u == 0) && (x < policies::get_epsilon<T, Policy>()))
|
||||
{
|
||||
// Truncated series evaluation for small x and v an integer,
|
||||
// much quicker in this area than temme_jy below.
|
||||
if(kind&need_j)
|
||||
Jv = bessel_j_small_z_series(v, x, pol);
|
||||
else
|
||||
Jv = std::numeric_limits<T>::quiet_NaN();
|
||||
if((org_kind&need_y && (!reflect || (cp != 0)))
|
||||
|| (org_kind & need_j && (reflect && (sp != 0))))
|
||||
{
|
||||
// Only calculate if we need it, and if the reflection formula will actually use it:
|
||||
Yv = bessel_yn_small_z(n, x, &Yv_scale, pol);
|
||||
}
|
||||
else
|
||||
Yv = std::numeric_limits<T>::quiet_NaN();
|
||||
}
|
||||
else if(asymptotic_bessel_large_x_limit(v, x))
|
||||
{
|
||||
if(kind&need_y)
|
||||
{
|
||||
Yv = asymptotic_bessel_y_large_x_2(v, x);
|
||||
}
|
||||
else
|
||||
Yv = std::numeric_limits<T>::quiet_NaN(); // any value will do, we're not using it.
|
||||
if(kind&need_j)
|
||||
{
|
||||
Jv = asymptotic_bessel_j_large_x_2(v, x);
|
||||
}
|
||||
else
|
||||
Jv = std::numeric_limits<T>::quiet_NaN(); // any value will do, we're not using it.
|
||||
}
|
||||
else if((x > 8) && hankel_PQ(v, x, &p, &q, pol))
|
||||
{
|
||||
//
|
||||
// Hankel approximation: note that this method works best when x
|
||||
// is large, but in that case we end up calculating sines and cosines
|
||||
// of large values, with horrendous resulting accuracy. It is fast though
|
||||
// when it works....
|
||||
//
|
||||
// Normally we calculate sin/cos(chi) where:
|
||||
//
|
||||
// chi = x - fmod(T(v / 2 + 0.25f), T(2)) * boost::math::constants::pi<T>();
|
||||
//
|
||||
// But this introduces large errors, so use sin/cos addition formulae to
|
||||
// improve accuracy:
|
||||
//
|
||||
T mod_v = fmod(T(v / 2 + 0.25f), T(2));
|
||||
T sx = sin(x);
|
||||
T cx = cos(x);
|
||||
T sv = sin_pi(mod_v);
|
||||
T cv = cos_pi(mod_v);
|
||||
|
||||
T sc = sx * cv - sv * cx; // == sin(chi);
|
||||
T cc = cx * cv + sx * sv; // == cos(chi);
|
||||
T chi = boost::math::constants::root_two<T>() / (boost::math::constants::root_pi<T>() * sqrt(x)); //sqrt(2 / (boost::math::constants::pi<T>() * x));
|
||||
Yv = chi * (p * sc + q * cc);
|
||||
Jv = chi * (p * cc - q * sc);
|
||||
}
|
||||
else if (x <= 2) // x in (0, 2]
|
||||
{
|
||||
if(temme_jy(u, x, &Yu, &Yu1, pol)) // Temme series
|
||||
{
|
||||
// domain error:
|
||||
*J = *Y = Yu;
|
||||
return 1;
|
||||
}
|
||||
prev = Yu;
|
||||
current = Yu1;
|
||||
T scale = 1;
|
||||
policies::check_series_iterations<T>(function, n, pol);
|
||||
for (k = 1; k <= n; k++) // forward recurrence for Y
|
||||
{
|
||||
T fact = 2 * (u + k) / x;
|
||||
if((tools::max_value<T>() - fabs(prev)) / fact < fabs(current))
|
||||
{
|
||||
scale /= current;
|
||||
prev /= current;
|
||||
current = 1;
|
||||
}
|
||||
next = fact * current - prev;
|
||||
prev = current;
|
||||
current = next;
|
||||
}
|
||||
Yv = prev;
|
||||
Yv1 = current;
|
||||
if(kind&need_j)
|
||||
{
|
||||
CF1_jy(v, x, &fv, &s, pol); // continued fraction CF1_jy
|
||||
Jv = scale * W / (Yv * fv - Yv1); // Wronskian relation
|
||||
}
|
||||
else
|
||||
Jv = std::numeric_limits<T>::quiet_NaN(); // any value will do, we're not using it.
|
||||
Yv_scale = scale;
|
||||
}
|
||||
else // x in (2, \infty)
|
||||
{
|
||||
// Get Y(u, x):
|
||||
|
||||
T ratio;
|
||||
CF1_jy(v, x, &fv, &s, pol);
|
||||
// tiny initial value to prevent overflow
|
||||
T init = sqrt(tools::min_value<T>());
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(init);
|
||||
prev = fv * s * init;
|
||||
current = s * init;
|
||||
if(v < max_factorial<T>::value)
|
||||
{
|
||||
policies::check_series_iterations<T>(function, n, pol);
|
||||
for (k = n; k > 0; k--) // backward recurrence for J
|
||||
{
|
||||
next = 2 * (u + k) * current / x - prev;
|
||||
prev = current;
|
||||
current = next;
|
||||
}
|
||||
ratio = (s * init) / current; // scaling ratio
|
||||
// can also call CF1_jy() to get fu, not much difference in precision
|
||||
fu = prev / current;
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// When v is large we may get overflow in this calculation
|
||||
// leading to NaN's and other nasty surprises:
|
||||
//
|
||||
policies::check_series_iterations<T>(function, n, pol);
|
||||
bool over = false;
|
||||
for (k = n; k > 0; k--) // backward recurrence for J
|
||||
{
|
||||
T t = 2 * (u + k) / x;
|
||||
if((t > 1) && (tools::max_value<T>() / t < current))
|
||||
{
|
||||
over = true;
|
||||
break;
|
||||
}
|
||||
next = t * current - prev;
|
||||
prev = current;
|
||||
current = next;
|
||||
}
|
||||
if(!over)
|
||||
{
|
||||
ratio = (s * init) / current; // scaling ratio
|
||||
// can also call CF1_jy() to get fu, not much difference in precision
|
||||
fu = prev / current;
|
||||
}
|
||||
else
|
||||
{
|
||||
ratio = 0;
|
||||
fu = 1;
|
||||
}
|
||||
}
|
||||
CF2_jy(u, x, &p, &q, pol); // continued fraction CF2_jy
|
||||
T t = u / x - fu; // t = J'/J
|
||||
gamma = (p - t) / q;
|
||||
//
|
||||
// We can't allow gamma to cancel out to zero competely as it messes up
|
||||
// the subsequent logic. So pretend that one bit didn't cancel out
|
||||
// and set to a suitably small value. The only test case we've been able to
|
||||
// find for this, is when v = 8.5 and x = 4*PI.
|
||||
//
|
||||
if(gamma == 0)
|
||||
{
|
||||
gamma = u * tools::epsilon<T>() / x;
|
||||
}
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(current);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(W);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(q);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(gamma);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(p);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(t);
|
||||
Ju = sign(current) * sqrt(W / (q + gamma * (p - t)));
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(Ju);
|
||||
|
||||
Jv = Ju * ratio; // normalization
|
||||
|
||||
Yu = gamma * Ju;
|
||||
Yu1 = Yu * (u/x - p - q/gamma);
|
||||
|
||||
if(kind&need_y)
|
||||
{
|
||||
// compute Y:
|
||||
prev = Yu;
|
||||
current = Yu1;
|
||||
policies::check_series_iterations<T>(function, n, pol);
|
||||
for (k = 1; k <= n; k++) // forward recurrence for Y
|
||||
{
|
||||
T fact = 2 * (u + k) / x;
|
||||
if((tools::max_value<T>() - fabs(prev)) / fact < fabs(current))
|
||||
{
|
||||
prev /= current;
|
||||
Yv_scale /= current;
|
||||
current = 1;
|
||||
}
|
||||
next = fact * current - prev;
|
||||
prev = current;
|
||||
current = next;
|
||||
}
|
||||
Yv = prev;
|
||||
}
|
||||
else
|
||||
Yv = std::numeric_limits<T>::quiet_NaN(); // any value will do, we're not using it.
|
||||
}
|
||||
|
||||
if (reflect)
|
||||
{
|
||||
if((sp != 0) && (tools::max_value<T>() * fabs(Yv_scale) < fabs(sp * Yv)))
|
||||
*J = org_kind & need_j ? T(-sign(sp) * sign(Yv) * sign(Yv_scale) * policies::raise_overflow_error<T>(function, 0, pol)) : T(0);
|
||||
else
|
||||
*J = cp * Jv - (sp == 0 ? T(0) : T((sp * Yv) / Yv_scale)); // reflection formula
|
||||
if((cp != 0) && (tools::max_value<T>() * fabs(Yv_scale) < fabs(cp * Yv)))
|
||||
*Y = org_kind & need_y ? T(-sign(cp) * sign(Yv) * sign(Yv_scale) * policies::raise_overflow_error<T>(function, 0, pol)) : T(0);
|
||||
else
|
||||
*Y = (sp != 0 ? sp * Jv : T(0)) + (cp == 0 ? T(0) : T((cp * Yv) / Yv_scale));
|
||||
}
|
||||
else
|
||||
{
|
||||
*J = Jv;
|
||||
if(tools::max_value<T>() * fabs(Yv_scale) < fabs(Yv))
|
||||
*Y = org_kind & need_y ? T(sign(Yv) * sign(Yv_scale) * policies::raise_overflow_error<T>(function, 0, pol)) : T(0);
|
||||
else
|
||||
*Y = Yv / Yv_scale;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_BESSEL_JY_HPP
|
||||
|
||||
223
code_isotrope/boost/math/special_functions/detail/bessel_jy_asym.hpp
Executable file
223
code_isotrope/boost/math/special_functions/detail/bessel_jy_asym.hpp
Executable file
@@ -0,0 +1,223 @@
|
||||
// Copyright (c) 2007 John Maddock
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
//
|
||||
// This is a partial header, do not include on it's own!!!
|
||||
//
|
||||
// Contains asymptotic expansions for Bessel J(v,x) and Y(v,x)
|
||||
// functions, as x -> INF.
|
||||
//
|
||||
#ifndef BOOST_MATH_SF_DETAIL_BESSEL_JY_ASYM_HPP
|
||||
#define BOOST_MATH_SF_DETAIL_BESSEL_JY_ASYM_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/special_functions/factorials.hpp>
|
||||
|
||||
namespace boost{ namespace math{ namespace detail{
|
||||
|
||||
template <class T>
|
||||
inline T asymptotic_bessel_amplitude(T v, T x)
|
||||
{
|
||||
// Calculate the amplitude of J(v, x) and Y(v, x) for large
|
||||
// x: see A&S 9.2.28.
|
||||
BOOST_MATH_STD_USING
|
||||
T s = 1;
|
||||
T mu = 4 * v * v;
|
||||
T txq = 2 * x;
|
||||
txq *= txq;
|
||||
|
||||
s += (mu - 1) / (2 * txq);
|
||||
s += 3 * (mu - 1) * (mu - 9) / (txq * txq * 8);
|
||||
s += 15 * (mu - 1) * (mu - 9) * (mu - 25) / (txq * txq * txq * 8 * 6);
|
||||
|
||||
return sqrt(s * 2 / (constants::pi<T>() * x));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T asymptotic_bessel_phase_mx(T v, T x)
|
||||
{
|
||||
//
|
||||
// Calculate the phase of J(v, x) and Y(v, x) for large x.
|
||||
// See A&S 9.2.29.
|
||||
// Note that the result returned is the phase less (x - PI(v/2 + 1/4))
|
||||
// which we'll factor in later when we calculate the sines/cosines of the result:
|
||||
//
|
||||
T mu = 4 * v * v;
|
||||
T denom = 4 * x;
|
||||
T denom_mult = denom * denom;
|
||||
|
||||
T s = 0;
|
||||
s += (mu - 1) / (2 * denom);
|
||||
denom *= denom_mult;
|
||||
s += (mu - 1) * (mu - 25) / (6 * denom);
|
||||
denom *= denom_mult;
|
||||
s += (mu - 1) * (mu * mu - 114 * mu + 1073) / (5 * denom);
|
||||
denom *= denom_mult;
|
||||
s += (mu - 1) * (5 * mu * mu * mu - 1535 * mu * mu + 54703 * mu - 375733) / (14 * denom);
|
||||
return s;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T asymptotic_bessel_y_large_x_2(T v, T x)
|
||||
{
|
||||
// See A&S 9.2.19.
|
||||
BOOST_MATH_STD_USING
|
||||
// Get the phase and amplitude:
|
||||
T ampl = asymptotic_bessel_amplitude(v, x);
|
||||
T phase = asymptotic_bessel_phase_mx(v, x);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(ampl);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(phase);
|
||||
//
|
||||
// Calculate the sine of the phase, using
|
||||
// sine/cosine addition rules to factor in
|
||||
// the x - PI(v/2 + 1/4) term not added to the
|
||||
// phase when we calculated it.
|
||||
//
|
||||
T cx = cos(x);
|
||||
T sx = sin(x);
|
||||
T ci = cos_pi(v / 2 + 0.25f);
|
||||
T si = sin_pi(v / 2 + 0.25f);
|
||||
T sin_phase = sin(phase) * (cx * ci + sx * si) + cos(phase) * (sx * ci - cx * si);
|
||||
BOOST_MATH_INSTRUMENT_CODE(sin(phase));
|
||||
BOOST_MATH_INSTRUMENT_CODE(cos(x));
|
||||
BOOST_MATH_INSTRUMENT_CODE(cos(phase));
|
||||
BOOST_MATH_INSTRUMENT_CODE(sin(x));
|
||||
return sin_phase * ampl;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T asymptotic_bessel_j_large_x_2(T v, T x)
|
||||
{
|
||||
// See A&S 9.2.19.
|
||||
BOOST_MATH_STD_USING
|
||||
// Get the phase and amplitude:
|
||||
T ampl = asymptotic_bessel_amplitude(v, x);
|
||||
T phase = asymptotic_bessel_phase_mx(v, x);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(ampl);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(phase);
|
||||
//
|
||||
// Calculate the sine of the phase, using
|
||||
// sine/cosine addition rules to factor in
|
||||
// the x - PI(v/2 + 1/4) term not added to the
|
||||
// phase when we calculated it.
|
||||
//
|
||||
BOOST_MATH_INSTRUMENT_CODE(cos(phase));
|
||||
BOOST_MATH_INSTRUMENT_CODE(cos(x));
|
||||
BOOST_MATH_INSTRUMENT_CODE(sin(phase));
|
||||
BOOST_MATH_INSTRUMENT_CODE(sin(x));
|
||||
T cx = cos(x);
|
||||
T sx = sin(x);
|
||||
T ci = cos_pi(v / 2 + 0.25f);
|
||||
T si = sin_pi(v / 2 + 0.25f);
|
||||
T sin_phase = cos(phase) * (cx * ci + sx * si) - sin(phase) * (sx * ci - cx * si);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(sin_phase);
|
||||
return sin_phase * ampl;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline bool asymptotic_bessel_large_x_limit(int v, const T& x)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
//
|
||||
// Determines if x is large enough compared to v to take the asymptotic
|
||||
// forms above. From A&S 9.2.28 we require:
|
||||
// v < x * eps^1/8
|
||||
// and from A&S 9.2.29 we require:
|
||||
// v^12/10 < 1.5 * x * eps^1/10
|
||||
// using the former seems to work OK in practice with broadly similar
|
||||
// error rates either side of the divide for v < 10000.
|
||||
// At double precision eps^1/8 ~= 0.01.
|
||||
//
|
||||
BOOST_ASSERT(v >= 0);
|
||||
return (v ? v : 1) < x * 0.004f;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline bool asymptotic_bessel_large_x_limit(const T& v, const T& x)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
//
|
||||
// Determines if x is large enough compared to v to take the asymptotic
|
||||
// forms above. From A&S 9.2.28 we require:
|
||||
// v < x * eps^1/8
|
||||
// and from A&S 9.2.29 we require:
|
||||
// v^12/10 < 1.5 * x * eps^1/10
|
||||
// using the former seems to work OK in practice with broadly similar
|
||||
// error rates either side of the divide for v < 10000.
|
||||
// At double precision eps^1/8 ~= 0.01.
|
||||
//
|
||||
return (std::max)(T(fabs(v)), T(1)) < x * sqrt(tools::forth_root_epsilon<T>());
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
void temme_asyptotic_y_small_x(T v, T x, T* Y, T* Y1, const Policy& pol)
|
||||
{
|
||||
T c = 1;
|
||||
T p = (v / boost::math::sin_pi(v, pol)) * pow(x / 2, -v) / boost::math::tgamma(1 - v, pol);
|
||||
T q = (v / boost::math::sin_pi(v, pol)) * pow(x / 2, v) / boost::math::tgamma(1 + v, pol);
|
||||
T f = (p - q) / v;
|
||||
T g_prefix = boost::math::sin_pi(v / 2, pol);
|
||||
g_prefix *= g_prefix * 2 / v;
|
||||
T g = f + g_prefix * q;
|
||||
T h = p;
|
||||
T c_mult = -x * x / 4;
|
||||
|
||||
T y(c * g), y1(c * h);
|
||||
|
||||
for(int k = 1; k < policies::get_max_series_iterations<Policy>(); ++k)
|
||||
{
|
||||
f = (k * f + p + q) / (k*k - v*v);
|
||||
p /= k - v;
|
||||
q /= k + v;
|
||||
c *= c_mult / k;
|
||||
T c1 = pow(-x * x / 4, k) / factorial<T>(k, pol);
|
||||
g = f + g_prefix * q;
|
||||
h = -k * g + p;
|
||||
y += c * g;
|
||||
y1 += c * h;
|
||||
if(c * g / tools::epsilon<T>() < y)
|
||||
break;
|
||||
}
|
||||
|
||||
*Y = -y;
|
||||
*Y1 = (-2 / x) * y1;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
T asymptotic_bessel_i_large_x(T v, T x, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING // ADL of std names
|
||||
T s = 1;
|
||||
T mu = 4 * v * v;
|
||||
T ex = 8 * x;
|
||||
T num = mu - 1;
|
||||
T denom = ex;
|
||||
|
||||
s -= num / denom;
|
||||
|
||||
num *= mu - 9;
|
||||
denom *= ex * 2;
|
||||
s += num / denom;
|
||||
|
||||
num *= mu - 25;
|
||||
denom *= ex * 3;
|
||||
s -= num / denom;
|
||||
|
||||
// Try and avoid overflow to the last minute:
|
||||
T e = exp(x/2);
|
||||
|
||||
s = e * (e * s / sqrt(2 * x * constants::pi<T>()));
|
||||
|
||||
return (boost::math::isfinite)(s) ?
|
||||
s : policies::raise_overflow_error<T>("boost::math::asymptotic_bessel_i_large_x<%1%>(%1%,%1%)", 0, pol);
|
||||
}
|
||||
|
||||
}}} // namespaces
|
||||
|
||||
#endif
|
||||
|
||||
141
code_isotrope/boost/math/special_functions/detail/bessel_jy_derivatives_asym.hpp
Executable file
141
code_isotrope/boost/math/special_functions/detail/bessel_jy_derivatives_asym.hpp
Executable file
@@ -0,0 +1,141 @@
|
||||
// Copyright (c) 2013 Anton Bikineev
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
//
|
||||
// This is a partial header, do not include on it's own!!!
|
||||
//
|
||||
// Contains asymptotic expansions for derivatives of Bessel J(v,x) and Y(v,x)
|
||||
// functions, as x -> INF.
|
||||
#ifndef BOOST_MATH_SF_DETAIL_BESSEL_JY_DERIVATIVES_ASYM_HPP
|
||||
#define BOOST_MATH_SF_DETAIL_BESSEL_JY_DERIVATIVES_ASYM_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
namespace boost{ namespace math{ namespace detail{
|
||||
|
||||
template <class T>
|
||||
inline T asymptotic_bessel_derivative_amplitude(T v, T x)
|
||||
{
|
||||
// Calculate the amplitude for J'(v,x) and I'(v,x)
|
||||
// for large x: see A&S 9.2.30.
|
||||
BOOST_MATH_STD_USING
|
||||
T s = 1;
|
||||
const T mu = 4 * v * v;
|
||||
T txq = 2 * x;
|
||||
txq *= txq;
|
||||
|
||||
s -= (mu - 3) / (2 * txq);
|
||||
s -= ((mu - 1) * (mu - 45)) / (txq * txq * 8);
|
||||
|
||||
return sqrt(s * 2 / (boost::math::constants::pi<T>() * x));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T asymptotic_bessel_derivative_phase_mx(T v, T x)
|
||||
{
|
||||
// Calculate the phase of J'(v, x) and Y'(v, x) for large x.
|
||||
// See A&S 9.2.31.
|
||||
// Note that the result returned is the phase less (x - PI(v/2 - 1/4))
|
||||
// which we'll factor in later when we calculate the sines/cosines of the result:
|
||||
const T mu = 4 * v * v;
|
||||
const T mu2 = mu * mu;
|
||||
const T mu3 = mu2 * mu;
|
||||
T denom = 4 * x;
|
||||
T denom_mult = denom * denom;
|
||||
|
||||
T s = 0;
|
||||
s += (mu + 3) / (2 * denom);
|
||||
denom *= denom_mult;
|
||||
s += (mu2 + (46 * mu) - 63) / (6 * denom);
|
||||
denom *= denom_mult;
|
||||
s += (mu3 + (185 * mu2) - (2053 * mu) + 1899) / (5 * denom);
|
||||
return s;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T asymptotic_bessel_y_derivative_large_x_2(T v, T x)
|
||||
{
|
||||
// See A&S 9.2.20.
|
||||
BOOST_MATH_STD_USING
|
||||
// Get the phase and amplitude:
|
||||
const T ampl = asymptotic_bessel_derivative_amplitude(v, x);
|
||||
const T phase = asymptotic_bessel_derivative_phase_mx(v, x);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(ampl);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(phase);
|
||||
//
|
||||
// Calculate the sine of the phase, using
|
||||
// sine/cosine addition rules to factor in
|
||||
// the x - PI(v/2 - 1/4) term not added to the
|
||||
// phase when we calculated it.
|
||||
//
|
||||
const T cx = cos(x);
|
||||
const T sx = sin(x);
|
||||
const T vd2shifted = (v / 2) - 0.25f;
|
||||
const T ci = cos_pi(vd2shifted);
|
||||
const T si = sin_pi(vd2shifted);
|
||||
const T sin_phase = sin(phase) * (cx * ci + sx * si) + cos(phase) * (sx * ci - cx * si);
|
||||
BOOST_MATH_INSTRUMENT_CODE(sin(phase));
|
||||
BOOST_MATH_INSTRUMENT_CODE(cos(x));
|
||||
BOOST_MATH_INSTRUMENT_CODE(cos(phase));
|
||||
BOOST_MATH_INSTRUMENT_CODE(sin(x));
|
||||
return sin_phase * ampl;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T asymptotic_bessel_j_derivative_large_x_2(T v, T x)
|
||||
{
|
||||
// See A&S 9.2.20.
|
||||
BOOST_MATH_STD_USING
|
||||
// Get the phase and amplitude:
|
||||
const T ampl = asymptotic_bessel_derivative_amplitude(v, x);
|
||||
const T phase = asymptotic_bessel_derivative_phase_mx(v, x);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(ampl);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(phase);
|
||||
//
|
||||
// Calculate the sine of the phase, using
|
||||
// sine/cosine addition rules to factor in
|
||||
// the x - PI(v/2 - 1/4) term not added to the
|
||||
// phase when we calculated it.
|
||||
//
|
||||
BOOST_MATH_INSTRUMENT_CODE(cos(phase));
|
||||
BOOST_MATH_INSTRUMENT_CODE(cos(x));
|
||||
BOOST_MATH_INSTRUMENT_CODE(sin(phase));
|
||||
BOOST_MATH_INSTRUMENT_CODE(sin(x));
|
||||
const T cx = cos(x);
|
||||
const T sx = sin(x);
|
||||
const T vd2shifted = (v / 2) - 0.25f;
|
||||
const T ci = cos_pi(vd2shifted);
|
||||
const T si = sin_pi(vd2shifted);
|
||||
const T sin_phase = cos(phase) * (cx * ci + sx * si) - sin(phase) * (sx * ci - cx * si);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(sin_phase);
|
||||
return sin_phase * ampl;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline bool asymptotic_bessel_derivative_large_x_limit(const T& v, const T& x)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
//
|
||||
// This function is the copy of math::asymptotic_bessel_large_x_limit
|
||||
// It means that we use the same rules for determining how x is large
|
||||
// compared to v.
|
||||
//
|
||||
// Determines if x is large enough compared to v to take the asymptotic
|
||||
// forms above. From A&S 9.2.28 we require:
|
||||
// v < x * eps^1/8
|
||||
// and from A&S 9.2.29 we require:
|
||||
// v^12/10 < 1.5 * x * eps^1/10
|
||||
// using the former seems to work OK in practice with broadly similar
|
||||
// error rates either side of the divide for v < 10000.
|
||||
// At double precision eps^1/8 ~= 0.01.
|
||||
//
|
||||
return (std::max)(T(fabs(v)), T(1)) < x * sqrt(boost::math::tools::forth_root_epsilon<T>());
|
||||
}
|
||||
|
||||
}}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_SF_DETAIL_BESSEL_JY_DERIVATIVES_ASYM_HPP
|
||||
@@ -0,0 +1,221 @@
|
||||
// Copyright (c) 2013 Anton Bikineev
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_MATH_BESSEL_JY_DERIVATIVES_SERIES_HPP
|
||||
#define BOOST_MATH_BESSEL_JY_DERIVATIVES_SERIES_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
namespace boost{ namespace math{ namespace detail{
|
||||
|
||||
template <class T, class Policy>
|
||||
struct bessel_j_derivative_small_z_series_term
|
||||
{
|
||||
typedef T result_type;
|
||||
|
||||
bessel_j_derivative_small_z_series_term(T v_, T x)
|
||||
: N(0), v(v_), term(1), mult(x / 2)
|
||||
{
|
||||
mult *= -mult;
|
||||
// iterate if v == 0; otherwise result of
|
||||
// first term is 0 and tools::sum_series stops
|
||||
if (v == 0)
|
||||
iterate();
|
||||
}
|
||||
T operator()()
|
||||
{
|
||||
T r = term * (v + 2 * N);
|
||||
iterate();
|
||||
return r;
|
||||
}
|
||||
private:
|
||||
void iterate()
|
||||
{
|
||||
++N;
|
||||
term *= mult / (N * (N + v));
|
||||
}
|
||||
unsigned N;
|
||||
T v;
|
||||
T term;
|
||||
T mult;
|
||||
};
|
||||
//
|
||||
// Series evaluation for BesselJ'(v, z) as z -> 0.
|
||||
// It's derivative of http://functions.wolfram.com/Bessel-TypeFunctions/BesselJ/06/01/04/01/01/0003/
|
||||
// Converges rapidly for all z << v.
|
||||
//
|
||||
template <class T, class Policy>
|
||||
inline T bessel_j_derivative_small_z_series(T v, T x, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
T prefix;
|
||||
if (v < boost::math::max_factorial<T>::value)
|
||||
{
|
||||
prefix = pow(x / 2, v - 1) / 2 / boost::math::tgamma(v + 1, pol);
|
||||
}
|
||||
else
|
||||
{
|
||||
prefix = (v - 1) * log(x / 2) - constants::ln_two<T>() - boost::math::lgamma(v + 1, pol);
|
||||
prefix = exp(prefix);
|
||||
}
|
||||
if (0 == prefix)
|
||||
return prefix;
|
||||
|
||||
bessel_j_derivative_small_z_series_term<T, Policy> s(v, x);
|
||||
boost::uintmax_t max_iter = boost::math::policies::get_max_series_iterations<Policy>();
|
||||
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
|
||||
T zero = 0;
|
||||
T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon<T, Policy>(), max_iter, zero);
|
||||
#else
|
||||
T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon<T, Policy>(), max_iter);
|
||||
#endif
|
||||
boost::math::policies::check_series_iterations<T>("boost::math::bessel_j_derivative_small_z_series<%1%>(%1%,%1%)", max_iter, pol);
|
||||
return prefix * result;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
struct bessel_y_derivative_small_z_series_term_a
|
||||
{
|
||||
typedef T result_type;
|
||||
|
||||
bessel_y_derivative_small_z_series_term_a(T v_, T x)
|
||||
: N(0), v(v_)
|
||||
{
|
||||
mult = x / 2;
|
||||
mult *= -mult;
|
||||
term = 1;
|
||||
}
|
||||
T operator()()
|
||||
{
|
||||
T r = term * (-v + 2 * N);
|
||||
++N;
|
||||
term *= mult / (N * (N - v));
|
||||
return r;
|
||||
}
|
||||
private:
|
||||
unsigned N;
|
||||
T v;
|
||||
T mult;
|
||||
T term;
|
||||
};
|
||||
|
||||
template <class T, class Policy>
|
||||
struct bessel_y_derivative_small_z_series_term_b
|
||||
{
|
||||
typedef T result_type;
|
||||
|
||||
bessel_y_derivative_small_z_series_term_b(T v_, T x)
|
||||
: N(0), v(v_)
|
||||
{
|
||||
mult = x / 2;
|
||||
mult *= -mult;
|
||||
term = 1;
|
||||
}
|
||||
T operator()()
|
||||
{
|
||||
T r = term * (v + 2 * N);
|
||||
++N;
|
||||
term *= mult / (N * (N + v));
|
||||
return r;
|
||||
}
|
||||
private:
|
||||
unsigned N;
|
||||
T v;
|
||||
T mult;
|
||||
T term;
|
||||
};
|
||||
//
|
||||
// Series form for BesselY' as z -> 0,
|
||||
// It's derivative of http://functions.wolfram.com/Bessel-TypeFunctions/BesselY/06/01/04/01/01/0003/
|
||||
// This series is only useful when the second term is small compared to the first
|
||||
// otherwise we get catestrophic cancellation errors.
|
||||
//
|
||||
// Approximating tgamma(v) by v^v, and assuming |tgamma(-z)| < eps we end up requiring:
|
||||
// eps/2 * v^v(x/2)^-v > (x/2)^v or log(eps/2) > v log((x/2)^2/v)
|
||||
//
|
||||
template <class T, class Policy>
|
||||
inline T bessel_y_derivative_small_z_series(T v, T x, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
static const char* function = "bessel_y_derivative_small_z_series<%1%>(%1%,%1%)";
|
||||
T prefix;
|
||||
T gam;
|
||||
T p = log(x / 2);
|
||||
T scale = 1;
|
||||
bool need_logs = (v >= boost::math::max_factorial<T>::value) || (boost::math::tools::log_max_value<T>() / v < fabs(p));
|
||||
if (!need_logs)
|
||||
{
|
||||
gam = boost::math::tgamma(v, pol);
|
||||
p = pow(x / 2, v + 1) * 2;
|
||||
if (boost::math::tools::max_value<T>() * p < gam)
|
||||
{
|
||||
scale /= gam;
|
||||
gam = 1;
|
||||
if (boost::math::tools::max_value<T>() * p < gam)
|
||||
{
|
||||
// This term will overflow to -INF, when combined with the series below it becomes +INF:
|
||||
return boost::math::policies::raise_overflow_error<T>(function, 0, pol);
|
||||
}
|
||||
}
|
||||
prefix = -gam / (boost::math::constants::pi<T>() * p);
|
||||
}
|
||||
else
|
||||
{
|
||||
gam = boost::math::lgamma(v, pol);
|
||||
p = (v + 1) * p + constants::ln_two<T>();
|
||||
prefix = gam - log(boost::math::constants::pi<T>()) - p;
|
||||
if (boost::math::tools::log_max_value<T>() < prefix)
|
||||
{
|
||||
prefix -= log(boost::math::tools::max_value<T>() / 4);
|
||||
scale /= (boost::math::tools::max_value<T>() / 4);
|
||||
if (boost::math::tools::log_max_value<T>() < prefix)
|
||||
{
|
||||
return boost::math::policies::raise_overflow_error<T>(function, 0, pol);
|
||||
}
|
||||
}
|
||||
prefix = -exp(prefix);
|
||||
}
|
||||
bessel_y_derivative_small_z_series_term_a<T, Policy> s(v, x);
|
||||
boost::uintmax_t max_iter = boost::math::policies::get_max_series_iterations<Policy>();
|
||||
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
|
||||
T zero = 0;
|
||||
T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon<T, Policy>(), max_iter, zero);
|
||||
#else
|
||||
T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon<T, Policy>(), max_iter);
|
||||
#endif
|
||||
boost::math::policies::check_series_iterations<T>("boost::math::bessel_y_derivative_small_z_series<%1%>(%1%,%1%)", max_iter, pol);
|
||||
result *= prefix;
|
||||
|
||||
p = pow(x / 2, v - 1) / 2;
|
||||
if (!need_logs)
|
||||
{
|
||||
prefix = boost::math::tgamma(-v, pol) * boost::math::cos_pi(v) * p / boost::math::constants::pi<T>();
|
||||
}
|
||||
else
|
||||
{
|
||||
int sgn;
|
||||
prefix = boost::math::lgamma(-v, &sgn, pol) + (v - 1) * log(x / 2) - constants::ln_two<T>();
|
||||
prefix = exp(prefix) * sgn / boost::math::constants::pi<T>();
|
||||
}
|
||||
bessel_y_derivative_small_z_series_term_b<T, Policy> s2(v, x);
|
||||
max_iter = boost::math::policies::get_max_series_iterations<Policy>();
|
||||
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
|
||||
T b = boost::math::tools::sum_series(s2, boost::math::policies::get_epsilon<T, Policy>(), max_iter, zero);
|
||||
#else
|
||||
T b = boost::math::tools::sum_series(s2, boost::math::policies::get_epsilon<T, Policy>(), max_iter);
|
||||
#endif
|
||||
result += scale * prefix * b;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Calculating of BesselY'(v,x) with small x (x < epsilon) and integer x using derivatives
|
||||
// of formulas in http://functions.wolfram.com/Bessel-TypeFunctions/BesselY/06/01/04/01/02/
|
||||
// seems to lose precision. Instead using linear combination of regular Bessel is preferred.
|
||||
|
||||
}}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_BESSEL_JY_DERIVATVIES_SERIES_HPP
|
||||
261
code_isotrope/boost/math/special_functions/detail/bessel_jy_series.hpp
Executable file
261
code_isotrope/boost/math/special_functions/detail/bessel_jy_series.hpp
Executable file
@@ -0,0 +1,261 @@
|
||||
// Copyright (c) 2011 John Maddock
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_MATH_BESSEL_JN_SERIES_HPP
|
||||
#define BOOST_MATH_BESSEL_JN_SERIES_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
namespace boost { namespace math { namespace detail{
|
||||
|
||||
template <class T, class Policy>
|
||||
struct bessel_j_small_z_series_term
|
||||
{
|
||||
typedef T result_type;
|
||||
|
||||
bessel_j_small_z_series_term(T v_, T x)
|
||||
: N(0), v(v_)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
mult = x / 2;
|
||||
mult *= -mult;
|
||||
term = 1;
|
||||
}
|
||||
T operator()()
|
||||
{
|
||||
T r = term;
|
||||
++N;
|
||||
term *= mult / (N * (N + v));
|
||||
return r;
|
||||
}
|
||||
private:
|
||||
unsigned N;
|
||||
T v;
|
||||
T mult;
|
||||
T term;
|
||||
};
|
||||
//
|
||||
// Series evaluation for BesselJ(v, z) as z -> 0.
|
||||
// See http://functions.wolfram.com/Bessel-TypeFunctions/BesselJ/06/01/04/01/01/0003/
|
||||
// Converges rapidly for all z << v.
|
||||
//
|
||||
template <class T, class Policy>
|
||||
inline T bessel_j_small_z_series(T v, T x, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
T prefix;
|
||||
if(v < max_factorial<T>::value)
|
||||
{
|
||||
prefix = pow(x / 2, v) / boost::math::tgamma(v+1, pol);
|
||||
}
|
||||
else
|
||||
{
|
||||
prefix = v * log(x / 2) - boost::math::lgamma(v+1, pol);
|
||||
prefix = exp(prefix);
|
||||
}
|
||||
if(0 == prefix)
|
||||
return prefix;
|
||||
|
||||
bessel_j_small_z_series_term<T, Policy> s(v, x);
|
||||
boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
|
||||
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
|
||||
T zero = 0;
|
||||
T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon<T, Policy>(), max_iter, zero);
|
||||
#else
|
||||
T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon<T, Policy>(), max_iter);
|
||||
#endif
|
||||
policies::check_series_iterations<T>("boost::math::bessel_j_small_z_series<%1%>(%1%,%1%)", max_iter, pol);
|
||||
return prefix * result;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
struct bessel_y_small_z_series_term_a
|
||||
{
|
||||
typedef T result_type;
|
||||
|
||||
bessel_y_small_z_series_term_a(T v_, T x)
|
||||
: N(0), v(v_)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
mult = x / 2;
|
||||
mult *= -mult;
|
||||
term = 1;
|
||||
}
|
||||
T operator()()
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
T r = term;
|
||||
++N;
|
||||
term *= mult / (N * (N - v));
|
||||
return r;
|
||||
}
|
||||
private:
|
||||
unsigned N;
|
||||
T v;
|
||||
T mult;
|
||||
T term;
|
||||
};
|
||||
|
||||
template <class T, class Policy>
|
||||
struct bessel_y_small_z_series_term_b
|
||||
{
|
||||
typedef T result_type;
|
||||
|
||||
bessel_y_small_z_series_term_b(T v_, T x)
|
||||
: N(0), v(v_)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
mult = x / 2;
|
||||
mult *= -mult;
|
||||
term = 1;
|
||||
}
|
||||
T operator()()
|
||||
{
|
||||
T r = term;
|
||||
++N;
|
||||
term *= mult / (N * (N + v));
|
||||
return r;
|
||||
}
|
||||
private:
|
||||
unsigned N;
|
||||
T v;
|
||||
T mult;
|
||||
T term;
|
||||
};
|
||||
//
|
||||
// Series form for BesselY as z -> 0,
|
||||
// see: http://functions.wolfram.com/Bessel-TypeFunctions/BesselY/06/01/04/01/01/0003/
|
||||
// This series is only useful when the second term is small compared to the first
|
||||
// otherwise we get catestrophic cancellation errors.
|
||||
//
|
||||
// Approximating tgamma(v) by v^v, and assuming |tgamma(-z)| < eps we end up requiring:
|
||||
// eps/2 * v^v(x/2)^-v > (x/2)^v or log(eps/2) > v log((x/2)^2/v)
|
||||
//
|
||||
template <class T, class Policy>
|
||||
inline T bessel_y_small_z_series(T v, T x, T* pscale, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
static const char* function = "bessel_y_small_z_series<%1%>(%1%,%1%)";
|
||||
T prefix;
|
||||
T gam;
|
||||
T p = log(x / 2);
|
||||
T scale = 1;
|
||||
bool need_logs = (v >= max_factorial<T>::value) || (tools::log_max_value<T>() / v < fabs(p));
|
||||
if(!need_logs)
|
||||
{
|
||||
gam = boost::math::tgamma(v, pol);
|
||||
p = pow(x / 2, v);
|
||||
if(tools::max_value<T>() * p < gam)
|
||||
{
|
||||
scale /= gam;
|
||||
gam = 1;
|
||||
if(tools::max_value<T>() * p < gam)
|
||||
{
|
||||
return -policies::raise_overflow_error<T>(function, 0, pol);
|
||||
}
|
||||
}
|
||||
prefix = -gam / (constants::pi<T>() * p);
|
||||
}
|
||||
else
|
||||
{
|
||||
gam = boost::math::lgamma(v, pol);
|
||||
p = v * p;
|
||||
prefix = gam - log(constants::pi<T>()) - p;
|
||||
if(tools::log_max_value<T>() < prefix)
|
||||
{
|
||||
prefix -= log(tools::max_value<T>() / 4);
|
||||
scale /= (tools::max_value<T>() / 4);
|
||||
if(tools::log_max_value<T>() < prefix)
|
||||
{
|
||||
return -policies::raise_overflow_error<T>(function, 0, pol);
|
||||
}
|
||||
}
|
||||
prefix = -exp(prefix);
|
||||
}
|
||||
bessel_y_small_z_series_term_a<T, Policy> s(v, x);
|
||||
boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
|
||||
*pscale = scale;
|
||||
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
|
||||
T zero = 0;
|
||||
T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon<T, Policy>(), max_iter, zero);
|
||||
#else
|
||||
T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon<T, Policy>(), max_iter);
|
||||
#endif
|
||||
policies::check_series_iterations<T>("boost::math::bessel_y_small_z_series<%1%>(%1%,%1%)", max_iter, pol);
|
||||
result *= prefix;
|
||||
|
||||
if(!need_logs)
|
||||
{
|
||||
prefix = boost::math::tgamma(-v, pol) * boost::math::cos_pi(v) * p / constants::pi<T>();
|
||||
}
|
||||
else
|
||||
{
|
||||
int sgn;
|
||||
prefix = boost::math::lgamma(-v, &sgn, pol) + p;
|
||||
prefix = exp(prefix) * sgn / constants::pi<T>();
|
||||
}
|
||||
bessel_y_small_z_series_term_b<T, Policy> s2(v, x);
|
||||
max_iter = policies::get_max_series_iterations<Policy>();
|
||||
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
|
||||
T b = boost::math::tools::sum_series(s2, boost::math::policies::get_epsilon<T, Policy>(), max_iter, zero);
|
||||
#else
|
||||
T b = boost::math::tools::sum_series(s2, boost::math::policies::get_epsilon<T, Policy>(), max_iter);
|
||||
#endif
|
||||
result -= scale * prefix * b;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
T bessel_yn_small_z(int n, T z, T* scale, const Policy& pol)
|
||||
{
|
||||
//
|
||||
// See http://functions.wolfram.com/Bessel-TypeFunctions/BesselY/06/01/04/01/02/
|
||||
//
|
||||
// Note that when called we assume that x < epsilon and n is a positive integer.
|
||||
//
|
||||
BOOST_MATH_STD_USING
|
||||
BOOST_ASSERT(n >= 0);
|
||||
BOOST_ASSERT((z < policies::get_epsilon<T, Policy>()));
|
||||
|
||||
if(n == 0)
|
||||
{
|
||||
return (2 / constants::pi<T>()) * (log(z / 2) + constants::euler<T>());
|
||||
}
|
||||
else if(n == 1)
|
||||
{
|
||||
return (z / constants::pi<T>()) * log(z / 2)
|
||||
- 2 / (constants::pi<T>() * z)
|
||||
- (z / (2 * constants::pi<T>())) * (1 - 2 * constants::euler<T>());
|
||||
}
|
||||
else if(n == 2)
|
||||
{
|
||||
return (z * z) / (4 * constants::pi<T>()) * log(z / 2)
|
||||
- (4 / (constants::pi<T>() * z * z))
|
||||
- ((z * z) / (8 * constants::pi<T>())) * (T(3)/2 - 2 * constants::euler<T>());
|
||||
}
|
||||
else
|
||||
{
|
||||
T p = pow(z / 2, n);
|
||||
T result = -((boost::math::factorial<T>(n - 1) / constants::pi<T>()));
|
||||
if(p * tools::max_value<T>() < result)
|
||||
{
|
||||
T div = tools::max_value<T>() / 8;
|
||||
result /= div;
|
||||
*scale /= div;
|
||||
if(p * tools::max_value<T>() < result)
|
||||
{
|
||||
return -policies::raise_overflow_error<T>("bessel_yn_small_z<%1%>(%1%,%1%)", 0, pol);
|
||||
}
|
||||
}
|
||||
return result / p;
|
||||
}
|
||||
}
|
||||
|
||||
}}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_BESSEL_JN_SERIES_HPP
|
||||
|
||||
617
code_isotrope/boost/math/special_functions/detail/bessel_jy_zero.hpp
Executable file
617
code_isotrope/boost/math/special_functions/detail/bessel_jy_zero.hpp
Executable file
@@ -0,0 +1,617 @@
|
||||
// Copyright (c) 2013 Christopher Kormanyos
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// This work is based on an earlier work:
|
||||
// "Algorithm 910: A Portable C++ Multiple-Precision System for Special-Function Calculations",
|
||||
// in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. http://doi.acm.org/10.1145/1916461.1916469
|
||||
//
|
||||
// This header contains implementation details for estimating the zeros
|
||||
// of cylindrical Bessel and Neumann functions on the positive real axis.
|
||||
// Support is included for both positive as well as negative order.
|
||||
// Various methods are used to estimate the roots. These include
|
||||
// empirical curve fitting and McMahon's asymptotic approximation
|
||||
// for small order, uniform asymptotic expansion for large order,
|
||||
// and iteration and root interlacing for negative order.
|
||||
//
|
||||
#ifndef _BESSEL_JY_ZERO_2013_01_18_HPP_
|
||||
#define _BESSEL_JY_ZERO_2013_01_18_HPP_
|
||||
|
||||
#include <algorithm>
|
||||
#include <boost/math/constants/constants.hpp>
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/math/special_functions/cbrt.hpp>
|
||||
#include <boost/math/special_functions/detail/airy_ai_bi_zero.hpp>
|
||||
|
||||
namespace boost { namespace math {
|
||||
namespace detail
|
||||
{
|
||||
namespace bessel_zero
|
||||
{
|
||||
template<class T>
|
||||
T equation_nist_10_21_19(const T& v, const T& a)
|
||||
{
|
||||
// Get the initial estimate of the m'th root of Jv or Yv.
|
||||
// This subroutine is used for the order m with m > 1.
|
||||
// The order m has been used to create the input parameter a.
|
||||
|
||||
// This is Eq. 10.21.19 in the NIST Handbook.
|
||||
const T mu = (v * v) * 4U;
|
||||
const T mu_minus_one = mu - T(1);
|
||||
const T eight_a_inv = T(1) / (a * 8U);
|
||||
const T eight_a_inv_squared = eight_a_inv * eight_a_inv;
|
||||
|
||||
const T term3 = ((mu_minus_one * 4U) * ((mu * 7U) - T(31U) )) / 3U;
|
||||
const T term5 = ((mu_minus_one * 32U) * ((((mu * 83U) - T(982U) ) * mu) + T(3779U) )) / 15U;
|
||||
const T term7 = ((mu_minus_one * 64U) * ((((((mu * 6949U) - T(153855UL)) * mu) + T(1585743UL)) * mu) - T(6277237UL))) / 105U;
|
||||
|
||||
return a + (((( - term7
|
||||
* eight_a_inv_squared - term5)
|
||||
* eight_a_inv_squared - term3)
|
||||
* eight_a_inv_squared - mu_minus_one)
|
||||
* eight_a_inv);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
class equation_as_9_3_39_and_its_derivative
|
||||
{
|
||||
public:
|
||||
equation_as_9_3_39_and_its_derivative(const T& zt) : zeta(zt) { }
|
||||
|
||||
boost::math::tuple<T, T> operator()(const T& z) const
|
||||
{
|
||||
BOOST_MATH_STD_USING // ADL of std names, needed for acos, sqrt.
|
||||
|
||||
// Return the function of zeta that is implicitly defined
|
||||
// in A&S Eq. 9.3.39 as a function of z. The function is
|
||||
// returned along with its derivative with respect to z.
|
||||
|
||||
const T zsq_minus_one_sqrt = sqrt((z * z) - T(1));
|
||||
|
||||
const T the_function(
|
||||
zsq_minus_one_sqrt
|
||||
- ( acos(T(1) / z) + ((T(2) / 3U) * (zeta * sqrt(zeta)))));
|
||||
|
||||
const T its_derivative(zsq_minus_one_sqrt / z);
|
||||
|
||||
return boost::math::tuple<T, T>(the_function, its_derivative);
|
||||
}
|
||||
|
||||
private:
|
||||
const equation_as_9_3_39_and_its_derivative& operator=(const equation_as_9_3_39_and_its_derivative&);
|
||||
const T zeta;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
static T equation_as_9_5_26(const T& v, const T& ai_bi_root)
|
||||
{
|
||||
BOOST_MATH_STD_USING // ADL of std names, needed for log, sqrt.
|
||||
|
||||
// Obtain the estimate of the m'th zero of Jv or Yv.
|
||||
// The order m has been used to create the input parameter ai_bi_root.
|
||||
// Here, v is larger than about 2.2. The estimate is computed
|
||||
// from Abramowitz and Stegun Eqs. 9.5.22 and 9.5.26, page 371.
|
||||
//
|
||||
// The inversion of z as a function of zeta is mentioned in the text
|
||||
// following A&S Eq. 9.5.26. Here, we accomplish the inversion by
|
||||
// performing a Taylor expansion of Eq. 9.3.39 for large z to order 2
|
||||
// and solving the resulting quadratic equation, thereby taking
|
||||
// the positive root of the quadratic.
|
||||
// In other words: (2/3)(-zeta)^(3/2) approx = z + 1/(2z) - pi/2.
|
||||
// This leads to: z^2 - [(2/3)(-zeta)^(3/2) + pi/2]z + 1/2 = 0.
|
||||
//
|
||||
// With this initial estimate, Newton-Raphson iteration is used
|
||||
// to refine the value of the estimate of the root of z
|
||||
// as a function of zeta.
|
||||
|
||||
const T v_pow_third(boost::math::cbrt(v));
|
||||
const T v_pow_minus_two_thirds(T(1) / (v_pow_third * v_pow_third));
|
||||
|
||||
// Obtain zeta using the order v combined with the m'th root of
|
||||
// an airy function, as shown in A&S Eq. 9.5.22.
|
||||
const T zeta = v_pow_minus_two_thirds * (-ai_bi_root);
|
||||
|
||||
const T zeta_sqrt = sqrt(zeta);
|
||||
|
||||
// Set up a quadratic equation based on the Taylor series
|
||||
// expansion mentioned above.
|
||||
const T b = -((((zeta * zeta_sqrt) * 2U) / 3U) + boost::math::constants::half_pi<T>());
|
||||
|
||||
// Solve the quadratic equation, taking the positive root.
|
||||
const T z_estimate = (-b + sqrt((b * b) - T(2))) / 2U;
|
||||
|
||||
// Establish the range, the digits, and the iteration limit
|
||||
// for the upcoming root-finding.
|
||||
const T range_zmin = (std::max<T>)(z_estimate - T(1), T(1));
|
||||
const T range_zmax = z_estimate + T(1);
|
||||
|
||||
const int my_digits10 = static_cast<int>(static_cast<float>(boost::math::tools::digits<T>() * 0.301F));
|
||||
|
||||
// Select the maximum allowed iterations based on the number
|
||||
// of decimal digits in the numeric type T, being at least 12.
|
||||
const boost::uintmax_t iterations_allowed = static_cast<boost::uintmax_t>((std::max)(12, my_digits10 * 2));
|
||||
|
||||
boost::uintmax_t iterations_used = iterations_allowed;
|
||||
|
||||
// Calculate the root of z as a function of zeta.
|
||||
const T z = boost::math::tools::newton_raphson_iterate(
|
||||
boost::math::detail::bessel_zero::equation_as_9_3_39_and_its_derivative<T>(zeta),
|
||||
z_estimate,
|
||||
range_zmin,
|
||||
range_zmax,
|
||||
(std::min)(boost::math::tools::digits<T>(), boost::math::tools::digits<float>()),
|
||||
iterations_used);
|
||||
|
||||
static_cast<void>(iterations_used);
|
||||
|
||||
// Continue with the implementation of A&S Eq. 9.3.39.
|
||||
const T zsq_minus_one = (z * z) - T(1);
|
||||
const T zsq_minus_one_sqrt = sqrt(zsq_minus_one);
|
||||
|
||||
// This is A&S Eq. 9.3.42.
|
||||
const T b0_term_5_24 = T(5) / ((zsq_minus_one * zsq_minus_one_sqrt) * 24U);
|
||||
const T b0_term_1_8 = T(1) / ( zsq_minus_one_sqrt * 8U);
|
||||
const T b0_term_5_48 = T(5) / ((zeta * zeta) * 48U);
|
||||
|
||||
const T b0 = -b0_term_5_48 + ((b0_term_5_24 + b0_term_1_8) / zeta_sqrt);
|
||||
|
||||
// This is the second line of A&S Eq. 9.5.26 for f_k with k = 1.
|
||||
const T f1 = ((z * zeta_sqrt) * b0) / zsq_minus_one_sqrt;
|
||||
|
||||
// This is A&S Eq. 9.5.22 expanded to k = 1 (i.e., one term in the series).
|
||||
return (v * z) + (f1 / v);
|
||||
}
|
||||
|
||||
namespace cyl_bessel_j_zero_detail
|
||||
{
|
||||
template<class T>
|
||||
T equation_nist_10_21_40_a(const T& v)
|
||||
{
|
||||
const T v_pow_third(boost::math::cbrt(v));
|
||||
const T v_pow_minus_two_thirds(T(1) / (v_pow_third * v_pow_third));
|
||||
|
||||
return v * ((((( + T(0.043)
|
||||
* v_pow_minus_two_thirds - T(0.0908))
|
||||
* v_pow_minus_two_thirds - T(0.00397))
|
||||
* v_pow_minus_two_thirds + T(1.033150))
|
||||
* v_pow_minus_two_thirds + T(1.8557571))
|
||||
* v_pow_minus_two_thirds + T(1));
|
||||
}
|
||||
|
||||
template<class T, class Policy>
|
||||
class function_object_jv
|
||||
{
|
||||
public:
|
||||
function_object_jv(const T& v,
|
||||
const Policy& pol) : my_v(v),
|
||||
my_pol(pol) { }
|
||||
|
||||
T operator()(const T& x) const
|
||||
{
|
||||
return boost::math::cyl_bessel_j(my_v, x, my_pol);
|
||||
}
|
||||
|
||||
private:
|
||||
const T my_v;
|
||||
const Policy& my_pol;
|
||||
const function_object_jv& operator=(const function_object_jv&);
|
||||
};
|
||||
|
||||
template<class T, class Policy>
|
||||
class function_object_jv_and_jv_prime
|
||||
{
|
||||
public:
|
||||
function_object_jv_and_jv_prime(const T& v,
|
||||
const bool order_is_zero,
|
||||
const Policy& pol) : my_v(v),
|
||||
my_order_is_zero(order_is_zero),
|
||||
my_pol(pol) { }
|
||||
|
||||
boost::math::tuple<T, T> operator()(const T& x) const
|
||||
{
|
||||
// Obtain Jv(x) and Jv'(x).
|
||||
// Chris's original code called the Bessel function implementation layer direct,
|
||||
// but that circumvented optimizations for integer-orders. Call the documented
|
||||
// top level functions instead, and let them sort out which implementation to use.
|
||||
T j_v;
|
||||
T j_v_prime;
|
||||
|
||||
if(my_order_is_zero)
|
||||
{
|
||||
j_v = boost::math::cyl_bessel_j(0, x, my_pol);
|
||||
j_v_prime = -boost::math::cyl_bessel_j(1, x, my_pol);
|
||||
}
|
||||
else
|
||||
{
|
||||
j_v = boost::math::cyl_bessel_j( my_v, x, my_pol);
|
||||
const T j_v_m1 (boost::math::cyl_bessel_j(T(my_v - 1), x, my_pol));
|
||||
j_v_prime = j_v_m1 - ((my_v * j_v) / x);
|
||||
}
|
||||
|
||||
// Return a tuple containing both Jv(x) and Jv'(x).
|
||||
return boost::math::make_tuple(j_v, j_v_prime);
|
||||
}
|
||||
|
||||
private:
|
||||
const T my_v;
|
||||
const bool my_order_is_zero;
|
||||
const Policy& my_pol;
|
||||
const function_object_jv_and_jv_prime& operator=(const function_object_jv_and_jv_prime&);
|
||||
};
|
||||
|
||||
template<class T> bool my_bisection_unreachable_tolerance(const T&, const T&) { return false; }
|
||||
|
||||
template<class T, class Policy>
|
||||
T initial_guess(const T& v, const int m, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING // ADL of std names, needed for floor.
|
||||
|
||||
// Compute an estimate of the m'th root of cyl_bessel_j.
|
||||
|
||||
T guess;
|
||||
|
||||
// There is special handling for negative order.
|
||||
if(v < 0)
|
||||
{
|
||||
if((m == 1) && (v > -0.5F))
|
||||
{
|
||||
// For small, negative v, use the results of empirical curve fitting.
|
||||
// Mathematica(R) session for the coefficients:
|
||||
// Table[{n, BesselJZero[n, 1]}, {n, -(1/2), 0, 1/10}]
|
||||
// N[%, 20]
|
||||
// Fit[%, {n^0, n^1, n^2, n^3, n^4, n^5, n^6}, n]
|
||||
guess = ((((( - T(0.2321156900729)
|
||||
* v - T(0.1493247777488))
|
||||
* v - T(0.15205419167239))
|
||||
* v + T(0.07814930561249))
|
||||
* v - T(0.17757573537688))
|
||||
* v + T(1.542805677045663))
|
||||
* v + T(2.40482555769577277);
|
||||
|
||||
return guess;
|
||||
}
|
||||
|
||||
// Create the positive order and extract its positive floor integer part.
|
||||
const T vv(-v);
|
||||
const T vv_floor(floor(vv));
|
||||
|
||||
// The to-be-found root is bracketed by the roots of the
|
||||
// Bessel function whose reflected, positive integer order
|
||||
// is less than, but nearest to vv.
|
||||
|
||||
T root_hi = boost::math::detail::bessel_zero::cyl_bessel_j_zero_detail::initial_guess(vv_floor, m, pol);
|
||||
T root_lo;
|
||||
|
||||
if(m == 1)
|
||||
{
|
||||
// The estimate of the first root for negative order is found using
|
||||
// an adaptive range-searching algorithm.
|
||||
root_lo = T(root_hi - 0.1F);
|
||||
|
||||
const bool hi_end_of_bracket_is_negative = (boost::math::cyl_bessel_j(v, root_hi, pol) < 0);
|
||||
|
||||
while((root_lo > boost::math::tools::epsilon<T>()))
|
||||
{
|
||||
const bool lo_end_of_bracket_is_negative = (boost::math::cyl_bessel_j(v, root_lo, pol) < 0);
|
||||
|
||||
if(hi_end_of_bracket_is_negative != lo_end_of_bracket_is_negative)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
root_hi = root_lo;
|
||||
|
||||
// Decrease the lower end of the bracket using an adaptive algorithm.
|
||||
if(root_lo > 0.5F)
|
||||
{
|
||||
root_lo -= 0.5F;
|
||||
}
|
||||
else
|
||||
{
|
||||
root_lo *= 0.75F;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
root_lo = boost::math::detail::bessel_zero::cyl_bessel_j_zero_detail::initial_guess(vv_floor, m - 1, pol);
|
||||
}
|
||||
|
||||
// Perform several steps of bisection iteration to refine the guess.
|
||||
boost::uintmax_t number_of_iterations(12U);
|
||||
|
||||
// Do the bisection iteration.
|
||||
const boost::math::tuple<T, T> guess_pair =
|
||||
boost::math::tools::bisect(
|
||||
boost::math::detail::bessel_zero::cyl_bessel_j_zero_detail::function_object_jv<T, Policy>(v, pol),
|
||||
root_lo,
|
||||
root_hi,
|
||||
boost::math::detail::bessel_zero::cyl_bessel_j_zero_detail::my_bisection_unreachable_tolerance<T>,
|
||||
number_of_iterations);
|
||||
|
||||
return (boost::math::get<0>(guess_pair) + boost::math::get<1>(guess_pair)) / 2U;
|
||||
}
|
||||
|
||||
if(m == 1U)
|
||||
{
|
||||
// Get the initial estimate of the first root.
|
||||
|
||||
if(v < 2.2F)
|
||||
{
|
||||
// For small v, use the results of empirical curve fitting.
|
||||
// Mathematica(R) session for the coefficients:
|
||||
// Table[{n, BesselJZero[n, 1]}, {n, 0, 22/10, 1/10}]
|
||||
// N[%, 20]
|
||||
// Fit[%, {n^0, n^1, n^2, n^3, n^4, n^5, n^6}, n]
|
||||
guess = ((((( - T(0.0008342379046010)
|
||||
* v + T(0.007590035637410))
|
||||
* v - T(0.030640914772013))
|
||||
* v + T(0.078232088020106))
|
||||
* v - T(0.169668712590620))
|
||||
* v + T(1.542187960073750))
|
||||
* v + T(2.4048359915254634);
|
||||
}
|
||||
else
|
||||
{
|
||||
// For larger v, use the first line of Eqs. 10.21.40 in the NIST Handbook.
|
||||
guess = boost::math::detail::bessel_zero::cyl_bessel_j_zero_detail::equation_nist_10_21_40_a(v);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(v < 2.2F)
|
||||
{
|
||||
// Use Eq. 10.21.19 in the NIST Handbook.
|
||||
const T a(((v + T(m * 2U)) - T(0.5)) * boost::math::constants::half_pi<T>());
|
||||
|
||||
guess = boost::math::detail::bessel_zero::equation_nist_10_21_19(v, a);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get an estimate of the m'th root of airy_ai.
|
||||
const T airy_ai_root(boost::math::detail::airy_zero::airy_ai_zero_detail::initial_guess<T>(m));
|
||||
|
||||
// Use Eq. 9.5.26 in the A&S Handbook.
|
||||
guess = boost::math::detail::bessel_zero::equation_as_9_5_26(v, airy_ai_root);
|
||||
}
|
||||
}
|
||||
|
||||
return guess;
|
||||
}
|
||||
} // namespace cyl_bessel_j_zero_detail
|
||||
|
||||
namespace cyl_neumann_zero_detail
|
||||
{
|
||||
template<class T>
|
||||
T equation_nist_10_21_40_b(const T& v)
|
||||
{
|
||||
const T v_pow_third(boost::math::cbrt(v));
|
||||
const T v_pow_minus_two_thirds(T(1) / (v_pow_third * v_pow_third));
|
||||
|
||||
return v * ((((( - T(0.001)
|
||||
* v_pow_minus_two_thirds - T(0.0060))
|
||||
* v_pow_minus_two_thirds + T(0.01198))
|
||||
* v_pow_minus_two_thirds + T(0.260351))
|
||||
* v_pow_minus_two_thirds + T(0.9315768))
|
||||
* v_pow_minus_two_thirds + T(1));
|
||||
}
|
||||
|
||||
template<class T, class Policy>
|
||||
class function_object_yv
|
||||
{
|
||||
public:
|
||||
function_object_yv(const T& v,
|
||||
const Policy& pol) : my_v(v),
|
||||
my_pol(pol) { }
|
||||
|
||||
T operator()(const T& x) const
|
||||
{
|
||||
return boost::math::cyl_neumann(my_v, x, my_pol);
|
||||
}
|
||||
|
||||
private:
|
||||
const T my_v;
|
||||
const Policy& my_pol;
|
||||
const function_object_yv& operator=(const function_object_yv&);
|
||||
};
|
||||
|
||||
template<class T, class Policy>
|
||||
class function_object_yv_and_yv_prime
|
||||
{
|
||||
public:
|
||||
function_object_yv_and_yv_prime(const T& v,
|
||||
const Policy& pol) : my_v(v),
|
||||
my_pol(pol) { }
|
||||
|
||||
boost::math::tuple<T, T> operator()(const T& x) const
|
||||
{
|
||||
const T half_epsilon(boost::math::tools::epsilon<T>() / 2U);
|
||||
|
||||
const bool order_is_zero = ((my_v > -half_epsilon) && (my_v < +half_epsilon));
|
||||
|
||||
// Obtain Yv(x) and Yv'(x).
|
||||
// Chris's original code called the Bessel function implementation layer direct,
|
||||
// but that circumvented optimizations for integer-orders. Call the documented
|
||||
// top level functions instead, and let them sort out which implementation to use.
|
||||
T y_v;
|
||||
T y_v_prime;
|
||||
|
||||
if(order_is_zero)
|
||||
{
|
||||
y_v = boost::math::cyl_neumann(0, x, my_pol);
|
||||
y_v_prime = -boost::math::cyl_neumann(1, x, my_pol);
|
||||
}
|
||||
else
|
||||
{
|
||||
y_v = boost::math::cyl_neumann( my_v, x, my_pol);
|
||||
const T y_v_m1 (boost::math::cyl_neumann(T(my_v - 1), x, my_pol));
|
||||
y_v_prime = y_v_m1 - ((my_v * y_v) / x);
|
||||
}
|
||||
|
||||
// Return a tuple containing both Yv(x) and Yv'(x).
|
||||
return boost::math::make_tuple(y_v, y_v_prime);
|
||||
}
|
||||
|
||||
private:
|
||||
const T my_v;
|
||||
const Policy& my_pol;
|
||||
const function_object_yv_and_yv_prime& operator=(const function_object_yv_and_yv_prime&);
|
||||
};
|
||||
|
||||
template<class T> bool my_bisection_unreachable_tolerance(const T&, const T&) { return false; }
|
||||
|
||||
template<class T, class Policy>
|
||||
T initial_guess(const T& v, const int m, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING // ADL of std names, needed for floor.
|
||||
|
||||
// Compute an estimate of the m'th root of cyl_neumann.
|
||||
|
||||
T guess;
|
||||
|
||||
// There is special handling for negative order.
|
||||
if(v < 0)
|
||||
{
|
||||
// Create the positive order and extract its positive floor and ceiling integer parts.
|
||||
const T vv(-v);
|
||||
const T vv_floor(floor(vv));
|
||||
|
||||
// The to-be-found root is bracketed by the roots of the
|
||||
// Bessel function whose reflected, positive integer order
|
||||
// is less than, but nearest to vv.
|
||||
|
||||
// The special case of negative, half-integer order uses
|
||||
// the relation between Yv and spherical Bessel functions
|
||||
// in order to obtain the bracket for the root.
|
||||
// In these special cases, cyl_neumann(-n/2, x) = sph_bessel_j(+n/2, x)
|
||||
// for v = -n/2.
|
||||
|
||||
T root_hi;
|
||||
T root_lo;
|
||||
|
||||
if(m == 1)
|
||||
{
|
||||
// The estimate of the first root for negative order is found using
|
||||
// an adaptive range-searching algorithm.
|
||||
// Take special precautions for the discontinuity at negative,
|
||||
// half-integer orders and use different brackets above and below these.
|
||||
if(T(vv - vv_floor) < 0.5F)
|
||||
{
|
||||
root_hi = boost::math::detail::bessel_zero::cyl_neumann_zero_detail::initial_guess(vv_floor, m, pol);
|
||||
}
|
||||
else
|
||||
{
|
||||
root_hi = boost::math::detail::bessel_zero::cyl_bessel_j_zero_detail::initial_guess(T(vv_floor + 0.5F), m, pol);
|
||||
}
|
||||
|
||||
root_lo = T(root_hi - 0.1F);
|
||||
|
||||
const bool hi_end_of_bracket_is_negative = (boost::math::cyl_neumann(v, root_hi, pol) < 0);
|
||||
|
||||
while((root_lo > boost::math::tools::epsilon<T>()))
|
||||
{
|
||||
const bool lo_end_of_bracket_is_negative = (boost::math::cyl_neumann(v, root_lo, pol) < 0);
|
||||
|
||||
if(hi_end_of_bracket_is_negative != lo_end_of_bracket_is_negative)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
root_hi = root_lo;
|
||||
|
||||
// Decrease the lower end of the bracket using an adaptive algorithm.
|
||||
if(root_lo > 0.5F)
|
||||
{
|
||||
root_lo -= 0.5F;
|
||||
}
|
||||
else
|
||||
{
|
||||
root_lo *= 0.75F;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(T(vv - vv_floor) < 0.5F)
|
||||
{
|
||||
root_lo = boost::math::detail::bessel_zero::cyl_neumann_zero_detail::initial_guess(vv_floor, m - 1, pol);
|
||||
root_hi = boost::math::detail::bessel_zero::cyl_neumann_zero_detail::initial_guess(vv_floor, m, pol);
|
||||
root_lo += 0.01F;
|
||||
root_hi += 0.01F;
|
||||
}
|
||||
else
|
||||
{
|
||||
root_lo = boost::math::detail::bessel_zero::cyl_bessel_j_zero_detail::initial_guess(T(vv_floor + 0.5F), m - 1, pol);
|
||||
root_hi = boost::math::detail::bessel_zero::cyl_bessel_j_zero_detail::initial_guess(T(vv_floor + 0.5F), m, pol);
|
||||
root_lo += 0.01F;
|
||||
root_hi += 0.01F;
|
||||
}
|
||||
}
|
||||
|
||||
// Perform several steps of bisection iteration to refine the guess.
|
||||
boost::uintmax_t number_of_iterations(12U);
|
||||
|
||||
// Do the bisection iteration.
|
||||
const boost::math::tuple<T, T> guess_pair =
|
||||
boost::math::tools::bisect(
|
||||
boost::math::detail::bessel_zero::cyl_neumann_zero_detail::function_object_yv<T, Policy>(v, pol),
|
||||
root_lo,
|
||||
root_hi,
|
||||
boost::math::detail::bessel_zero::cyl_neumann_zero_detail::my_bisection_unreachable_tolerance<T>,
|
||||
number_of_iterations);
|
||||
|
||||
return (boost::math::get<0>(guess_pair) + boost::math::get<1>(guess_pair)) / 2U;
|
||||
}
|
||||
|
||||
if(m == 1U)
|
||||
{
|
||||
// Get the initial estimate of the first root.
|
||||
|
||||
if(v < 2.2F)
|
||||
{
|
||||
// For small v, use the results of empirical curve fitting.
|
||||
// Mathematica(R) session for the coefficients:
|
||||
// Table[{n, BesselYZero[n, 1]}, {n, 0, 22/10, 1/10}]
|
||||
// N[%, 20]
|
||||
// Fit[%, {n^0, n^1, n^2, n^3, n^4, n^5, n^6}, n]
|
||||
guess = ((((( - T(0.0025095909235652)
|
||||
* v + T(0.021291887049053))
|
||||
* v - T(0.076487785486526))
|
||||
* v + T(0.159110268115362))
|
||||
* v - T(0.241681668765196))
|
||||
* v + T(1.4437846310885244))
|
||||
* v + T(0.89362115190200490);
|
||||
}
|
||||
else
|
||||
{
|
||||
// For larger v, use the second line of Eqs. 10.21.40 in the NIST Handbook.
|
||||
guess = boost::math::detail::bessel_zero::cyl_neumann_zero_detail::equation_nist_10_21_40_b(v);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(v < 2.2F)
|
||||
{
|
||||
// Use Eq. 10.21.19 in the NIST Handbook.
|
||||
const T a(((v + T(m * 2U)) - T(1.5)) * boost::math::constants::half_pi<T>());
|
||||
|
||||
guess = boost::math::detail::bessel_zero::equation_nist_10_21_19(v, a);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get an estimate of the m'th root of airy_bi.
|
||||
const T airy_bi_root(boost::math::detail::airy_zero::airy_bi_zero_detail::initial_guess<T>(m));
|
||||
|
||||
// Use Eq. 9.5.26 in the A&S Handbook.
|
||||
guess = boost::math::detail::bessel_zero::equation_as_9_5_26(v, airy_bi_root);
|
||||
}
|
||||
}
|
||||
|
||||
return guess;
|
||||
}
|
||||
} // namespace cyl_neumann_zero_detail
|
||||
} // namespace bessel_zero
|
||||
} } } // namespace boost::math::detail
|
||||
|
||||
#endif // _BESSEL_JY_ZERO_2013_01_18_HPP_
|
||||
509
code_isotrope/boost/math/special_functions/detail/bessel_k0.hpp
Executable file
509
code_isotrope/boost/math/special_functions/detail/bessel_k0.hpp
Executable file
@@ -0,0 +1,509 @@
|
||||
// Copyright (c) 2006 Xiaogang Zhang
|
||||
// Copyright (c) 2017 John Maddock
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_MATH_BESSEL_K0_HPP
|
||||
#define BOOST_MATH_BESSEL_K0_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4702) // Unreachable code (release mode only warning)
|
||||
#endif
|
||||
|
||||
#include <boost/math/tools/rational.hpp>
|
||||
#include <boost/math/tools/big_constant.hpp>
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
// Modified Bessel function of the second kind of order zero
|
||||
// minimax rational approximations on intervals, see
|
||||
// Russon and Blair, Chalk River Report AECL-3461, 1969,
|
||||
// as revised by Pavel Holoborodko in "Rational Approximations
|
||||
// for the Modified Bessel Function of the Second Kind - K0(x)
|
||||
// for Computations with Double Precision", see
|
||||
// http://www.advanpix.com/2015/11/25/rational-approximations-for-the-modified-bessel-function-of-the-second-kind-k0-for-computations-with-double-precision/
|
||||
//
|
||||
// The actual coefficients used are our own derivation (by JM)
|
||||
// since we extend to both greater and lesser precision than the
|
||||
// references above. We can also improve performance WRT to
|
||||
// Holoborodko without loss of precision.
|
||||
|
||||
namespace boost { namespace math { namespace detail{
|
||||
|
||||
template <typename T>
|
||||
T bessel_k0(const T& x);
|
||||
|
||||
template <class T, class tag>
|
||||
struct bessel_k0_initializer
|
||||
{
|
||||
struct init
|
||||
{
|
||||
init()
|
||||
{
|
||||
do_init(tag());
|
||||
}
|
||||
static void do_init(const mpl::int_<113>&)
|
||||
{
|
||||
bessel_k0(T(0.5));
|
||||
bessel_k0(T(1.5));
|
||||
}
|
||||
static void do_init(const mpl::int_<64>&)
|
||||
{
|
||||
bessel_k0(T(0.5));
|
||||
bessel_k0(T(1.5));
|
||||
}
|
||||
template <class U>
|
||||
static void do_init(const U&){}
|
||||
void force_instantiate()const{}
|
||||
};
|
||||
static const init initializer;
|
||||
static void force_instantiate()
|
||||
{
|
||||
initializer.force_instantiate();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class tag>
|
||||
const typename bessel_k0_initializer<T, tag>::init bessel_k0_initializer<T, tag>::initializer;
|
||||
|
||||
|
||||
template <typename T, int N>
|
||||
T bessel_k0_imp(const T& x, const mpl::int_<N>&)
|
||||
{
|
||||
BOOST_ASSERT(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T bessel_k0_imp(const T& x, const mpl::int_<24>&)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
if(x <= 1)
|
||||
{
|
||||
// Maximum Deviation Found : 2.358e-09
|
||||
// Expected Error Term : -2.358e-09
|
||||
// Maximum Relative Change in Control Points : 9.552e-02
|
||||
// Max Error found at float precision = Poly : 4.448220e-08
|
||||
static const T Y = 1.137250900268554688f;
|
||||
static const T P[] =
|
||||
{
|
||||
-1.372508979104259711e-01f,
|
||||
2.622545986273687617e-01f,
|
||||
5.047103728247919836e-03f
|
||||
};
|
||||
static const T Q[] =
|
||||
{
|
||||
1.000000000000000000e+00f,
|
||||
-8.928694018000029415e-02f,
|
||||
2.985980684180969241e-03f
|
||||
};
|
||||
T a = x * x / 4;
|
||||
a = (tools::evaluate_rational(P, Q, a) + Y) * a + 1;
|
||||
|
||||
// Maximum Deviation Found: 1.346e-09
|
||||
// Expected Error Term : -1.343e-09
|
||||
// Maximum Relative Change in Control Points : 2.405e-02
|
||||
// Max Error found at float precision = Poly : 1.354814e-07
|
||||
static const T P2[] = {
|
||||
1.159315158e-01f,
|
||||
2.789828686e-01f,
|
||||
2.524902861e-02f,
|
||||
8.457241514e-04f,
|
||||
1.530051997e-05f
|
||||
};
|
||||
return tools::evaluate_polynomial(P2, T(x * x)) - log(x) * a;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Maximum Deviation Found: 1.587e-08
|
||||
// Expected Error Term : 1.531e-08
|
||||
// Maximum Relative Change in Control Points : 9.064e-02
|
||||
// Max Error found at float precision = Poly : 5.065020e-08
|
||||
|
||||
static const T P[] =
|
||||
{
|
||||
2.533141220e-01,
|
||||
5.221502603e-01,
|
||||
6.380180669e-02,
|
||||
-5.934976547e-02
|
||||
};
|
||||
static const T Q[] =
|
||||
{
|
||||
1.000000000e+00,
|
||||
2.679722431e+00,
|
||||
1.561635813e+00,
|
||||
1.573660661e-01
|
||||
};
|
||||
if(x < tools::log_max_value<T>())
|
||||
return ((tools::evaluate_rational(P, Q, T(1 / x)) + 1) * exp(-x) / sqrt(x));
|
||||
else
|
||||
{
|
||||
T ex = exp(-x / 2);
|
||||
return ((tools::evaluate_rational(P, Q, T(1 / x)) + 1) * ex / sqrt(x)) * ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T bessel_k0_imp(const T& x, const mpl::int_<53>&)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
if(x <= 1)
|
||||
{
|
||||
// Maximum Deviation Found: 6.077e-17
|
||||
// Expected Error Term : -6.077e-17
|
||||
// Maximum Relative Change in Control Points : 7.797e-02
|
||||
// Max Error found at double precision = Poly : 1.003156e-16
|
||||
static const T Y = 1.137250900268554688;
|
||||
static const T P[] =
|
||||
{
|
||||
-1.372509002685546267e-01,
|
||||
2.574916117833312855e-01,
|
||||
1.395474602146869316e-02,
|
||||
5.445476986653926759e-04,
|
||||
7.125159422136622118e-06
|
||||
};
|
||||
static const T Q[] =
|
||||
{
|
||||
1.000000000000000000e+00,
|
||||
-5.458333438017788530e-02,
|
||||
1.291052816975251298e-03,
|
||||
-1.367653946978586591e-05
|
||||
};
|
||||
|
||||
T a = x * x / 4;
|
||||
a = (tools::evaluate_polynomial(P, a) / tools::evaluate_polynomial(Q, a) + Y) * a + 1;
|
||||
|
||||
// Maximum Deviation Found: 3.429e-18
|
||||
// Expected Error Term : 3.392e-18
|
||||
// Maximum Relative Change in Control Points : 2.041e-02
|
||||
// Max Error found at double precision = Poly : 2.513112e-16
|
||||
static const T P2[] =
|
||||
{
|
||||
1.159315156584124484e-01,
|
||||
2.789828789146031732e-01,
|
||||
2.524892993216121934e-02,
|
||||
8.460350907213637784e-04,
|
||||
1.491471924309617534e-05,
|
||||
1.627106892422088488e-07,
|
||||
1.208266102392756055e-09,
|
||||
6.611686391749704310e-12
|
||||
};
|
||||
|
||||
return tools::evaluate_polynomial(P2, T(x * x)) - log(x) * a;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Maximum Deviation Found: 4.316e-17
|
||||
// Expected Error Term : 9.570e-18
|
||||
// Maximum Relative Change in Control Points : 2.757e-01
|
||||
// Max Error found at double precision = Poly : 1.001560e-16
|
||||
|
||||
static const T Y = 1;
|
||||
static const T P[] =
|
||||
{
|
||||
2.533141373155002416e-01,
|
||||
3.628342133984595192e+00,
|
||||
1.868441889406606057e+01,
|
||||
4.306243981063412784e+01,
|
||||
4.424116209627428189e+01,
|
||||
1.562095339356220468e+01,
|
||||
-1.810138978229410898e+00,
|
||||
-1.414237994269995877e+00,
|
||||
-9.369168119754924625e-02
|
||||
};
|
||||
static const T Q[] =
|
||||
{
|
||||
1.000000000000000000e+00,
|
||||
1.494194694879908328e+01,
|
||||
8.265296455388554217e+01,
|
||||
2.162779506621866970e+02,
|
||||
2.845145155184222157e+02,
|
||||
1.851714491916334995e+02,
|
||||
5.486540717439723515e+01,
|
||||
6.118075837628957015e+00,
|
||||
1.586261269326235053e-01
|
||||
};
|
||||
if(x < tools::log_max_value<T>())
|
||||
return ((tools::evaluate_rational(P, Q, T(1 / x)) + Y) * exp(-x) / sqrt(x));
|
||||
else
|
||||
{
|
||||
T ex = exp(-x / 2);
|
||||
return ((tools::evaluate_rational(P, Q, T(1 / x)) + Y) * ex / sqrt(x)) * ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T bessel_k0_imp(const T& x, const mpl::int_<64>&)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
if(x <= 1)
|
||||
{
|
||||
// Maximum Deviation Found: 2.180e-22
|
||||
// Expected Error Term : 2.180e-22
|
||||
// Maximum Relative Change in Control Points : 2.943e-01
|
||||
// Max Error found at float80 precision = Poly : 3.923207e-20
|
||||
static const T Y = 1.137250900268554687500e+00;
|
||||
static const T P[] =
|
||||
{
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -1.372509002685546875002e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 2.566481981037407600436e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.551881122448948854873e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 6.646112454323276529650e-04),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.213747930378196492543e-05),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 9.423709328020389560844e-08)
|
||||
};
|
||||
static const T Q[] =
|
||||
{
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.000000000000000000000e+00),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -4.843828412587773008342e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.088484822515098936140e-03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -1.374724008530702784829e-05),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 8.452665455952581680339e-08)
|
||||
};
|
||||
|
||||
|
||||
T a = x * x / 4;
|
||||
a = (tools::evaluate_polynomial(P, a) / tools::evaluate_polynomial(Q, a) + Y) * a + 1;
|
||||
|
||||
// Maximum Deviation Found: 2.440e-21
|
||||
// Expected Error Term : -2.434e-21
|
||||
// Maximum Relative Change in Control Points : 2.459e-02
|
||||
// Max Error found at float80 precision = Poly : 1.482487e-19
|
||||
static const T P2[] =
|
||||
{
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.159315156584124488110e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 2.764832791416047889734e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.926062887220923354112e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 3.660777862036966089410e-04),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 2.094942446930673386849e-06)
|
||||
};
|
||||
static const T Q2[] =
|
||||
{
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.000000000000000000000e+00),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -2.156100313881251616320e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 2.315993873344905957033e-04),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -1.529444499350703363451e-06),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 5.524988589917857531177e-09)
|
||||
};
|
||||
return tools::evaluate_rational(P2, Q2, T(x * x)) - log(x) * a;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Maximum Deviation Found: 4.291e-20
|
||||
// Expected Error Term : 2.236e-21
|
||||
// Maximum Relative Change in Control Points : 3.021e-01
|
||||
//Max Error found at float80 precision = Poly : 8.727378e-20
|
||||
static const T Y = 1;
|
||||
static const T P[] =
|
||||
{
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 2.533141373155002512056e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 5.417942070721928652715e+00),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 4.477464607463971754433e+01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.838745728725943889876e+02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 4.009736314927811202517e+02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 4.557411293123609803452e+02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 2.360222564015361268955e+02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 2.385435333168505701022e+01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -1.750195760942181592050e+01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -4.059789241612946683713e+00),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -1.612783121537333908889e-01)
|
||||
};
|
||||
static const T Q[] =
|
||||
{
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.000000000000000000000e+00),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 2.200669254769325861404e+01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.900177593527144126549e+02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 8.361003989965786932682e+02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 2.041319870804843395893e+03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 2.828491555113790345068e+03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 2.190342229261529076624e+03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 9.003330795963812219852e+02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.773371397243777891569e+02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.368634935531158398439e+01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 2.543310879400359967327e-01)
|
||||
};
|
||||
if(x < tools::log_max_value<T>())
|
||||
return ((tools::evaluate_rational(P, Q, T(1 / x)) + Y) * exp(-x) / sqrt(x));
|
||||
else
|
||||
{
|
||||
T ex = exp(-x / 2);
|
||||
return ((tools::evaluate_rational(P, Q, T(1 / x)) + Y) * ex / sqrt(x)) * ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T bessel_k0_imp(const T& x, const mpl::int_<113>&)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
if(x <= 1)
|
||||
{
|
||||
// Maximum Deviation Found: 5.682e-37
|
||||
// Expected Error Term : 5.682e-37
|
||||
// Maximum Relative Change in Control Points : 6.094e-04
|
||||
// Max Error found at float128 precision = Poly : 5.338213e-35
|
||||
static const T Y = 1.137250900268554687500000000000000000e+00f;
|
||||
static const T P[] =
|
||||
{
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -1.372509002685546875000000000000000006e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.556212905071072782462974351698081303e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.742459135264203478530904179889103929e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 8.077860530453688571555479526961318918e-04),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.868173911669241091399374307788635148e-05),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.496405768838992243478709145123306602e-07),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.752489221949580551692915881999762125e-09),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 5.243010555737173524710512824955368526e-12)
|
||||
};
|
||||
static const T Q[] =
|
||||
{
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.000000000000000000000000000000000000e+00),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -4.095631064064621099785696980653193721e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 8.313880983725212151967078809725835532e-04),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -1.095229912293480063501285562382835142e-05),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.022828799511943141130509410251996277e-07),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -6.860874007419812445494782795829046836e-10),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.107297802344970725756092082686799037e-12),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -7.460529579244623559164763757787600944e-15)
|
||||
};
|
||||
T a = x * x / 4;
|
||||
a = (tools::evaluate_rational(P, Q, a) + Y) * a + 1;
|
||||
|
||||
// Maximum Deviation Found: 5.173e-38
|
||||
// Expected Error Term : 5.105e-38
|
||||
// Maximum Relative Change in Control Points : 9.734e-03
|
||||
// Max Error found at float128 precision = Poly : 1.688806e-34
|
||||
static const T P2[] =
|
||||
{
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.159315156584124488107200313757741370e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.789828789146031122026800078439435369e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.524892993216269451266750049024628432e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 8.460350907082229957222453839935101823e-04),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.491471929926042875260452849503857976e-05),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.627105610481598430816014719558896866e-07),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.208426165007797264194914898538250281e-09),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 6.508697838747354949164182457073784117e-12),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.659784680639805301101014383907273109e-14),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 8.531090131964391104248859415958109654e-17),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.205195117066478034260323124669936314e-19),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 4.692219280289030165761119775783115426e-22),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 8.362350161092532344171965861545860747e-25),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.277990623924628999539014980773738258e-27)
|
||||
};
|
||||
|
||||
return tools::evaluate_polynomial(P2, T(x * x)) - log(x) * a;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Maximum Deviation Found: 1.462e-34
|
||||
// Expected Error Term : 4.917e-40
|
||||
// Maximum Relative Change in Control Points : 3.385e-01
|
||||
// Max Error found at float128 precision = Poly : 1.567573e-34
|
||||
static const T Y = 1;
|
||||
static const T P[] =
|
||||
{
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.533141373155002512078826424055226265e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.001949740768235770078339977110749204e+01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 6.991516715983883248363351472378349986e+02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.429587951594593159075690819360687720e+04),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.911933815201948768044660065771258450e+05),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.769943016204926614862175317962439875e+06),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.170866154649560750500954150401105606e+07),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 5.634687099724383996792011977705727661e+07),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.989524036456492581597607246664394014e+08),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 5.160394785715328062088529400178080360e+08),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 9.778173054417826368076483100902201433e+08),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.335667778588806892764139643950439733e+09),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.283635100080306980206494425043706838e+09),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 8.300616188213640626577036321085025855e+08),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.277591957076162984986406540894621482e+08),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 5.564360536834214058158565361486115932e+07),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -1.043505161612403359098596828115690596e+07),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -7.217035248223503605127967970903027314e+06),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -1.422938158797326748375799596769964430e+06),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -1.229125746200586805278634786674745210e+05),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -4.201632288615609937883545928660649813e+03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -3.690820607338480548346746717311811406e+01)
|
||||
};
|
||||
static const T Q[] =
|
||||
{
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.000000000000000000000000000000000000e+00),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 7.964877874035741452203497983642653107e+01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.808929943826193766839360018583294769e+03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 5.814524004679994110944366890912384139e+04),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 7.897794522506725610540209610337355118e+05),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 7.456339470955813675629523617440433672e+06),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 5.057818717813969772198911392875127212e+07),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.513821619536852436424913886081133209e+08),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 9.255938846873380596038513316919990776e+08),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.537077551699028079347581816919572141e+09),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 5.176769339768120752974843214652367321e+09),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 7.828722317390455845253191337207432060e+09),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 8.698864296569996402006511705803675890e+09),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 7.007803261356636409943826918468544629e+09),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 4.016564631288740308993071395104715469e+09),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.595893010619754750655947035567624730e+09),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 4.241241839120481076862742189989406856e+08),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 7.168778094393076220871007550235840858e+07),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 7.156200301360388147635052029404211109e+06),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.752130382550379886741949463587008794e+05),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 8.370574966987293592457152146806662562e+03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 4.871254714311063594080644835895740323e+01)
|
||||
};
|
||||
if(x < tools::log_max_value<T>())
|
||||
return ((tools::evaluate_rational(P, Q, T(1 / x)) + Y) * exp(-x) / sqrt(x));
|
||||
else
|
||||
{
|
||||
T ex = exp(-x / 2);
|
||||
return ((tools::evaluate_rational(P, Q, T(1 / x)) + Y) * ex / sqrt(x)) * ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T bessel_k0_imp(const T& x, const mpl::int_<0>&)
|
||||
{
|
||||
if(boost::math::tools::digits<T>() <= 24)
|
||||
return bessel_k0_imp(x, mpl::int_<24>());
|
||||
else if(boost::math::tools::digits<T>() <= 53)
|
||||
return bessel_k0_imp(x, mpl::int_<53>());
|
||||
else if(boost::math::tools::digits<T>() <= 64)
|
||||
return bessel_k0_imp(x, mpl::int_<64>());
|
||||
else if(boost::math::tools::digits<T>() <= 113)
|
||||
return bessel_k0_imp(x, mpl::int_<113>());
|
||||
BOOST_ASSERT(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T bessel_k0(const T& x)
|
||||
{
|
||||
typedef mpl::int_<
|
||||
((std::numeric_limits<T>::digits == 0) || (std::numeric_limits<T>::radix != 2)) ?
|
||||
0 :
|
||||
std::numeric_limits<T>::digits <= 24 ?
|
||||
24 :
|
||||
std::numeric_limits<T>::digits <= 53 ?
|
||||
53 :
|
||||
std::numeric_limits<T>::digits <= 64 ?
|
||||
64 :
|
||||
std::numeric_limits<T>::digits <= 113 ?
|
||||
113 : -1
|
||||
> tag_type;
|
||||
|
||||
bessel_k0_initializer<T, tag_type>::force_instantiate();
|
||||
return bessel_k0_imp(x, tag_type());
|
||||
}
|
||||
|
||||
}}} // namespaces
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif // BOOST_MATH_BESSEL_K0_HPP
|
||||
|
||||
551
code_isotrope/boost/math/special_functions/detail/bessel_k1.hpp
Executable file
551
code_isotrope/boost/math/special_functions/detail/bessel_k1.hpp
Executable file
@@ -0,0 +1,551 @@
|
||||
// Copyright (c) 2006 Xiaogang Zhang
|
||||
// Copyright (c) 2017 John Maddock
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_MATH_BESSEL_K1_HPP
|
||||
#define BOOST_MATH_BESSEL_K1_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4702) // Unreachable code (release mode only warning)
|
||||
#endif
|
||||
|
||||
#include <boost/math/tools/rational.hpp>
|
||||
#include <boost/math/tools/big_constant.hpp>
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
// Modified Bessel function of the second kind of order zero
|
||||
// minimax rational approximations on intervals, see
|
||||
// Russon and Blair, Chalk River Report AECL-3461, 1969,
|
||||
// as revised by Pavel Holoborodko in "Rational Approximations
|
||||
// for the Modified Bessel Function of the Second Kind - K0(x)
|
||||
// for Computations with Double Precision", see
|
||||
// http://www.advanpix.com/2016/01/05/rational-approximations-for-the-modified-bessel-function-of-the-second-kind-k1-for-computations-with-double-precision/
|
||||
//
|
||||
// The actual coefficients used are our own derivation (by JM)
|
||||
// since we extend to both greater and lesser precision than the
|
||||
// references above. We can also improve performance WRT to
|
||||
// Holoborodko without loss of precision.
|
||||
|
||||
namespace boost { namespace math { namespace detail{
|
||||
|
||||
template <typename T>
|
||||
T bessel_k1(const T& x);
|
||||
|
||||
template <class T, class tag>
|
||||
struct bessel_k1_initializer
|
||||
{
|
||||
struct init
|
||||
{
|
||||
init()
|
||||
{
|
||||
do_init(tag());
|
||||
}
|
||||
static void do_init(const mpl::int_<113>&)
|
||||
{
|
||||
bessel_k1(T(0.5));
|
||||
bessel_k1(T(2));
|
||||
bessel_k1(T(6));
|
||||
}
|
||||
static void do_init(const mpl::int_<64>&)
|
||||
{
|
||||
bessel_k1(T(0.5));
|
||||
bessel_k1(T(6));
|
||||
}
|
||||
template <class U>
|
||||
static void do_init(const U&) {}
|
||||
void force_instantiate()const {}
|
||||
};
|
||||
static const init initializer;
|
||||
static void force_instantiate()
|
||||
{
|
||||
initializer.force_instantiate();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class tag>
|
||||
const typename bessel_k1_initializer<T, tag>::init bessel_k1_initializer<T, tag>::initializer;
|
||||
|
||||
|
||||
template <typename T, int N>
|
||||
inline T bessel_k1_imp(const T& x, const mpl::int_<N>&)
|
||||
{
|
||||
BOOST_ASSERT(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T bessel_k1_imp(const T& x, const mpl::int_<24>&)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
if(x <= 1)
|
||||
{
|
||||
// Maximum Deviation Found: 3.090e-12
|
||||
// Expected Error Term : -3.053e-12
|
||||
// Maximum Relative Change in Control Points : 4.927e-02
|
||||
// Max Error found at float precision = Poly : 7.918347e-10
|
||||
static const T Y = 8.695471287e-02f;
|
||||
static const T P[] =
|
||||
{
|
||||
-3.621379531e-03f,
|
||||
7.131781976e-03f,
|
||||
-1.535278300e-05f
|
||||
};
|
||||
static const T Q[] =
|
||||
{
|
||||
1.000000000e+00f,
|
||||
-5.173102701e-02f,
|
||||
9.203530671e-04f
|
||||
};
|
||||
|
||||
T a = x * x / 4;
|
||||
a = ((tools::evaluate_rational(P, Q, a) + Y) * a * a + a / 2 + 1) * x / 2;
|
||||
|
||||
// Maximum Deviation Found: 3.556e-08
|
||||
// Expected Error Term : -3.541e-08
|
||||
// Maximum Relative Change in Control Points : 8.203e-02
|
||||
static const T P2[] =
|
||||
{
|
||||
-3.079657469e-01f,
|
||||
-8.537108913e-02f,
|
||||
-4.640275408e-03f,
|
||||
-1.156442414e-04f
|
||||
};
|
||||
|
||||
return tools::evaluate_polynomial(P2, T(x * x)) * x + 1 / x + log(x) * a;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Maximum Deviation Found: 3.369e-08
|
||||
// Expected Error Term : -3.227e-08
|
||||
// Maximum Relative Change in Control Points : 9.917e-02
|
||||
// Max Error found at float precision = Poly : 6.084411e-08
|
||||
static const T Y = 1.450342178f;
|
||||
static const T P[] =
|
||||
{
|
||||
-1.970280088e-01f,
|
||||
2.188747807e-02f,
|
||||
7.270394756e-01f,
|
||||
2.490678196e-01f
|
||||
};
|
||||
static const T Q[] =
|
||||
{
|
||||
1.000000000e+00f,
|
||||
2.274292882e+00f,
|
||||
9.904984851e-01f,
|
||||
4.585534549e-02f
|
||||
};
|
||||
if(x < tools::log_max_value<T>())
|
||||
return ((tools::evaluate_rational(P, Q, T(1 / x)) + Y) * exp(-x) / sqrt(x));
|
||||
else
|
||||
{
|
||||
T ex = exp(-x / 2);
|
||||
return ((tools::evaluate_rational(P, Q, T(1 / x)) + Y) * ex / sqrt(x)) * ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T bessel_k1_imp(const T& x, const mpl::int_<53>&)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
if(x <= 1)
|
||||
{
|
||||
// Maximum Deviation Found: 1.922e-17
|
||||
// Expected Error Term : 1.921e-17
|
||||
// Maximum Relative Change in Control Points : 5.287e-03
|
||||
// Max Error found at double precision = Poly : 2.004747e-17
|
||||
static const T Y = 8.69547128677368164e-02f;
|
||||
static const T P[] =
|
||||
{
|
||||
-3.62137953440350228e-03,
|
||||
7.11842087490330300e-03,
|
||||
1.00302560256614306e-05,
|
||||
1.77231085381040811e-06
|
||||
};
|
||||
static const T Q[] =
|
||||
{
|
||||
1.00000000000000000e+00,
|
||||
-4.80414794429043831e-02,
|
||||
9.85972641934416525e-04,
|
||||
-8.91196859397070326e-06
|
||||
};
|
||||
|
||||
T a = x * x / 4;
|
||||
a = ((tools::evaluate_rational(P, Q, a) + Y) * a * a + a / 2 + 1) * x / 2;
|
||||
|
||||
// Maximum Deviation Found: 4.053e-17
|
||||
// Expected Error Term : -4.053e-17
|
||||
// Maximum Relative Change in Control Points : 3.103e-04
|
||||
// Max Error found at double precision = Poly : 1.246698e-16
|
||||
|
||||
static const T P2[] =
|
||||
{
|
||||
-3.07965757829206184e-01,
|
||||
-7.80929703673074907e-02,
|
||||
-2.70619343754051620e-03,
|
||||
-2.49549522229072008e-05
|
||||
};
|
||||
static const T Q2[] =
|
||||
{
|
||||
1.00000000000000000e+00,
|
||||
-2.36316836412163098e-02,
|
||||
2.64524577525962719e-04,
|
||||
-1.49749618004162787e-06
|
||||
};
|
||||
|
||||
return tools::evaluate_rational(P2, Q2, T(x * x)) * x + 1 / x + log(x) * a;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Maximum Deviation Found: 8.883e-17
|
||||
// Expected Error Term : -1.641e-17
|
||||
// Maximum Relative Change in Control Points : 2.786e-01
|
||||
// Max Error found at double precision = Poly : 1.258798e-16
|
||||
|
||||
static const T Y = 1.45034217834472656f;
|
||||
static const T P[] =
|
||||
{
|
||||
-1.97028041029226295e-01,
|
||||
-2.32408961548087617e+00,
|
||||
-7.98269784507699938e+00,
|
||||
-2.39968410774221632e+00,
|
||||
3.28314043780858713e+01,
|
||||
5.67713761158496058e+01,
|
||||
3.30907788466509823e+01,
|
||||
6.62582288933739787e+00,
|
||||
3.08851840645286691e-01
|
||||
};
|
||||
static const T Q[] =
|
||||
{
|
||||
1.00000000000000000e+00,
|
||||
1.41811409298826118e+01,
|
||||
7.35979466317556420e+01,
|
||||
1.77821793937080859e+02,
|
||||
2.11014501598705982e+02,
|
||||
1.19425262951064454e+02,
|
||||
2.88448064302447607e+01,
|
||||
2.27912927104139732e+00,
|
||||
2.50358186953478678e-02
|
||||
};
|
||||
if(x < tools::log_max_value<T>())
|
||||
return ((tools::evaluate_rational(P, Q, T(1 / x)) + Y) * exp(-x) / sqrt(x));
|
||||
else
|
||||
{
|
||||
T ex = exp(-x / 2);
|
||||
return ((tools::evaluate_rational(P, Q, T(1 / x)) + Y) * ex / sqrt(x)) * ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T bessel_k1_imp(const T& x, const mpl::int_<64>&)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
if(x <= 1)
|
||||
{
|
||||
// Maximum Deviation Found: 5.549e-23
|
||||
// Expected Error Term : -5.548e-23
|
||||
// Maximum Relative Change in Control Points : 2.002e-03
|
||||
// Max Error found at float80 precision = Poly : 9.352785e-22
|
||||
static const T Y = 8.695471286773681640625e-02f;
|
||||
static const T P[] =
|
||||
{
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -3.621379534403483072861e-03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 7.102135866103952705932e-03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 4.167545240236717601167e-05),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 2.537484002571894870830e-06),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 6.603228256820000135990e-09)
|
||||
};
|
||||
static const T Q[] =
|
||||
{
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.000000000000000000000e+00),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -4.354457194045068370363e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 8.709137201220209072820e-04),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -9.676151796359590545143e-06),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 5.162715192766245311659e-08)
|
||||
};
|
||||
|
||||
T a = x * x / 4;
|
||||
a = ((tools::evaluate_rational(P, Q, a) + Y) * a * a + a / 2 + 1) * x / 2;
|
||||
|
||||
// Maximum Deviation Found: 1.995e-23
|
||||
// Expected Error Term : 1.995e-23
|
||||
// Maximum Relative Change in Control Points : 8.174e-04
|
||||
// Max Error found at float80 precision = Poly : 4.137325e-20
|
||||
static const T P2[] =
|
||||
{
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -3.079657578292062244054e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -7.963049154965966503231e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -3.103277523735639924895e-03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -4.023052834702215699504e-05),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -1.719459155018493821839e-07)
|
||||
};
|
||||
static const T Q2[] =
|
||||
{
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.000000000000000000000e+00),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -1.863917670410152669768e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.699367098849735298090e-04),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -9.309358790546076298429e-07),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 2.708893480271612711933e-09)
|
||||
};
|
||||
|
||||
return tools::evaluate_rational(P2, Q2, T(x * x)) * x + 1 / x + log(x) * a;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Maximum Deviation Found: 9.785e-20
|
||||
// Expected Error Term : -3.302e-21
|
||||
// Maximum Relative Change in Control Points : 3.432e-01
|
||||
// Max Error found at float80 precision = Poly : 1.083755e-19
|
||||
static const T Y = 1.450342178344726562500e+00f;
|
||||
static const T P[] =
|
||||
{
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -1.970280410292263112917e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -4.058564803062959169322e+00),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -3.036658174194917777473e+01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -9.576825392332820142173e+01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -6.706969489248020941949e+01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 3.264572499406168221382e+02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 8.584972047303151034100e+02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 8.422082733280017909550e+02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 3.738005441471368178383e+02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 7.016938390144121276609e+01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 4.319614662598089438939e+00),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 3.710715864316521856193e-02)
|
||||
};
|
||||
static const T Q[] =
|
||||
{
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.000000000000000000000e+00),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 2.298433045824439052398e+01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 2.082047745067709230037e+02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 9.662367854250262046592e+02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 2.504148628460454004686e+03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 3.712730364911389908905e+03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 3.108002081150068641112e+03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.400149940532448553143e+03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 3.083303048095846226299e+02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 2.748706060530351833346e+01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 6.321900849331506946977e-01),
|
||||
};
|
||||
if(x < tools::log_max_value<T>())
|
||||
return ((tools::evaluate_polynomial(P, T(1 / x)) / tools::evaluate_polynomial(Q, T(1 / x)) + Y) * exp(-x) / sqrt(x));
|
||||
else
|
||||
{
|
||||
T ex = exp(-x / 2);
|
||||
return ((tools::evaluate_polynomial(P, T(1 / x)) / tools::evaluate_polynomial(Q, T(1 / x)) + Y) * ex / sqrt(x)) * ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T bessel_k1_imp(const T& x, const mpl::int_<113>&)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
if(x <= 1)
|
||||
{
|
||||
// Maximum Deviation Found: 7.120e-35
|
||||
// Expected Error Term : -7.119e-35
|
||||
// Maximum Relative Change in Control Points : 1.207e-03
|
||||
// Max Error found at float128 precision = Poly : 7.143688e-35
|
||||
static const T Y = 8.695471286773681640625000000000000000e-02f;
|
||||
static const T P[] =
|
||||
{
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -3.621379534403483072916666666666595475e-03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 7.074117676930975433219826471336547627e-03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 9.631337631362776369069668419033041661e-05),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.468935967870048731821071646104412775e-06),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.956705020559599861444492614737168261e-08),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.347140307321161346703214099534250263e-10),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 5.569608494081482873946791086435679661e-13)
|
||||
};
|
||||
static const T Q[] =
|
||||
{
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.000000000000000000000000000000000000e+00),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -3.580768910152105375615558920428350204e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 6.197467671701485365363068445534557369e-04),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -6.707466533308630411966030561446666237e-06),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 4.846687802282250112624373388491123527e-08),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -2.248493131151981569517383040323900343e-10),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 5.319279786372775264555728921709381080e-13)
|
||||
};
|
||||
|
||||
T a = x * x / 4;
|
||||
a = ((tools::evaluate_rational(P, Q, a) + Y) * a * a + a / 2 + 1) * x / 2;
|
||||
|
||||
// Maximum Deviation Found: 4.473e-37
|
||||
// Expected Error Term : 4.473e-37
|
||||
// Maximum Relative Change in Control Points : 8.550e-04
|
||||
// Max Error found at float128 precision = Poly : 8.167701e-35
|
||||
static const T P2[] =
|
||||
{
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -3.079657578292062244053600156878870690e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -8.133183745732467770755578848987414875e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -3.548968792764174773125420229299431951e-03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -5.886125468718182876076972186152445490e-05),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -4.506712111733707245745396404449639865e-07),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -1.632502325880313239698965376754406011e-09),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -2.311973065898784812266544485665624227e-12)
|
||||
};
|
||||
static const T Q2[] =
|
||||
{
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.000000000000000000000000000000000000e+00),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -1.311471216733781016657962995723287450e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 8.571876054797365417068164018709472969e-05),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -3.630181215268238731442496851497901293e-07),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.070176111227805048604885986867484807e-09),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -2.129046580769872602793220056461084761e-12),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.294906469421390890762001971790074432e-15)
|
||||
};
|
||||
|
||||
return tools::evaluate_rational(P2, Q2, T(x * x)) * x + 1 / x + log(x) * a;
|
||||
}
|
||||
else if(x < 4)
|
||||
{
|
||||
// Max error in interpolated form: 5.307e-37
|
||||
// Max Error found at float128 precision = Poly: 7.087862e-35
|
||||
static const T Y = 1.5023040771484375f;
|
||||
static const T P[] =
|
||||
{
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -2.489899398329369710528254347931380044e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -6.819080211203854781858815596508456873e+00),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -7.599915699069767382647695624952723034e+01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -4.450211910821295507926582231071300718e+02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -1.451374687870925175794150513723956533e+03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -2.405805746895098802803503988539098226e+03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -5.638808326778389656403861103277220518e+02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 5.513958744081268456191778822780865708e+03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.121301640926540743072258116122834804e+04),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.080094900175649541266613109971296190e+04),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 5.896531083639613332407534434915552429e+03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.856602122319645694042555107114028437e+03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.237121918853145421414003823957537419e+02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.842072954561323076230238664623893504e+01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.039705646510167437971862966128055524e+00),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.008418100718254816100425022904039530e-02)
|
||||
};
|
||||
static const T Q[] =
|
||||
{
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.000000000000000000000000000000000000e+00),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.927456835239137986889227412815459529e+01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.598985593265577043711382994516531273e+02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.449897377085510281395819892689690579e+03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.025555887684561913263090023158085327e+04),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.774140447181062463181892531100679195e+04),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 4.962055507843204417243602332246120418e+04),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 5.908269326976180183216954452196772931e+04),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 4.655160454422016855911700790722577942e+04),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.383586885019548163464418964577684608e+04),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 7.679920375586960324298491662159976419e+03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.478586421028842906987799049804565008e+03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.565384974896746094224942654383537090e+02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 7.902617937084010911005732488607114511e+00),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.429293010387921526110949911029094926e-01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.880342607911083143560111853491047663e-04)
|
||||
};
|
||||
return ((tools::evaluate_polynomial(P, T(1 / x)) / tools::evaluate_polynomial(Q, T(1 / x)) + Y) * exp(-x) / sqrt(x));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Maximum Deviation Found: 4.359e-37
|
||||
// Expected Error Term : -6.565e-40
|
||||
// Maximum Relative Change in Control Points : 1.880e-01
|
||||
// Max Error found at float128 precision = Poly : 2.943572e-35
|
||||
static const T Y = 1.308816909790039062500000000000000000f;
|
||||
static const T P[] =
|
||||
{
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -5.550277247453881129211735759447737350e-02),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -3.485883080219574328217554864956175929e+00),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -8.903760658131484239300875153154881958e+01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -1.144813672213626237418235110712293337e+03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -6.498400501156131446691826557494158173e+03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.573531831870363502604119835922166116e+04),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 5.417416550054632009958262596048841154e+05),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 4.271266450613557412825896604269130661e+06),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.898386013314389952534433455681107783e+07),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 5.353798784656436259250791761023512750e+07),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 9.839619195427352438957774052763490067e+07),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.169246368651532232388152442538005637e+08),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 8.696368884166831199967845883371116431e+07),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.810226630422736458064005843327500169e+07),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 8.854996610560406127438950635716757614e+06),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 8.981057433937398731355768088809437625e+05),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.519440069856232098711793483639792952e+04)
|
||||
};
|
||||
static const T Q[] =
|
||||
{
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.000000000000000000000000000000000000e+00),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 7.127348248283623146544565916604103560e+01),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.205092684176906740104488180754982065e+03),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.911249195069050636298346469740075758e+04),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 4.426103406579046249654548481377792614e+05),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.365861555422488771286500241966208541e+06),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.765377714160383676864913709252529840e+07),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 6.453822726931857253365138260720815246e+07),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.643207885048369990391975749439783892e+08),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.882540678243694621895816336640877878e+08),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.410120808992380266174106812005338148e+08),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.628138016559335882019310900426773027e+08),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.250794693811010646965360198541047961e+08),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.378723408195485594610593014072950078e+07),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 4.488253856312453816451380319061865560e+06),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.202167197882689873967723350537104582e+05),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.673233230356966539460728211412989843e+03)
|
||||
};
|
||||
if(x < tools::log_max_value<T>())
|
||||
return ((tools::evaluate_polynomial(P, T(1 / x)) / tools::evaluate_polynomial(Q, T(1 / x)) + Y) * exp(-x) / sqrt(x));
|
||||
else
|
||||
{
|
||||
T ex = exp(-x / 2);
|
||||
return ((tools::evaluate_polynomial(P, T(1 / x)) / tools::evaluate_polynomial(Q, T(1 / x)) + Y) * ex / sqrt(x)) * ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T bessel_k1_imp(const T& x, const mpl::int_<0>&)
|
||||
{
|
||||
if(boost::math::tools::digits<T>() <= 24)
|
||||
return bessel_k1_imp(x, mpl::int_<24>());
|
||||
else if(boost::math::tools::digits<T>() <= 53)
|
||||
return bessel_k1_imp(x, mpl::int_<53>());
|
||||
else if(boost::math::tools::digits<T>() <= 64)
|
||||
return bessel_k1_imp(x, mpl::int_<64>());
|
||||
else if(boost::math::tools::digits<T>() <= 113)
|
||||
return bessel_k1_imp(x, mpl::int_<113>());
|
||||
BOOST_ASSERT(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T bessel_k1(const T& x)
|
||||
{
|
||||
typedef mpl::int_<
|
||||
((std::numeric_limits<T>::digits == 0) || (std::numeric_limits<T>::radix != 2)) ?
|
||||
0 :
|
||||
std::numeric_limits<T>::digits <= 24 ?
|
||||
24 :
|
||||
std::numeric_limits<T>::digits <= 53 ?
|
||||
53 :
|
||||
std::numeric_limits<T>::digits <= 64 ?
|
||||
64 :
|
||||
std::numeric_limits<T>::digits <= 113 ?
|
||||
113 : -1
|
||||
> tag_type;
|
||||
|
||||
bessel_k1_initializer<T, tag_type>::force_instantiate();
|
||||
return bessel_k1_imp(x, tag_type());
|
||||
}
|
||||
|
||||
}}} // namespaces
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif // BOOST_MATH_BESSEL_K1_HPP
|
||||
|
||||
86
code_isotrope/boost/math/special_functions/detail/bessel_kn.hpp
Executable file
86
code_isotrope/boost/math/special_functions/detail/bessel_kn.hpp
Executable file
@@ -0,0 +1,86 @@
|
||||
// Copyright (c) 2006 Xiaogang Zhang
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_MATH_BESSEL_KN_HPP
|
||||
#define BOOST_MATH_BESSEL_KN_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/special_functions/detail/bessel_k0.hpp>
|
||||
#include <boost/math/special_functions/detail/bessel_k1.hpp>
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
|
||||
// Modified Bessel function of the second kind of integer order
|
||||
// K_n(z) is the dominant solution, forward recurrence always OK (though unstable)
|
||||
|
||||
namespace boost { namespace math { namespace detail{
|
||||
|
||||
template <typename T, typename Policy>
|
||||
T bessel_kn(int n, T x, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
T value, current, prev;
|
||||
|
||||
using namespace boost::math::tools;
|
||||
|
||||
static const char* function = "boost::math::bessel_kn<%1%>(%1%,%1%)";
|
||||
|
||||
if (x < 0)
|
||||
{
|
||||
return policies::raise_domain_error<T>(function,
|
||||
"Got x = %1%, but argument x must be non-negative, complex number result not supported.", x, pol);
|
||||
}
|
||||
if (x == 0)
|
||||
{
|
||||
return policies::raise_overflow_error<T>(function, 0, pol);
|
||||
}
|
||||
|
||||
if (n < 0)
|
||||
{
|
||||
n = -n; // K_{-n}(z) = K_n(z)
|
||||
}
|
||||
if (n == 0)
|
||||
{
|
||||
value = bessel_k0(x);
|
||||
}
|
||||
else if (n == 1)
|
||||
{
|
||||
value = bessel_k1(x);
|
||||
}
|
||||
else
|
||||
{
|
||||
prev = bessel_k0(x);
|
||||
current = bessel_k1(x);
|
||||
int k = 1;
|
||||
BOOST_ASSERT(k < n);
|
||||
T scale = 1;
|
||||
do
|
||||
{
|
||||
T fact = 2 * k / x;
|
||||
if((tools::max_value<T>() - fabs(prev)) / fact < fabs(current))
|
||||
{
|
||||
scale /= current;
|
||||
prev /= current;
|
||||
current = 1;
|
||||
}
|
||||
value = fact * current + prev;
|
||||
prev = current;
|
||||
current = value;
|
||||
++k;
|
||||
}
|
||||
while(k < n);
|
||||
if(tools::max_value<T>() * scale < fabs(value))
|
||||
return sign(scale) * sign(value) * policies::raise_overflow_error<T>(function, 0, pol);
|
||||
value /= scale;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
}}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_BESSEL_KN_HPP
|
||||
|
||||
230
code_isotrope/boost/math/special_functions/detail/bessel_y0.hpp
Executable file
230
code_isotrope/boost/math/special_functions/detail/bessel_y0.hpp
Executable file
@@ -0,0 +1,230 @@
|
||||
// Copyright (c) 2006 Xiaogang Zhang
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_MATH_BESSEL_Y0_HPP
|
||||
#define BOOST_MATH_BESSEL_Y0_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4702) // Unreachable code (release mode only warning)
|
||||
#endif
|
||||
|
||||
#include <boost/math/special_functions/detail/bessel_j0.hpp>
|
||||
#include <boost/math/constants/constants.hpp>
|
||||
#include <boost/math/tools/rational.hpp>
|
||||
#include <boost/math/tools/big_constant.hpp>
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
// Bessel function of the second kind of order zero
|
||||
// x <= 8, minimax rational approximations on root-bracketing intervals
|
||||
// x > 8, Hankel asymptotic expansion in Hart, Computer Approximations, 1968
|
||||
|
||||
namespace boost { namespace math { namespace detail{
|
||||
|
||||
template <typename T, typename Policy>
|
||||
T bessel_y0(T x, const Policy&);
|
||||
|
||||
template <class T, class Policy>
|
||||
struct bessel_y0_initializer
|
||||
{
|
||||
struct init
|
||||
{
|
||||
init()
|
||||
{
|
||||
do_init();
|
||||
}
|
||||
static void do_init()
|
||||
{
|
||||
bessel_y0(T(1), Policy());
|
||||
}
|
||||
void force_instantiate()const{}
|
||||
};
|
||||
static const init initializer;
|
||||
static void force_instantiate()
|
||||
{
|
||||
initializer.force_instantiate();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class Policy>
|
||||
const typename bessel_y0_initializer<T, Policy>::init bessel_y0_initializer<T, Policy>::initializer;
|
||||
|
||||
template <typename T, typename Policy>
|
||||
T bessel_y0(T x, const Policy& pol)
|
||||
{
|
||||
bessel_y0_initializer<T, Policy>::force_instantiate();
|
||||
|
||||
static const T P1[] = {
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0723538782003176831e+11)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -8.3716255451260504098e+09)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.0422274357376619816e+08)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -2.1287548474401797963e+06)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0102532948020907590e+04)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.8402381979244993524e+01)),
|
||||
};
|
||||
static const T Q1[] = {
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 5.8873865738997033405e+11)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 8.1617187777290363573e+09)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 5.5662956624278251596e+07)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.3889393209447253406e+05)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 6.6475986689240190091e+02)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0)),
|
||||
};
|
||||
static const T P2[] = {
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -2.2213976967566192242e+13)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -5.5107435206722644429e+11)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.3600098638603061642e+10)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -6.9590439394619619534e+08)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.6905288611678631510e+06)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.4566865832663635920e+04)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.7427031242901594547e+01)),
|
||||
};
|
||||
static const T Q2[] = {
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.3386146580707264428e+14)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 5.4266824419412347550e+12)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.4015103849971240096e+10)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.3960202770986831075e+08)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.0669982352539552018e+05)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 8.3030857612070288823e+02)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0)),
|
||||
};
|
||||
static const T P3[] = {
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -8.0728726905150210443e+15)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 6.7016641869173237784e+14)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.2829912364088687306e+11)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.9363051266772083678e+11)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.1958827170518100757e+09)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.0085539923498211426e+07)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.1363534169313901632e+04)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.7439661319197499338e+01)),
|
||||
};
|
||||
static const T Q3[] = {
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.4563724628846457519e+17)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.9272425569640309819e+15)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.2598377924042897629e+13)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 8.6926121104209825246e+10)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.4727219475672302327e+08)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 5.3924739209768057030e+05)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 8.7903362168128450017e+02)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0)),
|
||||
};
|
||||
static const T PC[] = {
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.2779090197304684302e+04)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.1345386639580765797e+04)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.1170523380864944322e+04)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.4806486443249270347e+03)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.5376201909008354296e+02)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 8.8961548424210455236e-01)),
|
||||
};
|
||||
static const T QC[] = {
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.2779090197304684318e+04)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.1370412495510416640e+04)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.1215350561880115730e+04)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.5028735138235608207e+03)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.5711159858080893649e+02)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0)),
|
||||
};
|
||||
static const T PS[] = {
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -8.9226600200800094098e+01)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.8591953644342993800e+02)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.1183429920482737611e+02)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -2.2300261666214198472e+01)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.2441026745835638459e+00)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -8.8033303048680751817e-03)),
|
||||
};
|
||||
static const T QS[] = {
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 5.7105024128512061905e+03)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.1951131543434613647e+04)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 7.2642780169211018836e+03)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.4887231232283756582e+03)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 9.0593769594993125859e+01)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0)),
|
||||
};
|
||||
static const T x1 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 8.9357696627916752158e-01)),
|
||||
x2 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.9576784193148578684e+00)),
|
||||
x3 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 7.0860510603017726976e+00)),
|
||||
x11 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.280e+02)),
|
||||
x12 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.9519662791675215849e-03)),
|
||||
x21 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0130e+03)),
|
||||
x22 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 6.4716931485786837568e-04)),
|
||||
x31 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.8140e+03)),
|
||||
x32 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.1356030177269762362e-04))
|
||||
;
|
||||
T value, factor, r, rc, rs;
|
||||
|
||||
BOOST_MATH_STD_USING
|
||||
using namespace boost::math::tools;
|
||||
using namespace boost::math::constants;
|
||||
|
||||
static const char* function = "boost::math::bessel_y0<%1%>(%1%,%1%)";
|
||||
|
||||
if (x < 0)
|
||||
{
|
||||
return policies::raise_domain_error<T>(function,
|
||||
"Got x = %1% but x must be non-negative, complex result not supported.", x, pol);
|
||||
}
|
||||
if (x == 0)
|
||||
{
|
||||
return -policies::raise_overflow_error<T>(function, 0, pol);
|
||||
}
|
||||
if (x <= 3) // x in (0, 3]
|
||||
{
|
||||
T y = x * x;
|
||||
T z = 2 * log(x/x1) * bessel_j0(x) / pi<T>();
|
||||
r = evaluate_rational(P1, Q1, y);
|
||||
factor = (x + x1) * ((x - x11/256) - x12);
|
||||
value = z + factor * r;
|
||||
}
|
||||
else if (x <= 5.5f) // x in (3, 5.5]
|
||||
{
|
||||
T y = x * x;
|
||||
T z = 2 * log(x/x2) * bessel_j0(x) / pi<T>();
|
||||
r = evaluate_rational(P2, Q2, y);
|
||||
factor = (x + x2) * ((x - x21/256) - x22);
|
||||
value = z + factor * r;
|
||||
}
|
||||
else if (x <= 8) // x in (5.5, 8]
|
||||
{
|
||||
T y = x * x;
|
||||
T z = 2 * log(x/x3) * bessel_j0(x) / pi<T>();
|
||||
r = evaluate_rational(P3, Q3, y);
|
||||
factor = (x + x3) * ((x - x31/256) - x32);
|
||||
value = z + factor * r;
|
||||
}
|
||||
else // x in (8, \infty)
|
||||
{
|
||||
T y = 8 / x;
|
||||
T y2 = y * y;
|
||||
rc = evaluate_rational(PC, QC, y2);
|
||||
rs = evaluate_rational(PS, QS, y2);
|
||||
factor = constants::one_div_root_pi<T>() / sqrt(x);
|
||||
//
|
||||
// The following code is really just:
|
||||
//
|
||||
// T z = x - 0.25f * pi<T>();
|
||||
// value = factor * (rc * sin(z) + y * rs * cos(z));
|
||||
//
|
||||
// But using the sin/cos addition formulae and constant values for
|
||||
// sin/cos of PI/4 which then cancel part of the "factor" term as they're all
|
||||
// 1 / sqrt(2):
|
||||
//
|
||||
T sx = sin(x);
|
||||
T cx = cos(x);
|
||||
value = factor * (rc * (sx - cx) + y * rs * (cx + sx));
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
}}} // namespaces
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif // BOOST_MATH_BESSEL_Y0_HPP
|
||||
|
||||
202
code_isotrope/boost/math/special_functions/detail/bessel_y1.hpp
Executable file
202
code_isotrope/boost/math/special_functions/detail/bessel_y1.hpp
Executable file
@@ -0,0 +1,202 @@
|
||||
// Copyright (c) 2006 Xiaogang Zhang
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_MATH_BESSEL_Y1_HPP
|
||||
#define BOOST_MATH_BESSEL_Y1_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4702) // Unreachable code (release mode only warning)
|
||||
#endif
|
||||
|
||||
#include <boost/math/special_functions/detail/bessel_j1.hpp>
|
||||
#include <boost/math/constants/constants.hpp>
|
||||
#include <boost/math/tools/rational.hpp>
|
||||
#include <boost/math/tools/big_constant.hpp>
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
// Bessel function of the second kind of order one
|
||||
// x <= 8, minimax rational approximations on root-bracketing intervals
|
||||
// x > 8, Hankel asymptotic expansion in Hart, Computer Approximations, 1968
|
||||
|
||||
namespace boost { namespace math { namespace detail{
|
||||
|
||||
template <typename T, typename Policy>
|
||||
T bessel_y1(T x, const Policy&);
|
||||
|
||||
template <class T, class Policy>
|
||||
struct bessel_y1_initializer
|
||||
{
|
||||
struct init
|
||||
{
|
||||
init()
|
||||
{
|
||||
do_init();
|
||||
}
|
||||
static void do_init()
|
||||
{
|
||||
bessel_y1(T(1), Policy());
|
||||
}
|
||||
void force_instantiate()const{}
|
||||
};
|
||||
static const init initializer;
|
||||
static void force_instantiate()
|
||||
{
|
||||
initializer.force_instantiate();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class Policy>
|
||||
const typename bessel_y1_initializer<T, Policy>::init bessel_y1_initializer<T, Policy>::initializer;
|
||||
|
||||
template <typename T, typename Policy>
|
||||
T bessel_y1(T x, const Policy& pol)
|
||||
{
|
||||
bessel_y1_initializer<T, Policy>::force_instantiate();
|
||||
|
||||
static const T P1[] = {
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.0535726612579544093e+13)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 5.4708611716525426053e+12)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -3.7595974497819597599e+11)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 7.2144548214502560419e+09)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -5.9157479997408395984e+07)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.2157953222280260820e+05)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -3.1714424660046133456e+02)),
|
||||
};
|
||||
static const T Q1[] = {
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.0737873921079286084e+14)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.1272286200406461981e+12)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.7800352738690585613e+10)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.2250435122182963220e+08)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.8136470753052572164e+05)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 8.2079908168393867438e+02)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0)),
|
||||
};
|
||||
static const T P2[] = {
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.1514276357909013326e+19)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -5.6808094574724204577e+18)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -2.3638408497043134724e+16)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.0686275289804744814e+15)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -5.9530713129741981618e+13)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.7453673962438488783e+11)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.1957961912070617006e+09)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.9153806858264202986e+06)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.2337180442012953128e+03)),
|
||||
};
|
||||
static const T Q2[] = {
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 5.3321844313316185697e+20)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 5.6968198822857178911e+18)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.0837179548112881950e+16)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.1187010065856971027e+14)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.0221766852960403645e+11)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 6.3550318087088919566e+08)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0453748201934079734e+06)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.2855164849321609336e+03)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0)),
|
||||
};
|
||||
static const T PC[] = {
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -4.4357578167941278571e+06)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -9.9422465050776411957e+06)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -6.6033732483649391093e+06)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.5235293511811373833e+06)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.0982405543459346727e+05)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.6116166443246101165e+03)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.0)),
|
||||
};
|
||||
static const T QC[] = {
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -4.4357578167941278568e+06)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -9.9341243899345856590e+06)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -6.5853394797230870728e+06)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.5118095066341608816e+06)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.0726385991103820119e+05)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.4550094401904961825e+03)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0)),
|
||||
};
|
||||
static const T PS[] = {
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.3220913409857223519e+04)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 8.5145160675335701966e+04)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 6.6178836581270835179e+04)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.8494262873223866797e+04)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.7063754290207680021e+03)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.5265133846636032186e+01)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.0)),
|
||||
};
|
||||
static const T QS[] = {
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 7.0871281941028743574e+05)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.8194580422439972989e+06)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.4194606696037208929e+06)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.0029443582266975117e+05)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.7890229745772202641e+04)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 8.6383677696049909675e+02)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0)),
|
||||
};
|
||||
static const T x1 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.1971413260310170351e+00)),
|
||||
x2 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 5.4296810407941351328e+00)),
|
||||
x11 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 5.620e+02)),
|
||||
x12 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.8288260310170351490e-03)),
|
||||
x21 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.3900e+03)),
|
||||
x22 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -6.4592058648672279948e-06))
|
||||
;
|
||||
T value, factor, r, rc, rs;
|
||||
|
||||
BOOST_MATH_STD_USING
|
||||
using namespace boost::math::tools;
|
||||
using namespace boost::math::constants;
|
||||
|
||||
if (x <= 0)
|
||||
{
|
||||
return policies::raise_domain_error<T>("bost::math::bessel_y1<%1%>(%1%,%1%)",
|
||||
"Got x == %1%, but x must be > 0, complex result not supported.", x, pol);
|
||||
}
|
||||
if (x <= 4) // x in (0, 4]
|
||||
{
|
||||
T y = x * x;
|
||||
T z = 2 * log(x/x1) * bessel_j1(x) / pi<T>();
|
||||
r = evaluate_rational(P1, Q1, y);
|
||||
factor = (x + x1) * ((x - x11/256) - x12) / x;
|
||||
value = z + factor * r;
|
||||
}
|
||||
else if (x <= 8) // x in (4, 8]
|
||||
{
|
||||
T y = x * x;
|
||||
T z = 2 * log(x/x2) * bessel_j1(x) / pi<T>();
|
||||
r = evaluate_rational(P2, Q2, y);
|
||||
factor = (x + x2) * ((x - x21/256) - x22) / x;
|
||||
value = z + factor * r;
|
||||
}
|
||||
else // x in (8, \infty)
|
||||
{
|
||||
T y = 8 / x;
|
||||
T y2 = y * y;
|
||||
rc = evaluate_rational(PC, QC, y2);
|
||||
rs = evaluate_rational(PS, QS, y2);
|
||||
factor = 1 / (sqrt(x) * root_pi<T>());
|
||||
//
|
||||
// This code is really just:
|
||||
//
|
||||
// T z = x - 0.75f * pi<T>();
|
||||
// value = factor * (rc * sin(z) + y * rs * cos(z));
|
||||
//
|
||||
// But using the sin/cos addition rules, plus constants for sin/cos of 3PI/4
|
||||
// which then cancel out with corresponding terms in "factor".
|
||||
//
|
||||
T sx = sin(x);
|
||||
T cx = cos(x);
|
||||
value = factor * (y * rs * (sx - cx) - rc * (sx + cx));
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
}}} // namespaces
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif // BOOST_MATH_BESSEL_Y1_HPP
|
||||
|
||||
112
code_isotrope/boost/math/special_functions/detail/bessel_yn.hpp
Executable file
112
code_isotrope/boost/math/special_functions/detail/bessel_yn.hpp
Executable file
@@ -0,0 +1,112 @@
|
||||
// Copyright (c) 2006 Xiaogang Zhang
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_MATH_BESSEL_YN_HPP
|
||||
#define BOOST_MATH_BESSEL_YN_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/special_functions/detail/bessel_y0.hpp>
|
||||
#include <boost/math/special_functions/detail/bessel_y1.hpp>
|
||||
#include <boost/math/special_functions/detail/bessel_jy_series.hpp>
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
|
||||
// Bessel function of the second kind of integer order
|
||||
// Y_n(z) is the dominant solution, forward recurrence always OK (though unstable)
|
||||
|
||||
namespace boost { namespace math { namespace detail{
|
||||
|
||||
template <typename T, typename Policy>
|
||||
T bessel_yn(int n, T x, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
T value, factor, current, prev;
|
||||
|
||||
using namespace boost::math::tools;
|
||||
|
||||
static const char* function = "boost::math::bessel_yn<%1%>(%1%,%1%)";
|
||||
|
||||
if ((x == 0) && (n == 0))
|
||||
{
|
||||
return -policies::raise_overflow_error<T>(function, 0, pol);
|
||||
}
|
||||
if (x <= 0)
|
||||
{
|
||||
return policies::raise_domain_error<T>(function,
|
||||
"Got x = %1%, but x must be > 0, complex result not supported.", x, pol);
|
||||
}
|
||||
|
||||
//
|
||||
// Reflection comes first:
|
||||
//
|
||||
if (n < 0)
|
||||
{
|
||||
factor = static_cast<T>((n & 0x1) ? -1 : 1); // Y_{-n}(z) = (-1)^n Y_n(z)
|
||||
n = -n;
|
||||
}
|
||||
else
|
||||
{
|
||||
factor = 1;
|
||||
}
|
||||
if(x < policies::get_epsilon<T, Policy>())
|
||||
{
|
||||
T scale = 1;
|
||||
value = bessel_yn_small_z(n, x, &scale, pol);
|
||||
if(tools::max_value<T>() * fabs(scale) < fabs(value))
|
||||
return boost::math::sign(scale) * boost::math::sign(value) * policies::raise_overflow_error<T>(function, 0, pol);
|
||||
value /= scale;
|
||||
}
|
||||
else if(asymptotic_bessel_large_x_limit(n, x))
|
||||
{
|
||||
value = factor * asymptotic_bessel_y_large_x_2(static_cast<T>(abs(n)), x);
|
||||
}
|
||||
else if (n == 0)
|
||||
{
|
||||
value = bessel_y0(x, pol);
|
||||
}
|
||||
else if (n == 1)
|
||||
{
|
||||
value = factor * bessel_y1(x, pol);
|
||||
}
|
||||
else
|
||||
{
|
||||
prev = bessel_y0(x, pol);
|
||||
current = bessel_y1(x, pol);
|
||||
int k = 1;
|
||||
BOOST_ASSERT(k < n);
|
||||
policies::check_series_iterations<T>("boost::math::bessel_y_n<%1%>(%1%,%1%)", n, pol);
|
||||
T mult = 2 * k / x;
|
||||
value = mult * current - prev;
|
||||
prev = current;
|
||||
current = value;
|
||||
++k;
|
||||
if((mult > 1) && (fabs(current) > 1))
|
||||
{
|
||||
prev /= current;
|
||||
factor /= current;
|
||||
value /= current;
|
||||
current = 1;
|
||||
}
|
||||
while(k < n)
|
||||
{
|
||||
mult = 2 * k / x;
|
||||
value = mult * current - prev;
|
||||
prev = current;
|
||||
current = value;
|
||||
++k;
|
||||
}
|
||||
if(fabs(tools::max_value<T>() * factor) < fabs(value))
|
||||
return sign(value) * sign(factor) * policies::raise_overflow_error<T>(function, 0, pol);
|
||||
value /= factor;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
}}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_BESSEL_YN_HPP
|
||||
|
||||
549
code_isotrope/boost/math/special_functions/detail/erf_inv.hpp
Executable file
549
code_isotrope/boost/math/special_functions/detail/erf_inv.hpp
Executable file
@@ -0,0 +1,549 @@
|
||||
// (C) Copyright John Maddock 2006.
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_MATH_SF_ERF_INV_HPP
|
||||
#define BOOST_MATH_SF_ERF_INV_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4127) // Conditional expression is constant
|
||||
#pragma warning(disable:4702) // Unreachable code: optimization warning
|
||||
#endif
|
||||
|
||||
namespace boost{ namespace math{
|
||||
|
||||
namespace detail{
|
||||
//
|
||||
// The inverse erf and erfc functions share a common implementation,
|
||||
// this version is for 80-bit long double's and smaller:
|
||||
//
|
||||
template <class T, class Policy>
|
||||
T erf_inv_imp(const T& p, const T& q, const Policy&, const boost::mpl::int_<64>*)
|
||||
{
|
||||
BOOST_MATH_STD_USING // for ADL of std names.
|
||||
|
||||
T result = 0;
|
||||
|
||||
if(p <= 0.5)
|
||||
{
|
||||
//
|
||||
// Evaluate inverse erf using the rational approximation:
|
||||
//
|
||||
// x = p(p+10)(Y+R(p))
|
||||
//
|
||||
// Where Y is a constant, and R(p) is optimised for a low
|
||||
// absolute error compared to |Y|.
|
||||
//
|
||||
// double: Max error found: 2.001849e-18
|
||||
// long double: Max error found: 1.017064e-20
|
||||
// Maximum Deviation Found (actual error term at infinite precision) 8.030e-21
|
||||
//
|
||||
static const float Y = 0.0891314744949340820313f;
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.000508781949658280665617),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.00836874819741736770379),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.0334806625409744615033),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.0126926147662974029034),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.0365637971411762664006),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.0219878681111168899165),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.00822687874676915743155),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.00538772965071242932965)
|
||||
};
|
||||
static const T Q[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.970005043303290640362),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -1.56574558234175846809),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.56221558398423026363),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.662328840472002992063),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.71228902341542847553),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.0527396382340099713954),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.0795283687341571680018),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.00233393759374190016776),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.000886216390456424707504)
|
||||
};
|
||||
T g = p * (p + 10);
|
||||
T r = tools::evaluate_polynomial(P, p) / tools::evaluate_polynomial(Q, p);
|
||||
result = g * Y + g * r;
|
||||
}
|
||||
else if(q >= 0.25)
|
||||
{
|
||||
//
|
||||
// Rational approximation for 0.5 > q >= 0.25
|
||||
//
|
||||
// x = sqrt(-2*log(q)) / (Y + R(q))
|
||||
//
|
||||
// Where Y is a constant, and R(q) is optimised for a low
|
||||
// absolute error compared to Y.
|
||||
//
|
||||
// double : Max error found: 7.403372e-17
|
||||
// long double : Max error found: 6.084616e-20
|
||||
// Maximum Deviation Found (error term) 4.811e-20
|
||||
//
|
||||
static const float Y = 2.249481201171875f;
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.202433508355938759655),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.105264680699391713268),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 8.37050328343119927838),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 17.6447298408374015486),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -18.8510648058714251895),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -44.6382324441786960818),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 17.445385985570866523),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 21.1294655448340526258),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -3.67192254707729348546)
|
||||
};
|
||||
static const T Q[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 6.24264124854247537712),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 3.9713437953343869095),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -28.6608180499800029974),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -20.1432634680485188801),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 48.5609213108739935468),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 10.8268667355460159008),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -22.6436933413139721736),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.72114765761200282724)
|
||||
};
|
||||
T g = sqrt(-2 * log(q));
|
||||
T xs = q - 0.25f;
|
||||
T r = tools::evaluate_polynomial(P, xs) / tools::evaluate_polynomial(Q, xs);
|
||||
result = g / (Y + r);
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// For q < 0.25 we have a series of rational approximations all
|
||||
// of the general form:
|
||||
//
|
||||
// let: x = sqrt(-log(q))
|
||||
//
|
||||
// Then the result is given by:
|
||||
//
|
||||
// x(Y+R(x-B))
|
||||
//
|
||||
// where Y is a constant, B is the lowest value of x for which
|
||||
// the approximation is valid, and R(x-B) is optimised for a low
|
||||
// absolute error compared to Y.
|
||||
//
|
||||
// Note that almost all code will really go through the first
|
||||
// or maybe second approximation. After than we're dealing with very
|
||||
// small input values indeed: 80 and 128 bit long double's go all the
|
||||
// way down to ~ 1e-5000 so the "tail" is rather long...
|
||||
//
|
||||
T x = sqrt(-log(q));
|
||||
if(x < 3)
|
||||
{
|
||||
// Max error found: 1.089051e-20
|
||||
static const float Y = 0.807220458984375f;
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.131102781679951906451),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.163794047193317060787),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.117030156341995252019),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.387079738972604337464),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.337785538912035898924),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.142869534408157156766),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.0290157910005329060432),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.00214558995388805277169),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.679465575181126350155e-6),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.285225331782217055858e-7),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.681149956853776992068e-9)
|
||||
};
|
||||
static const T Q[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 3.46625407242567245975),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 5.38168345707006855425),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 4.77846592945843778382),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 2.59301921623620271374),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.848854343457902036425),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.152264338295331783612),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.01105924229346489121)
|
||||
};
|
||||
T xs = x - 1.125f;
|
||||
T R = tools::evaluate_polynomial(P, xs) / tools::evaluate_polynomial(Q, xs);
|
||||
result = Y * x + R * x;
|
||||
}
|
||||
else if(x < 6)
|
||||
{
|
||||
// Max error found: 8.389174e-21
|
||||
static const float Y = 0.93995571136474609375f;
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.0350353787183177984712),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.00222426529213447927281),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.0185573306514231072324),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.00950804701325919603619),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.00187123492819559223345),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.000157544617424960554631),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.460469890584317994083e-5),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.230404776911882601748e-9),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.266339227425782031962e-11)
|
||||
};
|
||||
static const T Q[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.3653349817554063097),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.762059164553623404043),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.220091105764131249824),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.0341589143670947727934),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.00263861676657015992959),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.764675292302794483503e-4)
|
||||
};
|
||||
T xs = x - 3;
|
||||
T R = tools::evaluate_polynomial(P, xs) / tools::evaluate_polynomial(Q, xs);
|
||||
result = Y * x + R * x;
|
||||
}
|
||||
else if(x < 18)
|
||||
{
|
||||
// Max error found: 1.481312e-19
|
||||
static const float Y = 0.98362827301025390625f;
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.0167431005076633737133),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.00112951438745580278863),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.00105628862152492910091),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.000209386317487588078668),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.149624783758342370182e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.449696789927706453732e-6),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.462596163522878599135e-8),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.281128735628831791805e-13),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.99055709973310326855e-16)
|
||||
};
|
||||
static const T Q[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.591429344886417493481),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.138151865749083321638),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.0160746087093676504695),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.000964011807005165528527),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.275335474764726041141e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.282243172016108031869e-6)
|
||||
};
|
||||
T xs = x - 6;
|
||||
T R = tools::evaluate_polynomial(P, xs) / tools::evaluate_polynomial(Q, xs);
|
||||
result = Y * x + R * x;
|
||||
}
|
||||
else if(x < 44)
|
||||
{
|
||||
// Max error found: 5.697761e-20
|
||||
static const float Y = 0.99714565277099609375f;
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.0024978212791898131227),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.779190719229053954292e-5),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.254723037413027451751e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.162397777342510920873e-5),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.396341011304801168516e-7),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.411632831190944208473e-9),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.145596286718675035587e-11),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.116765012397184275695e-17)
|
||||
};
|
||||
static const T Q[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.207123112214422517181),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.0169410838120975906478),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.000690538265622684595676),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.145007359818232637924e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.144437756628144157666e-6),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.509761276599778486139e-9)
|
||||
};
|
||||
T xs = x - 18;
|
||||
T R = tools::evaluate_polynomial(P, xs) / tools::evaluate_polynomial(Q, xs);
|
||||
result = Y * x + R * x;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Max error found: 1.279746e-20
|
||||
static const float Y = 0.99941349029541015625f;
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.000539042911019078575891),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.28398759004727721098e-6),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.899465114892291446442e-6),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.229345859265920864296e-7),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.225561444863500149219e-9),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.947846627503022684216e-12),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.135880130108924861008e-14),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.348890393399948882918e-21)
|
||||
};
|
||||
static const T Q[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.0845746234001899436914),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.00282092984726264681981),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.468292921940894236786e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.399968812193862100054e-6),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.161809290887904476097e-8),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.231558608310259605225e-11)
|
||||
};
|
||||
T xs = x - 44;
|
||||
T R = tools::evaluate_polynomial(P, xs) / tools::evaluate_polynomial(Q, xs);
|
||||
result = Y * x + R * x;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
struct erf_roots
|
||||
{
|
||||
boost::math::tuple<T,T,T> operator()(const T& guess)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
T derivative = sign * (2 / sqrt(constants::pi<T>())) * exp(-(guess * guess));
|
||||
T derivative2 = -2 * guess * derivative;
|
||||
return boost::math::make_tuple(((sign > 0) ? static_cast<T>(boost::math::erf(guess, Policy()) - target) : static_cast<T>(boost::math::erfc(guess, Policy())) - target), derivative, derivative2);
|
||||
}
|
||||
erf_roots(T z, int s) : target(z), sign(s) {}
|
||||
private:
|
||||
T target;
|
||||
int sign;
|
||||
};
|
||||
|
||||
template <class T, class Policy>
|
||||
T erf_inv_imp(const T& p, const T& q, const Policy& pol, const boost::mpl::int_<0>*)
|
||||
{
|
||||
//
|
||||
// Generic version, get a guess that's accurate to 64-bits (10^-19)
|
||||
//
|
||||
T guess = erf_inv_imp(p, q, pol, static_cast<mpl::int_<64> const*>(0));
|
||||
T result;
|
||||
//
|
||||
// If T has more bit's than 64 in it's mantissa then we need to iterate,
|
||||
// otherwise we can just return the result:
|
||||
//
|
||||
if(policies::digits<T, Policy>() > 64)
|
||||
{
|
||||
boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
|
||||
if(p <= 0.5)
|
||||
{
|
||||
result = tools::halley_iterate(detail::erf_roots<typename remove_cv<T>::type, Policy>(p, 1), guess, static_cast<T>(0), tools::max_value<T>(), (policies::digits<T, Policy>() * 2) / 3, max_iter);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = tools::halley_iterate(detail::erf_roots<typename remove_cv<T>::type, Policy>(q, -1), guess, static_cast<T>(0), tools::max_value<T>(), (policies::digits<T, Policy>() * 2) / 3, max_iter);
|
||||
}
|
||||
policies::check_root_iterations<T>("boost::math::erf_inv<%1%>", max_iter, pol);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = guess;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
struct erf_inv_initializer
|
||||
{
|
||||
struct init
|
||||
{
|
||||
init()
|
||||
{
|
||||
do_init();
|
||||
}
|
||||
static bool is_value_non_zero(T);
|
||||
static void do_init()
|
||||
{
|
||||
// If std::numeric_limits<T>::digits is zero, we must not call
|
||||
// our inituialization code here as the precision presumably
|
||||
// varies at runtime, and will not have been set yet.
|
||||
if(std::numeric_limits<T>::digits)
|
||||
{
|
||||
boost::math::erf_inv(static_cast<T>(0.25), Policy());
|
||||
boost::math::erf_inv(static_cast<T>(0.55), Policy());
|
||||
boost::math::erf_inv(static_cast<T>(0.95), Policy());
|
||||
boost::math::erfc_inv(static_cast<T>(1e-15), Policy());
|
||||
// These following initializations must not be called if
|
||||
// type T can not hold the relevant values without
|
||||
// underflow to zero. We check this at runtime because
|
||||
// some tools such as valgrind silently change the precision
|
||||
// of T at runtime, and numeric_limits basically lies!
|
||||
if(is_value_non_zero(static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1e-130))))
|
||||
boost::math::erfc_inv(static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1e-130)), Policy());
|
||||
|
||||
// Some compilers choke on constants that would underflow, even in code that isn't instantiated
|
||||
// so try and filter these cases out in the preprocessor:
|
||||
#if LDBL_MAX_10_EXP >= 800
|
||||
if(is_value_non_zero(static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1e-800))))
|
||||
boost::math::erfc_inv(static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1e-800)), Policy());
|
||||
if(is_value_non_zero(static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1e-900))))
|
||||
boost::math::erfc_inv(static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1e-900)), Policy());
|
||||
#else
|
||||
if(is_value_non_zero(static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 64, 1e-800))))
|
||||
boost::math::erfc_inv(static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 64, 1e-800)), Policy());
|
||||
if(is_value_non_zero(static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 64, 1e-900))))
|
||||
boost::math::erfc_inv(static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 64, 1e-900)), Policy());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
void force_instantiate()const{}
|
||||
};
|
||||
static const init initializer;
|
||||
static void force_instantiate()
|
||||
{
|
||||
initializer.force_instantiate();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class Policy>
|
||||
const typename erf_inv_initializer<T, Policy>::init erf_inv_initializer<T, Policy>::initializer;
|
||||
|
||||
template <class T, class Policy>
|
||||
bool erf_inv_initializer<T, Policy>::init::is_value_non_zero(T v)
|
||||
{
|
||||
// This needs to be non-inline to detect whether v is non zero at runtime
|
||||
// rather than at compile time, only relevant when running under valgrind
|
||||
// which changes long double's to double's on the fly.
|
||||
return v != 0;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class T, class Policy>
|
||||
typename tools::promote_args<T>::type erfc_inv(T z, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T>::type result_type;
|
||||
|
||||
//
|
||||
// Begin by testing for domain errors, and other special cases:
|
||||
//
|
||||
static const char* function = "boost::math::erfc_inv<%1%>(%1%, %1%)";
|
||||
if((z < 0) || (z > 2))
|
||||
return policies::raise_domain_error<result_type>(function, "Argument outside range [0,2] in inverse erfc function (got p=%1%).", z, pol);
|
||||
if(z == 0)
|
||||
return policies::raise_overflow_error<result_type>(function, 0, pol);
|
||||
if(z == 2)
|
||||
return -policies::raise_overflow_error<result_type>(function, 0, pol);
|
||||
//
|
||||
// Normalise the input, so it's in the range [0,1], we will
|
||||
// negate the result if z is outside that range. This is a simple
|
||||
// application of the erfc reflection formula: erfc(-z) = 2 - erfc(z)
|
||||
//
|
||||
result_type p, q, s;
|
||||
if(z > 1)
|
||||
{
|
||||
q = 2 - z;
|
||||
p = 1 - q;
|
||||
s = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
p = 1 - z;
|
||||
q = z;
|
||||
s = 1;
|
||||
}
|
||||
//
|
||||
// A bit of meta-programming to figure out which implementation
|
||||
// to use, based on the number of bits in the mantissa of T:
|
||||
//
|
||||
typedef typename policies::precision<result_type, Policy>::type precision_type;
|
||||
typedef typename mpl::if_<
|
||||
mpl::or_<mpl::less_equal<precision_type, mpl::int_<0> >, mpl::greater<precision_type, mpl::int_<64> > >,
|
||||
mpl::int_<0>,
|
||||
mpl::int_<64>
|
||||
>::type tag_type;
|
||||
//
|
||||
// Likewise use internal promotion, so we evaluate at a higher
|
||||
// precision internally if it's appropriate:
|
||||
//
|
||||
typedef typename policies::evaluation<result_type, Policy>::type eval_type;
|
||||
typedef typename policies::normalise<
|
||||
Policy,
|
||||
policies::promote_float<false>,
|
||||
policies::promote_double<false>,
|
||||
policies::discrete_quantile<>,
|
||||
policies::assert_undefined<> >::type forwarding_policy;
|
||||
|
||||
detail::erf_inv_initializer<eval_type, forwarding_policy>::force_instantiate();
|
||||
|
||||
//
|
||||
// And get the result, negating where required:
|
||||
//
|
||||
return s * policies::checked_narrowing_cast<result_type, forwarding_policy>(
|
||||
detail::erf_inv_imp(static_cast<eval_type>(p), static_cast<eval_type>(q), forwarding_policy(), static_cast<tag_type const*>(0)), function);
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
typename tools::promote_args<T>::type erf_inv(T z, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T>::type result_type;
|
||||
|
||||
//
|
||||
// Begin by testing for domain errors, and other special cases:
|
||||
//
|
||||
static const char* function = "boost::math::erf_inv<%1%>(%1%, %1%)";
|
||||
if((z < -1) || (z > 1))
|
||||
return policies::raise_domain_error<result_type>(function, "Argument outside range [-1, 1] in inverse erf function (got p=%1%).", z, pol);
|
||||
if(z == 1)
|
||||
return policies::raise_overflow_error<result_type>(function, 0, pol);
|
||||
if(z == -1)
|
||||
return -policies::raise_overflow_error<result_type>(function, 0, pol);
|
||||
if(z == 0)
|
||||
return 0;
|
||||
//
|
||||
// Normalise the input, so it's in the range [0,1], we will
|
||||
// negate the result if z is outside that range. This is a simple
|
||||
// application of the erf reflection formula: erf(-z) = -erf(z)
|
||||
//
|
||||
result_type p, q, s;
|
||||
if(z < 0)
|
||||
{
|
||||
p = -z;
|
||||
q = 1 - p;
|
||||
s = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
p = z;
|
||||
q = 1 - z;
|
||||
s = 1;
|
||||
}
|
||||
//
|
||||
// A bit of meta-programming to figure out which implementation
|
||||
// to use, based on the number of bits in the mantissa of T:
|
||||
//
|
||||
typedef typename policies::precision<result_type, Policy>::type precision_type;
|
||||
typedef typename mpl::if_<
|
||||
mpl::or_<mpl::less_equal<precision_type, mpl::int_<0> >, mpl::greater<precision_type, mpl::int_<64> > >,
|
||||
mpl::int_<0>,
|
||||
mpl::int_<64>
|
||||
>::type tag_type;
|
||||
//
|
||||
// Likewise use internal promotion, so we evaluate at a higher
|
||||
// precision internally if it's appropriate:
|
||||
//
|
||||
typedef typename policies::evaluation<result_type, Policy>::type eval_type;
|
||||
typedef typename policies::normalise<
|
||||
Policy,
|
||||
policies::promote_float<false>,
|
||||
policies::promote_double<false>,
|
||||
policies::discrete_quantile<>,
|
||||
policies::assert_undefined<> >::type forwarding_policy;
|
||||
//
|
||||
// Likewise use internal promotion, so we evaluate at a higher
|
||||
// precision internally if it's appropriate:
|
||||
//
|
||||
typedef typename policies::evaluation<result_type, Policy>::type eval_type;
|
||||
|
||||
detail::erf_inv_initializer<eval_type, forwarding_policy>::force_instantiate();
|
||||
//
|
||||
// And get the result, negating where required:
|
||||
//
|
||||
return s * policies::checked_narrowing_cast<result_type, forwarding_policy>(
|
||||
detail::erf_inv_imp(static_cast<eval_type>(p), static_cast<eval_type>(q), forwarding_policy(), static_cast<tag_type const*>(0)), function);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typename tools::promote_args<T>::type erfc_inv(T z)
|
||||
{
|
||||
return erfc_inv(z, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typename tools::promote_args<T>::type erf_inv(T z)
|
||||
{
|
||||
return erf_inv(z, policies::policy<>());
|
||||
}
|
||||
|
||||
} // namespace math
|
||||
} // namespace boost
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif // BOOST_MATH_SF_ERF_INV_HPP
|
||||
|
||||
581
code_isotrope/boost/math/special_functions/detail/fp_traits.hpp
Executable file
581
code_isotrope/boost/math/special_functions/detail/fp_traits.hpp
Executable file
@@ -0,0 +1,581 @@
|
||||
// fp_traits.hpp
|
||||
|
||||
#ifndef BOOST_MATH_FP_TRAITS_HPP
|
||||
#define BOOST_MATH_FP_TRAITS_HPP
|
||||
|
||||
// Copyright (c) 2006 Johan Rade
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
/*
|
||||
To support old compilers, care has been taken to avoid partial template
|
||||
specialization and meta function forwarding.
|
||||
With these techniques, the code could be simplified.
|
||||
*/
|
||||
|
||||
#if defined(__vms) && defined(__DECCXX) && !__IEEE_FLOAT
|
||||
// The VAX floating point formats are used (for float and double)
|
||||
# define BOOST_FPCLASSIFY_VAX_FORMAT
|
||||
#endif
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/predef/other/endian.h>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/type_traits/is_floating_point.hpp>
|
||||
|
||||
#ifdef BOOST_NO_STDC_NAMESPACE
|
||||
namespace std{ using ::memcpy; }
|
||||
#endif
|
||||
|
||||
#ifndef FP_NORMAL
|
||||
|
||||
#define FP_ZERO 0
|
||||
#define FP_NORMAL 1
|
||||
#define FP_INFINITE 2
|
||||
#define FP_NAN 3
|
||||
#define FP_SUBNORMAL 4
|
||||
|
||||
#else
|
||||
|
||||
#define BOOST_HAS_FPCLASSIFY
|
||||
|
||||
#ifndef fpclassify
|
||||
# if (defined(__GLIBCPP__) || defined(__GLIBCXX__)) \
|
||||
&& defined(_GLIBCXX_USE_C99_MATH) \
|
||||
&& !(defined(_GLIBCXX_USE_C99_FP_MACROS_DYNAMIC) \
|
||||
&& (_GLIBCXX_USE_C99_FP_MACROS_DYNAMIC != 0))
|
||||
# ifdef _STLP_VENDOR_CSTD
|
||||
# if _STLPORT_VERSION >= 0x520
|
||||
# define BOOST_FPCLASSIFY_PREFIX ::__std_alias::
|
||||
# else
|
||||
# define BOOST_FPCLASSIFY_PREFIX ::_STLP_VENDOR_CSTD::
|
||||
# endif
|
||||
# else
|
||||
# define BOOST_FPCLASSIFY_PREFIX ::std::
|
||||
# endif
|
||||
# else
|
||||
# undef BOOST_HAS_FPCLASSIFY
|
||||
# define BOOST_FPCLASSIFY_PREFIX
|
||||
# endif
|
||||
#elif (defined(__HP_aCC) && !defined(__hppa))
|
||||
// aCC 6 appears to do "#define fpclassify fpclassify" which messes us up a bit!
|
||||
# define BOOST_FPCLASSIFY_PREFIX ::
|
||||
#else
|
||||
# define BOOST_FPCLASSIFY_PREFIX
|
||||
#endif
|
||||
|
||||
#ifdef __MINGW32__
|
||||
# undef BOOST_HAS_FPCLASSIFY
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace boost {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
The following classes are used to tag the different methods that are used
|
||||
for floating point classification
|
||||
*/
|
||||
|
||||
struct native_tag {};
|
||||
template <bool has_limits>
|
||||
struct generic_tag {};
|
||||
struct ieee_tag {};
|
||||
struct ieee_copy_all_bits_tag : public ieee_tag {};
|
||||
struct ieee_copy_leading_bits_tag : public ieee_tag {};
|
||||
|
||||
#ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
|
||||
//
|
||||
// These helper functions are used only when numeric_limits<>
|
||||
// members are not compile time constants:
|
||||
//
|
||||
inline bool is_generic_tag_false(const generic_tag<false>*)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
inline bool is_generic_tag_false(const void*)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Most processors support three different floating point precisions:
|
||||
single precision (32 bits), double precision (64 bits)
|
||||
and extended double precision (80 - 128 bits, depending on the processor)
|
||||
|
||||
Note that the C++ type long double can be implemented
|
||||
both as double precision and extended double precision.
|
||||
*/
|
||||
|
||||
struct unknown_precision{};
|
||||
struct single_precision {};
|
||||
struct double_precision {};
|
||||
struct extended_double_precision {};
|
||||
|
||||
// native_tag version --------------------------------------------------------------
|
||||
|
||||
template<class T> struct fp_traits_native
|
||||
{
|
||||
typedef native_tag method;
|
||||
};
|
||||
|
||||
// generic_tag version -------------------------------------------------------------
|
||||
|
||||
template<class T, class U> struct fp_traits_non_native
|
||||
{
|
||||
#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
|
||||
typedef generic_tag<std::numeric_limits<T>::is_specialized> method;
|
||||
#else
|
||||
typedef generic_tag<false> method;
|
||||
#endif
|
||||
};
|
||||
|
||||
// ieee_tag versions ---------------------------------------------------------------
|
||||
|
||||
/*
|
||||
These specializations of fp_traits_non_native contain information needed
|
||||
to "parse" the binary representation of a floating point number.
|
||||
|
||||
Typedef members:
|
||||
|
||||
bits -- the target type when copying the leading bytes of a floating
|
||||
point number. It is a typedef for uint32_t or uint64_t.
|
||||
|
||||
method -- tells us whether all bytes are copied or not.
|
||||
It is a typedef for ieee_copy_all_bits_tag or ieee_copy_leading_bits_tag.
|
||||
|
||||
Static data members:
|
||||
|
||||
sign, exponent, flag, significand -- bit masks that give the meaning of the
|
||||
bits in the leading bytes.
|
||||
|
||||
Static function members:
|
||||
|
||||
get_bits(), set_bits() -- provide access to the leading bytes.
|
||||
|
||||
*/
|
||||
|
||||
// ieee_tag version, float (32 bits) -----------------------------------------------
|
||||
|
||||
#ifndef BOOST_FPCLASSIFY_VAX_FORMAT
|
||||
|
||||
template<> struct fp_traits_non_native<float, single_precision>
|
||||
{
|
||||
typedef ieee_copy_all_bits_tag method;
|
||||
|
||||
BOOST_STATIC_CONSTANT(uint32_t, sign = 0x80000000u);
|
||||
BOOST_STATIC_CONSTANT(uint32_t, exponent = 0x7f800000);
|
||||
BOOST_STATIC_CONSTANT(uint32_t, flag = 0x00000000);
|
||||
BOOST_STATIC_CONSTANT(uint32_t, significand = 0x007fffff);
|
||||
|
||||
typedef uint32_t bits;
|
||||
static void get_bits(float x, uint32_t& a) { std::memcpy(&a, &x, 4); }
|
||||
static void set_bits(float& x, uint32_t a) { std::memcpy(&x, &a, 4); }
|
||||
};
|
||||
|
||||
// ieee_tag version, double (64 bits) ----------------------------------------------
|
||||
|
||||
#if defined(BOOST_NO_INT64_T) || defined(BOOST_NO_INCLASS_MEMBER_INITIALIZATION) \
|
||||
|| defined(__BORLANDC__) || defined(__CODEGEAR__)
|
||||
|
||||
template<> struct fp_traits_non_native<double, double_precision>
|
||||
{
|
||||
typedef ieee_copy_leading_bits_tag method;
|
||||
|
||||
BOOST_STATIC_CONSTANT(uint32_t, sign = 0x80000000u);
|
||||
BOOST_STATIC_CONSTANT(uint32_t, exponent = 0x7ff00000);
|
||||
BOOST_STATIC_CONSTANT(uint32_t, flag = 0);
|
||||
BOOST_STATIC_CONSTANT(uint32_t, significand = 0x000fffff);
|
||||
|
||||
typedef uint32_t bits;
|
||||
|
||||
static void get_bits(double x, uint32_t& a)
|
||||
{
|
||||
std::memcpy(&a, reinterpret_cast<const unsigned char*>(&x) + offset_, 4);
|
||||
}
|
||||
|
||||
static void set_bits(double& x, uint32_t a)
|
||||
{
|
||||
std::memcpy(reinterpret_cast<unsigned char*>(&x) + offset_, &a, 4);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
#if BOOST_ENDIAN_BIG_BYTE
|
||||
BOOST_STATIC_CONSTANT(int, offset_ = 0);
|
||||
#elif BOOST_ENDIAN_LITTLE_BYTE
|
||||
BOOST_STATIC_CONSTANT(int, offset_ = 4);
|
||||
#else
|
||||
BOOST_STATIC_ASSERT(false);
|
||||
#endif
|
||||
};
|
||||
|
||||
//..............................................................................
|
||||
|
||||
#else
|
||||
|
||||
template<> struct fp_traits_non_native<double, double_precision>
|
||||
{
|
||||
typedef ieee_copy_all_bits_tag method;
|
||||
|
||||
static const uint64_t sign = ((uint64_t)0x80000000u) << 32;
|
||||
static const uint64_t exponent = ((uint64_t)0x7ff00000) << 32;
|
||||
static const uint64_t flag = 0;
|
||||
static const uint64_t significand
|
||||
= (((uint64_t)0x000fffff) << 32) + ((uint64_t)0xffffffffu);
|
||||
|
||||
typedef uint64_t bits;
|
||||
static void get_bits(double x, uint64_t& a) { std::memcpy(&a, &x, 8); }
|
||||
static void set_bits(double& x, uint64_t a) { std::memcpy(&x, &a, 8); }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif // #ifndef BOOST_FPCLASSIFY_VAX_FORMAT
|
||||
|
||||
// long double (64 bits) -------------------------------------------------------
|
||||
|
||||
#if defined(BOOST_NO_INT64_T) || defined(BOOST_NO_INCLASS_MEMBER_INITIALIZATION)\
|
||||
|| defined(__BORLANDC__) || defined(__CODEGEAR__)
|
||||
|
||||
template<> struct fp_traits_non_native<long double, double_precision>
|
||||
{
|
||||
typedef ieee_copy_leading_bits_tag method;
|
||||
|
||||
BOOST_STATIC_CONSTANT(uint32_t, sign = 0x80000000u);
|
||||
BOOST_STATIC_CONSTANT(uint32_t, exponent = 0x7ff00000);
|
||||
BOOST_STATIC_CONSTANT(uint32_t, flag = 0);
|
||||
BOOST_STATIC_CONSTANT(uint32_t, significand = 0x000fffff);
|
||||
|
||||
typedef uint32_t bits;
|
||||
|
||||
static void get_bits(long double x, uint32_t& a)
|
||||
{
|
||||
std::memcpy(&a, reinterpret_cast<const unsigned char*>(&x) + offset_, 4);
|
||||
}
|
||||
|
||||
static void set_bits(long double& x, uint32_t a)
|
||||
{
|
||||
std::memcpy(reinterpret_cast<unsigned char*>(&x) + offset_, &a, 4);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
#if BOOST_ENDIAN_BIG_BYTE
|
||||
BOOST_STATIC_CONSTANT(int, offset_ = 0);
|
||||
#elif BOOST_ENDIAN_LITTLE_BYTE
|
||||
BOOST_STATIC_CONSTANT(int, offset_ = 4);
|
||||
#else
|
||||
BOOST_STATIC_ASSERT(false);
|
||||
#endif
|
||||
};
|
||||
|
||||
//..............................................................................
|
||||
|
||||
#else
|
||||
|
||||
template<> struct fp_traits_non_native<long double, double_precision>
|
||||
{
|
||||
typedef ieee_copy_all_bits_tag method;
|
||||
|
||||
static const uint64_t sign = (uint64_t)0x80000000u << 32;
|
||||
static const uint64_t exponent = (uint64_t)0x7ff00000 << 32;
|
||||
static const uint64_t flag = 0;
|
||||
static const uint64_t significand
|
||||
= ((uint64_t)0x000fffff << 32) + (uint64_t)0xffffffffu;
|
||||
|
||||
typedef uint64_t bits;
|
||||
static void get_bits(long double x, uint64_t& a) { std::memcpy(&a, &x, 8); }
|
||||
static void set_bits(long double& x, uint64_t a) { std::memcpy(&x, &a, 8); }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// long double (>64 bits), x86 and x64 -----------------------------------------
|
||||
|
||||
#if defined(__i386) || defined(__i386__) || defined(_M_IX86) \
|
||||
|| defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) \
|
||||
|| defined(__x86_64) || defined(__x86_64__) || defined(_M_X64)
|
||||
|
||||
// Intel extended double precision format (80 bits)
|
||||
|
||||
template<>
|
||||
struct fp_traits_non_native<long double, extended_double_precision>
|
||||
{
|
||||
typedef ieee_copy_leading_bits_tag method;
|
||||
|
||||
BOOST_STATIC_CONSTANT(uint32_t, sign = 0x80000000u);
|
||||
BOOST_STATIC_CONSTANT(uint32_t, exponent = 0x7fff0000);
|
||||
BOOST_STATIC_CONSTANT(uint32_t, flag = 0x00008000);
|
||||
BOOST_STATIC_CONSTANT(uint32_t, significand = 0x00007fff);
|
||||
|
||||
typedef uint32_t bits;
|
||||
|
||||
static void get_bits(long double x, uint32_t& a)
|
||||
{
|
||||
std::memcpy(&a, reinterpret_cast<const unsigned char*>(&x) + 6, 4);
|
||||
}
|
||||
|
||||
static void set_bits(long double& x, uint32_t a)
|
||||
{
|
||||
std::memcpy(reinterpret_cast<unsigned char*>(&x) + 6, &a, 4);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// long double (>64 bits), Itanium ---------------------------------------------
|
||||
|
||||
#elif defined(__ia64) || defined(__ia64__) || defined(_M_IA64)
|
||||
|
||||
// The floating point format is unknown at compile time
|
||||
// No template specialization is provided.
|
||||
// The generic_tag definition is used.
|
||||
|
||||
// The Itanium supports both
|
||||
// the Intel extended double precision format (80 bits) and
|
||||
// the IEEE extended double precision format with 15 exponent bits (128 bits).
|
||||
|
||||
#elif defined(__GNUC__) && (LDBL_MANT_DIG == 106)
|
||||
|
||||
//
|
||||
// Define nothing here and fall though to generic_tag:
|
||||
// We have GCC's "double double" in effect, and any attempt
|
||||
// to handle it via bit-fiddling is pretty much doomed to fail...
|
||||
//
|
||||
|
||||
// long double (>64 bits), PowerPC ---------------------------------------------
|
||||
|
||||
#elif defined(__powerpc) || defined(__powerpc__) || defined(__POWERPC__) \
|
||||
|| defined(__ppc) || defined(__ppc__) || defined(__PPC__)
|
||||
|
||||
// PowerPC extended double precision format (128 bits)
|
||||
|
||||
template<>
|
||||
struct fp_traits_non_native<long double, extended_double_precision>
|
||||
{
|
||||
typedef ieee_copy_leading_bits_tag method;
|
||||
|
||||
BOOST_STATIC_CONSTANT(uint32_t, sign = 0x80000000u);
|
||||
BOOST_STATIC_CONSTANT(uint32_t, exponent = 0x7ff00000);
|
||||
BOOST_STATIC_CONSTANT(uint32_t, flag = 0x00000000);
|
||||
BOOST_STATIC_CONSTANT(uint32_t, significand = 0x000fffff);
|
||||
|
||||
typedef uint32_t bits;
|
||||
|
||||
static void get_bits(long double x, uint32_t& a)
|
||||
{
|
||||
std::memcpy(&a, reinterpret_cast<const unsigned char*>(&x) + offset_, 4);
|
||||
}
|
||||
|
||||
static void set_bits(long double& x, uint32_t a)
|
||||
{
|
||||
std::memcpy(reinterpret_cast<unsigned char*>(&x) + offset_, &a, 4);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
#if BOOST_ENDIAN_BIG_BYTE
|
||||
BOOST_STATIC_CONSTANT(int, offset_ = 0);
|
||||
#elif BOOST_ENDIAN_LITTLE_BYTE
|
||||
BOOST_STATIC_CONSTANT(int, offset_ = 12);
|
||||
#else
|
||||
BOOST_STATIC_ASSERT(false);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
// long double (>64 bits), Motorola 68K ----------------------------------------
|
||||
|
||||
#elif defined(__m68k) || defined(__m68k__) \
|
||||
|| defined(__mc68000) || defined(__mc68000__) \
|
||||
|
||||
// Motorola extended double precision format (96 bits)
|
||||
|
||||
// It is the same format as the Intel extended double precision format,
|
||||
// except that 1) it is big-endian, 2) the 3rd and 4th byte are padding, and
|
||||
// 3) the flag bit is not set for infinity
|
||||
|
||||
template<>
|
||||
struct fp_traits_non_native<long double, extended_double_precision>
|
||||
{
|
||||
typedef ieee_copy_leading_bits_tag method;
|
||||
|
||||
BOOST_STATIC_CONSTANT(uint32_t, sign = 0x80000000u);
|
||||
BOOST_STATIC_CONSTANT(uint32_t, exponent = 0x7fff0000);
|
||||
BOOST_STATIC_CONSTANT(uint32_t, flag = 0x00008000);
|
||||
BOOST_STATIC_CONSTANT(uint32_t, significand = 0x00007fff);
|
||||
|
||||
// copy 1st, 2nd, 5th and 6th byte. 3rd and 4th byte are padding.
|
||||
|
||||
typedef uint32_t bits;
|
||||
|
||||
static void get_bits(long double x, uint32_t& a)
|
||||
{
|
||||
std::memcpy(&a, &x, 2);
|
||||
std::memcpy(reinterpret_cast<unsigned char*>(&a) + 2,
|
||||
reinterpret_cast<const unsigned char*>(&x) + 4, 2);
|
||||
}
|
||||
|
||||
static void set_bits(long double& x, uint32_t a)
|
||||
{
|
||||
std::memcpy(&x, &a, 2);
|
||||
std::memcpy(reinterpret_cast<unsigned char*>(&x) + 4,
|
||||
reinterpret_cast<const unsigned char*>(&a) + 2, 2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// long double (>64 bits), All other processors --------------------------------
|
||||
|
||||
#else
|
||||
|
||||
// IEEE extended double precision format with 15 exponent bits (128 bits)
|
||||
|
||||
template<>
|
||||
struct fp_traits_non_native<long double, extended_double_precision>
|
||||
{
|
||||
typedef ieee_copy_leading_bits_tag method;
|
||||
|
||||
BOOST_STATIC_CONSTANT(uint32_t, sign = 0x80000000u);
|
||||
BOOST_STATIC_CONSTANT(uint32_t, exponent = 0x7fff0000);
|
||||
BOOST_STATIC_CONSTANT(uint32_t, flag = 0x00000000);
|
||||
BOOST_STATIC_CONSTANT(uint32_t, significand = 0x0000ffff);
|
||||
|
||||
typedef uint32_t bits;
|
||||
|
||||
static void get_bits(long double x, uint32_t& a)
|
||||
{
|
||||
std::memcpy(&a, reinterpret_cast<const unsigned char*>(&x) + offset_, 4);
|
||||
}
|
||||
|
||||
static void set_bits(long double& x, uint32_t a)
|
||||
{
|
||||
std::memcpy(reinterpret_cast<unsigned char*>(&x) + offset_, &a, 4);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
#if BOOST_ENDIAN_BIG_BYTE
|
||||
BOOST_STATIC_CONSTANT(int, offset_ = 0);
|
||||
#elif BOOST_ENDIAN_LITTLE_BYTE
|
||||
BOOST_STATIC_CONSTANT(int, offset_ = 12);
|
||||
#else
|
||||
BOOST_STATIC_ASSERT(false);
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// size_to_precision is a type switch for converting a C++ floating point type
|
||||
// to the corresponding precision type.
|
||||
|
||||
template<int n, bool fp> struct size_to_precision
|
||||
{
|
||||
typedef unknown_precision type;
|
||||
};
|
||||
|
||||
template<> struct size_to_precision<4, true>
|
||||
{
|
||||
typedef single_precision type;
|
||||
};
|
||||
|
||||
template<> struct size_to_precision<8, true>
|
||||
{
|
||||
typedef double_precision type;
|
||||
};
|
||||
|
||||
template<> struct size_to_precision<10, true>
|
||||
{
|
||||
typedef extended_double_precision type;
|
||||
};
|
||||
|
||||
template<> struct size_to_precision<12, true>
|
||||
{
|
||||
typedef extended_double_precision type;
|
||||
};
|
||||
|
||||
template<> struct size_to_precision<16, true>
|
||||
{
|
||||
typedef extended_double_precision type;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Figure out whether to use native classification functions based on
|
||||
// whether T is a built in floating point type or not:
|
||||
//
|
||||
template <class T>
|
||||
struct select_native
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME size_to_precision<sizeof(T), ::boost::is_floating_point<T>::value>::type precision;
|
||||
typedef fp_traits_non_native<T, precision> type;
|
||||
};
|
||||
template<>
|
||||
struct select_native<float>
|
||||
{
|
||||
typedef fp_traits_native<float> type;
|
||||
};
|
||||
template<>
|
||||
struct select_native<double>
|
||||
{
|
||||
typedef fp_traits_native<double> type;
|
||||
};
|
||||
template<>
|
||||
struct select_native<long double>
|
||||
{
|
||||
typedef fp_traits_native<long double> type;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// fp_traits is a type switch that selects the right fp_traits_non_native
|
||||
|
||||
#if (defined(BOOST_MATH_USE_C99) && !(defined(__GNUC__) && (__GNUC__ < 4))) \
|
||||
&& !defined(__hpux) \
|
||||
&& !defined(__DECCXX)\
|
||||
&& !defined(__osf__) \
|
||||
&& !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION)\
|
||||
&& !defined(__FAST_MATH__)\
|
||||
&& !defined(BOOST_MATH_DISABLE_STD_FPCLASSIFY)\
|
||||
&& !defined(BOOST_INTEL)\
|
||||
&& !defined(sun)\
|
||||
&& !defined(__VXWORKS__)
|
||||
# define BOOST_MATH_USE_STD_FPCLASSIFY
|
||||
#endif
|
||||
|
||||
template<class T> struct fp_traits
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME size_to_precision<sizeof(T), ::boost::is_floating_point<T>::value>::type precision;
|
||||
#if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && !defined(BOOST_MATH_DISABLE_STD_FPCLASSIFY)
|
||||
typedef typename select_native<T>::type type;
|
||||
#else
|
||||
typedef fp_traits_non_native<T, precision> type;
|
||||
#endif
|
||||
typedef fp_traits_non_native<T, precision> sign_change_type;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
} // namespace detail
|
||||
} // namespace math
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
233
code_isotrope/boost/math/special_functions/detail/gamma_inva.hpp
Executable file
233
code_isotrope/boost/math/special_functions/detail/gamma_inva.hpp
Executable file
@@ -0,0 +1,233 @@
|
||||
// (C) Copyright John Maddock 2006.
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
//
|
||||
// This is not a complete header file, it is included by gamma.hpp
|
||||
// after it has defined it's definitions. This inverts the incomplete
|
||||
// gamma functions P and Q on the first parameter "a" using a generic
|
||||
// root finding algorithm (TOMS Algorithm 748).
|
||||
//
|
||||
|
||||
#ifndef BOOST_MATH_SP_DETAIL_GAMMA_INVA
|
||||
#define BOOST_MATH_SP_DETAIL_GAMMA_INVA
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/tools/toms748_solve.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
|
||||
namespace boost{ namespace math{ namespace detail{
|
||||
|
||||
template <class T, class Policy>
|
||||
struct gamma_inva_t
|
||||
{
|
||||
gamma_inva_t(T z_, T p_, bool invert_) : z(z_), p(p_), invert(invert_) {}
|
||||
T operator()(T a)
|
||||
{
|
||||
return invert ? p - boost::math::gamma_q(a, z, Policy()) : boost::math::gamma_p(a, z, Policy()) - p;
|
||||
}
|
||||
private:
|
||||
T z, p;
|
||||
bool invert;
|
||||
};
|
||||
|
||||
template <class T, class Policy>
|
||||
T inverse_poisson_cornish_fisher(T lambda, T p, T q, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
// mean:
|
||||
T m = lambda;
|
||||
// standard deviation:
|
||||
T sigma = sqrt(lambda);
|
||||
// skewness
|
||||
T sk = 1 / sigma;
|
||||
// kurtosis:
|
||||
// T k = 1/lambda;
|
||||
// Get the inverse of a std normal distribution:
|
||||
T x = boost::math::erfc_inv(p > q ? 2 * q : 2 * p, pol) * constants::root_two<T>();
|
||||
// Set the sign:
|
||||
if(p < 0.5)
|
||||
x = -x;
|
||||
T x2 = x * x;
|
||||
// w is correction term due to skewness
|
||||
T w = x + sk * (x2 - 1) / 6;
|
||||
/*
|
||||
// Add on correction due to kurtosis.
|
||||
// Disabled for now, seems to make things worse?
|
||||
//
|
||||
if(lambda >= 10)
|
||||
w += k * x * (x2 - 3) / 24 + sk * sk * x * (2 * x2 - 5) / -36;
|
||||
*/
|
||||
w = m + sigma * w;
|
||||
return w > tools::min_value<T>() ? w : tools::min_value<T>();
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
T gamma_inva_imp(const T& z, const T& p, const T& q, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING // for ADL of std lib math functions
|
||||
//
|
||||
// Special cases first:
|
||||
//
|
||||
if(p == 0)
|
||||
{
|
||||
return policies::raise_overflow_error<T>("boost::math::gamma_p_inva<%1%>(%1%, %1%)", 0, Policy());
|
||||
}
|
||||
if(q == 0)
|
||||
{
|
||||
return tools::min_value<T>();
|
||||
}
|
||||
//
|
||||
// Function object, this is the functor whose root
|
||||
// we have to solve:
|
||||
//
|
||||
gamma_inva_t<T, Policy> f(z, (p < q) ? p : q, (p < q) ? false : true);
|
||||
//
|
||||
// Tolerance: full precision.
|
||||
//
|
||||
tools::eps_tolerance<T> tol(policies::digits<T, Policy>());
|
||||
//
|
||||
// Now figure out a starting guess for what a may be,
|
||||
// we'll start out with a value that'll put p or q
|
||||
// right bang in the middle of their range, the functions
|
||||
// are quite sensitive so we should need too many steps
|
||||
// to bracket the root from there:
|
||||
//
|
||||
T guess;
|
||||
T factor = 8;
|
||||
if(z >= 1)
|
||||
{
|
||||
//
|
||||
// We can use the relationship between the incomplete
|
||||
// gamma function and the poisson distribution to
|
||||
// calculate an approximate inverse, for large z
|
||||
// this is actually pretty accurate, but it fails badly
|
||||
// when z is very small. Also set our step-factor according
|
||||
// to how accurate we think the result is likely to be:
|
||||
//
|
||||
guess = 1 + inverse_poisson_cornish_fisher(z, q, p, pol);
|
||||
if(z > 5)
|
||||
{
|
||||
if(z > 1000)
|
||||
factor = 1.01f;
|
||||
else if(z > 50)
|
||||
factor = 1.1f;
|
||||
else if(guess > 10)
|
||||
factor = 1.25f;
|
||||
else
|
||||
factor = 2;
|
||||
if(guess < 1.1)
|
||||
factor = 8;
|
||||
}
|
||||
}
|
||||
else if(z > 0.5)
|
||||
{
|
||||
guess = z * 1.2f;
|
||||
}
|
||||
else
|
||||
{
|
||||
guess = -0.4f / log(z);
|
||||
}
|
||||
//
|
||||
// Max iterations permitted:
|
||||
//
|
||||
boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
|
||||
//
|
||||
// Use our generic derivative-free root finding procedure.
|
||||
// We could use Newton steps here, taking the PDF of the
|
||||
// Poisson distribution as our derivative, but that's
|
||||
// even worse performance-wise than the generic method :-(
|
||||
//
|
||||
std::pair<T, T> r = bracket_and_solve_root(f, guess, factor, false, tol, max_iter, pol);
|
||||
if(max_iter >= policies::get_max_root_iterations<Policy>())
|
||||
return policies::raise_evaluation_error<T>("boost::math::gamma_p_inva<%1%>(%1%, %1%)", "Unable to locate the root within a reasonable number of iterations, closest approximation so far was %1%", r.first, pol);
|
||||
return (r.first + r.second) / 2;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class T1, class T2, class Policy>
|
||||
inline typename tools::promote_args<T1, T2>::type
|
||||
gamma_p_inva(T1 x, T2 p, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T1, T2>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
typedef typename policies::normalise<
|
||||
Policy,
|
||||
policies::promote_float<false>,
|
||||
policies::promote_double<false>,
|
||||
policies::discrete_quantile<>,
|
||||
policies::assert_undefined<> >::type forwarding_policy;
|
||||
|
||||
if(p == 0)
|
||||
{
|
||||
policies::raise_overflow_error<result_type>("boost::math::gamma_p_inva<%1%>(%1%, %1%)", 0, Policy());
|
||||
}
|
||||
if(p == 1)
|
||||
{
|
||||
return tools::min_value<result_type>();
|
||||
}
|
||||
|
||||
return policies::checked_narrowing_cast<result_type, forwarding_policy>(
|
||||
detail::gamma_inva_imp(
|
||||
static_cast<value_type>(x),
|
||||
static_cast<value_type>(p),
|
||||
static_cast<value_type>(1 - static_cast<value_type>(p)),
|
||||
pol), "boost::math::gamma_p_inva<%1%>(%1%, %1%)");
|
||||
}
|
||||
|
||||
template <class T1, class T2, class Policy>
|
||||
inline typename tools::promote_args<T1, T2>::type
|
||||
gamma_q_inva(T1 x, T2 q, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T1, T2>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
typedef typename policies::normalise<
|
||||
Policy,
|
||||
policies::promote_float<false>,
|
||||
policies::promote_double<false>,
|
||||
policies::discrete_quantile<>,
|
||||
policies::assert_undefined<> >::type forwarding_policy;
|
||||
|
||||
if(q == 1)
|
||||
{
|
||||
policies::raise_overflow_error<result_type>("boost::math::gamma_q_inva<%1%>(%1%, %1%)", 0, Policy());
|
||||
}
|
||||
if(q == 0)
|
||||
{
|
||||
return tools::min_value<result_type>();
|
||||
}
|
||||
|
||||
return policies::checked_narrowing_cast<result_type, forwarding_policy>(
|
||||
detail::gamma_inva_imp(
|
||||
static_cast<value_type>(x),
|
||||
static_cast<value_type>(1 - static_cast<value_type>(q)),
|
||||
static_cast<value_type>(q),
|
||||
pol), "boost::math::gamma_q_inva<%1%>(%1%, %1%)");
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
inline typename tools::promote_args<T1, T2>::type
|
||||
gamma_p_inva(T1 x, T2 p)
|
||||
{
|
||||
return boost::math::gamma_p_inva(x, p, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
inline typename tools::promote_args<T1, T2>::type
|
||||
gamma_q_inva(T1 x, T2 q)
|
||||
{
|
||||
return boost::math::gamma_q_inva(x, q, policies::policy<>());
|
||||
}
|
||||
|
||||
} // namespace math
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_MATH_SP_DETAIL_GAMMA_INVA
|
||||
|
||||
|
||||
|
||||
328
code_isotrope/boost/math/special_functions/detail/ibeta_inv_ab.hpp
Executable file
328
code_isotrope/boost/math/special_functions/detail/ibeta_inv_ab.hpp
Executable file
@@ -0,0 +1,328 @@
|
||||
// (C) Copyright John Maddock 2006.
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
//
|
||||
// This is not a complete header file, it is included by beta.hpp
|
||||
// after it has defined it's definitions. This inverts the incomplete
|
||||
// beta functions ibeta and ibetac on the first parameters "a"
|
||||
// and "b" using a generic root finding algorithm (TOMS Algorithm 748).
|
||||
//
|
||||
|
||||
#ifndef BOOST_MATH_SP_DETAIL_BETA_INV_AB
|
||||
#define BOOST_MATH_SP_DETAIL_BETA_INV_AB
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/tools/toms748_solve.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
|
||||
namespace boost{ namespace math{ namespace detail{
|
||||
|
||||
template <class T, class Policy>
|
||||
struct beta_inv_ab_t
|
||||
{
|
||||
beta_inv_ab_t(T b_, T z_, T p_, bool invert_, bool swap_ab_) : b(b_), z(z_), p(p_), invert(invert_), swap_ab(swap_ab_) {}
|
||||
T operator()(T a)
|
||||
{
|
||||
return invert ?
|
||||
p - boost::math::ibetac(swap_ab ? b : a, swap_ab ? a : b, z, Policy())
|
||||
: boost::math::ibeta(swap_ab ? b : a, swap_ab ? a : b, z, Policy()) - p;
|
||||
}
|
||||
private:
|
||||
T b, z, p;
|
||||
bool invert, swap_ab;
|
||||
};
|
||||
|
||||
template <class T, class Policy>
|
||||
T inverse_negative_binomial_cornish_fisher(T n, T sf, T sfc, T p, T q, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
// mean:
|
||||
T m = n * (sfc) / sf;
|
||||
T t = sqrt(n * (sfc));
|
||||
// standard deviation:
|
||||
T sigma = t / sf;
|
||||
// skewness
|
||||
T sk = (1 + sfc) / t;
|
||||
// kurtosis:
|
||||
T k = (6 - sf * (5+sfc)) / (n * (sfc));
|
||||
// Get the inverse of a std normal distribution:
|
||||
T x = boost::math::erfc_inv(p > q ? 2 * q : 2 * p, pol) * constants::root_two<T>();
|
||||
// Set the sign:
|
||||
if(p < 0.5)
|
||||
x = -x;
|
||||
T x2 = x * x;
|
||||
// w is correction term due to skewness
|
||||
T w = x + sk * (x2 - 1) / 6;
|
||||
//
|
||||
// Add on correction due to kurtosis.
|
||||
//
|
||||
if(n >= 10)
|
||||
w += k * x * (x2 - 3) / 24 + sk * sk * x * (2 * x2 - 5) / -36;
|
||||
|
||||
w = m + sigma * w;
|
||||
if(w < tools::min_value<T>())
|
||||
return tools::min_value<T>();
|
||||
return w;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
T ibeta_inv_ab_imp(const T& b, const T& z, const T& p, const T& q, bool swap_ab, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING // for ADL of std lib math functions
|
||||
//
|
||||
// Special cases first:
|
||||
//
|
||||
BOOST_MATH_INSTRUMENT_CODE("b = " << b << " z = " << z << " p = " << p << " q = " << " swap = " << swap_ab);
|
||||
if(p == 0)
|
||||
{
|
||||
return swap_ab ? tools::min_value<T>() : tools::max_value<T>();
|
||||
}
|
||||
if(q == 0)
|
||||
{
|
||||
return swap_ab ? tools::max_value<T>() : tools::min_value<T>();
|
||||
}
|
||||
//
|
||||
// Function object, this is the functor whose root
|
||||
// we have to solve:
|
||||
//
|
||||
beta_inv_ab_t<T, Policy> f(b, z, (p < q) ? p : q, (p < q) ? false : true, swap_ab);
|
||||
//
|
||||
// Tolerance: full precision.
|
||||
//
|
||||
tools::eps_tolerance<T> tol(policies::digits<T, Policy>());
|
||||
//
|
||||
// Now figure out a starting guess for what a may be,
|
||||
// we'll start out with a value that'll put p or q
|
||||
// right bang in the middle of their range, the functions
|
||||
// are quite sensitive so we should need too many steps
|
||||
// to bracket the root from there:
|
||||
//
|
||||
T guess = 0;
|
||||
T factor = 5;
|
||||
//
|
||||
// Convert variables to parameters of a negative binomial distribution:
|
||||
//
|
||||
T n = b;
|
||||
T sf = swap_ab ? z : 1-z;
|
||||
T sfc = swap_ab ? 1-z : z;
|
||||
T u = swap_ab ? p : q;
|
||||
T v = swap_ab ? q : p;
|
||||
if(u <= pow(sf, n))
|
||||
{
|
||||
//
|
||||
// Result is less than 1, negative binomial approximation
|
||||
// is useless....
|
||||
//
|
||||
if((p < q) != swap_ab)
|
||||
{
|
||||
guess = (std::min)(T(b * 2), T(1));
|
||||
}
|
||||
else
|
||||
{
|
||||
guess = (std::min)(T(b / 2), T(1));
|
||||
}
|
||||
}
|
||||
if(n * n * n * u * sf > 0.005)
|
||||
guess = 1 + inverse_negative_binomial_cornish_fisher(n, sf, sfc, u, v, pol);
|
||||
|
||||
if(guess < 10)
|
||||
{
|
||||
//
|
||||
// Negative binomial approximation not accurate in this area:
|
||||
//
|
||||
if((p < q) != swap_ab)
|
||||
{
|
||||
guess = (std::min)(T(b * 2), T(10));
|
||||
}
|
||||
else
|
||||
{
|
||||
guess = (std::min)(T(b / 2), T(10));
|
||||
}
|
||||
}
|
||||
else
|
||||
factor = (v < sqrt(tools::epsilon<T>())) ? 2 : (guess < 20 ? 1.2f : 1.1f);
|
||||
BOOST_MATH_INSTRUMENT_CODE("guess = " << guess);
|
||||
//
|
||||
// Max iterations permitted:
|
||||
//
|
||||
boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
|
||||
std::pair<T, T> r = bracket_and_solve_root(f, guess, factor, swap_ab ? true : false, tol, max_iter, pol);
|
||||
if(max_iter >= policies::get_max_root_iterations<Policy>())
|
||||
return policies::raise_evaluation_error<T>("boost::math::ibeta_invab_imp<%1%>(%1%,%1%,%1%)", "Unable to locate the root within a reasonable number of iterations, closest approximation so far was %1%", r.first, pol);
|
||||
return (r.first + r.second) / 2;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class RT1, class RT2, class RT3, class Policy>
|
||||
typename tools::promote_args<RT1, RT2, RT3>::type
|
||||
ibeta_inva(RT1 b, RT2 x, RT3 p, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<RT1, RT2, RT3>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
typedef typename policies::normalise<
|
||||
Policy,
|
||||
policies::promote_float<false>,
|
||||
policies::promote_double<false>,
|
||||
policies::discrete_quantile<>,
|
||||
policies::assert_undefined<> >::type forwarding_policy;
|
||||
|
||||
static const char* function = "boost::math::ibeta_inva<%1%>(%1%,%1%,%1%)";
|
||||
if(p == 0)
|
||||
{
|
||||
return policies::raise_overflow_error<result_type>(function, 0, Policy());
|
||||
}
|
||||
if(p == 1)
|
||||
{
|
||||
return tools::min_value<result_type>();
|
||||
}
|
||||
|
||||
return policies::checked_narrowing_cast<result_type, forwarding_policy>(
|
||||
detail::ibeta_inv_ab_imp(
|
||||
static_cast<value_type>(b),
|
||||
static_cast<value_type>(x),
|
||||
static_cast<value_type>(p),
|
||||
static_cast<value_type>(1 - static_cast<value_type>(p)),
|
||||
false, pol),
|
||||
function);
|
||||
}
|
||||
|
||||
template <class RT1, class RT2, class RT3, class Policy>
|
||||
typename tools::promote_args<RT1, RT2, RT3>::type
|
||||
ibetac_inva(RT1 b, RT2 x, RT3 q, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<RT1, RT2, RT3>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
typedef typename policies::normalise<
|
||||
Policy,
|
||||
policies::promote_float<false>,
|
||||
policies::promote_double<false>,
|
||||
policies::discrete_quantile<>,
|
||||
policies::assert_undefined<> >::type forwarding_policy;
|
||||
|
||||
static const char* function = "boost::math::ibetac_inva<%1%>(%1%,%1%,%1%)";
|
||||
if(q == 1)
|
||||
{
|
||||
return policies::raise_overflow_error<result_type>(function, 0, Policy());
|
||||
}
|
||||
if(q == 0)
|
||||
{
|
||||
return tools::min_value<result_type>();
|
||||
}
|
||||
|
||||
return policies::checked_narrowing_cast<result_type, forwarding_policy>(
|
||||
detail::ibeta_inv_ab_imp(
|
||||
static_cast<value_type>(b),
|
||||
static_cast<value_type>(x),
|
||||
static_cast<value_type>(1 - static_cast<value_type>(q)),
|
||||
static_cast<value_type>(q),
|
||||
false, pol),
|
||||
function);
|
||||
}
|
||||
|
||||
template <class RT1, class RT2, class RT3, class Policy>
|
||||
typename tools::promote_args<RT1, RT2, RT3>::type
|
||||
ibeta_invb(RT1 a, RT2 x, RT3 p, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<RT1, RT2, RT3>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
typedef typename policies::normalise<
|
||||
Policy,
|
||||
policies::promote_float<false>,
|
||||
policies::promote_double<false>,
|
||||
policies::discrete_quantile<>,
|
||||
policies::assert_undefined<> >::type forwarding_policy;
|
||||
|
||||
static const char* function = "boost::math::ibeta_invb<%1%>(%1%,%1%,%1%)";
|
||||
if(p == 0)
|
||||
{
|
||||
return tools::min_value<result_type>();
|
||||
}
|
||||
if(p == 1)
|
||||
{
|
||||
return policies::raise_overflow_error<result_type>(function, 0, Policy());
|
||||
}
|
||||
|
||||
return policies::checked_narrowing_cast<result_type, forwarding_policy>(
|
||||
detail::ibeta_inv_ab_imp(
|
||||
static_cast<value_type>(a),
|
||||
static_cast<value_type>(x),
|
||||
static_cast<value_type>(p),
|
||||
static_cast<value_type>(1 - static_cast<value_type>(p)),
|
||||
true, pol),
|
||||
function);
|
||||
}
|
||||
|
||||
template <class RT1, class RT2, class RT3, class Policy>
|
||||
typename tools::promote_args<RT1, RT2, RT3>::type
|
||||
ibetac_invb(RT1 a, RT2 x, RT3 q, const Policy& pol)
|
||||
{
|
||||
static const char* function = "boost::math::ibeta_invb<%1%>(%1%, %1%, %1%)";
|
||||
typedef typename tools::promote_args<RT1, RT2, RT3>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
typedef typename policies::normalise<
|
||||
Policy,
|
||||
policies::promote_float<false>,
|
||||
policies::promote_double<false>,
|
||||
policies::discrete_quantile<>,
|
||||
policies::assert_undefined<> >::type forwarding_policy;
|
||||
|
||||
if(q == 1)
|
||||
{
|
||||
return tools::min_value<result_type>();
|
||||
}
|
||||
if(q == 0)
|
||||
{
|
||||
return policies::raise_overflow_error<result_type>(function, 0, Policy());
|
||||
}
|
||||
|
||||
return policies::checked_narrowing_cast<result_type, forwarding_policy>(
|
||||
detail::ibeta_inv_ab_imp(
|
||||
static_cast<value_type>(a),
|
||||
static_cast<value_type>(x),
|
||||
static_cast<value_type>(1 - static_cast<value_type>(q)),
|
||||
static_cast<value_type>(q),
|
||||
true, pol),
|
||||
function);
|
||||
}
|
||||
|
||||
template <class RT1, class RT2, class RT3>
|
||||
inline typename tools::promote_args<RT1, RT2, RT3>::type
|
||||
ibeta_inva(RT1 b, RT2 x, RT3 p)
|
||||
{
|
||||
return boost::math::ibeta_inva(b, x, p, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class RT1, class RT2, class RT3>
|
||||
inline typename tools::promote_args<RT1, RT2, RT3>::type
|
||||
ibetac_inva(RT1 b, RT2 x, RT3 q)
|
||||
{
|
||||
return boost::math::ibetac_inva(b, x, q, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class RT1, class RT2, class RT3>
|
||||
inline typename tools::promote_args<RT1, RT2, RT3>::type
|
||||
ibeta_invb(RT1 a, RT2 x, RT3 p)
|
||||
{
|
||||
return boost::math::ibeta_invb(a, x, p, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class RT1, class RT2, class RT3>
|
||||
inline typename tools::promote_args<RT1, RT2, RT3>::type
|
||||
ibetac_invb(RT1 a, RT2 x, RT3 q)
|
||||
{
|
||||
return boost::math::ibetac_invb(a, x, q, policies::policy<>());
|
||||
}
|
||||
|
||||
} // namespace math
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_MATH_SP_DETAIL_BETA_INV_AB
|
||||
|
||||
|
||||
|
||||
993
code_isotrope/boost/math/special_functions/detail/ibeta_inverse.hpp
Executable file
993
code_isotrope/boost/math/special_functions/detail/ibeta_inverse.hpp
Executable file
@@ -0,0 +1,993 @@
|
||||
// Copyright John Maddock 2006.
|
||||
// Copyright Paul A. Bristow 2007
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_MATH_SPECIAL_FUNCTIONS_IBETA_INVERSE_HPP
|
||||
#define BOOST_MATH_SPECIAL_FUNCTIONS_IBETA_INVERSE_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/special_functions/beta.hpp>
|
||||
#include <boost/math/special_functions/erf.hpp>
|
||||
#include <boost/math/tools/roots.hpp>
|
||||
#include <boost/math/special_functions/detail/t_distribution_inv.hpp>
|
||||
|
||||
namespace boost{ namespace math{ namespace detail{
|
||||
|
||||
//
|
||||
// Helper object used by root finding
|
||||
// code to convert eta to x.
|
||||
//
|
||||
template <class T>
|
||||
struct temme_root_finder
|
||||
{
|
||||
temme_root_finder(const T t_, const T a_) : t(t_), a(a_) {}
|
||||
|
||||
boost::math::tuple<T, T> operator()(T x)
|
||||
{
|
||||
BOOST_MATH_STD_USING // ADL of std names
|
||||
|
||||
T y = 1 - x;
|
||||
if(y == 0)
|
||||
{
|
||||
T big = tools::max_value<T>() / 4;
|
||||
return boost::math::make_tuple(static_cast<T>(-big), static_cast<T>(-big));
|
||||
}
|
||||
if(x == 0)
|
||||
{
|
||||
T big = tools::max_value<T>() / 4;
|
||||
return boost::math::make_tuple(static_cast<T>(-big), big);
|
||||
}
|
||||
T f = log(x) + a * log(y) + t;
|
||||
T f1 = (1 / x) - (a / (y));
|
||||
return boost::math::make_tuple(f, f1);
|
||||
}
|
||||
private:
|
||||
T t, a;
|
||||
};
|
||||
//
|
||||
// See:
|
||||
// "Asymptotic Inversion of the Incomplete Beta Function"
|
||||
// N.M. Temme
|
||||
// Journal of Computation and Applied Mathematics 41 (1992) 145-157.
|
||||
// Section 2.
|
||||
//
|
||||
template <class T, class Policy>
|
||||
T temme_method_1_ibeta_inverse(T a, T b, T z, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING // ADL of std names
|
||||
|
||||
const T r2 = sqrt(T(2));
|
||||
//
|
||||
// get the first approximation for eta from the inverse
|
||||
// error function (Eq: 2.9 and 2.10).
|
||||
//
|
||||
T eta0 = boost::math::erfc_inv(2 * z, pol);
|
||||
eta0 /= -sqrt(a / 2);
|
||||
|
||||
T terms[4] = { eta0 };
|
||||
T workspace[7];
|
||||
//
|
||||
// calculate powers:
|
||||
//
|
||||
T B = b - a;
|
||||
T B_2 = B * B;
|
||||
T B_3 = B_2 * B;
|
||||
//
|
||||
// Calculate correction terms:
|
||||
//
|
||||
|
||||
// See eq following 2.15:
|
||||
workspace[0] = -B * r2 / 2;
|
||||
workspace[1] = (1 - 2 * B) / 8;
|
||||
workspace[2] = -(B * r2 / 48);
|
||||
workspace[3] = T(-1) / 192;
|
||||
workspace[4] = -B * r2 / 3840;
|
||||
terms[1] = tools::evaluate_polynomial(workspace, eta0, 5);
|
||||
// Eq Following 2.17:
|
||||
workspace[0] = B * r2 * (3 * B - 2) / 12;
|
||||
workspace[1] = (20 * B_2 - 12 * B + 1) / 128;
|
||||
workspace[2] = B * r2 * (20 * B - 1) / 960;
|
||||
workspace[3] = (16 * B_2 + 30 * B - 15) / 4608;
|
||||
workspace[4] = B * r2 * (21 * B + 32) / 53760;
|
||||
workspace[5] = (-32 * B_2 + 63) / 368640;
|
||||
workspace[6] = -B * r2 * (120 * B + 17) / 25804480;
|
||||
terms[2] = tools::evaluate_polynomial(workspace, eta0, 7);
|
||||
// Eq Following 2.17:
|
||||
workspace[0] = B * r2 * (-75 * B_2 + 80 * B - 16) / 480;
|
||||
workspace[1] = (-1080 * B_3 + 868 * B_2 - 90 * B - 45) / 9216;
|
||||
workspace[2] = B * r2 * (-1190 * B_2 + 84 * B + 373) / 53760;
|
||||
workspace[3] = (-2240 * B_3 - 2508 * B_2 + 2100 * B - 165) / 368640;
|
||||
terms[3] = tools::evaluate_polynomial(workspace, eta0, 4);
|
||||
//
|
||||
// Bring them together to get a final estimate for eta:
|
||||
//
|
||||
T eta = tools::evaluate_polynomial(terms, T(1/a), 4);
|
||||
//
|
||||
// now we need to convert eta to x, by solving the appropriate
|
||||
// quadratic equation:
|
||||
//
|
||||
T eta_2 = eta * eta;
|
||||
T c = -exp(-eta_2 / 2);
|
||||
T x;
|
||||
if(eta_2 == 0)
|
||||
x = 0.5;
|
||||
else
|
||||
x = (1 + eta * sqrt((1 + c) / eta_2)) / 2;
|
||||
|
||||
BOOST_ASSERT(x >= 0);
|
||||
BOOST_ASSERT(x <= 1);
|
||||
BOOST_ASSERT(eta * (x - 0.5) >= 0);
|
||||
#ifdef BOOST_INSTRUMENT
|
||||
std::cout << "Estimating x with Temme method 1: " << x << std::endl;
|
||||
#endif
|
||||
return x;
|
||||
}
|
||||
//
|
||||
// See:
|
||||
// "Asymptotic Inversion of the Incomplete Beta Function"
|
||||
// N.M. Temme
|
||||
// Journal of Computation and Applied Mathematics 41 (1992) 145-157.
|
||||
// Section 3.
|
||||
//
|
||||
template <class T, class Policy>
|
||||
T temme_method_2_ibeta_inverse(T /*a*/, T /*b*/, T z, T r, T theta, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING // ADL of std names
|
||||
|
||||
//
|
||||
// Get first estimate for eta, see Eq 3.9 and 3.10,
|
||||
// but note there is a typo in Eq 3.10:
|
||||
//
|
||||
T eta0 = boost::math::erfc_inv(2 * z, pol);
|
||||
eta0 /= -sqrt(r / 2);
|
||||
|
||||
T s = sin(theta);
|
||||
T c = cos(theta);
|
||||
//
|
||||
// Now we need to purturb eta0 to get eta, which we do by
|
||||
// evaluating the polynomial in 1/r at the bottom of page 151,
|
||||
// to do this we first need the error terms e1, e2 e3
|
||||
// which we'll fill into the array "terms". Since these
|
||||
// terms are themselves polynomials, we'll need another
|
||||
// array "workspace" to calculate those...
|
||||
//
|
||||
T terms[4] = { eta0 };
|
||||
T workspace[6];
|
||||
//
|
||||
// some powers of sin(theta)cos(theta) that we'll need later:
|
||||
//
|
||||
T sc = s * c;
|
||||
T sc_2 = sc * sc;
|
||||
T sc_3 = sc_2 * sc;
|
||||
T sc_4 = sc_2 * sc_2;
|
||||
T sc_5 = sc_2 * sc_3;
|
||||
T sc_6 = sc_3 * sc_3;
|
||||
T sc_7 = sc_4 * sc_3;
|
||||
//
|
||||
// Calculate e1 and put it in terms[1], see the middle of page 151:
|
||||
//
|
||||
workspace[0] = (2 * s * s - 1) / (3 * s * c);
|
||||
static const BOOST_MATH_INT_TABLE_TYPE(T, int) co1[] = { -1, -5, 5 };
|
||||
workspace[1] = -tools::evaluate_even_polynomial(co1, s, 3) / (36 * sc_2);
|
||||
static const BOOST_MATH_INT_TABLE_TYPE(T, int) co2[] = { 1, 21, -69, 46 };
|
||||
workspace[2] = tools::evaluate_even_polynomial(co2, s, 4) / (1620 * sc_3);
|
||||
static const BOOST_MATH_INT_TABLE_TYPE(T, int) co3[] = { 7, -2, 33, -62, 31 };
|
||||
workspace[3] = -tools::evaluate_even_polynomial(co3, s, 5) / (6480 * sc_4);
|
||||
static const BOOST_MATH_INT_TABLE_TYPE(T, int) co4[] = { 25, -52, -17, 88, -115, 46 };
|
||||
workspace[4] = tools::evaluate_even_polynomial(co4, s, 6) / (90720 * sc_5);
|
||||
terms[1] = tools::evaluate_polynomial(workspace, eta0, 5);
|
||||
//
|
||||
// Now evaluate e2 and put it in terms[2]:
|
||||
//
|
||||
static const BOOST_MATH_INT_TABLE_TYPE(T, int) co5[] = { 7, 12, -78, 52 };
|
||||
workspace[0] = -tools::evaluate_even_polynomial(co5, s, 4) / (405 * sc_3);
|
||||
static const BOOST_MATH_INT_TABLE_TYPE(T, int) co6[] = { -7, 2, 183, -370, 185 };
|
||||
workspace[1] = tools::evaluate_even_polynomial(co6, s, 5) / (2592 * sc_4);
|
||||
static const BOOST_MATH_INT_TABLE_TYPE(T, int) co7[] = { -533, 776, -1835, 10240, -13525, 5410 };
|
||||
workspace[2] = -tools::evaluate_even_polynomial(co7, s, 6) / (204120 * sc_5);
|
||||
static const BOOST_MATH_INT_TABLE_TYPE(T, int) co8[] = { -1579, 3747, -3372, -15821, 45588, -45213, 15071 };
|
||||
workspace[3] = -tools::evaluate_even_polynomial(co8, s, 7) / (2099520 * sc_6);
|
||||
terms[2] = tools::evaluate_polynomial(workspace, eta0, 4);
|
||||
//
|
||||
// And e3, and put it in terms[3]:
|
||||
//
|
||||
static const BOOST_MATH_INT_TABLE_TYPE(T, int) co9[] = {449, -1259, -769, 6686, -9260, 3704 };
|
||||
workspace[0] = tools::evaluate_even_polynomial(co9, s, 6) / (102060 * sc_5);
|
||||
static const BOOST_MATH_INT_TABLE_TYPE(T, int) co10[] = { 63149, -151557, 140052, -727469, 2239932, -2251437, 750479 };
|
||||
workspace[1] = -tools::evaluate_even_polynomial(co10, s, 7) / (20995200 * sc_6);
|
||||
static const BOOST_MATH_INT_TABLE_TYPE(T, int) co11[] = { 29233, -78755, 105222, 146879, -1602610, 3195183, -2554139, 729754 };
|
||||
workspace[2] = tools::evaluate_even_polynomial(co11, s, 8) / (36741600 * sc_7);
|
||||
terms[3] = tools::evaluate_polynomial(workspace, eta0, 3);
|
||||
//
|
||||
// Bring the correction terms together to evaluate eta,
|
||||
// this is the last equation on page 151:
|
||||
//
|
||||
T eta = tools::evaluate_polynomial(terms, T(1/r), 4);
|
||||
//
|
||||
// Now that we have eta we need to back solve for x,
|
||||
// we seek the value of x that gives eta in Eq 3.2.
|
||||
// The two methods used are described in section 5.
|
||||
//
|
||||
// Begin by defining a few variables we'll need later:
|
||||
//
|
||||
T x;
|
||||
T s_2 = s * s;
|
||||
T c_2 = c * c;
|
||||
T alpha = c / s;
|
||||
alpha *= alpha;
|
||||
T lu = (-(eta * eta) / (2 * s_2) + log(s_2) + c_2 * log(c_2) / s_2);
|
||||
//
|
||||
// Temme doesn't specify what value to switch on here,
|
||||
// but this seems to work pretty well:
|
||||
//
|
||||
if(fabs(eta) < 0.7)
|
||||
{
|
||||
//
|
||||
// Small eta use the expansion Temme gives in the second equation
|
||||
// of section 5, it's a polynomial in eta:
|
||||
//
|
||||
workspace[0] = s * s;
|
||||
workspace[1] = s * c;
|
||||
workspace[2] = (1 - 2 * workspace[0]) / 3;
|
||||
static const BOOST_MATH_INT_TABLE_TYPE(T, int) co12[] = { 1, -13, 13 };
|
||||
workspace[3] = tools::evaluate_polynomial(co12, workspace[0], 3) / (36 * s * c);
|
||||
static const BOOST_MATH_INT_TABLE_TYPE(T, int) co13[] = { 1, 21, -69, 46 };
|
||||
workspace[4] = tools::evaluate_polynomial(co13, workspace[0], 4) / (270 * workspace[0] * c * c);
|
||||
x = tools::evaluate_polynomial(workspace, eta, 5);
|
||||
#ifdef BOOST_INSTRUMENT
|
||||
std::cout << "Estimating x with Temme method 2 (small eta): " << x << std::endl;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// If eta is large we need to solve Eq 3.2 more directly,
|
||||
// begin by getting an initial approximation for x from
|
||||
// the last equation on page 155, this is a polynomial in u:
|
||||
//
|
||||
T u = exp(lu);
|
||||
workspace[0] = u;
|
||||
workspace[1] = alpha;
|
||||
workspace[2] = 0;
|
||||
workspace[3] = 3 * alpha * (3 * alpha + 1) / 6;
|
||||
workspace[4] = 4 * alpha * (4 * alpha + 1) * (4 * alpha + 2) / 24;
|
||||
workspace[5] = 5 * alpha * (5 * alpha + 1) * (5 * alpha + 2) * (5 * alpha + 3) / 120;
|
||||
x = tools::evaluate_polynomial(workspace, u, 6);
|
||||
//
|
||||
// At this point we may or may not have the right answer, Eq-3.2 has
|
||||
// two solutions for x for any given eta, however the mapping in 3.2
|
||||
// is 1:1 with the sign of eta and x-sin^2(theta) being the same.
|
||||
// So we can check if we have the right root of 3.2, and if not
|
||||
// switch x for 1-x. This transformation is motivated by the fact
|
||||
// that the distribution is *almost* symetric so 1-x will be in the right
|
||||
// ball park for the solution:
|
||||
//
|
||||
if((x - s_2) * eta < 0)
|
||||
x = 1 - x;
|
||||
#ifdef BOOST_INSTRUMENT
|
||||
std::cout << "Estimating x with Temme method 2 (large eta): " << x << std::endl;
|
||||
#endif
|
||||
}
|
||||
//
|
||||
// The final step is a few Newton-Raphson iterations to
|
||||
// clean up our approximation for x, this is pretty cheap
|
||||
// in general, and very cheap compared to an incomplete beta
|
||||
// evaluation. The limits set on x come from the observation
|
||||
// that the sign of eta and x-sin^2(theta) are the same.
|
||||
//
|
||||
T lower, upper;
|
||||
if(eta < 0)
|
||||
{
|
||||
lower = 0;
|
||||
upper = s_2;
|
||||
}
|
||||
else
|
||||
{
|
||||
lower = s_2;
|
||||
upper = 1;
|
||||
}
|
||||
//
|
||||
// If our initial approximation is out of bounds then bisect:
|
||||
//
|
||||
if((x < lower) || (x > upper))
|
||||
x = (lower+upper) / 2;
|
||||
//
|
||||
// And iterate:
|
||||
//
|
||||
x = tools::newton_raphson_iterate(
|
||||
temme_root_finder<T>(-lu, alpha), x, lower, upper, policies::digits<T, Policy>() / 2);
|
||||
|
||||
return x;
|
||||
}
|
||||
//
|
||||
// See:
|
||||
// "Asymptotic Inversion of the Incomplete Beta Function"
|
||||
// N.M. Temme
|
||||
// Journal of Computation and Applied Mathematics 41 (1992) 145-157.
|
||||
// Section 4.
|
||||
//
|
||||
template <class T, class Policy>
|
||||
T temme_method_3_ibeta_inverse(T a, T b, T p, T q, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING // ADL of std names
|
||||
|
||||
//
|
||||
// Begin by getting an initial approximation for the quantity
|
||||
// eta from the dominant part of the incomplete beta:
|
||||
//
|
||||
T eta0;
|
||||
if(p < q)
|
||||
eta0 = boost::math::gamma_q_inv(b, p, pol);
|
||||
else
|
||||
eta0 = boost::math::gamma_p_inv(b, q, pol);
|
||||
eta0 /= a;
|
||||
//
|
||||
// Define the variables and powers we'll need later on:
|
||||
//
|
||||
T mu = b / a;
|
||||
T w = sqrt(1 + mu);
|
||||
T w_2 = w * w;
|
||||
T w_3 = w_2 * w;
|
||||
T w_4 = w_2 * w_2;
|
||||
T w_5 = w_3 * w_2;
|
||||
T w_6 = w_3 * w_3;
|
||||
T w_7 = w_4 * w_3;
|
||||
T w_8 = w_4 * w_4;
|
||||
T w_9 = w_5 * w_4;
|
||||
T w_10 = w_5 * w_5;
|
||||
T d = eta0 - mu;
|
||||
T d_2 = d * d;
|
||||
T d_3 = d_2 * d;
|
||||
T d_4 = d_2 * d_2;
|
||||
T w1 = w + 1;
|
||||
T w1_2 = w1 * w1;
|
||||
T w1_3 = w1 * w1_2;
|
||||
T w1_4 = w1_2 * w1_2;
|
||||
//
|
||||
// Now we need to compute the purturbation error terms that
|
||||
// convert eta0 to eta, these are all polynomials of polynomials.
|
||||
// Probably these should be re-written to use tabulated data
|
||||
// (see examples above), but it's less of a win in this case as we
|
||||
// need to calculate the individual powers for the denominator terms
|
||||
// anyway, so we might as well use them for the numerator-polynomials
|
||||
// as well....
|
||||
//
|
||||
// Refer to p154-p155 for the details of these expansions:
|
||||
//
|
||||
T e1 = (w + 2) * (w - 1) / (3 * w);
|
||||
e1 += (w_3 + 9 * w_2 + 21 * w + 5) * d / (36 * w_2 * w1);
|
||||
e1 -= (w_4 - 13 * w_3 + 69 * w_2 + 167 * w + 46) * d_2 / (1620 * w1_2 * w_3);
|
||||
e1 -= (7 * w_5 + 21 * w_4 + 70 * w_3 + 26 * w_2 - 93 * w - 31) * d_3 / (6480 * w1_3 * w_4);
|
||||
e1 -= (75 * w_6 + 202 * w_5 + 188 * w_4 - 888 * w_3 - 1345 * w_2 + 118 * w + 138) * d_4 / (272160 * w1_4 * w_5);
|
||||
|
||||
T e2 = (28 * w_4 + 131 * w_3 + 402 * w_2 + 581 * w + 208) * (w - 1) / (1620 * w1 * w_3);
|
||||
e2 -= (35 * w_6 - 154 * w_5 - 623 * w_4 - 1636 * w_3 - 3983 * w_2 - 3514 * w - 925) * d / (12960 * w1_2 * w_4);
|
||||
e2 -= (2132 * w_7 + 7915 * w_6 + 16821 * w_5 + 35066 * w_4 + 87490 * w_3 + 141183 * w_2 + 95993 * w + 21640) * d_2 / (816480 * w_5 * w1_3);
|
||||
e2 -= (11053 * w_8 + 53308 * w_7 + 117010 * w_6 + 163924 * w_5 + 116188 * w_4 - 258428 * w_3 - 677042 * w_2 - 481940 * w - 105497) * d_3 / (14696640 * w1_4 * w_6);
|
||||
|
||||
T e3 = -((3592 * w_7 + 8375 * w_6 - 1323 * w_5 - 29198 * w_4 - 89578 * w_3 - 154413 * w_2 - 116063 * w - 29632) * (w - 1)) / (816480 * w_5 * w1_2);
|
||||
e3 -= (442043 * w_9 + 2054169 * w_8 + 3803094 * w_7 + 3470754 * w_6 + 2141568 * w_5 - 2393568 * w_4 - 19904934 * w_3 - 34714674 * w_2 - 23128299 * w - 5253353) * d / (146966400 * w_6 * w1_3);
|
||||
e3 -= (116932 * w_10 + 819281 * w_9 + 2378172 * w_8 + 4341330 * w_7 + 6806004 * w_6 + 10622748 * w_5 + 18739500 * w_4 + 30651894 * w_3 + 30869976 * w_2 + 15431867 * w + 2919016) * d_2 / (146966400 * w1_4 * w_7);
|
||||
//
|
||||
// Combine eta0 and the error terms to compute eta (Second eqaution p155):
|
||||
//
|
||||
T eta = eta0 + e1 / a + e2 / (a * a) + e3 / (a * a * a);
|
||||
//
|
||||
// Now we need to solve Eq 4.2 to obtain x. For any given value of
|
||||
// eta there are two solutions to this equation, and since the distribtion
|
||||
// may be very skewed, these are not related by x ~ 1-x we used when
|
||||
// implementing section 3 above. However we know that:
|
||||
//
|
||||
// cross < x <= 1 ; iff eta < mu
|
||||
// x == cross ; iff eta == mu
|
||||
// 0 <= x < cross ; iff eta > mu
|
||||
//
|
||||
// Where cross == 1 / (1 + mu)
|
||||
// Many thanks to Prof Temme for clarifying this point.
|
||||
//
|
||||
// Therefore we'll just jump straight into Newton iterations
|
||||
// to solve Eq 4.2 using these bounds, and simple bisection
|
||||
// as the first guess, in practice this converges pretty quickly
|
||||
// and we only need a few digits correct anyway:
|
||||
//
|
||||
if(eta <= 0)
|
||||
eta = tools::min_value<T>();
|
||||
T u = eta - mu * log(eta) + (1 + mu) * log(1 + mu) - mu;
|
||||
T cross = 1 / (1 + mu);
|
||||
T lower = eta < mu ? cross : 0;
|
||||
T upper = eta < mu ? 1 : cross;
|
||||
T x = (lower + upper) / 2;
|
||||
x = tools::newton_raphson_iterate(
|
||||
temme_root_finder<T>(u, mu), x, lower, upper, policies::digits<T, Policy>() / 2);
|
||||
#ifdef BOOST_INSTRUMENT
|
||||
std::cout << "Estimating x with Temme method 3: " << x << std::endl;
|
||||
#endif
|
||||
return x;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
struct ibeta_roots
|
||||
{
|
||||
ibeta_roots(T _a, T _b, T t, bool inv = false)
|
||||
: a(_a), b(_b), target(t), invert(inv) {}
|
||||
|
||||
boost::math::tuple<T, T, T> operator()(T x)
|
||||
{
|
||||
BOOST_MATH_STD_USING // ADL of std names
|
||||
|
||||
BOOST_FPU_EXCEPTION_GUARD
|
||||
|
||||
T f1;
|
||||
T y = 1 - x;
|
||||
T f = ibeta_imp(a, b, x, Policy(), invert, true, &f1) - target;
|
||||
if(invert)
|
||||
f1 = -f1;
|
||||
if(y == 0)
|
||||
y = tools::min_value<T>() * 64;
|
||||
if(x == 0)
|
||||
x = tools::min_value<T>() * 64;
|
||||
|
||||
T f2 = f1 * (-y * a + (b - 2) * x + 1);
|
||||
if(fabs(f2) < y * x * tools::max_value<T>())
|
||||
f2 /= (y * x);
|
||||
if(invert)
|
||||
f2 = -f2;
|
||||
|
||||
// make sure we don't have a zero derivative:
|
||||
if(f1 == 0)
|
||||
f1 = (invert ? -1 : 1) * tools::min_value<T>() * 64;
|
||||
|
||||
return boost::math::make_tuple(f, f1, f2);
|
||||
}
|
||||
private:
|
||||
T a, b, target;
|
||||
bool invert;
|
||||
};
|
||||
|
||||
template <class T, class Policy>
|
||||
T ibeta_inv_imp(T a, T b, T p, T q, const Policy& pol, T* py)
|
||||
{
|
||||
BOOST_MATH_STD_USING // For ADL of math functions.
|
||||
|
||||
//
|
||||
// The flag invert is set to true if we swap a for b and p for q,
|
||||
// in which case the result has to be subtracted from 1:
|
||||
//
|
||||
bool invert = false;
|
||||
//
|
||||
// Handle trivial cases first:
|
||||
//
|
||||
if(q == 0)
|
||||
{
|
||||
if(py) *py = 0;
|
||||
return 1;
|
||||
}
|
||||
else if(p == 0)
|
||||
{
|
||||
if(py) *py = 1;
|
||||
return 0;
|
||||
}
|
||||
else if(a == 1)
|
||||
{
|
||||
if(b == 1)
|
||||
{
|
||||
if(py) *py = 1 - p;
|
||||
return p;
|
||||
}
|
||||
// Change things around so we can handle as b == 1 special case below:
|
||||
std::swap(a, b);
|
||||
std::swap(p, q);
|
||||
invert = true;
|
||||
}
|
||||
//
|
||||
// Depending upon which approximation method we use, we may end up
|
||||
// calculating either x or y initially (where y = 1-x):
|
||||
//
|
||||
T x = 0; // Set to a safe zero to avoid a
|
||||
// MSVC 2005 warning C4701: potentially uninitialized local variable 'x' used
|
||||
// But code inspection appears to ensure that x IS assigned whatever the code path.
|
||||
T y;
|
||||
|
||||
// For some of the methods we can put tighter bounds
|
||||
// on the result than simply [0,1]:
|
||||
//
|
||||
T lower = 0;
|
||||
T upper = 1;
|
||||
//
|
||||
// Student's T with b = 0.5 gets handled as a special case, swap
|
||||
// around if the arguments are in the "wrong" order:
|
||||
//
|
||||
if(a == 0.5f)
|
||||
{
|
||||
if(b == 0.5f)
|
||||
{
|
||||
x = sin(p * constants::half_pi<T>());
|
||||
x *= x;
|
||||
if(py)
|
||||
{
|
||||
*py = sin(q * constants::half_pi<T>());
|
||||
*py *= *py;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
else if(b > 0.5f)
|
||||
{
|
||||
std::swap(a, b);
|
||||
std::swap(p, q);
|
||||
invert = !invert;
|
||||
}
|
||||
}
|
||||
//
|
||||
// Select calculation method for the initial estimate:
|
||||
//
|
||||
if((b == 0.5f) && (a >= 0.5f) && (p != 1))
|
||||
{
|
||||
//
|
||||
// We have a Student's T distribution:
|
||||
x = find_ibeta_inv_from_t_dist(a, p, q, &y, pol);
|
||||
}
|
||||
else if(b == 1)
|
||||
{
|
||||
if(p < q)
|
||||
{
|
||||
if(a > 1)
|
||||
{
|
||||
x = pow(p, 1 / a);
|
||||
y = -boost::math::expm1(log(p) / a, pol);
|
||||
}
|
||||
else
|
||||
{
|
||||
x = pow(p, 1 / a);
|
||||
y = 1 - x;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
x = exp(boost::math::log1p(-q, pol) / a);
|
||||
y = -boost::math::expm1(boost::math::log1p(-q, pol) / a, pol);
|
||||
}
|
||||
if(invert)
|
||||
std::swap(x, y);
|
||||
if(py)
|
||||
*py = y;
|
||||
return x;
|
||||
}
|
||||
else if(a + b > 5)
|
||||
{
|
||||
//
|
||||
// When a+b is large then we can use one of Prof Temme's
|
||||
// asymptotic expansions, begin by swapping things around
|
||||
// so that p < 0.5, we do this to avoid cancellations errors
|
||||
// when p is large.
|
||||
//
|
||||
if(p > 0.5)
|
||||
{
|
||||
std::swap(a, b);
|
||||
std::swap(p, q);
|
||||
invert = !invert;
|
||||
}
|
||||
T minv = (std::min)(a, b);
|
||||
T maxv = (std::max)(a, b);
|
||||
if((sqrt(minv) > (maxv - minv)) && (minv > 5))
|
||||
{
|
||||
//
|
||||
// When a and b differ by a small amount
|
||||
// the curve is quite symmetrical and we can use an error
|
||||
// function to approximate the inverse. This is the cheapest
|
||||
// of the three Temme expantions, and the calculated value
|
||||
// for x will never be much larger than p, so we don't have
|
||||
// to worry about cancellation as long as p is small.
|
||||
//
|
||||
x = temme_method_1_ibeta_inverse(a, b, p, pol);
|
||||
y = 1 - x;
|
||||
}
|
||||
else
|
||||
{
|
||||
T r = a + b;
|
||||
T theta = asin(sqrt(a / r));
|
||||
T lambda = minv / r;
|
||||
if((lambda >= 0.2) && (lambda <= 0.8) && (r >= 10))
|
||||
{
|
||||
//
|
||||
// The second error function case is the next cheapest
|
||||
// to use, it brakes down when the result is likely to be
|
||||
// very small, if a+b is also small, but we can use a
|
||||
// cheaper expansion there in any case. As before x won't
|
||||
// be much larger than p, so as long as p is small we should
|
||||
// be free of cancellation error.
|
||||
//
|
||||
T ppa = pow(p, 1/a);
|
||||
if((ppa < 0.0025) && (a + b < 200))
|
||||
{
|
||||
x = ppa * pow(a * boost::math::beta(a, b, pol), 1/a);
|
||||
}
|
||||
else
|
||||
x = temme_method_2_ibeta_inverse(a, b, p, r, theta, pol);
|
||||
y = 1 - x;
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// If we get here then a and b are very different in magnitude
|
||||
// and we need to use the third of Temme's methods which
|
||||
// involves inverting the incomplete gamma. This is much more
|
||||
// expensive than the other methods. We also can only use this
|
||||
// method when a > b, which can lead to cancellation errors
|
||||
// if we really want y (as we will when x is close to 1), so
|
||||
// a different expansion is used in that case.
|
||||
//
|
||||
if(a < b)
|
||||
{
|
||||
std::swap(a, b);
|
||||
std::swap(p, q);
|
||||
invert = !invert;
|
||||
}
|
||||
//
|
||||
// Try and compute the easy way first:
|
||||
//
|
||||
T bet = 0;
|
||||
if(b < 2)
|
||||
bet = boost::math::beta(a, b, pol);
|
||||
if(bet != 0)
|
||||
{
|
||||
y = pow(b * q * bet, 1/b);
|
||||
x = 1 - y;
|
||||
}
|
||||
else
|
||||
y = 1;
|
||||
if(y > 1e-5)
|
||||
{
|
||||
x = temme_method_3_ibeta_inverse(a, b, p, q, pol);
|
||||
y = 1 - x;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if((a < 1) && (b < 1))
|
||||
{
|
||||
//
|
||||
// Both a and b less than 1,
|
||||
// there is a point of inflection at xs:
|
||||
//
|
||||
T xs = (1 - a) / (2 - a - b);
|
||||
//
|
||||
// Now we need to ensure that we start our iteration from the
|
||||
// right side of the inflection point:
|
||||
//
|
||||
T fs = boost::math::ibeta(a, b, xs, pol) - p;
|
||||
if(fabs(fs) / p < tools::epsilon<T>() * 3)
|
||||
{
|
||||
// The result is at the point of inflection, best just return it:
|
||||
*py = invert ? xs : 1 - xs;
|
||||
return invert ? 1-xs : xs;
|
||||
}
|
||||
if(fs < 0)
|
||||
{
|
||||
std::swap(a, b);
|
||||
std::swap(p, q);
|
||||
invert = !invert;
|
||||
xs = 1 - xs;
|
||||
}
|
||||
T xg = pow(a * p * boost::math::beta(a, b, pol), 1/a);
|
||||
x = xg / (1 + xg);
|
||||
y = 1 / (1 + xg);
|
||||
//
|
||||
// And finally we know that our result is below the inflection
|
||||
// point, so set an upper limit on our search:
|
||||
//
|
||||
if(x > xs)
|
||||
x = xs;
|
||||
upper = xs;
|
||||
}
|
||||
else if((a > 1) && (b > 1))
|
||||
{
|
||||
//
|
||||
// Small a and b, both greater than 1,
|
||||
// there is a point of inflection at xs,
|
||||
// and it's complement is xs2, we must always
|
||||
// start our iteration from the right side of the
|
||||
// point of inflection.
|
||||
//
|
||||
T xs = (a - 1) / (a + b - 2);
|
||||
T xs2 = (b - 1) / (a + b - 2);
|
||||
T ps = boost::math::ibeta(a, b, xs, pol) - p;
|
||||
|
||||
if(ps < 0)
|
||||
{
|
||||
std::swap(a, b);
|
||||
std::swap(p, q);
|
||||
std::swap(xs, xs2);
|
||||
invert = !invert;
|
||||
}
|
||||
//
|
||||
// Estimate x and y, using expm1 to get a good estimate
|
||||
// for y when it's very small:
|
||||
//
|
||||
T lx = log(p * a * boost::math::beta(a, b, pol)) / a;
|
||||
x = exp(lx);
|
||||
y = x < 0.9 ? T(1 - x) : (T)(-boost::math::expm1(lx, pol));
|
||||
|
||||
if((b < a) && (x < 0.2))
|
||||
{
|
||||
//
|
||||
// Under a limited range of circumstances we can improve
|
||||
// our estimate for x, frankly it's clear if this has much effect!
|
||||
//
|
||||
T ap1 = a - 1;
|
||||
T bm1 = b - 1;
|
||||
T a_2 = a * a;
|
||||
T a_3 = a * a_2;
|
||||
T b_2 = b * b;
|
||||
T terms[5] = { 0, 1 };
|
||||
terms[2] = bm1 / ap1;
|
||||
ap1 *= ap1;
|
||||
terms[3] = bm1 * (3 * a * b + 5 * b + a_2 - a - 4) / (2 * (a + 2) * ap1);
|
||||
ap1 *= (a + 1);
|
||||
terms[4] = bm1 * (33 * a * b_2 + 31 * b_2 + 8 * a_2 * b_2 - 30 * a * b - 47 * b + 11 * a_2 * b + 6 * a_3 * b + 18 + 4 * a - a_3 + a_2 * a_2 - 10 * a_2)
|
||||
/ (3 * (a + 3) * (a + 2) * ap1);
|
||||
x = tools::evaluate_polynomial(terms, x, 5);
|
||||
}
|
||||
//
|
||||
// And finally we know that our result is below the inflection
|
||||
// point, so set an upper limit on our search:
|
||||
//
|
||||
if(x > xs)
|
||||
x = xs;
|
||||
upper = xs;
|
||||
}
|
||||
else /*if((a <= 1) != (b <= 1))*/
|
||||
{
|
||||
//
|
||||
// If all else fails we get here, only one of a and b
|
||||
// is above 1, and a+b is small. Start by swapping
|
||||
// things around so that we have a concave curve with b > a
|
||||
// and no points of inflection in [0,1]. As long as we expect
|
||||
// x to be small then we can use the simple (and cheap) power
|
||||
// term to estimate x, but when we expect x to be large then
|
||||
// this greatly underestimates x and leaves us trying to
|
||||
// iterate "round the corner" which may take almost forever...
|
||||
//
|
||||
// We could use Temme's inverse gamma function case in that case,
|
||||
// this works really rather well (albeit expensively) even though
|
||||
// strictly speaking we're outside it's defined range.
|
||||
//
|
||||
// However it's expensive to compute, and an alternative approach
|
||||
// which models the curve as a distorted quarter circle is much
|
||||
// cheaper to compute, and still keeps the number of iterations
|
||||
// required down to a reasonable level. With thanks to Prof Temme
|
||||
// for this suggestion.
|
||||
//
|
||||
if(b < a)
|
||||
{
|
||||
std::swap(a, b);
|
||||
std::swap(p, q);
|
||||
invert = !invert;
|
||||
}
|
||||
if(pow(p, 1/a) < 0.5)
|
||||
{
|
||||
x = pow(p * a * boost::math::beta(a, b, pol), 1 / a);
|
||||
if(x == 0)
|
||||
x = boost::math::tools::min_value<T>();
|
||||
y = 1 - x;
|
||||
}
|
||||
else /*if(pow(q, 1/b) < 0.1)*/
|
||||
{
|
||||
// model a distorted quarter circle:
|
||||
y = pow(1 - pow(p, b * boost::math::beta(a, b, pol)), 1/b);
|
||||
if(y == 0)
|
||||
y = boost::math::tools::min_value<T>();
|
||||
x = 1 - y;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Now we have a guess for x (and for y) we can set things up for
|
||||
// iteration. If x > 0.5 it pays to swap things round:
|
||||
//
|
||||
if(x > 0.5)
|
||||
{
|
||||
std::swap(a, b);
|
||||
std::swap(p, q);
|
||||
std::swap(x, y);
|
||||
invert = !invert;
|
||||
T l = 1 - upper;
|
||||
T u = 1 - lower;
|
||||
lower = l;
|
||||
upper = u;
|
||||
}
|
||||
//
|
||||
// lower bound for our search:
|
||||
//
|
||||
// We're not interested in denormalised answers as these tend to
|
||||
// these tend to take up lots of iterations, given that we can't get
|
||||
// accurate derivatives in this area (they tend to be infinite).
|
||||
//
|
||||
if(lower == 0)
|
||||
{
|
||||
if(invert && (py == 0))
|
||||
{
|
||||
//
|
||||
// We're not interested in answers smaller than machine epsilon:
|
||||
//
|
||||
lower = boost::math::tools::epsilon<T>();
|
||||
if(x < lower)
|
||||
x = lower;
|
||||
}
|
||||
else
|
||||
lower = boost::math::tools::min_value<T>();
|
||||
if(x < lower)
|
||||
x = lower;
|
||||
}
|
||||
//
|
||||
// Figure out how many digits to iterate towards:
|
||||
//
|
||||
int digits = boost::math::policies::digits<T, Policy>() / 2;
|
||||
if((x < 1e-50) && ((a < 1) || (b < 1)))
|
||||
{
|
||||
//
|
||||
// If we're in a region where the first derivative is very
|
||||
// large, then we have to take care that the root-finder
|
||||
// doesn't terminate prematurely. We'll bump the precision
|
||||
// up to avoid this, but we have to take care not to set the
|
||||
// precision too high or the last few iterations will just
|
||||
// thrash around and convergence may be slow in this case.
|
||||
// Try 3/4 of machine epsilon:
|
||||
//
|
||||
digits *= 3;
|
||||
digits /= 2;
|
||||
}
|
||||
//
|
||||
// Now iterate, we can use either p or q as the target here
|
||||
// depending on which is smaller:
|
||||
//
|
||||
boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
|
||||
x = boost::math::tools::halley_iterate(
|
||||
boost::math::detail::ibeta_roots<T, Policy>(a, b, (p < q ? p : q), (p < q ? false : true)), x, lower, upper, digits, max_iter);
|
||||
policies::check_root_iterations<T>("boost::math::ibeta<%1%>(%1%, %1%, %1%)", max_iter, pol);
|
||||
//
|
||||
// We don't really want these asserts here, but they are useful for sanity
|
||||
// checking that we have the limits right, uncomment if you suspect bugs *only*.
|
||||
//
|
||||
//BOOST_ASSERT(x != upper);
|
||||
//BOOST_ASSERT((x != lower) || (x == boost::math::tools::min_value<T>()) || (x == boost::math::tools::epsilon<T>()));
|
||||
//
|
||||
// Tidy up, if we "lower" was too high then zero is the best answer we have:
|
||||
//
|
||||
if(x == lower)
|
||||
x = 0;
|
||||
if(py)
|
||||
*py = invert ? x : 1 - x;
|
||||
return invert ? 1-x : x;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class Policy>
|
||||
inline typename tools::promote_args<T1, T2, T3, T4>::type
|
||||
ibeta_inv(T1 a, T2 b, T3 p, T4* py, const Policy& pol)
|
||||
{
|
||||
static const char* function = "boost::math::ibeta_inv<%1%>(%1%,%1%,%1%)";
|
||||
BOOST_FPU_EXCEPTION_GUARD
|
||||
typedef typename tools::promote_args<T1, T2, T3, T4>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
typedef typename policies::normalise<
|
||||
Policy,
|
||||
policies::promote_float<false>,
|
||||
policies::promote_double<false>,
|
||||
policies::discrete_quantile<>,
|
||||
policies::assert_undefined<> >::type forwarding_policy;
|
||||
|
||||
if(a <= 0)
|
||||
return policies::raise_domain_error<result_type>(function, "The argument a to the incomplete beta function inverse must be greater than zero (got a=%1%).", a, pol);
|
||||
if(b <= 0)
|
||||
return policies::raise_domain_error<result_type>(function, "The argument b to the incomplete beta function inverse must be greater than zero (got b=%1%).", b, pol);
|
||||
if((p < 0) || (p > 1))
|
||||
return policies::raise_domain_error<result_type>(function, "Argument p outside the range [0,1] in the incomplete beta function inverse (got p=%1%).", p, pol);
|
||||
|
||||
value_type rx, ry;
|
||||
|
||||
rx = detail::ibeta_inv_imp(
|
||||
static_cast<value_type>(a),
|
||||
static_cast<value_type>(b),
|
||||
static_cast<value_type>(p),
|
||||
static_cast<value_type>(1 - p),
|
||||
forwarding_policy(), &ry);
|
||||
|
||||
if(py) *py = policies::checked_narrowing_cast<T4, forwarding_policy>(ry, function);
|
||||
return policies::checked_narrowing_cast<result_type, forwarding_policy>(rx, function);
|
||||
}
|
||||
|
||||
template <class T1, class T2, class T3, class T4>
|
||||
inline typename tools::promote_args<T1, T2, T3, T4>::type
|
||||
ibeta_inv(T1 a, T2 b, T3 p, T4* py)
|
||||
{
|
||||
return ibeta_inv(a, b, p, py, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T1, class T2, class T3>
|
||||
inline typename tools::promote_args<T1, T2, T3>::type
|
||||
ibeta_inv(T1 a, T2 b, T3 p)
|
||||
{
|
||||
typedef typename tools::promote_args<T1, T2, T3>::type result_type;
|
||||
return ibeta_inv(a, b, p, static_cast<result_type*>(0), policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T1, class T2, class T3, class Policy>
|
||||
inline typename tools::promote_args<T1, T2, T3>::type
|
||||
ibeta_inv(T1 a, T2 b, T3 p, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T1, T2, T3>::type result_type;
|
||||
return ibeta_inv(a, b, p, static_cast<result_type*>(0), pol);
|
||||
}
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class Policy>
|
||||
inline typename tools::promote_args<T1, T2, T3, T4>::type
|
||||
ibetac_inv(T1 a, T2 b, T3 q, T4* py, const Policy& pol)
|
||||
{
|
||||
static const char* function = "boost::math::ibetac_inv<%1%>(%1%,%1%,%1%)";
|
||||
BOOST_FPU_EXCEPTION_GUARD
|
||||
typedef typename tools::promote_args<T1, T2, T3, T4>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
typedef typename policies::normalise<
|
||||
Policy,
|
||||
policies::promote_float<false>,
|
||||
policies::promote_double<false>,
|
||||
policies::discrete_quantile<>,
|
||||
policies::assert_undefined<> >::type forwarding_policy;
|
||||
|
||||
if(a <= 0)
|
||||
return policies::raise_domain_error<result_type>(function, "The argument a to the incomplete beta function inverse must be greater than zero (got a=%1%).", a, pol);
|
||||
if(b <= 0)
|
||||
return policies::raise_domain_error<result_type>(function, "The argument b to the incomplete beta function inverse must be greater than zero (got b=%1%).", b, pol);
|
||||
if((q < 0) || (q > 1))
|
||||
return policies::raise_domain_error<result_type>(function, "Argument q outside the range [0,1] in the incomplete beta function inverse (got q=%1%).", q, pol);
|
||||
|
||||
value_type rx, ry;
|
||||
|
||||
rx = detail::ibeta_inv_imp(
|
||||
static_cast<value_type>(a),
|
||||
static_cast<value_type>(b),
|
||||
static_cast<value_type>(1 - q),
|
||||
static_cast<value_type>(q),
|
||||
forwarding_policy(), &ry);
|
||||
|
||||
if(py) *py = policies::checked_narrowing_cast<T4, forwarding_policy>(ry, function);
|
||||
return policies::checked_narrowing_cast<result_type, forwarding_policy>(rx, function);
|
||||
}
|
||||
|
||||
template <class T1, class T2, class T3, class T4>
|
||||
inline typename tools::promote_args<T1, T2, T3, T4>::type
|
||||
ibetac_inv(T1 a, T2 b, T3 q, T4* py)
|
||||
{
|
||||
return ibetac_inv(a, b, q, py, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class RT1, class RT2, class RT3>
|
||||
inline typename tools::promote_args<RT1, RT2, RT3>::type
|
||||
ibetac_inv(RT1 a, RT2 b, RT3 q)
|
||||
{
|
||||
typedef typename tools::promote_args<RT1, RT2, RT3>::type result_type;
|
||||
return ibetac_inv(a, b, q, static_cast<result_type*>(0), policies::policy<>());
|
||||
}
|
||||
|
||||
template <class RT1, class RT2, class RT3, class Policy>
|
||||
inline typename tools::promote_args<RT1, RT2, RT3>::type
|
||||
ibetac_inv(RT1 a, RT2 b, RT3 q, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<RT1, RT2, RT3>::type result_type;
|
||||
return ibetac_inv(a, b, q, static_cast<result_type*>(0), pol);
|
||||
}
|
||||
|
||||
} // namespace math
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_MATH_SPECIAL_FUNCTIONS_IGAMMA_INVERSE_HPP
|
||||
|
||||
|
||||
|
||||
|
||||
42
code_isotrope/boost/math/special_functions/detail/iconv.hpp
Executable file
42
code_isotrope/boost/math/special_functions/detail/iconv.hpp
Executable file
@@ -0,0 +1,42 @@
|
||||
// Copyright (c) 2009 John Maddock
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_MATH_ICONV_HPP
|
||||
#define BOOST_MATH_ICONV_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/special_functions/round.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
|
||||
namespace boost { namespace math { namespace detail{
|
||||
|
||||
template <class T, class Policy>
|
||||
inline int iconv_imp(T v, Policy const&, mpl::true_ const&)
|
||||
{
|
||||
return static_cast<int>(v);
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline int iconv_imp(T v, Policy const& pol, mpl::false_ const&)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
return iround(v, pol);
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline int iconv(T v, Policy const& pol)
|
||||
{
|
||||
typedef typename boost::is_convertible<T, int>::type tag_type;
|
||||
return iconv_imp(v, pol, tag_type());
|
||||
}
|
||||
|
||||
|
||||
}}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_ICONV_HPP
|
||||
|
||||
551
code_isotrope/boost/math/special_functions/detail/igamma_inverse.hpp
Executable file
551
code_isotrope/boost/math/special_functions/detail/igamma_inverse.hpp
Executable file
@@ -0,0 +1,551 @@
|
||||
// (C) Copyright John Maddock 2006.
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_MATH_SPECIAL_FUNCTIONS_IGAMMA_INVERSE_HPP
|
||||
#define BOOST_MATH_SPECIAL_FUNCTIONS_IGAMMA_INVERSE_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/tools/tuple.hpp>
|
||||
#include <boost/math/special_functions/gamma.hpp>
|
||||
#include <boost/math/special_functions/sign.hpp>
|
||||
#include <boost/math/tools/roots.hpp>
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
|
||||
namespace boost{ namespace math{
|
||||
|
||||
namespace detail{
|
||||
|
||||
template <class T>
|
||||
T find_inverse_s(T p, T q)
|
||||
{
|
||||
//
|
||||
// Computation of the Incomplete Gamma Function Ratios and their Inverse
|
||||
// ARMIDO R. DIDONATO and ALFRED H. MORRIS, JR.
|
||||
// ACM Transactions on Mathematical Software, Vol. 12, No. 4,
|
||||
// December 1986, Pages 377-393.
|
||||
//
|
||||
// See equation 32.
|
||||
//
|
||||
BOOST_MATH_STD_USING
|
||||
T t;
|
||||
if(p < 0.5)
|
||||
{
|
||||
t = sqrt(-2 * log(p));
|
||||
}
|
||||
else
|
||||
{
|
||||
t = sqrt(-2 * log(q));
|
||||
}
|
||||
static const double a[4] = { 3.31125922108741, 11.6616720288968, 4.28342155967104, 0.213623493715853 };
|
||||
static const double b[5] = { 1, 6.61053765625462, 6.40691597760039, 1.27364489782223, 0.3611708101884203e-1 };
|
||||
T s = t - tools::evaluate_polynomial(a, t) / tools::evaluate_polynomial(b, t);
|
||||
if(p < 0.5)
|
||||
s = -s;
|
||||
return s;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T didonato_SN(T a, T x, unsigned N, T tolerance = 0)
|
||||
{
|
||||
//
|
||||
// Computation of the Incomplete Gamma Function Ratios and their Inverse
|
||||
// ARMIDO R. DIDONATO and ALFRED H. MORRIS, JR.
|
||||
// ACM Transactions on Mathematical Software, Vol. 12, No. 4,
|
||||
// December 1986, Pages 377-393.
|
||||
//
|
||||
// See equation 34.
|
||||
//
|
||||
T sum = 1;
|
||||
if(N >= 1)
|
||||
{
|
||||
T partial = x / (a + 1);
|
||||
sum += partial;
|
||||
for(unsigned i = 2; i <= N; ++i)
|
||||
{
|
||||
partial *= x / (a + i);
|
||||
sum += partial;
|
||||
if(partial < tolerance)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T didonato_FN(T p, T a, T x, unsigned N, T tolerance, const Policy& pol)
|
||||
{
|
||||
//
|
||||
// Computation of the Incomplete Gamma Function Ratios and their Inverse
|
||||
// ARMIDO R. DIDONATO and ALFRED H. MORRIS, JR.
|
||||
// ACM Transactions on Mathematical Software, Vol. 12, No. 4,
|
||||
// December 1986, Pages 377-393.
|
||||
//
|
||||
// See equation 34.
|
||||
//
|
||||
BOOST_MATH_STD_USING
|
||||
T u = log(p) + boost::math::lgamma(a + 1, pol);
|
||||
return exp((u + x - log(didonato_SN(a, x, N, tolerance))) / a);
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
T find_inverse_gamma(T a, T p, T q, const Policy& pol, bool* p_has_10_digits)
|
||||
{
|
||||
//
|
||||
// In order to understand what's going on here, you will
|
||||
// need to refer to:
|
||||
//
|
||||
// Computation of the Incomplete Gamma Function Ratios and their Inverse
|
||||
// ARMIDO R. DIDONATO and ALFRED H. MORRIS, JR.
|
||||
// ACM Transactions on Mathematical Software, Vol. 12, No. 4,
|
||||
// December 1986, Pages 377-393.
|
||||
//
|
||||
BOOST_MATH_STD_USING
|
||||
|
||||
T result;
|
||||
*p_has_10_digits = false;
|
||||
|
||||
if(a == 1)
|
||||
{
|
||||
result = -log(q);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(result);
|
||||
}
|
||||
else if(a < 1)
|
||||
{
|
||||
T g = boost::math::tgamma(a, pol);
|
||||
T b = q * g;
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(g);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(b);
|
||||
if((b > 0.6) || ((b >= 0.45) && (a >= 0.3)))
|
||||
{
|
||||
// DiDonato & Morris Eq 21:
|
||||
//
|
||||
// There is a slight variation from DiDonato and Morris here:
|
||||
// the first form given here is unstable when p is close to 1,
|
||||
// making it impossible to compute the inverse of Q(a,x) for small
|
||||
// q. Fortunately the second form works perfectly well in this case.
|
||||
//
|
||||
T u;
|
||||
if((b * q > 1e-8) && (q > 1e-5))
|
||||
{
|
||||
u = pow(p * g * a, 1 / a);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(u);
|
||||
}
|
||||
else
|
||||
{
|
||||
u = exp((-q / a) - constants::euler<T>());
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(u);
|
||||
}
|
||||
result = u / (1 - (u / (a + 1)));
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(result);
|
||||
}
|
||||
else if((a < 0.3) && (b >= 0.35))
|
||||
{
|
||||
// DiDonato & Morris Eq 22:
|
||||
T t = exp(-constants::euler<T>() - b);
|
||||
T u = t * exp(t);
|
||||
result = t * exp(u);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(result);
|
||||
}
|
||||
else if((b > 0.15) || (a >= 0.3))
|
||||
{
|
||||
// DiDonato & Morris Eq 23:
|
||||
T y = -log(b);
|
||||
T u = y - (1 - a) * log(y);
|
||||
result = y - (1 - a) * log(u) - log(1 + (1 - a) / (1 + u));
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(result);
|
||||
}
|
||||
else if (b > 0.1)
|
||||
{
|
||||
// DiDonato & Morris Eq 24:
|
||||
T y = -log(b);
|
||||
T u = y - (1 - a) * log(y);
|
||||
result = y - (1 - a) * log(u) - log((u * u + 2 * (3 - a) * u + (2 - a) * (3 - a)) / (u * u + (5 - a) * u + 2));
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
// DiDonato & Morris Eq 25:
|
||||
T y = -log(b);
|
||||
T c1 = (a - 1) * log(y);
|
||||
T c1_2 = c1 * c1;
|
||||
T c1_3 = c1_2 * c1;
|
||||
T c1_4 = c1_2 * c1_2;
|
||||
T a_2 = a * a;
|
||||
T a_3 = a_2 * a;
|
||||
|
||||
T c2 = (a - 1) * (1 + c1);
|
||||
T c3 = (a - 1) * (-(c1_2 / 2) + (a - 2) * c1 + (3 * a - 5) / 2);
|
||||
T c4 = (a - 1) * ((c1_3 / 3) - (3 * a - 5) * c1_2 / 2 + (a_2 - 6 * a + 7) * c1 + (11 * a_2 - 46 * a + 47) / 6);
|
||||
T c5 = (a - 1) * (-(c1_4 / 4)
|
||||
+ (11 * a - 17) * c1_3 / 6
|
||||
+ (-3 * a_2 + 13 * a -13) * c1_2
|
||||
+ (2 * a_3 - 25 * a_2 + 72 * a - 61) * c1 / 2
|
||||
+ (25 * a_3 - 195 * a_2 + 477 * a - 379) / 12);
|
||||
|
||||
T y_2 = y * y;
|
||||
T y_3 = y_2 * y;
|
||||
T y_4 = y_2 * y_2;
|
||||
result = y + c1 + (c2 / y) + (c3 / y_2) + (c4 / y_3) + (c5 / y_4);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(result);
|
||||
if(b < 1e-28f)
|
||||
*p_has_10_digits = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// DiDonato and Morris Eq 31:
|
||||
T s = find_inverse_s(p, q);
|
||||
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(s);
|
||||
|
||||
T s_2 = s * s;
|
||||
T s_3 = s_2 * s;
|
||||
T s_4 = s_2 * s_2;
|
||||
T s_5 = s_4 * s;
|
||||
T ra = sqrt(a);
|
||||
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(ra);
|
||||
|
||||
T w = a + s * ra + (s * s -1) / 3;
|
||||
w += (s_3 - 7 * s) / (36 * ra);
|
||||
w -= (3 * s_4 + 7 * s_2 - 16) / (810 * a);
|
||||
w += (9 * s_5 + 256 * s_3 - 433 * s) / (38880 * a * ra);
|
||||
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(w);
|
||||
|
||||
if((a >= 500) && (fabs(1 - w / a) < 1e-6))
|
||||
{
|
||||
result = w;
|
||||
*p_has_10_digits = true;
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(result);
|
||||
}
|
||||
else if (p > 0.5)
|
||||
{
|
||||
if(w < 3 * a)
|
||||
{
|
||||
result = w;
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
T D = (std::max)(T(2), T(a * (a - 1)));
|
||||
T lg = boost::math::lgamma(a, pol);
|
||||
T lb = log(q) + lg;
|
||||
if(lb < -D * 2.3)
|
||||
{
|
||||
// DiDonato and Morris Eq 25:
|
||||
T y = -lb;
|
||||
T c1 = (a - 1) * log(y);
|
||||
T c1_2 = c1 * c1;
|
||||
T c1_3 = c1_2 * c1;
|
||||
T c1_4 = c1_2 * c1_2;
|
||||
T a_2 = a * a;
|
||||
T a_3 = a_2 * a;
|
||||
|
||||
T c2 = (a - 1) * (1 + c1);
|
||||
T c3 = (a - 1) * (-(c1_2 / 2) + (a - 2) * c1 + (3 * a - 5) / 2);
|
||||
T c4 = (a - 1) * ((c1_3 / 3) - (3 * a - 5) * c1_2 / 2 + (a_2 - 6 * a + 7) * c1 + (11 * a_2 - 46 * a + 47) / 6);
|
||||
T c5 = (a - 1) * (-(c1_4 / 4)
|
||||
+ (11 * a - 17) * c1_3 / 6
|
||||
+ (-3 * a_2 + 13 * a -13) * c1_2
|
||||
+ (2 * a_3 - 25 * a_2 + 72 * a - 61) * c1 / 2
|
||||
+ (25 * a_3 - 195 * a_2 + 477 * a - 379) / 12);
|
||||
|
||||
T y_2 = y * y;
|
||||
T y_3 = y_2 * y;
|
||||
T y_4 = y_2 * y_2;
|
||||
result = y + c1 + (c2 / y) + (c3 / y_2) + (c4 / y_3) + (c5 / y_4);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
// DiDonato and Morris Eq 33:
|
||||
T u = -lb + (a - 1) * log(w) - log(1 + (1 - a) / (1 + w));
|
||||
result = -lb + (a - 1) * log(u) - log(1 + (1 - a) / (1 + u));
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
T z = w;
|
||||
T ap1 = a + 1;
|
||||
T ap2 = a + 2;
|
||||
if(w < 0.15f * ap1)
|
||||
{
|
||||
// DiDonato and Morris Eq 35:
|
||||
T v = log(p) + boost::math::lgamma(ap1, pol);
|
||||
z = exp((v + w) / a);
|
||||
s = boost::math::log1p(z / ap1 * (1 + z / ap2), pol);
|
||||
z = exp((v + z - s) / a);
|
||||
s = boost::math::log1p(z / ap1 * (1 + z / ap2), pol);
|
||||
z = exp((v + z - s) / a);
|
||||
s = boost::math::log1p(z / ap1 * (1 + z / ap2 * (1 + z / (a + 3))), pol);
|
||||
z = exp((v + z - s) / a);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(z);
|
||||
}
|
||||
|
||||
if((z <= 0.01 * ap1) || (z > 0.7 * ap1))
|
||||
{
|
||||
result = z;
|
||||
if(z <= 0.002 * ap1)
|
||||
*p_has_10_digits = true;
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
// DiDonato and Morris Eq 36:
|
||||
T ls = log(didonato_SN(a, z, 100, T(1e-4)));
|
||||
T v = log(p) + boost::math::lgamma(ap1, pol);
|
||||
z = exp((v + z - ls) / a);
|
||||
result = z * (1 - (a * log(z) - z - v + ls) / (a - z));
|
||||
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
struct gamma_p_inverse_func
|
||||
{
|
||||
gamma_p_inverse_func(T a_, T p_, bool inv) : a(a_), p(p_), invert(inv)
|
||||
{
|
||||
//
|
||||
// If p is too near 1 then P(x) - p suffers from cancellation
|
||||
// errors causing our root-finding algorithms to "thrash", better
|
||||
// to invert in this case and calculate Q(x) - (1-p) instead.
|
||||
//
|
||||
// Of course if p is *very* close to 1, then the answer we get will
|
||||
// be inaccurate anyway (because there's not enough information in p)
|
||||
// but at least we will converge on the (inaccurate) answer quickly.
|
||||
//
|
||||
if(p > 0.9)
|
||||
{
|
||||
p = 1 - p;
|
||||
invert = !invert;
|
||||
}
|
||||
}
|
||||
|
||||
boost::math::tuple<T, T, T> operator()(const T& x)const
|
||||
{
|
||||
BOOST_FPU_EXCEPTION_GUARD
|
||||
//
|
||||
// Calculate P(x) - p and the first two derivates, or if the invert
|
||||
// flag is set, then Q(x) - q and it's derivatives.
|
||||
//
|
||||
typedef typename policies::evaluation<T, Policy>::type value_type;
|
||||
// typedef typename lanczos::lanczos<T, Policy>::type evaluation_type;
|
||||
typedef typename policies::normalise<
|
||||
Policy,
|
||||
policies::promote_float<false>,
|
||||
policies::promote_double<false>,
|
||||
policies::discrete_quantile<>,
|
||||
policies::assert_undefined<> >::type forwarding_policy;
|
||||
|
||||
BOOST_MATH_STD_USING // For ADL of std functions.
|
||||
|
||||
T f, f1;
|
||||
value_type ft;
|
||||
f = static_cast<T>(boost::math::detail::gamma_incomplete_imp(
|
||||
static_cast<value_type>(a),
|
||||
static_cast<value_type>(x),
|
||||
true, invert,
|
||||
forwarding_policy(), &ft));
|
||||
f1 = static_cast<T>(ft);
|
||||
T f2;
|
||||
T div = (a - x - 1) / x;
|
||||
f2 = f1;
|
||||
if((fabs(div) > 1) && (tools::max_value<T>() / fabs(div) < f2))
|
||||
{
|
||||
// overflow:
|
||||
f2 = -tools::max_value<T>() / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
f2 *= div;
|
||||
}
|
||||
|
||||
if(invert)
|
||||
{
|
||||
f1 = -f1;
|
||||
f2 = -f2;
|
||||
}
|
||||
|
||||
return boost::math::make_tuple(static_cast<T>(f - p), f1, f2);
|
||||
}
|
||||
private:
|
||||
T a, p;
|
||||
bool invert;
|
||||
};
|
||||
|
||||
template <class T, class Policy>
|
||||
T gamma_p_inv_imp(T a, T p, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING // ADL of std functions.
|
||||
|
||||
static const char* function = "boost::math::gamma_p_inv<%1%>(%1%, %1%)";
|
||||
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(a);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(p);
|
||||
|
||||
if(a <= 0)
|
||||
return policies::raise_domain_error<T>(function, "Argument a in the incomplete gamma function inverse must be >= 0 (got a=%1%).", a, pol);
|
||||
if((p < 0) || (p > 1))
|
||||
return policies::raise_domain_error<T>(function, "Probabilty must be in the range [0,1] in the incomplete gamma function inverse (got p=%1%).", p, pol);
|
||||
if(p == 1)
|
||||
return policies::raise_overflow_error<T>(function, 0, Policy());
|
||||
if(p == 0)
|
||||
return 0;
|
||||
bool has_10_digits;
|
||||
T guess = detail::find_inverse_gamma<T>(a, p, 1 - p, pol, &has_10_digits);
|
||||
if((policies::digits<T, Policy>() <= 36) && has_10_digits)
|
||||
return guess;
|
||||
T lower = tools::min_value<T>();
|
||||
if(guess <= lower)
|
||||
guess = tools::min_value<T>();
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(guess);
|
||||
//
|
||||
// Work out how many digits to converge to, normally this is
|
||||
// 2/3 of the digits in T, but if the first derivative is very
|
||||
// large convergence is slow, so we'll bump it up to full
|
||||
// precision to prevent premature termination of the root-finding routine.
|
||||
//
|
||||
unsigned digits = policies::digits<T, Policy>();
|
||||
if(digits < 30)
|
||||
{
|
||||
digits *= 2;
|
||||
digits /= 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
digits /= 2;
|
||||
digits -= 1;
|
||||
}
|
||||
if((a < 0.125) && (fabs(gamma_p_derivative(a, guess, pol)) > 1 / sqrt(tools::epsilon<T>())))
|
||||
digits = policies::digits<T, Policy>() - 2;
|
||||
//
|
||||
// Go ahead and iterate:
|
||||
//
|
||||
boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
|
||||
guess = tools::halley_iterate(
|
||||
detail::gamma_p_inverse_func<T, Policy>(a, p, false),
|
||||
guess,
|
||||
lower,
|
||||
tools::max_value<T>(),
|
||||
digits,
|
||||
max_iter);
|
||||
policies::check_root_iterations<T>(function, max_iter, pol);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(guess);
|
||||
if(guess == lower)
|
||||
guess = policies::raise_underflow_error<T>(function, "Expected result known to be non-zero, but is smaller than the smallest available number.", pol);
|
||||
return guess;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
T gamma_q_inv_imp(T a, T q, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING // ADL of std functions.
|
||||
|
||||
static const char* function = "boost::math::gamma_q_inv<%1%>(%1%, %1%)";
|
||||
|
||||
if(a <= 0)
|
||||
return policies::raise_domain_error<T>(function, "Argument a in the incomplete gamma function inverse must be >= 0 (got a=%1%).", a, pol);
|
||||
if((q < 0) || (q > 1))
|
||||
return policies::raise_domain_error<T>(function, "Probabilty must be in the range [0,1] in the incomplete gamma function inverse (got q=%1%).", q, pol);
|
||||
if(q == 0)
|
||||
return policies::raise_overflow_error<T>(function, 0, Policy());
|
||||
if(q == 1)
|
||||
return 0;
|
||||
bool has_10_digits;
|
||||
T guess = detail::find_inverse_gamma<T>(a, 1 - q, q, pol, &has_10_digits);
|
||||
if((policies::digits<T, Policy>() <= 36) && has_10_digits)
|
||||
return guess;
|
||||
T lower = tools::min_value<T>();
|
||||
if(guess <= lower)
|
||||
guess = tools::min_value<T>();
|
||||
//
|
||||
// Work out how many digits to converge to, normally this is
|
||||
// 2/3 of the digits in T, but if the first derivative is very
|
||||
// large convergence is slow, so we'll bump it up to full
|
||||
// precision to prevent premature termination of the root-finding routine.
|
||||
//
|
||||
unsigned digits = policies::digits<T, Policy>();
|
||||
if(digits < 30)
|
||||
{
|
||||
digits *= 2;
|
||||
digits /= 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
digits /= 2;
|
||||
digits -= 1;
|
||||
}
|
||||
if((a < 0.125) && (fabs(gamma_p_derivative(a, guess, pol)) > 1 / sqrt(tools::epsilon<T>())))
|
||||
digits = policies::digits<T, Policy>();
|
||||
//
|
||||
// Go ahead and iterate:
|
||||
//
|
||||
boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
|
||||
guess = tools::halley_iterate(
|
||||
detail::gamma_p_inverse_func<T, Policy>(a, q, true),
|
||||
guess,
|
||||
lower,
|
||||
tools::max_value<T>(),
|
||||
digits,
|
||||
max_iter);
|
||||
policies::check_root_iterations<T>(function, max_iter, pol);
|
||||
if(guess == lower)
|
||||
guess = policies::raise_underflow_error<T>(function, "Expected result known to be non-zero, but is smaller than the smallest available number.", pol);
|
||||
return guess;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class T1, class T2, class Policy>
|
||||
inline typename tools::promote_args<T1, T2>::type
|
||||
gamma_p_inv(T1 a, T2 p, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T1, T2>::type result_type;
|
||||
return detail::gamma_p_inv_imp(
|
||||
static_cast<result_type>(a),
|
||||
static_cast<result_type>(p), pol);
|
||||
}
|
||||
|
||||
template <class T1, class T2, class Policy>
|
||||
inline typename tools::promote_args<T1, T2>::type
|
||||
gamma_q_inv(T1 a, T2 p, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T1, T2>::type result_type;
|
||||
return detail::gamma_q_inv_imp(
|
||||
static_cast<result_type>(a),
|
||||
static_cast<result_type>(p), pol);
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
inline typename tools::promote_args<T1, T2>::type
|
||||
gamma_p_inv(T1 a, T2 p)
|
||||
{
|
||||
return gamma_p_inv(a, p, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
inline typename tools::promote_args<T1, T2>::type
|
||||
gamma_q_inv(T1 a, T2 p)
|
||||
{
|
||||
return gamma_q_inv(a, p, policies::policy<>());
|
||||
}
|
||||
|
||||
} // namespace math
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_MATH_SPECIAL_FUNCTIONS_IGAMMA_INVERSE_HPP
|
||||
|
||||
|
||||
|
||||
768
code_isotrope/boost/math/special_functions/detail/igamma_large.hpp
Executable file
768
code_isotrope/boost/math/special_functions/detail/igamma_large.hpp
Executable file
@@ -0,0 +1,768 @@
|
||||
// Copyright John Maddock 2006.
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// This file implements the asymptotic expansions of the incomplete
|
||||
// gamma functions P(a, x) and Q(a, x), used when a is large and
|
||||
// x ~ a.
|
||||
//
|
||||
// The primary reference is:
|
||||
//
|
||||
// "The Asymptotic Expansion of the Incomplete Gamma Functions"
|
||||
// N. M. Temme.
|
||||
// Siam J. Math Anal. Vol 10 No 4, July 1979, p757.
|
||||
//
|
||||
// A different way of evaluating these expansions,
|
||||
// plus a lot of very useful background information is in:
|
||||
//
|
||||
// "A Set of Algorithms For the Incomplete Gamma Functions."
|
||||
// N. M. Temme.
|
||||
// Probability in the Engineering and Informational Sciences,
|
||||
// 8, 1994, 291.
|
||||
//
|
||||
// An alternative implementation is in:
|
||||
//
|
||||
// "Computation of the Incomplete Gamma Function Ratios and their Inverse."
|
||||
// A. R. Didonato and A. H. Morris.
|
||||
// ACM TOMS, Vol 12, No 4, Dec 1986, p377.
|
||||
//
|
||||
// There are various versions of the same code below, each accurate
|
||||
// to a different precision. To understand the code, refer to Didonato
|
||||
// and Morris, from Eq 17 and 18 onwards.
|
||||
//
|
||||
// The coefficients used here are not taken from Didonato and Morris:
|
||||
// the domain over which these expansions are used is slightly different
|
||||
// to theirs, and their constants are not quite accurate enough for
|
||||
// 128-bit long double's. Instead the coefficients were calculated
|
||||
// using the methods described by Temme p762 from Eq 3.8 onwards.
|
||||
// The values obtained agree with those obtained by Didonato and Morris
|
||||
// (at least to the first 30 digits that they provide).
|
||||
// At double precision the degrees of polynomial required for full
|
||||
// machine precision are close to those recomended to Didonato and Morris,
|
||||
// but of course many more terms are needed for larger types.
|
||||
//
|
||||
#ifndef BOOST_MATH_DETAIL_IGAMMA_LARGE
|
||||
#define BOOST_MATH_DETAIL_IGAMMA_LARGE
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
namespace boost{ namespace math{ namespace detail{
|
||||
|
||||
// This version will never be called (at runtime), it's a stub used
|
||||
// when T is unsuitable to be passed to these routines:
|
||||
//
|
||||
template <class T, class Policy>
|
||||
inline T igamma_temme_large(T, T, const Policy& /* pol */, mpl::int_<0> const *)
|
||||
{
|
||||
// stub function, should never actually be called
|
||||
BOOST_ASSERT(0);
|
||||
return 0;
|
||||
}
|
||||
//
|
||||
// This version is accurate for up to 64-bit mantissa's,
|
||||
// (80-bit long double, or 10^-20).
|
||||
//
|
||||
template <class T, class Policy>
|
||||
T igamma_temme_large(T a, T x, const Policy& pol, mpl::int_<64> const *)
|
||||
{
|
||||
BOOST_MATH_STD_USING // ADL of std functions
|
||||
T sigma = (x - a) / a;
|
||||
T phi = -boost::math::log1pmx(sigma, pol);
|
||||
T y = a * phi;
|
||||
T z = sqrt(2 * phi);
|
||||
if(x < a)
|
||||
z = -z;
|
||||
|
||||
T workspace[13];
|
||||
|
||||
static const T C0[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.333333333333333333333),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.0833333333333333333333),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.0148148148148148148148),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.00115740740740740740741),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.000352733686067019400353),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.0001787551440329218107),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.39192631785224377817e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.218544851067999216147e-5),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.18540622107151599607e-5),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.829671134095308600502e-6),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.176659527368260793044e-6),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.670785354340149858037e-8),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.102618097842403080426e-7),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.438203601845335318655e-8),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.914769958223679023418e-9),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.255141939949462497669e-10),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.583077213255042506746e-10),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.243619480206674162437e-10),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.502766928011417558909e-11),
|
||||
};
|
||||
workspace[0] = tools::evaluate_polynomial(C0, z);
|
||||
|
||||
static const T C1[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.00185185185185185185185),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.00347222222222222222222),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.00264550264550264550265),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.000990226337448559670782),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.000205761316872427983539),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.40187757201646090535e-6),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.18098550334489977837e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.764916091608111008464e-5),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.161209008945634460038e-5),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.464712780280743434226e-8),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.137863344691572095931e-6),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.575254560351770496402e-7),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.119516285997781473243e-7),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.175432417197476476238e-10),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.100915437106004126275e-8),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.416279299184258263623e-9),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.856390702649298063807e-10),
|
||||
};
|
||||
workspace[1] = tools::evaluate_polynomial(C1, z);
|
||||
|
||||
static const T C2[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.00413359788359788359788),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.00268132716049382716049),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.000771604938271604938272),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.200938786008230452675e-5),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.000107366532263651605215),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.529234488291201254164e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.127606351886187277134e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.342357873409613807419e-7),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.137219573090629332056e-5),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.629899213838005502291e-6),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.142806142060642417916e-6),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.204770984219908660149e-9),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.140925299108675210533e-7),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.622897408492202203356e-8),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.136704883966171134993e-8),
|
||||
};
|
||||
workspace[2] = tools::evaluate_polynomial(C2, z);
|
||||
|
||||
static const T C3[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.000649434156378600823045),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.000229472093621399176955),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.000469189494395255712128),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.000267720632062838852962),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.756180167188397641073e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.239650511386729665193e-6),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.110826541153473023615e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.56749528269915965675e-5),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.142309007324358839146e-5),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.278610802915281422406e-10),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.169584040919302772899e-6),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.809946490538808236335e-7),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.191111684859736540607e-7),
|
||||
};
|
||||
workspace[3] = tools::evaluate_polynomial(C3, z);
|
||||
|
||||
static const T C4[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.000861888290916711698605),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.000784039221720066627474),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.000299072480303190179733),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.146384525788434181781e-5),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.664149821546512218666e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.396836504717943466443e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.113757269706784190981e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.250749722623753280165e-9),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.169541495365583060147e-5),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.890750753220530968883e-6),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.229293483400080487057e-6),
|
||||
};
|
||||
workspace[4] = tools::evaluate_polynomial(C4, z);
|
||||
|
||||
static const T C5[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.000336798553366358150309),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.697281375836585777429e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.000277275324495939207873),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.000199325705161888477003),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.679778047793720783882e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.141906292064396701483e-6),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.135940481897686932785e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.801847025633420153972e-5),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.229148117650809517038e-5),
|
||||
};
|
||||
workspace[5] = tools::evaluate_polynomial(C5, z);
|
||||
|
||||
static const T C6[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.000531307936463992223166),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.000592166437353693882865),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.000270878209671804482771),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.790235323266032787212e-6),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.815396936756196875093e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.561168275310624965004e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.183291165828433755673e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.307961345060330478256e-8),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.346515536880360908674e-5),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.20291327396058603727e-5),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.57887928631490037089e-6),
|
||||
};
|
||||
workspace[6] = tools::evaluate_polynomial(C6, z);
|
||||
|
||||
static const T C7[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.000344367606892377671254),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.517179090826059219337e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.000334931610811422363117),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.000281269515476323702274),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.000109765822446847310235),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.127410090954844853795e-6),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.277444515115636441571e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.182634888057113326614e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.578769494973505239894e-5),
|
||||
};
|
||||
workspace[7] = tools::evaluate_polynomial(C7, z);
|
||||
|
||||
static const T C8[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.000652623918595309418922),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.000839498720672087279993),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.000438297098541721005061),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.696909145842055197137e-6),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.000166448466420675478374),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.000127835176797692185853),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.462995326369130429061e-4),
|
||||
};
|
||||
workspace[8] = tools::evaluate_polynomial(C8, z);
|
||||
|
||||
static const T C9[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.000596761290192746250124),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.720489541602001055909e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.000678230883766732836162),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.0006401475260262758451),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.000277501076343287044992),
|
||||
};
|
||||
workspace[9] = tools::evaluate_polynomial(C9, z);
|
||||
|
||||
static const T C10[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.00133244544948006563713),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.0019144384985654775265),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.00110893691345966373396),
|
||||
};
|
||||
workspace[10] = tools::evaluate_polynomial(C10, z);
|
||||
|
||||
static const T C11[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.00157972766073083495909),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.000162516262783915816899),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.00206334210355432762645),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.00213896861856890981541),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.00101085593912630031708),
|
||||
};
|
||||
workspace[11] = tools::evaluate_polynomial(C11, z);
|
||||
|
||||
static const T C12[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.00407251211951401664727),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.00640336283380806979482),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.00404101610816766177474),
|
||||
};
|
||||
workspace[12] = tools::evaluate_polynomial(C12, z);
|
||||
|
||||
T result = tools::evaluate_polynomial<13, T, T>(workspace, 1/a);
|
||||
result *= exp(-y) / sqrt(2 * constants::pi<T>() * a);
|
||||
if(x < a)
|
||||
result = -result;
|
||||
|
||||
result += boost::math::erfc(sqrt(y), pol) / 2;
|
||||
|
||||
return result;
|
||||
}
|
||||
//
|
||||
// This one is accurate for 53-bit mantissa's
|
||||
// (IEEE double precision or 10^-17).
|
||||
//
|
||||
template <class T, class Policy>
|
||||
T igamma_temme_large(T a, T x, const Policy& pol, mpl::int_<53> const *)
|
||||
{
|
||||
BOOST_MATH_STD_USING // ADL of std functions
|
||||
T sigma = (x - a) / a;
|
||||
T phi = -boost::math::log1pmx(sigma, pol);
|
||||
T y = a * phi;
|
||||
T z = sqrt(2 * phi);
|
||||
if(x < a)
|
||||
z = -z;
|
||||
|
||||
T workspace[10];
|
||||
|
||||
static const T C0[] = {
|
||||
static_cast<T>(-0.33333333333333333L),
|
||||
static_cast<T>(0.083333333333333333L),
|
||||
static_cast<T>(-0.014814814814814815L),
|
||||
static_cast<T>(0.0011574074074074074L),
|
||||
static_cast<T>(0.0003527336860670194L),
|
||||
static_cast<T>(-0.00017875514403292181L),
|
||||
static_cast<T>(0.39192631785224378e-4L),
|
||||
static_cast<T>(-0.21854485106799922e-5L),
|
||||
static_cast<T>(-0.185406221071516e-5L),
|
||||
static_cast<T>(0.8296711340953086e-6L),
|
||||
static_cast<T>(-0.17665952736826079e-6L),
|
||||
static_cast<T>(0.67078535434014986e-8L),
|
||||
static_cast<T>(0.10261809784240308e-7L),
|
||||
static_cast<T>(-0.43820360184533532e-8L),
|
||||
static_cast<T>(0.91476995822367902e-9L),
|
||||
};
|
||||
workspace[0] = tools::evaluate_polynomial(C0, z);
|
||||
|
||||
static const T C1[] = {
|
||||
static_cast<T>(-0.0018518518518518519L),
|
||||
static_cast<T>(-0.0034722222222222222L),
|
||||
static_cast<T>(0.0026455026455026455L),
|
||||
static_cast<T>(-0.00099022633744855967L),
|
||||
static_cast<T>(0.00020576131687242798L),
|
||||
static_cast<T>(-0.40187757201646091e-6L),
|
||||
static_cast<T>(-0.18098550334489978e-4L),
|
||||
static_cast<T>(0.76491609160811101e-5L),
|
||||
static_cast<T>(-0.16120900894563446e-5L),
|
||||
static_cast<T>(0.46471278028074343e-8L),
|
||||
static_cast<T>(0.1378633446915721e-6L),
|
||||
static_cast<T>(-0.5752545603517705e-7L),
|
||||
static_cast<T>(0.11951628599778147e-7L),
|
||||
};
|
||||
workspace[1] = tools::evaluate_polynomial(C1, z);
|
||||
|
||||
static const T C2[] = {
|
||||
static_cast<T>(0.0041335978835978836L),
|
||||
static_cast<T>(-0.0026813271604938272L),
|
||||
static_cast<T>(0.00077160493827160494L),
|
||||
static_cast<T>(0.20093878600823045e-5L),
|
||||
static_cast<T>(-0.00010736653226365161L),
|
||||
static_cast<T>(0.52923448829120125e-4L),
|
||||
static_cast<T>(-0.12760635188618728e-4L),
|
||||
static_cast<T>(0.34235787340961381e-7L),
|
||||
static_cast<T>(0.13721957309062933e-5L),
|
||||
static_cast<T>(-0.6298992138380055e-6L),
|
||||
static_cast<T>(0.14280614206064242e-6L),
|
||||
};
|
||||
workspace[2] = tools::evaluate_polynomial(C2, z);
|
||||
|
||||
static const T C3[] = {
|
||||
static_cast<T>(0.00064943415637860082L),
|
||||
static_cast<T>(0.00022947209362139918L),
|
||||
static_cast<T>(-0.00046918949439525571L),
|
||||
static_cast<T>(0.00026772063206283885L),
|
||||
static_cast<T>(-0.75618016718839764e-4L),
|
||||
static_cast<T>(-0.23965051138672967e-6L),
|
||||
static_cast<T>(0.11082654115347302e-4L),
|
||||
static_cast<T>(-0.56749528269915966e-5L),
|
||||
static_cast<T>(0.14230900732435884e-5L),
|
||||
};
|
||||
workspace[3] = tools::evaluate_polynomial(C3, z);
|
||||
|
||||
static const T C4[] = {
|
||||
static_cast<T>(-0.0008618882909167117L),
|
||||
static_cast<T>(0.00078403922172006663L),
|
||||
static_cast<T>(-0.00029907248030319018L),
|
||||
static_cast<T>(-0.14638452578843418e-5L),
|
||||
static_cast<T>(0.66414982154651222e-4L),
|
||||
static_cast<T>(-0.39683650471794347e-4L),
|
||||
static_cast<T>(0.11375726970678419e-4L),
|
||||
};
|
||||
workspace[4] = tools::evaluate_polynomial(C4, z);
|
||||
|
||||
static const T C5[] = {
|
||||
static_cast<T>(-0.00033679855336635815L),
|
||||
static_cast<T>(-0.69728137583658578e-4L),
|
||||
static_cast<T>(0.00027727532449593921L),
|
||||
static_cast<T>(-0.00019932570516188848L),
|
||||
static_cast<T>(0.67977804779372078e-4L),
|
||||
static_cast<T>(0.1419062920643967e-6L),
|
||||
static_cast<T>(-0.13594048189768693e-4L),
|
||||
static_cast<T>(0.80184702563342015e-5L),
|
||||
static_cast<T>(-0.22914811765080952e-5L),
|
||||
};
|
||||
workspace[5] = tools::evaluate_polynomial(C5, z);
|
||||
|
||||
static const T C6[] = {
|
||||
static_cast<T>(0.00053130793646399222L),
|
||||
static_cast<T>(-0.00059216643735369388L),
|
||||
static_cast<T>(0.00027087820967180448L),
|
||||
static_cast<T>(0.79023532326603279e-6L),
|
||||
static_cast<T>(-0.81539693675619688e-4L),
|
||||
static_cast<T>(0.56116827531062497e-4L),
|
||||
static_cast<T>(-0.18329116582843376e-4L),
|
||||
};
|
||||
workspace[6] = tools::evaluate_polynomial(C6, z);
|
||||
|
||||
static const T C7[] = {
|
||||
static_cast<T>(0.00034436760689237767L),
|
||||
static_cast<T>(0.51717909082605922e-4L),
|
||||
static_cast<T>(-0.00033493161081142236L),
|
||||
static_cast<T>(0.0002812695154763237L),
|
||||
static_cast<T>(-0.00010976582244684731L),
|
||||
};
|
||||
workspace[7] = tools::evaluate_polynomial(C7, z);
|
||||
|
||||
static const T C8[] = {
|
||||
static_cast<T>(-0.00065262391859530942L),
|
||||
static_cast<T>(0.00083949872067208728L),
|
||||
static_cast<T>(-0.00043829709854172101L),
|
||||
};
|
||||
workspace[8] = tools::evaluate_polynomial(C8, z);
|
||||
workspace[9] = static_cast<T>(-0.00059676129019274625L);
|
||||
|
||||
T result = tools::evaluate_polynomial<10, T, T>(workspace, 1/a);
|
||||
result *= exp(-y) / sqrt(2 * constants::pi<T>() * a);
|
||||
if(x < a)
|
||||
result = -result;
|
||||
|
||||
result += boost::math::erfc(sqrt(y), pol) / 2;
|
||||
|
||||
return result;
|
||||
}
|
||||
//
|
||||
// This one is accurate for 24-bit mantissa's
|
||||
// (IEEE float precision, or 10^-8)
|
||||
//
|
||||
template <class T, class Policy>
|
||||
T igamma_temme_large(T a, T x, const Policy& pol, mpl::int_<24> const *)
|
||||
{
|
||||
BOOST_MATH_STD_USING // ADL of std functions
|
||||
T sigma = (x - a) / a;
|
||||
T phi = -boost::math::log1pmx(sigma, pol);
|
||||
T y = a * phi;
|
||||
T z = sqrt(2 * phi);
|
||||
if(x < a)
|
||||
z = -z;
|
||||
|
||||
T workspace[3];
|
||||
|
||||
static const T C0[] = {
|
||||
static_cast<T>(-0.333333333L),
|
||||
static_cast<T>(0.0833333333L),
|
||||
static_cast<T>(-0.0148148148L),
|
||||
static_cast<T>(0.00115740741L),
|
||||
static_cast<T>(0.000352733686L),
|
||||
static_cast<T>(-0.000178755144L),
|
||||
static_cast<T>(0.391926318e-4L),
|
||||
};
|
||||
workspace[0] = tools::evaluate_polynomial(C0, z);
|
||||
|
||||
static const T C1[] = {
|
||||
static_cast<T>(-0.00185185185L),
|
||||
static_cast<T>(-0.00347222222L),
|
||||
static_cast<T>(0.00264550265L),
|
||||
static_cast<T>(-0.000990226337L),
|
||||
static_cast<T>(0.000205761317L),
|
||||
};
|
||||
workspace[1] = tools::evaluate_polynomial(C1, z);
|
||||
|
||||
static const T C2[] = {
|
||||
static_cast<T>(0.00413359788L),
|
||||
static_cast<T>(-0.00268132716L),
|
||||
static_cast<T>(0.000771604938L),
|
||||
};
|
||||
workspace[2] = tools::evaluate_polynomial(C2, z);
|
||||
|
||||
T result = tools::evaluate_polynomial(workspace, 1/a);
|
||||
result *= exp(-y) / sqrt(2 * constants::pi<T>() * a);
|
||||
if(x < a)
|
||||
result = -result;
|
||||
|
||||
result += boost::math::erfc(sqrt(y), pol) / 2;
|
||||
|
||||
return result;
|
||||
}
|
||||
//
|
||||
// And finally, a version for 113-bit mantissa's
|
||||
// (128-bit long doubles, or 10^-34).
|
||||
// Note this one has been optimised for a > 200
|
||||
// It's use for a < 200 is not recomended, that would
|
||||
// require many more terms in the polynomials.
|
||||
//
|
||||
template <class T, class Policy>
|
||||
T igamma_temme_large(T a, T x, const Policy& pol, mpl::int_<113> const *)
|
||||
{
|
||||
BOOST_MATH_STD_USING // ADL of std functions
|
||||
T sigma = (x - a) / a;
|
||||
T phi = -boost::math::log1pmx(sigma, pol);
|
||||
T y = a * phi;
|
||||
T z = sqrt(2 * phi);
|
||||
if(x < a)
|
||||
z = -z;
|
||||
|
||||
T workspace[14];
|
||||
|
||||
static const T C0[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.333333333333333333333333333333333333),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.0833333333333333333333333333333333333),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.0148148148148148148148148148148148148),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.00115740740740740740740740740740740741),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.0003527336860670194003527336860670194),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.000178755144032921810699588477366255144),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.391926317852243778169704095630021556e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.218544851067999216147364295512443661e-5),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.185406221071515996070179883622956325e-5),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.829671134095308600501624213166443227e-6),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.17665952736826079304360054245742403e-6),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.670785354340149858036939710029613572e-8),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.102618097842403080425739573227252951e-7),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.438203601845335318655297462244719123e-8),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.914769958223679023418248817633113681e-9),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.255141939949462497668779537993887013e-10),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.583077213255042506746408945040035798e-10),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.243619480206674162436940696707789943e-10),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.502766928011417558909054985925744366e-11),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.110043920319561347708374174497293411e-12),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.337176326240098537882769884169200185e-12),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.13923887224181620659193661848957998e-12),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.285348938070474432039669099052828299e-13),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.513911183424257261899064580300494205e-15),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.197522882943494428353962401580710912e-14),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.809952115670456133407115668702575255e-15),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.165225312163981618191514820265351162e-15),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.253054300974788842327061090060267385e-17),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.116869397385595765888230876507793475e-16),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.477003704982048475822167804084816597e-17),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.969912605905623712420709685898585354e-18),
|
||||
};
|
||||
workspace[0] = tools::evaluate_polynomial(C0, z);
|
||||
|
||||
static const T C1[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.00185185185185185185185185185185185185),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.00347222222222222222222222222222222222),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.0026455026455026455026455026455026455),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.000990226337448559670781893004115226337),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.000205761316872427983539094650205761317),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.401877572016460905349794238683127572e-6),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.180985503344899778370285914867533523e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.76491609160811100846374214980916921e-5),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.16120900894563446003775221882217767e-5),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.464712780280743434226135033938722401e-8),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.137863344691572095931187533077488877e-6),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.575254560351770496402194531835048307e-7),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.119516285997781473243076536699698169e-7),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.175432417197476476237547551202312502e-10),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.100915437106004126274577504686681675e-8),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.416279299184258263623372347219858628e-9),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.856390702649298063807431562579670208e-10),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.606721510160475861512701762169919581e-13),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.716249896481148539007961017165545733e-11),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.293318664377143711740636683615595403e-11),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.599669636568368872330374527568788909e-12),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.216717865273233141017100472779701734e-15),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.497833997236926164052815522048108548e-13),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.202916288237134247736694804325894226e-13),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.413125571381061004935108332558187111e-14),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.828651623988309644380188591057589316e-18),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.341003088693333279336339355910600992e-15),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.138541953028939715357034547426313703e-15),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.281234665322887466568860332727259483e-16),
|
||||
};
|
||||
workspace[1] = tools::evaluate_polynomial(C1, z);
|
||||
|
||||
static const T C2[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.0041335978835978835978835978835978836),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.00268132716049382716049382716049382716),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.000771604938271604938271604938271604938),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.200938786008230452674897119341563786e-5),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.000107366532263651605215391223621676297),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.529234488291201254164217127180090143e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.127606351886187277133779191392360117e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.34235787340961380741902003904747389e-7),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.137219573090629332055943852926020279e-5),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.629899213838005502290672234278391876e-6),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.142806142060642417915846008822771748e-6),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.204770984219908660149195854409200226e-9),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.140925299108675210532930244154315272e-7),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.622897408492202203356394293530327112e-8),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.136704883966171134992724380284402402e-8),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.942835615901467819547711211663208075e-12),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.128722524000893180595479368872770442e-9),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.556459561343633211465414765894951439e-10),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.119759355463669810035898150310311343e-10),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.416897822518386350403836626692480096e-14),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.109406404278845944099299008640802908e-11),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.4662239946390135746326204922464679e-12),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.990510576390690597844122258212382301e-13),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.189318767683735145056885183170630169e-16),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.885922187259112726176031067028740667e-14),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.373782039804640545306560251777191937e-14),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.786883363903515525774088394065960751e-15),
|
||||
};
|
||||
workspace[2] = tools::evaluate_polynomial(C2, z);
|
||||
|
||||
static const T C3[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.000649434156378600823045267489711934156),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.000229472093621399176954732510288065844),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.000469189494395255712128140111679206329),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.000267720632062838852962309752433209223),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.756180167188397641072538191879755666e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.239650511386729665193314027333231723e-6),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.110826541153473023614770299726861227e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.567495282699159656749963105701560205e-5),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.14230900732435883914551894470580433e-5),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.278610802915281422405802158211174452e-10),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.16958404091930277289864168795820267e-6),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.809946490538808236335278504852724081e-7),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.191111684859736540606728140872727635e-7),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.239286204398081179686413514022282056e-11),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.206201318154887984369925818486654549e-8),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.946049666185513217375417988510192814e-9),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.215410497757749078380130268468744512e-9),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.138882333681390304603424682490735291e-13),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.218947616819639394064123400466489455e-10),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.979099895117168512568262802255883368e-11),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.217821918801809621153859472011393244e-11),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.62088195734079014258166361684972205e-16),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.212697836327973697696702537114614471e-12),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.934468879151743333127396765626749473e-13),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.204536712267828493249215913063207436e-13),
|
||||
};
|
||||
workspace[3] = tools::evaluate_polynomial(C3, z);
|
||||
|
||||
static const T C4[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.000861888290916711698604702719929057378),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.00078403922172006662747403488144228885),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.000299072480303190179733389609932819809),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.146384525788434181781232535690697556e-5),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.664149821546512218665853782451862013e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.396836504717943466443123507595386882e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.113757269706784190980552042885831759e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.250749722623753280165221942390057007e-9),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.169541495365583060147164356781525752e-5),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.890750753220530968882898422505515924e-6),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.229293483400080487057216364891158518e-6),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.295679413754404904696572852500004588e-10),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.288658297427087836297341274604184504e-7),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.141897394378032193894774303903982717e-7),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.344635804994648970659527720474194356e-8),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.230245171745280671320192735850147087e-12),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.394092330280464052750697640085291799e-9),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.186023389685045019134258533045185639e-9),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.435632300505661804380678327446262424e-10),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.127860010162962312660550463349930726e-14),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.467927502665791946200382739991760062e-11),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.214924647061348285410535341910721086e-11),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.490881561480965216323649688463984082e-12),
|
||||
};
|
||||
workspace[4] = tools::evaluate_polynomial(C4, z);
|
||||
|
||||
static const T C5[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.000336798553366358150308767592718210002),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.697281375836585777429398828575783308e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.00027727532449593920787336425196507501),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.000199325705161888477003360405280844238),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.679778047793720783881640176604435742e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.141906292064396701483392727105575757e-6),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.135940481897686932784583938837504469e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.80184702563342015397192571980419684e-5),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.229148117650809517038048790128781806e-5),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.325247355129845395166230137750005047e-9),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.346528464910852649559195496827579815e-6),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.184471871911713432765322367374920978e-6),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.482409670378941807563762631738989002e-7),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.179894667217435153025754291716644314e-13),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.630619450001352343517516981425944698e-8),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.316241762877456793773762181540969623e-8),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.784092425369742929000839303523267545e-9),
|
||||
};
|
||||
workspace[5] = tools::evaluate_polynomial(C5, z);
|
||||
|
||||
static const T C6[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.00053130793646399222316574854297762391),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.000592166437353693882864836225604401187),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.000270878209671804482771279183488328692),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.790235323266032787212032944390816666e-6),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.815396936756196875092890088464682624e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.561168275310624965003775619041471695e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.183291165828433755673259749374098313e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.307961345060330478256414192546677006e-8),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.346515536880360908673728529745376913e-5),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.202913273960586037269527254582695285e-5),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.578879286314900370889997586203187687e-6),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.233863067382665698933480579231637609e-12),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.88286007463304835250508524317926246e-7),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.474359588804081278032150770595852426e-7),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.125454150207103824457130611214783073e-7),
|
||||
};
|
||||
workspace[6] = tools::evaluate_polynomial(C6, z);
|
||||
|
||||
static const T C7[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.000344367606892377671254279625108523655),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.517179090826059219337057843002058823e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.000334931610811422363116635090580012327),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.000281269515476323702273722110707777978),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.000109765822446847310235396824500789005),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.127410090954844853794579954588107623e-6),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.277444515115636441570715073933712622e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.182634888057113326614324442681892723e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.578769494973505239894178121070843383e-5),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.493875893393627039981813418398565502e-9),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.105953670140260427338098566209633945e-5),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.616671437611040747858836254004890765e-6),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.175629733590604619378669693914265388e-6),
|
||||
};
|
||||
workspace[7] = tools::evaluate_polynomial(C7, z);
|
||||
|
||||
static const T C8[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.000652623918595309418922034919726622692),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.000839498720672087279993357516764983445),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.000438297098541721005061087953050560377),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.696909145842055197136911097362072702e-6),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.00016644846642067547837384572662326101),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.000127835176797692185853344001461664247),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.462995326369130429061361032704489636e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.455790986792270771162749294232219616e-8),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.105952711258051954718238500312872328e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.678334290486516662273073740749269432e-5),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.210754766662588042469972680229376445e-5),
|
||||
};
|
||||
workspace[8] = tools::evaluate_polynomial(C8, z);
|
||||
|
||||
static const T C9[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.000596761290192746250124390067179459605),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.720489541602001055908571930225015052e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.000678230883766732836161951166000673426),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.000640147526026275845100045652582354779),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.000277501076343287044992374518205845463),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.181970083804651510461686554030325202e-6),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.847950711706850318239732559632810086e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.610519208250153101764709122740859458e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.210739201834048624082975255893773306e-4),
|
||||
};
|
||||
workspace[9] = tools::evaluate_polynomial(C9, z);
|
||||
|
||||
static const T C10[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.00133244544948006563712694993432717968),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.00191443849856547752650089885832852254),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.0011089369134596637339607446329267522),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.993240412264229896742295262075817566e-6),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.000508745012930931989848393025305956774),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.00042735056665392884328432271160040444),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.000168588537679107988033552814662382059),
|
||||
};
|
||||
workspace[10] = tools::evaluate_polynomial(C10, z);
|
||||
|
||||
static const T C11[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.00157972766073083495908785631307733022),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.000162516262783915816898635123980270998),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.00206334210355432762645284467690276817),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.00213896861856890981541061922797693947),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.00101085593912630031708085801712479376),
|
||||
};
|
||||
workspace[11] = tools::evaluate_polynomial(C11, z);
|
||||
|
||||
static const T C12[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.00407251211951401664727281097914544601),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.00640336283380806979482363809026579583),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.00404101610816766177473974858518094879),
|
||||
};
|
||||
workspace[12] = tools::evaluate_polynomial(C12, z);
|
||||
workspace[13] = -0.0059475779383993002845382844736066323L;
|
||||
|
||||
T result = tools::evaluate_polynomial(workspace, T(1/a));
|
||||
result *= exp(-y) / sqrt(2 * constants::pi<T>() * a);
|
||||
if(x < a)
|
||||
result = -result;
|
||||
|
||||
result += boost::math::erfc(sqrt(y), pol) / 2;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace math
|
||||
} // namespace math
|
||||
|
||||
|
||||
#endif // BOOST_MATH_DETAIL_IGAMMA_LARGE
|
||||
|
||||
134
code_isotrope/boost/math/special_functions/detail/lambert_w_lookup_table.ipp
Executable file
134
code_isotrope/boost/math/special_functions/detail/lambert_w_lookup_table.ipp
Executable file
@@ -0,0 +1,134 @@
|
||||
// Copyright Paul A. Bristow 2017.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// I:/modular-boost/libs/math/include/boost/math/special_functions/lambert_w_lookup_table.ipp
|
||||
|
||||
// A collection of 128-bit precision integral z argument Lambert W values computed using 37 decimal digits precision.
|
||||
// C++ floating-point precision is 128-bit long double.
|
||||
// Output as 53 decimal digits, suffixed L.
|
||||
|
||||
// C++ floating-point type is provided by lambert_w.hpp typedef.
|
||||
// For example: typedef lookup_t double; (or float or long double)
|
||||
|
||||
// Written by I:\modular-boost\libs\math\test\lambert_w_lookup_table_generator.cpp Thu Jan 25 16:52:07 2018
|
||||
|
||||
// Sizes of arrays of z values for Lambert W[0], W[1] ... W[64]" and W[-1], W[-2] ... W[-64].
|
||||
|
||||
namespace boost {
|
||||
namespace math {
|
||||
namespace lambert_w_detail {
|
||||
namespace lambert_w_lookup
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR std::size_t noof_sqrts = 12;
|
||||
BOOST_STATIC_CONSTEXPR std::size_t noof_halves = 12;
|
||||
BOOST_STATIC_CONSTEXPR std::size_t noof_w0es = 65;
|
||||
BOOST_STATIC_CONSTEXPR std::size_t noof_w0zs = 65;
|
||||
BOOST_STATIC_CONSTEXPR std::size_t noof_wm1es = 64;
|
||||
BOOST_STATIC_CONSTEXPR std::size_t noof_wm1zs = 64;
|
||||
|
||||
BOOST_STATIC_CONSTEXPR lookup_t halves[noof_halves] =
|
||||
{ // Common to Lambert W0 and W-1 (and exactly representable).
|
||||
0.5L, 0.25L, 0.125L, 0.0625L, 0.03125L, 0.015625L, 0.0078125L, 0.00390625L, 0.001953125L, 0.0009765625L, 0.00048828125L, 0.000244140625L
|
||||
}; // halves, 0.5, 0.25, ... 0.000244140625, common to W0 and W-1.
|
||||
|
||||
BOOST_STATIC_CONSTEXPR lookup_t sqrtw0s[noof_sqrts] =
|
||||
{ // For Lambert W0 only.
|
||||
0.6065306597126334242631173765403218567L, 0.77880078307140486866846070009071995L, 0.882496902584595403104717592968701829L, 0.9394130628134757862473572557999761753L, 0.9692332344763440819139583751755278177L, 0.9844964370054084060204319075254540376L, 0.9922179382602435121227899136829802692L, 0.996101369470117490071323985506950379L, 0.9980487811074754727142805899944244847L, 0.9990239141819756622368328253791383317L, 0.9995118379398893653889967919448497792L, 0.9997558891748972165136242351259789505L
|
||||
}; // sqrtw0s
|
||||
|
||||
BOOST_STATIC_CONSTEXPR lookup_t sqrtwm1s[noof_sqrts] =
|
||||
{ // For Lambert W-1 only.
|
||||
1.648721270700128146848650787814163572L, 1.284025416687741484073420568062436458L, 1.133148453066826316829007227811793873L, 1.064494458917859429563390594642889673L, 1.031743407499102670938747815281507144L, 1.015747708586685747458535072082351749L, 1.007843097206447977693453559760123579L, 1.003913889338347573443609603903460282L, 1.001955033591002812046518898047477216L, 1.000977039492416535242845292611606506L, 1.000488400478694473126173623807163354L, 1.000244170429747854937005233924135774L
|
||||
}; // sqrtwm1s
|
||||
|
||||
BOOST_STATIC_CONSTEXPR lookup_t w0es[noof_w0zs] =
|
||||
{ // Fukushima e powers array e[0] = 2.718, 1., e[2] = e^-1 = 0.135, e[3] = e^-2 = 0.133 ... e[64] = 4.3596100000630809736231248158884615452e-28.
|
||||
2.7182818284590452353602874713526624978e+00L,
|
||||
1.0000000000000000000000000000000000000e+00L, 3.6787944117144232159552377016146086745e-01L, 1.3533528323661269189399949497248440341e-01L, 4.9787068367863942979342415650061776632e-02L,
|
||||
1.8315638888734180293718021273241242212e-02L, 6.7379469990854670966360484231484242488e-03L, 2.4787521766663584230451674308166678915e-03L, 9.1188196555451620800313608440928262647e-04L,
|
||||
3.3546262790251183882138912578086101931e-04L, 1.2340980408667954949763669073003382607e-04L, 4.5399929762484851535591515560550610238e-05L, 1.6701700790245659312635517360580879078e-05L,
|
||||
6.1442123533282097586823081788055323112e-06L, 2.2603294069810543257852772905386894694e-06L, 8.3152871910356788406398514256526229461e-07L, 3.0590232050182578837147949770228963937e-07L,
|
||||
1.1253517471925911451377517906012719164e-07L, 4.1399377187851666596510277189552806229e-08L, 1.5229979744712628436136629233517431862e-08L, 5.6027964375372675400129828162064630798e-09L,
|
||||
2.0611536224385578279659403801558209764e-09L, 7.5825604279119067279417432412681264430e-10L, 2.7894680928689248077189130306442932077e-10L, 1.0261879631701890303927527840612497760e-10L,
|
||||
3.7751345442790977516449695475234067792e-11L, 1.3887943864964020594661763746086856910e-11L, 5.1090890280633247198744001934792157666e-12L, 1.8795288165390832947582704184221926212e-12L,
|
||||
6.9144001069402030094125846587414092712e-13L, 2.5436656473769229103033856148576816666e-13L, 9.3576229688401746049158322233787067450e-14L, 3.4424771084699764583923893328515572846e-14L,
|
||||
1.2664165549094175723120904155965096382e-14L, 4.6588861451033973641842455436101684114e-15L, 1.7139084315420129663027203425760492412e-15L, 6.3051167601469893856390211922465427614e-16L,
|
||||
2.3195228302435693883122636097380800411e-16L, 8.5330476257440657942780498229412441658e-17L, 3.1391327920480296287089646522319196491e-17L, 1.1548224173015785986262442063323868655e-17L,
|
||||
4.2483542552915889953292347828586580179e-18L, 1.5628821893349887680908829951058341550e-18L, 5.7495222642935598066643808805734234249e-19L, 2.1151310375910804866314010070226514702e-19L,
|
||||
7.7811322411337965157133167292798981918e-20L, 2.8625185805493936444701216291839372068e-20L, 1.0530617357553812378763324449428108806e-20L, 3.8739976286871871129314774972691278293e-21L,
|
||||
1.4251640827409351062853210280340602263e-21L, 5.2428856633634639371718053028323436716e-22L, 1.9287498479639177830173428165270125748e-22L, 7.0954741622847041389832693878080734877e-23L,
|
||||
2.6102790696677048047026953153318648093e-23L, 9.6026800545086760302307696700074909076e-24L, 3.5326285722008070297353928101772088374e-24L, 1.2995814250075030736007134060714855303e-24L,
|
||||
4.7808928838854690812771770423179628939e-25L, 1.7587922024243116489558751288034363178e-25L, 6.4702349256454603261540395529264893765e-26L, 2.3802664086944006058943245888024963309e-26L,
|
||||
8.7565107626965203384887328007391660366e-27L, 3.2213402859925160890012477758489437534e-27L, 1.1850648642339810062850307390972809891e-27L, 4.3596100000630809736231248158884596428e-28L,
|
||||
|
||||
}; // w0es
|
||||
|
||||
BOOST_STATIC_CONSTEXPR lookup_t w0zs[noof_w0zs] =
|
||||
{ // z values for W[0], W[1], W[2] ... W[64] (Fukushima array Fk).
|
||||
0.0000000000000000000000000000000000000e+00L,
|
||||
2.7182818284590452353602874713526624978e+00L, 1.4778112197861300454460854921150015626e+01L, 6.0256610769563003222785588963745153691e+01L, 2.1839260013257695631244104481144351361e+02L,
|
||||
7.4206579551288301710557790020276139812e+02L, 2.4205727609564107356503230832603296776e+03L, 7.6764321089992101948460416680168500271e+03L, 2.3847663896333826197948736795623109390e+04L,
|
||||
7.2927755348178456069389970204894839685e+04L, 2.2026465794806716516957900645284244366e+05L, 6.5861555886717600300859134371483559776e+05L, 1.9530574970280470496960624587818413980e+06L,
|
||||
5.7513740961159665432393360873381476632e+06L, 1.6836459978306874888489314790750032292e+07L, 4.9035260587081659589527825691375819733e+07L, 1.4217776832812596218820837985250320561e+08L,
|
||||
4.1063419681078006965118239806655900596e+08L, 1.1818794444719492004981570586630806042e+09L, 3.3911637183005579560532906419857313738e+09L, 9.7033039081958055593821366108308111737e+09L,
|
||||
2.7695130424147508641409976558651358487e+10L, 7.8868082614895014356985518811525255163e+10L, 2.2413047926372475980079655175092843139e+11L, 6.3573893111624333505933989166748517618e+11L,
|
||||
1.8001224834346468131040337866531539479e+12L, 5.0889698451498078710141863447784789126e+12L, 1.4365302496248562650461177217211790925e+13L, 4.0495197800161304862957327843914007993e+13L,
|
||||
1.1400869461717722015726999684446230289e+14L, 3.2059423744573386440971405952224204950e+14L, 9.0051433962267018216365614546207459567e+14L, 2.5268147258457822451512967243234631750e+15L,
|
||||
7.0832381329352301326018261305316090522e+15L, 1.9837699245933465967698692976753294646e+16L, 5.5510470830970075484537561902113104381e+16L, 1.5520433569614702817608320254284931407e+17L,
|
||||
4.3360826779369661842459877227403719730e+17L, 1.2105254067703227363724895246493485480e+18L, 3.3771426165357561311906703760513324357e+18L, 9.4154106734807994163159964299613921804e+18L,
|
||||
2.6233583234732252918129199544138403574e+19L, 7.3049547543861043990576614751671879498e+19L, 2.0329709713386190214340167519800405595e+20L, 5.6547040503180956413560918381429636734e+20L,
|
||||
1.5720421975868292906615658755032744790e+21L, 4.3682149334771264822761478593874428627e+21L, 1.2132170565093316762294432610117848880e+22L, 3.3680332378068632345542636794533635462e+22L,
|
||||
9.3459982052259884835729892206738573922e+22L, 2.5923527642935362320437266614667426924e+23L, 7.1876803203773878618909930893087860822e+23L, 1.9921241603726199616378561653688236827e+24L,
|
||||
5.5192924995054165325072406547517121131e+24L, 1.5286067837683347062387143159276002521e+25L, 4.2321318958281094260005100745711666956e+25L, 1.1713293177672778461879598480402173158e+26L,
|
||||
3.2408603996214813669049988277609543829e+26L, 8.9641258264226027960478448084812796397e+26L, 2.4787141382364034104243901241243054434e+27L, 6.8520443388941057019777430988685937812e+27L,
|
||||
1.8936217407781711443114787060753312270e+28L, 5.2317811346197017832254642778313331353e+28L, 1.4450833904658542238325922893692265683e+29L, 3.9904954117194348050619127737142206367e+29L
|
||||
|
||||
}; // w0zs
|
||||
|
||||
BOOST_STATIC_CONSTEXPR lookup_t wm1es[noof_wm1es] =
|
||||
{ // Fukushima e array e[0] = e^1 = 2.718, e[1] = e^2 = 7.39 ... e[64] = 4.60718e+28.
|
||||
2.7182818284590452353602874713526624978e+00L,
|
||||
7.3890560989306502272304274605750078132e+00L, 2.0085536923187667740928529654581717897e+01L, 5.4598150033144239078110261202860878403e+01L, 1.4841315910257660342111558004055227962e+02L,
|
||||
4.0342879349273512260838718054338827961e+02L, 1.0966331584284585992637202382881214324e+03L, 2.9809579870417282747435920994528886738e+03L, 8.1030839275753840077099966894327599650e+03L,
|
||||
2.2026465794806716516957900645284244366e+04L, 5.9874141715197818455326485792257781614e+04L, 1.6275479141900392080800520489848678317e+05L, 4.4241339200892050332610277594908828178e+05L,
|
||||
1.2026042841647767777492367707678594494e+06L, 3.2690173724721106393018550460917213155e+06L, 8.8861105205078726367630237407814503508e+06L, 2.4154952753575298214775435180385823880e+07L,
|
||||
6.5659969137330511138786503259060033569e+07L, 1.7848230096318726084491003378872270388e+08L, 4.8516519540979027796910683054154055868e+08L, 1.3188157344832146972099988837453027851e+09L,
|
||||
3.5849128461315915616811599459784206892e+09L, 9.7448034462489026000346326848229752776e+09L, 2.6489122129843472294139162152811882341e+10L, 7.2004899337385872524161351466126157915e+10L,
|
||||
1.9572960942883876426977639787609534279e+11L, 5.3204824060179861668374730434117744166e+11L, 1.4462570642914751736770474229969288569e+12L, 3.9313342971440420743886205808435276858e+12L,
|
||||
1.0686474581524462146990468650741401650e+13L, 2.9048849665247425231085682111679825667e+13L, 7.8962960182680695160978022635108224220e+13L, 2.1464357978591606462429776153126088037e+14L,
|
||||
5.8346174252745488140290273461039101900e+14L, 1.5860134523134307281296446257746601252e+15L, 4.3112315471151952271134222928569253908e+15L, 1.1719142372802611308772939791190194522e+16L,
|
||||
3.1855931757113756220328671701298646000e+16L, 8.6593400423993746953606932719264934250e+16L, 2.3538526683701998540789991074903480451e+17L, 6.3984349353005494922266340351557081888e+17L,
|
||||
1.7392749415205010473946813036112352261e+18L, 4.7278394682293465614744575627442803708e+18L, 1.2851600114359308275809299632143099258e+19L, 3.4934271057485095348034797233406099533e+19L,
|
||||
9.4961194206024488745133649117118323102e+19L, 2.5813128861900673962328580021527338043e+20L, 7.0167359120976317386547159988611740546e+20L, 1.9073465724950996905250998409538484474e+21L,
|
||||
5.1847055285870724640874533229334853848e+21L, 1.4093490824269387964492143312370168789e+22L, 3.8310080007165768493035695487861993899e+22L, 1.0413759433029087797183472933493796440e+23L,
|
||||
2.8307533032746939004420635480140745409e+23L, 7.6947852651420171381827455901293939921e+23L, 2.0916594960129961539070711572146737782e+24L, 5.6857199993359322226403488206332533034e+24L,
|
||||
1.5455389355901039303530766911174620068e+25L, 4.2012104037905142549565934307191617684e+25L, 1.1420073898156842836629571831447656302e+26L, 3.1042979357019199087073421411071003721e+26L,
|
||||
8.4383566687414544890733294803731179601e+26L, 2.2937831594696098790993528402686136005e+27L, 6.2351490808116168829092387089284697448e+27L
|
||||
}; // wm1es
|
||||
|
||||
BOOST_STATIC_CONSTEXPR lookup_t wm1zs[noof_wm1zs] =
|
||||
{ // Fukushima G array of z values for integral K, (Fukushima Gk) g[0] (k = -1) = 1 ... g[64] = -1.0264389699511303e-26.
|
||||
-3.6787944117144232159552377016146086745e-01L,
|
||||
-2.7067056647322538378799898994496880682e-01L, -1.4936120510359182893802724695018532990e-01L, -7.3262555554936721174872085092964968848e-02L, -3.3689734995427335483180242115742121244e-02L,
|
||||
-1.4872513059998150538271004584900007349e-02L, -6.3831737588816134560219525908649783853e-03L, -2.6837010232200947105711130062468881545e-03L, -1.1106882367801159454787302165703044346e-03L,
|
||||
-4.5399929762484851535591515560550610238e-04L, -1.8371870869270225243899069096638966986e-04L, -7.3730548239938517104187698145666387735e-05L, -2.9384282290753706235208604777002963102e-05L,
|
||||
-1.1641402067449950376895791995913672125e-05L, -4.5885348075273868255721924655343445906e-06L, -1.8005627955081458322204028649620350662e-06L, -7.0378941219347833214067471222239770590e-07L,
|
||||
-2.7413963540482731185045932620331377352e-07L, -1.0645313231320808326024667350792279852e-07L, -4.1223072448771156559318807603116419528e-08L, -1.5923376898615004128677660806663065530e-08L,
|
||||
-6.1368298043116345769816086674174450569e-09L, -2.3602323152914347699033314033408744848e-09L, -9.0603229062698346039479269140561762700e-10L, -3.4719859662410051486654409365217142276e-10L,
|
||||
-1.3283631472964644271673440503045960993e-10L, -5.0747278046555248958473301297399200773e-11L, -1.9360320299432568426355237044475945959e-11L, -7.3766303773930764398798182830872768331e-12L,
|
||||
-2.8072868906520523814747496670136120235e-12L, -1.0671679036256927021016406931839827582e-12L, -4.0525329757101362313986893299088308423e-13L, -1.5374324278841211301808010293913555758e-13L,
|
||||
-5.8272886672428440854292491647585674200e-14L, -2.2067908660514462849736574172862899665e-14L, -8.3502821888768497979241489950570881481e-15L, -3.1572276215253043438828784344882603413e-15L,
|
||||
-1.1928704609782512589094065678481294667e-15L, -4.5038074274761565346423524046963087756e-16L, -1.6993417021166355981316939131434632072e-16L, -6.4078169762734539491726202799339200356e-17L,
|
||||
-2.4147993510032951187990399698408378385e-17L, -9.0950634616416460925150243301974013218e-18L, -3.4236981860988704669138593608831552044e-18L, -1.2881333612472271400115547331327717431e-18L,
|
||||
-4.8440839844747536942311292467369300505e-19L, -1.8207788854829779430777944237164900798e-19L, -6.8407875971564885101695409345634890862e-20L, -2.5690139750480973292141845983878483991e-20L,
|
||||
-9.6437492398195889150867140826350628738e-21L, -3.6186918227651991108814673877821174787e-21L, -1.3573451162272064984454015639725697008e-21L, -5.0894204288895982960223079251039701810e-22L,
|
||||
-1.9076194289884357960571121174956927722e-22L, -7.1476978375412669048039237333931704166e-23L, -2.6773000149758626855152191436980592206e-23L, -1.0025115553818576399048488234179587012e-23L,
|
||||
-3.7527362568743669891693429406973638384e-24L, -1.4043571811296963574776515073934728352e-24L, -5.2539064576179122030932396804434996219e-25L, -1.9650175744554348142907611432678556896e-25L,
|
||||
-7.3474021582506822389671905824031421322e-26L, -2.7465543000397410133825686340097295749e-26L, -1.0264389699511282259046957018510946438e-26L
|
||||
}; // wm1zs
|
||||
} // namespace lambert_w_lookup
|
||||
} // namespace detail
|
||||
} // namespace math
|
||||
} // namespace boost
|
||||
220
code_isotrope/boost/math/special_functions/detail/lanczos_sse2.hpp
Executable file
220
code_isotrope/boost/math/special_functions/detail/lanczos_sse2.hpp
Executable file
@@ -0,0 +1,220 @@
|
||||
// (C) Copyright John Maddock 2006.
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_MATH_SPECIAL_FUNCTIONS_LANCZOS_SSE2
|
||||
#define BOOST_MATH_SPECIAL_FUNCTIONS_LANCZOS_SSE2
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <emmintrin.h>
|
||||
|
||||
#if defined(__GNUC__) || defined(__PGI) || defined(__SUNPRO_CC)
|
||||
#define ALIGN16 __attribute__((__aligned__(16)))
|
||||
#else
|
||||
#define ALIGN16 __declspec(align(16))
|
||||
#endif
|
||||
|
||||
namespace boost{ namespace math{ namespace lanczos{
|
||||
|
||||
template <>
|
||||
inline double lanczos13m53::lanczos_sum<double>(const double& x)
|
||||
{
|
||||
static const ALIGN16 double coeff[26] = {
|
||||
static_cast<double>(2.506628274631000270164908177133837338626L),
|
||||
static_cast<double>(1u),
|
||||
static_cast<double>(210.8242777515793458725097339207133627117L),
|
||||
static_cast<double>(66u),
|
||||
static_cast<double>(8071.672002365816210638002902272250613822L),
|
||||
static_cast<double>(1925u),
|
||||
static_cast<double>(186056.2653952234950402949897160456992822L),
|
||||
static_cast<double>(32670u),
|
||||
static_cast<double>(2876370.628935372441225409051620849613599L),
|
||||
static_cast<double>(357423u),
|
||||
static_cast<double>(31426415.58540019438061423162831820536287L),
|
||||
static_cast<double>(2637558u),
|
||||
static_cast<double>(248874557.8620541565114603864132294232163L),
|
||||
static_cast<double>(13339535u),
|
||||
static_cast<double>(1439720407.311721673663223072794912393972L),
|
||||
static_cast<double>(45995730u),
|
||||
static_cast<double>(6039542586.35202800506429164430729792107L),
|
||||
static_cast<double>(105258076u),
|
||||
static_cast<double>(17921034426.03720969991975575445893111267L),
|
||||
static_cast<double>(150917976u),
|
||||
static_cast<double>(35711959237.35566804944018545154716670596L),
|
||||
static_cast<double>(120543840u),
|
||||
static_cast<double>(42919803642.64909876895789904700198885093L),
|
||||
static_cast<double>(39916800u),
|
||||
static_cast<double>(23531376880.41075968857200767445163675473L),
|
||||
static_cast<double>(0u)
|
||||
};
|
||||
__m128d vx = _mm_load1_pd(&x);
|
||||
__m128d sum_even = _mm_load_pd(coeff);
|
||||
__m128d sum_odd = _mm_load_pd(coeff+2);
|
||||
__m128d nc_odd, nc_even;
|
||||
__m128d vx2 = _mm_mul_pd(vx, vx);
|
||||
|
||||
sum_even = _mm_mul_pd(sum_even, vx2);
|
||||
nc_even = _mm_load_pd(coeff + 4);
|
||||
sum_odd = _mm_mul_pd(sum_odd, vx2);
|
||||
nc_odd = _mm_load_pd(coeff + 6);
|
||||
sum_even = _mm_add_pd(sum_even, nc_even);
|
||||
sum_odd = _mm_add_pd(sum_odd, nc_odd);
|
||||
|
||||
sum_even = _mm_mul_pd(sum_even, vx2);
|
||||
nc_even = _mm_load_pd(coeff + 8);
|
||||
sum_odd = _mm_mul_pd(sum_odd, vx2);
|
||||
nc_odd = _mm_load_pd(coeff + 10);
|
||||
sum_even = _mm_add_pd(sum_even, nc_even);
|
||||
sum_odd = _mm_add_pd(sum_odd, nc_odd);
|
||||
|
||||
sum_even = _mm_mul_pd(sum_even, vx2);
|
||||
nc_even = _mm_load_pd(coeff + 12);
|
||||
sum_odd = _mm_mul_pd(sum_odd, vx2);
|
||||
nc_odd = _mm_load_pd(coeff + 14);
|
||||
sum_even = _mm_add_pd(sum_even, nc_even);
|
||||
sum_odd = _mm_add_pd(sum_odd, nc_odd);
|
||||
|
||||
sum_even = _mm_mul_pd(sum_even, vx2);
|
||||
nc_even = _mm_load_pd(coeff + 16);
|
||||
sum_odd = _mm_mul_pd(sum_odd, vx2);
|
||||
nc_odd = _mm_load_pd(coeff + 18);
|
||||
sum_even = _mm_add_pd(sum_even, nc_even);
|
||||
sum_odd = _mm_add_pd(sum_odd, nc_odd);
|
||||
|
||||
sum_even = _mm_mul_pd(sum_even, vx2);
|
||||
nc_even = _mm_load_pd(coeff + 20);
|
||||
sum_odd = _mm_mul_pd(sum_odd, vx2);
|
||||
nc_odd = _mm_load_pd(coeff + 22);
|
||||
sum_even = _mm_add_pd(sum_even, nc_even);
|
||||
sum_odd = _mm_add_pd(sum_odd, nc_odd);
|
||||
|
||||
sum_even = _mm_mul_pd(sum_even, vx2);
|
||||
nc_even = _mm_load_pd(coeff + 24);
|
||||
sum_odd = _mm_mul_pd(sum_odd, vx);
|
||||
sum_even = _mm_add_pd(sum_even, nc_even);
|
||||
sum_even = _mm_add_pd(sum_even, sum_odd);
|
||||
|
||||
|
||||
double ALIGN16 t[2];
|
||||
_mm_store_pd(t, sum_even);
|
||||
|
||||
return t[0] / t[1];
|
||||
}
|
||||
|
||||
template <>
|
||||
inline double lanczos13m53::lanczos_sum_expG_scaled<double>(const double& x)
|
||||
{
|
||||
static const ALIGN16 double coeff[26] = {
|
||||
static_cast<double>(0.006061842346248906525783753964555936883222L),
|
||||
static_cast<double>(1u),
|
||||
static_cast<double>(0.5098416655656676188125178644804694509993L),
|
||||
static_cast<double>(66u),
|
||||
static_cast<double>(19.51992788247617482847860966235652136208L),
|
||||
static_cast<double>(1925u),
|
||||
static_cast<double>(449.9445569063168119446858607650988409623L),
|
||||
static_cast<double>(32670u),
|
||||
static_cast<double>(6955.999602515376140356310115515198987526L),
|
||||
static_cast<double>(357423u),
|
||||
static_cast<double>(75999.29304014542649875303443598909137092L),
|
||||
static_cast<double>(2637558u),
|
||||
static_cast<double>(601859.6171681098786670226533699352302507L),
|
||||
static_cast<double>(13339535u),
|
||||
static_cast<double>(3481712.15498064590882071018964774556468L),
|
||||
static_cast<double>(45995730u),
|
||||
static_cast<double>(14605578.08768506808414169982791359218571L),
|
||||
static_cast<double>(105258076u),
|
||||
static_cast<double>(43338889.32467613834773723740590533316085L),
|
||||
static_cast<double>(150917976u),
|
||||
static_cast<double>(86363131.28813859145546927288977868422342L),
|
||||
static_cast<double>(120543840u),
|
||||
static_cast<double>(103794043.1163445451906271053616070238554L),
|
||||
static_cast<double>(39916800u),
|
||||
static_cast<double>(56906521.91347156388090791033559122686859L),
|
||||
static_cast<double>(0u)
|
||||
};
|
||||
__m128d vx = _mm_load1_pd(&x);
|
||||
__m128d sum_even = _mm_load_pd(coeff);
|
||||
__m128d sum_odd = _mm_load_pd(coeff+2);
|
||||
__m128d nc_odd, nc_even;
|
||||
__m128d vx2 = _mm_mul_pd(vx, vx);
|
||||
|
||||
sum_even = _mm_mul_pd(sum_even, vx2);
|
||||
nc_even = _mm_load_pd(coeff + 4);
|
||||
sum_odd = _mm_mul_pd(sum_odd, vx2);
|
||||
nc_odd = _mm_load_pd(coeff + 6);
|
||||
sum_even = _mm_add_pd(sum_even, nc_even);
|
||||
sum_odd = _mm_add_pd(sum_odd, nc_odd);
|
||||
|
||||
sum_even = _mm_mul_pd(sum_even, vx2);
|
||||
nc_even = _mm_load_pd(coeff + 8);
|
||||
sum_odd = _mm_mul_pd(sum_odd, vx2);
|
||||
nc_odd = _mm_load_pd(coeff + 10);
|
||||
sum_even = _mm_add_pd(sum_even, nc_even);
|
||||
sum_odd = _mm_add_pd(sum_odd, nc_odd);
|
||||
|
||||
sum_even = _mm_mul_pd(sum_even, vx2);
|
||||
nc_even = _mm_load_pd(coeff + 12);
|
||||
sum_odd = _mm_mul_pd(sum_odd, vx2);
|
||||
nc_odd = _mm_load_pd(coeff + 14);
|
||||
sum_even = _mm_add_pd(sum_even, nc_even);
|
||||
sum_odd = _mm_add_pd(sum_odd, nc_odd);
|
||||
|
||||
sum_even = _mm_mul_pd(sum_even, vx2);
|
||||
nc_even = _mm_load_pd(coeff + 16);
|
||||
sum_odd = _mm_mul_pd(sum_odd, vx2);
|
||||
nc_odd = _mm_load_pd(coeff + 18);
|
||||
sum_even = _mm_add_pd(sum_even, nc_even);
|
||||
sum_odd = _mm_add_pd(sum_odd, nc_odd);
|
||||
|
||||
sum_even = _mm_mul_pd(sum_even, vx2);
|
||||
nc_even = _mm_load_pd(coeff + 20);
|
||||
sum_odd = _mm_mul_pd(sum_odd, vx2);
|
||||
nc_odd = _mm_load_pd(coeff + 22);
|
||||
sum_even = _mm_add_pd(sum_even, nc_even);
|
||||
sum_odd = _mm_add_pd(sum_odd, nc_odd);
|
||||
|
||||
sum_even = _mm_mul_pd(sum_even, vx2);
|
||||
nc_even = _mm_load_pd(coeff + 24);
|
||||
sum_odd = _mm_mul_pd(sum_odd, vx);
|
||||
sum_even = _mm_add_pd(sum_even, nc_even);
|
||||
sum_even = _mm_add_pd(sum_even, sum_odd);
|
||||
|
||||
|
||||
double ALIGN16 t[2];
|
||||
_mm_store_pd(t, sum_even);
|
||||
|
||||
return t[0] / t[1];
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
BOOST_STATIC_ASSERT(sizeof(double) == sizeof(long double));
|
||||
|
||||
template <>
|
||||
inline long double lanczos13m53::lanczos_sum<long double>(const long double& x)
|
||||
{
|
||||
return lanczos_sum<double>(static_cast<double>(x));
|
||||
}
|
||||
template <>
|
||||
inline long double lanczos13m53::lanczos_sum_expG_scaled<long double>(const long double& x)
|
||||
{
|
||||
return lanczos_sum_expG_scaled<double>(static_cast<double>(x));
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace lanczos
|
||||
} // namespace math
|
||||
} // namespace boost
|
||||
|
||||
#undef ALIGN16
|
||||
|
||||
#endif // BOOST_MATH_SPECIAL_FUNCTIONS_LANCZOS
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
522
code_isotrope/boost/math/special_functions/detail/lgamma_small.hpp
Executable file
522
code_isotrope/boost/math/special_functions/detail/lgamma_small.hpp
Executable file
@@ -0,0 +1,522 @@
|
||||
// (C) Copyright John Maddock 2006.
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_MATH_SPECIAL_FUNCTIONS_DETAIL_LGAMMA_SMALL
|
||||
#define BOOST_MATH_SPECIAL_FUNCTIONS_DETAIL_LGAMMA_SMALL
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/tools/big_constant.hpp>
|
||||
|
||||
namespace boost{ namespace math{ namespace detail{
|
||||
|
||||
//
|
||||
// These need forward declaring to keep GCC happy:
|
||||
//
|
||||
template <class T, class Policy, class Lanczos>
|
||||
T gamma_imp(T z, const Policy& pol, const Lanczos& l);
|
||||
template <class T, class Policy>
|
||||
T gamma_imp(T z, const Policy& pol, const lanczos::undefined_lanczos& l);
|
||||
|
||||
//
|
||||
// lgamma for small arguments:
|
||||
//
|
||||
template <class T, class Policy, class Lanczos>
|
||||
T lgamma_small_imp(T z, T zm1, T zm2, const mpl::int_<64>&, const Policy& /* l */, const Lanczos&)
|
||||
{
|
||||
// This version uses rational approximations for small
|
||||
// values of z accurate enough for 64-bit mantissas
|
||||
// (80-bit long doubles), works well for 53-bit doubles as well.
|
||||
// Lanczos is only used to select the Lanczos function.
|
||||
|
||||
BOOST_MATH_STD_USING // for ADL of std names
|
||||
T result = 0;
|
||||
if(z < tools::epsilon<T>())
|
||||
{
|
||||
result = -log(z);
|
||||
}
|
||||
else if((zm1 == 0) || (zm2 == 0))
|
||||
{
|
||||
// nothing to do, result is zero....
|
||||
}
|
||||
else if(z > 2)
|
||||
{
|
||||
//
|
||||
// Begin by performing argument reduction until
|
||||
// z is in [2,3):
|
||||
//
|
||||
if(z >= 3)
|
||||
{
|
||||
do
|
||||
{
|
||||
z -= 1;
|
||||
zm2 -= 1;
|
||||
result += log(z);
|
||||
}while(z >= 3);
|
||||
// Update zm2, we need it below:
|
||||
zm2 = z - 2;
|
||||
}
|
||||
|
||||
//
|
||||
// Use the following form:
|
||||
//
|
||||
// lgamma(z) = (z-2)(z+1)(Y + R(z-2))
|
||||
//
|
||||
// where R(z-2) is a rational approximation optimised for
|
||||
// low absolute error - as long as it's absolute error
|
||||
// is small compared to the constant Y - then any rounding
|
||||
// error in it's computation will get wiped out.
|
||||
//
|
||||
// R(z-2) has the following properties:
|
||||
//
|
||||
// At double: Max error found: 4.231e-18
|
||||
// At long double: Max error found: 1.987e-21
|
||||
// Maximum Deviation Found (approximation error): 5.900e-24
|
||||
//
|
||||
static const T P[] = {
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -0.180355685678449379109e-1)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.25126649619989678683e-1)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.494103151567532234274e-1)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.172491608709613993966e-1)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -0.259453563205438108893e-3)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -0.541009869215204396339e-3)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -0.324588649825948492091e-4))
|
||||
};
|
||||
static const T Q[] = {
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.1e1)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.196202987197795200688e1)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.148019669424231326694e1)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.541391432071720958364e0)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.988504251128010129477e-1)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.82130967464889339326e-2)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.224936291922115757597e-3)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -0.223352763208617092964e-6))
|
||||
};
|
||||
|
||||
static const float Y = 0.158963680267333984375e0f;
|
||||
|
||||
T r = zm2 * (z + 1);
|
||||
T R = tools::evaluate_polynomial(P, zm2);
|
||||
R /= tools::evaluate_polynomial(Q, zm2);
|
||||
|
||||
result += r * Y + r * R;
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// If z is less than 1 use recurrance to shift to
|
||||
// z in the interval [1,2]:
|
||||
//
|
||||
if(z < 1)
|
||||
{
|
||||
result += -log(z);
|
||||
zm2 = zm1;
|
||||
zm1 = z;
|
||||
z += 1;
|
||||
}
|
||||
//
|
||||
// Two approximations, on for z in [1,1.5] and
|
||||
// one for z in [1.5,2]:
|
||||
//
|
||||
if(z <= 1.5)
|
||||
{
|
||||
//
|
||||
// Use the following form:
|
||||
//
|
||||
// lgamma(z) = (z-1)(z-2)(Y + R(z-1))
|
||||
//
|
||||
// where R(z-1) is a rational approximation optimised for
|
||||
// low absolute error - as long as it's absolute error
|
||||
// is small compared to the constant Y - then any rounding
|
||||
// error in it's computation will get wiped out.
|
||||
//
|
||||
// R(z-1) has the following properties:
|
||||
//
|
||||
// At double precision: Max error found: 1.230011e-17
|
||||
// At 80-bit long double precision: Max error found: 5.631355e-21
|
||||
// Maximum Deviation Found: 3.139e-021
|
||||
// Expected Error Term: 3.139e-021
|
||||
|
||||
//
|
||||
static const float Y = 0.52815341949462890625f;
|
||||
|
||||
static const T P[] = {
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.490622454069039543534e-1)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -0.969117530159521214579e-1)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -0.414983358359495381969e0)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -0.406567124211938417342e0)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -0.158413586390692192217e0)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -0.240149820648571559892e-1)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -0.100346687696279557415e-2))
|
||||
};
|
||||
static const T Q[] = {
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.1e1)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.302349829846463038743e1)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.348739585360723852576e1)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.191415588274426679201e1)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.507137738614363510846e0)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.577039722690451849648e-1)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.195768102601107189171e-2))
|
||||
};
|
||||
|
||||
T r = tools::evaluate_polynomial(P, zm1) / tools::evaluate_polynomial(Q, zm1);
|
||||
T prefix = zm1 * zm2;
|
||||
|
||||
result += prefix * Y + prefix * r;
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Use the following form:
|
||||
//
|
||||
// lgamma(z) = (2-z)(1-z)(Y + R(2-z))
|
||||
//
|
||||
// where R(2-z) is a rational approximation optimised for
|
||||
// low absolute error - as long as it's absolute error
|
||||
// is small compared to the constant Y - then any rounding
|
||||
// error in it's computation will get wiped out.
|
||||
//
|
||||
// R(2-z) has the following properties:
|
||||
//
|
||||
// At double precision, max error found: 1.797565e-17
|
||||
// At 80-bit long double precision, max error found: 9.306419e-21
|
||||
// Maximum Deviation Found: 2.151e-021
|
||||
// Expected Error Term: 2.150e-021
|
||||
//
|
||||
static const float Y = 0.452017307281494140625f;
|
||||
|
||||
static const T P[] = {
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -0.292329721830270012337e-1)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.144216267757192309184e0)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -0.142440390738631274135e0)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.542809694055053558157e-1)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -0.850535976868336437746e-2)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.431171342679297331241e-3))
|
||||
};
|
||||
static const T Q[] = {
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.1e1)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -0.150169356054485044494e1)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.846973248876495016101e0)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -0.220095151814995745555e0)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.25582797155975869989e-1)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -0.100666795539143372762e-2)),
|
||||
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -0.827193521891290553639e-6))
|
||||
};
|
||||
T r = zm2 * zm1;
|
||||
T R = tools::evaluate_polynomial(P, T(-zm2)) / tools::evaluate_polynomial(Q, T(-zm2));
|
||||
|
||||
result += r * Y + r * R;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
template <class T, class Policy, class Lanczos>
|
||||
T lgamma_small_imp(T z, T zm1, T zm2, const mpl::int_<113>&, const Policy& /* l */, const Lanczos&)
|
||||
{
|
||||
//
|
||||
// This version uses rational approximations for small
|
||||
// values of z accurate enough for 113-bit mantissas
|
||||
// (128-bit long doubles).
|
||||
//
|
||||
BOOST_MATH_STD_USING // for ADL of std names
|
||||
T result = 0;
|
||||
if(z < tools::epsilon<T>())
|
||||
{
|
||||
result = -log(z);
|
||||
BOOST_MATH_INSTRUMENT_CODE(result);
|
||||
}
|
||||
else if((zm1 == 0) || (zm2 == 0))
|
||||
{
|
||||
// nothing to do, result is zero....
|
||||
}
|
||||
else if(z > 2)
|
||||
{
|
||||
//
|
||||
// Begin by performing argument reduction until
|
||||
// z is in [2,3):
|
||||
//
|
||||
if(z >= 3)
|
||||
{
|
||||
do
|
||||
{
|
||||
z -= 1;
|
||||
result += log(z);
|
||||
}while(z >= 3);
|
||||
zm2 = z - 2;
|
||||
}
|
||||
BOOST_MATH_INSTRUMENT_CODE(zm2);
|
||||
BOOST_MATH_INSTRUMENT_CODE(z);
|
||||
BOOST_MATH_INSTRUMENT_CODE(result);
|
||||
|
||||
//
|
||||
// Use the following form:
|
||||
//
|
||||
// lgamma(z) = (z-2)(z+1)(Y + R(z-2))
|
||||
//
|
||||
// where R(z-2) is a rational approximation optimised for
|
||||
// low absolute error - as long as it's absolute error
|
||||
// is small compared to the constant Y - then any rounding
|
||||
// error in it's computation will get wiped out.
|
||||
//
|
||||
// Maximum Deviation Found (approximation error) 3.73e-37
|
||||
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.018035568567844937910504030027467476655),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.013841458273109517271750705401202404195),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.062031842739486600078866923383017722399),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.052518418329052161202007865149435256093),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.01881718142472784129191838493267755758),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.0025104830367021839316463675028524702846),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.00021043176101831873281848891452678568311),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.00010249622350908722793327719494037981166),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.11381479670982006841716879074288176994e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.49999811718089980992888533630523892389e-6),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.70529798686542184668416911331718963364e-8)
|
||||
};
|
||||
static const T Q[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.5877485070422317542808137697939233685),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.8797959228352591788629602533153837126),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.8030885955284082026405495275461180977),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.69774331297747390169238306148355428436),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.17261566063277623942044077039756583802),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.02729301254544230229429621192443000121),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.0026776425891195270663133581960016620433),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.00015244249160486584591370355730402168106),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.43997034032479866020546814475414346627e-5),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.46295080708455613044541885534408170934e-7),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.93326638207459533682980757982834180952e-11),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.42316456553164995177177407325292867513e-13)
|
||||
};
|
||||
|
||||
T R = tools::evaluate_polynomial(P, zm2);
|
||||
R /= tools::evaluate_polynomial(Q, zm2);
|
||||
|
||||
static const float Y = 0.158963680267333984375F;
|
||||
|
||||
T r = zm2 * (z + 1);
|
||||
|
||||
result += r * Y + r * R;
|
||||
BOOST_MATH_INSTRUMENT_CODE(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// If z is less than 1 use recurrance to shift to
|
||||
// z in the interval [1,2]:
|
||||
//
|
||||
if(z < 1)
|
||||
{
|
||||
result += -log(z);
|
||||
zm2 = zm1;
|
||||
zm1 = z;
|
||||
z += 1;
|
||||
}
|
||||
BOOST_MATH_INSTRUMENT_CODE(result);
|
||||
BOOST_MATH_INSTRUMENT_CODE(z);
|
||||
BOOST_MATH_INSTRUMENT_CODE(zm2);
|
||||
//
|
||||
// Three approximations, on for z in [1,1.35], [1.35,1.625] and [1.625,1]
|
||||
//
|
||||
if(z <= 1.35)
|
||||
{
|
||||
//
|
||||
// Use the following form:
|
||||
//
|
||||
// lgamma(z) = (z-1)(z-2)(Y + R(z-1))
|
||||
//
|
||||
// where R(z-1) is a rational approximation optimised for
|
||||
// low absolute error - as long as it's absolute error
|
||||
// is small compared to the constant Y - then any rounding
|
||||
// error in it's computation will get wiped out.
|
||||
//
|
||||
// R(z-1) has the following properties:
|
||||
//
|
||||
// Maximum Deviation Found (approximation error) 1.659e-36
|
||||
// Expected Error Term (theoretical error) 1.343e-36
|
||||
// Max error found at 128-bit long double precision 1.007e-35
|
||||
//
|
||||
static const float Y = 0.54076099395751953125f;
|
||||
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.036454670944013329356512090082402429697),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.066235835556476033710068679907798799959),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.67492399795577182387312206593595565371),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -1.4345555263962411429855341651960000166),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -1.4894319559821365820516771951249649563),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.87210277668067964629483299712322411566),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.29602090537771744401524080430529369136),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.0561832587517836908929331992218879676),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.0053236785487328044334381502530383140443),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.00018629360291358130461736386077971890789),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.10164985672213178500790406939467614498e-6),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.13680157145361387405588201461036338274e-8)
|
||||
};
|
||||
static const T Q[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 4.9106336261005990534095838574132225599),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 10.258804800866438510889341082793078432),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 11.88588976846826108836629960537466889),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 8.3455000546999704314454891036700998428),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.6428823682421746343233362007194282703),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.97465989807254572142266753052776132252),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.15121052897097822172763084966793352524),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.012017363555383555123769849654484594893),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.0003583032812720649835431669893011257277)
|
||||
};
|
||||
|
||||
T r = tools::evaluate_polynomial(P, zm1) / tools::evaluate_polynomial(Q, zm1);
|
||||
T prefix = zm1 * zm2;
|
||||
|
||||
result += prefix * Y + prefix * r;
|
||||
BOOST_MATH_INSTRUMENT_CODE(result);
|
||||
}
|
||||
else if(z <= 1.625)
|
||||
{
|
||||
//
|
||||
// Use the following form:
|
||||
//
|
||||
// lgamma(z) = (2-z)(1-z)(Y + R(2-z))
|
||||
//
|
||||
// where R(2-z) is a rational approximation optimised for
|
||||
// low absolute error - as long as it's absolute error
|
||||
// is small compared to the constant Y - then any rounding
|
||||
// error in it's computation will get wiped out.
|
||||
//
|
||||
// R(2-z) has the following properties:
|
||||
//
|
||||
// Max error found at 128-bit long double precision 9.634e-36
|
||||
// Maximum Deviation Found (approximation error) 1.538e-37
|
||||
// Expected Error Term (theoretical error) 2.350e-38
|
||||
//
|
||||
static const float Y = 0.483787059783935546875f;
|
||||
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.017977422421608624353488126610933005432),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.18484528905298309555089509029244135703),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.40401251514859546989565001431430884082),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.40277179799147356461954182877921388182),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.21993421441282936476709677700477598816),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.069595742223850248095697771331107571011),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.012681481427699686635516772923547347328),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.0012489322866834830413292771335113136034),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.57058739515423112045108068834668269608e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.8207548771933585614380644961342925976e-6)
|
||||
};
|
||||
static const T Q[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -2.9629552288944259229543137757200262073),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.7118380799042118987185957298964772755),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -2.5569815272165399297600586376727357187),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.0546764918220835097855665680632153367),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.26574021300894401276478730940980810831),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.03996289731752081380552901986471233462),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.0033398680924544836817826046380586480873),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.00013288854760548251757651556792598235735),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.17194794958274081373243161848194745111e-5)
|
||||
};
|
||||
T r = zm2 * zm1;
|
||||
T R = tools::evaluate_polynomial(P, T(0.625 - zm1)) / tools::evaluate_polynomial(Q, T(0.625 - zm1));
|
||||
|
||||
result += r * Y + r * R;
|
||||
BOOST_MATH_INSTRUMENT_CODE(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Same form as above.
|
||||
//
|
||||
// Max error found (at 128-bit long double precision) 1.831e-35
|
||||
// Maximum Deviation Found (approximation error) 8.588e-36
|
||||
// Expected Error Term (theoretical error) 1.458e-36
|
||||
//
|
||||
static const float Y = 0.443811893463134765625f;
|
||||
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.021027558364667626231512090082402429494),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.15128811104498736604523586803722368377),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.26249631480066246699388544451126410278),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.21148748610533489823742352180628489742),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.093964130697489071999873506148104370633),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.024292059227009051652542804957550866827),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.0036284453226534839926304745756906117066),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.0002939230129315195346843036254392485984),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.11088589183158123733132268042570710338e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.13240510580220763969511741896361984162e-6)
|
||||
};
|
||||
static const T Q[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -2.4240003754444040525462170802796471996),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.4868383476933178722203278602342786002),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -1.4047068395206343375520721509193698547),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.47583809087867443858344765659065773369),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.09865724264554556400463655444270700132),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.012238223514176587501074150988445109735),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.00084625068418239194670614419707491797097),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.2796574430456237061420839429225710602e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.30202973883316730694433702165188835331e-6)
|
||||
};
|
||||
// (2 - x) * (1 - x) * (c + R(2 - x))
|
||||
T r = zm2 * zm1;
|
||||
T R = tools::evaluate_polynomial(P, T(-zm2)) / tools::evaluate_polynomial(Q, T(-zm2));
|
||||
|
||||
result += r * Y + r * R;
|
||||
BOOST_MATH_INSTRUMENT_CODE(result);
|
||||
}
|
||||
}
|
||||
BOOST_MATH_INSTRUMENT_CODE(result);
|
||||
return result;
|
||||
}
|
||||
template <class T, class Policy, class Lanczos>
|
||||
T lgamma_small_imp(T z, T zm1, T zm2, const mpl::int_<0>&, const Policy& pol, const Lanczos&)
|
||||
{
|
||||
//
|
||||
// No rational approximations are available because either
|
||||
// T has no numeric_limits support (so we can't tell how
|
||||
// many digits it has), or T has more digits than we know
|
||||
// what to do with.... we do have a Lanczos approximation
|
||||
// though, and that can be used to keep errors under control.
|
||||
//
|
||||
BOOST_MATH_STD_USING // for ADL of std names
|
||||
T result = 0;
|
||||
if(z < tools::epsilon<T>())
|
||||
{
|
||||
result = -log(z);
|
||||
}
|
||||
else if(z < 0.5)
|
||||
{
|
||||
// taking the log of tgamma reduces the error, no danger of overflow here:
|
||||
result = log(gamma_imp(z, pol, Lanczos()));
|
||||
}
|
||||
else if(z >= 3)
|
||||
{
|
||||
// taking the log of tgamma reduces the error, no danger of overflow here:
|
||||
result = log(gamma_imp(z, pol, Lanczos()));
|
||||
}
|
||||
else if(z >= 1.5)
|
||||
{
|
||||
// special case near 2:
|
||||
T dz = zm2;
|
||||
result = dz * log((z + Lanczos::g() - T(0.5)) / boost::math::constants::e<T>());
|
||||
result += boost::math::log1p(dz / (Lanczos::g() + T(1.5)), pol) * T(1.5);
|
||||
result += boost::math::log1p(Lanczos::lanczos_sum_near_2(dz), pol);
|
||||
}
|
||||
else
|
||||
{
|
||||
// special case near 1:
|
||||
T dz = zm1;
|
||||
result = dz * log((z + Lanczos::g() - T(0.5)) / boost::math::constants::e<T>());
|
||||
result += boost::math::log1p(dz / (Lanczos::g() + T(0.5)), pol) / 2;
|
||||
result += boost::math::log1p(Lanczos::lanczos_sum_near_1(dz), pol);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_SPECIAL_FUNCTIONS_DETAIL_LGAMMA_SMALL
|
||||
|
||||
558
code_isotrope/boost/math/special_functions/detail/polygamma.hpp
Executable file
558
code_isotrope/boost/math/special_functions/detail/polygamma.hpp
Executable file
@@ -0,0 +1,558 @@
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright 2013 Nikhar Agrawal
|
||||
// Copyright 2013 Christopher Kormanyos
|
||||
// Copyright 2014 John Maddock
|
||||
// Copyright 2013 Paul Bristow
|
||||
// Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef _BOOST_POLYGAMMA_DETAIL_2013_07_30_HPP_
|
||||
#define _BOOST_POLYGAMMA_DETAIL_2013_07_30_HPP_
|
||||
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/math/policies/policy.hpp>
|
||||
#include <boost/math/special_functions/bernoulli.hpp>
|
||||
#include <boost/math/special_functions/trunc.hpp>
|
||||
#include <boost/math/special_functions/zeta.hpp>
|
||||
#include <boost/math/special_functions/digamma.hpp>
|
||||
#include <boost/math/special_functions/sin_pi.hpp>
|
||||
#include <boost/math/special_functions/cos_pi.hpp>
|
||||
#include <boost/math/special_functions/pow.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/int.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4702) // Unreachable code (release mode only warning)
|
||||
#endif
|
||||
|
||||
namespace boost { namespace math { namespace detail{
|
||||
|
||||
template<class T, class Policy>
|
||||
T polygamma_atinfinityplus(const int n, const T& x, const Policy& pol, const char* function) // for large values of x such as for x> 400
|
||||
{
|
||||
// See http://functions.wolfram.com/GammaBetaErf/PolyGamma2/06/02/0001/
|
||||
BOOST_MATH_STD_USING
|
||||
//
|
||||
// sum == current value of accumulated sum.
|
||||
// term == value of current term to be added to sum.
|
||||
// part_term == value of current term excluding the Bernoulli number part
|
||||
//
|
||||
if(n + x == x)
|
||||
{
|
||||
// x is crazy large, just concentrate on the first part of the expression and use logs:
|
||||
if(n == 1) return 1 / x;
|
||||
T nlx = n * log(x);
|
||||
if((nlx < tools::log_max_value<T>()) && (n < (int)max_factorial<T>::value))
|
||||
return ((n & 1) ? 1 : -1) * boost::math::factorial<T>(n - 1) * pow(x, -n);
|
||||
else
|
||||
return ((n & 1) ? 1 : -1) * exp(boost::math::lgamma(T(n), pol) - n * log(x));
|
||||
}
|
||||
T term, sum, part_term;
|
||||
T x_squared = x * x;
|
||||
//
|
||||
// Start by setting part_term to:
|
||||
//
|
||||
// (n-1)! / x^(n+1)
|
||||
//
|
||||
// which is common to both the first term of the series (with k = 1)
|
||||
// and to the leading part.
|
||||
// We can then get to the leading term by:
|
||||
//
|
||||
// part_term * (n + 2 * x) / 2
|
||||
//
|
||||
// and to the first term in the series
|
||||
// (excluding the Bernoulli number) by:
|
||||
//
|
||||
// part_term n * (n + 1) / (2x)
|
||||
//
|
||||
// If either the factorial would overflow,
|
||||
// or the power term underflows, this just gets set to 0 and then we
|
||||
// know that we have to use logs for the initial terms:
|
||||
//
|
||||
part_term = ((n > (int)boost::math::max_factorial<T>::value) && (T(n) * n > tools::log_max_value<T>()))
|
||||
? T(0) : static_cast<T>(boost::math::factorial<T>(n - 1, pol) * pow(x, -n - 1));
|
||||
if(part_term == 0)
|
||||
{
|
||||
// Either n is very large, or the power term underflows,
|
||||
// set the initial values of part_term, term and sum via logs:
|
||||
part_term = static_cast<T>(boost::math::lgamma(n, pol) - (n + 1) * log(x));
|
||||
sum = exp(part_term + log(n + 2 * x) - boost::math::constants::ln_two<T>());
|
||||
part_term += log(T(n) * (n + 1)) - boost::math::constants::ln_two<T>() - log(x);
|
||||
part_term = exp(part_term);
|
||||
}
|
||||
else
|
||||
{
|
||||
sum = part_term * (n + 2 * x) / 2;
|
||||
part_term *= (T(n) * (n + 1)) / 2;
|
||||
part_term /= x;
|
||||
}
|
||||
//
|
||||
// If the leading term is 0, so is the result:
|
||||
//
|
||||
if(sum == 0)
|
||||
return sum;
|
||||
|
||||
for(unsigned k = 1;;)
|
||||
{
|
||||
term = part_term * boost::math::bernoulli_b2n<T>(k, pol);
|
||||
sum += term;
|
||||
//
|
||||
// Normal termination condition:
|
||||
//
|
||||
if(fabs(term / sum) < tools::epsilon<T>())
|
||||
break;
|
||||
//
|
||||
// Increment our counter, and move part_term on to the next value:
|
||||
//
|
||||
++k;
|
||||
part_term *= T(n + 2 * k - 2) * (n - 1 + 2 * k);
|
||||
part_term /= (2 * k - 1) * 2 * k;
|
||||
part_term /= x_squared;
|
||||
//
|
||||
// Emergency get out termination condition:
|
||||
//
|
||||
if(k > policies::get_max_series_iterations<Policy>())
|
||||
{
|
||||
return policies::raise_evaluation_error(function, "Series did not converge, closest value was %1%", sum, pol);
|
||||
}
|
||||
}
|
||||
|
||||
if((n - 1) & 1)
|
||||
sum = -sum;
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
template<class T, class Policy>
|
||||
T polygamma_attransitionplus(const int n, const T& x, const Policy& pol, const char* function)
|
||||
{
|
||||
// See: http://functions.wolfram.com/GammaBetaErf/PolyGamma2/16/01/01/0017/
|
||||
|
||||
// Use N = (0.4 * digits) + (4 * n) for target value for x:
|
||||
BOOST_MATH_STD_USING
|
||||
const int d4d = static_cast<int>(0.4F * policies::digits_base10<T, Policy>());
|
||||
const int N = d4d + (4 * n);
|
||||
const int m = n;
|
||||
const int iter = N - itrunc(x);
|
||||
|
||||
if(iter > (int)policies::get_max_series_iterations<Policy>())
|
||||
return policies::raise_evaluation_error<T>(function, ("Exceeded maximum series evaluations evaluating at n = " + boost::lexical_cast<std::string>(n) + " and x = %1%").c_str(), x, pol);
|
||||
|
||||
const int minus_m_minus_one = -m - 1;
|
||||
|
||||
T z(x);
|
||||
T sum0(0);
|
||||
T z_plus_k_pow_minus_m_minus_one(0);
|
||||
|
||||
// Forward recursion to larger x, need to check for overflow first though:
|
||||
if(log(z + iter) * minus_m_minus_one > -tools::log_max_value<T>())
|
||||
{
|
||||
for(int k = 1; k <= iter; ++k)
|
||||
{
|
||||
z_plus_k_pow_minus_m_minus_one = pow(z, minus_m_minus_one);
|
||||
sum0 += z_plus_k_pow_minus_m_minus_one;
|
||||
z += 1;
|
||||
}
|
||||
sum0 *= boost::math::factorial<T>(n);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int k = 1; k <= iter; ++k)
|
||||
{
|
||||
T log_term = log(z) * minus_m_minus_one + boost::math::lgamma(T(n + 1), pol);
|
||||
sum0 += exp(log_term);
|
||||
z += 1;
|
||||
}
|
||||
}
|
||||
if((n - 1) & 1)
|
||||
sum0 = -sum0;
|
||||
|
||||
return sum0 + polygamma_atinfinityplus(n, z, pol, function);
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
T polygamma_nearzero(int n, T x, const Policy& pol, const char* function)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
//
|
||||
// If we take this expansion for polygamma: http://functions.wolfram.com/06.15.06.0003.02
|
||||
// and substitute in this expression for polygamma(n, 1): http://functions.wolfram.com/06.15.03.0009.01
|
||||
// we get an alternating series for polygamma when x is small in terms of zeta functions of
|
||||
// integer arguments (which are easy to evaluate, at least when the integer is even).
|
||||
//
|
||||
// In order to avoid spurious overflow, save the n! term for later, and rescale at the end:
|
||||
//
|
||||
T scale = boost::math::factorial<T>(n, pol);
|
||||
//
|
||||
// "factorial_part" contains everything except the zeta function
|
||||
// evaluations in each term:
|
||||
//
|
||||
T factorial_part = 1;
|
||||
//
|
||||
// "prefix" is what we'll be adding the accumulated sum to, it will
|
||||
// be n! / z^(n+1), but since we're scaling by n! it's just
|
||||
// 1 / z^(n+1) for now:
|
||||
//
|
||||
T prefix = pow(x, n + 1);
|
||||
if(prefix == 0)
|
||||
return boost::math::policies::raise_overflow_error<T>(function, 0, pol);
|
||||
prefix = 1 / prefix;
|
||||
//
|
||||
// First term in the series is necessarily < zeta(2) < 2, so
|
||||
// ignore the sum if it will have no effect on the result anyway:
|
||||
//
|
||||
if(prefix > 2 / policies::get_epsilon<T, Policy>())
|
||||
return ((n & 1) ? 1 : -1) *
|
||||
(tools::max_value<T>() / prefix < scale ? policies::raise_overflow_error<T>(function, 0, pol) : prefix * scale);
|
||||
//
|
||||
// As this is an alternating series we could accelerate it using
|
||||
// "Convergence Acceleration of Alternating Series",
|
||||
// Henri Cohen, Fernando Rodriguez Villegas, and Don Zagier, Experimental Mathematics, 1999.
|
||||
// In practice however, it appears not to make any difference to the number of terms
|
||||
// required except in some edge cases which are filtered out anyway before we get here.
|
||||
//
|
||||
T sum = prefix;
|
||||
for(unsigned k = 0;;)
|
||||
{
|
||||
// Get the k'th term:
|
||||
T term = factorial_part * boost::math::zeta(T(k + n + 1), pol);
|
||||
sum += term;
|
||||
// Termination condition:
|
||||
if(fabs(term) < fabs(sum * boost::math::policies::get_epsilon<T, Policy>()))
|
||||
break;
|
||||
//
|
||||
// Move on k and factorial_part:
|
||||
//
|
||||
++k;
|
||||
factorial_part *= (-x * (n + k)) / k;
|
||||
//
|
||||
// Last chance exit:
|
||||
//
|
||||
if(k > policies::get_max_series_iterations<Policy>())
|
||||
return policies::raise_evaluation_error<T>(function, "Series did not converge, best value is %1%", sum, pol);
|
||||
}
|
||||
//
|
||||
// We need to multiply by the scale, at each stage checking for oveflow:
|
||||
//
|
||||
if(boost::math::tools::max_value<T>() / scale < sum)
|
||||
return boost::math::policies::raise_overflow_error<T>(function, 0, pol);
|
||||
sum *= scale;
|
||||
return n & 1 ? sum : T(-sum);
|
||||
}
|
||||
|
||||
//
|
||||
// Helper function which figures out which slot our coefficient is in
|
||||
// given an angle multiplier for the cosine term of power:
|
||||
//
|
||||
template <class Table>
|
||||
typename Table::value_type::reference dereference_table(Table& table, unsigned row, unsigned power)
|
||||
{
|
||||
return table[row][power / 2];
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <class T, class Policy>
|
||||
T poly_cot_pi(int n, T x, T xc, const Policy& pol, const char* function)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
// Return n'th derivative of cot(pi*x) at x, these are simply
|
||||
// tabulated for up to n = 9, beyond that it is possible to
|
||||
// calculate coefficients as follows:
|
||||
//
|
||||
// The general form of each derivative is:
|
||||
//
|
||||
// pi^n * SUM{k=0, n} C[k,n] * cos^k(pi * x) * csc^(n+1)(pi * x)
|
||||
//
|
||||
// With constant C[0,1] = -1 and all other C[k,n] = 0;
|
||||
// Then for each k < n+1:
|
||||
// C[k-1, n+1] -= k * C[k, n];
|
||||
// C[k+1, n+1] += (k-n-1) * C[k, n];
|
||||
//
|
||||
// Note that there are many different ways of representing this derivative thanks to
|
||||
// the many trigomonetric identies available. In particular, the sum of powers of
|
||||
// cosines could be replaced by a sum of cosine multiple angles, and indeed if you
|
||||
// plug the derivative into Mathematica this is the form it will give. The two
|
||||
// forms are related via the Chebeshev polynomials of the first kind and
|
||||
// T_n(cos(x)) = cos(n x). The polynomial form has the great advantage that
|
||||
// all the cosine terms are zero at half integer arguments - right where this
|
||||
// function has it's minumum - thus avoiding cancellation error in this region.
|
||||
//
|
||||
// And finally, since every other term in the polynomials is zero, we can save
|
||||
// space by only storing the non-zero terms. This greatly complexifies
|
||||
// subscripting the tables in the calculation, but halves the storage space
|
||||
// (and complexity for that matter).
|
||||
//
|
||||
T s = fabs(x) < fabs(xc) ? boost::math::sin_pi(x, pol) : boost::math::sin_pi(xc, pol);
|
||||
T c = boost::math::cos_pi(x, pol);
|
||||
switch(n)
|
||||
{
|
||||
case 1:
|
||||
return -constants::pi<T, Policy>() / (s * s);
|
||||
case 2:
|
||||
{
|
||||
return 2 * constants::pi<T, Policy>() * constants::pi<T, Policy>() * c / boost::math::pow<3>(s, pol);
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
int P[] = { -2, -4 };
|
||||
return boost::math::pow<3>(constants::pi<T, Policy>(), pol) * tools::evaluate_even_polynomial(P, c) / boost::math::pow<4>(s, pol);
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
int P[] = { 16, 8 };
|
||||
return boost::math::pow<4>(constants::pi<T, Policy>(), pol) * c * tools::evaluate_even_polynomial(P, c) / boost::math::pow<5>(s, pol);
|
||||
}
|
||||
case 5:
|
||||
{
|
||||
int P[] = { -16, -88, -16 };
|
||||
return boost::math::pow<5>(constants::pi<T, Policy>(), pol) * tools::evaluate_even_polynomial(P, c) / boost::math::pow<6>(s, pol);
|
||||
}
|
||||
case 6:
|
||||
{
|
||||
int P[] = { 272, 416, 32 };
|
||||
return boost::math::pow<6>(constants::pi<T, Policy>(), pol) * c * tools::evaluate_even_polynomial(P, c) / boost::math::pow<7>(s, pol);
|
||||
}
|
||||
case 7:
|
||||
{
|
||||
int P[] = { -272, -2880, -1824, -64 };
|
||||
return boost::math::pow<7>(constants::pi<T, Policy>(), pol) * tools::evaluate_even_polynomial(P, c) / boost::math::pow<8>(s, pol);
|
||||
}
|
||||
case 8:
|
||||
{
|
||||
int P[] = { 7936, 24576, 7680, 128 };
|
||||
return boost::math::pow<8>(constants::pi<T, Policy>(), pol) * c * tools::evaluate_even_polynomial(P, c) / boost::math::pow<9>(s, pol);
|
||||
}
|
||||
case 9:
|
||||
{
|
||||
int P[] = { -7936, -137216, -185856, -31616, -256 };
|
||||
return boost::math::pow<9>(constants::pi<T, Policy>(), pol) * tools::evaluate_even_polynomial(P, c) / boost::math::pow<10>(s, pol);
|
||||
}
|
||||
case 10:
|
||||
{
|
||||
int P[] = { 353792, 1841152, 1304832, 128512, 512 };
|
||||
return boost::math::pow<10>(constants::pi<T, Policy>(), pol) * c * tools::evaluate_even_polynomial(P, c) / boost::math::pow<11>(s, pol);
|
||||
}
|
||||
case 11:
|
||||
{
|
||||
int P[] = { -353792, -9061376, -21253376, -8728576, -518656, -1024};
|
||||
return boost::math::pow<11>(constants::pi<T, Policy>(), pol) * tools::evaluate_even_polynomial(P, c) / boost::math::pow<12>(s, pol);
|
||||
}
|
||||
case 12:
|
||||
{
|
||||
int P[] = { 22368256, 175627264, 222398464, 56520704, 2084864, 2048 };
|
||||
return boost::math::pow<12>(constants::pi<T, Policy>(), pol) * c * tools::evaluate_even_polynomial(P, c) / boost::math::pow<13>(s, pol);
|
||||
}
|
||||
#ifndef BOOST_NO_LONG_LONG
|
||||
case 13:
|
||||
{
|
||||
long long P[] = { -22368256LL, -795300864LL, -2868264960LL, -2174832640LL, -357888000LL, -8361984LL, -4096 };
|
||||
return boost::math::pow<13>(constants::pi<T, Policy>(), pol) * tools::evaluate_even_polynomial(P, c) / boost::math::pow<14>(s, pol);
|
||||
}
|
||||
case 14:
|
||||
{
|
||||
long long P[] = { 1903757312LL, 21016670208LL, 41731645440LL, 20261765120LL, 2230947840LL, 33497088LL, 8192 };
|
||||
return boost::math::pow<14>(constants::pi<T, Policy>(), pol) * c * tools::evaluate_even_polynomial(P, c) / boost::math::pow<15>(s, pol);
|
||||
}
|
||||
case 15:
|
||||
{
|
||||
long long P[] = { -1903757312LL, -89702612992LL, -460858269696LL, -559148810240LL, -182172651520LL, -13754155008LL, -134094848LL, -16384 };
|
||||
return boost::math::pow<15>(constants::pi<T, Policy>(), pol) * tools::evaluate_even_polynomial(P, c) / boost::math::pow<16>(s, pol);
|
||||
}
|
||||
case 16:
|
||||
{
|
||||
long long P[] = { 209865342976LL, 3099269660672LL, 8885192097792LL, 7048869314560LL, 1594922762240LL, 84134068224LL, 536608768LL, 32768 };
|
||||
return boost::math::pow<16>(constants::pi<T, Policy>(), pol) * c * tools::evaluate_even_polynomial(P, c) / boost::math::pow<17>(s, pol);
|
||||
}
|
||||
case 17:
|
||||
{
|
||||
long long P[] = { -209865342976LL, -12655654469632LL, -87815735738368LL, -155964390375424LL, -84842998005760LL, -13684856848384LL, -511780323328LL, -2146926592LL, -65536 };
|
||||
return boost::math::pow<17>(constants::pi<T, Policy>(), pol) * tools::evaluate_even_polynomial(P, c) / boost::math::pow<18>(s, pol);
|
||||
}
|
||||
case 18:
|
||||
{
|
||||
long long P[] = { 29088885112832LL, 553753414467584LL, 2165206642589696LL, 2550316668551168LL, 985278548541440LL, 115620218667008LL, 3100738912256LL, 8588754944LL, 131072 };
|
||||
return boost::math::pow<18>(constants::pi<T, Policy>(), pol) * c * tools::evaluate_even_polynomial(P, c) / boost::math::pow<19>(s, pol);
|
||||
}
|
||||
case 19:
|
||||
{
|
||||
long long P[] = { -29088885112832LL, -2184860175433728LL, -19686087844429824LL, -48165109676113920LL, -39471306959486976LL, -11124607890751488LL, -965271355195392LL, -18733264797696LL, -34357248000LL, -262144 };
|
||||
return boost::math::pow<19>(constants::pi<T, Policy>(), pol) * tools::evaluate_even_polynomial(P, c) / boost::math::pow<20>(s, pol);
|
||||
}
|
||||
case 20:
|
||||
{
|
||||
long long P[] = { 4951498053124096LL, 118071834535526400LL, 603968063567560704LL, 990081991141490688LL, 584901762421358592LL, 122829335169859584LL, 7984436548730880LL, 112949304754176LL, 137433710592LL, 524288 };
|
||||
return boost::math::pow<20>(constants::pi<T, Policy>(), pol) * c * tools::evaluate_even_polynomial(P, c) / boost::math::pow<21>(s, pol);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
// We'll have to compute the coefficients up to n,
|
||||
// complexity is O(n^2) which we don't worry about for now
|
||||
// as the values are computed once and then cached.
|
||||
// However, if the final evaluation would have too many
|
||||
// terms just bail out right away:
|
||||
//
|
||||
if((unsigned)n / 2u > policies::get_max_series_iterations<Policy>())
|
||||
return policies::raise_evaluation_error<T>(function, "The value of n is so large that we're unable to compute the result in reasonable time, best guess is %1%", 0, pol);
|
||||
#ifdef BOOST_HAS_THREADS
|
||||
static boost::detail::lightweight_mutex m;
|
||||
boost::detail::lightweight_mutex::scoped_lock l(m);
|
||||
#endif
|
||||
static int digits = tools::digits<T>();
|
||||
static std::vector<std::vector<T> > table(1, std::vector<T>(1, T(-1)));
|
||||
|
||||
int current_digits = tools::digits<T>();
|
||||
|
||||
if(digits != current_digits)
|
||||
{
|
||||
// Oh my... our precision has changed!
|
||||
table = std::vector<std::vector<T> >(1, std::vector<T>(1, T(-1)));
|
||||
digits = current_digits;
|
||||
}
|
||||
|
||||
int index = n - 1;
|
||||
|
||||
if(index >= (int)table.size())
|
||||
{
|
||||
for(int i = (int)table.size() - 1; i < index; ++i)
|
||||
{
|
||||
int offset = i & 1; // 1 if the first cos power is 0, otherwise 0.
|
||||
int sin_order = i + 2; // order of the sin term
|
||||
int max_cos_order = sin_order - 1; // largest order of the polynomial of cos terms
|
||||
int max_columns = (max_cos_order - offset) / 2; // How many entries there are in the current row.
|
||||
int next_offset = offset ? 0 : 1;
|
||||
int next_max_columns = (max_cos_order + 1 - next_offset) / 2; // How many entries there will be in the next row
|
||||
table.push_back(std::vector<T>(next_max_columns + 1, T(0)));
|
||||
|
||||
for(int column = 0; column <= max_columns; ++column)
|
||||
{
|
||||
int cos_order = 2 * column + offset; // order of the cosine term in entry "column"
|
||||
BOOST_ASSERT(column < (int)table[i].size());
|
||||
BOOST_ASSERT((cos_order + 1) / 2 < (int)table[i + 1].size());
|
||||
table[i + 1][(cos_order + 1) / 2] += ((cos_order - sin_order) * table[i][column]) / (sin_order - 1);
|
||||
if(cos_order)
|
||||
table[i + 1][(cos_order - 1) / 2] += (-cos_order * table[i][column]) / (sin_order - 1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
T sum = boost::math::tools::evaluate_even_polynomial(&table[index][0], c, table[index].size());
|
||||
if(index & 1)
|
||||
sum *= c; // First coeffient is order 1, and really an odd polynomial.
|
||||
if(sum == 0)
|
||||
return sum;
|
||||
//
|
||||
// The remaining terms are computed using logs since the powers and factorials
|
||||
// get real large real quick:
|
||||
//
|
||||
T power_terms = n * log(boost::math::constants::pi<T>());
|
||||
if(s == 0)
|
||||
return sum * boost::math::policies::raise_overflow_error<T>(function, 0, pol);
|
||||
power_terms -= log(fabs(s)) * (n + 1);
|
||||
power_terms += boost::math::lgamma(T(n));
|
||||
power_terms += log(fabs(sum));
|
||||
|
||||
if(power_terms > boost::math::tools::log_max_value<T>())
|
||||
return sum * boost::math::policies::raise_overflow_error<T>(function, 0, pol);
|
||||
|
||||
return exp(power_terms) * ((s < 0) && ((n + 1) & 1) ? -1 : 1) * boost::math::sign(sum);
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
struct polygamma_initializer
|
||||
{
|
||||
struct init
|
||||
{
|
||||
init()
|
||||
{
|
||||
// Forces initialization of our table of coefficients and mutex:
|
||||
boost::math::polygamma(30, T(-2.5f), Policy());
|
||||
}
|
||||
void force_instantiate()const{}
|
||||
};
|
||||
static const init initializer;
|
||||
static void force_instantiate()
|
||||
{
|
||||
initializer.force_instantiate();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class Policy>
|
||||
const typename polygamma_initializer<T, Policy>::init polygamma_initializer<T, Policy>::initializer;
|
||||
|
||||
template<class T, class Policy>
|
||||
inline T polygamma_imp(const int n, T x, const Policy &pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
static const char* function = "boost::math::polygamma<%1%>(int, %1%)";
|
||||
polygamma_initializer<T, Policy>::initializer.force_instantiate();
|
||||
if(n < 0)
|
||||
return policies::raise_domain_error<T>(function, "Order must be >= 0, but got %1%", static_cast<T>(n), pol);
|
||||
if(x < 0)
|
||||
{
|
||||
if(floor(x) == x)
|
||||
{
|
||||
//
|
||||
// Result is infinity if x is odd, and a pole error if x is even.
|
||||
//
|
||||
if(lltrunc(x) & 1)
|
||||
return policies::raise_overflow_error<T>(function, 0, pol);
|
||||
else
|
||||
return policies::raise_pole_error<T>(function, "Evaluation at negative integer %1%", x, pol);
|
||||
}
|
||||
T z = 1 - x;
|
||||
T result = polygamma_imp(n, z, pol) + constants::pi<T, Policy>() * poly_cot_pi(n, z, x, pol, function);
|
||||
return n & 1 ? T(-result) : result;
|
||||
}
|
||||
//
|
||||
// Limit for use of small-x-series is chosen
|
||||
// so that the series doesn't go too divergent
|
||||
// in the first few terms. Ordinarily this
|
||||
// would mean setting the limit to ~ 1 / n,
|
||||
// but we can tolerate a small amount of divergence:
|
||||
//
|
||||
T small_x_limit = (std::min)(T(T(5) / n), T(0.25f));
|
||||
if(x < small_x_limit)
|
||||
{
|
||||
return polygamma_nearzero(n, x, pol, function);
|
||||
}
|
||||
else if(x > 0.4F * policies::digits_base10<T, Policy>() + 4.0f * n)
|
||||
{
|
||||
return polygamma_atinfinityplus(n, x, pol, function);
|
||||
}
|
||||
else if(x == 1)
|
||||
{
|
||||
return (n & 1 ? 1 : -1) * boost::math::factorial<T>(n, pol) * boost::math::zeta(T(n + 1), pol);
|
||||
}
|
||||
else if(x == 0.5f)
|
||||
{
|
||||
T result = (n & 1 ? 1 : -1) * boost::math::factorial<T>(n, pol) * boost::math::zeta(T(n + 1), pol);
|
||||
if(fabs(result) >= ldexp(tools::max_value<T>(), -n - 1))
|
||||
return boost::math::sign(result) * policies::raise_overflow_error<T>(function, 0, pol);
|
||||
result *= ldexp(T(1), n + 1) - 1;
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return polygamma_attransitionplus(n, x, pol, function);
|
||||
}
|
||||
}
|
||||
|
||||
} } } // namespace boost::math::detail
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif // _BOOST_POLYGAMMA_DETAIL_2013_07_30_HPP_
|
||||
|
||||
93
code_isotrope/boost/math/special_functions/detail/round_fwd.hpp
Executable file
93
code_isotrope/boost/math/special_functions/detail/round_fwd.hpp
Executable file
@@ -0,0 +1,93 @@
|
||||
// Copyright John Maddock 2008.
|
||||
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_MATH_SPECIAL_ROUND_FWD_HPP
|
||||
#define BOOST_MATH_SPECIAL_ROUND_FWD_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/math/tools/promotion.hpp>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace math
|
||||
{
|
||||
|
||||
template <class T, class Policy>
|
||||
typename tools::promote_args<T>::type trunc(const T& v, const Policy& pol);
|
||||
template <class T>
|
||||
typename tools::promote_args<T>::type trunc(const T& v);
|
||||
template <class T, class Policy>
|
||||
int itrunc(const T& v, const Policy& pol);
|
||||
template <class T>
|
||||
int itrunc(const T& v);
|
||||
template <class T, class Policy>
|
||||
long ltrunc(const T& v, const Policy& pol);
|
||||
template <class T>
|
||||
long ltrunc(const T& v);
|
||||
#ifdef BOOST_HAS_LONG_LONG
|
||||
template <class T, class Policy>
|
||||
boost::long_long_type lltrunc(const T& v, const Policy& pol);
|
||||
template <class T>
|
||||
boost::long_long_type lltrunc(const T& v);
|
||||
#endif
|
||||
template <class T, class Policy>
|
||||
typename tools::promote_args<T>::type round(const T& v, const Policy& pol);
|
||||
template <class T>
|
||||
typename tools::promote_args<T>::type round(const T& v);
|
||||
template <class T, class Policy>
|
||||
int iround(const T& v, const Policy& pol);
|
||||
template <class T>
|
||||
int iround(const T& v);
|
||||
template <class T, class Policy>
|
||||
long lround(const T& v, const Policy& pol);
|
||||
template <class T>
|
||||
long lround(const T& v);
|
||||
#ifdef BOOST_HAS_LONG_LONG
|
||||
template <class T, class Policy>
|
||||
boost::long_long_type llround(const T& v, const Policy& pol);
|
||||
template <class T>
|
||||
boost::long_long_type llround(const T& v);
|
||||
#endif
|
||||
template <class T, class Policy>
|
||||
T modf(const T& v, T* ipart, const Policy& pol);
|
||||
template <class T>
|
||||
T modf(const T& v, T* ipart);
|
||||
template <class T, class Policy>
|
||||
T modf(const T& v, int* ipart, const Policy& pol);
|
||||
template <class T>
|
||||
T modf(const T& v, int* ipart);
|
||||
template <class T, class Policy>
|
||||
T modf(const T& v, long* ipart, const Policy& pol);
|
||||
template <class T>
|
||||
T modf(const T& v, long* ipart);
|
||||
#ifdef BOOST_HAS_LONG_LONG
|
||||
template <class T, class Policy>
|
||||
T modf(const T& v, boost::long_long_type* ipart, const Policy& pol);
|
||||
template <class T>
|
||||
T modf(const T& v, boost::long_long_type* ipart);
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#undef BOOST_MATH_STD_USING
|
||||
#define BOOST_MATH_STD_USING BOOST_MATH_STD_USING_CORE\
|
||||
using boost::math::round;\
|
||||
using boost::math::iround;\
|
||||
using boost::math::lround;\
|
||||
using boost::math::trunc;\
|
||||
using boost::math::itrunc;\
|
||||
using boost::math::ltrunc;\
|
||||
using boost::math::modf;
|
||||
|
||||
|
||||
#endif // BOOST_MATH_SPECIAL_ROUND_FWD_HPP
|
||||
|
||||
549
code_isotrope/boost/math/special_functions/detail/t_distribution_inv.hpp
Executable file
549
code_isotrope/boost/math/special_functions/detail/t_distribution_inv.hpp
Executable file
@@ -0,0 +1,549 @@
|
||||
// Copyright John Maddock 2007.
|
||||
// Copyright Paul A. Bristow 2007
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_MATH_SF_DETAIL_INV_T_HPP
|
||||
#define BOOST_MATH_SF_DETAIL_INV_T_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/special_functions/cbrt.hpp>
|
||||
#include <boost/math/special_functions/round.hpp>
|
||||
#include <boost/math/special_functions/trunc.hpp>
|
||||
|
||||
namespace boost{ namespace math{ namespace detail{
|
||||
|
||||
//
|
||||
// The main method used is due to Hill:
|
||||
//
|
||||
// G. W. Hill, Algorithm 396, Student's t-Quantiles,
|
||||
// Communications of the ACM, 13(10): 619-620, Oct., 1970.
|
||||
//
|
||||
template <class T, class Policy>
|
||||
T inverse_students_t_hill(T ndf, T u, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
BOOST_ASSERT(u <= 0.5);
|
||||
|
||||
T a, b, c, d, q, x, y;
|
||||
|
||||
if (ndf > 1e20f)
|
||||
return -boost::math::erfc_inv(2 * u, pol) * constants::root_two<T>();
|
||||
|
||||
a = 1 / (ndf - 0.5f);
|
||||
b = 48 / (a * a);
|
||||
c = ((20700 * a / b - 98) * a - 16) * a + 96.36f;
|
||||
d = ((94.5f / (b + c) - 3) / b + 1) * sqrt(a * constants::pi<T>() / 2) * ndf;
|
||||
y = pow(d * 2 * u, 2 / ndf);
|
||||
|
||||
if (y > (0.05f + a))
|
||||
{
|
||||
//
|
||||
// Asymptotic inverse expansion about normal:
|
||||
//
|
||||
x = -boost::math::erfc_inv(2 * u, pol) * constants::root_two<T>();
|
||||
y = x * x;
|
||||
|
||||
if (ndf < 5)
|
||||
c += 0.3f * (ndf - 4.5f) * (x + 0.6f);
|
||||
c += (((0.05f * d * x - 5) * x - 7) * x - 2) * x + b;
|
||||
y = (((((0.4f * y + 6.3f) * y + 36) * y + 94.5f) / c - y - 3) / b + 1) * x;
|
||||
y = boost::math::expm1(a * y * y, pol);
|
||||
}
|
||||
else
|
||||
{
|
||||
y = static_cast<T>(((1 / (((ndf + 6) / (ndf * y) - 0.089f * d - 0.822f)
|
||||
* (ndf + 2) * 3) + 0.5 / (ndf + 4)) * y - 1)
|
||||
* (ndf + 1) / (ndf + 2) + 1 / y);
|
||||
}
|
||||
q = sqrt(ndf * y);
|
||||
|
||||
return -q;
|
||||
}
|
||||
//
|
||||
// Tail and body series are due to Shaw:
|
||||
//
|
||||
// www.mth.kcl.ac.uk/~shaww/web_page/papers/Tdistribution06.pdf
|
||||
//
|
||||
// Shaw, W.T., 2006, "Sampling Student's T distribution - use of
|
||||
// the inverse cumulative distribution function."
|
||||
// Journal of Computational Finance, Vol 9 Issue 4, pp 37-73, Summer 2006
|
||||
//
|
||||
template <class T, class Policy>
|
||||
T inverse_students_t_tail_series(T df, T v, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
// Tail series expansion, see section 6 of Shaw's paper.
|
||||
// w is calculated using Eq 60:
|
||||
T w = boost::math::tgamma_delta_ratio(df / 2, constants::half<T>(), pol)
|
||||
* sqrt(df * constants::pi<T>()) * v;
|
||||
// define some variables:
|
||||
T np2 = df + 2;
|
||||
T np4 = df + 4;
|
||||
T np6 = df + 6;
|
||||
//
|
||||
// Calculate the coefficients d(k), these depend only on the
|
||||
// number of degrees of freedom df, so at least in theory
|
||||
// we could tabulate these for fixed df, see p15 of Shaw:
|
||||
//
|
||||
T d[7] = { 1, };
|
||||
d[1] = -(df + 1) / (2 * np2);
|
||||
np2 *= (df + 2);
|
||||
d[2] = -df * (df + 1) * (df + 3) / (8 * np2 * np4);
|
||||
np2 *= df + 2;
|
||||
d[3] = -df * (df + 1) * (df + 5) * (((3 * df) + 7) * df -2) / (48 * np2 * np4 * np6);
|
||||
np2 *= (df + 2);
|
||||
np4 *= (df + 4);
|
||||
d[4] = -df * (df + 1) * (df + 7) *
|
||||
( (((((15 * df) + 154) * df + 465) * df + 286) * df - 336) * df + 64 )
|
||||
/ (384 * np2 * np4 * np6 * (df + 8));
|
||||
np2 *= (df + 2);
|
||||
d[5] = -df * (df + 1) * (df + 3) * (df + 9)
|
||||
* (((((((35 * df + 452) * df + 1573) * df + 600) * df - 2020) * df) + 928) * df -128)
|
||||
/ (1280 * np2 * np4 * np6 * (df + 8) * (df + 10));
|
||||
np2 *= (df + 2);
|
||||
np4 *= (df + 4);
|
||||
np6 *= (df + 6);
|
||||
d[6] = -df * (df + 1) * (df + 11)
|
||||
* ((((((((((((945 * df) + 31506) * df + 425858) * df + 2980236) * df + 11266745) * df + 20675018) * df + 7747124) * df - 22574632) * df - 8565600) * df + 18108416) * df - 7099392) * df + 884736)
|
||||
/ (46080 * np2 * np4 * np6 * (df + 8) * (df + 10) * (df +12));
|
||||
//
|
||||
// Now bring everthing together to provide the result,
|
||||
// this is Eq 62 of Shaw:
|
||||
//
|
||||
T rn = sqrt(df);
|
||||
T div = pow(rn * w, 1 / df);
|
||||
T power = div * div;
|
||||
T result = tools::evaluate_polynomial<7, T, T>(d, power);
|
||||
result *= rn;
|
||||
result /= div;
|
||||
return -result;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
T inverse_students_t_body_series(T df, T u, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
//
|
||||
// Body series for small N:
|
||||
//
|
||||
// Start with Eq 56 of Shaw:
|
||||
//
|
||||
T v = boost::math::tgamma_delta_ratio(df / 2, constants::half<T>(), pol)
|
||||
* sqrt(df * constants::pi<T>()) * (u - constants::half<T>());
|
||||
//
|
||||
// Workspace for the polynomial coefficients:
|
||||
//
|
||||
T c[11] = { 0, 1, };
|
||||
//
|
||||
// Figure out what the coefficients are, note these depend
|
||||
// only on the degrees of freedom (Eq 57 of Shaw):
|
||||
//
|
||||
T in = 1 / df;
|
||||
c[2] = static_cast<T>(0.16666666666666666667 + 0.16666666666666666667 * in);
|
||||
c[3] = static_cast<T>((0.0083333333333333333333 * in
|
||||
+ 0.066666666666666666667) * in
|
||||
+ 0.058333333333333333333);
|
||||
c[4] = static_cast<T>(((0.00019841269841269841270 * in
|
||||
+ 0.0017857142857142857143) * in
|
||||
+ 0.026785714285714285714) * in
|
||||
+ 0.025198412698412698413);
|
||||
c[5] = static_cast<T>((((2.7557319223985890653e-6 * in
|
||||
+ 0.00037477954144620811287) * in
|
||||
- 0.0011078042328042328042) * in
|
||||
+ 0.010559964726631393298) * in
|
||||
+ 0.012039792768959435626);
|
||||
c[6] = static_cast<T>(((((2.5052108385441718775e-8 * in
|
||||
- 0.000062705427288760622094) * in
|
||||
+ 0.00059458674042007375341) * in
|
||||
- 0.0016095979637646304313) * in
|
||||
+ 0.0061039211560044893378) * in
|
||||
+ 0.0038370059724226390893);
|
||||
c[7] = static_cast<T>((((((1.6059043836821614599e-10 * in
|
||||
+ 0.000015401265401265401265) * in
|
||||
- 0.00016376804137220803887) * in
|
||||
+ 0.00069084207973096861986) * in
|
||||
- 0.0012579159844784844785) * in
|
||||
+ 0.0010898206731540064873) * in
|
||||
+ 0.0032177478835464946576);
|
||||
c[8] = static_cast<T>(((((((7.6471637318198164759e-13 * in
|
||||
- 3.9851014346715404916e-6) * in
|
||||
+ 0.000049255746366361445727) * in
|
||||
- 0.00024947258047043099953) * in
|
||||
+ 0.00064513046951456342991) * in
|
||||
- 0.00076245135440323932387) * in
|
||||
+ 0.000033530976880017885309) * in
|
||||
+ 0.0017438262298340009980);
|
||||
c[9] = static_cast<T>((((((((2.8114572543455207632e-15 * in
|
||||
+ 1.0914179173496789432e-6) * in
|
||||
- 0.000015303004486655377567) * in
|
||||
+ 0.000090867107935219902229) * in
|
||||
- 0.00029133414466938067350) * in
|
||||
+ 0.00051406605788341121363) * in
|
||||
- 0.00036307660358786885787) * in
|
||||
- 0.00031101086326318780412) * in
|
||||
+ 0.00096472747321388644237);
|
||||
c[10] = static_cast<T>(((((((((8.2206352466243297170e-18 * in
|
||||
- 3.1239569599829868045e-7) * in
|
||||
+ 4.8903045291975346210e-6) * in
|
||||
- 0.000033202652391372058698) * in
|
||||
+ 0.00012645437628698076975) * in
|
||||
- 0.00028690924218514613987) * in
|
||||
+ 0.00035764655430568632777) * in
|
||||
- 0.00010230378073700412687) * in
|
||||
- 0.00036942667800009661203) * in
|
||||
+ 0.00054229262813129686486);
|
||||
//
|
||||
// The result is then a polynomial in v (see Eq 56 of Shaw):
|
||||
//
|
||||
return tools::evaluate_odd_polynomial<11, T, T>(c, v);
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
T inverse_students_t(T df, T u, T v, const Policy& pol, bool* pexact = 0)
|
||||
{
|
||||
//
|
||||
// df = number of degrees of freedom.
|
||||
// u = probablity.
|
||||
// v = 1 - u.
|
||||
// l = lanczos type to use.
|
||||
//
|
||||
BOOST_MATH_STD_USING
|
||||
bool invert = false;
|
||||
T result = 0;
|
||||
if(pexact)
|
||||
*pexact = false;
|
||||
if(u > v)
|
||||
{
|
||||
// function is symmetric, invert it:
|
||||
std::swap(u, v);
|
||||
invert = true;
|
||||
}
|
||||
if((floor(df) == df) && (df < 20))
|
||||
{
|
||||
//
|
||||
// we have integer degrees of freedom, try for the special
|
||||
// cases first:
|
||||
//
|
||||
T tolerance = ldexp(1.0f, (2 * policies::digits<T, Policy>()) / 3);
|
||||
|
||||
switch(itrunc(df, Policy()))
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
//
|
||||
// df = 1 is the same as the Cauchy distribution, see
|
||||
// Shaw Eq 35:
|
||||
//
|
||||
if(u == 0.5)
|
||||
result = 0;
|
||||
else
|
||||
result = -cos(constants::pi<T>() * u) / sin(constants::pi<T>() * u);
|
||||
if(pexact)
|
||||
*pexact = true;
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
//
|
||||
// df = 2 has an exact result, see Shaw Eq 36:
|
||||
//
|
||||
result =(2 * u - 1) / sqrt(2 * u * v);
|
||||
if(pexact)
|
||||
*pexact = true;
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
//
|
||||
// df = 4 has an exact result, see Shaw Eq 38 & 39:
|
||||
//
|
||||
T alpha = 4 * u * v;
|
||||
T root_alpha = sqrt(alpha);
|
||||
T r = 4 * cos(acos(root_alpha) / 3) / root_alpha;
|
||||
T x = sqrt(r - 4);
|
||||
result = u - 0.5f < 0 ? (T)-x : x;
|
||||
if(pexact)
|
||||
*pexact = true;
|
||||
break;
|
||||
}
|
||||
case 6:
|
||||
{
|
||||
//
|
||||
// We get numeric overflow in this area:
|
||||
//
|
||||
if(u < 1e-150)
|
||||
return (invert ? -1 : 1) * inverse_students_t_hill(df, u, pol);
|
||||
//
|
||||
// Newton-Raphson iteration of a polynomial case,
|
||||
// choice of seed value is taken from Shaw's online
|
||||
// supplement:
|
||||
//
|
||||
T a = 4 * (u - u * u);//1 - 4 * (u - 0.5f) * (u - 0.5f);
|
||||
T b = boost::math::cbrt(a);
|
||||
static const T c = static_cast<T>(0.85498797333834849467655443627193);
|
||||
T p = 6 * (1 + c * (1 / b - 1));
|
||||
T p0;
|
||||
do{
|
||||
T p2 = p * p;
|
||||
T p4 = p2 * p2;
|
||||
T p5 = p * p4;
|
||||
p0 = p;
|
||||
// next term is given by Eq 41:
|
||||
p = 2 * (8 * a * p5 - 270 * p2 + 2187) / (5 * (4 * a * p4 - 216 * p - 243));
|
||||
}while(fabs((p - p0) / p) > tolerance);
|
||||
//
|
||||
// Use Eq 45 to extract the result:
|
||||
//
|
||||
p = sqrt(p - df);
|
||||
result = (u - 0.5f) < 0 ? (T)-p : p;
|
||||
break;
|
||||
}
|
||||
#if 0
|
||||
//
|
||||
// These are Shaw's "exact" but iterative solutions
|
||||
// for even df, the numerical accuracy of these is
|
||||
// rather less than Hill's method, so these are disabled
|
||||
// for now, which is a shame because they are reasonably
|
||||
// quick to evaluate...
|
||||
//
|
||||
case 8:
|
||||
{
|
||||
//
|
||||
// Newton-Raphson iteration of a polynomial case,
|
||||
// choice of seed value is taken from Shaw's online
|
||||
// supplement:
|
||||
//
|
||||
static const T c8 = 0.85994765706259820318168359251872L;
|
||||
T a = 4 * (u - u * u); //1 - 4 * (u - 0.5f) * (u - 0.5f);
|
||||
T b = pow(a, T(1) / 4);
|
||||
T p = 8 * (1 + c8 * (1 / b - 1));
|
||||
T p0 = p;
|
||||
do{
|
||||
T p5 = p * p;
|
||||
p5 *= p5 * p;
|
||||
p0 = p;
|
||||
// Next term is given by Eq 42:
|
||||
p = 2 * (3 * p + (640 * (160 + p * (24 + p * (p + 4)))) / (-5120 + p * (-2048 - 960 * p + a * p5))) / 7;
|
||||
}while(fabs((p - p0) / p) > tolerance);
|
||||
//
|
||||
// Use Eq 45 to extract the result:
|
||||
//
|
||||
p = sqrt(p - df);
|
||||
result = (u - 0.5f) < 0 ? -p : p;
|
||||
break;
|
||||
}
|
||||
case 10:
|
||||
{
|
||||
//
|
||||
// Newton-Raphson iteration of a polynomial case,
|
||||
// choice of seed value is taken from Shaw's online
|
||||
// supplement:
|
||||
//
|
||||
static const T c10 = 0.86781292867813396759105692122285L;
|
||||
T a = 4 * (u - u * u); //1 - 4 * (u - 0.5f) * (u - 0.5f);
|
||||
T b = pow(a, T(1) / 5);
|
||||
T p = 10 * (1 + c10 * (1 / b - 1));
|
||||
T p0;
|
||||
do{
|
||||
T p6 = p * p;
|
||||
p6 *= p6 * p6;
|
||||
p0 = p;
|
||||
// Next term given by Eq 43:
|
||||
p = (8 * p) / 9 + (218750 * (21875 + 4 * p * (625 + p * (75 + 2 * p * (5 + p))))) /
|
||||
(9 * (-68359375 + 8 * p * (-2343750 + p * (-546875 - 175000 * p + 8 * a * p6))));
|
||||
}while(fabs((p - p0) / p) > tolerance);
|
||||
//
|
||||
// Use Eq 45 to extract the result:
|
||||
//
|
||||
p = sqrt(p - df);
|
||||
result = (u - 0.5f) < 0 ? -p : p;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
goto calculate_real;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
calculate_real:
|
||||
if(df > 0x10000000)
|
||||
{
|
||||
result = -boost::math::erfc_inv(2 * u, pol) * constants::root_two<T>();
|
||||
if((pexact) && (df >= 1e20))
|
||||
*pexact = true;
|
||||
}
|
||||
else if(df < 3)
|
||||
{
|
||||
//
|
||||
// Use a roughly linear scheme to choose between Shaw's
|
||||
// tail series and body series:
|
||||
//
|
||||
T crossover = 0.2742f - df * 0.0242143f;
|
||||
if(u > crossover)
|
||||
{
|
||||
result = boost::math::detail::inverse_students_t_body_series(df, u, pol);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = boost::math::detail::inverse_students_t_tail_series(df, u, pol);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Use Hill's method except in the exteme tails
|
||||
// where we use Shaw's tail series.
|
||||
// The crossover point is roughly exponential in -df:
|
||||
//
|
||||
T crossover = ldexp(1.0f, iround(T(df / -0.654f), typename policies::normalise<Policy, policies::rounding_error<policies::ignore_error> >::type()));
|
||||
if(u > crossover)
|
||||
{
|
||||
result = boost::math::detail::inverse_students_t_hill(df, u, pol);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = boost::math::detail::inverse_students_t_tail_series(df, u, pol);
|
||||
}
|
||||
}
|
||||
}
|
||||
return invert ? (T)-result : result;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T find_ibeta_inv_from_t_dist(T a, T p, T /*q*/, T* py, const Policy& pol)
|
||||
{
|
||||
T u = p / 2;
|
||||
T v = 1 - u;
|
||||
T df = a * 2;
|
||||
T t = boost::math::detail::inverse_students_t(df, u, v, pol);
|
||||
*py = t * t / (df + t * t);
|
||||
return df / (df + t * t);
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T fast_students_t_quantile_imp(T df, T p, const Policy& pol, const mpl::false_*)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
//
|
||||
// Need to use inverse incomplete beta to get
|
||||
// required precision so not so fast:
|
||||
//
|
||||
T probability = (p > 0.5) ? 1 - p : p;
|
||||
T t, x, y(0);
|
||||
x = ibeta_inv(df / 2, T(0.5), 2 * probability, &y, pol);
|
||||
if(df * y > tools::max_value<T>() * x)
|
||||
t = policies::raise_overflow_error<T>("boost::math::students_t_quantile<%1%>(%1%,%1%)", 0, pol);
|
||||
else
|
||||
t = sqrt(df * y / x);
|
||||
//
|
||||
// Figure out sign based on the size of p:
|
||||
//
|
||||
if(p < 0.5)
|
||||
t = -t;
|
||||
return t;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
T fast_students_t_quantile_imp(T df, T p, const Policy& pol, const mpl::true_*)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
bool invert = false;
|
||||
if((df < 2) && (floor(df) != df))
|
||||
return boost::math::detail::fast_students_t_quantile_imp(df, p, pol, static_cast<mpl::false_*>(0));
|
||||
if(p > 0.5)
|
||||
{
|
||||
p = 1 - p;
|
||||
invert = true;
|
||||
}
|
||||
//
|
||||
// Get an estimate of the result:
|
||||
//
|
||||
bool exact;
|
||||
T t = inverse_students_t(df, p, T(1-p), pol, &exact);
|
||||
if((t == 0) || exact)
|
||||
return invert ? -t : t; // can't do better!
|
||||
//
|
||||
// Change variables to inverse incomplete beta:
|
||||
//
|
||||
T t2 = t * t;
|
||||
T xb = df / (df + t2);
|
||||
T y = t2 / (df + t2);
|
||||
T a = df / 2;
|
||||
//
|
||||
// t can be so large that x underflows,
|
||||
// just return our estimate in that case:
|
||||
//
|
||||
if(xb == 0)
|
||||
return t;
|
||||
//
|
||||
// Get incomplete beta and it's derivative:
|
||||
//
|
||||
T f1;
|
||||
T f0 = xb < y ? ibeta_imp(a, constants::half<T>(), xb, pol, false, true, &f1)
|
||||
: ibeta_imp(constants::half<T>(), a, y, pol, true, true, &f1);
|
||||
|
||||
// Get cdf from incomplete beta result:
|
||||
T p0 = f0 / 2 - p;
|
||||
// Get pdf from derivative:
|
||||
T p1 = f1 * sqrt(y * xb * xb * xb / df);
|
||||
//
|
||||
// Second derivative divided by p1:
|
||||
//
|
||||
// yacas gives:
|
||||
//
|
||||
// In> PrettyForm(Simplify(D(t) (1 + t^2/v) ^ (-(v+1)/2)))
|
||||
//
|
||||
// | | v + 1 | |
|
||||
// | -| ----- + 1 | |
|
||||
// | | 2 | |
|
||||
// -| | 2 | |
|
||||
// | | t | |
|
||||
// | | -- + 1 | |
|
||||
// | ( v + 1 ) * | v | * t |
|
||||
// ---------------------------------------------
|
||||
// v
|
||||
//
|
||||
// Which after some manipulation is:
|
||||
//
|
||||
// -p1 * t * (df + 1) / (t^2 + df)
|
||||
//
|
||||
T p2 = t * (df + 1) / (t * t + df);
|
||||
// Halley step:
|
||||
t = fabs(t);
|
||||
t += p0 / (p1 + p0 * p2 / 2);
|
||||
return !invert ? -t : t;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T fast_students_t_quantile(T df, T p, const Policy& pol)
|
||||
{
|
||||
typedef typename policies::evaluation<T, Policy>::type value_type;
|
||||
typedef typename policies::normalise<
|
||||
Policy,
|
||||
policies::promote_float<false>,
|
||||
policies::promote_double<false>,
|
||||
policies::discrete_quantile<>,
|
||||
policies::assert_undefined<> >::type forwarding_policy;
|
||||
|
||||
typedef mpl::bool_<
|
||||
(std::numeric_limits<T>::digits <= 53)
|
||||
&&
|
||||
(std::numeric_limits<T>::is_specialized)
|
||||
&&
|
||||
(std::numeric_limits<T>::radix == 2)
|
||||
> tag_type;
|
||||
return policies::checked_narrowing_cast<T, forwarding_policy>(fast_students_t_quantile_imp(static_cast<value_type>(df), static_cast<value_type>(p), pol, static_cast<tag_type*>(0)), "boost::math::students_t_quantile<%1%>(%1%,%1%,%1%)");
|
||||
}
|
||||
|
||||
}}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_SF_DETAIL_INV_T_HPP
|
||||
|
||||
|
||||
|
||||
727
code_isotrope/boost/math/special_functions/detail/unchecked_bernoulli.hpp
Executable file
727
code_isotrope/boost/math/special_functions/detail/unchecked_bernoulli.hpp
Executable file
File diff suppressed because one or more lines are too long
805
code_isotrope/boost/math/special_functions/detail/unchecked_factorial.hpp
Executable file
805
code_isotrope/boost/math/special_functions/detail/unchecked_factorial.hpp
Executable file
@@ -0,0 +1,805 @@
|
||||
// Copyright John Maddock 2006.
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_MATH_SP_UC_FACTORIALS_HPP
|
||||
#define BOOST_MATH_SP_UC_FACTORIALS_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(push) // Temporary until lexical cast fixed.
|
||||
#pragma warning(disable: 4127 4701)
|
||||
#endif
|
||||
#ifndef BOOST_MATH_NO_LEXICAL_CAST
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#endif
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
#include <cmath>
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
|
||||
#ifdef BOOST_MATH_HAVE_CONSTEXPR_TABLES
|
||||
#include <array>
|
||||
#else
|
||||
#include <boost/array.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost { namespace math
|
||||
{
|
||||
// Forward declarations:
|
||||
template <class T>
|
||||
struct max_factorial;
|
||||
|
||||
// Definitions:
|
||||
template <>
|
||||
inline BOOST_MATH_CONSTEXPR_TABLE_FUNCTION float unchecked_factorial<float>(unsigned i BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(float))
|
||||
{
|
||||
#ifdef BOOST_MATH_HAVE_CONSTEXPR_TABLES
|
||||
constexpr std::array<float, 35> factorials = { {
|
||||
#else
|
||||
static const boost::array<float, 35> factorials = {{
|
||||
#endif
|
||||
1.0F,
|
||||
1.0F,
|
||||
2.0F,
|
||||
6.0F,
|
||||
24.0F,
|
||||
120.0F,
|
||||
720.0F,
|
||||
5040.0F,
|
||||
40320.0F,
|
||||
362880.0F,
|
||||
3628800.0F,
|
||||
39916800.0F,
|
||||
479001600.0F,
|
||||
6227020800.0F,
|
||||
87178291200.0F,
|
||||
1307674368000.0F,
|
||||
20922789888000.0F,
|
||||
355687428096000.0F,
|
||||
6402373705728000.0F,
|
||||
121645100408832000.0F,
|
||||
0.243290200817664e19F,
|
||||
0.5109094217170944e20F,
|
||||
0.112400072777760768e22F,
|
||||
0.2585201673888497664e23F,
|
||||
0.62044840173323943936e24F,
|
||||
0.15511210043330985984e26F,
|
||||
0.403291461126605635584e27F,
|
||||
0.10888869450418352160768e29F,
|
||||
0.304888344611713860501504e30F,
|
||||
0.8841761993739701954543616e31F,
|
||||
0.26525285981219105863630848e33F,
|
||||
0.822283865417792281772556288e34F,
|
||||
0.26313083693369353016721801216e36F,
|
||||
0.868331761881188649551819440128e37F,
|
||||
0.29523279903960414084761860964352e39F,
|
||||
}};
|
||||
|
||||
return factorials[i];
|
||||
}
|
||||
|
||||
template <>
|
||||
struct max_factorial<float>
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(unsigned, value = 34);
|
||||
};
|
||||
|
||||
|
||||
template <>
|
||||
inline BOOST_MATH_CONSTEXPR_TABLE_FUNCTION long double unchecked_factorial<long double>(unsigned i BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(long double))
|
||||
{
|
||||
#ifdef BOOST_MATH_HAVE_CONSTEXPR_TABLES
|
||||
constexpr std::array<long double, 171> factorials = { {
|
||||
#else
|
||||
static const boost::array<long double, 171> factorials = {{
|
||||
#endif
|
||||
1L,
|
||||
1L,
|
||||
2L,
|
||||
6L,
|
||||
24L,
|
||||
120L,
|
||||
720L,
|
||||
5040L,
|
||||
40320L,
|
||||
362880.0L,
|
||||
3628800.0L,
|
||||
39916800.0L,
|
||||
479001600.0L,
|
||||
6227020800.0L,
|
||||
87178291200.0L,
|
||||
1307674368000.0L,
|
||||
20922789888000.0L,
|
||||
355687428096000.0L,
|
||||
6402373705728000.0L,
|
||||
121645100408832000.0L,
|
||||
0.243290200817664e19L,
|
||||
0.5109094217170944e20L,
|
||||
0.112400072777760768e22L,
|
||||
0.2585201673888497664e23L,
|
||||
0.62044840173323943936e24L,
|
||||
0.15511210043330985984e26L,
|
||||
0.403291461126605635584e27L,
|
||||
0.10888869450418352160768e29L,
|
||||
0.304888344611713860501504e30L,
|
||||
0.8841761993739701954543616e31L,
|
||||
0.26525285981219105863630848e33L,
|
||||
0.822283865417792281772556288e34L,
|
||||
0.26313083693369353016721801216e36L,
|
||||
0.868331761881188649551819440128e37L,
|
||||
0.29523279903960414084761860964352e39L,
|
||||
0.103331479663861449296666513375232e41L,
|
||||
0.3719933267899012174679994481508352e42L,
|
||||
0.137637530912263450463159795815809024e44L,
|
||||
0.5230226174666011117600072241000742912e45L,
|
||||
0.203978820811974433586402817399028973568e47L,
|
||||
0.815915283247897734345611269596115894272e48L,
|
||||
0.3345252661316380710817006205344075166515e50L,
|
||||
0.1405006117752879898543142606244511569936e52L,
|
||||
0.6041526306337383563735513206851399750726e53L,
|
||||
0.265827157478844876804362581101461589032e55L,
|
||||
0.1196222208654801945619631614956577150644e57L,
|
||||
0.5502622159812088949850305428800254892962e58L,
|
||||
0.2586232415111681806429643551536119799692e60L,
|
||||
0.1241391559253607267086228904737337503852e62L,
|
||||
0.6082818640342675608722521633212953768876e63L,
|
||||
0.3041409320171337804361260816606476884438e65L,
|
||||
0.1551118753287382280224243016469303211063e67L,
|
||||
0.8065817517094387857166063685640376697529e68L,
|
||||
0.427488328406002556429801375338939964969e70L,
|
||||
0.2308436973392413804720927426830275810833e72L,
|
||||
0.1269640335365827592596510084756651695958e74L,
|
||||
0.7109985878048634518540456474637249497365e75L,
|
||||
0.4052691950487721675568060190543232213498e77L,
|
||||
0.2350561331282878571829474910515074683829e79L,
|
||||
0.1386831185456898357379390197203894063459e81L,
|
||||
0.8320987112741390144276341183223364380754e82L,
|
||||
0.507580213877224798800856812176625227226e84L,
|
||||
0.3146997326038793752565312235495076408801e86L,
|
||||
0.1982608315404440064116146708361898137545e88L,
|
||||
0.1268869321858841641034333893351614808029e90L,
|
||||
0.8247650592082470666723170306785496252186e91L,
|
||||
0.5443449390774430640037292402478427526443e93L,
|
||||
0.3647111091818868528824985909660546442717e95L,
|
||||
0.2480035542436830599600990418569171581047e97L,
|
||||
0.1711224524281413113724683388812728390923e99L,
|
||||
0.1197857166996989179607278372168909873646e101L,
|
||||
0.8504785885678623175211676442399260102886e102L,
|
||||
0.6123445837688608686152407038527467274078e104L,
|
||||
0.4470115461512684340891257138125051110077e106L,
|
||||
0.3307885441519386412259530282212537821457e108L,
|
||||
0.2480914081139539809194647711659403366093e110L,
|
||||
0.188549470166605025498793226086114655823e112L,
|
||||
0.1451830920282858696340707840863082849837e114L,
|
||||
0.1132428117820629783145752115873204622873e116L,
|
||||
0.8946182130782975286851441715398316520698e117L,
|
||||
0.7156945704626380229481153372318653216558e119L,
|
||||
0.5797126020747367985879734231578109105412e121L,
|
||||
0.4753643337012841748421382069894049466438e123L,
|
||||
0.3945523969720658651189747118012061057144e125L,
|
||||
0.3314240134565353266999387579130131288001e127L,
|
||||
0.2817104114380550276949479442260611594801e129L,
|
||||
0.2422709538367273238176552320344125971528e131L,
|
||||
0.210775729837952771721360051869938959523e133L,
|
||||
0.1854826422573984391147968456455462843802e135L,
|
||||
0.1650795516090846108121691926245361930984e137L,
|
||||
0.1485715964481761497309522733620825737886e139L,
|
||||
0.1352001527678402962551665687594951421476e141L,
|
||||
0.1243841405464130725547532432587355307758e143L,
|
||||
0.1156772507081641574759205162306240436215e145L,
|
||||
0.1087366156656743080273652852567866010042e147L,
|
||||
0.103299784882390592625997020993947270954e149L,
|
||||
0.9916779348709496892095714015418938011582e150L,
|
||||
0.9619275968248211985332842594956369871234e152L,
|
||||
0.942689044888324774562618574305724247381e154L,
|
||||
0.9332621544394415268169923885626670049072e156L,
|
||||
0.9332621544394415268169923885626670049072e158L,
|
||||
0.9425947759838359420851623124482936749562e160L,
|
||||
0.9614466715035126609268655586972595484554e162L,
|
||||
0.990290071648618040754671525458177334909e164L,
|
||||
0.1029901674514562762384858386476504428305e167L,
|
||||
0.1081396758240290900504101305800329649721e169L,
|
||||
0.1146280563734708354534347384148349428704e171L,
|
||||
0.1226520203196137939351751701038733888713e173L,
|
||||
0.132464181945182897449989183712183259981e175L,
|
||||
0.1443859583202493582204882102462797533793e177L,
|
||||
0.1588245541522742940425370312709077287172e179L,
|
||||
0.1762952551090244663872161047107075788761e181L,
|
||||
0.1974506857221074023536820372759924883413e183L,
|
||||
0.2231192748659813646596607021218715118256e185L,
|
||||
0.2543559733472187557120132004189335234812e187L,
|
||||
0.2925093693493015690688151804817735520034e189L,
|
||||
0.339310868445189820119825609358857320324e191L,
|
||||
0.396993716080872089540195962949863064779e193L,
|
||||
0.4684525849754290656574312362808384164393e195L,
|
||||
0.5574585761207605881323431711741977155627e197L,
|
||||
0.6689502913449127057588118054090372586753e199L,
|
||||
0.8094298525273443739681622845449350829971e201L,
|
||||
0.9875044200833601362411579871448208012564e203L,
|
||||
0.1214630436702532967576624324188129585545e206L,
|
||||
0.1506141741511140879795014161993280686076e208L,
|
||||
0.1882677176888926099743767702491600857595e210L,
|
||||
0.237217324288004688567714730513941708057e212L,
|
||||
0.3012660018457659544809977077527059692324e214L,
|
||||
0.3856204823625804217356770659234636406175e216L,
|
||||
0.4974504222477287440390234150412680963966e218L,
|
||||
0.6466855489220473672507304395536485253155e220L,
|
||||
0.8471580690878820510984568758152795681634e222L,
|
||||
0.1118248651196004307449963076076169029976e225L,
|
||||
0.1487270706090685728908450891181304809868e227L,
|
||||
0.1992942746161518876737324194182948445223e229L,
|
||||
0.269047270731805048359538766214698040105e231L,
|
||||
0.3659042881952548657689727220519893345429e233L,
|
||||
0.5012888748274991661034926292112253883237e235L,
|
||||
0.6917786472619488492228198283114910358867e237L,
|
||||
0.9615723196941089004197195613529725398826e239L,
|
||||
0.1346201247571752460587607385894161555836e242L,
|
||||
0.1898143759076170969428526414110767793728e244L,
|
||||
0.2695364137888162776588507508037290267094e246L,
|
||||
0.3854370717180072770521565736493325081944e248L,
|
||||
0.5550293832739304789551054660550388118e250L,
|
||||
0.80479260574719919448490292577980627711e252L,
|
||||
0.1174997204390910823947958271638517164581e255L,
|
||||
0.1727245890454638911203498659308620231933e257L,
|
||||
0.2556323917872865588581178015776757943262e259L,
|
||||
0.380892263763056972698595524350736933546e261L,
|
||||
0.571338395644585459047893286526105400319e263L,
|
||||
0.8627209774233240431623188626544191544816e265L,
|
||||
0.1311335885683452545606724671234717114812e268L,
|
||||
0.2006343905095682394778288746989117185662e270L,
|
||||
0.308976961384735088795856467036324046592e272L,
|
||||
0.4789142901463393876335775239063022722176e274L,
|
||||
0.7471062926282894447083809372938315446595e276L,
|
||||
0.1172956879426414428192158071551315525115e279L,
|
||||
0.1853271869493734796543609753051078529682e281L,
|
||||
0.2946702272495038326504339507351214862195e283L,
|
||||
0.4714723635992061322406943211761943779512e285L,
|
||||
0.7590705053947218729075178570936729485014e287L,
|
||||
0.1229694218739449434110178928491750176572e290L,
|
||||
0.2004401576545302577599591653441552787813e292L,
|
||||
0.3287218585534296227263330311644146572013e294L,
|
||||
0.5423910666131588774984495014212841843822e296L,
|
||||
0.9003691705778437366474261723593317460744e298L,
|
||||
0.1503616514864999040201201707840084015944e301L,
|
||||
0.2526075744973198387538018869171341146786e303L,
|
||||
0.4269068009004705274939251888899566538069e305L,
|
||||
0.7257415615307998967396728211129263114717e307L,
|
||||
}};
|
||||
|
||||
return factorials[i];
|
||||
}
|
||||
|
||||
template <>
|
||||
struct max_factorial<long double>
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(unsigned, value = 170);
|
||||
};
|
||||
|
||||
#ifdef BOOST_MATH_USE_FLOAT128
|
||||
|
||||
template <>
|
||||
inline BOOST_MATH_CONSTEXPR_TABLE_FUNCTION BOOST_MATH_FLOAT128_TYPE unchecked_factorial<BOOST_MATH_FLOAT128_TYPE>(unsigned i)
|
||||
{
|
||||
#ifdef BOOST_MATH_HAVE_CONSTEXPR_TABLES
|
||||
constexpr std::array<BOOST_MATH_FLOAT128_TYPE, 171> factorials = { {
|
||||
#else
|
||||
static const boost::array<BOOST_MATH_FLOAT128_TYPE, 171> factorials = { {
|
||||
#endif
|
||||
1,
|
||||
1,
|
||||
2,
|
||||
6,
|
||||
24,
|
||||
120,
|
||||
720,
|
||||
5040,
|
||||
40320,
|
||||
362880.0Q,
|
||||
3628800.0Q,
|
||||
39916800.0Q,
|
||||
479001600.0Q,
|
||||
6227020800.0Q,
|
||||
87178291200.0Q,
|
||||
1307674368000.0Q,
|
||||
20922789888000.0Q,
|
||||
355687428096000.0Q,
|
||||
6402373705728000.0Q,
|
||||
121645100408832000.0Q,
|
||||
0.243290200817664e19Q,
|
||||
0.5109094217170944e20Q,
|
||||
0.112400072777760768e22Q,
|
||||
0.2585201673888497664e23Q,
|
||||
0.62044840173323943936e24Q,
|
||||
0.15511210043330985984e26Q,
|
||||
0.403291461126605635584e27Q,
|
||||
0.10888869450418352160768e29Q,
|
||||
0.304888344611713860501504e30Q,
|
||||
0.8841761993739701954543616e31Q,
|
||||
0.26525285981219105863630848e33Q,
|
||||
0.822283865417792281772556288e34Q,
|
||||
0.26313083693369353016721801216e36Q,
|
||||
0.868331761881188649551819440128e37Q,
|
||||
0.29523279903960414084761860964352e39Q,
|
||||
0.103331479663861449296666513375232e41Q,
|
||||
0.3719933267899012174679994481508352e42Q,
|
||||
0.137637530912263450463159795815809024e44Q,
|
||||
0.5230226174666011117600072241000742912e45Q,
|
||||
0.203978820811974433586402817399028973568e47Q,
|
||||
0.815915283247897734345611269596115894272e48Q,
|
||||
0.3345252661316380710817006205344075166515e50Q,
|
||||
0.1405006117752879898543142606244511569936e52Q,
|
||||
0.6041526306337383563735513206851399750726e53Q,
|
||||
0.265827157478844876804362581101461589032e55Q,
|
||||
0.1196222208654801945619631614956577150644e57Q,
|
||||
0.5502622159812088949850305428800254892962e58Q,
|
||||
0.2586232415111681806429643551536119799692e60Q,
|
||||
0.1241391559253607267086228904737337503852e62Q,
|
||||
0.6082818640342675608722521633212953768876e63Q,
|
||||
0.3041409320171337804361260816606476884438e65Q,
|
||||
0.1551118753287382280224243016469303211063e67Q,
|
||||
0.8065817517094387857166063685640376697529e68Q,
|
||||
0.427488328406002556429801375338939964969e70Q,
|
||||
0.2308436973392413804720927426830275810833e72Q,
|
||||
0.1269640335365827592596510084756651695958e74Q,
|
||||
0.7109985878048634518540456474637249497365e75Q,
|
||||
0.4052691950487721675568060190543232213498e77Q,
|
||||
0.2350561331282878571829474910515074683829e79Q,
|
||||
0.1386831185456898357379390197203894063459e81Q,
|
||||
0.8320987112741390144276341183223364380754e82Q,
|
||||
0.507580213877224798800856812176625227226e84Q,
|
||||
0.3146997326038793752565312235495076408801e86Q,
|
||||
0.1982608315404440064116146708361898137545e88Q,
|
||||
0.1268869321858841641034333893351614808029e90Q,
|
||||
0.8247650592082470666723170306785496252186e91Q,
|
||||
0.5443449390774430640037292402478427526443e93Q,
|
||||
0.3647111091818868528824985909660546442717e95Q,
|
||||
0.2480035542436830599600990418569171581047e97Q,
|
||||
0.1711224524281413113724683388812728390923e99Q,
|
||||
0.1197857166996989179607278372168909873646e101Q,
|
||||
0.8504785885678623175211676442399260102886e102Q,
|
||||
0.6123445837688608686152407038527467274078e104Q,
|
||||
0.4470115461512684340891257138125051110077e106Q,
|
||||
0.3307885441519386412259530282212537821457e108Q,
|
||||
0.2480914081139539809194647711659403366093e110Q,
|
||||
0.188549470166605025498793226086114655823e112Q,
|
||||
0.1451830920282858696340707840863082849837e114Q,
|
||||
0.1132428117820629783145752115873204622873e116Q,
|
||||
0.8946182130782975286851441715398316520698e117Q,
|
||||
0.7156945704626380229481153372318653216558e119Q,
|
||||
0.5797126020747367985879734231578109105412e121Q,
|
||||
0.4753643337012841748421382069894049466438e123Q,
|
||||
0.3945523969720658651189747118012061057144e125Q,
|
||||
0.3314240134565353266999387579130131288001e127Q,
|
||||
0.2817104114380550276949479442260611594801e129Q,
|
||||
0.2422709538367273238176552320344125971528e131Q,
|
||||
0.210775729837952771721360051869938959523e133Q,
|
||||
0.1854826422573984391147968456455462843802e135Q,
|
||||
0.1650795516090846108121691926245361930984e137Q,
|
||||
0.1485715964481761497309522733620825737886e139Q,
|
||||
0.1352001527678402962551665687594951421476e141Q,
|
||||
0.1243841405464130725547532432587355307758e143Q,
|
||||
0.1156772507081641574759205162306240436215e145Q,
|
||||
0.1087366156656743080273652852567866010042e147Q,
|
||||
0.103299784882390592625997020993947270954e149Q,
|
||||
0.9916779348709496892095714015418938011582e150Q,
|
||||
0.9619275968248211985332842594956369871234e152Q,
|
||||
0.942689044888324774562618574305724247381e154Q,
|
||||
0.9332621544394415268169923885626670049072e156Q,
|
||||
0.9332621544394415268169923885626670049072e158Q,
|
||||
0.9425947759838359420851623124482936749562e160Q,
|
||||
0.9614466715035126609268655586972595484554e162Q,
|
||||
0.990290071648618040754671525458177334909e164Q,
|
||||
0.1029901674514562762384858386476504428305e167Q,
|
||||
0.1081396758240290900504101305800329649721e169Q,
|
||||
0.1146280563734708354534347384148349428704e171Q,
|
||||
0.1226520203196137939351751701038733888713e173Q,
|
||||
0.132464181945182897449989183712183259981e175Q,
|
||||
0.1443859583202493582204882102462797533793e177Q,
|
||||
0.1588245541522742940425370312709077287172e179Q,
|
||||
0.1762952551090244663872161047107075788761e181Q,
|
||||
0.1974506857221074023536820372759924883413e183Q,
|
||||
0.2231192748659813646596607021218715118256e185Q,
|
||||
0.2543559733472187557120132004189335234812e187Q,
|
||||
0.2925093693493015690688151804817735520034e189Q,
|
||||
0.339310868445189820119825609358857320324e191Q,
|
||||
0.396993716080872089540195962949863064779e193Q,
|
||||
0.4684525849754290656574312362808384164393e195Q,
|
||||
0.5574585761207605881323431711741977155627e197Q,
|
||||
0.6689502913449127057588118054090372586753e199Q,
|
||||
0.8094298525273443739681622845449350829971e201Q,
|
||||
0.9875044200833601362411579871448208012564e203Q,
|
||||
0.1214630436702532967576624324188129585545e206Q,
|
||||
0.1506141741511140879795014161993280686076e208Q,
|
||||
0.1882677176888926099743767702491600857595e210Q,
|
||||
0.237217324288004688567714730513941708057e212Q,
|
||||
0.3012660018457659544809977077527059692324e214Q,
|
||||
0.3856204823625804217356770659234636406175e216Q,
|
||||
0.4974504222477287440390234150412680963966e218Q,
|
||||
0.6466855489220473672507304395536485253155e220Q,
|
||||
0.8471580690878820510984568758152795681634e222Q,
|
||||
0.1118248651196004307449963076076169029976e225Q,
|
||||
0.1487270706090685728908450891181304809868e227Q,
|
||||
0.1992942746161518876737324194182948445223e229Q,
|
||||
0.269047270731805048359538766214698040105e231Q,
|
||||
0.3659042881952548657689727220519893345429e233Q,
|
||||
0.5012888748274991661034926292112253883237e235Q,
|
||||
0.6917786472619488492228198283114910358867e237Q,
|
||||
0.9615723196941089004197195613529725398826e239Q,
|
||||
0.1346201247571752460587607385894161555836e242Q,
|
||||
0.1898143759076170969428526414110767793728e244Q,
|
||||
0.2695364137888162776588507508037290267094e246Q,
|
||||
0.3854370717180072770521565736493325081944e248Q,
|
||||
0.5550293832739304789551054660550388118e250Q,
|
||||
0.80479260574719919448490292577980627711e252Q,
|
||||
0.1174997204390910823947958271638517164581e255Q,
|
||||
0.1727245890454638911203498659308620231933e257Q,
|
||||
0.2556323917872865588581178015776757943262e259Q,
|
||||
0.380892263763056972698595524350736933546e261Q,
|
||||
0.571338395644585459047893286526105400319e263Q,
|
||||
0.8627209774233240431623188626544191544816e265Q,
|
||||
0.1311335885683452545606724671234717114812e268Q,
|
||||
0.2006343905095682394778288746989117185662e270Q,
|
||||
0.308976961384735088795856467036324046592e272Q,
|
||||
0.4789142901463393876335775239063022722176e274Q,
|
||||
0.7471062926282894447083809372938315446595e276Q,
|
||||
0.1172956879426414428192158071551315525115e279Q,
|
||||
0.1853271869493734796543609753051078529682e281Q,
|
||||
0.2946702272495038326504339507351214862195e283Q,
|
||||
0.4714723635992061322406943211761943779512e285Q,
|
||||
0.7590705053947218729075178570936729485014e287Q,
|
||||
0.1229694218739449434110178928491750176572e290Q,
|
||||
0.2004401576545302577599591653441552787813e292Q,
|
||||
0.3287218585534296227263330311644146572013e294Q,
|
||||
0.5423910666131588774984495014212841843822e296Q,
|
||||
0.9003691705778437366474261723593317460744e298Q,
|
||||
0.1503616514864999040201201707840084015944e301Q,
|
||||
0.2526075744973198387538018869171341146786e303Q,
|
||||
0.4269068009004705274939251888899566538069e305Q,
|
||||
0.7257415615307998967396728211129263114717e307Q,
|
||||
} };
|
||||
|
||||
return factorials[i];
|
||||
}
|
||||
|
||||
template <>
|
||||
struct max_factorial<BOOST_MATH_FLOAT128_TYPE>
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(unsigned, value = 170);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
template <>
|
||||
inline BOOST_MATH_CONSTEXPR_TABLE_FUNCTION double unchecked_factorial<double>(unsigned i BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(double))
|
||||
{
|
||||
return static_cast<double>(boost::math::unchecked_factorial<long double>(i));
|
||||
}
|
||||
|
||||
template <>
|
||||
struct max_factorial<double>
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(unsigned,
|
||||
value = ::boost::math::max_factorial<long double>::value);
|
||||
};
|
||||
|
||||
#ifndef BOOST_MATH_NO_LEXICAL_CAST
|
||||
|
||||
template <class T>
|
||||
struct unchecked_factorial_initializer
|
||||
{
|
||||
struct init
|
||||
{
|
||||
init()
|
||||
{
|
||||
boost::math::unchecked_factorial<T>(3);
|
||||
}
|
||||
void force_instantiate()const {}
|
||||
};
|
||||
static const init initializer;
|
||||
static void force_instantiate()
|
||||
{
|
||||
initializer.force_instantiate();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
const typename unchecked_factorial_initializer<T>::init unchecked_factorial_initializer<T>::initializer;
|
||||
|
||||
|
||||
template <class T, int N>
|
||||
inline T unchecked_factorial_imp(unsigned i, const mpl::int_<N>&)
|
||||
{
|
||||
BOOST_STATIC_ASSERT(!boost::is_integral<T>::value);
|
||||
// factorial<unsigned int>(n) is not implemented
|
||||
// because it would overflow integral type T for too small n
|
||||
// to be useful. Use instead a floating-point type,
|
||||
// and convert to an unsigned type if essential, for example:
|
||||
// unsigned int nfac = static_cast<unsigned int>(factorial<double>(n));
|
||||
// See factorial documentation for more detail.
|
||||
|
||||
unchecked_factorial_initializer<T>::force_instantiate();
|
||||
|
||||
static const boost::array<T, 101> factorials = {{
|
||||
T(boost::math::tools::convert_from_string<T>("1")),
|
||||
T(boost::math::tools::convert_from_string<T>("1")),
|
||||
T(boost::math::tools::convert_from_string<T>("2")),
|
||||
T(boost::math::tools::convert_from_string<T>("6")),
|
||||
T(boost::math::tools::convert_from_string<T>("24")),
|
||||
T(boost::math::tools::convert_from_string<T>("120")),
|
||||
T(boost::math::tools::convert_from_string<T>("720")),
|
||||
T(boost::math::tools::convert_from_string<T>("5040")),
|
||||
T(boost::math::tools::convert_from_string<T>("40320")),
|
||||
T(boost::math::tools::convert_from_string<T>("362880")),
|
||||
T(boost::math::tools::convert_from_string<T>("3628800")),
|
||||
T(boost::math::tools::convert_from_string<T>("39916800")),
|
||||
T(boost::math::tools::convert_from_string<T>("479001600")),
|
||||
T(boost::math::tools::convert_from_string<T>("6227020800")),
|
||||
T(boost::math::tools::convert_from_string<T>("87178291200")),
|
||||
T(boost::math::tools::convert_from_string<T>("1307674368000")),
|
||||
T(boost::math::tools::convert_from_string<T>("20922789888000")),
|
||||
T(boost::math::tools::convert_from_string<T>("355687428096000")),
|
||||
T(boost::math::tools::convert_from_string<T>("6402373705728000")),
|
||||
T(boost::math::tools::convert_from_string<T>("121645100408832000")),
|
||||
T(boost::math::tools::convert_from_string<T>("2432902008176640000")),
|
||||
T(boost::math::tools::convert_from_string<T>("51090942171709440000")),
|
||||
T(boost::math::tools::convert_from_string<T>("1124000727777607680000")),
|
||||
T(boost::math::tools::convert_from_string<T>("25852016738884976640000")),
|
||||
T(boost::math::tools::convert_from_string<T>("620448401733239439360000")),
|
||||
T(boost::math::tools::convert_from_string<T>("15511210043330985984000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("403291461126605635584000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("10888869450418352160768000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("304888344611713860501504000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("8841761993739701954543616000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("265252859812191058636308480000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("8222838654177922817725562880000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("263130836933693530167218012160000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("8683317618811886495518194401280000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("295232799039604140847618609643520000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("10333147966386144929666651337523200000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("371993326789901217467999448150835200000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("13763753091226345046315979581580902400000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("523022617466601111760007224100074291200000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("20397882081197443358640281739902897356800000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("815915283247897734345611269596115894272000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("33452526613163807108170062053440751665152000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("1405006117752879898543142606244511569936384000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("60415263063373835637355132068513997507264512000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("2658271574788448768043625811014615890319638528000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("119622220865480194561963161495657715064383733760000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("5502622159812088949850305428800254892961651752960000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("258623241511168180642964355153611979969197632389120000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("12413915592536072670862289047373375038521486354677760000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("608281864034267560872252163321295376887552831379210240000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("30414093201713378043612608166064768844377641568960512000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("1551118753287382280224243016469303211063259720016986112000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("80658175170943878571660636856403766975289505440883277824000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("4274883284060025564298013753389399649690343788366813724672000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("230843697339241380472092742683027581083278564571807941132288000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("12696403353658275925965100847566516959580321051449436762275840000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("710998587804863451854045647463724949736497978881168458687447040000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("40526919504877216755680601905432322134980384796226602145184481280000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("2350561331282878571829474910515074683828862318181142924420699914240000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("138683118545689835737939019720389406345902876772687432540821294940160000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("8320987112741390144276341183223364380754172606361245952449277696409600000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("507580213877224798800856812176625227226004528988036003099405939480985600000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("31469973260387937525653122354950764088012280797258232192163168247821107200000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("1982608315404440064116146708361898137544773690227268628106279599612729753600000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("126886932185884164103433389335161480802865516174545192198801894375214704230400000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("8247650592082470666723170306785496252186258551345437492922123134388955774976000000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("544344939077443064003729240247842752644293064388798874532860126869671081148416000000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("36471110918188685288249859096605464427167635314049524593701628500267962436943872000000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("2480035542436830599600990418569171581047399201355367672371710738018221445712183296000000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("171122452428141311372468338881272839092270544893520369393648040923257279754140647424000000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("11978571669969891796072783721689098736458938142546425857555362864628009582789845319680000000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("850478588567862317521167644239926010288584608120796235886430763388588680378079017697280000000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("61234458376886086861524070385274672740778091784697328983823014963978384987221689274204160000000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("4470115461512684340891257138125051110076800700282905015819080092370422104067183317016903680000000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("330788544151938641225953028221253782145683251820934971170611926835411235700971565459250872320000000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("24809140811395398091946477116594033660926243886570122837795894512655842677572867409443815424000000000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("1885494701666050254987932260861146558230394535379329335672487982961844043495537923117729972224000000000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("145183092028285869634070784086308284983740379224208358846781574688061991349156420080065207861248000000000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("11324281178206297831457521158732046228731749579488251990048962825668835325234200766245086213177344000000000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("894618213078297528685144171539831652069808216779571907213868063227837990693501860533361810841010176000000000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("71569457046263802294811533723186532165584657342365752577109445058227039255480148842668944867280814080000000000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("5797126020747367985879734231578109105412357244731625958745865049716390179693892056256184534249745940480000000000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("475364333701284174842138206989404946643813294067993328617160934076743994734899148613007131808479167119360000000000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("39455239697206586511897471180120610571436503407643446275224357528369751562996629334879591940103770870906880000000000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("3314240134565353266999387579130131288000666286242049487118846032383059131291716864129885722968716753156177920000000000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("281710411438055027694947944226061159480056634330574206405101912752560026159795933451040286452340924018275123200000000000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("24227095383672732381765523203441259715284870552429381750838764496720162249742450276789464634901319465571660595200000000000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("2107757298379527717213600518699389595229783738061356212322972511214654115727593174080683423236414793504734471782400000000000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("185482642257398439114796845645546284380220968949399346684421580986889562184028199319100141244804501828416633516851200000000000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("16507955160908461081216919262453619309839666236496541854913520707833171034378509739399912570787600662729080382999756800000000000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("1485715964481761497309522733620825737885569961284688766942216863704985393094065876545992131370884059645617234469978112000000000000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("135200152767840296255166568759495142147586866476906677791741734597153670771559994765685283954750449427751168336768008192000000000000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("12438414054641307255475324325873553077577991715875414356840239582938137710983519518443046123837041347353107486982656753664000000000000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("1156772507081641574759205162306240436214753229576413535186142281213246807121467315215203289516844845303838996289387078090752000000000000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("108736615665674308027365285256786601004186803580182872307497374434045199869417927630229109214583415458560865651202385340530688000000000000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("10329978488239059262599702099394727095397746340117372869212250571234293987594703124871765375385424468563282236864226607350415360000000000000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("991677934870949689209571401541893801158183648651267795444376054838492222809091499987689476037000748982075094738965754305639874560000000000000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("96192759682482119853328425949563698712343813919172976158104477319333745612481875498805879175589072651261284189679678167647067832320000000000000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("9426890448883247745626185743057242473809693764078951663494238777294707070023223798882976159207729119823605850588608460429412647567360000000000000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("933262154439441526816992388562667004907159682643816214685929638952175999932299156089414639761565182862536979208272237582511852109168640000000000000000000000")),
|
||||
T(boost::math::tools::convert_from_string<T>("93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000")),
|
||||
}};
|
||||
|
||||
return factorials[i];
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T unchecked_factorial_imp(unsigned i, const mpl::int_<0>&)
|
||||
{
|
||||
BOOST_STATIC_ASSERT(!boost::is_integral<T>::value);
|
||||
// factorial<unsigned int>(n) is not implemented
|
||||
// because it would overflow integral type T for too small n
|
||||
// to be useful. Use instead a floating-point type,
|
||||
// and convert to an unsigned type if essential, for example:
|
||||
// unsigned int nfac = static_cast<unsigned int>(factorial<double>(n));
|
||||
// See factorial documentation for more detail.
|
||||
#ifdef BOOST_NO_CXX11_THREAD_LOCAL
|
||||
unchecked_factorial_initializer<T>::force_instantiate();
|
||||
#endif
|
||||
static const char* const factorial_strings[] = {
|
||||
"1",
|
||||
"1",
|
||||
"2",
|
||||
"6",
|
||||
"24",
|
||||
"120",
|
||||
"720",
|
||||
"5040",
|
||||
"40320",
|
||||
"362880",
|
||||
"3628800",
|
||||
"39916800",
|
||||
"479001600",
|
||||
"6227020800",
|
||||
"87178291200",
|
||||
"1307674368000",
|
||||
"20922789888000",
|
||||
"355687428096000",
|
||||
"6402373705728000",
|
||||
"121645100408832000",
|
||||
"2432902008176640000",
|
||||
"51090942171709440000",
|
||||
"1124000727777607680000",
|
||||
"25852016738884976640000",
|
||||
"620448401733239439360000",
|
||||
"15511210043330985984000000",
|
||||
"403291461126605635584000000",
|
||||
"10888869450418352160768000000",
|
||||
"304888344611713860501504000000",
|
||||
"8841761993739701954543616000000",
|
||||
"265252859812191058636308480000000",
|
||||
"8222838654177922817725562880000000",
|
||||
"263130836933693530167218012160000000",
|
||||
"8683317618811886495518194401280000000",
|
||||
"295232799039604140847618609643520000000",
|
||||
"10333147966386144929666651337523200000000",
|
||||
"371993326789901217467999448150835200000000",
|
||||
"13763753091226345046315979581580902400000000",
|
||||
"523022617466601111760007224100074291200000000",
|
||||
"20397882081197443358640281739902897356800000000",
|
||||
"815915283247897734345611269596115894272000000000",
|
||||
"33452526613163807108170062053440751665152000000000",
|
||||
"1405006117752879898543142606244511569936384000000000",
|
||||
"60415263063373835637355132068513997507264512000000000",
|
||||
"2658271574788448768043625811014615890319638528000000000",
|
||||
"119622220865480194561963161495657715064383733760000000000",
|
||||
"5502622159812088949850305428800254892961651752960000000000",
|
||||
"258623241511168180642964355153611979969197632389120000000000",
|
||||
"12413915592536072670862289047373375038521486354677760000000000",
|
||||
"608281864034267560872252163321295376887552831379210240000000000",
|
||||
"30414093201713378043612608166064768844377641568960512000000000000",
|
||||
"1551118753287382280224243016469303211063259720016986112000000000000",
|
||||
"80658175170943878571660636856403766975289505440883277824000000000000",
|
||||
"4274883284060025564298013753389399649690343788366813724672000000000000",
|
||||
"230843697339241380472092742683027581083278564571807941132288000000000000",
|
||||
"12696403353658275925965100847566516959580321051449436762275840000000000000",
|
||||
"710998587804863451854045647463724949736497978881168458687447040000000000000",
|
||||
"40526919504877216755680601905432322134980384796226602145184481280000000000000",
|
||||
"2350561331282878571829474910515074683828862318181142924420699914240000000000000",
|
||||
"138683118545689835737939019720389406345902876772687432540821294940160000000000000",
|
||||
"8320987112741390144276341183223364380754172606361245952449277696409600000000000000",
|
||||
"507580213877224798800856812176625227226004528988036003099405939480985600000000000000",
|
||||
"31469973260387937525653122354950764088012280797258232192163168247821107200000000000000",
|
||||
"1982608315404440064116146708361898137544773690227268628106279599612729753600000000000000",
|
||||
"126886932185884164103433389335161480802865516174545192198801894375214704230400000000000000",
|
||||
"8247650592082470666723170306785496252186258551345437492922123134388955774976000000000000000",
|
||||
"544344939077443064003729240247842752644293064388798874532860126869671081148416000000000000000",
|
||||
"36471110918188685288249859096605464427167635314049524593701628500267962436943872000000000000000",
|
||||
"2480035542436830599600990418569171581047399201355367672371710738018221445712183296000000000000000",
|
||||
"171122452428141311372468338881272839092270544893520369393648040923257279754140647424000000000000000",
|
||||
"11978571669969891796072783721689098736458938142546425857555362864628009582789845319680000000000000000",
|
||||
"850478588567862317521167644239926010288584608120796235886430763388588680378079017697280000000000000000",
|
||||
"61234458376886086861524070385274672740778091784697328983823014963978384987221689274204160000000000000000",
|
||||
"4470115461512684340891257138125051110076800700282905015819080092370422104067183317016903680000000000000000",
|
||||
"330788544151938641225953028221253782145683251820934971170611926835411235700971565459250872320000000000000000",
|
||||
"24809140811395398091946477116594033660926243886570122837795894512655842677572867409443815424000000000000000000",
|
||||
"1885494701666050254987932260861146558230394535379329335672487982961844043495537923117729972224000000000000000000",
|
||||
"145183092028285869634070784086308284983740379224208358846781574688061991349156420080065207861248000000000000000000",
|
||||
"11324281178206297831457521158732046228731749579488251990048962825668835325234200766245086213177344000000000000000000",
|
||||
"894618213078297528685144171539831652069808216779571907213868063227837990693501860533361810841010176000000000000000000",
|
||||
"71569457046263802294811533723186532165584657342365752577109445058227039255480148842668944867280814080000000000000000000",
|
||||
"5797126020747367985879734231578109105412357244731625958745865049716390179693892056256184534249745940480000000000000000000",
|
||||
"475364333701284174842138206989404946643813294067993328617160934076743994734899148613007131808479167119360000000000000000000",
|
||||
"39455239697206586511897471180120610571436503407643446275224357528369751562996629334879591940103770870906880000000000000000000",
|
||||
"3314240134565353266999387579130131288000666286242049487118846032383059131291716864129885722968716753156177920000000000000000000",
|
||||
"281710411438055027694947944226061159480056634330574206405101912752560026159795933451040286452340924018275123200000000000000000000",
|
||||
"24227095383672732381765523203441259715284870552429381750838764496720162249742450276789464634901319465571660595200000000000000000000",
|
||||
"2107757298379527717213600518699389595229783738061356212322972511214654115727593174080683423236414793504734471782400000000000000000000",
|
||||
"185482642257398439114796845645546284380220968949399346684421580986889562184028199319100141244804501828416633516851200000000000000000000",
|
||||
"16507955160908461081216919262453619309839666236496541854913520707833171034378509739399912570787600662729080382999756800000000000000000000",
|
||||
"1485715964481761497309522733620825737885569961284688766942216863704985393094065876545992131370884059645617234469978112000000000000000000000",
|
||||
"135200152767840296255166568759495142147586866476906677791741734597153670771559994765685283954750449427751168336768008192000000000000000000000",
|
||||
"12438414054641307255475324325873553077577991715875414356840239582938137710983519518443046123837041347353107486982656753664000000000000000000000",
|
||||
"1156772507081641574759205162306240436214753229576413535186142281213246807121467315215203289516844845303838996289387078090752000000000000000000000",
|
||||
"108736615665674308027365285256786601004186803580182872307497374434045199869417927630229109214583415458560865651202385340530688000000000000000000000",
|
||||
"10329978488239059262599702099394727095397746340117372869212250571234293987594703124871765375385424468563282236864226607350415360000000000000000000000",
|
||||
"991677934870949689209571401541893801158183648651267795444376054838492222809091499987689476037000748982075094738965754305639874560000000000000000000000",
|
||||
"96192759682482119853328425949563698712343813919172976158104477319333745612481875498805879175589072651261284189679678167647067832320000000000000000000000",
|
||||
"9426890448883247745626185743057242473809693764078951663494238777294707070023223798882976159207729119823605850588608460429412647567360000000000000000000000",
|
||||
"933262154439441526816992388562667004907159682643816214685929638952175999932299156089414639761565182862536979208272237582511852109168640000000000000000000000",
|
||||
"93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000",
|
||||
};
|
||||
|
||||
static BOOST_MATH_THREAD_LOCAL T factorials[sizeof(factorial_strings) / sizeof(factorial_strings[0])];
|
||||
static BOOST_MATH_THREAD_LOCAL int digits = 0;
|
||||
|
||||
int current_digits = boost::math::tools::digits<T>();
|
||||
|
||||
if(digits != current_digits)
|
||||
{
|
||||
digits = current_digits;
|
||||
for(unsigned k = 0; k < sizeof(factorials) / sizeof(factorials[0]); ++k)
|
||||
factorials[k] = static_cast<T>(boost::math::tools::convert_from_string<T>(factorial_strings[k]));
|
||||
}
|
||||
|
||||
return factorials[i];
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T unchecked_factorial(unsigned i)
|
||||
{
|
||||
typedef typename boost::math::policies::precision<T, boost::math::policies::policy<> >::type tag_type;
|
||||
return unchecked_factorial_imp<T>(i, tag_type());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
struct max_factorial
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(unsigned, value = 100);
|
||||
};
|
||||
|
||||
#else // BOOST_MATH_NO_LEXICAL_CAST
|
||||
|
||||
template <class T>
|
||||
inline T unchecked_factorial(unsigned i BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(T))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
struct max_factorial
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(unsigned, value = 0);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
|
||||
template <class T>
|
||||
const unsigned max_factorial<T>::value;
|
||||
#endif
|
||||
|
||||
} // namespace math
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_MATH_SP_UC_FACTORIALS_HPP
|
||||
|
||||
635
code_isotrope/boost/math/special_functions/digamma.hpp
Executable file
635
code_isotrope/boost/math/special_functions/digamma.hpp
Executable file
@@ -0,0 +1,635 @@
|
||||
// (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_DIGAMMA_HPP
|
||||
#define BOOST_MATH_SF_DIGAMMA_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4702) // Unreachable code (release mode only warning)
|
||||
#endif
|
||||
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/math/tools/rational.hpp>
|
||||
#include <boost/math/tools/series.hpp>
|
||||
#include <boost/math/tools/promotion.hpp>
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
#include <boost/math/constants/constants.hpp>
|
||||
#include <boost/mpl/comparison.hpp>
|
||||
#include <boost/math/tools/big_constant.hpp>
|
||||
|
||||
namespace boost{
|
||||
namespace math{
|
||||
namespace detail{
|
||||
//
|
||||
// Begin by defining the smallest value for which it is safe to
|
||||
// use the asymptotic expansion for digamma:
|
||||
//
|
||||
inline unsigned digamma_large_lim(const mpl::int_<0>*)
|
||||
{ return 20; }
|
||||
inline unsigned digamma_large_lim(const mpl::int_<113>*)
|
||||
{ return 20; }
|
||||
inline unsigned digamma_large_lim(const void*)
|
||||
{ return 10; }
|
||||
//
|
||||
// Implementations of the asymptotic expansion come next,
|
||||
// the coefficients of the series have been evaluated
|
||||
// in advance at high precision, and the series truncated
|
||||
// at the first term that's too small to effect the result.
|
||||
// Note that the series becomes divergent after a while
|
||||
// so truncation is very important.
|
||||
//
|
||||
// This first one gives 34-digit precision for x >= 20:
|
||||
//
|
||||
template <class T>
|
||||
inline T digamma_imp_large(T x, const mpl::int_<113>*)
|
||||
{
|
||||
BOOST_MATH_STD_USING // ADL of std functions.
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.083333333333333333333333333333333333333333333333333),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.0083333333333333333333333333333333333333333333333333),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.003968253968253968253968253968253968253968253968254),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.0041666666666666666666666666666666666666666666666667),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.0075757575757575757575757575757575757575757575757576),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.021092796092796092796092796092796092796092796092796),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.083333333333333333333333333333333333333333333333333),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.44325980392156862745098039215686274509803921568627),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.0539543302701197438039543302701197438039543302701),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -26.456212121212121212121212121212121212121212121212),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 281.4601449275362318840579710144927536231884057971),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -3607.510546398046398046398046398046398046398046398),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 54827.583333333333333333333333333333333333333333333),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -974936.82385057471264367816091954022988505747126437),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 20052695.796688078946143462272494530559046688078946),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -472384867.72162990196078431372549019607843137254902),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 12635724795.916666666666666666666666666666666666667)
|
||||
};
|
||||
x -= 1;
|
||||
T result = log(x);
|
||||
result += 1 / (2 * x);
|
||||
T z = 1 / (x*x);
|
||||
result -= z * tools::evaluate_polynomial(P, z);
|
||||
return result;
|
||||
}
|
||||
//
|
||||
// 19-digit precision for x >= 10:
|
||||
//
|
||||
template <class T>
|
||||
inline T digamma_imp_large(T x, const mpl::int_<64>*)
|
||||
{
|
||||
BOOST_MATH_STD_USING // ADL of std functions.
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.083333333333333333333333333333333333333333333333333),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.0083333333333333333333333333333333333333333333333333),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.003968253968253968253968253968253968253968253968254),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.0041666666666666666666666666666666666666666666666667),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.0075757575757575757575757575757575757575757575757576),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.021092796092796092796092796092796092796092796092796),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.083333333333333333333333333333333333333333333333333),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.44325980392156862745098039215686274509803921568627),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 3.0539543302701197438039543302701197438039543302701),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -26.456212121212121212121212121212121212121212121212),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 281.4601449275362318840579710144927536231884057971),
|
||||
};
|
||||
x -= 1;
|
||||
T result = log(x);
|
||||
result += 1 / (2 * x);
|
||||
T z = 1 / (x*x);
|
||||
result -= z * tools::evaluate_polynomial(P, z);
|
||||
return result;
|
||||
}
|
||||
//
|
||||
// 17-digit precision for x >= 10:
|
||||
//
|
||||
template <class T>
|
||||
inline T digamma_imp_large(T x, const mpl::int_<53>*)
|
||||
{
|
||||
BOOST_MATH_STD_USING // ADL of std functions.
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 0.083333333333333333333333333333333333333333333333333),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, -0.0083333333333333333333333333333333333333333333333333),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 0.003968253968253968253968253968253968253968253968254),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, -0.0041666666666666666666666666666666666666666666666667),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 0.0075757575757575757575757575757575757575757575757576),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, -0.021092796092796092796092796092796092796092796092796),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 0.083333333333333333333333333333333333333333333333333),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, -0.44325980392156862745098039215686274509803921568627)
|
||||
};
|
||||
x -= 1;
|
||||
T result = log(x);
|
||||
result += 1 / (2 * x);
|
||||
T z = 1 / (x*x);
|
||||
result -= z * tools::evaluate_polynomial(P, z);
|
||||
return result;
|
||||
}
|
||||
//
|
||||
// 9-digit precision for x >= 10:
|
||||
//
|
||||
template <class T>
|
||||
inline T digamma_imp_large(T x, const mpl::int_<24>*)
|
||||
{
|
||||
BOOST_MATH_STD_USING // ADL of std functions.
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 24, 0.083333333333333333333333333333333333333333333333333),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 24, -0.0083333333333333333333333333333333333333333333333333),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 24, 0.003968253968253968253968253968253968253968253968254)
|
||||
};
|
||||
x -= 1;
|
||||
T result = log(x);
|
||||
result += 1 / (2 * x);
|
||||
T z = 1 / (x*x);
|
||||
result -= z * tools::evaluate_polynomial(P, z);
|
||||
return result;
|
||||
}
|
||||
//
|
||||
// Fully generic asymptotic expansion in terms of Bernoulli numbers, see:
|
||||
// http://functions.wolfram.com/06.14.06.0012.01
|
||||
//
|
||||
template <class T>
|
||||
struct digamma_series_func
|
||||
{
|
||||
private:
|
||||
int k;
|
||||
T xx;
|
||||
T term;
|
||||
public:
|
||||
digamma_series_func(T x) : k(1), xx(x * x), term(1 / (x * x)) {}
|
||||
T operator()()
|
||||
{
|
||||
T result = term * boost::math::bernoulli_b2n<T>(k) / (2 * k);
|
||||
term /= xx;
|
||||
++k;
|
||||
return result;
|
||||
}
|
||||
typedef T result_type;
|
||||
};
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T digamma_imp_large(T x, const Policy& pol, const mpl::int_<0>*)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
digamma_series_func<T> s(x);
|
||||
T result = log(x) - 1 / (2 * x);
|
||||
boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
|
||||
result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon<T, Policy>(), max_iter, -result);
|
||||
result = -result;
|
||||
policies::check_series_iterations<T>("boost::math::digamma<%1%>(%1%)", max_iter, pol);
|
||||
return result;
|
||||
}
|
||||
//
|
||||
// Now follow rational approximations over the range [1,2].
|
||||
//
|
||||
// 35-digit precision:
|
||||
//
|
||||
template <class T>
|
||||
T digamma_imp_1_2(T x, const mpl::int_<113>*)
|
||||
{
|
||||
//
|
||||
// Now the approximation, we use the form:
|
||||
//
|
||||
// digamma(x) = (x - root) * (Y + R(x-1))
|
||||
//
|
||||
// Where root is the location of the positive root of digamma,
|
||||
// Y is a constant, and R is optimised for low absolute error
|
||||
// compared to Y.
|
||||
//
|
||||
// Max error found at 128-bit long double precision: 5.541e-35
|
||||
// Maximum Deviation Found (approximation error): 1.965e-35
|
||||
//
|
||||
static const float Y = 0.99558162689208984375F;
|
||||
|
||||
static const T root1 = T(1569415565) / 1073741824uL;
|
||||
static const T root2 = (T(381566830) / 1073741824uL) / 1073741824uL;
|
||||
static const T root3 = ((T(111616537) / 1073741824uL) / 1073741824uL) / 1073741824uL;
|
||||
static const T root4 = (((T(503992070) / 1073741824uL) / 1073741824uL) / 1073741824uL) / 1073741824uL;
|
||||
static const T root5 = BOOST_MATH_BIG_CONSTANT(T, 113, 0.52112228569249997894452490385577338504019838794544e-36);
|
||||
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.25479851061131551526977464225335883769),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.18684290534374944114622235683619897417),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.80360876047931768958995775910991929922),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.67227342794829064330498117008564270136),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.26569010991230617151285010695543858005),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.05775672694575986971640757748003553385),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.0071432147823164975485922555833274240665),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.00048740753910766168912364555706064993274),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.16454996865214115723416538844975174761e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.20327832297631728077731148515093164955e-6)
|
||||
};
|
||||
static const T Q[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.6210924610812025425088411043163287646),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.6850757078559596612621337395886392594),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.4320913706209965531250495490639289418),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.4410872083455009362557012239501953402),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.081385727399251729505165509278152487225),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.0089478633066857163432104815183858149496),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.00055861622855066424871506755481997374154),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.1760168552357342401304462967950178554e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.20585454493572473724556649516040874384e-6),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.90745971844439990284514121823069162795e-11),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.48857673606545846774761343500033283272e-13),
|
||||
};
|
||||
T g = x - root1;
|
||||
g -= root2;
|
||||
g -= root3;
|
||||
g -= root4;
|
||||
g -= root5;
|
||||
T r = tools::evaluate_polynomial(P, T(x-1)) / tools::evaluate_polynomial(Q, T(x-1));
|
||||
T result = g * Y + g * r;
|
||||
|
||||
return result;
|
||||
}
|
||||
//
|
||||
// 19-digit precision:
|
||||
//
|
||||
template <class T>
|
||||
T digamma_imp_1_2(T x, const mpl::int_<64>*)
|
||||
{
|
||||
//
|
||||
// Now the approximation, we use the form:
|
||||
//
|
||||
// digamma(x) = (x - root) * (Y + R(x-1))
|
||||
//
|
||||
// Where root is the location of the positive root of digamma,
|
||||
// Y is a constant, and R is optimised for low absolute error
|
||||
// compared to Y.
|
||||
//
|
||||
// Max error found at 80-bit long double precision: 5.016e-20
|
||||
// Maximum Deviation Found (approximation error): 3.575e-20
|
||||
//
|
||||
static const float Y = 0.99558162689208984375F;
|
||||
|
||||
static const T root1 = T(1569415565) / 1073741824uL;
|
||||
static const T root2 = (T(381566830) / 1073741824uL) / 1073741824uL;
|
||||
static const T root3 = BOOST_MATH_BIG_CONSTANT(T, 64, 0.9016312093258695918615325266959189453125e-19);
|
||||
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.254798510611315515235),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.314628554532916496608),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.665836341559876230295),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.314767657147375752913),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.0541156266153505273939),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.00289268368333918761452)
|
||||
};
|
||||
static const T Q[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 2.1195759927055347547),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.54350554664961128724),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.486986018231042975162),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.0660481487173569812846),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.00298999662592323990972),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.165079794012604905639e-5),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.317940243105952177571e-7)
|
||||
};
|
||||
T g = x - root1;
|
||||
g -= root2;
|
||||
g -= root3;
|
||||
T r = tools::evaluate_polynomial(P, T(x-1)) / tools::evaluate_polynomial(Q, T(x-1));
|
||||
T result = g * Y + g * r;
|
||||
|
||||
return result;
|
||||
}
|
||||
//
|
||||
// 18-digit precision:
|
||||
//
|
||||
template <class T>
|
||||
T digamma_imp_1_2(T x, const mpl::int_<53>*)
|
||||
{
|
||||
//
|
||||
// Now the approximation, we use the form:
|
||||
//
|
||||
// digamma(x) = (x - root) * (Y + R(x-1))
|
||||
//
|
||||
// Where root is the location of the positive root of digamma,
|
||||
// Y is a constant, and R is optimised for low absolute error
|
||||
// compared to Y.
|
||||
//
|
||||
// Maximum Deviation Found: 1.466e-18
|
||||
// At double precision, max error found: 2.452e-17
|
||||
//
|
||||
static const float Y = 0.99558162689208984F;
|
||||
|
||||
static const T root1 = T(1569415565) / 1073741824uL;
|
||||
static const T root2 = (T(381566830) / 1073741824uL) / 1073741824uL;
|
||||
static const T root3 = BOOST_MATH_BIG_CONSTANT(T, 53, 0.9016312093258695918615325266959189453125e-19);
|
||||
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 0.25479851061131551),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, -0.32555031186804491),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, -0.65031853770896507),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, -0.28919126444774784),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, -0.045251321448739056),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, -0.0020713321167745952)
|
||||
};
|
||||
static const T Q[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 1.0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 2.0767117023730469),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 1.4606242909763515),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 0.43593529692665969),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 0.054151797245674225),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 0.0021284987017821144),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, -0.55789841321675513e-6)
|
||||
};
|
||||
T g = x - root1;
|
||||
g -= root2;
|
||||
g -= root3;
|
||||
T r = tools::evaluate_polynomial(P, T(x-1)) / tools::evaluate_polynomial(Q, T(x-1));
|
||||
T result = g * Y + g * r;
|
||||
|
||||
return result;
|
||||
}
|
||||
//
|
||||
// 9-digit precision:
|
||||
//
|
||||
template <class T>
|
||||
inline T digamma_imp_1_2(T x, const mpl::int_<24>*)
|
||||
{
|
||||
//
|
||||
// Now the approximation, we use the form:
|
||||
//
|
||||
// digamma(x) = (x - root) * (Y + R(x-1))
|
||||
//
|
||||
// Where root is the location of the positive root of digamma,
|
||||
// Y is a constant, and R is optimised for low absolute error
|
||||
// compared to Y.
|
||||
//
|
||||
// Maximum Deviation Found: 3.388e-010
|
||||
// At float precision, max error found: 2.008725e-008
|
||||
//
|
||||
static const float Y = 0.99558162689208984f;
|
||||
static const T root = 1532632.0f / 1048576;
|
||||
static const T root_minor = static_cast<T>(0.3700660185912626595423257213284682051735604e-6L);
|
||||
static const T P[] = {
|
||||
0.25479851023250261e0f,
|
||||
-0.44981331915268368e0f,
|
||||
-0.43916936919946835e0f,
|
||||
-0.61041765350579073e-1f
|
||||
};
|
||||
static const T Q[] = {
|
||||
0.1e1,
|
||||
0.15890202430554952e1f,
|
||||
0.65341249856146947e0f,
|
||||
0.63851690523355715e-1f
|
||||
};
|
||||
T g = x - root;
|
||||
g -= root_minor;
|
||||
T r = tools::evaluate_polynomial(P, T(x-1)) / tools::evaluate_polynomial(Q, T(x-1));
|
||||
T result = g * Y + g * r;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T, class Tag, class Policy>
|
||||
T digamma_imp(T x, const Tag* t, const Policy& pol)
|
||||
{
|
||||
//
|
||||
// This handles reflection of negative arguments, and all our
|
||||
// error handling, then forwards to the T-specific approximation.
|
||||
//
|
||||
BOOST_MATH_STD_USING // ADL of std functions.
|
||||
|
||||
T result = 0;
|
||||
//
|
||||
// Check for negative arguments and use reflection:
|
||||
//
|
||||
if(x <= -1)
|
||||
{
|
||||
// Reflect:
|
||||
x = 1 - x;
|
||||
// Argument reduction for tan:
|
||||
T remainder = x - floor(x);
|
||||
// Shift to negative if > 0.5:
|
||||
if(remainder > 0.5)
|
||||
{
|
||||
remainder -= 1;
|
||||
}
|
||||
//
|
||||
// check for evaluation at a negative pole:
|
||||
//
|
||||
if(remainder == 0)
|
||||
{
|
||||
return policies::raise_pole_error<T>("boost::math::digamma<%1%>(%1%)", 0, (1-x), pol);
|
||||
}
|
||||
result = constants::pi<T>() / tan(constants::pi<T>() * remainder);
|
||||
}
|
||||
if(x == 0)
|
||||
return policies::raise_pole_error<T>("boost::math::digamma<%1%>(%1%)", 0, x, pol);
|
||||
//
|
||||
// If we're above the lower-limit for the
|
||||
// asymptotic expansion then use it:
|
||||
//
|
||||
if(x >= digamma_large_lim(t))
|
||||
{
|
||||
result += digamma_imp_large(x, t);
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// If x > 2 reduce to the interval [1,2]:
|
||||
//
|
||||
while(x > 2)
|
||||
{
|
||||
x -= 1;
|
||||
result += 1/x;
|
||||
}
|
||||
//
|
||||
// If x < 1 use recurrance to shift to > 1:
|
||||
//
|
||||
while(x < 1)
|
||||
{
|
||||
result -= 1/x;
|
||||
x += 1;
|
||||
}
|
||||
result += digamma_imp_1_2(x, t);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
T digamma_imp(T x, const mpl::int_<0>* t, const Policy& pol)
|
||||
{
|
||||
//
|
||||
// This handles reflection of negative arguments, and all our
|
||||
// error handling, then forwards to the T-specific approximation.
|
||||
//
|
||||
BOOST_MATH_STD_USING // ADL of std functions.
|
||||
|
||||
T result = 0;
|
||||
//
|
||||
// Check for negative arguments and use reflection:
|
||||
//
|
||||
if(x <= -1)
|
||||
{
|
||||
// Reflect:
|
||||
x = 1 - x;
|
||||
// Argument reduction for tan:
|
||||
T remainder = x - floor(x);
|
||||
// Shift to negative if > 0.5:
|
||||
if(remainder > 0.5)
|
||||
{
|
||||
remainder -= 1;
|
||||
}
|
||||
//
|
||||
// check for evaluation at a negative pole:
|
||||
//
|
||||
if(remainder == 0)
|
||||
{
|
||||
return policies::raise_pole_error<T>("boost::math::digamma<%1%>(%1%)", 0, (1 - x), pol);
|
||||
}
|
||||
result = constants::pi<T>() / tan(constants::pi<T>() * remainder);
|
||||
}
|
||||
if(x == 0)
|
||||
return policies::raise_pole_error<T>("boost::math::digamma<%1%>(%1%)", 0, x, pol);
|
||||
//
|
||||
// If we're above the lower-limit for the
|
||||
// asymptotic expansion then use it, the
|
||||
// limit is a linear interpolation with
|
||||
// limit = 10 at 50 bit precision and
|
||||
// limit = 250 at 1000 bit precision.
|
||||
//
|
||||
int lim = 10 + ((tools::digits<T>() - 50) * 240L) / 950;
|
||||
T two_x = ldexp(x, 1);
|
||||
if(x >= lim)
|
||||
{
|
||||
result += digamma_imp_large(x, pol, t);
|
||||
}
|
||||
else if(floor(x) == x)
|
||||
{
|
||||
//
|
||||
// Special case for integer arguments, see
|
||||
// http://functions.wolfram.com/06.14.03.0001.01
|
||||
//
|
||||
result = -constants::euler<T, Policy>();
|
||||
T val = 1;
|
||||
while(val < x)
|
||||
{
|
||||
result += 1 / val;
|
||||
val += 1;
|
||||
}
|
||||
}
|
||||
else if(floor(two_x) == two_x)
|
||||
{
|
||||
//
|
||||
// Special case for half integer arguments, see:
|
||||
// http://functions.wolfram.com/06.14.03.0007.01
|
||||
//
|
||||
result = -2 * constants::ln_two<T, Policy>() - constants::euler<T, Policy>();
|
||||
int n = itrunc(x);
|
||||
if(n)
|
||||
{
|
||||
for(int k = 1; k < n; ++k)
|
||||
result += 1 / T(k);
|
||||
for(int k = n; k <= 2 * n - 1; ++k)
|
||||
result += 2 / T(k);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Rescale so we can use the asymptotic expansion:
|
||||
//
|
||||
while(x < lim)
|
||||
{
|
||||
result -= 1 / x;
|
||||
x += 1;
|
||||
}
|
||||
result += digamma_imp_large(x, pol, t);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
//
|
||||
// Initializer: ensure all our constants are initialized prior to the first call of main:
|
||||
//
|
||||
template <class T, class Policy>
|
||||
struct digamma_initializer
|
||||
{
|
||||
struct init
|
||||
{
|
||||
init()
|
||||
{
|
||||
typedef typename policies::precision<T, Policy>::type precision_type;
|
||||
do_init(mpl::bool_<precision_type::value && (precision_type::value <= 113)>());
|
||||
}
|
||||
void do_init(const mpl::true_&)
|
||||
{
|
||||
boost::math::digamma(T(1.5), Policy());
|
||||
boost::math::digamma(T(500), Policy());
|
||||
}
|
||||
void do_init(const mpl::false_&){}
|
||||
void force_instantiate()const{}
|
||||
};
|
||||
static const init initializer;
|
||||
static void force_instantiate()
|
||||
{
|
||||
initializer.force_instantiate();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class Policy>
|
||||
const typename digamma_initializer<T, Policy>::init digamma_initializer<T, Policy>::initializer;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class T, class Policy>
|
||||
inline typename tools::promote_args<T>::type
|
||||
digamma(T x, const Policy&)
|
||||
{
|
||||
typedef typename tools::promote_args<T>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
typedef typename policies::precision<T, Policy>::type precision_type;
|
||||
typedef typename mpl::if_<
|
||||
mpl::or_<
|
||||
mpl::less_equal<precision_type, mpl::int_<0> >,
|
||||
mpl::greater<precision_type, mpl::int_<114> >
|
||||
>,
|
||||
mpl::int_<0>,
|
||||
typename mpl::if_<
|
||||
mpl::less<precision_type, mpl::int_<25> >,
|
||||
mpl::int_<24>,
|
||||
typename mpl::if_<
|
||||
mpl::less<precision_type, mpl::int_<54> >,
|
||||
mpl::int_<53>,
|
||||
typename mpl::if_<
|
||||
mpl::less<precision_type, mpl::int_<65> >,
|
||||
mpl::int_<64>,
|
||||
mpl::int_<113>
|
||||
>::type
|
||||
>::type
|
||||
>::type
|
||||
>::type tag_type;
|
||||
|
||||
typedef typename policies::normalise<
|
||||
Policy,
|
||||
policies::promote_float<false>,
|
||||
policies::promote_double<false>,
|
||||
policies::discrete_quantile<>,
|
||||
policies::assert_undefined<> >::type forwarding_policy;
|
||||
|
||||
// Force initialization of constants:
|
||||
detail::digamma_initializer<value_type, forwarding_policy>::force_instantiate();
|
||||
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(detail::digamma_imp(
|
||||
static_cast<value_type>(x),
|
||||
static_cast<const tag_type*>(0), forwarding_policy()), "boost::math::digamma<%1%>(%1%)");
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typename tools::promote_args<T>::type
|
||||
digamma(T x)
|
||||
{
|
||||
return digamma(x, policies::policy<>());
|
||||
}
|
||||
|
||||
} // namespace math
|
||||
} // namespace boost
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
201
code_isotrope/boost/math/special_functions/ellint_1.hpp
Executable file
201
code_isotrope/boost/math/special_functions/ellint_1.hpp
Executable file
@@ -0,0 +1,201 @@
|
||||
// Copyright (c) 2006 Xiaogang Zhang
|
||||
// Copyright (c) 2006 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)
|
||||
//
|
||||
// History:
|
||||
// XZ wrote the original of this file as part of the Google
|
||||
// Summer of Code 2006. JM modified it to fit into the
|
||||
// Boost.Math conceptual framework better, and to ensure
|
||||
// that the code continues to work no matter how many digits
|
||||
// type T has.
|
||||
|
||||
#ifndef BOOST_MATH_ELLINT_1_HPP
|
||||
#define BOOST_MATH_ELLINT_1_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/math/special_functions/ellint_rf.hpp>
|
||||
#include <boost/math/constants/constants.hpp>
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
#include <boost/math/tools/workaround.hpp>
|
||||
#include <boost/math/special_functions/round.hpp>
|
||||
|
||||
// Elliptic integrals (complete and incomplete) of the first kind
|
||||
// Carlson, Numerische Mathematik, vol 33, 1 (1979)
|
||||
|
||||
namespace boost { namespace math {
|
||||
|
||||
template <class T1, class T2, class Policy>
|
||||
typename tools::promote_args<T1, T2>::type ellint_1(T1 k, T2 phi, const Policy& pol);
|
||||
|
||||
namespace detail{
|
||||
|
||||
template <typename T, typename Policy>
|
||||
T ellint_k_imp(T k, const Policy& pol);
|
||||
|
||||
// Elliptic integral (Legendre form) of the first kind
|
||||
template <typename T, typename Policy>
|
||||
T ellint_f_imp(T phi, T k, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
using namespace boost::math::tools;
|
||||
using namespace boost::math::constants;
|
||||
|
||||
static const char* function = "boost::math::ellint_f<%1%>(%1%,%1%)";
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(phi);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(k);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(function);
|
||||
|
||||
if (abs(k) > 1)
|
||||
{
|
||||
return policies::raise_domain_error<T>(function,
|
||||
"Got k = %1%, function requires |k| <= 1", k, pol);
|
||||
}
|
||||
|
||||
bool invert = false;
|
||||
if(phi < 0)
|
||||
{
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(phi);
|
||||
phi = fabs(phi);
|
||||
invert = true;
|
||||
}
|
||||
|
||||
T result;
|
||||
|
||||
if(phi >= tools::max_value<T>())
|
||||
{
|
||||
// Need to handle infinity as a special case:
|
||||
result = policies::raise_overflow_error<T>(function, 0, pol);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(result);
|
||||
}
|
||||
else if(phi > 1 / tools::epsilon<T>())
|
||||
{
|
||||
// Phi is so large that phi%pi is necessarily zero (or garbage),
|
||||
// just return the second part of the duplication formula:
|
||||
result = 2 * phi * ellint_k_imp(k, pol) / constants::pi<T>();
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Carlson's algorithm works only for |phi| <= pi/2,
|
||||
// use the integrand's periodicity to normalize phi
|
||||
//
|
||||
// Xiaogang's original code used a cast to long long here
|
||||
// but that fails if T has more digits than a long long,
|
||||
// so rewritten to use fmod instead:
|
||||
//
|
||||
BOOST_MATH_INSTRUMENT_CODE("pi/2 = " << constants::pi<T>() / 2);
|
||||
T rphi = boost::math::tools::fmod_workaround(phi, T(constants::half_pi<T>()));
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(rphi);
|
||||
T m = boost::math::round((phi - rphi) / constants::half_pi<T>());
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(m);
|
||||
int s = 1;
|
||||
if(boost::math::tools::fmod_workaround(m, T(2)) > 0.5)
|
||||
{
|
||||
m += 1;
|
||||
s = -1;
|
||||
rphi = constants::half_pi<T>() - rphi;
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(rphi);
|
||||
}
|
||||
T sinp = sin(rphi);
|
||||
sinp *= sinp;
|
||||
T cosp = cos(rphi);
|
||||
cosp *= cosp;
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(sinp);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(cosp);
|
||||
if(sinp > tools::min_value<T>())
|
||||
{
|
||||
//
|
||||
// Use http://dlmf.nist.gov/19.25#E5, note that
|
||||
// c-1 simplifies to cot^2(rphi) which avoid cancellation:
|
||||
//
|
||||
T c = 1 / sinp;
|
||||
result = rphi == 0 ? static_cast<T>(0) : static_cast<T>(s * ellint_rf_imp(T(cosp / sinp), T(c - k * k), c, pol));
|
||||
}
|
||||
else
|
||||
result = s * sin(rphi);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(result);
|
||||
if(m != 0)
|
||||
{
|
||||
result += m * ellint_k_imp(k, pol);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(result);
|
||||
}
|
||||
}
|
||||
return invert ? T(-result) : result;
|
||||
}
|
||||
|
||||
// Complete elliptic integral (Legendre form) of the first kind
|
||||
template <typename T, typename Policy>
|
||||
T ellint_k_imp(T k, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
using namespace boost::math::tools;
|
||||
|
||||
static const char* function = "boost::math::ellint_k<%1%>(%1%)";
|
||||
|
||||
if (abs(k) > 1)
|
||||
{
|
||||
return policies::raise_domain_error<T>(function,
|
||||
"Got k = %1%, function requires |k| <= 1", k, pol);
|
||||
}
|
||||
if (abs(k) == 1)
|
||||
{
|
||||
return policies::raise_overflow_error<T>(function, 0, pol);
|
||||
}
|
||||
|
||||
T x = 0;
|
||||
T y = 1 - k * k;
|
||||
T z = 1;
|
||||
T value = ellint_rf_imp(x, y, z, pol);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
template <typename T, typename Policy>
|
||||
inline typename tools::promote_args<T>::type ellint_1(T k, const Policy& pol, const mpl::true_&)
|
||||
{
|
||||
typedef typename tools::promote_args<T>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(detail::ellint_k_imp(static_cast<value_type>(k), pol), "boost::math::ellint_1<%1%>(%1%)");
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
inline typename tools::promote_args<T1, T2>::type ellint_1(T1 k, T2 phi, const mpl::false_&)
|
||||
{
|
||||
return boost::math::ellint_1(k, phi, policies::policy<>());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Complete elliptic integral (Legendre form) of the first kind
|
||||
template <typename T>
|
||||
inline typename tools::promote_args<T>::type ellint_1(T k)
|
||||
{
|
||||
return ellint_1(k, policies::policy<>());
|
||||
}
|
||||
|
||||
// Elliptic integral (Legendre form) of the first kind
|
||||
template <class T1, class T2, class Policy>
|
||||
inline typename tools::promote_args<T1, T2>::type ellint_1(T1 k, T2 phi, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T1, T2>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(detail::ellint_f_imp(static_cast<value_type>(phi), static_cast<value_type>(k), pol), "boost::math::ellint_1<%1%>(%1%,%1%)");
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
inline typename tools::promote_args<T1, T2>::type ellint_1(T1 k, T2 phi)
|
||||
{
|
||||
typedef typename policies::is_policy<T2>::type tag_type;
|
||||
return detail::ellint_1(k, phi, tag_type());
|
||||
}
|
||||
|
||||
}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_ELLINT_1_HPP
|
||||
|
||||
191
code_isotrope/boost/math/special_functions/ellint_2.hpp
Executable file
191
code_isotrope/boost/math/special_functions/ellint_2.hpp
Executable file
@@ -0,0 +1,191 @@
|
||||
// Copyright (c) 2006 Xiaogang Zhang
|
||||
// Copyright (c) 2006 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)
|
||||
//
|
||||
// History:
|
||||
// XZ wrote the original of this file as part of the Google
|
||||
// Summer of Code 2006. JM modified it to fit into the
|
||||
// Boost.Math conceptual framework better, and to ensure
|
||||
// that the code continues to work no matter how many digits
|
||||
// type T has.
|
||||
|
||||
#ifndef BOOST_MATH_ELLINT_2_HPP
|
||||
#define BOOST_MATH_ELLINT_2_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/math/special_functions/ellint_rf.hpp>
|
||||
#include <boost/math/special_functions/ellint_rd.hpp>
|
||||
#include <boost/math/special_functions/ellint_rg.hpp>
|
||||
#include <boost/math/constants/constants.hpp>
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
#include <boost/math/tools/workaround.hpp>
|
||||
#include <boost/math/special_functions/round.hpp>
|
||||
|
||||
// Elliptic integrals (complete and incomplete) of the second kind
|
||||
// Carlson, Numerische Mathematik, vol 33, 1 (1979)
|
||||
|
||||
namespace boost { namespace math {
|
||||
|
||||
template <class T1, class T2, class Policy>
|
||||
typename tools::promote_args<T1, T2>::type ellint_2(T1 k, T2 phi, const Policy& pol);
|
||||
|
||||
namespace detail{
|
||||
|
||||
template <typename T, typename Policy>
|
||||
T ellint_e_imp(T k, const Policy& pol);
|
||||
|
||||
// Elliptic integral (Legendre form) of the second kind
|
||||
template <typename T, typename Policy>
|
||||
T ellint_e_imp(T phi, T k, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
using namespace boost::math::tools;
|
||||
using namespace boost::math::constants;
|
||||
|
||||
bool invert = false;
|
||||
if(phi < 0)
|
||||
{
|
||||
phi = fabs(phi);
|
||||
invert = true;
|
||||
}
|
||||
|
||||
T result;
|
||||
|
||||
if(phi >= tools::max_value<T>())
|
||||
{
|
||||
// Need to handle infinity as a special case:
|
||||
result = policies::raise_overflow_error<T>("boost::math::ellint_e<%1%>(%1%,%1%)", 0, pol);
|
||||
}
|
||||
else if(phi > 1 / tools::epsilon<T>())
|
||||
{
|
||||
// Phi is so large that phi%pi is necessarily zero (or garbage),
|
||||
// just return the second part of the duplication formula:
|
||||
result = 2 * phi * ellint_e_imp(k, pol) / constants::pi<T>();
|
||||
}
|
||||
else if(k == 0)
|
||||
{
|
||||
return invert ? T(-phi) : phi;
|
||||
}
|
||||
else if(fabs(k) == 1)
|
||||
{
|
||||
return invert ? T(-sin(phi)) : T(sin(phi));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Carlson's algorithm works only for |phi| <= pi/2,
|
||||
// use the integrand's periodicity to normalize phi
|
||||
//
|
||||
// Xiaogang's original code used a cast to long long here
|
||||
// but that fails if T has more digits than a long long,
|
||||
// so rewritten to use fmod instead:
|
||||
//
|
||||
T rphi = boost::math::tools::fmod_workaround(phi, T(constants::half_pi<T>()));
|
||||
T m = boost::math::round((phi - rphi) / constants::half_pi<T>());
|
||||
int s = 1;
|
||||
if(boost::math::tools::fmod_workaround(m, T(2)) > 0.5)
|
||||
{
|
||||
m += 1;
|
||||
s = -1;
|
||||
rphi = constants::half_pi<T>() - rphi;
|
||||
}
|
||||
T k2 = k * k;
|
||||
if(k2 > 1)
|
||||
{
|
||||
return policies::raise_domain_error<T>("boost::math::ellint_2<%1%>(%1%, %1%)", "The parameter k is out of range, got k = %1%", k, pol);
|
||||
}
|
||||
else if(rphi < tools::root_epsilon<T>())
|
||||
{
|
||||
// See http://functions.wolfram.com/EllipticIntegrals/EllipticE2/06/01/03/0001/
|
||||
result = s * rphi;
|
||||
}
|
||||
else
|
||||
{
|
||||
// http://dlmf.nist.gov/19.25#E10
|
||||
T sinp = sin(rphi);
|
||||
T cosp = cos(rphi);
|
||||
T c = 1 / (sinp * sinp);
|
||||
T cm1 = cosp * cosp / (sinp * sinp); // c - 1
|
||||
result = s * ((1 - k2) * ellint_rf_imp(cm1, T(c - k2), c, pol) + k2 * (1 - k2) * ellint_rd(cm1, c, T(c - k2), pol) / 3 + k2 * sqrt(cm1 / (c * (c - k2))));
|
||||
}
|
||||
if(m != 0)
|
||||
result += m * ellint_e_imp(k, pol);
|
||||
}
|
||||
return invert ? T(-result) : result;
|
||||
}
|
||||
|
||||
// Complete elliptic integral (Legendre form) of the second kind
|
||||
template <typename T, typename Policy>
|
||||
T ellint_e_imp(T k, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
using namespace boost::math::tools;
|
||||
|
||||
if (abs(k) > 1)
|
||||
{
|
||||
return policies::raise_domain_error<T>("boost::math::ellint_e<%1%>(%1%)",
|
||||
"Got k = %1%, function requires |k| <= 1", k, pol);
|
||||
}
|
||||
if (abs(k) == 1)
|
||||
{
|
||||
return static_cast<T>(1);
|
||||
}
|
||||
|
||||
T x = 0;
|
||||
T t = k * k;
|
||||
T y = 1 - t;
|
||||
T z = 1;
|
||||
T value = 2 * ellint_rg_imp(x, y, z, pol);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
template <typename T, typename Policy>
|
||||
inline typename tools::promote_args<T>::type ellint_2(T k, const Policy& pol, const mpl::true_&)
|
||||
{
|
||||
typedef typename tools::promote_args<T>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(detail::ellint_e_imp(static_cast<value_type>(k), pol), "boost::math::ellint_2<%1%>(%1%)");
|
||||
}
|
||||
|
||||
// Elliptic integral (Legendre form) of the second kind
|
||||
template <class T1, class T2>
|
||||
inline typename tools::promote_args<T1, T2>::type ellint_2(T1 k, T2 phi, const mpl::false_&)
|
||||
{
|
||||
return boost::math::ellint_2(k, phi, policies::policy<>());
|
||||
}
|
||||
|
||||
} // detail
|
||||
|
||||
// Complete elliptic integral (Legendre form) of the second kind
|
||||
template <typename T>
|
||||
inline typename tools::promote_args<T>::type ellint_2(T k)
|
||||
{
|
||||
return ellint_2(k, policies::policy<>());
|
||||
}
|
||||
|
||||
// Elliptic integral (Legendre form) of the second kind
|
||||
template <class T1, class T2>
|
||||
inline typename tools::promote_args<T1, T2>::type ellint_2(T1 k, T2 phi)
|
||||
{
|
||||
typedef typename policies::is_policy<T2>::type tag_type;
|
||||
return detail::ellint_2(k, phi, tag_type());
|
||||
}
|
||||
|
||||
template <class T1, class T2, class Policy>
|
||||
inline typename tools::promote_args<T1, T2>::type ellint_2(T1 k, T2 phi, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T1, T2>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(detail::ellint_e_imp(static_cast<value_type>(phi), static_cast<value_type>(k), pol), "boost::math::ellint_2<%1%>(%1%,%1%)");
|
||||
}
|
||||
|
||||
}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_ELLINT_2_HPP
|
||||
|
||||
376
code_isotrope/boost/math/special_functions/ellint_3.hpp
Executable file
376
code_isotrope/boost/math/special_functions/ellint_3.hpp
Executable file
@@ -0,0 +1,376 @@
|
||||
// Copyright (c) 2006 Xiaogang Zhang
|
||||
// Copyright (c) 2006 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)
|
||||
//
|
||||
// History:
|
||||
// XZ wrote the original of this file as part of the Google
|
||||
// Summer of Code 2006. JM modified it to fit into the
|
||||
// Boost.Math conceptual framework better, and to correctly
|
||||
// handle the various corner cases.
|
||||
//
|
||||
|
||||
#ifndef BOOST_MATH_ELLINT_3_HPP
|
||||
#define BOOST_MATH_ELLINT_3_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/math/special_functions/ellint_rf.hpp>
|
||||
#include <boost/math/special_functions/ellint_rj.hpp>
|
||||
#include <boost/math/special_functions/ellint_1.hpp>
|
||||
#include <boost/math/special_functions/ellint_2.hpp>
|
||||
#include <boost/math/special_functions/log1p.hpp>
|
||||
#include <boost/math/special_functions/atanh.hpp>
|
||||
#include <boost/math/constants/constants.hpp>
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
#include <boost/math/tools/workaround.hpp>
|
||||
#include <boost/math/special_functions/round.hpp>
|
||||
|
||||
// Elliptic integrals (complete and incomplete) of the third kind
|
||||
// Carlson, Numerische Mathematik, vol 33, 1 (1979)
|
||||
|
||||
namespace boost { namespace math {
|
||||
|
||||
namespace detail{
|
||||
|
||||
template <typename T, typename Policy>
|
||||
T ellint_pi_imp(T v, T k, T vc, const Policy& pol);
|
||||
|
||||
// Elliptic integral (Legendre form) of the third kind
|
||||
template <typename T, typename Policy>
|
||||
T ellint_pi_imp(T v, T phi, T k, T vc, const Policy& pol)
|
||||
{
|
||||
// Note vc = 1-v presumably without cancellation error.
|
||||
BOOST_MATH_STD_USING
|
||||
|
||||
static const char* function = "boost::math::ellint_3<%1%>(%1%,%1%,%1%)";
|
||||
|
||||
if(abs(k) > 1)
|
||||
{
|
||||
return policies::raise_domain_error<T>(function,
|
||||
"Got k = %1%, function requires |k| <= 1", k, pol);
|
||||
}
|
||||
|
||||
T sphi = sin(fabs(phi));
|
||||
T result = 0;
|
||||
|
||||
// Special cases first:
|
||||
if(v == 0)
|
||||
{
|
||||
// A&S 17.7.18 & 19
|
||||
return (k == 0) ? phi : ellint_f_imp(phi, k, pol);
|
||||
}
|
||||
if((v > 0) && (1 / v < (sphi * sphi)))
|
||||
{
|
||||
// Complex result is a domain error:
|
||||
return policies::raise_domain_error<T>(function,
|
||||
"Got v = %1%, but result is complex for v > 1 / sin^2(phi)", v, pol);
|
||||
}
|
||||
|
||||
if(v == 1)
|
||||
{
|
||||
// http://functions.wolfram.com/08.06.03.0008.01
|
||||
T m = k * k;
|
||||
result = sqrt(1 - m * sphi * sphi) * tan(phi) - ellint_e_imp(phi, k, pol);
|
||||
result /= 1 - m;
|
||||
result += ellint_f_imp(phi, k, pol);
|
||||
return result;
|
||||
}
|
||||
if(phi == constants::half_pi<T>())
|
||||
{
|
||||
// Have to filter this case out before the next
|
||||
// special case, otherwise we might get an infinity from
|
||||
// tan(phi).
|
||||
// Also note that since we can't represent PI/2 exactly
|
||||
// in a T, this is a bit of a guess as to the users true
|
||||
// intent...
|
||||
//
|
||||
return ellint_pi_imp(v, k, vc, pol);
|
||||
}
|
||||
if((phi > constants::half_pi<T>()) || (phi < 0))
|
||||
{
|
||||
// Carlson's algorithm works only for |phi| <= pi/2,
|
||||
// use the integrand's periodicity to normalize phi
|
||||
//
|
||||
// Xiaogang's original code used a cast to long long here
|
||||
// but that fails if T has more digits than a long long,
|
||||
// so rewritten to use fmod instead:
|
||||
//
|
||||
// See http://functions.wolfram.com/08.06.16.0002.01
|
||||
//
|
||||
if(fabs(phi) > 1 / tools::epsilon<T>())
|
||||
{
|
||||
if(v > 1)
|
||||
return policies::raise_domain_error<T>(
|
||||
function,
|
||||
"Got v = %1%, but this is only supported for 0 <= phi <= pi/2", v, pol);
|
||||
//
|
||||
// Phi is so large that phi%pi is necessarily zero (or garbage),
|
||||
// just return the second part of the duplication formula:
|
||||
//
|
||||
result = 2 * fabs(phi) * ellint_pi_imp(v, k, vc, pol) / constants::pi<T>();
|
||||
}
|
||||
else
|
||||
{
|
||||
T rphi = boost::math::tools::fmod_workaround(T(fabs(phi)), T(constants::half_pi<T>()));
|
||||
T m = boost::math::round((fabs(phi) - rphi) / constants::half_pi<T>());
|
||||
int sign = 1;
|
||||
if((m != 0) && (k >= 1))
|
||||
{
|
||||
return policies::raise_domain_error<T>(function, "Got k=1 and phi=%1% but the result is complex in that domain", phi, pol);
|
||||
}
|
||||
if(boost::math::tools::fmod_workaround(m, T(2)) > 0.5)
|
||||
{
|
||||
m += 1;
|
||||
sign = -1;
|
||||
rphi = constants::half_pi<T>() - rphi;
|
||||
}
|
||||
result = sign * ellint_pi_imp(v, rphi, k, vc, pol);
|
||||
if((m > 0) && (vc > 0))
|
||||
result += m * ellint_pi_imp(v, k, vc, pol);
|
||||
}
|
||||
return phi < 0 ? T(-result) : result;
|
||||
}
|
||||
if(k == 0)
|
||||
{
|
||||
// A&S 17.7.20:
|
||||
if(v < 1)
|
||||
{
|
||||
T vcr = sqrt(vc);
|
||||
return atan(vcr * tan(phi)) / vcr;
|
||||
}
|
||||
else if(v == 1)
|
||||
{
|
||||
return tan(phi);
|
||||
}
|
||||
else
|
||||
{
|
||||
// v > 1:
|
||||
T vcr = sqrt(-vc);
|
||||
T arg = vcr * tan(phi);
|
||||
return (boost::math::log1p(arg, pol) - boost::math::log1p(-arg, pol)) / (2 * vcr);
|
||||
}
|
||||
}
|
||||
if(v < 0)
|
||||
{
|
||||
//
|
||||
// If we don't shift to 0 <= v <= 1 we get
|
||||
// cancellation errors later on. Use
|
||||
// A&S 17.7.15/16 to shift to v > 0.
|
||||
//
|
||||
// Mathematica simplifies the expressions
|
||||
// given in A&S as follows (with thanks to
|
||||
// Rocco Romeo for figuring these out!):
|
||||
//
|
||||
// V = (k2 - n)/(1 - n)
|
||||
// Assuming[(k2 >= 0 && k2 <= 1) && n < 0, FullSimplify[Sqrt[(1 - V)*(1 - k2 / V)] / Sqrt[((1 - n)*(1 - k2 / n))]]]
|
||||
// Result: ((-1 + k2) n) / ((-1 + n) (-k2 + n))
|
||||
//
|
||||
// Assuming[(k2 >= 0 && k2 <= 1) && n < 0, FullSimplify[k2 / (Sqrt[-n*(k2 - n) / (1 - n)] * Sqrt[(1 - n)*(1 - k2 / n)])]]
|
||||
// Result : k2 / (k2 - n)
|
||||
//
|
||||
// Assuming[(k2 >= 0 && k2 <= 1) && n < 0, FullSimplify[Sqrt[1 / ((1 - n)*(1 - k2 / n))]]]
|
||||
// Result : Sqrt[n / ((k2 - n) (-1 + n))]
|
||||
//
|
||||
T k2 = k * k;
|
||||
T N = (k2 - v) / (1 - v);
|
||||
T Nm1 = (1 - k2) / (1 - v);
|
||||
T p2 = -v * N;
|
||||
T t;
|
||||
if(p2 <= tools::min_value<T>())
|
||||
p2 = sqrt(-v) * sqrt(N);
|
||||
else
|
||||
p2 = sqrt(p2);
|
||||
T delta = sqrt(1 - k2 * sphi * sphi);
|
||||
if(N > k2)
|
||||
{
|
||||
result = ellint_pi_imp(N, phi, k, Nm1, pol);
|
||||
result *= v / (v - 1);
|
||||
result *= (k2 - 1) / (v - k2);
|
||||
}
|
||||
|
||||
if(k != 0)
|
||||
{
|
||||
t = ellint_f_imp(phi, k, pol);
|
||||
t *= k2 / (k2 - v);
|
||||
result += t;
|
||||
}
|
||||
t = v / ((k2 - v) * (v - 1));
|
||||
if(t > tools::min_value<T>())
|
||||
{
|
||||
result += atan((p2 / 2) * sin(2 * phi) / delta) * sqrt(t);
|
||||
}
|
||||
else
|
||||
{
|
||||
result += atan((p2 / 2) * sin(2 * phi) / delta) * sqrt(fabs(1 / (k2 - v))) * sqrt(fabs(v / (v - 1)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
if(k == 1)
|
||||
{
|
||||
// See http://functions.wolfram.com/08.06.03.0013.01
|
||||
result = sqrt(v) * atanh(sqrt(v) * sin(phi)) - log(1 / cos(phi) + tan(phi));
|
||||
result /= v - 1;
|
||||
return result;
|
||||
}
|
||||
#if 0 // disabled but retained for future reference: see below.
|
||||
if(v > 1)
|
||||
{
|
||||
//
|
||||
// If v > 1 we can use the identity in A&S 17.7.7/8
|
||||
// to shift to 0 <= v <= 1. In contrast to previous
|
||||
// revisions of this header, this identity does now work
|
||||
// but appears not to produce better error rates in
|
||||
// practice. Archived here for future reference...
|
||||
//
|
||||
T k2 = k * k;
|
||||
T N = k2 / v;
|
||||
T Nm1 = (v - k2) / v;
|
||||
T p1 = sqrt((-vc) * (1 - k2 / v));
|
||||
T delta = sqrt(1 - k2 * sphi * sphi);
|
||||
//
|
||||
// These next two terms have a large amount of cancellation
|
||||
// so it's not clear if this relation is useable even if
|
||||
// the issues with phi > pi/2 can be fixed:
|
||||
//
|
||||
result = -ellint_pi_imp(N, phi, k, Nm1, pol);
|
||||
result += ellint_f_imp(phi, k, pol);
|
||||
//
|
||||
// This log term gives the complex result when
|
||||
// n > 1/sin^2(phi)
|
||||
// However that case is dealt with as an error above,
|
||||
// so we should always get a real result here:
|
||||
//
|
||||
result += log((delta + p1 * tan(phi)) / (delta - p1 * tan(phi))) / (2 * p1);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
//
|
||||
// Carlson's algorithm works only for |phi| <= pi/2,
|
||||
// by the time we get here phi should already have been
|
||||
// normalised above.
|
||||
//
|
||||
BOOST_ASSERT(fabs(phi) < constants::half_pi<T>());
|
||||
BOOST_ASSERT(phi >= 0);
|
||||
T x, y, z, p, t;
|
||||
T cosp = cos(phi);
|
||||
x = cosp * cosp;
|
||||
t = sphi * sphi;
|
||||
y = 1 - k * k * t;
|
||||
z = 1;
|
||||
if(v * t < 0.5)
|
||||
p = 1 - v * t;
|
||||
else
|
||||
p = x + vc * t;
|
||||
result = sphi * (ellint_rf_imp(x, y, z, pol) + v * t * ellint_rj_imp(x, y, z, p, pol) / 3);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Complete elliptic integral (Legendre form) of the third kind
|
||||
template <typename T, typename Policy>
|
||||
T ellint_pi_imp(T v, T k, T vc, const Policy& pol)
|
||||
{
|
||||
// Note arg vc = 1-v, possibly without cancellation errors
|
||||
BOOST_MATH_STD_USING
|
||||
using namespace boost::math::tools;
|
||||
|
||||
static const char* function = "boost::math::ellint_pi<%1%>(%1%,%1%)";
|
||||
|
||||
if (abs(k) >= 1)
|
||||
{
|
||||
return policies::raise_domain_error<T>(function,
|
||||
"Got k = %1%, function requires |k| <= 1", k, pol);
|
||||
}
|
||||
if(vc <= 0)
|
||||
{
|
||||
// Result is complex:
|
||||
return policies::raise_domain_error<T>(function,
|
||||
"Got v = %1%, function requires v < 1", v, pol);
|
||||
}
|
||||
|
||||
if(v == 0)
|
||||
{
|
||||
return (k == 0) ? boost::math::constants::pi<T>() / 2 : ellint_k_imp(k, pol);
|
||||
}
|
||||
|
||||
if(v < 0)
|
||||
{
|
||||
// Apply A&S 17.7.17:
|
||||
T k2 = k * k;
|
||||
T N = (k2 - v) / (1 - v);
|
||||
T Nm1 = (1 - k2) / (1 - v);
|
||||
T result = 0;
|
||||
result = boost::math::detail::ellint_pi_imp(N, k, Nm1, pol);
|
||||
// This next part is split in two to avoid spurious over/underflow:
|
||||
result *= -v / (1 - v);
|
||||
result *= (1 - k2) / (k2 - v);
|
||||
result += ellint_k_imp(k, pol) * k2 / (k2 - v);
|
||||
return result;
|
||||
}
|
||||
|
||||
T x = 0;
|
||||
T y = 1 - k * k;
|
||||
T z = 1;
|
||||
T p = vc;
|
||||
T value = ellint_rf_imp(x, y, z, pol) + v * ellint_rj_imp(x, y, z, p, pol) / 3;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
template <class T1, class T2, class T3>
|
||||
inline typename tools::promote_args<T1, T2, T3>::type ellint_3(T1 k, T2 v, T3 phi, const mpl::false_&)
|
||||
{
|
||||
return boost::math::ellint_3(k, v, phi, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T1, class T2, class Policy>
|
||||
inline typename tools::promote_args<T1, T2>::type ellint_3(T1 k, T2 v, const Policy& pol, const mpl::true_&)
|
||||
{
|
||||
typedef typename tools::promote_args<T1, T2>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(
|
||||
detail::ellint_pi_imp(
|
||||
static_cast<value_type>(v),
|
||||
static_cast<value_type>(k),
|
||||
static_cast<value_type>(1-v),
|
||||
pol), "boost::math::ellint_3<%1%>(%1%,%1%)");
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class T1, class T2, class T3, class Policy>
|
||||
inline typename tools::promote_args<T1, T2, T3>::type ellint_3(T1 k, T2 v, T3 phi, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T1, T2, T3>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(
|
||||
detail::ellint_pi_imp(
|
||||
static_cast<value_type>(v),
|
||||
static_cast<value_type>(phi),
|
||||
static_cast<value_type>(k),
|
||||
static_cast<value_type>(1-v),
|
||||
pol), "boost::math::ellint_3<%1%>(%1%,%1%,%1%)");
|
||||
}
|
||||
|
||||
template <class T1, class T2, class T3>
|
||||
typename detail::ellint_3_result<T1, T2, T3>::type ellint_3(T1 k, T2 v, T3 phi)
|
||||
{
|
||||
typedef typename policies::is_policy<T3>::type tag_type;
|
||||
return detail::ellint_3(k, v, phi, tag_type());
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
inline typename tools::promote_args<T1, T2>::type ellint_3(T1 k, T2 v)
|
||||
{
|
||||
return ellint_3(k, v, policies::policy<>());
|
||||
}
|
||||
|
||||
}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_ELLINT_3_HPP
|
||||
|
||||
181
code_isotrope/boost/math/special_functions/ellint_d.hpp
Executable file
181
code_isotrope/boost/math/special_functions/ellint_d.hpp
Executable file
@@ -0,0 +1,181 @@
|
||||
// Copyright (c) 2006 Xiaogang Zhang
|
||||
// Copyright (c) 2006 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)
|
||||
//
|
||||
// History:
|
||||
// XZ wrote the original of this file as part of the Google
|
||||
// Summer of Code 2006. JM modified it to fit into the
|
||||
// Boost.Math conceptual framework better, and to ensure
|
||||
// that the code continues to work no matter how many digits
|
||||
// type T has.
|
||||
|
||||
#ifndef BOOST_MATH_ELLINT_D_HPP
|
||||
#define BOOST_MATH_ELLINT_D_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/math/special_functions/ellint_rf.hpp>
|
||||
#include <boost/math/special_functions/ellint_rd.hpp>
|
||||
#include <boost/math/special_functions/ellint_rg.hpp>
|
||||
#include <boost/math/constants/constants.hpp>
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
#include <boost/math/tools/workaround.hpp>
|
||||
#include <boost/math/special_functions/round.hpp>
|
||||
|
||||
// Elliptic integrals (complete and incomplete) of the second kind
|
||||
// Carlson, Numerische Mathematik, vol 33, 1 (1979)
|
||||
|
||||
namespace boost { namespace math {
|
||||
|
||||
template <class T1, class T2, class Policy>
|
||||
typename tools::promote_args<T1, T2>::type ellint_d(T1 k, T2 phi, const Policy& pol);
|
||||
|
||||
namespace detail{
|
||||
|
||||
template <typename T, typename Policy>
|
||||
T ellint_d_imp(T k, const Policy& pol);
|
||||
|
||||
// Elliptic integral (Legendre form) of the second kind
|
||||
template <typename T, typename Policy>
|
||||
T ellint_d_imp(T phi, T k, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
using namespace boost::math::tools;
|
||||
using namespace boost::math::constants;
|
||||
|
||||
bool invert = false;
|
||||
if(phi < 0)
|
||||
{
|
||||
phi = fabs(phi);
|
||||
invert = true;
|
||||
}
|
||||
|
||||
T result;
|
||||
|
||||
if(phi >= tools::max_value<T>())
|
||||
{
|
||||
// Need to handle infinity as a special case:
|
||||
result = policies::raise_overflow_error<T>("boost::math::ellint_d<%1%>(%1%,%1%)", 0, pol);
|
||||
}
|
||||
else if(phi > 1 / tools::epsilon<T>())
|
||||
{
|
||||
// Phi is so large that phi%pi is necessarily zero (or garbage),
|
||||
// just return the second part of the duplication formula:
|
||||
result = 2 * phi * ellint_d_imp(k, pol) / constants::pi<T>();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Carlson's algorithm works only for |phi| <= pi/2,
|
||||
// use the integrand's periodicity to normalize phi
|
||||
//
|
||||
T rphi = boost::math::tools::fmod_workaround(phi, T(constants::half_pi<T>()));
|
||||
T m = boost::math::round((phi - rphi) / constants::half_pi<T>());
|
||||
int s = 1;
|
||||
if(boost::math::tools::fmod_workaround(m, T(2)) > 0.5)
|
||||
{
|
||||
m += 1;
|
||||
s = -1;
|
||||
rphi = constants::half_pi<T>() - rphi;
|
||||
}
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(rphi);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(m);
|
||||
T sinp = sin(rphi);
|
||||
T cosp = cos(rphi);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(sinp);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(cosp);
|
||||
T c = 1 / (sinp * sinp);
|
||||
T cm1 = cosp * cosp / (sinp * sinp); // c - 1
|
||||
T k2 = k * k;
|
||||
if(k2 > 1)
|
||||
{
|
||||
return policies::raise_domain_error<T>("boost::math::ellint_d<%1%>(%1%, %1%)", "The parameter k is out of range, got k = %1%", k, pol);
|
||||
}
|
||||
else if(rphi == 0)
|
||||
{
|
||||
result = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// http://dlmf.nist.gov/19.25#E10
|
||||
result = s * ellint_rd_imp(cm1, T(c - k2), c, pol) / 3;
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(result);
|
||||
}
|
||||
if(m != 0)
|
||||
result += m * ellint_d_imp(k, pol);
|
||||
}
|
||||
return invert ? T(-result) : result;
|
||||
}
|
||||
|
||||
// Complete elliptic integral (Legendre form) of the second kind
|
||||
template <typename T, typename Policy>
|
||||
T ellint_d_imp(T k, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
using namespace boost::math::tools;
|
||||
|
||||
if (abs(k) >= 1)
|
||||
{
|
||||
return policies::raise_domain_error<T>("boost::math::ellint_d<%1%>(%1%)",
|
||||
"Got k = %1%, function requires |k| <= 1", k, pol);
|
||||
}
|
||||
if(fabs(k) <= tools::root_epsilon<T>())
|
||||
return constants::pi<T>() / 4;
|
||||
|
||||
T x = 0;
|
||||
T t = k * k;
|
||||
T y = 1 - t;
|
||||
T z = 1;
|
||||
T value = ellint_rd_imp(x, y, z, pol) / 3;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
template <typename T, typename Policy>
|
||||
inline typename tools::promote_args<T>::type ellint_d(T k, const Policy& pol, const mpl::true_&)
|
||||
{
|
||||
typedef typename tools::promote_args<T>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(detail::ellint_d_imp(static_cast<value_type>(k), pol), "boost::math::ellint_d<%1%>(%1%)");
|
||||
}
|
||||
|
||||
// Elliptic integral (Legendre form) of the second kind
|
||||
template <class T1, class T2>
|
||||
inline typename tools::promote_args<T1, T2>::type ellint_d(T1 k, T2 phi, const mpl::false_&)
|
||||
{
|
||||
return boost::math::ellint_d(k, phi, policies::policy<>());
|
||||
}
|
||||
|
||||
} // detail
|
||||
|
||||
// Complete elliptic integral (Legendre form) of the second kind
|
||||
template <typename T>
|
||||
inline typename tools::promote_args<T>::type ellint_d(T k)
|
||||
{
|
||||
return ellint_d(k, policies::policy<>());
|
||||
}
|
||||
|
||||
// Elliptic integral (Legendre form) of the second kind
|
||||
template <class T1, class T2>
|
||||
inline typename tools::promote_args<T1, T2>::type ellint_d(T1 k, T2 phi)
|
||||
{
|
||||
typedef typename policies::is_policy<T2>::type tag_type;
|
||||
return detail::ellint_d(k, phi, tag_type());
|
||||
}
|
||||
|
||||
template <class T1, class T2, class Policy>
|
||||
inline typename tools::promote_args<T1, T2>::type ellint_d(T1 k, T2 phi, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T1, T2>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(detail::ellint_d_imp(static_cast<value_type>(phi), static_cast<value_type>(k), pol), "boost::math::ellint_2<%1%>(%1%,%1%)");
|
||||
}
|
||||
|
||||
}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_ELLINT_D_HPP
|
||||
|
||||
114
code_isotrope/boost/math/special_functions/ellint_rc.hpp
Executable file
114
code_isotrope/boost/math/special_functions/ellint_rc.hpp
Executable file
@@ -0,0 +1,114 @@
|
||||
// Copyright (c) 2006 Xiaogang Zhang, 2015 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)
|
||||
//
|
||||
// History:
|
||||
// XZ wrote the original of this file as part of the Google
|
||||
// Summer of Code 2006. JM modified it to fit into the
|
||||
// Boost.Math conceptual framework better, and to correctly
|
||||
// handle the y < 0 case.
|
||||
// Updated 2015 to use Carlson's latest methods.
|
||||
//
|
||||
|
||||
#ifndef BOOST_MATH_ELLINT_RC_HPP
|
||||
#define BOOST_MATH_ELLINT_RC_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
#include <boost/math/tools/config.hpp>
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/math/special_functions/log1p.hpp>
|
||||
#include <boost/math/constants/constants.hpp>
|
||||
#include <iostream>
|
||||
|
||||
// Carlson's degenerate elliptic integral
|
||||
// R_C(x, y) = R_F(x, y, y) = 0.5 * \int_{0}^{\infty} (t+x)^{-1/2} (t+y)^{-1} dt
|
||||
// Carlson, Numerische Mathematik, vol 33, 1 (1979)
|
||||
|
||||
namespace boost { namespace math { namespace detail{
|
||||
|
||||
template <typename T, typename Policy>
|
||||
T ellint_rc_imp(T x, T y, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
|
||||
static const char* function = "boost::math::ellint_rc<%1%>(%1%,%1%)";
|
||||
|
||||
if(x < 0)
|
||||
{
|
||||
return policies::raise_domain_error<T>(function,
|
||||
"Argument x must be non-negative but got %1%", x, pol);
|
||||
}
|
||||
if(y == 0)
|
||||
{
|
||||
return policies::raise_domain_error<T>(function,
|
||||
"Argument y must not be zero but got %1%", y, pol);
|
||||
}
|
||||
|
||||
// for y < 0, the integral is singular, return Cauchy principal value
|
||||
T prefix, result;
|
||||
if(y < 0)
|
||||
{
|
||||
prefix = sqrt(x / (x - y));
|
||||
x = x - y;
|
||||
y = -y;
|
||||
}
|
||||
else
|
||||
prefix = 1;
|
||||
|
||||
if(x == 0)
|
||||
{
|
||||
result = constants::half_pi<T>() / sqrt(y);
|
||||
}
|
||||
else if(x == y)
|
||||
{
|
||||
result = 1 / sqrt(x);
|
||||
}
|
||||
else if(y > x)
|
||||
{
|
||||
result = atan(sqrt((y - x) / x)) / sqrt(y - x);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(y / x > 0.5)
|
||||
{
|
||||
T arg = sqrt((x - y) / x);
|
||||
result = (boost::math::log1p(arg) - boost::math::log1p(-arg)) / (2 * sqrt(x - y));
|
||||
}
|
||||
else
|
||||
{
|
||||
result = log((sqrt(x) + sqrt(x - y)) / sqrt(y)) / sqrt(x - y);
|
||||
}
|
||||
}
|
||||
return prefix * result;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class T1, class T2, class Policy>
|
||||
inline typename tools::promote_args<T1, T2>::type
|
||||
ellint_rc(T1 x, T2 y, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T1, T2>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(
|
||||
detail::ellint_rc_imp(
|
||||
static_cast<value_type>(x),
|
||||
static_cast<value_type>(y), pol), "boost::math::ellint_rc<%1%>(%1%,%1%)");
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
inline typename tools::promote_args<T1, T2>::type
|
||||
ellint_rc(T1 x, T2 y)
|
||||
{
|
||||
return ellint_rc(x, y, policies::policy<>());
|
||||
}
|
||||
|
||||
}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_ELLINT_RC_HPP
|
||||
|
||||
206
code_isotrope/boost/math/special_functions/ellint_rd.hpp
Executable file
206
code_isotrope/boost/math/special_functions/ellint_rd.hpp
Executable file
@@ -0,0 +1,206 @@
|
||||
// Copyright (c) 2006 Xiaogang Zhang, 2015 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)
|
||||
//
|
||||
// History:
|
||||
// XZ wrote the original of this file as part of the Google
|
||||
// Summer of Code 2006. JM modified it slightly to fit into the
|
||||
// Boost.Math conceptual framework better.
|
||||
// Updated 2015 to use Carlson's latest methods.
|
||||
|
||||
#ifndef BOOST_MATH_ELLINT_RD_HPP
|
||||
#define BOOST_MATH_ELLINT_RD_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/math/special_functions/ellint_rc.hpp>
|
||||
#include <boost/math/special_functions/pow.hpp>
|
||||
#include <boost/math/tools/config.hpp>
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
|
||||
// Carlson's elliptic integral of the second kind
|
||||
// R_D(x, y, z) = R_J(x, y, z, z) = 1.5 * \int_{0}^{\infty} [(t+x)(t+y)]^{-1/2} (t+z)^{-3/2} dt
|
||||
// Carlson, Numerische Mathematik, vol 33, 1 (1979)
|
||||
|
||||
namespace boost { namespace math { namespace detail{
|
||||
|
||||
template <typename T, typename Policy>
|
||||
T ellint_rd_imp(T x, T y, T z, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
using std::swap;
|
||||
|
||||
static const char* function = "boost::math::ellint_rd<%1%>(%1%,%1%,%1%)";
|
||||
|
||||
if(x < 0)
|
||||
{
|
||||
return policies::raise_domain_error<T>(function,
|
||||
"Argument x must be >= 0, but got %1%", x, pol);
|
||||
}
|
||||
if(y < 0)
|
||||
{
|
||||
return policies::raise_domain_error<T>(function,
|
||||
"Argument y must be >= 0, but got %1%", y, pol);
|
||||
}
|
||||
if(z <= 0)
|
||||
{
|
||||
return policies::raise_domain_error<T>(function,
|
||||
"Argument z must be > 0, but got %1%", z, pol);
|
||||
}
|
||||
if(x + y == 0)
|
||||
{
|
||||
return policies::raise_domain_error<T>(function,
|
||||
"At most one argument can be zero, but got, x + y = %1%", x + y, pol);
|
||||
}
|
||||
//
|
||||
// Special cases from http://dlmf.nist.gov/19.20#iv
|
||||
//
|
||||
using std::swap;
|
||||
if(x == z)
|
||||
swap(x, y);
|
||||
if(y == z)
|
||||
{
|
||||
if(x == y)
|
||||
{
|
||||
return 1 / (x * sqrt(x));
|
||||
}
|
||||
else if(x == 0)
|
||||
{
|
||||
return 3 * constants::pi<T>() / (4 * y * sqrt(y));
|
||||
}
|
||||
else
|
||||
{
|
||||
if((std::min)(x, y) / (std::max)(x, y) > 1.3)
|
||||
return 3 * (ellint_rc_imp(x, y, pol) - sqrt(x) / y) / (2 * (y - x));
|
||||
// Otherwise fall through to avoid cancellation in the above (RC(x,y) -> 1/x^0.5 as x -> y)
|
||||
}
|
||||
}
|
||||
if(x == y)
|
||||
{
|
||||
if((std::min)(x, z) / (std::max)(x, z) > 1.3)
|
||||
return 3 * (ellint_rc_imp(z, x, pol) - 1 / sqrt(z)) / (z - x);
|
||||
// Otherwise fall through to avoid cancellation in the above (RC(x,y) -> 1/x^0.5 as x -> y)
|
||||
}
|
||||
if(y == 0)
|
||||
swap(x, y);
|
||||
if(x == 0)
|
||||
{
|
||||
//
|
||||
// Special handling for common case, from
|
||||
// Numerical Computation of Real or Complex Elliptic Integrals, eq.47
|
||||
//
|
||||
T xn = sqrt(y);
|
||||
T yn = sqrt(z);
|
||||
T x0 = xn;
|
||||
T y0 = yn;
|
||||
T sum = 0;
|
||||
T sum_pow = 0.25f;
|
||||
|
||||
while(fabs(xn - yn) >= 2.7 * tools::root_epsilon<T>() * fabs(xn))
|
||||
{
|
||||
T t = sqrt(xn * yn);
|
||||
xn = (xn + yn) / 2;
|
||||
yn = t;
|
||||
sum_pow *= 2;
|
||||
sum += sum_pow * boost::math::pow<2>(xn - yn);
|
||||
}
|
||||
T RF = constants::pi<T>() / (xn + yn);
|
||||
//
|
||||
// This following calculation suffers from serious cancellation when y ~ z
|
||||
// unless we combine terms. We have:
|
||||
//
|
||||
// ( ((x0 + y0)/2)^2 - z ) / (z(y-z))
|
||||
//
|
||||
// Substituting y = x0^2 and z = y0^2 and simplifying we get the following:
|
||||
//
|
||||
T pt = (x0 + 3 * y0) / (4 * z * (x0 + y0));
|
||||
//
|
||||
// Since we've moved the demoninator from eq.47 inside the expression, we
|
||||
// need to also scale "sum" by the same value:
|
||||
//
|
||||
pt -= sum / (z * (y - z));
|
||||
return pt * RF * 3;
|
||||
}
|
||||
|
||||
T xn = x;
|
||||
T yn = y;
|
||||
T zn = z;
|
||||
T An = (x + y + 3 * z) / 5;
|
||||
T A0 = An;
|
||||
// This has an extra 1.2 fudge factor which is really only needed when x, y and z are close in magnitude:
|
||||
T Q = pow(tools::epsilon<T>() / 4, -T(1) / 8) * (std::max)((std::max)(An - x, An - y), An - z) * 1.2f;
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(Q);
|
||||
T lambda, rx, ry, rz;
|
||||
unsigned k = 0;
|
||||
T fn = 1;
|
||||
T RD_sum = 0;
|
||||
|
||||
for(; k < policies::get_max_series_iterations<Policy>(); ++k)
|
||||
{
|
||||
rx = sqrt(xn);
|
||||
ry = sqrt(yn);
|
||||
rz = sqrt(zn);
|
||||
lambda = rx * ry + rx * rz + ry * rz;
|
||||
RD_sum += fn / (rz * (zn + lambda));
|
||||
An = (An + lambda) / 4;
|
||||
xn = (xn + lambda) / 4;
|
||||
yn = (yn + lambda) / 4;
|
||||
zn = (zn + lambda) / 4;
|
||||
fn /= 4;
|
||||
Q /= 4;
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(k);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(RD_sum);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(Q);
|
||||
if(Q < An)
|
||||
break;
|
||||
}
|
||||
|
||||
policies::check_series_iterations<T, Policy>(function, k, pol);
|
||||
|
||||
T X = fn * (A0 - x) / An;
|
||||
T Y = fn * (A0 - y) / An;
|
||||
T Z = -(X + Y) / 3;
|
||||
T E2 = X * Y - 6 * Z * Z;
|
||||
T E3 = (3 * X * Y - 8 * Z * Z) * Z;
|
||||
T E4 = 3 * (X * Y - Z * Z) * Z * Z;
|
||||
T E5 = X * Y * Z * Z * Z;
|
||||
|
||||
T result = fn * pow(An, T(-3) / 2) *
|
||||
(1 - 3 * E2 / 14 + E3 / 6 + 9 * E2 * E2 / 88 - 3 * E4 / 22 - 9 * E2 * E3 / 52 + 3 * E5 / 26 - E2 * E2 * E2 / 16
|
||||
+ 3 * E3 * E3 / 40 + 3 * E2 * E4 / 20 + 45 * E2 * E2 * E3 / 272 - 9 * (E3 * E4 + E2 * E5) / 68);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(result);
|
||||
result += 3 * RD_sum;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class T1, class T2, class T3, class Policy>
|
||||
inline typename tools::promote_args<T1, T2, T3>::type
|
||||
ellint_rd(T1 x, T2 y, T3 z, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T1, T2, T3>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(
|
||||
detail::ellint_rd_imp(
|
||||
static_cast<value_type>(x),
|
||||
static_cast<value_type>(y),
|
||||
static_cast<value_type>(z), pol), "boost::math::ellint_rd<%1%>(%1%,%1%,%1%)");
|
||||
}
|
||||
|
||||
template <class T1, class T2, class T3>
|
||||
inline typename tools::promote_args<T1, T2, T3>::type
|
||||
ellint_rd(T1 x, T2 y, T3 z)
|
||||
{
|
||||
return ellint_rd(x, y, z, policies::policy<>());
|
||||
}
|
||||
|
||||
}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_ELLINT_RD_HPP
|
||||
|
||||
174
code_isotrope/boost/math/special_functions/ellint_rf.hpp
Executable file
174
code_isotrope/boost/math/special_functions/ellint_rf.hpp
Executable file
@@ -0,0 +1,174 @@
|
||||
// Copyright (c) 2006 Xiaogang Zhang, 2015 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)
|
||||
//
|
||||
// History:
|
||||
// XZ wrote the original of this file as part of the Google
|
||||
// Summer of Code 2006. JM modified it to fit into the
|
||||
// Boost.Math conceptual framework better, and to handle
|
||||
// types longer than 80-bit reals.
|
||||
// Updated 2015 to use Carlson's latest methods.
|
||||
//
|
||||
#ifndef BOOST_MATH_ELLINT_RF_HPP
|
||||
#define BOOST_MATH_ELLINT_RF_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/math/tools/config.hpp>
|
||||
#include <boost/math/constants/constants.hpp>
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
#include <boost/math/special_functions/ellint_rc.hpp>
|
||||
|
||||
// Carlson's elliptic integral of the first kind
|
||||
// R_F(x, y, z) = 0.5 * \int_{0}^{\infty} [(t+x)(t+y)(t+z)]^{-1/2} dt
|
||||
// Carlson, Numerische Mathematik, vol 33, 1 (1979)
|
||||
|
||||
namespace boost { namespace math { namespace detail{
|
||||
|
||||
template <typename T, typename Policy>
|
||||
T ellint_rf_imp(T x, T y, T z, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
using namespace boost::math;
|
||||
using std::swap;
|
||||
|
||||
static const char* function = "boost::math::ellint_rf<%1%>(%1%,%1%,%1%)";
|
||||
|
||||
if(x < 0 || y < 0 || z < 0)
|
||||
{
|
||||
return policies::raise_domain_error<T>(function,
|
||||
"domain error, all arguments must be non-negative, "
|
||||
"only sensible result is %1%.",
|
||||
std::numeric_limits<T>::quiet_NaN(), pol);
|
||||
}
|
||||
if(x + y == 0 || y + z == 0 || z + x == 0)
|
||||
{
|
||||
return policies::raise_domain_error<T>(function,
|
||||
"domain error, at most one argument can be zero, "
|
||||
"only sensible result is %1%.",
|
||||
std::numeric_limits<T>::quiet_NaN(), pol);
|
||||
}
|
||||
//
|
||||
// Special cases from http://dlmf.nist.gov/19.20#i
|
||||
//
|
||||
if(x == y)
|
||||
{
|
||||
if(x == z)
|
||||
{
|
||||
// x, y, z equal:
|
||||
return 1 / sqrt(x);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 2 equal, x and y:
|
||||
if(z == 0)
|
||||
return constants::pi<T>() / (2 * sqrt(x));
|
||||
else
|
||||
return ellint_rc_imp(z, x, pol);
|
||||
}
|
||||
}
|
||||
if(x == z)
|
||||
{
|
||||
if(y == 0)
|
||||
return constants::pi<T>() / (2 * sqrt(x));
|
||||
else
|
||||
return ellint_rc_imp(y, x, pol);
|
||||
}
|
||||
if(y == z)
|
||||
{
|
||||
if(x == 0)
|
||||
return constants::pi<T>() / (2 * sqrt(y));
|
||||
else
|
||||
return ellint_rc_imp(x, y, pol);
|
||||
}
|
||||
if(x == 0)
|
||||
swap(x, z);
|
||||
else if(y == 0)
|
||||
swap(y, z);
|
||||
if(z == 0)
|
||||
{
|
||||
//
|
||||
// Special case for one value zero:
|
||||
//
|
||||
T xn = sqrt(x);
|
||||
T yn = sqrt(y);
|
||||
|
||||
while(fabs(xn - yn) >= 2.7 * tools::root_epsilon<T>() * fabs(xn))
|
||||
{
|
||||
T t = sqrt(xn * yn);
|
||||
xn = (xn + yn) / 2;
|
||||
yn = t;
|
||||
}
|
||||
return constants::pi<T>() / (xn + yn);
|
||||
}
|
||||
|
||||
T xn = x;
|
||||
T yn = y;
|
||||
T zn = z;
|
||||
T An = (x + y + z) / 3;
|
||||
T A0 = An;
|
||||
T Q = pow(3 * boost::math::tools::epsilon<T>(), T(-1) / 8) * (std::max)((std::max)(fabs(An - xn), fabs(An - yn)), fabs(An - zn));
|
||||
T fn = 1;
|
||||
|
||||
|
||||
// duplication
|
||||
unsigned k = 1;
|
||||
for(; k < boost::math::policies::get_max_series_iterations<Policy>(); ++k)
|
||||
{
|
||||
T root_x = sqrt(xn);
|
||||
T root_y = sqrt(yn);
|
||||
T root_z = sqrt(zn);
|
||||
T lambda = root_x * root_y + root_x * root_z + root_y * root_z;
|
||||
An = (An + lambda) / 4;
|
||||
xn = (xn + lambda) / 4;
|
||||
yn = (yn + lambda) / 4;
|
||||
zn = (zn + lambda) / 4;
|
||||
Q /= 4;
|
||||
fn *= 4;
|
||||
if(Q < fabs(An))
|
||||
break;
|
||||
}
|
||||
// Check to see if we gave up too soon:
|
||||
policies::check_series_iterations<T>(function, k, pol);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(k);
|
||||
|
||||
T X = (A0 - x) / (An * fn);
|
||||
T Y = (A0 - y) / (An * fn);
|
||||
T Z = -X - Y;
|
||||
|
||||
// Taylor series expansion to the 7th order
|
||||
T E2 = X * Y - Z * Z;
|
||||
T E3 = X * Y * Z;
|
||||
return (1 + E3 * (T(1) / 14 + 3 * E3 / 104) + E2 * (T(-1) / 10 + E2 / 24 - (3 * E3) / 44 - 5 * E2 * E2 / 208 + E2 * E3 / 16)) / sqrt(An);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class T1, class T2, class T3, class Policy>
|
||||
inline typename tools::promote_args<T1, T2, T3>::type
|
||||
ellint_rf(T1 x, T2 y, T3 z, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T1, T2, T3>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(
|
||||
detail::ellint_rf_imp(
|
||||
static_cast<value_type>(x),
|
||||
static_cast<value_type>(y),
|
||||
static_cast<value_type>(z), pol), "boost::math::ellint_rf<%1%>(%1%,%1%,%1%)");
|
||||
}
|
||||
|
||||
template <class T1, class T2, class T3>
|
||||
inline typename tools::promote_args<T1, T2, T3>::type
|
||||
ellint_rf(T1 x, T2 y, T3 z)
|
||||
{
|
||||
return ellint_rf(x, y, z, policies::policy<>());
|
||||
}
|
||||
|
||||
}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_ELLINT_RF_HPP
|
||||
|
||||
136
code_isotrope/boost/math/special_functions/ellint_rg.hpp
Executable file
136
code_isotrope/boost/math/special_functions/ellint_rg.hpp
Executable file
@@ -0,0 +1,136 @@
|
||||
// Copyright (c) 2015 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_ELLINT_RG_HPP
|
||||
#define BOOST_MATH_ELLINT_RG_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/math/tools/config.hpp>
|
||||
#include <boost/math/constants/constants.hpp>
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
#include <boost/math/special_functions/ellint_rd.hpp>
|
||||
#include <boost/math/special_functions/ellint_rf.hpp>
|
||||
#include <boost/math/special_functions/pow.hpp>
|
||||
|
||||
namespace boost { namespace math { namespace detail{
|
||||
|
||||
template <typename T, typename Policy>
|
||||
T ellint_rg_imp(T x, T y, T z, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
static const char* function = "boost::math::ellint_rf<%1%>(%1%,%1%,%1%)";
|
||||
|
||||
if(x < 0 || y < 0 || z < 0)
|
||||
{
|
||||
return policies::raise_domain_error<T>(function,
|
||||
"domain error, all arguments must be non-negative, "
|
||||
"only sensible result is %1%.",
|
||||
std::numeric_limits<T>::quiet_NaN(), pol);
|
||||
}
|
||||
//
|
||||
// Function is symmetric in x, y and z, but we require
|
||||
// (x - z)(y - z) >= 0 to avoid cancellation error in the result
|
||||
// which implies (for example) x >= z >= y
|
||||
//
|
||||
using std::swap;
|
||||
if(x < y)
|
||||
swap(x, y);
|
||||
if(x < z)
|
||||
swap(x, z);
|
||||
if(y > z)
|
||||
swap(y, z);
|
||||
|
||||
BOOST_ASSERT(x >= z);
|
||||
BOOST_ASSERT(z >= y);
|
||||
//
|
||||
// Special cases from http://dlmf.nist.gov/19.20#ii
|
||||
//
|
||||
if(x == z)
|
||||
{
|
||||
if(y == z)
|
||||
{
|
||||
// x = y = z
|
||||
// This also works for x = y = z = 0 presumably.
|
||||
return sqrt(x);
|
||||
}
|
||||
else if(y == 0)
|
||||
{
|
||||
// x = y, z = 0
|
||||
return constants::pi<T>() * sqrt(x) / 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
// x = z, y != 0
|
||||
swap(x, y);
|
||||
return (x == 0) ? T(sqrt(z) / 2) : T((z * ellint_rc_imp(x, z, pol) + sqrt(x)) / 2);
|
||||
}
|
||||
}
|
||||
else if(y == z)
|
||||
{
|
||||
if(x == 0)
|
||||
return constants::pi<T>() * sqrt(y) / 4;
|
||||
else
|
||||
return (y == 0) ? T(sqrt(x) / 2) : T((y * ellint_rc_imp(x, y, pol) + sqrt(x)) / 2);
|
||||
}
|
||||
else if(y == 0)
|
||||
{
|
||||
swap(y, z);
|
||||
//
|
||||
// Special handling for common case, from
|
||||
// Numerical Computation of Real or Complex Elliptic Integrals, eq.46
|
||||
//
|
||||
T xn = sqrt(x);
|
||||
T yn = sqrt(y);
|
||||
T x0 = xn;
|
||||
T y0 = yn;
|
||||
T sum = 0;
|
||||
T sum_pow = 0.25f;
|
||||
|
||||
while(fabs(xn - yn) >= 2.7 * tools::root_epsilon<T>() * fabs(xn))
|
||||
{
|
||||
T t = sqrt(xn * yn);
|
||||
xn = (xn + yn) / 2;
|
||||
yn = t;
|
||||
sum_pow *= 2;
|
||||
sum += sum_pow * boost::math::pow<2>(xn - yn);
|
||||
}
|
||||
T RF = constants::pi<T>() / (xn + yn);
|
||||
return ((boost::math::pow<2>((x0 + y0) / 2) - sum) * RF) / 2;
|
||||
}
|
||||
return (z * ellint_rf_imp(x, y, z, pol)
|
||||
- (x - z) * (y - z) * ellint_rd_imp(x, y, z, pol) / 3
|
||||
+ sqrt(x * y / z)) / 2;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class T1, class T2, class T3, class Policy>
|
||||
inline typename tools::promote_args<T1, T2, T3>::type
|
||||
ellint_rg(T1 x, T2 y, T3 z, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T1, T2, T3>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(
|
||||
detail::ellint_rg_imp(
|
||||
static_cast<value_type>(x),
|
||||
static_cast<value_type>(y),
|
||||
static_cast<value_type>(z), pol), "boost::math::ellint_rf<%1%>(%1%,%1%,%1%)");
|
||||
}
|
||||
|
||||
template <class T1, class T2, class T3>
|
||||
inline typename tools::promote_args<T1, T2, T3>::type
|
||||
ellint_rg(T1 x, T2 y, T3 z)
|
||||
{
|
||||
return ellint_rg(x, y, z, policies::policy<>());
|
||||
}
|
||||
|
||||
}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_ELLINT_RG_HPP
|
||||
|
||||
302
code_isotrope/boost/math/special_functions/ellint_rj.hpp
Executable file
302
code_isotrope/boost/math/special_functions/ellint_rj.hpp
Executable file
@@ -0,0 +1,302 @@
|
||||
// Copyright (c) 2006 Xiaogang Zhang, 2015 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)
|
||||
//
|
||||
// History:
|
||||
// XZ wrote the original of this file as part of the Google
|
||||
// Summer of Code 2006. JM modified it to fit into the
|
||||
// Boost.Math conceptual framework better, and to correctly
|
||||
// handle the p < 0 case.
|
||||
// Updated 2015 to use Carlson's latest methods.
|
||||
//
|
||||
|
||||
#ifndef BOOST_MATH_ELLINT_RJ_HPP
|
||||
#define BOOST_MATH_ELLINT_RJ_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/math/tools/config.hpp>
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
#include <boost/math/special_functions/ellint_rc.hpp>
|
||||
#include <boost/math/special_functions/ellint_rf.hpp>
|
||||
#include <boost/math/special_functions/ellint_rd.hpp>
|
||||
|
||||
// Carlson's elliptic integral of the third kind
|
||||
// R_J(x, y, z, p) = 1.5 * \int_{0}^{\infty} (t+p)^{-1} [(t+x)(t+y)(t+z)]^{-1/2} dt
|
||||
// Carlson, Numerische Mathematik, vol 33, 1 (1979)
|
||||
|
||||
namespace boost { namespace math { namespace detail{
|
||||
|
||||
template <typename T, typename Policy>
|
||||
T ellint_rc1p_imp(T y, const Policy& pol)
|
||||
{
|
||||
using namespace boost::math;
|
||||
// Calculate RC(1, 1 + x)
|
||||
BOOST_MATH_STD_USING
|
||||
|
||||
static const char* function = "boost::math::ellint_rc<%1%>(%1%,%1%)";
|
||||
|
||||
if(y == -1)
|
||||
{
|
||||
return policies::raise_domain_error<T>(function,
|
||||
"Argument y must not be zero but got %1%", y, pol);
|
||||
}
|
||||
|
||||
// for 1 + y < 0, the integral is singular, return Cauchy principal value
|
||||
T result;
|
||||
if(y < -1)
|
||||
{
|
||||
result = sqrt(1 / -y) * detail::ellint_rc_imp(T(-y), T(-1 - y), pol);
|
||||
}
|
||||
else if(y == 0)
|
||||
{
|
||||
result = 1;
|
||||
}
|
||||
else if(y > 0)
|
||||
{
|
||||
result = atan(sqrt(y)) / sqrt(y);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(y > -0.5)
|
||||
{
|
||||
T arg = sqrt(-y);
|
||||
result = (boost::math::log1p(arg) - boost::math::log1p(-arg)) / (2 * sqrt(-y));
|
||||
}
|
||||
else
|
||||
{
|
||||
result = log((1 + sqrt(-y)) / sqrt(1 + y)) / sqrt(-y);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T, typename Policy>
|
||||
T ellint_rj_imp(T x, T y, T z, T p, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
|
||||
static const char* function = "boost::math::ellint_rj<%1%>(%1%,%1%,%1%)";
|
||||
|
||||
if(x < 0)
|
||||
{
|
||||
return policies::raise_domain_error<T>(function,
|
||||
"Argument x must be non-negative, but got x = %1%", x, pol);
|
||||
}
|
||||
if(y < 0)
|
||||
{
|
||||
return policies::raise_domain_error<T>(function,
|
||||
"Argument y must be non-negative, but got y = %1%", y, pol);
|
||||
}
|
||||
if(z < 0)
|
||||
{
|
||||
return policies::raise_domain_error<T>(function,
|
||||
"Argument z must be non-negative, but got z = %1%", z, pol);
|
||||
}
|
||||
if(p == 0)
|
||||
{
|
||||
return policies::raise_domain_error<T>(function,
|
||||
"Argument p must not be zero, but got p = %1%", p, pol);
|
||||
}
|
||||
if(x + y == 0 || y + z == 0 || z + x == 0)
|
||||
{
|
||||
return policies::raise_domain_error<T>(function,
|
||||
"At most one argument can be zero, "
|
||||
"only possible result is %1%.", std::numeric_limits<T>::quiet_NaN(), pol);
|
||||
}
|
||||
|
||||
// for p < 0, the integral is singular, return Cauchy principal value
|
||||
if(p < 0)
|
||||
{
|
||||
//
|
||||
// We must ensure that x < y < z.
|
||||
// Since the integral is symmetrical in x, y and z
|
||||
// we can just permute the values:
|
||||
//
|
||||
if(x > y)
|
||||
std::swap(x, y);
|
||||
if(y > z)
|
||||
std::swap(y, z);
|
||||
if(x > y)
|
||||
std::swap(x, y);
|
||||
|
||||
BOOST_ASSERT(x <= y);
|
||||
BOOST_ASSERT(y <= z);
|
||||
|
||||
T q = -p;
|
||||
p = (z * (x + y + q) - x * y) / (z + q);
|
||||
|
||||
BOOST_ASSERT(p >= 0);
|
||||
|
||||
T value = (p - z) * ellint_rj_imp(x, y, z, p, pol);
|
||||
value -= 3 * ellint_rf_imp(x, y, z, pol);
|
||||
value += 3 * sqrt((x * y * z) / (x * y + p * q)) * ellint_rc_imp(T(x * y + p * q), T(p * q), pol);
|
||||
value /= (z + q);
|
||||
return value;
|
||||
}
|
||||
|
||||
//
|
||||
// Special cases from http://dlmf.nist.gov/19.20#iii
|
||||
//
|
||||
if(x == y)
|
||||
{
|
||||
if(x == z)
|
||||
{
|
||||
if(x == p)
|
||||
{
|
||||
// All values equal:
|
||||
return 1 / (x * sqrt(x));
|
||||
}
|
||||
else
|
||||
{
|
||||
// x = y = z:
|
||||
return 3 * (ellint_rc_imp(x, p, pol) - 1 / sqrt(x)) / (x - p);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// x = y only, permute so y = z:
|
||||
using std::swap;
|
||||
swap(x, z);
|
||||
if(y == p)
|
||||
{
|
||||
return ellint_rd_imp(x, y, y, pol);
|
||||
}
|
||||
else if((std::max)(y, p) / (std::min)(y, p) > 1.2)
|
||||
{
|
||||
return 3 * (ellint_rc_imp(x, y, pol) - ellint_rc_imp(x, p, pol)) / (p - y);
|
||||
}
|
||||
// Otherwise fall through to normal method, special case above will suffer too much cancellation...
|
||||
}
|
||||
}
|
||||
if(y == z)
|
||||
{
|
||||
if(y == p)
|
||||
{
|
||||
// y = z = p:
|
||||
return ellint_rd_imp(x, y, y, pol);
|
||||
}
|
||||
else if((std::max)(y, p) / (std::min)(y, p) > 1.2)
|
||||
{
|
||||
// y = z:
|
||||
return 3 * (ellint_rc_imp(x, y, pol) - ellint_rc_imp(x, p, pol)) / (p - y);
|
||||
}
|
||||
// Otherwise fall through to normal method, special case above will suffer too much cancellation...
|
||||
}
|
||||
if(z == p)
|
||||
{
|
||||
return ellint_rd_imp(x, y, z, pol);
|
||||
}
|
||||
|
||||
T xn = x;
|
||||
T yn = y;
|
||||
T zn = z;
|
||||
T pn = p;
|
||||
T An = (x + y + z + 2 * p) / 5;
|
||||
T A0 = An;
|
||||
T delta = (p - x) * (p - y) * (p - z);
|
||||
T Q = pow(tools::epsilon<T>() / 5, -T(1) / 8) * (std::max)((std::max)(fabs(An - x), fabs(An - y)), (std::max)(fabs(An - z), fabs(An - p)));
|
||||
|
||||
unsigned n;
|
||||
T lambda;
|
||||
T Dn;
|
||||
T En;
|
||||
T rx, ry, rz, rp;
|
||||
T fmn = 1; // 4^-n
|
||||
T RC_sum = 0;
|
||||
|
||||
for(n = 0; n < policies::get_max_series_iterations<Policy>(); ++n)
|
||||
{
|
||||
rx = sqrt(xn);
|
||||
ry = sqrt(yn);
|
||||
rz = sqrt(zn);
|
||||
rp = sqrt(pn);
|
||||
Dn = (rp + rx) * (rp + ry) * (rp + rz);
|
||||
En = delta / Dn;
|
||||
En /= Dn;
|
||||
if((En < -0.5) && (En > -1.5))
|
||||
{
|
||||
//
|
||||
// Occationally En ~ -1, we then have no means of calculating
|
||||
// RC(1, 1+En) without terrible cancellation error, so we
|
||||
// need to get to 1+En directly. By substitution we have
|
||||
//
|
||||
// 1+E_0 = 1 + (p-x)*(p-y)*(p-z)/((sqrt(p) + sqrt(x))*(sqrt(p)+sqrt(y))*(sqrt(p)+sqrt(z)))^2
|
||||
// = 2*sqrt(p)*(p+sqrt(x) * (sqrt(y)+sqrt(z)) + sqrt(y)*sqrt(z)) / ((sqrt(p) + sqrt(x))*(sqrt(p) + sqrt(y)*(sqrt(p)+sqrt(z))))
|
||||
//
|
||||
// And since this is just an application of the duplication formula for RJ, the same
|
||||
// expression works for 1+En if we use x,y,z,p_n etc.
|
||||
// This branch is taken only once or twice at the start of iteration,
|
||||
// after than En reverts to it's usual very small values.
|
||||
//
|
||||
T b = 2 * rp * (pn + rx * (ry + rz) + ry * rz) / Dn;
|
||||
RC_sum += fmn / Dn * detail::ellint_rc_imp(T(1), b, pol);
|
||||
}
|
||||
else
|
||||
{
|
||||
RC_sum += fmn / Dn * ellint_rc1p_imp(En, pol);
|
||||
}
|
||||
lambda = rx * ry + rx * rz + ry * rz;
|
||||
|
||||
// From here on we move to n+1:
|
||||
An = (An + lambda) / 4;
|
||||
fmn /= 4;
|
||||
|
||||
if(fmn * Q < An)
|
||||
break;
|
||||
|
||||
xn = (xn + lambda) / 4;
|
||||
yn = (yn + lambda) / 4;
|
||||
zn = (zn + lambda) / 4;
|
||||
pn = (pn + lambda) / 4;
|
||||
delta /= 64;
|
||||
}
|
||||
|
||||
T X = fmn * (A0 - x) / An;
|
||||
T Y = fmn * (A0 - y) / An;
|
||||
T Z = fmn * (A0 - z) / An;
|
||||
T P = (-X - Y - Z) / 2;
|
||||
T E2 = X * Y + X * Z + Y * Z - 3 * P * P;
|
||||
T E3 = X * Y * Z + 2 * E2 * P + 4 * P * P * P;
|
||||
T E4 = (2 * X * Y * Z + E2 * P + 3 * P * P * P) * P;
|
||||
T E5 = X * Y * Z * P * P;
|
||||
T result = fmn * pow(An, T(-3) / 2) *
|
||||
(1 - 3 * E2 / 14 + E3 / 6 + 9 * E2 * E2 / 88 - 3 * E4 / 22 - 9 * E2 * E3 / 52 + 3 * E5 / 26 - E2 * E2 * E2 / 16
|
||||
+ 3 * E3 * E3 / 40 + 3 * E2 * E4 / 20 + 45 * E2 * E2 * E3 / 272 - 9 * (E3 * E4 + E2 * E5) / 68);
|
||||
|
||||
result += 6 * RC_sum;
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class Policy>
|
||||
inline typename tools::promote_args<T1, T2, T3, T4>::type
|
||||
ellint_rj(T1 x, T2 y, T3 z, T4 p, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T1, T2, T3, T4>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(
|
||||
detail::ellint_rj_imp(
|
||||
static_cast<value_type>(x),
|
||||
static_cast<value_type>(y),
|
||||
static_cast<value_type>(z),
|
||||
static_cast<value_type>(p),
|
||||
pol), "boost::math::ellint_rj<%1%>(%1%,%1%,%1%,%1%)");
|
||||
}
|
||||
|
||||
template <class T1, class T2, class T3, class T4>
|
||||
inline typename tools::promote_args<T1, T2, T3, T4>::type
|
||||
ellint_rj(T1 x, T2 y, T3 z, T4 p)
|
||||
{
|
||||
return ellint_rj(x, y, z, p, policies::policy<>());
|
||||
}
|
||||
|
||||
}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_ELLINT_RJ_HPP
|
||||
|
||||
1276
code_isotrope/boost/math/special_functions/erf.hpp
Executable file
1276
code_isotrope/boost/math/special_functions/erf.hpp
Executable file
File diff suppressed because it is too large
Load Diff
1678
code_isotrope/boost/math/special_functions/expint.hpp
Executable file
1678
code_isotrope/boost/math/special_functions/expint.hpp
Executable file
File diff suppressed because it is too large
Load Diff
347
code_isotrope/boost/math/special_functions/expm1.hpp
Executable file
347
code_isotrope/boost/math/special_functions/expm1.hpp
Executable file
@@ -0,0 +1,347 @@
|
||||
// (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_EXPM1_INCLUDED
|
||||
#define BOOST_MATH_EXPM1_INCLUDED
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/config/no_tr1/cmath.hpp>
|
||||
#include <math.h> // platform's ::expm1
|
||||
#include <boost/limits.hpp>
|
||||
#include <boost/math/tools/config.hpp>
|
||||
#include <boost/math/tools/series.hpp>
|
||||
#include <boost/math/tools/precision.hpp>
|
||||
#include <boost/math/tools/big_constant.hpp>
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
#include <boost/math/tools/rational.hpp>
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/mpl/less_equal.hpp>
|
||||
|
||||
#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
|
||||
# include <boost/static_assert.hpp>
|
||||
#else
|
||||
# include <boost/assert.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost{ namespace math{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
// Functor expm1_series returns the next term in the Taylor series
|
||||
// x^k / k!
|
||||
// each time that operator() is invoked.
|
||||
//
|
||||
template <class T>
|
||||
struct expm1_series
|
||||
{
|
||||
typedef T result_type;
|
||||
|
||||
expm1_series(T x)
|
||||
: k(0), m_x(x), m_term(1) {}
|
||||
|
||||
T operator()()
|
||||
{
|
||||
++k;
|
||||
m_term *= m_x;
|
||||
m_term /= k;
|
||||
return m_term;
|
||||
}
|
||||
|
||||
int count()const
|
||||
{
|
||||
return k;
|
||||
}
|
||||
|
||||
private:
|
||||
int k;
|
||||
const T m_x;
|
||||
T m_term;
|
||||
expm1_series(const expm1_series&);
|
||||
expm1_series& operator=(const expm1_series&);
|
||||
};
|
||||
|
||||
template <class T, class Policy, class tag>
|
||||
struct expm1_initializer
|
||||
{
|
||||
struct init
|
||||
{
|
||||
init()
|
||||
{
|
||||
do_init(tag());
|
||||
}
|
||||
template <int N>
|
||||
static void do_init(const mpl::int_<N>&){}
|
||||
static void do_init(const mpl::int_<64>&)
|
||||
{
|
||||
expm1(T(0.5));
|
||||
}
|
||||
static void do_init(const mpl::int_<113>&)
|
||||
{
|
||||
expm1(T(0.5));
|
||||
}
|
||||
void force_instantiate()const{}
|
||||
};
|
||||
static const init initializer;
|
||||
static void force_instantiate()
|
||||
{
|
||||
initializer.force_instantiate();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class Policy, class tag>
|
||||
const typename expm1_initializer<T, Policy, tag>::init expm1_initializer<T, Policy, tag>::initializer;
|
||||
|
||||
//
|
||||
// Algorithm expm1 is part of C99, but is not yet provided by many compilers.
|
||||
//
|
||||
// This version uses a Taylor series expansion for 0.5 > |x| > epsilon.
|
||||
//
|
||||
template <class T, class Policy>
|
||||
T expm1_imp(T x, const mpl::int_<0>&, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
|
||||
T a = fabs(x);
|
||||
if((boost::math::isnan)(a))
|
||||
{
|
||||
return policies::raise_domain_error<T>("boost::math::expm1<%1%>(%1%)", "expm1 requires a finite argument, but got %1%", a, pol);
|
||||
}
|
||||
if(a > T(0.5f))
|
||||
{
|
||||
if(a >= tools::log_max_value<T>())
|
||||
{
|
||||
if(x > 0)
|
||||
return policies::raise_overflow_error<T>("boost::math::expm1<%1%>(%1%)", 0, pol);
|
||||
return -1;
|
||||
}
|
||||
return exp(x) - T(1);
|
||||
}
|
||||
if(a < tools::epsilon<T>())
|
||||
return x;
|
||||
detail::expm1_series<T> s(x);
|
||||
boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) && !BOOST_WORKAROUND(__EDG_VERSION__, <= 245)
|
||||
T result = tools::sum_series(s, policies::get_epsilon<T, Policy>(), max_iter);
|
||||
#else
|
||||
T zero = 0;
|
||||
T result = tools::sum_series(s, policies::get_epsilon<T, Policy>(), max_iter, zero);
|
||||
#endif
|
||||
policies::check_series_iterations<T>("boost::math::expm1<%1%>(%1%)", max_iter, pol);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T, class P>
|
||||
T expm1_imp(T x, const mpl::int_<53>&, const P& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
|
||||
T a = fabs(x);
|
||||
if(a > T(0.5L))
|
||||
{
|
||||
if(a >= tools::log_max_value<T>())
|
||||
{
|
||||
if(x > 0)
|
||||
return policies::raise_overflow_error<T>("boost::math::expm1<%1%>(%1%)", 0, pol);
|
||||
return -1;
|
||||
}
|
||||
return exp(x) - T(1);
|
||||
}
|
||||
if(a < tools::epsilon<T>())
|
||||
return x;
|
||||
|
||||
static const float Y = 0.10281276702880859e1f;
|
||||
static const T n[] = { static_cast<T>(-0.28127670288085937e-1), static_cast<T>(0.51278186299064534e0), static_cast<T>(-0.6310029069350198e-1), static_cast<T>(0.11638457975729296e-1), static_cast<T>(-0.52143390687521003e-3), static_cast<T>(0.21491399776965688e-4) };
|
||||
static const T d[] = { 1, static_cast<T>(-0.45442309511354755e0), static_cast<T>(0.90850389570911714e-1), static_cast<T>(-0.10088963629815502e-1), static_cast<T>(0.63003407478692265e-3), static_cast<T>(-0.17976570003654402e-4) };
|
||||
|
||||
T result = x * Y + x * tools::evaluate_polynomial(n, x) / tools::evaluate_polynomial(d, x);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T, class P>
|
||||
T expm1_imp(T x, const mpl::int_<64>&, const P& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
|
||||
T a = fabs(x);
|
||||
if(a > T(0.5L))
|
||||
{
|
||||
if(a >= tools::log_max_value<T>())
|
||||
{
|
||||
if(x > 0)
|
||||
return policies::raise_overflow_error<T>("boost::math::expm1<%1%>(%1%)", 0, pol);
|
||||
return -1;
|
||||
}
|
||||
return exp(x) - T(1);
|
||||
}
|
||||
if(a < tools::epsilon<T>())
|
||||
return x;
|
||||
|
||||
static const float Y = 0.10281276702880859375e1f;
|
||||
static const T n[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.281276702880859375e-1),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.512980290285154286358e0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.667758794592881019644e-1),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.131432469658444745835e-1),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.72303795326880286965e-3),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.447441185192951335042e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.714539134024984593011e-6)
|
||||
};
|
||||
static const T d[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.461477618025562520389e0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.961237488025708540713e-1),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.116483957658204450739e-1),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.873308008461557544458e-3),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.387922804997682392562e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.807473180049193557294e-6)
|
||||
};
|
||||
|
||||
T result = x * Y + x * tools::evaluate_polynomial(n, x) / tools::evaluate_polynomial(d, x);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T, class P>
|
||||
T expm1_imp(T x, const mpl::int_<113>&, const P& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
|
||||
T a = fabs(x);
|
||||
if(a > T(0.5L))
|
||||
{
|
||||
if(a >= tools::log_max_value<T>())
|
||||
{
|
||||
if(x > 0)
|
||||
return policies::raise_overflow_error<T>("boost::math::expm1<%1%>(%1%)", 0, pol);
|
||||
return -1;
|
||||
}
|
||||
return exp(x) - T(1);
|
||||
}
|
||||
if(a < tools::epsilon<T>())
|
||||
return x;
|
||||
|
||||
static const float Y = 0.10281276702880859375e1f;
|
||||
static const T n[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.28127670288085937499999999999999999854e-1),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.51278156911210477556524452177540792214e0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.63263178520747096729500254678819588223e-1),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.14703285606874250425508446801230572252e-1),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.8675686051689527802425310407898459386e-3),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.88126359618291165384647080266133492399e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.25963087867706310844432390015463138953e-5),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.14226691087800461778631773363204081194e-6),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.15995603306536496772374181066765665596e-8),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.45261820069007790520447958280473183582e-10)
|
||||
};
|
||||
static const T d[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.45441264709074310514348137469214538853e0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.96827131936192217313133611655555298106e-1),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.12745248725908178612540554584374876219e-1),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.11473613871583259821612766907781095472e-2),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.73704168477258911962046591907690764416e-4),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.34087499397791555759285503797256103259e-5),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.11114024704296196166272091230695179724e-6),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.23987051614110848595909588343223896577e-8),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.29477341859111589208776402638429026517e-10),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.13222065991022301420255904060628100924e-12)
|
||||
};
|
||||
|
||||
T result = x * Y + x * tools::evaluate_polynomial(n, x) / tools::evaluate_polynomial(d, x);
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class T, class Policy>
|
||||
inline typename tools::promote_args<T>::type expm1(T x, const Policy& /* pol */)
|
||||
{
|
||||
typedef typename tools::promote_args<T>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
typedef typename policies::precision<result_type, Policy>::type precision_type;
|
||||
typedef typename policies::normalise<
|
||||
Policy,
|
||||
policies::promote_float<false>,
|
||||
policies::promote_double<false>,
|
||||
policies::discrete_quantile<>,
|
||||
policies::assert_undefined<> >::type forwarding_policy;
|
||||
|
||||
typedef typename mpl::if_c<
|
||||
::std::numeric_limits<result_type>::is_specialized == 0,
|
||||
mpl::int_<0>, // no numeric_limits, use generic solution
|
||||
typename mpl::if_<
|
||||
typename mpl::less_equal<precision_type, mpl::int_<53> >::type,
|
||||
mpl::int_<53>, // double
|
||||
typename mpl::if_<
|
||||
typename mpl::less_equal<precision_type, mpl::int_<64> >::type,
|
||||
mpl::int_<64>, // 80-bit long double
|
||||
typename mpl::if_<
|
||||
typename mpl::less_equal<precision_type, mpl::int_<113> >::type,
|
||||
mpl::int_<113>, // 128-bit long double
|
||||
mpl::int_<0> // too many bits, use generic version.
|
||||
>::type
|
||||
>::type
|
||||
>::type
|
||||
>::type tag_type;
|
||||
|
||||
detail::expm1_initializer<value_type, forwarding_policy, tag_type>::force_instantiate();
|
||||
|
||||
return policies::checked_narrowing_cast<result_type, forwarding_policy>(detail::expm1_imp(
|
||||
static_cast<value_type>(x),
|
||||
tag_type(), forwarding_policy()), "boost::math::expm1<%1%>(%1%)");
|
||||
}
|
||||
|
||||
#ifdef expm1
|
||||
# ifndef BOOST_HAS_expm1
|
||||
# define BOOST_HAS_expm1
|
||||
# endif
|
||||
# undef expm1
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_EXPM1) && !(defined(__osf__) && defined(__DECCXX_VER))
|
||||
# ifdef BOOST_MATH_USE_C99
|
||||
inline float expm1(float x, const policies::policy<>&){ return ::expm1f(x); }
|
||||
# ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
|
||||
inline long double expm1(long double x, const policies::policy<>&){ return ::expm1l(x); }
|
||||
# endif
|
||||
# else
|
||||
inline float expm1(float x, const policies::policy<>&){ return static_cast<float>(::expm1(x)); }
|
||||
# endif
|
||||
inline double expm1(double x, const policies::policy<>&){ return ::expm1(x); }
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
inline typename tools::promote_args<T>::type expm1(T x)
|
||||
{
|
||||
return expm1(x, policies::policy<>());
|
||||
}
|
||||
|
||||
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
|
||||
inline float expm1(float z)
|
||||
{
|
||||
return expm1<float>(z);
|
||||
}
|
||||
inline double expm1(double z)
|
||||
{
|
||||
return expm1<double>(z);
|
||||
}
|
||||
#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
|
||||
inline long double expm1(long double z)
|
||||
{
|
||||
return expm1<long double>(z);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
} // namespace math
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_MATH_HYPOT_INCLUDED
|
||||
|
||||
|
||||
|
||||
|
||||
268
code_isotrope/boost/math/special_functions/factorials.hpp
Executable file
268
code_isotrope/boost/math/special_functions/factorials.hpp
Executable file
@@ -0,0 +1,268 @@
|
||||
// Copyright John Maddock 2006, 2010.
|
||||
// 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_FACTORIALS_HPP
|
||||
#define BOOST_MATH_SP_FACTORIALS_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/math/special_functions/gamma.hpp>
|
||||
#include <boost/math/special_functions/detail/unchecked_factorial.hpp>
|
||||
#include <boost/array.hpp>
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(push) // Temporary until lexical cast fixed.
|
||||
#pragma warning(disable: 4127 4701)
|
||||
#endif
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
#include <boost/config/no_tr1/cmath.hpp>
|
||||
|
||||
namespace boost { namespace math
|
||||
{
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T factorial(unsigned i, const Policy& pol)
|
||||
{
|
||||
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.
|
||||
|
||||
BOOST_MATH_STD_USING // Aid ADL for floor.
|
||||
|
||||
if(i <= max_factorial<T>::value)
|
||||
return unchecked_factorial<T>(i);
|
||||
T result = boost::math::tgamma(static_cast<T>(i+1), pol);
|
||||
if(result > tools::max_value<T>())
|
||||
return result; // Overflowed value! (But tgamma will have signalled the error already).
|
||||
return floor(result + 0.5f);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T factorial(unsigned i)
|
||||
{
|
||||
return factorial<T>(i, policies::policy<>());
|
||||
}
|
||||
/*
|
||||
// Can't have these in a policy enabled world?
|
||||
template<>
|
||||
inline float factorial<float>(unsigned i)
|
||||
{
|
||||
if(i <= max_factorial<float>::value)
|
||||
return unchecked_factorial<float>(i);
|
||||
return tools::overflow_error<float>(BOOST_CURRENT_FUNCTION);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline double factorial<double>(unsigned i)
|
||||
{
|
||||
if(i <= max_factorial<double>::value)
|
||||
return unchecked_factorial<double>(i);
|
||||
return tools::overflow_error<double>(BOOST_CURRENT_FUNCTION);
|
||||
}
|
||||
*/
|
||||
template <class T, class Policy>
|
||||
T double_factorial(unsigned i, const Policy& pol)
|
||||
{
|
||||
BOOST_STATIC_ASSERT(!boost::is_integral<T>::value);
|
||||
BOOST_MATH_STD_USING // ADL lookup of std names
|
||||
if(i & 1)
|
||||
{
|
||||
// odd i:
|
||||
if(i < max_factorial<T>::value)
|
||||
{
|
||||
unsigned n = (i - 1) / 2;
|
||||
return ceil(unchecked_factorial<T>(i) / (ldexp(T(1), (int)n) * unchecked_factorial<T>(n)) - 0.5f);
|
||||
}
|
||||
//
|
||||
// Fallthrough: i is too large to use table lookup, try the
|
||||
// gamma function instead.
|
||||
//
|
||||
T result = boost::math::tgamma(static_cast<T>(i) / 2 + 1, pol) / sqrt(constants::pi<T>());
|
||||
if(ldexp(tools::max_value<T>(), -static_cast<int>(i+1) / 2) > result)
|
||||
return ceil(result * ldexp(T(1), static_cast<int>(i+1) / 2) - 0.5f);
|
||||
}
|
||||
else
|
||||
{
|
||||
// even i:
|
||||
unsigned n = i / 2;
|
||||
T result = factorial<T>(n, pol);
|
||||
if(ldexp(tools::max_value<T>(), -(int)n) > result)
|
||||
return result * ldexp(T(1), (int)n);
|
||||
}
|
||||
//
|
||||
// If we fall through to here then the result is infinite:
|
||||
//
|
||||
return policies::raise_overflow_error<T>("boost::math::double_factorial<%1%>(unsigned)", 0, pol);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T double_factorial(unsigned i)
|
||||
{
|
||||
return double_factorial<T>(i, policies::policy<>());
|
||||
}
|
||||
|
||||
namespace detail{
|
||||
|
||||
template <class T, class Policy>
|
||||
T rising_factorial_imp(T x, int n, const Policy& pol)
|
||||
{
|
||||
BOOST_STATIC_ASSERT(!boost::is_integral<T>::value);
|
||||
if(x < 0)
|
||||
{
|
||||
//
|
||||
// For x less than zero, we really have a falling
|
||||
// factorial, modulo a possible change of sign.
|
||||
//
|
||||
// Note that the falling factorial isn't defined
|
||||
// for negative n, so we'll get rid of that case
|
||||
// first:
|
||||
//
|
||||
bool inv = false;
|
||||
if(n < 0)
|
||||
{
|
||||
x += n;
|
||||
n = -n;
|
||||
inv = true;
|
||||
}
|
||||
T result = ((n&1) ? -1 : 1) * falling_factorial(-x, n, pol);
|
||||
if(inv)
|
||||
result = 1 / result;
|
||||
return result;
|
||||
}
|
||||
if(n == 0)
|
||||
return 1;
|
||||
if(x == 0)
|
||||
{
|
||||
if(n < 0)
|
||||
return -boost::math::tgamma_delta_ratio(x + 1, static_cast<T>(-n), pol);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
if((x < 1) && (x + n < 0))
|
||||
{
|
||||
T val = boost::math::tgamma_delta_ratio(1 - x, static_cast<T>(-n), pol);
|
||||
return (n & 1) ? T(-val) : val;
|
||||
}
|
||||
//
|
||||
// We don't optimise this for small n, because
|
||||
// tgamma_delta_ratio is alreay optimised for that
|
||||
// use case:
|
||||
//
|
||||
return 1 / boost::math::tgamma_delta_ratio(x, static_cast<T>(n), pol);
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T falling_factorial_imp(T x, unsigned n, const Policy& pol)
|
||||
{
|
||||
BOOST_STATIC_ASSERT(!boost::is_integral<T>::value);
|
||||
BOOST_MATH_STD_USING // ADL of std names
|
||||
if((x == 0) && (n >= 0))
|
||||
return 0;
|
||||
if(x < 0)
|
||||
{
|
||||
//
|
||||
// For x < 0 we really have a rising factorial
|
||||
// modulo a possible change of sign:
|
||||
//
|
||||
return (n&1 ? -1 : 1) * rising_factorial(-x, n, pol);
|
||||
}
|
||||
if(n == 0)
|
||||
return 1;
|
||||
if(x < 0.5f)
|
||||
{
|
||||
//
|
||||
// 1 + x below will throw away digits, so split up calculation:
|
||||
//
|
||||
if(n > max_factorial<T>::value - 2)
|
||||
{
|
||||
// If the two end of the range are far apart we have a ratio of two very large
|
||||
// numbers, split the calculation up into two blocks:
|
||||
T t1 = x * boost::math::falling_factorial(x - 1, max_factorial<T>::value - 2);
|
||||
T t2 = boost::math::falling_factorial(x - max_factorial<T>::value + 1, n - max_factorial<T>::value + 1);
|
||||
if(tools::max_value<T>() / fabs(t1) < fabs(t2))
|
||||
return boost::math::sign(t1) * boost::math::sign(t2) * policies::raise_overflow_error<T>("boost::math::falling_factorial<%1%>", 0, pol);
|
||||
return t1 * t2;
|
||||
}
|
||||
return x * boost::math::falling_factorial(x - 1, n - 1);
|
||||
}
|
||||
if(x <= n - 1)
|
||||
{
|
||||
//
|
||||
// x+1-n will be negative and tgamma_delta_ratio won't
|
||||
// handle it, split the product up into three parts:
|
||||
//
|
||||
T xp1 = x + 1;
|
||||
unsigned n2 = itrunc((T)floor(xp1), pol);
|
||||
if(n2 == xp1)
|
||||
return 0;
|
||||
T result = boost::math::tgamma_delta_ratio(xp1, -static_cast<T>(n2), pol);
|
||||
x -= n2;
|
||||
result *= x;
|
||||
++n2;
|
||||
if(n2 < n)
|
||||
result *= falling_factorial(x - 1, n - n2, pol);
|
||||
return result;
|
||||
}
|
||||
//
|
||||
// Simple case: just the ratio of two
|
||||
// (positive argument) gamma functions.
|
||||
// Note that we don't optimise this for small n,
|
||||
// because tgamma_delta_ratio is alreay optimised
|
||||
// for that use case:
|
||||
//
|
||||
return boost::math::tgamma_delta_ratio(x + 1, -static_cast<T>(n), pol);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class RT>
|
||||
inline typename tools::promote_args<RT>::type
|
||||
falling_factorial(RT x, unsigned n)
|
||||
{
|
||||
typedef typename tools::promote_args<RT>::type result_type;
|
||||
return detail::falling_factorial_imp(
|
||||
static_cast<result_type>(x), n, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class RT, class Policy>
|
||||
inline typename tools::promote_args<RT>::type
|
||||
falling_factorial(RT x, unsigned n, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<RT>::type result_type;
|
||||
return detail::falling_factorial_imp(
|
||||
static_cast<result_type>(x), n, pol);
|
||||
}
|
||||
|
||||
template <class RT>
|
||||
inline typename tools::promote_args<RT>::type
|
||||
rising_factorial(RT x, int n)
|
||||
{
|
||||
typedef typename tools::promote_args<RT>::type result_type;
|
||||
return detail::rising_factorial_imp(
|
||||
static_cast<result_type>(x), n, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class RT, class Policy>
|
||||
inline typename tools::promote_args<RT>::type
|
||||
rising_factorial(RT x, int n, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<RT>::type result_type;
|
||||
return detail::rising_factorial_imp(
|
||||
static_cast<result_type>(x), n, pol);
|
||||
}
|
||||
|
||||
} // namespace math
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_MATH_SP_FACTORIALS_HPP
|
||||
|
||||
640
code_isotrope/boost/math/special_functions/fpclassify.hpp
Executable file
640
code_isotrope/boost/math/special_functions/fpclassify.hpp
Executable file
@@ -0,0 +1,640 @@
|
||||
// Copyright John Maddock 2005-2008.
|
||||
// Copyright (c) 2006-2008 Johan Rade
|
||||
// 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_FPCLASSIFY_HPP
|
||||
#define BOOST_MATH_FPCLASSIFY_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
#include <boost/config/no_tr1/cmath.hpp>
|
||||
#include <boost/limits.hpp>
|
||||
#include <boost/math/tools/real_cast.hpp>
|
||||
#include <boost/type_traits/is_floating_point.hpp>
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/math/special_functions/detail/fp_traits.hpp>
|
||||
/*!
|
||||
\file fpclassify.hpp
|
||||
\brief Classify floating-point value as normal, subnormal, zero, infinite, or NaN.
|
||||
\version 1.0
|
||||
\author John Maddock
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
1. If the platform is C99 compliant, then the native floating point
|
||||
classification functions are used. However, note that we must only
|
||||
define the functions which call std::fpclassify etc if that function
|
||||
really does exist: otherwise a compiler may reject the code even though
|
||||
the template is never instantiated.
|
||||
|
||||
2. If the platform is not C99 compliant, and the binary format for
|
||||
a floating point type (float, double or long double) can be determined
|
||||
at compile time, then the following algorithm is used:
|
||||
|
||||
If all exponent bits, the flag bit (if there is one),
|
||||
and all significand bits are 0, then the number is zero.
|
||||
|
||||
If all exponent bits and the flag bit (if there is one) are 0,
|
||||
and at least one significand bit is 1, then the number is subnormal.
|
||||
|
||||
If all exponent bits are 1 and all significand bits are 0,
|
||||
then the number is infinity.
|
||||
|
||||
If all exponent bits are 1 and at least one significand bit is 1,
|
||||
then the number is a not-a-number.
|
||||
|
||||
Otherwise the number is normal.
|
||||
|
||||
This algorithm works for the IEEE 754 representation,
|
||||
and also for several non IEEE 754 formats.
|
||||
|
||||
Most formats have the structure
|
||||
sign bit + exponent bits + significand bits.
|
||||
|
||||
A few have the structure
|
||||
sign bit + exponent bits + flag bit + significand bits.
|
||||
The flag bit is 0 for zero and subnormal numbers,
|
||||
and 1 for normal numbers and NaN.
|
||||
It is 0 (Motorola 68K) or 1 (Intel) for infinity.
|
||||
|
||||
To get the bits, the four or eight most significant bytes are copied
|
||||
into an uint32_t or uint64_t and bit masks are applied.
|
||||
This covers all the exponent bits and the flag bit (if there is one),
|
||||
but not always all the significand bits.
|
||||
Some of the functions below have two implementations,
|
||||
depending on whether all the significand bits are copied or not.
|
||||
|
||||
3. If the platform is not C99 compliant, and the binary format for
|
||||
a floating point type (float, double or long double) can not be determined
|
||||
at compile time, then comparison with std::numeric_limits values
|
||||
is used.
|
||||
|
||||
*/
|
||||
|
||||
#if defined(_MSC_VER) || defined(__BORLANDC__)
|
||||
#include <float.h>
|
||||
#endif
|
||||
#ifdef BOOST_MATH_USE_FLOAT128
|
||||
#ifdef __has_include
|
||||
#if __has_include("quadmath.h")
|
||||
#include "quadmath.h"
|
||||
#define BOOST_MATH_HAS_QUADMATH_H
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_NO_STDC_NAMESPACE
|
||||
namespace std{ using ::abs; using ::fabs; }
|
||||
#endif
|
||||
|
||||
namespace boost{
|
||||
|
||||
//
|
||||
// This must not be located in any namespace under boost::math
|
||||
// otherwise we can get into an infinite loop if isnan is
|
||||
// a #define for "isnan" !
|
||||
//
|
||||
namespace math_detail{
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4800)
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
inline bool is_nan_helper(T t, const boost::true_type&)
|
||||
{
|
||||
#ifdef isnan
|
||||
return isnan(t);
|
||||
#elif defined(BOOST_MATH_DISABLE_STD_FPCLASSIFY) || !defined(BOOST_HAS_FPCLASSIFY)
|
||||
(void)t;
|
||||
return false;
|
||||
#else // BOOST_HAS_FPCLASSIFY
|
||||
return (BOOST_FPCLASSIFY_PREFIX fpclassify(t) == (int)FP_NAN);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
inline bool is_nan_helper(T, const boost::false_type&)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#if defined(BOOST_MATH_USE_FLOAT128)
|
||||
#if defined(BOOST_MATH_HAS_QUADMATH_H)
|
||||
inline bool is_nan_helper(__float128 f, const boost::true_type&) { return ::isnanq(f); }
|
||||
inline bool is_nan_helper(__float128 f, const boost::false_type&) { return ::isnanq(f); }
|
||||
#elif defined(BOOST_GNU_STDLIB) && BOOST_GNU_STDLIB && \
|
||||
_GLIBCXX_USE_C99_MATH && !_GLIBCXX_USE_C99_FP_MACROS_DYNAMIC
|
||||
inline bool is_nan_helper(__float128 f, const boost::true_type&) { return std::isnan(static_cast<double>(f)); }
|
||||
inline bool is_nan_helper(__float128 f, const boost::false_type&) { return std::isnan(static_cast<double>(f)); }
|
||||
#else
|
||||
inline bool is_nan_helper(__float128 f, const boost::true_type&) { return ::isnan(static_cast<double>(f)); }
|
||||
inline bool is_nan_helper(__float128 f, const boost::false_type&) { return ::isnan(static_cast<double>(f)); }
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace math{
|
||||
|
||||
namespace detail{
|
||||
|
||||
#ifdef BOOST_MATH_USE_STD_FPCLASSIFY
|
||||
template <class T>
|
||||
inline int fpclassify_imp BOOST_NO_MACRO_EXPAND(T t, const native_tag&)
|
||||
{
|
||||
return (std::fpclassify)(t);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
inline int fpclassify_imp BOOST_NO_MACRO_EXPAND(T t, const generic_tag<true>&)
|
||||
{
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(t);
|
||||
|
||||
// whenever possible check for Nan's first:
|
||||
#if defined(BOOST_HAS_FPCLASSIFY) && !defined(BOOST_MATH_DISABLE_STD_FPCLASSIFY)
|
||||
if(::boost::math_detail::is_nan_helper(t, ::boost::is_floating_point<T>()))
|
||||
return FP_NAN;
|
||||
#elif defined(isnan)
|
||||
if(boost::math_detail::is_nan_helper(t, ::boost::is_floating_point<T>()))
|
||||
return FP_NAN;
|
||||
#elif defined(_MSC_VER) || defined(__BORLANDC__)
|
||||
if(::_isnan(boost::math::tools::real_cast<double>(t)))
|
||||
return FP_NAN;
|
||||
#endif
|
||||
// std::fabs broken on a few systems especially for long long!!!!
|
||||
T at = (t < T(0)) ? -t : t;
|
||||
|
||||
// Use a process of exclusion to figure out
|
||||
// what kind of type we have, this relies on
|
||||
// IEEE conforming reals that will treat
|
||||
// Nan's as unordered. Some compilers
|
||||
// don't do this once optimisations are
|
||||
// turned on, hence the check for nan's above.
|
||||
if(at <= (std::numeric_limits<T>::max)())
|
||||
{
|
||||
if(at >= (std::numeric_limits<T>::min)())
|
||||
return FP_NORMAL;
|
||||
return (at != 0) ? FP_SUBNORMAL : FP_ZERO;
|
||||
}
|
||||
else if(at > (std::numeric_limits<T>::max)())
|
||||
return FP_INFINITE;
|
||||
return FP_NAN;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline int fpclassify_imp BOOST_NO_MACRO_EXPAND(T t, const generic_tag<false>&)
|
||||
{
|
||||
#ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
|
||||
if(std::numeric_limits<T>::is_specialized)
|
||||
return fpclassify_imp(t, generic_tag<true>());
|
||||
#endif
|
||||
//
|
||||
// An unknown type with no numeric_limits support,
|
||||
// so what are we supposed to do we do here?
|
||||
//
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(t);
|
||||
|
||||
return t == 0 ? FP_ZERO : FP_NORMAL;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
int fpclassify_imp BOOST_NO_MACRO_EXPAND(T x, ieee_copy_all_bits_tag)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
|
||||
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(x);
|
||||
|
||||
BOOST_DEDUCED_TYPENAME traits::bits a;
|
||||
traits::get_bits(x,a);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(a);
|
||||
a &= traits::exponent | traits::flag | traits::significand;
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE((traits::exponent | traits::flag | traits::significand));
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(a);
|
||||
|
||||
if(a <= traits::significand) {
|
||||
if(a == 0)
|
||||
return FP_ZERO;
|
||||
else
|
||||
return FP_SUBNORMAL;
|
||||
}
|
||||
|
||||
if(a < traits::exponent) return FP_NORMAL;
|
||||
|
||||
a &= traits::significand;
|
||||
if(a == 0) return FP_INFINITE;
|
||||
|
||||
return FP_NAN;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
int fpclassify_imp BOOST_NO_MACRO_EXPAND(T x, ieee_copy_leading_bits_tag)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
|
||||
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(x);
|
||||
|
||||
BOOST_DEDUCED_TYPENAME traits::bits a;
|
||||
traits::get_bits(x,a);
|
||||
a &= traits::exponent | traits::flag | traits::significand;
|
||||
|
||||
if(a <= traits::significand) {
|
||||
if(x == 0)
|
||||
return FP_ZERO;
|
||||
else
|
||||
return FP_SUBNORMAL;
|
||||
}
|
||||
|
||||
if(a < traits::exponent) return FP_NORMAL;
|
||||
|
||||
a &= traits::significand;
|
||||
traits::set_bits(x,a);
|
||||
if(x == 0) return FP_INFINITE;
|
||||
|
||||
return FP_NAN;
|
||||
}
|
||||
|
||||
#if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && (defined(BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY) || defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS))
|
||||
inline int fpclassify_imp BOOST_NO_MACRO_EXPAND(long double t, const native_tag&)
|
||||
{
|
||||
return boost::math::detail::fpclassify_imp(t, generic_tag<true>());
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class T>
|
||||
inline int fpclassify BOOST_NO_MACRO_EXPAND(T t)
|
||||
{
|
||||
typedef typename detail::fp_traits<T>::type traits;
|
||||
typedef typename traits::method method;
|
||||
typedef typename tools::promote_args_permissive<T>::type value_type;
|
||||
#ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
|
||||
if(std::numeric_limits<T>::is_specialized && detail::is_generic_tag_false(static_cast<method*>(0)))
|
||||
return detail::fpclassify_imp(static_cast<value_type>(t), detail::generic_tag<true>());
|
||||
return detail::fpclassify_imp(static_cast<value_type>(t), method());
|
||||
#else
|
||||
return detail::fpclassify_imp(static_cast<value_type>(t), method());
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
|
||||
template <>
|
||||
inline int fpclassify<long double> BOOST_NO_MACRO_EXPAND(long double t)
|
||||
{
|
||||
typedef detail::fp_traits<long double>::type traits;
|
||||
typedef traits::method method;
|
||||
typedef long double value_type;
|
||||
#ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
|
||||
if(std::numeric_limits<long double>::is_specialized && detail::is_generic_tag_false(static_cast<method*>(0)))
|
||||
return detail::fpclassify_imp(static_cast<value_type>(t), detail::generic_tag<true>());
|
||||
return detail::fpclassify_imp(static_cast<value_type>(t), method());
|
||||
#else
|
||||
return detail::fpclassify_imp(static_cast<value_type>(t), method());
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace detail {
|
||||
|
||||
#ifdef BOOST_MATH_USE_STD_FPCLASSIFY
|
||||
template<class T>
|
||||
inline bool isfinite_impl(T x, native_tag const&)
|
||||
{
|
||||
return (std::isfinite)(x);
|
||||
}
|
||||
#endif
|
||||
|
||||
template<class T>
|
||||
inline bool isfinite_impl(T x, generic_tag<true> const&)
|
||||
{
|
||||
return x >= -(std::numeric_limits<T>::max)()
|
||||
&& x <= (std::numeric_limits<T>::max)();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline bool isfinite_impl(T x, generic_tag<false> const&)
|
||||
{
|
||||
#ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
|
||||
if(std::numeric_limits<T>::is_specialized)
|
||||
return isfinite_impl(x, generic_tag<true>());
|
||||
#endif
|
||||
(void)x; // warning suppression.
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline bool isfinite_impl(T x, ieee_tag const&)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME detail::fp_traits<T>::type traits;
|
||||
BOOST_DEDUCED_TYPENAME traits::bits a;
|
||||
traits::get_bits(x,a);
|
||||
a &= traits::exponent;
|
||||
return a != traits::exponent;
|
||||
}
|
||||
|
||||
#if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && defined(BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY)
|
||||
inline bool isfinite_impl BOOST_NO_MACRO_EXPAND(long double t, const native_tag&)
|
||||
{
|
||||
return boost::math::detail::isfinite_impl(t, generic_tag<true>());
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline bool (isfinite)(T x)
|
||||
{ //!< \brief return true if floating-point type t is finite.
|
||||
typedef typename detail::fp_traits<T>::type traits;
|
||||
typedef typename traits::method method;
|
||||
// typedef typename boost::is_floating_point<T>::type fp_tag;
|
||||
typedef typename tools::promote_args_permissive<T>::type value_type;
|
||||
return detail::isfinite_impl(static_cast<value_type>(x), method());
|
||||
}
|
||||
|
||||
#ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
|
||||
template<>
|
||||
inline bool (isfinite)(long double x)
|
||||
{ //!< \brief return true if floating-point type t is finite.
|
||||
typedef detail::fp_traits<long double>::type traits;
|
||||
typedef traits::method method;
|
||||
//typedef boost::is_floating_point<long double>::type fp_tag;
|
||||
typedef long double value_type;
|
||||
return detail::isfinite_impl(static_cast<value_type>(x), method());
|
||||
}
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace detail {
|
||||
|
||||
#ifdef BOOST_MATH_USE_STD_FPCLASSIFY
|
||||
template<class T>
|
||||
inline bool isnormal_impl(T x, native_tag const&)
|
||||
{
|
||||
return (std::isnormal)(x);
|
||||
}
|
||||
#endif
|
||||
|
||||
template<class T>
|
||||
inline bool isnormal_impl(T x, generic_tag<true> const&)
|
||||
{
|
||||
if(x < 0) x = -x;
|
||||
return x >= (std::numeric_limits<T>::min)()
|
||||
&& x <= (std::numeric_limits<T>::max)();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline bool isnormal_impl(T x, generic_tag<false> const&)
|
||||
{
|
||||
#ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
|
||||
if(std::numeric_limits<T>::is_specialized)
|
||||
return isnormal_impl(x, generic_tag<true>());
|
||||
#endif
|
||||
return !(x == 0);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline bool isnormal_impl(T x, ieee_tag const&)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME detail::fp_traits<T>::type traits;
|
||||
BOOST_DEDUCED_TYPENAME traits::bits a;
|
||||
traits::get_bits(x,a);
|
||||
a &= traits::exponent | traits::flag;
|
||||
return (a != 0) && (a < traits::exponent);
|
||||
}
|
||||
|
||||
#if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && defined(BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY)
|
||||
inline bool isnormal_impl BOOST_NO_MACRO_EXPAND(long double t, const native_tag&)
|
||||
{
|
||||
return boost::math::detail::isnormal_impl(t, generic_tag<true>());
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline bool (isnormal)(T x)
|
||||
{
|
||||
typedef typename detail::fp_traits<T>::type traits;
|
||||
typedef typename traits::method method;
|
||||
//typedef typename boost::is_floating_point<T>::type fp_tag;
|
||||
typedef typename tools::promote_args_permissive<T>::type value_type;
|
||||
return detail::isnormal_impl(static_cast<value_type>(x), method());
|
||||
}
|
||||
|
||||
#ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
|
||||
template<>
|
||||
inline bool (isnormal)(long double x)
|
||||
{
|
||||
typedef detail::fp_traits<long double>::type traits;
|
||||
typedef traits::method method;
|
||||
//typedef boost::is_floating_point<long double>::type fp_tag;
|
||||
typedef long double value_type;
|
||||
return detail::isnormal_impl(static_cast<value_type>(x), method());
|
||||
}
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace detail {
|
||||
|
||||
#ifdef BOOST_MATH_USE_STD_FPCLASSIFY
|
||||
template<class T>
|
||||
inline bool isinf_impl(T x, native_tag const&)
|
||||
{
|
||||
return (std::isinf)(x);
|
||||
}
|
||||
#endif
|
||||
|
||||
template<class T>
|
||||
inline bool isinf_impl(T x, generic_tag<true> const&)
|
||||
{
|
||||
(void)x; // in case the compiler thinks that x is unused because std::numeric_limits<T>::has_infinity is false
|
||||
return std::numeric_limits<T>::has_infinity
|
||||
&& ( x == std::numeric_limits<T>::infinity()
|
||||
|| x == -std::numeric_limits<T>::infinity());
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline bool isinf_impl(T x, generic_tag<false> const&)
|
||||
{
|
||||
#ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
|
||||
if(std::numeric_limits<T>::is_specialized)
|
||||
return isinf_impl(x, generic_tag<true>());
|
||||
#endif
|
||||
(void)x; // warning suppression.
|
||||
return false;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline bool isinf_impl(T x, ieee_copy_all_bits_tag const&)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
|
||||
|
||||
BOOST_DEDUCED_TYPENAME traits::bits a;
|
||||
traits::get_bits(x,a);
|
||||
a &= traits::exponent | traits::significand;
|
||||
return a == traits::exponent;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline bool isinf_impl(T x, ieee_copy_leading_bits_tag const&)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
|
||||
|
||||
BOOST_DEDUCED_TYPENAME traits::bits a;
|
||||
traits::get_bits(x,a);
|
||||
a &= traits::exponent | traits::significand;
|
||||
if(a != traits::exponent)
|
||||
return false;
|
||||
|
||||
traits::set_bits(x,0);
|
||||
return x == 0;
|
||||
}
|
||||
|
||||
#if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && defined(BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY)
|
||||
inline bool isinf_impl BOOST_NO_MACRO_EXPAND(long double t, const native_tag&)
|
||||
{
|
||||
return boost::math::detail::isinf_impl(t, generic_tag<true>());
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<class T>
|
||||
inline bool (isinf)(T x)
|
||||
{
|
||||
typedef typename detail::fp_traits<T>::type traits;
|
||||
typedef typename traits::method method;
|
||||
// typedef typename boost::is_floating_point<T>::type fp_tag;
|
||||
typedef typename tools::promote_args_permissive<T>::type value_type;
|
||||
return detail::isinf_impl(static_cast<value_type>(x), method());
|
||||
}
|
||||
|
||||
#ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
|
||||
template<>
|
||||
inline bool (isinf)(long double x)
|
||||
{
|
||||
typedef detail::fp_traits<long double>::type traits;
|
||||
typedef traits::method method;
|
||||
//typedef boost::is_floating_point<long double>::type fp_tag;
|
||||
typedef long double value_type;
|
||||
return detail::isinf_impl(static_cast<value_type>(x), method());
|
||||
}
|
||||
#endif
|
||||
#if defined(BOOST_MATH_USE_FLOAT128) && defined(BOOST_MATH_HAS_QUADMATH_H)
|
||||
template<>
|
||||
inline bool (isinf)(__float128 x)
|
||||
{
|
||||
return ::isinfq(x);
|
||||
}
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace detail {
|
||||
|
||||
#ifdef BOOST_MATH_USE_STD_FPCLASSIFY
|
||||
template<class T>
|
||||
inline bool isnan_impl(T x, native_tag const&)
|
||||
{
|
||||
return (std::isnan)(x);
|
||||
}
|
||||
#endif
|
||||
|
||||
template<class T>
|
||||
inline bool isnan_impl(T x, generic_tag<true> const&)
|
||||
{
|
||||
return std::numeric_limits<T>::has_infinity
|
||||
? !(x <= std::numeric_limits<T>::infinity())
|
||||
: x != x;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline bool isnan_impl(T x, generic_tag<false> const&)
|
||||
{
|
||||
#ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
|
||||
if(std::numeric_limits<T>::is_specialized)
|
||||
return isnan_impl(x, generic_tag<true>());
|
||||
#endif
|
||||
(void)x; // warning suppression
|
||||
return false;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline bool isnan_impl(T x, ieee_copy_all_bits_tag const&)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
|
||||
|
||||
BOOST_DEDUCED_TYPENAME traits::bits a;
|
||||
traits::get_bits(x,a);
|
||||
a &= traits::exponent | traits::significand;
|
||||
return a > traits::exponent;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline bool isnan_impl(T x, ieee_copy_leading_bits_tag const&)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
|
||||
|
||||
BOOST_DEDUCED_TYPENAME traits::bits a;
|
||||
traits::get_bits(x,a);
|
||||
|
||||
a &= traits::exponent | traits::significand;
|
||||
if(a < traits::exponent)
|
||||
return false;
|
||||
|
||||
a &= traits::significand;
|
||||
traits::set_bits(x,a);
|
||||
return x != 0;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<class T>
|
||||
inline bool (isnan)(T x)
|
||||
{ //!< \brief return true if floating-point type t is NaN (Not A Number).
|
||||
typedef typename detail::fp_traits<T>::type traits;
|
||||
typedef typename traits::method method;
|
||||
// typedef typename boost::is_floating_point<T>::type fp_tag;
|
||||
return detail::isnan_impl(x, method());
|
||||
}
|
||||
|
||||
#ifdef isnan
|
||||
template <> inline bool isnan BOOST_NO_MACRO_EXPAND<float>(float t){ return ::boost::math_detail::is_nan_helper(t, boost::true_type()); }
|
||||
template <> inline bool isnan BOOST_NO_MACRO_EXPAND<double>(double t){ return ::boost::math_detail::is_nan_helper(t, boost::true_type()); }
|
||||
template <> inline bool isnan BOOST_NO_MACRO_EXPAND<long double>(long double t){ return ::boost::math_detail::is_nan_helper(t, boost::true_type()); }
|
||||
#elif defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS)
|
||||
template<>
|
||||
inline bool (isnan)(long double x)
|
||||
{ //!< \brief return true if floating-point type t is NaN (Not A Number).
|
||||
typedef detail::fp_traits<long double>::type traits;
|
||||
typedef traits::method method;
|
||||
//typedef boost::is_floating_point<long double>::type fp_tag;
|
||||
return detail::isnan_impl(x, method());
|
||||
}
|
||||
#endif
|
||||
#if defined(BOOST_MATH_USE_FLOAT128) && defined(BOOST_MATH_HAS_QUADMATH_H)
|
||||
template<>
|
||||
inline bool (isnan)(__float128 x)
|
||||
{
|
||||
return ::isnanq(x);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace math
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_MATH_FPCLASSIFY_HPP
|
||||
|
||||
2080
code_isotrope/boost/math/special_functions/gamma.hpp
Executable file
2080
code_isotrope/boost/math/special_functions/gamma.hpp
Executable file
File diff suppressed because it is too large
Load Diff
180
code_isotrope/boost/math/special_functions/hankel.hpp
Executable file
180
code_isotrope/boost/math/special_functions/hankel.hpp
Executable file
@@ -0,0 +1,180 @@
|
||||
// Copyright John Maddock 2012.
|
||||
// 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_HANKEL_HPP
|
||||
#define BOOST_MATH_HANKEL_HPP
|
||||
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/math/special_functions/bessel.hpp>
|
||||
|
||||
namespace boost{ namespace math{
|
||||
|
||||
namespace detail{
|
||||
|
||||
template <class T, class Policy>
|
||||
std::complex<T> hankel_imp(T v, T x, const bessel_no_int_tag&, const Policy& pol, int sign)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
static const char* function = "boost::math::cyl_hankel_1<%1%>(%1%,%1%)";
|
||||
|
||||
if(x < 0)
|
||||
{
|
||||
bool isint_v = floor(v) == v;
|
||||
T j, y;
|
||||
bessel_jy(v, -x, &j, &y, need_j | need_y, pol);
|
||||
std::complex<T> cx(x), cv(v);
|
||||
std::complex<T> j_result, y_result;
|
||||
if(isint_v)
|
||||
{
|
||||
int s = (iround(v) & 1) ? -1 : 1;
|
||||
j_result = j * s;
|
||||
y_result = T(s) * (y - (2 / constants::pi<T>()) * (log(-x) - log(cx)) * j);
|
||||
}
|
||||
else
|
||||
{
|
||||
j_result = pow(cx, v) * pow(-cx, -v) * j;
|
||||
T p1 = pow(-x, v);
|
||||
std::complex<T> p2 = pow(cx, v);
|
||||
y_result = p1 * y / p2
|
||||
+ (p2 / p1 - p1 / p2) * j / tan(constants::pi<T>() * v);
|
||||
}
|
||||
// multiply y_result by i:
|
||||
y_result = std::complex<T>(-sign * y_result.imag(), sign * y_result.real());
|
||||
return j_result + y_result;
|
||||
}
|
||||
|
||||
if(x == 0)
|
||||
{
|
||||
if(v == 0)
|
||||
{
|
||||
// J is 1, Y is -INF
|
||||
return std::complex<T>(1, sign * -policies::raise_overflow_error<T>(function, 0, pol));
|
||||
}
|
||||
else
|
||||
{
|
||||
// At least one of J and Y is complex infinity:
|
||||
return std::complex<T>(policies::raise_overflow_error<T>(function, 0, pol), sign * policies::raise_overflow_error<T>(function, 0, pol));
|
||||
}
|
||||
}
|
||||
|
||||
T j, y;
|
||||
bessel_jy(v, x, &j, &y, need_j | need_y, pol);
|
||||
return std::complex<T>(j, sign * y);
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
std::complex<T> hankel_imp(int v, T x, const bessel_int_tag&, const Policy& pol, int sign);
|
||||
|
||||
template <class T, class Policy>
|
||||
inline std::complex<T> hankel_imp(T v, T x, const bessel_maybe_int_tag&, const Policy& pol, int sign)
|
||||
{
|
||||
BOOST_MATH_STD_USING // ADL of std names.
|
||||
int ival = detail::iconv(v, pol);
|
||||
if(0 == v - ival)
|
||||
{
|
||||
return hankel_imp(ival, x, bessel_int_tag(), pol, sign);
|
||||
}
|
||||
return hankel_imp(v, x, bessel_no_int_tag(), pol, sign);
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline std::complex<T> hankel_imp(int v, T x, const bessel_int_tag&, const Policy& pol, int sign)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
if((std::abs(v) < 200) && (x > 0))
|
||||
return std::complex<T>(bessel_jn(v, x, pol), sign * bessel_yn(v, x, pol));
|
||||
return hankel_imp(static_cast<T>(v), x, bessel_no_int_tag(), pol, sign);
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline std::complex<T> sph_hankel_imp(T v, T x, const Policy& pol, int sign)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
return constants::root_half_pi<T>() * hankel_imp(v + 0.5f, x, bessel_no_int_tag(), pol, sign) / sqrt(std::complex<T>(x));
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class T1, class T2, class Policy>
|
||||
inline std::complex<typename detail::bessel_traits<T1, T2, Policy>::result_type> cyl_hankel_1(T1 v, T2 x, const Policy& pol)
|
||||
{
|
||||
BOOST_FPU_EXCEPTION_GUARD
|
||||
typedef typename detail::bessel_traits<T1, T2, Policy>::result_type result_type;
|
||||
typedef typename detail::bessel_traits<T1, T2, Policy>::optimisation_tag tag_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
return policies::checked_narrowing_cast<std::complex<result_type>, Policy>(detail::hankel_imp<value_type>(v, static_cast<value_type>(x), tag_type(), pol, 1), "boost::math::cyl_hankel_1<%1%>(%1%,%1%)");
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
inline std::complex<typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type> cyl_hankel_1(T1 v, T2 x)
|
||||
{
|
||||
return cyl_hankel_1(v, x, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T1, class T2, class Policy>
|
||||
inline std::complex<typename detail::bessel_traits<T1, T2, Policy>::result_type> cyl_hankel_2(T1 v, T2 x, const Policy& pol)
|
||||
{
|
||||
BOOST_FPU_EXCEPTION_GUARD
|
||||
typedef typename detail::bessel_traits<T1, T2, Policy>::result_type result_type;
|
||||
typedef typename detail::bessel_traits<T1, T2, Policy>::optimisation_tag tag_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
return policies::checked_narrowing_cast<std::complex<result_type>, Policy>(detail::hankel_imp<value_type>(v, static_cast<value_type>(x), tag_type(), pol, -1), "boost::math::cyl_hankel_1<%1%>(%1%,%1%)");
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
inline std::complex<typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type> cyl_hankel_2(T1 v, T2 x)
|
||||
{
|
||||
return cyl_hankel_2(v, x, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T1, class T2, class Policy>
|
||||
inline std::complex<typename detail::bessel_traits<T1, T2, Policy>::result_type> sph_hankel_1(T1 v, T2 x, const Policy&)
|
||||
{
|
||||
BOOST_FPU_EXCEPTION_GUARD
|
||||
typedef typename detail::bessel_traits<T1, T2, Policy>::result_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;
|
||||
|
||||
return policies::checked_narrowing_cast<std::complex<result_type>, Policy>(detail::sph_hankel_imp<value_type>(static_cast<value_type>(v), static_cast<value_type>(x), forwarding_policy(), 1), "boost::math::sph_hankel_1<%1%>(%1%,%1%)");
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
inline std::complex<typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type> sph_hankel_1(T1 v, T2 x)
|
||||
{
|
||||
return sph_hankel_1(v, x, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T1, class T2, class Policy>
|
||||
inline std::complex<typename detail::bessel_traits<T1, T2, Policy>::result_type> sph_hankel_2(T1 v, T2 x, const Policy&)
|
||||
{
|
||||
BOOST_FPU_EXCEPTION_GUARD
|
||||
typedef typename detail::bessel_traits<T1, T2, Policy>::result_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;
|
||||
|
||||
return policies::checked_narrowing_cast<std::complex<result_type>, Policy>(detail::sph_hankel_imp<value_type>(static_cast<value_type>(v), static_cast<value_type>(x), forwarding_policy(), -1), "boost::math::sph_hankel_1<%1%>(%1%,%1%)");
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
inline std::complex<typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type> sph_hankel_2(T1 v, T2 x)
|
||||
{
|
||||
return sph_hankel_2(v, x, policies::policy<>());
|
||||
}
|
||||
|
||||
}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_HANKEL_HPP
|
||||
|
||||
76
code_isotrope/boost/math/special_functions/hermite.hpp
Executable file
76
code_isotrope/boost/math/special_functions/hermite.hpp
Executable file
@@ -0,0 +1,76 @@
|
||||
|
||||
// (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_HERMITE_HPP
|
||||
#define BOOST_MATH_SPECIAL_HERMITE_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/math/tools/config.hpp>
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
|
||||
namespace boost{
|
||||
namespace math{
|
||||
|
||||
// Recurrance relation for Hermite polynomials:
|
||||
template <class T1, class T2, class T3>
|
||||
inline typename tools::promote_args<T1, T2, T3>::type
|
||||
hermite_next(unsigned n, T1 x, T2 Hn, T3 Hnm1)
|
||||
{
|
||||
return (2 * x * Hn - 2 * n * Hnm1);
|
||||
}
|
||||
|
||||
namespace detail{
|
||||
|
||||
// Implement Hermite polynomials via recurrance:
|
||||
template <class T>
|
||||
T hermite_imp(unsigned n, T x)
|
||||
{
|
||||
T p0 = 1;
|
||||
T p1 = 2 * x;
|
||||
|
||||
if(n == 0)
|
||||
return p0;
|
||||
|
||||
unsigned c = 1;
|
||||
|
||||
while(c < n)
|
||||
{
|
||||
std::swap(p0, p1);
|
||||
p1 = hermite_next(c, x, p0, p1);
|
||||
++c;
|
||||
}
|
||||
return p1;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class T, class Policy>
|
||||
inline typename tools::promote_args<T>::type
|
||||
hermite(unsigned n, T x, const Policy&)
|
||||
{
|
||||
typedef typename tools::promote_args<T>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(detail::hermite_imp(n, static_cast<value_type>(x)), "boost::math::hermite<%1%>(unsigned, %1%)");
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typename tools::promote_args<T>::type
|
||||
hermite(unsigned n, T x)
|
||||
{
|
||||
return boost::math::hermite(n, x, policies::policy<>());
|
||||
}
|
||||
|
||||
} // namespace math
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_MATH_SPECIAL_HERMITE_HPP
|
||||
|
||||
|
||||
|
||||
87
code_isotrope/boost/math/special_functions/heuman_lambda.hpp
Executable file
87
code_isotrope/boost/math/special_functions/heuman_lambda.hpp
Executable file
@@ -0,0 +1,87 @@
|
||||
// Copyright (c) 2015 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_ELLINT_HL_HPP
|
||||
#define BOOST_MATH_ELLINT_HL_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/math/special_functions/ellint_rj.hpp>
|
||||
#include <boost/math/special_functions/ellint_rj.hpp>
|
||||
#include <boost/math/special_functions/ellint_1.hpp>
|
||||
#include <boost/math/special_functions/jacobi_zeta.hpp>
|
||||
#include <boost/math/constants/constants.hpp>
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
#include <boost/math/tools/workaround.hpp>
|
||||
|
||||
// Elliptic integral the Jacobi Zeta function.
|
||||
|
||||
namespace boost { namespace math {
|
||||
|
||||
namespace detail{
|
||||
|
||||
// Elliptic integral - Jacobi Zeta
|
||||
template <typename T, typename Policy>
|
||||
T heuman_lambda_imp(T phi, T k, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
using namespace boost::math::tools;
|
||||
using namespace boost::math::constants;
|
||||
|
||||
const char* function = "boost::math::heuman_lambda<%1%>(%1%, %1%)";
|
||||
|
||||
if(fabs(k) > 1)
|
||||
return policies::raise_domain_error<T>(function, "We require |k| <= 1 but got k = %1%", k, pol);
|
||||
|
||||
T result;
|
||||
T sinp = sin(phi);
|
||||
T cosp = cos(phi);
|
||||
T s2 = sinp * sinp;
|
||||
T k2 = k * k;
|
||||
T kp = 1 - k2;
|
||||
T delta = sqrt(1 - (kp * s2));
|
||||
if(fabs(phi) <= constants::half_pi<T>())
|
||||
{
|
||||
result = kp * sinp * cosp / (delta * constants::half_pi<T>());
|
||||
result *= ellint_rf_imp(T(0), kp, T(1), pol) + k2 * ellint_rj(T(0), kp, T(1), T(1 - k2 / (delta * delta)), pol) / (3 * delta * delta);
|
||||
}
|
||||
else
|
||||
{
|
||||
T rkp = sqrt(kp);
|
||||
T ratio;
|
||||
if(rkp == 1)
|
||||
{
|
||||
return policies::raise_domain_error<T>(function, "When 1-k^2 == 1 then phi must be < Pi/2, but got phi = %1%", phi, pol);
|
||||
}
|
||||
else
|
||||
ratio = ellint_f_imp(phi, rkp, pol) / ellint_k_imp(rkp, pol);
|
||||
result = ratio + ellint_k_imp(k, pol) * jacobi_zeta_imp(phi, rkp, pol) / constants::half_pi<T>();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // detail
|
||||
|
||||
template <class T1, class T2, class Policy>
|
||||
inline typename tools::promote_args<T1, T2>::type heuman_lambda(T1 k, T2 phi, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T1, T2>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(detail::heuman_lambda_imp(static_cast<value_type>(phi), static_cast<value_type>(k), pol), "boost::math::heuman_lambda<%1%>(%1%,%1%)");
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
inline typename tools::promote_args<T1, T2>::type heuman_lambda(T1 k, T2 phi)
|
||||
{
|
||||
return boost::math::heuman_lambda(k, phi, policies::policy<>());
|
||||
}
|
||||
|
||||
}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_ELLINT_D_HPP
|
||||
|
||||
86
code_isotrope/boost/math/special_functions/hypot.hpp
Executable file
86
code_isotrope/boost/math/special_functions/hypot.hpp
Executable file
@@ -0,0 +1,86 @@
|
||||
// (C) Copyright John Maddock 2005-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_HYPOT_INCLUDED
|
||||
#define BOOST_MATH_HYPOT_INCLUDED
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/tools/config.hpp>
|
||||
#include <boost/math/tools/precision.hpp>
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/config/no_tr1/cmath.hpp>
|
||||
#include <algorithm> // for swap
|
||||
|
||||
#ifdef BOOST_NO_STDC_NAMESPACE
|
||||
namespace std{ using ::sqrt; using ::fabs; }
|
||||
#endif
|
||||
|
||||
namespace boost{ namespace math{ namespace detail{
|
||||
|
||||
template <class T, class Policy>
|
||||
T hypot_imp(T x, T y, const Policy& pol)
|
||||
{
|
||||
//
|
||||
// Normalize x and y, so that both are positive and x >= y:
|
||||
//
|
||||
using std::fabs; using std::sqrt; // ADL of std names
|
||||
|
||||
x = fabs(x);
|
||||
y = fabs(y);
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4127)
|
||||
#endif
|
||||
// special case, see C99 Annex F:
|
||||
if(std::numeric_limits<T>::has_infinity
|
||||
&& ((x == std::numeric_limits<T>::infinity())
|
||||
|| (y == std::numeric_limits<T>::infinity())))
|
||||
return policies::raise_overflow_error<T>("boost::math::hypot<%1%>(%1%,%1%)", 0, pol);
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
if(y > x)
|
||||
(std::swap)(x, y);
|
||||
|
||||
if(x * tools::epsilon<T>() >= y)
|
||||
return x;
|
||||
|
||||
T rat = y / x;
|
||||
return x * sqrt(1 + rat*rat);
|
||||
} // template <class T> T hypot(T x, T y)
|
||||
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
inline typename tools::promote_args<T1, T2>::type
|
||||
hypot(T1 x, T2 y)
|
||||
{
|
||||
typedef typename tools::promote_args<T1, T2>::type result_type;
|
||||
return detail::hypot_imp(
|
||||
static_cast<result_type>(x), static_cast<result_type>(y), policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T1, class T2, class Policy>
|
||||
inline typename tools::promote_args<T1, T2>::type
|
||||
hypot(T1 x, T2 y, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T1, T2>::type result_type;
|
||||
return detail::hypot_imp(
|
||||
static_cast<result_type>(x), static_cast<result_type>(y), pol);
|
||||
}
|
||||
|
||||
} // namespace math
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_MATH_HYPOT_INCLUDED
|
||||
|
||||
|
||||
|
||||
321
code_isotrope/boost/math/special_functions/jacobi_elliptic.hpp
Executable file
321
code_isotrope/boost/math/special_functions/jacobi_elliptic.hpp
Executable file
@@ -0,0 +1,321 @@
|
||||
// Copyright John Maddock 2012.
|
||||
// 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_JACOBI_ELLIPTIC_HPP
|
||||
#define BOOST_MATH_JACOBI_ELLIPTIC_HPP
|
||||
|
||||
#include <boost/math/tools/precision.hpp>
|
||||
#include <boost/math/tools/promotion.hpp>
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
|
||||
namespace boost{ namespace math{
|
||||
|
||||
namespace detail{
|
||||
|
||||
template <class T, class Policy>
|
||||
T jacobi_recurse(const T& x, const T& k, T anm1, T bnm1, unsigned N, T* pTn, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
++N;
|
||||
T Tn;
|
||||
T cn = (anm1 - bnm1) / 2;
|
||||
T an = (anm1 + bnm1) / 2;
|
||||
if(cn < policies::get_epsilon<T, Policy>())
|
||||
{
|
||||
Tn = ldexp(T(1), (int)N) * x * an;
|
||||
}
|
||||
else
|
||||
Tn = jacobi_recurse<T>(x, k, an, sqrt(anm1 * bnm1), N, 0, pol);
|
||||
if(pTn)
|
||||
*pTn = Tn;
|
||||
return (Tn + asin((cn / an) * sin(Tn))) / 2;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
T jacobi_imp(const T& x, const T& k, T* cn, T* dn, const Policy& pol, const char* function)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
if(k < 0)
|
||||
{
|
||||
*cn = policies::raise_domain_error<T>(function, "Modulus k must be positive but got %1%.", k, pol);
|
||||
*dn = *cn;
|
||||
return *cn;
|
||||
}
|
||||
if(k > 1)
|
||||
{
|
||||
T xp = x * k;
|
||||
T kp = 1 / k;
|
||||
T snp, cnp, dnp;
|
||||
snp = jacobi_imp(xp, kp, &cnp, &dnp, pol, function);
|
||||
*cn = dnp;
|
||||
*dn = cnp;
|
||||
return snp * kp;
|
||||
}
|
||||
//
|
||||
// Special cases first:
|
||||
//
|
||||
if(x == 0)
|
||||
{
|
||||
*cn = *dn = 1;
|
||||
return 0;
|
||||
}
|
||||
if(k == 0)
|
||||
{
|
||||
*cn = cos(x);
|
||||
*dn = 1;
|
||||
return sin(x);
|
||||
}
|
||||
if(k == 1)
|
||||
{
|
||||
*cn = *dn = 1 / cosh(x);
|
||||
return tanh(x);
|
||||
}
|
||||
//
|
||||
// Asymptotic forms from A&S 16.13:
|
||||
//
|
||||
if(k < tools::forth_root_epsilon<T>())
|
||||
{
|
||||
T su = sin(x);
|
||||
T cu = cos(x);
|
||||
T m = k * k;
|
||||
*dn = 1 - m * su * su / 2;
|
||||
*cn = cu + m * (x - su * cu) * su / 4;
|
||||
return su - m * (x - su * cu) * cu / 4;
|
||||
}
|
||||
/* Can't get this to work to adequate precision - disabled for now...
|
||||
//
|
||||
// Asymptotic forms from A&S 16.15:
|
||||
//
|
||||
if(k > 1 - tools::root_epsilon<T>())
|
||||
{
|
||||
T tu = tanh(x);
|
||||
T su = sinh(x);
|
||||
T cu = cosh(x);
|
||||
T sec = 1 / cu;
|
||||
T kp = 1 - k;
|
||||
T m1 = 2 * kp - kp * kp;
|
||||
*dn = sec + m1 * (su * cu + x) * tu * sec / 4;
|
||||
*cn = sec - m1 * (su * cu - x) * tu * sec / 4;
|
||||
T sn = tu;
|
||||
T sn2 = m1 * (x * sec * sec - tu) / 4;
|
||||
T sn3 = (72 * x * cu + 4 * (8 * x * x - 5) * su - 19 * sinh(3 * x) + sinh(5 * x)) * sec * sec * sec * m1 * m1 / 512;
|
||||
return sn + sn2 - sn3;
|
||||
}*/
|
||||
T T1;
|
||||
T kc = 1 - k;
|
||||
T k_prime = k < 0.5 ? T(sqrt(1 - k * k)) : T(sqrt(2 * kc - kc * kc));
|
||||
T T0 = jacobi_recurse(x, k, T(1), k_prime, 0, &T1, pol);
|
||||
*cn = cos(T0);
|
||||
*dn = cos(T0) / cos(T1 - T0);
|
||||
return sin(T0);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class T, class U, class V, class Policy>
|
||||
inline typename tools::promote_args<T, U, V>::type jacobi_elliptic(T k, U theta, V* pcn, V* pdn, const Policy&)
|
||||
{
|
||||
BOOST_FPU_EXCEPTION_GUARD
|
||||
typedef typename tools::promote_args<T>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
typedef typename policies::normalise<
|
||||
Policy,
|
||||
policies::promote_float<false>,
|
||||
policies::promote_double<false>,
|
||||
policies::discrete_quantile<>,
|
||||
policies::assert_undefined<> >::type forwarding_policy;
|
||||
|
||||
static const char* function = "boost::math::jacobi_elliptic<%1%>(%1%)";
|
||||
|
||||
value_type sn, cn, dn;
|
||||
sn = detail::jacobi_imp<value_type>(static_cast<value_type>(theta), static_cast<value_type>(k), &cn, &dn, forwarding_policy(), function);
|
||||
if(pcn)
|
||||
*pcn = policies::checked_narrowing_cast<result_type, Policy>(cn, function);
|
||||
if(pdn)
|
||||
*pdn = policies::checked_narrowing_cast<result_type, Policy>(dn, function);
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(sn, function);;
|
||||
}
|
||||
|
||||
template <class T, class U, class V>
|
||||
inline typename tools::promote_args<T, U, V>::type jacobi_elliptic(T k, U theta, V* pcn, V* pdn)
|
||||
{
|
||||
return jacobi_elliptic(k, theta, pcn, pdn, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class U, class T, class Policy>
|
||||
inline typename tools::promote_args<T, U>::type jacobi_sn(U k, T theta, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T, U>::type result_type;
|
||||
return jacobi_elliptic(static_cast<result_type>(k), static_cast<result_type>(theta), static_cast<result_type*>(0), static_cast<result_type*>(0), pol);
|
||||
}
|
||||
|
||||
template <class U, class T>
|
||||
inline typename tools::promote_args<T, U>::type jacobi_sn(U k, T theta)
|
||||
{
|
||||
return jacobi_sn(k, theta, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T, class U, class Policy>
|
||||
inline typename tools::promote_args<T, U>::type jacobi_cn(T k, U theta, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T, U>::type result_type;
|
||||
result_type cn;
|
||||
jacobi_elliptic(static_cast<result_type>(k), static_cast<result_type>(theta), &cn, static_cast<result_type*>(0), pol);
|
||||
return cn;
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
inline typename tools::promote_args<T, U>::type jacobi_cn(T k, U theta)
|
||||
{
|
||||
return jacobi_cn(k, theta, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T, class U, class Policy>
|
||||
inline typename tools::promote_args<T, U>::type jacobi_dn(T k, U theta, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T, U>::type result_type;
|
||||
result_type dn;
|
||||
jacobi_elliptic(static_cast<result_type>(k), static_cast<result_type>(theta), static_cast<result_type*>(0), &dn, pol);
|
||||
return dn;
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
inline typename tools::promote_args<T, U>::type jacobi_dn(T k, U theta)
|
||||
{
|
||||
return jacobi_dn(k, theta, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T, class U, class Policy>
|
||||
inline typename tools::promote_args<T, U>::type jacobi_cd(T k, U theta, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T, U>::type result_type;
|
||||
result_type cn, dn;
|
||||
jacobi_elliptic(static_cast<result_type>(k), static_cast<result_type>(theta), &cn, &dn, pol);
|
||||
return cn / dn;
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
inline typename tools::promote_args<T, U>::type jacobi_cd(T k, U theta)
|
||||
{
|
||||
return jacobi_cd(k, theta, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T, class U, class Policy>
|
||||
inline typename tools::promote_args<T, U>::type jacobi_dc(T k, U theta, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T, U>::type result_type;
|
||||
result_type cn, dn;
|
||||
jacobi_elliptic(static_cast<result_type>(k), static_cast<result_type>(theta), &cn, &dn, pol);
|
||||
return dn / cn;
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
inline typename tools::promote_args<T, U>::type jacobi_dc(T k, U theta)
|
||||
{
|
||||
return jacobi_dc(k, theta, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T, class U, class Policy>
|
||||
inline typename tools::promote_args<T, U>::type jacobi_ns(T k, U theta, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T, U>::type result_type;
|
||||
return 1 / jacobi_elliptic(static_cast<result_type>(k), static_cast<result_type>(theta), static_cast<result_type*>(0), static_cast<result_type*>(0), pol);
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
inline typename tools::promote_args<T, U>::type jacobi_ns(T k, U theta)
|
||||
{
|
||||
return jacobi_ns(k, theta, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T, class U, class Policy>
|
||||
inline typename tools::promote_args<T, U>::type jacobi_sd(T k, U theta, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T, U>::type result_type;
|
||||
result_type sn, dn;
|
||||
sn = jacobi_elliptic(static_cast<result_type>(k), static_cast<result_type>(theta), static_cast<result_type*>(0), &dn, pol);
|
||||
return sn / dn;
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
inline typename tools::promote_args<T, U>::type jacobi_sd(T k, U theta)
|
||||
{
|
||||
return jacobi_sd(k, theta, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T, class U, class Policy>
|
||||
inline typename tools::promote_args<T, U>::type jacobi_ds(T k, U theta, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T, U>::type result_type;
|
||||
result_type sn, dn;
|
||||
sn = jacobi_elliptic(static_cast<result_type>(k), static_cast<result_type>(theta), static_cast<result_type*>(0), &dn, pol);
|
||||
return dn / sn;
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
inline typename tools::promote_args<T, U>::type jacobi_ds(T k, U theta)
|
||||
{
|
||||
return jacobi_ds(k, theta, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T, class U, class Policy>
|
||||
inline typename tools::promote_args<T, U>::type jacobi_nc(T k, U theta, const Policy& pol)
|
||||
{
|
||||
return 1 / jacobi_cn(k, theta, pol);
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
inline typename tools::promote_args<T, U>::type jacobi_nc(T k, U theta)
|
||||
{
|
||||
return jacobi_nc(k, theta, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T, class U, class Policy>
|
||||
inline typename tools::promote_args<T, U>::type jacobi_nd(T k, U theta, const Policy& pol)
|
||||
{
|
||||
return 1 / jacobi_dn(k, theta, pol);
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
inline typename tools::promote_args<T, U>::type jacobi_nd(T k, U theta)
|
||||
{
|
||||
return jacobi_nd(k, theta, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T, class U, class Policy>
|
||||
inline typename tools::promote_args<T, U>::type jacobi_sc(T k, U theta, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T, U>::type result_type;
|
||||
result_type sn, cn;
|
||||
sn = jacobi_elliptic(static_cast<result_type>(k), static_cast<result_type>(theta), &cn, static_cast<result_type*>(0), pol);
|
||||
return sn / cn;
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
inline typename tools::promote_args<T, U>::type jacobi_sc(T k, U theta)
|
||||
{
|
||||
return jacobi_sc(k, theta, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T, class U, class Policy>
|
||||
inline typename tools::promote_args<T, U>::type jacobi_cs(T k, U theta, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T, U>::type result_type;
|
||||
result_type sn, cn;
|
||||
sn = jacobi_elliptic(static_cast<result_type>(k), static_cast<result_type>(theta), &cn, static_cast<result_type*>(0), pol);
|
||||
return cn / sn;
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
inline typename tools::promote_args<T, U>::type jacobi_cs(T k, U theta)
|
||||
{
|
||||
return jacobi_cs(k, theta, policies::policy<>());
|
||||
}
|
||||
|
||||
}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_JACOBI_ELLIPTIC_HPP
|
||||
74
code_isotrope/boost/math/special_functions/jacobi_zeta.hpp
Executable file
74
code_isotrope/boost/math/special_functions/jacobi_zeta.hpp
Executable file
@@ -0,0 +1,74 @@
|
||||
// Copyright (c) 2015 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_ELLINT_JZ_HPP
|
||||
#define BOOST_MATH_ELLINT_JZ_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/math/special_functions/ellint_1.hpp>
|
||||
#include <boost/math/special_functions/ellint_rj.hpp>
|
||||
#include <boost/math/constants/constants.hpp>
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
#include <boost/math/tools/workaround.hpp>
|
||||
|
||||
// Elliptic integral the Jacobi Zeta function.
|
||||
|
||||
namespace boost { namespace math {
|
||||
|
||||
namespace detail{
|
||||
|
||||
// Elliptic integral - Jacobi Zeta
|
||||
template <typename T, typename Policy>
|
||||
T jacobi_zeta_imp(T phi, T k, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
using namespace boost::math::tools;
|
||||
using namespace boost::math::constants;
|
||||
|
||||
bool invert = false;
|
||||
if(phi < 0)
|
||||
{
|
||||
phi = fabs(phi);
|
||||
invert = true;
|
||||
}
|
||||
|
||||
T result;
|
||||
T sinp = sin(phi);
|
||||
T cosp = cos(phi);
|
||||
T s2 = sinp * sinp;
|
||||
T k2 = k * k;
|
||||
T kp = 1 - k2;
|
||||
if(k == 1)
|
||||
result = sinp * (boost::math::sign)(cosp); // We get here by simplifying JacobiZeta[w, 1] in Mathematica, and the fact that 0 <= phi.
|
||||
else
|
||||
result = k2 * sinp * cosp * sqrt(1 - k2 * s2) * ellint_rj_imp(T(0), kp, T(1), T(1 - k2 * s2), pol) / (3 * ellint_k_imp(k, pol));
|
||||
return invert ? T(-result) : result;
|
||||
}
|
||||
|
||||
} // detail
|
||||
|
||||
template <class T1, class T2, class Policy>
|
||||
inline typename tools::promote_args<T1, T2>::type jacobi_zeta(T1 k, T2 phi, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T1, T2>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(detail::jacobi_zeta_imp(static_cast<value_type>(phi), static_cast<value_type>(k), pol), "boost::math::jacobi_zeta<%1%>(%1%,%1%)");
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
inline typename tools::promote_args<T1, T2>::type jacobi_zeta(T1 k, T2 phi)
|
||||
{
|
||||
return boost::math::jacobi_zeta(k, phi, policies::policy<>());
|
||||
}
|
||||
|
||||
}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_ELLINT_D_HPP
|
||||
|
||||
139
code_isotrope/boost/math/special_functions/laguerre.hpp
Executable file
139
code_isotrope/boost/math/special_functions/laguerre.hpp
Executable file
@@ -0,0 +1,139 @@
|
||||
|
||||
// (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_LAGUERRE_HPP
|
||||
#define BOOST_MATH_SPECIAL_LAGUERRE_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/math/tools/config.hpp>
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
|
||||
namespace boost{
|
||||
namespace math{
|
||||
|
||||
// Recurrance relation for Laguerre polynomials:
|
||||
template <class T1, class T2, class T3>
|
||||
inline typename tools::promote_args<T1, T2, T3>::type
|
||||
laguerre_next(unsigned n, T1 x, T2 Ln, T3 Lnm1)
|
||||
{
|
||||
typedef typename tools::promote_args<T1, T2, T3>::type result_type;
|
||||
return ((2 * n + 1 - result_type(x)) * result_type(Ln) - n * result_type(Lnm1)) / (n + 1);
|
||||
}
|
||||
|
||||
namespace detail{
|
||||
|
||||
// Implement Laguerre polynomials via recurrance:
|
||||
template <class T>
|
||||
T laguerre_imp(unsigned n, T x)
|
||||
{
|
||||
T p0 = 1;
|
||||
T p1 = 1 - x;
|
||||
|
||||
if(n == 0)
|
||||
return p0;
|
||||
|
||||
unsigned c = 1;
|
||||
|
||||
while(c < n)
|
||||
{
|
||||
std::swap(p0, p1);
|
||||
p1 = laguerre_next(c, x, p0, p1);
|
||||
++c;
|
||||
}
|
||||
return p1;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline typename tools::promote_args<T>::type
|
||||
laguerre(unsigned n, T x, const Policy&, const mpl::true_&)
|
||||
{
|
||||
typedef typename tools::promote_args<T>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(detail::laguerre_imp(n, static_cast<value_type>(x)), "boost::math::laguerre<%1%>(unsigned, %1%)");
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typename tools::promote_args<T>::type
|
||||
laguerre(unsigned n, unsigned m, T x, const mpl::false_&)
|
||||
{
|
||||
return boost::math::laguerre(n, m, x, policies::policy<>());
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class T>
|
||||
inline typename tools::promote_args<T>::type
|
||||
laguerre(unsigned n, T x)
|
||||
{
|
||||
return laguerre(n, x, policies::policy<>());
|
||||
}
|
||||
|
||||
// Recurrence for associated polynomials:
|
||||
template <class T1, class T2, class T3>
|
||||
inline typename tools::promote_args<T1, T2, T3>::type
|
||||
laguerre_next(unsigned n, unsigned l, T1 x, T2 Pl, T3 Plm1)
|
||||
{
|
||||
typedef typename tools::promote_args<T1, T2, T3>::type result_type;
|
||||
return ((2 * n + l + 1 - result_type(x)) * result_type(Pl) - (n + l) * result_type(Plm1)) / (n+1);
|
||||
}
|
||||
|
||||
namespace detail{
|
||||
// Laguerre Associated Polynomial:
|
||||
template <class T, class Policy>
|
||||
T laguerre_imp(unsigned n, unsigned m, T x, const Policy& pol)
|
||||
{
|
||||
// Special cases:
|
||||
if(m == 0)
|
||||
return boost::math::laguerre(n, x, pol);
|
||||
|
||||
T p0 = 1;
|
||||
|
||||
if(n == 0)
|
||||
return p0;
|
||||
|
||||
T p1 = m + 1 - x;
|
||||
|
||||
unsigned c = 1;
|
||||
|
||||
while(c < n)
|
||||
{
|
||||
std::swap(p0, p1);
|
||||
p1 = laguerre_next(c, m, x, p0, p1);
|
||||
++c;
|
||||
}
|
||||
return p1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline typename tools::promote_args<T>::type
|
||||
laguerre(unsigned n, unsigned m, T x, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(detail::laguerre_imp(n, m, static_cast<value_type>(x), pol), "boost::math::laguerre<%1%>(unsigned, unsigned, %1%)");
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
inline typename laguerre_result<T1, T2>::type
|
||||
laguerre(unsigned n, T1 m, T2 x)
|
||||
{
|
||||
typedef typename policies::is_policy<T2>::type tag_type;
|
||||
return detail::laguerre(n, m, x, tag_type());
|
||||
}
|
||||
|
||||
} // namespace math
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_MATH_SPECIAL_LAGUERRE_HPP
|
||||
|
||||
|
||||
|
||||
2176
code_isotrope/boost/math/special_functions/lambert_w.hpp
Executable file
2176
code_isotrope/boost/math/special_functions/lambert_w.hpp
Executable file
File diff suppressed because it is too large
Load Diff
1296
code_isotrope/boost/math/special_functions/lanczos.hpp
Executable file
1296
code_isotrope/boost/math/special_functions/lanczos.hpp
Executable file
File diff suppressed because it is too large
Load Diff
373
code_isotrope/boost/math/special_functions/legendre.hpp
Executable file
373
code_isotrope/boost/math/special_functions/legendre.hpp
Executable file
@@ -0,0 +1,373 @@
|
||||
|
||||
// (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_LEGENDRE_HPP
|
||||
#define BOOST_MATH_SPECIAL_LEGENDRE_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/math/special_functions/factorials.hpp>
|
||||
#include <boost/math/tools/roots.hpp>
|
||||
#include <boost/math/tools/config.hpp>
|
||||
|
||||
namespace boost{
|
||||
namespace math{
|
||||
|
||||
// Recurrance relation for legendre P and Q polynomials:
|
||||
template <class T1, class T2, class T3>
|
||||
inline typename tools::promote_args<T1, T2, T3>::type
|
||||
legendre_next(unsigned l, T1 x, T2 Pl, T3 Plm1)
|
||||
{
|
||||
typedef typename tools::promote_args<T1, T2, T3>::type result_type;
|
||||
return ((2 * l + 1) * result_type(x) * result_type(Pl) - l * result_type(Plm1)) / (l + 1);
|
||||
}
|
||||
|
||||
namespace detail{
|
||||
|
||||
// Implement Legendre P and Q polynomials via recurrance:
|
||||
template <class T, class Policy>
|
||||
T legendre_imp(unsigned l, T x, const Policy& pol, bool second = false)
|
||||
{
|
||||
static const char* function = "boost::math::legrendre_p<%1%>(unsigned, %1%)";
|
||||
// Error handling:
|
||||
if((x < -1) || (x > 1))
|
||||
return policies::raise_domain_error<T>(
|
||||
function,
|
||||
"The Legendre Polynomial is defined for"
|
||||
" -1 <= x <= 1, but got x = %1%.", x, pol);
|
||||
|
||||
T p0, p1;
|
||||
if(second)
|
||||
{
|
||||
// A solution of the second kind (Q):
|
||||
p0 = (boost::math::log1p(x, pol) - boost::math::log1p(-x, pol)) / 2;
|
||||
p1 = x * p0 - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// A solution of the first kind (P):
|
||||
p0 = 1;
|
||||
p1 = x;
|
||||
}
|
||||
if(l == 0)
|
||||
return p0;
|
||||
|
||||
unsigned n = 1;
|
||||
|
||||
while(n < l)
|
||||
{
|
||||
std::swap(p0, p1);
|
||||
p1 = boost::math::legendre_next(n, x, p0, p1);
|
||||
++n;
|
||||
}
|
||||
return p1;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
T legendre_p_prime_imp(unsigned l, T x, const Policy& pol, T* Pn
|
||||
#ifdef BOOST_NO_CXX11_NULLPTR
|
||||
= 0
|
||||
#else
|
||||
= nullptr
|
||||
#endif
|
||||
)
|
||||
{
|
||||
static const char* function = "boost::math::legrendre_p_prime<%1%>(unsigned, %1%)";
|
||||
// Error handling:
|
||||
if ((x < -1) || (x > 1))
|
||||
return policies::raise_domain_error<T>(
|
||||
function,
|
||||
"The Legendre Polynomial is defined for"
|
||||
" -1 <= x <= 1, but got x = %1%.", x, pol);
|
||||
|
||||
if (l == 0)
|
||||
{
|
||||
if (Pn)
|
||||
{
|
||||
*Pn = 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
T p0 = 1;
|
||||
T p1 = x;
|
||||
T p_prime;
|
||||
bool odd = l & 1;
|
||||
// If the order is odd, we sum all the even polynomials:
|
||||
if (odd)
|
||||
{
|
||||
p_prime = p0;
|
||||
}
|
||||
else // Otherwise we sum the odd polynomials * (2n+1)
|
||||
{
|
||||
p_prime = 3*p1;
|
||||
}
|
||||
|
||||
unsigned n = 1;
|
||||
while(n < l - 1)
|
||||
{
|
||||
std::swap(p0, p1);
|
||||
p1 = boost::math::legendre_next(n, x, p0, p1);
|
||||
++n;
|
||||
if (odd)
|
||||
{
|
||||
p_prime += (2*n+1)*p1;
|
||||
odd = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
odd = true;
|
||||
}
|
||||
}
|
||||
// This allows us to evaluate the derivative and the function for the same cost.
|
||||
if (Pn)
|
||||
{
|
||||
std::swap(p0, p1);
|
||||
*Pn = boost::math::legendre_next(n, x, p0, p1);
|
||||
}
|
||||
return p_prime;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
struct legendre_p_zero_func
|
||||
{
|
||||
int n;
|
||||
const Policy& pol;
|
||||
|
||||
legendre_p_zero_func(int n_, const Policy& p) : n(n_), pol(p) {}
|
||||
|
||||
std::pair<T, T> operator()(T x) const
|
||||
{
|
||||
T Pn;
|
||||
T Pn_prime = detail::legendre_p_prime_imp(n, x, pol, &Pn);
|
||||
return std::pair<T, T>(Pn, Pn_prime);
|
||||
};
|
||||
};
|
||||
|
||||
template <class T, class Policy>
|
||||
std::vector<T> legendre_p_zeros_imp(int n, const Policy& pol)
|
||||
{
|
||||
using std::cos;
|
||||
using std::sin;
|
||||
using std::ceil;
|
||||
using std::sqrt;
|
||||
using boost::math::constants::pi;
|
||||
using boost::math::constants::half;
|
||||
using boost::math::tools::newton_raphson_iterate;
|
||||
|
||||
BOOST_ASSERT(n >= 0);
|
||||
std::vector<T> zeros;
|
||||
if (n == 0)
|
||||
{
|
||||
// There are no zeros of P_0(x) = 1.
|
||||
return zeros;
|
||||
}
|
||||
int k;
|
||||
if (n & 1)
|
||||
{
|
||||
zeros.resize((n-1)/2 + 1, std::numeric_limits<T>::quiet_NaN());
|
||||
zeros[0] = 0;
|
||||
k = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
zeros.resize(n/2, std::numeric_limits<T>::quiet_NaN());
|
||||
k = 0;
|
||||
}
|
||||
T half_n = ceil(n*half<T>());
|
||||
|
||||
while (k < (int)zeros.size())
|
||||
{
|
||||
// Bracket the root: Szego:
|
||||
// Gabriel Szego, Inequalities for the Zeros of Legendre Polynomials and Related Functions, Transactions of the American Mathematical Society, Vol. 39, No. 1 (1936)
|
||||
T theta_nk = ((half_n - half<T>()*half<T>() - static_cast<T>(k))*pi<T>())/(static_cast<T>(n)+half<T>());
|
||||
T lower_bound = cos( (half_n - static_cast<T>(k))*pi<T>()/static_cast<T>(n + 1));
|
||||
T cos_nk = cos(theta_nk);
|
||||
T upper_bound = cos_nk;
|
||||
// First guess follows from:
|
||||
// F. G. Tricomi, Sugli zeri dei polinomi sferici ed ultrasferici, Ann. Mat. Pura Appl., 31 (1950), pp. 93-97;
|
||||
T inv_n_sq = 1/static_cast<T>(n*n);
|
||||
T sin_nk = sin(theta_nk);
|
||||
T x_nk_guess = (1 - inv_n_sq/static_cast<T>(8) + inv_n_sq /static_cast<T>(8*n) - (inv_n_sq*inv_n_sq/384)*(39 - 28 / (sin_nk*sin_nk) ) )*cos_nk;
|
||||
|
||||
boost::uintmax_t number_of_iterations = policies::get_max_root_iterations<Policy>();
|
||||
|
||||
legendre_p_zero_func<T, Policy> f(n, pol);
|
||||
|
||||
const T x_nk = newton_raphson_iterate(f, x_nk_guess,
|
||||
lower_bound, upper_bound,
|
||||
policies::digits<T, Policy>(),
|
||||
number_of_iterations);
|
||||
|
||||
BOOST_ASSERT(lower_bound < x_nk);
|
||||
BOOST_ASSERT(upper_bound > x_nk);
|
||||
zeros[k] = x_nk;
|
||||
++k;
|
||||
}
|
||||
return zeros;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class T, class Policy>
|
||||
inline typename boost::enable_if_c<policies::is_policy<Policy>::value, typename tools::promote_args<T>::type>::type
|
||||
legendre_p(int l, T x, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
static const char* function = "boost::math::legendre_p<%1%>(unsigned, %1%)";
|
||||
if(l < 0)
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(detail::legendre_imp(-l-1, static_cast<value_type>(x), pol, false), function);
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(detail::legendre_imp(l, static_cast<value_type>(x), pol, false), function);
|
||||
}
|
||||
|
||||
|
||||
template <class T, class Policy>
|
||||
inline typename boost::enable_if_c<policies::is_policy<Policy>::value, typename tools::promote_args<T>::type>::type
|
||||
legendre_p_prime(int l, T x, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
static const char* function = "boost::math::legendre_p_prime<%1%>(unsigned, %1%)";
|
||||
if(l < 0)
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(detail::legendre_p_prime_imp(-l-1, static_cast<value_type>(x), pol), function);
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(detail::legendre_p_prime_imp(l, static_cast<value_type>(x), pol), function);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typename tools::promote_args<T>::type
|
||||
legendre_p(int l, T x)
|
||||
{
|
||||
return boost::math::legendre_p(l, x, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typename tools::promote_args<T>::type
|
||||
legendre_p_prime(int l, T x)
|
||||
{
|
||||
return boost::math::legendre_p_prime(l, x, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline std::vector<T> legendre_p_zeros(int l, const Policy& pol)
|
||||
{
|
||||
if(l < 0)
|
||||
return detail::legendre_p_zeros_imp<T>(-l-1, pol);
|
||||
|
||||
return detail::legendre_p_zeros_imp<T>(l, pol);
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
inline std::vector<T> legendre_p_zeros(int l)
|
||||
{
|
||||
return boost::math::legendre_p_zeros<T>(l, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline typename boost::enable_if_c<policies::is_policy<Policy>::value, typename tools::promote_args<T>::type>::type
|
||||
legendre_q(unsigned l, T x, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(detail::legendre_imp(l, static_cast<value_type>(x), pol, true), "boost::math::legendre_q<%1%>(unsigned, %1%)");
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typename tools::promote_args<T>::type
|
||||
legendre_q(unsigned l, T x)
|
||||
{
|
||||
return boost::math::legendre_q(l, x, policies::policy<>());
|
||||
}
|
||||
|
||||
// Recurrence for associated polynomials:
|
||||
template <class T1, class T2, class T3>
|
||||
inline typename tools::promote_args<T1, T2, T3>::type
|
||||
legendre_next(unsigned l, unsigned m, T1 x, T2 Pl, T3 Plm1)
|
||||
{
|
||||
typedef typename tools::promote_args<T1, T2, T3>::type result_type;
|
||||
return ((2 * l + 1) * result_type(x) * result_type(Pl) - (l + m) * result_type(Plm1)) / (l + 1 - m);
|
||||
}
|
||||
|
||||
namespace detail{
|
||||
// Legendre P associated polynomial:
|
||||
template <class T, class Policy>
|
||||
T legendre_p_imp(int l, int m, T x, T sin_theta_power, const Policy& pol)
|
||||
{
|
||||
// Error handling:
|
||||
if((x < -1) || (x > 1))
|
||||
return policies::raise_domain_error<T>(
|
||||
"boost::math::legendre_p<%1%>(int, int, %1%)",
|
||||
"The associated Legendre Polynomial is defined for"
|
||||
" -1 <= x <= 1, but got x = %1%.", x, pol);
|
||||
// Handle negative arguments first:
|
||||
if(l < 0)
|
||||
return legendre_p_imp(-l-1, m, x, sin_theta_power, pol);
|
||||
if(m < 0)
|
||||
{
|
||||
int sign = (m&1) ? -1 : 1;
|
||||
return sign * boost::math::tgamma_ratio(static_cast<T>(l+m+1), static_cast<T>(l+1-m), pol) * legendre_p_imp(l, -m, x, sin_theta_power, pol);
|
||||
}
|
||||
// Special cases:
|
||||
if(m > l)
|
||||
return 0;
|
||||
if(m == 0)
|
||||
return boost::math::legendre_p(l, x, pol);
|
||||
|
||||
T p0 = boost::math::double_factorial<T>(2 * m - 1, pol) * sin_theta_power;
|
||||
|
||||
if(m&1)
|
||||
p0 *= -1;
|
||||
if(m == l)
|
||||
return p0;
|
||||
|
||||
T p1 = x * (2 * m + 1) * p0;
|
||||
|
||||
int n = m + 1;
|
||||
|
||||
while(n < l)
|
||||
{
|
||||
std::swap(p0, p1);
|
||||
p1 = boost::math::legendre_next(n, m, x, p0, p1);
|
||||
++n;
|
||||
}
|
||||
return p1;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T legendre_p_imp(int l, int m, T x, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
// TODO: we really could use that mythical "pow1p" function here:
|
||||
return legendre_p_imp(l, m, x, static_cast<T>(pow(1 - x*x, T(abs(m))/2)), pol);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline typename tools::promote_args<T>::type
|
||||
legendre_p(int l, int m, T x, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(detail::legendre_p_imp(l, m, static_cast<value_type>(x), pol), "bost::math::legendre_p<%1%>(int, int, %1%)");
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typename tools::promote_args<T>::type
|
||||
legendre_p(int l, int m, T x)
|
||||
{
|
||||
return boost::math::legendre_p(l, m, x, policies::policy<>());
|
||||
}
|
||||
|
||||
} // namespace math
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_MATH_SPECIAL_LEGENDRE_HPP
|
||||
235
code_isotrope/boost/math/special_functions/legendre_stieltjes.hpp
Executable file
235
code_isotrope/boost/math/special_functions/legendre_stieltjes.hpp
Executable file
@@ -0,0 +1,235 @@
|
||||
// Copyright Nick Thompson 2017.
|
||||
// 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_LEGENDRE_STIELTJES_HPP
|
||||
#define BOOST_MATH_SPECIAL_LEGENDRE_STIELTJES_HPP
|
||||
|
||||
/*
|
||||
* Constructs the Legendre-Stieltjes polynomial of degree m.
|
||||
* The Legendre-Stieltjes polynomials are used to create extensions for Gaussian quadratures,
|
||||
* commonly called "Gauss-Konrod" quadratures.
|
||||
*
|
||||
* References:
|
||||
* Patterson, TNL. "The optimum addition of points to quadrature formulae." Mathematics of Computation 22.104 (1968): 847-856.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <boost/math/tools/roots.hpp>
|
||||
#include <boost/math/special_functions/legendre.hpp>
|
||||
|
||||
namespace boost{
|
||||
namespace math{
|
||||
|
||||
template<class Real>
|
||||
class legendre_stieltjes
|
||||
{
|
||||
public:
|
||||
legendre_stieltjes(size_t m)
|
||||
{
|
||||
if (m == 0)
|
||||
{
|
||||
throw std::domain_error("The Legendre-Stieltjes polynomial is defined for order m > 0.\n");
|
||||
}
|
||||
m_m = static_cast<int>(m);
|
||||
std::ptrdiff_t n = m - 1;
|
||||
std::ptrdiff_t q;
|
||||
std::ptrdiff_t r;
|
||||
bool odd = n & 1;
|
||||
if (odd)
|
||||
{
|
||||
q = 1;
|
||||
r = (n-1)/2 + 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
q = 0;
|
||||
r = n/2 + 1;
|
||||
}
|
||||
m_a.resize(r + 1);
|
||||
// We'll keep the ones-based indexing at the cost of storing a superfluous element
|
||||
// so that we can follow Patterson's notation exactly.
|
||||
m_a[r] = static_cast<Real>(1);
|
||||
// Make sure using the zero index is a bug:
|
||||
m_a[0] = std::numeric_limits<Real>::quiet_NaN();
|
||||
|
||||
for (std::ptrdiff_t k = 1; k < r; ++k)
|
||||
{
|
||||
Real ratio = 1;
|
||||
m_a[r - k] = 0;
|
||||
for (std::ptrdiff_t i = r + 1 - k; i <= r; ++i)
|
||||
{
|
||||
// See Patterson, equation 12
|
||||
std::ptrdiff_t num = (n - q + 2*(i + k - 1))*(n + q + 2*(k - i + 1))*(n-1-q+2*(i-k))*(2*(k+i-1) -1 -q -n);
|
||||
std::ptrdiff_t den = (n - q + 2*(i - k))*(2*(k + i - 1) - q - n)*(n + 1 + q + 2*(k - i))*(n - 1 - q + 2*(i + k));
|
||||
ratio *= static_cast<Real>(num)/static_cast<Real>(den);
|
||||
m_a[r - k] -= ratio*m_a[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Real norm_sq() const
|
||||
{
|
||||
Real t = 0;
|
||||
bool odd = m_m & 1;
|
||||
for (size_t i = 1; i < m_a.size(); ++i)
|
||||
{
|
||||
if(odd)
|
||||
{
|
||||
t += 2*m_a[i]*m_a[i]/static_cast<Real>(4*i-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
t += 2*m_a[i]*m_a[i]/static_cast<Real>(4*i-3);
|
||||
}
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
Real operator()(Real x) const
|
||||
{
|
||||
// Trivial implementation:
|
||||
// Em += m_a[i]*legendre_p(2*i - 1, x); m odd
|
||||
// Em += m_a[i]*legendre_p(2*i - 2, x); m even
|
||||
size_t r = m_a.size() - 1;
|
||||
Real p0 = 1;
|
||||
Real p1 = x;
|
||||
|
||||
Real Em;
|
||||
bool odd = m_m & 1;
|
||||
if (odd)
|
||||
{
|
||||
Em = m_a[1]*p1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Em = m_a[1]*p0;
|
||||
}
|
||||
|
||||
unsigned n = 1;
|
||||
for (size_t i = 2; i <= r; ++i)
|
||||
{
|
||||
std::swap(p0, p1);
|
||||
p1 = boost::math::legendre_next(n, x, p0, p1);
|
||||
++n;
|
||||
if (!odd)
|
||||
{
|
||||
Em += m_a[i]*p1;
|
||||
}
|
||||
std::swap(p0, p1);
|
||||
p1 = boost::math::legendre_next(n, x, p0, p1);
|
||||
++n;
|
||||
if(odd)
|
||||
{
|
||||
Em += m_a[i]*p1;
|
||||
}
|
||||
}
|
||||
return Em;
|
||||
}
|
||||
|
||||
|
||||
Real prime(Real x) const
|
||||
{
|
||||
Real Em_prime = 0;
|
||||
|
||||
for (size_t i = 1; i < m_a.size(); ++i)
|
||||
{
|
||||
if(m_m & 1)
|
||||
{
|
||||
Em_prime += m_a[i]*detail::legendre_p_prime_imp(static_cast<unsigned>(2*i - 1), x, policies::policy<>());
|
||||
}
|
||||
else
|
||||
{
|
||||
Em_prime += m_a[i]*detail::legendre_p_prime_imp(static_cast<unsigned>(2*i - 2), x, policies::policy<>());
|
||||
}
|
||||
}
|
||||
return Em_prime;
|
||||
}
|
||||
|
||||
std::vector<Real> zeros() const
|
||||
{
|
||||
using boost::math::constants::half;
|
||||
|
||||
std::vector<Real> stieltjes_zeros;
|
||||
std::vector<Real> legendre_zeros = legendre_p_zeros<Real>(m_m - 1);
|
||||
int k;
|
||||
if (m_m & 1)
|
||||
{
|
||||
stieltjes_zeros.resize(legendre_zeros.size() + 1, std::numeric_limits<Real>::quiet_NaN());
|
||||
stieltjes_zeros[0] = 0;
|
||||
k = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
stieltjes_zeros.resize(legendre_zeros.size(), std::numeric_limits<Real>::quiet_NaN());
|
||||
k = 0;
|
||||
}
|
||||
|
||||
while (k < (int)stieltjes_zeros.size())
|
||||
{
|
||||
Real lower_bound;
|
||||
Real upper_bound;
|
||||
if (m_m & 1)
|
||||
{
|
||||
lower_bound = legendre_zeros[k - 1];
|
||||
if (k == (int)legendre_zeros.size())
|
||||
{
|
||||
upper_bound = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
upper_bound = legendre_zeros[k];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lower_bound = legendre_zeros[k];
|
||||
if (k == (int)legendre_zeros.size() - 1)
|
||||
{
|
||||
upper_bound = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
upper_bound = legendre_zeros[k+1];
|
||||
}
|
||||
}
|
||||
|
||||
// The root bracketing is not very tight; to keep weird stuff from happening
|
||||
// in the Newton's method, let's tighten up the tolerance using a few bisections.
|
||||
boost::math::tools::eps_tolerance<Real> tol(6);
|
||||
auto g = [&](Real t) { return this->operator()(t); };
|
||||
auto p = boost::math::tools::bisect(g, lower_bound, upper_bound, tol);
|
||||
|
||||
Real x_nk_guess = p.first + (p.second - p.first)*half<Real>();
|
||||
boost::uintmax_t number_of_iterations = 500;
|
||||
|
||||
auto f = [&] (Real x) { Real Pn = this->operator()(x);
|
||||
Real Pn_prime = this->prime(x);
|
||||
return std::pair<Real, Real>(Pn, Pn_prime); };
|
||||
|
||||
const Real x_nk = boost::math::tools::newton_raphson_iterate(f, x_nk_guess,
|
||||
p.first, p.second,
|
||||
2*std::numeric_limits<Real>::digits10,
|
||||
number_of_iterations);
|
||||
|
||||
BOOST_ASSERT(p.first < x_nk);
|
||||
BOOST_ASSERT(x_nk < p.second);
|
||||
stieltjes_zeros[k] = x_nk;
|
||||
++k;
|
||||
}
|
||||
return stieltjes_zeros;
|
||||
}
|
||||
|
||||
private:
|
||||
// Coefficients of Legendre expansion
|
||||
std::vector<Real> m_a;
|
||||
int m_m;
|
||||
};
|
||||
|
||||
}}
|
||||
#endif
|
||||
509
code_isotrope/boost/math/special_functions/log1p.hpp
Executable file
509
code_isotrope/boost/math/special_functions/log1p.hpp
Executable file
@@ -0,0 +1,509 @@
|
||||
// (C) Copyright John Maddock 2005-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_LOG1P_INCLUDED
|
||||
#define BOOST_MATH_LOG1P_INCLUDED
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4702) // Unreachable code (release mode only warning)
|
||||
#endif
|
||||
|
||||
#include <boost/config/no_tr1/cmath.hpp>
|
||||
#include <math.h> // platform's ::log1p
|
||||
#include <boost/limits.hpp>
|
||||
#include <boost/math/tools/config.hpp>
|
||||
#include <boost/math/tools/series.hpp>
|
||||
#include <boost/math/tools/rational.hpp>
|
||||
#include <boost/math/tools/big_constant.hpp>
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
|
||||
#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
|
||||
# include <boost/static_assert.hpp>
|
||||
#else
|
||||
# include <boost/assert.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost{ namespace math{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
// Functor log1p_series returns the next term in the Taylor series
|
||||
// pow(-1, k-1)*pow(x, k) / k
|
||||
// each time that operator() is invoked.
|
||||
//
|
||||
template <class T>
|
||||
struct log1p_series
|
||||
{
|
||||
typedef T result_type;
|
||||
|
||||
log1p_series(T x)
|
||||
: k(0), m_mult(-x), m_prod(-1){}
|
||||
|
||||
T operator()()
|
||||
{
|
||||
m_prod *= m_mult;
|
||||
return m_prod / ++k;
|
||||
}
|
||||
|
||||
int count()const
|
||||
{
|
||||
return k;
|
||||
}
|
||||
|
||||
private:
|
||||
int k;
|
||||
const T m_mult;
|
||||
T m_prod;
|
||||
log1p_series(const log1p_series&);
|
||||
log1p_series& operator=(const log1p_series&);
|
||||
};
|
||||
|
||||
// Algorithm log1p is part of C99, but is not yet provided by many compilers.
|
||||
//
|
||||
// This version uses a Taylor series expansion for 0.5 > x > epsilon, which may
|
||||
// require up to std::numeric_limits<T>::digits+1 terms to be calculated.
|
||||
// It would be much more efficient to use the equivalence:
|
||||
// log(1+x) == (log(1+x) * x) / ((1-x) - 1)
|
||||
// Unfortunately many optimizing compilers make such a mess of this, that
|
||||
// it performs no better than log(1+x): which is to say not very well at all.
|
||||
//
|
||||
template <class T, class Policy>
|
||||
T log1p_imp(T const & x, const Policy& pol, const mpl::int_<0>&)
|
||||
{ // The function returns the natural logarithm of 1 + x.
|
||||
typedef typename tools::promote_args<T>::type result_type;
|
||||
BOOST_MATH_STD_USING
|
||||
|
||||
static const char* function = "boost::math::log1p<%1%>(%1%)";
|
||||
|
||||
if((x < -1) || (boost::math::isnan)(x))
|
||||
return policies::raise_domain_error<T>(
|
||||
function, "log1p(x) requires x > -1, but got x = %1%.", x, pol);
|
||||
if(x == -1)
|
||||
return -policies::raise_overflow_error<T>(
|
||||
function, 0, pol);
|
||||
|
||||
result_type a = abs(result_type(x));
|
||||
if(a > result_type(0.5f))
|
||||
return log(1 + result_type(x));
|
||||
// Note that without numeric_limits specialisation support,
|
||||
// epsilon just returns zero, and our "optimisation" will always fail:
|
||||
if(a < tools::epsilon<result_type>())
|
||||
return x;
|
||||
detail::log1p_series<result_type> s(x);
|
||||
boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) && !BOOST_WORKAROUND(__EDG_VERSION__, <= 245)
|
||||
result_type result = tools::sum_series(s, policies::get_epsilon<result_type, Policy>(), max_iter);
|
||||
#else
|
||||
result_type zero = 0;
|
||||
result_type result = tools::sum_series(s, policies::get_epsilon<result_type, Policy>(), max_iter, zero);
|
||||
#endif
|
||||
policies::check_series_iterations<T>(function, max_iter, pol);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
T log1p_imp(T const& x, const Policy& pol, const mpl::int_<53>&)
|
||||
{ // The function returns the natural logarithm of 1 + x.
|
||||
BOOST_MATH_STD_USING
|
||||
|
||||
static const char* function = "boost::math::log1p<%1%>(%1%)";
|
||||
|
||||
if(x < -1)
|
||||
return policies::raise_domain_error<T>(
|
||||
function, "log1p(x) requires x > -1, but got x = %1%.", x, pol);
|
||||
if(x == -1)
|
||||
return -policies::raise_overflow_error<T>(
|
||||
function, 0, pol);
|
||||
|
||||
T a = fabs(x);
|
||||
if(a > 0.5f)
|
||||
return log(1 + x);
|
||||
// Note that without numeric_limits specialisation support,
|
||||
// epsilon just returns zero, and our "optimisation" will always fail:
|
||||
if(a < tools::epsilon<T>())
|
||||
return x;
|
||||
|
||||
// Maximum Deviation Found: 1.846e-017
|
||||
// Expected Error Term: 1.843e-017
|
||||
// Maximum Relative Change in Control Points: 8.138e-004
|
||||
// Max Error found at double precision = 3.250766e-016
|
||||
static const T P[] = {
|
||||
0.15141069795941984e-16L,
|
||||
0.35495104378055055e-15L,
|
||||
0.33333333333332835L,
|
||||
0.99249063543365859L,
|
||||
1.1143969784156509L,
|
||||
0.58052937949269651L,
|
||||
0.13703234928513215L,
|
||||
0.011294864812099712L
|
||||
};
|
||||
static const T Q[] = {
|
||||
1L,
|
||||
3.7274719063011499L,
|
||||
5.5387948649720334L,
|
||||
4.159201143419005L,
|
||||
1.6423855110312755L,
|
||||
0.31706251443180914L,
|
||||
0.022665554431410243L,
|
||||
-0.29252538135177773e-5L
|
||||
};
|
||||
|
||||
T result = 1 - x / 2 + tools::evaluate_polynomial(P, x) / tools::evaluate_polynomial(Q, x);
|
||||
result *= x;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
T log1p_imp(T const& x, const Policy& pol, const mpl::int_<64>&)
|
||||
{ // The function returns the natural logarithm of 1 + x.
|
||||
BOOST_MATH_STD_USING
|
||||
|
||||
static const char* function = "boost::math::log1p<%1%>(%1%)";
|
||||
|
||||
if(x < -1)
|
||||
return policies::raise_domain_error<T>(
|
||||
function, "log1p(x) requires x > -1, but got x = %1%.", x, pol);
|
||||
if(x == -1)
|
||||
return -policies::raise_overflow_error<T>(
|
||||
function, 0, pol);
|
||||
|
||||
T a = fabs(x);
|
||||
if(a > 0.5f)
|
||||
return log(1 + x);
|
||||
// Note that without numeric_limits specialisation support,
|
||||
// epsilon just returns zero, and our "optimisation" will always fail:
|
||||
if(a < tools::epsilon<T>())
|
||||
return x;
|
||||
|
||||
// Maximum Deviation Found: 8.089e-20
|
||||
// Expected Error Term: 8.088e-20
|
||||
// Maximum Relative Change in Control Points: 9.648e-05
|
||||
// Max Error found at long double precision = 2.242324e-19
|
||||
static const T P[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.807533446680736736712e-19),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.490881544804798926426e-18),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.333333333333333373941),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.17141290782087994162),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.62790522814926264694),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.13156411870766876113),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.408087379932853785336),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.0706537026422828914622),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.00441709903782239229447)
|
||||
};
|
||||
static const T Q[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 4.26423872346263928361),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 7.48189472704477708962),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 6.94757016732904280913),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 3.6493508622280767304),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.06884863623790638317),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.158292216998514145947),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.00885295524069924328658),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.560026216133415663808e-6)
|
||||
};
|
||||
|
||||
T result = 1 - x / 2 + tools::evaluate_polynomial(P, x) / tools::evaluate_polynomial(Q, x);
|
||||
result *= x;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
T log1p_imp(T const& x, const Policy& pol, const mpl::int_<24>&)
|
||||
{ // The function returns the natural logarithm of 1 + x.
|
||||
BOOST_MATH_STD_USING
|
||||
|
||||
static const char* function = "boost::math::log1p<%1%>(%1%)";
|
||||
|
||||
if(x < -1)
|
||||
return policies::raise_domain_error<T>(
|
||||
function, "log1p(x) requires x > -1, but got x = %1%.", x, pol);
|
||||
if(x == -1)
|
||||
return -policies::raise_overflow_error<T>(
|
||||
function, 0, pol);
|
||||
|
||||
T a = fabs(x);
|
||||
if(a > 0.5f)
|
||||
return log(1 + x);
|
||||
// Note that without numeric_limits specialisation support,
|
||||
// epsilon just returns zero, and our "optimisation" will always fail:
|
||||
if(a < tools::epsilon<T>())
|
||||
return x;
|
||||
|
||||
// Maximum Deviation Found: 6.910e-08
|
||||
// Expected Error Term: 6.910e-08
|
||||
// Maximum Relative Change in Control Points: 2.509e-04
|
||||
// Max Error found at double precision = 6.910422e-08
|
||||
// Max Error found at float precision = 8.357242e-08
|
||||
static const T P[] = {
|
||||
-0.671192866803148236519e-7L,
|
||||
0.119670999140731844725e-6L,
|
||||
0.333339469182083148598L,
|
||||
0.237827183019664122066L
|
||||
};
|
||||
static const T Q[] = {
|
||||
1L,
|
||||
1.46348272586988539733L,
|
||||
0.497859871350117338894L,
|
||||
-0.00471666268910169651936L
|
||||
};
|
||||
|
||||
T result = 1 - x / 2 + tools::evaluate_polynomial(P, x) / tools::evaluate_polynomial(Q, x);
|
||||
result *= x;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T, class Policy, class tag>
|
||||
struct log1p_initializer
|
||||
{
|
||||
struct init
|
||||
{
|
||||
init()
|
||||
{
|
||||
do_init(tag());
|
||||
}
|
||||
template <int N>
|
||||
static void do_init(const mpl::int_<N>&){}
|
||||
static void do_init(const mpl::int_<64>&)
|
||||
{
|
||||
boost::math::log1p(static_cast<T>(0.25), Policy());
|
||||
}
|
||||
void force_instantiate()const{}
|
||||
};
|
||||
static const init initializer;
|
||||
static void force_instantiate()
|
||||
{
|
||||
initializer.force_instantiate();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class Policy, class tag>
|
||||
const typename log1p_initializer<T, Policy, tag>::init log1p_initializer<T, Policy, tag>::initializer;
|
||||
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class T, class Policy>
|
||||
inline typename tools::promote_args<T>::type log1p(T x, const Policy&)
|
||||
{
|
||||
typedef typename tools::promote_args<T>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
typedef typename policies::precision<result_type, Policy>::type precision_type;
|
||||
typedef typename policies::normalise<
|
||||
Policy,
|
||||
policies::promote_float<false>,
|
||||
policies::promote_double<false>,
|
||||
policies::discrete_quantile<>,
|
||||
policies::assert_undefined<> >::type forwarding_policy;
|
||||
|
||||
typedef typename mpl::if_<
|
||||
mpl::less_equal<precision_type, mpl::int_<0> >,
|
||||
mpl::int_<0>,
|
||||
typename mpl::if_<
|
||||
mpl::less_equal<precision_type, mpl::int_<53> >,
|
||||
mpl::int_<53>, // double
|
||||
typename mpl::if_<
|
||||
mpl::less_equal<precision_type, mpl::int_<64> >,
|
||||
mpl::int_<64>, // 80-bit long double
|
||||
mpl::int_<0> // too many bits, use generic version.
|
||||
>::type
|
||||
>::type
|
||||
>::type tag_type;
|
||||
|
||||
detail::log1p_initializer<value_type, forwarding_policy, tag_type>::force_instantiate();
|
||||
|
||||
return policies::checked_narrowing_cast<result_type, forwarding_policy>(
|
||||
detail::log1p_imp(static_cast<value_type>(x), forwarding_policy(), tag_type()), "boost::math::log1p<%1%>(%1%)");
|
||||
}
|
||||
|
||||
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
|
||||
// These overloads work around a type deduction bug:
|
||||
inline float log1p(float z)
|
||||
{
|
||||
return log1p<float>(z);
|
||||
}
|
||||
inline double log1p(double z)
|
||||
{
|
||||
return log1p<double>(z);
|
||||
}
|
||||
#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
|
||||
inline long double log1p(long double z)
|
||||
{
|
||||
return log1p<long double>(z);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef log1p
|
||||
# ifndef BOOST_HAS_LOG1P
|
||||
# define BOOST_HAS_LOG1P
|
||||
# endif
|
||||
# undef log1p
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_LOG1P) && !(defined(__osf__) && defined(__DECCXX_VER))
|
||||
# ifdef BOOST_MATH_USE_C99
|
||||
template <class Policy>
|
||||
inline float log1p(float x, const Policy& pol)
|
||||
{
|
||||
if(x < -1)
|
||||
return policies::raise_domain_error<float>(
|
||||
"log1p<%1%>(%1%)", "log1p(x) requires x > -1, but got x = %1%.", x, pol);
|
||||
if(x == -1)
|
||||
return -policies::raise_overflow_error<float>(
|
||||
"log1p<%1%>(%1%)", 0, pol);
|
||||
return ::log1pf(x);
|
||||
}
|
||||
#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
|
||||
template <class Policy>
|
||||
inline long double log1p(long double x, const Policy& pol)
|
||||
{
|
||||
if(x < -1)
|
||||
return policies::raise_domain_error<long double>(
|
||||
"log1p<%1%>(%1%)", "log1p(x) requires x > -1, but got x = %1%.", x, pol);
|
||||
if(x == -1)
|
||||
return -policies::raise_overflow_error<long double>(
|
||||
"log1p<%1%>(%1%)", 0, pol);
|
||||
return ::log1pl(x);
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
template <class Policy>
|
||||
inline float log1p(float x, const Policy& pol)
|
||||
{
|
||||
if(x < -1)
|
||||
return policies::raise_domain_error<float>(
|
||||
"log1p<%1%>(%1%)", "log1p(x) requires x > -1, but got x = %1%.", x, pol);
|
||||
if(x == -1)
|
||||
return -policies::raise_overflow_error<float>(
|
||||
"log1p<%1%>(%1%)", 0, pol);
|
||||
return ::log1p(x);
|
||||
}
|
||||
#endif
|
||||
template <class Policy>
|
||||
inline double log1p(double x, const Policy& pol)
|
||||
{
|
||||
if(x < -1)
|
||||
return policies::raise_domain_error<double>(
|
||||
"log1p<%1%>(%1%)", "log1p(x) requires x > -1, but got x = %1%.", x, pol);
|
||||
if(x == -1)
|
||||
return -policies::raise_overflow_error<double>(
|
||||
"log1p<%1%>(%1%)", 0, pol);
|
||||
return ::log1p(x);
|
||||
}
|
||||
#elif defined(_MSC_VER) && (BOOST_MSVC >= 1400)
|
||||
//
|
||||
// You should only enable this branch if you are absolutely sure
|
||||
// that your compilers optimizer won't mess this code up!!
|
||||
// Currently tested with VC8 and Intel 9.1.
|
||||
//
|
||||
template <class Policy>
|
||||
inline double log1p(double x, const Policy& pol)
|
||||
{
|
||||
if(x < -1)
|
||||
return policies::raise_domain_error<double>(
|
||||
"log1p<%1%>(%1%)", "log1p(x) requires x > -1, but got x = %1%.", x, pol);
|
||||
if(x == -1)
|
||||
return -policies::raise_overflow_error<double>(
|
||||
"log1p<%1%>(%1%)", 0, pol);
|
||||
double u = 1+x;
|
||||
if(u == 1.0)
|
||||
return x;
|
||||
else
|
||||
return ::log(u)*(x/(u-1.0));
|
||||
}
|
||||
template <class Policy>
|
||||
inline float log1p(float x, const Policy& pol)
|
||||
{
|
||||
return static_cast<float>(boost::math::log1p(static_cast<double>(x), pol));
|
||||
}
|
||||
#ifndef _WIN32_WCE
|
||||
//
|
||||
// For some reason this fails to compile under WinCE...
|
||||
// Needs more investigation.
|
||||
//
|
||||
template <class Policy>
|
||||
inline long double log1p(long double x, const Policy& pol)
|
||||
{
|
||||
if(x < -1)
|
||||
return policies::raise_domain_error<long double>(
|
||||
"log1p<%1%>(%1%)", "log1p(x) requires x > -1, but got x = %1%.", x, pol);
|
||||
if(x == -1)
|
||||
return -policies::raise_overflow_error<long double>(
|
||||
"log1p<%1%>(%1%)", 0, pol);
|
||||
long double u = 1+x;
|
||||
if(u == 1.0)
|
||||
return x;
|
||||
else
|
||||
return ::logl(u)*(x/(u-1.0));
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
inline typename tools::promote_args<T>::type log1p(T x)
|
||||
{
|
||||
return boost::math::log1p(x, policies::policy<>());
|
||||
}
|
||||
//
|
||||
// Compute log(1+x)-x:
|
||||
//
|
||||
template <class T, class Policy>
|
||||
inline typename tools::promote_args<T>::type
|
||||
log1pmx(T x, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T>::type result_type;
|
||||
BOOST_MATH_STD_USING
|
||||
static const char* function = "boost::math::log1pmx<%1%>(%1%)";
|
||||
|
||||
if(x < -1)
|
||||
return policies::raise_domain_error<T>(
|
||||
function, "log1pmx(x) requires x > -1, but got x = %1%.", x, pol);
|
||||
if(x == -1)
|
||||
return -policies::raise_overflow_error<T>(
|
||||
function, 0, pol);
|
||||
|
||||
result_type a = abs(result_type(x));
|
||||
if(a > result_type(0.95f))
|
||||
return log(1 + result_type(x)) - result_type(x);
|
||||
// Note that without numeric_limits specialisation support,
|
||||
// epsilon just returns zero, and our "optimisation" will always fail:
|
||||
if(a < tools::epsilon<result_type>())
|
||||
return -x * x / 2;
|
||||
boost::math::detail::log1p_series<T> s(x);
|
||||
s();
|
||||
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, policies::get_epsilon<T, Policy>(), max_iter, zero);
|
||||
#else
|
||||
T result = boost::math::tools::sum_series(s, policies::get_epsilon<T, Policy>(), max_iter);
|
||||
#endif
|
||||
policies::check_series_iterations<T>(function, max_iter, pol);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typename tools::promote_args<T>::type log1pmx(T x)
|
||||
{
|
||||
return log1pmx(x, policies::policy<>());
|
||||
}
|
||||
|
||||
} // namespace math
|
||||
} // namespace boost
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif // BOOST_MATH_LOG1P_INCLUDED
|
||||
|
||||
|
||||
|
||||
1678
code_isotrope/boost/math/special_functions/math_fwd.hpp
Executable file
1678
code_isotrope/boost/math/special_functions/math_fwd.hpp
Executable file
File diff suppressed because it is too large
Load Diff
71
code_isotrope/boost/math/special_functions/modf.hpp
Executable file
71
code_isotrope/boost/math/special_functions/modf.hpp
Executable file
@@ -0,0 +1,71 @@
|
||||
// Copyright John Maddock 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_MODF_HPP
|
||||
#define BOOST_MATH_MODF_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/math/tools/config.hpp>
|
||||
#include <boost/math/special_functions/trunc.hpp>
|
||||
|
||||
namespace boost{ namespace math{
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T modf(const T& v, T* ipart, const Policy& pol)
|
||||
{
|
||||
*ipart = trunc(v, pol);
|
||||
return v - *ipart;
|
||||
}
|
||||
template <class T>
|
||||
inline T modf(const T& v, T* ipart)
|
||||
{
|
||||
return modf(v, ipart, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T modf(const T& v, int* ipart, const Policy& pol)
|
||||
{
|
||||
*ipart = itrunc(v, pol);
|
||||
return v - *ipart;
|
||||
}
|
||||
template <class T>
|
||||
inline T modf(const T& v, int* ipart)
|
||||
{
|
||||
return modf(v, ipart, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T modf(const T& v, long* ipart, const Policy& pol)
|
||||
{
|
||||
*ipart = ltrunc(v, pol);
|
||||
return v - *ipart;
|
||||
}
|
||||
template <class T>
|
||||
inline T modf(const T& v, long* ipart)
|
||||
{
|
||||
return modf(v, ipart, policies::policy<>());
|
||||
}
|
||||
|
||||
#ifdef BOOST_HAS_LONG_LONG
|
||||
template <class T, class Policy>
|
||||
inline T modf(const T& v, boost::long_long_type* ipart, const Policy& pol)
|
||||
{
|
||||
*ipart = lltrunc(v, pol);
|
||||
return v - *ipart;
|
||||
}
|
||||
template <class T>
|
||||
inline T modf(const T& v, boost::long_long_type* ipart)
|
||||
{
|
||||
return modf(v, ipart, policies::policy<>());
|
||||
}
|
||||
#endif
|
||||
|
||||
}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_MODF_HPP
|
||||
858
code_isotrope/boost/math/special_functions/next.hpp
Executable file
858
code_isotrope/boost/math/special_functions/next.hpp
Executable file
@@ -0,0 +1,858 @@
|
||||
// (C) 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_NEXT_HPP
|
||||
#define BOOST_MATH_SPECIAL_NEXT_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
#include <boost/math/special_functions/fpclassify.hpp>
|
||||
#include <boost/math/special_functions/sign.hpp>
|
||||
#include <boost/math/special_functions/trunc.hpp>
|
||||
|
||||
#include <float.h>
|
||||
|
||||
#if !defined(_CRAYC) && !defined(__CUDACC__) && (!defined(__GNUC__) || (__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ > 3)))
|
||||
#if (defined(_M_IX86_FP) && (_M_IX86_FP >= 2)) || defined(__SSE2__)
|
||||
#include "xmmintrin.h"
|
||||
#define BOOST_MATH_CHECK_SSE2
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace boost{ namespace math{
|
||||
|
||||
namespace concepts {
|
||||
|
||||
class real_concept;
|
||||
class std_real_concept;
|
||||
|
||||
}
|
||||
|
||||
namespace detail{
|
||||
|
||||
template <class T>
|
||||
struct has_hidden_guard_digits;
|
||||
template <>
|
||||
struct has_hidden_guard_digits<float> : public mpl::false_ {};
|
||||
template <>
|
||||
struct has_hidden_guard_digits<double> : public mpl::false_ {};
|
||||
template <>
|
||||
struct has_hidden_guard_digits<long double> : public mpl::false_ {};
|
||||
#ifdef BOOST_HAS_FLOAT128
|
||||
template <>
|
||||
struct has_hidden_guard_digits<__float128> : public mpl::false_ {};
|
||||
#endif
|
||||
template <>
|
||||
struct has_hidden_guard_digits<boost::math::concepts::real_concept> : public mpl::false_ {};
|
||||
template <>
|
||||
struct has_hidden_guard_digits<boost::math::concepts::std_real_concept> : public mpl::false_ {};
|
||||
|
||||
template <class T, bool b>
|
||||
struct has_hidden_guard_digits_10 : public mpl::false_ {};
|
||||
template <class T>
|
||||
struct has_hidden_guard_digits_10<T, true> : public mpl::bool_<(std::numeric_limits<T>::digits10 != std::numeric_limits<T>::max_digits10)> {};
|
||||
|
||||
template <class T>
|
||||
struct has_hidden_guard_digits
|
||||
: public has_hidden_guard_digits_10<T,
|
||||
std::numeric_limits<T>::is_specialized
|
||||
&& (std::numeric_limits<T>::radix == 10) >
|
||||
{};
|
||||
|
||||
template <class T>
|
||||
inline const T& normalize_value(const T& val, const mpl::false_&) { return val; }
|
||||
template <class T>
|
||||
inline T normalize_value(const T& val, const mpl::true_&)
|
||||
{
|
||||
BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_specialized);
|
||||
BOOST_STATIC_ASSERT(std::numeric_limits<T>::radix != 2);
|
||||
|
||||
boost::intmax_t shift = (boost::intmax_t)std::numeric_limits<T>::digits - (boost::intmax_t)ilogb(val) - 1;
|
||||
T result = scalbn(val, shift);
|
||||
result = round(result);
|
||||
return scalbn(result, -shift);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T get_smallest_value(mpl::true_ const&)
|
||||
{
|
||||
//
|
||||
// numeric_limits lies about denorms being present - particularly
|
||||
// when this can be turned on or off at runtime, as is the case
|
||||
// when using the SSE2 registers in DAZ or FTZ mode.
|
||||
//
|
||||
static const T m = std::numeric_limits<T>::denorm_min();
|
||||
#ifdef BOOST_MATH_CHECK_SSE2
|
||||
return (_mm_getcsr() & (_MM_FLUSH_ZERO_ON | 0x40)) ? tools::min_value<T>() : m;;
|
||||
#else
|
||||
return ((tools::min_value<T>() / 2) == 0) ? tools::min_value<T>() : m;
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T get_smallest_value(mpl::false_ const&)
|
||||
{
|
||||
return tools::min_value<T>();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T get_smallest_value()
|
||||
{
|
||||
#if defined(BOOST_MSVC) && (BOOST_MSVC <= 1310)
|
||||
return get_smallest_value<T>(mpl::bool_<std::numeric_limits<T>::is_specialized && (std::numeric_limits<T>::has_denorm == 1)>());
|
||||
#else
|
||||
return get_smallest_value<T>(mpl::bool_<std::numeric_limits<T>::is_specialized && (std::numeric_limits<T>::has_denorm == std::denorm_present)>());
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
// Returns the smallest value that won't generate denorms when
|
||||
// we calculate the value of the least-significant-bit:
|
||||
//
|
||||
template <class T>
|
||||
T get_min_shift_value();
|
||||
|
||||
template <class T>
|
||||
struct min_shift_initializer
|
||||
{
|
||||
struct init
|
||||
{
|
||||
init()
|
||||
{
|
||||
do_init();
|
||||
}
|
||||
static void do_init()
|
||||
{
|
||||
get_min_shift_value<T>();
|
||||
}
|
||||
void force_instantiate()const{}
|
||||
};
|
||||
static const init initializer;
|
||||
static void force_instantiate()
|
||||
{
|
||||
initializer.force_instantiate();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
const typename min_shift_initializer<T>::init min_shift_initializer<T>::initializer;
|
||||
|
||||
template <class T>
|
||||
inline T calc_min_shifted(const mpl::true_&)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
return ldexp(tools::min_value<T>(), tools::digits<T>() + 1);
|
||||
}
|
||||
template <class T>
|
||||
inline T calc_min_shifted(const mpl::false_&)
|
||||
{
|
||||
BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_specialized);
|
||||
BOOST_STATIC_ASSERT(std::numeric_limits<T>::radix != 2);
|
||||
|
||||
return scalbn(tools::min_value<T>(), std::numeric_limits<T>::digits + 1);
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
inline T get_min_shift_value()
|
||||
{
|
||||
static const T val = calc_min_shifted<T>(mpl::bool_<!std::numeric_limits<T>::is_specialized || std::numeric_limits<T>::radix == 2>());
|
||||
min_shift_initializer<T>::force_instantiate();
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
T float_next_imp(const T& val, const mpl::true_&, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
int expon;
|
||||
static const char* function = "float_next<%1%>(%1%)";
|
||||
|
||||
int fpclass = (boost::math::fpclassify)(val);
|
||||
|
||||
if((fpclass == (int)FP_NAN) || (fpclass == (int)FP_INFINITE))
|
||||
{
|
||||
if(val < 0)
|
||||
return -tools::max_value<T>();
|
||||
return policies::raise_domain_error<T>(
|
||||
function,
|
||||
"Argument must be finite, but got %1%", val, pol);
|
||||
}
|
||||
|
||||
if(val >= tools::max_value<T>())
|
||||
return policies::raise_overflow_error<T>(function, 0, pol);
|
||||
|
||||
if(val == 0)
|
||||
return detail::get_smallest_value<T>();
|
||||
|
||||
if((fpclass != (int)FP_SUBNORMAL) && (fpclass != (int)FP_ZERO) && (fabs(val) < detail::get_min_shift_value<T>()) && (val != -tools::min_value<T>()))
|
||||
{
|
||||
//
|
||||
// Special case: if the value of the least significant bit is a denorm, and the result
|
||||
// would not be a denorm, then shift the input, increment, and shift back.
|
||||
// This avoids issues with the Intel SSE2 registers when the FTZ or DAZ flags are set.
|
||||
//
|
||||
return ldexp(float_next(T(ldexp(val, 2 * tools::digits<T>())), pol), -2 * tools::digits<T>());
|
||||
}
|
||||
|
||||
if(-0.5f == frexp(val, &expon))
|
||||
--expon; // reduce exponent when val is a power of two, and negative.
|
||||
T diff = ldexp(T(1), expon - tools::digits<T>());
|
||||
if(diff == 0)
|
||||
diff = detail::get_smallest_value<T>();
|
||||
return val + diff;
|
||||
} // float_next_imp
|
||||
//
|
||||
// Special version for some base other than 2:
|
||||
//
|
||||
template <class T, class Policy>
|
||||
T float_next_imp(const T& val, const mpl::false_&, const Policy& pol)
|
||||
{
|
||||
BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_specialized);
|
||||
BOOST_STATIC_ASSERT(std::numeric_limits<T>::radix != 2);
|
||||
|
||||
BOOST_MATH_STD_USING
|
||||
boost::intmax_t expon;
|
||||
static const char* function = "float_next<%1%>(%1%)";
|
||||
|
||||
int fpclass = (boost::math::fpclassify)(val);
|
||||
|
||||
if((fpclass == (int)FP_NAN) || (fpclass == (int)FP_INFINITE))
|
||||
{
|
||||
if(val < 0)
|
||||
return -tools::max_value<T>();
|
||||
return policies::raise_domain_error<T>(
|
||||
function,
|
||||
"Argument must be finite, but got %1%", val, pol);
|
||||
}
|
||||
|
||||
if(val >= tools::max_value<T>())
|
||||
return policies::raise_overflow_error<T>(function, 0, pol);
|
||||
|
||||
if(val == 0)
|
||||
return detail::get_smallest_value<T>();
|
||||
|
||||
if((fpclass != (int)FP_SUBNORMAL) && (fpclass != (int)FP_ZERO) && (fabs(val) < detail::get_min_shift_value<T>()) && (val != -tools::min_value<T>()))
|
||||
{
|
||||
//
|
||||
// Special case: if the value of the least significant bit is a denorm, and the result
|
||||
// would not be a denorm, then shift the input, increment, and shift back.
|
||||
// This avoids issues with the Intel SSE2 registers when the FTZ or DAZ flags are set.
|
||||
//
|
||||
return scalbn(float_next(T(scalbn(val, 2 * std::numeric_limits<T>::digits)), pol), -2 * std::numeric_limits<T>::digits);
|
||||
}
|
||||
|
||||
expon = 1 + ilogb(val);
|
||||
if(-1 == scalbn(val, -expon) * std::numeric_limits<T>::radix)
|
||||
--expon; // reduce exponent when val is a power of base, and negative.
|
||||
T diff = scalbn(T(1), expon - std::numeric_limits<T>::digits);
|
||||
if(diff == 0)
|
||||
diff = detail::get_smallest_value<T>();
|
||||
return val + diff;
|
||||
} // float_next_imp
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class T, class Policy>
|
||||
inline typename tools::promote_args<T>::type float_next(const T& val, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T>::type result_type;
|
||||
return detail::float_next_imp(detail::normalize_value(static_cast<result_type>(val), typename detail::has_hidden_guard_digits<result_type>::type()), mpl::bool_<!std::numeric_limits<result_type>::is_specialized || (std::numeric_limits<result_type>::radix == 2)>(), pol);
|
||||
}
|
||||
|
||||
#if 0 //def BOOST_MSVC
|
||||
//
|
||||
// We used to use ::_nextafter here, but doing so fails when using
|
||||
// the SSE2 registers if the FTZ or DAZ flags are set, so use our own
|
||||
// - albeit slower - code instead as at least that gives the correct answer.
|
||||
//
|
||||
template <class Policy>
|
||||
inline double float_next(const double& val, const Policy& pol)
|
||||
{
|
||||
static const char* function = "float_next<%1%>(%1%)";
|
||||
|
||||
if(!(boost::math::isfinite)(val) && (val > 0))
|
||||
return policies::raise_domain_error<double>(
|
||||
function,
|
||||
"Argument must be finite, but got %1%", val, pol);
|
||||
|
||||
if(val >= tools::max_value<double>())
|
||||
return policies::raise_overflow_error<double>(function, 0, pol);
|
||||
|
||||
return ::_nextafter(val, tools::max_value<double>());
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
inline typename tools::promote_args<T>::type float_next(const T& val)
|
||||
{
|
||||
return float_next(val, policies::policy<>());
|
||||
}
|
||||
|
||||
namespace detail{
|
||||
|
||||
template <class T, class Policy>
|
||||
T float_prior_imp(const T& val, const mpl::true_&, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
int expon;
|
||||
static const char* function = "float_prior<%1%>(%1%)";
|
||||
|
||||
int fpclass = (boost::math::fpclassify)(val);
|
||||
|
||||
if((fpclass == (int)FP_NAN) || (fpclass == (int)FP_INFINITE))
|
||||
{
|
||||
if(val > 0)
|
||||
return tools::max_value<T>();
|
||||
return policies::raise_domain_error<T>(
|
||||
function,
|
||||
"Argument must be finite, but got %1%", val, pol);
|
||||
}
|
||||
|
||||
if(val <= -tools::max_value<T>())
|
||||
return -policies::raise_overflow_error<T>(function, 0, pol);
|
||||
|
||||
if(val == 0)
|
||||
return -detail::get_smallest_value<T>();
|
||||
|
||||
if((fpclass != (int)FP_SUBNORMAL) && (fpclass != (int)FP_ZERO) && (fabs(val) < detail::get_min_shift_value<T>()) && (val != tools::min_value<T>()))
|
||||
{
|
||||
//
|
||||
// Special case: if the value of the least significant bit is a denorm, and the result
|
||||
// would not be a denorm, then shift the input, increment, and shift back.
|
||||
// This avoids issues with the Intel SSE2 registers when the FTZ or DAZ flags are set.
|
||||
//
|
||||
return ldexp(float_prior(T(ldexp(val, 2 * tools::digits<T>())), pol), -2 * tools::digits<T>());
|
||||
}
|
||||
|
||||
T remain = frexp(val, &expon);
|
||||
if(remain == 0.5f)
|
||||
--expon; // when val is a power of two we must reduce the exponent
|
||||
T diff = ldexp(T(1), expon - tools::digits<T>());
|
||||
if(diff == 0)
|
||||
diff = detail::get_smallest_value<T>();
|
||||
return val - diff;
|
||||
} // float_prior_imp
|
||||
//
|
||||
// Special version for bases other than 2:
|
||||
//
|
||||
template <class T, class Policy>
|
||||
T float_prior_imp(const T& val, const mpl::false_&, const Policy& pol)
|
||||
{
|
||||
BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_specialized);
|
||||
BOOST_STATIC_ASSERT(std::numeric_limits<T>::radix != 2);
|
||||
|
||||
BOOST_MATH_STD_USING
|
||||
boost::intmax_t expon;
|
||||
static const char* function = "float_prior<%1%>(%1%)";
|
||||
|
||||
int fpclass = (boost::math::fpclassify)(val);
|
||||
|
||||
if((fpclass == (int)FP_NAN) || (fpclass == (int)FP_INFINITE))
|
||||
{
|
||||
if(val > 0)
|
||||
return tools::max_value<T>();
|
||||
return policies::raise_domain_error<T>(
|
||||
function,
|
||||
"Argument must be finite, but got %1%", val, pol);
|
||||
}
|
||||
|
||||
if(val <= -tools::max_value<T>())
|
||||
return -policies::raise_overflow_error<T>(function, 0, pol);
|
||||
|
||||
if(val == 0)
|
||||
return -detail::get_smallest_value<T>();
|
||||
|
||||
if((fpclass != (int)FP_SUBNORMAL) && (fpclass != (int)FP_ZERO) && (fabs(val) < detail::get_min_shift_value<T>()) && (val != tools::min_value<T>()))
|
||||
{
|
||||
//
|
||||
// Special case: if the value of the least significant bit is a denorm, and the result
|
||||
// would not be a denorm, then shift the input, increment, and shift back.
|
||||
// This avoids issues with the Intel SSE2 registers when the FTZ or DAZ flags are set.
|
||||
//
|
||||
return scalbn(float_prior(T(scalbn(val, 2 * std::numeric_limits<T>::digits)), pol), -2 * std::numeric_limits<T>::digits);
|
||||
}
|
||||
|
||||
expon = 1 + ilogb(val);
|
||||
T remain = scalbn(val, -expon);
|
||||
if(remain * std::numeric_limits<T>::radix == 1)
|
||||
--expon; // when val is a power of two we must reduce the exponent
|
||||
T diff = scalbn(T(1), expon - std::numeric_limits<T>::digits);
|
||||
if(diff == 0)
|
||||
diff = detail::get_smallest_value<T>();
|
||||
return val - diff;
|
||||
} // float_prior_imp
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class T, class Policy>
|
||||
inline typename tools::promote_args<T>::type float_prior(const T& val, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T>::type result_type;
|
||||
return detail::float_prior_imp(detail::normalize_value(static_cast<result_type>(val), typename detail::has_hidden_guard_digits<result_type>::type()), mpl::bool_<!std::numeric_limits<result_type>::is_specialized || (std::numeric_limits<result_type>::radix == 2)>(), pol);
|
||||
}
|
||||
|
||||
#if 0 //def BOOST_MSVC
|
||||
//
|
||||
// We used to use ::_nextafter here, but doing so fails when using
|
||||
// the SSE2 registers if the FTZ or DAZ flags are set, so use our own
|
||||
// - albeit slower - code instead as at least that gives the correct answer.
|
||||
//
|
||||
template <class Policy>
|
||||
inline double float_prior(const double& val, const Policy& pol)
|
||||
{
|
||||
static const char* function = "float_prior<%1%>(%1%)";
|
||||
|
||||
if(!(boost::math::isfinite)(val) && (val < 0))
|
||||
return policies::raise_domain_error<double>(
|
||||
function,
|
||||
"Argument must be finite, but got %1%", val, pol);
|
||||
|
||||
if(val <= -tools::max_value<double>())
|
||||
return -policies::raise_overflow_error<double>(function, 0, pol);
|
||||
|
||||
return ::_nextafter(val, -tools::max_value<double>());
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
inline typename tools::promote_args<T>::type float_prior(const T& val)
|
||||
{
|
||||
return float_prior(val, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T, class U, class Policy>
|
||||
inline typename tools::promote_args<T, U>::type nextafter(const T& val, const U& direction, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T, U>::type result_type;
|
||||
return val < direction ? boost::math::float_next<result_type>(val, pol) : val == direction ? val : boost::math::float_prior<result_type>(val, pol);
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
inline typename tools::promote_args<T, U>::type nextafter(const T& val, const U& direction)
|
||||
{
|
||||
return nextafter(val, direction, policies::policy<>());
|
||||
}
|
||||
|
||||
namespace detail{
|
||||
|
||||
template <class T, class Policy>
|
||||
T float_distance_imp(const T& a, const T& b, const mpl::true_&, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
//
|
||||
// Error handling:
|
||||
//
|
||||
static const char* function = "float_distance<%1%>(%1%, %1%)";
|
||||
if(!(boost::math::isfinite)(a))
|
||||
return policies::raise_domain_error<T>(
|
||||
function,
|
||||
"Argument a must be finite, but got %1%", a, pol);
|
||||
if(!(boost::math::isfinite)(b))
|
||||
return policies::raise_domain_error<T>(
|
||||
function,
|
||||
"Argument b must be finite, but got %1%", b, pol);
|
||||
//
|
||||
// Special cases:
|
||||
//
|
||||
if(a > b)
|
||||
return -float_distance(b, a, pol);
|
||||
if(a == b)
|
||||
return T(0);
|
||||
if(a == 0)
|
||||
return 1 + fabs(float_distance(static_cast<T>((b < 0) ? T(-detail::get_smallest_value<T>()) : detail::get_smallest_value<T>()), b, pol));
|
||||
if(b == 0)
|
||||
return 1 + fabs(float_distance(static_cast<T>((a < 0) ? T(-detail::get_smallest_value<T>()) : detail::get_smallest_value<T>()), a, pol));
|
||||
if(boost::math::sign(a) != boost::math::sign(b))
|
||||
return 2 + fabs(float_distance(static_cast<T>((b < 0) ? T(-detail::get_smallest_value<T>()) : detail::get_smallest_value<T>()), b, pol))
|
||||
+ fabs(float_distance(static_cast<T>((a < 0) ? T(-detail::get_smallest_value<T>()) : detail::get_smallest_value<T>()), a, pol));
|
||||
//
|
||||
// By the time we get here, both a and b must have the same sign, we want
|
||||
// b > a and both postive for the following logic:
|
||||
//
|
||||
if(a < 0)
|
||||
return float_distance(static_cast<T>(-b), static_cast<T>(-a), pol);
|
||||
|
||||
BOOST_ASSERT(a >= 0);
|
||||
BOOST_ASSERT(b >= a);
|
||||
|
||||
int expon;
|
||||
//
|
||||
// Note that if a is a denorm then the usual formula fails
|
||||
// because we actually have fewer than tools::digits<T>()
|
||||
// significant bits in the representation:
|
||||
//
|
||||
frexp(((boost::math::fpclassify)(a) == (int)FP_SUBNORMAL) ? tools::min_value<T>() : a, &expon);
|
||||
T upper = ldexp(T(1), expon);
|
||||
T result = T(0);
|
||||
//
|
||||
// If b is greater than upper, then we *must* split the calculation
|
||||
// as the size of the ULP changes with each order of magnitude change:
|
||||
//
|
||||
if(b > upper)
|
||||
{
|
||||
int expon2;
|
||||
frexp(b, &expon2);
|
||||
T upper2 = ldexp(T(0.5), expon2);
|
||||
result = float_distance(upper2, b);
|
||||
result += (expon2 - expon - 1) * ldexp(T(1), tools::digits<T>() - 1);
|
||||
}
|
||||
//
|
||||
// Use compensated double-double addition to avoid rounding
|
||||
// errors in the subtraction:
|
||||
//
|
||||
expon = tools::digits<T>() - expon;
|
||||
T mb, x, y, z;
|
||||
if(((boost::math::fpclassify)(a) == (int)FP_SUBNORMAL) || (b - a < tools::min_value<T>()))
|
||||
{
|
||||
//
|
||||
// Special case - either one end of the range is a denormal, or else the difference is.
|
||||
// The regular code will fail if we're using the SSE2 registers on Intel and either
|
||||
// the FTZ or DAZ flags are set.
|
||||
//
|
||||
T a2 = ldexp(a, tools::digits<T>());
|
||||
T b2 = ldexp(b, tools::digits<T>());
|
||||
mb = -(std::min)(T(ldexp(upper, tools::digits<T>())), b2);
|
||||
x = a2 + mb;
|
||||
z = x - a2;
|
||||
y = (a2 - (x - z)) + (mb - z);
|
||||
|
||||
expon -= tools::digits<T>();
|
||||
}
|
||||
else
|
||||
{
|
||||
mb = -(std::min)(upper, b);
|
||||
x = a + mb;
|
||||
z = x - a;
|
||||
y = (a - (x - z)) + (mb - z);
|
||||
}
|
||||
if(x < 0)
|
||||
{
|
||||
x = -x;
|
||||
y = -y;
|
||||
}
|
||||
result += ldexp(x, expon) + ldexp(y, expon);
|
||||
//
|
||||
// Result must be an integer:
|
||||
//
|
||||
BOOST_ASSERT(result == floor(result));
|
||||
return result;
|
||||
} // float_distance_imp
|
||||
//
|
||||
// Special versions for bases other than 2:
|
||||
//
|
||||
template <class T, class Policy>
|
||||
T float_distance_imp(const T& a, const T& b, const mpl::false_&, const Policy& pol)
|
||||
{
|
||||
BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_specialized);
|
||||
BOOST_STATIC_ASSERT(std::numeric_limits<T>::radix != 2);
|
||||
|
||||
BOOST_MATH_STD_USING
|
||||
//
|
||||
// Error handling:
|
||||
//
|
||||
static const char* function = "float_distance<%1%>(%1%, %1%)";
|
||||
if(!(boost::math::isfinite)(a))
|
||||
return policies::raise_domain_error<T>(
|
||||
function,
|
||||
"Argument a must be finite, but got %1%", a, pol);
|
||||
if(!(boost::math::isfinite)(b))
|
||||
return policies::raise_domain_error<T>(
|
||||
function,
|
||||
"Argument b must be finite, but got %1%", b, pol);
|
||||
//
|
||||
// Special cases:
|
||||
//
|
||||
if(a > b)
|
||||
return -float_distance(b, a, pol);
|
||||
if(a == b)
|
||||
return T(0);
|
||||
if(a == 0)
|
||||
return 1 + fabs(float_distance(static_cast<T>((b < 0) ? T(-detail::get_smallest_value<T>()) : detail::get_smallest_value<T>()), b, pol));
|
||||
if(b == 0)
|
||||
return 1 + fabs(float_distance(static_cast<T>((a < 0) ? T(-detail::get_smallest_value<T>()) : detail::get_smallest_value<T>()), a, pol));
|
||||
if(boost::math::sign(a) != boost::math::sign(b))
|
||||
return 2 + fabs(float_distance(static_cast<T>((b < 0) ? T(-detail::get_smallest_value<T>()) : detail::get_smallest_value<T>()), b, pol))
|
||||
+ fabs(float_distance(static_cast<T>((a < 0) ? T(-detail::get_smallest_value<T>()) : detail::get_smallest_value<T>()), a, pol));
|
||||
//
|
||||
// By the time we get here, both a and b must have the same sign, we want
|
||||
// b > a and both postive for the following logic:
|
||||
//
|
||||
if(a < 0)
|
||||
return float_distance(static_cast<T>(-b), static_cast<T>(-a), pol);
|
||||
|
||||
BOOST_ASSERT(a >= 0);
|
||||
BOOST_ASSERT(b >= a);
|
||||
|
||||
boost::intmax_t expon;
|
||||
//
|
||||
// Note that if a is a denorm then the usual formula fails
|
||||
// because we actually have fewer than tools::digits<T>()
|
||||
// significant bits in the representation:
|
||||
//
|
||||
expon = 1 + ilogb(((boost::math::fpclassify)(a) == (int)FP_SUBNORMAL) ? tools::min_value<T>() : a);
|
||||
T upper = scalbn(T(1), expon);
|
||||
T result = T(0);
|
||||
//
|
||||
// If b is greater than upper, then we *must* split the calculation
|
||||
// as the size of the ULP changes with each order of magnitude change:
|
||||
//
|
||||
if(b > upper)
|
||||
{
|
||||
boost::intmax_t expon2 = 1 + ilogb(b);
|
||||
T upper2 = scalbn(T(1), expon2 - 1);
|
||||
result = float_distance(upper2, b);
|
||||
result += (expon2 - expon - 1) * scalbn(T(1), std::numeric_limits<T>::digits - 1);
|
||||
}
|
||||
//
|
||||
// Use compensated double-double addition to avoid rounding
|
||||
// errors in the subtraction:
|
||||
//
|
||||
expon = std::numeric_limits<T>::digits - expon;
|
||||
T mb, x, y, z;
|
||||
if(((boost::math::fpclassify)(a) == (int)FP_SUBNORMAL) || (b - a < tools::min_value<T>()))
|
||||
{
|
||||
//
|
||||
// Special case - either one end of the range is a denormal, or else the difference is.
|
||||
// The regular code will fail if we're using the SSE2 registers on Intel and either
|
||||
// the FTZ or DAZ flags are set.
|
||||
//
|
||||
T a2 = scalbn(a, std::numeric_limits<T>::digits);
|
||||
T b2 = scalbn(b, std::numeric_limits<T>::digits);
|
||||
mb = -(std::min)(T(scalbn(upper, std::numeric_limits<T>::digits)), b2);
|
||||
x = a2 + mb;
|
||||
z = x - a2;
|
||||
y = (a2 - (x - z)) + (mb - z);
|
||||
|
||||
expon -= std::numeric_limits<T>::digits;
|
||||
}
|
||||
else
|
||||
{
|
||||
mb = -(std::min)(upper, b);
|
||||
x = a + mb;
|
||||
z = x - a;
|
||||
y = (a - (x - z)) + (mb - z);
|
||||
}
|
||||
if(x < 0)
|
||||
{
|
||||
x = -x;
|
||||
y = -y;
|
||||
}
|
||||
result += scalbn(x, expon) + scalbn(y, expon);
|
||||
//
|
||||
// Result must be an integer:
|
||||
//
|
||||
BOOST_ASSERT(result == floor(result));
|
||||
return result;
|
||||
} // float_distance_imp
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class T, class U, class Policy>
|
||||
inline typename tools::promote_args<T, U>::type float_distance(const T& a, const U& b, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T, U>::type result_type;
|
||||
return detail::float_distance_imp(detail::normalize_value(static_cast<result_type>(a), typename detail::has_hidden_guard_digits<result_type>::type()), detail::normalize_value(static_cast<result_type>(b), typename detail::has_hidden_guard_digits<result_type>::type()), mpl::bool_<!std::numeric_limits<result_type>::is_specialized || (std::numeric_limits<result_type>::radix == 2)>(), pol);
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
typename tools::promote_args<T, U>::type float_distance(const T& a, const U& b)
|
||||
{
|
||||
return boost::math::float_distance(a, b, policies::policy<>());
|
||||
}
|
||||
|
||||
namespace detail{
|
||||
|
||||
template <class T, class Policy>
|
||||
T float_advance_imp(T val, int distance, const mpl::true_&, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
//
|
||||
// Error handling:
|
||||
//
|
||||
static const char* function = "float_advance<%1%>(%1%, int)";
|
||||
|
||||
int fpclass = (boost::math::fpclassify)(val);
|
||||
|
||||
if((fpclass == (int)FP_NAN) || (fpclass == (int)FP_INFINITE))
|
||||
return policies::raise_domain_error<T>(
|
||||
function,
|
||||
"Argument val must be finite, but got %1%", val, pol);
|
||||
|
||||
if(val < 0)
|
||||
return -float_advance(-val, -distance, pol);
|
||||
if(distance == 0)
|
||||
return val;
|
||||
if(distance == 1)
|
||||
return float_next(val, pol);
|
||||
if(distance == -1)
|
||||
return float_prior(val, pol);
|
||||
|
||||
if(fabs(val) < detail::get_min_shift_value<T>())
|
||||
{
|
||||
//
|
||||
// Special case: if the value of the least significant bit is a denorm,
|
||||
// implement in terms of float_next/float_prior.
|
||||
// This avoids issues with the Intel SSE2 registers when the FTZ or DAZ flags are set.
|
||||
//
|
||||
if(distance > 0)
|
||||
{
|
||||
do{ val = float_next(val, pol); } while(--distance);
|
||||
}
|
||||
else
|
||||
{
|
||||
do{ val = float_prior(val, pol); } while(++distance);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
int expon;
|
||||
frexp(val, &expon);
|
||||
T limit = ldexp((distance < 0 ? T(0.5f) : T(1)), expon);
|
||||
if(val <= tools::min_value<T>())
|
||||
{
|
||||
limit = sign(T(distance)) * tools::min_value<T>();
|
||||
}
|
||||
T limit_distance = float_distance(val, limit);
|
||||
while(fabs(limit_distance) < abs(distance))
|
||||
{
|
||||
distance -= itrunc(limit_distance);
|
||||
val = limit;
|
||||
if(distance < 0)
|
||||
{
|
||||
limit /= 2;
|
||||
expon--;
|
||||
}
|
||||
else
|
||||
{
|
||||
limit *= 2;
|
||||
expon++;
|
||||
}
|
||||
limit_distance = float_distance(val, limit);
|
||||
if(distance && (limit_distance == 0))
|
||||
{
|
||||
return policies::raise_evaluation_error<T>(function, "Internal logic failed while trying to increment floating point value %1%: most likely your FPU is in non-IEEE conforming mode.", val, pol);
|
||||
}
|
||||
}
|
||||
if((0.5f == frexp(val, &expon)) && (distance < 0))
|
||||
--expon;
|
||||
T diff = 0;
|
||||
if(val != 0)
|
||||
diff = distance * ldexp(T(1), expon - tools::digits<T>());
|
||||
if(diff == 0)
|
||||
diff = distance * detail::get_smallest_value<T>();
|
||||
return val += diff;
|
||||
} // float_advance_imp
|
||||
//
|
||||
// Special version for bases other than 2:
|
||||
//
|
||||
template <class T, class Policy>
|
||||
T float_advance_imp(T val, int distance, const mpl::false_&, const Policy& pol)
|
||||
{
|
||||
BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_specialized);
|
||||
BOOST_STATIC_ASSERT(std::numeric_limits<T>::radix != 2);
|
||||
|
||||
BOOST_MATH_STD_USING
|
||||
//
|
||||
// Error handling:
|
||||
//
|
||||
static const char* function = "float_advance<%1%>(%1%, int)";
|
||||
|
||||
int fpclass = (boost::math::fpclassify)(val);
|
||||
|
||||
if((fpclass == (int)FP_NAN) || (fpclass == (int)FP_INFINITE))
|
||||
return policies::raise_domain_error<T>(
|
||||
function,
|
||||
"Argument val must be finite, but got %1%", val, pol);
|
||||
|
||||
if(val < 0)
|
||||
return -float_advance(-val, -distance, pol);
|
||||
if(distance == 0)
|
||||
return val;
|
||||
if(distance == 1)
|
||||
return float_next(val, pol);
|
||||
if(distance == -1)
|
||||
return float_prior(val, pol);
|
||||
|
||||
if(fabs(val) < detail::get_min_shift_value<T>())
|
||||
{
|
||||
//
|
||||
// Special case: if the value of the least significant bit is a denorm,
|
||||
// implement in terms of float_next/float_prior.
|
||||
// This avoids issues with the Intel SSE2 registers when the FTZ or DAZ flags are set.
|
||||
//
|
||||
if(distance > 0)
|
||||
{
|
||||
do{ val = float_next(val, pol); } while(--distance);
|
||||
}
|
||||
else
|
||||
{
|
||||
do{ val = float_prior(val, pol); } while(++distance);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
boost::intmax_t expon = 1 + ilogb(val);
|
||||
T limit = scalbn(T(1), distance < 0 ? expon - 1 : expon);
|
||||
if(val <= tools::min_value<T>())
|
||||
{
|
||||
limit = sign(T(distance)) * tools::min_value<T>();
|
||||
}
|
||||
T limit_distance = float_distance(val, limit);
|
||||
while(fabs(limit_distance) < abs(distance))
|
||||
{
|
||||
distance -= itrunc(limit_distance);
|
||||
val = limit;
|
||||
if(distance < 0)
|
||||
{
|
||||
limit /= std::numeric_limits<T>::radix;
|
||||
expon--;
|
||||
}
|
||||
else
|
||||
{
|
||||
limit *= std::numeric_limits<T>::radix;
|
||||
expon++;
|
||||
}
|
||||
limit_distance = float_distance(val, limit);
|
||||
if(distance && (limit_distance == 0))
|
||||
{
|
||||
return policies::raise_evaluation_error<T>(function, "Internal logic failed while trying to increment floating point value %1%: most likely your FPU is in non-IEEE conforming mode.", val, pol);
|
||||
}
|
||||
}
|
||||
/*expon = 1 + ilogb(val);
|
||||
if((1 == scalbn(val, 1 + expon)) && (distance < 0))
|
||||
--expon;*/
|
||||
T diff = 0;
|
||||
if(val != 0)
|
||||
diff = distance * scalbn(T(1), expon - std::numeric_limits<T>::digits);
|
||||
if(diff == 0)
|
||||
diff = distance * detail::get_smallest_value<T>();
|
||||
return val += diff;
|
||||
} // float_advance_imp
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class T, class Policy>
|
||||
inline typename tools::promote_args<T>::type float_advance(T val, int distance, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T>::type result_type;
|
||||
return detail::float_advance_imp(detail::normalize_value(static_cast<result_type>(val), typename detail::has_hidden_guard_digits<result_type>::type()), distance, mpl::bool_<!std::numeric_limits<result_type>::is_specialized || (std::numeric_limits<result_type>::radix == 2)>(), pol);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typename tools::promote_args<T>::type float_advance(const T& val, int distance)
|
||||
{
|
||||
return boost::math::float_advance(val, distance, policies::policy<>());
|
||||
}
|
||||
|
||||
}} // boost math namespaces
|
||||
|
||||
#endif // BOOST_MATH_SPECIAL_NEXT_HPP
|
||||
|
||||
593
code_isotrope/boost/math/special_functions/nonfinite_num_facets.hpp
Executable file
593
code_isotrope/boost/math/special_functions/nonfinite_num_facets.hpp
Executable file
@@ -0,0 +1,593 @@
|
||||
#ifndef BOOST_MATH_NONFINITE_NUM_FACETS_HPP
|
||||
#define BOOST_MATH_NONFINITE_NUM_FACETS_HPP
|
||||
|
||||
// Copyright 2006 Johan Rade
|
||||
// Copyright 2012 K R Walker
|
||||
// Copyright 2011, 2012 Paul A. Bristow
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
/*
|
||||
\file
|
||||
|
||||
\brief non_finite_num facets for C99 standard output of infinity and NaN.
|
||||
|
||||
\details See fuller documentation at Boost.Math Facets
|
||||
for Floating-Point Infinities and NaNs.
|
||||
*/
|
||||
|
||||
#include <cstring>
|
||||
#include <ios>
|
||||
#include <limits>
|
||||
#include <locale>
|
||||
|
||||
#include <boost/version.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
#include <boost/math/special_functions/fpclassify.hpp>
|
||||
#include <boost/math/special_functions/sign.hpp>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable : 4127) // conditional expression is constant.
|
||||
# pragma warning(disable : 4706) // assignment within conditional expression.
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace math {
|
||||
|
||||
// flags (enums can be ORed together) -----------------------------------
|
||||
|
||||
const int legacy = 0x1; //!< get facet will recognize most string representations of infinity and NaN.
|
||||
const int signed_zero = 0x2; //!< put facet will distinguish between positive and negative zero.
|
||||
const int trap_infinity = 0x4; /*!< put facet will throw an exception of type std::ios_base::failure
|
||||
when an attempt is made to format positive or negative infinity.
|
||||
get will set the fail bit of the stream when an attempt is made
|
||||
to parse a string that represents positive or negative sign infinity.
|
||||
*/
|
||||
const int trap_nan = 0x8; /*!< put facet will throw an exception of type std::ios_base::failure
|
||||
when an attempt is made to format positive or negative NaN.
|
||||
get will set the fail bit of the stream when an attempt is made
|
||||
to parse a string that represents positive or negative sign infinity.
|
||||
*/
|
||||
|
||||
// class nonfinite_num_put -----------------------------------------------------
|
||||
|
||||
template<
|
||||
class CharType,
|
||||
class OutputIterator = std::ostreambuf_iterator<CharType>
|
||||
>
|
||||
class nonfinite_num_put : public std::num_put<CharType, OutputIterator>
|
||||
{
|
||||
public:
|
||||
explicit nonfinite_num_put(int flags = 0) : flags_(flags) {}
|
||||
|
||||
protected:
|
||||
virtual OutputIterator do_put(
|
||||
OutputIterator it, std::ios_base& iosb, CharType fill, double val) const
|
||||
{
|
||||
put_and_reset_width(it, iosb, fill, val);
|
||||
return it;
|
||||
}
|
||||
|
||||
virtual OutputIterator do_put(
|
||||
OutputIterator it, std::ios_base& iosb, CharType fill, long double val) const
|
||||
{
|
||||
put_and_reset_width(it, iosb, fill, val);
|
||||
return it;
|
||||
}
|
||||
|
||||
private:
|
||||
template<class ValType> void put_and_reset_width(
|
||||
OutputIterator& it, std::ios_base& iosb,
|
||||
CharType fill, ValType val) const
|
||||
{
|
||||
put_impl(it, iosb, fill, val);
|
||||
iosb.width(0);
|
||||
}
|
||||
|
||||
template<class ValType> void put_impl(
|
||||
OutputIterator& it, std::ios_base& iosb,
|
||||
CharType fill, ValType val) const
|
||||
{
|
||||
static const CharType prefix_plus[2] = { '+', '\0' };
|
||||
static const CharType prefix_minus[2] = { '-', '\0' };
|
||||
static const CharType body_inf[4] = { 'i', 'n', 'f', '\0' };
|
||||
static const CharType body_nan[4] = { 'n', 'a', 'n', '\0' };
|
||||
static const CharType* null_string = 0;
|
||||
|
||||
switch((boost::math::fpclassify)(val))
|
||||
{
|
||||
|
||||
case FP_INFINITE:
|
||||
if(flags_ & trap_infinity)
|
||||
{
|
||||
BOOST_THROW_EXCEPTION(std::ios_base::failure("Infinity"));
|
||||
}
|
||||
else if((boost::math::signbit)(val))
|
||||
{ // negative infinity.
|
||||
put_num_and_fill(it, iosb, prefix_minus, body_inf, fill, val);
|
||||
}
|
||||
else if(iosb.flags() & std::ios_base::showpos)
|
||||
{ // Explicit "+inf" wanted.
|
||||
put_num_and_fill(it, iosb, prefix_plus, body_inf, fill, val);
|
||||
}
|
||||
else
|
||||
{ // just "inf" wanted.
|
||||
put_num_and_fill(it, iosb, null_string, body_inf, fill, val);
|
||||
}
|
||||
break;
|
||||
|
||||
case FP_NAN:
|
||||
if(flags_ & trap_nan)
|
||||
{
|
||||
BOOST_THROW_EXCEPTION(std::ios_base::failure("NaN"));
|
||||
}
|
||||
else if((boost::math::signbit)(val))
|
||||
{ // negative so "-nan".
|
||||
put_num_and_fill(it, iosb, prefix_minus, body_nan, fill, val);
|
||||
}
|
||||
else if(iosb.flags() & std::ios_base::showpos)
|
||||
{ // explicit "+nan" wanted.
|
||||
put_num_and_fill(it, iosb, prefix_plus, body_nan, fill, val);
|
||||
}
|
||||
else
|
||||
{ // Just "nan".
|
||||
put_num_and_fill(it, iosb, null_string, body_nan, fill, val);
|
||||
}
|
||||
break;
|
||||
|
||||
case FP_ZERO:
|
||||
if((flags_ & signed_zero) && ((boost::math::signbit)(val)))
|
||||
{ // Flag set to distinguish between positive and negative zero.
|
||||
// But string "0" should have stuff after decimal point if setprecision and/or exp format.
|
||||
|
||||
std::basic_ostringstream<CharType> zeros; // Needs to be CharType version.
|
||||
|
||||
// Copy flags, fill, width and precision.
|
||||
zeros.flags(iosb.flags());
|
||||
zeros.unsetf(std::ios::showpos); // Ignore showpos because must be negative.
|
||||
zeros.precision(iosb.precision());
|
||||
//zeros.width is set by put_num_and_fill
|
||||
zeros.fill(static_cast<char>(fill));
|
||||
zeros << ValType(0);
|
||||
put_num_and_fill(it, iosb, prefix_minus, zeros.str().c_str(), fill, val);
|
||||
}
|
||||
else
|
||||
{ // Output the platform default for positive and negative zero.
|
||||
put_num_and_fill(it, iosb, null_string, null_string, fill, val);
|
||||
}
|
||||
break;
|
||||
|
||||
default: // Normal non-zero finite value.
|
||||
it = std::num_put<CharType, OutputIterator>::do_put(it, iosb, fill, val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template<class ValType>
|
||||
void put_num_and_fill(
|
||||
OutputIterator& it, std::ios_base& iosb, const CharType* prefix,
|
||||
const CharType* body, CharType fill, ValType val) const
|
||||
{
|
||||
int prefix_length = prefix ? (int)std::char_traits<CharType>::length(prefix) : 0;
|
||||
int body_length = body ? (int)std::char_traits<CharType>::length(body) : 0;
|
||||
int width = prefix_length + body_length;
|
||||
std::ios_base::fmtflags adjust = iosb.flags() & std::ios_base::adjustfield;
|
||||
const std::ctype<CharType>& ct
|
||||
= std::use_facet<std::ctype<CharType> >(iosb.getloc());
|
||||
|
||||
if(body || prefix)
|
||||
{ // adjust == std::ios_base::right, so leading fill needed.
|
||||
if(adjust != std::ios_base::internal && adjust != std::ios_base::left)
|
||||
put_fill(it, iosb, fill, width);
|
||||
}
|
||||
|
||||
if(prefix)
|
||||
{ // Adjust width for prefix.
|
||||
while(*prefix)
|
||||
*it = *(prefix++);
|
||||
iosb.width( iosb.width() - prefix_length );
|
||||
width -= prefix_length;
|
||||
}
|
||||
|
||||
if(body)
|
||||
{ //
|
||||
if(adjust == std::ios_base::internal)
|
||||
{ // Put fill between sign and digits.
|
||||
put_fill(it, iosb, fill, width);
|
||||
}
|
||||
if(iosb.flags() & std::ios_base::uppercase)
|
||||
{
|
||||
while(*body)
|
||||
*it = ct.toupper(*(body++));
|
||||
}
|
||||
else
|
||||
{
|
||||
while(*body)
|
||||
*it = *(body++);
|
||||
}
|
||||
|
||||
if(adjust == std::ios_base::left)
|
||||
put_fill(it, iosb, fill, width);
|
||||
}
|
||||
else
|
||||
{
|
||||
it = std::num_put<CharType, OutputIterator>::do_put(it, iosb, fill, val);
|
||||
}
|
||||
}
|
||||
|
||||
void put_fill(
|
||||
OutputIterator& it, std::ios_base& iosb, CharType fill, int width) const
|
||||
{ // Insert fill chars.
|
||||
for(std::streamsize i = iosb.width() - static_cast<std::streamsize>(width); i > 0; --i)
|
||||
*it = fill;
|
||||
}
|
||||
|
||||
private:
|
||||
const int flags_;
|
||||
};
|
||||
|
||||
|
||||
// class nonfinite_num_get ------------------------------------------------------
|
||||
|
||||
template<
|
||||
class CharType,
|
||||
class InputIterator = std::istreambuf_iterator<CharType>
|
||||
>
|
||||
class nonfinite_num_get : public std::num_get<CharType, InputIterator>
|
||||
{
|
||||
|
||||
public:
|
||||
explicit nonfinite_num_get(int flags = 0) : flags_(flags)
|
||||
{}
|
||||
|
||||
protected: // float, double and long double versions of do_get.
|
||||
virtual InputIterator do_get(
|
||||
InputIterator it, InputIterator end, std::ios_base& iosb,
|
||||
std::ios_base::iostate& state, float& val) const
|
||||
{
|
||||
get_and_check_eof(it, end, iosb, state, val);
|
||||
return it;
|
||||
}
|
||||
|
||||
virtual InputIterator do_get(
|
||||
InputIterator it, InputIterator end, std::ios_base& iosb,
|
||||
std::ios_base::iostate& state, double& val) const
|
||||
{
|
||||
get_and_check_eof(it, end, iosb, state, val);
|
||||
return it;
|
||||
}
|
||||
|
||||
virtual InputIterator do_get(
|
||||
InputIterator it, InputIterator end, std::ios_base& iosb,
|
||||
std::ios_base::iostate& state, long double& val) const
|
||||
{
|
||||
get_and_check_eof(it, end, iosb, state, val);
|
||||
return it;
|
||||
}
|
||||
|
||||
//..............................................................................
|
||||
|
||||
private:
|
||||
template<class ValType> static ValType positive_nan()
|
||||
{
|
||||
// On some platforms quiet_NaN() may be negative.
|
||||
return (boost::math::copysign)(
|
||||
std::numeric_limits<ValType>::quiet_NaN(), static_cast<ValType>(1)
|
||||
);
|
||||
// static_cast<ValType>(1) added Paul A. Bristow 5 Apr 11
|
||||
}
|
||||
|
||||
template<class ValType> void get_and_check_eof
|
||||
(
|
||||
InputIterator& it, InputIterator end, std::ios_base& iosb,
|
||||
std::ios_base::iostate& state, ValType& val
|
||||
) const
|
||||
{
|
||||
get_signed(it, end, iosb, state, val);
|
||||
if(it == end)
|
||||
state |= std::ios_base::eofbit;
|
||||
}
|
||||
|
||||
template<class ValType> void get_signed
|
||||
(
|
||||
InputIterator& it, InputIterator end, std::ios_base& iosb,
|
||||
std::ios_base::iostate& state, ValType& val
|
||||
) const
|
||||
{
|
||||
const std::ctype<CharType>& ct
|
||||
= std::use_facet<std::ctype<CharType> >(iosb.getloc());
|
||||
|
||||
char c = peek_char(it, end, ct);
|
||||
|
||||
bool negative = (c == '-');
|
||||
|
||||
if(negative || c == '+')
|
||||
{
|
||||
++it;
|
||||
c = peek_char(it, end, ct);
|
||||
if(c == '-' || c == '+')
|
||||
{ // Without this check, "++5" etc would be accepted.
|
||||
state |= std::ios_base::failbit;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
get_unsigned(it, end, iosb, ct, state, val);
|
||||
|
||||
if(negative)
|
||||
{
|
||||
val = (boost::math::changesign)(val);
|
||||
}
|
||||
} // void get_signed
|
||||
|
||||
template<class ValType> void get_unsigned
|
||||
( //! Get an unsigned floating-point value into val,
|
||||
//! but checking for letters indicating non-finites.
|
||||
InputIterator& it, InputIterator end, std::ios_base& iosb,
|
||||
const std::ctype<CharType>& ct,
|
||||
std::ios_base::iostate& state, ValType& val
|
||||
) const
|
||||
{
|
||||
switch(peek_char(it, end, ct))
|
||||
{
|
||||
case 'i':
|
||||
get_i(it, end, ct, state, val);
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
get_n(it, end, ct, state, val);
|
||||
break;
|
||||
|
||||
case 'q':
|
||||
case 's':
|
||||
get_q(it, end, ct, state, val);
|
||||
break;
|
||||
|
||||
default: // Got a normal floating-point value into val.
|
||||
it = std::num_get<CharType, InputIterator>::do_get(
|
||||
it, end, iosb, state, val);
|
||||
if((flags_ & legacy) && val == static_cast<ValType>(1)
|
||||
&& peek_char(it, end, ct) == '#')
|
||||
get_one_hash(it, end, ct, state, val);
|
||||
break;
|
||||
}
|
||||
} // get_unsigned
|
||||
|
||||
//..........................................................................
|
||||
|
||||
template<class ValType> void get_i
|
||||
( // Get the rest of all strings starting with 'i', expect "inf", "infinity".
|
||||
InputIterator& it, InputIterator end, const std::ctype<CharType>& ct,
|
||||
std::ios_base::iostate& state, ValType& val
|
||||
) const
|
||||
{
|
||||
if(!std::numeric_limits<ValType>::has_infinity
|
||||
|| (flags_ & trap_infinity))
|
||||
{
|
||||
state |= std::ios_base::failbit;
|
||||
return;
|
||||
}
|
||||
|
||||
++it;
|
||||
if(!match_string(it, end, ct, "nf"))
|
||||
{
|
||||
state |= std::ios_base::failbit;
|
||||
return;
|
||||
}
|
||||
|
||||
if(peek_char(it, end, ct) != 'i')
|
||||
{
|
||||
val = std::numeric_limits<ValType>::infinity(); // "inf"
|
||||
return;
|
||||
}
|
||||
|
||||
++it;
|
||||
if(!match_string(it, end, ct, "nity"))
|
||||
{ // Expected "infinity"
|
||||
state |= std::ios_base::failbit;
|
||||
return;
|
||||
}
|
||||
|
||||
val = std::numeric_limits<ValType>::infinity(); // "infinity"
|
||||
} // void get_i
|
||||
|
||||
template<class ValType> void get_n
|
||||
( // Get expected strings after 'n', "nan", "nanq", "nans", "nan(...)"
|
||||
InputIterator& it, InputIterator end, const std::ctype<CharType>& ct,
|
||||
std::ios_base::iostate& state, ValType& val
|
||||
) const
|
||||
{
|
||||
if(!std::numeric_limits<ValType>::has_quiet_NaN
|
||||
|| (flags_ & trap_nan)) {
|
||||
state |= std::ios_base::failbit;
|
||||
return;
|
||||
}
|
||||
|
||||
++it;
|
||||
if(!match_string(it, end, ct, "an"))
|
||||
{
|
||||
state |= std::ios_base::failbit;
|
||||
return;
|
||||
}
|
||||
|
||||
switch(peek_char(it, end, ct)) {
|
||||
case 'q':
|
||||
case 's':
|
||||
if(flags_ && legacy)
|
||||
++it;
|
||||
break; // "nanq", "nans"
|
||||
|
||||
case '(': // Optional payload field in (...) follows.
|
||||
{
|
||||
++it;
|
||||
char c;
|
||||
while((c = peek_char(it, end, ct))
|
||||
&& c != ')' && c != ' ' && c != '\n' && c != '\t')
|
||||
++it;
|
||||
if(c != ')')
|
||||
{ // Optional payload field terminator missing!
|
||||
state |= std::ios_base::failbit;
|
||||
return;
|
||||
}
|
||||
++it;
|
||||
break; // "nan(...)"
|
||||
}
|
||||
|
||||
default:
|
||||
break; // "nan"
|
||||
}
|
||||
|
||||
val = positive_nan<ValType>();
|
||||
} // void get_n
|
||||
|
||||
template<class ValType> void get_q
|
||||
( // Get expected rest of string starting with 'q': "qnan".
|
||||
InputIterator& it, InputIterator end, const std::ctype<CharType>& ct,
|
||||
std::ios_base::iostate& state, ValType& val
|
||||
) const
|
||||
{
|
||||
if(!std::numeric_limits<ValType>::has_quiet_NaN
|
||||
|| (flags_ & trap_nan) || !(flags_ & legacy))
|
||||
{
|
||||
state |= std::ios_base::failbit;
|
||||
return;
|
||||
}
|
||||
|
||||
++it;
|
||||
if(!match_string(it, end, ct, "nan"))
|
||||
{
|
||||
state |= std::ios_base::failbit;
|
||||
return;
|
||||
}
|
||||
|
||||
val = positive_nan<ValType>(); // "QNAN"
|
||||
} // void get_q
|
||||
|
||||
template<class ValType> void get_one_hash
|
||||
( // Get expected string after having read "1.#": "1.#IND", "1.#QNAN", "1.#SNAN".
|
||||
InputIterator& it, InputIterator end, const std::ctype<CharType>& ct,
|
||||
std::ios_base::iostate& state, ValType& val
|
||||
) const
|
||||
{
|
||||
|
||||
++it;
|
||||
switch(peek_char(it, end, ct))
|
||||
{
|
||||
case 'i': // from IND (indeterminate), considered same a QNAN.
|
||||
get_one_hash_i(it, end, ct, state, val); // "1.#IND"
|
||||
return;
|
||||
|
||||
case 'q': // from QNAN
|
||||
case 's': // from SNAN - treated the same as QNAN.
|
||||
if(std::numeric_limits<ValType>::has_quiet_NaN
|
||||
&& !(flags_ & trap_nan))
|
||||
{
|
||||
++it;
|
||||
if(match_string(it, end, ct, "nan"))
|
||||
{ // "1.#QNAN", "1.#SNAN"
|
||||
// ++it; // removed as caused assert() cannot increment iterator).
|
||||
// (match_string consumes string, so not needed?).
|
||||
// https://svn.boost.org/trac/boost/ticket/5467
|
||||
// Change in nonfinite_num_facet.hpp Paul A. Bristow 11 Apr 11 makes legacy_test.cpp work OK.
|
||||
val = positive_nan<ValType>(); // "1.#QNAN"
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
state |= std::ios_base::failbit;
|
||||
} // void get_one_hash
|
||||
|
||||
template<class ValType> void get_one_hash_i
|
||||
( // Get expected strings after 'i', "1.#INF", 1.#IND".
|
||||
InputIterator& it, InputIterator end, const std::ctype<CharType>& ct,
|
||||
std::ios_base::iostate& state, ValType& val
|
||||
) const
|
||||
{
|
||||
++it;
|
||||
|
||||
if(peek_char(it, end, ct) == 'n')
|
||||
{
|
||||
++it;
|
||||
switch(peek_char(it, end, ct))
|
||||
{
|
||||
case 'f': // "1.#INF"
|
||||
if(std::numeric_limits<ValType>::has_infinity
|
||||
&& !(flags_ & trap_infinity))
|
||||
{
|
||||
++it;
|
||||
val = std::numeric_limits<ValType>::infinity();
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'd': // 1.#IND"
|
||||
if(std::numeric_limits<ValType>::has_quiet_NaN
|
||||
&& !(flags_ & trap_nan))
|
||||
{
|
||||
++it;
|
||||
val = positive_nan<ValType>();
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
state |= std::ios_base::failbit;
|
||||
} // void get_one_hash_i
|
||||
|
||||
//..........................................................................
|
||||
|
||||
char peek_char
|
||||
( //! \return next char in the input buffer, ensuring lowercase (but do not 'consume' char).
|
||||
InputIterator& it, InputIterator end,
|
||||
const std::ctype<CharType>& ct
|
||||
) const
|
||||
{
|
||||
if(it == end) return 0;
|
||||
return ct.narrow(ct.tolower(*it), 0); // Always tolower to ensure case insensitive.
|
||||
}
|
||||
|
||||
bool match_string
|
||||
( //! Match remaining chars to expected string (case insensitive),
|
||||
//! consuming chars that match OK.
|
||||
//! \return true if matched expected string, else false.
|
||||
InputIterator& it, InputIterator end,
|
||||
const std::ctype<CharType>& ct,
|
||||
const char* s
|
||||
) const
|
||||
{
|
||||
while(it != end && *s && *s == ct.narrow(ct.tolower(*it), 0))
|
||||
{
|
||||
++s;
|
||||
++it; //
|
||||
}
|
||||
return !*s;
|
||||
} // bool match_string
|
||||
|
||||
private:
|
||||
const int flags_;
|
||||
}; //
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
} // namespace math
|
||||
} // namespace boost
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif // BOOST_MATH_NONFINITE_NUM_FACETS_HPP
|
||||
|
||||
1101
code_isotrope/boost/math/special_functions/owens_t.hpp
Executable file
1101
code_isotrope/boost/math/special_functions/owens_t.hpp
Executable file
File diff suppressed because it is too large
Load Diff
83
code_isotrope/boost/math/special_functions/polygamma.hpp
Executable file
83
code_isotrope/boost/math/special_functions/polygamma.hpp
Executable file
@@ -0,0 +1,83 @@
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright 2013 Nikhar Agrawal
|
||||
// Copyright 2013 Christopher Kormanyos
|
||||
// Copyright 2014 John Maddock
|
||||
// Copyright 2013 Paul Bristow
|
||||
// Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef _BOOST_POLYGAMMA_2013_07_30_HPP_
|
||||
#define _BOOST_POLYGAMMA_2013_07_30_HPP_
|
||||
|
||||
#include <boost/math/special_functions/factorials.hpp>
|
||||
#include <boost/math/special_functions/detail/polygamma.hpp>
|
||||
#include <boost/math/special_functions/trigamma.hpp>
|
||||
|
||||
namespace boost { namespace math {
|
||||
|
||||
|
||||
template<class T, class Policy>
|
||||
inline typename tools::promote_args<T>::type polygamma(const int n, T x, const Policy& pol)
|
||||
{
|
||||
//
|
||||
// Filter off special cases right at the start:
|
||||
//
|
||||
if(n == 0)
|
||||
return boost::math::digamma(x, pol);
|
||||
if(n == 1)
|
||||
return boost::math::trigamma(x, pol);
|
||||
//
|
||||
// We've found some standard library functions to misbehave if any FPU exception flags
|
||||
// are set prior to their call, this code will clear those flags, then reset them
|
||||
// on exit:
|
||||
//
|
||||
BOOST_FPU_EXCEPTION_GUARD
|
||||
//
|
||||
// The type of the result - the common type of T and U after
|
||||
// any integer types have been promoted to double:
|
||||
//
|
||||
typedef typename tools::promote_args<T>::type result_type;
|
||||
//
|
||||
// The type used for the calculation. This may be a wider type than
|
||||
// the result in order to ensure full precision:
|
||||
//
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
//
|
||||
// The type of the policy to forward to the actual implementation.
|
||||
// We disable promotion of float and double as that's [possibly]
|
||||
// happened already in the line above. Also reset to the default
|
||||
// any policies we don't use (reduces code bloat if we're called
|
||||
// multiple times with differing policies we don't actually use).
|
||||
// Also normalise the type, again to reduce code bloat in case we're
|
||||
// called multiple times with functionally identical policies that happen
|
||||
// to be different types.
|
||||
//
|
||||
typedef typename policies::normalise<
|
||||
Policy,
|
||||
policies::promote_float<false>,
|
||||
policies::promote_double<false>,
|
||||
policies::discrete_quantile<>,
|
||||
policies::assert_undefined<> >::type forwarding_policy;
|
||||
//
|
||||
// Whew. Now we can make the actual call to the implementation.
|
||||
// Arguments are explicitly cast to the evaluation type, and the result
|
||||
// passed through checked_narrowing_cast which handles things like overflow
|
||||
// according to the policy passed:
|
||||
//
|
||||
return policies::checked_narrowing_cast<result_type, forwarding_policy>(
|
||||
detail::polygamma_imp(n, static_cast<value_type>(x), forwarding_policy()),
|
||||
"boost::math::polygamma<%1%>(int, %1%)");
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline typename tools::promote_args<T>::type polygamma(const int n, T x)
|
||||
{
|
||||
return boost::math::polygamma(n, x, policies::policy<>());
|
||||
}
|
||||
|
||||
} } // namespace boost::math
|
||||
|
||||
#endif // _BOOST_BERNOULLI_2013_05_30_HPP_
|
||||
|
||||
148
code_isotrope/boost/math/special_functions/pow.hpp
Executable file
148
code_isotrope/boost/math/special_functions/pow.hpp
Executable file
@@ -0,0 +1,148 @@
|
||||
// Boost pow.hpp header file
|
||||
// Computes a power with exponent known at compile-time
|
||||
|
||||
// (C) Copyright Bruno Lalande 2008.
|
||||
// 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)
|
||||
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
|
||||
#ifndef BOOST_MATH_POW_HPP
|
||||
#define BOOST_MATH_POW_HPP
|
||||
|
||||
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/math/policies/policy.hpp>
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
#include <boost/math/tools/promotion.hpp>
|
||||
#include <boost/mpl/greater_equal.hpp>
|
||||
|
||||
|
||||
namespace boost {
|
||||
namespace math {
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4702) // Unreachable code, only triggered in release mode and /W4
|
||||
#endif
|
||||
|
||||
namespace detail {
|
||||
|
||||
|
||||
template <int N, int M = N%2>
|
||||
struct positive_power
|
||||
{
|
||||
template <typename T>
|
||||
static T result(T base)
|
||||
{
|
||||
T power = positive_power<N/2>::result(base);
|
||||
return power * power;
|
||||
}
|
||||
};
|
||||
|
||||
template <int N>
|
||||
struct positive_power<N, 1>
|
||||
{
|
||||
template <typename T>
|
||||
static T result(T base)
|
||||
{
|
||||
T power = positive_power<N/2>::result(base);
|
||||
return base * power * power;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct positive_power<1, 1>
|
||||
{
|
||||
template <typename T>
|
||||
static T result(T base){ return base; }
|
||||
};
|
||||
|
||||
|
||||
template <int N, bool>
|
||||
struct power_if_positive
|
||||
{
|
||||
template <typename T, class Policy>
|
||||
static T result(T base, const Policy&)
|
||||
{ return positive_power<N>::result(base); }
|
||||
};
|
||||
|
||||
template <int N>
|
||||
struct power_if_positive<N, false>
|
||||
{
|
||||
template <typename T, class Policy>
|
||||
static T result(T base, const Policy& policy)
|
||||
{
|
||||
if (base == 0)
|
||||
{
|
||||
return policies::raise_overflow_error<T>(
|
||||
"boost::math::pow(%1%)",
|
||||
"Attempted to compute a negative power of 0",
|
||||
policy
|
||||
);
|
||||
}
|
||||
|
||||
return T(1) / positive_power<-N>::result(base);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct power_if_positive<0, true>
|
||||
{
|
||||
template <typename T, class Policy>
|
||||
static T result(T base, const Policy& policy)
|
||||
{
|
||||
if (base == 0)
|
||||
{
|
||||
return policies::raise_indeterminate_result_error<T>(
|
||||
"boost::math::pow(%1%)",
|
||||
"The result of pow<0>(%1%) is undetermined",
|
||||
base,
|
||||
T(1),
|
||||
policy
|
||||
);
|
||||
}
|
||||
|
||||
return T(1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <int N>
|
||||
struct select_power_if_positive
|
||||
{
|
||||
typedef typename mpl::greater_equal<
|
||||
mpl::int_<N>,
|
||||
mpl::int_<0>
|
||||
>::type is_positive;
|
||||
|
||||
typedef power_if_positive<N, is_positive::value> type;
|
||||
};
|
||||
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
||||
template <int N, typename T, class Policy>
|
||||
inline typename tools::promote_args<T>::type pow(T base, const Policy& policy)
|
||||
{
|
||||
typedef typename tools::promote_args<T>::type result_type;
|
||||
return detail::select_power_if_positive<N>::type::result(static_cast<result_type>(base), policy);
|
||||
}
|
||||
|
||||
|
||||
template <int N, typename T>
|
||||
inline typename tools::promote_args<T>::type pow(T base)
|
||||
{ return pow<N>(base, policies::policy<>()); }
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
} // namespace math
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif
|
||||
84
code_isotrope/boost/math/special_functions/powm1.hpp
Executable file
84
code_isotrope/boost/math/special_functions/powm1.hpp
Executable file
@@ -0,0 +1,84 @@
|
||||
// (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_POWM1
|
||||
#define BOOST_MATH_POWM1
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4702) // Unreachable code (release mode only warning)
|
||||
#endif
|
||||
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/math/special_functions/log1p.hpp>
|
||||
#include <boost/math/special_functions/expm1.hpp>
|
||||
#include <boost/math/special_functions/trunc.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
namespace boost{ namespace math{ namespace detail{
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T powm1_imp(const T x, const T y, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
static const char* function = "boost::math::powm1<%1%>(%1%, %1%)";
|
||||
|
||||
if (x > 0)
|
||||
{
|
||||
if ((fabs(y * (x - 1)) < 0.5) || (fabs(y) < 0.2))
|
||||
{
|
||||
// We don't have any good/quick approximation for log(x) * y
|
||||
// so just try it and see:
|
||||
T l = y * log(x);
|
||||
if (l < 0.5)
|
||||
return boost::math::expm1(l);
|
||||
if (l > boost::math::tools::log_max_value<T>())
|
||||
return boost::math::policies::raise_overflow_error<T>(function, 0, pol);
|
||||
// fall through....
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// y had better be an integer:
|
||||
if (boost::math::trunc(y) != y)
|
||||
return boost::math::policies::raise_domain_error<T>(function, "For non-integral exponent, expected base > 0 but got %1%", x, pol);
|
||||
if (boost::math::trunc(y / 2) == y / 2)
|
||||
return powm1_imp(T(-x), y, pol);
|
||||
}
|
||||
return pow(x, y) - 1;
|
||||
}
|
||||
|
||||
} // detail
|
||||
|
||||
template <class T1, class T2>
|
||||
inline typename tools::promote_args<T1, T2>::type
|
||||
powm1(const T1 a, const T2 z)
|
||||
{
|
||||
typedef typename tools::promote_args<T1, T2>::type result_type;
|
||||
return detail::powm1_imp(static_cast<result_type>(a), static_cast<result_type>(z), policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T1, class T2, class Policy>
|
||||
inline typename tools::promote_args<T1, T2>::type
|
||||
powm1(const T1 a, const T2 z, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T1, T2>::type result_type;
|
||||
return detail::powm1_imp(static_cast<result_type>(a), static_cast<result_type>(z), pol);
|
||||
}
|
||||
|
||||
} // namespace math
|
||||
} // namespace boost
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif // BOOST_MATH_POWM1
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
1239
code_isotrope/boost/math/special_functions/prime.hpp
Executable file
1239
code_isotrope/boost/math/special_functions/prime.hpp
Executable file
File diff suppressed because it is too large
Load Diff
134
code_isotrope/boost/math/special_functions/relative_difference.hpp
Executable file
134
code_isotrope/boost/math/special_functions/relative_difference.hpp
Executable file
@@ -0,0 +1,134 @@
|
||||
// (C) Copyright John Maddock 2006, 2015
|
||||
// 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_RELATIVE_ERROR
|
||||
#define BOOST_MATH_RELATIVE_ERROR
|
||||
|
||||
#include <boost/math/special_functions/fpclassify.hpp>
|
||||
#include <boost/math/tools/promotion.hpp>
|
||||
#include <boost/math/tools/precision.hpp>
|
||||
|
||||
namespace boost{
|
||||
namespace math{
|
||||
|
||||
template <class T, class U>
|
||||
typename boost::math::tools::promote_args<T,U>::type relative_difference(const T& arg_a, const U& arg_b)
|
||||
{
|
||||
typedef typename boost::math::tools::promote_args<T, U>::type result_type;
|
||||
result_type a = arg_a;
|
||||
result_type b = arg_b;
|
||||
BOOST_MATH_STD_USING
|
||||
#ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
|
||||
//
|
||||
// If math.h has no long double support we can't rely
|
||||
// on the math functions generating exponents outside
|
||||
// the range of a double:
|
||||
//
|
||||
result_type min_val = (std::max)(
|
||||
tools::min_value<result_type>(),
|
||||
static_cast<result_type>((std::numeric_limits<double>::min)()));
|
||||
result_type max_val = (std::min)(
|
||||
tools::max_value<result_type>(),
|
||||
static_cast<result_type>((std::numeric_limits<double>::max)()));
|
||||
#else
|
||||
result_type min_val = tools::min_value<result_type>();
|
||||
result_type max_val = tools::max_value<result_type>();
|
||||
#endif
|
||||
// Screen out NaN's first, if either value is a NaN then the distance is "infinite":
|
||||
if((boost::math::isnan)(a) || (boost::math::isnan)(b))
|
||||
return max_val;
|
||||
// Screen out infinites:
|
||||
if(fabs(b) > max_val)
|
||||
{
|
||||
if(fabs(a) > max_val)
|
||||
return (a < 0) == (b < 0) ? 0 : max_val; // one infinity is as good as another!
|
||||
else
|
||||
return max_val; // one infinity and one finite value implies infinite difference
|
||||
}
|
||||
else if(fabs(a) > max_val)
|
||||
return max_val; // one infinity and one finite value implies infinite difference
|
||||
|
||||
//
|
||||
// If the values have different signs, treat as infinite difference:
|
||||
//
|
||||
if(((a < 0) != (b < 0)) && (a != 0) && (b != 0))
|
||||
return max_val;
|
||||
a = fabs(a);
|
||||
b = fabs(b);
|
||||
//
|
||||
// Now deal with zero's, if one value is zero (or denorm) then treat it the same as
|
||||
// min_val for the purposes of the calculation that follows:
|
||||
//
|
||||
if(a < min_val)
|
||||
a = min_val;
|
||||
if(b < min_val)
|
||||
b = min_val;
|
||||
|
||||
return (std::max)(fabs((a - b) / a), fabs((a - b) / b));
|
||||
}
|
||||
|
||||
#if (defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)) && (LDBL_MAX_EXP <= DBL_MAX_EXP)
|
||||
template <>
|
||||
inline boost::math::tools::promote_args<double, double>::type relative_difference(const double& arg_a, const double& arg_b)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
double a = arg_a;
|
||||
double b = arg_b;
|
||||
//
|
||||
// On Mac OS X we evaluate "double" functions at "long double" precision,
|
||||
// but "long double" actually has a very slightly narrower range than "double"!
|
||||
// Therefore use the range of "long double" as our limits since results outside
|
||||
// that range may have been truncated to 0 or INF:
|
||||
//
|
||||
double min_val = (std::max)((double)tools::min_value<long double>(), tools::min_value<double>());
|
||||
double max_val = (std::min)((double)tools::max_value<long double>(), tools::max_value<double>());
|
||||
|
||||
// Screen out NaN's first, if either value is a NaN then the distance is "infinite":
|
||||
if((boost::math::isnan)(a) || (boost::math::isnan)(b))
|
||||
return max_val;
|
||||
// Screen out infinites:
|
||||
if(fabs(b) > max_val)
|
||||
{
|
||||
if(fabs(a) > max_val)
|
||||
return 0; // one infinity is as good as another!
|
||||
else
|
||||
return max_val; // one infinity and one finite value implies infinite difference
|
||||
}
|
||||
else if(fabs(a) > max_val)
|
||||
return max_val; // one infinity and one finite value implies infinite difference
|
||||
|
||||
//
|
||||
// If the values have different signs, treat as infinite difference:
|
||||
//
|
||||
if(((a < 0) != (b < 0)) && (a != 0) && (b != 0))
|
||||
return max_val;
|
||||
a = fabs(a);
|
||||
b = fabs(b);
|
||||
//
|
||||
// Now deal with zero's, if one value is zero (or denorm) then treat it the same as
|
||||
// min_val for the purposes of the calculation that follows:
|
||||
//
|
||||
if(a < min_val)
|
||||
a = min_val;
|
||||
if(b < min_val)
|
||||
b = min_val;
|
||||
|
||||
return (std::max)(fabs((a - b) / a), fabs((a - b) / b));
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class T, class U>
|
||||
inline typename boost::math::tools::promote_args<T, U>::type epsilon_difference(const T& arg_a, const U& arg_b)
|
||||
{
|
||||
typedef typename boost::math::tools::promote_args<T, U>::type result_type;
|
||||
result_type r = relative_difference(arg_a, arg_b);
|
||||
if(tools::max_value<result_type>() * boost::math::tools::epsilon<result_type>() < r)
|
||||
return tools::max_value<result_type>();
|
||||
return r / boost::math::tools::epsilon<result_type>();
|
||||
}
|
||||
} // namespace math
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
132
code_isotrope/boost/math/special_functions/round.hpp
Executable file
132
code_isotrope/boost/math/special_functions/round.hpp
Executable file
@@ -0,0 +1,132 @@
|
||||
// Copyright John Maddock 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_ROUND_HPP
|
||||
#define BOOST_MATH_ROUND_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/tools/config.hpp>
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/math/special_functions/fpclassify.hpp>
|
||||
|
||||
namespace boost{ namespace math{
|
||||
|
||||
namespace detail{
|
||||
|
||||
template <class T, class Policy>
|
||||
inline typename tools::promote_args<T>::type round(const T& v, const Policy& pol, const mpl::false_)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
typedef typename tools::promote_args<T>::type result_type;
|
||||
if(!(boost::math::isfinite)(v))
|
||||
return policies::raise_rounding_error("boost::math::round<%1%>(%1%)", 0, static_cast<result_type>(v), static_cast<result_type>(v), pol);
|
||||
//
|
||||
// The logic here is rather convoluted, but avoids a number of traps,
|
||||
// see discussion here https://github.com/boostorg/math/pull/8
|
||||
//
|
||||
if (-0.5 < v && v < 0.5)
|
||||
{
|
||||
// special case to avoid rounding error on the direct
|
||||
// predecessor of +0.5 resp. the direct successor of -0.5 in
|
||||
// IEEE floating point types
|
||||
return 0;
|
||||
}
|
||||
else if (v > 0)
|
||||
{
|
||||
// subtract v from ceil(v) first in order to avoid rounding
|
||||
// errors on largest representable integer numbers
|
||||
result_type c(ceil(v));
|
||||
return 0.5 < c - v ? c - 1 : c;
|
||||
}
|
||||
else
|
||||
{
|
||||
// see former branch
|
||||
result_type f(floor(v));
|
||||
return 0.5 < v - f ? f + 1 : f;
|
||||
}
|
||||
}
|
||||
template <class T, class Policy>
|
||||
inline typename tools::promote_args<T>::type round(const T& v, const Policy&, const mpl::true_)
|
||||
{
|
||||
return v;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class T, class Policy>
|
||||
inline typename tools::promote_args<T>::type round(const T& v, const Policy& pol)
|
||||
{
|
||||
return detail::round(v, pol, mpl::bool_<detail::is_integer_for_rounding<T>::value>());
|
||||
}
|
||||
template <class T>
|
||||
inline typename tools::promote_args<T>::type round(const T& v)
|
||||
{
|
||||
return round(v, policies::policy<>());
|
||||
}
|
||||
//
|
||||
// The following functions will not compile unless T has an
|
||||
// implicit convertion to the integer types. For user-defined
|
||||
// number types this will likely not be the case. In that case
|
||||
// these functions should either be specialized for the UDT in
|
||||
// question, or else overloads should be placed in the same
|
||||
// namespace as the UDT: these will then be found via argument
|
||||
// dependent lookup. See our concept archetypes for examples.
|
||||
//
|
||||
template <class T, class Policy>
|
||||
inline int iround(const T& v, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
T r = boost::math::round(v, pol);
|
||||
if((r > (std::numeric_limits<int>::max)()) || (r < (std::numeric_limits<int>::min)()))
|
||||
return static_cast<int>(policies::raise_rounding_error("boost::math::iround<%1%>(%1%)", 0, v, 0, pol));
|
||||
return static_cast<int>(r);
|
||||
}
|
||||
template <class T>
|
||||
inline int iround(const T& v)
|
||||
{
|
||||
return iround(v, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline long lround(const T& v, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
T r = boost::math::round(v, pol);
|
||||
if((r > (std::numeric_limits<long>::max)()) || (r < (std::numeric_limits<long>::min)()))
|
||||
return static_cast<long int>(policies::raise_rounding_error("boost::math::lround<%1%>(%1%)", 0, v, 0L, pol));
|
||||
return static_cast<long int>(r);
|
||||
}
|
||||
template <class T>
|
||||
inline long lround(const T& v)
|
||||
{
|
||||
return lround(v, policies::policy<>());
|
||||
}
|
||||
|
||||
#ifdef BOOST_HAS_LONG_LONG
|
||||
|
||||
template <class T, class Policy>
|
||||
inline boost::long_long_type llround(const T& v, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
T r = boost::math::round(v, pol);
|
||||
if((r > (std::numeric_limits<boost::long_long_type>::max)()) || (r < (std::numeric_limits<boost::long_long_type>::min)()))
|
||||
return static_cast<boost::long_long_type>(policies::raise_rounding_error("boost::math::llround<%1%>(%1%)", 0, v, static_cast<boost::long_long_type>(0), pol));
|
||||
return static_cast<boost::long_long_type>(r);
|
||||
}
|
||||
template <class T>
|
||||
inline boost::long_long_type llround(const T& v)
|
||||
{
|
||||
return llround(v, policies::policy<>());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_ROUND_HPP
|
||||
194
code_isotrope/boost/math/special_functions/sign.hpp
Executable file
194
code_isotrope/boost/math/special_functions/sign.hpp
Executable file
@@ -0,0 +1,194 @@
|
||||
// (C) Copyright John Maddock 2006.
|
||||
// (C) Copyright Johan Rade 2006.
|
||||
// (C) Copyright Paul A. Bristow 2011 (added changesign).
|
||||
|
||||
// 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_TOOLS_SIGN_HPP
|
||||
#define BOOST_MATH_TOOLS_SIGN_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/tools/config.hpp>
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/math/special_functions/detail/fp_traits.hpp>
|
||||
|
||||
namespace boost{ namespace math{
|
||||
|
||||
namespace detail {
|
||||
|
||||
// signbit
|
||||
|
||||
#ifdef BOOST_MATH_USE_STD_FPCLASSIFY
|
||||
template<class T>
|
||||
inline int signbit_impl(T x, native_tag const&)
|
||||
{
|
||||
return (std::signbit)(x) ? 1 : 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Generic versions first, note that these do not handle
|
||||
// signed zero or NaN.
|
||||
|
||||
template<class T>
|
||||
inline int signbit_impl(T x, generic_tag<true> const&)
|
||||
{
|
||||
return x < 0;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline int signbit_impl(T x, generic_tag<false> const&)
|
||||
{
|
||||
return x < 0;
|
||||
}
|
||||
|
||||
#if defined(__GNUC__) && (LDBL_MANT_DIG == 106)
|
||||
//
|
||||
// Special handling for GCC's "double double" type,
|
||||
// in this case the sign is the same as the sign we
|
||||
// get by casting to double, no overflow/underflow
|
||||
// can occur since the exponents are the same magnitude
|
||||
// for the two types:
|
||||
//
|
||||
inline int signbit_impl(long double x, generic_tag<true> const&)
|
||||
{
|
||||
return (boost::math::signbit)(static_cast<double>(x));
|
||||
}
|
||||
inline int signbit_impl(long double x, generic_tag<false> const&)
|
||||
{
|
||||
return (boost::math::signbit)(static_cast<double>(x));
|
||||
}
|
||||
#endif
|
||||
|
||||
template<class T>
|
||||
inline int signbit_impl(T x, ieee_copy_all_bits_tag const&)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
|
||||
|
||||
BOOST_DEDUCED_TYPENAME traits::bits a;
|
||||
traits::get_bits(x,a);
|
||||
return a & traits::sign ? 1 : 0;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline int signbit_impl(T x, ieee_copy_leading_bits_tag const&)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
|
||||
|
||||
BOOST_DEDUCED_TYPENAME traits::bits a;
|
||||
traits::get_bits(x,a);
|
||||
|
||||
return a & traits::sign ? 1 : 0;
|
||||
}
|
||||
|
||||
// Changesign
|
||||
|
||||
// Generic versions first, note that these do not handle
|
||||
// signed zero or NaN.
|
||||
|
||||
template<class T>
|
||||
inline T (changesign_impl)(T x, generic_tag<true> const&)
|
||||
{
|
||||
return -x;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline T (changesign_impl)(T x, generic_tag<false> const&)
|
||||
{
|
||||
return -x;
|
||||
}
|
||||
#if defined(__GNUC__) && (LDBL_MANT_DIG == 106)
|
||||
//
|
||||
// Special handling for GCC's "double double" type,
|
||||
// in this case we need to change the sign of both
|
||||
// components of the "double double":
|
||||
//
|
||||
inline long double (changesign_impl)(long double x, generic_tag<true> const&)
|
||||
{
|
||||
double* pd = reinterpret_cast<double*>(&x);
|
||||
pd[0] = boost::math::changesign(pd[0]);
|
||||
pd[1] = boost::math::changesign(pd[1]);
|
||||
return x;
|
||||
}
|
||||
inline long double (changesign_impl)(long double x, generic_tag<false> const&)
|
||||
{
|
||||
double* pd = reinterpret_cast<double*>(&x);
|
||||
pd[0] = boost::math::changesign(pd[0]);
|
||||
pd[1] = boost::math::changesign(pd[1]);
|
||||
return x;
|
||||
}
|
||||
#endif
|
||||
|
||||
template<class T>
|
||||
inline T changesign_impl(T x, ieee_copy_all_bits_tag const&)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::sign_change_type traits;
|
||||
|
||||
BOOST_DEDUCED_TYPENAME traits::bits a;
|
||||
traits::get_bits(x,a);
|
||||
a ^= traits::sign;
|
||||
traits::set_bits(x,a);
|
||||
return x;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline T (changesign_impl)(T x, ieee_copy_leading_bits_tag const&)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::sign_change_type traits;
|
||||
|
||||
BOOST_DEDUCED_TYPENAME traits::bits a;
|
||||
traits::get_bits(x,a);
|
||||
a ^= traits::sign;
|
||||
traits::set_bits(x,a);
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<class T> int (signbit)(T x)
|
||||
{
|
||||
typedef typename detail::fp_traits<T>::type traits;
|
||||
typedef typename traits::method method;
|
||||
// typedef typename boost::is_floating_point<T>::type fp_tag;
|
||||
typedef typename tools::promote_args_permissive<T>::type result_type;
|
||||
return detail::signbit_impl(static_cast<result_type>(x), method());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline int sign BOOST_NO_MACRO_EXPAND(const T& z)
|
||||
{
|
||||
return (z == 0) ? 0 : (boost::math::signbit)(z) ? -1 : 1;
|
||||
}
|
||||
|
||||
template <class T> typename tools::promote_args_permissive<T>::type (changesign)(const T& x)
|
||||
{ //!< \brief return unchanged binary pattern of x, except for change of sign bit.
|
||||
typedef typename detail::fp_traits<T>::sign_change_type traits;
|
||||
typedef typename traits::method method;
|
||||
// typedef typename boost::is_floating_point<T>::type fp_tag;
|
||||
typedef typename tools::promote_args_permissive<T>::type result_type;
|
||||
|
||||
return detail::changesign_impl(static_cast<result_type>(x), method());
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
inline typename tools::promote_args_permissive<T, U>::type
|
||||
copysign BOOST_NO_MACRO_EXPAND(const T& x, const U& y)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
typedef typename tools::promote_args_permissive<T, U>::type result_type;
|
||||
return (boost::math::signbit)(static_cast<result_type>(x)) != (boost::math::signbit)(static_cast<result_type>(y))
|
||||
? (boost::math::changesign)(static_cast<result_type>(x)) : static_cast<result_type>(x);
|
||||
}
|
||||
|
||||
} // namespace math
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif // BOOST_MATH_TOOLS_SIGN_HPP
|
||||
|
||||
|
||||
78
code_isotrope/boost/math/special_functions/sin_pi.hpp
Executable file
78
code_isotrope/boost/math/special_functions/sin_pi.hpp
Executable file
@@ -0,0 +1,78 @@
|
||||
// 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)
|
||||
|
||||
#ifndef BOOST_MATH_SIN_PI_HPP
|
||||
#define BOOST_MATH_SIN_PI_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/config/no_tr1/cmath.hpp>
|
||||
#include <boost/math/tools/config.hpp>
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/math/special_functions/trunc.hpp>
|
||||
#include <boost/math/tools/promotion.hpp>
|
||||
#include <boost/math/constants/constants.hpp>
|
||||
|
||||
namespace boost{ namespace math{ namespace detail{
|
||||
|
||||
template <class T, class Policy>
|
||||
T sin_pi_imp(T x, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING // ADL of std names
|
||||
if(x < 0)
|
||||
return -sin_pi(-x);
|
||||
// sin of pi*x:
|
||||
bool invert;
|
||||
if(x < 0.5)
|
||||
return sin(constants::pi<T>() * x);
|
||||
if(x < 1)
|
||||
{
|
||||
invert = true;
|
||||
x = -x;
|
||||
}
|
||||
else
|
||||
invert = false;
|
||||
|
||||
T rem = floor(x);
|
||||
if(itrunc(rem, pol) & 1)
|
||||
invert = !invert;
|
||||
rem = x - rem;
|
||||
if(rem > 0.5f)
|
||||
rem = 1 - rem;
|
||||
if(rem == 0.5f)
|
||||
return static_cast<T>(invert ? -1 : 1);
|
||||
|
||||
rem = sin(constants::pi<T>() * rem);
|
||||
return invert ? T(-rem) : rem;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class T, class Policy>
|
||||
inline typename tools::promote_args<T>::type sin_pi(T x, const Policy&)
|
||||
{
|
||||
typedef typename tools::promote_args<T>::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;
|
||||
return policies::checked_narrowing_cast<result_type, forwarding_policy>(boost::math::detail::sin_pi_imp<value_type>(x, forwarding_policy()), "cos_pi");
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typename tools::promote_args<T>::type sin_pi(T x)
|
||||
{
|
||||
return boost::math::sin_pi(x, policies::policy<>());
|
||||
}
|
||||
|
||||
} // namespace math
|
||||
} // namespace boost
|
||||
#endif
|
||||
|
||||
125
code_isotrope/boost/math/special_functions/sinc.hpp
Executable file
125
code_isotrope/boost/math/special_functions/sinc.hpp
Executable file
@@ -0,0 +1,125 @@
|
||||
// boost sinc.hpp header file
|
||||
|
||||
// (C) Copyright Hubert Holin 2001.
|
||||
// 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)
|
||||
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
#ifndef BOOST_SINC_HPP
|
||||
#define BOOST_SINC_HPP
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/tools/config.hpp>
|
||||
#include <boost/math/tools/precision.hpp>
|
||||
#include <boost/math/policies/policy.hpp>
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/config/no_tr1/cmath.hpp>
|
||||
#include <boost/limits.hpp>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
|
||||
// These are the the "Sinus Cardinal" functions.
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace math
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
// This is the "Sinus Cardinal" of index Pi.
|
||||
|
||||
template<typename T>
|
||||
inline T sinc_pi_imp(const T x)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
|
||||
if (abs(x) >= 3.3 * tools::forth_root_epsilon<T>())
|
||||
{
|
||||
return(sin(x)/x);
|
||||
}
|
||||
else
|
||||
{
|
||||
// |x| < (eps*120)^(1/4)
|
||||
return 1 - x * x / 6;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class T>
|
||||
inline typename tools::promote_args<T>::type sinc_pi(T x)
|
||||
{
|
||||
typedef typename tools::promote_args<T>::type result_type;
|
||||
return detail::sinc_pi_imp(static_cast<result_type>(x));
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline typename tools::promote_args<T>::type sinc_pi(T x, const Policy&)
|
||||
{
|
||||
typedef typename tools::promote_args<T>::type result_type;
|
||||
return detail::sinc_pi_imp(static_cast<result_type>(x));
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_TEMPLATE_TEMPLATES
|
||||
template<typename T, template<typename> class U>
|
||||
inline U<T> sinc_pi(const U<T> x)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
using ::std::numeric_limits;
|
||||
|
||||
T const taylor_0_bound = tools::epsilon<T>();
|
||||
T const taylor_2_bound = tools::root_epsilon<T>();
|
||||
T const taylor_n_bound = tools::forth_root_epsilon<T>();
|
||||
|
||||
if (abs(x) >= taylor_n_bound)
|
||||
{
|
||||
return(sin(x)/x);
|
||||
}
|
||||
else
|
||||
{
|
||||
// approximation by taylor series in x at 0 up to order 0
|
||||
#ifdef __MWERKS__
|
||||
U<T> result = static_cast<U<T> >(1);
|
||||
#else
|
||||
U<T> result = U<T>(1);
|
||||
#endif
|
||||
|
||||
if (abs(x) >= taylor_0_bound)
|
||||
{
|
||||
U<T> x2 = x*x;
|
||||
|
||||
// approximation by taylor series in x at 0 up to order 2
|
||||
result -= x2/static_cast<T>(6);
|
||||
|
||||
if (abs(x) >= taylor_2_bound)
|
||||
{
|
||||
// approximation by taylor series in x at 0 up to order 4
|
||||
result += (x2*x2)/static_cast<T>(120);
|
||||
}
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, template<typename> class U, class Policy>
|
||||
inline U<T> sinc_pi(const U<T> x, const Policy&)
|
||||
{
|
||||
return sinc_pi(x);
|
||||
}
|
||||
#endif /* BOOST_NO_TEMPLATE_TEMPLATES */
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* BOOST_SINC_HPP */
|
||||
|
||||
156
code_isotrope/boost/math/special_functions/sinhc.hpp
Executable file
156
code_isotrope/boost/math/special_functions/sinhc.hpp
Executable file
@@ -0,0 +1,156 @@
|
||||
// boost sinhc.hpp header file
|
||||
|
||||
// (C) Copyright Hubert Holin 2001.
|
||||
// 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)
|
||||
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
#ifndef BOOST_SINHC_HPP
|
||||
#define BOOST_SINHC_HPP
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/tools/config.hpp>
|
||||
#include <boost/math/tools/precision.hpp>
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/config/no_tr1/cmath.hpp>
|
||||
#include <boost/limits.hpp>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
|
||||
// These are the the "Hyperbolic Sinus Cardinal" functions.
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace math
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
// This is the "Hyperbolic Sinus Cardinal" of index Pi.
|
||||
|
||||
template<typename T>
|
||||
inline T sinhc_pi_imp(const T x)
|
||||
{
|
||||
#if defined(BOOST_NO_STDC_NAMESPACE) && !defined(__SUNPRO_CC)
|
||||
using ::abs;
|
||||
using ::sinh;
|
||||
using ::sqrt;
|
||||
#else /* BOOST_NO_STDC_NAMESPACE */
|
||||
using ::std::abs;
|
||||
using ::std::sinh;
|
||||
using ::std::sqrt;
|
||||
#endif /* BOOST_NO_STDC_NAMESPACE */
|
||||
|
||||
static T const taylor_0_bound = tools::epsilon<T>();
|
||||
static T const taylor_2_bound = sqrt(taylor_0_bound);
|
||||
static T const taylor_n_bound = sqrt(taylor_2_bound);
|
||||
|
||||
if (abs(x) >= taylor_n_bound)
|
||||
{
|
||||
return(sinh(x)/x);
|
||||
}
|
||||
else
|
||||
{
|
||||
// approximation by taylor series in x at 0 up to order 0
|
||||
T result = static_cast<T>(1);
|
||||
|
||||
if (abs(x) >= taylor_0_bound)
|
||||
{
|
||||
T x2 = x*x;
|
||||
|
||||
// approximation by taylor series in x at 0 up to order 2
|
||||
result += x2/static_cast<T>(6);
|
||||
|
||||
if (abs(x) >= taylor_2_bound)
|
||||
{
|
||||
// approximation by taylor series in x at 0 up to order 4
|
||||
result += (x2*x2)/static_cast<T>(120);
|
||||
}
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class T>
|
||||
inline typename tools::promote_args<T>::type sinhc_pi(T x)
|
||||
{
|
||||
typedef typename tools::promote_args<T>::type result_type;
|
||||
return detail::sinhc_pi_imp(static_cast<result_type>(x));
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline typename tools::promote_args<T>::type sinhc_pi(T x, const Policy&)
|
||||
{
|
||||
return boost::math::sinhc_pi(x);
|
||||
}
|
||||
|
||||
#ifdef BOOST_NO_TEMPLATE_TEMPLATES
|
||||
#else /* BOOST_NO_TEMPLATE_TEMPLATES */
|
||||
template<typename T, template<typename> class U>
|
||||
inline U<T> sinhc_pi(const U<T> x)
|
||||
{
|
||||
#if defined(BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL) || defined(__GNUC__)
|
||||
using namespace std;
|
||||
#elif defined(BOOST_NO_STDC_NAMESPACE) && !defined(__SUNPRO_CC)
|
||||
using ::abs;
|
||||
using ::sinh;
|
||||
using ::sqrt;
|
||||
#else /* BOOST_NO_STDC_NAMESPACE */
|
||||
using ::std::abs;
|
||||
using ::std::sinh;
|
||||
using ::std::sqrt;
|
||||
#endif /* BOOST_NO_STDC_NAMESPACE */
|
||||
|
||||
using ::std::numeric_limits;
|
||||
|
||||
static T const taylor_0_bound = tools::epsilon<T>();
|
||||
static T const taylor_2_bound = sqrt(taylor_0_bound);
|
||||
static T const taylor_n_bound = sqrt(taylor_2_bound);
|
||||
|
||||
if (abs(x) >= taylor_n_bound)
|
||||
{
|
||||
return(sinh(x)/x);
|
||||
}
|
||||
else
|
||||
{
|
||||
// approximation by taylor series in x at 0 up to order 0
|
||||
#ifdef __MWERKS__
|
||||
U<T> result = static_cast<U<T> >(1);
|
||||
#else
|
||||
U<T> result = U<T>(1);
|
||||
#endif
|
||||
|
||||
if (abs(x) >= taylor_0_bound)
|
||||
{
|
||||
U<T> x2 = x*x;
|
||||
|
||||
// approximation by taylor series in x at 0 up to order 2
|
||||
result += x2/static_cast<T>(6);
|
||||
|
||||
if (abs(x) >= taylor_2_bound)
|
||||
{
|
||||
// approximation by taylor series in x at 0 up to order 4
|
||||
result += (x2*x2)/static_cast<T>(120);
|
||||
}
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
}
|
||||
#endif /* BOOST_NO_TEMPLATE_TEMPLATES */
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* BOOST_SINHC_HPP */
|
||||
|
||||
205
code_isotrope/boost/math/special_functions/spherical_harmonic.hpp
Executable file
205
code_isotrope/boost/math/special_functions/spherical_harmonic.hpp
Executable file
@@ -0,0 +1,205 @@
|
||||
|
||||
// (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_SPHERICAL_HARMONIC_HPP
|
||||
#define BOOST_MATH_SPECIAL_SPHERICAL_HARMONIC_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/math/special_functions/legendre.hpp>
|
||||
#include <boost/math/tools/workaround.hpp>
|
||||
#include <complex>
|
||||
|
||||
namespace boost{
|
||||
namespace math{
|
||||
|
||||
namespace detail{
|
||||
|
||||
//
|
||||
// Calculates the prefix term that's common to the real
|
||||
// and imaginary parts. Does *not* fix up the sign of the result
|
||||
// though.
|
||||
//
|
||||
template <class T, class Policy>
|
||||
inline T spherical_harmonic_prefix(unsigned n, unsigned m, T theta, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
|
||||
if(m > n)
|
||||
return 0;
|
||||
|
||||
T sin_theta = sin(theta);
|
||||
T x = cos(theta);
|
||||
|
||||
T leg = detail::legendre_p_imp(n, m, x, static_cast<T>(pow(fabs(sin_theta), T(m))), pol);
|
||||
|
||||
T prefix = boost::math::tgamma_delta_ratio(static_cast<T>(n - m + 1), static_cast<T>(2 * m), pol);
|
||||
prefix *= (2 * n + 1) / (4 * constants::pi<T>());
|
||||
prefix = sqrt(prefix);
|
||||
return prefix * leg;
|
||||
}
|
||||
//
|
||||
// Real Part:
|
||||
//
|
||||
template <class T, class Policy>
|
||||
T spherical_harmonic_r(unsigned n, int m, T theta, T phi, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING // ADL of std functions
|
||||
|
||||
bool sign = false;
|
||||
if(m < 0)
|
||||
{
|
||||
// Reflect and adjust sign if m < 0:
|
||||
sign = m&1;
|
||||
m = abs(m);
|
||||
}
|
||||
if(m&1)
|
||||
{
|
||||
// Check phase if theta is outside [0, PI]:
|
||||
T mod = boost::math::tools::fmod_workaround(theta, T(2 * constants::pi<T>()));
|
||||
if(mod < 0)
|
||||
mod += 2 * constants::pi<T>();
|
||||
if(mod > constants::pi<T>())
|
||||
sign = !sign;
|
||||
}
|
||||
// Get the value and adjust sign as required:
|
||||
T prefix = spherical_harmonic_prefix(n, m, theta, pol);
|
||||
prefix *= cos(m * phi);
|
||||
return sign ? T(-prefix) : prefix;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
T spherical_harmonic_i(unsigned n, int m, T theta, T phi, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING // ADL of std functions
|
||||
|
||||
bool sign = false;
|
||||
if(m < 0)
|
||||
{
|
||||
// Reflect and adjust sign if m < 0:
|
||||
sign = !(m&1);
|
||||
m = abs(m);
|
||||
}
|
||||
if(m&1)
|
||||
{
|
||||
// Check phase if theta is outside [0, PI]:
|
||||
T mod = boost::math::tools::fmod_workaround(theta, T(2 * constants::pi<T>()));
|
||||
if(mod < 0)
|
||||
mod += 2 * constants::pi<T>();
|
||||
if(mod > constants::pi<T>())
|
||||
sign = !sign;
|
||||
}
|
||||
// Get the value and adjust sign as required:
|
||||
T prefix = spherical_harmonic_prefix(n, m, theta, pol);
|
||||
prefix *= sin(m * phi);
|
||||
return sign ? T(-prefix) : prefix;
|
||||
}
|
||||
|
||||
template <class T, class U, class Policy>
|
||||
std::complex<T> spherical_harmonic(unsigned n, int m, U theta, U phi, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
//
|
||||
// Sort out the signs:
|
||||
//
|
||||
bool r_sign = false;
|
||||
bool i_sign = false;
|
||||
if(m < 0)
|
||||
{
|
||||
// Reflect and adjust sign if m < 0:
|
||||
r_sign = m&1;
|
||||
i_sign = !(m&1);
|
||||
m = abs(m);
|
||||
}
|
||||
if(m&1)
|
||||
{
|
||||
// Check phase if theta is outside [0, PI]:
|
||||
U mod = boost::math::tools::fmod_workaround(theta, U(2 * constants::pi<U>()));
|
||||
if(mod < 0)
|
||||
mod += 2 * constants::pi<U>();
|
||||
if(mod > constants::pi<U>())
|
||||
{
|
||||
r_sign = !r_sign;
|
||||
i_sign = !i_sign;
|
||||
}
|
||||
}
|
||||
//
|
||||
// Calculate the value:
|
||||
//
|
||||
U prefix = spherical_harmonic_prefix(n, m, theta, pol);
|
||||
U r = prefix * cos(m * phi);
|
||||
U i = prefix * sin(m * phi);
|
||||
//
|
||||
// Add in the signs:
|
||||
//
|
||||
if(r_sign)
|
||||
r = -r;
|
||||
if(i_sign)
|
||||
i = -i;
|
||||
static const char* function = "boost::math::spherical_harmonic<%1%>(int, int, %1%, %1%)";
|
||||
return std::complex<T>(policies::checked_narrowing_cast<T, Policy>(r, function), policies::checked_narrowing_cast<T, Policy>(i, function));
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class T1, class T2, class Policy>
|
||||
inline std::complex<typename tools::promote_args<T1, T2>::type>
|
||||
spherical_harmonic(unsigned n, int m, T1 theta, T2 phi, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T1, T2>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
return detail::spherical_harmonic<result_type, value_type>(n, m, static_cast<value_type>(theta), static_cast<value_type>(phi), pol);
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
inline std::complex<typename tools::promote_args<T1, T2>::type>
|
||||
spherical_harmonic(unsigned n, int m, T1 theta, T2 phi)
|
||||
{
|
||||
return boost::math::spherical_harmonic(n, m, theta, phi, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T1, class T2, class Policy>
|
||||
inline typename tools::promote_args<T1, T2>::type
|
||||
spherical_harmonic_r(unsigned n, int m, T1 theta, T2 phi, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T1, T2>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(detail::spherical_harmonic_r(n, m, static_cast<value_type>(theta), static_cast<value_type>(phi), pol), "bost::math::spherical_harmonic_r<%1%>(unsigned, int, %1%, %1%)");
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
inline typename tools::promote_args<T1, T2>::type
|
||||
spherical_harmonic_r(unsigned n, int m, T1 theta, T2 phi)
|
||||
{
|
||||
return boost::math::spherical_harmonic_r(n, m, theta, phi, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T1, class T2, class Policy>
|
||||
inline typename tools::promote_args<T1, T2>::type
|
||||
spherical_harmonic_i(unsigned n, int m, T1 theta, T2 phi, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T1, T2>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(detail::spherical_harmonic_i(n, m, static_cast<value_type>(theta), static_cast<value_type>(phi), pol), "boost::math::spherical_harmonic_i<%1%>(unsigned, int, %1%, %1%)");
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
inline typename tools::promote_args<T1, T2>::type
|
||||
spherical_harmonic_i(unsigned n, int m, T1 theta, T2 phi)
|
||||
{
|
||||
return boost::math::spherical_harmonic_i(n, m, theta, phi, policies::policy<>());
|
||||
}
|
||||
|
||||
} // namespace math
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_MATH_SPECIAL_SPHERICAL_HARMONIC_HPP
|
||||
|
||||
|
||||
|
||||
48
code_isotrope/boost/math/special_functions/sqrt1pm1.hpp
Executable file
48
code_isotrope/boost/math/special_functions/sqrt1pm1.hpp
Executable file
@@ -0,0 +1,48 @@
|
||||
// (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_SQRT1PM1
|
||||
#define BOOST_MATH_SQRT1PM1
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/math/special_functions/log1p.hpp>
|
||||
#include <boost/math/special_functions/expm1.hpp>
|
||||
|
||||
//
|
||||
// This algorithm computes sqrt(1+x)-1 for small x:
|
||||
//
|
||||
|
||||
namespace boost{ namespace math{
|
||||
|
||||
template <class T, class Policy>
|
||||
inline typename tools::promote_args<T>::type sqrt1pm1(const T& val, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T>::type result_type;
|
||||
BOOST_MATH_STD_USING
|
||||
|
||||
if(fabs(result_type(val)) > 0.75)
|
||||
return sqrt(1 + result_type(val)) - 1;
|
||||
return boost::math::expm1(boost::math::log1p(val, pol) / 2, pol);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typename tools::promote_args<T>::type sqrt1pm1(const T& val)
|
||||
{
|
||||
return sqrt1pm1(val, policies::policy<>());
|
||||
}
|
||||
|
||||
} // namespace math
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_MATH_SQRT1PM1
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
469
code_isotrope/boost/math/special_functions/trigamma.hpp
Executable file
469
code_isotrope/boost/math/special_functions/trigamma.hpp
Executable file
@@ -0,0 +1,469 @@
|
||||
// (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_TRIGAMMA_HPP
|
||||
#define BOOST_MATH_SF_TRIGAMMA_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/math/tools/rational.hpp>
|
||||
#include <boost/math/tools/series.hpp>
|
||||
#include <boost/math/tools/promotion.hpp>
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
#include <boost/math/constants/constants.hpp>
|
||||
#include <boost/mpl/comparison.hpp>
|
||||
#include <boost/math/tools/big_constant.hpp>
|
||||
#include <boost/math/special_functions/polygamma.hpp>
|
||||
|
||||
namespace boost{
|
||||
namespace math{
|
||||
namespace detail{
|
||||
|
||||
template<class T, class Policy>
|
||||
T polygamma_imp(const int n, T x, const Policy &pol);
|
||||
|
||||
template <class T, class Policy>
|
||||
T trigamma_prec(T x, const mpl::int_<53>*, const Policy&)
|
||||
{
|
||||
// Max error in interpolated form: 3.736e-017
|
||||
static const T offset = BOOST_MATH_BIG_CONSTANT(T, 53, 2.1093254089355469);
|
||||
static const T P_1_2[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, -1.1093280605946045),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, -3.8310674472619321),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, -3.3703848401898283),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 0.28080574467981213),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 1.6638069578676164),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 0.64468386819102836),
|
||||
};
|
||||
static const T Q_1_2[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 1.0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 3.4535389668541151),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 4.5208926987851437),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 2.7012734178351534),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 0.64468798399785611),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, -0.20314516859987728e-6),
|
||||
};
|
||||
// Max error in interpolated form: 1.159e-017
|
||||
static const T P_2_4[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, -0.13803835004508849e-7),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 0.50000049158540261),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 1.6077979838469348),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 2.5645435828098254),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 2.0534873203680393),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 0.74566981111565923),
|
||||
};
|
||||
static const T Q_2_4[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 1.0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 2.8822787662376169),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 4.1681660554090917),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 2.7853527819234466),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 0.74967671848044792),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, -0.00057069112416246805),
|
||||
};
|
||||
// Maximum Deviation Found: 6.896e-018
|
||||
// Expected Error Term : -6.895e-018
|
||||
// Maximum Relative Change in Control Points : 8.497e-004
|
||||
static const T P_4_inf[] = {
|
||||
static_cast<T>(0.68947581948701249e-17L),
|
||||
static_cast<T>(0.49999999999998975L),
|
||||
static_cast<T>(1.0177274392923795L),
|
||||
static_cast<T>(2.498208511343429L),
|
||||
static_cast<T>(2.1921221359427595L),
|
||||
static_cast<T>(1.5897035272532764L),
|
||||
static_cast<T>(0.40154388356961734L),
|
||||
};
|
||||
static const T Q_4_inf[] = {
|
||||
static_cast<T>(1.0L),
|
||||
static_cast<T>(1.7021215452463932L),
|
||||
static_cast<T>(4.4290431747556469L),
|
||||
static_cast<T>(2.9745631894384922L),
|
||||
static_cast<T>(2.3013614809773616L),
|
||||
static_cast<T>(0.28360399799075752L),
|
||||
static_cast<T>(0.022892987908906897L),
|
||||
};
|
||||
|
||||
if(x <= 2)
|
||||
{
|
||||
return (offset + boost::math::tools::evaluate_polynomial(P_1_2, x) / tools::evaluate_polynomial(Q_1_2, x)) / (x * x);
|
||||
}
|
||||
else if(x <= 4)
|
||||
{
|
||||
T y = 1 / x;
|
||||
return (1 + tools::evaluate_polynomial(P_2_4, y) / tools::evaluate_polynomial(Q_2_4, y)) / x;
|
||||
}
|
||||
T y = 1 / x;
|
||||
return (1 + tools::evaluate_polynomial(P_4_inf, y) / tools::evaluate_polynomial(Q_4_inf, y)) / x;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
T trigamma_prec(T x, const mpl::int_<64>*, const Policy&)
|
||||
{
|
||||
// Max error in interpolated form: 1.178e-020
|
||||
static const T offset_1_2 = BOOST_MATH_BIG_CONSTANT(T, 64, 2.109325408935546875);
|
||||
static const T P_1_2[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -1.10932535608960258341),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -4.18793841543017129052),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -4.63865531898487734531),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.919832884430500908047),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.68074038333180423012),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.21172611429185622377),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.259635673503366427284),
|
||||
};
|
||||
static const T Q_1_2[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 3.77521119359546982995),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 5.664338024578956321),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 4.25995134879278028361),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.62956638448940402182),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.259635512844691089868),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.629642219810618032207e-8),
|
||||
};
|
||||
// Max error in interpolated form: 3.912e-020
|
||||
static const T P_2_8[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.387540035162952880976e-11),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.500000000276430504),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 3.21926880986360957306),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 10.2550347708483445775),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 18.9002075150709144043),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 21.0357215832399705625),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 13.4346512182925923978),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 3.98656291026448279118),
|
||||
};
|
||||
static const T Q_2_8[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 6.10520430478613667724),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 18.475001060603645512),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 31.7087534567758405638),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 31.908814523890465398),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 17.4175479039227084798),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 3.98749106958394941276),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.000115917322224411128566),
|
||||
};
|
||||
// Maximum Deviation Found: 2.635e-020
|
||||
// Expected Error Term : 2.635e-020
|
||||
// Maximum Relative Change in Control Points : 1.791e-003
|
||||
static const T P_8_inf[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.263527875092466899848e-19),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.500000000000000058145),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.0730121433777364138677),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.94505878379957149534),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.0517092358874932620529),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.07995383547483921121),
|
||||
};
|
||||
static const T Q_8_inf[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.187309046577818095504),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 3.95255391645238842975),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -1.14743283327078949087),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 2.52989799376344914499),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.627414303172402506396),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.141554248216425512536),
|
||||
};
|
||||
|
||||
if(x <= 2)
|
||||
{
|
||||
return (offset_1_2 + boost::math::tools::evaluate_polynomial(P_1_2, x) / tools::evaluate_polynomial(Q_1_2, x)) / (x * x);
|
||||
}
|
||||
else if(x <= 8)
|
||||
{
|
||||
T y = 1 / x;
|
||||
return (1 + tools::evaluate_polynomial(P_2_8, y) / tools::evaluate_polynomial(Q_2_8, y)) / x;
|
||||
}
|
||||
T y = 1 / x;
|
||||
return (1 + tools::evaluate_polynomial(P_8_inf, y) / tools::evaluate_polynomial(Q_8_inf, y)) / x;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
T trigamma_prec(T x, const mpl::int_<113>*, const Policy&)
|
||||
{
|
||||
// Max error in interpolated form: 1.916e-035
|
||||
|
||||
static const T P_1_2[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.999999999999999082554457936871832533),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -4.71237311120865266379041700054847734),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -7.94125711970499027763789342500817316),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -5.74657746697664735258222071695644535),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.404213349456398905981223965160595687),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.47877781178642876561595890095758896),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.07714151702455125992166949812126433),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.858877899162360138844032265418028567),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.20499222604410032375789018837922397),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.0272103140348194747360175268778415049),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.0015764849020876949848954081173520686),
|
||||
};
|
||||
static const T Q_1_2[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 4.71237311120863419878375031457715223),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 9.58619118655339853449127952145877467),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 11.0940067269829372437561421279054968),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 8.09075424749327792073276309969037885),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.87705890159891405185343806884451286),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.22758678701914477836330837816976782),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.249092040606385004109672077814668716),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.0295750413900655597027079600025569048),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.00157648490200498142247694709728858139),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.161264050344059471721062360645432809e-14),
|
||||
};
|
||||
|
||||
// Max error in interpolated form: 8.958e-035
|
||||
static const T P_2_4[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -2.55843734739907925764326773972215085),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -12.2830208240542011967952466273455887),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -23.9195022162767993526575786066414403),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -24.9256431504823483094158828285470862),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -14.7979122765478779075108064826412285),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -4.46654453928610666393276765059122272),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.0191439033405649675717082465687845002),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.515412052554351265708917209749037352),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.195378348786064304378247325360320038),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.0334761282624174313035014426794245393),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.002373665205942206348500250056602687),
|
||||
};
|
||||
static const T Q_2_4[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 4.80098558454419907830670928248659245),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 9.99220727843170133895059300223445265),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 11.8896146167631330735386697123464976),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 8.96613256683809091593793565879092581),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 4.47254136149624110878909334574485751),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.48600982028196527372434773913633152),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.319570735766764237068541501137990078),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.0407358345787680953107374215319322066),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.00237366520593271641375755486420859837),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.239554887903526152679337256236302116e-15),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.294749244740618656265237072002026314e-17),
|
||||
};
|
||||
|
||||
static const T y_offset_2_4 = BOOST_MATH_BIG_CONSTANT(T, 113, 3.558437347412109375);
|
||||
|
||||
// Max error in interpolated form: 4.319e-035
|
||||
static const T P_4_8[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.166626112697021464248967707021688845e-16),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.499999999999997739552090249208808197),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 6.40270945019053817915772473771553187),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 41.3833374155000608013677627389343329),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 166.803341854562809335667241074035245),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 453.39964786925369319960722793414521),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 851.153712317697055375935433362983944),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1097.70657567285059133109286478004458),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 938.431232478455316020076349367632922),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 487.268001604651932322080970189930074),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 119.953445242335730062471193124820659),
|
||||
};
|
||||
static const T Q_4_8[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 12.4720855670474488978638945855932398),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 78.6093129753298570701376952709727391),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 307.470246050318322489781182863190127),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 805.140686101151538537565264188630079),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1439.12019760292146454787601409644413),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1735.6105285756048831268586001383127),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1348.32500712856328019355198611280536),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 607.225985860570846699704222144650563),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 119.952317857277045332558673164517227),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.000140165918355036060868680809129436084),
|
||||
};
|
||||
|
||||
// Maximum Deviation Found: 2.867e-035
|
||||
// Expected Error Term : 2.866e-035
|
||||
// Maximum Relative Change in Control Points : 2.662e-004
|
||||
static const T P_8_16[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.184828315274146610610872315609837439e-19),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.500000000000000004122475157735807738),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.02533865247313349284875558880415875),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 13.5995927517457371243039532492642734),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 35.3132224283087906757037999452941588),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 67.1639424550714159157603179911505619),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 83.5767733658513967581959839367419891),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 71.073491212235705900866411319363501),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 35.8621515614725564575893663483998663),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 8.72152231639983491987779743154333318),
|
||||
};
|
||||
static const T Q_8_16[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 5.71734397161293452310624822415866372),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 25.293404179620438179337103263274815),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 62.2619767967468199111077640625328469),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 113.955048909238993473389714972250235),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 130.807138328938966981862203944329408),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 102.423146902337654110717764213057753),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 44.0424772805245202514468199602123565),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 8.89898032477904072082994913461386099),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.0296627336872039988632793863671456398),
|
||||
};
|
||||
// Maximum Deviation Found: 1.079e-035
|
||||
// Expected Error Term : -1.079e-035
|
||||
// Maximum Relative Change in Control Points : 7.884e-003
|
||||
static const T P_16_inf[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.500000000000000000000000000000087317),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.345625669885456215194494735902663968),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 9.62895499360842232127552650044647769),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.5936085382439026269301003761320812),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 49.459599118438883265036646019410669),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 7.77519237321893917784735690560496607),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 74.4536074488178075948642351179304121),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.75209340397069050436806159297952699),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 23.9292359711471667884504840186561598),
|
||||
};
|
||||
static const T Q_16_inf[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.357918006437579097055656138920742037),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 19.1386039850709849435325005484512944),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.874349081464143606016221431763364517),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 98.6516097434855572678195488061432509),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -16.1051972833382893468655223662534306),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 154.316860216253720989145047141653727),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -40.2026880424378986053105969312264534),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 60.1679136674264778074736441126810223),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -13.3414844622256422644504472438320114),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.53795636200649908779512969030363442),
|
||||
};
|
||||
|
||||
if(x <= 2)
|
||||
{
|
||||
return (2 + boost::math::tools::evaluate_polynomial(P_1_2, x) / tools::evaluate_polynomial(Q_1_2, x)) / (x * x);
|
||||
}
|
||||
else if(x <= 4)
|
||||
{
|
||||
return (y_offset_2_4 + boost::math::tools::evaluate_polynomial(P_2_4, x) / tools::evaluate_polynomial(Q_2_4, x)) / (x * x);
|
||||
}
|
||||
else if(x <= 8)
|
||||
{
|
||||
T y = 1 / x;
|
||||
return (1 + tools::evaluate_polynomial(P_4_8, y) / tools::evaluate_polynomial(Q_4_8, y)) / x;
|
||||
}
|
||||
else if(x <= 16)
|
||||
{
|
||||
T y = 1 / x;
|
||||
return (1 + tools::evaluate_polynomial(P_8_16, y) / tools::evaluate_polynomial(Q_8_16, y)) / x;
|
||||
}
|
||||
T y = 1 / x;
|
||||
return (1 + tools::evaluate_polynomial(P_16_inf, y) / tools::evaluate_polynomial(Q_16_inf, y)) / x;
|
||||
}
|
||||
|
||||
template <class T, class Tag, class Policy>
|
||||
T trigamma_imp(T x, const Tag* t, const Policy& pol)
|
||||
{
|
||||
//
|
||||
// This handles reflection of negative arguments, and all our
|
||||
// error handling, then forwards to the T-specific approximation.
|
||||
//
|
||||
BOOST_MATH_STD_USING // ADL of std functions.
|
||||
|
||||
T result = 0;
|
||||
//
|
||||
// Check for negative arguments and use reflection:
|
||||
//
|
||||
if(x <= 0)
|
||||
{
|
||||
// Reflect:
|
||||
T z = 1 - x;
|
||||
// Argument reduction for tan:
|
||||
if(floor(x) == x)
|
||||
{
|
||||
return policies::raise_pole_error<T>("boost::math::trigamma<%1%>(%1%)", 0, (1-x), pol);
|
||||
}
|
||||
T s = fabs(x) < fabs(z) ? boost::math::sin_pi(x, pol) : boost::math::sin_pi(z, pol);
|
||||
return -trigamma_imp(z, t, pol) + boost::math::pow<2>(constants::pi<T>()) / (s * s);
|
||||
}
|
||||
if(x < 1)
|
||||
{
|
||||
result = 1 / (x * x);
|
||||
x += 1;
|
||||
}
|
||||
return result + trigamma_prec(x, t, pol);
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
T trigamma_imp(T x, const mpl::int_<0>*, const Policy& pol)
|
||||
{
|
||||
return polygamma_imp(1, x, pol);
|
||||
}
|
||||
//
|
||||
// Initializer: ensure all our constants are initialized prior to the first call of main:
|
||||
//
|
||||
template <class T, class Policy>
|
||||
struct trigamma_initializer
|
||||
{
|
||||
struct init
|
||||
{
|
||||
init()
|
||||
{
|
||||
typedef typename policies::precision<T, Policy>::type precision_type;
|
||||
do_init(mpl::bool_<precision_type::value && (precision_type::value <= 113)>());
|
||||
}
|
||||
void do_init(const mpl::true_&)
|
||||
{
|
||||
boost::math::trigamma(T(2.5), Policy());
|
||||
}
|
||||
void do_init(const mpl::false_&){}
|
||||
void force_instantiate()const{}
|
||||
};
|
||||
static const init initializer;
|
||||
static void force_instantiate()
|
||||
{
|
||||
initializer.force_instantiate();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class Policy>
|
||||
const typename trigamma_initializer<T, Policy>::init trigamma_initializer<T, Policy>::initializer;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class T, class Policy>
|
||||
inline typename tools::promote_args<T>::type
|
||||
trigamma(T x, const Policy&)
|
||||
{
|
||||
typedef typename tools::promote_args<T>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
typedef typename policies::precision<T, Policy>::type precision_type;
|
||||
typedef typename mpl::if_<
|
||||
mpl::or_<
|
||||
mpl::less_equal<precision_type, mpl::int_<0> >,
|
||||
mpl::greater<precision_type, mpl::int_<114> >
|
||||
>,
|
||||
mpl::int_<0>,
|
||||
typename mpl::if_<
|
||||
mpl::less<precision_type, mpl::int_<54> >,
|
||||
mpl::int_<53>,
|
||||
typename mpl::if_<
|
||||
mpl::less<precision_type, mpl::int_<65> >,
|
||||
mpl::int_<64>,
|
||||
mpl::int_<113>
|
||||
>::type
|
||||
>::type
|
||||
>::type tag_type;
|
||||
|
||||
typedef typename policies::normalise<
|
||||
Policy,
|
||||
policies::promote_float<false>,
|
||||
policies::promote_double<false>,
|
||||
policies::discrete_quantile<>,
|
||||
policies::assert_undefined<> >::type forwarding_policy;
|
||||
|
||||
// Force initialization of constants:
|
||||
detail::trigamma_initializer<value_type, forwarding_policy>::force_instantiate();
|
||||
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(detail::trigamma_imp(
|
||||
static_cast<value_type>(x),
|
||||
static_cast<const tag_type*>(0), forwarding_policy()), "boost::math::trigamma<%1%>(%1%)");
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typename tools::promote_args<T>::type
|
||||
trigamma(T x)
|
||||
{
|
||||
return trigamma(x, policies::policy<>());
|
||||
}
|
||||
|
||||
} // namespace math
|
||||
} // namespace boost
|
||||
#endif
|
||||
|
||||
111
code_isotrope/boost/math/special_functions/trunc.hpp
Executable file
111
code_isotrope/boost/math/special_functions/trunc.hpp
Executable file
@@ -0,0 +1,111 @@
|
||||
// Copyright John Maddock 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_TRUNC_HPP
|
||||
#define BOOST_MATH_TRUNC_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/math/tools/config.hpp>
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
#include <boost/math/special_functions/fpclassify.hpp>
|
||||
|
||||
namespace boost{ namespace math{ namespace detail{
|
||||
|
||||
template <class T, class Policy>
|
||||
inline typename tools::promote_args<T>::type trunc(const T& v, const Policy& pol, const mpl::false_&)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
typedef typename tools::promote_args<T>::type result_type;
|
||||
if(!(boost::math::isfinite)(v))
|
||||
return policies::raise_rounding_error("boost::math::trunc<%1%>(%1%)", 0, static_cast<result_type>(v), static_cast<result_type>(v), pol);
|
||||
return (v >= 0) ? static_cast<result_type>(floor(v)) : static_cast<result_type>(ceil(v));
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline typename tools::promote_args<T>::type trunc(const T& v, const Policy&, const mpl::true_&)
|
||||
{
|
||||
return v;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline typename tools::promote_args<T>::type trunc(const T& v, const Policy& pol)
|
||||
{
|
||||
return detail::trunc(v, pol, mpl::bool_<detail::is_integer_for_rounding<T>::value>());
|
||||
}
|
||||
template <class T>
|
||||
inline typename tools::promote_args<T>::type trunc(const T& v)
|
||||
{
|
||||
return trunc(v, policies::policy<>());
|
||||
}
|
||||
//
|
||||
// The following functions will not compile unless T has an
|
||||
// implicit convertion to the integer types. For user-defined
|
||||
// number types this will likely not be the case. In that case
|
||||
// these functions should either be specialized for the UDT in
|
||||
// question, or else overloads should be placed in the same
|
||||
// namespace as the UDT: these will then be found via argument
|
||||
// dependent lookup. See our concept archetypes for examples.
|
||||
//
|
||||
template <class T, class Policy>
|
||||
inline int itrunc(const T& v, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
typedef typename tools::promote_args<T>::type result_type;
|
||||
result_type r = boost::math::trunc(v, pol);
|
||||
if((r > (std::numeric_limits<int>::max)()) || (r < (std::numeric_limits<int>::min)()))
|
||||
return static_cast<int>(policies::raise_rounding_error("boost::math::itrunc<%1%>(%1%)", 0, static_cast<result_type>(v), 0, pol));
|
||||
return static_cast<int>(r);
|
||||
}
|
||||
template <class T>
|
||||
inline int itrunc(const T& v)
|
||||
{
|
||||
return itrunc(v, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline long ltrunc(const T& v, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
typedef typename tools::promote_args<T>::type result_type;
|
||||
result_type r = boost::math::trunc(v, pol);
|
||||
if((r > (std::numeric_limits<long>::max)()) || (r < (std::numeric_limits<long>::min)()))
|
||||
return static_cast<long>(policies::raise_rounding_error("boost::math::ltrunc<%1%>(%1%)", 0, static_cast<result_type>(v), 0L, pol));
|
||||
return static_cast<long>(r);
|
||||
}
|
||||
template <class T>
|
||||
inline long ltrunc(const T& v)
|
||||
{
|
||||
return ltrunc(v, policies::policy<>());
|
||||
}
|
||||
|
||||
#ifdef BOOST_HAS_LONG_LONG
|
||||
|
||||
template <class T, class Policy>
|
||||
inline boost::long_long_type lltrunc(const T& v, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
typedef typename tools::promote_args<T>::type result_type;
|
||||
result_type r = boost::math::trunc(v, pol);
|
||||
if((r > (std::numeric_limits<boost::long_long_type>::max)()) || (r < (std::numeric_limits<boost::long_long_type>::min)()))
|
||||
return static_cast<boost::long_long_type>(policies::raise_rounding_error("boost::math::lltrunc<%1%>(%1%)", 0, v, static_cast<boost::long_long_type>(0), pol));
|
||||
return static_cast<boost::long_long_type>(r);
|
||||
}
|
||||
template <class T>
|
||||
inline boost::long_long_type lltrunc(const T& v)
|
||||
{
|
||||
return lltrunc(v, policies::policy<>());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_TRUNC_HPP
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user