Hi, On Thu, 22 May 2025, 1nfocalypse wrote:
> Implements Philox Engine (P2075R6) and associated tests. > > v2 corrects a multiline comment left in error in serialize.cc, and > additionally corrects a bug hidden by said comment, where the stream was > given the output of 'y()' instead of 'y', causing state to be > incorrectly passed. Lastly, it fixes numerous whitespace issues found in the > original patch. My apologies for not noticing prior to the submission of the > original patch, which can now be disregarded. > > To reiterate from the original email, the template unpacking functions are > placed in a private classifier prior to the public one due to an ordering > bug, where in order to function correctly, they must be > placed prior to the bulk of the header. This is counter to the style > recommendations, but I was unable to obtain functionality any other way. > Additionally, while SIMD instructions are not utilized, and I do > not think that they would integrate well with how the generator's state is > currently handled, some structure choices could be made that may make them of > interest. > > Lastly, since word width can be specified, and thus atypical, maximum value > is calculated via some bit manipulation rather than numeric_limits, since the > specified width may differ from the width of the type > used. > > Built/tested on x86_64-linux-gnu. Sorry for the delay and thanks for your patience! Some initial review comments below. > > * 1nfocalypse > > > > > Subject: [PATCH] [PATCH v2] libstdc++: implement Philox Engine [PR119794] > > The template unpacking functions, while private, are placed prior > to the public access specifier due to issues where the template > pack could not be unpacked and used to populate the public member > arrays without being declared beforehand. > > Additionally, the tests implemented attempt to mirror the tests > for other engines, when they apply. Changes to random > provided cause for changing 'pr60037-neg.cc' because it suppresses > an error by explicit line number. It should still be correctly > suppressed in this patch. Lastly, v2 fixes an issue in > 'serialize.cc' for Philox, where a portion of the test was > commented out, hiding a bug where 'y()' was passed to the > stream instead of 'y'. Both have been remedied in this patch. This implements the changes to the original paper https://wg21.link/lwg4134 https://wg21.link/lwg4153 right? Maybe we could make a note of that in the commit message. > > Plus some whitespace fixes. > > PR libstdc++/119794 > > libstdc++-v3/ChangeLog: > > * include/bits/random.h: Add Philox Engine components. > * include/bits/random.tcc: Implement Philox Engine components. > * testsuite/26_numerics/random/pr60037-neg.cc: Alter line #. > * testsuite/26_numerics/random/inequal.cc: New test. > * 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. > --- > libstdc++-v3/include/bits/random.h | 340 ++++++++++++++++++ > libstdc++-v3/include/bits/random.tcc | 201 +++++++++++ > .../testsuite/26_numerics/random/inequal.cc | 49 +++ > .../26_numerics/random/philox4x32.cc | 42 +++ > .../26_numerics/random/philox4x64.cc | 42 +++ > .../random/philox_engine/cons/119794.cc | 57 +++ > .../random/philox_engine/cons/copy.cc | 44 +++ > .../random/philox_engine/cons/default.cc | 46 +++ > .../random/philox_engine/cons/seed.cc | 39 ++ > .../random/philox_engine/cons/seed_seq.cc | 41 +++ > .../random/philox_engine/operators/equal.cc | 49 +++ > .../random/philox_engine/operators/inequal.cc | 49 +++ > .../philox_engine/operators/serialize.cc | 68 ++++ > .../philox_engine/requirements/constants.cc | 45 +++ > .../requirements/constexpr_data.cc | 69 ++++ > .../requirements/constexpr_functions.cc | 60 ++++ > .../philox_engine/requirements/typedefs.cc | 45 +++ > .../26_numerics/random/pr60037-neg.cc | 2 +- > 18 files changed, 1287 insertions(+), 1 deletion(-) > create mode 100644 libstdc++-v3/testsuite/26_numerics/random/inequal.cc > 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..5c675927515 100644 > --- a/libstdc++-v3/include/bits/random.h > +++ b/libstdc++-v3/include/bits/random.h > @@ -1688,6 +1688,328 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > { return !(__lhs == __rhs); } > #endif > > +#if __cplusplus > 202302L The implementation should more specifically be guarded by the corresponding feature-test macro __cpp_lib_philox_engine (defined to 202406L). The way this is done nowadays in libstdc++ is to add philox_engine to libstdc++-v3/include/bits/version.def and regenerate version.h via 'autogen version.def'. This will define the internal feature-test macro __glibcxx_philox_engine that we can check here. In include/std/random, we need to do #define __glibcxx_want_philox_engine #include <bits/version.def> so that the __cpp_lib_philox_engine is provided by that header. > + > + /** > + * @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)==1, Can you remove the ==1? > + "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. */ > + static constexpr > + std::array<_UIntType, __n / 2> > + __popMultArray() > + { > + if constexpr (__n == 4) > + { We typically elide the braces for single-statement if branches. > + return > + std::array<_UIntType, __n / 2> {__consts...[0], __consts...[2]}; > + } else > + { > + return std::array<_UIntType, __n / 2> { __consts...[0] }; > + } > + } > + > + /** @brief an internal unpacking function for %philox_engine. */ > + static constexpr > + std::array<_UIntType, __n / 2> > + __popConstArray() > + { > + if constexpr (__n == 4) > + { > + return > + std::array<_UIntType, __n / 2> {__consts...[1], __consts...[3]}; > + } else > + { > + return std::array<_UIntType, __n / 2> {__consts...[1] }; > + } > + } > + > + 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 std::array<result_type, __n / 2> multipliers = > + philox_engine::__popMultArray(); > + static constexpr std::array<result_type, __n / 2> round_consts = > + philox_engine::__popConstArray(); > + > + /** @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 std::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 > + { Please use parens here instead. It should be formatted as return (std::equal(...) && ... && __x._M_ == __y._M_i); > + std::equal(__x.__x.begin(), __x.__x.end(), > + __y.__x.begin(), __y.__x.end()) && > + std::equal(__x.__y.begin(), __x.__y.end(), > + __y.__y.begin(), __y.__y.end()) && > + std::equal(__x.__k.begin(), __x.__k.end(), > + __y.__k.begin(), __y.__k.end()) && > + __x.__i == __y.__i > + }; > + } > + > + > + _UIntType > + operator()(); > + > + /** @brief discards __z numbers > + * > + * @params __z number of iterations to discard > + */ > + void > + discard(unsigned long long __z); > + > + // Note: hidden friend seems best, suspect a better way of doing things > + // but unable to find it > + /** @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) > + { > + using __ios_base = > + typename basic_ostream<_charT, _traits>::ios_base; > + 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(' ')); > + auto __it = __x.__k.begin(); > + while (__it != __x.__k.end()) > + { > + __os << *__it << ' '; > + ++__it; > + } > + auto __it2 = __x.__x.begin(); > + while (__it2 != __x.__x.end()) > + { > + __os << *__it2 << ' '; > + ++__it2; > + } > + __os << __x.__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) > + { > + using __ios_base = > + typename basic_istream<_charT, _traits>::ios_base; > + const typename __ios_base::fmtflags __flags = __is.flags(); > + __is.flags(__ios_base::dec | __ios_base::skipws); > + for (size_t __j = 0; __j < __x.__k.size(); ++__j) > + { > + __is >> __x.__k[__j]; > + } > + for (size_t __j = 0; __j < __x.__x.size(); ++__j) > + { > + __is >> __x.__x[__j]; > + } > + std::array<_UIntType, __n> __tmpCtr = __x.__x; > + unsigned char __setIndex = 0; > + for (size_t __j = 0; __j < __x.__x.size(); ++__j) > + { > + if (__x.__x[__j] > 0) > + { > + __setIndex = __j; > + break; > + } > + } > + for (size_t __j = 0; __j <= __setIndex; ++__j) > + { > + if (__j != __setIndex) > + { > + __x.__x[__j] = max(); > + } else > + { > + --__x.__x[__j]; > + } > + } > + __x.__philox(); > + __x.__x = __tmpCtr; > + __is >> __x.__i; > + __is.flags(__flags); > + return __is; > + } > + private: > + // private state variables > + std::array<_UIntType, __n> __x; > + std::array<_UIntType, __n / 2> __k; > + std::array<_UIntType, __n> __y; > + unsigned long long __i = 0; In libstdc++, internal non-static data members are conventionally uglified as _M_foo. Internal static members are uglified as _S_foo. > + > + /** @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 > + */ > + _UIntType > + __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 > + */ > + _UIntType > + __mullo(_UIntType __a, _UIntType __b); // (A*B)%2^W > + > + /** @brief an R-round SP-net followed by a Feistel Network for > + * %philox_engine > + */ > + void > + __philox(); > + > + /** @brief an internal transition function for the %philox_engine. */ > + void > + __transition(); > + }; > + > + /** > + * Compares two %philox_engine random number generator objects > + * of the same type for inequality. > + * > + * @param __lhs A %philox_engine random number generator object. > + * @param __rhs Another %philox_engine random number generator > + * object. > + * > + * @returns true if the streams would be different, false otherwise. > + */ > + template<class _UIntType, size_t __w, > + size_t __n, size_t __r, > + _UIntType... __consts> > + inline bool > + operator!=(const std::philox_engine<_UIntType, __w, > + __n, __r, __consts...>& __lhs, > + const std::philox_engine<_UIntType, __w, > + __n, __r, __consts...>& __rhs) > + { return !(__lhs == __rhs); } > + > +#endif > + > /** > * The classic Minimum Standard rand0 of Lewis, Goodman, and Miller. > */ > @@ -1742,6 +2064,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > typedef minstd_rand0 default_random_engine; > > +#if __cplusplus > 202302L > + > + typedef philox_engine< > + uint_fast32_t, > + 32, 4, 10, > + 0xCD9E8D57, 0x9E3779B9, > + 0xD2511F53, 0xBB67AE85> philox4x32; > + > + /** > + * Alternative Philox instance (64 bit) > + */ > + typedef philox_engine< > + std::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..faba3b6d4b5 100644 > --- a/libstdc++-v3/include/bits/random.tcc > +++ b/libstdc++-v3/include/bits/random.tcc > @@ -518,6 +518,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > return __is; > } > > + > + > #if ! __cpp_inline_variables > template<typename _UIntType, size_t __w, size_t __s, size_t __r> > constexpr size_t > @@ -907,6 +909,205 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > return __is; > } > > +#if __cplusplus > 202302L > + > + template<class _UIntType, > + size_t __w, size_t __n, > + size_t __r, _UIntType... __consts> > + _UIntType > + std::philox_engine<_UIntType, I believe std:: prefix here is unnecessary since we're already inside the std namespace. Why are some member functions defined inline and some out-of-line? > + __w, __n, __r, __consts...>::__mulhi(_UIntType __a, _UIntType __b) > + { > + const __uint128_t __num = Since not all targets provide a 128-bit integer type, I think we need to disable philox_engine on targets lacking it. The easiest way would be to add __SIZEOF_INT128__ to extra_conds in the corresponding version.def entry. > + static_cast<__uint128_t>(__a) * static_cast<__uint128_t>(__b); > + const __uint128_t __div = (static_cast<__uint128_t>(1) << __w); > + return static_cast<_UIntType>((__num / __div) & this->max()); Can we just right-shift by __w instead of dividing by 1 << __w? > + } > + > + template<class _UIntType, > + size_t __w, size_t __n, > + size_t __r, _UIntType... __consts> > + _UIntType > + std::philox_engine<_UIntType, > + __w, __n, __r, __consts...>::__mullo(_UIntType __a, _UIntType __b) > + { > + return ((__a * __b) & max()); > + } > + > + template<class _UIntType, > + size_t __w, size_t __n, > + size_t __r, _UIntType... __consts> > + void > + std::philox_engine<_UIntType, __w, __n, __r, __consts...>::__transition() > + { > + ++__i; > + if (__i == __n) > + { > + __philox(); > + if (__n == 4) > + { > + __uint128_t __uh = > + { > + (static_cast<__uint128_t>(this->__x[1]) << __w) > + | ((this->__x[0]) + 1) > + }; > + __uint128_t __lh = > + { > + ((static_cast<__uint128_t>(this->__x[3]) << __w) > + | (this->__x[2])) > + }; > + if (!(__uh & this->max())) > + { > + ++__lh; > + __uh = 0; > + } > + this->__x[0] = __uh & this->max(); > + this->__x[1] = (__uh >> (__w)) & this->max(); > + this->__x[2] = __lh & this->max(); > + this->__x[3] = (__lh >> (__w)) & this->max(); > + } else > + { > + __uint128_t __num = ((this->__x[1] << __w)) | ((this->__x[0]) + 1); > + this->__x[0] = __num & this->max(); > + this->__x[1] = (__num >> __w) & this->max(); > + } > + __i = 0; > + } > + } > + > + template<class _UIntType, > + size_t __w, size_t __n, > + size_t __r, _UIntType... __consts> > + void > + std::philox_engine<_UIntType, __w, __n, __r, __consts...>::__philox() > + { > + std::array<_UIntType, __n> __outputSeq{}; > + for (size_t __j = 0; __j < __n; ++__j) > + { > + __outputSeq[__j] = __x[__j]; > + } > + for (unsigned long __j = 0; __j < __r; ++__j) > + { > + std::array<_UIntType, __n> __intermedSeq{}; > + if (__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]= __mulhi(__intermedSeq[2*__k], multipliers[__k]) > + ^ (((this->__k[__k] + (__j * round_consts[__k])) & this->max())) > + ^ __intermedSeq[2*__k+1]; > + > + __outputSeq[(2*__k)+1]= __mullo(__intermedSeq[2*__k], > + multipliers[__k]); > + } > + } > + for (unsigned long __j = 0; __j < __n; ++__j) > + { > + __y[__j] = __outputSeq[__j]; > + } > + } > + > + template<class _UIntType, > + size_t __w, size_t __n, > + size_t __r, _UIntType... __consts> > + std::philox_engine<_UIntType, > + __w, __n, __r, __consts...>::philox_engine(result_type __value) > + { > + std::fill(__x.begin(), __x.end(), 0); > + std::fill(__k.begin(), __k.end(), 0); > + std::fill(__y.begin(), __y.end(), 0); > + __k[0] = __value & this->max(); > + __i = __n - 1; > + } > + > + template<class _UIntType, > + size_t __w, size_t __n, > + size_t __r, _UIntType... __consts> > + void > + std::philox_engine<_UIntType, > + __w, __n, __r, __consts...>::seed(result_type __value) > + { > + std::fill(__x.begin(), __x.end(), 0); > + std::fill(__k.begin(), __k.end(), 0); > + std::fill(__y.begin(), __y.end(), 0); > + __k[0] = __value & this->max(); > + __i = __n - 1; > + } > + > + template<class _UIntType, > + size_t __w, size_t __n, > + size_t __r, _UIntType... __consts> > + void > + std::philox_engine<_UIntType, __w, > + __n, __r, __consts...>::set_counter(const array<result_type, __n>& > __counter) > + { > + for (unsigned long long __j = 0; __j < __n; ++__j) > + { > + __x[__j] = __counter[__n - 1 - __j] & this->max(); > + } > + __i = __n - 1; > + } > + > + template<class _UIntType, > + size_t __w, size_t __n, > + size_t __r, _UIntType... __consts> > + template<typename _Sseq> > + auto > + std::philox_engine<_UIntType, __w, __n, __r, __consts...>::seed(_Sseq& > __q) > + -> _If_seed_seq<_Sseq> > + { > + std::fill(__k.begin(), __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) - 1; ++__k) this->__k has n/2 elements, but this loop is up to n/2 - 1? > + { > + unsigned long long __precalc = 0; > + for (unsigned long long __j = 0; __j < __p; ++__j) > + { > + unsigned long long __multiplicand = (1ull << (32 * __j - 1)); I believe this left shift is UB when __j is zero (and so the shift amount is huge). > + __precalc += (__tmpArr[__k*__p + __j] * __multiplicand) & this->max(); > + } > + this->__k[__k] = __precalc; > + } > + std::fill(__x.begin(), __x.end(), 0); > + std::fill(__y.begin(), __y.begin(), 0); __y.begin(), __y.end() rather? > + __i = __n - 1; > + } > + > + template<class _UIntType, > + size_t __w, size_t __n, > + size_t __r, _UIntType... __consts> > + void > + std::philox_engine<_UIntType, > + __w, __n, __r, __consts...>::discard(unsigned long long __z) > + { > + for (unsigned long long __j = 0; __j < __z; ++__j) > + { > + __transition(); > + } > + } > + > + template<class _UIntType, > + size_t __w, size_t __n, > + size_t __r, _UIntType... __consts> > + _UIntType > + std::philox_engine<_UIntType, __w, __n, __r, __consts...>::operator()() > + { > + __transition(); > + return __y[__i]; > + } > + > +#endif > > template<typename _IntType, typename _CharT, typename _Traits> > std::basic_ostream<_CharT, _Traits>& > diff --git a/libstdc++-v3/testsuite/26_numerics/random/inequal.cc > b/libstdc++-v3/testsuite/26_numerics/random/inequal.cc > new file mode 100644 > index 00000000000..081c908a3eb > --- /dev/null > +++ b/libstdc++-v3/testsuite/26_numerics/random/inequal.cc > @@ -0,0 +1,49 @@ > +// { dg-do run { target c++26 } } > +// { dg-require-cstdint "" } > +// > +// 2025-04-09 1nfocalypse <1nfocaly...@protonmail.com> > +// > +// Copyright (C) 2025-2034 Free Software Foundation, Inc. > +// > +// This file is part of the GNU ISO C++ Library. This library is free > +// software; you can redistribute it and/or modify it under the > +// terms of the GNU General Public License as published by the > +// Free Software Foundation; either version 3, or (at your option) > +// any later version. > +// > +// This library is distributed in the hope that it will be useful, > +// but WITHOUT ANY WARRANTY; without even the implied warranty of > +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +// GNU General Public License for more details. > +// > +// You should have received a copy of the GNU General Public License along > +// with this library; see the file COPYING3. If not see > +// https://www.gnu.org/licenses> Nowadays we don't add license headers to tests. > + > +// 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/philox4x32.cc > b/libstdc++-v3/testsuite/26_numerics/random/philox4x32.cc > new file mode 100644 > index 00000000000..67fd8455f51 > --- /dev/null > +++ b/libstdc++-v3/testsuite/26_numerics/random/philox4x32.cc > @@ -0,0 +1,42 @@ > +// { dg-do run { target c++26 } } > +// { dg-require-cstdint "" } > +// > +// 2025-04-09 1nfocalypse <1nfocaly...@protonmail.com> > +// > +// Copyright (C) 2025 Free Software Foundation, Inc. > +// > +// This file is part of the GNU ISO C++ Library. This library is free > +// software; you can redistribute it and/or modify it under the > +// terms of the GNU General Public License as published by the > +// Free Software Foundation; either version 3, or (at your option) > +// any later version. > +// > +// This library is distributed in the hope that it will be useful, > +// but WITHOUT ANY WARRANTY; without even the implied warranty of > +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +// GNU General Public License for more details. > +// > +// You should have received a copy of the GNU General Public License along > +// with this library; see the file COPYING3. If not see > +// https://www.gnu.org/licenses> > + > +// 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..9eb1722f2da > --- /dev/null > +++ b/libstdc++-v3/testsuite/26_numerics/random/philox4x64.cc > @@ -0,0 +1,42 @@ > +// { dg-do run { target c++26 } } > +// { dg-require-cstdint "" } > +// > +// 2025-04-09 1nfocalypse <1nfocaly...@protonmail.com> > +// > +// Copyright (C) 2025 Free Software Foundation, Inc. > +// > +// This file is part of the GNU ISO C++ Library. This library is free > +// software; you can redistribute it and/or modify it under the > +// terms of the GNU General Public License as published by the > +// Free Software Foundation; either version 3, or (at your option) > +// any later version. > +// > +// This library is distributed in the hope that it will be useful, > +// but WITHOUT ANY WARRANTY; without even the implied warranty of > +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +// GNU General Public License for more details. > +// > +// You should have received a copy of the GNU General Public License along > +// with this library; see the file COPYING3. If not see > +// https://www.gnu.org/licenses> > + > +// 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..2884d6e3117 > --- /dev/null > +++ b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/119794.cc > @@ -0,0 +1,57 @@ > +// { dg-do run { target c++26 } } > +// { dg-require-cstdint "" } > +// > +// Copyright (C) 2025 Free Software Foundation, Inc. > +// > +// This file is part of the GNU ISO C++ Library. This library is free > +// software; you can redistribute it and/or modify it under the > +// terms of the GNU General Public License as published by the > +// Free Software Foundation; either version 3, or (at your option) > +// any later version. > +// > +// This library is distributed in the hope that it will be useful, > +// but WITHOUT ANY WARRANTY; without even the implied warranty of > +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +// GNU General Public License for more details. > +// > +// You should have received a copy of the GNU General Public License along > +// with this library; see the file COPYING3. If not see > +// <http://www.gnu.org/licenses/>. > + > + > +#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..64b96a91559 > --- /dev/null > +++ b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/copy.cc > @@ -0,0 +1,44 @@ > +// { dg-do run { target c++26 } } > +// { dg-require-cstdint "" } > +// > +// 2025-04-09 1nfocalypse <1nfocaly...@protonmail.com> > +// > +// Copyright (C) 2025 Free Software Foundation, Inc. > +// > +// This file is part of the GNU ISO C++ Library. This library is free > +// software; you can redistribute it and/or modify it under the > +// terms of the GNU General Public License as published by the > +// Free Software Foundation; either version 3, or (at your option) > +// any later version. > +// > +// This library is distributed in the hope that it will be useful, > +// but WITHOUT ANY WARRANTY; without even the implied warranty of > +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +// GNU General Public License for more details. > +// > +// You should have received a copy of the GNU General Public License along > +// with this library; see the file COPYING3. If not see > +// https://www.gnu.org/licenses> > + > +// 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..1bdee6e7911 > --- /dev/null > +++ b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/default.cc > @@ -0,0 +1,46 @@ > +// { dg-do run { target c++26 } } > +// { dg-require-cstdint "" } > +// > +// 2025-04-09 1nfocalypse <1nfocaly...@protonmail.com> > +// > +// Copyright (C) 2025-2034 Free Software Foundation, Inc. > +// > +// This file is part of the GNU ISO C++ Library. This library is free > +// software; you can redistribute it and/or modify it under the > +// terms of the GNU General Public License as published by the > +// Free Software Foundation; either version 3, or (at your option) > +// any later version. > +// > +// This library is distributed in the hope that it will be useful, > +// but WITHOUT ANY WARRANTY; without even the implied warranty of > +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +// GNU General Public License for more details. > +// > +// You should have received a copy of the GNU General Public License along > +// with this library; see the file COPYING3. If not see > +// https://www.gnu.org/licenses> > + > +// 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..91ef286e5e1 > --- /dev/null > +++ b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/seed.cc > @@ -0,0 +1,39 @@ > +// { dg-do run { target c++26 } } > +// { dg-require-cstdint "" } > +// > +// 2025 1nfocalypse <1nfocaly...@protonmail.com> > +// > +// Copyright (C) 2025 Free Software Foundation, Inc. > +// > +// This file is part of the GNU ISO C++ Library. This library is free > +// software; you can redistribute it and/or modify it under the > +// terms of the GNU General Public License as published by the > +// Free Software Foundation; either version 3, or (at your option) > +// any later version. > +// > +// This library is distributed in the hope that it will be useful, > +// but WITHOUT ANY WARRANTY; without even the implied warranty of > +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +// GNU General Public License for more details. > +// > +// You should have received a copy of the GNU General Public License along > +// with this library; see the file COPYING3. If not see > +// <http://www.gnu.org/licenses/>. > + > +#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..d35ce5fa05b > --- /dev/null > +++ > b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/seed_seq.cc > @@ -0,0 +1,41 @@ > +// { dg-do run { target c++26 } } > +// { dg-require-cstdint "" } > +// > +// 2025-04-09 1nfocalypse <1nfocaly...@protonmail.com> > +// > +// Copyright (C) 2025-2034 Free Software Foundation, Inc. > +// > +// This file is part of the GNU ISO C++ Library. This library is free > +// software; you can redistribute it and/or modify it under the > +// terms of the GNU General Public License as published by the > +// Free Software Foundation; either version 3, or (at your option) > +// any later version. > +// > +// This library is distributed in the hope that it will be useful, > +// but WITHOUT ANY WARRANTY; without even the implied warranty of > +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +// GNU General Public License for more details. > +// > +// You should have received a copy of the GNU General Public License along > +// with this library; see the file COPYING3. If not see > +// https://www.gnu.org/licenses> > + > +// 29.5.4 Random Number Engine Class Templates > +// 29.5.4.5 Class Template philox_engine > + > +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..17cc2216791 > --- /dev/null > +++ > b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/operators/equal.cc > @@ -0,0 +1,49 @@ > +// { dg-do run { target c++26 } } > +// { dg-require-cstdint "" } > +// > +// 2025-04-09 1nfocalypse <1nfocaly...@protonmail.com> > +// > +// Copyright (C) 2025-2034 Free Software Foundation, Inc. > +// > +// This file is part of the GNU ISO C++ Library. This library is free > +// software; you can redistribute it and/or modify it under the > +// terms of the GNU General Public License as published by the > +// Free Software Foundation; either version 3, or (at your option) > +// any later version. > +// > +// This library is distributed in the hope that it will be useful, > +// but WITHOUT ANY WARRANTY; without even the implied warranty of > +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +// GNU General Public License for more details. > +// > +// You should have received a copy of the GNU General Public License along > +// with this library; see the file COPYING3. If not see > +// https://www.gnu.org/licenses> > + > +// 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..c8255249ed8 > --- /dev/null > +++ > b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/operators/inequal.cc > @@ -0,0 +1,49 @@ > +// { dg-do run { target c++26 } } > +// { dg-require-cstdint "" } > +// > +// 2025-04-09 1nfocalypse <1nfocaly...@protonmail.com> > +// > +// Copyright (C) 2025-2034 Free Software Foundation, Inc. > +// > +// This file is part of the GNU ISO C++ Library. This library is free > +// software; you can redistribute it and/or modify it under the > +// terms of the GNU General Public License as published by the > +// Free Software Foundation; either version 3, or (at your option) > +// any later version. > +// > +// This library is distributed in the hope that it will be useful, > +// but WITHOUT ANY WARRANTY; without even the implied warranty of > +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +// GNU General Public License for more details. > +// > +// You should have received a copy of the GNU General Public License along > +// with this library; see the file COPYING3. If not see > +// https://www.gnu.org/licenses> > + > +// 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..f3672f956b9 > --- /dev/null > +++ > b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/operators/serialize.cc > @@ -0,0 +1,68 @@ > +// { dg-do run { target c++26 } } > +// { dg-require-cstdint "" } > +// > +// 2025-04-09 1nfocalypse <1nfocaly...@protonmail.com> > +// > +// Copyright (C) 2025-2034 Free Software Foundation, Inc. > +// > +// This file is part of the GNU ISO C++ Library. This library is free > +// software; you can redistribute it and/or modify it under the > +// terms of the GNU General Public License as published by the > +// Free Software Foundation; either version 3, or (at your option) > +// any later version. > +// > +// This library is distributed in the hope that it will be useful, > +// but WITHOUT ANY WARRANTY; without even the implied warranty of > +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +// GNU General Public License for more details. > +// > +// You should have received a copy of the GNU General Public License along > +// with this library; see the file COPYING3. If not see > +// https://www.gnu.org/licenses> > + > +// 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..80579f4cf91 > --- /dev/null > +++ > b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/requirements/constants.cc > @@ -0,0 +1,45 @@ > +// { dg-do run { target c++26 } } > +// { dg-require-cstdint "" } > +// > +// 2025-04-09 1nfocalypse <1nfocaly...@protonmail.com> > +// > +// Copyright (C) 2025-2034 Free Software Foundation, Inc. > +// > +// This file is part of the GNU ISO C++ Library. This library is free > +// software; you can redistribute it and/or modify it under the > +// terms of the GNU General Public License as published by the > +// Free Software Foundation; either version 3, or (at your option) > +// any later version. > +// > +// This library is distributed in the hope that it will be useful, > +// but WITHOUT ANY WARRANTY; without even the implied warranty of > +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +// GNU General Public License for more details. > +// > +// You should have received a copy of the GNU General Public License along > +// with this library; see the file COPYING3. If not see > +// https://www.gnu.org/licenses> > + > +// 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; 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..6832f17c833 > --- /dev/null > +++ > b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/requirements/constexpr_data.cc > @@ -0,0 +1,69 @@ > +// { dg-do run { target c++26 } } > +// { dg-require-cstdint "" } > +// > +// 2025-04-09 1nfocalypse <1nfocaly...@protonmail.com> > +// > +// Copyright (C) 2025-2034 Free Software Foundation, Inc. > +// > +// This file is part of the GNU ISO C++ Library. This library is free > +// software; you can redistribute it and/or modify it under the > +// terms of the GNU General Public License as published by the > +// Free Software Foundation; either version 3, or (at your option) > +// any later version. > +// > +// This library is distributed in the hope that it will be useful, > +// but WITHOUT ANY WARRANTY; without even the implied warranty of > +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +// GNU General Public License for more details. > +// > +// You should have received a copy of the GNU General Public License along > +// with this library; see the file COPYING3. If not see > +// https://www.gnu.org/licenses> > + > +// 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..6209573a211 > --- /dev/null > +++ > b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/requirements/constexpr_functions.cc > @@ -0,0 +1,60 @@ > +// { dg-do run { target c++26 } } > +// { dg-require-cstdint "" } > +// > +// 2025-04-09 1nfocalypse <1nfocaly...@protonmail.com> > +// > +// Copyright (C) 2025-2034 Free Software Foundation, Inc. > +// > +// This file is part of the GNU ISO C++ Library. This library is free > +// software; you can redistribute it and/or modify it under the > +// terms of the GNU General Public License as published by the > +// Free Software Foundation; either version 3, or (at your option) > +// any later version. > +// > +// This library is distributed in the hope that it will be useful, > +// but WITHOUT ANY WARRANTY; without even the implied warranty of > +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +// GNU General Public License for more details. > +// > +// You should have received a copy of the GNU General Public License along > +// with this library; see the file COPYING3. If not see > +// https://www.gnu.org/licenses> > + > +// 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..ff4d357c5a2 > --- /dev/null > +++ > b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/requirements/typedefs.cc > @@ -0,0 +1,45 @@ > +// { dg-do run { target c++26 } } > +// { dg-require-cstdint "" } > +// > +// 2025-04-09 1nfocalypse <1nfocaly...@protonmail.com> > +// > +// Copyright (C) 2025-2034 Free Software Foundation, Inc. > +// > +// This file is part of the GNU ISO C++ Library. This library is free > +// software; you can redistribute it and/or modify it under the > +// terms of the GNU General Public License as published by the > +// Free Software Foundation; either version 3, or (at your option) > +// any later version. > +// > +// This library is distributed in the hope that it will be useful, > +// but WITHOUT ANY WARRANTY; without even the implied warranty of > +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +// GNU General Public License for more details. > +// > +// You should have received a copy of the GNU General Public License along > +// with this library; see the file COPYING3. If not see > +// https://www.gnu.org/licenses> > + > +// 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..5bb3f31eddc 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 *-*-* } 270 } > > -// { 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 *-*-* } 3558 } > -- > 2.49.0 >