std::seed_seq::generate
template< class RandomIt > void generate( RandomIt begin, RandomIt end ); |
(C++11 起) | |
以基于最初提供于此 seed_seq
构造函数的无符号整数值 i
,0 ≤ i < 232
填充范围 [
begin,
end)
。产生的值分布在整个 32 位范围,即使初值有强偏差。
使用下列算法(改编自松本真与西村拓士发明的梅森缠绕器生成器,加以斋藤睦夫于 2007 的改进工作)。
- 若 begin == end 则不做任何事。否则,
- 首先,设置输出范围的每个元素为值 0x8b8b8b8b。
- 按照下列算法变换输出范围的元素:
对于 k = 0,..., m - 1
其中 m = max(s + 1, n)
而 n = end - begin
而 s = v.size()
而 v 是保有最初为此 seed_seq
对象的构造函数所提供的值的私有容器,
- begin[k + p] += r1
- begin[k + q] += r2
- begin[k] = r2,
其中 p = (n - t) / 2
而 q = p + t
而 t = (n >= 623) ? 11 : (n >= 68) ? 7 : (n >= 39) ? 5 : (n >= 7) ? 3 : (n - 1) / 2
而 r1 = 1664525 * T(begin[k] ^ begin[k + p] ^ begin[k − 1])
而 T(x) = x ^ (x >> 27)
而若 k == 0 则 r2 = r1 + s,若 0 < k <= s 则 r2 = r1 + k % n + v[k - 1],若 k > s 则 r2 = r1 + k % n。
对于 k = m,..., m + n - 1,
- begin[k + p] ^= r3
- begin[k + q] ^= r4
- begin[k] = r4
其中 r3 = 1566083941 * T(begin[k] + begin[k + p] + begin[k - 1])
而 r4 = r3 - k % n
其中,所有计算均以 modulo 232
进行,并且以 modulo n 取输出范围的索引(begin[x])。
参数
begin, end | - | 可变随机访问迭代器,其 std::iterator_traits<>::value_type 为适合存储 32 位值的无符号整数类型 |
类型要求 | ||
-RandomIt 必须满足老式随机访问迭代器 (LegacyRandomAccessIterator) 。
|
返回值
无,写入结果到 [
begin,
end)
范围。
异常
仅若 begin 和 end 上的操作抛出才抛异常。
示例
#include <algorithm> #include <cassert> #include <cstdint> #include <iostream> #include <random> // 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; // // 假定 v = {1,2,3,4,5} 且 distance(first, last) == 10。 // // 步骤 1:以 0x8b8b8b8b 填充 // seeds = {2341178251, 2341178251, 2341178251, 2341178251, 2341178251, // 2341178251, 2341178251, 2341178251, 2341178251, 2341178251 } // std::fill(first, last, 0x8b8b8b8b); // // 步骤 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); // // 首次迭代,k = 0;r1 = 1371501266,r2 = 1371501271 // // seeds = {1371501271, 2341178251, 2341178251, 3712679517, 2341178251, // 2341178251, 3712679522, 2341178251, 2341178251, 2341178251 } // // 从 k = 1 到 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 } // // 从 k = 6 到 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]; // 即 begin[x] 按 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; } // // 步骤 3 // 从 k = 10 到 k = 19 迭代,用 ^= 修改输出 // // 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; // 使用 std 版本的 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'; // 使用自定义版本的 seed_seq seed_seq seq2(input); std::vector<std::uint32_t> seeds2(output_size); seq2.generate(seeds2.begin(), seeds2.end()); assert(seeds == seeds2); }
输出:
4204997637 4246533866 1856049002 1129615051 690460811 1075771511 46783058 3904109078 1534123438 1495905678