Awesome! Thanks for taking care of the ChangeLog entry, and my apologies for missing that. I'll start trying to get support for targets not supporting __uint128_t. Thanks for the feedback throughout as well!
On Tuesday, August 19th, 2025 at 8:42 AM, Patrick Palka <ppa...@redhat.com> wrote: > On Tue, 5 Aug 2025, 1nfocalypse wrote: > > > Implements Philox Engine (P2075R6) and associated tests. > > > > Implements additional feedback from v5 from Patrick Palka. > > Also cut some trailing whitespace from the limb propagation > > fix in v5. > > > > Apologies for the delay from v5 - I had to finish writing some > > CTF challenges for DEFCON this week. Thank you for the > > feedback, and please let me know if anything further needs > > to be changed. > > > > Built/tested on x86_64-pc-linux-gnu. > > > This version LGTM! A ChangeLog entry in the commit message is missing > (https://gcc.gnu.org/codingconventions.html#ChangeLogs) but I'm > happy to take care of that while pushing, it'll consist of mostly > boilerplate for a new feature like this. > > > Subject: [PATCH] [PATCH v6] libstdc++: Implement Philox Engine (PR119794) > > > > Implemented additional changes from Patrick Palka. > > Also removed some trailing whitespace in random.tcc. > > > > replaced alias of __ios_base with ios_base > > included <iomanip> in random.h > > altered line number in pr60037-neg.cc to be accurate > > Refactored iterator/index loops to be range-based for > > in istream/ostream operator overloads > > include <random> in philox_engine/cons/seed_seq.cc > > Conforms with errata LWG4143, LWG4153 for Philox Engine. > > > > PR libstdc++/119794 > > --- > > 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 + > > .../26_numerics/random/philox4x32.cc | 23 ++ > > .../26_numerics/random/philox4x64.cc | 23 ++ > > .../random/philox_engine/cons/119794.cc | 39 +++ > > .../random/philox_engine/cons/copy.cc | 25 ++ > > .../random/philox_engine/cons/default.cc | 27 ++ > > .../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 ++ > > .../philox_engine/operators/serialize.cc | 49 +++ > > .../philox_engine/requirements/constants.cc | 26 ++ > > .../requirements/constexpr_data.cc | 50 ++++ > > .../requirements/constexpr_functions.cc | 41 +++ > > .../philox_engine/requirements/typedefs.cc | 26 ++ > > .../26_numerics/random/pr60037-neg.cc | 4 +- > > 20 files changed, 931 insertions(+), 2 deletions(-) > > create mode 100644 libstdc++-v3/testsuite/26_numerics/random/philox4x32.cc > > create mode 100644 libstdc++-v3/testsuite/26_numerics/random/philox4x64.cc > > create mode 100644 > > libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/119794.cc > > create mode 100644 > > libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/copy.cc > > create mode 100644 > > libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/default.cc > > create mode 100644 > > libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/seed.cc > > create mode 100644 > > libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/seed_seq.cc > > create mode 100644 > > libstdc++-v3/testsuite/26_numerics/random/philox_engine/operators/equal.cc > > create mode 100644 > > libstdc++-v3/testsuite/26_numerics/random/philox_engine/operators/inequal.cc > > create mode 100644 > > libstdc++-v3/testsuite/26_numerics/random/philox_engine/operators/serialize.cc > > create mode 100644 > > libstdc++-v3/testsuite/26_numerics/random/philox_engine/requirements/constants.cc > > create mode 100644 > > libstdc++-v3/testsuite/26_numerics/random/philox_engine/requirements/constexpr_data.cc > > create mode 100644 > > libstdc++-v3/testsuite/26_numerics/random/philox_engine/requirements/constexpr_functions.cc > > create mode 100644 > > libstdc++-v3/testsuite/26_numerics/random/philox_engine/requirements/typedefs.cc > > > > diff --git a/libstdc++-v3/include/bits/random.h > > b/libstdc++-v3/include/bits/random.h > > index 1fdaf51934f..e74b7bd75c0 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); // (AB)/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); // (AB)%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 53ccacb2e38..53f302da800 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 dbe2cb8f175..4c21fa187c8 100644 > > --- a/libstdc++-v3/include/bits/version.def > > +++ b/libstdc++-v3/include/bits/version.def > > @@ -2069,6 +2069,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 7bb6016df68..75a9946adce 100644 > > --- a/libstdc++-v3/include/bits/version.h > > +++ b/libstdc++-v3/include/bits/version.h > > @@ -2318,4 +2318,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 0e058a04bd9..8a02ade4b75 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 00000000000..d5a8ca078ef > > --- /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 00000000000..131f094cb28 > > --- /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 00000000000..c3a5a0eb754 > > --- /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 00000000000..4f61928a157 > > --- /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 00000000000..9f9ae94db0f > > --- /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 00000000000..5cb914f4b45 > > --- /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 00000000000..7d9e3e6540d > > --- /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 00000000000..4f62bfbbd88 > > --- /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 00000000000..86d757db904 > > --- /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 00000000000..bec4b172512 > > --- /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 00000000000..c242056e0a4 > > --- /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 00000000000..5be0108c88c > > --- /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 00000000000..eb61d15568a > > --- /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 00000000000..b368ee74106 > > --- /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 0afba654152..13a0b8947b0 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_limitsstd::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 } > > -- > > 2.49.0