#define _RANDOM_H 1
#include <vector>
+#include <bits/ios_base.h>
#include <bits/uniform_int_dist.h>
-#include <iomanip>
namespace std _GLIBCXX_VISIBILITY(default)
{
{ return !(__lhs == __rhs); }
#endif
-#if __cpp_lib_philox_engine
-
+#if __glibcxx_philox_engine // >= C++26
/**
- * @brief: A discrete pseudorandom number generator based off of weakened
- * cryptographic primitives.
+ * @brief A discrete pseudorandom number generator with weak cryptographic
+ * properties
+ *
+ * This algorithm was designed to be used for highly parallel random number
+ * generation, and is capable of immensely long periods. It provides
+ * "Crush-resistance", denoting an ability to pass the TestU01 Suite's
+ * "Big Crush" test, demonstrating significant apparent entropy.
*
- * This algorithm was intended to be used for highly parallel random number
- * generation, and is capable of immensely long periods. It provides "Crush-
- * resistance", denoting an ability to pass the TestU01 Suite's "Big Crush"
- * test, demonstrating significant apparent entropy. It is not intended for
- * cryptographic use and should not be used for such, despite being based on
- * cryptographic primitives.
+ * It is not intended for cryptographic use and should not be used for such,
+ * despite being based on cryptographic primitives.
*
- * The two four-word definitions are likely the best use for this algorithm,
- * and are given below as defaults.
+ * The typedefs `philox4x32` and `philox4x64` are provided as suitable
+ * defaults for most use cases, providing high-quality random numbers
+ * with reasonable performance.
*
* This algorithm was created by John Salmon, Mark Moraes, Ron Dror, and
* David Shaw as a product of D.E. Shaw Research.
* @headerfile random
* @since C++26
*/
- template<class _UIntType, size_t __w,
- size_t __n, size_t __r,
- _UIntType... __consts>
+ template<typename _UIntType, size_t __w, size_t __n, size_t __r,
+ _UIntType... __consts>
class philox_engine
{
static_assert(__n == 2 || __n == 4,
static_assert(0 < __r, "a number of rounds must be specified");
static_assert((0 < __w && __w <= numeric_limits<_UIntType>::digits),
"specified bitlength must match input type");
+
template<typename _Sseq>
- using _If_seed_seq
- = __detail::_If_seed_seq_for<_Sseq, philox_engine, _UIntType>;
+ static constexpr bool __is_seed_seq = requires {
+ typename __detail::_If_seed_seq_for<_Sseq, philox_engine, _UIntType>;
+ };
- private:
- // the ordering here is essential to functionality.
- /** @brief an internal unpacking function for %philox_engine. */
- template <size_t __ind0, size_t __ind1>
- static constexpr
- array<_UIntType, __n / 2>
- _S_popArray()
- {
- if constexpr (__n == 4)
- return {__consts...[__ind0], __consts...[__ind1]};
- else
- return {__consts...[__ind0]};
- }
+ template <size_t __ind0, size_t __ind1>
+ static constexpr
+ array<_UIntType, __n / 2>
+ _S_popArray()
+ {
+ if constexpr (__n == 4)
+ return {__consts...[__ind0], __consts...[__ind1]};
+ else
+ return {__consts...[__ind0]};
+ }
public:
- /** Type of template param. */
using result_type = _UIntType;
// public members
static constexpr size_t word_size = __w;
static constexpr size_t word_count = __n;
static constexpr size_t round_count = __r;
- static constexpr array<result_type, __n / 2> multipliers =
- philox_engine::_S_popArray<0,2>();
- static constexpr array<result_type, __n / 2> round_consts =
- philox_engine::_S_popArray<1,3>();
+ static constexpr array<result_type, __n / 2> multipliers
+ = _S_popArray<0,2>();
+ static constexpr array<result_type, __n / 2> round_consts
+ = _S_popArray<1,3>();
- /** @brief returns the minimum value possible. */
+ /// The minimum value that this engine can return
static constexpr result_type
min()
{ return 0; }
- /** @brief returns the maximum value possible. */
+ /// The maximum value that this engine can return
static constexpr result_type
max()
{
// constructors
philox_engine()
: philox_engine(default_seed)
- {}
+ { }
explicit
- philox_engine(result_type __value);
+ philox_engine(result_type __value)
+ : _M_x{}, _M_y{}, _M_k{}, _M_i(__n - 1)
+ { _M_k[0] = __value & max(); }
/** @brief seed sequence constructor for %philox_engine
*
- * @params __q the seed sequence
+ * @param __q the seed sequence
*/
- template<typename _Sseq, typename = _If_seed_seq<_Sseq>>
+ template<typename _Sseq> requires __is_seed_seq<_Sseq>
explicit
philox_engine(_Sseq& __q)
{
}
void
- seed(result_type value = default_seed);
+ seed(result_type __value = default_seed)
+ {
+ _M_x = {};
+ _M_y = {};
+ _M_k = {};
+ _M_k[0] = __value & max();
+ _M_i = __n - 1;
+ }
/** @brief seeds %philox_engine by seed sequence
*
- * @params __q the seed sequence
+ * @param __q the seed sequence
*/
template<typename _Sseq>
- _If_seed_seq<_Sseq>
- seed(_Sseq& __q);
+ void
+ seed(_Sseq& __q) requires __is_seed_seq<_Sseq>;
/** @brief sets the internal counter "cleartext"
*
- * @params __counter std::array of len N
+ * @param __counter std::array of len N
*/
void
- set_counter(const array<result_type, __n>& __counter);
+ set_counter(const array<result_type, __n>& __counter)
+ {
+ for (size_t __j = 0; __j < __n; ++__j)
+ _M_x[__j] = __counter[__n - 1 - __j] & max();
+ _M_i = __n - 1;
+ }
/** @brief compares two %philox_engine objects
*
- * @params __x A %philox_engine object
- * @params __y A %philox_engine object
- *
- * @returns true if the objects will produce an identical stream, false
- * otherwise
+ * @returns true if the objects will produce an identical stream,
+ * false otherwise
*/
friend bool
- operator==(const philox_engine& __x, const philox_engine& __y)
- {
- return (std::equal(__x._M_x.begin(), __x._M_x.end(),
- __y._M_x.begin(), __y._M_x.end())
- && std::equal(__x._M_y.begin(), __x._M_y.end(),
- __y._M_y.begin(), __y._M_y.end())
- && std::equal(__x._M_k.begin(), __x._M_k.end(),
- __y._M_k.begin(), __y._M_k.end())
- && __x._M_i == __y._M_i);
- }
+ operator==(const philox_engine&, const philox_engine&) = default;
/** @brief outputs a single w-bit number and handles state advancement
*
* @returns return_type
*/
- _UIntType
- operator()();
+ result_type
+ operator()()
+ {
+ _M_transition();
+ return _M_y[_M_i];
+ }
/** @brief discards __z numbers
*
- * @params __z number of iterations to discard
+ * @param __z number of iterations to discard
*/
void
- discard(unsigned long long __z);
+ discard(unsigned long long __z)
+ {
+ while (__z--)
+ _M_transition();
+ }
/** @brief outputs the state of the generator
*
*/
template<typename _CharT, typename _Traits>
friend basic_ostream<_CharT, _Traits>&
- operator<<(basic_ostream<_CharT, _Traits>& __os,
- const philox_engine& __x)
- {
- const typename ios_base::fmtflags __flags = __os.flags();
- const _CharT __fill = __os.fill();
- __os.flags(ios_base::dec | ios_base::left);
- __os.fill(__os.widen(' '));
- for (auto &__subkey : __x._M_k)
- __os << __subkey << ' ';
- for (auto &__ctr : __x._M_x)
- __os << __ctr << ' ';
- __os << __x._M_i;
- __os.flags(__flags);
- __os.fill(__fill);
- return __os;
- }
+ operator<<(basic_ostream<_CharT, _Traits>& __os,
+ const philox_engine& __x)
+ {
+ const typename ios_base::fmtflags __flags = __os.flags();
+ const _CharT __fill = __os.fill();
+ __os.flags(ios_base::dec | ios_base::left);
+ _CharT __space = __os.widen(' ');
+ __os.fill(__space);
+ for (auto& __subkey : __x._M_k)
+ __os << __subkey << __space;
+ for (auto& __ctr : __x._M_x)
+ __os << __ctr << __space;
+ __os << __x._M_i;
+ __os.flags(__flags);
+ __os.fill(__fill);
+ return __os;
+ }
/** @brief takes input to set the state of the %philox_engine object
*
*/
template <typename _CharT, typename _Traits>
friend basic_istream<_CharT, _Traits>&
- operator>>(basic_istream<_CharT, _Traits>& __is,
- philox_engine& __x)
+ operator>>(basic_istream<_CharT, _Traits>& __is,
+ philox_engine& __x)
+ {
+ const typename ios_base::fmtflags __flags = __is.flags();
+ __is.flags(ios_base::dec | ios_base::skipws);
+ for (auto& __subkey : __x._M_k)
+ __is >> __subkey;
+ for (auto& __ctr : __x._M_x)
+ __is >> __ctr;
+ array<_UIntType, __n> __tmpCtr = __x._M_x;
+ unsigned char __setIndex = 0;
+ for (size_t __j = 0; __j < __x._M_x.size(); ++__j)
{
- const typename ios_base::fmtflags __flags = __is.flags();
- __is.flags(ios_base::dec | ios_base::skipws);
- for (auto &__subkey : __x._M_k)
- __is >> __subkey;
- for (auto &__ctr : __x._M_x)
- __is >> __ctr;
- array<_UIntType, __n> __tmpCtr = __x._M_x;
- unsigned char __setIndex = 0;
- for (size_t __j = 0; __j < __x._M_x.size(); ++__j)
- {
- if (__x._M_x[__j] > 0)
+ if (__x._M_x[__j] > 0)
{
__setIndex = __j;
break;
}
- }
- for (size_t __j = 0; __j <= __setIndex; ++__j)
- {
- if (__j != __setIndex)
- __x._M_x[__j] = max();
- else
- --__x._M_x[__j];
- }
- __x._M_philox();
- __x._M_x = __tmpCtr;
- __is >> __x._M_i;
- __is.flags(__flags);
- return __is;
}
+ for (size_t __j = 0; __j <= __setIndex; ++__j)
+ {
+ if (__j != __setIndex)
+ __x._M_x[__j] = max();
+ else
+ --__x._M_x[__j];
+ }
+ __x._M_philox();
+ __x._M_x = __tmpCtr;
+ __is >> __x._M_i;
+ __is.flags(__flags);
+ return __is;
+ }
+
private:
// private state variables
array<_UIntType, __n> _M_x;
array<_UIntType, __n> _M_y;
unsigned long long _M_i = 0;
- /** @brief Takes the high values of the product of __a, __b
- *
- * @params __a an unsigned integer
- * @params __b an unsigned integer
- *
- * @returns an unsigned integer of at most bitlength W
- */
- static
- _UIntType
+ // The high W bits of the product of __a and __b
+ static _UIntType
_S_mulhi(_UIntType __a, _UIntType __b); // (A*B)/2^W
- /** @brief Takes the low values of the product of __a, __b
- *
- * @params __a an unsigned integer
- * @params __b an unsigned integer
- *
- * @returns an unsigned integer of at most bitlength W
- */
- static
- _UIntType
+ // The low W bits of the product of __a and __b
+ static _UIntType
_S_mullo(_UIntType __a, _UIntType __b); // (A*B)%2^W
- /** @brief an R-round substitution/Feistel Network hybrid for
- * %philox_engine
- */
+ // An R-round substitution/Feistel Network hybrid for philox_engine
void
_M_philox();
- /** @brief an internal transition function for the %philox_engine. */
+ // The transition function
void
_M_transition();
};
-
#endif
/**
typedef minstd_rand0 default_random_engine;
-#if __cpp_lib_philox_engine
+#if __glibcxx_philox_engine
+ /// 32-bit four-word Philox engine.
typedef philox_engine<
uint_fast32_t,
32, 4, 10,
0xCD9E8D57, 0x9E3779B9,
0xD2511F53, 0xBB67AE85> philox4x32;
- /**
- * Alternative Philox instance (64 bit)
- */
+ /// 64-bit four-word Philox engine.
typedef philox_engine<
uint_fast64_t,
64, 4, 10,
return __is;
}
-#if __cpp_lib_philox_engine
-
- template<class _UIntType,
- size_t __w, size_t __n,
- size_t __r, _UIntType... __consts>
- _UIntType
- philox_engine<_UIntType,
- __w, __n, __r, __consts...>::_S_mulhi(_UIntType __a, _UIntType __b)
- {
- const __uint128_t __num =
- static_cast<__uint128_t>(__a) * static_cast<__uint128_t>(__b);
- return static_cast<_UIntType>((__num >> __w) & max());
- }
+#if __glibcxx_philox_engine // >= C++26
- template<class _UIntType,
- size_t __w, size_t __n,
- size_t __r, _UIntType... __consts>
- _UIntType
- philox_engine<_UIntType,
- __w, __n, __r, __consts...>::_S_mullo(_UIntType __a, _UIntType __b)
- {
- return static_cast<_UIntType>((__a * __b) & max());
- }
+ template<typename _UIntType, size_t __w, size_t __n, size_t __r,
+ _UIntType... __consts>
+ _UIntType
+ philox_engine<_UIntType, __w, __n, __r, __consts...>::
+ _S_mulhi(_UIntType __a, _UIntType __b)
+ {
+ const __uint128_t __num =
+ static_cast<__uint128_t>(__a) * static_cast<__uint128_t>(__b);
+ return static_cast<_UIntType>((__num >> __w) & max());
+ }
- template<class _UIntType,
- size_t __w, size_t __n,
- size_t __r, _UIntType... __consts>
- void
- philox_engine<_UIntType, __w, __n, __r, __consts...>::_M_transition()
- {
- ++_M_i;
- if (_M_i == __n)
+ template<typename _UIntType, size_t __w, size_t __n, size_t __r,
+ _UIntType... __consts>
+ _UIntType
+ philox_engine<_UIntType, __w, __n, __r, __consts...>::
+ _S_mullo(_UIntType __a, _UIntType __b)
{
+ return static_cast<_UIntType>((__a * __b) & max());
+ }
+
+ template<typename _UIntType, size_t __w, size_t __n, size_t __r,
+ _UIntType... __consts>
+ void
+ philox_engine<_UIntType, __w, __n, __r, __consts...>::_M_transition()
+ {
+ ++_M_i;
+ if (_M_i != __n)
+ return;
+
_M_philox();
if constexpr (__n == 4)
- {
- __uint128_t __uh =
- (static_cast<__uint128_t>(_M_x[1]) << __w)
- | (static_cast<__uint128_t>(_M_x[0]) + 1);
- __uint128_t __lh =
- ((static_cast<__uint128_t>(_M_x[3]) << __w)
- | (_M_x[2]));
- __uint128_t __bigMask =
- (static_cast<__uint128_t>(1) << ((2 * __w) - 1))
- | ((static_cast<__uint128_t>(1) << ((2 * __w) - 1)) - 1);
- if ((__uh & __bigMask) == 0)
{
- ++__lh;
- __uh = 0;
+ __uint128_t __uh =
+ (static_cast<__uint128_t>(_M_x[1]) << __w)
+ | (static_cast<__uint128_t>(_M_x[0]) + 1);
+ __uint128_t __lh =
+ ((static_cast<__uint128_t>(_M_x[3]) << __w)
+ | (_M_x[2]));
+ __uint128_t __bigMask =
+ (static_cast<__uint128_t>(1) << ((2 * __w) - 1))
+ | ((static_cast<__uint128_t>(1) << ((2 * __w) - 1)) - 1);
+ if ((__uh & __bigMask) == 0)
+ {
+ ++__lh;
+ __uh = 0;
+ }
+ _M_x[0] = __uh & max();
+ _M_x[1] = (__uh >> (__w)) & max();
+ _M_x[2] = __lh & max();
+ _M_x[3] = (__lh >> (__w)) & max();
+ }
+ else
+ {
+ __uint128_t __num =
+ (static_cast<__uint128_t>(_M_x[1]) << __w)
+ | (static_cast<__uint128_t>(_M_x[0]) + 1);
+ _M_x[0] = __num & max();
+ _M_x[1] = (__num >> __w) & max();
}
- _M_x[0] = __uh & max();
- _M_x[1] = (__uh >> (__w)) & max();
- _M_x[2] = __lh & max();
- _M_x[3] = (__lh >> (__w)) & max();
- } else
- {
- __uint128_t __num =
- (static_cast<__uint128_t>(_M_x[1]) << __w)
- | (static_cast<__uint128_t>(_M_x[0]) + 1);
- _M_x[0] = __num & max();
- _M_x[1] = (__num >> __w) & max();
- }
_M_i = 0;
}
- }
- template<class _UIntType,
- size_t __w, size_t __n,
- size_t __r, _UIntType... __consts>
- void
- philox_engine<_UIntType, __w, __n, __r, __consts...>::_M_philox()
- {
- array<_UIntType, __n> __outputSeq{};
- for (size_t __j = 0; __j < __n; ++__j)
- __outputSeq[__j] = _M_x[__j];
- for (unsigned long __j = 0; __j < __r; ++__j)
+ template<typename _UIntType, size_t __w, size_t __n, size_t __r,
+ _UIntType... __consts>
+ void
+ philox_engine<_UIntType, __w, __n, __r, __consts...>::_M_philox()
{
- array<_UIntType, __n> __intermedSeq{};
- if constexpr (__n == 4)
- {
- __intermedSeq[0] = __outputSeq[2];
- __intermedSeq[1] = __outputSeq[1];
- __intermedSeq[2] = __outputSeq[0];
- __intermedSeq[3] = __outputSeq[3];
- } else
- {
- __intermedSeq[0] = __outputSeq[0];
- __intermedSeq[1] = __outputSeq[1];
- }
- for (unsigned long __k = 0; __k < (__n/2); ++__k)
- {
- __outputSeq[2*__k]= _S_mulhi(__intermedSeq[2*__k], multipliers[__k])
- ^ (((_M_k[__k] + (__j * round_consts[__k])) & max()))
- ^ __intermedSeq[2*__k+1];
+ array<_UIntType, __n> __outputSeq = _M_x;
+ for (size_t __j = 0; __j < __r; ++__j)
+ {
+ array<_UIntType, __n> __intermedSeq{};
+ if constexpr (__n == 4)
+ {
+ __intermedSeq[0] = __outputSeq[2];
+ __intermedSeq[1] = __outputSeq[1];
+ __intermedSeq[2] = __outputSeq[0];
+ __intermedSeq[3] = __outputSeq[3];
+ }
+ else
+ {
+ __intermedSeq[0] = __outputSeq[0];
+ __intermedSeq[1] = __outputSeq[1];
+ }
+ for (unsigned long __k = 0; __k < (__n/2); ++__k)
+ {
+ __outputSeq[2*__k]
+ = _S_mulhi(__intermedSeq[2*__k], multipliers[__k])
+ ^ (((_M_k[__k] + (__j * round_consts[__k])) & max()))
+ ^ __intermedSeq[2*__k+1];
- __outputSeq[(2*__k)+1]= _S_mullo(__intermedSeq[2*__k],
- multipliers[__k]);
- }
+ __outputSeq[(2*__k)+1]
+ = _S_mullo(__intermedSeq[2*__k], multipliers[__k]);
+ }
+ }
+ _M_y = __outputSeq;
}
- for (unsigned long __j = 0; __j < __n; ++__j)
- _M_y[__j] = __outputSeq[__j];
- }
-
- template<class _UIntType,
- size_t __w, size_t __n,
- size_t __r, _UIntType... __consts>
- philox_engine<_UIntType,
- __w, __n, __r, __consts...>::philox_engine(result_type __value)
- {
- std::fill(_M_x.begin(), _M_x.end(), 0);
- std::fill(_M_k.begin(), _M_k.end(), 0);
- std::fill(_M_y.begin(), _M_y.end(), 0);
- _M_k[0] = __value & max();
- _M_i = __n - 1;
- }
- template<class _UIntType,
- size_t __w, size_t __n,
- size_t __r, _UIntType... __consts>
- void
- philox_engine<_UIntType,
- __w, __n, __r, __consts...>::seed(result_type __value)
- {
- std::fill(_M_x.begin(), _M_x.end(), 0);
- std::fill(_M_k.begin(), _M_k.end(), 0);
- std::fill(_M_y.begin(), _M_y.end(), 0);
- _M_k[0] = __value & max();
- _M_i = __n - 1;
- }
-
- template<class _UIntType,
- size_t __w, size_t __n,
- size_t __r, _UIntType... __consts>
- void
- philox_engine<_UIntType, __w,
- __n, __r, __consts...>::set_counter(const array<result_type, __n>& __counter)
- {
- for (unsigned long long __j = 0; __j < __n; ++__j)
- _M_x[__j] = __counter[__n - 1 - __j] & max();
- _M_i = __n - 1;
- }
-
- template<class _UIntType,
- size_t __w, size_t __n,
- size_t __r, _UIntType... __consts>
+ template<typename _UIntType, size_t __w, size_t __n, size_t __r,
+ _UIntType... __consts>
template<typename _Sseq>
- auto
- philox_engine<_UIntType, __w, __n, __r, __consts...>::seed(_Sseq& __q)
- -> _If_seed_seq<_Sseq>
- {
- std::fill(_M_k.begin(), _M_k.end(), 0);
- const unsigned long long __p = 1 + ((__w - 1)/ 32);
- uint_least32_t __tmpArr[(__n / 2) * __p];
- __q.generate(__tmpArr + 0, __tmpArr + ((__n / 2) *__p));
- for (unsigned long long __k = 0; __k < (__n/2); ++__k)
- {
- unsigned long long __precalc = 0;
- for (unsigned long long __j = 0; __j < __p; ++__j)
- {
- unsigned long long __multiplicand = (1ull << (32 * __j));
- __precalc += (__tmpArr[__k*__p + __j] * __multiplicand) & max();
- }
- _M_k[__k] = __precalc;
- }
- std::fill(_M_x.begin(), _M_x.end(), 0);
- std::fill(_M_y.begin(), _M_y.end(), 0);
- _M_i = __n - 1;
- }
-
- template<class _UIntType,
- size_t __w, size_t __n,
- size_t __r, _UIntType... __consts>
- void
- philox_engine<_UIntType,
- __w, __n, __r, __consts...>::discard(unsigned long long __z)
- {
- for (unsigned long long __j = 0; __j < __z; ++__j)
- _M_transition();
- }
-
- template<class _UIntType,
- size_t __w, size_t __n,
- size_t __r, _UIntType... __consts>
- _UIntType
- philox_engine<_UIntType, __w, __n, __r, __consts...>::operator()()
- {
- _M_transition();
- return _M_y[_M_i];
- }
+ void
+ philox_engine<_UIntType, __w, __n, __r, __consts...>::seed(_Sseq& __q)
+ requires __is_seed_seq<_Sseq>
+ {
+ seed(0);
-#endif
+ const unsigned __p = 1 + ((__w - 1) / 32);
+ uint_least32_t __tmpArr[(__n/2) * __p];
+ __q.generate(__tmpArr + 0, __tmpArr + ((__n/2) * __p));
+ for (unsigned __k = 0; __k < (__n/2); ++__k)
+ {
+ unsigned long long __precalc = 0;
+ for (unsigned __j = 0; __j < __p; ++__j)
+ {
+ unsigned long long __multiplicand = (1ull << (32 * __j));
+ __precalc += (__tmpArr[__k * __p + __j] * __multiplicand) & max();
+ }
+ _M_k[__k] = __precalc;
+ }
+ }
+#endif // philox_engine
template<typename _IntType, typename _CharT, typename _Traits>
std::basic_ostream<_CharT, _Traits>&
// { dg-do run { target c++26 } }
-// { dg-require-cstdint "" }
+// { dg-require-cpp-feature-test __cpp_lib_philox_engine }
-// 29.5.4 Random Number Engine Class Templates
-// 29.5.4.5 Class Template philox_engine
+// N5014 29.5.6 Engines and engine adaptors with predefined parameters
#include <random>
#include <testsuite_hooks.h>
+using test_type = std::philox_engine<std::uint_fast32_t, 32, 4, 10,
+ 0xCD9E8D57, 0x9E3779B9,
+ 0xD2511F53, 0xBB67AE85>;
+static_assert( std::is_same_v<test_type, std::philox4x32> );
+
void
test01()
{
int main()
{
test01();
- return 0;
}
// { dg-do run { target c++26 } }
-// { dg-require-cstdint "" }
+// { dg-require-cpp-feature-test __cpp_lib_philox_engine }
-// 29.5.4 Random Number Engine Class Templates
-// 29.5.4.5 Class Template philox_engine
+// N5014 29.5.6 Engines and engine adaptors with predefined parameters
#include <random>
#include <testsuite_hooks.h>
+using test_type = std::philox_engine<std::uint_fast64_t, 64, 4, 10,
+ 0xCA5A826395121157, 0x9E3779B97F4A7C15,
+ 0xD2E7470EE14C6C93, 0xBB67AE8584CAA73B>;
+static_assert( std::is_same_v<test_type, std::philox4x64> );
+
void
test01()
{
int main()
{
test01();
- return 0;
}
+++ /dev/null
-// { 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;
-}
// { dg-do run { target c++26 } }
-// { dg-require-cstdint "" }
+// { dg-require-cpp-feature-test __cpp_lib_philox_engine }
-// 29.5.4 Random Number Engine Class Templates
-// 29.5.4.5 Class Template philox_engine
+// N5014 29.5.4 Random Number Engine Class Templates
+// N5014 29.5.4.5 Class Template philox_engine
#include <random>
+#include <testsuite_hooks.h>
void
-test01()
+test01(unsigned long seed)
{
std::philox_engine<std::uint_fast32_t, 32, 4, 10, 0xCD9E8D57,
- 0x9E3779B9, 0xD2511F53, 0xBB67AE85> e(1ul);
+ 0x9E3779B9, 0xD2511F53, 0xBB67AE85> e(seed);
const auto f(e);
+ VERIFY( f == e );
auto g(f);
- g = g; // Suppress unused warning
+ VERIFY( g == f );
}
int main()
{
- test01();
- return 0;
+ test01(1ul);
+ test01(111ul);
}
// { dg-do run { target c++26 } }
-// { dg-require-cstdint "" }
+// { dg-require-cpp-feature-test __cpp_lib_philox_engine }
-// 29.5.4 Random Number Engine Class Templates
-// 29.5.4.5 Class Template philox_engine
+// N5014 29.5.4.5 Class Template philox_engine
#include <random>
#include <testsuite_hooks.h>
void
-test01()
+test_default_ctor()
{
std::philox_engine<std::uint_fast32_t,
32, 4, 10, 0xCD9E8D57,
VERIFY( philox4x32nullkey() == 0x6627e8d5ul );
}
+void
+test_seed()
+{
+ unsigned long seed = 2;
+ std::philox4x32 seeded(seed);
+
+ std::philox4x32 default_init;
+ VERIFY( seeded != default_init );
+
+ std::philox4x32 default_seeded(std::philox4x32::default_seed);
+ VERIFY( default_seeded == default_init );
+}
+
+void
+test_seed_seq()
+{
+ std::seed_seq sseq{ 1, 2, 3, 4 };
+ std::philox4x32 seeded(sseq);
+ std::philox4x32 default_init;
+ VERIFY( seeded != default_init );
+}
+
int main()
{
- test01();
- return 0;
+ test_default_ctor();
+ test_seed();
+ test_seed_seq();
}
// { dg-do run { target c++26 } }
-// { dg-require-cstdint "" }
+// { dg-require-cpp-feature-test __cpp_lib_philox_engine }
#include <random>
+#include <testsuite_hooks.h>
+
+int f(int x)
+{
+ std::seed_seq sq(&x, &x + 1);
+ auto rnd = std::philox4x32(sq);
+ return std::uniform_int_distribution<int>()(rnd);
+}
+
+int g(int x)
+{
+ std::seed_seq sq(&x, &x + 1);
+ auto rnd = std::philox4x32();
+ rnd.seed(sq);
+ return std::uniform_int_distribution<int>()(rnd);
+}
void
test01()
{
- unsigned long seed = 2;
- std::philox_engine<std::uint_fast32_t,
- 32, 4, 10, 0xCD9E8D57,
- 0x9E3779B9, 0xD2511F53,
- 0xBB67AE85> philox4x32seeded(seed);
+ const int f1 = f(0);
+ const int f2 = f(0);
+
+ const int g1 = g(0);
+ const int g2 = g(0);
+
+ VERIFY( f1 == f2 );
+ VERIFY( g1 == g2 );
+ VERIFY( f1 == g1 );
+}
+
+void
+test02()
+{
+ std::philox4x64 e1(25);
+ std::philox4x64 e2;
+ VERIFY( e2 != e1 );
+ e2.seed(25);
+ VERIFY( e2 == e1 );
+
}
int main()
{
test01();
- return 0;
+ test02();
}
+++ /dev/null
-// { dg-do run { target c++26 } }
-// { dg-require-cstdint "" }
-
-// 29.5.4 Random Number Engine Class Templates
-// 29.5.4.5 Class Template philox_engine
-
-#include <random>
-
-void
-test01()
-{
- std::seed_seq sseq{ 1, 2, 3, 4 };
- std::philox_engine<std::uint_fast32_t,
- 32, 4, 10, 0xCD9E8D57,
- 0x9E3779B9, 0xD2511F53,
- 0xBB67AE85> philox4x32sseq(sseq);
-}
-
-int
-main()
-{
- test01();
- return 0;
-}
// { dg-do run { target c++26 } }
-// { dg-require-cstdint "" }
+// { dg-require-cpp-feature-test __cpp_lib_philox_engine }
-// 29.5.4 Random Number Engine Class Templates
-// 29.5.4.5 Class Template philox_engine
+// N5014 29.5.4.5 Class Template philox_engine
#include <random>
#include <testsuite_hooks.h>
y.discard(100);
VERIFY (x == y);
+
+ x.discard(2);
+ VERIFY (x != y);
+ y.discard(2);
+ VERIFY (x == y);
}
int
main()
{
test01();
- return 0;
}
+++ /dev/null
-// { 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;
-}
// { dg-do run { target c++26 } }
-// { dg-require-cstdint "" }
+// { dg-require-cpp-feature-test __cpp_lib_philox_engine }
-// 29.5.4 Random Number Engine Class Templates
-// 29.5.4.5 Class Template philox_engine
+// N5014 29.5.4.5 Class Template philox_engine
#include <sstream>
#include <random>
#include <testsuite_hooks.h>
-#include <iostream>
void
test01()
main()
{
test01();
- return 0;
}
-// { dg-do run { target c++26 } }
-// { dg-require-cstdint "" }
+// { dg-do compile { target c++26 } }
+// { dg-require-cpp-feature-test __cpp_lib_philox_engine }
-// 29.5.4 Random Number Engine Class Templates
-// 29.5.4.5 Class Template philox_engine
+// N5014 29.5.4.5 Class Template philox_engine
#include <random>
-void test01()
+namespace test1
{
- std::philox4x32 philox;
- const void* p = &philox.word_size;
- p = &philox.word_count;
- p = &philox.round_count;
- p = &philox.multipliers;
- p = &philox.round_consts;
- p = &philox.default_seed;
- p = p; // Suppress unused warning.
+ using P = std::philox_engine<std::uint32_t, 32, 4, 5, 9, 99, 999, 9999>;
+ constexpr std::same_as<std::uint32_t> auto min = P::min();
+ static_assert( min == 0 );
+ constexpr std::same_as<std::uint32_t> auto max = P::max();
+ static_assert( max == 0xffffffff );
+ constexpr std::same_as<std::size_t> auto w = P::word_size;
+ static_assert( w == 32 );
+ constexpr std::same_as<std::size_t> auto n = P::word_count;
+ static_assert( n == 4 );
+ constexpr std::same_as<std::size_t> auto r = P::round_count;
+ static_assert( r == 5 );
+ constexpr std::array<std::uint32_t, 2> muls = P::multipliers;
+ static_assert( muls[0] == 9 && muls[1] == 999 );
+ constexpr std::array<std::uint32_t, 2> consts = P::round_consts;
+ static_assert( consts[0] == 99 && consts[1] == 9999 );
+ constexpr std::same_as<std::uint32_t> auto def = P::default_seed;
+ static_assert( def == 20111115u );
}
-int
-main()
+namespace test2
{
- test01();
- return 0;
+ using P = std::philox_engine<std::uint64_t, 64, 2, 12, 77, 777>;
+ constexpr std::same_as<std::uint64_t> auto min = P::min();
+ static_assert( min == 0 );
+ constexpr std::same_as<std::uint64_t> auto max = P::max();
+ static_assert( max == 0xffffffffffffffff );
+ constexpr std::same_as<std::size_t> auto w = P::word_size;
+ static_assert( w == 64 );
+ constexpr std::same_as<std::size_t> auto n = P::word_count;
+ static_assert( n == 2 );
+ constexpr std::same_as<std::size_t> auto r = P::round_count;
+ static_assert( r == 12 );
+ constexpr std::array<std::uint64_t, 1> muls = P::multipliers;
+ static_assert( muls[0] == 77 );
+ constexpr std::array<std::uint64_t, 1> consts = P::round_consts;
+ static_assert( consts[0] == 777 );
+ constexpr std::same_as<std::uint64_t> auto def = P::default_seed;
+ static_assert( def == 20111115u );
}
+++ /dev/null
-// { 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;
-}
+++ /dev/null
-// { 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;
-}
-// { dg-do run { target c++26 } }
-// { dg-require-cstdint "" }
-
-// 29.5.4 Random Number Engine Class Templates
-// 29.5.4.5 Class Template philox_engine
+// { dg-do compile { target c++26 } }
+// { dg-require-cpp-feature-test __cpp_lib_philox_engine }
+// N5014 29.5.4.5 Class Template philox_engine
#include <random>
0xBB67AE85> testType;
typedef testType::result_type result_type;
+ static_assert( std::is_same_v<result_type, std::uint_fast32_t> );
}
-int
-main()
+void
+test02()
{
- test01();
- return 0;
+ typedef std::philox_engine<std::uint_fast64_t,
+ 64, 4, 10, 0xCA5A826395121157,
+ 0x9E3779B97F4A7C15, 0xD2E7470EE14C6C93,
+ 0xBB67AE8584CAA73B> testType;
+
+ typedef testType::result_type result_type;
+ static_assert( std::is_same_v<result_type, std::uint_fast64_t> );
}
// { dg-error "static assertion failed: template argument must be a floating point type" "" { target *-*-* } 271 }
-// { dg-error "static assertion failed: template argument must be a floating point type" "" { target *-*-* } 3548 }
+// { dg-error "static assertion failed: template argument must be a floating point type" "" { target *-*-* } 3480 }