2
0
mirror of https://github.com/boostorg/math.git synced 2026-01-19 04:22:09 +00:00

Merged from branch 'hyper_exponential'.

This commit is contained in:
sguazt
2014-08-25 10:38:57 +02:00
3 changed files with 146 additions and 291 deletions

View File

@@ -33,6 +33,10 @@
#include <utility>
#include <vector>
#ifdef BOOST_MSVC
#pragma warning (push)
#pragma warning(disable:4127) // conditional expression is constant
#endif
namespace boost { namespace math {
@@ -157,11 +161,12 @@ bool check_rates(char const* function, std::vector<RealT> const& rates, RealT* p
template <typename RealT, typename PolicyT>
bool check_dist(char const* function, std::vector<RealT> const& probabilities, std::vector<RealT> const& rates, RealT* presult, PolicyT const& pol)
{
BOOST_MATH_STD_USING
if (probabilities.size() != rates.size())
{
*presult = policies::raise_domain_error<RealT>(function,
"The parameters \"probabilities\" and \"rates\" must have the same length, but their size differ by: %1%.",
std::abs(static_cast<RealT>(probabilities.size())-static_cast<RealT>(rates.size())),
fabs(static_cast<RealT>(probabilities.size())-static_cast<RealT>(rates.size())),
pol);
return false;
}
@@ -274,8 +279,6 @@ class hyperexponential_distribution
: probs_(prob_first, prob_last),
rates_(rate_first, rate_last)
{
hyperexp_detail::normalize(probs_);
RealT err;
hyperexp_detail::check_dist("boost::math::hyperexponential_distribution<%1%>::hyperexponential_distribution",
probs_,
@@ -289,6 +292,8 @@ class hyperexponential_distribution
: probs_(boost::begin(prob_range), boost::end(prob_range)),
rates_(boost::begin(rate_range), boost::end(rate_range))
{
assert(probs_.size() == rates_.size());
hyperexp_detail::normalize(probs_);
RealT err;
@@ -347,6 +352,7 @@ std::pair<RealT,RealT> support(hyperexponential_distribution<RealT,PolicyT> cons
template <typename RealT, typename PolicyT>
RealT pdf(hyperexponential_distribution<RealT, PolicyT> const& dist, RealT const& x)
{
BOOST_MATH_STD_USING
RealT result = 0;
if (!hyperexp_detail::check_x("boost::math::pdf(const boost::math::hyperexponential_distribution<%1%>&, %1%)", x, &result, PolicyT()))
@@ -360,11 +366,10 @@ RealT pdf(hyperexponential_distribution<RealT, PolicyT> const& dist, RealT const
for (std::size_t i = 0; i < n; ++i)
{
//result += probs[i]*rates[i]*std::exp(-rates[i]*x);
//const exponential_distribution<RealT,PolicyT> exp(rates[i]);
const exponential_distribution<RealT,PolicyT> exp(rates[i]);
result += probs[i]*pdf(exp, x);
//result += probs[i]*pdf(exp, x);
result += probs[i]*rates[i]*exp(-rates[i]*x);
}
return result;
@@ -473,7 +478,7 @@ RealT variance(hyperexponential_distribution<RealT, PolicyT> const& dist)
const RealT mean = boost::math::mean(dist);
result = 2.0*result-mean*mean;
result = 2*result-mean*mean;
return result;
}
@@ -482,7 +487,7 @@ template <typename RealT, typename PolicyT>
RealT skewness(hyperexponential_distribution<RealT,PolicyT> const& dist)
{
// (6(\sum_{i=1}^n\frac{p_i}{\lambda_i^3}) - (3(2(\sum_{i=1}^n\frac{p_i}{\lambda_i^2) - (\sum_{i=1}^n\frac{p_i}{\lambda_i})^2) + (\sum_{i=1}^n\frac{p_i}{\lambda_i})^2)(\sum_{i=1}^n\frac{p_i}{\lambda_i}))/((\sum_{i=1}^n\frac{p_i}{\lambda_i^2})-(\sum_{i=1}^n\frac{p_i}{\lambda_i})^2)^(3/2)
BOOST_MATH_STD_USING
const std::size_t n = dist.num_phases();
const std::vector<RealT> probs = dist.probabilities();
const std::vector<RealT> rates = dist.rates();
@@ -504,10 +509,10 @@ RealT skewness(hyperexponential_distribution<RealT,PolicyT> const& dist)
const RealT s1s1 = s1*s1;
const RealT num = (6.0*s3 - (3.0*(2.0*s2 - s1s1) + s1s1)*s1);
const RealT den = (2.0*s2 - s1s1);
const RealT num = (6*s3 - (3*(2*s2 - s1s1) + s1s1)*s1);
const RealT den = (2*s2 - s1s1);
return num/std::pow(den, 1.5);
return num / pow(den, static_cast<RealT>(1.5));
}
template <typename RealT, typename PolicyT>
@@ -539,8 +544,8 @@ RealT kurtosis(hyperexponential_distribution<RealT,PolicyT> const& dist)
const RealT s1s1 = s1*s1;
const RealT num = (24.0*s4 - 24.0*s3*s1 + 3.0*(2.0*(2.0*s2 - s1s1) + s1s1)*s1s1);
const RealT den = (2.0*s2 - s1s1);
const RealT num = (24*s4 - 24*s3*s1 + 3*(2*(2*s2 - s1s1) + s1s1)*s1s1);
const RealT den = (2*s2 - s1s1);
return num/(den*den);
}
@@ -559,6 +564,9 @@ RealT mode(hyperexponential_distribution<RealT,PolicyT> const& /*dist*/)
}} // namespace boost::math
#ifdef BOOST_MSVC
#pragma warning (pop)
#endif
// This include must be at the end, *after* the accessors
// for this distribution have been defined, in order to
// keep compilers that support two-phase lookup happy.

View File

@@ -66,6 +66,7 @@ void instantiate(RealType)
function_requires<DistributionConcept<gamma_distribution<RealType> > >();
function_requires<DistributionConcept<geometric_distribution<RealType> > >();
function_requires<DistributionConcept<hypergeometric_distribution<RealType> > >();
function_requires<DistributionConcept<hyperexponential_distribution<RealType> > >();
function_requires<DistributionConcept<inverse_chi_squared_distribution<RealType> > >();
function_requires<DistributionConcept<inverse_gamma_distribution<RealType> > >();
function_requires<DistributionConcept<inverse_gaussian_distribution<RealType> > >();

View File

@@ -20,116 +20,84 @@
#include <iostream>
#include <vector>
#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
# define HYPEREXP_TEST_LONGDOUBLE(test) (test)()
typedef boost::mpl::list<float, double, long double, boost::math::concepts::real_concept> test_types;
#else
# define HYPEREXP_TEST_LONGDOUBLE(test) \
std::cout << "<note>The long double tests have been disabled on this platform " \
"either because the long double overloads of the usual math functions are " \
"not available at all, or because they are too inaccurate for these tests " \
"to pass.</note>" << std::cout
#endif // BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
// We must use a low precision since it seems the involved computations are very challenging from the numerical point of view.
// Indeed, both Octave 3.6.4, MATLAB 2012a and Mathematica 10 provides different results.
// E.g.:
// x = [0 1 2 3 4]
// p = [0.2 0.3 0.5]
// r = [0.5 1.0 1.5]
// PDF(x)
// - MATLAB: 1.033333333333333, 0.335636985323608, 0.135792553231720, 0.061039382459897, 0.028790027125382
// - Octave: 1.0333333333333332, 0.3356369853236084, 0.1357925532317197, 0.0610393824598966, 0.0287900271253818
// - Mathematica: 1.15, 0.3383645184340184, 0.11472883036402601, 0.04558088392888389, 0.02088728412278129
//
// (Tested under Fedora Linux 20 x86_64 running on Intel(R) Core(TM) i7-3540M)
//
template <typename RealT>
struct make_tolerance_impl
{
RealT operator()() const
{
/*[code snippet taken from hypergeometric]
RealT tol = std::max(boost::math::tools::epsilon<RealT>(),
static_cast<RealT>(boost::math::tools::epsilon<double>()*5)*150);
// At float precision we need to up the tolerance, since
// the input values are rounded off to inexact quantities
// the results get thrown off by a noticeable amount.
if (boost::math::tools::digits<RealT>() < 50)
{
tol *= 50;
}
if (boost::is_floating_point<RealT>::value != 1)
{
tol *= 20; // real_concept special functions are less accurate
}
return tol;
*/
return 5e+6*boost::math::tools::epsilon<RealT>();
}
}; // make_tolerance_impl
template <>
struct make_tolerance_impl<double>
{
double operator()() const
{
return 2e+3*boost::math::tools::epsilon<double>();
}
}; // make_tolerance_impl
template <>
struct make_tolerance_impl<float>
{
float operator()() const
{
return 1e-4;
}
};
typedef boost::mpl::list<float, double> test_types;
#endif
template <typename RealT>
RealT make_tolerance()
{
const RealT tol = make_tolerance_impl<RealT>()();
// We must use a low precision since it seems the involved computations are very challenging from the numerical point of view.
// Indeed, both Octave 3.6.4, MATLAB 2012a and Mathematica 10 provides different results.
// E.g.:
// x = [0 1 2 3 4]
// p = [0.2 0.3 0.5]
// r = [0.5 1.0 1.5]
// PDF(x)
// - MATLAB: 1.033333333333333, 0.335636985323608, 0.135792553231720, 0.061039382459897, 0.028790027125382
// - Octave: 1.0333333333333332, 0.3356369853236084, 0.1357925532317197, 0.0610393824598966, 0.0287900271253818
// - Mathematica: 1.15, 0.3383645184340184, 0.11472883036402601, 0.04558088392888389, 0.02088728412278129
//
// (Tested under Fedora Linux 20 x86_64 running on Intel(R) Core(TM) i7-3540M)
//
/*
RealT tol = std::max(boost::math::tools::epsilon<RealT>(),
static_cast<RealT>(boost::math::tools::epsilon<double>()*5)*150);
// At float precision we need to up the tolerance, since
// the input values are rounded off to inexact quantities
// the results get thrown off by a noticeable amount.
if (boost::math::tools::digits<RealT>() < 50)
{
tol *= 50;
}
if (boost::is_floating_point<RealT>::value != 1)
{
tol *= 20; // real_concept special functions are less accurate
}
*/
// Current test data is limited to double precision:
const RealT tol = (std::max)(static_cast<RealT>(boost::math::tools::epsilon<double>()), boost::math::tools::epsilon<RealT>()) * 100 * 100;
//std::cout << "[" << __func__ << "] Tolerance: " << tol << "%" << std::endl;
return tol;
}
template <typename RealT>
void test_range()
BOOST_AUTO_TEST_CASE_TEMPLATE(range, RealT, test_types)
{
const RealT tol = make_tolerance<RealT>();
const RealT probs[] = {0.2, 0.3, 0.5};
const RealT rates[] = {0.5, 1.0, 1.5};
const std::size_t n = sizeof(probs)/sizeof(RealT);
const RealT probs[] = { static_cast<RealT>(0.2L), static_cast<RealT>(0.3L), static_cast<RealT>(0.5L) };
const RealT rates[] = { static_cast<RealT>(0.5L), static_cast<RealT>(1.0L), static_cast<RealT>(1.5L) };
const std::size_t n = sizeof(probs) / sizeof(RealT);
boost::math::hyperexponential_distribution<RealT> dist(probs, probs+n, rates, rates+n);
std::pair<RealT,RealT> res;
res = boost::math::range(dist);
BOOST_CHECK_CLOSE( res.first, 0, tol );
BOOST_CHECK_EQUAL( res.second, std::numeric_limits<RealT>::infinity() );
BOOST_CHECK_CLOSE( res.first, static_cast<RealT>(0), tol );
if(std::numeric_limits<RealT>::has_infinity)
{
BOOST_CHECK_EQUAL(res.second, std::numeric_limits<RealT>::infinity());
}
else
{
BOOST_CHECK_EQUAL(res.second, boost::math::tools::max_value<RealT>());
}
}
template <typename RealT>
void test_support()
BOOST_AUTO_TEST_CASE_TEMPLATE(support, RealT, test_types)
{
const RealT tol = make_tolerance<RealT>();
const RealT probs[] = {0.2, 0.3, 0.5};
const RealT rates[] = {0.5, 1.0, 1.5};
const RealT probs[] = { static_cast<RealT>(0.2L), static_cast<RealT>(0.3L), static_cast<RealT>(0.5L) };
const RealT rates[] = { static_cast<RealT>(0.5L), static_cast<RealT>(1), static_cast<RealT>(1.5L) };
const std::size_t n = sizeof(probs)/sizeof(RealT);
boost::math::hyperexponential_distribution<RealT> dist(probs, probs+n, rates, rates+n);
@@ -141,287 +109,165 @@ void test_support()
BOOST_CHECK_CLOSE( res.second, boost::math::tools::max_value<RealT>(), tol );
}
template <typename RealT>
void test_pdf()
BOOST_AUTO_TEST_CASE_TEMPLATE(pdf, RealT, test_types)
{
const RealT tol = make_tolerance<RealT>();
const RealT probs[] = {0.2, 0.3, 0.5};
const RealT rates[] = {0.5, 1.0, 1.5};
const RealT probs[] = { static_cast<RealT>(0.2L), static_cast<RealT>(0.3L), static_cast<RealT>(0.5L) };
const RealT rates[] = { static_cast<RealT>(0.5L), static_cast<RealT>(1), static_cast<RealT>(1.5) };
const std::size_t n = sizeof(probs)/sizeof(RealT);
boost::math::hyperexponential_distribution<RealT> dist(probs, probs+n, rates, rates+n);
// Mathematica: Table[SetPrecision[PDF[HyperexponentialDistribution[{0.2, 0.3, 0.5}, {.5, 1.0, 1.5}], x], 35], {x, 0, 4}]
// BOOST_CHECK_CLOSE( boost::math::pdf(dist, static_cast<RealT>(0)), static_cast<RealT>(1.15), tol );
// BOOST_CHECK_CLOSE( boost::math::pdf(dist, static_cast<RealT>(1)), static_cast<RealT>(0.3383645184340184), tol );
// BOOST_CHECK_CLOSE( boost::math::pdf(dist, static_cast<RealT>(2)), static_cast<RealT>(0.11472883036402601), tol );
// BOOST_CHECK_CLOSE( boost::math::pdf(dist, static_cast<RealT>(3)), static_cast<RealT>(0.04558088392888389), tol );
// BOOST_CHECK_CLOSE( boost::math::pdf(dist, static_cast<RealT>(4)), static_cast<RealT>(0.02088728412278129), tol );
BOOST_CHECK_CLOSE( boost::math::pdf(dist, static_cast<RealT>(0)), static_cast<RealT>(1.149999999999999911182158029987476766109466552734375L), tol );
BOOST_CHECK_CLOSE( boost::math::pdf(dist, static_cast<RealT>(1)), static_cast<RealT>(0.33836451843401837979996571448282338678836822509765625L), tol );
BOOST_CHECK_CLOSE( boost::math::pdf(dist, static_cast<RealT>(2)), static_cast<RealT>(0.1147288303640260076488033291752799414098262786865234375), tol );
BOOST_CHECK_CLOSE( boost::math::pdf(dist, static_cast<RealT>(3)), static_cast<RealT>(0.04558088392888388906687424650954199023544788360595703125L), tol );
BOOST_CHECK_CLOSE( boost::math::pdf(dist, static_cast<RealT>(4)), static_cast<RealT>(0.02088728412278129109580504518817178905010223388671875L), tol );
// Mathematica: Table[PDF[HyperexponentialDistribution[{0.2, 0.3, 0.5}, {.5, 1.0, 1.5}], x], {x, 0, 4}]
BOOST_CHECK_CLOSE( boost::math::pdf(dist, static_cast<RealT>(0)), static_cast<RealT>(1.15), tol );
BOOST_CHECK_CLOSE( boost::math::pdf(dist, static_cast<RealT>(1)), static_cast<RealT>(0.3383645184340184), tol );
BOOST_CHECK_CLOSE( boost::math::pdf(dist, static_cast<RealT>(2)), static_cast<RealT>(0.11472883036402601), tol );
BOOST_CHECK_CLOSE( boost::math::pdf(dist, static_cast<RealT>(3)), static_cast<RealT>(0.04558088392888389), tol );
BOOST_CHECK_CLOSE( boost::math::pdf(dist, static_cast<RealT>(4)), static_cast<RealT>(0.02088728412278129), tol );
}
template <typename RealT>
void test_cdf()
BOOST_AUTO_TEST_CASE_TEMPLATE(cdf, RealT, test_types)
{
const RealT tol = make_tolerance<RealT>();
const RealT probs[] = {0.2, 0.3, 0.5};
const RealT rates[] = {0.5, 1.0, 1.5};
const RealT probs[] = { static_cast<RealT>(0.2L), static_cast<RealT>(0.3L), static_cast<RealT>(0.5L) };
const RealT rates[] = { static_cast<RealT>(0.5L), static_cast<RealT>(1.0L), static_cast<RealT>(1.5L) };
const std::size_t n = sizeof(probs)/sizeof(RealT);
boost::math::hyperexponential_distribution<RealT> dist(probs, probs+n, rates, rates+n);
// Mathematica: Table[SetPrecision[CDF[HyperexponentialDistribution[{0.2, 0.3, 0.5}, {.5, 1.0, 1.5}], x], 35], {x, 0, 4}]
// Mathematica: Table[CDF[HyperexponentialDistribution[{0.2, 0.3, 0.5}, {.5, 1.0, 1.5}], x], {x, 0, 4}]
BOOST_CHECK_CLOSE( boost::math::cdf(dist, static_cast<RealT>(0)), static_cast<RealT>(0), tol );
// BOOST_CHECK_CLOSE( boost::math::cdf(dist, static_cast<RealT>(1)), static_cast<RealT>(0.6567649556318257), tol );
// BOOST_CHECK_CLOSE( boost::math::cdf(dist, static_cast<RealT>(2)), static_cast<RealT>(0.8609299926107957), tol );
// BOOST_CHECK_CLOSE( boost::math::cdf(dist, static_cast<RealT>(3)), static_cast<RealT>(0.9348833491908337), tol );
// BOOST_CHECK_CLOSE( boost::math::cdf(dist, static_cast<RealT>(4)), static_cast<RealT>(0.966198875597724), tol );
BOOST_CHECK_CLOSE( boost::math::cdf(dist, static_cast<RealT>(1)), static_cast<RealT>(0.65676495563182568648841197500587441027164459228515625L), tol );
BOOST_CHECK_CLOSE( boost::math::cdf(dist, static_cast<RealT>(2)), static_cast<RealT>(0.86092999261079572459465225620078854262828826904296875L), tol );
BOOST_CHECK_CLOSE( boost::math::cdf(dist, static_cast<RealT>(3)), static_cast<RealT>(0.93488334919083371232773060910403728485107421875L), tol );
BOOST_CHECK_CLOSE( boost::math::cdf(dist, static_cast<RealT>(4)), static_cast<RealT>(0.966198875597723993990939561626873910427093505859375L), tol );
BOOST_CHECK_CLOSE( boost::math::cdf(dist, static_cast<RealT>(1)), static_cast<RealT>(0.6567649556318257), tol );
BOOST_CHECK_CLOSE( boost::math::cdf(dist, static_cast<RealT>(2)), static_cast<RealT>(0.8609299926107957), tol );
BOOST_CHECK_CLOSE( boost::math::cdf(dist, static_cast<RealT>(3)), static_cast<RealT>(0.9348833491908337), tol );
BOOST_CHECK_CLOSE( boost::math::cdf(dist, static_cast<RealT>(4)), static_cast<RealT>(0.966198875597724), tol );
}
template <typename RealT>
void test_quantile()
BOOST_AUTO_TEST_CASE_TEMPLATE(quantile, RealT, test_types)
{
const RealT tol = make_tolerance<RealT>();
const RealT probs[] = {0.2, 0.3, 0.5};
const RealT rates[] = {0.5, 1.0, 1.5};
const RealT probs[] = { static_cast<RealT>(0.2L), static_cast<RealT>(0.3L), static_cast<RealT>(0.5L) };
const RealT rates[] = { static_cast<RealT>(0.5L), static_cast<RealT>(1.0L), static_cast<RealT>(1.5L) };
const std::size_t n = sizeof(probs)/sizeof(RealT);
boost::math::hyperexponential_distribution<RealT> dist(probs, probs+n, rates, rates+n);
// Mathematica: Table[SetPrecision[Quantile[HyperexponentialDistribution[{0.2, 0.3, 0.5}, {.5, 1.0, 1.5}], p], 35], {p, {0, 0.65676495563182568648841197500587441027164459228515625`35, 0.86092999261079572459465225620078854262828826904296875`35, 0.93488334919083371232773060910403728485107421875`35, 0.966198875597723993990939561626873910427093505859375`35}}]
// Mathematica: Table[Quantile[HyperexponentialDistribution[{0.2, 0.3, 0.5}, {.5, 1.0, 1.5}], p], {p, {0, 0.6567649556318257, 0.8609299926107957, 0.9348833491908337, 0.966198875597724}}]
BOOST_CHECK_CLOSE( boost::math::quantile(dist, static_cast<RealT>(0)), static_cast<RealT>(0), tol );
// BOOST_CHECK_CLOSE( boost::math::quantile(dist, static_cast<RealT>(0.6567649556318257)), static_cast<RealT>(1.0000000000000036), tol );
// BOOST_CHECK_CLOSE( boost::math::quantile(dist, static_cast<RealT>(0.8609299926107957)), static_cast<RealT>(1.9999999999999947), tol );
// BOOST_CHECK_CLOSE( boost::math::quantile(dist, static_cast<RealT>(0.9348833491908337)), static_cast<RealT>(3), tol );
// BOOST_CHECK_CLOSE( boost::math::quantile(dist, static_cast<RealT>(0.966198875597724)), static_cast<RealT>(3.9999999999999964), tol );
BOOST_CHECK_CLOSE( boost::math::quantile(dist, static_cast<RealT>(0.65676495563182568648841197500587441027164459228515625L)), static_cast<RealT>(1.000000000000003552713678800500929355621337890625), tol );
BOOST_CHECK_CLOSE( boost::math::quantile(dist, static_cast<RealT>(0.86092999261079572459465225620078854262828826904296875L)), static_cast<RealT>(2.000000000000003552713678800500929355621337890625L), tol );
BOOST_CHECK_CLOSE( boost::math::quantile(dist, static_cast<RealT>(0.93488334919083371232773060910403728485107421875L)), static_cast<RealT>(2.99999999999999289457264239899814128875732421875L), tol );
BOOST_CHECK_CLOSE( boost::math::quantile(dist, static_cast<RealT>(0.966198875597723993990939561626873910427093505859375L)), static_cast<RealT>(3.9999999999999946709294817992486059665679931640625L), tol );
BOOST_CHECK_CLOSE( boost::math::quantile(dist, static_cast<RealT>(0.6567649556318257)), static_cast<RealT>(1.0000000000000036), tol );
BOOST_CHECK_CLOSE( boost::math::quantile(dist, static_cast<RealT>(0.8609299926107957)), static_cast<RealT>(1.9999999999999947), tol );
BOOST_CHECK_CLOSE( boost::math::quantile(dist, static_cast<RealT>(0.9348833491908337)), static_cast<RealT>(3), tol );
BOOST_CHECK_CLOSE( boost::math::quantile(dist, static_cast<RealT>(0.966198875597724)), static_cast<RealT>(3.9999999999999964), tol );
}
template <typename RealT>
void test_ccdf()
BOOST_AUTO_TEST_CASE_TEMPLATE(ccdf, RealT, test_types)
{
const RealT tol = make_tolerance<RealT>();
const RealT probs[] = {0.2, 0.3, 0.5};
const RealT rates[] = {0.5, 1.0, 1.5};
const RealT probs[] = { static_cast<RealT>(0.2L), static_cast<RealT>(0.3L), static_cast<RealT>(0.5L) };
const RealT rates[] = { static_cast<RealT>(0.5L), static_cast<RealT>(1.0L), static_cast<RealT>(1.5L) };
const std::size_t n = sizeof(probs)/sizeof(RealT);
boost::math::hyperexponential_distribution<RealT> dist(probs, probs+n, rates, rates+n);
// Mathematica: Table[SetPrecision[SurvivalFunction[HyperexponentialDistribution[{0.2, 0.3, 0.5}, {.5, 1.0, 1.5}], x], 35], {x, 0, 4}]
// Mathematica: Table[SurvivalFunction[HyperexponentialDistribution[{0.2, 0.3, 0.5}, {.5, 1.0, 1.5}], x], {x, 0, 4}]
BOOST_CHECK_CLOSE( boost::math::cdf(boost::math::complement(dist, static_cast<RealT>(0))), static_cast<RealT>(1), tol );
// BOOST_CHECK_CLOSE( boost::math::cdf(boost::math::complement(dist, static_cast<RealT>(1))), static_cast<RealT>(0.3432350443681743), tol );
// BOOST_CHECK_CLOSE( boost::math::cdf(boost::math::complement(dist, static_cast<RealT>(2))), static_cast<RealT>(0.13907000738920425), tol );
// BOOST_CHECK_CLOSE( boost::math::cdf(boost::math::complement(dist, static_cast<RealT>(3))), static_cast<RealT>(0.0651166508091663), tol );
// BOOST_CHECK_CLOSE( boost::math::cdf(boost::math::complement(dist, static_cast<RealT>(4))), static_cast<RealT>(0.03380112440227598), tol );
BOOST_CHECK_CLOSE( boost::math::cdf(boost::math::complement(dist, static_cast<RealT>(1))), static_cast<RealT>(0.34323504436817431351158802499412558972835540771484375L), tol );
BOOST_CHECK_CLOSE( boost::math::cdf(boost::math::complement(dist, static_cast<RealT>(2))), static_cast<RealT>(0.1390700073892042476497721281702979467809200286865234375L), tol );
BOOST_CHECK_CLOSE( boost::math::cdf(boost::math::complement(dist, static_cast<RealT>(3))), static_cast<RealT>(0.06511665080916630155005719871041947044432163238525390625L), tol );
BOOST_CHECK_CLOSE( boost::math::cdf(boost::math::complement(dist, static_cast<RealT>(4))), static_cast<RealT>(0.0338011244022759782534848227442125789821147918701171875L), tol );
BOOST_CHECK_CLOSE( boost::math::cdf(boost::math::complement(dist, static_cast<RealT>(1))), static_cast<RealT>(0.3432350443681743), tol );
BOOST_CHECK_CLOSE( boost::math::cdf(boost::math::complement(dist, static_cast<RealT>(2))), static_cast<RealT>(0.13907000738920425), tol );
BOOST_CHECK_CLOSE( boost::math::cdf(boost::math::complement(dist, static_cast<RealT>(3))), static_cast<RealT>(0.0651166508091663), tol );
BOOST_CHECK_CLOSE( boost::math::cdf(boost::math::complement(dist, static_cast<RealT>(4))), static_cast<RealT>(0.03380112440227598), tol );
}
template <typename RealT>
void test_cquantile()
BOOST_AUTO_TEST_CASE_TEMPLATE(cquantile, RealT, test_types)
{
const RealT tol = make_tolerance<RealT>();
const RealT probs[] = {0.2, 0.3, 0.5};
const RealT rates[] = {0.5, 1.0, 1.5};
const std::size_t n = sizeof(probs)/sizeof(RealT);
const RealT probs[] = { static_cast<RealT>(0.2L), static_cast<RealT>(0.3L), static_cast<RealT>(0.5L) };
const RealT rates[] = { static_cast<RealT>(0.5L), static_cast<RealT>(1.0L), static_cast<RealT>(1.5L) };
const std::size_t n = sizeof(probs) / sizeof(RealT);
boost::math::hyperexponential_distribution<RealT> dist(probs, probs+n, rates, rates+n);
// Mathematica: Table[SetPrecision[InverseSurvivalFunction[HyperexponentialDistribution[{0.2, 0.3, 0.5}, {.5, 1.0, 1.5}], p], 35], {p, {1.`35, 0.34323504436817431351158802499412558972835540771484375`35, 0.1390700073892042476497721281702979467809200286865234375`35, 0.06511665080916630155005719871041947044432163238525390625`35, 0.0338011244022759782534848227442125789821147918701171875`35}}]
// Mathematica: Table[SurvivalFunction[HyperexponentialDistribution[{0.2, 0.3, 0.5}, {.5, 1.0, 1.5}], p], {p, {1., 0.3432350443681743, 0.13907000738920425, 0.0651166508091663, 0.03380112440227598}}]
BOOST_CHECK_CLOSE( boost::math::quantile(boost::math::complement(dist, static_cast<RealT>(1))), static_cast<RealT>(0), tol );
// BOOST_CHECK_CLOSE( boost::math::quantile(boost::math::complement(dist, static_cast<RealT>(0.3432350443681743))), static_cast<RealT>(1.0000000000000036), tol );
// BOOST_CHECK_CLOSE( boost::math::quantile(boost::math::complement(dist, static_cast<RealT>(0.13907000738920425))), static_cast<RealT>(1.9999999999999947), tol );
// BOOST_CHECK_CLOSE( boost::math::quantile(boost::math::complement(dist, static_cast<RealT>(0.0651166508091663))), static_cast<RealT>(3), tol );
// BOOST_CHECK_CLOSE( boost::math::quantile(boost::math::complement(dist, static_cast<RealT>(0.03380112440227598))), static_cast<RealT>(3.9999999999999964), tol );
BOOST_CHECK_CLOSE( boost::math::quantile(boost::math::complement(dist, static_cast<RealT>(0.34323504436817431351158802499412558972835540771484375))), static_cast<RealT>(1.000000000000003552713678800500929355621337890625L), tol );
BOOST_CHECK_CLOSE( boost::math::quantile(boost::math::complement(dist, static_cast<RealT>(0.1390700073892042476497721281702979467809200286865234375))), static_cast<RealT>(1.999999999999996447286321199499070644378662109375L), tol );
BOOST_CHECK_CLOSE( boost::math::quantile(boost::math::complement(dist, static_cast<RealT>(0.06511665080916630155005719871041947044432163238525390625))), static_cast<RealT>(3.000000000000010658141036401502788066864013671875L), tol );
BOOST_CHECK_CLOSE( boost::math::quantile(boost::math::complement(dist, static_cast<RealT>(0.0338011244022759782534848227442125789821147918701171875))), static_cast<RealT>(3.999999999999996447286321199499070644378662109375L), tol );
BOOST_CHECK_CLOSE( boost::math::quantile(boost::math::complement(dist, static_cast<RealT>(0.3432350443681743))), static_cast<RealT>(1.0000000000000036), tol );
BOOST_CHECK_CLOSE( boost::math::quantile(boost::math::complement(dist, static_cast<RealT>(0.13907000738920425))), static_cast<RealT>(1.9999999999999947), tol );
BOOST_CHECK_CLOSE( boost::math::quantile(boost::math::complement(dist, static_cast<RealT>(0.0651166508091663))), static_cast<RealT>(3), tol );
BOOST_CHECK_CLOSE( boost::math::quantile(boost::math::complement(dist, static_cast<RealT>(0.03380112440227598))), static_cast<RealT>(3.9999999999999964), tol );
}
template <typename RealT>
void test_mean()
BOOST_AUTO_TEST_CASE_TEMPLATE(mean, RealT, test_types)
{
const RealT tol = make_tolerance<RealT>();
const RealT probs[] = {0.2, 0.3, 0.5};
const RealT rates[] = {0.5, 1.0, 1.5};
const std::size_t n = sizeof(probs)/sizeof(RealT);
const RealT probs[] = { static_cast<RealT>(0.2L), static_cast<RealT>(0.3L), static_cast<RealT>(0.5L) };
const RealT rates[] = { static_cast<RealT>(0.5L), static_cast<RealT>(1.0L), static_cast<RealT>(1.5L) };
const std::size_t n = sizeof(probs) / sizeof(RealT);
boost::math::hyperexponential_distribution<RealT> dist(probs, probs+n, rates, rates+n);
// Mathematica: SetPrecision[Mean[HyperexponentialDistribution[{0.2, 0.3, 0.5}, {.5, 1.0, 1.5}]], 35]
// BOOST_CHECK_CLOSE( boost::math::mean(dist), static_cast<RealT>(1.0333333333333332), tol );
BOOST_CHECK_CLOSE( boost::math::mean(dist), static_cast<RealT>(1.0333333333333332149095440399833023548126220703125L), tol );
// Mathematica: Mean[HyperexponentialDistribution[{0.2, 0.3, 0.5}, {.5, 1.0, 1.5}]]
BOOST_CHECK_CLOSE( boost::math::mean(dist), static_cast<RealT>(1.0333333333333332), tol );
}
template <typename RealT>
void test_variance()
BOOST_AUTO_TEST_CASE_TEMPLATE(variance, RealT, test_types)
{
const RealT tol = make_tolerance<RealT>();
const RealT probs[] = {0.2, 0.3, 0.5};
const RealT rates[] = {0.5, 1.0, 1.5};
const std::size_t n = sizeof(probs)/sizeof(RealT);
const RealT probs[] = { static_cast<RealT>(0.2L), static_cast<RealT>(0.3L), static_cast<RealT>(0.5L) };
const RealT rates[] = { static_cast<RealT>(0.5L), static_cast<RealT>(1.0L), static_cast<RealT>(1.5L) };
const std::size_t n = sizeof(probs) / sizeof(RealT);
boost::math::hyperexponential_distribution<RealT> dist(probs, probs+n, rates, rates+n);
// Mathematica: SetPrecision[Variance[HyperexponentialDistribution[{0.2, 0.3, 0.5}, {.5, 1.0, 1.5}]], 35]
// BOOST_CHECK_CLOSE( boost::math::variance(dist), static_cast<RealT>(1.5766666666666673), tol );
BOOST_CHECK_CLOSE( boost::math::variance(dist), static_cast<RealT>(1.5766666666666673268792919770930893719196319580078125L), tol );
// Mathematica: Mean[HyperexponentialDistribution[{0.2, 0.3, 0.5}, {.5, 1.0, 1.5}]]
BOOST_CHECK_CLOSE( boost::math::variance(dist), static_cast<RealT>(1.5766666666666673), tol );
}
template <typename RealT>
void test_kurtosis()
BOOST_AUTO_TEST_CASE_TEMPLATE(kurtosis, RealT, test_types)
{
const RealT tol = make_tolerance<RealT>();
const RealT probs[] = {0.2, 0.3, 0.5};
const RealT rates[] = {0.5, 1.0, 1.5};
const std::size_t n = sizeof(probs)/sizeof(RealT);
const RealT probs[] = { static_cast<RealT>(0.2L), static_cast<RealT>(0.3L), static_cast<RealT>(0.5L) };
const RealT rates[] = { static_cast<RealT>(0.5L), static_cast<RealT>(1.0L), static_cast<RealT>(1.5L) };
const std::size_t n = sizeof(probs) / sizeof(RealT);
boost::math::hyperexponential_distribution<RealT> dist(probs, probs+n, rates, rates+n);
// Mathematica: SetPrecision[Kurtosis[HyperexponentialDistribution[{0.2, 0.3, 0.5}, {.5, 1.0, 1.5}]], 35]
// BOOST_CHECK_CLOSE( boost::math::kurtosis(dist), static_cast<RealT>(19.75073861680871), tol );
// BOOST_CHECK_CLOSE( boost::math::kurtosis_excess(dist), static_cast<RealT>(19.75073861680871)-static_cast<RealT>(3), tol );
BOOST_CHECK_CLOSE( boost::math::kurtosis(dist), static_cast<RealT>(19.75073861680871090129585354588925838470458984375L), tol );
BOOST_CHECK_CLOSE( boost::math::kurtosis_excess(dist), static_cast<RealT>(19.75073861680871090129585354588925838470458984375L)-static_cast<RealT>(3), tol );
// Mathematica: Kurtosis[HyperexponentialDistribution[{0.2, 0.3, 0.5}, {.5, 1.0, 1.5}]]
BOOST_CHECK_CLOSE( boost::math::kurtosis(dist), static_cast<RealT>(19.75073861680871), tol );
BOOST_CHECK_CLOSE( boost::math::kurtosis_excess(dist), static_cast<RealT>(19.75073861680871)-static_cast<RealT>(3), tol );
}
template <typename RealT>
void test_skewness()
BOOST_AUTO_TEST_CASE_TEMPLATE(skewness, RealT, test_types)
{
const RealT tol = make_tolerance<RealT>();
const RealT probs[] = {0.2, 0.3, 0.5};
const RealT rates[] = {0.5, 1.0, 1.5};
const std::size_t n = sizeof(probs)/sizeof(RealT);
const RealT probs[] = { static_cast<RealT>(0.2L), static_cast<RealT>(0.3L), static_cast<RealT>(0.5L) };
const RealT rates[] = { static_cast<RealT>(0.5L), static_cast<RealT>(1.0L), static_cast<RealT>(1.5L) };
const std::size_t n = sizeof(probs) / sizeof(RealT);
boost::math::hyperexponential_distribution<RealT> dist(probs, probs+n, rates, rates+n);
// Mathematica: SetPrecision[Skewness[HyperexponentialDistribution[{0.2, 0.3, 0.5}, {.5, 1.0, 1.5}]], 35]
//BOOST_CHECK_CLOSE( boost::math::skewness(dist), static_cast<RealT>(3.181138744996378), tol );
BOOST_CHECK_CLOSE( boost::math::skewness(dist), static_cast<RealT>(3.181138744996378164842099067755043506622314453125L), tol );
// Mathematica: Skewness[HyperexponentialDistribution[{0.2, 0.3, 0.5}, {.5, 1.0, 1.5}]]
BOOST_CHECK_CLOSE( boost::math::skewness(dist), static_cast<RealT>(3.181138744996378), tol );
}
template <typename RealT>
void test_mode()
BOOST_AUTO_TEST_CASE_TEMPLATE(mode, RealT, test_types)
{
const RealT tol = make_tolerance<RealT>();
const RealT probs[] = {0.2, 0.3, 0.5};
const RealT rates[] = {0.5, 1.0, 1.5};
const std::size_t n = sizeof(probs)/sizeof(RealT);
const RealT probs[] = { static_cast<RealT>(0.2L), static_cast<RealT>(0.3L), static_cast<RealT>(0.5L) };
const RealT rates[] = { static_cast<RealT>(0.5L), static_cast<RealT>(1.0L), static_cast<RealT>(1.5L) };
const std::size_t n = sizeof(probs) / sizeof(RealT);
boost::math::hyperexponential_distribution<RealT> dist(probs, probs+n, rates, rates+n);
BOOST_CHECK_CLOSE( boost::math::mode(dist), static_cast<RealT>(0), tol );
}
BOOST_AUTO_TEST_CASE( range )
{
test_range<float>();
test_range<double>();
HYPEREXP_TEST_LONGDOUBLE( test_range<long double> );
//test_range<boost::math::concepts::real_concept>();
}
BOOST_AUTO_TEST_CASE( support )
{
test_support<float>();
test_support<double>();
HYPEREXP_TEST_LONGDOUBLE( test_support<long double> );
}
BOOST_AUTO_TEST_CASE( pdf )
{
test_pdf<float>();
test_pdf<double>();
HYPEREXP_TEST_LONGDOUBLE( test_pdf<long double> );
}
BOOST_AUTO_TEST_CASE( cdf )
{
test_cdf<float>();
test_cdf<double>();
HYPEREXP_TEST_LONGDOUBLE( test_cdf<long double> );
}
BOOST_AUTO_TEST_CASE( quantile )
{
test_quantile<float>();
test_quantile<double>();
HYPEREXP_TEST_LONGDOUBLE( test_quantile<long double> );
}
BOOST_AUTO_TEST_CASE( ccdf )
{
test_ccdf<float>();
test_ccdf<double>();
HYPEREXP_TEST_LONGDOUBLE( test_ccdf<long double> );
}
BOOST_AUTO_TEST_CASE( cquantile )
{
test_cquantile<float>();
test_cquantile<double>();
HYPEREXP_TEST_LONGDOUBLE( test_cquantile<long double> );
}
BOOST_AUTO_TEST_CASE( mean )
{
test_mean<float>();
test_mean<double>();
HYPEREXP_TEST_LONGDOUBLE( test_mean<long double> );
}
BOOST_AUTO_TEST_CASE( variance )
{
test_variance<float>();
test_variance<double>();
HYPEREXP_TEST_LONGDOUBLE( test_variance<long double> );
}
BOOST_AUTO_TEST_CASE( kurtosis )
{
test_kurtosis<float>();
test_kurtosis<double>();
HYPEREXP_TEST_LONGDOUBLE( test_kurtosis<long double> );
}
BOOST_AUTO_TEST_CASE( skewness )
{
test_skewness<float>();
test_skewness<double>();
HYPEREXP_TEST_LONGDOUBLE( test_skewness<long double> );
}
BOOST_AUTO_TEST_CASE( mode )
{
test_mode<float>();
test_mode<double>();
HYPEREXP_TEST_LONGDOUBLE( test_mode<long double> );
}