std::seed_seq::generate
| template< class RandomIt > void generate( RandomIt begin, RandomIt end ); |
(seit C++11) | |
Generiert unverzerrte Seeds, indem der Ausgabebereich [begin, end) mit vorzeichenlosen 32-Bit-Integer-Werten füllt, basierend auf den (möglicherweise verzerrten) Seeds, die in v gespeichert sind.
- Wenn begin == end gilt, tut die Funktion nichts.
- Andernfalls werden Seeds gemäß dem nachfolgend beschriebenen Generierungsalgorithmus erzeugt.
Wenn std::iterator_traits<RandomIt>::value_type kein vorzeichenloser Integer-Typ ist oder seine Breite kleiner als 32 ist, ist das Programm schlecht geformt.
Wenn RandomIt nicht die Anforderungen an einen LegacyRandomAccessIterator erfüllt oder nicht mutable ist, ist das Verhalten undefiniert.
Inhalt |
[edit] Generierungsalgorithmus
Gegeben seien die folgenden Werte und Operationen
| Wert | Definition |
| z | v .size()
|
| n | end - begin |
| m | std::max(z + 1, n) |
| t | (n = 623) ? 11 : (n = 68) ? 7 : (n = 39) ? 5 : (n = 7) ? 3 : (n - 1) / 2 |
| p | (n - t) / 2 |
| q | p + t |
| Operation | Definition |
| xor | eingebauter bitweiser XOR |
| rshift | eingebauter bitweiser Rechts-Shift |
| T(x) | x xor (x rshift 27) |
Der Generierungsalgorithmus besteht aus den folgenden Schritten, wobei Si für begin[i % n] steht, Vi für v [i] steht
[0, m) werden die folgenden Operationen in Reihenfolge ausgeführt- z, wenn k=0
- (k mod n)+Vk-1, wenn 0<k⩽z
- k mod n, wenn z<k
.
.
.
[m, m + n) werden die folgenden Operationen in Reihenfolge ausgeführt.
.
.
[edit] Parameter
| begin, end | - | die Iteratoren, die den Ausgabebereich bezeichnen |
[edit] Ausnahmen
Wirft nur die Ausnahmen, die von den Operationen auf RandomIt für begin und end geworfen werden.
[edit] Hinweise
Der Generierungsalgorithmus ist an die Initialisierungssequenz des Mersenne-Twister-Generators von Makoto Matsumoto und Takuji Nishimura angepasst und integriert die Verbesserungen von Mutsuo Saito aus dem Jahr 2007.
[edit] Beispiel
#include <algorithm> #include <cassert> #include <cstdint> #include <iostream> #include <random> // Prototyping the main part of std::seed_seq... struct seed_seq { std::vector<std::uint32_t> v; seed_seq(std::initializer_list<std::uint32_t> const il) : v{il} {} template<typename RandomIt> void generate(RandomIt first, RandomIt last) { if (first == last) return; // // Assuming v = {1, 2, 3, 4, 5} and distance(first, last) == 10. // // Step 1: fill with 0x8b8b8b8b // seeds = {2341178251, 2341178251, 2341178251, 2341178251, 2341178251, // 2341178251, 2341178251, 2341178251, 2341178251, 2341178251} // std::fill(first, last, 0x8b8b8b8b); // // Step 2: // n = 10, s = 5, t = 3, p = 3, q = 6, m = 10 // const std::uint32_t n = last - first; const std::uint32_t s = v.size(); const std::uint32_t t = (n < 7) ? (n - 1) / 2 : (n < 39) ? 3 : (n < 68) ? 5 : (n < 623) ? 7 : 11; const std::uint32_t p = (n - t) / 2; const std::uint32_t q = p + t; const std::uint32_t m = std::max(s + 1, n); // // First iteration, k = 0; r1 = 1371501266, r2 = 1371501271 // // seeds = {1371501271, 2341178251, 2341178251, 3712679517, 2341178251, // 2341178251, 3712679522, 2341178251, 2341178251, 2341178251} // // Iterations from k = 1 to k = 5 (r2 = r1 + k % n + v[k - 1]) // // r1 = 2786190137, 3204727651, 4173325571, 1979226628, 401983366 // r2 = 2786190139, 3204727655, 4173325577, 1979226636, 401983376 // // seeds = {3350727907, 3188173515, 3204727655, 4173325577, 1979226636, // 401983376, 3591037797, 2811627722, 1652921976, 2219536532} // // Iterations from k = 6 to k = 9 (r2 = r1 + k % n) // // r1 = 2718637909, 1378394210, 2297813071, 1608643617 // r2 = 2718637915, 1378394217, 2297813079, 1608643626 // // seeds = { 434154821, 1191019290, 3237041891, 1256752498, 4277039715, // 2010627002, 2718637915, 1378394217, 2297813079, 1608643626} // auto begin_mod = [first, n](std::uint32_t u) -> decltype(*first)& { return first[u % n]; // i.e. begin[x] is taken modulo n }; auto T = [](std::uint32_t x) { return x ^ (x >> 27); }; for (std::uint32_t k = 0, r1, r2; k < m; ++k) { r1 = 1664525 * T(begin_mod(k) ^ begin_mod(k + p) ^ begin_mod(k - 1)); r2 = (k == 0) ? r1 + s : (k <= s) ? r1 + k % n + v[k - 1] : r1 + k % n; begin_mod(k + p) += r1; begin_mod(k + q) += r2; begin_mod(k) = r2; } // // Step 3 // iterations from k = 10 to k = 19, using ^= to modify the output // // r1 = 1615303485, 3210438310, 893477041, 2884072672, 1918321961, // r2 = 1615303485, 3210438309, 893477039, 2884072669, 1918321957 // // seeds = { 303093272, 3210438309, 893477039, 2884072669, 1918321957, // 1117182731, 1772877958, 2669970405, 3182737656, 4094066935} // // r1 = 423054846, 46783064, 3904109085, 1534123446, 1495905687 // r2 = 423054841, 46783058, 3904109078, 1534123438, 1495905678 // // seeds = { 4204997637, 4246533866, 1856049002, 1129615051, 690460811, // 1075771511, 46783058, 3904109078, 1534123438, 1495905678} // for (std::uint32_t k = m, r3, r4; k < m + n; ++k) { r3 = 1566083941 * T(begin_mod(k) + begin_mod(k + p) + begin_mod(k - 1)); r4 = r3 - k % n; begin_mod(k+p) ^= r3; begin_mod(k+q) ^= r4; begin_mod(k) = r4; } } }; int main() { const auto input = std::initializer_list<std::uint32_t>{1, 2, 3, 4, 5}; const auto output_size = 10; // using std version of seed_seq std::seed_seq seq(input); std::vector<std::uint32_t> seeds(output_size); seq.generate(seeds.begin(), seeds.end()); for (const std::uint32_t n : seeds) std::cout << n << '\n'; // using custom version of seed_seq seed_seq seq2(input); std::vector<std::uint32_t> seeds2(output_size); seq2.generate(seeds2.begin(), seeds2.end()); assert(seeds == seeds2); }
Ausgabe
4204997637 4246533866 1856049002 1129615051 690460811 1075771511 46783058 3904109078 1534123438 1495905678
[edit] Fehlerberichte
Die folgenden Verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.
| DR | angewendet auf | Verhalten wie veröffentlicht | Korrigiertes Verhalten |
|---|---|---|---|
| LWG 2180 | C++11 | seed_seq::generate wirft keine Ausnahmen |
sie kann Ausnahmen werfen |