Good evening,

Thanks for the feedback! I'll get a v4 done with the following changes:
- charT, traits capitalization
- remove accidental whitespace changes
- remove unnecessary this->/{}
- redundant parens - I suspect you're correct, I will validate and make the 
change accordingly. If it persists, I will note it.
- rm copyright header
- std:: qualification on functions

Regarding calling std::fill fully qualified - I wanted to confirm that this is 
specifically for functions? From jwakely's feedback on v2:

"The "std::" on std::array is not needed. The surrounding code in
<random> is a bit inconsistent about this, but that's because it was
ported from <tr1/random> where everything was in namespace std::tr1
and so the std:: qualification made it clear where things came from.
For <random> which is all in std, we don't need that. Especially not
in new code."

It makes sense to do this for functions given the concern about ADL; I just 
want to be sure I'm meeting the intended convention. Thanks in advance!

Lastly, a brief note on NumPy's Philox4x32-10 implementation. According to 
NumPy's documentation:
https://numpy.org/doc/stable/reference/random/bit_generators/philox.html

A seed comprised of an int or an array-like structure of ints is in turn passed 
to a seed sequence for derivation of the original seed. 
Conversely, the defined behavior of Philox Engine's default constructor is to 
set K_{0} := x mod 2^{w} = 20111115 
(https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2075r6.pdf). 
Additionally, within the errata for Philox Engine 
(https://cplusplus.github.io/LWG/issue4134), the test vectors are listed as:
- 1955073260 (Philox4x32-10) 
- 3409172418970261260 (Philox4x64-10) 
with the default-constructed instance, which these tests assert.

Previously, I also confirmed this implementation's behavior with a selection of 
test vectors from the Random123 reference library:
https://github.com/DEShawResearch/random123/blob/main/tests/kat_vectors

as well as independently confirmed the WG21 test vectors using the reference 
library.

Thank you once again for the review, and I'll have a v4 together shortly with 
the changes.



On Friday, July 18th, 2025 at 12:34 PM, Patrick Palka <ppa...@redhat.com> wrote:

> On Fri, 18 Jul 2025, 1nfocalypse wrote:
> 
> > Implements Philox Engine (P2075R6) and associated tests.
> > 
> > Additionally implements changes based on feedback from Patrick
> > Palka and jwakely on v2.
> > 
> > Regarding the question posed by Patrick on why some things are
> > defined inline and some out of line, things were either defined inline
> > either due to being concise (i.e. max()), to keep parity with other
> > generators (equality operator overload), or for functionality
> > (istream/ostream operators). I particularly attempted defining the
> > stream operators out of line because they are fairly obtrusive, however,
> > I couldn't get functionality out of them out of line. I am happy to revisit 
> > this
> > if needed.
> 
> 
> Yep, such hidden friends must be defined inside the class body.
> 
> > Of further note, altering version.def via autogen led to a line
> > in excess of 80 chars. Since it was the result of autogen, I let it lie. If 
> > this
> > was incorrect, I can adjust it.
> 
> 
> That's fine, we don't care about line lengths of autogenerated files.
> 
> > Otherwise, thank you for the review, and please let me know if further
> > alterations are needed.
> 
> 
> Nice, thanks! A couple of more review comments added inline.
> 
> > Built/tested on x86_64-linux-gnu.
> > 
> > Subject: [PATCH] [PATCH v3] libstdc++: implement Philox Engine [PR119794]
> > 
> > Implemented changes according to feedback from Patrick Palka
> > and jwakely.
> > 
> > Swapped out C++ version macro check for feature-check macro
> > (__glibcxx_philox_engine).
> > Modified version.def to support Philox Engine, and restricted
> > architectures to those supporting __uint128_t.
> > Implements LGW4143, LWG4153 errata for Philox Engine.
> > Convoluted ios_base reference simplified.
> > Template unpacking functions refactored into one.
> > Uglified internal members in accordance with style.
> > Utilized parens in equivalence operator overload.
> > Fixed improper test call in constants.cc
> > Removed license headers to comply with current test style guide.
> > Fixed errors in seed function with sseq argument,
> > - off by one error
> > - incorrect number
> > Removed extraneous == 1 from static_assert
> > Braces omitted for single line if statements.
> 
> 
> FWIW you can also omit braces for single-line while/for loops etc as per
> our coding style.
> 
> > Removed extraneous std:: qualifiers.
> > Optimized to rshift instead of division in mulhi.
> > Corrected iterator arguments.
> > Removed redundant neq overload.
> > Fixed incorrect copyright statement (covered by removal).
> > 
> > Additionally altered PR60037-neg.cc to correctly suppress
> > error (changed line number to remain correct).
> > 
> > PR libstdc++/119794
> > ---
> > libstdc++-v3/include/bits/random.h | 299 ++++++++++++++++++
> > libstdc++-v3/include/bits/random.tcc | 200 ++++++++++++
> > libstdc++-v3/include/bits/version.def | 9 +
> > libstdc++-v3/include/bits/version.h | 10 +
> > libstdc++-v3/include/std/random | 4 +
> > .../testsuite/26_numerics/random/inequal.cc | 49 +++
> > .../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 | 22 ++
> > .../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 | 2 +-
> > 21 files changed, 1003 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..182dcc45eb6 100644
> > --- a/libstdc++-v3/include/bits/random.h
> > +++ b/libstdc++-v3/include/bits/random.h
> > @@ -1688,6 +1688,286 @@ _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 (equal(__x._M_x.begin(), __x._M_x.end(),
> > + __y._M_x.begin(), __y._M_x.end())
> > + && equal(__x._M_y.begin(), __x._M_y.end(),
> > + __y._M_y.begin(), __y._M_y.end())
> > + && 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>
> 
> 
> Uppercase '_CharT', '_Traits'
> 
> > + friend basic_ostream<_charT, _traits>&
> > + operator<<(basic_ostream<_charT, _traits>& __os,
> > + const philox_engine& __x)
> > + {
> > + using __ios_base = 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._M_k.begin();
> > + while (__it != __x._M_k.end())
> > + {
> > + __os << __it << ' ';
> > + ++__it;
> > + }
> > + auto __it2 = __x._M_x.begin();
> > + while (__it2 != __x._M_x.end())
> > + {
> > + __os << __it2 << ' ';
> > + ++__it2;
> > + }
> > + __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>
> 
> 
> Same
> 
> > + friend basic_istream<_charT, _traits>&
> > + operator>>(basic_istream<_charT, _traits>& __is,
> > + philox_engine& __x)
> > + {
> > + using __ios_base = 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._M_k.size(); ++__j)
> > + {
> > + __is >> __x._M_k[__j];
> > + }
> > + for (size_t __j = 0; __j < __x._M_x.size(); ++__j)
> > + {
> > + __is >> __x._M_x[__j];
> > + }
> > + 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
> > + /
> > + _UIntType
> > + _M_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
> > + /
> > + _UIntType
> > + _M_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 +2022,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> > 
> > typedef minstd_rand0 default_random_engine;
> > 
> > +// replace w/ appropriate feature guard, not version guard
> > +#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..d1b1c6abff6 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;
> > }
> > 
> > +
> > +
> 
> 
> Accidental whitespace change?
> 
> > #if ! __cpp_inline_variables
> > template<typename _UIntType, size_t __w, size_t __s, size_t __r>
> > constexpr size_t
> > @@ -907,6 +909,204 @@ _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...>::_M_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) & this->max());
> > + }
> > +
> > + template<class _UIntType,
> > + size_t __w, size_t __n,
> > + size_t __r, _UIntType... __consts>
> > + _UIntType
> > + philox_engine<_UIntType,
> > + __w, __n, __r, __consts...>::_M_mullo(_UIntType __a, _UIntType __b)
> > + {
> > + return ((__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 (__n == 4)
> > + {
> > + __uint128_t __uh =
> > + {
> > + (static_cast<__uint128_t>(this->_M_x[1]) << __w)
> > + | ((this->_M_x[0]) + 1)
> 
> 
> Can you remove the unnecessary this-> qualifier and the
> 
> outer {}?
> 
> > + };
> > + __uint128_t __lh =
> > + {
> > + ((static_cast<__uint128_t>(this->_M_x[3]) << __w)
> > + | (this->_M_x[2]))
> > + };
> > + if (!(__uh & this->max()))
> > + {
> > + ++__lh;
> > + __uh = 0;
> > + }
> > + this->_M_x[0] = __uh & this->max();
> > + this->_M_x[1] = (__uh >> (__w)) & this->max();
> > + this->_M_x[2] = __lh & this->max();
> > + this->_M_x[3] = (__lh >> (__w)) & this->max();
> > + } else
> > + {
> > + __uint128_t __num = ((this->_M_x[1] << __w)) | ((this->_M_x[0]) + 1);
> > + this->_M_x[0] = __num & this->max();
> > + this->_M_x[1] = (__num >> __w) & this->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 (__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]= _M_mulhi(__intermedSeq[2*__k], multipliers[__k])
> > + ^ (((this->_M_k[__k] + (__j * round_consts[__k])) & this->max()))
> > + ^ __intermedSeq[2*__k+1];
> > +
> > + __outputSeq[(2*__k)+1]= _M_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)
> > + {
> > + fill(_M_x.begin(), _M_x.end(), 0);
> 
> 
> Can you please call std::fill fully qualified, as well as other
> namespace-scope std functions, so that we don't have to worry/wonder
> about unintentional ADL?
> 
> > + fill(_M_k.begin(), _M_k.end(), 0);
> > + fill(_M_y.begin(), _M_y.end(), 0);
> > + _M_k[0] = __value & this->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)
> > + {
> > + fill(_M_x.begin(), _M_x.end(), 0);
> > + fill(_M_k.begin(), _M_k.end(), 0);
> > + fill(_M_y.begin(), _M_y.end(), 0);
> > + _M_k[0] = __value & this->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] & this->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>
> > + {
> > + fill(_M_k.begin(), _M_k.end(), 0);
> > + const unsigned long long __p = 1 + ((__w - 1/ 32));
> 
> 
> The redundant parens seems suspicious, should this be (__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) & this->max();
> > + }
> > + this->_M_k[__k] = __precalc;
> > + }
> > + fill(_M_x.begin(), _M_x.end(), 0);
> > + 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 cf0672b4822..32eedb89bcf 100644
> > --- a/libstdc++-v3/include/bits/version.def
> > +++ b/libstdc++-v3/include/bits/version.def
> > @@ -2059,6 +2059,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 c01ddf14dd5..f90280b4dce 100644
> > --- a/libstdc++-v3/include/bits/version.h
> > +++ b/libstdc++-v3/include/bits/version.h
> > @@ -2309,4 +2309,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..4e2915c9d9a 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>
> > @@ -51,6 +54,7 @@
> > #include <bits/opt_random.h>
> > #include <bits/random.tcc>
> > 
> > +
> 
> 
> Another accidentaly whitespace change.
> 
> > #endif // C++11
> > 
> > #endif // _GLIBCXX_RANDOM
> > 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..c8974449675
> > --- /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>
> > +
> > +// 29.5.4 Random Number Engine Class Templates
> > +// 29.5.4.5 Class Template philox_engine
> > +
> 
> 
> Can you remove this copyright header too?
> 
> > +#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..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 );
> 
> 
> I naively tried verifying this result against numpy's philox4x32 impl, but I'm
> getting a different answer:
> 
> $ cat philox.py
> import numpy as np
> 
> bit_generator = np.random.Philox(seed=20111115)
> rng = np.random.Generator(bit_generator)
> 
> num_sequence = rng.integers(
> low=0,
> high=2**32,
> size=10000,
> dtype=np.uint32
> )
> 
> print(num_sequence[-1])
> 
> $ python philox.py
> 3330218339
> 
> > +}
> > +
> > +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..033667616f9
> > --- /dev/null
> > +++ 
> > b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/seed_seq.cc
> > @@ -0,0 +1,22 @@
> > +// { 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
> > +
> > +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..649e7020c86 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 --* } 3557 }
> > --
> > 2.49.0

Reply via email to