Files
2025-10-25 03:02:53 +03:00

647 lines
27 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[rand.eng]
# 29 Numerics library [[numerics]](./#numerics)
## 29.5 Random number generation [[rand]](rand#eng)
### 29.5.4 Random number engine class templates [rand.eng]
#### [29.5.4.1](#general) General [[rand.eng.general]](rand.eng.general)
[1](#general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L2595)
Each type instantiated
from a class template specified in [rand.eng]
meets the requirements
of a [random number engine](rand.req.eng "29.5.3.4Random number engine requirements[rand.req.eng]") type[.](#general-1.sentence-1)
[2](#general-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L2601)
Except where specified otherwise,
the complexity of each function
specified in [rand.eng]
is constant[.](#general-2.sentence-1)
[3](#general-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L2607)
Except where specified otherwise,
no function described in [rand.eng]
throws an exception[.](#general-3.sentence-1)
[4](#general-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L2612)
Every function described in [rand.eng]
that has a function parameter q of type Sseq& for a template type parameter named Sseq that is different from type seed_seq throws what and when the invocation of q.generate throws[.](#general-4.sentence-1)
[5](#general-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L2619)
Descriptions are provided in [rand.eng]
only for engine operations
that are not described in [[rand.req.eng]](rand.req.eng "29.5.3.4Random number engine requirements") or for operations where there is additional semantic information[.](#general-5.sentence-1)
In particular,
declarations for copy constructors,
for copy assignment operators,
for streaming operators,
and for equality and inequality operators
are not shown in the synopses[.](#general-5.sentence-2)
[6](#general-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L2631)
Each template specified in [rand.eng]
requires one or more relationships,
involving the value(s) of its constant template parameter(s), to hold[.](#general-6.sentence-1)
A program instantiating any of these templates
is ill-formed
if any such required relationship fails to hold[.](#general-6.sentence-2)
[7](#general-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L2639)
For every random number engine and for every random number engine adaptor X defined in [rand.eng] and in [[rand.adapt]](rand.adapt "29.5.5Random number engine adaptor class templates"):
- [(7.1)](#general-7.1)
if the constructortemplate<class Sseq> explicit X(Sseq& q); is called with a type Sseq that does not qualify as a seed sequence, then this
constructor shall not participate in overload resolution;
- [(7.2)](#general-7.2)
if the member functiontemplate<class Sseq> void seed(Sseq& q); is called with a type Sseq that does not qualify as a seed sequence, then this
function shall not participate in overload resolution[.](#general-7.sentence-1)
The extent to which an implementation determines that a type cannot be a seed sequence
is unspecified, except that as a minimum a type shall not qualify as a seed sequence
if it is implicitly convertible to X::result_type[.](#general-7.sentence-2)
#### [29.5.4.2](#lcong) Class template linear_congruential_engine [[rand.eng.lcong]](rand.eng.lcong)
[1](#lcong-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L2670)
A linear_congruential_engine random number engine
produces unsigned integer random numbers[.](#lcong-1.sentence-1)
The state xi of a linear_congruential_engine object x is of size 1 and consists of a single integer[.](#lcong-1.sentence-2)
The transition algorithm
is a modular linear function of the formTA(xi)=(aâ‹xi+c)modm;
the generation algorithm
is GA(xi)=xi+1[.](#lcong-1.sentence-3)
[🔗](#lib:linear_congruential_engine_)
namespace std {template<class UIntType, UIntType a, UIntType c, UIntType m>class linear_congruential_engine {public:// typesusing result_type = UIntType; // engine characteristicsstatic constexpr result_type multiplier = a; static constexpr result_type increment = c; static constexpr result_type modulus = m; static constexpr result_type min() { return c == 0u ? 1u: 0u; }static constexpr result_type max() { return m - 1u; }static constexpr result_type default_seed = 1u; // constructors and seeding functions linear_congruential_engine() : linear_congruential_engine(default_seed) {}explicit linear_congruential_engine(result_type s); template<class Sseq> explicit linear_congruential_engine(Sseq& q); void seed(result_type s = default_seed); template<class Sseq> void seed(Sseq& q); // equality operatorsfriend bool operator==(const linear_congruential_engine& x, const linear_congruential_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, // hostedconst linear_congruential_engine& x); template<class charT, class traits>friend basic_istream<charT, traits>&operator>>(basic_istream<charT, traits>& is, // hosted linear_congruential_engine& x); };}
[2](#lcong-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L2729)
If the template parameterm is 0,
the modulus m used throughout [[rand.eng.lcong]](#lcong "29.5.4.2Class template linear_­congruential_­engine") is numeric_limits<result_type>::max() plus 1[.](#lcong-2.sentence-1)
[*Note [1](#lcong-note-1)*:
m need not be representable
as a value of type result_type[.](#lcong-2.sentence-2)
— *end note*]
[3](#lcong-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L2740)
If the template parameterm is not 0,
the following relations shall hold: a < m and c < m[.](#lcong-3.sentence-1)
[4](#lcong-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L2748)
The textual representation
consists of
the value of xi[.](#lcong-4.sentence-1)
[🔗](#lib:linear_congruential_engine,constructor)
`explicit linear_congruential_engine(result_type s);
`
[5](#lcong-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L2759)
*Effects*: If cmodm is 0 and smodm is 0,
sets the engine's state to 1,
otherwise sets the engine's state to smodm[.](#lcong-5.sentence-1)
[🔗](#lib:linear_congruential_engine,constructor_)
`template<class Sseq> explicit linear_congruential_engine(Sseq& q);
`
[6](#lcong-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L2772)
*Effects*: With k=⌈log2m32⌉ and a an array (or equivalent)
of length k+3,
invokes q.generate(a+0, a+k+3) and then computes S=ˆ‘ˆ’1j=0aj+3â‹232j)modm[.](#lcong-6.sentence-1)
If cmodm is 0 and S is 0,
sets the engine's state to 1,
else sets the engine's state
to S[.](#lcong-6.sentence-2)
#### [29.5.4.3](#mers) Class template mersenne_twister_engine [[rand.eng.mers]](rand.eng.mers)
[1](#mers-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L2793)
A mersenne_twister_engine random number
engine[242](#footnote-242 "The name of this engine refers, in part, to a property of its period: For properly-selected values of the parameters, the period is closely related to a large Mersenne prime number.") produces unsigned integer random numbers
in the closed interval [0,2w−1][.](#mers-1.sentence-1)
The
statexi of a mersenne_twister_engine object x is of size n and consists of a sequence X of n values of the type delivered by x;
all subscripts applied to X are to be taken modulo n[.](#mers-1.sentence-2)
[2](#mers-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L2812)
The transition algorithm
employs a twisted generalized feedback shift register
defined by shift values n and m, a twist value r,
and a conditional xor-mask a[.](#mers-2.sentence-1)
To improve the uniformity of the result,
the bits of the raw shift register are additionally [*tempered*](#def:tempered) (i.e., scrambled) according to a bit-scrambling matrix
defined by values u, d, s, b, t, c, and ℓ[.](#mers-2.sentence-2)
The state transition is performed as follows:
- [(2.1)](#mers-2.1)
Concatenate
the upper ˆ’r bits of Xi−n with
the lower r bits of Xi+ˆ’n to obtain an unsigned integer value Y[.](#mers-2.1.sentence-1)
- [(2.2)](#mers-2.2)
With α=‹(Ybitand1),
set Xi to Xi+ˆ’nxor(Yrshift1)xorα[.](#mers-2.2.sentence-1)
The sequence X is initialized
with the help of an initialization multiplier f[.](#mers-2.sentence-4)
[3](#mers-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L2838)
The generation algorithm
determines the unsigned integer values z1,z2,z3,z4 as follows,
then delivers z4 as its result:
- [(3.1)](#mers-3.1)
Let z1=Xixor((Xirshiftu)bitandd)[.](#mers-3.1.sentence-1)
- [(3.2)](#mers-3.2)
Let z2=z1xor((z1lshiftws)bitandb)[.](#mers-3.2.sentence-1)
- [(3.3)](#mers-3.3)
Let z3=z2xor((z2lshiftwt)bitandc)[.](#mers-3.3.sentence-1)
- [(3.4)](#mers-3.4)
Let z4=z3xor(z3rshiftℓ)[.](#mers-3.4.sentence-1)
[🔗](#lib:mersenne_twister_engine_)
namespace std {template<class UIntType, size_t w, size_t n, size_t m, size_t r,
UIntType a, size_t u, UIntType d, size_t s,
UIntType b, size_t t,
UIntType c, size_t l, UIntType f>class mersenne_twister_engine {public:// typesusing result_type = UIntType; // engine characteristicsstatic constexpr size_t word_size = w; static constexpr size_t state_size = n; static constexpr size_t shift_size = m; static constexpr size_t mask_bits = r; static constexpr UIntType xor_mask = a; static constexpr size_t tempering_u = u; static constexpr UIntType tempering_d = d; static constexpr size_t tempering_s = s; static constexpr UIntType tempering_b = b; static constexpr size_t tempering_t = t; static constexpr UIntType tempering_c = c; static constexpr size_t tempering_l = l; static constexpr UIntType initialization_multiplier = f; static constexpr result_type min() { return 0; }static constexpr result_type max() { return 2w−1; }static constexpr result_type default_seed = 5489u; // constructors and seeding functions mersenne_twister_engine() : mersenne_twister_engine(default_seed) {}explicit mersenne_twister_engine(result_type value); template<class Sseq> explicit mersenne_twister_engine(Sseq& q); void seed(result_type value = default_seed); template<class Sseq> void seed(Sseq& q); // equality operatorsfriend bool operator==(const mersenne_twister_engine& x, const mersenne_twister_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, // hostedconst mersenne_twister_engine& x); template<class charT, class traits>friend basic_istream<charT, traits>&operator>>(basic_istream<charT, traits>& is, // hosted mersenne_twister_engine& x); };}
[4](#mers-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L2911)
The following relations shall hold: 0 < m, m <= n, 2u < w, r <= w, u <= w, s <= w, t <= w, l <= w, w <= numeric_limits<UIntType>::digits, a <= (1u << w) - 1u, b <= (1u << w) - 1u, c <= (1u << w) - 1u, d <= (1u << w) - 1u,
and f <= (1u << w) - 1u[.](#mers-4.sentence-1)
[5](#mers-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L2929)
The textual representation
of xi consists of the values of Xi−n,…,Xi−1,
in that order[.](#mers-5.sentence-1)
[🔗](#lib:mersenne_twister_engine,constructor)
`explicit mersenne_twister_engine(result_type value);
`
[6](#mers-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L2941)
*Effects*: Sets ˆ’n to valuemod2w[.](#mers-6.sentence-1)
Then, iteratively for i=ˆ’n,…,−1, sets Xi to
[‹(Xi−1xor(Xi−1rshift(ˆ’2)))+imodn]mod2w[.](#mers-6.sentence-2)
[7](#mers-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L2954)
*Complexity*: O(n)[.](#mers-7.sentence-1)
[🔗](#lib:mersenne_twister_engine,constructor_)
`template<class Sseq> explicit mersenne_twister_engine(Sseq& q);
`
[8](#mers-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L2965)
*Effects*: With k=⌈w/32⌉ and a an array (or equivalent)
of length ‹k,
invokes q.generate(a+0, a+‹k) and then, iteratively for i=−n,…,−1,
sets Xi to (∑ˆ’1j=0ak(i+n)+jâ‹232j)mod2w[.](#mers-8.sentence-1)
Finally,
if the most significant ˆ’r bits of ˆ’n are zero,
and if each of the other resulting Xi is 0,
changes ˆ’n to 2w−1[.](#mers-8.sentence-2)
[242)](#footnote-242)[242)](#footnoteref-242)
The name of this engine refers, in part, to a property of its period:
For properly-selected values of the parameters,
the period is closely related to a large Mersenne prime number[.](#footnote-242.sentence-1)
#### [29.5.4.4](#sub) Class template subtract_with_carry_engine [[rand.eng.sub]](rand.eng.sub)
[1](#sub-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L2989)
A subtract_with_carry_engine random number engine
produces unsigned integer random numbers[.](#sub-1.sentence-1)
[2](#sub-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L2993)
The state xi of a subtract_with_carry_engine object x is of sizeO(r),
and consists of
a sequence X of r integer values ‰¤Xi<m=2w;
all subscripts applied to X are to be taken modulo r[.](#sub-2.sentence-1)
The state xi additionally consists of an integer c (known as the [*carry*](#def:carry))
whose value is either 0 or 1[.](#sub-2.sentence-2)
[3](#sub-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L3006)
The state transition
is performed as follows:
- [(3.1)](#sub-3.1)
Let Y=Xi−ˆ’Xi−ˆ’c[.](#sub-3.1.sentence-1)
- [(3.2)](#sub-3.2)
Set Xi to y=Ymodm[.](#sub-3.2.sentence-1)
Set c to 1 if Y<0,
otherwise set c to 0[.](#sub-3.2.sentence-2)
[*Note [1](#sub-note-1)*:
This algorithm corresponds
to a modular linear function
of the form TA(xi)=(‹xi)modb,
where b is of the form mr−ms+1 and a=ˆ’(b−1)/m[.](#sub-3.sentence-2)
— *end note*]
[4](#sub-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L3027)
The generation algorithm
is given by GA(xi)=y,
where y is the value produced as a result
of advancing the engine's state as described above[.](#sub-4.sentence-1)
[🔗](#lib:subtract_with_carry_engine_)
namespace std {template<class UIntType, size_t w, size_t s, size_t r>class subtract_with_carry_engine {public:// typesusing result_type = UIntType; // engine characteristicsstatic constexpr size_t word_size = w; static constexpr size_t short_lag = s; static constexpr size_t long_lag = r; static constexpr result_type min() { return 0; }static constexpr result_type max() { return m−1; }static constexpr uint_least32_t default_seed = 19780503u; // constructors and seeding functions subtract_with_carry_engine() : subtract_with_carry_engine(0u) {}explicit subtract_with_carry_engine(result_type value); template<class Sseq> explicit subtract_with_carry_engine(Sseq& q); void seed(result_type value = 0u); template<class Sseq> void seed(Sseq& q); // equality operatorsfriend bool operator==(const subtract_with_carry_engine& x, const subtract_with_carry_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, // hostedconst subtract_with_carry_engine& x); template<class charT, class traits>friend basic_istream<charT, traits>&operator>>(basic_istream<charT, traits>& is, // hosted subtract_with_carry_engine& x); };}
[5](#sub-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L3079)
The following relations shall hold: 0u < s, s < r, 0 < w,
and w <= numeric_limits<UIntType>::digits[.](#sub-5.sentence-1)
[6](#sub-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L3087)
The textual representation
consists of the values of Xi−r,…,Xi−1,
in that order, followed by c[.](#sub-6.sentence-1)
[🔗](#lib:subtract_with_carry_engine,constructor)
`explicit subtract_with_carry_engine(result_type value);
`
[7](#sub-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L3099)
*Effects*: Sets the values of X−r,…,X−1,
in that order, as specified below[.](#sub-7.sentence-1)
If X−1 is then 0,
sets c to 1;
otherwise sets c to 0[.](#sub-7.sentence-2)
To set the values Xk,
first construct e, a linear_congruential_engine object,
as if by the following definition:linear_congruential_engine<uint_least32_t, 40014u, 0u, 2147483563u> e( value == 0u ? default_seed : static_cast<uint_least32_t>(value % 2147483563u));
Then, to set each Xk,
obtain new values z0,…,zn−1 from n=⌈w/32⌉ successive invocations
of e[.](#sub-7.sentence-4)
Set Xk to (∑ˆ’1j=0zjâ‹232j)modm[.](#sub-7.sentence-5)
[8](#sub-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L3121)
*Complexity*: Exactly nâ‹r invocations
of e[.](#sub-8.sentence-1)
[🔗](#lib:subtract_with_carry_engine,constructor_)
`template<class Sseq> explicit subtract_with_carry_engine(Sseq& q);
`
[9](#sub-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L3133)
*Effects*: With k=⌈w/32⌉ and a an array (or equivalent)
of length râ‹k,
invokes q.generate(a+0, a+râ‹k) and then, iteratively for i=−r,…,−1,
sets Xi to (∑ˆ’1j=0ak(i+r)+jâ‹232j)modm[.](#sub-9.sentence-1)
If X−1 is then 0,
sets c to 1;
otherwise sets c to 0[.](#sub-9.sentence-2)
#### [29.5.4.5](#philox) Class template philox_engine [[rand.eng.philox]](rand.eng.philox)
[1](#philox-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[.](#philox-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)](#philox-1.1)
X is the interpretation of the unsigned integer [*counter*](#def:counter) valueZ:=∑ˆ’1j=0Xjâ‹2wj of nâ‹w bits,
- [(1.2)](#philox-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.4Random number engine requirements")) is invoked,
- [(1.3)](#philox-1.3)
Y stores a batch of output values, and
- [(1.4)](#philox-1.4)
i is an index for an element of the sequence Y[.](#philox-1.sentence-2)
[2](#philox-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[.](#philox-2.sentence-1)
[3](#philox-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](#philox-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[.](#philox-4.sentence-1)
Philox applies an r-round substitution-permutation network to the values in X[.](#philox-4.sentence-2)
A single round of the generation algorithm performs the following steps:
- [(4.1)](#philox-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](#philox-note-1)*:
For n=2 the sequence is not permuted[.](#philox-4.1.sentence-2)
— *end note*]
- [(4.2)](#philox-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)](#philox-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)](#philox-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)](#philox-4.2.3)
k=0,…,n/2−1 is the index in the sequences,
* [(4.2.4)](#philox-4.2.4)
q=0,…,r−1 is the index of the round,
* [(4.2.5)](#philox-4.2.5)
keyqk is the kth round key for round q, keyqk:=(Kk+qâ‹Ck)mod2w,
* [(4.2.6)](#philox-4.2.6)
Kk are the elements of the key sequence K,
* [(4.2.7)](#philox-4.2.7)
Mk is multipliers[k], and
* [(4.2.8)](#philox-4.2.8)
Ck is round_consts[k].
[5](#philox-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′[.](#philox-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](#philox-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L3313)
*Mandates*:
- [(6.1)](#philox-6.1)
sizeof...(consts) == n is true, and
- [(6.2)](#philox-6.2)
n == 2 || n == 4 is true, and
- [(6.3)](#philox-6.3)
0 < r is true, and
- [(6.4)](#philox-6.4)
0 < w && w <= numeric_limits<UIntType>::digits is true[.](#philox-6.sentence-1)
[7](#philox-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][.](#philox-7.sentence-1)
[8](#philox-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[.](#philox-8.sentence-1)
[*Note [2](#philox-note-2)*:
The stream extraction operator can reconstruct Y from K and X, as needed[.](#philox-8.sentence-2)
— *end note*]
[🔗](#lib:philox_engine,constructor)
`explicit philox_engine(result_type value);
`
[9](#philox-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L3340)
*Effects*: Sets the K0 element of sequence K to valuemod2w[.](#philox-9.sentence-1)
All elements of sequences X and K (except K0) are set to 0[.](#philox-9.sentence-2)
The value of i is set to n−1[.](#philox-9.sentence-3)
[🔗](#lib:philox_engine,constructor_)
`template<class Sseq> explicit philox_engine(Sseq& q);
`
[10](#philox-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(∑ˆ’1j=0akp+jâ‹232j)mod2w[.](#philox-10.sentence-1)
All elements of sequence X are set to 0[.](#philox-10.sentence-2)
The value of i is set to n−1[.](#philox-10.sentence-3)
[🔗](#lib:set_counter,philox_engine)
`void set_counter(const array<result_type, n>& c);
`
[11](#philox-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L3371)
*Effects*: For j=0,…,n−1 sets Xj to Cn−ˆ’jmod2w[.](#philox-11.sentence-1)
The value of i is set to n−1[.](#philox-11.sentence-2)
[*Note [3](#philox-note-3)*:
The counter is the value Z introduced at the beginning of this subclause[.](#philox-11.sentence-3)
— *end note*]