https://gcc.gnu.org/g:2dc3e74b9ddbc971fdf602e71943717abcf40334
commit r16-4063-g2dc3e74b9ddbc971fdf602e71943717abcf40334 Author: Jonathan Wakely <jwak...@redhat.com> Date: Mon Sep 8 21:53:33 2025 +0100 libstdc++: Refactor std::philox_engine member functions libstdc++-v3/ChangeLog: * include/bits/random.h: Include <bits/ios_base.h> instead of <iomanip>. Change preprocessor checks to use internal feature test macro. (philox_engine): Reword doxygen comments. Use typename instead of class in template parameter lists. Reformat and adjust whitespace. (philox_engine::_If_seed_seq): Replace alias template with __is_seed_seq variable template. (philox_engine::philox_engine(result_type)): Define inline. (philox_engine::seed(result_type), philox_engine::set_counter) (philox_engine::operator(), philox_engine::discard): Likewise. (operator==): Define as defaulted. (operator<<): Reuse widened char. * include/bits/random.tcc: Reformat and adjust whitespace. (philox_engine::_M_philox): Use std::array copy constructor and std::array::fill instead of looping. * testsuite/26_numerics/random/philox4x32.cc: Gate test on feature test macro. Add static_assert to check typedef. * testsuite/26_numerics/random/philox4x64.cc: Likewise. * testsuite/26_numerics/random/philox_engine/cons/copy.cc: Add VERIFY assertions to check copies are equal. Test different seeds. * testsuite/26_numerics/random/philox_engine/cons/default.cc: Add VERIFY assertions to check construction results. * testsuite/26_numerics/random/philox_engine/cons/seed.cc: Likewise. * testsuite/26_numerics/random/philox_engine/operators/equal.cc: Also test inequality. * testsuite/26_numerics/random/philox_engine/operators/serialize.cc: Remove redundant include and return. * testsuite/26_numerics/random/philox_engine/requirements/constants.cc: Check values of all constants. * testsuite/26_numerics/random/philox_engine/requirements/typedefs.cc: Check typedefs are correct. * testsuite/26_numerics/random/philox_engine/cons/119794.cc: Removed. * testsuite/26_numerics/random/philox_engine/cons/seed_seq.cc: Removed. * testsuite/26_numerics/random/philox_engine/operators/inequal.cc: Removed. * testsuite/26_numerics/random/philox_engine/requirements/constexpr_data.cc: Removed. * testsuite/26_numerics/random/philox_engine/requirements/constexpr_functions.cc: Removed. * testsuite/26_numerics/random/pr60037-neg.cc: Adjust dg-error line number. Diff: --- libstdc++-v3/include/bits/random.h | 264 ++++++++++--------- libstdc++-v3/include/bits/random.tcc | 282 ++++++++------------- .../testsuite/26_numerics/random/philox4x32.cc | 11 +- .../testsuite/26_numerics/random/philox4x64.cc | 11 +- .../random/philox_engine/cons/119794.cc | 39 --- .../26_numerics/random/philox_engine/cons/copy.cc | 18 +- .../random/philox_engine/cons/default.cc | 34 ++- .../26_numerics/random/philox_engine/cons/seed.cc | 45 +++- .../random/philox_engine/cons/seed_seq.cc | 24 -- .../random/philox_engine/operators/equal.cc | 11 +- .../random/philox_engine/operators/inequal.cc | 30 --- .../random/philox_engine/operators/serialize.cc | 7 +- .../random/philox_engine/requirements/constants.cc | 56 ++-- .../philox_engine/requirements/constexpr_data.cc | 50 ---- .../requirements/constexpr_functions.cc | 41 --- .../random/philox_engine/requirements/typedefs.cc | 22 +- .../testsuite/26_numerics/random/pr60037-neg.cc | 2 +- 17 files changed, 387 insertions(+), 560 deletions(-) diff --git a/libstdc++-v3/include/bits/random.h b/libstdc++-v3/include/bits/random.h index e74b7bd75c03..4049a77fbf4c 100644 --- a/libstdc++-v3/include/bits/random.h +++ b/libstdc++-v3/include/bits/random.h @@ -32,8 +32,8 @@ #define _RANDOM_H 1 #include <vector> +#include <bits/ios_base.h> #include <bits/uniform_int_dist.h> -#include <iomanip> namespace std _GLIBCXX_VISIBILITY(default) { @@ -1689,21 +1689,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return !(__lhs == __rhs); } #endif -#if __cpp_lib_philox_engine - +#if __glibcxx_philox_engine // >= C++26 /** - * @brief: A discrete pseudorandom number generator based off of weakened - * cryptographic primitives. + * @brief A discrete pseudorandom number generator with weak cryptographic + * properties + * + * This algorithm was designed to be used for highly parallel random number + * generation, and is capable of immensely long periods. It provides + * "Crush-resistance", denoting an ability to pass the TestU01 Suite's + * "Big Crush" test, demonstrating significant apparent entropy. * - * This algorithm was intended to be used for highly parallel random number - * generation, and is capable of immensely long periods. It provides "Crush- - * resistance", denoting an ability to pass the TestU01 Suite's "Big Crush" - * test, demonstrating significant apparent entropy. It is not intended for - * cryptographic use and should not be used for such, despite being based on - * cryptographic primitives. + * It is not intended for cryptographic use and should not be used for such, + * despite being based on cryptographic primitives. * - * The two four-word definitions are likely the best use for this algorithm, - * and are given below as defaults. + * The typedefs `philox4x32` and `philox4x64` are provided as suitable + * defaults for most use cases, providing high-quality random numbers + * with reasonable performance. * * This algorithm was created by John Salmon, Mark Moraes, Ron Dror, and * David Shaw as a product of D.E. Shaw Research. @@ -1717,9 +1718,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @headerfile random * @since C++26 */ - template<class _UIntType, size_t __w, - size_t __n, size_t __r, - _UIntType... __consts> + template<typename _UIntType, size_t __w, size_t __n, size_t __r, + _UIntType... __consts> class philox_engine { static_assert(__n == 2 || __n == 4, @@ -1729,42 +1729,40 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static_assert(0 < __r, "a number of rounds must be specified"); static_assert((0 < __w && __w <= numeric_limits<_UIntType>::digits), "specified bitlength must match input type"); + template<typename _Sseq> - using _If_seed_seq - = __detail::_If_seed_seq_for<_Sseq, philox_engine, _UIntType>; + static constexpr bool __is_seed_seq = requires { + typename __detail::_If_seed_seq_for<_Sseq, philox_engine, _UIntType>; + }; - private: - // the ordering here is essential to functionality. - /** @brief an internal unpacking function for %philox_engine. */ - template <size_t __ind0, size_t __ind1> - static constexpr - array<_UIntType, __n / 2> - _S_popArray() - { - if constexpr (__n == 4) - return {__consts...[__ind0], __consts...[__ind1]}; - else - return {__consts...[__ind0]}; - } + template <size_t __ind0, size_t __ind1> + static constexpr + array<_UIntType, __n / 2> + _S_popArray() + { + if constexpr (__n == 4) + return {__consts...[__ind0], __consts...[__ind1]}; + else + return {__consts...[__ind0]}; + } public: - /** Type of template param. */ using result_type = _UIntType; // public members static constexpr size_t word_size = __w; static constexpr size_t word_count = __n; static constexpr size_t round_count = __r; - static constexpr array<result_type, __n / 2> multipliers = - philox_engine::_S_popArray<0,2>(); - static constexpr array<result_type, __n / 2> round_consts = - philox_engine::_S_popArray<1,3>(); + static constexpr array<result_type, __n / 2> multipliers + = _S_popArray<0,2>(); + static constexpr array<result_type, __n / 2> round_consts + = _S_popArray<1,3>(); - /** @brief returns the minimum value possible. */ + /// The minimum value that this engine can return static constexpr result_type min() { return 0; } - /** @brief returns the maximum value possible. */ + /// The maximum value that this engine can return static constexpr result_type max() { @@ -1776,16 +1774,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // constructors philox_engine() : philox_engine(default_seed) - {} + { } explicit - philox_engine(result_type __value); + philox_engine(result_type __value) + : _M_x{}, _M_y{}, _M_k{}, _M_i(__n - 1) + { _M_k[0] = __value & max(); } /** @brief seed sequence constructor for %philox_engine * - * @params __q the seed sequence + * @param __q the seed sequence */ - template<typename _Sseq, typename = _If_seed_seq<_Sseq>> + template<typename _Sseq> requires __is_seed_seq<_Sseq> explicit philox_engine(_Sseq& __q) { @@ -1793,56 +1793,64 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } void - seed(result_type value = default_seed); + seed(result_type __value = default_seed) + { + _M_x = {}; + _M_y = {}; + _M_k = {}; + _M_k[0] = __value & max(); + _M_i = __n - 1; + } /** @brief seeds %philox_engine by seed sequence * - * @params __q the seed sequence + * @param __q the seed sequence */ template<typename _Sseq> - _If_seed_seq<_Sseq> - seed(_Sseq& __q); + void + seed(_Sseq& __q) requires __is_seed_seq<_Sseq>; /** @brief sets the internal counter "cleartext" * - * @params __counter std::array of len N + * @param __counter std::array of len N */ void - set_counter(const array<result_type, __n>& __counter); + set_counter(const array<result_type, __n>& __counter) + { + for (size_t __j = 0; __j < __n; ++__j) + _M_x[__j] = __counter[__n - 1 - __j] & max(); + _M_i = __n - 1; + } /** @brief compares two %philox_engine objects * - * @params __x A %philox_engine object - * @params __y A %philox_engine object - * - * @returns true if the objects will produce an identical stream, false - * otherwise + * @returns true if the objects will produce an identical stream, + * false otherwise */ friend bool - operator==(const philox_engine& __x, const philox_engine& __y) - { - return (std::equal(__x._M_x.begin(), __x._M_x.end(), - __y._M_x.begin(), __y._M_x.end()) - && std::equal(__x._M_y.begin(), __x._M_y.end(), - __y._M_y.begin(), __y._M_y.end()) - && std::equal(__x._M_k.begin(), __x._M_k.end(), - __y._M_k.begin(), __y._M_k.end()) - && __x._M_i == __y._M_i); - } + operator==(const philox_engine&, const philox_engine&) = default; /** @brief outputs a single w-bit number and handles state advancement * * @returns return_type */ - _UIntType - operator()(); + result_type + operator()() + { + _M_transition(); + return _M_y[_M_i]; + } /** @brief discards __z numbers * - * @params __z number of iterations to discard + * @param __z number of iterations to discard */ void - discard(unsigned long long __z); + discard(unsigned long long __z) + { + while (__z--) + _M_transition(); + } /** @brief outputs the state of the generator * @@ -1853,22 +1861,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION */ template<typename _CharT, typename _Traits> friend basic_ostream<_CharT, _Traits>& - operator<<(basic_ostream<_CharT, _Traits>& __os, - const philox_engine& __x) - { - const typename ios_base::fmtflags __flags = __os.flags(); - const _CharT __fill = __os.fill(); - __os.flags(ios_base::dec | ios_base::left); - __os.fill(__os.widen(' ')); - for (auto &__subkey : __x._M_k) - __os << __subkey << ' '; - for (auto &__ctr : __x._M_x) - __os << __ctr << ' '; - __os << __x._M_i; - __os.flags(__flags); - __os.fill(__fill); - return __os; - } + operator<<(basic_ostream<_CharT, _Traits>& __os, + const philox_engine& __x) + { + const typename ios_base::fmtflags __flags = __os.flags(); + const _CharT __fill = __os.fill(); + __os.flags(ios_base::dec | ios_base::left); + _CharT __space = __os.widen(' '); + __os.fill(__space); + for (auto& __subkey : __x._M_k) + __os << __subkey << __space; + for (auto& __ctr : __x._M_x) + __os << __ctr << __space; + __os << __x._M_i; + __os.flags(__flags); + __os.fill(__fill); + return __os; + } /** @brief takes input to set the state of the %philox_engine object * @@ -1879,38 +1888,39 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION */ template <typename _CharT, typename _Traits> friend basic_istream<_CharT, _Traits>& - operator>>(basic_istream<_CharT, _Traits>& __is, - philox_engine& __x) + operator>>(basic_istream<_CharT, _Traits>& __is, + philox_engine& __x) + { + const typename ios_base::fmtflags __flags = __is.flags(); + __is.flags(ios_base::dec | ios_base::skipws); + for (auto& __subkey : __x._M_k) + __is >> __subkey; + for (auto& __ctr : __x._M_x) + __is >> __ctr; + array<_UIntType, __n> __tmpCtr = __x._M_x; + unsigned char __setIndex = 0; + for (size_t __j = 0; __j < __x._M_x.size(); ++__j) { - const typename ios_base::fmtflags __flags = __is.flags(); - __is.flags(ios_base::dec | ios_base::skipws); - for (auto &__subkey : __x._M_k) - __is >> __subkey; - for (auto &__ctr : __x._M_x) - __is >> __ctr; - array<_UIntType, __n> __tmpCtr = __x._M_x; - unsigned char __setIndex = 0; - for (size_t __j = 0; __j < __x._M_x.size(); ++__j) - { - if (__x._M_x[__j] > 0) + if (__x._M_x[__j] > 0) { __setIndex = __j; break; } - } - for (size_t __j = 0; __j <= __setIndex; ++__j) - { - if (__j != __setIndex) - __x._M_x[__j] = max(); - else - --__x._M_x[__j]; - } - __x._M_philox(); - __x._M_x = __tmpCtr; - __is >> __x._M_i; - __is.flags(__flags); - return __is; } + for (size_t __j = 0; __j <= __setIndex; ++__j) + { + if (__j != __setIndex) + __x._M_x[__j] = max(); + else + --__x._M_x[__j]; + } + __x._M_philox(); + __x._M_x = __tmpCtr; + __is >> __x._M_i; + __is.flags(__flags); + return __is; + } + private: // private state variables array<_UIntType, __n> _M_x; @@ -1918,39 +1928,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION array<_UIntType, __n> _M_y; unsigned long long _M_i = 0; - /** @brief Takes the high values of the product of __a, __b - * - * @params __a an unsigned integer - * @params __b an unsigned integer - * - * @returns an unsigned integer of at most bitlength W - */ - static - _UIntType + // The high W bits of the product of __a and __b + static _UIntType _S_mulhi(_UIntType __a, _UIntType __b); // (A*B)/2^W - /** @brief Takes the low values of the product of __a, __b - * - * @params __a an unsigned integer - * @params __b an unsigned integer - * - * @returns an unsigned integer of at most bitlength W - */ - static - _UIntType + // The low W bits of the product of __a and __b + static _UIntType _S_mullo(_UIntType __a, _UIntType __b); // (A*B)%2^W - /** @brief an R-round substitution/Feistel Network hybrid for - * %philox_engine - */ + // An R-round substitution/Feistel Network hybrid for philox_engine void _M_philox(); - /** @brief an internal transition function for the %philox_engine. */ + // The transition function void _M_transition(); }; - #endif /** @@ -2007,17 +2000,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef minstd_rand0 default_random_engine; -#if __cpp_lib_philox_engine +#if __glibcxx_philox_engine + /// 32-bit four-word Philox engine. typedef philox_engine< uint_fast32_t, 32, 4, 10, 0xCD9E8D57, 0x9E3779B9, 0xD2511F53, 0xBB67AE85> philox4x32; - /** - * Alternative Philox instance (64 bit) - */ + /// 64-bit four-word Philox engine. typedef philox_engine< uint_fast64_t, 64, 4, 10, diff --git a/libstdc++-v3/include/bits/random.tcc b/libstdc++-v3/include/bits/random.tcc index 53f302da8007..f4b9778e468e 100644 --- a/libstdc++-v3/include/bits/random.tcc +++ b/libstdc++-v3/include/bits/random.tcc @@ -907,197 +907,129 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __is; } -#if __cpp_lib_philox_engine - - template<class _UIntType, - size_t __w, size_t __n, - size_t __r, _UIntType... __consts> - _UIntType - philox_engine<_UIntType, - __w, __n, __r, __consts...>::_S_mulhi(_UIntType __a, _UIntType __b) - { - const __uint128_t __num = - static_cast<__uint128_t>(__a) * static_cast<__uint128_t>(__b); - return static_cast<_UIntType>((__num >> __w) & max()); - } +#if __glibcxx_philox_engine // >= C++26 - template<class _UIntType, - size_t __w, size_t __n, - size_t __r, _UIntType... __consts> - _UIntType - philox_engine<_UIntType, - __w, __n, __r, __consts...>::_S_mullo(_UIntType __a, _UIntType __b) - { - return static_cast<_UIntType>((__a * __b) & max()); - } + template<typename _UIntType, size_t __w, size_t __n, size_t __r, + _UIntType... __consts> + _UIntType + philox_engine<_UIntType, __w, __n, __r, __consts...>:: + _S_mulhi(_UIntType __a, _UIntType __b) + { + const __uint128_t __num = + static_cast<__uint128_t>(__a) * static_cast<__uint128_t>(__b); + return static_cast<_UIntType>((__num >> __w) & max()); + } - template<class _UIntType, - size_t __w, size_t __n, - size_t __r, _UIntType... __consts> - void - philox_engine<_UIntType, __w, __n, __r, __consts...>::_M_transition() - { - ++_M_i; - if (_M_i == __n) + template<typename _UIntType, size_t __w, size_t __n, size_t __r, + _UIntType... __consts> + _UIntType + philox_engine<_UIntType, __w, __n, __r, __consts...>:: + _S_mullo(_UIntType __a, _UIntType __b) { + return static_cast<_UIntType>((__a * __b) & max()); + } + + template<typename _UIntType, size_t __w, size_t __n, size_t __r, + _UIntType... __consts> + void + philox_engine<_UIntType, __w, __n, __r, __consts...>::_M_transition() + { + ++_M_i; + if (_M_i != __n) + return; + _M_philox(); if constexpr (__n == 4) - { - __uint128_t __uh = - (static_cast<__uint128_t>(_M_x[1]) << __w) - | (static_cast<__uint128_t>(_M_x[0]) + 1); - __uint128_t __lh = - ((static_cast<__uint128_t>(_M_x[3]) << __w) - | (_M_x[2])); - __uint128_t __bigMask = - (static_cast<__uint128_t>(1) << ((2 * __w) - 1)) - | ((static_cast<__uint128_t>(1) << ((2 * __w) - 1)) - 1); - if ((__uh & __bigMask) == 0) { - ++__lh; - __uh = 0; + __uint128_t __uh = + (static_cast<__uint128_t>(_M_x[1]) << __w) + | (static_cast<__uint128_t>(_M_x[0]) + 1); + __uint128_t __lh = + ((static_cast<__uint128_t>(_M_x[3]) << __w) + | (_M_x[2])); + __uint128_t __bigMask = + (static_cast<__uint128_t>(1) << ((2 * __w) - 1)) + | ((static_cast<__uint128_t>(1) << ((2 * __w) - 1)) - 1); + if ((__uh & __bigMask) == 0) + { + ++__lh; + __uh = 0; + } + _M_x[0] = __uh & max(); + _M_x[1] = (__uh >> (__w)) & max(); + _M_x[2] = __lh & max(); + _M_x[3] = (__lh >> (__w)) & max(); + } + else + { + __uint128_t __num = + (static_cast<__uint128_t>(_M_x[1]) << __w) + | (static_cast<__uint128_t>(_M_x[0]) + 1); + _M_x[0] = __num & max(); + _M_x[1] = (__num >> __w) & max(); } - _M_x[0] = __uh & max(); - _M_x[1] = (__uh >> (__w)) & max(); - _M_x[2] = __lh & max(); - _M_x[3] = (__lh >> (__w)) & max(); - } else - { - __uint128_t __num = - (static_cast<__uint128_t>(_M_x[1]) << __w) - | (static_cast<__uint128_t>(_M_x[0]) + 1); - _M_x[0] = __num & max(); - _M_x[1] = (__num >> __w) & max(); - } _M_i = 0; } - } - template<class _UIntType, - size_t __w, size_t __n, - size_t __r, _UIntType... __consts> - void - philox_engine<_UIntType, __w, __n, __r, __consts...>::_M_philox() - { - array<_UIntType, __n> __outputSeq{}; - for (size_t __j = 0; __j < __n; ++__j) - __outputSeq[__j] = _M_x[__j]; - for (unsigned long __j = 0; __j < __r; ++__j) + template<typename _UIntType, size_t __w, size_t __n, size_t __r, + _UIntType... __consts> + void + philox_engine<_UIntType, __w, __n, __r, __consts...>::_M_philox() { - array<_UIntType, __n> __intermedSeq{}; - if constexpr (__n == 4) - { - __intermedSeq[0] = __outputSeq[2]; - __intermedSeq[1] = __outputSeq[1]; - __intermedSeq[2] = __outputSeq[0]; - __intermedSeq[3] = __outputSeq[3]; - } else - { - __intermedSeq[0] = __outputSeq[0]; - __intermedSeq[1] = __outputSeq[1]; - } - for (unsigned long __k = 0; __k < (__n/2); ++__k) - { - __outputSeq[2*__k]= _S_mulhi(__intermedSeq[2*__k], multipliers[__k]) - ^ (((_M_k[__k] + (__j * round_consts[__k])) & max())) - ^ __intermedSeq[2*__k+1]; + array<_UIntType, __n> __outputSeq = _M_x; + for (size_t __j = 0; __j < __r; ++__j) + { + array<_UIntType, __n> __intermedSeq{}; + if constexpr (__n == 4) + { + __intermedSeq[0] = __outputSeq[2]; + __intermedSeq[1] = __outputSeq[1]; + __intermedSeq[2] = __outputSeq[0]; + __intermedSeq[3] = __outputSeq[3]; + } + else + { + __intermedSeq[0] = __outputSeq[0]; + __intermedSeq[1] = __outputSeq[1]; + } + for (unsigned long __k = 0; __k < (__n/2); ++__k) + { + __outputSeq[2*__k] + = _S_mulhi(__intermedSeq[2*__k], multipliers[__k]) + ^ (((_M_k[__k] + (__j * round_consts[__k])) & max())) + ^ __intermedSeq[2*__k+1]; - __outputSeq[(2*__k)+1]= _S_mullo(__intermedSeq[2*__k], - multipliers[__k]); - } + __outputSeq[(2*__k)+1] + = _S_mullo(__intermedSeq[2*__k], multipliers[__k]); + } + } + _M_y = __outputSeq; } - for (unsigned long __j = 0; __j < __n; ++__j) - _M_y[__j] = __outputSeq[__j]; - } - - template<class _UIntType, - size_t __w, size_t __n, - size_t __r, _UIntType... __consts> - philox_engine<_UIntType, - __w, __n, __r, __consts...>::philox_engine(result_type __value) - { - std::fill(_M_x.begin(), _M_x.end(), 0); - std::fill(_M_k.begin(), _M_k.end(), 0); - std::fill(_M_y.begin(), _M_y.end(), 0); - _M_k[0] = __value & max(); - _M_i = __n - 1; - } - template<class _UIntType, - size_t __w, size_t __n, - size_t __r, _UIntType... __consts> - void - philox_engine<_UIntType, - __w, __n, __r, __consts...>::seed(result_type __value) - { - std::fill(_M_x.begin(), _M_x.end(), 0); - std::fill(_M_k.begin(), _M_k.end(), 0); - std::fill(_M_y.begin(), _M_y.end(), 0); - _M_k[0] = __value & max(); - _M_i = __n - 1; - } - - template<class _UIntType, - size_t __w, size_t __n, - size_t __r, _UIntType... __consts> - void - philox_engine<_UIntType, __w, - __n, __r, __consts...>::set_counter(const array<result_type, __n>& __counter) - { - for (unsigned long long __j = 0; __j < __n; ++__j) - _M_x[__j] = __counter[__n - 1 - __j] & max(); - _M_i = __n - 1; - } - - template<class _UIntType, - size_t __w, size_t __n, - size_t __r, _UIntType... __consts> + template<typename _UIntType, size_t __w, size_t __n, size_t __r, + _UIntType... __consts> template<typename _Sseq> - auto - philox_engine<_UIntType, __w, __n, __r, __consts...>::seed(_Sseq& __q) - -> _If_seed_seq<_Sseq> - { - std::fill(_M_k.begin(), _M_k.end(), 0); - const unsigned long long __p = 1 + ((__w - 1)/ 32); - uint_least32_t __tmpArr[(__n / 2) * __p]; - __q.generate(__tmpArr + 0, __tmpArr + ((__n / 2) *__p)); - for (unsigned long long __k = 0; __k < (__n/2); ++__k) - { - unsigned long long __precalc = 0; - for (unsigned long long __j = 0; __j < __p; ++__j) - { - unsigned long long __multiplicand = (1ull << (32 * __j)); - __precalc += (__tmpArr[__k*__p + __j] * __multiplicand) & max(); - } - _M_k[__k] = __precalc; - } - std::fill(_M_x.begin(), _M_x.end(), 0); - std::fill(_M_y.begin(), _M_y.end(), 0); - _M_i = __n - 1; - } - - template<class _UIntType, - size_t __w, size_t __n, - size_t __r, _UIntType... __consts> - void - philox_engine<_UIntType, - __w, __n, __r, __consts...>::discard(unsigned long long __z) - { - for (unsigned long long __j = 0; __j < __z; ++__j) - _M_transition(); - } - - template<class _UIntType, - size_t __w, size_t __n, - size_t __r, _UIntType... __consts> - _UIntType - philox_engine<_UIntType, __w, __n, __r, __consts...>::operator()() - { - _M_transition(); - return _M_y[_M_i]; - } + void + philox_engine<_UIntType, __w, __n, __r, __consts...>::seed(_Sseq& __q) + requires __is_seed_seq<_Sseq> + { + seed(0); -#endif + const unsigned __p = 1 + ((__w - 1) / 32); + uint_least32_t __tmpArr[(__n/2) * __p]; + __q.generate(__tmpArr + 0, __tmpArr + ((__n/2) * __p)); + for (unsigned __k = 0; __k < (__n/2); ++__k) + { + unsigned long long __precalc = 0; + for (unsigned __j = 0; __j < __p; ++__j) + { + unsigned long long __multiplicand = (1ull << (32 * __j)); + __precalc += (__tmpArr[__k * __p + __j] * __multiplicand) & max(); + } + _M_k[__k] = __precalc; + } + } +#endif // philox_engine template<typename _IntType, typename _CharT, typename _Traits> std::basic_ostream<_CharT, _Traits>& diff --git a/libstdc++-v3/testsuite/26_numerics/random/philox4x32.cc b/libstdc++-v3/testsuite/26_numerics/random/philox4x32.cc index d5a8ca078eff..33842bb8db03 100644 --- a/libstdc++-v3/testsuite/26_numerics/random/philox4x32.cc +++ b/libstdc++-v3/testsuite/26_numerics/random/philox4x32.cc @@ -1,12 +1,16 @@ // { dg-do run { target c++26 } } -// { dg-require-cstdint "" } +// { dg-require-cpp-feature-test __cpp_lib_philox_engine } -// 29.5.4 Random Number Engine Class Templates -// 29.5.4.5 Class Template philox_engine +// N5014 29.5.6 Engines and engine adaptors with predefined parameters #include <random> #include <testsuite_hooks.h> +using test_type = std::philox_engine<std::uint_fast32_t, 32, 4, 10, + 0xCD9E8D57, 0x9E3779B9, + 0xD2511F53, 0xBB67AE85>; +static_assert( std::is_same_v<test_type, std::philox4x32> ); + void test01() { @@ -19,5 +23,4 @@ test01() int main() { test01(); - return 0; } diff --git a/libstdc++-v3/testsuite/26_numerics/random/philox4x64.cc b/libstdc++-v3/testsuite/26_numerics/random/philox4x64.cc index 131f094cb287..11a5691804e0 100644 --- a/libstdc++-v3/testsuite/26_numerics/random/philox4x64.cc +++ b/libstdc++-v3/testsuite/26_numerics/random/philox4x64.cc @@ -1,12 +1,16 @@ // { dg-do run { target c++26 } } -// { dg-require-cstdint "" } +// { dg-require-cpp-feature-test __cpp_lib_philox_engine } -// 29.5.4 Random Number Engine Class Templates -// 29.5.4.5 Class Template philox_engine +// N5014 29.5.6 Engines and engine adaptors with predefined parameters #include <random> #include <testsuite_hooks.h> +using test_type = std::philox_engine<std::uint_fast64_t, 64, 4, 10, + 0xCA5A826395121157, 0x9E3779B97F4A7C15, + 0xD2E7470EE14C6C93, 0xBB67AE8584CAA73B>; +static_assert( std::is_same_v<test_type, std::philox4x64> ); + void test01() { @@ -19,5 +23,4 @@ test01() int main() { test01(); - return 0; } diff --git a/libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/119794.cc b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/119794.cc deleted file mode 100644 index c3a5a0eb7545..000000000000 --- a/libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/119794.cc +++ /dev/null @@ -1,39 +0,0 @@ -// { dg-do run { target c++26 } } -// { dg-require-cstdint "" } - -#include <random> -#include <testsuite_hooks.h> - -int f(int x) -{ - std::seed_seq sq(&x, &x + 1); - auto rnd = std::philox4x32(sq); - return std::uniform_int_distribution<int>()(rnd); -} - -int g(int x) -{ - std::seed_seq sq(&x, &x + 1); - auto rnd = std::philox4x32(); - rnd.seed(sq); - return std::uniform_int_distribution<int>()(rnd); -} - -void test01() -{ - const int f1 = f(0); - const int f2 = f(0); - - const int g1 = g(0); - const int g2 = g(0); - - VERIFY( f1 == f2 ); - VERIFY( g1 == g2 ); - VERIFY( f1 == g1 ); -} - -int main() -{ - test01(); - return 0; -} diff --git a/libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/copy.cc b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/copy.cc index 4f61928a1575..163aec082332 100644 --- a/libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/copy.cc +++ b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/copy.cc @@ -1,25 +1,27 @@ // { dg-do run { target c++26 } } -// { dg-require-cstdint "" } +// { dg-require-cpp-feature-test __cpp_lib_philox_engine } -// 29.5.4 Random Number Engine Class Templates -// 29.5.4.5 Class Template philox_engine +// N5014 29.5.4 Random Number Engine Class Templates +// N5014 29.5.4.5 Class Template philox_engine #include <random> +#include <testsuite_hooks.h> void -test01() +test01(unsigned long seed) { std::philox_engine<std::uint_fast32_t, 32, 4, 10, 0xCD9E8D57, - 0x9E3779B9, 0xD2511F53, 0xBB67AE85> e(1ul); + 0x9E3779B9, 0xD2511F53, 0xBB67AE85> e(seed); const auto f(e); + VERIFY( f == e ); auto g(f); - g = g; // Suppress unused warning + VERIFY( g == f ); } int main() { - test01(); - return 0; + test01(1ul); + test01(111ul); } diff --git a/libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/default.cc b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/default.cc index 9f9ae94db0f3..183ca8201093 100644 --- a/libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/default.cc +++ b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/default.cc @@ -1,14 +1,13 @@ // { dg-do run { target c++26 } } -// { dg-require-cstdint "" } +// { dg-require-cpp-feature-test __cpp_lib_philox_engine } -// 29.5.4 Random Number Engine Class Templates -// 29.5.4.5 Class Template philox_engine +// N5014 29.5.4.5 Class Template philox_engine #include <random> #include <testsuite_hooks.h> void -test01() +test_default_ctor() { std::philox_engine<std::uint_fast32_t, 32, 4, 10, 0xCD9E8D57, @@ -20,8 +19,31 @@ test01() VERIFY( philox4x32nullkey() == 0x6627e8d5ul ); } +void +test_seed() +{ + unsigned long seed = 2; + std::philox4x32 seeded(seed); + + std::philox4x32 default_init; + VERIFY( seeded != default_init ); + + std::philox4x32 default_seeded(std::philox4x32::default_seed); + VERIFY( default_seeded == default_init ); +} + +void +test_seed_seq() +{ + std::seed_seq sseq{ 1, 2, 3, 4 }; + std::philox4x32 seeded(sseq); + std::philox4x32 default_init; + VERIFY( seeded != default_init ); +} + int main() { - test01(); - return 0; + test_default_ctor(); + test_seed(); + test_seed_seq(); } diff --git a/libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/seed.cc b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/seed.cc index 5cb914f4b45c..2b667b233644 100644 --- a/libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/seed.cc +++ b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/seed.cc @@ -1,20 +1,51 @@ // { dg-do run { target c++26 } } -// { dg-require-cstdint "" } +// { dg-require-cpp-feature-test __cpp_lib_philox_engine } #include <random> +#include <testsuite_hooks.h> + +int f(int x) +{ + std::seed_seq sq(&x, &x + 1); + auto rnd = std::philox4x32(sq); + return std::uniform_int_distribution<int>()(rnd); +} + +int g(int x) +{ + std::seed_seq sq(&x, &x + 1); + auto rnd = std::philox4x32(); + rnd.seed(sq); + return std::uniform_int_distribution<int>()(rnd); +} void test01() { - unsigned long seed = 2; - std::philox_engine<std::uint_fast32_t, - 32, 4, 10, 0xCD9E8D57, - 0x9E3779B9, 0xD2511F53, - 0xBB67AE85> philox4x32seeded(seed); + const int f1 = f(0); + const int f2 = f(0); + + const int g1 = g(0); + const int g2 = g(0); + + VERIFY( f1 == f2 ); + VERIFY( g1 == g2 ); + VERIFY( f1 == g1 ); +} + +void +test02() +{ + std::philox4x64 e1(25); + std::philox4x64 e2; + VERIFY( e2 != e1 ); + e2.seed(25); + VERIFY( e2 == e1 ); + } int main() { test01(); - return 0; + test02(); } diff --git a/libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/seed_seq.cc b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/seed_seq.cc deleted file mode 100644 index 7d9e3e6540d2..000000000000 --- a/libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/seed_seq.cc +++ /dev/null @@ -1,24 +0,0 @@ -// { dg-do run { target c++26 } } -// { dg-require-cstdint "" } - -// 29.5.4 Random Number Engine Class Templates -// 29.5.4.5 Class Template philox_engine - -#include <random> - -void -test01() -{ - std::seed_seq sseq{ 1, 2, 3, 4 }; - std::philox_engine<std::uint_fast32_t, - 32, 4, 10, 0xCD9E8D57, - 0x9E3779B9, 0xD2511F53, - 0xBB67AE85> philox4x32sseq(sseq); -} - -int -main() -{ - test01(); - return 0; -} diff --git a/libstdc++-v3/testsuite/26_numerics/random/philox_engine/operators/equal.cc b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/operators/equal.cc index 4f62bfbbd88e..cca1654603ef 100644 --- a/libstdc++-v3/testsuite/26_numerics/random/philox_engine/operators/equal.cc +++ b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/operators/equal.cc @@ -1,8 +1,7 @@ // { dg-do run { target c++26 } } -// { dg-require-cstdint "" } +// { dg-require-cpp-feature-test __cpp_lib_philox_engine } -// 29.5.4 Random Number Engine Class Templates -// 29.5.4.5 Class Template philox_engine +// N5014 29.5.4.5 Class Template philox_engine #include <random> #include <testsuite_hooks.h> @@ -20,11 +19,15 @@ test01() y.discard(100); VERIFY (x == y); + + x.discard(2); + VERIFY (x != y); + y.discard(2); + VERIFY (x == y); } int main() { test01(); - return 0; } diff --git a/libstdc++-v3/testsuite/26_numerics/random/philox_engine/operators/inequal.cc b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/operators/inequal.cc deleted file mode 100644 index 86d757db9040..000000000000 --- a/libstdc++-v3/testsuite/26_numerics/random/philox_engine/operators/inequal.cc +++ /dev/null @@ -1,30 +0,0 @@ -// { dg-do run { target c++26 } } -// { dg-require-cstdint "" } - -// 29.5.4 Random Number Engine Class Templates -// 29.5.4.5 Class Template philox_engine - -#include <random> -#include <testsuite_hooks.h> - -void -test01() -{ - std::philox_engine<std::uint_fast32_t, - 32, 4, 10, 0xCD9E8D57, - 0x9E3779B9, 0xD2511F53, - 0xBB67AE85> x, y; - - VERIFY ( !(x != y) ); - x.discard(100); - y.discard(100); - - VERIFY ( !(x != y) ); -} - -int -main() -{ - test01(); - return 0; -} diff --git a/libstdc++-v3/testsuite/26_numerics/random/philox_engine/operators/serialize.cc b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/operators/serialize.cc index bec4b1725127..4bd40e74a6b5 100644 --- a/libstdc++-v3/testsuite/26_numerics/random/philox_engine/operators/serialize.cc +++ b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/operators/serialize.cc @@ -1,13 +1,11 @@ // { dg-do run { target c++26 } } -// { dg-require-cstdint "" } +// { dg-require-cpp-feature-test __cpp_lib_philox_engine } -// 29.5.4 Random Number Engine Class Templates -// 29.5.4.5 Class Template philox_engine +// N5014 29.5.4.5 Class Template philox_engine #include <sstream> #include <random> #include <testsuite_hooks.h> -#include <iostream> void test01() @@ -45,5 +43,4 @@ int main() { test01(); - return 0; } diff --git a/libstdc++-v3/testsuite/26_numerics/random/philox_engine/requirements/constants.cc b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/requirements/constants.cc index c242056e0a4b..a3cb24eb0667 100644 --- a/libstdc++-v3/testsuite/26_numerics/random/philox_engine/requirements/constants.cc +++ b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/requirements/constants.cc @@ -1,26 +1,48 @@ -// { dg-do run { target c++26 } } -// { dg-require-cstdint "" } +// { dg-do compile { target c++26 } } +// { dg-require-cpp-feature-test __cpp_lib_philox_engine } -// 29.5.4 Random Number Engine Class Templates -// 29.5.4.5 Class Template philox_engine +// N5014 29.5.4.5 Class Template philox_engine #include <random> -void test01() +namespace test1 { - std::philox4x32 philox; - const void* p = &philox.word_size; - p = &philox.word_count; - p = &philox.round_count; - p = &philox.multipliers; - p = &philox.round_consts; - p = &philox.default_seed; - p = p; // Suppress unused warning. + using P = std::philox_engine<std::uint32_t, 32, 4, 5, 9, 99, 999, 9999>; + constexpr std::same_as<std::uint32_t> auto min = P::min(); + static_assert( min == 0 ); + constexpr std::same_as<std::uint32_t> auto max = P::max(); + static_assert( max == 0xffffffff ); + constexpr std::same_as<std::size_t> auto w = P::word_size; + static_assert( w == 32 ); + constexpr std::same_as<std::size_t> auto n = P::word_count; + static_assert( n == 4 ); + constexpr std::same_as<std::size_t> auto r = P::round_count; + static_assert( r == 5 ); + constexpr std::array<std::uint32_t, 2> muls = P::multipliers; + static_assert( muls[0] == 9 && muls[1] == 999 ); + constexpr std::array<std::uint32_t, 2> consts = P::round_consts; + static_assert( consts[0] == 99 && consts[1] == 9999 ); + constexpr std::same_as<std::uint32_t> auto def = P::default_seed; + static_assert( def == 20111115u ); } -int -main() +namespace test2 { - test01(); - return 0; + using P = std::philox_engine<std::uint64_t, 64, 2, 12, 77, 777>; + constexpr std::same_as<std::uint64_t> auto min = P::min(); + static_assert( min == 0 ); + constexpr std::same_as<std::uint64_t> auto max = P::max(); + static_assert( max == 0xffffffffffffffff ); + constexpr std::same_as<std::size_t> auto w = P::word_size; + static_assert( w == 64 ); + constexpr std::same_as<std::size_t> auto n = P::word_count; + static_assert( n == 2 ); + constexpr std::same_as<std::size_t> auto r = P::round_count; + static_assert( r == 12 ); + constexpr std::array<std::uint64_t, 1> muls = P::multipliers; + static_assert( muls[0] == 77 ); + constexpr std::array<std::uint64_t, 1> consts = P::round_consts; + static_assert( consts[0] == 777 ); + constexpr std::same_as<std::uint64_t> auto def = P::default_seed; + static_assert( def == 20111115u ); } diff --git a/libstdc++-v3/testsuite/26_numerics/random/philox_engine/requirements/constexpr_data.cc b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/requirements/constexpr_data.cc deleted file mode 100644 index 5be0108c88cd..000000000000 --- a/libstdc++-v3/testsuite/26_numerics/random/philox_engine/requirements/constexpr_data.cc +++ /dev/null @@ -1,50 +0,0 @@ -// { dg-do run { target c++26 } } -// { dg-require-cstdint "" } - -// 29.5.4 Random Number Engine Class Templates -// 29.5.4.5 Class Template philox_engine - -#include <random> -#include <testsuite_common_types.h> - -namespace __gnu_test -{ - struct constexpr_member_data - { - template<typename _Ttesttype> - void - operator()() - { - struct _Concept - { - void __constraint() - { - constexpr auto v1 __attribute__((unused)) - = _Ttesttype::word_size; - constexpr auto v2 __attribute__((unused)) - = _Ttesttype::word_count; - constexpr auto v3 __attribute__((unused)) - = _Ttesttype::round_count; - constexpr auto v4 __attribute__((unused)) - = _Ttesttype::multipliers; - constexpr auto v5 __attribute__((unused)) - = _Ttesttype::round_consts; - constexpr auto v6 __attribute__((unused)) - = _Ttesttype::default_seed; - } - }; - - _Concept c; - c.__constraint(); - } - }; -}; - -int -main() -{ - __gnu_test::constexpr_member_data test; - typedef std::philox4x32 type; - test.operator()<type>(); - return 0; -} diff --git a/libstdc++-v3/testsuite/26_numerics/random/philox_engine/requirements/constexpr_functions.cc b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/requirements/constexpr_functions.cc deleted file mode 100644 index eb61d15568aa..000000000000 --- a/libstdc++-v3/testsuite/26_numerics/random/philox_engine/requirements/constexpr_functions.cc +++ /dev/null @@ -1,41 +0,0 @@ -// { dg-do run { target c++26 } } -// { dg-require-cstdint "" } - -// 29.5.4 Random Number Engine Class Templates -// 29.5.4.5 Class Template philox_engine - -#include <random> -#include <testsuite_common_types.h> - -namespace __gnu_test -{ - struct constexpr_member_functions - { - template<typename _Ttesttype> - void - operator()() - { - struct _Concept - { - void __constraint() - { - constexpr auto v1 __attribute__((unused)) - = _Ttesttype::min(); - constexpr auto v2 __attribute__((unused)) - = _Ttesttype::max(); - } - }; - _Concept c; - c.__constraint(); - } - }; -} - -int -main() -{ - __gnu_test::constexpr_member_functions test; - typedef std::philox4x32 type; - test.operator()<type>(); - return 0; -} diff --git a/libstdc++-v3/testsuite/26_numerics/random/philox_engine/requirements/typedefs.cc b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/requirements/typedefs.cc index b368ee741069..1fc8fedc4c69 100644 --- a/libstdc++-v3/testsuite/26_numerics/random/philox_engine/requirements/typedefs.cc +++ b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/requirements/typedefs.cc @@ -1,9 +1,7 @@ -// { dg-do run { target c++26 } } -// { dg-require-cstdint "" } - -// 29.5.4 Random Number Engine Class Templates -// 29.5.4.5 Class Template philox_engine +// { dg-do compile { target c++26 } } +// { dg-require-cpp-feature-test __cpp_lib_philox_engine } +// N5014 29.5.4.5 Class Template philox_engine #include <random> @@ -16,11 +14,17 @@ test01() 0xBB67AE85> testType; typedef testType::result_type result_type; + static_assert( std::is_same_v<result_type, std::uint_fast32_t> ); } -int -main() +void +test02() { - test01(); - return 0; + typedef std::philox_engine<std::uint_fast64_t, + 64, 4, 10, 0xCA5A826395121157, + 0x9E3779B97F4A7C15, 0xD2E7470EE14C6C93, + 0xBB67AE8584CAA73B> testType; + + typedef testType::result_type result_type; + static_assert( std::is_same_v<result_type, std::uint_fast64_t> ); } diff --git a/libstdc++-v3/testsuite/26_numerics/random/pr60037-neg.cc b/libstdc++-v3/testsuite/26_numerics/random/pr60037-neg.cc index 13a0b8947b05..4b36f75bba26 100644 --- a/libstdc++-v3/testsuite/26_numerics/random/pr60037-neg.cc +++ b/libstdc++-v3/testsuite/26_numerics/random/pr60037-neg.cc @@ -12,4 +12,4 @@ auto x = std::generate_canonical<std::size_t, // { dg-error "static assertion failed: template argument must be a floating point type" "" { target *-*-* } 271 } -// { dg-error "static assertion failed: template argument must be a floating point type" "" { target *-*-* } 3548 } +// { dg-error "static assertion failed: template argument must be a floating point type" "" { target *-*-* } 3480 }