update boost

This commit is contained in:
2023-11-24 12:56:13 -06:00
parent cfc99971af
commit 19d727037a
9260 changed files with 849256 additions and 299957 deletions

View File

@@ -29,6 +29,7 @@
#ifndef BOOST_MATH_DIST_ARCSINE_HPP
#define BOOST_MATH_DIST_ARCSINE_HPP
#include <cmath>
#include <boost/math/distributions/fwd.hpp>
#include <boost/math/distributions/complement.hpp> // complements.
#include <boost/math/distributions/detail/common_error_handling.hpp> // error checks.
@@ -85,15 +86,14 @@ namespace boost
{ // Check x_min < x_max
if (x_min >= x_max)
{
std::string msg = "x_max argument is %1%, but must be > x_min = " + lexical_cast<std::string>(x_min) + "!";
std::string msg = "x_max argument is %1%, but must be > x_min";
*result = policies::raise_domain_error<RealType>(
function,
msg.c_str(), x_max, pol);
// "x_max argument is %1%, but must be > x_min !", x_max, pol);
// "x_max argument is %1%, but must be > x_min %2!", x_max, x_min, pol); would be better.
// But would require replication of all helpers functions in /policies/error_handling.hpp for two values,
// as well as two value versions of raise_error, raise_domain_error and do_format ...
// so use slightly hacky lexical_cast to string instead.
// "x_max argument is %1%, but must be > x_min !", x_max, pol);
// "x_max argument is %1%, but must be > x_min %2!", x_max, x_min, pol); would be better.
// But would require replication of all helpers functions in /policies/error_handling.hpp for two values,
// as well as two value versions of raise_error, raise_domain_error and do_format
return false;
}
return true;
@@ -195,6 +195,12 @@ namespace boost
// Convenient typedef to construct double version.
typedef arcsine_distribution<double> arcsine;
#ifdef __cpp_deduction_guides
template <class RealType>
arcsine_distribution(RealType)->arcsine_distribution<typename boost::math::tools::promote_args<RealType>::type>;
template <class RealType>
arcsine_distribution(RealType, RealType)->arcsine_distribution<typename boost::math::tools::promote_args<RealType>::type>;
#endif
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const arcsine_distribution<RealType, Policy>& dist)
@@ -428,7 +434,7 @@ namespace boost
// is less accurate, so use acos instead of asin for complement.
result = static_cast<RealType>(2) * acos(sqrt((x - x_min) / (x_max - x_min))) / pi<RealType>();
return result;
} // arcine ccdf
} // arcsine ccdf
template <class RealType, class Policy>
inline RealType quantile(const arcsine_distribution<RealType, Policy>& dist, const RealType& p)

View File

@@ -19,7 +19,7 @@
// (like others including the poisson, binomial & negative binomial)
// is strictly defined as a discrete function: only integral values of k are envisaged.
// However because of the method of calculation using a continuous gamma function,
// it is convenient to treat it as if a continous function,
// it is convenient to treat it as if a continuous function,
// and permit non-integral values of k.
// To enforce the strict mathematical model, users should use floor or ceil functions
// on k outside this function to ensure that k is integral.
@@ -55,12 +55,12 @@ namespace boost
return true;
}
template <class RealType, class Policy>
inline bool check_dist(const char* function, const RealType& p, RealType* result, const Policy& /* pol */, const mpl::true_&)
inline bool check_dist(const char* function, const RealType& p, RealType* result, const Policy& /* pol */, const std::true_type&)
{
return check_success_fraction(function, p, result, Policy());
}
template <class RealType, class Policy>
inline bool check_dist(const char* , const RealType& , RealType* , const Policy& /* pol */, const mpl::false_&)
inline bool check_dist(const char* , const RealType& , RealType* , const Policy& /* pol */, const std::false_type&)
{
return true;
}
@@ -126,6 +126,11 @@ namespace boost
typedef bernoulli_distribution<double> bernoulli;
#ifdef __cpp_deduction_guides
template <class RealType>
bernoulli_distribution(RealType)->bernoulli_distribution<typename boost::math::tools::promote_args<RealType>::type>;
#endif
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const bernoulli_distribution<RealType, Policy>& /* dist */)
{ // Range of permissible values for random variable k = {0, 1}.
@@ -146,7 +151,7 @@ namespace boost
return dist.success_fraction();
} // mean
// Rely on dereived_accessors quantile(half)
// Rely on derived_accessors quantile(half)
//template <class RealType>
//inline RealType median(const bernoulli_distribution<RealType, Policy>& dist)
//{ // Median of bernoulli distribution is not defined.

View File

@@ -2,6 +2,7 @@
// Copyright John Maddock 2006.
// Copyright Paul A. Bristow 2006.
// Copyright Matt Borland 2023.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
@@ -241,7 +242,7 @@ namespace boost
{
return result;
}
return ibeta_inva(beta, x, probability, Policy());
return static_cast<RealType>(ibeta_inva(beta, x, probability, Policy()));
} // RealType find_alpha(beta, a, probability)
static RealType find_beta(
@@ -264,7 +265,7 @@ namespace boost
{
return result;
}
return ibeta_invb(alpha, x, probability, Policy());
return static_cast<RealType>(ibeta_invb(alpha, x, probability, Policy()));
} // RealType find_beta(alpha, x, probability)
private:
@@ -272,6 +273,13 @@ namespace boost
RealType m_beta;
}; // template <class RealType, class Policy> class beta_distribution
#ifdef __cpp_deduction_guides
template <class RealType>
beta_distribution(RealType)->beta_distribution<typename boost::math::tools::promote_args<RealType>::type>;
template <class RealType>
beta_distribution(RealType, RealType)->beta_distribution<typename boost::math::tools::promote_args<RealType>::type>;
#endif
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const beta_distribution<RealType, Policy>& /* dist */)
{ // Range of permissible values for random variable x.
@@ -382,7 +390,41 @@ namespace boost
return result;
}
using boost::math::beta;
return ibeta_derivative(a, b, x, Policy());
// Corner cases: check_x ensures x element of [0, 1], but PDF is 0 for x = 0 and x = 1. PDF EQN:
// https://wikimedia.org/api/rest_v1/media/math/render/svg/125fdaa41844a8703d1a8610ac00fbf3edacc8e7
if(x == 0)
{
if (a == 1)
{
return static_cast<RealType>(1 / beta(a, b));
}
else if (a < 1)
{
policies::raise_overflow_error<RealType>(function, nullptr, Policy());
}
else
{
return RealType(0);
}
}
else if (x == 1)
{
if (b == 1)
{
return static_cast<RealType>(1 / beta(a, b));
}
else if (b < 1)
{
policies::raise_overflow_error<RealType>(function, nullptr, Policy());
}
else
{
return RealType(0);
}
}
return static_cast<RealType>(ibeta_derivative(a, b, x, Policy()));
} // pdf
template <class RealType, class Policy>
@@ -413,7 +455,7 @@ namespace boost
{
return 1;
}
return ibeta(a, b, x, Policy());
return static_cast<RealType>(ibeta(a, b, x, Policy()));
} // beta cdf
template <class RealType, class Policy>
@@ -440,16 +482,16 @@ namespace boost
}
if (x == 0)
{
return 1;
return RealType(1);
}
else if (x == 1)
{
return 0;
return RealType(0);
}
// Calculate cdf beta using the incomplete beta function.
// Use of ibeta here prevents cancellation errors in calculating
// 1 - x if x is very small, perhaps smaller than machine epsilon.
return ibetac(a, b, x, Policy());
return static_cast<RealType>(ibetac(a, b, x, Policy()));
} // beta cdf
template <class RealType, class Policy>
@@ -478,13 +520,13 @@ namespace boost
// Special cases:
if (p == 0)
{
return 0;
return RealType(0);
}
if (p == 1)
{
return 1;
return RealType(1);
}
return ibeta_inv(a, b, p, static_cast<RealType*>(0), Policy());
return static_cast<RealType>(ibeta_inv(a, b, p, static_cast<RealType*>(nullptr), Policy()));
} // quantile
template <class RealType, class Policy>
@@ -514,14 +556,14 @@ namespace boost
// Special cases:
if(q == 1)
{
return 0;
return RealType(0);
}
if(q == 0)
{
return 1;
return RealType(1);
}
return ibetac_inv(a, b, q, static_cast<RealType*>(0), Policy());
return static_cast<RealType>(ibetac_inv(a, b, q, static_cast<RealType*>(nullptr), Policy()));
} // Quantile Complement
} // namespace math

View File

