update boost on linux

This commit is contained in:
Bassem Girgis
2019-08-10 16:06:25 -05:00
parent 76ad52be58
commit 861b918727
5363 changed files with 483306 additions and 116507 deletions

View 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

View File

@@ -0,0 +1,237 @@
// (C) Copyright Nick Thompson 2017.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_MATH_SPECIAL_CHEBYSHEV_TRANSFORM_HPP
#define BOOST_MATH_SPECIAL_CHEBYSHEV_TRANSFORM_HPP
#include <cmath>
#include <type_traits>
#include <fftw3.h>
#include <boost/math/constants/constants.hpp>
#include <boost/math/special_functions/chebyshev.hpp>
#ifdef BOOST_HAS_FLOAT128
#include <quadmath.h>
#endif
namespace boost { namespace math {
namespace detail{
template <class T>
struct fftw_cos_transform;
template<>
struct fftw_cos_transform<double>
{
fftw_cos_transform(int n, double* data1, double* data2)
{
plan = fftw_plan_r2r_1d(n, data1, data2, FFTW_REDFT10, FFTW_ESTIMATE);
}
~fftw_cos_transform()
{
fftw_destroy_plan(plan);
}
void execute(double* data1, double* data2)
{
fftw_execute_r2r(plan, data1, data2);
}
static double cos(double x) { return std::cos(x); }
static double fabs(double x) { return std::fabs(x); }
private:
fftw_plan plan;
};
template<>
struct fftw_cos_transform<float>
{
fftw_cos_transform(int n, float* data1, float* data2)
{
plan = fftwf_plan_r2r_1d(n, data1, data2, FFTW_REDFT10, FFTW_ESTIMATE);
}
~fftw_cos_transform()
{
fftwf_destroy_plan(plan);
}
void execute(float* data1, float* data2)
{
fftwf_execute_r2r(plan, data1, data2);
}
static float cos(float x) { return std::cos(x); }
static float fabs(float x) { return std::fabs(x); }
private:
fftwf_plan plan;
};
template<>
struct fftw_cos_transform<long double>
{
fftw_cos_transform(int n, long double* data1, long double* data2)
{
plan = fftwl_plan_r2r_1d(n, data1, data2, FFTW_REDFT10, FFTW_ESTIMATE);
}
~fftw_cos_transform()
{
fftwl_destroy_plan(plan);
}
void execute(long double* data1, long double* data2)
{
fftwl_execute_r2r(plan, data1, data2);
}
static long double cos(long double x) { return std::cos(x); }
static long double fabs(long double x) { return std::fabs(x); }
private:
fftwl_plan plan;
};
#ifdef BOOST_HAS_FLOAT128
template<>
struct fftw_cos_transform<__float128>
{
fftw_cos_transform(int n, __float128* data1, __float128* data2)
{
plan = fftwq_plan_r2r_1d(n, data1, data2, FFTW_REDFT10, FFTW_ESTIMATE);
}
~fftw_cos_transform()
{
fftwq_destroy_plan(plan);
}
void execute(__float128* data1, __float128* data2)
{
fftwq_execute_r2r(plan, data1, data2);
}
static __float128 cos(__float128 x) { return cosq(x); }
static __float128 fabs(__float128 x) { return fabsq(x); }
private:
fftwq_plan plan;
};
#endif
}
template<class Real>
class chebyshev_transform
{
public:
template<class F>
chebyshev_transform(const F& f, Real a, Real b,
Real tol = 500 * std::numeric_limits<Real>::epsilon(),
size_t max_refinements = 15) : m_a(a), m_b(b)
{
if (a >= b)
{
throw std::domain_error("a < b is required.\n");
}
using boost::math::constants::half;
using boost::math::constants::pi;
using std::cos;
using std::abs;
Real bma = (b-a)*half<Real>();
Real bpa = (b+a)*half<Real>();
size_t n = 256;
std::vector<Real> vf;
size_t refinements = 0;
while(refinements < max_refinements)
{
vf.resize(n);
m_coeffs.resize(n);
detail::fftw_cos_transform<Real> plan(static_cast<int>(n), vf.data(), m_coeffs.data());
Real inv_n = 1/static_cast<Real>(n);
for(size_t j = 0; j < n/2; ++j)
{
// Use symmetry cos((j+1/2)pi/n) = - cos((n-1-j+1/2)pi/n)
Real y = detail::fftw_cos_transform<Real>::cos(pi<Real>()*(j+half<Real>())*inv_n);
vf[j] = f(y*bma + bpa)*inv_n;
vf[n-1-j]= f(bpa-y*bma)*inv_n;
}
plan.execute(vf.data(), m_coeffs.data());
Real max_coeff = 0;
for (auto const & coeff : m_coeffs)
{
if (detail::fftw_cos_transform<Real>::fabs(coeff) > max_coeff)
{
max_coeff = detail::fftw_cos_transform<Real>::fabs(coeff);
}
}
size_t j = m_coeffs.size() - 1;
while (abs(m_coeffs[j])/max_coeff < tol)
{
--j;
}
// If ten coefficients are eliminated, the we say we've done all
// we need to do:
if (n - j > 10)
{
m_coeffs.resize(j+1);
return;
}
n *= 2;
++refinements;
}
}
Real operator()(Real x) const
{
using boost::math::constants::half;
if (x > m_b || x < m_a)
{
throw std::domain_error("x not in [a, b]\n");
}
Real z = (2*x - m_a - m_b)/(m_b - m_a);
return chebyshev_clenshaw_recurrence(m_coeffs.data(), m_coeffs.size(), z);
}
// Integral over entire domain [a, b]
Real integrate() const
{
Real Q = m_coeffs[0]/2;
for(size_t j = 2; j < m_coeffs.size(); j += 2)
{
Q += -m_coeffs[j]/((j+1)*(j-1));
}
return (m_b - m_a)*Q;
}
const std::vector<Real>& coefficients() const
{
return m_coeffs;
}
Real prime(Real x) const
{
Real z = (2*x - m_a - m_b)/(m_b - m_a);
Real dzdx = 2/(m_b - m_a);
if (m_coeffs.size() < 2)
{
return 0;
}
Real b2 = 0;
Real d2 = 0;
Real b1 = m_coeffs[m_coeffs.size() -1];
Real d1 = 0;
for(size_t j = m_coeffs.size() - 2; j >= 1; --j)
{
Real tmp1 = 2*z*b1 - b2 + m_coeffs[j];
Real tmp2 = 2*z*d1 - d2 + 2*b1;
b2 = b1;
b1 = tmp1;
d2 = d1;
d1 = tmp2;
}
return dzdx*(z*d1 - d2 + b1);
}
private:
std::vector<Real> m_coeffs;
Real m_a;
Real m_b;
};
}}
#endif

View File

@@ -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
{

View File

@@ -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]; }

View File

@@ -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 :

View File

@@ -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 :

View File

@@ -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

View File

@@ -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

View File

@@ -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 :

View File

@@ -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 :

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,134 @@
// Copyright Paul A. Bristow 2017.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
// I:/modular-boost/libs/math/include/boost/math/special_functions/lambert_w_lookup_table.ipp
// A collection of 128-bit precision integral z argument Lambert W values computed using 37 decimal digits precision.
// C++ floating-point precision is 128-bit long double.
// Output as 53 decimal digits, suffixed L.
// C++ floating-point type is provided by lambert_w.hpp typedef.
// For example: typedef lookup_t double; (or float or long double)
// Written by I:\modular-boost\libs\math\test\lambert_w_lookup_table_generator.cpp Thu Jan 25 16:52:07 2018
// Sizes of arrays of z values for Lambert W[0], W[1] ... W[64]" and W[-1], W[-2] ... W[-64].
namespace boost {
namespace math {
namespace lambert_w_detail {
namespace lambert_w_lookup
{
BOOST_STATIC_CONSTEXPR std::size_t noof_sqrts = 12;
BOOST_STATIC_CONSTEXPR std::size_t noof_halves = 12;
BOOST_STATIC_CONSTEXPR std::size_t noof_w0es = 65;
BOOST_STATIC_CONSTEXPR std::size_t noof_w0zs = 65;
BOOST_STATIC_CONSTEXPR std::size_t noof_wm1es = 64;
BOOST_STATIC_CONSTEXPR std::size_t noof_wm1zs = 64;
BOOST_STATIC_CONSTEXPR lookup_t halves[noof_halves] =
{ // Common to Lambert W0 and W-1 (and exactly representable).
0.5L, 0.25L, 0.125L, 0.0625L, 0.03125L, 0.015625L, 0.0078125L, 0.00390625L, 0.001953125L, 0.0009765625L, 0.00048828125L, 0.000244140625L
}; // halves, 0.5, 0.25, ... 0.000244140625, common to W0 and W-1.
BOOST_STATIC_CONSTEXPR lookup_t sqrtw0s[noof_sqrts] =
{ // For Lambert W0 only.
0.6065306597126334242631173765403218567L, 0.77880078307140486866846070009071995L, 0.882496902584595403104717592968701829L, 0.9394130628134757862473572557999761753L, 0.9692332344763440819139583751755278177L, 0.9844964370054084060204319075254540376L, 0.9922179382602435121227899136829802692L, 0.996101369470117490071323985506950379L, 0.9980487811074754727142805899944244847L, 0.9990239141819756622368328253791383317L, 0.9995118379398893653889967919448497792L, 0.9997558891748972165136242351259789505L
}; // sqrtw0s
BOOST_STATIC_CONSTEXPR lookup_t sqrtwm1s[noof_sqrts] =
{ // For Lambert W-1 only.
1.648721270700128146848650787814163572L, 1.284025416687741484073420568062436458L, 1.133148453066826316829007227811793873L, 1.064494458917859429563390594642889673L, 1.031743407499102670938747815281507144L, 1.015747708586685747458535072082351749L, 1.007843097206447977693453559760123579L, 1.003913889338347573443609603903460282L, 1.001955033591002812046518898047477216L, 1.000977039492416535242845292611606506L, 1.000488400478694473126173623807163354L, 1.000244170429747854937005233924135774L
}; // sqrtwm1s
BOOST_STATIC_CONSTEXPR lookup_t w0es[noof_w0zs] =
{ // Fukushima e powers array e[0] = 2.718, 1., e[2] = e^-1 = 0.135, e[3] = e^-2 = 0.133 ... e[64] = 4.3596100000630809736231248158884615452e-28.
2.7182818284590452353602874713526624978e+00L,
1.0000000000000000000000000000000000000e+00L, 3.6787944117144232159552377016146086745e-01L, 1.3533528323661269189399949497248440341e-01L, 4.9787068367863942979342415650061776632e-02L,
1.8315638888734180293718021273241242212e-02L, 6.7379469990854670966360484231484242488e-03L, 2.4787521766663584230451674308166678915e-03L, 9.1188196555451620800313608440928262647e-04L,
3.3546262790251183882138912578086101931e-04L, 1.2340980408667954949763669073003382607e-04L, 4.5399929762484851535591515560550610238e-05L, 1.6701700790245659312635517360580879078e-05L,
6.1442123533282097586823081788055323112e-06L, 2.2603294069810543257852772905386894694e-06L, 8.3152871910356788406398514256526229461e-07L, 3.0590232050182578837147949770228963937e-07L,
1.1253517471925911451377517906012719164e-07L, 4.1399377187851666596510277189552806229e-08L, 1.5229979744712628436136629233517431862e-08L, 5.6027964375372675400129828162064630798e-09L,
2.0611536224385578279659403801558209764e-09L, 7.5825604279119067279417432412681264430e-10L, 2.7894680928689248077189130306442932077e-10L, 1.0261879631701890303927527840612497760e-10L,
3.7751345442790977516449695475234067792e-11L, 1.3887943864964020594661763746086856910e-11L, 5.1090890280633247198744001934792157666e-12L, 1.8795288165390832947582704184221926212e-12L,
6.9144001069402030094125846587414092712e-13L, 2.5436656473769229103033856148576816666e-13L, 9.3576229688401746049158322233787067450e-14L, 3.4424771084699764583923893328515572846e-14L,
1.2664165549094175723120904155965096382e-14L, 4.6588861451033973641842455436101684114e-15L, 1.7139084315420129663027203425760492412e-15L, 6.3051167601469893856390211922465427614e-16L,
2.3195228302435693883122636097380800411e-16L, 8.5330476257440657942780498229412441658e-17L, 3.1391327920480296287089646522319196491e-17L, 1.1548224173015785986262442063323868655e-17L,
4.2483542552915889953292347828586580179e-18L, 1.5628821893349887680908829951058341550e-18L, 5.7495222642935598066643808805734234249e-19L, 2.1151310375910804866314010070226514702e-19L,
7.7811322411337965157133167292798981918e-20L, 2.8625185805493936444701216291839372068e-20L, 1.0530617357553812378763324449428108806e-20L, 3.8739976286871871129314774972691278293e-21L,
1.4251640827409351062853210280340602263e-21L, 5.2428856633634639371718053028323436716e-22L, 1.9287498479639177830173428165270125748e-22L, 7.0954741622847041389832693878080734877e-23L,
2.6102790696677048047026953153318648093e-23L, 9.6026800545086760302307696700074909076e-24L, 3.5326285722008070297353928101772088374e-24L, 1.2995814250075030736007134060714855303e-24L,
4.7808928838854690812771770423179628939e-25L, 1.7587922024243116489558751288034363178e-25L, 6.4702349256454603261540395529264893765e-26L, 2.3802664086944006058943245888024963309e-26L,
8.7565107626965203384887328007391660366e-27L, 3.2213402859925160890012477758489437534e-27L, 1.1850648642339810062850307390972809891e-27L, 4.3596100000630809736231248158884596428e-28L,
}; // w0es
BOOST_STATIC_CONSTEXPR lookup_t w0zs[noof_w0zs] =
{ // z values for W[0], W[1], W[2] ... W[64] (Fukushima array Fk).
0.0000000000000000000000000000000000000e+00L,
2.7182818284590452353602874713526624978e+00L, 1.4778112197861300454460854921150015626e+01L, 6.0256610769563003222785588963745153691e+01L, 2.1839260013257695631244104481144351361e+02L,
7.4206579551288301710557790020276139812e+02L, 2.4205727609564107356503230832603296776e+03L, 7.6764321089992101948460416680168500271e+03L, 2.3847663896333826197948736795623109390e+04L,
7.2927755348178456069389970204894839685e+04L, 2.2026465794806716516957900645284244366e+05L, 6.5861555886717600300859134371483559776e+05L, 1.9530574970280470496960624587818413980e+06L,
5.7513740961159665432393360873381476632e+06L, 1.6836459978306874888489314790750032292e+07L, 4.9035260587081659589527825691375819733e+07L, 1.4217776832812596218820837985250320561e+08L,
4.1063419681078006965118239806655900596e+08L, 1.1818794444719492004981570586630806042e+09L, 3.3911637183005579560532906419857313738e+09L, 9.7033039081958055593821366108308111737e+09L,
2.7695130424147508641409976558651358487e+10L, 7.8868082614895014356985518811525255163e+10L, 2.2413047926372475980079655175092843139e+11L, 6.3573893111624333505933989166748517618e+11L,
1.8001224834346468131040337866531539479e+12L, 5.0889698451498078710141863447784789126e+12L, 1.4365302496248562650461177217211790925e+13L, 4.0495197800161304862957327843914007993e+13L,
1.1400869461717722015726999684446230289e+14L, 3.2059423744573386440971405952224204950e+14L, 9.0051433962267018216365614546207459567e+14L, 2.5268147258457822451512967243234631750e+15L,
7.0832381329352301326018261305316090522e+15L, 1.9837699245933465967698692976753294646e+16L, 5.5510470830970075484537561902113104381e+16L, 1.5520433569614702817608320254284931407e+17L,
4.3360826779369661842459877227403719730e+17L, 1.2105254067703227363724895246493485480e+18L, 3.3771426165357561311906703760513324357e+18L, 9.4154106734807994163159964299613921804e+18L,
2.6233583234732252918129199544138403574e+19L, 7.3049547543861043990576614751671879498e+19L, 2.0329709713386190214340167519800405595e+20L, 5.6547040503180956413560918381429636734e+20L,
1.5720421975868292906615658755032744790e+21L, 4.3682149334771264822761478593874428627e+21L, 1.2132170565093316762294432610117848880e+22L, 3.3680332378068632345542636794533635462e+22L,
9.3459982052259884835729892206738573922e+22L, 2.5923527642935362320437266614667426924e+23L, 7.1876803203773878618909930893087860822e+23L, 1.9921241603726199616378561653688236827e+24L,
5.5192924995054165325072406547517121131e+24L, 1.5286067837683347062387143159276002521e+25L, 4.2321318958281094260005100745711666956e+25L, 1.1713293177672778461879598480402173158e+26L,
3.2408603996214813669049988277609543829e+26L, 8.9641258264226027960478448084812796397e+26L, 2.4787141382364034104243901241243054434e+27L, 6.8520443388941057019777430988685937812e+27L,
1.8936217407781711443114787060753312270e+28L, 5.2317811346197017832254642778313331353e+28L, 1.4450833904658542238325922893692265683e+29L, 3.9904954117194348050619127737142206367e+29L
}; // w0zs
BOOST_STATIC_CONSTEXPR lookup_t wm1es[noof_wm1es] =
{ // Fukushima e array e[0] = e^1 = 2.718, e[1] = e^2 = 7.39 ... e[64] = 4.60718e+28.
2.7182818284590452353602874713526624978e+00L,
7.3890560989306502272304274605750078132e+00L, 2.0085536923187667740928529654581717897e+01L, 5.4598150033144239078110261202860878403e+01L, 1.4841315910257660342111558004055227962e+02L,
4.0342879349273512260838718054338827961e+02L, 1.0966331584284585992637202382881214324e+03L, 2.9809579870417282747435920994528886738e+03L, 8.1030839275753840077099966894327599650e+03L,
2.2026465794806716516957900645284244366e+04L, 5.9874141715197818455326485792257781614e+04L, 1.6275479141900392080800520489848678317e+05L, 4.4241339200892050332610277594908828178e+05L,
1.2026042841647767777492367707678594494e+06L, 3.2690173724721106393018550460917213155e+06L, 8.8861105205078726367630237407814503508e+06L, 2.4154952753575298214775435180385823880e+07L,
6.5659969137330511138786503259060033569e+07L, 1.7848230096318726084491003378872270388e+08L, 4.8516519540979027796910683054154055868e+08L, 1.3188157344832146972099988837453027851e+09L,
3.5849128461315915616811599459784206892e+09L, 9.7448034462489026000346326848229752776e+09L, 2.6489122129843472294139162152811882341e+10L, 7.2004899337385872524161351466126157915e+10L,
1.9572960942883876426977639787609534279e+11L, 5.3204824060179861668374730434117744166e+11L, 1.4462570642914751736770474229969288569e+12L, 3.9313342971440420743886205808435276858e+12L,
1.0686474581524462146990468650741401650e+13L, 2.9048849665247425231085682111679825667e+13L, 7.8962960182680695160978022635108224220e+13L, 2.1464357978591606462429776153126088037e+14L,
5.8346174252745488140290273461039101900e+14L, 1.5860134523134307281296446257746601252e+15L, 4.3112315471151952271134222928569253908e+15L, 1.1719142372802611308772939791190194522e+16L,
3.1855931757113756220328671701298646000e+16L, 8.6593400423993746953606932719264934250e+16L, 2.3538526683701998540789991074903480451e+17L, 6.3984349353005494922266340351557081888e+17L,
1.7392749415205010473946813036112352261e+18L, 4.7278394682293465614744575627442803708e+18L, 1.2851600114359308275809299632143099258e+19L, 3.4934271057485095348034797233406099533e+19L,
9.4961194206024488745133649117118323102e+19L, 2.5813128861900673962328580021527338043e+20L, 7.0167359120976317386547159988611740546e+20L, 1.9073465724950996905250998409538484474e+21L,
5.1847055285870724640874533229334853848e+21L, 1.4093490824269387964492143312370168789e+22L, 3.8310080007165768493035695487861993899e+22L, 1.0413759433029087797183472933493796440e+23L,
2.8307533032746939004420635480140745409e+23L, 7.6947852651420171381827455901293939921e+23L, 2.0916594960129961539070711572146737782e+24L, 5.6857199993359322226403488206332533034e+24L,
1.5455389355901039303530766911174620068e+25L, 4.2012104037905142549565934307191617684e+25L, 1.1420073898156842836629571831447656302e+26L, 3.1042979357019199087073421411071003721e+26L,
8.4383566687414544890733294803731179601e+26L, 2.2937831594696098790993528402686136005e+27L, 6.2351490808116168829092387089284697448e+27L
}; // wm1es
BOOST_STATIC_CONSTEXPR lookup_t wm1zs[noof_wm1zs] =
{ // Fukushima G array of z values for integral K, (Fukushima Gk) g[0] (k = -1) = 1 ... g[64] = -1.0264389699511303e-26.
-3.6787944117144232159552377016146086745e-01L,
-2.7067056647322538378799898994496880682e-01L, -1.4936120510359182893802724695018532990e-01L, -7.3262555554936721174872085092964968848e-02L, -3.3689734995427335483180242115742121244e-02L,
-1.4872513059998150538271004584900007349e-02L, -6.3831737588816134560219525908649783853e-03L, -2.6837010232200947105711130062468881545e-03L, -1.1106882367801159454787302165703044346e-03L,
-4.5399929762484851535591515560550610238e-04L, -1.8371870869270225243899069096638966986e-04L, -7.3730548239938517104187698145666387735e-05L, -2.9384282290753706235208604777002963102e-05L,
-1.1641402067449950376895791995913672125e-05L, -4.5885348075273868255721924655343445906e-06L, -1.8005627955081458322204028649620350662e-06L, -7.0378941219347833214067471222239770590e-07L,
-2.7413963540482731185045932620331377352e-07L, -1.0645313231320808326024667350792279852e-07L, -4.1223072448771156559318807603116419528e-08L, -1.5923376898615004128677660806663065530e-08L,
-6.1368298043116345769816086674174450569e-09L, -2.3602323152914347699033314033408744848e-09L, -9.0603229062698346039479269140561762700e-10L, -3.4719859662410051486654409365217142276e-10L,
-1.3283631472964644271673440503045960993e-10L, -5.0747278046555248958473301297399200773e-11L, -1.9360320299432568426355237044475945959e-11L, -7.3766303773930764398798182830872768331e-12L,
-2.8072868906520523814747496670136120235e-12L, -1.0671679036256927021016406931839827582e-12L, -4.0525329757101362313986893299088308423e-13L, -1.5374324278841211301808010293913555758e-13L,
-5.8272886672428440854292491647585674200e-14L, -2.2067908660514462849736574172862899665e-14L, -8.3502821888768497979241489950570881481e-15L, -3.1572276215253043438828784344882603413e-15L,
-1.1928704609782512589094065678481294667e-15L, -4.5038074274761565346423524046963087756e-16L, -1.6993417021166355981316939131434632072e-16L, -6.4078169762734539491726202799339200356e-17L,
-2.4147993510032951187990399698408378385e-17L, -9.0950634616416460925150243301974013218e-18L, -3.4236981860988704669138593608831552044e-18L, -1.2881333612472271400115547331327717431e-18L,
-4.8440839844747536942311292467369300505e-19L, -1.8207788854829779430777944237164900798e-19L, -6.8407875971564885101695409345634890862e-20L, -2.5690139750480973292141845983878483991e-20L,
-9.6437492398195889150867140826350628738e-21L, -3.6186918227651991108814673877821174787e-21L, -1.3573451162272064984454015639725697008e-21L, -5.0894204288895982960223079251039701810e-22L,
-1.9076194289884357960571121174956927722e-22L, -7.1476978375412669048039237333931704166e-23L, -2.6773000149758626855152191436980592206e-23L, -1.0025115553818576399048488234179587012e-23L,
-3.7527362568743669891693429406973638384e-24L, -1.4043571811296963574776515073934728352e-24L, -5.2539064576179122030932396804434996219e-25L, -1.9650175744554348142907611432678556896e-25L,
-7.3474021582506822389671905824031421322e-26L, -2.7465543000397410133825686340097295749e-26L, -1.0264389699511282259046957018510946438e-26L
}; // wm1zs
} // namespace lambert_w_lookup
} // namespace detail
} // namespace math
} // namespace boost

