[libc++] Support int8_t and uint8_t in integer distributions as an extension
In D125283, we ensured that integer distributions would not compile when
used with arbitrary unsupported types. This effectively enforced what
the Standard mentions here: http://eel.is/c++draft/rand#req.genl-1.5.
However, this also had the effect of breaking some users that were
using integer distributions with unsupported types like int8_t. Since we
already support using __int128_t in those distributions, it is reasonable
to also support smaller types like int8_t and its unsigned variant. This
commit implements that, adds tests and documents the extension. Note that
we voluntarily don't add support for instantiating these distributions
with bool and char, since those are not integer types. However, it is
trivial to replace uses of these random distributions on char using int8_t.
It is also interesting to note that in the process of adding tests
for smaller types, I discovered that our distributions sometimes don't
provide as faithful a distribution when instantiated with smaller types,
so I had to relax a couple of tests. In particular, we do a really bad
job at implementing the negative binomial, geometric and poisson distributions
for small types. I think this all boils down to the algorithm we use in
std::poisson_distribution, however I am running out of time to investigate
that and changing the algorithm would be an ABI break (which might be
reasonable).
As part of this patch, I also added a mitigation for a very likely
integer overflow bug we were hitting in our tests in negative_binomial_distribution.
I also filed http://llvm.org/PR56656 to track fixing the problematic
distributions with int8_t and uint8_t.
Supersedes D125283.
Differential Revision: https://reviews.llvm.org/D126823
NOKEYCHECK=True
GitOrigin-RevId: 07e984bc52014a8565033be10f7e80982e974b99
diff --git a/docs/ReleaseNotes.rst b/docs/ReleaseNotes.rst
index e958d72..2708ff2 100644
--- a/docs/ReleaseNotes.rst
+++ b/docs/ReleaseNotes.rst
@@ -163,8 +163,10 @@
``geometric_distribution``, ``negative_binomial_distribution``, ``poisson_distribution``,
and ``uniform_int_distribution`` now conform to the Standard by rejecting
template parameter types other than ``short``, ``int``, ``long``, ``long long``,
- (as an extension) ``__int128_t``, and the unsigned versions thereof.
- In particular, ``uniform_int_distribution<int8_t>`` is no longer supported.
+ and the unsigned versions thereof. As an extension, ``int8_t``, ``__int128_t`` and
+ their unsigned versions are supported too. In particular, instantiating these
+ distributions with non-integer types like ``bool`` and ``char`` will not compile
+ anymore.
Upcoming Deprecations and Removals
----------------------------------
diff --git a/docs/UsingLibcxx.rst b/docs/UsingLibcxx.rst
index 343937b..47cbe2d 100644
--- a/docs/UsingLibcxx.rst
+++ b/docs/UsingLibcxx.rst
@@ -427,3 +427,12 @@
* ``identity::operator()``
* ``to_integer``
* ``to_underlying``
+
+Additional types supported in random distributions
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The `C++ Standard <http://eel.is/c++draft/rand#req.genl-1.5>`_ mentions that instantiating several random number
+distributions with types other than ``short``, ``int``, ``long``, ``long long``, and their unsigned versions is
+undefined. As an extension, libc++ supports instantiating ``binomial_distribution``, ``discrete_distribution``,
+``geometric_distribution``, ``negative_binomial_distribution``, ``poisson_distribution``, and ``uniform_int_distribution``
+with ``int8_t``, ``__int128_t`` and their unsigned versions.
diff --git a/include/__random/binomial_distribution.h b/include/__random/binomial_distribution.h
index d0e8f30..af60fa2 100644
--- a/include/__random/binomial_distribution.h
+++ b/include/__random/binomial_distribution.h
@@ -27,7 +27,7 @@
template<class _IntType = int>
class _LIBCPP_TEMPLATE_VIS binomial_distribution
{
- static_assert(__libcpp_random_is_valid_inttype<_IntType>::value, "IntType must be an integer type larger than char");
+ static_assert(__libcpp_random_is_valid_inttype<_IntType>::value, "IntType must be a supported integer type");
public:
// types
typedef _IntType result_type;
diff --git a/include/__random/discrete_distribution.h b/include/__random/discrete_distribution.h
index d899e72..8dc63c0 100644
--- a/include/__random/discrete_distribution.h
+++ b/include/__random/discrete_distribution.h
@@ -30,7 +30,7 @@
template<class _IntType = int>
class _LIBCPP_TEMPLATE_VIS discrete_distribution
{
- static_assert(__libcpp_random_is_valid_inttype<_IntType>::value, "IntType must be an integer type larger than char");
+ static_assert(__libcpp_random_is_valid_inttype<_IntType>::value, "IntType must be a supported integer type");
public:
// types
typedef _IntType result_type;
diff --git a/include/__random/geometric_distribution.h b/include/__random/geometric_distribution.h
index 8e1be52..751cf78 100644
--- a/include/__random/geometric_distribution.h
+++ b/include/__random/geometric_distribution.h
@@ -27,7 +27,7 @@
template<class _IntType = int>
class _LIBCPP_TEMPLATE_VIS geometric_distribution
{
- static_assert(__libcpp_random_is_valid_inttype<_IntType>::value, "IntType must be an integer type larger than char");
+ static_assert(__libcpp_random_is_valid_inttype<_IntType>::value, "IntType must be a supported integer type");
public:
// types
typedef _IntType result_type;
diff --git a/include/__random/is_valid.h b/include/__random/is_valid.h
index d41bfa4..be3b61b 100644
--- a/include/__random/is_valid.h
+++ b/include/__random/is_valid.h
@@ -10,6 +10,7 @@
#define _LIBCPP___RANDOM_IS_VALID_H
#include <__config>
+#include <cstdint>
#include <type_traits>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -25,18 +26,20 @@
// unsigned int, unsigned long, or unsigned long long.
template<class> struct __libcpp_random_is_valid_inttype : false_type {};
+template<> struct __libcpp_random_is_valid_inttype<int8_t> : true_type {}; // extension
template<> struct __libcpp_random_is_valid_inttype<short> : true_type {};
template<> struct __libcpp_random_is_valid_inttype<int> : true_type {};
template<> struct __libcpp_random_is_valid_inttype<long> : true_type {};
template<> struct __libcpp_random_is_valid_inttype<long long> : true_type {};
+template<> struct __libcpp_random_is_valid_inttype<uint8_t> : true_type {}; // extension
template<> struct __libcpp_random_is_valid_inttype<unsigned short> : true_type {};
template<> struct __libcpp_random_is_valid_inttype<unsigned int> : true_type {};
template<> struct __libcpp_random_is_valid_inttype<unsigned long> : true_type {};
template<> struct __libcpp_random_is_valid_inttype<unsigned long long> : true_type {};
#ifndef _LIBCPP_HAS_NO_INT128
-template<> struct __libcpp_random_is_valid_inttype<__int128_t> : true_type {};
-template<> struct __libcpp_random_is_valid_inttype<__uint128_t> : true_type {};
+template<> struct __libcpp_random_is_valid_inttype<__int128_t> : true_type {}; // extension
+template<> struct __libcpp_random_is_valid_inttype<__uint128_t> : true_type {}; // extension
#endif // _LIBCPP_HAS_NO_INT128
// [rand.req.urng]/3:
diff --git a/include/__random/negative_binomial_distribution.h b/include/__random/negative_binomial_distribution.h
index 72ce88e..90d3f01 100644
--- a/include/__random/negative_binomial_distribution.h
+++ b/include/__random/negative_binomial_distribution.h
@@ -29,7 +29,7 @@
template<class _IntType = int>
class _LIBCPP_TEMPLATE_VIS negative_binomial_distribution
{
- static_assert(__libcpp_random_is_valid_inttype<_IntType>::value, "IntType must be an integer type larger than char");
+ static_assert(__libcpp_random_is_valid_inttype<_IntType>::value, "IntType must be a supported integer type");
public:
// types
typedef _IntType result_type;
@@ -121,7 +121,9 @@
static_assert(__libcpp_random_is_valid_urng<_URNG>::value, "");
result_type __k = __pr.k();
double __p = __pr.p();
- if (__k <= 21 * __p)
+ // When the number of bits in _IntType is small, we are too likely to
+ // overflow __f below to use this technique.
+ if (__k <= 21 * __p && sizeof(_IntType) > 1)
{
bernoulli_distribution __gen(__p);
result_type __f = 0;
@@ -133,6 +135,8 @@
else
++__f;
}
+ _LIBCPP_ASSERT(__f >= 0, "std::negative_binomial_distribution should never produce negative values. "
+ "This is almost certainly a signed integer overflow issue on __f.");
return __f;
}
return poisson_distribution<result_type>(gamma_distribution<double>
diff --git a/include/__random/poisson_distribution.h b/include/__random/poisson_distribution.h
index 7730923..ef55b1b 100644
--- a/include/__random/poisson_distribution.h
+++ b/include/__random/poisson_distribution.h
@@ -31,7 +31,7 @@
template<class _IntType = int>
class _LIBCPP_TEMPLATE_VIS poisson_distribution
{
- static_assert(__libcpp_random_is_valid_inttype<_IntType>::value, "IntType must be an integer type larger than char");
+ static_assert(__libcpp_random_is_valid_inttype<_IntType>::value, "IntType must be a supported integer type");
public:
// types
typedef _IntType result_type;
diff --git a/include/__random/uniform_int_distribution.h b/include/__random/uniform_int_distribution.h
index dd0a7e4..46b627f 100644
--- a/include/__random/uniform_int_distribution.h
+++ b/include/__random/uniform_int_distribution.h
@@ -159,7 +159,7 @@
template<class _IntType = int>
class uniform_int_distribution
{
- static_assert(__libcpp_random_is_valid_inttype<_IntType>::value, "IntType must be an integer type larger than char");
+ static_assert(__libcpp_random_is_valid_inttype<_IntType>::value, "IntType must be a supported integer type");
public:
// types
typedef _IntType result_type;
diff --git a/test/libcxx/numerics/rand/rand.req.urng/valid_int_type.verify.cpp b/test/libcxx/numerics/rand/rand.req.urng/valid_int_type.verify.cpp
index 1c3be49..eada742 100644
--- a/test/libcxx/numerics/rand/rand.req.urng/valid_int_type.verify.cpp
+++ b/test/libcxx/numerics/rand/rand.req.urng/valid_int_type.verify.cpp
@@ -13,37 +13,37 @@
void test()
{
{
- std::binomial_distribution<bool> baddist; //expected-error@*:* {{IntType must be an integer type larger than char}}
+ std::binomial_distribution<bool> baddist; //expected-error@*:* {{IntType must be a supported integer type}}
std::binomial_distribution<int> okdist;
(void)baddist;
(void)okdist;
}
{
- std::discrete_distribution<bool> baddist; //expected-error@*:* {{IntType must be an integer type larger than char}}
+ std::discrete_distribution<bool> baddist; //expected-error@*:* {{IntType must be a supported integer type}}
std::discrete_distribution<int> okdist;
(void)baddist;
(void)okdist;
}
{
- std::geometric_distribution<bool> baddist; //expected-error@*:* {{IntType must be an integer type larger than char}}
+ std::geometric_distribution<bool> baddist; //expected-error@*:* {{IntType must be a supported integer type}}
std::geometric_distribution<int> okdist;
(void)baddist;
(void)okdist;
}
{
- std::negative_binomial_distribution<bool> baddist; //expected-error@*:* {{IntType must be an integer type larger than char}}
+ std::negative_binomial_distribution<bool> baddist; //expected-error@*:* {{IntType must be a supported integer type}}
std::negative_binomial_distribution<int> okdist;
(void)baddist;
(void)okdist;
}
{
- std::poisson_distribution<bool> baddist; //expected-error@*:* {{IntType must be an integer type larger than char}}
+ std::poisson_distribution<bool> baddist; //expected-error@*:* {{IntType must be a supported integer type}}
std::poisson_distribution<int> okdist;
(void)baddist;
(void)okdist;
}
{
- std::uniform_int_distribution<bool> baddist; //expected-error@*:* {{IntType must be an integer type larger than char}}
+ std::uniform_int_distribution<bool> baddist; //expected-error@*:* {{IntType must be a supported integer type}}
std::uniform_int_distribution<int> okdist;
(void)baddist;
(void)okdist;
diff --git a/test/std/numerics/rand/rand.dist/rand.dist.bern/rand.dist.bern.bin/eval.pass.cpp b/test/std/numerics/rand/rand.dist/rand.dist.bern/rand.dist.bern.bin/eval.pass.cpp
index 46a2523..2e8bfae 100644
--- a/test/std/numerics/rand/rand.dist/rand.dist.bern/rand.dist.bern.bin/eval.pass.cpp
+++ b/test/std/numerics/rand/rand.dist/rand.dist.bern/rand.dist.bern.bin/eval.pass.cpp
@@ -20,26 +20,24 @@
#include <vector>
#include <cassert>
+#include "test_macros.h"
+
template <class T>
-inline
-T
-sqr(T x)
-{
+T sqr(T x) {
return x * x;
}
-void
-test1()
-{
- typedef std::binomial_distribution<> D;
+template <class T>
+void test1() {
+ typedef std::binomial_distribution<T> D;
typedef std::mt19937_64 G;
G g;
D d(5, .75);
const int N = 1000000;
- std::vector<D::result_type> u;
+ std::vector<typename D::result_type> u;
for (int i = 0; i < N; ++i)
{
- D::result_type v = d(g);
+ typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u.push_back(v);
}
@@ -71,18 +69,17 @@
assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.04);
}
-void
-test2()
-{
- typedef std::binomial_distribution<> D;
+template <class T>
+void test2() {
+ typedef std::binomial_distribution<T> D;
typedef std::mt19937 G;
G g;
D d(30, .03125);
const int N = 100000;
- std::vector<D::result_type> u;
+ std::vector<typename D::result_type> u;
for (int i = 0; i < N; ++i)
{
- D::result_type v = d(g);
+ typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u.push_back(v);
}
@@ -114,18 +111,17 @@
assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.01);
}
-void
-test3()
-{
- typedef std::binomial_distribution<> D;
+template <class T>
+void test3() {
+ typedef std::binomial_distribution<T> D;
typedef std::mt19937 G;
G g;
D d(40, .25);
const int N = 100000;
- std::vector<D::result_type> u;
+ std::vector<typename D::result_type> u;
for (int i = 0; i < N; ++i)
{
- D::result_type v = d(g);
+ typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u.push_back(v);
}
@@ -157,18 +153,17 @@
assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.3);
}
-void
-test4()
-{
- typedef std::binomial_distribution<> D;
+template <class T>
+void test4() {
+ typedef std::binomial_distribution<T> D;
typedef std::mt19937 G;
G g;
D d(40, 0);
const int N = 100000;
- std::vector<D::result_type> u;
+ std::vector<typename D::result_type> u;
for (int i = 0; i < N; ++i)
{
- D::result_type v = d(g);
+ typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u.push_back(v);
}
@@ -207,18 +202,17 @@
(void)kurtosis; (void)x_kurtosis;
}
-void
-test5()
-{
- typedef std::binomial_distribution<> D;
+template <class T>
+void test5() {
+ typedef std::binomial_distribution<T> D;
typedef std::mt19937 G;
G g;
D d(40, 1);
const int N = 100000;
- std::vector<D::result_type> u;
+ std::vector<typename D::result_type> u;
for (int i = 0; i < N; ++i)
{
- D::result_type v = d(g);
+ typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u.push_back(v);
}
@@ -257,18 +251,17 @@
(void)kurtosis; (void)x_kurtosis;
}
-void
-test6()
-{
- typedef std::binomial_distribution<> D;
+template <class T>
+void test6() {
+ typedef std::binomial_distribution<T> D;
typedef std::mt19937 G;
G g;
- D d(400, 0.5);
+ D d(127, 0.5);
const int N = 100000;
- std::vector<D::result_type> u;
+ std::vector<typename D::result_type> u;
for (int i = 0; i < N; ++i)
{
- D::result_type v = d(g);
+ typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u.push_back(v);
}
@@ -296,22 +289,21 @@
double x_kurtosis = (1-6*d.p()*(1-d.p())) / x_var;
assert(std::abs((mean - x_mean) / x_mean) < 0.01);
assert(std::abs((var - x_var) / x_var) < 0.01);
- assert(std::abs(skew - x_skew) < 0.01);
+ assert(std::abs(skew - x_skew) < 0.02);
assert(std::abs(kurtosis - x_kurtosis) < 0.01);
}
-void
-test7()
-{
- typedef std::binomial_distribution<> D;
+template <class T>
+void test7() {
+ typedef std::binomial_distribution<T> D;
typedef std::mt19937 G;
G g;
D d(1, 0.5);
const int N = 100000;
- std::vector<D::result_type> u;
+ std::vector<typename D::result_type> u;
for (int i = 0; i < N; ++i)
{
- D::result_type v = d(g);
+ typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u.push_back(v);
}
@@ -343,36 +335,35 @@
assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.01);
}
-void
-test8()
-{
+template <class T>
+void test8() {
const int N = 100000;
std::mt19937 gen1;
std::mt19937 gen2;
- std::binomial_distribution<> dist1(5, 0.1);
- std::binomial_distribution<unsigned> dist2(5, 0.1);
+ using UnsignedT = typename std::make_unsigned<T>::type;
+ std::binomial_distribution<T> dist1(5, 0.1);
+ std::binomial_distribution<UnsignedT> dist2(5, 0.1);
- for(int i = 0; i < N; ++i) {
- int r1 = dist1(gen1);
- unsigned r2 = dist2(gen2);
+ for (int i = 0; i < N; ++i) {
+ T r1 = dist1(gen1);
+ UnsignedT r2 = dist2(gen2);
assert(r1 >= 0);
- assert(static_cast<unsigned>(r1) == r2);
+ assert(static_cast<UnsignedT>(r1) == r2);
}
}
-void
-test9()
-{
- typedef std::binomial_distribution<> D;
+template <class T>
+void test9() {
+ typedef std::binomial_distribution<T> D;
typedef std::mt19937 G;
G g;
D d(0, 0.005);
const int N = 100000;
- std::vector<D::result_type> u;
+ std::vector<typename D::result_type> u;
for (int i = 0; i < N; ++i)
{
- D::result_type v = d(g);
+ typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u.push_back(v);
}
@@ -411,18 +402,17 @@
(void)kurtosis; (void)x_kurtosis;
}
-void
-test10()
-{
- typedef std::binomial_distribution<> D;
+template <class T>
+void test10() {
+ typedef std::binomial_distribution<T> D;
typedef std::mt19937 G;
G g;
D d(0, 0);
const int N = 100000;
- std::vector<D::result_type> u;
+ std::vector<typename D::result_type> u;
for (int i = 0; i < N; ++i)
{
- D::result_type v = d(g);
+ typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u.push_back(v);
}
@@ -461,18 +451,17 @@
(void)kurtosis; (void)x_kurtosis;
}
-void
-test11()
-{
- typedef std::binomial_distribution<> D;
+template <class T>
+void test11() {
+ typedef std::binomial_distribution<T> D;
typedef std::mt19937 G;
G g;
D d(0, 1);
const int N = 100000;
- std::vector<D::result_type> u;
+ std::vector<typename D::result_type> u;
for (int i = 0; i < N; ++i)
{
- D::result_type v = d(g);
+ typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u.push_back(v);
}
@@ -511,19 +500,40 @@
(void)kurtosis; (void)x_kurtosis;
}
-int main(int, char**)
-{
- test1();
- test2();
- test3();
- test4();
- test5();
- test6();
- test7();
- test8();
- test9();
- test10();
- test11();
+template <class T>
+void tests() {
+ test1<T>();
+ test2<T>();
+ test3<T>();
+ test4<T>();
+ test5<T>();
+ test6<T>();
+ test7<T>();
+ test8<T>();
+ test9<T>();
+ test10<T>();
+ test11<T>();
+}
+
+int main(int, char**) {
+ tests<short>();
+ tests<int>();
+ tests<long>();
+ tests<long long>();
+
+ tests<unsigned short>();
+ tests<unsigned int>();
+ tests<unsigned long>();
+ tests<unsigned long long>();
+
+#if defined(_LIBCPP_VERSION) // extension
+ tests<int8_t>();
+ tests<uint8_t>();
+#if !defined(TEST_HAS_NO_INT128)
+ tests<__int128_t>();
+ tests<__uint128_t>();
+#endif
+#endif
return 0;
}
diff --git a/test/std/numerics/rand/rand.dist/rand.dist.bern/rand.dist.bern.geo/eval.pass.cpp b/test/std/numerics/rand/rand.dist/rand.dist.bern/rand.dist.bern.geo/eval.pass.cpp
index 11eeb97..deccad1 100644
--- a/test/std/numerics/rand/rand.dist/rand.dist.bern/rand.dist.bern.geo/eval.pass.cpp
+++ b/test/std/numerics/rand/rand.dist/rand.dist.bern/rand.dist.bern.geo/eval.pass.cpp
@@ -23,10 +23,7 @@
#include "test_macros.h"
template <class T>
-inline
-T
-sqr(T x)
-{
+T sqr(T x) {
return x * x;
}
@@ -40,18 +37,17 @@
}
}
-void
-test1()
-{
- typedef std::geometric_distribution<> D;
+template <class T>
+void test1() {
+ typedef std::geometric_distribution<T> D;
typedef std::mt19937 G;
G g;
D d(.03125);
const int N = 1000000;
- std::vector<D::result_type> u;
+ std::vector<typename D::result_type> u;
for (int i = 0; i < N; ++i)
{
- D::result_type v = d(g);
+ typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u.push_back(v);
}
@@ -83,18 +79,17 @@
assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.01);
}
-void
-test2()
-{
- typedef std::geometric_distribution<> D;
+template <class T>
+void test2() {
+ typedef std::geometric_distribution<T> D;
typedef std::mt19937 G;
G g;
D d(0.05);
const int N = 1000000;
- std::vector<D::result_type> u;
+ std::vector<typename D::result_type> u;
for (int i = 0; i < N; ++i)
{
- D::result_type v = d(g);
+ typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u.push_back(v);
}
@@ -126,18 +121,17 @@
assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.03);
}
-void
-test3()
-{
- typedef std::geometric_distribution<> D;
+template <class T>
+void test3() {
+ typedef std::geometric_distribution<T> D;
typedef std::minstd_rand G;
G g;
D d(.25);
const int N = 1000000;
- std::vector<D::result_type> u;
+ std::vector<typename D::result_type> u;
for (int i = 0; i < N; ++i)
{
- D::result_type v = d(g);
+ typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u.push_back(v);
}
@@ -169,18 +163,17 @@
assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.02);
}
-void
-test4()
-{
- typedef std::geometric_distribution<> D;
+template <class T>
+void test4() {
+ typedef std::geometric_distribution<T> D;
typedef std::mt19937 G;
G g;
D d(0.5);
const int N = 1000000;
- std::vector<D::result_type> u;
+ std::vector<typename D::result_type> u;
for (int i = 0; i < N; ++i)
{
- D::result_type v = d(g);
+ typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u.push_back(v);
}
@@ -212,18 +205,17 @@
assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.02);
}
-void
-test5()
-{
- typedef std::geometric_distribution<> D;
+template <class T>
+void test5() {
+ typedef std::geometric_distribution<T> D;
typedef std::mt19937 G;
G g;
D d(0.75);
const int N = 1000000;
- std::vector<D::result_type> u;
+ std::vector<typename D::result_type> u;
for (int i = 0; i < N; ++i)
{
- D::result_type v = d(g);
+ typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u.push_back(v);
}
@@ -255,18 +247,17 @@
assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.02);
}
-void
-test6()
-{
- typedef std::geometric_distribution<> D;
+template <class T>
+void test6() {
+ typedef std::geometric_distribution<T> D;
typedef std::mt19937 G;
G g;
D d(0.96875);
const int N = 1000000;
- std::vector<D::result_type> u;
+ std::vector<typename D::result_type> u;
for (int i = 0; i < N; ++i)
{
- D::result_type v = d(g);
+ typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u.push_back(v);
}
@@ -298,15 +289,38 @@
assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.02);
}
-int main(int, char**)
-{
- test1();
- test2();
- test3();
- test4();
- test5();
- test6();
+template <class T>
+void tests() {
+ test1<T>();
+ test2<T>();
+ test3<T>();
+ test4<T>();
+ test5<T>();
+ test6<T>();
+}
+
+int main(int, char**) {
test_small_inputs();
- return 0;
+ tests<short>();
+ tests<int>();
+ tests<long>();
+ tests<long long>();
+
+ tests<unsigned short>();
+ tests<unsigned int>();
+ tests<unsigned long>();
+ tests<unsigned long long>();
+
+#if defined(_LIBCPP_VERSION) // extension
+ // TODO: std::geometric_distribution currently doesn't work reliably with small types.
+ // tests<int8_t>();
+ // tests<uint8_t>();
+#if !defined(TEST_HAS_NO_INT128)
+ tests<__int128_t>();
+ tests<__uint128_t>();
+#endif
+#endif
+
+ return 0;
}
diff --git a/test/std/numerics/rand/rand.dist/rand.dist.bern/rand.dist.bern.negbin/eval.pass.cpp b/test/std/numerics/rand/rand.dist/rand.dist.bern/rand.dist.bern.negbin/eval.pass.cpp
index 2b2adf2..d98a73d 100644
--- a/test/std/numerics/rand/rand.dist/rand.dist.bern/rand.dist.bern.negbin/eval.pass.cpp
+++ b/test/std/numerics/rand/rand.dist/rand.dist.bern/rand.dist.bern.negbin/eval.pass.cpp
@@ -20,26 +20,24 @@
#include <vector>
#include <cassert>
+#include "test_macros.h"
+
template <class T>
-inline
-T
-sqr(T x)
-{
+T sqr(T x) {
return x * x;
}
-void
-test1()
-{
- typedef std::negative_binomial_distribution<> D;
+template <class T>
+void test1() {
+ typedef std::negative_binomial_distribution<T> D;
typedef std::minstd_rand G;
G g;
D d(5, .25);
const int N = 1000000;
- std::vector<D::result_type> u;
+ std::vector<typename D::result_type> u;
for (int i = 0; i < N; ++i)
{
- D::result_type v = d(g);
+ typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u.push_back(v);
}
@@ -71,18 +69,17 @@
assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.02);
}
-void
-test2()
-{
- typedef std::negative_binomial_distribution<> D;
+template <class T>
+void test2() {
+ typedef std::negative_binomial_distribution<T> D;
typedef std::mt19937 G;
G g;
D d(30, .03125);
const int N = 1000000;
- std::vector<D::result_type> u;
+ std::vector<typename D::result_type> u;
for (int i = 0; i < N; ++i)
{
- D::result_type v = d(g);
+ typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u.push_back(v);
}
@@ -114,18 +111,17 @@
assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.01);
}
-void
-test3()
-{
- typedef std::negative_binomial_distribution<> D;
+template <class T>
+void test3() {
+ typedef std::negative_binomial_distribution<T> D;
typedef std::mt19937 G;
G g;
D d(40, .25);
const int N = 1000000;
- std::vector<D::result_type> u;
+ std::vector<typename D::result_type> u;
for (int i = 0; i < N; ++i)
{
- D::result_type v = d(g);
+ typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u.push_back(v);
}
@@ -157,18 +153,17 @@
assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.03);
}
-void
-test4()
-{
- typedef std::negative_binomial_distribution<> D;
+template <class T>
+void test4() {
+ typedef std::negative_binomial_distribution<T> D;
typedef std::mt19937 G;
G g;
D d(40, 1);
const int N = 1000;
- std::vector<D::result_type> u;
+ std::vector<typename D::result_type> u;
for (int i = 0; i < N; ++i)
{
- D::result_type v = d(g);
+ typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u.push_back(v);
}
@@ -202,18 +197,17 @@
(void)kurtosis; (void)x_kurtosis;
}
-void
-test5()
-{
- typedef std::negative_binomial_distribution<> D;
+template <class T>
+void test5() {
+ typedef std::negative_binomial_distribution<T> D;
typedef std::mt19937 G;
G g;
- D d(400, 0.5);
+ D d(127, 0.5);
const int N = 1000000;
- std::vector<D::result_type> u;
+ std::vector<typename D::result_type> u;
for (int i = 0; i < N; ++i)
{
- D::result_type v = d(g);
+ typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u.push_back(v);
}
@@ -245,18 +239,17 @@
assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.05);
}
-void
-test6()
-{
- typedef std::negative_binomial_distribution<> D;
+template <class T>
+void test6() {
+ typedef std::negative_binomial_distribution<T> D;
typedef std::mt19937 G;
G g;
D d(1, 0.05);
const int N = 1000000;
- std::vector<D::result_type> u;
+ std::vector<typename D::result_type> u;
for (int i = 0; i < N; ++i)
{
- D::result_type v = d(g);
+ typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u.push_back(v);
}
@@ -288,14 +281,36 @@
assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.03);
}
-int main(int, char**)
-{
- test1();
- test2();
- test3();
- test4();
- test5();
- test6();
+template <class T>
+void tests() {
+ test1<T>();
+ test2<T>();
+ test3<T>();
+ test4<T>();
+ test5<T>();
+ test6<T>();
+}
- return 0;
+int main(int, char**) {
+ tests<short>();
+ tests<int>();
+ tests<long>();
+ tests<long long>();
+
+ tests<unsigned short>();
+ tests<unsigned int>();
+ tests<unsigned long>();
+ tests<unsigned long long>();
+
+#if defined(_LIBCPP_VERSION) // extension
+ // TODO: std::negative_binomial_distribution currently doesn't work reliably with small types.
+ // tests<int8_t>();
+ // tests<uint8_t>();
+#if !defined(TEST_HAS_NO_INT128)
+ tests<__int128_t>();
+ tests<__uint128_t>();
+#endif
+#endif
+
+ return 0;
}
diff --git a/test/std/numerics/rand/rand.dist/rand.dist.pois/rand.dist.pois.poisson/eval.pass.cpp b/test/std/numerics/rand/rand.dist/rand.dist.pois/rand.dist.pois.poisson/eval.pass.cpp
index 00a70ac..e217d4d 100644
--- a/test/std/numerics/rand/rand.dist/rand.dist.pois/rand.dist.pois.poisson/eval.pass.cpp
+++ b/test/std/numerics/rand/rand.dist/rand.dist.pois/rand.dist.pois.poisson/eval.pass.cpp
@@ -23,11 +23,8 @@
#include "test_macros.h"
template <class T>
-inline
-T
-sqr(T x)
-{
- return x * x;
+T sqr(T x) {
+ return x * x;
}
void test_bad_ranges() {
@@ -91,126 +88,149 @@
}
}
-int main(int, char**)
-{
+template <class T>
+void tests() {
+ {
+ typedef std::poisson_distribution<T> D;
+ typedef std::minstd_rand G;
+ G g;
+ D d(2);
+ const int N = 100000;
+ std::vector<double> u;
+ for (int i = 0; i < N; ++i)
{
- typedef std::poisson_distribution<> D;
- typedef std::minstd_rand G;
- G g;
- D d(2);
- const int N = 100000;
- std::vector<double> u;
- for (int i = 0; i < N; ++i)
- {
- D::result_type v = d(g);
- assert(d.min() <= v && v <= d.max());
- u.push_back(v);
- }
- double mean = std::accumulate(u.begin(), u.end(), 0.0) / u.size();
- double var = 0;
- double skew = 0;
- double kurtosis = 0;
- for (unsigned i = 0; i < u.size(); ++i)
- {
- double dbl = (u[i] - mean);
- double d2 = sqr(dbl);
- var += d2;
- skew += dbl * d2;
- kurtosis += d2 * d2;
- }
- var /= u.size();
- double dev = std::sqrt(var);
- skew /= u.size() * dev * var;
- kurtosis /= u.size() * var * var;
- kurtosis -= 3;
- double x_mean = d.mean();
- double x_var = d.mean();
- double x_skew = 1 / std::sqrt(x_var);
- double x_kurtosis = 1 / x_var;
- assert(std::abs((mean - x_mean) / x_mean) < 0.01);
- assert(std::abs((var - x_var) / x_var) < 0.01);
- assert(std::abs((skew - x_skew) / x_skew) < 0.01);
- assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.03);
+ typename D::result_type v = d(g);
+ assert(d.min() <= v && v <= d.max());
+ u.push_back(v);
}
+ double mean = std::accumulate(u.begin(), u.end(), 0.0) / u.size();
+ double var = 0;
+ double skew = 0;
+ double kurtosis = 0;
+ for (unsigned i = 0; i < u.size(); ++i)
{
- typedef std::poisson_distribution<> D;
- typedef std::minstd_rand G;
- G g;
- D d(0.75);
- const int N = 100000;
- std::vector<double> u;
- for (int i = 0; i < N; ++i)
- {
- D::result_type v = d(g);
- assert(d.min() <= v && v <= d.max());
- u.push_back(v);
- }
- double mean = std::accumulate(u.begin(), u.end(), 0.0) / u.size();
- double var = 0;
- double skew = 0;
- double kurtosis = 0;
- for (unsigned i = 0; i < u.size(); ++i)
- {
- double dbl = (u[i] - mean);
- double d2 = sqr(dbl);
- var += d2;
- skew += dbl * d2;
- kurtosis += d2 * d2;
- }
- var /= u.size();
- double dev = std::sqrt(var);
- skew /= u.size() * dev * var;
- kurtosis /= u.size() * var * var;
- kurtosis -= 3;
- double x_mean = d.mean();
- double x_var = d.mean();
- double x_skew = 1 / std::sqrt(x_var);
- double x_kurtosis = 1 / x_var;
- assert(std::abs((mean - x_mean) / x_mean) < 0.01);
- assert(std::abs((var - x_var) / x_var) < 0.01);
- assert(std::abs((skew - x_skew) / x_skew) < 0.01);
- assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.04);
+ double dbl = (u[i] - mean);
+ double d2 = sqr(dbl);
+ var += d2;
+ skew += dbl * d2;
+ kurtosis += d2 * d2;
}
+ var /= u.size();
+ double dev = std::sqrt(var);
+ skew /= u.size() * dev * var;
+ kurtosis /= u.size() * var * var;
+ kurtosis -= 3;
+ double x_mean = d.mean();
+ double x_var = d.mean();
+ double x_skew = 1 / std::sqrt(x_var);
+ double x_kurtosis = 1 / x_var;
+ assert(std::abs((mean - x_mean) / x_mean) < 0.01);
+ assert(std::abs((var - x_var) / x_var) < 0.01);
+ assert(std::abs((skew - x_skew) / x_skew) < 0.01);
+ assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.03);
+ }
+ {
+ typedef std::poisson_distribution<T> D;
+ typedef std::minstd_rand G;
+ G g;
+ D d(0.75);
+ const int N = 100000;
+ std::vector<double> u;
+ for (int i = 0; i < N; ++i)
{
- typedef std::poisson_distribution<> D;
- typedef std::mt19937 G;
- G g;
- D d(20);
- const int N = 1000000;
- std::vector<double> u;
- for (int i = 0; i < N; ++i)
- {
- D::result_type v = d(g);
- assert(d.min() <= v && v <= d.max());
- u.push_back(v);
- }
- double mean = std::accumulate(u.begin(), u.end(), 0.0) / u.size();
- double var = 0;
- double skew = 0;
- double kurtosis = 0;
- for (unsigned i = 0; i < u.size(); ++i)
- {
- double dbl = (u[i] - mean);
- double d2 = sqr(dbl);
- var += d2;
- skew += dbl * d2;
- kurtosis += d2 * d2;
- }
- var /= u.size();
- double dev = std::sqrt(var);
- skew /= u.size() * dev * var;
- kurtosis /= u.size() * var * var;
- kurtosis -= 3;
- double x_mean = d.mean();
- double x_var = d.mean();
- double x_skew = 1 / std::sqrt(x_var);
- double x_kurtosis = 1 / x_var;
- assert(std::abs((mean - x_mean) / x_mean) < 0.01);
- assert(std::abs((var - x_var) / x_var) < 0.01);
- assert(std::abs((skew - x_skew) / x_skew) < 0.01);
- assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.01);
+ typename D::result_type v = d(g);
+ assert(d.min() <= v && v <= d.max());
+ u.push_back(v);
}
+ double mean = std::accumulate(u.begin(), u.end(), 0.0) / u.size();
+ double var = 0;
+ double skew = 0;
+ double kurtosis = 0;
+ for (unsigned i = 0; i < u.size(); ++i)
+ {
+ double dbl = (u[i] - mean);
+ double d2 = sqr(dbl);
+ var += d2;
+ skew += dbl * d2;
+ kurtosis += d2 * d2;
+ }
+ var /= u.size();
+ double dev = std::sqrt(var);
+ skew /= u.size() * dev * var;
+ kurtosis /= u.size() * var * var;
+ kurtosis -= 3;
+ double x_mean = d.mean();
+ double x_var = d.mean();
+ double x_skew = 1 / std::sqrt(x_var);
+ double x_kurtosis = 1 / x_var;
+ assert(std::abs((mean - x_mean) / x_mean) < 0.01);
+ assert(std::abs((var - x_var) / x_var) < 0.01);
+ assert(std::abs((skew - x_skew) / x_skew) < 0.01);
+ assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.04);
+ }
+ {
+ typedef std::poisson_distribution<T> D;
+ typedef std::mt19937 G;
+ G g;
+ D d(20);
+ const int N = 1000000;
+ std::vector<double> u;
+ for (int i = 0; i < N; ++i)
+ {
+ typename D::result_type v = d(g);
+ assert(d.min() <= v && v <= d.max());
+ u.push_back(v);
+ }
+ double mean = std::accumulate(u.begin(), u.end(), 0.0) / u.size();
+ double var = 0;
+ double skew = 0;
+ double kurtosis = 0;
+ for (unsigned i = 0; i < u.size(); ++i)
+ {
+ double dbl = (u[i] - mean);
+ double d2 = sqr(dbl);
+ var += d2;
+ skew += dbl * d2;
+ kurtosis += d2 * d2;
+ }
+ var /= u.size();
+ double dev = std::sqrt(var);
+ skew /= u.size() * dev * var;
+ kurtosis /= u.size() * var * var;
+ kurtosis -= 3;
+ double x_mean = d.mean();
+ double x_var = d.mean();
+ double x_skew = 1 / std::sqrt(x_var);
+ double x_kurtosis = 1 / x_var;
+ assert(std::abs((mean - x_mean) / x_mean) < 0.01);
+ assert(std::abs((var - x_var) / x_var) < 0.01);
+ assert(std::abs((skew - x_skew) / x_skew) < 0.01);
+ assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.01);
+ }
+}
- test_bad_ranges();
- return 0;
+int main(int, char**) {
+ test_bad_ranges();
+
+ tests<short>();
+ tests<int>();
+ tests<long>();
+ tests<long long>();
+
+ tests<unsigned short>();
+ tests<unsigned int>();
+ tests<unsigned long>();
+ tests<unsigned long long>();
+
+#if defined(_LIBCPP_VERSION) // extension
+ // TODO: std::poisson_distribution currently doesn't work reliably with small types.
+ // tests<int8_t>();
+ // tests<uint8_t>();
+#if !defined(TEST_HAS_NO_INT128)
+ tests<__int128_t>();
+ tests<__uint128_t>();
+#endif
+#endif
+
+ return 0;
}
diff --git a/test/std/numerics/rand/rand.dist/rand.dist.samp/rand.dist.samp.discrete/eval.pass.cpp b/test/std/numerics/rand/rand.dist/rand.dist.samp/rand.dist.samp.discrete/eval.pass.cpp
index 703b507..d290f51 100644
--- a/test/std/numerics/rand/rand.dist/rand.dist.samp/rand.dist.samp.discrete/eval.pass.cpp
+++ b/test/std/numerics/rand/rand.dist/rand.dist.samp/rand.dist.samp.discrete/eval.pass.cpp
@@ -21,72 +21,73 @@
#include "test_macros.h"
-int main(int, char**)
-{
+template <class T>
+void tests() {
+ typedef long long Frequency;
{
- typedef std::discrete_distribution<> D;
+ typedef std::discrete_distribution<T> D;
typedef std::minstd_rand G;
G g;
D d;
const int N = 100;
- std::vector<D::result_type> u(d.max()+1);
+ std::vector<Frequency> u(d.max()+1);
for (int i = 0; i < N; ++i)
{
- D::result_type v = d(g);
+ typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u[v]++;
}
std::vector<double> prob = d.probabilities();
- for (int i = 0; i <= d.max(); ++i)
+ for (unsigned i = 0; i < u.size(); ++i)
assert((double)u[i]/N == prob[i]);
}
{
- typedef std::discrete_distribution<> D;
+ typedef std::discrete_distribution<T> D;
typedef std::minstd_rand G;
G g;
double p0[] = {.3};
D d(p0, p0+1);
const int N = 100;
- std::vector<D::result_type> u(d.max()+1);
+ std::vector<Frequency> u(d.max()+1);
for (int i = 0; i < N; ++i)
{
- D::result_type v = d(g);
+ typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u[v]++;
}
std::vector<double> prob = d.probabilities();
- for (int i = 0; i <= d.max(); ++i)
+ for (unsigned i = 0; i < u.size(); ++i)
assert((double)u[i]/N == prob[i]);
}
{
- typedef std::discrete_distribution<> D;
+ typedef std::discrete_distribution<T> D;
typedef std::minstd_rand G;
G g;
double p0[] = {.75, .25};
D d(p0, p0+2);
const int N = 1000000;
- std::vector<D::result_type> u(d.max()+1);
+ std::vector<Frequency> u(d.max()+1);
for (int i = 0; i < N; ++i)
{
- D::result_type v = d(g);
+ typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u[v]++;
}
std::vector<double> prob = d.probabilities();
- for (int i = 0; i <= d.max(); ++i)
+ for (unsigned i = 0; i < u.size(); ++i)
assert(std::abs((double)u[i]/N - prob[i]) / prob[i] < 0.001);
}
{
- typedef std::discrete_distribution<> D;
+ typedef std::discrete_distribution<T> D;
typedef std::minstd_rand G;
G g;
double p0[] = {0, 1};
D d(p0, p0+2);
const int N = 1000000;
- std::vector<D::result_type> u(d.max()+1);
+ std::vector<Frequency> u(d.max()+1);
for (int i = 0; i < N; ++i)
{
- D::result_type v = d(g);
+ typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u[v]++;
}
@@ -95,16 +96,16 @@
assert((double)u[1]/N == prob[1]);
}
{
- typedef std::discrete_distribution<> D;
+ typedef std::discrete_distribution<T> D;
typedef std::minstd_rand G;
G g;
double p0[] = {1, 0};
D d(p0, p0+2);
const int N = 1000000;
- std::vector<D::result_type> u(d.max()+1);
+ std::vector<Frequency> u(d.max()+1);
for (int i = 0; i < N; ++i)
{
- D::result_type v = d(g);
+ typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u[v]++;
}
@@ -113,170 +114,191 @@
assert((double)u[1]/N == prob[1]);
}
{
- typedef std::discrete_distribution<> D;
+ typedef std::discrete_distribution<T> D;
typedef std::minstd_rand G;
G g;
double p0[] = {.3, .1, .6};
D d(p0, p0+3);
const int N = 10000000;
- std::vector<D::result_type> u(d.max()+1);
+ std::vector<Frequency> u(d.max()+1);
for (int i = 0; i < N; ++i)
{
- D::result_type v = d(g);
+ typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u[v]++;
}
std::vector<double> prob = d.probabilities();
- for (int i = 0; i <= d.max(); ++i)
+ for (unsigned i = 0; i < u.size(); ++i)
assert(std::abs((double)u[i]/N - prob[i]) / prob[i] < 0.001);
}
{
- typedef std::discrete_distribution<> D;
+ typedef std::discrete_distribution<T> D;
typedef std::minstd_rand G;
G g;
double p0[] = {0, 25, 75};
D d(p0, p0+3);
const int N = 1000000;
- std::vector<D::result_type> u(d.max()+1);
+ std::vector<Frequency> u(d.max()+1);
for (int i = 0; i < N; ++i)
{
- D::result_type v = d(g);
+ typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u[v]++;
}
std::vector<double> prob = d.probabilities();
- for (int i = 0; i <= d.max(); ++i)
+ for (unsigned i = 0; i < u.size(); ++i)
if (prob[i] != 0)
assert(std::abs((double)u[i]/N - prob[i]) / prob[i] < 0.001);
else
assert(u[i] == 0);
}
{
- typedef std::discrete_distribution<> D;
+ typedef std::discrete_distribution<T> D;
typedef std::minstd_rand G;
G g;
double p0[] = {25, 0, 75};
D d(p0, p0+3);
const int N = 1000000;
- std::vector<D::result_type> u(d.max()+1);
+ std::vector<Frequency> u(d.max()+1);
for (int i = 0; i < N; ++i)
{
- D::result_type v = d(g);
+ typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u[v]++;
}
std::vector<double> prob = d.probabilities();
- for (int i = 0; i <= d.max(); ++i)
+ for (unsigned i = 0; i < u.size(); ++i)
if (prob[i] != 0)
assert(std::abs((double)u[i]/N - prob[i]) / prob[i] < 0.001);
else
assert(u[i] == 0);
}
{
- typedef std::discrete_distribution<> D;
+ typedef std::discrete_distribution<T> D;
typedef std::minstd_rand G;
G g;
double p0[] = {25, 75, 0};
D d(p0, p0+3);
const int N = 1000000;
- std::vector<D::result_type> u(d.max()+1);
+ std::vector<Frequency> u(d.max()+1);
for (int i = 0; i < N; ++i)
{
- D::result_type v = d(g);
+ typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u[v]++;
}
std::vector<double> prob = d.probabilities();
- for (int i = 0; i <= d.max(); ++i)
+ for (unsigned i = 0; i < u.size(); ++i)
if (prob[i] != 0)
assert(std::abs((double)u[i]/N - prob[i]) / prob[i] < 0.001);
else
assert(u[i] == 0);
}
{
- typedef std::discrete_distribution<> D;
+ typedef std::discrete_distribution<T> D;
typedef std::minstd_rand G;
G g;
double p0[] = {0, 0, 1};
D d(p0, p0+3);
const int N = 100;
- std::vector<D::result_type> u(d.max()+1);
+ std::vector<Frequency> u(d.max()+1);
for (int i = 0; i < N; ++i)
{
- D::result_type v = d(g);
+ typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u[v]++;
}
std::vector<double> prob = d.probabilities();
- for (int i = 0; i <= d.max(); ++i)
+ for (unsigned i = 0; i < u.size(); ++i)
if (prob[i] != 0)
assert(std::abs((double)u[i]/N - prob[i]) / prob[i] < 0.001);
else
assert(u[i] == 0);
}
{
- typedef std::discrete_distribution<> D;
+ typedef std::discrete_distribution<T> D;
typedef std::minstd_rand G;
G g;
double p0[] = {0, 1, 0};
D d(p0, p0+3);
const int N = 100;
- std::vector<D::result_type> u(d.max()+1);
+ std::vector<Frequency> u(d.max()+1);
for (int i = 0; i < N; ++i)
{
- D::result_type v = d(g);
+ typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u[v]++;
}
std::vector<double> prob = d.probabilities();
- for (int i = 0; i <= d.max(); ++i)
+ for (unsigned i = 0; i < u.size(); ++i)
if (prob[i] != 0)
assert(std::abs((double)u[i]/N - prob[i]) / prob[i] < 0.001);
else
assert(u[i] == 0);
}
{
- typedef std::discrete_distribution<> D;
+ typedef std::discrete_distribution<T> D;
typedef std::minstd_rand G;
G g;
double p0[] = {1, 0, 0};
D d(p0, p0+3);
const int N = 100;
- std::vector<D::result_type> u(d.max()+1);
+ std::vector<Frequency> u(d.max()+1);
for (int i = 0; i < N; ++i)
{
- D::result_type v = d(g);
+ typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u[v]++;
}
std::vector<double> prob = d.probabilities();
- for (int i = 0; i <= d.max(); ++i)
+ for (unsigned i = 0; i < u.size(); ++i)
if (prob[i] != 0)
assert(std::abs((double)u[i]/N - prob[i]) / prob[i] < 0.001);
else
assert(u[i] == 0);
}
{
- typedef std::discrete_distribution<> D;
+ typedef std::discrete_distribution<T> D;
typedef std::minstd_rand G;
G g;
double p0[] = {33, 0, 0, 67};
D d(p0, p0+3);
const int N = 1000000;
- std::vector<D::result_type> u(d.max()+1);
+ std::vector<Frequency> u(d.max()+1);
for (int i = 0; i < N; ++i)
{
- D::result_type v = d(g);
+ typename D::result_type v = d(g);
assert(d.min() <= v && v <= d.max());
u[v]++;
}
std::vector<double> prob = d.probabilities();
- for (int i = 0; i <= d.max(); ++i)
+ for (unsigned i = 0; i < u.size(); ++i)
if (prob[i] != 0)
assert(std::abs((double)u[i]/N - prob[i]) / prob[i] < 0.001);
else
assert(u[i] == 0);
}
+}
- return 0;
+int main(int, char**) {
+ tests<short>();
+ tests<int>();
+ tests<long>();
+ tests<long long>();
+
+ tests<unsigned short>();
+ tests<unsigned int>();
+ tests<unsigned long>();
+ tests<unsigned long long>();
+
+#if defined(_LIBCPP_VERSION) // extension
+ tests<int8_t>();
+ tests<uint8_t>();
+#if !defined(TEST_HAS_NO_INT128)
+ tests<__int128_t>();
+ tests<__uint128_t>();
+#endif
+#endif
+
+ return 0;
}
diff --git a/test/std/numerics/rand/rand.dist/rand.dist.uni/rand.dist.uni.int/eval.pass.cpp b/test/std/numerics/rand/rand.dist/rand.dist.uni/rand.dist.uni.int/eval.pass.cpp
index 823cd16..d636c4c 100644
--- a/test/std/numerics/rand/rand.dist/rand.dist.uni/rand.dist.uni.int/eval.pass.cpp
+++ b/test/std/numerics/rand/rand.dist/rand.dist.uni/rand.dist.uni.int/eval.pass.cpp
@@ -32,14 +32,12 @@
#endif
template <class T>
-T sqr(T x)
-{
+T sqr(T x) {
return x * x;
}
template <class ResultType, class EngineType>
-void test_statistics(ResultType a, ResultType b)
-{
+void test_statistics(ResultType a, ResultType b) {
ASSERT_SAME_TYPE(typename std::uniform_int_distribution<ResultType>::result_type, ResultType);
EngineType g;
@@ -94,8 +92,7 @@
}
template <class ResultType, class EngineType>
-void test_statistics()
-{
+void test_statistics() {
test_statistics<ResultType, EngineType>(0, std::numeric_limits<ResultType>::max());
}
@@ -125,13 +122,9 @@
test_statistics<short, std::minstd_rand0>(SHRT_MIN, SHRT_MAX);
- // http://eel.is/c++draft/rand.req#genl-1.5
- // The effect of instantiating a template that has a parameter
- // named IntType is undefined unless the corresponding template
- // argument is cv-unqualified and is one of short, int, long,
- // long long, unsigned short, unsigned int, unsigned long,
- // or unsigned long long.
- // (We support __int128 as an extension.)
+#if defined(_LIBCPP_VERSION) // extension
+ test_statistics<int8_t, std::minstd_rand0>();
+ test_statistics<uint8_t, std::minstd_rand0>();
#if !defined(TEST_HAS_NO_INT128) && !defined(TEST_BUGGY_I128_FP)
test_statistics<__int128_t, std::minstd_rand0>();
@@ -142,6 +135,7 @@
test_statistics<__int128_t, std::minstd_rand0>(std::numeric_limits<__int128_t>::min(), std::numeric_limits<__int128_t>::max());
test_statistics<__uint128_t, std::minstd_rand0>(0, UINT64_MAX);
#endif
+#endif
return 0;
}