@@ -71,7 +71,7 @@
// (like others including the poisson, negative binomial & Bernoulli)
// is strictly defined as a discrete function: only integral values of k are envisaged.
// However because of the method of calculation using a continuous gamma function,
// it is convenient to treat it as if a continous function,
// it is convenient to treat it as if a continuous function,
// and permit non-integral values of k.
// To enforce the strict mathematical model, users should use floor or ceil functions
// on k outside this function to ensure that k is integral.
@@ -224,7 +224,7 @@ namespace boost
// but zero is the best we can do:
return 0;
}
if(p == 1)
if(p == 1 || success_fraction == 1)
{ // Probability of n or fewer successes is always one,
// so n is the most sensible answer here:
return trials;
@@ -233,10 +233,6 @@ namespace boost
{ // p <= pdf(dist, 0) == cdf(dist, 0)
return 0; // So the only reasonable result is zero.
} // And root finder would fail otherwise.
if(success_fraction == 1)
{ // our formulae break down in this case:
return p > 0.5f ? trials : 0;
}
// Solve for quantile numerically:
//
@@ -261,7 +257,7 @@ namespace boost
factor = 2; // trials largish, but in far tails.
typedef typename Policy::discrete_quantile_type discrete_quantile_type;
boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
std::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
return detail::inverse_discrete_quantile(
dist,
comp ? q : p,
@@ -335,8 +331,8 @@ namespace boost
// NOTE!!! The Clopper Pearson formula uses "successes" not
// "successes+1" as usual to get the lower bound,
// see http://www.itl.nist.gov/div898/handbook/prc/section2/prc241.htm
return (t == clopper_pearson_exact_interval) ? ibeta_inv(successes, trials - successes + 1, probability, static_cast<RealType*>(0), Policy())
: ibeta_inv(successes + 0.5f, trials - successes + 0.5f, probability, static_cast<RealType*>(0), Policy());
return (t == clopper_pearson_exact_interval) ? ibeta_inv(successes, trials - successes + 1, probability, static_cast<RealType*>(nullptr), Policy())
: ibeta_inv(successes + 0.5f, trials - successes + 0.5f, probability, static_cast<RealType*>(nullptr), Policy());
}
static RealType find_upper_bound_on_p(
RealType trials,
@@ -357,8 +353,8 @@ namespace boost
if(trials == successes)
return 1;
return (t == clopper_pearson_exact_interval) ? ibetac_inv(successes + 1, trials - successes, probability, static_cast<RealType*>(0), Policy())
: ibetac_inv(successes + 0.5f, trials - successes + 0.5f, probability, static_cast<RealType*>(0), Policy());
return (t == clopper_pearson_exact_interval) ? ibetac_inv(successes + 1, trials - successes, probability, static_cast<RealType*>(nullptr), Policy())
: ibetac_inv(successes + 0.5f, trials - successes + 0.5f, probability, static_cast<RealType*>(nullptr), Policy());
}
// Estimate number of trials parameter:
//
@@ -414,6 +410,13 @@ namespace boost
// IS now included since no longer a name clash with function binomial.
//typedef binomial_distribution<double> binomial; // Reserved name of type double.
#ifdef __cpp_deduction_guides
template <class RealType>
binomial_distribution(RealType)->binomial_distribution<typename boost::math::tools::promote_args<RealType>::type>;
template <class RealType>
binomial_distribution(RealType,RealType)->binomial_distribution<typename boost::math::tools::promote_args<RealType>::type>;
#endif
template <class RealType, class Policy>
const std::pair<RealType, RealType> range(const binomial_distribution<RealType, Policy>& dist)
{ // Range of permissible values for random variable k.
@@ -476,11 +479,6 @@ namespace boost
{
return 1; // Probability = 1 = certainty.
}
if (k == 0)
{ // binomial coeffic (n 0) = 1,
// n ^ 0 = 1
return pow(1 - dist.success_fraction(), n);
}
if (k == n)
{ // binomial coeffic (n n) = 1,
// n ^ 0 = 1
@@ -679,7 +677,7 @@ namespace boost
// Metrika (Metrika) ISSN 0026-1335 CODEN MTRKA8
// 1993, vol. 40, no3-4, pp. 185-189 (4 ref.)
// Bounds for median and 50 percetage point of binomial and negative binomial distribution
// Bounds for median and 50 percentage point of binomial and negative binomial distribution
// Metrika, ISSN 0026-1335 (Print) 1435-926X (Online)
// Volume 41, Number 1 / December, 1994, DOI 10.1007/BF01895303
BOOST_MATH_STD_USING // ADL of std functions.

View File

@@ -17,9 +17,8 @@
#include <boost/math/constants/constants.hpp>
#include <boost/math/distributions/complement.hpp>
#include <boost/math/distributions/detail/common_error_handling.hpp>
#include <boost/config/no_tr1/cmath.hpp>
#include <utility>
#include <cmath>
namespace boost{ namespace math
{
@@ -50,7 +49,7 @@ RealType cdf_imp(const cauchy_distribution<RealType, Policy>& dist, const RealTy
//
// CDF = -atan(1/x) ; x < 0
//
// So the proceedure is to calculate the cdf for -fabs(x)
// So the procedure is to calculate the cdf for -fabs(x)
// using the above formula, and then subtract from 1 when required
// to get the result.
//
@@ -82,7 +81,7 @@ RealType cdf_imp(const cauchy_distribution<RealType, Policy>& dist, const RealTy
RealType mx = -fabs((x - location) / scale); // scale is > 0
if(mx > -tools::epsilon<RealType>() / 8)
{ // special case first: x extremely close to location.
return 0.5;
return static_cast<RealType>(0.5f);
}
result = -atan(1 / mx) / constants::pi<RealType>();
return (((x > location) != complement) ? 1 - result : result);
@@ -98,7 +97,7 @@ RealType quantile_imp(
// the value p may be the probability, or its complement if complement=true.
//
// The procedure first performs argument reduction on p to avoid error
// when calculating the tangent, then calulates the distance from the
// when calculating the tangent, then calculates the distance from the
// mid-point of the distribution. This is either added or subtracted
// from the location parameter depending on whether `complement` is true.
//
@@ -177,6 +176,13 @@ private:
typedef cauchy_distribution<double> cauchy;
#ifdef __cpp_deduction_guides
template <class RealType>
cauchy_distribution(RealType)->cauchy_distribution<typename boost::math::tools::promote_args<RealType>::type>;
template <class RealType>
cauchy_distribution(RealType,RealType)->cauchy_distribution<typename boost::math::tools::promote_args<RealType>::type>;
#endif
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.
@@ -271,7 +277,7 @@ template <class RealType, class Policy>
inline RealType mean(const cauchy_distribution<RealType, Policy>&)
{ // There is no mean:
typedef typename Policy::assert_undefined_type assert_type;
BOOST_STATIC_ASSERT(assert_type::value == 0);
static_assert(assert_type::value == 0, "assert type is undefined");
return policies::raise_domain_error<RealType>(
"boost::math::mean(cauchy<%1%>&)",
@@ -285,7 +291,7 @@ inline RealType variance(const cauchy_distribution<RealType, Policy>& /*dist*/)
{
// There is no variance:
typedef typename Policy::assert_undefined_type assert_type;
BOOST_STATIC_ASSERT(assert_type::value == 0);
static_assert(assert_type::value == 0, "assert type is undefined");
return policies::raise_domain_error<RealType>(
"boost::math::variance(cauchy<%1%>&)",
@@ -310,7 +316,7 @@ inline RealType skewness(const cauchy_distribution<RealType, Policy>& /*dist*/)
{
// There is no skewness:
typedef typename Policy::assert_undefined_type assert_type;
BOOST_STATIC_ASSERT(assert_type::value == 0);
static_assert(assert_type::value == 0, "assert type is undefined");
return policies::raise_domain_error<RealType>(
"boost::math::skewness(cauchy<%1%>&)",
@@ -324,7 +330,7 @@ inline RealType kurtosis(const cauchy_distribution<RealType, Policy>& /*dist*/)
{
// There is no kurtosis:
typedef typename Policy::assert_undefined_type assert_type;
BOOST_STATIC_ASSERT(assert_type::value == 0);
static_assert(assert_type::value == 0, "assert type is undefined");
return policies::raise_domain_error<RealType>(
"boost::math::kurtosis(cauchy<%1%>&)",
@@ -338,7 +344,7 @@ inline RealType kurtosis_excess(const cauchy_distribution<RealType, Policy>& /*d
{
// There is no kurtosis excess:
typedef typename Policy::assert_undefined_type assert_type;
BOOST_STATIC_ASSERT(assert_type::value == 0);
static_assert(assert_type::value == 0, "assert type is undefined");
return policies::raise_domain_error<RealType>(
"boost::math::kurtosis_excess(cauchy<%1%>&)",
@@ -347,6 +353,13 @@ inline RealType kurtosis_excess(const cauchy_distribution<RealType, Policy>& /*d
std::numeric_limits<RealType>::quiet_NaN(), Policy());
}
template <class RealType, class Policy>
inline RealType entropy(const cauchy_distribution<RealType, Policy> & dist)
{
using std::log;
return log(2*constants::two_pi<RealType>()*dist.scale());
}
} // namespace math
} // namespace boost

View File

@@ -23,10 +23,10 @@ template <class RealType = double, class Policy = policies::policy<> >
class chi_squared_distribution
{
public:
typedef RealType value_type;
typedef Policy policy_type;
using value_type = RealType;
using policy_type = Policy;
chi_squared_distribution(RealType i) : m_df(i)
explicit chi_squared_distribution(RealType i) : m_df(i)
{
RealType result;
detail::check_df(
@@ -53,15 +53,20 @@ private:
RealType m_df; // degrees of freedom is a positive real number.
}; // class chi_squared_distribution
typedef chi_squared_distribution<double> chi_squared;
using chi_squared = chi_squared_distribution<double>;
#ifdef BOOST_MSVC
#ifdef __cpp_deduction_guides
template <class RealType>
chi_squared_distribution(RealType)->chi_squared_distribution<typename boost::math::tools::promote_args<RealType>::type>;
#endif
#ifdef _MSC_VER
#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*/)
inline std::pair<RealType, RealType> range(const chi_squared_distribution<RealType, Policy>& /*dist*/)
{ // Range of permissible values for random variable x.
if (std::numeric_limits<RealType>::has_infinity)
{
@@ -74,12 +79,12 @@ inline const std::pair<RealType, RealType> range(const chi_squared_distribution<
}
}
#ifdef BOOST_MSVC
#ifdef _MSC_VER
#pragma warning(pop)
#endif
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> support(const chi_squared_distribution<RealType, Policy>& /*dist*/)
inline std::pair<RealType, RealType> support(const chi_squared_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.
return std::pair<RealType, RealType>(static_cast<RealType>(0), tools::max_value<RealType>()); // 0 to + infinity.
@@ -219,17 +224,6 @@ inline RealType mode(const chi_squared_distribution<RealType, Policy>& dist)
{
RealType df = dist.degrees_of_freedom();
static const char* function = "boost::math::mode(const chi_squared_distribution<%1%>&)";
// Most sources only define mode for df >= 2,
// but for 0 <= df <= 2, the pdf maximum actually occurs at random variate = 0;
// So one could extend the definition of mode thus:
//if(df < 0)
//{
// return policies::raise_domain_error<RealType>(
// function,
// "Chi-Squared distribution only has a mode for degrees of freedom >= 0, but got degrees of freedom = %1%.",
// df, Policy());
//}
//return (df <= 2) ? 0 : df - 2;
if(df < 2)
return policies::raise_domain_error<RealType>(
@@ -239,25 +233,12 @@ inline RealType mode(const chi_squared_distribution<RealType, Policy>& dist)
return df - 2;
}
//template <class RealType, class Policy>
//inline RealType median(const chi_squared_distribution<RealType, Policy>& dist)
//{ // Median is given by Quantile[dist, 1/2]
// RealType df = dist.degrees_of_freedom();
// if(df <= 1)
// return tools::domain_error<RealType>(
// BOOST_CURRENT_FUNCTION,
// "The Chi-Squared distribution only has a mode for degrees of freedom >= 2, but got degrees of freedom = %1%.",
// df);
// return df - RealType(2)/3;
//}
// Now implemented via quantile(half) in derived accessors.
template <class RealType, class Policy>
inline RealType skewness(const chi_squared_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING // For ADL
RealType df = dist.degrees_of_freedom();
return sqrt (8 / df); // == 2 * sqrt(2 / df);
return sqrt (8 / df);
}
template <class RealType, class Policy>
@@ -340,7 +321,7 @@ RealType chi_squared_distribution<RealType, Policy>::find_degrees_of_freedom(
detail::df_estimator<RealType, Policy> f(alpha, beta, variance, difference_from_variance);
tools::eps_tolerance<RealType> tol(policies::digits<RealType, Policy>());
boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
std::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
std::pair<RealType, RealType> r =
tools::bracket_and_solve_root(f, hint, RealType(2), false, tol, max_iter, Policy());
RealType result = r.first + (r.second - r.first) / 2;

View File

@@ -29,7 +29,7 @@ struct complemented2_type
const RealType& param;
private:
complemented2_type& operator=(const complemented2_type&);
complemented2_type& operator=(const complemented2_type&) = delete;
};
template <class Dist, class RealType1, class RealType2>
@@ -47,7 +47,7 @@ struct complemented3_type
const RealType1& param1;
const RealType2& param2;
private:
complemented3_type& operator=(const complemented3_type&);
complemented3_type& operator=(const complemented3_type&) = delete;
};
template <class Dist, class RealType1, class RealType2, class RealType3>
@@ -68,7 +68,7 @@ struct complemented4_type
const RealType2& param2;
const RealType3& param3;
private:
complemented4_type& operator=(const complemented4_type&);
complemented4_type& operator=(const complemented4_type&) = delete;
};
template <class Dist, class RealType1, class RealType2, class RealType3, class RealType4>
@@ -92,7 +92,7 @@ struct complemented5_type
const RealType3& param3;
const RealType4& param4;
private:
complemented5_type& operator=(const complemented5_type&);
complemented5_type& operator=(const complemented5_type&) = delete;
};
template <class Dist, class RealType1, class RealType2, class RealType3, class RealType4, class RealType5>
@@ -119,7 +119,7 @@ struct complemented6_type
const RealType4& param4;
const RealType5& param5;
private:
complemented6_type& operator=(const complemented6_type&);
complemented6_type& operator=(const complemented6_type&) = delete;
};
template <class Dist, class RealType1, class RealType2, class RealType3, class RealType4, class RealType5, class RealType6>
@@ -149,7 +149,7 @@ struct complemented7_type
const RealType5& param5;
const RealType6& param6;
private:
complemented7_type& operator=(const complemented7_type&);
complemented7_type& operator=(const complemented7_type&) = delete;
};
template <class Dist, class RealType>

View File

@@ -14,7 +14,7 @@
// using boost::math::isfinite;
// using boost::math::isnan;
#ifdef BOOST_MSVC
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable: 4702) // unreachable code (return after domain_error throw).
#endif
@@ -185,11 +185,12 @@ inline bool check_non_centrality(
RealType* result,
const Policy& pol)
{
if((ncp < 0) || !(boost::math::isfinite)(ncp))
{ // Assume scale == 0 is NOT valid for any distribution.
static const RealType upper_limit = static_cast<RealType>((std::numeric_limits<long long>::max)()) - boost::math::policies::get_max_root_iterations<Policy>();
if((ncp < 0) || !(boost::math::isfinite)(ncp) || ncp > upper_limit)
{
*result = policies::raise_domain_error<RealType>(
function,
"Non centrality parameter is %1%, but must be > 0 !", ncp, pol);
"Non centrality parameter is %1%, but must be > 0, and a countable value such that x+1 != x", ncp, pol);
return false;
}
return true;
@@ -216,7 +217,7 @@ inline bool check_finite(
} // namespace math
} // namespace boost
#ifdef BOOST_MSVC
#ifdef _MSC_VER
# pragma warning(pop)
#endif

View File

@@ -24,13 +24,13 @@
// of the distribution header, AFTER the distribution and its core
// property accessors have been defined: this is so that compilers
// that implement 2-phase lookup and early-type-checking of templates
// can find the definitions refered to herein.
// can find the definitions referred to herein.
//
#include <boost/type_traits/is_same.hpp>
#include <boost/static_assert.hpp>
#include <cmath>
#include <boost/math/tools/assert.hpp>
#ifdef BOOST_MSVC
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable: 4723) // potential divide by 0
// Suppressing spurious warning in coefficient_of_variation
@@ -65,7 +65,7 @@ inline typename Distribution::value_type hazard(const Distribution& dist, const
value_type d = pdf(dist, x);
if(d > p * tools::max_value<value_type>())
return policies::raise_overflow_error<value_type>(
"boost::math::hazard(const Distribution&, %1%)", 0, policy_type());
"boost::math::hazard(const Distribution&, %1%)", nullptr, policy_type());
if(d == 0)
{
// This protects against 0/0, but is it the right thing to do?
@@ -94,7 +94,7 @@ inline typename Distribution::value_type coefficient_of_variation(const Distribu
value_type d = standard_deviation(dist);
if((abs(m) < 1) && (d > abs(m) * tools::max_value<value_type>()))
{ // Checks too that m is not zero,
return policies::raise_overflow_error<value_type>("boost::math::coefficient_of_variation(const Distribution&, %1%)", 0, policy_type());
return policies::raise_overflow_error<value_type>("boost::math::coefficient_of_variation(const Distribution&, %1%)", nullptr, policy_type());
}
return d / m; // so MSVC warning on zerodivide is spurious, and suppressed.
}
@@ -110,11 +110,25 @@ inline typename Distribution::value_type pdf(const Distribution& dist, const Rea
return pdf(dist, static_cast<value_type>(x));
}
template <class Distribution, class RealType>
inline typename Distribution::value_type logpdf(const Distribution& dist, const RealType& x)
{
using std::log;
typedef typename Distribution::value_type value_type;
return log(pdf(dist, static_cast<value_type>(x)));
}
template <class Distribution, class RealType>
inline typename Distribution::value_type cdf(const Distribution& dist, const RealType& x)
{
typedef typename Distribution::value_type value_type;
return cdf(dist, static_cast<value_type>(x));
}
template <class Distribution, class Realtype>
inline typename Distribution::value_type logcdf(const Distribution& dist, const Realtype& x)
{
using std::log;
using value_type = typename Distribution::value_type;
return log(cdf(dist, static_cast<value_type>(x)));
}
template <class Distribution, class RealType>
inline typename Distribution::value_type quantile(const Distribution& dist, const RealType& x)
{
@@ -136,6 +150,14 @@ inline typename Distribution::value_type cdf(const complemented2_type<Distributi
return cdf(complement(c.dist, static_cast<value_type>(c.param)));
}
template <class Distribution, class RealType>
inline typename Distribution::value_type logcdf(const complemented2_type<Distribution, RealType>& c)
{
using std::log;
typedef typename Distribution::value_type value_type;
return log(cdf(complement(c.dist, static_cast<value_type>(c.param))));
}
template <class Distribution, class RealType>
inline typename Distribution::value_type quantile(const complemented2_type<Distribution, RealType>& c)
{
@@ -156,7 +178,7 @@ inline typename Dist::value_type median(const Dist& d)
} // namespace boost
#ifdef BOOST_MSVC
#ifdef _MSC_VER
# pragma warning(pop)
#endif

View File

@@ -72,7 +72,7 @@ typename Dist::value_type generic_find_mode(const Dist& dist, typename Dist::val
v = pdf(dist, lower_bound);
}while(maxval < v);
boost::uintmax_t max_iter = policies::get_max_root_iterations<policy_type>();
std::uintmax_t max_iter = policies::get_max_root_iterations<policy_type>();
value_type result = tools::brent_find_minima(
pdf_minimizer<Dist>(dist),
@@ -125,7 +125,7 @@ typename Dist::value_type generic_find_mode_01(const Dist& dist, typename Dist::
v = pdf(dist, lower_bound);
}while(maxval < v);
boost::uintmax_t max_iter = policies::get_max_root_iterations<policy_type>();
std::uintmax_t max_iter = policies::get_max_root_iterations<policy_type>();
value_type result = tools::brent_find_minima(
pdf_minimizer<Dist>(dist),

View File

@@ -11,8 +11,8 @@ namespace boost{ namespace math{ namespace detail{
template <class Dist>
struct generic_quantile_finder
{
typedef typename Dist::value_type value_type;
typedef typename Dist::policy_type policy_type;
using value_type = typename Dist::value_type;
using policy_type = typename Dist::policy_type;
generic_quantile_finder(const Dist& d, value_type t, bool c)
: dist(d), target(t), comp(c) {}
@@ -34,25 +34,31 @@ template <class T, class Policy>
inline T check_range_result(const T& x, const Policy& pol, const char* function)
{
if((x >= 0) && (x < tools::min_value<T>()))
return policies::raise_underflow_error<T>(function, 0, pol);
{
return policies::raise_underflow_error<T>(function, nullptr, pol);
}
if(x <= -tools::max_value<T>())
return -policies::raise_overflow_error<T>(function, 0, pol);
{
return -policies::raise_overflow_error<T>(function, nullptr, pol);
}
if(x >= tools::max_value<T>())
return policies::raise_overflow_error<T>(function, 0, pol);
{
return policies::raise_overflow_error<T>(function, nullptr, pol);
}
return x;
}
template <class 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)
{
typedef typename Dist::value_type value_type;
typedef typename Dist::policy_type policy_type;
typedef typename policies::normalise<
policy_type,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
using value_type = typename Dist::value_type;
using policy_type = typename Dist::policy_type;
using forwarding_policy = typename policies::normalise<
policy_type,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type;
//
// Special cases first:
@@ -72,7 +78,7 @@ typename Dist::value_type generic_quantile(const Dist& dist, const typename Dist
generic_quantile_finder<Dist> f(dist, p, comp);
tools::eps_tolerance<value_type> tol(policies::digits<value_type, forwarding_policy>() - 3);
boost::uintmax_t max_iter = policies::get_max_root_iterations<forwarding_policy>();
std::uintmax_t max_iter = policies::get_max_root_iterations<forwarding_policy>();
std::pair<value_type, value_type> ir = tools::bracket_and_solve_root(
f, guess, value_type(2), true, tol, max_iter, forwarding_policy());
value_type result = ir.first + (ir.second - ir.first) / 2;

View File

@@ -10,13 +10,14 @@
#include <boost/math/policies/error_handling.hpp>
#include <boost/math/distributions/detail/hypergeometric_pdf.hpp>
#include <cstdint>
namespace boost{ namespace math{ namespace detail{
template <class T, class Policy>
T hypergeometric_cdf_imp(unsigned x, unsigned r, unsigned n, unsigned N, bool invert, const Policy& pol)
T hypergeometric_cdf_imp(std::uint64_t x, std::uint64_t r, std::uint64_t n, std::uint64_t N, bool invert, const Policy& pol)
{
#ifdef BOOST_MSVC
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable:4267)
#endif
@@ -27,7 +28,7 @@ namespace boost{ namespace math{ namespace detail{
{
result = hypergeometric_pdf<T>(x, r, n, N, pol);
T diff = result;
unsigned lower_limit = static_cast<unsigned>((std::max)(0, (int)(n + r) - (int)(N)));
const auto lower_limit = static_cast<std::uint64_t>((std::max)(INT64_C(0), static_cast<std::int64_t>(n + r) - static_cast<std::int64_t>(N)));
while(diff > (invert ? T(1) : result) * tools::epsilon<T>())
{
diff = T(x) * T((N + x) - n - r) * diff / (T(1 + n - x) * T(1 + r - x));
@@ -43,7 +44,7 @@ namespace boost{ namespace math{ namespace detail{
else
{
invert = !invert;
unsigned upper_limit = (std::min)(r, n);
const auto upper_limit = (std::min)(r, n);
if(x != upper_limit)
{
++x;
@@ -63,21 +64,21 @@ namespace boost{ namespace math{ namespace detail{
if(invert)
result = 1 - result;
return result;
#ifdef BOOST_MSVC
#ifdef _MSC_VER
# pragma warning(pop)
#endif
}
template <class T, class Policy>
inline T hypergeometric_cdf(unsigned x, unsigned r, unsigned n, unsigned N, bool invert, const Policy&)
inline T hypergeometric_cdf(std::uint64_t x, std::uint64_t r, std::uint64_t n, std::uint64_t N, bool invert, 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>,
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;

View File

@@ -15,6 +15,8 @@
#include <boost/math/special_functions/pow.hpp>
#include <boost/math/special_functions/prime.hpp>
#include <boost/math/policies/error_handling.hpp>
#include <algorithm>
#include <cstdint>
#ifdef BOOST_MATH_INSTRUMENT
#include <typeinfo>
@@ -40,7 +42,7 @@ template <class T>
struct sort_functor
{
sort_functor(const T* exponents) : m_exponents(exponents){}
bool operator()(int i, int j)
bool operator()(std::size_t i, std::size_t j)
{
return m_exponents[i] > m_exponents[j];
}
@@ -49,7 +51,7 @@ private:
};
template <class T, class Lanczos, class Policy>
T hypergeometric_pdf_lanczos_imp(T /*dummy*/, unsigned x, unsigned r, unsigned n, unsigned N, const Lanczos&, const Policy&)
T hypergeometric_pdf_lanczos_imp(T /*dummy*/, std::uint64_t x, std::uint64_t r, std::uint64_t n, std::uint64_t N, const Lanczos&, const Policy&)
{
BOOST_MATH_STD_USING
@@ -137,7 +139,7 @@ T hypergeometric_pdf_lanczos_imp(T /*dummy*/, unsigned x, unsigned r, unsigned n
//
// Combine equal powers:
//
int j = 8;
std::size_t j = 8;
while(exponents[sorted_indexes[j]] == 0) --j;
while(j)
{
@@ -184,7 +186,7 @@ T hypergeometric_pdf_lanczos_imp(T /*dummy*/, unsigned x, unsigned r, unsigned n
result = pow(bases[sorted_indexes[0]] * exp(static_cast<T>(base_e_factors[sorted_indexes[0]])), exponents[sorted_indexes[0]]);
}
BOOST_MATH_INSTRUMENT_VARIABLE(result);
for(unsigned i = 1; (i < 9) && (exponents[sorted_indexes[i]] > 0); ++i)
for(std::size_t i = 1; (i < 9) && (exponents[sorted_indexes[i]] > 0); ++i)
{
BOOST_FPU_EXCEPTION_GUARD
if(result < tools::min_value<T>())
@@ -215,7 +217,7 @@ T hypergeometric_pdf_lanczos_imp(T /*dummy*/, unsigned x, unsigned r, unsigned n
}
template <class T, class Policy>
T hypergeometric_pdf_lanczos_imp(T /*dummy*/, unsigned x, unsigned r, unsigned n, unsigned N, const boost::math::lanczos::undefined_lanczos&, const Policy& pol)
T hypergeometric_pdf_lanczos_imp(T /*dummy*/, std::uint64_t x, std::uint64_t r, std::uint64_t n, std::uint64_t N, const boost::math::lanczos::undefined_lanczos&, const Policy& pol)
{
BOOST_MATH_STD_USING
return exp(
@@ -260,7 +262,7 @@ inline T integer_power(const T& x, int ex)
#ifdef __SUNPRO_CC
return pow(x, T(ex));
#else
return pow(x, ex);
return static_cast<T>(pow(x, ex));
#endif
}
template <class T>
@@ -270,22 +272,22 @@ struct hypergeometric_pdf_prime_loop_result_entry
const hypergeometric_pdf_prime_loop_result_entry* next;
};
#ifdef BOOST_MSVC
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4510 4512 4610)
#endif
struct hypergeometric_pdf_prime_loop_data
{
const unsigned x;
const unsigned r;
const unsigned n;
const unsigned N;
unsigned prime_index;
unsigned current_prime;
const std::uint64_t x;
const std::uint64_t r;
const std::uint64_t n;
const std::uint64_t N;
std::size_t prime_index;
std::uint64_t current_prime;
};
#ifdef BOOST_MSVC
#ifdef _MSC_VER
#pragma warning(pop)
#endif
@@ -294,8 +296,8 @@ T hypergeometric_pdf_prime_loop_imp(hypergeometric_pdf_prime_loop_data& data, hy
{
while(data.current_prime <= data.N)
{
unsigned base = data.current_prime;
int prime_powers = 0;
std::uint64_t base = data.current_prime;
std::int64_t prime_powers = 0;
while(base <= data.N)
{
prime_powers += data.n / base;
@@ -381,7 +383,7 @@ T hypergeometric_pdf_prime_loop_imp(hypergeometric_pdf_prime_loop_data& data, hy
}
template <class T, class Policy>
inline T hypergeometric_pdf_prime_imp(unsigned x, unsigned r, unsigned n, unsigned N, const Policy&)
inline T hypergeometric_pdf_prime_imp(std::uint64_t x, std::uint64_t r, std::uint64_t n, std::uint64_t N, const Policy&)
{
hypergeometric_pdf_prime_loop_result_entry<T> result = { 1, 0 };
hypergeometric_pdf_prime_loop_data data = { x, r, n, N, 0, prime(0) };
@@ -389,10 +391,10 @@ inline T hypergeometric_pdf_prime_imp(unsigned x, unsigned r, unsigned n, unsign
}
template <class T, class Policy>
T hypergeometric_pdf_factorial_imp(unsigned x, unsigned r, unsigned n, unsigned N, const Policy&)
T hypergeometric_pdf_factorial_imp(std::uint64_t x, std::uint64_t r, std::uint64_t n, std::uint64_t N, const Policy&)
{
BOOST_MATH_STD_USING
BOOST_ASSERT(N <= boost::math::max_factorial<T>::value);
BOOST_MATH_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),
@@ -406,8 +408,8 @@ T hypergeometric_pdf_factorial_imp(unsigned x, unsigned r, unsigned n, unsigned
boost::math::unchecked_factorial<T>(r - x),
boost::math::unchecked_factorial<T>(N - n - r + x)
};
int i = 0;
int j = 0;
std::size_t i = 0;
std::size_t j = 0;
while((i < 3) || (j < 5))
{
while((j < 5) && ((result >= 1) || (i >= 3)))
@@ -427,7 +429,7 @@ T hypergeometric_pdf_factorial_imp(unsigned x, unsigned r, unsigned n, unsigned
template <class T, class Policy>
inline typename tools::promote_args<T>::type
hypergeometric_pdf(unsigned x, unsigned r, unsigned n, unsigned N, const Policy&)
hypergeometric_pdf(std::uint64_t x, std::uint64_t r, std::uint64_t n, std::uint64_t N, const Policy&)
{
BOOST_FPU_EXCEPTION_GUARD
typedef typename tools::promote_args<T>::type result_type;

View File

@@ -104,7 +104,7 @@ inline unsigned round_x_from_q(unsigned x, T /*q*/, T /*cum*/, T /*fudge_factor*
template <class T, class Policy>
unsigned hypergeometric_quantile_imp(T p, T q, unsigned r, unsigned n, unsigned N, const Policy& pol)
{
#ifdef BOOST_MSVC
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable:4267)
#endif
@@ -113,7 +113,7 @@ unsigned hypergeometric_quantile_imp(T p, T q, unsigned r, unsigned n, unsigned
BOOST_FPU_EXCEPTION_GUARD
T result;
T fudge_factor = 1 + tools::epsilon<T>() * ((N <= boost::math::prime(boost::math::max_prime - 1)) ? 50 : 2 * N);
unsigned base = static_cast<unsigned>((std::max)(0, (int)(n + r) - (int)(N)));
unsigned base = static_cast<unsigned>((std::max)(0, static_cast<int>(n + r) - static_cast<int>(N)));
unsigned lim = (std::min)(r, n);
BOOST_MATH_INSTRUMENT_VARIABLE(p);
@@ -150,12 +150,12 @@ unsigned hypergeometric_quantile_imp(T p, T q, unsigned r, unsigned n, unsigned
++x;
}
// By the time we get here, log_pdf may be fairly inaccurate due to
// roundoff errors, get a fresh PDF calculation before proceding:
// roundoff errors, get a fresh PDF calculation before proceeding:
diff = hypergeometric_pdf<T>(x, r, n, N, pol);
}
while(result < p)
{
diff = (diff > tools::min_value<T>() * 8)
diff = (diff > tools::min_value<T>() * 8)
? T(n - x) * T(r - x) * diff / (T(x + 1) * T(N + x + 1 - n - r))
: hypergeometric_pdf<T>(x + 1, r, n, N, pol);
if(result + diff / 2 > p)
@@ -198,7 +198,7 @@ unsigned hypergeometric_quantile_imp(T p, T q, unsigned r, unsigned n, unsigned
--x;
}
// By the time we get here, log_pdf may be fairly inaccurate due to
// roundoff errors, get a fresh PDF calculation before proceding:
// roundoff errors, get a fresh PDF calculation before proceeding:
diff = hypergeometric_pdf<T>(x, r, n, N, pol);
}
while(result + diff / 2 < q)
@@ -219,7 +219,7 @@ unsigned hypergeometric_quantile_imp(T p, T q, unsigned r, unsigned n, unsigned
}
return round_x_from_q(x, q, result, fudge_factor, base, lim, discrete_quantile_type());
}
#ifdef BOOST_MSVC
#ifdef _MSC_VER
# pragma warning(pop)
#endif
}
@@ -231,9 +231,9 @@ inline unsigned hypergeometric_quantile(T p, T q, unsigned r, unsigned n, unsign
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>,
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::assert_undefined<> >::type forwarding_policy;
return detail::hypergeometric_quantile_imp<value_type>(p, q, r, n, N, forwarding_policy());

View File

@@ -78,7 +78,7 @@ typename Dist::value_type
const typename Dist::value_type& multiplier,
typename Dist::value_type adder,
const Tolerance& tol,
boost::uintmax_t& max_iter)
std::uintmax_t& max_iter)
{
typedef typename Dist::value_type value_type;
typedef typename Dist::policy_type policy_type;
@@ -100,7 +100,7 @@ typename Dist::value_type
guess = min_bound;
value_type fa = f(guess);
boost::uintmax_t count = max_iter - 1;
std::uintmax_t count = max_iter - 1;
value_type fb(fa), a(guess), b =0; // Compiler warning C4701: potentially uninitialized local variable 'b' used
if(fa == 0)
@@ -316,7 +316,7 @@ inline typename Dist::value_type round_to_floor(const Dist& d, typename Dist::va
return result;
}
#ifdef BOOST_MSVC
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4127)
#endif
@@ -350,7 +350,7 @@ inline typename Dist::value_type round_to_ceil(const Dist& d, typename Dist::val
return result;
}
#ifdef BOOST_MSVC
#ifdef _MSC_VER
#pragma warning(pop)
#endif
//
@@ -370,7 +370,7 @@ inline typename Dist::value_type
const typename Dist::value_type& multiplier,
const typename Dist::value_type& adder,
const policies::discrete_quantile<policies::real>&,
boost::uintmax_t& max_iter)
std::uintmax_t& max_iter)
{
if(p > 0.5)
{
@@ -401,7 +401,7 @@ inline typename Dist::value_type
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)
std::uintmax_t& max_iter)
{
typedef typename Dist::value_type value_type;
BOOST_MATH_STD_USING
@@ -444,7 +444,7 @@ inline typename Dist::value_type
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)
std::uintmax_t& max_iter)
{
typedef typename Dist::value_type value_type;
BOOST_MATH_STD_USING
@@ -487,7 +487,7 @@ inline typename Dist::value_type
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)
std::uintmax_t& max_iter)
{
typedef typename Dist::value_type value_type;
BOOST_MATH_STD_USING
@@ -515,7 +515,7 @@ inline typename Dist::value_type
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)
std::uintmax_t& max_iter)
{
BOOST_MATH_STD_USING
typename Dist::value_type pp = c ? 1 - p : p;
@@ -542,7 +542,7 @@ inline typename Dist::value_type
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)
std::uintmax_t& max_iter)
{
typedef typename Dist::value_type value_type;
BOOST_MATH_STD_USING

View File

@@ -0,0 +1,73 @@
// Copyright Nick Thompson 2019.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_MATH_DISTRIBUTIONS_EMPIRICAL_CUMULATIVE_DISTRIBUTION_FUNCTION_HPP
#define BOOST_MATH_DISTRIBUTIONS_EMPIRICAL_CUMULATIVE_DISTRIBUTION_FUNCTION_HPP
#include <algorithm>
#include <iterator>
#include <stdexcept>
#include <type_traits>
#include <utility>
#include <boost/math/tools/is_standalone.hpp>
#ifndef BOOST_MATH_STANDALONE
#include <boost/config.hpp>
#ifdef BOOST_NO_CXX17_IF_CONSTEXPR
#error "The header <boost/math/norms.hpp> can only be used in C++17 and later."
#endif
#endif
namespace boost { namespace math{
template<class RandomAccessContainer>
class empirical_cumulative_distribution_function {
using Real = typename RandomAccessContainer::value_type;
public:
empirical_cumulative_distribution_function(RandomAccessContainer && v, bool sorted = false)
{
if (v.size() == 0) {
throw std::domain_error("At least one sample is required to compute an empirical CDF.");
}
m_v = std::move(v);
if (!sorted) {
std::sort(m_v.begin(), m_v.end());
}
}
auto operator()(Real x) const {
if constexpr (std::is_integral_v<Real>)
{
if (x < m_v[0]) {
return static_cast<double>(0);
}
if (x >= m_v[m_v.size()-1]) {
return static_cast<double>(1);
}
auto it = std::upper_bound(m_v.begin(), m_v.end(), x);
return static_cast<double>(std::distance(m_v.begin(), it))/static_cast<double>(m_v.size());
}
else
{
if (x < m_v[0]) {
return Real(0);
}
if (x >= m_v[m_v.size()-1]) {
return Real(1);
}
auto it = std::upper_bound(m_v.begin(), m_v.end(), x);
return static_cast<Real>(std::distance(m_v.begin(), it))/static_cast<Real>(m_v.size());
}
}
RandomAccessContainer&& return_data() {
return std::move(m_v);
}
private:
RandomAccessContainer m_v;
};
}}
#endif

View File

@@ -12,15 +12,15 @@
#include <boost/math/special_functions/expm1.hpp>
#include <boost/math/distributions/complement.hpp>
#include <boost/math/distributions/detail/common_error_handling.hpp>
#include <boost/config/no_tr1/cmath.hpp>
#ifdef BOOST_MSVC
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable: 4127) // conditional expression is constant
# pragma warning(disable: 4702) // unreachable code (return after domain_error throw).
#endif
#include <utility>
#include <cmath>
namespace boost{ namespace math{
@@ -60,10 +60,10 @@ template <class RealType = double, class Policy = policies::policy<> >
class exponential_distribution
{
public:
typedef RealType value_type;
typedef Policy policy_type;
using value_type = RealType;
using policy_type = Policy;
exponential_distribution(RealType l_lambda = 1)
explicit exponential_distribution(RealType l_lambda = 1)
: m_lambda(l_lambda)
{
RealType err;
@@ -76,10 +76,15 @@ private:
RealType m_lambda;
};
typedef exponential_distribution<double> exponential;
using exponential = exponential_distribution<double>;
#ifdef __cpp_deduction_guides
template <class RealType>
exponential_distribution(RealType)->exponential_distribution<typename boost::math::tools::promote_args<RealType>::type>;
#endif
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const exponential_distribution<RealType, Policy>& /*dist*/)
inline 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)
{
@@ -93,7 +98,7 @@ inline const std::pair<RealType, RealType> range(const exponential_distribution<
}
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> support(const exponential_distribution<RealType, Policy>& /*dist*/)
inline std::pair<RealType, RealType> support(const exponential_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.
using boost::math::tools::max_value;
@@ -122,6 +127,24 @@ inline RealType pdf(const exponential_distribution<RealType, Policy>& dist, cons
return result;
} // pdf
template <class RealType, class Policy>
inline RealType logpdf(const exponential_distribution<RealType, Policy>& dist, const RealType& x)
{
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::logpdf(const exponential_distribution<%1%>&, %1%)";
RealType lambda = dist.lambda();
RealType result = -std::numeric_limits<RealType>::infinity();
if(0 == detail::verify_lambda(function, lambda, &result, Policy()))
return result;
if(0 == detail::verify_exp_x(function, x, &result, Policy()))
return result;
result = log(lambda) - lambda * x;
return result;
} // logpdf
template <class RealType, class Policy>
inline RealType cdf(const exponential_distribution<RealType, Policy>& dist, const RealType& x)
{
@@ -140,6 +163,24 @@ inline RealType cdf(const exponential_distribution<RealType, Policy>& dist, cons
return result;
} // cdf
template <class RealType, class Policy>
inline RealType logcdf(const exponential_distribution<RealType, Policy>& dist, const RealType& x)
{
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::logcdf(const exponential_distribution<%1%>&, %1%)";
RealType result = 0;
RealType lambda = dist.lambda();
if(0 == detail::verify_lambda(function, lambda, &result, Policy()))
return result;
if(0 == detail::verify_exp_x(function, x, &result, Policy()))
return result;
result = boost::math::log1p(-exp(-x * lambda), Policy());
return result;
} // cdf
template <class RealType, class Policy>
inline RealType quantile(const exponential_distribution<RealType, Policy>& dist, const RealType& p)
{
@@ -184,6 +225,27 @@ inline RealType cdf(const complemented2_type<exponential_distribution<RealType,
return result;
}
template <class RealType, class Policy>
inline RealType logcdf(const complemented2_type<exponential_distribution<RealType, Policy>, RealType>& c)
{
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::logcdf(const exponential_distribution<%1%>&, %1%)";
RealType result = 0;
RealType lambda = c.dist.lambda();
if(0 == detail::verify_lambda(function, lambda, &result, Policy()))
return result;
if(0 == detail::verify_exp_x(function, c.param, &result, Policy()))
return result;
// Workaround for VC11/12 bug:
if (c.param >= tools::max_value<RealType>())
return 0;
result = -c.param * lambda;
return result;
}
template <class RealType, class Policy>
inline RealType quantile(const complemented2_type<exponential_distribution<RealType, Policy>, RealType>& c)
{
@@ -260,10 +322,17 @@ inline RealType kurtosis_excess(const exponential_distribution<RealType, Policy>
return 6;
}
template <class RealType, class Policy>
inline RealType entropy(const exponential_distribution<RealType, Policy>& dist)
{
using std::log;
return 1 - log(dist.lambda());
}
} // namespace math
} // namespace boost
#ifdef BOOST_MSVC
#ifdef _MSC_VER
# pragma warning(pop)
#endif

View File

@@ -12,7 +12,6 @@
#include <boost/math/special_functions/expm1.hpp>
#include <boost/math/distributions/complement.hpp>
#include <boost/math/distributions/detail/common_error_handling.hpp>
#include <boost/config/no_tr1/cmath.hpp>
//
// This is the maximum extreme value distribution, see
@@ -22,8 +21,9 @@
// distribution or a Gumbel distribution.
#include <utility>
#include <cmath>
#ifdef BOOST_MSVC
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable: 4702) // unreachable code (return after domain_error throw).
#endif
@@ -53,10 +53,10 @@ template <class RealType = double, class Policy = policies::policy<> >
class extreme_value_distribution
{
public:
typedef RealType value_type;
typedef Policy policy_type;
using value_type = RealType;
using policy_type = Policy;
extreme_value_distribution(RealType a = 0, RealType b = 1)
explicit extreme_value_distribution(RealType a = 0, RealType b = 1)
: m_a(a), m_b(b)
{
RealType err;
@@ -68,13 +68,21 @@ public:
RealType scale()const { return m_b; }
private:
RealType m_a, m_b;
RealType m_a;
RealType m_b;
};
typedef extreme_value_distribution<double> extreme_value;
using extreme_value = extreme_value_distribution<double>;
#ifdef __cpp_deduction_guides
template <class RealType>
extreme_value_distribution(RealType)->extreme_value_distribution<typename boost::math::tools::promote_args<RealType>::type>;
template <class RealType>
extreme_value_distribution(RealType,RealType)->extreme_value_distribution<typename boost::math::tools::promote_args<RealType>::type>;
#endif
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const extreme_value_distribution<RealType, Policy>& /*dist*/)
inline 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>(
@@ -83,7 +91,7 @@ inline const std::pair<RealType, RealType> range(const extreme_value_distributio
}
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> support(const extreme_value_distribution<RealType, Policy>& /*dist*/)
inline std::pair<RealType, RealType> support(const extreme_value_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.
using boost::math::tools::max_value;
@@ -115,6 +123,31 @@ inline RealType pdf(const extreme_value_distribution<RealType, Policy>& dist, co
return result;
} // pdf
template <class RealType, class Policy>
inline RealType logpdf(const extreme_value_distribution<RealType, Policy>& dist, const RealType& x)
{
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::logpdf(const extreme_value_distribution<%1%>&, %1%)";
RealType a = dist.location();
RealType b = dist.scale();
RealType result = -std::numeric_limits<RealType>::infinity();
if(0 == detail::verify_scale_b(function, b, &result, Policy()))
return result;
if(0 == detail::check_finite(function, a, &result, Policy()))
return result;
if((boost::math::isinf)(x))
return 0.0f;
if(0 == detail::check_x(function, x, &result, Policy()))
return result;
RealType e = (a - x) / b;
if(e < tools::log_max_value<RealType>())
result = log(1/b) + e - exp(e);
// else.... result *must* be zero since exp(e) is infinite...
return result;
} // logpdf
template <class RealType, class Policy>
inline RealType cdf(const extreme_value_distribution<RealType, Policy>& dist, const RealType& x)
{
@@ -141,6 +174,32 @@ inline RealType cdf(const extreme_value_distribution<RealType, Policy>& dist, co
return result;
} // cdf
template <class RealType, class Policy>
inline RealType logcdf(const extreme_value_distribution<RealType, Policy>& dist, const RealType& x)
{
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::logcdf(const extreme_value_distribution<%1%>&, %1%)";
if((boost::math::isinf)(x))
return x < 0 ? 0.0f : 1.0f;
RealType a = dist.location();
RealType b = dist.scale();
RealType result = 0;
if(0 == detail::verify_scale_b(function, b, &result, Policy()))
return result;
if(0 == detail::check_finite(function, a, &result, Policy()))
return result;
if(0 == detail::check_finite(function, a, &result, Policy()))
return result;
if(0 == detail::check_x("boost::math::logcdf(const extreme_value_distribution<%1%>&, %1%)", x, &result, Policy()))
return result;
result = -exp((a-x)/b);
return result;
} // logcdf
template <class RealType, class Policy>
RealType quantile(const extreme_value_distribution<RealType, Policy>& dist, const RealType& p)
{
@@ -192,6 +251,30 @@ inline RealType cdf(const complemented2_type<extreme_value_distribution<RealType
return result;
}
template <class RealType, class Policy>
inline RealType logcdf(const complemented2_type<extreme_value_distribution<RealType, Policy>, RealType>& c)
{
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::logcdf(const extreme_value_distribution<%1%>&, %1%)";
if((boost::math::isinf)(c.param))
return c.param < 0 ? 1.0f : 0.0f;
RealType a = c.dist.location();
RealType b = c.dist.scale();
RealType result = 0;
if(0 == detail::verify_scale_b(function, b, &result, Policy()))
return result;
if(0 == detail::check_finite(function, a, &result, Policy()))
return result;
if(0 == detail::check_x(function, c.param, &result, Policy()))
return result;
result = log1p(-exp(-exp((a-c.param)/b)), Policy());
return result;
}
template <class RealType, class Policy>
RealType quantile(const complemented2_type<extreme_value_distribution<RealType, Policy>, RealType>& c)
{
@@ -288,7 +371,7 @@ inline RealType kurtosis_excess(const extreme_value_distribution<RealType, Polic
} // namespace math
} // namespace boost
#ifdef BOOST_MSVC
#ifdef _MSC_VER
# pragma warning(pop)
#endif

View File

@@ -12,7 +12,6 @@
#include <boost/math/distributions/complement.hpp>
#include <boost/math/policies/policy.hpp>
#include <boost/math/tools/traits.hpp>
#include <boost/static_assert.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
#include <boost/math/policies/error_handling.hpp>
// using boost::math::policies::policy;
@@ -26,7 +25,7 @@ namespace boost
// Function to find location of random variable z
// to give probability p (given scale)
// Applies to normal, lognormal, extreme value, Cauchy, (and symmetrical triangular),
// enforced by BOOST_STATIC_ASSERT below.
// enforced by static_assert below.
template <class Dist, class Policy>
inline
@@ -38,13 +37,8 @@ namespace boost
const Policy& pol
)
{
#if !defined(BOOST_NO_SFINAE) && !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
// Will fail to compile here if try to use with a distribution without scale & location,
// for example pareto, and many others. These tests are disabled by the pp-logic
// above if the compiler doesn't support the SFINAE tricks used in the traits class.
BOOST_STATIC_ASSERT(::boost::math::tools::is_distribution<Dist>::value);
BOOST_STATIC_ASSERT(::boost::math::tools::is_scaled_distribution<Dist>::value);
#endif
static_assert(::boost::math::tools::is_distribution<Dist>::value, "The provided distribution does not meet the conceptual requirements of a distribution.");
static_assert(::boost::math::tools::is_scaled_distribution<Dist>::value, "The provided distribution does not meet the conceptual requirements of a scaled distribution.");
static const char* function = "boost::math::find_location<Dist, Policy>&, %1%)";
if(!(boost::math::isfinite)(p) || (p < 0) || (p > 1))

View File

@@ -13,7 +13,7 @@
#include <boost/math/policies/policy.hpp>
// using boost::math::policies::policy;
#include <boost/math/tools/traits.hpp>
#include <boost/static_assert.hpp>
#include <boost/math/tools/assert.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
#include <boost/math/policies/error_handling.hpp>
// using boost::math::complement; // will be needed by users who want complement,
@@ -39,10 +39,8 @@ namespace boost
const Policy& pol
)
{
#if !defined(BOOST_NO_SFINAE) && !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
BOOST_STATIC_ASSERT(::boost::math::tools::is_distribution<Dist>::value);
BOOST_STATIC_ASSERT(::boost::math::tools::is_scaled_distribution<Dist>::value);
#endif
static_assert(::boost::math::tools::is_distribution<Dist>::value, "The provided distribution does not meet the conceptual requirements of a distribution.");
static_assert(::boost::math::tools::is_scaled_distribution<Dist>::value, "The provided distribution does not meet the conceptual requirements of a scaled distribution.");
static const char* function = "boost::math::find_scale<Dist, Policy>(%1%, %1%, %1%, Policy)";
if(!(boost::math::isfinite)(p) || (p < 0) || (p > 1))
@@ -111,10 +109,8 @@ namespace boost
// << quantile(Dist(), c.param1) //q
// << endl;
#if !defined(BOOST_NO_SFINAE) && !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
BOOST_STATIC_ASSERT(::boost::math::tools::is_distribution<Dist>::value);
BOOST_STATIC_ASSERT(::boost::math::tools::is_scaled_distribution<Dist>::value);
#endif
static_assert(::boost::math::tools::is_distribution<Dist>::value, "The provided distribution does not meet the conceptual requirements of a distribution.");
static_assert(::boost::math::tools::is_scaled_distribution<Dist>::value, "The provided distribution does not meet the conceptual requirements of a scaled distribution.");
static const char* function = "boost::math::find_scale<Dist, Policy>(complement(%1%, %1%, %1%, Policy))";
// Checks on arguments, as not complemented version,
@@ -165,10 +161,8 @@ namespace boost
// << quantile(Dist(), c.param1) //q
// << endl;
#if !defined(BOOST_NO_SFINAE) && !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
BOOST_STATIC_ASSERT(::boost::math::tools::is_distribution<Dist>::value);
BOOST_STATIC_ASSERT(::boost::math::tools::is_scaled_distribution<Dist>::value);
#endif
static_assert(::boost::math::tools::is_distribution<Dist>::value, "The provided distribution does not meet the conceptual requirements of a distribution.");
static_assert(::boost::math::tools::is_scaled_distribution<Dist>::value, "The provided distribution does not meet the conceptual requirements of a scaled distribution.");
static const char* function = "boost::math::find_scale<Dist, Policy>(complement(%1%, %1%, %1%, Policy))";
// Checks on arguments, as not complemented version,

View File

@@ -54,6 +54,11 @@ private:
typedef fisher_f_distribution<double> fisher_f;
#ifdef __cpp_deduction_guides
template <class RealType>
fisher_f_distribution(RealType,RealType)->fisher_f_distribution<typename boost::math::tools::promote_args<RealType>::type>;
#endif
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const fisher_f_distribution<RealType, Policy>& /*dist*/)
{ // Range of permissible values for random variable x.
@@ -178,7 +183,7 @@ inline RealType quantile(const fisher_f_distribution<RealType, Policy>& dist, co
return error_result;
// With optimizations turned on, gcc wrongly warns about y being used
// uninitializated unless we initialize it to something:
// uninitialized unless we initialize it to something:
RealType x, y(0);
x = boost::math::ibeta_inv(df1 / 2, df2 / 2, p, &y, Policy());
@@ -301,10 +306,10 @@ inline RealType mode(const fisher_f_distribution<RealType, Policy>& dist)
&& detail::check_df(
function, df2, &error_result, Policy()))
return error_result;
if(df2 <= 2)
if(df1 <= 2)
{
return policies::raise_domain_error<RealType>(
function, "Second degree of freedom was %1% but must be > 2 in order for the distribution to have a mode.", df2, Policy());
function, "First degree of freedom was %1% but must be > 2 in order for the distribution to have a mode.", df1, Policy());
}
return df2 * (df1 - 2) / (df1 * (df2 + 2));
}
@@ -366,7 +371,7 @@ inline RealType kurtosis_excess(const fisher_f_distribution<RealType, Policy>& d
if(df2 <= 8)
{
return policies::raise_domain_error<RealType>(
function, "Second degree of freedom was %1% but must be > 8 in order for the distribution to have a kutosis.", df2, Policy());
function, "Second degree of freedom was %1% but must be > 8 in order for the distribution to have a kurtosis.", df2, Policy());
}
RealType df2_2 = df2 * df2;
RealType df1_2 = df1 * df1;

View File

@@ -63,6 +63,9 @@ class inverse_gamma_distribution;
template <class RealType, class Policy>
class inverse_gaussian_distribution;
template <class RealType, class Policy>
class kolmogorov_smirnov_distribution;
template <class RealType, class Policy>
class laplace_distribution;
@@ -129,6 +132,7 @@ class weibull_distribution;
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::kolmogorov_smirnov_distribution<Type, Policy> kolmogorov_smirnov;\
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;\

View File

@@ -12,10 +12,12 @@
#include <boost/math/distributions/fwd.hpp>
#include <boost/math/special_functions/gamma.hpp>
#include <boost/math/special_functions/digamma.hpp>
#include <boost/math/distributions/detail/common_error_handling.hpp>
#include <boost/math/distributions/complement.hpp>
#include <utility>
#include <type_traits>
namespace boost{ namespace math
{
@@ -70,10 +72,10 @@ template <class RealType = double, class Policy = policies::policy<> >
class gamma_distribution
{
public:
typedef RealType value_type;
typedef Policy policy_type;
using value_type = RealType;
using policy_type = Policy;
gamma_distribution(RealType l_shape, RealType l_scale = 1)
explicit gamma_distribution(RealType l_shape, RealType l_scale = 1)
: m_shape(l_shape), m_scale(l_scale)
{
RealType result;
@@ -99,15 +101,22 @@ private:
// NO typedef because of clash with name of gamma function.
#ifdef __cpp_deduction_guides
template <class RealType>
gamma_distribution(RealType)->gamma_distribution<typename boost::math::tools::promote_args<RealType>::type>;
template <class RealType>
gamma_distribution(RealType,RealType)->gamma_distribution<typename boost::math::tools::promote_args<RealType>::type>;
#endif
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const gamma_distribution<RealType, Policy>& /* dist */)
inline std::pair<RealType, RealType> range(const gamma_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>());
}
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> support(const gamma_distribution<RealType, Policy>& /* dist */)
inline std::pair<RealType, RealType> support(const gamma_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.
using boost::math::tools::max_value;
@@ -139,6 +148,33 @@ inline RealType pdf(const gamma_distribution<RealType, Policy>& dist, const Real
return result;
} // pdf
template <class RealType, class Policy>
inline RealType logpdf(const gamma_distribution<RealType, Policy>& dist, const RealType& x)
{
BOOST_MATH_STD_USING // for ADL of std functions
using boost::math::lgamma;
static const char* function = "boost::math::logpdf(const gamma_distribution<%1%>&, %1%)";
RealType k = dist.shape();
RealType theta = dist.scale();
RealType result = -std::numeric_limits<RealType>::infinity();
if(false == detail::check_gamma(function, theta, k, &result, Policy()))
return result;
if(false == detail::check_gamma_x(function, x, &result, Policy()))
return result;
if(x == 0)
{
return std::numeric_limits<RealType>::quiet_NaN();
}
result = -k*log(theta) + (k-1)*log(x) - lgamma(k) - (x/theta);
return result;
} // logpdf
template <class RealType, class Policy>
inline RealType cdf(const gamma_distribution<RealType, Policy>& dist, const RealType& x)
{
@@ -336,6 +372,15 @@ inline RealType kurtosis(const gamma_distribution<RealType, Policy>& dist)
return kurtosis_excess(dist) + 3;
}
template <class RealType, class Policy>
inline RealType entropy(const gamma_distribution<RealType, Policy>& dist)
{
RealType k = dist.shape();
RealType theta = dist.scale();
using std::log;
return k + log(theta) + lgamma(k) + (1-k)*digamma(k);
}
} // namespace math
} // namespace boost

View File

@@ -24,7 +24,7 @@
// is strictly defined as a discrete function:
// only integral values of k are envisaged.
// However because the method of calculation uses a continuous gamma function,
// it is convenient to treat it as if a continous function,
// it is convenient to treat it as if a continuous function,
// and permit non-integral values of k.
// To enforce the strict mathematical model, users should use floor or ceil functions
// on k outside this function to ensure that k is integral.
@@ -43,14 +43,11 @@
#include <boost/math/special_functions/fpclassify.hpp> // isnan.
#include <boost/math/tools/roots.hpp> // for root finding.
#include <boost/math/distributions/detail/inv_discrete_quantile.hpp>
#include <boost/type_traits/is_floating_point.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/mpl/if.hpp>
#include <boost/math/special_functions/log1p.hpp>
#include <limits> // using std::numeric_limits;
#include <utility>
#include <cmath>
#if defined (BOOST_MSVC)
# pragma warning(push)
@@ -163,7 +160,7 @@ namespace boost
// Discrete Distributions" Yong CAI and K. KRISHNAMOORTHY
// http://www.ucs.louisiana.edu/~kxk4695/Discrete_new.pdf
//
return ibeta_inv(successes, failures + 1, alpha, static_cast<RealType*>(0), Policy());
return ibeta_inv(successes, failures + 1, alpha, static_cast<RealType*>(nullptr), Policy());
} // find_lower_bound_on_p
static RealType find_upper_bound_on_p(
@@ -192,7 +189,7 @@ namespace boost
// Discrete Distributions" Yong CAI and K. Krishnamoorthy
// http://www.ucs.louisiana.edu/~kxk4695/Discrete_new.pdf
//
return ibetac_inv(successes, failures, alpha, static_cast<RealType*>(0), Policy());
return ibetac_inv(successes, failures, alpha, static_cast<RealType*>(nullptr), Policy());
} // find_upper_bound_on_p
// Estimate number of trials :
@@ -227,7 +224,7 @@ namespace boost
if(false == geometric_detail::check_dist_and_k(
function, p, k, &result, Policy())
&& detail::check_probability(function, alpha, &result, Policy()))
{
{
return result;
}
result = ibetac_inva(k + 1, p, alpha, Policy()); // returns n - k
@@ -241,6 +238,11 @@ namespace boost
typedef geometric_distribution<double> geometric; // Reserved name of type double.
#ifdef __cpp_deduction_guides
template <class RealType>
geometric_distribution(RealType)->geometric_distribution<typename boost::math::tools::promote_args<RealType>::type>;
#endif
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const geometric_distribution<RealType, Policy>& /* dist */)
{ // Range of permissible values for random variable k.
@@ -270,7 +272,7 @@ namespace boost
BOOST_MATH_STD_USING // ADL of std functions.
return 0;
} // mode
template <class RealType, class Policy>
inline RealType variance(const geometric_distribution<RealType, Policy>& dist)
{ // Variance of Binomial distribution = (1-p) / p^2.
@@ -378,9 +380,39 @@ namespace boost
return probability;
} // cdf Cumulative Distribution Function geometric.
template <class RealType, class Policy>
inline RealType cdf(const complemented2_type<geometric_distribution<RealType, Policy>, RealType>& c)
{ // Complemented Cumulative Distribution Function geometric.
template <class RealType, class Policy>
inline RealType logcdf(const geometric_distribution<RealType, Policy>& dist, const RealType& k)
{ // Cumulative Distribution Function of geometric.
using std::pow;
static const char* function = "boost::math::logcdf(const geometric_distribution<%1%>&, %1%)";
// k argument may be integral, signed, or unsigned, or floating point.
// If necessary, it has already been promoted from an integral type.
RealType p = dist.success_fraction();
// Error check:
RealType result = 0;
if(false == geometric_detail::check_dist_and_k(
function,
p,
k,
&result, Policy()))
{
return -std::numeric_limits<RealType>::infinity();
}
if(k == 0)
{
return log(p); // success_fraction
}
//RealType q = 1 - p; // Bad for small p
//RealType probability = 1 - std::pow(q, k+1);
RealType z = boost::math::log1p(-p, Policy()) * (k + 1);
return log1p(-exp(z), Policy());
} // logcdf Cumulative Distribution Function geometric.
template <class RealType, class Policy>
inline RealType cdf(const complemented2_type<geometric_distribution<RealType, Policy>, RealType>& c)
{ // Complemented Cumulative Distribution Function geometric.
BOOST_MATH_STD_USING
static const char* function = "boost::math::cdf(const geometric_distribution<%1%>&, %1%)";
// k argument may be integral, signed, or unsigned, or floating point.
@@ -403,6 +435,30 @@ namespace boost
return probability;
} // cdf Complemented Cumulative Distribution Function geometric.
template <class RealType, class Policy>
inline RealType logcdf(const complemented2_type<geometric_distribution<RealType, Policy>, RealType>& c)
{ // Complemented Cumulative Distribution Function geometric.
BOOST_MATH_STD_USING
static const char* function = "boost::math::logcdf(const geometric_distribution<%1%>&, %1%)";
// k argument may be integral, signed, or unsigned, or floating point.
// If necessary, it has already been promoted from an integral type.
RealType const& k = c.param;
geometric_distribution<RealType, Policy> const& dist = c.dist;
RealType p = dist.success_fraction();
// Error check:
RealType result = 0;
if(false == geometric_detail::check_dist_and_k(
function,
p,
k,
&result, Policy()))
{
return -std::numeric_limits<RealType>::infinity();
}
return boost::math::log1p(-p, Policy()) * (k+1);
} // logcdf Complemented Cumulative Distribution Function geometric.
template <class RealType, class Policy>
inline RealType quantile(const geometric_distribution<RealType, Policy>& dist, const RealType& x)
{ // Quantile, percentile/100 or Percent Point geometric function.
@@ -446,7 +502,7 @@ namespace boost
{
return 0;
}
// log(1-x) /log(1-success_fraction) -1; but use log1p in case success_fraction is small
result = boost::math::log1p(-x, Policy()) / boost::math::log1p(-success_fraction, Policy()) - 1;
// Subtract a few epsilons here too?

View File

@@ -15,8 +15,7 @@
#ifndef BOOST_MATH_DISTRIBUTIONS_HYPEREXPONENTIAL_HPP
#define BOOST_MATH_DISTRIBUTIONS_HYPEREXPONENTIAL_HPP
#include <boost/config.hpp>
#include <boost/math/tools/cxx03_warn.hpp>
#include <boost/math/distributions/complement.hpp>
#include <boost/math/distributions/detail/common_error_handling.hpp>
#include <boost/math/distributions/exponential.hpp>
@@ -24,20 +23,16 @@
#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 <boost/math/tools/is_detected.hpp>
#include <cstddef>
#include <iterator>
#include <limits>
#include <numeric>
#include <utility>
#include <vector>
#include <type_traits>
#include <initializer_list>
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
# include <initializer_list>
#endif
#ifdef _MSC_VER
# pragma warning (push)
@@ -142,7 +137,7 @@ bool check_dist(char const* function, std::vector<RealT> const& probabilities, s
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%.",
R"(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;
@@ -277,16 +272,29 @@ class hyperexponential_distribution
&err,
PolicyT());
}
private: template <typename T, typename = void>
struct is_iterator
{
static constexpr bool value = false;
};
// Two arg constructor from 2 ranges, we SFINAE this out of existance if
template <typename T>
struct is_iterator<T, boost::math::tools::void_t<typename std::iterator_traits<T>::difference_type>>
{
// std::iterator_traits<T>::difference_type returns void for invalid types
static constexpr bool value = !std::is_same<typename std::iterator_traits<T>::difference_type, void>::value;
};
// Two arg constructor from 2 ranges, we SFINAE this out of existence if
// either argument type is incrementable as in that case the type is
// probably an iterator:
public: template <typename ProbRangeT, typename RateRangeT>
public: template <typename ProbRangeT, typename RateRangeT,
typename std::enable_if<!is_iterator<ProbRangeT>::value &&
!is_iterator<RateRangeT>::value, bool>::type = true>
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))
RateRangeT const& rate_range)
: probs_(std::begin(prob_range), std::end(prob_range)),
rates_(std::begin(rate_range), std::end(rate_range))
{
hyperexp_detail::normalize(probs_);
@@ -299,13 +307,14 @@ class hyperexponential_distribution
}
// Two arg constructor for a pair of iterators: we SFINAE this out of
// existance if neither argument types are incrementable.
// existence 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>
public: template <typename RateIterT, typename RateIterT2,
typename std::enable_if<is_iterator<RateIterT>::value ||
is_iterator<RateIterT2>::value, bool>::type = true>
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)
RateIterT2 const& rate_last)
: probs_(std::distance(rate_first, rate_last), 1), // will be normalized below
rates_(rate_first, rate_last)
{
@@ -319,7 +328,6 @@ class hyperexponential_distribution
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()),
@@ -348,13 +356,12 @@ public: hyperexponential_distribution(std::initializer_list<RealT> l1)
&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))
: probs_(std::distance(std::begin(rate_range), std::end(rate_range)), 1), // will be normalized below
rates_(std::begin(rate_range), std::end(rate_range))
{
hyperexp_detail::normalize(probs_);
@@ -622,7 +629,7 @@ RealT mode(hyperexponential_distribution<RealT,PolicyT> const& /*dist*/)
}} // namespace boost::math
#ifdef BOOST_MSVC
#ifdef _MSC_VER
#pragma warning (pop)
#endif
// This include must be at the end, *after* the accessors

View File

@@ -1,5 +1,6 @@
// Copyright 2008 Gautam Sewani
// Copyright 2008 John Maddock
// Copyright 2021 Paul A. Bristow
//
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
@@ -15,7 +16,7 @@
#include <boost/math/distributions/detail/hypergeometric_cdf.hpp>
#include <boost/math/distributions/detail/hypergeometric_quantile.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
#include <cstdint>
namespace boost { namespace math {
@@ -26,7 +27,7 @@ namespace boost { namespace math {
typedef RealType value_type;
typedef Policy policy_type;
hypergeometric_distribution(unsigned r, unsigned n, unsigned N) // Constructor.
hypergeometric_distribution(std::uint64_t r, std::uint64_t n, std::uint64_t N) // Constructor. r=defective/failures/success, n=trials/draws, N=total population.
: m_n(n), m_N(N), m_r(r)
{
static const char* function = "boost::math::hypergeometric_distribution<%1%>::hypergeometric_distribution";
@@ -34,17 +35,17 @@ namespace boost { namespace math {
check_params(function, &ret);
}
// Accessor functions.
unsigned total()const
std::uint64_t total() const
{
return m_N;
}
unsigned defective()const
std::uint64_t defective() const // successes/failures/events
{
return m_r;
}
unsigned sample_count()const
std::uint64_t sample_count()const
{
return m_n;
}
@@ -65,9 +66,9 @@ namespace boost { namespace math {
}
return true;
}
bool check_x(unsigned x, const char* function, RealType* result)const
bool check_x(std::uint64_t x, const char* function, RealType* result)const
{
if(x < static_cast<unsigned>((std::max)(0, (int)(m_n + m_r) - (int)(m_N))))
if(x < static_cast<std::uint64_t>((std::max)(INT64_C(0), static_cast<std::int64_t>(m_n + m_r) - static_cast<std::int64_t>(m_N))))
{
*result = boost::math::policies::raise_domain_error<RealType>(
function, "Random variable out of range: must be > 0 and > m + r - N but got %1%", static_cast<RealType>(x), Policy());
@@ -84,40 +85,40 @@ namespace boost { namespace math {
private:
// Data members:
unsigned m_n; // number of items picked
unsigned m_N; // number of "total" items
unsigned m_r; // number of "defective" items
std::uint64_t m_n; // number of items picked or drawn.
std::uint64_t m_N; // number of "total" items.
std::uint64_t m_r; // number of "defective/successes/failures/events items.
}; // class hypergeometric_distribution
typedef hypergeometric_distribution<double> hypergeometric;
template <class RealType, class Policy>
inline const std::pair<unsigned, unsigned> range(const hypergeometric_distribution<RealType, Policy>& dist)
inline const std::pair<std::uint64_t, std::uint64_t> range(const hypergeometric_distribution<RealType, Policy>& dist)
{ // Range of permissible values for random variable x.
#ifdef BOOST_MSVC
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable:4267)
#endif
unsigned r = dist.defective();
unsigned n = dist.sample_count();
unsigned N = dist.total();
unsigned l = static_cast<unsigned>((std::max)(0, (int)(n + r) - (int)(N)));
unsigned u = (std::min)(r, n);
return std::pair<unsigned, unsigned>(l, u);
#ifdef BOOST_MSVC
const auto r = dist.defective();
const auto n = dist.sample_count();
const auto N = dist.total();
const auto l = static_cast<std::uint64_t>((std::max)(INT64_C(0), static_cast<std::int64_t>(n + r) - static_cast<std::int64_t>(N)));
const auto u = (std::min)(r, n);
return std::make_pair(l, u);
#ifdef _MSC_VER
# pragma warning(pop)
#endif
}
template <class RealType, class Policy>
inline const std::pair<unsigned, unsigned> support(const hypergeometric_distribution<RealType, Policy>& d)
{
inline const std::pair<std::uint64_t, std::uint64_t> support(const hypergeometric_distribution<RealType, Policy>& d)
{
return range(d);
}
template <class RealType, class Policy>
inline RealType pdf(const hypergeometric_distribution<RealType, Policy>& dist, const unsigned& x)
inline RealType pdf(const hypergeometric_distribution<RealType, Policy>& dist, const std::uint64_t& x)
{
static const char* function = "boost::math::pdf(const hypergeometric_distribution<%1%>&, const %1%&)";
RealType result = 0;
@@ -136,7 +137,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, typename policies::normalise<Policy, policies::rounding_error<policies::ignore_error> >::type());
auto u = static_cast<std::uint64_t>(lltrunc(r, typename policies::normalise<Policy, policies::rounding_error<policies::ignore_error> >::type()));
if(u != r)
{
return boost::math::policies::raise_domain_error<RealType>(
@@ -146,7 +147,7 @@ namespace boost { namespace math {
}
template <class RealType, class Policy>
inline RealType cdf(const hypergeometric_distribution<RealType, Policy>& dist, const unsigned& x)
inline RealType cdf(const hypergeometric_distribution<RealType, Policy>& dist, const std::uint64_t& x)
{
static const char* function = "boost::math::cdf(const hypergeometric_distribution<%1%>&, const %1%&)";
RealType result = 0;
@@ -165,7 +166,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, typename policies::normalise<Policy, policies::rounding_error<policies::ignore_error> >::type());
auto u = static_cast<std::uint64_t>(lltrunc(r, typename policies::normalise<Policy, policies::rounding_error<policies::ignore_error> >::type()));
if(u != r)
{
return boost::math::policies::raise_domain_error<RealType>(
@@ -175,7 +176,7 @@ namespace boost { namespace math {
}
template <class RealType, class Policy>
inline RealType cdf(const complemented2_type<hypergeometric_distribution<RealType, Policy>, unsigned>& c)
inline RealType cdf(const complemented2_type<hypergeometric_distribution<RealType, Policy>, std::uint64_t>& c)
{
static const char* function = "boost::math::cdf(const hypergeometric_distribution<%1%>&, const %1%&)";
RealType result = 0;
@@ -194,7 +195,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, typename policies::normalise<Policy, policies::rounding_error<policies::ignore_error> >::type());
auto u = static_cast<std::uint64_t>(lltrunc(r, typename policies::normalise<Policy, policies::rounding_error<policies::ignore_error> >::type()));
if(u != r)
{
return boost::math::policies::raise_domain_error<RealType>(
@@ -208,11 +209,14 @@ namespace boost { namespace math {
{
BOOST_MATH_STD_USING // for ADL of std functions
// Checking function argument
RealType result = 0;
// Checking function argument
RealType result = 0;
const char* function = "boost::math::quantile(const hypergeometric_distribution<%1%>&, %1%)";
if (false == dist.check_params(function, &result)) return result;
if(false == detail::check_probability(function, p, &result, Policy())) return result;
if (false == dist.check_params(function, &result))
return result;
if(false == detail::check_probability(function, p, &result, Policy()))
return result;
return static_cast<RealType>(detail::hypergeometric_quantile(p, RealType(1 - p), dist.defective(), dist.sample_count(), dist.total(), Policy()));
} // quantile
@@ -225,12 +229,16 @@ namespace boost { namespace math {
// Checking function argument
RealType result = 0;
const char* function = "quantile(const complemented2_type<hypergeometric_distribution<%1%>, %1%>&)";
if (false == c.dist.check_params(function, &result)) return result;
if(false == detail::check_probability(function, c.param, &result, Policy())) return result;
if (false == c.dist.check_params(function, &result))
return result;
if (false == detail::check_probability(function, c.param, &result, Policy()))
return result;
return static_cast<RealType>(detail::hypergeometric_quantile(RealType(1 - c.param), c.param, c.dist.defective(), c.dist.sample_count(), c.dist.total(), Policy()));
} // quantile
// https://www.wolframalpha.com/input/?i=kurtosis+hypergeometric+distribution
template <class RealType, class Policy>
inline RealType mean(const hypergeometric_distribution<RealType, Policy>& dist)
{
@@ -269,13 +277,23 @@ namespace boost { namespace math {
template <class RealType, class Policy>
inline RealType kurtosis_excess(const hypergeometric_distribution<RealType, Policy>& dist)
{
RealType r = static_cast<RealType>(dist.defective());
RealType n = static_cast<RealType>(dist.sample_count());
RealType N = static_cast<RealType>(dist.total());
RealType t1 = N * N * (N - 1) / (r * (N - 2) * (N - 3) * (N - r));
RealType t2 = (N * (N + 1) - 6 * N * (N - r)) / (n * (N - n))
+ 3 * r * (N - r) * (N + 6) / (N * N) - 6;
return t1 * t2;
// https://www.wolframalpha.com/input/?i=kurtosis+hypergeometric+distribution shown as plain text:
// mean | (m n)/N
// standard deviation | sqrt((m n(N - m) (N - n))/(N - 1))/N
// variance | (m n(1 - m/N) (N - n))/((N - 1) N)
// skewness | (sqrt(N - 1) (N - 2 m) (N - 2 n))/((N - 2) sqrt(m n(N - m) (N - n)))
// kurtosis | ((N - 1) N^2 ((3 m(N - m) (n^2 (-N) + (n - 2) N^2 + 6 n(N - n)))/N^2 - 6 n(N - n) + N(N + 1)))/(m n(N - 3) (N - 2) (N - m) (N - n))
// Kurtosis[HypergeometricDistribution[n, m, N]]
RealType m = static_cast<RealType>(dist.defective()); // Failures or success events. (Also symbols K or M are used).
RealType n = static_cast<RealType>(dist.sample_count()); // draws or trials.
RealType n2 = n * n; // n^2
RealType N = static_cast<RealType>(dist.total()); // Total population from which n draws or trials are made.
RealType N2 = N * N; // N^2
// result = ((N - 1) N^2 ((3 m(N - m) (n^2 (-N) + (n - 2) N^2 + 6 n(N - n)))/N^2 - 6 n(N - n) + N(N + 1)))/(m n(N - 3) (N - 2) (N - m) (N - n));
RealType result = ((N-1)*N2*((3*m*(N-m)*(n2*(-N)+(n-2)*N2+6*n*(N-n)))/N2-6*n*(N-n)+N*(N+1)))/(m*n*(N-3)*(N-2)*(N-m)*(N-n));
// Agrees with kurtosis hypergeometric distribution(50,200,500) kurtosis = 2.96917
// N[kurtosis[hypergeometricdistribution(50,200,500)], 55] 2.969174035736058474901169623721804275002985337280263464
return result;
} // RealType kurtosis_excess(const hypergeometric_distribution<RealType, Policy>& dist)
template <class RealType, class Policy>

View File

@@ -97,6 +97,13 @@ private:
typedef inverse_chi_squared_distribution<double> inverse_chi_squared;
#ifdef __cpp_deduction_guides
template <class RealType>
inverse_chi_squared_distribution(RealType)->inverse_chi_squared_distribution<typename boost::math::tools::promote_args<RealType>::type>;
template <class RealType>
inverse_chi_squared_distribution(RealType,RealType)->inverse_chi_squared_distribution<typename boost::math::tools::promote_args<RealType>::type>;
#endif
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const inverse_chi_squared_distribution<RealType, Policy>& /*dist*/)
{ // Range of permissible values for random variable x.

View File

@@ -28,6 +28,7 @@
#include <boost/math/distributions/complement.hpp>
#include <utility>
#include <cfenv>
namespace boost{ namespace math
{
@@ -88,10 +89,10 @@ template <class RealType = double, class Policy = policies::policy<> >
class inverse_gamma_distribution
{
public:
typedef RealType value_type;
typedef Policy policy_type;
using value_type = RealType;
using policy_type = Policy;
inverse_gamma_distribution(RealType l_shape = 1, RealType l_scale = 1)
explicit inverse_gamma_distribution(RealType l_shape = 1, RealType l_scale = 1)
: m_shape(l_shape), m_scale(l_scale)
{
RealType result;
@@ -117,22 +118,28 @@ private:
RealType m_scale; // distribution scale
};
typedef inverse_gamma_distribution<double> inverse_gamma;
using inverse_gamma = inverse_gamma_distribution<double>;
// typedef - but potential clash with name of inverse gamma *function*.
// but there is a typedef for gamma
// typedef boost::math::gamma_distribution<Type, Policy> gamma;
// but there is a typedef for the gamma distribution (gamma)
#ifdef __cpp_deduction_guides
template <class RealType>
inverse_gamma_distribution(RealType)->inverse_gamma_distribution<typename boost::math::tools::promote_args<RealType>::type>;
template <class RealType>
inverse_gamma_distribution(RealType,RealType)->inverse_gamma_distribution<typename boost::math::tools::promote_args<RealType>::type>;
#endif
// Allow random variable x to be zero, treated as a special case (unlike some definitions).
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const inverse_gamma_distribution<RealType, Policy>& /* dist */)
inline std::pair<RealType, RealType> range(const inverse_gamma_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>());
}
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> support(const inverse_gamma_distribution<RealType, Policy>& /* dist */)
inline std::pair<RealType, RealType> support(const inverse_gamma_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.
using boost::math::tools::max_value;
@@ -183,11 +190,47 @@ inline RealType pdf(const inverse_gamma_distribution<RealType, Policy>& dist, co
}
result /= (x * x);
}
// better than naive
// result = (pow(scale, shape) * pow(x, (-shape -1)) * exp(-scale/x) ) / tgamma(shape);
return result;
} // pdf
template <class RealType, class Policy>
inline RealType logpdf(const inverse_gamma_distribution<RealType, Policy>& dist, const RealType& x)
{
BOOST_MATH_STD_USING // for ADL of std functions
using boost::math::lgamma;
static const char* function = "boost::math::logpdf(const inverse_gamma_distribution<%1%>&, %1%)";
RealType shape = dist.shape();
RealType scale = dist.scale();
RealType result = -std::numeric_limits<RealType>::infinity();
if(false == detail::check_inverse_gamma(function, scale, shape, &result, Policy()))
{ // distribution parameters bad.
return result;
}
if(x == 0)
{ // Treat random variate zero as a special case.
return result;
}
else if(false == detail::check_inverse_gamma_x(function, x, &result, Policy()))
{ // x bad.
return result;
}
result = scale / x;
if(result < tools::min_value<RealType>())
return result; // random variable is infinite or so close as to make no difference.
// x * x may under or overflow, likewise our result
if (!(boost::math::isfinite)(x*x))
{
return policies::raise_overflow_error<RealType, Policy>(function, "PDF is infinite.", Policy());
}
return shape * log(scale) + (-shape-1)*log(x) - lgamma(shape) - (scale/x);
} // pdf
template <class RealType, class Policy>
inline RealType cdf(const inverse_gamma_distribution<RealType, Policy>& dist, const RealType& x)
{
@@ -262,7 +305,6 @@ inline RealType cdf(const complemented2_type<inverse_gamma_distribution<RealType
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;
}

View File

@@ -55,13 +55,9 @@
#include <boost/math/distributions/detail/common_error_handling.hpp>
#include <boost/math/distributions/normal.hpp>
#include <boost/math/distributions/gamma.hpp> // for gamma function
// using boost::math::gamma_p;
#include <boost/math/tools/tuple.hpp>
//using std::tr1::tuple;
//using std::tr1::make_tuple;
#include <boost/math/tools/roots.hpp>
//using boost::math::tools::newton_raphson_iterate;
#include <utility>
@@ -71,10 +67,10 @@ template <class RealType = double, class Policy = policies::policy<> >
class inverse_gaussian_distribution
{
public:
typedef RealType value_type;
typedef Policy policy_type;
using value_type = RealType;
using policy_type = Policy;
inverse_gaussian_distribution(RealType l_mean = 1, RealType l_scale = 1)
explicit 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";
@@ -113,17 +109,24 @@ private:
RealType m_scale; // distribution standard deviation or scale, aka lambda.
}; // class normal_distribution
typedef inverse_gaussian_distribution<double> inverse_gaussian;
using inverse_gaussian = inverse_gaussian_distribution<double>;
#ifdef __cpp_deduction_guides
template <class RealType>
inverse_gaussian_distribution(RealType)->inverse_gaussian_distribution<typename boost::math::tools::promote_args<RealType>::type>;
template <class RealType>
inverse_gaussian_distribution(RealType,RealType)->inverse_gaussian_distribution<typename boost::math::tools::promote_args<RealType>::type>;
#endif
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const inverse_gaussian_distribution<RealType, Policy>& /*dist*/)
inline std::pair<RealType, RealType> range(const inverse_gaussian_distribution<RealType, Policy>& /*dist*/)
{ // Range of permissible values for random variable x, zero to max.
using boost::math::tools::max_value;
return std::pair<RealType, RealType>(static_cast<RealType>(0.), max_value<RealType>()); // - to + max value.
}
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> support(const inverse_gaussian_distribution<RealType, Policy>& /*dist*/)
inline std::pair<RealType, RealType> support(const inverse_gaussian_distribution<RealType, Policy>& /*dist*/)
{ // Range of supported values for random variable x, zero to max.
// This is range where cdf rises from 0 to 1, and outside it, the pdf is zero.
using boost::math::tools::max_value;
@@ -167,6 +170,43 @@ inline RealType pdf(const inverse_gaussian_distribution<RealType, Policy>& dist,
return result;
} // pdf
template <class RealType, class Policy>
inline RealType logpdf(const inverse_gaussian_distribution<RealType, Policy>& dist, const RealType& x)
{ // Probability Density Function
BOOST_MATH_STD_USING // for ADL of std functions
RealType scale = dist.scale();
RealType mean = dist.mean();
RealType result = -std::numeric_limits<RealType>::infinity();
static const char* function = "boost::math::logpdf(const inverse_gaussian_distribution<%1%>&, %1%)";
if(false == detail::check_scale(function, scale, &result, Policy()))
{
return result;
}
if(false == detail::check_location(function, mean, &result, Policy()))
{
return result;
}
if(false == detail::check_x_gt0(function, mean, &result, Policy()))
{
return result;
}
if(false == detail::check_positive_x(function, x, &result, Policy()))
{
return result;
}
if (x == 0)
{
return std::numeric_limits<RealType>::quiet_NaN(); // Convenient, even if not defined mathematically. log(0)
}
const RealType two_pi = boost::math::constants::two_pi<RealType>();
result = (-scale*pow(mean - x, RealType(2))/(mean*mean*x) + log(scale) - 3*log(x) - log(two_pi)) / 2;
return result;
} // pdf
template <class RealType, class Policy>
inline RealType cdf(const inverse_gaussian_distribution<RealType, Policy>& dist, const RealType& x)
{ // Cumulative Density Function.
@@ -196,10 +236,7 @@ inline RealType cdf(const inverse_gaussian_distribution<RealType, Policy>& dist,
{
return 0; // Convenient, even if not defined mathematically.
}
// Problem with this formula for large scale > 1000 or small x,
//result = 0.5 * (erf(sqrt(scale / x) * ((x / mean) - 1) / constants::root_two<RealType>(), Policy()) + 1)
// + exp(2 * scale / mean) / 2
// * (1 - erf(sqrt(scale / x) * (x / mean + 1) / constants::root_two<RealType>(), Policy()));
// Problem with this formula for large scale > 1000 or small x
// so use normal distribution version:
// Wikipedia CDF equation http://en.wikipedia.org/wiki/Inverse_Gaussian_distribution.
@@ -263,22 +300,20 @@ namespace detail
template <class RealType>
inline RealType guess_ig(RealType p, RealType mu = 1, RealType lambda = 1)
{ // guess at random variate value x for inverse gaussian quantile.
BOOST_MATH_STD_USING
using boost::math::policies::policy;
// Error type.
using boost::math::policies::overflow_error;
// Action.
using boost::math::policies::ignore_error;
BOOST_MATH_STD_USING
using boost::math::policies::policy;
// Error type.
using boost::math::policies::overflow_error;
// Action.
using boost::math::policies::ignore_error;
typedef policy<
overflow_error<ignore_error> // Ignore overflow (return infinity)
> no_overthrow_policy;
using no_overthrow_policy = policy<overflow_error<ignore_error>>;
RealType x; // result is guess at random variate value x.
RealType phi = lambda / mu;
if (phi > 2.)
{ // Big phi, so starting to look like normal Gaussian distribution.
// x=(qnorm(p,0,1,true,false) - 0.5 * sqrt(mu/lambda)) / sqrt(lambda/mu);
//
// Whitmore, G.A. and Yalovsky, M.
// A normalising logarithmic transformation for inverse Gaussian random variables,
// Technometrics 20-2, 207-208 (1978), but using expression from
@@ -293,14 +328,12 @@ namespace detail
using boost::math::gamma_distribution;
// Define the distribution, using gamma_nooverflow:
typedef gamma_distribution<RealType, no_overthrow_policy> gamma_nooverflow;
using gamma_nooverflow = gamma_distribution<RealType, no_overthrow_policy>;
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
// R qgamma(0.2, 0.5, 1) = 0.0320923
RealType qg = quantile(complement(g, p));
//RealType qg1 = qgamma(1.- p, 0.5, 1.0, true, false);
x = lambda / (qg * 2);
//
if (x > mu/2) // x > mu /2?
@@ -343,19 +376,19 @@ inline RealType quantile(const inverse_gaussian_distribution<RealType, Policy>&
{ // overflow
result = policies::raise_overflow_error<RealType>(function,
"probability parameter is 1, but must be < 1!", Policy());
return result; // std::numeric_limits<RealType>::infinity();
return result; // infinity;
}
RealType guess = detail::guess_ig(p, dist.mean(), dist.scale());
using boost::math::tools::max_value;
RealType min = 0.; // Minimum possible value is bottom of range of distribution.
RealType min = static_cast<RealType>(0); // Minimum possible value is bottom of range of distribution.
RealType max = max_value<RealType>();// Maximum possible value is top of range.
// int digits = std::numeric_limits<RealType>::digits; // Maximum possible binary digits accuracy for type T.
// digits used to control how accurate to try to make the result.
// To allow user to control accuracy versus speed,
int get_digits = policies::digits<RealType, Policy>();// get digits from policy,
boost::uintmax_t m = policies::get_max_root_iterations<Policy>(); // and max iterations.
std::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, Policy>(dist, p), guess, min, max, get_digits, m);
@@ -371,21 +404,7 @@ inline RealType cdf(const complemented2_type<inverse_gaussian_distribution<RealT
RealType mean = c.dist.mean();
RealType x = c.param;
static const char* function = "boost::math::cdf(const complement(inverse_gaussian_distribution<%1%>&), %1%)";
// infinite arguments not supported.
//if((boost::math::isinf)(x))
//{
// if(x < 0) return 1; // cdf complement -infinity is unity.
// return 0; // cdf complement +infinity is zero
//}
// These produce MSVC 4127 warnings, so the above used instead.
//if(std::numeric_limits<RealType>::has_infinity && x == std::numeric_limits<RealType>::infinity())
//{ // cdf complement +infinity is zero.
// return 0;
//}
//if(std::numeric_limits<RealType>::has_infinity && x == -std::numeric_limits<RealType>::infinity())
//{ // cdf complement -infinity is unity.
// return 1;
//}
RealType result = 0;
if(false == detail::check_scale(function, scale, &result, Policy()))
return result;
@@ -435,12 +454,12 @@ inline RealType quantile(const complemented2_type<inverse_gaussian_distribution<
// Complement.
using boost::math::tools::max_value;
RealType min = 0.; // Minimum possible value is bottom of range of distribution.
RealType min = static_cast<RealType>(0); // Minimum possible value is bottom of range of distribution.
RealType max = max_value<RealType>();// Maximum possible value is top of range.
// int digits = std::numeric_limits<RealType>::digits; // Maximum possible binary digits accuracy for type T.
// digits used to control how accurate to try to make the result.
int get_digits = policies::digits<RealType, Policy>();
boost::uintmax_t m = policies::get_max_root_iterations<Policy>();
std::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, Policy>(c.dist, q), guess, min, max, get_digits, m);

View File

@@ -0,0 +1,499 @@
// Kolmogorov-Smirnov 1st order asymptotic distribution
// Copyright Evan Miller 2020
//
// 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)
//
// The Kolmogorov-Smirnov test in statistics compares two empirical distributions,
// or an empirical distribution against any theoretical distribution. It makes
// use of a specific distribution which doesn't have a formal name, but which
// is often called the Kolmogorv-Smirnov distribution for lack of anything
// better. This file implements the limiting form of this distribution, first
// identified by Andrey Kolmogorov in
//
// Kolmogorov, A. (1933) "Sulla Determinazione Empirica di una Legge di
// Distribuzione." Giornale dell' Istituto Italiano degli Attuari
//
// This limiting form of the CDF is a first-order Taylor expansion that is
// easily implemented by the fourth Jacobi Theta function (setting z=0). The
// PDF is then implemented here as a derivative of the Theta function. Note
// that this derivative is with respect to x, which enters into \tau, and not
// with respect to the z argument, which is always zero, and so the derivative
// identities in DLMF 20.4 do not apply here.
//
// A higher order order expansion is possible, and was first outlined by
//
// Pelz W, Good IJ (1976). "Approximating the Lower Tail-Areas of the
// Kolmogorov-Smirnov One-sample Statistic." Journal of the Royal Statistical
// Society B.
//
// The terms in this expansion get fairly complicated, and as far as I know the
// Pelz-Good expansion is not used in any statistics software. Someone could
// consider updating this implementation to use the Pelz-Good expansion in the
// future, but the math gets considerably hairier with each additional term.
//
// A formula for an exact version of the Kolmogorov-Smirnov test is laid out in
// Equation 2.4.4 of
//
// Durbin J (1973). "Distribution Theory for Tests Based on the Sample
// Distribution Func- tion." In SIAM CBMS-NSF Regional Conference Series in
// Applied Mathematics. SIAM, Philadelphia, PA.
//
// which is available in book form from Amazon and others. This exact version
// involves taking powers of large matrices. To do that right you need to
// compute eigenvalues and eigenvectors, which are beyond the scope of Boost.
// (Some recent work indicates the exact form can also be computed via FFT, see
// https://cran.r-project.org/web/packages/KSgeneral/KSgeneral.pdf).
//
// Even if the CDF of the exact distribution could be computed using Boost
// libraries (which would be cumbersome), the PDF would present another
// difficulty. Therefore I am limiting this implementation to the asymptotic
// form, even though the exact form has trivial values for certain specific
// values of x and n. For more on trivial values see
//
// Ruben H, Gambino J (1982). "The Exact Distribution of Kolmogorov's Statistic
// Dn for n <= 10." Annals of the Institute of Statistical Mathematics.
//
// For a good bibliography and overview of the various algorithms, including
// both exact and asymptotic forms, see
// https://www.jstatsoft.org/article/view/v039i11
//
// As for this implementation: the distribution is parameterized by n (number
// of observations) in the spirit of chi-squared's degrees of freedom. It then
// takes a single argument x. In terms of the Kolmogorov-Smirnov statistical
// test, x represents the distribution of D_n, where D_n is the maximum
// difference between the CDFs being compared, that is,
//
// D_n = sup|F_n(x) - G(x)|
//
// In the exact distribution, x is confined to the support [0, 1], but in this
// limiting approximation, we allow x to exceed unity (similar to how a normal
// approximation always spills over any boundaries).
//
// As mentioned previously, the CDF is implemented using the \tau
// parameterization of the fourth Jacobi Theta function as
//
// CDF=theta_4(0|2*x*x*n/pi)
//
// The PDF is a hand-coded derivative of that function. Actually, there are two
// (independent) derivatives, as separate code paths are used for "small x"
// (2*x*x*n < pi) and "large x", mirroring the separate code paths in the
// Jacobi Theta implementation to achieve fast convergence. Quantiles are
// computed using a Newton-Raphson iteration from an initial guess that I
// arrived at by trial and error.
//
// The mean and variance are implemented using simple closed-form expressions.
// Skewness and kurtosis use slightly more complicated closed-form expressions
// that involve the zeta function. The mode is calculated at run-time by
// maximizing the PDF. If you have an analytical solution for the mode, feel
// free to plop it in.
//
// The CDF and PDF could almost certainly be re-implemented and sped up using a
// polynomial or rational approximation, since the only meaningful argument is
// x * sqrt(n). But that is left as an exercise for the next maintainer.
//
// In the future, the Pelz-Good approximation could be added. I suggest adding
// a second parameter representing the order, e.g.
//
// kolmogorov_smirnov_dist<>(100) // N=100, order=1
// kolmogorov_smirnov_dist<>(100, 1) // N=100, order=1, i.e. Kolmogorov's formula
// kolmogorov_smirnov_dist<>(100, 4) // N=100, order=4, i.e. Pelz-Good formula
//
// The exact distribution could be added to the API with a special order
// parameter (e.g. 0 or infinity), or a separate distribution type altogether
// (e.g. kolmogorov_smirnov_exact_distribution).
//
#ifndef BOOST_MATH_DISTRIBUTIONS_KOLMOGOROV_SMIRNOV_HPP
#define BOOST_MATH_DISTRIBUTIONS_KOLMOGOROV_SMIRNOV_HPP
#include <boost/math/distributions/fwd.hpp>
#include <boost/math/distributions/complement.hpp>
#include <boost/math/distributions/detail/common_error_handling.hpp>
#include <boost/math/special_functions/jacobi_theta.hpp>
#include <boost/math/tools/tuple.hpp>
#include <boost/math/tools/roots.hpp> // Newton-Raphson
#include <boost/math/tools/minima.hpp> // For the mode
namespace boost { namespace math {
namespace detail {
template <class RealType>
inline RealType kolmogorov_smirnov_quantile_guess(RealType p) {
// Choose a starting point for the Newton-Raphson iteration
if (p > 0.9)
return RealType(1.8) - 5 * (1 - p);
if (p < 0.3)
return p + RealType(0.45);
return p + RealType(0.3);
}
// d/dk (theta2(0, 1/(2*k*k/M_PI))/sqrt(2*k*k*M_PI))
template <class RealType, class Policy>
RealType kolmogorov_smirnov_pdf_small_x(RealType x, RealType n, const Policy&) {
BOOST_MATH_STD_USING
RealType value = RealType(0), delta = RealType(0), last_delta = RealType(0);
RealType eps = policies::get_epsilon<RealType, Policy>();
int i = 0;
RealType pi2 = constants::pi_sqr<RealType>();
RealType x2n = x*x*n;
if (x2n*x2n == 0.0) {
return static_cast<RealType>(0);
}
while (true) {
delta = exp(-RealType(i+0.5)*RealType(i+0.5)*pi2/(2*x2n)) * (RealType(i+0.5)*RealType(i+0.5)*pi2 - x2n);
if (delta == 0.0)
break;
if (last_delta != 0.0 && fabs(delta/last_delta) < eps)
break;
value += delta + delta;
last_delta = delta;
i++;
}
return value * sqrt(n) * constants::root_half_pi<RealType>() / (x2n*x2n);
}
// d/dx (theta4(0, 2*x*x*n/M_PI))
template <class RealType, class Policy>
inline RealType kolmogorov_smirnov_pdf_large_x(RealType x, RealType n, const Policy&) {
BOOST_MATH_STD_USING
RealType value = RealType(0), delta = RealType(0), last_delta = RealType(0);
RealType eps = policies::get_epsilon<RealType, Policy>();
int i = 1;
while (true) {
delta = 8*x*i*i*exp(-2*i*i*x*x*n);
if (delta == 0.0)
break;
if (last_delta != 0.0 && fabs(delta / last_delta) < eps)
break;
if (i%2 == 0)
delta = -delta;
value += delta;
last_delta = delta;
i++;
}
return value * n;
}
} // detail
template <class RealType = double, class Policy = policies::policy<> >
class kolmogorov_smirnov_distribution
{
public:
typedef RealType value_type;
typedef Policy policy_type;
// Constructor
kolmogorov_smirnov_distribution( RealType n ) : n_obs_(n)
{
RealType result;
detail::check_df(
"boost::math::kolmogorov_smirnov_distribution<%1%>::kolmogorov_smirnov_distribution", n_obs_, &result, Policy());
}
RealType number_of_observations()const
{
return n_obs_;
}
private:
RealType n_obs_; // positive integer
};
typedef kolmogorov_smirnov_distribution<double> kolmogorov_k; // Convenience typedef for double version.
#ifdef __cpp_deduction_guides
template <class RealType>
kolmogorov_smirnov_distribution(RealType)->kolmogorov_smirnov_distribution<typename boost::math::tools::promote_args<RealType>::type>;
#endif
namespace detail {
template <class RealType, class Policy>
struct kolmogorov_smirnov_quantile_functor
{
kolmogorov_smirnov_quantile_functor(const boost::math::kolmogorov_smirnov_distribution<RealType, Policy> dist, RealType const& p)
: distribution(dist), prob(p)
{
}
boost::math::tuple<RealType, RealType> operator()(RealType const& x)
{
RealType fx = cdf(distribution, x) - prob; // Difference cdf - value - to minimize.
RealType dx = pdf(distribution, x); // pdf is 1st derivative.
// return both function evaluation difference f(x) and 1st derivative f'(x).
return boost::math::make_tuple(fx, dx);
}
private:
const boost::math::kolmogorov_smirnov_distribution<RealType, Policy> distribution;
RealType prob;
};
template <class RealType, class Policy>
struct kolmogorov_smirnov_complementary_quantile_functor
{
kolmogorov_smirnov_complementary_quantile_functor(const boost::math::kolmogorov_smirnov_distribution<RealType, Policy> dist, RealType const& p)
: distribution(dist), prob(p)
{
}
boost::math::tuple<RealType, RealType> operator()(RealType const& x)
{
RealType fx = cdf(complement(distribution, x)) - prob; // Difference cdf - value - to minimize.
RealType dx = -pdf(distribution, x); // pdf is the negative of the derivative of (1-CDF)
// return both function evaluation difference f(x) and 1st derivative f'(x).
return boost::math::make_tuple(fx, dx);
}
private:
const boost::math::kolmogorov_smirnov_distribution<RealType, Policy> distribution;
RealType prob;
};
template <class RealType, class Policy>
struct kolmogorov_smirnov_negative_pdf_functor
{
RealType operator()(RealType const& x) {
if (2*x*x < constants::pi<RealType>()) {
return -kolmogorov_smirnov_pdf_small_x(x, static_cast<RealType>(1), Policy());
}
return -kolmogorov_smirnov_pdf_large_x(x, static_cast<RealType>(1), Policy());
}
};
} // namespace detail
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const kolmogorov_smirnov_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>());
}
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> support(const kolmogorov_smirnov_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.
// In the exact distribution, the upper limit would be 1.
using boost::math::tools::max_value;
return std::pair<RealType, RealType>(static_cast<RealType>(0), max_value<RealType>());
}
template <class RealType, class Policy>
inline RealType pdf(const kolmogorov_smirnov_distribution<RealType, Policy>& dist, const RealType& x)
{
BOOST_FPU_EXCEPTION_GUARD
BOOST_MATH_STD_USING // for ADL of std functions.
RealType n = dist.number_of_observations();
RealType error_result;
static const char* function = "boost::math::pdf(const kolmogorov_smirnov_distribution<%1%>&, %1%)";
if(false == detail::check_x_not_NaN(function, x, &error_result, Policy()))
return error_result;
if(false == detail::check_df(function, n, &error_result, Policy()))
return error_result;
if (x < 0 || !(boost::math::isfinite)(x))
{
return policies::raise_domain_error<RealType>(
function, "Kolmogorov-Smirnov parameter was %1%, but must be > 0 !", x, Policy());
}
if (2*x*x*n < constants::pi<RealType>()) {
return detail::kolmogorov_smirnov_pdf_small_x(x, n, Policy());
}
return detail::kolmogorov_smirnov_pdf_large_x(x, n, Policy());
} // pdf
template <class RealType, class Policy>
inline RealType cdf(const kolmogorov_smirnov_distribution<RealType, Policy>& dist, const RealType& x)
{
BOOST_MATH_STD_USING // for ADL of std function exp.
static const char* function = "boost::math::cdf(const kolmogorov_smirnov_distribution<%1%>&, %1%)";
RealType error_result;
RealType n = dist.number_of_observations();
if(false == detail::check_x_not_NaN(function, x, &error_result, Policy()))
return error_result;
if(false == detail::check_df(function, n, &error_result, Policy()))
return error_result;
if((x < 0) || !(boost::math::isfinite)(x)) {
return policies::raise_domain_error<RealType>(
function, "Random variable parameter was %1%, but must be between > 0 !", x, Policy());
}
if (x*x*n == 0)
return 0;
return jacobi_theta4tau(RealType(0), 2*x*x*n/constants::pi<RealType>(), Policy());
} // cdf
template <class RealType, class Policy>
inline RealType cdf(const complemented2_type<kolmogorov_smirnov_distribution<RealType, Policy>, RealType>& c) {
BOOST_MATH_STD_USING // for ADL of std function exp.
RealType x = c.param;
static const char* function = "boost::math::cdf(const complemented2_type<const kolmogorov_smirnov_distribution<%1%>&, %1%>)";
RealType error_result;
kolmogorov_smirnov_distribution<RealType, Policy> const& dist = c.dist;
RealType n = dist.number_of_observations();
if(false == detail::check_x_not_NaN(function, x, &error_result, Policy()))
return error_result;
if(false == detail::check_df(function, n, &error_result, Policy()))
return error_result;
if((x < 0) || !(boost::math::isfinite)(x))
return policies::raise_domain_error<RealType>(
function, "Random variable parameter was %1%, but must be between > 0 !", x, Policy());
if (x*x*n == 0)
return 1;
if (2*x*x*n > constants::pi<RealType>())
return -jacobi_theta4m1tau(RealType(0), 2*x*x*n/constants::pi<RealType>(), Policy());
return RealType(1) - jacobi_theta4tau(RealType(0), 2*x*x*n/constants::pi<RealType>(), Policy());
} // cdf (complemented)
template <class RealType, class Policy>
inline RealType quantile(const kolmogorov_smirnov_distribution<RealType, Policy>& dist, const RealType& p)
{
BOOST_MATH_STD_USING
static const char* function = "boost::math::quantile(const kolmogorov_smirnov_distribution<%1%>&, %1%)";
// Error check:
RealType error_result;
RealType n = dist.number_of_observations();
if(false == detail::check_probability(function, p, &error_result, Policy()))
return error_result;
if(false == detail::check_df(function, n, &error_result, Policy()))
return error_result;
RealType k = detail::kolmogorov_smirnov_quantile_guess(p) / sqrt(n);
const int get_digits = policies::digits<RealType, Policy>();// get digits from policy,
std::uintmax_t m = policies::get_max_root_iterations<Policy>(); // and max iterations.
return tools::newton_raphson_iterate(detail::kolmogorov_smirnov_quantile_functor<RealType, Policy>(dist, p),
k, RealType(0), boost::math::tools::max_value<RealType>(), get_digits, m);
} // quantile
template <class RealType, class Policy>
inline RealType quantile(const complemented2_type<kolmogorov_smirnov_distribution<RealType, Policy>, RealType>& c) {
BOOST_MATH_STD_USING
static const char* function = "boost::math::quantile(const kolmogorov_smirnov_distribution<%1%>&, %1%)";
kolmogorov_smirnov_distribution<RealType, Policy> const& dist = c.dist;
RealType n = dist.number_of_observations();
// Error check:
RealType error_result;
RealType p = c.param;
if(false == detail::check_probability(function, p, &error_result, Policy()))
return error_result;
if(false == detail::check_df(function, n, &error_result, Policy()))
return error_result;
RealType k = detail::kolmogorov_smirnov_quantile_guess(RealType(1-p)) / sqrt(n);
const int get_digits = policies::digits<RealType, Policy>();// get digits from policy,
std::uintmax_t m = policies::get_max_root_iterations<Policy>(); // and max iterations.
return tools::newton_raphson_iterate(
detail::kolmogorov_smirnov_complementary_quantile_functor<RealType, Policy>(dist, p),
k, RealType(0), boost::math::tools::max_value<RealType>(), get_digits, m);
} // quantile (complemented)
template <class RealType, class Policy>
inline RealType mode(const kolmogorov_smirnov_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING
static const char* function = "boost::math::mode(const kolmogorov_smirnov_distribution<%1%>&)";
RealType n = dist.number_of_observations();
RealType error_result;
if(false == detail::check_df(function, n, &error_result, Policy()))
return error_result;
std::pair<RealType, RealType> r = boost::math::tools::brent_find_minima(
detail::kolmogorov_smirnov_negative_pdf_functor<RealType, Policy>(),
static_cast<RealType>(0), static_cast<RealType>(1), policies::digits<RealType, Policy>());
return r.first / sqrt(n);
}
// Mean and variance come directly from
// https://www.jstatsoft.org/article/view/v008i18 Section 3
template <class RealType, class Policy>
inline RealType mean(const kolmogorov_smirnov_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING
static const char* function = "boost::math::mean(const kolmogorov_smirnov_distribution<%1%>&)";
RealType n = dist.number_of_observations();
RealType error_result;
if(false == detail::check_df(function, n, &error_result, Policy()))
return error_result;
return constants::root_half_pi<RealType>() * constants::ln_two<RealType>() / sqrt(n);
}
template <class RealType, class Policy>
inline RealType variance(const kolmogorov_smirnov_distribution<RealType, Policy>& dist)
{
static const char* function = "boost::math::variance(const kolmogorov_smirnov_distribution<%1%>&)";
RealType n = dist.number_of_observations();
RealType error_result;
if(false == detail::check_df(function, n, &error_result, Policy()))
return error_result;
return (constants::pi_sqr_div_six<RealType>()
- constants::pi<RealType>() * constants::ln_two<RealType>() * constants::ln_two<RealType>()) / (2*n);
}
// Skewness and kurtosis come from integrating the PDF
// The alternating series pops out a Dirichlet eta function which is related to the zeta function
template <class RealType, class Policy>
inline RealType skewness(const kolmogorov_smirnov_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING
static const char* function = "boost::math::skewness(const kolmogorov_smirnov_distribution<%1%>&)";
RealType n = dist.number_of_observations();
RealType error_result;
if(false == detail::check_df(function, n, &error_result, Policy()))
return error_result;
RealType ex3 = RealType(0.5625) * constants::root_half_pi<RealType>() * constants::zeta_three<RealType>() / n / sqrt(n);
RealType mean = boost::math::mean(dist);
RealType var = boost::math::variance(dist);
return (ex3 - 3 * mean * var - mean * mean * mean) / var / sqrt(var);
}
template <class RealType, class Policy>
inline RealType kurtosis(const kolmogorov_smirnov_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING
static const char* function = "boost::math::kurtosis(const kolmogorov_smirnov_distribution<%1%>&)";
RealType n = dist.number_of_observations();
RealType error_result;
if(false == detail::check_df(function, n, &error_result, Policy()))
return error_result;
RealType ex4 = 7 * constants::pi_sqr_div_six<RealType>() * constants::pi_sqr_div_six<RealType>() / 20 / n / n;
RealType mean = boost::math::mean(dist);
RealType var = boost::math::variance(dist);
RealType skew = boost::math::skewness(dist);
return (ex4 - 4 * mean * skew * var * sqrt(var) - 6 * mean * mean * var - mean * mean * mean * mean) / var / var;
}
template <class RealType, class Policy>
inline RealType kurtosis_excess(const kolmogorov_smirnov_distribution<RealType, Policy>& dist)
{
static const char* function = "boost::math::kurtosis_excess(const kolmogorov_smirnov_distribution<%1%>&)";
RealType n = dist.number_of_observations();
RealType error_result;
if(false == detail::check_df(function, n, &error_result, Policy()))
return error_result;
return kurtosis(dist) - 3;
}
}}
#endif

View File

@@ -17,6 +17,7 @@
#ifndef BOOST_STATS_LAPLACE_HPP
#define BOOST_STATS_LAPLACE_HPP
#include <boost/math/special_functions/log1p.hpp>
#include <boost/math/distributions/detail/common_error_handling.hpp>
#include <boost/math/distributions/complement.hpp>
#include <boost/math/constants/constants.hpp>
@@ -24,7 +25,7 @@
namespace boost{ namespace math{
#ifdef BOOST_MSVC
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable:4127) // conditional expression is constant
#endif
@@ -36,13 +37,13 @@ public:
// ----------------------------------
// public Types
// ----------------------------------
typedef RealType value_type;
typedef Policy policy_type;
using value_type = RealType;
using policy_type = Policy;
// ----------------------------------
// Constructor(s)
// ----------------------------------
laplace_distribution(RealType l_location = 0, RealType l_scale = 1)
explicit laplace_distribution(RealType l_location = 0, RealType l_scale = 1)
: m_location(l_location), m_scale(l_scale)
{
RealType result;
@@ -78,14 +79,21 @@ private:
//
// Convenient type synonym for double.
typedef laplace_distribution<double> laplace;
using laplace = laplace_distribution<double>;
#ifdef __cpp_deduction_guides
template <class RealType>
laplace_distribution(RealType)->laplace_distribution<typename boost::math::tools::promote_args<RealType>::type>;
template <class RealType>
laplace_distribution(RealType,RealType)->laplace_distribution<typename boost::math::tools::promote_args<RealType>::type>;
#endif
//
// Non-member functions.
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const laplace_distribution<RealType, Policy>&)
inline std::pair<RealType, RealType> range(const laplace_distribution<RealType, Policy>&)
{
if (std::numeric_limits<RealType>::has_infinity)
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.
}
@@ -98,7 +106,7 @@ inline const std::pair<RealType, RealType> range(const laplace_distribution<Real
}
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> support(const laplace_distribution<RealType, Policy>&)
inline std::pair<RealType, RealType> support(const laplace_distribution<RealType, Policy>&)
{
if (std::numeric_limits<RealType>::has_infinity)
{ // Can Use infinity.
@@ -143,6 +151,48 @@ inline RealType pdf(const laplace_distribution<RealType, Policy>& dist, const Re
return result;
} // pdf
template <class RealType, class Policy>
inline RealType logpdf(const laplace_distribution<RealType, Policy>& dist, const RealType& x)
{
BOOST_MATH_STD_USING // for ADL of std functions
// Checking function argument
RealType result = -std::numeric_limits<RealType>::infinity();
const char* function = "boost::math::logpdf(const laplace_distribution<%1%>&, %1%))";
// Check scale and location.
if (false == dist.check_parameters(function, &result))
{
return result;
}
// Special pdf values.
if((boost::math::isinf)(x))
{
return result; // pdf + and - infinity is zero so logpdf is -INF
}
if (false == detail::check_x(function, x, &result, Policy()))
{
return result;
}
const RealType mu = dist.scale();
const RealType b = dist.location();
// if b is 0 avoid divde by 0 error
if(abs(b) < std::numeric_limits<RealType>::epsilon())
{
result = log(pdf(dist, x));
}
else
{
// General case
const RealType log2 = boost::math::constants::ln_two<RealType>();
result = -abs(x-mu)/b - log(b) - log2;
}
return result;
} // logpdf
template <class RealType, class Policy>
inline RealType cdf(const laplace_distribution<RealType, Policy>& dist, const RealType& x)
{
@@ -177,6 +227,50 @@ inline RealType cdf(const laplace_distribution<RealType, Policy>& dist, const Re
return result;
} // cdf
template <class RealType, class Policy>
inline RealType logcdf(const laplace_distribution<RealType, Policy>& dist, const RealType& x)
{
BOOST_MATH_STD_USING // For ADL of std functions.
RealType result = 0;
// Checking function argument.
const char* function = "boost::math::logcdf(const laplace_distribution<%1%>&, %1%)";
// Check scale and location.
if (false == dist.check_parameters(function, &result))
{
return result;
}
// Special cdf values:
if((boost::math::isinf)(x))
{
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() );
RealType location( dist.location() );
if (x < location)
{
result = ((x - location) / scale) - boost::math::constants::ln_two<RealType>();
}
else
{
result = log1p(-exp((location - x) / scale) / 2);
}
return result;
} // logcdf
template <class RealType, class Policy>
inline RealType quantile(const laplace_distribution<RealType, Policy>& dist, const RealType& p)
@@ -194,14 +288,14 @@ inline RealType quantile(const laplace_distribution<RealType, Policy>& dist, con
{
result = policies::raise_overflow_error<RealType>(function,
"probability parameter is 0, but must be > 0!", Policy());
return -result; // -std::numeric_limits<RealType>::infinity();
return -result; // -inf
}
if(p == 1)
{
result = policies::raise_overflow_error<RealType>(function,
"probability parameter is 1, but must be < 1!", Policy());
return result; // std::numeric_limits<RealType>::infinity();
return result; // inf
}
// Calculate Quantile
RealType scale( dist.scale() );
@@ -231,8 +325,6 @@ inline RealType cdf(const complemented2_type<laplace_distribution<RealType, Poli
const char* function = "boost::math::cdf(const complemented2_type<laplace_distribution<%1%>, %1%>&)";
// 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 values.
@@ -255,6 +347,46 @@ inline RealType cdf(const complemented2_type<laplace_distribution<RealType, Poli
return result;
} // cdf complement
template <class RealType, class Policy>
inline RealType logcdf(const complemented2_type<laplace_distribution<RealType, Policy>, RealType>& c)
{
// Calculate complement of logcdf.
BOOST_MATH_STD_USING // for ADL of std functions
RealType scale = c.dist.scale();
RealType location = c.dist.location();
RealType x = c.param;
RealType result = 0;
// Checking function argument.
const char* function = "boost::math::logcdf(const complemented2_type<laplace_distribution<%1%>, %1%>&)";
// Check scale and location.
if (false == c.dist.check_parameters(function, &result)) return result;
// 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)
{
result = (-x+location)/scale - boost::math::constants::ln_two<RealType>();
}
else
{
result = log1p(-exp( (-location+x)/scale )/2, Policy());
}
return result;
} // cdf complement
template <class RealType, class Policy>
inline RealType quantile(const complemented2_type<laplace_distribution<RealType, Policy>, RealType>& c)
@@ -333,7 +465,14 @@ inline RealType kurtosis_excess(const laplace_distribution<RealType, Policy>& /*
return 3;
}
#ifdef BOOST_MSVC
template <class RealType, class Policy>
inline RealType entropy(const laplace_distribution<RealType, Policy> & dist)
{
using std::log;
return log(2*dist.scale()*constants::e<RealType>());
}
#ifdef _MSC_VER
# pragma warning(pop)
#endif

View File

@@ -51,7 +51,14 @@ namespace boost { namespace math {
typedef logistic_distribution<double> logistic;
#ifdef __cpp_deduction_guides
template <class RealType>
logistic_distribution(RealType)->logistic_distribution<typename boost::math::tools::promote_args<RealType>::type>;
template <class RealType>
logistic_distribution(RealType,RealType)->logistic_distribution<typename boost::math::tools::promote_args<RealType>::type>;
#endif
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const logistic_distribution<RealType, Policy>& /* dist */)
{ // Range of permissible values for random variable x.
@@ -139,6 +146,49 @@ namespace boost { namespace math {
if(power < -tools::log_max_value<RealType>())
return 1;
return 1 / (1 + exp(power));
}
template <class RealType, class Policy>
inline RealType logcdf(const logistic_distribution<RealType, Policy>& dist, const RealType& x)
{
RealType scale = dist.scale();
RealType location = dist.location();
RealType result = 0; // of checks.
static const char* function = "boost::math::cdf(const logistic_distribution<%1%>&, %1%)";
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 0; // -infinity
}
return 1; // + infinity
}
if(false == detail::check_x(function, x, &result, Policy()))
{
return result;
}
BOOST_MATH_STD_USING
RealType power = (location - x) / scale;
if(power > tools::log_max_value<RealType>())
{
return 0;
}
if(power < -tools::log_max_value<RealType>())
{
return 1;
}
return -log1p(exp(power));
}
template <class RealType, class Policy>
@@ -212,6 +262,42 @@ namespace boost { namespace math {
return 1 / (1 + exp(power));
}
template <class RealType, class Policy>
inline RealType logcdf(const complemented2_type<logistic_distribution<RealType, Policy>, RealType>& c)
{
BOOST_MATH_STD_USING
RealType location = c.dist.location();
RealType scale = c.dist.scale();
RealType x = c.param;
static const char* function = "boost::math::cdf(const complement(logistic_distribution<%1%>&), %1%)";
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;
if(power < -tools::log_max_value<RealType>())
return 1;
return -log1p(exp(power));
}
template <class RealType, class Policy>
inline RealType quantile(const complemented2_type<logistic_distribution<RealType, Policy>, RealType>& c)
{
@@ -290,6 +376,13 @@ namespace boost { namespace math {
{
return kurtosis_excess(dist) + 3;
} // RealType kurtosis_excess(const logistic_distribution<RealType, Policy>& dist)
template <class RealType, class Policy>
inline RealType entropy(const logistic_distribution<RealType, Policy>& dist)
{
using std::log;
return 2 + log(dist.scale());
}
}}

View File

@@ -75,6 +75,13 @@ private:
typedef lognormal_distribution<double> lognormal;
#ifdef __cpp_deduction_guides
template <class RealType>
lognormal_distribution(RealType)->lognormal_distribution<typename boost::math::tools::promote_args<RealType>::type>;
template <class RealType>
lognormal_distribution(RealType,RealType)->lognormal_distribution<typename boost::math::tools::promote_args<RealType>::type>;
#endif
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const lognormal_distribution<RealType, Policy>& /*dist*/)
{ // Range of permissible values for random variable x is >0 to +infinity.
@@ -328,6 +335,15 @@ inline RealType kurtosis_excess(const lognormal_distribution<RealType, Policy>&
return exp(4 * ss) + 2 * exp(3 * ss) + 3 * exp(2 * ss) - 6;
}
template <class RealType, class Policy>
inline RealType entropy(const lognormal_distribution<RealType, Policy>& dist)
{
using std::log;
RealType mu = dist.location();
RealType sigma = dist.scale();
return mu + log(constants::two_pi<RealType>()*constants::e<RealType>()*sigma*sigma)/2;
}
} // namespace math
} // namespace boost

View File

@@ -19,7 +19,7 @@
// In a sequence of Bernoulli trials or events
// (independent, yes or no, succeed or fail) with success_fraction probability p,
// negative_binomial is the probability that k or fewer failures
// preceed the r th trial's success.
// precede the r th trial's success.
// random variable k is the number of failures (NOT the probability).
// Negative_binomial distribution is a discrete probability distribution.
@@ -27,7 +27,7 @@
// (like others including the binomial, Poisson & Bernoulli)
// is strictly defined as a discrete function: only integral values of k are envisaged.
// However because of the method of calculation using a continuous gamma function,
// it is convenient to treat it as if a continous function,
// it is convenient to treat it as if a continuous function,
// and permit non-integral values of k.
// However, by default the policy is to use discrete_quantile_policy.
@@ -52,11 +52,6 @@
#include <boost/math/tools/roots.hpp> // for root finding.
#include <boost/math/distributions/detail/inv_discrete_quantile.hpp>
#include <boost/type_traits/is_floating_point.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/mpl/if.hpp>
#include <limits> // using std::numeric_limits;
#include <utility>
@@ -181,7 +176,7 @@ namespace boost
// Discrete Distributions" Yong CAI and K. KRISHNAMOORTHY
// http://www.ucs.louisiana.edu/~kxk4695/Discrete_new.pdf
//
return ibeta_inv(successes, failures + 1, alpha, static_cast<RealType*>(0), Policy());
return ibeta_inv(successes, failures + 1, alpha, static_cast<RealType*>(nullptr), Policy());
} // find_lower_bound_on_p
static RealType find_upper_bound_on_p(
@@ -209,7 +204,7 @@ namespace boost
// Discrete Distributions" Yong CAI and K. KRISHNAMOORTHY
// http://www.ucs.louisiana.edu/~kxk4695/Discrete_new.pdf
//
return ibetac_inv(successes, failures, alpha, static_cast<RealType*>(0), Policy());
return ibetac_inv(successes, failures, alpha, static_cast<RealType*>(nullptr), Policy());
} // find_upper_bound_on_p
// Estimate number of trials :
@@ -256,6 +251,11 @@ namespace boost
typedef negative_binomial_distribution<double> negative_binomial; // Reserved name of type double.
#ifdef __cpp_deduction_guides
template <class RealType>
negative_binomial_distribution(RealType,RealType)->negative_binomial_distribution<typename boost::math::tools::promote_args<RealType>::type>;
#endif
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const negative_binomial_distribution<RealType, Policy>& /* dist */)
{ // Range of permissible values for random variable k.
@@ -492,7 +492,7 @@ namespace boost
//
// Max iterations permitted:
//
boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
std::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
typedef typename Policy::discrete_quantile_type discrete_type;
return detail::inverse_discrete_quantile(
dist,
@@ -579,7 +579,7 @@ namespace boost
//
// Max iterations permitted:
//
boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
std::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
typedef typename Policy::discrete_quantile_type discrete_type;
return detail::inverse_discrete_quantile(
dist,

View File

@@ -17,6 +17,7 @@
#include <boost/math/distributions/detail/generic_mode.hpp>
#include <boost/math/distributions/detail/common_error_handling.hpp> // error checks
#include <boost/math/special_functions/fpclassify.hpp> // isnan.
#include <boost/math/special_functions/trunc.hpp>
#include <boost/math/tools/roots.hpp> // for root finding.
#include <boost/math/tools/series.hpp>
@@ -38,7 +39,7 @@ namespace boost
//
// Variables come first:
//
boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
std::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
T errtol = boost::math::policies::get_epsilon<T, Policy>();
T l2 = lam / 2;
//
@@ -48,7 +49,7 @@ namespace boost
// k to zero, when l2 is small, as forward iteration
// is unstable:
//
int k = itrunc(l2);
long long k = lltrunc(l2);
if(k == 0)
k = 1;
// Starting Poisson weight:
@@ -74,8 +75,8 @@ namespace boost
// direction for recursion:
//
T last_term = 0;
boost::uintmax_t count = k;
for(int i = k; i >= 0; --i)
std::uintmax_t count = k;
for(auto i = k; i >= 0; --i)
{
T term = beta * pois;
sum += term;
@@ -86,10 +87,15 @@ namespace boost
}
pois *= i / l2;
beta += xterm;
xterm *= (a + i - 1) / (x * (a + b + i - 2));
if (a + b + i != 2)
{
xterm *= (a + i - 1) / (x * (a + b + i - 2));
}
last_term = term;
}
for(int i = k + 1; ; ++i)
for(auto i = k + 1; ; ++i)
{
poisf *= l2 / i;
xtermf *= (x * (a + b + i - 2)) / (a + i - 1);
@@ -101,7 +107,7 @@ namespace boost
{
break;
}
if(static_cast<boost::uintmax_t>(count + i - k) > max_iter)
if(static_cast<std::uintmax_t>(count + i - k) > max_iter)
{
return policies::raise_evaluation_error(
"cdf(non_central_beta_distribution<%1%>, %1%)",
@@ -119,14 +125,14 @@ namespace boost
//
// Variables come first:
//
boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
std::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
T errtol = boost::math::policies::get_epsilon<T, Policy>();
T l2 = lam / 2;
//
// k is the starting point for iteration, and is the
// maximum of the poisson weighting term:
//
int k = itrunc(l2);
long long k = lltrunc(l2);
T pois;
if(k <= 30)
{
@@ -168,8 +174,8 @@ namespace boost
// of the bulk of the sum:
//
T last_term = 0;
boost::uintmax_t count = 0;
for(int i = k + 1; ; ++i)
std::uintmax_t count = 0;
for(auto i = k + 1; ; ++i)
{
poisf *= l2 / i;
xtermf *= (x * (a + b + i - 2)) / (a + i - 1);
@@ -182,7 +188,7 @@ namespace boost
count = i - k;
break;
}
if(static_cast<boost::uintmax_t>(i - k) > max_iter)
if(static_cast<std::uintmax_t>(i - k) > max_iter)
{
return policies::raise_evaluation_error(
"cdf(non_central_beta_distribution<%1%>, %1%)",
@@ -190,7 +196,7 @@ namespace boost
}
last_term = term;
}
for(int i = k; i >= 0; --i)
for(auto i = k; i >= 0; --i)
{
T term = beta * pois;
sum += term;
@@ -198,7 +204,7 @@ namespace boost
{
break;
}
if(static_cast<boost::uintmax_t>(count + k - i) > max_iter)
if(static_cast<std::uintmax_t>(count + k - i) > max_iter)
{
return policies::raise_evaluation_error(
"cdf(non_central_beta_distribution<%1%>, %1%)",
@@ -289,12 +295,12 @@ namespace boost
// heuristics.
//
template <class F, class T, class Tol, class Policy>
std::pair<T, T> bracket_and_solve_root_01(F f, const T& guess, T factor, bool rising, Tol tol, boost::uintmax_t& max_iter, const Policy& pol)
std::pair<T, T> bracket_and_solve_root_01(F f, const T& guess, T factor, bool rising, Tol tol, std::uintmax_t& max_iter, const Policy& pol)
{
BOOST_MATH_STD_USING
static const char* function = "boost::math::tools::bracket_and_solve_root_01<%1%>";
//
// Set up inital brackets:
// Set up initial brackets:
//
T a = guess;
T b = a;
@@ -303,7 +309,7 @@ namespace boost
//
// Set up invocation count:
//
boost::uintmax_t count = max_iter - 1;
std::uintmax_t count = max_iter - 1;
if((fa < 0) == (guess < 0 ? !rising : rising))
{
@@ -424,7 +430,7 @@ namespace boost
static_cast<value_type>(p),
&r,
Policy()))
return (RealType)r;
return static_cast<RealType>(r);
//
// Special cases first:
//
@@ -489,7 +495,7 @@ namespace boost
detail::nc_beta_quantile_functor<value_type, Policy>
f(non_central_beta_distribution<value_type, Policy>(a, b, l), p, comp);
tools::eps_tolerance<value_type> tol(policies::digits<RealType, Policy>());
boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
std::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
std::pair<value_type, value_type> ir
= bracket_and_solve_root_01(
@@ -523,14 +529,14 @@ namespace boost
//
// Variables come first:
//
boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
std::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
T errtol = boost::math::policies::get_epsilon<T, Policy>();
T l2 = lam / 2;
//
// k is the starting point for iteration, and is the
// maximum of the poisson weighting term:
//
int k = itrunc(l2);
long long k = lltrunc(l2);
// Starting Poisson weight:
T pois = gamma_p_derivative(T(k+1), l2, pol);
// Starting beta term:
@@ -544,8 +550,8 @@ namespace boost
//
// Stable backwards recursion first:
//
boost::uintmax_t count = k;
for(int i = k; i >= 0; --i)
std::uintmax_t count = k;
for(auto i = k; i >= 0; --i)
{
T term = beta * pois;
sum += term;
@@ -555,9 +561,13 @@ namespace boost
break;
}
pois *= i / l2;
beta *= (a + i - 1) / (x * (a + i + b - 1));
if (a + b + i != 1)
{
beta *= (a + i - 1) / (x * (a + i + b - 1));
}
}
for(int i = k + 1; ; ++i)
for(auto i = k + 1; ; ++i)
{
poisf *= l2 / i;
betaf *= x * (a + b + i - 1) / (a + i - 1);
@@ -568,7 +578,7 @@ namespace boost
{
break;
}
if(static_cast<boost::uintmax_t>(count + i - k) > max_iter)
if(static_cast<std::uintmax_t>(count + i - k) > max_iter)
{
return policies::raise_evaluation_error(
"pdf(non_central_beta_distribution<%1%>, %1%)",
@@ -614,7 +624,7 @@ namespace boost
static_cast<value_type>(x),
&r,
Policy()))
return (RealType)r;
return static_cast<RealType>(r);
if(l == 0)
return pdf(boost::math::beta_distribution<RealType, Policy>(dist.alpha(), dist.beta()), x);
@@ -652,13 +662,10 @@ namespace boost
const char* function = "boost::math::detail::hypergeometric_2F2<%1%>(%1%,%1%,%1%,%1%,%1%)";
hypergeometric_2F2_sum<value_type> s(a1, a2, b1, b2, z);
boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
value_type zero = 0;
value_type result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon<value_type, Policy>(), max_iter, zero);
#else
std::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
value_type result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon<value_type, Policy>(), max_iter);
#endif
policies::check_series_iterations<T>(function, max_iter, pol);
return policies::checked_narrowing_cast<T, Policy>(result, function);
}
@@ -710,6 +717,11 @@ namespace boost
typedef non_central_beta_distribution<double> non_central_beta; // Reserved name of type double.
#ifdef __cpp_deduction_guides
template <class RealType>
non_central_beta_distribution(RealType,RealType,RealType)->non_central_beta_distribution<typename boost::math::tools::promote_args<RealType>::type>;
#endif
// Non-member functions to give properties of the distribution.
template <class RealType, class Policy>
@@ -749,7 +761,7 @@ namespace boost
l,
&r,
Policy()))
return (RealType)r;
return static_cast<RealType>(r);
RealType c = a + b + l / 2;
RealType mean = 1 - (b / c) * (1 + l / (2 * c * c));
return detail::generic_find_mode_01(
@@ -779,7 +791,7 @@ namespace boost
inline RealType variance(const non_central_beta_distribution<RealType, Policy>& dist)
{
//
// Relative error of this function may be arbitarily large... absolute
// Relative error of this function may be arbitrarily large... absolute
// error will be small however... that's the best we can do for now.
//
BOOST_MATH_STD_USING
@@ -800,7 +812,7 @@ namespace boost
{ // skewness = sqrt(l).
const char* function = "boost::math::non_central_beta_distribution<%1%>::skewness()";
typedef typename Policy::assert_undefined_type assert_type;
BOOST_STATIC_ASSERT(assert_type::value == 0);
static_assert(assert_type::value == 0, "Assert type is undefined.");
return policies::raise_evaluation_error<RealType>(
function,
@@ -813,7 +825,7 @@ namespace boost
{
const char* function = "boost::math::non_central_beta_distribution<%1%>::kurtosis_excess()";
typedef typename Policy::assert_undefined_type assert_type;
BOOST_STATIC_ASSERT(assert_type::value == 0);
static_assert(assert_type::value == 0, "Assert type is undefined.");
return policies::raise_evaluation_error<RealType>(
function,
@@ -860,7 +872,7 @@ namespace boost
x,
&r,
Policy()))
return (RealType)r;
return static_cast<RealType>(r);
if(l == 0)
return cdf(beta_distribution<RealType, Policy>(a, b), x);
@@ -897,7 +909,7 @@ namespace boost
x,
&r,
Policy()))
return (RealType)r;
return static_cast<RealType>(r);
if(l == 0)
return cdf(complement(beta_distribution<RealType, Policy>(a, b), x));

View File

@@ -13,7 +13,7 @@
#include <boost/math/distributions/fwd.hpp>
#include <boost/math/special_functions/gamma.hpp> // for incomplete gamma. gamma_q
#include <boost/math/special_functions/bessel.hpp> // for cyl_bessel_i
#include <boost/math/special_functions/round.hpp> // for iround
#include <boost/math/special_functions/round.hpp> // for llround
#include <boost/math/distributions/complement.hpp> // complements
#include <boost/math/distributions/chi_squared.hpp> // central distribution
#include <boost/math/distributions/detail/common_error_handling.hpp> // error checks
@@ -46,7 +46,7 @@ namespace boost
// Computing discrete mixtures of continuous
// distributions: noncentral chisquare, noncentral t
// and the distribution of the square of the sample
// multiple correlation coeficient.
// multiple correlation coefficient.
// D. Benton, K. Krishnamoorthy.
// Computational Statistics & Data Analysis 43 (2003) 249 - 267
//
@@ -62,7 +62,7 @@ namespace boost
T lambda = theta / 2;
T del = f / 2;
T y = x / 2;
boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
std::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
T errtol = boost::math::policies::get_epsilon<T, Policy>();
T sum = init_sum;
//
@@ -71,7 +71,7 @@ namespace boost
// k is chosen as the peek of the Poisson weights, which
// will occur *before* the largest term.
//
int k = iround(lambda, pol);
long long k = llround(lambda, pol);
// Forwards and backwards Poisson weights:
T poisf = boost::math::gamma_p_derivative(static_cast<T>(1 + k), lambda, pol);
T poisb = poisf * k / lambda;
@@ -88,8 +88,8 @@ namespace boost
// stable direction for the gamma function
// recurrences:
//
int i;
for(i = k; static_cast<boost::uintmax_t>(i-k) < max_iter; ++i)
long long i;
for(i = k; static_cast<std::uintmax_t>(i-k) < max_iter; ++i)
{
T term = poisf * gamf;
sum += term;
@@ -100,14 +100,14 @@ namespace boost
break;
}
//Error check:
if(static_cast<boost::uintmax_t>(i-k) >= max_iter)
if(static_cast<std::uintmax_t>(i-k) >= max_iter)
return policies::raise_evaluation_error(
"cdf(non_central_chi_squared_distribution<%1%>, %1%)",
"Series did not converge, closest value was %1%", sum, pol);
//
// Now backwards iteration: the gamma
// function recurrences are unstable in this
// direction, we rely on the terms deminishing in size
// direction, we rely on the terms diminishing in size
// faster than we introduce cancellation errors.
// For this reason it's very important that we start
// *before* the largest term so that backwards iteration
@@ -141,7 +141,7 @@ namespace boost
// This uses a stable forward iteration to sum the
// CDF, unfortunately this can not be used for large
// values of the non-centrality parameter because:
// * The first term may underfow to zero.
// * The first term may underflow to zero.
// * We may need an extra-ordinary number of terms
// before we reach the first *significant* term.
//
@@ -157,12 +157,12 @@ namespace boost
if(sum == 0)
return sum;
boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
std::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
T errtol = boost::math::policies::get_epsilon<T, Policy>();
int i;
T lterm(0), term(0);
for(i = 1; static_cast<boost::uintmax_t>(i) < max_iter; ++i)
for(i = 1; static_cast<std::uintmax_t>(i) < max_iter; ++i)
{
tk = tk * x / (f + 2 * i);
uk = uk * lambda / i;
@@ -174,7 +174,7 @@ namespace boost
break;
}
//Error check:
if(static_cast<boost::uintmax_t>(i) >= max_iter)
if(static_cast<std::uintmax_t>(i) >= max_iter)
return policies::raise_evaluation_error(
"cdf(non_central_chi_squared_distribution<%1%>, %1%)",
"Series did not converge, closest value was %1%", sum, pol);
@@ -191,7 +191,7 @@ namespace boost
// Computing discrete mixtures of continuous
// distributions: noncentral chisquare, noncentral t
// and the distribution of the square of the sample
// multiple correlation coeficient.
// multiple correlation coefficient.
// D. Benton, K. Krishnamoorthy.
// Computational Statistics & Data Analysis 43 (2003) 249 - 267
//
@@ -202,7 +202,7 @@ namespace boost
// Special case:
if(y == 0)
return 0;
boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
std::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
T errtol = boost::math::policies::get_epsilon<T, Policy>();
T errorf(0), errorb(0);
@@ -215,7 +215,7 @@ namespace boost
// function, which ocurrs *after* the largest term in the
// sum.
//
int k = iround(del, pol);
long long k = llround(del, pol);
T a = n / 2 + k;
// Central chi squared term for forward iteration:
T gamkf = boost::math::gamma_p(a, x, pol);
@@ -270,10 +270,10 @@ namespace boost
errorf = poiskf * gamkf;
sum += errorf;
++i;
}while((fabs(errorf / sum) > errtol) && (static_cast<boost::uintmax_t>(i) < max_iter));
}while((fabs(errorf / sum) > errtol) && (static_cast<std::uintmax_t>(i) < max_iter));
//Error check:
if(static_cast<boost::uintmax_t>(i) >= max_iter)
if(static_cast<std::uintmax_t>(i) >= max_iter)
return policies::raise_evaluation_error(
"cdf(non_central_chi_squared_distribution<%1%>, %1%)",
"Series did not converge, closest value was %1%", sum, pol);
@@ -288,29 +288,29 @@ namespace boost
// As above but for the PDF:
//
BOOST_MATH_STD_USING
boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
std::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
T errtol = boost::math::policies::get_epsilon<T, Policy>();
T x2 = x / 2;
T n2 = n / 2;
T l2 = lambda / 2;
T sum = 0;
int k = itrunc(l2);
long long k = lltrunc(l2);
T pois = gamma_p_derivative(static_cast<T>(k + 1), l2, pol) * gamma_p_derivative(static_cast<T>(n2 + k), x2);
if(pois == 0)
return 0;
T poisb = pois;
for(int i = k; ; ++i)
for(long long i = k; ; ++i)
{
sum += pois;
if(pois / sum < errtol)
break;
if(static_cast<boost::uintmax_t>(i - k) >= max_iter)
if(static_cast<std::uintmax_t>(i - k) >= max_iter)
return policies::raise_evaluation_error(
"pdf(non_central_chi_squared_distribution<%1%>, %1%)",
"Series did not converge, closest value was %1%", sum, pol);
pois *= l2 * x2 / ((i + 1) * (n2 + i));
}
for(int i = k - 1; i >= 0; --i)
for(long long i = k - 1; i >= 0; --i)
{
poisb *= (i + 1) * (n2 + i) / (l2 * x2);
sum += poisb;
@@ -428,7 +428,7 @@ namespace boost
static_cast<value_type>(p),
&r,
Policy()))
return (RealType)r;
return static_cast<RealType>(r);
//
// Special cases get short-circuited first:
//
@@ -519,7 +519,7 @@ namespace boost
(value_type)x,
&r,
Policy()))
return (RealType)r;
return static_cast<RealType>(r);
if(l == 0)
return pdf(boost::math::chi_squared_distribution<RealType, forwarding_policy>(dist.degrees_of_freedom()), x);
@@ -587,7 +587,7 @@ namespace boost
}
degrees_of_freedom_finder<RealType, Policy> f(lam, x, p < q ? p : q, p < q ? false : true);
tools::eps_tolerance<RealType> tol(policies::digits<RealType, Policy>());
boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
std::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
//
// Pick an initial guess that we know will give us a probability
// right around 0.5.
@@ -643,7 +643,7 @@ namespace boost
}
non_centrality_finder<RealType, Policy> f(v, x, p < q ? p : q, p < q ? false : true);
tools::eps_tolerance<RealType> tol(policies::digits<RealType, Policy>());
boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
std::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
//
// Pick an initial guess that we know will give us a probability
// right around 0.5.
@@ -783,6 +783,11 @@ namespace boost
typedef non_central_chi_squared_distribution<double> non_central_chi_squared; // Reserved name of type double.
#ifdef __cpp_deduction_guides
template <class RealType>
non_central_chi_squared_distribution(RealType,RealType)->non_central_chi_squared_distribution<typename boost::math::tools::promote_args<RealType>::type>;
#endif
// Non-member functions to give properties of the distribution.
template <class RealType, class Policy>
@@ -816,7 +821,7 @@ namespace boost
l,
&r,
Policy()))
return r;
return static_cast<RealType>(r);
return k + l;
} // mean
@@ -837,8 +842,10 @@ namespace boost
l,
&r,
Policy()))
return (RealType)r;
return detail::generic_find_mode(dist, 1 + k, function);
return static_cast<RealType>(r);
bool asymptotic_mode = k < l/4;
RealType starting_point = asymptotic_mode ? k + l - RealType(3) : RealType(1) + k;
return detail::generic_find_mode(dist, starting_point, function);
}
template <class RealType, class Policy>
@@ -857,7 +864,7 @@ namespace boost
l,
&r,
Policy()))
return r;
return static_cast<RealType>(r);
return 2 * (2 * l + k);
}
@@ -880,7 +887,7 @@ namespace boost
l,
&r,
Policy()))
return r;
return static_cast<RealType>(r);
BOOST_MATH_STD_USING
return pow(2 / (k + 2 * l), RealType(3)/2) * (k + 3 * l);
}
@@ -901,7 +908,7 @@ namespace boost
l,
&r,
Policy()))
return r;
return static_cast<RealType>(r);
return 12 * (k + 4 * l) / ((k + 2 * l) * (k + 2 * l));
} // kurtosis_excess
@@ -939,7 +946,7 @@ namespace boost
x,
&r,
Policy()))
return r;
return static_cast<RealType>(r);
return detail::non_central_chi_squared_cdf(x, k, l, false, Policy());
} // cdf
@@ -968,7 +975,7 @@ namespace boost
x,
&r,
Policy()))
return r;
return static_cast<RealType>(r);
return detail::non_central_chi_squared_cdf(x, k, l, true, Policy());
} // ccdf
@@ -994,6 +1001,3 @@ namespace boost
#include <boost/math/distributions/detail/derived_accessors.hpp>
#endif // BOOST_MATH_SPECIAL_NON_CENTRAL_CHI_SQUARE_HPP

View File

@@ -63,6 +63,11 @@ namespace boost
typedef non_central_f_distribution<double> non_central_f; // Reserved name of type double.
#ifdef __cpp_deduction_guides
template <class RealType>
non_central_f_distribution(RealType,RealType,RealType)->non_central_f_distribution<typename boost::math::tools::promote_args<RealType>::type>;
#endif
// Non-member functions to give properties of the distribution.
template <class RealType, class Policy>
@@ -101,7 +106,7 @@ namespace boost
l,
&r,
Policy()))
return r;
return r;
if(v2 <= 2)
return policies::raise_domain_error(
function,
@@ -132,7 +137,7 @@ namespace boost
l,
&r,
Policy()))
return r;
return r;
RealType guess = m > 2 ? RealType(m * (n + l) / (n * (m - 2))) : RealType(1);
return detail::generic_find_mode(
dist,
@@ -161,7 +166,7 @@ namespace boost
l,
&r,
Policy()))
return r;
return r;
if(m <= 4)
return policies::raise_domain_error(
function,
@@ -198,7 +203,7 @@ namespace boost
l,
&r,
Policy()))
return r;
return r;
if(m <= 6)
return policies::raise_domain_error(
function,
@@ -235,7 +240,7 @@ namespace boost
l,
&r,
Policy()))
return r;
return r;
if(m <= 8)
return policies::raise_domain_error(
function,
@@ -304,7 +309,7 @@ namespace boost
dist.non_centrality(),
&r,
Policy()))
return r;
return r;
if((x < 0) || !(boost::math::isfinite)(x))
{
@@ -345,7 +350,7 @@ namespace boost
c.dist.non_centrality(),
&r,
Policy()))
return r;
return r;
if((c.param < 0) || !(boost::math::isfinite)(c.param))
{

View File

@@ -15,6 +15,7 @@
#include <boost/math/distributions/normal.hpp> // for normal CDF and quantile
#include <boost/math/distributions/students_t.hpp>
#include <boost/math/distributions/detail/generic_quantile.hpp> // quantile
#include <boost/math/special_functions/trunc.hpp>
namespace boost
{
@@ -33,7 +34,7 @@ namespace boost
//
// Variables come first:
//
boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
std::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
T errtol = policies::get_epsilon<T, Policy>();
T d2 = delta * delta / 2;
//
@@ -43,17 +44,17 @@ namespace boost
// cancellation errors later (test case is v = 1621286869049072.3
// delta = 0.16212868690490723, x = 0.86987415482475994).
//
int k = itrunc(d2);
long long k = lltrunc(d2);
T pois;
if(k == 0) k = 1;
// Starting Poisson weight:
pois = gamma_p_derivative(T(k+1), d2, pol)
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:
// Recurrence & starting beta terms:
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);
@@ -67,14 +68,14 @@ namespace boost
// Backwards recursion first, this is the stable
// direction for recursion:
//
boost::uintmax_t count = 0;
std::uintmax_t count = 0;
T last_term = 0;
for(int i = k; i >= 0; --i)
for(auto i = k; i >= 0; --i)
{
T term = beta * pois;
sum += term;
// Don't terminate on first term in case we "fixed" k above:
if((fabs(last_term) > fabs(term)) && fabs(term/sum) < errtol)
if(((fabs(last_term) > fabs(term)) && fabs(term/sum) < errtol) || (v == 2 && i == 0))
break;
last_term = term;
pois *= (i + 0.5f) / d2;
@@ -83,7 +84,7 @@ namespace boost
++count;
}
last_term = 0;
for(int i = k + 1; ; ++i)
for(auto i = k + 1; ; ++i)
{
poisf *= d2 / (i + 0.5f);
xtermf *= (x * (v / 2 + i - 1)) / (i);
@@ -97,7 +98,7 @@ namespace boost
if(count > max_iter)
{
return policies::raise_evaluation_error(
"cdf(non_central_t_distribution<%1%>, %1%)",
"cdf(non_central_t_distribution<%1%>, %1%)",
"Series did not converge, closest value was %1%", sum, pol);
}
}
@@ -111,7 +112,7 @@ namespace boost
//
// Variables come first:
//
boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
std::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
T errtol = boost::math::policies::get_epsilon<T, Policy>();
T d2 = delta * delta / 2;
//
@@ -121,11 +122,11 @@ namespace boost
// (test case is v = 561908036470413.25, delta = 0.056190803647041321,
// x = 1.6155232703966216):
//
int k = itrunc(d2);
long long k = lltrunc(d2);
if(k == 0) k = 1;
// Starting Poisson weight:
T pois;
if((k < (int)(max_factorial<T>::value)) && (d2 < tools::log_max_value<T>()) && (log(d2) * k < tools::log_max_value<T>()))
if((k < static_cast<long long>(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
@@ -138,7 +139,7 @@ namespace boost
}
else
{
pois = gamma_p_derivative(T(k+1), d2, pol)
pois = gamma_p_derivative(T(k+1), d2, pol)
* tgamma_delta_ratio(T(k + 1), T(0.5f))
* delta / constants::root_two<T>();
}
@@ -150,8 +151,8 @@ namespace boost
// Starting beta term:
if(k != 0)
{
beta = x < y
? detail::ibeta_imp(T(k + 1), T(v / 2), x, pol, true, true, &xterm)
beta = x < y
? 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 / (v / 2 + k);
@@ -169,9 +170,9 @@ namespace boost
//
// Fused forward and backwards recursion:
//
boost::uintmax_t count = 0;
std::uintmax_t count = 0;
T last_term = 0;
for(int i = k + 1, j = k; ; ++i, --j)
for(auto i = k + 1, j = k; ; ++i, --j)
{
poisf *= d2 / (i + 0.5f);
xtermf *= (x * (v / 2 + i - 1)) / (i);
@@ -183,7 +184,8 @@ namespace boost
term += beta * pois;
pois *= (j + 0.5f) / d2;
beta -= xterm;
xterm *= (j) / (x * (v / 2 + j - 1));
if(!(v == 2 && j == 0))
xterm *= (j) / (x * (v / 2 + j - 1));
}
sum += term;
@@ -194,7 +196,7 @@ namespace boost
if(count > max_iter)
{
return policies::raise_evaluation_error(
"cdf(non_central_t_distribution<%1%>, %1%)",
"cdf(non_central_t_distribution<%1%>, %1%)",
"Series did not converge, closest value was %1%", sum, pol);
}
++count;
@@ -208,7 +210,7 @@ namespace boost
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);
normal_distribution<T, Policy> n(delta, 1);
return cdf(n, t);
}
//
@@ -294,9 +296,9 @@ namespace boost
// now passed as function
typedef typename policies::evaluation<T, Policy>::type value_type;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
@@ -305,9 +307,9 @@ namespace boost
function,
v, &r, Policy())
||
!detail::check_finite(
!detail::check_non_centrality(
function,
delta,
static_cast<T>(delta * delta),
&r,
Policy())
||
@@ -342,14 +344,14 @@ namespace boost
guess = quantile(complement(normal_distribution<value_type, forwarding_policy>(mean, var), q));
}
//
// We *must* get the sign of the initial guess correct,
// We *must* get the sign of the initial guess correct,
// or our root-finder will fail, so double check it now:
//
value_type pzero = non_central_t_cdf(
static_cast<value_type>(v),
static_cast<value_type>(delta),
static_cast<value_type>(0),
!(p < q),
static_cast<value_type>(v),
static_cast<value_type>(delta),
static_cast<value_type>(0),
!(p < q),
forwarding_policy());
int s;
if(p < q)
@@ -362,13 +364,13 @@ namespace boost
}
value_type result = detail::generic_quantile(
non_central_t_distribution<value_type, forwarding_policy>(v, delta),
(p < q ? p : q),
guess,
(p >= q),
non_central_t_distribution<value_type, forwarding_policy>(v, delta),
(p < q ? p : q),
guess,
(p >= q),
function);
return policies::checked_narrowing_cast<T, forwarding_policy>(
result,
result,
function);
}
@@ -379,19 +381,19 @@ namespace boost
//
// Variables come first:
//
boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
std::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
T errtol = boost::math::policies::get_epsilon<T, Policy>();
T d2 = delta * delta / 2;
//
// k is the starting point for iteration, and is the
// maximum of the poisson weighting term:
//
int k = itrunc(d2);
long long k = lltrunc(d2);
T pois, xterm;
if(k == 0)
k = 1;
// Starting Poisson weight:
pois = gamma_p_derivative(T(k+1), d2, pol)
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:
@@ -407,8 +409,8 @@ namespace boost
// Backwards recursion first, this is the stable
// direction for recursion:
//
boost::uintmax_t count = 0;
for(int i = k; i >= 0; --i)
std::uintmax_t count = 0;
for(auto i = k; i >= 0; --i)
{
T term = xterm * pois;
sum += term;
@@ -420,11 +422,11 @@ namespace boost
if(count > max_iter)
{
return policies::raise_evaluation_error(
"pdf(non_central_t_distribution<%1%>, %1%)",
"pdf(non_central_t_distribution<%1%>, %1%)",
"Series did not converge, closest value was %1%", sum, pol);
}
}
for(int i = k + 1; ; ++i)
for(auto i = k + 1; ; ++i)
{
poisf *= d2 / (i + 0.5f);
xtermf *= (x * (n / 2 + i)) / (i);
@@ -436,7 +438,7 @@ namespace boost
if(count > max_iter)
{
return policies::raise_evaluation_error(
"pdf(non_central_t_distribution<%1%>, %1%)",
"pdf(non_central_t_distribution<%1%>, %1%)",
"Series did not converge, closest value was %1%", sum, pol);
}
}
@@ -449,7 +451,7 @@ namespace boost
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);
normal_distribution<T, Policy> norm(delta, 1);
return pdf(norm, t);
}
//
@@ -463,16 +465,16 @@ namespace boost
{
//
// Handle this as a special case, using the formula
// from Weisstein, Eric W.
// "Noncentral Student's t-Distribution."
// From MathWorld--A Wolfram Web Resource.
// http://mathworld.wolfram.com/NoncentralStudentst-Distribution.html
//
// from Weisstein, Eric W.
// "Noncentral Student's t-Distribution."
// From MathWorld--A Wolfram Web Resource.
// http://mathworld.wolfram.com/NoncentralStudentst-Distribution.html
//
// The formula is simplified thanks to the relation
// 1F1(a,b,0) = 1.
//
return tgamma_delta_ratio(n / 2 + 0.5f, T(0.5f))
* sqrt(n / constants::pi<T>())
* sqrt(n / constants::pi<T>())
* exp(-delta * delta / 2) / 2;
}
if(fabs(delta / (4 * n)) < policies::get_epsilon<T, Policy>())
@@ -523,7 +525,7 @@ namespace boost
if (v > 1 / boost::math::tools::epsilon<T>() )
{
//normal_distribution<T, Policy> n(delta, 1);
//return boost::math::mean(n);
//return boost::math::mean(n);
return delta;
}
else
@@ -578,11 +580,11 @@ namespace boost
BOOST_MATH_STD_USING
if ((boost::math::isinf)(v))
{
return 3;
return 1;
}
if (delta == 0)
{ // == Student's t
return 3;
return 1;
}
T mean = boost::math::detail::mean(v, delta, pol);
T l2 = delta * delta;
@@ -592,11 +594,12 @@ namespace boost
result *= -mean * mean;
result += v * v * (l2 * l2 + 6 * l2 + 3) / ((v - 4) * (v - 2));
result /= var * var;
result -= static_cast<T>(3);
return result;
}
#if 0
//
//
// This code is disabled, since there can be multiple answers to the
// question, and it's not clear how to find the "right" one.
//
@@ -631,13 +634,13 @@ namespace boost
//
// Can't a thing if one of p and q is zero:
//
return policies::raise_evaluation_error<RealType>(function,
"Can't find degrees of freedom when the probability is 0 or 1, only possible answer is %1%",
return policies::raise_evaluation_error<RealType>(function,
"Can't find degrees of freedom when the probability is 0 or 1, only possible answer is %1%",
RealType(std::numeric_limits<RealType>::quiet_NaN()), Policy());
}
t_degrees_of_freedom_finder<RealType, Policy> f(delta, x, p < q ? p : q, p < q ? false : true);
tools::eps_tolerance<RealType> tol(policies::digits<RealType, Policy>());
boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
std::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
//
// Pick an initial guess:
//
@@ -684,13 +687,13 @@ 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%",
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%",
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);
tools::eps_tolerance<RealType> tol(policies::digits<RealType, Policy>());
boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
std::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
//
// Pick an initial guess that we know is the right side of
// zero:
@@ -721,15 +724,15 @@ namespace boost
typedef Policy policy_type;
non_central_t_distribution(RealType v_, RealType lambda) : v(v_), ncp(lambda)
{
{
const char* function = "boost::math::non_central_t_distribution<%1%>::non_central_t_distribution(%1%,%1%)";
RealType r;
detail::check_df_gt0_to_inf(
function,
v, &r, Policy());
detail::check_finite(
detail::check_non_centrality(
function,
lambda,
static_cast<value_type>(lambda * lambda),
&r,
Policy());
} // non_central_t_distribution constructor.
@@ -743,7 +746,7 @@ namespace boost
return ncp;
}
#if 0
//
//
// This code is disabled, since there can be multiple answers to the
// question, and it's not clear how to find the "right" one.
//
@@ -752,19 +755,19 @@ namespace boost
const char* function = "non_central_t<%1%>::find_degrees_of_freedom";
typedef typename policies::evaluation<RealType, Policy>::type value_type;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
value_type result = detail::find_t_degrees_of_freedom(
static_cast<value_type>(delta),
static_cast<value_type>(x),
static_cast<value_type>(p),
static_cast<value_type>(1-p),
static_cast<value_type>(delta),
static_cast<value_type>(x),
static_cast<value_type>(p),
static_cast<value_type>(1-p),
forwarding_policy());
return policies::checked_narrowing_cast<RealType, forwarding_policy>(
result,
result,
function);
}
template <class A, class B, class C>
@@ -773,19 +776,19 @@ namespace boost
const char* function = "non_central_t<%1%>::find_degrees_of_freedom";
typedef typename policies::evaluation<RealType, Policy>::type value_type;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
value_type result = detail::find_t_degrees_of_freedom(
static_cast<value_type>(c.dist),
static_cast<value_type>(c.param1),
static_cast<value_type>(1-c.param2),
static_cast<value_type>(c.param2),
static_cast<value_type>(c.dist),
static_cast<value_type>(c.param1),
static_cast<value_type>(1-c.param2),
static_cast<value_type>(c.param2),
forwarding_policy());
return policies::checked_narrowing_cast<RealType, forwarding_policy>(
result,
result,
function);
}
static RealType find_non_centrality(RealType v, RealType x, RealType p)
@@ -793,19 +796,19 @@ namespace boost
const char* function = "non_central_t<%1%>::find_t_non_centrality";
typedef typename policies::evaluation<RealType, Policy>::type value_type;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
value_type result = detail::find_t_non_centrality(
static_cast<value_type>(v),
static_cast<value_type>(x),
static_cast<value_type>(p),
static_cast<value_type>(1-p),
static_cast<value_type>(v),
static_cast<value_type>(x),
static_cast<value_type>(p),
static_cast<value_type>(1-p),
forwarding_policy());
return policies::checked_narrowing_cast<RealType, forwarding_policy>(
result,
result,
function);
}
template <class A, class B, class C>
@@ -814,19 +817,19 @@ namespace boost
const char* function = "non_central_t<%1%>::find_t_non_centrality";
typedef typename policies::evaluation<RealType, Policy>::type value_type;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
value_type result = detail::find_t_non_centrality(
static_cast<value_type>(c.dist),
static_cast<value_type>(c.param1),
static_cast<value_type>(1-c.param2),
static_cast<value_type>(c.param2),
static_cast<value_type>(c.dist),
static_cast<value_type>(c.param1),
static_cast<value_type>(1-c.param2),
static_cast<value_type>(c.param2),
forwarding_policy());
return policies::checked_narrowing_cast<RealType, forwarding_policy>(
result,
result,
function);
}
#endif
@@ -838,6 +841,11 @@ namespace boost
typedef non_central_t_distribution<double> non_central_t; // Reserved name of type double.
#ifdef __cpp_deduction_guides
template <class RealType>
non_central_t_distribution(RealType,RealType)->non_central_t_distribution<typename boost::math::tools::promote_args<RealType>::type>;
#endif
// Non-member functions to give properties of the distribution.
template <class RealType, class Policy>
@@ -866,12 +874,12 @@ namespace boost
function,
v, &r, Policy())
||
!detail::check_finite(
!detail::check_non_centrality(
function,
l,
static_cast<RealType>(l * l),
&r,
Policy()))
return (RealType)r;
return static_cast<RealType>(r);
BOOST_MATH_STD_USING
@@ -879,7 +887,7 @@ namespace boost
RealType var = v < 4 ? 1 : detail::variance(v, l, Policy());
return detail::generic_find_mode(
dist,
dist,
m,
function,
sqrt(var));
@@ -887,14 +895,14 @@ namespace boost
template <class RealType, class Policy>
inline RealType mean(const non_central_t_distribution<RealType, Policy>& dist)
{
{
BOOST_MATH_STD_USING
const char* function = "mean(const non_central_t_distribution<%1%>&)";
typedef typename policies::evaluation<RealType, Policy>::type value_type;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
RealType v = dist.degrees_of_freedom();
@@ -904,15 +912,15 @@ namespace boost
function,
v, &r, Policy())
||
!detail::check_finite(
!detail::check_non_centrality(
function,
l,
static_cast<RealType>(l * l),
&r,
Policy()))
return (RealType)r;
return static_cast<RealType>(r);
if(v <= 1)
return policies::raise_domain_error<RealType>(
function,
function,
"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>(
@@ -926,9 +934,9 @@ namespace boost
const char* function = "variance(const non_central_t_distribution<%1%>&)";
typedef typename policies::evaluation<RealType, Policy>::type value_type;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
BOOST_MATH_STD_USING
@@ -939,15 +947,15 @@ namespace boost
function,
v, &r, Policy())
||
!detail::check_finite(
!detail::check_non_centrality(
function,
l,
static_cast<RealType>(l * l),
&r,
Policy()))
return (RealType)r;
return static_cast<RealType>(r);
if(v <= 2)
return policies::raise_domain_error<RealType>(
function,
function,
"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);
@@ -962,9 +970,9 @@ namespace boost
const char* function = "skewness(const non_central_t_distribution<%1%>&)";
typedef typename policies::evaluation<RealType, Policy>::type value_type;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
RealType v = dist.degrees_of_freedom();
@@ -974,15 +982,15 @@ namespace boost
function,
v, &r, Policy())
||
!detail::check_finite(
!detail::check_non_centrality(
function,
l,
static_cast<RealType>(l * l),
&r,
Policy()))
return (RealType)r;
return static_cast<RealType>(r);
if(v <= 3)
return policies::raise_domain_error<RealType>(
function,
function,
"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);
@@ -990,13 +998,13 @@ namespace boost
template <class RealType, class Policy>
inline RealType kurtosis_excess(const non_central_t_distribution<RealType, Policy>& dist)
{
{
const char* function = "kurtosis_excess(const non_central_t_distribution<%1%>&)";
typedef typename policies::evaluation<RealType, Policy>::type value_type;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
RealType v = dist.degrees_of_freedom();
@@ -1006,15 +1014,15 @@ namespace boost
function,
v, &r, Policy())
||
!detail::check_finite(
!detail::check_non_centrality(
function,
l,
static_cast<RealType>(l * l),
&r,
Policy()))
return (RealType)r;
return static_cast<RealType>(r);
if(v <= 4)
return policies::raise_domain_error<RealType>(
function,
function,
"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);
@@ -1032,9 +1040,9 @@ namespace boost
const char* function = "pdf(non_central_t_distribution<%1%>, %1%)";
typedef typename policies::evaluation<RealType, Policy>::type value_type;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
@@ -1045,9 +1053,9 @@ namespace boost
function,
v, &r, Policy())
||
!detail::check_finite(
!detail::check_non_centrality(
function,
l,
static_cast<RealType>(l * l), // we need l^2 to be countable.
&r,
Policy())
||
@@ -1056,25 +1064,25 @@ namespace boost
t,
&r,
Policy()))
return (RealType)r;
return static_cast<RealType>(r);
return policies::checked_narrowing_cast<RealType, forwarding_policy>(
detail::non_central_t_pdf(static_cast<value_type>(v),
static_cast<value_type>(l),
static_cast<value_type>(t),
detail::non_central_t_pdf(static_cast<value_type>(v),
static_cast<value_type>(l),
static_cast<value_type>(t),
Policy()),
function);
} // pdf
template <class RealType, class Policy>
RealType cdf(const non_central_t_distribution<RealType, Policy>& dist, const RealType& x)
{
{
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,
policies::promote_float<false>,
policies::promote_double<false>,
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
@@ -1085,9 +1093,9 @@ namespace boost
function,
v, &r, Policy())
||
!detail::check_finite(
!detail::check_non_centrality(
function,
l,
static_cast<RealType>(l * l),
&r,
Policy())
||
@@ -1096,10 +1104,10 @@ namespace boost
x,
&r,
Policy()))
return (RealType)r;
if ((boost::math::isinf)(v))
return static_cast<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);
normal_distribution<RealType, Policy> n(l, 1);
cdf(n, x);
//return cdf(normal_distribution<RealType, Policy>(l, 1), x);
}
@@ -1110,9 +1118,9 @@ namespace boost
}
return policies::checked_narrowing_cast<RealType, forwarding_policy>(
detail::non_central_t_cdf(
static_cast<value_type>(v),
static_cast<value_type>(l),
static_cast<value_type>(x),
static_cast<value_type>(v),
static_cast<value_type>(l),
static_cast<value_type>(x),
false, Policy()),
function);
} // cdf
@@ -1124,9 +1132,9 @@ namespace boost
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,
policies::promote_float<false>,
policies::promote_double<false>,
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
@@ -1139,9 +1147,9 @@ namespace boost
function,
v, &r, Policy())
||
!detail::check_finite(
!detail::check_non_centrality(
function,
l,
static_cast<RealType>(l * l),
&r,
Policy())
||
@@ -1150,11 +1158,11 @@ namespace boost
x,
&r,
Policy()))
return (RealType)r;
return static_cast<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);
normal_distribution<RealType, Policy> n(l, 1);
return cdf(complement(n, x));
}
if(l == 0)
@@ -1163,9 +1171,9 @@ namespace boost
}
return policies::checked_narrowing_cast<RealType, forwarding_policy>(
detail::non_central_t_cdf(
static_cast<value_type>(v),
static_cast<value_type>(l),
static_cast<value_type>(x),
static_cast<value_type>(v),
static_cast<value_type>(l),
static_cast<value_type>(x),
true, Policy()),
function);
} // ccdf

View File

@@ -21,6 +21,7 @@
#include <boost/math/distributions/detail/common_error_handling.hpp>
#include <utility>
#include <type_traits>
namespace boost{ namespace math{
@@ -28,10 +29,10 @@ template <class RealType = double, class Policy = policies::policy<> >
class normal_distribution
{
public:
typedef RealType value_type;
typedef Policy policy_type;
using value_type = RealType;
using policy_type = Policy;
normal_distribution(RealType l_mean = 0, RealType sd = 1)
explicit 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";
@@ -69,15 +70,29 @@ private:
RealType m_sd; // distribution standard deviation or scale.
}; // class normal_distribution
typedef normal_distribution<double> normal;
using normal = normal_distribution<double>;
#ifdef BOOST_MSVC
//
// Deduction guides, note we don't check the
// value of __cpp_deduction_guides, just assume
// they work as advertised, even if this is pre-final C++17.
//
#ifdef __cpp_deduction_guides
template <class RealType>
normal_distribution(RealType, RealType)->normal_distribution<typename boost::math::tools::promote_args<RealType>::type>;
template <class RealType>
normal_distribution(RealType)->normal_distribution<typename boost::math::tools::promote_args<RealType>::type>;
#endif
#ifdef _MSC_VER
#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*/)
inline std::pair<RealType, RealType> range(const normal_distribution<RealType, Policy>& /*dist*/)
{ // Range of permissible values for random variable x.
if (std::numeric_limits<RealType>::has_infinity)
{
@@ -91,7 +106,7 @@ inline const std::pair<RealType, RealType> range(const normal_distribution<RealT
}
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> support(const normal_distribution<RealType, Policy>& /*dist*/)
inline std::pair<RealType, RealType> support(const normal_distribution<RealType, Policy>& /*dist*/)
{ // 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)
{
@@ -104,7 +119,7 @@ inline const std::pair<RealType, RealType> support(const normal_distribution<Rea
}
}
#ifdef BOOST_MSVC
#ifdef _MSC_VER
#pragma warning(pop)
#endif
@@ -131,11 +146,6 @@ inline RealType pdf(const normal_distribution<RealType, Policy>& dist, const Rea
{
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;
@@ -151,6 +161,42 @@ inline RealType pdf(const normal_distribution<RealType, Policy>& dist, const Rea
return result;
} // pdf
template <class RealType, class Policy>
inline RealType logpdf(const normal_distribution<RealType, Policy>& dist, const RealType& x)
{
BOOST_MATH_STD_USING // for ADL of std functions
const RealType sd = dist.standard_deviation();
const RealType mean = dist.mean();
static const char* function = "boost::math::logpdf(const normal_distribution<%1%>&, %1%)";
RealType result = -std::numeric_limits<RealType>::infinity();
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))
{
return result; // pdf + and - infinity is zero so logpdf is -inf
}
if(false == detail::check_x(function, x, &result, Policy()))
{
return result;
}
const RealType pi = boost::math::constants::pi<RealType>();
const RealType half = boost::math::constants::half<RealType>();
result = -log(sd) - half*log(2*pi) - (x-mean)*(x-mean)/(2*sd*sd);
return result;
}
template <class RealType, class Policy>
inline RealType cdf(const normal_distribution<RealType, Policy>& dist, const RealType& x)
{
@@ -173,15 +219,6 @@ inline RealType cdf(const normal_distribution<RealType, Policy>& dist, const Rea
if(x < 0) return 0; // -infinity
return 1; // + infinity
}
// These produce MSVC 4127 warnings, so the above used instead.
//if(std::numeric_limits<RealType>::has_infinity && x == std::numeric_limits<RealType>::infinity())
//{ // cdf +infinity is unity.
// return 1;
//}
//if(std::numeric_limits<RealType>::has_infinity && x == -std::numeric_limits<RealType>::infinity())
//{ // cdf -infinity is zero.
// return 0;
//}
if(false == detail::check_x(function, x, &result, Policy()))
{
return result;
@@ -235,15 +272,6 @@ inline RealType cdf(const complemented2_type<normal_distribution<RealType, Polic
if(x < 0) return 1; // cdf complement -infinity is unity.
return 0; // cdf complement +infinity is zero
}
// These produce MSVC 4127 warnings, so the above used instead.
//if(std::numeric_limits<RealType>::has_infinity && x == std::numeric_limits<RealType>::infinity())
//{ // cdf complement +infinity is zero.
// return 0;
//}
//if(std::numeric_limits<RealType>::has_infinity && x == -std::numeric_limits<RealType>::infinity())
//{ // cdf complement -infinity is unity.
// return 1;
//}
if(false == detail::check_x(function, x, &result, Policy()))
return result;
@@ -316,6 +344,14 @@ inline RealType kurtosis_excess(const normal_distribution<RealType, Policy>& /*d
return 0;
}
template <class RealType, class Policy>
inline RealType entropy(const normal_distribution<RealType, Policy> & dist)
{
using std::log;
RealType arg = constants::two_pi<RealType>()*constants::e<RealType>()*dist.standard_deviation()*dist.standard_deviation();
return log(arg)/2;
}
} // namespace math
} // namespace boost

View File

@@ -1,5 +1,6 @@
// Copyright John Maddock 2007.
// Copyright Paul A. Bristow 2007, 2009
// Copyright Matt Borland 2023.
// 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)
@@ -20,8 +21,11 @@
#include <boost/math/distributions/complement.hpp>
#include <boost/math/distributions/detail/common_error_handling.hpp>
#include <boost/math/special_functions/powm1.hpp>
#include <boost/math/special_functions/log1p.hpp>
#include <utility> // for BOOST_CURRENT_VALUE?
#include <limits>
#include <cmath>
namespace boost
{
@@ -160,6 +164,14 @@ namespace boost
typedef pareto_distribution<double> pareto; // Convenience to allow pareto(2., 3.);
#ifdef __cpp_deduction_guides
template <class RealType>
pareto_distribution(RealType)->pareto_distribution<typename boost::math::tools::promote_args<RealType>::type>;
template <class RealType>
pareto_distribution(RealType,RealType)->pareto_distribution<typename boost::math::tools::promote_args<RealType>::type>;
#endif
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const pareto_distribution<RealType, Policy>& /*dist*/)
{ // Range of permissible values for random variable x.
@@ -217,6 +229,28 @@ namespace boost
return result;
} // cdf
template <class RealType, class Policy>
inline RealType logcdf(const pareto_distribution<RealType, Policy>& dist, const RealType& x)
{
BOOST_MATH_STD_USING // for ADL of std function pow.
static const char* function = "boost::math::logcdf(const pareto_distribution<%1%>&, %1%)";
RealType scale = dist.scale();
RealType shape = dist.shape();
RealType result = 0;
if(false == (detail::check_pareto_x(function, x, &result, Policy())
&& detail::check_pareto(function, scale, shape, &result, Policy())))
return result;
if (x <= scale)
{ // regardless of shape, cdf is zero.
return -std::numeric_limits<RealType>::infinity();
}
result = log1p(-pow(scale/x, shape), Policy());
return result;
} // logcdf
template <class RealType, class Policy>
inline RealType quantile(const pareto_distribution<RealType, Policy>& dist, const RealType& p)
{
@@ -266,6 +300,28 @@ namespace boost
return result;
} // cdf complement
template <class RealType, class Policy>
inline RealType logcdf(const complemented2_type<pareto_distribution<RealType, Policy>, RealType>& c)
{
BOOST_MATH_STD_USING // for ADL of std function pow.
static const char* function = "boost::math::logcdf(const pareto_distribution<%1%>&, %1%)";
RealType result = 0;
RealType x = c.param;
RealType scale = c.dist.scale();
RealType shape = c.dist.shape();
if(false == (detail::check_pareto_x(function, x, &result, Policy())
&& detail::check_pareto(function, scale, shape, &result, Policy())))
return result;
if (x <= scale)
{ // regardless of shape, cdf is zero, and complement is unity.
return 0;
}
result = log(pow((scale/x), shape));
return result;
} // logcdf complement
template <class RealType, class Policy>
inline RealType quantile(const complemented2_type<pareto_distribution<RealType, Policy>, RealType>& c)
{
@@ -431,6 +487,15 @@ namespace boost
return result;
} // kurtosis_excess
template <class RealType, class Policy>
inline RealType entropy(const pareto_distribution<RealType, Policy>& dist)
{
using std::log;
RealType xm = dist.scale();
RealType alpha = dist.shape();
return log(xm/alpha) + 1 + 1/alpha;
}
} // namespace math
} // namespace boost

View File

@@ -25,7 +25,7 @@
// is strictly defined as a discrete function:
// only integral values of k are envisaged.
// However because the method of calculation uses a continuous gamma function,
// it is convenient to treat it as if a continous function,
// it is convenient to treat it as if a continuous function,
// and permit non-integral values of k.
// To enforce the strict mathematical model, users should use floor or ceil functions
// on k outside this function to ensure that k is integral.
@@ -47,6 +47,7 @@
#include <boost/math/distributions/detail/inv_discrete_quantile.hpp>
#include <utility>
#include <limits>
namespace boost
{
@@ -144,10 +145,10 @@ namespace boost
class poisson_distribution
{
public:
typedef RealType value_type;
typedef Policy policy_type;
using value_type = RealType;
using policy_type = Policy;
poisson_distribution(RealType l_mean = 1) : m_l(l_mean) // mean (lambda).
explicit 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(
@@ -165,19 +166,24 @@ namespace boost
RealType m_l; // mean number of occurrences.
}; // template <class RealType, class Policy> class poisson_distribution
typedef poisson_distribution<double> poisson; // Reserved name of type double.
using poisson = poisson_distribution<double>; // Reserved name of type double.
#ifdef __cpp_deduction_guides
template <class RealType>
poisson_distribution(RealType)->poisson_distribution<typename boost::math::tools::promote_args<RealType>::type>;
#endif
// Non-member functions to give properties of the distribution.
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const poisson_distribution<RealType, Policy>& /* dist */)
inline std::pair<RealType, RealType> range(const poisson_distribution<RealType, Policy>& /* dist */)
{ // Range of permissible values for random variable k.
using boost::math::tools::max_value;
return std::pair<RealType, RealType>(static_cast<RealType>(0), max_value<RealType>()); // Max integer?
}
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> support(const poisson_distribution<RealType, Policy>& /* dist */)
inline std::pair<RealType, RealType> support(const poisson_distribution<RealType, Policy>& /* dist */)
{ // Range of supported values for random variable k.
// This is range where cdf rises from 0 to 1, and outside it, the pdf is zero.
using boost::math::tools::max_value;
@@ -197,15 +203,7 @@ namespace boost
return floor(dist.mean());
}
//template <class RealType, class Policy>
//inline RealType median(const poisson_distribution<RealType, Policy>& dist)
//{ // median = approximately lambda + 1/3 - 0.2/lambda
// RealType l = dist.mean();
// return dist.mean() + static_cast<RealType>(0.3333333333333333333333333333333333333333333333)
// - static_cast<RealType>(0.2) / l;
//} // BUT this formula appears to be out-by-one compared to quantile(half)
// Query posted on Wikipedia.
// Now implemented via quantile(half) in derived accessors.
// Median now implemented via quantile(half) in derived accessors.
template <class RealType, class Policy>
inline RealType variance(const poisson_distribution<RealType, Policy>& dist)
@@ -213,7 +211,6 @@ namespace boost
return dist.mean();
}
// RealType standard_deviation(const poisson_distribution<RealType, Policy>& dist)
// standard_deviation provided by derived accessors.
template <class RealType, class Policy>
@@ -235,7 +232,7 @@ namespace boost
template <class RealType, class Policy>
inline RealType kurtosis(const poisson_distribution<RealType, Policy>& dist)
{ // kurtosis is 4th moment about the mean = u4 / sd ^ 4
// http://en.wikipedia.org/wiki/Curtosis
// http://en.wikipedia.org/wiki/Kurtosis
// kurtosis can range from -2 (flat top) to +infinity (sharp peak & heavy tails).
// http://www.itl.nist.gov/div898/handbook/eda/section3/eda35b.htm
return 3 + 1 / dist.mean(); // NIST.
@@ -276,6 +273,42 @@ namespace boost
return boost::math::gamma_p_derivative(k+1, mean, Policy());
} // pdf
template <class RealType, class Policy>
RealType logpdf(const poisson_distribution<RealType, Policy>& dist, const RealType& k)
{
BOOST_FPU_EXCEPTION_GUARD
BOOST_MATH_STD_USING // for ADL of std functions.
using boost::math::lgamma;
RealType mean = dist.mean();
// Error check:
RealType result = -std::numeric_limits<RealType>::infinity();
if(false == poisson_detail::check_dist_and_k(
"boost::math::pdf(const poisson_distribution<%1%>&, %1%)",
mean,
k,
&result, Policy()))
{
return result;
}
// Special case of mean zero, regardless of the number of events k.
if (mean == 0)
{ // Probability for any k is zero.
return std::numeric_limits<RealType>::quiet_NaN();
}
// Special case where k and lambda are both positive
if(k > 0 && mean > 0)
{
return -lgamma(k+1) + k*log(mean) - mean;
}
result = log(pdf(dist, k));
return result;
}
template <class RealType, class Policy>
RealType cdf(const poisson_distribution<RealType, Policy>& dist, const RealType& k)
{ // Cumulative Distribution Function Poisson.
@@ -288,7 +321,7 @@ namespace boost
// (like others including the binomial, negative binomial & Bernoulli)
// is strictly defined as a discrete function: only integral values of k are envisaged.
// However because of the method of calculation using a continuous gamma function,
// it is convenient to treat it as if it is a continous function
// it is convenient to treat it as if it is a continuous function
// and permit non-integral values of k.
// To enforce the strict mathematical model, users should use floor or ceil functions
// outside this function to ensure that k is integral.
@@ -315,8 +348,8 @@ namespace boost
return 0;
}
if (k == 0)
{ // return pdf(dist, static_cast<RealType>(0));
// but mean (and k) have already been checked,
{
// mean (and k) have already been checked,
// so this avoids unnecessary repeated checks.
return exp(-mean);
}
@@ -337,7 +370,7 @@ namespace boost
// (like others including the binomial, negative binomial & Bernoulli)
// is strictly defined as a discrete function: only integral values of k are envisaged.
// However because of the method of calculation using a continuous gamma function,
// it is convenient to treat it as is it is a continous function
// it is convenient to treat it as is it is a continuous function
// and permit non-integral values of k.
// To enforce the strict mathematical model, users should use floor or ceil functions
// outside this function to ensure that k is integral.
@@ -409,9 +442,10 @@ namespace boost
{
return policies::raise_overflow_error<RealType>(function, 0, Policy());
}
typedef typename Policy::discrete_quantile_type discrete_type;
boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
RealType guess, factor = 8;
using discrete_type = typename Policy::discrete_quantile_type;
std::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
RealType guess;
RealType factor = 8;
RealType z = dist.mean();
if(z < 1)
guess = z;
@@ -479,9 +513,10 @@ namespace boost
{
return 0; // Exact result regardless of discrete-quantile Policy
}
typedef typename Policy::discrete_quantile_type discrete_type;
boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
RealType guess, factor = 8;
using discrete_type = typename Policy::discrete_quantile_type;
std::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
RealType guess;
RealType factor = 8;
RealType z = dist.mean();
if(z < 1)
guess = z;
@@ -519,7 +554,6 @@ namespace boost
// 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/inv_discrete_quantile.hpp>
#endif // BOOST_MATH_SPECIAL_POISSON_HPP

View File

@@ -1,4 +1,5 @@
// Copyright Paul A. Bristow 2007.
// Copyright Matt Borland 2023.
// 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)
@@ -12,14 +13,15 @@
#include <boost/math/special_functions/expm1.hpp>
#include <boost/math/distributions/complement.hpp>
#include <boost/math/distributions/detail/common_error_handling.hpp>
#include <boost/config/no_tr1/cmath.hpp>
#ifdef BOOST_MSVC
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable: 4702) // unreachable code (return after domain_error throw).
#endif
#include <utility>
#include <limits>
#include <cmath>
namespace boost{ namespace math{
@@ -56,10 +58,10 @@ template <class RealType = double, class Policy = policies::policy<> >
class rayleigh_distribution
{
public:
typedef RealType value_type;
typedef Policy policy_type;
using value_type = RealType;
using policy_type = Policy;
rayleigh_distribution(RealType l_sigma = 1)
explicit rayleigh_distribution(RealType l_sigma = 1)
: m_sigma(l_sigma)
{
RealType err;
@@ -75,17 +77,22 @@ private:
RealType m_sigma;
}; // class rayleigh_distribution
typedef rayleigh_distribution<double> rayleigh;
using rayleigh = rayleigh_distribution<double>;
#ifdef __cpp_deduction_guides
template <class RealType>
rayleigh_distribution(RealType)->rayleigh_distribution<typename boost::math::tools::promote_args<RealType>::type>;
#endif
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const rayleigh_distribution<RealType, Policy>& /*dist*/)
inline 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), std::numeric_limits<RealType>::has_infinity ? std::numeric_limits<RealType>::infinity() : max_value<RealType>());
}
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> support(const rayleigh_distribution<RealType, Policy>& /*dist*/)
inline std::pair<RealType, RealType> support(const rayleigh_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.
using boost::math::tools::max_value;
@@ -117,6 +124,32 @@ inline RealType pdf(const rayleigh_distribution<RealType, Policy>& dist, const R
return result;
} // pdf
template <class RealType, class Policy>
inline RealType logpdf(const rayleigh_distribution<RealType, Policy>& dist, const RealType& x)
{
BOOST_MATH_STD_USING // for ADL of std function exp.
const RealType sigma = dist.sigma();
RealType result = -std::numeric_limits<RealType>::infinity();
static const char* function = "boost::math::logpdf(const rayleigh_distribution<%1%>&, %1%)";
if(false == detail::verify_sigma(function, sigma, &result, Policy()))
{
return result;
}
if(false == detail::verify_rayleigh_x(function, x, &result, Policy()))
{
return result;
}
if((boost::math::isinf)(x))
{
return result;
}
result = -(x*x)/(2*sigma*sigma) - 2*log(sigma) + log(x);
return result;
} // logpdf
template <class RealType, class Policy>
inline RealType cdf(const rayleigh_distribution<RealType, Policy>& dist, const RealType& x)
{
@@ -137,6 +170,26 @@ inline RealType cdf(const rayleigh_distribution<RealType, Policy>& dist, const R
return result;
} // cdf
template <class RealType, class Policy>
inline RealType logcdf(const rayleigh_distribution<RealType, Policy>& dist, const RealType& x)
{
BOOST_MATH_STD_USING // for ADL of std functions
RealType result = 0;
RealType sigma = dist.sigma();
static const char* function = "boost::math::logcdf(const rayleigh_distribution<%1%>&, %1%)";
if(false == detail::verify_sigma(function, sigma, &result, Policy()))
{
return -std::numeric_limits<RealType>::infinity();
}
if(false == detail::verify_rayleigh_x(function, x, &result, Policy()))
{
return -std::numeric_limits<RealType>::infinity();
}
result = log1p(-exp(-x * x / ( 2 * sigma * sigma)), Policy());
return result;
} // logcdf
template <class RealType, class Policy>
inline RealType quantile(const rayleigh_distribution<RealType, Policy>& dist, const RealType& p)
{
@@ -187,6 +240,31 @@ inline RealType cdf(const complemented2_type<rayleigh_distribution<RealType, Pol
return result;
} // cdf complement
template <class RealType, class Policy>
inline RealType logcdf(const complemented2_type<rayleigh_distribution<RealType, Policy>, RealType>& c)
{
BOOST_MATH_STD_USING // for ADL of std functions
RealType result = 0;
RealType sigma = c.dist.sigma();
static const char* function = "boost::math::logcdf(const rayleigh_distribution<%1%>&, %1%)";
if(false == detail::verify_sigma(function, sigma, &result, Policy()))
{
return -std::numeric_limits<RealType>::infinity();
}
RealType x = c.param;
if(false == detail::verify_rayleigh_x(function, x, &result, Policy()))
{
return -std::numeric_limits<RealType>::infinity();
}
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 = -ea;
return result;
} // logcdf complement
template <class RealType, class Policy>
inline RealType quantile(const complemented2_type<rayleigh_distribution<RealType, Policy>, RealType>& c)
{
@@ -260,36 +338,38 @@ inline RealType median(const rayleigh_distribution<RealType, Policy>& dist)
template <class RealType, class Policy>
inline RealType skewness(const rayleigh_distribution<RealType, Policy>& /*dist*/)
{
// using namespace boost::math::constants;
return static_cast<RealType>(0.63111065781893713819189935154422777984404221106391L);
// Computed using NTL at 150 bit, about 50 decimal digits.
// return 2 * root_pi<RealType>() * pi_minus_three<RealType>() / pow23_four_minus_pi<RealType>();
// 2 * sqrt(pi) * (pi-3) / pow(4, 2/3) - pi
}
template <class RealType, class Policy>
inline RealType kurtosis(const rayleigh_distribution<RealType, Policy>& /*dist*/)
{
// using namespace boost::math::constants;
return static_cast<RealType>(3.2450893006876380628486604106197544154170667057995L);
// Computed using NTL at 150 bit, about 50 decimal digits.
// return 3 - (6 * pi<RealType>() * pi<RealType>() - 24 * pi<RealType>() + 16) /
// (four_minus_pi<RealType>() * four_minus_pi<RealType>());
// 3 - (6*pi*pi - 24*pi + 16) / pow(4-pi, 2)
}
template <class RealType, class Policy>
inline RealType kurtosis_excess(const rayleigh_distribution<RealType, Policy>& /*dist*/)
{
//using namespace boost::math::constants;
// Computed using NTL at 150 bit, about 50 decimal digits.
return static_cast<RealType>(0.2450893006876380628486604106197544154170667057995L);
// return -(6 * pi<RealType>() * pi<RealType>() - 24 * pi<RealType>() + 16) /
// (four_minus_pi<RealType>() * four_minus_pi<RealType>());
} // kurtosis
// Computed using NTL at 150 bit, about 50 decimal digits.
// -(6*pi*pi - 24*pi + 16) / pow(4-pi,2)
} // kurtosis_excess
template <class RealType, class Policy>
inline RealType entropy(const rayleigh_distribution<RealType, Policy>& dist)
{
using std::log;
return 1 + log(dist.sigma()*constants::one_div_root_two<RealType>()) + constants::euler<RealType>()/2;
}
} // namespace math
} // namespace boost
#ifdef BOOST_MSVC
#ifdef _MSC_VER
# pragma warning(pop)
#endif

View File

@@ -21,7 +21,7 @@
#include <boost/math/constants/constants.hpp>
#include <boost/math/tools/tuple.hpp>
#include <boost/math/tools/roots.hpp> // Newton-Raphson
#include <boost/assert.hpp>
#include <boost/math/tools/assert.hpp>
#include <boost/math/distributions/detail/generic_mode.hpp> // pdf max finder.
#include <utility>
@@ -70,17 +70,17 @@ namespace boost{ namespace math{
}
RealType location()const
{
{
return location_;
}
RealType scale()const
{
{
return scale_;
}
RealType shape()const
{
{
return shape_;
}
@@ -96,12 +96,21 @@ namespace boost{ namespace math{
typedef skew_normal_distribution<double> skew_normal;
#ifdef __cpp_deduction_guides
template <class RealType>
skew_normal_distribution(RealType)->skew_normal_distribution<typename boost::math::tools::promote_args<RealType>::type>;
template <class RealType>
skew_normal_distribution(RealType,RealType)->skew_normal_distribution<typename boost::math::tools::promote_args<RealType>::type>;
template <class RealType>
skew_normal_distribution(RealType,RealType,RealType)->skew_normal_distribution<typename boost::math::tools::promote_args<RealType>::type>;
#endif
template <class RealType, class Policy>
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>(
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>(),
std::numeric_limits<RealType>::has_infinity ? std::numeric_limits<RealType>::infinity() : max_value<RealType>()); // - to + max value.
}
@@ -287,7 +296,7 @@ namespace boost{ namespace math{
{
using namespace boost::math::constants;
const RealType delta2 = static_cast<RealType>(1) / (static_cast<RealType>(1)+static_cast<RealType>(1)/(dist.shape()*dist.shape()));
const RealType delta2 = dist.shape() != 0 ? static_cast<RealType>(1) / (static_cast<RealType>(1)+static_cast<RealType>(1)/(dist.shape()*dist.shape())) : static_cast<RealType>(0);
//const RealType inv_delta2 = static_cast<RealType>(1)+static_cast<RealType>(1)/(dist.shape()*dist.shape());
RealType variance = dist.scale()*dist.scale()*(static_cast<RealType>(1)-two_div_pi<RealType>()*delta2);
@@ -301,7 +310,7 @@ namespace boost{ namespace math{
/*
TODO No closed expression for mode, so use max of pdf.
*/
template <class RealType, class Policy>
inline RealType mode_fallback(const skew_normal_distribution<RealType, Policy>& dist)
{ // mode.
@@ -309,7 +318,7 @@ namespace boost{ namespace math{
const RealType scale = dist.scale();
const RealType location = dist.location();
const RealType shape = dist.shape();
RealType result;
if(!detail::check_scale(
function,
@@ -334,7 +343,7 @@ namespace boost{ namespace math{
result = location-scale*result;
return result;
}
BOOST_MATH_STD_USING
// 21 elements
@@ -389,10 +398,10 @@ namespace boost{ namespace math{
const RealType* result_ptr = std::lower_bound(shapes, shapes+21, shape);
typedef typename std::iterator_traits<RealType*>::difference_type diff_type;
const diff_type d = std::distance(shapes, result_ptr);
BOOST_ASSERT(d > static_cast<diff_type>(0));
BOOST_MATH_ASSERT(d > static_cast<diff_type>(0));
// refine
if(d < static_cast<diff_type>(21)) // shape smaller 100
@@ -407,21 +416,21 @@ namespace boost{ namespace math{
}
skew_normal_distribution<RealType, Policy> helper(0, 1, shape);
result = detail::generic_find_mode_01(helper, result, function);
result = result*scale + location;
return result;
} // mode_fallback
/*
* TODO No closed expression for mode, so use f'(x) = 0
*/
template <class RealType, class Policy>
struct skew_normal_mode_functor
{
{
skew_normal_mode_functor(const boost::math::skew_normal_distribution<RealType, Policy> dist)
: distribution(dist)
{
@@ -442,9 +451,9 @@ namespace boost{ namespace math{
private:
const boost::math::skew_normal_distribution<RealType, Policy> distribution;
};
} // namespace detail
template <class RealType, class Policy>
inline RealType mode(const skew_normal_distribution<RealType, Policy>& dist)
{
@@ -477,7 +486,7 @@ namespace boost{ namespace math{
// 21 elements
static const RealType shapes[] = {
0.0,
static_cast<RealType>(0.0),
static_cast<RealType>(1.000000000000000e-004),
static_cast<RealType>(2.069138081114790e-004),
static_cast<RealType>(4.281332398719396e-004),
@@ -502,7 +511,7 @@ namespace boost{ namespace math{
// 21 elements
static const RealType guess[] = {
0.0,
static_cast<RealType>(0.0),
static_cast<RealType>(5.000050000525391e-005),
static_cast<RealType>(1.500015000148736e-004),
static_cast<RealType>(3.500035000350010e-004),
@@ -528,10 +537,10 @@ namespace boost{ namespace math{
const RealType* result_ptr = std::lower_bound(shapes, shapes+21, shape);
typedef typename std::iterator_traits<RealType*>::difference_type diff_type;
const diff_type d = std::distance(shapes, result_ptr);
BOOST_ASSERT(d > static_cast<diff_type>(0));
BOOST_MATH_ASSERT(d > static_cast<diff_type>(0));
// TODO: make the search bounds smarter, depending on the shape parameter
RealType search_min = 0; // below zero was caught above
@@ -550,22 +559,22 @@ namespace boost{ namespace math{
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
}
const int get_digits = policies::digits<RealType, Policy>();// get digits from policy,
boost::uintmax_t m = policies::get_max_root_iterations<Policy>(); // and max iterations.
const int get_digits = policies::digits<RealType, Policy>();// get digits from policy,
std::uintmax_t m = policies::get_max_root_iterations<Policy>(); // and max iterations.
skew_normal_distribution<RealType, Policy> helper(0, 1, shape);
result = tools::newton_raphson_iterate(detail::skew_normal_mode_functor<RealType, Policy>(helper), result,
search_min, search_max, get_digits, m);
result = result*scale + location;
return result;
}
template <class RealType, class Policy>
inline RealType skewness(const skew_normal_distribution<RealType, Policy>& dist)
{
@@ -575,8 +584,8 @@ namespace boost{ namespace math{
static const RealType factor = four_minus_pi<RealType>()/static_cast<RealType>(2);
const RealType delta = dist.shape() / sqrt(static_cast<RealType>(1)+dist.shape()*dist.shape());
return factor * pow(root_two_div_pi<RealType>() * delta, 3) /
pow(static_cast<RealType>(1)-two_div_pi<RealType>()*delta*delta, static_cast<RealType>(1.5));
return static_cast<RealType>(factor * pow(root_two_div_pi<RealType>() * delta, 3) /
pow(static_cast<RealType>(1)-two_div_pi<RealType>()*delta*delta, static_cast<RealType>(1.5)));
}
template <class RealType, class Policy>
@@ -592,7 +601,7 @@ namespace boost{ namespace math{
static const RealType factor = pi_minus_three<RealType>()*static_cast<RealType>(2);
const RealType delta2 = static_cast<RealType>(1) / (static_cast<RealType>(1)+static_cast<RealType>(1)/(dist.shape()*dist.shape()));
const RealType delta2 = dist.shape() != 0 ? static_cast<RealType>(1) / (static_cast<RealType>(1)+static_cast<RealType>(1)/(dist.shape()*dist.shape())) : static_cast<RealType>(0);
const RealType x = static_cast<RealType>(1)-two_div_pi<RealType>()*delta2;
const RealType y = two_div_pi<RealType>() * delta2;
@@ -605,7 +614,7 @@ namespace boost{ namespace math{
template <class RealType, class Policy>
struct skew_normal_quantile_functor
{
{
skew_normal_quantile_functor(const boost::math::skew_normal_distribution<RealType, Policy> dist, RealType const& p)
: distribution(dist), prob(p)
{
@@ -621,7 +630,7 @@ namespace boost{ namespace math{
}
private:
const boost::math::skew_normal_distribution<RealType, Policy> distribution;
RealType prob;
RealType prob;
};
} // namespace detail
@@ -670,8 +679,8 @@ namespace boost{ namespace math{
const RealType search_min = range(dist).first;
const RealType search_max = range(dist).second;
const int get_digits = policies::digits<RealType, Policy>();// get digits from policy,
boost::uintmax_t m = policies::get_max_root_iterations<Policy>(); // and max iterations.
const int get_digits = policies::digits<RealType, Policy>();// get digits from policy,
std::uintmax_t m = policies::get_max_root_iterations<Policy>(); // and max iterations.
result = tools::newton_raphson_iterate(detail::skew_normal_quantile_functor<RealType, Policy>(dist, p), result,
search_min, search_max, get_digits, m);

View File

@@ -14,13 +14,14 @@
#include <boost/math/distributions/fwd.hpp>
#include <boost/math/special_functions/beta.hpp> // for ibeta(a, b, x).
#include <boost/math/special_functions/digamma.hpp>
#include <boost/math/distributions/complement.hpp>
#include <boost/math/distributions/detail/common_error_handling.hpp>
#include <boost/math/distributions/normal.hpp>
#include <utility>
#ifdef BOOST_MSVC
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable: 4702) // unreachable code (return after domain_error throw).
#endif
@@ -61,6 +62,11 @@ private:
typedef students_t_distribution<double> students_t; // Convenience typedef for double version.
#ifdef __cpp_deduction_guides
template <class RealType>
students_t_distribution(RealType)->students_t_distribution<typename boost::math::tools::promote_args<RealType>::type>;
#endif
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.
@@ -324,7 +330,7 @@ RealType students_t_distribution<RealType, Policy>::find_degrees_of_freedom(
detail::sample_size_func<RealType, Policy> f(alpha, beta, sd, difference_from_mean);
tools::eps_tolerance<RealType> tol(policies::digits<RealType, Policy>());
boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
std::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
std::pair<RealType, RealType> r = tools::bracket_and_solve_root(f, hint, RealType(2), false, tol, max_iter, Policy());
RealType result = r.first + (r.second - r.first) / 2;
if(max_iter >= policies::get_max_root_iterations<Policy>())
@@ -478,10 +484,22 @@ inline RealType kurtosis_excess(const students_t_distribution<RealType, Policy>&
}
}
template <class RealType, class Policy>
inline RealType entropy(const students_t_distribution<RealType, Policy>& dist)
{
using std::log;
using std::sqrt;
RealType v = dist.degrees_of_freedom();
RealType vp1 = (v+1)/2;
RealType vd2 = v/2;
return vp1*(digamma(vp1) - digamma(vd2)) + log(sqrt(v)*beta(vd2, RealType(1)/RealType(2)));
}
} // namespace math
} // namespace boost
#ifdef BOOST_MSVC
#ifdef _MSC_VER
# pragma warning(pop)
#endif

View File

@@ -184,6 +184,15 @@ namespace boost{ namespace math
typedef triangular_distribution<double> triangular;
#ifdef __cpp_deduction_guides
template <class RealType>
triangular_distribution(RealType)->triangular_distribution<typename boost::math::tools::promote_args<RealType>::type>;
template <class RealType>
triangular_distribution(RealType,RealType)->triangular_distribution<typename boost::math::tools::promote_args<RealType>::type>;
template <class RealType>
triangular_distribution(RealType,RealType,RealType)->triangular_distribution<typename boost::math::tools::promote_args<RealType>::type>;
#endif
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const triangular_distribution<RealType, Policy>& /* dist */)
{ // Range of permissible values for random variable x.
@@ -517,6 +526,13 @@ namespace boost{ namespace math
// Assuming mathworld really means kurtosis excess? Wikipedia now corrected to match this.
}
template <class RealType, class Policy>
inline RealType entropy(const triangular_distribution<RealType, Policy>& dist)
{
using std::log;
return constants::half<RealType>() + log((dist.upper() - dist.lower())/2);
}
} // namespace math
} // namespace boost

View File

@@ -140,6 +140,13 @@ namespace boost{ namespace math
typedef uniform_distribution<double> uniform;
#ifdef __cpp_deduction_guides
template <class RealType>
uniform_distribution(RealType)->uniform_distribution<typename boost::math::tools::promote_args<RealType>::type>;
template <class RealType>
uniform_distribution(RealType,RealType)->uniform_distribution<typename boost::math::tools::promote_args<RealType>::type>;
#endif
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const uniform_distribution<RealType, Policy>& /* dist */)
{ // Range of permissible values for random variable x.
@@ -355,7 +362,7 @@ namespace boost{ namespace math
RealType lower = dist.lower();
RealType upper = dist.upper();
RealType result = 0; // of checks.
if(false == detail::check_uniform("boost::math::kurtosis_execess(const uniform_distribution<%1%>&)", lower, upper, &result, Policy()))
if(false == detail::check_uniform("boost::math::kurtosis_excess(const uniform_distribution<%1%>&)", lower, upper, &result, Policy()))
{
return result;
}
@@ -368,6 +375,13 @@ namespace boost{ namespace math
return kurtosis_excess(dist) + 3;
}
template <class RealType, class Policy>
inline RealType entropy(const uniform_distribution<RealType, Policy>& dist)
{
using std::log;
return log(dist.upper() - dist.lower());
}
} // namespace math
} // namespace boost

View File

@@ -70,10 +70,10 @@ template <class RealType = double, class Policy = policies::policy<> >
class weibull_distribution
{
public:
typedef RealType value_type;
typedef Policy policy_type;
using value_type = RealType;
using policy_type = Policy;
weibull_distribution(RealType l_shape, RealType l_scale = 1)
explicit weibull_distribution(RealType l_shape, RealType l_scale = 1)
: m_shape(l_shape), m_scale(l_scale)
{
RealType result;
@@ -97,17 +97,24 @@ private:
RealType m_scale; // distribution scale
};
typedef weibull_distribution<double> weibull;
using weibull = weibull_distribution<double>;
#ifdef __cpp_deduction_guides
template <class RealType>
weibull_distribution(RealType)->weibull_distribution<typename boost::math::tools::promote_args<RealType>::type>;
template <class RealType>
weibull_distribution(RealType,RealType)->weibull_distribution<typename boost::math::tools::promote_args<RealType>::type>;
#endif
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const weibull_distribution<RealType, Policy>& /*dist*/)
inline std::pair<RealType, RealType> range(const weibull_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>());
}
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> support(const weibull_distribution<RealType, Policy>& /*dist*/)
inline std::pair<RealType, RealType> support(const weibull_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.
using boost::math::tools::max_value;
@@ -150,6 +157,40 @@ inline RealType pdf(const weibull_distribution<RealType, Policy>& dist, const Re
return result;
}
template <class RealType, class Policy>
inline RealType logpdf(const weibull_distribution<RealType, Policy>& dist, const RealType& x)
{
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::logpdf(const weibull_distribution<%1%>, %1%)";
RealType shape = dist.shape();
RealType scale = dist.scale();
RealType result = 0;
if(false == detail::check_weibull(function, scale, shape, &result, Policy()))
return result;
if(false == detail::check_weibull_x(function, x, &result, Policy()))
return result;
if(x == 0)
{
if(shape == 1)
{
return log(1 / scale);
}
if(shape > 1)
{
return 0;
}
return policies::raise_overflow_error<RealType>(function, 0, Policy());
}
result = log(shape) - shape * log(scale) + log(x) * (shape - 1) - pow(x / scale, shape);
return result;
}
template <class RealType, class Policy>
inline RealType cdf(const weibull_distribution<RealType, Policy>& dist, const RealType& x)
{
@@ -171,6 +212,27 @@ inline RealType cdf(const weibull_distribution<RealType, Policy>& dist, const Re
return result;
}
template <class RealType, class Policy>
inline RealType logcdf(const weibull_distribution<RealType, Policy>& dist, const RealType& x)
{
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::logcdf(const weibull_distribution<%1%>, %1%)";
RealType shape = dist.shape();
RealType scale = dist.scale();
RealType result = 0;
if(false == detail::check_weibull(function, scale, shape, &result, Policy()))
return result;
if(false == detail::check_weibull_x(function, x, &result, Policy()))
return result;
result = log1p(-exp(-pow(x / scale, shape)), Policy());
return result;
}
template <class RealType, class Policy>
inline RealType quantile(const weibull_distribution<RealType, Policy>& dist, const RealType& p)
{
@@ -216,6 +278,27 @@ inline RealType cdf(const complemented2_type<weibull_distribution<RealType, Poli
return result;
}
template <class RealType, class Policy>
inline RealType logcdf(const complemented2_type<weibull_distribution<RealType, Policy>, RealType>& c)
{
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::logcdf(const weibull_distribution<%1%>, %1%)";
RealType shape = c.dist.shape();
RealType scale = c.dist.scale();
RealType result = 0;
if(false == detail::check_weibull(function, scale, shape, &result, Policy()))
return result;
if(false == detail::check_weibull_x(function, c.param, &result, Policy()))
return result;
result = -pow(c.param / scale, shape);
return result;
}
template <class RealType, class Policy>
inline RealType quantile(const complemented2_type<weibull_distribution<RealType, Policy>, RealType>& c)
{
@@ -335,12 +418,11 @@ inline RealType skewness(const weibull_distribution<RealType, Policy>& dist)
{
return result;
}
RealType g1, g2, g3, d;
g1 = boost::math::tgamma(1 + 1 / shape, Policy());
g2 = boost::math::tgamma(1 + 2 / shape, Policy());
g3 = boost::math::tgamma(1 + 3 / shape, Policy());
d = pow(g2 - g1 * g1, RealType(1.5));
RealType g1 = boost::math::tgamma(1 + 1 / shape, Policy());
RealType g2 = boost::math::tgamma(1 + 2 / shape, Policy());
RealType g3 = boost::math::tgamma(1 + 3 / shape, Policy());
RealType d = pow(g2 - g1 * g1, RealType(1.5));
result = (2 * g1 * g1 * g1 - 3 * g1 * g2 + g3) / d;
return result;
@@ -360,15 +442,13 @@ inline RealType kurtosis_excess(const weibull_distribution<RealType, Policy>& di
if(false == detail::check_weibull(function, scale, shape, &result, Policy()))
return result;
RealType g1, g2, g3, g4, d, g1_2, g1_4;
g1 = boost::math::tgamma(1 + 1 / shape, Policy());
g2 = boost::math::tgamma(1 + 2 / shape, Policy());
g3 = boost::math::tgamma(1 + 3 / shape, Policy());
g4 = boost::math::tgamma(1 + 4 / shape, Policy());
g1_2 = g1 * g1;
g1_4 = g1_2 * g1_2;
d = g2 - g1_2;
RealType g1 = boost::math::tgamma(1 + 1 / shape, Policy());
RealType g2 = boost::math::tgamma(1 + 2 / shape, Policy());
RealType g3 = boost::math::tgamma(1 + 3 / shape, Policy());
RealType g4 = boost::math::tgamma(1 + 4 / shape, Policy());
RealType g1_2 = g1 * g1;
RealType g1_4 = g1_2 * g1_2;
RealType d = g2 - g1_2;
d *= d;
result = -6 * g1_4 + 12 * g1_2 * g2 - 3 * g2 * g2 - 4 * g1 * g3 + g4;
@@ -382,6 +462,15 @@ inline RealType kurtosis(const weibull_distribution<RealType, Policy>& dist)
return kurtosis_excess(dist) + 3;
}
template <class RealType, class Policy>
inline RealType entropy(const weibull_distribution<RealType, Policy>& dist)
{
using std::log;
RealType k = dist.shape();
RealType lambda = dist.scale();
return constants::euler<RealType>()*(1-1/k) + log(lambda/k) + 1;
}
} // namespace math
} // namespace boost