View File

@@ -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{
//

View File

@@ -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;

View File

@@ -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));
}

View File

@@ -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{

View File

@@ -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);

View File

@@ -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;

View File

@@ -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

View File

@@ -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>

View File

@@ -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

View File

@@ -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))

File diff suppressed because it is too large Load Diff

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,235 @@
// Copyright Nick Thompson 2017.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_MATH_SPECIAL_LEGENDRE_STIELTJES_HPP
#define BOOST_MATH_SPECIAL_LEGENDRE_STIELTJES_HPP
/*
* Constructs the Legendre-Stieltjes polynomial of degree m.
* The Legendre-Stieltjes polynomials are used to create extensions for Gaussian quadratures,
* commonly called "Gauss-Konrod" quadratures.
*
* References:
* Patterson, TNL. "The optimum addition of points to quadrature formulae." Mathematics of Computation 22.104 (1968): 847-856.
*/
#include <iostream>
#include <vector>
#include <boost/math/tools/roots.hpp>
#include <boost/math/special_functions/legendre.hpp>
namespace boost{
namespace math{
template<class Real>
class legendre_stieltjes
{
public:
legendre_stieltjes(size_t m)
{
if (m == 0)
{
throw std::domain_error("The Legendre-Stieltjes polynomial is defined for order m > 0.\n");
}
m_m = static_cast<int>(m);
std::ptrdiff_t n = m - 1;
std::ptrdiff_t q;
std::ptrdiff_t r;
bool odd = n & 1;
if (odd)
{
q = 1;
r = (n-1)/2 + 2;
}
else
{
q = 0;
r = n/2 + 1;
}
m_a.resize(r + 1);
// We'll keep the ones-based indexing at the cost of storing a superfluous element
// so that we can follow Patterson's notation exactly.
m_a[r] = static_cast<Real>(1);
// Make sure using the zero index is a bug:
m_a[0] = std::numeric_limits<Real>::quiet_NaN();
for (std::ptrdiff_t k = 1; k < r; ++k)
{
Real ratio = 1;
m_a[r - k] = 0;
for (std::ptrdiff_t i = r + 1 - k; i <= r; ++i)
{
// See Patterson, equation 12
std::ptrdiff_t num = (n - q + 2*(i + k - 1))*(n + q + 2*(k - i + 1))*(n-1-q+2*(i-k))*(2*(k+i-1) -1 -q -n);
std::ptrdiff_t den = (n - q + 2*(i - k))*(2*(k + i - 1) - q - n)*(n + 1 + q + 2*(k - i))*(n - 1 - q + 2*(i + k));
ratio *= static_cast<Real>(num)/static_cast<Real>(den);
m_a[r - k] -= ratio*m_a[i];
}
}
}
Real norm_sq() const
{
Real t = 0;
bool odd = m_m & 1;
for (size_t i = 1; i < m_a.size(); ++i)
{
if(odd)
{
t += 2*m_a[i]*m_a[i]/static_cast<Real>(4*i-1);
}
else
{
t += 2*m_a[i]*m_a[i]/static_cast<Real>(4*i-3);
}
}
return t;
}
Real operator()(Real x) const
{
// Trivial implementation:
// Em += m_a[i]*legendre_p(2*i - 1, x); m odd
// Em += m_a[i]*legendre_p(2*i - 2, x); m even
size_t r = m_a.size() - 1;
Real p0 = 1;
Real p1 = x;
Real Em;
bool odd = m_m & 1;
if (odd)
{
Em = m_a[1]*p1;
}
else
{
Em = m_a[1]*p0;
}
unsigned n = 1;
for (size_t i = 2; i <= r; ++i)
{
std::swap(p0, p1);
p1 = boost::math::legendre_next(n, x, p0, p1);
++n;
if (!odd)
{
Em += m_a[i]*p1;
}
std::swap(p0, p1);
p1 = boost::math::legendre_next(n, x, p0, p1);
++n;
if(odd)
{
Em += m_a[i]*p1;
}
}
return Em;
}
Real prime(Real x) const
{
Real Em_prime = 0;
for (size_t i = 1; i < m_a.size(); ++i)
{
if(m_m & 1)
{
Em_prime += m_a[i]*detail::legendre_p_prime_imp(static_cast<unsigned>(2*i - 1), x, policies::policy<>());
}
else
{
Em_prime += m_a[i]*detail::legendre_p_prime_imp(static_cast<unsigned>(2*i - 2), x, policies::policy<>());
}
}
return Em_prime;
}
std::vector<Real> zeros() const
{
using boost::math::constants::half;
std::vector<Real> stieltjes_zeros;
std::vector<Real> legendre_zeros = legendre_p_zeros<Real>(m_m - 1);
int k;
if (m_m & 1)
{
stieltjes_zeros.resize(legendre_zeros.size() + 1, std::numeric_limits<Real>::quiet_NaN());
stieltjes_zeros[0] = 0;
k = 1;
}
else
{
stieltjes_zeros.resize(legendre_zeros.size(), std::numeric_limits<Real>::quiet_NaN());
k = 0;
}
while (k < (int)stieltjes_zeros.size())
{
Real lower_bound;
Real upper_bound;
if (m_m & 1)
{
lower_bound = legendre_zeros[k - 1];
if (k == (int)legendre_zeros.size())
{
upper_bound = 1;
}
else
{
upper_bound = legendre_zeros[k];
}
}
else
{
lower_bound = legendre_zeros[k];
if (k == (int)legendre_zeros.size() - 1)
{
upper_bound = 1;
}
else
{
upper_bound = legendre_zeros[k+1];
}
}
// The root bracketing is not very tight; to keep weird stuff from happening
// in the Newton's method, let's tighten up the tolerance using a few bisections.
boost::math::tools::eps_tolerance<Real> tol(6);
auto g = [&](Real t) { return this->operator()(t); };
auto p = boost::math::tools::bisect(g, lower_bound, upper_bound, tol);
Real x_nk_guess = p.first + (p.second - p.first)*half<Real>();
boost::uintmax_t number_of_iterations = 500;
auto f = [&] (Real x) { Real Pn = this->operator()(x);
Real Pn_prime = this->prime(x);
return std::pair<Real, Real>(Pn, Pn_prime); };
const Real x_nk = boost::math::tools::newton_raphson_iterate(f, x_nk_guess,
p.first, p.second,
2*std::numeric_limits<Real>::digits10,
number_of_iterations);
BOOST_ASSERT(p.first < x_nk);
BOOST_ASSERT(x_nk < p.second);
stieltjes_zeros[k] = x_nk;
++k;
}
return stieltjes_zeros;
}
private:
// Coefficients of Legendre expansion
std::vector<Real> m_a;
int m_m;
};
}}
#endif

View File

@@ -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

View File

@@ -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

View File

@@ -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>

View File

@@ -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

View File

@@ -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<>());
}

View File

@@ -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)
{

View File

@@ -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)
{

View File

@@ -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

View File

@@ -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;
}
}

View File

@@ -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{

View File

@@ -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.
//

View File

@@ -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>

View File

@@ -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