[rand.eng.philox]

# 29 Numerics library [[numerics]](./#numerics)

## 29.5 Random number generation [[rand]](rand#eng.philox)

### 29.5.4 Random number engine class templates [[rand.eng]](rand.eng#philox)

#### 29.5.4.5 Class template philox_engine [rand.eng.philox]

[1](#1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L3154)

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[.](#1.sentence-1)

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

- [(1.1)](#1.1)

X is the interpretation of the unsigned integer [*counter*](#def:counter) valueZ:=ânâ1j=0Xjâ2wj of nâw bits,

- [(1.2)](#1.2)

K are keys, which are generated once from the seed (see constructors below)
and remain constant unless the seed function ([[rand.req.eng]](rand.req.eng "29.5.3.4 Random number engine requirements")) is invoked,

- [(1.3)](#1.3)

Y stores a batch of output values, and

- [(1.4)](#1.4)

i is an index for an element of the sequence Y[.](#1.sentence-2)

[2](#2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L3177)

The generation algorithm returns Yi,
the value stored in the ith element of Y after applying
the transition algorithm[.](#2.sentence-1)

[3](#3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L3182)

The state transition is performed as if by the following algorithm:i = i + 1if (i == n) {Y = Philox(K, X) // *see below*Z = Z + 1i = 0}

[4](#4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L3193)

The Philox function maps the length-n/2 sequence K and
the length-n sequence X into a length-n output sequence Y[.](#4.sentence-1)

Philox applies an r-round substitution-permutation network to the values in X[.](#4.sentence-2)

A single round of the generation algorithm performs the following steps:

- [(4.1)](#4.1)

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](#tab:rand.eng.philox.f "Table 129: Values for the word permutation <b>f</b>ï¿½"). Table [129](#tab:rand.eng.philox.f) — Values for the word permutation fn(j) [[tab:rand.eng.philox.f]](./tab:rand.eng.philox.f)  

| [ð](#tab:rand.eng.philox.f-row-1)<br>fn(j) | | **j** | | | |
| --- | --- | --- | --- | --- | --- |
| [ð](#tab:rand.eng.philox.f-row-2) | | 0 | 1 | 2 | 3 |
| [ð](#tab:rand.eng.philox.f-row-3)<br>**n** | 2 | 0 | 1 |  | |
| [ð](#tab:rand.eng.philox.f-row-4)<br> | 4 | 2 | 1 | 0 | 3 |
| [ð](#tab:rand.eng.philox.f-row-5)<br> |

  [*Note [1](#note-1)*:
  For n=2 the sequence is not permuted[.](#4.1.sentence-2)
 â *end note*]

- [(4.2)](#4.2)

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:
  * [(4.2.1)](#4.2.1)

mullo(a, b, w) is
 the low half of the modular multiplication of a and b: (aâb)mod2w,

  * [(4.2.2)](#4.2.2)

mulhi(a, b, w) is
 the high half of the modular multiplication of a and b: (â(aâb)/2wâ),

  * [(4.2.3)](#4.2.3)

k=0,â¦,n/2â1 is the index in the sequences,

  * [(4.2.4)](#4.2.4)

q=0,â¦,râ1 is the index of the round,

  * [(4.2.5)](#4.2.5)

keyqk is the kth round key for round q, keyqk:=(Kk+qâCk)mod2w,

  * [(4.2.6)](#4.2.6)

Kk are the elements of the key sequence K,

  * [(4.2.7)](#4.2.7)

Mk is multipliers[k], and

  * [(4.2.8)](#4.2.8)

Ck is round_consts[k].

[5](#5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L3261)

After r applications of the single-round function,Philox returns the sequence Y=Xâ²[.](#5.sentence-1)

[ð](#lib:philox_engine_)

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 only*public:// 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<class Sseq> explicit philox_engine(Sseq& q); void seed(result_type value = default_seed); template<class Sseq> 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};}

[6](#6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L3313)

*Mandates*: 

- [(6.1)](#6.1)

sizeof...(consts) == n is true, and

- [(6.2)](#6.2)

n == 2 || n == 4 is true, and

- [(6.3)](#6.3)

0 < r is true, and

- [(6.4)](#6.4)

0 < w && w <= numeric_limits<UIntType>​::​digits is true[.](#6.sentence-1)

[7](#7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L3322)

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][.](#7.sentence-1)

[8](#8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L3327)

The textual representation consists of the values ofK0,â¦,Kn/2â1,X0,â¦,Xnâ1,i, in that order[.](#8.sentence-1)

[*Note [2](#note-2)*:

The stream extraction operator can reconstruct Y from K and X, as needed[.](#8.sentence-2)

â *end note*]

[ð](#lib:philox_engine,constructor)

`explicit philox_engine(result_type value);
`

[9](#9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L3340)

*Effects*: Sets the K0 element of sequence K to valuemod2w[.](#9.sentence-1)

All elements of sequences X and K (except K0) are set to 0[.](#9.sentence-2)

The value of i is set to nâ1[.](#9.sentence-3)

[ð](#lib:philox_engine,constructor_)

`template<class Sseq> explicit philox_engine(Sseq& q);
`

[10](#10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L3353)

*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[.](#10.sentence-1)

All elements of sequence X are set to 0[.](#10.sentence-2)

The value of i is set to nâ1[.](#10.sentence-3)

[ð](#lib:set_counter,philox_engine)

`void set_counter(const array<result_type, n>& c);
`

[11](#11)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L3371)

*Effects*: For j=0,â¦,nâ1 sets Xj to Cnâ1âjmod2w[.](#11.sentence-1)

The value of i is set to nâ1[.](#11.sentence-2)

[*Note [3](#note-3)*:

The counter is the value Z introduced at the beginning of this subclause[.](#11.sentence-3)

â *end note*]
