diff --git a/libcxx/docs/ReleaseNotes.rst b/libcxx/docs/ReleaseNotes.rst --- a/libcxx/docs/ReleaseNotes.rst +++ b/libcxx/docs/ReleaseNotes.rst @@ -163,8 +163,10 @@ ``geometric_distribution``, ``negative_binomial_distribution``, ``poisson_distribution``, and ``uniform_int_distribution`` now conform to the Standard by rejecting template parameter types other than ``short``, ``int``, ``long``, ``long long``, - (as an extension) ``__int128_t``, and the unsigned versions thereof. - In particular, ``uniform_int_distribution`` 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 --- a/libcxx/docs/UsingLibcxx.rst +++ b/libcxx/docs/UsingLibcxx.rst @@ -427,3 +427,12 @@ * ``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 --- a/libcxx/include/__random/binomial_distribution.h +++ b/libcxx/include/__random/binomial_distribution.h @@ -27,7 +27,7 @@ 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 --- a/libcxx/include/__random/discrete_distribution.h +++ b/libcxx/include/__random/discrete_distribution.h @@ -30,7 +30,7 @@ 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 --- a/libcxx/include/__random/geometric_distribution.h +++ b/libcxx/include/__random/geometric_distribution.h @@ -27,7 +27,7 @@ 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 --- 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 @@ // 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 --- a/libcxx/include/__random/negative_binomial_distribution.h +++ b/libcxx/include/__random/negative_binomial_distribution.h @@ -29,7 +29,7 @@ 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 @@ static_assert(__libcpp_random_is_valid_urng<_URNG>::value, ""); result_type __k = __pr.k(); double __p = __pr.p(); - if (__k <= 21 * __p) + // When the number of bits in _IntType is small, we are too likely to + // overflow __f below to use this technique. + if (__k <= 21 * __p && sizeof(_IntType) > 1) { bernoulli_distribution __gen(__p); result_type __f = 0; @@ -133,6 +135,8 @@ else ++__f; } + _LIBCPP_ASSERT(__f >= 0, "std::negative_binomial_distribution should never produce negative values. " + "This is almost certainly a signed integer overflow issue on __f."); return __f; } return poisson_distribution(gamma_distribution diff --git a/libcxx/include/__random/poisson_distribution.h b/libcxx/include/__random/poisson_distribution.h --- a/libcxx/include/__random/poisson_distribution.h +++ b/libcxx/include/__random/poisson_distribution.h @@ -31,7 +31,7 @@ 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 --- a/libcxx/include/__random/uniform_int_distribution.h +++ b/libcxx/include/__random/uniform_int_distribution.h @@ -159,7 +159,7 @@ 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 --- 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 --- 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 @@ 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 @@ 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 @@ 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 @@ (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 @@ (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 @@ 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 @@ 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 @@ (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 @@ (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 @@ (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 --- 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 -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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 --- 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 @@ 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 @@ 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 @@ 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 @@ (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 @@ 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 @@ 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 --- 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 @@ } } -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 --- 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 @@ 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 @@ 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 --- 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 @@ } template -void test_statistics() -{ +void test_statistics() { test_statistics(0, std::numeric_limits::max()); } @@ -125,13 +122,9 @@ 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>(); @@ -141,6 +134,7 @@ 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;