aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3/include/ext
diff options
context:
space:
mode:
authorEdward Smith-Rowland <3dw4rd@verizon.net>2013-11-21 12:27:02 +0000
committerEdward Smith-Rowland <emsr@gcc.gnu.org>2013-11-21 12:27:02 +0000
commitd2ae7b11b5fa0dfe134978d510d2aaa2595f2d2f (patch)
tree87279389735f7bac55d97f4929c8b474962aa641 /libstdc++-v3/include/ext
parentca1babb8e83558039ea2372b7acca5e5e524c06c (diff)
downloadgcc-d2ae7b11b5fa0dfe134978d510d2aaa2595f2d2f.zip
gcc-d2ae7b11b5fa0dfe134978d510d2aaa2595f2d2f.tar.gz
gcc-d2ae7b11b5fa0dfe134978d510d2aaa2595f2d2f.tar.bz2
Implement __gnu_cxx::hypergeometric_distribution.
2013-11-21 Edward Smith-Rowland <3dw4rd@verizon.net> Implement __gnu_cxx::hypergeometric_distribution. * include/ext/random: Add hypergeometric_distribution. * include/ext/random.tcc: Add hypergeometric_distribution. * testsuite/util/testsuite_random.h (hypergeometric_pdf): New pdf for the hypergeometric discreet distribution; (lbincoef): New supporting function for binomial coefficients. * testsuite/ext/random/hypergeometric_distribution/operators/ serialize.cc: New. * testsuite/ext/random/hypergeometric_distribution/operators/ equal.cc: New. * testsuite/ext/random/hypergeometric_distribution/operators/ inequal.cc: New. * testsuite/ext/random/hypergeometric_distribution/operators/ values.cc: New. * testsuite/ext/random/hypergeometric_distribution/cons/parms.cc: New. * testsuite/ext/random/hypergeometric_distribution/cons/default.cc: New. * testsuite/ext/random/hypergeometric_distribution/requirements/ explicit_instantiation/1.cc: New. * testsuite/ext/random/hypergeometric_distribution/requirements/ typedefs.cc: New. From-SVN: r205212
Diffstat (limited to 'libstdc++-v3/include/ext')
-rw-r--r--libstdc++-v3/include/ext/random261
-rw-r--r--libstdc++-v3/include/ext/random.tcc108
2 files changed, 368 insertions, 1 deletions
diff --git a/libstdc++-v3/include/ext/random b/libstdc++-v3/include/ext/random
index 347ebed..c82430e 100644
--- a/libstdc++-v3/include/ext/random
+++ b/libstdc++-v3/include/ext/random
@@ -2845,6 +2845,267 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
const __gnu_cxx::von_mises_distribution<_RealType>& __d2)
{ return !(__d1 == __d2); }
+
+ /**
+ * @brief A discrete hypergeometric random number distribution.
+ *
+ * The hypergeometric distribution is a discrete probability distribution
+ * that describes the probability of @p k successes in @p n draws @a without
+ * replacement from a finite population of size @p N containing exactly @p K
+ * successes.
+ *
+ * The formula for the hypergeometric probability density function is
+ * @f[
+ * p(k|N,K,n) = \frac{\binom{K}{k} \binom{N-K}{n-k}}{\binom{N}{n}}
+ * @f]
+ * where @f$N@f$ is the total population of the distribution,
+ * @f$K@f$ is the total population of the distribution.
+ *
+ * <table border=1 cellpadding=10 cellspacing=0>
+ * <caption align=top>Distribution Statistics</caption>
+ * <tr><td>Mean</td><td>@f$ n\frac{K}{N} @f$</td></tr>
+ * <tr><td>Variance</td><td>@f$ n\frac{K}{N}\frac{N-K}{N}\frac{N-n}{N-1}
+ * @f$</td></tr>
+ * <tr><td>Range</td><td>@f$[max(0, n+K-N), min(K, n)]@f$</td></tr>
+ * </table>
+ */
+ template<typename _UIntType = unsigned int>
+ class hypergeometric_distribution
+ {
+ static_assert(std::is_unsigned<_UIntType>::value, "template argument "
+ "substituting _UIntType not an unsigned integral type");
+
+ public:
+ /** The type of the range of the distribution. */
+ typedef _UIntType result_type;
+
+ /** Parameter type. */
+ struct param_type
+ {
+ typedef hypergeometric_distribution<_UIntType> distribution_type;
+ friend class hypergeometric_distribution<_UIntType>;
+
+ explicit
+ param_type(result_type __N = 10, result_type __K = 5,
+ result_type __n = 1)
+ : _M_N{__N}, _M_K{__K}, _M_n{__n}
+ {
+ _GLIBCXX_DEBUG_ASSERT(_M_N >= _M_K);
+ _GLIBCXX_DEBUG_ASSERT(_M_N >= _M_n);
+ }
+
+ result_type
+ total_size() const
+ { return _M_N; }
+
+ result_type
+ successful_size() const
+ { return _M_K; }
+
+ result_type
+ unsuccessful_size() const
+ { return _M_N - _M_K; }
+
+ result_type
+ total_draws() const
+ { return _M_n; }
+
+ friend bool
+ operator==(const param_type& __p1, const param_type& __p2)
+ { return (__p1._M_N == __p2._M_N)
+ && (__p1._M_K == __p2._M_K)
+ && (__p1._M_n == __p2._M_n); }
+
+ private:
+
+ result_type _M_N;
+ result_type _M_K;
+ result_type _M_n;
+ };
+
+ // constructors and member function
+ explicit
+ hypergeometric_distribution(result_type __N = 10, result_type __K = 5,
+ result_type __n = 1)
+ : _M_param{__N, __K, __n}
+ { }
+
+ explicit
+ hypergeometric_distribution(const param_type& __p)
+ : _M_param{__p}
+ { }
+
+ /**
+ * @brief Resets the distribution state.
+ */
+ void
+ reset()
+ { }
+
+ /**
+ * @brief Returns the distribution parameter @p N,
+ * the total number of items.
+ */
+ result_type
+ total_size() const
+ { return this->_M_param.total_size(); }
+
+ /**
+ * @brief Returns the distribution parameter @p K,
+ * the total number of successful items.
+ */
+ result_type
+ successful_size() const
+ { return this->_M_param.successful_size(); }
+
+ /**
+ * @brief Returns the total number of unsuccessful items @f$ N - K @f$.
+ */
+ result_type
+ unsuccessful_size() const
+ { return this->_M_param.unsuccessful_size(); }
+
+ /**
+ * @brief Returns the distribution parameter @p n,
+ * the total number of draws.
+ */
+ result_type
+ total_draws() const
+ { return this->_M_param.total_draws(); }
+
+ /**
+ * @brief Returns the parameter set of the distribution.
+ */
+ param_type
+ param() const
+ { return this->_M_param; }
+
+ /**
+ * @brief Sets the parameter set of the distribution.
+ * @param __param The new parameter set of the distribution.
+ */
+ void
+ param(const param_type& __param)
+ { this->_M_param = __param; }
+
+ /**
+ * @brief Returns the greatest lower bound value of the distribution.
+ */
+ result_type
+ min() const
+ {
+ using _IntType = typename std::make_signed<result_type>::type;
+ return static_cast<result_type>(std::max(static_cast<_IntType>(0),
+ static_cast<_IntType>(this->total_draws()
+ - this->unsuccessful_size())));
+ }
+
+ /**
+ * @brief Returns the least upper bound value of the distribution.
+ */
+ result_type
+ max() const
+ { return std::min(this->successful_size(), this->total_draws()); }
+
+ /**
+ * @brief Generating functions.
+ */
+ template<typename _UniformRandomNumberGenerator>
+ result_type
+ operator()(_UniformRandomNumberGenerator& __urng)
+ { return this->operator()(__urng, this->_M_param); }
+
+ template<typename _UniformRandomNumberGenerator>
+ result_type
+ operator()(_UniformRandomNumberGenerator& __urng,
+ const param_type& __p);
+
+ template<typename _ForwardIterator,
+ typename _UniformRandomNumberGenerator>
+ void
+ __generate(_ForwardIterator __f, _ForwardIterator __t,
+ _UniformRandomNumberGenerator& __urng)
+ { this->__generate(__f, __t, __urng, this->_M_param); }
+
+ template<typename _ForwardIterator,
+ typename _UniformRandomNumberGenerator>
+ void
+ __generate(_ForwardIterator __f, _ForwardIterator __t,
+ _UniformRandomNumberGenerator& __urng,
+ const param_type& __p)
+ { this->__generate_impl(__f, __t, __urng, __p); }
+
+ template<typename _UniformRandomNumberGenerator>
+ void
+ __generate(result_type* __f, result_type* __t,
+ _UniformRandomNumberGenerator& __urng,
+ const param_type& __p)
+ { this->__generate_impl(__f, __t, __urng, __p); }
+
+ /**
+ * @brief Return true if two hypergeometric distributions have the same
+ * parameters and the sequences that would be generated
+ * are equal.
+ */
+ friend bool
+ operator==(const hypergeometric_distribution& __d1,
+ const hypergeometric_distribution& __d2)
+ { return __d1._M_param == __d2._M_param; }
+
+ /**
+ * @brief Inserts a %hypergeometric_distribution random number
+ * distribution @p __x into the output stream @p __os.
+ *
+ * @param __os An output stream.
+ * @param __x A %hypergeometric_distribution random number
+ * distribution.
+ *
+ * @returns The output stream with the state of @p __x inserted or in
+ * an error state.
+ */
+ template<typename _UIntType1, typename _CharT, typename _Traits>
+ friend std::basic_ostream<_CharT, _Traits>&
+ operator<<(std::basic_ostream<_CharT, _Traits>& __os,
+ const __gnu_cxx::hypergeometric_distribution<_UIntType1>&
+ __x);
+
+ /**
+ * @brief Extracts a %hypergeometric_distribution random number
+ * distribution @p __x from the input stream @p __is.
+ *
+ * @param __is An input stream.
+ * @param __x A %hypergeometric_distribution random number generator
+ * distribution.
+ *
+ * @returns The input stream with @p __x extracted or in an error
+ * state.
+ */
+ template<typename _UIntType1, typename _CharT, typename _Traits>
+ friend std::basic_istream<_CharT, _Traits>&
+ operator>>(std::basic_istream<_CharT, _Traits>& __is,
+ __gnu_cxx::hypergeometric_distribution<_UIntType1>& __x);
+
+ private:
+
+ template<typename _ForwardIterator,
+ typename _UniformRandomNumberGenerator>
+ void
+ __generate_impl(_ForwardIterator __f, _ForwardIterator __t,
+ _UniformRandomNumberGenerator& __urng,
+ const param_type& __p);
+
+ param_type _M_param;
+ };
+
+ /**
+ * @brief Return true if two hypergeometric distributions are different.
+ */
+ template<typename _UIntType>
+ inline bool
+ operator!=(const __gnu_cxx::hypergeometric_distribution<_UIntType>& __d1,
+ const __gnu_cxx::hypergeometric_distribution<_UIntType>& __d2)
+ { return !(__d1 == __d2); }
+
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace __gnu_cxx
diff --git a/libstdc++-v3/include/ext/random.tcc b/libstdc++-v3/include/ext/random.tcc
index 009e0ef..7d68958 100644
--- a/libstdc++-v3/include/ext/random.tcc
+++ b/libstdc++-v3/include/ext/random.tcc
@@ -32,7 +32,6 @@
#pragma GCC system_header
-
namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
@@ -1307,6 +1306,113 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return __is;
}
+
+ template<typename _UIntType>
+ template<typename _UniformRandomNumberGenerator>
+ typename hypergeometric_distribution<_UIntType>::result_type
+ hypergeometric_distribution<_UIntType>::
+ operator()(_UniformRandomNumberGenerator& __urng,
+ const param_type& __param)
+ {
+ std::__detail::_Adaptor<_UniformRandomNumberGenerator, result_type>
+ __aurng(__urng);
+
+ result_type __a = __param.successful_size();
+ result_type __b = __param.total_size();
+ result_type __k = 0;
+
+ if (__param.total_draws() < __param.total_size() / 2)
+ {
+ for (result_type __i = 0; __i < __param.total_draws(); ++__i)
+ {
+ if (__b * __aurng() < __a)
+ {
+ ++__k;
+ if (__k == __param.successful_size())
+ return __k;
+ --__a;
+ }
+ --__b;
+ }
+ return __k;
+ }
+ else
+ {
+ for (result_type __i = 0; __i < __param.unsuccessful_size(); ++__i)
+ {
+ if (__b * __aurng() < __a)
+ {
+ ++__k;
+ if (__k == __param.successful_size())
+ return __param.successful_size() - __k;
+ --__a;
+ }
+ --__b;
+ }
+ return __param.successful_size() - __k;
+ }
+ }
+
+ template<typename _UIntType>
+ template<typename _OutputIterator,
+ typename _UniformRandomNumberGenerator>
+ void
+ hypergeometric_distribution<_UIntType>::
+ __generate_impl(_OutputIterator __f, _OutputIterator __t,
+ _UniformRandomNumberGenerator& __urng,
+ const param_type& __param)
+ {
+ __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator>)
+
+ while (__f != __t)
+ *__f++ = this->operator()(__urng);
+ }
+
+ template<typename _UIntType, typename _CharT, typename _Traits>
+ std::basic_ostream<_CharT, _Traits>&
+ operator<<(std::basic_ostream<_CharT, _Traits>& __os,
+ const __gnu_cxx::hypergeometric_distribution<_UIntType>& __x)
+ {
+ typedef std::basic_ostream<_CharT, _Traits> __ostream_type;
+ typedef typename __ostream_type::ios_base __ios_base;
+
+ const typename __ios_base::fmtflags __flags = __os.flags();
+ const _CharT __fill = __os.fill();
+ const std::streamsize __precision = __os.precision();
+ const _CharT __space = __os.widen(' ');
+ __os.flags(__ios_base::scientific | __ios_base::left);
+ __os.fill(__space);
+ __os.precision(std::numeric_limits<_UIntType>::max_digits10);
+
+ __os << __x.total_size() << __space << __x.successful_size() << __space
+ << __x.total_draws();
+
+ __os.flags(__flags);
+ __os.fill(__fill);
+ __os.precision(__precision);
+ return __os;
+ }
+
+ template<typename _UIntType, typename _CharT, typename _Traits>
+ std::basic_istream<_CharT, _Traits>&
+ operator>>(std::basic_istream<_CharT, _Traits>& __is,
+ __gnu_cxx::hypergeometric_distribution<_UIntType>& __x)
+ {
+ typedef std::basic_istream<_CharT, _Traits> __istream_type;
+ typedef typename __istream_type::ios_base __ios_base;
+
+ const typename __ios_base::fmtflags __flags = __is.flags();
+ __is.flags(__ios_base::dec | __ios_base::skipws);
+
+ _UIntType __total_size, __successful_size, __total_draws;
+ __is >> __total_size >> __successful_size >> __total_draws;
+ __x.param(typename __gnu_cxx::hypergeometric_distribution<_UIntType>::
+ param_type(__total_size, __successful_size, __total_draws));
+
+ __is.flags(__flags);
+ return __is;
+ }
+
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace