[libcxx-commits] [libcxx] 07e984b - [libc++] Support int8_t and uint8_t in integer distributions as an extension

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Fri Jul 22 05:33:54 PDT 2022


Author: Louis Dionne
Date: 2022-07-22T08:33:01-04:00
New Revision: 07e984bc52014a8565033be10f7e80982e974b99

URL: https://github.com/llvm/llvm-project/commit/07e984bc52014a8565033be10f7e80982e974b99
DIFF: https://github.com/llvm/llvm-project/commit/07e984bc52014a8565033be10f7e80982e974b99.diff

LOG: [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

Added: 
    

Modified: 
    libcxx/docs/ReleaseNotes.rst
    libcxx/docs/UsingLibcxx.rst
    libcxx/include/__random/binomial_distribution.h
    libcxx/include/__random/discrete_distribution.h
    libcxx/include/__random/geometric_distribution.h
    libcxx/include/__random/is_valid.h
    libcxx/include/__random/negative_binomial_distribution.h
    libcxx/include/__random/poisson_distribution.h
    libcxx/include/__random/uniform_int_distribution.h
    libcxx/test/libcxx/numerics/rand/rand.req.urng/valid_int_type.verify.cpp
    libcxx/test/std/numerics/rand/rand.dist/rand.dist.bern/rand.dist.bern.bin/eval.pass.cpp
    libcxx/test/std/numerics/rand/rand.dist/rand.dist.bern/rand.dist.bern.geo/eval.pass.cpp
    libcxx/test/std/numerics/rand/rand.dist/rand.dist.bern/rand.dist.bern.negbin/eval.pass.cpp
    libcxx/test/std/numerics/rand/rand.dist/rand.dist.pois/rand.dist.pois.poisson/eval.pass.cpp
    libcxx/test/std/numerics/rand/rand.dist/rand.dist.samp/rand.dist.samp.discrete/eval.pass.cpp
    libcxx/test/std/numerics/rand/rand.dist/rand.dist.uni/rand.dist.uni.int/eval.pass.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/docs/ReleaseNotes.rst b/libcxx/docs/ReleaseNotes.rst
index e958d72e39ae9..2708ff271fb73 100644
--- a/libcxx/docs/ReleaseNotes.rst
+++ b/libcxx/docs/ReleaseNotes.rst
@@ -163,8 +163,10 @@ Deprecations and Removals
   ``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/libcxx/docs/UsingLibcxx.rst b/libcxx/docs/UsingLibcxx.rst
index 343937b941495..47cbe2d514eec 100644
--- a/libcxx/docs/UsingLibcxx.rst
+++ b/libcxx/docs/UsingLibcxx.rst
@@ -427,3 +427,12 @@ which no dialect declares as such (See the second form described above).
 * ``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/libcxx/include/__random/binomial_distribution.h b/libcxx/include/__random/binomial_distribution.h
index d0e8f30349392..af60fa2a38e06 100644
--- a/libcxx/include/__random/binomial_distribution.h
+++ b/libcxx/include/__random/binomial_distribution.h
@@ -27,7 +27,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 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/libcxx/include/__random/discrete_distribution.h b/libcxx/include/__random/discrete_distribution.h
index d899e72d87f96..8dc63c0e98b49 100644
--- a/libcxx/include/__random/discrete_distribution.h
+++ b/libcxx/include/__random/discrete_distribution.h
@@ -30,7 +30,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 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/libcxx/include/__random/geometric_distribution.h b/libcxx/include/__random/geometric_distribution.h
index 8e1be522e0e32..751cf7860e66f 100644
--- a/libcxx/include/__random/geometric_distribution.h
+++ b/libcxx/include/__random/geometric_distribution.h
@@ -27,7 +27,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 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/libcxx/include/__random/is_valid.h b/libcxx/include/__random/is_valid.h
index d41bfa45ea70d..be3b61b8dc019 100644
--- a/libcxx/include/__random/is_valid.h
+++ b/libcxx/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 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 // 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/libcxx/include/__random/negative_binomial_distribution.h b/libcxx/include/__random/negative_binomial_distribution.h
index 72ce88ea74ba9..90d3f01789146 100644
--- a/libcxx/include/__random/negative_binomial_distribution.h
+++ b/libcxx/include/__random/negative_binomial_distribution.h
@@ -29,7 +29,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 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 @@ negative_binomial_distribution<_IntType>::operator()(_URNG& __urng, const param_
     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 @@ negative_binomial_distribution<_IntType>::operator()(_URNG& __urng, const param_
             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/libcxx/include/__random/poisson_distribution.h b/libcxx/include/__random/poisson_distribution.h
index 7730923ad6ca1..ef55b1be48444 100644
--- a/libcxx/include/__random/poisson_distribution.h
+++ b/libcxx/include/__random/poisson_distribution.h
@@ -31,7 +31,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 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/libcxx/include/__random/uniform_int_distribution.h b/libcxx/include/__random/uniform_int_distribution.h
index dd0a7e4e49828..46b627f45da93 100644
--- a/libcxx/include/__random/uniform_int_distribution.h
+++ b/libcxx/include/__random/uniform_int_distribution.h
@@ -159,7 +159,7 @@ __independent_bits_engine<_Engine, _UIntType>::__eval(true_type)
 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/libcxx/test/libcxx/numerics/rand/rand.req.urng/valid_int_type.verify.cpp b/libcxx/test/libcxx/numerics/rand/rand.req.urng/valid_int_type.verify.cpp
index 1c3be49f089ec..eada7422bea4e 100644
--- a/libcxx/test/libcxx/numerics/rand/rand.req.urng/valid_int_type.verify.cpp
+++ b/libcxx/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/libcxx/test/std/numerics/rand/rand.dist/rand.dist.bern/rand.dist.bern.bin/eval.pass.cpp b/libcxx/test/std/numerics/rand/rand.dist/rand.dist.bern/rand.dist.bern.bin/eval.pass.cpp
index 46a25238ab6ea..2e8bfaebf3677 100644
--- a/libcxx/test/std/numerics/rand/rand.dist/rand.dist.bern/rand.dist.bern.bin/eval.pass.cpp
+++ b/libcxx/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 @@ test1()
     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 @@ test2()
     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 @@ test3()
     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 @@ test4()
     (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 @@ test5()
     (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 @@ test6()
     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 @@ test7()
     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 @@ test9()
     (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 @@ test10()
     (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 @@ test11()
     (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/libcxx/test/std/numerics/rand/rand.dist/rand.dist.bern/rand.dist.bern.geo/eval.pass.cpp b/libcxx/test/std/numerics/rand/rand.dist/rand.dist.bern/rand.dist.bern.geo/eval.pass.cpp
index 11eeb97ccb1a6..deccad1db6d5b 100644
--- a/libcxx/test/std/numerics/rand/rand.dist/rand.dist.bern/rand.dist.bern.geo/eval.pass.cpp
+++ b/libcxx/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 test_small_inputs() {
   }
 }
 
-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 @@ test1()
     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 @@ test2()
     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 @@ test3()
     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 @@ test4()
     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 @@ test5()
     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 @@ test6()
     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/libcxx/test/std/numerics/rand/rand.dist/rand.dist.bern/rand.dist.bern.negbin/eval.pass.cpp b/libcxx/test/std/numerics/rand/rand.dist/rand.dist.bern/rand.dist.bern.negbin/eval.pass.cpp
index 2b2adf250524a..d98a73d296668 100644
--- a/libcxx/test/std/numerics/rand/rand.dist/rand.dist.bern/rand.dist.bern.negbin/eval.pass.cpp
+++ b/libcxx/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 @@ test1()
     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 @@ test2()
     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 @@ test3()
     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 @@ test4()
     (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 @@ test5()
     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 @@ test6()
     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>();
+}
+
+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;
+    return 0;
 }

diff  --git a/libcxx/test/std/numerics/rand/rand.dist/rand.dist.pois/rand.dist.pois.poisson/eval.pass.cpp b/libcxx/test/std/numerics/rand/rand.dist/rand.dist.pois/rand.dist.pois.poisson/eval.pass.cpp
index 00a70ac61b5a7..e217d4d6e2165 100644
--- a/libcxx/test/std/numerics/rand/rand.dist/rand.dist.pois/rand.dist.pois.poisson/eval.pass.cpp
+++ b/libcxx/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 @@ void test_bad_ranges() {
   }
 }
 
-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)
+    {
+      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.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)
+    {
+      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(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);
+      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)
     {
-        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);
+      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::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);
+      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);
+  }
+}
+
+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
 
