diff --git a/libcxx/docs/ReleaseNotes.rst b/libcxx/docs/ReleaseNotes.rst --- a/libcxx/docs/ReleaseNotes.rst +++ b/libcxx/docs/ReleaseNotes.rst @@ -37,6 +37,7 @@ Implemented Papers ------------------ +- P0226R1 - Mathematical Special Functions for C++17 Improvements and New Features ----------------------------- diff --git a/libcxx/docs/Status/Cxx17Papers.csv b/libcxx/docs/Status/Cxx17Papers.csv --- a/libcxx/docs/Status/Cxx17Papers.csv +++ b/libcxx/docs/Status/Cxx17Papers.csv @@ -26,7 +26,7 @@ "`P0013R1 `__","LWG","Logical type traits rev 2","Kona","|Complete|","3.8" "","","","","","" "`P0024R2 `__","LWG","The Parallelism TS Should be Standardized","Jacksonville","","" -"`P0226R1 `__","LWG","Mathematical Special Functions for C++17","Jacksonville","","" +"`P0226R1 `__","LWG","Mathematical Special Functions for C++17","Jacksonville","|Complete|","17.0" "`P0220R1 `__","LWG","Adopt Library Fundamentals V1 TS Components for C++17","Jacksonville","|Complete|","16.0" "`P0218R1 `__","LWG","Adopt the File System TS for C++17","Jacksonville","|Complete|","7.0" "`P0033R1 `__","LWG","Re-enabling shared_from_this","Jacksonville","|Complete|","3.9" diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -411,6 +411,7 @@ __iterator/unreachable_sentinel.h __iterator/wrap_iter.h __locale + __math/special_functions.h __mbstate_t.h __memory/addressof.h __memory/align.h diff --git a/libcxx/include/__availability b/libcxx/include/__availability --- a/libcxx/include/__availability +++ b/libcxx/include/__availability @@ -161,6 +161,8 @@ // to use it when the mechanism isn't overriden at compile-time. // # define _LIBCPP_HAS_NO_VERBOSE_ABORT_IN_LIBRARY +# define _LIBCPP_AVAILABILITY_MATHEMATICAL_SPECIAL_FUNCTIONS + #elif defined(__APPLE__) # define _LIBCPP_AVAILABILITY_SHARED_MUTEX \ diff --git a/libcxx/include/__math/special_functions.h b/libcxx/include/__math/special_functions.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__math/special_functions.h @@ -0,0 +1,553 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___MATH_SPECIAL_FUNCTIONS_H +#define _LIBCPP___MATH_SPECIAL_FUNCTIONS_H + +#include <__availability> +#include <__config> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_arithmetic.h> +#include +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +struct __msf_result { + bool __domain_error; + _Tp __ret; + + operator _Tp() { +# if math_errhandling & MATH_ERRNO + if (__domain_error) + errno = EDOM; +# endif + +# if math_errhandling & MATH_ERREXCEPT + if (__domain_error) + feraiseexcept(FE_INVALID); +# endif + + return __ret; + } +}; + +# define _LIBCPP_LIBRARY_MSF \ + [[__gnu__::__const__]] _LIBCPP_FUNC_VIS _LIBCPP_AVAILABILITY_MATHEMATICAL_SPECIAL_FUNCTIONS + +# define _LIBCPP_HEADER_MSF \ + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_MATHEMATICAL_SPECIAL_FUNCTIONS + +// assoc_laguerre +_LIBCPP_LIBRARY_MSF __msf_result __assoc_laguerre(unsigned int, unsigned int, float) noexcept; +_LIBCPP_LIBRARY_MSF __msf_result __assoc_laguerre(unsigned int, unsigned int, double) noexcept; +_LIBCPP_LIBRARY_MSF __msf_result __assoc_laguerre(unsigned int, unsigned int, long double) noexcept; + +_LIBCPP_HEADER_MSF inline float assoc_laguerre(unsigned int __n, unsigned int __m, float __x) noexcept { + return std::__assoc_laguerre(__n, __m, __x); +} + +_LIBCPP_HEADER_MSF inline double assoc_laguerre(unsigned int __n, unsigned int __m, double __x) noexcept { + return std::__assoc_laguerre(__n, __m, __x); +} + +_LIBCPP_HEADER_MSF inline long double assoc_laguerre(unsigned int __n, unsigned int __m, long double __x) noexcept { + return std::__assoc_laguerre(__n, __m, __x); +} + +_LIBCPP_HEADER_MSF inline float assoc_laguerref(unsigned int __n, unsigned int __m, float __x) noexcept { + return std::assoc_laguerre(__n, __m, __x); +} + +_LIBCPP_HEADER_MSF inline long double assoc_laguerrel(unsigned int __n, unsigned int __m, long double __x) noexcept { + return std::assoc_laguerre(__n, __m, __x); +} + +template , int> = 0> +_LIBCPP_HEADER_MSF double assoc_laguerre(unsigned int __n, unsigned int __m, _Tp __v) noexcept { + return std::assoc_laguerre(__n, __m, static_cast(__v)); +} + +// assoc_legendre +_LIBCPP_LIBRARY_MSF __msf_result __assoc_legendre(unsigned int, unsigned int, float) noexcept; +_LIBCPP_LIBRARY_MSF __msf_result __assoc_legendre(unsigned int, unsigned int, double) noexcept; +_LIBCPP_LIBRARY_MSF __msf_result __assoc_legendre(unsigned int, unsigned int, long double) noexcept; + +_LIBCPP_HEADER_MSF inline float assoc_legendre(unsigned int __n, unsigned int __m, float __x) noexcept { + return std::__assoc_legendre(__n, __m, __x); +} + +_LIBCPP_HEADER_MSF inline double assoc_legendre(unsigned int __n, unsigned int __m, double __x) noexcept { + return std::__assoc_legendre(__n, __m, __x); +} + +_LIBCPP_HEADER_MSF inline long double assoc_legendre(unsigned int __n, unsigned int __m, long double __x) noexcept { + return std::__assoc_legendre(__n, __m, __x); +} + +_LIBCPP_HEADER_MSF inline float assoc_legendref(unsigned int __n, unsigned int __m, float __x) noexcept { + return std::assoc_legendre(__n, __m, __x); +} + +_LIBCPP_HEADER_MSF inline long double assoc_legendrel(unsigned int __n, unsigned int __m, long double __x) noexcept { + return std::assoc_legendre(__n, __m, __x); +} + +template , int> = 0> +_LIBCPP_HEADER_MSF double assoc_legendre(unsigned int __n, unsigned int __m, _Tp __v) noexcept { + return std::assoc_legendre(__n, __m, static_cast(__v)); +} + +// beta +_LIBCPP_LIBRARY_MSF __msf_result __beta(float, float) noexcept; +_LIBCPP_LIBRARY_MSF __msf_result __beta(double, double) noexcept; +_LIBCPP_LIBRARY_MSF __msf_result __beta(long double, long double) noexcept; + +_LIBCPP_HEADER_MSF inline float beta(float __x, float __y) noexcept { return std::__beta(__x, __y); } +_LIBCPP_HEADER_MSF inline double beta(double __x, double __y) noexcept { return std::__beta(__x, __y); } +_LIBCPP_HEADER_MSF inline long double beta(long double __x, long double __y) noexcept { return std::__beta(__x, __y); } +_LIBCPP_HEADER_MSF inline float betaf(float __x, float __y) noexcept { return std::beta(__x, __y); } +_LIBCPP_HEADER_MSF inline long double betal(long double __x, long double __y) noexcept { return std::beta(__x, __y); } + +template && is_arithmetic_v<_Up>, int> = 0> +_LIBCPP_HEADER_MSF typename __promote<_Tp, _Up>::type beta(_Tp __x, _Up __y) noexcept { + using __result_type = typename __promote<_Tp, _Up>::type; + return std::beta(static_cast<__result_type>(__x), static_cast<__result_type>(__y)); +} + +// comp_ellint_1 +_LIBCPP_LIBRARY_MSF __msf_result __comp_ellint_1(float __x) noexcept; +_LIBCPP_LIBRARY_MSF __msf_result __comp_ellint_1(double __x) noexcept; +_LIBCPP_LIBRARY_MSF __msf_result __comp_ellint_1(long double __x) noexcept; + +_LIBCPP_HEADER_MSF inline float comp_ellint_1(float __x) noexcept { return std::__comp_ellint_1(__x); } +_LIBCPP_HEADER_MSF inline double comp_ellint_1(double __x) noexcept { return std::__comp_ellint_1(__x); } +_LIBCPP_HEADER_MSF inline long double comp_ellint_1(long double __x) noexcept { return std::__comp_ellint_1(__x); } +_LIBCPP_HEADER_MSF inline float comp_ellint_1f(float __x) noexcept { return std::comp_ellint_1(__x); } +_LIBCPP_HEADER_MSF inline long double comp_ellint_1l(long double __x) noexcept { return std::comp_ellint_1(__x); } + +template , int> = 0> +_LIBCPP_HEADER_MSF double comp_ellint_1(_Tp __x) noexcept { + return std::comp_ellint_1(static_cast(__x)); +} + +// comp_ellint_2 +_LIBCPP_LIBRARY_MSF __msf_result __comp_ellint_2(float __x) noexcept; +_LIBCPP_LIBRARY_MSF __msf_result __comp_ellint_2(double __x) noexcept; +_LIBCPP_LIBRARY_MSF __msf_result __comp_ellint_2(long double __x) noexcept; + +_LIBCPP_HEADER_MSF inline float comp_ellint_2(float __x) noexcept { return std::__comp_ellint_2(__x); } +_LIBCPP_HEADER_MSF inline double comp_ellint_2(double __x) noexcept { return std::__comp_ellint_2(__x); } +_LIBCPP_HEADER_MSF inline long double comp_ellint_2(long double __x) noexcept { return std::__comp_ellint_2(__x); } +_LIBCPP_HEADER_MSF inline float comp_ellint_2f(float __x) noexcept { return std::comp_ellint_2(__x); } +_LIBCPP_HEADER_MSF inline long double comp_ellint_2l(long double __x) noexcept { return std::comp_ellint_2(__x); } + +template , int> = 0> +_LIBCPP_HEADER_MSF double comp_ellint_2(_Tp __x) noexcept { + return std::comp_ellint_2(static_cast(__x)); +} + +// comp_ellint_3 +_LIBCPP_LIBRARY_MSF __msf_result __comp_ellint_3(float __x, float __y) noexcept; +_LIBCPP_LIBRARY_MSF __msf_result __comp_ellint_3(double __x, double __y) noexcept; +_LIBCPP_LIBRARY_MSF __msf_result __comp_ellint_3(long double __x, long double __y) noexcept; + +_LIBCPP_HEADER_MSF inline float comp_ellint_3(float __x, float __y) noexcept { return std::__comp_ellint_3(__x, __y); } + +_LIBCPP_HEADER_MSF inline double comp_ellint_3(double __x, double __y) noexcept { + return std::__comp_ellint_3(__x, __y); +} + +_LIBCPP_HEADER_MSF inline long double comp_ellint_3(long double __x, long double __y) noexcept { + return std::__comp_ellint_3(__x, __y); +} + +_LIBCPP_HEADER_MSF inline float comp_ellint_3f(float __x, float __y) noexcept { return std::comp_ellint_3(__x, __y); } + +_LIBCPP_HEADER_MSF inline long double comp_ellint_3l(long double __x, long double __y) noexcept { + return std::comp_ellint_3(__x, __y); +} + +template && is_arithmetic_v<_Up>, int> = 0> +_LIBCPP_HEADER_MSF typename __promote<_Tp, _Up>::type comp_ellint_3(_Tp __x, _Up __y) noexcept { + using __result_type = typename __promote<_Tp, _Up>::type; + return std::comp_ellint_3(static_cast<__result_type>(__x), static_cast<__result_type>(__y)); +} + +// cyl_bessel_i +_LIBCPP_LIBRARY_MSF __msf_result __cyl_bessel_i(float __x, float __y) noexcept; +_LIBCPP_LIBRARY_MSF __msf_result __cyl_bessel_i(double __x, double __y) noexcept; +_LIBCPP_LIBRARY_MSF __msf_result __cyl_bessel_i(long double __x, long double __y) noexcept; + +_LIBCPP_HEADER_MSF inline float cyl_bessel_i(float __x, float __y) noexcept { return std::__cyl_bessel_i(__x, __y); } +_LIBCPP_HEADER_MSF inline double cyl_bessel_i(double __x, double __y) noexcept { return std::__cyl_bessel_i(__x, __y); } + +_LIBCPP_HEADER_MSF inline long double cyl_bessel_i(long double __x, long double __y) noexcept { + return std::__cyl_bessel_i(__x, __y); +} + +_LIBCPP_HEADER_MSF inline float cyl_bessel_if(float __x, float __y) noexcept { return std::cyl_bessel_i(__x, __y); } + +_LIBCPP_HEADER_MSF inline long double cyl_bessel_il(long double __x, long double __y) noexcept { + return std::cyl_bessel_i(__x, __y); +} + +template && is_arithmetic_v<_Up>, int> = 0> +_LIBCPP_HEADER_MSF typename __promote<_Tp, _Up>::type cyl_bessel_i(_Tp __x, _Up __y) noexcept { + using __result_type = typename __promote<_Tp, _Up>::type; + return std::cyl_bessel_i(static_cast<__result_type>(__x), static_cast<__result_type>(__y)); +} + +// cyl_bessel_j +_LIBCPP_LIBRARY_MSF __msf_result __cyl_bessel_j(float __x, float __y) noexcept; +_LIBCPP_LIBRARY_MSF __msf_result __cyl_bessel_j(double __x, double __y) noexcept; +_LIBCPP_LIBRARY_MSF __msf_result __cyl_bessel_j(long double __x, long double __y) noexcept; + +_LIBCPP_HEADER_MSF inline float cyl_bessel_j(float __x, float __y) noexcept { return std::__cyl_bessel_j(__x, __y); } +_LIBCPP_HEADER_MSF inline double cyl_bessel_j(double __x, double __y) noexcept { return std::__cyl_bessel_j(__x, __y); } +_LIBCPP_HEADER_MSF inline long double cyl_bessel_j(long double __x, long double __y) noexcept { + return std::__cyl_bessel_j(__x, __y); +} + +_LIBCPP_HEADER_MSF inline float cyl_bessel_jf(float __x, float __y) noexcept { return std::cyl_bessel_j(__x, __y); } + +_LIBCPP_HEADER_MSF inline long double cyl_bessel_jl(long double __x, long double __y) noexcept { + return std::cyl_bessel_j(__x, __y); +} + +template && is_arithmetic_v<_Up>, int> = 0> +_LIBCPP_HEADER_MSF typename __promote<_Tp, _Up>::type cyl_bessel_j(_Tp __x, _Up __y) noexcept { + using __result_type = typename __promote<_Tp, _Up>::type; + return std::cyl_bessel_j(static_cast<__result_type>(__x), static_cast<__result_type>(__y)); +} + +// cyl_bessel_k +_LIBCPP_LIBRARY_MSF __msf_result __cyl_bessel_k(float __x, float __y) noexcept; +_LIBCPP_LIBRARY_MSF __msf_result __cyl_bessel_k(double __x, double __y) noexcept; +_LIBCPP_LIBRARY_MSF __msf_result __cyl_bessel_k(long double __x, long double __y) noexcept; + +_LIBCPP_HEADER_MSF inline float cyl_bessel_k(float __x, float __y) noexcept { return std::__cyl_bessel_k(__x, __y); } +_LIBCPP_HEADER_MSF inline double cyl_bessel_k(double __x, double __y) noexcept { return std::__cyl_bessel_k(__x, __y); } +_LIBCPP_HEADER_MSF inline long double cyl_bessel_k(long double __x, long double __y) noexcept { + return std::__cyl_bessel_k(__x, __y); +} + +_LIBCPP_HEADER_MSF inline float cyl_bessel_kf(float __x, float __y) noexcept { return std::cyl_bessel_k(__x, __y); } + +_LIBCPP_HEADER_MSF inline long double cyl_bessel_kl(long double __x, long double __y) noexcept { + return std::cyl_bessel_k(__x, __y); +} + +template && is_arithmetic_v<_Up>, int> = 0> +_LIBCPP_HEADER_MSF typename __promote<_Tp, _Up>::type cyl_bessel_k(_Tp __x, _Up __y) noexcept { + using __result_type = typename __promote<_Tp, _Up>::type; + return std::cyl_bessel_k(static_cast<__result_type>(__x), static_cast<__result_type>(__y)); +} + +// cyl_neumann +_LIBCPP_LIBRARY_MSF __msf_result __cyl_neumann(float __x, float __y) noexcept; +_LIBCPP_LIBRARY_MSF __msf_result __cyl_neumann(double __x, double __y) noexcept; +_LIBCPP_LIBRARY_MSF __msf_result __cyl_neumann(long double __x, long double __y) noexcept; + +_LIBCPP_HEADER_MSF inline float cyl_neumann(float __x, float __y) noexcept { return std::__cyl_neumann(__x, __y); } +_LIBCPP_HEADER_MSF inline double cyl_neumann(double __x, double __y) noexcept { return std::__cyl_neumann(__x, __y); } +_LIBCPP_HEADER_MSF inline long double cyl_neumann(long double __x, long double __y) noexcept { + return std::__cyl_neumann(__x, __y); +} + +_LIBCPP_HEADER_MSF inline float cyl_neumannf(float __x, float __y) noexcept { return std::cyl_neumann(__x, __y); } + +_LIBCPP_HEADER_MSF inline long double cyl_neumannl(long double __x, long double __y) noexcept { + return std::cyl_neumann(__x, __y); +} + +template && is_arithmetic_v<_Up>, int> = 0> +_LIBCPP_HEADER_MSF typename __promote<_Tp, _Up>::type cyl_neumann(_Tp __x, _Up __y) noexcept { + using __result_type = typename __promote<_Tp, _Up>::type; + return std::cyl_neumann(static_cast<__result_type>(__x), static_cast<__result_type>(__y)); +} + +// ellint_1 +_LIBCPP_LIBRARY_MSF __msf_result __ellint_1(float __x, float __y) noexcept; +_LIBCPP_LIBRARY_MSF __msf_result __ellint_1(double __x, double __y) noexcept; +_LIBCPP_LIBRARY_MSF __msf_result __ellint_1(long double __x, long double __y) noexcept; + +_LIBCPP_HEADER_MSF inline float ellint_1(float __x, float __y) noexcept { return std::__ellint_1(__x, __y); } +_LIBCPP_HEADER_MSF inline double ellint_1(double __x, double __y) noexcept { return std::__ellint_1(__x, __y); } +_LIBCPP_HEADER_MSF inline long double ellint_1(long double __x, long double __y) noexcept { + return std::__ellint_1(__x, __y); +} + +_LIBCPP_HEADER_MSF inline float ellint_1f(float __x, float __y) noexcept { return std::ellint_1(__x, __y); } + +_LIBCPP_HEADER_MSF inline long double ellint_1l(long double __x, long double __y) noexcept { + return std::ellint_1(__x, __y); +} + +template && is_arithmetic_v<_Up>, int> = 0> +_LIBCPP_HEADER_MSF typename __promote<_Tp, _Up>::type ellint_1(_Tp __x, _Up __y) noexcept { + using __result_type = typename __promote<_Tp, _Up>::type; + return std::ellint_1(static_cast<__result_type>(__x), static_cast<__result_type>(__y)); +} + +// ellint_2 +_LIBCPP_LIBRARY_MSF __msf_result __ellint_2(float __x, float __y) noexcept; +_LIBCPP_LIBRARY_MSF __msf_result __ellint_2(double __x, double __y) noexcept; +_LIBCPP_LIBRARY_MSF __msf_result __ellint_2(long double __x, long double __y) noexcept; + +_LIBCPP_HEADER_MSF inline float ellint_2(float __x, float __y) noexcept { return std::__ellint_2(__x, __y); } +_LIBCPP_HEADER_MSF inline double ellint_2(double __x, double __y) noexcept { return std::__ellint_2(__x, __y); } +_LIBCPP_HEADER_MSF inline long double ellint_2(long double __x, long double __y) noexcept { + return std::__ellint_2(__x, __y); +} + +_LIBCPP_HEADER_MSF inline float ellint_2f(float __x, float __y) noexcept { return std::ellint_2(__x, __y); } + +_LIBCPP_HEADER_MSF inline long double ellint_2l(long double __x, long double __y) noexcept { + return std::ellint_2(__x, __y); +} + +template && is_arithmetic_v<_Up>, int> = 0> +_LIBCPP_HEADER_MSF typename __promote<_Tp, _Up>::type ellint_2(_Tp __x, _Up __y) noexcept { + using __result_type = typename __promote<_Tp, _Up>::type; + return std::ellint_2(static_cast<__result_type>(__x), static_cast<__result_type>(__y)); +} + +// ellint_3 +_LIBCPP_LIBRARY_MSF __msf_result __ellint_3(float __x, float __y, float __z) noexcept; +_LIBCPP_LIBRARY_MSF __msf_result __ellint_3(double __x, double __y, double __z) noexcept; +_LIBCPP_LIBRARY_MSF __msf_result __ellint_3(long double __x, long double __y, long double __z) noexcept; + +_LIBCPP_HEADER_MSF inline float ellint_3(float __x, float __y, float __z) noexcept { + return std::__ellint_3(__x, __y, __z); +} + +_LIBCPP_HEADER_MSF inline double ellint_3(double __x, double __y, double __z) noexcept { + return std::__ellint_3(__x, __y, __z); +} + +_LIBCPP_HEADER_MSF inline long double ellint_3(long double __x, long double __y, long double __z) noexcept { + return std::__ellint_3(__x, __y, __z); +} + +_LIBCPP_HEADER_MSF inline float ellint_3f(float __x, float __y, float __z) noexcept { + return std::ellint_3(__x, __y, __z); +} + +_LIBCPP_HEADER_MSF inline long double ellint_3l(long double __x, long double __y, long double __z) noexcept { + return std::ellint_3(__x, __y, __z); +} + +template && is_arithmetic_v<_Up> && is_arithmetic_v<_Vp>, int> = 0> +_LIBCPP_HEADER_MSF typename __promote<_Tp, _Up, _Vp>::type ellint_3(_Tp __x, _Up __y, _Vp __z) noexcept { + using __result_type = typename __promote<_Tp, _Up, _Vp>::type; + return std::ellint_3( + static_cast<__result_type>(__x), static_cast<__result_type>(__y), static_cast<__result_type>(__z)); +} + +// expint +_LIBCPP_LIBRARY_MSF __msf_result __expint(float __x) noexcept; +_LIBCPP_LIBRARY_MSF __msf_result __expint(double __x) noexcept; +_LIBCPP_LIBRARY_MSF __msf_result __expint(long double __x) noexcept; + +_LIBCPP_HEADER_MSF inline float expint(float __x) noexcept { return std::__expint(__x); } +_LIBCPP_HEADER_MSF inline double expint(double __x) noexcept { return std::__expint(__x); } +_LIBCPP_HEADER_MSF inline long double expint(long double __x) noexcept { return std::__expint(__x); } +_LIBCPP_HEADER_MSF inline float expintf(float __x) noexcept { return std::expint(__x); } +_LIBCPP_HEADER_MSF inline long double expintl(long double __x) noexcept { return std::expint(__x); } + +template , int> = 0> +_LIBCPP_HEADER_MSF double expint(_Tp __x) noexcept { + return std::expint(static_cast(__x)); +} + +// hermite +_LIBCPP_LIBRARY_MSF __msf_result __hermite(unsigned int __n, float __x) noexcept; +_LIBCPP_LIBRARY_MSF __msf_result __hermite(unsigned int __n, double __x) noexcept; +_LIBCPP_LIBRARY_MSF __msf_result __hermite(unsigned int __n, long double __x) noexcept; + +_LIBCPP_HEADER_MSF inline float hermite(unsigned int __n, float __x) noexcept { return std::__hermite(__n, __x); } +_LIBCPP_HEADER_MSF inline double hermite(unsigned int __n, double __x) noexcept { return std::__hermite(__n, __x); } +_LIBCPP_HEADER_MSF inline long double hermite(unsigned int __n, long double __x) noexcept { + return std::__hermite(__n, __x); +} + +_LIBCPP_HEADER_MSF inline float hermitef(unsigned int __n, float __x) noexcept { return std::hermite(__n, __x); } + +_LIBCPP_HEADER_MSF inline long double hermitel(unsigned int __n, long double __x) noexcept { + return std::hermite(__n, __x); +} + +template , int> = 0> +_LIBCPP_HEADER_MSF double hermite(unsigned int __n, _Tp __x) noexcept { + return std::hermite(__n, static_cast(__x)); +} + +// laguerre +_LIBCPP_LIBRARY_MSF __msf_result __laguerre(unsigned int __n, float __x) noexcept; +_LIBCPP_LIBRARY_MSF __msf_result __laguerre(unsigned int __n, double __x) noexcept; +_LIBCPP_LIBRARY_MSF __msf_result __laguerre(unsigned int __n, long double __x) noexcept; + +_LIBCPP_HEADER_MSF inline float laguerre(unsigned int __n, float __x) noexcept { return std::__laguerre(__n, __x); } +_LIBCPP_HEADER_MSF inline double laguerre(unsigned int __n, double __x) noexcept { return std::__laguerre(__n, __x); } +_LIBCPP_HEADER_MSF inline long double laguerre(unsigned int __n, long double __x) noexcept { + return std::__laguerre(__n, __x); +} + +_LIBCPP_HEADER_MSF inline float laguerref(unsigned int __n, float __x) noexcept { return std::laguerre(__n, __x); } + +_LIBCPP_HEADER_MSF inline long double laguerrel(unsigned int __n, long double __x) noexcept { + return std::laguerre(__n, __x); +} + +template , int> = 0> +_LIBCPP_HEADER_MSF double laguerre(unsigned int __n, _Tp __x) noexcept { + return std::laguerre(__n, static_cast(__x)); +} + +// legendre +_LIBCPP_LIBRARY_MSF __msf_result __legendre(unsigned int __n, float __x) noexcept; +_LIBCPP_LIBRARY_MSF __msf_result __legendre(unsigned int __n, double __x) noexcept; +_LIBCPP_LIBRARY_MSF __msf_result __legendre(unsigned int __n, long double __x) noexcept; + +_LIBCPP_HEADER_MSF inline float legendre(unsigned int __n, float __x) noexcept { return std::__legendre(__n, __x); } +_LIBCPP_HEADER_MSF inline double legendre(unsigned int __n, double __x) noexcept { return std::__legendre(__n, __x); } +_LIBCPP_HEADER_MSF inline long double legendre(unsigned int __n, long double __x) noexcept { + return std::__legendre(__n, __x); +} + +_LIBCPP_HEADER_MSF inline float legendref(unsigned int __n, float __x) noexcept { return std::legendre(__n, __x); } + +_LIBCPP_HEADER_MSF inline long double legendrel(unsigned int __n, long double __x) noexcept { + return std::legendre(__n, __x); +} + +template , int> = 0> +_LIBCPP_HEADER_MSF double legendre(unsigned int __n, _Tp __x) noexcept { + return std::legendre(__n, static_cast(__x)); +} + +// riemann_zeta +_LIBCPP_LIBRARY_MSF __msf_result __riemann_zeta(float __x) noexcept; +_LIBCPP_LIBRARY_MSF __msf_result __riemann_zeta(double __x) noexcept; +_LIBCPP_LIBRARY_MSF __msf_result __riemann_zeta(long double __x) noexcept; + +_LIBCPP_HEADER_MSF inline float riemann_zeta(float __x) noexcept { return std::__riemann_zeta(__x); } +_LIBCPP_HEADER_MSF inline double riemann_zeta(double __x) noexcept { return std::__riemann_zeta(__x); } +_LIBCPP_HEADER_MSF inline long double riemann_zeta(long double __x) noexcept { return std::__riemann_zeta(__x); } + +_LIBCPP_HEADER_MSF inline float riemann_zetaf(float __x) noexcept { return std::riemann_zeta(__x); } +_LIBCPP_HEADER_MSF inline long double riemann_zetal(long double __x) noexcept { return std::riemann_zeta(__x); } + +template , int> = 0> +_LIBCPP_HEADER_MSF double riemann_zeta(_Tp __v) noexcept { + return std::riemann_zeta(static_cast(__v)); +} + +// sph_bessel +_LIBCPP_LIBRARY_MSF __msf_result __sph_bessel(unsigned int __n, float __x) noexcept; +_LIBCPP_LIBRARY_MSF __msf_result __sph_bessel(unsigned int __n, double __x) noexcept; +_LIBCPP_LIBRARY_MSF __msf_result __sph_bessel(unsigned int __n, long double __x) noexcept; + +_LIBCPP_HEADER_MSF inline float sph_bessel(unsigned int __n, float __x) noexcept { return std::__sph_bessel(__n, __x); } + +_LIBCPP_HEADER_MSF inline double sph_bessel(unsigned int __n, double __x) noexcept { + return std::__sph_bessel(__n, __x); +} +_LIBCPP_HEADER_MSF inline long double sph_bessel(unsigned int __n, long double __x) noexcept { + return std::__sph_bessel(__n, __x); +} + +_LIBCPP_HEADER_MSF inline float sph_besself(unsigned int __n, float __x) noexcept { return std::sph_bessel(__n, __x); } + +_LIBCPP_HEADER_MSF inline long double sph_bessell(unsigned int __n, long double __x) noexcept { + return std::sph_bessel(__n, __x); +} + +template , int> = 0> +_LIBCPP_HEADER_MSF double sph_bessel(unsigned int __n, _Tp __x) noexcept { + return std::sph_bessel(__n, static_cast(__x)); +} + +// sph_legendre +_LIBCPP_LIBRARY_MSF __msf_result __sph_legendre(unsigned int __x, unsigned int __y, float __z) noexcept; +_LIBCPP_LIBRARY_MSF __msf_result __sph_legendre(unsigned int __x, unsigned int __y, double __z) noexcept; +_LIBCPP_LIBRARY_MSF __msf_result +__sph_legendre(unsigned int __x, unsigned int __y, long double __z) noexcept; + +_LIBCPP_HEADER_MSF inline float sph_legendre(unsigned int __x, unsigned int __y, float __z) noexcept { + return std::__sph_legendre(__x, __y, __z); +} + +_LIBCPP_HEADER_MSF inline double sph_legendre(unsigned int __x, unsigned int __y, double __z) noexcept { + return std::__sph_legendre(__x, __y, __z); +} + +_LIBCPP_HEADER_MSF inline long double sph_legendre(unsigned int __x, unsigned int __y, long double __z) noexcept { + return std::__sph_legendre(__x, __y, __z); +} + +_LIBCPP_HEADER_MSF inline float sph_legendref(unsigned int __x, unsigned int __y, float __z) noexcept { + return std::sph_legendre(__x, __y, __z); +} + +_LIBCPP_HEADER_MSF inline long double sph_legendrel(unsigned int __x, unsigned int __y, long double __z) noexcept { + return std::sph_legendre(__x, __y, __z); +} + +template , int> = 0> +_LIBCPP_HEADER_MSF double sph_legendre(unsigned int __x, unsigned int __y, _Tp __z) noexcept { + return std::sph_legendre(__x, __y, static_cast(__z)); +} + +// sph_neumann +_LIBCPP_LIBRARY_MSF __msf_result __sph_neumann(unsigned int __n, float __x) noexcept; +_LIBCPP_LIBRARY_MSF __msf_result __sph_neumann(unsigned int __n, double __x) noexcept; +_LIBCPP_LIBRARY_MSF __msf_result __sph_neumann(unsigned int __n, long double __x) noexcept; + +_LIBCPP_HEADER_MSF inline float sph_neumann(unsigned int __n, float __x) noexcept { + return std::__sph_neumann(__n, __x); +} + +_LIBCPP_HEADER_MSF inline double sph_neumann(unsigned int __n, double __x) noexcept { + return std::__sph_neumann(__n, __x); +} + +_LIBCPP_HEADER_MSF inline long double sph_neumann(unsigned int __n, long double __x) noexcept { + return std::__sph_neumann(__n, __x); +} + +_LIBCPP_HEADER_MSF inline float sph_neumannf(unsigned int __n, float __x) noexcept { + return std::sph_neumann(__n, __x); +} + +_LIBCPP_HEADER_MSF inline long double sph_neumannl(unsigned int __n, long double __x) noexcept { + return std::sph_neumann(__n, __x); +} + +template , int> = 0> +_LIBCPP_HEADER_MSF double sph_neumann(unsigned int __n, _Tp __x) noexcept { + return std::sph_neumann(__n, static_cast(__x)); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___MATH_SPECIAL_FUNCTIONS_H diff --git a/libcxx/include/cmath b/libcxx/include/cmath --- a/libcxx/include/cmath +++ b/libcxx/include/cmath @@ -306,6 +306,7 @@ #include <__assert> // all public C++ headers provide the assertion handler #include <__config> +#include <__math/special_functions.h> #include <__type_traits/enable_if.h> #include <__type_traits/is_arithmetic.h> #include <__type_traits/is_constant_evaluated.h> diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in --- a/libcxx/include/module.modulemap.in +++ b/libcxx/include/module.modulemap.in @@ -1054,6 +1054,9 @@ export initializer_list export * } + module __math { + module special_functions { private header "__math/special_functions.h" } + } module memory { header "memory" export * diff --git a/libcxx/src/CMakeLists.txt b/libcxx/src/CMakeLists.txt --- a/libcxx/src/CMakeLists.txt +++ b/libcxx/src/CMakeLists.txt @@ -30,6 +30,7 @@ include/ryu/ryu.h include/to_chars_floating_point.h legacy_pointer_safety.cpp + mathematical_special_functions.cpp memory.cpp memory_resource.cpp mutex.cpp @@ -198,9 +199,10 @@ # Build the shared library. if (LIBCXX_ENABLE_SHARED) add_library(cxx_shared SHARED ${exclude_from_all} ${LIBCXX_SOURCES} ${LIBCXX_HEADERS}) - target_include_directories(cxx_shared PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) + target_include_directories(cxx_shared PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/third-party) target_link_libraries(cxx_shared PUBLIC cxx-headers PRIVATE ${LIBCXX_LIBRARIES}) + target_compile_definitions(cxx_shared PRIVATE "BOOST_MATH_STANDALONE") set_target_properties(cxx_shared PROPERTIES COMPILE_FLAGS "${LIBCXX_COMPILE_FLAGS}" @@ -292,10 +294,11 @@ # Build the static library. if (LIBCXX_ENABLE_STATIC) add_library(cxx_static STATIC ${exclude_from_all} ${LIBCXX_SOURCES} ${LIBCXX_HEADERS}) - target_include_directories(cxx_static PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) + target_include_directories(cxx_static PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/third-party) target_link_libraries(cxx_static PUBLIC cxx-headers PRIVATE ${LIBCXX_LIBRARIES} PRIVATE libcxx-abi-static) + target_compile_definitions(cxx_static PRIVATE "BOOST_MATH_STANDALONE") set_target_properties(cxx_static PROPERTIES COMPILE_FLAGS "${LIBCXX_COMPILE_FLAGS}" diff --git a/libcxx/src/mathematical_special_functions.cpp b/libcxx/src/mathematical_special_functions.cpp new file mode 100644 --- /dev/null +++ b/libcxx/src/mathematical_special_functions.cpp @@ -0,0 +1,297 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <__config> +#include +#include +#include +#include +#include + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace { +template +optional check_nan() { + return nullopt; +} + +template +optional check_nan(Arg arg, Args... args) { + if constexpr (is_floating_point_v) + if (std::isnan(arg)) + return arg; + return check_nan(args...); +} + +template > +auto invoke_boost_math(Func f, Args... args) -> __msf_result { + if (auto maybe_nan = check_nan(args...); maybe_nan.has_value()) + return {false, *maybe_nan}; + + try { + return {false, f(args...)}; + } catch (...) { + return {true, numeric_limits::quiet_NaN()}; + } +} +} // namespace + +__msf_result __assoc_laguerre(unsigned int n, unsigned int m, float x) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::laguerre(args...); }, n, m, x); +} + +__msf_result __assoc_laguerre(unsigned int n, unsigned int m, double x) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::laguerre(args...); }, n, m, x); +} + +__msf_result __assoc_laguerre(unsigned int n, unsigned int m, long double x) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::laguerre(args...); }, n, m, x); +} + +__msf_result __assoc_legendre(unsigned int n, unsigned int m, float x) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::legendre_p(args...); }, n, m, x); +} + +__msf_result __assoc_legendre(unsigned int n, unsigned int m, double x) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::legendre_p(args...); }, n, m, x); +} + +__msf_result __assoc_legendre(unsigned int n, unsigned int m, long double x) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::legendre_p(args...); }, n, m, x); +} + +__msf_result __beta(float x, float y) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::beta(args...); }, x, y); +} + +__msf_result __beta(double x, double y) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::beta(args...); }, x, y); +} + +__msf_result __beta(long double x, long double y) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::beta(args...); }, x, y); +} + +__msf_result __comp_ellint_1(float x) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::ellint_1(args...); }, x); +} + +__msf_result __comp_ellint_1(double x) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::ellint_1(args...); }, x); +} + +__msf_result __comp_ellint_1(long double x) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::ellint_1(args...); }, x); +} + +__msf_result __comp_ellint_2(float x) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::ellint_2(args...); }, x); +} + +__msf_result __comp_ellint_2(double x) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::ellint_2(args...); }, x); +} + +__msf_result __comp_ellint_2(long double x) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::ellint_2(args...); }, x); +} + +__msf_result __comp_ellint_3(float x, float y) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::ellint_3(args...); }, x, y); +} + +__msf_result __comp_ellint_3(double x, double y) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::ellint_3(args...); }, x, y); +} + +__msf_result __comp_ellint_3(long double x, long double y) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::ellint_3(args...); }, x, y); +} + +__msf_result __cyl_bessel_i(float x, float y) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::cyl_bessel_i(args...); }, x, y); +} + +__msf_result __cyl_bessel_i(double x, double y) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::cyl_bessel_i(args...); }, x, y); +} + +__msf_result __cyl_bessel_i(long double x, long double y) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::cyl_bessel_i(args...); }, x, y); +} + +__msf_result __cyl_bessel_j(float x, float y) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::cyl_bessel_j(args...); }, x, y); +} + +__msf_result __cyl_bessel_j(double x, double y) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::cyl_bessel_j(args...); }, x, y); +} + +__msf_result __cyl_bessel_j(long double x, long double y) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::cyl_bessel_j(args...); }, x, y); +} + +__msf_result __cyl_bessel_k(float x, float y) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::cyl_bessel_k(args...); }, x, y); +} + +__msf_result __cyl_bessel_k(double x, double y) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::cyl_bessel_k(args...); }, x, y); +} + +__msf_result __cyl_bessel_k(long double x, long double y) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::cyl_bessel_k(args...); }, x, y); +} + +__msf_result __cyl_neumann(float x, float y) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::cyl_neumann(args...); }, x, y); +} + +__msf_result __cyl_neumann(double x, double y) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::cyl_neumann(args...); }, x, y); +} + +__msf_result __cyl_neumann(long double x, long double y) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::cyl_neumann(args...); }, x, y); +} + +__msf_result __ellint_1(float x, float y) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::ellint_1(args...); }, x, y); +} + +__msf_result __ellint_1(double x, double y) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::ellint_1(args...); }, x, y); +} + +__msf_result __ellint_1(long double x, long double y) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::ellint_1(args...); }, x, y); +} + +__msf_result __ellint_2(float x, float y) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::ellint_2(args...); }, x, y); +} + +__msf_result __ellint_2(double x, double y) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::ellint_2(args...); }, x, y); +} + +__msf_result __ellint_2(long double x, long double y) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::ellint_2(args...); }, x, y); +} + +__msf_result __ellint_3(float x, float y, float z) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::ellint_3(args...); }, x, y, z); +} + +__msf_result __ellint_3(double x, double y, double z) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::ellint_3(args...); }, x, y, z); +} + +__msf_result __ellint_3(long double x, long double y, long double z) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::ellint_3(args...); }, x, y, z); +} + +__msf_result __expint(float x) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::expint(args...); }, x); +} + +__msf_result __expint(double x) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::expint(args...); }, x); +} + +__msf_result __expint(long double x) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::expint(args...); }, x); +} + +__msf_result __hermite(unsigned int n, float x) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::hermite(args...); }, n, x); +} + +__msf_result __hermite(unsigned int n, double x) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::hermite(args...); }, n, x); +} + +__msf_result __hermite(unsigned int n, long double x) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::hermite(args...); }, n, x); +} + +__msf_result __laguerre(unsigned int n, float x) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::laguerre(args...); }, n, x); +} + +__msf_result __laguerre(unsigned int n, double x) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::laguerre(args...); }, n, x); +} + +__msf_result __laguerre(unsigned int n, long double x) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::laguerre(args...); }, n, x); +} + +__msf_result __legendre(unsigned int n, float x) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::legendre_p(args...); }, n, x); +} + +__msf_result __legendre(unsigned int n, double x) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::legendre_p(args...); }, n, x); +} + +__msf_result __legendre(unsigned int n, long double x) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::legendre_p(args...); }, n, x); +} + +__msf_result __riemann_zeta(float x) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::zeta(args...); }, x); +} + +__msf_result __riemann_zeta(double x) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::zeta(args...); }, x); +} + +__msf_result __riemann_zeta(long double x) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::zeta(args...); }, x); +} + +__msf_result __sph_bessel(unsigned int n, float x) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::sph_bessel(args...); }, n, x); +} + +__msf_result __sph_bessel(unsigned int n, double x) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::sph_bessel(args...); }, n, x); +} + +__msf_result __sph_bessel(unsigned int n, long double x) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::sph_bessel(args...); }, n, x); +} + +__msf_result __sph_legendre(unsigned int n, unsigned int m, float x) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::spherical_harmonic_r(args..., 0.f); }, n, m, x); +} + +__msf_result __sph_legendre(unsigned int n, unsigned int m, double x) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::spherical_harmonic_r(args..., 0.0); }, n, m, x); +} + +__msf_result __sph_legendre(unsigned int n, unsigned int m, long double x) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::spherical_harmonic_r(args..., 0.l); }, n, m, x); +} + +__msf_result __sph_neumann(unsigned int m, float x) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::sph_neumann(args...); }, m, x); +} + +__msf_result __sph_neumann(unsigned int m, double x) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::sph_neumann(args...); }, m, x); +} + +__msf_result __sph_neumann(unsigned int m, long double x) noexcept { + return invoke_boost_math([&](auto... args) { return boost::math::sph_neumann(args...); }, m, x); +} + +_LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/src/third-party/LICENSE_1_0.txt b/libcxx/src/third-party/LICENSE_1_0.txt new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/LICENSE_1_0.txt @@ -0,0 +1,23 @@ +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/libcxx/src/third-party/boost/math/bindings/detail/big_digamma.hpp b/libcxx/src/third-party/boost/math/bindings/detail/big_digamma.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/bindings/detail/big_digamma.hpp @@ -0,0 +1,297 @@ +// (C) Copyright John Maddock 2006-8. +// 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_NTL_DIGAMMA +#define BOOST_MATH_NTL_DIGAMMA + +#include +#include +#include +#include +#include + +namespace boost{ namespace math{ namespace detail{ + +template +T big_digamma_helper(T x) +{ + static const T P[61] = { + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.6660133691143982067148122682345055274952e81), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.6365271516829242456324234577164675383137e81), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.2991038873096202943405966144203628966976e81), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.9211116495503170498076013367421231351115e80), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.2090792764676090716286400360584443891749e80), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.3730037777359591428226035156377978092809e79), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.5446396536956682043376492370432031543834e78), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.6692523966335177847425047827449069256345e77), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.7062543624100864681625612653756619116848e76), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.6499914905966283735005256964443226879158e75), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.5280364564853225211197557708655426736091e74), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.3823205608981176913075543599005095206953e73), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.2486733714214237704739129972671154532415e72), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.1462562139602039577983434547171318011675e71), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.7821169065036815012381267259559910324285e69), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.3820552182348155468636157988764435365078e68), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.1711618296983598244658239925535632505062e67), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.7056661618357643731419080738521475204245e65), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.2685246896473614017356264531791459936036e64), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.9455168125599643085283071944864977592391e62), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.3087541626972538362237309145177486236219e61), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.9367928873352980208052601301625005737407e59), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.2645306130689794942883818547314327466007e58), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.6961815141171454309161007351079576190079e56), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.1709637824471794552313802669803885946843e55), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.3921553258481531526663112728778759311158e53), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.8409006354449988687714450897575728228696e51), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.1686755204461325935742097669030363344927e50), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.3166653542877070999007425197729038754254e48), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.5566029092358215049069560272835654229637e46), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.9161766287916328133080586672953875116242e44), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 1412317772330871298317974693514430627922000), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 20387991986727877473732570146112459874790), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 275557928713904105182512535678580359839.3), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 3485719851040516559072031256589598330.723), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 41247046743564028399938106707656877.40859), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 456274078125709314602601667471879.0147312), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 4714450683242899367025707077155.310613012), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 45453933537925041680009544258.75073849996), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 408437900487067278846361972.302331241052), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 3415719344386166273085838.705771571751035), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 26541502879185876562320.93134691487351145), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 191261415065918713661.1571433274648417668), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 1275349770108718421.645275944284937551702), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 7849171120971773.318910987434906905704272), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 44455946386549.80866460312682983576538056), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 230920362395.3198137186361608905136598046), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 1095700096.240863858624279930600654130254), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 4727085.467506050153744334085516289728134), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 18440.75118859447173303252421991479005424), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 64.62515887799460295677071749181651317052), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.201851568864688406206528472883512147547), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.0005565091674187978029138500039504078098143), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.1338097668312907986354698683493366559613e-5), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.276308225077464312820179030238305271638e-8), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.4801582970473168520375942100071070575043e-11), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.6829184144212920949740376186058541800175e-14), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.7634080076358511276617829524639455399182e-17), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.6290035083727140966418512608156646142409e-20), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.339652245667538733044036638506893821352e-23), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.9017518064256388530773585529891677854909e-27) + }; + static const T Q[61] = { + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.1386831185456898357379390197203894063459e81), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.6467076379487574703291056110838151259438e81), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.1394967823848615838336194279565285465161e82), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.1872927317344192945218570366455046340458e82), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.1772461045338946243584650759986310355937e82), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.1267294892200258648315971144069595555118e82), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.7157764838362416821508872117623058626589e81), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.329447266909948668265277828268378274513e81), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.1264376077317689779509250183194342571207e81), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.4118230304191980787640446056583623228873e80), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.1154393529762694616405952270558316515261e80), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.281655612889423906125295485693696744275e79), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.6037483524928743102724159846414025482077e78), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.1145927995397835468123576831800276999614e78), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.1938624296151985600348534009382865995154e77), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.293980925856227626211879961219188406675e76), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.4015574518216966910319562902099567437832e75), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.4961475457509727343545565970423431880907e74), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.5565482348278933960215521991000378896338e73), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.5686112924615820754631098622770303094938e72), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.5305988545844796293285410303747469932856e71), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.4533363413802585060568537458067343491358e70), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.3553932059473516064068322757331575565718e69), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.2561198565218704414618802902533972354203e68), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.1699519313292900324098102065697454295572e67), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.1039830160862334505389615281373574959236e66), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.5873082967977428281000961954715372504986e64), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.3065255179030575882202133042549783442446e63), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.1479494813481364701208655943688307245459e62), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.6608150467921598615495180659808895663164e60), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.2732535313770902021791888953487787496976e59), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.1046402297662493314531194338414508049069e58), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.3711375077192882936085049147920021549622e56), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.1219154482883895482637944309702972234576e55), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.3708359374149458741391374452286837880162e53), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.1044095509971707189716913168889769471468e52), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.271951506225063286130946773813524945052e50), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.6548016291215163843464133978454065823866e48), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.1456062447610542135403751730809295219344e47), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.2986690175077969760978388356833006028929e45), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 5643149706574013350061247429006443326844000), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 98047545414467090421964387960743688053480), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 1563378767746846395507385099301468978550), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 22823360528584500077862274918382796495), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 304215527004115213046601295970388750), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 3690289075895685793844344966820325), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 40584512015702371433911456606050), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 402834190897282802772754873905), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 3589522158493606918146495750), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 28530557707503483723634725), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 200714561335055753000730), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 1237953783437761888641), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 6614698701445762950), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 30155495647727505), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 114953256021450), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 356398020013), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 863113950), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 1531345), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 1770), + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 1) + }; + static const T PD[60] = { + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.6365271516829242456324234577164675383137e81), + 2*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.2991038873096202943405966144203628966976e81), + 3*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.9211116495503170498076013367421231351115e80), + 4*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.2090792764676090716286400360584443891749e80), + 5*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.3730037777359591428226035156377978092809e79), + 6*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.5446396536956682043376492370432031543834e78), + 7*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.6692523966335177847425047827449069256345e77), + 8*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.7062543624100864681625612653756619116848e76), + 9*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.6499914905966283735005256964443226879158e75), + 10*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.5280364564853225211197557708655426736091e74), + 11*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.3823205608981176913075543599005095206953e73), + 12*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.2486733714214237704739129972671154532415e72), + 13*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.1462562139602039577983434547171318011675e71), + 14*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.7821169065036815012381267259559910324285e69), + 15*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.3820552182348155468636157988764435365078e68), + 16*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.1711618296983598244658239925535632505062e67), + 17*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.7056661618357643731419080738521475204245e65), + 18*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.2685246896473614017356264531791459936036e64), + 19*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.9455168125599643085283071944864977592391e62), + 20*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.3087541626972538362237309145177486236219e61), + 21*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.9367928873352980208052601301625005737407e59), + 22*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.2645306130689794942883818547314327466007e58), + 23*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.6961815141171454309161007351079576190079e56), + 24*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.1709637824471794552313802669803885946843e55), + 25*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.3921553258481531526663112728778759311158e53), + 26*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.8409006354449988687714450897575728228696e51), + 27*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.1686755204461325935742097669030363344927e50), + 28*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.3166653542877070999007425197729038754254e48), + 29*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.5566029092358215049069560272835654229637e46), + 30*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.9161766287916328133080586672953875116242e44), + 31*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 1412317772330871298317974693514430627922000), + 32*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 20387991986727877473732570146112459874790), + 33*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 275557928713904105182512535678580359839.3), + 34*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 3485719851040516559072031256589598330.723), + 35*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 41247046743564028399938106707656877.40859), + 36*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 456274078125709314602601667471879.0147312), + 37*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 4714450683242899367025707077155.310613012), + 38*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 45453933537925041680009544258.75073849996), + 39*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 408437900487067278846361972.302331241052), + 40*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 3415719344386166273085838.705771571751035), + 41*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 26541502879185876562320.93134691487351145), + 42*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 191261415065918713661.1571433274648417668), + 43*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 1275349770108718421.645275944284937551702), + 44*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 7849171120971773.318910987434906905704272), + 45*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 44455946386549.80866460312682983576538056), + 46*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 230920362395.3198137186361608905136598046), + 47*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 1095700096.240863858624279930600654130254), + 48*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 4727085.467506050153744334085516289728134), + 49*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 18440.75118859447173303252421991479005424), + 50*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 64.62515887799460295677071749181651317052), + 51*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.201851568864688406206528472883512147547), + 52*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.0005565091674187978029138500039504078098143), + 53*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.1338097668312907986354698683493366559613e-5), + 54*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.276308225077464312820179030238305271638e-8), + 55*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.4801582970473168520375942100071070575043e-11), + 56*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.6829184144212920949740376186058541800175e-14), + 57*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.7634080076358511276617829524639455399182e-17), + 58*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.6290035083727140966418512608156646142409e-20), + 59*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.339652245667538733044036638506893821352e-23), + 60*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.9017518064256388530773585529891677854909e-27) + }; + static const T QD[60] = { + BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.1386831185456898357379390197203894063459e81), + 2*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.6467076379487574703291056110838151259438e81), + 3*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.1394967823848615838336194279565285465161e82), + 4*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.1872927317344192945218570366455046340458e82), + 5*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.1772461045338946243584650759986310355937e82), + 6*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.1267294892200258648315971144069595555118e82), + 7*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.7157764838362416821508872117623058626589e81), + 8*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.329447266909948668265277828268378274513e81), + 9*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.1264376077317689779509250183194342571207e81), + 10*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.4118230304191980787640446056583623228873e80), + 11*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.1154393529762694616405952270558316515261e80), + 12*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.281655612889423906125295485693696744275e79), + 13*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.6037483524928743102724159846414025482077e78), + 14*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.1145927995397835468123576831800276999614e78), + 15*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.1938624296151985600348534009382865995154e77), + 16*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.293980925856227626211879961219188406675e76), + 17*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.4015574518216966910319562902099567437832e75), + 18*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.4961475457509727343545565970423431880907e74), + 19*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.5565482348278933960215521991000378896338e73), + 20*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.5686112924615820754631098622770303094938e72), + 21*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.5305988545844796293285410303747469932856e71), + 22*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.4533363413802585060568537458067343491358e70), + 23*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.3553932059473516064068322757331575565718e69), + 24*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.2561198565218704414618802902533972354203e68), + 25*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.1699519313292900324098102065697454295572e67), + 26*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.1039830160862334505389615281373574959236e66), + 27*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.5873082967977428281000961954715372504986e64), + 28*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.3065255179030575882202133042549783442446e63), + 29*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.1479494813481364701208655943688307245459e62), + 30*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.6608150467921598615495180659808895663164e60), + 31*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.2732535313770902021791888953487787496976e59), + 32*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.1046402297662493314531194338414508049069e58), + 33*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.3711375077192882936085049147920021549622e56), + 34*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.1219154482883895482637944309702972234576e55), + 35*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.3708359374149458741391374452286837880162e53), + 36*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.1044095509971707189716913168889769471468e52), + 37*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.271951506225063286130946773813524945052e50), + 38*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.6548016291215163843464133978454065823866e48), + 39*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.1456062447610542135403751730809295219344e47), + 40*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 0.2986690175077969760978388356833006028929e45), + 41*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 5643149706574013350061247429006443326844000), + 42*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 98047545414467090421964387960743688053480), + 43*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 1563378767746846395507385099301468978550), + 44*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 22823360528584500077862274918382796495), + 45*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 304215527004115213046601295970388750), + 46*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 3690289075895685793844344966820325), + 47*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 40584512015702371433911456606050), + 48*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 402834190897282802772754873905), + 49*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 3589522158493606918146495750), + 50*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 28530557707503483723634725), + 51*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 200714561335055753000730), + 52*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 1237953783437761888641), + 53*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 6614698701445762950), + 54*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 30155495647727505), + 55*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 114953256021450), + 56*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 356398020013), + 57*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 863113950), + 58*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 1531345), + 59*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 1770), + 60*BOOST_MATH_BIG_CONSTANT(T, boost::math::tools::numeric_traits::digits, 1) + }; + static const double g = 63.192152; + + T zgh = x + g - 0.5; + + T result = (x - 0.5) / zgh; + result += log(zgh); + result += tools::evaluate_polynomial(PD, x) / tools::evaluate_polynomial(P, x); + result -= tools::evaluate_polynomial(QD, x) / tools::evaluate_polynomial(Q, x); + result -= 1; + + return result; +} + +template +T big_digamma(T x) +{ + BOOST_MATH_STD_USING + + if(x < 0) + { + return big_digamma_helper(static_cast(1-x)) + constants::pi() / tan(constants::pi() * (1-x)); + } + return big_digamma_helper(x); +} + +}}} + +#endif // include guard diff --git a/libcxx/src/third-party/boost/math/bindings/detail/big_lanczos.hpp b/libcxx/src/third-party/boost/math/bindings/detail/big_lanczos.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/bindings/detail/big_lanczos.hpp @@ -0,0 +1,777 @@ +// (C) Copyright John Maddock 2006-8. +// 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_BIG_LANCZOS_HPP +#define BOOST_BIG_LANCZOS_HPP + +#include + +namespace boost{ namespace math{ namespace lanczos{ + +// +// Lanczos Coefficients for N=13 G=13.144565 +// Max experimental error (with arbitrary precision arithmetic) 9.2213e-23 +// Generated with compiler: Microsoft Visual C++ version 8.0 on Win32 at Mar 23 2006 +// +typedef lanczos13 lanczos13UDT; + +// +// Lanczos Coefficients for N=22 G=22.61891 +// Max experimental error (with arbitrary precision arithmetic) 2.9524e-38 +// Generated with compiler: Microsoft Visual C++ version 8.0 on Win32 at Mar 23 2006 +// +struct lanczos22UDT : public std::integral_constant +{ + // + // Produces slightly better than 128-bit long-double precision when + // evaluated at higher precision: + // + template + static T lanczos_sum(const T& z) + { + lanczos_initializer::force_instantiate(); // Ensure our constants get initialized before main() + static const T num[22] = { + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 46198410803245094237463011094.12173081986)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 43735859291852324413622037436.321513777)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 19716607234435171720534556386.97481377748)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 5629401471315018442177955161.245623932129)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 1142024910634417138386281569.245580222392)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 175048529315951173131586747.695329230778)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 21044290245653709191654675.41581372963167)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 2033001410561031998451380.335553678782601)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 160394318862140953773928.8736211601848891)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 10444944438396359705707.48957290388740896)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 565075825801617290121.1466393747967538948)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 25475874292116227538.99448534450411942597)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 957135055846602154.6720835535232270205725)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 29874506304047462.23662392445173880821515)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 769651310384737.2749087590725764959689181)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 16193289100889.15989633624378404096011797)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 273781151680.6807433264462376754578933261)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 3630485900.32917021712188739762161583295)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 36374352.05577334277856865691538582936484)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 258945.7742115532455441786924971194951043)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 1167.501919472435718934219997431551246996)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 2.50662827463100050241576528481104525333)) + }; + static const T denom[22] = { + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 0.0)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 2432902008176640000.0)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 8752948036761600000.0)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 13803759753640704000.0)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 12870931245150988800.0)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 8037811822645051776.0)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 3599979517947607200.0)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 1206647803780373360.0)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 311333643161390640.0)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 63030812099294896.0)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 10142299865511450.0)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 1307535010540395.0)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 135585182899530.0)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 11310276995381.0)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 756111184500.0)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 40171771630.0)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 1672280820.0)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 53327946.0)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 1256850.0)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 20615.0)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 210.0)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 1.0)) + }; + return boost::math::tools::evaluate_rational(num, denom, z); + } + + template + static T lanczos_sum_expG_scaled(const T& z) + { + lanczos_initializer::force_instantiate(); // Ensure our constants get initialized before main() + static const T num[22] = { + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 6939996264376682180.277485395074954356211)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 6570067992110214451.87201438870245659384)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 2961859037444440551.986724631496417064121)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 845657339772791245.3541226499766163431651)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 171556737035449095.2475716923888737881837)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 26296059072490867.7822441885603400926007)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 3161305619652108.433798300149816829198706)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 305400596026022.4774396904484542582526472)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 24094681058862.55120507202622377623528108)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 1569055604375.919477574824168939428328839)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 84886558909.02047889339710230696942513159)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 3827024985.166751989686050643579753162298)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 143782298.9273215199098728674282885500522)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 4487794.24541641841336786238909171265944)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 115618.2025760830513505888216285273541959)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 2432.580773108508276957461757328744780439)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 41.12782532742893597168530008461874360191)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 0.5453771709477689805460179187388702295792)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 0.005464211062612080347167337964166505282809)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 0.388992321263586767037090706042788910953e-4)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 0.1753839324538447655939518484052327068859e-6)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 0.3765495513732730583386223384116545391759e-9)) + }; + static const T denom[22] = { + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 0.0)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 2432902008176640000.0)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 8752948036761600000.0)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 13803759753640704000.0)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 12870931245150988800.0)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 8037811822645051776.0)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 3599979517947607200.0)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 1206647803780373360.0)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 311333643161390640.0)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 63030812099294896.0)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 10142299865511450.0)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 1307535010540395.0)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 135585182899530.0)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 11310276995381.0)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 756111184500.0)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 40171771630.0)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 1672280820.0)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 53327946.0)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 1256850.0)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 20615.0)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 210.0)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 1.0)) + }; + return boost::math::tools::evaluate_rational(num, denom, z); + } + + + template + static T lanczos_sum_near_1(const T& dz) + { + lanczos_initializer::force_instantiate(); // Ensure our constants get initialized before main() + static const T d[21] = { + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 8.318998691953337183034781139546384476554)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, -63.15415991415959158214140353299240638675)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 217.3108224383632868591462242669081540163)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, -448.5134281386108366899784093610397354889)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 619.2903759363285456927248474593012711346)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, -604.1630177420625418522025080080444177046)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 428.8166750424646119935047118287362193314)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, -224.6988753721310913866347429589434550302)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 87.32181627555510833499451817622786940961)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, -25.07866854821128965662498003029199058098)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 5.264398125689025351448861011657789005392)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, -0.792518936256495243383586076579921559914)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 0.08317448364744713773350272460937904691566)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, -0.005845345166274053157781068150827567998882)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 0.0002599412126352082483326238522490030412391)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, -0.6748102079670763884917431338234783496303e-5)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 0.908824383434109002762325095643458603605e-7)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, -0.5299325929309389890892469299969669579725e-9)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 0.994306085859549890267983602248532869362e-12)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, -0.3499893692975262747371544905820891835298e-15)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 0.7260746353663365145454867069182884694961e-20)), + }; + T result = 0; + for(unsigned k = 1; k <= sizeof(d)/sizeof(d[0]); ++k) + { + result += (-d[k-1]*dz)/(k*dz + k*k); + } + return result; + } + + template + static T lanczos_sum_near_2(const T& dz) + { + static const T d[21] = { + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 75.39272007105208086018421070699575462226)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, -572.3481967049935412452681346759966390319)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 1969.426202741555335078065370698955484358)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, -4064.74968778032030891520063865996757519)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 5612.452614138013929794736248384309574814)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, -5475.357667500026172903620177988213902339)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 3886.243614216111328329547926490398103492)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, -2036.382026072125407192448069428134470564)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 791.3727954936062108045551843636692287652)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, -227.2808432388436552794021219198885223122)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 47.70974355562144229897637024320739257284)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, -7.182373807798293545187073539819697141572)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 0.7537866989631514559601547530490976100468)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, -0.05297470142240154822658739758236594717787)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 0.00235577330936380542539812701472320434133)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, -0.6115613067659273118098229498679502138802e-4)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 0.8236417010170941915758315020695551724181e-6)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, -0.4802628430993048190311242611330072198089e-8)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 0.9011113376981524418952720279739624707342e-11)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, -0.3171854152689711198382455703658589996796e-14)), + static_cast(BOOST_MATH_BIG_CONSTANT(T, 120, 0.6580207998808093935798753964580596673177e-19)), + }; + T result = 0; + T z = dz + 2; + for(unsigned k = 1; k <= sizeof(d)/sizeof(d[0]); ++k) + { + result += (-d[k-1]*dz)/(z + k*z + k*k - 1); + } + return result; + } + + static double g(){ return 22.61890999999999962710717227309942245483; } +}; +// +// Lanczos Coefficients for N=31 G=32.08067 +// Max experimental error (with arbitrary precision arithmetic) 0.162e-52 +// Generated with compiler: Microsoft Visual C++ version 8.0 on Win32 at May 9 2006 +// +struct lanczos31UDT +{ + template + static T lanczos_sum(const T& z) + { + lanczos_initializer::force_instantiate(); // Ensure our constants get initialized before main() + static const T num[31] = { + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.2579646553333513328235723061836959833277e46)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.2444796504337453845497419271639377138264e46)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.1119885499016017172212179730662673475329e46)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.3301983829072723658949204487793889113715e45)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.7041171040503851585152895336505379417066e44)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.1156687509001223855125097826246939403504e44)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 1522559363393940883866575697565974893306000)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 164914363507650839510801418717701057005700)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 14978522943127593263654178827041568394060)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 1156707153701375383907746879648168666774)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 76739431129980851159755403434593664173.2)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 4407916278928188620282281495575981079.306)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 220487883931812802092792125175269667.3004)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 9644828280794966468052381443992828.433924)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 369996467042247229310044531282837.6549068)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 12468380890717344610932904378961.13494291)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 369289245210898235894444657859.0529720075)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 9607992460262594951559461829.34885209022)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 219225935074853412540086410.981421315799)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 4374309943598658046326340.720767382079549)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 76008779092264509404014.10530947173485581)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 1143503533822162444712.335663112617754987)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 14779233719977576920.37884890049671578409)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 162409028440678302.9992838032166348069916)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 1496561553388385.733407609544964535634135)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 11347624460661.81008311053190661436107043)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 68944915931.32004991941950530448472223832)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 322701221.6391432296123937035480931903651)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 1092364.213992634267819050120261755371294)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 2380.151399852411512711176940867823024864)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 2.506628274631000502415765284811045253007)), + }; + static const T denom[31] = { + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.8841761993739701954543616e31)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.3502799997985980526649278464e32)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.622621928420356134910574592e32)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 66951000306085302338993639424000)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 49361465831621147825759587123200)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 26751280755793398822580822142976)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 11139316913434780466101123891200)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 3674201658710345201899117607040)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 981347603630155088295475765440)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 215760462268683520394805979744)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 39539238727270799376544542000)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 6097272817323042122728617800)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 796974693974455191377937300)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 88776380550648116217781890)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 8459574446076318147830625)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 691254538651580660999025)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 48487623689430693038025)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 2918939500751087661105)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 150566737512021319125)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 6634460278534540725)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 248526574856284725)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 7860403394108265)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 207912996295875)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 4539323721075)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 80328850875)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 1122686019)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 11921175)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 90335)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 435)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 1)), + }; + return boost::math::tools::evaluate_rational(num, denom, z, 31); + } + + template + static T lanczos_sum_expG_scaled(const T& z) + { + lanczos_initializer::force_instantiate(); // Ensure our constants get initialized before main() + static const T num[31] = { + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 30137154810677525966583148469478.52374216)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 28561746428637727032849890123131.36314653)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 13083250730789213354063781611435.74046294)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 3857598154697777600846539129354.783647)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 822596651552555685068015316144.0952185852)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 135131964033213842052904200372.039133532)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 17787555889683709693655685146.19771358863)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 1926639793777927562221423874.149673297196)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 174989113988888477076973808.6991839697774)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 13513425905835560387095425.01158383184045)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 896521313378762433091075.1446749283094845)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 51496223433749515758124.71524415105430686)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 2575886794780078381228.37205955912263407)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 112677328855422964200.4155776009524490958)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 4322545967487943330.625233358130724324796)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 145663957202380774.0362027607207590519723)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 4314283729473470.686566233465428332496534)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 112246988185485.8877916434026906290603878)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 2561143864972.040563435178307062626388193)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 51103611767.9626550674442537989885239605)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 887985348.0369447209508500133077232094491)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 13359172.3954672607019822025834072685839)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 172660.8841147568768783928167105965064459)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 1897.370795407433013556725714874693719617)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 17.48383210090980598861217644749573257178)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.1325705316732132940835251054350153028901)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.0008054605783673449641889260501816356090452)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.377001130700104515644336869896819162464e-5)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.1276172868883867038813825443204454996531e-7)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.2780651912081116274907381023821492811093e-10)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.2928410648650955854121639682890739211234e-13)), + }; + static const T denom[31] = { + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.8841761993739701954543616e31)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.3502799997985980526649278464e32)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.622621928420356134910574592e32)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 66951000306085302338993639424000)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 49361465831621147825759587123200)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 26751280755793398822580822142976)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 11139316913434780466101123891200)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 3674201658710345201899117607040)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 981347603630155088295475765440)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 215760462268683520394805979744)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 39539238727270799376544542000)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 6097272817323042122728617800)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 796974693974455191377937300)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 88776380550648116217781890)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 8459574446076318147830625)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 691254538651580660999025)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 48487623689430693038025)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 2918939500751087661105)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 150566737512021319125)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 6634460278534540725)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 248526574856284725)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 7860403394108265)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 207912996295875)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 4539323721075)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 80328850875)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 1122686019)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 11921175)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 90335)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 435)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 1)), + }; + return boost::math::tools::evaluate_rational(num, denom, z, 31); + } + + + template + static T lanczos_sum_near_1(const T& dz) + { + lanczos_initializer::force_instantiate(); // Ensure our constants get initialized before main() + static const T d[30] = { + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 11.80038544942943603508206880307972596807)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -130.6355975335626214564236363322099481079)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 676.2177719145993049893392276809256538927)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -2174.724497783850503069990936574060452057)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 4869.877180638131076410069103742986502022)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -8065.744271864238179992762265472478229172)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 10245.03825618572106228191509520638651539)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -10212.83902362683215459850403668669647192)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 8110.289185383288952562767679576754140336)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -5179.310892558291062401828964000776095156)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 2673.987492589052370230989109591011091273)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -1118.342574651205183051884250033505609141)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 378.5812742511620662650096436471920295596)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -103.3725999812126067084828735543906768961)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 22.62913974335996321848099677797888917792)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -3.936414819950859548507275533569588041446)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.5376818198843817355682124535902641644854)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.0567827903603478957483409124122554243201)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.004545544993648879420352693271088478106482)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.0002689795568951033950042375135970897959935)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.1139493459006846530734617710847103572122e-4)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.3316581197839213921885210451302820192794e-6)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.6285613334898374028443777562554713906213e-8)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.7222145115734409070310317999856424167091e-10)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.4562976983547274766890241815002584238219e-12)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.1380593023819058919640038942493212141072e-14)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.1629663871586410129307496385264268190679e-17)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.5429994291916548849493889660077076739993e-21)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.2922682842441892106795386303084661338957e-25)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.8456967065309046044689041041336866118459e-31)), + }; + T result = 0; + for(unsigned k = 1; k <= sizeof(d)/sizeof(d[0]); ++k) + { + result += (-d[k-1]*dz)/(k*dz + k*k); + } + return result; + } + + template + static T lanczos_sum_near_2(const T& dz) + { + lanczos_initializer::force_instantiate(); // Ensure our constants get initialized before main() + static const T d[30] = { + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 147.9979641587472136175636384176549713358)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -1638.404318611773924210055619836375434296)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 8480.981744216135641122944743711911653273)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -27274.93942104458448200467097634494071176)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 61076.98019918759324489193232276937262854)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -101158.8762737154296509560513952101409264)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 128491.1252383947174824913796141607174379)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -128087.2892038336581928787480535905496026)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 101717.5492545853663296795562084430123258)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -64957.8330410311808907869707511362206858)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 33536.59139229792478811870738772305570317)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -14026.01847115365926835980820243003785821)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 4748.087094096186515212209389240715050212)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -1296.477510211815971152205100242259733245)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 283.8099337545793198947620951499958085157)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -49.36969067101255103452092297769364837753)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 6.743492833270653628580811118017061581404)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.7121578704864048548351804794951487823626)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.0570092738016915476694118877057948681298)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.003373485297696102660302960722607722438643)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.0001429128843527532859999752593761934089751)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.41595867130858508233493767243236888636e-5)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.7883284669307241040059778207492255409785e-7)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.905786322462384670803148223703187214379e-9)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.5722790216999820323272452464661250331451e-11)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.1731510870832349779315841757234562309727e-13)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.2043890314358438601429048378015983874378e-16)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.6810185176079344204740000170500311171065e-20)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.3665567641131713928114853776588342403919e-24)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.1060655106553177007425710511436497259484e-29)), + }; + T result = 0; + T z = dz + 2; + for(unsigned k = 1; k <= sizeof(d)/sizeof(d[0]); ++k) + { + result += (-d[k-1]*dz)/(z + k*z + k*k - 1); + } + return result; + } + + static double g(){ return 32.08066999999999779902282170951366424561; } +}; + +// +// Lanczos Coefficients for N=61 G=63.192152 +// Max experimental error (with 1000-bit precision arithmetic) 3.740e-113 +// Generated with compiler: Microsoft Visual C++ version 8.0 on Win32 at Mar 12 2006 +// +struct lanczos61UDT +{ + template + static T lanczos_sum(const T& z) + { + lanczos_initializer::force_instantiate(); // Ensure our constants get initialized before main() + using namespace boost; + static const T d[61] = { + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 2.50662827463100050241576528481104525300698674060993831662992357634229365460784197494659584)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 13349415823254323512107320481.3495396037261649201426994438803767191136434970492309775123879)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -300542621510568204264185787475.230003734889859348050696493467253861933279360152095861484548)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 3273919938390136737194044982676.40271056035622723775417608127544182097346526115858803376474)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -22989594065095806099337396006399.5874206181563663855129141706748733174902067950115092492439)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 116970582893952893160414263796102.542775878583510989850142808618916073286745084692189044738)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -459561969036479455224850813196807.283291532483532558959779434457349912822256480548436066098)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 1450959909778264914956547227964788.89797179379520834974601372820249784303794436366366810477)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -3782846865486775046285288437885921.41537699732805465141128848354901016102326190612528503251)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 8305043213936355459145388670886540.09976337905520168067329932809302445437208115570138102767)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -15580988484396722546934484726970745.4927787160273626078250810989811865283255762028143642311)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 25262722284076250779006793435537600.0822901485517345545978818780090308947301031347345640449)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -35714428027687018805443603728757116.5304655170478705341887572982734901197345415291580897698)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 44334726194692443174715432419157343.2294160783772787096321009453791271387235388689346602833)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -48599573547617297831555162417695106.187829304963846482633791012658974681648157963911491985)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 47258466493366798944386359199482189.0753349196625125615316002614813737880755896979754845101)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -40913448215392412059728312039233342.142914753896559359297977982314043378636755884088383226)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 31626312914486892948769164616982902.7262756989418188077611392594232674722318027323102462687)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -21878079174441332123064991795834438.4699982361692990285700077902601657354101259411789722708)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 13567268503974326527361474986354265.3136632133935430378937191911532112778452274286122946396)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -7551494211746723529747611556474669.62996644923557605747803028485900789337467673523741066527)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 3775516572689476384052312341432597.70584966904950490541958869730702790312581801585742038997)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -1696271471453637244930364711513292.79902955514107737992185368006225264329876265486853482449)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 684857608019352767999083000986166.20765273693720041519286231015176745354062413008561259139)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -248397566275708464679881624417990.410438107634139924805871051723444048539177890346227250473)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 80880368999557992138783568858556.1512378233079327986518410244522800950609595592170022878937)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -23618197945394013802495450485616.9025005749893350650829964098117490779655546610665927669729)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 6176884636893816103087134481332.06708966653493024119556843727320635285468825056891248447124)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -1444348683723439589948246285262.64080678953468490544615312565485170860503207005915261691108)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 301342031656979076702313946827.961658905182634508217626783081241074250132289461989777865387)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -55959656587719766738301589651.3940625826610668990368881615587469329021742236397809951765678)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 9223339169004064297247180402.36227016155682738556103138196079389248843082157924368301293963)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -1344882881571942601385730283.42710150182526891377514071881534880944872423492272147871101373)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 172841913316760599352601139.54409257740173055624405575900164401527761357324625574736896079)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -19496120443876233531343952.3802212016691702737346568192063937387825469602063310488794471653)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 1920907372583710284097959.44121420322495784420169085871802458519363819782779653621724219067)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -164429314798240461613359.399597503536657962383155875723527581699785846599051112719962464604)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 12154026644351189572525.1452249886865981747374191977801688548318519692423556934568426042152)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -770443988366210815096.519382051977221101156336663806705367929328924137169970381042234329058)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 41558909851418707920.4696085656889424895313728719601503526476333404973280596225722152966128)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -1890879946549708819.24562220042687554209318172044783707920086716716717574156283898330017796)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 71844996557297623.9583461685535340440524052492427928388171299145330229958643439878608673403)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -2253785109518255.55600197759875781765803818232939130127735487613049577235879610065545755637)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 57616883849355.997562563968344493719962252675875692642406455612671495250543228005045106721)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -1182495730353.08218118278997948852215670614084013289033222774171548915344541249351599628436)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 19148649358.6196967288062261380599423925174178776792840639099120170800869284300966978300613)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -239779605.891370259668403359614360511661030470269478602533200704639655585967442891496784613)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 2267583.00284368310957842936892685032434505866445291643236133553754152047677944820353796872)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -15749.490806784673108773558070497383604733010677027764233749920147549999361110299643477893)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 77.7059495149052727171505425584459982871343274332635726864135949842508025564999785370162956)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.261619987273930331397625130282851629108569607193781378836014468617185550622160348688297247)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.000572252321659691600529444769356185993188551770817110673186068921175991328434642504616377475)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.765167220661540041663007112207436426423746402583423562585653954743978584117929356523307954e-6)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.579179571056209077507916813937971472839851499147582627425979879366849876944438724610663401e-9)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.224804733043915149719206760378355636826808754704148660354494460792713189958510735070096991e-12)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.392711975389579343321746945135488409914483448652884894759297584020979857734289645857714768e-16)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.258603588346412049542768766878162221817684639789901440429511261589010049357907537684380983e-20)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.499992460848751668441190360024540741752242879565548017176883304716370989218399797418478685e-25)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.196211614533318174187346267877390498735734213905206562766348625767919122511096089367364025e-30)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.874722648949676363732094858062907290148733370978226751462386623191111439121706262759209573e-37)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.163907874717737848669759890242660846846105433791283903651924563157080252845636658802930428e-44)), + }; + T result = d[0]; + for(unsigned k = 1; k < sizeof(d)/sizeof(d[0]); ++k) + { + result += d[k]/(z+(k-1)); + } + return result; + } + + template + static T lanczos_sum_expG_scaled(const T& z) + { + lanczos_initializer::force_instantiate(); // Ensure our constants get initialized before main() + using namespace boost; + static const T d[61] = { + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.901751806425638853077358552989167785490911341809902155556127108480303870921448984935411583e-27)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 4.80241125306810017699523302110401965428995345115391817406006361151407344955277298373661032)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -108.119283021710869401330097315436214587270846871451487282117128515476478251641970487922552)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 1177.78262074811362219818923738088833932279000985161077740440010901595132448469513438139561)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -8270.43570321334374279057432173814835581983913167617217749736484999327758232081395983082867)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 42079.807161997077661752306902088979258826568702655699995911391774839958572703348502730394)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -165326.003834443330215001219988296482004968548294447320869281647211603153902436231468280089)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 521978.361504895300685499370463597042533432134369277742485307843747923127933979566742421213)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -1360867.51629992863544553419296636395576666570468519805449755596254912681418267100657262281)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 2987713.73338656161102517003716335104823650191612448011720936412226357385029800040631754755)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -5605212.64915921452169919008770165304171481697939254152852673009005154549681704553438450709)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 9088186.58332916818449459635132673652700922052988327069535513580836143146727832380184335474)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -12848155.5543636394746355365819800465364996596310467415907815393346205151090486190421959769)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 15949281.2867656960575878805158849857756293807220033618942867694361569866468996967761600898)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -17483546.9948295433308250581770557182576171673272450149400973735206019559576269174369907171)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 17001087.8599749419660906448951424280111036786456594738278573653160553115681287326064596964)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -14718487.0643665950346574802384331125115747311674609017568623694516187494204567579595827859)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 11377468.7255609717716845971105161298889777425898291183866813269222281486121330837791392732)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -7870571.64253038587947746661946939286858490057774448573157856145556080330153403858747655263)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 4880783.08440908743641723492059912671377140680710345996273343885045364205895751515063844239)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -2716626.7992639625103140035635916455652302249897918893040695025407382316653674141983775542)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 1358230.46602865696544327299659410214201327791319846880787515156343361311278133805428800255)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -610228.440751458395860905749312275043435828322076830117123636938979942213530882048883969802)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 246375.416501158654327780901087115642493055617468601787093268312234390446439555559050129729)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -89360.2599028475206119333931211015869139511677735549267100272095432140508089207221096740632)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 29096.4637987498328341260960356772198979319790332957125131055960448759586930781530063775634)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -8496.57401431514433694413130585404918350686834939156759654375188338156288564260152505382438)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 2222.11523574301594407443285016240908726891841242444092960094015874546135316534057865883047)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -519.599993280949289705514822058693289933461756514489674453254304308040888101533569480646682)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 108.406868361306987817730701109400305482972790224573776407166683184990131682003417239181112)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -20.1313142142558596796857948064047373605439974799116521459977609253211918146595346493447238)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 3.31806787671783168020012913552384112429614503798293169239082032849759155847394955909684383)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.483817477111537877685595212919784447924875428848331771524426361483392903320495411973587861)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.0621793463102927384924303843912913542297042029136293808338022462765755471002366206711862637)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.00701366932085103924241526535768453911099671087892444015581511551813219720807206445462785293)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.000691040514756294308758606917671220770856269030526647010461217455799229645004351524024364997)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.591529398871361458428147660822525365922497109038495896497692806150033516658042357799869656e-4)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.437237367535177689875119370170434437030440227275583289093139147244747901678407875809020739e-5)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.277164853397051135996651958345647824709602266382721185838782221179129726200661453504250697e-6)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.149506899012035980148891401548317536032574502641368034781671941165064546410613201579653674e-7)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.68023824066463262779882895193964639544061678698791279217407325790147925675797085217462974e-9)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.258460163734186329938721529982859244969655253624066115559707985878606277800329299821882688e-10)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.810792256024669306744649981276512583535251727474303382740940985102669076169168931092026491e-12)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.207274966207031327521921078048021807442500113231320959236850963529304158700096495799022922e-13)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.425399199286327802950259994834798737777721414442095221716122926637623478450472871269742436e-15)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.688866766744198529064607574117697940084548375790020728788313274612845280173338912495478431e-17)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.862599751805643281578607291655858333628582704771553874199104377131082877406179933909898885e-19)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.815756005678735657200275584442908437977926312650210429668619446123450972547018343768177988e-21)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.566583084099007858124915716926967268295318152203932871370429534546567151650626184750291695e-23)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.279544761599725082805446124351997692260093135930731230328454667675190245860598623539891708e-25)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.941169851584987983984201821679114408126982142904386301937192011680047611188837432096199601e-28)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.205866011331040736302780507155525142187875191518455173304638008169488993406425201915370746e-30)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.27526655245712584371295491216289353976964567057707464008951584303679019796521332324352501e-33)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.208358067979444305082929004102609366169534624348056112144990933897581971394396210379638792e-36)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.808728107661779323263133007119729988596844663194254976820030366188579170595441991680169012e-40)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.141276924383478964519776436955079978012672985961918248012931336621229652792338950573694356e-43)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.930318449287651389310440021745842417218125582685428432576258687100661462527604238849332053e-48)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.179870748819321661641184169834635133045197146966203370650788171790610563029431722308057539e-52)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.705865243912790337263229413370018392321238639017433365017168104310561824133229343750737083e-58)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.3146787805734405996448268100558028857930560442377698646099945108125281507396722995748398e-64)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.589653534231618730406843260601322236697428143603814281282790370329151249078338470962782338e-72)), + }; + T result = d[0]; + for(unsigned k = 1; k < sizeof(d)/sizeof(d[0]); ++k) + { + result += d[k]/(z+(k-1)); + } + return result; + } + + template + static T lanczos_sum_near_1(const T& dz) + { + lanczos_initializer::force_instantiate(); // Ensure our constants get initialized before main() + using namespace boost; + static const T d[60] = { + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 23.2463658527729692390378860713647146932236940604550445351214987229819352880524561852919518)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -523.358012551815715084547614110229469295755088686612838322817729744722233637819564673967396)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 5701.12892340421080714956066268650092612647620400476183901625272640935853188559347587495571)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -40033.5506451901904954336453419007623117537868026994808919201793803506999271787018654246699)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 203689.884259074923009439144410340256983393397995558814367995938668111650624499963153485034)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -800270.648969745331278757692597096167418585957703057412758177038340791380011708874081291202)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 2526668.23380061659863999395867315313385499515711742092815402701950519696944982260718031476)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -6587362.57559198722630391278043503867973853468105110382293763174847657538179665571836023631)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 14462211.3454541602975917764900442754186801975533106565506542322063393991552960595701762805)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -27132375.1879227404375395522940895789625516798992585980380939378508607160857820002128106898)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 43991923.8735251977856804364757478459275087361742168436524951824945035673768875988985478116)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -62192284.0030124679010201921841372967696262036115679150017649233887633598058364494608060812)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 77203473.0770033513405070667417251568915937590689150831268228886281254637715669678358204991)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -84630180.2217173903516348977915150565994784278120192219937728967986198118628659866582594874)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 82294807.2253549409847505891112074804416229757832871133388349982640444405470371147991706317)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -71245738.2484649177928765605893043553453557808557887270209768163561363857395639001251515788)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 55073334.3180266913441333534260714059077572215147571872597651029894142803987981342430068594)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -38097984.1648990787690036742690550656061009857688125101191167768314179751258568264424911474)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 23625729.5032184580395130592017474282828236643586203914515183078852982915252442161768527976)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -13149998.4348054726172055622442157883429575511528431835657668083088902165366619827169829685)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 6574597.77221556423683199818131482663205682902023554728024972161230111356285973623550338976)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -2953848.1483469149918109110050192571921018042012905892107136410603990336401921230407043408)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 1192595.29584357246380113611351829515963605337523874715861849584306265512819543347806085356)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -432553.812019608638388918135375154289816441900572658692369491476137741687213006403648722272)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 140843.215385933866391177743292449477205328233960902455943995092958295858485718885800427129)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -41128.186992679630058614841985110676526199977321524879849001760603476646382839182691529968)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 10756.2849191854701631989789887757784944313743544315113894758328432005767448056040879337769)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -2515.15559672041299884426826962296210458052543246529646213159169885444118227871246315458787)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 524.750087004805200600237632074908875763734578390662349666321453103782638818305404274166951)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -97.4468596421732493988298219295878130651986131393383646674144877163795143930682205035917965)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 16.0613108128210806736384551896802799172445298357754547684100294231532127326987175444453058)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -2.34194813526540240672426202485306862230641838409943369059203455578340880900483887447559874)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.300982934748016059399829007219431333744032924923669397318820178988611410275964499475465815)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.033950095985367909789000959795708551814461844488183964432565731809399824963680858993718525)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.00334502394288921146242772614150438404658527112198421937945605441697314216921393987758378122)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.000286333429067523984607730553301991502191011265745476190940771685897687956262049750683013485)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.211647426149364947402896718485536530479491688838087899435991994237067890628274492042231115e-4)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.134163345121302758109675190598169832775248626443483098532368562186356128620805552609175683e-5)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.723697303042715085329782938306424498336642078597508935450663080894255773653328980495047891e-7)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.329273487343139063533251321553223583999676337945788660475231347828772272134656322947906888e-8)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.12510922551028971731767784013117088894558604838820475961392154031378891971216135267744134e-9)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.392468958215589939603666430583400537413757786057185505426804034745840192914621891690369903e-11)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.100332717101049934370760667782927946803279422001380028508200697081188326364078428184546051e-12)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.205917088291197705194762747639836655808855850989058813560983717575008725393428497910009756e-14)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.333450178247893143608439314203175490705783992567107481617660357577257627854979230819461489e-16)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.417546693906616047110563550428133589051498362676394888715581845170969319500638944065594319e-18)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.394871691642184410859178529844325390739857256666676534513661579365702353214518478078730801e-20)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.274258012587811199757875927548699264063511843669070634471054184977334027224611843434000922e-22)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.135315354265459854889496635967343027244391821142592599244505313738163473730636430399785048e-24)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.455579032003288910408487905303223613382276173706542364543918076752861628464036586507967767e-27)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.99650703862462739161520123768147312466695159780582506041370833824093136783202694548427718e-30)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.1332444609228706921659395801935919548447859029572115502899861345555006827214220195650058e-32)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.100856999148765307000182397631280249632761913433008379786888200467467364474581430670889392e-35)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.39146979455613683472384690509165395074425354524713697428673406058157887065953366609738731e-39)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.683859606707931248105140296850112494069265272540298100341919970496564103098283709868586478e-43)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.450326344248604222735147147805963966503893913752040066400766411031387063854141246972061792e-47)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.870675378039492904184581895322153006461319724931909799151743284769901586333730037761678891e-52)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.341678395249272265744518787745356400350877656459401143889000625280131819505857966769964401e-57)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.152322191370871666358069530949353871960316638394428595988162174042653299702098929238880862e-63)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.285425405297633795767452984791738825078111150078605004958179057245980222485147999495352632e-71)), + }; + T result = 0; + for(unsigned k = 1; k <= sizeof(d)/sizeof(d[0]); ++k) + { + result += (-d[k-1]*dz)/(k*dz + k*k); + } + return result; + } + + template + static T lanczos_sum_near_2(const T& dz) + { + lanczos_initializer::force_instantiate(); // Ensure our constants get initialized before main() + using namespace boost; + static const T d[60] = { + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 557.56438192770795764344217888434355281097193198928944200046501607026919782564033547346298)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -12552.748616427645475141433405567201788681683808077269330800392600825597799119572762385222)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 136741.650054039199076788077149441364242294724343897779563222338447737802381279007988884806)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -960205.223613240309942047656967301131022760634321049075674684679438471862998829007639437133)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 4885504.47588736223774859617054275229642041717942140469884121916073195308537421162982679289)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -19194501.738192166918904824982935279260356575935661514109550613809352009246483412530545583)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 60602169.8633537742937457094837494059849674261357199218329545854990149896822944801504450843)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -157997975.522506767297528502540724511908584668874487506510120462561270100749019845014382885)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 346876323.86092543685419723290495817330608574729543216092477261152247521712190505658568876)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -650770365.471136883718747607976242475416651908858429752332176373467422603953536408709972919)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 1055146856.05909309330903130910708372830487315684258450293308627289334336871273080305128138)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -1491682726.25614447429071368736790697283307005456720192465860871846879804207692411263924608)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 1851726287.94866167094858600116562210167031458934987154557042242638980748286188183300900268)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -2029855953.68334371445800569238095379629407314338521720558391277508374519526853827142679839)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 1973842002.53354868177824629525448788555435194808657489238517523691040148611221295436287925)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -1708829941.98209573247426625323314413060108441455314880934710595647408841619484540679859098)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 1320934627.12433688699625456833930317624783222321555050330381730035733198249283009357314954)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -913780636.858542526294419197161614811332299249415125108737474024007693329922089123296358727)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 566663423.929632170286007468016419798879660054391183200464733820209439185545886930103546787)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -315402880.436816230388857961460509181823167373029384218959199936902955049832392362044305869)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 157691811.550465734461741500275930418786875005567018699867961482249002625886064187146134966)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -70848085.5705405970640618473551954585013808128304384354476488268600720054598122945113512731)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 28604413.4050137708444142264980840059788755325900041515286382001704951527733220637586013815)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -10374808.7067303054787164054055989420809074792801592763124972441820101840292558840131568633)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 3378126.32016207486657791623723515804931231041318964254116390764473281291389374196880720069)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -986460.090390653140964189383080344920103075349535669020623874668558777188889544398718979744)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 257989.631187387317948158483575125380011593209850756066176921901006833159795100137743395985)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -60326.0391159227288325790327830741260824763549807922845004854215660451399733578621565837087)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 12586.1375399649496159880821645216260841794563919652590583420570326276086323953958907053394)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -2337.26417330316922535871922886167444795452055677161063205953141105726549966801856628447293)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 385.230745012608736644117458716226876976056390433401632749144285378123105481506733917763829)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -56.1716559403731491675970177460841997333796694857076749852739159067307309470690838101179615)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 7.21907953468550196348585224042498727840087634483369357697580053424523903859773769748599575)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.814293485887386870805786409956942772883474224091975496298369877683530509729332902182019049)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.0802304419995150047616460464220884371214157889148846405799324851793571580868840034085001373)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.00686771095380619535195996193943858680694970000948742557733102777115482017857981277171196115)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.000507636621977556438232617777542864427109623356049335590894564220687567763620803789858345916)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.32179095465362720747836116655088181481893063531138957363431280817392443948706754917605911e-4)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.173578890579848508947329833426585354230744194615295570820295052665075101971588563893718407e-5)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.789762880006288893888161070734302768702358633525134582027140158619195373770299678322596835e-7)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.300074637200885066788470310738617992259402710843493097610337134266720909870967550606601658e-8)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.941337297619721713151110244242536308266701344868601679868536153775533330272973088246835359e-10)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.24064815013182536657310186836079333949814111498828401548170442715552017773994482539471456e-11)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.493892399304811910466345686492277504628763169549384435563232052965821874553923373100791477e-13)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.799780678476644196901221989475355609743387528732994566453160178199295104357319723742820593e-15)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.100148627870893347527249092785257443532967736956154251497569191947184705954310833302770086e-16)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.947100256812658897084619699699028861352615460106539259289295071616221848196411749449858071e-19)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.657808193528898116367845405906343884364280888644748907819280236995018351085371701094007759e-21)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.324554050057463845012469010247790763753999056976705084126950591088538742509983426730851614e-23)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.10927068902162908990029309141242256163212535730975970310918370355165185052827948996110107e-25)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.239012340507870646690121104637467232366271566488184795459093215303237974655782634371712486e-28)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.31958700972990573259359660326375143524864710953063781494908314884519046349402409667329667e-31)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.241905641292988284384362036555782113275737930713192053073501265726048089991747342247551645e-34)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.93894080230619233745797029179332447129464915420290457418429337322820997038069119047864035e-38)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.164023814025085488413251990798690797467351995518990067783355251949198292596815470576539877e-41)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.108010831192689925518484618970761942019888832176355541674171850211917230280206410356465451e-45)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.208831600642796805563854019033577205240227465154130766898180386564934443551840379116390645e-50)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.819516067465171848863933747691434138146789031214932473898084756489529673230665363014007306e-56)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.365344970579318347488211604761724311582675708113250505307342682118101409913523622073678179e-62)), + static_cast(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.684593199208628857931267904308244537968349564351534581234005234847904343404822808648361291e-70)), + }; + T result = 0; + T z = dz + 2; + for(unsigned k = 1; k <= sizeof(d)/sizeof(d[0]); ++k) + { + result += (-d[k-1]*dz)/(z + k*z + k*k - 1); + } + return result; + } + + static double g(){ return 63.19215200000000010049916454590857028961181640625; } +}; + +}}} // namespaces + +#endif + + diff --git a/libcxx/src/third-party/boost/math/bindings/mpfr.hpp b/libcxx/src/third-party/boost/math/bindings/mpfr.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/bindings/mpfr.hpp @@ -0,0 +1,974 @@ +// Copyright John Maddock 2008. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Wrapper that works with mpfr_class defined in gmpfrxx.h +// See http://math.berkeley.edu/~wilken/code/gmpfrxx/ +// Also requires the gmp and mpfr libraries. +// + +#ifndef BOOST_MATH_MPLFR_BINDINGS_HPP +#define BOOST_MATH_MPLFR_BINDINGS_HPP + +#include + +#ifdef _MSC_VER +// +// We get a lot of warnings from the gmp, mpfr and gmpfrxx headers, +// disable them here, so we only see warnings from *our* code: +// +#pragma warning(push) +#pragma warning(disable: 4127 4800 4512) +#endif + +#include + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +inline mpfr_class fabs(const mpfr_class& v) +{ + return abs(v); +} +template +inline mpfr_class fabs(const __gmp_expr& v) +{ + return abs(static_cast(v)); +} + +inline mpfr_class pow(const mpfr_class& b, const mpfr_class& e) +{ + mpfr_class result; + mpfr_pow(result.__get_mp(), b.__get_mp(), e.__get_mp(), GMP_RNDN); + return result; +} +/* +template +inline mpfr_class pow(const __gmp_expr& b, const __gmp_expr& e) +{ + return pow(static_cast(b), static_cast(e)); +} +*/ +inline mpfr_class ldexp(const mpfr_class& v, int e) +{ + //int e = mpfr_get_exp(*v.__get_mp()); + mpfr_class result(v); + mpfr_set_exp(result.__get_mp(), e); + return result; +} +template +inline mpfr_class ldexp(const __gmp_expr& v, int e) +{ + return ldexp(static_cast(v), e); +} + +inline mpfr_class frexp(const mpfr_class& v, int* expon) +{ + int e = mpfr_get_exp(v.__get_mp()); + mpfr_class result(v); + mpfr_set_exp(result.__get_mp(), 0); + *expon = e; + return result; +} +template +inline mpfr_class frexp(const __gmp_expr& v, int* expon) +{ + return frexp(static_cast(v), expon); +} + +inline mpfr_class fmod(const mpfr_class& v1, const mpfr_class& v2) +{ + mpfr_class n; + if(v1 < 0) + n = ceil(v1 / v2); + else + n = floor(v1 / v2); + return v1 - n * v2; +} +template +inline mpfr_class fmod(const __gmp_expr& v1, const __gmp_expr& v2) +{ + return fmod(static_cast(v1), static_cast(v2)); +} + +template +inline mpfr_class modf(const mpfr_class& v, long long* ipart, const Policy& pol) +{ + *ipart = lltrunc(v, pol); + return v - boost::math::tools::real_cast(*ipart); +} +template +inline mpfr_class modf(const __gmp_expr& v, long long* ipart, const Policy& pol) +{ + return modf(static_cast(v), ipart, pol); +} + +template +inline int iround(mpfr_class const& x, const Policy&) +{ + return boost::math::tools::real_cast(boost::math::round(x, typename boost::math::policies::normalise >::type())); +} +template +inline int iround(__gmp_expr const& x, const Policy& pol) +{ + return iround(static_cast(x), pol); +} + +template +inline long lround(mpfr_class const& x, const Policy&) +{ + return boost::math::tools::real_cast(boost::math::round(x, typename boost::math::policies::normalise >::type())); +} +template +inline long lround(__gmp_expr const& x, const Policy& pol) +{ + return lround(static_cast(x), pol); +} + +template +inline long long llround(mpfr_class const& x, const Policy&) +{ + return boost::math::tools::real_cast(boost::math::round(x, typename boost::math::policies::normalise >::type())); +} +template +inline long long llround(__gmp_expr const& x, const Policy& pol) +{ + return llround(static_cast(x), pol); +} + +template +inline int itrunc(mpfr_class const& x, const Policy&) +{ + return boost::math::tools::real_cast(boost::math::trunc(x, typename boost::math::policies::normalise >::type())); +} +template +inline int itrunc(__gmp_expr const& x, const Policy& pol) +{ + return itrunc(static_cast(x), pol); +} + +template +inline long ltrunc(mpfr_class const& x, const Policy&) +{ + return boost::math::tools::real_cast(boost::math::trunc(x, typename boost::math::policies::normalise >::type())); +} +template +inline long ltrunc(__gmp_expr const& x, const Policy& pol) +{ + return ltrunc(static_cast(x), pol); +} + +template +inline long long lltrunc(mpfr_class const& x, const Policy&) +{ + return boost::math::tools::real_cast(boost::math::trunc(x, typename boost::math::policies::normalise >::type())); +} +template +inline long long lltrunc(__gmp_expr const& x, const Policy& pol) +{ + return lltrunc(static_cast(x), pol); +} + +namespace boost{ + +#ifdef BOOST_MATH_USE_FLOAT128 + template<> struct std::is_convertible : public std::integral_constant{}; +#endif + template<> struct std::is_convertible : public std::integral_constant{}; + +namespace math{ + +#if defined(__GNUC__) && (__GNUC__ < 4) + using ::iround; + using ::lround; + using ::llround; + using ::itrunc; + using ::ltrunc; + using ::lltrunc; + using ::modf; +#endif + +namespace lanczos{ + +struct mpfr_lanczos +{ + static mpfr_class lanczos_sum(const mpfr_class& z) + { + unsigned long p = z.get_dprec(); + if(p <= 72) + return lanczos13UDT::lanczos_sum(z); + else if(p <= 120) + return lanczos22UDT::lanczos_sum(z); + else if(p <= 170) + return lanczos31UDT::lanczos_sum(z); + else //if(p <= 370) approx 100 digit precision: + return lanczos61UDT::lanczos_sum(z); + } + static mpfr_class lanczos_sum_expG_scaled(const mpfr_class& z) + { + unsigned long p = z.get_dprec(); + if(p <= 72) + return lanczos13UDT::lanczos_sum_expG_scaled(z); + else if(p <= 120) + return lanczos22UDT::lanczos_sum_expG_scaled(z); + else if(p <= 170) + return lanczos31UDT::lanczos_sum_expG_scaled(z); + else //if(p <= 370) approx 100 digit precision: + return lanczos61UDT::lanczos_sum_expG_scaled(z); + } + static mpfr_class lanczos_sum_near_1(const mpfr_class& z) + { + unsigned long p = z.get_dprec(); + if(p <= 72) + return lanczos13UDT::lanczos_sum_near_1(z); + else if(p <= 120) + return lanczos22UDT::lanczos_sum_near_1(z); + else if(p <= 170) + return lanczos31UDT::lanczos_sum_near_1(z); + else //if(p <= 370) approx 100 digit precision: + return lanczos61UDT::lanczos_sum_near_1(z); + } + static mpfr_class lanczos_sum_near_2(const mpfr_class& z) + { + unsigned long p = z.get_dprec(); + if(p <= 72) + return lanczos13UDT::lanczos_sum_near_2(z); + else if(p <= 120) + return lanczos22UDT::lanczos_sum_near_2(z); + else if(p <= 170) + return lanczos31UDT::lanczos_sum_near_2(z); + else //if(p <= 370) approx 100 digit precision: + return lanczos61UDT::lanczos_sum_near_2(z); + } + static mpfr_class g() + { + unsigned long p = mpfr_class::get_dprec(); + if(p <= 72) + return lanczos13UDT::g(); + else if(p <= 120) + return lanczos22UDT::g(); + else if(p <= 170) + return lanczos31UDT::g(); + else //if(p <= 370) approx 100 digit precision: + return lanczos61UDT::g(); + } +}; + +template +struct lanczos +{ + typedef mpfr_lanczos type; +}; + +} // namespace lanczos + +namespace constants{ + +template +struct construction_traits; + +template +struct construction_traits +{ + typedef std::integral_constant type; +}; + +} + +namespace tools +{ + +template +struct promote_arg<__gmp_expr > +{ // If T is integral type, then promote to double. + typedef mpfr_class type; +}; + +template<> +inline int digits(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpfr_class)) noexcept +{ + return mpfr_class::get_dprec(); +} + +namespace detail{ + +template +void convert_to_long_result(mpfr_class const& r, I& result) +{ + result = 0; + I last_result(0); + mpfr_class t(r); + double term; + do + { + term = real_cast(t); + last_result = result; + result += static_cast(term); + t -= term; + }while(result != last_result); +} + +} + +template <> +inline mpfr_class real_cast(long long t) +{ + mpfr_class result; + int expon = 0; + int sign = 1; + if(t < 0) + { + sign = -1; + t = -t; + } + while(t) + { + result += ldexp(static_cast(t & 0xffffL), expon); + expon += 32; + t >>= 32; + } + return result * sign; +} +template <> +inline unsigned real_cast(mpfr_class t) +{ + return t.get_ui(); +} +template <> +inline int real_cast(mpfr_class t) +{ + return t.get_si(); +} +template <> +inline double real_cast(mpfr_class t) +{ + return t.get_d(); +} +template <> +inline float real_cast(mpfr_class t) +{ + return static_cast(t.get_d()); +} +template <> +inline long real_cast(mpfr_class t) +{ + long result; + detail::convert_to_long_result(t, result); + return result; +} +template <> +inline long long real_cast(mpfr_class t) +{ + long long result; + detail::convert_to_long_result(t, result); + return result; +} + +template <> +inline mpfr_class max_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpfr_class)) +{ + static bool has_init = false; + static mpfr_class val; + if(!has_init) + { + val = 0.5; + mpfr_set_exp(val.__get_mp(), mpfr_get_emax()); + has_init = true; + } + return val; +} + +template <> +inline mpfr_class min_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpfr_class)) +{ + static bool has_init = false; + static mpfr_class val; + if(!has_init) + { + val = 0.5; + mpfr_set_exp(val.__get_mp(), mpfr_get_emin()); + has_init = true; + } + return val; +} + +template <> +inline mpfr_class log_max_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpfr_class)) +{ + static bool has_init = false; + static mpfr_class val = max_value(); + if(!has_init) + { + val = log(val); + has_init = true; + } + return val; +} + +template <> +inline mpfr_class log_min_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpfr_class)) +{ + static bool has_init = false; + static mpfr_class val = max_value(); + if(!has_init) + { + val = log(val); + has_init = true; + } + return val; +} + +template <> +inline mpfr_class epsilon(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpfr_class)) +{ + return ldexp(mpfr_class(1), 1-boost::math::policies::digits >()); +} + +} // namespace tools + +namespace policies{ + +template +struct evaluation<__gmp_expr, Policy> +{ + typedef mpfr_class type; +}; + +} + +template +inline mpfr_class skewness(const extreme_value_distribution& /*dist*/) +{ + // + // This is 12 * sqrt(6) * zeta(3) / pi^3: + // See http://mathworld.wolfram.com/ExtremeValueDistribution.html + // + #ifdef BOOST_MATH_STANDALONE + static_assert(sizeof(Policy) == 0, "mpfr skewness can not be calculated in standalone mode"); + #endif + + return static_cast("1.1395470994046486574927930193898461120875997958366"); +} + +template +inline mpfr_class skewness(const rayleigh_distribution& /*dist*/) +{ + // using namespace boost::math::constants; + #ifdef BOOST_MATH_STANDALONE + static_assert(sizeof(Policy) == 0, "mpfr skewness can not be calculated in standalone mode"); + #endif + + return static_cast("0.63111065781893713819189935154422777984404221106391"); + // Computed using NTL at 150 bit, about 50 decimal digits. + // return 2 * root_pi() * pi_minus_three() / pow23_four_minus_pi(); +} + +template +inline mpfr_class kurtosis(const rayleigh_distribution& /*dist*/) +{ + // using namespace boost::math::constants; + #ifdef BOOST_MATH_STANDALONE + static_assert(sizeof(Policy) == 0, "mpfr kurtosis can not be calculated in standalone mode"); + #endif + + return static_cast("3.2450893006876380628486604106197544154170667057995"); + // Computed using NTL at 150 bit, about 50 decimal digits. + // return 3 - (6 * pi() * pi() - 24 * pi() + 16) / + // (four_minus_pi() * four_minus_pi()); +} + +template +inline mpfr_class kurtosis_excess(const rayleigh_distribution& /*dist*/) +{ + //using namespace boost::math::constants; + // Computed using NTL at 150 bit, about 50 decimal digits. + #ifdef BOOST_MATH_STANDALONE + static_assert(sizeof(Policy) == 0, "mpfr excess kurtosis can not be calculated in standalone mode"); + #endif + + return static_cast("0.2450893006876380628486604106197544154170667057995"); + // return -(6 * pi() * pi() - 24 * pi() + 16) / + // (four_minus_pi() * four_minus_pi()); +} // kurtosis + +namespace detail{ + +// +// Version of Digamma accurate to ~100 decimal digits. +// +template +mpfr_class digamma_imp(mpfr_class x, const std::integral_constant* , const Policy& pol) +{ + // + // This handles reflection of negative arguments, and all our + // empfr_classor handling, then forwards to the T-specific approximation. + // + BOOST_MATH_STD_USING // ADL of std functions. + + mpfr_class result = 0; + // + // Check for negative arguments and use reflection: + // + if(x < 0) + { + // Reflect: + x = 1 - x; + // Argument reduction for tan: + mpfr_class remainder = x - floor(x); + // Shift to negative if > 0.5: + if(remainder > 0.5) + { + remainder -= 1; + } + // + // check for evaluation at a negative pole: + // + if(remainder == 0) + { + return policies::raise_pole_error("boost::math::digamma<%1%>(%1%)", nullptr, (1-x), pol); + } + result = constants::pi() / tan(constants::pi() * remainder); + } + result += big_digamma(x); + return result; +} +// +// Specialisations of this function provides the initial +// starting guess for Halley iteration: +// +template +inline mpfr_class erf_inv_imp(const mpfr_class& p, const mpfr_class& q, const Policy&, const std::integral_constant*) +{ + BOOST_MATH_STD_USING // for ADL of std names. + + mpfr_class result = 0; + + if(p <= 0.5) + { + // + // Evaluate inverse erf using the rational approximation: + // + // x = p(p+10)(Y+R(p)) + // + // Where Y is a constant, and R(p) is optimised for a low + // absolute empfr_classor compared to |Y|. + // + // double: Max empfr_classor found: 2.001849e-18 + // long double: Max empfr_classor found: 1.017064e-20 + // Maximum Deviation Found (actual empfr_classor term at infinite precision) 8.030e-21 + // + static const float Y = 0.0891314744949340820313f; + static const mpfr_class P[] = { + -0.000508781949658280665617, + -0.00836874819741736770379, + 0.0334806625409744615033, + -0.0126926147662974029034, + -0.0365637971411762664006, + 0.0219878681111168899165, + 0.00822687874676915743155, + -0.00538772965071242932965 + }; + static const mpfr_class Q[] = { + 1, + -0.970005043303290640362, + -1.56574558234175846809, + 1.56221558398423026363, + 0.662328840472002992063, + -0.71228902341542847553, + -0.0527396382340099713954, + 0.0795283687341571680018, + -0.00233393759374190016776, + 0.000886216390456424707504 + }; + mpfr_class g = p * (p + 10); + mpfr_class r = tools::evaluate_polynomial(P, p) / tools::evaluate_polynomial(Q, p); + result = g * Y + g * r; + } + else if(q >= 0.25) + { + // + // Rational approximation for 0.5 > q >= 0.25 + // + // x = sqrt(-2*log(q)) / (Y + R(q)) + // + // Where Y is a constant, and R(q) is optimised for a low + // absolute empfr_classor compared to Y. + // + // double : Max empfr_classor found: 7.403372e-17 + // long double : Max empfr_classor found: 6.084616e-20 + // Maximum Deviation Found (empfr_classor term) 4.811e-20 + // + static const float Y = 2.249481201171875f; + static const mpfr_class P[] = { + -0.202433508355938759655, + 0.105264680699391713268, + 8.37050328343119927838, + 17.6447298408374015486, + -18.8510648058714251895, + -44.6382324441786960818, + 17.445385985570866523, + 21.1294655448340526258, + -3.67192254707729348546 + }; + static const mpfr_class Q[] = { + 1, + 6.24264124854247537712, + 3.9713437953343869095, + -28.6608180499800029974, + -20.1432634680485188801, + 48.5609213108739935468, + 10.8268667355460159008, + -22.6436933413139721736, + 1.72114765761200282724 + }; + mpfr_class g = sqrt(-2 * log(q)); + mpfr_class xs = q - 0.25; + mpfr_class r = tools::evaluate_polynomial(P, xs) / tools::evaluate_polynomial(Q, xs); + result = g / (Y + r); + } + else + { + // + // For q < 0.25 we have a series of rational approximations all + // of the general form: + // + // let: x = sqrt(-log(q)) + // + // Then the result is given by: + // + // x(Y+R(x-B)) + // + // where Y is a constant, B is the lowest value of x for which + // the approximation is valid, and R(x-B) is optimised for a low + // absolute empfr_classor compared to Y. + // + // Note that almost all code will really go through the first + // or maybe second approximation. After than we're dealing with very + // small input values indeed: 80 and 128 bit long double's go all the + // way down to ~ 1e-5000 so the "tail" is rather long... + // + mpfr_class x = sqrt(-log(q)); + if(x < 3) + { + // Max empfr_classor found: 1.089051e-20 + static const float Y = 0.807220458984375f; + static const mpfr_class P[] = { + -0.131102781679951906451, + -0.163794047193317060787, + 0.117030156341995252019, + 0.387079738972604337464, + 0.337785538912035898924, + 0.142869534408157156766, + 0.0290157910005329060432, + 0.00214558995388805277169, + -0.679465575181126350155e-6, + 0.285225331782217055858e-7, + -0.681149956853776992068e-9 + }; + static const mpfr_class Q[] = { + 1, + 3.46625407242567245975, + 5.38168345707006855425, + 4.77846592945843778382, + 2.59301921623620271374, + 0.848854343457902036425, + 0.152264338295331783612, + 0.01105924229346489121 + }; + mpfr_class xs = x - 1.125; + mpfr_class R = tools::evaluate_polynomial(P, xs) / tools::evaluate_polynomial(Q, xs); + result = Y * x + R * x; + } + else if(x < 6) + { + // Max empfr_classor found: 8.389174e-21 + static const float Y = 0.93995571136474609375f; + static const mpfr_class P[] = { + -0.0350353787183177984712, + -0.00222426529213447927281, + 0.0185573306514231072324, + 0.00950804701325919603619, + 0.00187123492819559223345, + 0.000157544617424960554631, + 0.460469890584317994083e-5, + -0.230404776911882601748e-9, + 0.266339227425782031962e-11 + }; + static const mpfr_class Q[] = { + 1, + 1.3653349817554063097, + 0.762059164553623404043, + 0.220091105764131249824, + 0.0341589143670947727934, + 0.00263861676657015992959, + 0.764675292302794483503e-4 + }; + mpfr_class xs = x - 3; + mpfr_class R = tools::evaluate_polynomial(P, xs) / tools::evaluate_polynomial(Q, xs); + result = Y * x + R * x; + } + else if(x < 18) + { + // Max empfr_classor found: 1.481312e-19 + static const float Y = 0.98362827301025390625f; + static const mpfr_class P[] = { + -0.0167431005076633737133, + -0.00112951438745580278863, + 0.00105628862152492910091, + 0.000209386317487588078668, + 0.149624783758342370182e-4, + 0.449696789927706453732e-6, + 0.462596163522878599135e-8, + -0.281128735628831791805e-13, + 0.99055709973310326855e-16 + }; + static const mpfr_class Q[] = { + 1, + 0.591429344886417493481, + 0.138151865749083321638, + 0.0160746087093676504695, + 0.000964011807005165528527, + 0.275335474764726041141e-4, + 0.282243172016108031869e-6 + }; + mpfr_class xs = x - 6; + mpfr_class R = tools::evaluate_polynomial(P, xs) / tools::evaluate_polynomial(Q, xs); + result = Y * x + R * x; + } + else if(x < 44) + { + // Max empfr_classor found: 5.697761e-20 + static const float Y = 0.99714565277099609375f; + static const mpfr_class P[] = { + -0.0024978212791898131227, + -0.779190719229053954292e-5, + 0.254723037413027451751e-4, + 0.162397777342510920873e-5, + 0.396341011304801168516e-7, + 0.411632831190944208473e-9, + 0.145596286718675035587e-11, + -0.116765012397184275695e-17 + }; + static const mpfr_class Q[] = { + 1, + 0.207123112214422517181, + 0.0169410838120975906478, + 0.000690538265622684595676, + 0.145007359818232637924e-4, + 0.144437756628144157666e-6, + 0.509761276599778486139e-9 + }; + mpfr_class xs = x - 18; + mpfr_class R = tools::evaluate_polynomial(P, xs) / tools::evaluate_polynomial(Q, xs); + result = Y * x + R * x; + } + else + { + // Max empfr_classor found: 1.279746e-20 + static const float Y = 0.99941349029541015625f; + static const mpfr_class P[] = { + -0.000539042911019078575891, + -0.28398759004727721098e-6, + 0.899465114892291446442e-6, + 0.229345859265920864296e-7, + 0.225561444863500149219e-9, + 0.947846627503022684216e-12, + 0.135880130108924861008e-14, + -0.348890393399948882918e-21 + }; + static const mpfr_class Q[] = { + 1, + 0.0845746234001899436914, + 0.00282092984726264681981, + 0.468292921940894236786e-4, + 0.399968812193862100054e-6, + 0.161809290887904476097e-8, + 0.231558608310259605225e-11 + }; + mpfr_class xs = x - 44; + mpfr_class R = tools::evaluate_polynomial(P, xs) / tools::evaluate_polynomial(Q, xs); + result = Y * x + R * x; + } + } + return result; +} + +inline mpfr_class bessel_i0(mpfr_class x) +{ + #ifdef BOOST_MATH_STANDALONE + static_assert(sizeof(x) == 0, "mpfr bessel_i0 can not be calculated in standalone mode"); + #endif + + static const mpfr_class P1[] = { + static_cast("-2.2335582639474375249e+15"), + static_cast("-5.5050369673018427753e+14"), + static_cast("-3.2940087627407749166e+13"), + static_cast("-8.4925101247114157499e+11"), + static_cast("-1.1912746104985237192e+10"), + static_cast("-1.0313066708737980747e+08"), + static_cast("-5.9545626019847898221e+05"), + static_cast("-2.4125195876041896775e+03"), + static_cast("-7.0935347449210549190e+00"), + static_cast("-1.5453977791786851041e-02"), + static_cast("-2.5172644670688975051e-05"), + static_cast("-3.0517226450451067446e-08"), + static_cast("-2.6843448573468483278e-11"), + static_cast("-1.5982226675653184646e-14"), + static_cast("-5.2487866627945699800e-18"), + }; + static const mpfr_class Q1[] = { + static_cast("-2.2335582639474375245e+15"), + static_cast("7.8858692566751002988e+12"), + static_cast("-1.2207067397808979846e+10"), + static_cast("1.0377081058062166144e+07"), + static_cast("-4.8527560179962773045e+03"), + static_cast("1.0"), + }; + static const mpfr_class P2[] = { + static_cast("-2.2210262233306573296e-04"), + static_cast("1.3067392038106924055e-02"), + static_cast("-4.4700805721174453923e-01"), + static_cast("5.5674518371240761397e+00"), + static_cast("-2.3517945679239481621e+01"), + static_cast("3.1611322818701131207e+01"), + static_cast("-9.6090021968656180000e+00"), + }; + static const mpfr_class Q2[] = { + static_cast("-5.5194330231005480228e-04"), + static_cast("3.2547697594819615062e-02"), + static_cast("-1.1151759188741312645e+00"), + static_cast("1.3982595353892851542e+01"), + static_cast("-6.0228002066743340583e+01"), + static_cast("8.5539563258012929600e+01"), + static_cast("-3.1446690275135491500e+01"), + static_cast("1.0"), + }; + mpfr_class value, factor, r; + + BOOST_MATH_STD_USING + using namespace boost::math::tools; + + if (x < 0) + { + x = -x; // even function + } + if (x == 0) + { + return static_cast(1); + } + if (x <= 15) // x in (0, 15] + { + mpfr_class y = x * x; + value = evaluate_polynomial(P1, y) / evaluate_polynomial(Q1, y); + } + else // x in (15, \infty) + { + mpfr_class y = 1 / x - mpfr_class(1) / 15; + r = evaluate_polynomial(P2, y) / evaluate_polynomial(Q2, y); + factor = exp(x) / sqrt(x); + value = factor * r; + } + + return value; +} + +inline mpfr_class bessel_i1(mpfr_class x) +{ + static const mpfr_class P1[] = { + static_cast("-1.4577180278143463643e+15"), + static_cast("-1.7732037840791591320e+14"), + static_cast("-6.9876779648010090070e+12"), + static_cast("-1.3357437682275493024e+11"), + static_cast("-1.4828267606612366099e+09"), + static_cast("-1.0588550724769347106e+07"), + static_cast("-5.1894091982308017540e+04"), + static_cast("-1.8225946631657315931e+02"), + static_cast("-4.7207090827310162436e-01"), + static_cast("-9.1746443287817501309e-04"), + static_cast("-1.3466829827635152875e-06"), + static_cast("-1.4831904935994647675e-09"), + static_cast("-1.1928788903603238754e-12"), + static_cast("-6.5245515583151902910e-16"), + static_cast("-1.9705291802535139930e-19"), + }; + static const mpfr_class Q1[] = { + static_cast("-2.9154360556286927285e+15"), + static_cast("9.7887501377547640438e+12"), + static_cast("-1.4386907088588283434e+10"), + static_cast("1.1594225856856884006e+07"), + static_cast("-5.1326864679904189920e+03"), + static_cast("1.0"), + }; + static const mpfr_class P2[] = { + static_cast("1.4582087408985668208e-05"), + static_cast("-8.9359825138577646443e-04"), + static_cast("2.9204895411257790122e-02"), + static_cast("-3.4198728018058047439e-01"), + static_cast("1.3960118277609544334e+00"), + static_cast("-1.9746376087200685843e+00"), + static_cast("8.5591872901933459000e-01"), + static_cast("-6.0437159056137599999e-02"), + }; + static const mpfr_class Q2[] = { + static_cast("3.7510433111922824643e-05"), + static_cast("-2.2835624489492512649e-03"), + static_cast("7.4212010813186530069e-02"), + static_cast("-8.5017476463217924408e-01"), + static_cast("3.2593714889036996297e+00"), + static_cast("-3.8806586721556593450e+00"), + static_cast("1.0"), + }; + mpfr_class value, factor, r, w; + + BOOST_MATH_STD_USING + using namespace boost::math::tools; + + w = abs(x); + if (x == 0) + { + return static_cast(0); + } + if (w <= 15) // w in (0, 15] + { + mpfr_class y = x * x; + r = evaluate_polynomial(P1, y) / evaluate_polynomial(Q1, y); + factor = w; + value = factor * r; + } + else // w in (15, \infty) + { + mpfr_class y = 1 / w - mpfr_class(1) / 15; + r = evaluate_polynomial(P2, y) / evaluate_polynomial(Q2, y); + factor = exp(w) / sqrt(w); + value = factor * r; + } + + if (x < 0) + { + value *= -value; // odd function + } + return value; +} + +} // namespace detail + +} + +template<> struct std::is_convertible : public std::false_type{}; + +} + +#endif // BOOST_MATH_MPLFR_BINDINGS_HPP + diff --git a/libcxx/src/third-party/boost/math/bindings/mpreal.hpp b/libcxx/src/third-party/boost/math/bindings/mpreal.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/bindings/mpreal.hpp @@ -0,0 +1,921 @@ +// Copyright John Maddock 2008. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Wrapper that works with mpfr::mpreal defined in gmpfrxx.h +// See http://math.berkeley.edu/~wilken/code/gmpfrxx/ +// Also requires the gmp and mpfr libraries. +// + +#ifndef BOOST_MATH_MPREAL_BINDINGS_HPP +#define BOOST_MATH_MPREAL_BINDINGS_HPP + +#include + +#ifdef _MSC_VER +// +// We get a lot of warnings from the gmp, mpfr and gmpfrxx headers, +// disable them here, so we only see warnings from *our* code: +// +#pragma warning(push) +#pragma warning(disable: 4127 4800 4512) +#endif + +#include + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef BOOST_MATH_STANDALONE +#include +#endif + +namespace mpfr{ + +template +inline mpreal operator + (const mpreal& r, const T& t){ return r + mpreal(t); } +template +inline mpreal operator - (const mpreal& r, const T& t){ return r - mpreal(t); } +template +inline mpreal operator * (const mpreal& r, const T& t){ return r * mpreal(t); } +template +inline mpreal operator / (const mpreal& r, const T& t){ return r / mpreal(t); } + +template +inline mpreal operator + (const T& t, const mpreal& r){ return mpreal(t) + r; } +template +inline mpreal operator - (const T& t, const mpreal& r){ return mpreal(t) - r; } +template +inline mpreal operator * (const T& t, const mpreal& r){ return mpreal(t) * r; } +template +inline mpreal operator / (const T& t, const mpreal& r){ return mpreal(t) / r; } + +template +inline bool operator == (const mpreal& r, const T& t){ return r == mpreal(t); } +template +inline bool operator != (const mpreal& r, const T& t){ return r != mpreal(t); } +template +inline bool operator <= (const mpreal& r, const T& t){ return r <= mpreal(t); } +template +inline bool operator >= (const mpreal& r, const T& t){ return r >= mpreal(t); } +template +inline bool operator < (const mpreal& r, const T& t){ return r < mpreal(t); } +template +inline bool operator > (const mpreal& r, const T& t){ return r > mpreal(t); } + +template +inline bool operator == (const T& t, const mpreal& r){ return mpreal(t) == r; } +template +inline bool operator != (const T& t, const mpreal& r){ return mpreal(t) != r; } +template +inline bool operator <= (const T& t, const mpreal& r){ return mpreal(t) <= r; } +template +inline bool operator >= (const T& t, const mpreal& r){ return mpreal(t) >= r; } +template +inline bool operator < (const T& t, const mpreal& r){ return mpreal(t) < r; } +template +inline bool operator > (const T& t, const mpreal& r){ return mpreal(t) > r; } + +/* +inline mpfr::mpreal fabs(const mpfr::mpreal& v) +{ + return abs(v); +} +inline mpfr::mpreal pow(const mpfr::mpreal& b, const mpfr::mpreal e) +{ + mpfr::mpreal result; + mpfr_pow(result.__get_mp(), b.__get_mp(), e.__get_mp(), GMP_RNDN); + return result; +} +*/ +inline mpfr::mpreal ldexp(const mpfr::mpreal& v, int e) +{ + return mpfr::ldexp(v, static_cast(e)); +} + +inline mpfr::mpreal frexp(const mpfr::mpreal& v, int* expon) +{ + mp_exp_t e; + mpfr::mpreal r = mpfr::frexp(v, &e); + *expon = e; + return r; +} + +#if (MPFR_VERSION < MPFR_VERSION_NUM(2,4,0)) +mpfr::mpreal fmod(const mpfr::mpreal& v1, const mpfr::mpreal& v2) +{ + mpfr::mpreal n; + if(v1 < 0) + n = ceil(v1 / v2); + else + n = floor(v1 / v2); + return v1 - n * v2; +} +#endif + +template +inline mpfr::mpreal modf(const mpfr::mpreal& v, long long* ipart, const Policy& pol) +{ + *ipart = lltrunc(v, pol); + return v - boost::math::tools::real_cast(*ipart); +} +template +inline int iround(mpfr::mpreal const& x, const Policy& pol) +{ + return boost::math::tools::real_cast(boost::math::round(x, pol)); +} + +template +inline long lround(mpfr::mpreal const& x, const Policy& pol) +{ + return boost::math::tools::real_cast(boost::math::round(x, pol)); +} + +template +inline long long llround(mpfr::mpreal const& x, const Policy& pol) +{ + return boost::math::tools::real_cast(boost::math::round(x, pol)); +} + +template +inline int itrunc(mpfr::mpreal const& x, const Policy& pol) +{ + return boost::math::tools::real_cast(boost::math::trunc(x, pol)); +} + +template +inline long ltrunc(mpfr::mpreal const& x, const Policy& pol) +{ + return boost::math::tools::real_cast(boost::math::trunc(x, pol)); +} + +template +inline long long lltrunc(mpfr::mpreal const& x, const Policy& pol) +{ + return boost::math::tools::real_cast(boost::math::trunc(x, pol)); +} + +} + +namespace boost{ namespace math{ + +#if defined(__GNUC__) && (__GNUC__ < 4) + using ::iround; + using ::lround; + using ::llround; + using ::itrunc; + using ::ltrunc; + using ::lltrunc; + using ::modf; +#endif + +namespace lanczos{ + +struct mpreal_lanczos +{ + static mpfr::mpreal lanczos_sum(const mpfr::mpreal& z) + { + unsigned long p = z.get_default_prec(); + if(p <= 72) + return lanczos13UDT::lanczos_sum(z); + else if(p <= 120) + return lanczos22UDT::lanczos_sum(z); + else if(p <= 170) + return lanczos31UDT::lanczos_sum(z); + else //if(p <= 370) approx 100 digit precision: + return lanczos61UDT::lanczos_sum(z); + } + static mpfr::mpreal lanczos_sum_expG_scaled(const mpfr::mpreal& z) + { + unsigned long p = z.get_default_prec(); + if(p <= 72) + return lanczos13UDT::lanczos_sum_expG_scaled(z); + else if(p <= 120) + return lanczos22UDT::lanczos_sum_expG_scaled(z); + else if(p <= 170) + return lanczos31UDT::lanczos_sum_expG_scaled(z); + else //if(p <= 370) approx 100 digit precision: + return lanczos61UDT::lanczos_sum_expG_scaled(z); + } + static mpfr::mpreal lanczos_sum_near_1(const mpfr::mpreal& z) + { + unsigned long p = z.get_default_prec(); + if(p <= 72) + return lanczos13UDT::lanczos_sum_near_1(z); + else if(p <= 120) + return lanczos22UDT::lanczos_sum_near_1(z); + else if(p <= 170) + return lanczos31UDT::lanczos_sum_near_1(z); + else //if(p <= 370) approx 100 digit precision: + return lanczos61UDT::lanczos_sum_near_1(z); + } + static mpfr::mpreal lanczos_sum_near_2(const mpfr::mpreal& z) + { + unsigned long p = z.get_default_prec(); + if(p <= 72) + return lanczos13UDT::lanczos_sum_near_2(z); + else if(p <= 120) + return lanczos22UDT::lanczos_sum_near_2(z); + else if(p <= 170) + return lanczos31UDT::lanczos_sum_near_2(z); + else //if(p <= 370) approx 100 digit precision: + return lanczos61UDT::lanczos_sum_near_2(z); + } + static mpfr::mpreal g() + { + unsigned long p = mpfr::mpreal::get_default_prec(); + if(p <= 72) + return lanczos13UDT::g(); + else if(p <= 120) + return lanczos22UDT::g(); + else if(p <= 170) + return lanczos31UDT::g(); + else //if(p <= 370) approx 100 digit precision: + return lanczos61UDT::g(); + } +}; + +template +struct lanczos +{ + typedef mpreal_lanczos type; +}; + +} // namespace lanczos + +namespace tools +{ + +template<> +inline int digits(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpfr::mpreal)) +{ + return mpfr::mpreal::get_default_prec(); +} + +namespace detail{ + +template +void convert_to_long_result(mpfr::mpreal const& r, I& result) +{ + result = 0; + I last_result(0); + mpfr::mpreal t(r); + double term; + do + { + term = real_cast(t); + last_result = result; + result += static_cast(term); + t -= term; + }while(result != last_result); +} + +} + +template <> +inline mpfr::mpreal real_cast(long long t) +{ + mpfr::mpreal result; + int expon = 0; + int sign = 1; + if(t < 0) + { + sign = -1; + t = -t; + } + while(t) + { + result += ldexp(static_cast(t & 0xffffL), expon); + expon += 32; + t >>= 32; + } + return result * sign; +} +/* +template <> +inline unsigned real_cast(mpfr::mpreal t) +{ + return t.get_ui(); +} +template <> +inline int real_cast(mpfr::mpreal t) +{ + return t.get_si(); +} +template <> +inline double real_cast(mpfr::mpreal t) +{ + return t.get_d(); +} +template <> +inline float real_cast(mpfr::mpreal t) +{ + return static_cast(t.get_d()); +} +template <> +inline long real_cast(mpfr::mpreal t) +{ + long result; + detail::convert_to_long_result(t, result); + return result; +} +*/ +template <> +inline long long real_cast(mpfr::mpreal t) +{ + long long result; + detail::convert_to_long_result(t, result); + return result; +} + +template <> +inline mpfr::mpreal max_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpfr::mpreal)) +{ + static bool has_init = false; + static mpfr::mpreal val(0.5); + if(!has_init) + { + val = ldexp(val, mpfr_get_emax()); + has_init = true; + } + return val; +} + +template <> +inline mpfr::mpreal min_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpfr::mpreal)) +{ + static bool has_init = false; + static mpfr::mpreal val(0.5); + if(!has_init) + { + val = ldexp(val, mpfr_get_emin()); + has_init = true; + } + return val; +} + +template <> +inline mpfr::mpreal log_max_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpfr::mpreal)) +{ + static bool has_init = false; + static mpfr::mpreal val = max_value(); + if(!has_init) + { + val = log(val); + has_init = true; + } + return val; +} + +template <> +inline mpfr::mpreal log_min_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpfr::mpreal)) +{ + static bool has_init = false; + static mpfr::mpreal val = max_value(); + if(!has_init) + { + val = log(val); + has_init = true; + } + return val; +} + +template <> +inline mpfr::mpreal epsilon(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpfr::mpreal)) +{ + return ldexp(mpfr::mpreal(1), 1-boost::math::policies::digits >()); +} + +} // namespace tools + +template +inline mpfr::mpreal skewness(const extreme_value_distribution& /*dist*/) +{ + // + // This is 12 * sqrt(6) * zeta(3) / pi^3: + // See http://mathworld.wolfram.com/ExtremeValueDistribution.html + // + #ifdef BOOST_MATH_STANDALONE + static_assert(sizeof(Policy) == 0, "mpreal skewness can not be calculated in standalone mode"); + #endif + + return boost::lexical_cast("1.1395470994046486574927930193898461120875997958366"); +} + +template +inline mpfr::mpreal skewness(const rayleigh_distribution& /*dist*/) +{ + // using namespace boost::math::constants; + #ifdef BOOST_MATH_STANDALONE + static_assert(sizeof(Policy) == 0, "mpreal skewness can not be calculated in standalone mode"); + #endif + + return boost::lexical_cast("0.63111065781893713819189935154422777984404221106391"); + // Computed using NTL at 150 bit, about 50 decimal digits. + // return 2 * root_pi() * pi_minus_three() / pow23_four_minus_pi(); +} + +template +inline mpfr::mpreal kurtosis(const rayleigh_distribution& /*dist*/) +{ + // using namespace boost::math::constants; + #ifdef BOOST_MATH_STANDALONE + static_assert(sizeof(Policy) == 0, "mpreal kurtosis can not be calculated in standalone mode"); + #endif + + return boost::lexical_cast("3.2450893006876380628486604106197544154170667057995"); + // Computed using NTL at 150 bit, about 50 decimal digits. + // return 3 - (6 * pi() * pi() - 24 * pi() + 16) / + // (four_minus_pi() * four_minus_pi()); +} + +template +inline mpfr::mpreal kurtosis_excess(const rayleigh_distribution& /*dist*/) +{ + //using namespace boost::math::constants; + // Computed using NTL at 150 bit, about 50 decimal digits. + #ifdef BOOST_MATH_STANDALONE + static_assert(sizeof(Policy) == 0, "mpreal excess kurtosis can not be calculated in standalone mode"); + #endif + + return boost::lexical_cast("0.2450893006876380628486604106197544154170667057995"); + // return -(6 * pi() * pi() - 24 * pi() + 16) / + // (four_minus_pi() * four_minus_pi()); +} // kurtosis + +namespace detail{ + +// +// Version of Digamma accurate to ~100 decimal digits. +// +template +mpfr::mpreal digamma_imp(mpfr::mpreal x, const std::integral_constant* , const Policy& pol) +{ + // + // This handles reflection of negative arguments, and all our + // empfr_classor handling, then forwards to the T-specific approximation. + // + BOOST_MATH_STD_USING // ADL of std functions. + + mpfr::mpreal result = 0; + // + // Check for negative arguments and use reflection: + // + if(x < 0) + { + // Reflect: + x = 1 - x; + // Argument reduction for tan: + mpfr::mpreal remainder = x - floor(x); + // Shift to negative if > 0.5: + if(remainder > 0.5) + { + remainder -= 1; + } + // + // check for evaluation at a negative pole: + // + if(remainder == 0) + { + return policies::raise_pole_error("boost::math::digamma<%1%>(%1%)", nullptr, (1-x), pol); + } + result = constants::pi() / tan(constants::pi() * remainder); + } + result += big_digamma(x); + return result; +} +// +// Specialisations of this function provides the initial +// starting guess for Halley iteration: +// +template +mpfr::mpreal erf_inv_imp(const mpfr::mpreal& p, const mpfr::mpreal& q, const Policy&, const std::integral_constant*) +{ + BOOST_MATH_STD_USING // for ADL of std names. + + mpfr::mpreal result = 0; + + if(p <= 0.5) + { + // + // Evaluate inverse erf using the rational approximation: + // + // x = p(p+10)(Y+R(p)) + // + // Where Y is a constant, and R(p) is optimised for a low + // absolute empfr_classor compared to |Y|. + // + // double: Max empfr_classor found: 2.001849e-18 + // long double: Max empfr_classor found: 1.017064e-20 + // Maximum Deviation Found (actual empfr_classor term at infinite precision) 8.030e-21 + // + static const float Y = 0.0891314744949340820313f; + static const mpfr::mpreal P[] = { + -0.000508781949658280665617, + -0.00836874819741736770379, + 0.0334806625409744615033, + -0.0126926147662974029034, + -0.0365637971411762664006, + 0.0219878681111168899165, + 0.00822687874676915743155, + -0.00538772965071242932965 + }; + static const mpfr::mpreal Q[] = { + 1, + -0.970005043303290640362, + -1.56574558234175846809, + 1.56221558398423026363, + 0.662328840472002992063, + -0.71228902341542847553, + -0.0527396382340099713954, + 0.0795283687341571680018, + -0.00233393759374190016776, + 0.000886216390456424707504 + }; + mpfr::mpreal g = p * (p + 10); + mpfr::mpreal r = tools::evaluate_polynomial(P, p) / tools::evaluate_polynomial(Q, p); + result = g * Y + g * r; + } + else if(q >= 0.25) + { + // + // Rational approximation for 0.5 > q >= 0.25 + // + // x = sqrt(-2*log(q)) / (Y + R(q)) + // + // Where Y is a constant, and R(q) is optimised for a low + // absolute empfr_classor compared to Y. + // + // double : Max empfr_classor found: 7.403372e-17 + // long double : Max empfr_classor found: 6.084616e-20 + // Maximum Deviation Found (empfr_classor term) 4.811e-20 + // + static const float Y = 2.249481201171875f; + static const mpfr::mpreal P[] = { + -0.202433508355938759655, + 0.105264680699391713268, + 8.37050328343119927838, + 17.6447298408374015486, + -18.8510648058714251895, + -44.6382324441786960818, + 17.445385985570866523, + 21.1294655448340526258, + -3.67192254707729348546 + }; + static const mpfr::mpreal Q[] = { + 1, + 6.24264124854247537712, + 3.9713437953343869095, + -28.6608180499800029974, + -20.1432634680485188801, + 48.5609213108739935468, + 10.8268667355460159008, + -22.6436933413139721736, + 1.72114765761200282724 + }; + mpfr::mpreal g = sqrt(-2 * log(q)); + mpfr::mpreal xs = q - 0.25; + mpfr::mpreal r = tools::evaluate_polynomial(P, xs) / tools::evaluate_polynomial(Q, xs); + result = g / (Y + r); + } + else + { + // + // For q < 0.25 we have a series of rational approximations all + // of the general form: + // + // let: x = sqrt(-log(q)) + // + // Then the result is given by: + // + // x(Y+R(x-B)) + // + // where Y is a constant, B is the lowest value of x for which + // the approximation is valid, and R(x-B) is optimised for a low + // absolute empfr_classor compared to Y. + // + // Note that almost all code will really go through the first + // or maybe second approximation. After than we're dealing with very + // small input values indeed: 80 and 128 bit long double's go all the + // way down to ~ 1e-5000 so the "tail" is rather long... + // + mpfr::mpreal x = sqrt(-log(q)); + if(x < 3) + { + // Max empfr_classor found: 1.089051e-20 + static const float Y = 0.807220458984375f; + static const mpfr::mpreal P[] = { + -0.131102781679951906451, + -0.163794047193317060787, + 0.117030156341995252019, + 0.387079738972604337464, + 0.337785538912035898924, + 0.142869534408157156766, + 0.0290157910005329060432, + 0.00214558995388805277169, + -0.679465575181126350155e-6, + 0.285225331782217055858e-7, + -0.681149956853776992068e-9 + }; + static const mpfr::mpreal Q[] = { + 1, + 3.46625407242567245975, + 5.38168345707006855425, + 4.77846592945843778382, + 2.59301921623620271374, + 0.848854343457902036425, + 0.152264338295331783612, + 0.01105924229346489121 + }; + mpfr::mpreal xs = x - 1.125; + mpfr::mpreal R = tools::evaluate_polynomial(P, xs) / tools::evaluate_polynomial(Q, xs); + result = Y * x + R * x; + } + else if(x < 6) + { + // Max empfr_classor found: 8.389174e-21 + static const float Y = 0.93995571136474609375f; + static const mpfr::mpreal P[] = { + -0.0350353787183177984712, + -0.00222426529213447927281, + 0.0185573306514231072324, + 0.00950804701325919603619, + 0.00187123492819559223345, + 0.000157544617424960554631, + 0.460469890584317994083e-5, + -0.230404776911882601748e-9, + 0.266339227425782031962e-11 + }; + static const mpfr::mpreal Q[] = { + 1, + 1.3653349817554063097, + 0.762059164553623404043, + 0.220091105764131249824, + 0.0341589143670947727934, + 0.00263861676657015992959, + 0.764675292302794483503e-4 + }; + mpfr::mpreal xs = x - 3; + mpfr::mpreal R = tools::evaluate_polynomial(P, xs) / tools::evaluate_polynomial(Q, xs); + result = Y * x + R * x; + } + else if(x < 18) + { + // Max empfr_classor found: 1.481312e-19 + static const float Y = 0.98362827301025390625f; + static const mpfr::mpreal P[] = { + -0.0167431005076633737133, + -0.00112951438745580278863, + 0.00105628862152492910091, + 0.000209386317487588078668, + 0.149624783758342370182e-4, + 0.449696789927706453732e-6, + 0.462596163522878599135e-8, + -0.281128735628831791805e-13, + 0.99055709973310326855e-16 + }; + static const mpfr::mpreal Q[] = { + 1, + 0.591429344886417493481, + 0.138151865749083321638, + 0.0160746087093676504695, + 0.000964011807005165528527, + 0.275335474764726041141e-4, + 0.282243172016108031869e-6 + }; + mpfr::mpreal xs = x - 6; + mpfr::mpreal R = tools::evaluate_polynomial(P, xs) / tools::evaluate_polynomial(Q, xs); + result = Y * x + R * x; + } + else if(x < 44) + { + // Max empfr_classor found: 5.697761e-20 + static const float Y = 0.99714565277099609375f; + static const mpfr::mpreal P[] = { + -0.0024978212791898131227, + -0.779190719229053954292e-5, + 0.254723037413027451751e-4, + 0.162397777342510920873e-5, + 0.396341011304801168516e-7, + 0.411632831190944208473e-9, + 0.145596286718675035587e-11, + -0.116765012397184275695e-17 + }; + static const mpfr::mpreal Q[] = { + 1, + 0.207123112214422517181, + 0.0169410838120975906478, + 0.000690538265622684595676, + 0.145007359818232637924e-4, + 0.144437756628144157666e-6, + 0.509761276599778486139e-9 + }; + mpfr::mpreal xs = x - 18; + mpfr::mpreal R = tools::evaluate_polynomial(P, xs) / tools::evaluate_polynomial(Q, xs); + result = Y * x + R * x; + } + else + { + // Max empfr_classor found: 1.279746e-20 + static const float Y = 0.99941349029541015625f; + static const mpfr::mpreal P[] = { + -0.000539042911019078575891, + -0.28398759004727721098e-6, + 0.899465114892291446442e-6, + 0.229345859265920864296e-7, + 0.225561444863500149219e-9, + 0.947846627503022684216e-12, + 0.135880130108924861008e-14, + -0.348890393399948882918e-21 + }; + static const mpfr::mpreal Q[] = { + 1, + 0.0845746234001899436914, + 0.00282092984726264681981, + 0.468292921940894236786e-4, + 0.399968812193862100054e-6, + 0.161809290887904476097e-8, + 0.231558608310259605225e-11 + }; + mpfr::mpreal xs = x - 44; + mpfr::mpreal R = tools::evaluate_polynomial(P, xs) / tools::evaluate_polynomial(Q, xs); + result = Y * x + R * x; + } + } + return result; +} + +inline mpfr::mpreal bessel_i0(mpfr::mpreal x) +{ + #ifdef BOOST_MATH_STANDALONE + static_assert(sizeof(x) == 0, "mpreal bessel_i0 can not be calculated in standalone mode"); + #endif + + static const mpfr::mpreal P1[] = { + boost::lexical_cast("-2.2335582639474375249e+15"), + boost::lexical_cast("-5.5050369673018427753e+14"), + boost::lexical_cast("-3.2940087627407749166e+13"), + boost::lexical_cast("-8.4925101247114157499e+11"), + boost::lexical_cast("-1.1912746104985237192e+10"), + boost::lexical_cast("-1.0313066708737980747e+08"), + boost::lexical_cast("-5.9545626019847898221e+05"), + boost::lexical_cast("-2.4125195876041896775e+03"), + boost::lexical_cast("-7.0935347449210549190e+00"), + boost::lexical_cast("-1.5453977791786851041e-02"), + boost::lexical_cast("-2.5172644670688975051e-05"), + boost::lexical_cast("-3.0517226450451067446e-08"), + boost::lexical_cast("-2.6843448573468483278e-11"), + boost::lexical_cast("-1.5982226675653184646e-14"), + boost::lexical_cast("-5.2487866627945699800e-18"), + }; + static const mpfr::mpreal Q1[] = { + boost::lexical_cast("-2.2335582639474375245e+15"), + boost::lexical_cast("7.8858692566751002988e+12"), + boost::lexical_cast("-1.2207067397808979846e+10"), + boost::lexical_cast("1.0377081058062166144e+07"), + boost::lexical_cast("-4.8527560179962773045e+03"), + boost::lexical_cast("1.0"), + }; + static const mpfr::mpreal P2[] = { + boost::lexical_cast("-2.2210262233306573296e-04"), + boost::lexical_cast("1.3067392038106924055e-02"), + boost::lexical_cast("-4.4700805721174453923e-01"), + boost::lexical_cast("5.5674518371240761397e+00"), + boost::lexical_cast("-2.3517945679239481621e+01"), + boost::lexical_cast("3.1611322818701131207e+01"), + boost::lexical_cast("-9.6090021968656180000e+00"), + }; + static const mpfr::mpreal Q2[] = { + boost::lexical_cast("-5.5194330231005480228e-04"), + boost::lexical_cast("3.2547697594819615062e-02"), + boost::lexical_cast("-1.1151759188741312645e+00"), + boost::lexical_cast("1.3982595353892851542e+01"), + boost::lexical_cast("-6.0228002066743340583e+01"), + boost::lexical_cast("8.5539563258012929600e+01"), + boost::lexical_cast("-3.1446690275135491500e+01"), + boost::lexical_cast("1.0"), + }; + mpfr::mpreal value, factor, r; + + BOOST_MATH_STD_USING + using namespace boost::math::tools; + + if (x < 0) + { + x = -x; // even function + } + if (x == 0) + { + return static_cast(1); + } + if (x <= 15) // x in (0, 15] + { + mpfr::mpreal y = x * x; + value = evaluate_polynomial(P1, y) / evaluate_polynomial(Q1, y); + } + else // x in (15, \infty) + { + mpfr::mpreal y = 1 / x - mpfr::mpreal(1) / 15; + r = evaluate_polynomial(P2, y) / evaluate_polynomial(Q2, y); + factor = exp(x) / sqrt(x); + value = factor * r; + } + + return value; +} + +inline mpfr::mpreal bessel_i1(mpfr::mpreal x) +{ + static const mpfr::mpreal P1[] = { + static_cast("-1.4577180278143463643e+15"), + static_cast("-1.7732037840791591320e+14"), + static_cast("-6.9876779648010090070e+12"), + static_cast("-1.3357437682275493024e+11"), + static_cast("-1.4828267606612366099e+09"), + static_cast("-1.0588550724769347106e+07"), + static_cast("-5.1894091982308017540e+04"), + static_cast("-1.8225946631657315931e+02"), + static_cast("-4.7207090827310162436e-01"), + static_cast("-9.1746443287817501309e-04"), + static_cast("-1.3466829827635152875e-06"), + static_cast("-1.4831904935994647675e-09"), + static_cast("-1.1928788903603238754e-12"), + static_cast("-6.5245515583151902910e-16"), + static_cast("-1.9705291802535139930e-19"), + }; + static const mpfr::mpreal Q1[] = { + static_cast("-2.9154360556286927285e+15"), + static_cast("9.7887501377547640438e+12"), + static_cast("-1.4386907088588283434e+10"), + static_cast("1.1594225856856884006e+07"), + static_cast("-5.1326864679904189920e+03"), + static_cast("1.0"), + }; + static const mpfr::mpreal P2[] = { + static_cast("1.4582087408985668208e-05"), + static_cast("-8.9359825138577646443e-04"), + static_cast("2.9204895411257790122e-02"), + static_cast("-3.4198728018058047439e-01"), + static_cast("1.3960118277609544334e+00"), + static_cast("-1.9746376087200685843e+00"), + static_cast("8.5591872901933459000e-01"), + static_cast("-6.0437159056137599999e-02"), + }; + static const mpfr::mpreal Q2[] = { + static_cast("3.7510433111922824643e-05"), + static_cast("-2.2835624489492512649e-03"), + static_cast("7.4212010813186530069e-02"), + static_cast("-8.5017476463217924408e-01"), + static_cast("3.2593714889036996297e+00"), + static_cast("-3.8806586721556593450e+00"), + static_cast("1.0"), + }; + mpfr::mpreal value, factor, r, w; + + BOOST_MATH_STD_USING + using namespace boost::math::tools; + + w = abs(x); + if (x == 0) + { + return static_cast(0); + } + if (w <= 15) // w in (0, 15] + { + mpfr::mpreal y = x * x; + r = evaluate_polynomial(P1, y) / evaluate_polynomial(Q1, y); + factor = w; + value = factor * r; + } + else // w in (15, \infty) + { + mpfr::mpreal y = 1 / w - mpfr::mpreal(1) / 15; + r = evaluate_polynomial(P2, y) / evaluate_polynomial(Q2, y); + factor = exp(w) / sqrt(w); + value = factor * r; + } + + if (x < 0) + { + value *= -value; // odd function + } + return value; +} + +} // namespace detail +} // namespace math + +} + +#endif // BOOST_MATH_MPLFR_BINDINGS_HPP + diff --git a/libcxx/src/third-party/boost/math/bindings/rr.hpp b/libcxx/src/third-party/boost/math/bindings/rr.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/bindings/rr.hpp @@ -0,0 +1,876 @@ +// Copyright John Maddock 2007. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_NTL_RR_HPP +#define BOOST_MATH_NTL_RR_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost{ namespace math{ + +namespace ntl +{ + +class RR; + +RR ldexp(RR r, int exp); +RR frexp(RR r, int* exp); + +class RR +{ +public: + // Constructors: + RR() {} + RR(const ::NTL::RR& c) : m_value(c){} + RR(char c) + { + m_value = c; + } + RR(wchar_t c) + { + m_value = c; + } + RR(unsigned char c) + { + m_value = c; + } + RR(signed char c) + { + m_value = c; + } + RR(unsigned short c) + { + m_value = c; + } + RR(short c) + { + m_value = c; + } + RR(unsigned int c) + { + assign_large_int(c); + } + RR(int c) + { + assign_large_int(c); + } + RR(unsigned long c) + { + assign_large_int(c); + } + RR(long c) + { + assign_large_int(c); + } + RR(unsigned long long c) + { + assign_large_int(c); + } + RR(long long c) + { + assign_large_int(c); + } + RR(float c) + { + m_value = c; + } + RR(double c) + { + m_value = c; + } + RR(long double c) + { + assign_large_real(c); + } + + // Assignment: + RR& operator=(char c) { m_value = c; return *this; } + RR& operator=(unsigned char c) { m_value = c; return *this; } + RR& operator=(signed char c) { m_value = c; return *this; } + RR& operator=(wchar_t c) { m_value = c; return *this; } + RR& operator=(short c) { m_value = c; return *this; } + RR& operator=(unsigned short c) { m_value = c; return *this; } + RR& operator=(int c) { assign_large_int(c); return *this; } + RR& operator=(unsigned int c) { assign_large_int(c); return *this; } + RR& operator=(long c) { assign_large_int(c); return *this; } + RR& operator=(unsigned long c) { assign_large_int(c); return *this; } + RR& operator=(long long c) { assign_large_int(c); return *this; } + RR& operator=(unsigned long long c) { assign_large_int(c); return *this; } + RR& operator=(float c) { m_value = c; return *this; } + RR& operator=(double c) { m_value = c; return *this; } + RR& operator=(long double c) { assign_large_real(c); return *this; } + + // Access: + NTL::RR& value(){ return m_value; } + NTL::RR const& value()const{ return m_value; } + + // Member arithmetic: + RR& operator+=(const RR& other) + { m_value += other.value(); return *this; } + RR& operator-=(const RR& other) + { m_value -= other.value(); return *this; } + RR& operator*=(const RR& other) + { m_value *= other.value(); return *this; } + RR& operator/=(const RR& other) + { m_value /= other.value(); return *this; } + RR operator-()const + { return -m_value; } + RR const& operator+()const + { return *this; } + + // RR compatibility: + const ::NTL::ZZ& mantissa() const + { return m_value.mantissa(); } + long exponent() const + { return m_value.exponent(); } + + static void SetPrecision(long p) + { ::NTL::RR::SetPrecision(p); } + + static long precision() + { return ::NTL::RR::precision(); } + + static void SetOutputPrecision(long p) + { ::NTL::RR::SetOutputPrecision(p); } + static long OutputPrecision() + { return ::NTL::RR::OutputPrecision(); } + + +private: + ::NTL::RR m_value; + + template + void assign_large_real(const V& a) + { + using std::frexp; + using std::ldexp; + using std::floor; + if (a == 0) { + clear(m_value); + return; + } + + if (a == 1) { + NTL::set(m_value); + return; + } + + if (!(boost::math::isfinite)(a)) + { + throw std::overflow_error("Cannot construct an instance of NTL::RR with an infinite value."); + } + + int e; + long double f, term; + ::NTL::RR t; + clear(m_value); + + f = frexp(a, &e); + + while(f) + { + // extract 30 bits from f: + f = ldexp(f, 30); + term = floor(f); + e -= 30; + conv(t.x, (int)term); + t.e = e; + m_value += t; + f -= term; + } + } + + template + void assign_large_int(V a) + { +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4146) +#endif + clear(m_value); + int exp = 0; + NTL::RR t; + bool neg = a < V(0) ? true : false; + if(neg) + a = -a; + while(a) + { + t = static_cast(a & 0xffff); + m_value += ldexp(RR(t), exp).value(); + a >>= 16; + exp += 16; + } + if(neg) + m_value = -m_value; +#ifdef _MSC_VER +#pragma warning(pop) +#endif + } +}; + +// Non-member arithmetic: +inline RR operator+(const RR& a, const RR& b) +{ + RR result(a); + result += b; + return result; +} +inline RR operator-(const RR& a, const RR& b) +{ + RR result(a); + result -= b; + return result; +} +inline RR operator*(const RR& a, const RR& b) +{ + RR result(a); + result *= b; + return result; +} +inline RR operator/(const RR& a, const RR& b) +{ + RR result(a); + result /= b; + return result; +} + +// Comparison: +inline bool operator == (const RR& a, const RR& b) +{ return a.value() == b.value() ? true : false; } +inline bool operator != (const RR& a, const RR& b) +{ return a.value() != b.value() ? true : false;} +inline bool operator < (const RR& a, const RR& b) +{ return a.value() < b.value() ? true : false; } +inline bool operator <= (const RR& a, const RR& b) +{ return a.value() <= b.value() ? true : false; } +inline bool operator > (const RR& a, const RR& b) +{ return a.value() > b.value() ? true : false; } +inline bool operator >= (const RR& a, const RR& b) +{ return a.value() >= b.value() ? true : false; } + +#if 0 +// Non-member mixed compare: +template +inline bool operator == (const T& a, const RR& b) +{ + return a == b.value(); +} +template +inline bool operator != (const T& a, const RR& b) +{ + return a != b.value(); +} +template +inline bool operator < (const T& a, const RR& b) +{ + return a < b.value(); +} +template +inline bool operator > (const T& a, const RR& b) +{ + return a > b.value(); +} +template +inline bool operator <= (const T& a, const RR& b) +{ + return a <= b.value(); +} +template +inline bool operator >= (const T& a, const RR& b) +{ + return a >= b.value(); +} +#endif // Non-member mixed compare: + +// Non-member functions: +/* +inline RR acos(RR a) +{ return ::NTL::acos(a.value()); } +*/ +inline RR cos(RR a) +{ return ::NTL::cos(a.value()); } +/* +inline RR asin(RR a) +{ return ::NTL::asin(a.value()); } +inline RR atan(RR a) +{ return ::NTL::atan(a.value()); } +inline RR atan2(RR a, RR b) +{ return ::NTL::atan2(a.value(), b.value()); } +*/ +inline RR ceil(RR a) +{ return ::NTL::ceil(a.value()); } +/* +inline RR fmod(RR a, RR b) +{ return ::NTL::fmod(a.value(), b.value()); } +inline RR cosh(RR a) +{ return ::NTL::cosh(a.value()); } +*/ +inline RR exp(RR a) +{ return ::NTL::exp(a.value()); } +inline RR fabs(RR a) +{ return ::NTL::fabs(a.value()); } +inline RR abs(RR a) +{ return ::NTL::abs(a.value()); } +inline RR floor(RR a) +{ return ::NTL::floor(a.value()); } +/* +inline RR modf(RR a, RR* ipart) +{ + ::NTL::RR ip; + RR result = modf(a.value(), &ip); + *ipart = ip; + return result; +} +inline RR frexp(RR a, int* expon) +{ return ::NTL::frexp(a.value(), expon); } +inline RR ldexp(RR a, int expon) +{ return ::NTL::ldexp(a.value(), expon); } +*/ +inline RR log(RR a) +{ return ::NTL::log(a.value()); } +inline RR log10(RR a) +{ return ::NTL::log10(a.value()); } +/* +inline RR tan(RR a) +{ return ::NTL::tan(a.value()); } +*/ +inline RR pow(RR a, RR b) +{ return ::NTL::pow(a.value(), b.value()); } +inline RR pow(RR a, int b) +{ return ::NTL::power(a.value(), b); } +inline RR sin(RR a) +{ return ::NTL::sin(a.value()); } +/* +inline RR sinh(RR a) +{ return ::NTL::sinh(a.value()); } +*/ +inline RR sqrt(RR a) +{ return ::NTL::sqrt(a.value()); } +/* +inline RR tanh(RR a) +{ return ::NTL::tanh(a.value()); } +*/ + inline RR pow(const RR& r, long l) + { + return ::NTL::power(r.value(), l); + } + inline RR tan(const RR& a) + { + return sin(a)/cos(a); + } + inline RR frexp(RR r, int* exp) + { + *exp = r.value().e; + r.value().e = 0; + while(r >= 1) + { + *exp += 1; + r.value().e -= 1; + } + while(r < 0.5) + { + *exp -= 1; + r.value().e += 1; + } + BOOST_MATH_ASSERT(r < 1); + BOOST_MATH_ASSERT(r >= 0.5); + return r; + } + inline RR ldexp(RR r, int exp) + { + r.value().e += exp; + return r; + } + +// Streaming: +template +inline std::basic_ostream& operator<<(std::basic_ostream& os, const RR& a) +{ + return os << a.value(); +} +template +inline std::basic_istream& operator>>(std::basic_istream& is, RR& a) +{ + ::NTL::RR v; + is >> v; + a = v; + return is; +} + +} // namespace ntl + +namespace lanczos{ + +struct ntl_lanczos +{ + static ntl::RR lanczos_sum(const ntl::RR& z) + { + unsigned long p = ntl::RR::precision(); + if(p <= 72) + return lanczos13UDT::lanczos_sum(z); + else if(p <= 120) + return lanczos22UDT::lanczos_sum(z); + else if(p <= 170) + return lanczos31UDT::lanczos_sum(z); + else //if(p <= 370) approx 100 digit precision: + return lanczos61UDT::lanczos_sum(z); + } + static ntl::RR lanczos_sum_expG_scaled(const ntl::RR& z) + { + unsigned long p = ntl::RR::precision(); + if(p <= 72) + return lanczos13UDT::lanczos_sum_expG_scaled(z); + else if(p <= 120) + return lanczos22UDT::lanczos_sum_expG_scaled(z); + else if(p <= 170) + return lanczos31UDT::lanczos_sum_expG_scaled(z); + else //if(p <= 370) approx 100 digit precision: + return lanczos61UDT::lanczos_sum_expG_scaled(z); + } + static ntl::RR lanczos_sum_near_1(const ntl::RR& z) + { + unsigned long p = ntl::RR::precision(); + if(p <= 72) + return lanczos13UDT::lanczos_sum_near_1(z); + else if(p <= 120) + return lanczos22UDT::lanczos_sum_near_1(z); + else if(p <= 170) + return lanczos31UDT::lanczos_sum_near_1(z); + else //if(p <= 370) approx 100 digit precision: + return lanczos61UDT::lanczos_sum_near_1(z); + } + static ntl::RR lanczos_sum_near_2(const ntl::RR& z) + { + unsigned long p = ntl::RR::precision(); + if(p <= 72) + return lanczos13UDT::lanczos_sum_near_2(z); + else if(p <= 120) + return lanczos22UDT::lanczos_sum_near_2(z); + else if(p <= 170) + return lanczos31UDT::lanczos_sum_near_2(z); + else //if(p <= 370) approx 100 digit precision: + return lanczos61UDT::lanczos_sum_near_2(z); + } + static ntl::RR g() + { + unsigned long p = ntl::RR::precision(); + if(p <= 72) + return lanczos13UDT::g(); + else if(p <= 120) + return lanczos22UDT::g(); + else if(p <= 170) + return lanczos31UDT::g(); + else //if(p <= 370) approx 100 digit precision: + return lanczos61UDT::g(); + } +}; + +template +struct lanczos +{ + typedef ntl_lanczos type; +}; + +} // namespace lanczos + +namespace tools +{ + +template<> +inline int digits(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR)) +{ + return ::NTL::RR::precision(); +} + +template <> +inline float real_cast(boost::math::ntl::RR t) +{ + double r; + conv(r, t.value()); + return static_cast(r); +} +template <> +inline double real_cast(boost::math::ntl::RR t) +{ + double r; + conv(r, t.value()); + return r; +} + +namespace detail{ + +template +void convert_to_long_result(NTL::RR const& r, I& result) +{ + result = 0; + I last_result(0); + NTL::RR t(r); + double term; + do + { + conv(term, t); + last_result = result; + result += static_cast(term); + t -= term; + }while(result != last_result); +} + +} + +template <> +inline long double real_cast(boost::math::ntl::RR t) +{ + long double result(0); + detail::convert_to_long_result(t.value(), result); + return result; +} +template <> +inline boost::math::ntl::RR real_cast(boost::math::ntl::RR t) +{ + return t; +} +template <> +inline unsigned real_cast(boost::math::ntl::RR t) +{ + unsigned result; + detail::convert_to_long_result(t.value(), result); + return result; +} +template <> +inline int real_cast(boost::math::ntl::RR t) +{ + int result; + detail::convert_to_long_result(t.value(), result); + return result; +} +template <> +inline long real_cast(boost::math::ntl::RR t) +{ + long result; + detail::convert_to_long_result(t.value(), result); + return result; +} +template <> +inline long long real_cast(boost::math::ntl::RR t) +{ + long long result; + detail::convert_to_long_result(t.value(), result); + return result; +} + +template <> +inline boost::math::ntl::RR max_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR)) +{ + static bool has_init = false; + static NTL::RR val; + if(!has_init) + { + val = 1; + val.e = NTL_OVFBND-20; + has_init = true; + } + return val; +} + +template <> +inline boost::math::ntl::RR min_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR)) +{ + static bool has_init = false; + static NTL::RR val; + if(!has_init) + { + val = 1; + val.e = -NTL_OVFBND+20; + has_init = true; + } + return val; +} + +template <> +inline boost::math::ntl::RR log_max_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR)) +{ + static bool has_init = false; + static NTL::RR val; + if(!has_init) + { + val = 1; + val.e = NTL_OVFBND-20; + val = log(val); + has_init = true; + } + return val; +} + +template <> +inline boost::math::ntl::RR log_min_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR)) +{ + static bool has_init = false; + static NTL::RR val; + if(!has_init) + { + val = 1; + val.e = -NTL_OVFBND+20; + val = log(val); + has_init = true; + } + return val; +} + +template <> +inline boost::math::ntl::RR epsilon(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR)) +{ + return ldexp(boost::math::ntl::RR(1), 1-boost::math::policies::digits >()); +} + +} // namespace tools + +// +// The number of digits precision in RR can vary with each call +// so we need to recalculate these with each call: +// +namespace constants{ + +template<> inline boost::math::ntl::RR pi(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR)) +{ + NTL::RR result; + ComputePi(result); + return result; +} +template<> inline boost::math::ntl::RR e(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR)) +{ + NTL::RR result; + result = 1; + return exp(result); +} + +} // namespace constants + +namespace ntl{ + // + // These are some fairly brain-dead versions of the math + // functions that NTL fails to provide. + // + + + // + // Inverse trig functions: + // + struct asin_root + { + asin_root(RR const& target) : t(target){} + + boost::math::tuple operator()(RR const& p) + { + RR f0 = sin(p); + RR f1 = cos(p); + RR f2 = -f0; + f0 -= t; + return boost::math::make_tuple(f0, f1, f2); + } + private: + RR t; + }; + + inline RR asin(RR z) + { + double r; + conv(r, z.value()); + return boost::math::tools::halley_iterate( + asin_root(z), + RR(std::asin(r)), + RR(-boost::math::constants::pi()/2), + RR(boost::math::constants::pi()/2), + NTL::RR::precision()); + } + + struct acos_root + { + acos_root(RR const& target) : t(target){} + + boost::math::tuple operator()(RR const& p) + { + RR f0 = cos(p); + RR f1 = -sin(p); + RR f2 = -f0; + f0 -= t; + return boost::math::make_tuple(f0, f1, f2); + } + private: + RR t; + }; + + inline RR acos(RR z) + { + double r; + conv(r, z.value()); + return boost::math::tools::halley_iterate( + acos_root(z), + RR(std::acos(r)), + RR(-boost::math::constants::pi()/2), + RR(boost::math::constants::pi()/2), + NTL::RR::precision()); + } + + struct atan_root + { + atan_root(RR const& target) : t(target){} + + boost::math::tuple operator()(RR const& p) + { + RR c = cos(p); + RR ta = tan(p); + RR f0 = ta - t; + RR f1 = 1 / (c * c); + RR f2 = 2 * ta / (c * c); + return boost::math::make_tuple(f0, f1, f2); + } + private: + RR t; + }; + + inline RR atan(RR z) + { + double r; + conv(r, z.value()); + return boost::math::tools::halley_iterate( + atan_root(z), + RR(std::atan(r)), + -boost::math::constants::pi()/2, + boost::math::constants::pi()/2, + NTL::RR::precision()); + } + + inline RR atan2(RR y, RR x) + { + if(x > 0) + return atan(y / x); + if(x < 0) + { + return y < 0 ? atan(y / x) - boost::math::constants::pi() : atan(y / x) + boost::math::constants::pi(); + } + return y < 0 ? -boost::math::constants::half_pi() : boost::math::constants::half_pi() ; + } + + inline RR sinh(RR z) + { + return (expm1(z.value()) - expm1(-z.value())) / 2; + } + + inline RR cosh(RR z) + { + return (exp(z) + exp(-z)) / 2; + } + + inline RR tanh(RR z) + { + return sinh(z) / cosh(z); + } + + inline RR fmod(RR x, RR y) + { + // This is a really crummy version of fmod, we rely on lots + // of digits to get us out of trouble... + RR factor = floor(x/y); + return x - factor * y; + } + + template + inline int iround(RR const& x, const Policy& pol) + { + return tools::real_cast(round(x, pol)); + } + + template + inline long lround(RR const& x, const Policy& pol) + { + return tools::real_cast(round(x, pol)); + } + + template + inline long long llround(RR const& x, const Policy& pol) + { + return tools::real_cast(round(x, pol)); + } + + template + inline int itrunc(RR const& x, const Policy& pol) + { + return tools::real_cast(trunc(x, pol)); + } + + template + inline long ltrunc(RR const& x, const Policy& pol) + { + return tools::real_cast(trunc(x, pol)); + } + + template + inline long long lltrunc(RR const& x, const Policy& pol) + { + return tools::real_cast(trunc(x, pol)); + } + +} // namespace ntl + +namespace detail{ + +template +ntl::RR digamma_imp(ntl::RR x, const std::integral_constant* , const Policy& pol) +{ + // + // This handles reflection of negative arguments, and all our + // error handling, then forwards to the T-specific approximation. + // + BOOST_MATH_STD_USING // ADL of std functions. + + ntl::RR result = 0; + // + // Check for negative arguments and use reflection: + // + if(x < 0) + { + // Reflect: + x = 1 - x; + // Argument reduction for tan: + ntl::RR remainder = x - floor(x); + // Shift to negative if > 0.5: + if(remainder > 0.5) + { + remainder -= 1; + } + // + // check for evaluation at a negative pole: + // + if(remainder == 0) + { + return policies::raise_pole_error("boost::math::digamma<%1%>(%1%)", nullptr, (1-x), pol); + } + result = constants::pi() / tan(constants::pi() * remainder); + } + result += big_digamma(x); + return result; +} + +} // namespace detail + +} // namespace math +} // namespace boost + +#endif // BOOST_MATH_REAL_CONCEPT_HPP + + diff --git a/libcxx/src/third-party/boost/math/ccmath/abs.hpp b/libcxx/src/third-party/boost/math/ccmath/abs.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/ccmath/abs.hpp @@ -0,0 +1,87 @@ +// (C) Copyright Matt Borland 2021. +// 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) +// +// Constepxr implementation of abs (see c.math.abs secion 26.8.2 of the ISO standard) + +#ifndef BOOST_MATH_CCMATH_ABS +#define BOOST_MATH_CCMATH_ABS + +#include +#include +#include +#include +#include +#include +#include + +namespace boost::math::ccmath { + +namespace detail { + +template +constexpr T abs_impl(T x) noexcept +{ + if (boost::math::ccmath::isnan(x)) + { + return std::numeric_limits::quiet_NaN(); + } + else if (x == static_cast(-0)) + { + return static_cast(0); + } + + if constexpr (std::is_integral_v) + { + BOOST_MATH_ASSERT(x != (std::numeric_limits::min)()); + } + + return x >= 0 ? x : -x; +} + +} // Namespace detail + +template , bool> = true> +constexpr T abs(T x) noexcept +{ + if(BOOST_MATH_IS_CONSTANT_EVALUATED(x)) + { + return detail::abs_impl(x); + } + else + { + using std::abs; + return abs(x); + } +} + +// If abs() is called with an argument of type X for which is_unsigned_v is true and if X +// cannot be converted to int by integral promotion (7.3.7), the program is ill-formed. +template , bool> = true> +constexpr T abs(T x) noexcept +{ + if constexpr (std::is_convertible_v) + { + return detail::abs_impl(static_cast(x)); + } + else + { + static_assert(sizeof(T) == 0, "Taking the absolute value of an unsigned value not covertible to int is UB."); + return T(0); // Unreachable, but suppresses warnings + } +} + +constexpr long int labs(long int j) noexcept +{ + return boost::math::ccmath::abs(j); +} + +constexpr long long int llabs(long long int j) noexcept +{ + return boost::math::ccmath::abs(j); +} + +} // Namespaces + +#endif // BOOST_MATH_CCMATH_ABS diff --git a/libcxx/src/third-party/boost/math/ccmath/ccmath.hpp b/libcxx/src/third-party/boost/math/ccmath/ccmath.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/ccmath/ccmath.hpp @@ -0,0 +1,45 @@ +// (C) Copyright Matt Borland 2021 - 2022. +// 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_CCMATH_HPP +#define BOOST_MATH_CCMATH_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif // BOOST_MATH_CCMATH_HPP diff --git a/libcxx/src/third-party/boost/math/ccmath/ceil.hpp b/libcxx/src/third-party/boost/math/ccmath/ceil.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/ccmath/ceil.hpp @@ -0,0 +1,75 @@ +// (C) Copyright Matt Borland 2021. +// 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_CCMATH_CEIL_HPP +#define BOOST_MATH_CCMATH_CEIL_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace boost::math::ccmath { + +namespace detail { + +template +inline constexpr T ceil_impl(T arg) noexcept +{ + T result = boost::math::ccmath::floor(arg); + + if(result == arg) + { + return result; + } + else + { + return result + 1; + } +} + +} // Namespace detail + +template , bool> = true> +inline constexpr Real ceil(Real arg) noexcept +{ + if(BOOST_MATH_IS_CONSTANT_EVALUATED(arg)) + { + return boost::math::ccmath::abs(arg) == Real(0) ? arg : + boost::math::ccmath::isinf(arg) ? arg : + boost::math::ccmath::isnan(arg) ? arg : + boost::math::ccmath::detail::ceil_impl(arg); + } + else + { + using std::ceil; + return ceil(arg); + } +} + +template , bool> = true> +inline constexpr double ceil(Z arg) noexcept +{ + return boost::math::ccmath::ceil(static_cast(arg)); +} + +inline constexpr float ceilf(float arg) noexcept +{ + return boost::math::ccmath::ceil(arg); +} + +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS +inline constexpr long double ceill(long double arg) noexcept +{ + return boost::math::ccmath::ceil(arg); +} +#endif + +} // Namespaces + +#endif // BOOST_MATH_CCMATH_CEIL_HPP diff --git a/libcxx/src/third-party/boost/math/ccmath/copysign.hpp b/libcxx/src/third-party/boost/math/ccmath/copysign.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/ccmath/copysign.hpp @@ -0,0 +1,81 @@ +// (C) Copyright Matt Borland 2021. +// 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_CCMATH_COPYSIGN_HPP +#define BOOST_MATH_CCMATH_COPYSIGN_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost::math::ccmath { + +namespace detail { + +template +constexpr T copysign_impl(const T mag, const T sgn) noexcept +{ + if (boost::math::ccmath::signbit(sgn)) + { + return -boost::math::ccmath::abs(mag); + } + else + { + return boost::math::ccmath::abs(mag); + } +} + +} // Namespace detail + +template , bool> = true> +constexpr Real copysign(Real mag, Real sgn) noexcept +{ + if(BOOST_MATH_IS_CONSTANT_EVALUATED(mag)) + { + return boost::math::ccmath::detail::copysign_impl(mag, sgn); + } + else + { + using std::copysign; + return copysign(mag, sgn); + } +} + +template +constexpr auto copysign(T1 mag, T2 sgn) noexcept +{ + if (BOOST_MATH_IS_CONSTANT_EVALUATED(mag)) + { + using promoted_type = boost::math::tools::promote_args_2_t; + return boost::math::ccmath::copysign(static_cast(mag), static_cast(sgn)); + } + else + { + using std::copysign; + return copysign(mag, sgn); + } +} + +constexpr float copysignf(float mag, float sgn) noexcept +{ + return boost::math::ccmath::copysign(mag, sgn); +} + +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS +constexpr long double copysignl(long double mag, long double sgn) noexcept +{ + return boost::math::ccmath::copysign(mag, sgn); +} +#endif + +} // Namespaces + +#endif // BOOST_MATH_CCMATH_COPYSIGN_HPP diff --git a/libcxx/src/third-party/boost/math/ccmath/detail/swap.hpp b/libcxx/src/third-party/boost/math/ccmath/detail/swap.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/ccmath/detail/swap.hpp @@ -0,0 +1,21 @@ +// (C) Copyright Matt Borland 2021. +// 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_CCMATH_DETAIL_SWAP_HPP +#define BOOST_MATH_CCMATH_DETAIL_SWAP_HPP + +namespace boost::math::ccmath::detail { + +template +inline constexpr void swap(T& x, T& y) noexcept +{ + T temp = x; + x = y; + y = temp; +} + +} + +#endif // BOOST_MATH_CCMATH_DETAIL_SWAP_HPP diff --git a/libcxx/src/third-party/boost/math/ccmath/div.hpp b/libcxx/src/third-party/boost/math/ccmath/div.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/ccmath/div.hpp @@ -0,0 +1,84 @@ +// (C) Copyright Matt Borland 2021. +// 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_CCMATH_DIV_HPP +#define BOOST_MATH_CCMATH_DIV_HPP + +#include +#include +#include +#include +#include + +namespace boost::math::ccmath { + +namespace detail { + +template +inline constexpr ReturnType div_impl(const Z x, const Z y) noexcept +{ + // std::div_t/ldiv_t/lldiv_t/imaxdiv_t can be defined as either { Z quot; Z rem; }; or { Z rem; Z quot; }; + // so don't use braced initialziation to guarantee compatibility + ReturnType ans {0, 0}; + + ans.quot = x / y; + ans.rem = x % y; + + return ans; +} + +} // Namespace detail + +// Used for types other than built-ins (e.g. boost multiprecision) +template +struct div_t +{ + Z quot; + Z rem; +}; + +template +inline constexpr auto div(Z x, Z y) noexcept +{ + if constexpr (std::is_same_v) + { + return detail::div_impl(x, y); + } + else if constexpr (std::is_same_v) + { + return detail::div_impl(x, y); + } + else if constexpr (std::is_same_v) + { + return detail::div_impl(x, y); + } + else if constexpr (std::is_same_v) + { + return detail::div_impl(x, y); + } + else + { + return detail::div_impl>(x, y); + } +} + +inline constexpr std::ldiv_t ldiv(long x, long y) noexcept +{ + return detail::div_impl(x, y); +} + +inline constexpr std::lldiv_t lldiv(long long x, long long y) noexcept +{ + return detail::div_impl(x, y); +} + +inline constexpr std::imaxdiv_t imaxdiv(std::intmax_t x, std::intmax_t y) noexcept +{ + return detail::div_impl(x, y); +} + +} // Namespaces + +#endif // BOOST_MATH_CCMATH_DIV_HPP diff --git a/libcxx/src/third-party/boost/math/ccmath/fabs.hpp b/libcxx/src/third-party/boost/math/ccmath/fabs.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/ccmath/fabs.hpp @@ -0,0 +1,35 @@ +// (C) Copyright Matt Borland 2021. +// 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) +// +// Constepxr implementation of fabs (see c.math.abs secion 26.8.2 of the ISO standard) + +#ifndef BOOST_MATH_CCMATH_FABS +#define BOOST_MATH_CCMATH_FABS + +#include + +namespace boost::math::ccmath { + +template +inline constexpr auto fabs(T x) noexcept +{ + return boost::math::ccmath::abs(x); +} + +inline constexpr float fabsf(float x) noexcept +{ + return boost::math::ccmath::abs(x); +} + +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS +inline constexpr long double fabsl(long double x) noexcept +{ + return boost::math::ccmath::abs(x); +} +#endif + +} + +#endif // BOOST_MATH_CCMATH_FABS diff --git a/libcxx/src/third-party/boost/math/ccmath/fdim.hpp b/libcxx/src/third-party/boost/math/ccmath/fdim.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/ccmath/fdim.hpp @@ -0,0 +1,100 @@ +// (C) Copyright Matt Borland 2022. +// 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_CCMATH_FDIM_HPP +#define BOOST_MATH_CCMATH_FDIM_HPP + +#include +#include +#include +#include +#include + +namespace boost::math::ccmath { + +namespace detail { + +template +inline constexpr T fdim_impl(const T x, const T y) noexcept +{ + if (x <= y) + { + return 0; + } + else if ((y < 0) && (x > (std::numeric_limits::max)() + y)) + { + return std::numeric_limits::infinity(); + } + else + { + return x - y; + } +} + +} // Namespace detail + +template , bool> = true> +inline constexpr Real fdim(Real x, Real y) noexcept +{ + if (BOOST_MATH_IS_CONSTANT_EVALUATED(x)) + { + return boost::math::ccmath::isnan(x) ? std::numeric_limits::quiet_NaN() : + boost::math::ccmath::isnan(y) ? std::numeric_limits::quiet_NaN() : + boost::math::ccmath::detail::fdim_impl(x, y); + } + else + { + using std::fdim; + return fdim(x, y); + } +} + +template +inline constexpr auto fdim(T1 x, T2 y) noexcept +{ + if (BOOST_MATH_IS_CONSTANT_EVALUATED(x)) + { + // If the type is an integer (e.g. epsilon == 0) then set the epsilon value to 1 so that type is at a minimum + // cast to double + constexpr auto T1p = std::numeric_limits::epsilon() > 0 ? std::numeric_limits::epsilon() : 1; + constexpr auto T2p = std::numeric_limits::epsilon() > 0 ? std::numeric_limits::epsilon() : 1; + + using promoted_type = + #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + std::conditional_t>>>; + #else + >>; + #endif + + return boost::math::ccmath::fdim(promoted_type(x), promoted_type(y)); + } + else + { + using std::fdim; + return fdim(x, y); + } +} + +inline constexpr float fdimf(float x, float y) noexcept +{ + return boost::math::ccmath::fdim(x, y); +} + +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS +inline constexpr long double fdiml(long double x, long double y) noexcept +{ + return boost::math::ccmath::fdim(x, y); +} +#endif + +} // Namespace boost::math::ccmath + +#endif // BOOST_MATH_CCMATH_FDIM_HPP diff --git a/libcxx/src/third-party/boost/math/ccmath/floor.hpp b/libcxx/src/third-party/boost/math/ccmath/floor.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/ccmath/floor.hpp @@ -0,0 +1,121 @@ +// (C) Copyright Matt Borland 2021. +// 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_CCMATH_FLOOR_HPP +#define BOOST_MATH_CCMATH_FLOOR_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace boost::math::ccmath { + +namespace detail { + +template +inline constexpr T floor_pos_impl(T arg) noexcept +{ + T result = 1; + + if(result < arg) + { + while(result < arg) + { + result *= 2; + } + while(result > arg) + { + --result; + } + + return result; + } + else + { + return T(0); + } +} + +template +inline constexpr T floor_neg_impl(T arg) noexcept +{ + T result = -1; + + if(result > arg) + { + while(result > arg) + { + result *= 2; + } + while(result < arg) + { + ++result; + } + if(result != arg) + { + --result; + } + } + + return result; +} + +template +inline constexpr T floor_impl(T arg) noexcept +{ + if(arg > 0) + { + return floor_pos_impl(arg); + } + else + { + return floor_neg_impl(arg); + } +} + +} // Namespace detail + +template , bool> = true> +inline constexpr Real floor(Real arg) noexcept +{ + if(BOOST_MATH_IS_CONSTANT_EVALUATED(arg)) + { + return boost::math::ccmath::abs(arg) == Real(0) ? arg : + boost::math::ccmath::isinf(arg) ? arg : + boost::math::ccmath::isnan(arg) ? arg : + boost::math::ccmath::detail::floor_impl(arg); + } + else + { + using std::floor; + return floor(arg); + } +} + +template , bool> = true> +inline constexpr double floor(Z arg) noexcept +{ + return boost::math::ccmath::floor(static_cast(arg)); +} + +inline constexpr float floorf(float arg) noexcept +{ + return boost::math::ccmath::floor(arg); +} + +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS +inline constexpr long double floorl(long double arg) noexcept +{ + return boost::math::ccmath::floor(arg); +} +#endif + +} // Namespaces + +#endif // BOOST_MATH_CCMATH_FLOOR_HPP diff --git a/libcxx/src/third-party/boost/math/ccmath/fma.hpp b/libcxx/src/third-party/boost/math/ccmath/fma.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/ccmath/fma.hpp @@ -0,0 +1,128 @@ +// (C) Copyright Matt Borland 2022. +// 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_CCMATH_FMA_HPP +#define BOOST_MATH_CCMATH_FMA_HPP + +#include +#include +#include +#include +#include +#include + +namespace boost::math::ccmath { + +namespace detail { + +template +constexpr T fma_imp(const T x, const T y, const T z) noexcept +{ + #if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER) && !defined(__INTEL_LLVM_COMPILER) + if constexpr (std::is_same_v) + { + return __builtin_fmaf(x, y, z); + } + else if constexpr (std::is_same_v) + { + return __builtin_fma(x, y, z); + } + else if constexpr (std::is_same_v) + { + return __builtin_fmal(x, y, z); + } + #endif + + // If we can't use compiler intrinsics hope that -fma flag optimizes this call to fma instruction + return (x * y) + z; +} + +} // Namespace detail + +template , bool> = true> +constexpr Real fma(Real x, Real y, Real z) noexcept +{ + if (BOOST_MATH_IS_CONSTANT_EVALUATED(x)) + { + if (x == 0 && boost::math::ccmath::isinf(y)) + { + return std::numeric_limits::quiet_NaN(); + } + else if (y == 0 && boost::math::ccmath::isinf(x)) + { + return std::numeric_limits::quiet_NaN(); + } + else if (boost::math::ccmath::isnan(x)) + { + return std::numeric_limits::quiet_NaN(); + } + else if (boost::math::ccmath::isnan(y)) + { + return std::numeric_limits::quiet_NaN(); + } + else if (boost::math::ccmath::isnan(z)) + { + return std::numeric_limits::quiet_NaN(); + } + + return boost::math::ccmath::detail::fma_imp(x, y, z); + } + else + { + using std::fma; + return fma(x, y, z); + } +} + +template +constexpr auto fma(T1 x, T2 y, T3 z) noexcept +{ + if (BOOST_MATH_IS_CONSTANT_EVALUATED(x)) + { + // If the type is an integer (e.g. epsilon == 0) then set the epsilon value to 1 so that type is at a minimum + // cast to double + constexpr auto T1p = std::numeric_limits::epsilon() > 0 ? std::numeric_limits::epsilon() : 1; + constexpr auto T2p = std::numeric_limits::epsilon() > 0 ? std::numeric_limits::epsilon() : 1; + constexpr auto T3p = std::numeric_limits::epsilon() > 0 ? std::numeric_limits::epsilon() : 1; + + using promoted_type = + #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + std::conditional_t>>>>>; + #else + >>>; + #endif + + return boost::math::ccmath::fma(promoted_type(x), promoted_type(y), promoted_type(z)); + } + else + { + using std::fma; + return fma(x, y, z); + } +} + +constexpr float fmaf(float x, float y, float z) noexcept +{ + return boost::math::ccmath::fma(x, y, z); +} + +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS +constexpr long double fmal(long double x, long double y, long double z) noexcept +{ + return boost::math::ccmath::fma(x, y, z); +} +#endif + +} // Namespace boost::math::ccmath + +#endif // BOOST_MATH_CCMATH_FMA_HPP diff --git a/libcxx/src/third-party/boost/math/ccmath/fmax.hpp b/libcxx/src/third-party/boost/math/ccmath/fmax.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/ccmath/fmax.hpp @@ -0,0 +1,97 @@ +// (C) Copyright Matt Borland 2022. +// 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_CCMATH_FMAX_HPP +#define BOOST_MATH_CCMATH_FMAX_HPP + +#include +#include +#include +#include +#include + +namespace boost::math::ccmath { + +namespace detail { + +template +inline constexpr T fmax_impl(const T x, const T y) noexcept +{ + if (x > y) + { + return x; + } + else + { + return y; + } +} + +} // Namespace detail + +template , bool> = true> +inline constexpr Real fmax(Real x, Real y) noexcept +{ + if (BOOST_MATH_IS_CONSTANT_EVALUATED(x)) + { + return boost::math::ccmath::isnan(x) && boost::math::ccmath::isnan(y) ? std::numeric_limits::quiet_NaN() : + boost::math::ccmath::isnan(x) ? y : + boost::math::ccmath::isnan(y) ? x : + boost::math::ccmath::detail::fmax_impl(x, y); + } + else + { + using std::fmax; + return fmax(x, y); + } +} + +template +inline constexpr auto fmax(T1 x, T2 y) noexcept +{ + if (BOOST_MATH_IS_CONSTANT_EVALUATED(x)) + { + // If the type is an integer (e.g. epsilon == 0) then set the epsilon value to 1 so that type is at a minimum + // cast to double + constexpr auto T1p = std::numeric_limits::epsilon() > 0 ? std::numeric_limits::epsilon() : 1; + constexpr auto T2p = std::numeric_limits::epsilon() > 0 ? std::numeric_limits::epsilon() : 1; + + using promoted_type = + #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + std::conditional_t>>>; + #else + >>; + #endif + + return boost::math::ccmath::fmax(promoted_type(x), promoted_type(y)); + } + else + { + using std::fmax; + return fmax(x, y); + } +} + +inline constexpr float fmaxf(float x, float y) noexcept +{ + return boost::math::ccmath::fmax(x, y); +} + +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS +inline constexpr long double fmaxl(long double x, long double y) noexcept +{ + return boost::math::ccmath::fmax(x, y); +} +#endif + +} // Namespace boost::math::ccmath + +#endif // BOOST_MATH_CCMATH_FMAX_HPP diff --git a/libcxx/src/third-party/boost/math/ccmath/fmin.hpp b/libcxx/src/third-party/boost/math/ccmath/fmin.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/ccmath/fmin.hpp @@ -0,0 +1,97 @@ +// (C) Copyright Matt Borland 2022. +// 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_CCMATH_FMIN_HPP +#define BOOST_MATH_CCMATH_FMIN_HPP + +#include +#include +#include +#include +#include + +namespace boost::math::ccmath { + +namespace detail { + +template +inline constexpr T fmin_impl(const T x, const T y) noexcept +{ + if (x < y) + { + return x; + } + else + { + return y; + } +} + +} // Namespace detail + +template , bool> = true> +inline constexpr Real fmin(Real x, Real y) noexcept +{ + if (BOOST_MATH_IS_CONSTANT_EVALUATED(x)) + { + return boost::math::ccmath::isnan(x) && boost::math::ccmath::isnan(y) ? std::numeric_limits::quiet_NaN() : + boost::math::ccmath::isnan(x) ? y : + boost::math::ccmath::isnan(y) ? x : + boost::math::ccmath::detail::fmin_impl(x, y); + } + else + { + using std::fmin; + return fmin(x, y); + } +} + +template +inline constexpr auto fmin(T1 x, T2 y) noexcept +{ + if (BOOST_MATH_IS_CONSTANT_EVALUATED(x)) + { + // If the type is an integer (e.g. epsilon == 0) then set the epsilon value to 1 so that type is at a minimum + // cast to double + constexpr auto T1p = std::numeric_limits::epsilon() > 0 ? std::numeric_limits::epsilon() : 1; + constexpr auto T2p = std::numeric_limits::epsilon() > 0 ? std::numeric_limits::epsilon() : 1; + + using promoted_type = + #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + std::conditional_t>>>; + #else + >>; + #endif + + return boost::math::ccmath::fmin(promoted_type(x), promoted_type(y)); + } + else + { + using std::fmin; + return fmin(x, y); + } +} + +inline constexpr float fminf(float x, float y) noexcept +{ + return boost::math::ccmath::fmin(x, y); +} + +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS +inline constexpr long double fminl(long double x, long double y) noexcept +{ + return boost::math::ccmath::fmin(x, y); +} +#endif + +} // Namespace boost::math::ccmath + +#endif // BOOST_MATH_CCMATH_FMIN_HPP diff --git a/libcxx/src/third-party/boost/math/ccmath/fmod.hpp b/libcxx/src/third-party/boost/math/ccmath/fmod.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/ccmath/fmod.hpp @@ -0,0 +1,112 @@ +// (C) Copyright Matt Borland 2021 - 2022. +// 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_CCMATH_FMOD_HPP +#define BOOST_MATH_CCMATH_FMOD_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost::math::ccmath { + +namespace detail { + +template +constexpr T fmod_impl(T x, T y) +{ + if (x == y) + { + return static_cast(0); + } + else + { + while (x >= y) + { + x -= y; + } + + return static_cast(x); + } +} + +} // Namespace detail + +template , bool> = true> +constexpr Real fmod(Real x, Real y) +{ + if(BOOST_MATH_IS_CONSTANT_EVALUATED(x)) + { + if (boost::math::ccmath::abs(x) == static_cast(0) && y != static_cast(0)) + { + return x; + } + else if (boost::math::ccmath::isinf(x) && !boost::math::ccmath::isnan(y)) + { + return std::numeric_limits::quiet_NaN(); + } + else if (boost::math::ccmath::abs(y) == static_cast(0) && !boost::math::ccmath::isnan(x)) + { + return std::numeric_limits::quiet_NaN(); + } + else if (boost::math::ccmath::isinf(y) && boost::math::ccmath::isfinite(x)) + { + return x; + } + else if (boost::math::ccmath::isnan(x)) + { + return x; + } + else if (boost::math::ccmath::isnan(y)) + { + return y; + } + + return boost::math::ccmath::detail::fmod_impl(x, y); + } + else + { + using std::fmod; + return fmod(x, y); + } +} + +template +constexpr auto fmod(T1 x, T2 y) +{ + if(BOOST_MATH_IS_CONSTANT_EVALUATED(x)) + { + using promoted_type = boost::math::tools::promote_args_t; + return boost::math::ccmath::fmod(promoted_type(x), promoted_type(y)); + } + else + { + using std::fmod; + return fmod(x, y); + } +} + +constexpr float fmodf(float x, float y) +{ + return boost::math::ccmath::fmod(x, y); +} + +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS +constexpr long double fmodl(long double x, long double y) +{ + return boost::math::ccmath::fmod(x, y); +} +#endif + +} // Namespaces + +#endif // BOOST_MATH_CCMATH_FMOD_HPP diff --git a/libcxx/src/third-party/boost/math/ccmath/fpclassify.hpp b/libcxx/src/third-party/boost/math/ccmath/fpclassify.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/ccmath/fpclassify.hpp @@ -0,0 +1,45 @@ +// (C) Copyright Matt Borland 2021. +// 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_CCMATH_FPCLASSIFY +#define BOOST_MATH_CCMATH_FPCLASSIFY + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost::math::ccmath { + +template , bool> = true> +inline constexpr int fpclassify(T x) +{ + if(BOOST_MATH_IS_CONSTANT_EVALUATED(x)) + { + return boost::math::ccmath::isnan(x) ? FP_NAN : + boost::math::ccmath::isinf(x) ? FP_INFINITE : + boost::math::ccmath::abs(x) == T(0) ? FP_ZERO : + boost::math::ccmath::abs(x) > 0 && boost::math::ccmath::abs(x) < (std::numeric_limits::min)() ? FP_SUBNORMAL : FP_NORMAL; + } + else + { + using std::fpclassify; + return fpclassify(x); + } +} + +template , bool> = true> +inline constexpr int fpclassify(Z x) +{ + return boost::math::ccmath::fpclassify(static_cast(x)); +} + +} + +#endif // BOOST_MATH_CCMATH_FPCLASSIFY diff --git a/libcxx/src/third-party/boost/math/ccmath/frexp.hpp b/libcxx/src/third-party/boost/math/ccmath/frexp.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/ccmath/frexp.hpp @@ -0,0 +1,98 @@ +// (C) Copyright Christopher Kormanyos 1999 - 2021. +// (C) Copyright Matt Borland 2021. +// 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_CCMATH_FREXP_HPP +#define BOOST_MATH_CCMATH_FREXP_HPP + +#include +#include +#include +#include +#include +#include + +namespace boost::math::ccmath { + +namespace detail +{ + +template +inline constexpr Real frexp_zero_impl(Real arg, int* exp) +{ + *exp = 0; + return arg; +} + +template +inline constexpr Real frexp_impl(Real arg, int* exp) +{ + const bool negative_arg = (arg < Real(0)); + + Real f = negative_arg ? -arg : arg; + int e2 = 0; + constexpr Real two_pow_32 = Real(4294967296); + + while (f >= two_pow_32) + { + f = f / two_pow_32; + e2 += 32; + } + + while(f >= Real(1)) + { + f = f / Real(2); + ++e2; + } + + if(exp != nullptr) + { + *exp = e2; + } + + return !negative_arg ? f : -f; +} + +} // namespace detail + +template , bool> = true> +inline constexpr Real frexp(Real arg, int* exp) +{ + if(BOOST_MATH_IS_CONSTANT_EVALUATED(arg)) + { + return arg == Real(0) ? detail::frexp_zero_impl(arg, exp) : + arg == Real(-0) ? detail::frexp_zero_impl(arg, exp) : + boost::math::ccmath::isinf(arg) ? detail::frexp_zero_impl(arg, exp) : + boost::math::ccmath::isnan(arg) ? detail::frexp_zero_impl(arg, exp) : + boost::math::ccmath::detail::frexp_impl(arg, exp); + } + else + { + using std::frexp; + return frexp(arg, exp); + } +} + +template , bool> = true> +inline constexpr double frexp(Z arg, int* exp) +{ + return boost::math::ccmath::frexp(static_cast(arg), exp); +} + +inline constexpr float frexpf(float arg, int* exp) +{ + return boost::math::ccmath::frexp(arg, exp); +} + +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS +inline constexpr long double frexpl(long double arg, int* exp) +{ + return boost::math::ccmath::frexp(arg, exp); +} +#endif + +} + +#endif // BOOST_MATH_CCMATH_FREXP_HPP diff --git a/libcxx/src/third-party/boost/math/ccmath/hypot.hpp b/libcxx/src/third-party/boost/math/ccmath/hypot.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/ccmath/hypot.hpp @@ -0,0 +1,114 @@ +// (C) Copyright John Maddock 2005-2021. +// (C) Copyright Matt Borland 2021. +// 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_CCMATH_HYPOT_HPP +#define BOOST_MATH_CCMATH_HYPOT_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost::math::ccmath { + +namespace detail { + +template +inline constexpr T hypot_impl(T x, T y) noexcept +{ + x = boost::math::ccmath::abs(x); + y = boost::math::ccmath::abs(y); + + if (y > x) + { + boost::math::ccmath::detail::swap(x, y); + } + + if(x * std::numeric_limits::epsilon() >= y) + { + return x; + } + + T rat = y / x; + return x * boost::math::ccmath::sqrt(1 + rat * rat); +} + +} // Namespace detail + +template , bool> = true> +inline constexpr Real hypot(Real x, Real y) noexcept +{ + if(BOOST_MATH_IS_CONSTANT_EVALUATED(x)) + { + return boost::math::ccmath::abs(x) == Real(0) ? boost::math::ccmath::abs(y) : + boost::math::ccmath::abs(y) == Real(0) ? boost::math::ccmath::abs(x) : + boost::math::ccmath::isinf(x) ? std::numeric_limits::infinity() : + boost::math::ccmath::isinf(y) ? std::numeric_limits::infinity() : + boost::math::ccmath::isnan(x) ? std::numeric_limits::quiet_NaN() : + boost::math::ccmath::isnan(y) ? std::numeric_limits::quiet_NaN() : + boost::math::ccmath::detail::hypot_impl(x, y); + } + else + { + using std::hypot; + return hypot(x, y); + } +} + +template +inline constexpr auto hypot(T1 x, T2 y) noexcept +{ + if(BOOST_MATH_IS_CONSTANT_EVALUATED(x)) + { + // If the type is an integer (e.g. epsilon == 0) then set the epsilon value to 1 so that type is at a minimum + // cast to double + constexpr auto T1p = std::numeric_limits::epsilon() > 0 ? std::numeric_limits::epsilon() : 1; + constexpr auto T2p = std::numeric_limits::epsilon() > 0 ? std::numeric_limits::epsilon() : 1; + + using promoted_type = + #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + std::conditional_t>>>; + #else + >>; + #endif + + return boost::math::ccmath::hypot(promoted_type(x), promoted_type(y)); + } + else + { + using std::hypot; + return hypot(x, y); + } +} + +inline constexpr float hypotf(float x, float y) noexcept +{ + return boost::math::ccmath::hypot(x, y); +} + +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS +inline constexpr long double hypotl(long double x, long double y) noexcept +{ + return boost::math::ccmath::hypot(x, y); +} +#endif + +} // Namespaces + +#endif // BOOST_MATH_CCMATH_HYPOT_HPP diff --git a/libcxx/src/third-party/boost/math/ccmath/ilogb.hpp b/libcxx/src/third-party/boost/math/ccmath/ilogb.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/ccmath/ilogb.hpp @@ -0,0 +1,57 @@ +// (C) Copyright Matt Borland 2021. +// 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_CCMATH_ILOGB_HPP +#define BOOST_MATH_CCMATH_ILOGB_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace boost::math::ccmath { + +// If arg is not zero, infinite, or NaN, the value returned is exactly equivalent to static_cast(std::logb(arg)) +template , bool> = true> +inline constexpr int ilogb(Real arg) noexcept +{ + if(BOOST_MATH_IS_CONSTANT_EVALUATED(arg)) + { + return boost::math::ccmath::abs(arg) == Real(0) ? FP_ILOGB0 : + boost::math::ccmath::isinf(arg) ? INT_MAX : + boost::math::ccmath::isnan(arg) ? FP_ILOGBNAN : + static_cast(boost::math::ccmath::logb(arg)); + } + else + { + using std::ilogb; + return ilogb(arg); + } +} + +template , bool> = true> +inline constexpr int ilogb(Z arg) noexcept +{ + return boost::math::ccmath::ilogb(static_cast(arg)); +} + +inline constexpr int ilogbf(float arg) noexcept +{ + return boost::math::ccmath::ilogb(arg); +} + +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS +inline constexpr int ilogbl(long double arg) noexcept +{ + return boost::math::ccmath::ilogb(arg); +} +#endif + +} // Namespaces + +#endif // BOOST_MATH_CCMATH_ILOGB_HPP diff --git a/libcxx/src/third-party/boost/math/ccmath/isfinite.hpp b/libcxx/src/third-party/boost/math/ccmath/isfinite.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/ccmath/isfinite.hpp @@ -0,0 +1,50 @@ +// (C) Copyright Matt Borland 2021. +// 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_CCMATH_ISFINITE +#define BOOST_MATH_CCMATH_ISFINITE + +#include +#include +#include +#include +#include + +namespace boost::math::ccmath { + +template +inline constexpr bool isfinite(T x) +{ + if(BOOST_MATH_IS_CONSTANT_EVALUATED(x)) + { + // bool isfinite (IntegralType arg) is a set of overloads accepting the arg argument of any integral type + // equivalent to casting the integral argument arg to double (e.g. static_cast(arg)) + if constexpr (std::is_integral_v) + { + return !boost::math::ccmath::isinf(static_cast(x)) && !boost::math::ccmath::isnan(static_cast(x)); + } + else + { + return !boost::math::ccmath::isinf(x) && !boost::math::ccmath::isnan(x); + } + } + else + { + using std::isfinite; + + if constexpr (!std::is_integral_v) + { + return isfinite(x); + } + else + { + return isfinite(static_cast(x)); + } + } +} + +} + +#endif // BOOST_MATH_CCMATH_ISFINITE diff --git a/libcxx/src/third-party/boost/math/ccmath/isgreater.hpp b/libcxx/src/third-party/boost/math/ccmath/isgreater.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/ccmath/isgreater.hpp @@ -0,0 +1,39 @@ +// (C) Copyright Matt Borland 2022. +// 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_CCMATH_ISGREATER_HPP +#define BOOST_MATH_CCMATH_ISGREATER_HPP + +#include +#include +#include +#include + +namespace boost::math::ccmath { + +template +inline constexpr bool isgreater(T1 x, T2 y) noexcept +{ + if (BOOST_MATH_IS_CONSTANT_EVALUATED(x)) + { + if (boost::math::ccmath::isnan(x) || boost::math::ccmath::isnan(y)) + { + return false; + } + else + { + return x > y; + } + } + else + { + using std::isgreater; + return isgreater(x, y); + } +} + +} // Namespaces + +#endif // BOOST_MATH_CCMATH_ISGREATER_HPP diff --git a/libcxx/src/third-party/boost/math/ccmath/isgreaterequal.hpp b/libcxx/src/third-party/boost/math/ccmath/isgreaterequal.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/ccmath/isgreaterequal.hpp @@ -0,0 +1,39 @@ +// (C) Copyright Matt Borland 2022. +// 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_CCMATH_ISGREATEREQUAL_HPP +#define BOOST_MATH_CCMATH_ISGREATEREQUAL_HPP + +#include +#include +#include +#include + +namespace boost::math::ccmath { + +template +inline constexpr bool isgreaterequal(T1 x, T2 y) noexcept +{ + if (BOOST_MATH_IS_CONSTANT_EVALUATED(x)) + { + if (boost::math::ccmath::isnan(x) || boost::math::ccmath::isnan(y)) + { + return false; + } + else + { + return x >= y; + } + } + else + { + using std::isgreaterequal; + return isgreaterequal(x, y); + } +} + +} // Namespaces + +#endif // BOOST_MATH_CCMATH_ISGREATEREQUAL_HPP diff --git a/libcxx/src/third-party/boost/math/ccmath/isinf.hpp b/libcxx/src/third-party/boost/math/ccmath/isinf.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/ccmath/isinf.hpp @@ -0,0 +1,40 @@ +// (C) Copyright Matt Borland 2021. +// 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_CCMATH_ISINF +#define BOOST_MATH_CCMATH_ISINF + +#include +#include +#include +#include + +namespace boost::math::ccmath { + +template +inline constexpr bool isinf(T x) +{ + if(BOOST_MATH_IS_CONSTANT_EVALUATED(x)) + { + return x == std::numeric_limits::infinity() || -x == std::numeric_limits::infinity(); + } + else + { + using std::isinf; + + if constexpr (!std::is_integral_v) + { + return isinf(x); + } + else + { + return isinf(static_cast(x)); + } + } +} + +} + +#endif // BOOST_MATH_CCMATH_ISINF diff --git a/libcxx/src/third-party/boost/math/ccmath/isless.hpp b/libcxx/src/third-party/boost/math/ccmath/isless.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/ccmath/isless.hpp @@ -0,0 +1,39 @@ +// (C) Copyright Matt Borland 2022. +// 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_CCMATH_ISLESS_HPP +#define BOOST_MATH_CCMATH_ISLESS_HPP + +#include +#include +#include +#include + +namespace boost::math::ccmath { + +template +inline constexpr bool isless(T1 x, T2 y) noexcept +{ + if (BOOST_MATH_IS_CONSTANT_EVALUATED(x)) + { + if (boost::math::ccmath::isnan(x) || boost::math::ccmath::isnan(y)) + { + return false; + } + else + { + return x < y; + } + } + else + { + using std::isless; + return isless(x, y); + } +} + +} // Namespaces + +#endif // BOOST_MATH_CCMATH_ISLESS_HPP diff --git a/libcxx/src/third-party/boost/math/ccmath/islessequal.hpp b/libcxx/src/third-party/boost/math/ccmath/islessequal.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/ccmath/islessequal.hpp @@ -0,0 +1,39 @@ +// (C) Copyright Matt Borland 2022. +// 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_CCMATH_ISLESSEQUAL_HPP +#define BOOST_MATH_CCMATH_ISLESSEQUAL_HPP + +#include +#include +#include +#include + +namespace boost::math::ccmath { + +template +inline constexpr bool islessequal(T1 x, T2 y) noexcept +{ + if (BOOST_MATH_IS_CONSTANT_EVALUATED(x)) + { + if (boost::math::ccmath::isnan(x) || boost::math::ccmath::isnan(y)) + { + return false; + } + else + { + return x <= y; + } + } + else + { + using std::islessequal; + return islessequal(x, y); + } +} + +} // Namespaces + +#endif // BOOST_MATH_CCMATH_ISLESSEQUAL_HPP diff --git a/libcxx/src/third-party/boost/math/ccmath/isnan.hpp b/libcxx/src/third-party/boost/math/ccmath/isnan.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/ccmath/isnan.hpp @@ -0,0 +1,39 @@ +// (C) Copyright Matt Borland 2021. +// 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_CCMATH_ISNAN +#define BOOST_MATH_CCMATH_ISNAN + +#include +#include +#include + +namespace boost::math::ccmath { + +template +inline constexpr bool isnan(T x) +{ + if(BOOST_MATH_IS_CONSTANT_EVALUATED(x)) + { + return x != x; + } + else + { + using std::isnan; + + if constexpr (!std::is_integral_v) + { + return isnan(x); + } + else + { + return isnan(static_cast(x)); + } + } +} + +} + +#endif // BOOST_MATH_CCMATH_ISNAN diff --git a/libcxx/src/third-party/boost/math/ccmath/isnormal.hpp b/libcxx/src/third-party/boost/math/ccmath/isnormal.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/ccmath/isnormal.hpp @@ -0,0 +1,45 @@ +// (C) Copyright Matt Borland 2021. +// 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_ISNORMAL_HPP +#define BOOST_MATH_ISNORMAL_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace boost::math::ccmath { + +template +inline constexpr bool isnormal(T x) +{ + if(BOOST_MATH_IS_CONSTANT_EVALUATED(x)) + { + return x == T(0) ? false : + boost::math::ccmath::isinf(x) ? false : + boost::math::ccmath::isnan(x) ? false : + boost::math::ccmath::abs(x) < (std::numeric_limits::min)() ? false : true; + } + else + { + using std::isnormal; + + if constexpr (!std::is_integral_v) + { + return isnormal(x); + } + else + { + return isnormal(static_cast(x)); + } + } +} +} + +#endif // BOOST_MATH_ISNORMAL_HPP diff --git a/libcxx/src/third-party/boost/math/ccmath/isunordered.hpp b/libcxx/src/third-party/boost/math/ccmath/isunordered.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/ccmath/isunordered.hpp @@ -0,0 +1,31 @@ +// (C) Copyright Matt Borland 2022. +// 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_CCMATH_ISUNORDERED_HPP +#define BOOST_MATH_CCMATH_ISUNORDERED_HPP + +#include +#include +#include + +namespace boost::math::ccmath { + +template +inline constexpr bool isunordered(const T x, const T y) noexcept +{ + if(BOOST_MATH_IS_CONSTANT_EVALUATED(x)) + { + return boost::math::ccmath::isnan(x) || boost::math::ccmath::isnan(y); + } + else + { + using std::isunordered; + return isunordered(x, y); + } +} + +} // Namespaces + +#endif // BOOST_MATH_CCMATH_ISUNORDERED_HPP diff --git a/libcxx/src/third-party/boost/math/ccmath/ldexp.hpp b/libcxx/src/third-party/boost/math/ccmath/ldexp.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/ccmath/ldexp.hpp @@ -0,0 +1,79 @@ +// (C) Copyright Matt Borland 2021. +// (C) Copyright John Maddock 2021. +// 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_CCMATH_LDEXP_HPP +#define BOOST_MATH_CCMATH_LDEXP_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost::math::ccmath { + +namespace detail { + +template +inline constexpr Real ldexp_impl(Real arg, int exp) noexcept +{ + while(exp > 0) + { + arg *= 2; + --exp; + } + while(exp < 0) + { + arg /= 2; + ++exp; + } + + return arg; +} + +} // Namespace detail + +template , bool> = true> +inline constexpr Real ldexp(Real arg, int exp) noexcept +{ + if(BOOST_MATH_IS_CONSTANT_EVALUATED(arg)) + { + return boost::math::ccmath::abs(arg) == Real(0) ? arg : + boost::math::ccmath::isinf(arg) ? arg : + boost::math::ccmath::isnan(arg) ? arg : + boost::math::ccmath::detail::ldexp_impl(arg, exp); + } + else + { + using std::ldexp; + return ldexp(arg, exp); + } +} + +template , bool> = true> +inline constexpr double ldexp(Z arg, int exp) noexcept +{ + return boost::math::ccmath::ldexp(static_cast(arg), exp); +} + +inline constexpr float ldexpf(float arg, int exp) noexcept +{ + return boost::math::ccmath::ldexp(arg, exp); +} + +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS +inline constexpr long double ldexpl(long double arg, int exp) noexcept +{ + return boost::math::ccmath::ldexp(arg, exp); +} +#endif + +} // Namespaces + +#endif // BOOST_MATH_CCMATH_LDEXP_HPP diff --git a/libcxx/src/third-party/boost/math/ccmath/logb.hpp b/libcxx/src/third-party/boost/math/ccmath/logb.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/ccmath/logb.hpp @@ -0,0 +1,74 @@ +// (C) Copyright Matt Borland 2021. +// 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_CCMATH_LOGB_HPP +#define BOOST_MATH_CCMATH_LOGB_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost::math::ccmath { + +namespace detail { + +// The value of the exponent returned by std::logb is always 1 less than the exponent returned by +// std::frexp because of the different normalization requirements: for the exponent e returned by std::logb, +// |arg*r^-e| is between 1 and r (typically between 1 and 2), but for the exponent e returned by std::frexp, +// |arg*2^-e| is between 0.5 and 1. +template +inline constexpr T logb_impl(T arg) noexcept +{ + int exp = 0; + boost::math::ccmath::frexp(arg, &exp); + + return exp - 1; +} + +} // Namespace detail + +template , bool> = true> +inline constexpr Real logb(Real arg) noexcept +{ + if(BOOST_MATH_IS_CONSTANT_EVALUATED(arg)) + { + return boost::math::ccmath::abs(arg) == Real(0) ? -std::numeric_limits::infinity() : + boost::math::ccmath::isinf(arg) ? std::numeric_limits::infinity() : + boost::math::ccmath::isnan(arg) ? std::numeric_limits::quiet_NaN() : + boost::math::ccmath::detail::logb_impl(arg); + } + else + { + using std::logb; + return logb(arg); + } +} + +template , bool> = true> +inline constexpr double logb(Z arg) noexcept +{ + return boost::math::ccmath::logb(static_cast(arg)); +} + +inline constexpr float logbf(float arg) noexcept +{ + return boost::math::ccmath::logb(arg); +} + +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS +inline constexpr long double logbl(long double arg) noexcept +{ + return boost::math::ccmath::logb(arg); +} +#endif + +} // Namespaces + +#endif // BOOST_MATH_CCMATH_LOGB_HPP diff --git a/libcxx/src/third-party/boost/math/ccmath/modf.hpp b/libcxx/src/third-party/boost/math/ccmath/modf.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/ccmath/modf.hpp @@ -0,0 +1,77 @@ +// (C) Copyright Matt Borland 2021. +// 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_CCMATH_MODF_HPP +#define BOOST_MATH_CCMATH_MODF_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost::math::ccmath { + +namespace detail { + +template +inline constexpr Real modf_error_impl(Real x, Real* iptr) +{ + *iptr = x; + return boost::math::ccmath::abs(x) == Real(0) ? x : + x > Real(0) ? Real(0) : -Real(0); +} + +template +inline constexpr Real modf_nan_impl(Real x, Real* iptr) +{ + *iptr = x; + return x; +} + +template +inline constexpr Real modf_impl(Real x, Real* iptr) +{ + *iptr = boost::math::ccmath::trunc(x); + return (x - *iptr); +} + +} // Namespace detail + +template +inline constexpr Real modf(Real x, Real* iptr) +{ + if(BOOST_MATH_IS_CONSTANT_EVALUATED(x)) + { + return boost::math::ccmath::abs(x) == Real(0) ? detail::modf_error_impl(x, iptr) : + boost::math::ccmath::isinf(x) ? detail::modf_error_impl(x, iptr) : + boost::math::ccmath::isnan(x) ? detail::modf_nan_impl(x, iptr) : + boost::math::ccmath::detail::modf_impl(x, iptr); + } + else + { + using std::modf; + return modf(x, iptr); + } +} + +inline constexpr float modff(float x, float* iptr) +{ + return boost::math::ccmath::modf(x, iptr); +} + +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS +inline constexpr long double modfl(long double x, long double* iptr) +{ + return boost::math::ccmath::modf(x, iptr); +} +#endif + +} // Namespaces + +#endif // BOOST_MATH_CCMATH_MODF_HPP diff --git a/libcxx/src/third-party/boost/math/ccmath/next.hpp b/libcxx/src/third-party/boost/math/ccmath/next.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/ccmath/next.hpp @@ -0,0 +1,456 @@ +// (C) Copyright John Maddock 2008 - 2022. +// (C) Copyright Matt Borland 2022. +// 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_CCMATH_NEXT_HPP +#define BOOST_MATH_CCMATH_NEXT_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost::math::ccmath { + +namespace detail { + +// Forward Declarations +template > +constexpr result_type float_prior(const T& val); + +template > +constexpr result_type float_next(const T& val); + +template +struct has_hidden_guard_digits; +template <> +struct has_hidden_guard_digits : public std::false_type {}; +template <> +struct has_hidden_guard_digits : public std::false_type {}; +template <> +struct has_hidden_guard_digits : public std::false_type {}; +#ifdef BOOST_HAS_FLOAT128 +template <> +struct has_hidden_guard_digits<__float128> : public std::false_type {}; +#endif + +template +struct has_hidden_guard_digits_10 : public std::false_type {}; +template +struct has_hidden_guard_digits_10 : public std::integral_constant::digits10 != std::numeric_limits::max_digits10)> {}; + +template +struct has_hidden_guard_digits + : public has_hidden_guard_digits_10::is_specialized + && (std::numeric_limits::radix == 10) > +{}; + +template +constexpr T normalize_value(const T& val, const std::false_type&) { return val; } +template +constexpr T normalize_value(const T& val, const std::true_type&) +{ + static_assert(std::numeric_limits::is_specialized, "Type T must be specialized."); + static_assert(std::numeric_limits::radix != 2, "Type T must be specialized."); + + std::intmax_t shift = static_cast(std::numeric_limits::digits) - static_cast(boost::math::ccmath::ilogb(val)) - 1; + T result = boost::math::ccmath::scalbn(val, shift); + result = boost::math::ccmath::round(result); + return boost::math::ccmath::scalbn(result, -shift); +} + +template +constexpr T get_smallest_value(const std::true_type&) +{ + // + // numeric_limits lies about denorms being present - particularly + // when this can be turned on or off at runtime, as is the case + // when using the SSE2 registers in DAZ or FTZ mode. + // + constexpr T m = std::numeric_limits::denorm_min(); + return ((tools::min_value() / 2) == 0) ? tools::min_value() : m; +} + +template +constexpr T get_smallest_value(const std::false_type&) +{ + return tools::min_value(); +} + +template +constexpr T get_smallest_value() +{ + return get_smallest_value(std::integral_constant::is_specialized && (std::numeric_limits::has_denorm == std::denorm_present)>()); +} + +template +constexpr T calc_min_shifted(const std::true_type&) +{ + return boost::math::ccmath::ldexp(tools::min_value(), tools::digits() + 1); +} + +template +constexpr T calc_min_shifted(const std::false_type&) +{ + static_assert(std::numeric_limits::is_specialized, "Type T must be specialized."); + static_assert(std::numeric_limits::radix != 2, "Type T must be specialized."); + + return boost::math::ccmath::scalbn(tools::min_value(), std::numeric_limits::digits + 1); +} + +template +constexpr T get_min_shift_value() +{ + const T val = calc_min_shifted(std::integral_constant::is_specialized || std::numeric_limits::radix == 2>()); + return val; +} + +template > +struct exponent_type +{ + using type = int; +}; + +template +struct exponent_type +{ + using type = typename T::backend_type::exponent_type; +}; + +template > +using exponent_type_t = typename exponent_type::type; + +template +constexpr T float_next_imp(const T& val, const std::true_type&) +{ + using exponent_type = exponent_type_t; + + exponent_type expon {}; + + int fpclass = boost::math::ccmath::fpclassify(val); + + if (fpclass == FP_NAN) + { + return val; + } + else if (fpclass == FP_INFINITE) + { + return val; + } + else if (val <= -tools::max_value()) + { + return val; + } + + if (val == 0) + { + return detail::get_smallest_value(); + } + + if ((fpclass != FP_SUBNORMAL) && (fpclass != FP_ZERO) + && (boost::math::ccmath::fabs(val) < detail::get_min_shift_value()) + && (val != -tools::min_value())) + { + // + // 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 boost::math::ccmath::ldexp(boost::math::ccmath::detail::float_next(static_cast(boost::math::ccmath::ldexp(val, 2 * tools::digits()))), -2 * tools::digits()); + } + + if (-0.5f == boost::math::ccmath::frexp(val, &expon)) + { + --expon; // reduce exponent when val is a power of two, and negative. + } + T diff = boost::math::ccmath::ldexp(static_cast(1), expon - tools::digits()); + if(diff == 0) + { + diff = detail::get_smallest_value(); + } + return val + diff; +} + +// +// Special version for some base other than 2: +// +template +constexpr T float_next_imp(const T& val, const std::false_type&) +{ + using exponent_type = exponent_type_t; + + static_assert(std::numeric_limits::is_specialized, "Type T must be specialized."); + static_assert(std::numeric_limits::radix != 2, "Type T must be specialized."); + + exponent_type expon {}; + + int fpclass = boost::math::ccmath::fpclassify(val); + + if (fpclass == FP_NAN) + { + return val; + } + else if (fpclass == FP_INFINITE) + { + return val; + } + else if (val <= -tools::max_value()) + { + return val; + } + + if (val == 0) + { + return detail::get_smallest_value(); + } + + if ((fpclass != FP_SUBNORMAL) && (fpclass != FP_ZERO) + && (boost::math::ccmath::fabs(val) < detail::get_min_shift_value()) + && (val != -tools::min_value())) + { + // + // 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 boost::math::ccmath::scalbn(boost::math::ccmath::detail::float_next(static_cast(boost::math::ccmath::scalbn(val, 2 * std::numeric_limits::digits))), -2 * std::numeric_limits::digits); + } + + expon = 1 + boost::math::ccmath::ilogb(val); + if(-1 == boost::math::ccmath::scalbn(val, -expon) * std::numeric_limits::radix) + { + --expon; // reduce exponent when val is a power of base, and negative. + } + + T diff = boost::math::ccmath::scalbn(static_cast(1), expon - std::numeric_limits::digits); + if(diff == 0) + { + diff = detail::get_smallest_value(); + } + + return val + diff; +} + +template +constexpr result_type float_next(const T& val) +{ + return detail::float_next_imp(detail::normalize_value(static_cast(val), typename detail::has_hidden_guard_digits::type()), std::integral_constant::is_specialized || (std::numeric_limits::radix == 2)>()); +} + +template +constexpr T float_prior_imp(const T& val, const std::true_type&) +{ + using exponent_type = exponent_type_t; + + exponent_type expon {}; + + int fpclass = boost::math::ccmath::fpclassify(val); + + if (fpclass == FP_NAN) + { + return val; + } + else if (fpclass == FP_INFINITE) + { + return val; + } + else if (val <= -tools::max_value()) + { + return val; + } + + if (val == 0) + { + return -detail::get_smallest_value(); + } + + if ((fpclass != FP_SUBNORMAL) && (fpclass != FP_ZERO) + && (boost::math::ccmath::fabs(val) < detail::get_min_shift_value()) + && (val != tools::min_value())) + { + // + // 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 boost::math::ccmath::ldexp(boost::math::ccmath::detail::float_prior(static_cast(boost::math::ccmath::ldexp(val, 2 * tools::digits()))), -2 * tools::digits()); + } + + if(T remain = boost::math::ccmath::frexp(val, &expon); remain == 0.5f) + { + --expon; // when val is a power of two we must reduce the exponent + } + + T diff = boost::math::ccmath::ldexp(static_cast(1), expon - tools::digits()); + if(diff == 0) + { + diff = detail::get_smallest_value(); + } + + return val - diff; +} + +// +// Special version for bases other than 2: +// +template +constexpr T float_prior_imp(const T& val, const std::false_type&) +{ + using exponent_type = exponent_type_t; + + static_assert(std::numeric_limits::is_specialized, "Type T must be specialized."); + static_assert(std::numeric_limits::radix != 2, "Type T must be specialized."); + + exponent_type expon {}; + + int fpclass = boost::math::ccmath::fpclassify(val); + + if (fpclass == FP_NAN) + { + return val; + } + else if (fpclass == FP_INFINITE) + { + return val; + } + else if (val <= -tools::max_value()) + { + return val; + } + + if (val == 0) + { + return -detail::get_smallest_value(); + } + + if ((fpclass != FP_SUBNORMAL) && (fpclass != FP_ZERO) + && (boost::math::ccmath::fabs(val) < detail::get_min_shift_value()) + && (val != tools::min_value())) + { + // + // 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 boost::math::ccmath::scalbn(boost::math::ccmath::detail::float_prior(static_cast(boost::math::ccmath::scalbn(val, 2 * std::numeric_limits::digits))), -2 * std::numeric_limits::digits); + } + + expon = 1 + boost::math::ccmath::ilogb(val); + + if (T remain = boost::math::ccmath::scalbn(val, -expon); remain * std::numeric_limits::radix == 1) + { + --expon; // when val is a power of two we must reduce the exponent + } + + T diff = boost::math::ccmath::scalbn(static_cast(1), expon - std::numeric_limits::digits); + if (diff == 0) + { + diff = detail::get_smallest_value(); + } + return val - diff; +} // float_prior_imp + +template +constexpr result_type float_prior(const T& val) +{ + return detail::float_prior_imp(detail::normalize_value(static_cast(val), typename detail::has_hidden_guard_digits::type()), std::integral_constant::is_specialized || (std::numeric_limits::radix == 2)>()); +} + +} // namespace detail + +template > +constexpr result_type nextafter(const T& val, const U& direction) +{ + if (BOOST_MATH_IS_CONSTANT_EVALUATED(val)) + { + if (boost::math::ccmath::isnan(val)) + { + return val; + } + else if (boost::math::ccmath::isnan(direction)) + { + return direction; + } + else if (val < direction) + { + return boost::math::ccmath::detail::float_next(val); + } + else if (val == direction) + { + // IEC 60559 recommends that from is returned whenever from == to. These functions return to instead, + // which makes the behavior around zero consistent: std::nextafter(-0.0, +0.0) returns +0.0 and + // std::nextafter(+0.0, -0.0) returns -0.0. + return direction; + } + + return boost::math::ccmath::detail::float_prior(val); + } + else + { + using std::nextafter; + return nextafter(static_cast(val), static_cast(direction)); + } +} + +constexpr float nextafterf(float val, float direction) +{ + return boost::math::ccmath::nextafter(val, direction); +} + +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + +constexpr long double nextafterl(long double val, long double direction) +{ + return boost::math::ccmath::nextafter(val, direction); +} + +template , typename return_type = std::conditional_t, double, T>> +constexpr return_type nexttoward(T val, long double direction) +{ + if (BOOST_MATH_IS_CONSTANT_EVALUATED(val)) + { + return static_cast(boost::math::ccmath::nextafter(static_cast(val), direction)); + } + else + { + using std::nexttoward; + return nexttoward(val, direction); + } +} + +constexpr float nexttowardf(float val, long double direction) +{ + return boost::math::ccmath::nexttoward(val, direction); +} + +constexpr long double nexttowardl(long double val, long double direction) +{ + return boost::math::ccmath::nexttoward(val, direction); +} + +#endif + +} // Namespaces + +#endif // BOOST_MATH_SPECIAL_NEXT_HPP diff --git a/libcxx/src/third-party/boost/math/ccmath/remainder.hpp b/libcxx/src/third-party/boost/math/ccmath/remainder.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/ccmath/remainder.hpp @@ -0,0 +1,104 @@ +// (C) Copyright Matt Borland 2021 - 2022. +// 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_CCMATH_REMAINDER_HPP +#define BOOST_MATH_CCMATH_REMAINDER_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost::math::ccmath { + +namespace detail { + +template +constexpr T remainder_impl(const T x, const T y) +{ + T n = 0; + + if (T fractional_part = boost::math::ccmath::modf((x / y), &n); fractional_part > static_cast(1.0/2)) + { + ++n; + } + else if (fractional_part < static_cast(-1.0/2)) + { + --n; + } + + return x - n*y; +} + +} // Namespace detail + +template , bool> = true> +constexpr Real remainder(Real x, Real y) +{ + if (BOOST_MATH_IS_CONSTANT_EVALUATED(x)) + { + if (boost::math::ccmath::isinf(x) && !boost::math::ccmath::isnan(y)) + { + return std::numeric_limits::quiet_NaN(); + } + else if (boost::math::ccmath::abs(y) == static_cast(0) && !boost::math::ccmath::isnan(x)) + { + return std::numeric_limits::quiet_NaN(); + } + else if (boost::math::ccmath::isnan(x)) + { + return x; + } + else if (boost::math::ccmath::isnan(y)) + { + return y; + } + + return boost::math::ccmath::detail::remainder_impl(x, y); + } + else + { + using std::remainder; + return remainder(x, y); + } +} + +template +constexpr auto remainder(T1 x, T2 y) +{ + if (BOOST_MATH_IS_CONSTANT_EVALUATED(x)) + { + using promoted_type = boost::math::tools::promote_args_t; + return boost::math::ccmath::remainder(promoted_type(x), promoted_type(y)); + } + else + { + using std::remainder; + return remainder(x, y); + } +} + +constexpr float remainderf(float x, float y) +{ + return boost::math::ccmath::remainder(x, y); +} + +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS +constexpr long double remainderl(long double x, long double y) +{ + return boost::math::ccmath::remainder(x, y); +} +#endif + +} // Namespaces + +#endif // BOOST_MATH_CCMATH_REMAINDER_HPP diff --git a/libcxx/src/third-party/boost/math/ccmath/round.hpp b/libcxx/src/third-party/boost/math/ccmath/round.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/ccmath/round.hpp @@ -0,0 +1,176 @@ +// (C) Copyright Matt Borland 2021. +// 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_CCMATH_ROUND_HPP +#define BOOST_MATH_CCMATH_ROUND_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost::math::ccmath { + +namespace detail { + +// Computes the nearest integer value to arg (in floating-point format), +// rounding halfway cases away from zero, regardless of the current rounding mode. +template +inline constexpr T round_impl(T arg) noexcept +{ + T iptr = 0; + const T x = boost::math::ccmath::modf(arg, &iptr); + constexpr T half = T(1)/2; + + if(x >= half && iptr > 0) + { + return iptr + 1; + } + else if(boost::math::ccmath::abs(x) >= half && iptr < 0) + { + return iptr - 1; + } + else + { + return iptr; + } +} + +template +inline constexpr ReturnType int_round_impl(T arg) +{ + const T rounded_arg = round_impl(arg); + + if(rounded_arg > static_cast((std::numeric_limits::max)())) + { + if constexpr (std::is_same_v) + { + throw std::domain_error("Rounded value cannot be represented by a long long type without overflow"); + } + else + { + throw std::domain_error("Rounded value cannot be represented by a long type without overflow"); + } + } + else + { + return static_cast(rounded_arg); + } +} + +} // Namespace detail + +template , bool> = true> +inline constexpr Real round(Real arg) noexcept +{ + if(BOOST_MATH_IS_CONSTANT_EVALUATED(arg)) + { + return boost::math::ccmath::abs(arg) == Real(0) ? arg : + boost::math::ccmath::isinf(arg) ? arg : + boost::math::ccmath::isnan(arg) ? arg : + boost::math::ccmath::detail::round_impl(arg); + } + else + { + using std::round; + return round(arg); + } +} + +template , bool> = true> +inline constexpr double round(Z arg) noexcept +{ + return boost::math::ccmath::round(static_cast(arg)); +} + +inline constexpr float roundf(float arg) noexcept +{ + return boost::math::ccmath::round(arg); +} + +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS +inline constexpr long double roundl(long double arg) noexcept +{ + return boost::math::ccmath::round(arg); +} +#endif + +template , bool> = true> +inline constexpr long lround(Real arg) +{ + if(BOOST_MATH_IS_CONSTANT_EVALUATED(arg)) + { + return boost::math::ccmath::abs(arg) == Real(0) ? 0l : + boost::math::ccmath::isinf(arg) ? 0l : + boost::math::ccmath::isnan(arg) ? 0l : + boost::math::ccmath::detail::int_round_impl(arg); + } + else + { + using std::lround; + return lround(arg); + } +} + +template , bool> = true> +inline constexpr long lround(Z arg) +{ + return boost::math::ccmath::lround(static_cast(arg)); +} + +inline constexpr long lroundf(float arg) +{ + return boost::math::ccmath::lround(arg); +} + +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS +inline constexpr long lroundl(long double arg) +{ + return boost::math::ccmath::lround(arg); +} +#endif + +template , bool> = true> +inline constexpr long long llround(Real arg) +{ + if(BOOST_MATH_IS_CONSTANT_EVALUATED(arg)) + { + return boost::math::ccmath::abs(arg) == Real(0) ? 0ll : + boost::math::ccmath::isinf(arg) ? 0ll : + boost::math::ccmath::isnan(arg) ? 0ll : + boost::math::ccmath::detail::int_round_impl(arg); + } + else + { + using std::llround; + return llround(arg); + } +} + +template , bool> = true> +inline constexpr long llround(Z arg) +{ + return boost::math::ccmath::llround(static_cast(arg)); +} + +inline constexpr long long llroundf(float arg) +{ + return boost::math::ccmath::llround(arg); +} + +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS +inline constexpr long long llroundl(long double arg) +{ + return boost::math::ccmath::llround(arg); +} +#endif + +} // Namespaces + +#endif // BOOST_MATH_CCMATH_ROUND_HPP diff --git a/libcxx/src/third-party/boost/math/ccmath/scalbln.hpp b/libcxx/src/third-party/boost/math/ccmath/scalbln.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/ccmath/scalbln.hpp @@ -0,0 +1,57 @@ +// (C) Copyright Matt Borland 2021. +// 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_CCMATH_SCALBLN_HPP +#define BOOST_MATH_CCMATH_SCALBLN_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost::math::ccmath { + +template , bool> = true> +inline constexpr Real scalbln(Real arg, long exp) noexcept +{ + if(BOOST_MATH_IS_CONSTANT_EVALUATED(arg)) + { + return boost::math::ccmath::abs(arg) == Real(0) ? arg : + boost::math::ccmath::isinf(arg) ? arg : + boost::math::ccmath::isnan(arg) ? arg : + boost::math::ccmath::detail::scalbn_impl(arg, exp); + } + else + { + using std::scalbln; + return scalbln(arg, exp); + } +} + +template , bool> = true> +inline constexpr double scalbln(Z arg, long exp) noexcept +{ + return boost::math::ccmath::scalbln(static_cast(arg), exp); +} + +inline constexpr float scalblnf(float arg, long exp) noexcept +{ + return boost::math::ccmath::scalbln(arg, exp); +} + +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS +inline constexpr long double scalblnl(long double arg, long exp) noexcept +{ + return boost::math::ccmath::scalbln(arg, exp); +} +#endif + +} // Namespaces + +#endif // BOOST_MATH_CCMATH_SCALBLN_HPP diff --git a/libcxx/src/third-party/boost/math/ccmath/scalbn.hpp b/libcxx/src/third-party/boost/math/ccmath/scalbn.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/ccmath/scalbn.hpp @@ -0,0 +1,79 @@ +// (C) Copyright Matt Borland 2021. +// (C) Copyright John Maddock 2021. +// 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_CCMATH_SCALBN_HPP +#define BOOST_MATH_CCMATH_SCALBN_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost::math::ccmath { + +namespace detail { + +template +inline constexpr Real scalbn_impl(Real arg, Z exp) noexcept +{ + while(exp > 0) + { + arg *= FLT_RADIX; + --exp; + } + while(exp < 0) + { + arg /= FLT_RADIX; + ++exp; + } + + return arg; +} + +} // Namespace detail + +template , bool> = true> +inline constexpr Real scalbn(Real arg, int exp) noexcept +{ + if(BOOST_MATH_IS_CONSTANT_EVALUATED(arg)) + { + return boost::math::ccmath::abs(arg) == Real(0) ? arg : + boost::math::ccmath::isinf(arg) ? arg : + boost::math::ccmath::isnan(arg) ? arg : + boost::math::ccmath::detail::scalbn_impl(arg, exp); + } + else + { + using std::scalbn; + return scalbn(arg, exp); + } +} + +template , bool> = true> +inline constexpr double scalbn(Z arg, int exp) noexcept +{ + return boost::math::ccmath::scalbn(static_cast(arg), exp); +} + +inline constexpr float scalbnf(float arg, int exp) noexcept +{ + return boost::math::ccmath::scalbn(arg, exp); +} + +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS +inline constexpr long double scalbnl(long double arg, int exp) noexcept +{ + return boost::math::ccmath::scalbn(arg, exp); +} +#endif + +} // Namespaces + +#endif // BOOST_MATH_CCMATH_SCALBN_HPP diff --git a/libcxx/src/third-party/boost/math/ccmath/signbit.hpp b/libcxx/src/third-party/boost/math/ccmath/signbit.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/ccmath/signbit.hpp @@ -0,0 +1,217 @@ +// (C) Copyright Matt Borland 2022. +// 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_CCMATH_SIGNBIT_HPP +#define BOOST_MATH_CCMATH_SIGNBIT_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __has_include +# if __has_include() +# include +# if __cpp_lib_bit_cast >= 201806L +# define BOOST_MATH_BIT_CAST(T, x) std::bit_cast(x) +# endif +# elif defined(__has_builtin) +# if __has_builtin(__builtin_bit_cast) +# define BOOST_MATH_BIT_CAST(T, x) __builtin_bit_cast(T, x) +# endif +# endif +#endif + +/* +The following error is given using Apple Clang version 13.1.6, and Clang 13, and 14 on Ubuntu 22.04.01 +TODO: Remove the following undef when Apple Clang supports + +ccmath_signbit_test.cpp:32:19: error: static_assert expression is not an integral constant expression + static_assert(boost::math::ccmath::signbit(T(-1)) == true); + ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +../../../boost/math/ccmath/signbit.hpp:62:24: note: constexpr bit_cast involving bit-field is not yet supported + const auto u = BOOST_MATH_BIT_CAST(float_bits, arg); + ^ +../../../boost/math/ccmath/signbit.hpp:20:37: note: expanded from macro 'BOOST_MATH_BIT_CAST' +# define BOOST_MATH_BIT_CAST(T, x) __builtin_bit_cast(T, x) + ^ +*/ + +#if defined(__clang__) && defined(BOOST_MATH_BIT_CAST) +# undef BOOST_MATH_BIT_CAST +#endif + +namespace boost::math::ccmath { + +namespace detail { + +#ifdef BOOST_MATH_BIT_CAST + +struct IEEEf2bits +{ +#if BOOST_MATH_ENDIAN_LITTLE_BYTE + std::uint32_t mantissa : 23; + std::uint32_t exponent : 8; + std::uint32_t sign : 1; +#else // Big endian + std::uint32_t sign : 1; + std::uint32_t exponent : 8; + std::uint32_t mantissa : 23; +#endif +}; + +struct IEEEd2bits +{ +#if BOOST_MATH_ENDIAN_LITTLE_BYTE + std::uint32_t mantissa_l : 32; + std::uint32_t mantissa_h : 20; + std::uint32_t exponent : 11; + std::uint32_t sign : 1; +#else // Big endian + std::uint32_t sign : 1; + std::uint32_t exponent : 11; + std::uint32_t mantissa_h : 20; + std::uint32_t mantissa_l : 32; +#endif +}; + +// 80 bit long double +#if LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 + +struct IEEEl2bits +{ +#if BOOST_MATH_ENDIAN_LITTLE_BYTE + std::uint32_t mantissa_l : 32; + std::uint32_t mantissa_h : 32; + std::uint32_t exponent : 15; + std::uint32_t sign : 1; + std::uint32_t pad : 32; +#else // Big endian + std::uint32_t pad : 32; + std::uint32_t sign : 1; + std::uint32_t exponent : 15; + std::uint32_t mantissa_h : 32; + std::uint32_t mantissa_l : 32; +#endif +}; + +// 128 bit long double +#elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 + +struct IEEEl2bits +{ +#if BOOST_MATH_ENDIAN_LITTLE_BYTE + std::uint64_t mantissa_l : 64; + std::uint64_t mantissa_h : 48; + std::uint32_t exponent : 15; + std::uint32_t sign : 1; +#else // Big endian + std::uint32_t sign : 1; + std::uint32_t exponent : 15; + std::uint64_t mantissa_h : 48; + std::uint64_t mantissa_l : 64; +#endif +}; + +// 64 bit long double (double == long double on ARM) +#elif LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 + +struct IEEEl2bits +{ +#if BOOST_MATH_ENDIAN_LITTLE_BYTE + std::uint32_t mantissa_l : 32; + std::uint32_t mantissa_h : 20; + std::uint32_t exponent : 11; + std::uint32_t sign : 1; +#else // Big endian + std::uint32_t sign : 1; + std::uint32_t exponent : 11; + std::uint32_t mantissa_h : 20; + std::uint32_t mantissa_l : 32; +#endif +}; + +#else // Unsupported long double representation +# define BOOST_MATH_UNSUPPORTED_LONG_DOUBLE +#endif + +template +constexpr bool signbit_impl(T arg) +{ + if constexpr (std::is_same_v) + { + const auto u = BOOST_MATH_BIT_CAST(IEEEf2bits, arg); + return u.sign; + } + else if constexpr (std::is_same_v) + { + const auto u = BOOST_MATH_BIT_CAST(IEEEd2bits, arg); + return u.sign; + } + #ifndef BOOST_MATH_UNSUPPORTED_LONG_DOUBLE + else if constexpr (std::is_same_v) + { + const auto u = BOOST_MATH_BIT_CAST(IEEEl2bits, arg); + return u.sign; + } + #endif + else + { + BOOST_MATH_ASSERT_MSG(!boost::math::ccmath::isnan(arg), "NAN is not supported with this type or platform"); + BOOST_MATH_ASSERT_MSG(boost::math::ccmath::abs(arg) != 0, "Signed 0 is not support with this type or platform"); + + return arg < static_cast(0); + } +} + +#else + +// Typical implementations of signbit involve type punning via union and manipulating +// overflow (see libc++ or musl). Neither of these are allowed in constexpr contexts +// (technically type punning via union in general is UB in c++ but well defined in C) +// therefore we static assert these cases. + +template +constexpr bool signbit_impl(T arg) +{ + BOOST_MATH_ASSERT_MSG(!boost::math::ccmath::isnan(arg), "NAN is not supported without __builtin_bit_cast or std::bit_cast"); + BOOST_MATH_ASSERT_MSG(boost::math::ccmath::abs(arg) != 0, "Signed 0 is not support without __builtin_bit_cast or std::bit_cast"); + + return arg < static_cast(0); +} + +#endif + +} + +// Return value: true if arg is negative, false if arg is 0, NAN, or positive +template , bool> = true> +constexpr bool signbit(Real arg) +{ + if (BOOST_MATH_IS_CONSTANT_EVALUATED(arg)) + { + return boost::math::ccmath::detail::signbit_impl(arg); + } + else + { + using std::signbit; + return signbit(arg); + } +} + +template , bool> = true> +constexpr bool signbit(Z arg) +{ + return boost::math::ccmath::signbit(static_cast(arg)); +} + +} // Namespaces + +#endif // BOOST_MATH_CCMATH_SIGNBIT_HPP diff --git a/libcxx/src/third-party/boost/math/ccmath/sqrt.hpp b/libcxx/src/third-party/boost/math/ccmath/sqrt.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/ccmath/sqrt.hpp @@ -0,0 +1,66 @@ +// (C) Copyright Matt Borland 2021. +// 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) +// +// Constexpr implementation of sqrt function + +#ifndef BOOST_MATH_CCMATH_SQRT +#define BOOST_MATH_CCMATH_SQRT + +#include +#include +#include +#include +#include +#include + +namespace boost::math::ccmath { + +namespace detail { + +template +inline constexpr Real sqrt_impl_2(Real x, Real s, Real s2) +{ + return !(s < s2) ? s2 : sqrt_impl_2(x, (x / s + s) / 2, s); +} + +template +inline constexpr Real sqrt_impl_1(Real x, Real s) +{ + return sqrt_impl_2(x, (x / s + s) / 2, s); +} + +template +inline constexpr Real sqrt_impl(Real x) +{ + return sqrt_impl_1(x, x > 1 ? x : Real(1)); +} + +} // namespace detail + +template , bool> = true> +inline constexpr Real sqrt(Real x) +{ + if(BOOST_MATH_IS_CONSTANT_EVALUATED(x)) + { + return boost::math::ccmath::isnan(x) ? std::numeric_limits::quiet_NaN() : + boost::math::ccmath::isinf(x) ? std::numeric_limits::infinity() : + detail::sqrt_impl(x); + } + else + { + using std::sqrt; + return sqrt(x); + } +} + +template , bool> = true> +inline constexpr double sqrt(Z x) +{ + return detail::sqrt_impl(static_cast(x)); +} + +} // Namespaces + +#endif // BOOST_MATH_CCMATH_SQRT diff --git a/libcxx/src/third-party/boost/math/ccmath/trunc.hpp b/libcxx/src/third-party/boost/math/ccmath/trunc.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/ccmath/trunc.hpp @@ -0,0 +1,67 @@ +// (C) Copyright Matt Borland 2021. +// 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_CCMATH_TRUNC_HPP +#define BOOST_MATH_CCMATH_TRUNC_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost::math::ccmath { + +namespace detail { + +template +inline constexpr T trunc_impl(T arg) noexcept +{ + return (arg > 0) ? boost::math::ccmath::floor(arg) : boost::math::ccmath::ceil(arg); +} + +} // Namespace detail + +template , bool> = true> +inline constexpr Real trunc(Real arg) noexcept +{ + if(BOOST_MATH_IS_CONSTANT_EVALUATED(arg)) + { + return boost::math::ccmath::abs(arg) == Real(0) ? arg : + boost::math::ccmath::isinf(arg) ? arg : + boost::math::ccmath::isnan(arg) ? arg : + boost::math::ccmath::detail::trunc_impl(arg); + } + else + { + using std::trunc; + return trunc(arg); + } +} + +template , bool> = true> +inline constexpr double trunc(Z arg) noexcept +{ + return boost::math::ccmath::trunc(static_cast(arg)); +} + +inline constexpr float truncf(float arg) noexcept +{ + return boost::math::ccmath::trunc(arg); +} + +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS +inline constexpr long double truncl(long double arg) noexcept +{ + return boost::math::ccmath::trunc(arg); +} +#endif + +} // Namespaces + +#endif // BOOST_MATH_CCMATH_TRUNC_HPP diff --git a/libcxx/src/third-party/boost/math/common_factor.hpp b/libcxx/src/third-party/boost/math/common_factor.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/common_factor.hpp @@ -0,0 +1,23 @@ +// Boost common_factor.hpp header file -------------------------------------// + +// (C) Copyright Daryle Walker 2001-2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#ifndef BOOST_MATH_COMMON_FACTOR_HPP +#define BOOST_MATH_COMMON_FACTOR_HPP + +#ifndef BOOST_MATH_STANDALONE +#include +#include +#include + +BOOST_MATH_HEADER_DEPRECATED(""); +#else +#error Common factor is not available in standalone mode because it requires boost.integer. +#endif // BOOST_MATH_STANDALONE + +#endif // BOOST_MATH_COMMON_FACTOR_HPP diff --git a/libcxx/src/third-party/boost/math/common_factor_ct.hpp b/libcxx/src/third-party/boost/math/common_factor_ct.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/common_factor_ct.hpp @@ -0,0 +1,34 @@ +// Boost common_factor_ct.hpp header file ----------------------------------// + +// (C) Copyright John Maddock 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#ifndef BOOST_MATH_COMMON_FACTOR_CT_HPP +#define BOOST_MATH_COMMON_FACTOR_CT_HPP + +#ifndef BOOST_MATH_STANDALONE +#include +#include + +BOOST_MATH_HEADER_DEPRECATED(""); + +namespace boost +{ +namespace math +{ + + using boost::integer::static_gcd; + using boost::integer::static_lcm; + using boost::integer::static_gcd_type; + +} // namespace math +} // namespace boost +#else +#error Common factor is not available in standalone mode because it requires boost.integer. +#endif // BOOST_MATH_STANDALONE + +#endif // BOOST_MATH_COMMON_FACTOR_CT_HPP diff --git a/libcxx/src/third-party/boost/math/common_factor_rt.hpp b/libcxx/src/third-party/boost/math/common_factor_rt.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/common_factor_rt.hpp @@ -0,0 +1,30 @@ +// (C) Copyright John Maddock 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_COMMON_FACTOR_RT_HPP +#define BOOST_MATH_COMMON_FACTOR_RT_HPP + +#ifndef BOOST_MATH_STANDALONE +#include +#include + +BOOST_MATH_HEADER_DEPRECATED(""); + +namespace boost { + namespace math { + using boost::integer::gcd; + using boost::integer::lcm; + using boost::integer::gcd_range; + using boost::integer::lcm_range; + using boost::integer::gcd_evaluator; + using boost::integer::lcm_evaluator; + } +} +#else +#error Common factor is not available in standalone mode because it requires boost.integer. +#endif // BOOST_MATH_STANDALONE + +#endif // BOOST_MATH_COMMON_FACTOR_RT_HPP diff --git a/libcxx/src/third-party/boost/math/complex.hpp b/libcxx/src/third-party/boost/math/complex.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/complex.hpp @@ -0,0 +1,32 @@ +// (C) Copyright John Maddock 2005. +// 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_COMPLEX_INCLUDED +#define BOOST_MATH_COMPLEX_INCLUDED + +#ifndef BOOST_MATH_COMPLEX_ASIN_INCLUDED +# include +#endif +#ifndef BOOST_MATH_COMPLEX_ASINH_INCLUDED +# include +#endif +#ifndef BOOST_MATH_COMPLEX_ACOS_INCLUDED +# include +#endif +#ifndef BOOST_MATH_COMPLEX_ACOSH_INCLUDED +# include +#endif +#ifndef BOOST_MATH_COMPLEX_ATAN_INCLUDED +# include +#endif +#ifndef BOOST_MATH_COMPLEX_ATANH_INCLUDED +# include +#endif +#ifndef BOOST_MATH_COMPLEX_FABS_INCLUDED +# include +#endif + + +#endif // BOOST_MATH_COMPLEX_INCLUDED diff --git a/libcxx/src/third-party/boost/math/complex/acos.hpp b/libcxx/src/third-party/boost/math/complex/acos.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/complex/acos.hpp @@ -0,0 +1,245 @@ +// (C) Copyright John Maddock 2005. +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_COMPLEX_ACOS_INCLUDED +#define BOOST_MATH_COMPLEX_ACOS_INCLUDED + +#ifndef BOOST_MATH_COMPLEX_DETAILS_INCLUDED +# include +#endif +#ifndef BOOST_MATH_LOG1P_INCLUDED +# include +#endif +#include + +#ifdef BOOST_NO_STDC_NAMESPACE +namespace std{ using ::sqrt; using ::fabs; using ::acos; using ::asin; using ::atan; using ::atan2; } +#endif + +namespace boost{ namespace math{ + +template +std::complex acos(const std::complex& z) +{ + // + // This implementation is a transcription of the pseudo-code in: + // + // "Implementing the Complex Arcsine and Arccosine Functions using Exception Handling." + // T E Hull, Thomas F Fairgrieve and Ping Tak Peter Tang. + // ACM Transactions on Mathematical Software, Vol 23, No 3, Sept 1997. + // + + // + // These static constants should really be in a maths constants library, + // note that we have tweaked a_crossover as per: https://svn.boost.org/trac/boost/ticket/7290 + // + static const T one = static_cast(1); + //static const T two = static_cast(2); + static const T half = static_cast(0.5L); + static const T a_crossover = static_cast(10); + static const T b_crossover = static_cast(0.6417L); + static const T s_pi = boost::math::constants::pi(); + static const T half_pi = s_pi / 2; + static const T log_two = boost::math::constants::ln_two(); + static const T quarter_pi = s_pi / 4; + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4127) +#endif + // + // Get real and imaginary parts, discard the signs as we can + // figure out the sign of the result later: + // + T x = std::fabs(z.real()); + T y = std::fabs(z.imag()); + + T real, imag; // these hold our result + + // + // Handle special cases specified by the C99 standard, + // many of these special cases aren't really needed here, + // but doing it this way prevents overflow/underflow arithmetic + // in the main body of the logic, which may trip up some machines: + // + if((boost::math::isinf)(x)) + { + if((boost::math::isinf)(y)) + { + real = quarter_pi; + imag = std::numeric_limits::infinity(); + } + else if((boost::math::isnan)(y)) + { + return std::complex(y, -std::numeric_limits::infinity()); + } + else + { + // y is not infinity or nan: + real = 0; + imag = std::numeric_limits::infinity(); + } + } + else if((boost::math::isnan)(x)) + { + if((boost::math::isinf)(y)) + return std::complex(x, ((boost::math::signbit)(z.imag())) ? std::numeric_limits::infinity() : -std::numeric_limits::infinity()); + return std::complex(x, x); + } + else if((boost::math::isinf)(y)) + { + real = half_pi; + imag = std::numeric_limits::infinity(); + } + else if((boost::math::isnan)(y)) + { + return std::complex((x == 0) ? half_pi : y, y); + } + else + { + // + // What follows is the regular Hull et al code, + // begin with the special case for real numbers: + // + if((y == 0) && (x <= one)) + return std::complex((x == 0) ? half_pi : std::acos(z.real()), (boost::math::changesign)(z.imag())); + // + // Figure out if our input is within the "safe area" identified by Hull et al. + // This would be more efficient with portable floating point exception handling; + // fortunately the quantities M and u identified by Hull et al (figure 3), + // match with the max and min methods of numeric_limits. + // + T safe_max = detail::safe_max(static_cast(8)); + T safe_min = detail::safe_min(static_cast(4)); + + T xp1 = one + x; + T xm1 = x - one; + + if((x < safe_max) && (x > safe_min) && (y < safe_max) && (y > safe_min)) + { + T yy = y * y; + T r = std::sqrt(xp1*xp1 + yy); + T s = std::sqrt(xm1*xm1 + yy); + T a = half * (r + s); + T b = x / a; + + if(b <= b_crossover) + { + real = std::acos(b); + } + else + { + T apx = a + x; + if(x <= one) + { + real = std::atan(std::sqrt(half * apx * (yy /(r + xp1) + (s-xm1)))/x); + } + else + { + real = std::atan((y * std::sqrt(half * (apx/(r + xp1) + apx/(s+xm1))))/x); + } + } + + if(a <= a_crossover) + { + T am1; + if(x < one) + { + am1 = half * (yy/(r + xp1) + yy/(s - xm1)); + } + else + { + am1 = half * (yy/(r + xp1) + (s + xm1)); + } + imag = boost::math::log1p(am1 + std::sqrt(am1 * (a + one))); + } + else + { + imag = std::log(a + std::sqrt(a*a - one)); + } + } + else + { + // + // This is the Hull et al exception handling code from Fig 6 of their paper: + // + if(y <= (std::numeric_limits::epsilon() * std::fabs(xm1))) + { + if(x < one) + { + real = std::acos(x); + imag = y / std::sqrt(xp1*(one-x)); + } + else + { + // This deviates from Hull et al's paper as per https://svn.boost.org/trac/boost/ticket/7290 + if(((std::numeric_limits::max)() / xp1) > xm1) + { + // xp1 * xm1 won't overflow: + real = y / std::sqrt(xm1*xp1); + imag = boost::math::log1p(xm1 + std::sqrt(xp1*xm1)); + } + else + { + real = y / x; + imag = log_two + std::log(x); + } + } + } + else if(y <= safe_min) + { + // There is an assumption in Hull et al's analysis that + // if we get here then x == 1. This is true for all "good" + // machines where : + // + // E^2 > 8*sqrt(u); with: + // + // E = std::numeric_limits::epsilon() + // u = (std::numeric_limits::min)() + // + // Hull et al provide alternative code for "bad" machines + // but we have no way to test that here, so for now just assert + // on the assumption: + // + BOOST_MATH_ASSERT(x == 1); + real = std::sqrt(y); + imag = std::sqrt(y); + } + else if(std::numeric_limits::epsilon() * y - one >= x) + { + real = half_pi; + imag = log_two + std::log(y); + } + else if(x > one) + { + real = std::atan(y/x); + T xoy = x/y; + imag = log_two + std::log(y) + half * boost::math::log1p(xoy*xoy); + } + else + { + real = half_pi; + T a = std::sqrt(one + y*y); + imag = half * boost::math::log1p(static_cast(2)*y*(y+a)); + } + } + } + + // + // Finish off by working out the sign of the result: + // + if((boost::math::signbit)(z.real())) + real = s_pi - real; + if(!(boost::math::signbit)(z.imag())) + imag = (boost::math::changesign)(imag); + + return std::complex(real, imag); +#ifdef _MSC_VER +#pragma warning(pop) +#endif +} + +} } // namespaces + +#endif // BOOST_MATH_COMPLEX_ACOS_INCLUDED diff --git a/libcxx/src/third-party/boost/math/complex/acosh.hpp b/libcxx/src/third-party/boost/math/complex/acosh.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/complex/acosh.hpp @@ -0,0 +1,34 @@ +// (C) Copyright John Maddock 2005. +// 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_COMPLEX_ACOSH_INCLUDED +#define BOOST_MATH_COMPLEX_ACOSH_INCLUDED + +#ifndef BOOST_MATH_COMPLEX_DETAILS_INCLUDED +# include +#endif +#ifndef BOOST_MATH_COMPLEX_ATANH_INCLUDED +# include +#endif + +namespace boost{ namespace math{ + +template +inline std::complex acosh(const std::complex& z) +{ + // + // We use the relation acosh(z) = +-i acos(z) + // Choosing the sign of multiplier to give real(acosh(z)) >= 0 + // as well as compatibility with C99. + // + std::complex result = boost::math::acos(z); + if(!(boost::math::isnan)(result.imag()) && signbit(result.imag())) + return detail::mult_i(result); + return detail::mult_minus_i(result); +} + +} } // namespaces + +#endif // BOOST_MATH_COMPLEX_ACOSH_INCLUDED diff --git a/libcxx/src/third-party/boost/math/complex/asin.hpp b/libcxx/src/third-party/boost/math/complex/asin.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/complex/asin.hpp @@ -0,0 +1,252 @@ +// (C) Copyright John Maddock 2005. +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_COMPLEX_ASIN_INCLUDED +#define BOOST_MATH_COMPLEX_ASIN_INCLUDED + +#ifndef BOOST_MATH_COMPLEX_DETAILS_INCLUDED +# include +#endif +#ifndef BOOST_MATH_LOG1P_INCLUDED +# include +#endif +#include + +#ifdef BOOST_NO_STDC_NAMESPACE +namespace std{ using ::sqrt; using ::fabs; using ::acos; using ::asin; using ::atan; using ::atan2; } +#endif + +namespace boost{ namespace math{ + +template +inline std::complex asin(const std::complex& z) +{ + // + // This implementation is a transcription of the pseudo-code in: + // + // "Implementing the complex Arcsine and Arccosine Functions using Exception Handling." + // T E Hull, Thomas F Fairgrieve and Ping Tak Peter Tang. + // ACM Transactions on Mathematical Software, Vol 23, No 3, Sept 1997. + // + + // + // These static constants should really be in a maths constants library, + // note that we have tweaked the value of a_crossover as per https://svn.boost.org/trac/boost/ticket/7290: + // + static const T one = static_cast(1); + //static const T two = static_cast(2); + static const T half = static_cast(0.5L); + static const T a_crossover = static_cast(10); + static const T b_crossover = static_cast(0.6417L); + static const T s_pi = boost::math::constants::pi(); + static const T half_pi = s_pi / 2; + static const T log_two = boost::math::constants::ln_two(); + static const T quarter_pi = s_pi / 4; +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4127) +#endif + // + // Get real and imaginary parts, discard the signs as we can + // figure out the sign of the result later: + // + T x = std::fabs(z.real()); + T y = std::fabs(z.imag()); + T real, imag; // our results + + // + // Begin by handling the special cases for infinities and nan's + // specified in C99, most of this is handled by the regular logic + // below, but handling it as a special case prevents overflow/underflow + // arithmetic which may trip up some machines: + // + if((boost::math::isnan)(x)) + { + if((boost::math::isnan)(y)) + return std::complex(x, x); + if((boost::math::isinf)(y)) + { + real = x; + imag = std::numeric_limits::infinity(); + } + else + return std::complex(x, x); + } + else if((boost::math::isnan)(y)) + { + if(x == 0) + { + real = 0; + imag = y; + } + else if((boost::math::isinf)(x)) + { + real = y; + imag = std::numeric_limits::infinity(); + } + else + return std::complex(y, y); + } + else if((boost::math::isinf)(x)) + { + if((boost::math::isinf)(y)) + { + real = quarter_pi; + imag = std::numeric_limits::infinity(); + } + else + { + real = half_pi; + imag = std::numeric_limits::infinity(); + } + } + else if((boost::math::isinf)(y)) + { + real = 0; + imag = std::numeric_limits::infinity(); + } + else + { + // + // special case for real numbers: + // + if((y == 0) && (x <= one)) + return std::complex(std::asin(z.real()), z.imag()); + // + // Figure out if our input is within the "safe area" identified by Hull et al. + // This would be more efficient with portable floating point exception handling; + // fortunately the quantities M and u identified by Hull et al (figure 3), + // match with the max and min methods of numeric_limits. + // + T safe_max = detail::safe_max(static_cast(8)); + T safe_min = detail::safe_min(static_cast(4)); + + T xp1 = one + x; + T xm1 = x - one; + + if((x < safe_max) && (x > safe_min) && (y < safe_max) && (y > safe_min)) + { + T yy = y * y; + T r = std::sqrt(xp1*xp1 + yy); + T s = std::sqrt(xm1*xm1 + yy); + T a = half * (r + s); + T b = x / a; + + if(b <= b_crossover) + { + real = std::asin(b); + } + else + { + T apx = a + x; + if(x <= one) + { + real = std::atan(x/std::sqrt(half * apx * (yy /(r + xp1) + (s-xm1)))); + } + else + { + real = std::atan(x/(y * std::sqrt(half * (apx/(r + xp1) + apx/(s+xm1))))); + } + } + + if(a <= a_crossover) + { + T am1; + if(x < one) + { + am1 = half * (yy/(r + xp1) + yy/(s - xm1)); + } + else + { + am1 = half * (yy/(r + xp1) + (s + xm1)); + } + imag = boost::math::log1p(am1 + std::sqrt(am1 * (a + one))); + } + else + { + imag = std::log(a + std::sqrt(a*a - one)); + } + } + else + { + // + // This is the Hull et al exception handling code from Fig 3 of their paper: + // + if(y <= (std::numeric_limits::epsilon() * std::fabs(xm1))) + { + if(x < one) + { + real = std::asin(x); + imag = y / std::sqrt(-xp1*xm1); + } + else + { + real = half_pi; + if(((std::numeric_limits::max)() / xp1) > xm1) + { + // xp1 * xm1 won't overflow: + imag = boost::math::log1p(xm1 + std::sqrt(xp1*xm1)); + } + else + { + imag = log_two + std::log(x); + } + } + } + else if(y <= safe_min) + { + // There is an assumption in Hull et al's analysis that + // if we get here then x == 1. This is true for all "good" + // machines where : + // + // E^2 > 8*sqrt(u); with: + // + // E = std::numeric_limits::epsilon() + // u = (std::numeric_limits::min)() + // + // Hull et al provide alternative code for "bad" machines + // but we have no way to test that here, so for now just assert + // on the assumption: + // + BOOST_MATH_ASSERT(x == 1); + real = half_pi - std::sqrt(y); + imag = std::sqrt(y); + } + else if(std::numeric_limits::epsilon() * y - one >= x) + { + real = x/y; // This can underflow! + imag = log_two + std::log(y); + } + else if(x > one) + { + real = std::atan(x/y); + T xoy = x/y; + imag = log_two + std::log(y) + half * boost::math::log1p(xoy*xoy); + } + else + { + T a = std::sqrt(one + y*y); + real = x/a; // This can underflow! + imag = half * boost::math::log1p(static_cast(2)*y*(y+a)); + } + } + } + + // + // Finish off by working out the sign of the result: + // + if((boost::math::signbit)(z.real())) + real = (boost::math::changesign)(real); + if((boost::math::signbit)(z.imag())) + imag = (boost::math::changesign)(imag); + + return std::complex(real, imag); +#ifdef _MSC_VER +#pragma warning(pop) +#endif +} + +} } // namespaces + +#endif // BOOST_MATH_COMPLEX_ASIN_INCLUDED diff --git a/libcxx/src/third-party/boost/math/complex/asinh.hpp b/libcxx/src/third-party/boost/math/complex/asinh.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/complex/asinh.hpp @@ -0,0 +1,32 @@ +// (C) Copyright John Maddock 2005. +// 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_COMPLEX_ASINH_INCLUDED +#define BOOST_MATH_COMPLEX_ASINH_INCLUDED + +#ifndef BOOST_MATH_COMPLEX_DETAILS_INCLUDED +# include +#endif +#ifndef BOOST_MATH_COMPLEX_ASIN_INCLUDED +# include +#endif + +namespace boost{ namespace math{ + +template +inline std::complex asinh(const std::complex& x) +{ + // + // We use asinh(z) = i asin(-i z); + // Note that C99 defines this the other way around (which is + // to say asin is specified in terms of asinh), this is consistent + // with C99 though: + // + return ::boost::math::detail::mult_i(::boost::math::asin(::boost::math::detail::mult_minus_i(x))); +} + +} } // namespaces + +#endif // BOOST_MATH_COMPLEX_ASINH_INCLUDED diff --git a/libcxx/src/third-party/boost/math/complex/atan.hpp b/libcxx/src/third-party/boost/math/complex/atan.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/complex/atan.hpp @@ -0,0 +1,36 @@ +// (C) Copyright John Maddock 2005. +// 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_COMPLEX_ATAN_INCLUDED +#define BOOST_MATH_COMPLEX_ATAN_INCLUDED + +#ifndef BOOST_MATH_COMPLEX_DETAILS_INCLUDED +# include +#endif +#ifndef BOOST_MATH_COMPLEX_ATANH_INCLUDED +# include +#endif + +namespace boost{ namespace math{ + +template +std::complex atan(const std::complex& x) +{ + // + // We're using the C99 definition here; atan(z) = -i atanh(iz): + // + if(x.real() == 0) + { + if(x.imag() == 1) + return std::complex(0, std::numeric_limits::has_infinity ? std::numeric_limits::infinity() : static_cast(HUGE_VAL)); + if(x.imag() == -1) + return std::complex(0, std::numeric_limits::has_infinity ? -std::numeric_limits::infinity() : -static_cast(HUGE_VAL)); + } + return ::boost::math::detail::mult_minus_i(::boost::math::atanh(::boost::math::detail::mult_i(x))); +} + +} } // namespaces + +#endif // BOOST_MATH_COMPLEX_ATAN_INCLUDED diff --git a/libcxx/src/third-party/boost/math/complex/atanh.hpp b/libcxx/src/third-party/boost/math/complex/atanh.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/complex/atanh.hpp @@ -0,0 +1,214 @@ +// (C) Copyright John Maddock 2005. +// 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_COMPLEX_ATANH_INCLUDED +#define BOOST_MATH_COMPLEX_ATANH_INCLUDED + +#ifndef BOOST_MATH_COMPLEX_DETAILS_INCLUDED +# include +#endif +#ifndef BOOST_MATH_LOG1P_INCLUDED +# include +#endif +#include + +#ifdef BOOST_NO_STDC_NAMESPACE +namespace std{ using ::sqrt; using ::fabs; using ::acos; using ::asin; using ::atan; using ::atan2; } +#endif + +namespace boost{ namespace math{ + +template +std::complex atanh(const std::complex& z) +{ + // + // References: + // + // Eric W. Weisstein. "Inverse Hyperbolic Tangent." + // From MathWorld--A Wolfram Web Resource. + // http://mathworld.wolfram.com/InverseHyperbolicTangent.html + // + // Also: The Wolfram Functions Site, + // http://functions.wolfram.com/ElementaryFunctions/ArcTanh/ + // + // Also "Abramowitz and Stegun. Handbook of Mathematical Functions." + // at : http://jove.prohosting.com/~skripty/toc.htm + // + // See also: https://svn.boost.org/trac/boost/ticket/7291 + // + + static const T pi = boost::math::constants::pi(); + static const T half_pi = pi / 2; + static const T one = static_cast(1.0L); + static const T two = static_cast(2.0L); + static const T four = static_cast(4.0L); + static const T zero = static_cast(0); + static const T log_two = boost::math::constants::ln_two(); + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4127) +#endif + + T x = std::fabs(z.real()); + T y = std::fabs(z.imag()); + + T real, imag; // our results + + T safe_upper = detail::safe_max(two); + T safe_lower = detail::safe_min(static_cast(2)); + + // + // Begin by handling the special cases specified in C99: + // + if((boost::math::isnan)(x)) + { + if((boost::math::isnan)(y)) + return std::complex(x, x); + else if((boost::math::isinf)(y)) + return std::complex(0, ((boost::math::signbit)(z.imag()) ? -half_pi : half_pi)); + else + return std::complex(x, x); + } + else if((boost::math::isnan)(y)) + { + if(x == 0) + return std::complex(x, y); + if((boost::math::isinf)(x)) + return std::complex(0, y); + else + return std::complex(y, y); + } + else if((x > safe_lower) && (x < safe_upper) && (y > safe_lower) && (y < safe_upper)) + { + + T yy = y*y; + T mxm1 = one - x; + /// + // The real part is given by: + // + // real(atanh(z)) == log1p(4*x / ((x-1)*(x-1) + y^2)) + // + real = boost::math::log1p(four * x / (mxm1*mxm1 + yy)); + real /= four; + if((boost::math::signbit)(z.real())) + real = (boost::math::changesign)(real); + + imag = std::atan2((y * two), (mxm1*(one+x) - yy)); + imag /= two; + if(z.imag() < 0) + imag = (boost::math::changesign)(imag); + } + else + { + // + // This section handles exception cases that would normally cause + // underflow or overflow in the main formulas. + // + // Begin by working out the real part, we need to approximate + // real = boost::math::log1p(4x / ((x-1)^2 + y^2)) + // without either overflow or underflow in the squared terms. + // + T mxm1 = one - x; + if(x >= safe_upper) + { + // x-1 = x to machine precision: + if((boost::math::isinf)(x) || (boost::math::isinf)(y)) + { + real = 0; + } + else if(y >= safe_upper) + { + // Big x and y: divide through by x*y: + real = boost::math::log1p((four/y) / (x/y + y/x)); + } + else if(y > one) + { + // Big x: divide through by x: + real = boost::math::log1p(four / (x + y*y/x)); + } + else + { + // Big x small y, as above but neglect y^2/x: + real = boost::math::log1p(four/x); + } + } + else if(y >= safe_upper) + { + if(x > one) + { + // Big y, medium x, divide through by y: + real = boost::math::log1p((four*x/y) / (y + mxm1*mxm1/y)); + } + else + { + // Small or medium x, large y: + real = four*x/y/y; + } + } + else if (x != one) + { + // y is small, calculate divisor carefully: + T div = mxm1*mxm1; + if(y > safe_lower) + div += y*y; + real = boost::math::log1p(four*x/div); + } + else + real = boost::math::changesign(two * (std::log(y) - log_two)); + + real /= four; + if((boost::math::signbit)(z.real())) + real = (boost::math::changesign)(real); + + // + // Now handle imaginary part, this is much easier, + // if x or y are large, then the formula: + // atan2(2y, (1-x)*(1+x) - y^2) + // evaluates to +-(PI - theta) where theta is negligible compared to PI. + // + if((x >= safe_upper) || (y >= safe_upper)) + { + imag = pi; + } + else if(x <= safe_lower) + { + // + // If both x and y are small then atan(2y), + // otherwise just x^2 is negligible in the divisor: + // + if(y <= safe_lower) + imag = std::atan2(two*y, one); + else + { + if((y == zero) && (x == zero)) + imag = 0; + else + imag = std::atan2(two*y, one - y*y); + } + } + else + { + // + // y^2 is negligible: + // + if((y == zero) && (x == one)) + imag = 0; + else + imag = std::atan2(two*y, mxm1*(one+x)); + } + imag /= two; + if((boost::math::signbit)(z.imag())) + imag = (boost::math::changesign)(imag); + } + return std::complex(real, imag); +#ifdef _MSC_VER +#pragma warning(pop) +#endif +} + +} } // namespaces + +#endif // BOOST_MATH_COMPLEX_ATANH_INCLUDED diff --git a/libcxx/src/third-party/boost/math/complex/details.hpp b/libcxx/src/third-party/boost/math/complex/details.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/complex/details.hpp @@ -0,0 +1,69 @@ +// (C) Copyright John Maddock 2005. +// 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_COMPLEX_DETAILS_INCLUDED +#define BOOST_MATH_COMPLEX_DETAILS_INCLUDED +// +// This header contains all the support code that is common to the +// inverse trig complex functions, it also contains all the includes +// that we need to implement all these functions. +// + +#include +#include +#include +#include +#include +#include +#include + +namespace boost{ namespace math{ namespace detail{ + +template +inline T mult_minus_one(const T& t) +{ + return (boost::math::isnan)(t) ? t : (boost::math::changesign)(t); +} + +template +inline std::complex mult_i(const std::complex& t) +{ + return std::complex(mult_minus_one(t.imag()), t.real()); +} + +template +inline std::complex mult_minus_i(const std::complex& t) +{ + return std::complex(t.imag(), mult_minus_one(t.real())); +} + +template +inline T safe_max(T t) +{ + return std::sqrt((std::numeric_limits::max)()) / t; +} +inline long double safe_max(long double t) +{ + // long double sqrt often returns infinity due to + // insufficient internal precision: + return std::sqrt((std::numeric_limits::max)()) / t; +} + +template +inline T safe_min(T t) +{ + return std::sqrt((std::numeric_limits::min)()) * t; +} +inline long double safe_min(long double t) +{ + // long double sqrt often returns zero due to + // insufficient internal precision: + return std::sqrt((std::numeric_limits::min)()) * t; +} + +} } } // namespaces + +#endif // BOOST_MATH_COMPLEX_DETAILS_INCLUDED + diff --git a/libcxx/src/third-party/boost/math/complex/fabs.hpp b/libcxx/src/third-party/boost/math/complex/fabs.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/complex/fabs.hpp @@ -0,0 +1,23 @@ +// (C) Copyright John Maddock 2005. +// 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_COMPLEX_FABS_INCLUDED +#define BOOST_MATH_COMPLEX_FABS_INCLUDED + +#ifndef BOOST_MATH_HYPOT_INCLUDED +# include +#endif + +namespace boost{ namespace math{ + +template +inline T fabs(const std::complex& z) +{ + return ::boost::math::hypot(z.real(), z.imag()); +} + +} } // namespaces + +#endif // BOOST_MATH_COMPLEX_FABS_INCLUDED diff --git a/libcxx/src/third-party/boost/math/concepts/distributions.hpp b/libcxx/src/third-party/boost/math/concepts/distributions.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/concepts/distributions.hpp @@ -0,0 +1,497 @@ +// Copyright John Maddock 2006. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// distributions.hpp provides definitions of the concept of a distribution +// and non-member accessor functions that must be implemented by all distributions. +// This is used to verify that +// all the features of a distributions have been fully implemented. + +#ifndef BOOST_MATH_DISTRIBUTION_CONCEPT_HPP +#define BOOST_MATH_DISTRIBUTION_CONCEPT_HPP + +#ifndef BOOST_MATH_STANDALONE + +#include +#include +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4100) +#pragma warning(disable: 4510) +#pragma warning(disable: 4610) +#pragma warning(disable: 4189) // local variable is initialized but not referenced. +#endif +#include +#ifdef _MSC_VER +#pragma warning(pop) +#endif +#include + +namespace boost{ +namespace math{ + +namespace concepts +{ +// Begin by defining a concept archetype +// for a distribution class: +// +template +class distribution_archetype +{ +public: + typedef RealType value_type; + + distribution_archetype(const distribution_archetype&); // Copy constructible. + distribution_archetype& operator=(const distribution_archetype&); // Assignable. + + // There is no default constructor, + // but we need a way to instantiate the archetype: + static distribution_archetype& get_object() + { + // will never get caled: + return *reinterpret_cast(nullptr); + } +}; // template class distribution_archetype + +// Non-member accessor functions: +// (This list defines the functions that must be implemented by all distributions). + +template +RealType pdf(const distribution_archetype& dist, const RealType& x); + +template +RealType cdf(const distribution_archetype& dist, const RealType& x); + +template +RealType quantile(const distribution_archetype& dist, const RealType& p); + +template +RealType cdf(const complemented2_type, RealType>& c); + +template +RealType quantile(const complemented2_type, RealType>& c); + +template +RealType mean(const distribution_archetype& dist); + +template +RealType standard_deviation(const distribution_archetype& dist); + +template +RealType variance(const distribution_archetype& dist); + +template +RealType hazard(const distribution_archetype& dist); + +template +RealType chf(const distribution_archetype& dist); +// http://en.wikipedia.org/wiki/Characteristic_function_%28probability_theory%29 + +template +RealType coefficient_of_variation(const distribution_archetype& dist); + +template +RealType mode(const distribution_archetype& dist); + +template +RealType skewness(const distribution_archetype& dist); + +template +RealType kurtosis_excess(const distribution_archetype& dist); + +template +RealType kurtosis(const distribution_archetype& dist); + +template +RealType median(const distribution_archetype& dist); + +template +std::pair range(const distribution_archetype& dist); + +template +std::pair support(const distribution_archetype& dist); + +// +// Next comes the concept checks for verifying that a class +// fulfils the requirements of a Distribution: +// +template +struct DistributionConcept +{ + typedef typename Distribution::value_type value_type; + + void constraints() + { + function_requires >(); + function_requires >(); + + const Distribution& dist = DistributionConcept::get_object(); + + value_type x = 0; + // The result values are ignored in all these checks. + value_type v = cdf(dist, x); + v = cdf(complement(dist, x)); + suppress_unused_variable_warning(v); + v = pdf(dist, x); + suppress_unused_variable_warning(v); + v = quantile(dist, x); + suppress_unused_variable_warning(v); + v = quantile(complement(dist, x)); + suppress_unused_variable_warning(v); + v = mean(dist); + suppress_unused_variable_warning(v); + v = mode(dist); + suppress_unused_variable_warning(v); + v = standard_deviation(dist); + suppress_unused_variable_warning(v); + v = variance(dist); + suppress_unused_variable_warning(v); + v = hazard(dist, x); + suppress_unused_variable_warning(v); + v = chf(dist, x); + suppress_unused_variable_warning(v); + v = coefficient_of_variation(dist); + suppress_unused_variable_warning(v); + v = skewness(dist); + suppress_unused_variable_warning(v); + v = kurtosis(dist); + suppress_unused_variable_warning(v); + v = kurtosis_excess(dist); + suppress_unused_variable_warning(v); + v = median(dist); + suppress_unused_variable_warning(v); + std::pair pv; + pv = range(dist); + suppress_unused_variable_warning(pv); + pv = support(dist); + suppress_unused_variable_warning(pv); + + float f = 1; + v = cdf(dist, f); + suppress_unused_variable_warning(v); + v = cdf(complement(dist, f)); + suppress_unused_variable_warning(v); + v = pdf(dist, f); + suppress_unused_variable_warning(v); + v = quantile(dist, f); + suppress_unused_variable_warning(v); + v = quantile(complement(dist, f)); + suppress_unused_variable_warning(v); + v = hazard(dist, f); + suppress_unused_variable_warning(v); + v = chf(dist, f); + suppress_unused_variable_warning(v); + double d = 1; + v = cdf(dist, d); + suppress_unused_variable_warning(v); + v = cdf(complement(dist, d)); + suppress_unused_variable_warning(v); + v = pdf(dist, d); + suppress_unused_variable_warning(v); + v = quantile(dist, d); + suppress_unused_variable_warning(v); + v = quantile(complement(dist, d)); + suppress_unused_variable_warning(v); + v = hazard(dist, d); + suppress_unused_variable_warning(v); + v = chf(dist, d); + suppress_unused_variable_warning(v); +#ifndef TEST_MPFR + long double ld = 1; + v = cdf(dist, ld); + suppress_unused_variable_warning(v); + v = cdf(complement(dist, ld)); + suppress_unused_variable_warning(v); + v = pdf(dist, ld); + suppress_unused_variable_warning(v); + v = quantile(dist, ld); + suppress_unused_variable_warning(v); + v = quantile(complement(dist, ld)); + suppress_unused_variable_warning(v); + v = hazard(dist, ld); + suppress_unused_variable_warning(v); + v = chf(dist, ld); + suppress_unused_variable_warning(v); +#endif + int i = 1; + v = cdf(dist, i); + suppress_unused_variable_warning(v); + v = cdf(complement(dist, i)); + suppress_unused_variable_warning(v); + v = pdf(dist, i); + suppress_unused_variable_warning(v); + v = quantile(dist, i); + suppress_unused_variable_warning(v); + v = quantile(complement(dist, i)); + suppress_unused_variable_warning(v); + v = hazard(dist, i); + suppress_unused_variable_warning(v); + v = chf(dist, i); + suppress_unused_variable_warning(v); + unsigned long li = 1; + v = cdf(dist, li); + suppress_unused_variable_warning(v); + v = cdf(complement(dist, li)); + suppress_unused_variable_warning(v); + v = pdf(dist, li); + suppress_unused_variable_warning(v); + v = quantile(dist, li); + suppress_unused_variable_warning(v); + v = quantile(complement(dist, li)); + suppress_unused_variable_warning(v); + v = hazard(dist, li); + suppress_unused_variable_warning(v); + v = chf(dist, li); + suppress_unused_variable_warning(v); + test_extra_members(dist); + } + template + static void test_extra_members(const D&) + {} + template + static void test_extra_members(const boost::math::bernoulli_distribution& d) + { + value_type r = d.success_fraction(); + (void)r; // warning suppression + } + template + static void test_extra_members(const boost::math::beta_distribution& d) + { + value_type r1 = d.alpha(); + value_type r2 = d.beta(); + r1 = boost::math::beta_distribution::find_alpha(r1, r2); + suppress_unused_variable_warning(r1); + r1 = boost::math::beta_distribution::find_beta(r1, r2); + suppress_unused_variable_warning(r1); + r1 = boost::math::beta_distribution::find_alpha(r1, r2, r1); + suppress_unused_variable_warning(r1); + r1 = boost::math::beta_distribution::find_beta(r1, r2, r1); + suppress_unused_variable_warning(r1); + } + template + static void test_extra_members(const boost::math::binomial_distribution& d) + { + value_type r = d.success_fraction(); + r = d.trials(); + r = Distribution::find_lower_bound_on_p(r, r, r); + r = Distribution::find_lower_bound_on_p(r, r, r, Distribution::clopper_pearson_exact_interval); + r = Distribution::find_lower_bound_on_p(r, r, r, Distribution::jeffreys_prior_interval); + r = Distribution::find_upper_bound_on_p(r, r, r); + r = Distribution::find_upper_bound_on_p(r, r, r, Distribution::clopper_pearson_exact_interval); + r = Distribution::find_upper_bound_on_p(r, r, r, Distribution::jeffreys_prior_interval); + r = Distribution::find_minimum_number_of_trials(r, r, r); + r = Distribution::find_maximum_number_of_trials(r, r, r); + suppress_unused_variable_warning(r); + } + template + static void test_extra_members(const boost::math::cauchy_distribution& d) + { + value_type r = d.location(); + r = d.scale(); + suppress_unused_variable_warning(r); + } + template + static void test_extra_members(const boost::math::chi_squared_distribution& d) + { + value_type r = d.degrees_of_freedom(); + r = Distribution::find_degrees_of_freedom(r, r, r, r); + r = Distribution::find_degrees_of_freedom(r, r, r, r, r); + suppress_unused_variable_warning(r); + } + template + static void test_extra_members(const boost::math::exponential_distribution& d) + { + value_type r = d.lambda(); + suppress_unused_variable_warning(r); + } + template + static void test_extra_members(const boost::math::extreme_value_distribution& d) + { + value_type r = d.scale(); + r = d.location(); + suppress_unused_variable_warning(r); + } + template + static void test_extra_members(const boost::math::fisher_f_distribution& d) + { + value_type r = d.degrees_of_freedom1(); + r = d.degrees_of_freedom2(); + suppress_unused_variable_warning(r); + } + template + static void test_extra_members(const boost::math::gamma_distribution& d) + { + value_type r = d.scale(); + r = d.shape(); + suppress_unused_variable_warning(r); + } + template + static void test_extra_members(const boost::math::inverse_chi_squared_distribution& d) + { + value_type r = d.scale(); + r = d.degrees_of_freedom(); + suppress_unused_variable_warning(r); + } + template + static void test_extra_members(const boost::math::inverse_gamma_distribution& d) + { + value_type r = d.scale(); + r = d.shape(); + suppress_unused_variable_warning(r); + } + template + static void test_extra_members(const boost::math::hypergeometric_distribution& d) + { + unsigned u = d.defective(); + u = d.sample_count(); + u = d.total(); + suppress_unused_variable_warning(u); + } + template + static void test_extra_members(const boost::math::laplace_distribution& d) + { + value_type r = d.scale(); + r = d.location(); + suppress_unused_variable_warning(r); + } + template + static void test_extra_members(const boost::math::logistic_distribution& d) + { + value_type r = d.scale(); + r = d.location(); + suppress_unused_variable_warning(r); + } + template + static void test_extra_members(const boost::math::lognormal_distribution& d) + { + value_type r = d.scale(); + r = d.location(); + suppress_unused_variable_warning(r); + } + template + static void test_extra_members(const boost::math::negative_binomial_distribution& d) + { + value_type r = d.success_fraction(); + r = d.successes(); + r = Distribution::find_lower_bound_on_p(r, r, r); + r = Distribution::find_upper_bound_on_p(r, r, r); + r = Distribution::find_minimum_number_of_trials(r, r, r); + r = Distribution::find_maximum_number_of_trials(r, r, r); + suppress_unused_variable_warning(r); + } + template + static void test_extra_members(const boost::math::non_central_beta_distribution& d) + { + value_type r1 = d.alpha(); + value_type r2 = d.beta(); + r1 = d.non_centrality(); + (void)r1; // warning suppression + (void)r2; // warning suppression + } + template + static void test_extra_members(const boost::math::non_central_chi_squared_distribution& d) + { + value_type r = d.degrees_of_freedom(); + r = d.non_centrality(); + r = Distribution::find_degrees_of_freedom(r, r, r); + r = Distribution::find_degrees_of_freedom(boost::math::complement(r, r, r)); + r = Distribution::find_non_centrality(r, r, r); + r = Distribution::find_non_centrality(boost::math::complement(r, r, r)); + (void)r; // warning suppression + } + template + static void test_extra_members(const boost::math::non_central_f_distribution& d) + { + value_type r = d.degrees_of_freedom1(); + r = d.degrees_of_freedom2(); + r = d.non_centrality(); + (void)r; // warning suppression + } + template + static void test_extra_members(const boost::math::non_central_t_distribution& d) + { + value_type r = d.degrees_of_freedom(); + r = d.non_centrality(); + (void)r; // warning suppression + } + template + static void test_extra_members(const boost::math::normal_distribution& d) + { + value_type r = d.scale(); + r = d.location(); + r = d.mean(); + r = d.standard_deviation(); + (void)r; // warning suppression + } + template + static void test_extra_members(const boost::math::pareto_distribution& d) + { + value_type r = d.scale(); + r = d.shape(); + (void)r; // warning suppression + } + template + static void test_extra_members(const boost::math::poisson_distribution& d) + { + value_type r = d.mean(); + (void)r; // warning suppression + } + template + static void test_extra_members(const boost::math::rayleigh_distribution& d) + { + value_type r = d.sigma(); + (void)r; // warning suppression + } + template + static void test_extra_members(const boost::math::students_t_distribution& d) + { + value_type r = d.degrees_of_freedom(); + r = d.find_degrees_of_freedom(r, r, r, r); + r = d.find_degrees_of_freedom(r, r, r, r, r); + (void)r; // warning suppression + } + template + static void test_extra_members(const boost::math::triangular_distribution& d) + { + value_type r = d.lower(); + r = d.mode(); + r = d.upper(); + (void)r; // warning suppression + } + template + static void test_extra_members(const boost::math::weibull_distribution& d) + { + value_type r = d.scale(); + r = d.shape(); + (void)r; // warning suppression + } + template + static void test_extra_members(const boost::math::uniform_distribution& d) + { + value_type r = d.lower(); + r = d.upper(); + (void)r; // warning suppression + } +private: + static Distribution* pd; + static Distribution& get_object() + { + // In reality this will never get called: + return *pd; + } +}; // struct DistributionConcept + +template +Distribution* DistributionConcept::pd = 0; + +} // namespace concepts +} // namespace math +} // namespace boost + +#else +#error This header can not be used in standalone mode. +#endif // BOOST_MATH_STANDALONE + +#endif // BOOST_MATH_DISTRIBUTION_CONCEPT_HPP + diff --git a/libcxx/src/third-party/boost/math/concepts/real_concept.hpp b/libcxx/src/third-party/boost/math/concepts/real_concept.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/concepts/real_concept.hpp @@ -0,0 +1,380 @@ +// Copyright John Maddock 2006. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// Test real concept. + +// real_concept is an archetype for User defined Real types. + +// This file defines the features, constructors, operators, functions... +// that are essential to use mathematical and statistical functions. +// The template typename "RealType" is used where this type +// (as well as the normal built-in types, float, double & long double) +// can be used. +// That this is the minimum set is confirmed by use as a type +// in tests of all functions & distributions, for example: +// test_spots(0.F); & test_spots(0.); for float and double, but also +// test_spots(boost::math::concepts::real_concept(0.)); +// NTL quad_float type is an example of a type meeting the requirements, +// but note minor additions are needed - see ntl.diff and documentation +// "Using With NTL - a High-Precision Floating-Point Library". + +#ifndef BOOST_MATH_REAL_CONCEPT_HPP +#define BOOST_MATH_REAL_CONCEPT_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(__SGI_STL_PORT) +# include +#endif +#include +#include +#include +#include +#include + +#if defined(__SGI_STL_PORT) || defined(_RWSTD_VER) || defined(__LIBCOMO__) +# include +#endif + +namespace boost{ namespace math{ + +namespace concepts +{ + +#ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + typedef double real_concept_base_type; +#else + typedef long double real_concept_base_type; +#endif + +class real_concept +{ +public: + // Constructors: + real_concept() : m_value(0){} + real_concept(char c) : m_value(c){} + real_concept(wchar_t c) : m_value(c){} + real_concept(unsigned char c) : m_value(c){} + real_concept(signed char c) : m_value(c){} + real_concept(unsigned short c) : m_value(c){} + real_concept(short c) : m_value(c){} + real_concept(unsigned int c) : m_value(c){} + real_concept(int c) : m_value(c){} + real_concept(unsigned long c) : m_value(c){} + real_concept(long c) : m_value(c){} + real_concept(unsigned long long c) : m_value(static_cast(c)){} + real_concept(long long c) : m_value(static_cast(c)){} + real_concept(float c) : m_value(c){} + real_concept(double c) : m_value(c){} + real_concept(long double c) : m_value(c){} +#ifdef BOOST_MATH_USE_FLOAT128 + real_concept(BOOST_MATH_FLOAT128_TYPE c) : m_value(c){} +#endif + + // Assignment: + real_concept& operator=(char c) { m_value = c; return *this; } + real_concept& operator=(unsigned char c) { m_value = c; return *this; } + real_concept& operator=(signed char c) { m_value = c; return *this; } + real_concept& operator=(wchar_t c) { m_value = c; return *this; } + real_concept& operator=(short c) { m_value = c; return *this; } + real_concept& operator=(unsigned short c) { m_value = c; return *this; } + real_concept& operator=(int c) { m_value = c; return *this; } + real_concept& operator=(unsigned int c) { m_value = c; return *this; } + real_concept& operator=(long c) { m_value = c; return *this; } + real_concept& operator=(unsigned long c) { m_value = c; return *this; } + real_concept& operator=(long long c) { m_value = static_cast(c); return *this; } + real_concept& operator=(unsigned long long c) { m_value = static_cast(c); return *this; } + real_concept& operator=(float c) { m_value = c; return *this; } + real_concept& operator=(double c) { m_value = c; return *this; } + real_concept& operator=(long double c) { m_value = c; return *this; } + + // Access: + real_concept_base_type value()const{ return m_value; } + + // Member arithmetic: + real_concept& operator+=(const real_concept& other) + { m_value += other.value(); return *this; } + real_concept& operator-=(const real_concept& other) + { m_value -= other.value(); return *this; } + real_concept& operator*=(const real_concept& other) + { m_value *= other.value(); return *this; } + real_concept& operator/=(const real_concept& other) + { m_value /= other.value(); return *this; } + real_concept operator-()const + { return -m_value; } + real_concept const& operator+()const + { return *this; } + real_concept& operator++() + { ++m_value; return *this; } + real_concept& operator--() + { --m_value; return *this; } + +private: + real_concept_base_type m_value; +}; + +// Non-member arithmetic: +inline real_concept operator+(const real_concept& a, const real_concept& b) +{ + real_concept result(a); + result += b; + return result; +} +inline real_concept operator-(const real_concept& a, const real_concept& b) +{ + real_concept result(a); + result -= b; + return result; +} +inline real_concept operator*(const real_concept& a, const real_concept& b) +{ + real_concept result(a); + result *= b; + return result; +} +inline real_concept operator/(const real_concept& a, const real_concept& b) +{ + real_concept result(a); + result /= b; + return result; +} + +// Comparison: +inline bool operator == (const real_concept& a, const real_concept& b) +{ return a.value() == b.value(); } +inline bool operator != (const real_concept& a, const real_concept& b) +{ return a.value() != b.value();} +inline bool operator < (const real_concept& a, const real_concept& b) +{ return a.value() < b.value(); } +inline bool operator <= (const real_concept& a, const real_concept& b) +{ return a.value() <= b.value(); } +inline bool operator > (const real_concept& a, const real_concept& b) +{ return a.value() > b.value(); } +inline bool operator >= (const real_concept& a, const real_concept& b) +{ return a.value() >= b.value(); } + +// Non-member functions: +inline real_concept acos(real_concept a) +{ return std::acos(a.value()); } +inline real_concept cos(real_concept a) +{ return std::cos(a.value()); } +inline real_concept asin(real_concept a) +{ return std::asin(a.value()); } +inline real_concept atan(real_concept a) +{ return std::atan(a.value()); } +inline real_concept atan2(real_concept a, real_concept b) +{ return std::atan2(a.value(), b.value()); } +inline real_concept ceil(real_concept a) +{ return std::ceil(a.value()); } +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS +// I've seen std::fmod(long double) crash on some platforms +// so use fmodl instead: +#ifdef _WIN32_WCE +// +// Ugly workaround for macro fmodl: +// +inline long double call_fmodl(long double a, long double b) +{ return fmodl(a, b); } +inline real_concept fmod(real_concept a, real_concept b) +{ return call_fmodl(a.value(), b.value()); } +#else +inline real_concept fmod(real_concept a, real_concept b) +{ return fmodl(a.value(), b.value()); } +#endif +#endif +inline real_concept cosh(real_concept a) +{ return std::cosh(a.value()); } +inline real_concept exp(real_concept a) +{ return std::exp(a.value()); } +inline real_concept fabs(real_concept a) +{ return std::fabs(a.value()); } +inline real_concept abs(real_concept a) +{ return std::abs(a.value()); } +inline real_concept floor(real_concept a) +{ return std::floor(a.value()); } +inline real_concept modf(real_concept a, real_concept* ipart) +{ +#ifdef __MINGW32__ + real_concept_base_type ip; + real_concept_base_type result = boost::math::modf(a.value(), &ip); + *ipart = ip; + return result; +#else + real_concept_base_type ip; + real_concept_base_type result = std::modf(a.value(), &ip); + *ipart = ip; + return result; +#endif +} +inline real_concept frexp(real_concept a, int* expon) +{ return std::frexp(a.value(), expon); } +inline real_concept ldexp(real_concept a, int expon) +{ return std::ldexp(a.value(), expon); } +inline real_concept log(real_concept a) +{ return std::log(a.value()); } +inline real_concept log10(real_concept a) +{ return std::log10(a.value()); } +inline real_concept tan(real_concept a) +{ return std::tan(a.value()); } +inline real_concept pow(real_concept a, real_concept b) +{ return std::pow(a.value(), b.value()); } +#if !defined(__SUNPRO_CC) +inline real_concept pow(real_concept a, int b) +{ return std::pow(a.value(), b); } +#else +inline real_concept pow(real_concept a, int b) +{ return std::pow(a.value(), static_cast(b)); } +#endif +inline real_concept sin(real_concept a) +{ return std::sin(a.value()); } +inline real_concept sinh(real_concept a) +{ return std::sinh(a.value()); } +inline real_concept sqrt(real_concept a) +{ return std::sqrt(a.value()); } +inline real_concept tanh(real_concept a) +{ return std::tanh(a.value()); } + +// +// C++11 ism's +// Note that these must not actually call the std:: versions as that precludes using this +// header to test in C++03 mode, call the Boost versions instead: +// +inline boost::math::concepts::real_concept asinh(boost::math::concepts::real_concept a) +{ + return boost::math::asinh(a.value(), boost::math::policies::make_policy(boost::math::policies::overflow_error())); +} +inline boost::math::concepts::real_concept acosh(boost::math::concepts::real_concept a) +{ + return boost::math::acosh(a.value(), boost::math::policies::make_policy(boost::math::policies::overflow_error())); +} +inline boost::math::concepts::real_concept atanh(boost::math::concepts::real_concept a) +{ + return boost::math::atanh(a.value(), boost::math::policies::make_policy(boost::math::policies::overflow_error())); +} + +// +// Conversion and truncation routines: +// +template +inline int iround(const concepts::real_concept& v, const Policy& pol) +{ return boost::math::iround(v.value(), pol); } +inline int iround(const concepts::real_concept& v) +{ return boost::math::iround(v.value(), policies::policy<>()); } +template +inline long lround(const concepts::real_concept& v, const Policy& pol) +{ return boost::math::lround(v.value(), pol); } +inline long lround(const concepts::real_concept& v) +{ return boost::math::lround(v.value(), policies::policy<>()); } + +template +inline long long llround(const concepts::real_concept& v, const Policy& pol) +{ return boost::math::llround(v.value(), pol); } +inline long long llround(const concepts::real_concept& v) +{ return boost::math::llround(v.value(), policies::policy<>()); } + +template +inline int itrunc(const concepts::real_concept& v, const Policy& pol) +{ return boost::math::itrunc(v.value(), pol); } +inline int itrunc(const concepts::real_concept& v) +{ return boost::math::itrunc(v.value(), policies::policy<>()); } +template +inline long ltrunc(const concepts::real_concept& v, const Policy& pol) +{ return boost::math::ltrunc(v.value(), pol); } +inline long ltrunc(const concepts::real_concept& v) +{ return boost::math::ltrunc(v.value(), policies::policy<>()); } + +template +inline long long lltrunc(const concepts::real_concept& v, const Policy& pol) +{ return boost::math::lltrunc(v.value(), pol); } +inline long long lltrunc(const concepts::real_concept& v) +{ return boost::math::lltrunc(v.value(), policies::policy<>()); } + +// Streaming: +template +inline std::basic_ostream& operator<<(std::basic_ostream& os, const real_concept& a) +{ + return os << a.value(); +} +template +inline std::basic_istream& operator>>(std::basic_istream& is, real_concept& a) +{ + real_concept_base_type v; + is >> v; + a = v; + return is; +} + +} // namespace concepts + +namespace tools +{ + +template <> +inline concepts::real_concept make_big_value(boost::math::tools::largest_float val, const char* , std::false_type const&, std::false_type const&) +{ + return val; // Can't use lexical_cast here, sometimes it fails.... +} + +template <> +inline concepts::real_concept max_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::real_concept)) +{ + return max_value(); +} + +template <> +inline concepts::real_concept min_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::real_concept)) +{ + return min_value(); +} + +template <> +inline concepts::real_concept log_max_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::real_concept)) +{ + return log_max_value(); +} + +template <> +inline concepts::real_concept log_min_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::real_concept)) +{ + return log_min_value(); +} + +template <> +inline concepts::real_concept epsilon(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::real_concept)) +{ +#ifdef __SUNPRO_CC + return std::numeric_limits::epsilon(); +#else + return tools::epsilon(); +#endif +} + +template <> +inline constexpr int digits(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::real_concept)) noexcept +{ + // Assume number of significand bits is same as real_concept_base_type, + // unless std::numeric_limits::is_specialized to provide digits. + return tools::digits(); + // Note that if numeric_limits real concept is NOT specialized to provide digits10 + // (or max_digits10) then the default precision of 6 decimal digits will be used + // by Boost test (giving misleading error messages like + // "difference between {9.79796} and {9.79796} exceeds 5.42101e-19%" + // and by Boost lexical cast and serialization causing loss of accuracy. +} + +} // namespace tools +} // namespace math +} // namespace boost + +#endif // BOOST_MATH_REAL_CONCEPT_HPP + + diff --git a/libcxx/src/third-party/boost/math/concepts/real_type_concept.hpp b/libcxx/src/third-party/boost/math/concepts/real_type_concept.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/concepts/real_type_concept.hpp @@ -0,0 +1,119 @@ +// Copyright John Maddock 2007-8. +// 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_REAL_TYPE_CONCEPT_HPP +#define BOOST_MATH_REAL_TYPE_CONCEPT_HPP + +#include +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4100) +#pragma warning(disable: 4510) +#pragma warning(disable: 4610) +#endif +#ifdef _MSC_VER +#pragma warning(pop) +#endif +#include +#include + + +namespace boost{ namespace math{ namespace concepts{ + +template +struct RealTypeConcept +{ + template + void check_binary_ops(Other o) const + { + RealType r(o); + r = o; + r -= o; + r += o; + r *= o; + r /= o; + r = r - o; + r = o - r; + r = r + o; + r = o + r; + r = o * r; + r = r * o; + r = r / o; + r = o / r; + bool b; + b = r == o; + suppress_unused_variable_warning(b); + b = o == r; + suppress_unused_variable_warning(b); + b = r != o; + suppress_unused_variable_warning(b); + b = o != r; + suppress_unused_variable_warning(b); + b = r <= o; + suppress_unused_variable_warning(b); + b = o <= r; + suppress_unused_variable_warning(b); + b = r >= o; + suppress_unused_variable_warning(b); + b = o >= r; + suppress_unused_variable_warning(b); + b = r < o; + suppress_unused_variable_warning(b); + b = o < r; + suppress_unused_variable_warning(b); + b = r > o; + suppress_unused_variable_warning(b); + b = o > r; + suppress_unused_variable_warning(b); + } + + void constraints() + { + BOOST_MATH_STD_USING + + RealType r; + check_binary_ops(r); + check_binary_ops(0.5f); + check_binary_ops(0.5); + //check_binary_ops(0.5L); + check_binary_ops(1); + //check_binary_ops(1u); + check_binary_ops(1L); + //check_binary_ops(1uL); + check_binary_ops(1LL); + RealType r2 = +r; + r2 = -r; + + r2 = fabs(r); + r2 = abs(r); + r2 = ceil(r); + r2 = floor(r); + r2 = exp(r); + r2 = pow(r, r2); + r2 = sqrt(r); + r2 = log(r); + r2 = cos(r); + r2 = sin(r); + r2 = tan(r); + r2 = asin(r); + r2 = acos(r); + r2 = atan(r); + int i {}; + r2 = ldexp(r, i); + r2 = frexp(r, &i); + i = boost::math::tools::digits(); + r2 = boost::math::tools::max_value(); + r2 = boost::math::tools::min_value(); + r2 = boost::math::tools::log_max_value(); + r2 = boost::math::tools::log_min_value(); + r2 = boost::math::tools::epsilon(); + } +}; // struct DistributionConcept + + +}}} // namespaces + +#endif + diff --git a/libcxx/src/third-party/boost/math/concepts/std_real_concept.hpp b/libcxx/src/third-party/boost/math/concepts/std_real_concept.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/concepts/std_real_concept.hpp @@ -0,0 +1,421 @@ +// Copyright John Maddock 2006. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// std_real_concept is an archetype for built-in Real types. + +// The main purpose in providing this type is to verify +// that std lib functions are found via a using declaration +// bringing those functions into the current scope, and not +// just because they happen to be in global scope. +// +// If ::pow is found rather than std::pow say, then the code +// will silently compile, but truncation of long doubles to +// double will cause a significant loss of precision. +// A template instantiated with std_real_concept will *only* +// compile if it std::whatever is in scope. + +#include +#include +#include +#include +#include +#include + +#ifndef BOOST_MATH_STD_REAL_CONCEPT_HPP +#define BOOST_MATH_STD_REAL_CONCEPT_HPP + +namespace boost{ namespace math{ + +namespace concepts +{ + +#ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + typedef double std_real_concept_base_type; +#else + typedef long double std_real_concept_base_type; +#endif + +class std_real_concept +{ +public: + // Constructors: + std_real_concept() : m_value(0){} + std_real_concept(char c) : m_value(c){} +#ifndef BOOST_NO_INTRINSIC_WCHAR_T + std_real_concept(wchar_t c) : m_value(c){} +#endif + std_real_concept(unsigned char c) : m_value(c){} + std_real_concept(signed char c) : m_value(c){} + std_real_concept(unsigned short c) : m_value(c){} + std_real_concept(short c) : m_value(c){} + std_real_concept(unsigned int c) : m_value(c){} + std_real_concept(int c) : m_value(c){} + std_real_concept(unsigned long c) : m_value(c){} + std_real_concept(long c) : m_value(c){} +#if defined(__DECCXX) || defined(__SUNPRO_CC) + std_real_concept(unsigned long long c) : m_value(static_cast(c)){} + std_real_concept(long long c) : m_value(static_cast(c)){} +#endif + std_real_concept(unsigned long long c) : m_value(static_cast(c)){} + std_real_concept(long long c) : m_value(static_cast(c)){} + std_real_concept(float c) : m_value(c){} + std_real_concept(double c) : m_value(c){} + std_real_concept(long double c) : m_value(c){} +#ifdef BOOST_MATH_USE_FLOAT128 + std_real_concept(BOOST_MATH_FLOAT128_TYPE c) : m_value(c){} +#endif + + // Assignment: + std_real_concept& operator=(char c) { m_value = c; return *this; } + std_real_concept& operator=(unsigned char c) { m_value = c; return *this; } + std_real_concept& operator=(signed char c) { m_value = c; return *this; } +#ifndef BOOST_NO_INTRINSIC_WCHAR_T + std_real_concept& operator=(wchar_t c) { m_value = c; return *this; } +#endif + std_real_concept& operator=(short c) { m_value = c; return *this; } + std_real_concept& operator=(unsigned short c) { m_value = c; return *this; } + std_real_concept& operator=(int c) { m_value = c; return *this; } + std_real_concept& operator=(unsigned int c) { m_value = c; return *this; } + std_real_concept& operator=(long c) { m_value = c; return *this; } + std_real_concept& operator=(unsigned long c) { m_value = c; return *this; } +#if defined(__DECCXX) || defined(__SUNPRO_CC) + std_real_concept& operator=(unsigned long long c) { m_value = static_cast(c); return *this; } + std_real_concept& operator=(long long c) { m_value = static_cast(c); return *this; } +#endif + std_real_concept& operator=(long long c) { m_value = static_cast(c); return *this; } + std_real_concept& operator=(unsigned long long c) { m_value = static_cast(c); return *this; } + + std_real_concept& operator=(float c) { m_value = c; return *this; } + std_real_concept& operator=(double c) { m_value = c; return *this; } + std_real_concept& operator=(long double c) { m_value = c; return *this; } + + // Access: + std_real_concept_base_type value()const{ return m_value; } + + // Member arithmetic: + std_real_concept& operator+=(const std_real_concept& other) + { m_value += other.value(); return *this; } + std_real_concept& operator-=(const std_real_concept& other) + { m_value -= other.value(); return *this; } + std_real_concept& operator*=(const std_real_concept& other) + { m_value *= other.value(); return *this; } + std_real_concept& operator/=(const std_real_concept& other) + { m_value /= other.value(); return *this; } + std_real_concept operator-()const + { return -m_value; } + std_real_concept const& operator+()const + { return *this; } + +private: + std_real_concept_base_type m_value; +}; + +// Non-member arithmetic: +inline std_real_concept operator+(const std_real_concept& a, const std_real_concept& b) +{ + std_real_concept result(a); + result += b; + return result; +} +inline std_real_concept operator-(const std_real_concept& a, const std_real_concept& b) +{ + std_real_concept result(a); + result -= b; + return result; +} +inline std_real_concept operator*(const std_real_concept& a, const std_real_concept& b) +{ + std_real_concept result(a); + result *= b; + return result; +} +inline std_real_concept operator/(const std_real_concept& a, const std_real_concept& b) +{ + std_real_concept result(a); + result /= b; + return result; +} + +// Comparison: +inline bool operator == (const std_real_concept& a, const std_real_concept& b) +{ return a.value() == b.value(); } +inline bool operator != (const std_real_concept& a, const std_real_concept& b) +{ return a.value() != b.value();} +inline bool operator < (const std_real_concept& a, const std_real_concept& b) +{ return a.value() < b.value(); } +inline bool operator <= (const std_real_concept& a, const std_real_concept& b) +{ return a.value() <= b.value(); } +inline bool operator > (const std_real_concept& a, const std_real_concept& b) +{ return a.value() > b.value(); } +inline bool operator >= (const std_real_concept& a, const std_real_concept& b) +{ return a.value() >= b.value(); } + +} // namespace concepts +} // namespace math +} // namespace boost + +namespace std{ + +// Non-member functions: +inline boost::math::concepts::std_real_concept acos(boost::math::concepts::std_real_concept a) +{ return std::acos(a.value()); } +inline boost::math::concepts::std_real_concept cos(boost::math::concepts::std_real_concept a) +{ return std::cos(a.value()); } +inline boost::math::concepts::std_real_concept asin(boost::math::concepts::std_real_concept a) +{ return std::asin(a.value()); } +inline boost::math::concepts::std_real_concept atan(boost::math::concepts::std_real_concept a) +{ return std::atan(a.value()); } +inline boost::math::concepts::std_real_concept atan2(boost::math::concepts::std_real_concept a, boost::math::concepts::std_real_concept b) +{ return std::atan2(a.value(), b.value()); } +inline boost::math::concepts::std_real_concept ceil(boost::math::concepts::std_real_concept a) +{ return std::ceil(a.value()); } +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS +inline boost::math::concepts::std_real_concept fmod(boost::math::concepts::std_real_concept a, boost::math::concepts::std_real_concept b) +{ return fmodl(a.value(), b.value()); } +#else +inline boost::math::concepts::std_real_concept fmod(boost::math::concepts::std_real_concept a, boost::math::concepts::std_real_concept b) +{ return std::fmod(a.value(), b.value()); } +#endif +inline boost::math::concepts::std_real_concept cosh(boost::math::concepts::std_real_concept a) +{ return std::cosh(a.value()); } +inline boost::math::concepts::std_real_concept exp(boost::math::concepts::std_real_concept a) +{ return std::exp(a.value()); } +inline boost::math::concepts::std_real_concept fabs(boost::math::concepts::std_real_concept a) +{ return std::fabs(a.value()); } +inline boost::math::concepts::std_real_concept abs(boost::math::concepts::std_real_concept a) +{ return std::abs(a.value()); } +inline boost::math::concepts::std_real_concept floor(boost::math::concepts::std_real_concept a) +{ return std::floor(a.value()); } +inline boost::math::concepts::std_real_concept modf(boost::math::concepts::std_real_concept a, boost::math::concepts::std_real_concept* ipart) +{ + boost::math::concepts::std_real_concept_base_type ip; + boost::math::concepts::std_real_concept_base_type result = std::modf(a.value(), &ip); + *ipart = ip; + return result; +} +inline boost::math::concepts::std_real_concept frexp(boost::math::concepts::std_real_concept a, int* expon) +{ return std::frexp(a.value(), expon); } +inline boost::math::concepts::std_real_concept ldexp(boost::math::concepts::std_real_concept a, int expon) +{ return std::ldexp(a.value(), expon); } +inline boost::math::concepts::std_real_concept log(boost::math::concepts::std_real_concept a) +{ return std::log(a.value()); } +inline boost::math::concepts::std_real_concept log10(boost::math::concepts::std_real_concept a) +{ return std::log10(a.value()); } +inline boost::math::concepts::std_real_concept tan(boost::math::concepts::std_real_concept a) +{ return std::tan(a.value()); } +inline boost::math::concepts::std_real_concept pow(boost::math::concepts::std_real_concept a, boost::math::concepts::std_real_concept b) +{ return std::pow(a.value(), b.value()); } +#if !defined(__SUNPRO_CC) +inline boost::math::concepts::std_real_concept pow(boost::math::concepts::std_real_concept a, int b) +{ return std::pow(a.value(), b); } +#else +inline boost::math::concepts::std_real_concept pow(boost::math::concepts::std_real_concept a, int b) +{ return std::pow(a.value(), static_cast(b)); } +#endif +inline boost::math::concepts::std_real_concept sin(boost::math::concepts::std_real_concept a) +{ return std::sin(a.value()); } +inline boost::math::concepts::std_real_concept sinh(boost::math::concepts::std_real_concept a) +{ return std::sinh(a.value()); } +inline boost::math::concepts::std_real_concept sqrt(boost::math::concepts::std_real_concept a) +{ return std::sqrt(a.value()); } +inline boost::math::concepts::std_real_concept tanh(boost::math::concepts::std_real_concept a) +{ return std::tanh(a.value()); } +inline boost::math::concepts::std_real_concept (nextafter)(boost::math::concepts::std_real_concept a, boost::math::concepts::std_real_concept b) +{ return (boost::math::nextafter)(a, b); } +// +// C++11 ism's +// Note that these must not actually call the std:: versions as that precludes using this +// header to test in C++03 mode, call the Boost versions instead: +// +inline boost::math::concepts::std_real_concept asinh(boost::math::concepts::std_real_concept a) +{ return boost::math::asinh(a.value(), boost::math::policies::make_policy(boost::math::policies::overflow_error())); } +inline boost::math::concepts::std_real_concept acosh(boost::math::concepts::std_real_concept a) +{ return boost::math::acosh(a.value(), boost::math::policies::make_policy(boost::math::policies::overflow_error())); } +inline boost::math::concepts::std_real_concept atanh(boost::math::concepts::std_real_concept a) +{ return boost::math::atanh(a.value(), boost::math::policies::make_policy(boost::math::policies::overflow_error())); } +inline bool (isfinite)(boost::math::concepts::std_real_concept a) +{ + return (boost::math::isfinite)(a.value()); +} + + +} // namespace std + +#include +#include +#include +#include + +namespace boost{ namespace math{ namespace concepts{ + +// +// Conversion and truncation routines: +// +template +inline int iround(const concepts::std_real_concept& v, const Policy& pol) +{ + return boost::math::iround(v.value(), pol); +} +inline int iround(const concepts::std_real_concept& v) +{ + return boost::math::iround(v.value(), policies::policy<>()); +} + +template +inline long lround(const concepts::std_real_concept& v, const Policy& pol) +{ + return boost::math::lround(v.value(), pol); +} +inline long lround(const concepts::std_real_concept& v) +{ + return boost::math::lround(v.value(), policies::policy<>()); +} + +template +inline long long llround(const concepts::std_real_concept& v, const Policy& pol) +{ + return boost::math::llround(v.value(), pol); +} +inline long long llround(const concepts::std_real_concept& v) +{ + return boost::math::llround(v.value(), policies::policy<>()); +} + +template +inline int itrunc(const concepts::std_real_concept& v, const Policy& pol) +{ + return boost::math::itrunc(v.value(), pol); +} +inline int itrunc(const concepts::std_real_concept& v) +{ + return boost::math::itrunc(v.value(), policies::policy<>()); +} + +template +inline long ltrunc(const concepts::std_real_concept& v, const Policy& pol) +{ + return boost::math::ltrunc(v.value(), pol); +} +inline long ltrunc(const concepts::std_real_concept& v) +{ + return boost::math::ltrunc(v.value(), policies::policy<>()); +} + +template +inline long long lltrunc(const concepts::std_real_concept& v, const Policy& pol) +{ + return boost::math::lltrunc(v.value(), pol); +} +inline long long lltrunc(const concepts::std_real_concept& v) +{ + return boost::math::lltrunc(v.value(), policies::policy<>()); +} + +// Streaming: +template +inline std::basic_ostream& operator<<(std::basic_ostream& os, const std_real_concept& a) +{ + return os << a.value(); +} +template +inline std::basic_istream& operator>>(std::basic_istream& is, std_real_concept& a) +{ +#if defined(__SGI_STL_PORT) || defined(_RWSTD_VER) || defined(__LIBCOMO__) || defined(_LIBCPP_VERSION) + std::string s; + std_real_concept_base_type d; + is >> s; + std::sscanf(s.c_str(), "%Lf", &d); + a = d; + return is; +#else + std_real_concept_base_type v; + is >> v; + a = v; + return is; +#endif +} + +} // namespace concepts +}} + +#include + +namespace boost{ namespace math{ +namespace tools +{ + +template <> +inline concepts::std_real_concept make_big_value(boost::math::tools::largest_float val, const char*, std::false_type const&, std::false_type const&) +{ + return val; // Can't use lexical_cast here, sometimes it fails.... +} + +template <> +inline concepts::std_real_concept max_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::std_real_concept)) +{ + return max_value(); +} + +template <> +inline concepts::std_real_concept min_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::std_real_concept)) +{ + return min_value(); +} + +template <> +inline concepts::std_real_concept log_max_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::std_real_concept)) +{ + return log_max_value(); +} + +template <> +inline concepts::std_real_concept log_min_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::std_real_concept)) +{ + return log_min_value(); +} + +template <> +inline concepts::std_real_concept epsilon(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::std_real_concept)) +{ + return tools::epsilon(); +} + +template <> +inline constexpr int digits(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::std_real_concept)) noexcept +{ // Assume number of significand bits is same as std_real_concept_base_type, + // unless std::numeric_limits::is_specialized to provide digits. + return digits(); +} + +template <> +inline double real_cast(concepts::std_real_concept r) +{ + return static_cast(r.value()); +} + + +} // namespace tools + +#if defined(_MSC_VER) && (_MSC_VER <= 1310) +using concepts::itrunc; +using concepts::ltrunc; +using concepts::lltrunc; +using concepts::iround; +using concepts::lround; +using concepts::llround; +#endif + +} // namespace math +} // namespace boost + +// +// These must go at the end, as they include stuff that won't compile until +// after std_real_concept has been defined: +// +#include +#include +#include + +#endif // BOOST_MATH_STD_REAL_CONCEPT_HPP diff --git a/libcxx/src/third-party/boost/math/constants/calculate_constants.hpp b/libcxx/src/third-party/boost/math/constants/calculate_constants.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/constants/calculate_constants.hpp @@ -0,0 +1,1110 @@ +// Copyright John Maddock 2010, 2012. +// Copyright Paul A. Bristow 2011, 2012. + +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_CALCULATE_CONSTANTS_CONSTANTS_INCLUDED +#define BOOST_MATH_CALCULATE_CONSTANTS_CONSTANTS_INCLUDED +#include + +namespace boost{ namespace math{ namespace constants{ namespace detail{ + +template +template +inline T constant_pi::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + + return ldexp(acos(T(0)), 1); + + /* + // Although this code works well, it's usually more accurate to just call acos + // and access the number types own representation of PI which is usually calculated + // at slightly higher precision... + + T result; + T a = 1; + T b; + T A(a); + T B = 0.5f; + T D = 0.25f; + + T lim; + lim = boost::math::tools::epsilon(); + + unsigned k = 1; + + do + { + result = A + B; + result = ldexp(result, -2); + b = sqrt(B); + a += b; + a = ldexp(a, -1); + A = a * a; + B = A - result; + B = ldexp(B, 1); + result = A - B; + bool neg = boost::math::sign(result) < 0; + if(neg) + result = -result; + if(result <= lim) + break; + if(neg) + result = -result; + result = ldexp(result, k - 1); + D -= result; + ++k; + lim = ldexp(lim, 1); + } + while(true); + + result = B / D; + return result; + */ +} + +template +template +inline T constant_two_pi::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + return 2 * pi > >(); +} + +template // 2 / pi +template +inline T constant_two_div_pi::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + return 2 / pi > >(); +} + +template // sqrt(2/pi) +template +inline T constant_root_two_div_pi::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return sqrt((2 / pi > >())); +} + +template +template +inline T constant_one_div_two_pi::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + return 1 / two_pi > >(); +} + +template +template +inline T constant_root_pi::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return sqrt(pi > >()); +} + +template +template +inline T constant_root_half_pi::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return sqrt(pi > >() / 2); +} + +template +template +inline T constant_root_two_pi::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return sqrt(two_pi > >()); +} + +template +template +inline T constant_log_root_two_pi::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return log(root_two_pi > >()); +} + +template +template +inline T constant_root_ln_four::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return sqrt(log(static_cast(4))); +} + +template +template +inline T constant_e::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + // + // Although we can clearly calculate this from first principles, this hooks into + // T's own notion of e, which hopefully will more accurate than one calculated to + // a few epsilon: + // + BOOST_MATH_STD_USING + return exp(static_cast(1)); +} + +template +template +inline T constant_half::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + return static_cast(1) / static_cast(2); +} + +template +template +inline T constant_euler::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + // + // This is the method described in: + // "Some New Algorithms for High-Precision Computation of Euler's Constant" + // Richard P Brent and Edwin M McMillan. + // Mathematics of Computation, Volume 34, Number 149, Jan 1980, pages 305-312. + // See equation 17 with p = 2. + // + T n = 3 + (M ? (std::min)(M, tools::digits()) : tools::digits()) / 4; + T lim = M ? ldexp(T(1), 1 - (std::min)(M, tools::digits())) : tools::epsilon(); + T lnn = log(n); + T term = 1; + T N = -lnn; + T D = 1; + T Hk = 0; + T one = 1; + + for(unsigned k = 1;; ++k) + { + term *= n * n; + term /= k * k; + Hk += one / k; + N += term * (Hk - lnn); + D += term; + + if(term < D * lim) + break; + } + return N / D; +} + +template +template +inline T constant_euler_sqr::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return euler > >() + * euler > >(); +} + +template +template +inline T constant_one_div_euler::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return static_cast(1) + / euler > >(); +} + + +template +template +inline T constant_root_two::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return sqrt(static_cast(2)); +} + + +template +template +inline T constant_root_three::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return sqrt(static_cast(3)); +} + +template +template +inline T constant_half_root_two::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return sqrt(static_cast(2)) / 2; +} + +template +template +inline T constant_ln_two::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + // + // Although there are good ways to calculate this from scratch, this hooks into + // T's own notion of log(2) which will hopefully be accurate to the full precision + // of T: + // + BOOST_MATH_STD_USING + return log(static_cast(2)); +} + +template +template +inline T constant_ln_ten::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return log(static_cast(10)); +} + +template +template +inline T constant_ln_ln_two::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return log(log(static_cast(2))); +} + +template +template +inline T constant_third::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return static_cast(1) / static_cast(3); +} + +template +template +inline T constant_twothirds::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return static_cast(2) / static_cast(3); +} + +template +template +inline T constant_two_thirds::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return static_cast(2) / static_cast(3); +} + +template +template +inline T constant_three_quarters::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return static_cast(3) / static_cast(4); +} + +template +template +inline T constant_sixth::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return static_cast(1) / static_cast(6); +} + +// Pi and related constants. +template +template +inline T constant_pi_minus_three::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + return pi > >() - static_cast(3); +} + +template +template +inline T constant_four_minus_pi::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + return static_cast(4) - pi > >(); +} + +template +template +inline T constant_exp_minus_half::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return exp(static_cast(-0.5)); +} + +template +template +inline T constant_exp_minus_one::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return exp(static_cast(-1.)); +} + +template +template +inline T constant_one_div_root_two::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + return static_cast(1) / root_two > >(); +} + +template +template +inline T constant_one_div_root_pi::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + return static_cast(1) / root_pi > >(); +} + +template +template +inline T constant_one_div_root_two_pi::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + return static_cast(1) / root_two_pi > >(); +} + +template +template +inline T constant_root_one_div_pi::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return sqrt(static_cast(1) / pi > >()); +} + +template +template +inline T constant_four_thirds_pi::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return pi > >() * static_cast(4) / static_cast(3); +} + +template +template +inline T constant_half_pi::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return pi > >() / static_cast(2); +} + +template +template +inline T constant_third_pi::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return pi > >() / static_cast(3); +} + +template +template +inline T constant_sixth_pi::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return pi > >() / static_cast(6); +} + +template +template +inline T constant_two_thirds_pi::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return pi > >() * static_cast(2) / static_cast(3); +} + +template +template +inline T constant_three_quarters_pi::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return pi > >() * static_cast(3) / static_cast(4); +} + +template +template +inline T constant_pi_pow_e::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return pow(pi > >(), e > >()); // +} + +template +template +inline T constant_pi_sqr::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return pi > >() + * pi > >() ; // +} + +template +template +inline T constant_pi_sqr_div_six::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return pi > >() + * pi > >() + / static_cast(6); // +} + +template +template +inline T constant_pi_cubed::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return pi > >() + * pi > >() + * pi > >() + ; // +} + +template +template +inline T constant_cbrt_pi::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return pow(pi > >(), static_cast(1)/ static_cast(3)); +} + +template +template +inline T constant_one_div_cbrt_pi::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return static_cast(1) + / pow(pi > >(), static_cast(1)/ static_cast(3)); +} + +// Euler's e + +template +template +inline T constant_e_pow_pi::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return pow(e > >(), pi > >()); // +} + +template +template +inline T constant_root_e::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return sqrt(e > >()); +} + +template +template +inline T constant_log10_e::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return log10(e > >()); +} + +template +template +inline T constant_one_div_log10_e::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return static_cast(1) / + log10(e > >()); +} + +// Trigonometric + +template +template +inline T constant_degree::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return pi > >() + / static_cast(180) + ; // +} + +template +template +inline T constant_radian::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return static_cast(180) + / pi > >() + ; // +} + +template +template +inline T constant_sin_one::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return sin(static_cast(1)) ; // +} + +template +template +inline T constant_cos_one::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return cos(static_cast(1)) ; // +} + +template +template +inline T constant_sinh_one::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return sinh(static_cast(1)) ; // +} + +template +template +inline T constant_cosh_one::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return cosh(static_cast(1)) ; // +} + +template +template +inline T constant_phi::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return (static_cast(1) + sqrt(static_cast(5)) )/static_cast(2) ; // +} + +template +template +inline T constant_ln_phi::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return log((static_cast(1) + sqrt(static_cast(5)) )/static_cast(2) ); +} + +template +template +inline T constant_one_div_ln_phi::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + return static_cast(1) / + log((static_cast(1) + sqrt(static_cast(5)) )/static_cast(2) ); +} + +// Zeta + +template +template +inline T constant_zeta_two::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + BOOST_MATH_STD_USING + + return pi > >() + * pi > >() + /static_cast(6); +} + +template +template +inline T constant_zeta_three::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + // http://mathworld.wolfram.com/AperysConstant.html + // http://en.wikipedia.org/wiki/Mathematical_constant + + // http://oeis.org/A002117/constant + //T zeta3("1.20205690315959428539973816151144999076" + // "4986292340498881792271555341838205786313" + // "09018645587360933525814619915"); + + //"1.202056903159594285399738161511449990, 76498629234049888179227155534183820578631309018645587360933525814619915" A002117 + // 1.202056903159594285399738161511449990, 76498629234049888179227155534183820578631309018645587360933525814619915780, +00); + //"1.2020569031595942 double + // http://www.spaennare.se/SSPROG/ssnum.pdf // section 11, Algorithm for Apery's constant zeta(3). + // Programs to Calculate some Mathematical Constants to Large Precision, Document Version 1.50 + + // by Stefan Spannare September 19, 2007 + // zeta(3) = 1/64 * sum + BOOST_MATH_STD_USING + T n_fact=static_cast(1); // build n! for n = 0. + T sum = static_cast(77); // Start with n = 0 case. + // for n = 0, (77/1) /64 = 1.203125 + //double lim = std::numeric_limits::epsilon(); + T lim = N ? ldexp(T(1), 1 - (std::min)(N, tools::digits())) : tools::epsilon(); + for(unsigned int n = 1; n < 40; ++n) + { // three to five decimal digits per term, so 40 should be plenty for 100 decimal digits. + //cout << "n = " << n << endl; + n_fact *= n; // n! + T n_fact_p10 = n_fact * n_fact * n_fact * n_fact * n_fact * n_fact * n_fact * n_fact * n_fact * n_fact; // (n!)^10 + T num = ((205 * n * n) + (250 * n) + 77) * n_fact_p10; // 205n^2 + 250n + 77 + // int nn = (2 * n + 1); + // T d = factorial(nn); // inline factorial. + T d = 1; + for(unsigned int i = 1; i <= (n+n + 1); ++i) // (2n + 1) + { + d *= i; + } + T den = d * d * d * d * d; // [(2n+1)!]^5 + //cout << "den = " << den << endl; + T term = num/den; + if (n % 2 != 0) + { //term *= -1; + sum -= term; + } + else + { + sum += term; + } + //cout << "term = " << term << endl; + //cout << "sum/64 = " << sum/64 << endl; + if(abs(term) < lim) + { + break; + } + } + return sum / 64; +} + +template +template +inline T constant_catalan::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ // http://oeis.org/A006752/constant + //T c("0.915965594177219015054603514932384110774" + //"149374281672134266498119621763019776254769479356512926115106248574"); + + // 9.159655941772190150546035149323841107, 74149374281672134266498119621763019776254769479356512926115106248574422619, -01); + + // This is equation (entry) 31 from + // http://www-2.cs.cmu.edu/~adamchik/articles/catalan/catalan.htm + // See also http://www.mpfr.org/algorithms.pdf + BOOST_MATH_STD_USING + T k_fact = 1; + T tk_fact = 1; + T sum = 1; + T term; + T lim = N ? ldexp(T(1), 1 - (std::min)(N, tools::digits())) : tools::epsilon(); + + for(unsigned k = 1;; ++k) + { + k_fact *= k; + tk_fact *= (2 * k) * (2 * k - 1); + term = k_fact * k_fact / (tk_fact * (2 * k + 1) * (2 * k + 1)); + sum += term; + if(term < lim) + { + break; + } + } + return boost::math::constants::pi >() + * log(2 + boost::math::constants::root_three >()) + / 8 + + 3 * sum / 8; +} + +namespace khinchin_detail{ + +template +T zeta_polynomial_series(T s, T sc, int digits) +{ + BOOST_MATH_STD_USING + // + // This is algorithm 3 from: + // + // "An Efficient Algorithm for the Riemann Zeta Function", P. Borwein, + // Canadian Mathematical Society, Conference Proceedings, 2000. + // See: http://www.cecm.sfu.ca/personal/pborwein/PAPERS/P155.pdf + // + BOOST_MATH_STD_USING + int n = (digits * 19) / 53; + T sum = 0; + T two_n = ldexp(T(1), n); + int ej_sign = 1; + for(int j = 0; j < n; ++j) + { + sum += ej_sign * -two_n / pow(T(j + 1), s); + ej_sign = -ej_sign; + } + T ej_sum = 1; + T ej_term = 1; + for(int j = n; j <= 2 * n - 1; ++j) + { + sum += ej_sign * (ej_sum - two_n) / pow(T(j + 1), s); + ej_sign = -ej_sign; + ej_term *= 2 * n - j; + ej_term /= j - n + 1; + ej_sum += ej_term; + } + return -sum / (two_n * (1 - pow(T(2), sc))); +} + +template +T khinchin(int digits) +{ + BOOST_MATH_STD_USING + T sum = 0; + T term; + T lim = ldexp(T(1), 1-digits); + T factor = 0; + unsigned last_k = 1; + T num = 1; + for(unsigned n = 1;; ++n) + { + for(unsigned k = last_k; k <= 2 * n - 1; ++k) + { + factor += num / k; + num = -num; + } + last_k = 2 * n; + term = (zeta_polynomial_series(T(2 * n), T(1 - T(2 * n)), digits) - 1) * factor / n; + sum += term; + if(term < lim) + break; + } + return exp(sum / boost::math::constants::ln_two >()); +} + +} + +template +template +inline T constant_khinchin::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + int n = N ? (std::min)(N, tools::digits()) : tools::digits(); + return khinchin_detail::khinchin(n); +} + +template +template +inline T constant_extreme_value_skewness::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ // N[12 Sqrt[6] Zeta[3]/Pi^3, 1101] + BOOST_MATH_STD_USING + T ev(12 * sqrt(static_cast(6)) * zeta_three > >() + / pi_cubed > >() ); + +//T ev( +//"1.1395470994046486574927930193898461120875997958365518247216557100852480077060706857071875468869385150" +//"1894272048688553376986765366075828644841024041679714157616857834895702411080704529137366329462558680" +//"2015498788776135705587959418756809080074611906006528647805347822929577145038743873949415294942796280" +//"0895597703063466053535550338267721294164578901640163603544404938283861127819804918174973533694090594" +//"3094963822672055237678432023017824416203652657301470473548274848068762500300316769691474974950757965" +//"8640779777748741897542093874605477776538884083378029488863880220988107155275203245233994097178778984" +//"3488995668362387892097897322246698071290011857605809901090220903955815127463328974447572119951192970" +//"3684453635456559086126406960279692862247058250100678008419431185138019869693206366891639436908462809" +//"9756051372711251054914491837034685476095423926553367264355374652153595857163724698198860485357368964" +//"3807049634423621246870868566707915720704996296083373077647528285782964567312903914752617978405994377" +//"9064157147206717895272199736902453130842229559980076472936976287378945035706933650987259357729800315"); + + return ev; +} + +namespace detail{ +// +// Calculation of the Glaisher constant depends upon calculating the +// derivative of the zeta function at 2, we can then use the relation: +// zeta'(2) = 1/6 pi^2 [euler + ln(2pi)-12ln(A)] +// To get the constant A. +// See equation 45 at http://mathworld.wolfram.com/RiemannZetaFunction.html. +// +// The derivative of the zeta function is computed by direct differentiation +// of the relation: +// (1-2^(1-s))zeta(s) = SUM(n=0, INF){ (-n)^n / (n+1)^s } +// Which gives us 2 slowly converging but alternating sums to compute, +// for this we use Algorithm 1 from "Convergent Acceleration of Alternating Series", +// Henri Cohen, Fernando Rodriguez Villegas and Don Zagier, Experimental Mathematics 9:1 (1999). +// See http://www.math.utexas.edu/users/villegas/publications/conv-accel.pdf +// +template +T zeta_series_derivative_2(unsigned digits) +{ + // Derivative of the series part, evaluated at 2: + BOOST_MATH_STD_USING + int n = digits * 301 * 13 / 10000; + T d = pow(3 + sqrt(T(8)), n); + d = (d + 1 / d) / 2; + T b = -1; + T c = -d; + T s = 0; + for(int k = 0; k < n; ++k) + { + T a = -log(T(k+1)) / ((k+1) * (k+1)); + c = b - c; + s = s + c * a; + b = (k + n) * (k - n) * b / ((k + T(0.5f)) * (k + 1)); + } + return s / d; +} + +template +T zeta_series_2(unsigned digits) +{ + // Series part of zeta at 2: + BOOST_MATH_STD_USING + int n = digits * 301 * 13 / 10000; + T d = pow(3 + sqrt(T(8)), n); + d = (d + 1 / d) / 2; + T b = -1; + T c = -d; + T s = 0; + for(int k = 0; k < n; ++k) + { + T a = T(1) / ((k + 1) * (k + 1)); + c = b - c; + s = s + c * a; + b = (k + n) * (k - n) * b / ((k + T(0.5f)) * (k + 1)); + } + return s / d; +} + +template +inline T zeta_series_lead_2() +{ + // lead part at 2: + return 2; +} + +template +inline T zeta_series_derivative_lead_2() +{ + // derivative of lead part at 2: + return -2 * boost::math::constants::ln_two(); +} + +template +inline T zeta_derivative_2(unsigned n) +{ + // zeta derivative at 2: + return zeta_series_derivative_2(n) * zeta_series_lead_2() + + zeta_series_derivative_lead_2() * zeta_series_2(n); +} + +} // namespace detail + +template +template +inline T constant_glaisher::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + + BOOST_MATH_STD_USING + typedef policies::policy > forwarding_policy; + int n = N ? (std::min)(N, tools::digits()) : tools::digits(); + T v = detail::zeta_derivative_2(n); + v *= 6; + v /= boost::math::constants::pi() * boost::math::constants::pi(); + v -= boost::math::constants::euler(); + v -= log(2 * boost::math::constants::pi()); + v /= -12; + return exp(v); + + /* + // from http://mpmath.googlecode.com/svn/data/glaisher.txt + // 20,000 digits of the Glaisher-Kinkelin constant A = exp(1/2 - zeta'(-1)) + // Computed using A = exp((6 (-zeta'(2))/pi^2 + log 2 pi + gamma)/12) + // with Euler-Maclaurin summation for zeta'(2). + T g( + "1.282427129100622636875342568869791727767688927325001192063740021740406308858826" + "46112973649195820237439420646120399000748933157791362775280404159072573861727522" + "14334327143439787335067915257366856907876561146686449997784962754518174312394652" + "76128213808180219264516851546143919901083573730703504903888123418813674978133050" + "93770833682222494115874837348064399978830070125567001286994157705432053927585405" + "81731588155481762970384743250467775147374600031616023046613296342991558095879293" + "36343887288701988953460725233184702489001091776941712153569193674967261270398013" + "52652668868978218897401729375840750167472114895288815996668743164513890306962645" + "59870469543740253099606800842447417554061490189444139386196089129682173528798629" + "88434220366989900606980888785849587494085307347117090132667567503310523405221054" + "14176776156308191919997185237047761312315374135304725819814797451761027540834943" + "14384965234139453373065832325673954957601692256427736926358821692159870775858274" + "69575162841550648585890834128227556209547002918593263079373376942077522290940187"); + + return g; + */ +} + +template +template +inline T constant_rayleigh_skewness::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ // 1100 digits of the Rayleigh distribution skewness + // N[2 Sqrt[Pi] (Pi - 3)/((4 - Pi)^(3/2)), 1100] + + BOOST_MATH_STD_USING + T rs(2 * root_pi > >() + * pi_minus_three > >() + / pow(four_minus_pi > >(), static_cast(3./2)) + ); + // 6.31110657818937138191899351544227779844042203134719497658094585692926819617473725459905027032537306794400047264, + + //"0.6311106578189371381918993515442277798440422031347194976580945856929268196174737254599050270325373067" + //"9440004726436754739597525250317640394102954301685809920213808351450851396781817932734836994829371322" + //"5797376021347531983451654130317032832308462278373358624120822253764532674177325950686466133508511968" + //"2389168716630349407238090652663422922072397393006683401992961569208109477307776249225072042971818671" + //"4058887072693437217879039875871765635655476241624825389439481561152126886932506682176611183750503553" + //"1218982627032068396407180216351425758181396562859085306247387212297187006230007438534686340210168288" + //"8956816965453815849613622117088096547521391672977226658826566757207615552041767516828171274858145957" + //"6137539156656005855905288420585194082284972984285863898582313048515484073396332610565441264220790791" + //"0194897267890422924599776483890102027823328602965235306539844007677157873140562950510028206251529523" + //"7428049693650605954398446899724157486062545281504433364675815915402937209673727753199567661561209251" + //"4695589950526053470201635372590001578503476490223746511106018091907936826431407434894024396366284848"); ; + return rs; +} + +template +template +inline T constant_rayleigh_kurtosis_excess::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ // - (6 Pi^2 - 24 Pi + 16)/((Pi - 4)^2) + // Might provide and calculate this using pi_minus_four. + BOOST_MATH_STD_USING + return - (((static_cast(6) * pi > >() + * pi > >()) + - (static_cast(24) * pi > >()) + static_cast(16) ) + / + ((pi > >() - static_cast(4)) + * (pi > >() - static_cast(4))) + ); +} + +template +template +inline T constant_rayleigh_kurtosis::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ // 3 - (6 Pi^2 - 24 Pi + 16)/((Pi - 4)^2) + // Might provide and calculate this using pi_minus_four. + BOOST_MATH_STD_USING + return static_cast(3) - (((static_cast(6) * pi > >() + * pi > >()) + - (static_cast(24) * pi > >()) + static_cast(16) ) + / + ((pi > >() - static_cast(4)) + * (pi > >() - static_cast(4))) + ); +} + +template +template +inline T constant_log2_e::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + return 1 / boost::math::constants::ln_two(); +} + +template +template +inline T constant_quarter_pi::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + return boost::math::constants::pi() / 4; +} + +template +template +inline T constant_one_div_pi::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + return 1 / boost::math::constants::pi(); +} + +template +template +inline T constant_two_div_root_pi::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + return 2 * boost::math::constants::one_div_root_pi(); +} + +#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900) +template +template +inline T constant_first_feigenbaum::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + // We know the constant to 1018 decimal digits. + // See: http://www.plouffe.fr/simon/constants/feigenbaum.txt + // Also: https://oeis.org/A006890 + // N is in binary digits; so we multiply by log_2(10) + + static_assert(N < 3.321*1018, "\nThe first Feigenbaum constant cannot be computed at runtime; it is too expensive. It is known to 1018 decimal digits; you must request less than that."); + T alpha{"4.6692016091029906718532038204662016172581855774757686327456513430041343302113147371386897440239480138171659848551898151344086271420279325223124429888908908599449354632367134115324817142199474556443658237932020095610583305754586176522220703854106467494942849814533917262005687556659523398756038256372256480040951071283890611844702775854285419801113440175002428585382498335715522052236087250291678860362674527213399057131606875345083433934446103706309452019115876972432273589838903794946257251289097948986768334611626889116563123474460575179539122045562472807095202198199094558581946136877445617396074115614074243754435499204869180982648652368438702799649017397793425134723808737136211601860128186102056381818354097598477964173900328936171432159878240789776614391395764037760537119096932066998361984288981837003229412030210655743295550388845849737034727532121925706958414074661841981961006129640161487712944415901405467941800198133253378592493365883070459999938375411726563553016862529032210862320550634510679399023341675"}; + return alpha; +} + +template +template +inline T constant_plastic::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + using std::cbrt; + using std::sqrt; + return (cbrt(9-sqrt(T(69))) + cbrt(9+sqrt(T(69))))/cbrt(T(18)); +} + + +template +template +inline T constant_gauss::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + using std::sqrt; + T a = sqrt(T(2)); + T g = 1; + const T scale = sqrt(std::numeric_limits::epsilon())/512; + while (a-g > scale*g) + { + T anp1 = (a + g)/2; + g = sqrt(a*g); + a = anp1; + } + + return 2/(a + g); +} + +template +template +inline T constant_dottie::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + // Error analysis: cos(x(1+d)) - x(1+d) = -(sin(x)+1)xd; plug in x = 0.739 gives -1.236d; take d as half an ulp gives the termination criteria we want. + using std::cos; + using std::abs; + using std::sin; + T x{".739085133215160641655312087673873404013411758900757464965680635773284654883547594599376106931766531849801246"}; + T residual = cos(x) - x; + do { + x += residual/(sin(x)+1); + residual = cos(x) - x; + } while(abs(residual) > std::numeric_limits::epsilon()); + return x; +} + + +template +template +inline T constant_reciprocal_fibonacci::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + // Wikipedia says Gosper has deviced a faster algorithm for this, but I read the linked paper and couldn't see it! + // In any case, k bits per iteration is fine, though it would be better to sum from smallest to largest. + // That said, the condition number is unity, so it should be fine. + T x0 = 1; + T x1 = 1; + T sum = 2; + T diff = 1; + while (diff > std::numeric_limits::epsilon()) { + T tmp = x1 + x0; + diff = 1/tmp; + sum += diff; + x0 = x1; + x1 = tmp; + } + return sum; +} + +template +template +inline T constant_laplace_limit::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) +{ + // If x is the exact root, then the approximate root is given by x(1+delta). + // Plugging this into the equation for the Laplace limit gives the residual of approximately + // 2.6389delta. Take delta as half an epsilon and give some leeway so we don't get caught in an infinite loop, + // gives a termination condition as 2eps. + using std::abs; + using std::exp; + using std::sqrt; + T x{"0.66274341934918158097474209710925290705623354911502241752039253499097185308651127724965480259895818168"}; + T tmp = sqrt(1+x*x); + T etmp = exp(tmp); + T residual = x*exp(tmp) - 1 - tmp; + T df = etmp -x/tmp + etmp*x*x/tmp; + do { + x -= residual/df; + tmp = sqrt(1+x*x); + etmp = exp(tmp); + residual = x*exp(tmp) - 1 - tmp; + df = etmp -x/tmp + etmp*x*x/tmp; + } while(abs(residual) > 2*std::numeric_limits::epsilon()); + return x; +} + +#endif + +} +} +} +} // namespaces + +#endif // BOOST_MATH_CALCULATE_CONSTANTS_CONSTANTS_INCLUDED diff --git a/libcxx/src/third-party/boost/math/constants/constants.hpp b/libcxx/src/third-party/boost/math/constants/constants.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/constants/constants.hpp @@ -0,0 +1,345 @@ +// Copyright John Maddock 2005-2006, 2011. +// Copyright Paul A. Bristow 2006-2011. +// 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_CONSTANTS_CONSTANTS_INCLUDED +#define BOOST_MATH_CONSTANTS_CONSTANTS_INCLUDED + +#include +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4127 4701) +#endif +#ifdef _MSC_VER +#pragma warning(pop) +#endif +#include +#include + +#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 diagnostic ignored work :( +// +#pragma GCC system_header +#endif + +namespace boost{ namespace math +{ + namespace constants + { + // To permit other calculations at about 100 decimal digits with some UDT, + // it is obviously necessary to define constants to this accuracy. + + // However, some compilers do not accept decimal digits strings as long as this. + // So the constant is split into two parts, with the 1st containing at least + // long double precision, and the 2nd zero if not needed or known. + // The 3rd part permits an exponent to be provided if necessary (use zero if none) - + // the other two parameters may only contain decimal digits (and sign and decimal point), + // and may NOT include an exponent like 1.234E99. + // The second digit string is only used if T is a User-Defined Type, + // when the constant is converted to a long string literal and lexical_casted to type T. + // (This is necessary because you can't use a numeric constant + // since even a long double might not have enough digits). + + enum construction_method + { + construct_from_float = 1, + construct_from_double = 2, + construct_from_long_double = 3, + construct_from_string = 4, + construct_from_float128 = 5, + // Must be the largest value above: + construct_max = construct_from_float128 + }; + + // + // Traits class determines how to convert from string based on whether T has a constructor + // from const char* or not: + // + template + struct dummy_size{}; + + // + // Max number of binary digits in the string representations of our constants: + // + static constexpr int max_string_digits = (101 * 1000L) / 301L; + + template + struct construction_traits + { + private: + using real_precision = typename policies::precision::type; + using float_precision = typename policies::precision::type; + using double_precision = typename policies::precision::type; + using long_double_precision = typename policies::precision::type; + public: + using type = std::integral_constant::value && (real_precision::value <= float_precision::value)? construct_from_float : + std::is_convertible::value && (real_precision::value <= double_precision::value)? construct_from_double : + std::is_convertible::value && (real_precision::value <= long_double_precision::value)? construct_from_long_double : +#ifdef BOOST_MATH_USE_FLOAT128 + std::is_convertible::value && (real_precision::value <= 113) ? construct_from_float128 : +#endif + (real_precision::value <= max_string_digits) ? construct_from_string : real_precision::value + >; + }; + +#ifdef BOOST_HAS_THREADS +#define BOOST_MATH_CONSTANT_THREAD_HELPER(name, prefix) \ + boost::once_flag f = BOOST_ONCE_INIT;\ + boost::call_once(f, &BOOST_JOIN(BOOST_JOIN(string_, get_), name)); +#else +#define BOOST_MATH_CONSTANT_THREAD_HELPER(name, prefix) +#endif + + namespace detail{ + + template > + struct constant_return + { + using construct_type = typename construction_traits::type; + using type = typename std::conditional< + (construct_type::value == construct_from_string) || (construct_type::value > construct_max), + const Real&, Real>::type; + }; + + template + struct constant_initializer + { + static void force_instantiate() + { + init.force_instantiate(); + } + private: + struct initializer + { + initializer() + { + F(); + } + void force_instantiate()const{} + }; + static const initializer init; + }; + + template + typename constant_initializer::initializer const constant_initializer::init; + + template )) BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(T))> + struct constant_initializer2 + { + static void force_instantiate() + { + init.force_instantiate(); + } + private: + struct initializer + { + initializer() + { + F(); + } + void force_instantiate()const{} + }; + static const initializer init; + }; + + template )) BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(T))> + typename constant_initializer2::initializer const constant_initializer2::init; + + } + +#ifdef BOOST_MATH_USE_FLOAT128 +# define BOOST_MATH_FLOAT128_CONSTANT_OVERLOAD(x) \ + static inline constexpr T get(const std::integral_constant&) noexcept\ + { return BOOST_JOIN(x, Q); } +#else +# define BOOST_MATH_FLOAT128_CONSTANT_OVERLOAD(x) +#endif + +#ifdef BOOST_NO_CXX11_THREAD_LOCAL +# define BOOST_MATH_PRECOMPUTE_IF_NOT_LOCAL(constant_, name) constant_initializer::get_from_variable_precision>::force_instantiate(); +#else +# define BOOST_MATH_PRECOMPUTE_IF_NOT_LOCAL(constant_, name) +#endif + +#define BOOST_DEFINE_MATH_CONSTANT(name, x, y)\ + namespace detail{\ + template struct BOOST_JOIN(constant_, name){\ + private:\ + /* The default implementations come next: */ \ + static inline const T& get_from_string()\ + {\ + static const T result(boost::math::tools::convert_from_string(y));\ + return result;\ + }\ + /* This one is for very high precision that is none the less known at compile time: */ \ + template static T compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant)));\ + template static inline const T& get_from_compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant)))\ + {\ + static const T result = compute();\ + return result;\ + }\ + static inline const T& get_from_variable_precision()\ + {\ + static BOOST_MATH_THREAD_LOCAL int digits = 0;\ + static BOOST_MATH_THREAD_LOCAL T value;\ + int current_digits = boost::math::tools::digits();\ + if(digits != current_digits)\ + {\ + value = current_digits > max_string_digits ? compute<0>() : T(boost::math::tools::convert_from_string(y));\ + digits = current_digits; \ + }\ + return value;\ + }\ + /* public getters come next */\ + public:\ + static inline const T& get(const std::integral_constant&)\ + {\ + constant_initializer::get_from_string >::force_instantiate();\ + return get_from_string();\ + }\ + static inline constexpr T get(const std::integral_constant) noexcept\ + { return BOOST_JOIN(x, F); }\ + static inline constexpr T get(const std::integral_constant&) noexcept\ + { return x; }\ + static inline constexpr T get(const std::integral_constant&) noexcept\ + { return BOOST_JOIN(x, L); }\ + BOOST_MATH_FLOAT128_CONSTANT_OVERLOAD(x) \ + template static inline const T& get(const std::integral_constant&)\ + {\ + constant_initializer2::template get_from_compute >::force_instantiate();\ + return get_from_compute(); \ + }\ + /* This one is for true arbitrary precision, which may well vary at runtime: */ \ + static inline T get(const std::integral_constant&)\ + {\ + BOOST_MATH_PRECOMPUTE_IF_NOT_LOCAL(constant_, name)\ + return get_from_variable_precision(); }\ + }; /* end of struct */\ + } /* namespace detail */ \ + \ + \ + /* The actual forwarding function: */ \ + template inline constexpr typename detail::constant_return::type name(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(T) BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(Policy)) BOOST_MATH_NOEXCEPT(T)\ + { return detail:: BOOST_JOIN(constant_, name)::get(typename construction_traits::type()); }\ + template inline constexpr typename detail::constant_return::type name(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(T)) BOOST_MATH_NOEXCEPT(T)\ + { return name >(); }\ + \ + \ + /* Now the namespace specific versions: */ \ + } namespace float_constants{ static constexpr float name = BOOST_JOIN(x, F); }\ + namespace double_constants{ static constexpr double name = x; } \ + namespace long_double_constants{ static constexpr long double name = BOOST_JOIN(x, L); }\ + namespace constants{ + + BOOST_DEFINE_MATH_CONSTANT(half, 5.000000000000000000000000000000000000e-01, "5.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-01") + BOOST_DEFINE_MATH_CONSTANT(third, 3.333333333333333333333333333333333333e-01, "3.33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333e-01") + BOOST_DEFINE_MATH_CONSTANT(twothirds, 6.666666666666666666666666666666666666e-01, "6.66666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666667e-01") + BOOST_DEFINE_MATH_CONSTANT(two_thirds, 6.666666666666666666666666666666666666e-01, "6.66666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666667e-01") + BOOST_DEFINE_MATH_CONSTANT(sixth, 1.666666666666666666666666666666666666e-01, "1.66666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666667e-01") + BOOST_DEFINE_MATH_CONSTANT(three_quarters, 7.500000000000000000000000000000000000e-01, "7.50000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-01") + BOOST_DEFINE_MATH_CONSTANT(root_two, 1.414213562373095048801688724209698078e+00, "1.41421356237309504880168872420969807856967187537694807317667973799073247846210703885038753432764157273501384623e+00") + BOOST_DEFINE_MATH_CONSTANT(root_three, 1.732050807568877293527446341505872366e+00, "1.73205080756887729352744634150587236694280525381038062805580697945193301690880003708114618675724857567562614142e+00") + BOOST_DEFINE_MATH_CONSTANT(half_root_two, 7.071067811865475244008443621048490392e-01, "7.07106781186547524400844362104849039284835937688474036588339868995366239231053519425193767163820786367506923115e-01") + BOOST_DEFINE_MATH_CONSTANT(ln_two, 6.931471805599453094172321214581765680e-01, "6.93147180559945309417232121458176568075500134360255254120680009493393621969694715605863326996418687542001481021e-01") + BOOST_DEFINE_MATH_CONSTANT(ln_ln_two, -3.665129205816643270124391582326694694e-01, "-3.66512920581664327012439158232669469454263447837105263053677713670561615319352738549455822856698908358302523045e-01") + BOOST_DEFINE_MATH_CONSTANT(root_ln_four, 1.177410022515474691011569326459699637e+00, "1.17741002251547469101156932645969963774738568938582053852252575650002658854698492680841813836877081106747157858e+00") + BOOST_DEFINE_MATH_CONSTANT(one_div_root_two, 7.071067811865475244008443621048490392e-01, "7.07106781186547524400844362104849039284835937688474036588339868995366239231053519425193767163820786367506923115e-01") + BOOST_DEFINE_MATH_CONSTANT(pi, 3.141592653589793238462643383279502884e+00, "3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651e+00") + BOOST_DEFINE_MATH_CONSTANT(half_pi, 1.570796326794896619231321691639751442e+00, "1.57079632679489661923132169163975144209858469968755291048747229615390820314310449931401741267105853399107404326e+00") + BOOST_DEFINE_MATH_CONSTANT(third_pi, 1.047197551196597746154214461093167628e+00, "1.04719755119659774615421446109316762806572313312503527365831486410260546876206966620934494178070568932738269550e+00") + BOOST_DEFINE_MATH_CONSTANT(sixth_pi, 5.235987755982988730771072305465838140e-01, "5.23598775598298873077107230546583814032861566562517636829157432051302734381034833104672470890352844663691347752e-01") + BOOST_DEFINE_MATH_CONSTANT(two_pi, 6.283185307179586476925286766559005768e+00, "6.28318530717958647692528676655900576839433879875021164194988918461563281257241799725606965068423413596429617303e+00") + BOOST_DEFINE_MATH_CONSTANT(two_thirds_pi, 2.094395102393195492308428922186335256e+00, "2.09439510239319549230842892218633525613144626625007054731662972820521093752413933241868988356141137865476539101e+00") + BOOST_DEFINE_MATH_CONSTANT(three_quarters_pi, 2.356194490192344928846982537459627163e+00, "2.35619449019234492884698253745962716314787704953132936573120844423086230471465674897102611900658780098661106488e+00") + BOOST_DEFINE_MATH_CONSTANT(four_thirds_pi, 4.188790204786390984616857844372670512e+00, "4.18879020478639098461685784437267051226289253250014109463325945641042187504827866483737976712282275730953078202e+00") + BOOST_DEFINE_MATH_CONSTANT(one_div_two_pi, 1.591549430918953357688837633725143620e-01, "1.59154943091895335768883763372514362034459645740456448747667344058896797634226535090113802766253085956072842727e-01") + BOOST_DEFINE_MATH_CONSTANT(one_div_root_two_pi, 3.989422804014326779399460599343818684e-01, "3.98942280401432677939946059934381868475858631164934657665925829670657925899301838501252333907306936430302558863e-01") + BOOST_DEFINE_MATH_CONSTANT(root_pi, 1.772453850905516027298167483341145182e+00, "1.77245385090551602729816748334114518279754945612238712821380778985291128459103218137495065673854466541622682362e+00") + BOOST_DEFINE_MATH_CONSTANT(root_half_pi, 1.253314137315500251207882642405522626e+00, "1.25331413731550025120788264240552262650349337030496915831496178817114682730392098747329791918902863305800498633e+00") + BOOST_DEFINE_MATH_CONSTANT(root_two_pi, 2.506628274631000502415765284811045253e+00, "2.50662827463100050241576528481104525300698674060993831662992357634229365460784197494659583837805726611600997267e+00") + BOOST_DEFINE_MATH_CONSTANT(log_root_two_pi, 9.189385332046727417803297364056176398e-01, "9.18938533204672741780329736405617639861397473637783412817151540482765695927260397694743298635954197622005646625e-01") + BOOST_DEFINE_MATH_CONSTANT(one_div_root_pi, 5.641895835477562869480794515607725858e-01, "5.64189583547756286948079451560772585844050629328998856844085721710642468441493414486743660202107363443028347906e-01") + BOOST_DEFINE_MATH_CONSTANT(root_one_div_pi, 5.641895835477562869480794515607725858e-01, "5.64189583547756286948079451560772585844050629328998856844085721710642468441493414486743660202107363443028347906e-01") + BOOST_DEFINE_MATH_CONSTANT(pi_minus_three, 1.415926535897932384626433832795028841e-01, "1.41592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513e-01") + BOOST_DEFINE_MATH_CONSTANT(four_minus_pi, 8.584073464102067615373566167204971158e-01, "8.58407346410206761537356616720497115802830600624894179025055407692183593713791001371965174657882932017851913487e-01") + //BOOST_DEFINE_MATH_CONSTANT(pow23_four_minus_pi, 7.953167673715975443483953350568065807e-01, "7.95316767371597544348395335056806580727639173327713205445302234388856268267518187590758006888600828436839800178e-01") + BOOST_DEFINE_MATH_CONSTANT(pi_pow_e, 2.245915771836104547342715220454373502e+01, "2.24591577183610454734271522045437350275893151339966922492030025540669260403991179123185197527271430315314500731e+01") + BOOST_DEFINE_MATH_CONSTANT(pi_sqr, 9.869604401089358618834490999876151135e+00, "9.86960440108935861883449099987615113531369940724079062641334937622004482241920524300177340371855223182402591377e+00") + BOOST_DEFINE_MATH_CONSTANT(pi_sqr_div_six, 1.644934066848226436472415166646025189e+00, "1.64493406684822643647241516664602518921894990120679843773555822937000747040320087383362890061975870530400431896e+00") + BOOST_DEFINE_MATH_CONSTANT(pi_cubed, 3.100627668029982017547631506710139520e+01, "3.10062766802998201754763150671013952022252885658851076941445381038063949174657060375667010326028861930301219616e+01") + BOOST_DEFINE_MATH_CONSTANT(cbrt_pi, 1.464591887561523263020142527263790391e+00, "1.46459188756152326302014252726379039173859685562793717435725593713839364979828626614568206782035382089750397002e+00") + BOOST_DEFINE_MATH_CONSTANT(one_div_cbrt_pi, 6.827840632552956814670208331581645981e-01, "6.82784063255295681467020833158164598108367515632448804042681583118899226433403918237673501922595519865685577274e-01") + BOOST_DEFINE_MATH_CONSTANT(log2_e, 1.44269504088896340735992468100189213742664595415298, "1.44269504088896340735992468100189213742664595415298593413544940693110921918118507988552662289350634449699751830965e+00") + BOOST_DEFINE_MATH_CONSTANT(e, 2.718281828459045235360287471352662497e+00, "2.71828182845904523536028747135266249775724709369995957496696762772407663035354759457138217852516642742746639193e+00") + BOOST_DEFINE_MATH_CONSTANT(exp_minus_half, 6.065306597126334236037995349911804534e-01, "6.06530659712633423603799534991180453441918135487186955682892158735056519413748423998647611507989456026423789794e-01") + BOOST_DEFINE_MATH_CONSTANT(exp_minus_one, 3.678794411714423215955237701614608674e-01, "3.67879441171442321595523770161460867445811131031767834507836801697461495744899803357147274345919643746627325277e-01") + BOOST_DEFINE_MATH_CONSTANT(e_pow_pi, 2.314069263277926900572908636794854738e+01, "2.31406926327792690057290863679485473802661062426002119934450464095243423506904527835169719970675492196759527048e+01") + BOOST_DEFINE_MATH_CONSTANT(root_e, 1.648721270700128146848650787814163571e+00, "1.64872127070012814684865078781416357165377610071014801157507931164066102119421560863277652005636664300286663776e+00") + BOOST_DEFINE_MATH_CONSTANT(log10_e, 4.342944819032518276511289189166050822e-01, "4.34294481903251827651128918916605082294397005803666566114453783165864649208870774729224949338431748318706106745e-01") + BOOST_DEFINE_MATH_CONSTANT(one_div_log10_e, 2.302585092994045684017991454684364207e+00, "2.30258509299404568401799145468436420760110148862877297603332790096757260967735248023599720508959829834196778404e+00") + BOOST_DEFINE_MATH_CONSTANT(ln_ten, 2.302585092994045684017991454684364207e+00, "2.30258509299404568401799145468436420760110148862877297603332790096757260967735248023599720508959829834196778404e+00") + BOOST_DEFINE_MATH_CONSTANT(degree, 1.745329251994329576923690768488612713e-02, "1.74532925199432957692369076848861271344287188854172545609719144017100911460344944368224156963450948221230449251e-02") + BOOST_DEFINE_MATH_CONSTANT(radian, 5.729577951308232087679815481410517033e+01, "5.72957795130823208767981548141051703324054724665643215491602438612028471483215526324409689958511109441862233816e+01") + BOOST_DEFINE_MATH_CONSTANT(sin_one, 8.414709848078965066525023216302989996e-01, "8.41470984807896506652502321630298999622563060798371065672751709991910404391239668948639743543052695854349037908e-01") + BOOST_DEFINE_MATH_CONSTANT(cos_one, 5.403023058681397174009366074429766037e-01, "5.40302305868139717400936607442976603732310420617922227670097255381100394774471764517951856087183089343571731160e-01") + BOOST_DEFINE_MATH_CONSTANT(sinh_one, 1.175201193643801456882381850595600815e+00, "1.17520119364380145688238185059560081515571798133409587022956541301330756730432389560711745208962339184041953333e+00") + BOOST_DEFINE_MATH_CONSTANT(cosh_one, 1.543080634815243778477905620757061682e+00, "1.54308063481524377847790562075706168260152911236586370473740221471076906304922369896426472643554303558704685860e+00") + BOOST_DEFINE_MATH_CONSTANT(phi, 1.618033988749894848204586834365638117e+00, "1.61803398874989484820458683436563811772030917980576286213544862270526046281890244970720720418939113748475408808e+00") + BOOST_DEFINE_MATH_CONSTANT(ln_phi, 4.812118250596034474977589134243684231e-01, "4.81211825059603447497758913424368423135184334385660519661018168840163867608221774412009429122723474997231839958e-01") + BOOST_DEFINE_MATH_CONSTANT(one_div_ln_phi, 2.078086921235027537601322606117795767e+00, "2.07808692123502753760132260611779576774219226778328348027813992191974386928553540901445615414453604821933918634e+00") + BOOST_DEFINE_MATH_CONSTANT(euler, 5.772156649015328606065120900824024310e-01, "5.77215664901532860606512090082402431042159335939923598805767234884867726777664670936947063291746749514631447250e-01") + BOOST_DEFINE_MATH_CONSTANT(one_div_euler, 1.732454714600633473583025315860829681e+00, "1.73245471460063347358302531586082968115577655226680502204843613287065531408655243008832840219409928068072365714e+00") + BOOST_DEFINE_MATH_CONSTANT(euler_sqr, 3.331779238077186743183761363552442266e-01, "3.33177923807718674318376136355244226659417140249629743150833338002265793695756669661263268631715977303039565603e-01") + BOOST_DEFINE_MATH_CONSTANT(zeta_two, 1.644934066848226436472415166646025189e+00, "1.64493406684822643647241516664602518921894990120679843773555822937000747040320087383362890061975870530400431896e+00") + BOOST_DEFINE_MATH_CONSTANT(zeta_three, 1.202056903159594285399738161511449990e+00, "1.20205690315959428539973816151144999076498629234049888179227155534183820578631309018645587360933525814619915780e+00") + BOOST_DEFINE_MATH_CONSTANT(catalan, 9.159655941772190150546035149323841107e-01, "9.15965594177219015054603514932384110774149374281672134266498119621763019776254769479356512926115106248574422619e-01") + BOOST_DEFINE_MATH_CONSTANT(glaisher, 1.282427129100622636875342568869791727e+00, "1.28242712910062263687534256886979172776768892732500119206374002174040630885882646112973649195820237439420646120e+00") + BOOST_DEFINE_MATH_CONSTANT(khinchin, 2.685452001065306445309714835481795693e+00, "2.68545200106530644530971483548179569382038229399446295305115234555721885953715200280114117493184769799515346591e+00") + BOOST_DEFINE_MATH_CONSTANT(extreme_value_skewness, 1.139547099404648657492793019389846112e+00, "1.13954709940464865749279301938984611208759979583655182472165571008524800770607068570718754688693851501894272049e+00") + BOOST_DEFINE_MATH_CONSTANT(rayleigh_skewness, 6.311106578189371381918993515442277798e-01, "6.31110657818937138191899351544227779844042203134719497658094585692926819617473725459905027032537306794400047264e-01") + BOOST_DEFINE_MATH_CONSTANT(rayleigh_kurtosis, 3.245089300687638062848660410619754415e+00, "3.24508930068763806284866041061975441541706673178920936177133764493367904540874159051490619368679348977426462633e+00") + BOOST_DEFINE_MATH_CONSTANT(rayleigh_kurtosis_excess, 2.450893006876380628486604106197544154e-01, "2.45089300687638062848660410619754415417066731789209361771337644933679045408741590514906193686793489774264626328e-01") + + BOOST_DEFINE_MATH_CONSTANT(two_div_pi, 6.366197723675813430755350534900574481e-01, "6.36619772367581343075535053490057448137838582961825794990669376235587190536906140360455211065012343824291370907e-01") + BOOST_DEFINE_MATH_CONSTANT(root_two_div_pi, 7.978845608028653558798921198687637369e-01, "7.97884560802865355879892119868763736951717262329869315331851659341315851798603677002504667814613872860605117725e-01") + BOOST_DEFINE_MATH_CONSTANT(quarter_pi, 0.785398163397448309615660845819875721049292, "0.785398163397448309615660845819875721049292349843776455243736148076954101571552249657008706335529266995537021628320576661773") + BOOST_DEFINE_MATH_CONSTANT(one_div_pi, 0.3183098861837906715377675267450287240689192, "0.31830988618379067153776752674502872406891929148091289749533468811779359526845307018022760553250617191214568545351") + BOOST_DEFINE_MATH_CONSTANT(two_div_root_pi, 1.12837916709551257389615890312154517168810125, "1.12837916709551257389615890312154517168810125865799771368817144342128493688298682897348732040421472688605669581272") + +#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900) + BOOST_DEFINE_MATH_CONSTANT(first_feigenbaum, 4.66920160910299067185320382046620161725818557747576863274, "4.6692016091029906718532038204662016172581855774757686327456513430041343302113147371386897440239480138171") + BOOST_DEFINE_MATH_CONSTANT(plastic, 1.324717957244746025960908854478097340734404056901733364534, "1.32471795724474602596090885447809734073440405690173336453401505030282785124554759405469934798178728032991") + BOOST_DEFINE_MATH_CONSTANT(gauss, 0.834626841674073186281429732799046808993993013490347002449, "0.83462684167407318628142973279904680899399301349034700244982737010368199270952641186969116035127532412906785") + BOOST_DEFINE_MATH_CONSTANT(dottie, 0.739085133215160641655312087673873404013411758900757464965, "0.739085133215160641655312087673873404013411758900757464965680635773284654883547594599376106931766531849801246") + BOOST_DEFINE_MATH_CONSTANT(reciprocal_fibonacci, 3.35988566624317755317201130291892717968890513, "3.35988566624317755317201130291892717968890513373196848649555381532513031899668338361541621645679008729704") + BOOST_DEFINE_MATH_CONSTANT(laplace_limit, 0.662743419349181580974742097109252907056233549115022417, "0.66274341934918158097474209710925290705623354911502241752039253499097185308651127724965480259895818168") +#endif + +template +inline constexpr T tau() { return two_pi(); } + +} // namespace constants +} // namespace math +} // namespace boost + +// +// We deliberately include this *after* all the declarations above, +// that way the calculation routines can call on other constants above: +// +#include + +#endif // BOOST_MATH_CONSTANTS_CONSTANTS_INCLUDED + + diff --git a/libcxx/src/third-party/boost/math/constants/info.hpp b/libcxx/src/third-party/boost/math/constants/info.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/constants/info.hpp @@ -0,0 +1,163 @@ +// Copyright John Maddock 2010. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifdef _MSC_VER +# pragma once +#endif + +#ifndef BOOST_MATH_CONSTANTS_INFO_INCLUDED +#define BOOST_MATH_CONSTANTS_INFO_INCLUDED + +#include +#include +#include +#include + +namespace boost{ namespace math{ namespace constants{ + + namespace detail{ + + template + const char* nameof(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(T)) + { + return typeid(T).name(); + } + template <> + const char* nameof(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(float)) + { + return "float"; + } + template <> + const char* nameof(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(double)) + { + return "double"; + } + template <> + const char* nameof(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(long double)) + { + return "long double"; + } + + } + +template +void print_info_on_type(std::ostream& os = std::cout BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(T) BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(Policy)) +{ + using detail::nameof; +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4127) +#endif + os << + "Information on the Implementation and Handling of \n" + "Mathematical Constants for Type " << nameof() << + "\n\n" + "Checking for std::numeric_limits<" << nameof() << "> specialisation: " << + (std::numeric_limits::is_specialized ? "yes" : "no") << std::endl; + if(std::numeric_limits::is_specialized) + { + os << + "std::numeric_limits<" << nameof() << ">::digits reports that the radix is " << std::numeric_limits::radix << ".\n"; + if (std::numeric_limits::radix == 2) + { + os << + "std::numeric_limits<" << nameof() << ">::digits reports that the precision is \n" << std::numeric_limits::digits << " binary digits.\n"; + } + else if (std::numeric_limits::radix == 10) + { + os << + "std::numeric_limits<" << nameof() << ">::digits reports that the precision is \n" << std::numeric_limits::digits10 << " decimal digits.\n"; + os << + "std::numeric_limits<" << nameof() << ">::digits reports that the precision is \n" + << std::numeric_limits::digits * 1000L /301L << " binary digits.\n"; // divide by log2(10) - about 3 bits per decimal digit. + } + else + { + os << "Unknown radix = " << std::numeric_limits::radix << "\n"; + } + } + typedef typename boost::math::policies::precision::type precision_type; + if(precision_type::value) + { + if (std::numeric_limits::radix == 2) + { + os << + "boost::math::policies::precision<" << nameof() << ", " << nameof() << " reports that the compile time precision is \n" << precision_type::value << " binary digits.\n"; + } + else if (std::numeric_limits::radix == 10) + { + os << + "boost::math::policies::precision<" << nameof() << ", " << nameof() << " reports that the compile time precision is \n" << precision_type::value << " binary digits.\n"; + } + else + { + os << "Unknown radix = " << std::numeric_limits::radix << "\n"; + } + } + else + { + os << + "boost::math::policies::precision<" << nameof() << ", Policy> \n" + "reports that there is no compile type precision available.\n" + "boost::math::tools::digits<" << nameof() << ">() \n" + "reports that the current runtime precision is \n" << + boost::math::tools::digits() << " binary digits.\n"; + } + + typedef typename construction_traits::type construction_type; + + switch(construction_type::value) + { + case 0: + os << + "No compile time precision is available, the construction method \n" + "will be decided at runtime and results will not be cached \n" + "- this may lead to poor runtime performance.\n" + "Current runtime precision indicates that\n"; + if(boost::math::tools::digits() > max_string_digits) + { + os << "the constant will be recalculated on each call.\n"; + } + else + { + os << "the constant will be constructed from a string on each call.\n"; + } + break; + case 1: + os << + "The constant will be constructed from a float.\n"; + break; + case 2: + os << + "The constant will be constructed from a double.\n"; + break; + case 3: + os << + "The constant will be constructed from a long double.\n"; + break; + case 4: + os << + "The constant will be constructed from a string (and the result cached).\n"; + break; + default: + os << + "The constant will be calculated (and the result cached).\n"; + break; + } + os << std::endl; +#ifdef _MSC_VER +#pragma warning(pop) +#endif +} + +template +void print_info_on_type(std::ostream& os = std::cout BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(T)) +{ + print_info_on_type >(os); +} + +}}} // namespaces + +#endif // BOOST_MATH_CONSTANTS_INFO_INCLUDED diff --git a/libcxx/src/third-party/boost/math/cstdfloat/cstdfloat_cmath.hpp b/libcxx/src/third-party/boost/math/cstdfloat/cstdfloat_cmath.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/cstdfloat/cstdfloat_cmath.hpp @@ -0,0 +1,1058 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2014. +// Copyright John Maddock 2014. +// Copyright Paul Bristow 2014. +// 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) +// + +// Implement quadruple-precision support. + +#ifndef BOOST_MATH_CSTDFLOAT_CMATH_2014_02_15_HPP_ +#define BOOST_MATH_CSTDFLOAT_CMATH_2014_02_15_HPP_ + +#include +#include + +#if defined(BOOST_CSTDFLOAT_HAS_INTERNAL_FLOAT128_T) && defined(BOOST_MATH_USE_FLOAT128) && !defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT) + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(_WIN32) && defined(__GNUC__) + // Several versions of Mingw and probably cygwin too have broken + // libquadmath implementations that segfault as soon as you call + // expq or any function that depends on it. +#define BOOST_CSTDFLOAT_BROKEN_FLOAT128_MATH_FUNCTIONS +#endif + +// Here is a helper function used for raising the value of a given +// floating-point type to the power of n, where n has integral type. +namespace boost { + namespace math { + namespace cstdfloat { + namespace detail { + + template + inline float_type pown(const float_type& x, const integer_type p) + { + const bool isneg = (x < 0); + const bool isnan = (x != x); + const bool isinf = ((!isneg) ? bool(+x > (std::numeric_limits::max)()) + : bool(-x > (std::numeric_limits::max)())); + + if (isnan) { return x; } + + if (isinf) { return std::numeric_limits::quiet_NaN(); } + + const bool x_is_neg = (x < 0); + const float_type abs_x = (x_is_neg ? -x : x); + + if (p < static_cast(0)) + { + if (abs_x < (std::numeric_limits::min)()) + { + return (x_is_neg ? -std::numeric_limits::infinity() + : +std::numeric_limits::infinity()); + } + else + { + return float_type(1) / pown(x, static_cast(-p)); + } + } + + if (p == static_cast(0)) + { + return float_type(1); + } + else + { + if (p == static_cast(1)) { return x; } + + if (abs_x > (std::numeric_limits::max)()) + { + return (x_is_neg ? -std::numeric_limits::infinity() + : +std::numeric_limits::infinity()); + } + + if (p == static_cast(2)) { return (x * x); } + else if (p == static_cast(3)) { return ((x * x) * x); } + else if (p == static_cast(4)) { const float_type x2 = (x * x); return (x2 * x2); } + else + { + // The variable xn stores the binary powers of x. + float_type result(((p % integer_type(2)) != integer_type(0)) ? x : float_type(1)); + float_type xn(x); + + integer_type p2 = p; + + while (integer_type(p2 /= 2) != integer_type(0)) + { + // Square xn for each binary power. + xn *= xn; + + const bool has_binary_power = (integer_type(p2 % integer_type(2)) != integer_type(0)); + + if (has_binary_power) + { + // Multiply the result with each binary power contained in the exponent. + result *= xn; + } + } + + return result; + } + } + } + + } + } + } +} // boost::math::cstdfloat::detail + +// We will now define preprocessor symbols representing quadruple-precision functions. +#if defined(__INTEL_COMPILER) +#define BOOST_CSTDFLOAT_FLOAT128_LDEXP __ldexpq +#define BOOST_CSTDFLOAT_FLOAT128_FREXP __frexpq +#define BOOST_CSTDFLOAT_FLOAT128_FABS __fabsq +#define BOOST_CSTDFLOAT_FLOAT128_FLOOR __floorq +#define BOOST_CSTDFLOAT_FLOAT128_CEIL __ceilq +#if !defined(BOOST_CSTDFLOAT_FLOAT128_SQRT) +#define BOOST_CSTDFLOAT_FLOAT128_SQRT __sqrtq +#endif +#define BOOST_CSTDFLOAT_FLOAT128_TRUNC __truncq +#define BOOST_CSTDFLOAT_FLOAT128_EXP __expq +#define BOOST_CSTDFLOAT_FLOAT128_EXPM1 __expm1q +#define BOOST_CSTDFLOAT_FLOAT128_POW __powq +#define BOOST_CSTDFLOAT_FLOAT128_LOG __logq +#define BOOST_CSTDFLOAT_FLOAT128_LOG10 __log10q +#define BOOST_CSTDFLOAT_FLOAT128_SIN __sinq +#define BOOST_CSTDFLOAT_FLOAT128_COS __cosq +#define BOOST_CSTDFLOAT_FLOAT128_TAN __tanq +#define BOOST_CSTDFLOAT_FLOAT128_ASIN __asinq +#define BOOST_CSTDFLOAT_FLOAT128_ACOS __acosq +#define BOOST_CSTDFLOAT_FLOAT128_ATAN __atanq +#define BOOST_CSTDFLOAT_FLOAT128_SINH __sinhq +#define BOOST_CSTDFLOAT_FLOAT128_COSH __coshq +#define BOOST_CSTDFLOAT_FLOAT128_TANH __tanhq +#define BOOST_CSTDFLOAT_FLOAT128_ASINH __asinhq +#define BOOST_CSTDFLOAT_FLOAT128_ACOSH __acoshq +#define BOOST_CSTDFLOAT_FLOAT128_ATANH __atanhq +#define BOOST_CSTDFLOAT_FLOAT128_FMOD __fmodq +#define BOOST_CSTDFLOAT_FLOAT128_ATAN2 __atan2q +#define BOOST_CSTDFLOAT_FLOAT128_LGAMMA __lgammaq +#define BOOST_CSTDFLOAT_FLOAT128_TGAMMA __tgammaq +// begin more functions +#define BOOST_CSTDFLOAT_FLOAT128_REMAINDER __remainderq +#define BOOST_CSTDFLOAT_FLOAT128_REMQUO __remquoq +#define BOOST_CSTDFLOAT_FLOAT128_FMA __fmaq +#define BOOST_CSTDFLOAT_FLOAT128_FMAX __fmaxq +#define BOOST_CSTDFLOAT_FLOAT128_FMIN __fminq +#define BOOST_CSTDFLOAT_FLOAT128_FDIM __fdimq +#define BOOST_CSTDFLOAT_FLOAT128_NAN __nanq +//#define BOOST_CSTDFLOAT_FLOAT128_EXP2 __exp2q +#define BOOST_CSTDFLOAT_FLOAT128_LOG2 __log2q +#define BOOST_CSTDFLOAT_FLOAT128_LOG1P __log1pq +#define BOOST_CSTDFLOAT_FLOAT128_CBRT __cbrtq +#define BOOST_CSTDFLOAT_FLOAT128_HYPOT __hypotq +#define BOOST_CSTDFLOAT_FLOAT128_ERF __erfq +#define BOOST_CSTDFLOAT_FLOAT128_ERFC __erfcq +#define BOOST_CSTDFLOAT_FLOAT128_LLROUND __llroundq +#define BOOST_CSTDFLOAT_FLOAT128_LROUND __lroundq +#define BOOST_CSTDFLOAT_FLOAT128_ROUND __roundq +#define BOOST_CSTDFLOAT_FLOAT128_NEARBYINT __nearbyintq +#define BOOST_CSTDFLOAT_FLOAT128_LLRINT __llrintq +#define BOOST_CSTDFLOAT_FLOAT128_LRINT __lrintq +#define BOOST_CSTDFLOAT_FLOAT128_RINT __rintq +#define BOOST_CSTDFLOAT_FLOAT128_MODF __modfq +#define BOOST_CSTDFLOAT_FLOAT128_SCALBLN __scalblnq +#define BOOST_CSTDFLOAT_FLOAT128_SCALBN __scalbnq +#define BOOST_CSTDFLOAT_FLOAT128_ILOGB __ilogbq +#define BOOST_CSTDFLOAT_FLOAT128_LOGB __logbq +#define BOOST_CSTDFLOAT_FLOAT128_NEXTAFTER __nextafterq +//#define BOOST_CSTDFLOAT_FLOAT128_NEXTTOWARD __nexttowardq +#define BOOST_CSTDFLOAT_FLOAT128_COPYSIGN __copysignq +#define BOOST_CSTDFLOAT_FLOAT128_SIGNBIT __signbitq +//#define BOOST_CSTDFLOAT_FLOAT128_FPCLASSIFY __fpclassifyq +//#define BOOST_CSTDFLOAT_FLOAT128_ISFINITE __isfiniteq +#define BOOST_CSTDFLOAT_FLOAT128_ISINF __isinfq +#define BOOST_CSTDFLOAT_FLOAT128_ISNAN __isnanq +//#define BOOST_CSTDFLOAT_FLOAT128_ISNORMAL __isnormalq +//#define BOOST_CSTDFLOAT_FLOAT128_ISGREATER __isgreaterq +//#define BOOST_CSTDFLOAT_FLOAT128_ISGREATEREQUAL __isgreaterequalq +//#define BOOST_CSTDFLOAT_FLOAT128_ISLESS __islessq +//#define BOOST_CSTDFLOAT_FLOAT128_ISLESSEQUAL __islessequalq +//#define BOOST_CSTDFLOAT_FLOAT128_ISLESSGREATER __islessgreaterq +//#define BOOST_CSTDFLOAT_FLOAT128_ISUNORDERED __isunorderedq +// end more functions +#elif defined(__GNUC__) +#define BOOST_CSTDFLOAT_FLOAT128_LDEXP ldexpq +#define BOOST_CSTDFLOAT_FLOAT128_FREXP frexpq +#define BOOST_CSTDFLOAT_FLOAT128_FABS fabsq +#define BOOST_CSTDFLOAT_FLOAT128_FLOOR floorq +#define BOOST_CSTDFLOAT_FLOAT128_CEIL ceilq +#if !defined(BOOST_CSTDFLOAT_FLOAT128_SQRT) +#define BOOST_CSTDFLOAT_FLOAT128_SQRT sqrtq +#endif +#define BOOST_CSTDFLOAT_FLOAT128_TRUNC truncq +#define BOOST_CSTDFLOAT_FLOAT128_POW powq +#define BOOST_CSTDFLOAT_FLOAT128_LOG logq +#define BOOST_CSTDFLOAT_FLOAT128_LOG10 log10q +#define BOOST_CSTDFLOAT_FLOAT128_SIN sinq +#define BOOST_CSTDFLOAT_FLOAT128_COS cosq +#define BOOST_CSTDFLOAT_FLOAT128_TAN tanq +#define BOOST_CSTDFLOAT_FLOAT128_ASIN asinq +#define BOOST_CSTDFLOAT_FLOAT128_ACOS acosq +#define BOOST_CSTDFLOAT_FLOAT128_ATAN atanq +#define BOOST_CSTDFLOAT_FLOAT128_FMOD fmodq +#define BOOST_CSTDFLOAT_FLOAT128_ATAN2 atan2q +#define BOOST_CSTDFLOAT_FLOAT128_LGAMMA lgammaq +#if !defined(BOOST_CSTDFLOAT_BROKEN_FLOAT128_MATH_FUNCTIONS) +#define BOOST_CSTDFLOAT_FLOAT128_EXP expq +#define BOOST_CSTDFLOAT_FLOAT128_EXPM1 expm1q +#define BOOST_CSTDFLOAT_FLOAT128_SINH sinhq +#define BOOST_CSTDFLOAT_FLOAT128_COSH coshq +#define BOOST_CSTDFLOAT_FLOAT128_TANH tanhq +#define BOOST_CSTDFLOAT_FLOAT128_ASINH asinhq +#define BOOST_CSTDFLOAT_FLOAT128_ACOSH acoshq +#define BOOST_CSTDFLOAT_FLOAT128_ATANH atanhq +#define BOOST_CSTDFLOAT_FLOAT128_TGAMMA tgammaq +#else // BOOST_CSTDFLOAT_BROKEN_FLOAT128_MATH_FUNCTIONS +#define BOOST_CSTDFLOAT_FLOAT128_EXP expq_patch +#define BOOST_CSTDFLOAT_FLOAT128_SINH sinhq_patch +#define BOOST_CSTDFLOAT_FLOAT128_COSH coshq_patch +#define BOOST_CSTDFLOAT_FLOAT128_TANH tanhq_patch +#define BOOST_CSTDFLOAT_FLOAT128_ASINH asinhq_patch +#define BOOST_CSTDFLOAT_FLOAT128_ACOSH acoshq_patch +#define BOOST_CSTDFLOAT_FLOAT128_ATANH atanhq_patch +#define BOOST_CSTDFLOAT_FLOAT128_TGAMMA tgammaq_patch +#endif // BOOST_CSTDFLOAT_BROKEN_FLOAT128_MATH_FUNCTIONS +// begin more functions +#define BOOST_CSTDFLOAT_FLOAT128_REMAINDER remainderq +#define BOOST_CSTDFLOAT_FLOAT128_REMQUO remquoq +#define BOOST_CSTDFLOAT_FLOAT128_FMA fmaq +#define BOOST_CSTDFLOAT_FLOAT128_FMAX fmaxq +#define BOOST_CSTDFLOAT_FLOAT128_FMIN fminq +#define BOOST_CSTDFLOAT_FLOAT128_FDIM fdimq +#define BOOST_CSTDFLOAT_FLOAT128_NAN nanq +//#define BOOST_CSTDFLOAT_FLOAT128_EXP2 exp2q +#define BOOST_CSTDFLOAT_FLOAT128_LOG2 log2q +#define BOOST_CSTDFLOAT_FLOAT128_LOG1P log1pq +#define BOOST_CSTDFLOAT_FLOAT128_CBRT cbrtq +#define BOOST_CSTDFLOAT_FLOAT128_HYPOT hypotq +#define BOOST_CSTDFLOAT_FLOAT128_ERF erfq +#define BOOST_CSTDFLOAT_FLOAT128_ERFC erfcq +#define BOOST_CSTDFLOAT_FLOAT128_LLROUND llroundq +#define BOOST_CSTDFLOAT_FLOAT128_LROUND lroundq +#define BOOST_CSTDFLOAT_FLOAT128_ROUND roundq +#define BOOST_CSTDFLOAT_FLOAT128_NEARBYINT nearbyintq +#define BOOST_CSTDFLOAT_FLOAT128_LLRINT llrintq +#define BOOST_CSTDFLOAT_FLOAT128_LRINT lrintq +#define BOOST_CSTDFLOAT_FLOAT128_RINT rintq +#define BOOST_CSTDFLOAT_FLOAT128_MODF modfq +#define BOOST_CSTDFLOAT_FLOAT128_SCALBLN scalblnq +#define BOOST_CSTDFLOAT_FLOAT128_SCALBN scalbnq +#define BOOST_CSTDFLOAT_FLOAT128_ILOGB ilogbq +#define BOOST_CSTDFLOAT_FLOAT128_LOGB logbq +#define BOOST_CSTDFLOAT_FLOAT128_NEXTAFTER nextafterq +//#define BOOST_CSTDFLOAT_FLOAT128_NEXTTOWARD nexttowardq +#define BOOST_CSTDFLOAT_FLOAT128_COPYSIGN copysignq +#define BOOST_CSTDFLOAT_FLOAT128_SIGNBIT signbitq +//#define BOOST_CSTDFLOAT_FLOAT128_FPCLASSIFY fpclassifyq +//#define BOOST_CSTDFLOAT_FLOAT128_ISFINITE isfiniteq +#define BOOST_CSTDFLOAT_FLOAT128_ISINF isinfq +#define BOOST_CSTDFLOAT_FLOAT128_ISNAN isnanq +//#define BOOST_CSTDFLOAT_FLOAT128_ISNORMAL isnormalq +//#define BOOST_CSTDFLOAT_FLOAT128_ISGREATER isgreaterq +//#define BOOST_CSTDFLOAT_FLOAT128_ISGREATEREQUAL isgreaterequalq +//#define BOOST_CSTDFLOAT_FLOAT128_ISLESS islessq +//#define BOOST_CSTDFLOAT_FLOAT128_ISLESSEQUAL islessequalq +//#define BOOST_CSTDFLOAT_FLOAT128_ISLESSGREATER islessgreaterq +//#define BOOST_CSTDFLOAT_FLOAT128_ISUNORDERED isunorderedq +// end more functions +#endif + +// Implement quadruple-precision functions in the namespace +// boost::math::cstdfloat::detail. Subsequently inject these into the +// std namespace via *using* directive. + +// Begin with some forward function declarations. Also implement patches +// for compilers that have broken float128 exponential functions. + +extern "C" int quadmath_snprintf(char*, std::size_t, const char*, ...) BOOST_MATH_NOTHROW; + +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LDEXP(boost::math::cstdfloat::detail::float_internal128_t, int) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FREXP(boost::math::cstdfloat::detail::float_internal128_t, int*) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FABS(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FLOOR(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_CEIL(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SQRT(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TRUNC(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_POW(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LOG(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LOG10(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SIN(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_COS(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TAN(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ASIN(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ACOS(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ATAN(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FMOD(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ATAN2(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LGAMMA(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; + +// begin more functions +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_REMAINDER(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_REMQUO(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t, int*) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FMA(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FMAX(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FMIN(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FDIM(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_NAN(const char*) BOOST_MATH_NOTHROW; +//extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_EXP2 (boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LOG2(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LOG1P(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_CBRT(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_HYPOT(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ERF(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ERFC(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" long long int BOOST_CSTDFLOAT_FLOAT128_LLROUND(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" long int BOOST_CSTDFLOAT_FLOAT128_LROUND(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ROUND(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_NEARBYINT(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" long long int BOOST_CSTDFLOAT_FLOAT128_LLRINT(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" long int BOOST_CSTDFLOAT_FLOAT128_LRINT(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_RINT(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_MODF(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t*) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SCALBLN(boost::math::cstdfloat::detail::float_internal128_t, long int) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SCALBN(boost::math::cstdfloat::detail::float_internal128_t, int) BOOST_MATH_NOTHROW; +extern "C" int BOOST_CSTDFLOAT_FLOAT128_ILOGB(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LOGB(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_NEXTAFTER(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +//extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_NEXTTOWARD (boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_COPYSIGN(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" int BOOST_CSTDFLOAT_FLOAT128_SIGNBIT(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +//extern "C" int BOOST_CSTDFLOAT_FLOAT128_FPCLASSIFY (boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +//extern "C" int BOOST_CSTDFLOAT_FLOAT128_ISFINITE (boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" int BOOST_CSTDFLOAT_FLOAT128_ISINF(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" int BOOST_CSTDFLOAT_FLOAT128_ISNAN(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +//extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ISNORMAL (boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +//extern "C" int BOOST_CSTDFLOAT_FLOAT128_ISGREATER (boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +//extern "C" int BOOST_CSTDFLOAT_FLOAT128_ISGREATEREQUAL(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +//extern "C" int BOOST_CSTDFLOAT_FLOAT128_ISLESS (boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +//extern "C" int BOOST_CSTDFLOAT_FLOAT128_ISLESSEQUAL (boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +//extern "C" int BOOST_CSTDFLOAT_FLOAT128_ISLESSGREATER(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +//extern "C" int BOOST_CSTDFLOAT_FLOAT128_ISUNORDERED (boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; + // end more functions + +#if !defined(BOOST_CSTDFLOAT_BROKEN_FLOAT128_MATH_FUNCTIONS) + +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_EXP(boost::math::cstdfloat::detail::float_internal128_t x) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_EXPM1(boost::math::cstdfloat::detail::float_internal128_t x) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SINH(boost::math::cstdfloat::detail::float_internal128_t x) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_COSH(boost::math::cstdfloat::detail::float_internal128_t x) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TANH(boost::math::cstdfloat::detail::float_internal128_t x) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ASINH(boost::math::cstdfloat::detail::float_internal128_t x) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ACOSH(boost::math::cstdfloat::detail::float_internal128_t x) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ATANH(boost::math::cstdfloat::detail::float_internal128_t x) BOOST_MATH_NOTHROW; +extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TGAMMA(boost::math::cstdfloat::detail::float_internal128_t x) BOOST_MATH_NOTHROW; + +#else // BOOST_CSTDFLOAT_BROKEN_FLOAT128_MATH_FUNCTIONS + +// Forward declaration of the patched exponent function, exp(x). +inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_EXP(boost::math::cstdfloat::detail::float_internal128_t x); + +inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_EXPM1(boost::math::cstdfloat::detail::float_internal128_t x) +{ + // Compute exp(x) - 1 for x small. + + // Use an order-12 Pade approximation of the exponential function. + // PadeApproximant[Exp[x] - 1, {x, 0, 12, 12}]. + + typedef boost::math::cstdfloat::detail::float_internal128_t float_type; + + float_type sum; + + if (x > BOOST_FLOAT128_C(0.693147180559945309417232121458176568075500134360255)) + { + sum = ::BOOST_CSTDFLOAT_FLOAT128_EXP(x) - float_type(1); + } + else + { + const float_type x2 = (x * x); + + const float_type top = ((((( float_type(BOOST_FLOAT128_C(2.4087176110456818621091195109360728010934088788572E-13)) * x2 + + float_type(BOOST_FLOAT128_C(9.2735628025258751691201101171038802842096241836000E-10))) * x2 + + float_type(BOOST_FLOAT128_C(9.0806726962333369656024118266681195742980640005812E-07))) * x2 + + float_type(BOOST_FLOAT128_C(3.1055900621118012422360248447204968944099378881988E-04))) * x2 + + float_type(BOOST_FLOAT128_C(3.6231884057971014492753623188405797101449275362319E-02))) * x2 + + float_type(BOOST_FLOAT128_C(1.00000000000000000000000000000000000000000000000000000))) + ; + + const float_type bot = (((((((((((( float_type(BOOST_FLOAT128_C(+7.7202487533515444298369215094104897470942592271063E-16)) * x + + float_type(BOOST_FLOAT128_C(-1.2043588055228409310545597554680364005467044394286E-13))) * x + + float_type(BOOST_FLOAT128_C(+9.2735628025258751691201101171038802842096241836000E-12))) * x + + float_type(BOOST_FLOAT128_C(-4.6367814012629375845600550585519401421048120918000E-10))) * x + + float_type(BOOST_FLOAT128_C(+1.6692413044546575304416198210786984511577323530480E-08))) * x + + float_type(BOOST_FLOAT128_C(-4.5403363481166684828012059133340597871490320002906E-07))) * x + + float_type(BOOST_FLOAT128_C(+9.5347063310450038138825324180015255530129672006102E-06))) * x + + float_type(BOOST_FLOAT128_C(-1.5527950310559006211180124223602484472049689440994E-04))) * x + + float_type(BOOST_FLOAT128_C(+1.9409937888198757763975155279503105590062111801242E-03))) * x + + float_type(BOOST_FLOAT128_C(-1.8115942028985507246376811594202898550724637681159E-02))) * x + + float_type(BOOST_FLOAT128_C(+1.1956521739130434782608695652173913043478260869565E-01))) * x + + float_type(BOOST_FLOAT128_C(-0.50000000000000000000000000000000000000000000000000000))) * x + + float_type(BOOST_FLOAT128_C(+1.00000000000000000000000000000000000000000000000000000))) + ; + + sum = (x * top) / bot; + } + + return sum; +} +inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_EXP(boost::math::cstdfloat::detail::float_internal128_t x) +{ + // Patch the expq() function for a subset of broken GCC compilers + // like GCC 4.7, 4.8 on MinGW. + + typedef boost::math::cstdfloat::detail::float_internal128_t float_type; + + // Scale the argument x to the range (-ln2 < x < ln2). + constexpr float_type one_over_ln2 = float_type(BOOST_FLOAT128_C(1.44269504088896340735992468100189213742664595415299)); + const float_type x_over_ln2 = x * one_over_ln2; + + int n; + + if (x != x) + { + // The argument is NaN. + return std::numeric_limits::quiet_NaN(); + } + else if (::BOOST_CSTDFLOAT_FLOAT128_FABS(x) > BOOST_FLOAT128_C(+0.693147180559945309417232121458176568075500134360255)) + { + // The absolute value of the argument exceeds ln2. + n = static_cast(::BOOST_CSTDFLOAT_FLOAT128_FLOOR(x_over_ln2)); + } + else if (::BOOST_CSTDFLOAT_FLOAT128_FABS(x) < BOOST_FLOAT128_C(+0.693147180559945309417232121458176568075500134360255)) + { + // The absolute value of the argument is less than ln2. + n = 0; + } + else + { + // The absolute value of the argument is exactly equal to ln2 (in the sense of floating-point equality). + return float_type(2); + } + + // Check if the argument is very near an integer. + const float_type floor_of_x = ::BOOST_CSTDFLOAT_FLOAT128_FLOOR(x); + + if (::BOOST_CSTDFLOAT_FLOAT128_FABS(x - floor_of_x) < float_type(BOOST_CSTDFLOAT_FLOAT128_EPS)) + { + // Return e^n for arguments very near an integer. + return boost::math::cstdfloat::detail::pown(BOOST_FLOAT128_C(2.71828182845904523536028747135266249775724709369996), static_cast(floor_of_x)); + } + + // Compute the scaled argument alpha. + const float_type alpha = x - (n * BOOST_FLOAT128_C(0.693147180559945309417232121458176568075500134360255)); + + // Compute the polynomial approximation of expm1(alpha) and add to it + // in order to obtain the scaled result. + const float_type scaled_result = ::BOOST_CSTDFLOAT_FLOAT128_EXPM1(alpha) + float_type(1); + + // Rescale the result and return it. + return scaled_result * boost::math::cstdfloat::detail::pown(float_type(2), n); +} +inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SINH(boost::math::cstdfloat::detail::float_internal128_t x) +{ + // Patch the sinhq() function for a subset of broken GCC compilers + // like GCC 4.7, 4.8 on MinGW. + typedef boost::math::cstdfloat::detail::float_internal128_t float_type; + + // Here, we use the following: + // Set: ex = exp(x) + // Set: em1 = expm1(x) + // Then + // sinh(x) = (ex - 1/ex) / 2 ; for |x| >= 1 + // sinh(x) = (2em1 + em1^2) / (2ex) ; for |x| < 1 + + const float_type ex = ::BOOST_CSTDFLOAT_FLOAT128_EXP(x); + + if (::BOOST_CSTDFLOAT_FLOAT128_FABS(x) < float_type(+1)) + { + const float_type em1 = ::BOOST_CSTDFLOAT_FLOAT128_EXPM1(x); + + return ((em1 * 2) + (em1 * em1)) / (ex * 2); + } + else + { + return (ex - (float_type(1) / ex)) / 2; + } +} +inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_COSH(boost::math::cstdfloat::detail::float_internal128_t x) +{ + // Patch the coshq() function for a subset of broken GCC compilers + // like GCC 4.7, 4.8 on MinGW. + typedef boost::math::cstdfloat::detail::float_internal128_t float_type; + const float_type ex = ::BOOST_CSTDFLOAT_FLOAT128_EXP(x); + return (ex + (float_type(1) / ex)) / 2; +} +inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TANH(boost::math::cstdfloat::detail::float_internal128_t x) +{ + // Patch the tanhq() function for a subset of broken GCC compilers + // like GCC 4.7, 4.8 on MinGW. + typedef boost::math::cstdfloat::detail::float_internal128_t float_type; + const float_type ex_plus = ::BOOST_CSTDFLOAT_FLOAT128_EXP(x); + const float_type ex_minus = (float_type(1) / ex_plus); + return (ex_plus - ex_minus) / (ex_plus + ex_minus); +} +inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ASINH(boost::math::cstdfloat::detail::float_internal128_t x) BOOST_MATH_NOTHROW +{ + // Patch the asinh() function since quadmath does not have it. + typedef boost::math::cstdfloat::detail::float_internal128_t float_type; + return ::BOOST_CSTDFLOAT_FLOAT128_LOG(x + ::BOOST_CSTDFLOAT_FLOAT128_SQRT((x * x) + float_type(1))); +} +inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ACOSH(boost::math::cstdfloat::detail::float_internal128_t x) BOOST_MATH_NOTHROW +{ + // Patch the acosh() function since quadmath does not have it. + typedef boost::math::cstdfloat::detail::float_internal128_t float_type; + const float_type zp(x + float_type(1)); + const float_type zm(x - float_type(1)); + + return ::BOOST_CSTDFLOAT_FLOAT128_LOG(x + (zp * ::BOOST_CSTDFLOAT_FLOAT128_SQRT(zm / zp))); +} +inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ATANH(boost::math::cstdfloat::detail::float_internal128_t x) BOOST_MATH_NOTHROW +{ + // Patch the atanh() function since quadmath does not have it. + typedef boost::math::cstdfloat::detail::float_internal128_t float_type; + return (::BOOST_CSTDFLOAT_FLOAT128_LOG(float_type(1) + x) + - ::BOOST_CSTDFLOAT_FLOAT128_LOG(float_type(1) - x)) / 2; +} +inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TGAMMA(boost::math::cstdfloat::detail::float_internal128_t x) BOOST_MATH_NOTHROW +{ + // Patch the tgammaq() function for a subset of broken GCC compilers + // like GCC 4.7, 4.8 on MinGW. + typedef boost::math::cstdfloat::detail::float_internal128_t float_type; + + if (x > float_type(0)) + { + return ::BOOST_CSTDFLOAT_FLOAT128_EXP(::BOOST_CSTDFLOAT_FLOAT128_LGAMMA(x)); + } + else if (x < float_type(0)) + { + // For x < 0, compute tgamma(-x) and use the reflection formula. + const float_type positive_x = -x; + float_type gamma_value = ::BOOST_CSTDFLOAT_FLOAT128_TGAMMA(positive_x); + const float_type floor_of_positive_x = ::BOOST_CSTDFLOAT_FLOAT128_FLOOR(positive_x); + + // Take the reflection checks (slightly adapted) from . + const bool floor_of_z_is_equal_to_z = (positive_x == ::BOOST_CSTDFLOAT_FLOAT128_FLOOR(positive_x)); + + constexpr float_type my_pi = BOOST_FLOAT128_C(3.14159265358979323846264338327950288419716939937511); + + if (floor_of_z_is_equal_to_z) + { + const bool is_odd = ((std::int32_t(floor_of_positive_x) % std::int32_t(2)) != std::int32_t(0)); + + return (is_odd ? -std::numeric_limits::infinity() + : +std::numeric_limits::infinity()); + } + + const float_type sinpx_value = x * ::BOOST_CSTDFLOAT_FLOAT128_SIN(my_pi * x); + + gamma_value *= sinpx_value; + + const bool result_is_too_large_to_represent = ((::BOOST_CSTDFLOAT_FLOAT128_FABS(gamma_value) < float_type(1)) + && (((std::numeric_limits::max)() * ::BOOST_CSTDFLOAT_FLOAT128_FABS(gamma_value)) < my_pi)); + + if (result_is_too_large_to_represent) + { + const bool is_odd = ((std::int32_t(floor_of_positive_x) % std::int32_t(2)) != std::int32_t(0)); + + return (is_odd ? -std::numeric_limits::infinity() + : +std::numeric_limits::infinity()); + } + + gamma_value = -my_pi / gamma_value; + + if ((gamma_value > float_type(0)) || (gamma_value < float_type(0))) + { + return gamma_value; + } + else + { + // The value of gamma is too small to represent. Return 0.0 here. + return float_type(0); + } + } + else + { + // Gamma of zero is complex infinity. Return NaN here. + return std::numeric_limits::quiet_NaN(); + } +} +#endif // BOOST_CSTDFLOAT_BROKEN_FLOAT128_MATH_FUNCTIONS + +// Define the quadruple-precision functions in the namespace boost::math::cstdfloat::detail. + +namespace boost { + namespace math { + namespace cstdfloat { + namespace detail { + inline boost::math::cstdfloat::detail::float_internal128_t ldexp(boost::math::cstdfloat::detail::float_internal128_t x, int n) { return ::BOOST_CSTDFLOAT_FLOAT128_LDEXP(x, n); } + inline boost::math::cstdfloat::detail::float_internal128_t frexp(boost::math::cstdfloat::detail::float_internal128_t x, int* pn) { return ::BOOST_CSTDFLOAT_FLOAT128_FREXP(x, pn); } + inline boost::math::cstdfloat::detail::float_internal128_t fabs(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_FABS(x); } + inline boost::math::cstdfloat::detail::float_internal128_t abs(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_FABS(x); } + inline boost::math::cstdfloat::detail::float_internal128_t floor(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_FLOOR(x); } + inline boost::math::cstdfloat::detail::float_internal128_t ceil(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_CEIL(x); } + inline boost::math::cstdfloat::detail::float_internal128_t sqrt(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_SQRT(x); } + inline boost::math::cstdfloat::detail::float_internal128_t trunc(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_TRUNC(x); } + inline boost::math::cstdfloat::detail::float_internal128_t exp(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_EXP(x); } + inline boost::math::cstdfloat::detail::float_internal128_t expm1(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_EXPM1(x); } + inline boost::math::cstdfloat::detail::float_internal128_t pow(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t a) { return ::BOOST_CSTDFLOAT_FLOAT128_POW(x, a); } + inline boost::math::cstdfloat::detail::float_internal128_t pow(boost::math::cstdfloat::detail::float_internal128_t x, int a) { return ::BOOST_CSTDFLOAT_FLOAT128_POW(x, boost::math::cstdfloat::detail::float_internal128_t(a)); } + inline boost::math::cstdfloat::detail::float_internal128_t log(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LOG(x); } + inline boost::math::cstdfloat::detail::float_internal128_t log10(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LOG10(x); } + inline boost::math::cstdfloat::detail::float_internal128_t sin(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_SIN(x); } + inline boost::math::cstdfloat::detail::float_internal128_t cos(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_COS(x); } + inline boost::math::cstdfloat::detail::float_internal128_t tan(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_TAN(x); } + inline boost::math::cstdfloat::detail::float_internal128_t asin(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ASIN(x); } + inline boost::math::cstdfloat::detail::float_internal128_t acos(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ACOS(x); } + inline boost::math::cstdfloat::detail::float_internal128_t atan(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ATAN(x); } + inline boost::math::cstdfloat::detail::float_internal128_t sinh(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_SINH(x); } + inline boost::math::cstdfloat::detail::float_internal128_t cosh(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_COSH(x); } + inline boost::math::cstdfloat::detail::float_internal128_t tanh(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_TANH(x); } + inline boost::math::cstdfloat::detail::float_internal128_t asinh(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ASINH(x); } + inline boost::math::cstdfloat::detail::float_internal128_t acosh(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ACOSH(x); } + inline boost::math::cstdfloat::detail::float_internal128_t atanh(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ATANH(x); } + inline boost::math::cstdfloat::detail::float_internal128_t fmod(boost::math::cstdfloat::detail::float_internal128_t a, boost::math::cstdfloat::detail::float_internal128_t b) { return ::BOOST_CSTDFLOAT_FLOAT128_FMOD(a, b); } + inline boost::math::cstdfloat::detail::float_internal128_t atan2(boost::math::cstdfloat::detail::float_internal128_t y, boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ATAN2(y, x); } + inline boost::math::cstdfloat::detail::float_internal128_t lgamma(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LGAMMA(x); } + inline boost::math::cstdfloat::detail::float_internal128_t tgamma(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_TGAMMA(x); } + // begin more functions + inline boost::math::cstdfloat::detail::float_internal128_t remainder(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_REMAINDER(x, y); } + inline boost::math::cstdfloat::detail::float_internal128_t remquo(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y, int* z) { return ::BOOST_CSTDFLOAT_FLOAT128_REMQUO(x, y, z); } + inline boost::math::cstdfloat::detail::float_internal128_t fma(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y, boost::math::cstdfloat::detail::float_internal128_t z) { return BOOST_CSTDFLOAT_FLOAT128_FMA(x, y, z); } + + inline boost::math::cstdfloat::detail::float_internal128_t fmax(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_FMAX(x, y); } + template + inline typename std::enable_if< + std::is_convertible::value + && !std::is_same::value, boost::math::cstdfloat::detail::float_internal128_t>::type + fmax(boost::math::cstdfloat::detail::float_internal128_t x, T y) { return ::BOOST_CSTDFLOAT_FLOAT128_FMAX(x, y); } + template + inline typename std::enable_if< + std::is_convertible::value + && !std::is_same::value, boost::math::cstdfloat::detail::float_internal128_t>::type + fmax(T x, boost::math::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_FMAX(x, y); } + inline boost::math::cstdfloat::detail::float_internal128_t fmin(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_FMIN(x, y); } + template + inline typename std::enable_if< + std::is_convertible::value + && !std::is_same::value, boost::math::cstdfloat::detail::float_internal128_t>::type + fmin(boost::math::cstdfloat::detail::float_internal128_t x, T y) { return ::BOOST_CSTDFLOAT_FLOAT128_FMIN(x, y); } + template + inline typename std::enable_if< + std::is_convertible::value + && !std::is_same::value, boost::math::cstdfloat::detail::float_internal128_t>::type + fmin(T x, boost::math::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_FMIN(x, y); } + + inline boost::math::cstdfloat::detail::float_internal128_t fdim(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_FDIM(x, y); } + inline boost::math::cstdfloat::detail::float_internal128_t nanq(const char* x) { return ::BOOST_CSTDFLOAT_FLOAT128_NAN(x); } + inline boost::math::cstdfloat::detail::float_internal128_t exp2(boost::math::cstdfloat::detail::float_internal128_t x) + { + return ::BOOST_CSTDFLOAT_FLOAT128_POW(boost::math::cstdfloat::detail::float_internal128_t(2), x); + } + inline boost::math::cstdfloat::detail::float_internal128_t log2(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LOG2(x); } + inline boost::math::cstdfloat::detail::float_internal128_t log1p(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LOG1P(x); } + inline boost::math::cstdfloat::detail::float_internal128_t cbrt(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_CBRT(x); } + inline boost::math::cstdfloat::detail::float_internal128_t hypot(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y, boost::math::cstdfloat::detail::float_internal128_t z) { return ::BOOST_CSTDFLOAT_FLOAT128_SQRT(x*x + y * y + z * z); } + inline boost::math::cstdfloat::detail::float_internal128_t hypot(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_HYPOT(x, y); } + template + inline typename std::enable_if< + std::is_convertible::value + && !std::is_same::value, boost::math::cstdfloat::detail::float_internal128_t>::type + hypot(boost::math::cstdfloat::detail::float_internal128_t x, T y) { return ::BOOST_CSTDFLOAT_FLOAT128_HYPOT(x, y); } + template + inline typename std::enable_if< + std::is_convertible::value + && !std::is_same::value, boost::math::cstdfloat::detail::float_internal128_t>::type + hypot(T x, boost::math::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_HYPOT(x, y); } + + + inline boost::math::cstdfloat::detail::float_internal128_t erf(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ERF(x); } + inline boost::math::cstdfloat::detail::float_internal128_t erfc(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ERFC(x); } + inline long long int llround(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LLROUND(x); } + inline long int lround(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LROUND(x); } + inline boost::math::cstdfloat::detail::float_internal128_t round(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ROUND(x); } + inline boost::math::cstdfloat::detail::float_internal128_t nearbyint(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_NEARBYINT(x); } + inline long long int llrint(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LLRINT(x); } + inline long int lrint(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LRINT(x); } + inline boost::math::cstdfloat::detail::float_internal128_t rint(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_RINT(x); } + inline boost::math::cstdfloat::detail::float_internal128_t modf(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t* y) { return ::BOOST_CSTDFLOAT_FLOAT128_MODF(x, y); } + inline boost::math::cstdfloat::detail::float_internal128_t scalbln(boost::math::cstdfloat::detail::float_internal128_t x, long int y) { return ::BOOST_CSTDFLOAT_FLOAT128_SCALBLN(x, y); } + inline boost::math::cstdfloat::detail::float_internal128_t scalbn(boost::math::cstdfloat::detail::float_internal128_t x, int y) { return ::BOOST_CSTDFLOAT_FLOAT128_SCALBN(x, y); } + inline int ilogb(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ILOGB(x); } + inline boost::math::cstdfloat::detail::float_internal128_t logb(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LOGB(x); } + inline boost::math::cstdfloat::detail::float_internal128_t nextafter(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_NEXTAFTER(x, y); } + inline boost::math::cstdfloat::detail::float_internal128_t nexttoward(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) { return -(::BOOST_CSTDFLOAT_FLOAT128_NEXTAFTER(-x, -y)); } + inline boost::math::cstdfloat::detail::float_internal128_t copysign BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_COPYSIGN(x, y); } + inline bool signbit BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_SIGNBIT(x); } + inline int fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x) + { + if (::BOOST_CSTDFLOAT_FLOAT128_ISNAN(x)) + return FP_NAN; + else if (::BOOST_CSTDFLOAT_FLOAT128_ISINF(x)) + return FP_INFINITE; + else if (x == BOOST_FLOAT128_C(0.0)) + return FP_ZERO; + + if (::BOOST_CSTDFLOAT_FLOAT128_FABS(x) < BOOST_CSTDFLOAT_FLOAT128_MIN) + return FP_SUBNORMAL; + else + return FP_NORMAL; + } + inline bool isfinite BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x) + { + return !::BOOST_CSTDFLOAT_FLOAT128_ISNAN(x) && !::BOOST_CSTDFLOAT_FLOAT128_ISINF(x); + } + inline bool isinf BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ISINF(x); } + inline bool isnan BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ISNAN(x); } + inline bool isnormal BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x) { return boost::math::cstdfloat::detail::fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(x) == FP_NORMAL; } + inline bool isgreater BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) + { + if (isnan BOOST_PREVENT_MACRO_SUBSTITUTION(x) || isnan BOOST_PREVENT_MACRO_SUBSTITUTION(y)) + return false; + return x > y; + } + template + inline typename std::enable_if< + std::is_convertible::value + && !std::is_same::value, boost::math::cstdfloat::detail::float_internal128_t>::type + isgreater BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, T y) { return isgreater BOOST_PREVENT_MACRO_SUBSTITUTION(x, (boost::math::cstdfloat::detail::float_internal128_t)y); } + template + inline typename std::enable_if< + std::is_convertible::value + && !std::is_same::value, boost::math::cstdfloat::detail::float_internal128_t>::type + isgreater BOOST_PREVENT_MACRO_SUBSTITUTION(T x, boost::math::cstdfloat::detail::float_internal128_t y) { return isgreater BOOST_PREVENT_MACRO_SUBSTITUTION((boost::math::cstdfloat::detail::float_internal128_t)x, y); } + + inline bool isgreaterequal BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) + { + if (isnan BOOST_PREVENT_MACRO_SUBSTITUTION(x) || isnan BOOST_PREVENT_MACRO_SUBSTITUTION(y)) + return false; + return x >= y; + } + template + inline typename std::enable_if< + std::is_convertible::value + && !std::is_same::value, boost::math::cstdfloat::detail::float_internal128_t>::type + isgreaterequal BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, T y) { return isgreaterequal BOOST_PREVENT_MACRO_SUBSTITUTION(x, (boost::math::cstdfloat::detail::float_internal128_t)y); } + template + inline typename std::enable_if< + std::is_convertible::value + && !std::is_same::value, boost::math::cstdfloat::detail::float_internal128_t>::type + isgreaterequal BOOST_PREVENT_MACRO_SUBSTITUTION(T x, boost::math::cstdfloat::detail::float_internal128_t y) { return isgreaterequal BOOST_PREVENT_MACRO_SUBSTITUTION((boost::math::cstdfloat::detail::float_internal128_t)x, y); } + + inline bool isless BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) + { + if (isnan BOOST_PREVENT_MACRO_SUBSTITUTION(x) || isnan BOOST_PREVENT_MACRO_SUBSTITUTION(y)) + return false; + return x < y; + } + template + inline typename std::enable_if< + std::is_convertible::value + && !std::is_same::value, boost::math::cstdfloat::detail::float_internal128_t>::type + isless BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, T y) { return isless BOOST_PREVENT_MACRO_SUBSTITUTION(x, (boost::math::cstdfloat::detail::float_internal128_t)y); } + template + inline typename std::enable_if< + std::is_convertible::value + && !std::is_same::value, boost::math::cstdfloat::detail::float_internal128_t>::type + isless BOOST_PREVENT_MACRO_SUBSTITUTION(T x, boost::math::cstdfloat::detail::float_internal128_t y) { return isless BOOST_PREVENT_MACRO_SUBSTITUTION((boost::math::cstdfloat::detail::float_internal128_t)x, y); } + + + inline bool islessequal BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) + { + if (isnan BOOST_PREVENT_MACRO_SUBSTITUTION(x) || isnan BOOST_PREVENT_MACRO_SUBSTITUTION(y)) + return false; + return x <= y; + } + template + inline typename std::enable_if< + std::is_convertible::value + && !std::is_same::value, boost::math::cstdfloat::detail::float_internal128_t>::type + islessequal BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, T y) { return islessequal BOOST_PREVENT_MACRO_SUBSTITUTION(x, (boost::math::cstdfloat::detail::float_internal128_t)y); } + template + inline typename std::enable_if< + std::is_convertible::value + && !std::is_same::value, boost::math::cstdfloat::detail::float_internal128_t>::type + islessequal BOOST_PREVENT_MACRO_SUBSTITUTION(T x, boost::math::cstdfloat::detail::float_internal128_t y) { return islessequal BOOST_PREVENT_MACRO_SUBSTITUTION((boost::math::cstdfloat::detail::float_internal128_t)x, y); } + + + inline bool islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) + { + if (isnan BOOST_PREVENT_MACRO_SUBSTITUTION(x) || isnan BOOST_PREVENT_MACRO_SUBSTITUTION(y)) + return false; + return (x < y) || (x > y); + } + template + inline typename std::enable_if< + std::is_convertible::value + && !std::is_same::value, boost::math::cstdfloat::detail::float_internal128_t>::type + islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, T y) { return islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(x, (boost::math::cstdfloat::detail::float_internal128_t)y); } + template + inline typename std::enable_if< + std::is_convertible::value + && !std::is_same::value, boost::math::cstdfloat::detail::float_internal128_t>::type + islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(T x, boost::math::cstdfloat::detail::float_internal128_t y) { return islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION((boost::math::cstdfloat::detail::float_internal128_t)x, y); } + + + inline bool isunordered BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_ISNAN(x) || ::BOOST_CSTDFLOAT_FLOAT128_ISNAN(y); } + template + inline typename std::enable_if< + std::is_convertible::value + && !std::is_same::value, boost::math::cstdfloat::detail::float_internal128_t>::type + isunordered BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, T y) { return isunordered BOOST_PREVENT_MACRO_SUBSTITUTION(x, (boost::math::cstdfloat::detail::float_internal128_t)y); } + template + inline typename std::enable_if< + std::is_convertible::value + && !std::is_same::value, boost::math::cstdfloat::detail::float_internal128_t>::type + isunordered BOOST_PREVENT_MACRO_SUBSTITUTION(T x, boost::math::cstdfloat::detail::float_internal128_t y) { return isunordered BOOST_PREVENT_MACRO_SUBSTITUTION((boost::math::cstdfloat::detail::float_internal128_t)x, y); } + + + // end more functions + } + } + } +} // boost::math::cstdfloat::detail + +// We will now inject the quadruple-precision functions +// into the std namespace. This is done via *using* directive. +namespace std +{ + using boost::math::cstdfloat::detail::ldexp; + using boost::math::cstdfloat::detail::frexp; + using boost::math::cstdfloat::detail::fabs; + +#if !(defined(_GLIBCXX_USE_FLOAT128) && defined(__GNUC__) && (__GNUC__ >= 7)) +#if (defined(__clang__) && !(!defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128))) || (__GNUC__ <= 6 && !defined(__clang__)) + // workaround for clang using libstdc++ and old GCC + using boost::math::cstdfloat::detail::abs; +#endif +#endif + + using boost::math::cstdfloat::detail::floor; + using boost::math::cstdfloat::detail::ceil; + using boost::math::cstdfloat::detail::sqrt; + using boost::math::cstdfloat::detail::trunc; + using boost::math::cstdfloat::detail::exp; + using boost::math::cstdfloat::detail::expm1; + using boost::math::cstdfloat::detail::pow; + using boost::math::cstdfloat::detail::log; + using boost::math::cstdfloat::detail::log10; + using boost::math::cstdfloat::detail::sin; + using boost::math::cstdfloat::detail::cos; + using boost::math::cstdfloat::detail::tan; + using boost::math::cstdfloat::detail::asin; + using boost::math::cstdfloat::detail::acos; + using boost::math::cstdfloat::detail::atan; + using boost::math::cstdfloat::detail::sinh; + using boost::math::cstdfloat::detail::cosh; + using boost::math::cstdfloat::detail::tanh; + using boost::math::cstdfloat::detail::asinh; + using boost::math::cstdfloat::detail::acosh; + using boost::math::cstdfloat::detail::atanh; + using boost::math::cstdfloat::detail::fmod; + using boost::math::cstdfloat::detail::atan2; + using boost::math::cstdfloat::detail::lgamma; + using boost::math::cstdfloat::detail::tgamma; + + // begin more functions + using boost::math::cstdfloat::detail::remainder; + using boost::math::cstdfloat::detail::remquo; + using boost::math::cstdfloat::detail::fma; + using boost::math::cstdfloat::detail::fmax; + using boost::math::cstdfloat::detail::fmin; + using boost::math::cstdfloat::detail::fdim; + using boost::math::cstdfloat::detail::nanq; + using boost::math::cstdfloat::detail::exp2; + using boost::math::cstdfloat::detail::log2; + using boost::math::cstdfloat::detail::log1p; + using boost::math::cstdfloat::detail::cbrt; + using boost::math::cstdfloat::detail::hypot; + using boost::math::cstdfloat::detail::erf; + using boost::math::cstdfloat::detail::erfc; + using boost::math::cstdfloat::detail::llround; + using boost::math::cstdfloat::detail::lround; + using boost::math::cstdfloat::detail::round; + using boost::math::cstdfloat::detail::nearbyint; + using boost::math::cstdfloat::detail::llrint; + using boost::math::cstdfloat::detail::lrint; + using boost::math::cstdfloat::detail::rint; + using boost::math::cstdfloat::detail::modf; + using boost::math::cstdfloat::detail::scalbln; + using boost::math::cstdfloat::detail::scalbn; + using boost::math::cstdfloat::detail::ilogb; + using boost::math::cstdfloat::detail::logb; + using boost::math::cstdfloat::detail::nextafter; + using boost::math::cstdfloat::detail::nexttoward; + using boost::math::cstdfloat::detail::copysign; + using boost::math::cstdfloat::detail::signbit; + using boost::math::cstdfloat::detail::fpclassify; + using boost::math::cstdfloat::detail::isfinite; + using boost::math::cstdfloat::detail::isinf; + using boost::math::cstdfloat::detail::isnan; + using boost::math::cstdfloat::detail::isnormal; + using boost::math::cstdfloat::detail::isgreater; + using boost::math::cstdfloat::detail::isgreaterequal; + using boost::math::cstdfloat::detail::isless; + using boost::math::cstdfloat::detail::islessequal; + using boost::math::cstdfloat::detail::islessgreater; + using boost::math::cstdfloat::detail::isunordered; + // end more functions + + // + // Very basic iostream operator: + // + inline std::ostream& operator << (std::ostream& os, __float128 m_value) + { + std::streamsize digits = os.precision(); + std::ios_base::fmtflags f = os.flags(); + std::string s; + + char buf[100]; + std::unique_ptr buf2; + std::string format = "%"; + if (f & std::ios_base::showpos) + format += "+"; + if (f & std::ios_base::showpoint) + format += "#"; + format += ".*"; + if (digits == 0) + digits = 36; + format += "Q"; + if (f & std::ios_base::scientific) + format += "e"; + else if (f & std::ios_base::fixed) + format += "f"; + else + format += "g"; + + int v = quadmath_snprintf(buf, 100, format.c_str(), digits, m_value); + + if ((v < 0) || (v >= 99)) + { + int v_max = v; + buf2.reset(new char[v + 3]); + v = quadmath_snprintf(&buf2[0], v_max + 3, format.c_str(), digits, m_value); + if (v >= v_max + 3) + { + BOOST_MATH_THROW_EXCEPTION(std::runtime_error("Formatting of float128_type failed.")); + } + s = &buf2[0]; + } + else + s = buf; + std::streamsize ss = os.width(); + if (ss > static_cast(s.size())) + { + char fill = os.fill(); + if ((os.flags() & std::ios_base::left) == std::ios_base::left) + s.append(static_cast(ss - s.size()), fill); + else + s.insert(static_cast(0), static_cast(ss - s.size()), fill); + } + + return os << s; + } + + +} // namespace std + +// We will now remove the preprocessor symbols representing quadruple-precision +// functions from the preprocessor. + +#undef BOOST_CSTDFLOAT_FLOAT128_LDEXP +#undef BOOST_CSTDFLOAT_FLOAT128_FREXP +#undef BOOST_CSTDFLOAT_FLOAT128_FABS +#undef BOOST_CSTDFLOAT_FLOAT128_FLOOR +#undef BOOST_CSTDFLOAT_FLOAT128_CEIL +#undef BOOST_CSTDFLOAT_FLOAT128_SQRT +#undef BOOST_CSTDFLOAT_FLOAT128_TRUNC +#undef BOOST_CSTDFLOAT_FLOAT128_EXP +#undef BOOST_CSTDFLOAT_FLOAT128_EXPM1 +#undef BOOST_CSTDFLOAT_FLOAT128_POW +#undef BOOST_CSTDFLOAT_FLOAT128_LOG +#undef BOOST_CSTDFLOAT_FLOAT128_LOG10 +#undef BOOST_CSTDFLOAT_FLOAT128_SIN +#undef BOOST_CSTDFLOAT_FLOAT128_COS +#undef BOOST_CSTDFLOAT_FLOAT128_TAN +#undef BOOST_CSTDFLOAT_FLOAT128_ASIN +#undef BOOST_CSTDFLOAT_FLOAT128_ACOS +#undef BOOST_CSTDFLOAT_FLOAT128_ATAN +#undef BOOST_CSTDFLOAT_FLOAT128_SINH +#undef BOOST_CSTDFLOAT_FLOAT128_COSH +#undef BOOST_CSTDFLOAT_FLOAT128_TANH +#undef BOOST_CSTDFLOAT_FLOAT128_ASINH +#undef BOOST_CSTDFLOAT_FLOAT128_ACOSH +#undef BOOST_CSTDFLOAT_FLOAT128_ATANH +#undef BOOST_CSTDFLOAT_FLOAT128_FMOD +#undef BOOST_CSTDFLOAT_FLOAT128_ATAN2 +#undef BOOST_CSTDFLOAT_FLOAT128_LGAMMA +#undef BOOST_CSTDFLOAT_FLOAT128_TGAMMA + +// begin more functions +#undef BOOST_CSTDFLOAT_FLOAT128_REMAINDER +#undef BOOST_CSTDFLOAT_FLOAT128_REMQUO +#undef BOOST_CSTDFLOAT_FLOAT128_FMA +#undef BOOST_CSTDFLOAT_FLOAT128_FMAX +#undef BOOST_CSTDFLOAT_FLOAT128_FMIN +#undef BOOST_CSTDFLOAT_FLOAT128_FDIM +#undef BOOST_CSTDFLOAT_FLOAT128_NAN +#undef BOOST_CSTDFLOAT_FLOAT128_EXP2 +#undef BOOST_CSTDFLOAT_FLOAT128_LOG2 +#undef BOOST_CSTDFLOAT_FLOAT128_LOG1P +#undef BOOST_CSTDFLOAT_FLOAT128_CBRT +#undef BOOST_CSTDFLOAT_FLOAT128_HYPOT +#undef BOOST_CSTDFLOAT_FLOAT128_ERF +#undef BOOST_CSTDFLOAT_FLOAT128_ERFC +#undef BOOST_CSTDFLOAT_FLOAT128_LLROUND +#undef BOOST_CSTDFLOAT_FLOAT128_LROUND +#undef BOOST_CSTDFLOAT_FLOAT128_ROUND +#undef BOOST_CSTDFLOAT_FLOAT128_NEARBYINT +#undef BOOST_CSTDFLOAT_FLOAT128_LLRINT +#undef BOOST_CSTDFLOAT_FLOAT128_LRINT +#undef BOOST_CSTDFLOAT_FLOAT128_RINT +#undef BOOST_CSTDFLOAT_FLOAT128_MODF +#undef BOOST_CSTDFLOAT_FLOAT128_SCALBLN +#undef BOOST_CSTDFLOAT_FLOAT128_SCALBN +#undef BOOST_CSTDFLOAT_FLOAT128_ILOGB +#undef BOOST_CSTDFLOAT_FLOAT128_LOGB +#undef BOOST_CSTDFLOAT_FLOAT128_NEXTAFTER +#undef BOOST_CSTDFLOAT_FLOAT128_NEXTTOWARD +#undef BOOST_CSTDFLOAT_FLOAT128_COPYSIGN +#undef BOOST_CSTDFLOAT_FLOAT128_SIGNBIT +#undef BOOST_CSTDFLOAT_FLOAT128_FPCLASSIFY +#undef BOOST_CSTDFLOAT_FLOAT128_ISFINITE +#undef BOOST_CSTDFLOAT_FLOAT128_ISINF +#undef BOOST_CSTDFLOAT_FLOAT128_ISNAN +#undef BOOST_CSTDFLOAT_FLOAT128_ISNORMAL +#undef BOOST_CSTDFLOAT_FLOAT128_ISGREATER +#undef BOOST_CSTDFLOAT_FLOAT128_ISGREATEREQUAL +#undef BOOST_CSTDFLOAT_FLOAT128_ISLESS +#undef BOOST_CSTDFLOAT_FLOAT128_ISLESSEQUAL +#undef BOOST_CSTDFLOAT_FLOAT128_ISLESSGREATER +#undef BOOST_CSTDFLOAT_FLOAT128_ISUNORDERED +// end more functions + +#endif // Not BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT (i.e., the user would like to have libquadmath support) + +#endif // BOOST_MATH_CSTDFLOAT_CMATH_2014_02_15_HPP_ + diff --git a/libcxx/src/third-party/boost/math/cstdfloat/cstdfloat_complex.hpp b/libcxx/src/third-party/boost/math/cstdfloat/cstdfloat_complex.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/cstdfloat/cstdfloat_complex.hpp @@ -0,0 +1,38 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2014. +// Copyright John Maddock 2014. +// Copyright Paul Bristow 2014. +// 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) +// + +// Implement quadruple-precision (and extended) support for . + +#ifndef BOOST_MATH_CSTDFLOAT_COMPLEX_2014_02_15_HPP_ + #define BOOST_MATH_CSTDFLOAT_COMPLEX_2014_02_15_HPP_ + + #include + #include + #include + #include + + #if defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_LIMITS) + #error You can not use with BOOST_CSTDFLOAT_NO_LIBQUADMATH_LIMITS defined. + #endif + #if defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_CMATH) + #error You can not use with BOOST_CSTDFLOAT_NO_LIBQUADMATH_CMATH defined. + #endif + #if defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_IOSTREAM) + #error You can not use with BOOST_CSTDFLOAT_NO_LIBQUADMATH_IOSTREAM defined. + #endif + + #if defined(BOOST_CSTDFLOAT_HAS_INTERNAL_FLOAT128_T) && defined(BOOST_MATH_USE_FLOAT128) && !defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT) + + #define BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE boost::math::cstdfloat::detail::float_internal128_t + #include + #undef BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE + + #endif // Not BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT (i.e., the user would like to have libquadmath support) + +#endif // BOOST_MATH_CSTDFLOAT_COMPLEX_2014_02_15_HPP_ diff --git a/libcxx/src/third-party/boost/math/cstdfloat/cstdfloat_complex_std.hpp b/libcxx/src/third-party/boost/math/cstdfloat/cstdfloat_complex_std.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/cstdfloat/cstdfloat_complex_std.hpp @@ -0,0 +1,813 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2014. +// Copyright John Maddock 2014. +// Copyright Paul Bristow 2014. +// 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) +// + +// Implement a specialization of std::complex<> for *anything* that +// is defined as BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE. + +#ifndef BOOST_MATH_CSTDFLOAT_COMPLEX_STD_2014_02_15_HPP_ + #define BOOST_MATH_CSTDFLOAT_COMPLEX_STD_2014_02_15_HPP_ + + #if defined(__GNUC__) + #pragma GCC system_header + #endif + + #include + #include + #include + + namespace std + { + // Forward declarations. + template + class complex; + + template<> + class complex; + + inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE real(const complex&); + inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE imag(const complex&); + + inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE abs (const complex&); + inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE arg (const complex&); + inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE norm(const complex&); + + inline complex conj (const complex&); + inline complex proj (const complex&); + + inline complex polar(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE&, + const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& = 0); + + inline complex sqrt (const complex&); + + inline complex sin (const complex&); + inline complex cos (const complex&); + inline complex tan (const complex&); + inline complex asin (const complex&); + inline complex acos (const complex&); + inline complex atan (const complex&); + + inline complex exp (const complex&); + inline complex log (const complex&); + inline complex log10(const complex&); + + inline complex pow (const complex&, + int); + inline complex pow (const complex&, + const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE&); + inline complex pow (const complex&, + const complex&); + inline complex pow (const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE&, + const complex&); + + inline complex sinh (const complex&); + inline complex cosh (const complex&); + inline complex tanh (const complex&); + + inline complex asinh(const complex&); + inline complex acosh(const complex&); + inline complex atanh(const complex&); + + template + inline std::basic_ostream& operator<<(std::basic_ostream&, const std::complex&); + + template + inline std::basic_istream& operator>>(std::basic_istream&, std::complex&); + + // Template specialization of the complex class. + template<> + class complex + { + public: + typedef BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE value_type; + + complex(const complex&); + complex(const complex&); + complex(const complex&); + + #if defined(BOOST_NO_CXX11_CONSTEXPR) + complex(const value_type& r = value_type(), + const value_type& i = value_type()) : re(r), + im(i) { } + + template + explicit complex(const complex& x) : re(x.real()), + im(x.imag()) { } + + const value_type& real() const { return re; } + const value_type& imag() const { return im; } + + value_type& real() { return re; } + value_type& imag() { return im; } + #else + constexpr complex(const value_type& r = value_type(), + const value_type& i = value_type()) : re(r), + im(i) { } + + template + explicit constexpr complex(const complex& x) : re(x.real()), + im(x.imag()) { } + + value_type real() const { return re; } + value_type imag() const { return im; } + #endif + + void real(value_type r) { re = r; } + void imag(value_type i) { im = i; } + + complex& operator=(const value_type& v) + { + re = v; + im = value_type(0); + return *this; + } + + complex& operator+=(const value_type& v) + { + re += v; + return *this; + } + + complex& operator-=(const value_type& v) + { + re -= v; + return *this; + } + + complex& operator*=(const value_type& v) + { + re *= v; + im *= v; + return *this; + } + + complex& operator/=(const value_type& v) + { + re /= v; + im /= v; + return *this; + } + + template + complex& operator=(const complex& x) + { + re = x.real(); + im = x.imag(); + return *this; + } + + template + complex& operator+=(const complex& x) + { + re += x.real(); + im += x.imag(); + return *this; + } + + template + complex& operator-=(const complex& x) + { + re -= x.real(); + im -= x.imag(); + return *this; + } + + template + complex& operator*=(const complex& x) + { + const value_type tmp_real = (re * x.real()) - (im * x.imag()); + im = (re * x.imag()) + (im * x.real()); + re = tmp_real; + return *this; + } + + template + complex& operator/=(const complex& x) + { + const value_type tmp_real = (re * x.real()) + (im * x.imag()); + const value_type the_norm = std::norm(x); + im = ((im * x.real()) - (re * x.imag())) / the_norm; + re = tmp_real / the_norm; + return *this; + } + + private: + value_type re; + value_type im; + }; + + // Constructors from built-in complex representation of floating-point types. + inline complex::complex(const complex& f) : re(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE( f.real())), im(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE( f.imag())) { } + inline complex::complex(const complex& d) : re(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE( d.real())), im(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE( d.imag())) { } + inline complex::complex(const complex& ld) : re(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(ld.real())), im(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(ld.imag())) { } + } // namespace std + + namespace boost { namespace math { namespace cstdfloat { namespace detail { + template inline std::complex multiply_by_i(const std::complex& x) + { + // Multiply x (in C) by I (the imaginary component), and return the result. + return std::complex(-x.imag(), x.real()); + } + } } } } // boost::math::cstdfloat::detail + + namespace std + { + // ISO/IEC 14882:2011, Section 26.4.7, specific values. + inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE real(const complex& x) { return x.real(); } + inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE imag(const complex& x) { return x.imag(); } + + inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE abs (const complex& x) { using std::sqrt; return sqrt ((real(x) * real(x)) + (imag(x) * imag(x))); } + inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE arg (const complex& x) { using std::atan2; return atan2(x.imag(), x.real()); } + inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE norm(const complex& x) { return (real(x) * real(x)) + (imag(x) * imag(x)); } + + inline complex conj (const complex& x) { return complex(x.real(), -x.imag()); } + + inline complex proj (const complex& x) + { + const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE m = (std::numeric_limits::max)(); + if ( (x.real() > m) + || (x.real() < -m) + || (x.imag() > m) + || (x.imag() < -m)) + { + // We have an infinity, return a normalized infinity, respecting the sign of the imaginary part: + return complex(std::numeric_limits::infinity(), x.imag() < 0 ? -0 : 0); + } + return x; + } + + inline complex polar(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& rho, + const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& theta) + { + using std::sin; + using std::cos; + + return complex(rho * cos(theta), rho * sin(theta)); + } + + // Global add, sub, mul, div. + inline complex operator+(const complex& u, const complex& v) { return complex(u.real() + v.real(), u.imag() + v.imag()); } + inline complex operator-(const complex& u, const complex& v) { return complex(u.real() - v.real(), u.imag() - v.imag()); } + + inline complex operator*(const complex& u, const complex& v) + { + return complex((u.real() * v.real()) - (u.imag() * v.imag()), + (u.real() * v.imag()) + (u.imag() * v.real())); + } + + inline complex operator/(const complex& u, const complex& v) + { + const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE the_norm = std::norm(v); + + return complex(((u.real() * v.real()) + (u.imag() * v.imag())) / the_norm, + ((u.imag() * v.real()) - (u.real() * v.imag())) / the_norm); + } + + inline complex operator+(const complex& u, const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& v) { return complex(u.real() + v, u.imag()); } + inline complex operator-(const complex& u, const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& v) { return complex(u.real() - v, u.imag()); } + inline complex operator*(const complex& u, const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& v) { return complex(u.real() * v, u.imag() * v); } + inline complex operator/(const complex& u, const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& v) { return complex(u.real() / v, u.imag() / v); } + + inline complex operator+(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& u, const complex& v) { return complex(u + v.real(), v.imag()); } + inline complex operator-(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& u, const complex& v) { return complex(u - v.real(), -v.imag()); } + inline complex operator*(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& u, const complex& v) { return complex(u * v.real(), u * v.imag()); } + inline complex operator/(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& u, const complex& v) { const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE v_norm = norm(v); return complex((u * v.real()) / v_norm, (-u * v.imag()) / v_norm); } + + // Unary plus / minus. + inline complex operator+(const complex& u) { return u; } + inline complex operator-(const complex& u) { return complex(-u.real(), -u.imag()); } + + // Equality and inequality. + inline bool operator==(const complex& x, const complex& y) { return ((x.real() == y.real()) && (x.imag() == y.imag())); } + inline bool operator==(const complex& x, const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& y) { return ((x.real() == y) && (x.imag() == BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(0))); } + inline bool operator==(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& x, const complex& y) { return ((x == y.real()) && (y.imag() == BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(0))); } + inline bool operator!=(const complex& x, const complex& y) { return ((x.real() != y.real()) || (x.imag() != y.imag())); } + inline bool operator!=(const complex& x, const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& y) { return ((x.real() != y) || (x.imag() != BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(0))); } + inline bool operator!=(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& x, const complex& y) { return ((x != y.real()) || (y.imag() != BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(0))); } + + // ISO/IEC 14882:2011, Section 26.4.8, transcendentals. + inline complex sqrt(const complex& x) + { + using std::fabs; + using std::sqrt; + + // Compute sqrt(x) for x in C: + // sqrt(x) = (s , xi / 2s) : for xr > 0, + // (|xi| / 2s, +-s) : for xr < 0, + // (sqrt(xi), sqrt(xi) : for xr = 0, + // where s = sqrt{ [ |xr| + sqrt(xr^2 + xi^2) ] / 2 }, + // and the +- sign is the same as the sign of xi. + + if(x.real() > 0) + { + const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE s = sqrt((fabs(x.real()) + std::abs(x)) / 2); + + return complex(s, x.imag() / (s * 2)); + } + else if(x.real() < 0) + { + const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE s = sqrt((fabs(x.real()) + std::abs(x)) / 2); + + const bool imag_is_neg = (x.imag() < 0); + + return complex(fabs(x.imag()) / (s * 2), (imag_is_neg ? -s : s)); + } + else + { + const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sqrt_xi_half = sqrt(x.imag() / 2); + + return complex(sqrt_xi_half, sqrt_xi_half); + } + } + + inline complex sin(const complex& x) + { + using std::sin; + using std::cos; + using std::exp; + + const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sin_x = sin (x.real()); + const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cos_x = cos (x.real()); + const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_yp = exp (x.imag()); + const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_ym = BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) / exp_yp; + const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sinh_y = (exp_yp - exp_ym) / 2; + const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cosh_y = (exp_yp + exp_ym) / 2; + + return complex(sin_x * cosh_y, cos_x * sinh_y); + } + + inline complex cos(const complex& x) + { + using std::sin; + using std::cos; + using std::exp; + + const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sin_x = sin (x.real()); + const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cos_x = cos (x.real()); + const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_yp = exp (x.imag()); + const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_ym = BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) / exp_yp; + const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sinh_y = (exp_yp - exp_ym) / 2; + const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cosh_y = (exp_yp + exp_ym) / 2; + + return complex(cos_x * cosh_y, -(sin_x * sinh_y)); + } + + inline complex tan(const complex& x) + { + using std::sin; + using std::cos; + using std::exp; + + const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sin_x = sin (x.real()); + const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cos_x = cos (x.real()); + const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_yp = exp (x.imag()); + const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_ym = BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) / exp_yp; + const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sinh_y = (exp_yp - exp_ym) / 2; + const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cosh_y = (exp_yp + exp_ym) / 2; + + return ( complex(sin_x * cosh_y, cos_x * sinh_y) + / complex(cos_x * cosh_y, -sin_x * sinh_y)); + } + + inline complex asin(const complex& x) + { + return -boost::math::cstdfloat::detail::multiply_by_i(std::log(boost::math::cstdfloat::detail::multiply_by_i(x) + std::sqrt(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) - (x * x)))); + } + + inline complex acos(const complex& x) + { + return boost::math::constants::half_pi() - std::asin(x); + } + + inline complex atan(const complex& x) + { + const complex izz = boost::math::cstdfloat::detail::multiply_by_i(x); + + return boost::math::cstdfloat::detail::multiply_by_i(std::log(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) - izz) - std::log(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) + izz)) / 2; + } + + inline complex exp(const complex& x) + { + using std::exp; + + return std::polar(exp(x.real()), x.imag()); + } + + inline complex log(const complex& x) + { + using std::atan2; + using std::log; + + const bool re_isneg = (x.real() < 0); + const bool re_isnan = (x.real() != x.real()); + const bool re_isinf = ((!re_isneg) ? bool(+x.real() > (std::numeric_limits::max)()) + : bool(-x.real() > (std::numeric_limits::max)())); + + const bool im_isneg = (x.imag() < 0); + const bool im_isnan = (x.imag() != x.imag()); + const bool im_isinf = ((!im_isneg) ? bool(+x.imag() > (std::numeric_limits::max)()) + : bool(-x.imag() > (std::numeric_limits::max)())); + + if(re_isnan || im_isnan) { return x; } + + if(re_isinf || im_isinf) + { + return complex(std::numeric_limits::infinity(), + BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(0.0)); + } + + const bool re_iszero = ((re_isneg || (x.real() > 0)) == false); + + if(re_iszero) + { + const bool im_iszero = ((im_isneg || (x.imag() > 0)) == false); + + if(im_iszero) + { + return std::complex + ( + -std::numeric_limits::infinity(), + BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(0.0) + ); + } + else + { + if(im_isneg == false) + { + return std::complex + ( + log(x.imag()), + boost::math::constants::half_pi() + ); + } + else + { + return std::complex + ( + log(-x.imag()), + -boost::math::constants::half_pi() + ); + } + } + } + else + { + return complex(log(std::norm(x)) / 2, atan2(x.imag(), x.real())); + } + } + + inline complex log10(const complex& x) + { + return std::log(x) / boost::math::constants::ln_ten(); + } + + inline complex pow(const complex& x, + int p) + { + const bool re_isneg = (x.real() < 0); + const bool re_isnan = (x.real() != x.real()); + const bool re_isinf = ((!re_isneg) ? bool(+x.real() > (std::numeric_limits::max)()) + : bool(-x.real() > (std::numeric_limits::max)())); + + const bool im_isneg = (x.imag() < 0); + const bool im_isnan = (x.imag() != x.imag()); + const bool im_isinf = ((!im_isneg) ? bool(+x.imag() > (std::numeric_limits::max)()) + : bool(-x.imag() > (std::numeric_limits::max)())); + + if(re_isnan || im_isnan) { return x; } + + if(re_isinf || im_isinf) + { + return complex(std::numeric_limits::quiet_NaN(), + std::numeric_limits::quiet_NaN()); + } + + if(p < 0) + { + if(std::abs(x) < (std::numeric_limits::min)()) + { + return complex(std::numeric_limits::infinity(), + std::numeric_limits::infinity()); + } + else + { + return BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) / std::pow(x, -p); + } + } + + if(p == 0) + { + return complex(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1)); + } + else + { + if(p == 1) { return x; } + + if(std::abs(x) > (std::numeric_limits::max)()) + { + const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE re = (re_isneg ? -std::numeric_limits::infinity() + : +std::numeric_limits::infinity()); + + const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE im = (im_isneg ? -std::numeric_limits::infinity() + : +std::numeric_limits::infinity()); + + return complex(re, im); + } + + if (p == 2) { return (x * x); } + else if(p == 3) { return ((x * x) * x); } + else if(p == 4) { const complex x2 = (x * x); return (x2 * x2); } + else + { + // The variable xn stores the binary powers of x. + complex result(((p % 2) != 0) ? x : complex(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1))); + complex xn (x); + + int p2 = p; + + while((p2 /= 2) != 0) + { + // Square xn for each binary power. + xn *= xn; + + const bool has_binary_power = ((p2 % 2) != 0); + + if(has_binary_power) + { + // Multiply the result with each binary power contained in the exponent. + result *= xn; + } + } + + return result; + } + } + } + + inline complex pow(const complex& x, + const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& a) + { + const bool x_im_isneg = (x.imag() < 0); + const bool x_im_iszero = ((x_im_isneg || (x.imag() > 0)) == false); + + if(x_im_iszero) + { + using std::pow; + + const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE pxa = pow(x.real(), a); + + return complex(pxa, BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(0)); + } + else + { + return std::exp(a * std::log(x)); + } + } + + inline complex pow(const complex& x, + const complex& a) + { + const bool x_im_isneg = (x.imag() < 0); + const bool x_im_iszero = ((x_im_isneg || (x.imag() > 0)) == false); + + if(x_im_iszero) + { + using std::pow; + + return pow(x.real(), a); + } + else + { + return std::exp(a * std::log(x)); + } + } + + inline complex pow(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& x, + const complex& a) + { + const bool x_isneg = (x < 0); + const bool x_isnan = (x != x); + const bool x_isinf = ((!x_isneg) ? bool(+x > (std::numeric_limits::max)()) + : bool(-x > (std::numeric_limits::max)())); + + const bool a_re_isneg = (a.real() < 0); + const bool a_re_isnan = (a.real() != a.real()); + const bool a_re_isinf = ((!a_re_isneg) ? bool(+a.real() > (std::numeric_limits::max)()) + : bool(-a.real() > (std::numeric_limits::max)())); + + const bool a_im_isneg = (a.imag() < 0); + const bool a_im_isnan = (a.imag() != a.imag()); + const bool a_im_isinf = ((!a_im_isneg) ? bool(+a.imag() > (std::numeric_limits::max)()) + : bool(-a.imag() > (std::numeric_limits::max)())); + + const bool args_is_nan = (x_isnan || a_re_isnan || a_im_isnan); + const bool a_is_finite = (!(a_re_isnan || a_re_isinf || a_im_isnan || a_im_isinf)); + + complex result; + + if(args_is_nan) + { + result = + complex + ( + std::numeric_limits::quiet_NaN(), + std::numeric_limits::quiet_NaN() + ); + } + else if(x_isinf) + { + if(a_is_finite) + { + result = + complex + ( + std::numeric_limits::infinity(), + std::numeric_limits::infinity() + ); + } + else + { + result = + complex + ( + std::numeric_limits::quiet_NaN(), + std::numeric_limits::quiet_NaN() + ); + } + } + else if(x > 0) + { + result = std::exp(a * std::log(x)); + } + else if(x < 0) + { + using std::acos; + using std::log; + + const complex + cpx_lg_x + ( + log(-x), + acos(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(-1)) + ); + + result = std::exp(a * cpx_lg_x); + } + else + { + if(a_is_finite) + { + result = + complex + ( + BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(0), + BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(0) + ); + } + else + { + result = + complex + ( + std::numeric_limits::quiet_NaN(), + std::numeric_limits::quiet_NaN() + ); + } + } + + return result; + } + + inline complex sinh(const complex& x) + { + using std::sin; + using std::cos; + using std::exp; + + const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sin_y = sin (x.imag()); + const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cos_y = cos (x.imag()); + const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_xp = exp (x.real()); + const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_xm = BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) / exp_xp; + const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sinh_x = (exp_xp - exp_xm) / 2; + const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cosh_x = (exp_xp + exp_xm) / 2; + + return complex(cos_y * sinh_x, cosh_x * sin_y); + } + + inline complex cosh(const complex& x) + { + using std::sin; + using std::cos; + using std::exp; + + const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sin_y = sin (x.imag()); + const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cos_y = cos (x.imag()); + const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_xp = exp (x.real()); + const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_xm = BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) / exp_xp; + const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sinh_x = (exp_xp - exp_xm) / 2; + const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cosh_x = (exp_xp + exp_xm) / 2; + + return complex(cos_y * cosh_x, sin_y * sinh_x); + } + + inline complex tanh(const complex& x) + { + const complex ex_plus = std::exp(x); + const complex ex_minus = BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) / ex_plus; + + return (ex_plus - ex_minus) / (ex_plus + ex_minus); + } + + inline complex asinh(const complex& x) + { + return std::log(x + std::sqrt((x * x) + BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1))); + } + + inline complex acosh(const complex& x) + { + const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE my_one(1); + + const complex zp(x.real() + my_one, x.imag()); + const complex zm(x.real() - my_one, x.imag()); + + return std::log(x + (zp * std::sqrt(zm / zp))); + } + + inline complex atanh(const complex& x) + { + return (std::log(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) + x) - std::log(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) - x)) / 2.0; + } + + template + inline std::basic_ostream& operator<<(std::basic_ostream& os, const std::complex& x) + { + std::basic_ostringstream ostr; + + ostr.flags(os.flags()); + ostr.imbue(os.getloc()); + ostr.precision(os.precision()); + + ostr << char_type('(') + << x.real() + << char_type(',') + << x.imag() + << char_type(')'); + + return (os << ostr.str()); + } + + template + inline std::basic_istream& operator>>(std::basic_istream& is, std::complex& x) + { + BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE rx; + BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE ix; + + char_type the_char; + + static_cast(is >> the_char); + + if(the_char == static_cast('(')) + { + static_cast(is >> rx >> the_char); + + if(the_char == static_cast(',')) + { + static_cast(is >> ix >> the_char); + + if(the_char == static_cast(')')) + { + x = complex(rx, ix); + } + else + { + is.setstate(ios_base::failbit); + } + } + else if(the_char == static_cast(')')) + { + x = rx; + } + else + { + is.setstate(ios_base::failbit); + } + } + else + { + static_cast(is.putback(the_char)); + + static_cast(is >> rx); + + x = rx; + } + + return is; + } + } // namespace std + +#endif // BOOST_MATH_CSTDFLOAT_COMPLEX_STD_2014_02_15_HPP_ diff --git a/libcxx/src/third-party/boost/math/cstdfloat/cstdfloat_iostream.hpp b/libcxx/src/third-party/boost/math/cstdfloat/cstdfloat_iostream.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/cstdfloat/cstdfloat_iostream.hpp @@ -0,0 +1,775 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2014. +// Copyright John Maddock 2014. +// Copyright Paul Bristow 2014. +// 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) +// + +// Implement quadruple-precision I/O stream operations. + +#ifndef BOOST_MATH_CSTDFLOAT_IOSTREAM_2014_02_15_HPP_ + #define BOOST_MATH_CSTDFLOAT_IOSTREAM_2014_02_15_HPP_ + + #include + #include + #include + + #if defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_CMATH) + #error You can not use with BOOST_CSTDFLOAT_NO_LIBQUADMATH_CMATH defined. + #endif + + #if defined(BOOST_CSTDFLOAT_HAS_INTERNAL_FLOAT128_T) && defined(BOOST_MATH_USE_FLOAT128) && !defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT) + + #include + #include + #include + #include + #include + #include + #include + #include + #include + +// #if (0) + #if defined(__GNUC__) + + // Forward declarations of quadruple-precision string functions. + extern "C" int quadmath_snprintf(char *str, size_t size, const char *format, ...) BOOST_MATH_NOTHROW; + extern "C" boost::math::cstdfloat::detail::float_internal128_t strtoflt128(const char*, char **) BOOST_MATH_NOTHROW; + + namespace std + { + template + inline std::basic_ostream& operator<<(std::basic_ostream& os, const boost::math::cstdfloat::detail::float_internal128_t& x) + { + std::basic_ostringstream ostr; + ostr.flags(os.flags()); + ostr.imbue(os.getloc()); + ostr.precision(os.precision()); + + char my_buffer[64U]; + + const int my_prec = static_cast(os.precision()); + const int my_digits = ((my_prec == 0) ? 36 : my_prec); + + const std::ios_base::fmtflags my_flags = os.flags(); + + char my_format_string[8U]; + + std::size_t my_format_string_index = 0U; + + my_format_string[my_format_string_index] = '%'; + ++my_format_string_index; + + if(my_flags & std::ios_base::showpos) { my_format_string[my_format_string_index] = '+'; ++my_format_string_index; } + if(my_flags & std::ios_base::showpoint) { my_format_string[my_format_string_index] = '#'; ++my_format_string_index; } + + my_format_string[my_format_string_index + 0U] = '.'; + my_format_string[my_format_string_index + 1U] = '*'; + my_format_string[my_format_string_index + 2U] = 'Q'; + + my_format_string_index += 3U; + + char the_notation_char; + + if (my_flags & std::ios_base::scientific) { the_notation_char = 'e'; } + else if(my_flags & std::ios_base::fixed) { the_notation_char = 'f'; } + else { the_notation_char = 'g'; } + + my_format_string[my_format_string_index + 0U] = the_notation_char; + my_format_string[my_format_string_index + 1U] = 0; + + const int v = ::quadmath_snprintf(my_buffer, + static_cast(sizeof(my_buffer)), + my_format_string, + my_digits, + x); + + if(v < 0) { BOOST_MATH_THROW_EXCEPTION(std::runtime_error("Formatting of boost::float128_t failed internally in quadmath_snprintf().")); } + + if(v >= static_cast(sizeof(my_buffer) - 1U)) + { + // Evidently there is a really long floating-point string here, + // such as a small decimal representation in non-scientific notation. + // So we have to use dynamic memory allocation for the output + // string buffer. + + char* my_buffer2 = static_cast(0U); + +#ifndef BOOST_NO_EXCEPTIONS + try + { +#endif + my_buffer2 = new char[v + 3]; +#ifndef BOOST_NO_EXCEPTIONS + } + catch(const std::bad_alloc&) + { + BOOST_MATH_THROW_EXCEPTION(std::runtime_error("Formatting of boost::float128_t failed while allocating memory.")); + } +#endif + const int v2 = ::quadmath_snprintf(my_buffer2, + v + 3, + my_format_string, + my_digits, + x); + + if(v2 >= v + 3) + { + BOOST_MATH_THROW_EXCEPTION(std::runtime_error("Formatting of boost::float128_t failed.")); + } + + static_cast(ostr << my_buffer2); + + delete [] my_buffer2; + } + else + { + static_cast(ostr << my_buffer); + } + + return (os << ostr.str()); + } + + template + inline std::basic_istream& operator>>(std::basic_istream& is, boost::math::cstdfloat::detail::float_internal128_t& x) + { + std::string str; + + static_cast(is >> str); + + char* p_end; + + x = strtoflt128(str.c_str(), &p_end); + + if(static_cast(p_end - str.c_str()) != static_cast(str.length())) + { + for(std::string::const_reverse_iterator it = str.rbegin(); it != str.rend(); ++it) + { + static_cast(is.putback(*it)); + } + + is.setstate(ios_base::failbit); + + BOOST_MATH_THROW_EXCEPTION(std::runtime_error("Unable to interpret input string as a boost::float128_t")); + } + + return is; + } + } + +// #elif defined(__GNUC__) + #elif defined(__INTEL_COMPILER) + + // The section for I/O stream support for the ICC compiler is particularly + // long, because these functions must be painstakingly synthesized from + // manually-written routines (ICC does not support I/O stream operations + // for its _Quad type). + + // The following string-extraction routines are based on the methodology + // used in Boost.Multiprecision by John Maddock and Christopher Kormanyos. + // This methodology has been slightly modified here for boost::float128_t. + + #include + #include + + namespace boost { namespace math { namespace cstdfloat { namespace detail { + + template + void format_float_string(string_type& str, + int my_exp, + int digits, + const std::ios_base::fmtflags f, + const bool iszero) + { + typedef typename string_type::size_type size_type; + + const bool scientific = ((f & std::ios_base::scientific) == std::ios_base::scientific); + const bool fixed = ((f & std::ios_base::fixed) == std::ios_base::fixed); + const bool showpoint = ((f & std::ios_base::showpoint) == std::ios_base::showpoint); + const bool showpos = ((f & std::ios_base::showpos) == std::ios_base::showpos); + + const bool b_neg = ((str.size() != 0U) && (str[0] == '-')); + + if(b_neg) + { + str.erase(0, 1); + } + + if(digits == 0) + { + digits = static_cast((std::max)(str.size(), size_type(16))); + } + + if(iszero || str.empty() || (str.find_first_not_of('0') == string_type::npos)) + { + // We will be printing zero, even though the value might not + // actually be zero (it just may have been rounded to zero). + str = "0"; + + if(scientific || fixed) + { + str.append(1, '.'); + str.append(size_type(digits), '0'); + + if(scientific) + { + str.append("e+00"); + } + } + else + { + if(showpoint) + { + str.append(1, '.'); + if(digits > 1) + { + str.append(size_type(digits - 1), '0'); + } + } + } + + if(b_neg) + { + str.insert(0U, 1U, '-'); + } + else if(showpos) + { + str.insert(0U, 1U, '+'); + } + + return; + } + + if(!fixed && !scientific && !showpoint) + { + // Suppress trailing zeros. + typename string_type::iterator pos = str.end(); + + while(pos != str.begin() && *--pos == '0') { ; } + + if(pos != str.end()) + { + ++pos; + } + + str.erase(pos, str.end()); + + if(str.empty()) + { + str = '0'; + } + } + else if(!fixed || (my_exp >= 0)) + { + // Pad out the end with zero's if we need to. + + int chars = static_cast(str.size()); + chars = digits - chars; + + if(scientific) + { + ++chars; + } + + if(chars > 0) + { + str.append(static_cast(chars), '0'); + } + } + + if(fixed || (!scientific && (my_exp >= -4) && (my_exp < digits))) + { + if((1 + my_exp) > static_cast(str.size())) + { + // Just pad out the end with zeros. + str.append(static_cast((1 + my_exp) - static_cast(str.size())), '0'); + + if(showpoint || fixed) + { + str.append("."); + } + } + else if(my_exp + 1 < static_cast(str.size())) + { + if(my_exp < 0) + { + str.insert(0U, static_cast(-1 - my_exp), '0'); + str.insert(0U, "0."); + } + else + { + // Insert the decimal point: + str.insert(static_cast(my_exp + 1), 1, '.'); + } + } + else if(showpoint || fixed) // we have exactly the digits we require to left of the point + { + str += "."; + } + + if(fixed) + { + // We may need to add trailing zeros. + int l = static_cast(str.find('.') + 1U); + l = digits - (static_cast(str.size()) - l); + + if(l > 0) + { + str.append(size_type(l), '0'); + } + } + } + else + { + // Scientific format: + if(showpoint || (str.size() > 1)) + { + str.insert(1U, 1U, '.'); + } + + str.append(1U, 'e'); + + string_type e = std::to_string(std::abs(my_exp)); + + if(e.size() < 2U) + { + e.insert(0U, 2U - e.size(), '0'); + } + + if(my_exp < 0) + { + e.insert(0U, 1U, '-'); + } + else + { + e.insert(0U, 1U, '+'); + } + + str.append(e); + } + + if(b_neg) + { + str.insert(0U, 1U, '-'); + } + else if(showpos) + { + str.insert(0U, 1U, '+'); + } + } + + template inline void eval_convert_to(type_a* pa, const float_type& cb) { *pa = static_cast(cb); } + template inline void eval_add (float_type& b, const type_a& a) { b += a; } + template inline void eval_subtract (float_type& b, const type_a& a) { b -= a; } + template inline void eval_multiply (float_type& b, const type_a& a) { b *= a; } + template inline void eval_multiply (float_type& b, const float_type& cb, const float_type& cb2) { b = (cb * cb2); } + template inline void eval_divide (float_type& b, const type_a& a) { b /= a; } + template inline void eval_log10 (float_type& b, const float_type& cb) { b = std::log10(cb); } + template inline void eval_floor (float_type& b, const float_type& cb) { b = std::floor(cb); } + + inline void round_string_up_at(std::string& s, int pos, int& expon) + { + // This subroutine rounds up a string representation of a + // number at the given position pos. + + if(pos < 0) + { + s.insert(0U, 1U, '1'); + s.erase(s.size() - 1U); + ++expon; + } + else if(s[pos] == '9') + { + s[pos] = '0'; + round_string_up_at(s, pos - 1, expon); + } + else + { + if((pos == 0) && (s[pos] == '0') && (s.size() == 1)) + { + ++expon; + } + + ++s[pos]; + } + } + + template + std::string convert_to_string(float_type& x, + std::streamsize digits, + const std::ios_base::fmtflags f) + { + const bool isneg = (x < 0); + const bool iszero = ((!isneg) ? bool(+x < (std::numeric_limits::min)()) + : bool(-x < (std::numeric_limits::min)())); + const bool isnan = (x != x); + const bool isinf = ((!isneg) ? bool(+x > (std::numeric_limits::max)()) + : bool(-x > (std::numeric_limits::max)())); + + int expon = 0; + + if(digits <= 0) { digits = std::numeric_limits::max_digits10; } + + const int org_digits = static_cast(digits); + + std::string result; + + if(iszero) + { + result = "0"; + } + else if(isinf) + { + if(x < 0) + { + return "-inf"; + } + else + { + return ((f & std::ios_base::showpos) == std::ios_base::showpos) ? "+inf" : "inf"; + } + } + else if(isnan) + { + return "nan"; + } + else + { + // Start by figuring out the base-10 exponent. + if(isneg) { x = -x; } + + float_type t; + float_type ten = 10; + + eval_log10(t, x); + eval_floor(t, t); + eval_convert_to(&expon, t); + + if(-expon > std::numeric_limits::max_exponent10 - 3) + { + int e = -expon / 2; + + const float_type t2 = boost::math::cstdfloat::detail::pown(ten, e); + + eval_multiply(t, t2, x); + eval_multiply(t, t2); + + if((expon & 1) != 0) + { + eval_multiply(t, ten); + } + } + else + { + t = boost::math::cstdfloat::detail::pown(ten, -expon); + eval_multiply(t, x); + } + + // Make sure that the value lies between [1, 10), and adjust if not. + if(t < 1) + { + eval_multiply(t, 10); + + --expon; + } + else if(t >= 10) + { + eval_divide(t, 10); + + ++expon; + } + + float_type digit; + int cdigit; + + // Adjust the number of digits required based on formatting options. + if(((f & std::ios_base::fixed) == std::ios_base::fixed) && (expon != -1)) + { + digits += (expon + 1); + } + + if((f & std::ios_base::scientific) == std::ios_base::scientific) + { + ++digits; + } + + // Extract the base-10 digits one at a time. + for(int i = 0; i < digits; ++i) + { + eval_floor(digit, t); + eval_convert_to(&cdigit, digit); + + result += static_cast('0' + cdigit); + + eval_subtract(t, digit); + eval_multiply(t, ten); + } + + // Possibly round the result. + if(digits >= 0) + { + eval_floor(digit, t); + eval_convert_to(&cdigit, digit); + eval_subtract(t, digit); + + if((cdigit == 5) && (t == 0)) + { + // Use simple bankers rounding. + + if((static_cast(*result.rbegin() - '0') & 1) != 0) + { + round_string_up_at(result, static_cast(result.size() - 1U), expon); + } + } + else if(cdigit >= 5) + { + round_string_up_at(result, static_cast(result.size() - 1), expon); + } + } + } + + while((result.size() > static_cast(digits)) && result.size()) + { + // We may get here as a result of rounding. + + if(result.size() > 1U) + { + result.erase(result.size() - 1U); + } + else + { + if(expon > 0) + { + --expon; // so we put less padding in the result. + } + else + { + ++expon; + } + + ++digits; + } + } + + if(isneg) + { + result.insert(0U, 1U, '-'); + } + + format_float_string(result, expon, org_digits, f, iszero); + + return result; + } + + template + bool convert_from_string(float_type& value, const char* p) + { + value = 0; + + if((p == static_cast(0U)) || (*p == static_cast(0))) + { + return; + } + + bool is_neg = false; + bool is_neg_expon = false; + + constexpr int ten = 10; + + int expon = 0; + int digits_seen = 0; + + constexpr int max_digits = std::numeric_limits::max_digits10 + 1; + + if(*p == static_cast('+')) + { + ++p; + } + else if(*p == static_cast('-')) + { + is_neg = true; + ++p; + } + + const bool isnan = ((std::strcmp(p, "nan") == 0) || (std::strcmp(p, "NaN") == 0) || (std::strcmp(p, "NAN") == 0)); + + if(isnan) + { + eval_divide(value, 0); + + if(is_neg) + { + value = -value; + } + + return true; + } + + const bool isinf = ((std::strcmp(p, "inf") == 0) || (std::strcmp(p, "Inf") == 0) || (std::strcmp(p, "INF") == 0)); + + if(isinf) + { + value = 1; + eval_divide(value, 0); + + if(is_neg) + { + value = -value; + } + + return true; + } + + // Grab all the leading digits before the decimal point. + while(std::isdigit(*p)) + { + eval_multiply(value, ten); + eval_add(value, static_cast(*p - '0')); + ++p; + ++digits_seen; + } + + if(*p == static_cast('.')) + { + // Grab everything after the point, stop when we've seen + // enough digits, even if there are actually more available. + + ++p; + + while(std::isdigit(*p)) + { + eval_multiply(value, ten); + eval_add(value, static_cast(*p - '0')); + ++p; + --expon; + + if(++digits_seen > max_digits) + { + break; + } + } + + while(std::isdigit(*p)) + { + ++p; + } + } + + // Parse the exponent. + if((*p == static_cast('e')) || (*p == static_cast('E'))) + { + ++p; + + if(*p == static_cast('+')) + { + ++p; + } + else if(*p == static_cast('-')) + { + is_neg_expon = true; + ++p; + } + + int e2 = 0; + + while(std::isdigit(*p)) + { + e2 *= 10; + e2 += (*p - '0'); + ++p; + } + + if(is_neg_expon) + { + e2 = -e2; + } + + expon += e2; + } + + if(expon) + { + // Scale by 10^expon. Note that 10^expon can be outside the range + // of our number type, even though the result is within range. + // If that looks likely, then split the calculation in two parts. + float_type t; + t = ten; + + if(expon > (std::numeric_limits::min_exponent10 + 2)) + { + t = boost::math::cstdfloat::detail::pown(t, expon); + eval_multiply(value, t); + } + else + { + t = boost::math::cstdfloat::detail::pown(t, (expon + digits_seen + 1)); + eval_multiply(value, t); + t = ten; + t = boost::math::cstdfloat::detail::pown(t, (-digits_seen - 1)); + eval_multiply(value, t); + } + } + + if(is_neg) + { + value = -value; + } + + return (*p == static_cast(0)); + } + } } } } // boost::math::cstdfloat::detail + + namespace std + { + template + inline std::basic_ostream& operator<<(std::basic_ostream& os, const boost::math::cstdfloat::detail::float_internal128_t& x) + { + boost::math::cstdfloat::detail::float_internal128_t non_const_x = x; + + const std::string str = boost::math::cstdfloat::detail::convert_to_string(non_const_x, + os.precision(), + os.flags()); + + std::basic_ostringstream ostr; + ostr.flags(os.flags()); + ostr.imbue(os.getloc()); + ostr.precision(os.precision()); + + static_cast(ostr << str); + + return (os << ostr.str()); + } + + template + inline std::basic_istream& operator>>(std::basic_istream& is, boost::math::cstdfloat::detail::float_internal128_t& x) + { + std::string str; + + static_cast(is >> str); + + const bool conversion_is_ok = boost::math::cstdfloat::detail::convert_from_string(x, str.c_str()); + + if(false == conversion_is_ok) + { + for(std::string::const_reverse_iterator it = str.rbegin(); it != str.rend(); ++it) + { + static_cast(is.putback(*it)); + } + + is.setstate(ios_base::failbit); + + BOOST_MATH_THROW_EXCEPTION(std::runtime_error("Unable to interpret input string as a boost::float128_t")); + } + + return is; + } + } + + #endif // Use __GNUC__ or __INTEL_COMPILER libquadmath + + #endif // Not BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT (i.e., the user would like to have libquadmath support) + +#endif // BOOST_MATH_CSTDFLOAT_IOSTREAM_2014_02_15_HPP_ diff --git a/libcxx/src/third-party/boost/math/cstdfloat/cstdfloat_limits.hpp b/libcxx/src/third-party/boost/math/cstdfloat/cstdfloat_limits.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/cstdfloat/cstdfloat_limits.hpp @@ -0,0 +1,87 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2014. +// Copyright John Maddock 2014. +// Copyright Paul Bristow 2014. +// 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) +// + +// Implement quadruple-precision std::numeric_limits<> support. + +#ifndef BOOST_MATH_CSTDFLOAT_LIMITS_2014_01_09_HPP_ + #define BOOST_MATH_CSTDFLOAT_LIMITS_2014_01_09_HPP_ + + #include + +#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 diagnostic ignored work :( +// +#pragma GCC system_header +#endif + + #if defined(BOOST_CSTDFLOAT_HAS_INTERNAL_FLOAT128_T) && defined(BOOST_MATH_USE_FLOAT128) && !defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT) + + #include + #include + + // Define the name of the global quadruple-precision function to be used for + // calculating quiet_NaN() in the specialization of std::numeric_limits<>. + #if defined(__INTEL_COMPILER) + #define BOOST_CSTDFLOAT_FLOAT128_SQRT __sqrtq + #elif defined(__GNUC__) + #define BOOST_CSTDFLOAT_FLOAT128_SQRT sqrtq + #endif + + // Forward declaration of the quadruple-precision square root function. + extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SQRT(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; + + namespace std + { + template<> + class numeric_limits + { + public: + static constexpr bool is_specialized = true; + static boost::math::cstdfloat::detail::float_internal128_t (min) () noexcept { return BOOST_CSTDFLOAT_FLOAT128_MIN; } + static boost::math::cstdfloat::detail::float_internal128_t (max) () noexcept { return BOOST_CSTDFLOAT_FLOAT128_MAX; } + static boost::math::cstdfloat::detail::float_internal128_t lowest() noexcept { return -(max)(); } + static constexpr int digits = 113; + static constexpr int digits10 = 33; + static constexpr int max_digits10 = 36; + static constexpr bool is_signed = true; + static constexpr bool is_integer = false; + static constexpr bool is_exact = false; + static constexpr int radix = 2; + static boost::math::cstdfloat::detail::float_internal128_t epsilon () { return BOOST_CSTDFLOAT_FLOAT128_EPS; } + static boost::math::cstdfloat::detail::float_internal128_t round_error() { return BOOST_FLOAT128_C(0.5); } + static constexpr int min_exponent = -16381; + static constexpr int min_exponent10 = static_cast((min_exponent * 301L) / 1000L); + static constexpr int max_exponent = +16384; + static constexpr int max_exponent10 = static_cast((max_exponent * 301L) / 1000L); + static constexpr bool has_infinity = true; + static constexpr bool has_quiet_NaN = true; + static constexpr bool has_signaling_NaN = false; + static constexpr float_denorm_style has_denorm = denorm_present; + static constexpr bool has_denorm_loss = false; + static boost::math::cstdfloat::detail::float_internal128_t infinity () { return BOOST_FLOAT128_C(1.0) / BOOST_FLOAT128_C(0.0); } + static boost::math::cstdfloat::detail::float_internal128_t quiet_NaN () { return -(::BOOST_CSTDFLOAT_FLOAT128_SQRT(BOOST_FLOAT128_C(-1.0))); } + static boost::math::cstdfloat::detail::float_internal128_t signaling_NaN() { return BOOST_FLOAT128_C(0.0); } + static boost::math::cstdfloat::detail::float_internal128_t denorm_min () { return BOOST_CSTDFLOAT_FLOAT128_DENORM_MIN; } + static constexpr bool is_iec559 = true; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = false; + static constexpr bool traps = false; + static constexpr bool tinyness_before = false; + static constexpr float_round_style round_style = round_to_nearest; + }; + } // namespace std + + #endif // Not BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT (i.e., the user would like to have libquadmath support) + +#endif // BOOST_MATH_CSTDFLOAT_LIMITS_2014_01_09_HPP_ + diff --git a/libcxx/src/third-party/boost/math/cstdfloat/cstdfloat_types.hpp b/libcxx/src/third-party/boost/math/cstdfloat/cstdfloat_types.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/cstdfloat/cstdfloat_types.hpp @@ -0,0 +1,441 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2014. +// Copyright John Maddock 2014. +// Copyright Paul Bristow 2014. +// 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) +// + +// Implement the types for floating-point typedefs having specified widths. + +#ifndef BOOST_MATH_CSTDFLOAT_TYPES_2014_01_09_HPP_ + #define BOOST_MATH_CSTDFLOAT_TYPES_2014_01_09_HPP_ + + #include + #include + #include + + // This is the beginning of the preamble. + + // In this preamble, the preprocessor is used to query certain + // preprocessor definitions from . Based on the results + // of these queries, an attempt is made to automatically detect + // the presence of built-in floating-point types having specified + // widths. These are *thought* to be conformant with IEEE-754, + // whereby an unequivocal test based on std::numeric_limits<> + // follows below. + + // In addition, various macros that are used for initializing + // floating-point literal values having specified widths and + // some basic min/max values are defined. + + // First, we will pre-load certain preprocessor definitions + // with a dummy value. + + #define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 0 + + #define BOOST_CSTDFLOAT_HAS_FLOAT16_NATIVE_TYPE 0 + #define BOOST_CSTDFLOAT_HAS_FLOAT32_NATIVE_TYPE 0 + #define BOOST_CSTDFLOAT_HAS_FLOAT64_NATIVE_TYPE 0 + #define BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE 0 + #define BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE 0 + + // Ensure that the compiler has a radix-2 floating-point representation. + #if (!defined(FLT_RADIX) || ((defined(FLT_RADIX) && (FLT_RADIX != 2)))) + #error The compiler does not support any radix-2 floating-point types required for . + #endif + + // Check if built-in float is equivalent to float16_t, float32_t, float64_t, float80_t, or float128_t. + #if(defined(FLT_MANT_DIG) && defined(FLT_MAX_EXP)) + #if ((FLT_MANT_DIG == 11) && (FLT_MAX_EXP == 16) && (BOOST_CSTDFLOAT_HAS_FLOAT16_NATIVE_TYPE == 0)) + #define BOOST_CSTDFLOAT_FLOAT16_NATIVE_TYPE float + #undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH + #define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 16 + #undef BOOST_CSTDFLOAT_HAS_FLOAT16_NATIVE_TYPE + #define BOOST_CSTDFLOAT_HAS_FLOAT16_NATIVE_TYPE 1 + #define BOOST_FLOAT16_C(x) (x ## F) + #define BOOST_CSTDFLOAT_FLOAT_16_MIN FLT_MIN + #define BOOST_CSTDFLOAT_FLOAT_16_MAX FLT_MAX + #elif((FLT_MANT_DIG == 24) && (FLT_MAX_EXP == 128) && (BOOST_CSTDFLOAT_HAS_FLOAT32_NATIVE_TYPE == 0)) + #define BOOST_CSTDFLOAT_FLOAT32_NATIVE_TYPE float + #undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH + #define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 32 + #undef BOOST_CSTDFLOAT_HAS_FLOAT32_NATIVE_TYPE + #define BOOST_CSTDFLOAT_HAS_FLOAT32_NATIVE_TYPE 1 + #define BOOST_FLOAT32_C(x) (x ## F) + #define BOOST_CSTDFLOAT_FLOAT_32_MIN FLT_MIN + #define BOOST_CSTDFLOAT_FLOAT_32_MAX FLT_MAX + #elif((FLT_MANT_DIG == 53) && (FLT_MAX_EXP == 1024) && (BOOST_CSTDFLOAT_HAS_FLOAT64_NATIVE_TYPE == 0)) + #define BOOST_CSTDFLOAT_FLOAT64_NATIVE_TYPE float + #undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH + #define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 64 + #undef BOOST_CSTDFLOAT_HAS_FLOAT64_NATIVE_TYPE + #define BOOST_CSTDFLOAT_HAS_FLOAT64_NATIVE_TYPE 1 + #define BOOST_FLOAT64_C(x) (x ## F) + #define BOOST_CSTDFLOAT_FLOAT_64_MIN FLT_MIN + #define BOOST_CSTDFLOAT_FLOAT_64_MAX FLT_MAX + #elif((FLT_MANT_DIG == 64) && (FLT_MAX_EXP == 16384) && (BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE == 0)) + #define BOOST_CSTDFLOAT_FLOAT80_NATIVE_TYPE float + #undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH + #define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 80 + #undef BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE + #define BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE 1 + #define BOOST_FLOAT80_C(x) (x ## F) + #define BOOST_CSTDFLOAT_FLOAT_80_MIN FLT_MIN + #define BOOST_CSTDFLOAT_FLOAT_80_MAX FLT_MAX + #elif((FLT_MANT_DIG == 113) && (FLT_MAX_EXP == 16384) && (BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE == 0)) + #define BOOST_CSTDFLOAT_FLOAT128_NATIVE_TYPE float + #undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH + #define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 128 + #undef BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE + #define BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE 1 + #define BOOST_FLOAT128_C(x) (x ## F) + #define BOOST_CSTDFLOAT_FLOAT_128_MIN FLT_MIN + #define BOOST_CSTDFLOAT_FLOAT_128_MAX FLT_MAX + #endif + #endif + + // Check if built-in double is equivalent to float16_t, float32_t, float64_t, float80_t, or float128_t. + #if(defined(DBL_MANT_DIG) && defined(DBL_MAX_EXP)) + #if ((DBL_MANT_DIG == 11) && (DBL_MAX_EXP == 16) && (BOOST_CSTDFLOAT_HAS_FLOAT16_NATIVE_TYPE == 0)) + #define BOOST_CSTDFLOAT_FLOAT16_NATIVE_TYPE double + #undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH + #define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 16 + #undef BOOST_CSTDFLOAT_HAS_FLOAT16_NATIVE_TYPE + #define BOOST_CSTDFLOAT_HAS_FLOAT16_NATIVE_TYPE 1 + #define BOOST_FLOAT16_C(x) (x) + #define BOOST_CSTDFLOAT_FLOAT_16_MIN DBL_MIN + #define BOOST_CSTDFLOAT_FLOAT_16_MAX DBL_MAX + #elif((DBL_MANT_DIG == 24) && (DBL_MAX_EXP == 128) && (BOOST_CSTDFLOAT_HAS_FLOAT32_NATIVE_TYPE == 0)) + #define BOOST_CSTDFLOAT_FLOAT32_NATIVE_TYPE double + #undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH + #define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 32 + #undef BOOST_CSTDFLOAT_HAS_FLOAT32_NATIVE_TYPE + #define BOOST_CSTDFLOAT_HAS_FLOAT32_NATIVE_TYPE 1 + #define BOOST_FLOAT32_C(x) (x) + #define BOOST_CSTDFLOAT_FLOAT_32_MIN DBL_MIN + #define BOOST_CSTDFLOAT_FLOAT_32_MAX DBL_MAX + #elif((DBL_MANT_DIG == 53) && (DBL_MAX_EXP == 1024) && (BOOST_CSTDFLOAT_HAS_FLOAT64_NATIVE_TYPE == 0)) + #define BOOST_CSTDFLOAT_FLOAT64_NATIVE_TYPE double + #undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH + #define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 64 + #undef BOOST_CSTDFLOAT_HAS_FLOAT64_NATIVE_TYPE + #define BOOST_CSTDFLOAT_HAS_FLOAT64_NATIVE_TYPE 1 + #define BOOST_FLOAT64_C(x) (x) + #define BOOST_CSTDFLOAT_FLOAT_64_MIN DBL_MIN + #define BOOST_CSTDFLOAT_FLOAT_64_MAX DBL_MAX + #elif((DBL_MANT_DIG == 64) && (DBL_MAX_EXP == 16384) && (BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE == 0)) + #define BOOST_CSTDFLOAT_FLOAT80_NATIVE_TYPE double + #undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH + #define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 80 + #undef BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE + #define BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE 1 + #define BOOST_FLOAT80_C(x) (x) + #define BOOST_CSTDFLOAT_FLOAT_80_MIN DBL_MIN + #define BOOST_CSTDFLOAT_FLOAT_80_MAX DBL_MAX + #elif((DBL_MANT_DIG == 113) && (DBL_MAX_EXP == 16384) && (BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE == 0)) + #define BOOST_CSTDFLOAT_FLOAT128_NATIVE_TYPE double + #undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH + #define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 128 + #undef BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE + #define BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE 1 + #define BOOST_FLOAT128_C(x) (x) + #define BOOST_CSTDFLOAT_FLOAT_128_MIN DBL_MIN + #define BOOST_CSTDFLOAT_FLOAT_128_MAX DBL_MAX + #endif + #endif + + // Disable check long double capability even if supported by compiler since some math runtime + // implementations are broken for long double. + #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + // Check if built-in long double is equivalent to float16_t, float32_t, float64_t, float80_t, or float128_t. + #if(defined(LDBL_MANT_DIG) && defined(LDBL_MAX_EXP)) + #if ((LDBL_MANT_DIG == 11) && (LDBL_MAX_EXP == 16) && (BOOST_CSTDFLOAT_HAS_FLOAT16_NATIVE_TYPE == 0)) + #define BOOST_CSTDFLOAT_FLOAT16_NATIVE_TYPE long double + #undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH + #define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 16 + #undef BOOST_CSTDFLOAT_HAS_FLOAT16_NATIVE_TYPE + #define BOOST_CSTDFLOAT_HAS_FLOAT16_NATIVE_TYPE 1 + #define BOOST_FLOAT16_C(x) (x ## L) + #define BOOST_CSTDFLOAT_FLOAT_16_MIN LDBL_MIN + #define BOOST_CSTDFLOAT_FLOAT_16_MAX LDBL_MAX + #elif((LDBL_MANT_DIG == 24) && (LDBL_MAX_EXP == 128) && (BOOST_CSTDFLOAT_HAS_FLOAT32_NATIVE_TYPE == 0)) + #define BOOST_CSTDFLOAT_FLOAT32_NATIVE_TYPE long double + #undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH + #define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 32 + #undef BOOST_CSTDFLOAT_HAS_FLOAT32_NATIVE_TYPE + #define BOOST_CSTDFLOAT_HAS_FLOAT32_NATIVE_TYPE 1 + #define BOOST_FLOAT32_C(x) (x ## L) + #define BOOST_CSTDFLOAT_FLOAT_32_MIN LDBL_MIN + #define BOOST_CSTDFLOAT_FLOAT_32_MAX LDBL_MAX + #elif((LDBL_MANT_DIG == 53) && (LDBL_MAX_EXP == 1024) && (BOOST_CSTDFLOAT_HAS_FLOAT64_NATIVE_TYPE == 0)) + #define BOOST_CSTDFLOAT_FLOAT64_NATIVE_TYPE long double + #undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH + #define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 64 + #undef BOOST_CSTDFLOAT_HAS_FLOAT64_NATIVE_TYPE + #define BOOST_CSTDFLOAT_HAS_FLOAT64_NATIVE_TYPE 1 + #define BOOST_FLOAT64_C(x) (x ## L) + #define BOOST_CSTDFLOAT_FLOAT_64_MIN LDBL_MIN + #define BOOST_CSTDFLOAT_FLOAT_64_MAX LDBL_MAX + #elif((LDBL_MANT_DIG == 64) && (LDBL_MAX_EXP == 16384) && (BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE == 0)) + #define BOOST_CSTDFLOAT_FLOAT80_NATIVE_TYPE long double + #undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH + #define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 80 + #undef BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE + #define BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE 1 + #define BOOST_FLOAT80_C(x) (x ## L) + #define BOOST_CSTDFLOAT_FLOAT_80_MIN LDBL_MIN + #define BOOST_CSTDFLOAT_FLOAT_80_MAX LDBL_MAX + #elif((LDBL_MANT_DIG == 113) && (LDBL_MAX_EXP == 16384) && (BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE == 0)) + #define BOOST_CSTDFLOAT_FLOAT128_NATIVE_TYPE long double + #undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH + #define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 128 + #undef BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE + #define BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE 1 + #define BOOST_FLOAT128_C(x) (x ## L) + #define BOOST_CSTDFLOAT_FLOAT_128_MIN LDBL_MIN + #define BOOST_CSTDFLOAT_FLOAT_128_MAX LDBL_MAX + #endif + #endif + #endif + + // Check if quadruple-precision is supported. Here, we are checking + // for the presence of __float128 from GCC's quadmath.h or _Quad + // from ICC's /Qlong-double flag). To query these, we use the + // BOOST_MATH_USE_FLOAT128 pre-processor definition from + // . + + #if (BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE == 0) && defined(BOOST_MATH_USE_FLOAT128) && !defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT) + + // Specify the underlying name of the internal 128-bit floating-point type definition. + namespace boost { namespace math { namespace cstdfloat { namespace detail { + #if defined(__GNUC__) + typedef __float128 float_internal128_t; + #elif defined(__INTEL_COMPILER) + typedef _Quad float_internal128_t; + #else + #error "Sorry, the compiler is neither GCC, nor Intel, I don't know how to configure ." + #endif + } } } } // boost::math::cstdfloat::detail + + #define BOOST_CSTDFLOAT_FLOAT128_NATIVE_TYPE boost::math::cstdfloat::detail::float_internal128_t + #undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH + #define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 128 + #undef BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE + #define BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE 1 + #define BOOST_FLOAT128_C(x) (x ## Q) + #define BOOST_CSTDFLOAT_FLOAT128_MIN 3.36210314311209350626267781732175260e-4932Q + #define BOOST_CSTDFLOAT_FLOAT128_MAX 1.18973149535723176508575932662800702e+4932Q + #define BOOST_CSTDFLOAT_FLOAT128_EPS 1.92592994438723585305597794258492732e-0034Q + #define BOOST_CSTDFLOAT_FLOAT128_DENORM_MIN 6.475175119438025110924438958227646552e-4966Q + + #endif // Not BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT (i.e., the user would like to have libquadmath support) + + // This is the end of the preamble, and also the end of the + // sections providing support for the C++ standard library + // for quadruple-precision. + + // Now we use the results of the queries that have been obtained + // in the preamble (far above) for the final type definitions in + // the namespace boost. + + // Make sure that the compiler has any floating-point type(s) whatsoever. + #if ( (BOOST_CSTDFLOAT_HAS_FLOAT16_NATIVE_TYPE == 0) \ + && (BOOST_CSTDFLOAT_HAS_FLOAT32_NATIVE_TYPE == 0) \ + && (BOOST_CSTDFLOAT_HAS_FLOAT64_NATIVE_TYPE == 0) \ + && (BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE == 0) \ + && (BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE == 0)) + #error The compiler does not support any of the floating-point types required for . + #endif + + // The following section contains the various min/max macros + // for the *leastN and *fastN types. + + #if(BOOST_CSTDFLOAT_HAS_FLOAT16_NATIVE_TYPE == 1) + #define BOOST_FLOAT_FAST16_MIN BOOST_CSTDFLOAT_FLOAT_16_MIN + #define BOOST_FLOAT_LEAST16_MIN BOOST_CSTDFLOAT_FLOAT_16_MIN + #define BOOST_FLOAT_FAST16_MAX BOOST_CSTDFLOAT_FLOAT_16_MAX + #define BOOST_FLOAT_LEAST16_MAX BOOST_CSTDFLOAT_FLOAT_16_MAX + #endif + + #if(BOOST_CSTDFLOAT_HAS_FLOAT32_NATIVE_TYPE == 1) + #define BOOST_FLOAT_FAST32_MIN BOOST_CSTDFLOAT_FLOAT_32_MIN + #define BOOST_FLOAT_LEAST32_MIN BOOST_CSTDFLOAT_FLOAT_32_MIN + #define BOOST_FLOAT_FAST32_MAX BOOST_CSTDFLOAT_FLOAT_32_MAX + #define BOOST_FLOAT_LEAST32_MAX BOOST_CSTDFLOAT_FLOAT_32_MAX + #endif + + #if(BOOST_CSTDFLOAT_HAS_FLOAT64_NATIVE_TYPE == 1) + #define BOOST_FLOAT_FAST64_MIN BOOST_CSTDFLOAT_FLOAT_64_MIN + #define BOOST_FLOAT_LEAST64_MIN BOOST_CSTDFLOAT_FLOAT_64_MIN + #define BOOST_FLOAT_FAST64_MAX BOOST_CSTDFLOAT_FLOAT_64_MAX + #define BOOST_FLOAT_LEAST64_MAX BOOST_CSTDFLOAT_FLOAT_64_MAX + #endif + + #if(BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE == 1) + #define BOOST_FLOAT_FAST80_MIN BOOST_CSTDFLOAT_FLOAT_80_MIN + #define BOOST_FLOAT_LEAST80_MIN BOOST_CSTDFLOAT_FLOAT_80_MIN + #define BOOST_FLOAT_FAST80_MAX BOOST_CSTDFLOAT_FLOAT_80_MAX + #define BOOST_FLOAT_LEAST80_MAX BOOST_CSTDFLOAT_FLOAT_80_MAX + #endif + + #if(BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE == 1) + #define BOOST_CSTDFLOAT_HAS_INTERNAL_FLOAT128_T + + #define BOOST_FLOAT_FAST128_MIN BOOST_CSTDFLOAT_FLOAT_128_MIN + #define BOOST_FLOAT_LEAST128_MIN BOOST_CSTDFLOAT_FLOAT_128_MIN + #define BOOST_FLOAT_FAST128_MAX BOOST_CSTDFLOAT_FLOAT_128_MAX + #define BOOST_FLOAT_LEAST128_MAX BOOST_CSTDFLOAT_FLOAT_128_MAX + #endif + + // The following section contains the various min/max macros + // for the *floatmax types. + + #if (BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH == 16) + #define BOOST_FLOATMAX_C(x) BOOST_FLOAT16_C(x) + #define BOOST_FLOATMAX_MIN BOOST_CSTDFLOAT_FLOAT_16_MIN + #define BOOST_FLOATMAX_MAX BOOST_CSTDFLOAT_FLOAT_16_MAX + #elif(BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH == 32) + #define BOOST_FLOATMAX_C(x) BOOST_FLOAT32_C(x) + #define BOOST_FLOATMAX_MIN BOOST_CSTDFLOAT_FLOAT_32_MIN + #define BOOST_FLOATMAX_MAX BOOST_CSTDFLOAT_FLOAT_32_MAX + #elif(BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH == 64) + #define BOOST_FLOATMAX_C(x) BOOST_FLOAT64_C(x) + #define BOOST_FLOATMAX_MIN BOOST_CSTDFLOAT_FLOAT_64_MIN + #define BOOST_FLOATMAX_MAX BOOST_CSTDFLOAT_FLOAT_64_MAX + #elif(BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH == 80) + #define BOOST_FLOATMAX_C(x) BOOST_FLOAT80_C(x) + #define BOOST_FLOATMAX_MIN BOOST_CSTDFLOAT_FLOAT_80_MIN + #define BOOST_FLOATMAX_MAX BOOST_CSTDFLOAT_FLOAT_80_MAX + #elif(BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH == 128) + #define BOOST_FLOATMAX_C(x) BOOST_FLOAT128_C(x) + #define BOOST_FLOATMAX_MIN BOOST_CSTDFLOAT_FLOAT_128_MIN + #define BOOST_FLOATMAX_MAX BOOST_CSTDFLOAT_FLOAT_128_MAX + #else + #error The maximum available floating-point width for is undefined. + #endif + + // And finally..., we define the floating-point typedefs having + // specified widths. The types are defined in the namespace boost. + + // For simplicity, the least and fast types are type defined identically + // as the corresponding fixed-width type. This behavior may, however, + // be modified when being optimized for a given compiler implementation. + + // In addition, a clear assessment of IEEE-754 conformance is carried out + // using compile-time assertion. + + namespace boost + { + #if(BOOST_CSTDFLOAT_HAS_FLOAT16_NATIVE_TYPE == 1) + typedef BOOST_CSTDFLOAT_FLOAT16_NATIVE_TYPE float16_t; + typedef boost::float16_t float_fast16_t; + typedef boost::float16_t float_least16_t; + + static_assert(std::numeric_limits::is_iec559 == true, "boost::float16_t has been detected in , but verification with std::numeric_limits fails"); + static_assert(std::numeric_limits::radix == 2, "boost::float16_t has been detected in , but verification with std::numeric_limits fails"); + static_assert(std::numeric_limits::digits == 11, "boost::float16_t has been detected in , but verification with std::numeric_limits fails"); + static_assert(std::numeric_limits::max_exponent == 16, "boost::float16_t has been detected in , but verification with std::numeric_limits fails"); + + #undef BOOST_CSTDFLOAT_FLOAT_16_MIN + #undef BOOST_CSTDFLOAT_FLOAT_16_MAX + #endif + + #if(BOOST_CSTDFLOAT_HAS_FLOAT32_NATIVE_TYPE == 1) + typedef BOOST_CSTDFLOAT_FLOAT32_NATIVE_TYPE float32_t; + typedef boost::float32_t float_fast32_t; + typedef boost::float32_t float_least32_t; + + static_assert(std::numeric_limits::is_iec559 == true, "boost::float32_t has been detected in , but verification with std::numeric_limits fails"); + static_assert(std::numeric_limits::radix == 2, "boost::float32_t has been detected in , but verification with std::numeric_limits fails"); + static_assert(std::numeric_limits::digits == 24, "boost::float32_t has been detected in , but verification with std::numeric_limits fails"); + static_assert(std::numeric_limits::max_exponent == 128, "boost::float32_t has been detected in , but verification with std::numeric_limits fails"); + + #undef BOOST_CSTDFLOAT_FLOAT_32_MIN + #undef BOOST_CSTDFLOAT_FLOAT_32_MAX + #endif + +#if (defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)) && defined(__SUNPRO_CC) +#undef BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE +#define BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE 0 +#undef BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE +#define BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE 0 +#undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH +#define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 64 +#endif + + #if(BOOST_CSTDFLOAT_HAS_FLOAT64_NATIVE_TYPE == 1) + typedef BOOST_CSTDFLOAT_FLOAT64_NATIVE_TYPE float64_t; + typedef boost::float64_t float_fast64_t; + typedef boost::float64_t float_least64_t; + + static_assert(std::numeric_limits::is_iec559 == true, "boost::float64_t has been detected in , but verification with std::numeric_limits fails"); + static_assert(std::numeric_limits::radix == 2, "boost::float64_t has been detected in , but verification with std::numeric_limits fails"); + static_assert(std::numeric_limits::digits == 53, "boost::float64_t has been detected in , but verification with std::numeric_limits fails"); + static_assert(std::numeric_limits::max_exponent == 1024, "boost::float64_t has been detected in , but verification with std::numeric_limits fails"); + + #undef BOOST_CSTDFLOAT_FLOAT_64_MIN + #undef BOOST_CSTDFLOAT_FLOAT_64_MAX + #endif + + #if(BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE == 1) + typedef BOOST_CSTDFLOAT_FLOAT80_NATIVE_TYPE float80_t; + typedef boost::float80_t float_fast80_t; + typedef boost::float80_t float_least80_t; + + static_assert(std::numeric_limits::is_iec559 == true, "boost::float80_t has been detected in , but verification with std::numeric_limits fails"); + static_assert(std::numeric_limits::radix == 2, "boost::float80_t has been detected in , but verification with std::numeric_limits fails"); + static_assert(std::numeric_limits::digits == 64, "boost::float80_t has been detected in , but verification with std::numeric_limits fails"); + static_assert(std::numeric_limits::max_exponent == 16384, "boost::float80_t has been detected in , but verification with std::numeric_limits fails"); + + #undef BOOST_CSTDFLOAT_FLOAT_80_MIN + #undef BOOST_CSTDFLOAT_FLOAT_80_MAX + #endif + + #if(BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE == 1) + typedef BOOST_CSTDFLOAT_FLOAT128_NATIVE_TYPE float128_t; + typedef boost::float128_t float_fast128_t; + typedef boost::float128_t float_least128_t; + + #if defined(BOOST_CSTDFLOAT_HAS_INTERNAL_FLOAT128_T) && defined(BOOST_MATH_USE_FLOAT128) && !defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT) + // This configuration does not *yet* support std::numeric_limits. + // Support for std::numeric_limits is added in the detail + // file . + #else + static_assert(std::numeric_limits::is_iec559 == true, "boost::float128_t has been detected in , but verification with std::numeric_limits fails"); + static_assert(std::numeric_limits::radix == 2, "boost::float128_t has been detected in , but verification with std::numeric_limits fails"); + static_assert(std::numeric_limits::digits == 113, "boost::float128_t has been detected in , but verification with std::numeric_limits fails"); + static_assert(std::numeric_limits::max_exponent == 16384, "boost::float128_t has been detected in , but verification with std::numeric_limits fails"); + #endif + + #undef BOOST_CSTDFLOAT_FLOAT_128_MIN + #undef BOOST_CSTDFLOAT_FLOAT_128_MAX + #endif + + #if (BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH == 16) + typedef boost::float16_t floatmax_t; + #elif(BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH == 32) + typedef boost::float32_t floatmax_t; + #elif(BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH == 64) + typedef boost::float64_t floatmax_t; + #elif(BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH == 80) + typedef boost::float80_t floatmax_t; + #elif(BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH == 128) + typedef boost::float128_t floatmax_t; + #else + #error The maximum available floating-point width for is undefined. + #endif + + #undef BOOST_CSTDFLOAT_HAS_FLOAT16_NATIVE_TYPE + #undef BOOST_CSTDFLOAT_HAS_FLOAT32_NATIVE_TYPE + #undef BOOST_CSTDFLOAT_HAS_FLOAT64_NATIVE_TYPE + #undef BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE + #undef BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE + + #undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH + } + // namespace boost + +#endif // BOOST_MATH_CSTDFLOAT_BASE_TYPES_2014_01_09_HPP_ + diff --git a/libcxx/src/third-party/boost/math/differentiation/autodiff.hpp b/libcxx/src/third-party/boost/math/differentiation/autodiff.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/differentiation/autodiff.hpp @@ -0,0 +1,2061 @@ +// Copyright Matthew Pulver 2018 - 2019. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// https://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_DIFFERENTIATION_AUTODIFF_HPP +#define BOOST_MATH_DIFFERENTIATION_AUTODIFF_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace math { +namespace differentiation { +// Automatic Differentiation v1 +inline namespace autodiff_v1 { +namespace detail { + +template +struct promote_args_n { + using type = typename tools::promote_args_2::type>::type; +}; + +template +struct promote_args_n { + using type = typename tools::promote_arg::type; +}; + +} // namespace detail + +template +using promote = typename detail::promote_args_n::type; + +namespace detail { + +template +class fvar; + +template +struct is_fvar_impl : std::false_type {}; + +template +struct is_fvar_impl> : std::true_type {}; + +template +using is_fvar = is_fvar_impl::type>; + +template +struct nest_fvar { + using type = fvar::type, Order>; +}; + +template +struct nest_fvar { + using type = fvar; +}; + +template +struct get_depth_impl : std::integral_constant {}; + +template +struct get_depth_impl> + : std::integral_constant::value + 1> {}; + +template +using get_depth = get_depth_impl::type>; + +template +struct get_order_sum_t : std::integral_constant {}; + +template +struct get_order_sum_t> + : std::integral_constant::value + Order> {}; + +template +using get_order_sum = get_order_sum_t::type>; + +template +struct get_root_type { + using type = RealType; +}; + +template +struct get_root_type> { + using type = typename get_root_type::type; +}; + +template +struct type_at { + using type = RealType; +}; + +template +struct type_at, Depth> { + using type = typename std::conditional, + typename type_at::type>::type; +}; + +template +using get_type_at = typename type_at::type; + +// Satisfies Boost's Conceptual Requirements for Real Number Types. +// https://www.boost.org/libs/math/doc/html/math_toolkit/real_concepts.html +template +class fvar { + protected: + std::array v; + + public: + using root_type = typename get_root_type::type; // RealType in the root fvar. + + fvar() = default; + + // Initialize a variable or constant. + fvar(root_type const&, bool const is_variable); + + // RealType(cr) | RealType | RealType is copy constructible. + fvar(fvar const&) = default; + + // Be aware of implicit casting from one fvar<> type to another by this copy constructor. + template + fvar(fvar const&); + + // RealType(ca) | RealType | RealType is copy constructible from the arithmetic types. + explicit fvar(root_type const&); // Initialize a constant. (No epsilon terms.) + + template + fvar(RealType2 const& ca); // Supports any RealType2 for which static_cast(ca) compiles. + + // r = cr | RealType& | Assignment operator. + fvar& operator=(fvar const&) = default; + + // r = ca | RealType& | Assignment operator from the arithmetic types. + // Handled by constructor that takes a single parameter of generic type. + // fvar& operator=(root_type const&); // Set a constant. + + // r += cr | RealType& | Adds cr to r. + template + fvar& operator+=(fvar const&); + + // r += ca | RealType& | Adds ar to r. + fvar& operator+=(root_type const&); + + // r -= cr | RealType& | Subtracts cr from r. + template + fvar& operator-=(fvar const&); + + // r -= ca | RealType& | Subtracts ca from r. + fvar& operator-=(root_type const&); + + // r *= cr | RealType& | Multiplies r by cr. + template + fvar& operator*=(fvar const&); + + // r *= ca | RealType& | Multiplies r by ca. + fvar& operator*=(root_type const&); + + // r /= cr | RealType& | Divides r by cr. + template + fvar& operator/=(fvar const&); + + // r /= ca | RealType& | Divides r by ca. + fvar& operator/=(root_type const&); + + // -r | RealType | Unary Negation. + fvar operator-() const; + + // +r | RealType& | Identity Operation. + fvar const& operator+() const; + + // cr + cr2 | RealType | Binary Addition + template + promote> operator+(fvar const&) const; + + // cr + ca | RealType | Binary Addition + fvar operator+(root_type const&) const; + + // ca + cr | RealType | Binary Addition + template + friend fvar operator+(typename fvar::root_type const&, + fvar const&); + + // cr - cr2 | RealType | Binary Subtraction + template + promote> operator-(fvar const&) const; + + // cr - ca | RealType | Binary Subtraction + fvar operator-(root_type const&) const; + + // ca - cr | RealType | Binary Subtraction + template + friend fvar operator-(typename fvar::root_type const&, + fvar const&); + + // cr * cr2 | RealType | Binary Multiplication + template + promote> operator*(fvar const&)const; + + // cr * ca | RealType | Binary Multiplication + fvar operator*(root_type const&)const; + + // ca * cr | RealType | Binary Multiplication + template + friend fvar operator*(typename fvar::root_type const&, + fvar const&); + + // cr / cr2 | RealType | Binary Subtraction + template + promote> operator/(fvar const&) const; + + // cr / ca | RealType | Binary Subtraction + fvar operator/(root_type const&) const; + + // ca / cr | RealType | Binary Subtraction + template + friend fvar operator/(typename fvar::root_type const&, + fvar const&); + + // For all comparison overloads, only the root term is compared. + + // cr == cr2 | bool | Equality Comparison + template + bool operator==(fvar const&) const; + + // cr == ca | bool | Equality Comparison + bool operator==(root_type const&) const; + + // ca == cr | bool | Equality Comparison + template + friend bool operator==(typename fvar::root_type const&, fvar const&); + + // cr != cr2 | bool | Inequality Comparison + template + bool operator!=(fvar const&) const; + + // cr != ca | bool | Inequality Comparison + bool operator!=(root_type const&) const; + + // ca != cr | bool | Inequality Comparison + template + friend bool operator!=(typename fvar::root_type const&, fvar const&); + + // cr <= cr2 | bool | Less than equal to. + template + bool operator<=(fvar const&) const; + + // cr <= ca | bool | Less than equal to. + bool operator<=(root_type const&) const; + + // ca <= cr | bool | Less than equal to. + template + friend bool operator<=(typename fvar::root_type const&, fvar const&); + + // cr >= cr2 | bool | Greater than equal to. + template + bool operator>=(fvar const&) const; + + // cr >= ca | bool | Greater than equal to. + bool operator>=(root_type const&) const; + + // ca >= cr | bool | Greater than equal to. + template + friend bool operator>=(typename fvar::root_type const&, fvar const&); + + // cr < cr2 | bool | Less than comparison. + template + bool operator<(fvar const&) const; + + // cr < ca | bool | Less than comparison. + bool operator<(root_type const&) const; + + // ca < cr | bool | Less than comparison. + template + friend bool operator<(typename fvar::root_type const&, fvar const&); + + // cr > cr2 | bool | Greater than comparison. + template + bool operator>(fvar const&) const; + + // cr > ca | bool | Greater than comparison. + bool operator>(root_type const&) const; + + // ca > cr | bool | Greater than comparison. + template + friend bool operator>(typename fvar::root_type const&, fvar const&); + + // Will throw std::out_of_range if Order < order. + template + get_type_at at(size_t order, Orders... orders) const; + + template + get_type_at derivative(Orders... orders) const; + + const RealType& operator[](size_t) const; + + fvar inverse() const; // Multiplicative inverse. + + fvar& negate(); // Negate and return reference to *this. + + static constexpr size_t depth = get_depth::value; // Number of nested std::array. + + static constexpr size_t order_sum = get_order_sum::value; + + explicit operator root_type() const; // Must be explicit, otherwise overloaded operators are ambiguous. + + template ::type>::value>> + explicit operator T() const; // Must be explicit; multiprecision has trouble without the std::enable_if + + fvar& set_root(root_type const&); + + // Apply coefficients using horner method. + template + promote, Fvar, Fvars...> apply_coefficients(size_t const order, + Func const& f, + Fvar const& cr, + Fvars&&... fvars) const; + + template + fvar apply_coefficients(size_t const order, Func const& f) const; + + // Use when function returns derivative(i)/factorial(i) and may have some infinite derivatives. + template + promote, Fvar, Fvars...> apply_coefficients_nonhorner(size_t const order, + Func const& f, + Fvar const& cr, + Fvars&&... fvars) const; + + template + fvar apply_coefficients_nonhorner(size_t const order, Func const& f) const; + + // Apply derivatives using horner method. + template + promote, Fvar, Fvars...> apply_derivatives(size_t const order, + Func const& f, + Fvar const& cr, + Fvars&&... fvars) const; + + template + fvar apply_derivatives(size_t const order, Func const& f) const; + + // Use when function returns derivative(i) and may have some infinite derivatives. + template + promote, Fvar, Fvars...> apply_derivatives_nonhorner(size_t const order, + Func const& f, + Fvar const& cr, + Fvars&&... fvars) const; + + template + fvar apply_derivatives_nonhorner(size_t const order, Func const& f) const; + + private: + RealType epsilon_inner_product(size_t z0, + size_t isum0, + size_t m0, + fvar const& cr, + size_t z1, + size_t isum1, + size_t m1, + size_t j) const; + + fvar epsilon_multiply(size_t z0, size_t isum0, fvar const& cr, size_t z1, size_t isum1) const; + + fvar epsilon_multiply(size_t z0, size_t isum0, root_type const& ca) const; + + fvar inverse_apply() const; + + fvar& multiply_assign_by_root_type(bool is_root, root_type const&); + + template + friend class fvar; + + template + friend std::ostream& operator<<(std::ostream&, fvar const&); + + // C++11 Compatibility +#ifdef BOOST_NO_CXX17_IF_CONSTEXPR + template + void fvar_cpp11(std::true_type, RootType const& ca, bool const is_variable); + + template + void fvar_cpp11(std::false_type, RootType const& ca, bool const is_variable); + + template + get_type_at at_cpp11(std::true_type, size_t order, Orders... orders) const; + + template + get_type_at at_cpp11(std::false_type, size_t order, Orders... orders) const; + + template + fvar epsilon_multiply_cpp11(std::true_type, + SizeType z0, + size_t isum0, + fvar const& cr, + size_t z1, + size_t isum1) const; + + template + fvar epsilon_multiply_cpp11(std::false_type, + SizeType z0, + size_t isum0, + fvar const& cr, + size_t z1, + size_t isum1) const; + + template + fvar epsilon_multiply_cpp11(std::true_type, SizeType z0, size_t isum0, root_type const& ca) const; + + template + fvar epsilon_multiply_cpp11(std::false_type, SizeType z0, size_t isum0, root_type const& ca) const; + + template + fvar& multiply_assign_by_root_type_cpp11(std::true_type, bool is_root, RootType const& ca); + + template + fvar& multiply_assign_by_root_type_cpp11(std::false_type, bool is_root, RootType const& ca); + + template + fvar& negate_cpp11(std::true_type, RootType const&); + + template + fvar& negate_cpp11(std::false_type, RootType const&); + + template + fvar& set_root_cpp11(std::true_type, RootType const& root); + + template + fvar& set_root_cpp11(std::false_type, RootType const& root); +#endif +}; + +// Standard Library Support Requirements + +// fabs(cr1) | RealType +template +fvar fabs(fvar const&); + +// abs(cr1) | RealType +template +fvar abs(fvar const&); + +// ceil(cr1) | RealType +template +fvar ceil(fvar const&); + +// floor(cr1) | RealType +template +fvar floor(fvar const&); + +// exp(cr1) | RealType +template +fvar exp(fvar const&); + +// pow(cr, ca) | RealType +template +fvar pow(fvar const&, typename fvar::root_type const&); + +// pow(ca, cr) | RealType +template +fvar pow(typename fvar::root_type const&, fvar const&); + +// pow(cr1, cr2) | RealType +template +promote, fvar> pow(fvar const&, + fvar const&); + +// sqrt(cr1) | RealType +template +fvar sqrt(fvar const&); + +// log(cr1) | RealType +template +fvar log(fvar const&); + +// frexp(cr1, &i) | RealType +template +fvar frexp(fvar const&, int*); + +// ldexp(cr1, i) | RealType +template +fvar ldexp(fvar const&, int); + +// cos(cr1) | RealType +template +fvar cos(fvar const&); + +// sin(cr1) | RealType +template +fvar sin(fvar const&); + +// asin(cr1) | RealType +template +fvar asin(fvar const&); + +// tan(cr1) | RealType +template +fvar tan(fvar const&); + +// atan(cr1) | RealType +template +fvar atan(fvar const&); + +// atan2(cr, ca) | RealType +template +fvar atan2(fvar const&, typename fvar::root_type const&); + +// atan2(ca, cr) | RealType +template +fvar atan2(typename fvar::root_type const&, fvar const&); + +// atan2(cr1, cr2) | RealType +template +promote, fvar> atan2(fvar const&, + fvar const&); + +// fmod(cr1,cr2) | RealType +template +promote, fvar> fmod(fvar const&, + fvar const&); + +// round(cr1) | RealType +template +fvar round(fvar const&); + +// iround(cr1) | int +template +int iround(fvar const&); + +template +long lround(fvar const&); + +template +long long llround(fvar const&); + +// trunc(cr1) | RealType +template +fvar trunc(fvar const&); + +template +long double truncl(fvar const&); + +// itrunc(cr1) | int +template +int itrunc(fvar const&); + +template +long long lltrunc(fvar const&); + +// Additional functions +template +fvar acos(fvar const&); + +template +fvar acosh(fvar const&); + +template +fvar asinh(fvar const&); + +template +fvar atanh(fvar const&); + +template +fvar cosh(fvar const&); + +template +fvar digamma(fvar const&); + +template +fvar erf(fvar const&); + +template +fvar erfc(fvar const&); + +template +fvar lambert_w0(fvar const&); + +template +fvar lgamma(fvar const&); + +template +fvar sinc(fvar const&); + +template +fvar sinh(fvar const&); + +template +fvar tanh(fvar const&); + +template +fvar tgamma(fvar const&); + +template +struct zero : std::integral_constant {}; + +} // namespace detail + +template +using autodiff_fvar = typename detail::nest_fvar::type; + +template +autodiff_fvar make_fvar(RealType const& ca) { + return autodiff_fvar(ca, true); +} + +#ifndef BOOST_NO_CXX17_IF_CONSTEXPR +namespace detail { + +template +auto make_fvar_for_tuple(std::index_sequence, RealType const& ca) { + return make_fvar::value..., Order>(ca); +} + +template +auto make_ftuple_impl(std::index_sequence, RealTypes const&... ca) { + return std::make_tuple(make_fvar_for_tuple(std::make_index_sequence{}, ca)...); +} + +} // namespace detail + +template +auto make_ftuple(RealTypes const&... ca) { + static_assert(sizeof...(Orders) == sizeof...(RealTypes), + "Number of Orders must match number of function parameters."); + return detail::make_ftuple_impl(std::index_sequence_for{}, ca...); +} +#endif + +namespace detail { + +#ifndef BOOST_NO_CXX17_IF_CONSTEXPR +template +fvar::fvar(root_type const& ca, bool const is_variable) { + if constexpr (is_fvar::value) { + v.front() = RealType(ca, is_variable); + if constexpr (0 < Order) + std::fill(v.begin() + 1, v.end(), static_cast(0)); + } else { + v.front() = ca; + if constexpr (0 < Order) + v[1] = static_cast(static_cast(is_variable)); + if constexpr (1 < Order) + std::fill(v.begin() + 2, v.end(), static_cast(0)); + } +} +#endif + +template +template +fvar::fvar(fvar const& cr) { + for (size_t i = 0; i <= (std::min)(Order, Order2); ++i) + v[i] = static_cast(cr.v[i]); + BOOST_IF_CONSTEXPR (Order2 < Order) + std::fill(v.begin() + (Order2 + 1), v.end(), static_cast(0)); +} + +template +fvar::fvar(root_type const& ca) : v{{static_cast(ca)}} {} + +// Can cause compiler error if RealType2 cannot be cast to root_type. +template +template +fvar::fvar(RealType2 const& ca) : v{{static_cast(ca)}} {} + +/* +template +fvar& fvar::operator=(root_type const& ca) +{ + v.front() = static_cast(ca); + if constexpr (0 < Order) + std::fill(v.begin()+1, v.end(), static_cast(0)); + return *this; +} +*/ + +template +template +fvar& fvar::operator+=(fvar const& cr) { + for (size_t i = 0; i <= (std::min)(Order, Order2); ++i) + v[i] += cr.v[i]; + return *this; +} + +template +fvar& fvar::operator+=(root_type const& ca) { + v.front() += ca; + return *this; +} + +template +template +fvar& fvar::operator-=(fvar const& cr) { + for (size_t i = 0; i <= Order; ++i) + v[i] -= cr.v[i]; + return *this; +} + +template +fvar& fvar::operator-=(root_type const& ca) { + v.front() -= ca; + return *this; +} + +template +template +fvar& fvar::operator*=(fvar const& cr) { + using diff_t = typename std::array::difference_type; + promote const zero(0); + BOOST_IF_CONSTEXPR (Order <= Order2) + for (size_t i = 0, j = Order; i <= Order; ++i, --j) + v[j] = std::inner_product(v.cbegin(), v.cend() - diff_t(i), cr.v.crbegin() + diff_t(i), zero); + else { + for (size_t i = 0, j = Order; i <= Order - Order2; ++i, --j) + v[j] = std::inner_product(cr.v.cbegin(), cr.v.cend(), v.crbegin() + diff_t(i), zero); + for (size_t i = Order - Order2 + 1, j = Order2 - 1; i <= Order; ++i, --j) + v[j] = std::inner_product(cr.v.cbegin(), cr.v.cbegin() + diff_t(j + 1), v.crbegin() + diff_t(i), zero); + } + return *this; +} + +template +fvar& fvar::operator*=(root_type const& ca) { + return multiply_assign_by_root_type(true, ca); +} + +template +template +fvar& fvar::operator/=(fvar const& cr) { + using diff_t = typename std::array::difference_type; + RealType const zero(0); + v.front() /= cr.v.front(); + BOOST_IF_CONSTEXPR (Order < Order2) + for (size_t i = 1, j = Order2 - 1, k = Order; i <= Order; ++i, --j, --k) + (v[i] -= std::inner_product( + cr.v.cbegin() + 1, cr.v.cend() - diff_t(j), v.crbegin() + diff_t(k), zero)) /= cr.v.front(); + else BOOST_IF_CONSTEXPR (0 < Order2) + for (size_t i = 1, j = Order2 - 1, k = Order; i <= Order; ++i, j && --j, --k) + (v[i] -= std::inner_product( + cr.v.cbegin() + 1, cr.v.cend() - diff_t(j), v.crbegin() + diff_t(k), zero)) /= cr.v.front(); + else + for (size_t i = 1; i <= Order; ++i) + v[i] /= cr.v.front(); + return *this; +} + +template +fvar& fvar::operator/=(root_type const& ca) { + std::for_each(v.begin(), v.end(), [&ca](RealType& x) { x /= ca; }); + return *this; +} + +template +fvar fvar::operator-() const { + fvar retval(*this); + retval.negate(); + return retval; +} + +template +fvar const& fvar::operator+() const { + return *this; +} + +template +template +promote, fvar> fvar::operator+( + fvar const& cr) const { + promote, fvar> retval; + for (size_t i = 0; i <= (std::min)(Order, Order2); ++i) + retval.v[i] = v[i] + cr.v[i]; + BOOST_IF_CONSTEXPR (Order < Order2) + for (size_t i = Order + 1; i <= Order2; ++i) + retval.v[i] = cr.v[i]; + else BOOST_IF_CONSTEXPR (Order2 < Order) + for (size_t i = Order2 + 1; i <= Order; ++i) + retval.v[i] = v[i]; + return retval; +} + +template +fvar fvar::operator+(root_type const& ca) const { + fvar retval(*this); + retval.v.front() += ca; + return retval; +} + +template +fvar operator+(typename fvar::root_type const& ca, + fvar const& cr) { + return cr + ca; +} + +template +template +promote, fvar> fvar::operator-( + fvar const& cr) const { + promote, fvar> retval; + for (size_t i = 0; i <= (std::min)(Order, Order2); ++i) + retval.v[i] = v[i] - cr.v[i]; + BOOST_IF_CONSTEXPR (Order < Order2) + for (auto i = Order + 1; i <= Order2; ++i) + retval.v[i] = -cr.v[i]; + else BOOST_IF_CONSTEXPR (Order2 < Order) + for (auto i = Order2 + 1; i <= Order; ++i) + retval.v[i] = v[i]; + return retval; +} + +template +fvar fvar::operator-(root_type const& ca) const { + fvar retval(*this); + retval.v.front() -= ca; + return retval; +} + +template +fvar operator-(typename fvar::root_type const& ca, + fvar const& cr) { + fvar mcr = -cr; // Has same address as retval in operator-() due to NRVO. + mcr += ca; + return mcr; // <-- This allows for NRVO. The following does not. --> return mcr += ca; +} + +template +template +promote, fvar> fvar::operator*( + fvar const& cr) const { + using diff_t = typename std::array::difference_type; + promote const zero(0); + promote, fvar> retval; + BOOST_IF_CONSTEXPR (Order < Order2) + for (size_t i = 0, j = Order, k = Order2; i <= Order2; ++i, j && --j, --k) + retval.v[i] = std::inner_product(v.cbegin(), v.cend() - diff_t(j), cr.v.crbegin() + diff_t(k), zero); + else + for (size_t i = 0, j = Order2, k = Order; i <= Order; ++i, j && --j, --k) + retval.v[i] = std::inner_product(cr.v.cbegin(), cr.v.cend() - diff_t(j), v.crbegin() + diff_t(k), zero); + return retval; +} + +template +fvar fvar::operator*(root_type const& ca) const { + fvar retval(*this); + retval *= ca; + return retval; +} + +template +fvar operator*(typename fvar::root_type const& ca, + fvar const& cr) { + return cr * ca; +} + +template +template +promote, fvar> fvar::operator/( + fvar const& cr) const { + using diff_t = typename std::array::difference_type; + promote const zero(0); + promote, fvar> retval; + retval.v.front() = v.front() / cr.v.front(); + BOOST_IF_CONSTEXPR (Order < Order2) { + for (size_t i = 1, j = Order2 - 1; i <= Order; ++i, --j) + retval.v[i] = + (v[i] - std::inner_product( + cr.v.cbegin() + 1, cr.v.cend() - diff_t(j), retval.v.crbegin() + diff_t(j + 1), zero)) / + cr.v.front(); + for (size_t i = Order + 1, j = Order2 - Order - 1; i <= Order2; ++i, --j) + retval.v[i] = + -std::inner_product( + cr.v.cbegin() + 1, cr.v.cend() - diff_t(j), retval.v.crbegin() + diff_t(j + 1), zero) / + cr.v.front(); + } else BOOST_IF_CONSTEXPR (0 < Order2) + for (size_t i = 1, j = Order2 - 1, k = Order; i <= Order; ++i, j && --j, --k) + retval.v[i] = + (v[i] - std::inner_product( + cr.v.cbegin() + 1, cr.v.cend() - diff_t(j), retval.v.crbegin() + diff_t(k), zero)) / + cr.v.front(); + else + for (size_t i = 1; i <= Order; ++i) + retval.v[i] = v[i] / cr.v.front(); + return retval; +} + +template +fvar fvar::operator/(root_type const& ca) const { + fvar retval(*this); + retval /= ca; + return retval; +} + +template +fvar operator/(typename fvar::root_type const& ca, + fvar const& cr) { + using diff_t = typename std::array::difference_type; + fvar retval; + retval.v.front() = ca / cr.v.front(); + BOOST_IF_CONSTEXPR (0 < Order) { + RealType const zero(0); + for (size_t i = 1, j = Order - 1; i <= Order; ++i, --j) + retval.v[i] = + -std::inner_product( + cr.v.cbegin() + 1, cr.v.cend() - diff_t(j), retval.v.crbegin() + diff_t(j + 1), zero) / + cr.v.front(); + } + return retval; +} + +template +template +bool fvar::operator==(fvar const& cr) const { + return v.front() == cr.v.front(); +} + +template +bool fvar::operator==(root_type const& ca) const { + return v.front() == ca; +} + +template +bool operator==(typename fvar::root_type const& ca, fvar const& cr) { + return ca == cr.v.front(); +} + +template +template +bool fvar::operator!=(fvar const& cr) const { + return v.front() != cr.v.front(); +} + +template +bool fvar::operator!=(root_type const& ca) const { + return v.front() != ca; +} + +template +bool operator!=(typename fvar::root_type const& ca, fvar const& cr) { + return ca != cr.v.front(); +} + +template +template +bool fvar::operator<=(fvar const& cr) const { + return v.front() <= cr.v.front(); +} + +template +bool fvar::operator<=(root_type const& ca) const { + return v.front() <= ca; +} + +template +bool operator<=(typename fvar::root_type const& ca, fvar const& cr) { + return ca <= cr.v.front(); +} + +template +template +bool fvar::operator>=(fvar const& cr) const { + return v.front() >= cr.v.front(); +} + +template +bool fvar::operator>=(root_type const& ca) const { + return v.front() >= ca; +} + +template +bool operator>=(typename fvar::root_type const& ca, fvar const& cr) { + return ca >= cr.v.front(); +} + +template +template +bool fvar::operator<(fvar const& cr) const { + return v.front() < cr.v.front(); +} + +template +bool fvar::operator<(root_type const& ca) const { + return v.front() < ca; +} + +template +bool operator<(typename fvar::root_type const& ca, fvar const& cr) { + return ca < cr.v.front(); +} + +template +template +bool fvar::operator>(fvar const& cr) const { + return v.front() > cr.v.front(); +} + +template +bool fvar::operator>(root_type const& ca) const { + return v.front() > ca; +} + +template +bool operator>(typename fvar::root_type const& ca, fvar const& cr) { + return ca > cr.v.front(); +} + + /*** Other methods and functions ***/ + +#ifndef BOOST_NO_CXX17_IF_CONSTEXPR +// f : order -> derivative(order)/factorial(order) +// Use this when you have the polynomial coefficients, rather than just the derivatives. E.g. See atan2(). +template +template +promote, Fvar, Fvars...> fvar::apply_coefficients( + size_t const order, + Func const& f, + Fvar const& cr, + Fvars&&... fvars) const { + fvar const epsilon = fvar(*this).set_root(0); + size_t i = (std::min)(order, order_sum); + promote, Fvar, Fvars...> accumulator = cr.apply_coefficients( + order - i, [&f, i](auto... indices) { return f(i, indices...); }, std::forward(fvars)...); + while (i--) + (accumulator *= epsilon) += cr.apply_coefficients( + order - i, [&f, i](auto... indices) { return f(i, indices...); }, std::forward(fvars)...); + return accumulator; +} +#endif + +// f : order -> derivative(order)/factorial(order) +// Use this when you have the polynomial coefficients, rather than just the derivatives. E.g. See atan(). +template +template +fvar fvar::apply_coefficients(size_t const order, Func const& f) const { + fvar const epsilon = fvar(*this).set_root(0); +#ifndef BOOST_NO_CXX17_IF_CONSTEXPR + size_t i = (std::min)(order, order_sum); +#else // ODR-use of static constexpr + size_t i = order < order_sum ? order : order_sum; +#endif + fvar accumulator = f(i); + while (i--) + (accumulator *= epsilon) += f(i); + return accumulator; +} + +#ifndef BOOST_NO_CXX17_IF_CONSTEXPR +// f : order -> derivative(order) +template +template +promote, Fvar, Fvars...> fvar::apply_coefficients_nonhorner( + size_t const order, + Func const& f, + Fvar const& cr, + Fvars&&... fvars) const { + fvar const epsilon = fvar(*this).set_root(0); + fvar epsilon_i = fvar(1); // epsilon to the power of i + promote, Fvar, Fvars...> accumulator = cr.apply_coefficients_nonhorner( + order, + [&f](auto... indices) { return f(0, static_cast(indices)...); }, + std::forward(fvars)...); + size_t const i_max = (std::min)(order, order_sum); + for (size_t i = 1; i <= i_max; ++i) { + epsilon_i = epsilon_i.epsilon_multiply(i - 1, 0, epsilon, 1, 0); + accumulator += epsilon_i.epsilon_multiply( + i, + 0, + cr.apply_coefficients_nonhorner( + order - i, + [&f, i](auto... indices) { return f(i, static_cast(indices)...); }, + std::forward(fvars)...), + 0, + 0); + } + return accumulator; +} +#endif + +// f : order -> coefficient(order) +template +template +fvar fvar::apply_coefficients_nonhorner(size_t const order, + Func const& f) const { + fvar const epsilon = fvar(*this).set_root(0); + fvar epsilon_i = fvar(1); // epsilon to the power of i + fvar accumulator = fvar(f(0u)); +#ifndef BOOST_NO_CXX17_IF_CONSTEXPR + size_t const i_max = (std::min)(order, order_sum); +#else // ODR-use of static constexpr + size_t const i_max = order < order_sum ? order : order_sum; +#endif + for (size_t i = 1; i <= i_max; ++i) { + epsilon_i = epsilon_i.epsilon_multiply(i - 1, 0, epsilon, 1, 0); + accumulator += epsilon_i.epsilon_multiply(i, 0, f(i)); + } + return accumulator; +} + +#ifndef BOOST_NO_CXX17_IF_CONSTEXPR +// f : order -> derivative(order) +template +template +promote, Fvar, Fvars...> fvar::apply_derivatives( + size_t const order, + Func const& f, + Fvar const& cr, + Fvars&&... fvars) const { + fvar const epsilon = fvar(*this).set_root(0); + size_t i = (std::min)(order, order_sum); + promote, Fvar, Fvars...> accumulator = + cr.apply_derivatives( + order - i, [&f, i](auto... indices) { return f(i, indices...); }, std::forward(fvars)...) / + factorial(static_cast(i)); + while (i--) + (accumulator *= epsilon) += + cr.apply_derivatives( + order - i, [&f, i](auto... indices) { return f(i, indices...); }, std::forward(fvars)...) / + factorial(static_cast(i)); + return accumulator; +} +#endif + +// f : order -> derivative(order) +template +template +fvar fvar::apply_derivatives(size_t const order, Func const& f) const { + fvar const epsilon = fvar(*this).set_root(0); +#ifndef BOOST_NO_CXX17_IF_CONSTEXPR + size_t i = (std::min)(order, order_sum); +#else // ODR-use of static constexpr + size_t i = order < order_sum ? order : order_sum; +#endif + fvar accumulator = f(i) / factorial(static_cast(i)); + while (i--) + (accumulator *= epsilon) += f(i) / factorial(static_cast(i)); + return accumulator; +} + +#ifndef BOOST_NO_CXX17_IF_CONSTEXPR +// f : order -> derivative(order) +template +template +promote, Fvar, Fvars...> fvar::apply_derivatives_nonhorner( + size_t const order, + Func const& f, + Fvar const& cr, + Fvars&&... fvars) const { + fvar const epsilon = fvar(*this).set_root(0); + fvar epsilon_i = fvar(1); // epsilon to the power of i + promote, Fvar, Fvars...> accumulator = cr.apply_derivatives_nonhorner( + order, + [&f](auto... indices) { return f(0, static_cast(indices)...); }, + std::forward(fvars)...); + size_t const i_max = (std::min)(order, order_sum); + for (size_t i = 1; i <= i_max; ++i) { + epsilon_i = epsilon_i.epsilon_multiply(i - 1, 0, epsilon, 1, 0); + accumulator += epsilon_i.epsilon_multiply( + i, + 0, + cr.apply_derivatives_nonhorner( + order - i, + [&f, i](auto... indices) { return f(i, static_cast(indices)...); }, + std::forward(fvars)...) / + factorial(static_cast(i)), + 0, + 0); + } + return accumulator; +} +#endif + +// f : order -> derivative(order) +template +template +fvar fvar::apply_derivatives_nonhorner(size_t const order, + Func const& f) const { + fvar const epsilon = fvar(*this).set_root(0); + fvar epsilon_i = fvar(1); // epsilon to the power of i + fvar accumulator = fvar(f(0u)); +#ifndef BOOST_NO_CXX17_IF_CONSTEXPR + size_t const i_max = (std::min)(order, order_sum); +#else // ODR-use of static constexpr + size_t const i_max = order < order_sum ? order : order_sum; +#endif + for (size_t i = 1; i <= i_max; ++i) { + epsilon_i = epsilon_i.epsilon_multiply(i - 1, 0, epsilon, 1, 0); + accumulator += epsilon_i.epsilon_multiply(i, 0, f(i) / factorial(static_cast(i))); + } + return accumulator; +} + +#ifndef BOOST_NO_CXX17_IF_CONSTEXPR +// Can throw "std::out_of_range: array::at: __n (which is 7) >= _Nm (which is 7)" +template +template +get_type_at fvar::at(size_t order, Orders... orders) const { + if constexpr (0 < sizeof...(Orders)) + return v.at(order).at(static_cast(orders)...); + else + return v.at(order); +} +#endif + +#ifndef BOOST_NO_CXX17_IF_CONSTEXPR +// Can throw "std::out_of_range: array::at: __n (which is 7) >= _Nm (which is 7)" +template +template +get_type_at, sizeof...(Orders)> fvar::derivative( + Orders... orders) const { + static_assert(sizeof...(Orders) <= depth, + "Number of parameters to derivative(...) cannot exceed fvar::depth."); + return at(static_cast(orders)...) * + (... * factorial(static_cast(orders))); +} +#endif + +template +const RealType& fvar::operator[](size_t i) const { + return v[i]; +} + +template +RealType fvar::epsilon_inner_product(size_t z0, + size_t const isum0, + size_t const m0, + fvar const& cr, + size_t z1, + size_t const isum1, + size_t const m1, + size_t const j) const { + static_assert(is_fvar::value, "epsilon_inner_product() must have 1 < depth."); + RealType accumulator = RealType(); + auto const i0_max = m1 < j ? j - m1 : 0; + for (auto i0 = m0, i1 = j - m0; i0 <= i0_max; ++i0, --i1) + accumulator += v[i0].epsilon_multiply(z0, isum0 + i0, cr.v[i1], z1, isum1 + i1); + return accumulator; +} + +#ifndef BOOST_NO_CXX17_IF_CONSTEXPR +template +fvar fvar::epsilon_multiply(size_t z0, + size_t isum0, + fvar const& cr, + size_t z1, + size_t isum1) const { + using diff_t = typename std::array::difference_type; + RealType const zero(0); + size_t const m0 = order_sum + isum0 < Order + z0 ? Order + z0 - (order_sum + isum0) : 0; + size_t const m1 = order_sum + isum1 < Order + z1 ? Order + z1 - (order_sum + isum1) : 0; + size_t const i_max = m0 + m1 < Order ? Order - (m0 + m1) : 0; + fvar retval = fvar(); + if constexpr (is_fvar::value) + for (size_t i = 0, j = Order; i <= i_max; ++i, --j) + retval.v[j] = epsilon_inner_product(z0, isum0, m0, cr, z1, isum1, m1, j); + else + for (size_t i = 0, j = Order; i <= i_max; ++i, --j) + retval.v[j] = std::inner_product( + v.cbegin() + diff_t(m0), v.cend() - diff_t(i + m1), cr.v.crbegin() + diff_t(i + m0), zero); + return retval; +} +#endif + +#ifndef BOOST_NO_CXX17_IF_CONSTEXPR +// When called from outside this method, z0 should be non-zero. Otherwise if z0=0 then it will give an +// incorrect result of 0 when the root value is 0 and ca=inf, when instead the correct product is nan. +// If z0=0 then use the regular multiply operator*() instead. +template +fvar fvar::epsilon_multiply(size_t z0, + size_t isum0, + root_type const& ca) const { + fvar retval(*this); + size_t const m0 = order_sum + isum0 < Order + z0 ? Order + z0 - (order_sum + isum0) : 0; + if constexpr (is_fvar::value) + for (size_t i = m0; i <= Order; ++i) + retval.v[i] = retval.v[i].epsilon_multiply(z0, isum0 + i, ca); + else + for (size_t i = m0; i <= Order; ++i) + if (retval.v[i] != static_cast(0)) + retval.v[i] *= ca; + return retval; +} +#endif + +template +fvar fvar::inverse() const { + return static_cast(*this) == 0 ? inverse_apply() : 1 / *this; +} + +#ifndef BOOST_NO_CXX17_IF_CONSTEXPR +template +fvar& fvar::negate() { + if constexpr (is_fvar::value) + std::for_each(v.begin(), v.end(), [](RealType& r) { r.negate(); }); + else + std::for_each(v.begin(), v.end(), [](RealType& a) { a = -a; }); + return *this; +} +#endif + +// This gives log(0.0) = depth(1)(-inf,inf,-inf,inf,-inf,inf) +// 1 / *this: log(0.0) = depth(1)(-inf,inf,-inf,-nan,-nan,-nan) +template +fvar fvar::inverse_apply() const { + root_type derivatives[order_sum + 1]; // LCOV_EXCL_LINE This causes a false negative on lcov coverage test. + root_type const x0 = static_cast(*this); + *derivatives = 1 / x0; + for (size_t i = 1; i <= order_sum; ++i) + derivatives[i] = -derivatives[i - 1] * i / x0; + return apply_derivatives_nonhorner(order_sum, [&derivatives](size_t j) { return derivatives[j]; }); +} + +#ifndef BOOST_NO_CXX17_IF_CONSTEXPR +template +fvar& fvar::multiply_assign_by_root_type(bool is_root, + root_type const& ca) { + auto itr = v.begin(); + if constexpr (is_fvar::value) { + itr->multiply_assign_by_root_type(is_root, ca); + for (++itr; itr != v.end(); ++itr) + itr->multiply_assign_by_root_type(false, ca); + } else { + if (is_root || *itr != 0) + *itr *= ca; // Skip multiplication of 0 by ca=inf to avoid nan, except when is_root. + for (++itr; itr != v.end(); ++itr) + if (*itr != 0) + *itr *= ca; + } + return *this; +} +#endif + +template +fvar::operator root_type() const { + return static_cast(v.front()); +} + +template +template +fvar::operator T() const { + return static_cast(static_cast(v.front())); +} + +#ifndef BOOST_NO_CXX17_IF_CONSTEXPR +template +fvar& fvar::set_root(root_type const& root) { + if constexpr (is_fvar::value) + v.front().set_root(root); + else + v.front() = root; + return *this; +} +#endif + +// Standard Library Support Requirements + +template +fvar fabs(fvar const& cr) { + typename fvar::root_type const zero(0); + return cr < zero ? -cr + : cr == zero ? fvar() // Canonical fabs'(0) = 0. + : cr; // Propagate NaN. +} + +template +fvar abs(fvar const& cr) { + return fabs(cr); +} + +template +fvar ceil(fvar const& cr) { + using std::ceil; + return fvar(ceil(static_cast::root_type>(cr))); +} + +template +fvar floor(fvar const& cr) { + using std::floor; + return fvar(floor(static_cast::root_type>(cr))); +} + +template +fvar exp(fvar const& cr) { + using std::exp; + constexpr size_t order = fvar::order_sum; + using root_type = typename fvar::root_type; + root_type const d0 = exp(static_cast(cr)); + return cr.apply_derivatives(order, [&d0](size_t) { return d0; }); +} + +template +fvar pow(fvar const& x, + typename fvar::root_type const& y) { + BOOST_MATH_STD_USING + using root_type = typename fvar::root_type; + constexpr size_t order = fvar::order_sum; + root_type const x0 = static_cast(x); + root_type derivatives[order + 1]{pow(x0, y)}; + if (fabs(x0) < std::numeric_limits::epsilon()) { + root_type coef = 1; + for (size_t i = 0; i < order && y - i != 0; ++i) { + coef *= y - i; + derivatives[i + 1] = coef * pow(x0, y - (i + 1)); + } + return x.apply_derivatives_nonhorner(order, [&derivatives](size_t i) { return derivatives[i]; }); + } else { + for (size_t i = 0; i < order && y - i != 0; ++i) + derivatives[i + 1] = (y - i) * derivatives[i] / x0; + return x.apply_derivatives(order, [&derivatives](size_t i) { return derivatives[i]; }); + } +} + +template +fvar pow(typename fvar::root_type const& x, + fvar const& y) { + BOOST_MATH_STD_USING + using root_type = typename fvar::root_type; + constexpr size_t order = fvar::order_sum; + root_type const y0 = static_cast(y); + root_type derivatives[order + 1]; + *derivatives = pow(x, y0); + root_type const logx = log(x); + for (size_t i = 0; i < order; ++i) + derivatives[i + 1] = derivatives[i] * logx; + return y.apply_derivatives(order, [&derivatives](size_t i) { return derivatives[i]; }); +} + +template +promote, fvar> pow(fvar const& x, + fvar const& y) { + BOOST_MATH_STD_USING + using return_type = promote, fvar>; + using root_type = typename return_type::root_type; + constexpr size_t order = return_type::order_sum; + root_type const x0 = static_cast(x); + root_type const y0 = static_cast(y); + root_type dxydx[order + 1]{pow(x0, y0)}; + BOOST_IF_CONSTEXPR (order == 0) + return return_type(*dxydx); + else { + for (size_t i = 0; i < order && y0 - i != 0; ++i) + dxydx[i + 1] = (y0 - i) * dxydx[i] / x0; + std::array, order + 1> lognx; + lognx.front() = fvar(1); +#ifndef BOOST_NO_CXX17_IF_CONSTEXPR + lognx[1] = log(make_fvar(x0)); +#else // for compilers that compile this branch when order == 0. + lognx[(std::min)(size_t(1), order)] = log(make_fvar(x0)); +#endif + for (size_t i = 1; i < order; ++i) + lognx[i + 1] = lognx[i] * lognx[1]; + auto const f = [&dxydx, &lognx](size_t i, size_t j) { + size_t binomial = 1; + root_type sum = dxydx[i] * static_cast(lognx[j]); + for (size_t k = 1; k <= i; ++k) { + (binomial *= (i - k + 1)) /= k; // binomial_coefficient(i,k) + sum += binomial * dxydx[i - k] * lognx[j].derivative(k); + } + return sum; + }; + if (fabs(x0) < std::numeric_limits::epsilon()) + return x.apply_derivatives_nonhorner(order, f, y); + return x.apply_derivatives(order, f, y); + } +} + +template +fvar sqrt(fvar const& cr) { + using std::sqrt; + using root_type = typename fvar::root_type; + constexpr size_t order = fvar::order_sum; + root_type derivatives[order + 1]; + root_type const x = static_cast(cr); + *derivatives = sqrt(x); + BOOST_IF_CONSTEXPR (order == 0) + return fvar(*derivatives); + else { + root_type numerator = 0.5; + root_type powers = 1; +#ifndef BOOST_NO_CXX17_IF_CONSTEXPR + derivatives[1] = numerator / *derivatives; +#else // for compilers that compile this branch when order == 0. + derivatives[(std::min)(size_t(1), order)] = numerator / *derivatives; +#endif + using diff_t = typename std::array::difference_type; + for (size_t i = 2; i <= order; ++i) { + numerator *= static_cast(-0.5) * ((static_cast(i) << 1) - 3); + powers *= x; + derivatives[i] = numerator / (powers * *derivatives); + } + auto const f = [&derivatives](size_t i) { return derivatives[i]; }; + if (cr < std::numeric_limits::epsilon()) + return cr.apply_derivatives_nonhorner(order, f); + return cr.apply_derivatives(order, f); + } +} + +// Natural logarithm. If cr==0 then derivative(i) may have nans due to nans from inverse(). +template +fvar log(fvar const& cr) { + using std::log; + using root_type = typename fvar::root_type; + constexpr size_t order = fvar::order_sum; + root_type const d0 = log(static_cast(cr)); + BOOST_IF_CONSTEXPR (order == 0) + return fvar(d0); + else { + auto const d1 = make_fvar(static_cast(cr)).inverse(); // log'(x) = 1 / x + return cr.apply_coefficients_nonhorner(order, [&d0, &d1](size_t i) { return i ? d1[i - 1] / i : d0; }); + } +} + +template +fvar frexp(fvar const& cr, int* exp) { + using std::exp2; + using std::frexp; + using root_type = typename fvar::root_type; + frexp(static_cast(cr), exp); + return cr * static_cast(exp2(-*exp)); +} + +template +fvar ldexp(fvar const& cr, int exp) { + // argument to std::exp2 must be casted to root_type, otherwise std::exp2 returns double (always) + using std::exp2; + return cr * exp2(static_cast::root_type>(exp)); +} + +template +fvar cos(fvar const& cr) { + BOOST_MATH_STD_USING + using root_type = typename fvar::root_type; + constexpr size_t order = fvar::order_sum; + root_type const d0 = cos(static_cast(cr)); + BOOST_IF_CONSTEXPR (order == 0) + return fvar(d0); + else { + root_type const d1 = -sin(static_cast(cr)); + root_type const derivatives[4]{d0, d1, -d0, -d1}; + return cr.apply_derivatives(order, [&derivatives](size_t i) { return derivatives[i & 3]; }); + } +} + +template +fvar sin(fvar const& cr) { + BOOST_MATH_STD_USING + using root_type = typename fvar::root_type; + constexpr size_t order = fvar::order_sum; + root_type const d0 = sin(static_cast(cr)); + BOOST_IF_CONSTEXPR (order == 0) + return fvar(d0); + else { + root_type const d1 = cos(static_cast(cr)); + root_type const derivatives[4]{d0, d1, -d0, -d1}; + return cr.apply_derivatives(order, [&derivatives](size_t i) { return derivatives[i & 3]; }); + } +} + +template +fvar asin(fvar const& cr) { + using std::asin; + using root_type = typename fvar::root_type; + constexpr size_t order = fvar::order_sum; + root_type const d0 = asin(static_cast(cr)); + BOOST_IF_CONSTEXPR (order == 0) + return fvar(d0); + else { + auto x = make_fvar(static_cast(cr)); + auto const d1 = sqrt((x *= x).negate() += 1).inverse(); // asin'(x) = 1 / sqrt(1-x*x). + return cr.apply_coefficients_nonhorner(order, [&d0, &d1](size_t i) { return i ? d1[i - 1] / i : d0; }); + } +} + +template +fvar tan(fvar const& cr) { + using std::tan; + using root_type = typename fvar::root_type; + constexpr size_t order = fvar::order_sum; + root_type const d0 = tan(static_cast(cr)); + BOOST_IF_CONSTEXPR (order == 0) + return fvar(d0); + else { + auto c = cos(make_fvar(static_cast(cr))); + auto const d1 = (c *= c).inverse(); // tan'(x) = 1 / cos(x)^2 + return cr.apply_coefficients_nonhorner(order, [&d0, &d1](size_t i) { return i ? d1[i - 1] / i : d0; }); + } +} + +template +fvar atan(fvar const& cr) { + using std::atan; + using root_type = typename fvar::root_type; + constexpr size_t order = fvar::order_sum; + root_type const d0 = atan(static_cast(cr)); + BOOST_IF_CONSTEXPR (order == 0) + return fvar(d0); + else { + auto x = make_fvar(static_cast(cr)); + auto const d1 = ((x *= x) += 1).inverse(); // atan'(x) = 1 / (x*x+1). + return cr.apply_coefficients(order, [&d0, &d1](size_t i) { return i ? d1[i - 1] / i : d0; }); + } +} + +template +fvar atan2(fvar const& cr, + typename fvar::root_type const& ca) { + using std::atan2; + using root_type = typename fvar::root_type; + constexpr size_t order = fvar::order_sum; + root_type const d0 = atan2(static_cast(cr), ca); + BOOST_IF_CONSTEXPR (order == 0) + return fvar(d0); + else { + auto y = make_fvar(static_cast(cr)); + auto const d1 = ca / ((y *= y) += (ca * ca)); // (d/dy)atan2(y,x) = x / (y*y+x*x) + return cr.apply_coefficients(order, [&d0, &d1](size_t i) { return i ? d1[i - 1] / i : d0; }); + } +} + +template +fvar atan2(typename fvar::root_type const& ca, + fvar const& cr) { + using std::atan2; + using root_type = typename fvar::root_type; + constexpr size_t order = fvar::order_sum; + root_type const d0 = atan2(ca, static_cast(cr)); + BOOST_IF_CONSTEXPR (order == 0) + return fvar(d0); + else { + auto x = make_fvar(static_cast(cr)); + auto const d1 = -ca / ((x *= x) += (ca * ca)); // (d/dx)atan2(y,x) = -y / (x*x+y*y) + return cr.apply_coefficients(order, [&d0, &d1](size_t i) { return i ? d1[i - 1] / i : d0; }); + } +} + +template +promote, fvar> atan2(fvar const& cr1, + fvar const& cr2) { + using std::atan2; + using return_type = promote, fvar>; + using root_type = typename return_type::root_type; + constexpr size_t order = return_type::order_sum; + root_type const y = static_cast(cr1); + root_type const x = static_cast(cr2); + root_type const d00 = atan2(y, x); + BOOST_IF_CONSTEXPR (order == 0) + return return_type(d00); + else { + constexpr size_t order1 = fvar::order_sum; + constexpr size_t order2 = fvar::order_sum; + auto x01 = make_fvar::root_type, order2 - 1>(x); + auto const d01 = -y / ((x01 *= x01) += (y * y)); + auto y10 = make_fvar::root_type, order1 - 1>(y); + auto x10 = make_fvar::root_type, 0, order2>(x); + auto const d10 = x10 / ((x10 * x10) + (y10 *= y10)); + auto const f = [&d00, &d01, &d10](size_t i, size_t j) { + return i ? d10[i - 1][j] / i : j ? d01[j - 1] / j : d00; + }; + return cr1.apply_coefficients(order, f, cr2); + } +} + +template +promote, fvar> fmod(fvar const& cr1, + fvar const& cr2) { + using boost::math::trunc; + auto const numer = static_cast::root_type>(cr1); + auto const denom = static_cast::root_type>(cr2); + return cr1 - cr2 * trunc(numer / denom); +} + +template +fvar round(fvar const& cr) { + using boost::math::round; + return fvar(round(static_cast::root_type>(cr))); +} + +template +int iround(fvar const& cr) { + using boost::math::iround; + return iround(static_cast::root_type>(cr)); +} + +template +long lround(fvar const& cr) { + using boost::math::lround; + return lround(static_cast::root_type>(cr)); +} + +template +long long llround(fvar const& cr) { + using boost::math::llround; + return llround(static_cast::root_type>(cr)); +} + +template +fvar trunc(fvar const& cr) { + using boost::math::trunc; + return fvar(trunc(static_cast::root_type>(cr))); +} + +template +long double truncl(fvar const& cr) { + using std::truncl; + return truncl(static_cast::root_type>(cr)); +} + +template +int itrunc(fvar const& cr) { + using boost::math::itrunc; + return itrunc(static_cast::root_type>(cr)); +} + +template +long long lltrunc(fvar const& cr) { + using boost::math::lltrunc; + return lltrunc(static_cast::root_type>(cr)); +} + +template +std::ostream& operator<<(std::ostream& out, fvar const& cr) { + out << "depth(" << cr.depth << ")(" << cr.v.front(); + for (size_t i = 1; i <= Order; ++i) + out << ',' << cr.v[i]; + return out << ')'; +} + +// Additional functions + +template +fvar acos(fvar const& cr) { + using std::acos; + using root_type = typename fvar::root_type; + constexpr size_t order = fvar::order_sum; + root_type const d0 = acos(static_cast(cr)); + BOOST_IF_CONSTEXPR (order == 0) + return fvar(d0); + else { + auto x = make_fvar(static_cast(cr)); + auto const d1 = sqrt((x *= x).negate() += 1).inverse().negate(); // acos'(x) = -1 / sqrt(1-x*x). + return cr.apply_coefficients(order, [&d0, &d1](size_t i) { return i ? d1[i - 1] / i : d0; }); + } +} + +template +fvar acosh(fvar const& cr) { + using boost::math::acosh; + using root_type = typename fvar::root_type; + constexpr size_t order = fvar::order_sum; + root_type const d0 = acosh(static_cast(cr)); + BOOST_IF_CONSTEXPR (order == 0) + return fvar(d0); + else { + auto x = make_fvar(static_cast(cr)); + auto const d1 = sqrt((x *= x) -= 1).inverse(); // acosh'(x) = 1 / sqrt(x*x-1). + return cr.apply_coefficients(order, [&d0, &d1](size_t i) { return i ? d1[i - 1] / i : d0; }); + } +} + +template +fvar asinh(fvar const& cr) { + using boost::math::asinh; + using root_type = typename fvar::root_type; + constexpr size_t order = fvar::order_sum; + root_type const d0 = asinh(static_cast(cr)); + BOOST_IF_CONSTEXPR (order == 0) + return fvar(d0); + else { + auto x = make_fvar(static_cast(cr)); + auto const d1 = sqrt((x *= x) += 1).inverse(); // asinh'(x) = 1 / sqrt(x*x+1). + return cr.apply_coefficients(order, [&d0, &d1](size_t i) { return i ? d1[i - 1] / i : d0; }); + } +} + +template +fvar atanh(fvar const& cr) { + using boost::math::atanh; + using root_type = typename fvar::root_type; + constexpr size_t order = fvar::order_sum; + root_type const d0 = atanh(static_cast(cr)); + BOOST_IF_CONSTEXPR (order == 0) + return fvar(d0); + else { + auto x = make_fvar(static_cast(cr)); + auto const d1 = ((x *= x).negate() += 1).inverse(); // atanh'(x) = 1 / (1-x*x) + return cr.apply_coefficients(order, [&d0, &d1](size_t i) { return i ? d1[i - 1] / i : d0; }); + } +} + +template +fvar cosh(fvar const& cr) { + BOOST_MATH_STD_USING + using root_type = typename fvar::root_type; + constexpr size_t order = fvar::order_sum; + root_type const d0 = cosh(static_cast(cr)); + BOOST_IF_CONSTEXPR (order == 0) + return fvar(d0); + else { + root_type const derivatives[2]{d0, sinh(static_cast(cr))}; + return cr.apply_derivatives(order, [&derivatives](size_t i) { return derivatives[i & 1]; }); + } +} + +template +fvar digamma(fvar const& cr) { + using boost::math::digamma; + using root_type = typename fvar::root_type; + constexpr size_t order = fvar::order_sum; + root_type const x = static_cast(cr); + root_type const d0 = digamma(x); + BOOST_IF_CONSTEXPR (order == 0) + return fvar(d0); + else { + static_assert(order <= static_cast((std::numeric_limits::max)()), + "order exceeds maximum derivative for boost::math::polygamma()."); + return cr.apply_derivatives( + order, [&x, &d0](size_t i) { return i ? boost::math::polygamma(static_cast(i), x) : d0; }); + } +} + +template +fvar erf(fvar const& cr) { + using boost::math::erf; + using root_type = typename fvar::root_type; + constexpr size_t order = fvar::order_sum; + root_type const d0 = erf(static_cast(cr)); + BOOST_IF_CONSTEXPR (order == 0) + return fvar(d0); + else { + auto x = make_fvar(static_cast(cr)); // d1 = 2/sqrt(pi)*exp(-x*x) + auto const d1 = 2 * constants::one_div_root_pi() * exp((x *= x).negate()); + return cr.apply_coefficients(order, [&d0, &d1](size_t i) { return i ? d1[i - 1] / i : d0; }); + } +} + +template +fvar erfc(fvar const& cr) { + using boost::math::erfc; + using root_type = typename fvar::root_type; + constexpr size_t order = fvar::order_sum; + root_type const d0 = erfc(static_cast(cr)); + BOOST_IF_CONSTEXPR (order == 0) + return fvar(d0); + else { + auto x = make_fvar(static_cast(cr)); // erfc'(x) = -erf'(x) + auto const d1 = -2 * constants::one_div_root_pi() * exp((x *= x).negate()); + return cr.apply_coefficients(order, [&d0, &d1](size_t i) { return i ? d1[i - 1] / i : d0; }); + } +} + +template +fvar lambert_w0(fvar const& cr) { + using std::exp; + using boost::math::lambert_w0; + using root_type = typename fvar::root_type; + constexpr size_t order = fvar::order_sum; + root_type derivatives[order + 1]; + *derivatives = lambert_w0(static_cast(cr)); + BOOST_IF_CONSTEXPR (order == 0) + return fvar(*derivatives); + else { + root_type const expw = exp(*derivatives); + derivatives[1] = 1 / (static_cast(cr) + expw); + BOOST_IF_CONSTEXPR (order == 1) + return cr.apply_derivatives_nonhorner(order, [&derivatives](size_t i) { return derivatives[i]; }); + else { + using diff_t = typename std::array::difference_type; + root_type d1powers = derivatives[1] * derivatives[1]; + root_type const x = derivatives[1] * expw; + derivatives[2] = d1powers * (-1 - x); + std::array coef{{-1, -1}}; // as in derivatives[2]. + for (size_t n = 3; n <= order; ++n) { + coef[n - 1] = coef[n - 2] * -static_cast(2 * n - 3); + for (size_t j = n - 2; j != 0; --j) + (coef[j] *= -static_cast(n - 1)) -= (n + j - 2) * coef[j - 1]; + coef[0] *= -static_cast(n - 1); + d1powers *= derivatives[1]; + derivatives[n] = + d1powers * std::accumulate(coef.crend() - diff_t(n - 1), + coef.crend(), + coef[n - 1], + [&x](root_type const& a, root_type const& b) { return a * x + b; }); + } + return cr.apply_derivatives_nonhorner(order, [&derivatives](size_t i) { return derivatives[i]; }); + } + } +} + +template +fvar lgamma(fvar const& cr) { + using std::lgamma; + using root_type = typename fvar::root_type; + constexpr size_t order = fvar::order_sum; + root_type const x = static_cast(cr); + root_type const d0 = lgamma(x); + BOOST_IF_CONSTEXPR (order == 0) + return fvar(d0); + else { + static_assert(order <= static_cast((std::numeric_limits::max)()) + 1, + "order exceeds maximum derivative for boost::math::polygamma()."); + return cr.apply_derivatives( + order, [&x, &d0](size_t i) { return i ? boost::math::polygamma(static_cast(i - 1), x) : d0; }); + } +} + +template +fvar sinc(fvar const& cr) { + if (cr != 0) + return sin(cr) / cr; + using root_type = typename fvar::root_type; + constexpr size_t order = fvar::order_sum; + root_type taylor[order + 1]{1}; // sinc(0) = 1 + BOOST_IF_CONSTEXPR (order == 0) + return fvar(*taylor); + else { + for (size_t n = 2; n <= order; n += 2) + taylor[n] = (1 - static_cast(n & 2)) / factorial(static_cast(n + 1)); + return cr.apply_coefficients_nonhorner(order, [&taylor](size_t i) { return taylor[i]; }); + } +} + +template +fvar sinh(fvar const& cr) { + BOOST_MATH_STD_USING + using root_type = typename fvar::root_type; + constexpr size_t order = fvar::order_sum; + root_type const d0 = sinh(static_cast(cr)); + BOOST_IF_CONSTEXPR (fvar::order_sum == 0) + return fvar(d0); + else { + root_type const derivatives[2]{d0, cosh(static_cast(cr))}; + return cr.apply_derivatives(order, [&derivatives](size_t i) { return derivatives[i & 1]; }); + } +} + +template +fvar tanh(fvar const& cr) { + fvar retval = exp(cr * 2); + fvar const denom = retval + 1; + (retval -= 1) /= denom; + return retval; +} + +template +fvar tgamma(fvar const& cr) { + using std::tgamma; + using root_type = typename fvar::root_type; + constexpr size_t order = fvar::order_sum; + BOOST_IF_CONSTEXPR (order == 0) + return fvar(tgamma(static_cast(cr))); + else { + if (cr < 0) + return constants::pi() / (sin(constants::pi() * cr) * tgamma(1 - cr)); + return exp(lgamma(cr)).set_root(tgamma(static_cast(cr))); + } +} + +} // namespace detail +} // namespace autodiff_v1 +} // namespace differentiation +} // namespace math +} // namespace boost + +namespace std { + +// boost::math::tools::digits() is handled by this std::numeric_limits<> specialization, +// and similarly for max_value, min_value, log_max_value, log_min_value, and epsilon. +template +class numeric_limits> + : public numeric_limits::root_type> { +}; + +} // namespace std + +namespace boost { +namespace math { +namespace tools { +namespace detail { + +template +using autodiff_fvar_type = differentiation::detail::fvar; + +template +using autodiff_root_type = typename autodiff_fvar_type::root_type; +} // namespace detail + +// See boost/math/tools/promotion.hpp +template +struct promote_args_2, + detail::autodiff_fvar_type> { + using type = detail::autodiff_fvar_type::type, +#ifndef BOOST_NO_CXX14_CONSTEXPR + (std::max)(Order0, Order1)>; +#else + Order0; +#endif +}; + +template +struct promote_args> { + using type = detail::autodiff_fvar_type::type, Order>; +}; + +template +struct promote_args_2, RealType1> { + using type = detail::autodiff_fvar_type::type, Order0>; +}; + +template +struct promote_args_2> { + using type = detail::autodiff_fvar_type::type, Order1>; +}; + +template +inline constexpr destination_t real_cast(detail::autodiff_fvar_type const& from_v) + noexcept(BOOST_MATH_IS_FLOAT(destination_t) && BOOST_MATH_IS_FLOAT(RealType)) { + return real_cast(static_cast>(from_v)); +} + +} // namespace tools + +namespace policies { + +template +using fvar_t = differentiation::detail::fvar; +template +struct evaluation, Policy> { + using type = fvar_t::type, Order>; +}; + +template +struct evaluation, Policy> { + using type = + fvar_t::type, Order>; +}; + +} // namespace policies +} // namespace math +} // namespace boost + +#ifdef BOOST_NO_CXX17_IF_CONSTEXPR +#include "autodiff_cpp11.hpp" +#endif + +#endif // BOOST_MATH_DIFFERENTIATION_AUTODIFF_HPP diff --git a/libcxx/src/third-party/boost/math/differentiation/autodiff_cpp11.hpp b/libcxx/src/third-party/boost/math/differentiation/autodiff_cpp11.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/differentiation/autodiff_cpp11.hpp @@ -0,0 +1,387 @@ +// Copyright Matthew Pulver 2018 - 2019. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// https://www.boost.org/LICENSE_1_0.txt) + +// Contributors: +// * Kedar R. Bhat - C++11 compatibility. + +// Notes: +// * Any changes to this file should always be downstream from autodiff.cpp. +// C++17 is a higher-level language and is easier to maintain. For example, a number of functions which are +// lucidly read in autodiff.cpp are forced to be split into multiple structs/functions in this file for +// C++11. +// * Use of typename RootType and SizeType is a hack to prevent Visual Studio 2015 from compiling functions +// that are never called, that would otherwise produce compiler errors. Also forces functions to be inline. + +#ifndef BOOST_MATH_DIFFERENTIATION_AUTODIFF_HPP +#error \ + "Do not #include this file directly. This should only be #included by autodiff.hpp for C++11 compatibility." +#endif + +#include +#include + +namespace boost { +namespace math { + +namespace mp = tools::meta_programming; + +namespace differentiation { +inline namespace autodiff_v1 { +namespace detail { + +template +fvar::fvar(root_type const& ca, bool const is_variable) { + fvar_cpp11(is_fvar{}, ca, is_variable); +} + +template +template +void fvar::fvar_cpp11(std::true_type, RootType const& ca, bool const is_variable) { + v.front() = RealType(ca, is_variable); + if (0 < Order) + std::fill(v.begin() + 1, v.end(), static_cast(0)); +} + +template +template +void fvar::fvar_cpp11(std::false_type, RootType const& ca, bool const is_variable) { + v.front() = ca; + if (0 < Order) { + v[1] = static_cast(static_cast(is_variable)); + if (1 < Order) + std::fill(v.begin() + 2, v.end(), static_cast(0)); + } +} + +template +template +get_type_at fvar::at_cpp11(std::true_type, + size_t order, + Orders...) const { + return v.at(order); +} + +template +template +get_type_at fvar::at_cpp11(std::false_type, + size_t order, + Orders... orders) const { + return v.at(order).at(orders...); +} + +// Can throw "std::out_of_range: array::at: __n (which is 7) >= _Nm (which is 7)" +template +template +get_type_at fvar::at(size_t order, Orders... orders) const { + return at_cpp11(std::integral_constant{}, order, orders...); +} + +template +constexpr T product(Ts...) { + return static_cast(1); +} + +template +constexpr T product(T factor, Ts... factors) { + return factor * product(factors...); +} + +// Can throw "std::out_of_range: array::at: __n (which is 7) >= _Nm (which is 7)" +template +template +get_type_at, sizeof...(Orders)> fvar::derivative( + Orders... orders) const { + static_assert(sizeof...(Orders) <= depth, + "Number of parameters to derivative(...) cannot exceed fvar::depth."); + return at(static_cast(orders)...) * + product(boost::math::factorial(static_cast(orders))...); +} + +template +class Curry { + Func const& f_; + size_t const i_; + + public: + template // typename SizeType to force inline constructor. + Curry(Func const& f, SizeType i) : f_(f), i_(static_cast(i)) {} + template + RootType operator()(Indices... indices) const { + using unsigned_t = typename std::make_unsigned::type...>::type; + return f_(i_, static_cast(indices)...); + } +}; + +template +template +promote, Fvar, Fvars...> fvar::apply_coefficients( + size_t const order, + Func const& f, + Fvar const& cr, + Fvars&&... fvars) const { + fvar const epsilon = fvar(*this).set_root(0); + size_t i = order < order_sum ? order : order_sum; + using return_type = promote, Fvar, Fvars...>; + return_type accumulator = cr.apply_coefficients( + order - i, Curry(f, i), std::forward(fvars)...); + while (i--) + (accumulator *= epsilon) += cr.apply_coefficients( + order - i, Curry(f, i), std::forward(fvars)...); + return accumulator; +} + +template +template +promote, Fvar, Fvars...> fvar::apply_coefficients_nonhorner( + size_t const order, + Func const& f, + Fvar const& cr, + Fvars&&... fvars) const { + fvar const epsilon = fvar(*this).set_root(0); + fvar epsilon_i = fvar(1); // epsilon to the power of i + using return_type = promote, Fvar, Fvars...>; + return_type accumulator = cr.apply_coefficients_nonhorner( + order, Curry(f, 0), std::forward(fvars)...); + size_t const i_max = order < order_sum ? order : order_sum; + for (size_t i = 1; i <= i_max; ++i) { + epsilon_i = epsilon_i.epsilon_multiply(i - 1, 0, epsilon, 1, 0); + accumulator += epsilon_i.epsilon_multiply( + i, + 0, + cr.apply_coefficients_nonhorner( + order - i, Curry(f, i), std::forward(fvars)...), + 0, + 0); + } + return accumulator; +} + +template +template +promote, Fvar, Fvars...> fvar::apply_derivatives( + size_t const order, + Func const& f, + Fvar const& cr, + Fvars&&... fvars) const { + fvar const epsilon = fvar(*this).set_root(0); + size_t i = order < order_sum ? order : order_sum; + using return_type = promote, Fvar, Fvars...>; + return_type accumulator = + cr.apply_derivatives( + order - i, Curry(f, i), std::forward(fvars)...) / + factorial(static_cast(i)); + while (i--) + (accumulator *= epsilon) += + cr.apply_derivatives( + order - i, Curry(f, i), std::forward(fvars)...) / + factorial(static_cast(i)); + return accumulator; +} + +template +template +promote, Fvar, Fvars...> fvar::apply_derivatives_nonhorner( + size_t const order, + Func const& f, + Fvar const& cr, + Fvars&&... fvars) const { + fvar const epsilon = fvar(*this).set_root(0); + fvar epsilon_i = fvar(1); // epsilon to the power of i + using return_type = promote, Fvar, Fvars...>; + return_type accumulator = cr.apply_derivatives_nonhorner( + order, Curry(f, 0), std::forward(fvars)...); + size_t const i_max = order < order_sum ? order : order_sum; + for (size_t i = 1; i <= i_max; ++i) { + epsilon_i = epsilon_i.epsilon_multiply(i - 1, 0, epsilon, 1, 0); + accumulator += epsilon_i.epsilon_multiply( + i, + 0, + cr.apply_derivatives_nonhorner( + order - i, Curry(f, i), std::forward(fvars)...) / + factorial(static_cast(i)), + 0, + 0); + } + return accumulator; +} + +template +template +fvar fvar::epsilon_multiply_cpp11(std::true_type, + SizeType z0, + size_t isum0, + fvar const& cr, + size_t z1, + size_t isum1) const { + size_t const m0 = order_sum + isum0 < Order + z0 ? Order + z0 - (order_sum + isum0) : 0; + size_t const m1 = order_sum + isum1 < Order + z1 ? Order + z1 - (order_sum + isum1) : 0; + size_t const i_max = m0 + m1 < Order ? Order - (m0 + m1) : 0; + fvar retval = fvar(); + for (size_t i = 0, j = Order; i <= i_max; ++i, --j) + retval.v[j] = epsilon_inner_product(z0, isum0, m0, cr, z1, isum1, m1, j); + return retval; +} + +template +template +fvar fvar::epsilon_multiply_cpp11(std::false_type, + SizeType z0, + size_t isum0, + fvar const& cr, + size_t z1, + size_t isum1) const { + using ssize_t = typename std::make_signed::type; + RealType const zero(0); + size_t const m0 = order_sum + isum0 < Order + z0 ? Order + z0 - (order_sum + isum0) : 0; + size_t const m1 = order_sum + isum1 < Order + z1 ? Order + z1 - (order_sum + isum1) : 0; + size_t const i_max = m0 + m1 < Order ? Order - (m0 + m1) : 0; + fvar retval = fvar(); + for (size_t i = 0, j = Order; i <= i_max; ++i, --j) + retval.v[j] = std::inner_product( + v.cbegin() + ssize_t(m0), v.cend() - ssize_t(i + m1), cr.v.crbegin() + ssize_t(i + m0), zero); + return retval; +} + +template +fvar fvar::epsilon_multiply(size_t z0, + size_t isum0, + fvar const& cr, + size_t z1, + size_t isum1) const { + return epsilon_multiply_cpp11(is_fvar{}, z0, isum0, cr, z1, isum1); +} + +template +template +fvar fvar::epsilon_multiply_cpp11(std::true_type, + SizeType z0, + size_t isum0, + root_type const& ca) const { + fvar retval(*this); + size_t const m0 = order_sum + isum0 < Order + z0 ? Order + z0 - (order_sum + isum0) : 0; + for (size_t i = m0; i <= Order; ++i) + retval.v[i] = retval.v[i].epsilon_multiply(z0, isum0 + i, ca); + return retval; +} + +template +template +fvar fvar::epsilon_multiply_cpp11(std::false_type, + SizeType z0, + size_t isum0, + root_type const& ca) const { + fvar retval(*this); + size_t const m0 = order_sum + isum0 < Order + z0 ? Order + z0 - (order_sum + isum0) : 0; + for (size_t i = m0; i <= Order; ++i) + if (retval.v[i] != static_cast(0)) + retval.v[i] *= ca; + return retval; +} + +template +fvar fvar::epsilon_multiply(size_t z0, + size_t isum0, + root_type const& ca) const { + return epsilon_multiply_cpp11(is_fvar{}, z0, isum0, ca); +} + +template +template +fvar& fvar::multiply_assign_by_root_type_cpp11(std::true_type, + bool is_root, + RootType const& ca) { + auto itr = v.begin(); + itr->multiply_assign_by_root_type(is_root, ca); + for (++itr; itr != v.end(); ++itr) + itr->multiply_assign_by_root_type(false, ca); + return *this; +} + +template +template +fvar& fvar::multiply_assign_by_root_type_cpp11(std::false_type, + bool is_root, + RootType const& ca) { + auto itr = v.begin(); + if (is_root || *itr != 0) + *itr *= ca; // Skip multiplication of 0 by ca=inf to avoid nan, except when is_root. + for (++itr; itr != v.end(); ++itr) + if (*itr != 0) + *itr *= ca; + return *this; +} + +template +fvar& fvar::multiply_assign_by_root_type(bool is_root, + root_type const& ca) { + return multiply_assign_by_root_type_cpp11(is_fvar{}, is_root, ca); +} + +template +template +fvar& fvar::negate_cpp11(std::true_type, RootType const&) { + std::for_each(v.begin(), v.end(), [](RealType& r) { r.negate(); }); + return *this; +} + +template +template +fvar& fvar::negate_cpp11(std::false_type, RootType const&) { + std::for_each(v.begin(), v.end(), [](RealType& a) { a = -a; }); + return *this; +} + +template +fvar& fvar::negate() { + return negate_cpp11(is_fvar{}, static_cast(*this)); +} + +template +template +fvar& fvar::set_root_cpp11(std::true_type, RootType const& root) { + v.front().set_root(root); + return *this; +} + +template +template +fvar& fvar::set_root_cpp11(std::false_type, RootType const& root) { + v.front() = root; + return *this; +} + +template +fvar& fvar::set_root(root_type const& root) { + return set_root_cpp11(is_fvar{}, root); +} + +template +auto make_fvar_for_tuple(mp::index_sequence, RealType const& ca) + -> decltype(make_fvar::value..., Order>(ca)) { + return make_fvar::value..., Order>(ca); +} + +template +auto make_ftuple_impl(mp::index_sequence, RealTypes const&... ca) + -> decltype(std::make_tuple(make_fvar_for_tuple(mp::make_index_sequence{}, + ca)...)) { + return std::make_tuple(make_fvar_for_tuple(mp::make_index_sequence{}, ca)...); +} + +} // namespace detail + +template +auto make_ftuple(RealTypes const&... ca) + -> decltype(detail::make_ftuple_impl(mp::index_sequence_for{}, + ca...)) { + static_assert(sizeof...(Orders) == sizeof...(RealTypes), + "Number of Orders must match number of function parameters."); + return detail::make_ftuple_impl(mp::index_sequence_for{}, ca...); +} + +} // namespace autodiff_v1 +} // namespace differentiation +} // namespace math +} // namespace boost diff --git a/libcxx/src/third-party/boost/math/differentiation/finite_difference.hpp b/libcxx/src/third-party/boost/math/differentiation/finite_difference.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/differentiation/finite_difference.hpp @@ -0,0 +1,266 @@ +// (C) Copyright Nick Thompson 2018. +// 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_DIFFERENTIATION_FINITE_DIFFERENCE_HPP +#define BOOST_MATH_DIFFERENTIATION_FINITE_DIFFERENCE_HPP + +/* + * Performs numerical differentiation by finite-differences. + * + * All numerical differentiation using finite-differences are ill-conditioned, and these routines are no exception. + * A simple argument demonstrates that the error is unbounded as h->0. + * Take the one sides finite difference formula f'(x) = (f(x+h)-f(x))/h. + * The evaluation of f induces an error as well as the error from the finite-difference approximation, giving + * |f'(x) - (f(x+h) -f(x))/h| < h|f''(x)|/2 + (|f(x)|+|f(x+h)|)eps/h =: g(h), where eps is the unit roundoff for the type. + * It is reasonable to choose h in a way that minimizes the maximum error bound g(h). + * The value of h that minimizes g is h = sqrt(2eps(|f(x)| + |f(x+h)|)/|f''(x)|), and for this value of h the error bound is + * sqrt(2eps(|f(x+h) +f(x)||f''(x)|)). + * In fact it is not necessary to compute the ratio (|f(x+h)| + |f(x)|)/|f''(x)|; the error bound of ~\sqrt{\epsilon} still holds if we set it to one. + * + * + * For more details on this method of analysis, see + * + * http://www.uio.no/studier/emner/matnat/math/MAT-INF1100/h08/kompendiet/diffint.pdf + * http://web.archive.org/web/20150420195907/http://www.uio.no/studier/emner/matnat/math/MAT-INF1100/h08/kompendiet/diffint.pdf + * + * + * It can be shown on general grounds that when choosing the optimal h, the maximum error in f'(x) is ~(|f(x)|eps)^k/k+1|f^(k-1)(x)|^1/k+1. + * From this we can see that full precision can be recovered in the limit k->infinity. + * + * References: + * + * 1) Fornberg, Bengt. "Generation of finite difference formulas on arbitrarily spaced grids." Mathematics of computation 51.184 (1988): 699-706. + * + * + * The second algorithm, the complex step derivative, is not ill-conditioned. + * However, it requires that your function can be evaluated at complex arguments. + * The idea is that f(x+ih) = f(x) +ihf'(x) - h^2f''(x) + ... so f'(x) \approx Im[f(x+ih)]/h. + * No subtractive cancellation occurs. The error is ~ eps|f'(x)| + eps^2|f'''(x)|/6; hard to beat that. + * + * References: + * + * 1) Squire, William, and George Trapp. "Using complex variables to estimate derivatives of real functions." Siam Review 40.1 (1998): 110-112. + */ + +#include +#include + +namespace boost{ namespace math{ namespace differentiation { + +namespace detail { + template + Real make_xph_representable(Real x, Real h) + { + using std::numeric_limits; + // Redefine h so that x + h is representable. Not using this trick leads to large error. + // The compiler flag -ffast-math evaporates these operations . . . + Real temp = x + h; + h = temp - x; + // Handle the case x + h == x: + if (h == 0) + { + h = boost::math::nextafter(x, (numeric_limits::max)()) - x; + } + return h; + } +} + +template +Real complex_step_derivative(const F f, Real x) +{ + // Is it really this easy? Yes. + // Note that some authors recommend taking the stepsize h to be smaller than epsilon(), some recommending use of the min(). + // This idea was tested over a few billion test cases and found the make the error *much* worse. + // Even 2eps and eps/2 made the error worse, which was surprising. + using std::complex; + using std::numeric_limits; + constexpr const Real step = (numeric_limits::epsilon)(); + constexpr const Real inv_step = 1/(numeric_limits::epsilon)(); + return f(complex(x, step)).imag()*inv_step; +} + +namespace detail { + + template + struct fd_tag {}; + + template + Real finite_difference_derivative(const F f, Real x, Real* error, const fd_tag<1>&) + { + using std::sqrt; + using std::pow; + using std::abs; + using std::numeric_limits; + + const Real eps = (numeric_limits::epsilon)(); + // Error bound ~eps^1/2 + // Note that this estimate of h differs from the best estimate by a factor of sqrt((|f(x)| + |f(x+h)|)/|f''(x)|). + // Since this factor is invariant under the scaling f -> kf, then we are somewhat justified in approximating it by 1. + // This approximation will get better as we move to higher orders of accuracy. + Real h = 2 * sqrt(eps); + h = detail::make_xph_representable(x, h); + + Real yh = f(x + h); + Real y0 = f(x); + Real diff = yh - y0; + if (error) + { + Real ym = f(x - h); + Real ypph = abs(yh - 2 * y0 + ym) / h; + // h*|f''(x)|*0.5 + (|f(x+h)+|f(x)|)*eps/h + *error = ypph / 2 + (abs(yh) + abs(y0))*eps / h; + } + return diff / h; + } + + template + Real finite_difference_derivative(const F f, Real x, Real* error, const fd_tag<2>&) + { + using std::sqrt; + using std::pow; + using std::abs; + using std::numeric_limits; + + const Real eps = (numeric_limits::epsilon)(); + // Error bound ~eps^2/3 + // See the previous discussion to understand determination of h and the error bound. + // Series[(f[x+h] - f[x-h])/(2*h), {h, 0, 4}] + Real h = pow(3 * eps, static_cast(1) / static_cast(3)); + h = detail::make_xph_representable(x, h); + + Real yh = f(x + h); + Real ymh = f(x - h); + Real diff = yh - ymh; + if (error) + { + Real yth = f(x + 2 * h); + Real ymth = f(x - 2 * h); + *error = eps * (abs(yh) + abs(ymh)) / (2 * h) + abs((yth - ymth) / 2 - diff) / (6 * h); + } + + return diff / (2 * h); + } + + template + Real finite_difference_derivative(const F f, Real x, Real* error, const fd_tag<4>&) + { + using std::sqrt; + using std::pow; + using std::abs; + using std::numeric_limits; + + const Real eps = (numeric_limits::epsilon)(); + // Error bound ~eps^4/5 + Real h = pow(11.25*eps, static_cast(1) / static_cast(5)); + h = detail::make_xph_representable(x, h); + Real ymth = f(x - 2 * h); + Real yth = f(x + 2 * h); + Real yh = f(x + h); + Real ymh = f(x - h); + Real y2 = ymth - yth; + Real y1 = yh - ymh; + if (error) + { + // Mathematica code to extract the remainder: + // Series[(f[x-2*h]+ 8*f[x+h] - 8*f[x-h] - f[x+2*h])/(12*h), {h, 0, 7}] + Real y_three_h = f(x + 3 * h); + Real y_m_three_h = f(x - 3 * h); + // Error from fifth derivative: + *error = abs((y_three_h - y_m_three_h) / 2 + 2 * (ymth - yth) + 5 * (yh - ymh) / 2) / (30 * h); + // Error from function evaluation: + *error += eps * (abs(yth) + abs(ymth) + 8 * (abs(ymh) + abs(yh))) / (12 * h); + } + return (y2 + 8 * y1) / (12 * h); + } + + template + Real finite_difference_derivative(const F f, Real x, Real* error, const fd_tag<6>&) + { + using std::sqrt; + using std::pow; + using std::abs; + using std::numeric_limits; + + const Real eps = (numeric_limits::epsilon)(); + // Error bound ~eps^6/7 + // Error: h^6f^(7)(x)/140 + 5|f(x)|eps/h + Real h = pow(eps / 168, static_cast(1) / static_cast(7)); + h = detail::make_xph_representable(x, h); + + Real yh = f(x + h); + Real ymh = f(x - h); + Real y1 = yh - ymh; + Real y2 = f(x - 2 * h) - f(x + 2 * h); + Real y3 = f(x + 3 * h) - f(x - 3 * h); + + if (error) + { + // Mathematica code to generate fd scheme for 7th derivative: + // Sum[(-1)^i*Binomial[7, i]*(f[x+(3-i)*h] + f[x+(4-i)*h])/2, {i, 0, 7}] + // Mathematica to demonstrate that this is a finite difference formula for 7th derivative: + // Series[(f[x+4*h]-f[x-4*h] + 6*(f[x-3*h] - f[x+3*h]) + 14*(f[x-h] - f[x+h] + f[x+2*h] - f[x-2*h]))/2, {h, 0, 15}] + Real y7 = (f(x + 4 * h) - f(x - 4 * h) - 6 * y3 - 14 * y1 - 14 * y2) / 2; + *error = abs(y7) / (140 * h) + 5 * (abs(yh) + abs(ymh))*eps / h; + } + return (y3 + 9 * y2 + 45 * y1) / (60 * h); + } + + template + Real finite_difference_derivative(const F f, Real x, Real* error, const fd_tag<8>&) + { + using std::sqrt; + using std::pow; + using std::abs; + using std::numeric_limits; + + const Real eps = (numeric_limits::epsilon)(); + // Error bound ~eps^8/9. + // In double precision, we only expect to lose two digits of precision while using this formula, at the cost of 8 function evaluations. + // Error: h^8|f^(9)(x)|/630 + 7|f(x)|eps/h assuming 7 unstabilized additions. + // Mathematica code to get the error: + // Series[(f[x+h]-f[x-h])*(4/5) + (1/5)*(f[x-2*h] - f[x+2*h]) + (4/105)*(f[x+3*h] - f[x-3*h]) + (1/280)*(f[x-4*h] - f[x+4*h]), {h, 0, 9}] + // If we used Kahan summation, we could get the max error down to h^8|f^(9)(x)|/630 + |f(x)|eps/h. + Real h = pow(551.25*eps, static_cast(1) / static_cast(9)); + h = detail::make_xph_representable(x, h); + + Real yh = f(x + h); + Real ymh = f(x - h); + Real y1 = yh - ymh; + Real y2 = f(x - 2 * h) - f(x + 2 * h); + Real y3 = f(x + 3 * h) - f(x - 3 * h); + Real y4 = f(x - 4 * h) - f(x + 4 * h); + + Real tmp1 = 3 * y4 / 8 + 4 * y3; + Real tmp2 = 21 * y2 + 84 * y1; + + if (error) + { + // Mathematica code to generate fd scheme for 7th derivative: + // Sum[(-1)^i*Binomial[9, i]*(f[x+(4-i)*h] + f[x+(5-i)*h])/2, {i, 0, 9}] + // Mathematica to demonstrate that this is a finite difference formula for 7th derivative: + // Series[(f[x+5*h]-f[x- 5*h])/2 + 4*(f[x-4*h] - f[x+4*h]) + 27*(f[x+3*h] - f[x-3*h])/2 + 24*(f[x-2*h] - f[x+2*h]) + 21*(f[x+h] - f[x-h]), {h, 0, 15}] + Real f9 = (f(x + 5 * h) - f(x - 5 * h)) / 2 + 4 * y4 + 27 * y3 / 2 + 24 * y2 + 21 * y1; + *error = abs(f9) / (630 * h) + 7 * (abs(yh) + abs(ymh))*eps / h; + } + return (tmp1 + tmp2) / (105 * h); + } + + template + Real finite_difference_derivative(const F, Real, Real*, const tag&) + { + // Always fails, but condition is template-arg-dependent so only evaluated if we get instantiated. + static_assert(sizeof(Real) == 0, "Finite difference not implemented for this order: try 1, 2, 4, 6 or 8"); + } + +} + +template +inline Real finite_difference_derivative(const F f, Real x, Real* error = nullptr) +{ + return detail::finite_difference_derivative(f, x, error, detail::fd_tag()); +} + +}}} // namespaces +#endif diff --git a/libcxx/src/third-party/boost/math/differentiation/lanczos_smoothing.hpp b/libcxx/src/third-party/boost/math/differentiation/lanczos_smoothing.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/differentiation/lanczos_smoothing.hpp @@ -0,0 +1,582 @@ +// (C) Copyright Nick Thompson 2019. +// 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_DIFFERENTIATION_LANCZOS_SMOOTHING_HPP +#define BOOST_MATH_DIFFERENTIATION_LANCZOS_SMOOTHING_HPP +#include // for std::abs +#include +#include // to nan initialize +#include +#include +#include +#include +#include + +namespace boost::math::differentiation { + +namespace detail { +template +class discrete_legendre { + public: + explicit discrete_legendre(std::size_t n, Real x) : m_n{n}, m_r{2}, m_x{x}, + m_qrm2{1}, m_qrm1{x}, + m_qrm2p{0}, m_qrm1p{1}, + m_qrm2pp{0}, m_qrm1pp{0} + { + using std::abs; + BOOST_MATH_ASSERT_MSG(abs(m_x) <= 1, "Three term recurrence is stable only for |x| <=1."); + // The integer n indexes a family of discrete Legendre polynomials indexed by k <= 2*n + } + + Real norm_sq(int r) const + { + Real prod = Real(2) / Real(2 * r + 1); + for (int k = -r; k <= r; ++k) { + prod *= Real(2 * m_n + 1 + k) / Real(2 * m_n); + } + return prod; + } + + Real next() + { + Real N = 2 * m_n + 1; + Real num = (m_r - 1) * (N * N - (m_r - 1) * (m_r - 1)) * m_qrm2; + Real tmp = (2 * m_r - 1) * m_x * m_qrm1 - num / Real(4 * m_n * m_n); + m_qrm2 = m_qrm1; + m_qrm1 = tmp / m_r; + ++m_r; + return m_qrm1; + } + + Real next_prime() + { + Real N = 2 * m_n + 1; + Real s = (m_r - 1) * (N * N - (m_r - 1) * (m_r - 1)) / Real(4 * m_n * m_n); + Real tmp1 = ((2 * m_r - 1) * m_x * m_qrm1 - s * m_qrm2) / m_r; + Real tmp2 = ((2 * m_r - 1) * (m_qrm1 + m_x * m_qrm1p) - s * m_qrm2p) / m_r; + m_qrm2 = m_qrm1; + m_qrm1 = tmp1; + m_qrm2p = m_qrm1p; + m_qrm1p = tmp2; + ++m_r; + return m_qrm1p; + } + + Real next_dbl_prime() + { + Real N = 2*m_n + 1; + Real trm1 = 2*m_r - 1; + Real s = (m_r - 1) * (N * N - (m_r - 1) * (m_r - 1)) / Real(4 * m_n * m_n); + Real rqrpp = 2*trm1*m_qrm1p + trm1*m_x*m_qrm1pp - s*m_qrm2pp; + Real tmp1 = ((2 * m_r - 1) * m_x * m_qrm1 - s * m_qrm2) / m_r; + Real tmp2 = ((2 * m_r - 1) * (m_qrm1 + m_x * m_qrm1p) - s * m_qrm2p) / m_r; + m_qrm2 = m_qrm1; + m_qrm1 = tmp1; + m_qrm2p = m_qrm1p; + m_qrm1p = tmp2; + m_qrm2pp = m_qrm1pp; + m_qrm1pp = rqrpp/m_r; + ++m_r; + return m_qrm1pp; + } + + Real operator()(Real x, std::size_t k) + { + BOOST_MATH_ASSERT_MSG(k <= 2 * m_n, "r <= 2n is required."); + if (k == 0) + { + return 1; + } + if (k == 1) + { + return x; + } + Real qrm2 = 1; + Real qrm1 = x; + Real N = 2 * m_n + 1; + for (std::size_t r = 2; r <= k; ++r) { + Real num = (r - 1) * (N * N - (r - 1) * (r - 1)) * qrm2; + Real tmp = (2 * r - 1) * x * qrm1 - num / Real(4 * m_n * m_n); + qrm2 = qrm1; + qrm1 = tmp / r; + } + return qrm1; + } + + Real prime(Real x, std::size_t k) { + BOOST_MATH_ASSERT_MSG(k <= 2 * m_n, "r <= 2n is required."); + if (k == 0) { + return 0; + } + if (k == 1) { + return 1; + } + Real qrm2 = 1; + Real qrm1 = x; + Real qrm2p = 0; + Real qrm1p = 1; + Real N = 2 * m_n + 1; + for (std::size_t r = 2; r <= k; ++r) { + Real s = + (r - 1) * (N * N - (r - 1) * (r - 1)) / Real(4 * m_n * m_n); + Real tmp1 = ((2 * r - 1) * x * qrm1 - s * qrm2) / r; + Real tmp2 = ((2 * r - 1) * (qrm1 + x * qrm1p) - s * qrm2p) / r; + qrm2 = qrm1; + qrm1 = tmp1; + qrm2p = qrm1p; + qrm1p = tmp2; + } + return qrm1p; + } + + private: + std::size_t m_n; + std::size_t m_r; + Real m_x; + Real m_qrm2; + Real m_qrm1; + Real m_qrm2p; + Real m_qrm1p; + Real m_qrm2pp; + Real m_qrm1pp; +}; + +template +std::vector interior_velocity_filter(std::size_t n, std::size_t p) { + auto dlp = discrete_legendre(n, 0); + std::vector coeffs(p+1); + coeffs[1] = 1/dlp.norm_sq(1); + for (std::size_t l = 3; l < p + 1; l += 2) + { + dlp.next_prime(); + coeffs[l] = dlp.next_prime()/ dlp.norm_sq(l); + } + + // We could make the filter length n, as f[0] = 0, + // but that'd make the indexing awkward when applying the filter. + std::vector f(n + 1); + // This value should never be read, but this is the correct value *if it is read*. + // Hmm, should it be a nan then? I'm not gonna agonize. + f[0] = 0; + for (std::size_t j = 1; j < f.size(); ++j) + { + Real arg = Real(j) / Real(n); + dlp = discrete_legendre(n, arg); + f[j] = coeffs[1]*arg; + for (std::size_t l = 3; l <= p; l += 2) + { + dlp.next(); + f[j] += coeffs[l]*dlp.next(); + } + f[j] /= (n * n); + } + return f; +} + +template +std::vector boundary_velocity_filter(std::size_t n, std::size_t p, int64_t s) +{ + std::vector coeffs(p+1, std::numeric_limits::quiet_NaN()); + Real sn = Real(s) / Real(n); + auto dlp = discrete_legendre(n, sn); + coeffs[0] = 0; + coeffs[1] = 1/dlp.norm_sq(1); + for (std::size_t l = 2; l < p + 1; ++l) + { + // Calculation of the norms is common to all filters, + // so it seems like an obvious optimization target. + // I tried this: The spent in computing the norms time is not negligible, + // but still a small fraction of the total compute time. + // Hence I'm not refactoring out these norm calculations. + coeffs[l] = dlp.next_prime()/ dlp.norm_sq(l); + } + + std::vector f(2*n + 1); + for (std::size_t k = 0; k < f.size(); ++k) + { + Real j = Real(k) - Real(n); + Real arg = j/Real(n); + dlp = discrete_legendre(n, arg); + f[k] = coeffs[1]*arg; + for (std::size_t l = 2; l <= p; ++l) + { + f[k] += coeffs[l]*dlp.next(); + } + f[k] /= (n * n); + } + return f; +} + +template +std::vector acceleration_filter(std::size_t n, std::size_t p, int64_t s) +{ + BOOST_MATH_ASSERT_MSG(p <= 2*n, "Approximation order must be <= 2*n"); + BOOST_MATH_ASSERT_MSG(p > 2, "Approximation order must be > 2"); + + std::vector coeffs(p+1, std::numeric_limits::quiet_NaN()); + Real sn = Real(s) / Real(n); + auto dlp = discrete_legendre(n, sn); + coeffs[0] = 0; + coeffs[1] = 0; + for (std::size_t l = 2; l < p + 1; ++l) + { + coeffs[l] = dlp.next_dbl_prime()/ dlp.norm_sq(l); + } + + std::vector f(2*n + 1, 0); + for (std::size_t k = 0; k < f.size(); ++k) + { + Real j = Real(k) - Real(n); + Real arg = j/Real(n); + dlp = discrete_legendre(n, arg); + for (std::size_t l = 2; l <= p; ++l) + { + f[k] += coeffs[l]*dlp.next(); + } + f[k] /= (n * n * n); + } + return f; +} + + +} // namespace detail + +template +class discrete_lanczos_derivative { +public: + discrete_lanczos_derivative(Real const & spacing, + std::size_t n = 18, + std::size_t approximation_order = 3) + : m_dt{spacing} + { + static_assert(!std::is_integral_v, + "Spacing must be a floating point type."); + BOOST_MATH_ASSERT_MSG(spacing > 0, + "Spacing between samples must be > 0."); + + if constexpr (order == 1) + { + BOOST_MATH_ASSERT_MSG(approximation_order <= 2 * n, + "The approximation order must be <= 2n"); + BOOST_MATH_ASSERT_MSG(approximation_order >= 2, + "The approximation order must be >= 2"); + + if constexpr (std::is_same_v || std::is_same_v) + { + auto interior = detail::interior_velocity_filter(n, approximation_order); + m_f.resize(interior.size()); + for (std::size_t j = 0; j < interior.size(); ++j) + { + m_f[j] = static_cast(interior[j])/m_dt; + } + } + else + { + m_f = detail::interior_velocity_filter(n, approximation_order); + for (auto & x : m_f) + { + x /= m_dt; + } + } + + m_boundary_filters.resize(n); + // This for loop is a natural candidate for parallelization. + // But does it matter? Probably not. + for (std::size_t i = 0; i < n; ++i) + { + if constexpr (std::is_same_v || std::is_same_v) + { + int64_t s = static_cast(i) - static_cast(n); + auto bf = detail::boundary_velocity_filter(n, approximation_order, s); + m_boundary_filters[i].resize(bf.size()); + for (std::size_t j = 0; j < bf.size(); ++j) + { + m_boundary_filters[i][j] = static_cast(bf[j])/m_dt; + } + } + else + { + int64_t s = static_cast(i) - static_cast(n); + m_boundary_filters[i] = detail::boundary_velocity_filter(n, approximation_order, s); + for (auto & bf : m_boundary_filters[i]) + { + bf /= m_dt; + } + } + } + } + else if constexpr (order == 2) + { + // High precision isn't warranted for small p; only for large p. + // (The computation appears stable for large n.) + // But given that the filters are reusable for many vectors, + // it's better to do a high precision computation and then cast back, + // since the resulting cost is a factor of 2, and the cost of the filters not working is hours of debugging. + if constexpr (std::is_same_v || std::is_same_v) + { + auto f = detail::acceleration_filter(n, approximation_order, 0); + m_f.resize(n+1); + for (std::size_t i = 0; i < m_f.size(); ++i) + { + m_f[i] = static_cast(f[i+n])/(m_dt*m_dt); + } + m_boundary_filters.resize(n); + for (std::size_t i = 0; i < n; ++i) + { + int64_t s = static_cast(i) - static_cast(n); + auto bf = detail::acceleration_filter(n, approximation_order, s); + m_boundary_filters[i].resize(bf.size()); + for (std::size_t j = 0; j < bf.size(); ++j) + { + m_boundary_filters[i][j] = static_cast(bf[j])/(m_dt*m_dt); + } + } + } + else + { + // Given that the purpose is denoising, for higher precision calculations, + // the default precision should be fine. + auto f = detail::acceleration_filter(n, approximation_order, 0); + m_f.resize(n+1); + for (std::size_t i = 0; i < m_f.size(); ++i) + { + m_f[i] = f[i+n]/(m_dt*m_dt); + } + m_boundary_filters.resize(n); + for (std::size_t i = 0; i < n; ++i) + { + int64_t s = static_cast(i) - static_cast(n); + m_boundary_filters[i] = detail::acceleration_filter(n, approximation_order, s); + for (auto & bf : m_boundary_filters[i]) + { + bf /= (m_dt*m_dt); + } + } + } + } + else + { + BOOST_MATH_ASSERT_MSG(false, "Derivatives of order 3 and higher are not implemented."); + } + } + + Real get_spacing() const + { + return m_dt; + } + + template + Real operator()(RandomAccessContainer const & v, std::size_t i) const + { + static_assert(std::is_same_v, + "The type of the values in the vector provided does not match the type in the filters."); + + BOOST_MATH_ASSERT_MSG(std::size(v) >= m_boundary_filters[0].size(), + "Vector must be at least as long as the filter length"); + + if constexpr (order==1) + { + if (i >= m_f.size() - 1 && i <= std::size(v) - m_f.size()) + { + // The filter has length >= 1: + Real dvdt = m_f[1] * (v[i + 1] - v[i - 1]); + for (std::size_t j = 2; j < m_f.size(); ++j) + { + dvdt += m_f[j] * (v[i + j] - v[i - j]); + } + return dvdt; + } + + // m_f.size() = N+1 + if (i < m_f.size() - 1) + { + auto &bf = m_boundary_filters[i]; + Real dvdt = bf[0]*v[0]; + for (std::size_t j = 1; j < bf.size(); ++j) + { + dvdt += bf[j] * v[j]; + } + return dvdt; + } + + if (i > std::size(v) - m_f.size() && i < std::size(v)) + { + int k = std::size(v) - 1 - i; + auto &bf = m_boundary_filters[k]; + Real dvdt = bf[0]*v[std::size(v)-1]; + for (std::size_t j = 1; j < bf.size(); ++j) + { + dvdt += bf[j] * v[std::size(v) - 1 - j]; + } + return -dvdt; + } + } + else if constexpr (order==2) + { + if (i >= m_f.size() - 1 && i <= std::size(v) - m_f.size()) + { + Real d2vdt2 = m_f[0]*v[i]; + for (std::size_t j = 1; j < m_f.size(); ++j) + { + d2vdt2 += m_f[j] * (v[i + j] + v[i - j]); + } + return d2vdt2; + } + + // m_f.size() = N+1 + if (i < m_f.size() - 1) + { + auto &bf = m_boundary_filters[i]; + Real d2vdt2 = bf[0]*v[0]; + for (std::size_t j = 1; j < bf.size(); ++j) + { + d2vdt2 += bf[j] * v[j]; + } + return d2vdt2; + } + + if (i > std::size(v) - m_f.size() && i < std::size(v)) + { + int k = std::size(v) - 1 - i; + auto &bf = m_boundary_filters[k]; + Real d2vdt2 = bf[0] * v[std::size(v) - 1]; + for (std::size_t j = 1; j < bf.size(); ++j) + { + d2vdt2 += bf[j] * v[std::size(v) - 1 - j]; + } + return d2vdt2; + } + } + + // OOB access: + std::string msg = "Out of bounds access in Lanczos derivative."; + msg += "Input vector has length " + std::to_string(std::size(v)) + ", but user requested access at index " + std::to_string(i) + "."; + throw std::out_of_range(msg); + return std::numeric_limits::quiet_NaN(); + } + + template + void operator()(RandomAccessContainer const & v, RandomAccessContainer & w) const + { + static_assert(std::is_same_v, + "The type of the values in the vector provided does not match the type in the filters."); + if (&w[0] == &v[0]) + { + throw std::logic_error("This transform cannot be performed in-place."); + } + + if (std::size(v) < m_boundary_filters[0].size()) + { + std::string msg = "The input vector must be at least as long as the filter length. "; + msg += "The input vector has length = " + std::to_string(std::size(v)) + ", the filter has length " + std::to_string(m_boundary_filters[0].size()); + throw std::length_error(msg); + } + + if (std::size(w) < std::size(v)) + { + std::string msg = "The output vector (containing the derivative) must be at least as long as the input vector."; + msg += "The output vector has length = " + std::to_string(std::size(w)) + ", the input vector has length " + std::to_string(std::size(v)); + throw std::length_error(msg); + } + + if constexpr (order==1) + { + for (std::size_t i = 0; i < m_f.size() - 1; ++i) + { + auto &bf = m_boundary_filters[i]; + Real dvdt = bf[0] * v[0]; + for (std::size_t j = 1; j < bf.size(); ++j) + { + dvdt += bf[j] * v[j]; + } + w[i] = dvdt; + } + + for(std::size_t i = m_f.size() - 1; i <= std::size(v) - m_f.size(); ++i) + { + Real dvdt = m_f[1] * (v[i + 1] - v[i - 1]); + for (std::size_t j = 2; j < m_f.size(); ++j) + { + dvdt += m_f[j] *(v[i + j] - v[i - j]); + } + w[i] = dvdt; + } + + + for(std::size_t i = std::size(v) - m_f.size() + 1; i < std::size(v); ++i) + { + int k = std::size(v) - 1 - i; + auto &f = m_boundary_filters[k]; + Real dvdt = f[0] * v[std::size(v) - 1];; + for (std::size_t j = 1; j < f.size(); ++j) + { + dvdt += f[j] * v[std::size(v) - 1 - j]; + } + w[i] = -dvdt; + } + } + else if constexpr (order==2) + { + // m_f.size() = N+1 + for (std::size_t i = 0; i < m_f.size() - 1; ++i) + { + auto &bf = m_boundary_filters[i]; + Real d2vdt2 = 0; + for (std::size_t j = 0; j < bf.size(); ++j) + { + d2vdt2 += bf[j] * v[j]; + } + w[i] = d2vdt2; + } + + for (std::size_t i = m_f.size() - 1; i <= std::size(v) - m_f.size(); ++i) + { + Real d2vdt2 = m_f[0]*v[i]; + for (std::size_t j = 1; j < m_f.size(); ++j) + { + d2vdt2 += m_f[j] * (v[i + j] + v[i - j]); + } + w[i] = d2vdt2; + } + + for (std::size_t i = std::size(v) - m_f.size() + 1; i < std::size(v); ++i) + { + int k = std::size(v) - 1 - i; + auto &bf = m_boundary_filters[k]; + Real d2vdt2 = bf[0] * v[std::size(v) - 1]; + for (std::size_t j = 1; j < bf.size(); ++j) + { + d2vdt2 += bf[j] * v[std::size(v) - 1 - j]; + } + w[i] = d2vdt2; + } + } + } + + template + RandomAccessContainer operator()(RandomAccessContainer const & v) const + { + RandomAccessContainer w(std::size(v)); + this->operator()(v, w); + return w; + } + + + // Don't copy; too big. + discrete_lanczos_derivative( const discrete_lanczos_derivative & ) = delete; + discrete_lanczos_derivative& operator=(const discrete_lanczos_derivative&) = delete; + + // Allow moves: + discrete_lanczos_derivative(discrete_lanczos_derivative&&) noexcept = default; + discrete_lanczos_derivative& operator=(discrete_lanczos_derivative&&) noexcept = default; + +private: + std::vector m_f; + std::vector> m_boundary_filters; + Real m_dt; +}; + +} // namespaces +#endif diff --git a/libcxx/src/third-party/boost/math/distributions.hpp b/libcxx/src/third-party/boost/math/distributions.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/distributions.hpp @@ -0,0 +1,54 @@ +// Copyright John Maddock 2006, 2007. +// Copyright Paul A. Bristow 2006, 2007, 2009, 2010. + +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// This file includes *all* the distributions. +// this *may* be convenient if many are used +// - to avoid including each distribution individually. + +#ifndef BOOST_MATH_DISTRIBUTIONS_HPP +#define BOOST_MATH_DISTRIBUTIONS_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif // BOOST_MATH_DISTRIBUTIONS_HPP + diff --git a/libcxx/src/third-party/boost/math/distributions/arcsine.hpp b/libcxx/src/third-party/boost/math/distributions/arcsine.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/distributions/arcsine.hpp @@ -0,0 +1,541 @@ +// boost/math/distributions/arcsine.hpp + +// Copyright John Maddock 2014. +// Copyright Paul A. Bristow 2014. + +// 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) + +// http://en.wikipedia.org/wiki/arcsine_distribution + +// The arcsine Distribution is a continuous probability distribution. +// http://en.wikipedia.org/wiki/Arcsine_distribution +// http://www.wolframalpha.com/input/?i=ArcSinDistribution + +// Standard arcsine distribution is a special case of beta distribution with both a & b = one half, +// and 0 <= x <= 1. + +// It is generalized to include any bounded support a <= x <= b from 0 <= x <= 1 +// by Wolfram and Wikipedia, +// but using location and scale parameters by +// Virtual Laboratories in Probability and Statistics http://www.math.uah.edu/stat/index.html +// http://www.math.uah.edu/stat/special/Arcsine.html +// The end-point version is simpler and more obvious, so we implement that. +// TODO Perhaps provide location and scale functions? + + +#ifndef BOOST_MATH_DIST_ARCSINE_HPP +#define BOOST_MATH_DIST_ARCSINE_HPP + +#include +#include +#include // complements. +#include // error checks. +#include + +#include // isnan. + +#if defined (BOOST_MSVC) +# pragma warning(push) +# pragma warning(disable: 4702) // Unreachable code, +// in domain_error_imp in error_handling. +#endif + +#include +#include // For std::domain_error. + +namespace boost +{ + namespace math + { + namespace arcsine_detail + { + // Common error checking routines for arcsine distribution functions: + // Duplicating for x_min and x_max provides specific error messages. + template + inline bool check_x_min(const char* function, const RealType& x, RealType* result, const Policy& pol) + { + if (!(boost::math::isfinite)(x)) + { + *result = policies::raise_domain_error( + function, + "x_min argument is %1%, but must be finite !", x, pol); + return false; + } + return true; + } // bool check_x_min + + template + inline bool check_x_max(const char* function, const RealType& x, RealType* result, const Policy& pol) + { + if (!(boost::math::isfinite)(x)) + { + *result = policies::raise_domain_error( + function, + "x_max argument is %1%, but must be finite !", x, pol); + return false; + } + return true; + } // bool check_x_max + + + template + inline bool check_x_minmax(const char* function, const RealType& x_min, const RealType& x_max, RealType* result, const Policy& pol) + { // Check x_min < x_max + if (x_min >= x_max) + { + std::string msg = "x_max argument is %1%, but must be > x_min"; + *result = policies::raise_domain_error( + function, + msg.c_str(), x_max, pol); + // "x_max argument is %1%, but must be > x_min !", x_max, pol); + // "x_max argument is %1%, but must be > x_min %2!", x_max, x_min, pol); would be better. + // But would require replication of all helpers functions in /policies/error_handling.hpp for two values, + // as well as two value versions of raise_error, raise_domain_error and do_format + return false; + } + return true; + } // bool check_x_minmax + + template + inline bool check_prob(const char* function, const RealType& p, RealType* result, const Policy& pol) + { + if ((p < 0) || (p > 1) || !(boost::math::isfinite)(p)) + { + *result = policies::raise_domain_error( + function, + "Probability argument is %1%, but must be >= 0 and <= 1 !", p, pol); + return false; + } + return true; + } // bool check_prob + + template + inline bool check_x(const char* function, const RealType& x_min, const RealType& x_max, const RealType& x, RealType* result, const Policy& pol) + { // Check x finite and x_min < x < x_max. + if (!(boost::math::isfinite)(x)) + { + *result = policies::raise_domain_error( + function, + "x argument is %1%, but must be finite !", x, pol); + return false; + } + if ((x < x_min) || (x > x_max)) + { + // std::cout << x_min << ' ' << x << x_max << std::endl; + *result = policies::raise_domain_error( + function, + "x argument is %1%, but must be x_min < x < x_max !", x, pol); + // For example: + // Error in function boost::math::pdf(arcsine_distribution const&, double) : x argument is -1.01, but must be x_min < x < x_max ! + // TODO Perhaps show values of x_min and x_max? + return false; + } + return true; + } // bool check_x + + template + inline bool check_dist(const char* function, const RealType& x_min, const RealType& x_max, RealType* result, const Policy& pol) + { // Check both x_min and x_max finite, and x_min < x_max. + return check_x_min(function, x_min, result, pol) + && check_x_max(function, x_max, result, pol) + && check_x_minmax(function, x_min, x_max, result, pol); + } // bool check_dist + + template + inline bool check_dist_and_x(const char* function, const RealType& x_min, const RealType& x_max, RealType x, RealType* result, const Policy& pol) + { + return check_dist(function, x_min, x_max, result, pol) + && arcsine_detail::check_x(function, x_min, x_max, x, result, pol); + } // bool check_dist_and_x + + template + inline bool check_dist_and_prob(const char* function, const RealType& x_min, const RealType& x_max, RealType p, RealType* result, const Policy& pol) + { + return check_dist(function, x_min, x_max, result, pol) + && check_prob(function, p, result, pol); + } // bool check_dist_and_prob + + } // namespace arcsine_detail + + template > + class arcsine_distribution + { + public: + typedef RealType value_type; + typedef Policy policy_type; + + arcsine_distribution(RealType x_min = 0, RealType x_max = 1) : m_x_min(x_min), m_x_max(x_max) + { // Default beta (alpha = beta = 0.5) is standard arcsine with x_min = 0, x_max = 1. + // Generalized to allow x_min and x_max to be specified. + RealType result; + arcsine_detail::check_dist( + "boost::math::arcsine_distribution<%1%>::arcsine_distribution", + m_x_min, + m_x_max, + &result, Policy()); + } // arcsine_distribution constructor. + // Accessor functions: + RealType x_min() const + { + return m_x_min; + } + RealType x_max() const + { + return m_x_max; + } + + private: + RealType m_x_min; // Two x min and x max parameters of the arcsine distribution. + RealType m_x_max; + }; // template class arcsine_distribution + + // Convenient typedef to construct double version. + typedef arcsine_distribution arcsine; + + #ifdef __cpp_deduction_guides + template + arcsine_distribution(RealType)->arcsine_distribution::type>; + template + arcsine_distribution(RealType, RealType)->arcsine_distribution::type>; + #endif + + template + inline const std::pair range(const arcsine_distribution& dist) + { // Range of permissible values for random variable x. + using boost::math::tools::max_value; + return std::pair(static_cast(dist.x_min()), static_cast(dist.x_max())); + } + + template + inline const std::pair support(const arcsine_distribution& dist) + { // Range of supported values for random variable x. + // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. + return std::pair(static_cast(dist.x_min()), static_cast(dist.x_max())); + } + + template + inline RealType mean(const arcsine_distribution& dist) + { // Mean of arcsine distribution . + RealType result; + RealType x_min = dist.x_min(); + RealType x_max = dist.x_max(); + + if (false == arcsine_detail::check_dist( + "boost::math::mean(arcsine_distribution<%1%> const&, %1% )", + x_min, + x_max, + &result, Policy()) + ) + { + return result; + } + return (x_min + x_max) / 2; + } // mean + + template + inline RealType variance(const arcsine_distribution& dist) + { // Variance of standard arcsine distribution = (1-0)/8 = 0.125. + RealType result; + RealType x_min = dist.x_min(); + RealType x_max = dist.x_max(); + if (false == arcsine_detail::check_dist( + "boost::math::variance(arcsine_distribution<%1%> const&, %1% )", + x_min, + x_max, + &result, Policy()) + ) + { + return result; + } + return (x_max - x_min) * (x_max - x_min) / 8; + } // variance + + template + inline RealType mode(const arcsine_distribution& /* dist */) + { //There are always [*two] values for the mode, at ['x_min] and at ['x_max], default 0 and 1, + // so instead we raise the exception domain_error. + return policies::raise_domain_error( + "boost::math::mode(arcsine_distribution<%1%>&)", + "The arcsine distribution has two modes at x_min and x_max: " + "so the return value is %1%.", + std::numeric_limits::quiet_NaN(), Policy()); + } // mode + + template + inline RealType median(const arcsine_distribution& dist) + { // Median of arcsine distribution (a + b) / 2 == mean. + RealType x_min = dist.x_min(); + RealType x_max = dist.x_max(); + RealType result; + if (false == arcsine_detail::check_dist( + "boost::math::median(arcsine_distribution<%1%> const&, %1% )", + x_min, + x_max, + &result, Policy()) + ) + { + return result; + } + return (x_min + x_max) / 2; + } + + template + inline RealType skewness(const arcsine_distribution& dist) + { + RealType result; + RealType x_min = dist.x_min(); + RealType x_max = dist.x_max(); + + if (false == arcsine_detail::check_dist( + "boost::math::skewness(arcsine_distribution<%1%> const&, %1% )", + x_min, + x_max, + &result, Policy()) + ) + { + return result; + } + return 0; + } // skewness + + template + inline RealType kurtosis_excess(const arcsine_distribution& dist) + { + RealType result; + RealType x_min = dist.x_min(); + RealType x_max = dist.x_max(); + + if (false == arcsine_detail::check_dist( + "boost::math::kurtosis_excess(arcsine_distribution<%1%> const&, %1% )", + x_min, + x_max, + &result, Policy()) + ) + { + return result; + } + result = -3; + return result / 2; + } // kurtosis_excess + + template + inline RealType kurtosis(const arcsine_distribution& dist) + { + RealType result; + RealType x_min = dist.x_min(); + RealType x_max = dist.x_max(); + + if (false == arcsine_detail::check_dist( + "boost::math::kurtosis(arcsine_distribution<%1%> const&, %1% )", + x_min, + x_max, + &result, Policy()) + ) + { + return result; + } + + return 3 + kurtosis_excess(dist); + } // kurtosis + + template + inline RealType pdf(const arcsine_distribution& dist, const RealType& xx) + { // Probability Density/Mass Function arcsine. + BOOST_FPU_EXCEPTION_GUARD + BOOST_MATH_STD_USING // For ADL of std functions. + + static const char* function = "boost::math::pdf(arcsine_distribution<%1%> const&, %1%)"; + + RealType lo = dist.x_min(); + RealType hi = dist.x_max(); + RealType x = xx; + + // Argument checks: + RealType result = 0; + if (false == arcsine_detail::check_dist_and_x( + function, + lo, hi, x, + &result, Policy())) + { + return result; + } + using boost::math::constants::pi; + result = static_cast(1) / (pi() * sqrt((x - lo) * (hi - x))); + return result; + } // pdf + + template + inline RealType cdf(const arcsine_distribution& dist, const RealType& x) + { // Cumulative Distribution Function arcsine. + BOOST_MATH_STD_USING // For ADL of std functions. + + static const char* function = "boost::math::cdf(arcsine_distribution<%1%> const&, %1%)"; + + RealType x_min = dist.x_min(); + RealType x_max = dist.x_max(); + + // Argument checks: + RealType result = 0; + if (false == arcsine_detail::check_dist_and_x( + function, + x_min, x_max, x, + &result, Policy())) + { + return result; + } + // Special cases: + if (x == x_min) + { + return 0; + } + else if (x == x_max) + { + return 1; + } + using boost::math::constants::pi; + result = static_cast(2) * asin(sqrt((x - x_min) / (x_max - x_min))) / pi(); + return result; + } // arcsine cdf + + template + inline RealType cdf(const complemented2_type, RealType>& c) + { // Complemented Cumulative Distribution Function arcsine. + BOOST_MATH_STD_USING // For ADL of std functions. + static const char* function = "boost::math::cdf(arcsine_distribution<%1%> const&, %1%)"; + + RealType x = c.param; + arcsine_distribution const& dist = c.dist; + RealType x_min = dist.x_min(); + RealType x_max = dist.x_max(); + + // Argument checks: + RealType result = 0; + if (false == arcsine_detail::check_dist_and_x( + function, + x_min, x_max, x, + &result, Policy())) + { + return result; + } + if (x == x_min) + { + return 0; + } + else if (x == x_max) + { + return 1; + } + using boost::math::constants::pi; + // Naive version x = 1 - x; + // result = static_cast(2) * asin(sqrt((x - x_min) / (x_max - x_min))) / pi(); + // is less accurate, so use acos instead of asin for complement. + result = static_cast(2) * acos(sqrt((x - x_min) / (x_max - x_min))) / pi(); + return result; + } // arcsine ccdf + + template + inline RealType quantile(const arcsine_distribution& dist, const RealType& p) + { + // Quantile or Percent Point arcsine function or + // Inverse Cumulative probability distribution function CDF. + // Return x (0 <= x <= 1), + // for a given probability p (0 <= p <= 1). + // These functions take a probability as an argument + // and return a value such that the probability that a random variable x + // will be less than or equal to that value + // is whatever probability you supplied as an argument. + BOOST_MATH_STD_USING // For ADL of std functions. + + using boost::math::constants::half_pi; + + static const char* function = "boost::math::quantile(arcsine_distribution<%1%> const&, %1%)"; + + RealType result = 0; // of argument checks: + RealType x_min = dist.x_min(); + RealType x_max = dist.x_max(); + if (false == arcsine_detail::check_dist_and_prob( + function, + x_min, x_max, p, + &result, Policy())) + { + return result; + } + // Special cases: + if (p == 0) + { + return 0; + } + if (p == 1) + { + return 1; + } + + RealType sin2hpip = sin(half_pi() * p); + RealType sin2hpip2 = sin2hpip * sin2hpip; + result = -x_min * sin2hpip2 + x_min + x_max * sin2hpip2; + + return result; + } // quantile + + template + inline RealType quantile(const complemented2_type, RealType>& c) + { + // Complement Quantile or Percent Point arcsine function. + // Return the number of expected x for a given + // complement of the probability q. + BOOST_MATH_STD_USING // For ADL of std functions. + + using boost::math::constants::half_pi; + static const char* function = "boost::math::quantile(arcsine_distribution<%1%> const&, %1%)"; + + // Error checks: + RealType q = c.param; + const arcsine_distribution& dist = c.dist; + RealType result = 0; + RealType x_min = dist.x_min(); + RealType x_max = dist.x_max(); + if (false == arcsine_detail::check_dist_and_prob( + function, + x_min, + x_max, + q, + &result, Policy())) + { + return result; + } + // Special cases: + if (q == 1) + { + return 0; + } + if (q == 0) + { + return 1; + } + // Naive RealType p = 1 - q; result = sin(half_pi() * p); loses accuracy, so use a cos alternative instead. + //result = cos(half_pi() * q); // for arcsine(0,1) + //result = result * result; + // For generalized arcsine: + RealType cos2hpip = cos(half_pi() * q); + RealType cos2hpip2 = cos2hpip * cos2hpip; + result = -x_min * cos2hpip2 + x_min + x_max * cos2hpip2; + + return result; + } // Quantile Complement + + } // namespace math +} // namespace boost + +// This include must be at the end, *after* the accessors +// for this distribution have been defined, in order to +// keep compilers that support two-phase lookup happy. +#include + +#if defined (BOOST_MSVC) +# pragma warning(pop) +#endif + +#endif // BOOST_MATH_DIST_ARCSINE_HPP diff --git a/libcxx/src/third-party/boost/math/distributions/bernoulli.hpp b/libcxx/src/third-party/boost/math/distributions/bernoulli.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/distributions/bernoulli.hpp @@ -0,0 +1,341 @@ +// boost\math\distributions\bernoulli.hpp + +// Copyright John Maddock 2006. +// Copyright Paul A. Bristow 2007. + +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +// http://en.wikipedia.org/wiki/bernoulli_distribution +// http://mathworld.wolfram.com/BernoulliDistribution.html + +// bernoulli distribution is the discrete probability distribution of +// the number (k) of successes, in a single Bernoulli trials. +// It is a version of the binomial distribution when n = 1. + +// But note that the bernoulli distribution +// (like others including the poisson, binomial & negative binomial) +// is strictly defined as a discrete function: only integral values of k are envisaged. +// However because of the method of calculation using a continuous gamma function, +// it is convenient to treat it as if a continuous function, +// and permit non-integral values of k. +// To enforce the strict mathematical model, users should use floor or ceil functions +// on k outside this function to ensure that k is integral. + +#ifndef BOOST_MATH_SPECIAL_BERNOULLI_HPP +#define BOOST_MATH_SPECIAL_BERNOULLI_HPP + +#include +#include +#include // complements +#include // error checks +#include // isnan. + +#include + +namespace boost +{ + namespace math + { + namespace bernoulli_detail + { + // Common error checking routines for bernoulli distribution functions: + template + inline bool check_success_fraction(const char* function, const RealType& p, RealType* result, const Policy& /* pol */) + { + if(!(boost::math::isfinite)(p) || (p < 0) || (p > 1)) + { + *result = policies::raise_domain_error( + function, + "Success fraction argument is %1%, but must be >= 0 and <= 1 !", p, Policy()); + return false; + } + return true; + } + template + inline bool check_dist(const char* function, const RealType& p, RealType* result, const Policy& /* pol */, const std::true_type&) + { + return check_success_fraction(function, p, result, Policy()); + } + template + inline bool check_dist(const char* , const RealType& , RealType* , const Policy& /* pol */, const std::false_type&) + { + return true; + } + template + inline bool check_dist(const char* function, const RealType& p, RealType* result, const Policy& /* pol */) + { + return check_dist(function, p, result, Policy(), typename policies::constructor_error_check::type()); + } + + template + inline bool check_dist_and_k(const char* function, const RealType& p, RealType k, RealType* result, const Policy& pol) + { + if(check_dist(function, p, result, Policy(), typename policies::method_error_check::type()) == false) + { + return false; + } + if(!(boost::math::isfinite)(k) || !((k == 0) || (k == 1))) + { + *result = policies::raise_domain_error( + function, + "Number of successes argument is %1%, but must be 0 or 1 !", k, pol); + return false; + } + return true; + } + template + inline bool check_dist_and_prob(const char* function, RealType p, RealType prob, RealType* result, const Policy& /* pol */) + { + if((check_dist(function, p, result, Policy(), typename policies::method_error_check::type()) && detail::check_probability(function, prob, result, Policy())) == false) + { + return false; + } + return true; + } + } // namespace bernoulli_detail + + + template > + class bernoulli_distribution + { + public: + typedef RealType value_type; + typedef Policy policy_type; + + bernoulli_distribution(RealType p = 0.5) : m_p(p) + { // Default probability = half suits 'fair' coin tossing + // where probability of heads == probability of tails. + RealType result; // of checks. + bernoulli_detail::check_dist( + "boost::math::bernoulli_distribution<%1%>::bernoulli_distribution", + m_p, + &result, Policy()); + } // bernoulli_distribution constructor. + + RealType success_fraction() const + { // Probability. + return m_p; + } + + private: + RealType m_p; // success_fraction + }; // template class bernoulli_distribution + + typedef bernoulli_distribution bernoulli; + + #ifdef __cpp_deduction_guides + template + bernoulli_distribution(RealType)->bernoulli_distribution::type>; + #endif + + template + inline const std::pair range(const bernoulli_distribution& /* dist */) + { // Range of permissible values for random variable k = {0, 1}. + using boost::math::tools::max_value; + return std::pair(static_cast(0), static_cast(1)); + } + + template + inline const std::pair support(const bernoulli_distribution& /* dist */) + { // Range of supported values for random variable k = {0, 1}. + // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. + return std::pair(static_cast(0), static_cast(1)); + } + + template + inline RealType mean(const bernoulli_distribution& dist) + { // Mean of bernoulli distribution = p (n = 1). + return dist.success_fraction(); + } // mean + + // Rely on dereived_accessors quantile(half) + //template + //inline RealType median(const bernoulli_distribution& dist) + //{ // Median of bernoulli distribution is not defined. + // return tools::domain_error(BOOST_CURRENT_FUNCTION, "Median is not implemented, result is %1%!", std::numeric_limits::quiet_NaN()); + //} // median + + template + inline RealType variance(const bernoulli_distribution& dist) + { // Variance of bernoulli distribution =p * q. + return dist.success_fraction() * (1 - dist.success_fraction()); + } // variance + + template + RealType pdf(const bernoulli_distribution& dist, const RealType& k) + { // Probability Density/Mass Function. + BOOST_FPU_EXCEPTION_GUARD + // Error check: + RealType result = 0; // of checks. + if(false == bernoulli_detail::check_dist_and_k( + "boost::math::pdf(bernoulli_distribution<%1%>, %1%)", + dist.success_fraction(), // 0 to 1 + k, // 0 or 1 + &result, Policy())) + { + return result; + } + // Assume k is integral. + if (k == 0) + { + return 1 - dist.success_fraction(); // 1 - p + } + else // k == 1 + { + return dist.success_fraction(); // p + } + } // pdf + + template + inline RealType cdf(const bernoulli_distribution& dist, const RealType& k) + { // Cumulative Distribution Function Bernoulli. + RealType p = dist.success_fraction(); + // Error check: + RealType result = 0; + if(false == bernoulli_detail::check_dist_and_k( + "boost::math::cdf(bernoulli_distribution<%1%>, %1%)", + p, + k, + &result, Policy())) + { + return result; + } + if (k == 0) + { + return 1 - p; + } + else + { // k == 1 + return 1; + } + } // bernoulli cdf + + template + inline RealType cdf(const complemented2_type, RealType>& c) + { // Complemented Cumulative Distribution Function bernoulli. + RealType const& k = c.param; + bernoulli_distribution const& dist = c.dist; + RealType p = dist.success_fraction(); + // Error checks: + RealType result = 0; + if(false == bernoulli_detail::check_dist_and_k( + "boost::math::cdf(bernoulli_distribution<%1%>, %1%)", + p, + k, + &result, Policy())) + { + return result; + } + if (k == 0) + { + return p; + } + else + { // k == 1 + return 0; + } + } // bernoulli cdf complement + + template + inline RealType quantile(const bernoulli_distribution& dist, const RealType& p) + { // Quantile or Percent Point Bernoulli function. + // Return the number of expected successes k either 0 or 1. + // for a given probability p. + + RealType result = 0; // of error checks: + if(false == bernoulli_detail::check_dist_and_prob( + "boost::math::quantile(bernoulli_distribution<%1%>, %1%)", + dist.success_fraction(), + p, + &result, Policy())) + { + return result; + } + if (p <= (1 - dist.success_fraction())) + { // p <= pdf(dist, 0) == cdf(dist, 0) + return 0; + } + else + { + return 1; + } + } // quantile + + template + inline RealType quantile(const complemented2_type, RealType>& c) + { // Quantile or Percent Point bernoulli function. + // Return the number of expected successes k for a given + // complement of the probability q. + // + // Error checks: + RealType q = c.param; + const bernoulli_distribution& dist = c.dist; + RealType result = 0; + if(false == bernoulli_detail::check_dist_and_prob( + "boost::math::quantile(bernoulli_distribution<%1%>, %1%)", + dist.success_fraction(), + q, + &result, Policy())) + { + return result; + } + + if (q <= 1 - dist.success_fraction()) + { // // q <= cdf(complement(dist, 0)) == pdf(dist, 0) + return 1; + } + else + { + return 0; + } + } // quantile complemented. + + template + inline RealType mode(const bernoulli_distribution& dist) + { + return static_cast((dist.success_fraction() <= 0.5) ? 0 : 1); // p = 0.5 can be 0 or 1 + } + + template + inline RealType skewness(const bernoulli_distribution& dist) + { + BOOST_MATH_STD_USING; // Aid ADL for sqrt. + RealType p = dist.success_fraction(); + return (1 - 2 * p) / sqrt(p * (1 - p)); + } + + template + inline RealType kurtosis_excess(const bernoulli_distribution& dist) + { + RealType p = dist.success_fraction(); + // Note Wolfram says this is kurtosis in text, but gamma2 is the kurtosis excess, + // and Wikipedia also says this is the kurtosis excess formula. + // return (6 * p * p - 6 * p + 1) / (p * (1 - p)); + // But Wolfram kurtosis article gives this simpler formula for kurtosis excess: + return 1 / (1 - p) + 1/p -6; + } + + template + inline RealType kurtosis(const bernoulli_distribution& dist) + { + RealType p = dist.success_fraction(); + return 1 / (1 - p) + 1/p -6 + 3; + // Simpler than: + // return (6 * p * p - 6 * p + 1) / (p * (1 - p)) + 3; + } + + } // namespace math +} // namespace boost + +// This include must be at the end, *after* the accessors +// for this distribution have been defined, in order to +// keep compilers that support two-phase lookup happy. +#include + +#endif // BOOST_MATH_SPECIAL_BERNOULLI_HPP + + + diff --git a/libcxx/src/third-party/boost/math/distributions/beta.hpp b/libcxx/src/third-party/boost/math/distributions/beta.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/distributions/beta.hpp @@ -0,0 +1,555 @@ +// boost\math\distributions\beta.hpp + +// Copyright John Maddock 2006. +// Copyright Paul A. Bristow 2006. + +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +// http://en.wikipedia.org/wiki/Beta_distribution +// http://www.itl.nist.gov/div898/handbook/eda/section3/eda366h.htm +// http://mathworld.wolfram.com/BetaDistribution.html + +// The Beta Distribution is a continuous probability distribution. +// The beta distribution is used to model events which are constrained to take place +// within an interval defined by maxima and minima, +// so is used extensively in PERT and other project management systems +// to describe the time to completion. +// The cdf of the beta distribution is used as a convenient way +// of obtaining the sum over a set of binomial outcomes. +// The beta distribution is also used in Bayesian statistics. + +#ifndef BOOST_MATH_DIST_BETA_HPP +#define BOOST_MATH_DIST_BETA_HPP + +#include +#include // for beta. +#include // complements. +#include // error checks +#include // isnan. +#include // for root finding. + +#if defined (BOOST_MSVC) +# pragma warning(push) +# pragma warning(disable: 4702) // unreachable code +// in domain_error_imp in error_handling +#endif + +#include + +namespace boost +{ + namespace math + { + namespace beta_detail + { + // Common error checking routines for beta distribution functions: + template + inline bool check_alpha(const char* function, const RealType& alpha, RealType* result, const Policy& pol) + { + if(!(boost::math::isfinite)(alpha) || (alpha <= 0)) + { + *result = policies::raise_domain_error( + function, + "Alpha argument is %1%, but must be > 0 !", alpha, pol); + return false; + } + return true; + } // bool check_alpha + + template + inline bool check_beta(const char* function, const RealType& beta, RealType* result, const Policy& pol) + { + if(!(boost::math::isfinite)(beta) || (beta <= 0)) + { + *result = policies::raise_domain_error( + function, + "Beta argument is %1%, but must be > 0 !", beta, pol); + return false; + } + return true; + } // bool check_beta + + template + inline bool check_prob(const char* function, const RealType& p, RealType* result, const Policy& pol) + { + if((p < 0) || (p > 1) || !(boost::math::isfinite)(p)) + { + *result = policies::raise_domain_error( + function, + "Probability argument is %1%, but must be >= 0 and <= 1 !", p, pol); + return false; + } + return true; + } // bool check_prob + + template + inline bool check_x(const char* function, const RealType& x, RealType* result, const Policy& pol) + { + if(!(boost::math::isfinite)(x) || (x < 0) || (x > 1)) + { + *result = policies::raise_domain_error( + function, + "x argument is %1%, but must be >= 0 and <= 1 !", x, pol); + return false; + } + return true; + } // bool check_x + + template + inline bool check_dist(const char* function, const RealType& alpha, const RealType& beta, RealType* result, const Policy& pol) + { // Check both alpha and beta. + return check_alpha(function, alpha, result, pol) + && check_beta(function, beta, result, pol); + } // bool check_dist + + template + inline bool check_dist_and_x(const char* function, const RealType& alpha, const RealType& beta, RealType x, RealType* result, const Policy& pol) + { + return check_dist(function, alpha, beta, result, pol) + && beta_detail::check_x(function, x, result, pol); + } // bool check_dist_and_x + + template + inline bool check_dist_and_prob(const char* function, const RealType& alpha, const RealType& beta, RealType p, RealType* result, const Policy& pol) + { + return check_dist(function, alpha, beta, result, pol) + && check_prob(function, p, result, pol); + } // bool check_dist_and_prob + + template + inline bool check_mean(const char* function, const RealType& mean, RealType* result, const Policy& pol) + { + if(!(boost::math::isfinite)(mean) || (mean <= 0)) + { + *result = policies::raise_domain_error( + function, + "mean argument is %1%, but must be > 0 !", mean, pol); + return false; + } + return true; + } // bool check_mean + template + inline bool check_variance(const char* function, const RealType& variance, RealType* result, const Policy& pol) + { + if(!(boost::math::isfinite)(variance) || (variance <= 0)) + { + *result = policies::raise_domain_error( + function, + "variance argument is %1%, but must be > 0 !", variance, pol); + return false; + } + return true; + } // bool check_variance + } // namespace beta_detail + + // typedef beta_distribution beta; + // is deliberately NOT included to avoid a name clash with the beta function. + // Use beta_distribution<> mybeta(...) to construct type double. + + template > + class beta_distribution + { + public: + typedef RealType value_type; + typedef Policy policy_type; + + beta_distribution(RealType l_alpha = 1, RealType l_beta = 1) : m_alpha(l_alpha), m_beta(l_beta) + { + RealType result; + beta_detail::check_dist( + "boost::math::beta_distribution<%1%>::beta_distribution", + m_alpha, + m_beta, + &result, Policy()); + } // beta_distribution constructor. + // Accessor functions: + RealType alpha() const + { + return m_alpha; + } + RealType beta() const + { // . + return m_beta; + } + + // Estimation of the alpha & beta parameters. + // http://en.wikipedia.org/wiki/Beta_distribution + // gives formulae in section on parameter estimation. + // Also NIST EDA page 3 & 4 give the same. + // http://www.itl.nist.gov/div898/handbook/eda/section3/eda366h.htm + // http://www.epi.ucdavis.edu/diagnostictests/betabuster.html + + static RealType find_alpha( + RealType mean, // Expected value of mean. + RealType variance) // Expected value of variance. + { + static const char* function = "boost::math::beta_distribution<%1%>::find_alpha"; + RealType result = 0; // of error checks. + if(false == + ( + beta_detail::check_mean(function, mean, &result, Policy()) + && beta_detail::check_variance(function, variance, &result, Policy()) + ) + ) + { + return result; + } + return mean * (( (mean * (1 - mean)) / variance)- 1); + } // RealType find_alpha + + static RealType find_beta( + RealType mean, // Expected value of mean. + RealType variance) // Expected value of variance. + { + static const char* function = "boost::math::beta_distribution<%1%>::find_beta"; + RealType result = 0; // of error checks. + if(false == + ( + beta_detail::check_mean(function, mean, &result, Policy()) + && + beta_detail::check_variance(function, variance, &result, Policy()) + ) + ) + { + return result; + } + return (1 - mean) * (((mean * (1 - mean)) /variance)-1); + } // RealType find_beta + + // Estimate alpha & beta from either alpha or beta, and x and probability. + // Uses for these parameter estimators are unclear. + + static RealType find_alpha( + RealType beta, // from beta. + RealType x, // x. + RealType probability) // cdf + { + static const char* function = "boost::math::beta_distribution<%1%>::find_alpha"; + RealType result = 0; // of error checks. + if(false == + ( + beta_detail::check_prob(function, probability, &result, Policy()) + && + beta_detail::check_beta(function, beta, &result, Policy()) + && + beta_detail::check_x(function, x, &result, Policy()) + ) + ) + { + return result; + } + return ibeta_inva(beta, x, probability, Policy()); + } // RealType find_alpha(beta, a, probability) + + static RealType find_beta( + // ibeta_invb(T b, T x, T p); (alpha, x, cdf,) + RealType alpha, // alpha. + RealType x, // probability x. + RealType probability) // probability cdf. + { + static const char* function = "boost::math::beta_distribution<%1%>::find_beta"; + RealType result = 0; // of error checks. + if(false == + ( + beta_detail::check_prob(function, probability, &result, Policy()) + && + beta_detail::check_alpha(function, alpha, &result, Policy()) + && + beta_detail::check_x(function, x, &result, Policy()) + ) + ) + { + return result; + } + return ibeta_invb(alpha, x, probability, Policy()); + } // RealType find_beta(alpha, x, probability) + + private: + RealType m_alpha; // Two parameters of the beta distribution. + RealType m_beta; + }; // template class beta_distribution + + #ifdef __cpp_deduction_guides + template + beta_distribution(RealType)->beta_distribution::type>; + template + beta_distribution(RealType, RealType)->beta_distribution::type>; + #endif + + template + inline const std::pair range(const beta_distribution& /* dist */) + { // Range of permissible values for random variable x. + using boost::math::tools::max_value; + return std::pair(static_cast(0), static_cast(1)); + } + + template + inline const std::pair support(const beta_distribution& /* dist */) + { // Range of supported values for random variable x. + // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. + return std::pair(static_cast(0), static_cast(1)); + } + + template + inline RealType mean(const beta_distribution& dist) + { // Mean of beta distribution = np. + return dist.alpha() / (dist.alpha() + dist.beta()); + } // mean + + template + inline RealType variance(const beta_distribution& dist) + { // Variance of beta distribution = np(1-p). + RealType a = dist.alpha(); + RealType b = dist.beta(); + return (a * b) / ((a + b ) * (a + b) * (a + b + 1)); + } // variance + + template + inline RealType mode(const beta_distribution& dist) + { + static const char* function = "boost::math::mode(beta_distribution<%1%> const&)"; + + RealType result; + if ((dist.alpha() <= 1)) + { + result = policies::raise_domain_error( + function, + "mode undefined for alpha = %1%, must be > 1!", dist.alpha(), Policy()); + return result; + } + + if ((dist.beta() <= 1)) + { + result = policies::raise_domain_error( + function, + "mode undefined for beta = %1%, must be > 1!", dist.beta(), Policy()); + return result; + } + RealType a = dist.alpha(); + RealType b = dist.beta(); + return (a-1) / (a + b - 2); + } // mode + + //template + //inline RealType median(const beta_distribution& dist) + //{ // Median of beta distribution is not defined. + // return tools::domain_error(function, "Median is not implemented, result is %1%!", std::numeric_limits::quiet_NaN()); + //} // median + + //But WILL be provided by the derived accessor as quantile(0.5). + + template + inline RealType skewness(const beta_distribution& dist) + { + BOOST_MATH_STD_USING // ADL of std functions. + RealType a = dist.alpha(); + RealType b = dist.beta(); + return (2 * (b-a) * sqrt(a + b + 1)) / ((a + b + 2) * sqrt(a * b)); + } // skewness + + template + inline RealType kurtosis_excess(const beta_distribution& dist) + { + RealType a = dist.alpha(); + RealType b = dist.beta(); + RealType a_2 = a * a; + RealType n = 6 * (a_2 * a - a_2 * (2 * b - 1) + b * b * (b + 1) - 2 * a * b * (b + 2)); + RealType d = a * b * (a + b + 2) * (a + b + 3); + return n / d; + } // kurtosis_excess + + template + inline RealType kurtosis(const beta_distribution& dist) + { + return 3 + kurtosis_excess(dist); + } // kurtosis + + template + inline RealType pdf(const beta_distribution& dist, const RealType& x) + { // Probability Density/Mass Function. + BOOST_FPU_EXCEPTION_GUARD + + static const char* function = "boost::math::pdf(beta_distribution<%1%> const&, %1%)"; + + BOOST_MATH_STD_USING // for ADL of std functions + + RealType a = dist.alpha(); + RealType b = dist.beta(); + + // Argument checks: + RealType result = 0; + if(false == beta_detail::check_dist_and_x( + function, + a, b, x, + &result, Policy())) + { + return result; + } + using boost::math::beta; + + // Corner case: check_x ensures x element of [0, 1], but PDF is 0 for x = 0 and x = 1. PDF EQN: + // https://wikimedia.org/api/rest_v1/media/math/render/svg/125fdaa41844a8703d1a8610ac00fbf3edacc8e7 + if(x == 0 || x == 1) + { + return RealType(0); + } + return ibeta_derivative(a, b, x, Policy()); + } // pdf + + template + inline RealType cdf(const beta_distribution& dist, const RealType& x) + { // Cumulative Distribution Function beta. + BOOST_MATH_STD_USING // for ADL of std functions + + static const char* function = "boost::math::cdf(beta_distribution<%1%> const&, %1%)"; + + RealType a = dist.alpha(); + RealType b = dist.beta(); + + // Argument checks: + RealType result = 0; + if(false == beta_detail::check_dist_and_x( + function, + a, b, x, + &result, Policy())) + { + return result; + } + // Special cases: + if (x == 0) + { + return 0; + } + else if (x == 1) + { + return 1; + } + return ibeta(a, b, x, Policy()); + } // beta cdf + + template + inline RealType cdf(const complemented2_type, RealType>& c) + { // Complemented Cumulative Distribution Function beta. + + BOOST_MATH_STD_USING // for ADL of std functions + + static const char* function = "boost::math::cdf(beta_distribution<%1%> const&, %1%)"; + + RealType const& x = c.param; + beta_distribution const& dist = c.dist; + RealType a = dist.alpha(); + RealType b = dist.beta(); + + // Argument checks: + RealType result = 0; + if(false == beta_detail::check_dist_and_x( + function, + a, b, x, + &result, Policy())) + { + return result; + } + if (x == 0) + { + return 1; + } + else if (x == 1) + { + return 0; + } + // Calculate cdf beta using the incomplete beta function. + // Use of ibeta here prevents cancellation errors in calculating + // 1 - x if x is very small, perhaps smaller than machine epsilon. + return ibetac(a, b, x, Policy()); + } // beta cdf + + template + inline RealType quantile(const beta_distribution& dist, const RealType& p) + { // Quantile or Percent Point beta function or + // Inverse Cumulative probability distribution function CDF. + // Return x (0 <= x <= 1), + // for a given probability p (0 <= p <= 1). + // These functions take a probability as an argument + // and return a value such that the probability that a random variable x + // will be less than or equal to that value + // is whatever probability you supplied as an argument. + + static const char* function = "boost::math::quantile(beta_distribution<%1%> const&, %1%)"; + + RealType result = 0; // of argument checks: + RealType a = dist.alpha(); + RealType b = dist.beta(); + if(false == beta_detail::check_dist_and_prob( + function, + a, b, p, + &result, Policy())) + { + return result; + } + // Special cases: + if (p == 0) + { + return 0; + } + if (p == 1) + { + return 1; + } + return ibeta_inv(a, b, p, static_cast(nullptr), Policy()); + } // quantile + + template + inline RealType quantile(const complemented2_type, RealType>& c) + { // Complement Quantile or Percent Point beta function . + // Return the number of expected x for a given + // complement of the probability q. + + static const char* function = "boost::math::quantile(beta_distribution<%1%> const&, %1%)"; + + // + // Error checks: + RealType q = c.param; + const beta_distribution& dist = c.dist; + RealType result = 0; + RealType a = dist.alpha(); + RealType b = dist.beta(); + if(false == beta_detail::check_dist_and_prob( + function, + a, + b, + q, + &result, Policy())) + { + return result; + } + // Special cases: + if(q == 1) + { + return 0; + } + if(q == 0) + { + return 1; + } + + return ibetac_inv(a, b, q, static_cast(nullptr), Policy()); + } // Quantile Complement + + } // namespace math +} // namespace boost + +// This include must be at the end, *after* the accessors +// for this distribution have been defined, in order to +// keep compilers that support two-phase lookup happy. +#include + +#if defined (BOOST_MSVC) +# pragma warning(pop) +#endif + +#endif // BOOST_MATH_DIST_BETA_HPP + + diff --git a/libcxx/src/third-party/boost/math/distributions/binomial.hpp b/libcxx/src/third-party/boost/math/distributions/binomial.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/distributions/binomial.hpp @@ -0,0 +1,730 @@ +// boost\math\distributions\binomial.hpp + +// Copyright John Maddock 2006. +// Copyright Paul A. Bristow 2007. + +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +// http://en.wikipedia.org/wiki/binomial_distribution + +// Binomial distribution is the discrete probability distribution of +// the number (k) of successes, in a sequence of +// n independent (yes or no, success or failure) Bernoulli trials. + +// It expresses the probability of a number of events occurring in a fixed time +// if these events occur with a known average rate (probability of success), +// and are independent of the time since the last event. + +// The number of cars that pass through a certain point on a road during a given period of time. +// The number of spelling mistakes a secretary makes while typing a single page. +// The number of phone calls at a call center per minute. +// The number of times a web server is accessed per minute. +// The number of light bulbs that burn out in a certain amount of time. +// The number of roadkill found per unit length of road + +// http://en.wikipedia.org/wiki/binomial_distribution + +// Given a sample of N measured values k[i], +// we wish to estimate the value of the parameter x (mean) +// of the binomial population from which the sample was drawn. +// To calculate the maximum likelihood value = 1/N sum i = 1 to N of k[i] + +// Also may want a function for EXACTLY k. + +// And probability that there are EXACTLY k occurrences is +// exp(-x) * pow(x, k) / factorial(k) +// where x is expected occurrences (mean) during the given interval. +// For example, if events occur, on average, every 4 min, +// and we are interested in number of events occurring in 10 min, +// then x = 10/4 = 2.5 + +// http://www.itl.nist.gov/div898/handbook/eda/section3/eda366i.htm + +// The binomial distribution is used when there are +// exactly two mutually exclusive outcomes of a trial. +// These outcomes are appropriately labeled "success" and "failure". +// The binomial distribution is used to obtain +// the probability of observing x successes in N trials, +// with the probability of success on a single trial denoted by p. +// The binomial distribution assumes that p is fixed for all trials. + +// P(x, p, n) = n!/(x! * (n-x)!) * p^x * (1-p)^(n-x) + +// http://mathworld.wolfram.com/BinomialCoefficient.html + +// The binomial coefficient (n; k) is the number of ways of picking +// k unordered outcomes from n possibilities, +// also known as a combination or combinatorial number. +// The symbols _nC_k and (n; k) are used to denote a binomial coefficient, +// and are sometimes read as "n choose k." +// (n; k) therefore gives the number of k-subsets possible out of a set of n distinct items. + +// For example: +// The 2-subsets of {1,2,3,4} are the six pairs {1,2}, {1,3}, {1,4}, {2,3}, {2,4}, and {3,4}, so (4; 2)==6. + +// http://functions.wolfram.com/GammaBetaErf/Binomial/ for evaluation. + +// But note that the binomial distribution +// (like others including the poisson, negative binomial & Bernoulli) +// is strictly defined as a discrete function: only integral values of k are envisaged. +// However because of the method of calculation using a continuous gamma function, +// it is convenient to treat it as if a continuous function, +// and permit non-integral values of k. +// To enforce the strict mathematical model, users should use floor or ceil functions +// on k outside this function to ensure that k is integral. + +#ifndef BOOST_MATH_SPECIAL_BINOMIAL_HPP +#define BOOST_MATH_SPECIAL_BINOMIAL_HPP + +#include +#include // for incomplete beta. +#include // complements +#include // error checks +#include // error checks +#include // isnan. +#include // for root finding. + +#include + +namespace boost +{ + namespace math + { + + template + class binomial_distribution; + + namespace binomial_detail{ + // common error checking routines for binomial distribution functions: + template + inline bool check_N(const char* function, const RealType& N, RealType* result, const Policy& pol) + { + if((N < 0) || !(boost::math::isfinite)(N)) + { + *result = policies::raise_domain_error( + function, + "Number of Trials argument is %1%, but must be >= 0 !", N, pol); + return false; + } + return true; + } + template + inline bool check_success_fraction(const char* function, const RealType& p, RealType* result, const Policy& pol) + { + if((p < 0) || (p > 1) || !(boost::math::isfinite)(p)) + { + *result = policies::raise_domain_error( + function, + "Success fraction argument is %1%, but must be >= 0 and <= 1 !", p, pol); + return false; + } + return true; + } + template + inline bool check_dist(const char* function, const RealType& N, const RealType& p, RealType* result, const Policy& pol) + { + return check_success_fraction( + function, p, result, pol) + && check_N( + function, N, result, pol); + } + template + inline bool check_dist_and_k(const char* function, const RealType& N, const RealType& p, RealType k, RealType* result, const Policy& pol) + { + if(check_dist(function, N, p, result, pol) == false) + return false; + if((k < 0) || !(boost::math::isfinite)(k)) + { + *result = policies::raise_domain_error( + function, + "Number of Successes argument is %1%, but must be >= 0 !", k, pol); + return false; + } + if(k > N) + { + *result = policies::raise_domain_error( + function, + "Number of Successes argument is %1%, but must be <= Number of Trials !", k, pol); + return false; + } + return true; + } + template + inline bool check_dist_and_prob(const char* function, const RealType& N, RealType p, RealType prob, RealType* result, const Policy& pol) + { + if((check_dist(function, N, p, result, pol) && detail::check_probability(function, prob, result, pol)) == false) + return false; + return true; + } + + template + T inverse_binomial_cornish_fisher(T n, T sf, T p, T q, const Policy& pol) + { + BOOST_MATH_STD_USING + // mean: + T m = n * sf; + // standard deviation: + T sigma = sqrt(n * sf * (1 - sf)); + // skewness + T sk = (1 - 2 * sf) / sigma; + // kurtosis: + // T k = (1 - 6 * sf * (1 - sf) ) / (n * sf * (1 - sf)); + // Get the inverse of a std normal distribution: + T x = boost::math::erfc_inv(p > q ? 2 * q : 2 * p, pol) * constants::root_two(); + // Set the sign: + if(p < 0.5) + x = -x; + T x2 = x * x; + // w is correction term due to skewness + T w = x + sk * (x2 - 1) / 6; + /* + // Add on correction due to kurtosis. + // Disabled for now, seems to make things worse? + // + if(n >= 10) + w += k * x * (x2 - 3) / 24 + sk * sk * x * (2 * x2 - 5) / -36; + */ + w = m + sigma * w; + if(w < tools::min_value()) + return sqrt(tools::min_value()); + if(w > n) + return n; + return w; + } + + template + RealType quantile_imp(const binomial_distribution& dist, const RealType& p, const RealType& q, bool comp) + { // Quantile or Percent Point Binomial function. + // Return the number of expected successes k, + // for a given probability p. + // + // Error checks: + BOOST_MATH_STD_USING // ADL of std names + RealType result = 0; + RealType trials = dist.trials(); + RealType success_fraction = dist.success_fraction(); + if(false == binomial_detail::check_dist_and_prob( + "boost::math::quantile(binomial_distribution<%1%> const&, %1%)", + trials, + success_fraction, + p, + &result, Policy())) + { + return result; + } + + // Special cases: + // + if(p == 0) + { // There may actually be no answer to this question, + // since the probability of zero successes may be non-zero, + // but zero is the best we can do: + return 0; + } + if(p == 1) + { // Probability of n or fewer successes is always one, + // so n is the most sensible answer here: + return trials; + } + if (p <= pow(1 - success_fraction, trials)) + { // p <= pdf(dist, 0) == cdf(dist, 0) + return 0; // So the only reasonable result is zero. + } // And root finder would fail otherwise. + if(success_fraction == 1) + { // our formulae break down in this case: + return p > 0.5f ? trials : 0; + } + + // Solve for quantile numerically: + // + RealType guess = binomial_detail::inverse_binomial_cornish_fisher(trials, success_fraction, p, q, Policy()); + RealType factor = 8; + if(trials > 100) + factor = 1.01f; // guess is pretty accurate + else if((trials > 10) && (trials - 1 > guess) && (guess > 3)) + factor = 1.15f; // less accurate but OK. + else if(trials < 10) + { + // pretty inaccurate guess in this area: + if(guess > trials / 64) + { + guess = trials / 4; + factor = 2; + } + else + guess = trials / 1024; + } + else + factor = 2; // trials largish, but in far tails. + + typedef typename Policy::discrete_quantile_type discrete_quantile_type; + std::uintmax_t max_iter = policies::get_max_root_iterations(); + return detail::inverse_discrete_quantile( + dist, + comp ? q : p, + comp, + guess, + factor, + RealType(1), + discrete_quantile_type(), + max_iter); + } // quantile + + } + + template > + class binomial_distribution + { + public: + typedef RealType value_type; + typedef Policy policy_type; + + binomial_distribution(RealType n = 1, RealType p = 0.5) : m_n(n), m_p(p) + { // Default n = 1 is the Bernoulli distribution + // with equal probability of 'heads' or 'tails. + RealType r; + binomial_detail::check_dist( + "boost::math::binomial_distribution<%1%>::binomial_distribution", + m_n, + m_p, + &r, Policy()); + } // binomial_distribution constructor. + + RealType success_fraction() const + { // Probability. + return m_p; + } + RealType trials() const + { // Total number of trials. + return m_n; + } + + enum interval_type{ + clopper_pearson_exact_interval, + jeffreys_prior_interval + }; + + // + // Estimation of the success fraction parameter. + // The best estimate is actually simply successes/trials, + // these functions are used + // to obtain confidence intervals for the success fraction. + // + static RealType find_lower_bound_on_p( + RealType trials, + RealType successes, + RealType probability, + interval_type t = clopper_pearson_exact_interval) + { + static const char* function = "boost::math::binomial_distribution<%1%>::find_lower_bound_on_p"; + // Error checks: + RealType result = 0; + if(false == binomial_detail::check_dist_and_k( + function, trials, RealType(0), successes, &result, Policy()) + && + binomial_detail::check_dist_and_prob( + function, trials, RealType(0), probability, &result, Policy())) + { return result; } + + if(successes == 0) + return 0; + + // NOTE!!! The Clopper Pearson formula uses "successes" not + // "successes+1" as usual to get the lower bound, + // see http://www.itl.nist.gov/div898/handbook/prc/section2/prc241.htm + return (t == clopper_pearson_exact_interval) ? ibeta_inv(successes, trials - successes + 1, probability, static_cast(nullptr), Policy()) + : ibeta_inv(successes + 0.5f, trials - successes + 0.5f, probability, static_cast(nullptr), Policy()); + } + static RealType find_upper_bound_on_p( + RealType trials, + RealType successes, + RealType probability, + interval_type t = clopper_pearson_exact_interval) + { + static const char* function = "boost::math::binomial_distribution<%1%>::find_upper_bound_on_p"; + // Error checks: + RealType result = 0; + if(false == binomial_detail::check_dist_and_k( + function, trials, RealType(0), successes, &result, Policy()) + && + binomial_detail::check_dist_and_prob( + function, trials, RealType(0), probability, &result, Policy())) + { return result; } + + if(trials == successes) + return 1; + + return (t == clopper_pearson_exact_interval) ? ibetac_inv(successes + 1, trials - successes, probability, static_cast(nullptr), Policy()) + : ibetac_inv(successes + 0.5f, trials - successes + 0.5f, probability, static_cast(nullptr), Policy()); + } + // Estimate number of trials parameter: + // + // "How many trials do I need to be P% sure of seeing k events?" + // or + // "How many trials can I have to be P% sure of seeing fewer than k events?" + // + static RealType find_minimum_number_of_trials( + RealType k, // number of events + RealType p, // success fraction + RealType alpha) // risk level + { + static const char* function = "boost::math::binomial_distribution<%1%>::find_minimum_number_of_trials"; + // Error checks: + RealType result = 0; + if(false == binomial_detail::check_dist_and_k( + function, k, p, k, &result, Policy()) + && + binomial_detail::check_dist_and_prob( + function, k, p, alpha, &result, Policy())) + { return result; } + + result = ibetac_invb(k + 1, p, alpha, Policy()); // returns n - k + return result + k; + } + + static RealType find_maximum_number_of_trials( + RealType k, // number of events + RealType p, // success fraction + RealType alpha) // risk level + { + static const char* function = "boost::math::binomial_distribution<%1%>::find_maximum_number_of_trials"; + // Error checks: + RealType result = 0; + if(false == binomial_detail::check_dist_and_k( + function, k, p, k, &result, Policy()) + && + binomial_detail::check_dist_and_prob( + function, k, p, alpha, &result, Policy())) + { return result; } + + result = ibeta_invb(k + 1, p, alpha, Policy()); // returns n - k + return result + k; + } + + private: + RealType m_n; // Not sure if this shouldn't be an int? + RealType m_p; // success_fraction + }; // template class binomial_distribution + + typedef binomial_distribution<> binomial; + // typedef binomial_distribution binomial; + // IS now included since no longer a name clash with function binomial. + //typedef binomial_distribution binomial; // Reserved name of type double. + + #ifdef __cpp_deduction_guides + template + binomial_distribution(RealType)->binomial_distribution::type>; + template + binomial_distribution(RealType,RealType)->binomial_distribution::type>; + #endif + + template + const std::pair range(const binomial_distribution& dist) + { // Range of permissible values for random variable k. + using boost::math::tools::max_value; + return std::pair(static_cast(0), dist.trials()); + } + + template + const std::pair support(const binomial_distribution& dist) + { // Range of supported values for random variable k. + // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. + return std::pair(static_cast(0), dist.trials()); + } + + template + inline RealType mean(const binomial_distribution& dist) + { // Mean of Binomial distribution = np. + return dist.trials() * dist.success_fraction(); + } // mean + + template + inline RealType variance(const binomial_distribution& dist) + { // Variance of Binomial distribution = np(1-p). + return dist.trials() * dist.success_fraction() * (1 - dist.success_fraction()); + } // variance + + template + RealType pdf(const binomial_distribution& dist, const RealType& k) + { // Probability Density/Mass Function. + BOOST_FPU_EXCEPTION_GUARD + + BOOST_MATH_STD_USING // for ADL of std functions + + RealType n = dist.trials(); + + // Error check: + RealType result = 0; // initialization silences some compiler warnings + if(false == binomial_detail::check_dist_and_k( + "boost::math::pdf(binomial_distribution<%1%> const&, %1%)", + n, + dist.success_fraction(), + k, + &result, Policy())) + { + return result; + } + + // Special cases of success_fraction, regardless of k successes and regardless of n trials. + if (dist.success_fraction() == 0) + { // probability of zero successes is 1: + return static_cast(k == 0 ? 1 : 0); + } + if (dist.success_fraction() == 1) + { // probability of n successes is 1: + return static_cast(k == n ? 1 : 0); + } + // k argument may be integral, signed, or unsigned, or floating point. + // If necessary, it has already been promoted from an integral type. + if (n == 0) + { + return 1; // Probability = 1 = certainty. + } + if (k == n) + { // binomial coeffic (n n) = 1, + // n ^ 0 = 1 + return pow(dist.success_fraction(), k); // * pow((1 - dist.success_fraction()), (n - k)) = 1 + } + + // Probability of getting exactly k successes + // if C(n, k) is the binomial coefficient then: + // + // f(k; n,p) = C(n, k) * p^k * (1-p)^(n-k) + // = (n!/(k!(n-k)!)) * p^k * (1-p)^(n-k) + // = (tgamma(n+1) / (tgamma(k+1)*tgamma(n-k+1))) * p^k * (1-p)^(n-k) + // = p^k (1-p)^(n-k) / (beta(k+1, n-k+1) * (n+1)) + // = ibeta_derivative(k+1, n-k+1, p) / (n+1) + // + using boost::math::ibeta_derivative; // a, b, x + return ibeta_derivative(k+1, n-k+1, dist.success_fraction(), Policy()) / (n+1); + + } // pdf + + template + inline RealType cdf(const binomial_distribution& dist, const RealType& k) + { // Cumulative Distribution Function Binomial. + // The random variate k is the number of successes in n trials. + // k argument may be integral, signed, or unsigned, or floating point. + // If necessary, it has already been promoted from an integral type. + + // Returns the sum of the terms 0 through k of the Binomial Probability Density/Mass: + // + // i=k + // -- ( n ) i n-i + // > | | p (1-p) + // -- ( i ) + // i=0 + + // The terms are not summed directly instead + // the incomplete beta integral is employed, + // according to the formula: + // P = I[1-p]( n-k, k+1). + // = 1 - I[p](k + 1, n - k) + + BOOST_MATH_STD_USING // for ADL of std functions + + RealType n = dist.trials(); + RealType p = dist.success_fraction(); + + // Error check: + RealType result = 0; + if(false == binomial_detail::check_dist_and_k( + "boost::math::cdf(binomial_distribution<%1%> const&, %1%)", + n, + p, + k, + &result, Policy())) + { + return result; + } + if (k == n) + { + return 1; + } + + // Special cases, regardless of k. + if (p == 0) + { // This need explanation: + // the pdf is zero for all cases except when k == 0. + // For zero p the probability of zero successes is one. + // Therefore the cdf is always 1: + // the probability of k or *fewer* successes is always 1 + // if there are never any successes! + return 1; + } + if (p == 1) + { // This is correct but needs explanation: + // when k = 1 + // all the cdf and pdf values are zero *except* when k == n, + // and that case has been handled above already. + return 0; + } + // + // P = I[1-p](n - k, k + 1) + // = 1 - I[p](k + 1, n - k) + // Use of ibetac here prevents cancellation errors in calculating + // 1-p if p is very small, perhaps smaller than machine epsilon. + // + // Note that we do not use a finite sum here, since the incomplete + // beta uses a finite sum internally for integer arguments, so + // we'll just let it take care of the necessary logic. + // + return ibetac(k + 1, n - k, p, Policy()); + } // binomial cdf + + template + inline RealType cdf(const complemented2_type, RealType>& c) + { // Complemented Cumulative Distribution Function Binomial. + // The random variate k is the number of successes in n trials. + // k argument may be integral, signed, or unsigned, or floating point. + // If necessary, it has already been promoted from an integral type. + + // Returns the sum of the terms k+1 through n of the Binomial Probability Density/Mass: + // + // i=n + // -- ( n ) i n-i + // > | | p (1-p) + // -- ( i ) + // i=k+1 + + // The terms are not summed directly instead + // the incomplete beta integral is employed, + // according to the formula: + // Q = 1 -I[1-p]( n-k, k+1). + // = I[p](k + 1, n - k) + + BOOST_MATH_STD_USING // for ADL of std functions + + RealType const& k = c.param; + binomial_distribution const& dist = c.dist; + RealType n = dist.trials(); + RealType p = dist.success_fraction(); + + // Error checks: + RealType result = 0; + if(false == binomial_detail::check_dist_and_k( + "boost::math::cdf(binomial_distribution<%1%> const&, %1%)", + n, + p, + k, + &result, Policy())) + { + return result; + } + + if (k == n) + { // Probability of greater than n successes is necessarily zero: + return 0; + } + + // Special cases, regardless of k. + if (p == 0) + { + // This need explanation: the pdf is zero for all + // cases except when k == 0. For zero p the probability + // of zero successes is one. Therefore the cdf is always + // 1: the probability of *more than* k successes is always 0 + // if there are never any successes! + return 0; + } + if (p == 1) + { + // This needs explanation, when p = 1 + // we always have n successes, so the probability + // of more than k successes is 1 as long as k < n. + // The k == n case has already been handled above. + return 1; + } + // + // Calculate cdf binomial using the incomplete beta function. + // Q = 1 -I[1-p](n - k, k + 1) + // = I[p](k + 1, n - k) + // Use of ibeta here prevents cancellation errors in calculating + // 1-p if p is very small, perhaps smaller than machine epsilon. + // + // Note that we do not use a finite sum here, since the incomplete + // beta uses a finite sum internally for integer arguments, so + // we'll just let it take care of the necessary logic. + // + return ibeta(k + 1, n - k, p, Policy()); + } // binomial cdf + + template + inline RealType quantile(const binomial_distribution& dist, const RealType& p) + { + return binomial_detail::quantile_imp(dist, p, RealType(1-p), false); + } // quantile + + template + RealType quantile(const complemented2_type, RealType>& c) + { + return binomial_detail::quantile_imp(c.dist, RealType(1-c.param), c.param, true); + } // quantile + + template + inline RealType mode(const binomial_distribution& dist) + { + BOOST_MATH_STD_USING // ADL of std functions. + RealType p = dist.success_fraction(); + RealType n = dist.trials(); + return floor(p * (n + 1)); + } + + template + inline RealType median(const binomial_distribution& dist) + { // Bounds for the median of the negative binomial distribution + // VAN DE VEN R. ; WEBER N. C. ; + // Univ. Sydney, school mathematics statistics, Sydney N.S.W. 2006, AUSTRALIE + // Metrika (Metrika) ISSN 0026-1335 CODEN MTRKA8 + // 1993, vol. 40, no3-4, pp. 185-189 (4 ref.) + + // Bounds for median and 50 percentage point of binomial and negative binomial distribution + // Metrika, ISSN 0026-1335 (Print) 1435-926X (Online) + // Volume 41, Number 1 / December, 1994, DOI 10.1007/BF01895303 + BOOST_MATH_STD_USING // ADL of std functions. + RealType p = dist.success_fraction(); + RealType n = dist.trials(); + // Wikipedia says one of floor(np) -1, floor (np), floor(np) +1 + return floor(p * n); // Chose the middle value. + } + + template + inline RealType skewness(const binomial_distribution& dist) + { + BOOST_MATH_STD_USING // ADL of std functions. + RealType p = dist.success_fraction(); + RealType n = dist.trials(); + return (1 - 2 * p) / sqrt(n * p * (1 - p)); + } + + template + inline RealType kurtosis(const binomial_distribution& dist) + { + RealType p = dist.success_fraction(); + RealType n = dist.trials(); + return 3 - 6 / n + 1 / (n * p * (1 - p)); + } + + template + inline RealType kurtosis_excess(const binomial_distribution& dist) + { + RealType p = dist.success_fraction(); + RealType q = 1 - p; + RealType n = dist.trials(); + return (1 - 6 * p * q) / (n * p * q); + } + + } // namespace math + } // namespace boost + +// This include must be at the end, *after* the accessors +// for this distribution have been defined, in order to +// keep compilers that support two-phase lookup happy. +#include + +#endif // BOOST_MATH_SPECIAL_BINOMIAL_HPP + + diff --git a/libcxx/src/third-party/boost/math/distributions/cauchy.hpp b/libcxx/src/third-party/boost/math/distributions/cauchy.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/distributions/cauchy.hpp @@ -0,0 +1,375 @@ +// Copyright John Maddock 2006, 2007. +// Copyright Paul A. Bristow 2007. + +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_STATS_CAUCHY_HPP +#define BOOST_STATS_CAUCHY_HPP + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4127) // conditional expression is constant +#endif + +#include +#include +#include +#include +#include +#include + +namespace boost{ namespace math +{ + +template +class cauchy_distribution; + +namespace detail +{ + +template +RealType cdf_imp(const cauchy_distribution& dist, const RealType& x, bool complement) +{ + // + // This calculates the cdf of the Cauchy distribution and/or its complement. + // + // The usual formula for the Cauchy cdf is: + // + // cdf = 0.5 + atan(x)/pi + // + // But that suffers from cancellation error as x -> -INF. + // + // Recall that for x < 0: + // + // atan(x) = -pi/2 - atan(1/x) + // + // Substituting into the above we get: + // + // CDF = -atan(1/x) ; x < 0 + // + // So the procedure is to calculate the cdf for -fabs(x) + // using the above formula, and then subtract from 1 when required + // to get the result. + // + BOOST_MATH_STD_USING // for ADL of std functions + static const char* function = "boost::math::cdf(cauchy<%1%>&, %1%)"; + RealType result = 0; + RealType location = dist.location(); + RealType scale = dist.scale(); + if(false == detail::check_location(function, location, &result, Policy())) + { + return result; + } + if(false == detail::check_scale(function, scale, &result, Policy())) + { + return result; + } + if(std::numeric_limits::has_infinity && x == std::numeric_limits::infinity()) + { // cdf +infinity is unity. + return static_cast((complement) ? 0 : 1); + } + if(std::numeric_limits::has_infinity && x == -std::numeric_limits::infinity()) + { // cdf -infinity is zero. + return static_cast((complement) ? 1 : 0); + } + if(false == detail::check_x(function, x, &result, Policy())) + { // Catches x == NaN + return result; + } + RealType mx = -fabs((x - location) / scale); // scale is > 0 + if(mx > -tools::epsilon() / 8) + { // special case first: x extremely close to location. + return 0.5; + } + result = -atan(1 / mx) / constants::pi(); + return (((x > location) != complement) ? 1 - result : result); +} // cdf + +template +RealType quantile_imp( + const cauchy_distribution& dist, + const RealType& p, + bool complement) +{ + // This routine implements the quantile for the Cauchy distribution, + // the value p may be the probability, or its complement if complement=true. + // + // The procedure first performs argument reduction on p to avoid error + // when calculating the tangent, then calculates the distance from the + // mid-point of the distribution. This is either added or subtracted + // from the location parameter depending on whether `complement` is true. + // + static const char* function = "boost::math::quantile(cauchy<%1%>&, %1%)"; + BOOST_MATH_STD_USING // for ADL of std functions + + RealType result = 0; + RealType location = dist.location(); + RealType scale = dist.scale(); + if(false == detail::check_location(function, location, &result, Policy())) + { + return result; + } + if(false == detail::check_scale(function, scale, &result, Policy())) + { + return result; + } + if(false == detail::check_probability(function, p, &result, Policy())) + { + return result; + } + // Special cases: + if(p == 1) + { + return (complement ? -1 : 1) * policies::raise_overflow_error(function, 0, Policy()); + } + if(p == 0) + { + return (complement ? 1 : -1) * policies::raise_overflow_error(function, 0, Policy()); + } + + RealType P = p - floor(p); // argument reduction of p: + if(P > 0.5) + { + P = P - 1; + } + if(P == 0.5) // special case: + { + return location; + } + result = -scale / tan(constants::pi() * P); + return complement ? RealType(location - result) : RealType(location + result); +} // quantile + +} // namespace detail + +template > +class cauchy_distribution +{ +public: + typedef RealType value_type; + typedef Policy policy_type; + + cauchy_distribution(RealType l_location = 0, RealType l_scale = 1) + : m_a(l_location), m_hg(l_scale) + { + static const char* function = "boost::math::cauchy_distribution<%1%>::cauchy_distribution"; + RealType result; + detail::check_location(function, l_location, &result, Policy()); + detail::check_scale(function, l_scale, &result, Policy()); + } // cauchy_distribution + + RealType location()const + { + return m_a; + } + RealType scale()const + { + return m_hg; + } + +private: + RealType m_a; // The location, this is the median of the distribution. + RealType m_hg; // The scale )or shape), this is the half width at half height. +}; + +typedef cauchy_distribution cauchy; + +#ifdef __cpp_deduction_guides +template +cauchy_distribution(RealType)->cauchy_distribution::type>; +template +cauchy_distribution(RealType,RealType)->cauchy_distribution::type>; +#endif + +template +inline const std::pair range(const cauchy_distribution&) +{ // Range of permissible values for random variable x. + if (std::numeric_limits::has_infinity) + { + return std::pair(-std::numeric_limits::infinity(), std::numeric_limits::infinity()); // - to + infinity. + } + else + { // Can only use max_value. + using boost::math::tools::max_value; + return std::pair(-max_value(), max_value()); // - to + max. + } +} + +template +inline const std::pair support(const cauchy_distribution& ) +{ // Range of supported values for random variable x. + // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. + if (std::numeric_limits::has_infinity) + { + return std::pair(-std::numeric_limits::infinity(), std::numeric_limits::infinity()); // - to + infinity. + } + else + { // Can only use max_value. + using boost::math::tools::max_value; + return std::pair(-tools::max_value(), max_value()); // - to + max. + } +} + +template +inline RealType pdf(const cauchy_distribution& dist, const RealType& x) +{ + BOOST_MATH_STD_USING // for ADL of std functions + + static const char* function = "boost::math::pdf(cauchy<%1%>&, %1%)"; + RealType result = 0; + RealType location = dist.location(); + RealType scale = dist.scale(); + if(false == detail::check_scale("boost::math::pdf(cauchy<%1%>&, %1%)", scale, &result, Policy())) + { + return result; + } + if(false == detail::check_location("boost::math::pdf(cauchy<%1%>&, %1%)", location, &result, Policy())) + { + return result; + } + if((boost::math::isinf)(x)) + { + return 0; // pdf + and - infinity is zero. + } + // These produce MSVC 4127 warnings, so the above used instead. + //if(std::numeric_limits::has_infinity && abs(x) == std::numeric_limits::infinity()) + //{ // pdf + and - infinity is zero. + // return 0; + //} + + if(false == detail::check_x(function, x, &result, Policy())) + { // Catches x = NaN + return result; + } + + RealType xs = (x - location) / scale; + result = 1 / (constants::pi() * scale * (1 + xs * xs)); + return result; +} // pdf + +template +inline RealType cdf(const cauchy_distribution& dist, const RealType& x) +{ + return detail::cdf_imp(dist, x, false); +} // cdf + +template +inline RealType quantile(const cauchy_distribution& dist, const RealType& p) +{ + return detail::quantile_imp(dist, p, false); +} // quantile + +template +inline RealType cdf(const complemented2_type, RealType>& c) +{ + return detail::cdf_imp(c.dist, c.param, true); +} // cdf complement + +template +inline RealType quantile(const complemented2_type, RealType>& c) +{ + return detail::quantile_imp(c.dist, c.param, true); +} // quantile complement + +template +inline RealType mean(const cauchy_distribution&) +{ // There is no mean: + typedef typename Policy::assert_undefined_type assert_type; + static_assert(assert_type::value == 0, "assert type is undefined"); + + return policies::raise_domain_error( + "boost::math::mean(cauchy<%1%>&)", + "The Cauchy distribution does not have a mean: " + "the only possible return value is %1%.", + std::numeric_limits::quiet_NaN(), Policy()); +} + +template +inline RealType variance(const cauchy_distribution& /*dist*/) +{ + // There is no variance: + typedef typename Policy::assert_undefined_type assert_type; + static_assert(assert_type::value == 0, "assert type is undefined"); + + return policies::raise_domain_error( + "boost::math::variance(cauchy<%1%>&)", + "The Cauchy distribution does not have a variance: " + "the only possible return value is %1%.", + std::numeric_limits::quiet_NaN(), Policy()); +} + +template +inline RealType mode(const cauchy_distribution& dist) +{ + return dist.location(); +} + +template +inline RealType median(const cauchy_distribution& dist) +{ + return dist.location(); +} +template +inline RealType skewness(const cauchy_distribution& /*dist*/) +{ + // There is no skewness: + typedef typename Policy::assert_undefined_type assert_type; + static_assert(assert_type::value == 0, "assert type is undefined"); + + return policies::raise_domain_error( + "boost::math::skewness(cauchy<%1%>&)", + "The Cauchy distribution does not have a skewness: " + "the only possible return value is %1%.", + std::numeric_limits::quiet_NaN(), Policy()); // infinity? +} + +template +inline RealType kurtosis(const cauchy_distribution& /*dist*/) +{ + // There is no kurtosis: + typedef typename Policy::assert_undefined_type assert_type; + static_assert(assert_type::value == 0, "assert type is undefined"); + + return policies::raise_domain_error( + "boost::math::kurtosis(cauchy<%1%>&)", + "The Cauchy distribution does not have a kurtosis: " + "the only possible return value is %1%.", + std::numeric_limits::quiet_NaN(), Policy()); +} + +template +inline RealType kurtosis_excess(const cauchy_distribution& /*dist*/) +{ + // There is no kurtosis excess: + typedef typename Policy::assert_undefined_type assert_type; + static_assert(assert_type::value == 0, "assert type is undefined"); + + return policies::raise_domain_error( + "boost::math::kurtosis_excess(cauchy<%1%>&)", + "The Cauchy distribution does not have a kurtosis: " + "the only possible return value is %1%.", + std::numeric_limits::quiet_NaN(), Policy()); +} + +template +inline RealType entropy(const cauchy_distribution & dist) +{ + using std::log; + return log(2*constants::two_pi()*dist.scale()); +} + +} // namespace math +} // namespace boost + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +// This include must be at the end, *after* the accessors +// for this distribution have been defined, in order to +// keep compilers that support two-phase lookup happy. +#include + +#endif // BOOST_STATS_CAUCHY_HPP diff --git a/libcxx/src/third-party/boost/math/distributions/chi_squared.hpp b/libcxx/src/third-party/boost/math/distributions/chi_squared.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/distributions/chi_squared.hpp @@ -0,0 +1,345 @@ +// Copyright John Maddock 2006, 2007. +// Copyright Paul A. Bristow 2008, 2010. + +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_DISTRIBUTIONS_CHI_SQUARED_HPP +#define BOOST_MATH_DISTRIBUTIONS_CHI_SQUARED_HPP + +#include +#include // for incomplete beta. +#include // complements +#include // error checks +#include + +#include + +namespace boost{ namespace math{ + +template > +class chi_squared_distribution +{ +public: + using value_type = RealType; + using policy_type = Policy; + + explicit chi_squared_distribution(RealType i) : m_df(i) + { + RealType result; + detail::check_df( + "boost::math::chi_squared_distribution<%1%>::chi_squared_distribution", m_df, &result, Policy()); + } // chi_squared_distribution + + RealType degrees_of_freedom()const + { + return m_df; + } + + // Parameter estimation: + static RealType find_degrees_of_freedom( + RealType difference_from_variance, + RealType alpha, + RealType beta, + RealType variance, + RealType hint = 100); + +private: + // + // Data member: + // + RealType m_df; // degrees of freedom is a positive real number. +}; // class chi_squared_distribution + +using chi_squared = chi_squared_distribution; + +#ifdef __cpp_deduction_guides +template +chi_squared_distribution(RealType)->chi_squared_distribution::type>; +#endif + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4127) +#endif + +template +inline std::pair range(const chi_squared_distribution& /*dist*/) +{ // Range of permissible values for random variable x. + if (std::numeric_limits::has_infinity) + { + return std::pair(static_cast(0), std::numeric_limits::infinity()); // 0 to + infinity. + } + else + { + using boost::math::tools::max_value; + return std::pair(static_cast(0), max_value()); // 0 to + max. + } +} + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +template +inline std::pair support(const chi_squared_distribution& /*dist*/) +{ // Range of supported values for random variable x. + // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. + return std::pair(static_cast(0), tools::max_value()); // 0 to + infinity. +} + +template +RealType pdf(const chi_squared_distribution& dist, const RealType& chi_square) +{ + BOOST_MATH_STD_USING // for ADL of std functions + RealType degrees_of_freedom = dist.degrees_of_freedom(); + // Error check: + RealType error_result; + + static const char* function = "boost::math::pdf(const chi_squared_distribution<%1%>&, %1%)"; + + if(false == detail::check_df( + function, degrees_of_freedom, &error_result, Policy())) + return error_result; + + if((chi_square < 0) || !(boost::math::isfinite)(chi_square)) + { + return policies::raise_domain_error( + function, "Chi Square parameter was %1%, but must be > 0 !", chi_square, Policy()); + } + + if(chi_square == 0) + { + // Handle special cases: + if(degrees_of_freedom < 2) + { + return policies::raise_overflow_error( + function, 0, Policy()); + } + else if(degrees_of_freedom == 2) + { + return 0.5f; + } + else + { + return 0; + } + } + + return gamma_p_derivative(degrees_of_freedom / 2, chi_square / 2, Policy()) / 2; +} // pdf + +template +inline RealType cdf(const chi_squared_distribution& dist, const RealType& chi_square) +{ + RealType degrees_of_freedom = dist.degrees_of_freedom(); + // Error check: + RealType error_result; + static const char* function = "boost::math::cdf(const chi_squared_distribution<%1%>&, %1%)"; + + if(false == detail::check_df( + function, degrees_of_freedom, &error_result, Policy())) + return error_result; + + if((chi_square < 0) || !(boost::math::isfinite)(chi_square)) + { + return policies::raise_domain_error( + function, "Chi Square parameter was %1%, but must be > 0 !", chi_square, Policy()); + } + + return boost::math::gamma_p(degrees_of_freedom / 2, chi_square / 2, Policy()); +} // cdf + +template +inline RealType quantile(const chi_squared_distribution& dist, const RealType& p) +{ + RealType degrees_of_freedom = dist.degrees_of_freedom(); + static const char* function = "boost::math::quantile(const chi_squared_distribution<%1%>&, %1%)"; + // Error check: + RealType error_result; + if(false == + ( + detail::check_df(function, degrees_of_freedom, &error_result, Policy()) + && detail::check_probability(function, p, &error_result, Policy())) + ) + return error_result; + + return 2 * boost::math::gamma_p_inv(degrees_of_freedom / 2, p, Policy()); +} // quantile + +template +inline RealType cdf(const complemented2_type, RealType>& c) +{ + RealType const& degrees_of_freedom = c.dist.degrees_of_freedom(); + RealType const& chi_square = c.param; + static const char* function = "boost::math::cdf(const chi_squared_distribution<%1%>&, %1%)"; + // Error check: + RealType error_result; + if(false == detail::check_df( + function, degrees_of_freedom, &error_result, Policy())) + return error_result; + + if((chi_square < 0) || !(boost::math::isfinite)(chi_square)) + { + return policies::raise_domain_error( + function, "Chi Square parameter was %1%, but must be > 0 !", chi_square, Policy()); + } + + return boost::math::gamma_q(degrees_of_freedom / 2, chi_square / 2, Policy()); +} + +template +inline RealType quantile(const complemented2_type, RealType>& c) +{ + RealType const& degrees_of_freedom = c.dist.degrees_of_freedom(); + RealType const& q = c.param; + static const char* function = "boost::math::quantile(const chi_squared_distribution<%1%>&, %1%)"; + // Error check: + RealType error_result; + if(false == ( + detail::check_df(function, degrees_of_freedom, &error_result, Policy()) + && detail::check_probability(function, q, &error_result, Policy())) + ) + return error_result; + + return 2 * boost::math::gamma_q_inv(degrees_of_freedom / 2, q, Policy()); +} + +template +inline RealType mean(const chi_squared_distribution& dist) +{ // Mean of Chi-Squared distribution = v. + return dist.degrees_of_freedom(); +} // mean + +template +inline RealType variance(const chi_squared_distribution& dist) +{ // Variance of Chi-Squared distribution = 2v. + return 2 * dist.degrees_of_freedom(); +} // variance + +template +inline RealType mode(const chi_squared_distribution& dist) +{ + RealType df = dist.degrees_of_freedom(); + static const char* function = "boost::math::mode(const chi_squared_distribution<%1%>&)"; + + if(df < 2) + return policies::raise_domain_error( + function, + "Chi-Squared distribution only has a mode for degrees of freedom >= 2, but got degrees of freedom = %1%.", + df, Policy()); + return df - 2; +} + +template +inline RealType skewness(const chi_squared_distribution& dist) +{ + BOOST_MATH_STD_USING // For ADL + RealType df = dist.degrees_of_freedom(); + return sqrt (8 / df); +} + +template +inline RealType kurtosis(const chi_squared_distribution& dist) +{ + RealType df = dist.degrees_of_freedom(); + return 3 + 12 / df; +} + +template +inline RealType kurtosis_excess(const chi_squared_distribution& dist) +{ + RealType df = dist.degrees_of_freedom(); + return 12 / df; +} + +// +// Parameter estimation comes last: +// +namespace detail +{ + +template +struct df_estimator +{ + df_estimator(RealType a, RealType b, RealType variance, RealType delta) + : alpha(a), beta(b), ratio(delta/variance) + { // Constructor + } + + RealType operator()(const RealType& df) + { + if(df <= tools::min_value()) + return 1; + chi_squared_distribution cs(df); + + RealType result; + if(ratio > 0) + { + RealType r = 1 + ratio; + result = cdf(cs, quantile(complement(cs, alpha)) / r) - beta; + } + else + { // ratio <= 0 + RealType r = 1 + ratio; + result = cdf(complement(cs, quantile(cs, alpha) / r)) - beta; + } + return result; + } +private: + RealType alpha; + RealType beta; + RealType ratio; // Difference from variance / variance, so fractional. +}; + +} // namespace detail + +template +RealType chi_squared_distribution::find_degrees_of_freedom( + RealType difference_from_variance, + RealType alpha, + RealType beta, + RealType variance, + RealType hint) +{ + static const char* function = "boost::math::chi_squared_distribution<%1%>::find_degrees_of_freedom(%1%,%1%,%1%,%1%,%1%)"; + // Check for domain errors: + RealType error_result; + if(false == + detail::check_probability(function, alpha, &error_result, Policy()) + && detail::check_probability(function, beta, &error_result, Policy())) + { // Either probability is outside 0 to 1. + return error_result; + } + + if(hint <= 0) + { // No hint given, so guess df = 1. + hint = 1; + } + + detail::df_estimator f(alpha, beta, variance, difference_from_variance); + tools::eps_tolerance tol(policies::digits()); + std::uintmax_t max_iter = policies::get_max_root_iterations(); + std::pair r = + tools::bracket_and_solve_root(f, hint, RealType(2), false, tol, max_iter, Policy()); + RealType result = r.first + (r.second - r.first) / 2; + if(max_iter >= policies::get_max_root_iterations()) + { + policies::raise_evaluation_error(function, "Unable to locate solution in a reasonable time:" + " either there is no answer to how many degrees of freedom are required" + " or the answer is infinite. Current best guess is %1%", result, Policy()); + } + return result; +} + +} // namespace math +} // namespace boost + +// This include must be at the end, *after* the accessors +// for this distribution have been defined, in order to +// keep compilers that support two-phase lookup happy. +#include + +#endif // BOOST_MATH_DISTRIBUTIONS_CHI_SQUARED_HPP diff --git a/libcxx/src/third-party/boost/math/distributions/complement.hpp b/libcxx/src/third-party/boost/math/distributions/complement.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/distributions/complement.hpp @@ -0,0 +1,195 @@ +// (C) Copyright John Maddock 2006. +// (C) Copyright Paul A. Bristow 2006. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_STATS_COMPLEMENT_HPP +#define BOOST_STATS_COMPLEMENT_HPP + +// +// This code really defines our own tuple type. +// It would be nice to reuse boost::math::tuple +// while retaining our own type safety, but it's +// not clear if that's possible. In any case this +// code is *very* lightweight. +// +namespace boost{ namespace math{ + +template +struct complemented2_type +{ + complemented2_type( + const Dist& d, + const RealType& p1) + : dist(d), + param(p1) {} + + const Dist& dist; + const RealType& param; + +private: + complemented2_type& operator=(const complemented2_type&) = delete; +}; + +template +struct complemented3_type +{ + complemented3_type( + const Dist& d, + const RealType1& p1, + const RealType2& p2) + : dist(d), + param1(p1), + param2(p2) {} + + const Dist& dist; + const RealType1& param1; + const RealType2& param2; +private: + complemented3_type& operator=(const complemented3_type&) = delete; +}; + +template +struct complemented4_type +{ + complemented4_type( + const Dist& d, + const RealType1& p1, + const RealType2& p2, + const RealType3& p3) + : dist(d), + param1(p1), + param2(p2), + param3(p3) {} + + const Dist& dist; + const RealType1& param1; + const RealType2& param2; + const RealType3& param3; +private: + complemented4_type& operator=(const complemented4_type&) = delete; +}; + +template +struct complemented5_type +{ + complemented5_type( + const Dist& d, + const RealType1& p1, + const RealType2& p2, + const RealType3& p3, + const RealType4& p4) + : dist(d), + param1(p1), + param2(p2), + param3(p3), + param4(p4) {} + + const Dist& dist; + const RealType1& param1; + const RealType2& param2; + const RealType3& param3; + const RealType4& param4; +private: + complemented5_type& operator=(const complemented5_type&) = delete; +}; + +template +struct complemented6_type +{ + complemented6_type( + const Dist& d, + const RealType1& p1, + const RealType2& p2, + const RealType3& p3, + const RealType4& p4, + const RealType5& p5) + : dist(d), + param1(p1), + param2(p2), + param3(p3), + param4(p4), + param5(p5) {} + + const Dist& dist; + const RealType1& param1; + const RealType2& param2; + const RealType3& param3; + const RealType4& param4; + const RealType5& param5; +private: + complemented6_type& operator=(const complemented6_type&) = delete; +}; + +template +struct complemented7_type +{ + complemented7_type( + const Dist& d, + const RealType1& p1, + const RealType2& p2, + const RealType3& p3, + const RealType4& p4, + const RealType5& p5, + const RealType6& p6) + : dist(d), + param1(p1), + param2(p2), + param3(p3), + param4(p4), + param5(p5), + param6(p6) {} + + const Dist& dist; + const RealType1& param1; + const RealType2& param2; + const RealType3& param3; + const RealType4& param4; + const RealType5& param5; + const RealType6& param6; +private: + complemented7_type& operator=(const complemented7_type&) = delete; +}; + +template +inline complemented2_type complement(const Dist& d, const RealType& r) +{ + return complemented2_type(d, r); +} + +template +inline complemented3_type complement(const Dist& d, const RealType1& r1, const RealType2& r2) +{ + return complemented3_type(d, r1, r2); +} + +template +inline complemented4_type complement(const Dist& d, const RealType1& r1, const RealType2& r2, const RealType3& r3) +{ + return complemented4_type(d, r1, r2, r3); +} + +template +inline complemented5_type complement(const Dist& d, const RealType1& r1, const RealType2& r2, const RealType3& r3, const RealType4& r4) +{ + return complemented5_type(d, r1, r2, r3, r4); +} + +template +inline complemented6_type complement(const Dist& d, const RealType1& r1, const RealType2& r2, const RealType3& r3, const RealType4& r4, const RealType5& r5) +{ + return complemented6_type(d, r1, r2, r3, r4, r5); +} + +template +inline complemented7_type complement(const Dist& d, const RealType1& r1, const RealType2& r2, const RealType3& r3, const RealType4& r4, const RealType5& r5, const RealType6& r6) +{ + return complemented7_type(d, r1, r2, r3, r4, r5, r6); +} + +} // namespace math +} // namespace boost + +#endif // BOOST_STATS_COMPLEMENT_HPP + diff --git a/libcxx/src/third-party/boost/math/distributions/detail/common_error_handling.hpp b/libcxx/src/third-party/boost/math/distributions/detail/common_error_handling.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/distributions/detail/common_error_handling.hpp @@ -0,0 +1,223 @@ +// Copyright John Maddock 2006, 2007. +// Copyright Paul A. Bristow 2006, 2007, 2012. + +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_DISTRIBUTIONS_COMMON_ERROR_HANDLING_HPP +#define BOOST_MATH_DISTRIBUTIONS_COMMON_ERROR_HANDLING_HPP + +#include +#include +// using boost::math::isfinite; +// using boost::math::isnan; + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable: 4702) // unreachable code (return after domain_error throw). +#endif + +namespace boost{ namespace math{ namespace detail +{ + +template +inline bool check_probability(const char* function, RealType const& prob, RealType* result, const Policy& pol) +{ + if((prob < 0) || (prob > 1) || !(boost::math::isfinite)(prob)) + { + *result = policies::raise_domain_error( + function, + "Probability argument is %1%, but must be >= 0 and <= 1 !", prob, pol); + return false; + } + return true; +} + +template +inline bool check_df(const char* function, RealType const& df, RealType* result, const Policy& pol) +{ // df > 0 but NOT +infinity allowed. + if((df <= 0) || !(boost::math::isfinite)(df)) + { + *result = policies::raise_domain_error( + function, + "Degrees of freedom argument is %1%, but must be > 0 !", df, pol); + return false; + } + return true; +} + +template +inline bool check_df_gt0_to_inf(const char* function, RealType const& df, RealType* result, const Policy& pol) +{ // df > 0 or +infinity are allowed. + if( (df <= 0) || (boost::math::isnan)(df) ) + { // is bad df <= 0 or NaN or -infinity. + *result = policies::raise_domain_error( + function, + "Degrees of freedom argument is %1%, but must be > 0 !", df, pol); + return false; + } + return true; +} // check_df_gt0_to_inf + + +template +inline bool check_scale( + const char* function, + RealType scale, + RealType* result, + const Policy& pol) +{ + if((scale <= 0) || !(boost::math::isfinite)(scale)) + { // Assume scale == 0 is NOT valid for any distribution. + *result = policies::raise_domain_error( + function, + "Scale parameter is %1%, but must be > 0 !", scale, pol); + return false; + } + return true; +} + +template +inline bool check_location( + const char* function, + RealType location, + RealType* result, + const Policy& pol) +{ + if(!(boost::math::isfinite)(location)) + { + *result = policies::raise_domain_error( + function, + "Location parameter is %1%, but must be finite!", location, pol); + return false; + } + return true; +} + +template +inline bool check_x( + const char* function, + RealType x, + RealType* result, + const Policy& pol) +{ + // Note that this test catches both infinity and NaN. + // Some distributions permit x to be infinite, so these must be tested 1st and return, + // leaving this test to catch any NaNs. + // See Normal, Logistic, Laplace and Cauchy for example. + if(!(boost::math::isfinite)(x)) + { + *result = policies::raise_domain_error( + function, + "Random variate x is %1%, but must be finite!", x, pol); + return false; + } + return true; +} // bool check_x + +template +inline bool check_x_not_NaN( + const char* function, + RealType x, + RealType* result, + const Policy& pol) +{ + // Note that this test catches only NaN. + // Some distributions permit x to be infinite, leaving this test to catch any NaNs. + // See Normal, Logistic, Laplace and Cauchy for example. + if ((boost::math::isnan)(x)) + { + *result = policies::raise_domain_error( + function, + "Random variate x is %1%, but must be finite or + or - infinity!", x, pol); + return false; + } + return true; +} // bool check_x_not_NaN + +template +inline bool check_x_gt0( + const char* function, + RealType x, + RealType* result, + const Policy& pol) +{ + if(x <= 0) + { + *result = policies::raise_domain_error( + function, + "Random variate x is %1%, but must be > 0!", x, pol); + return false; + } + + return true; + // Note that this test catches both infinity and NaN. + // Some special cases permit x to be infinite, so these must be tested 1st, + // leaving this test to catch any NaNs. See Normal and cauchy for example. +} // bool check_x_gt0 + +template +inline bool check_positive_x( + const char* function, + RealType x, + RealType* result, + const Policy& pol) +{ + if(!(boost::math::isfinite)(x) || (x < 0)) + { + *result = policies::raise_domain_error( + function, + "Random variate x is %1%, but must be finite and >= 0!", x, pol); + return false; + } + return true; + // Note that this test catches both infinity and NaN. + // Some special cases permit x to be infinite, so these must be tested 1st, + // leaving this test to catch any NaNs. see Normal and cauchy for example. +} + +template +inline bool check_non_centrality( + const char* function, + RealType ncp, + RealType* result, + const Policy& pol) +{ + if((ncp < 0) || !(boost::math::isfinite)(ncp)) + { // Assume scale == 0 is NOT valid for any distribution. + *result = policies::raise_domain_error( + function, + "Non centrality parameter is %1%, but must be > 0 !", ncp, pol); + return false; + } + return true; +} + +template +inline bool check_finite( + const char* function, + RealType x, + RealType* result, + const Policy& pol) +{ + if(!(boost::math::isfinite)(x)) + { // Assume scale == 0 is NOT valid for any distribution. + *result = policies::raise_domain_error( + function, + "Parameter is %1%, but must be finite !", x, pol); + return false; + } + return true; +} + +} // namespace detail +} // namespace math +} // namespace boost + +#ifdef _MSC_VER +# pragma warning(pop) +#endif + +#endif // BOOST_MATH_DISTRIBUTIONS_COMMON_ERROR_HANDLING_HPP diff --git a/libcxx/src/third-party/boost/math/distributions/detail/derived_accessors.hpp b/libcxx/src/third-party/boost/math/distributions/detail/derived_accessors.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/distributions/detail/derived_accessors.hpp @@ -0,0 +1,170 @@ +// Copyright John Maddock 2006. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_STATS_DERIVED_HPP +#define BOOST_STATS_DERIVED_HPP + +// This file implements various common properties of distributions +// that can be implemented in terms of other properties: +// variance OR standard deviation (see note below), +// hazard, cumulative hazard (chf), coefficient_of_variation. +// +// Note that while both variance and standard_deviation are provided +// here, each distribution MUST SPECIALIZE AT LEAST ONE OF THESE +// otherwise these two versions will just call each other over and over +// until stack space runs out ... + +// Of course there may be more efficient means of implementing these +// that are specific to a particular distribution, but these generic +// versions give these properties "for free" with most distributions. +// +// In order to make use of this header, it must be included AT THE END +// of the distribution header, AFTER the distribution and its core +// property accessors have been defined: this is so that compilers +// that implement 2-phase lookup and early-type-checking of templates +// can find the definitions referred to herein. +// + +#include +#include + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable: 4723) // potential divide by 0 +// Suppressing spurious warning in coefficient_of_variation +#endif + +namespace boost{ namespace math{ + +template +typename Distribution::value_type variance(const Distribution& dist); + +template +inline typename Distribution::value_type standard_deviation(const Distribution& dist) +{ + BOOST_MATH_STD_USING // ADL of sqrt. + return sqrt(variance(dist)); +} + +template +inline typename Distribution::value_type variance(const Distribution& dist) +{ + typename Distribution::value_type result = standard_deviation(dist); + return result * result; +} + +template +inline typename Distribution::value_type hazard(const Distribution& dist, const RealType& x) +{ // hazard function + // http://www.itl.nist.gov/div898/handbook/eda/section3/eda362.htm#HAZ + typedef typename Distribution::value_type value_type; + typedef typename Distribution::policy_type policy_type; + value_type p = cdf(complement(dist, x)); + value_type d = pdf(dist, x); + if(d > p * tools::max_value()) + return policies::raise_overflow_error( + "boost::math::hazard(const Distribution&, %1%)", nullptr, policy_type()); + if(d == 0) + { + // This protects against 0/0, but is it the right thing to do? + return 0; + } + return d / p; +} + +template +inline typename Distribution::value_type chf(const Distribution& dist, const RealType& x) +{ // cumulative hazard function. + // http://www.itl.nist.gov/div898/handbook/eda/section3/eda362.htm#HAZ + BOOST_MATH_STD_USING + return -log(cdf(complement(dist, x))); +} + +template +inline typename Distribution::value_type coefficient_of_variation(const Distribution& dist) +{ + typedef typename Distribution::value_type value_type; + typedef typename Distribution::policy_type policy_type; + + using std::abs; + + value_type m = mean(dist); + value_type d = standard_deviation(dist); + if((abs(m) < 1) && (d > abs(m) * tools::max_value())) + { // Checks too that m is not zero, + return policies::raise_overflow_error("boost::math::coefficient_of_variation(const Distribution&, %1%)", nullptr, policy_type()); + } + return d / m; // so MSVC warning on zerodivide is spurious, and suppressed. +} +// +// Next follow overloads of some of the standard accessors with mixed +// argument types. We just use a typecast to forward on to the "real" +// implementation with all arguments of the same type: +// +template +inline typename Distribution::value_type pdf(const Distribution& dist, const RealType& x) +{ + typedef typename Distribution::value_type value_type; + return pdf(dist, static_cast(x)); +} +template +inline typename Distribution::value_type logpdf(const Distribution& dist, const RealType& x) +{ + using std::log; + typedef typename Distribution::value_type value_type; + return log(pdf(dist, static_cast(x))); +} +template +inline typename Distribution::value_type cdf(const Distribution& dist, const RealType& x) +{ + typedef typename Distribution::value_type value_type; + return cdf(dist, static_cast(x)); +} +template +inline typename Distribution::value_type quantile(const Distribution& dist, const RealType& x) +{ + typedef typename Distribution::value_type value_type; + return quantile(dist, static_cast(x)); +} +/* +template +inline typename Distribution::value_type chf(const Distribution& dist, const RealType& x) +{ + typedef typename Distribution::value_type value_type; + return chf(dist, static_cast(x)); +} +*/ +template +inline typename Distribution::value_type cdf(const complemented2_type& c) +{ + typedef typename Distribution::value_type value_type; + return cdf(complement(c.dist, static_cast(c.param))); +} + +template +inline typename Distribution::value_type quantile(const complemented2_type& c) +{ + typedef typename Distribution::value_type value_type; + return quantile(complement(c.dist, static_cast(c.param))); +} + +template +inline typename Dist::value_type median(const Dist& d) +{ // median - default definition for those distributions for which a + // simple closed form is not known, + // and for which a domain_error and/or NaN generating function is NOT defined. + typedef typename Dist::value_type value_type; + return quantile(d, static_cast(0.5f)); +} + +} // namespace math +} // namespace boost + + +#ifdef _MSC_VER +# pragma warning(pop) +#endif + +#endif // BOOST_STATS_DERIVED_HPP diff --git a/libcxx/src/third-party/boost/math/distributions/detail/generic_mode.hpp b/libcxx/src/third-party/boost/math/distributions/detail/generic_mode.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/distributions/detail/generic_mode.hpp @@ -0,0 +1,149 @@ +// Copyright John Maddock 2008. + +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_DISTRIBUTIONS_DETAIL_MODE_HPP +#define BOOST_MATH_DISTRIBUTIONS_DETAIL_MODE_HPP + +#include // function minimization for mode +#include +#include + +namespace boost{ namespace math{ namespace detail{ + +template +struct pdf_minimizer +{ + pdf_minimizer(const Dist& d) + : dist(d) {} + + typename Dist::value_type operator()(const typename Dist::value_type& x) + { + return -pdf(dist, x); + } +private: + Dist dist; +}; + +template +typename Dist::value_type generic_find_mode(const Dist& dist, typename Dist::value_type guess, const char* function, typename Dist::value_type step = 0) +{ + BOOST_MATH_STD_USING + typedef typename Dist::value_type value_type; + typedef typename Dist::policy_type policy_type; + // + // Need to begin by bracketing the maxima of the PDF: + // + value_type maxval; + value_type upper_bound = guess; + value_type lower_bound; + value_type v = pdf(dist, guess); + if(v == 0) + { + // + // Oops we don't know how to handle this, or even in which + // direction we should move in, treat as an evaluation error: + // + return policies::raise_evaluation_error( + function, + "Could not locate a starting location for the search for the mode, original guess was %1%", guess, policy_type()); + } + do + { + maxval = v; + if(step != 0) + upper_bound += step; + else + upper_bound *= 2; + v = pdf(dist, upper_bound); + }while(maxval < v); + + lower_bound = upper_bound; + do + { + maxval = v; + if(step != 0) + lower_bound -= step; + else + lower_bound /= 2; + v = pdf(dist, lower_bound); + }while(maxval < v); + + std::uintmax_t max_iter = policies::get_max_root_iterations(); + + value_type result = tools::brent_find_minima( + pdf_minimizer(dist), + lower_bound, + upper_bound, + policies::digits(), + max_iter).first; + if(max_iter >= policies::get_max_root_iterations()) + { + return policies::raise_evaluation_error( + function, + "Unable to locate solution in a reasonable time:" + " either there is no answer to the mode of the distribution" + " or the answer is infinite. Current best guess is %1%", result, policy_type()); + } + return result; +} +// +// As above,but confined to the interval [0,1]: +// +template +typename Dist::value_type generic_find_mode_01(const Dist& dist, typename Dist::value_type guess, const char* function) +{ + BOOST_MATH_STD_USING + typedef typename Dist::value_type value_type; + typedef typename Dist::policy_type policy_type; + // + // Need to begin by bracketing the maxima of the PDF: + // + value_type maxval; + value_type upper_bound = guess; + value_type lower_bound; + value_type v = pdf(dist, guess); + do + { + maxval = v; + upper_bound = 1 - (1 - upper_bound) / 2; + if(upper_bound == 1) + return 1; + v = pdf(dist, upper_bound); + }while(maxval < v); + + lower_bound = upper_bound; + do + { + maxval = v; + lower_bound /= 2; + if(lower_bound < tools::min_value()) + return 0; + v = pdf(dist, lower_bound); + }while(maxval < v); + + std::uintmax_t max_iter = policies::get_max_root_iterations(); + + value_type result = tools::brent_find_minima( + pdf_minimizer(dist), + lower_bound, + upper_bound, + policies::digits(), + max_iter).first; + if(max_iter >= policies::get_max_root_iterations()) + { + return policies::raise_evaluation_error( + function, + "Unable to locate solution in a reasonable time:" + " either there is no answer to the mode of the distribution" + " or the answer is infinite. Current best guess is %1%", result, policy_type()); + } + return result; +} + +}}} // namespaces + +#endif // BOOST_MATH_DISTRIBUTIONS_DETAIL_MODE_HPP diff --git a/libcxx/src/third-party/boost/math/distributions/detail/generic_quantile.hpp b/libcxx/src/third-party/boost/math/distributions/detail/generic_quantile.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/distributions/detail/generic_quantile.hpp @@ -0,0 +1,97 @@ +// Copyright John Maddock 2008. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_DISTIBUTIONS_DETAIL_GENERIC_QUANTILE_HPP +#define BOOST_MATH_DISTIBUTIONS_DETAIL_GENERIC_QUANTILE_HPP + +namespace boost{ namespace math{ namespace detail{ + +template +struct generic_quantile_finder +{ + using value_type = typename Dist::value_type; + using policy_type = typename Dist::policy_type; + + generic_quantile_finder(const Dist& d, value_type t, bool c) + : dist(d), target(t), comp(c) {} + + value_type operator()(const value_type& x) + { + return comp ? + value_type(target - cdf(complement(dist, x))) + : value_type(cdf(dist, x) - target); + } + +private: + Dist dist; + value_type target; + bool comp; +}; + +template +inline T check_range_result(const T& x, const Policy& pol, const char* function) +{ + if((x >= 0) && (x < tools::min_value())) + { + return policies::raise_underflow_error(function, nullptr, pol); + } + if(x <= -tools::max_value()) + { + return -policies::raise_overflow_error(function, nullptr, pol); + } + if(x >= tools::max_value()) + { + return policies::raise_overflow_error(function, nullptr, pol); + } + return x; +} + +template +typename Dist::value_type generic_quantile(const Dist& dist, const typename Dist::value_type& p, const typename Dist::value_type& guess, bool comp, const char* function) +{ + using value_type = typename Dist::value_type; + using policy_type = typename Dist::policy_type; + using forwarding_policy = typename policies::normalise< + policy_type, + policies::promote_float, + policies::promote_double, + policies::discrete_quantile<>, + policies::assert_undefined<> >::type; + + // + // Special cases first: + // + if(p == 0) + { + return comp + ? check_range_result(range(dist).second, forwarding_policy(), function) + : check_range_result(range(dist).first, forwarding_policy(), function); + } + if(p == 1) + { + return !comp + ? check_range_result(range(dist).second, forwarding_policy(), function) + : check_range_result(range(dist).first, forwarding_policy(), function); + } + + generic_quantile_finder f(dist, p, comp); + tools::eps_tolerance tol(policies::digits() - 3); + std::uintmax_t max_iter = policies::get_max_root_iterations(); + std::pair ir = tools::bracket_and_solve_root( + f, guess, value_type(2), true, tol, max_iter, forwarding_policy()); + value_type result = ir.first + (ir.second - ir.first) / 2; + if(max_iter >= policies::get_max_root_iterations()) + { + return policies::raise_evaluation_error(function, "Unable to locate solution in a reasonable time:" + " either there is no answer to quantile" + " or the answer is infinite. Current best guess is %1%", result, forwarding_policy()); + } + return result; +} + +}}} // namespaces + +#endif // BOOST_MATH_DISTIBUTIONS_DETAIL_GENERIC_QUANTILE_HPP + diff --git a/libcxx/src/third-party/boost/math/distributions/detail/hypergeometric_cdf.hpp b/libcxx/src/third-party/boost/math/distributions/detail/hypergeometric_cdf.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/distributions/detail/hypergeometric_cdf.hpp @@ -0,0 +1,100 @@ +// Copyright 2008 John Maddock +// +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_DISTRIBUTIONS_DETAIL_HG_CDF_HPP +#define BOOST_MATH_DISTRIBUTIONS_DETAIL_HG_CDF_HPP + +#include +#include + +namespace boost{ namespace math{ namespace detail{ + + template + T hypergeometric_cdf_imp(unsigned x, unsigned r, unsigned n, unsigned N, bool invert, const Policy& pol) + { +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable:4267) +#endif + BOOST_MATH_STD_USING + T result = 0; + T mode = floor(T(r + 1) * T(n + 1) / (N + 2)); + if(x < mode) + { + result = hypergeometric_pdf(x, r, n, N, pol); + T diff = result; + unsigned lower_limit = static_cast((std::max)(0, static_cast(n + r) - static_cast(N))); + while(diff > (invert ? T(1) : result) * tools::epsilon()) + { + diff = T(x) * T((N + x) - n - r) * diff / (T(1 + n - x) * T(1 + r - x)); + result += diff; + BOOST_MATH_INSTRUMENT_VARIABLE(x); + BOOST_MATH_INSTRUMENT_VARIABLE(diff); + BOOST_MATH_INSTRUMENT_VARIABLE(result); + if(x == lower_limit) + break; + --x; + } + } + else + { + invert = !invert; + unsigned upper_limit = (std::min)(r, n); + if(x != upper_limit) + { + ++x; + result = hypergeometric_pdf(x, r, n, N, pol); + T diff = result; + while((x <= upper_limit) && (diff > (invert ? T(1) : result) * tools::epsilon())) + { + diff = T(n - x) * T(r - x) * diff / (T(x + 1) * T((N + x + 1) - n - r)); + result += diff; + ++x; + BOOST_MATH_INSTRUMENT_VARIABLE(x); + BOOST_MATH_INSTRUMENT_VARIABLE(diff); + BOOST_MATH_INSTRUMENT_VARIABLE(result); + } + } + } + if(invert) + result = 1 - result; + return result; +#ifdef _MSC_VER +# pragma warning(pop) +#endif + } + + template + inline T hypergeometric_cdf(unsigned x, unsigned r, unsigned n, unsigned N, bool invert, const Policy&) + { + BOOST_FPU_EXCEPTION_GUARD + typedef typename tools::promote_args::type result_type; + typedef typename policies::evaluation::type value_type; + typedef typename policies::normalise< + Policy, + policies::promote_float, + policies::promote_double, + policies::discrete_quantile<>, + policies::assert_undefined<> >::type forwarding_policy; + + value_type result; + result = detail::hypergeometric_cdf_imp(x, r, n, N, invert, forwarding_policy()); + if(result > 1) + { + result = 1; + } + if(result < 0) + { + result = 0; + } + return policies::checked_narrowing_cast(result, "boost::math::hypergeometric_cdf<%1%>(%1%,%1%,%1%,%1%)"); + } + +}}} // namespaces + +#endif + diff --git a/libcxx/src/third-party/boost/math/distributions/detail/hypergeometric_pdf.hpp b/libcxx/src/third-party/boost/math/distributions/detail/hypergeometric_pdf.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/distributions/detail/hypergeometric_pdf.hpp @@ -0,0 +1,488 @@ +// Copyright 2008 Gautam Sewani +// Copyright 2008 John Maddock +// +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_DISTRIBUTIONS_DETAIL_HG_PDF_HPP +#define BOOST_MATH_DISTRIBUTIONS_DETAIL_HG_PDF_HPP + +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_MATH_INSTRUMENT +#include +#endif + +namespace boost{ namespace math{ namespace detail{ + +template +void bubble_down_one(T* first, T* last, Func f) +{ + using std::swap; + T* next = first; + ++next; + while((next != last) && (!f(*first, *next))) + { + swap(*first, *next); + ++first; + ++next; + } +} + +template +struct sort_functor +{ + sort_functor(const T* exponents) : m_exponents(exponents){} + bool operator()(int i, int j) + { + return m_exponents[i] > m_exponents[j]; + } +private: + const T* m_exponents; +}; + +template +T hypergeometric_pdf_lanczos_imp(T /*dummy*/, unsigned x, unsigned r, unsigned n, unsigned N, const Lanczos&, const Policy&) +{ + BOOST_MATH_STD_USING + + BOOST_MATH_INSTRUMENT_FPU + BOOST_MATH_INSTRUMENT_VARIABLE(x); + BOOST_MATH_INSTRUMENT_VARIABLE(r); + BOOST_MATH_INSTRUMENT_VARIABLE(n); + BOOST_MATH_INSTRUMENT_VARIABLE(N); + BOOST_MATH_INSTRUMENT_VARIABLE(typeid(Lanczos).name()); + + T bases[9] = { + T(n) + static_cast(Lanczos::g()) + 0.5f, + T(r) + static_cast(Lanczos::g()) + 0.5f, + T(N - n) + static_cast(Lanczos::g()) + 0.5f, + T(N - r) + static_cast(Lanczos::g()) + 0.5f, + 1 / (T(N) + static_cast(Lanczos::g()) + 0.5f), + 1 / (T(x) + static_cast(Lanczos::g()) + 0.5f), + 1 / (T(n - x) + static_cast(Lanczos::g()) + 0.5f), + 1 / (T(r - x) + static_cast(Lanczos::g()) + 0.5f), + 1 / (T(N - n - r + x) + static_cast(Lanczos::g()) + 0.5f) + }; + T exponents[9] = { + n + T(0.5f), + r + T(0.5f), + N - n + T(0.5f), + N - r + T(0.5f), + N + T(0.5f), + x + T(0.5f), + n - x + T(0.5f), + r - x + T(0.5f), + N - n - r + x + T(0.5f) + }; + int base_e_factors[9] = { + -1, -1, -1, -1, 1, 1, 1, 1, 1 + }; + int sorted_indexes[9] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8 + }; +#ifdef BOOST_MATH_INSTRUMENT + BOOST_MATH_INSTRUMENT_FPU + for(unsigned i = 0; i < 9; ++i) + { + BOOST_MATH_INSTRUMENT_VARIABLE(i); + BOOST_MATH_INSTRUMENT_VARIABLE(bases[i]); + BOOST_MATH_INSTRUMENT_VARIABLE(exponents[i]); + BOOST_MATH_INSTRUMENT_VARIABLE(base_e_factors[i]); + BOOST_MATH_INSTRUMENT_VARIABLE(sorted_indexes[i]); + } +#endif + std::sort(sorted_indexes, sorted_indexes + 9, sort_functor(exponents)); +#ifdef BOOST_MATH_INSTRUMENT + BOOST_MATH_INSTRUMENT_FPU + for(unsigned i = 0; i < 9; ++i) + { + BOOST_MATH_INSTRUMENT_VARIABLE(i); + BOOST_MATH_INSTRUMENT_VARIABLE(bases[i]); + BOOST_MATH_INSTRUMENT_VARIABLE(exponents[i]); + BOOST_MATH_INSTRUMENT_VARIABLE(base_e_factors[i]); + BOOST_MATH_INSTRUMENT_VARIABLE(sorted_indexes[i]); + } +#endif + + do{ + exponents[sorted_indexes[0]] -= exponents[sorted_indexes[1]]; + bases[sorted_indexes[1]] *= bases[sorted_indexes[0]]; + if((bases[sorted_indexes[1]] < tools::min_value()) && (exponents[sorted_indexes[1]] != 0)) + { + return 0; + } + base_e_factors[sorted_indexes[1]] += base_e_factors[sorted_indexes[0]]; + bubble_down_one(sorted_indexes, sorted_indexes + 9, sort_functor(exponents)); + +#ifdef BOOST_MATH_INSTRUMENT + for(unsigned i = 0; i < 9; ++i) + { + BOOST_MATH_INSTRUMENT_VARIABLE(i); + BOOST_MATH_INSTRUMENT_VARIABLE(bases[i]); + BOOST_MATH_INSTRUMENT_VARIABLE(exponents[i]); + BOOST_MATH_INSTRUMENT_VARIABLE(base_e_factors[i]); + BOOST_MATH_INSTRUMENT_VARIABLE(sorted_indexes[i]); + } +#endif + }while(exponents[sorted_indexes[1]] > 1); + + // + // Combine equal powers: + // + int j = 8; + while(exponents[sorted_indexes[j]] == 0) --j; + while(j) + { + while(j && (exponents[sorted_indexes[j-1]] == exponents[sorted_indexes[j]])) + { + bases[sorted_indexes[j-1]] *= bases[sorted_indexes[j]]; + exponents[sorted_indexes[j]] = 0; + base_e_factors[sorted_indexes[j-1]] += base_e_factors[sorted_indexes[j]]; + bubble_down_one(sorted_indexes + j, sorted_indexes + 9, sort_functor(exponents)); + --j; + } + --j; + +#ifdef BOOST_MATH_INSTRUMENT + BOOST_MATH_INSTRUMENT_VARIABLE(j); + for(unsigned i = 0; i < 9; ++i) + { + BOOST_MATH_INSTRUMENT_VARIABLE(i); + BOOST_MATH_INSTRUMENT_VARIABLE(bases[i]); + BOOST_MATH_INSTRUMENT_VARIABLE(exponents[i]); + BOOST_MATH_INSTRUMENT_VARIABLE(base_e_factors[i]); + BOOST_MATH_INSTRUMENT_VARIABLE(sorted_indexes[i]); + } +#endif + } + +#ifdef BOOST_MATH_INSTRUMENT + BOOST_MATH_INSTRUMENT_FPU + for(unsigned i = 0; i < 9; ++i) + { + BOOST_MATH_INSTRUMENT_VARIABLE(i); + BOOST_MATH_INSTRUMENT_VARIABLE(bases[i]); + BOOST_MATH_INSTRUMENT_VARIABLE(exponents[i]); + BOOST_MATH_INSTRUMENT_VARIABLE(base_e_factors[i]); + BOOST_MATH_INSTRUMENT_VARIABLE(sorted_indexes[i]); + } +#endif + + T result; + BOOST_MATH_INSTRUMENT_VARIABLE(bases[sorted_indexes[0]] * exp(static_cast(base_e_factors[sorted_indexes[0]]))); + BOOST_MATH_INSTRUMENT_VARIABLE(exponents[sorted_indexes[0]]); + { + BOOST_FPU_EXCEPTION_GUARD + result = pow(bases[sorted_indexes[0]] * exp(static_cast(base_e_factors[sorted_indexes[0]])), exponents[sorted_indexes[0]]); + } + BOOST_MATH_INSTRUMENT_VARIABLE(result); + for(unsigned i = 1; (i < 9) && (exponents[sorted_indexes[i]] > 0); ++i) + { + BOOST_FPU_EXCEPTION_GUARD + if(result < tools::min_value()) + return 0; // short circuit further evaluation + if(exponents[sorted_indexes[i]] == 1) + result *= bases[sorted_indexes[i]] * exp(static_cast(base_e_factors[sorted_indexes[i]])); + else if(exponents[sorted_indexes[i]] == 0.5f) + result *= sqrt(bases[sorted_indexes[i]] * exp(static_cast(base_e_factors[sorted_indexes[i]]))); + else + result *= pow(bases[sorted_indexes[i]] * exp(static_cast(base_e_factors[sorted_indexes[i]])), exponents[sorted_indexes[i]]); + + BOOST_MATH_INSTRUMENT_VARIABLE(result); + } + + result *= Lanczos::lanczos_sum_expG_scaled(static_cast(n + 1)) + * Lanczos::lanczos_sum_expG_scaled(static_cast(r + 1)) + * Lanczos::lanczos_sum_expG_scaled(static_cast(N - n + 1)) + * Lanczos::lanczos_sum_expG_scaled(static_cast(N - r + 1)) + / + ( Lanczos::lanczos_sum_expG_scaled(static_cast(N + 1)) + * Lanczos::lanczos_sum_expG_scaled(static_cast(x + 1)) + * Lanczos::lanczos_sum_expG_scaled(static_cast(n - x + 1)) + * Lanczos::lanczos_sum_expG_scaled(static_cast(r - x + 1)) + * Lanczos::lanczos_sum_expG_scaled(static_cast(N - n - r + x + 1))); + + BOOST_MATH_INSTRUMENT_VARIABLE(result); + return result; +} + +template +T hypergeometric_pdf_lanczos_imp(T /*dummy*/, unsigned x, unsigned r, unsigned n, unsigned N, const boost::math::lanczos::undefined_lanczos&, const Policy& pol) +{ + BOOST_MATH_STD_USING + return exp( + boost::math::lgamma(T(n + 1), pol) + + boost::math::lgamma(T(r + 1), pol) + + boost::math::lgamma(T(N - n + 1), pol) + + boost::math::lgamma(T(N - r + 1), pol) + - boost::math::lgamma(T(N + 1), pol) + - boost::math::lgamma(T(x + 1), pol) + - boost::math::lgamma(T(n - x + 1), pol) + - boost::math::lgamma(T(r - x + 1), pol) + - boost::math::lgamma(T(N - n - r + x + 1), pol)); +} + +template +inline T integer_power(const T& x, int ex) +{ + if(ex < 0) + return 1 / integer_power(x, -ex); + switch(ex) + { + case 0: + return 1; + case 1: + return x; + case 2: + return x * x; + case 3: + return x * x * x; + case 4: + return boost::math::pow<4>(x); + case 5: + return boost::math::pow<5>(x); + case 6: + return boost::math::pow<6>(x); + case 7: + return boost::math::pow<7>(x); + case 8: + return boost::math::pow<8>(x); + } + BOOST_MATH_STD_USING +#ifdef __SUNPRO_CC + return pow(x, T(ex)); +#else + return pow(x, ex); +#endif +} +template +struct hypergeometric_pdf_prime_loop_result_entry +{ + T value; + const hypergeometric_pdf_prime_loop_result_entry* next; +}; + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4510 4512 4610) +#endif + +struct hypergeometric_pdf_prime_loop_data +{ + const unsigned x; + const unsigned r; + const unsigned n; + const unsigned N; + unsigned prime_index; + unsigned current_prime; +}; + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +template +T hypergeometric_pdf_prime_loop_imp(hypergeometric_pdf_prime_loop_data& data, hypergeometric_pdf_prime_loop_result_entry& result) +{ + while(data.current_prime <= data.N) + { + unsigned base = data.current_prime; + int prime_powers = 0; + while(base <= data.N) + { + prime_powers += data.n / base; + prime_powers += data.r / base; + prime_powers += (data.N - data.n) / base; + prime_powers += (data.N - data.r) / base; + prime_powers -= data.N / base; + prime_powers -= data.x / base; + prime_powers -= (data.n - data.x) / base; + prime_powers -= (data.r - data.x) / base; + prime_powers -= (data.N - data.n - data.r + data.x) / base; + base *= data.current_prime; + } + if(prime_powers) + { + T p = integer_power(static_cast(data.current_prime), prime_powers); + if((p > 1) && (tools::max_value() / p < result.value)) + { + // + // The next calculation would overflow, use recursion + // to sidestep the issue: + // + hypergeometric_pdf_prime_loop_result_entry t = { p, &result }; + data.current_prime = prime(++data.prime_index); + return hypergeometric_pdf_prime_loop_imp(data, t); + } + if((p < 1) && (tools::min_value() / p > result.value)) + { + // + // The next calculation would underflow, use recursion + // to sidestep the issue: + // + hypergeometric_pdf_prime_loop_result_entry t = { p, &result }; + data.current_prime = prime(++data.prime_index); + return hypergeometric_pdf_prime_loop_imp(data, t); + } + result.value *= p; + } + data.current_prime = prime(++data.prime_index); + } + // + // When we get to here we have run out of prime factors, + // the overall result is the product of all the partial + // results we have accumulated on the stack so far, these + // are in a linked list starting with "data.head" and ending + // with "result". + // + // All that remains is to multiply them together, taking + // care not to overflow or underflow. + // + // Enumerate partial results >= 1 in variable i + // and partial results < 1 in variable j: + // + hypergeometric_pdf_prime_loop_result_entry const *i, *j; + i = &result; + while(i && i->value < 1) + i = i->next; + j = &result; + while(j && j->value >= 1) + j = j->next; + + T prod = 1; + + while(i || j) + { + while(i && ((prod <= 1) || (j == 0))) + { + prod *= i->value; + i = i->next; + while(i && i->value < 1) + i = i->next; + } + while(j && ((prod >= 1) || (i == 0))) + { + prod *= j->value; + j = j->next; + while(j && j->value >= 1) + j = j->next; + } + } + + return prod; +} + +template +inline T hypergeometric_pdf_prime_imp(unsigned x, unsigned r, unsigned n, unsigned N, const Policy&) +{ + hypergeometric_pdf_prime_loop_result_entry result = { 1, 0 }; + hypergeometric_pdf_prime_loop_data data = { x, r, n, N, 0, prime(0) }; + return hypergeometric_pdf_prime_loop_imp(data, result); +} + +template +T hypergeometric_pdf_factorial_imp(unsigned x, unsigned r, unsigned n, unsigned N, const Policy&) +{ + BOOST_MATH_STD_USING + BOOST_MATH_ASSERT(N <= boost::math::max_factorial::value); + T result = boost::math::unchecked_factorial(n); + T num[3] = { + boost::math::unchecked_factorial(r), + boost::math::unchecked_factorial(N - n), + boost::math::unchecked_factorial(N - r) + }; + T denom[5] = { + boost::math::unchecked_factorial(N), + boost::math::unchecked_factorial(x), + boost::math::unchecked_factorial(n - x), + boost::math::unchecked_factorial(r - x), + boost::math::unchecked_factorial(N - n - r + x) + }; + int i = 0; + int j = 0; + while((i < 3) || (j < 5)) + { + while((j < 5) && ((result >= 1) || (i >= 3))) + { + result /= denom[j]; + ++j; + } + while((i < 3) && ((result <= 1) || (j >= 5))) + { + result *= num[i]; + ++i; + } + } + return result; +} + + +template +inline typename tools::promote_args::type + hypergeometric_pdf(unsigned x, unsigned r, unsigned n, unsigned N, const Policy&) +{ + BOOST_FPU_EXCEPTION_GUARD + typedef typename tools::promote_args::type result_type; + typedef typename policies::evaluation::type value_type; + typedef typename lanczos::lanczos::type evaluation_type; + typedef typename policies::normalise< + Policy, + policies::promote_float, + policies::promote_double, + policies::discrete_quantile<>, + policies::assert_undefined<> >::type forwarding_policy; + + value_type result; + if(N <= boost::math::max_factorial::value) + { + // + // If N is small enough then we can evaluate the PDF via the factorials + // directly: table lookup of the factorials gives the best performance + // of the methods available: + // + result = detail::hypergeometric_pdf_factorial_imp(x, r, n, N, forwarding_policy()); + } + else if(N <= boost::math::prime(boost::math::max_prime - 1)) + { + // + // If N is no larger than the largest prime number in our lookup table + // (104729) then we can use prime factorisation to evaluate the PDF, + // this is slow but accurate: + // + result = detail::hypergeometric_pdf_prime_imp(x, r, n, N, forwarding_policy()); + } + else + { + // + // Catch all case - use the lanczos approximation - where available - + // to evaluate the ratio of factorials. This is reasonably fast + // (almost as quick as using logarithmic evaluation in terms of lgamma) + // but only a few digits better in accuracy than using lgamma: + // + result = detail::hypergeometric_pdf_lanczos_imp(value_type(), x, r, n, N, evaluation_type(), forwarding_policy()); + } + + if(result > 1) + { + result = 1; + } + if(result < 0) + { + result = 0; + } + + return policies::checked_narrowing_cast(result, "boost::math::hypergeometric_pdf<%1%>(%1%,%1%,%1%,%1%)"); +} + +}}} // namespaces + +#endif + diff --git a/libcxx/src/third-party/boost/math/distributions/detail/hypergeometric_quantile.hpp b/libcxx/src/third-party/boost/math/distributions/detail/hypergeometric_quantile.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/distributions/detail/hypergeometric_quantile.hpp @@ -0,0 +1,245 @@ +// Copyright 2008 John Maddock +// +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_DISTRIBUTIONS_DETAIL_HG_QUANTILE_HPP +#define BOOST_MATH_DISTRIBUTIONS_DETAIL_HG_QUANTILE_HPP + +#include +#include + +namespace boost{ namespace math{ namespace detail{ + +template +inline unsigned round_x_from_p(unsigned x, T p, T cum, T fudge_factor, unsigned lbound, unsigned /*ubound*/, const policies::discrete_quantile&) +{ + if((p < cum * fudge_factor) && (x != lbound)) + { + BOOST_MATH_INSTRUMENT_VARIABLE(x-1); + return --x; + } + return x; +} + +template +inline unsigned round_x_from_p(unsigned x, T p, T cum, T fudge_factor, unsigned /*lbound*/, unsigned ubound, const policies::discrete_quantile&) +{ + if((cum < p * fudge_factor) && (x != ubound)) + { + BOOST_MATH_INSTRUMENT_VARIABLE(x+1); + return ++x; + } + return x; +} + +template +inline unsigned round_x_from_p(unsigned x, T p, T cum, T fudge_factor, unsigned lbound, unsigned ubound, const policies::discrete_quantile&) +{ + if(p >= 0.5) + return round_x_from_p(x, p, cum, fudge_factor, lbound, ubound, policies::discrete_quantile()); + return round_x_from_p(x, p, cum, fudge_factor, lbound, ubound, policies::discrete_quantile()); +} + +template +inline unsigned round_x_from_p(unsigned x, T p, T cum, T fudge_factor, unsigned lbound, unsigned ubound, const policies::discrete_quantile&) +{ + if(p >= 0.5) + return round_x_from_p(x, p, cum, fudge_factor, lbound, ubound, policies::discrete_quantile()); + return round_x_from_p(x, p, cum, fudge_factor, lbound, ubound, policies::discrete_quantile()); +} + +template +inline unsigned round_x_from_p(unsigned x, T /*p*/, T /*cum*/, T /*fudge_factor*/, unsigned /*lbound*/, unsigned /*ubound*/, const policies::discrete_quantile&) +{ + return x; +} + +template +inline unsigned round_x_from_q(unsigned x, T q, T cum, T fudge_factor, unsigned lbound, unsigned /*ubound*/, const policies::discrete_quantile&) +{ + if((q * fudge_factor > cum) && (x != lbound)) + { + BOOST_MATH_INSTRUMENT_VARIABLE(x-1); + return --x; + } + return x; +} + +template +inline unsigned round_x_from_q(unsigned x, T q, T cum, T fudge_factor, unsigned /*lbound*/, unsigned ubound, const policies::discrete_quantile&) +{ + if((q < cum * fudge_factor) && (x != ubound)) + { + BOOST_MATH_INSTRUMENT_VARIABLE(x+1); + return ++x; + } + return x; +} + +template +inline unsigned round_x_from_q(unsigned x, T q, T cum, T fudge_factor, unsigned lbound, unsigned ubound, const policies::discrete_quantile&) +{ + if(q < 0.5) + return round_x_from_q(x, q, cum, fudge_factor, lbound, ubound, policies::discrete_quantile()); + return round_x_from_q(x, q, cum, fudge_factor, lbound, ubound, policies::discrete_quantile()); +} + +template +inline unsigned round_x_from_q(unsigned x, T q, T cum, T fudge_factor, unsigned lbound, unsigned ubound, const policies::discrete_quantile&) +{ + if(q >= 0.5) + return round_x_from_q(x, q, cum, fudge_factor, lbound, ubound, policies::discrete_quantile()); + return round_x_from_q(x, q, cum, fudge_factor, lbound, ubound, policies::discrete_quantile()); +} + +template +inline unsigned round_x_from_q(unsigned x, T /*q*/, T /*cum*/, T /*fudge_factor*/, unsigned /*lbound*/, unsigned /*ubound*/, const policies::discrete_quantile&) +{ + return x; +} + +template +unsigned hypergeometric_quantile_imp(T p, T q, unsigned r, unsigned n, unsigned N, const Policy& pol) +{ +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable:4267) +#endif + typedef typename Policy::discrete_quantile_type discrete_quantile_type; + BOOST_MATH_STD_USING + BOOST_FPU_EXCEPTION_GUARD + T result; + T fudge_factor = 1 + tools::epsilon() * ((N <= boost::math::prime(boost::math::max_prime - 1)) ? 50 : 2 * N); + unsigned base = static_cast((std::max)(0, static_cast(n + r) - static_cast(N))); + unsigned lim = (std::min)(r, n); + + BOOST_MATH_INSTRUMENT_VARIABLE(p); + BOOST_MATH_INSTRUMENT_VARIABLE(q); + BOOST_MATH_INSTRUMENT_VARIABLE(r); + BOOST_MATH_INSTRUMENT_VARIABLE(n); + BOOST_MATH_INSTRUMENT_VARIABLE(N); + BOOST_MATH_INSTRUMENT_VARIABLE(fudge_factor); + BOOST_MATH_INSTRUMENT_VARIABLE(base); + BOOST_MATH_INSTRUMENT_VARIABLE(lim); + + if(p <= 0.5) + { + unsigned x = base; + result = hypergeometric_pdf(x, r, n, N, pol); + T diff = result; + if (diff == 0) + { + ++x; + // We want to skip through x values as fast as we can until we start getting non-zero values, + // otherwise we're just making lots of expensive PDF calls: + T log_pdf = boost::math::lgamma(static_cast(n + 1), pol) + + boost::math::lgamma(static_cast(r + 1), pol) + + boost::math::lgamma(static_cast(N - n + 1), pol) + + boost::math::lgamma(static_cast(N - r + 1), pol) + - boost::math::lgamma(static_cast(N + 1), pol) + - boost::math::lgamma(static_cast(x + 1), pol) + - boost::math::lgamma(static_cast(n - x + 1), pol) + - boost::math::lgamma(static_cast(r - x + 1), pol) + - boost::math::lgamma(static_cast(N - n - r + x + 1), pol); + while (log_pdf < tools::log_min_value()) + { + log_pdf += -log(static_cast(x + 1)) + log(static_cast(n - x)) + log(static_cast(r - x)) - log(static_cast(N - n - r + x + 1)); + ++x; + } + // By the time we get here, log_pdf may be fairly inaccurate due to + // roundoff errors, get a fresh PDF calculation before proceeding: + diff = hypergeometric_pdf(x, r, n, N, pol); + } + while(result < p) + { + diff = (diff > tools::min_value() * 8) + ? T(n - x) * T(r - x) * diff / (T(x + 1) * T(N + x + 1 - n - r)) + : hypergeometric_pdf(x + 1, r, n, N, pol); + if(result + diff / 2 > p) + break; + ++x; + result += diff; +#ifdef BOOST_MATH_INSTRUMENT + if(diff != 0) + { + BOOST_MATH_INSTRUMENT_VARIABLE(x); + BOOST_MATH_INSTRUMENT_VARIABLE(diff); + BOOST_MATH_INSTRUMENT_VARIABLE(result); + } +#endif + } + return round_x_from_p(x, p, result, fudge_factor, base, lim, discrete_quantile_type()); + } + else + { + unsigned x = lim; + result = 0; + T diff = hypergeometric_pdf(x, r, n, N, pol); + if (diff == 0) + { + // We want to skip through x values as fast as we can until we start getting non-zero values, + // otherwise we're just making lots of expensive PDF calls: + --x; + T log_pdf = boost::math::lgamma(static_cast(n + 1), pol) + + boost::math::lgamma(static_cast(r + 1), pol) + + boost::math::lgamma(static_cast(N - n + 1), pol) + + boost::math::lgamma(static_cast(N - r + 1), pol) + - boost::math::lgamma(static_cast(N + 1), pol) + - boost::math::lgamma(static_cast(x + 1), pol) + - boost::math::lgamma(static_cast(n - x + 1), pol) + - boost::math::lgamma(static_cast(r - x + 1), pol) + - boost::math::lgamma(static_cast(N - n - r + x + 1), pol); + while (log_pdf < tools::log_min_value()) + { + log_pdf += log(static_cast(x)) - log(static_cast(n - x + 1)) - log(static_cast(r - x + 1)) + log(static_cast(N - n - r + x)); + --x; + } + // By the time we get here, log_pdf may be fairly inaccurate due to + // roundoff errors, get a fresh PDF calculation before proceeding: + diff = hypergeometric_pdf(x, r, n, N, pol); + } + while(result + diff / 2 < q) + { + result += diff; + diff = (diff > tools::min_value() * 8) + ? x * T(N + x - n - r) * diff / (T(1 + n - x) * T(1 + r - x)) + : hypergeometric_pdf(x - 1, r, n, N, pol); + --x; +#ifdef BOOST_MATH_INSTRUMENT + if(diff != 0) + { + BOOST_MATH_INSTRUMENT_VARIABLE(x); + BOOST_MATH_INSTRUMENT_VARIABLE(diff); + BOOST_MATH_INSTRUMENT_VARIABLE(result); + } +#endif + } + return round_x_from_q(x, q, result, fudge_factor, base, lim, discrete_quantile_type()); + } +#ifdef _MSC_VER +# pragma warning(pop) +#endif +} + +template +inline unsigned hypergeometric_quantile(T p, T q, unsigned r, unsigned n, unsigned N, const Policy&) +{ + BOOST_FPU_EXCEPTION_GUARD + typedef typename tools::promote_args::type result_type; + typedef typename policies::evaluation::type value_type; + typedef typename policies::normalise< + Policy, + policies::promote_float, + policies::promote_double, + policies::assert_undefined<> >::type forwarding_policy; + + return detail::hypergeometric_quantile_imp(p, q, r, n, N, forwarding_policy()); +} + +}}} // namespaces + +#endif + diff --git a/libcxx/src/third-party/boost/math/distributions/detail/inv_discrete_quantile.hpp b/libcxx/src/third-party/boost/math/distributions/detail/inv_discrete_quantile.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/distributions/detail/inv_discrete_quantile.hpp @@ -0,0 +1,571 @@ +// Copyright John Maddock 2007. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_DISTRIBUTIONS_DETAIL_INV_DISCRETE_QUANTILE +#define BOOST_MATH_DISTRIBUTIONS_DETAIL_INV_DISCRETE_QUANTILE + +#include + +namespace boost{ namespace math{ namespace detail{ + +// +// Functor for root finding algorithm: +// +template +struct distribution_quantile_finder +{ + typedef typename Dist::value_type value_type; + typedef typename Dist::policy_type policy_type; + + distribution_quantile_finder(const Dist d, value_type p, bool c) + : dist(d), target(p), comp(c) {} + + value_type operator()(value_type const& x) + { + return comp ? value_type(target - cdf(complement(dist, x))) : value_type(cdf(dist, x) - target); + } + +private: + Dist dist; + value_type target; + bool comp; +}; +// +// The purpose of adjust_bounds, is to toggle the last bit of the +// range so that both ends round to the same integer, if possible. +// If they do both round the same then we terminate the search +// for the root *very* quickly when finding an integer result. +// At the point that this function is called we know that "a" is +// below the root and "b" above it, so this change can not result +// in the root no longer being bracketed. +// +template +void adjust_bounds(Real& /* a */, Real& /* b */, Tol const& /* tol */){} + +template +void adjust_bounds(Real& /* a */, Real& b, tools::equal_floor const& /* tol */) +{ + BOOST_MATH_STD_USING + b -= tools::epsilon() * b; +} + +template +void adjust_bounds(Real& a, Real& /* b */, tools::equal_ceil const& /* tol */) +{ + BOOST_MATH_STD_USING + a += tools::epsilon() * a; +} + +template +void adjust_bounds(Real& a, Real& b, tools::equal_nearest_integer const& /* tol */) +{ + BOOST_MATH_STD_USING + a += tools::epsilon() * a; + b -= tools::epsilon() * b; +} +// +// This is where all the work is done: +// +template +typename Dist::value_type + do_inverse_discrete_quantile( + const Dist& dist, + const typename Dist::value_type& p, + bool comp, + typename Dist::value_type guess, + const typename Dist::value_type& multiplier, + typename Dist::value_type adder, + const Tolerance& tol, + std::uintmax_t& max_iter) +{ + typedef typename Dist::value_type value_type; + typedef typename Dist::policy_type policy_type; + + static const char* function = "boost::math::do_inverse_discrete_quantile<%1%>"; + + BOOST_MATH_STD_USING + + distribution_quantile_finder f(dist, p, comp); + // + // Max bounds of the distribution: + // + value_type min_bound, max_bound; + boost::math::tie(min_bound, max_bound) = support(dist); + + if(guess > max_bound) + guess = max_bound; + if(guess < min_bound) + guess = min_bound; + + value_type fa = f(guess); + std::uintmax_t count = max_iter - 1; + value_type fb(fa), a(guess), b =0; // Compiler warning C4701: potentially uninitialized local variable 'b' used + + if(fa == 0) + return guess; + + // + // For small expected results, just use a linear search: + // + if(guess < 10) + { + b = a; + while((a < 10) && (fa * fb >= 0)) + { + if(fb <= 0) + { + a = b; + b = a + 1; + if(b > max_bound) + b = max_bound; + fb = f(b); + --count; + if(fb == 0) + return b; + if(a == b) + return b; // can't go any higher! + } + else + { + b = a; + a = (std::max)(value_type(b - 1), value_type(0)); + if(a < min_bound) + a = min_bound; + fa = f(a); + --count; + if(fa == 0) + return a; + if(a == b) + return a; // We can't go any lower than this! + } + } + } + // + // Try and bracket using a couple of additions first, + // we're assuming that "guess" is likely to be accurate + // to the nearest int or so: + // + else if(adder != 0) + { + // + // If we're looking for a large result, then bump "adder" up + // by a bit to increase our chances of bracketing the root: + // + //adder = (std::max)(adder, 0.001f * guess); + if(fa < 0) + { + b = a + adder; + if(b > max_bound) + b = max_bound; + } + else + { + b = (std::max)(value_type(a - adder), value_type(0)); + if(b < min_bound) + b = min_bound; + } + fb = f(b); + --count; + if(fb == 0) + return b; + if(count && (fa * fb >= 0)) + { + // + // We didn't bracket the root, try + // once more: + // + a = b; + fa = fb; + if(fa < 0) + { + b = a + adder; + if(b > max_bound) + b = max_bound; + } + else + { + b = (std::max)(value_type(a - adder), value_type(0)); + if(b < min_bound) + b = min_bound; + } + fb = f(b); + --count; + } + if(a > b) + { + using std::swap; + swap(a, b); + swap(fa, fb); + } + } + // + // If the root hasn't been bracketed yet, try again + // using the multiplier this time: + // + if((boost::math::sign)(fb) == (boost::math::sign)(fa)) + { + if(fa < 0) + { + // + // Zero is to the right of x2, so walk upwards + // until we find it: + // + while(((boost::math::sign)(fb) == (boost::math::sign)(fa)) && (a != b)) + { + if(count == 0) + return policies::raise_evaluation_error(function, "Unable to bracket root, last nearest value was %1%", b, policy_type()); + a = b; + fa = fb; + b *= multiplier; + if(b > max_bound) + b = max_bound; + fb = f(b); + --count; + BOOST_MATH_INSTRUMENT_CODE("a = " << a << " b = " << b << " fa = " << fa << " fb = " << fb << " count = " << count); + } + } + else + { + // + // Zero is to the left of a, so walk downwards + // until we find it: + // + while(((boost::math::sign)(fb) == (boost::math::sign)(fa)) && (a != b)) + { + if(fabs(a) < tools::min_value()) + { + // Escape route just in case the answer is zero! + max_iter -= count; + max_iter += 1; + return 0; + } + if(count == 0) + return policies::raise_evaluation_error(function, "Unable to bracket root, last nearest value was %1%", a, policy_type()); + b = a; + fb = fa; + a /= multiplier; + if(a < min_bound) + a = min_bound; + fa = f(a); + --count; + BOOST_MATH_INSTRUMENT_CODE("a = " << a << " b = " << b << " fa = " << fa << " fb = " << fb << " count = " << count); + } + } + } + max_iter -= count; + if(fa == 0) + return a; + if(fb == 0) + return b; + if(a == b) + return b; // Ran out of bounds trying to bracket - there is no answer! + // + // Adjust bounds so that if we're looking for an integer + // result, then both ends round the same way: + // + adjust_bounds(a, b, tol); + // + // We don't want zero or denorm lower bounds: + // + if(a < tools::min_value()) + a = tools::min_value(); + // + // Go ahead and find the root: + // + std::pair r = toms748_solve(f, a, b, fa, fb, tol, count, policy_type()); + max_iter += count; + BOOST_MATH_INSTRUMENT_CODE("max_iter = " << max_iter << " count = " << count); + return (r.first + r.second) / 2; +} +// +// Some special routine for rounding up and down: +// We want to check and see if we are very close to an integer, and if so test to see if +// that integer is an exact root of the cdf. We do this because our root finder only +// guarantees to find *a root*, and there can sometimes be many consecutive floating +// point values which are all roots. This is especially true if the target probability +// is very close 1. +// +template +inline typename Dist::value_type round_to_floor(const Dist& d, typename Dist::value_type result, typename Dist::value_type p, bool c) +{ + BOOST_MATH_STD_USING + typename Dist::value_type cc = ceil(result); + typename Dist::value_type pp = cc <= support(d).second ? c ? cdf(complement(d, cc)) : cdf(d, cc) : 1; + if(pp == p) + result = cc; + else + result = floor(result); + // + // Now find the smallest integer <= result for which we get an exact root: + // + while(result != 0) + { + cc = result - 1; + if(cc < support(d).first) + break; + pp = c ? cdf(complement(d, cc)) : cdf(d, cc); + if(pp == p) + result = cc; + else if(c ? pp > p : pp < p) + break; + result -= 1; + } + + return result; +} + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4127) +#endif + +template +inline typename Dist::value_type round_to_ceil(const Dist& d, typename Dist::value_type result, typename Dist::value_type p, bool c) +{ + BOOST_MATH_STD_USING + typename Dist::value_type cc = floor(result); + typename Dist::value_type pp = cc >= support(d).first ? c ? cdf(complement(d, cc)) : cdf(d, cc) : 0; + if(pp == p) + result = cc; + else + result = ceil(result); + // + // Now find the largest integer >= result for which we get an exact root: + // + while(true) + { + cc = result + 1; + if(cc > support(d).second) + break; + pp = c ? cdf(complement(d, cc)) : cdf(d, cc); + if(pp == p) + result = cc; + else if(c ? pp < p : pp > p) + break; + result += 1; + } + + return result; +} + +#ifdef _MSC_VER +#pragma warning(pop) +#endif +// +// Now finally are the public API functions. +// There is one overload for each policy, +// each one is responsible for selecting the correct +// termination condition, and rounding the result +// to an int where required. +// +template +inline typename Dist::value_type + inverse_discrete_quantile( + const Dist& dist, + typename Dist::value_type p, + bool c, + const typename Dist::value_type& guess, + const typename Dist::value_type& multiplier, + const typename Dist::value_type& adder, + const policies::discrete_quantile&, + std::uintmax_t& max_iter) +{ + if(p > 0.5) + { + p = 1 - p; + c = !c; + } + typename Dist::value_type pp = c ? 1 - p : p; + if(pp <= pdf(dist, 0)) + return 0; + return do_inverse_discrete_quantile( + dist, + p, + c, + guess, + multiplier, + adder, + tools::eps_tolerance(policies::digits()), + max_iter); +} + +template +inline typename Dist::value_type + inverse_discrete_quantile( + const Dist& dist, + const typename Dist::value_type& p, + bool c, + const typename Dist::value_type& guess, + const typename Dist::value_type& multiplier, + const typename Dist::value_type& adder, + const policies::discrete_quantile&, + std::uintmax_t& max_iter) +{ + typedef typename Dist::value_type value_type; + BOOST_MATH_STD_USING + typename Dist::value_type pp = c ? 1 - p : p; + if(pp <= pdf(dist, 0)) + return 0; + // + // What happens next depends on whether we're looking for an + // upper or lower quantile: + // + if(pp < 0.5f) + return round_to_floor(dist, do_inverse_discrete_quantile( + dist, + p, + c, + (guess < 1 ? value_type(1) : (value_type)floor(guess)), + multiplier, + adder, + tools::equal_floor(), + max_iter), p, c); + // else: + return round_to_ceil(dist, do_inverse_discrete_quantile( + dist, + p, + c, + (value_type)ceil(guess), + multiplier, + adder, + tools::equal_ceil(), + max_iter), p, c); +} + +template +inline typename Dist::value_type + inverse_discrete_quantile( + const Dist& dist, + const typename Dist::value_type& p, + bool c, + const typename Dist::value_type& guess, + const typename Dist::value_type& multiplier, + const typename Dist::value_type& adder, + const policies::discrete_quantile&, + std::uintmax_t& max_iter) +{ + typedef typename Dist::value_type value_type; + BOOST_MATH_STD_USING + typename Dist::value_type pp = c ? 1 - p : p; + if(pp <= pdf(dist, 0)) + return 0; + // + // What happens next depends on whether we're looking for an + // upper or lower quantile: + // + if(pp < 0.5f) + return round_to_ceil(dist, do_inverse_discrete_quantile( + dist, + p, + c, + ceil(guess), + multiplier, + adder, + tools::equal_ceil(), + max_iter), p, c); + // else: + return round_to_floor(dist, do_inverse_discrete_quantile( + dist, + p, + c, + (guess < 1 ? value_type(1) : floor(guess)), + multiplier, + adder, + tools::equal_floor(), + max_iter), p, c); +} + +template +inline typename Dist::value_type + inverse_discrete_quantile( + const Dist& dist, + const typename Dist::value_type& p, + bool c, + const typename Dist::value_type& guess, + const typename Dist::value_type& multiplier, + const typename Dist::value_type& adder, + const policies::discrete_quantile&, + std::uintmax_t& max_iter) +{ + typedef typename Dist::value_type value_type; + BOOST_MATH_STD_USING + typename Dist::value_type pp = c ? 1 - p : p; + if(pp <= pdf(dist, 0)) + return 0; + return round_to_floor(dist, do_inverse_discrete_quantile( + dist, + p, + c, + (guess < 1 ? value_type(1) : floor(guess)), + multiplier, + adder, + tools::equal_floor(), + max_iter), p, c); +} + +template +inline typename Dist::value_type + inverse_discrete_quantile( + const Dist& dist, + const typename Dist::value_type& p, + bool c, + const typename Dist::value_type& guess, + const typename Dist::value_type& multiplier, + const typename Dist::value_type& adder, + const policies::discrete_quantile&, + std::uintmax_t& max_iter) +{ + BOOST_MATH_STD_USING + typename Dist::value_type pp = c ? 1 - p : p; + if(pp <= pdf(dist, 0)) + return 0; + return round_to_ceil(dist, do_inverse_discrete_quantile( + dist, + p, + c, + ceil(guess), + multiplier, + adder, + tools::equal_ceil(), + max_iter), p, c); +} + +template +inline typename Dist::value_type + inverse_discrete_quantile( + const Dist& dist, + const typename Dist::value_type& p, + bool c, + const typename Dist::value_type& guess, + const typename Dist::value_type& multiplier, + const typename Dist::value_type& adder, + const policies::discrete_quantile&, + std::uintmax_t& max_iter) +{ + typedef typename Dist::value_type value_type; + BOOST_MATH_STD_USING + typename Dist::value_type pp = c ? 1 - p : p; + if(pp <= pdf(dist, 0)) + return 0; + // + // Note that we adjust the guess to the nearest half-integer: + // this increase the chances that we will bracket the root + // with two results that both round to the same integer quickly. + // + return round_to_floor(dist, do_inverse_discrete_quantile( + dist, + p, + c, + (guess < 0.5f ? value_type(1.5f) : floor(guess + 0.5f) + 0.5f), + multiplier, + adder, + tools::equal_nearest_integer(), + max_iter) + 0.5f, p, c); +} + +}}} // namespaces + +#endif // BOOST_MATH_DISTRIBUTIONS_DETAIL_INV_DISCRETE_QUANTILE + diff --git a/libcxx/src/third-party/boost/math/distributions/empirical_cumulative_distribution_function.hpp b/libcxx/src/third-party/boost/math/distributions/empirical_cumulative_distribution_function.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/distributions/empirical_cumulative_distribution_function.hpp @@ -0,0 +1,65 @@ +// Copyright Nick Thompson 2019. +// 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_DISTRIBUTIONS_EMPIRICAL_CUMULATIVE_DISTRIBUTION_FUNCTION_HPP +#define BOOST_MATH_DISTRIBUTIONS_EMPIRICAL_CUMULATIVE_DISTRIBUTION_FUNCTION_HPP +#include +#include +#include +#include +#include + +namespace boost { namespace math{ + +template +class empirical_cumulative_distribution_function { + using Real = typename RandomAccessContainer::value_type; +public: + empirical_cumulative_distribution_function(RandomAccessContainer && v, bool sorted = false) + { + if (v.size() == 0) { + throw std::domain_error("At least one sample is required to compute an empirical CDF."); + } + m_v = std::move(v); + if (!sorted) { + std::sort(m_v.begin(), m_v.end()); + } + } + + auto operator()(Real x) const { + if constexpr (std::is_integral_v) + { + if (x < m_v[0]) { + return static_cast(0); + } + if (x >= m_v[m_v.size()-1]) { + return static_cast(1); + } + auto it = std::upper_bound(m_v.begin(), m_v.end(), x); + return static_cast(std::distance(m_v.begin(), it))/static_cast(m_v.size()); + } + else + { + if (x < m_v[0]) { + return Real(0); + } + if (x >= m_v[m_v.size()-1]) { + return Real(1); + } + auto it = std::upper_bound(m_v.begin(), m_v.end(), x); + return static_cast(std::distance(m_v.begin(), it))/static_cast(m_v.size()); + } + } + + RandomAccessContainer&& return_data() { + return std::move(m_v); + } + +private: + RandomAccessContainer m_v; +}; + +}} +#endif diff --git a/libcxx/src/third-party/boost/math/distributions/exponential.hpp b/libcxx/src/third-party/boost/math/distributions/exponential.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/distributions/exponential.hpp @@ -0,0 +1,305 @@ +// Copyright John Maddock 2006. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_STATS_EXPONENTIAL_HPP +#define BOOST_STATS_EXPONENTIAL_HPP + +#include +#include +#include +#include +#include +#include + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable: 4127) // conditional expression is constant +# pragma warning(disable: 4702) // unreachable code (return after domain_error throw). +#endif + +#include +#include + +namespace boost{ namespace math{ + +namespace detail{ +// +// Error check: +// +template +inline bool verify_lambda(const char* function, RealType l, RealType* presult, const Policy& pol) +{ + if((l <= 0) || !(boost::math::isfinite)(l)) + { + *presult = policies::raise_domain_error( + function, + "The scale parameter \"lambda\" must be > 0, but was: %1%.", l, pol); + return false; + } + return true; +} + +template +inline bool verify_exp_x(const char* function, RealType x, RealType* presult, const Policy& pol) +{ + if((x < 0) || (boost::math::isnan)(x)) + { + *presult = policies::raise_domain_error( + function, + "The random variable must be >= 0, but was: %1%.", x, pol); + return false; + } + return true; +} + +} // namespace detail + +template > +class exponential_distribution +{ +public: + using value_type = RealType; + using policy_type = Policy; + + explicit exponential_distribution(RealType l_lambda = 1) + : m_lambda(l_lambda) + { + RealType err; + detail::verify_lambda("boost::math::exponential_distribution<%1%>::exponential_distribution", l_lambda, &err, Policy()); + } // exponential_distribution + + RealType lambda()const { return m_lambda; } + +private: + RealType m_lambda; +}; + +using exponential = exponential_distribution; + +#ifdef __cpp_deduction_guides +template +exponential_distribution(RealType)->exponential_distribution::type>; +#endif + +template +inline std::pair range(const exponential_distribution& /*dist*/) +{ // Range of permissible values for random variable x. + if (std::numeric_limits::has_infinity) + { + return std::pair(static_cast(0), std::numeric_limits::infinity()); // 0 to + infinity. + } + else + { + using boost::math::tools::max_value; + return std::pair(static_cast(0), max_value()); // 0 to + max + } +} + +template +inline std::pair support(const exponential_distribution& /*dist*/) +{ // Range of supported values for random variable x. + // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. + using boost::math::tools::max_value; + using boost::math::tools::min_value; + return std::pair(min_value(), max_value()); + // min_value() to avoid a discontinuity at x = 0. +} + +template +inline RealType pdf(const exponential_distribution& dist, const RealType& x) +{ + BOOST_MATH_STD_USING // for ADL of std functions + + static const char* function = "boost::math::pdf(const exponential_distribution<%1%>&, %1%)"; + + RealType lambda = dist.lambda(); + RealType result = 0; + if(0 == detail::verify_lambda(function, lambda, &result, Policy())) + return result; + if(0 == detail::verify_exp_x(function, x, &result, Policy())) + return result; + // Workaround for VC11/12 bug: + if ((boost::math::isinf)(x)) + return 0; + result = lambda * exp(-lambda * x); + return result; +} // pdf + +template +inline RealType logpdf(const exponential_distribution& dist, const RealType& x) +{ + BOOST_MATH_STD_USING // for ADL of std functions + + static const char* function = "boost::math::logpdf(const exponential_distribution<%1%>&, %1%)"; + + RealType lambda = dist.lambda(); + RealType result = -std::numeric_limits::infinity(); + if(0 == detail::verify_lambda(function, lambda, &result, Policy())) + return result; + if(0 == detail::verify_exp_x(function, x, &result, Policy())) + return result; + + result = log(lambda) - lambda * x; + return result; +} // logpdf + +template +inline RealType cdf(const exponential_distribution& dist, const RealType& x) +{ + BOOST_MATH_STD_USING // for ADL of std functions + + static const char* function = "boost::math::cdf(const exponential_distribution<%1%>&, %1%)"; + + RealType result = 0; + RealType lambda = dist.lambda(); + if(0 == detail::verify_lambda(function, lambda, &result, Policy())) + return result; + if(0 == detail::verify_exp_x(function, x, &result, Policy())) + return result; + result = -boost::math::expm1(-x * lambda, Policy()); + + return result; +} // cdf + +template +inline RealType quantile(const exponential_distribution& dist, const RealType& p) +{ + BOOST_MATH_STD_USING // for ADL of std functions + + static const char* function = "boost::math::quantile(const exponential_distribution<%1%>&, %1%)"; + + RealType result = 0; + RealType lambda = dist.lambda(); + if(0 == detail::verify_lambda(function, lambda, &result, Policy())) + return result; + if(0 == detail::check_probability(function, p, &result, Policy())) + return result; + + if(p == 0) + return 0; + if(p == 1) + return policies::raise_overflow_error(function, 0, Policy()); + + result = -boost::math::log1p(-p, Policy()) / lambda; + return result; +} // quantile + +template +inline RealType cdf(const complemented2_type, RealType>& c) +{ + BOOST_MATH_STD_USING // for ADL of std functions + + static const char* function = "boost::math::cdf(const exponential_distribution<%1%>&, %1%)"; + + RealType result = 0; + RealType lambda = c.dist.lambda(); + if(0 == detail::verify_lambda(function, lambda, &result, Policy())) + return result; + if(0 == detail::verify_exp_x(function, c.param, &result, Policy())) + return result; + // Workaround for VC11/12 bug: + if (c.param >= tools::max_value()) + return 0; + result = exp(-c.param * lambda); + + return result; +} + +template +inline RealType quantile(const complemented2_type, RealType>& c) +{ + BOOST_MATH_STD_USING // for ADL of std functions + + static const char* function = "boost::math::quantile(const exponential_distribution<%1%>&, %1%)"; + + RealType result = 0; + RealType lambda = c.dist.lambda(); + if(0 == detail::verify_lambda(function, lambda, &result, Policy())) + return result; + + RealType q = c.param; + if(0 == detail::check_probability(function, q, &result, Policy())) + return result; + + if(q == 1) + return 0; + if(q == 0) + return policies::raise_overflow_error(function, 0, Policy()); + + result = -log(q) / lambda; + return result; +} + +template +inline RealType mean(const exponential_distribution& dist) +{ + RealType result = 0; + RealType lambda = dist.lambda(); + if(0 == detail::verify_lambda("boost::math::mean(const exponential_distribution<%1%>&)", lambda, &result, Policy())) + return result; + return 1 / lambda; +} + +template +inline RealType standard_deviation(const exponential_distribution& dist) +{ + RealType result = 0; + RealType lambda = dist.lambda(); + if(0 == detail::verify_lambda("boost::math::standard_deviation(const exponential_distribution<%1%>&)", lambda, &result, Policy())) + return result; + return 1 / lambda; +} + +template +inline RealType mode(const exponential_distribution& /*dist*/) +{ + return 0; +} + +template +inline RealType median(const exponential_distribution& dist) +{ + using boost::math::constants::ln_two; + return ln_two() / dist.lambda(); // ln(2) / lambda +} + +template +inline RealType skewness(const exponential_distribution& /*dist*/) +{ + return 2; +} + +template +inline RealType kurtosis(const exponential_distribution& /*dist*/) +{ + return 9; +} + +template +inline RealType kurtosis_excess(const exponential_distribution& /*dist*/) +{ + return 6; +} + +template +inline RealType entropy(const exponential_distribution& dist) +{ + using std::log; + return 1 - log(dist.lambda()); +} + +} // namespace math +} // namespace boost + +#ifdef _MSC_VER +# pragma warning(pop) +#endif + +// This include must be at the end, *after* the accessors +// for this distribution have been defined, in order to +// keep compilers that support two-phase lookup happy. +#include + +#endif // BOOST_STATS_EXPONENTIAL_HPP diff --git a/libcxx/src/third-party/boost/math/distributions/extreme_value.hpp b/libcxx/src/third-party/boost/math/distributions/extreme_value.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/distributions/extreme_value.hpp @@ -0,0 +1,333 @@ +// Copyright John Maddock 2006. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_STATS_EXTREME_VALUE_HPP +#define BOOST_STATS_EXTREME_VALUE_HPP + +#include +#include +#include +#include +#include +#include + +// +// This is the maximum extreme value distribution, see +// http://www.itl.nist.gov/div898/handbook/eda/section3/eda366g.htm +// and http://mathworld.wolfram.com/ExtremeValueDistribution.html +// Also known as a Fisher-Tippett distribution, a log-Weibull +// distribution or a Gumbel distribution. + +#include +#include + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable: 4702) // unreachable code (return after domain_error throw). +#endif + +namespace boost{ namespace math{ + +namespace detail{ +// +// Error check: +// +template +inline bool verify_scale_b(const char* function, RealType b, RealType* presult, const Policy& pol) +{ + if((b <= 0) || !(boost::math::isfinite)(b)) + { + *presult = policies::raise_domain_error( + function, + "The scale parameter \"b\" must be finite and > 0, but was: %1%.", b, pol); + return false; + } + return true; +} + +} // namespace detail + +template > +class extreme_value_distribution +{ +public: + using value_type = RealType; + using policy_type = Policy; + + explicit extreme_value_distribution(RealType a = 0, RealType b = 1) + : m_a(a), m_b(b) + { + RealType err; + detail::verify_scale_b("boost::math::extreme_value_distribution<%1%>::extreme_value_distribution", b, &err, Policy()); + detail::check_finite("boost::math::extreme_value_distribution<%1%>::extreme_value_distribution", a, &err, Policy()); + } // extreme_value_distribution + + RealType location()const { return m_a; } + RealType scale()const { return m_b; } + +private: + RealType m_a; + RealType m_b; +}; + +using extreme_value = extreme_value_distribution; + +#ifdef __cpp_deduction_guides +template +extreme_value_distribution(RealType)->extreme_value_distribution::type>; +template +extreme_value_distribution(RealType,RealType)->extreme_value_distribution::type>; +#endif + +template +inline std::pair range(const extreme_value_distribution& /*dist*/) +{ // Range of permissible values for random variable x. + using boost::math::tools::max_value; + return std::pair( + std::numeric_limits::has_infinity ? -std::numeric_limits::infinity() : -max_value(), + std::numeric_limits::has_infinity ? std::numeric_limits::infinity() : max_value()); +} + +template +inline std::pair support(const extreme_value_distribution& /*dist*/) +{ // Range of supported values for random variable x. + // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. + using boost::math::tools::max_value; + return std::pair(-max_value(), max_value()); +} + +template +inline RealType pdf(const extreme_value_distribution& dist, const RealType& x) +{ + BOOST_MATH_STD_USING // for ADL of std functions + + static const char* function = "boost::math::pdf(const extreme_value_distribution<%1%>&, %1%)"; + + RealType a = dist.location(); + RealType b = dist.scale(); + RealType result = 0; + if(0 == detail::verify_scale_b(function, b, &result, Policy())) + return result; + if(0 == detail::check_finite(function, a, &result, Policy())) + return result; + if((boost::math::isinf)(x)) + return 0.0f; + if(0 == detail::check_x(function, x, &result, Policy())) + return result; + RealType e = (a - x) / b; + if(e < tools::log_max_value()) + result = exp(e) * exp(-exp(e)) / b; + // else.... result *must* be zero since exp(e) is infinite... + return result; +} // pdf + +template +inline RealType logpdf(const extreme_value_distribution& dist, const RealType& x) +{ + BOOST_MATH_STD_USING // for ADL of std functions + + static const char* function = "boost::math::logpdf(const extreme_value_distribution<%1%>&, %1%)"; + + RealType a = dist.location(); + RealType b = dist.scale(); + RealType result = -std::numeric_limits::infinity(); + if(0 == detail::verify_scale_b(function, b, &result, Policy())) + return result; + if(0 == detail::check_finite(function, a, &result, Policy())) + return result; + if((boost::math::isinf)(x)) + return 0.0f; + if(0 == detail::check_x(function, x, &result, Policy())) + return result; + RealType e = (a - x) / b; + if(e < tools::log_max_value()) + result = log(1/b) + e - exp(e); + // else.... result *must* be zero since exp(e) is infinite... + return result; +} // logpdf + +template +inline RealType cdf(const extreme_value_distribution& dist, const RealType& x) +{ + BOOST_MATH_STD_USING // for ADL of std functions + + static const char* function = "boost::math::cdf(const extreme_value_distribution<%1%>&, %1%)"; + + if((boost::math::isinf)(x)) + return x < 0 ? 0.0f : 1.0f; + RealType a = dist.location(); + RealType b = dist.scale(); + RealType result = 0; + if(0 == detail::verify_scale_b(function, b, &result, Policy())) + return result; + if(0 == detail::check_finite(function, a, &result, Policy())) + return result; + if(0 == detail::check_finite(function, a, &result, Policy())) + return result; + if(0 == detail::check_x("boost::math::cdf(const extreme_value_distribution<%1%>&, %1%)", x, &result, Policy())) + return result; + + result = exp(-exp((a-x)/b)); + + return result; +} // cdf + +template +RealType quantile(const extreme_value_distribution& dist, const RealType& p) +{ + BOOST_MATH_STD_USING // for ADL of std functions + + static const char* function = "boost::math::quantile(const extreme_value_distribution<%1%>&, %1%)"; + + RealType a = dist.location(); + RealType b = dist.scale(); + RealType result = 0; + if(0 == detail::verify_scale_b(function, b, &result, Policy())) + return result; + if(0 == detail::check_finite(function, a, &result, Policy())) + return result; + if(0 == detail::check_probability(function, p, &result, Policy())) + return result; + + if(p == 0) + return -policies::raise_overflow_error(function, 0, Policy()); + if(p == 1) + return policies::raise_overflow_error(function, 0, Policy()); + + result = a - log(-log(p)) * b; + + return result; +} // quantile + +template +inline RealType cdf(const complemented2_type, RealType>& c) +{ + BOOST_MATH_STD_USING // for ADL of std functions + + static const char* function = "boost::math::cdf(const extreme_value_distribution<%1%>&, %1%)"; + + if((boost::math::isinf)(c.param)) + return c.param < 0 ? 1.0f : 0.0f; + RealType a = c.dist.location(); + RealType b = c.dist.scale(); + RealType result = 0; + if(0 == detail::verify_scale_b(function, b, &result, Policy())) + return result; + if(0 == detail::check_finite(function, a, &result, Policy())) + return result; + if(0 == detail::check_x(function, c.param, &result, Policy())) + return result; + + result = -boost::math::expm1(-exp((a-c.param)/b), Policy()); + + return result; +} + +template +RealType quantile(const complemented2_type, RealType>& c) +{ + BOOST_MATH_STD_USING // for ADL of std functions + + static const char* function = "boost::math::quantile(const extreme_value_distribution<%1%>&, %1%)"; + + RealType a = c.dist.location(); + RealType b = c.dist.scale(); + RealType q = c.param; + RealType result = 0; + if(0 == detail::verify_scale_b(function, b, &result, Policy())) + return result; + if(0 == detail::check_finite(function, a, &result, Policy())) + return result; + if(0 == detail::check_probability(function, q, &result, Policy())) + return result; + + if(q == 0) + return policies::raise_overflow_error(function, 0, Policy()); + if(q == 1) + return -policies::raise_overflow_error(function, 0, Policy()); + + result = a - log(-boost::math::log1p(-q, Policy())) * b; + + return result; +} + +template +inline RealType mean(const extreme_value_distribution& dist) +{ + RealType a = dist.location(); + RealType b = dist.scale(); + RealType result = 0; + if(0 == detail::verify_scale_b("boost::math::mean(const extreme_value_distribution<%1%>&)", b, &result, Policy())) + return result; + if (0 == detail::check_finite("boost::math::mean(const extreme_value_distribution<%1%>&)", a, &result, Policy())) + return result; + return a + constants::euler() * b; +} + +template +inline RealType standard_deviation(const extreme_value_distribution& dist) +{ + BOOST_MATH_STD_USING // for ADL of std functions. + + RealType b = dist.scale(); + RealType result = 0; + if(0 == detail::verify_scale_b("boost::math::standard_deviation(const extreme_value_distribution<%1%>&)", b, &result, Policy())) + return result; + if(0 == detail::check_finite("boost::math::standard_deviation(const extreme_value_distribution<%1%>&)", dist.location(), &result, Policy())) + return result; + return constants::pi() * b / sqrt(static_cast(6)); +} + +template +inline RealType mode(const extreme_value_distribution& dist) +{ + return dist.location(); +} + +template +inline RealType median(const extreme_value_distribution& dist) +{ + using constants::ln_ln_two; + return dist.location() - dist.scale() * ln_ln_two(); +} + +template +inline RealType skewness(const extreme_value_distribution& /*dist*/) +{ + // + // This is 12 * sqrt(6) * zeta(3) / pi^3: + // See http://mathworld.wolfram.com/ExtremeValueDistribution.html + // + return static_cast(1.1395470994046486574927930193898461120875997958366L); +} + +template +inline RealType kurtosis(const extreme_value_distribution& /*dist*/) +{ + // See http://mathworld.wolfram.com/ExtremeValueDistribution.html + return RealType(27) / 5; +} + +template +inline RealType kurtosis_excess(const extreme_value_distribution& /*dist*/) +{ + // See http://mathworld.wolfram.com/ExtremeValueDistribution.html + return RealType(12) / 5; +} + + +} // namespace math +} // namespace boost + +#ifdef _MSC_VER +# pragma warning(pop) +#endif + +// This include must be at the end, *after* the accessors +// for this distribution have been defined, in order to +// keep compilers that support two-phase lookup happy. +#include + +#endif // BOOST_STATS_EXTREME_VALUE_HPP diff --git a/libcxx/src/third-party/boost/math/distributions/find_location.hpp b/libcxx/src/third-party/boost/math/distributions/find_location.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/distributions/find_location.hpp @@ -0,0 +1,140 @@ +// Copyright John Maddock 2007. +// Copyright Paul A. Bristow 2007. + +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_STATS_FIND_LOCATION_HPP +#define BOOST_STATS_FIND_LOCATION_HPP + +#include // for all distribution signatures. +#include +#include +#include +#include +#include +// using boost::math::policies::policy; +// using boost::math::complement; // will be needed by users who want complement, +// but NOT placed here to avoid putting it in global scope. + +namespace boost +{ + namespace math + { + // Function to find location of random variable z + // to give probability p (given scale) + // Applies to normal, lognormal, extreme value, Cauchy, (and symmetrical triangular), + // enforced by static_assert below. + + template + inline + typename Dist::value_type find_location( // For example, normal mean. + typename Dist::value_type z, // location of random variable z to give probability, P(X > z) == p. + // For example, a nominal minimum acceptable z, so that p * 100 % are > z + typename Dist::value_type p, // probability value desired at x, say 0.95 for 95% > z. + typename Dist::value_type scale, // scale parameter, for example, normal standard deviation. + const Policy& pol + ) + { + static_assert(::boost::math::tools::is_distribution::value, "The provided distribution does not meet the conceptual requirements of a distribution."); + static_assert(::boost::math::tools::is_scaled_distribution::value, "The provided distribution does not meet the conceptual requirements of a scaled distribution."); + static const char* function = "boost::math::find_location&, %1%)"; + + if(!(boost::math::isfinite)(p) || (p < 0) || (p > 1)) + { + return policies::raise_domain_error( + function, "Probability parameter was %1%, but must be >= 0 and <= 1!", p, pol); + } + if(!(boost::math::isfinite)(z)) + { + return policies::raise_domain_error( + function, "z parameter was %1%, but must be finite!", z, pol); + } + if(!(boost::math::isfinite)(scale)) + { + return policies::raise_domain_error( + function, "scale parameter was %1%, but must be finite!", scale, pol); + } + + //cout << "z " << z << ", p " << p << ", quantile(Dist(), p) " + // << quantile(Dist(), p) << ", quan * scale " << quantile(Dist(), p) * scale << endl; + return z - (quantile(Dist(), p) * scale); + } // find_location + + template + inline // with default policy. + typename Dist::value_type find_location( // For example, normal mean. + typename Dist::value_type z, // location of random variable z to give probability, P(X > z) == p. + // For example, a nominal minimum acceptable z, so that p * 100 % are > z + typename Dist::value_type p, // probability value desired at x, say 0.95 for 95% > z. + typename Dist::value_type scale) // scale parameter, for example, normal standard deviation. + { // Forward to find_location with default policy. + return (find_location(z, p, scale, policies::policy<>())); + } // find_location + + // So the user can start from the complement q = (1 - p) of the probability p, + // for example, l = find_location(complement(z, q, sd)); + + template + inline typename Dist::value_type find_location( // Default policy. + complemented3_type const& c) + { + static const char* function = "boost::math::find_location&, %1%)"; + + typename Dist::value_type p = c.param1; + if(!(boost::math::isfinite)(p) || (p < 0) || (p > 1)) + { + return policies::raise_domain_error( + function, "Probability parameter was %1%, but must be >= 0 and <= 1!", p, policies::policy<>()); + } + typename Dist::value_type z = c.dist; + if(!(boost::math::isfinite)(z)) + { + return policies::raise_domain_error( + function, "z parameter was %1%, but must be finite!", z, policies::policy<>()); + } + typename Dist::value_type scale = c.param2; + if(!(boost::math::isfinite)(scale)) + { + return policies::raise_domain_error( + function, "scale parameter was %1%, but must be finite!", scale, policies::policy<>()); + } + // cout << "z " << c.dist << ", quantile (Dist(), " << c.param1 << ") * scale " << c.param2 << endl; + return z - quantile(Dist(), p) * scale; + } // find_location complement + + + template + inline typename Dist::value_type find_location( // Explicit policy. + complemented4_type const& c) + { + static const char* function = "boost::math::find_location&, %1%)"; + + typename Dist::value_type p = c.param1; + if(!(boost::math::isfinite)(p) || (p < 0) || (p > 1)) + { + return policies::raise_domain_error( + function, "Probability parameter was %1%, but must be >= 0 and <= 1!", p, c.param3); + } + typename Dist::value_type z = c.dist; + if(!(boost::math::isfinite)(z)) + { + return policies::raise_domain_error( + function, "z parameter was %1%, but must be finite!", z, c.param3); + } + typename Dist::value_type scale = c.param2; + if(!(boost::math::isfinite)(scale)) + { + return policies::raise_domain_error( + function, "scale parameter was %1%, but must be finite!", scale, c.param3); + } + // cout << "z " << c.dist << ", quantile (Dist(), " << c.param1 << ") * scale " << c.param2 << endl; + return z - quantile(Dist(), p) * scale; + } // find_location complement + + } // namespace boost +} // namespace math + +#endif // BOOST_STATS_FIND_LOCATION_HPP + diff --git a/libcxx/src/third-party/boost/math/distributions/find_scale.hpp b/libcxx/src/third-party/boost/math/distributions/find_scale.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/distributions/find_scale.hpp @@ -0,0 +1,205 @@ +// Copyright John Maddock 2007. +// Copyright Paul A. Bristow 2007. + +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_STATS_FIND_SCALE_HPP +#define BOOST_STATS_FIND_SCALE_HPP + +#include // for all distribution signatures. +#include +#include +// using boost::math::policies::policy; +#include +#include +#include +#include +// using boost::math::complement; // will be needed by users who want complement, +// but NOT placed here to avoid putting it in global scope. + +namespace boost +{ + namespace math + { + // Function to find location of random variable z + // to give probability p (given scale) + // Applies to normal, lognormal, extreme value, Cauchy, (and symmetrical triangular), + // distributions that have scale. + // BOOST_STATIC_ASSERTs, see below, are used to enforce this. + + template + inline + typename Dist::value_type find_scale( // For example, normal mean. + typename Dist::value_type z, // location of random variable z to give probability, P(X > z) == p. + // For example, a nominal minimum acceptable weight z, so that p * 100 % are > z + typename Dist::value_type p, // probability value desired at x, say 0.95 for 95% > z. + typename Dist::value_type location, // location parameter, for example, normal distribution mean. + const Policy& pol + ) + { + static_assert(::boost::math::tools::is_distribution::value, "The provided distribution does not meet the conceptual requirements of a distribution."); + static_assert(::boost::math::tools::is_scaled_distribution::value, "The provided distribution does not meet the conceptual requirements of a scaled distribution."); + static const char* function = "boost::math::find_scale(%1%, %1%, %1%, Policy)"; + + if(!(boost::math::isfinite)(p) || (p < 0) || (p > 1)) + { + return policies::raise_domain_error( + function, "Probability parameter was %1%, but must be >= 0 and <= 1!", p, pol); + } + if(!(boost::math::isfinite)(z)) + { + return policies::raise_domain_error( + function, "find_scale z parameter was %1%, but must be finite!", z, pol); + } + if(!(boost::math::isfinite)(location)) + { + return policies::raise_domain_error( + function, "find_scale location parameter was %1%, but must be finite!", location, pol); + } + + //cout << "z " << z << ", p " << p << ", quantile(Dist(), p) " + //<< quantile(Dist(), p) << ", z - mean " << z - location + //<<", sd " << (z - location) / quantile(Dist(), p) << endl; + + //quantile(N01, 0.001) -3.09023 + //quantile(N01, 0.01) -2.32635 + //quantile(N01, 0.05) -1.64485 + //quantile(N01, 0.333333) -0.430728 + //quantile(N01, 0.5) 0 + //quantile(N01, 0.666667) 0.430728 + //quantile(N01, 0.9) 1.28155 + //quantile(N01, 0.95) 1.64485 + //quantile(N01, 0.99) 2.32635 + //quantile(N01, 0.999) 3.09023 + + typename Dist::value_type result = + (z - location) // difference between desired x and current location. + / quantile(Dist(), p); // standard distribution. + + if (result <= 0) + { // If policy isn't to throw, return the scale <= 0. + policies::raise_evaluation_error(function, + "Computed scale (%1%) is <= 0!" " Was the complement intended?", + result, Policy()); + } + return result; + } // template find_scale + + template + inline // with default policy. + typename Dist::value_type find_scale( // For example, normal mean. + typename Dist::value_type z, // location of random variable z to give probability, P(X > z) == p. + // For example, a nominal minimum acceptable z, so that p * 100 % are > z + typename Dist::value_type p, // probability value desired at x, say 0.95 for 95% > z. + typename Dist::value_type location) // location parameter, for example, mean. + { // Forward to find_scale using the default policy. + return (find_scale(z, p, location, policies::policy<>())); + } // find_scale + + template + inline typename Dist::value_type find_scale( + complemented4_type const& c) + { + //cout << "cparam1 q " << c.param1 // q + // << ", c.dist z " << c.dist // z + // << ", c.param2 l " << c.param2 // l + // << ", quantile (Dist(), c.param1 = q) " + // << quantile(Dist(), c.param1) //q + // << endl; + + static_assert(::boost::math::tools::is_distribution::value, "The provided distribution does not meet the conceptual requirements of a distribution."); + static_assert(::boost::math::tools::is_scaled_distribution::value, "The provided distribution does not meet the conceptual requirements of a scaled distribution."); + static const char* function = "boost::math::find_scale(complement(%1%, %1%, %1%, Policy))"; + + // Checks on arguments, as not complemented version, + // Explicit policy. + typename Dist::value_type q = c.param1; + if(!(boost::math::isfinite)(q) || (q < 0) || (q > 1)) + { + return policies::raise_domain_error( + function, "Probability parameter was %1%, but must be >= 0 and <= 1!", q, c.param3); + } + typename Dist::value_type z = c.dist; + if(!(boost::math::isfinite)(z)) + { + return policies::raise_domain_error( + function, "find_scale z parameter was %1%, but must be finite!", z, c.param3); + } + typename Dist::value_type location = c.param2; + if(!(boost::math::isfinite)(location)) + { + return policies::raise_domain_error( + function, "find_scale location parameter was %1%, but must be finite!", location, c.param3); + } + + typename Dist::value_type result = + (c.dist - c.param2) // difference between desired x and current location. + / quantile(complement(Dist(), c.param1)); + // ( z - location) / (quantile(complement(Dist(), q)) + if (result <= 0) + { // If policy isn't to throw, return the scale <= 0. + policies::raise_evaluation_error(function, + "Computed scale (%1%) is <= 0!" " Was the complement intended?", + result, Policy()); + } + return result; + } // template typename Dist::value_type find_scale + + // So the user can start from the complement q = (1 - p) of the probability p, + // for example, s = find_scale(complement(z, q, l)); + + template + inline typename Dist::value_type find_scale( + complemented3_type const& c) + { + //cout << "cparam1 q " << c.param1 // q + // << ", c.dist z " << c.dist // z + // << ", c.param2 l " << c.param2 // l + // << ", quantile (Dist(), c.param1 = q) " + // << quantile(Dist(), c.param1) //q + // << endl; + + static_assert(::boost::math::tools::is_distribution::value, "The provided distribution does not meet the conceptual requirements of a distribution."); + static_assert(::boost::math::tools::is_scaled_distribution::value, "The provided distribution does not meet the conceptual requirements of a scaled distribution."); + static const char* function = "boost::math::find_scale(complement(%1%, %1%, %1%, Policy))"; + + // Checks on arguments, as not complemented version, + // default policy policies::policy<>(). + typename Dist::value_type q = c.param1; + if(!(boost::math::isfinite)(q) || (q < 0) || (q > 1)) + { + return policies::raise_domain_error( + function, "Probability parameter was %1%, but must be >= 0 and <= 1!", q, policies::policy<>()); + } + typename Dist::value_type z = c.dist; + if(!(boost::math::isfinite)(z)) + { + return policies::raise_domain_error( + function, "find_scale z parameter was %1%, but must be finite!", z, policies::policy<>()); + } + typename Dist::value_type location = c.param2; + if(!(boost::math::isfinite)(location)) + { + return policies::raise_domain_error( + function, "find_scale location parameter was %1%, but must be finite!", location, policies::policy<>()); + } + + typename Dist::value_type result = + (z - location) // difference between desired x and current location. + / quantile(complement(Dist(), q)); + // ( z - location) / (quantile(complement(Dist(), q)) + if (result <= 0) + { // If policy isn't to throw, return the scale <= 0. + policies::raise_evaluation_error(function, + "Computed scale (%1%) is <= 0!" " Was the complement intended?", + result, policies::policy<>()); // This is only the default policy - also Want a version with Policy here. + } + return result; + } // template typename Dist::value_type find_scale + + } // namespace boost +} // namespace math + +#endif // BOOST_STATS_FIND_SCALE_HPP diff --git a/libcxx/src/third-party/boost/math/distributions/fisher_f.hpp b/libcxx/src/third-party/boost/math/distributions/fisher_f.hpp new file mode 100644 --- /dev/null +++ b/libcxx/src/third-party/boost/math/distributions/fisher_f.hpp @@ -0,0 +1,392 @@ +// Copyright John Maddock 2006. + +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_DISTRIBUTIONS_FISHER_F_HPP +#define BOOST_MATH_DISTRIBUTIONS_FISHER_F_HPP + +#include +#include // for incomplete beta. +#include // complements +#include // error checks +#include + +#include + +namespace boost{ namespace math{ + +template > +class fisher_f_distribution +{ +public: + typedef RealType value_type; + typedef Policy policy_type; + + fisher_f_distribution(const RealType& i, const RealType& j) : m_df1(i), m_df2(j) + { + static const char* function = "fisher_f_distribution<%1%>::fisher_f_distribution"; + RealType result; + detail::check_df( + function, m_df1, &result, Policy()); + detail::check_df( + function, m_df2, &result, Policy()); + } // fisher_f_distribution + + RealType degrees_of_freedom1()const + { + return m_df1; + } + RealType degrees_of_freedom2()const + { + return m_df2; + } + +private: + // + // Data members: + // + RealType m_df1; // degrees of freedom are a real number. + RealType m_df2; // degrees of freedom are a real number. +}; + +typedef fisher_f_distribution fisher_f; + +#ifdef __cpp_deduction_guides +template +fisher_f_distribution(RealType,RealType)->fisher_f_distribution::type>; +#endif + +template +inline const std::pair range(const fisher_f_distribution& /*dist*/) +{ // Range of permissible values for random variable x. + using boost::math::tools::max_value; + return std::pair(static_cast(0), max_value()); +} + +template +inline const std::pair support(const fisher_f_distribution& /*dist*/) +{ // Range of supported values for random variable x. + // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. + using boost::math::tools::max_value; + return std::pair(static_cast(0), max_value()); +} + +template +RealType pdf(const fisher_f_distribution& dist, const RealType& x) +{ + BOOST_MATH_STD_USING // for ADL of std functions + RealType df1 = dist.degrees_of_freedom1(); + RealType df2 = dist.degrees_of_freedom2(); + // Error check: + RealType error_result = 0; + static const char* function = "boost::math::pdf(fisher_f_distribution<%1%> const&, %1%)"; + if(false == (detail::check_df( + function, df1, &error_result, Policy()) + && detail::check_df( + function, df2, &error_result, Policy()))) + return error_result; + + if((x < 0) || !(boost::math::isfinite)(x)) + { + return policies::raise_domain_error( + function, "Random variable parameter was %1%, but must be > 0 !", x, Policy()); + } + + if(x == 0) + { + // special cases: + if(df1 < 2) + return policies::raise_overflow_error( + function, 0, Policy()); + else if(df1 == 2) + return 1; + else + return 0; + } + + // + // You reach this formula by direct differentiation of the + // cdf expressed in terms of the incomplete beta. + // + // There are two versions so we don't pass a value of z + // that is very close to 1 to ibeta_derivative: for some values + // of df1 and df2, all the change takes place in this area. + // + RealType v1x = df1 * x; + RealType result; + if(v1x > df2) + { + result = (df2 * df1) / ((df2 + v1x) * (df2 + v1x)); + result *= ibeta_derivative(df2 / 2, df1 / 2, df2 / (df2 + v1x), Policy()); + } + else + { + result = df2 + df1 * x; + result = (result * df1 - x * df1 * df1) / (result * result); + result *= ibeta_derivative(df1 / 2, df2 / 2, v1x / (df2 + v1x), Policy()); + } + return result; +} // pdf + +template +inline RealType cdf(const fisher_f_distribution& dist, const RealType& x) +{ + static const char* function = "boost::math::cdf(fisher_f_distribution<%1%> const&, %1%)"; + RealType df1 = dist.degrees_of_freedom1(); + RealType df2 = dist.degrees_of_freedom2(); + // Error check: + RealType error_result = 0; + if(false == detail::check_df( + function, df1, &error_result, Policy()) + && detail::check_df( + function, df2, &error_result, Policy())) + return error_result; + + if((x < 0) || !(boost::math::isfinite)(x)) + { + return policies::raise_domain_error( + function, "Random Variable parameter was %1%, but must be > 0 !", x, Policy()); + } + + RealType v1x = df1 * x; + // + // There are two equivalent formulas used here, the aim is + // to prevent the final argument to the incomplete beta + // from being too close to 1: for some values of df1 and df2 + // the rate of change can be arbitrarily large in this area, + // whilst the value we're passing will have lost information + // content as a result of being 0.999999something. Better + // to switch things around so we're passing 1-z instead. + // + return v1x > df2 + ? boost::math::ibetac(df2 / 2, df1 / 2, df2 / (df2 + v1x), Policy()) + : boost::math::ibeta(df1 / 2, df2 / 2, v1x / (df2 + v1x), Policy()); +} // cdf + +template +inline RealType quantile(const fisher_f_distribution& dist, const RealType& p) +{ + static const char* function = "boost::math::quantile(fisher_f_distribution<%1%> const&, %1%)"; + RealType df1 = dist.degrees_of_freedom1(); + RealType df2 = dist.degrees_of_freedom2(); + // Error check: + RealType error_result = 0; + if(false == (detail::check_df( + function, df1, &error_result, Policy()) + && detail::check_df( + function, df2, &error_result, Policy()) + && detail::check_probability( + function, p, &error_result, Policy()))) + return error_result; + + // With optimizations turned on, gcc wrongly warns about y being used + // uninitialized unless we initialize it to something: + RealType x, y(0); + + x = boost::math::ibeta_inv(df1 / 2, df2 / 2, p, &y, Policy()); + + return df2 * x / (df1 * y); +} // quantile + +template +inline RealType cdf(const complemented2_type, RealType>& c) +{ + static const char* function = "boost::math::cdf(fisher_f_distribution<%1%> const&, %1%)"; + RealType df1 = c.dist.degrees_of_freedom1(); + RealType df2 = c.dist.degrees_of_freedom2(); + RealType x = c.param; + // Error check: + RealType error_result = 0; + if(false == detail::check_df( + function, df1, &error_result, Policy()) + && detail::check_df( + function, df2, &error_result, Policy())) + return error_result; + + if((x < 0) || !(boost::math::isfinite)(x)) + { + return policies::raise_domain_error( + function, "Random Variable parameter was %1%, but must be > 0 !", x, Policy()); + } + + RealType v1x = df1 * x; + // + // There are two equivalent formulas used here, the aim is + // to prevent the final argument to the incomplete beta + // from being too close to 1: for some values of df1 and df2 + // the rate of change can be arbitrarily large in this area, + // whilst the value we're passing will have lost information + // content as a result of being 0.999999something. Better + // to switch things around so we're passing 1-z instead. + // + return v1x > df2 + ? boost::math::ibeta(df2 / 2, df1 / 2, df2 / (df2 + v1x), Policy()) + : boost::math::ibetac(df1 / 2, df2 / 2, v1x / (df2 + v1x), Policy()); +} + +template +inline RealType quantile(const complemented2_type, RealType>& c) +{ + static const char* function = "boost::math::quantile(fisher_f_distribution<%1%> const&, %1%)"; + RealType df1 = c.dist.degrees_of_freedom1(); + RealType df2 = c.dist.degrees_of_freedom2(); + RealType p = c.param; + // Error check: + RealType error_result = 0; + if(false == (detail::check_df( + function, df1, &error_result, Policy()) + && detail::check_df( + function, df2, &error_result, Policy()) + && detail::check_probability( + function, p, &error_result, Policy()))) + return error_result; + + RealType x, y; + + x = boost::math::ibetac_inv(df1 / 2, df2 / 2, p, &y, Policy()); + + return df2 * x / (df1 * y); +} + +template +inline RealType mean(const fisher_f_distribution& dist) +{ // Mean of F distribution = v. + static const char* function = "boost::math::mean(fisher_f_distribution<%1%> const&)"; + RealType df1 = dist.degrees_of_freedom1(); + RealType df2 = dist.degrees_of_freedom2(); + // Error check: + RealType error_result = 0; + if(false == detail::check_df( + function, df1, &error_result, Policy()) + && detail::check_df( + function, df2, &error_result, Policy())) + return error_result; + if(df2 <= 2) + { + return policies::raise_domain_error( + function, "Second degree of freedom was %1% but must be > 2 in order for the distribution to have a mean.", df2, Policy()); + } + return df2 / (df2 - 2); +} // mean + +template +inline RealType variance(const fisher_f_distribution& dist) +{ // Variance of F distribution. + static const char* function = "boost::math::variance(fisher_f_distribution<%1%> const&)"; + RealType df1 = dist.degrees_of_freedom1(); + RealType df2 = dist.degrees_of_freedom2(); + // Error check: + RealType error_result = 0; + if(false == detail::check_df( + function, df1, &error_result, Policy()) + && detail::check_df( + function, df2, &error_result, Policy())) + return error_result; + if(df2 <= 4) + { + return policies::raise_domain_error( + function, "Second degree of freedom was %1% but must be > 4 in order for the distribution to have a valid variance.", df2, Policy()); + } + return 2 * df2 * df2 * (df1 + df2 - 2) / (df1 * (df2 - 2) * (df2 - 2) * (df2 - 4)); +} // variance + +template +inline RealType mode(const fisher_f_distribution& dist) +{ + static const char* function = "boost::math::mode(fisher_f_distribution<%1%> const&)"; + RealType df1 = dist.degrees_of_freedom1(); + RealType df2 = dist.degrees_of_freedom2(); + // Error check: + RealType error_result = 0; + if(false == detail::check_df( + function, df1, &error_result, Policy()) + && detail::check_df( + function, df2, &error_result, Policy())) + return error_result; + if(df2 <= 2) + { + return policies::raise_domain_error( + function, "Second degree of freedom was %1% but must be > 2 in order for the distribution to have a mode.", df2, Policy()); + } + return df2 * (df1 - 2) / (df1 * (df2 + 2)); +} + +//template +//inline RealType median(const fish