647 lines
27 KiB
Markdown
647 lines
27 KiB
Markdown
[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.4 Random 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.4 Random 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.5 Random 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.2 Class 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=(âkâ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 wâr bits of Xiân with
|
||
the lower r bits of Xi+1ân to obtain an unsigned integer value Y[.](#mers-2.1.sentence-1)
|
||
|
||
- [(2.2)](#mers-2.2)
|
||
|
||
With α=aâ(Ybitand1),
|
||
set Xi to Xi+mâ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 Xân to valuemod2w[.](#mers-6.sentence-1)
|
||
|
||
Then, iteratively for i=1ân,â¦,â1, sets Xi to
|
||
[fâ(Xiâ1xor(Xiâ1rshift(wâ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 nâk,
|
||
invokes q.generate(a+0, a+nâk) and then, iteratively for i=ân,â¦,â1,
|
||
sets Xi to (âkâ1j=0ak(i+n)+jâ232j)mod2w[.](#mers-8.sentence-1)
|
||
|
||
Finally,
|
||
if the most significant wâr bits of Xân are zero,
|
||
and if each of the other resulting Xi is 0,
|
||
changes Xâ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 0â¤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âsâXiârâ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)=(aâxi)modb,
|
||
where b is of the form mrâms+1 and a=bâ(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 (ânâ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 (âkâ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:=ânâ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.4 Random 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(âpâ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â1â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*]
|