-    test_bad_ranges();
-    return 0;
+  return 0;
 }

diff  --git a/libcxx/test/std/numerics/rand/rand.dist/rand.dist.samp/rand.dist.samp.discrete/eval.pass.cpp b/libcxx/test/std/numerics/rand/rand.dist/rand.dist.samp/rand.dist.samp.discrete/eval.pass.cpp
index 703b5077b003a..d290f51d60c84 100644
--- a/libcxx/test/std/numerics/rand/rand.dist/rand.dist.samp/rand.dist.samp.discrete/eval.pass.cpp
+++ b/libcxx/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 @@ int main(int, char**)
         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 @@ int main(int, char**)
         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);
     }
+}
+
+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;
+    return 0;
 }

diff  --git a/libcxx/test/std/numerics/rand/rand.dist/rand.dist.uni/rand.dist.uni.int/eval.pass.cpp b/libcxx/test/std/numerics/rand/rand.dist/rand.dist.uni/rand.dist.uni.int/eval.pass.cpp
index 823cd1665302a..d636c4c955c36 100644
--- a/libcxx/test/std/numerics/rand/rand.dist/rand.dist.uni/rand.dist.uni.int/eval.pass.cpp
+++ b/libcxx/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 @@ void test_statistics(ResultType a, ResultType b)
 }
 
 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 @@ int main(int, char**)
 
     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>();
@@ -141,6 +134,7 @@ int main(int, char**)
     test_statistics<__int128_t, std::minstd_rand0>(0, UINT64_MAX);
     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;


        


More information about the libcxx-commits mailing list