update boost on linux
This commit is contained in:
169
linx64/include/boost/math/special_functions/chebyshev.hpp
Normal file
169
linx64/include/boost/math/special_functions/chebyshev.hpp
Normal 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
|
||||
@@ -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
|
||||
@@ -86,7 +86,7 @@
|
||||
class function_object_ai_and_ai_prime
|
||||
{
|
||||
public:
|
||||
function_object_ai_and_ai_prime(const Policy pol) : my_pol(pol) { }
|
||||
function_object_ai_and_ai_prime(const Policy& pol) : my_pol(pol) { }
|
||||
|
||||
boost::math::tuple<T, T> operator()(const T& x) const
|
||||
{
|
||||
@@ -137,7 +137,7 @@
|
||||
class function_object_bi_and_bi_prime
|
||||
{
|
||||
public:
|
||||
function_object_bi_and_bi_prime(const Policy pol) : my_pol(pol) { }
|
||||
function_object_bi_and_bi_prime(const Policy& pol) : my_pol(pol) { }
|
||||
|
||||
boost::math::tuple<T, T> operator()(const T& x) const
|
||||
{
|
||||
|
||||
@@ -9,67 +9,11 @@
|
||||
|
||||
#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>
|
||||
|
||||
#ifdef BOOST_HAS_THREADS
|
||||
|
||||
#ifndef BOOST_NO_CXX11_HDR_ATOMIC
|
||||
# include <atomic>
|
||||
# define BOOST_MATH_ATOMIC_NS std
|
||||
#if ATOMIC_INT_LOCK_FREE == 2
|
||||
typedef std::atomic<int> atomic_counter_type;
|
||||
typedef int atomic_integer_type;
|
||||
#elif ATOMIC_SHORT_LOCK_FREE == 2
|
||||
typedef std::atomic<short> atomic_counter_type;
|
||||
typedef short atomic_integer_type;
|
||||
#elif ATOMIC_LONG_LOCK_FREE == 2
|
||||
typedef std::atomic<long> atomic_counter_type;
|
||||
typedef long atomic_integer_type;
|
||||
#elif ATOMIC_LLONG_LOCK_FREE == 2
|
||||
typedef std::atomic<long long> atomic_counter_type;
|
||||
typedef long long atomic_integer_type;
|
||||
#else
|
||||
# define BOOST_MATH_NO_ATOMIC_INT
|
||||
#endif
|
||||
|
||||
#else // BOOST_NO_CXX11_HDR_ATOMIC
|
||||
//
|
||||
// We need Boost.Atomic, but on any platform that supports auto-linking we do
|
||||
// not need to link against a separate library:
|
||||
//
|
||||
#define BOOST_ATOMIC_NO_LIB
|
||||
#include <boost/atomic.hpp>
|
||||
# define BOOST_MATH_ATOMIC_NS boost
|
||||
|
||||
namespace boost{ namespace math{ namespace detail{
|
||||
|
||||
//
|
||||
// We need a type to use as an atomic counter:
|
||||
//
|
||||
#if BOOST_ATOMIC_INT_LOCK_FREE == 2
|
||||
typedef boost::atomic<int> atomic_counter_type;
|
||||
typedef int atomic_integer_type;
|
||||
#elif BOOST_ATOMIC_SHORT_LOCK_FREE == 2
|
||||
typedef boost::atomic<short> atomic_counter_type;
|
||||
typedef short atomic_integer_type;
|
||||
#elif BOOST_ATOMIC_LONG_LOCK_FREE == 2
|
||||
typedef boost::atomic<long> atomic_counter_type;
|
||||
typedef long atomic_integer_type;
|
||||
#elif BOOST_ATOMIC_LLONG_LOCK_FREE == 2
|
||||
typedef boost::atomic<long long> atomic_counter_type;
|
||||
typedef long long atomic_integer_type;
|
||||
#else
|
||||
# define BOOST_MATH_NO_ATOMIC_INT
|
||||
#endif
|
||||
|
||||
}}} // namespaces
|
||||
|
||||
#endif // BOOST_NO_CXX11_HDR_ATOMIC
|
||||
|
||||
#endif // BOOST_HAS_THREADS
|
||||
|
||||
namespace boost{ namespace math{ namespace detail{
|
||||
//
|
||||
// Asymptotic expansion for B2n due to
|
||||
@@ -248,9 +192,18 @@ struct fixed_vector : private std::allocator<T>
|
||||
}
|
||||
~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]; }
|
||||
|
||||
@@ -15,9 +15,19 @@
|
||||
#include <boost/math/tools/big_constant.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#if defined(__GNUC__) && defined(BOOST_MATH_USE_FLOAT128)
|
||||
//
|
||||
// This is the only way we can avoid
|
||||
// warning: non-standard suffix on floating constant [-Wpedantic]
|
||||
// when building with -Wall -pedantic. Neither __extension__
|
||||
// nor #pragma dianostic ignored work :(
|
||||
//
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
// Modified Bessel function of the first kind of order zero
|
||||
// we use the approximating forms derived in:
|
||||
// "Rational Approximations for the Modified Bessel Function of the First Kind – I0(x) for Computations with Double Precision"
|
||||
// "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.
|
||||
@@ -532,7 +542,7 @@ template <typename T>
|
||||
inline T bessel_i0(const T& x)
|
||||
{
|
||||
typedef mpl::int_<
|
||||
std::numeric_limits<T>::digits == 0 ?
|
||||
((std::numeric_limits<T>::digits == 0) || (std::numeric_limits<T>::radix != 2)) ?
|
||||
0 :
|
||||
std::numeric_limits<T>::digits <= 24 ?
|
||||
24 :
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
// 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"
|
||||
// "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.
|
||||
@@ -16,6 +21,16 @@
|
||||
#include <boost/math/tools/big_constant.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#if defined(__GNUC__) && defined(BOOST_MATH_USE_FLOAT128)
|
||||
//
|
||||
// This is the only way we can avoid
|
||||
// warning: non-standard suffix on floating constant [-Wpedantic]
|
||||
// when building with -Wall -pedantic. Neither __extension__
|
||||
// nor #pragma dianostic ignored work :(
|
||||
//
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
// Modified Bessel function of the first kind of order one
|
||||
// minimax rational approximations on intervals, see
|
||||
// Blair and Edwards, Chalk River Report AECL-4928, 1974
|
||||
@@ -555,7 +570,7 @@ template <typename T>
|
||||
inline T bessel_i1(const T& x)
|
||||
{
|
||||
typedef mpl::int_<
|
||||
std::numeric_limits<T>::digits == 0 ?
|
||||
((std::numeric_limits<T>::digits == 0) || (std::numeric_limits<T>::radix != 2)) ?
|
||||
0 :
|
||||
std::numeric_limits<T>::digits <= 24 ?
|
||||
24 :
|
||||
|
||||
@@ -15,6 +15,16 @@
|
||||
#include <boost/math/tools/big_constant.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#if defined(__GNUC__) && defined(BOOST_MATH_USE_FLOAT128)
|
||||
//
|
||||
// This is the only way we can avoid
|
||||
// warning: non-standard suffix on floating constant [-Wpedantic]
|
||||
// when building with -Wall -pedantic. Neither __extension__
|
||||
// nor #pragma dianostic ignored work :(
|
||||
//
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
// Bessel function of the first kind of order zero
|
||||
// x <= 8, minimax rational approximations on root-bracketing intervals
|
||||
// x > 8, Hankel asymptotic expansion in Hart, Computer Approximations, 1968
|
||||
|
||||
@@ -15,6 +15,16 @@
|
||||
#include <boost/math/tools/big_constant.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#if defined(__GNUC__) && defined(BOOST_MATH_USE_FLOAT128)
|
||||
//
|
||||
// This is the only way we can avoid
|
||||
// warning: non-standard suffix on floating constant [-Wpedantic]
|
||||
// when building with -Wall -pedantic. Neither __extension__
|
||||
// nor #pragma dianostic ignored work :(
|
||||
//
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
// Bessel function of the first kind of order one
|
||||
// x <= 8, minimax rational approximations on root-bracketing intervals
|
||||
// x > 8, Hankel asymptotic expansion in Hart, Computer Approximations, 1968
|
||||
|
||||
@@ -18,6 +18,16 @@
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#if defined(__GNUC__) && defined(BOOST_MATH_USE_FLOAT128)
|
||||
//
|
||||
// This is the only way we can avoid
|
||||
// warning: non-standard suffix on floating constant [-Wpedantic]
|
||||
// when building with -Wall -pedantic. Neither __extension__
|
||||
// nor #pragma dianostic ignored work :(
|
||||
//
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
// Modified Bessel function of the second kind of order zero
|
||||
// minimax rational approximations on intervals, see
|
||||
// Russon and Blair, Chalk River Report AECL-3461, 1969,
|
||||
@@ -483,7 +493,7 @@ template <typename T>
|
||||
inline T bessel_k0(const T& x)
|
||||
{
|
||||
typedef mpl::int_<
|
||||
std::numeric_limits<T>::digits == 0 ?
|
||||
((std::numeric_limits<T>::digits == 0) || (std::numeric_limits<T>::radix != 2)) ?
|
||||
0 :
|
||||
std::numeric_limits<T>::digits <= 24 ?
|
||||
24 :
|
||||
|
||||
@@ -18,6 +18,16 @@
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#if defined(__GNUC__) && defined(BOOST_MATH_USE_FLOAT128)
|
||||
//
|
||||
// This is the only way we can avoid
|
||||
// warning: non-standard suffix on floating constant [-Wpedantic]
|
||||
// when building with -Wall -pedantic. Neither __extension__
|
||||
// nor #pragma dianostic ignored work :(
|
||||
//
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
// Modified Bessel function of the second kind of order zero
|
||||
// minimax rational approximations on intervals, see
|
||||
// Russon and Blair, Chalk River Report AECL-3461, 1969,
|
||||
@@ -525,7 +535,7 @@ namespace boost { namespace math { namespace detail{
|
||||
inline T bessel_k1(const T& x)
|
||||
{
|
||||
typedef mpl::int_<
|
||||
std::numeric_limits<T>::digits == 0 ?
|
||||
((std::numeric_limits<T>::digits == 0) || (std::numeric_limits<T>::radix != 2)) ?
|
||||
0 :
|
||||
std::numeric_limits<T>::digits <= 24 ?
|
||||
24 :
|
||||
|
||||
@@ -19,6 +19,16 @@
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#if defined(__GNUC__) && defined(BOOST_MATH_USE_FLOAT128)
|
||||
//
|
||||
// This is the only way we can avoid
|
||||
// warning: non-standard suffix on floating constant [-Wpedantic]
|
||||
// when building with -Wall -pedantic. Neither __extension__
|
||||
// nor #pragma dianostic ignored work :(
|
||||
//
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
// Bessel function of the second kind of order zero
|
||||
// x <= 8, minimax rational approximations on root-bracketing intervals
|
||||
// x > 8, Hankel asymptotic expansion in Hart, Computer Approximations, 1968
|
||||
|
||||
@@ -19,6 +19,16 @@
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#if defined(__GNUC__) && defined(BOOST_MATH_USE_FLOAT128)
|
||||
//
|
||||
// This is the only way we can avoid
|
||||
// warning: non-standard suffix on floating constant [-Wpedantic]
|
||||
// when building with -Wall -pedantic. Neither __extension__
|
||||
// nor #pragma dianostic ignored work :(
|
||||
//
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
// Bessel function of the second kind of order one
|
||||
// x <= 8, minimax rational approximations on root-bracketing intervals
|
||||
// x > 8, Hankel asymptotic expansion in Hart, Computer Approximations, 1968
|
||||
|
||||
@@ -24,7 +24,7 @@ With these techniques, the code could be simplified.
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/detail/endian.hpp>
|
||||
#include <boost/predef/other/endian.h>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/type_traits/is_floating_point.hpp>
|
||||
|
||||
@@ -51,9 +51,9 @@ With these techniques, the code could be simplified.
|
||||
&& (_GLIBCXX_USE_C99_FP_MACROS_DYNAMIC != 0))
|
||||
# ifdef _STLP_VENDOR_CSTD
|
||||
# if _STLPORT_VERSION >= 0x520
|
||||
# define BOOST_FPCLASSIFY_PREFIX ::__std_alias::
|
||||
# define BOOST_FPCLASSIFY_PREFIX ::__std_alias::
|
||||
# else
|
||||
# define BOOST_FPCLASSIFY_PREFIX ::_STLP_VENDOR_CSTD::
|
||||
# define BOOST_FPCLASSIFY_PREFIX ::_STLP_VENDOR_CSTD::
|
||||
# endif
|
||||
# else
|
||||
# define BOOST_FPCLASSIFY_PREFIX ::std::
|
||||
@@ -84,7 +84,7 @@ namespace detail {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
/*
|
||||
The following classes are used to tag the different methods that are used
|
||||
for floating point classification
|
||||
*/
|
||||
@@ -216,9 +216,9 @@ template<> struct fp_traits_non_native<double, double_precision>
|
||||
|
||||
private:
|
||||
|
||||
#if defined(BOOST_BIG_ENDIAN)
|
||||
#if BOOST_ENDIAN_BIG_BYTE
|
||||
BOOST_STATIC_CONSTANT(int, offset_ = 0);
|
||||
#elif defined(BOOST_LITTLE_ENDIAN)
|
||||
#elif BOOST_ENDIAN_LITTLE_BYTE
|
||||
BOOST_STATIC_CONSTANT(int, offset_ = 4);
|
||||
#else
|
||||
BOOST_STATIC_ASSERT(false);
|
||||
@@ -276,9 +276,9 @@ template<> struct fp_traits_non_native<long double, double_precision>
|
||||
|
||||
private:
|
||||
|
||||
#if defined(BOOST_BIG_ENDIAN)
|
||||
#if BOOST_ENDIAN_BIG_BYTE
|
||||
BOOST_STATIC_CONSTANT(int, offset_ = 0);
|
||||
#elif defined(BOOST_LITTLE_ENDIAN)
|
||||
#elif BOOST_ENDIAN_LITTLE_BYTE
|
||||
BOOST_STATIC_CONSTANT(int, offset_ = 4);
|
||||
#else
|
||||
BOOST_STATIC_ASSERT(false);
|
||||
@@ -390,9 +390,9 @@ struct fp_traits_non_native<long double, extended_double_precision>
|
||||
|
||||
private:
|
||||
|
||||
#if defined(BOOST_BIG_ENDIAN)
|
||||
#if BOOST_ENDIAN_BIG_BYTE
|
||||
BOOST_STATIC_CONSTANT(int, offset_ = 0);
|
||||
#elif defined(BOOST_LITTLE_ENDIAN)
|
||||
#elif BOOST_ENDIAN_LITTLE_BYTE
|
||||
BOOST_STATIC_CONSTANT(int, offset_ = 12);
|
||||
#else
|
||||
BOOST_STATIC_ASSERT(false);
|
||||
@@ -471,9 +471,9 @@ struct fp_traits_non_native<long double, extended_double_precision>
|
||||
|
||||
private:
|
||||
|
||||
#if defined(BOOST_BIG_ENDIAN)
|
||||
#if BOOST_ENDIAN_BIG_BYTE
|
||||
BOOST_STATIC_CONSTANT(int, offset_ = 0);
|
||||
#elif defined(BOOST_LITTLE_ENDIAN)
|
||||
#elif BOOST_ENDIAN_LITTLE_BYTE
|
||||
BOOST_STATIC_CONSTANT(int, offset_ = 12);
|
||||
#else
|
||||
BOOST_STATIC_ASSERT(false);
|
||||
@@ -556,7 +556,8 @@ struct select_native<long double>
|
||||
&& !defined(__FAST_MATH__)\
|
||||
&& !defined(BOOST_MATH_DISABLE_STD_FPCLASSIFY)\
|
||||
&& !defined(BOOST_INTEL)\
|
||||
&& !defined(sun)
|
||||
&& !defined(sun)\
|
||||
&& !defined(__VXWORKS__)
|
||||
# define BOOST_MATH_USE_STD_FPCLASSIFY
|
||||
#endif
|
||||
|
||||
|
||||
@@ -49,6 +49,16 @@
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && defined(BOOST_MATH_USE_FLOAT128)
|
||||
//
|
||||
// This is the only way we can avoid
|
||||
// warning: non-standard suffix on floating constant [-Wpedantic]
|
||||
// when building with -Wall -pedantic. Neither __extension__
|
||||
// nor #pragma dianostic ignored work :(
|
||||
//
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
namespace boost{ namespace math{ namespace detail{
|
||||
|
||||
// This version will never be called (at runtime), it's a stub used
|
||||
|
||||
@@ -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
|
||||
@@ -12,6 +12,16 @@
|
||||
|
||||
#include <boost/math/tools/big_constant.hpp>
|
||||
|
||||
#if defined(__GNUC__) && defined(BOOST_MATH_USE_FLOAT128)
|
||||
//
|
||||
// This is the only way we can avoid
|
||||
// warning: non-standard suffix on floating constant [-Wpedantic]
|
||||
// when building with -Wall -pedantic. Neither __extension__
|
||||
// nor #pragma dianostic ignored work :(
|
||||
//
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
namespace boost{ namespace math{ namespace detail{
|
||||
|
||||
//
|
||||
|
||||
@@ -19,6 +19,13 @@
|
||||
#include <boost/mpl/int.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
|
||||
#ifdef BOOST_MATH_HAVE_CONSTEXPR_TABLES
|
||||
#include <array>
|
||||
#else
|
||||
#include <boost/array.hpp>
|
||||
#endif
|
||||
|
||||
|
||||
namespace boost { namespace math {
|
||||
|
||||
namespace detail {
|
||||
@@ -83,9 +90,13 @@ struct max_bernoulli_b2n : public detail::max_bernoulli_index<detail::bernoulli_
|
||||
namespace detail{
|
||||
|
||||
template <class T>
|
||||
inline T unchecked_bernoulli_imp(std::size_t n, const mpl::int_<0>& )
|
||||
inline BOOST_MATH_CONSTEXPR_TABLE_FUNCTION T unchecked_bernoulli_imp(std::size_t n, const mpl::int_<0>& )
|
||||
{
|
||||
#ifdef BOOST_MATH_HAVE_CONSTEXPR_TABLES
|
||||
constexpr std::array<boost::int64_t, 1 + max_bernoulli_b2n<T>::value> numerators =
|
||||
#else
|
||||
static const boost::array<boost::int64_t, 1 + max_bernoulli_b2n<T>::value> numerators =
|
||||
#endif
|
||||
{{
|
||||
boost::int64_t( +1LL),
|
||||
boost::int64_t( +1LL),
|
||||
@@ -107,7 +118,11 @@ inline T unchecked_bernoulli_imp(std::size_t n, const mpl::int_<0>& )
|
||||
boost::int64_t(+2577687858367LL)
|
||||
}};
|
||||
|
||||
#ifdef BOOST_MATH_HAVE_CONSTEXPR_TABLES
|
||||
constexpr std::array<boost::int64_t, 1 + max_bernoulli_b2n<T>::value> denominators =
|
||||
#else
|
||||
static const boost::array<boost::int64_t, 1 + max_bernoulli_b2n<T>::value> denominators =
|
||||
#endif
|
||||
{{
|
||||
boost::int64_t( 1LL),
|
||||
boost::int64_t( 6LL),
|
||||
@@ -132,9 +147,13 @@ inline T unchecked_bernoulli_imp(std::size_t n, const mpl::int_<0>& )
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T unchecked_bernoulli_imp(std::size_t n, const mpl::int_<1>& )
|
||||
inline BOOST_MATH_CONSTEXPR_TABLE_FUNCTION T unchecked_bernoulli_imp(std::size_t n, const mpl::int_<1>& )
|
||||
{
|
||||
#ifdef BOOST_MATH_HAVE_CONSTEXPR_TABLES
|
||||
constexpr std::array<float, 1 + max_bernoulli_b2n<T>::value> bernoulli_data =
|
||||
#else
|
||||
static const boost::array<float, 1 + max_bernoulli_b2n<T>::value> bernoulli_data =
|
||||
#endif
|
||||
{{
|
||||
+1.00000000000000000000000000000000000000000F,
|
||||
+0.166666666666666666666666666666666666666667F,
|
||||
@@ -176,9 +195,13 @@ inline T unchecked_bernoulli_imp(std::size_t n, const mpl::int_<1>& )
|
||||
|
||||
|
||||
template <class T>
|
||||
inline T unchecked_bernoulli_imp(std::size_t n, const mpl::int_<2>& )
|
||||
inline BOOST_MATH_CONSTEXPR_TABLE_FUNCTION T unchecked_bernoulli_imp(std::size_t n, const mpl::int_<2>& )
|
||||
{
|
||||
#ifdef BOOST_MATH_HAVE_CONSTEXPR_TABLES
|
||||
constexpr std::array<double, 1 + max_bernoulli_b2n<T>::value> bernoulli_data =
|
||||
#else
|
||||
static const boost::array<double, 1 + max_bernoulli_b2n<T>::value> bernoulli_data =
|
||||
#endif
|
||||
{{
|
||||
+1.00000000000000000000000000000000000000000,
|
||||
+0.166666666666666666666666666666666666666667,
|
||||
@@ -316,9 +339,13 @@ inline T unchecked_bernoulli_imp(std::size_t n, const mpl::int_<2>& )
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T unchecked_bernoulli_imp(std::size_t n, const mpl::int_<3>& )
|
||||
inline BOOST_MATH_CONSTEXPR_TABLE_FUNCTION T unchecked_bernoulli_imp(std::size_t n, const mpl::int_<3>& )
|
||||
{
|
||||
#ifdef BOOST_MATH_HAVE_CONSTEXPR_TABLES
|
||||
constexpr std::array<long double, 1 + max_bernoulli_b2n<T>::value> bernoulli_data =
|
||||
#else
|
||||
static const boost::array<long double, 1 + max_bernoulli_b2n<T>::value> bernoulli_data =
|
||||
#endif
|
||||
{{
|
||||
+1.00000000000000000000000000000000000000000L,
|
||||
+0.166666666666666666666666666666666666666667L,
|
||||
@@ -688,7 +715,7 @@ inline T unchecked_bernoulli_imp(std::size_t n, const mpl::int_<4>& )
|
||||
} // namespace detail
|
||||
|
||||
template<class T>
|
||||
inline T unchecked_bernoulli_b2n(const std::size_t n)
|
||||
inline BOOST_MATH_CONSTEXPR_TABLE_FUNCTION T unchecked_bernoulli_b2n(const std::size_t n)
|
||||
{
|
||||
typedef mpl::int_<detail::bernoulli_imp_variant<T>::value> tag_type;
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/array.hpp>
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(push) // Temporary until lexical cast fixed.
|
||||
#pragma warning(disable: 4127 4701)
|
||||
@@ -21,9 +20,25 @@
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
#include <boost/config/no_tr1/cmath.hpp>
|
||||
#include <cmath>
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
|
||||
#ifdef BOOST_MATH_HAVE_CONSTEXPR_TABLES
|
||||
#include <array>
|
||||
#else
|
||||
#include <boost/array.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && defined(BOOST_MATH_USE_FLOAT128)
|
||||
//
|
||||
// This is the only way we can avoid
|
||||
// warning: non-standard suffix on floating constant [-Wpedantic]
|
||||
// when building with -Wall -pedantic. Neither __extension__
|
||||
// nor #pragma dianostic ignored work :(
|
||||
//
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
namespace boost { namespace math
|
||||
{
|
||||
// Forward declarations:
|
||||
@@ -32,9 +47,13 @@ struct max_factorial;
|
||||
|
||||
// Definitions:
|
||||
template <>
|
||||
inline float unchecked_factorial<float>(unsigned i BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(float))
|
||||
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,
|
||||
@@ -83,9 +102,13 @@ struct max_factorial<float>
|
||||
|
||||
|
||||
template <>
|
||||
inline long double unchecked_factorial<long double>(unsigned i BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(long double))
|
||||
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,
|
||||
@@ -271,9 +294,13 @@ struct max_factorial<long double>
|
||||
#ifdef BOOST_MATH_USE_FLOAT128
|
||||
|
||||
template <>
|
||||
inline BOOST_MATH_FLOAT128_TYPE unchecked_factorial<BOOST_MATH_FLOAT128_TYPE>(unsigned i)
|
||||
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,
|
||||
@@ -459,7 +486,7 @@ struct max_factorial<BOOST_MATH_FLOAT128_TYPE>
|
||||
#endif
|
||||
|
||||
template <>
|
||||
inline double unchecked_factorial<double>(unsigned i BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(double))
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -21,6 +21,16 @@
|
||||
#include <boost/mpl/comparison.hpp>
|
||||
#include <boost/math/tools/big_constant.hpp>
|
||||
|
||||
#if defined(__GNUC__) && defined(BOOST_MATH_USE_FLOAT128)
|
||||
//
|
||||
// This is the only way we can avoid
|
||||
// warning: non-standard suffix on floating constant [-Wpedantic]
|
||||
// when building with -Wall -pedantic. Neither __extension__
|
||||
// nor #pragma dianostic ignored work :(
|
||||
//
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
namespace boost{
|
||||
namespace math{
|
||||
namespace detail{
|
||||
|
||||
@@ -82,8 +82,12 @@ T ellint_d_imp(T phi, T k, const Policy& pol)
|
||||
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;
|
||||
@@ -99,6 +103,7 @@ T ellint_d_imp(T phi, T k, const Policy& pol)
|
||||
{
|
||||
// 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);
|
||||
|
||||
@@ -133,6 +133,7 @@ T ellint_rd_imp(T x, T y, T z, const Policy& pol)
|
||||
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;
|
||||
@@ -151,6 +152,9 @@ T ellint_rd_imp(T x, T y, T z, const Policy& pol)
|
||||
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;
|
||||
}
|
||||
@@ -168,6 +172,7 @@ T ellint_rd_imp(T x, T y, T z, const Policy& pol)
|
||||
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;
|
||||
|
||||
@@ -17,6 +17,16 @@
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
#include <boost/math/tools/big_constant.hpp>
|
||||
|
||||
#if defined(__GNUC__) && defined(BOOST_MATH_USE_FLOAT128)
|
||||
//
|
||||
// This is the only way we can avoid
|
||||
// warning: non-standard suffix on floating constant [-Wpedantic]
|
||||
// when building with -Wall -pedantic. Neither __extension__
|
||||
// nor #pragma dianostic ignored work :(
|
||||
//
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
namespace boost{ namespace math{
|
||||
|
||||
namespace detail
|
||||
@@ -182,6 +192,9 @@ T erf_imp(T z, bool invert, const Policy& pol, const mpl::int_<53>& t)
|
||||
|
||||
BOOST_MATH_INSTRUMENT_CODE("53-bit precision erf_imp called");
|
||||
|
||||
if ((boost::math::isnan)(z))
|
||||
return policies::raise_denorm_error("boost::math::erf<%1%>(%1%)", "Expected a finite argument but got %1%", z, pol);
|
||||
|
||||
if(z < 0)
|
||||
{
|
||||
if(!invert)
|
||||
@@ -305,7 +318,14 @@ T erf_imp(T z, bool invert, const Policy& pol, const mpl::int_<53>& t)
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 0.00410369723978904575884),
|
||||
};
|
||||
result = Y + tools::evaluate_polynomial(P, T(z - 1.5)) / tools::evaluate_polynomial(Q, T(z - 1.5));
|
||||
result *= exp(-z * z) / z;
|
||||
T hi, lo;
|
||||
int expon;
|
||||
hi = floor(ldexp(frexp(z, &expon), 26));
|
||||
hi = ldexp(hi, expon - 26);
|
||||
lo = z - hi;
|
||||
T sq = z * z;
|
||||
T err_sqr = ((hi * hi - sq) + 2 * hi * lo) + lo * lo;
|
||||
result *= exp(-sq) * exp(-err_sqr) / z;
|
||||
}
|
||||
else if(z < 4.5f)
|
||||
{
|
||||
@@ -331,7 +351,14 @@ T erf_imp(T z, bool invert, const Policy& pol, const mpl::int_<53>& t)
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 0.000479411269521714493907),
|
||||
};
|
||||
result = Y + tools::evaluate_polynomial(P, T(z - 3.5)) / tools::evaluate_polynomial(Q, T(z - 3.5));
|
||||
result *= exp(-z * z) / z;
|
||||
T hi, lo;
|
||||
int expon;
|
||||
hi = floor(ldexp(frexp(z, &expon), 26));
|
||||
hi = ldexp(hi, expon - 26);
|
||||
lo = z - hi;
|
||||
T sq = z * z;
|
||||
T err_sqr = ((hi * hi - sq) + 2 * hi * lo) + lo * lo;
|
||||
result *= exp(-sq) * exp(-err_sqr) / z;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -359,7 +386,14 @@ T erf_imp(T z, bool invert, const Policy& pol, const mpl::int_<53>& t)
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 5.48409182238641741584),
|
||||
};
|
||||
result = Y + tools::evaluate_polynomial(P, T(1 / z)) / tools::evaluate_polynomial(Q, T(1 / z));
|
||||
result *= exp(-z * z) / z;
|
||||
T hi, lo;
|
||||
int expon;
|
||||
hi = floor(ldexp(frexp(z, &expon), 26));
|
||||
hi = ldexp(hi, expon - 26);
|
||||
lo = z - hi;
|
||||
T sq = z * z;
|
||||
T err_sqr = ((hi * hi - sq) + 2 * hi * lo) + lo * lo;
|
||||
result *= exp(-sq) * exp(-err_sqr) / z;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -477,7 +511,14 @@ T erf_imp(T z, bool invert, const Policy& pol, const mpl::int_<64>& t)
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.00279220237309449026796),
|
||||
};
|
||||
result = Y + tools::evaluate_polynomial(P, T(z - 0.5f)) / tools::evaluate_polynomial(Q, T(z - 0.5f));
|
||||
result *= exp(-z * z) / z;
|
||||
T hi, lo;
|
||||
int expon;
|
||||
hi = floor(ldexp(frexp(z, &expon), 32));
|
||||
hi = ldexp(hi, expon - 32);
|
||||
lo = z - hi;
|
||||
T sq = z * z;
|
||||
T err_sqr = ((hi * hi - sq) + 2 * hi * lo) + lo * lo;
|
||||
result *= exp(-sq) * exp(-err_sqr) / z;
|
||||
}
|
||||
else if(z < 2.5)
|
||||
{
|
||||
@@ -505,7 +546,14 @@ T erf_imp(T z, bool invert, const Policy& pol, const mpl::int_<64>& t)
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.000897871370778031611439),
|
||||
};
|
||||
result = Y + tools::evaluate_polynomial(P, T(z - 1.5f)) / tools::evaluate_polynomial(Q, T(z - 1.5f));
|
||||
result *= exp(-z * z) / z;
|
||||
T hi, lo;
|
||||
int expon;
|
||||
hi = floor(ldexp(frexp(z, &expon), 32));
|
||||
hi = ldexp(hi, expon - 32);
|
||||
lo = z - hi;
|
||||
T sq = z * z;
|
||||
T err_sqr = ((hi * hi - sq) + 2 * hi * lo) + lo * lo;
|
||||
result *= exp(-sq) * exp(-err_sqr) / z;
|
||||
}
|
||||
else if(z < 4.5)
|
||||
{
|
||||
@@ -533,7 +581,14 @@ T erf_imp(T z, bool invert, const Policy& pol, const mpl::int_<64>& t)
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.804149464190309799804e-4),
|
||||
};
|
||||
result = Y + tools::evaluate_polynomial(P, T(z - 3.5f)) / tools::evaluate_polynomial(Q, T(z - 3.5f));
|
||||
result *= exp(-z * z) / z;
|
||||
T hi, lo;
|
||||
int expon;
|
||||
hi = floor(ldexp(frexp(z, &expon), 32));
|
||||
hi = ldexp(hi, expon - 32);
|
||||
lo = z - hi;
|
||||
T sq = z * z;
|
||||
T err_sqr = ((hi * hi - sq) + 2 * hi * lo) + lo * lo;
|
||||
result *= exp(-sq) * exp(-err_sqr) / z;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -565,7 +620,14 @@ T erf_imp(T z, bool invert, const Policy& pol, const mpl::int_<64>& t)
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 30.8365511891224291717),
|
||||
};
|
||||
result = Y + tools::evaluate_polynomial(P, T(1 / z)) / tools::evaluate_polynomial(Q, T(1 / z));
|
||||
result *= exp(-z * z) / z;
|
||||
T hi, lo;
|
||||
int expon;
|
||||
hi = floor(ldexp(frexp(z, &expon), 32));
|
||||
hi = ldexp(hi, expon - 32);
|
||||
lo = z - hi;
|
||||
T sq = z * z;
|
||||
T err_sqr = ((hi * hi - sq) + 2 * hi * lo) + lo * lo;
|
||||
result *= exp(-sq) * exp(-err_sqr) / z;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -693,7 +755,14 @@ T erf_imp(T z, bool invert, const Policy& pol, const mpl::int_<113>& t)
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.270666232259029102353426738909226413e-10),
|
||||
};
|
||||
result = Y + tools::evaluate_polynomial(P, T(z - 0.5f)) / tools::evaluate_polynomial(Q, T(z - 0.5f));
|
||||
result *= exp(-z * z) / z;
|
||||
T hi, lo;
|
||||
int expon;
|
||||
hi = floor(ldexp(frexp(z, &expon), 56));
|
||||
hi = ldexp(hi, expon - 56);
|
||||
lo = z - hi;
|
||||
T sq = z * z;
|
||||
T err_sqr = ((hi * hi - sq) + 2 * hi * lo) + lo * lo;
|
||||
result *= exp(-sq) * exp(-err_sqr) / z;
|
||||
}
|
||||
else if(z < 1.5)
|
||||
{
|
||||
@@ -727,7 +796,14 @@ T erf_imp(T z, bool invert, const Policy& pol, const mpl::int_<113>& t)
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.123749319840299552925421880481085392e-4),
|
||||
};
|
||||
result = Y + tools::evaluate_polynomial(P, T(z - 1.0f)) / tools::evaluate_polynomial(Q, T(z - 1.0f));
|
||||
result *= exp(-z * z) / z;
|
||||
T hi, lo;
|
||||
int expon;
|
||||
hi = floor(ldexp(frexp(z, &expon), 56));
|
||||
hi = ldexp(hi, expon - 56);
|
||||
lo = z - hi;
|
||||
T sq = z * z;
|
||||
T err_sqr = ((hi * hi - sq) + 2 * hi * lo) + lo * lo;
|
||||
result *= exp(-sq) * exp(-err_sqr) / z;
|
||||
}
|
||||
else if(z < 2.25)
|
||||
{
|
||||
@@ -762,7 +838,14 @@ T erf_imp(T z, bool invert, const Policy& pol, const mpl::int_<113>& t)
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.18647774409821470950544212696270639e-12),
|
||||
};
|
||||
result = Y + tools::evaluate_polynomial(P, T(z - 1.5f)) / tools::evaluate_polynomial(Q, T(z - 1.5f));
|
||||
result *= exp(-z * z) / z;
|
||||
T hi, lo;
|
||||
int expon;
|
||||
hi = floor(ldexp(frexp(z, &expon), 56));
|
||||
hi = ldexp(hi, expon - 56);
|
||||
lo = z - hi;
|
||||
T sq = z * z;
|
||||
T err_sqr = ((hi * hi - sq) + 2 * hi * lo) + lo * lo;
|
||||
result *= exp(-sq) * exp(-err_sqr) / z;
|
||||
}
|
||||
else if (z < 3)
|
||||
{
|
||||
@@ -796,7 +879,14 @@ T erf_imp(T z, bool invert, const Policy& pol, const mpl::int_<113>& t)
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.192093541425429248675532015101904262e-5),
|
||||
};
|
||||
result = Y + tools::evaluate_polynomial(P, T(z - 2.25f)) / tools::evaluate_polynomial(Q, T(z - 2.25f));
|
||||
result *= exp(-z * z) / z;
|
||||
T hi, lo;
|
||||
int expon;
|
||||
hi = floor(ldexp(frexp(z, &expon), 56));
|
||||
hi = ldexp(hi, expon - 56);
|
||||
lo = z - hi;
|
||||
T sq = z * z;
|
||||
T err_sqr = ((hi * hi - sq) + 2 * hi * lo) + lo * lo;
|
||||
result *= exp(-sq) * exp(-err_sqr) / z;
|
||||
}
|
||||
else if(z < 3.5)
|
||||
{
|
||||
@@ -828,7 +918,14 @@ T erf_imp(T z, bool invert, const Policy& pol, const mpl::int_<113>& t)
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.407763415954267700941230249989140046e-5),
|
||||
};
|
||||
result = Y + tools::evaluate_polynomial(P, T(z - 3.0f)) / tools::evaluate_polynomial(Q, T(z - 3.0f));
|
||||
result *= exp(-z * z) / z;
|
||||
T hi, lo;
|
||||
int expon;
|
||||
hi = floor(ldexp(frexp(z, &expon), 56));
|
||||
hi = ldexp(hi, expon - 56);
|
||||
lo = z - hi;
|
||||
T sq = z * z;
|
||||
T err_sqr = ((hi * hi - sq) + 2 * hi * lo) + lo * lo;
|
||||
result *= exp(-sq) * exp(-err_sqr) / z;
|
||||
}
|
||||
else if(z < 5.5)
|
||||
{
|
||||
@@ -864,7 +961,14 @@ T erf_imp(T z, bool invert, const Policy& pol, const mpl::int_<113>& t)
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.11005507545746069573608988651927452e-7),
|
||||
};
|
||||
result = Y + tools::evaluate_polynomial(P, T(z - 4.5f)) / tools::evaluate_polynomial(Q, T(z - 4.5f));
|
||||
result *= exp(-z * z) / z;
|
||||
T hi, lo;
|
||||
int expon;
|
||||
hi = floor(ldexp(frexp(z, &expon), 56));
|
||||
hi = ldexp(hi, expon - 56);
|
||||
lo = z - hi;
|
||||
T sq = z * z;
|
||||
T err_sqr = ((hi * hi - sq) + 2 * hi * lo) + lo * lo;
|
||||
result *= exp(-sq) * exp(-err_sqr) / z;
|
||||
}
|
||||
else if(z < 7.5)
|
||||
{
|
||||
@@ -898,7 +1002,14 @@ T erf_imp(T z, bool invert, const Policy& pol, const mpl::int_<113>& t)
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.997637501418963696542159244436245077e-8),
|
||||
};
|
||||
result = Y + tools::evaluate_polynomial(P, T(z - 6.5f)) / tools::evaluate_polynomial(Q, T(z - 6.5f));
|
||||
result *= exp(-z * z) / z;
|
||||
T hi, lo;
|
||||
int expon;
|
||||
hi = floor(ldexp(frexp(z, &expon), 56));
|
||||
hi = ldexp(hi, expon - 56);
|
||||
lo = z - hi;
|
||||
T sq = z * z;
|
||||
T err_sqr = ((hi * hi - sq) + 2 * hi * lo) + lo * lo;
|
||||
result *= exp(-sq) * exp(-err_sqr) / z;
|
||||
}
|
||||
else if(z < 11.5)
|
||||
{
|
||||
@@ -932,7 +1043,14 @@ T erf_imp(T z, bool invert, const Policy& pol, const mpl::int_<113>& t)
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.356615210500531410114914617294694857e-6),
|
||||
};
|
||||
result = Y + tools::evaluate_polynomial(P, T(z / 2 - 4.75f)) / tools::evaluate_polynomial(Q, T(z / 2 - 4.75f));
|
||||
result *= exp(-z * z) / z;
|
||||
T hi, lo;
|
||||
int expon;
|
||||
hi = floor(ldexp(frexp(z, &expon), 56));
|
||||
hi = ldexp(hi, expon - 56);
|
||||
lo = z - hi;
|
||||
T sq = z * z;
|
||||
T err_sqr = ((hi * hi - sq) + 2 * hi * lo) + lo * lo;
|
||||
result *= exp(-sq) * exp(-err_sqr) / z;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -970,7 +1088,14 @@ T erf_imp(T z, bool invert, const Policy& pol, const mpl::int_<113>& t)
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 72.7415265778588087243442792401576737),
|
||||
};
|
||||
result = Y + tools::evaluate_polynomial(P, T(1 / z)) / tools::evaluate_polynomial(Q, T(1 / z));
|
||||
result *= exp(-z * z) / z;
|
||||
T hi, lo;
|
||||
int expon;
|
||||
hi = floor(ldexp(frexp(z, &expon), 56));
|
||||
hi = ldexp(hi, expon - 56);
|
||||
lo = z - hi;
|
||||
T sq = z * z;
|
||||
T err_sqr = ((hi * hi - sq) + 2 * hi * lo) + lo * lo;
|
||||
result *= exp(-sq) * exp(-err_sqr) / z;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -22,6 +22,16 @@
|
||||
#include <boost/math/special_functions/log1p.hpp>
|
||||
#include <boost/math/special_functions/pow.hpp>
|
||||
|
||||
#if defined(__GNUC__) && defined(BOOST_MATH_USE_FLOAT128)
|
||||
//
|
||||
// This is the only way we can avoid
|
||||
// warning: non-standard suffix on floating constant [-Wpedantic]
|
||||
// when building with -Wall -pedantic. Neither __extension__
|
||||
// nor #pragma dianostic ignored work :(
|
||||
//
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
namespace boost{ namespace math{
|
||||
|
||||
template <class T, class Policy>
|
||||
|
||||
@@ -28,6 +28,16 @@
|
||||
# include <boost/assert.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && defined(BOOST_MATH_USE_FLOAT128)
|
||||
//
|
||||
// This is the only way we can avoid
|
||||
// warning: non-standard suffix on floating constant [-Wpedantic]
|
||||
// when building with -Wall -pedantic. Neither __extension__
|
||||
// nor #pragma dianostic ignored work :(
|
||||
//
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
namespace boost{ namespace math{
|
||||
|
||||
namespace detail
|
||||
|
||||
@@ -550,6 +550,8 @@ T lgamma_imp(T z, const Policy& pol, const lanczos::undefined_lanczos&, int* sig
|
||||
// Special case handling of small factorials:
|
||||
if((!b_neg) && floor_of_z_is_equal_to_z && (z < boost::math::max_factorial<T>::value))
|
||||
{
|
||||
if (sign)
|
||||
*sign = 1;
|
||||
return log(boost::math::unchecked_factorial<T>(itrunc(z) - 1));
|
||||
}
|
||||
|
||||
@@ -567,22 +569,19 @@ T lgamma_imp(T z, const Policy& pol, const lanczos::undefined_lanczos&, int* sig
|
||||
// is relatively small and overflow is not expected to be likely.
|
||||
if(fabs(z - 1) < 0.25)
|
||||
{
|
||||
return log_gamma_near_1(T(zz - 1), pol);
|
||||
log_gamma_value = log_gamma_near_1(T(zz - 1), pol);
|
||||
}
|
||||
else if(fabs(z - 2) < 0.25)
|
||||
{
|
||||
return log_gamma_near_1(T(zz - 2), pol) + log(zz - 1);
|
||||
log_gamma_value = log_gamma_near_1(T(zz - 2), pol) + log(zz - 1);
|
||||
}
|
||||
else if (z > -tools::root_epsilon<T>())
|
||||
{
|
||||
// Reflection formula may fail if z is very close to zero, let the series
|
||||
// expansion for tgamma close to zero do the work:
|
||||
log_gamma_value = log(abs(gamma_imp(z, pol, lanczos::undefined_lanczos())));
|
||||
if (sign)
|
||||
{
|
||||
*sign = z < 0 ? -1 : 1;
|
||||
}
|
||||
return log_gamma_value;
|
||||
*sign = z < 0 ? -1 : 1;
|
||||
return log(abs(gamma_imp(z, pol, lanczos::undefined_lanczos())));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -769,6 +768,8 @@ T full_igamma_prefix(T a, T z, const Policy& pol)
|
||||
BOOST_MATH_STD_USING
|
||||
|
||||
T prefix;
|
||||
if (z > tools::max_value<T>())
|
||||
return 0;
|
||||
T alz = a * log(z);
|
||||
|
||||
if(z >= 1)
|
||||
@@ -818,6 +819,8 @@ template <class T, class Policy, class Lanczos>
|
||||
T regularised_gamma_prefix(T a, T z, const Policy& pol, const Lanczos& l)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
if (z >= tools::max_value<T>())
|
||||
return 0;
|
||||
T agh = a + static_cast<T>(Lanczos::g()) - T(0.5);
|
||||
T prefix;
|
||||
T d = ((z - a) - static_cast<T>(Lanczos::g()) + T(0.5)) / agh;
|
||||
@@ -1035,6 +1038,37 @@ T finite_half_gamma_q(T a, T x, T* p_derivative, const Policy& pol)
|
||||
}
|
||||
return e;
|
||||
}
|
||||
//
|
||||
// Asymptotic approximation for large argument, see: https://dlmf.nist.gov/8.11#E2
|
||||
//
|
||||
template <class T>
|
||||
struct incomplete_tgamma_large_x_series
|
||||
{
|
||||
typedef T result_type;
|
||||
incomplete_tgamma_large_x_series(const T& a, const T& x)
|
||||
: a_poch(a - 1), z(x), term(1) {}
|
||||
T operator()()
|
||||
{
|
||||
T result = term;
|
||||
term *= a_poch / z;
|
||||
a_poch -= 1;
|
||||
return result;
|
||||
}
|
||||
T a_poch, z, term;
|
||||
};
|
||||
|
||||
template <class T, class Policy>
|
||||
T incomplete_tgamma_large_x(const T& a, const T& x, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
incomplete_tgamma_large_x_series<T> s(a, x);
|
||||
boost::uintmax_t max_iter = boost::math::policies::get_max_series_iterations<Policy>();
|
||||
T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon<T, Policy>(), max_iter);
|
||||
boost::math::policies::check_series_iterations<T>("boost::math::tgamma<%1%>(%1%,%1%)", max_iter, pol);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Main incomplete gamma entry point, handles all four incomplete gamma's:
|
||||
//
|
||||
@@ -1151,6 +1185,12 @@ T gamma_incomplete_imp(T a, T x, bool normalised, bool invert,
|
||||
{
|
||||
eval_method = 6;
|
||||
}
|
||||
else if ((x > 1000) && ((a < x) || (fabs(a - 50) / x < 1)))
|
||||
{
|
||||
// calculate Q via asymptotic approximation:
|
||||
invert = !invert;
|
||||
eval_method = 7;
|
||||
}
|
||||
else if(x < 0.5)
|
||||
{
|
||||
//
|
||||
@@ -1365,7 +1405,22 @@ T gamma_incomplete_imp(T a, T x, bool normalised, bool invert,
|
||||
// use http://functions.wolfram.com/GammaBetaErf/GammaRegularized/06/01/05/01/01/
|
||||
result = !normalised ? pow(x, a) / (a) : pow(x, a) / boost::math::tgamma(a + 1, pol);
|
||||
result *= 1 - a * x / (a + 1);
|
||||
if (p_derivative)
|
||||
*p_derivative = regularised_gamma_prefix(a, x, pol, lanczos_type());
|
||||
break;
|
||||
}
|
||||
case 7:
|
||||
{
|
||||
// x is large,
|
||||
// Compute Q:
|
||||
result = normalised ? regularised_gamma_prefix(a, x, pol, lanczos_type()) : full_igamma_prefix(a, x, pol);
|
||||
if (p_derivative)
|
||||
*p_derivative = result;
|
||||
result /= x;
|
||||
if (result != 0)
|
||||
result *= incomplete_tgamma_large_x(a, x, pol);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(normalised && (result > 1))
|
||||
|
||||
2186
linx64/include/boost/math/special_functions/lambert_w.hpp
Normal file
2186
linx64/include/boost/math/special_functions/lambert_w.hpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -21,6 +21,16 @@
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#if defined(__GNUC__) && defined(BOOST_MATH_USE_FLOAT128)
|
||||
//
|
||||
// This is the only way we can avoid
|
||||
// warning: non-standard suffix on floating constant [-Wpedantic]
|
||||
// when building with -Wall -pedantic. Neither __extension__
|
||||
// nor #pragma dianostic ignored work :(
|
||||
//
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
namespace boost{ namespace math{ namespace lanczos{
|
||||
|
||||
//
|
||||
@@ -1284,7 +1294,7 @@ struct lanczos
|
||||
} // namespace boost
|
||||
|
||||
#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__) || defined(_M_AMD64) || defined(_M_X64)
|
||||
#if ((defined(_M_IX86_FP) && (_M_IX86_FP >= 2)) || defined(__SSE2__) || defined(_M_AMD64) || defined(_M_X64)) && !defined(_MANAGED)
|
||||
#include <boost/math/special_functions/detail/lanczos_sse2.hpp>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -11,8 +11,11 @@
|
||||
#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{
|
||||
@@ -68,6 +71,149 @@ T legendre_imp(unsigned l, T x, const Policy& pol, bool second = false)
|
||||
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>
|
||||
@@ -82,13 +228,49 @@ inline typename boost::enable_if_c<policies::is_policy<Policy>::value, typename
|
||||
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
|
||||
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)
|
||||
@@ -99,7 +281,7 @@ inline typename boost::enable_if_c<policies::is_policy<Policy>::value, typename
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typename tools::promote_args<T>::type
|
||||
inline typename tools::promote_args<T>::type
|
||||
legendre_q(unsigned l, T x)
|
||||
{
|
||||
return boost::math::legendre_q(l, x, policies::policy<>());
|
||||
@@ -107,7 +289,7 @@ inline typename tools::promote_args<T>::type
|
||||
|
||||
// Recurrence for associated polynomials:
|
||||
template <class T1, class T2, class T3>
|
||||
inline typename tools::promote_args<T1, T2, T3>::type
|
||||
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;
|
||||
@@ -189,6 +371,3 @@ inline typename tools::promote_args<T>::type
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_MATH_SPECIAL_LEGENDRE_HPP
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -28,6 +28,16 @@
|
||||
# include <boost/assert.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && defined(BOOST_MATH_USE_FLOAT128)
|
||||
//
|
||||
// This is the only way we can avoid
|
||||
// warning: non-standard suffix on floating constant [-Wpedantic]
|
||||
// when building with -Wall -pedantic. Neither __extension__
|
||||
// nor #pragma dianostic ignored work :(
|
||||
//
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
namespace boost{ namespace math{
|
||||
|
||||
namespace detail
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <vector>
|
||||
#include <boost/math/special_functions/detail/round_fwd.hpp>
|
||||
#include <boost/math/tools/promotion.hpp> // for argument promotion.
|
||||
#include <boost/math/policies/policy.hpp>
|
||||
@@ -181,10 +182,24 @@ namespace boost
|
||||
template <class T>
|
||||
typename tools::promote_args<T>::type
|
||||
legendre_p(int l, T x);
|
||||
template <class T>
|
||||
typename tools::promote_args<T>::type
|
||||
legendre_p_prime(int l, T x);
|
||||
|
||||
|
||||
template <class T, class Policy>
|
||||
inline std::vector<T> legendre_p_zeros(int l, const Policy& pol);
|
||||
|
||||
template <class T>
|
||||
inline std::vector<T> legendre_p_zeros(int l);
|
||||
|
||||
#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
|
||||
template <class T, class Policy>
|
||||
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);
|
||||
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);
|
||||
#endif
|
||||
template <class T>
|
||||
typename tools::promote_args<T>::type
|
||||
@@ -248,6 +263,30 @@ namespace boost
|
||||
typename tools::promote_args<T1, T2, T3>::type
|
||||
hermite_next(unsigned n, T1 x, T2 Hn, T3 Hnm1);
|
||||
|
||||
template<class T1, class T2, class T3>
|
||||
typename tools::promote_args<T1, T2, T3>::type chebyshev_next(T1 const & x, T2 const & Tn, T3 const & Tn_1);
|
||||
|
||||
template <class Real, class Policy>
|
||||
typename tools::promote_args<Real>::type
|
||||
chebyshev_t(unsigned n, Real const & x, const Policy&);
|
||||
template<class Real>
|
||||
typename tools::promote_args<Real>::type chebyshev_t(unsigned n, Real const & x);
|
||||
|
||||
template <class Real, class Policy>
|
||||
typename tools::promote_args<Real>::type
|
||||
chebyshev_u(unsigned n, Real const & x, const Policy&);
|
||||
template<class Real>
|
||||
typename tools::promote_args<Real>::type chebyshev_u(unsigned n, Real const & x);
|
||||
|
||||
template <class Real, class Policy>
|
||||
typename tools::promote_args<Real>::type
|
||||
chebyshev_t_prime(unsigned n, Real const & x, const Policy&);
|
||||
template<class Real>
|
||||
typename tools::promote_args<Real>::type chebyshev_t_prime(unsigned n, Real const & x);
|
||||
|
||||
template<class Real, class T2>
|
||||
Real chebyshev_clenshaw_recurrence(const Real* const c, size_t length, const T2& x);
|
||||
|
||||
template <class T1, class T2>
|
||||
std::complex<typename tools::promote_args<T1, T2>::type>
|
||||
spherical_harmonic(unsigned n, int m, T1 theta, T2 phi);
|
||||
@@ -1018,7 +1057,7 @@ namespace boost
|
||||
typename tools::promote_args<T, U>::type epsilon_difference(const T&, const U&);
|
||||
|
||||
template<class T>
|
||||
T unchecked_bernoulli_b2n(const std::size_t n);
|
||||
BOOST_MATH_CONSTEXPR_TABLE_FUNCTION T unchecked_bernoulli_b2n(const std::size_t n);
|
||||
template <class T, class Policy>
|
||||
T bernoulli_b2n(const int i, const Policy &pol);
|
||||
template <class T>
|
||||
@@ -1046,6 +1085,27 @@ namespace boost
|
||||
const unsigned number_of_bernoullis_b2n,
|
||||
OutputIterator out_it);
|
||||
|
||||
// Lambert W:
|
||||
template <class T, class Policy>
|
||||
typename boost::math::tools::promote_args<T>::type lambert_w0(T z, const Policy& pol);
|
||||
template <class T>
|
||||
typename boost::math::tools::promote_args<T>::type lambert_w0(T z);
|
||||
template <class T, class Policy>
|
||||
typename boost::math::tools::promote_args<T>::type lambert_wm1(T z, const Policy& pol);
|
||||
template <class T>
|
||||
typename boost::math::tools::promote_args<T>::type lambert_wm1(T z);
|
||||
template <class T, class Policy>
|
||||
typename boost::math::tools::promote_args<T>::type lambert_w0_prime(T z, const Policy& pol);
|
||||
template <class T>
|
||||
typename boost::math::tools::promote_args<T>::type lambert_w0_prime(T z);
|
||||
template <class T, class Policy>
|
||||
typename boost::math::tools::promote_args<T>::type lambert_wm1_prime(T z, const Policy& pol);
|
||||
template <class T>
|
||||
typename boost::math::tools::promote_args<T>::type lambert_wm1_prime(T z);
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace math
|
||||
} // namespace boost
|
||||
|
||||
@@ -1144,6 +1204,10 @@ namespace boost
|
||||
template <class T>\
|
||||
inline typename boost::math::tools::promote_args<T>::type \
|
||||
legendre_p(int l, T x){ return ::boost::math::legendre_p(l, x, Policy()); }\
|
||||
\
|
||||
template <class T>\
|
||||
inline typename boost::math::tools::promote_args<T>::type \
|
||||
legendre_p_prime(int l, T x){ return ::boost::math::legendre_p(l, x, Policy()); }\
|
||||
\
|
||||
template <class T>\
|
||||
inline typename boost::math::tools::promote_args<T>::type \
|
||||
@@ -1170,6 +1234,19 @@ namespace boost
|
||||
hermite(unsigned n, T x){ return ::boost::math::hermite(n, x, Policy()); }\
|
||||
\
|
||||
using boost::math::hermite_next;\
|
||||
\
|
||||
using boost::math::chebyshev_next;\
|
||||
\
|
||||
template<class Real>\
|
||||
Real chebyshev_t(unsigned n, Real const & x){ return ::boost::math::chebyshev_t(n, x, Policy()); }\
|
||||
\
|
||||
template<class Real>\
|
||||
Real chebyshev_u(unsigned n, Real const & x){ return ::boost::math::chebyshev_u(n, x, Policy()); }\
|
||||
\
|
||||
template<class Real>\
|
||||
Real chebyshev_t_prime(unsigned n, Real const & x){ return ::boost::math::chebyshev_t_prime(n, x, Policy()); }\
|
||||
\
|
||||
using ::boost::math::chebyshev_clenshaw_recurrence;\
|
||||
\
|
||||
template <class T1, class T2>\
|
||||
inline std::complex<typename boost::math::tools::promote_args<T1, T2>::type> \
|
||||
@@ -1587,11 +1664,15 @@ template <class OutputIterator, class T>\
|
||||
OutputIterator tangent_t2n(int start_index, unsigned number_of_bernoullis_b2n, OutputIterator out_it)\
|
||||
{ return boost::math::tangent_t2n<T>(start_index, number_of_bernoullis_b2n, out_it, Policy()); }\
|
||||
\
|
||||
template <class T> inline typename boost::math::tools::promote_args<T>::type lambert_w0(T z) { return boost::math::lambert_w0(z, Policy()); }\
|
||||
template <class T> inline typename boost::math::tools::promote_args<T>::type lambert_wm1(T z) { return boost::math::lambert_w0(z, Policy()); }\
|
||||
template <class T> inline typename boost::math::tools::promote_args<T>::type lambert_w0_prime(T z) { return boost::math::lambert_w0(z, Policy()); }\
|
||||
template <class T> inline typename boost::math::tools::promote_args<T>::type lambert_wm1_prime(T z) { return boost::math::lambert_w0(z, Policy()); }\
|
||||
\
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // BOOST_MATH_SPECIAL_MATH_FWD_HPP
|
||||
|
||||
|
||||
|
||||
@@ -27,8 +27,58 @@
|
||||
|
||||
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&)
|
||||
{
|
||||
@@ -93,19 +143,33 @@ struct min_shift_initializer
|
||||
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()
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
static const T val = ldexp(tools::min_value<T>(), tools::digits<T>() + 1);
|
||||
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 Policy& pol)
|
||||
T float_next_imp(const T& val, const mpl::true_&, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
int expon;
|
||||
@@ -145,6 +209,54 @@ T float_next_imp(const T& val, const Policy& pol)
|
||||
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
|
||||
|
||||
@@ -152,7 +264,7 @@ 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(static_cast<result_type>(val), pol);
|
||||
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
|
||||
@@ -187,7 +299,7 @@ inline typename tools::promote_args<T>::type float_next(const T& val)
|
||||
namespace detail{
|
||||
|
||||
template <class T, class Policy>
|
||||
T float_prior_imp(const T& val, const Policy& pol)
|
||||
T float_prior_imp(const T& val, const mpl::true_&, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
int expon;
|
||||
@@ -221,13 +333,62 @@ T float_prior_imp(const T& val, const Policy& pol)
|
||||
}
|
||||
|
||||
T remain = frexp(val, &expon);
|
||||
if(remain == 0.5)
|
||||
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
|
||||
|
||||
@@ -235,7 +396,7 @@ 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(static_cast<result_type>(val), pol);
|
||||
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
|
||||
@@ -283,7 +444,7 @@ inline typename tools::promote_args<T, U>::type nextafter(const T& val, const U&
|
||||
namespace detail{
|
||||
|
||||
template <class T, class Policy>
|
||||
T float_distance_imp(const T& a, const T& b, const Policy& pol)
|
||||
T float_distance_imp(const T& a, const T& b, const mpl::true_&, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
//
|
||||
@@ -331,19 +492,23 @@ T float_distance_imp(const T& a, const T& b, const Policy& pol)
|
||||
frexp(((boost::math::fpclassify)(a) == (int)FP_SUBNORMAL) ? tools::min_value<T>() : a, &expon);
|
||||
T upper = ldexp(T(1), expon);
|
||||
T result = T(0);
|
||||
expon = tools::digits<T>() - expon;
|
||||
//
|
||||
// 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)
|
||||
{
|
||||
result = float_distance(upper, b);
|
||||
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>()))
|
||||
{
|
||||
@@ -380,6 +545,113 @@ T float_distance_imp(const T& a, const T& b, const Policy& pol)
|
||||
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
|
||||
|
||||
@@ -387,7 +659,7 @@ 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(static_cast<result_type>(a), static_cast<result_type>(b), pol);
|
||||
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>
|
||||
@@ -399,7 +671,7 @@ typename tools::promote_args<T, U>::type float_distance(const T& a, const U& b)
|
||||
namespace detail{
|
||||
|
||||
template <class T, class Policy>
|
||||
T float_advance_imp(T val, int distance, const Policy& pol)
|
||||
T float_advance_imp(T val, int distance, const mpl::true_&, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
//
|
||||
@@ -478,6 +750,92 @@ T float_advance_imp(T val, int distance, const Policy& pol)
|
||||
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
|
||||
|
||||
@@ -485,7 +843,7 @@ 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(static_cast<result_type>(val), distance, pol);
|
||||
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>
|
||||
|
||||
@@ -32,6 +32,16 @@
|
||||
#pragma warning(disable:4127)
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && defined(BOOST_MATH_USE_FLOAT128)
|
||||
//
|
||||
// This is the only way we can avoid
|
||||
// warning: non-standard suffix on floating constant [-Wpedantic]
|
||||
// when building with -Wall -pedantic. Neither __extension__
|
||||
// nor #pragma dianostic ignored work :(
|
||||
//
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace math
|
||||
|
||||
@@ -8,15 +8,19 @@
|
||||
#ifndef BOOST_MATH_SF_PRIME_HPP
|
||||
#define BOOST_MATH_SF_PRIME_HPP
|
||||
|
||||
#include <boost/array.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
#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{
|
||||
|
||||
template <class Policy>
|
||||
boost::uint32_t prime(unsigned n, const Policy& pol)
|
||||
BOOST_MATH_CONSTEXPR_TABLE_FUNCTION boost::uint32_t prime(unsigned n, const Policy& pol)
|
||||
{
|
||||
//
|
||||
// This is basically three big tables which together
|
||||
@@ -26,10 +30,17 @@ namespace boost{ namespace math{
|
||||
// That gives us the first 10000 primes with the largest
|
||||
// being 104729:
|
||||
//
|
||||
#ifdef BOOST_MATH_HAVE_CONSTEXPR_TABLES
|
||||
constexpr unsigned b1 = 53;
|
||||
constexpr unsigned b2 = 6541;
|
||||
constexpr unsigned b3 = 10000;
|
||||
constexpr std::array<unsigned char, 54> a1 = {{
|
||||
#else
|
||||
static const unsigned b1 = 53;
|
||||
static const unsigned b2 = 6541;
|
||||
static const unsigned b3 = 10000;
|
||||
static const boost::array<unsigned char, 54> a1 = {{
|
||||
#endif
|
||||
2u, 3u, 5u, 7u, 11u, 13u, 17u, 19u, 23u, 29u, 31u,
|
||||
37u, 41u, 43u, 47u, 53u, 59u, 61u, 67u, 71u, 73u,
|
||||
79u, 83u, 89u, 97u, 101u, 103u, 107u, 109u, 113u,
|
||||
@@ -37,7 +48,11 @@ namespace boost{ namespace math{
|
||||
167u, 173u, 179u, 181u, 191u, 193u, 197u, 199u,
|
||||
211u, 223u, 227u, 229u, 233u, 239u, 241u, 251u
|
||||
}};
|
||||
#ifdef BOOST_MATH_HAVE_CONSTEXPR_TABLES
|
||||
constexpr std::array<boost::uint16_t, 6488> a2 = {{
|
||||
#else
|
||||
static const boost::array<boost::uint16_t, 6488> a2 = {{
|
||||
#endif
|
||||
257u, 263u, 269u, 271u, 277u, 281u, 283u, 293u,
|
||||
307u, 311u, 313u, 317u, 331u, 337u, 347u, 349u, 353u,
|
||||
359u, 367u, 373u, 379u, 383u, 389u, 397u, 401u, 409u,
|
||||
@@ -760,7 +775,11 @@ namespace boost{ namespace math{
|
||||
65323u, 65327u, 65353u, 65357u, 65371u, 65381u, 65393u, 65407u, 65413u,
|
||||
65419u, 65423u, 65437u, 65447u, 65449u, 65479u, 65497u, 65519u, 65521u
|
||||
}};
|
||||
#ifdef BOOST_MATH_HAVE_CONSTEXPR_TABLES
|
||||
constexpr std::array<boost::uint16_t, 3458> a3 = {{
|
||||
#else
|
||||
static const boost::array<boost::uint16_t, 3458> a3 = {{
|
||||
#endif
|
||||
2u, 4u, 8u, 16u, 22u, 28u, 44u,
|
||||
46u, 52u, 64u, 74u, 82u, 94u, 98u, 112u,
|
||||
116u, 122u, 142u, 152u, 164u, 166u, 172u, 178u,
|
||||
@@ -1208,7 +1227,7 @@ namespace boost{ namespace math{
|
||||
return static_cast<boost::uint32_t>(a3[n - b2 - 1]) + 0xFFFFu;
|
||||
}
|
||||
|
||||
inline boost::uint32_t prime(unsigned n)
|
||||
inline BOOST_MATH_CONSTEXPR_TABLE_FUNCTION boost::uint32_t prime(unsigned n)
|
||||
{
|
||||
return boost::math::prime(n, boost::math::policies::policy<>());
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ namespace boost{
|
||||
return (std::max)(fabs((a - b) / a), fabs((a - b) / b));
|
||||
}
|
||||
|
||||
#if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
|
||||
#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)
|
||||
{
|
||||
|
||||
@@ -35,7 +35,7 @@ inline typename tools::promote_args<T>::type round(const T& v, const Policy& pol
|
||||
// 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;
|
||||
return static_cast<result_type>(0);
|
||||
}
|
||||
else if (v > 0)
|
||||
{
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace detail {
|
||||
template<class T>
|
||||
inline int signbit_impl(T x, native_tag const&)
|
||||
{
|
||||
return (std::signbit)(x);
|
||||
return (std::signbit)(x) ? 1 : 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -43,34 +43,14 @@ namespace boost
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
|
||||
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)
|
||||
if (abs(x) >= 3.3 * tools::forth_root_epsilon<T>())
|
||||
{
|
||||
return(sin(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);
|
||||
// |x| < (eps*120)^(1/4)
|
||||
return 1 - x * x / 6;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,16 @@
|
||||
#include <boost/math/tools/big_constant.hpp>
|
||||
#include <boost/math/special_functions/polygamma.hpp>
|
||||
|
||||
#if defined(__GNUC__) && defined(BOOST_MATH_USE_FLOAT128)
|
||||
//
|
||||
// This is the only way we can avoid
|
||||
// warning: non-standard suffix on floating constant [-Wpedantic]
|
||||
// when building with -Wall -pedantic. Neither __extension__
|
||||
// nor #pragma dianostic ignored work :(
|
||||
//
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
namespace boost{
|
||||
namespace math{
|
||||
namespace detail{
|
||||
|
||||
@@ -50,7 +50,7 @@ inline typename tools::promote_args<T>::type trunc(const T& v)
|
||||
// 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
|
||||
// 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.
|
||||
//
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
namespace boost{ namespace math{ namespace detail{
|
||||
|
||||
template <class T, class Policy>
|
||||
T ulp_imp(const T& val, const Policy& pol)
|
||||
T ulp_imp(const T& val, const mpl::true_&, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
int expon;
|
||||
@@ -48,6 +48,40 @@ T ulp_imp(const T& val, const Policy& pol)
|
||||
diff = detail::get_smallest_value<T>();
|
||||
return diff;
|
||||
}
|
||||
// non-binary version:
|
||||
template <class T, class Policy>
|
||||
T ulp_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
|
||||
int expon;
|
||||
static const char* function = "ulp<%1%>(%1%)";
|
||||
|
||||
int fpclass = (boost::math::fpclassify)(val);
|
||||
|
||||
if(fpclass == (int)FP_NAN)
|
||||
{
|
||||
return policies::raise_domain_error<T>(
|
||||
function,
|
||||
"Argument must be finite, but got %1%", val, pol);
|
||||
}
|
||||
else if((fpclass == (int)FP_INFINITE) || (fabs(val) >= tools::max_value<T>()))
|
||||
{
|
||||
return (val < 0 ? -1 : 1) * policies::raise_overflow_error<T>(function, 0, pol);
|
||||
}
|
||||
else if(fpclass == FP_ZERO)
|
||||
return detail::get_smallest_value<T>();
|
||||
//
|
||||
// This code is almost the same as that for float_next, except for negative integers,
|
||||
// where we preserve the relation ulp(x) == ulp(-x) as does Java:
|
||||
//
|
||||
expon = 1 + ilogb(fabs(val));
|
||||
T diff = scalbn(T(1), expon - std::numeric_limits<T>::digits);
|
||||
if(diff == 0)
|
||||
diff = detail::get_smallest_value<T>();
|
||||
return diff;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -55,7 +89,7 @@ template <class T, class Policy>
|
||||
inline typename tools::promote_args<T>::type ulp(const T& val, const Policy& pol)
|
||||
{
|
||||
typedef typename tools::promote_args<T>::type result_type;
|
||||
return detail::ulp_imp(static_cast<result_type>(val), pol);
|
||||
return detail::ulp_imp(static_cast<result_type>(val), mpl::bool_<!std::numeric_limits<result_type>::is_specialized || (std::numeric_limits<result_type>::radix == 2)>(), pol);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
|
||||
@@ -19,6 +19,16 @@
|
||||
#include <boost/math/special_functions/factorials.hpp>
|
||||
#include <boost/math/special_functions/sin_pi.hpp>
|
||||
|
||||
#if defined(__GNUC__) && defined(BOOST_MATH_USE_FLOAT128)
|
||||
//
|
||||
// This is the only way we can avoid
|
||||
// warning: non-standard suffix on floating constant [-Wpedantic]
|
||||
// when building with -Wall -pedantic. Neither __extension__
|
||||
// nor #pragma dianostic ignored work :(
|
||||
//
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
namespace boost{ namespace math{ namespace detail{
|
||||
|
||||
#if 0
|
||||
|
||||
Reference in New Issue
Block a user