Namensräume
Varianten
Aktionen

std::seed_seq::generate

Von cppreference.com
< cpp‎ | numeric‎ | random‎ | seed seq
 
 
 
 
 
template< class RandomIt >
void generate( RandomIt begin, RandomIt end );
(seit C++11)

Generiert unverzerrte Seeds, indem der Ausgabebereich [beginend) 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

1) Setzen Sie jedes Element des Ausgabebereichs auf den Wert 0x8b8b8b8b.
2) Für jede Ganzzahl k im Bereich [0m) werden die folgenden Operationen in Reihenfolge ausgeführt
1) Sei r1 gleich 1664525·T(Sk xor Sk+p xor Sk-1).
2) Sei r2 gleich r1+j, wobei j ist
  • z, wenn k=0
  • (k mod n)+Vk-1, wenn 0<k⩽z
  • k mod n, wenn z<k
3) Setzen Sie Sk+p auf (Sk+p+r1) mod 232
.
4) Setzen Sie Sk+q auf (Sk+q+r2) mod 232
.
5) Setzen Sie Sk auf r2 mod 232
.
3) Für jede Ganzzahl k im Bereich [mm + n) werden die folgenden Operationen in Reihenfolge ausgeführt
1) Sei r3 gleich 1566083941·T(Sk+Sk+p+Sk-1).
2) Sei r4 gleich r3-(k mod n).
3) Setzen Sie Sk+p auf (Sk+p xor r3) mod 232
.
4) Setzen Sie Sk+q auf (Sk+q xor r4) mod 232
.
5) Setzen Sie Sk auf r4 mod 232
.

[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