diff --git a/libcxx/docs/ReleaseNotes.rst b/libcxx/docs/ReleaseNotes.rst --- a/libcxx/docs/ReleaseNotes.rst +++ b/libcxx/docs/ReleaseNotes.rst @@ -79,13 +79,6 @@ in namespace ``std``, it might be because one of your source files now needs to include one or more of the headers listed above. -- The integer distributions ``binomial_distribution``, ``discrete_distribution``, - ``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. - - The C++14 function ``std::quoted(const char*)`` is no longer supported in C++03 or C++11 modes. 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 @@ -24,10 +24,8 @@ _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"); +template +class _LIBCPP_TEMPLATE_VIS binomial_distribution { 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 @@ -27,10 +27,8 @@ _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"); +template +class _LIBCPP_TEMPLATE_VIS discrete_distribution { 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 @@ -10,7 +10,6 @@ #define _LIBCPP___RANDOM_GEOMETRIC_DISTRIBUTION_H #include <__config> -#include <__random/is_valid.h> #include <__random/negative_binomial_distribution.h> #include #include @@ -24,10 +23,8 @@ _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"); +template +class _LIBCPP_TEMPLATE_VIS geometric_distribution { 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 @@ -18,27 +18,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD -// [rand.req.genl]/1.5: -// The effect of instantiating a template that has a template type 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. - -template struct __libcpp_random_is_valid_inttype : false_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 {}; -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 {}; -#endif // _LIBCPP_HAS_NO_INT128 - // [rand.req.urng]/3: // A class G meets the uniform random bit generator requirements if G models // uniform_random_bit_generator, invoke_result_t is an unsigned integer type, 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 @@ -26,10 +26,8 @@ _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"); +template +class _LIBCPP_TEMPLATE_VIS negative_binomial_distribution { public: // types typedef _IntType result_type; 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 @@ -12,7 +12,6 @@ #include <__config> #include <__random/clamp_to_integral.h> #include <__random/exponential_distribution.h> -#include <__random/is_valid.h> #include <__random/normal_distribution.h> #include <__random/uniform_real_distribution.h> #include @@ -28,10 +27,8 @@ _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"); +template +class _LIBCPP_TEMPLATE_VIS poisson_distribution { 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 @@ -156,10 +156,8 @@ return _Sp; } -template -class uniform_int_distribution -{ - static_assert(__libcpp_random_is_valid_inttype<_IntType>::value, "IntType must be an integer type larger than char"); +template // __int128_t is also supported as an extension here +class uniform_int_distribution { public: // types typedef _IntType result_type; @@ -226,6 +224,14 @@ {return !(__x == __y);} }; +template +struct __unsigned_equivalent : make_unsigned<_Tp> {}; + +template <> +struct __unsigned_equivalent { + using type = unsigned char; +}; + template template typename uniform_int_distribution<_IntType>::result_type @@ -233,8 +239,8 @@ _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK { static_assert(__libcpp_random_is_valid_urng<_URNG>::value, ""); - typedef typename conditional::type>::type _UIntType; + using _UIntType = + _If::type>; const _UIntType _Rp = _UIntType(__p.b()) - _UIntType(__p.a()) + _UIntType(1); if (_Rp == 1) return __p.a(); 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 deleted file mode 100644 --- a/libcxx/test/libcxx/numerics/rand/rand.req.urng/valid_int_type.verify.cpp +++ /dev/null @@ -1,51 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// - -#include - -void test() -{ - { - std::binomial_distribution baddist; //expected-error@*:* {{IntType must be an integer type larger than char}} - 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 okdist; - (void)baddist; - (void)okdist; - } - { - std::geometric_distribution baddist; //expected-error@*:* {{IntType must be an integer type larger than char}} - 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 okdist; - (void)baddist; - (void)okdist; - } - { - std::poisson_distribution baddist; //expected-error@*:* {{IntType must be an integer type larger than char}} - 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 okdist; - (void)baddist; - (void)okdist; - } -} diff --git a/libcxx/test/std/numerics/rand/rand.dis/rand.dist.uni/rand.dist.uni.int/eval.pass.cpp b/libcxx/test/std/numerics/rand/rand.dis/rand.dist.uni/rand.dist.uni.int/eval.pass.cpp --- a/libcxx/test/std/numerics/rand/rand.dis/rand.dist.uni/rand.dist.uni.int/eval.pass.cpp +++ b/libcxx/test/std/numerics/rand/rand.dis/rand.dist.uni/rand.dist.uni.int/eval.pass.cpp @@ -16,9 +16,11 @@ // template result_type operator()(_URNG& g); #include +#include #include #include #include +#include #include #include #include @@ -99,6 +101,25 @@ test_statistics(0, std::numeric_limits::max()); } +// Since the values should be uniformly distributed, and there's only two +// values, we should have roughly half `false` and half `true`. That means we +// can have a simple test for `bool`. +template +void test_bool_statistics() { + EngineType gen; + std::uniform_int_distribution dist(false, true); + assert(dist.a() == false); + assert(dist.b() == true); + // We use 100x more values than non-bool tests to secure >99.9% confidence. + std::vector values(1000000); + for (auto i : values) { + i = dist(gen); + } + + double average = std::accumulate(values.begin(), values.end(), 0.0) / values.size(); + assert(0.49875 < average && average < 0.50125); +} + int main(int, char**) { test_statistics(); @@ -113,16 +134,32 @@ test_statistics(-6, 106); test_statistics(5, 100); + test_statistics(); + + test_statistics(); test_statistics(); test_statistics(); test_statistics(); test_statistics(); + test_statistics(); test_statistics(); test_statistics(); test_statistics(); test_statistics(); + test_bool_statistics(); + test_bool_statistics(); + test_bool_statistics(); + test_bool_statistics(); + test_bool_statistics(); + test_bool_statistics(); + test_bool_statistics(); + test_bool_statistics(); + test_bool_statistics(); + + test_statistics(CHAR_MIN, CHAR_MAX); + test_statistics(SCHAR_MIN, SCHAR_MAX); test_statistics(SHRT_MIN, SHRT_MAX); // http://eel.is/c++draft/rand.req#genl-1.5