mirror of
https://github.com/boostorg/math.git
synced 2026-01-19 04:22:09 +00:00
Modify Marco's 1 and 2 arg constructors to use SFINAE to differentiate between iterators and ranges.
Add a 1 arg initializer list constructor. Update tests accordingly.
This commit is contained in:
@@ -24,9 +24,11 @@
|
||||
#include <boost/math/special_functions/fpclassify.hpp>
|
||||
#include <boost/math/tools/precision.hpp>
|
||||
#include <boost/math/tools/roots.hpp>
|
||||
#include <boost/type_traits/has_pre_increment.hpp>
|
||||
//#include <boost/math/tools/tuple.hpp>
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/range/size.hpp>
|
||||
#include <cstddef>
|
||||
//#include <iostream>
|
||||
#include <limits>
|
||||
@@ -263,6 +265,7 @@ class hyperexponential_distribution
|
||||
PolicyT());
|
||||
}
|
||||
|
||||
// Four arg constructor: no ambiguity here, the arguments must be two pairs of iterators:
|
||||
public: template <typename ProbIterT, typename RateIterT>
|
||||
hyperexponential_distribution(ProbIterT prob_first, ProbIterT prob_last,
|
||||
RateIterT rate_first, RateIterT rate_last)
|
||||
@@ -276,9 +279,11 @@ class hyperexponential_distribution
|
||||
&err,
|
||||
PolicyT());
|
||||
}
|
||||
|
||||
// Two arg constructor from 2 ranges, we SFINAE this out of existance if either argument type is incrementable
|
||||
// as in that case the type is probably an iterator:
|
||||
public: template <typename ProbRangeT, typename RateRangeT>
|
||||
hyperexponential_distribution(ProbRangeT const& prob_range, RateRangeT const& rate_range)
|
||||
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))
|
||||
{
|
||||
@@ -293,29 +298,13 @@ class hyperexponential_distribution
|
||||
&err,
|
||||
PolicyT());
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
||||
template <typename ArgT>
|
||||
hyperexponential_distribution(const std::initializer_list<ArgT>& l1, const std::initializer_list<ArgT>& l2)
|
||||
: probs_(l1.begin(), l1.end()),
|
||||
rates_(l2.begin(), l2.end())
|
||||
{
|
||||
assert(probs_.size() == rates_.size());
|
||||
|
||||
hyperexp_detail::normalize(probs_);
|
||||
|
||||
RealT err;
|
||||
hyperexp_detail::check_dist("boost::math::hyperexponential_distribution<%1%>::hyperexponential_distribution",
|
||||
probs_,
|
||||
rates_,
|
||||
&err,
|
||||
PolicyT());
|
||||
}
|
||||
#endif
|
||||
|
||||
public: template <typename RateIterT>
|
||||
hyperexponential_distribution(std::size_t n, RateIterT rate_first, RateIterT rate_last)
|
||||
: probs_(n, 1), // will be normalized below
|
||||
// Two arg constructor for a pair of iterators: we SFINAE this out of existance if neither
|
||||
// argument types are incrementable. Note that we allow different argument types here to
|
||||
// allow for construction from an array plus a pointer into that array:
|
||||
public: template <typename RateIterT, typename RateIterT2>
|
||||
hyperexponential_distribution(RateIterT const& rate_first, RateIterT2 const& rate_last,
|
||||
typename boost::enable_if_c<boost::has_pre_increment<RateIterT>::value || boost::has_pre_increment<RateIterT2>::value>::type* = 0)
|
||||
: probs_(std::distance(rate_first, rate_last), 1), // will be normalized below
|
||||
rates_(rate_first, rate_last)
|
||||
{
|
||||
assert(probs_.size() == rates_.size());
|
||||
@@ -330,9 +319,45 @@ class hyperexponential_distribution
|
||||
PolicyT());
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
||||
// Initializer list constructor: allows for construction from array literals:
|
||||
template <typename ArgT>
|
||||
hyperexponential_distribution(const std::initializer_list<ArgT>& l1, const std::initializer_list<ArgT>& l2)
|
||||
: probs_(l1.begin(), l1.end()),
|
||||
rates_(l2.begin(), l2.end())
|
||||
{
|
||||
assert(probs_.size() == rates_.size());
|
||||
|
||||
hyperexp_detail::normalize(probs_);
|
||||
|
||||
RealT err;
|
||||
hyperexp_detail::check_dist("boost::math::hyperexponential_distribution<%1%>::hyperexponential_distribution",
|
||||
probs_,
|
||||
rates_,
|
||||
&err,
|
||||
PolicyT());
|
||||
}
|
||||
template <typename ArgT>
|
||||
hyperexponential_distribution(const std::initializer_list<ArgT>& l1)
|
||||
: probs_(l1.size(), 1),
|
||||
rates_(l1.begin(), l1.end())
|
||||
{
|
||||
assert(probs_.size() == rates_.size());
|
||||
|
||||
hyperexp_detail::normalize(probs_);
|
||||
|
||||
RealT err;
|
||||
hyperexp_detail::check_dist("boost::math::hyperexponential_distribution<%1%>::hyperexponential_distribution",
|
||||
probs_,
|
||||
rates_,
|
||||
&err,
|
||||
PolicyT());
|
||||
}
|
||||
#endif
|
||||
// Single argument constructor: argument must be a range.
|
||||
public: template <typename RateRangeT>
|
||||
hyperexponential_distribution(std::size_t n, RateRangeT const& rate_range)
|
||||
: probs_(n, 1), // will be normalized below
|
||||
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))
|
||||
{
|
||||
assert(probs_.size() == rates_.size());
|
||||
|
||||
@@ -42,7 +42,7 @@ template <typename RealT>
|
||||
RealT make_tolerance()
|
||||
{
|
||||
// Tolerance is 100eps expressed as a persentage (as required by Boost.Build):
|
||||
return boost::math::tools::epsilon<RealT>() * 100 * 100;;
|
||||
return boost::math::tools::epsilon<RealT>() * 100 * 100;
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE_TEMPLATE(klass, RealT, test_types)
|
||||
@@ -62,28 +62,33 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(klass, RealT, test_types)
|
||||
BOOST_CHECK_EQUAL(dist_it.num_phases(), n);
|
||||
BOOST_MATH_HYPEREXP_CHECK_CLOSE_COLLECTIONS(RealT, dist_it.probabilities(), std::vector<RealT>(probs, probs+n), tol);
|
||||
BOOST_MATH_HYPEREXP_CHECK_CLOSE_COLLECTIONS(RealT, dist_it.rates(), std::vector<RealT>(rates, rates+n), tol);
|
||||
|
||||
|
||||
boost::math::hyperexponential_distribution<RealT> dist_r(probs, rates);
|
||||
BOOST_CHECK_EQUAL(dist_r.num_phases(), n);
|
||||
BOOST_MATH_HYPEREXP_CHECK_CLOSE_COLLECTIONS(RealT, dist_r.probabilities(), std::vector<RealT>(probs, probs+n), tol);
|
||||
BOOST_MATH_HYPEREXP_CHECK_CLOSE_COLLECTIONS(RealT, dist_r.rates(), std::vector<RealT>(rates, rates+n), tol);
|
||||
|
||||
|
||||
#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
|
||||
boost::math::hyperexponential_distribution<RealT> dist_il = {{static_cast<RealT>(0.2L), static_cast<RealT>(0.3L), static_cast<RealT>(0.5L)}, {static_cast<RealT>(0.5L), static_cast<RealT>(1.0L), static_cast<RealT>(1.5L)}};
|
||||
BOOST_CHECK_EQUAL(dist_il.num_phases(), n);
|
||||
BOOST_MATH_HYPEREXP_CHECK_CLOSE_COLLECTIONS(RealT, dist_il.probabilities(), std::vector<RealT>(probs, probs+n), tol);
|
||||
BOOST_MATH_HYPEREXP_CHECK_CLOSE_COLLECTIONS(RealT, dist_il.rates(), std::vector<RealT>(rates, rates+n), tol);
|
||||
|
||||
boost::math::hyperexponential_distribution<RealT> dist_n_r = { static_cast<RealT>(0.5L), static_cast<RealT>(1.0L), static_cast<RealT>(1.5L) };
|
||||
BOOST_CHECK_EQUAL(dist_n_r.num_phases(), n);
|
||||
BOOST_MATH_HYPEREXP_CHECK_CLOSE_COLLECTIONS(RealT, dist_n_r.probabilities(), std::vector<RealT>(n, static_cast<RealT>(1.0L / 3.0L)), tol);
|
||||
BOOST_MATH_HYPEREXP_CHECK_CLOSE_COLLECTIONS(RealT, dist_n_r.rates(), std::vector<RealT>(rates, rates + n), tol);
|
||||
#endif // BOOST_NO_CXX11_HDR_INITIALIZER_LIST
|
||||
|
||||
boost::math::hyperexponential_distribution<RealT> dist_n_it(n, rates, rates+n);
|
||||
boost::math::hyperexponential_distribution<RealT> dist_n_it(rates, rates+n);
|
||||
BOOST_CHECK_EQUAL(dist_n_it.num_phases(), n);
|
||||
BOOST_MATH_HYPEREXP_CHECK_CLOSE_COLLECTIONS(RealT, dist_n_it.probabilities(), std::vector<RealT>(n, static_cast<RealT>(1.0L/3.0L)), tol);
|
||||
BOOST_MATH_HYPEREXP_CHECK_CLOSE_COLLECTIONS(RealT, dist_n_it.rates(), std::vector<RealT>(rates, rates+n), tol);
|
||||
|
||||
boost::math::hyperexponential_distribution<RealT> dist_n_r(n, rates);
|
||||
BOOST_CHECK_EQUAL(dist_n_r.num_phases(), n);
|
||||
BOOST_MATH_HYPEREXP_CHECK_CLOSE_COLLECTIONS(RealT, dist_n_r.probabilities(), std::vector<RealT>(n, static_cast<RealT>(1.0L/3.0L)), tol);
|
||||
BOOST_MATH_HYPEREXP_CHECK_CLOSE_COLLECTIONS(RealT, dist_n_r.rates(), std::vector<RealT>(rates, rates+n), tol);
|
||||
boost::math::hyperexponential_distribution<RealT> dist_n_r2(rates);
|
||||
BOOST_CHECK_EQUAL(dist_n_r2.num_phases(), n);
|
||||
BOOST_MATH_HYPEREXP_CHECK_CLOSE_COLLECTIONS(RealT, dist_n_r2.probabilities(), std::vector<RealT>(n, static_cast<RealT>(1.0L/3.0L)), tol);
|
||||
BOOST_MATH_HYPEREXP_CHECK_CLOSE_COLLECTIONS(RealT, dist_n_r2.rates(), std::vector<RealT>(rates, rates+n), tol);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE_TEMPLATE(range, RealT, test_types)
|
||||
|
||||
Reference in New Issue
Block a user