8.0 KiB
[rand.eng.philox]
29 Numerics library [numerics]
29.5 Random number generation [rand]
29.5.4 Random number engine class templates [rand.eng]
29.5.4.5 Class template philox_engine [rand.eng.philox]
A philox_engine random number engine produces unsigned integer random numbers in the interval [0, m), where m=2w and the template parameter w defines the range of the produced numbers.
The state of a philox_engine object consists of a sequence X of n unsigned integer values of width w, a sequence K of n/2 values of result_type, a sequence Y of n values of result_type, and a scalar i, where
X is the interpretation of the unsigned integer counter valueZ:=ânâ1j=0Xjâ2wj of nâw bits,
K are keys, which are generated once from the seed (see constructors below) and remain constant unless the seed function ([rand.req.eng]) is invoked,
Y stores a batch of output values, and
i is an index for an element of the sequence Y.
The generation algorithm returns Yi, the value stored in the ith element of Y after applying the transition algorithm.
The state transition is performed as if by the following algorithm:i = i + 1if (i == n) {Y = Philox(K, X) // see belowZ = Z + 1i = 0}
The Philox function maps the length-n/2 sequence K and the length-n sequence X into a length-n output sequence Y.
Philox applies an r-round substitution-permutation network to the values in X.
A single round of the generation algorithm performs the following steps:
The output sequence Xâ² of the previous round (X in case of the first round) is permuted to obtain the intermediate state V:Vj=Xâ²fn(j) where j=0,â¦,nâ1 andfn(j) is defined in Table 129. Table 129 — Values for the word permutation fn(j) [tab:rand.eng.philox.f]
| ð fn(j) |
j | ||||
|---|---|---|---|---|---|
| ð | 0 | 1 | 2 | 3 | |
| ð n |
2 | 0 | 1 | ||
| ð |
4 | 2 | 1 | 0 | 3 |
| ð |
[Note 1: For n=2 the sequence is not permuted. â end note]
The following computations are applied to the elements of the V sequence:X2k+0=mulhi(V2k,Mk,w)xorkeyqkxorV2k+1X2k+1=mullo(V2k,Mk,w) where:
mullo(a, b, w) is the low half of the modular multiplication of a and b: (aâb)mod2w,
mulhi(a, b, w) is the high half of the modular multiplication of a and b: (â(aâb)/2wâ),
k=0,â¦,n/2â1 is the index in the sequences,
q=0,â¦,râ1 is the index of the round,
keyqk is the kth round key for round q, keyqk:=(Kk+qâCk)mod2w,
Kk are the elements of the key sequence K,
Mk is multipliers[k], and
Ck is round_consts[k].
After r applications of the single-round function,Philox returns the sequence Y=Xâ².
namespace std {template<class UIntType, size_t w, size_t n, size_t r, UIntType... consts>class philox_engine {static constexpr size_t array-size = n / 2; // exposition onlypublic:// typesusing result_type = UIntType; // engine characteristicsstatic 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, array-size> multipliers; static constexpr array<result_type, array-size> round_consts; static constexpr result_type min() { return 0; }static constexpr result_type max() { return m - 1; }static constexpr result_type default_seed = 20111115u; // constructors and seeding functions philox_engine() : philox_engine(default_seed) {}explicit philox_engine(result_type value); template explicit philox_engine(Sseq& q); void seed(result_type value = default_seed); template void seed(Sseq& q); void set_counter(const array<result_type, n>& counter); // equality operatorsfriend bool operator==(const philox_engine& x, const philox_engine& y); // generating functions result_type operator()(); void discard(unsigned long long z); // inserters and extractorstemplate<class charT, class traits>friend basic_ostream<charT, traits>&operator<<(basic_ostream<charT, traits>& os, const philox_engine& x); // hostedtemplate<class charT, class traits>friend basic_istream<charT, traits>&operator>>(basic_istream<charT, traits>& is, philox_engine& x); // hosted};}
Mandates:
sizeof...(consts) == n is true, and
n == 2 || n == 4 is true, and
0 < r is true, and
0 < w && w <= numeric_limits::digits is true.
The template parameter pack consts represents the Mk and Ck constants which are grouped as follows:[M0,C0,M1,C1,M2,C2,â¦,Mn/2â1,Cn/2â1].
The textual representation consists of the values ofK0,â¦,Kn/2â1,X0,â¦,Xnâ1,i, in that order.
[Note 2:
The stream extraction operator can reconstruct Y from K and X, as needed.
â end note]
explicit philox_engine(result_type value);
Effects: Sets the K0 element of sequence K to valuemod2w.
All elements of sequences X and K (except K0) are set to 0.
The value of i is set to nâ1.
template<class Sseq> explicit philox_engine(Sseq& q);
Effects: With p=âw/32â and an array (or equivalent) a of length (n/2)âp, invokes q.generate(a + 0, a + n / 2 * p) and then iteratively for k=0,â¦,n/2â1, sets Kk to(âpâ1j=0akp+jâ232j)mod2w.
All elements of sequence X are set to 0.
The value of i is set to nâ1.
void set_counter(const array<result_type, n>& c);
Effects: For j=0,â¦,nâ1 sets Xj to Cnâ1âjmod2w.
The value of i is set to nâ1.
[Note 3:
The counter is the value Z introduced at the beginning of this subclause.
â end note]