https://gcc.gnu.org/g:1c06243e65561726ae4fc1060b6164d0caec2ae6
commit r16-4062-g1c06243e65561726ae4fc1060b6164d0caec2ae6 Author: 1nfocalypse <1nfocaly...@protonmail.com> Date: Tue Aug 5 01:37:18 2025 +0000 libstdc++: Implement Philox Engine (PR119794) Conforms with errata LWG4143, LWG4153 for Philox Engine. PR libstdc++/119794 libstdc++-v3/ChangeLog: * include/bits/random.h (philox_engine): Define. * include/bits/random.tcc (philox_engine): Define member functions. * include/bits/version.def (philox_engine): New macro. * include/bits/version.h: Regenerated. * include/std/random: Define __glibcxx_want_philox_engine and include <bits/version.h>. * testsuite/26_numerics/random/pr60037-neg.cc: Adjust dg-error line number. * testsuite/26_numerics/random/philox4x32.cc: New test. * testsuite/26_numerics/random/philox4x64.cc: New test. * testsuite/26_numerics/random/philox_engine/cons/119794.cc: New test. * testsuite/26_numerics/random/philox_engine/cons/copy.cc: New test. * testsuite/26_numerics/random/philox_engine/cons/default.cc: New test. * testsuite/26_numerics/random/philox_engine/cons/seed.cc: New test. * testsuite/26_numerics/random/philox_engine/cons/seed_seq.cc: New test. * testsuite/26_numerics/random/philox_engine/operators/equal.cc: New test. * testsuite/26_numerics/random/philox_engine/operators/inequal.cc: New test. * testsuite/26_numerics/random/philox_engine/operators/serialize.cc: New test. * testsuite/26_numerics/random/philox_engine/requirements/constants.cc: New test. * testsuite/26_numerics/random/philox_engine/requirements/constexpr_data.cc: New test. * testsuite/26_numerics/random/philox_engine/requirements/constexpr_functions.cc: New test. * testsuite/26_numerics/random/philox_engine/requirements/typedefs.cc: New test. Diff: --- libstdc++-v3/include/bits/random.h | 283 +++++++++++++++++++++ libstdc++-v3/include/bits/random.tcc | 191 ++++++++++++++ libstdc++-v3/include/bits/version.def | 9 + libstdc++-v3/include/bits/version.h | 10 + libstdc++-v3/include/std/random | 3 + .../testsuite/26_numerics/random/philox4x32.cc | 23 ++ .../testsuite/26_numerics/random/philox4x64.cc | 23 ++ .../random/philox_engine/cons/119794.cc | 39 +++ .../26_numerics/random/philox_engine/cons/copy.cc | 25 ++ .../random/philox_engine/cons/default.cc | 27 ++ .../26_numerics/random/philox_engine/cons/seed.cc | 20 ++ .../random/philox_engine/cons/seed_seq.cc | 24 ++ .../random/philox_engine/operators/equal.cc | 30 +++ .../random/philox_engine/operators/inequal.cc | 30 +++ .../random/philox_engine/operators/serialize.cc | 49 ++++ .../random/philox_engine/requirements/constants.cc | 26 ++ .../philox_engine/requirements/constexpr_data.cc | 50 ++++ .../requirements/constexpr_functions.cc | 41 +++ .../random/philox_engine/requirements/typedefs.cc | 26 ++ .../testsuite/26_numerics/random/pr60037-neg.cc | 4 +- 20 files changed, 931 insertions(+), 2 deletions(-) diff --git a/libstdc++-v3/include/bits/random.h b/libstdc++-v3/include/bits/random.h index 1fdaf51934fd..e74b7bd75c03 100644 --- a/libstdc++-v3/include/bits/random.h +++ b/libstdc++-v3/include/bits/random.h @@ -33,6 +33,7 @@ #include <vector> #include <bits/uniform_int_dist.h> +#include <iomanip> namespace std _GLIBCXX_VISIBILITY(default) { @@ -1688,6 +1689,270 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return !(__lhs == __rhs); } #endif +#if __cpp_lib_philox_engine + + /** + * @brief: A discrete pseudorandom number generator based off of weakened + * cryptographic primitives. + * + * 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. + * + * The two four-word definitions are likely the best use for this algorithm, + * and are given below as defaults. + * + * This algorithm was created by John Salmon, Mark Moraes, Ron Dror, and + * David Shaw as a product of D.E. Shaw Research. + * + * @tparam __w Word size + * @tparam __n Buffer size + * @tparam __r Rounds + * @tparam __consts Multiplication and round constant pack, ordered as + * M_{0}, C_{0}, M_{1}, C_{1}, ... , M_{N/2-1}, C_{N/2-1} + * + * @headerfile random + * @since C++26 + */ + template<class _UIntType, size_t __w, + size_t __n, size_t __r, + _UIntType... __consts> + class philox_engine + { + static_assert(__n == 2 || __n == 4, + "template argument N must be either 2 or 4"); + static_assert(sizeof...(__consts) == __n, + "length of consts array must match specified N"); + 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>; + + 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]}; + } + + 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>(); + + /** @brief returns the minimum value possible. */ + static constexpr result_type + min() + { return 0; } + + /** @brief returns the maximum value possible. */ + static constexpr result_type + max() + { + return ((1ull << (__w - 1)) | ((1ull << (__w - 1)) - 1)); + } + // default key value + static constexpr result_type default_seed = 20111115u; + + // constructors + philox_engine() + : philox_engine(default_seed) + {} + + explicit + philox_engine(result_type __value); + + /** @brief seed sequence constructor for %philox_engine + * + * @params __q the seed sequence + */ + template<typename _Sseq, typename = _If_seed_seq<_Sseq>> + explicit + philox_engine(_Sseq& __q) + { + seed(__q); + } + + void + seed(result_type value = default_seed); + + /** @brief seeds %philox_engine by seed sequence + * + * @params __q the seed sequence + */ + template<typename _Sseq> + _If_seed_seq<_Sseq> + seed(_Sseq& __q); + + /** @brief sets the internal counter "cleartext" + * + * @params __counter std::array of len N + */ + void + set_counter(const array<result_type, __n>& __counter); + + /** @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 + */ + 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); + } + + /** @brief outputs a single w-bit number and handles state advancement + * + * @returns return_type + */ + _UIntType + operator()(); + + /** @brief discards __z numbers + * + * @params __z number of iterations to discard + */ + void + discard(unsigned long long __z); + + /** @brief outputs the state of the generator + * + * @param __os An output stream. + * @param __x A %philox_engine object reference + * + * @returns the state of the Philox Engine in __os + */ + 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; + } + + /** @brief takes input to set the state of the %philox_engine object + * + * @param __is An input stream. + * @param __x A %philox_engine object reference + * + * @returns %philox_engine object is set with values from instream + */ + template <typename _CharT, typename _Traits> + friend basic_istream<_CharT, _Traits>& + 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) + { + 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; + } + private: + // private state variables + array<_UIntType, __n> _M_x; + array<_UIntType, __n / 2> _M_k; + 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 + _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 + _S_mullo(_UIntType __a, _UIntType __b); // (A*B)%2^W + + /** @brief an R-round substitution/Feistel Network hybrid for + * %philox_engine + */ + void + _M_philox(); + + /** @brief an internal transition function for the %philox_engine. */ + void + _M_transition(); + }; + +#endif + /** * The classic Minimum Standard rand0 of Lewis, Goodman, and Miller. */ @@ -1742,6 +2007,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef minstd_rand0 default_random_engine; +#if __cpp_lib_philox_engine + + typedef philox_engine< + uint_fast32_t, + 32, 4, 10, + 0xCD9E8D57, 0x9E3779B9, + 0xD2511F53, 0xBB67AE85> philox4x32; + + /** + * Alternative Philox instance (64 bit) + */ + typedef philox_engine< + uint_fast64_t, + 64, 4, 10, + 0xCA5A826395121157, 0x9E3779B97F4A7C15, + 0xD2E7470EE14C6C93, 0xBB67AE8584CAA73B> philox4x64; +#endif + /** * A standard interface to a platform-specific non-deterministic * random number generator (if any are available). diff --git a/libstdc++-v3/include/bits/random.tcc b/libstdc++-v3/include/bits/random.tcc index 53ccacb2e38b..53f302da8007 100644 --- a/libstdc++-v3/include/bits/random.tcc +++ b/libstdc++-v3/include/bits/random.tcc @@ -907,6 +907,197 @@ _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()); + } + + 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<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) + { + _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; + } + _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) + { + 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]); + } + } + 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 _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]; + } + +#endif template<typename _IntType, typename _CharT, typename _Traits> std::basic_ostream<_CharT, _Traits>& diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def index 721125df280f..3a26234f87ed 100644 --- a/libstdc++-v3/include/bits/version.def +++ b/libstdc++-v3/include/bits/version.def @@ -2137,6 +2137,15 @@ ftms = { }; }; +ftms = { + name = philox_engine; + values = { + v = 202406; + cxxmin = 26; + extra_cond = "__SIZEOF_INT128__"; + }; +}; + // Standard test specifications. stds[97] = ">= 199711L"; stds[03] = ">= 199711L"; diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h index 7e8ad1007efa..46e4c1121e7a 100644 --- a/libstdc++-v3/include/bits/version.h +++ b/libstdc++-v3/include/bits/version.h @@ -2397,4 +2397,14 @@ #endif /* !defined(__cpp_lib_constexpr_exceptions) && defined(__glibcxx_want_constexpr_exceptions) */ #undef __glibcxx_want_constexpr_exceptions +#if !defined(__cpp_lib_philox_engine) +# if (__cplusplus > 202302L) && (__SIZEOF_INT128__) +# define __glibcxx_philox_engine 202406L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_philox_engine) +# define __cpp_lib_philox_engine 202406L +# endif +# endif +#endif /* !defined(__cpp_lib_philox_engine) && defined(__glibcxx_want_philox_engine) */ +#undef __glibcxx_want_philox_engine + #undef __glibcxx_want_all diff --git a/libstdc++-v3/include/std/random b/libstdc++-v3/include/std/random index 0e058a04bd9a..8a02ade4b75e 100644 --- a/libstdc++-v3/include/std/random +++ b/libstdc++-v3/include/std/random @@ -39,6 +39,9 @@ # include <bits/c++0x_warning.h> #else +#define __glibcxx_want_philox_engine +#include <bits/version.h> + #include <cmath> #include <cstdint> // For uint_fast32_t, uint_fast64_t, uint_least32_t #include <cstdlib> diff --git a/libstdc++-v3/testsuite/26_numerics/random/philox4x32.cc b/libstdc++-v3/testsuite/26_numerics/random/philox4x32.cc new file mode 100644 index 000000000000..d5a8ca078eff --- /dev/null +++ b/libstdc++-v3/testsuite/26_numerics/random/philox4x32.cc @@ -0,0 +1,23 @@ +// { 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::philox4x32 a; + a.discard(9999); + + VERIFY( a() == 1955073260 ); +} + +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 new file mode 100644 index 000000000000..131f094cb287 --- /dev/null +++ b/libstdc++-v3/testsuite/26_numerics/random/philox4x64.cc @@ -0,0 +1,23 @@ +// { 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::philox4x64 a; + a.discard(9999); + + VERIFY( a() == 3409172418970261260 ); +} + +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 new file mode 100644 index 000000000000..c3a5a0eb7545 --- /dev/null +++ b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/119794.cc @@ -0,0 +1,39 @@ +// { 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 new file mode 100644 index 000000000000..4f61928a1575 --- /dev/null +++ b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/copy.cc @@ -0,0 +1,25 @@ +// { 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::philox_engine<std::uint_fast32_t, 32, 4, 10, 0xCD9E8D57, + 0x9E3779B9, 0xD2511F53, 0xBB67AE85> e(1ul); + + const auto f(e); + auto g(f); + g = g; // Suppress unused warning +} + +int main() +{ + test01(); + return 0; +} 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 new file mode 100644 index 000000000000..9f9ae94db0f3 --- /dev/null +++ b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/default.cc @@ -0,0 +1,27 @@ +// { 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> philox4x32nullkey(0); + + VERIFY( philox4x32nullkey.min() == 0 ); + VERIFY( philox4x32nullkey.max() == (1ul << 31 | (1ul << 31) - 1) ); + VERIFY( philox4x32nullkey() == 0x6627e8d5ul ); +} + +int main() +{ + test01(); + return 0; +} 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 new file mode 100644 index 000000000000..5cb914f4b45c --- /dev/null +++ b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/seed.cc @@ -0,0 +1,20 @@ +// { dg-do run { target c++26 } } +// { dg-require-cstdint "" } + +#include <random> + +void +test01() +{ + unsigned long seed = 2; + std::philox_engine<std::uint_fast32_t, + 32, 4, 10, 0xCD9E8D57, + 0x9E3779B9, 0xD2511F53, + 0xBB67AE85> philox4x32seeded(seed); +} + +int main() +{ + test01(); + return 0; +} 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 new file mode 100644 index 000000000000..7d9e3e6540d2 --- /dev/null +++ b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/seed_seq.cc @@ -0,0 +1,24 @@ +// { 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 new file mode 100644 index 000000000000..4f62bfbbd88e --- /dev/null +++ b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/operators/equal.cc @@ -0,0 +1,30 @@ +// { 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/inequal.cc b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/operators/inequal.cc new file mode 100644 index 000000000000..86d757db9040 --- /dev/null +++ b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/operators/inequal.cc @@ -0,0 +1,30 @@ +// { 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 new file mode 100644 index 000000000000..bec4b1725127 --- /dev/null +++ b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/operators/serialize.cc @@ -0,0 +1,49 @@ +// { 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 <sstream> +#include <random> +#include <testsuite_hooks.h> +#include <iostream> + +void +test01() +{ + std::stringstream str; + std::philox_engine<std::uint_fast32_t, + 32, 4, 10, 0xCD9E8D57, + 0x9E3779B9, 0xD2511F53, + 0xBB67AE85> x, y; + + x(); + str << x; + + VERIFY ( !(x == y) ); + str >> y; + VERIFY ( x == y ); + for (unsigned long i = 0; i < 100; ++i) + { + VERIFY (x() == y()); + } + str.clear(); + str << y; + x(); + x(); + x(); + str >> x; + VERIFY ( x == y ); + for (unsigned long i = 0; i < 1000; ++i) + { + VERIFY (x() == y()); + } +} + +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 new file mode 100644 index 000000000000..c242056e0a4b --- /dev/null +++ b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/requirements/constants.cc @@ -0,0 +1,26 @@ +// { 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::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. +} + +int +main() +{ + test01(); + return 0; +} 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 new file mode 100644 index 000000000000..5be0108c88cd --- /dev/null +++ b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/requirements/constexpr_data.cc @@ -0,0 +1,50 @@ +// { 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 new file mode 100644 index 000000000000..eb61d15568aa --- /dev/null +++ b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/requirements/constexpr_functions.cc @@ -0,0 +1,41 @@ +// { 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 new file mode 100644 index 000000000000..b368ee741069 --- /dev/null +++ b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/requirements/typedefs.cc @@ -0,0 +1,26 @@ +// { 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() +{ + typedef std::philox_engine<std::uint_fast32_t, + 32, 4, 10, 0xCD9E8D57, + 0x9E3779B9, 0xD2511F53, + 0xBB67AE85> testType; + + typedef testType::result_type result_type; +} + +int +main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/26_numerics/random/pr60037-neg.cc b/libstdc++-v3/testsuite/26_numerics/random/pr60037-neg.cc index 0afba654152c..13a0b8947b05 100644 --- a/libstdc++-v3/testsuite/26_numerics/random/pr60037-neg.cc +++ b/libstdc++-v3/testsuite/26_numerics/random/pr60037-neg.cc @@ -10,6 +10,6 @@ std::__detail::_Adaptor<std::mt19937, unsigned long> aurng(urng); auto x = std::generate_canonical<std::size_t, std::numeric_limits<std::size_t>::digits>(urng); -// { dg-error "static assertion failed: template argument must be a floating point type" "" { target *-*-* } 270 } +// { 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 *-*-* } 3357 } +// { dg-error "static assertion failed: template argument must be a floating point type" "" { target *-*-* } 3548 }