From 07e984bc52014a8565033be10f7e80982e974b99 Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Wed, 1 Jun 2022 15:25:14 -0400 Subject: [PATCH] [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 --- libcxx/docs/ReleaseNotes.rst | 6 +- libcxx/docs/UsingLibcxx.rst | 9 + libcxx/include/__random/binomial_distribution.h | 2 +- libcxx/include/__random/discrete_distribution.h | 2 +- libcxx/include/__random/geometric_distribution.h | 2 +- libcxx/include/__random/is_valid.h | 7 +- .../__random/negative_binomial_distribution.h | 8 +- libcxx/include/__random/poisson_distribution.h | 2 +- libcxx/include/__random/uniform_int_distribution.h | 2 +- .../rand/rand.req.urng/valid_int_type.verify.cpp | 12 +- .../rand.dist.bern.bin/eval.pass.cpp | 186 ++++++++------- .../rand.dist.bern.geo/eval.pass.cpp | 112 +++++---- .../rand.dist.bern.negbin/eval.pass.cpp | 115 +++++---- .../rand.dist.pois.poisson/eval.pass.cpp | 260 +++++++++++---------- .../rand.dist.samp.discrete/eval.pass.cpp | 128 +++++----- .../rand.dist.uni/rand.dist.uni.int/eval.pass.cpp | 20 +- 16 files changed, 483 insertions(+), 390 deletions(-) diff --git a/libcxx/docs/ReleaseNotes.rst b/libcxx/docs/ReleaseNotes.rst index e958d72..2708ff2 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`` 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 343937b..47cbe2d 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 `_ 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 d0e8f30..af60fa2 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 _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 d899e72..8dc63c0 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 _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 8e1be52..751cf78 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 _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 d41bfa4..be3b61b 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 #include #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 struct __libcpp_random_is_valid_inttype : false_type {}; +template<> struct __libcpp_random_is_valid_inttype : true_type {}; // extension template<> struct __libcpp_random_is_valid_inttype : true_type {}; template<> struct __libcpp_random_is_valid_inttype : true_type {}; template<> struct __libcpp_random_is_valid_inttype : true_type {}; template<> struct __libcpp_random_is_valid_inttype : true_type {}; +template<> struct __libcpp_random_is_valid_inttype : true_type {}; // extension template<> struct __libcpp_random_is_valid_inttype : true_type {}; template<> struct __libcpp_random_is_valid_inttype : true_type {}; template<> struct __libcpp_random_is_valid_inttype : true_type {}; template<> struct __libcpp_random_is_valid_inttype : 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 72ce88e..90d3f01 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 _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(gamma_distribution diff --git a/libcxx/include/__random/poisson_distribution.h b/libcxx/include/__random/poisson_distribution.h index 7730923..ef55b1b 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 _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 dd0a7e4..46b627f 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 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 1c3be49..eada742 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 baddist; //expected-error@*:* {{IntType must be an integer type larger than char}} + std::binomial_distribution baddist; //expected-error@*:* {{IntType must be a supported integer type}} std::binomial_distribution okdist; (void)baddist; (void)okdist; } { - std::discrete_distribution baddist; //expected-error@*:* {{IntType must be an integer type larger than char}} + std::discrete_distribution baddist; //expected-error@*:* {{IntType must be a supported integer type}} std::discrete_distribution okdist; (void)baddist; (void)okdist; } { - std::geometric_distribution baddist; //expected-error@*:* {{IntType must be an integer type larger than char}} + std::geometric_distribution baddist; //expected-error@*:* {{IntType must be a supported integer type}} std::geometric_distribution okdist; (void)baddist; (void)okdist; } { - std::negative_binomial_distribution baddist; //expected-error@*:* {{IntType must be an integer type larger than char}} + std::negative_binomial_distribution baddist; //expected-error@*:* {{IntType must be a supported integer type}} std::negative_binomial_distribution okdist; (void)baddist; (void)okdist; } { - std::poisson_distribution baddist; //expected-error@*:* {{IntType must be an integer type larger than char}} + std::poisson_distribution baddist; //expected-error@*:* {{IntType must be a supported integer type}} std::poisson_distribution okdist; (void)baddist; (void)okdist; } { - std::uniform_int_distribution baddist; //expected-error@*:* {{IntType must be an integer type larger than char}} + std::uniform_int_distribution baddist; //expected-error@*:* {{IntType must be a supported integer type}} std::uniform_int_distribution 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 46a2523..2e8bfaeb 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 #include +#include "test_macros.h" + template -inline -T -sqr(T x) -{ +T sqr(T x) { return x * x; } -void -test1() -{ - typedef std::binomial_distribution<> D; +template +void test1() { + typedef std::binomial_distribution D; typedef std::mt19937_64 G; G g; D d(5, .75); const int N = 1000000; - std::vector u; + std::vector 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 +void test2() { + typedef std::binomial_distribution D; typedef std::mt19937 G; G g; D d(30, .03125); const int N = 100000; - std::vector u; + std::vector 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 +void test3() { + typedef std::binomial_distribution D; typedef std::mt19937 G; G g; D d(40, .25); const int N = 100000; - std::vector u; + std::vector 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 +void test4() { + typedef std::binomial_distribution D; typedef std::mt19937 G; G g; D d(40, 0); const int N = 100000; - std::vector u; + std::vector 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 +void test5() { + typedef std::binomial_distribution D; typedef std::mt19937 G; G g; D d(40, 1); const int N = 100000; - std::vector u; + std::vector 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 +void test6() { + typedef std::binomial_distribution D; typedef std::mt19937 G; G g; - D d(400, 0.5); + D d(127, 0.5); const int N = 100000; - std::vector u; + std::vector 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 +void test7() { + typedef std::binomial_distribution D; typedef std::mt19937 G; G g; D d(1, 0.5); const int N = 100000; - std::vector u; + std::vector 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 +void test8() { const int N = 100000; std::mt19937 gen1; std::mt19937 gen2; - std::binomial_distribution<> dist1(5, 0.1); - std::binomial_distribution dist2(5, 0.1); + using UnsignedT = typename std::make_unsigned::type; + std::binomial_distribution dist1(5, 0.1); + std::binomial_distribution 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(r1) == r2); + assert(static_cast(r1) == r2); } } -void -test9() -{ - typedef std::binomial_distribution<> D; +template +void test9() { + typedef std::binomial_distribution D; typedef std::mt19937 G; G g; D d(0, 0.005); const int N = 100000; - std::vector u; + std::vector 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 +void test10() { + typedef std::binomial_distribution D; typedef std::mt19937 G; G g; D d(0, 0); const int N = 100000; - std::vector u; + std::vector 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 +void test11() { + typedef std::binomial_distribution D; typedef std::mt19937 G; G g; D d(0, 1); const int N = 100000; - std::vector u; + std::vector 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 +void tests() { + test1(); + test2(); + test3(); + test4(); + test5(); + test6(); + test7(); + test8(); + test9(); + test10(); + test11(); +} + +int main(int, char**) { + tests(); + tests(); + tests(); + tests(); + + tests(); + tests(); + tests(); + tests(); + +#if defined(_LIBCPP_VERSION) // extension + tests(); + tests(); +#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 11eeb97..deccad1 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 -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 +void test1() { + typedef std::geometric_distribution D; typedef std::mt19937 G; G g; D d(.03125); const int N = 1000000; - std::vector u; + std::vector 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 +void test2() { + typedef std::geometric_distribution D; typedef std::mt19937 G; G g; D d(0.05); const int N = 1000000; - std::vector u; + std::vector 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 +void test3() { + typedef std::geometric_distribution D; typedef std::minstd_rand G; G g; D d(.25); const int N = 1000000; - std::vector u; + std::vector 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 +void test4() { + typedef std::geometric_distribution D; typedef std::mt19937 G; G g; D d(0.5); const int N = 1000000; - std::vector u; + std::vector 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 +void test5() { + typedef std::geometric_distribution D; typedef std::mt19937 G; G g; D d(0.75); const int N = 1000000; - std::vector u; + std::vector 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 +void test6() { + typedef std::geometric_distribution D; typedef std::mt19937 G; G g; D d(0.96875); const int N = 1000000; - std::vector u; + std::vector 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 +void tests() { + test1(); + test2(); + test3(); + test4(); + test5(); + test6(); +} + +int main(int, char**) { test_small_inputs(); - return 0; + tests(); + tests(); + tests(); + tests(); + + tests(); + tests(); + tests(); + tests(); + +#if defined(_LIBCPP_VERSION) // extension + // TODO: std::geometric_distribution currently doesn't work reliably with small types. + // tests(); + // tests(); +#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 2b2adf2..d98a73d 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 #include +#include "test_macros.h" + template -inline -T -sqr(T x) -{ +T sqr(T x) { return x * x; } -void -test1() -{ - typedef std::negative_binomial_distribution<> D; +template +void test1() { + typedef std::negative_binomial_distribution D; typedef std::minstd_rand G; G g; D d(5, .25); const int N = 1000000; - std::vector u; + std::vector 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 +void test2() { + typedef std::negative_binomial_distribution D; typedef std::mt19937 G; G g; D d(30, .03125); const int N = 1000000; - std::vector u; + std::vector 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 +void test3() { + typedef std::negative_binomial_distribution D; typedef std::mt19937 G; G g; D d(40, .25); const int N = 1000000; - std::vector u; + std::vector 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 +void test4() { + typedef std::negative_binomial_distribution D; typedef std::mt19937 G; G g; D d(40, 1); const int N = 1000; - std::vector u; + std::vector 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 +void test5() { + typedef std::negative_binomial_distribution D; typedef std::mt19937 G; G g; - D d(400, 0.5); + D d(127, 0.5); const int N = 1000000; - std::vector u; + std::vector 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 +void test6() { + typedef std::negative_binomial_distribution D; typedef std::mt19937 G; G g; D d(1, 0.05); const int N = 1000000; - std::vector u; + std::vector 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 +void tests() { + test1(); + test2(); + test3(); + test4(); + test5(); + test6(); +} + +int main(int, char**) { + tests(); + tests(); + tests(); + tests(); + + tests(); + tests(); + tests(); + tests(); + +#if defined(_LIBCPP_VERSION) // extension + // TODO: std::negative_binomial_distribution currently doesn't work reliably with small types. + // tests(); + // tests(); +#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 00a70ac..e217d4d 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 -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 +void tests() { + { + typedef std::poisson_distribution D; + typedef std::minstd_rand G; + G g; + D d(2); + const int N = 100000; + std::vector 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 D; + typedef std::minstd_rand G; + G g; + D d(0.75); + const int N = 100000; + std::vector 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 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 D; + typedef std::mt19937 G; + G g; + D d(20); + const int N = 1000000; + std::vector 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 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 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(); + tests(); + tests(); + tests(); + + tests(); + tests(); + tests(); + tests(); + +#if defined(_LIBCPP_VERSION) // extension + // TODO: std::poisson_distribution currently doesn't work reliably with small types. + // tests(); + // tests(); +#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 703b507..d290f51 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 +void tests() { + typedef long long Frequency; { - typedef std::discrete_distribution<> D; + typedef std::discrete_distribution D; typedef std::minstd_rand G; G g; D d; const int N = 100; - std::vector u(d.max()+1); + std::vector 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 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 D; typedef std::minstd_rand G; G g; double p0[] = {.3}; D d(p0, p0+1); const int N = 100; - std::vector u(d.max()+1); + std::vector 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 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 D; typedef std::minstd_rand G; G g; double p0[] = {.75, .25}; D d(p0, p0+2); const int N = 1000000; - std::vector u(d.max()+1); + std::vector 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 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 D; typedef std::minstd_rand G; G g; double p0[] = {0, 1}; D d(p0, p0+2); const int N = 1000000; - std::vector u(d.max()+1); + std::vector 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 D; typedef std::minstd_rand G; G g; double p0[] = {1, 0}; D d(p0, p0+2); const int N = 1000000; - std::vector u(d.max()+1); + std::vector 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 D; typedef std::minstd_rand G; G g; double p0[] = {.3, .1, .6}; D d(p0, p0+3); const int N = 10000000; - std::vector u(d.max()+1); + std::vector 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 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 D; typedef std::minstd_rand G; G g; double p0[] = {0, 25, 75}; D d(p0, p0+3); const int N = 1000000; - std::vector u(d.max()+1); + std::vector 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 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 D; typedef std::minstd_rand G; G g; double p0[] = {25, 0, 75}; D d(p0, p0+3); const int N = 1000000; - std::vector u(d.max()+1); + std::vector 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 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 D; typedef std::minstd_rand G; G g; double p0[] = {25, 75, 0}; D d(p0, p0+3); const int N = 1000000; - std::vector u(d.max()+1); + std::vector 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 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 D; typedef std::minstd_rand G; G g; double p0[] = {0, 0, 1}; D d(p0, p0+3); const int N = 100; - std::vector u(d.max()+1); + std::vector 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 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 D; typedef std::minstd_rand G; G g; double p0[] = {0, 1, 0}; D d(p0, p0+3); const int N = 100; - std::vector u(d.max()+1); + std::vector 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 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 D; typedef std::minstd_rand G; G g; double p0[] = {1, 0, 0}; D d(p0, p0+3); const int N = 100; - std::vector u(d.max()+1); + std::vector 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 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 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 u(d.max()+1); + std::vector 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 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(); + tests(); + tests(); + tests(); + + tests(); + tests(); + tests(); + tests(); + +#if defined(_LIBCPP_VERSION) // extension + tests(); + tests(); +#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 823cd16..d636c4c 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 -T sqr(T x) -{ +T sqr(T x) { return x * x; } template -void test_statistics(ResultType a, ResultType b) -{ +void test_statistics(ResultType a, ResultType b) { ASSERT_SAME_TYPE(typename std::uniform_int_distribution::result_type, ResultType); EngineType g; @@ -94,8 +92,7 @@ void test_statistics(ResultType a, ResultType b) } template -void test_statistics() -{ +void test_statistics() { test_statistics(0, std::numeric_limits::max()); } @@ -125,13 +122,9 @@ int main(int, char**) test_statistics(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(); + test_statistics(); #if !defined(TEST_HAS_NO_INT128) && !defined(TEST_BUGGY_I128_FP) test_statistics<__int128_t, std::minstd_rand0>(); @@ -142,6 +135,7 @@ int main(int, char**) 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; } -- 2.7.4