std::seed_seq:: generate
|
template
<
class
RandomIt
>
void generate ( RandomIt begin, RandomIt end ) ; |
(自 C++11 起) | |
通过基于存储在
v
中的(可能存在偏差的)种子,向输出范围
[
begin
,
end
)
填充32位无符号整数值来生成无偏种子。
- 如果 begin == end 为 true ,则不执行任何操作。
- 否则,通过下文描述的生成算法生成种子。
如果 std:: iterator_traits < RandomIt > :: value_type 不是无符号整数类型,或其宽度小于32位,则程序非良构。
如果
RandomIt
不满足
LegacyRandomAccessIterator
的要求,或者它不是
mutable
的,则行为未定义。
目录 |
生成算法
给定以下数值与运算:
| 值 | 定义 |
| 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 |
| 操作 | 定义 |
| xor | 内置 按位异或 |
| rshift | 内置 按位右移 |
| T(x) | x xor (x rshift 27) |
生成算法包含以下步骤,其中
S
i
表示
begin
[
i
%
n
]
,
V
i
表示
v
[
i
]
:
[
0
,
m
)
内的每个整数
k
,按顺序执行以下操作:
- z ,若 k=0
- (k mod n)+V k-1 ,若 0<k⩽z
- k mod n ,若 z<k
。
。
。
[
m
,
m
+
n
)
内的每个整数
k
,按顺序执行以下操作:
。
。
。
参数
| begin, end | - | 表示输出范围的迭代器 |
异常
仅抛出对
begin
和
end
进行
RandomIt
操作时抛出的异常。
注释
生成算法改编自 松本真和西村拓士 提出的梅森旋转生成器初始化序列,并融合了 斋藤睦夫于2007年 实现的改进方案。
示例
#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] 取模 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
缺陷报告
以下行为变更缺陷报告被追溯应用于先前发布的C++标准。
| 缺陷报告 | 适用范围 | 发布时行为 | 正确行为 |
|---|---|---|---|
| LWG 2180 | C++11 |
seed_seq::generate
不抛出异常
|
可能抛出异常 |