summaryrefslogtreecommitdiff
path: root/boost/math
diff options
context:
space:
mode:
authorChanho Park <chanho61.park@samsung.com>2014-12-11 18:55:56 +0900
committerChanho Park <chanho61.park@samsung.com>2014-12-11 18:55:56 +0900
commit08c1e93fa36a49f49325a07fe91ff92c964c2b6c (patch)
tree7a7053ceb8874b28ec4b868d4c49b500008a102e /boost/math
parentbb4dd8289b351fae6b55e303f189127a394a1edd (diff)
downloadboost-08c1e93fa36a49f49325a07fe91ff92c964c2b6c.tar.gz
boost-08c1e93fa36a49f49325a07fe91ff92c964c2b6c.tar.bz2
boost-08c1e93fa36a49f49325a07fe91ff92c964c2b6c.zip
Imported Upstream version 1.57.0upstream/1.57.0
Diffstat (limited to 'boost/math')
-rw-r--r--boost/math/bindings/detail/big_digamma.hpp1
-rw-r--r--boost/math/bindings/detail/big_lanczos.hpp21
-rw-r--r--boost/math/bindings/e_float.hpp3
-rw-r--r--boost/math/bindings/mpfr.hpp116
-rw-r--r--boost/math/bindings/mpreal.hpp6
-rw-r--r--boost/math/common_factor_ct.hpp83
-rw-r--r--boost/math/common_factor_rt.hpp70
-rw-r--r--boost/math/complex/acos.hpp9
-rw-r--r--boost/math/complex/asin.hpp5
-rw-r--r--boost/math/complex/atanh.hpp89
-rw-r--r--boost/math/concepts/real_concept.hpp11
-rw-r--r--boost/math/concepts/std_real_concept.hpp14
-rw-r--r--boost/math/constants/calculate_constants.hpp33
-rw-r--r--boost/math/constants/constants.hpp121
-rw-r--r--boost/math/constants/generate.hpp76
-rw-r--r--boost/math/cstdfloat/cstdfloat_cmath.hpp600
-rw-r--r--boost/math/cstdfloat/cstdfloat_complex.hpp38
-rw-r--r--boost/math/cstdfloat/cstdfloat_complex_std.hpp641
-rw-r--r--boost/math/cstdfloat/cstdfloat_iostream.hpp771
-rw-r--r--boost/math/cstdfloat/cstdfloat_limits.hpp75
-rw-r--r--boost/math/cstdfloat/cstdfloat_types.hpp431
-rw-r--r--boost/math/distributions.hpp2
-rw-r--r--boost/math/distributions/beta.hpp51
-rw-r--r--boost/math/distributions/binomial.hpp10
-rw-r--r--boost/math/distributions/cauchy.hpp27
-rw-r--r--boost/math/distributions/chi_squared.hpp43
-rw-r--r--boost/math/distributions/detail/common_error_handling.hpp26
-rw-r--r--boost/math/distributions/detail/generic_mode.hpp2
-rw-r--r--boost/math/distributions/detail/generic_quantile.hpp2
-rw-r--r--boost/math/distributions/detail/hypergeometric_pdf.hpp20
-rw-r--r--boost/math/distributions/detail/inv_discrete_quantile.hpp172
-rw-r--r--boost/math/distributions/exponential.hpp26
-rw-r--r--boost/math/distributions/extreme_value.hpp49
-rw-r--r--boost/math/distributions/fisher_f.hpp8
-rw-r--r--boost/math/distributions/fwd.hpp39
-rw-r--r--boost/math/distributions/gamma.hpp6
-rw-r--r--boost/math/distributions/geometric.hpp10
-rw-r--r--boost/math/distributions/hyperexponential.hpp634
-rw-r--r--boost/math/distributions/hypergeometric.hpp6
-rw-r--r--boost/math/distributions/inverse_chi_squared.hpp2
-rw-r--r--boost/math/distributions/inverse_gamma.hpp9
-rw-r--r--boost/math/distributions/inverse_gaussian.hpp28
-rw-r--r--boost/math/distributions/laplace.hpp94
-rw-r--r--boost/math/distributions/logistic.hpp50
-rw-r--r--boost/math/distributions/lognormal.hpp37
-rw-r--r--boost/math/distributions/negative_binomial.hpp29
-rw-r--r--boost/math/distributions/non_central_beta.hpp11
-rw-r--r--boost/math/distributions/non_central_chi_squared.hpp55
-rw-r--r--boost/math/distributions/non_central_f.hpp3
-rw-r--r--boost/math/distributions/non_central_t.hpp328
-rw-r--r--boost/math/distributions/normal.hpp65
-rw-r--r--boost/math/distributions/pareto.hpp10
-rw-r--r--boost/math/distributions/poisson.hpp107
-rw-r--r--boost/math/distributions/rayleigh.hpp24
-rw-r--r--boost/math/distributions/skew_normal.hpp113
-rw-r--r--boost/math/distributions/students_t.hpp338
-rw-r--r--boost/math/distributions/triangular.hpp6
-rw-r--r--boost/math/distributions/uniform.hpp6
-rw-r--r--boost/math/distributions/weibull.hpp22
-rw-r--r--boost/math/octonion.hpp516
-rw-r--r--boost/math/policies/error_handling.hpp342
-rw-r--r--boost/math/policies/policy.hpp21
-rw-r--r--boost/math/quaternion.hpp161
-rw-r--r--boost/math/special_functions.hpp9
-rw-r--r--boost/math/special_functions/acosh.hpp14
-rw-r--r--boost/math/special_functions/airy.hpp469
-rw-r--r--boost/math/special_functions/asinh.hpp16
-rw-r--r--boost/math/special_functions/atanh.hpp23
-rw-r--r--boost/math/special_functions/bernoulli.hpp143
-rw-r--r--boost/math/special_functions/bessel.hpp391
-rw-r--r--boost/math/special_functions/bessel_prime.hpp359
-rw-r--r--boost/math/special_functions/beta.hpp83
-rw-r--r--boost/math/special_functions/binomial.hpp1
-rw-r--r--boost/math/special_functions/cos_pi.hpp1
-rw-r--r--boost/math/special_functions/detail/airy_ai_bi_zero.hpp160
-rw-r--r--boost/math/special_functions/detail/bernoulli_details.hpp653
-rw-r--r--boost/math/special_functions/detail/bessel_derivatives_linear.hpp75
-rw-r--r--boost/math/special_functions/detail/bessel_i0.hpp5
-rw-r--r--boost/math/special_functions/detail/bessel_i1.hpp5
-rw-r--r--boost/math/special_functions/detail/bessel_ik.hpp23
-rw-r--r--boost/math/special_functions/detail/bessel_j0.hpp16
-rw-r--r--boost/math/special_functions/detail/bessel_j1.hpp17
-rw-r--r--boost/math/special_functions/detail/bessel_jn.hpp13
-rw-r--r--boost/math/special_functions/detail/bessel_jy.hpp1042
-rw-r--r--boost/math/special_functions/detail/bessel_jy_asym.hpp176
-rw-r--r--boost/math/special_functions/detail/bessel_jy_derivatives_asym.hpp141
-rw-r--r--boost/math/special_functions/detail/bessel_jy_derivatives_series.hpp220
-rw-r--r--boost/math/special_functions/detail/bessel_jy_series.hpp8
-rw-r--r--boost/math/special_functions/detail/bessel_jy_zero.hpp617
-rw-r--r--boost/math/special_functions/detail/bessel_kn.hpp1
-rw-r--r--boost/math/special_functions/detail/bessel_y0.hpp17
-rw-r--r--boost/math/special_functions/detail/bessel_y1.hpp16
-rw-r--r--boost/math/special_functions/detail/bessel_yn.hpp3
-rw-r--r--boost/math/special_functions/detail/erf_inv.hpp51
-rw-r--r--boost/math/special_functions/detail/fp_traits.hpp11
-rw-r--r--boost/math/special_functions/detail/gamma_inva.hpp8
-rw-r--r--boost/math/special_functions/detail/ibeta_inv_ab.hpp24
-rw-r--r--boost/math/special_functions/detail/ibeta_inverse.hpp97
-rw-r--r--boost/math/special_functions/detail/igamma_inverse.hpp22
-rw-r--r--boost/math/special_functions/detail/lanczos_sse2.hpp20
-rw-r--r--boost/math/special_functions/detail/lgamma_small.hpp12
-rw-r--r--boost/math/special_functions/detail/round_fwd.hpp21
-rw-r--r--boost/math/special_functions/detail/t_distribution_inv.hpp19
-rw-r--r--boost/math/special_functions/detail/unchecked_bernoulli.hpp700
-rw-r--r--boost/math/special_functions/detail/unchecked_factorial.hpp210
-rw-r--r--boost/math/special_functions/digamma.hpp15
-rw-r--r--boost/math/special_functions/ellint_1.hpp8
-rw-r--r--boost/math/special_functions/ellint_2.hpp8
-rw-r--r--boost/math/special_functions/ellint_3.hpp8
-rw-r--r--boost/math/special_functions/ellint_rj.hpp2
-rw-r--r--boost/math/special_functions/erf.hpp46
-rw-r--r--boost/math/special_functions/expint.hpp65
-rw-r--r--boost/math/special_functions/expm1.hpp10
-rw-r--r--boost/math/special_functions/factorials.hpp36
-rw-r--r--boost/math/special_functions/fpclassify.hpp175
-rw-r--r--boost/math/special_functions/gamma.hpp562
-rw-r--r--boost/math/special_functions/hankel.hpp12
-rw-r--r--boost/math/special_functions/jacobi_elliptic.hpp321
-rw-r--r--boost/math/special_functions/lanczos.hpp24
-rw-r--r--boost/math/special_functions/log1p.hpp2
-rw-r--r--boost/math/special_functions/math_fwd.hpp533
-rw-r--r--boost/math/special_functions/modf.hpp1
-rw-r--r--boost/math/special_functions/next.hpp250
-rw-r--r--boost/math/special_functions/owens_t.hpp86
-rw-r--r--boost/math/special_functions/pow.hpp8
-rw-r--r--boost/math/special_functions/powm1.hpp2
-rw-r--r--boost/math/special_functions/prime.hpp1
-rw-r--r--boost/math/special_functions/round.hpp48
-rw-r--r--boost/math/special_functions/sign.hpp71
-rw-r--r--boost/math/special_functions/sin_pi.hpp1
-rw-r--r--boost/math/special_functions/sinc.hpp52
-rw-r--r--boost/math/special_functions/sinhc.hpp11
-rw-r--r--boost/math/special_functions/spherical_harmonic.hpp3
-rw-r--r--boost/math/special_functions/sqrt1pm1.hpp2
-rw-r--r--boost/math/special_functions/trunc.hpp39
-rw-r--r--boost/math/special_functions/zeta.hpp63
-rw-r--r--boost/math/tools/big_constant.hpp25
-rw-r--r--boost/math/tools/config.hpp107
-rw-r--r--boost/math/tools/detail/polynomial_horner1_10.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner1_11.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner1_12.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner1_13.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner1_14.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner1_15.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner1_16.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner1_17.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner1_18.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner1_19.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner1_2.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner1_20.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner1_3.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner1_4.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner1_5.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner1_6.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner1_7.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner1_8.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner1_9.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner2_10.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner2_11.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner2_12.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner2_13.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner2_14.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner2_15.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner2_16.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner2_17.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner2_18.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner2_19.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner2_2.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner2_20.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner2_3.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner2_4.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner2_5.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner2_6.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner2_7.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner2_8.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner2_9.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner3_10.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner3_11.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner3_12.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner3_13.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner3_14.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner3_15.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner3_16.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner3_17.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner3_18.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner3_19.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner3_2.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner3_20.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner3_3.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner3_4.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner3_5.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner3_6.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner3_7.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner3_8.hpp2
-rw-r--r--boost/math/tools/detail/polynomial_horner3_9.hpp2
-rw-r--r--boost/math/tools/detail/rational_horner2_10.hpp2
-rw-r--r--boost/math/tools/detail/rational_horner2_11.hpp2
-rw-r--r--boost/math/tools/detail/rational_horner2_12.hpp2
-rw-r--r--boost/math/tools/detail/rational_horner2_13.hpp2
-rw-r--r--boost/math/tools/detail/rational_horner2_14.hpp2
-rw-r--r--boost/math/tools/detail/rational_horner2_15.hpp2
-rw-r--r--boost/math/tools/detail/rational_horner2_16.hpp2
-rw-r--r--boost/math/tools/detail/rational_horner2_17.hpp2
-rw-r--r--boost/math/tools/detail/rational_horner2_18.hpp2
-rw-r--r--boost/math/tools/detail/rational_horner2_19.hpp2
-rw-r--r--boost/math/tools/detail/rational_horner2_2.hpp2
-rw-r--r--boost/math/tools/detail/rational_horner2_20.hpp2
-rw-r--r--boost/math/tools/detail/rational_horner2_3.hpp2
-rw-r--r--boost/math/tools/detail/rational_horner2_4.hpp2
-rw-r--r--boost/math/tools/detail/rational_horner2_5.hpp2
-rw-r--r--boost/math/tools/detail/rational_horner2_6.hpp2
-rw-r--r--boost/math/tools/detail/rational_horner2_7.hpp2
-rw-r--r--boost/math/tools/detail/rational_horner2_8.hpp2
-rw-r--r--boost/math/tools/detail/rational_horner2_9.hpp2
-rw-r--r--boost/math/tools/detail/rational_horner3_10.hpp2
-rw-r--r--boost/math/tools/detail/rational_horner3_11.hpp2
-rw-r--r--boost/math/tools/detail/rational_horner3_12.hpp2
-rw-r--r--boost/math/tools/detail/rational_horner3_13.hpp2
-rw-r--r--boost/math/tools/detail/rational_horner3_14.hpp2
-rw-r--r--boost/math/tools/detail/rational_horner3_15.hpp2
-rw-r--r--boost/math/tools/detail/rational_horner3_16.hpp2
-rw-r--r--boost/math/tools/detail/rational_horner3_17.hpp2
-rw-r--r--boost/math/tools/detail/rational_horner3_18.hpp2
-rw-r--r--boost/math/tools/detail/rational_horner3_19.hpp2
-rw-r--r--boost/math/tools/detail/rational_horner3_2.hpp2
-rw-r--r--boost/math/tools/detail/rational_horner3_20.hpp2
-rw-r--r--boost/math/tools/detail/rational_horner3_3.hpp2
-rw-r--r--boost/math/tools/detail/rational_horner3_4.hpp2
-rw-r--r--boost/math/tools/detail/rational_horner3_5.hpp2
-rw-r--r--boost/math/tools/detail/rational_horner3_6.hpp2
-rw-r--r--boost/math/tools/detail/rational_horner3_7.hpp2
-rw-r--r--boost/math/tools/detail/rational_horner3_8.hpp2
-rw-r--r--boost/math/tools/detail/rational_horner3_9.hpp2
-rw-r--r--boost/math/tools/fraction.hpp2
-rw-r--r--boost/math/tools/precision.hpp53
-rw-r--r--boost/math/tools/promotion.hpp27
-rw-r--r--boost/math/tools/remez.hpp667
-rw-r--r--boost/math/tools/roots.hpp22
-rw-r--r--boost/math/tools/solve.hpp79
-rw-r--r--boost/math/tools/test.hpp332
-rw-r--r--boost/math/tools/test_data.hpp767
-rw-r--r--boost/math/tools/toms748_solve.hpp50
-rw-r--r--boost/math/tools/tuple.hpp24
-rw-r--r--boost/math/tools/user.hpp8
-rw-r--r--boost/math/tr1_c_macros.ipp2
245 files changed, 12230 insertions, 5226 deletions
diff --git a/boost/math/bindings/detail/big_digamma.hpp b/boost/math/bindings/detail/big_digamma.hpp
index 3d7819b500..bbddb23f04 100644
--- a/boost/math/bindings/detail/big_digamma.hpp
+++ b/boost/math/bindings/detail/big_digamma.hpp
@@ -9,6 +9,7 @@
#include <boost/math/tools/rational.hpp>
#include <boost/math/policies/error_handling.hpp>
#include <boost/math/constants/constants.hpp>
+#include <boost/lexical_cast.hpp>
namespace boost{ namespace math{ namespace detail{
diff --git a/boost/math/bindings/detail/big_lanczos.hpp b/boost/math/bindings/detail/big_lanczos.hpp
index 314b4f88c4..573f9ec1af 100644
--- a/boost/math/bindings/detail/big_lanczos.hpp
+++ b/boost/math/bindings/detail/big_lanczos.hpp
@@ -7,7 +7,6 @@
#define BOOST_BIG_LANCZOS_HPP
#include <boost/math/special_functions/lanczos.hpp>
-#include <boost/lexical_cast.hpp>
namespace boost{ namespace math{ namespace lanczos{
@@ -58,7 +57,7 @@ struct lanczos22UDT : public mpl::int_<120>
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 2.50662827463100050241576528481104525333))
};
static const T denom[22] = {
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 0)),
+ static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 0.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 2432902008176640000.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 8752948036761600000.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 13803759753640704000.0)),
@@ -75,11 +74,11 @@ struct lanczos22UDT : public mpl::int_<120>
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 756111184500.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 40171771630.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 1672280820.0)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 53327946)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 1256850)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 20615)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 210)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 1))
+ static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 53327946.0)),
+ static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 1256850.0)),
+ static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 20615.0)),
+ static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 210.0)),
+ static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 1.0))
};
return boost::math::tools::evaluate_rational(num, denom, z);
}
@@ -113,7 +112,7 @@ struct lanczos22UDT : public mpl::int_<120>
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 0.3765495513732730583386223384116545391759e-9))
};
static const T denom[22] = {
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 0)),
+ static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 0.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 2432902008176640000.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 8752948036761600000.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 13803759753640704000.0)),
@@ -132,9 +131,9 @@ struct lanczos22UDT : public mpl::int_<120>
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 1672280820.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 53327946.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 1256850.0)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 20615)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 210)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 1))
+ static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 20615.0)),
+ static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 210.0)),
+ static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 1.0))
};
return boost::math::tools::evaluate_rational(num, denom, z);
}
diff --git a/boost/math/bindings/e_float.hpp b/boost/math/bindings/e_float.hpp
index d7f9a73508..4068e35922 100644
--- a/boost/math/bindings/e_float.hpp
+++ b/boost/math/bindings/e_float.hpp
@@ -25,6 +25,7 @@
#include <boost/math/special_functions/fpclassify.hpp>
#include <boost/math/bindings/detail/big_digamma.hpp>
#include <boost/math/bindings/detail/big_lanczos.hpp>
+#include <boost/lexical_cast.hpp>
namespace boost{ namespace math{ namespace ef{
@@ -714,7 +715,7 @@ boost::math::ef::e_float bessel_i0(boost::math::ef::e_float x)
}
else // x in (15, \infty)
{
- boost::math::ef::e_float y = 1 / x - 1 / 15;
+ boost::math::ef::e_float y = 1 / x - boost::math::ef::e_float(1) / 15;
r = evaluate_polynomial(P2, y) / evaluate_polynomial(Q2, y);
factor = exp(x) / sqrt(x);
value = factor * r;
diff --git a/boost/math/bindings/mpfr.hpp b/boost/math/bindings/mpfr.hpp
index e5c6ba071d..5edc0ae44c 100644
--- a/boost/math/bindings/mpfr.hpp
+++ b/boost/math/bindings/mpfr.hpp
@@ -12,6 +12,7 @@
#define BOOST_MATH_MPLFR_BINDINGS_HPP
#include <boost/config.hpp>
+#include <boost/lexical_cast.hpp>
#ifdef BOOST_MSVC
//
@@ -35,19 +36,31 @@
#include <boost/math/special_functions/math_fwd.hpp>
#include <boost/math/bindings/detail/big_digamma.hpp>
#include <boost/math/bindings/detail/big_lanczos.hpp>
+#include <boost/math/tools/big_constant.hpp>
inline mpfr_class fabs(const mpfr_class& v)
{
return abs(v);
}
+template <class T, class U>
+inline mpfr_class fabs(const __gmp_expr<T,U>& v)
+{
+ return abs(static_cast<mpfr_class>(v));
+}
-inline mpfr_class pow(const mpfr_class& b, const mpfr_class e)
+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 <class T, class U, class V, class W>
+inline mpfr_class pow(const __gmp_expr<T,U>& b, const __gmp_expr<V,W>& e)
+{
+ return pow(static_cast<mpfr_class>(b), static_cast<mpfr_class>(e));
+}
+*/
inline mpfr_class ldexp(const mpfr_class& v, int e)
{
//int e = mpfr_get_exp(*v.__get_mp());
@@ -55,6 +68,11 @@ inline mpfr_class ldexp(const mpfr_class& v, int e)
mpfr_set_exp(result.__get_mp(), e);
return result;
}
+template <class T, class U>
+inline mpfr_class ldexp(const __gmp_expr<T,U>& v, int e)
+{
+ return ldexp(static_cast<mpfr_class>(v), e);
+}
inline mpfr_class frexp(const mpfr_class& v, int* expon)
{
@@ -64,6 +82,11 @@ inline mpfr_class frexp(const mpfr_class& v, int* expon)
*expon = e;
return result;
}
+template <class T, class U>
+inline mpfr_class frexp(const __gmp_expr<T,U>& v, int* expon)
+{
+ return frexp(static_cast<mpfr_class>(v), expon);
+}
inline mpfr_class fmod(const mpfr_class& v1, const mpfr_class& v2)
{
@@ -74,6 +97,11 @@ inline mpfr_class fmod(const mpfr_class& v1, const mpfr_class& v2)
n = floor(v1 / v2);
return v1 - n * v2;
}
+template <class T, class U, class V, class W>
+inline mpfr_class fmod(const __gmp_expr<T,U>& v1, const __gmp_expr<V,W>& v2)
+{
+ return fmod(static_cast<mpfr_class>(v1), static_cast<mpfr_class>(v2));
+}
template <class Policy>
inline mpfr_class modf(const mpfr_class& v, long long* ipart, const Policy& pol)
@@ -81,43 +109,86 @@ 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<mpfr_class>(*ipart);
}
+template <class T, class U, class Policy>
+inline mpfr_class modf(const __gmp_expr<T,U>& v, long long* ipart, const Policy& pol)
+{
+ return modf(static_cast<mpfr_class>(v), ipart, pol);
+}
+
template <class Policy>
-inline int iround(mpfr_class const& x, const Policy& pol)
+inline int iround(mpfr_class const& x, const Policy&)
{
- return boost::math::tools::real_cast<int>(boost::math::round(x, pol));
+ return boost::math::tools::real_cast<int>(boost::math::round(x, typename boost::math::policies::normalise<Policy, boost::math::policies::rounding_error< boost::math::policies::throw_on_error> >::type()));
+}
+template <class T, class U, class Policy>
+inline int iround(__gmp_expr<T,U> const& x, const Policy& pol)
+{
+ return iround(static_cast<mpfr_class>(x), pol);
}
template <class Policy>
-inline long lround(mpfr_class const& x, const Policy& pol)
+inline long lround(mpfr_class const& x, const Policy&)
+{
+ return boost::math::tools::real_cast<long>(boost::math::round(x, typename boost::math::policies::normalise<Policy, boost::math::policies::rounding_error< boost::math::policies::throw_on_error> >::type()));
+}
+template <class T, class U, class Policy>
+inline long lround(__gmp_expr<T,U> const& x, const Policy& pol)
{
- return boost::math::tools::real_cast<long>(boost::math::round(x, pol));
+ return lround(static_cast<mpfr_class>(x), pol);
}
template <class Policy>
-inline long long llround(mpfr_class const& x, const Policy& pol)
+inline long long llround(mpfr_class const& x, const Policy&)
{
- return boost::math::tools::real_cast<long long>(boost::math::round(x, pol));
+ return boost::math::tools::real_cast<long long>(boost::math::round(x, typename boost::math::policies::normalise<Policy, boost::math::policies::rounding_error< boost::math::policies::throw_on_error> >::type()));
+}
+template <class T, class U, class Policy>
+inline long long llround(__gmp_expr<T,U> const& x, const Policy& pol)
+{
+ return llround(static_cast<mpfr_class>(x), pol);
}
template <class Policy>
-inline int itrunc(mpfr_class const& x, const Policy& pol)
+inline int itrunc(mpfr_class const& x, const Policy&)
+{
+ return boost::math::tools::real_cast<int>(boost::math::trunc(x, typename boost::math::policies::normalise<Policy, boost::math::policies::rounding_error< boost::math::policies::throw_on_error> >::type()));
+}
+template <class T, class U, class Policy>
+inline int itrunc(__gmp_expr<T,U> const& x, const Policy& pol)
{
- return boost::math::tools::real_cast<int>(boost::math::trunc(x, pol));
+ return itrunc(static_cast<mpfr_class>(x), pol);
}
template <class Policy>
-inline long ltrunc(mpfr_class const& x, const Policy& pol)
+inline long ltrunc(mpfr_class const& x, const Policy&)
{
- return boost::math::tools::real_cast<long>(boost::math::trunc(x, pol));
+ return boost::math::tools::real_cast<long>(boost::math::trunc(x, typename boost::math::policies::normalise<Policy, boost::math::policies::rounding_error< boost::math::policies::throw_on_error> >::type()));
+}
+template <class T, class U, class Policy>
+inline long ltrunc(__gmp_expr<T,U> const& x, const Policy& pol)
+{
+ return ltrunc(static_cast<mpfr_class>(x), pol);
}
template <class Policy>
-inline long long lltrunc(mpfr_class const& x, const Policy& pol)
+inline long long lltrunc(mpfr_class const& x, const Policy&)
+{
+ return boost::math::tools::real_cast<long long>(boost::math::trunc(x, typename boost::math::policies::normalise<Policy, boost::math::policies::rounding_error< boost::math::policies::throw_on_error> >::type()));
+}
+template <class T, class U, class Policy>
+inline long long lltrunc(__gmp_expr<T,U> const& x, const Policy& pol)
{
- return boost::math::tools::real_cast<long long>(boost::math::trunc(x, pol));
+ return lltrunc(static_cast<mpfr_class>(x), pol);
}
-namespace boost{ namespace math{
+namespace boost{
+
+#ifdef BOOST_MATH_USE_FLOAT128
+ template<> struct is_convertible<BOOST_MATH_FLOAT128_TYPE, mpfr_class> : public boost::integral_constant<bool, false>{};
+#endif
+ template<> struct is_convertible<long long, mpfr_class> : public boost::integral_constant<bool, false>{};
+
+namespace math{
#if defined(__GNUC__) && (__GNUC__ < 4)
using ::iround;
@@ -203,6 +274,19 @@ struct lanczos<mpfr_class, Policy>
} // namespace lanczos
+namespace constants{
+
+template <class Real, class Policy>
+struct construction_traits;
+
+template <class Policy>
+struct construction_traits<mpfr_class, Policy>
+{
+ typedef mpl::int_<0> type;
+};
+
+}
+
namespace tools
{
@@ -771,7 +855,7 @@ inline mpfr_class bessel_i0(mpfr_class x)
}
else // x in (15, \infty)
{
- mpfr_class y = 1 / x - 1 / 15;
+ 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;
diff --git a/boost/math/bindings/mpreal.hpp b/boost/math/bindings/mpreal.hpp
index 82f7950b92..80ed81946d 100644
--- a/boost/math/bindings/mpreal.hpp
+++ b/boost/math/bindings/mpreal.hpp
@@ -736,7 +736,7 @@ mpfr::mpreal erf_inv_imp(const mpfr::mpreal& p, const mpfr::mpreal& q, const Pol
return result;
}
-mpfr::mpreal bessel_i0(mpfr::mpreal x)
+inline mpfr::mpreal bessel_i0(mpfr::mpreal x)
{
static const mpfr::mpreal P1[] = {
boost::lexical_cast<mpfr::mpreal>("-2.2335582639474375249e+15"),
@@ -802,7 +802,7 @@ mpfr::mpreal bessel_i0(mpfr::mpreal x)
}
else // x in (15, \infty)
{
- mpfr::mpreal y = 1 / x - 1 / 15;
+ 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;
@@ -811,7 +811,7 @@ mpfr::mpreal bessel_i0(mpfr::mpreal x)
return value;
}
-mpfr::mpreal bessel_i1(mpfr::mpreal x)
+inline mpfr::mpreal bessel_i1(mpfr::mpreal x)
{
static const mpfr::mpreal P1[] = {
static_cast<mpfr::mpreal>("-1.4577180278143463643e+15"),
diff --git a/boost/math/common_factor_ct.hpp b/boost/math/common_factor_ct.hpp
index 848c925290..bf58b94eb2 100644
--- a/boost/math/common_factor_ct.hpp
+++ b/boost/math/common_factor_ct.hpp
@@ -23,7 +23,6 @@ namespace math
namespace detail
{
-#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
// Build GCD with Euclid's recursive algorithm
template < static_gcd_type Value1, static_gcd_type Value2 >
struct static_gcd_helper_t
@@ -54,48 +53,7 @@ namespace detail
{
BOOST_STATIC_CONSTANT( static_gcd_type, value = Value1 );
};
-#else
- // Use inner class template workaround from Peter Dimov
- template < static_gcd_type Value1 >
- struct static_gcd_helper2_t
- {
- template < static_gcd_type Value2 >
- struct helper
- {
- BOOST_STATIC_CONSTANT( static_gcd_type, value
- = static_gcd_helper2_t<Value2>::BOOST_NESTED_TEMPLATE
- helper<Value1 % Value2>::value );
- };
-
- template < >
- struct helper< 0UL >
- {
- BOOST_STATIC_CONSTANT( static_gcd_type, value = Value1 );
- };
- };
-
- // Special case
- template < >
- struct static_gcd_helper2_t< 0UL >
- {
- template < static_gcd_type Value2 >
- struct helper
- {
- BOOST_STATIC_CONSTANT( static_gcd_type, value = Value2 );
- };
- };
-
- // Build the GCD from the above template(s)
- template < static_gcd_type Value1, static_gcd_type Value2 >
- struct static_gcd_helper_t
- {
- BOOST_STATIC_CONSTANT( static_gcd_type, value
- = static_gcd_helper2_t<Value1>::BOOST_NESTED_TEMPLATE
- helper<Value2>::value );
- };
-#endif
-#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
// Build the LCM from the GCD
template < static_gcd_type Value1, static_gcd_type Value2 >
struct static_lcm_helper_t
@@ -112,47 +70,6 @@ namespace detail
{
BOOST_STATIC_CONSTANT( static_gcd_type, value = 0UL );
};
-#else
- // Adapt GCD's inner class template workaround for LCM
- template < static_gcd_type Value1 >
- struct static_lcm_helper2_t
- {
- template < static_gcd_type Value2 >
- struct helper
- {
- typedef static_gcd_helper_t<Value1, Value2> gcd_type;
-
- BOOST_STATIC_CONSTANT( static_gcd_type, value = Value1
- / gcd_type::value * Value2 );
- };
-
- template < >
- struct helper< 0UL >
- {
- BOOST_STATIC_CONSTANT( static_gcd_type, value = 0UL );
- };
- };
-
- // Special case
- template < >
- struct static_lcm_helper2_t< 0UL >
- {
- template < static_gcd_type Value2 >
- struct helper
- {
- BOOST_STATIC_CONSTANT( static_gcd_type, value = 0UL );
- };
- };
-
- // Build the LCM from the above template(s)
- template < static_gcd_type Value1, static_gcd_type Value2 >
- struct static_lcm_helper_t
- {
- BOOST_STATIC_CONSTANT( static_gcd_type, value
- = static_lcm_helper2_t<Value1>::BOOST_NESTED_TEMPLATE
- helper<Value2>::value );
- };
-#endif
} // namespace detail
diff --git a/boost/math/common_factor_rt.hpp b/boost/math/common_factor_rt.hpp
index 4582a96c7b..10a92ebf56 100644
--- a/boost/math/common_factor_rt.hpp
+++ b/boost/math/common_factor_rt.hpp
@@ -222,7 +222,6 @@ namespace detail
// Function objects to find the best way of computing GCD or LCM
#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
-#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template < typename T, bool IsSpecialized, bool IsSigned >
struct gcd_optimal_evaluator_helper_t
{
@@ -240,40 +239,6 @@ namespace detail
return gcd_integer( a, b );
}
};
-#else
- template < bool IsSpecialized, bool IsSigned >
- struct gcd_optimal_evaluator_helper2_t
- {
- template < typename T >
- struct helper
- {
- T operator ()( T const &a, T const &b )
- {
- return gcd_euclidean( a, b );
- }
- };
- };
-
- template < >
- struct gcd_optimal_evaluator_helper2_t< true, true >
- {
- template < typename T >
- struct helper
- {
- T operator ()( T const &a, T const &b )
- {
- return gcd_integer( a, b );
- }
- };
- };
-
- template < typename T, bool IsSpecialized, bool IsSigned >
- struct gcd_optimal_evaluator_helper_t
- : gcd_optimal_evaluator_helper2_t<IsSpecialized, IsSigned>
- ::BOOST_NESTED_TEMPLATE helper<T>
- {
- };
-#endif
template < typename T >
struct gcd_optimal_evaluator
@@ -348,7 +313,6 @@ namespace detail
#undef BOOST_PRIVATE_GCD_SF
#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
-#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template < typename T, bool IsSpecialized, bool IsSigned >
struct lcm_optimal_evaluator_helper_t
{
@@ -366,40 +330,6 @@ namespace detail
return lcm_integer( a, b );
}
};
-#else
- template < bool IsSpecialized, bool IsSigned >
- struct lcm_optimal_evaluator_helper2_t
- {
- template < typename T >
- struct helper
- {
- T operator ()( T const &a, T const &b )
- {
- return lcm_euclidean( a, b );
- }
- };
- };
-
- template < >
- struct lcm_optimal_evaluator_helper2_t< true, true >
- {
- template < typename T >
- struct helper
- {
- T operator ()( T const &a, T const &b )
- {
- return lcm_integer( a, b );
- }
- };
- };
-
- template < typename T, bool IsSpecialized, bool IsSigned >
- struct lcm_optimal_evaluator_helper_t
- : lcm_optimal_evaluator_helper2_t<IsSpecialized, IsSigned>
- ::BOOST_NESTED_TEMPLATE helper<T>
- {
- };
-#endif
template < typename T >
struct lcm_optimal_evaluator
diff --git a/boost/math/complex/acos.hpp b/boost/math/complex/acos.hpp
index 466dcc63f1..a911756949 100644
--- a/boost/math/complex/acos.hpp
+++ b/boost/math/complex/acos.hpp
@@ -31,12 +31,13 @@ std::complex<T> acos(const std::complex<T>& z)
//
//
- // These static constants should really be in a maths constants library:
+ // 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<T>(1);
//static const T two = static_cast<T>(2);
static const T half = static_cast<T>(0.5L);
- static const T a_crossover = static_cast<T>(1.5L);
+ static const T a_crossover = static_cast<T>(10);
static const T b_crossover = static_cast<T>(0.6417L);
static const T s_pi = boost::math::constants::pi<T>();
static const T half_pi = s_pi / 2;
@@ -172,14 +173,16 @@ std::complex<T> acos(const std::complex<T>& z)
}
else
{
- real = 0;
+ // This deviates from Hull et al's paper as per https://svn.boost.org/trac/boost/ticket/7290
if(((std::numeric_limits<T>::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);
}
}
diff --git a/boost/math/complex/asin.hpp b/boost/math/complex/asin.hpp
index 1d20795217..087c3b51ef 100644
--- a/boost/math/complex/asin.hpp
+++ b/boost/math/complex/asin.hpp
@@ -31,12 +31,13 @@ inline std::complex<T> asin(const std::complex<T>& z)
//
//
- // These static constants should really be in a maths constants library:
+ // 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<T>(1);
//static const T two = static_cast<T>(2);
static const T half = static_cast<T>(0.5L);
- static const T a_crossover = static_cast<T>(1.5L);
+ static const T a_crossover = static_cast<T>(10);
static const T b_crossover = static_cast<T>(0.6417L);
static const T s_pi = boost::math::constants::pi<T>();
static const T half_pi = s_pi / 2;
diff --git a/boost/math/complex/atanh.hpp b/boost/math/complex/atanh.hpp
index 4ecb4e199f..66f4599e52 100644
--- a/boost/math/complex/atanh.hpp
+++ b/boost/math/complex/atanh.hpp
@@ -36,6 +36,8 @@ std::complex<T> atanh(const std::complex<T>& z)
// 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<T>();
static const T half_pi = pi / 2;
@@ -43,7 +45,7 @@ std::complex<T> atanh(const std::complex<T>& z)
static const T two = static_cast<T>(2.0L);
static const T four = static_cast<T>(4.0L);
static const T zero = static_cast<T>(0);
- static const T a_crossover = static_cast<T>(0.3L);
+ static const T log_two = boost::math::constants::ln_two<T>();
#ifdef BOOST_MSVC
#pragma warning(push)
@@ -82,45 +84,19 @@ std::complex<T> atanh(const std::complex<T>& z)
else if((x > safe_lower) && (x < safe_upper) && (y > safe_lower) && (y < safe_upper))
{
- T xx = x*x;
T yy = y*y;
- T x2 = x * two;
-
+ T mxm1 = one - x;
///
// The real part is given by:
//
- // real(atanh(z)) == log((1 + x^2 + y^2 + 2x) / (1 + x^2 + y^2 - 2x))
+ // real(atanh(z)) == log1p(4*x / ((x-1)*(x-1) + y^2))
//
- // However, when x is either large (x > 1/E) or very small
- // (x < E) then this effectively simplifies
- // to log(1), leading to wildly inaccurate results.
- // By dividing the above (top and bottom) by (1 + x^2 + y^2) we get:
- //
- // real(atanh(z)) == log((1 + (2x / (1 + x^2 + y^2))) / (1 - (-2x / (1 + x^2 + y^2))))
- //
- // which is much more sensitive to the value of x, when x is not near 1
- // (remember we can compute log(1+x) for small x very accurately).
- //
- // The cross-over from one method to the other has to be determined
- // experimentally, the value used below appears correct to within a
- // factor of 2 (and there are larger errors from other parts
- // of the input domain anyway).
- //
- T alpha = two*x / (one + xx + yy);
- if(alpha < a_crossover)
- {
- real = boost::math::log1p(alpha) - boost::math::log1p((boost::math::changesign)(alpha));
- }
- else
- {
- T xm1 = x - one;
- real = boost::math::log1p(x2 + xx + yy) - std::log(xm1*xm1 + yy);
- }
+ 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), (one - xx - yy));
+ imag = std::atan2((y * two), (mxm1*(one+x) - yy));
imag /= two;
if(z.imag() < 0)
imag = (boost::math::changesign)(imag);
@@ -132,30 +108,31 @@ std::complex<T> atanh(const std::complex<T>& z)
// underflow or overflow in the main formulas.
//
// Begin by working out the real part, we need to approximate
- // alpha = 2x / (1 + x^2 + y^2)
+ // real = boost::math::log1p(4x / ((x-1)^2 + y^2))
// without either overflow or underflow in the squared terms.
//
- T alpha = 0;
+ T mxm1 = one - x;
if(x >= safe_upper)
{
+ // x-1 = x to machine precision:
if((boost::math::isinf)(x) || (boost::math::isinf)(y))
{
- alpha = 0;
+ real = 0;
}
else if(y >= safe_upper)
{
- // Big x and y: divide alpha through by x*y:
- alpha = (two/y) / (x/y + y/x);
+ // 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:
- alpha = two / (x + y*y/x);
+ real = boost::math::log1p(four / (x + y*y/x));
}
else
{
// Big x small y, as above but neglect y^2/x:
- alpha = two/x;
+ real = boost::math::log1p(four/x);
}
}
else if(y >= safe_upper)
@@ -163,39 +140,25 @@ std::complex<T> atanh(const std::complex<T>& z)
if(x > one)
{
// Big y, medium x, divide through by y:
- alpha = (two*x/y) / (y + x*x/y);
+ real = boost::math::log1p((four*x/y) / (y + mxm1*mxm1/y));
}
else
{
- // Small x and y, whatever alpha is, it's too small to calculate:
- alpha = 0;
+ // Small or medium x, large y:
+ real = four*x/y/y;
}
}
- else
+ else if (x != one)
{
- // one or both of x and y are small, calculate divisor carefully:
- T div = one;
- if(x > safe_lower)
- div += x*x;
+ // y is small, calculate divisor carefully:
+ T div = mxm1*mxm1;
if(y > safe_lower)
div += y*y;
- alpha = two*x/div;
- }
- if(alpha < a_crossover)
- {
- real = boost::math::log1p(alpha) - boost::math::log1p((boost::math::changesign)(alpha));
+ real = boost::math::log1p(four*x/div);
}
else
- {
- // We can only get here as a result of small y and medium sized x,
- // we can simply neglect the y^2 terms:
- BOOST_ASSERT(x >= safe_lower);
- BOOST_ASSERT(x <= safe_upper);
- //BOOST_ASSERT(y <= safe_lower);
- T xm1 = x - one;
- real = std::log(1 + two*x + x*x) - std::log(xm1*xm1);
- }
-
+ real = boost::math::changesign(two * (std::log(y) - log_two));
+
real /= four;
if((boost::math::signbit)(z.real()))
real = (boost::math::changesign)(real);
@@ -203,7 +166,7 @@ std::complex<T> atanh(const std::complex<T>& z)
//
// Now handle imaginary part, this is much easier,
// if x or y are large, then the formula:
- // atan2(2y, 1 - x^2 - y^2)
+ // 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))
@@ -234,7 +197,7 @@ std::complex<T> atanh(const std::complex<T>& z)
if((y == zero) && (x == one))
imag = 0;
else
- imag = std::atan2(two*y, 1 - x*x);
+ imag = std::atan2(two*y, mxm1*(one+x));
}
imag /= two;
if((boost::math::signbit)(z.imag()))
diff --git a/boost/math/concepts/real_concept.hpp b/boost/math/concepts/real_concept.hpp
index 1ed2c1df00..2267271a00 100644
--- a/boost/math/concepts/real_concept.hpp
+++ b/boost/math/concepts/real_concept.hpp
@@ -84,6 +84,9 @@ public:
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; }
@@ -304,7 +307,7 @@ inline std::basic_istream<charT, traits>& operator>>(std::basic_istream<charT, t
is >> v;
a = v;
return is;
-#elif defined(__SGI_STL_PORT) || defined(_RWSTD_VER) || defined(__LIBCOMO__)
+#elif defined(__SGI_STL_PORT) || defined(_RWSTD_VER) || defined(__LIBCOMO__) || defined(_LIBCPP_VERSION)
std::string s;
real_concept_base_type d;
is >> s;
@@ -325,7 +328,7 @@ namespace tools
{
template <>
-inline concepts::real_concept make_big_value<concepts::real_concept>(long double val, const char* , mpl::false_ const&, mpl::false_ const&)
+inline concepts::real_concept make_big_value<concepts::real_concept>(boost::floatmax_t val, const char* , mpl::false_ const&, mpl::false_ const&)
{
return val; // Can't use lexical_cast here, sometimes it fails....
}
@@ -366,7 +369,7 @@ inline concepts::real_concept epsilon<concepts::real_concept>(BOOST_MATH_EXPLICI
template <>
inline int digits<concepts::real_concept>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::real_concept))
-{
+{
// Assume number of significand bits is same as real_concept_base_type,
// unless std::numeric_limits<T>::is_specialized to provide digits.
return tools::digits<concepts::real_concept_base_type>();
@@ -432,7 +435,7 @@ inline long double real_cast<long double, concepts::real_concept>(concepts::real
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
//
-// For some strange reason ADL sometimes fails to find the
+// For some strange reason ADL sometimes fails to find the
// correct overloads, unless we bring these declarations into scope:
//
using concepts::itrunc;
diff --git a/boost/math/concepts/std_real_concept.hpp b/boost/math/concepts/std_real_concept.hpp
index 4c4eb6ac32..b4f75bcadb 100644
--- a/boost/math/concepts/std_real_concept.hpp
+++ b/boost/math/concepts/std_real_concept.hpp
@@ -67,6 +67,9 @@ public:
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; }
@@ -313,10 +316,19 @@ inline std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, t
template <class charT, class traits>
inline std::basic_istream<charT, traits>& operator>>(std::basic_istream<charT, traits>& 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
@@ -330,7 +342,7 @@ namespace tools
{
template <>
-inline concepts::std_real_concept make_big_value<concepts::std_real_concept>(long double val, const char* , mpl::false_ const&, mpl::false_ const&)
+inline concepts::std_real_concept make_big_value<concepts::std_real_concept>(boost::floatmax_t val, const char*, mpl::false_ const&, mpl::false_ const&)
{
return val; // Can't use lexical_cast here, sometimes it fails....
}
diff --git a/boost/math/constants/calculate_constants.hpp b/boost/math/constants/calculate_constants.hpp
index 0b78929e71..2dcdb9a02b 100644
--- a/boost/math/constants/calculate_constants.hpp
+++ b/boost/math/constants/calculate_constants.hpp
@@ -85,6 +85,7 @@ template <class T> // sqrt(2/pi)
template <int N>
inline T constant_root_two_div_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
+ BOOST_MATH_STD_USING
return sqrt((2 / pi<T, policies::policy<policies::digits2<N> > >()));
}
@@ -121,6 +122,14 @@ inline T constant_root_two_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC
template <class T>
template<int N>
+inline T constant_log_root_two_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
+{
+ BOOST_MATH_STD_USING
+ return log(root_two_pi<T, policies::policy<policies::digits2<N> > >());
+}
+
+template <class T>
+template<int N>
inline T constant_root_ln_four<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
@@ -156,11 +165,11 @@ inline T constant_euler<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::
// 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 Comnputation, Volume 34, Number 149, Jan 1980, pages 305-312.
+ // 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<T>()) : tools::digits<T>()) / 4;
- T lim = M ? ldexp(T(1), (std::min)(M, tools::digits<T>())) : tools::epsilon<T>();
+ T lim = M ? ldexp(T(1), 1 - (std::min)(M, tools::digits<T>())) : tools::epsilon<T>();
T lnn = log(n);
T term = 1;
T N = -lnn;
@@ -301,13 +310,13 @@ inline T constant_four_minus_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SP
return static_cast<T>(4) - pi<T, policies::policy<policies::digits2<N> > >();
}
-template <class T>
-template<int N>
-inline T constant_pow23_four_minus_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
-{
- BOOST_MATH_STD_USING
- return pow(four_minus_pi<T, policies::policy<policies::digits2<N> > >(), static_cast<T>(1.5));
-}
+//template <class T>
+//template<int N>
+//inline T constant_pow23_four_minus_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
+//{
+// BOOST_MATH_STD_USING
+// return pow(four_minus_pi<T, policies::policy<policies::digits2<N> > >(), static_cast<T>(1.5));
+//}
template <class T>
template<int N>
@@ -595,7 +604,7 @@ inline T constant_zeta_three<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(
//"1.202056903159594285399738161511449990, 76498629234049888179227155534183820578631309018645587360933525814619915" A002117
// 1.202056903159594285399738161511449990, 76498629234049888179227155534183820578631309018645587360933525814619915780, +00);
//"1.2020569031595942 double
- // http://www.spaennare.se/SSPROG/ssnum.pdf // section 11, Algorithmfor Apery’s constant zeta(3).
+ // 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
@@ -928,7 +937,7 @@ template <class T>
template<int N>
inline T constant_rayleigh_kurtosis_excess<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{ // - (6 Pi^2 - 24 Pi + 16)/((Pi - 4)^2)
- // Might provide provide and calculate this using pi_minus_four.
+ // Might provide and calculate this using pi_minus_four.
BOOST_MATH_STD_USING
return - (((static_cast<T>(6) * pi<T, policies::policy<policies::digits2<N> > >()
* pi<T, policies::policy<policies::digits2<N> > >())
@@ -943,7 +952,7 @@ template <class T>
template<int N>
inline T constant_rayleigh_kurtosis<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{ // 3 - (6 Pi^2 - 24 Pi + 16)/((Pi - 4)^2)
- // Might provide provide and calculate this using pi_minus_four.
+ // Might provide and calculate this using pi_minus_four.
BOOST_MATH_STD_USING
return static_cast<T>(3) - (((static_cast<T>(6) * pi<T, policies::policy<policies::digits2<N> > >()
* pi<T, policies::policy<policies::digits2<N> > >())
diff --git a/boost/math/constants/constants.hpp b/boost/math/constants/constants.hpp
index bb2260e7a7..e9381adeb6 100644
--- a/boost/math/constants/constants.hpp
+++ b/boost/math/constants/constants.hpp
@@ -14,7 +14,9 @@
#pragma warning(push)
#pragma warning(disable: 4127 4701)
#endif
+#ifndef BOOST_MATH_NO_LEXICAL_CAST
#include <boost/lexical_cast.hpp>
+#endif
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
@@ -22,12 +24,14 @@
#include <boost/mpl/and.hpp>
#include <boost/mpl/int.hpp>
#include <boost/type_traits/is_convertible.hpp>
+#include <boost/utility/declval.hpp>
+
namespace boost{ namespace math
{
namespace constants
{
- // To permit other calculations at about 100 decimal digits with NTL::RR type,
+ // 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.
@@ -46,7 +50,33 @@ namespace boost{ namespace math
construct_from_float = 1,
construct_from_double = 2,
construct_from_long_double = 3,
- construct_from_string = 4
+ 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 <int N>
+ struct dummy_size{};
+
+ template <class T>
+ struct is_explicitly_convertible_from_string
+ {
+#ifndef BOOST_NO_SFINAE_EXPR
+ template<typename S1, typename T1>
+ static type_traits::yes_type selector(dummy_size<sizeof(static_cast<T1>(declval<S1>()))>*);
+
+ template<typename S1, typename T1>
+ static type_traits::no_type selector(...);
+
+ static const bool value = sizeof(selector<const char*, T>(0)) == sizeof(type_traits::yes_type);
+#else
+ static const bool value = false;
+#endif
};
//
@@ -63,6 +93,9 @@ namespace boost{ namespace math
typedef typename policies::precision<float, Policy>::type t2;
typedef typename policies::precision<double, Policy>::type t3;
typedef typename policies::precision<long double, Policy>::type t4;
+#ifdef BOOST_MATH_USE_FLOAT128
+ typedef mpl::int_<113> t5;
+#endif
public:
typedef typename mpl::if_<
mpl::and_<boost::is_convertible<float, Real>, mpl::bool_< t1::value <= t2::value>, mpl::bool_<0 != t1::value> >,
@@ -73,11 +106,23 @@ namespace boost{ namespace math
typename mpl::if_<
mpl::and_<boost::is_convertible<long double, Real>, mpl::bool_< t1::value <= t4::value>, mpl::bool_<0 != t1::value> >,
mpl::int_<construct_from_long_double>,
+#ifdef BOOST_MATH_USE_FLOAT128
+ typename mpl::if_<
+ mpl::and_<boost::is_convertible<BOOST_MATH_FLOAT128_TYPE, Real>, mpl::bool_< t1::value <= t5::value>, mpl::bool_<0 != t1::value> >,
+ mpl::int_<construct_from_float128>,
+ typename mpl::if_<
+ mpl::and_<mpl::bool_< t1::value <= max_string_digits>, mpl::bool_<0 != t1::value> >,
+ mpl::int_<construct_from_string>,
+ mpl::int_<t1::value>
+ >::type
+ >::type
+#else
typename mpl::if_<
mpl::and_<mpl::bool_< t1::value <= max_string_digits>, mpl::bool_<0 != t1::value> >,
mpl::int_<construct_from_string>,
mpl::int_<t1::value>
>::type
+#endif
>::type
>::type
>::type type;
@@ -93,10 +138,24 @@ namespace boost{ namespace math
namespace detail{
+ template <class Real, class Policy = boost::math::policies::policy<> >
+ struct constant_return
+ {
+ typedef typename construction_traits<Real, Policy>::type construct_type;
+ typedef typename mpl::if_c<
+ (construct_type::value == construct_from_string) || (construct_type::value > construct_max),
+ const Real&, Real>::type type;
+ };
+
template <class Real>
Real convert_from_string(const char* p, const mpl::false_&)
{
+#ifdef BOOST_MATH_NO_LEXICAL_CAST
+ // This function should not compile, we don't have the necesary functionality to support it:
+ BOOST_STATIC_ASSERT(sizeof(Real) == 0);
+#else
return boost::lexical_cast<Real>(p);
+#endif
}
template <class Real>
const char* convert_from_string(const char* p, const mpl::true_&)
@@ -104,7 +163,7 @@ namespace boost{ namespace math
return p;
}
- template <class T, T (*F)(BOOST_EXPLICIT_TEMPLATE_TYPE_SPEC(T))>
+ template <class T, const T& (*F)()>
struct constant_initializer
{
static void force_instantiate()
@@ -116,21 +175,17 @@ namespace boost{ namespace math
{
initializer()
{
- F(
- #ifdef BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS
- 0
- #endif
- );
+ F();
}
void force_instantiate()const{}
};
static const initializer init;
};
- template <class T, T (*F)(BOOST_EXPLICIT_TEMPLATE_TYPE_SPEC(T))>
+ template <class T, const T& (*F)()>
typename constant_initializer<T, F>::initializer const constant_initializer<T, F>::init;
- template <class T, int N, T (*F)(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>) BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(T))>
+ template <class T, int N, const T& (*F)(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>) BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(T))>
struct constant_initializer2
{
static void force_instantiate()
@@ -142,37 +197,47 @@ namespace boost{ namespace math
{
initializer()
{
- F(
- #ifdef BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS
- mpl::int_<N>() , 0
- #endif
- );
+ F();
}
void force_instantiate()const{}
};
static const initializer init;
};
- template <class T, int N, T (*F)(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>) BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(T))>
+ template <class T, int N, const T& (*F)(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>) BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(T))>
typename constant_initializer2<T, N, F>::initializer const constant_initializer2<T, N, F>::init;
}
- #define BOOST_DEFINE_MATH_CONSTANT(name, x, y)\
+#ifdef BOOST_MATH_USE_FLOAT128
+# define BOOST_MATH_FLOAT128_CONSTANT_OVERLOAD(x) \
+ static inline BOOST_CONSTEXPR T get(const mpl::int_<construct_from_float128>&)\
+ { return BOOST_JOIN(x, Q); }
+#else
+# define BOOST_MATH_FLOAT128_CONSTANT_OVERLOAD(x)
+#endif
+
+#define BOOST_DEFINE_MATH_CONSTANT(name, x, y)\
namespace detail{\
template <class T> struct BOOST_JOIN(constant_, name){\
private:\
/* The default implementations come next: */ \
- static inline T get_from_string()\
+ static inline const T& get_from_string()\
{\
- static const T result = convert_from_string<T>(y, boost::is_convertible<const char*, T>());\
+ typedef mpl::bool_<boost::is_convertible<const char*, T>::value || boost::math::constants::is_explicitly_convertible_from_string<T>::value> tag_type;\
+ static const T result(convert_from_string<T>(y, tag_type()));\
return result;\
}\
/* This one is for very high precision that is none the less known at compile time: */ \
template <int N> static T compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>));\
+ template <int N> static inline const T& get_from_compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))\
+ {\
+ static const T result = compute<N>();\
+ return result;\
+ }\
/* public getters come next */\
public:\
- static inline T get(const mpl::int_<construct_from_string>&)\
+ static inline const T& get(const mpl::int_<construct_from_string>&)\
{\
constant_initializer<T, & BOOST_JOIN(constant_, name)<T>::get_from_string >::force_instantiate();\
return get_from_string();\
@@ -183,10 +248,11 @@ namespace boost{ namespace math
{ return x; }\
static inline BOOST_CONSTEXPR T get(const mpl::int_<construct_from_long_double>&)\
{ return BOOST_JOIN(x, L); }\
- template <int N> static inline T get(const mpl::int_<N>& n)\
+ BOOST_MATH_FLOAT128_CONSTANT_OVERLOAD(x) \
+ template <int N> static inline const T& get(const mpl::int_<N>&)\
{\
- constant_initializer2<T, N, & BOOST_JOIN(constant_, name)<T>::template compute<N> >::force_instantiate();\
- return compute<N>(); \
+ constant_initializer2<T, N, & BOOST_JOIN(constant_, name)<T>::template get_from_compute<N> >::force_instantiate();\
+ return get_from_compute<N>(); \
}\
/* This one is for true arbitary precision, which may well vary at runtime: */ \
static inline T get(const mpl::int_<0>&)\
@@ -196,9 +262,9 @@ namespace boost{ namespace math
\
\
/* The actual forwarding function: */ \
- template <class T, class Policy> inline BOOST_CONSTEXPR T name(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(T) BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(Policy))\
+ template <class T, class Policy> inline BOOST_CONSTEXPR typename detail::constant_return<T, Policy>::type name(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(T) BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(Policy))\
{ return detail:: BOOST_JOIN(constant_, name)<T>::get(typename construction_traits<T, Policy>::type()); }\
- template <class T> inline BOOST_CONSTEXPR T name(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(T))\
+ template <class T> inline BOOST_CONSTEXPR typename detail::constant_return<T>::type name(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(T))\
{ return name<T, boost::math::policies::policy<> >(); }\
\
\
@@ -233,11 +299,12 @@ namespace boost{ namespace math
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(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")
@@ -272,7 +339,7 @@ namespace boost{ namespace math
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")
diff --git a/boost/math/constants/generate.hpp b/boost/math/constants/generate.hpp
deleted file mode 100644
index dfb15633a5..0000000000
--- a/boost/math/constants/generate.hpp
+++ /dev/null
@@ -1,76 +0,0 @@
-// 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)
-
-#ifndef BOOST_MATH_CONSTANTS_GENERATE_INCLUDED
-#define BOOST_MATH_CONSTANTS_GENERATE_INCLUDED
-
-#include <boost/math/constants/constants.hpp>
-#include <boost/regex.hpp>
-#include <iostream>
-#include <iomanip>
-#include <sstream>
-
-#ifdef USE_MPFR
-#include <boost/math/bindings/mpfr.hpp>
-#elif defined(USE_MPREAL)
-#include <boost/math/bindings/mpreal.hpp>
-#elif defined(USE_CPP_FLOAT)
-#include <boost/multiprecision/cpp_float.hpp>
-#else
-#include <boost/math/bindings/rr.hpp>
-#endif
-
-namespace boost{ namespace math{ namespace constants{
-
-#ifdef USE_MPFR
-typedef mpfr_class generator_type;
-#elif defined(USE_MPREAL)
-typedef mpfr::mpreal generator_type;
-#elif defined(USE_CPP_FLOAT)
-typedef boost::multiprecision::mp_number<boost::multiprecision::cpp_float<500> > generator_type;
-#else
-typedef ntl::RR generator_type;
-#endif
-
-inline void print_constant(const char* name, generator_type(*f)(const mpl::int_<0>&))
-{
-#ifdef USE_MPFR
- mpfr_class::set_dprec(((200 + 1) * 1000L) / 301L);
-#elif defined(USE_MPREAL)
- mpfr::mpreal::set_default_prec(((200 + 1) * 1000L) / 301L);
-#elif defined(USE_CPP_FLOAT)
- // Nothing to do, precision is already set.
-#else
- ntl::RR::SetPrecision(((200 + 1) * 1000L) / 301L);
- ntl::RR::SetOutputPrecision(102);
-#endif
- generator_type value = f(boost::mpl::int_<0>());
- std::stringstream os;
- os << std::setprecision(110) << std::scientific;
- os << value;
- std::string s = os.str();
- static const regex e("([+-]?\\d+(?:\\.\\d{0,36})?)(\\d*)(?:e([+-]?\\d+))?");
- smatch what;
- if(regex_match(s, what, e))
- {
- std::cout <<
- "BOOST_DEFINE_MATH_CONSTANT(" << name << ", "
- << what[1] << "e" << (what[3].length() ? what[3].str() : std::string("0")) << ", "
- << "\"" << what[1] << what[2] << "e" << (what[3].length() ? what[3].str() : std::string("0"))
- << "\");" << std::endl;
- }
- else
- {
- std::cout << "Format of numeric constant was not recognised!!" << std::endl;
- }
-}
-
-#define BOOST_CONSTANTS_GENERATE(name) \
- boost::math::constants::print_constant(#name, \
- & boost::math::constants::detail::BOOST_JOIN(constant_, name)<boost::math::constants::generator_type>::get)
-
-}}} // namespaces
-
-#endif // BOOST_MATH_CONSTANTS_GENERATE_INCLUDED
diff --git a/boost/math/cstdfloat/cstdfloat_cmath.hpp b/boost/math/cstdfloat/cstdfloat_cmath.hpp
new file mode 100644
index 0000000000..3043d90567
--- /dev/null
+++ b/boost/math/cstdfloat/cstdfloat_cmath.hpp
@@ -0,0 +1,600 @@
+///////////////////////////////////////////////////////////////////////////////
+// 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 <cmath> support.
+
+#ifndef _BOOST_CSTDFLOAT_CMATH_2014_02_15_HPP_
+ #define _BOOST_CSTDFLOAT_CMATH_2014_02_15_HPP_
+
+ #include <boost/math/cstdfloat/cstdfloat_types.hpp>
+ #include <boost/math/cstdfloat/cstdfloat_limits.hpp>
+
+ #if defined(BOOST_CSTDFLOAT_HAS_INTERNAL_FLOAT128_T) && defined(BOOST_MATH_USE_FLOAT128) && !defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT)
+
+ #include <cmath>
+ #include <stdexcept>
+ #include <boost/cstdint.hpp>
+ #include <boost/static_assert.hpp>
+ #include <boost/throw_exception.hpp>
+
+ #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<class float_type, class integer_type>
+ 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<float_type>::max)())
+ : bool(-x > (std::numeric_limits<float_type>::max)()));
+
+ if(isnan) { return x; }
+
+ if(isinf) { return std::numeric_limits<float_type>::quiet_NaN(); }
+
+ const bool x_is_neg = (x < 0);
+ const float_type abs_x = (x_is_neg ? -x : x);
+
+ if(p < static_cast<integer_type>(0))
+ {
+ if(abs_x < (std::numeric_limits<float_type>::min)())
+ {
+ return (x_is_neg ? -std::numeric_limits<float_type>::infinity()
+ : +std::numeric_limits<float_type>::infinity());
+ }
+ else
+ {
+ return float_type(1) / pown(x, static_cast<integer_type>(-p));
+ }
+ }
+
+ if(p == static_cast<integer_type>(0))
+ {
+ return float_type(1);
+ }
+ else
+ {
+ if(p == static_cast<integer_type>(1)) { return x; }
+
+ if(abs_x > (std::numeric_limits<float_type>::max)())
+ {
+ return (x_is_neg ? -std::numeric_limits<float_type>::infinity()
+ : +std::numeric_limits<float_type>::infinity());
+ }
+
+ if (p == static_cast<integer_type>(2)) { return (x * x); }
+ else if(p == static_cast<integer_type>(3)) { return ((x * x) * x); }
+ else if(p == static_cast<integer_type>(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 <cmath> functions.
+ #if defined(BOOST_INTEL)
+ #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
+ #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_internal
+ #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
+ #endif
+
+ // Implement quadruple-precision <cmath> 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" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LDEXP (boost::math::cstdfloat::detail::float_internal128_t, int) throw();
+ extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FREXP (boost::math::cstdfloat::detail::float_internal128_t, int*) throw();
+ extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FABS (boost::math::cstdfloat::detail::float_internal128_t) throw();
+ extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FLOOR (boost::math::cstdfloat::detail::float_internal128_t) throw();
+ extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_CEIL (boost::math::cstdfloat::detail::float_internal128_t) throw();
+ extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SQRT (boost::math::cstdfloat::detail::float_internal128_t) throw();
+ extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TRUNC (boost::math::cstdfloat::detail::float_internal128_t) throw();
+ 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) throw();
+ extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LOG (boost::math::cstdfloat::detail::float_internal128_t) throw();
+ extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LOG10 (boost::math::cstdfloat::detail::float_internal128_t) throw();
+ extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SIN (boost::math::cstdfloat::detail::float_internal128_t) throw();
+ extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_COS (boost::math::cstdfloat::detail::float_internal128_t) throw();
+ extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TAN (boost::math::cstdfloat::detail::float_internal128_t) throw();
+ extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ASIN (boost::math::cstdfloat::detail::float_internal128_t) throw();
+ extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ACOS (boost::math::cstdfloat::detail::float_internal128_t) throw();
+ extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ATAN (boost::math::cstdfloat::detail::float_internal128_t) throw();
+ 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) throw();
+ 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) throw();
+ extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LGAMMA(boost::math::cstdfloat::detail::float_internal128_t) throw();
+
+ #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) throw();
+ extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SINH (boost::math::cstdfloat::detail::float_internal128_t x) throw();
+ extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_COSH (boost::math::cstdfloat::detail::float_internal128_t x) throw();
+ extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TANH (boost::math::cstdfloat::detail::float_internal128_t x) throw();
+ extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ASINH (boost::math::cstdfloat::detail::float_internal128_t x) throw();
+ extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ACOSH (boost::math::cstdfloat::detail::float_internal128_t x) throw();
+ extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ATANH (boost::math::cstdfloat::detail::float_internal128_t x) throw();
+ extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TGAMMA(boost::math::cstdfloat::detail::float_internal128_t x) throw();
+
+ #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-36 polynomial approximation of the exponential function
+ // in the range of (-ln2 < x < ln2). Scale the argument to this range
+ // and subsequently multiply the result by 2^n accordingly.
+
+ // Derive the polynomial coefficients with Mathematica(R) by generating
+ // a table of high-precision values of exp(x) in the range (-ln2 < x < ln2)
+ // and subsequently applying the built-in *Fit* function.
+
+ // Table[{x, Exp[x] - 1}, {x, -Log[2], Log[2], 1/180}]
+ // N[%, 120]
+ // Fit[%, {x, x^2, x^3, x^4, x^5, x^6, x^7, x^8, x^9, x^10, x^11, x^12,
+ // x^13, x^14, x^15, x^16, x^17, x^18, x^19, x^20, x^21, x^22,
+ // x^23, x^24, x^25, x^26, x^27, x^28, x^29, x^30, x^31, x^32,
+ // x^33, x^34, x^35, x^36}, x]
+
+ 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
+ {
+ // Compute the polynomial approximation of exp(alpha).
+ sum = (((((((((((((((((((((((((((((((((((( float_type(BOOST_FLOAT128_C(2.69291698127774166063293705964720493864630783729857438187365E-42)) * x
+ + float_type(BOOST_FLOAT128_C(9.70937085471487654794114679403710456028986572118859594614033E-41))) * x
+ + float_type(BOOST_FLOAT128_C(3.38715585158055097155585505318085512156885389014410753080500E-39))) * x
+ + float_type(BOOST_FLOAT128_C(1.15162718532861050809222658798662695267019717760563645440433E-37))) * x
+ + float_type(BOOST_FLOAT128_C(3.80039074689434663295873584133017767349635602413675471702393E-36))) * x
+ + float_type(BOOST_FLOAT128_C(1.21612504934087520075905434734158045947460467096773246215239E-34))) * x
+ + float_type(BOOST_FLOAT128_C(3.76998762883139753126119821241037824830069851253295480396224E-33))) * x
+ + float_type(BOOST_FLOAT128_C(1.13099628863830344684998293828608215735777107850991029729440E-31))) * x
+ + float_type(BOOST_FLOAT128_C(3.27988923706982293204067897468714277771890104022419696770352E-30))) * x
+ + float_type(BOOST_FLOAT128_C(9.18368986379558482800593745627556950089950023355628325088207E-29))) * x
+ + float_type(BOOST_FLOAT128_C(2.47959626322479746949155352659617642905315302382639380521497E-27))) * x
+ + float_type(BOOST_FLOAT128_C(6.44695028438447337900255966737803112935639344283098705091949E-26))) * x
+ + float_type(BOOST_FLOAT128_C(1.61173757109611834904452725462599961406036904573072897122957E-24))) * x
+ + float_type(BOOST_FLOAT128_C(3.86817017063068403772269360016918092488847584660382953555804E-23))) * x
+ + float_type(BOOST_FLOAT128_C(8.89679139245057328674891109315654704307721758924206107351744E-22))) * x
+ + float_type(BOOST_FLOAT128_C(1.95729410633912612308475595397946731738088422488032228717097E-20))) * x
+ + float_type(BOOST_FLOAT128_C(4.11031762331216485847799061511674191805055663711439605760231E-19))) * x
+ + float_type(BOOST_FLOAT128_C(8.22063524662432971695598123977873600603370758794431071426640E-18))) * x
+ + float_type(BOOST_FLOAT128_C(1.56192069685862264622163643500633782667263448653185159383285E-16))) * x
+ + float_type(BOOST_FLOAT128_C(2.81145725434552076319894558300988749849555291507956994126835E-15))) * x
+ + float_type(BOOST_FLOAT128_C(4.77947733238738529743820749111754320727153728139716409114011E-14))) * x
+ + float_type(BOOST_FLOAT128_C(7.64716373181981647590113198578807092707697416852226691068627E-13))) * x
+ + float_type(BOOST_FLOAT128_C(1.14707455977297247138516979786821056670509688396295740818677E-11))) * x
+ + float_type(BOOST_FLOAT128_C(1.60590438368216145993923771701549479323291461578567184216302E-10))) * x
+ + float_type(BOOST_FLOAT128_C(2.08767569878680989792100903212014323125428376052986408239620E-09))) * x
+ + float_type(BOOST_FLOAT128_C(2.50521083854417187750521083854417187750523408006206780016659E-08))) * x
+ + float_type(BOOST_FLOAT128_C(2.75573192239858906525573192239858906525573195144226062684604E-07))) * x
+ + float_type(BOOST_FLOAT128_C(2.75573192239858906525573192239858906525573191310049321957902E-06))) * x
+ + float_type(BOOST_FLOAT128_C(0.00002480158730158730158730158730158730158730158730149317774))) * x
+ + float_type(BOOST_FLOAT128_C(0.00019841269841269841269841269841269841269841269841293575920))) * x
+ + float_type(BOOST_FLOAT128_C(0.00138888888888888888888888888888888888888888888888889071045))) * x
+ + float_type(BOOST_FLOAT128_C(0.00833333333333333333333333333333333333333333333333332986595))) * x
+ + float_type(BOOST_FLOAT128_C(0.04166666666666666666666666666666666666666666666666666664876))) * x
+ + float_type(BOOST_FLOAT128_C(0.16666666666666666666666666666666666666666666666666666669048))) * x
+ + float_type(BOOST_FLOAT128_C(0.50000000000000000000000000000000000000000000000000000000006))) * x
+ + float_type(BOOST_FLOAT128_C(0.99999999999999999999999999999999999999999999999999999999995))) * x);
+ }
+
+ 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.
+
+ // Use an order-36 polynomial approximation of the exponential function
+ // in the range of (-ln2 < x < ln2). Scale the argument to this range
+ // and subsequently multiply the result by 2^n accordingly.
+
+ // Derive the polynomial coefficients with Mathematica(R) by generating
+ // a table of high-precision values of exp(x) in the range (-ln2 < x < ln2)
+ // and subsequently applying the built-in *Fit* function.
+
+ // Table[{x, Exp[x] - 1}, {x, -Log[2], Log[2], 1/180}]
+ // N[%, 120]
+ // Fit[%, {x, x^2, x^3, x^4, x^5, x^6, x^7, x^8, x^9, x^10, x^11, x^12,
+ // x^13, x^14, x^15, x^16, x^17, x^18, x^19, x^20, x^21, x^22,
+ // x^23, x^24, x^25, x^26, x^27, x^28, x^29, x^30, x^31, x^32,
+ // x^33, x^34, x^35, x^36}, x]
+
+ typedef boost::math::cstdfloat::detail::float_internal128_t float_type;
+
+ // Scale the argument x to the range (-ln2 < x < ln2).
+ BOOST_CONSTEXPR_OR_CONST float_type one_over_ln2 = float_type(BOOST_FLOAT128_C(1.44269504088896340735992468100189213742664595415299));
+ const float_type x_over_ln2 = x * one_over_ln2;
+
+ boost::int_fast32_t n;
+
+ if(x != x)
+ {
+ // The argument is NaN.
+ return std::numeric_limits<float_type>::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::int_fast32_t>(::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 = static_cast<boost::int_fast32_t>(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<boost::int_fast32_t>(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) throw()
+ {
+ // 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) throw()
+ {
+ // 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) throw()
+ {
+ // 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) throw()
+ {
+ // 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 <boost/math/gamma.hpp>.
+ const bool floor_of_z_is_equal_to_z = (positive_x == ::BOOST_CSTDFLOAT_FLOAT128_FLOOR(positive_x));
+
+ BOOST_CONSTEXPR_OR_CONST float_type my_pi = BOOST_FLOAT128_C(3.14159265358979323846264338327950288419716939937511);
+
+ if(floor_of_z_is_equal_to_z)
+ {
+ const bool is_odd = ((boost::int32_t(floor_of_positive_x) % boost::int32_t(2)) != boost::int32_t(0));
+
+ return (is_odd ? -std::numeric_limits<float_type>::infinity()
+ : +std::numeric_limits<float_type>::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<float_type>::max)() * ::BOOST_CSTDFLOAT_FLOAT128_FABS(gamma_value)) < my_pi));
+
+ if(result_is_too_large_to_represent)
+ {
+ const bool is_odd = ((boost::int32_t(floor_of_positive_x) % boost::int32_t(2)) != boost::int32_t(0));
+
+ return (is_odd ? -std::numeric_limits<float_type>::infinity()
+ : +std::numeric_limits<float_type>::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<float_type>::quiet_NaN();
+ }
+ }
+ #endif // BOOST_CSTDFLOAT_BROKEN_FLOAT128_MATH_FUNCTIONS
+
+ // Define the quadruple-precision <cmath> 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 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); }
+ } } } } // boost::math::cstdfloat::detail
+
+ // We will now inject the quadruple-precision <cmath> 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;
+ using boost::math::cstdfloat::detail::abs;
+ 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::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;
+ } // namespace std
+
+ // We will now remove the preprocessor symbols representing quadruple-precision <cmath>
+ // 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
+
+ #endif // Not BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT (i.e., the user would like to have libquadmath support)
+
+#endif // _BOOST_CSTDFLOAT_CMATH_2014_02_15_HPP_
diff --git a/boost/math/cstdfloat/cstdfloat_complex.hpp b/boost/math/cstdfloat/cstdfloat_complex.hpp
new file mode 100644
index 0000000000..b3f4314280
--- /dev/null
+++ b/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 <complex>.
+
+#ifndef _BOOST_CSTDFLOAT_COMPLEX_2014_02_15_HPP_
+ #define _BOOST_CSTDFLOAT_COMPLEX_2014_02_15_HPP_
+
+ #include <boost/math/cstdfloat/cstdfloat_types.hpp>
+ #include <boost/math/cstdfloat/cstdfloat_limits.hpp>
+ #include <boost/math/cstdfloat/cstdfloat_cmath.hpp>
+ #include <boost/math/cstdfloat/cstdfloat_iostream.hpp>
+
+ #if defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_LIMITS)
+ #error You can not use <boost/math/cstdfloat/cstdfloat_complex.hpp> with BOOST_CSTDFLOAT_NO_LIBQUADMATH_LIMITS defined.
+ #endif
+ #if defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_CMATH)
+ #error You can not use <boost/math/cstdfloat/cstdfloat_complex.hpp> with BOOST_CSTDFLOAT_NO_LIBQUADMATH_CMATH defined.
+ #endif
+ #if defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_IOSTREAM)
+ #error You can not use <boost/math/cstdfloat/cstdfloat_complex.hpp> 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 <boost/math/cstdfloat/cstdfloat_complex_std.hpp>
+ #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_CSTDFLOAT_COMPLEX_2014_02_15_HPP_
diff --git a/boost/math/cstdfloat/cstdfloat_complex_std.hpp b/boost/math/cstdfloat/cstdfloat_complex_std.hpp
new file mode 100644
index 0000000000..f949a9aa46
--- /dev/null
+++ b/boost/math/cstdfloat/cstdfloat_complex_std.hpp
@@ -0,0 +1,641 @@
+///////////////////////////////////////////////////////////////////////////////
+// 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_CSTDFLOAT_COMPLEX_STD_2014_02_15_HPP_
+ #define _BOOST_CSTDFLOAT_COMPLEX_STD_2014_02_15_HPP_
+
+ #if defined(__GNUC__)
+ #pragma GCC system_header
+ #endif
+
+ #include <complex>
+ #include <boost/math/constants/constants.hpp>
+
+ namespace std
+ {
+ // Forward declarations.
+ template<class float_type>
+ class complex;
+
+ template<>
+ class complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>;
+
+ inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE real(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+ inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE imag(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+
+ inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE abs (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+ inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE arg (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+ inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE norm(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> conj (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> proj (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> polar(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE&,
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& = 0);
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> sqrt (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> sin (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> cos (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> tan (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> asin (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> acos (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> atan (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> exp (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> log (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> log10(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> pow (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&,
+ int);
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> pow (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&,
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE&);
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> pow (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&,
+ const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> pow (const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE&,
+ const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> sinh (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> cosh (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> tanh (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> asinh(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> acosh(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> atanh(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+
+ template<class char_type, class traits_type>
+ inline std::basic_ostream<char_type, traits_type>& operator<<(std::basic_ostream<char_type, traits_type>&, const std::complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+
+ template<class char_type, class traits_type>
+ inline std::basic_istream<char_type, traits_type>& operator>>(std::basic_istream<char_type, traits_type>&, std::complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
+
+ // Template specialization of the complex class.
+ template<>
+ class complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>
+ {
+ public:
+ typedef BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE value_type;
+
+ explicit complex(const complex<float>&);
+ explicit complex(const complex<double>&);
+ explicit complex(const complex<long double>&);
+
+ #if defined(BOOST_NO_CXX11_CONSTEXPR)
+ complex(const value_type& r = value_type(),
+ const value_type& i = value_type()) : re(r),
+ im(i) { }
+
+ template<typename X>
+ complex(const complex<X>& 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
+ BOOST_CONSTEXPR complex(const value_type& r = value_type(),
+ const value_type& i = value_type()) : re(r),
+ im(i) { }
+
+ template<typename X>
+ BOOST_CONSTEXPR complex(const complex<X>& 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<value_type>& operator=(const value_type& v)
+ {
+ re = v;
+ im = value_type(0);
+ return *this;
+ }
+
+ complex<value_type>& operator+=(const value_type& v)
+ {
+ re += v;
+ return *this;
+ }
+
+ complex<value_type>& operator-=(const value_type& v)
+ {
+ re -= v;
+ return *this;
+ }
+
+ complex<value_type>& operator*=(const value_type& v)
+ {
+ re *= v;
+ im *= v;
+ return *this;
+ }
+
+ complex<value_type>& operator/=(const value_type& v)
+ {
+ re /= v;
+ im /= v;
+ return *this;
+ }
+
+ template<typename X>
+ complex<value_type>& operator=(const complex<X>& x)
+ {
+ re = x.real();
+ im = x.imag();
+ return *this;
+ }
+
+ template<typename X>
+ complex<value_type>& operator+=(const complex<X>& x)
+ {
+ re += x.real();
+ im += x.imag();
+ return *this;
+ }
+
+ template<typename X>
+ complex<value_type>& operator-=(const complex<X>& x)
+ {
+ re -= x.real();
+ im -= x.imag();
+ return *this;
+ }
+
+ template<typename X>
+ complex<value_type>& operator*=(const complex<X>& 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<typename X>
+ complex<value_type>& operator/=(const complex<X>& 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.
+ complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::complex(const complex<float>& f) : re(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE( f.real())), im(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE( f.imag())) { }
+ complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::complex(const complex<double>& d) : re(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE( d.real())), im(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE( d.imag())) { }
+ complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::complex(const complex<long double>& 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<class float_type> std::complex<float_type> multiply_by_i(const std::complex<float_type>& x)
+ {
+ // Multiply x (in C) by I (the imaginary component), and return the result.
+ return std::complex<float_type>(-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<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x) { return x.real(); }
+ inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE imag(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x) { return x.imag(); }
+
+ inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE abs (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x) { using std::sqrt; return sqrt ((real(x) * real(x)) + (imag(x) * imag(x))); }
+ inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE arg (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x) { using std::atan2; return atan2(x.imag(), x.real()); }
+ inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE norm(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x) { return (real(x) * real(x)) + (imag(x) * imag(x)); }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> conj (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x) { return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(x.real(), -x.imag()); }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> proj (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
+ {
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE m = (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::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<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::infinity(), x.imag() < 0 ? -0 : 0);
+ }
+ return x;
+ }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> 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<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(rho * cos(theta), rho * sin(theta));
+ }
+
+ // Global add, sub, mul, div.
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator+(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& u, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& v) { return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(u.real() + v.real(), u.imag() + v.imag()); }
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator-(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& u, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& v) { return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(u.real() - v.real(), u.imag() - v.imag()); }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator*(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& u, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& v)
+ {
+ return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>((u.real() * v.real()) - (u.imag() * v.imag()),
+ (u.real() * v.imag()) + (u.imag() * v.real()));
+ }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator/(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& u, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& v)
+ {
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE the_norm = std::norm(v);
+
+ return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(((u.real() * v.real()) + (u.imag() * v.imag())) / the_norm,
+ ((u.imag() * v.real()) - (u.real() * v.imag())) / the_norm);
+ }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator+(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& u, const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& v) { return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(u.real() + v, u.imag()); }
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator-(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& u, const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& v) { return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(u.real() - v, u.imag()); }
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator*(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& u, const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& v) { return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(u.real() * v, u.imag() * v); }
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator/(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& u, const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& v) { return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(u.real() / v, u.imag() / v); }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator+(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& u, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& v) { return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(u + v.real(), v.imag()); }
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator-(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& u, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& v) { return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(u - v.real(), -v.imag()); }
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator*(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& u, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& v) { return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(u * v.real(), u * v.imag()); }
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator/(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& u, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& v) { const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE v_norm = norm(v); return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>((u * v.real()) / v_norm, (-u * v.imag()) / v_norm); }
+
+ // Unary plus / minus.
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator+(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& u) { return u; }
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator-(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& u) { return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(-u.real(), -u.imag()); }
+
+ // Equality and inequality.
+ inline bool operator==(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& y) { return ((x.real() == y.real()) && (x.imag() == y.imag())); }
+ inline bool operator==(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& 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<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& y) { return ((x == y.real()) && (y.imag() == BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(0))); }
+ inline bool operator!=(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& y) { return ((x.real() != y.real()) || (x.imag() != y.imag())); }
+ inline bool operator!=(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& 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<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& 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<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> sqrt(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& 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<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(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<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(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<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(sqrt_xi_half, sqrt_xi_half);
+ }
+ }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> sin(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& 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<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(sin_x * cosh_y, cos_x * sinh_y);
+ }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> cos(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& 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<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(cos_x * cosh_y, -(sin_x * sinh_y));
+ }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> tan(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& 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<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(sin_x * cosh_y, cos_x * sinh_y)
+ / complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(cos_x * cosh_y, -sin_x * sinh_y));
+ }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> asin(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& 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<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> acos(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
+ {
+ return boost::math::constants::half_pi<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>() - std::asin(x);
+ }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> atan(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
+ {
+ const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> 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<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> exp(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
+ {
+ using std::exp;
+
+ return std::polar(exp(x.real()), x.imag());
+ }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> log(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
+ {
+ using std::atan2;
+ using std::log;
+
+ return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(log(std::norm(x)) / 2, atan2(x.imag(), x.real()));
+ }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> log10(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
+ {
+ return std::log(x) / boost::math::constants::ln_ten<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>();
+ }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> pow(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& 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<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::max)())
+ : bool(-x.real() > (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::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<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::max)())
+ : bool(-x.imag() > (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::max)()));
+
+ if(re_isnan || im_isnan) { return x; }
+
+ if(re_isinf || im_isinf)
+ {
+ return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::quiet_NaN(),
+ std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::quiet_NaN());
+ }
+
+ if(p < 0)
+ {
+ if(std::abs(x) < (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::min)())
+ {
+ return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::infinity(),
+ std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::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>(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1));
+ }
+ else
+ {
+ if(p == 1) { return x; }
+
+ if(std::abs(x) > (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::max)())
+ {
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE re = (re_isneg ? -std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::infinity()
+ : +std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::infinity());
+
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE im = (im_isneg ? -std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::infinity()
+ : +std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::infinity());
+
+ return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(re, im);
+ }
+
+ if (p == 2) { return (x * x); }
+ else if(p == 3) { return ((x * x) * x); }
+ else if(p == 4) { const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> x2 = (x * x); return (x2 * x2); }
+ else
+ {
+ // The variable xn stores the binary powers of x.
+ complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> result(((p % 2) != 0) ? x : complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1)));
+ complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> 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<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> pow(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x,
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& a)
+ {
+ return std::exp(a * std::log(x));
+ }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> pow(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x,
+ const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& a)
+ {
+ return std::exp(a * std::log(x));
+ }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> pow(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& x,
+ const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& a)
+ {
+ return std::exp(a * std::log(x));
+ }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> sinh(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& 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<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(cos_y * sinh_x, cosh_x * sin_y);
+ }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> cosh(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& 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<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(cos_y * cosh_x, sin_y * sinh_x);
+ }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> tanh(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
+ {
+ const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> ex_plus = std::exp(x);
+ const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> ex_minus = BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) / ex_plus;
+
+ return (ex_plus - ex_minus) / (ex_plus + ex_minus);
+ }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> asinh(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
+ {
+ return std::log(x + std::sqrt((x * x) + BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1)));
+ }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> acosh(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
+ {
+ const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE my_one(1);
+
+ const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> zp(x.real() + my_one, x.imag());
+ const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> zm(x.real() - my_one, x.imag());
+
+ return std::log(x + (zp * std::sqrt(zm / zp)));
+ }
+
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> atanh(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& 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<class char_type, class traits_type>
+ inline std::basic_ostream<char_type, traits_type>& operator<<(std::basic_ostream<char_type, traits_type>& os, const std::complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
+ {
+ std::basic_ostringstream<char_type, traits_type> 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<class char_type, class traits_type>
+ inline std::basic_istream<char_type, traits_type>& operator>>(std::basic_istream<char_type, traits_type>& is, std::complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
+ {
+ BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE rx;
+ BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE ix;
+
+ char_type the_char;
+
+ static_cast<void>(is >> the_char);
+
+ if(the_char == static_cast<char_type>('('))
+ {
+ static_cast<void>(is >> rx >> the_char);
+
+ if(the_char == static_cast<char_type>(','))
+ {
+ static_cast<void>(is >> ix >> the_char);
+
+ if(the_char == static_cast<char_type>(')'))
+ {
+ x = complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(rx, ix);
+ }
+ else
+ {
+ is.setstate(ios_base::failbit);
+ }
+ }
+ else if(the_char == static_cast<char_type>(')'))
+ {
+ x = rx;
+ }
+ else
+ {
+ is.setstate(ios_base::failbit);
+ }
+ }
+ else
+ {
+ static_cast<void>(is.putback(the_char));
+
+ static_cast<void>(is >> rx);
+
+ x = rx;
+ }
+
+ return is;
+ }
+ } // namespace std
+
+#endif // _BOOST_CSTDFLOAT_COMPLEX_STD_2014_02_15_HPP_
diff --git a/boost/math/cstdfloat/cstdfloat_iostream.hpp b/boost/math/cstdfloat/cstdfloat_iostream.hpp
new file mode 100644
index 0000000000..ac94fd35f9
--- /dev/null
+++ b/boost/math/cstdfloat/cstdfloat_iostream.hpp
@@ -0,0 +1,771 @@
+///////////////////////////////////////////////////////////////////////////////
+// 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_CSTDFLOAT_IOSTREAM_2014_02_15_HPP_
+ #define _BOOST_CSTDFLOAT_IOSTREAM_2014_02_15_HPP_
+
+ #include <boost/math/cstdfloat/cstdfloat_types.hpp>
+ #include <boost/math/cstdfloat/cstdfloat_limits.hpp>
+ #include <boost/math/cstdfloat/cstdfloat_cmath.hpp>
+
+ #if defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_CMATH)
+ #error You can not use <boost/math/cstdfloat/cstdfloat_iostream.hpp> 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 <cstddef>
+ #include <istream>
+ #include <ostream>
+ #include <sstream>
+ #include <stdexcept>
+ #include <string>
+ #include <boost/static_assert.hpp>
+ #include <boost/throw_exception.hpp>
+
+// #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, ...) throw();
+ extern "C" boost::math::cstdfloat::detail::float_internal128_t strtoflt128(const char*, char **) throw();
+
+ namespace std
+ {
+ template<typename char_type, class traits_type>
+ inline std::basic_ostream<char_type, traits_type>& operator<<(std::basic_ostream<char_type, traits_type>& os, const boost::math::cstdfloat::detail::float_internal128_t& x)
+ {
+ std::basic_ostringstream<char_type, traits_type> ostr;
+ ostr.flags(os.flags());
+ ostr.imbue(os.getloc());
+ ostr.precision(os.precision());
+
+ char my_buffer[64U];
+
+ const int my_prec = static_cast<int>(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<int>(sizeof(my_buffer)),
+ my_format_string,
+ my_digits,
+ x);
+
+ if(v < 0) { BOOST_THROW_EXCEPTION(std::runtime_error("Formatting of boost::float128_t failed internally in quadmath_snprintf().")); }
+
+ if(v >= static_cast<int>(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<char*>(0U);
+
+ try
+ {
+ my_buffer2 = new char[v + 3];
+ }
+ catch(const std::bad_alloc&)
+ {
+ BOOST_THROW_EXCEPTION(std::runtime_error("Formatting of boost::float128_t failed while allocating memory."));
+ }
+
+ const int v2 = ::quadmath_snprintf(my_buffer2,
+ v + 3,
+ my_format_string,
+ my_digits,
+ x);
+
+ if(v2 >= v + 3)
+ {
+ BOOST_THROW_EXCEPTION(std::runtime_error("Formatting of boost::float128_t failed."));
+ }
+
+ static_cast<void>(ostr << my_buffer2);
+
+ delete [] my_buffer2;
+ }
+ else
+ {
+ static_cast<void>(ostr << my_buffer);
+ }
+
+ return (os << ostr.str());
+ }
+
+ template<typename char_type, class traits_type>
+ inline std::basic_istream<char_type, traits_type>& operator>>(std::basic_istream<char_type, traits_type>& is, boost::math::cstdfloat::detail::float_internal128_t& x)
+ {
+ std::string str;
+
+ static_cast<void>(is >> str);
+
+ char* p_end;
+
+ x = strtoflt128(str.c_str(), &p_end);
+
+ if(static_cast<std::ptrdiff_t>(p_end - str.c_str()) != static_cast<std::ptrdiff_t>(str.length()))
+ {
+ for(std::string::const_reverse_iterator it = str.rbegin(); it != str.rend(); ++it)
+ {
+ static_cast<void>(is.putback(*it));
+ }
+
+ is.setstate(ios_base::failbit);
+
+ BOOST_THROW_EXCEPTION(std::runtime_error("Unable to interpret input string as a boost::float128_t"));
+ }
+
+ return is;
+ }
+ }
+
+// #elif defined(__GNUC__)
+ #elif defined(BOOST_INTEL)
+
+ // 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 <cstring>
+ #include <cctype>
+ #include <boost/lexical_cast.hpp>
+
+ namespace boost { namespace math { namespace cstdfloat { namespace detail {
+
+ template<class string_type>
+ 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<int>((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<int>(str.size());
+ chars = digits - chars;
+
+ if(scientific)
+ {
+ ++chars;
+ }
+
+ if(chars > 0)
+ {
+ str.append(static_cast<size_type>(chars), '0');
+ }
+ }
+
+ if(fixed || (!scientific && (my_exp >= -4) && (my_exp < digits)))
+ {
+ if((1 + my_exp) > static_cast<int>(str.size()))
+ {
+ // Just pad out the end with zeros.
+ str.append(static_cast<size_type>((1 + my_exp) - static_cast<int>(str.size())), '0');
+
+ if(showpoint || fixed)
+ {
+ str.append(".");
+ }
+ }
+ else if(my_exp + 1 < static_cast<int>(str.size()))
+ {
+ if(my_exp < 0)
+ {
+ str.insert(0U, static_cast<size_type>(-1 - my_exp), '0');
+ str.insert(0U, "0.");
+ }
+ else
+ {
+ // Insert the decimal point:
+ str.insert(static_cast<size_type>(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<int>(str.find('.') + 1U);
+ l = digits - (static_cast<int>(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 = boost::lexical_cast<string_type>(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<class float_type, class type_a> inline void eval_convert_to(type_a* pa, const float_type& cb) { *pa = static_cast<type_a>(cb); }
+ template<class float_type, class type_a> inline void eval_add (float_type& b, const type_a& a) { b += a; }
+ template<class float_type, class type_a> inline void eval_subtract (float_type& b, const type_a& a) { b -= a; }
+ template<class float_type, class type_a> inline void eval_multiply (float_type& b, const type_a& a) { b *= a; }
+ template<class float_type> inline void eval_multiply (float_type& b, const float_type& cb, const float_type& cb2) { b = (cb * cb2); }
+ template<class float_type, class type_a> inline void eval_divide (float_type& b, const type_a& a) { b /= a; }
+ template<class float_type> inline void eval_log10 (float_type& b, const float_type& cb) { b = std::log10(cb); }
+ template<class float_type> 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<class float_type>
+ 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<float_type>::min)())
+ : bool(-x < (std::numeric_limits<float_type>::min)()));
+ const bool isnan = (x != x);
+ const bool isinf = ((!isneg) ? bool(+x > (std::numeric_limits<float_type>::max)())
+ : bool(-x > (std::numeric_limits<float_type>::max)()));
+
+ int expon = 0;
+
+ if(digits <= 0) { digits = std::numeric_limits<float_type>::max_digits10; }
+
+ const int org_digits = static_cast<int>(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<float_type>::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<char>('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<int>(*result.rbegin() - '0') & 1) != 0)
+ {
+ round_string_up_at(result, static_cast<int>(result.size() - 1U), expon);
+ }
+ }
+ else if(cdigit >= 5)
+ {
+ round_string_up_at(result, static_cast<int>(result.size() - 1), expon);
+ }
+ }
+ }
+
+ while((result.size() > static_cast<std::string::size_type>(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 <class float_type>
+ bool convert_from_string(float_type& value, const char* p)
+ {
+ value = 0;
+
+ if((p == static_cast<const char*>(0U)) || (*p == static_cast<char>(0)))
+ {
+ return;
+ }
+
+ bool is_neg = false;
+ bool is_neg_expon = false;
+
+ BOOST_CONSTEXPR_OR_CONST int ten = 10;
+
+ int expon = 0;
+ int digits_seen = 0;
+
+ BOOST_CONSTEXPR_OR_CONST int max_digits = std::numeric_limits<float_type>::max_digits10 + 1;
+
+ if(*p == static_cast<char>('+'))
+ {
+ ++p;
+ }
+ else if(*p == static_cast<char>('-'))
+ {
+ 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<int>(*p - '0'));
+ ++p;
+ ++digits_seen;
+ }
+
+ if(*p == static_cast<char>('.'))
+ {
+ // 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<int>(*p - '0'));
+ ++p;
+ --expon;
+
+ if(++digits_seen > max_digits)
+ {
+ break;
+ }
+ }
+
+ while(std::isdigit(*p))
+ {
+ ++p;
+ }
+ }
+
+ // Parse the exponent.
+ if((*p == static_cast<char>('e')) || (*p == static_cast<char>('E')))
+ {
+ ++p;
+
+ if(*p == static_cast<char>('+'))
+ {
+ ++p;
+ }
+ else if(*p == static_cast<char>('-'))
+ {
+ 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<float_type>::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<char>(0));
+ }
+ } } } } // boost::math::cstdfloat::detail
+
+ namespace std
+ {
+ template<typename char_type, class traits_type>
+ inline std::basic_ostream<char_type, traits_type>& operator<<(std::basic_ostream<char_type, traits_type>& 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<char_type, traits_type> ostr;
+ ostr.flags(os.flags());
+ ostr.imbue(os.getloc());
+ ostr.precision(os.precision());
+
+ static_cast<void>(ostr << str);
+
+ return (os << ostr.str());
+ }
+
+ template<typename char_type, class traits_type>
+ inline std::basic_istream<char_type, traits_type>& operator>>(std::basic_istream<char_type, traits_type>& is, boost::math::cstdfloat::detail::float_internal128_t& x)
+ {
+ std::string str;
+
+ static_cast<void>(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<void>(is.putback(*it));
+ }
+
+ is.setstate(ios_base::failbit);
+
+ BOOST_THROW_EXCEPTION(std::runtime_error("Unable to interpret input string as a boost::float128_t"));
+ }
+
+ return is;
+ }
+ }
+
+ #endif // Use __GNUC__ or BOOST_INTEL libquadmath
+
+ #endif // Not BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT (i.e., the user would like to have libquadmath support)
+
+#endif // _BOOST_CSTDFLOAT_IOSTREAM_2014_02_15_HPP_
diff --git a/boost/math/cstdfloat/cstdfloat_limits.hpp b/boost/math/cstdfloat/cstdfloat_limits.hpp
new file mode 100644
index 0000000000..c04062639a
--- /dev/null
+++ b/boost/math/cstdfloat/cstdfloat_limits.hpp
@@ -0,0 +1,75 @@
+///////////////////////////////////////////////////////////////////////////////
+// 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_CSTDFLOAT_LIMITS_2014_01_09_HPP_
+ #define _BOOST_CSTDFLOAT_LIMITS_2014_01_09_HPP_
+
+ #include <boost/math/cstdfloat/cstdfloat_types.hpp>
+
+ #if defined(BOOST_CSTDFLOAT_HAS_INTERNAL_FLOAT128_T) && defined(BOOST_MATH_USE_FLOAT128) && !defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT)
+
+ #include <limits>
+
+ // 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(BOOST_INTEL)
+ #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) throw();
+
+ namespace std
+ {
+ template<>
+ class numeric_limits<boost::math::cstdfloat::detail::float_internal128_t>
+ {
+ public:
+ BOOST_STATIC_CONSTEXPR bool is_specialized = true;
+ static boost::math::cstdfloat::detail::float_internal128_t (min) () BOOST_NOEXCEPT { return BOOST_CSTDFLOAT_FLOAT128_MIN; }
+ static boost::math::cstdfloat::detail::float_internal128_t (max) () BOOST_NOEXCEPT { return BOOST_CSTDFLOAT_FLOAT128_MAX; }
+ static boost::math::cstdfloat::detail::float_internal128_t lowest() BOOST_NOEXCEPT { return -(max)(); }
+ BOOST_STATIC_CONSTEXPR int digits = 113;
+ BOOST_STATIC_CONSTEXPR int digits10 = 34;
+ BOOST_STATIC_CONSTEXPR int max_digits10 = 36;
+ BOOST_STATIC_CONSTEXPR bool is_signed = true;
+ BOOST_STATIC_CONSTEXPR bool is_integer = false;
+ BOOST_STATIC_CONSTEXPR bool is_exact = false;
+ BOOST_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); }
+ BOOST_STATIC_CONSTEXPR int min_exponent = -16381;
+ BOOST_STATIC_CONSTEXPR int min_exponent10 = static_cast<int>((min_exponent * 301L) / 1000L);
+ BOOST_STATIC_CONSTEXPR int max_exponent = +16384;
+ BOOST_STATIC_CONSTEXPR int max_exponent10 = static_cast<int>((max_exponent * 301L) / 1000L);
+ BOOST_STATIC_CONSTEXPR bool has_infinity = true;
+ BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = true;
+ BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false;
+ BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent;
+ BOOST_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_FLOAT128_C(0.0); }
+ BOOST_STATIC_CONSTEXPR bool is_iec559 = true;
+ BOOST_STATIC_CONSTEXPR bool is_bounded = false;
+ BOOST_STATIC_CONSTEXPR bool is_modulo = false;
+ BOOST_STATIC_CONSTEXPR bool traps = false;
+ BOOST_STATIC_CONSTEXPR bool tinyness_before = false;
+ BOOST_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_CSTDFLOAT_LIMITS_2014_01_09_HPP_
diff --git a/boost/math/cstdfloat/cstdfloat_types.hpp b/boost/math/cstdfloat/cstdfloat_types.hpp
new file mode 100644
index 0000000000..3ffcce21db
--- /dev/null
+++ b/boost/math/cstdfloat/cstdfloat_types.hpp
@@ -0,0 +1,431 @@
+///////////////////////////////////////////////////////////////////////////////
+// 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_CSTDFLOAT_TYPES_2014_01_09_HPP_
+ #define _BOOST_CSTDFLOAT_TYPES_2014_01_09_HPP_
+
+ #include <float.h>
+ #include <limits>
+ #include <boost/static_assert.hpp>
+ #include <boost/math/tools/config.hpp>
+
+ // This is the beginning of the preamble.
+
+ // In this preamble, the preprocessor is used to query certain
+ // preprocessor definitions from <float.h>. 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 <boost/cstdfloat.hpp>.
+ #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
+ // <boost/math/tools/config.hpp>.
+
+ #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(BOOST_INTEL)
+ typedef _Quad float_internal128_t;
+ #elif defined(__GNUC__)
+ typedef __float128 float_internal128_t;
+ #else
+ #error "Sorry, the compiler is neither GCC, nor Intel, I don't know how to configure <boost/cstdfloat.hpp>."
+ #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
+
+ #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 <boost/cstdfloat.hpp>.
+ #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 <boost/cstdfloat.hpp> 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 comformance 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;
+
+ BOOST_STATIC_ASSERT_MSG(std::numeric_limits<boost::float16_t>::is_iec559 == true, "boost::float16_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
+ BOOST_STATIC_ASSERT_MSG(std::numeric_limits<boost::float16_t>::radix == 2, "boost::float16_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
+ BOOST_STATIC_ASSERT_MSG(std::numeric_limits<boost::float16_t>::digits == 11, "boost::float16_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
+ BOOST_STATIC_ASSERT_MSG(std::numeric_limits<boost::float16_t>::max_exponent == 16, "boost::float16_t has been detected in <boost/cstdfloat>, 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;
+
+ BOOST_STATIC_ASSERT_MSG(std::numeric_limits<boost::float32_t>::is_iec559 == true, "boost::float32_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
+ BOOST_STATIC_ASSERT_MSG(std::numeric_limits<boost::float32_t>::radix == 2, "boost::float32_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
+ BOOST_STATIC_ASSERT_MSG(std::numeric_limits<boost::float32_t>::digits == 24, "boost::float32_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
+ BOOST_STATIC_ASSERT_MSG(std::numeric_limits<boost::float32_t>::max_exponent == 128, "boost::float32_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
+
+ #undef BOOST_CSTDFLOAT_FLOAT_32_MIN
+ #undef BOOST_CSTDFLOAT_FLOAT_32_MAX
+ #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;
+
+ BOOST_STATIC_ASSERT_MSG(std::numeric_limits<boost::float64_t>::is_iec559 == true, "boost::float64_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
+ BOOST_STATIC_ASSERT_MSG(std::numeric_limits<boost::float64_t>::radix == 2, "boost::float64_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
+ BOOST_STATIC_ASSERT_MSG(std::numeric_limits<boost::float64_t>::digits == 53, "boost::float64_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
+ BOOST_STATIC_ASSERT_MSG(std::numeric_limits<boost::float64_t>::max_exponent == 1024, "boost::float64_t has been detected in <boost/cstdfloat>, 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;
+
+ BOOST_STATIC_ASSERT_MSG(std::numeric_limits<boost::float80_t>::is_iec559 == true, "boost::float80_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
+ BOOST_STATIC_ASSERT_MSG(std::numeric_limits<boost::float80_t>::radix == 2, "boost::float80_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
+ BOOST_STATIC_ASSERT_MSG(std::numeric_limits<boost::float80_t>::digits == 64, "boost::float80_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
+ BOOST_STATIC_ASSERT_MSG(std::numeric_limits<boost::float80_t>::max_exponent == 16384, "boost::float80_t has been detected in <boost/cstdfloat>, 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<boost::float128_t>.
+ // Support for std::numeric_limits<boost::float128_t> is added in the detail
+ // file <boost/math/cstdfloat/cstdfloat_limits.hpp>.
+ #else
+ BOOST_STATIC_ASSERT_MSG(std::numeric_limits<boost::float128_t>::is_iec559 == true, "boost::float128_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
+ BOOST_STATIC_ASSERT_MSG(std::numeric_limits<boost::float128_t>::radix == 2, "boost::float128_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
+ BOOST_STATIC_ASSERT_MSG(std::numeric_limits<boost::float128_t>::digits == 113, "boost::float128_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
+ BOOST_STATIC_ASSERT_MSG(std::numeric_limits<boost::float128_t>::max_exponent == 16384, "boost::float128_t has been detected in <boost/cstdfloat>, 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 <boost/cstdfloat.hpp> 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_CSTDFLOAT_BASE_TYPES_2014_01_09_HPP_
diff --git a/boost/math/distributions.hpp b/boost/math/distributions.hpp
index 37cf027a80..cbcc0ace88 100644
--- a/boost/math/distributions.hpp
+++ b/boost/math/distributions.hpp
@@ -23,6 +23,7 @@
#include <boost/math/distributions/fisher_f.hpp>
#include <boost/math/distributions/gamma.hpp>
#include <boost/math/distributions/geometric.hpp>
+#include <boost/math/distributions/hyperexponential.hpp>
#include <boost/math/distributions/hypergeometric.hpp>
#include <boost/math/distributions/inverse_chi_squared.hpp>
#include <boost/math/distributions/inverse_gamma.hpp>
@@ -39,6 +40,7 @@
#include <boost/math/distributions/pareto.hpp>
#include <boost/math/distributions/poisson.hpp>
#include <boost/math/distributions/rayleigh.hpp>
+#include <boost/math/distributions/skew_normal.hpp>
#include <boost/math/distributions/students_t.hpp>
#include <boost/math/distributions/triangular.hpp>
#include <boost/math/distributions/uniform.hpp>
diff --git a/boost/math/distributions/beta.hpp b/boost/math/distributions/beta.hpp
index cfadd7bff5..5ecf902d99 100644
--- a/boost/math/distributions/beta.hpp
+++ b/boost/math/distributions/beta.hpp
@@ -156,7 +156,7 @@ namespace boost
typedef RealType value_type;
typedef Policy policy_type;
- beta_distribution(RealType alpha = 1, RealType beta = 1) : m_alpha(alpha), m_beta(beta)
+ beta_distribution(RealType l_alpha = 1, RealType l_beta = 1) : m_alpha(l_alpha), m_beta(l_beta)
{
RealType result;
beta_detail::check_dist(
@@ -189,11 +189,10 @@ namespace boost
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())
+ (
+ beta_detail::check_mean(function, mean, &result, Policy())
+ && beta_detail::check_variance(function, variance, &result, Policy())
+ )
)
{
return result;
@@ -208,11 +207,11 @@ namespace boost
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())
+ (
+ beta_detail::check_mean(function, mean, &result, Policy())
+ &&
+ beta_detail::check_variance(function, variance, &result, Policy())
+ )
)
{
return result;
@@ -231,14 +230,13 @@ namespace boost
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())
+ (
+ 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;
@@ -255,14 +253,13 @@ namespace boost
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())
+ (
+ 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;
diff --git a/boost/math/distributions/binomial.hpp b/boost/math/distributions/binomial.hpp
index 5ab3928949..a48c89c5b9 100644
--- a/boost/math/distributions/binomial.hpp
+++ b/boost/math/distributions/binomial.hpp
@@ -196,7 +196,7 @@ namespace boost
}
template <class RealType, class Policy>
- RealType quantile_imp(const binomial_distribution<RealType, Policy>& dist, const RealType& p, const RealType& q)
+ RealType quantile_imp(const binomial_distribution<RealType, Policy>& 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.
@@ -264,8 +264,8 @@ namespace boost
boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
return detail::inverse_discrete_quantile(
dist,
- p,
- q,
+ comp ? q : p,
+ comp,
guess,
factor,
RealType(1),
@@ -653,13 +653,13 @@ namespace boost
template <class RealType, class Policy>
inline RealType quantile(const binomial_distribution<RealType, Policy>& dist, const RealType& p)
{
- return binomial_detail::quantile_imp(dist, p, RealType(1-p));
+ return binomial_detail::quantile_imp(dist, p, RealType(1-p), false);
} // quantile
template <class RealType, class Policy>
RealType quantile(const complemented2_type<binomial_distribution<RealType, Policy>, RealType>& c)
{
- return binomial_detail::quantile_imp(c.dist, RealType(1-c.param), c.param);
+ return binomial_detail::quantile_imp(c.dist, RealType(1-c.param), c.param, true);
} // quantile
template <class RealType, class Policy>
diff --git a/boost/math/distributions/cauchy.hpp b/boost/math/distributions/cauchy.hpp
index 0c93febaa5..5a3a64f0f2 100644
--- a/boost/math/distributions/cauchy.hpp
+++ b/boost/math/distributions/cauchy.hpp
@@ -152,13 +152,13 @@ public:
typedef RealType value_type;
typedef Policy policy_type;
- cauchy_distribution(RealType location = 0, RealType scale = 1)
- : m_a(location), m_hg(scale)
+ 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, location, &result, Policy());
- detail::check_scale(function, scale, &result, Policy());
+ detail::check_location(function, l_location, &result, Policy());
+ detail::check_scale(function, l_scale, &result, Policy());
} // cauchy_distribution
RealType location()const
@@ -180,15 +180,30 @@ typedef cauchy_distribution<double> cauchy;
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const cauchy_distribution<RealType, Policy>&)
{ // Range of permissible values for random variable x.
+ if (std::numeric_limits<RealType>::has_infinity)
+ {
+ return std::pair<RealType, RealType>(-std::numeric_limits<RealType>::infinity(), std::numeric_limits<RealType>::infinity()); // - to + infinity.
+ }
+ else
+ { // Can only use max_value.
using boost::math::tools::max_value;
- return std::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>()); // - to + infinity.
+ return std::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>()); // - to + max.
+ }
}
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> support(const cauchy_distribution<RealType, Policy>& )
{ // 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<RealType, RealType>(-tools::max_value<RealType>(), tools::max_value<RealType>()); // - to + infinity.
+ if (std::numeric_limits<RealType>::has_infinity)
+ {
+ return std::pair<RealType, RealType>(-std::numeric_limits<RealType>::infinity(), std::numeric_limits<RealType>::infinity()); // - to + infinity.
+ }
+ else
+ { // Can only use max_value.
+ using boost::math::tools::max_value;
+ return std::pair<RealType, RealType>(-tools::max_value<RealType>(), max_value<RealType>()); // - to + max.
+ }
}
template <class RealType, class Policy>
diff --git a/boost/math/distributions/chi_squared.hpp b/boost/math/distributions/chi_squared.hpp
index 367a7154a3..071c7756f4 100644
--- a/boost/math/distributions/chi_squared.hpp
+++ b/boost/math/distributions/chi_squared.hpp
@@ -50,18 +50,34 @@ private:
//
// Data member:
//
- RealType m_df; // degrees of freedom are a real number.
+ RealType m_df; // degrees of freedom is a positive real number.
}; // class chi_squared_distribution
typedef chi_squared_distribution<double> chi_squared;
+#ifdef BOOST_MSVC
+#pragma warning(push)
+#pragma warning(disable:4127)
+#endif
+
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const chi_squared_distribution<RealType, Policy>& /*dist*/)
{ // Range of permissible values for random variable x.
- using boost::math::tools::max_value;
- return std::pair<RealType, RealType>(static_cast<RealType>(0), max_value<RealType>()); // 0 to + infinity.
+ if (std::numeric_limits<RealType>::has_infinity)
+ {
+ return std::pair<RealType, RealType>(static_cast<RealType>(0), std::numeric_limits<RealType>::infinity()); // 0 to + infinity.
+ }
+ else
+ {
+ using boost::math::tools::max_value;
+ return std::pair<RealType, RealType>(static_cast<RealType>(0), max_value<RealType>()); // 0 to + max.
+ }
}
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> support(const chi_squared_distribution<RealType, Policy>& /*dist*/)
{ // Range of supported values for random variable x.
@@ -138,11 +154,12 @@ inline RealType quantile(const chi_squared_distribution<RealType, Policy>& dist,
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;
+ 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
@@ -176,11 +193,11 @@ inline RealType quantile(const complemented2_type<chi_squared_distribution<RealT
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;
+ 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());
}
diff --git a/boost/math/distributions/detail/common_error_handling.hpp b/boost/math/distributions/detail/common_error_handling.hpp
index 46ded33cde..71a771e5a1 100644
--- a/boost/math/distributions/detail/common_error_handling.hpp
+++ b/boost/math/distributions/detail/common_error_handling.hpp
@@ -1,5 +1,5 @@
// Copyright John Maddock 2006, 2007.
-// Copyright Paul A. Bristow 2006, 2007.
+// Copyright Paul A. Bristow 2006, 2007, 2012.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
@@ -12,6 +12,7 @@
#include <boost/math/policies/error_handling.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
// using boost::math::isfinite;
+// using boost::math::isnan;
namespace boost{ namespace math{ namespace detail
{
@@ -31,7 +32,7 @@ inline bool check_probability(const char* function, RealType const& prob, RealTy
template <class RealType, class Policy>
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<RealType>(
@@ -43,6 +44,20 @@ inline bool check_df(const char* function, RealType const& df, RealType* result,
}
template <class RealType, class Policy>
+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<RealType>(
+ function,
+ "Degrees of freedom argument is %1%, but must be > 0 !", df, pol);
+ return false;
+ }
+ return true;
+} // check_df_gt0_to_inf
+
+
+template <class RealType, class Policy>
inline bool check_scale(
const char* function,
RealType scale,
@@ -83,6 +98,10 @@ inline bool check_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<RealType>(
@@ -91,9 +110,6 @@ inline bool check_x(
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
template <class RealType, class Policy>
diff --git a/boost/math/distributions/detail/generic_mode.hpp b/boost/math/distributions/detail/generic_mode.hpp
index 085dc691cd..3857c9f2ec 100644
--- a/boost/math/distributions/detail/generic_mode.hpp
+++ b/boost/math/distributions/detail/generic_mode.hpp
@@ -47,7 +47,7 @@ typename Dist::value_type generic_find_mode(const Dist& dist, typename Dist::val
// Oops we don't know how to handle this, or even in which
// direction we should move in, treat as an evaluation error:
//
- policies::raise_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());
}
diff --git a/boost/math/distributions/detail/generic_quantile.hpp b/boost/math/distributions/detail/generic_quantile.hpp
index b36f31c8b9..afde2cacb7 100644
--- a/boost/math/distributions/detail/generic_quantile.hpp
+++ b/boost/math/distributions/detail/generic_quantile.hpp
@@ -78,7 +78,7 @@ typename Dist::value_type generic_quantile(const Dist& dist, const typename Dist
value_type result = ir.first + (ir.second - ir.first) / 2;
if(max_iter >= policies::get_max_root_iterations<forwarding_policy>())
{
- policies::raise_evaluation_error<value_type>(function, "Unable to locate solution in a reasonable time:"
+ return policies::raise_evaluation_error<value_type>(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());
}
diff --git a/boost/math/distributions/detail/hypergeometric_pdf.hpp b/boost/math/distributions/detail/hypergeometric_pdf.hpp
index 895a2f1c94..1e6a5ca20d 100644
--- a/boost/math/distributions/detail/hypergeometric_pdf.hpp
+++ b/boost/math/distributions/detail/hypergeometric_pdf.hpp
@@ -61,15 +61,15 @@ T hypergeometric_pdf_lanczos_imp(T /*dummy*/, unsigned x, unsigned r, unsigned n
BOOST_MATH_INSTRUMENT_VARIABLE(typeid(Lanczos).name());
T bases[9] = {
- T(n) + Lanczos::g() + 0.5f,
- T(r) + Lanczos::g() + 0.5f,
- T(N - n) + Lanczos::g() + 0.5f,
- T(N - r) + Lanczos::g() + 0.5f,
- 1 / (T(N) + Lanczos::g() + 0.5f),
- 1 / (T(x) + Lanczos::g() + 0.5f),
- 1 / (T(n - x) + Lanczos::g() + 0.5f),
- 1 / (T(r - x) + Lanczos::g() + 0.5f),
- 1 / (T(N - n - r + x) + Lanczos::g() + 0.5f)
+ T(n) + static_cast<T>(Lanczos::g()) + 0.5f,
+ T(r) + static_cast<T>(Lanczos::g()) + 0.5f,
+ T(N - n) + static_cast<T>(Lanczos::g()) + 0.5f,
+ T(N - r) + static_cast<T>(Lanczos::g()) + 0.5f,
+ 1 / (T(N) + static_cast<T>(Lanczos::g()) + 0.5f),
+ 1 / (T(x) + static_cast<T>(Lanczos::g()) + 0.5f),
+ 1 / (T(n - x) + static_cast<T>(Lanczos::g()) + 0.5f),
+ 1 / (T(r - x) + static_cast<T>(Lanczos::g()) + 0.5f),
+ 1 / (T(N - n - r + x) + static_cast<T>(Lanczos::g()) + 0.5f)
};
T exponents[9] = {
n + T(0.5f),
@@ -392,7 +392,7 @@ template <class T, class Policy>
T hypergeometric_pdf_factorial_imp(unsigned x, unsigned r, unsigned n, unsigned N, const Policy&)
{
BOOST_MATH_STD_USING
- BOOST_ASSERT(N < boost::math::max_factorial<T>::value);
+ BOOST_ASSERT(N <= boost::math::max_factorial<T>::value);
T result = boost::math::unchecked_factorial<T>(n);
T num[3] = {
boost::math::unchecked_factorial<T>(r),
diff --git a/boost/math/distributions/detail/inv_discrete_quantile.hpp b/boost/math/distributions/detail/inv_discrete_quantile.hpp
index 9397e7c7c2..23e00b8e03 100644
--- a/boost/math/distributions/detail/inv_discrete_quantile.hpp
+++ b/boost/math/distributions/detail/inv_discrete_quantile.hpp
@@ -19,8 +19,8 @@ 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, value_type q)
- : dist(d), target(p < q ? p : q), comp(p < q ? false : true) {}
+ distribution_quantile_finder(const Dist d, value_type p, bool c)
+ : dist(d), target(p), comp(c) {}
value_type operator()(value_type const& x)
{
@@ -73,7 +73,7 @@ typename Dist::value_type
do_inverse_discrete_quantile(
const Dist& dist,
const typename Dist::value_type& p,
- const typename Dist::value_type& q,
+ bool comp,
typename Dist::value_type guess,
const typename Dist::value_type& multiplier,
typename Dist::value_type adder,
@@ -87,7 +87,7 @@ typename Dist::value_type
BOOST_MATH_STD_USING
- distribution_quantile_finder<Dist> f(dist, p, q);
+ distribution_quantile_finder<Dist> f(dist, p, comp);
//
// Max bounds of the distribution:
//
@@ -215,7 +215,7 @@ typename Dist::value_type
while(((boost::math::sign)(fb) == (boost::math::sign)(fa)) && (a != b))
{
if(count == 0)
- policies::raise_evaluation_error(function, "Unable to bracket root, last nearest value was %1%", b, policy_type());
+ return policies::raise_evaluation_error(function, "Unable to bracket root, last nearest value was %1%", b, policy_type());
a = b;
fa = fb;
b *= multiplier;
@@ -242,7 +242,7 @@ typename Dist::value_type
return 0;
}
if(count == 0)
- policies::raise_evaluation_error(function, "Unable to bracket root, last nearest value was %1%", a, policy_type());
+ return policies::raise_evaluation_error(function, "Unable to bracket root, last nearest value was %1%", a, policy_type());
b = a;
fb = fa;
a /= multiplier;
@@ -280,6 +280,80 @@ typename Dist::value_type
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 <class Dist>
+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 BOOST_MSVC
+#pragma warning(push)
+#pragma warning(disable:4127)
+#endif
+
+template <class Dist>
+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 BOOST_MSVC
+#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
@@ -290,20 +364,26 @@ template <class Dist>
inline typename Dist::value_type
inverse_discrete_quantile(
const Dist& dist,
- const typename Dist::value_type& p,
- const typename Dist::value_type& q,
+ 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<policies::real>&,
boost::uintmax_t& max_iter)
{
- if(p <= pdf(dist, 0))
+ 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,
- q,
+ c,
guess,
multiplier,
adder,
@@ -316,7 +396,7 @@ inline typename Dist::value_type
inverse_discrete_quantile(
const Dist& dist,
const typename Dist::value_type& p,
- const typename Dist::value_type& q,
+ bool c,
const typename Dist::value_type& guess,
const typename Dist::value_type& multiplier,
const typename Dist::value_type& adder,
@@ -325,32 +405,33 @@ inline typename Dist::value_type
{
typedef typename Dist::value_type value_type;
BOOST_MATH_STD_USING
- if(p <= pdf(dist, 0))
+ 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(p < 0.5f)
- return floor(do_inverse_discrete_quantile(
+ if(pp < 0.5f)
+ return round_to_floor(dist, do_inverse_discrete_quantile(
dist,
p,
- q,
+ c,
(guess < 1 ? value_type(1) : (value_type)floor(guess)),
multiplier,
adder,
tools::equal_floor(),
- max_iter));
+ max_iter), p, c);
// else:
- return ceil(do_inverse_discrete_quantile(
+ return round_to_ceil(dist, do_inverse_discrete_quantile(
dist,
p,
- q,
+ c,
(value_type)ceil(guess),
multiplier,
adder,
tools::equal_ceil(),
- max_iter));
+ max_iter), p, c);
}
template <class Dist>
@@ -358,7 +439,7 @@ inline typename Dist::value_type
inverse_discrete_quantile(
const Dist& dist,
const typename Dist::value_type& p,
- const typename Dist::value_type& q,
+ bool c,
const typename Dist::value_type& guess,
const typename Dist::value_type& multiplier,
const typename Dist::value_type& adder,
@@ -367,32 +448,33 @@ inline typename Dist::value_type
{
typedef typename Dist::value_type value_type;
BOOST_MATH_STD_USING
- if(p <= pdf(dist, 0))
+ 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(p < 0.5f)
- return ceil(do_inverse_discrete_quantile(
+ if(pp < 0.5f)
+ return round_to_ceil(dist, do_inverse_discrete_quantile(
dist,
p,
- q,
+ c,
ceil(guess),
multiplier,
adder,
tools::equal_ceil(),
- max_iter));
+ max_iter), p, c);
// else:
- return floor(do_inverse_discrete_quantile(
+ return round_to_floor(dist, do_inverse_discrete_quantile(
dist,
p,
- q,
+ c,
(guess < 1 ? value_type(1) : floor(guess)),
multiplier,
adder,
tools::equal_floor(),
- max_iter));
+ max_iter), p, c);
}
template <class Dist>
@@ -400,7 +482,7 @@ inline typename Dist::value_type
inverse_discrete_quantile(
const Dist& dist,
const typename Dist::value_type& p,
- const typename Dist::value_type& q,
+ bool c,
const typename Dist::value_type& guess,
const typename Dist::value_type& multiplier,
const typename Dist::value_type& adder,
@@ -409,17 +491,18 @@ inline typename Dist::value_type
{
typedef typename Dist::value_type value_type;
BOOST_MATH_STD_USING
- if(p <= pdf(dist, 0))
+ typename Dist::value_type pp = c ? 1 - p : p;
+ if(pp <= pdf(dist, 0))
return 0;
- return floor(do_inverse_discrete_quantile(
+ return round_to_floor(dist, do_inverse_discrete_quantile(
dist,
p,
- q,
+ c,
(guess < 1 ? value_type(1) : floor(guess)),
multiplier,
adder,
tools::equal_floor(),
- max_iter));
+ max_iter), p, c);
}
template <class Dist>
@@ -427,7 +510,7 @@ inline typename Dist::value_type
inverse_discrete_quantile(
const Dist& dist,
const typename Dist::value_type& p,
- const typename Dist::value_type& q,
+ bool c,
const typename Dist::value_type& guess,
const typename Dist::value_type& multiplier,
const typename Dist::value_type& adder,
@@ -435,17 +518,18 @@ inline typename Dist::value_type
boost::uintmax_t& max_iter)
{
BOOST_MATH_STD_USING
- if(p <= pdf(dist, 0))
+ typename Dist::value_type pp = c ? 1 - p : p;
+ if(pp <= pdf(dist, 0))
return 0;
- return ceil(do_inverse_discrete_quantile(
+ return round_to_ceil(dist, do_inverse_discrete_quantile(
dist,
p,
- q,
+ c,
ceil(guess),
multiplier,
adder,
tools::equal_ceil(),
- max_iter));
+ max_iter), p, c);
}
template <class Dist>
@@ -453,7 +537,7 @@ inline typename Dist::value_type
inverse_discrete_quantile(
const Dist& dist,
const typename Dist::value_type& p,
- const typename Dist::value_type& q,
+ bool c,
const typename Dist::value_type& guess,
const typename Dist::value_type& multiplier,
const typename Dist::value_type& adder,
@@ -462,26 +546,26 @@ inline typename Dist::value_type
{
typedef typename Dist::value_type value_type;
BOOST_MATH_STD_USING
- if(p <= pdf(dist, 0))
+ 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 floor(do_inverse_discrete_quantile(
+ return round_to_floor(dist, do_inverse_discrete_quantile(
dist,
p,
- q,
+ c,
(guess < 0.5f ? value_type(1.5f) : floor(guess + 0.5f) + 0.5f),
multiplier,
adder,
tools::equal_nearest_integer(),
- max_iter) + 0.5f);
+ max_iter) + 0.5f, p, c);
}
}}} // namespaces
#endif // BOOST_MATH_DISTRIBUTIONS_DETAIL_INV_DISCRETE_QUANTILE
-
diff --git a/boost/math/distributions/exponential.hpp b/boost/math/distributions/exponential.hpp
index 62b858c873..bfe7e6b4ac 100644
--- a/boost/math/distributions/exponential.hpp
+++ b/boost/math/distributions/exponential.hpp
@@ -16,6 +16,7 @@
#ifdef BOOST_MSVC
# pragma warning(push)
+# pragma warning(disable: 4127) // conditional expression is constant
# pragma warning(disable: 4702) // unreachable code (return after domain_error throw).
#endif
@@ -30,7 +31,7 @@ namespace detail{
template <class RealType, class Policy>
inline bool verify_lambda(const char* function, RealType l, RealType* presult, const Policy& pol)
{
- if(l <= 0)
+ if((l <= 0) || !(boost::math::isfinite)(l))
{
*presult = policies::raise_domain_error<RealType>(
function,
@@ -43,7 +44,7 @@ inline bool verify_lambda(const char* function, RealType l, RealType* presult, c
template <class RealType, class Policy>
inline bool verify_exp_x(const char* function, RealType x, RealType* presult, const Policy& pol)
{
- if(x < 0)
+ if((x < 0) || (boost::math::isnan)(x))
{
*presult = policies::raise_domain_error<RealType>(
function,
@@ -62,11 +63,11 @@ public:
typedef RealType value_type;
typedef Policy policy_type;
- exponential_distribution(RealType lambda = 1)
- : m_lambda(lambda)
+ exponential_distribution(RealType l_lambda = 1)
+ : m_lambda(l_lambda)
{
RealType err;
- detail::verify_lambda("boost::math::exponential_distribution<%1%>::exponential_distribution", lambda, &err, Policy());
+ detail::verify_lambda("boost::math::exponential_distribution<%1%>::exponential_distribution", l_lambda, &err, Policy());
} // exponential_distribution
RealType lambda()const { return m_lambda; }
@@ -80,8 +81,15 @@ typedef exponential_distribution<double> exponential;
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const exponential_distribution<RealType, Policy>& /*dist*/)
{ // Range of permissible values for random variable x.
+ if (std::numeric_limits<RealType>::has_infinity)
+ {
+ return std::pair<RealType, RealType>(static_cast<RealType>(0), std::numeric_limits<RealType>::infinity()); // 0 to + infinity.
+ }
+ else
+ {
using boost::math::tools::max_value;
- return std::pair<RealType, RealType>(static_cast<RealType>(0), max_value<RealType>());
+ return std::pair<RealType, RealType>(static_cast<RealType>(0), max_value<RealType>()); // 0 to + max
+ }
}
template <class RealType, class Policy>
@@ -107,6 +115,9 @@ inline RealType pdf(const exponential_distribution<RealType, Policy>& dist, cons
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
@@ -165,6 +176,9 @@ inline RealType cdf(const complemented2_type<exponential_distribution<RealType,
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<RealType>())
+ return 0;
result = exp(-c.param * lambda);
return result;
diff --git a/boost/math/distributions/extreme_value.hpp b/boost/math/distributions/extreme_value.hpp
index 3cf94d4b39..ef9fbe817d 100644
--- a/boost/math/distributions/extreme_value.hpp
+++ b/boost/math/distributions/extreme_value.hpp
@@ -37,11 +37,11 @@ namespace detail{
template <class RealType, class Policy>
inline bool verify_scale_b(const char* function, RealType b, RealType* presult, const Policy& pol)
{
- if(b <= 0)
+ if((b <= 0) || !(boost::math::isfinite)(b))
{
*presult = policies::raise_domain_error<RealType>(
function,
- "The scale parameter \"b\" must be > 0, but was: %1%.", b, pol);
+ "The scale parameter \"b\" must be finite and > 0, but was: %1%.", b, pol);
return false;
}
return true;
@@ -61,6 +61,7 @@ public:
{
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; }
@@ -76,7 +77,9 @@ template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const extreme_value_distribution<RealType, Policy>& /*dist*/)
{ // Range of permissible values for random variable x.
using boost::math::tools::max_value;
- return std::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>());
+ return std::pair<RealType, RealType>(
+ std::numeric_limits<RealType>::has_infinity ? -std::numeric_limits<RealType>::infinity() : -max_value<RealType>(),
+ std::numeric_limits<RealType>::has_infinity ? std::numeric_limits<RealType>::infinity() : max_value<RealType>());
}
template <class RealType, class Policy>
@@ -92,10 +95,18 @@ inline RealType pdf(const extreme_value_distribution<RealType, Policy>& dist, co
{
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("boost::math::pdf(const extreme_value_distribution<%1%>&, %1%)", b, &result, Policy()))
+ if((boost::math::isinf)(x))
+ return 0.0f;
+ 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, x, &result, Policy()))
return result;
result = exp((a-x)/b) * exp(-exp((a-x)/b)) / b;
return result;
@@ -106,10 +117,20 @@ inline RealType cdf(const extreme_value_distribution<RealType, Policy>& dist, co
{
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("boost::math::cdf(const extreme_value_distribution<%1%>&, %1%)", b, &result, Policy()))
+ 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));
@@ -129,6 +150,8 @@ RealType quantile(const extreme_value_distribution<RealType, Policy>& dist, cons
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;
@@ -147,10 +170,18 @@ inline RealType cdf(const complemented2_type<extreme_value_distribution<RealType
{
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("boost::math::cdf(const extreme_value_distribution<%1%>&, %1%)", b, &result, Policy()))
+ 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());
@@ -171,6 +202,8 @@ RealType quantile(const complemented2_type<extreme_value_distribution<RealType,
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;
@@ -192,6 +225,8 @@ inline RealType mean(const extreme_value_distribution<RealType, Policy>& dist)
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_scale("boost::math::mean(const extreme_value_distribution<%1%>&)", a, &result, Policy()))
+ return result;
return a + constants::euler<RealType>() * b;
}
@@ -204,6 +239,8 @@ inline RealType standard_deviation(const extreme_value_distribution<RealType, Po
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_scale("boost::math::standard_deviation(const extreme_value_distribution<%1%>&)", dist.location(), &result, Policy()))
+ return result;
return constants::pi<RealType>() * b / sqrt(static_cast<RealType>(6));
}
diff --git a/boost/math/distributions/fisher_f.hpp b/boost/math/distributions/fisher_f.hpp
index 07bcc81a6a..9e259bcc96 100644
--- a/boost/math/distributions/fisher_f.hpp
+++ b/boost/math/distributions/fisher_f.hpp
@@ -169,12 +169,12 @@ inline RealType quantile(const fisher_f_distribution<RealType, Policy>& dist, co
RealType df2 = dist.degrees_of_freedom2();
// Error check:
RealType error_result = 0;
- if(false == detail::check_df(
+ 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()))
+ function, p, &error_result, Policy())))
return error_result;
// With optimizations turned on, gcc wrongly warns about y being used
@@ -231,12 +231,12 @@ inline RealType quantile(const complemented2_type<fisher_f_distribution<RealType
RealType p = c.param;
// Error check:
RealType error_result = 0;
- if(false == detail::check_df(
+ 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()))
+ function, p, &error_result, Policy())))
return error_result;
RealType x, y;
diff --git a/boost/math/distributions/fwd.hpp b/boost/math/distributions/fwd.hpp
index 35ccc8cbaa..d2b50ad010 100644
--- a/boost/math/distributions/fwd.hpp
+++ b/boost/math/distributions/fwd.hpp
@@ -1,6 +1,6 @@
// fwd.hpp Forward declarations of Boost.Math distributions.
-// Copyright Paul A. Bristow 2007, 2010.
+// Copyright Paul A. Bristow 2007, 2010, 2012.
// Copyright John Maddock 2007.
// Use, modification and distribution are subject to the
@@ -11,6 +11,8 @@
#ifndef BOOST_MATH_DISTRIBUTIONS_FWD_HPP
#define BOOST_MATH_DISTRIBUTIONS_FWD_HPP
+// 31 distributions at Boost 1.52
+
namespace boost{ namespace math{
template <class RealType, class Policy>
@@ -44,6 +46,9 @@ template <class RealType, class Policy>
class geometric_distribution;
template <class RealType, class Policy>
+class hyperexponential_distribution;
+
+template <class RealType, class Policy>
class hypergeometric_distribution;
template <class RealType, class Policy>
@@ -56,9 +61,6 @@ template <class RealType, class Policy>
class inverse_gaussian_distribution;
template <class RealType, class Policy>
-class inverse_uniform_distribution;
-
-template <class RealType, class Policy>
class laplace_distribution;
template <class RealType, class Policy>
@@ -71,10 +73,10 @@ template <class RealType, class Policy>
class negative_binomial_distribution;
template <class RealType, class Policy>
-class non_central_chi_squared_distribution;
+class non_central_beta_distribution;
template <class RealType, class Policy>
-class non_central_beta_distribution;
+class non_central_chi_squared_distribution;
template <class RealType, class Policy>
class non_central_f_distribution;
@@ -95,6 +97,9 @@ template <class RealType, class Policy>
class rayleigh_distribution;
template <class RealType, class Policy>
+class skew_normal_distribution;
+
+template <class RealType, class Policy>
class students_t_distribution;
template <class RealType, class Policy>
@@ -118,27 +123,27 @@ class weibull_distribution;
typedef boost::math::extreme_value_distribution<Type, Policy> extreme_value;\
typedef boost::math::fisher_f_distribution<Type, Policy> fisher_f;\
typedef boost::math::gamma_distribution<Type, Policy> gamma;\
+ typedef boost::math::geometric_distribution<Type, Policy> geometric;\
+ typedef boost::math::hypergeometric_distribution<Type, Policy> hypergeometric;\
+ typedef boost::math::inverse_chi_squared_distribution<Type, Policy> inverse_chi_squared;\
+ typedef boost::math::inverse_gaussian_distribution<Type, Policy> inverse_gaussian;\
+ typedef boost::math::inverse_gamma_distribution<Type, Policy> inverse_gamma;\
typedef boost::math::laplace_distribution<Type, Policy> laplace;\
typedef boost::math::logistic_distribution<Type, Policy> logistic;\
typedef boost::math::lognormal_distribution<Type, Policy> lognormal;\
typedef boost::math::negative_binomial_distribution<Type, Policy> negative_binomial;\
+ typedef boost::math::non_central_beta_distribution<Type, Policy> non_central_beta;\
+ typedef boost::math::non_central_chi_squared_distribution<Type, Policy> non_central_chi_squared;\
+ typedef boost::math::non_central_f_distribution<Type, Policy> non_central_f;\
+ typedef boost::math::non_central_t_distribution<Type, Policy> non_central_t;\
typedef boost::math::normal_distribution<Type, Policy> normal;\
typedef boost::math::pareto_distribution<Type, Policy> pareto;\
typedef boost::math::poisson_distribution<Type, Policy> poisson;\
typedef boost::math::rayleigh_distribution<Type, Policy> rayleigh;\
+ typedef boost::math::skew_normal_distribution<Type, Policy> skew_normal;\
typedef boost::math::students_t_distribution<Type, Policy> students_t;\
typedef boost::math::triangular_distribution<Type, Policy> triangular;\
typedef boost::math::uniform_distribution<Type, Policy> uniform;\
- typedef boost::math::weibull_distribution<Type, Policy> weibull;\
- typedef boost::math::non_central_chi_squared_distribution<Type, Policy> non_central_chi_squared;\
- typedef boost::math::non_central_beta_distribution<Type, Policy> non_central_beta;\
- typedef boost::math::non_central_f_distribution<Type, Policy> non_central_f;\
- typedef boost::math::non_central_t_distribution<Type, Policy> non_central_t;\
- typedef boost::math::hypergeometric_distribution<Type, Policy> hypergeometric;\
- typedef boost::math::inverse_uniform_distribution<Type, Policy> inverse_uniform;\
- typedef boost::math::geometric_distribution<Type, Policy> geometric;\
- typedef boost::math::inverse_chi_squared_distribution<Type, Policy> inverse_chi_squared;\
- typedef boost::math::inverse_gamma_distribution<Type, Policy> inverse_gamma;\
- typedef boost::math::inverse_gaussian_distribution<Type, Policy> inverse_gaussian;\
+ typedef boost::math::weibull_distribution<Type, Policy> weibull;
#endif // BOOST_MATH_DISTRIBUTIONS_FWD_HPP
diff --git a/boost/math/distributions/gamma.hpp b/boost/math/distributions/gamma.hpp
index c15973bac0..9a9e2a4f52 100644
--- a/boost/math/distributions/gamma.hpp
+++ b/boost/math/distributions/gamma.hpp
@@ -73,11 +73,11 @@ public:
typedef RealType value_type;
typedef Policy policy_type;
- gamma_distribution(RealType shape, RealType scale = 1)
- : m_shape(shape), m_scale(scale)
+ gamma_distribution(RealType l_shape, RealType l_scale = 1)
+ : m_shape(l_shape), m_scale(l_scale)
{
RealType result;
- detail::check_gamma("boost::math::gamma_distribution<%1%>::gamma_distribution", scale, shape, &result, Policy());
+ detail::check_gamma("boost::math::gamma_distribution<%1%>::gamma_distribution", l_scale, l_shape, &result, Policy());
}
RealType shape()const
diff --git a/boost/math/distributions/geometric.hpp b/boost/math/distributions/geometric.hpp
index 51e55e69fa..88947d6c57 100644
--- a/boost/math/distributions/geometric.hpp
+++ b/boost/math/distributions/geometric.hpp
@@ -372,8 +372,8 @@ namespace boost
//RealType q = 1 - p; // Bad for small p
//RealType probability = 1 - std::pow(q, k+1);
- RealType z = boost::math::log1p(-p) * (k+1);
- RealType probability = -boost::math::expm1(z);
+ RealType z = boost::math::log1p(-p, Policy()) * (k + 1);
+ RealType probability = -boost::math::expm1(z, Policy());
return probability;
} // cdf Cumulative Distribution Function geometric.
@@ -398,7 +398,7 @@ namespace boost
{
return result;
}
- RealType z = boost::math::log1p(-p) * (k+1);
+ RealType z = boost::math::log1p(-p, Policy()) * (k+1);
RealType probability = exp(z);
return probability;
} // cdf Complemented Cumulative Distribution Function geometric.
@@ -448,7 +448,7 @@ namespace boost
}
// log(1-x) /log(1-success_fraction) -1; but use log1p in case success_fraction is small
- result = boost::math::log1p(-x) / boost::math::log1p(-success_fraction) -1;
+ result = boost::math::log1p(-x, Policy()) / boost::math::log1p(-success_fraction, Policy()) - 1;
// Subtract a few epsilons here too?
// to make sure it doesn't slip over, so ceil would be one too many.
return result;
@@ -496,7 +496,7 @@ namespace boost
// unless #define BOOST_MATH_THROW_ON_OVERFLOW_ERROR
}
// log(x) /log(1-success_fraction) -1; but use log1p in case success_fraction is small
- result = log(x) / boost::math::log1p(-success_fraction) -1;
+ result = log(x) / boost::math::log1p(-success_fraction, Policy()) - 1;
return result;
} // quantile complement
diff --git a/boost/math/distributions/hyperexponential.hpp b/boost/math/distributions/hyperexponential.hpp
new file mode 100644
index 0000000000..4ed281c662
--- /dev/null
+++ b/boost/math/distributions/hyperexponential.hpp
@@ -0,0 +1,634 @@
+// Copyright 2014 Marco Guazzone (marco.guazzone@gmail.com)
+//
+// 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 module implements the Hyper-Exponential distribution.
+//
+// References:
+// - "Queueing Theory in Manufacturing Systems Analysis and Design" by H.T. Papadopolous, C. Heavey and J. Browne (Chapman & Hall/CRC, 1993)
+// - http://reference.wolfram.com/language/ref/HyperexponentialDistribution.html
+// - http://en.wikipedia.org/wiki/Hyperexponential_distribution
+//
+
+#ifndef BOOST_MATH_DISTRIBUTIONS_HYPEREXPONENTIAL_HPP
+#define BOOST_MATH_DISTRIBUTIONS_HYPEREXPONENTIAL_HPP
+
+
+#include <boost/config.hpp>
+#include <boost/math/distributions/complement.hpp>
+#include <boost/math/distributions/detail/common_error_handling.hpp>
+#include <boost/math/distributions/exponential.hpp>
+#include <boost/math/policies/policy.hpp>
+#include <boost/math/special_functions/fpclassify.hpp>
+#include <boost/math/tools/precision.hpp>
+#include <boost/math/tools/roots.hpp>
+#include <boost/range/begin.hpp>
+#include <boost/range/end.hpp>
+#include <boost/range/size.hpp>
+#include <boost/type_traits/has_pre_increment.hpp>
+#include <cstddef>
+#include <iterator>
+#include <limits>
+#include <numeric>
+#include <utility>
+#include <vector>
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+# include <initializer_list>
+#endif
+
+#ifdef _MSC_VER
+# pragma warning (push)
+# pragma warning(disable:4127) // conditional expression is constant
+# pragma warning(disable:4389) // '==' : signed/unsigned mismatch in test_tools
+#endif // _MSC_VER
+
+namespace boost { namespace math {
+
+namespace detail {
+
+template <typename Dist>
+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);
+
+} // Namespace detail
+
+
+template <typename RealT, typename PolicyT>
+class hyperexponential_distribution;
+
+
+namespace /*<unnamed>*/ { namespace hyperexp_detail {
+
+template <typename T>
+void normalize(std::vector<T>& v)
+{
+ if(!v.size())
+ return; // Our error handlers will get this later
+ const T sum = std::accumulate(v.begin(), v.end(), static_cast<T>(0));
+ T final_sum = 0;
+ const typename std::vector<T>::iterator end = --v.end();
+ for (typename std::vector<T>::iterator it = v.begin();
+ it != end;
+ ++it)
+ {
+ *it /= sum;
+ final_sum += *it;
+ }
+ *end = 1 - final_sum; // avoids round off errors, ensures the probs really do sum to 1.
+}
+
+template <typename RealT, typename PolicyT>
+bool check_probabilities(char const* function, std::vector<RealT> const& probabilities, RealT* presult, PolicyT const& pol)
+{
+ BOOST_MATH_STD_USING
+ const std::size_t n = probabilities.size();
+ RealT sum = 0;
+ for (std::size_t i = 0; i < n; ++i)
+ {
+ if (probabilities[i] < 0
+ || probabilities[i] > 1
+ || !(boost::math::isfinite)(probabilities[i]))
+ {
+ *presult = policies::raise_domain_error<RealT>(function,
+ "The elements of parameter \"probabilities\" must be >= 0 and <= 1, but at least one of them was: %1%.",
+ probabilities[i],
+ pol);
+ return false;
+ }
+ sum += probabilities[i];
+ }
+
+ //
+ // We try to keep phase probabilities correctly normalized in the distribution constructors,
+ // however in practice we have to allow for a very slight divergence from a sum of exactly 1:
+ //
+ if (fabs(sum - 1) > tools::epsilon<RealT>() * 2)
+ {
+ *presult = policies::raise_domain_error<RealT>(function,
+ "The elements of parameter \"probabilities\" must sum to 1, but their sum is: %1%.",
+ sum,
+ pol);
+ return false;
+ }
+
+ return true;
+}
+
+template <typename RealT, typename PolicyT>
+bool check_rates(char const* function, std::vector<RealT> const& rates, RealT* presult, PolicyT const& pol)
+{
+ const std::size_t n = rates.size();
+ for (std::size_t i = 0; i < n; ++i)
+ {
+ if (rates[i] <= 0
+ || !(boost::math::isfinite)(rates[i]))
+ {
+ *presult = policies::raise_domain_error<RealT>(function,
+ "The elements of parameter \"rates\" must be > 0, but at least one of them is: %1%.",
+ rates[i],
+ pol);
+ return false;
+ }
+ }
+ return true;
+}
+
+template <typename RealT, typename PolicyT>
+bool check_dist(char const* function, std::vector<RealT> const& probabilities, std::vector<RealT> const& rates, RealT* presult, PolicyT const& pol)
+{
+ BOOST_MATH_STD_USING
+ if (probabilities.size() != rates.size())
+ {
+ *presult = policies::raise_domain_error<RealT>(function,
+ "The parameters \"probabilities\" and \"rates\" must have the same length, but their size differ by: %1%.",
+ fabs(static_cast<RealT>(probabilities.size())-static_cast<RealT>(rates.size())),
+ pol);
+ return false;
+ }
+
+ return check_probabilities(function, probabilities, presult, pol)
+ && check_rates(function, rates, presult, pol);
+}
+
+template <typename RealT, typename PolicyT>
+bool check_x(char const* function, RealT x, RealT* presult, PolicyT const& pol)
+{
+ if (x < 0 || (boost::math::isnan)(x))
+ {
+ *presult = policies::raise_domain_error<RealT>(function, "The random variable must be >= 0, but is: %1%.", x, pol);
+ return false;
+ }
+ return true;
+}
+
+template <typename RealT, typename PolicyT>
+bool check_probability(char const* function, RealT p, RealT* presult, PolicyT const& pol)
+{
+ if (p < 0 || p > 1 || (boost::math::isnan)(p))
+ {
+ *presult = policies::raise_domain_error<RealT>(function, "The probability be >= 0 and <= 1, but is: %1%.", p, pol);
+ return false;
+ }
+ return true;
+}
+
+template <typename RealT, typename PolicyT>
+RealT quantile_impl(hyperexponential_distribution<RealT, PolicyT> const& dist, RealT const& p, bool comp)
+{
+ // Don't have a closed form so try to numerically solve the inverse CDF...
+
+ typedef typename policies::evaluation<RealT, PolicyT>::type value_type;
+ typedef typename policies::normalise<PolicyT,
+ policies::promote_float<false>,
+ policies::promote_double<false>,
+ policies::discrete_quantile<>,
+ policies::assert_undefined<> >::type forwarding_policy;
+
+ static const char* function = comp ? "boost::math::quantile(const boost::math::complemented2_type<boost::math::hyperexponential_distribution<%1%>, %1%>&)"
+ : "boost::math::quantile(const boost::math::hyperexponential_distribution<%1%>&, %1%)";
+
+ RealT result = 0;
+
+ if (!check_probability(function, p, &result, PolicyT()))
+ {
+ return result;
+ }
+
+ const std::size_t n = dist.num_phases();
+ const std::vector<RealT> probs = dist.probabilities();
+ const std::vector<RealT> rates = dist.rates();
+
+ // A possible (but inaccurate) approximation is given below, where the
+ // quantile is given by the weighted sum of exponential quantiles:
+ RealT guess = 0;
+ if (comp)
+ {
+ for (std::size_t i = 0; i < n; ++i)
+ {
+ const exponential_distribution<RealT,PolicyT> exp(rates[i]);
+
+ guess += probs[i]*quantile(complement(exp, p));
+ }
+ }
+ else
+ {
+ for (std::size_t i = 0; i < n; ++i)
+ {
+ const exponential_distribution<RealT,PolicyT> exp(rates[i]);
+
+ guess += probs[i]*quantile(exp, p);
+ }
+ }
+
+ // Fast return in case the Hyper-Exponential is essentially an Exponential
+ if (n == 1)
+ {
+ return guess;
+ }
+
+ value_type q;
+ q = detail::generic_quantile(hyperexponential_distribution<RealT,forwarding_policy>(probs, rates),
+ p,
+ guess,
+ comp,
+ function);
+
+ result = policies::checked_narrowing_cast<RealT,forwarding_policy>(q, function);
+
+ return result;
+}
+
+}} // Namespace <unnamed>::hyperexp_detail
+
+
+template <typename RealT = double, typename PolicyT = policies::policy<> >
+class hyperexponential_distribution
+{
+ public: typedef RealT value_type;
+ public: typedef PolicyT policy_type;
+
+
+ public: hyperexponential_distribution()
+ : probs_(1, 1),
+ rates_(1, 1)
+ {
+ RealT err;
+ hyperexp_detail::check_dist("boost::math::hyperexponential_distribution<%1%>::hyperexponential_distribution",
+ probs_,
+ rates_,
+ &err,
+ PolicyT());
+ }
+
+ // Four arg constructor: no ambiguity here, the arguments must be two pairs of iterators:
+ public: template <typename ProbIterT, typename RateIterT>
+ hyperexponential_distribution(ProbIterT prob_first, ProbIterT prob_last,
+ RateIterT rate_first, RateIterT rate_last)
+ : probs_(prob_first, prob_last),
+ rates_(rate_first, rate_last)
+ {
+ hyperexp_detail::normalize(probs_);
+ RealT err;
+ hyperexp_detail::check_dist("boost::math::hyperexponential_distribution<%1%>::hyperexponential_distribution",
+ probs_,
+ rates_,
+ &err,
+ PolicyT());
+ }
+
+ // Two arg constructor from 2 ranges, we SFINAE this out of existance if
+ // either argument type is incrementable as in that case the type is
+ // probably an iterator:
+ public: template <typename ProbRangeT, typename RateRangeT>
+ hyperexponential_distribution(ProbRangeT const& prob_range,
+ RateRangeT const& rate_range,
+ typename boost::disable_if_c<boost::has_pre_increment<ProbRangeT>::value || boost::has_pre_increment<RateRangeT>::value>::type* = 0)
+ : probs_(boost::begin(prob_range), boost::end(prob_range)),
+ rates_(boost::begin(rate_range), boost::end(rate_range))
+ {
+ hyperexp_detail::normalize(probs_);
+
+ RealT err;
+ hyperexp_detail::check_dist("boost::math::hyperexponential_distribution<%1%>::hyperexponential_distribution",
+ probs_,
+ rates_,
+ &err,
+ PolicyT());
+ }
+
+ // Two arg constructor for a pair of iterators: we SFINAE this out of
+ // existance if neither argument types are incrementable.
+ // Note that we allow different argument types here to allow for
+ // construction from an array plus a pointer into that array.
+ public: template <typename RateIterT, typename RateIterT2>
+ hyperexponential_distribution(RateIterT const& rate_first,
+ RateIterT2 const& rate_last,
+ typename boost::enable_if_c<boost::has_pre_increment<RateIterT>::value || boost::has_pre_increment<RateIterT2>::value>::type* = 0)
+ : probs_(std::distance(rate_first, rate_last), 1), // will be normalized below
+ rates_(rate_first, rate_last)
+ {
+ hyperexp_detail::normalize(probs_);
+
+ RealT err;
+ hyperexp_detail::check_dist("boost::math::hyperexponential_distribution<%1%>::hyperexponential_distribution",
+ probs_,
+ rates_,
+ &err,
+ PolicyT());
+ }
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ // Initializer list constructor: allows for construction from array literals:
+public: hyperexponential_distribution(std::initializer_list<RealT> l1, std::initializer_list<RealT> l2)
+ : probs_(l1.begin(), l1.end()),
+ rates_(l2.begin(), l2.end())
+ {
+ hyperexp_detail::normalize(probs_);
+
+ RealT err;
+ hyperexp_detail::check_dist("boost::math::hyperexponential_distribution<%1%>::hyperexponential_distribution",
+ probs_,
+ rates_,
+ &err,
+ PolicyT());
+ }
+
+public: hyperexponential_distribution(std::initializer_list<RealT> l1)
+ : probs_(l1.size(), 1),
+ rates_(l1.begin(), l1.end())
+ {
+ hyperexp_detail::normalize(probs_);
+
+ RealT err;
+ hyperexp_detail::check_dist("boost::math::hyperexponential_distribution<%1%>::hyperexponential_distribution",
+ probs_,
+ rates_,
+ &err,
+ PolicyT());
+ }
+#endif // !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+
+ // Single argument constructor: argument must be a range.
+ public: template <typename RateRangeT>
+ hyperexponential_distribution(RateRangeT const& rate_range)
+ : probs_(boost::size(rate_range), 1), // will be normalized below
+ rates_(boost::begin(rate_range), boost::end(rate_range))
+ {
+ hyperexp_detail::normalize(probs_);
+
+ RealT err;
+ hyperexp_detail::check_dist("boost::math::hyperexponential_distribution<%1%>::hyperexponential_distribution",
+ probs_,
+ rates_,
+ &err,
+ PolicyT());
+ }
+
+ public: std::vector<RealT> probabilities() const
+ {
+ return probs_;
+ }
+
+ public: std::vector<RealT> rates() const
+ {
+ return rates_;
+ }
+
+ public: std::size_t num_phases() const
+ {
+ return rates_.size();
+ }
+
+
+ private: std::vector<RealT> probs_;
+ private: std::vector<RealT> rates_;
+}; // class hyperexponential_distribution
+
+
+// Convenient type synonym for double.
+typedef hyperexponential_distribution<double> hyperexponential;
+
+
+// Range of permissible values for random variable x
+template <typename RealT, typename PolicyT>
+std::pair<RealT,RealT> range(hyperexponential_distribution<RealT,PolicyT> const&)
+{
+ if (std::numeric_limits<RealT>::has_infinity)
+ {
+ return std::make_pair(static_cast<RealT>(0), std::numeric_limits<RealT>::infinity()); // 0 to +inf.
+ }
+
+ return std::make_pair(static_cast<RealT>(0), tools::max_value<RealT>()); // 0 to +<max value>
+}
+
+// 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.
+template <typename RealT, typename PolicyT>
+std::pair<RealT,RealT> support(hyperexponential_distribution<RealT,PolicyT> const&)
+{
+ return std::make_pair(tools::min_value<RealT>(), tools::max_value<RealT>()); // <min value> to +<max value>.
+}
+
+template <typename RealT, typename PolicyT>
+RealT pdf(hyperexponential_distribution<RealT, PolicyT> const& dist, RealT const& x)
+{
+ BOOST_MATH_STD_USING
+ RealT result = 0;
+
+ if (!hyperexp_detail::check_x("boost::math::pdf(const boost::math::hyperexponential_distribution<%1%>&, %1%)", x, &result, PolicyT()))
+ {
+ return result;
+ }
+
+ const std::size_t n = dist.num_phases();
+ const std::vector<RealT> probs = dist.probabilities();
+ const std::vector<RealT> rates = dist.rates();
+
+ for (std::size_t i = 0; i < n; ++i)
+ {
+ const exponential_distribution<RealT,PolicyT> exp(rates[i]);
+
+ result += probs[i]*pdf(exp, x);
+ //result += probs[i]*rates[i]*exp(-rates[i]*x);
+ }
+
+ return result;
+}
+
+template <typename RealT, typename PolicyT>
+RealT cdf(hyperexponential_distribution<RealT, PolicyT> const& dist, RealT const& x)
+{
+ RealT result = 0;
+
+ if (!hyperexp_detail::check_x("boost::math::cdf(const boost::math::hyperexponential_distribution<%1%>&, %1%)", x, &result, PolicyT()))
+ {
+ return result;
+ }
+
+ const std::size_t n = dist.num_phases();
+ const std::vector<RealT> probs = dist.probabilities();
+ const std::vector<RealT> rates = dist.rates();
+
+ for (std::size_t i = 0; i < n; ++i)
+ {
+ const exponential_distribution<RealT,PolicyT> exp(rates[i]);
+
+ result += probs[i]*cdf(exp, x);
+ }
+
+ return result;
+}
+
+template <typename RealT, typename PolicyT>
+RealT quantile(hyperexponential_distribution<RealT, PolicyT> const& dist, RealT const& p)
+{
+ return hyperexp_detail::quantile_impl(dist, p , false);
+}
+
+template <typename RealT, typename PolicyT>
+RealT cdf(complemented2_type<hyperexponential_distribution<RealT,PolicyT>, RealT> const& c)
+{
+ RealT const& x = c.param;
+ hyperexponential_distribution<RealT,PolicyT> const& dist = c.dist;
+
+ RealT result = 0;
+
+ if (!hyperexp_detail::check_x("boost::math::cdf(boost::math::complemented2_type<const boost::math::hyperexponential_distribution<%1%>&, %1%>)", x, &result, PolicyT()))
+ {
+ return result;
+ }
+
+ const std::size_t n = dist.num_phases();
+ const std::vector<RealT> probs = dist.probabilities();
+ const std::vector<RealT> rates = dist.rates();
+
+ for (std::size_t i = 0; i < n; ++i)
+ {
+ const exponential_distribution<RealT,PolicyT> exp(rates[i]);
+
+ result += probs[i]*cdf(complement(exp, x));
+ }
+
+ return result;
+}
+
+
+template <typename RealT, typename PolicyT>
+RealT quantile(complemented2_type<hyperexponential_distribution<RealT, PolicyT>, RealT> const& c)
+{
+ RealT const& p = c.param;
+ hyperexponential_distribution<RealT,PolicyT> const& dist = c.dist;
+
+ return hyperexp_detail::quantile_impl(dist, p , true);
+}
+
+template <typename RealT, typename PolicyT>
+RealT mean(hyperexponential_distribution<RealT, PolicyT> const& dist)
+{
+ RealT result = 0;
+
+ const std::size_t n = dist.num_phases();
+ const std::vector<RealT> probs = dist.probabilities();
+ const std::vector<RealT> rates = dist.rates();
+
+ for (std::size_t i = 0; i < n; ++i)
+ {
+ const exponential_distribution<RealT,PolicyT> exp(rates[i]);
+
+ result += probs[i]*mean(exp);
+ }
+
+ return result;
+}
+
+template <typename RealT, typename PolicyT>
+RealT variance(hyperexponential_distribution<RealT, PolicyT> const& dist)
+{
+ RealT result = 0;
+
+ const std::size_t n = dist.num_phases();
+ const std::vector<RealT> probs = dist.probabilities();
+ const std::vector<RealT> rates = dist.rates();
+
+ for (std::size_t i = 0; i < n; ++i)
+ {
+ result += probs[i]/(rates[i]*rates[i]);
+ }
+
+ const RealT mean = boost::math::mean(dist);
+
+ result = 2*result-mean*mean;
+
+ return result;
+}
+
+template <typename RealT, typename PolicyT>
+RealT skewness(hyperexponential_distribution<RealT,PolicyT> const& dist)
+{
+ BOOST_MATH_STD_USING
+ const std::size_t n = dist.num_phases();
+ const std::vector<RealT> probs = dist.probabilities();
+ const std::vector<RealT> rates = dist.rates();
+
+ RealT s1 = 0; // \sum_{i=1}^n \frac{p_i}{\lambda_i}
+ RealT s2 = 0; // \sum_{i=1}^n \frac{p_i}{\lambda_i^2}
+ RealT s3 = 0; // \sum_{i=1}^n \frac{p_i}{\lambda_i^3}
+ for (std::size_t i = 0; i < n; ++i)
+ {
+ const RealT p = probs[i];
+ const RealT r = rates[i];
+ const RealT r2 = r*r;
+ const RealT r3 = r2*r;
+
+ s1 += p/r;
+ s2 += p/r2;
+ s3 += p/r3;
+ }
+
+ const RealT s1s1 = s1*s1;
+
+ const RealT num = (6*s3 - (3*(2*s2 - s1s1) + s1s1)*s1);
+ const RealT den = (2*s2 - s1s1);
+
+ return num / pow(den, static_cast<RealT>(1.5));
+}
+
+template <typename RealT, typename PolicyT>
+RealT kurtosis(hyperexponential_distribution<RealT,PolicyT> const& dist)
+{
+ const std::size_t n = dist.num_phases();
+ const std::vector<RealT> probs = dist.probabilities();
+ const std::vector<RealT> rates = dist.rates();
+
+ RealT s1 = 0; // \sum_{i=1}^n \frac{p_i}{\lambda_i}
+ RealT s2 = 0; // \sum_{i=1}^n \frac{p_i}{\lambda_i^2}
+ RealT s3 = 0; // \sum_{i=1}^n \frac{p_i}{\lambda_i^3}
+ RealT s4 = 0; // \sum_{i=1}^n \frac{p_i}{\lambda_i^4}
+ for (std::size_t i = 0; i < n; ++i)
+ {
+ const RealT p = probs[i];
+ const RealT r = rates[i];
+ const RealT r2 = r*r;
+ const RealT r3 = r2*r;
+ const RealT r4 = r3*r;
+
+ s1 += p/r;
+ s2 += p/r2;
+ s3 += p/r3;
+ s4 += p/r4;
+ }
+
+ const RealT s1s1 = s1*s1;
+
+ const RealT num = (24*s4 - 24*s3*s1 + 3*(2*(2*s2 - s1s1) + s1s1)*s1s1);
+ const RealT den = (2*s2 - s1s1);
+
+ return num/(den*den);
+}
+
+template <typename RealT, typename PolicyT>
+RealT kurtosis_excess(hyperexponential_distribution<RealT,PolicyT> const& dist)
+{
+ return kurtosis(dist) - 3;
+}
+
+template <typename RealT, typename PolicyT>
+RealT mode(hyperexponential_distribution<RealT,PolicyT> const& /*dist*/)
+{
+ return 0;
+}
+
+}} // namespace boost::math
+
+#ifdef BOOST_MSVC
+#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 <boost/math/distributions/detail/derived_accessors.hpp>
+#include <boost/math/distributions/detail/generic_quantile.hpp>
+
+#endif // BOOST_MATH_DISTRIBUTIONS_HYPEREXPONENTIAL
diff --git a/boost/math/distributions/hypergeometric.hpp b/boost/math/distributions/hypergeometric.hpp
index e30d438f31..5d1ebc7388 100644
--- a/boost/math/distributions/hypergeometric.hpp
+++ b/boost/math/distributions/hypergeometric.hpp
@@ -136,7 +136,7 @@ namespace boost { namespace math {
BOOST_MATH_STD_USING
static const char* function = "boost::math::pdf(const hypergeometric_distribution<%1%>&, const %1%&)";
RealType r = static_cast<RealType>(x);
- unsigned u = itrunc(r);
+ unsigned u = itrunc(r, typename policies::normalise<Policy, policies::rounding_error<policies::ignore_error> >::type());
if(u != r)
{
return boost::math::policies::raise_domain_error<RealType>(
@@ -165,7 +165,7 @@ namespace boost { namespace math {
BOOST_MATH_STD_USING
static const char* function = "boost::math::cdf(const hypergeometric_distribution<%1%>&, const %1%&)";
RealType r = static_cast<RealType>(x);
- unsigned u = itrunc(r);
+ unsigned u = itrunc(r, typename policies::normalise<Policy, policies::rounding_error<policies::ignore_error> >::type());
if(u != r)
{
return boost::math::policies::raise_domain_error<RealType>(
@@ -194,7 +194,7 @@ namespace boost { namespace math {
BOOST_MATH_STD_USING
static const char* function = "boost::math::cdf(const hypergeometric_distribution<%1%>&, const %1%&)";
RealType r = static_cast<RealType>(c.param);
- unsigned u = itrunc(r);
+ unsigned u = itrunc(r, typename policies::normalise<Policy, policies::rounding_error<policies::ignore_error> >::type());
if(u != r)
{
return boost::math::policies::raise_domain_error<RealType>(
diff --git a/boost/math/distributions/inverse_chi_squared.hpp b/boost/math/distributions/inverse_chi_squared.hpp
index 8fc13e39e7..c1e54905da 100644
--- a/boost/math/distributions/inverse_chi_squared.hpp
+++ b/boost/math/distributions/inverse_chi_squared.hpp
@@ -51,7 +51,7 @@ public:
typedef RealType value_type;
typedef Policy policy_type;
- inverse_chi_squared_distribution(RealType df, RealType scale) : m_df(df), m_scale (scale)
+ inverse_chi_squared_distribution(RealType df, RealType l_scale) : m_df(df), m_scale (l_scale)
{
RealType result;
detail::check_df(
diff --git a/boost/math/distributions/inverse_gamma.hpp b/boost/math/distributions/inverse_gamma.hpp
index 88083e084f..fa5d357ac7 100644
--- a/boost/math/distributions/inverse_gamma.hpp
+++ b/boost/math/distributions/inverse_gamma.hpp
@@ -91,13 +91,13 @@ public:
typedef RealType value_type;
typedef Policy policy_type;
- inverse_gamma_distribution(RealType shape = 1, RealType scale = 1)
- : m_shape(shape), m_scale(scale)
+ inverse_gamma_distribution(RealType l_shape = 1, RealType l_scale = 1)
+ : m_shape(l_shape), m_scale(l_scale)
{
RealType result;
detail::check_inverse_gamma(
"boost::math::inverse_gamma_distribution<%1%>::inverse_gamma_distribution",
- scale, shape, &result, Policy());
+ l_scale, l_shape, &result, Policy());
}
RealType shape()const
@@ -259,6 +259,9 @@ inline RealType cdf(const complemented2_type<inverse_gamma_distribution<RealType
if(false == detail::check_inverse_gamma_x(function, c.param, &result, Policy()))
return result;
+ if(c.param == 0)
+ return 1; // Avoid division by zero
+
//result = 1. - gamma_q(shape, c.param / scale, Policy());
result = gamma_p(shape, scale/c.param, Policy());
return result;
diff --git a/boost/math/distributions/inverse_gaussian.hpp b/boost/math/distributions/inverse_gaussian.hpp
index 67c1b4109c..eeca12ad48 100644
--- a/boost/math/distributions/inverse_gaussian.hpp
+++ b/boost/math/distributions/inverse_gaussian.hpp
@@ -74,14 +74,14 @@ public:
typedef RealType value_type;
typedef Policy policy_type;
- inverse_gaussian_distribution(RealType mean = 1, RealType scale = 1)
- : m_mean(mean), m_scale(scale)
+ inverse_gaussian_distribution(RealType l_mean = 1, RealType l_scale = 1)
+ : m_mean(l_mean), m_scale(l_scale)
{ // Default is a 1,1 inverse_gaussian distribution.
static const char* function = "boost::math::inverse_gaussian_distribution<%1%>::inverse_gaussian_distribution";
RealType result;
- detail::check_scale(function, scale, &result, Policy());
- detail::check_location(function, mean, &result, Policy());
+ detail::check_scale(function, l_scale, &result, Policy());
+ detail::check_location(function, l_mean, &result, Policy());
}
RealType mean()const
@@ -207,11 +207,11 @@ inline RealType cdf(const inverse_gaussian_distribution<RealType, Policy>& dist,
return result;
} // cdf
-template <class RealType>
+template <class RealType, class Policy>
struct inverse_gaussian_quantile_functor
{
- inverse_gaussian_quantile_functor(const boost::math::inverse_gaussian_distribution<RealType> dist, RealType const& p)
+ inverse_gaussian_quantile_functor(const boost::math::inverse_gaussian_distribution<RealType, Policy> dist, RealType const& p)
: distribution(dist), prob(p)
{
}
@@ -224,14 +224,14 @@ struct inverse_gaussian_quantile_functor
return boost::math::make_tuple(fx, dx);
}
private:
- const boost::math::inverse_gaussian_distribution<RealType> distribution;
+ const boost::math::inverse_gaussian_distribution<RealType, Policy> distribution;
RealType prob;
};
-template <class RealType>
+template <class RealType, class Policy>
struct inverse_gaussian_quantile_complement_functor
{
- inverse_gaussian_quantile_complement_functor(const boost::math::inverse_gaussian_distribution<RealType> dist, RealType const& p)
+ inverse_gaussian_quantile_complement_functor(const boost::math::inverse_gaussian_distribution<RealType, Policy> dist, RealType const& p)
: distribution(dist), prob(p)
{
}
@@ -245,7 +245,7 @@ struct inverse_gaussian_quantile_complement_functor
return boost::math::make_tuple(fx, dx);
}
private:
- const boost::math::inverse_gaussian_distribution<RealType> distribution;
+ const boost::math::inverse_gaussian_distribution<RealType, Policy> distribution;
RealType prob;
};
@@ -286,7 +286,7 @@ namespace detail
// Define the distribution, using gamma_nooverflow:
typedef gamma_distribution<RealType, no_overthrow_policy> gamma_nooverflow;
- gamma_distribution<RealType, no_overthrow_policy> g(static_cast<RealType>(0.5), static_cast<RealType>(1.));
+ gamma_nooverflow g(static_cast<RealType>(0.5), static_cast<RealType>(1.));
// gamma_nooverflow g(static_cast<RealType>(0.5), static_cast<RealType>(1.));
// R qgamma(0.2, 0.5, 1) 0.0320923
@@ -347,7 +347,7 @@ inline RealType quantile(const inverse_gaussian_distribution<RealType, Policy>&
boost::uintmax_t m = policies::get_max_root_iterations<Policy>(); // and max iterations.
using boost::math::tools::newton_raphson_iterate;
result =
- newton_raphson_iterate(inverse_gaussian_quantile_functor<RealType>(dist, p), guess, min, max, get_digits, m);
+ newton_raphson_iterate(inverse_gaussian_quantile_functor<RealType, Policy>(dist, p), guess, min, max, get_digits, m);
return result;
} // quantile
@@ -380,7 +380,7 @@ inline RealType cdf(const complemented2_type<inverse_gaussian_distribution<RealT
return result;
if(false == detail::check_location(function, mean, &result, Policy()))
return result;
- if(false == detail::check_x(function, x, &result, Policy()))
+ if(false == detail::check_positive_x(function, x, &result, Policy()))
return result;
normal_distribution<RealType> n01;
@@ -428,7 +428,7 @@ inline RealType quantile(const complemented2_type<inverse_gaussian_distribution<
boost::uintmax_t m = policies::get_max_root_iterations<Policy>();
using boost::math::tools::newton_raphson_iterate;
result =
- newton_raphson_iterate(inverse_gaussian_quantile_complement_functor<RealType>(c.dist, q), guess, min, max, get_digits, m);
+ newton_raphson_iterate(inverse_gaussian_quantile_complement_functor<RealType, Policy>(c.dist, q), guess, min, max, get_digits, m);
return result;
} // quantile
diff --git a/boost/math/distributions/laplace.hpp b/boost/math/distributions/laplace.hpp
index a872b16839..09b24c868b 100644
--- a/boost/math/distributions/laplace.hpp
+++ b/boost/math/distributions/laplace.hpp
@@ -1,6 +1,6 @@
// Copyright Thijs van den Berg, 2008.
// Copyright John Maddock 2008.
-// Copyright Paul A. Bristow 2008.
+// Copyright Paul A. Bristow 2008, 2014.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
@@ -24,6 +24,11 @@
namespace boost{ namespace math{
+#ifdef BOOST_MSVC
+# pragma warning(push)
+# pragma warning(disable:4127) // conditional expression is constant
+#endif
+
template <class RealType = double, class Policy = policies::policy<> >
class laplace_distribution
{
@@ -37,8 +42,8 @@ public:
// ----------------------------------
// Constructor(s)
// ----------------------------------
- laplace_distribution(RealType location = 0, RealType scale = 1)
- : m_location(location), m_scale(scale)
+ laplace_distribution(RealType l_location = 0, RealType l_scale = 1)
+ : m_location(l_location), m_scale(l_scale)
{
RealType result;
check_parameters("boost::math::laplace_distribution<%1%>::laplace_distribution()", &result);
@@ -72,23 +77,38 @@ private:
}; // class laplace_distribution
//
-// Convenient type synonym for double
+// Convenient type synonym for double.
typedef laplace_distribution<double> laplace;
//
-// Non member functions
+// Non-member functions.
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const laplace_distribution<RealType, Policy>&)
{
- using boost::math::tools::max_value;
- return std::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>());
+ if (std::numeric_limits<RealType>::has_infinity)
+ { // Can use infinity.
+ return std::pair<RealType, RealType>(-std::numeric_limits<RealType>::infinity(), std::numeric_limits<RealType>::infinity()); // - to + infinity.
+ }
+ else
+ { // Can only use max_value.
+ using boost::math::tools::max_value;
+ return std::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>()); // - to + max value.
+ }
+
}
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> support(const laplace_distribution<RealType, Policy>&)
{
- using boost::math::tools::max_value;
- return std::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>());
+ if (std::numeric_limits<RealType>::has_infinity)
+ { // Can Use infinity.
+ return std::pair<RealType, RealType>(-std::numeric_limits<RealType>::infinity(), std::numeric_limits<RealType>::infinity()); // - to + infinity.
+ }
+ else
+ { // Can only use max_value.
+ using boost::math::tools::max_value;
+ return std::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>()); // - to + max value.
+ }
}
template <class RealType, class Policy>
@@ -99,12 +119,15 @@ inline RealType pdf(const laplace_distribution<RealType, Policy>& dist, const Re
// Checking function argument
RealType result = 0;
const char* function = "boost::math::pdf(const laplace_distribution<%1%>&, %1%))";
- if (false == dist.check_parameters(function, &result)) return result;
- if (false == detail::check_x(function, x, &result, Policy())) return result;
- // Special pdf values
+ // Check scale and location.
+ if (false == dist.check_parameters(function, &result)) return result;
+ // Special pdf values.
if((boost::math::isinf)(x))
+ {
return 0; // pdf + and - infinity is zero.
+ }
+ if (false == detail::check_x(function, x, &result, Policy())) return result;
// General case
RealType scale( dist.scale() );
@@ -123,20 +146,21 @@ inline RealType pdf(const laplace_distribution<RealType, Policy>& dist, const Re
template <class RealType, class Policy>
inline RealType cdf(const laplace_distribution<RealType, Policy>& dist, const RealType& x)
{
- BOOST_MATH_STD_USING // for ADL of std functions
+ BOOST_MATH_STD_USING // For ADL of std functions.
- // Checking function argument
RealType result = 0;
+ // Checking function argument.
const char* function = "boost::math::cdf(const laplace_distribution<%1%>&, %1%)";
+ // Check scale and location.
if (false == dist.check_parameters(function, &result)) return result;
- if (false == detail::check_x(function, x, &result, Policy())) return result;
// Special cdf values:
if((boost::math::isinf)(x))
{
- if(x < 0) return 0; // -infinity
- return 1; // + infinity
+ if(x < 0) return 0; // -infinity.
+ return 1; // + infinity.
}
+ if (false == detail::check_x(function, x, &result, Policy())) return result;
// General cdf values
RealType scale( dist.scale() );
@@ -195,25 +219,29 @@ inline RealType quantile(const laplace_distribution<RealType, Policy>& dist, con
template <class RealType, class Policy>
inline RealType cdf(const complemented2_type<laplace_distribution<RealType, Policy>, RealType>& c)
{
+ // Calculate complement of cdf.
BOOST_MATH_STD_USING // for ADL of std functions
RealType scale = c.dist.scale();
RealType location = c.dist.location();
RealType x = c.param;
-
- // Checking function argument
RealType result = 0;
+
+ // Checking function argument.
const char* function = "boost::math::cdf(const complemented2_type<laplace_distribution<%1%>, %1%>&)";
- if(false == detail::check_x(function, x, &result, Policy()))return result;
- // Calculate complement of cdf.
+ // Check scale and location.
+ //if(false == detail::check_scale(function, scale, result, Policy())) return false;
+ //if(false == detail::check_location(function, location, result, Policy())) return false;
+ if (false == c.dist.check_parameters(function, &result)) return result;
- // Special cdf value
+ // Special cdf values.
if((boost::math::isinf)(x))
{
if(x < 0) return 1; // cdf complement -infinity is unity.
return 0; // cdf complement +infinity is zero.
}
+ if(false == detail::check_x(function, x, &result, Policy()))return result;
// Cdf interval value.
if (-x < -location)
@@ -237,17 +265,23 @@ inline RealType quantile(const complemented2_type<laplace_distribution<RealType,
RealType scale = c.dist.scale();
RealType location = c.dist.location();
RealType q = c.param;
+ RealType result = 0;
// Checking function argument.
- RealType result = 0;
const char* function = "quantile(const complemented2_type<laplace_distribution<%1%>, %1%>&)";
+ if (false == c.dist.check_parameters(function, &result)) return result;
+
+ // Extreme values.
+ if(q == 0)
+ {
+ return std::numeric_limits<RealType>::infinity();
+ }
+ if(q == 1)
+ {
+ return -std::numeric_limits<RealType>::infinity();
+ }
if(false == detail::check_probability(function, q, &result, Policy())) return result;
-
- // extreme values
- if(q == 0) return std::numeric_limits<RealType>::infinity();
- if(q == 1) return -std::numeric_limits<RealType>::infinity();
-
if (0.5 - q < 0.0)
result = location + scale*log( static_cast<RealType>(-q*2 + 2) );
else
@@ -299,6 +333,10 @@ inline RealType kurtosis_excess(const laplace_distribution<RealType, Policy>& /*
return 3;
}
+#ifdef BOOST_MSVC
+# pragma warning(pop)
+#endif
+
} // namespace math
} // namespace boost
diff --git a/boost/math/distributions/logistic.hpp b/boost/math/distributions/logistic.hpp
index e48f0b4f49..b3d16b7197 100644
--- a/boost/math/distributions/logistic.hpp
+++ b/boost/math/distributions/logistic.hpp
@@ -5,6 +5,9 @@
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
+#ifndef BOOST_MATH_DISTRIBUTIONS_LOGISTIC
+#define BOOST_MATH_DISTRIBUTIONS_LOGISTIC
+
#include <boost/math/distributions/fwd.hpp>
#include <boost/math/distributions/detail/common_error_handling.hpp>
#include <boost/math/distributions/complement.hpp>
@@ -21,14 +24,14 @@ namespace boost { namespace math {
typedef RealType value_type;
typedef Policy policy_type;
- logistic_distribution(RealType location=0, RealType scale=1) // Constructor.
- : m_location(location), m_scale(scale)
+ logistic_distribution(RealType l_location=0, RealType l_scale=1) // Constructor.
+ : m_location(l_location), m_scale(l_scale)
{
static const char* function = "boost::math::logistic_distribution<%1%>::logistic_distribution";
RealType result;
- detail::check_scale(function, scale, &result, Policy());
- detail::check_location(function, location, &result, Policy());
+ detail::check_scale(function, l_scale, &result, Policy());
+ detail::check_location(function, l_location, &result, Policy());
}
// Accessor functions.
RealType scale()const
@@ -53,7 +56,9 @@ namespace boost { namespace math {
inline const std::pair<RealType, RealType> range(const logistic_distribution<RealType, Policy>& /* dist */)
{ // Range of permissible values for random variable x.
using boost::math::tools::max_value;
- return std::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>()); // - to + infinity
+ return std::pair<RealType, RealType>(
+ std::numeric_limits<RealType>::has_infinity ? -std::numeric_limits<RealType>::infinity() : -max_value<RealType>(),
+ std::numeric_limits<RealType>::has_infinity ? std::numeric_limits<RealType>::infinity() : max_value<RealType>());
}
template <class RealType, class Policy>
@@ -63,21 +68,15 @@ namespace boost { namespace math {
using boost::math::tools::max_value;
return std::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>()); // - to + infinity
}
-
-
+
template <class RealType, class Policy>
inline RealType pdf(const logistic_distribution<RealType, Policy>& dist, const RealType& x)
{
+ static const char* function = "boost::math::pdf(const logistic_distribution<%1%>&, %1%)";
RealType scale = dist.scale();
RealType location = dist.location();
-
- static const char* function = "boost::math::pdf(const logistic_distribution<%1%>&, %1%)";
- if((boost::math::isinf)(x))
- {
- return 0; // pdf + and - infinity is zero.
- }
-
RealType result = 0;
+
if(false == detail::check_scale(function, scale , &result, Policy()))
{
return result;
@@ -86,6 +85,12 @@ namespace boost { namespace math {
{
return result;
}
+
+ if((boost::math::isinf)(x))
+ {
+ return 0; // pdf + and - infinity is zero.
+ }
+
if(false == detail::check_x(function, x, &result, Policy()))
{
return result;
@@ -181,18 +186,24 @@ namespace boost { namespace math {
RealType x = c.param;
static const char* function = "boost::math::cdf(const complement(logistic_distribution<%1%>&), %1%)";
- if((boost::math::isinf)(x))
- {
- if(x < 0) return 1; // cdf complement -infinity is unity.
- return 0; // cdf complement +infinity is zero
- }
RealType result = 0;
if(false == detail::check_scale(function, scale, &result, Policy()))
+ {
return result;
+ }
if(false == detail::check_location(function, location, &result, Policy()))
+ {
return result;
+ }
+ if((boost::math::isinf)(x))
+ {
+ if(x < 0) return 1; // cdf complement -infinity is unity.
+ return 0; // cdf complement +infinity is zero.
+ }
if(false == detail::check_x(function, x, &result, Policy()))
+ {
return result;
+ }
RealType power = (x - location) / scale;
if(power > tools::log_max_value<RealType>())
return 0;
@@ -285,3 +296,4 @@ namespace boost { namespace math {
// Must come at the end:
#include <boost/math/distributions/detail/derived_accessors.hpp>
+#endif // BOOST_MATH_DISTRIBUTIONS_LOGISTIC
diff --git a/boost/math/distributions/lognormal.hpp b/boost/math/distributions/lognormal.hpp
index a6cfa17a2e..4e6c0610d4 100644
--- a/boost/math/distributions/lognormal.hpp
+++ b/boost/math/distributions/lognormal.hpp
@@ -48,11 +48,12 @@ public:
typedef RealType value_type;
typedef Policy policy_type;
- lognormal_distribution(RealType location = 0, RealType scale = 1)
- : m_location(location), m_scale(scale)
+ lognormal_distribution(RealType l_location = 0, RealType l_scale = 1)
+ : m_location(l_location), m_scale(l_scale)
{
RealType result;
- detail::check_scale("boost::math::lognormal_distribution<%1%>::lognormal_distribution", scale, &result, Policy());
+ detail::check_scale("boost::math::lognormal_distribution<%1%>::lognormal_distribution", l_scale, &result, Policy());
+ detail::check_location("boost::math::lognormal_distribution<%1%>::lognormal_distribution", l_location, &result, Policy());
}
RealType location()const
@@ -102,6 +103,8 @@ RealType pdf(const lognormal_distribution<RealType, Policy>& dist, const RealTyp
RealType result = 0;
if(0 == detail::check_scale(function, sigma, &result, Policy()))
return result;
+ if(0 == detail::check_location(function, mu, &result, Policy()))
+ return result;
if(0 == detail::check_lognormal_x(function, x, &result, Policy()))
return result;
@@ -126,6 +129,10 @@ inline RealType cdf(const lognormal_distribution<RealType, Policy>& dist, const
static const char* function = "boost::math::cdf(const lognormal_distribution<%1%>&, %1%)";
RealType result = 0;
+ if(0 == detail::check_scale(function, dist.scale(), &result, Policy()))
+ return result;
+ if(0 == detail::check_location(function, dist.location(), &result, Policy()))
+ return result;
if(0 == detail::check_lognormal_x(function, x, &result, Policy()))
return result;
@@ -144,6 +151,10 @@ inline RealType quantile(const lognormal_distribution<RealType, Policy>& dist, c
static const char* function = "boost::math::quantile(const lognormal_distribution<%1%>&, %1%)";
RealType result = 0;
+ if(0 == detail::check_scale(function, dist.scale(), &result, Policy()))
+ return result;
+ if(0 == detail::check_location(function, dist.location(), &result, Policy()))
+ return result;
if(0 == detail::check_probability(function, p, &result, Policy()))
return result;
@@ -164,6 +175,10 @@ inline RealType cdf(const complemented2_type<lognormal_distribution<RealType, Po
static const char* function = "boost::math::cdf(const lognormal_distribution<%1%>&, %1%)";
RealType result = 0;
+ if(0 == detail::check_scale(function, c.dist.scale(), &result, Policy()))
+ return result;
+ if(0 == detail::check_location(function, c.dist.location(), &result, Policy()))
+ return result;
if(0 == detail::check_lognormal_x(function, c.param, &result, Policy()))
return result;
@@ -182,6 +197,10 @@ inline RealType quantile(const complemented2_type<lognormal_distribution<RealTyp
static const char* function = "boost::math::quantile(const lognormal_distribution<%1%>&, %1%)";
RealType result = 0;
+ if(0 == detail::check_scale(function, c.dist.scale(), &result, Policy()))
+ return result;
+ if(0 == detail::check_location(function, c.dist.location(), &result, Policy()))
+ return result;
if(0 == detail::check_probability(function, c.param, &result, Policy()))
return result;
@@ -205,6 +224,8 @@ inline RealType mean(const lognormal_distribution<RealType, Policy>& dist)
RealType result = 0;
if(0 == detail::check_scale("boost::math::mean(const lognormal_distribution<%1%>&)", sigma, &result, Policy()))
return result;
+ if(0 == detail::check_location("boost::math::mean(const lognormal_distribution<%1%>&)", mu, &result, Policy()))
+ return result;
return exp(mu + sigma * sigma / 2);
}
@@ -220,6 +241,8 @@ inline RealType variance(const lognormal_distribution<RealType, Policy>& dist)
RealType result = 0;
if(0 == detail::check_scale("boost::math::variance(const lognormal_distribution<%1%>&)", sigma, &result, Policy()))
return result;
+ if(0 == detail::check_location("boost::math::variance(const lognormal_distribution<%1%>&)", mu, &result, Policy()))
+ return result;
return boost::math::expm1(sigma * sigma, Policy()) * exp(2 * mu + sigma * sigma);
}
@@ -235,6 +258,8 @@ inline RealType mode(const lognormal_distribution<RealType, Policy>& dist)
RealType result = 0;
if(0 == detail::check_scale("boost::math::mode(const lognormal_distribution<%1%>&)", sigma, &result, Policy()))
return result;
+ if(0 == detail::check_location("boost::math::mode(const lognormal_distribution<%1%>&)", mu, &result, Policy()))
+ return result;
return exp(mu - sigma * sigma);
}
@@ -261,6 +286,8 @@ inline RealType skewness(const lognormal_distribution<RealType, Policy>& dist)
RealType result = 0;
if(0 == detail::check_scale("boost::math::skewness(const lognormal_distribution<%1%>&)", sigma, &result, Policy()))
return result;
+ if(0 == detail::check_location("boost::math::skewness(const lognormal_distribution<%1%>&)", dist.location(), &result, Policy()))
+ return result;
return (ess + 2) * sqrt(boost::math::expm1(ss, Policy()));
}
@@ -277,6 +304,8 @@ inline RealType kurtosis(const lognormal_distribution<RealType, Policy>& dist)
RealType result = 0;
if(0 == detail::check_scale("boost::math::kurtosis(const lognormal_distribution<%1%>&)", sigma, &result, Policy()))
return result;
+ if(0 == detail::check_location("boost::math::kurtosis(const lognormal_distribution<%1%>&)", dist.location(), &result, Policy()))
+ return result;
return exp(4 * ss) + 2 * exp(3 * ss) + 3 * exp(2 * ss) - 3;
}
@@ -293,6 +322,8 @@ inline RealType kurtosis_excess(const lognormal_distribution<RealType, Policy>&
RealType result = 0;
if(0 == detail::check_scale("boost::math::kurtosis_excess(const lognormal_distribution<%1%>&)", sigma, &result, Policy()))
return result;
+ if(0 == detail::check_location("boost::math::kurtosis_excess(const lognormal_distribution<%1%>&)", dist.location(), &result, Policy()))
+ return result;
return exp(4 * ss) + 2 * exp(3 * ss) + 3 * exp(2 * ss) - 6;
}
diff --git a/boost/math/distributions/negative_binomial.hpp b/boost/math/distributions/negative_binomial.hpp
index 28ce4b996c..ca5723fa7d 100644
--- a/boost/math/distributions/negative_binomial.hpp
+++ b/boost/math/distributions/negative_binomial.hpp
@@ -460,6 +460,15 @@ namespace boost
{ // p <= pdf(dist, 0) == cdf(dist, 0)
return 0;
}
+ if(p == 0)
+ { // Would need +infinity failures for total confidence.
+ result = policies::raise_overflow_error<RealType>(
+ function,
+ "Success fraction is 0, which implies infinite failures !", Policy());
+ return result;
+ // usually means return +std::numeric_limits<RealType>::infinity();
+ // unless #define BOOST_MATH_THROW_ON_OVERFLOW_ERROR
+ }
/*
// Calculate quantile of negative_binomial using the inverse incomplete beta function.
using boost::math::ibeta_invb;
@@ -488,7 +497,7 @@ namespace boost
return detail::inverse_discrete_quantile(
dist,
P,
- 1-P,
+ false,
guess,
factor,
RealType(1),
@@ -527,16 +536,26 @@ namespace boost
// since the probability of zero failures may be non-zero,
return 0; // but zero is the best we can do:
}
+ if(Q == 0)
+ { // Probability 1 - Q == 1 so infinite failures to achieve certainty.
+ // Would need +infinity failures for total confidence.
+ result = policies::raise_overflow_error<RealType>(
+ function,
+ "Probability argument complement is 0, which implies infinite failures !", Policy());
+ return result;
+ // usually means return +std::numeric_limits<RealType>::infinity();
+ // unless #define BOOST_MATH_THROW_ON_OVERFLOW_ERROR
+ }
if (-Q <= boost::math::powm1(dist.success_fraction(), dist.successes(), Policy()))
{ // q <= cdf(complement(dist, 0)) == pdf(dist, 0)
return 0; //
}
- if(Q == 0)
- { // Probability 1 - Q == 1 so infinite failures to achieve certainty.
+ if(p == 0)
+ { // Success fraction is 0 so infinite failures to achieve certainty.
// Would need +infinity failures for total confidence.
result = policies::raise_overflow_error<RealType>(
function,
- "Probability argument complement is 0, which implies infinite failures !", Policy());
+ "Success fraction is 0, which implies infinite failures !", Policy());
return result;
// usually means return +std::numeric_limits<RealType>::infinity();
// unless #define BOOST_MATH_THROW_ON_OVERFLOW_ERROR
@@ -564,8 +583,8 @@ namespace boost
typedef typename Policy::discrete_quantile_type discrete_type;
return detail::inverse_discrete_quantile(
dist,
- 1-Q,
Q,
+ true,
guess,
factor,
RealType(1),
diff --git a/boost/math/distributions/non_central_beta.hpp b/boost/math/distributions/non_central_beta.hpp
index ebb6e91fa1..6e699e509f 100644
--- a/boost/math/distributions/non_central_beta.hpp
+++ b/boost/math/distributions/non_central_beta.hpp
@@ -51,17 +51,8 @@ namespace boost
int k = itrunc(l2);
if(k == 0)
k = 1;
- T pois;
- if(k == 0)
- {
// Starting Poisson weight:
- pois = exp(-l2);
- }
- else
- {
- // Starting Poisson weight:
- pois = gamma_p_derivative(T(k+1), l2, pol);
- }
+ T pois = gamma_p_derivative(T(k+1), l2, pol);
if(pois == 0)
return init_val;
// recurance term:
diff --git a/boost/math/distributions/non_central_chi_squared.hpp b/boost/math/distributions/non_central_chi_squared.hpp
index a3f98982b9..88933c1956 100644
--- a/boost/math/distributions/non_central_chi_squared.hpp
+++ b/boost/math/distributions/non_central_chi_squared.hpp
@@ -101,7 +101,7 @@ namespace boost
}
//Error check:
if(static_cast<boost::uintmax_t>(i-k) >= max_iter)
- policies::raise_evaluation_error(
+ return policies::raise_evaluation_error(
"cdf(non_central_chi_squared_distribution<%1%>, %1%)",
"Series did not converge, closest value was %1%", sum, pol);
//
@@ -175,7 +175,7 @@ namespace boost
}
//Error check:
if(static_cast<boost::uintmax_t>(i) >= max_iter)
- policies::raise_evaluation_error(
+ return policies::raise_evaluation_error(
"cdf(non_central_chi_squared_distribution<%1%>, %1%)",
"Series did not converge, closest value was %1%", sum, pol);
return sum;
@@ -274,7 +274,7 @@ namespace boost
//Error check:
if(static_cast<boost::uintmax_t>(i) >= max_iter)
- policies::raise_evaluation_error(
+ return policies::raise_evaluation_error(
"cdf(non_central_chi_squared_distribution<%1%>, %1%)",
"Series did not converge, closest value was %1%", sum, pol);
@@ -400,6 +400,7 @@ namespace boost
template <class RealType, class Policy>
RealType nccs_quantile(const non_central_chi_squared_distribution<RealType, Policy>& dist, const RealType& p, bool comp)
{
+ BOOST_MATH_STD_USING
static const char* function = "quantile(non_central_chi_squared_distribution<%1%>, %1%)";
typedef typename policies::evaluation<RealType, Policy>::type value_type;
typedef typename policies::normalise<
@@ -428,25 +429,57 @@ namespace boost
&r,
Policy()))
return (RealType)r;
-
- value_type b = (l * l) / (k + 3 * l);
+ //
+ // Special cases get short-circuited first:
+ //
+ if(p == 0)
+ return comp ? policies::raise_overflow_error<RealType>(function, 0, Policy()) : 0;
+ if(p == 1)
+ return comp ? 0 : policies::raise_overflow_error<RealType>(function, 0, Policy());
+ //
+ // This is Pearson's approximation to the quantile, see
+ // Pearson, E. S. (1959) "Note on an approximation to the distribution of
+ // noncentral chi squared", Biometrika 46: 364.
+ // See also:
+ // "A comparison of approximations to percentiles of the noncentral chi2-distribution",
+ // Hardeo Sahai and Mario Miguel Ojeda, Revista de Matematica: Teoria y Aplicaciones 2003 10(1–2) : 57–76.
+ // Note that the latter reference refers to an approximation of the CDF, when they really mean the quantile.
+ //
+ value_type b = -(l * l) / (k + 3 * l);
value_type c = (k + 3 * l) / (k + 2 * l);
value_type ff = (k + 2 * l) / (c * c);
value_type guess;
if(comp)
+ {
guess = b + c * quantile(complement(chi_squared_distribution<value_type, forwarding_policy>(ff), p));
+ }
else
+ {
guess = b + c * quantile(chi_squared_distribution<value_type, forwarding_policy>(ff), p);
-
- if(guess < 0)
- guess = tools::min_value<value_type>();
-
+ }
+ //
+ // Sometimes guess goes very small or negative, in that case we have
+ // to do something else for the initial guess, this approximation
+ // was provided in a private communication from Thomas Luu, PhD candidate,
+ // University College London. It's an asymptotic expansion for the
+ // quantile which usually gets us within an order of magnitude of the
+ // correct answer.
+ //
+ if(guess < 0.005)
+ {
+ value_type pp = comp ? 1 - p : p;
+ //guess = pow(pow(value_type(2), (k / 2 - 1)) * exp(l / 2) * pp * k, 2 / k);
+ guess = pow(pow(value_type(2), (k / 2 - 1)) * exp(l / 2) * pp * k * boost::math::tgamma(k / 2, forwarding_policy()), (2 / k));
+ if(guess == 0)
+ guess = tools::min_value<value_type>();
+ }
value_type result = detail::generic_quantile(
non_central_chi_squared_distribution<value_type, forwarding_policy>(k, l),
p,
guess,
comp,
function);
+
return policies::checked_narrowing_cast<RealType, forwarding_policy>(
result,
function);
@@ -564,7 +597,7 @@ namespace boost
RealType result = ir.first + (ir.second - ir.first) / 2;
if(max_iter >= policies::get_max_root_iterations<Policy>())
{
- policies::raise_evaluation_error<RealType>(function, "Unable to locate solution in a reasonable time:"
+ return policies::raise_evaluation_error<RealType>(function, "Unable to locate solution in a reasonable time:"
" or there is no answer to problem. Current best guess is %1%", result, Policy());
}
return result;
@@ -620,7 +653,7 @@ namespace boost
RealType result = ir.first + (ir.second - ir.first) / 2;
if(max_iter >= policies::get_max_root_iterations<Policy>())
{
- policies::raise_evaluation_error<RealType>(function, "Unable to locate solution in a reasonable time:"
+ return policies::raise_evaluation_error<RealType>(function, "Unable to locate solution in a reasonable time:"
" or there is no answer to problem. Current best guess is %1%", result, Policy());
}
return result;
diff --git a/boost/math/distributions/non_central_f.hpp b/boost/math/distributions/non_central_f.hpp
index 0549f38fe5..780dbff9a7 100644
--- a/boost/math/distributions/non_central_f.hpp
+++ b/boost/math/distributions/non_central_f.hpp
@@ -133,9 +133,10 @@ namespace boost
&r,
Policy()))
return r;
+ RealType guess = m > 2 ? RealType(m * (n + l) / (n * (m - 2))) : RealType(1);
return detail::generic_find_mode(
dist,
- m * (n + l) / (n * (m - 2)),
+ guess,
function);
}
diff --git a/boost/math/distributions/non_central_t.hpp b/boost/math/distributions/non_central_t.hpp
index e46980fc2d..df7a58e575 100644
--- a/boost/math/distributions/non_central_t.hpp
+++ b/boost/math/distributions/non_central_t.hpp
@@ -27,7 +27,7 @@ namespace boost
namespace detail{
template <class T, class Policy>
- T non_central_t2_p(T n, T delta, T x, T y, const Policy& pol, T init_val)
+ T non_central_t2_p(T v, T delta, T x, T y, const Policy& pol, T init_val)
{
BOOST_MATH_STD_USING
//
@@ -38,43 +38,26 @@ namespace boost
T d2 = delta * delta / 2;
//
// k is the starting point for iteration, and is the
- // maximum of the poisson weighting term:
+ // maximum of the poisson weighting term, we don't
+ // ever allow k == 0 as this can lead to catastrophic
+ // cancellation errors later (test case is v = 1621286869049072.3
+ // delta = 0.16212868690490723, x = 0.86987415482475994).
//
int k = itrunc(d2);
T pois;
- if(k < 15)
- {
- // Since we'll likely need 30-40 terms anyway, start from zero
- // since this simplifies the arithmetic, don't go too overboard though
- // as this is the *unstable* direction:
- k = 0;
- // Starting Poisson weight:
- pois = exp(-d2) * 2 / constants::root_pi<T>();
- pois *= delta / constants::root_two<T>();
- }
- else
- {
- // Starting Poisson weight:
- pois = gamma_p_derivative(T(k+1), d2, pol)
- * tgamma_delta_ratio(T(k + 1), T(0.5f))
- * delta / constants::root_two<T>();
- }
+ if(k == 0) k = 1;
+ // Starting Poisson weight:
+ pois = gamma_p_derivative(T(k+1), d2, pol)
+ * tgamma_delta_ratio(T(k + 1), T(0.5f))
+ * delta / constants::root_two<T>();
if(pois == 0)
return init_val;
T xterm, beta;
// Recurrance & starting beta terms:
- if(k == 0)
- {
- beta = -boost::math::powm1(y, n / 2, pol);
- xterm = beta > 0.5f ? T(pow(y, n / 2)) : T(1 - beta);
- }
- else
- {
- beta = x < y
- ? detail::ibeta_imp(T(k + 1), T(n / 2), x, pol, false, true, &xterm)
- : detail::ibeta_imp(T(n / 2), T(k + 1), y, pol, true, true, &xterm);
- xterm *= y / (n / 2 + k);
- }
+ beta = x < y
+ ? detail::ibeta_imp(T(k + 1), T(v / 2), x, pol, false, true, &xterm)
+ : detail::ibeta_imp(T(v / 2), T(k + 1), y, pol, true, true, &xterm);
+ xterm *= y / (v / 2 + k);
T poisf(pois), betaf(beta), xtermf(xterm);
T sum = init_val;
if((xterm == 0) && (beta == 0))
@@ -85,26 +68,31 @@ namespace boost
// direction for recursion:
//
boost::uintmax_t count = 0;
+ T last_term = 0;
for(int i = k; i >= 0; --i)
{
T term = beta * pois;
sum += term;
- if(fabs(term/sum) < errtol)
+ // Don't terminate on first term in case we "fixed" k above:
+ if((fabs(last_term) > fabs(term)) && fabs(term/sum) < errtol)
break;
+ last_term = term;
pois *= (i + 0.5f) / d2;
beta += xterm;
- xterm *= (i) / (x * (n / 2 + i - 1));
+ xterm *= (i) / (x * (v / 2 + i - 1));
++count;
}
+ last_term = 0;
for(int i = k + 1; ; ++i)
{
poisf *= d2 / (i + 0.5f);
- xtermf *= (x * (n / 2 + i - 1)) / (i);
+ xtermf *= (x * (v / 2 + i - 1)) / (i);
betaf -= xtermf;
T term = poisf * betaf;
sum += term;
- if(fabs(term/sum) < errtol)
+ if((fabs(last_term) > fabs(term)) && (fabs(term/sum) < errtol))
break;
+ last_term = term;
++count;
if(count > max_iter)
{
@@ -117,7 +105,7 @@ namespace boost
}
template <class T, class Policy>
- T non_central_t2_q(T n, T delta, T x, T y, const Policy& pol, T init_val)
+ T non_central_t2_q(T v, T delta, T x, T y, const Policy& pol, T init_val)
{
BOOST_MATH_STD_USING
//
@@ -128,23 +116,16 @@ namespace boost
T d2 = delta * delta / 2;
//
// k is the starting point for iteration, and is the
- // maximum of the poisson weighting term:
+ // maximum of the poisson weighting term, we don't allow
+ // k == 0 as this can cause catastrophic cancellation errors
+ // (test case is v = 561908036470413.25, delta = 0.056190803647041321,
+ // x = 1.6155232703966216):
//
int k = itrunc(d2);
- if(k < 30)
- {
- // We typically need around 40 terms so may as well start at 0
- // and gain faster computation of starting conditions:
- k = 0;
- }
+ if(k == 0) k = 1;
// Starting Poisson weight:
T pois;
- if(k == 0)
- {
- pois = exp(-d2) * 2 / constants::root_pi<T>();
- pois *= delta / constants::root_two<T>();
- }
- else if((k < (int)(max_factorial<T>::value)) && (d2 < tools::log_max_value<T>()) && (log(d2) * k < tools::log_max_value<T>()))
+ if((k < (int)(max_factorial<T>::value)) && (d2 < tools::log_max_value<T>()) && (log(d2) * k < tools::log_max_value<T>()))
{
//
// For small k we can optimise this calculation by using
@@ -170,14 +151,14 @@ namespace boost
if(k != 0)
{
beta = x < y
- ? detail::ibeta_imp(T(k + 1), T(n / 2), x, pol, true, true, &xterm)
- : detail::ibeta_imp(T(n / 2), T(k + 1), y, pol, false, true, &xterm);
+ ? detail::ibeta_imp(T(k + 1), T(v / 2), x, pol, true, true, &xterm)
+ : detail::ibeta_imp(T(v / 2), T(k + 1), y, pol, false, true, &xterm);
- xterm *= y / (n / 2 + k);
+ xterm *= y / (v / 2 + k);
}
else
{
- beta = pow(y, n / 2);
+ beta = pow(y, v / 2);
xterm = beta;
}
T poisf(pois), betaf(beta), xtermf(xterm);
@@ -189,10 +170,11 @@ namespace boost
// Fused forward and backwards recursion:
//
boost::uintmax_t count = 0;
+ T last_term = 0;
for(int i = k + 1, j = k; ; ++i, --j)
{
poisf *= d2 / (i + 0.5f);
- xtermf *= (x * (n / 2 + i - 1)) / (i);
+ xtermf *= (x * (v / 2 + i - 1)) / (i);
betaf += xtermf;
T term = poisf * betaf;
@@ -201,12 +183,14 @@ namespace boost
term += beta * pois;
pois *= (j + 0.5f) / d2;
beta -= xterm;
- xterm *= (j) / (x * (n / 2 + j - 1));
+ xterm *= (j) / (x * (v / 2 + j - 1));
}
sum += term;
- if(fabs(term/sum) < errtol)
+ // Don't terminate on first term in case we "fixed" the value of k above:
+ if((fabs(last_term) > fabs(term)) && fabs(term/sum) < errtol)
break;
+ last_term = term;
if(count > max_iter)
{
return policies::raise_evaluation_error(
@@ -219,27 +203,47 @@ namespace boost
}
template <class T, class Policy>
- T non_central_t_cdf(T n, T delta, T t, bool invert, const Policy& pol)
+ T non_central_t_cdf(T v, T delta, T t, bool invert, const Policy& pol)
{
+ BOOST_MATH_STD_USING
+ if ((boost::math::isinf)(v))
+ { // Infinite degrees of freedom, so use normal distribution located at delta.
+ normal_distribution<T, Policy> n(delta, 1);
+ return cdf(n, t);
+ }
//
- // For t < 0 we have to use reflect:
- //
+ // Otherwise, for t < 0 we have to use the reflection formula:
if(t < 0)
{
t = -t;
delta = -delta;
invert = !invert;
}
+ if(fabs(delta / (4 * v)) < policies::get_epsilon<T, Policy>())
+ {
+ // Approximate with a Student's T centred on delta,
+ // the crossover point is based on eq 2.6 from
+ // "A Comparison of Approximations To Percentiles of the
+ // Noncentral t-Distribution". H. Sahai and M. M. Ojeda,
+ // Revista Investigacion Operacional Vol 21, No 2, 2000.
+ // Original sources referenced in the above are:
+ // "Some Approximations to the Percentage Points of the Noncentral
+ // t-Distribution". C. van Eeden. International Statistical Review, 29, 4-31.
+ // "Continuous Univariate Distributions". N.L. Johnson, S. Kotz and
+ // N. Balkrishnan. 1995. John Wiley and Sons New York.
+ T result = cdf(students_t_distribution<T, Policy>(v), t - delta);
+ return invert ? 1 - result : result;
+ }
//
// x and y are the corresponding random
// variables for the noncentral beta distribution,
// with y = 1 - x:
//
- T x = t * t / (n + t * t);
- T y = n / (n + t * t);
+ T x = t * t / (v + t * t);
+ T y = v / (v + t * t);
T d2 = delta * delta;
T a = 0.5f;
- T b = n / 2;
+ T b = v / 2;
T c = a + b + d2 / 2;
//
// Crossover point for calculating p or q is the same
@@ -255,7 +259,7 @@ namespace boost
if(x != 0)
{
result = non_central_beta_p(a, b, d2, x, y, pol);
- result = non_central_t2_p(n, delta, x, y, pol, result);
+ result = non_central_t2_p(v, delta, x, y, pol, result);
result /= 2;
}
else
@@ -271,10 +275,10 @@ namespace boost
if(x != 0)
{
result = non_central_beta_q(a, b, d2, x, y, pol);
- result = non_central_t2_q(n, delta, x, y, pol, result);
+ result = non_central_t2_q(v, delta, x, y, pol, result);
result /= 2;
}
- else
+ else // x == 0
result = cdf(complement(boost::math::normal_distribution<T, Policy>(), -delta));
}
if(invert)
@@ -283,10 +287,11 @@ namespace boost
}
template <class T, class Policy>
- T non_central_t_quantile(T v, T delta, T p, T q, const Policy&)
+ T non_central_t_quantile(const char* function, T v, T delta, T p, T q, const Policy&)
{
BOOST_MATH_STD_USING
- static const char* function = "quantile(non_central_t_distribution<%1%>, %1%)";
+ // static const char* function = "quantile(non_central_t_distribution<%1%>, %1%)";
+ // now passed as function
typedef typename policies::evaluation<T, Policy>::type value_type;
typedef typename policies::normalise<
Policy,
@@ -296,7 +301,7 @@ namespace boost
policies::assert_undefined<> >::type forwarding_policy;
T r;
- if(!detail::check_df(
+ if(!detail::check_df_gt0_to_inf(
function,
v, &r, Policy())
||
@@ -313,11 +318,24 @@ namespace boost
Policy()))
return r;
+
value_type guess = 0;
- if(v > 3)
- {
- value_type mean = delta * sqrt(v / 2) * tgamma_delta_ratio((v - 1) * 0.5f, T(0.5f));
- value_type var = ((delta * delta + 1) * v) / (v - 2) - mean * mean;
+ if ( ((boost::math::isinf)(v)) || (v > 1 / boost::math::tools::epsilon<T>()) )
+ { // Infinite or very large degrees of freedom, so use normal distribution located at delta.
+ normal_distribution<T, Policy> n(delta, 1);
+ if (p < q)
+ {
+ return quantile(n, p);
+ }
+ else
+ {
+ return quantile(complement(n, q));
+ }
+ }
+ else if(v > 3)
+ { // Use normal distribution to calculate guess.
+ value_type mean = (v > 1 / policies::get_epsilon<T, Policy>()) ? delta : delta * sqrt(v / 2) * tgamma_delta_ratio((v - 1) * 0.5f, T(0.5f));
+ value_type var = (v > 1 / policies::get_epsilon<T, Policy>()) ? value_type(1) : (((delta * delta + 1) * v) / (v - 2) - mean * mean);
if(p < q)
guess = quantile(normal_distribution<value_type, forwarding_policy>(mean, var), p);
else
@@ -370,31 +388,16 @@ namespace boost
//
int k = itrunc(d2);
T pois, xterm;
- if(k < 30)
- {
- //
- // Since we'll need at least 30-40 terms anyway, start from 0
- // since this simplifies the starting arithmetic:
- //
- k = 0;
- // Starting Poisson weight:
- pois = exp(-d2)
- * (2 / constants::root_pi<T>())
- * delta / constants::root_two<T>();
- // Starting beta term:
- xterm = pow(y, n / 2 - 1) * n / 2;
- }
- else
- {
- // Starting Poisson weight:
- pois = gamma_p_derivative(T(k+1), d2, pol)
- * tgamma_delta_ratio(T(k + 1), T(0.5f))
- * delta / constants::root_two<T>();
- // Starting beta term:
- xterm = x < y
- ? ibeta_derivative(T(k + 1), n / 2, x, pol)
- : ibeta_derivative(n / 2, T(k + 1), y, pol);
- }
+ if(k == 0)
+ k = 1;
+ // Starting Poisson weight:
+ pois = gamma_p_derivative(T(k+1), d2, pol)
+ * tgamma_delta_ratio(T(k + 1), T(0.5f))
+ * delta / constants::root_two<T>();
+ // Starting beta term:
+ xterm = x < y
+ ? ibeta_derivative(T(k + 1), n / 2, x, pol)
+ : ibeta_derivative(n / 2, T(k + 1), y, pol);
T poisf(pois), xtermf(xterm);
T sum = init_val;
if((pois == 0) || (xterm == 0))
@@ -409,7 +412,7 @@ namespace boost
{
T term = xterm * pois;
sum += term;
- if((fabs(term/sum) < errtol) || (term == 0))
+ if(((fabs(term/sum) < errtol) && (i != k)) || (term == 0))
break;
pois *= (i + 0.5f) / d2;
xterm *= (i) / (x * (n / 2 + i));
@@ -444,9 +447,13 @@ namespace boost
T non_central_t_pdf(T n, T delta, T t, const Policy& pol)
{
BOOST_MATH_STD_USING
+ if ((boost::math::isinf)(n))
+ { // Infinite degrees of freedom, so use normal distribution located at delta.
+ normal_distribution<T, Policy> norm(delta, 1);
+ return pdf(norm, t);
+ }
//
- // For t < 0 we have to use the reflection formula:
- //
+ // Otherwise, for t < 0 we have to use the reflection formula:
if(t < 0)
{
t = -t;
@@ -468,6 +475,20 @@ namespace boost
* sqrt(n / constants::pi<T>())
* exp(-delta * delta / 2) / 2;
}
+ if(fabs(delta / (4 * n)) < policies::get_epsilon<T, Policy>())
+ {
+ // Approximate with a Student's T centred on delta,
+ // the crossover point is based on eq 2.6 from
+ // "A Comparison of Approximations To Percentiles of the
+ // Noncentral t-Distribution". H. Sahai and M. M. Ojeda,
+ // Revista Investigacion Operacional Vol 21, No 2, 2000.
+ // Original sources referenced in the above are:
+ // "Some Approximations to the Percentage Points of the Noncentral
+ // t-Distribution". C. van Eeden. International Statistical Review, 29, 4-31.
+ // "Continuous Univariate Distributions". N.L. Johnson, S. Kotz and
+ // N. Balkrishnan. 1995. John Wiley and Sons New York.
+ return pdf(students_t_distribution<T, Policy>(n), t - delta);
+ }
//
// x and y are the corresponding random
// variables for the noncentral beta distribution,
@@ -494,13 +515,35 @@ namespace boost
template <class T, class Policy>
T mean(T v, T delta, const Policy& pol)
{
+ if ((boost::math::isinf)(v))
+ {
+ return delta;
+ }
BOOST_MATH_STD_USING
- return delta * sqrt(v / 2) * tgamma_delta_ratio((v - 1) * 0.5f, T(0.5f), pol);
+ if (v > 1 / boost::math::tools::epsilon<T>() )
+ {
+ //normal_distribution<T, Policy> n(delta, 1);
+ //return boost::math::mean(n);
+ return delta;
+ }
+ else
+ {
+ return delta * sqrt(v / 2) * tgamma_delta_ratio((v - 1) * 0.5f, T(0.5f), pol);
+ }
+ // Other moments use mean so using normal distribution is propagated.
}
template <class T, class Policy>
T variance(T v, T delta, const Policy& pol)
{
+ if ((boost::math::isinf)(v))
+ {
+ return 1;
+ }
+ if (delta == 0)
+ { // == Student's t
+ return v / (v - 2);
+ }
T result = ((delta * delta + 1) * v) / (v - 2);
T m = mean(v, delta, pol);
result -= m * m;
@@ -511,6 +554,14 @@ namespace boost
T skewness(T v, T delta, const Policy& pol)
{
BOOST_MATH_STD_USING
+ if ((boost::math::isinf)(v))
+ {
+ return 0;
+ }
+ if(delta == 0)
+ { // == Student's t
+ return 0;
+ }
T mean = boost::math::detail::mean(v, delta, pol);
T l2 = delta * delta;
T var = ((l2 + 1) * v) / (v - 2) - mean * mean;
@@ -525,6 +576,14 @@ namespace boost
T kurtosis_excess(T v, T delta, const Policy& pol)
{
BOOST_MATH_STD_USING
+ if ((boost::math::isinf)(v))
+ {
+ return 3;
+ }
+ if (delta == 0)
+ { // == Student's t
+ return 3;
+ }
T mean = boost::math::detail::mean(v, delta, pol);
T l2 = delta * delta;
T var = ((l2 + 1) * v) / (v - 2) - mean * mean;
@@ -588,7 +647,7 @@ namespace boost
RealType result = ir.first + (ir.second - ir.first) / 2;
if(max_iter >= policies::get_max_root_iterations<Policy>())
{
- policies::raise_evaluation_error<RealType>(function, "Unable to locate solution in a reasonable time:"
+ return policies::raise_evaluation_error<RealType>(function, "Unable to locate solution in a reasonable time:"
" or there is no answer to problem. Current best guess is %1%", result, Policy());
}
return result;
@@ -626,7 +685,7 @@ namespace boost
// Can't do a thing if one of p and q is zero:
//
return policies::raise_evaluation_error<RealType>(function,
- "Can't find non centrality parameter when the probability is 0 or 1, only possible answer is %1%",
+ "Can't find non-centrality parameter when the probability is 0 or 1, only possible answer is %1%",
RealType(std::numeric_limits<RealType>::quiet_NaN()), Policy());
}
t_non_centrality_finder<RealType, Policy> f(v, x, p < q ? p : q, p < q ? false : true);
@@ -646,13 +705,13 @@ namespace boost
RealType result = ir.first + (ir.second - ir.first) / 2;
if(max_iter >= policies::get_max_root_iterations<Policy>())
{
- policies::raise_evaluation_error<RealType>(function, "Unable to locate solution in a reasonable time:"
+ return policies::raise_evaluation_error<RealType>(function, "Unable to locate solution in a reasonable time:"
" or there is no answer to problem. Current best guess is %1%", result, Policy());
}
return result;
}
#endif
- } // namespace detail
+ } // namespace detail ======================================================================
template <class RealType = double, class Policy = policies::policy<> >
class non_central_t_distribution
@@ -665,7 +724,7 @@ namespace boost
{
const char* function = "boost::math::non_central_t_distribution<%1%>::non_central_t_distribution(%1%,%1%)";
RealType r;
- detail::check_df(
+ detail::check_df_gt0_to_inf(
function,
v, &r, Policy());
detail::check_finite(
@@ -803,7 +862,7 @@ namespace boost
RealType v = dist.degrees_of_freedom();
RealType l = dist.non_centrality();
RealType r;
- if(!detail::check_df(
+ if(!detail::check_df_gt0_to_inf(
function,
v, &r, Policy())
||
@@ -841,7 +900,7 @@ namespace boost
RealType v = dist.degrees_of_freedom();
RealType l = dist.non_centrality();
RealType r;
- if(!detail::check_df(
+ if(!detail::check_df_gt0_to_inf(
function,
v, &r, Policy())
||
@@ -854,7 +913,7 @@ namespace boost
if(v <= 1)
return policies::raise_domain_error<RealType>(
function,
- "The non central t distribution has no defined mean for degrees of freedom <= 1: got v=%1%.", v, Policy());
+ "The non-central t distribution has no defined mean for degrees of freedom <= 1: got v=%1%.", v, Policy());
// return l * sqrt(v / 2) * tgamma_delta_ratio((v - 1) * 0.5f, RealType(0.5f));
return policies::checked_narrowing_cast<RealType, forwarding_policy>(
detail::mean(static_cast<value_type>(v), static_cast<value_type>(l), forwarding_policy()), function);
@@ -876,7 +935,7 @@ namespace boost
RealType v = dist.degrees_of_freedom();
RealType l = dist.non_centrality();
RealType r;
- if(!detail::check_df(
+ if(!detail::check_df_gt0_to_inf(
function,
v, &r, Policy())
||
@@ -889,7 +948,7 @@ namespace boost
if(v <= 2)
return policies::raise_domain_error<RealType>(
function,
- "The non central t distribution has no defined variance for degrees of freedom <= 2: got v=%1%.", v, Policy());
+ "The non-central t distribution has no defined variance for degrees of freedom <= 2: got v=%1%.", v, Policy());
return policies::checked_narrowing_cast<RealType, forwarding_policy>(
detail::variance(static_cast<value_type>(v), static_cast<value_type>(l), forwarding_policy()), function);
}
@@ -911,7 +970,7 @@ namespace boost
RealType v = dist.degrees_of_freedom();
RealType l = dist.non_centrality();
RealType r;
- if(!detail::check_df(
+ if(!detail::check_df_gt0_to_inf(
function,
v, &r, Policy())
||
@@ -924,7 +983,7 @@ namespace boost
if(v <= 3)
return policies::raise_domain_error<RealType>(
function,
- "The non central t distribution has no defined skewness for degrees of freedom <= 3: got v=%1%.", v, Policy());;
+ "The non-central t distribution has no defined skewness for degrees of freedom <= 3: got v=%1%.", v, Policy());;
return policies::checked_narrowing_cast<RealType, forwarding_policy>(
detail::skewness(static_cast<value_type>(v), static_cast<value_type>(l), forwarding_policy()), function);
}
@@ -943,7 +1002,7 @@ namespace boost
RealType v = dist.degrees_of_freedom();
RealType l = dist.non_centrality();
RealType r;
- if(!detail::check_df(
+ if(!detail::check_df_gt0_to_inf(
function,
v, &r, Policy())
||
@@ -956,7 +1015,7 @@ namespace boost
if(v <= 4)
return policies::raise_domain_error<RealType>(
function,
- "The non central t distribution has no defined kurtosis for degrees of freedom <= 4: got v=%1%.", v, Policy());;
+ "The non-central t distribution has no defined kurtosis for degrees of freedom <= 4: got v=%1%.", v, Policy());;
return policies::checked_narrowing_cast<RealType, forwarding_policy>(
detail::kurtosis_excess(static_cast<value_type>(v), static_cast<value_type>(l), forwarding_policy()), function);
} // kurtosis_excess
@@ -970,7 +1029,7 @@ namespace boost
template <class RealType, class Policy>
inline RealType pdf(const non_central_t_distribution<RealType, Policy>& dist, const RealType& t)
{ // Probability Density/Mass Function.
- const char* function = "cdf(non_central_t_distribution<%1%>, %1%)";
+ const char* function = "pdf(non_central_t_distribution<%1%>, %1%)";
typedef typename policies::evaluation<RealType, Policy>::type value_type;
typedef typename policies::normalise<
Policy,
@@ -982,7 +1041,7 @@ namespace boost
RealType v = dist.degrees_of_freedom();
RealType l = dist.non_centrality();
RealType r;
- if(!detail::check_df(
+ if(!detail::check_df_gt0_to_inf(
function,
v, &r, Policy())
||
@@ -1009,7 +1068,8 @@ namespace boost
template <class RealType, class Policy>
RealType cdf(const non_central_t_distribution<RealType, Policy>& dist, const RealType& x)
{
- const char* function = "boost::math::non_central_t_distribution<%1%>::cdf(%1%)";
+ const char* function = "boost::math::cdf(non_central_t_distribution<%1%>&, %1%)";
+// was const char* function = "boost::math::non_central_t_distribution<%1%>::cdf(%1%)";
typedef typename policies::evaluation<RealType, Policy>::type value_type;
typedef typename policies::normalise<
Policy,
@@ -1021,7 +1081,7 @@ namespace boost
RealType v = dist.degrees_of_freedom();
RealType l = dist.non_centrality();
RealType r;
- if(!detail::check_df(
+ if(!detail::check_df_gt0_to_inf(
function,
v, &r, Policy())
||
@@ -1037,10 +1097,17 @@ namespace boost
&r,
Policy()))
return (RealType)r;
+ if ((boost::math::isinf)(v))
+ { // Infinite degrees of freedom, so use normal distribution located at delta.
+ normal_distribution<RealType, Policy> n(l, 1);
+ cdf(n, x);
+ //return cdf(normal_distribution<RealType, Policy>(l, 1), x);
+ }
if(l == 0)
+ { // NO non-centrality, so use Student's t instead.
return cdf(students_t_distribution<RealType, Policy>(v), x);
-
+ }
return policies::checked_narrowing_cast<RealType, forwarding_policy>(
detail::non_central_t_cdf(
static_cast<value_type>(v),
@@ -1053,7 +1120,8 @@ namespace boost
template <class RealType, class Policy>
RealType cdf(const complemented2_type<non_central_t_distribution<RealType, Policy>, RealType>& c)
{ // Complemented Cumulative Distribution Function
- const char* function = "boost::math::non_central_t_distribution<%1%>::cdf(%1%)";
+ // was const char* function = "boost::math::non_central_t_distribution<%1%>::cdf(%1%)";
+ const char* function = "boost::math::cdf(const complement(non_central_t_distribution<%1%>&), %1%)";
typedef typename policies::evaluation<RealType, Policy>::type value_type;
typedef typename policies::normalise<
Policy,
@@ -1065,9 +1133,9 @@ namespace boost
non_central_t_distribution<RealType, Policy> const& dist = c.dist;
RealType x = c.param;
RealType v = dist.degrees_of_freedom();
- RealType l = dist.non_centrality();
+ RealType l = dist.non_centrality(); // aka delta
RealType r;
- if(!detail::check_df(
+ if(!detail::check_df_gt0_to_inf(
function,
v, &r, Policy())
||
@@ -1084,9 +1152,15 @@ namespace boost
Policy()))
return (RealType)r;
+ if ((boost::math::isinf)(v))
+ { // Infinite degrees of freedom, so use normal distribution located at delta.
+ normal_distribution<RealType, Policy> n(l, 1);
+ return cdf(complement(n, x));
+ }
if(l == 0)
+ { // zero non-centrality so use Student's t distribution.
return cdf(complement(students_t_distribution<RealType, Policy>(v), x));
-
+ }
return policies::checked_narrowing_cast<RealType, forwarding_policy>(
detail::non_central_t_cdf(
static_cast<value_type>(v),
@@ -1099,19 +1173,21 @@ namespace boost
template <class RealType, class Policy>
inline RealType quantile(const non_central_t_distribution<RealType, Policy>& dist, const RealType& p)
{ // Quantile (or Percent Point) function.
+ static const char* function = "quantile(const non_central_t_distribution<%1%>, %1%)";
RealType v = dist.degrees_of_freedom();
RealType l = dist.non_centrality();
- return detail::non_central_t_quantile(v, l, p, RealType(1-p), Policy());
+ return detail::non_central_t_quantile(function, v, l, p, RealType(1-p), Policy());
} // quantile
template <class RealType, class Policy>
inline RealType quantile(const complemented2_type<non_central_t_distribution<RealType, Policy>, RealType>& c)
{ // Quantile (or Percent Point) function.
+ static const char* function = "quantile(const complement(non_central_t_distribution<%1%>, %1%))";
non_central_t_distribution<RealType, Policy> const& dist = c.dist;
RealType q = c.param;
RealType v = dist.degrees_of_freedom();
RealType l = dist.non_centrality();
- return detail::non_central_t_quantile(v, l, RealType(1-q), q, Policy());
+ return detail::non_central_t_quantile(function, v, l, RealType(1-q), q, Policy());
} // quantile complement.
} // namespace math
diff --git a/boost/math/distributions/normal.hpp b/boost/math/distributions/normal.hpp
index baeecf6348..32cf66e3ef 100644
--- a/boost/math/distributions/normal.hpp
+++ b/boost/math/distributions/normal.hpp
@@ -31,14 +31,14 @@ public:
typedef RealType value_type;
typedef Policy policy_type;
- normal_distribution(RealType mean = 0, RealType sd = 1)
- : m_mean(mean), m_sd(sd)
+ normal_distribution(RealType l_mean = 0, RealType sd = 1)
+ : m_mean(l_mean), m_sd(sd)
{ // Default is a 'standard' normal distribution N01.
static const char* function = "boost::math::normal_distribution<%1%>::normal_distribution";
RealType result;
detail::check_scale(function, sd, &result, Policy());
- detail::check_location(function, mean, &result, Policy());
+ detail::check_location(function, l_mean, &result, Policy());
}
RealType mean()const
@@ -71,22 +71,43 @@ private:
typedef normal_distribution<double> normal;
+#ifdef BOOST_MSVC
+#pragma warning(push)
+#pragma warning(disable:4127)
+#endif
+
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const normal_distribution<RealType, Policy>& /*dist*/)
{ // Range of permissible values for random variable x.
- using boost::math::tools::max_value;
- return std::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>()); // - to + max value.
+ if (std::numeric_limits<RealType>::has_infinity)
+ {
+ return std::pair<RealType, RealType>(-std::numeric_limits<RealType>::infinity(), std::numeric_limits<RealType>::infinity()); // - to + infinity.
+ }
+ else
+ { // Can only use max_value.
+ using boost::math::tools::max_value;
+ return std::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>()); // - to + max value.
+ }
}
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> support(const normal_distribution<RealType, Policy>& /*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.
-
+{ // This is range values for random variable x where cdf rises from 0 to 1, and outside it, the pdf is zero.
+ if (std::numeric_limits<RealType>::has_infinity)
+ {
+ return std::pair<RealType, RealType>(-std::numeric_limits<RealType>::infinity(), std::numeric_limits<RealType>::infinity()); // - to + infinity.
+ }
+ else
+ { // Can only use max_value.
using boost::math::tools::max_value;
return std::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>()); // - to + max value.
+ }
}
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
template <class RealType, class Policy>
inline RealType pdf(const normal_distribution<RealType, Policy>& dist, const RealType& x)
{
@@ -96,15 +117,6 @@ inline RealType pdf(const normal_distribution<RealType, Policy>& dist, const Rea
RealType mean = dist.mean();
static const char* function = "boost::math::pdf(const normal_distribution<%1%>&, %1%)";
- if((boost::math::isinf)(x))
- {
- return 0; // pdf + and - infinity is zero.
- }
- // Below produces MSVC 4127 warnings, so the above used instead.
- //if(std::numeric_limits<RealType>::has_infinity && abs(x) == std::numeric_limits<RealType>::infinity())
- //{ // pdf + and - infinity is zero.
- // return 0;
- //}
RealType result = 0;
if(false == detail::check_scale(function, sd, &result, Policy()))
@@ -115,6 +127,15 @@ inline RealType pdf(const normal_distribution<RealType, Policy>& dist, const Rea
{
return result;
}
+ if((boost::math::isinf)(x))
+ {
+ return 0; // pdf + and - infinity is zero.
+ }
+ // Below produces MSVC 4127 warnings, so the above used instead.
+ //if(std::numeric_limits<RealType>::has_infinity && abs(x) == std::numeric_limits<RealType>::infinity())
+ //{ // pdf + and - infinity is zero.
+ // return 0;
+ //}
if(false == detail::check_x(function, x, &result, Policy()))
{
return result;
@@ -204,6 +225,11 @@ inline RealType cdf(const complemented2_type<normal_distribution<RealType, Polic
RealType x = c.param;
static const char* function = "boost::math::cdf(const complement(normal_distribution<%1%>&), %1%)";
+ RealType result = 0;
+ if(false == detail::check_scale(function, sd, &result, Policy()))
+ return result;
+ if(false == detail::check_location(function, mean, &result, Policy()))
+ return result;
if((boost::math::isinf)(x))
{
if(x < 0) return 1; // cdf complement -infinity is unity.
@@ -218,11 +244,6 @@ inline RealType cdf(const complemented2_type<normal_distribution<RealType, Polic
//{ // cdf complement -infinity is unity.
// return 1;
//}
- RealType result = 0;
- if(false == detail::check_scale(function, sd, &result, Policy()))
- return result;
- if(false == detail::check_location(function, mean, &result, Policy()))
- return result;
if(false == detail::check_x(function, x, &result, Policy()))
return result;
diff --git a/boost/math/distributions/pareto.hpp b/boost/math/distributions/pareto.hpp
index ff7082e2de..1c6cf350f8 100644
--- a/boost/math/distributions/pareto.hpp
+++ b/boost/math/distributions/pareto.hpp
@@ -136,11 +136,11 @@ namespace boost
typedef RealType value_type;
typedef Policy policy_type;
- pareto_distribution(RealType scale = 1, RealType shape = 1)
- : m_scale(scale), m_shape(shape)
+ pareto_distribution(RealType l_scale = 1, RealType l_shape = 1)
+ : m_scale(l_scale), m_shape(l_shape)
{ // Constructor.
RealType result = 0;
- detail::check_pareto("boost::math::pareto_distribution<%1%>::pareto_distribution", scale, shape, &result, Policy());
+ detail::check_pareto("boost::math::pareto_distribution<%1%>::pareto_distribution", l_scale, l_shape, &result, Policy());
}
RealType scale()const
@@ -236,7 +236,7 @@ namespace boost
}
if (p == 1)
{
- return tools::max_value<RealType>(); // x = + infinity.
+ return policies::raise_overflow_error<RealType>(function, 0, Policy()); // x = + infinity.
}
result = scale /
(pow((1 - p), 1 / shape));
@@ -286,7 +286,7 @@ namespace boost
}
if (q == 0)
{
- return tools::max_value<RealType>(); // x = + infinity.
+ return policies::raise_overflow_error<RealType>(function, 0, Policy()); // x = + infinity.
}
result = scale / (pow(q, 1 / shape));
// K. Krishnamoorthy, ISBN 1-58488-635-8 eq 23.1.3
diff --git a/boost/math/distributions/poisson.hpp b/boost/math/distributions/poisson.hpp
index 3dd58f80cb..e4665bff69 100644
--- a/boost/math/distributions/poisson.hpp
+++ b/boost/math/distributions/poisson.hpp
@@ -52,68 +52,6 @@ namespace boost
{
namespace math
{
- namespace detail{
- template <class Dist>
- inline typename Dist::value_type
- inverse_discrete_quantile(
- const Dist& dist,
- const typename Dist::value_type& p,
- const typename Dist::value_type& guess,
- const typename Dist::value_type& multiplier,
- const typename Dist::value_type& adder,
- const policies::discrete_quantile<policies::integer_round_nearest>&,
- boost::uintmax_t& max_iter);
- template <class Dist>
- inline typename Dist::value_type
- inverse_discrete_quantile(
- const Dist& dist,
- const typename Dist::value_type& p,
- const typename Dist::value_type& guess,
- const typename Dist::value_type& multiplier,
- const typename Dist::value_type& adder,
- const policies::discrete_quantile<policies::integer_round_up>&,
- boost::uintmax_t& max_iter);
- template <class Dist>
- inline typename Dist::value_type
- inverse_discrete_quantile(
- const Dist& dist,
- const typename Dist::value_type& p,
- const typename Dist::value_type& guess,
- const typename Dist::value_type& multiplier,
- const typename Dist::value_type& adder,
- const policies::discrete_quantile<policies::integer_round_down>&,
- boost::uintmax_t& max_iter);
- template <class Dist>
- inline typename Dist::value_type
- inverse_discrete_quantile(
- const Dist& dist,
- const typename Dist::value_type& p,
- const typename Dist::value_type& guess,
- const typename Dist::value_type& multiplier,
- const typename Dist::value_type& adder,
- const policies::discrete_quantile<policies::integer_round_outwards>&,
- boost::uintmax_t& max_iter);
- template <class Dist>
- inline typename Dist::value_type
- inverse_discrete_quantile(
- const Dist& dist,
- const typename Dist::value_type& p,
- const typename Dist::value_type& guess,
- const typename Dist::value_type& multiplier,
- const typename Dist::value_type& adder,
- const policies::discrete_quantile<policies::integer_round_inwards>&,
- boost::uintmax_t& max_iter);
- template <class Dist>
- inline typename Dist::value_type
- inverse_discrete_quantile(
- const Dist& dist,
- const typename Dist::value_type& p,
- const typename Dist::value_type& guess,
- const typename Dist::value_type& multiplier,
- const typename Dist::value_type& adder,
- const policies::discrete_quantile<policies::real>&,
- boost::uintmax_t& max_iter);
- }
namespace poisson_detail
{
// Common error checking routines for Poisson distribution functions.
@@ -209,7 +147,7 @@ namespace boost
typedef RealType value_type;
typedef Policy policy_type;
- poisson_distribution(RealType mean = 1) : m_l(mean) // mean (lambda).
+ poisson_distribution(RealType l_mean = 1) : m_l(l_mean) // mean (lambda).
{ // Expected mean number of events that occur during the given interval.
RealType r;
poisson_detail::check_dist(
@@ -443,9 +381,10 @@ namespace boost
inline RealType quantile(const poisson_distribution<RealType, Policy>& dist, const RealType& p)
{ // Quantile (or Percent Point) Poisson function.
// Return the number of expected events k for a given probability p.
+ static const char* function = "boost::math::quantile(const poisson_distribution<%1%>&, %1%)";
RealType result = 0; // of Argument checks:
if(false == poisson_detail::check_prob(
- "boost::math::quantile(const poisson_distribution<%1%>&, %1%)",
+ function,
p,
&result, Policy()))
{
@@ -455,23 +394,21 @@ namespace boost
if (dist.mean() == 0)
{ // if mean = 0 then p = 0, so k can be anything?
if (false == poisson_detail::check_mean_NZ(
- "boost::math::quantile(const poisson_distribution<%1%>&, %1%)",
+ function,
dist.mean(),
&result, Policy()))
{
return result;
}
}
- /*
- BOOST_MATH_STD_USING // ADL of std functions.
- // if(p == 0) NOT necessarily zero!
- // Not necessarily any special value of k because is unlimited.
- if (p <= exp(-dist.mean()))
- { // if p <= cdf for 0 events (== pdf for 0 events), then quantile must be zero.
- return 0;
+ if(p == 0)
+ {
+ return 0; // Exact result regardless of discrete-quantile Policy
+ }
+ if(p == 1)
+ {
+ return policies::raise_overflow_error<RealType>(function, 0, Policy());
}
- return gamma_q_inva(dist.mean(), p, Policy()) - 1;
- */
typedef typename Policy::discrete_quantile_type discrete_type;
boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
RealType guess, factor = 8;
@@ -497,7 +434,7 @@ namespace boost
return detail::inverse_discrete_quantile(
dist,
p,
- 1-p,
+ false,
guess,
factor,
RealType(1),
@@ -512,11 +449,12 @@ namespace boost
// complement of the probability q.
//
// Error checks:
+ static const char* function = "boost::math::quantile(complement(const poisson_distribution<%1%>&, %1%))";
RealType q = c.param;
const poisson_distribution<RealType, Policy>& dist = c.dist;
RealType result = 0; // of argument checks.
if(false == poisson_detail::check_prob(
- "boost::math::quantile(const poisson_distribution<%1%>&, %1%)",
+ function,
q,
&result, Policy()))
{
@@ -526,20 +464,21 @@ namespace boost
if (dist.mean() == 0)
{ // if mean = 0 then p = 0, so k can be anything?
if (false == poisson_detail::check_mean_NZ(
- "boost::math::quantile(const poisson_distribution<%1%>&, %1%)",
+ function,
dist.mean(),
&result, Policy()))
{
return result;
}
}
- /*
- if (-q <= boost::math::expm1(-dist.mean()))
- { // if q <= cdf(complement for 0 events, then quantile must be zero.
- return 0;
+ if(q == 0)
+ {
+ return policies::raise_overflow_error<RealType>(function, 0, Policy());
+ }
+ if(q == 1)
+ {
+ return 0; // Exact result regardless of discrete-quantile Policy
}
- return gamma_p_inva(dist.mean(), q, Policy()) -1;
- */
typedef typename Policy::discrete_quantile_type discrete_type;
boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
RealType guess, factor = 8;
@@ -564,8 +503,8 @@ namespace boost
return detail::inverse_discrete_quantile(
dist,
- 1-q,
q,
+ true,
guess,
factor,
RealType(1),
diff --git a/boost/math/distributions/rayleigh.hpp b/boost/math/distributions/rayleigh.hpp
index 1ffb9dc0ad..01f38c0b01 100644
--- a/boost/math/distributions/rayleigh.hpp
+++ b/boost/math/distributions/rayleigh.hpp
@@ -28,11 +28,11 @@ namespace detail
template <class RealType, class Policy>
inline bool verify_sigma(const char* function, RealType sigma, RealType* presult, const Policy& pol)
{
- if(sigma <= 0)
+ if((sigma <= 0) || (!(boost::math::isfinite)(sigma)))
{
*presult = policies::raise_domain_error<RealType>(
function,
- "The scale parameter \"sigma\" must be > 0, but was: %1%.", sigma, pol);
+ "The scale parameter \"sigma\" must be > 0 and finite, but was: %1%.", sigma, pol);
return false;
}
return true;
@@ -41,7 +41,7 @@ namespace detail
template <class RealType, class Policy>
inline bool verify_rayleigh_x(const char* function, RealType x, RealType* presult, const Policy& pol)
{
- if(x < 0)
+ if((x < 0) || (boost::math::isnan)(x))
{
*presult = policies::raise_domain_error<RealType>(
function,
@@ -59,11 +59,11 @@ public:
typedef RealType value_type;
typedef Policy policy_type;
- rayleigh_distribution(RealType sigma = 1)
- : m_sigma(sigma)
+ rayleigh_distribution(RealType l_sigma = 1)
+ : m_sigma(l_sigma)
{
RealType err;
- detail::verify_sigma("boost::math::rayleigh_distribution<%1%>::rayleigh_distribution", sigma, &err, Policy());
+ detail::verify_sigma("boost::math::rayleigh_distribution<%1%>::rayleigh_distribution", l_sigma, &err, Policy());
} // rayleigh_distribution
RealType sigma()const
@@ -81,7 +81,7 @@ template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const rayleigh_distribution<RealType, Policy>& /*dist*/)
{ // Range of permissible values for random variable x.
using boost::math::tools::max_value;
- return std::pair<RealType, RealType>(static_cast<RealType>(0), max_value<RealType>());
+ return std::pair<RealType, RealType>(static_cast<RealType>(0), std::numeric_limits<RealType>::has_infinity ? std::numeric_limits<RealType>::infinity() : max_value<RealType>());
}
template <class RealType, class Policy>
@@ -108,6 +108,10 @@ inline RealType pdf(const rayleigh_distribution<RealType, Policy>& dist, const R
{
return result;
}
+ if((boost::math::isinf)(x))
+ {
+ return 0;
+ }
RealType sigmasqr = sigma * sigma;
result = x * (exp(-(x * x) / ( 2 * sigmasqr))) / sigmasqr;
return result;
@@ -175,7 +179,11 @@ inline RealType cdf(const complemented2_type<rayleigh_distribution<RealType, Pol
{
return result;
}
- result = exp(-x * x / ( 2 * sigma * sigma));
+ RealType ea = x * x / (2 * sigma * sigma);
+ // Fix for VC11/12 x64 bug in exp(float):
+ if (ea >= tools::max_value<RealType>())
+ return 0;
+ result = exp(-ea);
return result;
} // cdf complement
diff --git a/boost/math/distributions/skew_normal.hpp b/boost/math/distributions/skew_normal.hpp
index 58526defdb..98348e59bb 100644
--- a/boost/math/distributions/skew_normal.hpp
+++ b/boost/math/distributions/skew_normal.hpp
@@ -1,4 +1,4 @@
-// (C) Benjamin Sobotta 2012
+// Copyright Benjamin Sobotta 2012
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
@@ -58,15 +58,15 @@ namespace boost{ namespace math{
typedef RealType value_type;
typedef Policy policy_type;
- skew_normal_distribution(RealType location = 0, RealType scale = 1, RealType shape = 0)
- : location_(location), scale_(scale), shape_(shape)
+ skew_normal_distribution(RealType l_location = 0, RealType l_scale = 1, RealType l_shape = 0)
+ : location_(l_location), scale_(l_scale), shape_(l_shape)
{ // Default is a 'standard' normal distribution N01. (shape=0 results in the normal distribution with no skew)
static const char* function = "boost::math::skew_normal_distribution<%1%>::skew_normal_distribution";
RealType result;
- detail::check_scale(function, scale, &result, Policy());
- detail::check_location(function, location, &result, Policy());
- detail::check_skew_normal_shape(function, shape, &result, Policy());
+ detail::check_scale(function, l_scale, &result, Policy());
+ detail::check_location(function, l_location, &result, Policy());
+ detail::check_skew_normal_shape(function, l_shape, &result, Policy());
}
RealType location()const
@@ -100,7 +100,9 @@ namespace boost{ namespace math{
inline const std::pair<RealType, RealType> range(const skew_normal_distribution<RealType, Policy>& /*dist*/)
{ // Range of permissible values for random variable x.
using boost::math::tools::max_value;
- return std::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>()); // - to + max value.
+ return std::pair<RealType, RealType>(
+ std::numeric_limits<RealType>::has_infinity ? -std::numeric_limits<RealType>::infinity() : -max_value<RealType>(),
+ std::numeric_limits<RealType>::has_infinity ? std::numeric_limits<RealType>::infinity() : max_value<RealType>()); // - to + max value.
}
template <class RealType, class Policy>
@@ -476,50 +478,51 @@ namespace boost{ namespace math{
// 21 elements
static const RealType shapes[] = {
0.0,
- 1.000000000000000e-004,
- 2.069138081114790e-004,
- 4.281332398719396e-004,
- 8.858667904100824e-004,
- 1.832980710832436e-003,
- 3.792690190732250e-003,
- 7.847599703514606e-003,
- 1.623776739188722e-002,
- 3.359818286283781e-002,
- 6.951927961775606e-002,
- 1.438449888287663e-001,
- 2.976351441631319e-001,
- 6.158482110660261e-001,
- 1.274274985703135e+000,
- 2.636650898730361e+000,
- 5.455594781168514e+000,
- 1.128837891684688e+001,
- 2.335721469090121e+001,
- 4.832930238571753e+001,
- 1.000000000000000e+002};
+ static_cast<RealType>(1.000000000000000e-004),
+ static_cast<RealType>(2.069138081114790e-004),
+ static_cast<RealType>(4.281332398719396e-004),
+ static_cast<RealType>(8.858667904100824e-004),
+ static_cast<RealType>(1.832980710832436e-003),
+ static_cast<RealType>(3.792690190732250e-003),
+ static_cast<RealType>(7.847599703514606e-003),
+ static_cast<RealType>(1.623776739188722e-002),
+ static_cast<RealType>(3.359818286283781e-002),
+ static_cast<RealType>(6.951927961775606e-002),
+ static_cast<RealType>(1.438449888287663e-001),
+ static_cast<RealType>(2.976351441631319e-001),
+ static_cast<RealType>(6.158482110660261e-001),
+ static_cast<RealType>(1.274274985703135e+000),
+ static_cast<RealType>(2.636650898730361e+000),
+ static_cast<RealType>(5.455594781168514e+000),
+ static_cast<RealType>(1.128837891684688e+001),
+ static_cast<RealType>(2.335721469090121e+001),
+ static_cast<RealType>(4.832930238571753e+001),
+ static_cast<RealType>(1.000000000000000e+002)
+ };
// 21 elements
static const RealType guess[] = {
0.0,
- 5.000050000525391e-005,
- 1.500015000148736e-004,
- 3.500035000350010e-004,
- 7.500075000752560e-004,
- 1.450014500145258e-003,
- 3.050030500305390e-003,
- 6.250062500624765e-003,
- 1.295012950129504e-002,
- 2.675026750267495e-002,
- 5.525055250552491e-002,
- 1.132511325113255e-001,
- 2.249522495224952e-001,
- 3.992539925399257e-001,
- 5.353553535535358e-001,
- 4.954549545495457e-001,
- 3.524535245352451e-001,
- 2.182521825218249e-001,
- 1.256512565125654e-001,
- 6.945069450694508e-002,
- 3.735037350373460e-002
+ static_cast<RealType>(5.000050000525391e-005),
+ static_cast<RealType>(1.500015000148736e-004),
+ static_cast<RealType>(3.500035000350010e-004),
+ static_cast<RealType>(7.500075000752560e-004),
+ static_cast<RealType>(1.450014500145258e-003),
+ static_cast<RealType>(3.050030500305390e-003),
+ static_cast<RealType>(6.250062500624765e-003),
+ static_cast<RealType>(1.295012950129504e-002),
+ static_cast<RealType>(2.675026750267495e-002),
+ static_cast<RealType>(5.525055250552491e-002),
+ static_cast<RealType>(1.132511325113255e-001),
+ static_cast<RealType>(2.249522495224952e-001),
+ static_cast<RealType>(3.992539925399257e-001),
+ static_cast<RealType>(5.353553535535358e-001),
+ static_cast<RealType>(4.954549545495457e-001),
+ static_cast<RealType>(3.524535245352451e-001),
+ static_cast<RealType>(2.182521825218249e-001),
+ static_cast<RealType>(1.256512565125654e-001),
+ static_cast<RealType>(6.945069450694508e-002),
+ static_cast<RealType>(3.735037350373460e-002)
};
const RealType* result_ptr = std::lower_bound(shapes, shapes+21, shape);
@@ -532,7 +535,7 @@ namespace boost{ namespace math{
// TODO: make the search bounds smarter, depending on the shape parameter
RealType search_min = 0; // below zero was caught above
- RealType search_max = 0.55; // will never go above 0.55
+ RealType search_max = 0.55f; // will never go above 0.55
// refine
if(d < static_cast<diff_type>(21)) // shape smaller 100
@@ -544,7 +547,7 @@ namespace boost{ namespace math{
}
else // shape greater 100
{
- result = 1e-4;
+ result = 1e-4f;
search_max = guess[19]; // set 19 instead of 20 to have a safety margin because the table may not be exact @ shape=100
}
@@ -642,23 +645,23 @@ namespace boost{ namespace math{
if(false == detail::check_probability(function, p, &result, Policy()))
return result;
- // compute initial guess via Cornish-Fisher expansion
+ // Compute initial guess via Cornish-Fisher expansion.
RealType x = -boost::math::erfc_inv(2 * p, Policy()) * constants::root_two<RealType>();
- // avoid unnecessary computations if there is no skew
+ // Avoid unnecessary computations if there is no skew.
if(shape != 0)
{
const RealType skew = skewness(dist);
const RealType exk = kurtosis_excess(dist);
x = x + (x*x-static_cast<RealType>(1))*skew/static_cast<RealType>(6)
- + x*(x*x-static_cast<RealType>(3))*exk/static_cast<RealType>(24)
- - x*(static_cast<RealType>(2)*x*x-static_cast<RealType>(5))*skew*skew/static_cast<RealType>(36);
+ + x*(x*x-static_cast<RealType>(3))*exk/static_cast<RealType>(24)
+ - x*(static_cast<RealType>(2)*x*x-static_cast<RealType>(5))*skew*skew/static_cast<RealType>(36);
} // if(shape != 0)
result = standard_deviation(dist)*x+mean(dist);
- // handle special case of non-skew normal distribution
+ // handle special case of non-skew normal distribution.
if(shape == 0)
return result;
@@ -678,7 +681,7 @@ namespace boost{ namespace math{
template <class RealType, class Policy>
inline RealType quantile(const complemented2_type<skew_normal_distribution<RealType, Policy>, RealType>& c)
- {
+ {
const RealType scale = c.dist.scale();
const RealType location = c.dist.location();
const RealType shape = c.dist.shape();
diff --git a/boost/math/distributions/students_t.hpp b/boost/math/distributions/students_t.hpp
index 38df1b6287..0d6a646691 100644
--- a/boost/math/distributions/students_t.hpp
+++ b/boost/math/distributions/students_t.hpp
@@ -1,5 +1,7 @@
// Copyright John Maddock 2006.
-// Copyright Paul A. Bristow 2006.
+// Copyright Paul A. Bristow 2006, 2012.
+// Copyright Thomas Mang 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)
@@ -14,6 +16,7 @@
#include <boost/math/special_functions/beta.hpp> // for ibeta(a, b, x).
#include <boost/math/distributions/complement.hpp>
#include <boost/math/distributions/detail/common_error_handling.hpp>
+#include <boost/math/distributions/normal.hpp>
#include <utility>
@@ -31,16 +34,16 @@ public:
typedef RealType value_type;
typedef Policy policy_type;
- students_t_distribution(RealType i) : m_df(i)
+ students_t_distribution(RealType df) : df_(df)
{ // Constructor.
RealType result;
- detail::check_df(
- "boost::math::students_t_distribution<%1%>::students_t_distribution", m_df, &result, Policy());
+ detail::check_df_gt0_to_inf( // Checks that df > 0 or df == inf.
+ "boost::math::students_t_distribution<%1%>::students_t_distribution", df_, &result, Policy());
} // students_t_distribution
RealType degrees_of_freedom()const
{
- return m_df;
+ return df_;
}
// Parameter estimation:
@@ -52,17 +55,16 @@ public:
RealType hint = 100);
private:
- //
- // Data members:
- //
- RealType m_df; // degrees of freedom are a real number.
+ // Data member:
+ RealType df_; // degrees of freedom is a real number or +infinity.
};
-typedef students_t_distribution<double> students_t;
+typedef students_t_distribution<double> students_t; // Convenience typedef for double version.
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const students_t_distribution<RealType, Policy>& /*dist*/)
{ // Range of permissible values for random variable x.
+ // NOT including infinity.
using boost::math::tools::max_value;
return std::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>());
}
@@ -76,77 +78,124 @@ inline const std::pair<RealType, RealType> support(const students_t_distribution
}
template <class RealType, class Policy>
-inline RealType pdf(const students_t_distribution<RealType, Policy>& dist, const RealType& t)
+inline RealType pdf(const students_t_distribution<RealType, Policy>& dist, const RealType& x)
{
BOOST_FPU_EXCEPTION_GUARD
- BOOST_MATH_STD_USING // for ADL of std functions
+ BOOST_MATH_STD_USING // for ADL of std functions.
- RealType degrees_of_freedom = dist.degrees_of_freedom();
- // Error check:
RealType error_result;
- if(false == detail::check_df(
- "boost::math::pdf(const students_t_distribution<%1%>&, %1%)", degrees_of_freedom, &error_result, Policy()))
+ if(false == detail::check_x(
+ "boost::math::pdf(const students_t_distribution<%1%>&, %1%)", x, &error_result, Policy()))
+ return error_result;
+ RealType df = dist.degrees_of_freedom();
+ if(false == detail::check_df_gt0_to_inf( // Check that df > 0 or == +infinity.
+ "boost::math::pdf(const students_t_distribution<%1%>&, %1%)", df, &error_result, Policy()))
return error_result;
- // Might conceivably permit df = +infinity and use normal distribution.
+
RealType result;
- RealType basem1 = t * t / degrees_of_freedom;
- if(basem1 < 0.125)
- {
- result = exp(-boost::math::log1p(basem1, Policy()) * (1+degrees_of_freedom) / 2);
+ if ((boost::math::isinf)(x))
+ { // +infinity.
+ normal_distribution<RealType, Policy> n(0, 1);
+ result = pdf(n, x);
+ return result;
+ }
+ RealType limit = policies::get_epsilon<RealType, Policy>();
+ // Use policies so that if policy requests lower precision,
+ // then get the normal distribution approximation earlier.
+ limit = static_cast<RealType>(1) / limit; // 1/eps
+ // for 64-bit double 1/eps = 4503599627370496
+ if (df > limit)
+ { // Special case for really big degrees_of_freedom > 1 / eps
+ // - use normal distribution which is much faster and more accurate.
+ normal_distribution<RealType, Policy> n(0, 1);
+ result = pdf(n, x);
}
else
- {
- result = pow(1 / (1 + basem1), (degrees_of_freedom + 1) / 2);
+ { //
+ RealType basem1 = x * x / df;
+ if(basem1 < 0.125)
+ {
+ result = exp(-boost::math::log1p(basem1, Policy()) * (1+df) / 2);
+ }
+ else
+ {
+ result = pow(1 / (1 + basem1), (df + 1) / 2);
+ }
+ result /= sqrt(df) * boost::math::beta(df / 2, RealType(0.5f), Policy());
}
- result /= sqrt(degrees_of_freedom) * boost::math::beta(degrees_of_freedom / 2, RealType(0.5f), Policy());
return result;
} // pdf
template <class RealType, class Policy>
-inline RealType cdf(const students_t_distribution<RealType, Policy>& dist, const RealType& t)
+inline RealType cdf(const students_t_distribution<RealType, Policy>& dist, const RealType& x)
{
- RealType degrees_of_freedom = dist.degrees_of_freedom();
- // Error check:
RealType error_result;
- if(false == detail::check_df(
- "boost::math::cdf(const students_t_distribution<%1%>&, %1%)", degrees_of_freedom, &error_result, Policy()))
+ if(false == detail::check_x(
+ "boost::math::pdf(const students_t_distribution<%1%>&, %1%)", x, &error_result, Policy()))
return error_result;
+ RealType df = dist.degrees_of_freedom();
+ // Error check:
- if (t == 0)
- {
- return 0.5;
+ if(false == detail::check_df_gt0_to_inf( // Check that df > 0 or == +infinity.
+ "boost::math::cdf(const students_t_distribution<%1%>&, %1%)", df, &error_result, Policy()))
+ return error_result;
+
+ if (x == 0)
+ { // Special case with exact result.
+ return static_cast<RealType>(0.5);
}
- //
- // Calculate probability of Student's t using the incomplete beta function.
- // probability = ibeta(degrees_of_freedom / 2, 1/2, degrees_of_freedom / (degrees_of_freedom + t*t))
- //
- // However when t is small compared to the degrees of freedom, that formula
- // suffers from rounding error, use the identity formula to work around
- // the problem:
- //
- // I[x](a,b) = 1 - I[1-x](b,a)
- //
- // and:
- //
- // x = df / (df + t^2)
- //
- // so:
- //
- // 1 - x = t^2 / (df + t^2)
- //
- RealType t2 = t * t;
- RealType probability;
- if(degrees_of_freedom > 2 * t2)
- {
- RealType z = t2 / (degrees_of_freedom + t2);
- probability = ibetac(static_cast<RealType>(0.5), degrees_of_freedom / 2, z, Policy()) / 2;
+ if ((boost::math::isinf)(x))
+ { // +infinity.
+ normal_distribution<RealType, Policy> n(0, 1);
+ RealType result = cdf(n, x);
+ return result;
}
- else
- {
- RealType z = degrees_of_freedom / (degrees_of_freedom + t2);
- probability = ibeta(degrees_of_freedom / 2, static_cast<RealType>(0.5), z, Policy()) / 2;
+ RealType limit = policies::get_epsilon<RealType, Policy>();
+ // Use policies so that if policy requests lower precision,
+ // then get the normal distribution approximation earlier.
+ limit = static_cast<RealType>(1) / limit; // 1/eps
+ // for 64-bit double 1/eps = 4503599627370496
+ if (df > limit)
+ { // Special case for really big degrees_of_freedom > 1 / eps (perhaps infinite?)
+ // - use normal distribution which is much faster and more accurate.
+ normal_distribution<RealType, Policy> n(0, 1);
+ RealType result = cdf(n, x);
+ return result;
}
- return (t > 0 ? 1 - probability : probability);
+ else
+ { // normal df case.
+ //
+ // Calculate probability of Student's t using the incomplete beta function.
+ // probability = ibeta(degrees_of_freedom / 2, 1/2, degrees_of_freedom / (degrees_of_freedom + t*t))
+ //
+ // However when t is small compared to the degrees of freedom, that formula
+ // suffers from rounding error, use the identity formula to work around
+ // the problem:
+ //
+ // I[x](a,b) = 1 - I[1-x](b,a)
+ //
+ // and:
+ //
+ // x = df / (df + t^2)
+ //
+ // so:
+ //
+ // 1 - x = t^2 / (df + t^2)
+ //
+ RealType x2 = x * x;
+ RealType probability;
+ if(df > 2 * x2)
+ {
+ RealType z = x2 / (df + x2);
+ probability = ibetac(static_cast<RealType>(0.5), df / 2, z, Policy()) / 2;
+ }
+ else
+ {
+ RealType z = df / (df + x2);
+ probability = ibeta(df / 2, static_cast<RealType>(0.5), z, Policy()) / 2;
+ }
+ return (x > 0 ? 1 - probability : probability);
+ }
} // cdf
template <class RealType, class Policy>
@@ -155,31 +204,27 @@ inline RealType quantile(const students_t_distribution<RealType, Policy>& dist,
BOOST_MATH_STD_USING // for ADL of std functions
//
// Obtain parameters:
- //
- RealType degrees_of_freedom = dist.degrees_of_freedom();
RealType probability = p;
- //
+
// Check for domain errors:
- //
+ RealType df = dist.degrees_of_freedom();
static const char* function = "boost::math::quantile(const students_t_distribution<%1%>&, %1%)";
RealType error_result;
- if(false == detail::check_df(
- function, degrees_of_freedom, &error_result, Policy())
- && detail::check_probability(function, probability, &error_result, Policy()))
+ if(false == (detail::check_df_gt0_to_inf( // Check that df > 0 or == +infinity.
+ function, df, &error_result, Policy())
+ && detail::check_probability(function, probability, &error_result, Policy())))
return error_result;
-
// Special cases, regardless of degrees_of_freedom.
if (probability == 0)
return -policies::raise_overflow_error<RealType>(function, 0, Policy());
if (probability == 1)
return policies::raise_overflow_error<RealType>(function, 0, Policy());
if (probability == static_cast<RealType>(0.5))
- return 0;
- //
- // This next block is disabled in favour of a faster method than
- // incomplete beta inverse, code retained for future reference:
+ return 0; //
//
#if 0
+ // This next block is disabled in favour of a faster method than
+ // incomplete beta inverse, but code retained for future reference:
//
// Calculate quantile of Student's t using the incomplete beta function inverse:
//
@@ -205,7 +250,7 @@ inline RealType quantile(const students_t_distribution<RealType, Policy>& dist,
// and a couple of epsilon at double precision and in the central
// region where most use cases will occur...
//
- return boost::math::detail::fast_students_t_quantile(degrees_of_freedom, probability, Policy());
+ return boost::math::detail::fast_students_t_quantile(df, probability, Policy());
} // quantile
template <class RealType, class Policy>
@@ -236,7 +281,9 @@ struct sample_size_func
RealType operator()(const RealType& df)
{
if(df <= tools::min_value<RealType>())
+ { //
return 1;
+ }
students_t_distribution<RealType, Policy> t(df);
RealType qa = quantile(complement(t, alpha));
RealType qb = quantile(complement(t, beta));
@@ -279,7 +326,7 @@ RealType students_t_distribution<RealType, Policy>::find_degrees_of_freedom(
RealType result = r.first + (r.second - r.first) / 2;
if(max_iter >= policies::get_max_root_iterations<Policy>())
{
- policies::raise_evaluation_error<RealType>(function, "Unable to locate solution in a reasonable time:"
+ return policies::raise_evaluation_error<RealType>(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());
}
@@ -287,76 +334,145 @@ RealType students_t_distribution<RealType, Policy>::find_degrees_of_freedom(
}
template <class RealType, class Policy>
-inline RealType mean(const students_t_distribution<RealType, Policy>& )
+inline RealType mode(const students_t_distribution<RealType, Policy>& /*dist*/)
{
- return 0;
+ // Assume no checks on degrees of freedom are useful (unlike mean).
+ return 0; // Always zero by definition.
}
template <class RealType, class Policy>
-inline RealType variance(const students_t_distribution<RealType, Policy>& dist)
+inline RealType median(const students_t_distribution<RealType, Policy>& /*dist*/)
{
- // Error check:
- RealType error_result;
- if(false == detail::check_df(
- "boost::math::variance(students_t_distribution<%1%> const&, %1%)", dist.degrees_of_freedom(), &error_result, Policy()))
- return error_result;
-
- RealType v = dist.degrees_of_freedom();
- return v / (v - 2);
+ // Assume no checks on degrees of freedom are useful (unlike mean).
+ return 0; // Always zero by definition.
}
+// See section 5.1 on moments at http://en.wikipedia.org/wiki/Student%27s_t-distribution
+
template <class RealType, class Policy>
-inline RealType mode(const students_t_distribution<RealType, Policy>& /*dist*/)
-{
+inline RealType mean(const students_t_distribution<RealType, Policy>& dist)
+{ // Revised for https://svn.boost.org/trac/boost/ticket/7177
+ RealType df = dist.degrees_of_freedom();
+ if(((boost::math::isnan)(df)) || (df <= 1) )
+ { // mean is undefined for moment <= 1!
+ return policies::raise_domain_error<RealType>(
+ "boost::math::mean(students_t_distribution<%1%> const&, %1%)",
+ "Mean is undefined for degrees of freedom < 1 but got %1%.", df, Policy());
+ return std::numeric_limits<RealType>::quiet_NaN();
+ }
return 0;
-}
+} // mean
template <class RealType, class Policy>
-inline RealType median(const students_t_distribution<RealType, Policy>& /*dist*/)
-{
- return 0;
-}
+inline RealType variance(const students_t_distribution<RealType, Policy>& dist)
+{ // http://en.wikipedia.org/wiki/Student%27s_t-distribution
+ // Revised for https://svn.boost.org/trac/boost/ticket/7177
+ RealType df = dist.degrees_of_freedom();
+ if ((boost::math::isnan)(df) || (df <= 2))
+ { // NaN or undefined for <= 2.
+ return policies::raise_domain_error<RealType>(
+ "boost::math::variance(students_t_distribution<%1%> const&, %1%)",
+ "variance is undefined for degrees of freedom <= 2, but got %1%.",
+ df, Policy());
+ return std::numeric_limits<RealType>::quiet_NaN(); // Undefined.
+ }
+ if ((boost::math::isinf)(df))
+ { // +infinity.
+ return 1;
+ }
+ RealType limit = policies::get_epsilon<RealType, Policy>();
+ // Use policies so that if policy requests lower precision,
+ // then get the normal distribution approximation earlier.
+ limit = static_cast<RealType>(1) / limit; // 1/eps
+ // for 64-bit double 1/eps = 4503599627370496
+ if (df > limit)
+ { // Special case for really big degrees_of_freedom > 1 / eps.
+ return 1;
+ }
+ else
+ {
+ return df / (df - 2);
+ }
+} // variance
template <class RealType, class Policy>
inline RealType skewness(const students_t_distribution<RealType, Policy>& dist)
{
- if(dist.degrees_of_freedom() <= 3)
- {
- policies::raise_domain_error<RealType>(
+ RealType df = dist.degrees_of_freedom();
+ if( ((boost::math::isnan)(df)) || (dist.degrees_of_freedom() <= 3))
+ { // Undefined for moment k = 3.
+ return policies::raise_domain_error<RealType>(
"boost::math::skewness(students_t_distribution<%1%> const&, %1%)",
"Skewness is undefined for degrees of freedom <= 3, but got %1%.",
dist.degrees_of_freedom(), Policy());
+ return std::numeric_limits<RealType>::quiet_NaN();
}
- return 0;
-}
+ return 0; // For all valid df, including infinity.
+} // skewness
template <class RealType, class Policy>
inline RealType kurtosis(const students_t_distribution<RealType, Policy>& dist)
{
RealType df = dist.degrees_of_freedom();
- if(df <= 3)
+ if(((boost::math::isnan)(df)) || (df <= 4))
+ { // Undefined or infinity for moment k = 4.
+ return policies::raise_domain_error<RealType>(
+ "boost::math::kurtosis(students_t_distribution<%1%> const&, %1%)",
+ "Kurtosis is undefined for degrees of freedom <= 4, but got %1%.",
+ df, Policy());
+ return std::numeric_limits<RealType>::quiet_NaN(); // Undefined.
+ }
+ if ((boost::math::isinf)(df))
+ { // +infinity.
+ return 3;
+ }
+ RealType limit = policies::get_epsilon<RealType, Policy>();
+ // Use policies so that if policy requests lower precision,
+ // then get the normal distribution approximation earlier.
+ limit = static_cast<RealType>(1) / limit; // 1/eps
+ // for 64-bit double 1/eps = 4503599627370496
+ if (df > limit)
+ { // Special case for really big degrees_of_freedom > 1 / eps.
+ return 3;
+ }
+ else
{
- policies::raise_domain_error<RealType>(
- "boost::math::kurtosis(students_t_distribution<%1%> const&, %1%)",
- "Skewness is undefined for degrees of freedom <= 3, but got %1%.",
- df, Policy());
+ //return 3 * (df - 2) / (df - 4); re-arranged to
+ return 6 / (df - 4) + 3;
}
- return 3 * (df - 2) / (df - 4);
-}
+} // kurtosis
template <class RealType, class Policy>
inline RealType kurtosis_excess(const students_t_distribution<RealType, Policy>& dist)
{
// see http://mathworld.wolfram.com/Kurtosis.html
+
RealType df = dist.degrees_of_freedom();
- if(df <= 3)
+ if(((boost::math::isnan)(df)) || (df <= 4))
+ { // Undefined or infinity for moment k = 4.
+ return policies::raise_domain_error<RealType>(
+ "boost::math::kurtosis_excess(students_t_distribution<%1%> const&, %1%)",
+ "Kurtosis_excess is undefined for degrees of freedom <= 4, but got %1%.",
+ df, Policy());
+ return std::numeric_limits<RealType>::quiet_NaN(); // Undefined.
+ }
+ if ((boost::math::isinf)(df))
+ { // +infinity.
+ return 0;
+ }
+ RealType limit = policies::get_epsilon<RealType, Policy>();
+ // Use policies so that if policy requests lower precision,
+ // then get the normal distribution approximation earlier.
+ limit = static_cast<RealType>(1) / limit; // 1/eps
+ // for 64-bit double 1/eps = 4503599627370496
+ if (df > limit)
+ { // Special case for really big degrees_of_freedom > 1 / eps.
+ return 0;
+ }
+ else
{
- policies::raise_domain_error<RealType>(
- "boost::math::kurtosis_excess(students_t_distribution<%1%> const&, %1%)",
- "Skewness is undefined for degrees of freedom <= 3, but got %1%.",
- df, Policy());
+ return 6 / (df - 4);
}
- return 6 / (df - 4);
}
} // namespace math
diff --git a/boost/math/distributions/triangular.hpp b/boost/math/distributions/triangular.hpp
index 735d20235c..78ef0df744 100644
--- a/boost/math/distributions/triangular.hpp
+++ b/boost/math/distributions/triangular.hpp
@@ -147,14 +147,14 @@ namespace boost{ namespace math
typedef RealType value_type;
typedef Policy policy_type;
- triangular_distribution(RealType lower = -1, RealType mode = 0, RealType upper = 1)
- : m_lower(lower), m_mode(mode), m_upper(upper) // Constructor.
+ triangular_distribution(RealType l_lower = -1, RealType l_mode = 0, RealType l_upper = 1)
+ : m_lower(l_lower), m_mode(l_mode), m_upper(l_upper) // Constructor.
{ // Evans says 'standard triangular' is lower 0, mode 1/2, upper 1,
// has median sqrt(c/2) for c <=1/2 and 1 - sqrt(1-c)/2 for c >= 1/2
// But this -1, 0, 1 is more useful in most applications to approximate normal distribution,
// where the central value is the most likely and deviations either side equally likely.
RealType result;
- detail::check_triangular("boost::math::triangular_distribution<%1%>::triangular_distribution",lower, mode, upper, &result, Policy());
+ detail::check_triangular("boost::math::triangular_distribution<%1%>::triangular_distribution",l_lower, l_mode, l_upper, &result, Policy());
}
// Accessor functions.
RealType lower()const
diff --git a/boost/math/distributions/uniform.hpp b/boost/math/distributions/uniform.hpp
index 3645b2039b..a20597a66a 100644
--- a/boost/math/distributions/uniform.hpp
+++ b/boost/math/distributions/uniform.hpp
@@ -116,11 +116,11 @@ namespace boost{ namespace math
typedef RealType value_type;
typedef Policy policy_type;
- uniform_distribution(RealType lower = 0, RealType upper = 1) // Constructor.
- : m_lower(lower), m_upper(upper) // Default is standard uniform distribution.
+ uniform_distribution(RealType l_lower = 0, RealType l_upper = 1) // Constructor.
+ : m_lower(l_lower), m_upper(l_upper) // Default is standard uniform distribution.
{
RealType result;
- detail::check_uniform("boost::math::uniform_distribution<%1%>::uniform_distribution", lower, upper, &result, Policy());
+ detail::check_uniform("boost::math::uniform_distribution<%1%>::uniform_distribution", l_lower, l_upper, &result, Policy());
}
// Accessor functions.
RealType lower()const
diff --git a/boost/math/distributions/weibull.hpp b/boost/math/distributions/weibull.hpp
index 6b5c7db34c..da1189090c 100644
--- a/boost/math/distributions/weibull.hpp
+++ b/boost/math/distributions/weibull.hpp
@@ -28,7 +28,7 @@ inline bool check_weibull_shape(
RealType shape,
RealType* result, const Policy& pol)
{
- if((shape < 0) || !(boost::math::isfinite)(shape))
+ if((shape <= 0) || !(boost::math::isfinite)(shape))
{
*result = policies::raise_domain_error<RealType>(
function,
@@ -73,11 +73,11 @@ public:
typedef RealType value_type;
typedef Policy policy_type;
- weibull_distribution(RealType shape, RealType scale = 1)
- : m_shape(shape), m_scale(scale)
+ weibull_distribution(RealType l_shape, RealType l_scale = 1)
+ : m_shape(l_shape), m_scale(l_scale)
{
RealType result;
- detail::check_weibull("boost::math::weibull_distribution<%1%>::weibull_distribution", scale, shape, &result, Policy());
+ detail::check_weibull("boost::math::weibull_distribution<%1%>::weibull_distribution", l_scale, l_shape, &result, Policy());
}
RealType shape()const
@@ -133,11 +133,19 @@ inline RealType pdf(const weibull_distribution<RealType, Policy>& dist, const Re
return result;
if(x == 0)
- { // Special case, but x == min, pdf = 1 for shape = 1,
- return 0;
+ {
+ if(shape == 1)
+ {
+ return 1 / scale;
+ }
+ if(shape > 1)
+ {
+ return 0;
+ }
+ return policies::raise_overflow_error<RealType>(function, 0, Policy());
}
result = exp(-pow(x / scale, shape));
- result *= pow(x / scale, shape) * shape / x;
+ result *= pow(x / scale, shape - 1) * shape / scale;
return result;
}
diff --git a/boost/math/octonion.hpp b/boost/math/octonion.hpp
index ce1b66f1da..fba9aff273 100644
--- a/boost/math/octonion.hpp
+++ b/boost/math/octonion.hpp
@@ -18,23 +18,6 @@ namespace boost
{
namespace math
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- // gcc 2.95.x uses expression templates for valarray calculations, but
- // the result is not conforming. We need BOOST_GET_VALARRAY to get an
- // actual valarray result when we need to call a member function
- #define BOOST_GET_VALARRAY(T,x) ::std::valarray<T>(x)
- // gcc 2.95.x has an "std::ios" class that is similar to
- // "std::ios_base", so we just use a #define
- #define BOOST_IOS_BASE ::std::ios
- // gcc 2.x ignores function scope using declarations,
- // put them in the scope of the enclosing namespace instead:
- using ::std::valarray;
- using ::std::sqrt;
- using ::std::cos;
- using ::std::sin;
- using ::std::exp;
- using ::std::cosh;
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
#define BOOST_OCTONION_ACCESSOR_GENERATOR(type) \
type real() const \
@@ -958,48 +941,7 @@ namespace boost
return(*this); \
}
-#if defined(__GNUC__) && (__GNUC__ < 3)
- #define BOOST_OCTONION_MEMBER_DIV_GENERATOR_2(type) \
- octonion<type> & operator /= (::std::complex<type> const & rhs) \
- { \
- using ::std::valarray; \
- \
- valarray<type> tr(2); \
- \
- tr[0] = rhs.real(); \
- tr[1] = rhs.imag(); \
- \
- type mixam = (BOOST_GET_VALARRAY(type,static_cast<type>(1)/abs(tr)).max)(); \
- \
- tr *= mixam; \
- \
- valarray<type> tt(8); \
- \
- tt[0] = +a*tr[0]-b*tr[1]; \
- tt[1] = -a*tr[1]+b*tr[0]; \
- tt[2] = +c*tr[0]-d*tr[1]; \
- tt[3] = +c*tr[1]+d*tr[0]; \
- tt[4] = +e*tr[0]-f*tr[1]; \
- tt[5] = +e*tr[1]+f*tr[0]; \
- tt[6] = +g*tr[0]+h*tr[1]; \
- tt[7] = +g*tr[1]+h*tr[0]; \
- \
- tr *= tr; \
- \
- tt *= (mixam/tr.sum()); \
- \
- a = tt[0]; \
- b = tt[1]; \
- c = tt[2]; \
- d = tt[3]; \
- e = tt[4]; \
- f = tt[5]; \
- g = tt[6]; \
- h = tt[7]; \
- \
- return(*this); \
- }
-#elif defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
+#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
#define BOOST_OCTONION_MEMBER_DIV_GENERATOR_2(type) \
octonion<type> & operator /= (::std::complex<type> const & rhs) \
{ \
@@ -1082,52 +1024,9 @@ namespace boost
\
return(*this); \
}
-#endif /* defined(__GNUC__) && (__GNUC__ < 3) */ /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
+#endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
-#if defined(__GNUC__) && (__GNUC__ < 3)
- #define BOOST_OCTONION_MEMBER_DIV_GENERATOR_3(type) \
- octonion<type> & operator /= (::boost::math::quaternion<type> const & rhs) \
- { \
- using ::std::valarray; \
- \
- valarray<type> tr(4); \
- \
- tr[0] = static_cast<type>(rhs.R_component_1()); \
- tr[1] = static_cast<type>(rhs.R_component_2()); \
- tr[2] = static_cast<type>(rhs.R_component_3()); \
- tr[3] = static_cast<type>(rhs.R_component_4()); \
- \
- type mixam = (BOOST_GET_VALARRAY(type,static_cast<type>(1)/abs(tr)).max)();\
- \
- tr *= mixam; \
- \
- valarray<type> tt(8); \
- \
- tt[0] = +a*tr[0]+b*tr[1]+c*tr[2]+d*tr[3]; \
- tt[1] = -a*tr[1]+b*tr[0]-c*tr[3]+d*tr[2]; \
- tt[2] = -a*tr[2]+b*tr[3]+c*tr[0]-d*tr[1]; \
- tt[3] = -a*tr[3]-b*tr[2]+c*tr[1]+d*tr[0]; \
- tt[4] = +e*tr[0]-f*tr[1]-g*tr[2]-h*tr[3]; \
- tt[5] = +e*tr[1]+f*tr[0]+g*tr[3]-h*tr[2]; \
- tt[6] = +e*tr[2]-f*tr[3]+g*tr[0]+h*tr[1]; \
- tt[7] = +e*tr[3]+f*tr[2]-g*tr[1]+h*tr[0]; \
- \
- tr *= tr; \
- \
- tt *= (mixam/tr.sum()); \
- \
- a = tt[0]; \
- b = tt[1]; \
- c = tt[2]; \
- d = tt[3]; \
- e = tt[4]; \
- f = tt[5]; \
- g = tt[6]; \
- h = tt[7]; \
- \
- return(*this); \
- }
-#elif defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
+#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
#define BOOST_OCTONION_MEMBER_DIV_GENERATOR_3(type) \
octonion<type> & operator /= (::boost::math::quaternion<type> const & rhs) \
{ \
@@ -1214,57 +1113,9 @@ namespace boost
\
return(*this); \
}
-#endif /* defined(__GNUC__) && (__GNUC__ < 3) */ /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
+#endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
-#if defined(__GNUC__) && (__GNUC__ < 3)
- #define BOOST_OCTONION_MEMBER_DIV_GENERATOR_4(type) \
- template<typename X> \
- octonion<type> & operator /= (octonion<X> const & rhs) \
- { \
- using ::std::valarray; \
- \
- valarray<type> tr(8); \
- \
- tr[0] = static_cast<type>(rhs.R_component_1()); \
- tr[1] = static_cast<type>(rhs.R_component_2()); \
- tr[2] = static_cast<type>(rhs.R_component_3()); \
- tr[3] = static_cast<type>(rhs.R_component_4()); \
- tr[4] = static_cast<type>(rhs.R_component_5()); \
- tr[5] = static_cast<type>(rhs.R_component_6()); \
- tr[6] = static_cast<type>(rhs.R_component_7()); \
- tr[7] = static_cast<type>(rhs.R_component_8()); \
- \
- type mixam = (BOOST_GET_VALARRAY(type,static_cast<type>(1)/abs(tr)).max)();\
- \
- tr *= mixam; \
- \
- valarray<type> tt(8); \
- \
- tt[0] = +a*tr[0]+b*tr[1]+c*tr[2]+d*tr[3]+e*tr[4]+f*tr[5]+g*tr[6]+h*tr[7]; \
- tt[1] = -a*tr[1]+b*tr[0]-c*tr[3]+d*tr[2]-e*tr[5]+f*tr[4]+g*tr[7]-h*tr[6]; \
- tt[2] = -a*tr[2]+b*tr[3]+c*tr[0]-d*tr[1]-e*tr[6]-f*tr[7]+g*tr[4]+h*tr[5]; \
- tt[3] = -a*tr[3]-b*tr[2]+c*tr[1]+d*tr[0]-e*tr[7]+f*tr[6]-g*tr[5]+h*tr[4]; \
- tt[4] = -a*tr[4]+b*tr[5]+c*tr[6]+d*tr[7]+e*tr[0]-f*tr[1]-g*tr[2]-h*tr[3]; \
- tt[5] = -a*tr[5]-b*tr[4]+c*tr[7]-d*tr[6]+e*tr[1]+f*tr[0]+g*tr[3]-h*tr[2]; \
- tt[6] = -a*tr[6]-b*tr[7]-c*tr[4]+d*tr[5]+e*tr[2]-f*tr[3]+g*tr[0]+h*tr[1]; \
- tt[7] = -a*tr[7]+b*tr[6]-c*tr[5]-d*tr[4]+e*tr[3]+f*tr[2]-g*tr[1]+h*tr[0]; \
- \
- tr *= tr; \
- \
- tt *= (mixam/tr.sum()); \
- \
- a = tt[0]; \
- b = tt[1]; \
- c = tt[2]; \
- d = tt[3]; \
- e = tt[4]; \
- f = tt[5]; \
- g = tt[6]; \
- h = tt[7]; \
- \
- return(*this); \
- }
-#elif defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
+#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
#define BOOST_OCTONION_MEMBER_DIV_GENERATOR_4(type) \
template<typename X> \
octonion<type> & operator /= (octonion<X> const & rhs) \
@@ -1361,7 +1212,7 @@ namespace boost
\
return(*this); \
}
-#endif /* defined(__GNUC__) && (__GNUC__ < 3) */ /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
+#endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
#define BOOST_OCTONION_MEMBER_ADD_GENERATOR(type) \
@@ -1856,21 +1707,10 @@ namespace boost
// Note: the default values in the constructors of the complex and quaternions make for
// a very complex and ambiguous situation; we have made choices to disambiguate.
-
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- template<typename T>
- ::std::istream & operator >> ( ::std::istream & is,
- octonion<T>& o)
-#else
template<typename T, typename charT, class traits>
::std::basic_istream<charT,traits> & operator >> ( ::std::basic_istream<charT,traits> & is,
octonion<T> & o)
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- typedef char charT;
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
-
#ifdef BOOST_NO_STD_LOCALE
#else
const ::std::ctype<charT> & ct = ::std::use_facet< ::std::ctype<charT> >(is.getloc());
@@ -1988,20 +1828,12 @@ namespace boost
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else if (cc ==',') // read "((u,"
@@ -2060,38 +1892,22 @@ namespace boost
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // read "((a"
@@ -2180,11 +1996,7 @@ namespace boost
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // read "((a),(c" or "((a),(e"
@@ -2267,29 +2079,17 @@ namespace boost
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else if (cc == ',') // read "((a),(c," or "((a),(e,"
@@ -2342,20 +2142,12 @@ namespace boost
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // read "((a),(c,d" or "((a),(e,f"
@@ -2438,29 +2230,17 @@ namespace boost
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else if (cc == ',') // read "((a),(e,f," (ambiguity resolution)
@@ -2501,11 +2281,7 @@ namespace boost
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else if (cc == ',') // read "((a),(e,f,g,"
@@ -2544,48 +2320,28 @@ namespace boost
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
}
@@ -2651,39 +2407,23 @@ namespace boost
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else if (cc ==',') // read "((a,"
@@ -2758,29 +2498,17 @@ namespace boost
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else
@@ -2869,11 +2597,7 @@ namespace boost
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // read "((a,b),(c" or "((a,b),(e"
@@ -2956,29 +2680,17 @@ namespace boost
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else if (cc == ',') // read "((a,b),(c," or "((a,b),(e,"
@@ -3033,20 +2745,12 @@ namespace boost
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // read "((a,b),(c,d" or "((a,b),(e,f"
@@ -3129,29 +2833,17 @@ namespace boost
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else if (cc == ',') // read "((a,b),(e,f," (ambiguity resolution)
@@ -3192,11 +2884,7 @@ namespace boost
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else if (cc == ',') // read "((a,b),(e,f,g,"
@@ -3235,67 +2923,39 @@ namespace boost
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else if (cc == ',') // read "((a,b,"
@@ -3354,20 +3014,12 @@ namespace boost
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else if (cc == ',') // read "((a,b,c,"
@@ -3426,57 +3078,33 @@ namespace boost
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
}
@@ -3554,11 +3182,7 @@ namespace boost
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // read "(a,(c" or "(a,(e"
@@ -3641,29 +3265,17 @@ namespace boost
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else if (cc == ',') // read "(a,(c," or "(a,(e,"
@@ -3718,20 +3330,12 @@ namespace boost
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // read "(a,(c,d" or "(a,(e,f"
@@ -3814,29 +3418,17 @@ namespace boost
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else if (cc == ',') // read "(a,(e,f," (ambiguity resolution)
@@ -3877,11 +3469,7 @@ namespace boost
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else if (cc == ',') // read "(a,(e,f,g,"
@@ -3920,48 +3508,28 @@ namespace boost
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
}
@@ -4047,20 +3615,12 @@ namespace boost
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // read "(a,b,c" or "(a,c,e"
@@ -4127,11 +3687,7 @@ namespace boost
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // read "(a,b,c,d" (ambiguity resolution)
@@ -4238,77 +3794,45 @@ namespace boost
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
}
@@ -4328,21 +3852,11 @@ namespace boost
}
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- template<typename T>
- ::std::ostream & operator << ( ::std::ostream & os,
- octonion<T> const & o)
-#else
template<typename T, typename charT, class traits>
::std::basic_ostream<charT,traits> & operator << ( ::std::basic_ostream<charT,traits> & os,
octonion<T> const & o)
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- ::std::ostringstream s;
-#else
::std::basic_ostringstream<charT,traits> s;
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
s.flags(os.flags());
#ifdef BOOST_NO_STD_LOCALE
@@ -4404,11 +3918,7 @@ namespace boost
BOOST_OCTONION_VALARRAY_LOADER
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- return((BOOST_GET_VALARRAY(T, abs(temp)).max)());
-#else
return((abs(temp).max)());
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
@@ -4421,11 +3931,7 @@ namespace boost
BOOST_OCTONION_VALARRAY_LOADER
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- return(BOOST_GET_VALARRAY(T, abs(temp)).sum());
-#else
return(abs(temp).sum());
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
@@ -4440,11 +3946,7 @@ namespace boost
BOOST_OCTONION_VALARRAY_LOADER
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- T maxim = (BOOST_GET_VALARRAY(T,abs(temp)).max)(); // overflow protection
-#else
T maxim = (abs(temp).max)(); // overflow protection
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
if (maxim == static_cast<T>(0))
{
@@ -4745,10 +4247,4 @@ namespace boost
}
}
-
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- #undef BOOST_GET_VALARRAY
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
-
-
#endif /* BOOST_OCTONION_HPP */
diff --git a/boost/math/policies/error_handling.hpp b/boost/math/policies/error_handling.hpp
index d4306c6006..674759006e 100644
--- a/boost/math/policies/error_handling.hpp
+++ b/boost/math/policies/error_handling.hpp
@@ -12,7 +12,7 @@
#include <iomanip>
#include <string>
#include <cerrno>
-#include <complex>
+#include <boost/config/no_tr1/complex.hpp>
#include <boost/config/no_tr1/cmath.hpp>
#include <stdexcept>
#include <boost/math/tools/config.hpp>
@@ -24,7 +24,7 @@
# pragma warning(disable: 4996) // _SCL_SECURE_NO_DEPRECATE
# pragma warning(disable: 4512) // assignment operator could not be generated.
// And warnings in error handling:
-# pragma warning(disable: 4702) // unreachable code
+# pragma warning(disable: 4702) // unreachable code.
// Note that this only occurs when the compiler can deduce code is unreachable,
// for example when policy macros are used to ignore errors rather than throw.
#endif
@@ -46,7 +46,7 @@ public:
namespace policies{
//
-// Forward declarations of user error handlers,
+// Forward declarations of user error handlers,
// it's up to the user to provide the definition of these:
//
template <class T>
@@ -70,7 +70,7 @@ namespace detail
{
//
// Helper function to avoid binding rvalue to non-const-reference,
-// in other words a warning suppression mechansim:
+// in other words a warning suppression mechanism:
//
template <class Formatter, class Group>
inline std::string do_format(Formatter f, const Group& g)
@@ -78,6 +78,27 @@ inline std::string do_format(Formatter f, const Group& g)
return (f % g).str();
}
+template <class T>
+inline const char* name_of()
+{
+#ifndef BOOST_NO_RTTI
+ return typeid(T).name();
+#else
+ return "unknown";
+#endif
+}
+template <> inline const char* name_of<float>(){ return "float"; }
+template <> inline const char* name_of<double>(){ return "double"; }
+template <> inline const char* name_of<long double>(){ return "long double"; }
+
+#ifdef BOOST_MATH_USE_FLOAT128
+template <>
+inline const char* name_of<BOOST_MATH_FLOAT128_TYPE>()
+{
+ return "__float128";
+}
+#endif
+
template <class E, class T>
void raise_error(const char* function, const char* message)
{
@@ -87,7 +108,11 @@ void raise_error(const char* function, const char* message)
message = "Cause unknown";
std::string msg("Error in function ");
- msg += (boost::format(function) % typeid(T).name()).str();
+#ifndef BOOST_NO_RTTI
+ msg += (boost::format(function) % boost::math::policies::detail::name_of<T>()).str();
+#else
+ msg += function;
+#endif
msg += ": ";
msg += message;
@@ -104,7 +129,11 @@ void raise_error(const char* function, const char* message, const T& val)
message = "Cause unknown: error caused by bad argument with value %1%";
std::string msg("Error in function ");
- msg += (boost::format(function) % typeid(T).name()).str();
+#ifndef BOOST_NO_RTTI
+ msg += (boost::format(function) % boost::math::policies::detail::name_of<T>()).str();
+#else
+ msg += function;
+#endif
msg += ": ";
msg += message;
@@ -117,9 +146,9 @@ void raise_error(const char* function, const char* message, const T& val)
template <class T>
inline T raise_domain_error(
- const char* function,
- const char* message,
- const T& val,
+ const char* function,
+ const char* message,
+ const T& val,
const ::boost::math::policies::domain_error< ::boost::math::policies::throw_on_error>&)
{
raise_error<std::domain_error, T>(function, message, val);
@@ -129,9 +158,9 @@ inline T raise_domain_error(
template <class T>
inline T raise_domain_error(
- const char* ,
- const char* ,
- const T& ,
+ const char* ,
+ const char* ,
+ const T& ,
const ::boost::math::policies::domain_error< ::boost::math::policies::ignore_error>&)
{
// This may or may not do the right thing, but the user asked for the error
@@ -141,9 +170,9 @@ inline T raise_domain_error(
template <class T>
inline T raise_domain_error(
- const char* ,
- const char* ,
- const T& ,
+ const char* ,
+ const char* ,
+ const T& ,
const ::boost::math::policies::domain_error< ::boost::math::policies::errno_on_error>&)
{
errno = EDOM;
@@ -154,9 +183,9 @@ inline T raise_domain_error(
template <class T>
inline T raise_domain_error(
- const char* function,
- const char* message,
- const T& val,
+ const char* function,
+ const char* message,
+ const T& val,
const ::boost::math::policies::domain_error< ::boost::math::policies::user_error>&)
{
return user_domain_error(function, message, val);
@@ -164,9 +193,9 @@ inline T raise_domain_error(
template <class T>
inline T raise_pole_error(
- const char* function,
- const char* message,
- const T& val,
+ const char* function,
+ const char* message,
+ const T& val,
const ::boost::math::policies::pole_error< ::boost::math::policies::throw_on_error>&)
{
return boost::math::policies::detail::raise_domain_error(function, message, val, ::boost::math::policies::domain_error< ::boost::math::policies::throw_on_error>());
@@ -174,9 +203,9 @@ inline T raise_pole_error(
template <class T>
inline T raise_pole_error(
- const char* function,
- const char* message,
- const T& val,
+ const char* function,
+ const char* message,
+ const T& val,
const ::boost::math::policies::pole_error< ::boost::math::policies::ignore_error>&)
{
return ::boost::math::policies::detail::raise_domain_error(function, message, val, ::boost::math::policies::domain_error< ::boost::math::policies::ignore_error>());
@@ -184,9 +213,9 @@ inline T raise_pole_error(
template <class T>
inline T raise_pole_error(
- const char* function,
- const char* message,
- const T& val,
+ const char* function,
+ const char* message,
+ const T& val,
const ::boost::math::policies::pole_error< ::boost::math::policies::errno_on_error>&)
{
return ::boost::math::policies::detail::raise_domain_error(function, message, val, ::boost::math::policies::domain_error< ::boost::math::policies::errno_on_error>());
@@ -194,29 +223,54 @@ inline T raise_pole_error(
template <class T>
inline T raise_pole_error(
- const char* function,
- const char* message,
- const T& val,
+ const char* function,
+ const char* message,
+ const T& val,
const ::boost::math::policies::pole_error< ::boost::math::policies::user_error>&)
{
return user_pole_error(function, message, val);
}
+
template <class T>
inline T raise_overflow_error(
- const char* function,
- const char* message,
+ const char* function,
+ const char* message,
const ::boost::math::policies::overflow_error< ::boost::math::policies::throw_on_error>&)
{
raise_error<std::overflow_error, T>(function, message ? message : "numeric overflow");
- // we never get here:
+ // We should never get here:
return std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();
}
template <class T>
inline T raise_overflow_error(
- const char* ,
- const char* ,
+ const char* function,
+ const char* message,
+ const T& val,
+ const ::boost::math::policies::overflow_error< ::boost::math::policies::throw_on_error>&)
+{
+ raise_error<std::overflow_error, T>(function, message ? message : "numeric overflow", val);
+ // We should never get here:
+ return std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();
+}
+
+template <class T>
+inline T raise_overflow_error(
+ const char* ,
+ const char* ,
+ const ::boost::math::policies::overflow_error< ::boost::math::policies::ignore_error>&)
+{
+ // This may or may not do the right thing, but the user asked for the error
+ // to be ignored so here we go anyway:
+ return std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();
+}
+
+template <class T>
+inline T raise_overflow_error(
+ const char* ,
+ const char* ,
+ const T&,
const ::boost::math::policies::overflow_error< ::boost::math::policies::ignore_error>&)
{
// This may or may not do the right thing, but the user asked for the error
@@ -226,8 +280,8 @@ inline T raise_overflow_error(
template <class T>
inline T raise_overflow_error(
- const char* ,
- const char* ,
+ const char* ,
+ const char* ,
const ::boost::math::policies::overflow_error< ::boost::math::policies::errno_on_error>&)
{
errno = ERANGE;
@@ -238,28 +292,59 @@ inline T raise_overflow_error(
template <class T>
inline T raise_overflow_error(
- const char* function,
- const char* message,
+ const char* ,
+ const char* ,
+ const T&,
+ const ::boost::math::policies::overflow_error< ::boost::math::policies::errno_on_error>&)
+{
+ errno = ERANGE;
+ // This may or may not do the right thing, but the user asked for the error
+ // to be silent so here we go anyway:
+ return std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();
+}
+
+template <class T>
+inline T raise_overflow_error(
+ const char* function,
+ const char* message,
const ::boost::math::policies::overflow_error< ::boost::math::policies::user_error>&)
{
return user_overflow_error(function, message, std::numeric_limits<T>::infinity());
}
template <class T>
+inline T raise_overflow_error(
+ const char* function,
+ const char* message,
+ const T& val,
+ const ::boost::math::policies::overflow_error< ::boost::math::policies::user_error>&)
+{
+ std::string fmsg("Error in function ");
+#ifndef BOOST_NO_RTTI
+ fmsg += (boost::format(function) % boost::math::policies::detail::name_of<T>()).str();
+#else
+ fmsg += function;
+#endif
+ int prec = 2 + (boost::math::policies::digits<T, boost::math::policies::policy<> >() * 30103UL) / 100000UL;
+ std::string msg = do_format(boost::format(message), boost::io::group(std::setprecision(prec), val));
+ return user_overflow_error(fmsg.c_str(), msg.c_str(), std::numeric_limits<T>::infinity());
+}
+
+template <class T>
inline T raise_underflow_error(
- const char* function,
- const char* message,
+ const char* function,
+ const char* message,
const ::boost::math::policies::underflow_error< ::boost::math::policies::throw_on_error>&)
{
raise_error<std::underflow_error, T>(function, message ? message : "numeric underflow");
- // we never get here:
+ // We should never get here:
return 0;
}
template <class T>
inline T raise_underflow_error(
- const char* ,
- const char* ,
+ const char* ,
+ const char* ,
const ::boost::math::policies::underflow_error< ::boost::math::policies::ignore_error>&)
{
// This may or may not do the right thing, but the user asked for the error
@@ -269,8 +354,8 @@ inline T raise_underflow_error(
template <class T>
inline T raise_underflow_error(
- const char* /* function */,
- const char* /* message */,
+ const char* /* function */,
+ const char* /* message */,
const ::boost::math::policies::underflow_error< ::boost::math::policies::errno_on_error>&)
{
errno = ERANGE;
@@ -281,8 +366,8 @@ inline T raise_underflow_error(
template <class T>
inline T raise_underflow_error(
- const char* function,
- const char* message,
+ const char* function,
+ const char* message,
const ::boost::math::policies::underflow_error< ::boost::math::policies::user_error>&)
{
return user_underflow_error(function, message, T(0));
@@ -290,8 +375,8 @@ inline T raise_underflow_error(
template <class T>
inline T raise_denorm_error(
- const char* function,
- const char* message,
+ const char* function,
+ const char* message,
const T& /* val */,
const ::boost::math::policies::denorm_error< ::boost::math::policies::throw_on_error>&)
{
@@ -302,8 +387,8 @@ inline T raise_denorm_error(
template <class T>
inline T raise_denorm_error(
- const char* ,
- const char* ,
+ const char* ,
+ const char* ,
const T& val,
const ::boost::math::policies::denorm_error< ::boost::math::policies::ignore_error>&)
{
@@ -314,8 +399,8 @@ inline T raise_denorm_error(
template <class T>
inline T raise_denorm_error(
- const char* ,
- const char* ,
+ const char* ,
+ const char* ,
const T& val,
const ::boost::math::policies::denorm_error< ::boost::math::policies::errno_on_error>&)
{
@@ -327,8 +412,8 @@ inline T raise_denorm_error(
template <class T>
inline T raise_denorm_error(
- const char* function,
- const char* message,
+ const char* function,
+ const char* message,
const T& val,
const ::boost::math::policies::denorm_error< ::boost::math::policies::user_error>&)
{
@@ -337,9 +422,9 @@ inline T raise_denorm_error(
template <class T>
inline T raise_evaluation_error(
- const char* function,
- const char* message,
- const T& val,
+ const char* function,
+ const char* message,
+ const T& val,
const ::boost::math::policies::evaluation_error< ::boost::math::policies::throw_on_error>&)
{
raise_error<boost::math::evaluation_error, T>(function, message, val);
@@ -349,9 +434,9 @@ inline T raise_evaluation_error(
template <class T>
inline T raise_evaluation_error(
- const char* ,
- const char* ,
- const T& val,
+ const char* ,
+ const char* ,
+ const T& val,
const ::boost::math::policies::evaluation_error< ::boost::math::policies::ignore_error>&)
{
// This may or may not do the right thing, but the user asked for the error
@@ -361,9 +446,9 @@ inline T raise_evaluation_error(
template <class T>
inline T raise_evaluation_error(
- const char* ,
- const char* ,
- const T& val,
+ const char* ,
+ const char* ,
+ const T& val,
const ::boost::math::policies::evaluation_error< ::boost::math::policies::errno_on_error>&)
{
errno = EDOM;
@@ -374,59 +459,61 @@ inline T raise_evaluation_error(
template <class T>
inline T raise_evaluation_error(
- const char* function,
- const char* message,
- const T& val,
+ const char* function,
+ const char* message,
+ const T& val,
const ::boost::math::policies::evaluation_error< ::boost::math::policies::user_error>&)
{
return user_evaluation_error(function, message, val);
}
template <class T, class TargetType>
-inline T raise_rounding_error(
- const char* function,
- const char* message,
- const T& val,
+inline TargetType raise_rounding_error(
+ const char* function,
+ const char* message,
+ const T& val,
const TargetType&,
const ::boost::math::policies::rounding_error< ::boost::math::policies::throw_on_error>&)
{
raise_error<boost::math::rounding_error, T>(function, message, val);
// we never get here:
- return T(0);
+ return TargetType(0);
}
template <class T, class TargetType>
-inline T raise_rounding_error(
- const char* ,
- const char* ,
- const T& val,
+inline TargetType raise_rounding_error(
+ const char* ,
+ const char* ,
+ const T& val,
const TargetType&,
const ::boost::math::policies::rounding_error< ::boost::math::policies::ignore_error>&)
{
// This may or may not do the right thing, but the user asked for the error
// to be ignored so here we go anyway:
- return std::numeric_limits<T>::is_specialized ? (val > 0 ? (std::numeric_limits<T>::max)() : -(std::numeric_limits<T>::max)()): val;
+ BOOST_STATIC_ASSERT(std::numeric_limits<TargetType>::is_specialized);
+ return val > 0 ? (std::numeric_limits<TargetType>::max)() : (std::numeric_limits<TargetType>::is_integer ? (std::numeric_limits<TargetType>::min)() : -(std::numeric_limits<TargetType>::max)());
}
template <class T, class TargetType>
-inline T raise_rounding_error(
- const char* ,
- const char* ,
- const T& val,
+inline TargetType raise_rounding_error(
+ const char* ,
+ const char* ,
+ const T& val,
const TargetType&,
const ::boost::math::policies::rounding_error< ::boost::math::policies::errno_on_error>&)
{
errno = ERANGE;
// This may or may not do the right thing, but the user asked for the error
// to be silent so here we go anyway:
- return std::numeric_limits<T>::is_specialized ? (val > 0 ? (std::numeric_limits<T>::max)() : -(std::numeric_limits<T>::max)()): val;
+ BOOST_STATIC_ASSERT(std::numeric_limits<TargetType>::is_specialized);
+ return val > 0 ? (std::numeric_limits<TargetType>::max)() : (std::numeric_limits<TargetType>::is_integer ? (std::numeric_limits<TargetType>::min)() : -(std::numeric_limits<TargetType>::max)());
}
template <class T, class TargetType>
-inline T raise_rounding_error(
- const char* function,
- const char* message,
- const T& val,
+inline TargetType raise_rounding_error(
+ const char* function,
+ const char* message,
+ const T& val,
const TargetType& t,
const ::boost::math::policies::rounding_error< ::boost::math::policies::user_error>&)
{
@@ -435,9 +522,9 @@ inline T raise_rounding_error(
template <class T, class R>
inline T raise_indeterminate_result_error(
- const char* function,
- const char* message,
- const T& val,
+ const char* function,
+ const char* message,
+ const T& val,
const R& ,
const ::boost::math::policies::indeterminate_result_error< ::boost::math::policies::throw_on_error>&)
{
@@ -448,10 +535,10 @@ inline T raise_indeterminate_result_error(
template <class T, class R>
inline T raise_indeterminate_result_error(
- const char* ,
- const char* ,
- const T& ,
- const R& result,
+ const char* ,
+ const char* ,
+ const T& ,
+ const R& result,
const ::boost::math::policies::indeterminate_result_error< ::boost::math::policies::ignore_error>&)
{
// This may or may not do the right thing, but the user asked for the error
@@ -461,10 +548,10 @@ inline T raise_indeterminate_result_error(
template <class T, class R>
inline T raise_indeterminate_result_error(
- const char* ,
- const char* ,
- const T& ,
- const R& result,
+ const char* ,
+ const char* ,
+ const T& ,
+ const R& result,
const ::boost::math::policies::indeterminate_result_error< ::boost::math::policies::errno_on_error>&)
{
errno = EDOM;
@@ -475,10 +562,10 @@ inline T raise_indeterminate_result_error(
template <class T, class R>
inline T raise_indeterminate_result_error(
- const char* function,
- const char* message,
- const T& val,
- const R& ,
+ const char* function,
+ const char* message,
+ const T& val,
+ const R& ,
const ::boost::math::policies::indeterminate_result_error< ::boost::math::policies::user_error>&)
{
return user_indeterminate_result_error(function, message, val);
@@ -491,7 +578,7 @@ inline T raise_domain_error(const char* function, const char* message, const T&
{
typedef typename Policy::domain_error_type policy_type;
return detail::raise_domain_error(
- function, message ? message : "Domain Error evaluating function at %1%",
+ function, message ? message : "Domain Error evaluating function at %1%",
val, policy_type());
}
@@ -500,7 +587,7 @@ inline T raise_pole_error(const char* function, const char* message, const T& va
{
typedef typename Policy::pole_error_type policy_type;
return detail::raise_pole_error(
- function, message ? message : "Evaluation of function at pole %1%",
+ function, message ? message : "Evaluation of function at pole %1%",
val, policy_type());
}
@@ -509,16 +596,25 @@ inline T raise_overflow_error(const char* function, const char* message, const P
{
typedef typename Policy::overflow_error_type policy_type;
return detail::raise_overflow_error<T>(
- function, message ? message : "Overflow Error",
+ function, message ? message : "Overflow Error",
policy_type());
}
template <class T, class Policy>
+inline T raise_overflow_error(const char* function, const char* message, const T& val, const Policy&)
+{
+ typedef typename Policy::overflow_error_type policy_type;
+ return detail::raise_overflow_error(
+ function, message ? message : "Overflow evaluating function at %1%",
+ val, policy_type());
+}
+
+template <class T, class Policy>
inline T raise_underflow_error(const char* function, const char* message, const Policy&)
{
typedef typename Policy::underflow_error_type policy_type;
return detail::raise_underflow_error<T>(
- function, message ? message : "Underflow Error",
+ function, message ? message : "Underflow Error",
policy_type());
}
@@ -527,7 +623,7 @@ inline T raise_denorm_error(const char* function, const char* message, const T&
{
typedef typename Policy::denorm_error_type policy_type;
return detail::raise_denorm_error<T>(
- function, message ? message : "Denorm Error",
+ function, message ? message : "Denorm Error",
val,
policy_type());
}
@@ -537,16 +633,16 @@ inline T raise_evaluation_error(const char* function, const char* message, const
{
typedef typename Policy::evaluation_error_type policy_type;
return detail::raise_evaluation_error(
- function, message ? message : "Internal Evaluation Error, best value so far was %1%",
+ function, message ? message : "Internal Evaluation Error, best value so far was %1%",
val, policy_type());
}
template <class T, class TargetType, class Policy>
-inline T raise_rounding_error(const char* function, const char* message, const T& val, const TargetType& t, const Policy&)
+inline TargetType raise_rounding_error(const char* function, const char* message, const T& val, const TargetType& t, const Policy&)
{
typedef typename Policy::rounding_error_type policy_type;
return detail::raise_rounding_error(
- function, message ? message : "Value %1% can not be represented in the target integer type.",
+ function, message ? message : "Value %1% can not be represented in the target integer type.",
val, t, policy_type());
}
@@ -571,7 +667,8 @@ inline bool check_overflow(T val, R* result, const char* function, const Policy&
BOOST_MATH_STD_USING
if(fabs(val) > tools::max_value<R>())
{
- *result = static_cast<R>(boost::math::policies::detail::raise_overflow_error<R>(function, 0, pol));
+ boost::math::policies::detail::raise_overflow_error<R>(function, 0, pol);
+ *result = static_cast<R>(val);
return true;
}
return false;
@@ -581,7 +678,8 @@ inline bool check_overflow(std::complex<T> val, R* result, const char* function,
{
typedef typename R::value_type r_type;
r_type re, im;
- bool r = check_overflow<r_type>(val.real(), &re, function, pol) || check_overflow<r_type>(val.imag(), &im, function, pol);
+ bool r = check_overflow<r_type>(val.real(), &re, function, pol);
+ r = check_overflow<r_type>(val.imag(), &im, function, pol) || r;
*result = R(re, im);
return r;
}
@@ -600,7 +698,8 @@ inline bool check_underflow(std::complex<T> val, R* result, const char* function
{
typedef typename R::value_type r_type;
r_type re, im;
- bool r = check_underflow<r_type>(val.real(), &re, function, pol) || check_underflow<r_type>(val.imag(), &im, function, pol);
+ bool r = check_underflow<r_type>(val.real(), &re, function, pol);
+ r = check_underflow<r_type>(val.imag(), &im, function, pol) || r;
*result = R(re, im);
return r;
}
@@ -620,7 +719,8 @@ inline bool check_denorm(std::complex<T> val, R* result, const char* function, c
{
typedef typename R::value_type r_type;
r_type re, im;
- bool r = check_denorm<r_type>(val.real(), &re, function, pol) || check_denorm<r_type>(val.imag(), &im, function, pol);
+ bool r = check_denorm<r_type>(val.real(), &re, function, pol);
+ r = check_denorm<r_type>(val.imag(), &im, function, pol) || r;
*result = R(re, im);
return r;
}
@@ -681,6 +781,20 @@ inline void check_root_iterations(const char* function, boost::uintmax_t max_ite
} //namespace policies
+namespace detail{
+
+//
+// Simple helper function to assist in returning a pair from a single value,
+// that value usually comes from one of the error handlers above:
+//
+template <class T>
+std::pair<T, T> pair_from_single(const T& val)
+{
+ return std::make_pair(val, val);
+}
+
+}
+
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
diff --git a/boost/math/policies/policy.hpp b/boost/math/policies/policy.hpp
index 70e67c70ba..49068a6ed5 100644
--- a/boost/math/policies/policy.hpp
+++ b/boost/math/policies/policy.hpp
@@ -94,8 +94,7 @@ namespace policies{
#define BOOST_MATH_MAX_ROOT_ITERATION_POLICY 200
#endif
-#if !defined(__BORLANDC__) \
- && !(defined(__GNUC__) && (__GNUC__ == 3) && (__GNUC_MINOR__ <= 2))
+#if !defined(__BORLANDC__)
#define BOOST_MATH_META_INT(type, name, Default)\
template <type N = Default> struct name : public boost::mpl::int_<N>{};\
namespace detail{\
@@ -431,7 +430,7 @@ public:
//
// Mathematically undefined properties:
//
- typedef typename detail::find_arg<arg_list, is_assert_undefined<mpl::_1>, discrete_quantile<> >::type assert_undefined_type;
+ typedef typename detail::find_arg<arg_list, is_assert_undefined<mpl::_1>, assert_undefined<> >::type assert_undefined_type;
//
// Max iterations:
//
@@ -537,12 +536,12 @@ private:
//
// Mathematically undefined properties:
//
- typedef typename detail::find_arg<arg_list, is_assert_undefined<mpl::_1>, discrete_quantile<> >::type assert_undefined_type;
+ typedef typename detail::find_arg<arg_list, is_assert_undefined<mpl::_1>, typename Policy::assert_undefined_type >::type assert_undefined_type;
//
// Max iterations:
//
- typedef typename detail::find_arg<arg_list, is_max_series_iterations<mpl::_1>, max_series_iterations<> >::type max_series_iterations_type;
- typedef typename detail::find_arg<arg_list, is_max_root_iterations<mpl::_1>, max_root_iterations<> >::type max_root_iterations_type;
+ typedef typename detail::find_arg<arg_list, is_max_series_iterations<mpl::_1>, typename Policy::max_series_iterations_type>::type max_series_iterations_type;
+ typedef typename detail::find_arg<arg_list, is_max_root_iterations<mpl::_1>, typename Policy::max_root_iterations_type>::type max_root_iterations_type;
//
// Define a typelist of the policies:
//
@@ -813,6 +812,16 @@ struct precision
#endif
+#ifdef BOOST_MATH_USE_FLOAT128
+
+template <class Policy>
+struct precision<BOOST_MATH_FLOAT128_TYPE, Policy>
+{
+ typedef mpl::int_<113> type;
+};
+
+#endif
+
namespace detail{
template <class T, class Policy>
diff --git a/boost/math/quaternion.hpp b/boost/math/quaternion.hpp
index bbe767d22b..d816a767cb 100644
--- a/boost/math/quaternion.hpp
+++ b/boost/math/quaternion.hpp
@@ -33,23 +33,6 @@ namespace boost
{
namespace math
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- // gcc 2.95.x uses expression templates for valarray calculations, but
- // the result is not conforming. We need BOOST_GET_VALARRAY to get an
- // actual valarray result when we need to call a member function
- #define BOOST_GET_VALARRAY(T,x) ::std::valarray<T>(x)
- // gcc 2.95.x has an "std::ios" class that is similar to
- // "std::ios_base", so we just use a #define
- #define BOOST_IOS_BASE ::std::ios
- // gcc 2.x ignores function scope using declarations,
- // put them in the scope of the enclosing namespace instead:
- using ::std::valarray;
- using ::std::sqrt;
- using ::std::cos;
- using ::std::sin;
- using ::std::exp;
- using ::std::cosh;
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
#define BOOST_QUATERNION_ACCESSOR_GENERATOR(type) \
type real() const \
@@ -601,40 +584,7 @@ namespace boost
return(*this); \
}
-#if defined(__GNUC__) && (__GNUC__ < 3)
- #define BOOST_QUATERNION_MEMBER_DIV_GENERATOR_2(type) \
- quaternion<type> & operator /= (::std::complex<type> const & rhs) \
- { \
- using ::std::valarray; \
- \
- valarray<type> tr(2); \
- \
- tr[0] = rhs.real(); \
- tr[1] = rhs.imag(); \
- \
- type mixam = (BOOST_GET_VALARRAY(type,static_cast<type>(1)/abs(tr)).max)(); \
- \
- tr *= mixam; \
- \
- valarray<type> tt(4); \
- \
- tt[0] = +a*tr[0]+b*tr[1]; \
- tt[1] = -a*tr[1]+b*tr[0]; \
- tt[2] = +c*tr[0]-d*tr[1]; \
- tt[3] = +c*tr[1]+d*tr[0]; \
- \
- tr *= tr; \
- \
- tt *= (mixam/tr.sum()); \
- \
- a = tt[0]; \
- b = tt[1]; \
- c = tt[2]; \
- d = tt[3]; \
- \
- return(*this); \
- }
-#elif defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
+#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
#define BOOST_QUATERNION_MEMBER_DIV_GENERATOR_2(type) \
quaternion<type> & operator /= (::std::complex<type> const & rhs) \
{ \
@@ -701,45 +651,9 @@ namespace boost
\
return(*this); \
}
-#endif /* defined(__GNUC__) && (__GNUC__ < 3) */ /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
+#endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
-#if defined(__GNUC__) && (__GNUC__ < 3)
- #define BOOST_QUATERNION_MEMBER_DIV_GENERATOR_3(type) \
- template<typename X> \
- quaternion<type> & operator /= (quaternion<X> const & rhs) \
- { \
- using ::std::valarray; \
- \
- valarray<type> tr(4); \
- \
- tr[0] = static_cast<type>(rhs.R_component_1()); \
- tr[1] = static_cast<type>(rhs.R_component_2()); \
- tr[2] = static_cast<type>(rhs.R_component_3()); \
- tr[3] = static_cast<type>(rhs.R_component_4()); \
- \
- type mixam = (BOOST_GET_VALARRAY(type,static_cast<type>(1)/abs(tr)).max)(); \
- \
- tr *= mixam; \
- \
- valarray<type> tt(4); \
- \
- tt[0] = +a*tr[0]+b*tr[1]+c*tr[2]+d*tr[3]; \
- tt[1] = -a*tr[1]+b*tr[0]-c*tr[3]+d*tr[2]; \
- tt[2] = -a*tr[2]+b*tr[3]+c*tr[0]-d*tr[1]; \
- tt[3] = -a*tr[3]-b*tr[2]+c*tr[1]+d*tr[0]; \
- \
- tr *= tr; \
- \
- tt *= (mixam/tr.sum()); \
- \
- a = tt[0]; \
- b = tt[1]; \
- c = tt[2]; \
- d = tt[3]; \
- \
- return(*this); \
- }
-#elif defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
+#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
#define BOOST_QUATERNION_MEMBER_DIV_GENERATOR_3(type) \
template<typename X> \
quaternion<type> & operator /= (quaternion<X> const & rhs) \
@@ -812,7 +726,7 @@ namespace boost
\
return(*this); \
}
-#endif /* defined(__GNUC__) && (__GNUC__ < 3) */ /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
+#endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
#define BOOST_QUATERNION_MEMBER_ADD_GENERATOR(type) \
BOOST_QUATERNION_MEMBER_ADD_GENERATOR_1(type) \
@@ -1219,19 +1133,10 @@ namespace boost
// a
// (a), (a,b), (a,b,c), (a,b,c,d)
// (a,(c)), (a,(c,d)), ((a)), ((a),c), ((a),(c)), ((a),(c,d)), ((a,b)), ((a,b),c), ((a,b),(c)), ((a,b),(c,d))
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- template<typename T>
- std::istream & operator >> ( ::std::istream & is,
- quaternion<T> & q)
-#else
template<typename T, typename charT, class traits>
::std::basic_istream<charT,traits> & operator >> ( ::std::basic_istream<charT,traits> & is,
quaternion<T> & q)
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- typedef char charT;
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
#ifdef BOOST_NO_STD_LOCALE
#else
@@ -1319,20 +1224,12 @@ namespace boost
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // read "(a", possible: (a), (a,b), (a,b,c), (a,b,c,d), (a,(c)), (a,(c,d))
@@ -1396,11 +1293,7 @@ namespace boost
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // read "(a,b", possible: (a,b), (a,b,c), (a,b,c,d)
@@ -1467,39 +1360,23 @@ namespace boost
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
}
else // error
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- is.setstate(::std::ios::failbit);
-#else
is.setstate(::std::ios_base::failbit);
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
}
}
@@ -1519,22 +1396,12 @@ namespace boost
}
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- template<typename T>
- ::std::ostream & operator << ( ::std::ostream & os,
- quaternion<T> const & q)
-#else
template<typename T, typename charT, class traits>
::std::basic_ostream<charT,traits> & operator << ( ::std::basic_ostream<charT,traits> & os,
quaternion<T> const & q)
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
{
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- ::std::ostringstream s;
-#else
::std::basic_ostringstream<charT,traits> s;
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
-
+
s.flags(os.flags());
#ifdef BOOST_NO_STD_LOCALE
#else
@@ -1587,11 +1454,7 @@ namespace boost
BOOST_QUATERNION_VALARRAY_LOADER
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- return((BOOST_GET_VALARRAY(T, abs(temp)).max)());
-#else
return((abs(temp).max)());
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
@@ -1604,11 +1467,7 @@ namespace boost
BOOST_QUATERNION_VALARRAY_LOADER
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- return(BOOST_GET_VALARRAY(T, abs(temp)).sum());
-#else
return(abs(temp).sum());
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
}
@@ -1623,11 +1482,7 @@ namespace boost
BOOST_QUATERNION_VALARRAY_LOADER
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- T maxim = (BOOST_GET_VALARRAY(T, abs(temp)).max)(); // overflow protection
-#else
T maxim = (abs(temp).max)(); // overflow protection
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
if (maxim == static_cast<T>(0))
{
@@ -1915,10 +1770,4 @@ namespace boost
}
}
-
-#if BOOST_WORKAROUND(__GNUC__, < 3)
- #undef BOOST_GET_VALARRAY
-#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
-
-
#endif /* BOOST_QUATERNION_HPP */
diff --git a/boost/math/special_functions.hpp b/boost/math/special_functions.hpp
index 00fe866f4a..aa7019a1eb 100644
--- a/boost/math/special_functions.hpp
+++ b/boost/math/special_functions.hpp
@@ -1,5 +1,5 @@
-// Copyright John Maddock 2006, 2007.
-// Copyright Paul A. Bristow 2006, 2007.
+// Copyright John Maddock 2006, 2007, 2012.
+// Copyright Paul A. Bristow 2006, 2007, 2012
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
@@ -12,10 +12,13 @@
#ifndef BOOST_MATH_SPECIAL_FUNCTIONS_HPP
#define BOOST_MATH_SPECIAL_FUNCTIONS_HPP
+#include <boost/math/special_functions/airy.hpp>
#include <boost/math/special_functions/acosh.hpp>
#include <boost/math/special_functions/asinh.hpp>
#include <boost/math/special_functions/atanh.hpp>
+#include <boost/math/special_functions/bernoulli.hpp>
#include <boost/math/special_functions/bessel.hpp>
+#include <boost/math/special_functions/bessel_prime.hpp>
#include <boost/math/special_functions/beta.hpp>
#include <boost/math/special_functions/binomial.hpp>
#include <boost/math/special_functions/cbrt.hpp>
@@ -36,12 +39,14 @@
#include <boost/math/special_functions/gamma.hpp>
#include <boost/math/special_functions/hermite.hpp>
#include <boost/math/special_functions/hypot.hpp>
+#include <boost/math/special_functions/jacobi_elliptic.hpp>
#include <boost/math/special_functions/laguerre.hpp>
#include <boost/math/special_functions/lanczos.hpp>
#include <boost/math/special_functions/legendre.hpp>
#include <boost/math/special_functions/log1p.hpp>
#include <boost/math/special_functions/math_fwd.hpp>
#include <boost/math/special_functions/next.hpp>
+#include <boost/math/special_functions/owens_t.hpp>
#include <boost/math/special_functions/powm1.hpp>
#include <boost/math/special_functions/sign.hpp>
#include <boost/math/special_functions/sin_pi.hpp>
diff --git a/boost/math/special_functions/acosh.hpp b/boost/math/special_functions/acosh.hpp
index 40ca985edc..0af5c94c14 100644
--- a/boost/math/special_functions/acosh.hpp
+++ b/boost/math/special_functions/acosh.hpp
@@ -21,6 +21,7 @@
#include <boost/math/policies/error_handling.hpp>
#include <boost/math/special_functions/math_fwd.hpp>
#include <boost/math/special_functions/log1p.hpp>
+#include <boost/math/constants/constants.hpp>
// This is the inverse of the hyperbolic cosine function.
@@ -30,17 +31,6 @@ namespace boost
{
namespace detail
{
-#if defined(__GNUC__) && (__GNUC__ < 3)
- // gcc 2.x ignores function scope using declarations,
- // put them in the scope of the enclosing namespace instead:
-
- using ::std::abs;
- using ::std::sqrt;
- using ::std::log;
-
- using ::std::numeric_limits;
-#endif
-
template<typename T, typename Policy>
inline T acosh_imp(const T x, const Policy& pol)
{
@@ -58,7 +48,7 @@ namespace boost
{
// http://functions.wolfram.com/ElementaryFunctions/ArcCosh/06/01/06/01/0001/
// approximation by laurent series in 1/x at 0+ order from -1 to 0
- return( log( x * 2) );
+ return log(x) + constants::ln_two<T>();
}
else if(x < 1.5f)
{
diff --git a/boost/math/special_functions/airy.hpp b/boost/math/special_functions/airy.hpp
new file mode 100644
index 0000000000..82167dc5f0
--- /dev/null
+++ b/boost/math/special_functions/airy.hpp
@@ -0,0 +1,469 @@
+// Copyright John Maddock 2012.
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MATH_AIRY_HPP
+#define BOOST_MATH_AIRY_HPP
+
+#include <limits>
+#include <boost/math/special_functions/math_fwd.hpp>
+#include <boost/math/special_functions/bessel.hpp>
+#include <boost/math/special_functions/cbrt.hpp>
+#include <boost/math/special_functions/detail/airy_ai_bi_zero.hpp>
+#include <boost/math/tools/roots.hpp>
+
+namespace boost{ namespace math{
+
+namespace detail{
+
+template <class T, class Policy>
+T airy_ai_imp(T x, const Policy& pol)
+{
+ BOOST_MATH_STD_USING
+
+ if(x < 0)
+ {
+ T p = (-x * sqrt(-x) * 2) / 3;
+ T v = T(1) / 3;
+ T j1 = boost::math::cyl_bessel_j(v, p, pol);
+ T j2 = boost::math::cyl_bessel_j(-v, p, pol);
+ T ai = sqrt(-x) * (j1 + j2) / 3;
+ //T bi = sqrt(-x / 3) * (j2 - j1);
+ return ai;
+ }
+ else if(fabs(x * x * x) / 6 < tools::epsilon<T>())
+ {
+ T tg = boost::math::tgamma(constants::twothirds<T>(), pol);
+ T ai = 1 / (pow(T(3), constants::twothirds<T>()) * tg);
+ //T bi = 1 / (sqrt(boost::math::cbrt(T(3))) * tg);
+ return ai;
+ }
+ else
+ {
+ T p = 2 * x * sqrt(x) / 3;
+ T v = T(1) / 3;
+ //T j1 = boost::math::cyl_bessel_i(-v, p, pol);
+ //T j2 = boost::math::cyl_bessel_i(v, p, pol);
+ //
+ // Note that although we can calculate ai from j1 and j2, the accuracy is horrible
+ // as we're subtracting two very large values, so use the Bessel K relation instead:
+ //
+ T ai = cyl_bessel_k(v, p, pol) * sqrt(x / 3) / boost::math::constants::pi<T>(); //sqrt(x) * (j1 - j2) / 3;
+ //T bi = sqrt(x / 3) * (j1 + j2);
+ return ai;
+ }
+}
+
+template <class T, class Policy>
+T airy_bi_imp(T x, const Policy& pol)
+{
+ BOOST_MATH_STD_USING
+
+ if(x < 0)
+ {
+ T p = (-x * sqrt(-x) * 2) / 3;
+ T v = T(1) / 3;
+ T j1 = boost::math::cyl_bessel_j(v, p, pol);
+ T j2 = boost::math::cyl_bessel_j(-v, p, pol);
+ //T ai = sqrt(-x) * (j1 + j2) / 3;
+ T bi = sqrt(-x / 3) * (j2 - j1);
+ return bi;
+ }
+ else if(fabs(x * x * x) / 6 < tools::epsilon<T>())
+ {
+ T tg = boost::math::tgamma(constants::twothirds<T>(), pol);
+ //T ai = 1 / (pow(T(3), constants::twothirds<T>()) * tg);
+ T bi = 1 / (sqrt(boost::math::cbrt(T(3))) * tg);
+ return bi;
+ }
+ else
+ {
+ T p = 2 * x * sqrt(x) / 3;
+ T v = T(1) / 3;
+ T j1 = boost::math::cyl_bessel_i(-v, p, pol);
+ T j2 = boost::math::cyl_bessel_i(v, p, pol);
+ T bi = sqrt(x / 3) * (j1 + j2);
+ return bi;
+ }
+}
+
+template <class T, class Policy>
+T airy_ai_prime_imp(T x, const Policy& pol)
+{
+ BOOST_MATH_STD_USING
+
+ if(x < 0)
+ {
+ T p = (-x * sqrt(-x) * 2) / 3;
+ T v = T(2) / 3;
+ T j1 = boost::math::cyl_bessel_j(v, p, pol);
+ T j2 = boost::math::cyl_bessel_j(-v, p, pol);
+ T aip = -x * (j1 - j2) / 3;
+ return aip;
+ }
+ else if(fabs(x * x) / 2 < tools::epsilon<T>())
+ {
+ T tg = boost::math::tgamma(constants::third<T>(), pol);
+ T aip = 1 / (boost::math::cbrt(T(3)) * tg);
+ return -aip;
+ }
+ else
+ {
+ T p = 2 * x * sqrt(x) / 3;
+ T v = T(2) / 3;
+ //T j1 = boost::math::cyl_bessel_i(-v, p, pol);
+ //T j2 = boost::math::cyl_bessel_i(v, p, pol);
+ //
+ // Note that although we can calculate ai from j1 and j2, the accuracy is horrible
+ // as we're subtracting two very large values, so use the Bessel K relation instead:
+ //
+ T aip = -cyl_bessel_k(v, p, pol) * x / (boost::math::constants::root_three<T>() * boost::math::constants::pi<T>());
+ return aip;
+ }
+}
+
+template <class T, class Policy>
+T airy_bi_prime_imp(T x, const Policy& pol)
+{
+ BOOST_MATH_STD_USING
+
+ if(x < 0)
+ {
+ T p = (-x * sqrt(-x) * 2) / 3;
+ T v = T(2) / 3;
+ T j1 = boost::math::cyl_bessel_j(v, p, pol);
+ T j2 = boost::math::cyl_bessel_j(-v, p, pol);
+ T aip = -x * (j1 + j2) / constants::root_three<T>();
+ return aip;
+ }
+ else if(fabs(x * x) / 2 < tools::epsilon<T>())
+ {
+ T tg = boost::math::tgamma(constants::third<T>(), pol);
+ T bip = sqrt(boost::math::cbrt(T(3))) / tg;
+ return bip;
+ }
+ else
+ {
+ T p = 2 * x * sqrt(x) / 3;
+ T v = T(2) / 3;
+ T j1 = boost::math::cyl_bessel_i(-v, p, pol);
+ T j2 = boost::math::cyl_bessel_i(v, p, pol);
+ T aip = x * (j1 + j2) / boost::math::constants::root_three<T>();
+ return aip;
+ }
+}
+
+template <class T, class Policy>
+T airy_ai_zero_imp(int m, const Policy& pol)
+{
+ BOOST_MATH_STD_USING // ADL of std names, needed for log, sqrt.
+
+ // Handle cases when a negative zero (negative rank) is requested.
+ if(m < 0)
+ {
+ return policies::raise_domain_error<T>("boost::math::airy_ai_zero<%1%>(%1%, int)",
+ "Requested the %1%'th zero, but the rank must be 1 or more !", m, pol);
+ }
+
+ // Handle case when the zero'th zero is requested.
+ if(m == 0U)
+ {
+ return policies::raise_domain_error<T>("boost::math::airy_ai_zero<%1%>(%1%,%1%)",
+ "The requested rank of the zero is %1%, but must be 1 or more !", static_cast<T>(m), pol);
+ }
+
+ // Set up the initial guess for the upcoming root-finding.
+ const T guess_root = boost::math::detail::airy_zero::airy_ai_zero_detail::initial_guess<T>(m);
+
+ // Select the maximum allowed iterations based on the number
+ // of decimal digits in the numeric type T, being at least 12.
+ const int my_digits10 = static_cast<int>(static_cast<float>(policies::digits<T, Policy>() * 0.301F));
+
+ const boost::uintmax_t iterations_allowed = static_cast<boost::uintmax_t>((std::max)(12, my_digits10 * 2));
+
+ boost::uintmax_t iterations_used = iterations_allowed;
+
+ // Use a dynamic tolerance because the roots get closer the higher m gets.
+ T tolerance;
+
+ if (m <= 10) { tolerance = T(0.3F); }
+ else if(m <= 100) { tolerance = T(0.1F); }
+ else if(m <= 1000) { tolerance = T(0.05F); }
+ else { tolerance = T(1) / sqrt(T(m)); }
+
+ // Perform the root-finding using Newton-Raphson iteration from Boost.Math.
+ const T am =
+ boost::math::tools::newton_raphson_iterate(
+ boost::math::detail::airy_zero::airy_ai_zero_detail::function_object_ai_and_ai_prime<T, Policy>(pol),
+ guess_root,
+ T(guess_root - tolerance),
+ T(guess_root + tolerance),
+ policies::digits<T, Policy>(),
+ iterations_used);
+
+ static_cast<void>(iterations_used);
+
+ return am;
+}
+
+template <class T, class Policy>
+T airy_bi_zero_imp(int m, const Policy& pol)
+{
+ BOOST_MATH_STD_USING // ADL of std names, needed for log, sqrt.
+
+ // Handle cases when a negative zero (negative rank) is requested.
+ if(m < 0)
+ {
+ return policies::raise_domain_error<T>("boost::math::airy_bi_zero<%1%>(%1%, int)",
+ "Requested the %1%'th zero, but the rank must 1 or more !", m, pol);
+ }
+
+ // Handle case when the zero'th zero is requested.
+ if(m == 0U)
+ {
+ return policies::raise_domain_error<T>("boost::math::airy_bi_zero<%1%>(%1%,%1%)",
+ "The requested rank of the zero is %1%, but must be 1 or more !", static_cast<T>(m), pol);
+ }
+ // Set up the initial guess for the upcoming root-finding.
+ const T guess_root = boost::math::detail::airy_zero::airy_bi_zero_detail::initial_guess<T>(m);
+
+ // Select the maximum allowed iterations based on the number
+ // of decimal digits in the numeric type T, being at least 12.
+ const int my_digits10 = static_cast<int>(static_cast<float>(policies::digits<T, Policy>() * 0.301F));
+
+ const boost::uintmax_t iterations_allowed = static_cast<boost::uintmax_t>((std::max)(12, my_digits10 * 2));
+
+ boost::uintmax_t iterations_used = iterations_allowed;
+
+ // Use a dynamic tolerance because the roots get closer the higher m gets.
+ T tolerance;
+
+ if (m <= 10) { tolerance = T(0.3F); }
+ else if(m <= 100) { tolerance = T(0.1F); }
+ else if(m <= 1000) { tolerance = T(0.05F); }
+ else { tolerance = T(1) / sqrt(T(m)); }
+
+ // Perform the root-finding using Newton-Raphson iteration from Boost.Math.
+ const T bm =
+ boost::math::tools::newton_raphson_iterate(
+ boost::math::detail::airy_zero::airy_bi_zero_detail::function_object_bi_and_bi_prime<T, Policy>(pol),
+ guess_root,
+ T(guess_root - tolerance),
+ T(guess_root + tolerance),
+ policies::digits<T, Policy>(),
+ iterations_used);
+
+ static_cast<void>(iterations_used);
+
+ return bm;
+}
+
+} // namespace detail
+
+template <class T, class Policy>
+inline typename tools::promote_args<T>::type airy_ai(T x, const Policy&)
+{
+ BOOST_FPU_EXCEPTION_GUARD
+ typedef typename tools::promote_args<T>::type result_type;
+ typedef typename policies::evaluation<result_type, Policy>::type value_type;
+ typedef typename policies::normalise<
+ Policy,
+ policies::promote_float<false>,
+ policies::promote_double<false>,
+ policies::discrete_quantile<>,
+ policies::assert_undefined<> >::type forwarding_policy;
+
+ return policies::checked_narrowing_cast<result_type, Policy>(detail::airy_ai_imp<value_type>(static_cast<value_type>(x), forwarding_policy()), "boost::math::airy<%1%>(%1%)");
+}
+
+template <class T>
+inline typename tools::promote_args<T>::type airy_ai(T x)
+{
+ return airy_ai(x, policies::policy<>());
+}
+
+template <class T, class Policy>
+inline typename tools::promote_args<T>::type airy_bi(T x, const Policy&)
+{
+ BOOST_FPU_EXCEPTION_GUARD
+ typedef typename tools::promote_args<T>::type result_type;
+ typedef typename policies::evaluation<result_type, Policy>::type value_type;
+ typedef typename policies::normalise<
+ Policy,
+ policies::promote_float<false>,
+ policies::promote_double<false>,
+ policies::discrete_quantile<>,
+ policies::assert_undefined<> >::type forwarding_policy;
+
+ return policies::checked_narrowing_cast<result_type, Policy>(detail::airy_bi_imp<value_type>(static_cast<value_type>(x), forwarding_policy()), "boost::math::airy<%1%>(%1%)");
+}
+
+template <class T>
+inline typename tools::promote_args<T>::type airy_bi(T x)
+{
+ return airy_bi(x, policies::policy<>());
+}
+
+template <class T, class Policy>
+inline typename tools::promote_args<T>::type airy_ai_prime(T x, const Policy&)
+{
+ BOOST_FPU_EXCEPTION_GUARD
+ typedef typename tools::promote_args<T>::type result_type;
+ typedef typename policies::evaluation<result_type, Policy>::type value_type;
+ typedef typename policies::normalise<
+ Policy,
+ policies::promote_float<false>,
+ policies::promote_double<false>,
+ policies::discrete_quantile<>,
+ policies::assert_undefined<> >::type forwarding_policy;
+
+ return policies::checked_narrowing_cast<result_type, Policy>(detail::airy_ai_prime_imp<value_type>(static_cast<value_type>(x), forwarding_policy()), "boost::math::airy<%1%>(%1%)");
+}
+
+template <class T>
+inline typename tools::promote_args<T>::type airy_ai_prime(T x)
+{
+ return airy_ai_prime(x, policies::policy<>());
+}
+
+template <class T, class Policy>
+inline typename tools::promote_args<T>::type airy_bi_prime(T x, const Policy&)
+{
+ BOOST_FPU_EXCEPTION_GUARD
+ typedef typename tools::promote_args<T>::type result_type;
+ typedef typename policies::evaluation<result_type, Policy>::type value_type;
+ typedef typename policies::normalise<
+ Policy,
+ policies::promote_float<false>,
+ policies::promote_double<false>,
+ policies::discrete_quantile<>,
+ policies::assert_undefined<> >::type forwarding_policy;
+
+ return policies::checked_narrowing_cast<result_type, Policy>(detail::airy_bi_prime_imp<value_type>(static_cast<value_type>(x), forwarding_policy()), "boost::math::airy<%1%>(%1%)");
+}
+
+template <class T>
+inline typename tools::promote_args<T>::type airy_bi_prime(T x)
+{
+ return airy_bi_prime(x, policies::policy<>());
+}
+
+template <class T, class Policy>
+inline T airy_ai_zero(int m, const Policy& /*pol*/)
+{
+ BOOST_FPU_EXCEPTION_GUARD
+ typedef typename policies::evaluation<T, Policy>::type value_type;
+ typedef typename policies::normalise<
+ Policy,
+ policies::promote_float<false>,
+ policies::promote_double<false>,
+ policies::discrete_quantile<>,
+ policies::assert_undefined<> >::type forwarding_policy;
+
+ BOOST_STATIC_ASSERT_MSG( false == std::numeric_limits<T>::is_specialized
+ || ( true == std::numeric_limits<T>::is_specialized
+ && false == std::numeric_limits<T>::is_integer),
+ "Airy value type must be a floating-point type.");
+
+ return policies::checked_narrowing_cast<T, Policy>(detail::airy_ai_zero_imp<value_type>(m, forwarding_policy()), "boost::math::airy_ai_zero<%1%>(unsigned)");
+}
+
+template <class T>
+inline T airy_ai_zero(int m)
+{
+ return airy_ai_zero<T>(m, policies::policy<>());
+}
+
+template <class T, class OutputIterator, class Policy>
+inline OutputIterator airy_ai_zero(
+ int start_index,
+ unsigned number_of_zeros,
+ OutputIterator out_it,
+ const Policy& pol)
+{
+ typedef T result_type;
+
+ BOOST_STATIC_ASSERT_MSG( false == std::numeric_limits<T>::is_specialized
+ || ( true == std::numeric_limits<T>::is_specialized
+ && false == std::numeric_limits<T>::is_integer),
+ "Airy value type must be a floating-point type.");
+
+ for(unsigned i = 0; i < number_of_zeros; ++i)
+ {
+ *out_it = boost::math::airy_ai_zero<result_type>(start_index + i, pol);
+ ++out_it;
+ }
+ return out_it;
+}
+
+template <class T, class OutputIterator>
+inline OutputIterator airy_ai_zero(
+ int start_index,
+ unsigned number_of_zeros,
+ OutputIterator out_it)
+{
+ return airy_ai_zero<T>(start_index, number_of_zeros, out_it, policies::policy<>());
+}
+
+template <class T, class Policy>
+inline T airy_bi_zero(int m, const Policy& /*pol*/)
+{
+ BOOST_FPU_EXCEPTION_GUARD
+ typedef typename policies::evaluation<T, Policy>::type value_type;
+ typedef typename policies::normalise<
+ Policy,
+ policies::promote_float<false>,
+ policies::promote_double<false>,
+ policies::discrete_quantile<>,
+ policies::assert_undefined<> >::type forwarding_policy;
+
+ BOOST_STATIC_ASSERT_MSG( false == std::numeric_limits<T>::is_specialized
+ || ( true == std::numeric_limits<T>::is_specialized
+ && false == std::numeric_limits<T>::is_integer),
+ "Airy value type must be a floating-point type.");
+
+ return policies::checked_narrowing_cast<T, Policy>(detail::airy_bi_zero_imp<value_type>(m, forwarding_policy()), "boost::math::airy_bi_zero<%1%>(unsigned)");
+}
+
+template <typename T>
+inline T airy_bi_zero(int m)
+{
+ return airy_bi_zero<T>(m, policies::policy<>());
+}
+
+template <class T, class OutputIterator, class Policy>
+inline OutputIterator airy_bi_zero(
+ int start_index,
+ unsigned number_of_zeros,
+ OutputIterator out_it,
+ const Policy& pol)
+{
+ typedef T result_type;
+
+ BOOST_STATIC_ASSERT_MSG( false == std::numeric_limits<T>::is_specialized
+ || ( true == std::numeric_limits<T>::is_specialized
+ && false == std::numeric_limits<T>::is_integer),
+ "Airy value type must be a floating-point type.");
+
+ for(unsigned i = 0; i < number_of_zeros; ++i)
+ {
+ *out_it = boost::math::airy_bi_zero<result_type>(start_index + i, pol);
+ ++out_it;
+ }
+ return out_it;
+}
+
+template <class T, class OutputIterator>
+inline OutputIterator airy_bi_zero(
+ int start_index,
+ unsigned number_of_zeros,
+ OutputIterator out_it)
+{
+ return airy_bi_zero<T>(start_index, number_of_zeros, out_it, policies::policy<>());
+}
+
+}} // namespaces
+
+#endif // BOOST_MATH_AIRY_HPP
diff --git a/boost/math/special_functions/asinh.hpp b/boost/math/special_functions/asinh.hpp
index 14289688b4..a863e68854 100644
--- a/boost/math/special_functions/asinh.hpp
+++ b/boost/math/special_functions/asinh.hpp
@@ -22,6 +22,7 @@
#include <boost/math/special_functions/math_fwd.hpp>
#include <boost/math/special_functions/sqrt1pm1.hpp>
#include <boost/math/special_functions/log1p.hpp>
+#include <boost/math/constants/constants.hpp>
// This is the inverse of the hyperbolic sine function.
@@ -30,17 +31,6 @@ namespace boost
namespace math
{
namespace detail{
-#if defined(__GNUC__) && (__GNUC__ < 3)
- // gcc 2.x ignores function scope using declarations,
- // put them in the scope of the enclosing namespace instead:
-
- using ::std::abs;
- using ::std::sqrt;
- using ::std::log;
-
- using ::std::numeric_limits;
-#endif
-
template<typename T, class Policy>
inline T asinh_imp(const T x, const Policy& pol)
{
@@ -52,7 +42,7 @@ namespace boost
{
// http://functions.wolfram.com/ElementaryFunctions/ArcSinh/06/01/06/01/0001/
// approximation by laurent series in 1/x at 0+ order from -1 to 1
- return log(x * 2) + 1/ (4 * x * x);
+ return constants::ln_two<T>() + log(x) + 1/ (4 * x * x);
}
else if(x < 0.5f)
{
@@ -67,7 +57,7 @@ namespace boost
}
else if (x <= -tools::forth_root_epsilon<T>())
{
- return(-asinh(-x));
+ return(-asinh(-x, pol));
}
else
{
diff --git a/boost/math/special_functions/atanh.hpp b/boost/math/special_functions/atanh.hpp
index d447e2057b..2c5e3f4b78 100644
--- a/boost/math/special_functions/atanh.hpp
+++ b/boost/math/special_functions/atanh.hpp
@@ -31,17 +31,6 @@ namespace boost
{
namespace detail
{
-#if defined(__GNUC__) && (__GNUC__ < 3)
- // gcc 2.x ignores function scope using declarations,
- // put them in the scope of the enclosing namespace instead:
-
- using ::std::abs;
- using ::std::sqrt;
- using ::std::log;
-
- using ::std::numeric_limits;
-#endif
-
// This is the main fare
template<typename T, typename Policy>
@@ -56,6 +45,12 @@ namespace boost
function,
"atanh requires x >= -1, but got x = %1%.", x, pol);
}
+ else if(x > 1)
+ {
+ return policies::raise_domain_error<T>(
+ function,
+ "atanh requires x <= 1, but got x = %1%.", x, pol);
+ }
else if(x < -1 + tools::epsilon<T>())
{
// -Infinity:
@@ -66,12 +61,6 @@ namespace boost
// Infinity:
return policies::raise_overflow_error<T>(function, 0, pol);
}
- else if(x > 1)
- {
- return policies::raise_domain_error<T>(
- function,
- "atanh requires x <= 1, but got x = %1%.", x, pol);
- }
else if(abs(x) >= tools::forth_root_epsilon<T>())
{
// http://functions.wolfram.com/ElementaryFunctions/ArcTanh/02/
diff --git a/boost/math/special_functions/bernoulli.hpp b/boost/math/special_functions/bernoulli.hpp
new file mode 100644
index 0000000000..2c2ccd5236
--- /dev/null
+++ b/boost/math/special_functions/bernoulli.hpp
@@ -0,0 +1,143 @@
+
+///////////////////////////////////////////////////////////////////////////////
+// Copyright 2013 Nikhar Agrawal
+// Copyright 2013 Christopher Kormanyos
+// Copyright 2013 John Maddock
+// Copyright 2013 Paul Bristow
+// Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef _BOOST_BERNOULLI_B2N_2013_05_30_HPP_
+#define _BOOST_BERNOULLI_B2N_2013_05_30_HPP_
+
+#include <boost/math/special_functions/math_fwd.hpp>
+#include <boost/math/special_functions/detail/unchecked_bernoulli.hpp>
+#include <boost/math/special_functions/detail/bernoulli_details.hpp>
+
+namespace boost { namespace math {
+
+namespace detail {
+
+template <class T, class OutputIterator, class Policy, int N>
+OutputIterator bernoulli_number_imp(OutputIterator out, std::size_t start, std::size_t n, const Policy& pol, const mpl::int_<N>& tag)
+{
+ for(std::size_t i = start; (i <= max_bernoulli_b2n<T>::value) && (i < start + n); ++i)
+ {
+ *out = unchecked_bernoulli_imp<T>(i, tag);
+ ++out;
+ }
+
+ for(std::size_t i = (std::max)(static_cast<std::size_t>(max_bernoulli_b2n<T>::value + 1), start); i < start + n; ++i)
+ {
+ // We must overflow:
+ *out = (i & 1 ? 1 : -1) * policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(n)", 0, T(i), pol);
+ ++out;
+ }
+ return out;
+}
+
+template <class T, class OutputIterator, class Policy>
+OutputIterator bernoulli_number_imp(OutputIterator out, std::size_t start, std::size_t n, const Policy& pol, const mpl::int_<0>& tag)
+{
+ for(std::size_t i = start; (i <= max_bernoulli_b2n<T>::value) && (i < start + n); ++i)
+ {
+ *out = unchecked_bernoulli_imp<T>(i, tag);
+ ++out;
+ }
+ //
+ // Short circuit return so we don't grab the mutex below unless we have to:
+ //
+ if(start + n <= max_bernoulli_b2n<T>::value)
+ return out;
+
+ return get_bernoulli_numbers_cache<T, Policy>().copy_bernoulli_numbers(out, start, n, pol);
+}
+
+} // namespace detail
+
+template <class T, class Policy>
+inline T bernoulli_b2n(const int i, const Policy &pol)
+{
+ typedef mpl::int_<detail::bernoulli_imp_variant<T>::value> tag_type;
+ if(i < 0)
+ return policies::raise_domain_error<T>("boost::math::bernoulli_b2n<%1%>", "Index should be >= 0 but got %1%", T(i), pol);
+
+ T result;
+ boost::math::detail::bernoulli_number_imp<T>(&result, static_cast<std::size_t>(i), 1u, pol, tag_type());
+ return result;
+}
+
+template <class T>
+inline T bernoulli_b2n(const int i)
+{
+ return boost::math::bernoulli_b2n<T>(i, policies::policy<>());
+}
+
+template <class T, class OutputIterator, class Policy>
+inline OutputIterator bernoulli_b2n(const int start_index,
+ const unsigned number_of_bernoullis_b2n,
+ OutputIterator out_it,
+ const Policy& pol)
+{
+ typedef mpl::int_<detail::bernoulli_imp_variant<T>::value> tag_type;
+ if(start_index < 0)
+ {
+ *out_it = policies::raise_domain_error<T>("boost::math::bernoulli_b2n<%1%>", "Index should be >= 0 but got %1%", T(start_index), pol);
+ return ++out_it;
+ }
+
+ return boost::math::detail::bernoulli_number_imp<T>(out_it, start_index, number_of_bernoullis_b2n, pol, tag_type());
+}
+
+template <class T, class OutputIterator>
+inline OutputIterator bernoulli_b2n(const int start_index,
+ const unsigned number_of_bernoullis_b2n,
+ OutputIterator out_it)
+{
+ return boost::math::bernoulli_b2n<T, OutputIterator>(start_index, number_of_bernoullis_b2n, out_it, policies::policy<>());
+}
+
+template <class T, class Policy>
+inline T tangent_t2n(const int i, const Policy &pol)
+{
+ if(i < 0)
+ return policies::raise_domain_error<T>("boost::math::tangent_t2n<%1%>", "Index should be >= 0 but got %1%", T(i), pol);
+
+ T result;
+ boost::math::detail::get_bernoulli_numbers_cache<T, Policy>().copy_tangent_numbers(&result, i, 1, pol);
+ return result;
+}
+
+template <class T>
+inline T tangent_t2n(const int i)
+{
+ return boost::math::tangent_t2n<T>(i, policies::policy<>());
+}
+
+template <class T, class OutputIterator, class Policy>
+inline OutputIterator tangent_t2n(const int start_index,
+ const unsigned number_of_tangent_t2n,
+ OutputIterator out_it,
+ const Policy& pol)
+{
+ if(start_index < 0)
+ {
+ *out_it = policies::raise_domain_error<T>("boost::math::tangent_t2n<%1%>", "Index should be >= 0 but got %1%", T(start_index), pol);
+ return ++out_it;
+ }
+
+ return boost::math::detail::get_bernoulli_numbers_cache<T, Policy>().copy_tangent_numbers(out_it, start_index, number_of_tangent_t2n, pol);
+}
+
+template <class T, class OutputIterator>
+inline OutputIterator tangent_t2n(const int start_index,
+ const unsigned number_of_tangent_t2n,
+ OutputIterator out_it)
+{
+ return boost::math::tangent_t2n<T, OutputIterator>(start_index, number_of_tangent_t2n, out_it, policies::policy<>());
+}
+
+} } // namespace boost::math
+
+#endif // _BOOST_BERNOULLI_B2N_2013_05_30_HPP_
diff --git a/boost/math/special_functions/bessel.hpp b/boost/math/special_functions/bessel.hpp
index d9d3c60bd0..438b763ab7 100644
--- a/boost/math/special_functions/bessel.hpp
+++ b/boost/math/special_functions/bessel.hpp
@@ -1,4 +1,5 @@
-// Copyright (c) 2007 John Maddock
+// Copyright (c) 2007, 2013 John Maddock
+// Copyright Christopher Kormanyos 2013.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -11,12 +12,15 @@
#define BOOST_MATH_BESSEL_HPP
#ifdef _MSC_VER
-#pragma once
+# pragma once
#endif
+#include <limits>
+#include <boost/math/special_functions/math_fwd.hpp>
#include <boost/math/special_functions/detail/bessel_jy.hpp>
#include <boost/math/special_functions/detail/bessel_jn.hpp>
#include <boost/math/special_functions/detail/bessel_yn.hpp>
+#include <boost/math/special_functions/detail/bessel_jy_zero.hpp>
#include <boost/math/special_functions/detail/bessel_ik.hpp>
#include <boost/math/special_functions/detail/bessel_i0.hpp>
#include <boost/math/special_functions/detail/bessel_i1.hpp>
@@ -30,6 +34,7 @@
#include <boost/math/tools/rational.hpp>
#include <boost/math/tools/promotion.hpp>
#include <boost/math/tools/series.hpp>
+#include <boost/math/tools/roots.hpp>
namespace boost{ namespace math{
@@ -45,7 +50,13 @@ struct sph_bessel_j_small_z_series_term
{
BOOST_MATH_STD_USING
mult = x / 2;
- term = pow(mult, T(v)) / boost::math::tgamma(v+1+T(0.5f), Policy());
+ if(v + 3 > max_factorial<T>::value)
+ {
+ term = v * log(mult) - boost::math::lgamma(v+1+T(0.5f), Policy());
+ term = exp(term);
+ }
+ else
+ term = pow(mult, T(v)) / boost::math::tgamma(v+1+T(0.5f), Policy());
mult *= -mult;
}
T operator()()
@@ -98,22 +109,6 @@ T cyl_bessel_j_imp(T v, T x, const bessel_no_int_tag& t, const Policy& pol)
function,
"Got x = %1%, but we need x >= 0", x, pol);
}
- if(x == 0)
- return (v == 0) ? 1 : (v > 0) ? 0 :
- policies::raise_domain_error<T>(
- function,
- "Got v = %1%, but require v >= 0 or a negative integer: the result would be complex.", v, pol);
-
-
- if((v >= 0) && ((x < 1) || (v > x * x / 4) || (x < 5)))
- {
- //
- // This series will actually converge rapidly for all small
- // x - say up to x < 20 - but the first few terms are large
- // and divergent which leads to large errors :-(
- //
- return bessel_j_small_z_series(v, x, pol);
- }
T j, y;
bessel_jy(v, x, &j, &y, need_j, pol);
@@ -125,9 +120,11 @@ inline T cyl_bessel_j_imp(T v, T x, const bessel_maybe_int_tag&, const Policy& p
{
BOOST_MATH_STD_USING // ADL of std names.
int ival = detail::iconv(v, pol);
- if((abs(ival) < 200) && (0 == v - ival))
+ // If v is an integer, use the integer recursion
+ // method, both that and Steeds method are O(v):
+ if((0 == v - ival))
{
- return bessel_jn(ival/*iround(v, pol)*/, x, pol);
+ return bessel_jn(ival, x, pol);
}
return cyl_bessel_j_imp(v, x, bessel_no_int_tag(), pol);
}
@@ -153,6 +150,11 @@ inline T sph_bessel_j_imp(unsigned n, T x, const Policy& pol)
if(n == 0)
return boost::math::sinc_pi(x, pol);
//
+ // Special case for x == 0:
+ //
+ if(x == 0)
+ return 0;
+ //
// When x is small we may end up with 0/0, use series evaluation
// instead, especially as it converges rapidly:
//
@@ -294,14 +296,13 @@ template <class T, class Policy>
inline T cyl_neumann_imp(T v, T x, const bessel_maybe_int_tag&, const Policy& pol)
{
BOOST_MATH_STD_USING
- typedef typename bessel_asymptotic_tag<T, Policy>::type tag_type;
BOOST_MATH_INSTRUMENT_VARIABLE(v);
BOOST_MATH_INSTRUMENT_VARIABLE(x);
if(floor(v) == v)
{
- if((fabs(x) > asymptotic_bessel_y_limit<T>(tag_type())) && (fabs(x) > 5 * abs(v)))
+ if(asymptotic_bessel_large_x_limit(v, x))
{
T r = asymptotic_bessel_y_large_x_2(static_cast<T>(abs(v)), x);
if((v < 0) && (itrunc(v, pol) & 1))
@@ -325,12 +326,11 @@ template <class T, class Policy>
inline T cyl_neumann_imp(int v, T x, const bessel_int_tag&, const Policy& pol)
{
BOOST_MATH_STD_USING
- typedef typename bessel_asymptotic_tag<T, Policy>::type tag_type;
BOOST_MATH_INSTRUMENT_VARIABLE(v);
BOOST_MATH_INSTRUMENT_VARIABLE(x);
- if((fabs(x) > asymptotic_bessel_y_limit<T>(tag_type())) && (fabs(x) > 5 * abs(v)))
+ if(asymptotic_bessel_large_x_limit(T(v), x))
{
T r = asymptotic_bessel_y_large_x_2(static_cast<T>(abs(v)), x);
if((v < 0) && (v & 1))
@@ -367,16 +367,180 @@ inline T sph_neumann_imp(unsigned v, T x, const Policy& pol)
return result * tx;
}
+template <class T, class Policy>
+inline T cyl_bessel_j_zero_imp(T v, int m, const Policy& pol)
+{
+ BOOST_MATH_STD_USING // ADL of std names, needed for floor.
+
+ static const char* function = "boost::math::cyl_bessel_j_zero<%1%>(%1%, int)";
+
+ const T half_epsilon(boost::math::tools::epsilon<T>() / 2U);
+
+ // Handle non-finite order.
+ if (!(boost::math::isfinite)(v) )
+ {
+ return policies::raise_domain_error<T>(function, "Order argument is %1%, but must be finite >= 0 !", v, pol);
+ }
+
+ // Handle negative rank.
+ if(m < 0)
+ {
+ // Zeros of Jv(x) with negative rank are not defined and requesting one raises a domain error.
+ return policies::raise_domain_error<T>(function, "Requested the %1%'th zero, but the rank must be positive !", m, pol);
+ }
+
+ // Get the absolute value of the order.
+ const bool order_is_negative = (v < 0);
+ const T vv((!order_is_negative) ? v : T(-v));
+
+ // Check if the order is very close to zero or very close to an integer.
+ const bool order_is_zero = (vv < half_epsilon);
+ const bool order_is_integer = ((vv - floor(vv)) < half_epsilon);
+
+ if(m == 0)
+ {
+ if(order_is_zero)
+ {
+ // The zero'th zero of J0(x) is not defined and requesting it raises a domain error.
+ return policies::raise_domain_error<T>(function, "Requested the %1%'th zero of J0, but the rank must be > 0 !", m, pol);
+ }
+
+ // The zero'th zero of Jv(x) for v < 0 is not defined
+ // unless the order is a negative integer.
+ if(order_is_negative && (!order_is_integer))
+ {
+ // For non-integer, negative order, requesting the zero'th zero raises a domain error.
+ return policies::raise_domain_error<T>(function, "Requested the %1%'th zero of Jv for negative, non-integer order, but the rank must be > 0 !", m, pol);
+ }
+
+ // The zero'th zero does exist and its value is zero.
+ return T(0);
+ }
+
+ // Set up the initial guess for the upcoming root-finding.
+ // If the order is a negative integer, then use the corresponding
+ // positive integer for the order.
+ const T guess_root = boost::math::detail::bessel_zero::cyl_bessel_j_zero_detail::initial_guess<T, Policy>((order_is_integer ? vv : v), m, pol);
+
+ // Select the maximum allowed iterations from the policy.
+ boost::uintmax_t number_of_iterations = policies::get_max_root_iterations<Policy>();
+
+ const T delta_lo = ((guess_root > 0.2F) ? T(0.2) : T(guess_root / 2U));
+
+ // Perform the root-finding using Newton-Raphson iteration from Boost.Math.
+ const T jvm =
+ boost::math::tools::newton_raphson_iterate(
+ boost::math::detail::bessel_zero::cyl_bessel_j_zero_detail::function_object_jv_and_jv_prime<T, Policy>((order_is_integer ? vv : v), order_is_zero, pol),
+ guess_root,
+ T(guess_root - delta_lo),
+ T(guess_root + 0.2F),
+ policies::digits<T, Policy>(),
+ number_of_iterations);
+
+ if(number_of_iterations >= policies::get_max_root_iterations<Policy>())
+ {
+ return policies::raise_evaluation_error<T>(function, "Unable to locate root in a reasonable time:"
+ " Current best guess is %1%", jvm, Policy());
+ }
+
+ return jvm;
+}
+
+template <class T, class Policy>
+inline T cyl_neumann_zero_imp(T v, int m, const Policy& pol)
+{
+ BOOST_MATH_STD_USING // ADL of std names, needed for floor.
+
+ static const char* function = "boost::math::cyl_neumann_zero<%1%>(%1%, int)";
+
+ // Handle non-finite order.
+ if (!(boost::math::isfinite)(v) )
+ {
+ return policies::raise_domain_error<T>(function, "Order argument is %1%, but must be finite >= 0 !", v, pol);
+ }
+
+ // Handle negative rank.
+ if(m < 0)
+ {
+ return policies::raise_domain_error<T>(function, "Requested the %1%'th zero, but the rank must be positive !", m, pol);
+ }
+
+ const T half_epsilon(boost::math::tools::epsilon<T>() / 2U);
+
+ // Get the absolute value of the order.
+ const bool order_is_negative = (v < 0);
+ const T vv((!order_is_negative) ? v : T(-v));
+
+ const bool order_is_integer = ((vv - floor(vv)) < half_epsilon);
+
+ // For negative integers, use reflection to positive integer order.
+ if(order_is_negative && order_is_integer)
+ return boost::math::detail::cyl_neumann_zero_imp(vv, m, pol);
+
+ // Check if the order is very close to a negative half-integer.
+ const T delta_half_integer(vv - (floor(vv) + 0.5F));
+
+ const bool order_is_negative_half_integer =
+ (order_is_negative && ((delta_half_integer > -half_epsilon) && (delta_half_integer < +half_epsilon)));
+
+ // The zero'th zero of Yv(x) for v < 0 is not defined
+ // unless the order is a negative integer.
+ if((m == 0) && (!order_is_negative_half_integer))
+ {
+ // For non-integer, negative order, requesting the zero'th zero raises a domain error.
+ return policies::raise_domain_error<T>(function, "Requested the %1%'th zero of Yv for negative, non-half-integer order, but the rank must be > 0 !", m, pol);
+ }
+
+ // For negative half-integers, use the corresponding
+ // spherical Bessel function of positive half-integer order.
+ if(order_is_negative_half_integer)
+ return boost::math::detail::cyl_bessel_j_zero_imp(vv, m, pol);
+
+ // Set up the initial guess for the upcoming root-finding.
+ // If the order is a negative integer, then use the corresponding
+ // positive integer for the order.
+ const T guess_root = boost::math::detail::bessel_zero::cyl_neumann_zero_detail::initial_guess<T, Policy>(v, m, pol);
+
+ // Select the maximum allowed iterations from the policy.
+ boost::uintmax_t number_of_iterations = policies::get_max_root_iterations<Policy>();
+
+ const T delta_lo = ((guess_root > 0.2F) ? T(0.2) : T(guess_root / 2U));
+
+ // Perform the root-finding using Newton-Raphson iteration from Boost.Math.
+ const T yvm =
+ boost::math::tools::newton_raphson_iterate(
+ boost::math::detail::bessel_zero::cyl_neumann_zero_detail::function_object_yv_and_yv_prime<T, Policy>(v, pol),
+ guess_root,
+ T(guess_root - delta_lo),
+ T(guess_root + 0.2F),
+ policies::digits<T, Policy>(),
+ number_of_iterations);
+
+ if(number_of_iterations >= policies::get_max_root_iterations<Policy>())
+ {
+ return policies::raise_evaluation_error<T>(function, "Unable to locate root in a reasonable time:"
+ " Current best guess is %1%", yvm, Policy());
+ }
+
+ return yvm;
+}
+
} // namespace detail
template <class T1, class T2, class Policy>
-inline typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_bessel_j(T1 v, T2 x, const Policy& pol)
+inline typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_bessel_j(T1 v, T2 x, const Policy& /* pol */)
{
BOOST_FPU_EXCEPTION_GUARD
typedef typename detail::bessel_traits<T1, T2, Policy>::result_type result_type;
typedef typename detail::bessel_traits<T1, T2, Policy>::optimisation_tag tag_type;
typedef typename policies::evaluation<result_type, Policy>::type value_type;
- return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_bessel_j_imp<value_type>(v, static_cast<value_type>(x), tag_type(), pol), "boost::math::cyl_bessel_j<%1%>(%1%,%1%)");
+ typedef typename policies::normalise<
+ Policy,
+ policies::promote_float<false>,
+ policies::promote_double<false>,
+ policies::discrete_quantile<>,
+ policies::assert_undefined<> >::type forwarding_policy;
+ return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_bessel_j_imp<value_type>(v, static_cast<value_type>(x), tag_type(), forwarding_policy()), "boost::math::cyl_bessel_j<%1%>(%1%,%1%)");
}
template <class T1, class T2>
@@ -386,12 +550,18 @@ inline typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type
}
template <class T, class Policy>
-inline typename detail::bessel_traits<T, T, Policy>::result_type sph_bessel(unsigned v, T x, const Policy& pol)
+inline typename detail::bessel_traits<T, T, Policy>::result_type sph_bessel(unsigned v, T x, const Policy& /* pol */)
{
BOOST_FPU_EXCEPTION_GUARD
typedef typename detail::bessel_traits<T, T, Policy>::result_type result_type;
typedef typename policies::evaluation<result_type, Policy>::type value_type;
- return policies::checked_narrowing_cast<result_type, Policy>(detail::sph_bessel_j_imp<value_type>(v, static_cast<value_type>(x), pol), "boost::math::sph_bessel<%1%>(%1%,%1%)");
+ typedef typename policies::normalise<
+ Policy,
+ policies::promote_float<false>,
+ policies::promote_double<false>,
+ policies::discrete_quantile<>,
+ policies::assert_undefined<> >::type forwarding_policy;
+ return policies::checked_narrowing_cast<result_type, Policy>(detail::sph_bessel_j_imp<value_type>(v, static_cast<value_type>(x), forwarding_policy()), "boost::math::sph_bessel<%1%>(%1%,%1%)");
}
template <class T>
@@ -401,12 +571,18 @@ inline typename detail::bessel_traits<T, T, policies::policy<> >::result_type sp
}
template <class T1, class T2, class Policy>
-inline typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_bessel_i(T1 v, T2 x, const Policy& pol)
+inline typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_bessel_i(T1 v, T2 x, const Policy& /* pol */)
{
BOOST_FPU_EXCEPTION_GUARD
typedef typename detail::bessel_traits<T1, T2, Policy>::result_type result_type;
typedef typename policies::evaluation<result_type, Policy>::type value_type;
- return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_bessel_i_imp<value_type>(v, static_cast<value_type>(x), pol), "boost::math::cyl_bessel_i<%1%>(%1%,%1%)");
+ typedef typename policies::normalise<
+ Policy,
+ policies::promote_float<false>,
+ policies::promote_double<false>,
+ policies::discrete_quantile<>,
+ policies::assert_undefined<> >::type forwarding_policy;
+ return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_bessel_i_imp<value_type>(v, static_cast<value_type>(x), forwarding_policy()), "boost::math::cyl_bessel_i<%1%>(%1%,%1%)");
}
template <class T1, class T2>
@@ -416,13 +592,19 @@ inline typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type
}
template <class T1, class T2, class Policy>
-inline typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_bessel_k(T1 v, T2 x, const Policy& pol)
+inline typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_bessel_k(T1 v, T2 x, const Policy& /* pol */)
{
BOOST_FPU_EXCEPTION_GUARD
typedef typename detail::bessel_traits<T1, T2, Policy>::result_type result_type;
typedef typename detail::bessel_traits<T1, T2, Policy>::optimisation_tag tag_type;
typedef typename policies::evaluation<result_type, Policy>::type value_type;
- return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_bessel_k_imp<value_type>(v, static_cast<value_type>(x), tag_type(), pol), "boost::math::cyl_bessel_k<%1%>(%1%,%1%)");
+ typedef typename policies::normalise<
+ Policy,
+ policies::promote_float<false>,
+ policies::promote_double<false>,
+ policies::discrete_quantile<>,
+ policies::assert_undefined<> >::type forwarding_policy;
+ return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_bessel_k_imp<value_type>(v, static_cast<value_type>(x), tag_type(), forwarding_policy()), "boost::math::cyl_bessel_k<%1%>(%1%,%1%)");
}
template <class T1, class T2>
@@ -432,13 +614,19 @@ inline typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type
}
template <class T1, class T2, class Policy>
-inline typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_neumann(T1 v, T2 x, const Policy& pol)
+inline typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_neumann(T1 v, T2 x, const Policy& /* pol */)
{
BOOST_FPU_EXCEPTION_GUARD
typedef typename detail::bessel_traits<T1, T2, Policy>::result_type result_type;
typedef typename detail::bessel_traits<T1, T2, Policy>::optimisation_tag tag_type;
typedef typename policies::evaluation<result_type, Policy>::type value_type;
- return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_neumann_imp<value_type>(v, static_cast<value_type>(x), tag_type(), pol), "boost::math::cyl_neumann<%1%>(%1%,%1%)");
+ typedef typename policies::normalise<
+ Policy,
+ policies::promote_float<false>,
+ policies::promote_double<false>,
+ policies::discrete_quantile<>,
+ policies::assert_undefined<> >::type forwarding_policy;
+ return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_neumann_imp<value_type>(v, static_cast<value_type>(x), tag_type(), forwarding_policy()), "boost::math::cyl_neumann<%1%>(%1%,%1%)");
}
template <class T1, class T2>
@@ -448,12 +636,18 @@ inline typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type
}
template <class T, class Policy>
-inline typename detail::bessel_traits<T, T, Policy>::result_type sph_neumann(unsigned v, T x, const Policy& pol)
+inline typename detail::bessel_traits<T, T, Policy>::result_type sph_neumann(unsigned v, T x, const Policy& /* pol */)
{
BOOST_FPU_EXCEPTION_GUARD
typedef typename detail::bessel_traits<T, T, Policy>::result_type result_type;
typedef typename policies::evaluation<result_type, Policy>::type value_type;
- return policies::checked_narrowing_cast<result_type, Policy>(detail::sph_neumann_imp<value_type>(v, static_cast<value_type>(x), pol), "boost::math::sph_neumann<%1%>(%1%,%1%)");
+ typedef typename policies::normalise<
+ Policy,
+ policies::promote_float<false>,
+ policies::promote_double<false>,
+ policies::discrete_quantile<>,
+ policies::assert_undefined<> >::type forwarding_policy;
+ return policies::checked_narrowing_cast<result_type, Policy>(detail::sph_neumann_imp<value_type>(v, static_cast<value_type>(x), forwarding_policy()), "boost::math::sph_neumann<%1%>(%1%,%1%)");
}
template <class T>
@@ -462,8 +656,131 @@ inline typename detail::bessel_traits<T, T, policies::policy<> >::result_type sp
return sph_neumann(v, x, policies::policy<>());
}
+template <class T, class Policy>
+inline typename detail::bessel_traits<T, T, Policy>::result_type cyl_bessel_j_zero(T v, int m, const Policy& /* pol */)
+{
+ BOOST_FPU_EXCEPTION_GUARD
+ typedef typename detail::bessel_traits<T, T, Policy>::result_type result_type;
+ typedef typename policies::evaluation<result_type, Policy>::type value_type;
+ typedef typename policies::normalise<
+ Policy,
+ policies::promote_float<false>,
+ policies::promote_double<false>,
+ policies::discrete_quantile<>,
+ policies::assert_undefined<> >::type forwarding_policy;
+
+ BOOST_STATIC_ASSERT_MSG( false == std::numeric_limits<T>::is_specialized
+ || ( true == std::numeric_limits<T>::is_specialized
+ && false == std::numeric_limits<T>::is_integer),
+ "Order must be a floating-point type.");
+
+ return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_bessel_j_zero_imp<value_type>(v, m, forwarding_policy()), "boost::math::cyl_bessel_j_zero<%1%>(%1%,%1%)");
+}
+
+template <class T>
+inline typename detail::bessel_traits<T, T, policies::policy<> >::result_type cyl_bessel_j_zero(T v, int m)
+{
+ BOOST_STATIC_ASSERT_MSG( false == std::numeric_limits<T>::is_specialized
+ || ( true == std::numeric_limits<T>::is_specialized
+ && false == std::numeric_limits<T>::is_integer),
+ "Order must be a floating-point type.");
+
+ return cyl_bessel_j_zero<T, policies::policy<> >(v, m, policies::policy<>());
+}
+
+template <class T, class OutputIterator, class Policy>
+inline OutputIterator cyl_bessel_j_zero(T v,
+ int start_index,
+ unsigned number_of_zeros,
+ OutputIterator out_it,
+ const Policy& pol)
+{
+ BOOST_STATIC_ASSERT_MSG( false == std::numeric_limits<T>::is_specialized
+ || ( true == std::numeric_limits<T>::is_specialized
+ && false == std::numeric_limits<T>::is_integer),
+ "Order must be a floating-point type.");
+
+ for(int i = 0; i < static_cast<int>(number_of_zeros); ++i)
+ {
+ *out_it = boost::math::cyl_bessel_j_zero(v, start_index + i, pol);
+ ++out_it;
+ }
+ return out_it;
+}
+
+template <class T, class OutputIterator>
+inline OutputIterator cyl_bessel_j_zero(T v,
+ int start_index,
+ unsigned number_of_zeros,
+ OutputIterator out_it)
+{
+ return cyl_bessel_j_zero(v, start_index, number_of_zeros, out_it, policies::policy<>());
+}
+
+template <class T, class Policy>
+inline typename detail::bessel_traits<T, T, Policy>::result_type cyl_neumann_zero(T v, int m, const Policy& /* pol */)
+{
+ BOOST_FPU_EXCEPTION_GUARD
+ typedef typename detail::bessel_traits<T, T, Policy>::result_type result_type;
+ typedef typename policies::evaluation<result_type, Policy>::type value_type;
+ typedef typename policies::normalise<
+ Policy,
+ policies::promote_float<false>,
+ policies::promote_double<false>,
+ policies::discrete_quantile<>,
+ policies::assert_undefined<> >::type forwarding_policy;
+
+ BOOST_STATIC_ASSERT_MSG( false == std::numeric_limits<T>::is_specialized
+ || ( true == std::numeric_limits<T>::is_specialized
+ && false == std::numeric_limits<T>::is_integer),
+ "Order must be a floating-point type.");
+
+ return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_neumann_zero_imp<value_type>(v, m, forwarding_policy()), "boost::math::cyl_neumann_zero<%1%>(%1%,%1%)");
+}
+
+template <class T>
+inline typename detail::bessel_traits<T, T, policies::policy<> >::result_type cyl_neumann_zero(T v, int m)
+{
+ BOOST_STATIC_ASSERT_MSG( false == std::numeric_limits<T>::is_specialized
+ || ( true == std::numeric_limits<T>::is_specialized
+ && false == std::numeric_limits<T>::is_integer),
+ "Order must be a floating-point type.");
+
+ return cyl_neumann_zero<T, policies::policy<> >(v, m, policies::policy<>());
+}
+
+template <class T, class OutputIterator, class Policy>
+inline OutputIterator cyl_neumann_zero(T v,
+ int start_index,
+ unsigned number_of_zeros,
+ OutputIterator out_it,
+ const Policy& pol)
+{
+ BOOST_STATIC_ASSERT_MSG( false == std::numeric_limits<T>::is_specialized
+ || ( true == std::numeric_limits<T>::is_specialized
+ && false == std::numeric_limits<T>::is_integer),
+ "Order must be a floating-point type.");
+
+ for(int i = 0; i < static_cast<int>(number_of_zeros); ++i)
+ {
+ *out_it = boost::math::cyl_neumann_zero(v, start_index + i, pol);
+ ++out_it;
+ }
+ return out_it;
+}
+
+template <class T, class OutputIterator>
+inline OutputIterator cyl_neumann_zero(T v,
+ int start_index,
+ unsigned number_of_zeros,
+ OutputIterator out_it)
+{
+ return cyl_neumann_zero(v, start_index, number_of_zeros, out_it, policies::policy<>());
+}
+
} // namespace math
} // namespace boost
#endif // BOOST_MATH_BESSEL_HPP
+
diff --git a/boost/math/special_functions/bessel_prime.hpp b/boost/math/special_functions/bessel_prime.hpp
new file mode 100644
index 0000000000..c5f2d58c2b
--- /dev/null
+++ b/boost/math/special_functions/bessel_prime.hpp
@@ -0,0 +1,359 @@
+// Copyright (c) 2013 Anton Bikineev
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+#ifndef BOOST_MATH_BESSEL_DERIVATIVES_HPP
+#define BOOST_MATH_BESSEL_DERIVATIVES_HPP
+
+#ifdef _MSC_VER
+# pragma once
+#endif
+
+#include <boost/math/special_functions/math_fwd.hpp>
+#include <boost/math/special_functions/bessel.hpp>
+#include <boost/math/special_functions/detail/bessel_jy_derivatives_asym.hpp>
+#include <boost/math/special_functions/detail/bessel_jy_derivatives_series.hpp>
+#include <boost/math/special_functions/detail/bessel_derivatives_linear.hpp>
+
+namespace boost{ namespace math{
+
+namespace detail{
+
+template <class Tag, class T, class Policy>
+inline T cyl_bessel_j_prime_imp(T v, T x, const Policy& pol)
+{
+ static const char* const function = "boost::math::cyl_bessel_j_prime<%1%>(%1%,%1%)";
+ BOOST_MATH_STD_USING
+ //
+ // Prevent complex result:
+ //
+ if (x < 0 && floor(v) != v)
+ return boost::math::policies::raise_domain_error<T>(
+ function,
+ "Got x = %1%, but function requires x >= 0", x, pol);
+ //
+ // Special cases for x == 0:
+ //
+ if (x == 0)
+ {
+ if (v == 1)
+ return 0.5;
+ else if (v == -1)
+ return -0.5;
+ else if (floor(v) == v || v > 1)
+ return 0;
+ else return boost::math::policies::raise_domain_error<T>(
+ function,
+ "Got x = %1%, but function is indeterminate for this order", x, pol);
+ }
+ //
+ // Special case for large x: use asymptotic expansion:
+ //
+ if (boost::math::detail::asymptotic_bessel_derivative_large_x_limit(v, x))
+ return boost::math::detail::asymptotic_bessel_j_derivative_large_x_2(v, x);
+ //
+ // Special case for small x: use Taylor series:
+ //
+ if ((abs(x) < 5) || (abs(v) > x * x / 4))
+ {
+ bool inversed = false;
+ if (floor(v) == v && v < 0)
+ {
+ v = -v;
+ if (itrunc(v, pol) & 1)
+ inversed = true;
+ }
+ T r = boost::math::detail::bessel_j_derivative_small_z_series(v, x, pol);
+ return inversed ? T(-r) : r;
+ }
+ //
+ // Special case for v == 0:
+ //
+ if (v == 0)
+ return -boost::math::detail::cyl_bessel_j_imp<T>(1, x, Tag(), pol);
+ //
+ // Default case:
+ //
+ return boost::math::detail::bessel_j_derivative_linear(v, x, Tag(), pol);
+}
+
+template <class T, class Policy>
+inline T sph_bessel_j_prime_imp(unsigned v, T x, const Policy& pol)
+{
+ static const char* const function = "boost::math::sph_bessel_prime<%1%>(%1%,%1%)";
+ //
+ // Prevent complex result:
+ //
+ if (x < 0)
+ return boost::math::policies::raise_domain_error<T>(
+ function,
+ "Got x = %1%, but function requires x >= 0.", x, pol);
+ //
+ // Special case for v == 0:
+ //
+ if (v == 0)
+ return (x == 0) ? boost::math::policies::raise_overflow_error<T>(function, 0, pol)
+ : static_cast<T>(-boost::math::detail::sph_bessel_j_imp<T>(1, x, pol));
+ //
+ // Special case for x == 0 and v > 0:
+ //
+ if (x == 0)
+ return boost::math::policies::raise_domain_error<T>(
+ function,
+ "Got x = %1%, but function is indeterminate for this order", x, pol);
+ //
+ // Default case:
+ //
+ return boost::math::detail::sph_bessel_j_derivative_linear(v, x, pol);
+}
+
+template <class T, class Policy>
+inline T cyl_bessel_i_prime_imp(T v, T x, const Policy& pol)
+{
+ static const char* const function = "boost::math::cyl_bessel_i_prime<%1%>(%1%,%1%)";
+ BOOST_MATH_STD_USING
+ //
+ // Prevent complex result:
+ //
+ if (x < 0 && floor(v) != v)
+ return boost::math::policies::raise_domain_error<T>(
+ function,
+ "Got x = %1%, but function requires x >= 0", x, pol);
+ //
+ // Special cases for x == 0:
+ //
+ if (x == 0)
+ {
+ if (v == 1 || v == -1)
+ return 0.5;
+ else if (floor(v) == v || v > 1)
+ return 0;
+ else return boost::math::policies::raise_domain_error<T>(
+ function,
+ "Got x = %1%, but function is indeterminate for this order", x, pol);
+ }
+ //
+ // Special case for v == 0:
+ //
+ if (v == 0)
+ return boost::math::detail::cyl_bessel_i_imp<T>(1, x, pol);
+ //
+ // Default case:
+ //
+ return boost::math::detail::bessel_i_derivative_linear(v, x, pol);
+}
+
+template <class Tag, class T, class Policy>
+inline T cyl_bessel_k_prime_imp(T v, T x, const Policy& pol)
+{
+ //
+ // Prevent complex and indeterminate results:
+ //
+ if (x <= 0)
+ return boost::math::policies::raise_domain_error<T>(
+ "boost::math::cyl_bessel_k_prime<%1%>(%1%,%1%)",
+ "Got x = %1%, but function requires x > 0", x, pol);
+ //
+ // Special case for v == 0:
+ //
+ if (v == 0)
+ return -boost::math::detail::cyl_bessel_k_imp<T>(1, x, Tag(), pol);
+ //
+ // Default case:
+ //
+ return boost::math::detail::bessel_k_derivative_linear(v, x, Tag(), pol);
+}
+
+template <class Tag, class T, class Policy>
+inline T cyl_neumann_prime_imp(T v, T x, const Policy& pol)
+{
+ BOOST_MATH_STD_USING
+ //
+ // Prevent complex and indeterminate results:
+ //
+ if (x <= 0)
+ return boost::math::policies::raise_domain_error<T>(
+ "boost::math::cyl_neumann_prime<%1%>(%1%,%1%)",
+ "Got x = %1%, but function requires x > 0", x, pol);
+ //
+ // Special case for large x: use asymptotic expansion:
+ //
+ if (boost::math::detail::asymptotic_bessel_derivative_large_x_limit(v, x))
+ return boost::math::detail::asymptotic_bessel_y_derivative_large_x_2(v, x);
+ //
+ // Special case for small x: use Taylor series:
+ //
+ if (v > 0 && floor(v) != v)
+ {
+ const T eps = boost::math::policies::get_epsilon<T, Policy>();
+ if (log(eps / 2) > v * log((x * x) / (v * 4)))
+ return boost::math::detail::bessel_y_derivative_small_z_series(v, x, pol);
+ }
+ //
+ // Special case for v == 0:
+ //
+ if (v == 0)
+ return -boost::math::detail::cyl_neumann_imp<T>(1, x, Tag(), pol);
+ //
+ // Default case:
+ //
+ return boost::math::detail::bessel_y_derivative_linear(v, x, Tag(), pol);
+}
+
+template <class T, class Policy>
+inline T sph_neumann_prime_imp(unsigned v, T x, const Policy& pol)
+{
+ //
+ // Prevent complex and indeterminate result:
+ //
+ if (x <= 0)
+ return boost::math::policies::raise_domain_error<T>(
+ "boost::math::sph_neumann_prime<%1%>(%1%,%1%)",
+ "Got x = %1%, but function requires x > 0.", x, pol);
+ //
+ // Special case for v == 0:
+ //
+ if (v == 0)
+ return -boost::math::detail::sph_neumann_imp<T>(1, x, pol);
+ //
+ // Default case:
+ //
+ return boost::math::detail::sph_neumann_derivative_linear(v, x, pol);
+}
+
+} // namespace detail
+
+template <class T1, class T2, class Policy>
+inline typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_bessel_j_prime(T1 v, T2 x, const Policy& /* pol */)
+{
+ BOOST_FPU_EXCEPTION_GUARD
+ typedef typename detail::bessel_traits<T1, T2, Policy>::result_type result_type;
+ typedef typename detail::bessel_traits<T1, T2, Policy>::optimisation_tag tag_type;
+ typedef typename policies::evaluation<result_type, Policy>::type value_type;
+ typedef typename policies::normalise<
+ Policy,
+ policies::promote_float<false>,
+ policies::promote_double<false>,
+ policies::discrete_quantile<>,
+ policies::assert_undefined<> >::type forwarding_policy;
+ return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_bessel_j_prime_imp<tag_type, value_type>(v, static_cast<value_type>(x), forwarding_policy()), "boost::math::cyl_bessel_j_prime<%1%,%1%>(%1%,%1%)");
+}
+
+template <class T1, class T2>
+inline typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type cyl_bessel_j_prime(T1 v, T2 x)
+{
+ return cyl_bessel_j_prime(v, x, policies::policy<>());
+}
+
+template <class T, class Policy>
+inline typename detail::bessel_traits<T, T, Policy>::result_type sph_bessel_prime(unsigned v, T x, const Policy& /* pol */)
+{
+ BOOST_FPU_EXCEPTION_GUARD
+ typedef typename detail::bessel_traits<T, T, Policy>::result_type result_type;
+ typedef typename policies::evaluation<result_type, Policy>::type value_type;
+ typedef typename policies::normalise<
+ Policy,
+ policies::promote_float<false>,
+ policies::promote_double<false>,
+ policies::discrete_quantile<>,
+ policies::assert_undefined<> >::type forwarding_policy;
+ return policies::checked_narrowing_cast<result_type, Policy>(detail::sph_bessel_j_prime_imp<value_type>(v, static_cast<value_type>(x), forwarding_policy()), "boost::math::sph_bessel_j_prime<%1%>(%1%,%1%)");
+}
+
+template <class T>
+inline typename detail::bessel_traits<T, T, policies::policy<> >::result_type sph_bessel_prime(unsigned v, T x)
+{
+ return sph_bessel_prime(v, x, policies::policy<>());
+}
+
+template <class T1, class T2, class Policy>
+inline typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_bessel_i_prime(T1 v, T2 x, const Policy& /* pol */)
+{
+ BOOST_FPU_EXCEPTION_GUARD
+ typedef typename detail::bessel_traits<T1, T2, Policy>::result_type result_type;
+ typedef typename policies::evaluation<result_type, Policy>::type value_type;
+ typedef typename policies::normalise<
+ Policy,
+ policies::promote_float<false>,
+ policies::promote_double<false>,
+ policies::discrete_quantile<>,
+ policies::assert_undefined<> >::type forwarding_policy;
+ return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_bessel_i_prime_imp<value_type>(v, static_cast<value_type>(x), forwarding_policy()), "boost::math::cyl_bessel_i_prime<%1%>(%1%,%1%)");
+}
+
+template <class T1, class T2>
+inline typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type cyl_bessel_i_prime(T1 v, T2 x)
+{
+ return cyl_bessel_i_prime(v, x, policies::policy<>());
+}
+
+template <class T1, class T2, class Policy>
+inline typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_bessel_k_prime(T1 v, T2 x, const Policy& /* pol */)
+{
+ BOOST_FPU_EXCEPTION_GUARD
+ typedef typename detail::bessel_traits<T1, T2, Policy>::result_type result_type;
+ typedef typename detail::bessel_traits<T1, T2, Policy>::optimisation_tag tag_type;
+ typedef typename policies::evaluation<result_type, Policy>::type value_type;
+ typedef typename policies::normalise<
+ Policy,
+ policies::promote_float<false>,
+ policies::promote_double<false>,
+ policies::discrete_quantile<>,
+ policies::assert_undefined<> >::type forwarding_policy;
+ return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_bessel_k_prime_imp<tag_type, value_type>(v, static_cast<value_type>(x), forwarding_policy()), "boost::math::cyl_bessel_k_prime<%1%,%1%>(%1%,%1%)");
+}
+
+template <class T1, class T2>
+inline typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type cyl_bessel_k_prime(T1 v, T2 x)
+{
+ return cyl_bessel_k_prime(v, x, policies::policy<>());
+}
+
+template <class T1, class T2, class Policy>
+inline typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_neumann_prime(T1 v, T2 x, const Policy& /* pol */)
+{
+ BOOST_FPU_EXCEPTION_GUARD
+ typedef typename detail::bessel_traits<T1, T2, Policy>::result_type result_type;
+ typedef typename detail::bessel_traits<T1, T2, Policy>::optimisation_tag tag_type;
+ typedef typename policies::evaluation<result_type, Policy>::type value_type;
+ typedef typename policies::normalise<
+ Policy,
+ policies::promote_float<false>,
+ policies::promote_double<false>,
+ policies::discrete_quantile<>,
+ policies::assert_undefined<> >::type forwarding_policy;
+ return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_neumann_prime_imp<tag_type, value_type>(v, static_cast<value_type>(x), forwarding_policy()), "boost::math::cyl_neumann_prime<%1%,%1%>(%1%,%1%)");
+}
+
+template <class T1, class T2>
+inline typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type cyl_neumann_prime(T1 v, T2 x)
+{
+ return cyl_neumann_prime(v, x, policies::policy<>());
+}
+
+template <class T, class Policy>
+inline typename detail::bessel_traits<T, T, Policy>::result_type sph_neumann_prime(unsigned v, T x, const Policy& /* pol */)
+{
+ BOOST_FPU_EXCEPTION_GUARD
+ typedef typename detail::bessel_traits<T, T, Policy>::result_type result_type;
+ typedef typename policies::evaluation<result_type, Policy>::type value_type;
+ typedef typename policies::normalise<
+ Policy,
+ policies::promote_float<false>,
+ policies::promote_double<false>,
+ policies::discrete_quantile<>,
+ policies::assert_undefined<> >::type forwarding_policy;
+ return policies::checked_narrowing_cast<result_type, Policy>(detail::sph_neumann_prime_imp<value_type>(v, static_cast<value_type>(x), forwarding_policy()), "boost::math::sph_neumann_prime<%1%>(%1%,%1%)");
+}
+
+template <class T>
+inline typename detail::bessel_traits<T, T, policies::policy<> >::result_type sph_neumann_prime(unsigned v, T x)
+{
+ return sph_neumann_prime(v, x, policies::policy<>());
+}
+
+} // namespace math
+} // namespace boost
+
+#endif // BOOST_MATH_BESSEL_DERIVATIVES_HPP
diff --git a/boost/math/special_functions/beta.hpp b/boost/math/special_functions/beta.hpp
index 1177f44d60..8486b824f2 100644
--- a/boost/math/special_functions/beta.hpp
+++ b/boost/math/special_functions/beta.hpp
@@ -35,9 +35,9 @@ T beta_imp(T a, T b, const Lanczos&, const Policy& pol)
BOOST_MATH_STD_USING // for ADL of std names
if(a <= 0)
- policies::raise_domain_error<T>("boost::math::beta<%1%>(%1%,%1%)", "The arguments to the beta function must be greater than zero (got a=%1%).", a, pol);
+ return policies::raise_domain_error<T>("boost::math::beta<%1%>(%1%,%1%)", "The arguments to the beta function must be greater than zero (got a=%1%).", a, pol);
if(b <= 0)
- policies::raise_domain_error<T>("boost::math::beta<%1%>(%1%,%1%)", "The arguments to the beta function must be greater than zero (got b=%1%).", b, pol);
+ return policies::raise_domain_error<T>("boost::math::beta<%1%>(%1%,%1%)", "The arguments to the beta function must be greater than zero (got b=%1%).", b, pol);
T result;
@@ -119,9 +119,9 @@ T beta_imp(T a, T b, const lanczos::undefined_lanczos& /* l */, const Policy& po
BOOST_MATH_STD_USING
if(a <= 0)
- policies::raise_domain_error<T>("boost::math::beta<%1%>(%1%,%1%)", "The arguments to the beta function must be greater than zero (got a=%1%).", a, pol);
+ return policies::raise_domain_error<T>("boost::math::beta<%1%>(%1%,%1%)", "The arguments to the beta function must be greater than zero (got a=%1%).", a, pol);
if(b <= 0)
- policies::raise_domain_error<T>("boost::math::beta<%1%>(%1%,%1%)", "The arguments to the beta function must be greater than zero (got b=%1%).", b, pol);
+ return policies::raise_domain_error<T>("boost::math::beta<%1%>(%1%,%1%)", "The arguments to the beta function must be greater than zero (got b=%1%).", b, pol);
T result;
@@ -597,7 +597,7 @@ struct ibeta_fraction2_t
{
typedef std::pair<T, T> result_type;
- ibeta_fraction2_t(T a_, T b_, T x_) : a(a_), b(b_), x(x_), m(0) {}
+ ibeta_fraction2_t(T a_, T b_, T x_, T y_) : a(a_), b(b_), x(x_), y(y_), m(0) {}
result_type operator()()
{
@@ -607,7 +607,7 @@ struct ibeta_fraction2_t
T bN = m;
bN += (m * (b - m) * x) / (a + 2*m - 1);
- bN += ((a + m) * (a - (a + b) * x + 1 + m *(2 - x))) / (a + 2*m + 1);
+ bN += ((a + m) * (a * y - b * x + 1 + m *(2 - x))) / (a + 2*m + 1);
++m;
@@ -615,7 +615,7 @@ struct ibeta_fraction2_t
}
private:
- T a, b, x;
+ T a, b, x, y;
int m;
};
//
@@ -635,8 +635,10 @@ inline T ibeta_fraction2(T a, T b, T x, T y, const Policy& pol, bool normalised,
if(result == 0)
return result;
- ibeta_fraction2_t<T> f(a, b, x);
+ ibeta_fraction2_t<T> f(a, b, x, y);
T fract = boost::math::tools::continued_fraction_b(f, boost::math::policies::get_epsilon<T, Policy>());
+ BOOST_MATH_INSTRUMENT_VARIABLE(fract);
+ BOOST_MATH_INSTRUMENT_VARIABLE(result);
return result / fract;
}
//
@@ -887,19 +889,19 @@ T ibeta_imp(T a, T b, T x, const Policy& pol, bool inv, bool normalised, T* p_de
*p_derivative = -1; // value not set.
if((x < 0) || (x > 1))
- policies::raise_domain_error<T>(function, "Parameter x outside the range [0,1] in the incomplete beta function (got x=%1%).", x, pol);
+ return policies::raise_domain_error<T>(function, "Parameter x outside the range [0,1] in the incomplete beta function (got x=%1%).", x, pol);
if(normalised)
{
if(a < 0)
- policies::raise_domain_error<T>(function, "The argument a to the incomplete beta function must be >= zero (got a=%1%).", a, pol);
+ return policies::raise_domain_error<T>(function, "The argument a to the incomplete beta function must be >= zero (got a=%1%).", a, pol);
if(b < 0)
- policies::raise_domain_error<T>(function, "The argument b to the incomplete beta function must be >= zero (got b=%1%).", b, pol);
+ return policies::raise_domain_error<T>(function, "The argument b to the incomplete beta function must be >= zero (got b=%1%).", b, pol);
// extend to a few very special cases:
if(a == 0)
{
if(b == 0)
- policies::raise_domain_error<T>(function, "The arguments a and b to the incomplete beta function cannot both be zero, with x=%1%.", x, pol);
+ return policies::raise_domain_error<T>(function, "The arguments a and b to the incomplete beta function cannot both be zero, with x=%1%.", x, pol);
if(b > 0)
return inv ? 0 : 1;
}
@@ -912,9 +914,9 @@ T ibeta_imp(T a, T b, T x, const Policy& pol, bool inv, bool normalised, T* p_de
else
{
if(a <= 0)
- policies::raise_domain_error<T>(function, "The argument a to the incomplete beta function must be greater than zero (got a=%1%).", a, pol);
+ return policies::raise_domain_error<T>(function, "The argument a to the incomplete beta function must be greater than zero (got a=%1%).", a, pol);
if(b <= 0)
- policies::raise_domain_error<T>(function, "The argument b to the incomplete beta function must be greater than zero (got b=%1%).", b, pol);
+ return policies::raise_domain_error<T>(function, "The argument b to the incomplete beta function must be greater than zero (got b=%1%).", b, pol);
}
if(x == 0)
@@ -933,6 +935,49 @@ T ibeta_imp(T a, T b, T x, const Policy& pol, bool inv, bool normalised, T* p_de
}
return (invert == 0 ? (normalised ? 1 : boost::math::beta(a, b, pol)) : 0);
}
+ if((a == 0.5f) && (b == 0.5f))
+ {
+ // We have an arcsine distribution:
+ if(p_derivative)
+ {
+ *p_derivative = 1 / constants::pi<T>() * sqrt(y * x);
+ }
+ T p = invert ? asin(sqrt(y)) / constants::half_pi<T>() : asin(sqrt(x)) / constants::half_pi<T>();
+ if(!normalised)
+ p *= constants::pi<T>();
+ return p;
+ }
+ if(a == 1)
+ {
+ std::swap(a, b);
+ std::swap(x, y);
+ invert = !invert;
+ }
+ if(b == 1)
+ {
+ //
+ // Special case see: http://functions.wolfram.com/GammaBetaErf/BetaRegularized/03/01/01/
+ //
+ if(a == 1)
+ {
+ if(p_derivative)
+ *p_derivative = 1;
+ return invert ? y : x;
+ }
+
+ if(p_derivative)
+ {
+ *p_derivative = a * pow(x, a - 1);
+ }
+ T p;
+ if(y < 0.5)
+ p = invert ? T(-boost::math::expm1(a * boost::math::log1p(-y, pol), pol)) : T(exp(a * boost::math::log1p(-y, pol)));
+ else
+ p = invert ? T(-boost::math::powm1(x, a, pol)) : T(pow(x, a));
+ if(!normalised)
+ p /= a;
+ return p;
+ }
if((std::min)(a, b) <= 1)
{
@@ -1115,7 +1160,7 @@ T ibeta_imp(T a, T b, T x, const Policy& pol, bool inv, bool normalised, T* p_de
if(b < 40)
{
- if((floor(a) == a) && (floor(b) == b))
+ if((floor(a) == a) && (floor(b) == b) && (a < (std::numeric_limits<int>::max)() - 100))
{
// relate to the binomial distribution and use a finite sum:
T k = a - 1;
@@ -1236,11 +1281,11 @@ T ibeta_derivative_imp(T a, T b, T x, const Policy& pol)
// start with the usual error checks:
//
if(a <= 0)
- policies::raise_domain_error<T>(function, "The argument a to the incomplete beta function must be greater than zero (got a=%1%).", a, pol);
+ return policies::raise_domain_error<T>(function, "The argument a to the incomplete beta function must be greater than zero (got a=%1%).", a, pol);
if(b <= 0)
- policies::raise_domain_error<T>(function, "The argument b to the incomplete beta function must be greater than zero (got b=%1%).", b, pol);
+ return policies::raise_domain_error<T>(function, "The argument b to the incomplete beta function must be greater than zero (got b=%1%).", b, pol);
if((x < 0) || (x > 1))
- policies::raise_domain_error<T>(function, "Parameter x outside the range [0,1] in the incomplete beta function (got x=%1%).", x, pol);
+ return policies::raise_domain_error<T>(function, "Parameter x outside the range [0,1] in the incomplete beta function (got x=%1%).", x, pol);
//
// Now the corner cases:
//
@@ -1329,7 +1374,6 @@ inline typename tools::promote_args<RT1, RT2, RT3>::type
BOOST_FPU_EXCEPTION_GUARD
typedef typename tools::promote_args<RT1, RT2, RT3>::type result_type;
typedef typename policies::evaluation<result_type, Policy>::type value_type;
- typedef typename lanczos::lanczos<value_type, Policy>::type evaluation_type;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
@@ -1347,7 +1391,6 @@ inline typename tools::promote_args<RT1, RT2, RT3>::type
BOOST_FPU_EXCEPTION_GUARD
typedef typename tools::promote_args<RT1, RT2, RT3>::type result_type;
typedef typename policies::evaluation<result_type, Policy>::type value_type;
- typedef typename lanczos::lanczos<value_type, Policy>::type evaluation_type;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
diff --git a/boost/math/special_functions/binomial.hpp b/boost/math/special_functions/binomial.hpp
index 16b4f3305d..8fa2e26d84 100644
--- a/boost/math/special_functions/binomial.hpp
+++ b/boost/math/special_functions/binomial.hpp
@@ -10,6 +10,7 @@
#pragma once
#endif
+#include <boost/math/special_functions/math_fwd.hpp>
#include <boost/math/special_functions/factorials.hpp>
#include <boost/math/special_functions/beta.hpp>
#include <boost/math/policies/error_handling.hpp>
diff --git a/boost/math/special_functions/cos_pi.hpp b/boost/math/special_functions/cos_pi.hpp
index 93102c1cb3..18d06c00df 100644
--- a/boost/math/special_functions/cos_pi.hpp
+++ b/boost/math/special_functions/cos_pi.hpp
@@ -10,6 +10,7 @@
#pragma once
#endif
+#include <boost/math/special_functions/math_fwd.hpp>
#include <boost/config/no_tr1/cmath.hpp>
#include <boost/math/tools/config.hpp>
#include <boost/math/special_functions/trunc.hpp>
diff --git a/boost/math/special_functions/detail/airy_ai_bi_zero.hpp b/boost/math/special_functions/detail/airy_ai_bi_zero.hpp
new file mode 100644
index 0000000000..dbb7388dda
--- /dev/null
+++ b/boost/math/special_functions/detail/airy_ai_bi_zero.hpp
@@ -0,0 +1,160 @@
+// Copyright (c) 2013 Christopher Kormanyos
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// This work is based on an earlier work:
+// "Algorithm 910: A Portable C++ Multiple-Precision System for Special-Function Calculations",
+// in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. http://doi.acm.org/10.1145/1916461.1916469
+//
+// This header contains implementation details for estimating the zeros
+// of the Airy functions airy_ai and airy_bi on the negative real axis.
+//
+#ifndef _AIRY_AI_BI_ZERO_2013_01_20_HPP_
+ #define _AIRY_AI_BI_ZERO_2013_01_20_HPP_
+
+ #include <boost/math/constants/constants.hpp>
+ #include <boost/math/special_functions/cbrt.hpp>
+
+ namespace boost { namespace math {
+ namespace detail
+ {
+ // Forward declarations of the needed Airy function implementations.
+ template <class T, class Policy>
+ T airy_ai_imp(T x, const Policy& pol);
+ template <class T, class Policy>
+ T airy_bi_imp(T x, const Policy& pol);
+ template <class T, class Policy>
+ T airy_ai_prime_imp(T x, const Policy& pol);
+ template <class T, class Policy>
+ T airy_bi_prime_imp(T x, const Policy& pol);
+
+ namespace airy_zero
+ {
+ template<class T>
+ T equation_as_10_4_105(const T& z)
+ {
+ const T one_over_z (T(1) / z);
+ const T one_over_z_squared(one_over_z * one_over_z);
+
+ const T z_pow_third (boost::math::cbrt(z));
+ const T z_pow_two_thirds(z_pow_third * z_pow_third);
+
+ // Implement the top line of Eq. 10.4.105.
+ const T fz(z_pow_two_thirds * ((((( + (T(162375596875.0) / 334430208UL)
+ * one_over_z_squared - ( T(108056875.0) / 6967296UL))
+ * one_over_z_squared + ( T(77125UL) / 82944UL))
+ * one_over_z_squared - ( T(5U) / 36U))
+ * one_over_z_squared + ( T(5U) / 48U))
+ * one_over_z_squared + (1)));
+
+ return fz;
+ }
+
+ namespace airy_ai_zero_detail
+ {
+ template<class T>
+ T initial_guess(const int m)
+ {
+ T guess;
+
+ switch(m)
+ {
+ case 0: { guess = T(0); break; }
+ case 1: { guess = T(-2.33810741045976703849); break; }
+ case 2: { guess = T(-4.08794944413097061664); break; }
+ case 3: { guess = T(-5.52055982809555105913); break; }
+ case 4: { guess = T(-6.78670809007175899878); break; }
+ case 5: { guess = T(-7.94413358712085312314); break; }
+ case 6: { guess = T(-9.02265085334098038016); break; }
+ case 7: { guess = T(-10.0401743415580859306); break; }
+ case 8: { guess = T(-11.0085243037332628932); break; }
+ case 9: { guess = T(-11.9360155632362625170); break; }
+ case 10:{ guess = T(-12.8287767528657572004); break; }
+ default:
+ {
+ const T t(((boost::math::constants::pi<T>() * 3) * ((T(m) * 4) - 1)) / 8);
+ guess = -boost::math::detail::airy_zero::equation_as_10_4_105(t);
+ break;
+ }
+ }
+
+ return guess;
+ }
+
+ template<class T, class Policy>
+ class function_object_ai_and_ai_prime
+ {
+ public:
+ function_object_ai_and_ai_prime(const Policy pol) : my_pol(pol) { }
+
+ boost::math::tuple<T, T> operator()(const T& x) const
+ {
+ // Return a tuple containing both Ai(x) and Ai'(x).
+ return boost::math::make_tuple(
+ boost::math::detail::airy_ai_imp (x, my_pol),
+ boost::math::detail::airy_ai_prime_imp(x, my_pol));
+ }
+
+ private:
+ const Policy& my_pol;
+ const function_object_ai_and_ai_prime& operator=(const function_object_ai_and_ai_prime&);
+ };
+ } // namespace airy_ai_zero_detail
+
+ namespace airy_bi_zero_detail
+ {
+ template<class T>
+ T initial_guess(const int m)
+ {
+ T guess;
+
+ switch(m)
+ {
+ case 0: { guess = T(0); break; }
+ case 1: { guess = T(-1.17371322270912792492); break; }
+ case 2: { guess = T(-3.27109330283635271568); break; }
+ case 3: { guess = T(-4.83073784166201593267); break; }
+ case 4: { guess = T(-6.16985212831025125983); break; }
+ case 5: { guess = T(-7.37676207936776371360); break; }
+ case 6: { guess = T(-8.49194884650938801345); break; }
+ case 7: { guess = T(-9.53819437934623888663); break; }
+ case 8: { guess = T(-10.5299135067053579244); break; }
+ case 9: { guess = T(-11.4769535512787794379); break; }
+ case 10: { guess = T(-12.3864171385827387456); break; }
+ default:
+ {
+ const T t(((boost::math::constants::pi<T>() * 3) * ((T(m) * 4) - 3)) / 8);
+ guess = -boost::math::detail::airy_zero::equation_as_10_4_105(t);
+ break;
+ }
+ }
+
+ return guess;
+ }
+
+ template<class T, class Policy>
+ class function_object_bi_and_bi_prime
+ {
+ public:
+ function_object_bi_and_bi_prime(const Policy pol) : my_pol(pol) { }
+
+ boost::math::tuple<T, T> operator()(const T& x) const
+ {
+ // Return a tuple containing both Bi(x) and Bi'(x).
+ return boost::math::make_tuple(
+ boost::math::detail::airy_bi_imp (x, my_pol),
+ boost::math::detail::airy_bi_prime_imp(x, my_pol));
+ }
+
+ private:
+ const Policy& my_pol;
+ const function_object_bi_and_bi_prime& operator=(const function_object_bi_and_bi_prime&);
+ };
+ } // namespace airy_bi_zero_detail
+ } // namespace airy_zero
+ } // namespace detail
+ } // namespace math
+ } // namespaces boost
+
+#endif // _AIRY_AI_BI_ZERO_2013_01_20_HPP_
diff --git a/boost/math/special_functions/detail/bernoulli_details.hpp b/boost/math/special_functions/detail/bernoulli_details.hpp
new file mode 100644
index 0000000000..f2d3c655c8
--- /dev/null
+++ b/boost/math/special_functions/detail/bernoulli_details.hpp
@@ -0,0 +1,653 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright 2013 John Maddock
+// Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MATH_BERNOULLI_DETAIL_HPP
+#define BOOST_MATH_BERNOULLI_DETAIL_HPP
+
+#include <boost/config.hpp>
+#include <boost/detail/lightweight_mutex.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/math/tools/toms748_solve.hpp>
+
+#ifdef BOOST_HAS_THREADS
+
+#ifndef BOOST_NO_CXX11_HDR_ATOMIC
+# include <atomic>
+# define BOOST_MATH_ATOMIC_NS std
+#if ATOMIC_INT_LOCK_FREE == 2
+typedef std::atomic<int> atomic_counter_type;
+typedef int atomic_integer_type;
+#elif ATOMIC_SHORT_LOCK_FREE == 2
+typedef std::atomic<short> atomic_counter_type;
+typedef short atomic_integer_type;
+#elif ATOMIC_LONG_LOCK_FREE == 2
+typedef std::atomic<long> atomic_counter_type;
+typedef long atomic_integer_type;
+#elif ATOMIC_LLONG_LOCK_FREE == 2
+typedef std::atomic<long long> atomic_counter_type;
+typedef long long atomic_integer_type;
+#else
+# define BOOST_MATH_NO_ATOMIC_INT
+#endif
+
+#else // BOOST_NO_CXX11_HDR_ATOMIC
+//
+// We need Boost.Atomic, but on any platform that supports auto-linking we do
+// not need to link against a separate library:
+//
+#define BOOST_ATOMIC_NO_LIB
+#include <boost/atomic.hpp>
+# define BOOST_MATH_ATOMIC_NS boost
+
+namespace boost{ namespace math{ namespace detail{
+
+//
+// We need a type to use as an atomic counter:
+//
+#if BOOST_ATOMIC_INT_LOCK_FREE == 2
+typedef boost::atomic<int> atomic_counter_type;
+typedef int atomic_integer_type;
+#elif BOOST_ATOMIC_SHORT_LOCK_FREE == 2
+typedef boost::atomic<short> atomic_counter_type;
+typedef short atomic_integer_type;
+#elif BOOST_ATOMIC_LONG_LOCK_FREE == 2
+typedef boost::atomic<long> atomic_counter_type;
+typedef long atomic_integer_type;
+#elif BOOST_ATOMIC_LLONG_LOCK_FREE == 2
+typedef boost::atomic<long long> atomic_counter_type;
+typedef long long atomic_integer_type;
+#else
+# define BOOST_MATH_NO_ATOMIC_INT
+#endif
+
+}}} // namespaces
+
+#endif // BOOST_NO_CXX11_HDR_ATOMIC
+
+#endif // BOOST_HAS_THREADS
+
+namespace boost{ namespace math{ namespace detail{
+//
+// Asymptotic expansion for B2n due to
+// Luschny LogB3 formula (http://www.luschny.de/math/primes/bernincl.html)
+//
+template <class T, class Policy>
+T b2n_asymptotic(int n)
+{
+ BOOST_MATH_STD_USING
+ const T nx = static_cast<T>(n);
+ const T nx2(nx * nx);
+
+ const T approximate_log_of_bernoulli_bn =
+ ((boost::math::constants::half<T>() + nx) * log(nx))
+ + ((boost::math::constants::half<T>() - nx) * log(boost::math::constants::pi<T>()))
+ + (((T(3) / 2) - nx) * boost::math::constants::ln_two<T>())
+ + ((nx * (T(2) - (nx2 * 7) * (1 + ((nx2 * 30) * ((nx2 * 12) - 1))))) / (((nx2 * nx2) * nx2) * 2520));
+ return ((n / 2) & 1 ? 1 : -1) * (approximate_log_of_bernoulli_bn > tools::log_max_value<T>()
+ ? policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, nx, Policy())
+ : static_cast<T>(exp(approximate_log_of_bernoulli_bn)));
+}
+
+template <class T, class Policy>
+T t2n_asymptotic(int n)
+{
+ BOOST_MATH_STD_USING
+ // Just get B2n and convert to a Tangent number:
+ T t2n = fabs(b2n_asymptotic<T, Policy>(2 * n)) / (2 * n);
+ T p2 = ldexp(T(1), n);
+ if(tools::max_value<T>() / p2 < t2n)
+ return policies::raise_overflow_error<T>("boost::math::tangent_t2n<%1%>(std::size_t)", 0, T(n), Policy());
+ t2n *= p2;
+ p2 -= 1;
+ if(tools::max_value<T>() / p2 < t2n)
+ return policies::raise_overflow_error<T>("boost::math::tangent_t2n<%1%>(std::size_t)", 0, Policy());
+ t2n *= p2;
+ return t2n;
+}
+//
+// We need to know the approximate value of /n/ which will
+// cause bernoulli_b2n<T>(n) to return infinity - this allows
+// us to elude a great deal of runtime checking for values below
+// n, and only perform the full overflow checks when we know that we're
+// getting close to the point where our calculations will overflow.
+// We use Luschny's LogB3 formula (http://www.luschny.de/math/primes/bernincl.html)
+// to find the limit, and since we're dealing with the log of the Bernoulli numbers
+// we need only perform the calculation at double precision and not with T
+// (which may be a multiprecision type). The limit returned is within 1 of the true
+// limit for all the types tested. Note that although the code below is basically
+// the same as b2n_asymptotic above, it has been recast as a continuous real-valued
+// function as this makes the root finding go smoother/faster. It also omits the
+// sign of the Bernoulli number.
+//
+struct max_bernoulli_root_functor
+{
+ max_bernoulli_root_functor(long long t) : target(static_cast<double>(t)) {}
+ double operator()(double n)
+ {
+ BOOST_MATH_STD_USING
+
+ // Luschny LogB3(n) formula.
+
+ const double nx2(n * n);
+
+ const double approximate_log_of_bernoulli_bn
+ = ((boost::math::constants::half<double>() + n) * log(n))
+ + ((boost::math::constants::half<double>() - n) * log(boost::math::constants::pi<double>()))
+ + (((double(3) / 2) - n) * boost::math::constants::ln_two<double>())
+ + ((n * (2 - (nx2 * 7) * (1 + ((nx2 * 30) * ((nx2 * 12) - 1))))) / (((nx2 * nx2) * nx2) * 2520));
+
+ return approximate_log_of_bernoulli_bn - target;
+ }
+private:
+ double target;
+};
+
+template <class T, class Policy>
+inline std::size_t find_bernoulli_overflow_limit(const mpl::false_&)
+{
+ long long t = lltrunc(boost::math::tools::log_max_value<T>());
+ max_bernoulli_root_functor fun(t);
+ boost::math::tools::equal_floor tol;
+ boost::uintmax_t max_iter = boost::math::policies::get_max_root_iterations<Policy>();
+ return static_cast<std::size_t>(boost::math::tools::toms748_solve(fun, sqrt(double(t)), double(t), tol, max_iter).first) / 2;
+}
+
+template <class T, class Policy>
+inline std::size_t find_bernoulli_overflow_limit(const mpl::true_&)
+{
+ return max_bernoulli_index<bernoulli_imp_variant<T>::value>::value;
+}
+
+template <class T, class Policy>
+std::size_t b2n_overflow_limit()
+{
+ // This routine is called at program startup if it's called at all:
+ // that guarantees safe initialization of the static variable.
+ typedef mpl::bool_<(bernoulli_imp_variant<T>::value >= 1) && (bernoulli_imp_variant<T>::value <= 3)> tag_type;
+ static const std::size_t lim = find_bernoulli_overflow_limit<T, Policy>(tag_type());
+ return lim;
+}
+
+//
+// The tangent numbers grow larger much more rapidly than the Bernoulli numbers do....
+// so to compute the Bernoulli numbers from the tangent numbers, we need to avoid spurious
+// overflow in the calculation, we can do this by scaling all the tangent number by some scale factor:
+//
+template <class T>
+inline typename enable_if_c<std::numeric_limits<T>::is_specialized && (std::numeric_limits<T>::radix == 2), T>::type tangent_scale_factor()
+{
+ BOOST_MATH_STD_USING
+ return ldexp(T(1), std::numeric_limits<T>::min_exponent + 5);
+}
+template <class T>
+inline typename disable_if_c<std::numeric_limits<T>::is_specialized && (std::numeric_limits<T>::radix == 2), T>::type tangent_scale_factor()
+{
+ return tools::min_value<T>() * 16;
+}
+//
+// Initializer: ensure all our constants are initialized prior to the first call of main:
+//
+template <class T, class Policy>
+struct bernoulli_initializer
+{
+ struct init
+ {
+ init()
+ {
+ //
+ // We call twice, once to initialize our static table, and once to
+ // initialize our dymanic table:
+ //
+ boost::math::bernoulli_b2n<T>(2, Policy());
+ try{
+ boost::math::bernoulli_b2n<T>(max_bernoulli_b2n<T>::value + 1, Policy());
+ } catch(const std::overflow_error&){}
+ boost::math::tangent_t2n<T>(2, Policy());
+ }
+ void force_instantiate()const{}
+ };
+ static const init initializer;
+ static void force_instantiate()
+ {
+ initializer.force_instantiate();
+ }
+};
+
+template <class T, class Policy>
+const typename bernoulli_initializer<T, Policy>::init bernoulli_initializer<T, Policy>::initializer;
+
+//
+// We need something to act as a cache for our calculated Bernoulli numbers. In order to
+// ensure both fast access and thread safety, we need a stable table which may be extended
+// in size, but which never reallocates: that way values already calculated may be accessed
+// concurrently with another thread extending the table with new values.
+//
+// Very very simple vector class that will never allocate more than once, we could use
+// boost::container::static_vector here, but that allocates on the stack, which may well
+// cause issues for the amount of memory we want in the extreme case...
+//
+template <class T>
+struct fixed_vector : private std::allocator<T>
+{
+ typedef unsigned size_type;
+ typedef T* iterator;
+ typedef const T* const_iterator;
+ fixed_vector() : m_used(0)
+ {
+ std::size_t overflow_limit = 5 + b2n_overflow_limit<T, policies::policy<> >();
+ m_capacity = static_cast<unsigned>((std::min)(overflow_limit, static_cast<std::size_t>(100000u)));
+ m_data = this->allocate(m_capacity);
+ }
+ ~fixed_vector()
+ {
+ for(unsigned i = 0; i < m_used; ++i)
+ this->destroy(&m_data[i]);
+ this->deallocate(m_data, m_capacity);
+ }
+ T& operator[](unsigned n) { BOOST_ASSERT(n < m_used); return m_data[n]; }
+ const T& operator[](unsigned n)const { BOOST_ASSERT(n < m_used); return m_data[n]; }
+ unsigned size()const { return m_used; }
+ unsigned size() { return m_used; }
+ void resize(unsigned n, const T& val)
+ {
+ if(n > m_capacity)
+ throw std::runtime_error("Exhausted storage for Bernoulli numbers.");
+ for(unsigned i = m_used; i < n; ++i)
+ new (m_data + i) T(val);
+ m_used = n;
+ }
+ void resize(unsigned n) { resize(n, T()); }
+ T* begin() { return m_data; }
+ T* end() { return m_data + m_used; }
+ T* begin()const { return m_data; }
+ T* end()const { return m_data + m_used; }
+ unsigned capacity()const { return m_capacity; }
+private:
+ T* m_data;
+ unsigned m_used, m_capacity;
+};
+
+template <class T, class Policy>
+class bernoulli_numbers_cache
+{
+public:
+ bernoulli_numbers_cache() : m_overflow_limit((std::numeric_limits<std::size_t>::max)())
+#if defined(BOOST_HAS_THREADS) && !defined(BOOST_MATH_NO_ATOMIC_INT)
+ , m_counter(0)
+#endif
+ {}
+
+ typedef fixed_vector<T> container_type;
+
+ void tangent(std::size_t m)
+ {
+ static const std::size_t min_overflow_index = b2n_overflow_limit<T, Policy>() - 1;
+ tn.resize(static_cast<typename container_type::size_type>(m), T(0U));
+
+ BOOST_MATH_INSTRUMENT_VARIABLE(min_overflow_index);
+
+ std::size_t prev_size = m_intermediates.size();
+ m_intermediates.resize(m, T(0U));
+
+ if(prev_size == 0)
+ {
+ m_intermediates[1] = tangent_scale_factor<T>() /*T(1U)*/;
+ tn[0U] = T(0U);
+ tn[1U] = tangent_scale_factor<T>()/* T(1U)*/;
+ BOOST_MATH_INSTRUMENT_VARIABLE(tn[0]);
+ BOOST_MATH_INSTRUMENT_VARIABLE(tn[1]);
+ }
+
+ for(std::size_t i = std::max<size_t>(2, prev_size); i < m; i++)
+ {
+ bool overflow_check = false;
+ if(i >= min_overflow_index && (boost::math::tools::max_value<T>() / (i-1) < m_intermediates[1]) )
+ {
+ std::fill(tn.begin() + i, tn.end(), boost::math::tools::max_value<T>());
+ break;
+ }
+ m_intermediates[1] = m_intermediates[1] * (i-1);
+ for(std::size_t j = 2; j <= i; j++)
+ {
+ overflow_check =
+ (i >= min_overflow_index) && (
+ (boost::math::tools::max_value<T>() / (i - j) < m_intermediates[j])
+ || (boost::math::tools::max_value<T>() / (i - j + 2) < m_intermediates[j-1])
+ || (boost::math::tools::max_value<T>() - m_intermediates[j] * (i - j) < m_intermediates[j-1] * (i - j + 2))
+ || ((boost::math::isinf)(m_intermediates[j]))
+ );
+
+ if(overflow_check)
+ {
+ std::fill(tn.begin() + i, tn.end(), boost::math::tools::max_value<T>());
+ break;
+ }
+ m_intermediates[j] = m_intermediates[j] * (i - j) + m_intermediates[j-1] * (i - j + 2);
+ }
+ if(overflow_check)
+ break; // already filled the tn...
+ tn[static_cast<typename container_type::size_type>(i)] = m_intermediates[i];
+ BOOST_MATH_INSTRUMENT_VARIABLE(i);
+ BOOST_MATH_INSTRUMENT_VARIABLE(tn[static_cast<typename container_type::size_type>(i)]);
+ }
+ }
+
+ void tangent_numbers_series(const std::size_t m)
+ {
+ BOOST_MATH_STD_USING
+ static const std::size_t min_overflow_index = b2n_overflow_limit<T, Policy>() - 1;
+
+ typename container_type::size_type old_size = bn.size();
+
+ tangent(m);
+ bn.resize(static_cast<typename container_type::size_type>(m));
+
+ if(!old_size)
+ {
+ bn[0] = 1;
+ old_size = 1;
+ }
+
+ T power_two(ldexp(T(1), static_cast<int>(2 * old_size)));
+
+ for(std::size_t i = old_size; i < m; i++)
+ {
+ T b(static_cast<T>(i * 2));
+ //
+ // Not only do we need to take care to avoid spurious over/under flow in
+ // the calculation, but we also need to avoid overflow altogether in case
+ // we're calculating with a type where "bad things" happen in that case:
+ //
+ b = b / (power_two * tangent_scale_factor<T>());
+ b /= (power_two - 1);
+ bool overflow_check = (i >= min_overflow_index) && (tools::max_value<T>() / tn[static_cast<typename container_type::size_type>(i)] < b);
+ if(overflow_check)
+ {
+ m_overflow_limit = i;
+ while(i < m)
+ {
+ b = std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity() : tools::max_value<T>();
+ bn[static_cast<typename container_type::size_type>(i)] = ((i % 2U) ? b : T(-b));
+ ++i;
+ }
+ break;
+ }
+ else
+ {
+ b *= tn[static_cast<typename container_type::size_type>(i)];
+ }
+
+ power_two = ldexp(power_two, 2);
+
+ const bool b_neg = i % 2 == 0;
+
+ bn[static_cast<typename container_type::size_type>(i)] = ((!b_neg) ? b : T(-b));
+ }
+ }
+
+ template <class OutputIterator>
+ OutputIterator copy_bernoulli_numbers(OutputIterator out, std::size_t start, std::size_t n, const Policy& pol)
+ {
+ //
+ // There are basically 3 thread safety options:
+ //
+ // 1) There are no threads (BOOST_HAS_THREADS is not defined).
+ // 2) There are threads, but we do not have a true atomic integer type,
+ // in this case we just use a mutex to guard against race conditions.
+ // 3) There are threads, and we have an atomic integer: in this case we can
+ // use the double-checked locking pattern to avoid thread synchronisation
+ // when accessing values already in the cache.
+ //
+ // First off handle the common case for overflow and/or asymptotic expansion:
+ //
+ if(start + n > bn.capacity())
+ {
+ if(start < bn.capacity())
+ {
+ out = copy_bernoulli_numbers(out, start, bn.capacity() - start, pol);
+ n -= bn.capacity() - start;
+ start = static_cast<std::size_t>(bn.capacity());
+ }
+ if(start < b2n_overflow_limit<T, Policy>() + 2u)
+ {
+ for(; n; ++start, --n)
+ {
+ *out = b2n_asymptotic<T, Policy>(static_cast<typename container_type::size_type>(start * 2U));
+ ++out;
+ }
+ }
+ for(; n; ++start, --n)
+ {
+ *out = policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(start), pol);
+ ++out;
+ }
+ return out;
+ }
+ #if !defined(BOOST_HAS_THREADS)
+ //
+ // Single threaded code, very simple:
+ //
+ if(start + n >= bn.size())
+ {
+ std::size_t new_size = (std::min)((std::max)((std::max)(start + n, std::size_t(bn.size() + 20)), std::size_t(50)), std::size_t(bn.capacity()));
+ tangent_numbers_series(new_size);
+ }
+
+ for(std::size_t i = (std::max)(max_bernoulli_b2n<T>::value + 1, start); i < start + n; ++i)
+ {
+ *out = (i >= m_overflow_limit) ? policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol) : bn[i];
+ ++out;
+ }
+ #elif defined(BOOST_MATH_NO_ATOMIC_INT)
+ //
+ // We need to grab a mutex every time we get here, for both readers and writers:
+ //
+ boost::detail::lightweight_mutex::scoped_lock l(m_mutex);
+ if(start + n >= bn.size())
+ {
+ std::size_t new_size = (std::min)((std::max)((std::max)(start + n, std::size_t(bn.size() + 20)), std::size_t(50)), std::size_t(bn.capacity()));
+ tangent_numbers_series(new_size);
+ }
+
+ for(std::size_t i = (std::max)(max_bernoulli_b2n<T>::value + 1, start); i < start + n; ++i)
+ {
+ *out = (i >= m_overflow_limit) ? policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol) : bn[i];
+ ++out;
+ }
+
+ #else
+ //
+ // Double-checked locking pattern, lets us access cached already cached values
+ // without locking:
+ //
+ // Get the counter and see if we need to calculate more constants:
+ //
+ if(static_cast<std::size_t>(m_counter.load(BOOST_MATH_ATOMIC_NS::memory_order_consume)) < start + n)
+ {
+ boost::detail::lightweight_mutex::scoped_lock l(m_mutex);
+
+ if(static_cast<std::size_t>(m_counter.load(BOOST_MATH_ATOMIC_NS::memory_order_consume)) < start + n)
+ {
+ if(start + n >= bn.size())
+ {
+ std::size_t new_size = (std::min)((std::max)((std::max)(start + n, std::size_t(bn.size() + 20)), std::size_t(50)), std::size_t(bn.capacity()));
+ tangent_numbers_series(new_size);
+ }
+ m_counter.store(static_cast<atomic_integer_type>(bn.size()), BOOST_MATH_ATOMIC_NS::memory_order_release);
+ }
+ }
+
+ for(std::size_t i = (std::max)(static_cast<std::size_t>(max_bernoulli_b2n<T>::value + 1), start); i < start + n; ++i)
+ {
+ *out = (i >= m_overflow_limit) ? policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol) : bn[static_cast<typename container_type::size_type>(i)];
+ ++out;
+ }
+
+ #endif
+ return out;
+ }
+
+ template <class OutputIterator>
+ OutputIterator copy_tangent_numbers(OutputIterator out, std::size_t start, std::size_t n, const Policy& pol)
+ {
+ //
+ // There are basically 3 thread safety options:
+ //
+ // 1) There are no threads (BOOST_HAS_THREADS is not defined).
+ // 2) There are threads, but we do not have a true atomic integer type,
+ // in this case we just use a mutex to guard against race conditions.
+ // 3) There are threads, and we have an atomic integer: in this case we can
+ // use the double-checked locking pattern to avoid thread synchronisation
+ // when accessing values already in the cache.
+ //
+ //
+ // First off handle the common case for overflow and/or asymptotic expansion:
+ //
+ if(start + n > bn.capacity())
+ {
+ if(start < bn.capacity())
+ {
+ out = copy_tangent_numbers(out, start, bn.capacity() - start, pol);
+ n -= bn.capacity() - start;
+ start = static_cast<std::size_t>(bn.capacity());
+ }
+ if(start < b2n_overflow_limit<T, Policy>() + 2u)
+ {
+ for(; n; ++start, --n)
+ {
+ *out = t2n_asymptotic<T, Policy>(static_cast<typename container_type::size_type>(start));
+ ++out;
+ }
+ }
+ for(; n; ++start, --n)
+ {
+ *out = policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(start), pol);
+ ++out;
+ }
+ return out;
+ }
+ #if !defined(BOOST_HAS_THREADS)
+ //
+ // Single threaded code, very simple:
+ //
+ if(start + n >= bn.size())
+ {
+ std::size_t new_size = (std::min)((std::max)((std::max)(start + n, std::size_t(bn.size() + 20)), std::size_t(50)), std::size_t(bn.capacity()));
+ tangent_numbers_series(new_size);
+ }
+
+ for(std::size_t i = start; i < start + n; ++i)
+ {
+ if(i >= m_overflow_limit)
+ *out = policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol);
+ else
+ {
+ if(tools::max_value<T>() * tangent_scale_factor<T>() < tn[static_cast<typename container_type::size_type>(i)])
+ *out = policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol);
+ else
+ *out = tn[static_cast<typename container_type::size_type>(i)] / tangent_scale_factor<T>();
+ }
+ ++out;
+ }
+ #elif defined(BOOST_MATH_NO_ATOMIC_INT)
+ //
+ // We need to grab a mutex every time we get here, for both readers and writers:
+ //
+ boost::detail::lightweight_mutex::scoped_lock l(m_mutex);
+ if(start + n >= bn.size())
+ {
+ std::size_t new_size = (std::min)((std::max)((std::max)(start + n, std::size_t(bn.size() + 20)), std::size_t(50)), std::size_t(bn.capacity()));
+ tangent_numbers_series(new_size);
+ }
+
+ for(std::size_t i = start; i < start + n; ++i)
+ {
+ if(i >= m_overflow_limit)
+ *out = policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol);
+ else
+ {
+ if(tools::max_value<T>() * tangent_scale_factor<T>() < tn[static_cast<typename container_type::size_type>(i)])
+ *out = policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol);
+ else
+ *out = tn[static_cast<typename container_type::size_type>(i)] / tangent_scale_factor<T>();
+ }
+ ++out;
+ }
+
+ #else
+ //
+ // Double-checked locking pattern, lets us access cached already cached values
+ // without locking:
+ //
+ // Get the counter and see if we need to calculate more constants:
+ //
+ if(static_cast<std::size_t>(m_counter.load(BOOST_MATH_ATOMIC_NS::memory_order_consume)) < start + n)
+ {
+ boost::detail::lightweight_mutex::scoped_lock l(m_mutex);
+
+ if(static_cast<std::size_t>(m_counter.load(BOOST_MATH_ATOMIC_NS::memory_order_consume)) < start + n)
+ {
+ if(start + n >= bn.size())
+ {
+ std::size_t new_size = (std::min)((std::max)((std::max)(start + n, std::size_t(bn.size() + 20)), std::size_t(50)), std::size_t(bn.capacity()));
+ tangent_numbers_series(new_size);
+ }
+ m_counter.store(static_cast<atomic_integer_type>(bn.size()), BOOST_MATH_ATOMIC_NS::memory_order_release);
+ }
+ }
+
+ for(std::size_t i = start; i < start + n; ++i)
+ {
+ if(i >= m_overflow_limit)
+ *out = policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol);
+ else
+ {
+ if(tools::max_value<T>() * tangent_scale_factor<T>() < tn[static_cast<typename container_type::size_type>(i)])
+ *out = policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol);
+ else
+ *out = tn[static_cast<typename container_type::size_type>(i)] / tangent_scale_factor<T>();
+ }
+ ++out;
+ }
+
+ #endif
+ return out;
+ }
+
+private:
+ //
+ // The caches for Bernoulli and tangent numbers, once allocated,
+ // these must NEVER EVER reallocate as it breaks our thread
+ // safety guarentees:
+ //
+ fixed_vector<T> bn, tn;
+ std::vector<T> m_intermediates;
+ // The value at which we know overflow has already occured for the Bn:
+ std::size_t m_overflow_limit;
+#if !defined(BOOST_HAS_THREADS)
+#elif defined(BOOST_MATH_NO_ATOMIC_INT)
+ boost::detail::lightweight_mutex m_mutex;
+#else
+ boost::detail::lightweight_mutex m_mutex;
+ atomic_counter_type m_counter;
+#endif
+};
+
+template <class T, class Policy>
+inline bernoulli_numbers_cache<T, Policy>& get_bernoulli_numbers_cache()
+{
+ //
+ // Force this function to be called at program startup so all the static variables
+ // get initailzed then (thread safety).
+ //
+ bernoulli_initializer<T, Policy>::force_instantiate();
+ static bernoulli_numbers_cache<T, Policy> data;
+ return data;
+}
+
+}}}
+
+#endif // BOOST_MATH_BERNOULLI_DETAIL_HPP
diff --git a/boost/math/special_functions/detail/bessel_derivatives_linear.hpp b/boost/math/special_functions/detail/bessel_derivatives_linear.hpp
new file mode 100644
index 0000000000..2ee86a03ee
--- /dev/null
+++ b/boost/math/special_functions/detail/bessel_derivatives_linear.hpp
@@ -0,0 +1,75 @@
+// Copyright (c) 2013 Anton Bikineev
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+//
+// This is a partial header, do not include on it's own!!!
+//
+// Linear combination for bessel derivatives are defined here
+#ifndef BOOST_MATH_SF_DETAIL_BESSEL_DERIVATIVES_LINEAR_HPP
+#define BOOST_MATH_SF_DETAIL_BESSEL_DERIVATIVES_LINEAR_HPP
+
+#ifdef _MSC_VER
+#pragma once
+#endif
+
+namespace boost{ namespace math{ namespace detail{
+
+template <class T, class Tag, class Policy>
+inline T bessel_j_derivative_linear(T v, T x, Tag tag, Policy pol)
+{
+ return (boost::math::detail::cyl_bessel_j_imp<T>(v-1, x, tag, pol) - boost::math::detail::cyl_bessel_j_imp<T>(v+1, x, tag, pol)) / 2;
+}
+
+template <class T, class Policy>
+inline T bessel_j_derivative_linear(T v, T x, const bessel_int_tag& tag, Policy pol)
+{
+ return (boost::math::detail::cyl_bessel_j_imp<T>(itrunc(v-1), x, tag, pol) - boost::math::detail::cyl_bessel_j_imp<T>(itrunc(v+1), x, tag, pol)) / 2;
+}
+
+template <class T, class Policy>
+inline T sph_bessel_j_derivative_linear(unsigned v, T x, Policy pol)
+{
+ return (v / x) * boost::math::detail::sph_bessel_j_imp<T>(v, x, pol) - boost::math::detail::sph_bessel_j_imp<T>(v+1, x, pol);
+}
+
+template <class T, class Policy>
+inline T bessel_i_derivative_linear(T v, T x, Policy pol)
+{
+ return (boost::math::detail::cyl_bessel_i_imp<T>(v-1, x, pol) + boost::math::detail::cyl_bessel_i_imp<T>(v+1, x, pol)) / 2;
+}
+
+template <class T, class Tag, class Policy>
+inline T bessel_k_derivative_linear(T v, T x, Tag tag, Policy pol)
+{
+ return (boost::math::detail::cyl_bessel_k_imp<T>(v-1, x, tag, pol) + boost::math::detail::cyl_bessel_k_imp<T>(v+1, x, tag, pol)) / -2;
+}
+
+template <class T, class Policy>
+inline T bessel_k_derivative_linear(T v, T x, const bessel_int_tag& tag, Policy pol)
+{
+ return (boost::math::detail::cyl_bessel_k_imp<T>(itrunc(v-1), x, tag, pol) + boost::math::detail::cyl_bessel_k_imp<T>(itrunc(v+1), x, tag, pol)) / -2;
+}
+
+template <class T, class Tag, class Policy>
+inline T bessel_y_derivative_linear(T v, T x, Tag tag, Policy pol)
+{
+ return (boost::math::detail::cyl_neumann_imp<T>(v-1, x, tag, pol) - boost::math::detail::cyl_neumann_imp<T>(v+1, x, tag, pol)) / 2;
+}
+
+template <class T, class Policy>
+inline T bessel_y_derivative_linear(T v, T x, const bessel_int_tag& tag, Policy pol)
+{
+ return (boost::math::detail::cyl_neumann_imp<T>(itrunc(v-1), x, tag, pol) - boost::math::detail::cyl_neumann_imp<T>(itrunc(v+1), x, tag, pol)) / 2;
+}
+
+template <class T, class Policy>
+inline T sph_neumann_derivative_linear(unsigned v, T x, Policy pol)
+{
+ return (v / x) * boost::math::detail::sph_neumann_imp<T>(v, x, pol) - boost::math::detail::sph_neumann_imp<T>(v+1, x, pol);
+}
+
+}}} // namespaces
+
+#endif // BOOST_MATH_SF_DETAIL_BESSEL_DERIVATIVES_LINEAR_HPP
diff --git a/boost/math/special_functions/detail/bessel_i0.hpp b/boost/math/special_functions/detail/bessel_i0.hpp
index 7dc65d1a1b..676eb71511 100644
--- a/boost/math/special_functions/detail/bessel_i0.hpp
+++ b/boost/math/special_functions/detail/bessel_i0.hpp
@@ -102,10 +102,7 @@ T bessel_i0(T x)
BOOST_MATH_STD_USING
using namespace boost::math::tools;
- if (x < 0)
- {
- x = -x; // even function
- }
+ BOOST_ASSERT(x >= 0); // negative x is handled before we get here
if (x == 0)
{
return static_cast<T>(1);
diff --git a/boost/math/special_functions/detail/bessel_i1.hpp b/boost/math/special_functions/detail/bessel_i1.hpp
index 47f1b79883..b85bc67546 100644
--- a/boost/math/special_functions/detail/bessel_i1.hpp
+++ b/boost/math/special_functions/detail/bessel_i1.hpp
@@ -103,6 +103,7 @@ T bessel_i1(T x)
BOOST_MATH_STD_USING
using namespace boost::math::tools;
+ BOOST_ASSERT(x >= 0); // negative x is handled before we get here
w = abs(x);
if (x == 0)
{
@@ -123,10 +124,6 @@ T bessel_i1(T x)
value = factor * r;
}
- if (x < 0)
- {
- value *= -value; // odd function
- }
return value;
}
diff --git a/boost/math/special_functions/detail/bessel_ik.hpp b/boost/math/special_functions/detail/bessel_ik.hpp
index a589673ffb..10118d9715 100644
--- a/boost/math/special_functions/detail/bessel_ik.hpp
+++ b/boost/math/special_functions/detail/bessel_ik.hpp
@@ -234,6 +234,7 @@ int CF2_ik(T v, T x, T* Kv, T* Kv1, const Policy& pol)
BOOST_MATH_INSTRUMENT_VARIABLE(b);
BOOST_MATH_INSTRUMENT_VARIABLE(D);
BOOST_MATH_INSTRUMENT_VARIABLE(f);
+
for (k = 2; k < policies::get_max_series_iterations<Policy>(); k++) // starting from 2
{
// continued fraction f = z1 / z0
@@ -250,10 +251,27 @@ int CF2_ik(T v, T x, T* Kv, T* Kv1, const Policy& pol)
C *= -a / k;
Q += C * q;
S += Q * delta;
+ //
+ // Under some circumstances q can grow very small and C very
+ // large, leading to under/overflow. This is particularly an
+ // issue for types which have many digits precision but a narrow
+ // exponent range. A typical example being a "double double" type.
+ // To avoid this situation we can normalise q (and related prev/current)
+ // and C. All other variables remain unchanged in value. A typical
+ // test case occurs when x is close to 2, for example cyl_bessel_k(9.125, 2.125).
+ //
+ if(q < tools::epsilon<T>())
+ {
+ C *= q;
+ prev /= q;
+ current /= q;
+ q = 1;
+ }
// S converges slower than f
BOOST_MATH_INSTRUMENT_VARIABLE(Q * delta);
BOOST_MATH_INSTRUMENT_VARIABLE(abs(S) * tolerance);
+ BOOST_MATH_INSTRUMENT_VARIABLE(S);
if (abs(Q * delta) < abs(S) * tolerance)
{
break;
@@ -261,7 +279,10 @@ int CF2_ik(T v, T x, T* Kv, T* Kv1, const Policy& pol)
}
policies::check_series_iterations<T>("boost::math::bessel_ik<%1%>(%1%,%1%) in CF2_ik", k, pol);
- *Kv = sqrt(pi<T>() / (2 * x)) * exp(-x) / S;
+ if(x >= tools::log_max_value<T>())
+ *Kv = exp(0.5f * log(pi<T>() / (2 * x)) - x - log(S));
+ else
+ *Kv = sqrt(pi<T>() / (2 * x)) * exp(-x) / S;
*Kv1 = *Kv * (0.5f + v + x + (v * v - 0.25f) * f) / x;
BOOST_MATH_INSTRUMENT_VARIABLE(*Kv);
BOOST_MATH_INSTRUMENT_VARIABLE(*Kv1);
diff --git a/boost/math/special_functions/detail/bessel_j0.hpp b/boost/math/special_functions/detail/bessel_j0.hpp
index a07052d73e..ebcab17240 100644
--- a/boost/math/special_functions/detail/bessel_j0.hpp
+++ b/boost/math/special_functions/detail/bessel_j0.hpp
@@ -165,13 +165,23 @@ T bessel_j0(T x)
{
T y = 8 / x;
T y2 = y * y;
- T z = x - 0.25f * pi<T>();
BOOST_ASSERT(sizeof(PC) == sizeof(QC));
BOOST_ASSERT(sizeof(PS) == sizeof(QS));
rc = evaluate_rational(PC, QC, y2);
rs = evaluate_rational(PS, QS, y2);
- factor = sqrt(2 / (x * pi<T>()));
- value = factor * (rc * cos(z) - y * rs * sin(z));
+ factor = constants::one_div_root_pi<T>() / sqrt(x);
+ //
+ // What follows is really just:
+ //
+ // T z = x - pi/4;
+ // value = factor * (rc * cos(z) - y * rs * sin(z));
+ //
+ // But using the addition formulae for sin and cos, plus
+ // the special values for sin/cos of pi/4.
+ //
+ T sx = sin(x);
+ T cx = cos(x);
+ value = factor * (rc * (cx + sx) - y * rs * (sx - cx));
}
return value;
diff --git a/boost/math/special_functions/detail/bessel_j1.hpp b/boost/math/special_functions/detail/bessel_j1.hpp
index 09d862c240..91ecd2832d 100644
--- a/boost/math/special_functions/detail/bessel_j1.hpp
+++ b/boost/math/special_functions/detail/bessel_j1.hpp
@@ -166,13 +166,24 @@ T bessel_j1(T x)
{
T y = 8 / w;
T y2 = y * y;
- T z = w - 0.75f * pi<T>();
BOOST_ASSERT(sizeof(PC) == sizeof(QC));
BOOST_ASSERT(sizeof(PS) == sizeof(QS));
rc = evaluate_rational(PC, QC, y2);
rs = evaluate_rational(PS, QS, y2);
- factor = sqrt(2 / (w * pi<T>()));
- value = factor * (rc * cos(z) - y * rs * sin(z));
+ factor = 1 / (sqrt(w) * constants::root_pi<T>());
+ //
+ // What follows is really just:
+ //
+ // T z = w - 0.75f * pi<T>();
+ // value = factor * (rc * cos(z) - y * rs * sin(z));
+ //
+ // but using the sin/cos addition rules plus constants
+ // for the values of sin/cos of 3PI/4 which then cancel
+ // out with corresponding terms in "factor".
+ //
+ T sx = sin(x);
+ T cx = cos(x);
+ value = factor * (rc * (sx - cx) + y * rs * (sx + cx));
}
if (x < 0)
diff --git a/boost/math/special_functions/detail/bessel_jn.hpp b/boost/math/special_functions/detail/bessel_jn.hpp
index 2bf8d78b74..3f15f9cd87 100644
--- a/boost/math/special_functions/detail/bessel_jn.hpp
+++ b/boost/math/special_functions/detail/bessel_jn.hpp
@@ -42,6 +42,11 @@ T bessel_jn(int n, T x, const Policy& pol)
{
factor = 1;
}
+ if(x < 0)
+ {
+ factor *= (n & 0x1) ? -1 : 1; // J_{n}(-z) = (-1)^n J_n(z)
+ x = -x;
+ }
//
// Special cases:
//
@@ -59,8 +64,7 @@ T bessel_jn(int n, T x, const Policy& pol)
return static_cast<T>(0);
}
- typedef typename bessel_asymptotic_tag<T, Policy>::type tag_type;
- if(fabs(x) > asymptotic_bessel_j_limit<T>(n, tag_type()))
+ if(asymptotic_bessel_large_x_limit(T(n), x))
return factor * asymptotic_bessel_j_large_x_2<T>(n, x);
BOOST_ASSERT(n > 1);
@@ -69,6 +73,7 @@ T bessel_jn(int n, T x, const Policy& pol)
{
prev = bessel_j0(x);
current = bessel_j1(x);
+ policies::check_series_iterations<T>("boost::math::bessel_j_n<%1%>(%1%,%1%)", n, pol);
for (int k = 1; k < n; k++)
{
T fact = 2 * k / x;
@@ -86,7 +91,7 @@ T bessel_jn(int n, T x, const Policy& pol)
current = value;
}
}
- else if(x < 1)
+ else if((x < 1) || (n > x * x / 4) || (x < 5))
{
return factor * bessel_j_small_z_series(T(n), x, pol);
}
@@ -97,6 +102,8 @@ T bessel_jn(int n, T x, const Policy& pol)
boost::math::detail::CF1_jy(static_cast<T>(n), x, &fn, &s, pol);
prev = fn;
current = 1;
+ // Check recursion won't go on too far:
+ policies::check_series_iterations<T>("boost::math::bessel_j_n<%1%>(%1%,%1%)", n, pol);
for (int k = n; k > 0; k--)
{
T fact = 2 * k / x;
diff --git a/boost/math/special_functions/detail/bessel_jy.hpp b/boost/math/special_functions/detail/bessel_jy.hpp
index d60dda2d41..b67d989b68 100644
--- a/boost/math/special_functions/detail/bessel_jy.hpp
+++ b/boost/math/special_functions/detail/bessel_jy.hpp
@@ -28,440 +28,464 @@
namespace boost { namespace math {
-namespace detail {
-
-//
-// Simultaneous calculation of A&S 9.2.9 and 9.2.10
-// for use in A&S 9.2.5 and 9.2.6.
-// This series is quick to evaluate, but divergent unless
-// x is very large, in fact it's pretty hard to figure out
-// with any degree of precision when this series actually
-// *will* converge!! Consequently, we may just have to
-// try it and see...
-//
-template <class T, class Policy>
-bool hankel_PQ(T v, T x, T* p, T* q, const Policy& )
-{
- BOOST_MATH_STD_USING
- T tolerance = 2 * policies::get_epsilon<T, Policy>();
- *p = 1;
- *q = 0;
- T k = 1;
- T z8 = 8 * x;
- T sq = 1;
- T mu = 4 * v * v;
- T term = 1;
- bool ok = true;
- do
- {
- term *= (mu - sq * sq) / (k * z8);
- *q += term;
- k += 1;
- sq += 2;
- T mult = (sq * sq - mu) / (k * z8);
- ok = fabs(mult) < 0.5f;
- term *= mult;
- *p += term;
- k += 1;
- sq += 2;
- }
- while((fabs(term) > tolerance * *p) && ok);
- return ok;
-}
-
-// Calculate Y(v, x) and Y(v+1, x) by Temme's method, see
-// Temme, Journal of Computational Physics, vol 21, 343 (1976)
-template <typename T, typename Policy>
-int temme_jy(T v, T x, T* Y, T* Y1, const Policy& pol)
-{
- T g, h, p, q, f, coef, sum, sum1, tolerance;
- T a, d, e, sigma;
- unsigned long k;
-
- BOOST_MATH_STD_USING
- using namespace boost::math::tools;
- using namespace boost::math::constants;
-
- BOOST_ASSERT(fabs(v) <= 0.5f); // precondition for using this routine
-
- T gp = boost::math::tgamma1pm1(v, pol);
- T gm = boost::math::tgamma1pm1(-v, pol);
- T spv = boost::math::sin_pi(v, pol);
- T spv2 = boost::math::sin_pi(v/2, pol);
- T xp = pow(x/2, v);
-
- a = log(x / 2);
- sigma = -a * v;
- d = abs(sigma) < tools::epsilon<T>() ?
- T(1) : sinh(sigma) / sigma;
- e = abs(v) < tools::epsilon<T>() ? T(v*pi<T>()*pi<T>() / 2)
- : T(2 * spv2 * spv2 / v);
-
- T g1 = (v == 0) ? T(-euler<T>()) : T((gp - gm) / ((1 + gp) * (1 + gm) * 2 * v));
- T g2 = (2 + gp + gm) / ((1 + gp) * (1 + gm) * 2);
- T vspv = (fabs(v) < tools::epsilon<T>()) ? T(1/constants::pi<T>()) : T(v / spv);
- f = (g1 * cosh(sigma) - g2 * a * d) * 2 * vspv;
-
- p = vspv / (xp * (1 + gm));
- q = vspv * xp / (1 + gp);
-
- g = f + e * q;
- h = p;
- coef = 1;
- sum = coef * g;
- sum1 = coef * h;
-
- T v2 = v * v;
- T coef_mult = -x * x / 4;
-
- // series summation
- tolerance = policies::get_epsilon<T, Policy>();
- for (k = 1; k < policies::get_max_series_iterations<Policy>(); k++)
- {
- f = (k * f + p + q) / (k*k - v2);
- p /= k - v;
- q /= k + v;
- g = f + e * q;
- h = p - k * g;
- coef *= coef_mult / k;
- sum += coef * g;
- sum1 += coef * h;
- if (abs(coef * g) < abs(sum) * tolerance)
- {
- break;
- }
- }
- policies::check_series_iterations<T>("boost::math::bessel_jy<%1%>(%1%,%1%) in temme_jy", k, pol);
- *Y = -sum;
- *Y1 = -2 * sum1 / x;
-
- return 0;
-}
-
-// Evaluate continued fraction fv = J_(v+1) / J_v, see
-// Abramowitz and Stegun, Handbook of Mathematical Functions, 1972, 9.1.73
-template <typename T, typename Policy>
-int CF1_jy(T v, T x, T* fv, int* sign, const Policy& pol)
-{
- T C, D, f, a, b, delta, tiny, tolerance;
- unsigned long k;
- int s = 1;
-
- BOOST_MATH_STD_USING
-
- // |x| <= |v|, CF1_jy converges rapidly
- // |x| > |v|, CF1_jy needs O(|x|) iterations to converge
-
- // modified Lentz's method, see
- // Lentz, Applied Optics, vol 15, 668 (1976)
- tolerance = 2 * policies::get_epsilon<T, Policy>();;
- tiny = sqrt(tools::min_value<T>());
- C = f = tiny; // b0 = 0, replace with tiny
- D = 0;
- for (k = 1; k < policies::get_max_series_iterations<Policy>() * 100; k++)
- {
- a = -1;
- b = 2 * (v + k) / x;
- C = b + a / C;
- D = b + a * D;
- if (C == 0) { C = tiny; }
- if (D == 0) { D = tiny; }
- D = 1 / D;
- delta = C * D;
- f *= delta;
- if (D < 0) { s = -s; }
- if (abs(delta - 1) < tolerance)
- { break; }
- }
- policies::check_series_iterations<T>("boost::math::bessel_jy<%1%>(%1%,%1%) in CF1_jy", k / 100, pol);
- *fv = -f;
- *sign = s; // sign of denominator
-
- return 0;
-}
-//
-// This algorithm was originally written by Xiaogang Zhang
-// using std::complex to perform the complex arithmetic.
-// However, that turns out to 10x or more slower than using
-// all real-valued arithmetic, so it's been rewritten using
-// real values only.
-//
-template <typename T, typename Policy>
-int CF2_jy(T v, T x, T* p, T* q, const Policy& pol)
-{
- BOOST_MATH_STD_USING
-
- T Cr, Ci, Dr, Di, fr, fi, a, br, bi, delta_r, delta_i, temp;
- T tiny;
- unsigned long k;
-
- // |x| >= |v|, CF2_jy converges rapidly
- // |x| -> 0, CF2_jy fails to converge
- BOOST_ASSERT(fabs(x) > 1);
-
- // modified Lentz's method, complex numbers involved, see
- // Lentz, Applied Optics, vol 15, 668 (1976)
- T tolerance = 2 * policies::get_epsilon<T, Policy>();
- tiny = sqrt(tools::min_value<T>());
- Cr = fr = -0.5f / x;
- Ci = fi = 1;
- //Dr = Di = 0;
- T v2 = v * v;
- a = (0.25f - v2) / x; // Note complex this one time only!
- br = 2 * x;
- bi = 2;
- temp = Cr * Cr + 1;
- Ci = bi + a * Cr / temp;
- Cr = br + a / temp;
- Dr = br;
- Di = bi;
- if (fabs(Cr) + fabs(Ci) < tiny) { Cr = tiny; }
- if (fabs(Dr) + fabs(Di) < tiny) { Dr = tiny; }
- temp = Dr * Dr + Di * Di;
- Dr = Dr / temp;
- Di = -Di / temp;
- delta_r = Cr * Dr - Ci * Di;
- delta_i = Ci * Dr + Cr * Di;
- temp = fr;
- fr = temp * delta_r - fi * delta_i;
- fi = temp * delta_i + fi * delta_r;
- for (k = 2; k < policies::get_max_series_iterations<Policy>(); k++)
- {
- a = k - 0.5f;
- a *= a;
- a -= v2;
- bi += 2;
- temp = Cr * Cr + Ci * Ci;
- Cr = br + a * Cr / temp;
- Ci = bi - a * Ci / temp;
- Dr = br + a * Dr;
- Di = bi + a * Di;
- if (fabs(Cr) + fabs(Ci) < tiny) { Cr = tiny; }
- if (fabs(Dr) + fabs(Di) < tiny) { Dr = tiny; }
- temp = Dr * Dr + Di * Di;
- Dr = Dr / temp;
- Di = -Di / temp;
- delta_r = Cr * Dr - Ci * Di;
- delta_i = Ci * Dr + Cr * Di;
- temp = fr;
- fr = temp * delta_r - fi * delta_i;
- fi = temp * delta_i + fi * delta_r;
- if (fabs(delta_r - 1) + fabs(delta_i) < tolerance)
- break;
- }
- policies::check_series_iterations<T>("boost::math::bessel_jy<%1%>(%1%,%1%) in CF2_jy", k, pol);
- *p = fr;
- *q = fi;
-
- return 0;
-}
-
-enum
-{
- need_j = 1, need_y = 2
-};
-
-// Compute J(v, x) and Y(v, x) simultaneously by Steed's method, see
-// Barnett et al, Computer Physics Communications, vol 8, 377 (1974)
-template <typename T, typename Policy>
-int bessel_jy(T v, T x, T* J, T* Y, int kind, const Policy& pol)
-{
- BOOST_ASSERT(x >= 0);
-
- T u, Jv, Ju, Yv, Yv1, Yu, Yu1(0), fv, fu;
- T W, p, q, gamma, current, prev, next;
- bool reflect = false;
- unsigned n, k;
- int s;
- int org_kind = kind;
- T cp = 0;
- T sp = 0;
-
- static const char* function = "boost::math::bessel_jy<%1%>(%1%,%1%)";
-
- BOOST_MATH_STD_USING
- using namespace boost::math::tools;
- using namespace boost::math::constants;
-
- if (v < 0)
- {
- reflect = true;
- v = -v; // v is non-negative from here
- kind = need_j|need_y; // need both for reflection formula
- }
- n = iround(v, pol);
- u = v - n; // -1/2 <= u < 1/2
-
- if(reflect)
- {
- T z = (u + n % 2);
- cp = boost::math::cos_pi(z, pol);
- sp = boost::math::sin_pi(z, pol);
- }
-
- if (x == 0)
- {
- *J = *Y = policies::raise_overflow_error<T>(
- function, 0, pol);
- return 1;
- }
-
- // x is positive until reflection
- W = T(2) / (x * pi<T>()); // Wronskian
- T Yv_scale = 1;
- if((x > 8) && (x < 1000) && hankel_PQ(v, x, &p, &q, pol))
- {
- //
- // Hankel approximation: note that this method works best when x
- // is large, but in that case we end up calculating sines and cosines
- // of large values, with horrendous resulting accuracy. It is fast though
- // when it works....
- //
- T chi = x - fmod(T(v / 2 + 0.25f), T(2)) * boost::math::constants::pi<T>();
- T sc = sin(chi);
- T cc = cos(chi);
- chi = sqrt(2 / (boost::math::constants::pi<T>() * x));
- Yv = chi * (p * sc + q * cc);
- Jv = chi * (p * cc - q * sc);
- }
- else if((x < 1) && (u != 0) && (log(policies::get_epsilon<T, Policy>() / 2) > v * log((x/2) * (x/2) / v)))
- {
- // Evaluate using series representations.
- // This is particularly important for x << v as in this
- // area temme_jy may be slow to converge, if it converges at all.
- // Requires x is not an integer.
- if(kind&need_j)
- Jv = bessel_j_small_z_series(v, x, pol);
- else
- Jv = std::numeric_limits<T>::quiet_NaN();
- if((org_kind&need_y && (!reflect || (cp != 0)))
- || (org_kind & need_j && (reflect && (sp != 0))))
- {
- // Only calculate if we need it, and if the reflection formula will actually use it:
- Yv = bessel_y_small_z_series(v, x, &Yv_scale, pol);
- }
- else
- Yv = std::numeric_limits<T>::quiet_NaN();
- }
- else if((u == 0) && (x < policies::get_epsilon<T, Policy>()))
- {
- // Truncated series evaluation for small x and v an integer,
- // much quicker in this area than temme_jy below.
- if(kind&need_j)
- Jv = bessel_j_small_z_series(v, x, pol);
- else
- Jv = std::numeric_limits<T>::quiet_NaN();
- if((org_kind&need_y && (!reflect || (cp != 0)))
- || (org_kind & need_j && (reflect && (sp != 0))))
- {
- // Only calculate if we need it, and if the reflection formula will actually use it:
- Yv = bessel_yn_small_z(n, x, &Yv_scale, pol);
- }
- else
- Yv = std::numeric_limits<T>::quiet_NaN();
- }
- else if (x <= 2) // x in (0, 2]
- {
- if(temme_jy(u, x, &Yu, &Yu1, pol)) // Temme series
- {
- // domain error:
- *J = *Y = Yu;
- return 1;
- }
- prev = Yu;
- current = Yu1;
- T scale = 1;
- for (k = 1; k <= n; k++) // forward recurrence for Y
- {
- T fact = 2 * (u + k) / x;
- if((tools::max_value<T>() - fabs(prev)) / fact < fabs(current))
+ namespace detail {
+
+ //
+ // Simultaneous calculation of A&S 9.2.9 and 9.2.10
+ // for use in A&S 9.2.5 and 9.2.6.
+ // This series is quick to evaluate, but divergent unless
+ // x is very large, in fact it's pretty hard to figure out
+ // with any degree of precision when this series actually
+ // *will* converge!! Consequently, we may just have to
+ // try it and see...
+ //
+ template <class T, class Policy>
+ bool hankel_PQ(T v, T x, T* p, T* q, const Policy& )
+ {
+ BOOST_MATH_STD_USING
+ T tolerance = 2 * policies::get_epsilon<T, Policy>();
+ *p = 1;
+ *q = 0;
+ T k = 1;
+ T z8 = 8 * x;
+ T sq = 1;
+ T mu = 4 * v * v;
+ T term = 1;
+ bool ok = true;
+ do
+ {
+ term *= (mu - sq * sq) / (k * z8);
+ *q += term;
+ k += 1;
+ sq += 2;
+ T mult = (sq * sq - mu) / (k * z8);
+ ok = fabs(mult) < 0.5f;
+ term *= mult;
+ *p += term;
+ k += 1;
+ sq += 2;
+ }
+ while((fabs(term) > tolerance * *p) && ok);
+ return ok;
+ }
+
+ // Calculate Y(v, x) and Y(v+1, x) by Temme's method, see
+ // Temme, Journal of Computational Physics, vol 21, 343 (1976)
+ template <typename T, typename Policy>
+ int temme_jy(T v, T x, T* Y, T* Y1, const Policy& pol)
+ {
+ T g, h, p, q, f, coef, sum, sum1, tolerance;
+ T a, d, e, sigma;
+ unsigned long k;
+
+ BOOST_MATH_STD_USING
+ using namespace boost::math::tools;
+ using namespace boost::math::constants;
+
+ BOOST_ASSERT(fabs(v) <= 0.5f); // precondition for using this routine
+
+ T gp = boost::math::tgamma1pm1(v, pol);
+ T gm = boost::math::tgamma1pm1(-v, pol);
+ T spv = boost::math::sin_pi(v, pol);
+ T spv2 = boost::math::sin_pi(v/2, pol);
+ T xp = pow(x/2, v);
+
+ a = log(x / 2);
+ sigma = -a * v;
+ d = abs(sigma) < tools::epsilon<T>() ?
+ T(1) : sinh(sigma) / sigma;
+ e = abs(v) < tools::epsilon<T>() ? T(v*pi<T>()*pi<T>() / 2)
+ : T(2 * spv2 * spv2 / v);
+
+ T g1 = (v == 0) ? T(-euler<T>()) : T((gp - gm) / ((1 + gp) * (1 + gm) * 2 * v));
+ T g2 = (2 + gp + gm) / ((1 + gp) * (1 + gm) * 2);
+ T vspv = (fabs(v) < tools::epsilon<T>()) ? T(1/constants::pi<T>()) : T(v / spv);
+ f = (g1 * cosh(sigma) - g2 * a * d) * 2 * vspv;
+
+ p = vspv / (xp * (1 + gm));
+ q = vspv * xp / (1 + gp);
+
+ g = f + e * q;
+ h = p;
+ coef = 1;
+ sum = coef * g;
+ sum1 = coef * h;
+
+ T v2 = v * v;
+ T coef_mult = -x * x / 4;
+
+ // series summation
+ tolerance = policies::get_epsilon<T, Policy>();
+ for (k = 1; k < policies::get_max_series_iterations<Policy>(); k++)
+ {
+ f = (k * f + p + q) / (k*k - v2);
+ p /= k - v;
+ q /= k + v;
+ g = f + e * q;
+ h = p - k * g;
+ coef *= coef_mult / k;
+ sum += coef * g;
+ sum1 += coef * h;
+ if (abs(coef * g) < abs(sum) * tolerance)
+ {
+ break;
+ }
+ }
+ policies::check_series_iterations<T>("boost::math::bessel_jy<%1%>(%1%,%1%) in temme_jy", k, pol);
+ *Y = -sum;
+ *Y1 = -2 * sum1 / x;
+
+ return 0;
+ }
+
+ // Evaluate continued fraction fv = J_(v+1) / J_v, see
+ // Abramowitz and Stegun, Handbook of Mathematical Functions, 1972, 9.1.73
+ template <typename T, typename Policy>
+ int CF1_jy(T v, T x, T* fv, int* sign, const Policy& pol)
+ {
+ T C, D, f, a, b, delta, tiny, tolerance;
+ unsigned long k;
+ int s = 1;
+
+ BOOST_MATH_STD_USING
+
+ // |x| <= |v|, CF1_jy converges rapidly
+ // |x| > |v|, CF1_jy needs O(|x|) iterations to converge
+
+ // modified Lentz's method, see
+ // Lentz, Applied Optics, vol 15, 668 (1976)
+ tolerance = 2 * policies::get_epsilon<T, Policy>();;
+ tiny = sqrt(tools::min_value<T>());
+ C = f = tiny; // b0 = 0, replace with tiny
+ D = 0;
+ for (k = 1; k < policies::get_max_series_iterations<Policy>() * 100; k++)
+ {
+ a = -1;
+ b = 2 * (v + k) / x;
+ C = b + a / C;
+ D = b + a * D;
+ if (C == 0) { C = tiny; }
+ if (D == 0) { D = tiny; }
+ D = 1 / D;
+ delta = C * D;
+ f *= delta;
+ if (D < 0) { s = -s; }
+ if (abs(delta - 1) < tolerance)
+ { break; }
+ }
+ policies::check_series_iterations<T>("boost::math::bessel_jy<%1%>(%1%,%1%) in CF1_jy", k / 100, pol);
+ *fv = -f;
+ *sign = s; // sign of denominator
+
+ return 0;
+ }
+ //
+ // This algorithm was originally written by Xiaogang Zhang
+ // using std::complex to perform the complex arithmetic.
+ // However, that turns out to 10x or more slower than using
+ // all real-valued arithmetic, so it's been rewritten using
+ // real values only.
+ //
+ template <typename T, typename Policy>
+ int CF2_jy(T v, T x, T* p, T* q, const Policy& pol)
+ {
+ BOOST_MATH_STD_USING
+
+ T Cr, Ci, Dr, Di, fr, fi, a, br, bi, delta_r, delta_i, temp;
+ T tiny;
+ unsigned long k;
+
+ // |x| >= |v|, CF2_jy converges rapidly
+ // |x| -> 0, CF2_jy fails to converge
+ BOOST_ASSERT(fabs(x) > 1);
+
+ // modified Lentz's method, complex numbers involved, see
+ // Lentz, Applied Optics, vol 15, 668 (1976)
+ T tolerance = 2 * policies::get_epsilon<T, Policy>();
+ tiny = sqrt(tools::min_value<T>());
+ Cr = fr = -0.5f / x;
+ Ci = fi = 1;
+ //Dr = Di = 0;
+ T v2 = v * v;
+ a = (0.25f - v2) / x; // Note complex this one time only!
+ br = 2 * x;
+ bi = 2;
+ temp = Cr * Cr + 1;
+ Ci = bi + a * Cr / temp;
+ Cr = br + a / temp;
+ Dr = br;
+ Di = bi;
+ if (fabs(Cr) + fabs(Ci) < tiny) { Cr = tiny; }
+ if (fabs(Dr) + fabs(Di) < tiny) { Dr = tiny; }
+ temp = Dr * Dr + Di * Di;
+ Dr = Dr / temp;
+ Di = -Di / temp;
+ delta_r = Cr * Dr - Ci * Di;
+ delta_i = Ci * Dr + Cr * Di;
+ temp = fr;
+ fr = temp * delta_r - fi * delta_i;
+ fi = temp * delta_i + fi * delta_r;
+ for (k = 2; k < policies::get_max_series_iterations<Policy>(); k++)
+ {
+ a = k - 0.5f;
+ a *= a;
+ a -= v2;
+ bi += 2;
+ temp = Cr * Cr + Ci * Ci;
+ Cr = br + a * Cr / temp;
+ Ci = bi - a * Ci / temp;
+ Dr = br + a * Dr;
+ Di = bi + a * Di;
+ if (fabs(Cr) + fabs(Ci) < tiny) { Cr = tiny; }
+ if (fabs(Dr) + fabs(Di) < tiny) { Dr = tiny; }
+ temp = Dr * Dr + Di * Di;
+ Dr = Dr / temp;
+ Di = -Di / temp;
+ delta_r = Cr * Dr - Ci * Di;
+ delta_i = Ci * Dr + Cr * Di;
+ temp = fr;
+ fr = temp * delta_r - fi * delta_i;
+ fi = temp * delta_i + fi * delta_r;
+ if (fabs(delta_r - 1) + fabs(delta_i) < tolerance)
+ break;
+ }
+ policies::check_series_iterations<T>("boost::math::bessel_jy<%1%>(%1%,%1%) in CF2_jy", k, pol);
+ *p = fr;
+ *q = fi;
+
+ return 0;
+ }
+
+ static const int need_j = 1;
+ static const int need_y = 2;
+
+ // Compute J(v, x) and Y(v, x) simultaneously by Steed's method, see
+ // Barnett et al, Computer Physics Communications, vol 8, 377 (1974)
+ template <typename T, typename Policy>
+ int bessel_jy(T v, T x, T* J, T* Y, int kind, const Policy& pol)
+ {
+ BOOST_ASSERT(x >= 0);
+
+ T u, Jv, Ju, Yv, Yv1, Yu, Yu1(0), fv, fu;
+ T W, p, q, gamma, current, prev, next;
+ bool reflect = false;
+ unsigned n, k;
+ int s;
+ int org_kind = kind;
+ T cp = 0;
+ T sp = 0;
+
+ static const char* function = "boost::math::bessel_jy<%1%>(%1%,%1%)";
+
+ BOOST_MATH_STD_USING
+ using namespace boost::math::tools;
+ using namespace boost::math::constants;
+
+ if (v < 0)
+ {
+ reflect = true;
+ v = -v; // v is non-negative from here
+ }
+ if (v > static_cast<T>((std::numeric_limits<int>::max)()))
+ {
+ *J = *Y = policies::raise_evaluation_error<T>(function, "Order of Bessel function is too large to evaluate: got %1%", v, pol);
+ return 1;
+ }
+ n = iround(v, pol);
+ u = v - n; // -1/2 <= u < 1/2
+
+ if(reflect)
+ {
+ T z = (u + n % 2);
+ cp = boost::math::cos_pi(z, pol);
+ sp = boost::math::sin_pi(z, pol);
+ if(u != 0)
+ kind = need_j|need_y; // need both for reflection formula
+ }
+
+ if(x == 0)
+ {
+ if(v == 0)
+ *J = 1;
+ else if((u == 0) || !reflect)
+ *J = 0;
+ else if(kind & need_j)
+ *J = policies::raise_domain_error<T>(function, "Value of Bessel J_v(x) is complex-infinity at %1%", x, pol); // complex infinity
+ else
+ *J = std::numeric_limits<T>::quiet_NaN(); // any value will do, not using J.
+
+ if((kind & need_y) == 0)
+ *Y = std::numeric_limits<T>::quiet_NaN(); // any value will do, not using Y.
+ else if(v == 0)
+ *Y = -policies::raise_overflow_error<T>(function, 0, pol);
+ else
+ *Y = policies::raise_domain_error<T>(function, "Value of Bessel Y_v(x) is complex-infinity at %1%", x, pol); // complex infinity
+ return 1;
+ }
+
+ // x is positive until reflection
+ W = T(2) / (x * pi<T>()); // Wronskian
+ T Yv_scale = 1;
+ if(((kind & need_y) == 0) && ((x < 1) || (v > x * x / 4) || (x < 5)))
+ {
+ //
+ // This series will actually converge rapidly for all small
+ // x - say up to x < 20 - but the first few terms are large
+ // and divergent which leads to large errors :-(
+ //
+ Jv = bessel_j_small_z_series(v, x, pol);
+ Yv = std::numeric_limits<T>::quiet_NaN();
+ }
+ else if((x < 1) && (u != 0) && (log(policies::get_epsilon<T, Policy>() / 2) > v * log((x/2) * (x/2) / v)))
+ {
+ // Evaluate using series representations.
+ // This is particularly important for x << v as in this
+ // area temme_jy may be slow to converge, if it converges at all.
+ // Requires x is not an integer.
+ if(kind&need_j)
+ Jv = bessel_j_small_z_series(v, x, pol);
+ else
+ Jv = std::numeric_limits<T>::quiet_NaN();
+ if((org_kind&need_y && (!reflect || (cp != 0)))
+ || (org_kind & need_j && (reflect && (sp != 0))))
{
- scale /= current;
- prev /= current;
- current = 1;
+ // Only calculate if we need it, and if the reflection formula will actually use it:
+ Yv = bessel_y_small_z_series(v, x, &Yv_scale, pol);
}
- next = fact * current - prev;
- prev = current;
- current = next;
- }
- Yv = prev;
- Yv1 = current;
- if(kind&need_j)
+ else
+ Yv = std::numeric_limits<T>::quiet_NaN();
+ }
+ else if((u == 0) && (x < policies::get_epsilon<T, Policy>()))
{
- CF1_jy(v, x, &fv, &s, pol); // continued fraction CF1_jy
- Jv = scale * W / (Yv * fv - Yv1); // Wronskian relation
+ // Truncated series evaluation for small x and v an integer,
+ // much quicker in this area than temme_jy below.
+ if(kind&need_j)
+ Jv = bessel_j_small_z_series(v, x, pol);
+ else
+ Jv = std::numeric_limits<T>::quiet_NaN();
+ if((org_kind&need_y && (!reflect || (cp != 0)))
+ || (org_kind & need_j && (reflect && (sp != 0))))
+ {
+ // Only calculate if we need it, and if the reflection formula will actually use it:
+ Yv = bessel_yn_small_z(n, x, &Yv_scale, pol);
+ }
+ else
+ Yv = std::numeric_limits<T>::quiet_NaN();
}
- else
- Jv = std::numeric_limits<T>::quiet_NaN(); // any value will do, we're not using it.
- Yv_scale = scale;
- }
- else // x in (2, \infty)
- {
- // Get Y(u, x):
- // define tag type that will dispatch to right limits:
- typedef typename bessel_asymptotic_tag<T, Policy>::type tag_type;
-
- T lim, ratio;
- switch(kind)
- {
- case need_j:
- lim = asymptotic_bessel_j_limit<T>(v, tag_type());
- break;
- case need_y:
- lim = asymptotic_bessel_y_limit<T>(tag_type());
- break;
- default:
- lim = (std::max)(
- asymptotic_bessel_j_limit<T>(v, tag_type()),
- asymptotic_bessel_y_limit<T>(tag_type()));
- break;
- }
- if(x > lim)
- {
- if(kind&need_y)
- {
- Yu = asymptotic_bessel_y_large_x_2(u, x);
- Yu1 = asymptotic_bessel_y_large_x_2(T(u + 1), x);
- }
- else
- Yu = std::numeric_limits<T>::quiet_NaN(); // any value will do, we're not using it.
- if(kind&need_j)
- {
- Jv = asymptotic_bessel_j_large_x_2(v, x);
- }
- else
- Jv = std::numeric_limits<T>::quiet_NaN(); // any value will do, we're not using it.
- }
- else
- {
- CF1_jy(v, x, &fv, &s, pol);
- // tiny initial value to prevent overflow
- T init = sqrt(tools::min_value<T>());
- prev = fv * s * init;
- current = s * init;
- if(v < max_factorial<T>::value)
- {
- for (k = n; k > 0; k--) // backward recurrence for J
- {
+ else if(asymptotic_bessel_large_x_limit(v, x))
+ {
+ if(kind&need_y)
+ {
+ Yv = asymptotic_bessel_y_large_x_2(v, x);
+ }
+ else
+ Yv = std::numeric_limits<T>::quiet_NaN(); // any value will do, we're not using it.
+ if(kind&need_j)
+ {
+ Jv = asymptotic_bessel_j_large_x_2(v, x);
+ }
+ else
+ Jv = std::numeric_limits<T>::quiet_NaN(); // any value will do, we're not using it.
+ }
+ else if((x > 8) && hankel_PQ(v, x, &p, &q, pol))
+ {
+ //
+ // Hankel approximation: note that this method works best when x
+ // is large, but in that case we end up calculating sines and cosines
+ // of large values, with horrendous resulting accuracy. It is fast though
+ // when it works....
+ //
+ // Normally we calculate sin/cos(chi) where:
+ //
+ // chi = x - fmod(T(v / 2 + 0.25f), T(2)) * boost::math::constants::pi<T>();
+ //
+ // But this introduces large errors, so use sin/cos addition formulae to
+ // improve accuracy:
+ //
+ T mod_v = fmod(T(v / 2 + 0.25f), T(2));
+ T sx = sin(x);
+ T cx = cos(x);
+ T sv = sin_pi(mod_v);
+ T cv = cos_pi(mod_v);
+
+ T sc = sx * cv - sv * cx; // == sin(chi);
+ T cc = cx * cv + sx * sv; // == cos(chi);
+ T chi = boost::math::constants::root_two<T>() / (boost::math::constants::root_pi<T>() * sqrt(x)); //sqrt(2 / (boost::math::constants::pi<T>() * x));
+ Yv = chi * (p * sc + q * cc);
+ Jv = chi * (p * cc - q * sc);
+ }
+ else if (x <= 2) // x in (0, 2]
+ {
+ if(temme_jy(u, x, &Yu, &Yu1, pol)) // Temme series
+ {
+ // domain error:
+ *J = *Y = Yu;
+ return 1;
+ }
+ prev = Yu;
+ current = Yu1;
+ T scale = 1;
+ policies::check_series_iterations<T>(function, n, pol);
+ for (k = 1; k <= n; k++) // forward recurrence for Y
+ {
+ T fact = 2 * (u + k) / x;
+ if((tools::max_value<T>() - fabs(prev)) / fact < fabs(current))
+ {
+ scale /= current;
+ prev /= current;
+ current = 1;
+ }
+ next = fact * current - prev;
+ prev = current;
+ current = next;
+ }
+ Yv = prev;
+ Yv1 = current;
+ if(kind&need_j)
+ {
+ CF1_jy(v, x, &fv, &s, pol); // continued fraction CF1_jy
+ Jv = scale * W / (Yv * fv - Yv1); // Wronskian relation
+ }
+ else
+ Jv = std::numeric_limits<T>::quiet_NaN(); // any value will do, we're not using it.
+ Yv_scale = scale;
+ }
+ else // x in (2, \infty)
+ {
+ // Get Y(u, x):
+
+ T ratio;
+ CF1_jy(v, x, &fv, &s, pol);
+ // tiny initial value to prevent overflow
+ T init = sqrt(tools::min_value<T>());
+ BOOST_MATH_INSTRUMENT_VARIABLE(init);
+ prev = fv * s * init;
+ current = s * init;
+ if(v < max_factorial<T>::value)
+ {
+ policies::check_series_iterations<T>(function, n, pol);
+ for (k = n; k > 0; k--) // backward recurrence for J
+ {
next = 2 * (u + k) * current / x - prev;
prev = current;
current = next;
- }
- ratio = (s * init) / current; // scaling ratio
- // can also call CF1_jy() to get fu, not much difference in precision
- fu = prev / current;
- }
- else
- {
- //
- // When v is large we may get overflow in this calculation
- // leading to NaN's and other nasty surprises:
- //
- bool over = false;
- for (k = n; k > 0; k--) // backward recurrence for J
- {
+ }
+ ratio = (s * init) / current; // scaling ratio
+ // can also call CF1_jy() to get fu, not much difference in precision
+ fu = prev / current;
+ }
+ else
+ {
+ //
+ // When v is large we may get overflow in this calculation
+ // leading to NaN's and other nasty surprises:
+ //
+ policies::check_series_iterations<T>(function, n, pol);
+ bool over = false;
+ for (k = n; k > 0; k--) // backward recurrence for J
+ {
T t = 2 * (u + k) / x;
- if(tools::max_value<T>() / t < current)
+ if((t > 1) && (tools::max_value<T>() / t < current))
{
over = true;
break;
@@ -469,87 +493,95 @@ int bessel_jy(T v, T x, T* J, T* Y, int kind, const Policy& pol)
next = t * current - prev;
prev = current;
current = next;
- }
- if(!over)
- {
- ratio = (s * init) / current; // scaling ratio
- // can also call CF1_jy() to get fu, not much difference in precision
- fu = prev / current;
- }
- else
- {
- ratio = 0;
- fu = 1;
- }
- }
- CF2_jy(u, x, &p, &q, pol); // continued fraction CF2_jy
- T t = u / x - fu; // t = J'/J
- gamma = (p - t) / q;
- //
- // We can't allow gamma to cancel out to zero competely as it messes up
- // the subsequent logic. So pretend that one bit didn't cancel out
- // and set to a suitably small value. The only test case we've been able to
- // find for this, is when v = 8.5 and x = 4*PI.
- //
- if(gamma == 0)
- {
- gamma = u * tools::epsilon<T>() / x;
- }
- Ju = sign(current) * sqrt(W / (q + gamma * (p - t)));
-
- Jv = Ju * ratio; // normalization
-
- Yu = gamma * Ju;
- Yu1 = Yu * (u/x - p - q/gamma);
- }
- if(kind&need_y)
- {
- // compute Y:
- prev = Yu;
- current = Yu1;
- for (k = 1; k <= n; k++) // forward recurrence for Y
- {
- T fact = 2 * (u + k) / x;
- if((tools::max_value<T>() - fabs(prev)) / fact < fabs(current))
+ }
+ if(!over)
{
- prev /= current;
- Yv_scale /= current;
- current = 1;
+ ratio = (s * init) / current; // scaling ratio
+ // can also call CF1_jy() to get fu, not much difference in precision
+ fu = prev / current;
}
- next = fact * current - prev;
- prev = current;
- current = next;
- }
- Yv = prev;
- }
- else
- Yv = std::numeric_limits<T>::quiet_NaN(); // any value will do, we're not using it.
- }
-
- if (reflect)
- {
- if((sp != 0) && (tools::max_value<T>() * fabs(Yv_scale) < fabs(sp * Yv)))
- *J = org_kind & need_j ? T(-sign(sp) * sign(Yv) * sign(Yv_scale) * policies::raise_overflow_error<T>(function, 0, pol)) : T(0);
- else
- *J = cp * Jv - (sp == 0 ? T(0) : T((sp * Yv) / Yv_scale)); // reflection formula
- if((cp != 0) && (tools::max_value<T>() * fabs(Yv_scale) < fabs(cp * Yv)))
- *Y = org_kind & need_y ? T(-sign(cp) * sign(Yv) * sign(Yv_scale) * policies::raise_overflow_error<T>(function, 0, pol)) : T(0);
- else
- *Y = sp * Jv + (cp == 0 ? T(0) : T((cp * Yv) / Yv_scale));
- }
- else
- {
- *J = Jv;
- if(tools::max_value<T>() * fabs(Yv_scale) < fabs(Yv))
- *Y = org_kind & need_y ? T(sign(Yv) * sign(Yv_scale) * policies::raise_overflow_error<T>(function, 0, pol)) : T(0);
- else
- *Y = Yv / Yv_scale;
- }
-
- return 0;
-}
-
-} // namespace detail
+ else
+ {
+ ratio = 0;
+ fu = 1;
+ }
+ }
+ CF2_jy(u, x, &p, &q, pol); // continued fraction CF2_jy
+ T t = u / x - fu; // t = J'/J
+ gamma = (p - t) / q;
+ //
+ // We can't allow gamma to cancel out to zero competely as it messes up
+ // the subsequent logic. So pretend that one bit didn't cancel out
+ // and set to a suitably small value. The only test case we've been able to
+ // find for this, is when v = 8.5 and x = 4*PI.
+ //
+ if(gamma == 0)
+ {
+ gamma = u * tools::epsilon<T>() / x;
+ }
+ BOOST_MATH_INSTRUMENT_VARIABLE(current);
+ BOOST_MATH_INSTRUMENT_VARIABLE(W);
+ BOOST_MATH_INSTRUMENT_VARIABLE(q);
+ BOOST_MATH_INSTRUMENT_VARIABLE(gamma);
+ BOOST_MATH_INSTRUMENT_VARIABLE(p);
+ BOOST_MATH_INSTRUMENT_VARIABLE(t);
+ Ju = sign(current) * sqrt(W / (q + gamma * (p - t)));
+ BOOST_MATH_INSTRUMENT_VARIABLE(Ju);
+
+ Jv = Ju * ratio; // normalization
+
+ Yu = gamma * Ju;
+ Yu1 = Yu * (u/x - p - q/gamma);
+
+ if(kind&need_y)
+ {
+ // compute Y:
+ prev = Yu;
+ current = Yu1;
+ policies::check_series_iterations<T>(function, n, pol);
+ for (k = 1; k <= n; k++) // forward recurrence for Y
+ {
+ T fact = 2 * (u + k) / x;
+ if((tools::max_value<T>() - fabs(prev)) / fact < fabs(current))
+ {
+ prev /= current;
+ Yv_scale /= current;
+ current = 1;
+ }
+ next = fact * current - prev;
+ prev = current;
+ current = next;
+ }
+ Yv = prev;
+ }
+ else
+ Yv = std::numeric_limits<T>::quiet_NaN(); // any value will do, we're not using it.
+ }
+
+ if (reflect)
+ {
+ if((sp != 0) && (tools::max_value<T>() * fabs(Yv_scale) < fabs(sp * Yv)))
+ *J = org_kind & need_j ? T(-sign(sp) * sign(Yv) * sign(Yv_scale) * policies::raise_overflow_error<T>(function, 0, pol)) : T(0);
+ else
+ *J = cp * Jv - (sp == 0 ? T(0) : T((sp * Yv) / Yv_scale)); // reflection formula
+ if((cp != 0) && (tools::max_value<T>() * fabs(Yv_scale) < fabs(cp * Yv)))
+ *Y = org_kind & need_y ? T(-sign(cp) * sign(Yv) * sign(Yv_scale) * policies::raise_overflow_error<T>(function, 0, pol)) : T(0);
+ else
+ *Y = (sp != 0 ? sp * Jv : T(0)) + (cp == 0 ? T(0) : T((cp * Yv) / Yv_scale));
+ }
+ else
+ {
+ *J = Jv;
+ if(tools::max_value<T>() * fabs(Yv_scale) < fabs(Yv))
+ *Y = org_kind & need_y ? T(sign(Yv) * sign(Yv_scale) * policies::raise_overflow_error<T>(function, 0, pol)) : T(0);
+ else
+ *Y = Yv / Yv_scale;
+ }
+
+ return 0;
+ }
+
+ } // namespace detail
}} // namespaces
diff --git a/boost/math/special_functions/detail/bessel_jy_asym.hpp b/boost/math/special_functions/detail/bessel_jy_asym.hpp
index 0021f8c86a..81f6238e58 100644
--- a/boost/math/special_functions/detail/bessel_jy_asym.hpp
+++ b/boost/math/special_functions/detail/bessel_jy_asym.hpp
@@ -21,61 +21,6 @@
namespace boost{ namespace math{ namespace detail{
template <class T>
-inline T asymptotic_bessel_j_large_x_P(T v, T x)
-{
- // A&S 9.2.9
- T s = 1;
- T mu = 4 * v * v;
- T ez2 = 8 * x;
- ez2 *= ez2;
- s -= (mu-1) * (mu-9) / (2 * ez2);
- s += (mu-1) * (mu-9) * (mu-25) * (mu - 49) / (24 * ez2 * ez2);
- return s;
-}
-
-template <class T>
-inline T asymptotic_bessel_j_large_x_Q(T v, T x)
-{
- // A&S 9.2.10
- T s = 0;
- T mu = 4 * v * v;
- T ez = 8*x;
- s += (mu-1) / ez;
- s -= (mu-1) * (mu-9) * (mu-25) / (6 * ez*ez*ez);
- return s;
-}
-
-template <class T>
-inline T asymptotic_bessel_j_large_x(T v, T x)
-{
- //
- // See http://functions.wolfram.com/BesselAiryStruveFunctions/BesselJ/06/02/02/0001/
- //
- // Also A&S 9.2.5
- //
- BOOST_MATH_STD_USING // ADL of std names
- T chi = fabs(x) - constants::pi<T>() * (2 * v + 1) / 4;
- return sqrt(2 / (constants::pi<T>() * x))
- * (asymptotic_bessel_j_large_x_P(v, x) * cos(chi)
- - asymptotic_bessel_j_large_x_Q(v, x) * sin(chi));
-}
-
-template <class T>
-inline T asymptotic_bessel_y_large_x(T v, T x)
-{
- //
- // See http://functions.wolfram.com/BesselAiryStruveFunctions/BesselJ/06/02/02/0001/
- //
- // Also A&S 9.2.5
- //
- BOOST_MATH_STD_USING // ADL of std names
- T chi = fabs(x) - constants::pi<T>() * (2 * v + 1) / 4;
- return sqrt(2 / (constants::pi<T>() * x))
- * (asymptotic_bessel_j_large_x_P(v, x) * sin(chi)
- - asymptotic_bessel_j_large_x_Q(v, x) * cos(chi));
-}
-
-template <class T>
inline T asymptotic_bessel_amplitude(T v, T x)
{
// Calculate the amplitude of J(v, x) and Y(v, x) for large
@@ -99,13 +44,14 @@ T asymptotic_bessel_phase_mx(T v, T x)
//
// Calculate the phase of J(v, x) and Y(v, x) for large x.
// See A&S 9.2.29.
- // Note that the result returned is the phase less x.
+ // Note that the result returned is the phase less (x - PI(v/2 + 1/4))
+ // which we'll factor in later when we calculate the sines/cosines of the result:
//
T mu = 4 * v * v;
T denom = 4 * x;
T denom_mult = denom * denom;
- T s = -constants::pi<T>() * (v / 2 + 0.25f);
+ T s = 0;
s += (mu - 1) / (2 * denom);
denom *= denom_mult;
s += (mu - 1) * (mu - 25) / (6 * denom);
@@ -127,10 +73,16 @@ inline T asymptotic_bessel_y_large_x_2(T v, T x)
BOOST_MATH_INSTRUMENT_VARIABLE(ampl);
BOOST_MATH_INSTRUMENT_VARIABLE(phase);
//
- // Calculate the sine of the phase, using:
- // sin(x+p) = sin(x)cos(p) + cos(x)sin(p)
+ // Calculate the sine of the phase, using
+ // sine/cosine addition rules to factor in
+ // the x - PI(v/2 + 1/4) term not added to the
+ // phase when we calculated it.
//
- T sin_phase = sin(phase) * cos(x) + cos(phase) * sin(x);
+ T cx = cos(x);
+ T sx = sin(x);
+ T ci = cos_pi(v / 2 + 0.25f);
+ T si = sin_pi(v / 2 + 0.25f);
+ T sin_phase = sin(phase) * (cx * ci + sx * si) + cos(phase) * (sx * ci - cx * si);
BOOST_MATH_INSTRUMENT_CODE(sin(phase));
BOOST_MATH_INSTRUMENT_CODE(cos(x));
BOOST_MATH_INSTRUMENT_CODE(cos(phase));
@@ -149,101 +101,39 @@ inline T asymptotic_bessel_j_large_x_2(T v, T x)
BOOST_MATH_INSTRUMENT_VARIABLE(ampl);
BOOST_MATH_INSTRUMENT_VARIABLE(phase);
//
- // Calculate the sine of the phase, using:
- // cos(x+p) = cos(x)cos(p) - sin(x)sin(p)
+ // Calculate the sine of the phase, using
+ // sine/cosine addition rules to factor in
+ // the x - PI(v/2 + 1/4) term not added to the
+ // phase when we calculated it.
//
BOOST_MATH_INSTRUMENT_CODE(cos(phase));
BOOST_MATH_INSTRUMENT_CODE(cos(x));
BOOST_MATH_INSTRUMENT_CODE(sin(phase));
BOOST_MATH_INSTRUMENT_CODE(sin(x));
- T sin_phase = cos(phase) * cos(x) - sin(phase) * sin(x);
+ T cx = cos(x);
+ T sx = sin(x);
+ T ci = cos_pi(v / 2 + 0.25f);
+ T si = sin_pi(v / 2 + 0.25f);
+ T sin_phase = cos(phase) * (cx * ci + sx * si) - sin(phase) * (sx * ci - cx * si);
BOOST_MATH_INSTRUMENT_VARIABLE(sin_phase);
return sin_phase * ampl;
}
-//
-// Various limits for the J and Y asymptotics
-// (the asympotic expansions are safe to use if
-// x is less than the limit given).
-// We assume that if we don't use these expansions then the
-// error will likely be >100eps, so the limits given are chosen
-// to lead to < 100eps truncation error.
-//
template <class T>
-inline T asymptotic_bessel_y_limit(const mpl::int_<0>&)
+inline bool asymptotic_bessel_large_x_limit(const T& v, const T& x)
{
- // default case:
BOOST_MATH_STD_USING
- return 2.25 / pow(100 * tools::epsilon<T>() / T(0.001f), T(0.2f));
-}
-template <class T>
-inline T asymptotic_bessel_y_limit(const mpl::int_<53>&)
-{
- // double case:
- return 304 /*780*/;
-}
-template <class T>
-inline T asymptotic_bessel_y_limit(const mpl::int_<64>&)
-{
- // 80-bit extended-double case:
- return 1552 /*3500*/;
-}
-template <class T>
-inline T asymptotic_bessel_y_limit(const mpl::int_<113>&)
-{
- // 128-bit long double case:
- return 1245243 /*3128000*/;
-}
-
-template <class T, class Policy>
-struct bessel_asymptotic_tag
-{
- typedef typename policies::precision<T, Policy>::type precision_type;
- typedef typename mpl::if_<
- mpl::or_<
- mpl::equal_to<precision_type, mpl::int_<0> >,
- mpl::greater<precision_type, mpl::int_<113> > >,
- mpl::int_<0>,
- typename mpl::if_<
- mpl::greater<precision_type, mpl::int_<64> >,
- mpl::int_<113>,
- typename mpl::if_<
- mpl::greater<precision_type, mpl::int_<53> >,
- mpl::int_<64>,
- mpl::int_<53>
- >::type
- >::type
- >::type type;
-};
-
-template <class T>
-inline T asymptotic_bessel_j_limit(const T& v, const mpl::int_<0>&)
-{
- // default case:
- BOOST_MATH_STD_USING
- T v2 = (std::max)(T(3), T(v * v));
- return v2 / pow(100 * tools::epsilon<T>() / T(2e-5f), T(0.17f));
-}
-template <class T>
-inline T asymptotic_bessel_j_limit(const T& v, const mpl::int_<53>&)
-{
- // double case:
- T v2 = (std::max)(T(3), T(v * v));
- return v2 * 33 /*73*/;
-}
-template <class T>
-inline T asymptotic_bessel_j_limit(const T& v, const mpl::int_<64>&)
-{
- // 80-bit extended-double case:
- T v2 = (std::max)(T(3), T(v * v));
- return v2 * 121 /*266*/;
-}
-template <class T>
-inline T asymptotic_bessel_j_limit(const T& v, const mpl::int_<113>&)
-{
- // 128-bit long double case:
- T v2 = (std::max)(T(3), T(v * v));
- return v2 * 39154 /*85700*/;
+ //
+ // Determines if x is large enough compared to v to take the asymptotic
+ // forms above. From A&S 9.2.28 we require:
+ // v < x * eps^1/8
+ // and from A&S 9.2.29 we require:
+ // v^12/10 < 1.5 * x * eps^1/10
+ // using the former seems to work OK in practice with broadly similar
+ // error rates either side of the divide for v < 10000.
+ // At double precision eps^1/8 ~= 0.01.
+ //
+ return (std::max)(T(fabs(v)), T(1)) < x * sqrt(tools::forth_root_epsilon<T>());
}
template <class T, class Policy>
diff --git a/boost/math/special_functions/detail/bessel_jy_derivatives_asym.hpp b/boost/math/special_functions/detail/bessel_jy_derivatives_asym.hpp
new file mode 100644
index 0000000000..bdbfb9d0c1
--- /dev/null
+++ b/boost/math/special_functions/detail/bessel_jy_derivatives_asym.hpp
@@ -0,0 +1,141 @@
+// Copyright (c) 2013 Anton Bikineev
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+//
+// This is a partial header, do not include on it's own!!!
+//
+// Contains asymptotic expansions for derivatives of Bessel J(v,x) and Y(v,x)
+// functions, as x -> INF.
+#ifndef BOOST_MATH_SF_DETAIL_BESSEL_JY_DERIVATIVES_ASYM_HPP
+#define BOOST_MATH_SF_DETAIL_BESSEL_JY_DERIVATIVES_ASYM_HPP
+
+#ifdef _MSC_VER
+#pragma once
+#endif
+
+namespace boost{ namespace math{ namespace detail{
+
+template <class T>
+inline T asymptotic_bessel_derivative_amplitude(T v, T x)
+{
+ // Calculate the amplitude for J'(v,x) and I'(v,x)
+ // for large x: see A&S 9.2.30.
+ BOOST_MATH_STD_USING
+ T s = 1;
+ const T mu = 4 * v * v;
+ T txq = 2 * x;
+ txq *= txq;
+
+ s -= (mu - 3) / (2 * txq);
+ s -= ((mu - 1) * (mu - 45)) / (txq * txq * 8);
+
+ return sqrt(s * 2 / (boost::math::constants::pi<T>() * x));
+}
+
+template <class T>
+inline T asymptotic_bessel_derivative_phase_mx(T v, T x)
+{
+ // Calculate the phase of J'(v, x) and Y'(v, x) for large x.
+ // See A&S 9.2.31.
+ // Note that the result returned is the phase less (x - PI(v/2 - 1/4))
+ // which we'll factor in later when we calculate the sines/cosines of the result:
+ const T mu = 4 * v * v;
+ const T mu2 = mu * mu;
+ const T mu3 = mu2 * mu;
+ T denom = 4 * x;
+ T denom_mult = denom * denom;
+
+ T s = 0;
+ s += (mu + 3) / (2 * denom);
+ denom *= denom_mult;
+ s += (mu2 + (46 * mu) - 63) / (6 * denom);
+ denom *= denom_mult;
+ s += (mu3 + (185 * mu2) - (2053 * mu) + 1899) / (5 * denom);
+ return s;
+}
+
+template <class T>
+inline T asymptotic_bessel_y_derivative_large_x_2(T v, T x)
+{
+ // See A&S 9.2.20.
+ BOOST_MATH_STD_USING
+ // Get the phase and amplitude:
+ const T ampl = asymptotic_bessel_derivative_amplitude(v, x);
+ const T phase = asymptotic_bessel_derivative_phase_mx(v, x);
+ BOOST_MATH_INSTRUMENT_VARIABLE(ampl);
+ BOOST_MATH_INSTRUMENT_VARIABLE(phase);
+ //
+ // Calculate the sine of the phase, using
+ // sine/cosine addition rules to factor in
+ // the x - PI(v/2 - 1/4) term not added to the
+ // phase when we calculated it.
+ //
+ const T cx = cos(x);
+ const T sx = sin(x);
+ const T vd2shifted = (v / 2) - 0.25f;
+ const T ci = cos_pi(vd2shifted);
+ const T si = sin_pi(vd2shifted);
+ const T sin_phase = sin(phase) * (cx * ci + sx * si) + cos(phase) * (sx * ci - cx * si);
+ BOOST_MATH_INSTRUMENT_CODE(sin(phase));
+ BOOST_MATH_INSTRUMENT_CODE(cos(x));
+ BOOST_MATH_INSTRUMENT_CODE(cos(phase));
+ BOOST_MATH_INSTRUMENT_CODE(sin(x));
+ return sin_phase * ampl;
+}
+
+template <class T>
+inline T asymptotic_bessel_j_derivative_large_x_2(T v, T x)
+{
+ // See A&S 9.2.20.
+ BOOST_MATH_STD_USING
+ // Get the phase and amplitude:
+ const T ampl = asymptotic_bessel_derivative_amplitude(v, x);
+ const T phase = asymptotic_bessel_derivative_phase_mx(v, x);
+ BOOST_MATH_INSTRUMENT_VARIABLE(ampl);
+ BOOST_MATH_INSTRUMENT_VARIABLE(phase);
+ //
+ // Calculate the sine of the phase, using
+ // sine/cosine addition rules to factor in
+ // the x - PI(v/2 - 1/4) term not added to the
+ // phase when we calculated it.
+ //
+ BOOST_MATH_INSTRUMENT_CODE(cos(phase));
+ BOOST_MATH_INSTRUMENT_CODE(cos(x));
+ BOOST_MATH_INSTRUMENT_CODE(sin(phase));
+ BOOST_MATH_INSTRUMENT_CODE(sin(x));
+ const T cx = cos(x);
+ const T sx = sin(x);
+ const T vd2shifted = (v / 2) - 0.25f;
+ const T ci = cos_pi(vd2shifted);
+ const T si = sin_pi(vd2shifted);
+ const T sin_phase = cos(phase) * (cx * ci + sx * si) - sin(phase) * (sx * ci - cx * si);
+ BOOST_MATH_INSTRUMENT_VARIABLE(sin_phase);
+ return sin_phase * ampl;
+}
+
+template <class T>
+inline bool asymptotic_bessel_derivative_large_x_limit(const T& v, const T& x)
+{
+ BOOST_MATH_STD_USING
+ //
+ // This function is the copy of math::asymptotic_bessel_large_x_limit
+ // It means that we use the same rules for determining how x is large
+ // compared to v.
+ //
+ // Determines if x is large enough compared to v to take the asymptotic
+ // forms above. From A&S 9.2.28 we require:
+ // v < x * eps^1/8
+ // and from A&S 9.2.29 we require:
+ // v^12/10 < 1.5 * x * eps^1/10
+ // using the former seems to work OK in practice with broadly similar
+ // error rates either side of the divide for v < 10000.
+ // At double precision eps^1/8 ~= 0.01.
+ //
+ return (std::max)(T(fabs(v)), T(1)) < x * sqrt(boost::math::tools::forth_root_epsilon<T>());
+}
+
+}}} // namespaces
+
+#endif // BOOST_MATH_SF_DETAIL_BESSEL_JY_DERIVATIVES_ASYM_HPP
diff --git a/boost/math/special_functions/detail/bessel_jy_derivatives_series.hpp b/boost/math/special_functions/detail/bessel_jy_derivatives_series.hpp
new file mode 100644
index 0000000000..0dc68fc73c
--- /dev/null
+++ b/boost/math/special_functions/detail/bessel_jy_derivatives_series.hpp
@@ -0,0 +1,220 @@
+// Copyright (c) 2013 Anton Bikineev
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MATH_BESSEL_JY_DERIVATIVES_SERIES_HPP
+#define BOOST_MATH_BESSEL_JY_DERIVATIVES_SERIES_HPP
+
+#ifdef _MSC_VER
+#pragma once
+#endif
+
+namespace boost{ namespace math{ namespace detail{
+
+template <class T, class Policy>
+struct bessel_j_derivative_small_z_series_term
+{
+ typedef T result_type;
+
+ bessel_j_derivative_small_z_series_term(T v_, T x)
+ : N(0), v(v_), term(1), mult(x / 2)
+ {
+ mult *= -mult;
+ // iterate if v == 0; otherwise result of
+ // first term is 0 and tools::sum_series stops
+ if (v == 0)
+ iterate();
+ }
+ T operator()()
+ {
+ T r = term * (v + 2 * N);
+ iterate();
+ return r;
+ }
+private:
+ void iterate()
+ {
+ ++N;
+ term *= mult / (N * (N + v));
+ }
+ unsigned N;
+ T v;
+ T term;
+ T mult;
+};
+//
+// Series evaluation for BesselJ'(v, z) as z -> 0.
+// It's derivative of http://functions.wolfram.com/Bessel-TypeFunctions/BesselJ/06/01/04/01/01/0003/
+// Converges rapidly for all z << v.
+//
+template <class T, class Policy>
+inline T bessel_j_derivative_small_z_series(T v, T x, const Policy& pol)
+{
+ BOOST_MATH_STD_USING
+ T prefix;
+ if (v < boost::math::max_factorial<T>::value)
+ {
+ prefix = pow(x / 2, v - 1) / 2 / boost::math::tgamma(v + 1, pol);
+ }
+ else
+ {
+ prefix = (v - 1) * log(x / 2) - constants::ln_two<T>() - boost::math::lgamma(v + 1, pol);
+ prefix = exp(prefix);
+ }
+ if (0 == prefix)
+ return prefix;
+
+ bessel_j_derivative_small_z_series_term<T, Policy> s(v, x);
+ boost::uintmax_t max_iter = boost::math::policies::get_max_series_iterations<Policy>();
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
+ T zero = 0;
+ T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon<T, Policy>(), max_iter, zero);
+#else
+ T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon<T, Policy>(), max_iter);
+#endif
+ boost::math::policies::check_series_iterations<T>("boost::math::bessel_j_derivative_small_z_series<%1%>(%1%,%1%)", max_iter, pol);
+ return prefix * result;
+}
+
+template <class T, class Policy>
+struct bessel_y_derivative_small_z_series_term_a
+{
+ typedef T result_type;
+
+ bessel_y_derivative_small_z_series_term_a(T v_, T x)
+ : N(0), v(v_)
+ {
+ mult = x / 2;
+ mult *= -mult;
+ term = 1;
+ }
+ T operator()()
+ {
+ T r = term * (-v + 2 * N);
+ ++N;
+ term *= mult / (N * (N - v));
+ return r;
+ }
+private:
+ unsigned N;
+ T v;
+ T mult;
+ T term;
+};
+
+template <class T, class Policy>
+struct bessel_y_derivative_small_z_series_term_b
+{
+ typedef T result_type;
+
+ bessel_y_derivative_small_z_series_term_b(T v_, T x)
+ : N(0), v(v_)
+ {
+ mult = x / 2;
+ mult *= -mult;
+ term = 1;
+ }
+ T operator()()
+ {
+ T r = term * (v + 2 * N);
+ ++N;
+ term *= mult / (N * (N + v));
+ return r;
+ }
+private:
+ unsigned N;
+ T v;
+ T mult;
+ T term;
+};
+//
+// Series form for BesselY' as z -> 0,
+// It's derivative of http://functions.wolfram.com/Bessel-TypeFunctions/BesselY/06/01/04/01/01/0003/
+// This series is only useful when the second term is small compared to the first
+// otherwise we get catestrophic cancellation errors.
+//
+// Approximating tgamma(v) by v^v, and assuming |tgamma(-z)| < eps we end up requiring:
+// eps/2 * v^v(x/2)^-v > (x/2)^v or log(eps/2) > v log((x/2)^2/v)
+//
+template <class T, class Policy>
+inline T bessel_y_derivative_small_z_series(T v, T x, const Policy& pol)
+{
+ BOOST_MATH_STD_USING
+ static const char* function = "bessel_y_derivative_small_z_series<%1%>(%1%,%1%)";
+ T prefix;
+ T gam;
+ T p = log(x / 2);
+ T scale = 1;
+ bool need_logs = (v >= boost::math::max_factorial<T>::value) || (boost::math::tools::log_max_value<T>() / v < fabs(p));
+ if (!need_logs)
+ {
+ gam = boost::math::tgamma(v, pol);
+ p = pow(x / 2, v + 1) * 2;
+ if (boost::math::tools::max_value<T>() * p < gam)
+ {
+ scale /= gam;
+ gam = 1;
+ if (boost::math::tools::max_value<T>() * p < gam)
+ {
+ return -boost::math::policies::raise_overflow_error<T>(function, 0, pol);
+ }
+ }
+ prefix = -gam / (boost::math::constants::pi<T>() * p);
+ }
+ else
+ {
+ gam = boost::math::lgamma(v, pol);
+ p = (v + 1) * p + constants::ln_two<T>();
+ prefix = gam - log(boost::math::constants::pi<T>()) - p;
+ if (boost::math::tools::log_max_value<T>() < prefix)
+ {
+ prefix -= log(boost::math::tools::max_value<T>() / 4);
+ scale /= (boost::math::tools::max_value<T>() / 4);
+ if (boost::math::tools::log_max_value<T>() < prefix)
+ {
+ return -boost::math::policies::raise_overflow_error<T>(function, 0, pol);
+ }
+ }
+ prefix = -exp(prefix);
+ }
+ bessel_y_derivative_small_z_series_term_a<T, Policy> s(v, x);
+ boost::uintmax_t max_iter = boost::math::policies::get_max_series_iterations<Policy>();
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
+ T zero = 0;
+ T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon<T, Policy>(), max_iter, zero);
+#else
+ T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon<T, Policy>(), max_iter);
+#endif
+ boost::math::policies::check_series_iterations<T>("boost::math::bessel_y_derivative_small_z_series<%1%>(%1%,%1%)", max_iter, pol);
+ result *= prefix;
+
+ p = pow(x / 2, v - 1) / 2;
+ if (!need_logs)
+ {
+ prefix = boost::math::tgamma(-v, pol) * boost::math::cos_pi(v) * p / boost::math::constants::pi<T>();
+ }
+ else
+ {
+ int sgn;
+ prefix = boost::math::lgamma(-v, &sgn, pol) + (v - 1) * log(x / 2) - constants::ln_two<T>();
+ prefix = exp(prefix) * sgn / boost::math::constants::pi<T>();
+ }
+ bessel_y_derivative_small_z_series_term_b<T, Policy> s2(v, x);
+ max_iter = boost::math::policies::get_max_series_iterations<Policy>();
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
+ T b = boost::math::tools::sum_series(s2, boost::math::policies::get_epsilon<T, Policy>(), max_iter, zero);
+#else
+ T b = boost::math::tools::sum_series(s2, boost::math::policies::get_epsilon<T, Policy>(), max_iter);
+#endif
+ result += scale * prefix * b;
+ return result;
+}
+
+// Calculating of BesselY'(v,x) with small x (x < epsilon) and integer x using derivatives
+// of formulas in http://functions.wolfram.com/Bessel-TypeFunctions/BesselY/06/01/04/01/02/
+// seems to lose precision. Instead using linear combination of regular Bessel is preferred.
+
+}}} // namespaces
+
+#endif // BOOST_MATH_BESSEL_JY_DERIVATVIES_SERIES_HPP
diff --git a/boost/math/special_functions/detail/bessel_jy_series.hpp b/boost/math/special_functions/detail/bessel_jy_series.hpp
index b926366eb0..d50bef84e8 100644
--- a/boost/math/special_functions/detail/bessel_jy_series.hpp
+++ b/boost/math/special_functions/detail/bessel_jy_series.hpp
@@ -194,9 +194,9 @@ inline T bessel_y_small_z_series(T v, T x, T* pscale, const Policy& pol)
}
else
{
- int s;
- prefix = boost::math::lgamma(-v, &s, pol) + p;
- prefix = exp(prefix) * s / constants::pi<T>();
+ int sgn;
+ prefix = boost::math::lgamma(-v, &sgn, pol) + p;
+ prefix = exp(prefix) * sgn / constants::pi<T>();
}
bessel_y_small_z_series_term_b<T, Policy> s2(v, x);
max_iter = policies::get_max_series_iterations<Policy>();
@@ -235,7 +235,7 @@ T bessel_yn_small_z(int n, T z, T* scale, const Policy& pol)
{
return (z * z) / (4 * constants::pi<T>()) * log(z / 2)
- (4 / (constants::pi<T>() * z * z))
- - ((z * z) / (8 * constants::pi<T>())) * (3/2 - 2 * constants::euler<T>());
+ - ((z * z) / (8 * constants::pi<T>())) * (T(3)/2 - 2 * constants::euler<T>());
}
else
{
diff --git a/boost/math/special_functions/detail/bessel_jy_zero.hpp b/boost/math/special_functions/detail/bessel_jy_zero.hpp
new file mode 100644
index 0000000000..ecd8696eee
--- /dev/null
+++ b/boost/math/special_functions/detail/bessel_jy_zero.hpp
@@ -0,0 +1,617 @@
+// Copyright (c) 2013 Christopher Kormanyos
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// This work is based on an earlier work:
+// "Algorithm 910: A Portable C++ Multiple-Precision System for Special-Function Calculations",
+// in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. http://doi.acm.org/10.1145/1916461.1916469
+//
+// This header contains implementation details for estimating the zeros
+// of cylindrical Bessel and Neumann functions on the positive real axis.
+// Support is included for both positive as well as negative order.
+// Various methods are used to estimate the roots. These include
+// empirical curve fitting and McMahon's asymptotic approximation
+// for small order, uniform asymptotic expansion for large order,
+// and iteration and root interlacing for negative order.
+//
+#ifndef _BESSEL_JY_ZERO_2013_01_18_HPP_
+ #define _BESSEL_JY_ZERO_2013_01_18_HPP_
+
+ #include <algorithm>
+ #include <boost/math/constants/constants.hpp>
+ #include <boost/math/special_functions/math_fwd.hpp>
+ #include <boost/math/special_functions/cbrt.hpp>
+ #include <boost/math/special_functions/detail/airy_ai_bi_zero.hpp>
+
+ namespace boost { namespace math {
+ namespace detail
+ {
+ namespace bessel_zero
+ {
+ template<class T>
+ T equation_nist_10_21_19(const T& v, const T& a)
+ {
+ // Get the initial estimate of the m'th root of Jv or Yv.
+ // This subroutine is used for the order m with m > 1.
+ // The order m has been used to create the input parameter a.
+
+ // This is Eq. 10.21.19 in the NIST Handbook.
+ const T mu = (v * v) * 4U;
+ const T mu_minus_one = mu - T(1);
+ const T eight_a_inv = T(1) / (a * 8U);
+ const T eight_a_inv_squared = eight_a_inv * eight_a_inv;
+
+ const T term3 = ((mu_minus_one * 4U) * ((mu * 7U) - T(31U) )) / 3U;
+ const T term5 = ((mu_minus_one * 32U) * ((((mu * 83U) - T(982U) ) * mu) + T(3779U) )) / 15U;
+ const T term7 = ((mu_minus_one * 64U) * ((((((mu * 6949U) - T(153855UL)) * mu) + T(1585743UL)) * mu) - T(6277237UL))) / 105U;
+
+ return a + (((( - term7
+ * eight_a_inv_squared - term5)
+ * eight_a_inv_squared - term3)
+ * eight_a_inv_squared - mu_minus_one)
+ * eight_a_inv);
+ }
+
+ template<typename T>
+ class equation_as_9_3_39_and_its_derivative
+ {
+ public:
+ equation_as_9_3_39_and_its_derivative(const T& zt) : zeta(zt) { }
+
+ boost::math::tuple<T, T> operator()(const T& z) const
+ {
+ BOOST_MATH_STD_USING // ADL of std names, needed for acos, sqrt.
+
+ // Return the function of zeta that is implicitly defined
+ // in A&S Eq. 9.3.39 as a function of z. The function is
+ // returned along with its derivative with respect to z.
+
+ const T zsq_minus_one_sqrt = sqrt((z * z) - T(1));
+
+ const T the_function(
+ zsq_minus_one_sqrt
+ - ( acos(T(1) / z) + ((T(2) / 3U) * (zeta * sqrt(zeta)))));
+
+ const T its_derivative(zsq_minus_one_sqrt / z);
+
+ return boost::math::tuple<T, T>(the_function, its_derivative);
+ }
+
+ private:
+ const equation_as_9_3_39_and_its_derivative& operator=(const equation_as_9_3_39_and_its_derivative&);
+ const T zeta;
+ };
+
+ template<class T>
+ static T equation_as_9_5_26(const T& v, const T& ai_bi_root)
+ {
+ BOOST_MATH_STD_USING // ADL of std names, needed for log, sqrt.
+
+ // Obtain the estimate of the m'th zero of Jv or Yv.
+ // The order m has been used to create the input parameter ai_bi_root.
+ // Here, v is larger than about 2.2. The estimate is computed
+ // from Abramowitz and Stegun Eqs. 9.5.22 and 9.5.26, page 371.
+ //
+ // The inversion of z as a function of zeta is mentioned in the text
+ // following A&S Eq. 9.5.26. Here, we accomplish the inversion by
+ // performing a Taylor expansion of Eq. 9.3.39 for large z to order 2
+ // and solving the resulting quadratic equation, thereby taking
+ // the positive root of the quadratic.
+ // In other words: (2/3)(-zeta)^(3/2) approx = z + 1/(2z) - pi/2.
+ // This leads to: z^2 - [(2/3)(-zeta)^(3/2) + pi/2]z + 1/2 = 0.
+ //
+ // With this initial estimate, Newton-Raphson iteration is used
+ // to refine the value of the estimate of the root of z
+ // as a function of zeta.
+
+ const T v_pow_third(boost::math::cbrt(v));
+ const T v_pow_minus_two_thirds(T(1) / (v_pow_third * v_pow_third));
+
+ // Obtain zeta using the order v combined with the m'th root of
+ // an airy function, as shown in A&S Eq. 9.5.22.
+ const T zeta = v_pow_minus_two_thirds * (-ai_bi_root);
+
+ const T zeta_sqrt = sqrt(zeta);
+
+ // Set up a quadratic equation based on the Taylor series
+ // expansion mentioned above.
+ const T b = -((((zeta * zeta_sqrt) * 2U) / 3U) + boost::math::constants::half_pi<T>());
+
+ // Solve the quadratic equation, taking the positive root.
+ const T z_estimate = (-b + sqrt((b * b) - T(2))) / 2U;
+
+ // Establish the range, the digits, and the iteration limit
+ // for the upcoming root-finding.
+ const T range_zmin = (std::max<T>)(z_estimate - T(1), T(1));
+ const T range_zmax = z_estimate + T(1);
+
+ const int my_digits10 = static_cast<int>(static_cast<float>(boost::math::tools::digits<T>() * 0.301F));
+
+ // Select the maximum allowed iterations based on the number
+ // of decimal digits in the numeric type T, being at least 12.
+ const boost::uintmax_t iterations_allowed = static_cast<boost::uintmax_t>((std::max)(12, my_digits10 * 2));
+
+ boost::uintmax_t iterations_used = iterations_allowed;
+
+ // Calculate the root of z as a function of zeta.
+ const T z = boost::math::tools::newton_raphson_iterate(
+ boost::math::detail::bessel_zero::equation_as_9_3_39_and_its_derivative<T>(zeta),
+ z_estimate,
+ range_zmin,
+ range_zmax,
+ (std::min)(boost::math::tools::digits<T>(), boost::math::tools::digits<float>()),
+ iterations_used);
+
+ static_cast<void>(iterations_used);
+
+ // Continue with the implementation of A&S Eq. 9.3.39.
+ const T zsq_minus_one = (z * z) - T(1);
+ const T zsq_minus_one_sqrt = sqrt(zsq_minus_one);
+
+ // This is A&S Eq. 9.3.42.
+ const T b0_term_5_24 = T(5) / ((zsq_minus_one * zsq_minus_one_sqrt) * 24U);
+ const T b0_term_1_8 = T(1) / ( zsq_minus_one_sqrt * 8U);
+ const T b0_term_5_48 = T(5) / ((zeta * zeta) * 48U);
+
+ const T b0 = -b0_term_5_48 + ((b0_term_5_24 + b0_term_1_8) / zeta_sqrt);
+
+ // This is the second line of A&S Eq. 9.5.26 for f_k with k = 1.
+ const T f1 = ((z * zeta_sqrt) * b0) / zsq_minus_one_sqrt;
+
+ // This is A&S Eq. 9.5.22 expanded to k = 1 (i.e., one term in the series).
+ return (v * z) + (f1 / v);
+ }
+
+ namespace cyl_bessel_j_zero_detail
+ {
+ template<class T>
+ T equation_nist_10_21_40_a(const T& v)
+ {
+ const T v_pow_third(boost::math::cbrt(v));
+ const T v_pow_minus_two_thirds(T(1) / (v_pow_third * v_pow_third));
+
+ return v * ((((( + T(0.043)
+ * v_pow_minus_two_thirds - T(0.0908))
+ * v_pow_minus_two_thirds - T(0.00397))
+ * v_pow_minus_two_thirds + T(1.033150))
+ * v_pow_minus_two_thirds + T(1.8557571))
+ * v_pow_minus_two_thirds + T(1));
+ }
+
+ template<class T, class Policy>
+ class function_object_jv
+ {
+ public:
+ function_object_jv(const T& v,
+ const Policy& pol) : my_v(v),
+ my_pol(pol) { }
+
+ T operator()(const T& x) const
+ {
+ return boost::math::cyl_bessel_j(my_v, x, my_pol);
+ }
+
+ private:
+ const T my_v;
+ const Policy& my_pol;
+ const function_object_jv& operator=(const function_object_jv&);
+ };
+
+ template<class T, class Policy>
+ class function_object_jv_and_jv_prime
+ {
+ public:
+ function_object_jv_and_jv_prime(const T& v,
+ const bool order_is_zero,
+ const Policy& pol) : my_v(v),
+ my_order_is_zero(order_is_zero),
+ my_pol(pol) { }
+
+ boost::math::tuple<T, T> operator()(const T& x) const
+ {
+ // Obtain Jv(x) and Jv'(x).
+ // Chris's original code called the Bessel function implementation layer direct,
+ // but that circumvented optimizations for integer-orders. Call the documented
+ // top level functions instead, and let them sort out which implementation to use.
+ T j_v;
+ T j_v_prime;
+
+ if(my_order_is_zero)
+ {
+ j_v = boost::math::cyl_bessel_j(0, x, my_pol);
+ j_v_prime = -boost::math::cyl_bessel_j(1, x, my_pol);
+ }
+ else
+ {
+ j_v = boost::math::cyl_bessel_j( my_v, x, my_pol);
+ const T j_v_m1 (boost::math::cyl_bessel_j(T(my_v - 1), x, my_pol));
+ j_v_prime = j_v_m1 - ((my_v * j_v) / x);
+ }
+
+ // Return a tuple containing both Jv(x) and Jv'(x).
+ return boost::math::make_tuple(j_v, j_v_prime);
+ }
+
+ private:
+ const T my_v;
+ const bool my_order_is_zero;
+ const Policy& my_pol;
+ const function_object_jv_and_jv_prime& operator=(const function_object_jv_and_jv_prime&);
+ };
+
+ template<class T> bool my_bisection_unreachable_tolerance(const T&, const T&) { return false; }
+
+ template<class T, class Policy>
+ T initial_guess(const T& v, const int m, const Policy& pol)
+ {
+ BOOST_MATH_STD_USING // ADL of std names, needed for floor.
+
+ // Compute an estimate of the m'th root of cyl_bessel_j.
+
+ T guess;
+
+ // There is special handling for negative order.
+ if(v < 0)
+ {
+ if((m == 1) && (v > -0.5F))
+ {
+ // For small, negative v, use the results of empirical curve fitting.
+ // Mathematica(R) session for the coefficients:
+ // Table[{n, BesselJZero[n, 1]}, {n, -(1/2), 0, 1/10}]
+ // N[%, 20]
+ // Fit[%, {n^0, n^1, n^2, n^3, n^4, n^5, n^6}, n]
+ guess = ((((( - T(0.2321156900729)
+ * v - T(0.1493247777488))
+ * v - T(0.15205419167239))
+ * v + T(0.07814930561249))
+ * v - T(0.17757573537688))
+ * v + T(1.542805677045663))
+ * v + T(2.40482555769577277);
+
+ return guess;
+ }
+
+ // Create the positive order and extract its positive floor integer part.
+ const T vv(-v);
+ const T vv_floor(floor(vv));
+
+ // The to-be-found root is bracketed by the roots of the
+ // Bessel function whose reflected, positive integer order
+ // is less than, but nearest to vv.
+
+ T root_hi = boost::math::detail::bessel_zero::cyl_bessel_j_zero_detail::initial_guess(vv_floor, m, pol);
+ T root_lo;
+
+ if(m == 1)
+ {
+ // The estimate of the first root for negative order is found using
+ // an adaptive range-searching algorithm.
+ root_lo = T(root_hi - 0.1F);
+
+ const bool hi_end_of_bracket_is_negative = (boost::math::cyl_bessel_j(v, root_hi, pol) < 0);
+
+ while((root_lo > boost::math::tools::epsilon<T>()))
+ {
+ const bool lo_end_of_bracket_is_negative = (boost::math::cyl_bessel_j(v, root_lo, pol) < 0);
+
+ if(hi_end_of_bracket_is_negative != lo_end_of_bracket_is_negative)
+ {
+ break;
+ }
+
+ root_hi = root_lo;
+
+ // Decrease the lower end of the bracket using an adaptive algorithm.
+ if(root_lo > 0.5F)
+ {
+ root_lo -= 0.5F;
+ }
+ else
+ {
+ root_lo *= 0.75F;
+ }
+ }
+ }
+ else
+ {
+ root_lo = boost::math::detail::bessel_zero::cyl_bessel_j_zero_detail::initial_guess(vv_floor, m - 1, pol);
+ }
+
+ // Perform several steps of bisection iteration to refine the guess.
+ boost::uintmax_t number_of_iterations(12U);
+
+ // Do the bisection iteration.
+ const boost::math::tuple<T, T> guess_pair =
+ boost::math::tools::bisect(
+ boost::math::detail::bessel_zero::cyl_bessel_j_zero_detail::function_object_jv<T, Policy>(v, pol),
+ root_lo,
+ root_hi,
+ boost::math::detail::bessel_zero::cyl_bessel_j_zero_detail::my_bisection_unreachable_tolerance<T>,
+ number_of_iterations);
+
+ return (boost::math::get<0>(guess_pair) + boost::math::get<1>(guess_pair)) / 2U;
+ }
+
+ if(m == 1U)
+ {
+ // Get the initial estimate of the first root.
+
+ if(v < 2.2F)
+ {
+ // For small v, use the results of empirical curve fitting.
+ // Mathematica(R) session for the coefficients:
+ // Table[{n, BesselJZero[n, 1]}, {n, 0, 22/10, 1/10}]
+ // N[%, 20]
+ // Fit[%, {n^0, n^1, n^2, n^3, n^4, n^5, n^6}, n]
+ guess = ((((( - T(0.0008342379046010)
+ * v + T(0.007590035637410))
+ * v - T(0.030640914772013))
+ * v + T(0.078232088020106))
+ * v - T(0.169668712590620))
+ * v + T(1.542187960073750))
+ * v + T(2.4048359915254634);
+ }
+ else
+ {
+ // For larger v, use the first line of Eqs. 10.21.40 in the NIST Handbook.
+ guess = boost::math::detail::bessel_zero::cyl_bessel_j_zero_detail::equation_nist_10_21_40_a(v);
+ }
+ }
+ else
+ {
+ if(v < 2.2F)
+ {
+ // Use Eq. 10.21.19 in the NIST Handbook.
+ const T a(((v + T(m * 2U)) - T(0.5)) * boost::math::constants::half_pi<T>());
+
+ guess = boost::math::detail::bessel_zero::equation_nist_10_21_19(v, a);
+ }
+ else
+ {
+ // Get an estimate of the m'th root of airy_ai.
+ const T airy_ai_root(boost::math::detail::airy_zero::airy_ai_zero_detail::initial_guess<T>(m));
+
+ // Use Eq. 9.5.26 in the A&S Handbook.
+ guess = boost::math::detail::bessel_zero::equation_as_9_5_26(v, airy_ai_root);
+ }
+ }
+
+ return guess;
+ }
+ } // namespace cyl_bessel_j_zero_detail
+
+ namespace cyl_neumann_zero_detail
+ {
+ template<class T>
+ T equation_nist_10_21_40_b(const T& v)
+ {
+ const T v_pow_third(boost::math::cbrt(v));
+ const T v_pow_minus_two_thirds(T(1) / (v_pow_third * v_pow_third));
+
+ return v * ((((( - T(0.001)
+ * v_pow_minus_two_thirds - T(0.0060))
+ * v_pow_minus_two_thirds + T(0.01198))
+ * v_pow_minus_two_thirds + T(0.260351))
+ * v_pow_minus_two_thirds + T(0.9315768))
+ * v_pow_minus_two_thirds + T(1));
+ }
+
+ template<class T, class Policy>
+ class function_object_yv
+ {
+ public:
+ function_object_yv(const T& v,
+ const Policy& pol) : my_v(v),
+ my_pol(pol) { }
+
+ T operator()(const T& x) const
+ {
+ return boost::math::cyl_neumann(my_v, x, my_pol);
+ }
+
+ private:
+ const T my_v;
+ const Policy& my_pol;
+ const function_object_yv& operator=(const function_object_yv&);
+ };
+
+ template<class T, class Policy>
+ class function_object_yv_and_yv_prime
+ {
+ public:
+ function_object_yv_and_yv_prime(const T& v,
+ const Policy& pol) : my_v(v),
+ my_pol(pol) { }
+
+ boost::math::tuple<T, T> operator()(const T& x) const
+ {
+ const T half_epsilon(boost::math::tools::epsilon<T>() / 2U);
+
+ const bool order_is_zero = ((my_v > -half_epsilon) && (my_v < +half_epsilon));
+
+ // Obtain Yv(x) and Yv'(x).
+ // Chris's original code called the Bessel function implementation layer direct,
+ // but that circumvented optimizations for integer-orders. Call the documented
+ // top level functions instead, and let them sort out which implementation to use.
+ T y_v;
+ T y_v_prime;
+
+ if(order_is_zero)
+ {
+ y_v = boost::math::cyl_neumann(0, x, my_pol);
+ y_v_prime = -boost::math::cyl_neumann(1, x, my_pol);
+ }
+ else
+ {
+ y_v = boost::math::cyl_neumann( my_v, x, my_pol);
+ const T y_v_m1 (boost::math::cyl_neumann(T(my_v - 1), x, my_pol));
+ y_v_prime = y_v_m1 - ((my_v * y_v) / x);
+ }
+
+ // Return a tuple containing both Yv(x) and Yv'(x).
+ return boost::math::make_tuple(y_v, y_v_prime);
+ }
+
+ private:
+ const T my_v;
+ const Policy& my_pol;
+ const function_object_yv_and_yv_prime& operator=(const function_object_yv_and_yv_prime&);
+ };
+
+ template<class T> bool my_bisection_unreachable_tolerance(const T&, const T&) { return false; }
+
+ template<class T, class Policy>
+ T initial_guess(const T& v, const int m, const Policy& pol)
+ {
+ BOOST_MATH_STD_USING // ADL of std names, needed for floor.
+
+ // Compute an estimate of the m'th root of cyl_neumann.
+
+ T guess;
+
+ // There is special handling for negative order.
+ if(v < 0)
+ {
+ // Create the positive order and extract its positive floor and ceiling integer parts.
+ const T vv(-v);
+ const T vv_floor(floor(vv));
+
+ // The to-be-found root is bracketed by the roots of the
+ // Bessel function whose reflected, positive integer order
+ // is less than, but nearest to vv.
+
+ // The special case of negative, half-integer order uses
+ // the relation between Yv and spherical Bessel functions
+ // in order to obtain the bracket for the root.
+ // In these special cases, cyl_neumann(-n/2, x) = sph_bessel_j(+n/2, x)
+ // for v = -n/2.
+
+ T root_hi;
+ T root_lo;
+
+ if(m == 1)
+ {
+ // The estimate of the first root for negative order is found using
+ // an adaptive range-searching algorithm.
+ // Take special precautions for the discontinuity at negative,
+ // half-integer orders and use different brackets above and below these.
+ if(T(vv - vv_floor) < 0.5F)
+ {
+ root_hi = boost::math::detail::bessel_zero::cyl_neumann_zero_detail::initial_guess(vv_floor, m, pol);
+ }
+ else
+ {
+ root_hi = boost::math::detail::bessel_zero::cyl_bessel_j_zero_detail::initial_guess(T(vv_floor + 0.5F), m, pol);
+ }
+
+ root_lo = T(root_hi - 0.1F);
+
+ const bool hi_end_of_bracket_is_negative = (boost::math::cyl_neumann(v, root_hi, pol) < 0);
+
+ while((root_lo > boost::math::tools::epsilon<T>()))
+ {
+ const bool lo_end_of_bracket_is_negative = (boost::math::cyl_neumann(v, root_lo, pol) < 0);
+
+ if(hi_end_of_bracket_is_negative != lo_end_of_bracket_is_negative)
+ {
+ break;
+ }
+
+ root_hi = root_lo;
+
+ // Decrease the lower end of the bracket using an adaptive algorithm.
+ if(root_lo > 0.5F)
+ {
+ root_lo -= 0.5F;
+ }
+ else
+ {
+ root_lo *= 0.75F;
+ }
+ }
+ }
+ else
+ {
+ if(T(vv - vv_floor) < 0.5F)
+ {
+ root_lo = boost::math::detail::bessel_zero::cyl_neumann_zero_detail::initial_guess(vv_floor, m - 1, pol);
+ root_hi = boost::math::detail::bessel_zero::cyl_neumann_zero_detail::initial_guess(vv_floor, m, pol);
+ root_lo += 0.01F;
+ root_hi += 0.01F;
+ }
+ else
+ {
+ root_lo = boost::math::detail::bessel_zero::cyl_bessel_j_zero_detail::initial_guess(T(vv_floor + 0.5F), m - 1, pol);
+ root_hi = boost::math::detail::bessel_zero::cyl_bessel_j_zero_detail::initial_guess(T(vv_floor + 0.5F), m, pol);
+ root_lo += 0.01F;
+ root_hi += 0.01F;
+ }
+ }
+
+ // Perform several steps of bisection iteration to refine the guess.
+ boost::uintmax_t number_of_iterations(12U);
+
+ // Do the bisection iteration.
+ const boost::math::tuple<T, T> guess_pair =
+ boost::math::tools::bisect(
+ boost::math::detail::bessel_zero::cyl_neumann_zero_detail::function_object_yv<T, Policy>(v, pol),
+ root_lo,
+ root_hi,
+ boost::math::detail::bessel_zero::cyl_neumann_zero_detail::my_bisection_unreachable_tolerance<T>,
+ number_of_iterations);
+
+ return (boost::math::get<0>(guess_pair) + boost::math::get<1>(guess_pair)) / 2U;
+ }
+
+ if(m == 1U)
+ {
+ // Get the initial estimate of the first root.
+
+ if(v < 2.2F)
+ {
+ // For small v, use the results of empirical curve fitting.
+ // Mathematica(R) session for the coefficients:
+ // Table[{n, BesselYZero[n, 1]}, {n, 0, 22/10, 1/10}]
+ // N[%, 20]
+ // Fit[%, {n^0, n^1, n^2, n^3, n^4, n^5, n^6}, n]
+ guess = ((((( - T(0.0025095909235652)
+ * v + T(0.021291887049053))
+ * v - T(0.076487785486526))
+ * v + T(0.159110268115362))
+ * v - T(0.241681668765196))
+ * v + T(1.4437846310885244))
+ * v + T(0.89362115190200490);
+ }
+ else
+ {
+ // For larger v, use the second line of Eqs. 10.21.40 in the NIST Handbook.
+ guess = boost::math::detail::bessel_zero::cyl_neumann_zero_detail::equation_nist_10_21_40_b(v);
+ }
+ }
+ else
+ {
+ if(v < 2.2F)
+ {
+ // Use Eq. 10.21.19 in the NIST Handbook.
+ const T a(((v + T(m * 2U)) - T(1.5)) * boost::math::constants::half_pi<T>());
+
+ guess = boost::math::detail::bessel_zero::equation_nist_10_21_19(v, a);
+ }
+ else
+ {
+ // Get an estimate of the m'th root of airy_bi.
+ const T airy_bi_root(boost::math::detail::airy_zero::airy_bi_zero_detail::initial_guess<T>(m));
+
+ // Use Eq. 9.5.26 in the A&S Handbook.
+ guess = boost::math::detail::bessel_zero::equation_as_9_5_26(v, airy_bi_root);
+ }
+ }
+
+ return guess;
+ }
+ } // namespace cyl_neumann_zero_detail
+ } // namespace bessel_zero
+ } } } // namespace boost::math::detail
+
+#endif // _BESSEL_JY_ZERO_2013_01_18_HPP_
diff --git a/boost/math/special_functions/detail/bessel_kn.hpp b/boost/math/special_functions/detail/bessel_kn.hpp
index 5f01460995..e3a5023c63 100644
--- a/boost/math/special_functions/detail/bessel_kn.hpp
+++ b/boost/math/special_functions/detail/bessel_kn.hpp
@@ -22,6 +22,7 @@ namespace boost { namespace math { namespace detail{
template <typename T, typename Policy>
T bessel_kn(int n, T x, const Policy& pol)
{
+ BOOST_MATH_STD_USING
T value, current, prev;
using namespace boost::math::tools;
diff --git a/boost/math/special_functions/detail/bessel_y0.hpp b/boost/math/special_functions/detail/bessel_y0.hpp
index 289bda5f18..533ab7c8a0 100644
--- a/boost/math/special_functions/detail/bessel_y0.hpp
+++ b/boost/math/special_functions/detail/bessel_y0.hpp
@@ -197,11 +197,22 @@ T bessel_y0(T x, const Policy& pol)
{
T y = 8 / x;
T y2 = y * y;
- T z = x - 0.25f * pi<T>();
rc = evaluate_rational(PC, QC, y2);
rs = evaluate_rational(PS, QS, y2);
- factor = sqrt(2 / (x * pi<T>()));
- value = factor * (rc * sin(z) + y * rs * cos(z));
+ factor = constants::one_div_root_pi<T>() / sqrt(x);
+ //
+ // The following code is really just:
+ //
+ // T z = x - 0.25f * pi<T>();
+ // value = factor * (rc * sin(z) + y * rs * cos(z));
+ //
+ // But using the sin/cos addition formulae and constant values for
+ // sin/cos of PI/4 which then cancel part of the "factor" term as they're all
+ // 1 / sqrt(2):
+ //
+ T sx = sin(x);
+ T cx = cos(x);
+ value = factor * (rc * (sx - cx) + y * rs * (cx + sx));
}
return value;
diff --git a/boost/math/special_functions/detail/bessel_y1.hpp b/boost/math/special_functions/detail/bessel_y1.hpp
index caf09ffd26..8396f8fe11 100644
--- a/boost/math/special_functions/detail/bessel_y1.hpp
+++ b/boost/math/special_functions/detail/bessel_y1.hpp
@@ -170,11 +170,21 @@ T bessel_y1(T x, const Policy& pol)
{
T y = 8 / x;
T y2 = y * y;
- T z = x - 0.75f * pi<T>();
rc = evaluate_rational(PC, QC, y2);
rs = evaluate_rational(PS, QS, y2);
- factor = sqrt(2 / (x * pi<T>()));
- value = factor * (rc * sin(z) + y * rs * cos(z));
+ factor = 1 / (sqrt(x) * root_pi<T>());
+ //
+ // This code is really just:
+ //
+ // T z = x - 0.75f * pi<T>();
+ // value = factor * (rc * sin(z) + y * rs * cos(z));
+ //
+ // But using the sin/cos addition rules, plus constants for sin/cos of 3PI/4
+ // which then cancel out with corresponding terms in "factor".
+ //
+ T sx = sin(x);
+ T cx = cos(x);
+ value = factor * (y * rs * (sx - cx) - rc * (sx + cx));
}
return value;
diff --git a/boost/math/special_functions/detail/bessel_yn.hpp b/boost/math/special_functions/detail/bessel_yn.hpp
index b4f9855a2f..0509062bbd 100644
--- a/boost/math/special_functions/detail/bessel_yn.hpp
+++ b/boost/math/special_functions/detail/bessel_yn.hpp
@@ -75,10 +75,11 @@ T bessel_yn(int n, T x, const Policy& pol)
current = bessel_y1(x, pol);
int k = 1;
BOOST_ASSERT(k < n);
+ policies::check_series_iterations<T>("boost::math::bessel_y_n<%1%>(%1%,%1%)", n, pol);
do
{
T fact = 2 * k / x;
- if((tools::max_value<T>() - fabs(prev)) / fact < fabs(current))
+ if((fact > 1) && ((tools::max_value<T>() - fabs(prev)) / fact < fabs(current)))
{
prev /= current;
factor /= current;
diff --git a/boost/math/special_functions/detail/erf_inv.hpp b/boost/math/special_functions/detail/erf_inv.hpp
index d51db9d52f..77aa72fc26 100644
--- a/boost/math/special_functions/detail/erf_inv.hpp
+++ b/boost/math/special_functions/detail/erf_inv.hpp
@@ -50,7 +50,7 @@ T erf_inv_imp(const T& p, const T& q, const Policy&, const boost::mpl::int_<64>*
BOOST_MATH_BIG_CONSTANT(T, 64, -0.00538772965071242932965)
};
static const T Q[] = {
- 1,
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 64, -0.970005043303290640362),
BOOST_MATH_BIG_CONSTANT(T, 64, -1.56574558234175846809),
BOOST_MATH_BIG_CONSTANT(T, 64, 1.56221558398423026363),
@@ -92,7 +92,7 @@ T erf_inv_imp(const T& p, const T& q, const Policy&, const boost::mpl::int_<64>*
BOOST_MATH_BIG_CONSTANT(T, 64, -3.67192254707729348546)
};
static const T Q[] = {
- BOOST_MATH_BIG_CONSTANT(T, 64, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 64, 6.24264124854247537712),
BOOST_MATH_BIG_CONSTANT(T, 64, 3.9713437953343869095),
BOOST_MATH_BIG_CONSTANT(T, 64, -28.6608180499800029974),
@@ -147,7 +147,7 @@ T erf_inv_imp(const T& p, const T& q, const Policy&, const boost::mpl::int_<64>*
BOOST_MATH_BIG_CONSTANT(T, 64, -0.681149956853776992068e-9)
};
static const T Q[] = {
- 1,
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 64, 3.46625407242567245975),
BOOST_MATH_BIG_CONSTANT(T, 64, 5.38168345707006855425),
BOOST_MATH_BIG_CONSTANT(T, 64, 4.77846592945843778382),
@@ -176,7 +176,7 @@ T erf_inv_imp(const T& p, const T& q, const Policy&, const boost::mpl::int_<64>*
BOOST_MATH_BIG_CONSTANT(T, 64, 0.266339227425782031962e-11)
};
static const T Q[] = {
- BOOST_MATH_BIG_CONSTANT(T, 64, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 64, 1.3653349817554063097),
BOOST_MATH_BIG_CONSTANT(T, 64, 0.762059164553623404043),
BOOST_MATH_BIG_CONSTANT(T, 64, 0.220091105764131249824),
@@ -204,7 +204,7 @@ T erf_inv_imp(const T& p, const T& q, const Policy&, const boost::mpl::int_<64>*
BOOST_MATH_BIG_CONSTANT(T, 64, 0.99055709973310326855e-16)
};
static const T Q[] = {
- BOOST_MATH_BIG_CONSTANT(T, 64, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 64, 0.591429344886417493481),
BOOST_MATH_BIG_CONSTANT(T, 64, 0.138151865749083321638),
BOOST_MATH_BIG_CONSTANT(T, 64, 0.0160746087093676504695),
@@ -231,7 +231,7 @@ T erf_inv_imp(const T& p, const T& q, const Policy&, const boost::mpl::int_<64>*
BOOST_MATH_BIG_CONSTANT(T, 64, -0.116765012397184275695e-17)
};
static const T Q[] = {
- BOOST_MATH_BIG_CONSTANT(T, 64, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 64, 0.207123112214422517181),
BOOST_MATH_BIG_CONSTANT(T, 64, 0.0169410838120975906478),
BOOST_MATH_BIG_CONSTANT(T, 64, 0.000690538265622684595676),
@@ -258,7 +258,7 @@ T erf_inv_imp(const T& p, const T& q, const Policy&, const boost::mpl::int_<64>*
BOOST_MATH_BIG_CONSTANT(T, 64, -0.348890393399948882918e-21)
};
static const T Q[] = {
- BOOST_MATH_BIG_CONSTANT(T, 64, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 64, 0.0845746234001899436914),
BOOST_MATH_BIG_CONSTANT(T, 64, 0.00282092984726264681981),
BOOST_MATH_BIG_CONSTANT(T, 64, 0.468292921940894236786e-4),
@@ -282,7 +282,7 @@ struct erf_roots
BOOST_MATH_STD_USING
T derivative = sign * (2 / sqrt(constants::pi<T>())) * exp(-(guess * guess));
T derivative2 = -2 * guess * derivative;
- return boost::math::make_tuple(((sign > 0) ? boost::math::erf(guess, Policy()) : boost::math::erfc(guess, Policy())) - target, derivative, derivative2);
+ return boost::math::make_tuple(((sign > 0) ? static_cast<T>(boost::math::erf(guess, Policy()) - target) : static_cast<T>(boost::math::erfc(guess, Policy())) - target), derivative, derivative2);
}
erf_roots(T z, int s) : target(z), sign(s) {}
private:
@@ -331,18 +331,34 @@ struct erf_inv_initializer
{
do_init();
}
+ static bool is_value_non_zero(T);
static void do_init()
{
boost::math::erf_inv(static_cast<T>(0.25), Policy());
boost::math::erf_inv(static_cast<T>(0.55), Policy());
boost::math::erf_inv(static_cast<T>(0.95), Policy());
boost::math::erfc_inv(static_cast<T>(1e-15), Policy());
- if(static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1e-130)) != 0)
+ // These following initializations must not be called if
+ // type T can not hold the relevant values without
+ // underflow to zero. We check this at runtime because
+ // some tools such as valgrind silently change the precision
+ // of T at runtime, and numeric_limits basically lies!
+ if(is_value_non_zero(static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1e-130))))
boost::math::erfc_inv(static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1e-130)), Policy());
- if(static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1e-800)) != 0)
+
+ // Some compilers choke on constants that would underflow, even in code that isn't instantiated
+ // so try and filter these cases out in the preprocessor:
+#if LDBL_MAX_10_EXP >= 800
+ if(is_value_non_zero(static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1e-800))))
boost::math::erfc_inv(static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1e-800)), Policy());
- if(static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1e-900)) != 0)
+ if(is_value_non_zero(static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1e-900))))
boost::math::erfc_inv(static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1e-900)), Policy());
+#else
+ if(is_value_non_zero(static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 64, 1e-800))))
+ boost::math::erfc_inv(static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 64, 1e-800)), Policy());
+ if(is_value_non_zero(static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 64, 1e-900))))
+ boost::math::erfc_inv(static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 64, 1e-900)), Policy());
+#endif
}
void force_instantiate()const{}
};
@@ -356,6 +372,15 @@ struct erf_inv_initializer
template <class T, class Policy>
const typename erf_inv_initializer<T, Policy>::init erf_inv_initializer<T, Policy>::initializer;
+template <class T, class Policy>
+bool erf_inv_initializer<T, Policy>::init::is_value_non_zero(T v)
+{
+ // This needs to be non-inline to detect whether v is non zero at runtime
+ // rather than at compile time, only relevant when running under valgrind
+ // which changes long double's to double's on the fly.
+ return v != 0;
+}
+
} // namespace detail
template <class T, class Policy>
@@ -368,7 +393,7 @@ typename tools::promote_args<T>::type erfc_inv(T z, const Policy& pol)
//
static const char* function = "boost::math::erfc_inv<%1%>(%1%, %1%)";
if((z < 0) || (z > 2))
- policies::raise_domain_error<result_type>(function, "Argument outside range [0,2] in inverse erfc function (got p=%1%).", z, pol);
+ return policies::raise_domain_error<result_type>(function, "Argument outside range [0,2] in inverse erfc function (got p=%1%).", z, pol);
if(z == 0)
return policies::raise_overflow_error<result_type>(function, 0, pol);
if(z == 2)
@@ -432,7 +457,7 @@ typename tools::promote_args<T>::type erf_inv(T z, const Policy& pol)
//
static const char* function = "boost::math::erf_inv<%1%>(%1%, %1%)";
if((z < -1) || (z > 1))
- policies::raise_domain_error<result_type>(function, "Argument outside range [-1, 1] in inverse erf function (got p=%1%).", z, pol);
+ return policies::raise_domain_error<result_type>(function, "Argument outside range [-1, 1] in inverse erf function (got p=%1%).", z, pol);
if(z == 1)
return policies::raise_overflow_error<result_type>(function, 0, pol);
if(z == -1)
diff --git a/boost/math/special_functions/detail/fp_traits.hpp b/boost/math/special_functions/detail/fp_traits.hpp
index 50c034d303..63ebf11ae0 100644
--- a/boost/math/special_functions/detail/fp_traits.hpp
+++ b/boost/math/special_functions/detail/fp_traits.hpp
@@ -351,6 +351,13 @@ struct fp_traits_non_native<long double, extended_double_precision>
// the Intel extended double precision format (80 bits) and
// the IEEE extended double precision format with 15 exponent bits (128 bits).
+#elif defined(__GNUC__) && (LDBL_MANT_DIG == 106)
+
+//
+// Define nothing here and fall though to generic_tag:
+// We have GCC's "double double" in effect, and any attempt
+// to handle it via bit-fiddling is pretty much doomed to fail...
+//
// long double (>64 bits), PowerPC ---------------------------------------------
@@ -546,7 +553,9 @@ struct select_native<long double>
&& !defined(__DECCXX)\
&& !defined(__osf__) \
&& !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION)\
- && !defined(BOOST_MATH_DISABLE_STD_FPCLASSIFY)
+ && !defined(__FAST_MATH__)\
+ && !defined(BOOST_MATH_DISABLE_STD_FPCLASSIFY)\
+ && !defined(BOOST_INTEL)
# define BOOST_MATH_USE_STD_FPCLASSIFY
#endif
diff --git a/boost/math/special_functions/detail/gamma_inva.hpp b/boost/math/special_functions/detail/gamma_inva.hpp
index 549bc3d552..7c32d2946c 100644
--- a/boost/math/special_functions/detail/gamma_inva.hpp
+++ b/boost/math/special_functions/detail/gamma_inva.hpp
@@ -75,7 +75,7 @@ T gamma_inva_imp(const T& z, const T& p, const T& q, const Policy& pol)
//
if(p == 0)
{
- return tools::max_value<T>();
+ return policies::raise_overflow_error<T>("boost::math::gamma_p_inva<%1%>(%1%, %1%)", 0, Policy());
}
if(q == 0)
{
@@ -144,7 +144,7 @@ T gamma_inva_imp(const T& z, const T& p, const T& q, const Policy& pol)
//
std::pair<T, T> r = bracket_and_solve_root(f, guess, factor, false, tol, max_iter, pol);
if(max_iter >= policies::get_max_root_iterations<Policy>())
- policies::raise_evaluation_error<T>("boost::math::gamma_p_inva<%1%>(%1%, %1%)", "Unable to locate the root within a reasonable number of iterations, closest approximation so far was %1%", r.first, pol);
+ return policies::raise_evaluation_error<T>("boost::math::gamma_p_inva<%1%>(%1%, %1%)", "Unable to locate the root within a reasonable number of iterations, closest approximation so far was %1%", r.first, pol);
return (r.first + r.second) / 2;
}
@@ -165,7 +165,7 @@ inline typename tools::promote_args<T1, T2>::type
if(p == 0)
{
- return tools::max_value<result_type>();
+ policies::raise_overflow_error<result_type>("boost::math::gamma_p_inva<%1%>(%1%, %1%)", 0, Policy());
}
if(p == 1)
{
@@ -195,7 +195,7 @@ inline typename tools::promote_args<T1, T2>::type
if(q == 1)
{
- return tools::max_value<result_type>();
+ policies::raise_overflow_error<result_type>("boost::math::gamma_q_inva<%1%>(%1%, %1%)", 0, Policy());
}
if(q == 0)
{
diff --git a/boost/math/special_functions/detail/ibeta_inv_ab.hpp b/boost/math/special_functions/detail/ibeta_inv_ab.hpp
index 8318a28454..f5735a8495 100644
--- a/boost/math/special_functions/detail/ibeta_inv_ab.hpp
+++ b/boost/math/special_functions/detail/ibeta_inv_ab.hpp
@@ -153,7 +153,7 @@ T ibeta_inv_ab_imp(const T& b, const T& z, const T& p, const T& q, bool swap_ab,
boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
std::pair<T, T> r = bracket_and_solve_root(f, guess, factor, swap_ab ? true : false, tol, max_iter, pol);
if(max_iter >= policies::get_max_root_iterations<Policy>())
- policies::raise_evaluation_error<T>("boost::math::ibeta_invab_imp<%1%>(%1%,%1%,%1%)", "Unable to locate the root within a reasonable number of iterations, closest approximation so far was %1%", r.first, pol);
+ return policies::raise_evaluation_error<T>("boost::math::ibeta_invab_imp<%1%>(%1%,%1%,%1%)", "Unable to locate the root within a reasonable number of iterations, closest approximation so far was %1%", r.first, pol);
return (r.first + r.second) / 2;
}
@@ -172,9 +172,10 @@ typename tools::promote_args<RT1, RT2, RT3>::type
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
+ static const char* function = "boost::math::ibeta_inva<%1%>(%1%,%1%,%1%)";
if(p == 0)
{
- return tools::max_value<result_type>();
+ return policies::raise_overflow_error<result_type>(function, 0, Policy());
}
if(p == 1)
{
@@ -188,7 +189,7 @@ typename tools::promote_args<RT1, RT2, RT3>::type
static_cast<value_type>(p),
static_cast<value_type>(1 - static_cast<value_type>(p)),
false, pol),
- "boost::math::ibeta_inva<%1%>(%1%,%1%,%1%)");
+ function);
}
template <class RT1, class RT2, class RT3, class Policy>
@@ -204,9 +205,10 @@ typename tools::promote_args<RT1, RT2, RT3>::type
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
+ static const char* function = "boost::math::ibetac_inva<%1%>(%1%,%1%,%1%)";
if(q == 1)
{
- return tools::max_value<result_type>();
+ return policies::raise_overflow_error<result_type>(function, 0, Policy());
}
if(q == 0)
{
@@ -220,7 +222,7 @@ typename tools::promote_args<RT1, RT2, RT3>::type
static_cast<value_type>(1 - static_cast<value_type>(q)),
static_cast<value_type>(q),
false, pol),
- "boost::math::ibetac_inva<%1%>(%1%,%1%,%1%)");
+ function);
}
template <class RT1, class RT2, class RT3, class Policy>
@@ -236,13 +238,14 @@ typename tools::promote_args<RT1, RT2, RT3>::type
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
+ static const char* function = "boost::math::ibeta_invb<%1%>(%1%,%1%,%1%)";
if(p == 0)
{
return tools::min_value<result_type>();
}
if(p == 1)
{
- return tools::max_value<result_type>();
+ return policies::raise_overflow_error<result_type>(function, 0, Policy());
}
return policies::checked_narrowing_cast<result_type, forwarding_policy>(
@@ -252,13 +255,14 @@ typename tools::promote_args<RT1, RT2, RT3>::type
static_cast<value_type>(p),
static_cast<value_type>(1 - static_cast<value_type>(p)),
true, pol),
- "boost::math::ibeta_invb<%1%>(%1%,%1%,%1%)");
+ function);
}
template <class RT1, class RT2, class RT3, class Policy>
typename tools::promote_args<RT1, RT2, RT3>::type
ibetac_invb(RT1 a, RT2 x, RT3 q, const Policy& pol)
{
+ static const char* function = "boost::math::ibeta_invb<%1%>(%1%, %1%, %1%)";
typedef typename tools::promote_args<RT1, RT2, RT3>::type result_type;
typedef typename policies::evaluation<result_type, Policy>::type value_type;
typedef typename policies::normalise<
@@ -274,7 +278,7 @@ typename tools::promote_args<RT1, RT2, RT3>::type
}
if(q == 0)
{
- return tools::max_value<result_type>();
+ return policies::raise_overflow_error<result_type>(function, 0, Policy());
}
return policies::checked_narrowing_cast<result_type, forwarding_policy>(
@@ -282,9 +286,9 @@ typename tools::promote_args<RT1, RT2, RT3>::type
static_cast<value_type>(a),
static_cast<value_type>(x),
static_cast<value_type>(1 - static_cast<value_type>(q)),
- static_cast<value_type>(q),
+ static_cast<value_type>(q),
true, pol),
- "boost::math::ibetac_invb<%1%>(%1%,%1%,%1%)");
+ function);
}
template <class RT1, class RT2, class RT3>
diff --git a/boost/math/special_functions/detail/ibeta_inverse.hpp b/boost/math/special_functions/detail/ibeta_inverse.hpp
index ccfa9197d9..a9fe8cd49c 100644
--- a/boost/math/special_functions/detail/ibeta_inverse.hpp
+++ b/boost/math/special_functions/detail/ibeta_inverse.hpp
@@ -35,12 +35,12 @@ struct temme_root_finder
if(y == 0)
{
T big = tools::max_value<T>() / 4;
- return boost::math::make_tuple(-big, -big);
+ return boost::math::make_tuple(static_cast<T>(-big), static_cast<T>(-big));
}
if(x == 0)
{
T big = tools::max_value<T>() / 4;
- return boost::math::make_tuple(-big, big);
+ return boost::math::make_tuple(static_cast<T>(-big), big);
}
T f = log(x) + a * log(y) + t;
T f1 = (1 / x) - (a / (y));
@@ -455,6 +455,11 @@ T ibeta_inv_imp(T a, T b, T p, T q, const Policy& pol, T* py)
BOOST_MATH_STD_USING // For ADL of math functions.
//
+ // The flag invert is set to true if we swap a for b and p for q,
+ // in which case the result has to be subtracted from 1:
+ //
+ bool invert = false;
+ //
// Handle trivial cases first:
//
if(q == 0)
@@ -467,17 +472,19 @@ T ibeta_inv_imp(T a, T b, T p, T q, const Policy& pol, T* py)
if(py) *py = 1;
return 0;
}
- else if((a == 1) && (b == 1))
+ else if(a == 1)
{
- if(py) *py = 1 - p;
- return p;
+ if(b == 1)
+ {
+ if(py) *py = 1 - p;
+ return p;
+ }
+ // Change things around so we can handle as b == 1 special case below:
+ std::swap(a, b);
+ std::swap(p, q);
+ invert = true;
}
//
- // The flag invert is set to true if we swap a for b and p for q,
- // in which case the result has to be subtracted from 1:
- //
- bool invert = false;
- //
// Depending upon which approximation method we use, we may end up
// calculating either x or y initially (where y = 1-x):
//
@@ -495,21 +502,61 @@ T ibeta_inv_imp(T a, T b, T p, T q, const Policy& pol, T* py)
// Student's T with b = 0.5 gets handled as a special case, swap
// around if the arguments are in the "wrong" order:
//
- if((a == 0.5f) && (b >= 0.5f))
+ if(a == 0.5f)
{
- std::swap(a, b);
- std::swap(p, q);
- invert = !invert;
+ if(b == 0.5f)
+ {
+ x = sin(p * constants::half_pi<T>());
+ x *= x;
+ if(py)
+ {
+ *py = sin(q * constants::half_pi<T>());
+ *py *= *py;
+ }
+ return x;
+ }
+ else if(b > 0.5f)
+ {
+ std::swap(a, b);
+ std::swap(p, q);
+ invert = !invert;
+ }
}
//
// Select calculation method for the initial estimate:
//
- if((b == 0.5f) && (a >= 0.5f))
+ if((b == 0.5f) && (a >= 0.5f) && (p != 1))
{
//
// We have a Student's T distribution:
x = find_ibeta_inv_from_t_dist(a, p, q, &y, pol);
}
+ else if(b == 1)
+ {
+ if(p < q)
+ {
+ if(a > 1)
+ {
+ x = pow(p, 1 / a);
+ y = -boost::math::expm1(log(p) / a, pol);
+ }
+ else
+ {
+ x = pow(p, 1 / a);
+ y = 1 - x;
+ }
+ }
+ else
+ {
+ x = exp(boost::math::log1p(-q, pol) / a);
+ y = -boost::math::expm1(boost::math::log1p(-q, pol) / a, pol);
+ }
+ if(invert)
+ std::swap(x, y);
+ if(py)
+ *py = y;
+ return x;
+ }
else if(a + b > 5)
{
//
@@ -866,14 +913,16 @@ template <class T1, class T2, class T3>
inline typename tools::promote_args<T1, T2, T3>::type
ibeta_inv(T1 a, T2 b, T3 p)
{
- return ibeta_inv(a, b, p, static_cast<T1*>(0), policies::policy<>());
+ typedef typename tools::promote_args<T1, T2, T3>::type result_type;
+ return ibeta_inv(a, b, p, static_cast<result_type*>(0), policies::policy<>());
}
template <class T1, class T2, class T3, class Policy>
inline typename tools::promote_args<T1, T2, T3>::type
ibeta_inv(T1 a, T2 b, T3 p, const Policy& pol)
{
- return ibeta_inv(a, b, p, static_cast<T1*>(0), pol);
+ typedef typename tools::promote_args<T1, T2, T3>::type result_type;
+ return ibeta_inv(a, b, p, static_cast<result_type*>(0), pol);
}
template <class T1, class T2, class T3, class T4, class Policy>
@@ -892,11 +941,11 @@ inline typename tools::promote_args<T1, T2, T3, T4>::type
policies::assert_undefined<> >::type forwarding_policy;
if(a <= 0)
- policies::raise_domain_error<result_type>(function, "The argument a to the incomplete beta function inverse must be greater than zero (got a=%1%).", a, pol);
+ return policies::raise_domain_error<result_type>(function, "The argument a to the incomplete beta function inverse must be greater than zero (got a=%1%).", a, pol);
if(b <= 0)
- policies::raise_domain_error<result_type>(function, "The argument b to the incomplete beta function inverse must be greater than zero (got b=%1%).", b, pol);
+ return policies::raise_domain_error<result_type>(function, "The argument b to the incomplete beta function inverse must be greater than zero (got b=%1%).", b, pol);
if((q < 0) || (q > 1))
- policies::raise_domain_error<result_type>(function, "Argument q outside the range [0,1] in the incomplete beta function inverse (got q=%1%).", q, pol);
+ return policies::raise_domain_error<result_type>(function, "Argument q outside the range [0,1] in the incomplete beta function inverse (got q=%1%).", q, pol);
value_type rx, ry;
@@ -922,16 +971,16 @@ template <class RT1, class RT2, class RT3>
inline typename tools::promote_args<RT1, RT2, RT3>::type
ibetac_inv(RT1 a, RT2 b, RT3 q)
{
- typedef typename remove_cv<RT1>::type dummy;
- return ibetac_inv(a, b, q, static_cast<dummy*>(0), policies::policy<>());
+ typedef typename tools::promote_args<RT1, RT2, RT3>::type result_type;
+ return ibetac_inv(a, b, q, static_cast<result_type*>(0), policies::policy<>());
}
template <class RT1, class RT2, class RT3, class Policy>
inline typename tools::promote_args<RT1, RT2, RT3>::type
ibetac_inv(RT1 a, RT2 b, RT3 q, const Policy& pol)
{
- typedef typename remove_cv<RT1>::type dummy;
- return ibetac_inv(a, b, q, static_cast<dummy*>(0), pol);
+ typedef typename tools::promote_args<RT1, RT2, RT3>::type result_type;
+ return ibetac_inv(a, b, q, static_cast<result_type*>(0), pol);
}
} // namespace math
diff --git a/boost/math/special_functions/detail/igamma_inverse.hpp b/boost/math/special_functions/detail/igamma_inverse.hpp
index 53875ff83e..fd0189ca6d 100644
--- a/boost/math/special_functions/detail/igamma_inverse.hpp
+++ b/boost/math/special_functions/detail/igamma_inverse.hpp
@@ -281,11 +281,11 @@ T find_inverse_gamma(T a, T p, T q, const Policy& pol, bool* p_has_10_digits)
// DiDonato and Morris Eq 35:
T v = log(p) + boost::math::lgamma(ap1, pol);
z = exp((v + w) / a);
- s = boost::math::log1p(z / ap1 * (1 + z / ap2));
+ s = boost::math::log1p(z / ap1 * (1 + z / ap2), pol);
z = exp((v + z - s) / a);
- s = boost::math::log1p(z / ap1 * (1 + z / ap2));
+ s = boost::math::log1p(z / ap1 * (1 + z / ap2), pol);
z = exp((v + z - s) / a);
- s = boost::math::log1p(z / ap1 * (1 + z / ap2 * (1 + z / (a + 3))));
+ s = boost::math::log1p(z / ap1 * (1 + z / ap2 * (1 + z / (a + 3))), pol);
z = exp((v + z - s) / a);
BOOST_MATH_INSTRUMENT_VARIABLE(z);
}
@@ -341,7 +341,7 @@ struct gamma_p_inverse_func
// flag is set, then Q(x) - q and it's derivatives.
//
typedef typename policies::evaluation<T, Policy>::type value_type;
- typedef typename lanczos::lanczos<T, Policy>::type evaluation_type;
+ // typedef typename lanczos::lanczos<T, Policy>::type evaluation_type;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
@@ -378,7 +378,7 @@ struct gamma_p_inverse_func
f2 = -f2;
}
- return boost::math::make_tuple(f - p, f1, f2);
+ return boost::math::make_tuple(static_cast<T>(f - p), f1, f2);
}
private:
T a, p;
@@ -396,11 +396,11 @@ T gamma_p_inv_imp(T a, T p, const Policy& pol)
BOOST_MATH_INSTRUMENT_VARIABLE(p);
if(a <= 0)
- policies::raise_domain_error<T>(function, "Argument a in the incomplete gamma function inverse must be >= 0 (got a=%1%).", a, pol);
+ return policies::raise_domain_error<T>(function, "Argument a in the incomplete gamma function inverse must be >= 0 (got a=%1%).", a, pol);
if((p < 0) || (p > 1))
- policies::raise_domain_error<T>(function, "Probabilty must be in the range [0,1] in the incomplete gamma function inverse (got p=%1%).", p, pol);
+ return policies::raise_domain_error<T>(function, "Probabilty must be in the range [0,1] in the incomplete gamma function inverse (got p=%1%).", p, pol);
if(p == 1)
- return tools::max_value<T>();
+ return policies::raise_overflow_error<T>(function, 0, Policy());
if(p == 0)
return 0;
bool has_10_digits;
@@ -456,11 +456,11 @@ T gamma_q_inv_imp(T a, T q, const Policy& pol)
static const char* function = "boost::math::gamma_q_inv<%1%>(%1%, %1%)";
if(a <= 0)
- policies::raise_domain_error<T>(function, "Argument a in the incomplete gamma function inverse must be >= 0 (got a=%1%).", a, pol);
+ return policies::raise_domain_error<T>(function, "Argument a in the incomplete gamma function inverse must be >= 0 (got a=%1%).", a, pol);
if((q < 0) || (q > 1))
- policies::raise_domain_error<T>(function, "Probabilty must be in the range [0,1] in the incomplete gamma function inverse (got q=%1%).", q, pol);
+ return policies::raise_domain_error<T>(function, "Probabilty must be in the range [0,1] in the incomplete gamma function inverse (got q=%1%).", q, pol);
if(q == 0)
- return tools::max_value<T>();
+ return policies::raise_overflow_error<T>(function, 0, Policy());
if(q == 1)
return 0;
bool has_10_digits;
diff --git a/boost/math/special_functions/detail/lanczos_sse2.hpp b/boost/math/special_functions/detail/lanczos_sse2.hpp
index f8846bf376..edef3a0412 100644
--- a/boost/math/special_functions/detail/lanczos_sse2.hpp
+++ b/boost/math/special_functions/detail/lanczos_sse2.hpp
@@ -51,11 +51,11 @@ inline double lanczos13m53::lanczos_sum<double>(const double& x)
static_cast<double>(23531376880.41075968857200767445163675473L),
static_cast<double>(0u)
};
- register __m128d vx = _mm_load1_pd(&x);
- register __m128d sum_even = _mm_load_pd(coeff);
- register __m128d sum_odd = _mm_load_pd(coeff+2);
- register __m128d nc_odd, nc_even;
- register __m128d vx2 = _mm_mul_pd(vx, vx);
+ __m128d vx = _mm_load1_pd(&x);
+ __m128d sum_even = _mm_load_pd(coeff);
+ __m128d sum_odd = _mm_load_pd(coeff+2);
+ __m128d nc_odd, nc_even;
+ __m128d vx2 = _mm_mul_pd(vx, vx);
sum_even = _mm_mul_pd(sum_even, vx2);
nc_even = _mm_load_pd(coeff + 4);
@@ -136,11 +136,11 @@ inline double lanczos13m53::lanczos_sum_expG_scaled<double>(const double& x)
static_cast<double>(56906521.91347156388090791033559122686859L),
static_cast<double>(0u)
};
- register __m128d vx = _mm_load1_pd(&x);
- register __m128d sum_even = _mm_load_pd(coeff);
- register __m128d sum_odd = _mm_load_pd(coeff+2);
- register __m128d nc_odd, nc_even;
- register __m128d vx2 = _mm_mul_pd(vx, vx);
+ __m128d vx = _mm_load1_pd(&x);
+ __m128d sum_even = _mm_load_pd(coeff);
+ __m128d sum_odd = _mm_load_pd(coeff+2);
+ __m128d nc_odd, nc_even;
+ __m128d vx2 = _mm_mul_pd(vx, vx);
sum_even = _mm_mul_pd(sum_even, vx2);
nc_even = _mm_load_pd(coeff + 4);
diff --git a/boost/math/special_functions/detail/lgamma_small.hpp b/boost/math/special_functions/detail/lgamma_small.hpp
index ec28ed2adf..e65f8b7e98 100644
--- a/boost/math/special_functions/detail/lgamma_small.hpp
+++ b/boost/math/special_functions/detail/lgamma_small.hpp
@@ -87,7 +87,7 @@ T lgamma_small_imp(T z, T zm1, T zm2, const mpl::int_<64>&, const Policy& /* l *
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -0.324588649825948492091e-4))
};
static const T Q[] = {
- static_cast<T>(0.1e1),
+ static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.1e1)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.196202987197795200688e1)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.148019669424231326694e1)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.541391432071720958364e0)),
@@ -198,7 +198,7 @@ T lgamma_small_imp(T z, T zm1, T zm2, const mpl::int_<64>&, const Policy& /* l *
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.431171342679297331241e-3))
};
static const T Q[] = {
- static_cast<T>(0.1e1),
+ static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.1e1)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -0.150169356054485044494e1)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.846973248876495016101e0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -0.220095151814995745555e0)),
@@ -278,7 +278,7 @@ T lgamma_small_imp(T z, T zm1, T zm2, const mpl::int_<113>&, const Policy& /* l
BOOST_MATH_BIG_CONSTANT(T, 113, -0.70529798686542184668416911331718963364e-8)
};
static const T Q[] = {
- BOOST_MATH_BIG_CONSTANT(T, 113, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.5877485070422317542808137697939233685),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.8797959228352591788629602533153837126),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.8030885955284082026405495275461180977),
@@ -357,7 +357,7 @@ T lgamma_small_imp(T z, T zm1, T zm2, const mpl::int_<113>&, const Policy& /* l
BOOST_MATH_BIG_CONSTANT(T, 113, 0.13680157145361387405588201461036338274e-8)
};
static const T Q[] = {
- 1,
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 113, 4.9106336261005990534095838574132225599),
BOOST_MATH_BIG_CONSTANT(T, 113, 10.258804800866438510889341082793078432),
BOOST_MATH_BIG_CONSTANT(T, 113, 11.88588976846826108836629960537466889),
@@ -408,7 +408,7 @@ T lgamma_small_imp(T z, T zm1, T zm2, const mpl::int_<113>&, const Policy& /* l
BOOST_MATH_BIG_CONSTANT(T, 113, 0.8207548771933585614380644961342925976e-6)
};
static const T Q[] = {
- 1,
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 113, -2.9629552288944259229543137757200262073),
BOOST_MATH_BIG_CONSTANT(T, 113, 3.7118380799042118987185957298964772755),
BOOST_MATH_BIG_CONSTANT(T, 113, -2.5569815272165399297600586376727357187),
@@ -449,7 +449,7 @@ T lgamma_small_imp(T z, T zm1, T zm2, const mpl::int_<113>&, const Policy& /* l
BOOST_MATH_BIG_CONSTANT(T, 113, 0.13240510580220763969511741896361984162e-6)
};
static const T Q[] = {
- 1,
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 113, -2.4240003754444040525462170802796471996),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.4868383476933178722203278602342786002),
BOOST_MATH_BIG_CONSTANT(T, 113, -1.4047068395206343375520721509193698547),
diff --git a/boost/math/special_functions/detail/round_fwd.hpp b/boost/math/special_functions/detail/round_fwd.hpp
index 952259ae93..8c45a7d75a 100644
--- a/boost/math/special_functions/detail/round_fwd.hpp
+++ b/boost/math/special_functions/detail/round_fwd.hpp
@@ -9,6 +9,7 @@
#define BOOST_MATH_SPECIAL_ROUND_FWD_HPP
#include <boost/config.hpp>
+#include <boost/math/tools/promotion.hpp>
#ifdef _MSC_VER
#pragma once
@@ -20,9 +21,9 @@ namespace boost
{
template <class T, class Policy>
- T trunc(const T& v, const Policy& pol);
+ typename tools::promote_args<T>::type trunc(const T& v, const Policy& pol);
template <class T>
- T trunc(const T& v);
+ typename tools::promote_args<T>::type trunc(const T& v);
template <class T, class Policy>
int itrunc(const T& v, const Policy& pol);
template <class T>
@@ -38,9 +39,9 @@ namespace boost
boost::long_long_type lltrunc(const T& v);
#endif
template <class T, class Policy>
- T round(const T& v, const Policy& pol);
+ typename tools::promote_args<T>::type round(const T& v, const Policy& pol);
template <class T>
- T round(const T& v);
+ typename tools::promote_args<T>::type round(const T& v);
template <class T, class Policy>
int iround(const T& v, const Policy& pol);
template <class T>
@@ -76,5 +77,17 @@ namespace boost
}
}
+
+#undef BOOST_MATH_STD_USING
+#define BOOST_MATH_STD_USING BOOST_MATH_STD_USING_CORE\
+ using boost::math::round;\
+ using boost::math::iround;\
+ using boost::math::lround;\
+ using boost::math::trunc;\
+ using boost::math::itrunc;\
+ using boost::math::ltrunc;\
+ using boost::math::modf;
+
+
#endif // BOOST_MATH_SPECIAL_ROUND_FWD_HPP
diff --git a/boost/math/special_functions/detail/t_distribution_inv.hpp b/boost/math/special_functions/detail/t_distribution_inv.hpp
index 4e0d2d1b79..72f6f0c646 100644
--- a/boost/math/special_functions/detail/t_distribution_inv.hpp
+++ b/boost/math/special_functions/detail/t_distribution_inv.hpp
@@ -372,7 +372,13 @@ T inverse_students_t(T df, T u, T v, const Policy& pol, bool* pexact = 0)
else
{
calculate_real:
- if(df < 3)
+ if(df > 0x10000000)
+ {
+ result = -boost::math::erfc_inv(2 * u, pol) * constants::root_two<T>();
+ if((pexact) && (df >= 1e20))
+ *pexact = true;
+ }
+ else if(df < 3)
{
//
// Use a roughly linear scheme to choose between Shaw's
@@ -395,7 +401,7 @@ calculate_real:
// where we use Shaw's tail series.
// The crossover point is roughly exponential in -df:
//
- T crossover = ldexp(1.0f, iround(T(df / -0.654f), pol));
+ T crossover = ldexp(1.0f, iround(T(df / -0.654f), typename policies::normalise<Policy, policies::rounding_error<policies::ignore_error> >::type()));
if(u > crossover)
{
result = boost::math::detail::inverse_students_t_hill(df, u, pol);
@@ -410,15 +416,14 @@ calculate_real:
}
template <class T, class Policy>
-inline T find_ibeta_inv_from_t_dist(T a, T p, T q, T* py, const Policy& pol)
+inline T find_ibeta_inv_from_t_dist(T a, T p, T /*q*/, T* py, const Policy& pol)
{
- T u = (p > q) ? T(0.5f - q) / T(2) : T(p / 2);
- T v = 1 - u; // u < 0.5 so no cancellation error
+ T u = p / 2;
+ T v = 1 - u;
T df = a * 2;
T t = boost::math::detail::inverse_students_t(df, u, v, pol);
- T x = df / (df + t * t);
*py = t * t / (df + t * t);
- return x;
+ return df / (df + t * t);
}
template <class T, class Policy>
diff --git a/boost/math/special_functions/detail/unchecked_bernoulli.hpp b/boost/math/special_functions/detail/unchecked_bernoulli.hpp
new file mode 100644
index 0000000000..03c376678d
--- /dev/null
+++ b/boost/math/special_functions/detail/unchecked_bernoulli.hpp
@@ -0,0 +1,700 @@
+
+///////////////////////////////////////////////////////////////////////////////
+// Copyright 2013 Nikhar Agrawal
+// Copyright 2013 Christopher Kormanyos
+// Copyright 2013 John Maddock
+// Copyright 2013 Paul Bristow
+// Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MATH_UNCHECKED_BERNOULLI_HPP
+#define BOOST_MATH_UNCHECKED_BERNOULLI_HPP
+
+#include <limits>
+#include <cmath>
+#include <boost/math/policies/error_handling.hpp>
+#include <boost/math/constants/constants.hpp>
+#include <boost/math/special_functions/math_fwd.hpp>
+#include <boost/mpl/int.hpp>
+#include <boost/type_traits/is_convertible.hpp>
+
+namespace boost { namespace math {
+
+namespace detail {
+
+template <unsigned N>
+struct max_bernoulli_index
+{
+ BOOST_STATIC_CONSTANT(unsigned, value = 17);
+};
+
+template <>
+struct max_bernoulli_index<1>
+{
+ BOOST_STATIC_CONSTANT(unsigned, value = 32);
+};
+
+template <>
+struct max_bernoulli_index<2>
+{
+ BOOST_STATIC_CONSTANT(unsigned, value = 129);
+};
+
+template <>
+struct max_bernoulli_index<3>
+{
+ BOOST_STATIC_CONSTANT(unsigned, value = 1156);
+};
+
+template <>
+struct max_bernoulli_index<4>
+{
+ BOOST_STATIC_CONSTANT(unsigned, value = 11);
+};
+
+template <class T>
+struct bernoulli_imp_variant
+{
+ static const unsigned value =
+ (std::numeric_limits<T>::max_exponent == 128)
+ && (std::numeric_limits<T>::radix == 2)
+ && (std::numeric_limits<T>::digits <= std::numeric_limits<float>::digits)
+ && (boost::is_convertible<float, T>::value) ? 1 :
+ (
+ (std::numeric_limits<T>::max_exponent == 1024)
+ && (std::numeric_limits<T>::radix == 2)
+ && (std::numeric_limits<T>::digits <= std::numeric_limits<double>::digits)
+ && (boost::is_convertible<double, T>::value) ? 2 :
+ (
+ (std::numeric_limits<T>::max_exponent == 16384)
+ && (std::numeric_limits<T>::radix == 2)
+ && (std::numeric_limits<T>::digits <= std::numeric_limits<long double>::digits)
+ && (boost::is_convertible<long double, T>::value) ? 3 : (!is_convertible<boost::int64_t, T>::value ? 4 : 0)
+ )
+ );
+};
+
+} // namespace detail
+
+template <class T>
+struct max_bernoulli_b2n : public detail::max_bernoulli_index<detail::bernoulli_imp_variant<T>::value>{};
+
+namespace detail{
+
+template <class T>
+inline T unchecked_bernoulli_imp(std::size_t n, const mpl::int_<0>& )
+{
+ static const boost::array<boost::int64_t, 1 + max_bernoulli_b2n<T>::value> numerators =
+ {{
+ boost::int64_t( +1LL),
+ boost::int64_t( +1LL),
+ boost::int64_t( -1LL),
+ boost::int64_t( +1LL),
+ boost::int64_t( -1LL),
+ boost::int64_t( +5LL),
+ boost::int64_t( -691LL),
+ boost::int64_t( +7LL),
+ boost::int64_t( -3617LL),
+ boost::int64_t( +43867LL),
+ boost::int64_t( -174611LL),
+ boost::int64_t( +854513LL),
+ boost::int64_t( -236364091LL),
+ boost::int64_t( +8553103LL),
+ boost::int64_t( -23749461029LL),
+ boost::int64_t(+8615841276005LL),
+ boost::int64_t(-7709321041217LL),
+ boost::int64_t(+2577687858367LL)
+ }};
+
+ static const boost::array<boost::int64_t, 1 + max_bernoulli_b2n<T>::value> denominators =
+ {{
+ boost::int64_t( 1LL),
+ boost::int64_t( 6LL),
+ boost::int64_t( 30LL),
+ boost::int64_t( 42LL),
+ boost::int64_t( 30LL),
+ boost::int64_t( 66LL),
+ boost::int64_t( 2730LL),
+ boost::int64_t( 6LL),
+ boost::int64_t( 510LL),
+ boost::int64_t( 798LL),
+ boost::int64_t( 330LL),
+ boost::int64_t( 138LL),
+ boost::int64_t( 2730LL),
+ boost::int64_t( 6LL),
+ boost::int64_t( 870LL),
+ boost::int64_t( 14322LL),
+ boost::int64_t( 510LL),
+ boost::int64_t( 6LL)
+ }};
+ return T(numerators[n]) / denominators[n];
+}
+
+template <class T>
+inline T unchecked_bernoulli_imp(std::size_t n, const mpl::int_<1>& )
+{
+ static const boost::array<float, 1 + max_bernoulli_b2n<T>::value> bernoulli_data =
+ {{
+ +1.00000000000000000000000000000000000000000F,
+ +0.166666666666666666666666666666666666666667F,
+ -0.0333333333333333333333333333333333333333333F,
+ +0.0238095238095238095238095238095238095238095F,
+ -0.0333333333333333333333333333333333333333333F,
+ +0.0757575757575757575757575757575757575757576F,
+ -0.253113553113553113553113553113553113553114F,
+ +1.16666666666666666666666666666666666666667F,
+ -7.09215686274509803921568627450980392156863F,
+ +54.9711779448621553884711779448621553884712F,
+ -529.124242424242424242424242424242424242424F,
+ +6192.12318840579710144927536231884057971014F,
+ -86580.2531135531135531135531135531135531136F,
+ +1.42551716666666666666666666666666666666667e6F,
+ -2.72982310678160919540229885057471264367816e7F,
+ +6.01580873900642368384303868174835916771401e8F,
+ -1.51163157670921568627450980392156862745098e10F,
+ +4.29614643061166666666666666666666666666667e11F,
+ -1.37116552050883327721590879485616327721591e13F,
+ +4.88332318973593166666666666666666666666667e14F,
+ -1.92965793419400681486326681448632668144863e16F,
+ +8.41693047573682615000553709856035437430786e17F,
+ -4.03380718540594554130768115942028985507246e19F,
+ +2.11507486380819916056014539007092198581560e21F,
+ -1.20866265222965259346027311937082525317819e23F,
+ +7.50086674607696436685572007575757575757576e24F,
+ -5.03877810148106891413789303052201257861635e26F,
+ +3.65287764848181233351104308429711779448622e28F,
+ -2.84987693024508822262691464329106781609195e30F,
+ +2.38654274996836276446459819192192149717514e32F,
+ -2.13999492572253336658107447651910973926742e34F,
+ +2.05009757234780975699217330956723102516667e36F,
+ -2.09380059113463784090951852900279701847092e38F,
+ }};
+
+ return bernoulli_data[n];
+}
+
+
+template <class T>
+inline T unchecked_bernoulli_imp(std::size_t n, const mpl::int_<2>& )
+{
+ static const boost::array<double, 1 + max_bernoulli_b2n<T>::value> bernoulli_data =
+ {{
+ +1.00000000000000000000000000000000000000000,
+ +0.166666666666666666666666666666666666666667,
+ -0.0333333333333333333333333333333333333333333,
+ +0.0238095238095238095238095238095238095238095,
+ -0.0333333333333333333333333333333333333333333,
+ +0.0757575757575757575757575757575757575757576,
+ -0.253113553113553113553113553113553113553114,
+ +1.16666666666666666666666666666666666666667,
+ -7.09215686274509803921568627450980392156863,
+ +54.9711779448621553884711779448621553884712,
+ -529.124242424242424242424242424242424242424,
+ +6192.12318840579710144927536231884057971014,
+ -86580.2531135531135531135531135531135531136,
+ +1.42551716666666666666666666666666666666667e6,
+ -2.72982310678160919540229885057471264367816e7,
+ +6.01580873900642368384303868174835916771401e8,
+ -1.51163157670921568627450980392156862745098e10,
+ +4.29614643061166666666666666666666666666667e11,
+ -1.37116552050883327721590879485616327721591e13,
+ +4.88332318973593166666666666666666666666667e14,
+ -1.92965793419400681486326681448632668144863e16,
+ +8.41693047573682615000553709856035437430786e17,
+ -4.03380718540594554130768115942028985507246e19,
+ +2.11507486380819916056014539007092198581560e21,
+ -1.20866265222965259346027311937082525317819e23,
+ +7.50086674607696436685572007575757575757576e24,
+ -5.03877810148106891413789303052201257861635e26,
+ +3.65287764848181233351104308429711779448622e28,
+ -2.84987693024508822262691464329106781609195e30,
+ +2.38654274996836276446459819192192149717514e32,
+ -2.13999492572253336658107447651910973926742e34,
+ +2.05009757234780975699217330956723102516667e36,
+ -2.09380059113463784090951852900279701847092e38,
+ +2.27526964884635155596492603527692645814700e40,
+ -2.62577102862395760473030497361582020814490e42,
+ +3.21250821027180325182047923042649852435219e44,
+ -4.15982781667947109139170744952623589366896e46,
+ +5.69206954820352800238834562191210586444805e48,
+ -8.21836294197845756922906534686173330145509e50,
+ +1.25029043271669930167323398297028955241772e53,
+ -2.00155832332483702749253291988132987687242e55,
+ +3.36749829153643742333966769033387530162196e57,
+ -5.94709705031354477186604968440515408405791e59,
+ +1.10119103236279775595641307904376916046305e62,
+ -2.13552595452535011886583850190410656789733e64,
+ +4.33288969866411924196166130593792062184514e66,
+ -9.18855282416693282262005552155018971389604e68,
+ +2.03468967763290744934550279902200200659751e71,
+ -4.70038339580357310785752555350060606545967e73,
+ +1.13180434454842492706751862577339342678904e76,
+ -2.83822495706937069592641563364817647382847e78,
+ +7.40642489796788506297508271409209841768797e80,
+ -2.00964548027566044834656196727153631868673e83,
+ +5.66571700508059414457193460305193569614195e85,
+ -1.65845111541362169158237133743199123014950e88,
+ +5.03688599504923774192894219151801548124424e90,
+ -1.58614682376581863693634015729664387827410e93,
+ +5.17567436175456269840732406825071225612408e95,
+ -1.74889218402171173396900258776181591451415e98,
+ +6.11605199949521852558245252642641677807677e100,
+ -2.21227769127078349422883234567129324455732e103,
+ +8.27227767987709698542210624599845957312047e105,
+ -3.19589251114157095835916343691808148735263e108,
+ +1.27500822233877929823100243029266798669572e111,
+ -5.25009230867741338994028246245651754469199e113,
+ +2.23018178942416252098692981988387281437383e116,
+ -9.76845219309552044386335133989802393011669e118,
+ +4.40983619784529542722726228748131691918758e121,
+ -2.05085708864640888397293377275830154864566e124,
+ +9.82144332797912771075729696020975210414919e126,
+ -4.84126007982088805087891967099634127611305e129,
+ +2.45530888014809826097834674040886903996737e132,
+ -1.28069268040847475487825132786017857218118e135,
+ +6.86761671046685811921018885984644004360924e137,
+ -3.78464685819691046949789954163795568144895e140,
+ +2.14261012506652915508713231351482720966602e143,
+ -1.24567271371836950070196429616376072194583e146,
+ +7.43457875510001525436796683940520613117807e148,
+ -4.55357953046417048940633332233212748767721e151,
+ +2.86121128168588683453638472510172325229190e154,
+ -1.84377235520338697276882026536287854875414e157,
+ +1.21811545362210466995013165065995213558174e160,
+ -8.24821871853141215484818457296893447301419e162,
+ +5.72258779378329433296516498142978615918685e165,
+ -4.06685305250591047267679693831158655602196e168,
+ +2.95960920646420500628752695815851870426379e171,
+ -2.20495225651894575090311752273445984836379e174,
+ +1.68125970728895998058311525151360665754464e177,
+ -1.31167362135569576486452806355817153004431e180,
+ +1.04678940094780380821832853929823089643829e183,
+ -8.54328935788337077185982546299082774593270e185,
+ +7.12878213224865423522884066771438224721245e188,
+ -6.08029314555358993000847118686477458461988e191,
+ +5.29967764248499239300942910043247266228490e194,
+ -4.71942591687458626443646229013379911103761e197,
+ +4.29284137914029810894168296541074669045521e200,
+ -3.98767449682322074434477655542938795106651e203,
+ +3.78197804193588827138944181161393327898220e206,
+ -3.66142336836811912436858082151197348755196e209,
+ +3.61760902723728623488554609298914089477541e212,
+ -3.64707726451913543621383088655499449048682e215,
+ +3.75087554364544090983452410104814189306842e218,
+ -3.93458672964390282694891288533713429355657e221,
+ +4.20882111481900820046571171111494898242731e224,
+ -4.59022962206179186559802940573325591059371e227,
+ +5.10317257726295759279198185106496768539760e230,
+ -5.78227623036569554015377271242917142512200e233,
+ +6.67624821678358810322637794412809363451080e236,
+ -7.85353076444504163225916259639312444428230e239,
+ +9.41068940670587255245443288258762485293948e242,
+ -1.14849338734651839938498599206805592548354e246,
+ +1.42729587428487856771416320087122499897180e249,
+ -1.80595595869093090142285728117654560926719e252,
+ +2.32615353076608052161297985184708876161736e255,
+ -3.04957517154995947681942819261542593785327e258,
+ +4.06858060764339734424012124124937318633684e261,
+ -5.52310313219743616252320044093186392324280e264,
+ +7.62772793964343924869949690204961215533859e267,
+ -1.07155711196978863132793524001065396932667e271,
+ +1.53102008959691884453440916153355334355847e274,
+ -2.22448916821798346676602348865048510824835e277,
+ +3.28626791906901391668189736436895275365183e280,
+ -4.93559289559603449020711938191575963496999e283,
+ +7.53495712008325067212266049779283956727824e286,
+ -1.16914851545841777278088924731655041783900e290,
+ +1.84352614678389394126646201597702232396492e293,
+ -2.95368261729680829728014917350525183485207e296,
+ +4.80793212775015697668878704043264072227967e299,
+ -7.95021250458852528538243631671158693036798e302,
+ +1.33527841873546338750122832017820518292039e306
+ }};
+
+ return bernoulli_data[n];
+}
+
+template <class T>
+inline T unchecked_bernoulli_imp(std::size_t n, const mpl::int_<3>& )
+{
+ static const boost::array<long double, 1 + max_bernoulli_b2n<T>::value> bernoulli_data =
+ {{
+ +1.00000000000000000000000000000000000000000L,
+ +0.166666666666666666666666666666666666666667L,
+ -0.0333333333333333333333333333333333333333333L,
+ +0.0238095238095238095238095238095238095238095L,
+ -0.0333333333333333333333333333333333333333333L,
+ +0.0757575757575757575757575757575757575757576L,
+ -0.253113553113553113553113553113553113553114L,
+ +1.16666666666666666666666666666666666666667L,
+ -7.09215686274509803921568627450980392156863L,
+ +54.9711779448621553884711779448621553884712L,
+ -529.124242424242424242424242424242424242424L,
+ +6192.12318840579710144927536231884057971014L,
+ -86580.2531135531135531135531135531135531136L,
+ +1.42551716666666666666666666666666666666667E6L,
+ -2.72982310678160919540229885057471264367816E7L,
+ +6.01580873900642368384303868174835916771401E8L,
+ -1.51163157670921568627450980392156862745098E10L,
+ +4.29614643061166666666666666666666666666667E11L,
+ -1.37116552050883327721590879485616327721591E13L,
+ +4.88332318973593166666666666666666666666667E14L,
+ -1.92965793419400681486326681448632668144863E16L,
+ +8.41693047573682615000553709856035437430786E17L,
+ -4.03380718540594554130768115942028985507246E19L,
+ +2.11507486380819916056014539007092198581560E21L,
+ -1.20866265222965259346027311937082525317819E23L,
+ +7.50086674607696436685572007575757575757576E24L,
+ -5.03877810148106891413789303052201257861635E26L,
+ +3.65287764848181233351104308429711779448622E28L,
+ -2.84987693024508822262691464329106781609195E30L,
+ +2.38654274996836276446459819192192149717514E32L,
+ -2.13999492572253336658107447651910973926742E34L,
+ +2.05009757234780975699217330956723102516667E36L,
+ -2.09380059113463784090951852900279701847092E38L,
+ +2.27526964884635155596492603527692645814700E40L,
+ -2.62577102862395760473030497361582020814490E42L,
+ +3.21250821027180325182047923042649852435219E44L,
+ -4.15982781667947109139170744952623589366896E46L,
+ +5.69206954820352800238834562191210586444805E48L,
+ -8.21836294197845756922906534686173330145509E50L,
+ +1.25029043271669930167323398297028955241772E53L,
+ -2.00155832332483702749253291988132987687242E55L,
+ +3.36749829153643742333966769033387530162196E57L,
+ -5.94709705031354477186604968440515408405791E59L,
+ +1.10119103236279775595641307904376916046305E62L,
+ -2.13552595452535011886583850190410656789733E64L,
+ +4.33288969866411924196166130593792062184514E66L,
+ -9.18855282416693282262005552155018971389604E68L,
+ +2.03468967763290744934550279902200200659751E71L,
+ -4.70038339580357310785752555350060606545967E73L,
+ +1.13180434454842492706751862577339342678904E76L,
+ -2.83822495706937069592641563364817647382847E78L,
+ +7.40642489796788506297508271409209841768797E80L,
+ -2.00964548027566044834656196727153631868673E83L,
+ +5.66571700508059414457193460305193569614195E85L,
+ -1.65845111541362169158237133743199123014950E88L,
+ +5.03688599504923774192894219151801548124424E90L,
+ -1.58614682376581863693634015729664387827410E93L,
+ +5.17567436175456269840732406825071225612408E95L,
+ -1.74889218402171173396900258776181591451415E98L,
+ +6.11605199949521852558245252642641677807677E100L,
+ -2.21227769127078349422883234567129324455732E103L,
+ +8.27227767987709698542210624599845957312047E105L,
+ -3.19589251114157095835916343691808148735263E108L,
+ +1.27500822233877929823100243029266798669572E111L,
+ -5.25009230867741338994028246245651754469199E113L,
+ +2.23018178942416252098692981988387281437383E116L,
+ -9.76845219309552044386335133989802393011669E118L,
+ +4.40983619784529542722726228748131691918758E121L,
+ -2.05085708864640888397293377275830154864566E124L,
+ +9.82144332797912771075729696020975210414919E126L,
+ -4.84126007982088805087891967099634127611305E129L,
+ +2.45530888014809826097834674040886903996737E132L,
+ -1.28069268040847475487825132786017857218118E135L,
+ +6.86761671046685811921018885984644004360924E137L,
+ -3.78464685819691046949789954163795568144895E140L,
+ +2.14261012506652915508713231351482720966602E143L,
+ -1.24567271371836950070196429616376072194583E146L,
+ +7.43457875510001525436796683940520613117807E148L,
+ -4.55357953046417048940633332233212748767721E151L,
+ +2.86121128168588683453638472510172325229190E154L,
+ -1.84377235520338697276882026536287854875414E157L,
+ +1.21811545362210466995013165065995213558174E160L,
+ -8.24821871853141215484818457296893447301419E162L,
+ +5.72258779378329433296516498142978615918685E165L,
+ -4.06685305250591047267679693831158655602196E168L,
+ +2.95960920646420500628752695815851870426379E171L,
+ -2.20495225651894575090311752273445984836379E174L,
+ +1.68125970728895998058311525151360665754464E177L,
+ -1.31167362135569576486452806355817153004431E180L,
+ +1.04678940094780380821832853929823089643829E183L,
+ -8.54328935788337077185982546299082774593270E185L,
+ +7.12878213224865423522884066771438224721245E188L,
+ -6.08029314555358993000847118686477458461988E191L,
+ +5.29967764248499239300942910043247266228490E194L,
+ -4.71942591687458626443646229013379911103761E197L,
+ +4.29284137914029810894168296541074669045521E200L,
+ -3.98767449682322074434477655542938795106651E203L,
+ +3.78197804193588827138944181161393327898220E206L,
+ -3.66142336836811912436858082151197348755196E209L,
+ +3.61760902723728623488554609298914089477541E212L,
+ -3.64707726451913543621383088655499449048682E215L,
+ +3.75087554364544090983452410104814189306842E218L,
+ -3.93458672964390282694891288533713429355657E221L,
+ +4.20882111481900820046571171111494898242731E224L,
+ -4.59022962206179186559802940573325591059371E227L,
+ +5.10317257726295759279198185106496768539760E230L,
+ -5.78227623036569554015377271242917142512200E233L,
+ +6.67624821678358810322637794412809363451080E236L,
+ -7.85353076444504163225916259639312444428230E239L,
+ +9.41068940670587255245443288258762485293948E242L,
+ -1.14849338734651839938498599206805592548354E246L,
+ +1.42729587428487856771416320087122499897180E249L,
+ -1.80595595869093090142285728117654560926719E252L,
+ +2.32615353076608052161297985184708876161736E255L,
+ -3.04957517154995947681942819261542593785327E258L,
+ +4.06858060764339734424012124124937318633684E261L,
+ -5.52310313219743616252320044093186392324280E264L,
+ +7.62772793964343924869949690204961215533859E267L,
+ -1.07155711196978863132793524001065396932667E271L,
+ +1.53102008959691884453440916153355334355847E274L,
+ -2.22448916821798346676602348865048510824835E277L,
+ +3.28626791906901391668189736436895275365183E280L,
+ -4.93559289559603449020711938191575963496999E283L,
+ +7.53495712008325067212266049779283956727824E286L,
+ -1.16914851545841777278088924731655041783900E290L,
+ +1.84352614678389394126646201597702232396492E293L,
+ -2.95368261729680829728014917350525183485207E296L,
+ +4.80793212775015697668878704043264072227967E299L,
+ -7.95021250458852528538243631671158693036798E302L,
+ +1.33527841873546338750122832017820518292039E306L,
+#if LDBL_MAX_EXP == 16384
+ // Entries 260 - 600 http://www.wolframalpha.com/input/?i=TABLE[N[Bernoulli[i]%2C40]%2C+{i%2C258%2C600%2C2}]
+ -2.277640649601959593875058983506938037019e309L,
+ 3.945184036046326234163525556422667595884e312L,
+ -6.938525772130602106071724989641405550473e315L,
+ 1.238896367577564823729057820219210929986e319L,
+ -2.245542599169309759499987966025604480745e322L,
+ 4.131213176073842359732511639489669404266e325L,
+ -7.713581346815269584960928069762882771369e328L,
+ 1.461536066837669600638613788471335541313e332L,
+ -2.809904606225532896862935642992712059631e335L,
+ 5.480957121318876639512096994413992284327e338L,
+ -1.084573284087686110518125291186079616320e342L,
+ 2.176980775647663539729165173863716459962e345L,
+ -4.431998786117553751947439433256752608068e348L,
+ 9.150625657715535047417756278073770096073e351L,
+ -1.915867353003157351316577579148683133613e355L,
+ 4.067256303542212258698836003682016040629e358L,
+ -8.754223791037736616228150209910348734629e361L,
+ 1.910173688735533667244373747124109379826e365L,
+ -4.225001320265091714631115064713174404607e368L,
+ 9.471959352547827678466770796787503034505e371L,
+ -2.152149973279986829719817376756088198573e375L,
+ 4.955485775334221051344839716507812871361e378L,
+ -1.156225941759134696630956889716381968142e382L,
+ 2.733406597646137698610991926705098514017e385L,
+ -6.546868135325176947099912523279938546333e388L,
+ 1.588524912441221472814692121069821695547e392L,
+ -3.904354800861715180218598151050191841308e395L,
+ 9.719938686092045781827273411668132975319e398L,
+ -2.450763621049522051234479737511375679283e402L,
+ 6.257892098396815305085674126334317095277e405L,
+ -1.618113552083806592527989531636955084420e409L,
+ 4.236528795217618357348618613216833722648e412L,
+ -1.123047068199051008086174989124136878992e416L,
+ 3.013971787525654770217283559392286666886e419L,
+ -8.188437573221553030375681429202969070420e422L,
+ 2.251910591336716809153958146725775718707e426L,
+ -6.268411292043789823075314151509139413399e429L,
+ 1.765990845202322642693572112511312471527e433L,
+ -5.035154436231331651259071296731160882240e436L,
+ 1.452779356460483245253765356664402207266e440L,
+ -4.241490890130137339052414960684151515166e443L,
+ 1.252966001692427774088293833338841893293e447L,
+ -3.744830047478272947978103227876747240343e450L,
+ 1.132315806695710930595876001089232216024e454L,
+ -3.463510845942701805991786197773934662578e457L,
+ 1.071643382649675572086865465873916611537e461L,
+ -3.353824475439933688957233489984711465335e464L,
+ 1.061594257145875875963152734129803268488e468L,
+ -3.398420969215528955528654193586189805265e471L,
+ 1.100192502000434096206138068020551065890e475L,
+ -3.601686379213993374332690210094863486472e478L,
+ 1.192235170430164900533187239994513019475e482L,
+ -3.990342751779668381699052942504119409180e485L,
+ 1.350281800938769780891258894167663309221e489L,
+ -4.619325443466054312873093650888507562249e492L,
+ 1.597522243968586548227514639959727696694e496L,
+ -5.584753729092155108530929002119620487652e499L,
+ 1.973443623104646193229794524759543752089e503L,
+ -7.048295441989615807045620880311201930244e506L,
+ 2.544236702499719094591873151590280263560e510L,
+ -9.281551595258615205927443367289948150345e513L,
+ 3.421757163154453657766296828520235351572e517L,
+ -1.274733639384538364282697627345068947433e521L,
+ 4.798524805311016034711205886780460173566e524L,
+ -1.825116948422858388787806917284878870034e528L,
+ 7.013667442807288452441777981425055613982e531L,
+ -2.723003862685989740898815670978399383114e535L,
+ 1.068014853917260290630122222858884658850e539L,
+ -4.231650952273697842269381683768681118533e542L,
+ 1.693650052202594386658903598564772900388e546L,
+ -6.846944855806453360616258582310883597678e549L,
+ 2.795809132238082267120232174243715559601e553L,
+ -1.153012972808983269106716828311318981951e557L,
+ 4.802368854268746357511997492039592697149e560L,
+ -2.019995255271910836389761734035403905781e564L,
+ 8.580207235032617856059250643095019760968e567L,
+ -3.680247942263468164408192134916355198549e571L,
+ 1.593924457586765331397457407661306895942e575L,
+ -6.970267175232643679233530367569943057501e578L,
+ 3.077528087427698518703282907890556154309e582L,
+ -1.371846760052887888926055417297342106614e586L,
+ 6.173627360829553396851763207025505289166e589L,
+ -2.804703130495506384463249394043486916669e593L,
+ 1.286250900087150126167490951216207186092e597L,
+ -5.954394420063617872366818601092036543220e600L,
+ 2.782297785278756426177542270854984091406e604L,
+ -1.312214674935307746141207680066262384215e608L,
+ 6.246299145383554153167974732783934504370e611L,
+ -3.000812007679574430883792565577444226490e615L,
+ 1.454904877136007844493861746476079537075e619L,
+ -7.118558521873800304612781121044077357278e622L,
+ 3.514739820897817389472822276832677887997e626L,
+ -1.751137068816377401163011262831890828437e630L,
+ 8.803498091818800678575314081978951179602e633L,
+ -4.465612911700593572269200981612564161010e637L,
+ 2.285494565287530681465757798517033542888e641L,
+ -1.180145168917737098025683613598595411329e645L,
+ 6.147941849198393232663105284575149616925e648L,
+ -3.231069156963603593233679426198974663352e652L,
+ 1.713042725635435041806895849197608270935e656L,
+ -9.161761363270648920537613435771882898051e659L,
+ 4.942675965960539112005679080810117766825e663L,
+ -2.689684712697383518131267222872386600031e667L,
+ 1.476320014229917759615308193449511534656e671L,
+ -8.173037740864781506597184122049453514594e674L,
+ 4.563462313190521363235182420178784459580e678L,
+ -2.569790015236158475703055501886439298708e682L,
+ 1.459410219452119981958355737832022375085e686L,
+ -8.358304882556983795372406183642486436653e689L,
+ 4.827305091483557818593092377664570208355e693L,
+ -2.811394311081493166793414157061950132403e697L,
+ 1.651026863340675349245561261339568827739e701L,
+ -9.776578579336866764167878646459810047899e704L,
+ 5.837207965197521880181236529616560780535e708L,
+ -3.513938957938032127105389702846371181520e712L,
+ 2.132747371360190507595748444536911078788e716L,
+ -1.305047363239192640729466563372665311602e720L,
+ 8.050825342678337497636292798039996484780e723L,
+ -5.006884161223862543665524155681082112689e727L,
+ 3.139016066011452177570812014513491361235e731L,
+ -1.983829535212711378291469356666001365873e735L,
+ 1.263822427649676371257598052486237628698e739L,
+ -8.115678659900522918802121684491754629503e742L,
+ 5.252995164972075271667364371449050412435e746L,
+ -3.427038125662404660056511738625477058135e750L,
+ 2.253446011834352733279946306835940729858e754L,
+ -1.493407341897034717876962786798831719683e758L,
+ 9.974681322653365118752729509398728354442e761L,
+ -6.714230142773850863927710112350816379426e765L,
+ 4.554668668931723346600337564274944733530e769L,
+ -3.113635386023220127834102980385275379533e773L,
+ 2.144945411287666204679363498162954050208e777L,
+ -1.488982121181387164932397544378555256016e781L,
+ 1.041537218854627455352298173588983048748e785L,
+ -7.341073881786613676177562822942175683993e788L,
+ 5.213524272587199574980117351016322518428e792L,
+ -3.730592531776514409283897139216167197989e796L,
+ 2.689592876341877079083449497724049500175e800L,
+ -1.953643788231947582529884602972233135002e804L,
+ 1.429691073080500563348668321308878246277e808L,
+ -1.054059177095488639836063073070536825675e812L,
+ 7.828919160938693948399336431565350676613e815L,
+ -5.857884457184396382550955498026762014753e819L,
+ 4.415401588264172474136969345712659422380e823L,
+ -3.352573884181287635796498822858109969161e827L,
+ 2.564210385719224000156548240934108974447e831L,
+ -1.975534392116037602837941409848663077528e835L,
+ 1.533062123975940045180943006948008486466e839L,
+ -1.198306160488763291730059994812781226903e843L,
+ 9.434034267770711698676321369174735725321e846L,
+ -7.480619200038505368468483892246806488879e850L,
+ 5.974161898439971564124576801455052907638e854L,
+ -4.805125663714699771668630995361572639386e858L,
+ 3.892332138028039952403812726744593073776e862L,
+ -3.175276505779699340738548328810180869575e866L,
+ 2.608608681939322393581069188271626122519e870L,
+ -2.158148554392732439392868052394994052628e874L,
+ 1.797993483301448477700600221980862686033e878L,
+ -1.508407575089108597171576068862286462909e882L,
+ 1.274273406242459482708930389008701147244e886L,
+ -1.083950475353171986748233157909397370193e890L,
+ 9.284292630726328432038470356821265395331e893L,
+ -8.007012115449516364480417355063446317414e897L,
+ 6.952871948429568933888979915833266241471e901L,
+ -6.078828929473797621198666799700739891205e905L,
+ 5.350908089710964244671334224708057812633e909L,
+ -4.742168072503284973969982758434401589090e913L,
+ 4.231149239401967697257534662010605751136e917L,
+ -3.800684612827828851942743291026898158947e921L,
+ 3.436984796314246158361599955909956583986e925L,
+ -3.128930718993658356398482705317381808301e929L,
+ //
+ // 602-1300: http://www.wolframalpha.com/input/?i=TABLE[N[Bernoulli[i]%2C40]%2C+{i%2C602%2C1300%2C2}]
+ 2.867524740577223817164663595437919813239e933L, -2.645462974939090580963101220449509725942e937L, 2.456800827789169780295419018499543141869e941L, -2.296690549725790064673528302231294870532e945L, 2.161174697699793265715182091764676666457e949L, -2.047023224586087259305754002882269123194e953L, 1.951604806042481282712736234132803700277e957L, -1.872785206668284042110390583158639495143e961L, 1.808847160923282257302788929692654262867e965L, -1.758427529634609613399327744595257497188e969L, 1.720468488019528147087036246754294757647e973L, -1.694180279355332648057740852839804839425e977L, 1.679013685251183870616469618951463869496e981L, -1.674640861433092946269144173974414945664e985L, 1.680943600147858322148767806987527412112e989L, -1.698008433134805056489370119323402510305e993L, 1.726128304411348354183882648263448448633e997L, -1.765810838736918108045764015629875016219e1001L, 1.817793526882665071123822455897912718293e1005L, -1.883066459765807128944897377914669600374e1009L, 1.962903588035940537938222992228124233567e1013L, -2.058903881920696086033171142046100185783e1017L, 2.173044241735786946064676598703393618281e1021L, -2.307746591425236218893160658331303115253e1025L, 2.465962312241418731528973526597433097256e1029L, -2.651278087802503406316742676403301581549e1033L, 2.868048395658440423778896607880692085708e1037L, -3.121561373094393453726645989392054731637e1041L, 3.418246710091027042099932753084126095820e1045L, -3.765936717592482928796920675282930034018e1049L, 4.174194967165213973474293718362757753877e1053L, -4.654731142471753017867105249805137855862e1057L, 5.221926310090434518253178454907900079787e1061L, -5.893500145664015254409680930288710794031e1065L, 6.691361332576333738130720616841706994101e1069L, -7.642695184575063524608775697714741180954e1073L, 8.781359617440634128952082759434723165820e1077L, -1.014968338800868135594698909567734048618e1082L, 1.180079105471061498849752479044520598414e1086L, -1.380162016721660241308046692646452732446e1090L, 1.623685158291375662775444238282343536948e1094L, -1.921404880943289359290531906131400049399e1098L, 2.287040419533950152851434188305457266969e1102L, -2.738162880206032093123060939173765335255e1106L, 3.297371307848643161532227459901386725801e1110L, -3.993854689967542662299211323085023297602e1114L, 4.865474805885735467044047308902313673643e1118L, -5.961554732739027308247618738765152679497e1122L, 7.346627151757492821447573639763873833441e1126L, -9.105493288459908620636712748727395637965e1130L, 1.135007867626164861991621396462821975167e1135L, -1.422876214067403769204874786137232627418e1139L, 1.793912271573925309173135913914667878908e1143L, -2.274542916104231188526120123855259514144e1147L, 2.900273688809987694128857655036783261991e1151L, -3.719022795563122339874875448447744493398e1155L, 4.795753420982845153626611023078973364321e1159L, -6.218937220186281310109009529226561379773e1163L, 8.109611247999584815668395828940708619394e1167L, -1.063412316303440216539797215354141158589e1172L, 1.402214363674117662460496032135704328989e1176L, -1.859223235464558752766840772026058694872e1180L, 2.478828203789903637835992128856742276028e1184L, -3.323169416193176673655321536761413885767e1188L, 4.479640207312477092938541546776915956580e1192L, -6.071721672924085739424644485636889518799e1196L, 8.274698015123579607850404326757887762270e1200L, -1.133855131459773018024052539697784205966e1205L, 1.562146222050424344025824344480153248984e1209L, -2.163904570724750459592352173471446831752e1213L, 3.013703210722669908901286635073603018696e1217L, -4.219903244242308803914269531001720703294e1221L, 5.940703220571043642186808904696174833998e1225L, -8.408147464216029127243257448169774333631e1229L, 1.196419999747411909144144315499654470715e1234L, -1.711518922741148710381740436694440587059e1238L, 2.461434539630850545757453894977350505251e1242L, -3.558748530932574002484841810677232366801e1246L, 5.172525606281917297657859608800373729529e1250L, -7.557850217376323621984784308774476917753e1254L, 1.110141075986004209769735296234549704181e1259L, -1.639216556732622481406083885926912451281e1263L, 2.433138328152562628385514545400044125983e1267L, -3.630476645219033020888837165221286413171e1271L, 5.445289518636306992942604775585977779418e1275L, -8.209806424989072060381590985042272020067e1279L, 1.244209849774134691374848390346442737613e1284L, -1.895384488692308848372754844910263931874e1288L, 2.902272596647764894203369746806169285113e1292L, -4.466944174025026625137032739317650862593e1296L, 6.910485739507636504313238347702354354916e1300L, -1.074550085668784170644854815272144687769e1305L, 1.679419258904938802199084915274175753529e1309L, -2.638155207645646220849795321076977230763e1313L, 4.165284786632654168563096850610185378233e1317L, -6.609774274649031371770290191295685774584e1321L, 1.054194100570841329575393359295845860860e1326L, -1.689822316104196916970708778265725885275e1330L, 2.722340957904912685605914893019783431164e1334L, -4.407776313964403233676810178851005163725e1338L, 7.172436210641903635864868181569129834361e1342L, -1.172947440100495955246356688225986736990e1347L, 1.927745674072824377954824961348211728006e1351L, -3.184013467435655962214317208087993711563e1355L, 5.285045125125832341263897233405196808096e1359L, -8.815883582819232027207118521581424783107e1363L, 1.477818368424505276711779171224799759099e1368L, -2.489482576496570159333357550363134602876e1372L, 4.214292881345076419678976329218843808204e1376L, -7.169068531615459070909644981451297906220e1380L, 1.225513133750594558180516896275774441895e1385L, -2.105160827387119480607950260289853896637e1389L, 3.633787605672960549893307203363402915249e1393L, -6.302830804027849515239463308430185990705e1397L, 1.098521433860299633481449685364914115468e1402L, -1.923858597401607622723144320370279518600e1406L, 3.385512828549942051667348582951554570164e1410L, -5.986286250836771248147827011780631183980e1414L, 1.063572794668186370728928272374836554300e1419L, -1.898666684876492795233907174493757572290e1423L, 3.405627002840442789235393111726609930533e1427L, -6.137724140284450036591063946055819333244e1431L, 1.111411024660941507986132154479364267486e1436L, -2.022060876221034821890406900217875915949e1440L, 3.696248025817144690840539132103538834108e1444L, -6.788448439024998306316860676030442691610e1448L, 1.252615233049059554031883468823648511657e1453L, -2.322190433141265975888955985950824418729e1457L, 4.325200102353909846882217732999001735342e1461L, -8.093531903011880118699218269369570178812e1465L, 1.521558881878323790120983450270946857209e1470L, -2.873780311010933807686415826253380907421e1474L, 5.452903697278823304173192839252276211670e1478L, -1.039457922537509500320638240809547113575e1483L, 1.990610112724715126895008793014214505760e1487L, -3.829667853173777076954453401761025071562e1491L, 7.401624504283011888971231756333356050310e1495L, -1.437075122764477911733220492562365990710e1500L, 2.802940275035867428066581228962104019228e1504L, -5.491938363067613321364335249495394164430e1508L, 1.080961960603953462180593404647115933651e1513L, -2.137290931892412298654741768897581319007e1517L, 4.245031321673807283498263276791307370788e1521L, -8.469499523038763989328773224520912663309e1525L, 1.697421812794203793865032206191322699261e1530L, -3.417217332563937242285349373774004020539e1534L, 6.910378594841763785923780822895851271770e1538L, -1.403696282437585785557998429691459557649e1543L, 2.864060533055333035232343601021192111053e1547L, -5.869818290384811353182423286543086530728e1551L, 1.208359745327224593486268988808338456906e1556L, -2.498576742140453770373914215325521001990e1560L, 5.189311407347546310078739863704346083861e1564L, -1.082537954843916294257278789980768336964e1569L, 2.268238255751421312559806122980932952706e1573L, -4.773557403917983369065731568732198697502e1577L, 1.009019097334998841920279535262007639746e1582L, -2.142181266523235177327239693359275472557e1586L, 4.567814904130855969979178320003286614868e1590L, -9.782550516204803195398428611221899469345e1594L, 2.104180123097086948576304557651398411373e1599L, -4.545658958087323864004652894518442709646e1603L, 9.862563944609427542603740078470901803131e1607L, -2.149105846582226970866569209122813809019e1612L, 4.703235567543888152049628411354542509156e1616L, -1.033719212601584878353206879472796545848e1621L, 2.281767401903848796732740825793310514456e1625L, -5.058236070813950229238666252351966279306e1629L, 1.126112519657857205642546937554224492775e1634L, -2.517766761987679577706779689880657777343e1638L, 5.653225190181653388317503182908983211029e1642L, -1.274735955461074142223278576503188429497e1647L, 2.886578974679460464298863945016671299242e1651L, -6.564203307141426181809363135003467581753e1655L, 1.499036144473064593308260681782048262301e1660L, -3.437714715599902386917108442954580869236e1664L, 7.916830957072777234152907034541325149479e1668L, -1.830850567422571420661248197094782575285e1673L, 4.251778280827419894527511469762091846660e1677L, -9.915182507286989818033146623995507108134e1681L, 2.321878208636697663781227497233334385222e1686L, -5.459879022461660582811365437190884471726e1690L, 1.289222044549922720398543474297554204559e1695L, -3.056819658344217799458557578658863826289e1699L, 7.277891759142725294172926258364455941365e1703L, -1.739928293433385104144012025546489673795e1708L, 4.176797408823713136137404972612780406904e1712L, -1.006788178307821554781930741698052910780e1717L, 2.436754569909644399766538111317379484511e1721L, -5.921896599028498715774458493117079340155e1725L, 1.445045688171565118619109316933316429671e1730L, -3.540547766876069233350621578795319652040e1734L, 8.710114552028472554054293344204504325978e1738L, -2.151484527880464463303897113553085899101e1743L, 5.335928195512405709733771642389502809087e1747L, -1.328726408335015910030370523083559660016e1752L, 3.322090527232917400247098823651437597786e1756L, -8.339387326241218096865362177688582376376e1760L, 2.101842203781264395369771906884644062395e1765L, -5.318704469415522036482913743767085545209e1769L, 1.351288005941730688647540059088127991581e1774L, -3.446853546858473171100748720136784228698e1778L, 8.827284762030783576089954173424852998700e1782L, -2.269642226090373319660782216907175419317e1787L, 5.858820683661708553422363777419430816755e1791L, -1.518385813684321665045387969920683656625e1796L, 3.950661327164595923092260035122668890334e1800L, -1.031976516347387969958181456058243183780e1805L, 2.706317892325103782207094286049104555552e1809L, -7.125140422584701175967252533378906957380e1813L, 1.883260203116768075569432925204868418472e1818L, -4.997193687108743666000994570700725873035e1822L, 1.331182722092654526185433799891693838871e1827L, -3.559930289076558484535632566755216035553e1831L, 9.557281027056970446117541983785660301558e1835L, -2.575805002229372523547972911961335317502e1840L, 6.969058431277067406841032797913179025984e1844L, -1.892842481279278678390672746902260183506e1849L, 5.160964211693777744707760614147460787285e1853L, -1.412602588198037643242529860614298968137e1858L, 3.881313379962387603749693387037174052146e1862L, -1.070542170988009009334148472388319844527e1867L, 2.964094312414144330805731101996829908435e1871L, -8.238350132106899955856124602934281976453e1875L, 2.298504171050560756192352106062598639825e1880L, -6.437303944649223478093890316531995121228e1884L, 1.809727811843121957353712606428292269805e1889L, -5.107047553992257935533518628886728031061e1893L, 1.446674478990385642488446075734631327506e1898L, -4.113513327511444762766719175770513771122e1902L, 1.174067517257431444028448391638451935667e1907L, -3.363630086409895071362533854123306097827e1911L, 9.672868956071838221096869293070568259792e1915L, -2.792101741911955365960369780457612630184e1920L, 8.089710604557382430162031502761771390568e1924L, -2.352650988877130983061761312962677887796e1929L, 6.867549079740051556501575104006222995568e1933L, -2.012161201632998475706904405535757516336e1938L, 5.917489529279588702317256137229398357271e1942L, -1.746718667239329545125902248821502764273e1947L, 5.175069416058975040990816515838893249437e1951L, -1.538913401594651457295303469904084052963e1956L, 4.593185746210984655636051293374195150815e1960L, -1.375981868450401919299150690829612124045e1965L, 4.137207965217520410530508053863759216958e1969L, -1.248518564582257710069294326648626362439e1974L, 3.781575291117895093413381897917341286951e1978L, -1.149575999691408110085856948595444100435e1983L, 3.507413095836612229403470531176947165451e1987L, -1.074032838410645352804690949680310176413e1992L, 3.300857202456564870338466973024760446263e1996L, -1.018149578840803516349758843017979498322e2001L, 3.151876950233613792531594490714752800621e2005L, -9.792574827376149360558532022944033224780e2009L, 3.053456145978161645823454710737904504036e2014L, -9.555442346102849014299990542596620094035e2018L, 3.001037449298122384017009412541525703002e2023L, -9.459120112371096268275049056229023773120e2027L, 2.992168042152196502453442556462819104060e2032L, -9.498922680869041470681858599915282791899e2036L, 3.026307717971075309746179763189393755074e2041L, -9.676079238806159594565350708123427510151e2045L, 3.104778286352798464772361361434013339088e2050L, -9.997786802782252742109475924344598057966e2054L, 3.230847952724856366943939804248186203776e2059L, -1.047769651900498931701604323213605884945e2064L, 3.409958102134053489747140426163802214042e2068L, -1.113687894644055086152064258459886518528e2073L, 3.650114509271160332136458711252217684956e2077L, -1.200536387553969483433239131469825141412e2082L, 3.962482337718333099498977337189304099484e2086L, -1.312441206957064803437100929905979391106e2091L, 4.362246723746013772563799740886664288515e2095L, -1.454975881895253548422481637083633839534e2100L, 4.869831412214692119172895822285084162147e2104L, -1.635618419512383251104125916207188960680e2109L, 5.512611314145041257838234038980389596534e2113L, -1.864392957231340288547618808749072127289e2118L, 6.327317613106621547060670091824665547127e2122L, -2.154772001506498703267302897994526372056e2127L, 7.363426139490286496267931634843475368903e2131L, -2.524950643808031915843604894357998905460e2136L, 8.687956390288096215918373666581638675156e2140L, -2.999656978200020459428228924242615592768e2145L, 1.039231328851609224822335039430898644149e2150L, -3.612742437616019936358910410005123924796e2154L, 1.260211309932738404790711574105022002093e2159L, -4.410916378453971105434385837025433805752e2163L, 1.549140617923265948720013792673729394719e2168L, -5.459173749226782924959103886664322964926e2172L, 1.930343307630952098252884031069043541182e2177L, -6.848749229218425353808144618581305978045e2181L, 2.438117138001365487681440577590059588102e2186L, -8.708873656769794358508423272379627581292e2190L, 3.121268068338199458891764932384819739714e2195L, -1.122430216307539309816165910733145404999e2200L, 4.049900779207199370582177687160985635615e2204L, -1.466167983141158219266077836130256565915e2209L, 5.325678718693772500250292767751070974887e2213L, -1.940955845102272053048140384364058448998e2218L, 7.097467198361219669927211698104447309186e2222L, -2.603968771680987683436428778397387110896e2227L, 9.585403285394812946713320044815117440444e2231L, -3.540176030547640510648455468270569908446e2236L, 1.311827683984025111744358347783996339730e2241L, -4.877124229155333857009747836542843294702e2245L, 1.819213075760490882591173222316749809951e2250L, -6.808221630329265915405178596748950929642e2254L, 2.556299969544109052724772800143396857058e2259L, -9.629763347675306704861859899230073979116e2263L, 3.639508580119285595844040783082958425575e2268L, -1.380037493555816309137481185927387732499e2273L, 5.249980712165216709135893538080020409581e2277L, -2.003737844109055078145975651407367170529e2282L, 7.672522280806944397358668566379646540213e2286L, -2.947454993639165318799389781921184991045e2291L, 1.135966912801707623489383623092951142963e2296L, -4.392293711194501621873299212059053651432e2300L, 1.703813210168560937608104155973968112409e2305L, -6.630636743874062041158387022015853902938e2309L, 2.588742636486379690203698247275411406029e2314L, -1.013959594068423546627946242481463893979e2319L, 3.984265821528043268586235974854766821078e2323L, -1.570614519682157047612769672066387881154e2328L, 6.211297381339606877062824459742129064477e2332L, -2.464246931985476159686671650962783785426e2337L, 9.807833742601662212615240518855757197483e2341L, -3.916036434571217691317276306031837539092e2346L, 1.568566392975837368624727722120313955274e2351L, -6.302885887601142677858008037129298948063e2355L, 2.540704455306077495480843691828334210014e2360L, -1.027412480318234348899627142408950111875e2365L, 4.167823618450297116765978030480648316769e2369L, -1.696076602731914277275203926124423530377e2374L, 6.923904505633301788461482786634220738504e2378L, -2.835463065742506394026733592206185459035e2383L, 1.164828772275756526225951620927486307632e2388L, -4.800242878545012539781545966693324656699e2392L, 1.984381759611877246529319121941597679107e2397L, -8.228979942542641498511023600269641046627e2401L, 3.423130231367101727862739208673375060101e2406L, -1.428418168129733054582191895023094524495e2411L, 5.979153801634459282232521647160044877770e2415L, -2.510581926948409809562349588087762800160e2420L, 1.057443785053915411991029410076722022815e2425L, -4.467723713549428749678277264414266162837e2429L, 1.893474116528533144079731251913008472748e2434L, -8.049601965052954947260081891142509464888e2438L, 3.432648527503971149009691133946275281368e2443L, -1.468324699963694393989960228042259134294e2448L,
+ //
+ // 1302-1600: http://www.wolframalpha.com/input/?i=TABLE[N[Bernoulli[i]%2C40]%2C+{i%2C1302%2C1600%2C2}]
+ 6.300146502435743791500010801885493871234e2452L, -2.711520667146768856688291798851999580833e2457L, 1.170595555513900137297344452318266434006e2462L, -5.069095411973246242900074508988493530542e2466L, 2.201819284807954055092117706033113168896e2471L, -9.593088725189386197503123561368325167085e2475L, 4.192362385909155628936230811010649614060e2480L, -1.837725836941968309866675158105812946762e2485L, 8.080201101491972605313807752565294881374e2489L, -3.563536075527215702966392543784039539240e2494L, 1.576361051321107275181955665159661781175e2499L, -6.994292466180175594372663323941761853364e2503L, 3.112744353537336702834647901141392426258e2508L, -1.389481328370627358752727485697345194612e2513L, 6.221134636655213696041740685131223999953e2517L, -2.793779613656947577224654924852010601105e2522L, 1.258399062987759035354039924686781081603e2527L, -5.685208194704131918461885165870560583895e2531L, 2.576167857759537340210434756292816456179e2536L, -1.170846052338591953257169251219597581763e2541L, 5.337296787116189575571202979672747140313e2545L, -2.440264475369219459038748840841422948951e2550L, 1.119037151526195093932933161706501865175e2555L, -5.146858829220973887154576240993607686435e2559L, 2.374259791963193693837576781321391741634e2564L, -1.098501215269400934956638118646657823799e2569L, 5.097500369683616795005376807036889542869e2573L, -2.372446971688020647583535886090779018865e2578L, 1.107430282014636546248612381377039463753e2583L, -5.184597227131050012643138079903381280471e2587L, 2.434392040100910394476893838832599310265e2592L, -1.146412753331162872665743308094817095949e2597L, 5.414578104816988124950636101250217797539e2601L, -2.564835392810685332173156758121489913946e2606L, 1.218495070518549208066544111736985586178e2611L, -5.805713573821806672815019495319510297824e2615L, 2.774298194574319430697819781128985128618e2620L, -1.329580186505564627453485444017911980430e2625L, 6.390545858902318479863947547243743500916e2629L, -3.080502542499571035376377703435361520427e2634L, 1.489236104239976282318361008292980814533e2639L, -7.220413839991892382038608955317126799684e2643L, 3.510874916591640642524021216241607185085e2648L, -1.712070118580404599831061485055269100525e2653L, 8.372956919832386730490070625622785478703e2657L, -4.106629146981883685523102256292669054596e2662L, 2.019945438530802964718619732330776495740e2667L, -9.964133277392242111939720494354938982970e2671L, 4.929278642971447854669801547226335041410e2676L, -2.445509657169810919463982615395074704130e2681L, 1.216734421265677299127016883839223226884e2686L, -6.071008437677720186241562251151490713584e2690L, 3.037824949882992896564570441252792097027e2695L, -1.524402878612630565501569310883356490225e2700L, 7.671320530781999359200097739951316234193e2704L, -3.871436167706734376478728954716915204399e2709L, 1.959313530432202158587932399068682252335e2714L, -9.944063618400630821320953821427307024297e2718L, 5.061161998202463346818982228476199873781e2723L, -2.583219090831132705328958245740715185448e2728L, 1.322193991367293532684189527174543501836e2733L, -6.786569982732483290873213417465458376706e2737L, 3.493212334804776543395067018414547811062e2742L, -1.803090099978261928508495412750404640933e2747L, 9.333100843930216567894508007158644926767e2751L, -4.844499031405982604449146511179496492045e2756L, 2.521648090959971240812330574936006906830e2761L, -1.316227870932708474838173333385377250286e2766L, 6.889488826832738674261056521130795910494e2770L, -3.616184242864384509259984293501533623932e2775L, 1.903356124758119137116543283603627028779e2780L, -1.004601544584640657081847200643996069583e2785L, 5.317043885597842225603585588404817559596e2789L, -2.821938866752488868682751438901900485500e2794L, 1.501842023003449590337997900945924161741e2799L, -8.014908048137216649348740300633172710524e2803L, 4.289126235121619907138036129192558937445e2808L, -2.301619137231461344870820700320913118444e2813L, 1.238485136850053215006962645111854705210e2818L, -6.682503731149007943059244518074044280490e2822L, 3.615572393938012932030234169574978859655e2827L, -1.961565108627429629104703146282982075623e2832L, 1.067123259692924564435881096382837264046e2837L, -5.821179870182035246401397327057170726418e2841L, 3.184127229476322727732208017279268211356e2846L, -1.746429902183019597973436257300843998825e2851L, 9.604873565299766333876882842813498685054e2855L, -5.296759978724702692134960752308186890356e2860L, 2.928906353338652198977536576170287112391e2865L, -1.623961162577704769945821804737884742792e2870L, 9.028574047002736235613238355032484299017e2874L, -5.033087486357905828950503441308068892610e2879L, 2.813325650062267479031371852434194635210e2884L, -1.576791132296320840138263753339056345362e2889L, 8.861258343945925667272164531504265693289e2893L, -4.993236404321511029440212686547068244002e2898L, 2.821192993950901287717082243608730217471e2903L, -1.598254169674379493385730199445427966752e2908L, 9.078617590346932363947095804057608979359e2912L, -5.170742114456472142154347566092068443393e2917L, 2.952866185102528847516095880416675972086e2922L, -1.690794578626103552690094140317813413244e2927L, 9.707168799669516048238542260085175133847e2931L, -5.587884732306715493795271931175883605707e2936L, 3.225179489154957423492905957887744116530e2941L, -1.866424419669188178697802576490431604300e2946L, 1.082967626854618222657109354056973072044e2951L, -6.300392007169862865282706277272018077291e2955L, 3.675066377245428685118763485986517510658e2960L, -2.149348371085132073107516253339849053182e2965L, 1.260349351812619395000600434630904474324e2970L, -7.409963623771231302980906971935254993610e2974L, 4.367980758467862686643231700861155889684e2979L, -2.581566823350789671250829457603555544100e2984L, 1.529757357568342629912560827243282062227e2989L, -9.088595394263364554625061567617375176719e2993L, 5.413829169254585648363594604231030415354e2998L, -3.233288119606092759447005827969216281573e3003L, 1.936042437734875803183915765854038424658e3008L, -1.162289934202291715747729318797398221667e3013L, 6.995870350500567071550614251287615697508e3017L, -4.221776496490106417392945233048068288503e3022L, 2.554309239868912570382343877718991746122e3027L, -1.549440871550119801225143558087410562418e3032L, 9.423199525954784955533959981278992475051e3036L, -5.745689660772387668861183913170050552119e3041L, 3.512407521007240798565045328376471603253e3046L, -2.152708113797517364614914569890010876143e3051L, 1.322761289733739440340237168659770154654e3056L, -8.148777388506488753591136948542248584098e3060L, 5.032880858479326069741729004270784264612e3065L, -3.116396010103058126269735274818345780360e3070L, 1.934634831148214353514796782480703021435e3075L, -1.204077166243116651938489240924641810276e3080L, 7.513065583444964704795707060501161621868e3084L, -4.699873512563164914493150520500838535415e3089L, 2.947541197349762411713872934523813866703e3094L, -1.853262416286420077763886100673646141885e3099L, 1.168196427912100545575264493997591040800e3104L, -7.382362285873345348505276546404015842875e3108L, 4.677071041058096429847797962954927487730e3113L, -2.970642034084362431442183248944824506476e3118L, 1.891572688282564476274920103912259755482e3123L, -1.207509963440193713810418554061532113326e3128L, 7.727731208240101791845515599659441557781e3132L, -4.957988488048495669466804712012179891532e3137L, 3.188965862446236259925047956715566822864e3142L, -2.056286895821370106507670239256782411337e3147L, 1.329246918771714093479509313343886287414e3152L, -8.614188519577835653765633797787633659253e3156L,
+ //
+ // 1602-1900: http://www.wolframalpha.com/input/?i=TABLE[N[Bernoulli[i]%2C40]%2C+{i%2C1602%2C1900%2C2}]
+ 5.596396533621874175909933615343145642161e3161L, -3.644908483469388437457938883454376864180e3166L, 2.379838409026860469990569665632800095988e3171L, -1.557720925267669865362152155022069166772e3176L, 1.022143420270029721682551084917730373739e3181L, -6.723767358891570842116651998814252095792e3185L, 4.433950491570308179905446963723780229747e3190L, -2.931196854668917448553150023532223509373e3195L, 1.942557068752664549549945921392100172355e3200L, -1.290553202978622786891265558106235068695e3205L, 8.595082329732118303768775883557789195136e3209L, -5.738453265222970049867280061719670658457e3214L, 3.840687915100689856736926915331157331684e3219L, -2.576862441955523551149886625900059307506e3224L, 1.733166107320377310388765047659987844208e3229L, -1.168569552450178559412843683052610870569e3234L, 7.898289836694980777809433306209459851871e3238L, -5.351485909164216694400535493924387979018e3243L, 3.634772439350395177931952925644409735777e3248L, -2.474801048002975145046569303233576339695e3253L, 1.689126939254790850063878942448569759390e3258L, -1.155691524500722774057997965355407962525e3263L, 7.926435404542361405718288670391575676323e3267L, -5.449654814183048796524718620178906854846e3272L, 3.755898589900254795894812942275711835138e3277L, -2.594843902682143854622514329649211211808e3282L, 1.797048752397789969347915328338360264536e3287L, -1.247551415074438712713815166107969504456e3292L, 8.681719521514448143910215886388510318746e3296L, -6.056203898213120922016159444227958572276e3301L, 4.234882876331814099029781995617143573641e3306L, -2.968432911643338866295929748049749932906e3311L, 2.085723508930484816454740610260790948864e3316L, -1.469023169879432026361623513301566735138e3321L, 1.037150346505052892302077637883522696572e3326L, -7.339977067836656769144838365069396168014e3330L, 5.206985412168234130596004552956337839140e3335L, -3.702673773319239583641029108403509825141e3340L, 2.639251227995760315076225206168354089692e3345L, -1.885736353072698581595150856674914203383e3350L, 1.350563292338261784288559687678302458996e3355L, -9.695749980998301526113046898985991802000e3359L, 6.977167462628398202151721319169989304520e3364L, -5.032768280399753942925624560483352299263e3369L, 3.638844963651800168080623511900705036698e3374L, -2.637228631269251606169613775399022890118e3379L, 1.915836351653767108720464847696767898597e3384L, -1.395064293615007319328267865803567670760e3389L, 1.018249052614943190644465556486933211307e3394L, -7.449662162606857550867922631658930320805e3398L, 5.463119632208085241594107781601567713991e3403L, -4.015736541676989144201935890497836963875e3408L, 2.958754190183866660901503059509579790900e3413L, -2.185096074054288399312733179064098492511e3418L, 1.617517444557020250864919655301189186103e3423L, -1.200170662015511746748935675940010250555e3428L, 8.925888349899029449015791684428724952411e3432L, -6.653851763691885517669938275618991145962e3437L, 4.971722031098457895973348076474071155918e3442L, -3.723500582577984967442020337848702786829e3447L, 2.795153783541721373364976034391375710110e3452L, -2.103141577212720698169118819883801186873e3457L, 1.586129575320959267959148073466004084241e3462L, -1.198988457279648730711646682156242973137e3467L, 9.084402368157025658430300252246526602197e3471L, -6.898927494435965163817354296023108913714e3476L, 5.251332286149361587885046891266325872375e3481L, -4.006442950956739933884502808470603581850e3486L, 3.063718202820270282280659950794978994604e3491L, -2.348215284130973783732145823834807395920e3496L, 1.803952490148087317330011096671019781340e3501L, -1.389022326803437345760911068933754707688e3506L, 1.071986115818329525986099441493200866389e3511L, -8.292085224650940719705699485423856363908e3515L, 6.428829064452939640541475198655560890344e3520L, -4.995654440302797445368056643032307686314e3525L, 3.890847042582299188849273838681034339406e3530L, -3.037288555751484681537442833929275697351e3535L, 2.376385803695694695338601696534348875191e3540L, -1.863527130251861900692886008704804849076e3545L, 1.464674913498036269270793715104706378182e3550L, -1.153804954579033578659954846698233083197e3555L, 9.109783835348935092264268296199541780964e3559L, -7.208869193983001804305451104827153729326e3564L, 5.717530734277611949162917337810749919265e3569L, -4.544970302634007326980094771330550661605e3574L, 3.621042850825283032134228901678636353355e3579L, -2.891447067949778492831490654980043715471e3584L, 2.314060419397710657435821461707043283167e3589L, -1.856140759923563235273220981623595304434e3594L, 1.492185412981476596273279338314204171587e3599L, -1.202290032627175365810126250991853594801e3604L, 9.708881154579770196658265042625239421053e3608L, -7.857809850747029705680072304049448493252e3613L, 6.373898598298513400228819113197728735438e3618L, -5.181780406472117449048907989647202286666e3623L, 4.222036621953044040518942750638183171221e3628L, -3.447728386429130175025813550845575613047e3633L, 2.821701521717856346224159586852612710800e3638L, -2.314488376711998526455043944505424906920e3643L, 1.902671298033180765286213227393060711096e3648L, -1.567603736821312488140289549008391847440e3653L, 1.294408945316538946551785312385509945367e3658L, -1.071194533081615830960091702262923009420e3663L, 8.884351908108581551151252566466606126397e3667L, -7.384866682828103669170236267589653324531e3672L, 6.152023838008155718180876735217718355563e3677L, -5.136304310431705506236573876510219357975e3682L, 4.297736808124296434723193397876220759378e3687L, -3.603994887745884762510172194982172483480e3692L, 3.028884745605031552399167746007361297342e3697L, -2.551141302205187365552982635794121855138e3702L, 2.153467982869535549299173317536193051608e3707L, -1.821769476343602094059466497311600827296e3712L, 1.544537580582347892980177956984101211006e3717L, -1.312358705945937257247030754517293537539e3722L, 1.117518229297781388884979995402355617235e3727L, -9.536820860779441793021624381677086661097e3731L, 8.156400668831968026931547065507466530546e3736L, -6.990984948728184142718575396052260691181e3741L, 6.005124901126818071638224144541102727563e3746L, -5.169500241880947716732682089328427995109e3751L, 4.459815478235310026240134567325749844182e3756L, -3.855902253361684187081283218890336962427e3761L, 3.340988024176995223515640815937037040546e3766L, -2.901099226680215736735094376078800376829e3771L, 2.524573363444334459448089563912567842927e3776L, -2.201659455716348555524529213295341212492e3781L, 1.924190302190936448078364755844591374353e3786L, -1.685313186099770223843319514432495898517e3791L, 1.479268235966730475749985741048766689808e3796L, -1.301205702893883803117530921635013780575e3801L, 1.147035071153450453405384269242743907426e3806L, -1.013300250456366849150496776951686112298e3811L, 8.970761720605591762300958007557533865346e3815L, -7.958829781488943084496783248922217392838e3820L, 7.076146954685024795720193943027902028642e3825L, -6.304798526260409199660290516451546966159e3830L, 5.629519616664188107056583939722984509867e3835L, -5.037281594099054092767959480843344929292e3840L, 4.516946091316834843581919268794683123349e3845L, -4.058975118925834202620358386772092359951e3850L, 3.655187798978978909014603682039470653549e3855L, -3.298555903041546671060101785513812175322e3860L, 2.983031738662727912016882399515879119620e3865L, -2.703403043317732979516341931451317866898e3870L, 2.455170460800096241793872443768546335444e3875L, -2.234443928432490538417605502448376856290e3880L, 2.037854924078003280537856980560782325730e3885L, -1.862482033918775734840779765743099458137e3890L,
+ //
+ // 1902-2200: http://www.wolframalpha.com/input/?i=TABLE[N[Bernoulli[i]%2C40]%2C+{i%2C1902%2C2200%2C2}]
+ 1.705787724951999960095629912416210969679e3895L, -1.565564556110550991891247404758895970376e3900L, 1.439889351869832939488618785632174464789e3905L, -1.327084102784257406218693901793045990520e3910L, 1.225682557296027075027021534960026145706e3915L, -1.134401635488994148555787301654561211982e3920L, 1.052116934052356802920509999705307165985e3925L, -9.778417073593082219082361206542342793584e3929L, 9.107088061888562704837019028349522303725e3934L, -8.499551364633102138471246155980056936129e3939L, 7.949082681085658044610890152056533167407e3944L, -7.449748809722797718736397140511396011691e3949L, 6.996307824769340144608141799981589288378e3954L, -6.584122718472954006131003060359621706243e3959L, 6.209086595833487707192492087176843233407e3964L, -5.867557793863165391821489909125720982339e3969L, 5.556303538475260373917478405626416604297e3974L, -5.272450955936249442242634142613834212778e3979L, 5.013444428433789818228792126117223030641e3984L, -4.777008429684552423800736200488532033034e3989L, 4.561115100786341787876705283291018781137e3994L, -4.363955932181992701667719449097126840439e3999L, 4.183917007557000586305945495258591147615e4004L, -4.019557342177353010692923286760895584096e4009L, 3.869589913635745758786275231296652917580e4014L, -3.732865038934070181861017140563175000872e4019L, 3.608355799736107390800162778737339576843e4024L, -3.495145258697474565347261083975193776541e4029L, 3.392415245050326563747729613872524362741e4034L, -3.299436517958948801426629481782413630714e4039L, 3.215560142306355508598119430378551642857e4044L, -3.140209934146377815556058799557727461298e4049L, 3.072875852591406752692761744649563131272e4054L, -3.013108231854799187724018548255922550991e4059L, 2.960512761914376268185064129600549308882e4064L, -2.914746139139036596123006476633770383901e4069L, 2.875512319506974985103149834921665445532e4074L, -2.842559316984704569380036093537576068104e4079L, 2.815676498441436148701483904115879856704e4084L, -2.794692334326268275058539147656334465534e4089L, 2.779472571396106785963004020814493340829e4094L, -2.769918800191406321625251621260024635680e4099L, 2.765967395840433013288935879837390099329e4104L, -2.767588816244119880300161388073836623878e4109L, 2.774787246856347651152278076466043136230e4114L, -2.787600586224957950622601135620189837948e4119L, 2.806100771288225169339048358106052817280e4124L, -2.830394446218080573456394167711739786431e4129L, 2.860623983452244712039094143642843717029e4134L, -2.896968870550611723525738907034588104300e4139L, 2.939647481737606306044335918078617963078e4144L, -2.988919258547518526076380181812161398808e4149L, 3.045087329976721023952450383837883029431e4154L, -3.108501609077197464748958150625867523408e4159L, 3.179562410123820875787052833975010965963e4164L, -3.258724638491880104953913719767939138170e4169L, 3.346502614347964869115073881474258766546e4174L, -3.443475601364631413158991572423086599816e4179L, 3.550294123121350747300886840907918182129e4184L, -3.667687162886053419715985091863398517145e4189L, 3.796470357354794420044278000297864085607e4194L, -3.937555311976846882455930574021795626971e4199L, 4.091960185075595842547638450930710467324e4204L, -4.260821710519620959138720129506770036460e4209L, 4.445408854703156440576808070360934740837e4214L, -4.647138333645908068599900650548418672065e4219L, 4.867592250805288922190809906525766574205e4224L, -5.108538156515551259475573296900660666192e4229L, 5.371951876776035157276013631113314852508e4234L, -5.660043513521220243900043448456234873940e4239L, 5.975287081834808618140945840817834710330e4244L, -6.320454323372684034118816565375206053746e4249L, 6.698653321371992324876559665938996023646e4254L, -7.113372643219128807424340495235606473967e4259L, 7.568531854202750881338746432078817214052e4264L, -8.068539383842553693076672384509126681464e4269L, 8.618358887685935324188596304168259394311e4274L, -9.223585437012291673660319256730398171887e4279L, 9.890533091606747031464718533600572123091e4284L, -1.062633567277107015128545384570274268438e4290L, 1.143906286231591191271274413511275981288e4295L, -1.233785411712565904499340744089870916842e4300L, 1.333307331840530219050170916015276125870e4305L, -1.443648758235403286296065629219598769529e4310L, 1.566147425967471851736562867318748510088e4315L, -1.702326086290842780634120184324081017286e4320L, 1.853920350455786350409148418966087344063e4325L, -2.022911043115598592197907512410632615740e4330L, 2.211561842992792253055716743938240466613e4335L, -2.422463130294011318178080247305407476096e4340L, 2.658583129381772791030436640519847627789e4345L, -2.923327636881988941081365085520742216540e4350L, 3.220609866329557159104267531058019683271e4355L, -3.554932228621330128152149026066400241546e4360L, 3.931482212643167323798366327390058684499e4365L, -4.356244944221399578650235478583297389113e4370L, 4.836135498303121165971331625888490168138e4375L, -5.379154636371461359750682662639062606297e4380L, 5.994572359716861309678596804350346692501e4385L, -6.693144535124290060793936095397161934045e4390L, 7.487368894313509797084395689517008597061e4395L, -8.391787970609807810531578161564037339793e4400L, 9.423348062978921203475110312003096820035e4405L, -1.060182516651648405903017734022504884319e4411L, 1.195033105063952979885086754342706651656e4416L, -1.349591538868673992167798923586925758429e4421L, 1.527028315253291113905307092657539132480e4426L, -1.731065051510920640409442255224015234974e4431L, 1.966076741510092840076264635935585216200e4436L, -2.237214093245750681191361238831105906202e4441L, 2.550550094903891445719729187215253324232e4446L, -2.913255853313667303707651906277658164129e4451L, 3.333811847072394764285817140850092324169e4456L, -3.822262084288044913490118858492563410392e4461L, 4.390520310533864198186202368026630430120e4466L, -5.052739449335052080092114976206610871466e4471L, 5.825757966350870043117899492954521458799e4476L, -6.729639942938203582008846884575881320532e4481L, 7.788329466816396015493306357116312471970e4486L, -9.030444674469025073047417528762134025409e4491L, 1.049024263381993629167658236142000524752e4497L, -1.220879351508964912255081664072251573277e4502L, 1.423541151220109512749655991050110438471e4507L, -1.662940118618541616964708044356967429362e4512L, 1.946219185900482116137855064775635250366e4517L, -2.281995008842006909631764011781911322493e4522L, 2.680678198213108543648324254258111216040e4527L, -3.154866427472784086389609599207759103500e4532L, 3.719827710160801797530420206201570269720e4537L, -4.394095404360277919140027580071549980218e4542L, 5.200201854779615608741690339830306148442e4547L, -6.165584312943608652377791415603277251516e4552L, 7.323705248531382981433751104158852636445e4557L, -8.715439846124090647163930834760361817820e4562L, 1.039079696609215651011736087603304766850e4568L, -1.241105689556982425619608247473478857800e4573L, 1.485143079696380339521658550262280772546e4578L, -1.780437412164973637340821168154300094802e4583L, 2.138372099157518882088209435171770222745e4588L, -2.572985071149069551034276570909360759588e4593L, 3.101615379617643734762997559011097203354e4598L, -3.745713657616368229906151946770042703357e4603L, 4.531859496161940719835150033082561700677e4608L, -5.493040495326927998321538336584233566465e4613L, 6.670262730603009306595018122252730741798e4618L, -8.114581584793494903775255213273982440688e4623L, 9.889666561810883044159054730371102725871e4628L, -1.207504541653929734716275932570097623330e4634L, 1.477021377885843688233899471354959308782e4639L, -1.809984912147908767583043524070645821179e4644L,
+ //
+ // 2202-2320: http://www.wolframalpha.com/input/?i=TABLE[N[Bernoulli[i]%2C40]%2C+{i%2C2202%2C2320%2C2}]
+ 2.222043594325228980916360265527780300093e4649L, -2.732869701246338361699515268224049951411e4654L, 3.367233945421922463553518272642397177145e4659L, -4.156377225041273602431272489314020150392e4664L, 5.139764368092890466235162431795350591151e4669L, -6.367329693760865476879589228002216011370e4674L, 7.902356742934106007362514378717026407839e4679L, -9.825176966314431712897976595483070301406e4684L, 1.223792760178593282435724837135946867088e4690L, -1.527068151452750404853140815207477555192e4695L, 1.908935682572268829496101580401263597905e4700L, -2.390593888616966248780378941331847473699e4705L, 2.999171106576893833644521002894489856321e4710L, -3.769440655453736670024798444784356437578e4715L, 4.746047769851891438576002047529258107351e4720L, -5.986405469241447720766576164546767533359e4725L, 7.564466155536872051712519119999711534616e4730L, -9.575641408047918720040356745796976488951e4735L, 1.214322951835035451699619713803395497423e4741L, -1.542682591979864353012093794301924196234e4746L, 1.963334539793192183270983986567556358603e4751L, -2.503148969013901182572118121398034622584e4756L, 3.197076711250102964526567664729089847162e4761L, -4.090653552025822488578293526174572934858e4766L, 5.243302769651520536759521264615159906699e4771L, -6.732697170903775309261288127044088674182e4776L, 8.660529543801770516930589210020128142543e4781L, -1.116015823611149634592870112730519454113e4787L, 1.440675306432920129218036927923030695520e4792L, -1.863078034853256227415397798026969938881e4797L, 2.413595413458810442409656314019115041699e4802L, -3.132317029597258599678590012779717945144e4807L, 4.072246763371584312534474102756137619716e4812L, -5.303577511521827157146305369181950467569e4817L, 6.919417518688636032335131253584331645491e4822L, -9.043473312934241153732087612484569398979e4827L, 1.184037400265044213826044590639924237359e4833L, -1.552956685415800894409743993367334099777e4838L, 2.040404893052952221581694807126473204625e4843L, -2.685565763841580219033402331219206776210e4848L, 3.540927057361929050327811875290025248120e4853L, -4.676912607538885419407656762767991163574e4858L, 6.188165903566760647569323704623433330229e4863L, -8.202087471895029964699042637255411806373e4868L, 1.089045274355389654614196651761310970580e4874L, -1.448524684976553869119447042300206226148e4879L, 1.930028100376784839502387280956424581974e4884L, -2.576074799096023589462128312524664980682e4889L, 3.444369635011990347297134928452972402038e4894L, -4.613354441299253694113609154769978684993e4899L, 6.189834306866879018555349507257537840922e4904L, -8.319470760665157534580593571258276368233e4909L, 1.120124240070996761986102680587384813245e4915L, -1.510740451399746828351090108638980398124e4920L, 2.041108231091323198877509959371257503819e4925L, -2.762447751447012472733302936575873838539e4930L,
+#endif
+ }};
+
+ return bernoulli_data[n];
+}
+
+template <class T>
+inline T unchecked_bernoulli_imp(std::size_t n, const mpl::int_<4>& )
+{
+ //
+ // Special case added for multiprecision types that have no conversion from long long,
+ // there are very few such types, but mpfr_class is one.
+ //
+ static const boost::array<boost::int32_t, 1 + max_bernoulli_b2n<T>::value> numerators =
+ {{
+ boost::int32_t( +1LL),
+ boost::int32_t( +1LL),
+ boost::int32_t( -1LL),
+ boost::int32_t( +1LL),
+ boost::int32_t( -1LL),
+ boost::int32_t( +5LL),
+ boost::int32_t( -691LL),
+ boost::int32_t( +7LL),
+ boost::int32_t( -3617LL),
+ boost::int32_t( +43867LL),
+ boost::int32_t( -174611LL),
+ boost::int32_t( +854513LL),
+ }};
+
+ static const boost::array<boost::int32_t, 1 + max_bernoulli_b2n<T>::value> denominators =
+ {{
+ boost::int32_t( 1LL),
+ boost::int32_t( 6LL),
+ boost::int32_t( 30LL),
+ boost::int32_t( 42LL),
+ boost::int32_t( 30LL),
+ boost::int32_t( 66LL),
+ boost::int32_t( 2730LL),
+ boost::int32_t( 6LL),
+ boost::int32_t( 510LL),
+ boost::int32_t( 798LL),
+ boost::int32_t( 330LL),
+ boost::int32_t( 138LL),
+ }};
+ return T(numerators[n]) / T(denominators[n]);
+}
+
+} // namespace detail
+
+template<class T>
+inline T unchecked_bernoulli_b2n(const std::size_t n)
+{
+ typedef mpl::int_<detail::bernoulli_imp_variant<T>::value> tag_type;
+
+ return detail::unchecked_bernoulli_imp<T>(n, tag_type());
+}
+
+}} // namespaces
+
+#endif // BOOST_MATH_UNCHECKED_BERNOULLI_HPP
diff --git a/boost/math/special_functions/detail/unchecked_factorial.hpp b/boost/math/special_functions/detail/unchecked_factorial.hpp
index eb8927a268..3c23d6e15a 100644
--- a/boost/math/special_functions/detail/unchecked_factorial.hpp
+++ b/boost/math/special_functions/detail/unchecked_factorial.hpp
@@ -15,7 +15,9 @@
#pragma warning(push) // Temporary until lexical cast fixed.
#pragma warning(disable: 4127 4701)
#endif
+#ifndef BOOST_MATH_NO_LEXICAL_CAST
#include <boost/lexical_cast.hpp>
+#endif
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
@@ -266,6 +268,196 @@ struct max_factorial<long double>
BOOST_STATIC_CONSTANT(unsigned, value = 170);
};
+#ifdef BOOST_MATH_USE_FLOAT128
+
+template <>
+inline BOOST_MATH_FLOAT128_TYPE unchecked_factorial<BOOST_MATH_FLOAT128_TYPE>(unsigned i)
+{
+ static const boost::array<BOOST_MATH_FLOAT128_TYPE, 171> factorials = { {
+ 1,
+ 1,
+ 2,
+ 6,
+ 24,
+ 120,
+ 720,
+ 5040,
+ 40320,
+ 362880.0Q,
+ 3628800.0Q,
+ 39916800.0Q,
+ 479001600.0Q,
+ 6227020800.0Q,
+ 87178291200.0Q,
+ 1307674368000.0Q,
+ 20922789888000.0Q,
+ 355687428096000.0Q,
+ 6402373705728000.0Q,
+ 121645100408832000.0Q,
+ 0.243290200817664e19Q,
+ 0.5109094217170944e20Q,
+ 0.112400072777760768e22Q,
+ 0.2585201673888497664e23Q,
+ 0.62044840173323943936e24Q,
+ 0.15511210043330985984e26Q,
+ 0.403291461126605635584e27Q,
+ 0.10888869450418352160768e29Q,
+ 0.304888344611713860501504e30Q,
+ 0.8841761993739701954543616e31Q,
+ 0.26525285981219105863630848e33Q,
+ 0.822283865417792281772556288e34Q,
+ 0.26313083693369353016721801216e36Q,
+ 0.868331761881188649551819440128e37Q,
+ 0.29523279903960414084761860964352e39Q,
+ 0.103331479663861449296666513375232e41Q,
+ 0.3719933267899012174679994481508352e42Q,
+ 0.137637530912263450463159795815809024e44Q,
+ 0.5230226174666011117600072241000742912e45Q,
+ 0.203978820811974433586402817399028973568e47Q,
+ 0.815915283247897734345611269596115894272e48Q,
+ 0.3345252661316380710817006205344075166515e50Q,
+ 0.1405006117752879898543142606244511569936e52Q,
+ 0.6041526306337383563735513206851399750726e53Q,
+ 0.265827157478844876804362581101461589032e55Q,
+ 0.1196222208654801945619631614956577150644e57Q,
+ 0.5502622159812088949850305428800254892962e58Q,
+ 0.2586232415111681806429643551536119799692e60Q,
+ 0.1241391559253607267086228904737337503852e62Q,
+ 0.6082818640342675608722521633212953768876e63Q,
+ 0.3041409320171337804361260816606476884438e65Q,
+ 0.1551118753287382280224243016469303211063e67Q,
+ 0.8065817517094387857166063685640376697529e68Q,
+ 0.427488328406002556429801375338939964969e70Q,
+ 0.2308436973392413804720927426830275810833e72Q,
+ 0.1269640335365827592596510084756651695958e74Q,
+ 0.7109985878048634518540456474637249497365e75Q,
+ 0.4052691950487721675568060190543232213498e77Q,
+ 0.2350561331282878571829474910515074683829e79Q,
+ 0.1386831185456898357379390197203894063459e81Q,
+ 0.8320987112741390144276341183223364380754e82Q,
+ 0.507580213877224798800856812176625227226e84Q,
+ 0.3146997326038793752565312235495076408801e86Q,
+ 0.1982608315404440064116146708361898137545e88Q,
+ 0.1268869321858841641034333893351614808029e90Q,
+ 0.8247650592082470666723170306785496252186e91Q,
+ 0.5443449390774430640037292402478427526443e93Q,
+ 0.3647111091818868528824985909660546442717e95Q,
+ 0.2480035542436830599600990418569171581047e97Q,
+ 0.1711224524281413113724683388812728390923e99Q,
+ 0.1197857166996989179607278372168909873646e101Q,
+ 0.8504785885678623175211676442399260102886e102Q,
+ 0.6123445837688608686152407038527467274078e104Q,
+ 0.4470115461512684340891257138125051110077e106Q,
+ 0.3307885441519386412259530282212537821457e108Q,
+ 0.2480914081139539809194647711659403366093e110Q,
+ 0.188549470166605025498793226086114655823e112Q,
+ 0.1451830920282858696340707840863082849837e114Q,
+ 0.1132428117820629783145752115873204622873e116Q,
+ 0.8946182130782975286851441715398316520698e117Q,
+ 0.7156945704626380229481153372318653216558e119Q,
+ 0.5797126020747367985879734231578109105412e121Q,
+ 0.4753643337012841748421382069894049466438e123Q,
+ 0.3945523969720658651189747118012061057144e125Q,
+ 0.3314240134565353266999387579130131288001e127Q,
+ 0.2817104114380550276949479442260611594801e129Q,
+ 0.2422709538367273238176552320344125971528e131Q,
+ 0.210775729837952771721360051869938959523e133Q,
+ 0.1854826422573984391147968456455462843802e135Q,
+ 0.1650795516090846108121691926245361930984e137Q,
+ 0.1485715964481761497309522733620825737886e139Q,
+ 0.1352001527678402962551665687594951421476e141Q,
+ 0.1243841405464130725547532432587355307758e143Q,
+ 0.1156772507081641574759205162306240436215e145Q,
+ 0.1087366156656743080273652852567866010042e147Q,
+ 0.103299784882390592625997020993947270954e149Q,
+ 0.9916779348709496892095714015418938011582e150Q,
+ 0.9619275968248211985332842594956369871234e152Q,
+ 0.942689044888324774562618574305724247381e154Q,
+ 0.9332621544394415268169923885626670049072e156Q,
+ 0.9332621544394415268169923885626670049072e158Q,
+ 0.9425947759838359420851623124482936749562e160Q,
+ 0.9614466715035126609268655586972595484554e162Q,
+ 0.990290071648618040754671525458177334909e164Q,
+ 0.1029901674514562762384858386476504428305e167Q,
+ 0.1081396758240290900504101305800329649721e169Q,
+ 0.1146280563734708354534347384148349428704e171Q,
+ 0.1226520203196137939351751701038733888713e173Q,
+ 0.132464181945182897449989183712183259981e175Q,
+ 0.1443859583202493582204882102462797533793e177Q,
+ 0.1588245541522742940425370312709077287172e179Q,
+ 0.1762952551090244663872161047107075788761e181Q,
+ 0.1974506857221074023536820372759924883413e183Q,
+ 0.2231192748659813646596607021218715118256e185Q,
+ 0.2543559733472187557120132004189335234812e187Q,
+ 0.2925093693493015690688151804817735520034e189Q,
+ 0.339310868445189820119825609358857320324e191Q,
+ 0.396993716080872089540195962949863064779e193Q,
+ 0.4684525849754290656574312362808384164393e195Q,
+ 0.5574585761207605881323431711741977155627e197Q,
+ 0.6689502913449127057588118054090372586753e199Q,
+ 0.8094298525273443739681622845449350829971e201Q,
+ 0.9875044200833601362411579871448208012564e203Q,
+ 0.1214630436702532967576624324188129585545e206Q,
+ 0.1506141741511140879795014161993280686076e208Q,
+ 0.1882677176888926099743767702491600857595e210Q,
+ 0.237217324288004688567714730513941708057e212Q,
+ 0.3012660018457659544809977077527059692324e214Q,
+ 0.3856204823625804217356770659234636406175e216Q,
+ 0.4974504222477287440390234150412680963966e218Q,
+ 0.6466855489220473672507304395536485253155e220Q,
+ 0.8471580690878820510984568758152795681634e222Q,
+ 0.1118248651196004307449963076076169029976e225Q,
+ 0.1487270706090685728908450891181304809868e227Q,
+ 0.1992942746161518876737324194182948445223e229Q,
+ 0.269047270731805048359538766214698040105e231Q,
+ 0.3659042881952548657689727220519893345429e233Q,
+ 0.5012888748274991661034926292112253883237e235Q,
+ 0.6917786472619488492228198283114910358867e237Q,
+ 0.9615723196941089004197195613529725398826e239Q,
+ 0.1346201247571752460587607385894161555836e242Q,
+ 0.1898143759076170969428526414110767793728e244Q,
+ 0.2695364137888162776588507508037290267094e246Q,
+ 0.3854370717180072770521565736493325081944e248Q,
+ 0.5550293832739304789551054660550388118e250Q,
+ 0.80479260574719919448490292577980627711e252Q,
+ 0.1174997204390910823947958271638517164581e255Q,
+ 0.1727245890454638911203498659308620231933e257Q,
+ 0.2556323917872865588581178015776757943262e259Q,
+ 0.380892263763056972698595524350736933546e261Q,
+ 0.571338395644585459047893286526105400319e263Q,
+ 0.8627209774233240431623188626544191544816e265Q,
+ 0.1311335885683452545606724671234717114812e268Q,
+ 0.2006343905095682394778288746989117185662e270Q,
+ 0.308976961384735088795856467036324046592e272Q,
+ 0.4789142901463393876335775239063022722176e274Q,
+ 0.7471062926282894447083809372938315446595e276Q,
+ 0.1172956879426414428192158071551315525115e279Q,
+ 0.1853271869493734796543609753051078529682e281Q,
+ 0.2946702272495038326504339507351214862195e283Q,
+ 0.4714723635992061322406943211761943779512e285Q,
+ 0.7590705053947218729075178570936729485014e287Q,
+ 0.1229694218739449434110178928491750176572e290Q,
+ 0.2004401576545302577599591653441552787813e292Q,
+ 0.3287218585534296227263330311644146572013e294Q,
+ 0.5423910666131588774984495014212841843822e296Q,
+ 0.9003691705778437366474261723593317460744e298Q,
+ 0.1503616514864999040201201707840084015944e301Q,
+ 0.2526075744973198387538018869171341146786e303Q,
+ 0.4269068009004705274939251888899566538069e305Q,
+ 0.7257415615307998967396728211129263114717e307Q,
+ } };
+
+ return factorials[i];
+}
+
+template <>
+struct max_factorial<BOOST_MATH_FLOAT128_TYPE>
+{
+ BOOST_STATIC_CONSTANT(unsigned, value = 170);
+};
+
+#endif
+
template <>
inline double unchecked_factorial<double>(unsigned i BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(double))
{
@@ -279,6 +471,8 @@ struct max_factorial<double>
value = ::boost::math::max_factorial<long double>::value);
};
+#ifndef BOOST_MATH_NO_LEXICAL_CAST
+
template <class T>
inline T unchecked_factorial(unsigned i BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(T))
{
@@ -403,6 +597,22 @@ struct max_factorial
BOOST_STATIC_CONSTANT(unsigned, value = 100);
};
+#else // BOOST_MATH_NO_LEXICAL_CAST
+
+template <class T>
+inline T unchecked_factorial(unsigned i BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(T))
+{
+ return 1;
+}
+
+template <class T>
+struct max_factorial
+{
+ BOOST_STATIC_CONSTANT(unsigned, value = 0);
+};
+
+#endif
+
#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
template <class T>
const unsigned max_factorial<T>::value;
diff --git a/boost/math/special_functions/digamma.hpp b/boost/math/special_functions/digamma.hpp
index 1268b64dc9..785cd75c5e 100644
--- a/boost/math/special_functions/digamma.hpp
+++ b/boost/math/special_functions/digamma.hpp
@@ -10,6 +10,7 @@
#pragma once
#endif
+#include <boost/math/special_functions/math_fwd.hpp>
#include <boost/math/tools/rational.hpp>
#include <boost/math/tools/promotion.hpp>
#include <boost/math/policies/error_handling.hpp>
@@ -180,7 +181,7 @@ T digamma_imp_1_2(T x, const mpl::int_<0>*)
BOOST_MATH_BIG_CONSTANT(T, 113, -0.20327832297631728077731148515093164955e-6)
};
static const T Q[] = {
- 1,
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.6210924610812025425088411043163287646),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.6850757078559596612621337395886392594),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.4320913706209965531250495490639289418),
@@ -236,7 +237,7 @@ T digamma_imp_1_2(T x, const mpl::int_<64>*)
BOOST_MATH_BIG_CONSTANT(T, 64, -0.00289268368333918761452)
};
static const T Q[] = {
- 1,
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 64, 2.1195759927055347547),
BOOST_MATH_BIG_CONSTANT(T, 64, 1.54350554664961128724),
BOOST_MATH_BIG_CONSTANT(T, 64, 0.486986018231042975162),
@@ -286,7 +287,7 @@ T digamma_imp_1_2(T x, const mpl::int_<53>*)
BOOST_MATH_BIG_CONSTANT(T, 53, -0.0020713321167745952)
};
static const T Q[] = {
- BOOST_MATH_BIG_CONSTANT(T, 53, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 53, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 53, 2.0767117023730469),
BOOST_MATH_BIG_CONSTANT(T, 53, 1.4606242909763515),
BOOST_MATH_BIG_CONSTANT(T, 53, 0.43593529692665969),
@@ -356,7 +357,7 @@ T digamma_imp(T x, const Tag* t, const Policy& pol)
//
// Check for negative arguments and use reflection:
//
- if(x < 0)
+ if(x <= -1)
{
// Reflect:
x = 1 - x;
@@ -376,6 +377,8 @@ T digamma_imp(T x, const Tag* t, const Policy& pol)
}
result = constants::pi<T>() / tan(constants::pi<T>() * remainder);
}
+ if(x == 0)
+ return policies::raise_pole_error<T>("boost::math::digamma<%1%>(%1%)", 0, x, pol);
//
// If we're above the lower-limit for the
// asymptotic expansion then use it:
@@ -397,9 +400,9 @@ T digamma_imp(T x, const Tag* t, const Policy& pol)
//
// If x < 1 use recurrance to shift to > 1:
//
- if(x < 1)
+ while(x < 1)
{
- result = -1/x;
+ result -= 1/x;
x += 1;
}
result += digamma_imp_1_2(x, t);
diff --git a/boost/math/special_functions/ellint_1.hpp b/boost/math/special_functions/ellint_1.hpp
index 469f4bd01a..da16bc6f26 100644
--- a/boost/math/special_functions/ellint_1.hpp
+++ b/boost/math/special_functions/ellint_1.hpp
@@ -18,10 +18,12 @@
#pragma once
#endif
+#include <boost/math/special_functions/math_fwd.hpp>
#include <boost/math/special_functions/ellint_rf.hpp>
#include <boost/math/constants/constants.hpp>
#include <boost/math/policies/error_handling.hpp>
#include <boost/math/tools/workaround.hpp>
+#include <boost/math/special_functions/round.hpp>
// Elliptic integrals (complete and incomplete) of the first kind
// Carlson, Numerische Mathematik, vol 33, 1 (1979)
@@ -88,16 +90,16 @@ T ellint_f_imp(T phi, T k, const Policy& pol)
// so rewritten to use fmod instead:
//
BOOST_MATH_INSTRUMENT_CODE("pi/2 = " << constants::pi<T>() / 2);
- T rphi = boost::math::tools::fmod_workaround(phi, T(constants::pi<T>() / 2));
+ T rphi = boost::math::tools::fmod_workaround(phi, T(constants::half_pi<T>()));
BOOST_MATH_INSTRUMENT_VARIABLE(rphi);
- T m = floor((2 * phi) / constants::pi<T>());
+ T m = boost::math::round((phi - rphi) / constants::half_pi<T>());
BOOST_MATH_INSTRUMENT_VARIABLE(m);
int s = 1;
if(boost::math::tools::fmod_workaround(m, T(2)) > 0.5)
{
m += 1;
s = -1;
- rphi = constants::pi<T>() / 2 - rphi;
+ rphi = constants::half_pi<T>() - rphi;
BOOST_MATH_INSTRUMENT_VARIABLE(rphi);
}
T sinp = sin(rphi);
diff --git a/boost/math/special_functions/ellint_2.hpp b/boost/math/special_functions/ellint_2.hpp
index 85eca6cde7..72caf3eb11 100644
--- a/boost/math/special_functions/ellint_2.hpp
+++ b/boost/math/special_functions/ellint_2.hpp
@@ -18,11 +18,13 @@
#pragma once
#endif
+#include <boost/math/special_functions/math_fwd.hpp>
#include <boost/math/special_functions/ellint_rf.hpp>
#include <boost/math/special_functions/ellint_rd.hpp>
#include <boost/math/constants/constants.hpp>
#include <boost/math/policies/error_handling.hpp>
#include <boost/math/tools/workaround.hpp>
+#include <boost/math/special_functions/round.hpp>
// Elliptic integrals (complete and incomplete) of the second kind
// Carlson, Numerische Mathematik, vol 33, 1 (1979)
@@ -74,14 +76,14 @@ T ellint_e_imp(T phi, T k, const Policy& pol)
// but that fails if T has more digits than a long long,
// so rewritten to use fmod instead:
//
- T rphi = boost::math::tools::fmod_workaround(phi, T(constants::pi<T>() / 2));
- T m = floor((2 * phi) / constants::pi<T>());
+ T rphi = boost::math::tools::fmod_workaround(phi, T(constants::half_pi<T>()));
+ T m = boost::math::round((phi - rphi) / constants::half_pi<T>());
int s = 1;
if(boost::math::tools::fmod_workaround(m, T(2)) > 0.5)
{
m += 1;
s = -1;
- rphi = constants::pi<T>() / 2 - rphi;
+ rphi = constants::half_pi<T>() - rphi;
}
T sinp = sin(rphi);
T cosp = cos(rphi);
diff --git a/boost/math/special_functions/ellint_3.hpp b/boost/math/special_functions/ellint_3.hpp
index f63bb2d4b0..ac7e68c17f 100644
--- a/boost/math/special_functions/ellint_3.hpp
+++ b/boost/math/special_functions/ellint_3.hpp
@@ -18,6 +18,7 @@
#pragma once
#endif
+#include <boost/math/special_functions/math_fwd.hpp>
#include <boost/math/special_functions/ellint_rf.hpp>
#include <boost/math/special_functions/ellint_rj.hpp>
#include <boost/math/special_functions/ellint_1.hpp>
@@ -26,6 +27,7 @@
#include <boost/math/constants/constants.hpp>
#include <boost/math/policies/error_handling.hpp>
#include <boost/math/tools/workaround.hpp>
+#include <boost/math/special_functions/round.hpp>
// Elliptic integrals (complete and incomplete) of the third kind
// Carlson, Numerische Mathematik, vol 33, 1 (1979)
@@ -182,14 +184,14 @@ T ellint_pi_imp(T v, T phi, T k, T vc, const Policy& pol)
}
else
{
- T rphi = boost::math::tools::fmod_workaround(T(fabs(phi)), T(constants::pi<T>() / 2));
- T m = floor((2 * fabs(phi)) / constants::pi<T>());
+ T rphi = boost::math::tools::fmod_workaround(T(fabs(phi)), T(constants::half_pi<T>()));
+ T m = boost::math::round((fabs(phi) - rphi) / constants::half_pi<T>());
int sign = 1;
if(boost::math::tools::fmod_workaround(m, T(2)) > 0.5)
{
m += 1;
sign = -1;
- rphi = constants::pi<T>() / 2 - rphi;
+ rphi = constants::half_pi<T>() - rphi;
}
T sinp = sin(rphi);
T cosp = cos(rphi);
diff --git a/boost/math/special_functions/ellint_rj.hpp b/boost/math/special_functions/ellint_rj.hpp
index 1ecca753a4..8a242f06a4 100644
--- a/boost/math/special_functions/ellint_rj.hpp
+++ b/boost/math/special_functions/ellint_rj.hpp
@@ -91,7 +91,7 @@ T ellint_rj_imp(T x, T y, T z, T p, const Policy& pol)
BOOST_ASSERT(pmy >= 0);
- T p = pmy + y;
+ p = pmy + y;
value = boost::math::ellint_rj(x, y, z, p, pol);
value *= pmy;
value -= 3 * boost::math::ellint_rf(x, y, z, pol);
diff --git a/boost/math/special_functions/erf.hpp b/boost/math/special_functions/erf.hpp
index e67332a61a..f7f75b0bc7 100644
--- a/boost/math/special_functions/erf.hpp
+++ b/boost/math/special_functions/erf.hpp
@@ -226,7 +226,7 @@ T erf_imp(T z, bool invert, const Policy& pol, const mpl::int_<53>& t)
BOOST_MATH_BIG_CONSTANT(T, 53, -0.000322780120964605683831),
};
static const T Q[] = {
- 1L,
+ BOOST_MATH_BIG_CONSTANT(T, 53, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 53, 0.455004033050794024546),
BOOST_MATH_BIG_CONSTANT(T, 53, 0.0875222600142252549554),
BOOST_MATH_BIG_CONSTANT(T, 53, 0.00858571925074406212772),
@@ -258,7 +258,7 @@ T erf_imp(T z, bool invert, const Policy& pol, const mpl::int_<53>& t)
BOOST_MATH_BIG_CONSTANT(T, 53, 0.00180424538297014223957),
};
static const T Q[] = {
- 1L,
+ BOOST_MATH_BIG_CONSTANT(T, 53, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 53, 1.84759070983002217845),
BOOST_MATH_BIG_CONSTANT(T, 53, 1.42628004845511324508),
BOOST_MATH_BIG_CONSTANT(T, 53, 0.578052804889902404909),
@@ -266,8 +266,14 @@ T erf_imp(T z, bool invert, const Policy& pol, const mpl::int_<53>& t)
BOOST_MATH_BIG_CONSTANT(T, 53, 0.0113385233577001411017),
BOOST_MATH_BIG_CONSTANT(T, 53, 0.337511472483094676155e-5),
};
+ BOOST_MATH_INSTRUMENT_VARIABLE(Y);
+ BOOST_MATH_INSTRUMENT_VARIABLE(P[0]);
+ BOOST_MATH_INSTRUMENT_VARIABLE(Q[0]);
+ BOOST_MATH_INSTRUMENT_VARIABLE(z);
result = Y + tools::evaluate_polynomial(P, T(z - 0.5)) / tools::evaluate_polynomial(Q, T(z - 0.5));
+ BOOST_MATH_INSTRUMENT_VARIABLE(result);
result *= exp(-z * z) / z;
+ BOOST_MATH_INSTRUMENT_VARIABLE(result);
}
else if(z < 2.5f)
{
@@ -285,7 +291,7 @@ T erf_imp(T z, bool invert, const Policy& pol, const mpl::int_<53>& t)
BOOST_MATH_BIG_CONSTANT(T, 53, 0.000235839115596880717416),
};
static const T Q[] = {
- BOOST_MATH_BIG_CONSTANT(T, 53, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 53, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 53, 1.53991494948552447182),
BOOST_MATH_BIG_CONSTANT(T, 53, 0.982403709157920235114),
BOOST_MATH_BIG_CONSTANT(T, 53, 0.325732924782444448493),
@@ -311,7 +317,7 @@ T erf_imp(T z, bool invert, const Policy& pol, const mpl::int_<53>& t)
BOOST_MATH_BIG_CONSTANT(T, 53, 0.113212406648847561139e-4),
};
static const T Q[] = {
- BOOST_MATH_BIG_CONSTANT(T, 53, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 53, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 53, 1.04217814166938418171),
BOOST_MATH_BIG_CONSTANT(T, 53, 0.442597659481563127003),
BOOST_MATH_BIG_CONSTANT(T, 53, 0.0958492726301061423444),
@@ -338,7 +344,7 @@ T erf_imp(T z, bool invert, const Policy& pol, const mpl::int_<53>& t)
BOOST_MATH_BIG_CONSTANT(T, 53, -2.8175401114513378771),
};
static const T Q[] = {
- BOOST_MATH_BIG_CONSTANT(T, 53, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 53, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 53, 2.79257750980575282228),
BOOST_MATH_BIG_CONSTANT(T, 53, 11.0567237927800161565),
BOOST_MATH_BIG_CONSTANT(T, 53, 15.930646027911794143),
@@ -422,7 +428,7 @@ T erf_imp(T z, bool invert, const Policy& pol, const mpl::int_<64>& t)
BOOST_MATH_BIG_CONSTANT(T, 64, -0.200305626366151877759e-4),
};
static const T Q[] = {
- BOOST_MATH_BIG_CONSTANT(T, 64, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 64, 0.455817300515875172439),
BOOST_MATH_BIG_CONSTANT(T, 64, 0.0916537354356241792007),
BOOST_MATH_BIG_CONSTANT(T, 64, 0.0102722652675910031202),
@@ -456,7 +462,7 @@ T erf_imp(T z, bool invert, const Policy& pol, const mpl::int_<64>& t)
BOOST_MATH_BIG_CONSTANT(T, 64, 0.266689068336295642561e-7),
};
static const T Q[] = {
- BOOST_MATH_BIG_CONSTANT(T, 64, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 64, 2.03237474985469469291),
BOOST_MATH_BIG_CONSTANT(T, 64, 1.78355454954969405222),
BOOST_MATH_BIG_CONSTANT(T, 64, 0.867940326293760578231),
@@ -484,7 +490,7 @@ T erf_imp(T z, bool invert, const Policy& pol, const mpl::int_<64>& t)
BOOST_MATH_BIG_CONSTANT(T, 64, 0.515917266698050027934e-4),
};
static const T Q[] = {
- BOOST_MATH_BIG_CONSTANT(T, 64, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 64, 1.71657861671930336344),
BOOST_MATH_BIG_CONSTANT(T, 64, 1.26409634824280366218),
BOOST_MATH_BIG_CONSTANT(T, 64, 0.512371437838969015941),
@@ -512,7 +518,7 @@ T erf_imp(T z, bool invert, const Policy& pol, const mpl::int_<64>& t)
BOOST_MATH_BIG_CONSTANT(T, 64, 0.189896043050331257262e-5),
};
static const T Q[] = {
- BOOST_MATH_BIG_CONSTANT(T, 64, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 64, 1.19352160185285642574),
BOOST_MATH_BIG_CONSTANT(T, 64, 0.603256964363454392857),
BOOST_MATH_BIG_CONSTANT(T, 64, 0.165411142458540585835),
@@ -542,7 +548,7 @@ T erf_imp(T z, bool invert, const Policy& pol, const mpl::int_<64>& t)
BOOST_MATH_BIG_CONSTANT(T, 64, -16.8865774499799676937),
};
static const T Q[] = {
- BOOST_MATH_BIG_CONSTANT(T, 64, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 64, 4.72948911186645394541),
BOOST_MATH_BIG_CONSTANT(T, 64, 23.6750543147695749212),
BOOST_MATH_BIG_CONSTANT(T, 64, 60.0021517335693186785),
@@ -630,7 +636,7 @@ T erf_imp(T z, bool invert, const Policy& pol, const mpl::int_<113>& t)
BOOST_MATH_BIG_CONSTANT(T, 113, -0.344448249920445916714548295433198544e-7),
};
static const T Q[] = {
- BOOST_MATH_BIG_CONSTANT(T, 113, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 113, 0.466542092785657604666906909196052522),
BOOST_MATH_BIG_CONSTANT(T, 113, 0.100005087012526447295176964142107611),
BOOST_MATH_BIG_CONSTANT(T, 113, 0.0128341535890117646540050072234142603),
@@ -668,7 +674,7 @@ T erf_imp(T z, bool invert, const Policy& pol, const mpl::int_<113>& t)
BOOST_MATH_BIG_CONSTANT(T, 113, 0.436544865032836914773944382339900079e-5),
};
static const T Q[] = {
- BOOST_MATH_BIG_CONSTANT(T, 113, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.47651182872457465043733800302427977),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.78706486002517996428836400245547955),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.87295924621659627926365005293130693),
@@ -703,7 +709,7 @@ T erf_imp(T z, bool invert, const Policy& pol, const mpl::int_<113>& t)
BOOST_MATH_BIG_CONSTANT(T, 113, 0.133166058052466262415271732172490045e-5),
};
static const T Q[] = {
- BOOST_MATH_BIG_CONSTANT(T, 113, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.32970330146503867261275580968135126),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.46325715420422771961250513514928746),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.55307882560757679068505047390857842),
@@ -737,7 +743,7 @@ T erf_imp(T z, bool invert, const Policy& pol, const mpl::int_<113>& t)
BOOST_MATH_BIG_CONSTANT(T, 113, 0.312857043762117596999398067153076051e-6),
};
static const T Q[] = {
- BOOST_MATH_BIG_CONSTANT(T, 113, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.13506082409097783827103424943508554),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.06399257267556230937723190496806215),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.18678481279932541314830499880691109),
@@ -772,7 +778,7 @@ T erf_imp(T z, bool invert, const Policy& pol, const mpl::int_<113>& t)
BOOST_MATH_BIG_CONSTANT(T, 113, 0.676586625472423508158937481943649258e-7),
};
static const T Q[] = {
- BOOST_MATH_BIG_CONSTANT(T, 113, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.93669171363907292305550231764920001),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.69468476144051356810672506101377494),
BOOST_MATH_BIG_CONSTANT(T, 113, 0.880023580986436640372794392579985511),
@@ -805,7 +811,7 @@ T erf_imp(T z, bool invert, const Policy& pol, const mpl::int_<113>& t)
BOOST_MATH_BIG_CONSTANT(T, 113, 0.971120407556888763695313774578711839e-7),
};
static const T Q[] = {
- BOOST_MATH_BIG_CONSTANT(T, 113, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.59911256167540354915906501335919317),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.136006830764025173864831382946934),
BOOST_MATH_BIG_CONSTANT(T, 113, 0.468565867990030871678574840738423023),
@@ -839,7 +845,7 @@ T erf_imp(T z, bool invert, const Policy& pol, const mpl::int_<113>& t)
BOOST_MATH_BIG_CONSTANT(T, 113, 0.156161469668275442569286723236274457e-9),
};
static const T Q[] = {
- BOOST_MATH_BIG_CONSTANT(T, 113, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.52955245103668419479878456656709381),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.06263944820093830054635017117417064),
BOOST_MATH_BIG_CONSTANT(T, 113, 0.441684612681607364321013134378316463),
@@ -874,7 +880,7 @@ T erf_imp(T z, bool invert, const Policy& pol, const mpl::int_<113>& t)
BOOST_MATH_BIG_CONSTANT(T, 113, 0.673002744115866600294723141176820155e-10),
};
static const T Q[] = {
- BOOST_MATH_BIG_CONSTANT(T, 113, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.12843690320861239631195353379313367),
BOOST_MATH_BIG_CONSTANT(T, 113, 0.569900657061622955362493442186537259),
BOOST_MATH_BIG_CONSTANT(T, 113, 0.169094404206844928112348730277514273),
@@ -908,7 +914,7 @@ T erf_imp(T z, bool invert, const Policy& pol, const mpl::int_<113>& t)
BOOST_MATH_BIG_CONSTANT(T, 113, 0.119735694018906705225870691331543806e-8),
};
static const T Q[] = {
- BOOST_MATH_BIG_CONSTANT(T, 113, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.69889613396167354566098060039549882),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.28824647372749624464956031163282674),
BOOST_MATH_BIG_CONSTANT(T, 113, 0.572297795434934493541628008224078717),
@@ -944,7 +950,7 @@ T erf_imp(T z, bool invert, const Policy& pol, const mpl::int_<113>& t)
BOOST_MATH_BIG_CONSTANT(T, 113, -60.0530577077238079968843307523245547),
};
static const T Q[] = {
- BOOST_MATH_BIG_CONSTANT(T, 113, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 113, 3.49040448075464744191022350947892036),
BOOST_MATH_BIG_CONSTANT(T, 113, 34.3563592467165971295915749548313227),
BOOST_MATH_BIG_CONSTANT(T, 113, 84.4993232033879023178285731843850461),
diff --git a/boost/math/special_functions/expint.hpp b/boost/math/special_functions/expint.hpp
index 1c86d282fa..c26420db9e 100644
--- a/boost/math/special_functions/expint.hpp
+++ b/boost/math/special_functions/expint.hpp
@@ -15,6 +15,7 @@
#include <boost/math/tools/fraction.hpp>
#include <boost/math/tools/series.hpp>
#include <boost/math/policies/error_handling.hpp>
+#include <boost/math/special_functions/math_fwd.hpp>
#include <boost/math/special_functions/digamma.hpp>
#include <boost/math/special_functions/log1p.hpp>
#include <boost/math/special_functions/pow.hpp>
@@ -55,7 +56,7 @@ T expint_1_rational(const T& z, const mpl::int_<53>&)
BOOST_MATH_BIG_CONSTANT(T, 53, -0.000111507792921197858394)
};
static const T Q[6] = {
- BOOST_MATH_BIG_CONSTANT(T, 53, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 53, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 53, 0.37091387659397013215),
BOOST_MATH_BIG_CONSTANT(T, 53, 0.056770677104207528384),
BOOST_MATH_BIG_CONSTANT(T, 53, 0.00427347600017103698101),
@@ -84,7 +85,7 @@ T expint_1_rational(const T& z, const mpl::int_<53>&)
BOOST_MATH_BIG_CONSTANT(T, 53, -1185.45720315201027667)
};
static const T Q[12] = {
- BOOST_MATH_BIG_CONSTANT(T, 53, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 53, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 53, 45.3058660811801465927),
BOOST_MATH_BIG_CONSTANT(T, 53, 809.193214954550328455),
BOOST_MATH_BIG_CONSTANT(T, 53, 7417.37624454689546708),
@@ -130,7 +131,7 @@ T expint_1_rational(const T& z, const mpl::int_<64>&)
BOOST_MATH_BIG_CONSTANT(T, 64, 0.30853660894346057053e-4)
};
static const T Q[7] = {
- BOOST_MATH_BIG_CONSTANT(T, 64, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 64, 0.317978365797784100273),
BOOST_MATH_BIG_CONSTANT(T, 64, 0.0393622602554758722511),
BOOST_MATH_BIG_CONSTANT(T, 64, 0.00204062029115966323229),
@@ -163,7 +164,7 @@ T expint_1_rational(const T& z, const mpl::int_<64>&)
BOOST_MATH_BIG_CONSTANT(T, 64, -2038.82870680427258038)
};
static const T Q[14] = {
- BOOST_MATH_BIG_CONSTANT(T, 64, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 64, 64.1517806091379399478),
BOOST_MATH_BIG_CONSTANT(T, 64, 1690.76044393722763785),
BOOST_MATH_BIG_CONSTANT(T, 64, 24035.9534033068949426),
@@ -215,7 +216,7 @@ T expint_1_rational(const T& z, const mpl::int_<113>&)
BOOST_MATH_BIG_CONSTANT(T, 113, -0.340500302777838063940402160594523429e-9)
};
static const T Q[10] = {
- BOOST_MATH_BIG_CONSTANT(T, 113, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 113, 0.426568827778942588160423015589537302),
BOOST_MATH_BIG_CONSTANT(T, 113, 0.0841384046470893490592450881447510148),
BOOST_MATH_BIG_CONSTANT(T, 113, 0.0100557215850668029618957359471132995),
@@ -256,7 +257,7 @@ T expint_1_rational(const T& z, const mpl::int_<113>&)
BOOST_MATH_BIG_CONSTANT(T, 113, -1.51492042209561411434644938098833499)
};
static const T Q[16] = {
- BOOST_MATH_BIG_CONSTANT(T, 113, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 113, 46.734521442032505570517810766704587),
BOOST_MATH_BIG_CONSTANT(T, 113, 908.694714348462269000247450058595655),
BOOST_MATH_BIG_CONSTANT(T, 113, 9701.76053033673927362784882748513195),
@@ -305,7 +306,7 @@ T expint_1_rational(const T& z, const mpl::int_<113>&)
BOOST_MATH_BIG_CONSTANT(T, 113, -68028222642.1941480871395695677675137)
};
static const T Q[20] = {
- BOOST_MATH_BIG_CONSTANT(T, 113, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 113, 168.542326331163836642960118190147311),
BOOST_MATH_BIG_CONSTANT(T, 113, 12535.7237814586576783518249115343619),
BOOST_MATH_BIG_CONSTANT(T, 113, 544891.263372016404143120911148640627),
@@ -541,7 +542,7 @@ T expint_i_imp(T z, const Policy& pol, const mpl::int_<53>& tag)
BOOST_MATH_BIG_CONSTANT(T, 53, 0.2777056254402008721e-6)
};
static const T Q[8] = {
- BOOST_MATH_BIG_CONSTANT(T, 53, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 53, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 53, -1.17090412365413911947),
BOOST_MATH_BIG_CONSTANT(T, 53, 0.62215109846016746276),
BOOST_MATH_BIG_CONSTANT(T, 53, -0.195114782069495403315),
@@ -563,7 +564,7 @@ T expint_i_imp(T z, const Policy& pol, const mpl::int_<53>& tag)
result *= t;
if(fabs(t) < 0.1)
{
- result += boost::math::log1p(t / r);
+ result += boost::math::log1p(t / r, pol);
}
else
{
@@ -587,7 +588,7 @@ T expint_i_imp(T z, const Policy& pol, const mpl::int_<53>& tag)
BOOST_MATH_BIG_CONSTANT(T, 53, -0.396487648924804510056e-5)
};
static const T Q[8] = {
- BOOST_MATH_BIG_CONSTANT(T, 53, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 53, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 53, 0.744625566823272107711),
BOOST_MATH_BIG_CONSTANT(T, 53, 0.329061095011767059236),
BOOST_MATH_BIG_CONSTANT(T, 53, 0.100128624977313872323),
@@ -621,7 +622,7 @@ T expint_i_imp(T z, const Policy& pol, const mpl::int_<53>& tag)
BOOST_MATH_BIG_CONSTANT(T, 53, -0.138652200349182596186e-4)
};
static const T Q[9] = {
- BOOST_MATH_BIG_CONSTANT(T, 53, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 53, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 53, 1.97017214039061194971),
BOOST_MATH_BIG_CONSTANT(T, 53, 1.86232465043073157508),
BOOST_MATH_BIG_CONSTANT(T, 53, 1.09601437090337519977),
@@ -657,7 +658,7 @@ T expint_i_imp(T z, const Policy& pol, const mpl::int_<53>& tag)
BOOST_MATH_BIG_CONSTANT(T, 53, -0.113161784705911400295e-9)
};
static const T Q[9] = {
- BOOST_MATH_BIG_CONSTANT(T, 53, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 53, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 53, 2.84354408840148561131),
BOOST_MATH_BIG_CONSTANT(T, 53, 3.6599610090072393012),
BOOST_MATH_BIG_CONSTANT(T, 53, 2.75088464344293083595),
@@ -686,7 +687,7 @@ T expint_i_imp(T z, const Policy& pol, const mpl::int_<53>& tag)
BOOST_MATH_BIG_CONSTANT(T, 53, -38703.1431362056714134)
};
static const T Q[7] = {
- BOOST_MATH_BIG_CONSTANT(T, 53, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 53, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 53, 61.9733592849439884145),
BOOST_MATH_BIG_CONSTANT(T, 53, -2354.56211323420194283),
BOOST_MATH_BIG_CONSTANT(T, 53, 22329.1459489893079041),
@@ -757,7 +758,7 @@ T expint_i_imp(T z, const Policy& pol, const mpl::int_<64>& tag)
BOOST_MATH_BIG_CONSTANT(T, 64, 0.177833045143692498221e-7)
};
static const T Q[9] = {
- BOOST_MATH_BIG_CONSTANT(T, 64, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 64, -1.20352377969742325748),
BOOST_MATH_BIG_CONSTANT(T, 64, 0.66707904942606479811),
BOOST_MATH_BIG_CONSTANT(T, 64, -0.223014531629140771914),
@@ -780,7 +781,7 @@ T expint_i_imp(T z, const Policy& pol, const mpl::int_<64>& tag)
result *= t;
if(fabs(t) < 0.1)
{
- result += boost::math::log1p(t / r);
+ result += boost::math::log1p(t / r, pol);
}
else
{
@@ -806,7 +807,7 @@ T expint_i_imp(T z, const Policy& pol, const mpl::int_<64>& tag)
BOOST_MATH_BIG_CONSTANT(T, 64, -0.377246883283337141444e-6)
};
static const T Q[10] = {
- BOOST_MATH_BIG_CONSTANT(T, 64, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 64, 1.08073635708902053767),
BOOST_MATH_BIG_CONSTANT(T, 64, 0.553681133533942532909),
BOOST_MATH_BIG_CONSTANT(T, 64, 0.176763647137553797451),
@@ -844,7 +845,7 @@ T expint_i_imp(T z, const Policy& pol, const mpl::int_<64>& tag)
BOOST_MATH_BIG_CONSTANT(T, 64, -0.252788029251437017959e-5)
};
static const T Q[10] = {
- BOOST_MATH_BIG_CONSTANT(T, 64, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 64, 2.00323265503572414261),
BOOST_MATH_BIG_CONSTANT(T, 64, 1.94688958187256383178),
BOOST_MATH_BIG_CONSTANT(T, 64, 1.19733638134417472296),
@@ -883,7 +884,7 @@ T expint_i_imp(T z, const Policy& pol, const mpl::int_<64>& tag)
BOOST_MATH_BIG_CONSTANT(T, 64, -0.533769629702262072175e-11)
};
static const T Q[9] = {
- BOOST_MATH_BIG_CONSTANT(T, 64, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 64, 3.13286733695729715455),
BOOST_MATH_BIG_CONSTANT(T, 64, 4.49281223045653491929),
BOOST_MATH_BIG_CONSTANT(T, 64, 3.84900294427622911374),
@@ -921,7 +922,7 @@ T expint_i_imp(T z, const Policy& pol, const mpl::int_<64>& tag)
BOOST_MATH_BIG_CONSTANT(T, 64, 137839271.592778020028)
};
static const T Q[9] = {
- BOOST_MATH_BIG_CONSTANT(T, 64, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 64, 27.2103343964943718802),
BOOST_MATH_BIG_CONSTANT(T, 64, -8785.48528692879413676),
BOOST_MATH_BIG_CONSTANT(T, 64, 397530.290000322626766),
@@ -962,8 +963,8 @@ T expint_i_imp(T z, const Policy& pol, const mpl::int_<64>& tag)
return result;
}
-template <class T>
-void expint_i_imp_113a(T& result, const T& z)
+template <class T, class Policy>
+void expint_i_imp_113a(T& result, const T& z, const Policy& pol)
{
BOOST_MATH_STD_USING
// Maximum Deviation Found: 1.230e-36
@@ -989,7 +990,7 @@ void expint_i_imp_113a(T& result, const T& z)
BOOST_MATH_BIG_CONSTANT(T, 113, 0.306243138978114692252817805327426657e-13)
};
static const T Q[15] = {
- BOOST_MATH_BIG_CONSTANT(T, 113, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 113, -1.40178870313943798705491944989231793),
BOOST_MATH_BIG_CONSTANT(T, 113, 0.943810968269701047641218856758605284),
BOOST_MATH_BIG_CONSTANT(T, 113, -0.405026631534345064600850391026113165),
@@ -1022,7 +1023,7 @@ void expint_i_imp_113a(T& result, const T& z)
result *= t;
if(fabs(t) < 0.1)
{
- result += boost::math::log1p(t / r);
+ result += boost::math::log1p(t / r, pol);
}
else
{
@@ -1057,7 +1058,7 @@ void expint_i_113b(T& result, const T& z)
BOOST_MATH_BIG_CONSTANT(T, 113, -0.384276705503357655108096065452950822e-12)
};
static const T Q[15] = {
- BOOST_MATH_BIG_CONSTANT(T, 113, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.58784732785354597996617046880946257),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.18550755302279446339364262338114098),
BOOST_MATH_BIG_CONSTANT(T, 113, 0.55598993549661368604527040349702836),
@@ -1110,7 +1111,7 @@ void expint_i_113c(T& result, const T& z)
BOOST_MATH_BIG_CONSTANT(T, 113, 0.869226483473172853557775877908693647e-15)
};
static const T Q[15] = {
- BOOST_MATH_BIG_CONSTANT(T, 113, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.23227220874479061894038229141871087),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.40221000361027971895657505660959863),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.65476320985936174728238416007084214),
@@ -1159,7 +1160,7 @@ void expint_i_113d(T& result, const T& z)
BOOST_MATH_BIG_CONSTANT(T, 113, -0.133141358866324100955927979606981328e-10)
};
static const T Q[14] = {
- BOOST_MATH_BIG_CONSTANT(T, 113, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.72490783907582654629537013560044682),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.44524329516800613088375685659759765),
BOOST_MATH_BIG_CONSTANT(T, 113, 0.778241785539308257585068744978050181),
@@ -1211,7 +1212,7 @@ void expint_i_113e(T& result, const T& z)
BOOST_MATH_BIG_CONSTANT(T, 113, -0.105428907085424234504608142258423505e-8)
};
static const T Q[16] = {
- BOOST_MATH_BIG_CONSTANT(T, 113, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 113, 3.17261315255467581204685605414005525),
BOOST_MATH_BIG_CONSTANT(T, 113, 4.85267952971640525245338392887217426),
BOOST_MATH_BIG_CONSTANT(T, 113, 4.74341914912439861451492872946725151),
@@ -1262,7 +1263,7 @@ void expint_i_113f(T& result, const T& z)
BOOST_MATH_BIG_CONSTANT(T, 113, -0.107839681938752337160494412638656696e-8)
};
static const T Q[12] = {
- BOOST_MATH_BIG_CONSTANT(T, 113, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.09913805456661084097134805151524958),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.07041755535439919593503171320431849),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.26406517226052371320416108604874734),
@@ -1308,7 +1309,7 @@ void expint_i_113g(T& result, const T& z)
BOOST_MATH_BIG_CONSTANT(T, 113, -0.720558173805289167524715527536874694e-7)
};
static const T Q[11] = {
- BOOST_MATH_BIG_CONSTANT(T, 113, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.95918362458402597039366979529287095),
BOOST_MATH_BIG_CONSTANT(T, 113, 3.96472247520659077944638411856748924),
BOOST_MATH_BIG_CONSTANT(T, 113, 3.15563251550528513747923714884142131),
@@ -1351,7 +1352,7 @@ void expint_i_113h(T& result, const T& z)
BOOST_MATH_BIG_CONSTANT(T, 113, -6758379.93672362080947905580906028645)
};
static const T Q[10] = {
- BOOST_MATH_BIG_CONSTANT(T, 113, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 113, -99.4868026047611434569541483506091713),
BOOST_MATH_BIG_CONSTANT(T, 113, 3879.67753690517114249705089803055473),
BOOST_MATH_BIG_CONSTANT(T, 113, -76495.82413252517165830203774900806),
@@ -1383,7 +1384,7 @@ T expint_i_imp(T z, const Policy& pol, const mpl::int_<113>& tag)
if(z <= 6)
{
- expint_i_imp_113a(result, z);
+ expint_i_imp_113a(result, z, pol);
}
else if (z <= 10)
{
@@ -1432,7 +1433,7 @@ T expint_i_imp(T z, const Policy& pol, const mpl::int_<113>& tag)
BOOST_MATH_BIG_CONSTANT(T, 113, 175864.614717440010942804684741336853)
};
static const T Q[9] = {
- BOOST_MATH_BIG_CONSTANT(T, 113, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 113, -65.6998869881600212224652719706425129),
BOOST_MATH_BIG_CONSTANT(T, 113, 1642.73850032324014781607859416890077),
BOOST_MATH_BIG_CONSTANT(T, 113, -19937.2610222467322481947237312818575),
diff --git a/boost/math/special_functions/expm1.hpp b/boost/math/special_functions/expm1.hpp
index 9ff2541fb1..7423dc5c81 100644
--- a/boost/math/special_functions/expm1.hpp
+++ b/boost/math/special_functions/expm1.hpp
@@ -151,8 +151,8 @@ T expm1_imp(T x, const mpl::int_<53>&, const P& pol)
return x;
static const float Y = 0.10281276702880859e1f;
- static const T n[] = { -0.28127670288085937e-1, 0.51278186299064534e0, -0.6310029069350198e-1, 0.11638457975729296e-1, -0.52143390687521003e-3, 0.21491399776965688e-4 };
- static const T d[] = { 1, -0.45442309511354755e0, 0.90850389570911714e-1, -0.10088963629815502e-1, 0.63003407478692265e-3, -0.17976570003654402e-4 };
+ static const T n[] = { static_cast<T>(-0.28127670288085937e-1), static_cast<T>(0.51278186299064534e0), static_cast<T>(-0.6310029069350198e-1), static_cast<T>(0.11638457975729296e-1), static_cast<T>(-0.52143390687521003e-3), static_cast<T>(0.21491399776965688e-4) };
+ static const T d[] = { 1, static_cast<T>(-0.45442309511354755e0), static_cast<T>(0.90850389570911714e-1), static_cast<T>(-0.10088963629815502e-1), static_cast<T>(0.63003407478692265e-3), static_cast<T>(-0.17976570003654402e-4) };
T result = x * Y + x * tools::evaluate_polynomial(n, x) / tools::evaluate_polynomial(d, x);
return result;
@@ -188,7 +188,7 @@ T expm1_imp(T x, const mpl::int_<64>&, const P& pol)
BOOST_MATH_BIG_CONSTANT(T, 64, -0.714539134024984593011e-6)
};
static const T d[] = {
- 1,
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 64, -0.461477618025562520389e0),
BOOST_MATH_BIG_CONSTANT(T, 64, 0.961237488025708540713e-1),
BOOST_MATH_BIG_CONSTANT(T, 64, -0.116483957658204450739e-1),
@@ -234,7 +234,7 @@ T expm1_imp(T x, const mpl::int_<113>&, const P& pol)
BOOST_MATH_BIG_CONSTANT(T, 113, 0.45261820069007790520447958280473183582e-10)
};
static const T d[] = {
- 1,
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 113, -0.45441264709074310514348137469214538853e0),
BOOST_MATH_BIG_CONSTANT(T, 113, 0.96827131936192217313133611655555298106e-1),
BOOST_MATH_BIG_CONSTANT(T, 113, -0.12745248725908178612540554584374876219e-1),
@@ -305,7 +305,7 @@ inline float expm1(float x, const policies::policy<>&){ return ::expm1f(x); }
inline long double expm1(long double x, const policies::policy<>&){ return ::expm1l(x); }
# endif
# else
-inline float expm1(float x, const policies::policy<>&){ return ::expm1(x); }
+inline float expm1(float x, const policies::policy<>&){ return static_cast<float>(::expm1(x)); }
# endif
inline double expm1(double x, const policies::policy<>&){ return ::expm1(x); }
#endif
diff --git a/boost/math/special_functions/factorials.hpp b/boost/math/special_functions/factorials.hpp
index f57147ebfa..de24642ac4 100644
--- a/boost/math/special_functions/factorials.hpp
+++ b/boost/math/special_functions/factorials.hpp
@@ -10,15 +10,14 @@
#pragma once
#endif
-#include <boost/math/special_functions/gamma.hpp>
#include <boost/math/special_functions/math_fwd.hpp>
+#include <boost/math/special_functions/gamma.hpp>
#include <boost/math/special_functions/detail/unchecked_factorial.hpp>
#include <boost/array.hpp>
#ifdef BOOST_MSVC
#pragma warning(push) // Temporary until lexical cast fixed.
#pragma warning(disable: 4127 4701)
#endif
-#include <boost/lexical_cast.hpp>
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
@@ -142,6 +141,18 @@ T rising_factorial_imp(T x, int n, const Policy& pol)
}
if(n == 0)
return 1;
+ if(x == 0)
+ {
+ if(n < 0)
+ return -boost::math::tgamma_delta_ratio(x + 1, static_cast<T>(-n), pol);
+ else
+ return 0;
+ }
+ if((x < 1) && (x + n < 0))
+ {
+ T val = boost::math::tgamma_delta_ratio(1 - x, static_cast<T>(-n), pol);
+ return (n & 1) ? -val : val;
+ }
//
// We don't optimise this for small n, because
// tgamma_delta_ratio is alreay optimised for that
@@ -155,7 +166,7 @@ inline T falling_factorial_imp(T x, unsigned n, const Policy& pol)
{
BOOST_STATIC_ASSERT(!boost::is_integral<T>::value);
BOOST_MATH_STD_USING // ADL of std names
- if(x == 0)
+ if((x == 0) && (n >= 0))
return 0;
if(x < 0)
{
@@ -167,7 +178,24 @@ inline T falling_factorial_imp(T x, unsigned n, const Policy& pol)
}
if(n == 0)
return 1;
- if(x < n-1)
+ if(x < 0.5f)
+ {
+ //
+ // 1 + x below will throw away digits, so split up calculation:
+ //
+ if(n > max_factorial<T>::value - 2)
+ {
+ // If the two end of the range are far apart we have a ratio of two very large
+ // numbers, split the calculation up into two blocks:
+ T t1 = x * boost::math::falling_factorial(x - 1, max_factorial<T>::value - 2);
+ T t2 = boost::math::falling_factorial(x - max_factorial<T>::value + 1, n - max_factorial<T>::value + 1);
+ if(tools::max_value<T>() / fabs(t1) < fabs(t2))
+ return boost::math::sign(t1) * boost::math::sign(t2) * policies::raise_overflow_error<T>("boost::math::falling_factorial<%1%>", 0, pol);
+ return t1 * t2;
+ }
+ return x * boost::math::falling_factorial(x - 1, n - 1);
+ }
+ if(x <= n - 1)
{
//
// x+1-n will be negative and tgamma_delta_ratio won't
diff --git a/boost/math/special_functions/fpclassify.hpp b/boost/math/special_functions/fpclassify.hpp
index 2abec5fa84..40f6e14ba5 100644
--- a/boost/math/special_functions/fpclassify.hpp
+++ b/boost/math/special_functions/fpclassify.hpp
@@ -37,13 +37,13 @@ the template is never instantiated.
a floating point type (float, double or long double) can be determined
at compile time, then the following algorithm is used:
- If all exponent bits, the flag bit (if there is one),
+ If all exponent bits, the flag bit (if there is one),
and all significand bits are 0, then the number is zero.
- If all exponent bits and the flag bit (if there is one) are 0,
+ If all exponent bits and the flag bit (if there is one) are 0,
and at least one significand bit is 1, then the number is subnormal.
- If all exponent bits are 1 and all significand bits are 0,
+ If all exponent bits are 1 and all significand bits are 0,
then the number is infinity.
If all exponent bits are 1 and at least one significand bit is 1,
@@ -56,7 +56,7 @@ at compile time, then the following algorithm is used:
Most formats have the structure
sign bit + exponent bits + significand bits.
-
+
A few have the structure
sign bit + exponent bits + flag bit + significand bits.
The flag bit is 0 for zero and subnormal numbers,
@@ -85,7 +85,7 @@ is used.
namespace std{ using ::abs; using ::fabs; }
#endif
-namespace boost{
+namespace boost{
//
// This must not be located in any namespace under boost::math
@@ -94,18 +94,28 @@ namespace boost{
//
namespace math_detail{
+#ifdef BOOST_MSVC
+#pragma warning(push)
+#pragma warning(disable:4800)
+#endif
+
template <class T>
inline bool is_nan_helper(T t, const boost::true_type&)
{
#ifdef isnan
return isnan(t);
#elif defined(BOOST_MATH_DISABLE_STD_FPCLASSIFY) || !defined(BOOST_HAS_FPCLASSIFY)
+ (void)t;
return false;
#else // BOOST_HAS_FPCLASSIFY
return (BOOST_FPCLASSIFY_PREFIX fpclassify(t) == (int)FP_NAN);
#endif
}
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
template <class T>
inline bool is_nan_helper(T, const boost::false_type&)
{
@@ -169,7 +179,7 @@ inline int fpclassify_imp BOOST_NO_MACRO_EXPAND(T t, const generic_tag<false>&)
if(std::numeric_limits<T>::is_specialized)
return fpclassify_imp(t, generic_tag<true>());
#endif
- //
+ //
// An unknown type with no numeric_limits support,
// so what are we supposed to do we do here?
//
@@ -178,7 +188,7 @@ inline int fpclassify_imp BOOST_NO_MACRO_EXPAND(T t, const generic_tag<false>&)
return t == 0 ? FP_ZERO : FP_NORMAL;
}
-template<class T>
+template<class T>
int fpclassify_imp BOOST_NO_MACRO_EXPAND(T x, ieee_copy_all_bits_tag)
{
typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
@@ -207,7 +217,7 @@ int fpclassify_imp BOOST_NO_MACRO_EXPAND(T x, ieee_copy_all_bits_tag)
return FP_NAN;
}
-template<class T>
+template<class T>
int fpclassify_imp BOOST_NO_MACRO_EXPAND(T x, ieee_copy_leading_bits_tag)
{
typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
@@ -215,7 +225,7 @@ int fpclassify_imp BOOST_NO_MACRO_EXPAND(T x, ieee_copy_leading_bits_tag)
BOOST_MATH_INSTRUMENT_VARIABLE(x);
BOOST_DEDUCED_TYPENAME traits::bits a;
- traits::get_bits(x,a);
+ traits::get_bits(x,a);
a &= traits::exponent | traits::flag | traits::significand;
if(a <= traits::significand) {
@@ -234,9 +244,8 @@ int fpclassify_imp BOOST_NO_MACRO_EXPAND(T x, ieee_copy_leading_bits_tag)
return FP_NAN;
}
-#if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && defined(BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY)
-template <>
-inline int fpclassify_imp<long double> BOOST_NO_MACRO_EXPAND(long double t, const native_tag&)
+#if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && (defined(BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY) || defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS))
+inline int fpclassify_imp BOOST_NO_MACRO_EXPAND(long double t, const native_tag&)
{
return boost::math::detail::fpclassify_imp(t, generic_tag<true>());
}
@@ -249,33 +258,51 @@ inline int fpclassify BOOST_NO_MACRO_EXPAND(T t)
{
typedef typename detail::fp_traits<T>::type traits;
typedef typename traits::method method;
+ typedef typename tools::promote_args_permissive<T>::type value_type;
#ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
if(std::numeric_limits<T>::is_specialized && detail::is_generic_tag_false(static_cast<method*>(0)))
- return detail::fpclassify_imp(t, detail::generic_tag<true>());
- return detail::fpclassify_imp(t, method());
+ return detail::fpclassify_imp(static_cast<value_type>(t), detail::generic_tag<true>());
+ return detail::fpclassify_imp(static_cast<value_type>(t), method());
#else
- return detail::fpclassify_imp(t, method());
+ return detail::fpclassify_imp(static_cast<value_type>(t), method());
#endif
}
+#ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
+template <>
+inline int fpclassify<long double> BOOST_NO_MACRO_EXPAND(long double t)
+{
+ typedef detail::fp_traits<long double>::type traits;
+ typedef traits::method method;
+ typedef long double value_type;
+#ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
+ if(std::numeric_limits<long double>::is_specialized && detail::is_generic_tag_false(static_cast<method*>(0)))
+ return detail::fpclassify_imp(static_cast<value_type>(t), detail::generic_tag<true>());
+ return detail::fpclassify_imp(static_cast<value_type>(t), method());
+#else
+ return detail::fpclassify_imp(static_cast<value_type>(t), method());
+#endif
+}
+#endif
+
namespace detail {
#ifdef BOOST_MATH_USE_STD_FPCLASSIFY
- template<class T>
+ template<class T>
inline bool isfinite_impl(T x, native_tag const&)
{
return (std::isfinite)(x);
}
#endif
- template<class T>
+ template<class T>
inline bool isfinite_impl(T x, generic_tag<true> const&)
{
return x >= -(std::numeric_limits<T>::max)()
&& x <= (std::numeric_limits<T>::max)();
}
- template<class T>
+ template<class T>
inline bool isfinite_impl(T x, generic_tag<false> const&)
{
#ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
@@ -286,7 +313,7 @@ namespace detail {
return true;
}
- template<class T>
+ template<class T>
inline bool isfinite_impl(T x, ieee_tag const&)
{
typedef BOOST_DEDUCED_TYPENAME detail::fp_traits<T>::type traits;
@@ -297,8 +324,7 @@ namespace detail {
}
#if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && defined(BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY)
-template <>
-inline bool isfinite_impl<long double> BOOST_NO_MACRO_EXPAND(long double t, const native_tag&)
+inline bool isfinite_impl BOOST_NO_MACRO_EXPAND(long double t, const native_tag&)
{
return boost::math::detail::isfinite_impl(t, generic_tag<true>());
}
@@ -306,28 +332,41 @@ inline bool isfinite_impl<long double> BOOST_NO_MACRO_EXPAND(long double t, cons
}
-template<class T>
+template<class T>
inline bool (isfinite)(T x)
{ //!< \brief return true if floating-point type t is finite.
typedef typename detail::fp_traits<T>::type traits;
typedef typename traits::method method;
- typedef typename boost::is_floating_point<T>::type fp_tag;
- return detail::isfinite_impl(x, method());
+ // typedef typename boost::is_floating_point<T>::type fp_tag;
+ typedef typename tools::promote_args_permissive<T>::type value_type;
+ return detail::isfinite_impl(static_cast<value_type>(x), method());
}
+#ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
+template<>
+inline bool (isfinite)(long double x)
+{ //!< \brief return true if floating-point type t is finite.
+ typedef detail::fp_traits<long double>::type traits;
+ typedef traits::method method;
+ //typedef boost::is_floating_point<long double>::type fp_tag;
+ typedef long double value_type;
+ return detail::isfinite_impl(static_cast<value_type>(x), method());
+}
+#endif
+
//------------------------------------------------------------------------------
namespace detail {
#ifdef BOOST_MATH_USE_STD_FPCLASSIFY
- template<class T>
+ template<class T>
inline bool isnormal_impl(T x, native_tag const&)
{
return (std::isnormal)(x);
}
#endif
- template<class T>
+ template<class T>
inline bool isnormal_impl(T x, generic_tag<true> const&)
{
if(x < 0) x = -x;
@@ -335,7 +374,7 @@ namespace detail {
&& x <= (std::numeric_limits<T>::max)();
}
- template<class T>
+ template<class T>
inline bool isnormal_impl(T x, generic_tag<false> const&)
{
#ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
@@ -345,7 +384,7 @@ namespace detail {
return !(x == 0);
}
- template<class T>
+ template<class T>
inline bool isnormal_impl(T x, ieee_tag const&)
{
typedef BOOST_DEDUCED_TYPENAME detail::fp_traits<T>::type traits;
@@ -356,8 +395,7 @@ namespace detail {
}
#if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && defined(BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY)
-template <>
-inline bool isnormal_impl<long double> BOOST_NO_MACRO_EXPAND(long double t, const native_tag&)
+inline bool isnormal_impl BOOST_NO_MACRO_EXPAND(long double t, const native_tag&)
{
return boost::math::detail::isnormal_impl(t, generic_tag<true>());
}
@@ -365,37 +403,50 @@ inline bool isnormal_impl<long double> BOOST_NO_MACRO_EXPAND(long double t, cons
}
-template<class T>
+template<class T>
inline bool (isnormal)(T x)
{
typedef typename detail::fp_traits<T>::type traits;
typedef typename traits::method method;
- typedef typename boost::is_floating_point<T>::type fp_tag;
- return detail::isnormal_impl(x, method());
+ //typedef typename boost::is_floating_point<T>::type fp_tag;
+ typedef typename tools::promote_args_permissive<T>::type value_type;
+ return detail::isnormal_impl(static_cast<value_type>(x), method());
}
+#ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
+template<>
+inline bool (isnormal)(long double x)
+{
+ typedef detail::fp_traits<long double>::type traits;
+ typedef traits::method method;
+ //typedef boost::is_floating_point<long double>::type fp_tag;
+ typedef long double value_type;
+ return detail::isnormal_impl(static_cast<value_type>(x), method());
+}
+#endif
+
//------------------------------------------------------------------------------
namespace detail {
#ifdef BOOST_MATH_USE_STD_FPCLASSIFY
- template<class T>
+ template<class T>
inline bool isinf_impl(T x, native_tag const&)
{
return (std::isinf)(x);
}
#endif
- template<class T>
+ template<class T>
inline bool isinf_impl(T x, generic_tag<true> const&)
{
(void)x; // in case the compiler thinks that x is unused because std::numeric_limits<T>::has_infinity is false
- return std::numeric_limits<T>::has_infinity
+ return std::numeric_limits<T>::has_infinity
&& ( x == std::numeric_limits<T>::infinity()
|| x == -std::numeric_limits<T>::infinity());
}
- template<class T>
+ template<class T>
inline bool isinf_impl(T x, generic_tag<false> const&)
{
#ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
@@ -406,7 +457,7 @@ namespace detail {
return false;
}
- template<class T>
+ template<class T>
inline bool isinf_impl(T x, ieee_copy_all_bits_tag const&)
{
typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
@@ -417,7 +468,7 @@ namespace detail {
return a == traits::exponent;
}
- template<class T>
+ template<class T>
inline bool isinf_impl(T x, ieee_copy_leading_bits_tag const&)
{
typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
@@ -433,8 +484,7 @@ namespace detail {
}
#if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && defined(BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY)
-template <>
-inline bool isinf_impl<long double> BOOST_NO_MACRO_EXPAND(long double t, const native_tag&)
+inline bool isinf_impl BOOST_NO_MACRO_EXPAND(long double t, const native_tag&)
{
return boost::math::detail::isinf_impl(t, generic_tag<true>());
}
@@ -442,28 +492,41 @@ inline bool isinf_impl<long double> BOOST_NO_MACRO_EXPAND(long double t, const n
} // namespace detail
-template<class T>
+template<class T>
inline bool (isinf)(T x)
{
typedef typename detail::fp_traits<T>::type traits;
typedef typename traits::method method;
- typedef typename boost::is_floating_point<T>::type fp_tag;
- return detail::isinf_impl(x, method());
+ // typedef typename boost::is_floating_point<T>::type fp_tag;
+ typedef typename tools::promote_args_permissive<T>::type value_type;
+ return detail::isinf_impl(static_cast<value_type>(x), method());
}
+#ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
+template<>
+inline bool (isinf)(long double x)
+{
+ typedef detail::fp_traits<long double>::type traits;
+ typedef traits::method method;
+ //typedef boost::is_floating_point<long double>::type fp_tag;
+ typedef long double value_type;
+ return detail::isinf_impl(static_cast<value_type>(x), method());
+}
+#endif
+
//------------------------------------------------------------------------------
namespace detail {
#ifdef BOOST_MATH_USE_STD_FPCLASSIFY
- template<class T>
+ template<class T>
inline bool isnan_impl(T x, native_tag const&)
{
return (std::isnan)(x);
}
#endif
- template<class T>
+ template<class T>
inline bool isnan_impl(T x, generic_tag<true> const&)
{
return std::numeric_limits<T>::has_infinity
@@ -471,7 +534,7 @@ namespace detail {
: x != x;
}
- template<class T>
+ template<class T>
inline bool isnan_impl(T x, generic_tag<false> const&)
{
#ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
@@ -482,7 +545,7 @@ namespace detail {
return false;
}
- template<class T>
+ template<class T>
inline bool isnan_impl(T x, ieee_copy_all_bits_tag const&)
{
typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
@@ -493,7 +556,7 @@ namespace detail {
return a > traits::exponent;
}
- template<class T>
+ template<class T>
inline bool isnan_impl(T x, ieee_copy_leading_bits_tag const&)
{
typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
@@ -512,11 +575,12 @@ namespace detail {
} // namespace detail
-template<class T> bool (isnan)(T x)
+template<class T>
+inline bool (isnan)(T x)
{ //!< \brief return true if floating-point type t is NaN (Not A Number).
typedef typename detail::fp_traits<T>::type traits;
typedef typename traits::method method;
- typedef typename boost::is_floating_point<T>::type fp_tag;
+ // typedef typename boost::is_floating_point<T>::type fp_tag;
return detail::isnan_impl(x, method());
}
@@ -524,6 +588,15 @@ template<class T> bool (isnan)(T x)
template <> inline bool isnan BOOST_NO_MACRO_EXPAND<float>(float t){ return ::boost::math_detail::is_nan_helper(t, boost::true_type()); }
template <> inline bool isnan BOOST_NO_MACRO_EXPAND<double>(double t){ return ::boost::math_detail::is_nan_helper(t, boost::true_type()); }
template <> inline bool isnan BOOST_NO_MACRO_EXPAND<long double>(long double t){ return ::boost::math_detail::is_nan_helper(t, boost::true_type()); }
+#elif defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS)
+template<>
+inline bool (isnan)(long double x)
+{ //!< \brief return true if floating-point type t is NaN (Not A Number).
+ typedef detail::fp_traits<long double>::type traits;
+ typedef traits::method method;
+ //typedef boost::is_floating_point<long double>::type fp_tag;
+ return detail::isnan_impl(x, method());
+}
#endif
} // namespace math
diff --git a/boost/math/special_functions/gamma.hpp b/boost/math/special_functions/gamma.hpp
index 86d15b7f2a..b6b4c574a9 100644
--- a/boost/math/special_functions/gamma.hpp
+++ b/boost/math/special_functions/gamma.hpp
@@ -1,6 +1,8 @@
-// Copyright John Maddock 2006-7.
-// Copyright Paul A. Bristow 2007.
+// Copyright John Maddock 2006-7, 2013-14.
+// Copyright Paul A. Bristow 2007, 2013-14.
+// Copyright Nikhar Agrawal 2013-14
+// Copyright Christopher Kormanyos 2013-14
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
@@ -14,17 +16,6 @@
#endif
#include <boost/config.hpp>
-#ifdef BOOST_MSVC
-# pragma warning(push)
-# pragma warning(disable: 4127 4701)
-// // For lexical_cast, until fixed in 1.35?
-// // conditional expression is constant &
-// // Potentially uninitialized local variable 'name' used
-#endif
-#include <boost/lexical_cast.hpp>
-#ifdef BOOST_MSVC
-# pragma warning(pop)
-#endif
#include <boost/math/tools/series.hpp>
#include <boost/math/tools/fraction.hpp>
#include <boost/math/tools/precision.hpp>
@@ -41,6 +32,7 @@
#include <boost/math/special_functions/detail/igamma_large.hpp>
#include <boost/math/special_functions/detail/unchecked_factorial.hpp>
#include <boost/math/special_functions/detail/lgamma_small.hpp>
+#include <boost/math/special_functions/bernoulli.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/assert.hpp>
#include <boost/mpl/greater.hpp>
@@ -50,12 +42,6 @@
#include <boost/config/no_tr1/cmath.hpp>
#include <algorithm>
-#ifdef BOOST_MATH_INSTRUMENT
-#include <iostream>
-#include <iomanip>
-#include <typeinfo>
-#endif
-
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable: 4702) // unreachable code (return after domain_error throw).
@@ -153,7 +139,7 @@ T gamma_imp(T z, const Policy& pol, const Lanczos& l)
result = gamma_imp(T(-z), pol, l) * sinpx(z);
BOOST_MATH_INSTRUMENT_VARIABLE(result);
if((fabs(result) < 1) && (tools::max_value<T>() * fabs(result) < boost::math::constants::pi<T>()))
- return policies::raise_overflow_error<T>(function, "Result of tgamma is too large to represent.", pol);
+ return -boost::math::sign(result) * policies::raise_overflow_error<T>(function, "Result of tgamma is too large to represent.", pol);
result = -boost::math::constants::pi<T>() / result;
if(result == 0)
return policies::raise_underflow_error<T>(function, "Result of tgamma is too small to represent.", pol);
@@ -176,30 +162,36 @@ T gamma_imp(T z, const Policy& pol, const Lanczos& l)
result *= unchecked_factorial<T>(itrunc(z, pol) - 1);
BOOST_MATH_INSTRUMENT_VARIABLE(result);
}
+ else if (z < tools::root_epsilon<T>())
+ {
+ if (z < 1 / tools::max_value<T>())
+ result = policies::raise_overflow_error<T>(function, 0, pol);
+ result *= 1 / z - constants::euler<T>();
+ }
else
{
result *= Lanczos::lanczos_sum(z);
+ T zgh = (z + static_cast<T>(Lanczos::g()) - boost::math::constants::half<T>());
+ T lzgh = log(zgh);
BOOST_MATH_INSTRUMENT_VARIABLE(result);
BOOST_MATH_INSTRUMENT_VARIABLE(tools::log_max_value<T>());
- if(z * log(z) > tools::log_max_value<T>())
+ if(z * lzgh > tools::log_max_value<T>())
{
// we're going to overflow unless this is done with care:
- T zgh = (z + static_cast<T>(Lanczos::g()) - boost::math::constants::half<T>());
BOOST_MATH_INSTRUMENT_VARIABLE(zgh);
- if(log(zgh) * z / 2 > tools::log_max_value<T>())
- return policies::raise_overflow_error<T>(function, "Result of tgamma is too large to represent.", pol);
+ if(lzgh * z / 2 > tools::log_max_value<T>())
+ return boost::math::sign(result) * policies::raise_overflow_error<T>(function, "Result of tgamma is too large to represent.", pol);
T hp = pow(zgh, (z / 2) - T(0.25));
BOOST_MATH_INSTRUMENT_VARIABLE(hp);
result *= hp / exp(zgh);
BOOST_MATH_INSTRUMENT_VARIABLE(result);
if(tools::max_value<T>() / hp < result)
- return policies::raise_overflow_error<T>(function, "Result of tgamma is too large to represent.", pol);
+ return boost::math::sign(result) * policies::raise_overflow_error<T>(function, "Result of tgamma is too large to represent.", pol);
result *= hp;
BOOST_MATH_INSTRUMENT_VARIABLE(result);
}
else
{
- T zgh = (z + static_cast<T>(Lanczos::g()) - boost::math::constants::half<T>());
BOOST_MATH_INSTRUMENT_VARIABLE(zgh);
BOOST_MATH_INSTRUMENT_VARIABLE(pow(zgh, z - boost::math::constants::half<T>()));
BOOST_MATH_INSTRUMENT_VARIABLE(exp(zgh));
@@ -230,7 +222,7 @@ T lgamma_imp(T z, const Policy& pol, const Lanczos& l, int* sign = 0)
T result = 0;
int sresult = 1;
- if(z <= 0)
+ if(z <= -tools::root_epsilon<T>())
{
// reflection formula:
if(floor(z) == z)
@@ -248,6 +240,17 @@ T lgamma_imp(T z, const Policy& pol, const Lanczos& l, int* sign = 0)
}
result = log(boost::math::constants::pi<T>()) - lgamma_imp(z, pol, l) - log(t);
}
+ else if (z < tools::root_epsilon<T>())
+ {
+ if (0 == z)
+ return policies::raise_pole_error<T>(function, "Evaluation of lgamma at %1%.", z, pol);
+ if (fabs(z) < 1 / tools::max_value<T>())
+ result = -log(fabs(z));
+ else
+ result = log(fabs(1 / z - constants::euler<T>()));
+ if (z < 0)
+ sresult = -1;
+ }
else if(z < 15)
{
typedef typename policies::precision<T, Policy>::type precision_type;
@@ -266,7 +269,7 @@ T lgamma_imp(T z, const Policy& pol, const Lanczos& l, int* sign = 0)
>::type tag_type;
result = lgamma_small_imp<T>(z, T(z - 1), T(z - 2), tag_type(), pol, l);
}
- else if((z >= 3) && (z < 100))
+ else if((z >= 3) && (z < 100) && (std::numeric_limits<T>::max_exponent >= 1024))
{
// taking the log of tgamma reduces the error, no danger of overflow here:
result = log(gamma_imp(z, pol, l));
@@ -353,96 +356,271 @@ inline T lower_gamma_series(T a, T z, const Policy& pol, T init_value = 0)
}
//
-// Fully generic tgamma and lgamma use the incomplete partial
-// sums added together:
+// Fully generic tgamma and lgamma use Stirling's approximation
+// with Bernoulli numbers.
//
+template<class T>
+std::size_t highest_bernoulli_index()
+{
+ const float digits10_of_type = (std::numeric_limits<T>::is_specialized
+ ? static_cast<float>(std::numeric_limits<T>::digits10)
+ : static_cast<float>(boost::math::tools::digits<T>() * 0.301F));
+
+ // Find the high index n for Bn to produce the desired precision in Stirling's calculation.
+ return static_cast<std::size_t>(18.0F + (0.6F * digits10_of_type));
+}
+
+template<class T>
+T minimum_argument_for_bernoulli_recursion()
+{
+ const float digits10_of_type = (std::numeric_limits<T>::is_specialized
+ ? static_cast<float>(std::numeric_limits<T>::digits10)
+ : static_cast<float>(boost::math::tools::digits<T>() * 0.301F));
+
+ return T(digits10_of_type * 1.7F);
+}
+
+// Forward declaration of the lgamma_imp template specialization.
template <class T, class Policy>
-T gamma_imp(T z, const Policy& pol, const lanczos::undefined_lanczos& l)
+T lgamma_imp(T z, const Policy& pol, const lanczos::undefined_lanczos&, int* sign = 0);
+
+template <class T, class Policy>
+T gamma_imp(T z, const Policy& pol, const lanczos::undefined_lanczos&)
{
- static const char* function = "boost::math::tgamma<%1%>(%1%)";
BOOST_MATH_STD_USING
- if((z <= 0) && (floor(z) == z))
- return policies::raise_pole_error<T>(function, "Evaluation of tgamma at a negative integer %1%.", z, pol);
- if(z <= -20)
+
+ static const char* function = "boost::math::tgamma<%1%>(%1%)";
+
+ // Check if the argument of tgamma is identically zero.
+ const bool is_at_zero = (z == 0);
+
+ if(is_at_zero)
+ return policies::raise_domain_error<T>(function, "Evaluation of tgamma at zero %1%.", z, pol);
+
+ const bool b_neg = (z < 0);
+
+ const bool floor_of_z_is_equal_to_z = (floor(z) == z);
+
+ // Special case handling of small factorials:
+ if((!b_neg) && floor_of_z_is_equal_to_z && (z < boost::math::max_factorial<T>::value))
{
- T result = gamma_imp(T(-z), pol, l) * sinpx(z);
- if((fabs(result) < 1) && (tools::max_value<T>() * fabs(result) < boost::math::constants::pi<T>()))
- return policies::raise_overflow_error<T>(function, "Result of tgamma is too large to represent.", pol);
- result = -boost::math::constants::pi<T>() / result;
- if(result == 0)
- return policies::raise_underflow_error<T>(function, "Result of tgamma is too small to represent.", pol);
- if((boost::math::fpclassify)(result) == (int)FP_SUBNORMAL)
- return policies::raise_denorm_error<T>(function, "Result of tgamma is denormalized.", result, pol);
- return result;
+ return boost::math::unchecked_factorial<T>(itrunc(z) - 1);
}
- //
- // The upper gamma fraction is *very* slow for z < 6, actually it's very
- // slow to converge everywhere but recursing until z > 6 gets rid of the
- // worst of it's behaviour.
- //
- T prefix = 1;
- while(z < 6)
+
+ // Make a local, unsigned copy of the input argument.
+ T zz((!b_neg) ? z : -z);
+
+ // Special case for ultra-small z:
+ if(zz < tools::cbrt_epsilon<T>())
{
- prefix /= z;
- z += 1;
+ const T a0(1);
+ const T a1(boost::math::constants::euler<T>());
+ const T six_euler_squared((boost::math::constants::euler<T>() * boost::math::constants::euler<T>()) * 6);
+ const T a2((six_euler_squared - boost::math::constants::pi_sqr<T>()) / 12);
+
+ const T inverse_tgamma_series = z * ((a2 * z + a1) * z + a0);
+
+ return 1 / inverse_tgamma_series;
}
- BOOST_MATH_INSTRUMENT_CODE(prefix);
- if((floor(z) == z) && (z < max_factorial<T>::value))
+
+ // Scale the argument up for the calculation of lgamma,
+ // and use downward recursion later for the final result.
+ const T min_arg_for_recursion = minimum_argument_for_bernoulli_recursion<T>();
+
+ int n_recur;
+
+ if(zz < min_arg_for_recursion)
{
- prefix *= unchecked_factorial<T>(itrunc(z, pol) - 1);
+ n_recur = boost::math::itrunc(min_arg_for_recursion - zz) + 1;
+
+ zz += n_recur;
}
else
{
- prefix = prefix * pow(z / boost::math::constants::e<T>(), z);
- BOOST_MATH_INSTRUMENT_CODE(prefix);
- T sum = detail::lower_gamma_series(z, z, pol) / z;
- BOOST_MATH_INSTRUMENT_CODE(sum);
- sum += detail::upper_gamma_fraction(z, z, ::boost::math::policies::get_epsilon<T, Policy>());
- BOOST_MATH_INSTRUMENT_CODE(sum);
- if(fabs(tools::max_value<T>() / prefix) < fabs(sum))
+ n_recur = 0;
+ }
+
+ const T log_gamma_value = lgamma_imp(zz, pol, lanczos::undefined_lanczos());
+
+ if(log_gamma_value > tools::log_max_value<T>())
+ return policies::raise_overflow_error<T>(function, 0, pol);
+
+ T gamma_value = exp(log_gamma_value);
+
+ // Rescale the result using downward recursion if necessary.
+ if(n_recur)
+ {
+ // The order of divides is important, if we keep subtracting 1 from zz
+ // we DO NOT get back to z (cancellation error). Further if z < epsilon
+ // we would end up dividing by zero. Also in order to prevent spurious
+ // overflow with the first division, we must save dividing by |z| till last,
+ // so the optimal order of divides is z+1, z+2, z+3...z+n_recur-1,z.
+ zz = fabs(z) + 1;
+ for(int k = 1; k < n_recur; ++k)
+ {
+ gamma_value /= zz;
+ zz += 1;
+ }
+ gamma_value /= fabs(z);
+ }
+
+ // Return the result, accounting for possible negative arguments.
+ if(b_neg)
+ {
+ // Provide special error analysis for:
+ // * arguments in the neighborhood of a negative integer
+ // * arguments exactly equal to a negative integer.
+
+ // Check if the argument of tgamma is exactly equal to a negative integer.
+ if(floor_of_z_is_equal_to_z)
+ return policies::raise_pole_error<T>(function, "Evaluation of tgamma at a negative integer %1%.", z, pol);
+
+ gamma_value *= sinpx(z);
+
+ BOOST_MATH_INSTRUMENT_VARIABLE(gamma_value);
+
+ const bool result_is_too_large_to_represent = ( (abs(gamma_value) < 1)
+ && ((tools::max_value<T>() * abs(gamma_value)) < boost::math::constants::pi<T>()));
+
+ if(result_is_too_large_to_represent)
return policies::raise_overflow_error<T>(function, "Result of tgamma is too large to represent.", pol);
- BOOST_MATH_INSTRUMENT_CODE((sum * prefix));
- return sum * prefix;
+
+ gamma_value = -boost::math::constants::pi<T>() / gamma_value;
+ BOOST_MATH_INSTRUMENT_VARIABLE(gamma_value);
+
+ if(gamma_value == 0)
+ return policies::raise_underflow_error<T>(function, "Result of tgamma is too small to represent.", pol);
+
+ if((boost::math::fpclassify)(gamma_value) == static_cast<int>(FP_SUBNORMAL))
+ return policies::raise_denorm_error<T>(function, "Result of tgamma is denormalized.", gamma_value, pol);
}
- return prefix;
+
+ return gamma_value;
}
template <class T, class Policy>
-T lgamma_imp(T z, const Policy& pol, const lanczos::undefined_lanczos& l, int*sign)
+T lgamma_imp(T z, const Policy& pol, const lanczos::undefined_lanczos&, int* sign)
{
BOOST_MATH_STD_USING
static const char* function = "boost::math::lgamma<%1%>(%1%)";
- T result = 0;
- int sresult = 1;
- if(z <= 0)
+
+ // Check if the argument of lgamma is identically zero.
+ const bool is_at_zero = (z == 0);
+
+ if(is_at_zero)
+ return policies::raise_domain_error<T>(function, "Evaluation of lgamma at zero %1%.", z, pol);
+
+ const bool b_neg = (z < 0);
+
+ const bool floor_of_z_is_equal_to_z = (floor(z) == z);
+
+ // Special case handling of small factorials:
+ if((!b_neg) && floor_of_z_is_equal_to_z && (z < boost::math::max_factorial<T>::value))
{
- if(floor(z) == z)
- return policies::raise_pole_error<T>(function, "Evaluation of tgamma at a negative integer %1%.", z, pol);
- T t = detail::sinpx(z);
- z = -z;
+ return log(boost::math::unchecked_factorial<T>(itrunc(z) - 1));
+ }
+
+ // Make a local, unsigned copy of the input argument.
+ T zz((!b_neg) ? z : -z);
+
+ const T min_arg_for_recursion = minimum_argument_for_bernoulli_recursion<T>();
+
+ T log_gamma_value;
+
+ if (zz < min_arg_for_recursion)
+ {
+ // Here we simply take the logarithm of tgamma(). This is somewhat
+ // inefficient, but simple. The rationale is that the argument here
+ // is relatively small and overflow is not expected to be likely.
+ if (z > -tools::root_epsilon<T>())
+ {
+ // Reflection formula may fail if z is very close to zero, let the series
+ // expansion for tgamma close to zero do the work:
+ log_gamma_value = log(abs(gamma_imp(z, pol, lanczos::undefined_lanczos())));
+ if (sign)
+ {
+ *sign = z < 0 ? -1 : 1;
+ }
+ return log_gamma_value;
+ }
+ else
+ {
+ // No issue with spurious overflow in reflection formula,
+ // just fall through to regular code:
+ log_gamma_value = log(abs(gamma_imp(zz, pol, lanczos::undefined_lanczos())));
+ }
+ }
+ else
+ {
+ // Perform the Bernoulli series expansion of Stirling's approximation.
+
+ const std::size_t number_of_bernoullis_b2n = highest_bernoulli_index<T>();
+
+ T one_over_x_pow_two_n_minus_one = 1 / zz;
+ const T one_over_x2 = one_over_x_pow_two_n_minus_one * one_over_x_pow_two_n_minus_one;
+ T sum = (boost::math::bernoulli_b2n<T>(1) / 2) * one_over_x_pow_two_n_minus_one;
+ const T target_epsilon_to_break_loop = (sum * boost::math::tools::epsilon<T>()) * T(1.0E-10F);
+
+ for(std::size_t n = 2U; n < number_of_bernoullis_b2n; ++n)
+ {
+ one_over_x_pow_two_n_minus_one *= one_over_x2;
+
+ const std::size_t n2 = static_cast<std::size_t>(n * 2U);
+
+ const T term = (boost::math::bernoulli_b2n<T>(static_cast<int>(n)) * one_over_x_pow_two_n_minus_one) / (n2 * (n2 - 1U));
+
+ if((n >= 8U) && (abs(term) < target_epsilon_to_break_loop))
+ {
+ // We have reached the desired precision in Stirling's expansion.
+ // Adding additional terms to the sum of this divergent asymptotic
+ // expansion will not improve the result.
+
+ // Break from the loop.
+ break;
+ }
+
+ sum += term;
+ }
+
+ // Complete Stirling's approximation.
+ const T half_ln_two_pi = log(boost::math::constants::two_pi<T>()) / 2;
+
+ log_gamma_value = ((((zz - boost::math::constants::half<T>()) * log(zz)) - zz) + half_ln_two_pi) + sum;
+ }
+
+ int sign_of_result = 1;
+
+ if(b_neg)
+ {
+ // Provide special error analysis if the argument is exactly
+ // equal to a negative integer.
+
+ // Check if the argument of lgamma is exactly equal to a negative integer.
+ if(floor_of_z_is_equal_to_z)
+ return policies::raise_pole_error<T>(function, "Evaluation of lgamma at a negative integer %1%.", z, pol);
+
+ T t = sinpx(z);
+
if(t < 0)
{
t = -t;
}
else
{
- sresult = -sresult;
+ sign_of_result = -sign_of_result;
}
- result = log(boost::math::constants::pi<T>()) - lgamma_imp(z, pol, l, 0) - log(t);
- }
- else if((z != 1) && (z != 2))
- {
- T limit = (std::max)(T(z+1), T(10));
- T prefix = z * log(limit) - limit;
- T sum = detail::lower_gamma_series(z, limit, pol) / z;
- sum += detail::upper_gamma_fraction(z, limit, ::boost::math::policies::get_epsilon<T, Policy>());
- result = log(sum) + prefix;
+
+ log_gamma_value = - log_gamma_value
+ + log(boost::math::constants::pi<T>())
+ - log(t);
}
- if(sign)
- *sign = sresult;
- return result;
+
+ if(sign != static_cast<int*>(0U)) { *sign = sign_of_result; }
+
+ return log_gamma_value;
}
+
//
// This helper calculates tgamma(dz+1)-1 without cancellation errors,
// used by the upper incomplete gamma with z < 1:
@@ -604,7 +782,7 @@ T full_igamma_prefix(T a, T z, const Policy& pol)
// rather than before it...
//
if((boost::math::fpclassify)(prefix) == (int)FP_INFINITE)
- policies::raise_overflow_error<T>("boost::math::detail::full_igamma_prefix<%1%>(%1%, %1%)", "Result of incomplete gamma function is too large to represent.", pol);
+ return policies::raise_overflow_error<T>("boost::math::detail::full_igamma_prefix<%1%>(%1%, %1%)", "Result of incomplete gamma function is too large to represent.", pol);
return prefix;
}
@@ -842,9 +1020,9 @@ T gamma_incomplete_imp(T a, T x, bool normalised, bool invert,
{
static const char* function = "boost::math::gamma_p<%1%>(%1%, %1%)";
if(a <= 0)
- policies::raise_domain_error<T>(function, "Argument a to the incomplete gamma function must be greater than zero (got a=%1%).", a, pol);
+ return policies::raise_domain_error<T>(function, "Argument a to the incomplete gamma function must be greater than zero (got a=%1%).", a, pol);
if(x < 0)
- policies::raise_domain_error<T>(function, "Argument x to the incomplete gamma function must be >= 0 (got x=%1%).", x, pol);
+ return policies::raise_domain_error<T>(function, "Argument x to the incomplete gamma function must be >= 0 (got x=%1%).", x, pol);
BOOST_MATH_STD_USING
@@ -852,10 +1030,51 @@ T gamma_incomplete_imp(T a, T x, bool normalised, bool invert,
T result = 0; // Just to avoid warning C4701: potentially uninitialized local variable 'result' used
+ if(a >= max_factorial<T>::value && !normalised)
+ {
+ //
+ // When we're computing the non-normalized incomplete gamma
+ // and a is large the result is rather hard to compute unless
+ // we use logs. There are really two options - if x is a long
+ // way from a in value then we can reliably use methods 2 and 4
+ // below in logarithmic form and go straight to the result.
+ // Otherwise we let the regularized gamma take the strain
+ // (the result is unlikely to unerflow in the central region anyway)
+ // and combine with lgamma in the hopes that we get a finite result.
+ //
+ if(invert && (a * 4 < x))
+ {
+ // This is method 4 below, done in logs:
+ result = a * log(x) - x;
+ if(p_derivative)
+ *p_derivative = exp(result);
+ result += log(upper_gamma_fraction(a, x, policies::get_epsilon<T, Policy>()));
+ }
+ else if(!invert && (a > 4 * x))
+ {
+ // This is method 2 below, done in logs:
+ result = a * log(x) - x;
+ if(p_derivative)
+ *p_derivative = exp(result);
+ T init_value = 0;
+ result += log(detail::lower_gamma_series(a, x, pol, init_value) / a);
+ }
+ else
+ {
+ result = gamma_incomplete_imp(a, x, true, invert, pol, p_derivative);
+ if(result == 0)
+ return policies::raise_evaluation_error<T>(function, "Obtained %1% for the incomplete gamma function, but in truth we don't really know what the answer is...", result, pol);
+ result = log(result) + boost::math::lgamma(a, pol);
+ }
+ if(result > tools::log_max_value<T>())
+ return policies::raise_overflow_error<T>(function, 0, pol);
+ return exp(result);
+ }
+
BOOST_ASSERT((p_derivative == 0) || (normalised == true));
bool is_int, is_half_int;
- bool is_small_a = (a < 30) && (a <= x + 1);
+ bool is_small_a = (a < 30) && (a <= x + 1) && (x < tools::log_max_value<T>());
if(is_small_a)
{
T fa = floor(a);
@@ -881,6 +1100,10 @@ T gamma_incomplete_imp(T a, T x, bool normalised, bool invert,
invert = !invert;
eval_method = 1;
}
+ else if((x < tools::root_epsilon<T>()) && (a > 1))
+ {
+ eval_method = 6;
+ }
else if(x < 0.5)
{
//
@@ -994,13 +1217,39 @@ T gamma_incomplete_imp(T a, T x, bool normalised, bool invert,
*p_derivative = result;
if(result != 0)
{
+ //
+ // If we're going to be inverting the result then we can
+ // reduce the number of series evaluations by quite
+ // a few iterations if we set an initial value for the
+ // series sum based on what we'll end up subtracting it from
+ // at the end.
+ // Have to be careful though that this optimization doesn't
+ // lead to spurious numberic overflow. Note that the
+ // scary/expensive overflow checks below are more often
+ // than not bypassed in practice for "sensible" input
+ // values:
+ //
T init_value = 0;
+ bool optimised_invert = false;
if(invert)
{
- init_value = -a * (normalised ? 1 : boost::math::tgamma(a, pol)) / result;
+ init_value = (normalised ? 1 : boost::math::tgamma(a, pol));
+ if(normalised || (result >= 1) || (tools::max_value<T>() * result > init_value))
+ {
+ init_value /= result;
+ if(normalised || (a < 1) || (tools::max_value<T>() / a > init_value))
+ {
+ init_value *= -a;
+ optimised_invert = true;
+ }
+ else
+ init_value = 0;
+ }
+ else
+ init_value = 0;
}
result *= detail::lower_gamma_series(a, x, pol, init_value) / a;
- if(invert)
+ if(optimised_invert)
{
invert = false;
result = -result;
@@ -1063,6 +1312,13 @@ T gamma_incomplete_imp(T a, T x, bool normalised, bool invert,
*p_derivative = regularised_gamma_prefix(a, x, pol, lanczos_type());
break;
}
+ case 6:
+ {
+ // x is so small that P is necessarily very small too,
+ // use http://functions.wolfram.com/GammaBetaErf/GammaRegularized/06/01/05/01/01/
+ result = !normalised ? pow(x, a) / (a) : pow(x, a) / boost::math::tgamma(a + 1, pol);
+ result *= 1 - a * x / (a + 1);
+ }
}
if(normalised && (result > 1))
@@ -1093,9 +1349,32 @@ T gamma_incomplete_imp(T a, T x, bool normalised, bool invert,
// Ratios of two gamma functions:
//
template <class T, class Policy, class Lanczos>
-T tgamma_delta_ratio_imp_lanczos(T z, T delta, const Policy& pol, const Lanczos&)
+T tgamma_delta_ratio_imp_lanczos(T z, T delta, const Policy& pol, const Lanczos& l)
{
BOOST_MATH_STD_USING
+ if(z < tools::epsilon<T>())
+ {
+ //
+ // We get spurious numeric overflow unless we're very careful, this
+ // can occur either inside Lanczos::lanczos_sum(z) or in the
+ // final combination of terms, to avoid this, split the product up
+ // into 2 (or 3) parts:
+ //
+ // G(z) / G(L) = 1 / (z * G(L)) ; z < eps, L = z + delta = delta
+ // z * G(L) = z * G(lim) * (G(L)/G(lim)) ; lim = largest factorial
+ //
+ if(boost::math::max_factorial<T>::value < delta)
+ {
+ T ratio = tgamma_delta_ratio_imp_lanczos(delta, T(boost::math::max_factorial<T>::value - delta), pol, l);
+ ratio *= z;
+ ratio *= boost::math::unchecked_factorial<T>(boost::math::max_factorial<T>::value - 1);
+ return 1 / ratio;
+ }
+ else
+ {
+ return 1 / (z * boost::math::tgamma(z + delta, pol));
+ }
+ }
T zgh = z + Lanczos::g() - constants::half<T>();
T result;
if(fabs(delta) < 10)
@@ -1106,8 +1385,9 @@ T tgamma_delta_ratio_imp_lanczos(T z, T delta, const Policy& pol, const Lanczos&
{
result = pow(zgh / (zgh + delta), z - constants::half<T>());
}
- result *= pow(constants::e<T>() / (zgh + delta), delta);
+ // Split the calculation up to avoid spurious overflow:
result *= Lanczos::lanczos_sum(z) / Lanczos::lanczos_sum(T(z + delta));
+ result *= pow(constants::e<T>() / (zgh + delta), delta);
return result;
}
//
@@ -1155,10 +1435,11 @@ T tgamma_delta_ratio_imp(T z, T delta, const Policy& pol)
{
BOOST_MATH_STD_USING
- if(z <= 0)
- policies::raise_domain_error<T>("boost::math::tgamma_delta_ratio<%1%>(%1%, %1%)", "Gamma function ratios only implemented for positive arguments (got a=%1%).", z, pol);
- if(z+delta <= 0)
- policies::raise_domain_error<T>("boost::math::tgamma_delta_ratio<%1%>(%1%, %1%)", "Gamma function ratios only implemented for positive arguments (got b=%1%).", z+delta, pol);
+ if((z <= 0) || (z + delta <= 0))
+ {
+ // This isn't very sofisticated, or accurate, but it does work:
+ return boost::math::tgamma(z, pol) / boost::math::tgamma(z + delta, pol);
+ }
if(floor(delta) == delta)
{
@@ -1208,15 +1489,84 @@ T tgamma_delta_ratio_imp(T z, T delta, const Policy& pol)
}
template <class T, class Policy>
+T tgamma_ratio_imp(T x, T y, const Policy& pol)
+{
+ BOOST_MATH_STD_USING
+
+ if((x <= 0) || (boost::math::isinf)(x))
+ return policies::raise_domain_error<T>("boost::math::tgamma_ratio<%1%>(%1%, %1%)", "Gamma function ratios only implemented for positive arguments (got a=%1%).", x, pol);
+ if((y <= 0) || (boost::math::isinf)(y))
+ return policies::raise_domain_error<T>("boost::math::tgamma_ratio<%1%>(%1%, %1%)", "Gamma function ratios only implemented for positive arguments (got b=%1%).", y, pol);
+
+ if(x <= tools::min_value<T>())
+ {
+ // Special case for denorms...Ugh.
+ T shift = ldexp(T(1), tools::digits<T>());
+ return shift * tgamma_ratio_imp(T(x * shift), y, pol);
+ }
+
+ if((x < max_factorial<T>::value) && (y < max_factorial<T>::value))
+ {
+ // Rather than subtracting values, lets just call the gamma functions directly:
+ return boost::math::tgamma(x, pol) / boost::math::tgamma(y, pol);
+ }
+ T prefix = 1;
+ if(x < 1)
+ {
+ if(y < 2 * max_factorial<T>::value)
+ {
+ // We need to sidestep on x as well, otherwise we'll underflow
+ // before we get to factor in the prefix term:
+ prefix /= x;
+ x += 1;
+ while(y >= max_factorial<T>::value)
+ {
+ y -= 1;
+ prefix /= y;
+ }
+ return prefix * boost::math::tgamma(x, pol) / boost::math::tgamma(y, pol);
+ }
+ //
+ // result is almost certainly going to underflow to zero, try logs just in case:
+ //
+ return exp(boost::math::lgamma(x, pol) - boost::math::lgamma(y, pol));
+ }
+ if(y < 1)
+ {
+ if(x < 2 * max_factorial<T>::value)
+ {
+ // We need to sidestep on y as well, otherwise we'll overflow
+ // before we get to factor in the prefix term:
+ prefix *= y;
+ y += 1;
+ while(x >= max_factorial<T>::value)
+ {
+ x -= 1;
+ prefix *= x;
+ }
+ return prefix * boost::math::tgamma(x, pol) / boost::math::tgamma(y, pol);
+ }
+ //
+ // Result will almost certainly overflow, try logs just in case:
+ //
+ return exp(boost::math::lgamma(x, pol) - boost::math::lgamma(y, pol));
+ }
+ //
+ // Regular case, x and y both large and similar in magnitude:
+ //
+ return boost::math::tgamma_delta_ratio(x, y - x, pol);
+}
+
+template <class T, class Policy>
T gamma_p_derivative_imp(T a, T x, const Policy& pol)
{
//
// Usual error checks first:
//
if(a <= 0)
- policies::raise_domain_error<T>("boost::math::gamma_p_derivative<%1%>(%1%, %1%)", "Argument a to the incomplete gamma function must be greater than zero (got a=%1%).", a, pol);
+ return policies::raise_domain_error<T>("boost::math::gamma_p_derivative<%1%>(%1%, %1%)", "Argument a to the incomplete gamma function must be greater than zero (got a=%1%).", a, pol);
if(x < 0)
- policies::raise_domain_error<T>("boost::math::gamma_p_derivative<%1%>(%1%, %1%)", "Argument x to the incomplete gamma function must be >= 0 (got x=%1%).", x, pol);
+ return policies::raise_domain_error<T>("boost::math::gamma_p_derivative<%1%>(%1%, %1%)", "Argument x to the incomplete gamma function must be >= 0 (got x=%1%).", x, pol);
//
// Now special cases:
//
@@ -1360,7 +1710,7 @@ inline typename tools::promote_args<T1, T2>::type
BOOST_FPU_EXCEPTION_GUARD
typedef typename tools::promote_args<T1, T2>::type result_type;
typedef typename policies::evaluation<result_type, Policy>::type value_type;
- typedef typename lanczos::lanczos<value_type, Policy>::type evaluation_type;
+ // typedef typename lanczos::lanczos<value_type, Policy>::type evaluation_type;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
@@ -1489,7 +1839,7 @@ inline typename tools::promote_args<T1, T2>::type
BOOST_FPU_EXCEPTION_GUARD
typedef typename tools::promote_args<T1, T2>::type result_type;
typedef typename policies::evaluation<result_type, Policy>::type value_type;
- typedef typename lanczos::lanczos<value_type, Policy>::type evaluation_type;
+ // typedef typename lanczos::lanczos<value_type, Policy>::type evaluation_type;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
@@ -1520,7 +1870,7 @@ inline typename tools::promote_args<T1, T2>::type
BOOST_FPU_EXCEPTION_GUARD
typedef typename tools::promote_args<T1, T2>::type result_type;
typedef typename policies::evaluation<result_type, Policy>::type value_type;
- typedef typename lanczos::lanczos<value_type, Policy>::type evaluation_type;
+ // typedef typename lanczos::lanczos<value_type, Policy>::type evaluation_type;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
@@ -1551,7 +1901,7 @@ inline typename tools::promote_args<T1, T2>::type
BOOST_FPU_EXCEPTION_GUARD
typedef typename tools::promote_args<T1, T2>::type result_type;
typedef typename policies::evaluation<result_type, Policy>::type value_type;
- typedef typename lanczos::lanczos<value_type, Policy>::type evaluation_type;
+ // typedef typename lanczos::lanczos<value_type, Policy>::type evaluation_type;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
@@ -1609,7 +1959,7 @@ inline typename tools::promote_args<T1, T2>::type
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
- return policies::checked_narrowing_cast<result_type, forwarding_policy>(detail::tgamma_delta_ratio_imp(static_cast<value_type>(a), static_cast<value_type>(static_cast<value_type>(b) - static_cast<value_type>(a)), forwarding_policy()), "boost::math::tgamma_delta_ratio<%1%>(%1%, %1%)");
+ return policies::checked_narrowing_cast<result_type, forwarding_policy>(detail::tgamma_ratio_imp(static_cast<value_type>(a), static_cast<value_type>(b), forwarding_policy()), "boost::math::tgamma_delta_ratio<%1%>(%1%, %1%)");
}
template <class T1, class T2>
inline typename tools::promote_args<T1, T2>::type
diff --git a/boost/math/special_functions/hankel.hpp b/boost/math/special_functions/hankel.hpp
index bc3fc2d742..4266ef808c 100644
--- a/boost/math/special_functions/hankel.hpp
+++ b/boost/math/special_functions/hankel.hpp
@@ -7,6 +7,7 @@
#ifndef BOOST_MATH_HANKEL_HPP
#define BOOST_MATH_HANKEL_HPP
+#include <boost/math/special_functions/math_fwd.hpp>
#include <boost/math/special_functions/bessel.hpp>
namespace boost{ namespace math{
@@ -28,7 +29,7 @@ std::complex<T> hankel_imp(T v, T x, const bessel_no_int_tag&, const Policy& pol
std::complex<T> j_result, y_result;
if(isint_v)
{
- int s = (iround(j) & 1) ? -1 : 1;
+ int s = (iround(v) & 1) ? -1 : 1;
j_result = j * s;
y_result = T(s) * (y - (2 / constants::pi<T>()) * (log(-x) - log(cx)) * j);
}
@@ -83,7 +84,7 @@ template <class T, class Policy>
inline std::complex<T> hankel_imp(int v, T x, const bessel_int_tag&, const Policy& pol, int sign)
{
BOOST_MATH_STD_USING
- if((std::abs(v < 200)) && (x > 0))
+ if((std::abs(v) < 200) && (x > 0))
return std::complex<T>(bessel_jn(v, x, pol), sign * bessel_yn(v, x, pol));
return hankel_imp(static_cast<T>(v), x, bessel_no_int_tag(), pol, sign);
}
@@ -130,7 +131,7 @@ inline std::complex<typename detail::bessel_traits<T1, T2, policies::policy<> >:
}
template <class T1, class T2, class Policy>
-inline std::complex<typename detail::bessel_traits<T1, T2, Policy>::result_type> sph_hankel_1(T1 v, T2 x, const Policy& pol)
+inline std::complex<typename detail::bessel_traits<T1, T2, Policy>::result_type> sph_hankel_1(T1 v, T2 x, const Policy&)
{
BOOST_FPU_EXCEPTION_GUARD
typedef typename detail::bessel_traits<T1, T2, Policy>::result_type result_type;
@@ -152,7 +153,7 @@ inline std::complex<typename detail::bessel_traits<T1, T2, policies::policy<> >:
}
template <class T1, class T2, class Policy>
-inline std::complex<typename detail::bessel_traits<T1, T2, Policy>::result_type> sph_hankel_2(T1 v, T2 x, const Policy& pol)
+inline std::complex<typename detail::bessel_traits<T1, T2, Policy>::result_type> sph_hankel_2(T1 v, T2 x, const Policy&)
{
BOOST_FPU_EXCEPTION_GUARD
typedef typename detail::bessel_traits<T1, T2, Policy>::result_type result_type;
@@ -175,4 +176,5 @@ inline std::complex<typename detail::bessel_traits<T1, T2, policies::policy<> >:
}} // namespaces
-#endif // BOOST_MATH_HANKEL_HPP \ No newline at end of file
+#endif // BOOST_MATH_HANKEL_HPP
+
diff --git a/boost/math/special_functions/jacobi_elliptic.hpp b/boost/math/special_functions/jacobi_elliptic.hpp
new file mode 100644
index 0000000000..3ffc011566
--- /dev/null
+++ b/boost/math/special_functions/jacobi_elliptic.hpp
@@ -0,0 +1,321 @@
+// Copyright John Maddock 2012.
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MATH_JACOBI_ELLIPTIC_HPP
+#define BOOST_MATH_JACOBI_ELLIPTIC_HPP
+
+#include <boost/math/tools/precision.hpp>
+#include <boost/math/tools/promotion.hpp>
+#include <boost/math/policies/error_handling.hpp>
+#include <boost/math/special_functions/math_fwd.hpp>
+
+namespace boost{ namespace math{
+
+namespace detail{
+
+template <class T, class Policy>
+T jacobi_recurse(const T& x, const T& k, T anm1, T bnm1, unsigned N, T* pTn, const Policy& pol)
+{
+ BOOST_MATH_STD_USING
+ ++N;
+ T Tn;
+ T cn = (anm1 - bnm1) / 2;
+ T an = (anm1 + bnm1) / 2;
+ if(cn < policies::get_epsilon<T, Policy>())
+ {
+ Tn = ldexp(T(1), (int)N) * x * an;
+ }
+ else
+ Tn = jacobi_recurse<T>(x, k, an, sqrt(anm1 * bnm1), N, 0, pol);
+ if(pTn)
+ *pTn = Tn;
+ return (Tn + asin((cn / an) * sin(Tn))) / 2;
+}
+
+template <class T, class Policy>
+T jacobi_imp(const T& x, const T& k, T* cn, T* dn, const Policy& pol, const char* function)
+{
+ BOOST_MATH_STD_USING
+ if(k < 0)
+ {
+ *cn = policies::raise_domain_error<T>(function, "Modulus k must be positive but got %1%.", k, pol);
+ *dn = *cn;
+ return *cn;
+ }
+ if(k > 1)
+ {
+ T xp = x * k;
+ T kp = 1 / k;
+ T snp, cnp, dnp;
+ snp = jacobi_imp(xp, kp, &cnp, &dnp, pol, function);
+ *cn = dnp;
+ *dn = cnp;
+ return snp * kp;
+ }
+ //
+ // Special cases first:
+ //
+ if(x == 0)
+ {
+ *cn = *dn = 1;
+ return 0;
+ }
+ if(k == 0)
+ {
+ *cn = cos(x);
+ *dn = 1;
+ return sin(x);
+ }
+ if(k == 1)
+ {
+ *cn = *dn = 1 / cosh(x);
+ return tanh(x);
+ }
+ //
+ // Asymptotic forms from A&S 16.13:
+ //
+ if(k < tools::forth_root_epsilon<T>())
+ {
+ T su = sin(x);
+ T cu = cos(x);
+ T m = k * k;
+ *dn = 1 - m * su * su / 2;
+ *cn = cu + m * (x - su * cu) * su / 4;
+ return su - m * (x - su * cu) * cu / 4;
+ }
+ /* Can't get this to work to adequate precision - disabled for now...
+ //
+ // Asymptotic forms from A&S 16.15:
+ //
+ if(k > 1 - tools::root_epsilon<T>())
+ {
+ T tu = tanh(x);
+ T su = sinh(x);
+ T cu = cosh(x);
+ T sec = 1 / cu;
+ T kp = 1 - k;
+ T m1 = 2 * kp - kp * kp;
+ *dn = sec + m1 * (su * cu + x) * tu * sec / 4;
+ *cn = sec - m1 * (su * cu - x) * tu * sec / 4;
+ T sn = tu;
+ T sn2 = m1 * (x * sec * sec - tu) / 4;
+ T sn3 = (72 * x * cu + 4 * (8 * x * x - 5) * su - 19 * sinh(3 * x) + sinh(5 * x)) * sec * sec * sec * m1 * m1 / 512;
+ return sn + sn2 - sn3;
+ }*/
+ T T1;
+ T kc = 1 - k;
+ T k_prime = k < 0.5 ? T(sqrt(1 - k * k)) : T(sqrt(2 * kc - kc * kc));
+ T T0 = jacobi_recurse(x, k, T(1), k_prime, 0, &T1, pol);
+ *cn = cos(T0);
+ *dn = cos(T0) / cos(T1 - T0);
+ return sin(T0);
+}
+
+} // namespace detail
+
+template <class T, class U, class V, class Policy>
+inline typename tools::promote_args<T, U, V>::type jacobi_elliptic(T k, U theta, V* pcn, V* pdn, const Policy&)
+{
+ BOOST_FPU_EXCEPTION_GUARD
+ typedef typename tools::promote_args<T>::type result_type;
+ typedef typename policies::evaluation<result_type, Policy>::type value_type;
+ typedef typename policies::normalise<
+ Policy,
+ policies::promote_float<false>,
+ policies::promote_double<false>,
+ policies::discrete_quantile<>,
+ policies::assert_undefined<> >::type forwarding_policy;
+
+ static const char* function = "boost::math::jacobi_elliptic<%1%>(%1%)";
+
+ value_type sn, cn, dn;
+ sn = detail::jacobi_imp<value_type>(static_cast<value_type>(theta), static_cast<value_type>(k), &cn, &dn, forwarding_policy(), function);
+ if(pcn)
+ *pcn = policies::checked_narrowing_cast<result_type, Policy>(cn, function);
+ if(pdn)
+ *pdn = policies::checked_narrowing_cast<result_type, Policy>(dn, function);
+ return policies::checked_narrowing_cast<result_type, Policy>(sn, function);;
+}
+
+template <class T, class U, class V>
+inline typename tools::promote_args<T, U, V>::type jacobi_elliptic(T k, U theta, V* pcn, V* pdn)
+{
+ return jacobi_elliptic(k, theta, pcn, pdn, policies::policy<>());
+}
+
+template <class U, class T, class Policy>
+inline typename tools::promote_args<T, U>::type jacobi_sn(U k, T theta, const Policy& pol)
+{
+ typedef typename tools::promote_args<T, U>::type result_type;
+ return jacobi_elliptic(static_cast<result_type>(k), static_cast<result_type>(theta), static_cast<result_type*>(0), static_cast<result_type*>(0), pol);
+}
+
+template <class U, class T>
+inline typename tools::promote_args<T, U>::type jacobi_sn(U k, T theta)
+{
+ return jacobi_sn(k, theta, policies::policy<>());
+}
+
+template <class T, class U, class Policy>
+inline typename tools::promote_args<T, U>::type jacobi_cn(T k, U theta, const Policy& pol)
+{
+ typedef typename tools::promote_args<T, U>::type result_type;
+ result_type cn;
+ jacobi_elliptic(static_cast<result_type>(k), static_cast<result_type>(theta), &cn, static_cast<result_type*>(0), pol);
+ return cn;
+}
+
+template <class T, class U>
+inline typename tools::promote_args<T, U>::type jacobi_cn(T k, U theta)
+{
+ return jacobi_cn(k, theta, policies::policy<>());
+}
+
+template <class T, class U, class Policy>
+inline typename tools::promote_args<T, U>::type jacobi_dn(T k, U theta, const Policy& pol)
+{
+ typedef typename tools::promote_args<T, U>::type result_type;
+ result_type dn;
+ jacobi_elliptic(static_cast<result_type>(k), static_cast<result_type>(theta), static_cast<result_type*>(0), &dn, pol);
+ return dn;
+}
+
+template <class T, class U>
+inline typename tools::promote_args<T, U>::type jacobi_dn(T k, U theta)
+{
+ return jacobi_dn(k, theta, policies::policy<>());
+}
+
+template <class T, class U, class Policy>
+inline typename tools::promote_args<T, U>::type jacobi_cd(T k, U theta, const Policy& pol)
+{
+ typedef typename tools::promote_args<T, U>::type result_type;
+ result_type cn, dn;
+ jacobi_elliptic(static_cast<result_type>(k), static_cast<result_type>(theta), &cn, &dn, pol);
+ return cn / dn;
+}
+
+template <class T, class U>
+inline typename tools::promote_args<T, U>::type jacobi_cd(T k, U theta)
+{
+ return jacobi_cd(k, theta, policies::policy<>());
+}
+
+template <class T, class U, class Policy>
+inline typename tools::promote_args<T, U>::type jacobi_dc(T k, U theta, const Policy& pol)
+{
+ typedef typename tools::promote_args<T, U>::type result_type;
+ result_type cn, dn;
+ jacobi_elliptic(static_cast<result_type>(k), static_cast<result_type>(theta), &cn, &dn, pol);
+ return dn / cn;
+}
+
+template <class T, class U>
+inline typename tools::promote_args<T, U>::type jacobi_dc(T k, U theta)
+{
+ return jacobi_dc(k, theta, policies::policy<>());
+}
+
+template <class T, class U, class Policy>
+inline typename tools::promote_args<T, U>::type jacobi_ns(T k, U theta, const Policy& pol)
+{
+ typedef typename tools::promote_args<T, U>::type result_type;
+ return 1 / jacobi_elliptic(static_cast<result_type>(k), static_cast<result_type>(theta), static_cast<result_type*>(0), static_cast<result_type*>(0), pol);
+}
+
+template <class T, class U>
+inline typename tools::promote_args<T, U>::type jacobi_ns(T k, U theta)
+{
+ return jacobi_ns(k, theta, policies::policy<>());
+}
+
+template <class T, class U, class Policy>
+inline typename tools::promote_args<T, U>::type jacobi_sd(T k, U theta, const Policy& pol)
+{
+ typedef typename tools::promote_args<T, U>::type result_type;
+ result_type sn, dn;
+ sn = jacobi_elliptic(static_cast<result_type>(k), static_cast<result_type>(theta), static_cast<result_type*>(0), &dn, pol);
+ return sn / dn;
+}
+
+template <class T, class U>
+inline typename tools::promote_args<T, U>::type jacobi_sd(T k, U theta)
+{
+ return jacobi_sd(k, theta, policies::policy<>());
+}
+
+template <class T, class U, class Policy>
+inline typename tools::promote_args<T, U>::type jacobi_ds(T k, U theta, const Policy& pol)
+{
+ typedef typename tools::promote_args<T, U>::type result_type;
+ result_type sn, dn;
+ sn = jacobi_elliptic(static_cast<result_type>(k), static_cast<result_type>(theta), static_cast<result_type*>(0), &dn, pol);
+ return dn / sn;
+}
+
+template <class T, class U>
+inline typename tools::promote_args<T, U>::type jacobi_ds(T k, U theta)
+{
+ return jacobi_ds(k, theta, policies::policy<>());
+}
+
+template <class T, class U, class Policy>
+inline typename tools::promote_args<T, U>::type jacobi_nc(T k, U theta, const Policy& pol)
+{
+ return 1 / jacobi_cn(k, theta, pol);
+}
+
+template <class T, class U>
+inline typename tools::promote_args<T, U>::type jacobi_nc(T k, U theta)
+{
+ return jacobi_nc(k, theta, policies::policy<>());
+}
+
+template <class T, class U, class Policy>
+inline typename tools::promote_args<T, U>::type jacobi_nd(T k, U theta, const Policy& pol)
+{
+ return 1 / jacobi_dn(k, theta, pol);
+}
+
+template <class T, class U>
+inline typename tools::promote_args<T, U>::type jacobi_nd(T k, U theta)
+{
+ return jacobi_nd(k, theta, policies::policy<>());
+}
+
+template <class T, class U, class Policy>
+inline typename tools::promote_args<T, U>::type jacobi_sc(T k, U theta, const Policy& pol)
+{
+ typedef typename tools::promote_args<T, U>::type result_type;
+ result_type sn, cn;
+ sn = jacobi_elliptic(static_cast<result_type>(k), static_cast<result_type>(theta), &cn, static_cast<result_type*>(0), pol);
+ return sn / cn;
+}
+
+template <class T, class U>
+inline typename tools::promote_args<T, U>::type jacobi_sc(T k, U theta)
+{
+ return jacobi_sc(k, theta, policies::policy<>());
+}
+
+template <class T, class U, class Policy>
+inline typename tools::promote_args<T, U>::type jacobi_cs(T k, U theta, const Policy& pol)
+{
+ typedef typename tools::promote_args<T, U>::type result_type;
+ result_type sn, cn;
+ sn = jacobi_elliptic(static_cast<result_type>(k), static_cast<result_type>(theta), &cn, static_cast<result_type*>(0), pol);
+ return cn / sn;
+}
+
+template <class T, class U>
+inline typename tools::promote_args<T, U>::type jacobi_cs(T k, U theta)
+{
+ return jacobi_cs(k, theta, policies::policy<>());
+}
+
+}} // namespaces
+
+#endif // BOOST_MATH_JACOBI_ELLIPTIC_HPP
diff --git a/boost/math/special_functions/lanczos.hpp b/boost/math/special_functions/lanczos.hpp
index ed891549f1..0db21d3d16 100644
--- a/boost/math/special_functions/lanczos.hpp
+++ b/boost/math/special_functions/lanczos.hpp
@@ -1068,7 +1068,7 @@ struct lanczos24m113 : public mpl::int_<113>
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 113, 2.50662827463100050241576528481104515966515623051532908941425544355490413900497467936202516))
};
static const T denom[24] = {
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 113, 0)),
+ static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 113, 0.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 113, 0.112400072777760768e22)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 113, 0.414847677933545472e22)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 113, 6756146673770930688000.0)),
@@ -1087,11 +1087,11 @@ struct lanczos24m113 : public mpl::int_<113>
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 113, 3256091103430.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 113, 136717357942.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 113, 4546047198.0)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 113, 116896626)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 113, 2240315)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 113, 30107)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 113, 253)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 113, 1))
+ static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 113, 116896626.0)),
+ static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 113, 2240315.0)),
+ static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 113, 30107.0)),
+ static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 113, 253.0)),
+ static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 113, 1.0))
};
return boost::math::tools::evaluate_rational(num, denom, z);
}
@@ -1127,7 +1127,7 @@ struct lanczos24m113 : public mpl::int_<113>
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 113, 0.374799931707148855771381263542708435935402853962736029347951399323367765509988401336565436e-8))
};
static const T denom[24] = {
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 113, 0)),
+ static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 113, 0.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 113, 0.112400072777760768e22)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 113, 0.414847677933545472e22)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 113, 6756146673770930688000.0)),
@@ -1146,11 +1146,11 @@ struct lanczos24m113 : public mpl::int_<113>
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 113, 3256091103430.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 113, 136717357942.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 113, 4546047198.0)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 113, 116896626)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 113, 2240315)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 113, 30107)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 113, 253)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 113, 1))
+ static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 113, 116896626.0)),
+ static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 113, 2240315.0)),
+ static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 113, 30107.0)),
+ static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 113, 253.0)),
+ static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 113, 1.0))
};
return boost::math::tools::evaluate_rational(num, denom, z);
}
diff --git a/boost/math/special_functions/log1p.hpp b/boost/math/special_functions/log1p.hpp
index 989bdc21b6..62f5b8027c 100644
--- a/boost/math/special_functions/log1p.hpp
+++ b/boost/math/special_functions/log1p.hpp
@@ -195,7 +195,7 @@ T log1p_imp(T const& x, const Policy& pol, const mpl::int_<64>&)
BOOST_MATH_BIG_CONSTANT(T, 64, 0.00441709903782239229447)
};
static const T Q[] = {
- BOOST_MATH_BIG_CONSTANT(T, 64, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 64, 4.26423872346263928361),
BOOST_MATH_BIG_CONSTANT(T, 64, 7.48189472704477708962),
BOOST_MATH_BIG_CONSTANT(T, 64, 6.94757016732904280913),
diff --git a/boost/math/special_functions/math_fwd.hpp b/boost/math/special_functions/math_fwd.hpp
index 982cdf7ca3..e952dcdb51 100644
--- a/boost/math/special_functions/math_fwd.hpp
+++ b/boost/math/special_functions/math_fwd.hpp
@@ -14,7 +14,7 @@
// IT = Integer type.
// RT = Real type (built-in floating-point types, float, double, long double) & User Defined Types
-// AT = Integer or Real type
+// AT = Integer or Real type
#ifndef BOOST_MATH_SPECIAL_MATH_FWD_HPP
#define BOOST_MATH_SPECIAL_MATH_FWD_HPP
@@ -28,7 +28,6 @@
#include <boost/math/policies/policy.hpp>
#include <boost/mpl/comparison.hpp>
#include <boost/config/no_tr1/complex.hpp>
-#include <complex>
#define BOOST_NO_MACRO_EXPAND /**/
@@ -39,111 +38,111 @@ namespace boost
// Beta functions.
template <class RT1, class RT2>
- typename tools::promote_args<RT1, RT2>::type
+ typename tools::promote_args<RT1, RT2>::type
beta(RT1 a, RT2 b); // Beta function (2 arguments).
template <class RT1, class RT2, class A>
- typename tools::promote_args<RT1, RT2, A>::type
+ typename tools::promote_args<RT1, RT2, A>::type
beta(RT1 a, RT2 b, A x); // Beta function (3 arguments).
template <class RT1, class RT2, class RT3, class Policy>
- typename tools::promote_args<RT1, RT2, RT3>::type
+ typename tools::promote_args<RT1, RT2, RT3>::type
beta(RT1 a, RT2 b, RT3 x, const Policy& pol); // Beta function (3 arguments).
template <class RT1, class RT2, class RT3>
- typename tools::promote_args<RT1, RT2, RT3>::type
+ typename tools::promote_args<RT1, RT2, RT3>::type
betac(RT1 a, RT2 b, RT3 x);
template <class RT1, class RT2, class RT3, class Policy>
- typename tools::promote_args<RT1, RT2, RT3>::type
+ typename tools::promote_args<RT1, RT2, RT3>::type
betac(RT1 a, RT2 b, RT3 x, const Policy& pol);
template <class RT1, class RT2, class RT3>
- typename tools::promote_args<RT1, RT2, RT3>::type
+ typename tools::promote_args<RT1, RT2, RT3>::type
ibeta(RT1 a, RT2 b, RT3 x); // Incomplete beta function.
template <class RT1, class RT2, class RT3, class Policy>
- typename tools::promote_args<RT1, RT2, RT3>::type
+ typename tools::promote_args<RT1, RT2, RT3>::type
ibeta(RT1 a, RT2 b, RT3 x, const Policy& pol); // Incomplete beta function.
template <class RT1, class RT2, class RT3>
- typename tools::promote_args<RT1, RT2, RT3>::type
+ typename tools::promote_args<RT1, RT2, RT3>::type
ibetac(RT1 a, RT2 b, RT3 x); // Incomplete beta complement function.
template <class RT1, class RT2, class RT3, class Policy>
- typename tools::promote_args<RT1, RT2, RT3>::type
+ typename tools::promote_args<RT1, RT2, RT3>::type
ibetac(RT1 a, RT2 b, RT3 x, const Policy& pol); // Incomplete beta complement function.
template <class T1, class T2, class T3, class T4>
- typename tools::promote_args<T1, T2, T3, T4>::type
+ typename tools::promote_args<T1, T2, T3, T4>::type
ibeta_inv(T1 a, T2 b, T3 p, T4* py);
template <class T1, class T2, class T3, class T4, class Policy>
- typename tools::promote_args<T1, T2, T3, T4>::type
+ typename tools::promote_args<T1, T2, T3, T4>::type
ibeta_inv(T1 a, T2 b, T3 p, T4* py, const Policy& pol);
template <class RT1, class RT2, class RT3>
- typename tools::promote_args<RT1, RT2, RT3>::type
+ typename tools::promote_args<RT1, RT2, RT3>::type
ibeta_inv(RT1 a, RT2 b, RT3 p); // Incomplete beta inverse function.
template <class RT1, class RT2, class RT3, class Policy>
- typename tools::promote_args<RT1, RT2, RT3>::type
+ typename tools::promote_args<RT1, RT2, RT3>::type
ibeta_inv(RT1 a, RT2 b, RT3 p, const Policy&); // Incomplete beta inverse function.
template <class RT1, class RT2, class RT3>
- typename tools::promote_args<RT1, RT2, RT3>::type
+ typename tools::promote_args<RT1, RT2, RT3>::type
ibeta_inva(RT1 a, RT2 b, RT3 p); // Incomplete beta inverse function.
template <class RT1, class RT2, class RT3, class Policy>
- typename tools::promote_args<RT1, RT2, RT3>::type
+ typename tools::promote_args<RT1, RT2, RT3>::type
ibeta_inva(RT1 a, RT2 b, RT3 p, const Policy&); // Incomplete beta inverse function.
template <class RT1, class RT2, class RT3>
- typename tools::promote_args<RT1, RT2, RT3>::type
+ typename tools::promote_args<RT1, RT2, RT3>::type
ibeta_invb(RT1 a, RT2 b, RT3 p); // Incomplete beta inverse function.
template <class RT1, class RT2, class RT3, class Policy>
- typename tools::promote_args<RT1, RT2, RT3>::type
+ typename tools::promote_args<RT1, RT2, RT3>::type
ibeta_invb(RT1 a, RT2 b, RT3 p, const Policy&); // Incomplete beta inverse function.
template <class T1, class T2, class T3, class T4>
- typename tools::promote_args<T1, T2, T3, T4>::type
+ typename tools::promote_args<T1, T2, T3, T4>::type
ibetac_inv(T1 a, T2 b, T3 q, T4* py);
template <class T1, class T2, class T3, class T4, class Policy>
- typename tools::promote_args<T1, T2, T3, T4>::type
+ typename tools::promote_args<T1, T2, T3, T4>::type
ibetac_inv(T1 a, T2 b, T3 q, T4* py, const Policy& pol);
template <class RT1, class RT2, class RT3>
- typename tools::promote_args<RT1, RT2, RT3>::type
+ typename tools::promote_args<RT1, RT2, RT3>::type
ibetac_inv(RT1 a, RT2 b, RT3 q); // Incomplete beta complement inverse function.
template <class RT1, class RT2, class RT3, class Policy>
- typename tools::promote_args<RT1, RT2, RT3>::type
+ typename tools::promote_args<RT1, RT2, RT3>::type
ibetac_inv(RT1 a, RT2 b, RT3 q, const Policy&); // Incomplete beta complement inverse function.
template <class RT1, class RT2, class RT3>
- typename tools::promote_args<RT1, RT2, RT3>::type
+ typename tools::promote_args<RT1, RT2, RT3>::type
ibetac_inva(RT1 a, RT2 b, RT3 q); // Incomplete beta complement inverse function.
template <class RT1, class RT2, class RT3, class Policy>
- typename tools::promote_args<RT1, RT2, RT3>::type
+ typename tools::promote_args<RT1, RT2, RT3>::type
ibetac_inva(RT1 a, RT2 b, RT3 q, const Policy&); // Incomplete beta complement inverse function.
template <class RT1, class RT2, class RT3>
- typename tools::promote_args<RT1, RT2, RT3>::type
+ typename tools::promote_args<RT1, RT2, RT3>::type
ibetac_invb(RT1 a, RT2 b, RT3 q); // Incomplete beta complement inverse function.
template <class RT1, class RT2, class RT3, class Policy>
- typename tools::promote_args<RT1, RT2, RT3>::type
+ typename tools::promote_args<RT1, RT2, RT3>::type
ibetac_invb(RT1 a, RT2 b, RT3 q, const Policy&); // Incomplete beta complement inverse function.
template <class RT1, class RT2, class RT3>
- typename tools::promote_args<RT1, RT2, RT3>::type
+ typename tools::promote_args<RT1, RT2, RT3>::type
ibeta_derivative(RT1 a, RT2 b, RT3 x); // derivative of incomplete beta
template <class RT1, class RT2, class RT3, class Policy>
- typename tools::promote_args<RT1, RT2, RT3>::type
+ typename tools::promote_args<RT1, RT2, RT3>::type
ibeta_derivative(RT1 a, RT2 b, RT3 x, const Policy& pol); // derivative of incomplete beta
// erf & erfc error functions.
@@ -169,51 +168,51 @@ namespace boost
// Polynomials:
template <class T1, class T2, class T3>
- typename tools::promote_args<T1, T2, T3>::type
+ typename tools::promote_args<T1, T2, T3>::type
legendre_next(unsigned l, T1 x, T2 Pl, T3 Plm1);
template <class T>
- typename tools::promote_args<T>::type
+ typename tools::promote_args<T>::type
legendre_p(int l, T x);
template <class T, class Policy>
- typename tools::promote_args<T>::type
+ typename tools::promote_args<T>::type
legendre_p(int l, T x, const Policy& pol);
template <class T>
- typename tools::promote_args<T>::type
+ typename tools::promote_args<T>::type
legendre_q(unsigned l, T x);
template <class T, class Policy>
- typename tools::promote_args<T>::type
+ typename tools::promote_args<T>::type
legendre_q(unsigned l, T x, const Policy& pol);
template <class T1, class T2, class T3>
- typename tools::promote_args<T1, T2, T3>::type
+ typename tools::promote_args<T1, T2, T3>::type
legendre_next(unsigned l, unsigned m, T1 x, T2 Pl, T3 Plm1);
template <class T>
- typename tools::promote_args<T>::type
+ typename tools::promote_args<T>::type
legendre_p(int l, int m, T x);
template <class T, class Policy>
- typename tools::promote_args<T>::type
+ typename tools::promote_args<T>::type
legendre_p(int l, int m, T x, const Policy& pol);
template <class T1, class T2, class T3>
- typename tools::promote_args<T1, T2, T3>::type
+ typename tools::promote_args<T1, T2, T3>::type
laguerre_next(unsigned n, T1 x, T2 Ln, T3 Lnm1);
template <class T1, class T2, class T3>
- typename tools::promote_args<T1, T2, T3>::type
+ typename tools::promote_args<T1, T2, T3>::type
laguerre_next(unsigned n, unsigned l, T1 x, T2 Pl, T3 Plm1);
template <class T>
- typename tools::promote_args<T>::type
+ typename tools::promote_args<T>::type
laguerre(unsigned n, T x);
template <class T, class Policy>
- typename tools::promote_args<T>::type
+ typename tools::promote_args<T>::type
laguerre(unsigned n, unsigned m, T x, const Policy& pol);
template <class T1, class T2>
@@ -227,76 +226,76 @@ namespace boost
};
template <class T1, class T2>
- typename laguerre_result<T1, T2>::type
+ typename laguerre_result<T1, T2>::type
laguerre(unsigned n, T1 m, T2 x);
template <class T>
- typename tools::promote_args<T>::type
+ typename tools::promote_args<T>::type
hermite(unsigned n, T x);
template <class T, class Policy>
- typename tools::promote_args<T>::type
+ typename tools::promote_args<T>::type
hermite(unsigned n, T x, const Policy& pol);
template <class T1, class T2, class T3>
- typename tools::promote_args<T1, T2, T3>::type
+ typename tools::promote_args<T1, T2, T3>::type
hermite_next(unsigned n, T1 x, T2 Hn, T3 Hnm1);
template <class T1, class T2>
- std::complex<typename tools::promote_args<T1, T2>::type>
+ std::complex<typename tools::promote_args<T1, T2>::type>
spherical_harmonic(unsigned n, int m, T1 theta, T2 phi);
template <class T1, class T2, class Policy>
- std::complex<typename tools::promote_args<T1, T2>::type>
+ std::complex<typename tools::promote_args<T1, T2>::type>
spherical_harmonic(unsigned n, int m, T1 theta, T2 phi, const Policy& pol);
template <class T1, class T2>
- typename tools::promote_args<T1, T2>::type
+ typename tools::promote_args<T1, T2>::type
spherical_harmonic_r(unsigned n, int m, T1 theta, T2 phi);
template <class T1, class T2, class Policy>
- typename tools::promote_args<T1, T2>::type
+ typename tools::promote_args<T1, T2>::type
spherical_harmonic_r(unsigned n, int m, T1 theta, T2 phi, const Policy& pol);
template <class T1, class T2>
- typename tools::promote_args<T1, T2>::type
+ typename tools::promote_args<T1, T2>::type
spherical_harmonic_i(unsigned n, int m, T1 theta, T2 phi);
template <class T1, class T2, class Policy>
- typename tools::promote_args<T1, T2>::type
+ typename tools::promote_args<T1, T2>::type
spherical_harmonic_i(unsigned n, int m, T1 theta, T2 phi, const Policy& pol);
// Elliptic integrals:
template <class T1, class T2, class T3>
- typename tools::promote_args<T1, T2, T3>::type
+ typename tools::promote_args<T1, T2, T3>::type
ellint_rf(T1 x, T2 y, T3 z);
template <class T1, class T2, class T3, class Policy>
- typename tools::promote_args<T1, T2, T3>::type
+ typename tools::promote_args<T1, T2, T3>::type
ellint_rf(T1 x, T2 y, T3 z, const Policy& pol);
template <class T1, class T2, class T3>
- typename tools::promote_args<T1, T2, T3>::type
+ typename tools::promote_args<T1, T2, T3>::type
ellint_rd(T1 x, T2 y, T3 z);
template <class T1, class T2, class T3, class Policy>
- typename tools::promote_args<T1, T2, T3>::type
+ typename tools::promote_args<T1, T2, T3>::type
ellint_rd(T1 x, T2 y, T3 z, const Policy& pol);
template <class T1, class T2>
- typename tools::promote_args<T1, T2>::type
+ typename tools::promote_args<T1, T2>::type
ellint_rc(T1 x, T2 y);
template <class T1, class T2, class Policy>
- typename tools::promote_args<T1, T2>::type
+ typename tools::promote_args<T1, T2>::type
ellint_rc(T1 x, T2 y, const Policy& pol);
template <class T1, class T2, class T3, class T4>
- typename tools::promote_args<T1, T2, T3, T4>::type
+ typename tools::promote_args<T1, T2, T3, T4>::type
ellint_rj(T1 x, T2 y, T3 z, T4 p);
template <class T1, class T2, class T3, class T4, class Policy>
- typename tools::promote_args<T1, T2, T3, T4>::type
+ typename tools::promote_args<T1, T2, T3, T4>::type
ellint_rj(T1 x, T2 y, T3 z, T4 p, const Policy& pol);
template <typename T>
@@ -350,7 +349,7 @@ namespace boost
template <class RT, class Policy>
RT factorial(unsigned int, const Policy& pol);
template <class RT>
- RT unchecked_factorial(unsigned int BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(RT));
+ RT unchecked_factorial(unsigned int BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(RT));
template <class RT>
RT double_factorial(unsigned i);
template <class RT, class Policy>
@@ -466,11 +465,11 @@ namespace boost
// Hypotenuse function sqrt(x ^ 2 + y ^ 2).
template <class T1, class T2>
- typename tools::promote_args<T1, T2>::type
+ typename tools::promote_args<T1, T2>::type
hypot(T1 x, T2 y);
template <class T1, class T2, class Policy>
- typename tools::promote_args<T1, T2>::type
+ typename tools::promote_args<T1, T2>::type
hypot(T1 x, T2 y, const Policy&);
// cbrt - cube root.
@@ -503,11 +502,11 @@ namespace boost
// Power - 1
template <class T1, class T2>
- typename tools::promote_args<T1, T2>::type
+ typename tools::promote_args<T1, T2>::type
powm1(const T1 a, const T2 z);
template <class T1, class T2, class Policy>
- typename tools::promote_args<T1, T2>::type
+ typename tools::promote_args<T1, T2>::type
powm1(const T1 a, const T2 z, const Policy&);
// sqrt(1+x) - 1
@@ -581,47 +580,109 @@ namespace boost
// Bessel functions:
template <class T1, class T2, class Policy>
typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_bessel_j(T1 v, T2 x, const Policy& pol);
+ template <class T1, class T2, class Policy>
+ typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_bessel_j_prime(T1 v, T2 x, const Policy& pol);
template <class T1, class T2>
typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type cyl_bessel_j(T1 v, T2 x);
+ template <class T1, class T2>
+ typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type cyl_bessel_j_prime(T1 v, T2 x);
template <class T, class Policy>
typename detail::bessel_traits<T, T, Policy>::result_type sph_bessel(unsigned v, T x, const Policy& pol);
+ template <class T, class Policy>
+ typename detail::bessel_traits<T, T, Policy>::result_type sph_bessel_prime(unsigned v, T x, const Policy& pol);
template <class T>
typename detail::bessel_traits<T, T, policies::policy<> >::result_type sph_bessel(unsigned v, T x);
+ template <class T>
+ typename detail::bessel_traits<T, T, policies::policy<> >::result_type sph_bessel_prime(unsigned v, T x);
template <class T1, class T2, class Policy>
typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_bessel_i(T1 v, T2 x, const Policy& pol);
+ template <class T1, class T2, class Policy>
+ typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_bessel_i_prime(T1 v, T2 x, const Policy& pol);
template <class T1, class T2>
typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type cyl_bessel_i(T1 v, T2 x);
+ template <class T1, class T2>
+ typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type cyl_bessel_i_prime(T1 v, T2 x);
template <class T1, class T2, class Policy>
typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_bessel_k(T1 v, T2 x, const Policy& pol);
+ template <class T1, class T2, class Policy>
+ typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_bessel_k_prime(T1 v, T2 x, const Policy& pol);
template <class T1, class T2>
typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type cyl_bessel_k(T1 v, T2 x);
+ template <class T1, class T2>
+ typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type cyl_bessel_k_prime(T1 v, T2 x);
template <class T1, class T2, class Policy>
typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_neumann(T1 v, T2 x, const Policy& pol);
+ template <class T1, class T2, class Policy>
+ typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_neumann_prime(T1 v, T2 x, const Policy& pol);
template <class T1, class T2>
typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type cyl_neumann(T1 v, T2 x);
+ template <class T1, class T2>
+ typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type cyl_neumann_prime(T1 v, T2 x);
template <class T, class Policy>
typename detail::bessel_traits<T, T, Policy>::result_type sph_neumann(unsigned v, T x, const Policy& pol);
+ template <class T, class Policy>
+ typename detail::bessel_traits<T, T, Policy>::result_type sph_neumann_prime(unsigned v, T x, const Policy& pol);
template <class T>
typename detail::bessel_traits<T, T, policies::policy<> >::result_type sph_neumann(unsigned v, T x);
+ template <class T>
+ typename detail::bessel_traits<T, T, policies::policy<> >::result_type sph_neumann_prime(unsigned v, T x);
- template <class T1, class T2, class Policy>
- std::complex<typename detail::bessel_traits<T1, T2, Policy>::result_type> cyl_hankel_1(T1 v, T2 x, const Policy& pol);
+ template <class T, class Policy>
+ typename detail::bessel_traits<T, T, Policy>::result_type cyl_bessel_j_zero(T v, int m, const Policy& pol);
+
+ template <class T>
+ typename detail::bessel_traits<T, T, policies::policy<> >::result_type cyl_bessel_j_zero(T v, int m);
+
+ template <class T, class OutputIterator>
+ OutputIterator cyl_bessel_j_zero(T v,
+ int start_index,
+ unsigned number_of_zeros,
+ OutputIterator out_it);
+
+ template <class T, class OutputIterator, class Policy>
+ OutputIterator cyl_bessel_j_zero(T v,
+ int start_index,
+ unsigned number_of_zeros,
+ OutputIterator out_it,
+ const Policy&);
+
+ template <class T, class Policy>
+ typename detail::bessel_traits<T, T, Policy>::result_type cyl_neumann_zero(T v, int m, const Policy& pol);
+
+ template <class T>
+ typename detail::bessel_traits<T, T, policies::policy<> >::result_type cyl_neumann_zero(T v, int m);
+
+ template <class T, class OutputIterator>
+ OutputIterator cyl_neumann_zero(T v,
+ int start_index,
+ unsigned number_of_zeros,
+ OutputIterator out_it);
+
+ template <class T, class OutputIterator, class Policy>
+ OutputIterator cyl_neumann_zero(T v,
+ int start_index,
+ unsigned number_of_zeros,
+ OutputIterator out_it,
+ const Policy&);
template <class T1, class T2>
std::complex<typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type> cyl_hankel_1(T1 v, T2 x);
template <class T1, class T2, class Policy>
+ std::complex<typename detail::bessel_traits<T1, T2, Policy>::result_type> cyl_hankel_1(T1 v, T2 x, const Policy& pol);
+
+ template <class T1, class T2, class Policy>
std::complex<typename detail::bessel_traits<T1, T2, Policy>::result_type> cyl_hankel_2(T1 v, T2 x, const Policy& pol);
template <class T1, class T2>
@@ -640,6 +701,64 @@ namespace boost
std::complex<typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type> sph_hankel_2(T1 v, T2 x);
template <class T, class Policy>
+ typename tools::promote_args<T>::type airy_ai(T x, const Policy&);
+
+ template <class T>
+ typename tools::promote_args<T>::type airy_ai(T x);
+
+ template <class T, class Policy>
+ typename tools::promote_args<T>::type airy_bi(T x, const Policy&);
+
+ template <class T>
+ typename tools::promote_args<T>::type airy_bi(T x);
+
+ template <class T, class Policy>
+ typename tools::promote_args<T>::type airy_ai_prime(T x, const Policy&);
+
+ template <class T>
+ typename tools::promote_args<T>::type airy_ai_prime(T x);
+
+ template <class T, class Policy>
+ typename tools::promote_args<T>::type airy_bi_prime(T x, const Policy&);
+
+ template <class T>
+ typename tools::promote_args<T>::type airy_bi_prime(T x);
+
+ template <class T>
+ T airy_ai_zero(int m);
+ template <class T, class Policy>
+ T airy_ai_zero(int m, const Policy&);
+
+ template <class OutputIterator>
+ OutputIterator airy_ai_zero(
+ int start_index,
+ unsigned number_of_zeros,
+ OutputIterator out_it);
+ template <class OutputIterator, class Policy>
+ OutputIterator airy_ai_zero(
+ int start_index,
+ unsigned number_of_zeros,
+ OutputIterator out_it,
+ const Policy&);
+
+ template <class T>
+ T airy_bi_zero(int m);
+ template <class T, class Policy>
+ T airy_bi_zero(int m, const Policy&);
+
+ template <class OutputIterator>
+ OutputIterator airy_bi_zero(
+ int start_index,
+ unsigned number_of_zeros,
+ OutputIterator out_it);
+ template <class OutputIterator, class Policy>
+ OutputIterator airy_bi_zero(
+ int start_index,
+ unsigned number_of_zeros,
+ OutputIterator out_it,
+ const Policy&);
+
+ template <class T, class Policy>
typename tools::promote_args<T>::type sin_pi(T x, const Policy&);
template <class T>
@@ -666,17 +785,17 @@ namespace boost
template <class T>
bool isnormal BOOST_NO_MACRO_EXPAND(T t);
- template<class T>
+ template<class T>
int signbit BOOST_NO_MACRO_EXPAND(T x);
template <class T>
int sign BOOST_NO_MACRO_EXPAND(const T& z);
- template <class T>
- T copysign BOOST_NO_MACRO_EXPAND(const T& x, const T& y);
+ template <class T, class U>
+ typename tools::promote_args_permissive<T, U>::type copysign BOOST_NO_MACRO_EXPAND(const T& x, const U& y);
template <class T>
- T changesign BOOST_NO_MACRO_EXPAND(const T& z);
+ typename tools::promote_args_permissive<T>::type changesign BOOST_NO_MACRO_EXPAND(const T& z);
// Exponential integrals:
namespace detail{
@@ -713,6 +832,86 @@ namespace boost
template <class T1, class T2>
typename tools::promote_args<T1, T2>::type owens_t(T1 h, T2 a);
+ // Jacobi Functions:
+ template <class T, class U, class V, class Policy>
+ typename tools::promote_args<T, U, V>::type jacobi_elliptic(T k, U theta, V* pcn, V* pdn, const Policy&);
+
+ template <class T, class U, class V>
+ typename tools::promote_args<T, U, V>::type jacobi_elliptic(T k, U theta, V* pcn = 0, V* pdn = 0);
+
+ template <class U, class T, class Policy>
+ typename tools::promote_args<T, U>::type jacobi_sn(U k, T theta, const Policy& pol);
+
+ template <class U, class T>
+ typename tools::promote_args<T, U>::type jacobi_sn(U k, T theta);
+
+ template <class T, class U, class Policy>
+ typename tools::promote_args<T, U>::type jacobi_cn(T k, U theta, const Policy& pol);
+
+ template <class T, class U>
+ typename tools::promote_args<T, U>::type jacobi_cn(T k, U theta);
+
+ template <class T, class U, class Policy>
+ typename tools::promote_args<T, U>::type jacobi_dn(T k, U theta, const Policy& pol);
+
+ template <class T, class U>
+ typename tools::promote_args<T, U>::type jacobi_dn(T k, U theta);
+
+ template <class T, class U, class Policy>
+ typename tools::promote_args<T, U>::type jacobi_cd(T k, U theta, const Policy& pol);
+
+ template <class T, class U>
+ typename tools::promote_args<T, U>::type jacobi_cd(T k, U theta);
+
+ template <class T, class U, class Policy>
+ typename tools::promote_args<T, U>::type jacobi_dc(T k, U theta, const Policy& pol);
+
+ template <class T, class U>
+ typename tools::promote_args<T, U>::type jacobi_dc(T k, U theta);
+
+ template <class T, class U, class Policy>
+ typename tools::promote_args<T, U>::type jacobi_ns(T k, U theta, const Policy& pol);
+
+ template <class T, class U>
+ typename tools::promote_args<T, U>::type jacobi_ns(T k, U theta);
+
+ template <class T, class U, class Policy>
+ typename tools::promote_args<T, U>::type jacobi_sd(T k, U theta, const Policy& pol);
+
+ template <class T, class U>
+ typename tools::promote_args<T, U>::type jacobi_sd(T k, U theta);
+
+ template <class T, class U, class Policy>
+ typename tools::promote_args<T, U>::type jacobi_ds(T k, U theta, const Policy& pol);
+
+ template <class T, class U>
+ typename tools::promote_args<T, U>::type jacobi_ds(T k, U theta);
+
+ template <class T, class U, class Policy>
+ typename tools::promote_args<T, U>::type jacobi_nc(T k, U theta, const Policy& pol);
+
+ template <class T, class U>
+ typename tools::promote_args<T, U>::type jacobi_nc(T k, U theta);
+
+ template <class T, class U, class Policy>
+ typename tools::promote_args<T, U>::type jacobi_nd(T k, U theta, const Policy& pol);
+
+ template <class T, class U>
+ typename tools::promote_args<T, U>::type jacobi_nd(T k, U theta);
+
+ template <class T, class U, class Policy>
+ typename tools::promote_args<T, U>::type jacobi_sc(T k, U theta, const Policy& pol);
+
+ template <class T, class U>
+ typename tools::promote_args<T, U>::type jacobi_sc(T k, U theta);
+
+ template <class T, class U, class Policy>
+ typename tools::promote_args<T, U>::type jacobi_cs(T k, U theta, const Policy& pol);
+
+ template <class T, class U>
+ typename tools::promote_args<T, U>::type jacobi_cs(T k, U theta);
+
+
template <class T>
typename tools::promote_args<T>::type zeta(T s);
@@ -724,22 +923,55 @@ namespace boost
typename tools::promote_args<T>::type pow(T base);
// next:
+ template <class T, class U, class Policy>
+ typename tools::promote_args<T, U>::type nextafter(const T&, const U&, const Policy&);
+ template <class T, class U>
+ typename tools::promote_args<T, U>::type nextafter(const T&, const U&);
template <class T, class Policy>
- T nextafter(const T&, const T&, const Policy&);
+ typename tools::promote_args<T>::type float_next(const T&, const Policy&);
template <class T>
- T nextafter(const T&, const T&);
+ typename tools::promote_args<T>::type float_next(const T&);
template <class T, class Policy>
- T float_next(const T&, const Policy&);
+ typename tools::promote_args<T>::type float_prior(const T&, const Policy&);
template <class T>
- T float_next(const T&);
+ typename tools::promote_args<T>::type float_prior(const T&);
+ template <class T, class U, class Policy>
+ typename tools::promote_args<T, U>::type float_distance(const T&, const U&, const Policy&);
+ template <class T, class U>
+ typename tools::promote_args<T, U>::type float_distance(const T&, const U&);
template <class T, class Policy>
- T float_prior(const T&, const Policy&);
+ typename tools::promote_args<T>::type float_advance(T val, int distance, const Policy& pol);
template <class T>
- T float_prior(const T&);
+ typename tools::promote_args<T>::type float_advance(const T& val, int distance);
+
+ template<class T>
+ T unchecked_bernoulli_b2n(const std::size_t n);
template <class T, class Policy>
- T float_distance(const T&, const T&, const Policy&);
+ T bernoulli_b2n(const int i, const Policy &pol);
template <class T>
- T float_distance(const T&, const T&);
+ T bernoulli_b2n(const int i);
+ template <class T, class OutputIterator, class Policy>
+ OutputIterator bernoulli_b2n(const int start_index,
+ const unsigned number_of_bernoullis_b2n,
+ OutputIterator out_it,
+ const Policy& pol);
+ template <class T, class OutputIterator>
+ OutputIterator bernoulli_b2n(const int start_index,
+ const unsigned number_of_bernoullis_b2n,
+ OutputIterator out_it);
+ template <class T, class Policy>
+ T tangent_t2n(const int i, const Policy &pol);
+ template <class T>
+ T tangent_t2n(const int i);
+ template <class T, class OutputIterator, class Policy>
+ OutputIterator tangent_t2n(const int start_index,
+ const unsigned number_of_bernoullis_b2n,
+ OutputIterator out_it,
+ const Policy& pol);
+ template <class T, class OutputIterator>
+ OutputIterator tangent_t2n(const int start_index,
+ const unsigned number_of_bernoullis_b2n,
+ OutputIterator out_it);
} // namespace math
} // namespace boost
@@ -1015,27 +1247,73 @@ namespace boost
inline typename boost::math::detail::bessel_traits<T1, T2, Policy >::result_type cyl_bessel_j(T1 v, T2 x)\
{ return boost::math::cyl_bessel_j(v, x, Policy()); }\
\
+ template <class T1, class T2>\
+ inline typename boost::math::detail::bessel_traits<T1, T2, Policy >::result_type cyl_bessel_j_prime(T1 v, T2 x)\
+ { return boost::math::cyl_bessel_j_prime(v, x, Policy()); }\
+\
template <class T>\
inline typename boost::math::detail::bessel_traits<T, T, Policy >::result_type sph_bessel(unsigned v, T x)\
{ return boost::math::sph_bessel(v, x, Policy()); }\
\
+ template <class T>\
+ inline typename boost::math::detail::bessel_traits<T, T, Policy >::result_type sph_bessel_prime(unsigned v, T x)\
+ { return boost::math::sph_bessel_prime(v, x, Policy()); }\
+\
template <class T1, class T2>\
inline typename boost::math::detail::bessel_traits<T1, T2, Policy >::result_type \
cyl_bessel_i(T1 v, T2 x) { return boost::math::cyl_bessel_i(v, x, Policy()); }\
\
template <class T1, class T2>\
inline typename boost::math::detail::bessel_traits<T1, T2, Policy >::result_type \
+ cyl_bessel_i_prime(T1 v, T2 x) { return boost::math::cyl_bessel_i_prime(v, x, Policy()); }\
+\
+ template <class T1, class T2>\
+ inline typename boost::math::detail::bessel_traits<T1, T2, Policy >::result_type \
cyl_bessel_k(T1 v, T2 x) { return boost::math::cyl_bessel_k(v, x, Policy()); }\
\
template <class T1, class T2>\
inline typename boost::math::detail::bessel_traits<T1, T2, Policy >::result_type \
+ cyl_bessel_k_prime(T1 v, T2 x) { return boost::math::cyl_bessel_k_prime(v, x, Policy()); }\
+\
+ template <class T1, class T2>\
+ inline typename boost::math::detail::bessel_traits<T1, T2, Policy >::result_type \
cyl_neumann(T1 v, T2 x){ return boost::math::cyl_neumann(v, x, Policy()); }\
\
+ template <class T1, class T2>\
+ inline typename boost::math::detail::bessel_traits<T1, T2, Policy >::result_type \
+ cyl_neumann_prime(T1 v, T2 x){ return boost::math::cyl_neumann_prime(v, x, Policy()); }\
+\
template <class T>\
inline typename boost::math::detail::bessel_traits<T, T, Policy >::result_type \
sph_neumann(unsigned v, T x){ return boost::math::sph_neumann(v, x, Policy()); }\
\
template <class T>\
+ inline typename boost::math::detail::bessel_traits<T, T, Policy >::result_type \
+ sph_neumann_prime(unsigned v, T x){ return boost::math::sph_neumann_prime(v, x, Policy()); }\
+\
+ template <class T>\
+ inline typename boost::math::detail::bessel_traits<T, T, Policy >::result_type cyl_bessel_j_zero(T v, int m)\
+ { return boost::math::cyl_bessel_j_zero(v, m, Policy()); }\
+\
+template <class OutputIterator, class T>\
+ inline void cyl_bessel_j_zero(T v,\
+ int start_index,\
+ unsigned number_of_zeros,\
+ OutputIterator out_it)\
+ { boost::math::cyl_bessel_j_zero(v, start_index, number_of_zeros, out_it, Policy()); }\
+\
+ template <class T>\
+ inline typename boost::math::detail::bessel_traits<T, T, Policy >::result_type cyl_neumann_zero(T v, int m)\
+ { return boost::math::cyl_neumann_zero(v, m, Policy()); }\
+\
+template <class OutputIterator, class T>\
+ inline void cyl_neumann_zero(T v,\
+ int start_index,\
+ unsigned number_of_zeros,\
+ OutputIterator out_it)\
+ { boost::math::cyl_neumann_zero(v, start_index, number_of_zeros, out_it, Policy()); }\
+\
+ template <class T>\
inline typename boost::math::tools::promote_args<T>::type sin_pi(T x){ return boost::math::sin_pi(x); }\
\
template <class T>\
@@ -1114,6 +1392,105 @@ namespace boost
template <class T1, class T2>\
inline std::complex<typename boost::math::detail::bessel_traits<T1, T2, Policy >::result_type> sph_hankel_2(T1 v, T2 x)\
{ return boost::math::sph_hankel_2(v, x, Policy()); }\
+ \
+ template <class T>\
+ inline typename boost::math::tools::promote_args<T>::type jacobi_elliptic(T k, T theta, T* pcn, T* pdn)\
+ { return boost::math::jacobi_elliptic(k, theta, pcn, pdn, Policy()); }\
+ \
+ template <class U, class T>\
+ inline typename boost::math::tools::promote_args<T, U>::type jacobi_sn(U k, T theta)\
+ { return boost::math::jacobi_sn(k, theta, Policy()); }\
+ \
+ template <class T, class U>\
+ inline typename boost::math::tools::promote_args<T, U>::type jacobi_cn(T k, U theta)\
+ { return boost::math::jacobi_cn(k, theta, Policy()); }\
+ \
+ template <class T, class U>\
+ inline typename boost::math::tools::promote_args<T, U>::type jacobi_dn(T k, U theta)\
+ { return boost::math::jacobi_dn(k, theta, Policy()); }\
+ \
+ template <class T, class U>\
+ inline typename boost::math::tools::promote_args<T, U>::type jacobi_cd(T k, U theta)\
+ { return boost::math::jacobi_cd(k, theta, Policy()); }\
+ \
+ template <class T, class U>\
+ inline typename boost::math::tools::promote_args<T, U>::type jacobi_dc(T k, U theta)\
+ { return boost::math::jacobi_dc(k, theta, Policy()); }\
+ \
+ template <class T, class U>\
+ inline typename boost::math::tools::promote_args<T, U>::type jacobi_ns(T k, U theta)\
+ { return boost::math::jacobi_ns(k, theta, Policy()); }\
+ \
+ template <class T, class U>\
+ inline typename boost::math::tools::promote_args<T, U>::type jacobi_sd(T k, U theta)\
+ { return boost::math::jacobi_sd(k, theta, Policy()); }\
+ \
+ template <class T, class U>\
+ inline typename boost::math::tools::promote_args<T, U>::type jacobi_ds(T k, U theta)\
+ { return boost::math::jacobi_ds(k, theta, Policy()); }\
+ \
+ template <class T, class U>\
+ inline typename boost::math::tools::promote_args<T, U>::type jacobi_nc(T k, U theta)\
+ { return boost::math::jacobi_nc(k, theta, Policy()); }\
+ \
+ template <class T, class U>\
+ inline typename boost::math::tools::promote_args<T, U>::type jacobi_nd(T k, U theta)\
+ { return boost::math::jacobi_nd(k, theta, Policy()); }\
+ \
+ template <class T, class U>\
+ inline typename boost::math::tools::promote_args<T, U>::type jacobi_sc(T k, U theta)\
+ { return boost::math::jacobi_sc(k, theta, Policy()); }\
+ \
+ template <class T, class U>\
+ inline typename boost::math::tools::promote_args<T, U>::type jacobi_cs(T k, U theta)\
+ { return boost::math::jacobi_cs(k, theta, Policy()); }\
+ \
+ template <class T>\
+ inline typename boost::math::tools::promote_args<T>::type airy_ai(T x)\
+ { return boost::math::airy_ai(x, Policy()); }\
+ \
+ template <class T>\
+ inline typename boost::math::tools::promote_args<T>::type airy_bi(T x)\
+ { return boost::math::airy_bi(x, Policy()); }\
+ \
+ template <class T>\
+ inline typename boost::math::tools::promote_args<T>::type airy_ai_prime(T x)\
+ { return boost::math::airy_ai_prime(x, Policy()); }\
+ \
+ template <class T>\
+ inline typename boost::math::tools::promote_args<T>::type airy_bi_prime(T x)\
+ { return boost::math::airy_bi_prime(x, Policy()); }\
+ \
+ template <class T>\
+ inline T airy_ai_zero(int m)\
+ { return boost::math::airy_ai_zero<T>(m, Policy()); }\
+ template <class T, class OutputIterator>\
+ OutputIterator airy_ai_zero(int start_index, unsigned number_of_zeros, OutputIterator out_it)\
+ { return boost::math::airy_ai_zero<T>(start_index, number_of_zeros, out_it, Policy()); }\
+ \
+ template <class T>\
+ inline T airy_bi_zero(int m)\
+ { return boost::math::airy_bi_zero<T>(m, Policy()); }\
+ template <class T, class OutputIterator>\
+ OutputIterator airy_bi_zero(int start_index, unsigned number_of_zeros, OutputIterator out_it)\
+ { return boost::math::airy_bi_zero<T>(start_index, number_of_zeros, out_it, Policy()); }\
+ \
+ template <class T>\
+ T bernoulli_b2n(const int i)\
+ { return boost::math::bernoulli_b2n<T>(i, Policy()); }\
+ template <class T, class OutputIterator>\
+ OutputIterator bernoulli_b2n(int start_index, unsigned number_of_bernoullis_b2n, OutputIterator out_it)\
+ { return boost::math::bernoulli_b2n<T>(start_index, number_of_bernoullis_b2n, out_it, Policy()); }\
+ \
+ template <class T>\
+ T tangent_t2n(const int i)\
+ { return boost::math::tangent_t2n<T>(i, Policy()); }\
+ template <class T, class OutputIterator>\
+ OutputIterator tangent_t2n(int start_index, unsigned number_of_bernoullis_b2n, OutputIterator out_it)\
+ { return boost::math::tangent_t2n<T>(start_index, number_of_bernoullis_b2n, out_it, Policy()); }\
+ \
+
+
diff --git a/boost/math/special_functions/modf.hpp b/boost/math/special_functions/modf.hpp
index 48b15fe44f..3ce74e7aa3 100644
--- a/boost/math/special_functions/modf.hpp
+++ b/boost/math/special_functions/modf.hpp
@@ -10,6 +10,7 @@
#pragma once
#endif
+#include <boost/math/special_functions/math_fwd.hpp>
#include <boost/math/tools/config.hpp>
#include <boost/math/special_functions/trunc.hpp>
diff --git a/boost/math/special_functions/next.hpp b/boost/math/special_functions/next.hpp
index 6c91cd1e38..9602bc7697 100644
--- a/boost/math/special_functions/next.hpp
+++ b/boost/math/special_functions/next.hpp
@@ -10,13 +10,19 @@
#pragma once
#endif
+#include <boost/math/special_functions/math_fwd.hpp>
#include <boost/math/policies/error_handling.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
#include <boost/math/special_functions/sign.hpp>
#include <boost/math/special_functions/trunc.hpp>
-#ifdef BOOST_MSVC
#include <float.h>
+
+#if !defined(_CRAYC) && !defined(__CUDACC__) && (!defined(__GNUC__) || (__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ > 3)))
+#if (defined(_M_IX86_FP) && (_M_IX86_FP >= 2)) || defined(__SSE2__)
+#include "xmmintrin.h"
+#define BOOST_MATH_CHECK_SSE2
+#endif
#endif
namespace boost{ namespace math{
@@ -26,7 +32,17 @@ namespace detail{
template <class T>
inline T get_smallest_value(mpl::true_ const&)
{
- return std::numeric_limits<T>::denorm_min();
+ //
+ // numeric_limits lies about denorms being present - particularly
+ // when this can be turned on or off at runtime, as is the case
+ // when using the SSE2 registers in DAZ or FTZ mode.
+ //
+ static const T m = std::numeric_limits<T>::denorm_min();
+#ifdef BOOST_MATH_CHECK_SSE2
+ return (_mm_getcsr() & (_MM_FLUSH_ZERO_ON | 0x40)) ? tools::min_value<T>() : m;;
+#else
+ return ((tools::min_value<T>() / 2) == 0) ? tools::min_value<T>() : m;
+#endif
}
template <class T>
@@ -45,16 +61,59 @@ inline T get_smallest_value()
#endif
}
+//
+// Returns the smallest value that won't generate denorms when
+// we calculate the value of the least-significant-bit:
+//
+template <class T>
+T get_min_shift_value();
+
+template <class T>
+struct min_shift_initializer
+{
+ struct init
+ {
+ init()
+ {
+ do_init();
+ }
+ static void do_init()
+ {
+ get_min_shift_value<T>();
+ }
+ void force_instantiate()const{}
+ };
+ static const init initializer;
+ static void force_instantiate()
+ {
+ initializer.force_instantiate();
+ }
+};
+
+template <class T>
+const typename min_shift_initializer<T>::init min_shift_initializer<T>::initializer;
+
+
+template <class T>
+inline T get_min_shift_value()
+{
+ BOOST_MATH_STD_USING
+ static const T val = ldexp(tools::min_value<T>(), tools::digits<T>() + 1);
+ min_shift_initializer<T>::force_instantiate();
+
+ return val;
}
template <class T, class Policy>
-T float_next(const T& val, const Policy& pol)
+T float_next_imp(const T& val, const Policy& pol)
{
BOOST_MATH_STD_USING
int expon;
static const char* function = "float_next<%1%>(%1%)";
- if(!(boost::math::isfinite)(val))
+ int fpclass = (boost::math::fpclassify)(val);
+
+ if((fpclass == (int)FP_NAN) || (fpclass == (int)FP_INFINITE))
{
if(val < 0)
return -tools::max_value<T>();
@@ -69,6 +128,16 @@ T float_next(const T& val, const Policy& pol)
if(val == 0)
return detail::get_smallest_value<T>();
+ if((fpclass != (int)FP_SUBNORMAL) && (fpclass != (int)FP_ZERO) && (fabs(val) < detail::get_min_shift_value<T>()) && (val != -tools::min_value<T>()))
+ {
+ //
+ // Special case: if the value of the least significant bit is a denorm, and the result
+ // would not be a denorm, then shift the input, increment, and shift back.
+ // This avoids issues with the Intel SSE2 registers when the FTZ or DAZ flags are set.
+ //
+ return ldexp(float_next(T(ldexp(val, 2 * tools::digits<T>())), pol), -2 * tools::digits<T>());
+ }
+
if(-0.5f == frexp(val, &expon))
--expon; // reduce exponent when val is a power of two, and negative.
T diff = ldexp(T(1), expon - tools::digits<T>());
@@ -77,7 +146,21 @@ T float_next(const T& val, const Policy& pol)
return val + diff;
}
-#ifdef BOOST_MSVC
+}
+
+template <class T, class Policy>
+inline typename tools::promote_args<T>::type float_next(const T& val, const Policy& pol)
+{
+ typedef typename tools::promote_args<T>::type result_type;
+ return detail::float_next_imp(static_cast<result_type>(val), pol);
+}
+
+#if 0 //def BOOST_MSVC
+//
+// We used to use ::_nextafter here, but doing so fails when using
+// the SSE2 registers if the FTZ or DAZ flags are set, so use our own
+// - albeit slower - code instead as at least that gives the correct answer.
+//
template <class Policy>
inline double float_next(const double& val, const Policy& pol)
{
@@ -96,19 +179,23 @@ inline double float_next(const double& val, const Policy& pol)
#endif
template <class T>
-inline T float_next(const T& val)
+inline typename tools::promote_args<T>::type float_next(const T& val)
{
return float_next(val, policies::policy<>());
}
+namespace detail{
+
template <class T, class Policy>
-T float_prior(const T& val, const Policy& pol)
+T float_prior_imp(const T& val, const Policy& pol)
{
BOOST_MATH_STD_USING
int expon;
static const char* function = "float_prior<%1%>(%1%)";
- if(!(boost::math::isfinite)(val))
+ int fpclass = (boost::math::fpclassify)(val);
+
+ if((fpclass == (int)FP_NAN) || (fpclass == (int)FP_INFINITE))
{
if(val > 0)
return tools::max_value<T>();
@@ -123,6 +210,16 @@ T float_prior(const T& val, const Policy& pol)
if(val == 0)
return -detail::get_smallest_value<T>();
+ if((fpclass != (int)FP_SUBNORMAL) && (fpclass != (int)FP_ZERO) && (fabs(val) < detail::get_min_shift_value<T>()) && (val != tools::min_value<T>()))
+ {
+ //
+ // Special case: if the value of the least significant bit is a denorm, and the result
+ // would not be a denorm, then shift the input, increment, and shift back.
+ // This avoids issues with the Intel SSE2 registers when the FTZ or DAZ flags are set.
+ //
+ return ldexp(float_prior(T(ldexp(val, 2 * tools::digits<T>())), pol), -2 * tools::digits<T>());
+ }
+
T remain = frexp(val, &expon);
if(remain == 0.5)
--expon; // when val is a power of two we must reduce the exponent
@@ -132,7 +229,21 @@ T float_prior(const T& val, const Policy& pol)
return val - diff;
}
-#ifdef BOOST_MSVC
+}
+
+template <class T, class Policy>
+inline typename tools::promote_args<T>::type float_prior(const T& val, const Policy& pol)
+{
+ typedef typename tools::promote_args<T>::type result_type;
+ return detail::float_prior_imp(static_cast<result_type>(val), pol);
+}
+
+#if 0 //def BOOST_MSVC
+//
+// We used to use ::_nextafter here, but doing so fails when using
+// the SSE2 registers if the FTZ or DAZ flags are set, so use our own
+// - albeit slower - code instead as at least that gives the correct answer.
+//
template <class Policy>
inline double float_prior(const double& val, const Policy& pol)
{
@@ -151,25 +262,28 @@ inline double float_prior(const double& val, const Policy& pol)
#endif
template <class T>
-inline T float_prior(const T& val)
+inline typename tools::promote_args<T>::type float_prior(const T& val)
{
return float_prior(val, policies::policy<>());
}
-template <class T, class Policy>
-inline T nextafter(const T& val, const T& direction, const Policy& pol)
+template <class T, class U, class Policy>
+inline typename tools::promote_args<T, U>::type nextafter(const T& val, const U& direction, const Policy& pol)
{
- return val < direction ? boost::math::float_next(val, pol) : val == direction ? val : boost::math::float_prior(val, pol);
+ typedef typename tools::promote_args<T, U>::type result_type;
+ return val < direction ? boost::math::float_next<result_type>(val, pol) : val == direction ? val : boost::math::float_prior<result_type>(val, pol);
}
-template <class T>
-inline T nextafter(const T& val, const T& direction)
+template <class T, class U>
+inline typename tools::promote_args<T, U>::type nextafter(const T& val, const U& direction)
{
return nextafter(val, direction, policies::policy<>());
}
+namespace detail{
+
template <class T, class Policy>
-T float_distance(const T& a, const T& b, const Policy& pol)
+T float_distance_imp(const T& a, const T& b, const Policy& pol)
{
BOOST_MATH_STD_USING
//
@@ -188,22 +302,22 @@ T float_distance(const T& a, const T& b, const Policy& pol)
// Special cases:
//
if(a > b)
- return -float_distance(b, a);
+ return -float_distance(b, a, pol);
if(a == b)
return 0;
if(a == 0)
- return 1 + fabs(float_distance(static_cast<T>(boost::math::sign(b) * detail::get_smallest_value<T>()), b, pol));
+ return 1 + fabs(float_distance(static_cast<T>((b < 0) ? T(-detail::get_smallest_value<T>()) : detail::get_smallest_value<T>()), b, pol));
if(b == 0)
- return 1 + fabs(float_distance(static_cast<T>(boost::math::sign(a) * detail::get_smallest_value<T>()), a, pol));
+ return 1 + fabs(float_distance(static_cast<T>((a < 0) ? T(-detail::get_smallest_value<T>()) : detail::get_smallest_value<T>()), a, pol));
if(boost::math::sign(a) != boost::math::sign(b))
- return 2 + fabs(float_distance(static_cast<T>(boost::math::sign(b) * detail::get_smallest_value<T>()), b, pol))
- + fabs(float_distance(static_cast<T>(boost::math::sign(a) * detail::get_smallest_value<T>()), a, pol));
+ return 2 + fabs(float_distance(static_cast<T>((b < 0) ? T(-detail::get_smallest_value<T>()) : detail::get_smallest_value<T>()), b, pol))
+ + fabs(float_distance(static_cast<T>((a < 0) ? T(-detail::get_smallest_value<T>()) : detail::get_smallest_value<T>()), a, pol));
//
// By the time we get here, both a and b must have the same sign, we want
// b > a and both postive for the following logic:
//
if(a < 0)
- return float_distance(static_cast<T>(-b), static_cast<T>(-a));
+ return float_distance(static_cast<T>(-b), static_cast<T>(-a), pol);
BOOST_ASSERT(a >= 0);
BOOST_ASSERT(b >= a);
@@ -214,7 +328,7 @@ T float_distance(const T& a, const T& b, const Policy& pol)
// because we actually have fewer than tools::digits<T>()
// significant bits in the representation:
//
- frexp(((boost::math::fpclassify)(a) == FP_SUBNORMAL) ? tools::min_value<T>() : a, &expon);
+ frexp(((boost::math::fpclassify)(a) == (int)FP_SUBNORMAL) ? tools::min_value<T>() : a, &expon);
T upper = ldexp(T(1), expon);
T result = 0;
expon = tools::digits<T>() - expon;
@@ -227,13 +341,33 @@ T float_distance(const T& a, const T& b, const Policy& pol)
result = float_distance(upper, b);
}
//
- // Use compensated double-double addition to avoid rounding
+ // Use compensated double-double addition to avoid rounding
// errors in the subtraction:
//
- T mb = -(std::min)(upper, b);
- T x = a + mb;
- T z = x - a;
- T y = (a - (x - z)) + (mb - z);
+ T mb, x, y, z;
+ if(((boost::math::fpclassify)(a) == (int)FP_SUBNORMAL) || (b - a < tools::min_value<T>()))
+ {
+ //
+ // Special case - either one end of the range is a denormal, or else the difference is.
+ // The regular code will fail if we're using the SSE2 registers on Intel and either
+ // the FTZ or DAZ flags are set.
+ //
+ T a2 = ldexp(a, tools::digits<T>());
+ T b2 = ldexp(b, tools::digits<T>());
+ mb = -(std::min)(T(ldexp(upper, tools::digits<T>())), b2);
+ x = a2 + mb;
+ z = x - a2;
+ y = (a2 - (x - z)) + (mb - z);
+
+ expon -= tools::digits<T>();
+ }
+ else
+ {
+ mb = -(std::min)(upper, b);
+ x = a + mb;
+ z = x - a;
+ y = (a - (x - z)) + (mb - z);
+ }
if(x < 0)
{
x = -x;
@@ -247,20 +381,35 @@ T float_distance(const T& a, const T& b, const Policy& pol)
return result;
}
-template <class T>
-T float_distance(const T& a, const T& b)
+}
+
+template <class T, class U, class Policy>
+inline typename tools::promote_args<T, U>::type float_distance(const T& a, const U& b, const Policy& pol)
+{
+ typedef typename tools::promote_args<T, U>::type result_type;
+ return detail::float_distance_imp(static_cast<result_type>(a), static_cast<result_type>(b), pol);
+}
+
+template <class T, class U>
+typename tools::promote_args<T, U>::type float_distance(const T& a, const U& b)
{
return boost::math::float_distance(a, b, policies::policy<>());
}
+namespace detail{
+
template <class T, class Policy>
-T float_advance(T val, int distance, const Policy& pol)
+T float_advance_imp(T val, int distance, const Policy& pol)
{
+ BOOST_MATH_STD_USING
//
// Error handling:
//
static const char* function = "float_advance<%1%>(%1%, int)";
- if(!(boost::math::isfinite)(val))
+
+ int fpclass = (boost::math::fpclassify)(val);
+
+ if((fpclass == (int)FP_NAN) || (fpclass == (int)FP_INFINITE))
return policies::raise_domain_error<T>(
function,
"Argument val must be finite, but got %1%", val, pol);
@@ -273,7 +422,25 @@ T float_advance(T val, int distance, const Policy& pol)
return float_next(val, pol);
if(distance == -1)
return float_prior(val, pol);
- BOOST_MATH_STD_USING
+
+ if(fabs(val) < detail::get_min_shift_value<T>())
+ {
+ //
+ // Special case: if the value of the least significant bit is a denorm,
+ // implement in terms of float_next/float_prior.
+ // This avoids issues with the Intel SSE2 registers when the FTZ or DAZ flags are set.
+ //
+ if(distance > 0)
+ {
+ do{ val = float_next(val, pol); } while(--distance);
+ }
+ else
+ {
+ do{ val = float_prior(val, pol); } while(++distance);
+ }
+ return val;
+ }
+
int expon;
frexp(val, &expon);
T limit = ldexp((distance < 0 ? T(0.5f) : T(1)), expon);
@@ -286,7 +453,7 @@ T float_advance(T val, int distance, const Policy& pol)
{
distance -= itrunc(limit_distance);
val = limit;
- if(distance < 0)
+ if(distance < 0)
{
limit /= 2;
expon--;
@@ -297,6 +464,10 @@ T float_advance(T val, int distance, const Policy& pol)
expon++;
}
limit_distance = float_distance(val, limit);
+ if(distance && (limit_distance == 0))
+ {
+ return policies::raise_evaluation_error<T>(function, "Internal logic failed while trying to increment floating point value %1%: most likely your FPU is in non-IEEE conforming mode.", val, pol);
+ }
}
if((0.5f == frexp(val, &expon)) && (distance < 0))
--expon;
@@ -308,8 +479,17 @@ T float_advance(T val, int distance, const Policy& pol)
return val += diff;
}
+}
+
+template <class T, class Policy>
+inline typename tools::promote_args<T>::type float_advance(T val, int distance, const Policy& pol)
+{
+ typedef typename tools::promote_args<T>::type result_type;
+ return detail::float_advance_imp(static_cast<result_type>(val), distance, pol);
+}
+
template <class T>
-inline T float_advance(const T& val, int distance)
+inline typename tools::promote_args<T>::type float_advance(const T& val, int distance)
{
return boost::math::float_advance(val, distance, policies::policy<>());
}
diff --git a/boost/math/special_functions/owens_t.hpp b/boost/math/special_functions/owens_t.hpp
index 98d6380c39..6de93a4887 100644
--- a/boost/math/special_functions/owens_t.hpp
+++ b/boost/math/special_functions/owens_t.hpp
@@ -1,4 +1,4 @@
-// (C) Benjamin Sobotta 2012
+// Copyright Benjamin Sobotta 2012
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
@@ -16,6 +16,7 @@
# pragma once
#endif
+#include <boost/math/special_functions/math_fwd.hpp>
#include <boost/config/no_tr1/cmath.hpp>
#include <boost/math/special_functions/erf.hpp>
#include <boost/math/special_functions/expm1.hpp>
@@ -26,6 +27,11 @@
#include <stdexcept>
+#ifdef BOOST_MSVC
+#pragma warning(push)
+#pragma warning(disable:4127)
+#endif
+
namespace boost
{
namespace math
@@ -144,8 +150,8 @@ namespace boost
}
// compute the value of Owen's T function with method T1 from the reference paper
- template<typename RealType>
- inline RealType owens_t_T1(const RealType h, const RealType a, const unsigned short m)
+ template<typename RealType, typename Policy>
+ inline RealType owens_t_T1(const RealType h, const RealType a, const unsigned short m, const Policy& pol)
{
BOOST_MATH_STD_USING
using namespace boost::math::constants;
@@ -157,7 +163,7 @@ namespace boost
unsigned short j=1;
RealType jj = 1;
RealType aj = a * one_div_two_pi<RealType>();
- RealType dj = expm1( hs );
+ RealType dj = boost::math::expm1( hs, pol);
RealType gj = hs*dhs;
RealType val = atan( a ) * one_div_two_pi<RealType>();
@@ -219,7 +225,7 @@ namespace boost
BOOST_MATH_STD_USING
using namespace boost::math::constants;
- const unsigned short m = 20;
+ const unsigned short m = 20;
static const RealType c2[] =
{
@@ -275,37 +281,37 @@ namespace boost
static const RealType c2[] =
{
- BOOST_MATH_BIG_CONSTANT(RealType, 260, 0.99999999999999999999999729978162447266851932041876728736094298092917625009873),
- BOOST_MATH_BIG_CONSTANT(RealType, 260, -0.99999999999999999999467056379678391810626533251885323416799874878563998732905968),
- BOOST_MATH_BIG_CONSTANT(RealType, 260, 0.99999999999999999824849349313270659391127814689133077036298754586814091034842536),
- BOOST_MATH_BIG_CONSTANT(RealType, 260, -0.9999999999999997703859616213643405880166422891953033591551179153879839440241685),
- BOOST_MATH_BIG_CONSTANT(RealType, 260, 0.99999999999998394883415238173334565554173013941245103172035286759201504179038147),
- BOOST_MATH_BIG_CONSTANT(RealType, 260, -0.9999999999993063616095509371081203145247992197457263066869044528823599399470977),
- BOOST_MATH_BIG_CONSTANT(RealType, 260, 0.9999999999797336340409464429599229870590160411238245275855903767652432017766116267),
- BOOST_MATH_BIG_CONSTANT(RealType, 260, -0.999999999574958412069046680119051639753412378037565521359444170241346845522403274),
- BOOST_MATH_BIG_CONSTANT(RealType, 260, 0.9999999933226234193375324943920160947158239076786103108097456617750134812033362048),
- BOOST_MATH_BIG_CONSTANT(RealType, 260, -0.9999999188923242461073033481053037468263536806742737922476636768006622772762168467),
- BOOST_MATH_BIG_CONSTANT(RealType, 260, 0.9999992195143483674402853783549420883055129680082932629160081128947764415749728967),
- BOOST_MATH_BIG_CONSTANT(RealType, 260, -0.999993935137206712830997921913316971472227199741857386575097250553105958772041501),
- BOOST_MATH_BIG_CONSTANT(RealType, 260, 0.99996135597690552745362392866517133091672395614263398912807169603795088421057688716),
- BOOST_MATH_BIG_CONSTANT(RealType, 260, -0.99979556366513946026406788969630293820987757758641211293079784585126692672425362469),
- BOOST_MATH_BIG_CONSTANT(RealType, 260, 0.999092789629617100153486251423850590051366661947344315423226082520411961968929483),
- BOOST_MATH_BIG_CONSTANT(RealType, 260, -0.996593837411918202119308620432614600338157335862888580671450938858935084316004769854),
- BOOST_MATH_BIG_CONSTANT(RealType, 260, 0.98910017138386127038463510314625339359073956513420458166238478926511821146316469589567),
- BOOST_MATH_BIG_CONSTANT(RealType, 260, -0.970078558040693314521331982203762771512160168582494513347846407314584943870399016019),
- BOOST_MATH_BIG_CONSTANT(RealType, 260, 0.92911438683263187495758525500033707204091967947532160289872782771388170647150321633673),
- BOOST_MATH_BIG_CONSTANT(RealType, 260, -0.8542058695956156057286980736842905011429254735181323743367879525470479126968822863),
- BOOST_MATH_BIG_CONSTANT(RealType, 260, 0.73796526033030091233118357742803709382964420335559408722681794195743240930748630755),
- BOOST_MATH_BIG_CONSTANT(RealType, 260, -0.58523469882837394570128599003785154144164680587615878645171632791404210655891158),
- BOOST_MATH_BIG_CONSTANT(RealType, 260, 0.415997776145676306165661663581868460503874205343014196580122174949645271353372263),
- BOOST_MATH_BIG_CONSTANT(RealType, 260, -0.2588210875241943574388730510317252236407805082485246378222935376279663808416534365),
- BOOST_MATH_BIG_CONSTANT(RealType, 260, 0.1375535825163892648504646951500265585055789019410617565727090346559210218472356689),
- BOOST_MATH_BIG_CONSTANT(RealType, 260, -0.0607952766325955730493900985022020434830339794955745989150270485056436844239206648),
- BOOST_MATH_BIG_CONSTANT(RealType, 260, 0.0216337683299871528059836483840390514275488679530797294557060229266785853764115),
- BOOST_MATH_BIG_CONSTANT(RealType, 260, -0.00593405693455186729876995814181203900550014220428843483927218267309209471516256),
- BOOST_MATH_BIG_CONSTANT(RealType, 260, 0.0011743414818332946510474576182739210553333860106811865963485870668929503649964142),
- BOOST_MATH_BIG_CONSTANT(RealType, 260, -1.489155613350368934073453260689881330166342484405529981510694514036264969925132e-4),
- BOOST_MATH_BIG_CONSTANT(RealType, 260, 9.072354320794357587710929507988814669454281514268844884841547607134260303118208e-6)
+ BOOST_MATH_BIG_CONSTANT(RealType, 260, 0.99999999999999999999999729978162447266851932041876728736094298092917625009873),
+ BOOST_MATH_BIG_CONSTANT(RealType, 260, -0.99999999999999999999467056379678391810626533251885323416799874878563998732905968),
+ BOOST_MATH_BIG_CONSTANT(RealType, 260, 0.99999999999999999824849349313270659391127814689133077036298754586814091034842536),
+ BOOST_MATH_BIG_CONSTANT(RealType, 260, -0.9999999999999997703859616213643405880166422891953033591551179153879839440241685),
+ BOOST_MATH_BIG_CONSTANT(RealType, 260, 0.99999999999998394883415238173334565554173013941245103172035286759201504179038147),
+ BOOST_MATH_BIG_CONSTANT(RealType, 260, -0.9999999999993063616095509371081203145247992197457263066869044528823599399470977),
+ BOOST_MATH_BIG_CONSTANT(RealType, 260, 0.9999999999797336340409464429599229870590160411238245275855903767652432017766116267),
+ BOOST_MATH_BIG_CONSTANT(RealType, 260, -0.999999999574958412069046680119051639753412378037565521359444170241346845522403274),
+ BOOST_MATH_BIG_CONSTANT(RealType, 260, 0.9999999933226234193375324943920160947158239076786103108097456617750134812033362048),
+ BOOST_MATH_BIG_CONSTANT(RealType, 260, -0.9999999188923242461073033481053037468263536806742737922476636768006622772762168467),
+ BOOST_MATH_BIG_CONSTANT(RealType, 260, 0.9999992195143483674402853783549420883055129680082932629160081128947764415749728967),
+ BOOST_MATH_BIG_CONSTANT(RealType, 260, -0.999993935137206712830997921913316971472227199741857386575097250553105958772041501),
+ BOOST_MATH_BIG_CONSTANT(RealType, 260, 0.99996135597690552745362392866517133091672395614263398912807169603795088421057688716),
+ BOOST_MATH_BIG_CONSTANT(RealType, 260, -0.99979556366513946026406788969630293820987757758641211293079784585126692672425362469),
+ BOOST_MATH_BIG_CONSTANT(RealType, 260, 0.999092789629617100153486251423850590051366661947344315423226082520411961968929483),
+ BOOST_MATH_BIG_CONSTANT(RealType, 260, -0.996593837411918202119308620432614600338157335862888580671450938858935084316004769854),
+ BOOST_MATH_BIG_CONSTANT(RealType, 260, 0.98910017138386127038463510314625339359073956513420458166238478926511821146316469589567),
+ BOOST_MATH_BIG_CONSTANT(RealType, 260, -0.970078558040693314521331982203762771512160168582494513347846407314584943870399016019),
+ BOOST_MATH_BIG_CONSTANT(RealType, 260, 0.92911438683263187495758525500033707204091967947532160289872782771388170647150321633673),
+ BOOST_MATH_BIG_CONSTANT(RealType, 260, -0.8542058695956156057286980736842905011429254735181323743367879525470479126968822863),
+ BOOST_MATH_BIG_CONSTANT(RealType, 260, 0.73796526033030091233118357742803709382964420335559408722681794195743240930748630755),
+ BOOST_MATH_BIG_CONSTANT(RealType, 260, -0.58523469882837394570128599003785154144164680587615878645171632791404210655891158),
+ BOOST_MATH_BIG_CONSTANT(RealType, 260, 0.415997776145676306165661663581868460503874205343014196580122174949645271353372263),
+ BOOST_MATH_BIG_CONSTANT(RealType, 260, -0.2588210875241943574388730510317252236407805082485246378222935376279663808416534365),
+ BOOST_MATH_BIG_CONSTANT(RealType, 260, 0.1375535825163892648504646951500265585055789019410617565727090346559210218472356689),
+ BOOST_MATH_BIG_CONSTANT(RealType, 260, -0.0607952766325955730493900985022020434830339794955745989150270485056436844239206648),
+ BOOST_MATH_BIG_CONSTANT(RealType, 260, 0.0216337683299871528059836483840390514275488679530797294557060229266785853764115),
+ BOOST_MATH_BIG_CONSTANT(RealType, 260, -0.00593405693455186729876995814181203900550014220428843483927218267309209471516256),
+ BOOST_MATH_BIG_CONSTANT(RealType, 260, 0.0011743414818332946510474576182739210553333860106811865963485870668929503649964142),
+ BOOST_MATH_BIG_CONSTANT(RealType, 260, -1.489155613350368934073453260689881330166342484405529981510694514036264969925132e-4),
+ BOOST_MATH_BIG_CONSTANT(RealType, 260, 9.072354320794357587710929507988814669454281514268844884841547607134260303118208e-6)
};
const RealType as = a*a;
@@ -595,7 +601,7 @@ namespace boost
term = one_minus_dj_sum * a_pow / (2 * j + 1);
c = b - c;
sum += c * term;
- abs_err += ldexp(std::max(T(fabs(sum)), T(fabs(c*term))), -tools::digits<T>());
+ abs_err += ldexp((std::max)(T(fabs(sum)), T(fabs(c*term))), -tools::digits<T>());
b = (j + n) * (j - n) * b / ((j + T(0.5)) * (j + 1));
++j;
//
@@ -795,7 +801,7 @@ namespace boost
switch( meth[icode] )
{
case 1: // T1
- val = owens_t_T1(h,a,m);
+ val = owens_t_T1(h,a,m,pol);
break;
case 2: // T2
typedef typename policies::precision<RealType, Policy>::type precision_type;
@@ -1057,5 +1063,9 @@ namespace boost
} // namespace math
} // namespace boost
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
#endif
// EOF
diff --git a/boost/math/special_functions/pow.hpp b/boost/math/special_functions/pow.hpp
index 5423e9c8e4..494f721d05 100644
--- a/boost/math/special_functions/pow.hpp
+++ b/boost/math/special_functions/pow.hpp
@@ -13,6 +13,7 @@
#define BOOST_MATH_POW_HPP
+#include <boost/math/special_functions/math_fwd.hpp>
#include <boost/math/policies/policy.hpp>
#include <boost/math/policies/error_handling.hpp>
#include <boost/math/tools/promotion.hpp>
@@ -22,6 +23,10 @@
namespace boost {
namespace math {
+#ifdef BOOST_MSVC
+#pragma warning(push)
+#pragma warning(disable:4702) // Unreachable code, only triggered in release mode and /W4
+#endif
namespace detail {
@@ -132,6 +137,9 @@ template <int N, typename T>
inline typename tools::promote_args<T>::type pow(T base)
{ return pow<N>(base, policies::policy<>()); }
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
} // namespace math
} // namespace boost
diff --git a/boost/math/special_functions/powm1.hpp b/boost/math/special_functions/powm1.hpp
index cb33ae03d0..f3af3d6e59 100644
--- a/boost/math/special_functions/powm1.hpp
+++ b/boost/math/special_functions/powm1.hpp
@@ -10,9 +10,9 @@
#pragma once
#endif
+#include <boost/math/special_functions/math_fwd.hpp>
#include <boost/math/special_functions/log1p.hpp>
#include <boost/math/special_functions/expm1.hpp>
-#include <boost/math/special_functions/math_fwd.hpp>
#include <boost/assert.hpp>
namespace boost{ namespace math{ namespace detail{
diff --git a/boost/math/special_functions/prime.hpp b/boost/math/special_functions/prime.hpp
index ee25f991a3..94c28f9842 100644
--- a/boost/math/special_functions/prime.hpp
+++ b/boost/math/special_functions/prime.hpp
@@ -11,6 +11,7 @@
#include <boost/array.hpp>
#include <boost/cstdint.hpp>
#include <boost/math/policies/error_handling.hpp>
+#include <boost/math/special_functions/math_fwd.hpp>
namespace boost{ namespace math{
diff --git a/boost/math/special_functions/round.hpp b/boost/math/special_functions/round.hpp
index 2b4497e198..e21f7185d1 100644
--- a/boost/math/special_functions/round.hpp
+++ b/boost/math/special_functions/round.hpp
@@ -12,20 +12,60 @@
#include <boost/math/tools/config.hpp>
#include <boost/math/policies/error_handling.hpp>
+#include <boost/math/special_functions/math_fwd.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
namespace boost{ namespace math{
+namespace detail{
+
template <class T, class Policy>
-inline T round(const T& v, const Policy& pol)
+inline typename tools::promote_args<T>::type round(const T& v, const Policy& pol, const mpl::false_)
{
BOOST_MATH_STD_USING
+ typedef typename tools::promote_args<T>::type result_type;
if(!(boost::math::isfinite)(v))
- return policies::raise_rounding_error("boost::math::round<%1%>(%1%)", 0, v, v, pol);
- return v < 0 ? static_cast<T>(ceil(v - 0.5f)) : static_cast<T>(floor(v + 0.5f));
+ return policies::raise_rounding_error("boost::math::round<%1%>(%1%)", 0, static_cast<result_type>(v), static_cast<result_type>(v), pol);
+ //
+ // The logic here is rather convoluted, but avoids a number of traps,
+ // see discussion here https://github.com/boostorg/math/pull/8
+ //
+ if (-0.5 < v && v < 0.5)
+ {
+ // special case to avoid rounding error on the direct
+ // predecessor of +0.5 resp. the direct successor of -0.5 in
+ // IEEE floating point types
+ return 0;
+ }
+ else if (v > 0)
+ {
+ // subtract v from ceil(v) first in order to avoid rounding
+ // errors on largest representable integer numbers
+ result_type c(ceil(v));
+ return 0.5 < c - v ? c - 1 : c;
+ }
+ else
+ {
+ // see former branch
+ result_type f(floor(v));
+ return 0.5 < v - f ? f + 1 : f;
+ }
+}
+template <class T, class Policy>
+inline typename tools::promote_args<T>::type round(const T& v, const Policy&, const mpl::true_)
+{
+ return v;
+}
+
+} // namespace detail
+
+template <class T, class Policy>
+inline typename tools::promote_args<T>::type round(const T& v, const Policy& pol)
+{
+ return detail::round(v, pol, mpl::bool_<detail::is_integer_for_rounding<T>::value>());
}
template <class T>
-inline T round(const T& v)
+inline typename tools::promote_args<T>::type round(const T& v)
{
return round(v, policies::policy<>());
}
diff --git a/boost/math/special_functions/sign.hpp b/boost/math/special_functions/sign.hpp
index 6de88b29a2..f5c562d44c 100644
--- a/boost/math/special_functions/sign.hpp
+++ b/boost/math/special_functions/sign.hpp
@@ -31,7 +31,10 @@ namespace detail {
}
#endif
- template<class T>
+ // Generic versions first, note that these do not handle
+ // signed zero or NaN.
+
+ template<class T>
inline int signbit_impl(T x, generic_tag<true> const&)
{
return x < 0;
@@ -43,7 +46,25 @@ namespace detail {
return x < 0;
}
- template<class T>
+#if defined(__GNUC__) && (LDBL_MANT_DIG == 106)
+ //
+ // Special handling for GCC's "double double" type,
+ // in this case the sign is the same as the sign we
+ // get by casting to double, no overflow/underflow
+ // can occur since the exponents are the same magnitude
+ // for the two types:
+ //
+ inline int signbit_impl(long double x, generic_tag<true> const&)
+ {
+ return boost::math::signbit(static_cast<double>(x));
+ }
+ inline int signbit_impl(long double x, generic_tag<false> const&)
+ {
+ return boost::math::signbit(static_cast<double>(x));
+ }
+#endif
+
+ template<class T>
inline int signbit_impl(T x, ieee_copy_all_bits_tag const&)
{
typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
@@ -65,6 +86,9 @@ namespace detail {
}
// Changesign
+
+ // Generic versions first, note that these do not handle
+ // signed zero or NaN.
template<class T>
inline T (changesign_impl)(T x, generic_tag<true> const&)
@@ -77,7 +101,27 @@ namespace detail {
{
return -x;
}
-
+#if defined(__GNUC__) && (LDBL_MANT_DIG == 106)
+ //
+ // Special handling for GCC's "double double" type,
+ // in this case we need to change the sign of both
+ // components of the "double double":
+ //
+ inline long double (changesign_impl)(long double x, generic_tag<true> const&)
+ {
+ double* pd = reinterpret_cast<double*>(&x);
+ pd[0] = boost::math::changesign(pd[0]);
+ pd[1] = boost::math::changesign(pd[1]);
+ return x;
+ }
+ inline long double (changesign_impl)(long double x, generic_tag<false> const&)
+ {
+ double* pd = reinterpret_cast<double*>(&x);
+ pd[0] = boost::math::changesign(pd[0]);
+ pd[1] = boost::math::changesign(pd[1]);
+ return x;
+ }
+#endif
template<class T>
inline T changesign_impl(T x, ieee_copy_all_bits_tag const&)
@@ -110,8 +154,9 @@ template<class T> int (signbit)(T x)
{
typedef typename detail::fp_traits<T>::type traits;
typedef typename traits::method method;
- typedef typename boost::is_floating_point<T>::type fp_tag;
- return detail::signbit_impl(x, method());
+ // typedef typename boost::is_floating_point<T>::type fp_tag;
+ typedef typename tools::promote_args_permissive<T>::type result_type;
+ return detail::signbit_impl(static_cast<result_type>(x), method());
}
template <class T>
@@ -120,20 +165,24 @@ inline int sign BOOST_NO_MACRO_EXPAND(const T& z)
return (z == 0) ? 0 : (boost::math::signbit)(z) ? -1 : 1;
}
-template<class T> T (changesign)(const T& x)
+template <class T> typename tools::promote_args_permissive<T>::type (changesign)(const T& x)
{ //!< \brief return unchanged binary pattern of x, except for change of sign bit.
typedef typename detail::fp_traits<T>::sign_change_type traits;
typedef typename traits::method method;
- typedef typename boost::is_floating_point<T>::type fp_tag;
+ // typedef typename boost::is_floating_point<T>::type fp_tag;
+ typedef typename tools::promote_args_permissive<T>::type result_type;
- return detail::changesign_impl(x, method());
+ return detail::changesign_impl(static_cast<result_type>(x), method());
}
-template <class T>
-inline T copysign BOOST_NO_MACRO_EXPAND(const T& x, const T& y)
+template <class T, class U>
+inline typename tools::promote_args_permissive<T, U>::type
+ copysign BOOST_NO_MACRO_EXPAND(const T& x, const U& y)
{
BOOST_MATH_STD_USING
- return (boost::math::signbit)(x) != (boost::math::signbit)(y) ? (boost::math::changesign)(x) : x;
+ typedef typename tools::promote_args_permissive<T, U>::type result_type;
+ return (boost::math::signbit)(static_cast<result_type>(x)) != (boost::math::signbit)(static_cast<result_type>(y))
+ ? (boost::math::changesign)(static_cast<result_type>(x)) : static_cast<result_type>(x);
}
} // namespace math
diff --git a/boost/math/special_functions/sin_pi.hpp b/boost/math/special_functions/sin_pi.hpp
index 38c02bc99e..16aed51d2b 100644
--- a/boost/math/special_functions/sin_pi.hpp
+++ b/boost/math/special_functions/sin_pi.hpp
@@ -12,6 +12,7 @@
#include <boost/config/no_tr1/cmath.hpp>
#include <boost/math/tools/config.hpp>
+#include <boost/math/special_functions/math_fwd.hpp>
#include <boost/math/special_functions/trunc.hpp>
#include <boost/math/tools/promotion.hpp>
#include <boost/math/constants/constants.hpp>
diff --git a/boost/math/special_functions/sinc.hpp b/boost/math/special_functions/sinc.hpp
index ffb19d8b99..84fbf0e324 100644
--- a/boost/math/special_functions/sinc.hpp
+++ b/boost/math/special_functions/sinc.hpp
@@ -36,36 +36,16 @@ namespace boost
{
namespace detail
{
-#if defined(__GNUC__) && (__GNUC__ < 3)
- // gcc 2.x ignores function scope using declarations,
- // put them in the scope of the enclosing namespace instead:
-
- using ::std::abs;
- using ::std::sqrt;
- using ::std::sin;
-
- using ::std::numeric_limits;
-#endif /* defined(__GNUC__) && (__GNUC__ < 3) */
-
// This is the "Sinus Cardinal" of index Pi.
template<typename T>
inline T sinc_pi_imp(const T x)
{
-#if defined(BOOST_NO_STDC_NAMESPACE) && !defined(__SUNPRO_CC)
- using ::abs;
- using ::sin;
- using ::sqrt;
-#else /* BOOST_NO_STDC_NAMESPACE */
- using ::std::abs;
- using ::std::sin;
- using ::std::sqrt;
-#endif /* BOOST_NO_STDC_NAMESPACE */
-
- // Note: this code is *not* thread safe!
- static T const taylor_0_bound = tools::epsilon<T>();
- static T const taylor_2_bound = sqrt(taylor_0_bound);
- static T const taylor_n_bound = sqrt(taylor_2_bound);
+ BOOST_MATH_STD_USING
+
+ T const taylor_0_bound = tools::epsilon<T>();
+ T const taylor_2_bound = tools::root_epsilon<T>();
+ T const taylor_n_bound = tools::forth_root_epsilon<T>();
if (abs(x) >= taylor_n_bound)
{
@@ -110,28 +90,16 @@ namespace boost
return detail::sinc_pi_imp(static_cast<result_type>(x));
}
-#ifdef BOOST_NO_TEMPLATE_TEMPLATES
-#else /* BOOST_NO_TEMPLATE_TEMPLATES */
+#ifndef BOOST_NO_TEMPLATE_TEMPLATES
template<typename T, template<typename> class U>
inline U<T> sinc_pi(const U<T> x)
{
-#if defined(BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL) || defined(__GNUC__)
- using namespace std;
-#elif defined(BOOST_NO_STDC_NAMESPACE) && !defined(__SUNPRO_CC)
- using ::abs;
- using ::sin;
- using ::sqrt;
-#else /* BOOST_NO_STDC_NAMESPACE */
- using ::std::abs;
- using ::std::sin;
- using ::std::sqrt;
-#endif /* BOOST_NO_STDC_NAMESPACE */
-
+ BOOST_MATH_STD_USING
using ::std::numeric_limits;
- static T const taylor_0_bound = tools::epsilon<T>();
- static T const taylor_2_bound = sqrt(taylor_0_bound);
- static T const taylor_n_bound = sqrt(taylor_2_bound);
+ T const taylor_0_bound = tools::epsilon<T>();
+ T const taylor_2_bound = tools::root_epsilon<T>();
+ T const taylor_n_bound = tools::forth_root_epsilon<T>();
if (abs(x) >= taylor_n_bound)
{
diff --git a/boost/math/special_functions/sinhc.hpp b/boost/math/special_functions/sinhc.hpp
index d19a4b71c6..1216b7bfb7 100644
--- a/boost/math/special_functions/sinhc.hpp
+++ b/boost/math/special_functions/sinhc.hpp
@@ -34,17 +34,6 @@ namespace boost
{
namespace detail
{
-#if defined(__GNUC__) && (__GNUC__ < 3)
- // gcc 2.x ignores function scope using declarations,
- // put them in the scope of the enclosing namespace instead:
-
- using ::std::abs;
- using ::std::sqrt;
- using ::std::sinh;
-
- using ::std::numeric_limits;
-#endif /* defined(__GNUC__) && (__GNUC__ < 3) */
-
// This is the "Hyperbolic Sinus Cardinal" of index Pi.
template<typename T>
diff --git a/boost/math/special_functions/spherical_harmonic.hpp b/boost/math/special_functions/spherical_harmonic.hpp
index 33b2574480..00a6ade0d2 100644
--- a/boost/math/special_functions/spherical_harmonic.hpp
+++ b/boost/math/special_functions/spherical_harmonic.hpp
@@ -11,6 +11,7 @@
#pragma once
#endif
+#include <boost/math/special_functions/math_fwd.hpp>
#include <boost/math/special_functions/legendre.hpp>
#include <boost/math/tools/workaround.hpp>
#include <complex>
@@ -119,7 +120,7 @@ std::complex<T> spherical_harmonic(unsigned n, int m, U theta, U phi, const Poli
if(m&1)
{
// Check phase if theta is outside [0, PI]:
- U mod = boost::math::tools::fmod_workaround(theta, 2 * constants::pi<U>());
+ U mod = boost::math::tools::fmod_workaround(theta, U(2 * constants::pi<U>()));
if(mod < 0)
mod += 2 * constants::pi<U>();
if(mod > constants::pi<U>())
diff --git a/boost/math/special_functions/sqrt1pm1.hpp b/boost/math/special_functions/sqrt1pm1.hpp
index ad0203e722..293a9d97b3 100644
--- a/boost/math/special_functions/sqrt1pm1.hpp
+++ b/boost/math/special_functions/sqrt1pm1.hpp
@@ -10,9 +10,9 @@
#pragma once
#endif
+#include <boost/math/special_functions/math_fwd.hpp>
#include <boost/math/special_functions/log1p.hpp>
#include <boost/math/special_functions/expm1.hpp>
-#include <boost/math/special_functions/math_fwd.hpp>
//
// This algorithm computes sqrt(1+x)-1 for small x:
diff --git a/boost/math/special_functions/trunc.hpp b/boost/math/special_functions/trunc.hpp
index 7346afe6d1..3f80c96fee 100644
--- a/boost/math/special_functions/trunc.hpp
+++ b/boost/math/special_functions/trunc.hpp
@@ -10,22 +10,38 @@
#pragma once
#endif
+#include <boost/math/special_functions/math_fwd.hpp>
#include <boost/math/tools/config.hpp>
#include <boost/math/policies/error_handling.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
-namespace boost{ namespace math{
+namespace boost{ namespace math{ namespace detail{
template <class T, class Policy>
-inline T trunc(const T& v, const Policy& pol)
+inline typename tools::promote_args<T>::type trunc(const T& v, const Policy& pol, const mpl::false_&)
{
BOOST_MATH_STD_USING
+ typedef typename tools::promote_args<T>::type result_type;
if(!(boost::math::isfinite)(v))
- return policies::raise_rounding_error("boost::math::trunc<%1%>(%1%)", 0, v, v, pol);
- return (v >= 0) ? static_cast<T>(floor(v)) : static_cast<T>(ceil(v));
+ return policies::raise_rounding_error("boost::math::trunc<%1%>(%1%)", 0, static_cast<result_type>(v), static_cast<result_type>(v), pol);
+ return (v >= 0) ? static_cast<result_type>(floor(v)) : static_cast<result_type>(ceil(v));
+}
+
+template <class T, class Policy>
+inline typename tools::promote_args<T>::type trunc(const T& v, const Policy&, const mpl::true_&)
+{
+ return v;
+}
+
+}
+
+template <class T, class Policy>
+inline typename tools::promote_args<T>::type trunc(const T& v, const Policy& pol)
+{
+ return detail::trunc(v, pol, mpl::bool_<detail::is_integer_for_rounding<T>::value>());
}
template <class T>
-inline T trunc(const T& v)
+inline typename tools::promote_args<T>::type trunc(const T& v)
{
return trunc(v, policies::policy<>());
}
@@ -42,9 +58,10 @@ template <class T, class Policy>
inline int itrunc(const T& v, const Policy& pol)
{
BOOST_MATH_STD_USING
- T r = boost::math::trunc(v, pol);
+ typedef typename tools::promote_args<T>::type result_type;
+ result_type r = boost::math::trunc(v, pol);
if((r > (std::numeric_limits<int>::max)()) || (r < (std::numeric_limits<int>::min)()))
- return static_cast<int>(policies::raise_rounding_error("boost::math::itrunc<%1%>(%1%)", 0, v, 0, pol));
+ return static_cast<int>(policies::raise_rounding_error("boost::math::itrunc<%1%>(%1%)", 0, static_cast<result_type>(v), 0, pol));
return static_cast<int>(r);
}
template <class T>
@@ -57,9 +74,10 @@ template <class T, class Policy>
inline long ltrunc(const T& v, const Policy& pol)
{
BOOST_MATH_STD_USING
- T r = boost::math::trunc(v, pol);
+ typedef typename tools::promote_args<T>::type result_type;
+ result_type r = boost::math::trunc(v, pol);
if((r > (std::numeric_limits<long>::max)()) || (r < (std::numeric_limits<long>::min)()))
- return static_cast<long>(policies::raise_rounding_error("boost::math::ltrunc<%1%>(%1%)", 0, v, 0L, pol));
+ return static_cast<long>(policies::raise_rounding_error("boost::math::ltrunc<%1%>(%1%)", 0, static_cast<result_type>(v), 0L, pol));
return static_cast<long>(r);
}
template <class T>
@@ -74,7 +92,8 @@ template <class T, class Policy>
inline boost::long_long_type lltrunc(const T& v, const Policy& pol)
{
BOOST_MATH_STD_USING
- T r = boost::math::trunc(v, pol);
+ typedef typename tools::promote_args<T>::type result_type;
+ result_type r = boost::math::trunc(v, pol);
if((r > (std::numeric_limits<boost::long_long_type>::max)()) || (r < (std::numeric_limits<boost::long_long_type>::min)()))
return static_cast<boost::long_long_type>(policies::raise_rounding_error("boost::math::lltrunc<%1%>(%1%)", 0, v, static_cast<boost::long_long_type>(0), pol));
return static_cast<boost::long_long_type>(r);
diff --git a/boost/math/special_functions/zeta.hpp b/boost/math/special_functions/zeta.hpp
index 011182718e..b176f20176 100644
--- a/boost/math/special_functions/zeta.hpp
+++ b/boost/math/special_functions/zeta.hpp
@@ -10,6 +10,7 @@
#pragma once
#endif
+#include <boost/math/special_functions/math_fwd.hpp>
#include <boost/math/tools/precision.hpp>
#include <boost/math/tools/series.hpp>
#include <boost/math/tools/big_constant.hpp>
@@ -378,7 +379,7 @@ T zeta_imp_prec(T s, T sc, const Policy&, const mpl::int_<64>&)
BOOST_MATH_BIG_CONSTANT(T, 64, -0.279496685273033761927e-4),
};
static const T Q[7] = {
- BOOST_MATH_BIG_CONSTANT(T, 64, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 64, -0.30425480068225790522),
BOOST_MATH_BIG_CONSTANT(T, 64, 0.050052748580371598736),
BOOST_MATH_BIG_CONSTANT(T, 64, -0.00519355671064700627862),
@@ -406,7 +407,7 @@ T zeta_imp_prec(T s, T sc, const Policy&, const mpl::int_<64>&)
BOOST_MATH_BIG_CONSTANT(T, 64, 0.700867470265983665042e-5),
};
static const T Q[7] = {
- BOOST_MATH_BIG_CONSTANT(T, 64, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 64, 0.259385759149531030085),
BOOST_MATH_BIG_CONSTANT(T, 64, 0.0373974962106091316854),
BOOST_MATH_BIG_CONSTANT(T, 64, 0.00332735159183332820617),
@@ -432,7 +433,7 @@ T zeta_imp_prec(T s, T sc, const Policy&, const mpl::int_<64>&)
BOOST_MATH_BIG_CONSTANT(T, 64, 0.540319769113543934483e-7),
};
static const T Q[8] = {
- 1,
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 64, 0.286577739726542730421),
BOOST_MATH_BIG_CONSTANT(T, 64, 0.0447355811517733225843),
BOOST_MATH_BIG_CONSTANT(T, 64, 0.00430125107610252363302),
@@ -458,7 +459,7 @@ T zeta_imp_prec(T s, T sc, const Policy&, const mpl::int_<64>&)
BOOST_MATH_BIG_CONSTANT(T, 64, -0.252884970740994069582e-5),
};
static const T Q[9] = {
- 1,
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 64, 1.01300131390690459085),
BOOST_MATH_BIG_CONSTANT(T, 64, 0.387898115758643503827),
BOOST_MATH_BIG_CONSTANT(T, 64, 0.0695071490045701135188),
@@ -487,7 +488,7 @@ T zeta_imp_prec(T s, T sc, const Policy&, const mpl::int_<64>&)
BOOST_MATH_BIG_CONSTANT(T, 64, -0.815696314790853893484e-8),
};
static const T Q[9] = {
- 1,
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 64, 0.525765665400123515036),
BOOST_MATH_BIG_CONSTANT(T, 64, 0.10852641753657122787),
BOOST_MATH_BIG_CONSTANT(T, 64, 0.0115669945375362045249),
@@ -516,7 +517,7 @@ T zeta_imp_prec(T s, T sc, const Policy&, const mpl::int_<64>&)
BOOST_MATH_BIG_CONSTANT(T, 64, -0.145392555873022044329e-9),
};
static const T Q[10] = {
- 1,
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 64, 0.205135978585281988052),
BOOST_MATH_BIG_CONSTANT(T, 64, 0.0192359357875879453602),
BOOST_MATH_BIG_CONSTANT(T, 64, 0.00111496452029715514119),
@@ -554,7 +555,7 @@ T zeta_imp_prec(T s, T sc, const Policy&, const mpl::int_<113>&)
// Max error found at long double precision: 7.281332e-31
static const T P[10] = {
- BOOST_MATH_BIG_CONSTANT(T, 113, -1),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -1.0),
BOOST_MATH_BIG_CONSTANT(T, 113, -0.0353008629988648122808504280990313668),
BOOST_MATH_BIG_CONSTANT(T, 113, 0.0107795651204927743049369868548706909),
BOOST_MATH_BIG_CONSTANT(T, 113, 0.000523961870530500751114866884685172975),
@@ -566,7 +567,7 @@ T zeta_imp_prec(T s, T sc, const Policy&, const mpl::int_<113>&)
BOOST_MATH_BIG_CONSTANT(T, 113, 0.113103113698388531428914333768142527e-10),
};
static const T Q[11] = {
- BOOST_MATH_BIG_CONSTANT(T, 113, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 113, -0.387483472099602327112637481818565459),
BOOST_MATH_BIG_CONSTANT(T, 113, 0.0802265315091063135271497708694776875),
BOOST_MATH_BIG_CONSTANT(T, 113, -0.0110727276164171919280036408995078164),
@@ -600,7 +601,7 @@ T zeta_imp_prec(T s, T sc, const Policy&, const mpl::int_<113>&)
BOOST_MATH_BIG_CONSTANT(T, 113, -0.835774625259919268768735944711219256e-11),
};
static const T Q[11] = {
- BOOST_MATH_BIG_CONSTANT(T, 113, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 113, 0.316661751179735502065583176348292881),
BOOST_MATH_BIG_CONSTANT(T, 113, 0.0540401806533507064453851182728635272),
BOOST_MATH_BIG_CONSTANT(T, 113, 0.00598621274107420237785899476374043797),
@@ -636,7 +637,7 @@ T zeta_imp_prec(T s, T sc, const Policy&, const mpl::int_<113>&)
BOOST_MATH_BIG_CONSTANT(T, 113, 0.340169592866058506675897646629036044e-12),
};
static const T Q[12] = {
- BOOST_MATH_BIG_CONSTANT(T, 113, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 113, 0.363755247765087100018556983050520554),
BOOST_MATH_BIG_CONSTANT(T, 113, 0.0696581979014242539385695131258321598),
BOOST_MATH_BIG_CONSTANT(T, 113, 0.00882208914484611029571547753782014817),
@@ -675,7 +676,7 @@ T zeta_imp_prec(T s, T sc, const Policy&, const mpl::int_<113>&)
BOOST_MATH_BIG_CONSTANT(T, 113, -0.15090220092460596872172844424267351e-10),
};
static const T Q[14] = {
- BOOST_MATH_BIG_CONSTANT(T, 113, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.69490865837142338462982225731926485),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.22697696630994080733321401255942464),
BOOST_MATH_BIG_CONSTANT(T, 113, 0.495409420862526540074366618006341533),
@@ -715,7 +716,7 @@ T zeta_imp_prec(T s, T sc, const Policy&, const mpl::int_<113>&)
BOOST_MATH_BIG_CONSTANT(T, 113, -0.420204769185233365849253969097184005e-12),
};
static const T Q[14] = {
- BOOST_MATH_BIG_CONSTANT(T, 113, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 113, 0.97663511666410096104783358493318814),
BOOST_MATH_BIG_CONSTANT(T, 113, 0.40878780231201806504987368939673249),
BOOST_MATH_BIG_CONSTANT(T, 113, 0.0963890666609396058945084107597727252),
@@ -753,7 +754,7 @@ T zeta_imp_prec(T s, T sc, const Policy&, const mpl::int_<113>&)
BOOST_MATH_BIG_CONSTANT(T, 113, -0.289187187441625868404494665572279364e-15),
};
static const T Q[14] = {
- BOOST_MATH_BIG_CONSTANT(T, 113, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 113, 0.427310044448071818775721584949868806),
BOOST_MATH_BIG_CONSTANT(T, 113, 0.074602514873055756201435421385243062),
BOOST_MATH_BIG_CONSTANT(T, 113, 0.00688651562174480772901425121653945942),
@@ -792,7 +793,7 @@ T zeta_imp_prec(T s, T sc, const Policy&, const mpl::int_<113>&)
BOOST_MATH_BIG_CONSTANT(T, 113, -0.402663128248642002351627980255756363e-16),
};
static const T Q[14] = {
- BOOST_MATH_BIG_CONSTANT(T, 113, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 113, 0.311288325355705609096155335186466508),
BOOST_MATH_BIG_CONSTANT(T, 113, 0.0438318468940415543546769437752132748),
BOOST_MATH_BIG_CONSTANT(T, 113, 0.00374396349183199548610264222242269536),
@@ -831,7 +832,7 @@ T zeta_imp_prec(T s, T sc, const Policy&, const mpl::int_<113>&)
BOOST_MATH_BIG_CONSTANT(T, 113, -0.376708747782400769427057630528578187e-19),
};
static const T Q[16] = {
- BOOST_MATH_BIG_CONSTANT(T, 113, 1),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
BOOST_MATH_BIG_CONSTANT(T, 113, 0.205076752981410805177554569784219717),
BOOST_MATH_BIG_CONSTANT(T, 113, 0.0202526722696670378999575738524540269),
BOOST_MATH_BIG_CONSTANT(T, 113, 0.001278305290005994980069466658219057),
@@ -866,15 +867,16 @@ template <class T, class Policy, class Tag>
T zeta_imp(T s, T sc, const Policy& pol, const Tag& tag)
{
BOOST_MATH_STD_USING
- if(s == 1)
+ static const char* function = "boost::math::zeta<%1%>";
+ if(sc == 0)
return policies::raise_pole_error<T>(
- "boost::math::zeta<%1%>",
+ function,
"Evaluation of zeta function at pole %1%",
s, pol);
T result;
- if(s == 0)
+ if(fabs(s) < tools::root_epsilon<T>())
{
- result = -0.5;
+ result = -0.5f - constants::log_root_two_pi<T, Policy>() * s;
}
else if(s < 0)
{
@@ -883,10 +885,25 @@ T zeta_imp(T s, T sc, const Policy& pol, const Tag& tag)
result = 0;
else
{
- result = boost::math::sin_pi(0.5f * sc, pol)
- * 2 * pow(2 * constants::pi<T>(), -s)
- * boost::math::tgamma(s, pol)
- * zeta_imp(s, sc, pol, tag);
+ if(s > max_factorial<T>::value)
+ {
+ T mult = boost::math::sin_pi(0.5f * sc, pol) * 2 * zeta_imp(s, sc, pol, tag);
+ result = boost::math::lgamma(s, pol);
+ result -= s * log(2 * constants::pi<T>());
+ if(result > tools::log_max_value<T>())
+ return sign(mult) * policies::raise_overflow_error<T>(function, 0, pol);
+ result = exp(result);
+ if(tools::max_value<T>() / fabs(mult) < result)
+ return boost::math::sign(mult) * policies::raise_overflow_error<T>(function, 0, pol);
+ result *= mult;
+ }
+ else
+ {
+ result = boost::math::sin_pi(0.5f * sc, pol)
+ * 2 * pow(2 * constants::pi<T>(), -s)
+ * boost::math::tgamma(s, pol)
+ * zeta_imp(s, sc, pol, tag);
+ }
}
}
else
diff --git a/boost/math/tools/big_constant.hpp b/boost/math/tools/big_constant.hpp
index 119063164a..423cc1b631 100644
--- a/boost/math/tools/big_constant.hpp
+++ b/boost/math/tools/big_constant.hpp
@@ -8,30 +8,35 @@
#define BOOST_MATH_TOOLS_BIG_CONSTANT_HPP
#include <boost/math/tools/config.hpp>
+#ifndef BOOST_MATH_NO_LEXICAL_CAST
#include <boost/lexical_cast.hpp>
+#endif
#include <boost/type_traits/is_convertible.hpp>
+#include <boost/math/cstdfloat/cstdfloat_types.hpp>
namespace boost{ namespace math{
namespace tools{
template <class T>
-inline BOOST_CONSTEXPR_OR_CONST T make_big_value(long double v, const char*, mpl::true_ const&, mpl::false_ const&)
+inline BOOST_CONSTEXPR_OR_CONST T make_big_value(boost::floatmax_t v, const char*, mpl::true_ const&, mpl::false_ const&)
{
return static_cast<T>(v);
}
template <class T>
-inline BOOST_CONSTEXPR_OR_CONST T make_big_value(long double v, const char*, mpl::true_ const&, mpl::true_ const&)
+inline BOOST_CONSTEXPR_OR_CONST T make_big_value(boost::floatmax_t v, const char*, mpl::true_ const&, mpl::true_ const&)
{
return static_cast<T>(v);
}
+#ifndef BOOST_MATH_NO_LEXICAL_CAST
template <class T>
-inline T make_big_value(long double, const char* s, mpl::false_ const&, mpl::false_ const&)
+inline T make_big_value(boost::floatmax_t, const char* s, mpl::false_ const&, mpl::false_ const&)
{
return boost::lexical_cast<T>(s);
}
+#endif
template <class T>
-inline BOOST_CONSTEXPR const char* make_big_value(long double, const char* s, mpl::false_ const&, mpl::true_ const&)
+inline BOOST_CONSTEXPR const char* make_big_value(boost::floatmax_t, const char* s, mpl::false_ const&, mpl::true_ const&)
{
return s;
}
@@ -41,19 +46,21 @@ inline BOOST_CONSTEXPR const char* make_big_value(long double, const char* s, mp
//
#define BOOST_MATH_BIG_CONSTANT(T, D, x)\
boost::math::tools::make_big_value<T>(\
- BOOST_JOIN(x, L), \
+ BOOST_FLOATMAX_C(x), \
BOOST_STRINGIZE(x), \
- mpl::bool_< (is_convertible<long double, T>::value) && \
- ((D <= std::numeric_limits<long double>::digits) \
+ mpl::bool_< (is_convertible<boost::floatmax_t, T>::value) && \
+ ((D <= std::numeric_limits<boost::floatmax_t>::digits) \
|| is_floating_point<T>::value \
|| (std::numeric_limits<T>::is_specialized && \
- (std::numeric_limits<T>::digits10 <= std::numeric_limits<long double>::digits10))) >(), \
+ (std::numeric_limits<T>::digits10 <= std::numeric_limits<boost::floatmax_t>::digits10))) >(), \
boost::is_convertible<const char*, T>())
//
// For constants too huge for any conceivable long double (and which generate compiler errors if we try and declare them as such):
//
#define BOOST_MATH_HUGE_CONSTANT(T, D, x)\
- boost::math::tools::make_big_value<T>(0.0L, BOOST_STRINGIZE(x), mpl::bool_<false>(), boost::is_convertible<const char*, T>())
+ boost::math::tools::make_big_value<T>(0.0L, BOOST_STRINGIZE(x), \
+ mpl::bool_<is_floating_point<T>::value || (std::numeric_limits<T>::is_specialized && std::numeric_limits<T>::max_exponent <= std::numeric_limits<long double>::max_exponent && std::numeric_limits<T>::digits <= std::numeric_limits<long double>::digits)>(), \
+ boost::is_convertible<const char*, T>())
}}} // namespaces
diff --git a/boost/math/tools/config.hpp b/boost/math/tools/config.hpp
index b1fcd13856..4ec5768aaf 100644
--- a/boost/math/tools/config.hpp
+++ b/boost/math/tools/config.hpp
@@ -13,6 +13,7 @@
#include <boost/config.hpp>
#include <boost/cstdint.hpp> // for boost::uintmax_t
#include <boost/detail/workaround.hpp>
+#include <boost/type_traits/is_integral.hpp>
#include <algorithm> // for min and max
#include <boost/config/no_tr1/cmath.hpp>
#include <climits>
@@ -20,9 +21,11 @@
#if (defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__))
# include <math.h>
#endif
+#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
+# include <limits>
+#endif
#include <boost/math/tools/user.hpp>
-#include <boost/math/special_functions/detail/round_fwd.hpp>
#if (defined(__CYGWIN__) || defined(__FreeBSD__) || defined(__NetBSD__) \
|| (defined(__hppa) && !defined(__OpenBSD__)) || (defined(__NO_LONG_DOUBLE_MATH) && (DBL_MANT_DIG != LDBL_MANT_DIG))) \
@@ -99,13 +102,18 @@
# define BOOST_MATH_USE_C99
#endif
+#if defined(_LIBCPP_VERSION) && !defined(_MSC_VER)
+# define BOOST_MATH_USE_C99
+#endif
+
#if defined(__CYGWIN__) || defined(__HP_aCC) || defined(BOOST_INTEL) \
|| defined(BOOST_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY) \
- || (defined(__GNUC__) && !defined(BOOST_MATH_USE_C99))
+ || (defined(__GNUC__) && !defined(BOOST_MATH_USE_C99))\
+ || defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS)
# define BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY
#endif
-#if defined(BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS) || BOOST_WORKAROUND(__SUNPRO_CC, <= 0x590)
+#if BOOST_WORKAROUND(__SUNPRO_CC, <= 0x590)
# include "boost/type.hpp"
# include "boost/non_type.hpp"
@@ -139,12 +147,12 @@
# define BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_NON_TYPE_SPEC(t, v)
-#endif // defined BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS
+#endif // __SUNPRO_CC
#if (defined(__SUNPRO_CC) || defined(__hppa) || defined(__GNUC__)) && !defined(BOOST_MATH_SMALL_CONSTANT)
// Sun's compiler emits a hard error if a constant underflows,
// as does aCC on PA-RISC, while gcc issues a large number of warnings:
-# define BOOST_MATH_SMALL_CONSTANT(x) 0
+# define BOOST_MATH_SMALL_CONSTANT(x) 0.0
#else
# define BOOST_MATH_SMALL_CONSTANT(x) x
#endif
@@ -203,6 +211,37 @@
#ifndef BOOST_MATH_INT_VALUE_SUFFIX
# define BOOST_MATH_INT_VALUE_SUFFIX(RV, SUF) RV##SUF
#endif
+//
+// Test whether to support __float128:
+//
+#if defined(_GLIBCXX_USE_FLOAT128) && defined(BOOST_GCC) && !defined(__STRICT_ANSI__) \
+ && !defined(BOOST_MATH_DISABLE_FLOAT128) || defined(BOOST_MATH_USE_FLOAT128)
+//
+// Only enable this when the compiler really is GCC as clang and probably
+// intel too don't support __float128 yet :-(
+//
+#ifndef BOOST_MATH_USE_FLOAT128
+# define BOOST_MATH_USE_FLOAT128
+#endif
+
+# if defined(BOOST_INTEL) && defined(BOOST_INTEL_CXX_VERSION) && (BOOST_INTEL_CXX_VERSION >= 1310) && defined(__GNUC__)
+# if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6))
+# define BOOST_MATH_FLOAT128_TYPE __float128
+# endif
+# elif defined(__GNUC__)
+# define BOOST_MATH_FLOAT128_TYPE __float128
+# endif
+
+# ifndef BOOST_MATH_FLOAT128_TYPE
+# define BOOST_MATH_FLOAT128_TYPE _Quad
+# endif
+#endif
+//
+// Check for WinCE with no iostream support:
+//
+#if defined(_WIN32_WCE) && !defined(__SGI_STL_PORT)
+# define BOOST_MATH_NO_LEXICAL_CAST
+#endif
//
// Helper macro for controlling the FP behaviour:
@@ -213,7 +252,7 @@
//
// Helper macro for using statements:
//
-#define BOOST_MATH_STD_USING \
+#define BOOST_MATH_STD_USING_CORE \
using std::abs;\
using std::acos;\
using std::cos;\
@@ -236,15 +275,9 @@
using std::ceil;\
using std::floor;\
using std::log10;\
- using std::sqrt;\
- using boost::math::round;\
- using boost::math::iround;\
- using boost::math::lround;\
- using boost::math::trunc;\
- using boost::math::itrunc;\
- using boost::math::ltrunc;\
- using boost::math::modf;
+ using std::sqrt;
+#define BOOST_MATH_STD_USING BOOST_MATH_STD_USING_CORE
namespace boost{ namespace math{
namespace tools
@@ -269,9 +302,35 @@ void suppress_unused_variable_warning(const T&)
{
}
+namespace detail{
+
+template <class T>
+struct is_integer_for_rounding
+{
+ static const bool value = boost::is_integral<T>::value
+#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
+ || (std::numeric_limits<T>::is_specialized && std::numeric_limits<T>::is_integer)
+#endif
+ ;
+};
+
+}
+
}} // namespace boost namespace math
-#if ((defined(__linux__) && !defined(__UCLIBC__)) || defined(__QNX__) || defined(__IBMCPP__)) && !defined(BOOST_NO_FENV_H)
+#ifdef __GLIBC_PREREQ
+# if __GLIBC_PREREQ(2,14)
+# define BOOST_MATH_HAVE_FIXED_GLIBC
+# endif
+#endif
+
+#if ((defined(__linux__) && !defined(__UCLIBC__) && !defined(BOOST_MATH_HAVE_FIXED_GLIBC)) || defined(__QNX__) || defined(__IBMCPP__)) && !defined(BOOST_NO_FENV_H)
+//
+// This code was introduced in response to this glibc bug: http://sourceware.org/bugzilla/show_bug.cgi?id=2445
+// Basically powl and expl can return garbage when the result is small and certain exception flags are set
+// on entrance to these functions. This appears to have been fixed in Glibc 2.14 (May 2011).
+// Much more information in this message thread: https://groups.google.com/forum/#!topic/boost-list/ZT99wtIFlb4
+//
#include <boost/detail/fenv.hpp>
@@ -314,12 +373,20 @@ namespace boost{ namespace math{
#endif
#ifdef BOOST_MATH_INSTRUMENT
-#define BOOST_MATH_INSTRUMENT_CODE(x) \
- std::cout << std::setprecision(35) << __FILE__ << ":" << __LINE__ << " " << x << std::endl;
-#define BOOST_MATH_INSTRUMENT_VARIABLE(name) BOOST_MATH_INSTRUMENT_CODE(BOOST_STRINGIZE(name) << " = " << name)
+
+# include <iostream>
+# include <iomanip>
+# include <typeinfo>
+
+# define BOOST_MATH_INSTRUMENT_CODE(x) \
+ std::cout << std::setprecision(35) << __FILE__ << ":" << __LINE__ << " " << x << std::endl;
+# define BOOST_MATH_INSTRUMENT_VARIABLE(name) BOOST_MATH_INSTRUMENT_CODE(BOOST_STRINGIZE(name) << " = " << name)
+
#else
-#define BOOST_MATH_INSTRUMENT_CODE(x)
-#define BOOST_MATH_INSTRUMENT_VARIABLE(name)
+
+# define BOOST_MATH_INSTRUMENT_CODE(x)
+# define BOOST_MATH_INSTRUMENT_VARIABLE(name)
+
#endif
#endif // BOOST_MATH_TOOLS_CONFIG_HPP
diff --git a/boost/math/tools/detail/polynomial_horner1_10.hpp b/boost/math/tools/detail/polynomial_horner1_10.hpp
index ffc3a68040..b13d6a3887 100644
--- a/boost/math/tools/detail/polynomial_horner1_10.hpp
+++ b/boost/math/tools/detail/polynomial_horner1_10.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner1_11.hpp b/boost/math/tools/detail/polynomial_horner1_11.hpp
index 8e2232c534..f0cf67e959 100644
--- a/boost/math/tools/detail/polynomial_horner1_11.hpp
+++ b/boost/math/tools/detail/polynomial_horner1_11.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner1_12.hpp b/boost/math/tools/detail/polynomial_horner1_12.hpp
index 07d2947c9f..03b974ceca 100644
--- a/boost/math/tools/detail/polynomial_horner1_12.hpp
+++ b/boost/math/tools/detail/polynomial_horner1_12.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner1_13.hpp b/boost/math/tools/detail/polynomial_horner1_13.hpp
index d826b5150b..b947f542c3 100644
--- a/boost/math/tools/detail/polynomial_horner1_13.hpp
+++ b/boost/math/tools/detail/polynomial_horner1_13.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner1_14.hpp b/boost/math/tools/detail/polynomial_horner1_14.hpp
index 02b23ada59..8374e38904 100644
--- a/boost/math/tools/detail/polynomial_horner1_14.hpp
+++ b/boost/math/tools/detail/polynomial_horner1_14.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner1_15.hpp b/boost/math/tools/detail/polynomial_horner1_15.hpp
index 72cbbd2986..ebfa463601 100644
--- a/boost/math/tools/detail/polynomial_horner1_15.hpp
+++ b/boost/math/tools/detail/polynomial_horner1_15.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner1_16.hpp b/boost/math/tools/detail/polynomial_horner1_16.hpp
index 39202e0019..60eb4dc675 100644
--- a/boost/math/tools/detail/polynomial_horner1_16.hpp
+++ b/boost/math/tools/detail/polynomial_horner1_16.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner1_17.hpp b/boost/math/tools/detail/polynomial_horner1_17.hpp
index a777ab76b3..6233f1b07b 100644
--- a/boost/math/tools/detail/polynomial_horner1_17.hpp
+++ b/boost/math/tools/detail/polynomial_horner1_17.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner1_18.hpp b/boost/math/tools/detail/polynomial_horner1_18.hpp
index 57e171c6bf..2a06def44b 100644
--- a/boost/math/tools/detail/polynomial_horner1_18.hpp
+++ b/boost/math/tools/detail/polynomial_horner1_18.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner1_19.hpp b/boost/math/tools/detail/polynomial_horner1_19.hpp
index f2e893d650..8f0da8b219 100644
--- a/boost/math/tools/detail/polynomial_horner1_19.hpp
+++ b/boost/math/tools/detail/polynomial_horner1_19.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner1_2.hpp b/boost/math/tools/detail/polynomial_horner1_2.hpp
index cf2af8ec26..a0b10d5ee5 100644
--- a/boost/math/tools/detail/polynomial_horner1_2.hpp
+++ b/boost/math/tools/detail/polynomial_horner1_2.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner1_20.hpp b/boost/math/tools/detail/polynomial_horner1_20.hpp
index 6cd2fa2ca8..d1a886dd76 100644
--- a/boost/math/tools/detail/polynomial_horner1_20.hpp
+++ b/boost/math/tools/detail/polynomial_horner1_20.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner1_3.hpp b/boost/math/tools/detail/polynomial_horner1_3.hpp
index 34283d1cf0..715a69aee0 100644
--- a/boost/math/tools/detail/polynomial_horner1_3.hpp
+++ b/boost/math/tools/detail/polynomial_horner1_3.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner1_4.hpp b/boost/math/tools/detail/polynomial_horner1_4.hpp
index 7a06708e06..d74b7a6386 100644
--- a/boost/math/tools/detail/polynomial_horner1_4.hpp
+++ b/boost/math/tools/detail/polynomial_horner1_4.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner1_5.hpp b/boost/math/tools/detail/polynomial_horner1_5.hpp
index 135e155ec7..bb66e6c41d 100644
--- a/boost/math/tools/detail/polynomial_horner1_5.hpp
+++ b/boost/math/tools/detail/polynomial_horner1_5.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner1_6.hpp b/boost/math/tools/detail/polynomial_horner1_6.hpp
index af993517cb..a29c2710e8 100644
--- a/boost/math/tools/detail/polynomial_horner1_6.hpp
+++ b/boost/math/tools/detail/polynomial_horner1_6.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner1_7.hpp b/boost/math/tools/detail/polynomial_horner1_7.hpp
index 9205f2efa0..093ab89b02 100644
--- a/boost/math/tools/detail/polynomial_horner1_7.hpp
+++ b/boost/math/tools/detail/polynomial_horner1_7.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner1_8.hpp b/boost/math/tools/detail/polynomial_horner1_8.hpp
index 70afa90088..a3d329a37b 100644
--- a/boost/math/tools/detail/polynomial_horner1_8.hpp
+++ b/boost/math/tools/detail/polynomial_horner1_8.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner1_9.hpp b/boost/math/tools/detail/polynomial_horner1_9.hpp
index b823f24b5f..e90f578d04 100644
--- a/boost/math/tools/detail/polynomial_horner1_9.hpp
+++ b/boost/math/tools/detail/polynomial_horner1_9.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner2_10.hpp b/boost/math/tools/detail/polynomial_horner2_10.hpp
index 0474d7e3e1..7c4101f465 100644
--- a/boost/math/tools/detail/polynomial_horner2_10.hpp
+++ b/boost/math/tools/detail/polynomial_horner2_10.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner2_11.hpp b/boost/math/tools/detail/polynomial_horner2_11.hpp
index 6fd1ea99e0..bebd1e6483 100644
--- a/boost/math/tools/detail/polynomial_horner2_11.hpp
+++ b/boost/math/tools/detail/polynomial_horner2_11.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner2_12.hpp b/boost/math/tools/detail/polynomial_horner2_12.hpp
index c6615c7ac0..c4da24ac88 100644
--- a/boost/math/tools/detail/polynomial_horner2_12.hpp
+++ b/boost/math/tools/detail/polynomial_horner2_12.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner2_13.hpp b/boost/math/tools/detail/polynomial_horner2_13.hpp
index 02f4136b72..5d7dddc5b5 100644
--- a/boost/math/tools/detail/polynomial_horner2_13.hpp
+++ b/boost/math/tools/detail/polynomial_horner2_13.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner2_14.hpp b/boost/math/tools/detail/polynomial_horner2_14.hpp
index 34d27cc9fa..21a5a37903 100644
--- a/boost/math/tools/detail/polynomial_horner2_14.hpp
+++ b/boost/math/tools/detail/polynomial_horner2_14.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner2_15.hpp b/boost/math/tools/detail/polynomial_horner2_15.hpp
index a1615243fd..7b41214466 100644
--- a/boost/math/tools/detail/polynomial_horner2_15.hpp
+++ b/boost/math/tools/detail/polynomial_horner2_15.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner2_16.hpp b/boost/math/tools/detail/polynomial_horner2_16.hpp
index 43a2679bf9..aa3763ad65 100644
--- a/boost/math/tools/detail/polynomial_horner2_16.hpp
+++ b/boost/math/tools/detail/polynomial_horner2_16.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner2_17.hpp b/boost/math/tools/detail/polynomial_horner2_17.hpp
index 83dd92129a..6ed5566d49 100644
--- a/boost/math/tools/detail/polynomial_horner2_17.hpp
+++ b/boost/math/tools/detail/polynomial_horner2_17.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner2_18.hpp b/boost/math/tools/detail/polynomial_horner2_18.hpp
index 8a13a049e4..02c72b8227 100644
--- a/boost/math/tools/detail/polynomial_horner2_18.hpp
+++ b/boost/math/tools/detail/polynomial_horner2_18.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner2_19.hpp b/boost/math/tools/detail/polynomial_horner2_19.hpp
index 38e5226343..6e36ace904 100644
--- a/boost/math/tools/detail/polynomial_horner2_19.hpp
+++ b/boost/math/tools/detail/polynomial_horner2_19.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner2_2.hpp b/boost/math/tools/detail/polynomial_horner2_2.hpp
index 5421d828c3..e2a4e7faef 100644
--- a/boost/math/tools/detail/polynomial_horner2_2.hpp
+++ b/boost/math/tools/detail/polynomial_horner2_2.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner2_20.hpp b/boost/math/tools/detail/polynomial_horner2_20.hpp
index dd422705c1..e394b6b325 100644
--- a/boost/math/tools/detail/polynomial_horner2_20.hpp
+++ b/boost/math/tools/detail/polynomial_horner2_20.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner2_3.hpp b/boost/math/tools/detail/polynomial_horner2_3.hpp
index cd568ab79d..187b86c1ce 100644
--- a/boost/math/tools/detail/polynomial_horner2_3.hpp
+++ b/boost/math/tools/detail/polynomial_horner2_3.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner2_4.hpp b/boost/math/tools/detail/polynomial_horner2_4.hpp
index a99a695c76..84badc365a 100644
--- a/boost/math/tools/detail/polynomial_horner2_4.hpp
+++ b/boost/math/tools/detail/polynomial_horner2_4.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner2_5.hpp b/boost/math/tools/detail/polynomial_horner2_5.hpp
index 950568f9d0..287b4be08e 100644
--- a/boost/math/tools/detail/polynomial_horner2_5.hpp
+++ b/boost/math/tools/detail/polynomial_horner2_5.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner2_6.hpp b/boost/math/tools/detail/polynomial_horner2_6.hpp
index b1035f5031..3662d44f93 100644
--- a/boost/math/tools/detail/polynomial_horner2_6.hpp
+++ b/boost/math/tools/detail/polynomial_horner2_6.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner2_7.hpp b/boost/math/tools/detail/polynomial_horner2_7.hpp
index 0b167564df..78ed0df54d 100644
--- a/boost/math/tools/detail/polynomial_horner2_7.hpp
+++ b/boost/math/tools/detail/polynomial_horner2_7.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner2_8.hpp b/boost/math/tools/detail/polynomial_horner2_8.hpp
index ba92c21e20..ac8e941180 100644
--- a/boost/math/tools/detail/polynomial_horner2_8.hpp
+++ b/boost/math/tools/detail/polynomial_horner2_8.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner2_9.hpp b/boost/math/tools/detail/polynomial_horner2_9.hpp
index cc4afb38d3..e1a3d17eca 100644
--- a/boost/math/tools/detail/polynomial_horner2_9.hpp
+++ b/boost/math/tools/detail/polynomial_horner2_9.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner3_10.hpp b/boost/math/tools/detail/polynomial_horner3_10.hpp
index 14b1b66f38..69736d7118 100644
--- a/boost/math/tools/detail/polynomial_horner3_10.hpp
+++ b/boost/math/tools/detail/polynomial_horner3_10.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner3_11.hpp b/boost/math/tools/detail/polynomial_horner3_11.hpp
index 690906938f..273ed535cc 100644
--- a/boost/math/tools/detail/polynomial_horner3_11.hpp
+++ b/boost/math/tools/detail/polynomial_horner3_11.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner3_12.hpp b/boost/math/tools/detail/polynomial_horner3_12.hpp
index d17d3c586d..340567400b 100644
--- a/boost/math/tools/detail/polynomial_horner3_12.hpp
+++ b/boost/math/tools/detail/polynomial_horner3_12.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner3_13.hpp b/boost/math/tools/detail/polynomial_horner3_13.hpp
index aff043bd17..849c93e54a 100644
--- a/boost/math/tools/detail/polynomial_horner3_13.hpp
+++ b/boost/math/tools/detail/polynomial_horner3_13.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner3_14.hpp b/boost/math/tools/detail/polynomial_horner3_14.hpp
index 5ff2a51de9..f5ac1df9d1 100644
--- a/boost/math/tools/detail/polynomial_horner3_14.hpp
+++ b/boost/math/tools/detail/polynomial_horner3_14.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner3_15.hpp b/boost/math/tools/detail/polynomial_horner3_15.hpp
index 896545617b..b57af7e3dc 100644
--- a/boost/math/tools/detail/polynomial_horner3_15.hpp
+++ b/boost/math/tools/detail/polynomial_horner3_15.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner3_16.hpp b/boost/math/tools/detail/polynomial_horner3_16.hpp
index 5bfddc59a6..1fc8560a21 100644
--- a/boost/math/tools/detail/polynomial_horner3_16.hpp
+++ b/boost/math/tools/detail/polynomial_horner3_16.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner3_17.hpp b/boost/math/tools/detail/polynomial_horner3_17.hpp
index d6679b392e..4a0d0aa472 100644
--- a/boost/math/tools/detail/polynomial_horner3_17.hpp
+++ b/boost/math/tools/detail/polynomial_horner3_17.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner3_18.hpp b/boost/math/tools/detail/polynomial_horner3_18.hpp
index df016a1739..899117d2f9 100644
--- a/boost/math/tools/detail/polynomial_horner3_18.hpp
+++ b/boost/math/tools/detail/polynomial_horner3_18.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner3_19.hpp b/boost/math/tools/detail/polynomial_horner3_19.hpp
index 10adbe556b..7c4f728419 100644
--- a/boost/math/tools/detail/polynomial_horner3_19.hpp
+++ b/boost/math/tools/detail/polynomial_horner3_19.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner3_2.hpp b/boost/math/tools/detail/polynomial_horner3_2.hpp
index b32501f0ad..372630cfd9 100644
--- a/boost/math/tools/detail/polynomial_horner3_2.hpp
+++ b/boost/math/tools/detail/polynomial_horner3_2.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner3_20.hpp b/boost/math/tools/detail/polynomial_horner3_20.hpp
index 68bd0beadf..b20e0d5fe1 100644
--- a/boost/math/tools/detail/polynomial_horner3_20.hpp
+++ b/boost/math/tools/detail/polynomial_horner3_20.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner3_3.hpp b/boost/math/tools/detail/polynomial_horner3_3.hpp
index 8296740a54..cc6b1a9351 100644
--- a/boost/math/tools/detail/polynomial_horner3_3.hpp
+++ b/boost/math/tools/detail/polynomial_horner3_3.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner3_4.hpp b/boost/math/tools/detail/polynomial_horner3_4.hpp
index e6ba3179b1..74192f0c90 100644
--- a/boost/math/tools/detail/polynomial_horner3_4.hpp
+++ b/boost/math/tools/detail/polynomial_horner3_4.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner3_5.hpp b/boost/math/tools/detail/polynomial_horner3_5.hpp
index d4e94b90d5..73d1900998 100644
--- a/boost/math/tools/detail/polynomial_horner3_5.hpp
+++ b/boost/math/tools/detail/polynomial_horner3_5.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner3_6.hpp b/boost/math/tools/detail/polynomial_horner3_6.hpp
index 143defc63d..da02574866 100644
--- a/boost/math/tools/detail/polynomial_horner3_6.hpp
+++ b/boost/math/tools/detail/polynomial_horner3_6.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner3_7.hpp b/boost/math/tools/detail/polynomial_horner3_7.hpp
index 016895076c..d45a622278 100644
--- a/boost/math/tools/detail/polynomial_horner3_7.hpp
+++ b/boost/math/tools/detail/polynomial_horner3_7.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner3_8.hpp b/boost/math/tools/detail/polynomial_horner3_8.hpp
index 9a373446e1..d0198bf345 100644
--- a/boost/math/tools/detail/polynomial_horner3_8.hpp
+++ b/boost/math/tools/detail/polynomial_horner3_8.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/polynomial_horner3_9.hpp b/boost/math/tools/detail/polynomial_horner3_9.hpp
index d0f9dd310c..b3e0b19970 100644
--- a/boost/math/tools/detail/polynomial_horner3_9.hpp
+++ b/boost/math/tools/detail/polynomial_horner3_9.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class V>
-inline V evaluate_polynomial_c_imp(const T* a, const V&, const mpl::int_<0>*)
+inline V evaluate_polynomial_c_imp(const T*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/rational_horner2_10.hpp b/boost/math/tools/detail/rational_horner2_10.hpp
index db752742dc..e26d2d934f 100644
--- a/boost/math/tools/detail/rational_horner2_10.hpp
+++ b/boost/math/tools/detail/rational_horner2_10.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class U, class V>
-inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const mpl::int_<0>*)
+inline V evaluate_rational_c_imp(const T*, const U*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/rational_horner2_11.hpp b/boost/math/tools/detail/rational_horner2_11.hpp
index 2b728e8b4f..c05e697197 100644
--- a/boost/math/tools/detail/rational_horner2_11.hpp
+++ b/boost/math/tools/detail/rational_horner2_11.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class U, class V>
-inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const mpl::int_<0>*)
+inline V evaluate_rational_c_imp(const T*, const U*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/rational_horner2_12.hpp b/boost/math/tools/detail/rational_horner2_12.hpp
index daa14e4d2b..4ee3734001 100644
--- a/boost/math/tools/detail/rational_horner2_12.hpp
+++ b/boost/math/tools/detail/rational_horner2_12.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class U, class V>
-inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const mpl::int_<0>*)
+inline V evaluate_rational_c_imp(const T*, const U*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/rational_horner2_13.hpp b/boost/math/tools/detail/rational_horner2_13.hpp
index e5dfc62288..37977a111d 100644
--- a/boost/math/tools/detail/rational_horner2_13.hpp
+++ b/boost/math/tools/detail/rational_horner2_13.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class U, class V>
-inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const mpl::int_<0>*)
+inline V evaluate_rational_c_imp(const T*, const U*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/rational_horner2_14.hpp b/boost/math/tools/detail/rational_horner2_14.hpp
index 37ddfa5e65..78edfbbe1b 100644
--- a/boost/math/tools/detail/rational_horner2_14.hpp
+++ b/boost/math/tools/detail/rational_horner2_14.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class U, class V>
-inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const mpl::int_<0>*)
+inline V evaluate_rational_c_imp(const T*, const U*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/rational_horner2_15.hpp b/boost/math/tools/detail/rational_horner2_15.hpp
index 9168b2efcd..3cf4ef56a0 100644
--- a/boost/math/tools/detail/rational_horner2_15.hpp
+++ b/boost/math/tools/detail/rational_horner2_15.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class U, class V>
-inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const mpl::int_<0>*)
+inline V evaluate_rational_c_imp(const T*, const U*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/rational_horner2_16.hpp b/boost/math/tools/detail/rational_horner2_16.hpp
index 7dafa460a5..3936a1ba4b 100644
--- a/boost/math/tools/detail/rational_horner2_16.hpp
+++ b/boost/math/tools/detail/rational_horner2_16.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class U, class V>
-inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const mpl::int_<0>*)
+inline V evaluate_rational_c_imp(const T*, const U*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/rational_horner2_17.hpp b/boost/math/tools/detail/rational_horner2_17.hpp
index 06330599d3..4d253b9593 100644
--- a/boost/math/tools/detail/rational_horner2_17.hpp
+++ b/boost/math/tools/detail/rational_horner2_17.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class U, class V>
-inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const mpl::int_<0>*)
+inline V evaluate_rational_c_imp(const T*, const U*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/rational_horner2_18.hpp b/boost/math/tools/detail/rational_horner2_18.hpp
index 78584e037f..6c213ecfb0 100644
--- a/boost/math/tools/detail/rational_horner2_18.hpp
+++ b/boost/math/tools/detail/rational_horner2_18.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class U, class V>
-inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const mpl::int_<0>*)
+inline V evaluate_rational_c_imp(const T*, const U*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/rational_horner2_19.hpp b/boost/math/tools/detail/rational_horner2_19.hpp
index 592e9edbcf..88e0b9ff01 100644
--- a/boost/math/tools/detail/rational_horner2_19.hpp
+++ b/boost/math/tools/detail/rational_horner2_19.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class U, class V>
-inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const mpl::int_<0>*)
+inline V evaluate_rational_c_imp(const T*, const U*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/rational_horner2_2.hpp b/boost/math/tools/detail/rational_horner2_2.hpp
index c5400a0d1c..35b5abb354 100644
--- a/boost/math/tools/detail/rational_horner2_2.hpp
+++ b/boost/math/tools/detail/rational_horner2_2.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class U, class V>
-inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const mpl::int_<0>*)
+inline V evaluate_rational_c_imp(const T*, const U*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/rational_horner2_20.hpp b/boost/math/tools/detail/rational_horner2_20.hpp
index 7f8f5d6a0a..dc73fdd58e 100644
--- a/boost/math/tools/detail/rational_horner2_20.hpp
+++ b/boost/math/tools/detail/rational_horner2_20.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class U, class V>
-inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const mpl::int_<0>*)
+inline V evaluate_rational_c_imp(const T*, const U*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/rational_horner2_3.hpp b/boost/math/tools/detail/rational_horner2_3.hpp
index 645c3c3642..8838ac13e6 100644
--- a/boost/math/tools/detail/rational_horner2_3.hpp
+++ b/boost/math/tools/detail/rational_horner2_3.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class U, class V>
-inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const mpl::int_<0>*)
+inline V evaluate_rational_c_imp(const T*, const U*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/rational_horner2_4.hpp b/boost/math/tools/detail/rational_horner2_4.hpp
index 781b4c1094..5fe5ada83b 100644
--- a/boost/math/tools/detail/rational_horner2_4.hpp
+++ b/boost/math/tools/detail/rational_horner2_4.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class U, class V>
-inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const mpl::int_<0>*)
+inline V evaluate_rational_c_imp(const T*, const U*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/rational_horner2_5.hpp b/boost/math/tools/detail/rational_horner2_5.hpp
index a11d0d643f..48b8498bc7 100644
--- a/boost/math/tools/detail/rational_horner2_5.hpp
+++ b/boost/math/tools/detail/rational_horner2_5.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class U, class V>
-inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const mpl::int_<0>*)
+inline V evaluate_rational_c_imp(const T*, const U*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/rational_horner2_6.hpp b/boost/math/tools/detail/rational_horner2_6.hpp
index 596bc115c6..83631eaf51 100644
--- a/boost/math/tools/detail/rational_horner2_6.hpp
+++ b/boost/math/tools/detail/rational_horner2_6.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class U, class V>
-inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const mpl::int_<0>*)
+inline V evaluate_rational_c_imp(const T*, const U*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/rational_horner2_7.hpp b/boost/math/tools/detail/rational_horner2_7.hpp
index 28998d2c9c..3ed86eafcd 100644
--- a/boost/math/tools/detail/rational_horner2_7.hpp
+++ b/boost/math/tools/detail/rational_horner2_7.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class U, class V>
-inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const mpl::int_<0>*)
+inline V evaluate_rational_c_imp(const T*, const U*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/rational_horner2_8.hpp b/boost/math/tools/detail/rational_horner2_8.hpp
index 1405c432f4..f8b36ece4a 100644
--- a/boost/math/tools/detail/rational_horner2_8.hpp
+++ b/boost/math/tools/detail/rational_horner2_8.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class U, class V>
-inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const mpl::int_<0>*)
+inline V evaluate_rational_c_imp(const T*, const U*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/rational_horner2_9.hpp b/boost/math/tools/detail/rational_horner2_9.hpp
index 5a537ef4e8..88cc4e5fcf 100644
--- a/boost/math/tools/detail/rational_horner2_9.hpp
+++ b/boost/math/tools/detail/rational_horner2_9.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class U, class V>
-inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const mpl::int_<0>*)
+inline V evaluate_rational_c_imp(const T*, const U*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/rational_horner3_10.hpp b/boost/math/tools/detail/rational_horner3_10.hpp
index 205077c2d7..019ffdacc3 100644
--- a/boost/math/tools/detail/rational_horner3_10.hpp
+++ b/boost/math/tools/detail/rational_horner3_10.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class U, class V>
-inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const mpl::int_<0>*)
+inline V evaluate_rational_c_imp(const T*, const U*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/rational_horner3_11.hpp b/boost/math/tools/detail/rational_horner3_11.hpp
index 05ed555c23..13ce3134ae 100644
--- a/boost/math/tools/detail/rational_horner3_11.hpp
+++ b/boost/math/tools/detail/rational_horner3_11.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class U, class V>
-inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const mpl::int_<0>*)
+inline V evaluate_rational_c_imp(const T*, const U*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/rational_horner3_12.hpp b/boost/math/tools/detail/rational_horner3_12.hpp
index 88d6d9402a..634140bd0d 100644
--- a/boost/math/tools/detail/rational_horner3_12.hpp
+++ b/boost/math/tools/detail/rational_horner3_12.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class U, class V>
-inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const mpl::int_<0>*)
+inline V evaluate_rational_c_imp(const T*, const U*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/rational_horner3_13.hpp b/boost/math/tools/detail/rational_horner3_13.hpp
index 8f1661a883..0b4974a501 100644
--- a/boost/math/tools/detail/rational_horner3_13.hpp
+++ b/boost/math/tools/detail/rational_horner3_13.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class U, class V>
-inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const mpl::int_<0>*)
+inline V evaluate_rational_c_imp(const T*, const U*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/rational_horner3_14.hpp b/boost/math/tools/detail/rational_horner3_14.hpp
index 2996173390..63f4e95963 100644
--- a/boost/math/tools/detail/rational_horner3_14.hpp
+++ b/boost/math/tools/detail/rational_horner3_14.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class U, class V>
-inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const mpl::int_<0>*)
+inline V evaluate_rational_c_imp(const T*, const U*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/rational_horner3_15.hpp b/boost/math/tools/detail/rational_horner3_15.hpp
index 67b71b42c4..c13500f130 100644
--- a/boost/math/tools/detail/rational_horner3_15.hpp
+++ b/boost/math/tools/detail/rational_horner3_15.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class U, class V>
-inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const mpl::int_<0>*)
+inline V evaluate_rational_c_imp(const T*, const U*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/rational_horner3_16.hpp b/boost/math/tools/detail/rational_horner3_16.hpp
index 75cb17a60b..b1c89774f8 100644
--- a/boost/math/tools/detail/rational_horner3_16.hpp
+++ b/boost/math/tools/detail/rational_horner3_16.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class U, class V>
-inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const mpl::int_<0>*)
+inline V evaluate_rational_c_imp(const T*, const U*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/rational_horner3_17.hpp b/boost/math/tools/detail/rational_horner3_17.hpp
index 275236412d..9c3498ec24 100644
--- a/boost/math/tools/detail/rational_horner3_17.hpp
+++ b/boost/math/tools/detail/rational_horner3_17.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class U, class V>
-inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const mpl::int_<0>*)
+inline V evaluate_rational_c_imp(const T*, const U*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/rational_horner3_18.hpp b/boost/math/tools/detail/rational_horner3_18.hpp
index 19e0a5337b..5401e9f3a2 100644
--- a/boost/math/tools/detail/rational_horner3_18.hpp
+++ b/boost/math/tools/detail/rational_horner3_18.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class U, class V>
-inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const mpl::int_<0>*)
+inline V evaluate_rational_c_imp(const T*, const U*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/rational_horner3_19.hpp b/boost/math/tools/detail/rational_horner3_19.hpp
index ff7156c804..c111b68f1e 100644
--- a/boost/math/tools/detail/rational_horner3_19.hpp
+++ b/boost/math/tools/detail/rational_horner3_19.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class U, class V>
-inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const mpl::int_<0>*)
+inline V evaluate_rational_c_imp(const T*, const U*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/rational_horner3_2.hpp b/boost/math/tools/detail/rational_horner3_2.hpp
index c5400a0d1c..35b5abb354 100644
--- a/boost/math/tools/detail/rational_horner3_2.hpp
+++ b/boost/math/tools/detail/rational_horner3_2.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class U, class V>
-inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const mpl::int_<0>*)
+inline V evaluate_rational_c_imp(const T*, const U*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/rational_horner3_20.hpp b/boost/math/tools/detail/rational_horner3_20.hpp
index a5948d2ff8..7bee9b110a 100644
--- a/boost/math/tools/detail/rational_horner3_20.hpp
+++ b/boost/math/tools/detail/rational_horner3_20.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class U, class V>
-inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const mpl::int_<0>*)
+inline V evaluate_rational_c_imp(const T*, const U*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/rational_horner3_3.hpp b/boost/math/tools/detail/rational_horner3_3.hpp
index 645c3c3642..8838ac13e6 100644
--- a/boost/math/tools/detail/rational_horner3_3.hpp
+++ b/boost/math/tools/detail/rational_horner3_3.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class U, class V>
-inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const mpl::int_<0>*)
+inline V evaluate_rational_c_imp(const T*, const U*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/rational_horner3_4.hpp b/boost/math/tools/detail/rational_horner3_4.hpp
index 781b4c1094..5fe5ada83b 100644
--- a/boost/math/tools/detail/rational_horner3_4.hpp
+++ b/boost/math/tools/detail/rational_horner3_4.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class U, class V>
-inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const mpl::int_<0>*)
+inline V evaluate_rational_c_imp(const T*, const U*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/rational_horner3_5.hpp b/boost/math/tools/detail/rational_horner3_5.hpp
index 333b7fd2e8..23a606855b 100644
--- a/boost/math/tools/detail/rational_horner3_5.hpp
+++ b/boost/math/tools/detail/rational_horner3_5.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class U, class V>
-inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const mpl::int_<0>*)
+inline V evaluate_rational_c_imp(const T*, const U*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/rational_horner3_6.hpp b/boost/math/tools/detail/rational_horner3_6.hpp
index 33e075b6af..186167d614 100644
--- a/boost/math/tools/detail/rational_horner3_6.hpp
+++ b/boost/math/tools/detail/rational_horner3_6.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class U, class V>
-inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const mpl::int_<0>*)
+inline V evaluate_rational_c_imp(const T*, const U*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/rational_horner3_7.hpp b/boost/math/tools/detail/rational_horner3_7.hpp
index 6f886d16df..e08dce62d7 100644
--- a/boost/math/tools/detail/rational_horner3_7.hpp
+++ b/boost/math/tools/detail/rational_horner3_7.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class U, class V>
-inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const mpl::int_<0>*)
+inline V evaluate_rational_c_imp(const T*, const U*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/rational_horner3_8.hpp b/boost/math/tools/detail/rational_horner3_8.hpp
index 062f9d3cba..3ceb717439 100644
--- a/boost/math/tools/detail/rational_horner3_8.hpp
+++ b/boost/math/tools/detail/rational_horner3_8.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class U, class V>
-inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const mpl::int_<0>*)
+inline V evaluate_rational_c_imp(const T*, const U*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/detail/rational_horner3_9.hpp b/boost/math/tools/detail/rational_horner3_9.hpp
index 5c47864eb0..94dab4c0db 100644
--- a/boost/math/tools/detail/rational_horner3_9.hpp
+++ b/boost/math/tools/detail/rational_horner3_9.hpp
@@ -12,7 +12,7 @@
namespace boost{ namespace math{ namespace tools{ namespace detail{
template <class T, class U, class V>
-inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const mpl::int_<0>*)
+inline V evaluate_rational_c_imp(const T*, const U*, const V&, const mpl::int_<0>*)
{
return static_cast<V>(0);
}
diff --git a/boost/math/tools/fraction.hpp b/boost/math/tools/fraction.hpp
index a9938094a7..b245ddd2a3 100644
--- a/boost/math/tools/fraction.hpp
+++ b/boost/math/tools/fraction.hpp
@@ -33,7 +33,7 @@ namespace detail
typedef typename Gen::result_type result_type;
typedef typename Gen::result_type value_type;
- static result_type a(const value_type& v)
+ static result_type a(const value_type&)
{
return 1;
}
diff --git a/boost/math/tools/precision.hpp b/boost/math/tools/precision.hpp
index 8cdcd4eb87..49e653d6a3 100644
--- a/boost/math/tools/precision.hpp
+++ b/boost/math/tools/precision.hpp
@@ -18,8 +18,6 @@
#include <boost/mpl/if.hpp>
#include <boost/math/policies/policy.hpp>
-#include <iostream>
-#include <iomanip>
// These two are for LDBL_MAN_DIG:
#include <limits.h>
#include <math.h>
@@ -159,11 +157,19 @@ inline T epsilon(const mpl::true_& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T))
return std::numeric_limits<T>::epsilon();
}
-#if (defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)) && ((LDBL_MANT_DIG == 106) || (__LDBL_MANT_DIG__ == 106))
+#if defined(__GNUC__) && ((LDBL_MANT_DIG == 106) || (__LDBL_MANT_DIG__ == 106))
template <>
inline long double epsilon<long double>(const mpl::true_& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(long double))
{
- // numeric_limits on Darwin tells lies here.
+ // numeric_limits on Darwin (and elsewhere) tells lies here:
+ // the issue is that long double on a few platforms is
+ // really a "double double" which has a non-contiguous
+ // mantissa: 53 bits followed by an unspecified number of
+ // zero bits, followed by 53 more bits. Thus the apparent
+ // precision of the type varies depending where it's been.
+ // Set epsilon to the value that a 106 bit fixed mantissa
+ // type would have, as that will give us sensible behaviour everywhere.
+ //
// This static assert fails for some unknown reason, so
// disabled for now...
// BOOST_STATIC_ASSERT(std::numeric_limits<long double>::digits == 106);
@@ -282,6 +288,38 @@ inline T root_epsilon_imp(const T*, const Tag&)
}
template <class T>
+inline T cbrt_epsilon_imp(const mpl::int_<24>&)
+{
+ return static_cast<T>(0.0049215666011518482998719164346805794944150447839903L);
+}
+
+template <class T>
+inline T cbrt_epsilon_imp(const T*, const mpl::int_<53>&)
+{
+ return static_cast<T>(6.05545445239333906078989272793696693569753008995e-6L);
+}
+
+template <class T>
+inline T cbrt_epsilon_imp(const T*, const mpl::int_<64>&)
+{
+ return static_cast<T>(4.76837158203125e-7L);
+}
+
+template <class T>
+inline T cbrt_epsilon_imp(const T*, const mpl::int_<113>&)
+{
+ return static_cast<T>(5.7749313854154005630396773604745549542403508090496e-12L);
+}
+
+template <class T, class Tag>
+inline T cbrt_epsilon_imp(const T*, const Tag&)
+{
+ BOOST_MATH_STD_USING;
+ static const T cbrt_eps = pow(tools::epsilon<T>(), T(1) / 3);
+ return cbrt_eps;
+}
+
+template <class T>
inline T forth_root_epsilon_imp(const T*, const mpl::int_<24>&)
{
return static_cast<T>(0.018581361171917516667460937040007436176452688944747L);
@@ -323,6 +361,13 @@ inline T root_epsilon()
}
template <class T>
+inline T cbrt_epsilon()
+{
+ typedef mpl::int_< (::std::numeric_limits<T>::radix == 2) ? std::numeric_limits<T>::digits : 0> tag_type;
+ return detail::cbrt_epsilon_imp(static_cast<T const*>(0), tag_type());
+}
+
+template <class T>
inline T forth_root_epsilon()
{
typedef mpl::int_< (::std::numeric_limits<T>::radix == 2) ? std::numeric_limits<T>::digits : 0> tag_type;
diff --git a/boost/math/tools/promotion.hpp b/boost/math/tools/promotion.hpp
index 728aaf1209..b3ad204077 100644
--- a/boost/math/tools/promotion.hpp
+++ b/boost/math/tools/promotion.hpp
@@ -138,10 +138,35 @@ namespace boost
//
// Guard against use of long double if it's not supported:
//
- BOOST_STATIC_ASSERT((0 == ::boost::is_same<type, long double>::value));
+ BOOST_STATIC_ASSERT_MSG((0 == ::boost::is_same<type, long double>::value), "Sorry, but this platform does not have sufficient long double support for the special functions to be reliably implemented.");
#endif
};
+ //
+ // This struct is the same as above, but has no static assert on long double usage,
+ // it should be used only on functions that can be implemented for long double
+ // even when std lib support is missing or broken for that type.
+ //
+ template <class T1, class T2=float, class T3=float, class T4=float, class T5=float, class T6=float>
+ struct promote_args_permissive
+ {
+ typedef typename promote_args_2<
+ typename remove_cv<T1>::type,
+ typename promote_args_2<
+ typename remove_cv<T2>::type,
+ typename promote_args_2<
+ typename remove_cv<T3>::type,
+ typename promote_args_2<
+ typename remove_cv<T4>::type,
+ typename promote_args_2<
+ typename remove_cv<T5>::type, typename remove_cv<T6>::type
+ >::type
+ >::type
+ >::type
+ >::type
+ >::type type;
+ };
+
} // namespace tools
} // namespace math
} // namespace boost
diff --git a/boost/math/tools/remez.hpp b/boost/math/tools/remez.hpp
deleted file mode 100644
index afcbe25afa..0000000000
--- a/boost/math/tools/remez.hpp
+++ /dev/null
@@ -1,667 +0,0 @@
-// (C) Copyright John Maddock 2006.
-// Use, modification and distribution are subject to the
-// Boost Software License, Version 1.0. (See accompanying file
-// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef BOOST_MATH_TOOLS_REMEZ_HPP
-#define BOOST_MATH_TOOLS_REMEZ_HPP
-
-#ifdef _MSC_VER
-#pragma once
-#endif
-
-#include <boost/math/tools/solve.hpp>
-#include <boost/math/tools/minima.hpp>
-#include <boost/math/tools/roots.hpp>
-#include <boost/math/tools/polynomial.hpp>
-#include <boost/function/function1.hpp>
-#include <boost/scoped_array.hpp>
-#include <boost/math/constants/constants.hpp>
-#include <boost/math/policies/policy.hpp>
-
-namespace boost{ namespace math{ namespace tools{
-
-namespace detail{
-
-//
-// The error function: the difference between F(x) and
-// the current approximation. This is the function
-// for which we must find the extema.
-//
-template <class T>
-struct remez_error_function
-{
- typedef boost::function1<T, T const &> function_type;
-public:
- remez_error_function(
- function_type f_,
- const polynomial<T>& n,
- const polynomial<T>& d,
- bool rel_err)
- : f(f_), numerator(n), denominator(d), rel_error(rel_err) {}
-
- T operator()(const T& z)const
- {
- T y = f(z);
- T abs = y - (numerator.evaluate(z) / denominator.evaluate(z));
- T err;
- if(rel_error)
- {
- if(y != 0)
- err = abs / fabs(y);
- else if(0 == abs)
- {
- // we must be at a root, or it's not recoverable:
- BOOST_ASSERT(0 == abs);
- err = 0;
- }
- else
- {
- // We have a divide by zero!
- // Lets assume that f(x) is zero as a result of
- // internal cancellation error that occurs as a result
- // of shifting a root at point z to the origin so that
- // the approximation can be "pinned" to pass through
- // the origin: in that case it really
- // won't matter what our approximation calculates here
- // as long as it's a small number, return the absolute error:
- err = abs;
- }
- }
- else
- err = abs;
- return err;
- }
-private:
- function_type f;
- polynomial<T> numerator;
- polynomial<T> denominator;
- bool rel_error;
-};
-//
-// This function adapts the error function so that it's minima
-// are the extema of the error function. We can find the minima
-// with standard techniques.
-//
-template <class T>
-struct remez_max_error_function
-{
- remez_max_error_function(const remez_error_function<T>& f)
- : func(f) {}
-
- T operator()(const T& x)
- {
- BOOST_MATH_STD_USING
- return -fabs(func(x));
- }
-private:
- remez_error_function<T> func;
-};
-
-} // detail
-
-template <class T>
-class remez_minimax
-{
-public:
- typedef boost::function1<T, T const &> function_type;
- typedef boost::numeric::ublas::vector<T> vector_type;
- typedef boost::numeric::ublas::matrix<T> matrix_type;
-
- remez_minimax(function_type f, unsigned oN, unsigned oD, T a, T b, bool pin = true, bool rel_err = false, int sk = 0, int bits = 0);
- remez_minimax(function_type f, unsigned oN, unsigned oD, T a, T b, bool pin, bool rel_err, int sk, int bits, const vector_type& points);
-
- void reset(unsigned oN, unsigned oD, T a, T b, bool pin = true, bool rel_err = false, int sk = 0, int bits = 0);
- void reset(unsigned oN, unsigned oD, T a, T b, bool pin, bool rel_err, int sk, int bits, const vector_type& points);
-
- void set_brake(int b)
- {
- BOOST_ASSERT(b < 100);
- BOOST_ASSERT(b >= 0);
- m_brake = b;
- }
-
- T iterate();
-
- polynomial<T> denominator()const;
- polynomial<T> numerator()const;
-
- vector_type const& chebyshev_points()const
- {
- return control_points;
- }
-
- vector_type const& zero_points()const
- {
- return zeros;
- }
-
- T error_term()const
- {
- return solution[solution.size() - 1];
- }
- T max_error()const
- {
- return m_max_error;
- }
- T max_change()const
- {
- return m_max_change;
- }
- void rotate()
- {
- --orderN;
- ++orderD;
- }
- void rescale(T a, T b)
- {
- T scale = (b - a) / (max - min);
- for(unsigned i = 0; i < control_points.size(); ++i)
- {
- control_points[i] = (control_points[i] - min) * scale + a;
- }
- min = a;
- max = b;
- }
-private:
-
- void init_chebyshev();
-
- function_type func; // The function to approximate.
- vector_type control_points; // Current control points to be used for the next iteration.
- vector_type solution; // Solution from the last iteration contains all unknowns including the error term.
- vector_type zeros; // Location of points of zero error from last iteration, plus the two end points.
- vector_type maxima; // Location of maxima of the error function, actually contains the control points used for the last iteration.
- T m_max_error; // Maximum error found in last approximation.
- T m_max_change; // Maximum change in location of control points after last iteration.
- unsigned orderN; // Order of the numerator polynomial.
- unsigned orderD; // Order of the denominator polynomial.
- T min, max; // End points of the range to optimise over.
- bool rel_error; // If true optimise for relative not absolute error.
- bool pinned; // If true the approximation is "pinned" to go through the origin.
- unsigned unknowns; // Total number of unknowns.
- int m_precision; // Number of bits precision to which the zeros and maxima are found.
- T m_max_change_history[2]; // Past history of changes to control points.
- int m_brake; // amount to break by in percentage points.
- int m_skew; // amount to skew starting points by in percentage points: -100-100
-};
-
-#ifndef BRAKE
-#define BRAKE 0
-#endif
-#ifndef SKEW
-#define SKEW 0
-#endif
-
-template <class T>
-void remez_minimax<T>::init_chebyshev()
-{
- BOOST_MATH_STD_USING
- //
- // Fill in the zeros:
- //
- unsigned terms = pinned ? orderD + orderN : orderD + orderN + 1;
-
- for(unsigned i = 0; i < terms; ++i)
- {
- T cheb = cos((2 * terms - 1 - 2 * i) * constants::pi<T>() / (2 * terms));
- cheb += 1;
- cheb /= 2;
- if(m_skew != 0)
- {
- T p = static_cast<T>(200 + m_skew) / 200;
- cheb = pow(cheb, p);
- }
- cheb *= (max - min);
- cheb += min;
- zeros[i+1] = cheb;
- }
- zeros[0] = min;
- zeros[unknowns] = max;
- // perform a regular interpolation fit:
- matrix_type A(terms, terms);
- vector_type b(terms);
- // fill in the y values:
- for(unsigned i = 0; i < b.size(); ++i)
- {
- b[i] = func(zeros[i+1]);
- }
- // fill in powers of x evaluated at each of the control points:
- unsigned offsetN = pinned ? 0 : 1;
- unsigned offsetD = offsetN + orderN;
- unsigned maxorder = (std::max)(orderN, orderD);
- for(unsigned i = 0; i < b.size(); ++i)
- {
- T x0 = zeros[i+1];
- T x = x0;
- if(!pinned)
- A(i, 0) = 1;
- for(unsigned j = 0; j < maxorder; ++j)
- {
- if(j < orderN)
- A(i, j + offsetN) = x;
- if(j < orderD)
- {
- A(i, j + offsetD) = -x * b[i];
- }
- x *= x0;
- }
- }
- //
- // Now go ahead and solve the expression to get our solution:
- //
- vector_type l_solution = boost::math::tools::solve(A, b);
- // need to add a "fake" error term:
- l_solution.resize(unknowns);
- l_solution[unknowns-1] = 0;
- solution = l_solution;
- //
- // Now find all the extrema of the error function:
- //
- detail::remez_error_function<T> Err(func, this->numerator(), this->denominator(), rel_error);
- detail::remez_max_error_function<T> Ex(Err);
- m_max_error = 0;
- int max_err_location = 0;
- for(unsigned i = 0; i < unknowns; ++i)
- {
- std::pair<T, T> r = brent_find_minima(Ex, zeros[i], zeros[i+1], m_precision);
- maxima[i] = r.first;
- T rel_err = fabs(r.second);
- if(rel_err > m_max_error)
- {
- m_max_error = fabs(r.second);
- max_err_location = i;
- }
- }
- control_points = maxima;
-}
-
-template <class T>
-void remez_minimax<T>::reset(
- unsigned oN,
- unsigned oD,
- T a,
- T b,
- bool pin,
- bool rel_err,
- int sk,
- int bits)
-{
- control_points = vector_type(oN + oD + (pin ? 1 : 2));
- solution = control_points;
- zeros = vector_type(oN + oD + (pin ? 2 : 3));
- maxima = control_points;
- orderN = oN;
- orderD = oD;
- rel_error = rel_err;
- pinned = pin;
- m_skew = sk;
- min = a;
- max = b;
- m_max_error = 0;
- unknowns = orderN + orderD + (pinned ? 1 : 2);
- // guess our initial control points:
- control_points[0] = min;
- control_points[unknowns - 1] = max;
- T interval = (max - min) / (unknowns - 1);
- T spot = min + interval;
- for(unsigned i = 1; i < control_points.size(); ++i)
- {
- control_points[i] = spot;
- spot += interval;
- }
- solution[unknowns - 1] = 0;
- m_max_error = 0;
- if(bits == 0)
- {
- // don't bother about more than float precision:
- m_precision = (std::min)(24, (boost::math::policies::digits<T, boost::math::policies::policy<> >() / 2) - 2);
- }
- else
- {
- // can't be more accurate than half the bits of T:
- m_precision = (std::min)(bits, (boost::math::policies::digits<T, boost::math::policies::policy<> >() / 2) - 2);
- }
- m_max_change_history[0] = m_max_change_history[1] = 1;
- init_chebyshev();
- // do one iteration whatever:
- //iterate();
-}
-
-template <class T>
-inline remez_minimax<T>::remez_minimax(
- typename remez_minimax<T>::function_type f,
- unsigned oN,
- unsigned oD,
- T a,
- T b,
- bool pin,
- bool rel_err,
- int sk,
- int bits)
- : func(f)
-{
- m_brake = 0;
- reset(oN, oD, a, b, pin, rel_err, sk, bits);
-}
-
-template <class T>
-void remez_minimax<T>::reset(
- unsigned oN,
- unsigned oD,
- T a,
- T b,
- bool pin,
- bool rel_err,
- int sk,
- int bits,
- const vector_type& points)
-{
- control_points = vector_type(oN + oD + (pin ? 1 : 2));
- solution = control_points;
- zeros = vector_type(oN + oD + (pin ? 2 : 3));
- maxima = control_points;
- orderN = oN;
- orderD = oD;
- rel_error = rel_err;
- pinned = pin;
- m_skew = sk;
- min = a;
- max = b;
- m_max_error = 0;
- unknowns = orderN + orderD + (pinned ? 1 : 2);
- control_points = points;
- solution[unknowns - 1] = 0;
- m_max_error = 0;
- if(bits == 0)
- {
- // don't bother about more than float precision:
- m_precision = (std::min)(24, (boost::math::policies::digits<T, boost::math::policies::policy<> >() / 2) - 2);
- }
- else
- {
- // can't be more accurate than half the bits of T:
- m_precision = (std::min)(bits, (boost::math::policies::digits<T, boost::math::policies::policy<> >() / 2) - 2);
- }
- m_max_change_history[0] = m_max_change_history[1] = 1;
- // do one iteration whatever:
- //iterate();
-}
-
-template <class T>
-inline remez_minimax<T>::remez_minimax(
- typename remez_minimax<T>::function_type f,
- unsigned oN,
- unsigned oD,
- T a,
- T b,
- bool pin,
- bool rel_err,
- int sk,
- int bits,
- const vector_type& points)
- : func(f)
-{
- m_brake = 0;
- reset(oN, oD, a, b, pin, rel_err, sk, bits, points);
-}
-
-template <class T>
-T remez_minimax<T>::iterate()
-{
- BOOST_MATH_STD_USING
- matrix_type A(unknowns, unknowns);
- vector_type b(unknowns);
-
- // fill in evaluation of f(x) at each of the control points:
- for(unsigned i = 0; i < b.size(); ++i)
- {
- // take care that none of our control points are at the origin:
- if(pinned && (control_points[i] == 0))
- {
- if(i)
- control_points[i] = control_points[i-1] / 3;
- else
- control_points[i] = control_points[i+1] / 3;
- }
- b[i] = func(control_points[i]);
- }
-
- T err_err;
- unsigned convergence_count = 0;
- do{
- // fill in powers of x evaluated at each of the control points:
- int sign = 1;
- unsigned offsetN = pinned ? 0 : 1;
- unsigned offsetD = offsetN + orderN;
- unsigned maxorder = (std::max)(orderN, orderD);
- T Elast = solution[unknowns - 1];
-
- for(unsigned i = 0; i < b.size(); ++i)
- {
- T x0 = control_points[i];
- T x = x0;
- if(!pinned)
- A(i, 0) = 1;
- for(unsigned j = 0; j < maxorder; ++j)
- {
- if(j < orderN)
- A(i, j + offsetN) = x;
- if(j < orderD)
- {
- T mult = rel_error ? (b[i] - sign * fabs(b[i]) * Elast): (b[i] - sign * Elast);
- A(i, j + offsetD) = -x * mult;
- }
- x *= x0;
- }
- // The last variable to be solved for is the error term,
- // sign changes with each control point:
- T E = rel_error ? sign * fabs(b[i]) : sign;
- A(i, unknowns - 1) = E;
- sign = -sign;
- }
-
- #ifdef BOOST_MATH_INSTRUMENT
- for(unsigned i = 0; i < b.size(); ++i)
- std::cout << b[i] << " ";
- std::cout << "\n\n";
- for(unsigned i = 0; i < b.size(); ++i)
- {
- for(unsigned j = 0; j < b.size(); ++ j)
- std::cout << A(i, j) << " ";
- std::cout << "\n";
- }
- std::cout << std::endl;
- #endif
- //
- // Now go ahead and solve the expression to get our solution:
- //
- solution = boost::math::tools::solve(A, b);
-
- err_err = (Elast != 0) ? fabs((fabs(solution[unknowns-1]) - fabs(Elast)) / fabs(Elast)) : 1;
- }while(orderD && (convergence_count++ < 80) && (err_err > 0.001));
-
- //
- // Perform a sanity check to verify that the solution to the equations
- // is not so much in error as to be useless. The matrix inversion can
- // be very close to singular, so this can be a real problem.
- //
- vector_type sanity = prod(A, solution);
- for(unsigned i = 0; i < b.size(); ++i)
- {
- T err = fabs((b[i] - sanity[i]) / fabs(b[i]));
- if(err > sqrt(epsilon<T>()))
- {
- std::cerr << "Sanity check failed: more than half the digits in the found solution are in error." << std::endl;
- }
- }
-
- //
- // Next comes another sanity check, we want to verify that all the control
- // points do actually alternate in sign, in practice we may have
- // additional roots in the error function that cause this to fail.
- // Failure here is always fatal: even though this code attempts to correct
- // the problem it usually only postpones the inevitable.
- //
- polynomial<T> num, denom;
- num = this->numerator();
- denom = this->denominator();
- T e1 = b[0] - num.evaluate(control_points[0]) / denom.evaluate(control_points[0]);
-#ifdef BOOST_MATH_INSTRUMENT
- std::cout << e1;
-#endif
- for(unsigned i = 1; i < b.size(); ++i)
- {
- T e2 = b[i] - num.evaluate(control_points[i]) / denom.evaluate(control_points[i]);
-#ifdef BOOST_MATH_INSTRUMENT
- std::cout << " " << e2;
-#endif
- if(e2 * e1 > 0)
- {
- std::cerr << std::flush << "Basic sanity check failed: Error term does not alternate in sign, non-recoverable error may follow..." << std::endl;
- T perturbation = 0.05;
- do{
- T point = control_points[i] * (1 - perturbation) + control_points[i-1] * perturbation;
- e2 = func(point) - num.evaluate(point) / denom.evaluate(point);
- if(e2 * e1 < 0)
- {
- control_points[i] = point;
- break;
- }
- perturbation += 0.05;
- }while(perturbation < 0.8);
-
- if((e2 * e1 > 0) && (i + 1 < b.size()))
- {
- perturbation = 0.05;
- do{
- T point = control_points[i] * (1 - perturbation) + control_points[i+1] * perturbation;
- e2 = func(point) - num.evaluate(point) / denom.evaluate(point);
- if(e2 * e1 < 0)
- {
- control_points[i] = point;
- break;
- }
- perturbation += 0.05;
- }while(perturbation < 0.8);
- }
-
- }
- e1 = e2;
- }
-
-#ifdef BOOST_MATH_INSTRUMENT
- for(unsigned i = 0; i < solution.size(); ++i)
- std::cout << solution[i] << " ";
- std::cout << std::endl << this->numerator() << std::endl;
- std::cout << this->denominator() << std::endl;
- std::cout << std::endl;
-#endif
-
- //
- // The next step is to find all the intervals in which our maxima
- // lie:
- //
- detail::remez_error_function<T> Err(func, this->numerator(), this->denominator(), rel_error);
- zeros[0] = min;
- zeros[unknowns] = max;
- for(unsigned i = 1; i < control_points.size(); ++i)
- {
- eps_tolerance<T> tol(m_precision);
- boost::uintmax_t max_iter = 1000;
- std::pair<T, T> p = toms748_solve(
- Err,
- control_points[i-1],
- control_points[i],
- tol,
- max_iter);
- zeros[i] = (p.first + p.second) / 2;
- //zeros[i] = bisect(Err, control_points[i-1], control_points[i], m_precision);
- }
- //
- // Now find all the extrema of the error function:
- //
- detail::remez_max_error_function<T> Ex(Err);
- m_max_error = 0;
- int max_err_location = 0;
- for(unsigned i = 0; i < unknowns; ++i)
- {
- std::pair<T, T> r = brent_find_minima(Ex, zeros[i], zeros[i+1], m_precision);
- maxima[i] = r.first;
- T rel_err = fabs(r.second);
- if(rel_err > m_max_error)
- {
- m_max_error = fabs(r.second);
- max_err_location = i;
- }
- }
- //
- // Almost done now! we just need to set our control points
- // to the extrema, and calculate how much each point has changed
- // (this will be our termination condition):
- //
- swap(control_points, maxima);
- m_max_change = 0;
- int max_change_location = 0;
- for(unsigned i = 0; i < unknowns; ++i)
- {
- control_points[i] = (control_points[i] * (100 - m_brake) + maxima[i] * m_brake) / 100;
- T change = fabs((control_points[i] - maxima[i]) / control_points[i]);
-#if 0
- if(change > m_max_change_history[1])
- {
- // divergence!!! try capping the change:
- std::cerr << "Possible divergent step, change will be capped!!" << std::endl;
- change = m_max_change_history[1];
- if(control_points[i] < maxima[i])
- control_points[i] = maxima[i] - change * maxima[i];
- else
- control_points[i] = maxima[i] + change * maxima[i];
- }
-#endif
- if(change > m_max_change)
- {
- m_max_change = change;
- max_change_location = i;
- }
- }
- //
- // store max change information:
- //
- m_max_change_history[0] = m_max_change_history[1];
- m_max_change_history[1] = fabs(m_max_change);
-
- return m_max_change;
-}
-
-template <class T>
-polynomial<T> remez_minimax<T>::numerator()const
-{
- boost::scoped_array<T> a(new T[orderN + 1]);
- if(pinned)
- a[0] = 0;
- unsigned terms = pinned ? orderN : orderN + 1;
- for(unsigned i = 0; i < terms; ++i)
- a[pinned ? i+1 : i] = solution[i];
- return boost::math::tools::polynomial<T>(&a[0], orderN);
-}
-
-template <class T>
-polynomial<T> remez_minimax<T>::denominator()const
-{
- unsigned terms = orderD + 1;
- unsigned offsetD = pinned ? orderN : (orderN + 1);
- boost::scoped_array<T> a(new T[terms]);
- a[0] = 1;
- for(unsigned i = 0; i < orderD; ++i)
- a[i+1] = solution[i + offsetD];
- return boost::math::tools::polynomial<T>(&a[0], orderD);
-}
-
-
-}}} // namespaces
-
-#endif // BOOST_MATH_TOOLS_REMEZ_HPP
-
-
-
diff --git a/boost/math/tools/roots.hpp b/boost/math/tools/roots.hpp
index 356197dcf2..2442f5c2d1 100644
--- a/boost/math/tools/roots.hpp
+++ b/boost/math/tools/roots.hpp
@@ -109,13 +109,13 @@ std::pair<T, T> bisect(F f, T min, T max, Tol tol, boost::uintmax_t& max_iter, c
static const char* function = "boost::math::tools::bisect<%1%>";
if(min >= max)
{
- policies::raise_evaluation_error(function,
- "Arguments in wrong order in boost::math::tools::bisect (first arg=%1%)", min, pol);
+ return boost::math::detail::pair_from_single(policies::raise_evaluation_error(function,
+ "Arguments in wrong order in boost::math::tools::bisect (first arg=%1%)", min, pol));
}
if(fmin * fmax >= 0)
{
- policies::raise_evaluation_error(function,
- "No change of sign in boost::math::tools::bisect, either there is no root to find, or there are multiple roots in the interval (f(min) = %1%).", fmin, pol);
+ return boost::math::detail::pair_from_single(policies::raise_evaluation_error(function,
+ "No change of sign in boost::math::tools::bisect, either there is no root to find, or there are multiple roots in the interval (f(min) = %1%).", fmin, pol));
}
//
@@ -302,7 +302,7 @@ T halley_iterate(F f, T guess, T min, T max, int digits, boost::uintmax_t& max_i
if(0 == f0)
break;
- if((f1 == 0) && (f2 == 0))
+ if(f1 == 0)
{
// Oops zero derivative!!!
#ifdef BOOST_MATH_INSTRUMENT
@@ -329,8 +329,18 @@ T halley_iterate(F f, T guess, T min, T max, int digits, boost::uintmax_t& max_i
delta = denom / num;
if(delta * f1 / f0 < 0)
{
- // probably cancellation error, try a Newton step instead:
+ // Oh dear, we have a problem as Newton and Halley steps
+ // disagree about which way we should move. Probably
+ // there is cancelation error in the calculation of the
+ // Halley step, or else the derivatives are so small
+ // that their values are basically trash. We will move
+ // in the direction indicated by a Newton step, but
+ // by no more than twice the current guess value, otherwise
+ // we can jump way out of bounds if we're not careful.
+ // See https://svn.boost.org/trac/boost/ticket/8314.
delta = f0 / f1;
+ if(fabs(delta) > 2 * fabs(guess))
+ delta = (delta < 0 ? -1 : 1) * 2 * fabs(guess);
}
}
else
diff --git a/boost/math/tools/solve.hpp b/boost/math/tools/solve.hpp
deleted file mode 100644
index 64b01e5210..0000000000
--- a/boost/math/tools/solve.hpp
+++ /dev/null
@@ -1,79 +0,0 @@
-// (C) Copyright John Maddock 2006.
-// Use, modification and distribution are subject to the
-// Boost Software License, Version 1.0. (See accompanying file
-// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef BOOST_MATH_TOOLS_SOLVE_HPP
-#define BOOST_MATH_TOOLS_SOLVE_HPP
-
-#ifdef _MSC_VER
-#pragma once
-#endif
-
-#include <boost/config.hpp>
-#include <boost/assert.hpp>
-
-#ifdef BOOST_MSVC
-#pragma warning(push)
-#pragma warning(disable:4996 4267 4244)
-#endif
-
-#include <boost/numeric/ublas/lu.hpp>
-#include <boost/numeric/ublas/matrix.hpp>
-#include <boost/numeric/ublas/vector.hpp>
-
-#ifdef BOOST_MSVC
-#pragma warning(pop)
-#endif
-
-namespace boost{ namespace math{ namespace tools{
-
-//
-// Find x such that Ax = b
-//
-// Caution: this uses undocumented, and untested ublas code,
-// however short of writing our own LU-decompostion code
-// it's the only game in town.
-//
-template <class T>
-boost::numeric::ublas::vector<T> solve(
- const boost::numeric::ublas::matrix<T>& A_,
- const boost::numeric::ublas::vector<T>& b_)
-{
- //BOOST_ASSERT(A_.size() == b_.size());
-
- boost::numeric::ublas::matrix<T> A(A_);
- boost::numeric::ublas::vector<T> b(b_);
- boost::numeric::ublas::permutation_matrix<> piv(b.size());
- lu_factorize(A, piv);
- lu_substitute(A, piv, b);
- //
- // iterate to reduce error:
- //
- boost::numeric::ublas::vector<T> delta(b.size());
- for(unsigned i = 0; i < 1; ++i)
- {
- noalias(delta) = prod(A_, b);
- delta -= b_;
- lu_substitute(A, piv, delta);
- b -= delta;
-
- T max_error = 0;
-
- for(unsigned i = 0; i < delta.size(); ++i)
- {
- T err = fabs(delta[i] / b[i]);
- if(err > max_error)
- max_error = err;
- }
- //std::cout << "Max change in LU error correction: " << max_error << std::endl;
- }
-
- return b;
-}
-
-}}} // namespaces
-
-#endif // BOOST_MATH_TOOLS_SOLVE_HPP
-
-
diff --git a/boost/math/tools/test.hpp b/boost/math/tools/test.hpp
deleted file mode 100644
index af51d9e3e1..0000000000
--- a/boost/math/tools/test.hpp
+++ /dev/null
@@ -1,332 +0,0 @@
-// (C) Copyright John Maddock 2006.
-// Use, modification and distribution are subject to the
-// Boost Software License, Version 1.0. (See accompanying file
-// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef BOOST_MATH_TOOLS_TEST_HPP
-#define BOOST_MATH_TOOLS_TEST_HPP
-
-#ifdef _MSC_VER
-#pragma once
-#endif
-
-#include <boost/math/tools/config.hpp>
-#include <boost/math/tools/stats.hpp>
-#include <boost/math/special_functions/fpclassify.hpp>
-#include <boost/test/test_tools.hpp>
-#include <stdexcept>
-
-namespace boost{ namespace math{ namespace tools{
-
-template <class T>
-struct test_result
-{
-private:
- boost::math::tools::stats<T> stat; // Statistics for the test.
- unsigned worst_case; // Index of the worst case test.
-public:
- test_result() { worst_case = 0; }
- void set_worst(int i){ worst_case = i; }
- void add(const T& point){ stat.add(point); }
- // accessors:
- unsigned worst()const{ return worst_case; }
- T min BOOST_PREVENT_MACRO_SUBSTITUTION()const{ return (stat.min)(); }
- T max BOOST_PREVENT_MACRO_SUBSTITUTION()const{ return (stat.max)(); }
- T total()const{ return stat.total(); }
- T mean()const{ return stat.mean(); }
- boost::uintmax_t count()const{ return stat.count(); }
- T variance()const{ return stat.variance(); }
- T variance1()const{ return stat.variance1(); }
- T rms()const{ return stat.rms(); }
-
- test_result& operator+=(const test_result& t)
- {
- if((t.stat.max)() > (stat.max)())
- worst_case = t.worst_case;
- stat += t.stat;
- return *this;
- }
-};
-
-template <class T>
-struct calculate_result_type
-{
- typedef typename T::value_type row_type;
- typedef typename row_type::value_type value_type;
-};
-
-template <class T>
-T relative_error(T a, T b)
-{
- BOOST_MATH_STD_USING
-#ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
- //
- // If math.h has no long double support we can't rely
- // on the math functions generating exponents outside
- // the range of a double:
- //
- T min_val = (std::max)(
- tools::min_value<T>(),
- static_cast<T>((std::numeric_limits<double>::min)()));
- T max_val = (std::min)(
- tools::max_value<T>(),
- static_cast<T>((std::numeric_limits<double>::max)()));
-#else
- T min_val = tools::min_value<T>();
- T max_val = tools::max_value<T>();
-#endif
-
- if((a != 0) && (b != 0))
- {
- // TODO: use isfinite:
- if(fabs(b) >= max_val)
- {
- if(fabs(a) >= max_val)
- return 0; // one infinity is as good as another!
- }
- // If the result is denormalised, treat all denorms as equivalent:
- if((a < min_val) && (a > 0))
- a = min_val;
- else if((a > -min_val) && (a < 0))
- a = -min_val;
- if((b < min_val) && (b > 0))
- b = min_val;
- else if((b > -min_val) && (b < 0))
- b = -min_val;
- return (std::max)(fabs((a-b)/a), fabs((a-b)/b));
- }
-
- // Handle special case where one or both are zero:
- if(min_val == 0)
- return fabs(a-b);
- if(fabs(a) < min_val)
- a = min_val;
- if(fabs(b) < min_val)
- b = min_val;
- return (std::max)(fabs((a-b)/a), fabs((a-b)/b));
-}
-
-#if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
-template <>
-inline double relative_error<double>(double a, double b)
-{
- BOOST_MATH_STD_USING
- //
- // On Mac OS X we evaluate "double" functions at "long double" precision,
- // but "long double" actually has a very slightly narrower range than "double"!
- // Therefore use the range of "long double" as our limits since results outside
- // that range may have been truncated to 0 or INF:
- //
- double min_val = (std::max)((double)tools::min_value<long double>(), tools::min_value<double>());
- double max_val = (std::min)((double)tools::max_value<long double>(), tools::max_value<double>());
-
- if((a != 0) && (b != 0))
- {
- // TODO: use isfinite:
- if(b > max_val)
- {
- if(a > max_val)
- return 0; // one infinity is as good as another!
- }
- // If the result is denormalised, treat all denorms as equivalent:
- if((a < min_val) && (a > 0))
- a = min_val;
- else if((a > -min_val) && (a < 0))
- a = -min_val;
- if((b < min_val) && (b > 0))
- b = min_val;
- else if((b > -min_val) && (b < 0))
- b = -min_val;
- return (std::max)(fabs((a-b)/a), fabs((a-b)/b));
- }
-
- // Handle special case where one or both are zero:
- if(min_val == 0)
- return fabs(a-b);
- if(fabs(a) < min_val)
- a = min_val;
- if(fabs(b) < min_val)
- b = min_val;
- return (std::max)(fabs((a-b)/a), fabs((a-b)/b));
-}
-#endif
-
-template <class T>
-void set_output_precision(T)
-{
-#ifdef BOOST_MSVC
-#pragma warning(push)
-#pragma warning(disable:4127)
-#endif
- if(std::numeric_limits<T>::digits10)
- {
- std::cout << std::setprecision(std::numeric_limits<T>::digits10 + 2);
- }
-#ifdef BOOST_MSVC
-#pragma warning(pop)
-#endif
-}
-
-template <class Seq>
-void print_row(const Seq& row)
-{
- set_output_precision(row[0]);
- for(unsigned i = 0; i < row.size(); ++i)
- {
- if(i)
- std::cout << ", ";
- std::cout << row[i];
- }
- std::cout << std::endl;
-}
-
-//
-// Function test accepts an matrix of input values (probably a 2D boost::array)
-// and calls two functors for each row in the array - one calculates a value
-// to test, and one extracts the expected value from the array (or possibly
-// calculates it at high precision). The two functors are usually simple lambda
-// expressions.
-//
-template <class A, class F1, class F2>
-test_result<typename calculate_result_type<A>::value_type> test(const A& a, F1 test_func, F2 expect_func)
-{
- typedef typename A::value_type row_type;
- typedef typename row_type::value_type value_type;
-
- test_result<value_type> result;
-
- for(unsigned i = 0; i < a.size(); ++i)
- {
- const row_type& row = a[i];
- value_type point;
- try
- {
- point = test_func(row);
- }
- catch(const std::underflow_error&)
- {
- point = 0;
- }
- catch(const std::overflow_error&)
- {
- point = std::numeric_limits<value_type>::has_infinity ?
- std::numeric_limits<value_type>::infinity()
- : tools::max_value<value_type>();
- }
- catch(const std::exception& e)
- {
- std::cerr << e.what() << std::endl;
- print_row(row);
- BOOST_ERROR("Unexpected exception.");
- // so we don't get further errors:
- point = expect_func(row);
- }
- value_type expected = expect_func(row);
- value_type err = relative_error(point, expected);
-#ifdef BOOST_INSTRUMENT
- if(err != 0)
- {
- std::cout << row[0] << " " << err;
- if(std::numeric_limits<value_type>::is_specialized)
- {
- std::cout << " (" << err / std::numeric_limits<value_type>::epsilon() << "eps)";
- }
- std::cout << std::endl;
- }
-#endif
- if(!(boost::math::isfinite)(point) && (boost::math::isfinite)(expected))
- {
- std::cout << "CAUTION: Found non-finite result, when a finite value was expected at entry " << i << "\n";
- std::cout << "Found: " << point << " Expected " << expected << " Error: " << err << std::endl;
- print_row(row);
- BOOST_ERROR("Unexpected non-finite result");
- }
- if(err > 0.5)
- {
- std::cout << "CAUTION: Gross error found at entry " << i << ".\n";
- std::cout << "Found: " << point << " Expected " << expected << " Error: " << err << std::endl;
- print_row(row);
- BOOST_ERROR("Gross error");
- }
- result.add(err);
- if((result.max)() == err)
- result.set_worst(i);
- }
- return result;
-}
-
-template <class Real, class A, class F1, class F2>
-test_result<Real> test_hetero(const A& a, F1 test_func, F2 expect_func)
-{
- typedef typename A::value_type row_type;
- typedef Real value_type;
-
- test_result<value_type> result;
-
- for(unsigned i = 0; i < a.size(); ++i)
- {
- const row_type& row = a[i];
- value_type point;
- try
- {
- point = test_func(row);
- }
- catch(const std::underflow_error&)
- {
- point = 0;
- }
- catch(const std::overflow_error&)
- {
- point = std::numeric_limits<value_type>::has_infinity ?
- std::numeric_limits<value_type>::infinity()
- : tools::max_value<value_type>();
- }
- catch(const std::exception& e)
- {
- std::cerr << e.what() << std::endl;
- print_row(row);
- BOOST_ERROR("Unexpected exception.");
- // so we don't get further errors:
- point = expect_func(row);
- }
- value_type expected = expect_func(row);
- value_type err = relative_error(point, expected);
-#ifdef BOOST_INSTRUMENT
- if(err != 0)
- {
- std::cout << row[0] << " " << err;
- if(std::numeric_limits<value_type>::is_specialized)
- {
- std::cout << " (" << err / std::numeric_limits<value_type>::epsilon() << "eps)";
- }
- std::cout << std::endl;
- }
-#endif
- if(!(boost::math::isfinite)(point) && (boost::math::isfinite)(expected))
- {
- std::cout << "CAUTION: Found non-finite result, when a finite value was expected at entry " << i << "\n";
- std::cout << "Found: " << point << " Expected " << expected << " Error: " << err << std::endl;
- print_row(row);
- BOOST_ERROR("Unexpected non-finite result");
- }
- if(err > 0.5)
- {
- std::cout << "CAUTION: Gross error found at entry " << i << ".\n";
- std::cout << "Found: " << point << " Expected " << expected << " Error: " << err << std::endl;
- print_row(row);
- BOOST_ERROR("Gross error");
- }
- result.add(err);
- if((result.max)() == err)
- result.set_worst(i);
- }
- return result;
-}
-
-} // namespace tools
-} // namespace math
-} // namespace boost
-
-#endif
-
-
diff --git a/boost/math/tools/test_data.hpp b/boost/math/tools/test_data.hpp
deleted file mode 100644
index 56bae051b4..0000000000
--- a/boost/math/tools/test_data.hpp
+++ /dev/null
@@ -1,767 +0,0 @@
-// (C) Copyright John Maddock 2006.
-// Use, modification and distribution are subject to the
-// Boost Software License, Version 1.0. (See accompanying file
-// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef BOOST_MATH_TOOLS_TEST_DATA_HPP
-#define BOOST_MATH_TOOLS_TEST_DATA_HPP
-
-#ifdef _MSC_VER
-#pragma once
-#endif
-
-#include <boost/math/tools/config.hpp>
-#include <boost/assert.hpp>
-#ifdef BOOST_MSVC
-# pragma warning(push)
-# pragma warning(disable: 4127 4701 4512)
-# pragma warning(disable: 4130) // '==' : logical operation on address of string constant.
-#endif
-#include <boost/algorithm/string/trim.hpp>
-#include <boost/lexical_cast.hpp>
-#ifdef BOOST_MSVC
-#pragma warning(pop)
-#endif
-#include <boost/type_traits/is_floating_point.hpp>
-#include <boost/type_traits/is_convertible.hpp>
-#include <boost/type_traits/integral_constant.hpp>
-#include <boost/tr1/random.hpp>
-#include <boost/math/tools/tuple.hpp>
-#include <boost/math/tools/real_cast.hpp>
-
-#include <set>
-#include <vector>
-#include <iostream>
-
-#ifdef BOOST_MSVC
-# pragma warning(push)
-# pragma warning(disable: 4130) // '==' : logical operation on address of string constant.
-// Used as a warning with BOOST_ASSERT
-#endif
-
-namespace boost{ namespace math{ namespace tools{
-
-enum parameter_type
-{
- random_in_range = 0,
- periodic_in_range = 1,
- power_series = 2,
- dummy_param = 0x80
-};
-
-parameter_type operator | (parameter_type a, parameter_type b)
-{
- return static_cast<parameter_type>((int)a|(int)b);
-}
-parameter_type& operator |= (parameter_type& a, parameter_type b)
-{
- a = static_cast<parameter_type>(a|b);
- return a;
-}
-
-//
-// If type == random_in_range then
-// z1 and r2 are the endpoints of the half open range and n1 is the number of points.
-//
-// If type == periodic_in_range then
-// z1 and r2 are the endpoints of the half open range and n1 is the number of points.
-//
-// If type == power_series then
-// n1 and n2 are the endpoints of the exponents (closed range) and z1 is the basis.
-//
-// If type & dummy_param then this data is ignored and not stored in the output, it
-// is passed to the generator function however which can do with it as it sees fit.
-//
-template <class T>
-struct parameter_info
-{
- parameter_type type;
- T z1, z2;
- int n1, n2;
-};
-
-template <class T>
-inline parameter_info<T> make_random_param(T start_range, T end_range, int n_points)
-{
- parameter_info<T> result = { random_in_range, start_range, end_range, n_points, 0 };
- return result;
-}
-
-template <class T>
-inline parameter_info<T> make_periodic_param(T start_range, T end_range, int n_points)
-{
- parameter_info<T> result = { periodic_in_range, start_range, end_range, n_points, 0 };
- return result;
-}
-
-template <class T>
-inline parameter_info<T> make_power_param(T basis, int start_exponent, int end_exponent)
-{
- parameter_info<T> result = { power_series, basis, 0, start_exponent, end_exponent };
- return result;
-}
-
-namespace detail{
-
-template <class Seq, class Item, int N>
-inline void unpack_and_append_tuple(Seq& s,
- const Item& data,
- const boost::integral_constant<int, N>&,
- const boost::false_type&)
-{
- // termimation condition nothing to do here
-}
-
-template <class Seq, class Item, int N>
-inline void unpack_and_append_tuple(Seq& s,
- const Item& data,
- const boost::integral_constant<int, N>&,
- const boost::true_type&)
-{
- // extract the N'th element, append, and recurse:
- typedef typename Seq::value_type value_type;
- value_type val = boost::math::get<N>(data);
- s.push_back(val);
-
- typedef boost::integral_constant<int, N+1> next_value;
- typedef boost::integral_constant<bool, (boost::math::tuple_size<Item>::value > N+1)> terminate;
-
- unpack_and_append_tuple(s, data, next_value(), terminate());
-}
-
-template <class Seq, class Item>
-inline void unpack_and_append(Seq& s, const Item& data, const boost::true_type&)
-{
- s.push_back(data);
-}
-
-template <class Seq, class Item>
-inline void unpack_and_append(Seq& s, const Item& data, const boost::false_type&)
-{
- // Item had better be a tuple-like type or we've had it!!!!
- typedef boost::integral_constant<int, 0> next_value;
- typedef boost::integral_constant<bool, (boost::math::tuple_size<Item>::value > 0)> terminate;
-
- unpack_and_append_tuple(s, data, next_value(), terminate());
-}
-
-template <class Seq, class Item>
-inline void unpack_and_append(Seq& s, const Item& data)
-{
- typedef typename Seq::value_type value_type;
- unpack_and_append(s, data, ::boost::is_convertible<Item, value_type>());
-}
-
-} // detail
-
-template <class T>
-class test_data
-{
-public:
- typedef std::vector<T> row_type;
- typedef row_type value_type;
-private:
- typedef std::set<row_type> container_type;
-public:
- typedef typename container_type::reference reference;
- typedef typename container_type::const_reference const_reference;
- typedef typename container_type::iterator iterator;
- typedef typename container_type::const_iterator const_iterator;
- typedef typename container_type::difference_type difference_type;
- typedef typename container_type::size_type size_type;
-
- // creation:
- test_data(){}
- template <class F>
- test_data(F func, const parameter_info<T>& arg1)
- {
- insert(func, arg1);
- }
-
- // insertion:
- template <class F>
- test_data& insert(F func, const parameter_info<T>& arg1)
- {
- // generate data for single argument functor F
-
- typedef typename std::set<T>::const_iterator it_type;
-
- std::set<T> points;
- create_test_points(points, arg1);
- it_type a = points.begin();
- it_type b = points.end();
- row_type row;
- while(a != b)
- {
- if((arg1.type & dummy_param) == 0)
- row.push_back(*a);
- try{
- // domain_error exceptions from func are swallowed
- // and this data point is ignored:
- boost::math::tools::detail::unpack_and_append(row, func(*a));
- m_data.insert(row);
- }
- catch(const std::domain_error&){}
- row.clear();
- ++a;
- }
- return *this;
- }
-
- template <class F>
- test_data& insert(F func, const parameter_info<T>& arg1, const parameter_info<T>& arg2)
- {
- // generate data for 2-argument functor F
-
- typedef typename std::set<T>::const_iterator it_type;
-
- std::set<T> points1, points2;
- create_test_points(points1, arg1);
- create_test_points(points2, arg2);
- it_type a = points1.begin();
- it_type b = points1.end();
- row_type row;
- while(a != b)
- {
- it_type c = points2.begin();
- it_type d = points2.end();
- while(c != d)
- {
- if((arg1.type & dummy_param) == 0)
- row.push_back(*a);
- if((arg2.type & dummy_param) == 0)
- row.push_back(*c);
- try{
- // domain_error exceptions from func are swallowed
- // and this data point is ignored:
- detail::unpack_and_append(row, func(*a, *c));
- m_data.insert(row);
- }
- catch(const std::domain_error&){}
- row.clear();
- ++c;
- }
- ++a;
- }
- return *this;
- }
-
- template <class F>
- test_data& insert(F func, const parameter_info<T>& arg1, const parameter_info<T>& arg2, const parameter_info<T>& arg3)
- {
- // generate data for 3-argument functor F
-
- typedef typename std::set<T>::const_iterator it_type;
-
- std::set<T> points1, points2, points3;
- create_test_points(points1, arg1);
- create_test_points(points2, arg2);
- create_test_points(points3, arg3);
- it_type a = points1.begin();
- it_type b = points1.end();
- row_type row;
- while(a != b)
- {
- it_type c = points2.begin();
- it_type d = points2.end();
- while(c != d)
- {
- it_type e = points3.begin();
- it_type f = points3.end();
- while(e != f)
- {
- if((arg1.type & dummy_param) == 0)
- row.push_back(*a);
- if((arg2.type & dummy_param) == 0)
- row.push_back(*c);
- if((arg3.type & dummy_param) == 0)
- row.push_back(*e);
- try{
- // domain_error exceptions from func are swallowed
- // and this data point is ignored:
- detail::unpack_and_append(row, func(*a, *c, *e));
- m_data.insert(row);
- }
- catch(const std::domain_error&){}
- row.clear();
- ++e;
- }
- ++c;
- }
- ++a;
- }
- return *this;
- }
-
- void clear(){ m_data.clear(); }
-
- // access:
- iterator begin() { return m_data.begin(); }
- iterator end() { return m_data.end(); }
- const_iterator begin()const { return m_data.begin(); }
- const_iterator end()const { return m_data.end(); }
- bool operator==(const test_data& d)const{ return m_data == d.m_data; }
- bool operator!=(const test_data& d)const{ return m_data != d.m_data; }
- void swap(test_data& other){ m_data.swap(other.m_data); }
- size_type size()const{ return m_data.size(); }
- size_type max_size()const{ return m_data.max_size(); }
- bool empty()const{ return m_data.empty(); }
-
- bool operator < (const test_data& dat)const{ return m_data < dat.m_data; }
- bool operator <= (const test_data& dat)const{ return m_data <= dat.m_data; }
- bool operator > (const test_data& dat)const{ return m_data > dat.m_data; }
- bool operator >= (const test_data& dat)const{ return m_data >= dat.m_data; }
-
-private:
- void create_test_points(std::set<T>& points, const parameter_info<T>& arg1);
- std::set<row_type> m_data;
-
- static float extern_val;
- static float truncate_to_float(float const * pf);
- static float truncate_to_float(float c){ return truncate_to_float(&c); }
-};
-
-//
-// This code exists to bemuse the compiler's optimizer and force a
-// truncation to float-precision only:
-//
-template <class T>
-inline float test_data<T>::truncate_to_float(float const * pf)
-{
- BOOST_MATH_STD_USING
- int expon;
- float f = floor(ldexp(frexp(*pf, &expon), 22));
- f = ldexp(f, expon - 22);
- return f;
-
- //extern_val = *pf;
- //return *pf;
-}
-
-template <class T>
-float test_data<T>::extern_val = 0;
-
-template <class T>
-void test_data<T>::create_test_points(std::set<T>& points, const parameter_info<T>& arg1)
-{
- BOOST_MATH_STD_USING
- //
- // Generate a set of test points as requested, try and generate points
- // at only float precision: otherwise when testing float versions of functions
- // there will be a rounding error in our input values which throws off the results
- // (Garbage in garbage out etc).
- //
- switch(arg1.type & 0x7F)
- {
- case random_in_range:
- {
- BOOST_ASSERT(arg1.z1 < arg1.z2);
- BOOST_ASSERT(arg1.n1 > 0);
- typedef float random_type;
-
- std::tr1::mt19937 rnd;
- std::tr1::uniform_real<random_type> ur_a(real_cast<random_type>(arg1.z1), real_cast<random_type>(arg1.z2));
- std::tr1::variate_generator<std::tr1::mt19937, std::tr1::uniform_real<random_type> > gen(rnd, ur_a);
-
- for(int i = 0; i < arg1.n1; ++i)
- {
- random_type r = gen();
- points.insert(truncate_to_float(r));
- }
- }
- break;
- case periodic_in_range:
- {
- BOOST_ASSERT(arg1.z1 < arg1.z2);
- BOOST_ASSERT(arg1.n1 > 0);
- float interval = real_cast<float>((arg1.z2 - arg1.z1) / arg1.n1);
- T val = arg1.z1;
- while(val < arg1.z2)
- {
- points.insert(truncate_to_float(real_cast<float>(val)));
- val += interval;
- }
- }
- break;
- case power_series:
- {
- BOOST_ASSERT(arg1.n1 < arg1.n2);
-
- typedef float random_type;
- typedef typename boost::mpl::if_<
- ::boost::is_floating_point<T>,
- T, long double>::type power_type;
-
- std::tr1::mt19937 rnd;
- std::tr1::uniform_real<random_type> ur_a(1.0, 2.0);
- std::tr1::variate_generator<std::tr1::mt19937, std::tr1::uniform_real<random_type> > gen(rnd, ur_a);
-
- for(int power = arg1.n1; power <= arg1.n2; ++power)
- {
- random_type r = gen();
- power_type p = ldexp(static_cast<power_type>(r), power);
- points.insert(truncate_to_float(real_cast<float>(arg1.z1 + p)));
- }
- }
- break;
- default:
- BOOST_ASSERT(0 == "Invalid parameter_info object");
- // Assert will fail if get here.
- // Triggers warning 4130) // '==' : logical operation on address of string constant.
- }
-}
-
-//
-// Prompt a user for information on a parameter range:
-//
-template <class T>
-bool get_user_parameter_info(parameter_info<T>& info, const char* param_name)
-{
-#ifdef BOOST_MSVC
-# pragma warning(push)
-# pragma warning(disable: 4127)
-#endif
- std::string line;
- do{
- std::cout << "What kind of distribution do you require for parameter " << param_name << "?\n"
- "Choices are:\n"
- " r Random values in a half open range\n"
- " p Evenly spaced periodic values in a half open range\n"
- " e Exponential power series at a particular point: a + 2^b for some range of b\n"
- "[Default=r]";
-
- std::getline(std::cin, line);
- boost::algorithm::trim(line);
-
- if(line == "r")
- {
- info.type = random_in_range;
- break;
- }
- else if(line == "p")
- {
- info.type = periodic_in_range;
- break;
- }
- else if(line == "e")
- {
- info.type = power_series;
- break;
- }
- else if(line == "")
- {
- info.type = random_in_range;
- break;
- }
- //
- // Ooops, not a valid input....
- //
- std::cout << "Sorry don't recognise \"" << line << "\" as a valid input\n"
- "do you want to try again [y/n]?";
- std::getline(std::cin, line);
- boost::algorithm::trim(line);
- if(line == "n")
- return false;
- else if(line == "y")
- continue;
- std::cout << "Sorry don't recognise that either, giving up...\n\n";
- return false;
- }while(true);
-
- switch(info.type & ~dummy_param)
- {
- case random_in_range:
- case periodic_in_range:
- // get start and end points of range:
- do{
- std::cout << "Data will be in the half open range a <= x < b,\n"
- "enter value for the start point fo the range [default=0]:";
- std::getline(std::cin, line);
- boost::algorithm::trim(line);
- if(line == "")
- {
- info.z1 = 0;
- break;
- }
- try{
- info.z1 = boost::lexical_cast<T>(line);
- break;
- }
- catch(const boost::bad_lexical_cast&)
- {
- std::cout << "Sorry, that was not valid input, try again [y/n]?";
- std::getline(std::cin, line);
- boost::algorithm::trim(line);
- if(line == "y")
- continue;
- if(line == "n")
- return false;
- std::cout << "Sorry don't recognise that either, giving up...\n\n";
- return false;
- }
- }while(true);
- do{
- std::cout << "Enter value for the end point fo the range [default=1]:";
- std::getline(std::cin, line);
- boost::algorithm::trim(line);
- if(line == "")
- {
- info.z2 = 1;
- }
- else
- {
- try
- {
- info.z2 = boost::lexical_cast<T>(line);
- }
- catch(const boost::bad_lexical_cast&)
- {
- std::cout << "Sorry, that was not valid input, try again [y/n]?";
- std::getline(std::cin, line);
- boost::algorithm::trim(line);
- if(line == "y")
- continue;
- if(line == "n")
- return false;
- std::cout << "Sorry don't recognise that either, giving up...\n\n";
- return false;
- }
- }
- if(info.z1 >= info.z2)
- {
- std::cout << "The end point of the range was <= the start point\n"
- "try a different value for the endpoint [y/n]?";
- std::getline(std::cin, line);
- boost::algorithm::trim(line);
- if(line == "y")
- continue;
- if(line == "n")
- return false;
- std::cout << "Sorry don't recognise that either, giving up...\n\n";
- return false;
- }
- break;
- }while(true);
- do{
- // get the number of points:
- std::cout << "How many data points do you want?";
- std::getline(std::cin, line);
- boost::algorithm::trim(line);
- try{
- info.n1 = boost::lexical_cast<int>(line);
- info.n2 = 0;
- if(info.n1 <= 0)
- {
- std::cout << "The number of points should be > 0\n"
- "try again [y/n]?";
- std::getline(std::cin, line);
- boost::algorithm::trim(line);
- if(line == "y")
- continue;
- if(line == "n")
- return false;
- std::cout << "Sorry don't recognise that either, giving up...\n\n";
- return false;
- }
- break;
- }
- catch(const boost::bad_lexical_cast&)
- {
- std::cout << "Sorry, that was not valid input, try again [y/n]?";
- std::getline(std::cin, line);
- boost::algorithm::trim(line);
- if(line == "y")
- continue;
- if(line == "n")
- return false;
- std::cout << "Sorry don't recognise that either, giving up...\n\n";
- return false;
- }
- }while(true);
- break;
- case power_series:
- // get start and end points of range:
- info.z2 = 0;
- do{
- std::cout << "Data will be in the form a + r*2^b\n"
- "for random value r,\n"
- "enter value for the point a [default=0]:";
- std::getline(std::cin, line);
- boost::algorithm::trim(line);
- if(line == "")
- {
- info.z1 = 0;
- break;
- }
- try{
- info.z1 = boost::lexical_cast<T>(line);
- break;
- }
- catch(const boost::bad_lexical_cast&)
- {
- std::cout << "Sorry, that was not valid input, try again [y/n]?";
- std::getline(std::cin, line);
- boost::algorithm::trim(line);
- if(line == "y")
- continue;
- if(line == "n")
- return false;
- std::cout << "Sorry don't recognise that either, giving up...\n\n";
- return false;
- }
- }while(true);
-
- do{
- std::cout << "Data will be in the form a + r*2^b\n"
- "for random value r,\n"
- "enter value for the starting exponent b:";
- std::getline(std::cin, line);
- boost::algorithm::trim(line);
- try{
- info.n1 = boost::lexical_cast<int>(line);
- break;
- }
- catch(const boost::bad_lexical_cast&)
- {
- std::cout << "Sorry, that was not valid input, try again [y/n]?";
- std::getline(std::cin, line);
- boost::algorithm::trim(line);
- if(line == "y")
- continue;
- if(line == "n")
- return false;
- std::cout << "Sorry don't recognise that either, giving up...\n\n";
- return false;
- }
- }while(true);
-
- do{
- std::cout << "Data will be in the form a + r*2^b\n"
- "for random value r,\n"
- "enter value for the ending exponent b:";
- std::getline(std::cin, line);
- boost::algorithm::trim(line);
- try{
- info.n2 = boost::lexical_cast<int>(line);
- break;
- }
- catch(const boost::bad_lexical_cast&)
- {
- std::cout << "Sorry, that was not valid input, try again [y/n]?";
- std::getline(std::cin, line);
- boost::algorithm::trim(line);
- if(line == "y")
- continue;
- if(line == "n")
- return false;
- std::cout << "Sorry don't recognise that either, giving up...\n\n";
- return false;
- }
- }while(true);
-
- break;
- default:
- BOOST_ASSERT(0); // should never get here!!
- }
-
- return true;
-#ifdef BOOST_MSVC
-# pragma warning(pop)
-#endif
-}
-
-template <class charT, class traits, class T>
-inline std::basic_ostream<charT, traits>& write_csv(std::basic_ostream<charT, traits>& os,
- const test_data<T>& data)
-{
- const charT defarg[] = { ',', ' ', '\0' };
- return write_csv(os, data, defarg);
-}
-
-template <class charT, class traits, class T>
-std::basic_ostream<charT, traits>& write_csv(std::basic_ostream<charT, traits>& os,
- const test_data<T>& data,
- const charT* separator)
-{
- typedef typename test_data<T>::const_iterator it_type;
- typedef typename test_data<T>::value_type value_type;
- typedef typename value_type::const_iterator value_type_iterator;
- it_type a, b;
- a = data.begin();
- b = data.end();
- while(a != b)
- {
- value_type_iterator x, y;
- bool sep = false;
- x = a->begin();
- y = a->end();
- while(x != y)
- {
- if(sep)
- os << separator;
- os << *x;
- sep = true;
- ++x;
- }
- os << std::endl;
- ++a;
- }
- return os;
-}
-
-template <class T>
-std::ostream& write_code(std::ostream& os,
- const test_data<T>& data,
- const char* name)
-{
- typedef typename test_data<T>::const_iterator it_type;
- typedef typename test_data<T>::value_type value_type;
- typedef typename value_type::const_iterator value_type_iterator;
-
- BOOST_ASSERT(os.good());
-
- it_type a, b;
- a = data.begin();
- b = data.end();
- if(a == b)
- return os;
-
- os << "#ifndef SC_\n# define SC_(x) static_cast<T>(BOOST_JOIN(x, L))\n#endif\n"
- " static const boost::array<boost::array<T, "
- << a->size() << ">, " << data.size() << "> " << name << " = {{\n";
-
- while(a != b)
- {
- if(a != data.begin())
- os << ", \n";
-
- value_type_iterator x, y;
- x = a->begin();
- y = a->end();
- os << " { ";
- while(x != y)
- {
- if(x != a->begin())
- os << ", ";
- os << "SC_(" << *x << ")";
- ++x;
- }
- os << " }";
- ++a;
- }
- os << "\n }};\n//#undef SC_\n\n";
- return os;
-}
-
-} // namespace tools
-} // namespace math
-} // namespace boost
-
-#ifdef BOOST_MSVC
-#pragma warning(pop)
-#endif
-
-
-#endif // BOOST_MATH_TOOLS_TEST_DATA_HPP
-
-
diff --git a/boost/math/tools/toms748_solve.hpp b/boost/math/tools/toms748_solve.hpp
index f0c42324e8..48737a821a 100644
--- a/boost/math/tools/toms748_solve.hpp
+++ b/boost/math/tools/toms748_solve.hpp
@@ -17,6 +17,14 @@
#include <boost/cstdint.hpp>
#include <limits>
+#ifdef BOOST_MATH_LOG_ROOT_ITERATIONS
+# define BOOST_MATH_LOGGER_INCLUDE <boost/math/tools/iteration_logger.hpp>
+# include BOOST_MATH_LOGGER_INCLUDE
+# undef BOOST_MATH_LOGGER_INCLUDE
+#else
+# define BOOST_MATH_LOG_COUNT(count)
+#endif
+
namespace boost{ namespace math{ namespace tools{
template <class T>
@@ -197,7 +205,7 @@ T quadratic_interpolate(const T& a, const T& b, T const& d,
T A = safe_div(T(fd - fb), T(d - b), tools::max_value<T>());
A = safe_div(T(A - B), T(d - a), T(0));
- if(a == 0)
+ if(A == 0)
{
// failure to determine coefficients, try a secant step:
return secant_interpolate(a, b, fa, fb);
@@ -298,9 +306,9 @@ std::pair<T, T> toms748_solve(F f, const T& ax, const T& bx, const T& fax, const
a = ax;
b = bx;
if(a >= b)
- policies::raise_domain_error(
+ return boost::math::detail::pair_from_single(policies::raise_domain_error(
function,
- "Parameters a and b out of order: a=%1%", a, pol);
+ "Parameters a and b out of order: a=%1%", a, pol));
fa = fax;
fb = fbx;
@@ -315,9 +323,9 @@ std::pair<T, T> toms748_solve(F f, const T& ax, const T& bx, const T& fax, const
}
if(boost::math::sign(fa) * boost::math::sign(fb) > 0)
- policies::raise_domain_error(
+ return boost::math::detail::pair_from_single(policies::raise_domain_error(
function,
- "Parameters a and b do not bracket the root: a=%1%", a, pol);
+ "Parameters a and b do not bracket the root: a=%1%", a, pol));
// dummy value for fd, e and fe:
fe = e = fd = 1e5F;
@@ -452,6 +460,7 @@ std::pair<T, T> toms748_solve(F f, const T& ax, const T& bx, const T& fax, const
{
a = b;
}
+ BOOST_MATH_LOG_COUNT(max_iter)
return std::make_pair(a, b);
}
@@ -493,6 +502,8 @@ std::pair<T, T> bracket_and_solve_root(F f, const T& guess, T factor, bool risin
//
boost::uintmax_t count = max_iter - 1;
+ int step = 32;
+
if((fa < 0) == (guess < 0 ? !rising : rising))
{
//
@@ -502,13 +513,19 @@ std::pair<T, T> bracket_and_solve_root(F f, const T& guess, T factor, bool risin
while((boost::math::sign)(fb) == (boost::math::sign)(fa))
{
if(count == 0)
- policies::raise_evaluation_error(function, "Unable to bracket root, last nearest value was %1%", b, pol);
+ return boost::math::detail::pair_from_single(policies::raise_evaluation_error(function, "Unable to bracket root, last nearest value was %1%", b, pol));
//
- // Heuristic: every 20 iterations we double the growth factor in case the
- // initial guess was *really* bad !
+ // Heuristic: normally it's best not to increase the step sizes as we'll just end up
+ // with a really wide range to search for the root. However, if the initial guess was *really*
+ // bad then we need to speed up the search otherwise we'll take forever if we're orders of
+ // magnitude out. This happens most often if the guess is a small value (say 1) and the result
+ // we're looking for is close to std::numeric_limits<T>::min().
//
- if((max_iter - count) % 20 == 0)
+ if((max_iter - count) % step == 0)
+ {
factor *= 2;
+ if(step > 1) step /= 2;
+ }
//
// Now go ahead and move our guess by "factor":
//
@@ -536,13 +553,19 @@ std::pair<T, T> bracket_and_solve_root(F f, const T& guess, T factor, bool risin
return a > 0 ? std::make_pair(T(0), T(a)) : std::make_pair(T(a), T(0));
}
if(count == 0)
- policies::raise_evaluation_error(function, "Unable to bracket root, last nearest value was %1%", a, pol);
+ return boost::math::detail::pair_from_single(policies::raise_evaluation_error(function, "Unable to bracket root, last nearest value was %1%", a, pol));
//
- // Heuristic: every 20 iterations we double the growth factor in case the
- // initial guess was *really* bad !
+ // Heuristic: normally it's best not to increase the step sizes as we'll just end up
+ // with a really wide range to search for the root. However, if the initial guess was *really*
+ // bad then we need to speed up the search otherwise we'll take forever if we're orders of
+ // magnitude out. This happens most often if the guess is a small value (say 1) and the result
+ // we're looking for is close to std::numeric_limits<T>::min().
//
- if((max_iter - count) % 20 == 0)
+ if((max_iter - count) % step == 0)
+ {
factor *= 2;
+ if(step > 1) step /= 2;
+ }
//
// Now go ahead and move are guess by "factor":
//
@@ -567,6 +590,7 @@ std::pair<T, T> bracket_and_solve_root(F f, const T& guess, T factor, bool risin
pol);
max_iter += count;
BOOST_MATH_INSTRUMENT_CODE("max_iter = " << max_iter << " count = " << count);
+ BOOST_MATH_LOG_COUNT(max_iter)
return r;
}
diff --git a/boost/math/tools/tuple.hpp b/boost/math/tools/tuple.hpp
index 2f297360a2..0ae778cbef 100644
--- a/boost/math/tools/tuple.hpp
+++ b/boost/math/tools/tuple.hpp
@@ -7,8 +7,6 @@
# define BOOST_MATH_TUPLE_HPP_INCLUDED
# include <boost/config.hpp>
-#include <boost/tr1/detail/config.hpp> // for BOOST_HAS_TR1_TUPLE
-
#ifndef BOOST_NO_CXX11_HDR_TUPLE
#include <tuple>
@@ -29,27 +27,7 @@ using ::std::tuple_element;
}}
-#elif defined(BOOST_HAS_TR1_TUPLE)
-
-#include <boost/tr1/tuple.hpp>
-
-namespace boost{ namespace math{
-
-using ::std::tr1::tuple;
-
-// [6.1.3.2] Tuple creation functions
-using ::std::tr1::ignore;
-using ::std::tr1::make_tuple;
-using ::std::tr1::tie;
-using ::std::tr1::get;
-
-// [6.1.3.3] Tuple helper classes
-using ::std::tr1::tuple_size;
-using ::std::tr1::tuple_element;
-
-}}
-
-#elif (defined(__BORLANDC__) && (__BORLANDC__ <= 0x600)) || (defined(_MSC_VER) && (_MSC_VER < 1310)) || defined(__IBMCPP__)
+#elif (defined(__BORLANDC__) && (__BORLANDC__ <= 0x600)) || defined(__IBMCPP__)
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_comparison.hpp>
diff --git a/boost/math/tools/user.hpp b/boost/math/tools/user.hpp
index c1bdaf7d87..08a7e53d9e 100644
--- a/boost/math/tools/user.hpp
+++ b/boost/math/tools/user.hpp
@@ -91,6 +91,14 @@
// Maximum root finding steps permitted:
//
// define BOOST_MATH_MAX_ROOT_ITERATION_POLICY 200
+//
+// Enable use of __float128 in numeric constants:
+//
+// #define BOOST_MATH_USE_FLOAT128
+//
+// Disable use of __float128 in numeric_constants even if the compiler looks to support it:
+//
+// #define BOOST_MATH_DISABLE_FLOAT128
#endif // BOOST_MATH_TOOLS_USER_HPP
diff --git a/boost/math/tr1_c_macros.ipp b/boost/math/tr1_c_macros.ipp
index c173639af5..ec8e7da3ef 100644
--- a/boost/math/tr1_c_macros.ipp
+++ b/boost/math/tr1_c_macros.ipp
@@ -807,4 +807,4 @@
#endif
#define sph_neumannl boost_sph_neumannl
-#endif // BOOST_MATH_C_MACROS_IPP \ No newline at end of file
+#endif // BOOST_MATH_C_MACROS_IPP