Namespaces
Variants

std::seed_seq:: generate

From cppreference.net
template < class RandomIt >
void generate ( RandomIt begin, RandomIt end ) ;
(seit C++11)

Erzeugen Sie unvoreingenommene Startwerte, indem Sie den Ausgabebereich [ begin , end ) mit 32-Bit-Ganzzahlen ohne Vorzeichen füllen, basierend auf den (möglicherweise voreingenommenen) Startwerten, die in v gespeichert sind.

  • Wenn begin == end true ist, tut nichts.
  • Andernfalls erzeugt Seeds gemäß dem unten beschriebenen Generierungsalgorithmus.

Wenn std:: iterator_traits < RandomIt > :: value_type kein vorzeichenloser Ganzzahltyp ist oder seine Breite weniger als 32 beträgt, ist das Programm fehlerhaft.

Falls RandomIt die Anforderungen an LegacyRandomAccessIterator nicht erfüllt oder nicht mutable ist, ist das Verhalten undefiniert.

Inhaltsverzeichnis

Generierungsalgorithmus

Gegeben 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 eingebaute bitweise XOR-Operation
rshift eingebaute bitweise Rechtsverschiebung
T(x) x xor (x rshift 27)

Der Generierungsalgorithmus besteht aus den folgenden Schritten, wobei S i für begin [ i % n ] steht, V i für v  [ i ] steht:

1) Setzen Sie jedes Element des Ausgabebereichs auf den Wert 0x8b8b8b8b .
2) Für jede ganze Zahl k im Bereich [ 0 , m ) , führt die folgenden Operationen in dieser Reihenfolge aus:
1) Sei r 1 gleich 1664525·T(S k xor S k+p xor S k-1 ) .
2) Sei r 2 gleich r 1 +j , wobei j definiert ist als:
  • z , falls k=0
  • (k mod n)+V k-1 , falls 0<k⩽z
  • k mod n , falls z<k
3) Setze S k+p auf (S k+p +r 1 ) mod 2 32
.
4) Setze S k+q auf (S k+q +r 2 ) mod 2 32
.
5) Setze S k auf r 2 mod 2 32
.
3) Für jede ganze Zahl k im Bereich [ m , m + n ) , führt die folgenden Operationen in dieser Reihenfolge aus:
1) Sei r 3 gleich 1566083941·T(S k +S k+p +S k-1 ) .
2) Sei r 4 gleich r 3 -(k mod n) .
3) Setze S k+p auf (S k+p xor r 3 ) mod 2 32
.
4) Setzen Sie S k+q auf (S k+q xor r 4 ) mod 2 32
.
5) Setze S k auf r 4 mod 2 32
.

Parameter

begin, end - die Iteratoren, die den Ausgabebereich bezeichnen

Ausnahmen

Wirft nur die Ausnahmen, die von den RandomIt Operationen auf begin und end geworfen werden.

Hinweise

Der Generierungsalgorithmus ist angepasst von der Initialisierungssequenz des Mersenne-Twister-Generators von Makoto Matsumoto und Takuji Nishimura , unter Einbeziehung der Verbesserungen, die von Mutsuo Saito im Jahr 2007 vorgenommen wurden.

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;
        //
        // Angenommen v = {1, 2, 3, 4, 5} und distance(first, last) == 10.
        //
        // Schritt 1: füllen mit 0x8b8b8b8b
        // seeds = {2341178251, 2341178251, 2341178251, 2341178251, 2341178251,
        //          2341178251, 2341178251, 2341178251, 2341178251, 2341178251}
        //
        std::fill(first, last, 0x8b8b8b8b);
        //
        // Schritt 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);
        //
        // Erste Iteration, k = 0; r1 = 1371501266, r2 = 1371501271
        //
        // seeds = {1371501271, 2341178251, 2341178251, 3712679517, 2341178251,
        //          2341178251, 3712679522, 2341178251, 2341178251, 2341178251}
        //
        // Iterationen von k = 1 bis 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}
        //
        // Iterationen von k = 6 bis 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]; // d.h. begin[x] wird modulo n genommen
        };
        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;
        }
        //
        // Schritt 3
        // Iterationen von k = 10 bis k = 19, unter Verwendung von ^= zur Modifikation der Ausgabe
        //
        // 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;
    // Verwendung der std-Version von 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';
    // Verwendung einer benutzerdefinierten Version von 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

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 ist nicht-werfend kann Ausnahmen werfen