RandX 1.4.3
基于 xoshiro/xoroshiro 算法族的纯头文件伪随机数生成器库
载入中...
搜索中...
未找到
RandX.hpp
浏览该文件的文档.
1//----------------------------------------------------------------------------------------
2//
3// RandX.hpp — 基于 Xoshiro 的伪随机数生成器封装库(C++23)
4//
5// 原始算法:David Blackman & Sebastiano Vigna (http://prng.di.unimi.it/)
6// 原始 C++ 封装:Ryo Suzuki (https://github.com/Reputeless/Xoshiro-cpp)
7//
8//========================================================================================
9//
10// 快速上手
11//
12// #include "RandX.hpp"
13//
14// // 最简用法:直接调用便捷函数(内部使用线程局部 Xoshiro256StarStar)
15// int dice = RandX::RandInt(1, 6); // [1, 6] 闭区间整数
16// double coin = RandX::RandReal(); // [0.0, 1.0) 浮点数
17// bool flag = RandX::RandBool(0.3); // 30% 概率为 true
18//
19// std::vector<int> v = {10, 20, 30, 40};
20// auto& elem = RandX::RandElement(v); // 随机取一个元素
21//
22// 扩展 API
23//
24// auto sample = RandX::RandSample(v, 2); // 无放回抽样 2 个
25// auto perm = RandX::RandPermutation(10); // [0,10) 随机排列
26// auto token = RandX::RandString(16); // 16 位随机字符串
27// auto uuid = RandX::RandUUID(); // UUID v4
28// auto byte = RandX::RandBits<8>(); // [0, 256) 随机整数
29// auto exp = RandX::RandExp(2.0); // 指数分布 λ=2
30// auto poi = RandX::RandPoisson(5.0); // 泊松分布 μ=5
31//
32// 手动管理引擎
33//
34// // 用真随机种子创建引擎
35// RandX::Xoshiro256StarStar rng{ RandX::RandomSeed() };
36//
37// // 指定引擎的便捷函数重载
38// int val = RandX::RandInt(rng, 0, 99);
39//
40// // 配合标准库 distribution 使用(满足 UniformRandomBitGenerator)
41// std::normal_distribution<double> norm(0.0, 1.0);
42// double sample = norm(rng);
43//
44// 多流并行
45//
46// auto s0 = RandX::MakeStreamEngine<RandX::Xoshiro256StarStar>(0);
47// auto s1 = RandX::MakeStreamEngine<RandX::Xoshiro256StarStar>(1);
48// // 各流间隔 2^128 步,互不重叠
49//
50// 编译期随机(constexpr)
51//
52// constexpr int v = RandX::RandIntCE(0, 100);
53// constexpr auto shuffled = RandX::ShuffledArray<int, 5>({1,2,3,4,5});
54//
55// 序列化 / 反序列化(保存和恢复状态)
56//
57// auto state = rng.serialize();
58// rng.deserialize(state);
59//
60// 跳跃(并行计算中生成不重叠子序列)
61//
62// rng.jump(); // 等价于前进 2^128 步(xoshiro256 系列)
63// rng.longJump(); // 等价于前进 2^192 步
64//
65// 跳过指定次数
66//
67// rng.discard(1000); // 跳过 1000 个输出
68//
69// 引擎选择指南
70//
71// 引擎 输出 周期 状态 适用场景
72// ─────────────────────────────────────────────────────────────
73// Xoshiro256StarStar 64-bit 2^256-1 32B 通用首选,统计质量最优
74// Xoroshiro128StarStar 64-bit 2^128-1 16B 内存受限,统计更优
75// Xoshiro128StarStar 32-bit 2^128-1 16B 32 位平台,统计更优
76// Xoroshiro64StarStar 32-bit 2^64-1 8B 极端内存受限
77// SplitMix64 64-bit 2^64 8B 种子扩展 / 哈希,非通用 PRNG
78// SFC64 64-bit >= 2^64 32B 速度极快,通过 PractRand
79// RomuDuoJr 64-bit >= 2^51 16B 极简极快,非关键模拟
80// ChaCha20 64-bit 无周期 48B+ 密码学安全 CSPRNG(RFC 8439)
81//
82// ⚠️ 安全声明
83// 本库的 xoshiro/xoroshiro/SFC64/RomuDuoJr 引擎均非 CSPRNG。
84// 状态可从输出逆推,不可用于密码/密钥/会话 token 等安全场景。
85// 此类场景请使用 ChaCha20 引擎或 SecureRandomBytes()。
86//
87//----------------------------------------------------------------------------------------
88
89# pragma once
90# include <cmath>
91# include <cstdint>
92# include <array>
93# include <limits>
94# include <concepts>
95# include <random>
96# include <algorithm>
97# include <bit>
98# include <cassert>
99# include <type_traits>
100# include <ranges>
101# include <string>
102# include <string_view>
103# include <unordered_set>
104# include <vector>
105# include <stdexcept>
106# include <chrono> // std::chrono(RandomSeed 时间戳兜底用)
107# include <atomic> // std::atomic(RandomSeed 兜底计数)
108# include <functional>// std::hash(RandomSeed 线程 Hash)
109# include <thread> // std::this_thread(RandomSeed 线程 ID)
110# include <ios> // std::ios_base::failbit(流状态标志完整定义)
111# include <istream> // std::basic_istream(operator>> 所需完整类型)
112# include <ostream> // std::basic_ostream(operator<< 所需完整类型)
113# if defined(_MSC_VER) && (defined(__x86_64__) || defined(_M_X64))
114# include <immintrin.h>
115# include <intrin.h>
116# endif
117// ── A3 跨平台 OS 熵源头文件(条件包含) ──
118# if defined(_WIN32) && __has_include(<bcrypt.h>)
119// bcrypt.h 依赖 <windows.h> 提供的 ULONG/NTSTATUS 等类型(MSVC 和 MinGW 均需)
120// NOMINMAX 阻止 <windows.h> 定义 min/max 宏(与引擎的 min()/max() 方法冲突)
121# ifndef WIN32_LEAN_AND_MEAN
122# define WIN32_LEAN_AND_MEAN
123# endif
124# ifndef NOMINMAX
125# define NOMINMAX
126# endif
127# include <windows.h>
128# include <bcrypt.h>
129# pragma comment(lib, "bcrypt.lib") // 仅 MSVC 生效
130// MinGW 不支持 #pragma comment(lib),须手动添加 -lbcrypt 链接选项
131# if(defined(__MINGW32__) || defined(__MINGW64__)) && !defined(RANDX_SUPPRESS_LINK_HINT)
132# pragma message("RandX: MinGW 需手动链接 bcrypt(编译命令添加 -lbcrypt)")
133# endif
134# elif defined(__linux__) && __has_include(<sys/random.h>)
135# include <sys/random.h>
136# include <cerrno>
137# elif defined(__APPLE__)
138# include <TargetConditionals.h>
139# if TARGET_OS_IPHONE
140# if __has_include(<Security/SecRandom.h>)
141# include <Security/SecRandom.h>
142# endif
143# elif __has_include(<Security/Security.h>)
144# include <Security/Security.h>
145# endif
146# endif
147# include <cstring> // std::memcpy(std::random_device 回退路径用)
148
149namespace RandX
150{
151 // 生成器的默认种子值
152 inline constexpr std::uint64_t DefaultSeed = 1234567890ULL;
153
154 // 将给定的 uint32 值 `i` 转换为 [0.0f, 1.0f) 范围内的 32 位浮点数
155 template <std::same_as<std::uint32_t> Uint32>
156 [[nodiscard]]
157 inline constexpr float FloatFromBits(Uint32 i) noexcept;
158
159 // 将给定的 uint64 值 `i` 转换为 [0.0, 1.0) 范围内的 64 位浮点数
160 template <std::same_as<std::uint64_t> Uint64>
161 [[nodiscard]]
162 inline constexpr double DoubleFromBits(Uint64 i) noexcept;
163
164 // ── 引擎基础设施(提前定义,供 EngineBase CRTP 基类使用) ──
165 namespace detail
166 {
167 [[nodiscard]]
168 inline constexpr std::uint64_t RotL(const std::uint64_t x, const int s) noexcept
169 {
170 return std::rotl(x, s);
171 }
172
173 [[nodiscard]]
174 inline constexpr std::uint32_t RotL(const std::uint32_t x, const int s) noexcept
175 {
176 return std::rotl(x, s);
177 }
178
179 // 检测状态数组是否全零(全零是 xoshiro/xoroshiro 的吸收态)
180 template <std::size_t N>
181 [[nodiscard]]
182 inline constexpr bool IsAllZero(const std::array<std::uint64_t, N>& state) noexcept
183 {
184 for (const auto& s : state) { if (s != 0) return false; }
185 return true;
186 }
187
188 template <std::size_t N>
189 [[nodiscard]]
190 inline constexpr bool IsAllZero(const std::array<std::uint32_t, N>& state) noexcept
191 {
192 for (const auto& s : state) { if (s != 0) return false; }
193 return true;
194 }
195
196 template <typename State>
197 [[nodiscard]]
198 inline constexpr bool IsValidState(const State& state) noexcept
199 {
200 return !IsAllZero(state);
201 }
202 }
203
207
217 {
218 public:
219
220 using state_type = std::uint64_t;
221 using result_type = std::uint64_t;
222
225 [[nodiscard]]
226 explicit constexpr SplitMix64(state_type state = DefaultSeed) noexcept;
227
230 template <class SeedSeq>
231 requires (!std::same_as<std::remove_cvref_t<SeedSeq>, SplitMix64>)
232 [[nodiscard]]
233 explicit constexpr SplitMix64(SeedSeq& seq);
234
237 constexpr result_type operator()() noexcept;
238
241 constexpr void discard(unsigned long long n) noexcept;
242
246 template <std::size_t N>
247 [[nodiscard]]
248 constexpr std::array<std::uint64_t, N> generateSeedSequence() noexcept;
249
252 [[nodiscard]]
253 static constexpr result_type min() noexcept;
254
257 [[nodiscard]]
258 static constexpr result_type max() noexcept;
259
263 [[nodiscard]]
264 constexpr state_type serialize() const noexcept;
265
269 constexpr void deserialize(state_type state) noexcept;
270
271 friend auto operator <=>(const SplitMix64&, const SplitMix64&) = default;
272
273 private:
274
275 state_type m_state;
276 };
277
278 // ── EngineBase CRTP 基类 ──
279 // 为数组状态引擎提供公共接口:min/max/discard/serialize/比较/构造/jumpPoly
280 // SplitMix64(标量状态)和 ChaCha20(CSPRNG)不继承此基类
281 namespace detail
282 {
283 template <class Derived, class ResultType, std::size_t N>
285 {
286 using result_type = ResultType;
287 using state_type = std::array<ResultType, N>;
288
289 // --- 公共接口 ---
290
291 [[nodiscard]]
292 static constexpr result_type min() noexcept
293 {
294 return std::numeric_limits<result_type>::lowest();
295 }
296
297 [[nodiscard]]
298 static constexpr result_type max() noexcept
299 {
300 return std::numeric_limits<result_type>::max();
301 }
302
303 constexpr void discard(unsigned long long z) noexcept
304 {
305 for (unsigned long long i = 0; i < z; ++i)
306 static_cast<Derived*>(this)->operator()();
307 }
308
309 [[nodiscard]]
310 constexpr state_type serialize() const noexcept
311 {
312 return s_;
313 }
314
315 constexpr void deserialize(const state_type& s) noexcept
316 {
317 s_ = s;
318 if (IsAllZero(s_))
319 {
320 s_[0] = static_cast<ResultType>(1);
321 }
322 assert(!IsAllZero(s_) && "absorbing all-zero state");
323 }
324
325 // C++23: defaulted 三路比较(保留 ==, !=, <, >, <=, >= 全套)
326 friend auto operator<=>(const EngineBase&, const EngineBase&) = default;
327
328 protected:
329
330 static constexpr int Bits = static_cast<int>(sizeof(ResultType) * 8);
331
332 EngineBase() = default;
333
334 // State 构造(用户直接传入,包含 Release/Debug 全零状态静默修正)
335 explicit constexpr EngineBase(const state_type& state) noexcept
336 : s_(state)
337 {
338 if (IsAllZero(s_))
339 {
340 s_[0] = static_cast<ResultType>(1);
341 }
342 assert(!IsAllZero(s_) && "absorbing all-zero state");
343 }
344
345 // SeedSeq 构造(零状态修正,Release 安全)
346 template <class SeedSeq>
347 requires (!std::same_as<std::remove_cvref_t<SeedSeq>, state_type>
348 && !std::same_as<std::remove_cvref_t<SeedSeq>, Derived>)
349 explicit constexpr EngineBase(SeedSeq& seq)
350 {
351 if constexpr (sizeof(result_type) == 8)
352 {
353 std::array<std::uint32_t, N * 2> raw;
354 seq.generate(raw.begin(), raw.end());
355 for (std::size_t i = 0; i < N; ++i)
356 s_[i] = (static_cast<result_type>(raw[2 * i]) << 32) | raw[2 * i + 1];
357 }
358 else
359 {
360 std::array<std::uint32_t, N> raw;
361 seq.generate(raw.begin(), raw.end());
362 for (std::size_t i = 0; i < N; ++i)
363 s_[i] = static_cast<result_type>(raw[i]);
364 }
365 if (IsAllZero(s_)) s_[0] = 1;
366 }
367
368 // 单值播种(SplitMix64 扩展,等价于 generateSeedSequence<N>)
369 explicit constexpr EngineBase(std::uint64_t seed) noexcept
370 {
371 SplitMix64 sm{ seed };
372 for (std::size_t i = 0; i < N; ++i)
373 s_[i] = static_cast<result_type>(sm());
374 if (IsAllZero(s_)) s_[0] = 1;
375 }
376
377 // jump 多项式通用实现(constexpr,供 MakeStreamEngine 编译期调用)
378 template <std::size_t K>
379 constexpr void jumpPoly(const ResultType (&poly)[K]) noexcept
380 {
381 std::array<ResultType, N> acc{};
382 for (std::size_t i = 0; i < K; ++i)
383 for (int b = 0; b < Bits; ++b)
384 {
385 if (poly[i] & (ResultType{ 1 } << b))
386 for (std::size_t j = 0; j < N; ++j)
387 acc[j] ^= s_[j];
388 static_cast<Derived*>(this)->operator()();
389 }
390 s_ = acc;
391 }
392
394 };
395 }
396
406 : public detail::EngineBase<Xoshiro256StarStar, std::uint64_t, 4>
407 {
409 public:
410
411 using typename Base::result_type;
412 using typename Base::state_type;
413
415 constexpr Xoshiro256StarStar() noexcept : Base(DefaultSeed) {}
416
419 [[nodiscard]]
420 explicit constexpr Xoshiro256StarStar(std::uint64_t seed) noexcept
421 : Base(seed) {}
422
425 template <class SeedSeq>
426 requires (!std::same_as<std::remove_cvref_t<SeedSeq>, Xoshiro256StarStar>)
427 [[nodiscard]]
428 explicit constexpr Xoshiro256StarStar(SeedSeq& seq)
429 : Base(seq) {}
430
433 [[nodiscard]]
434 explicit constexpr Xoshiro256StarStar(state_type state) noexcept
435 : Base(state) {}
436
439 constexpr result_type operator()() noexcept;
440
444 constexpr void jump() noexcept;
445
449 constexpr void longJump() noexcept;
450 };
451
461 : public detail::EngineBase<Xoroshiro128StarStar, std::uint64_t, 2>
462 {
464 public:
465
466 using typename Base::result_type;
467 using typename Base::state_type;
468
470 constexpr Xoroshiro128StarStar() noexcept : Base(DefaultSeed) {}
471
474 [[nodiscard]]
475 explicit constexpr Xoroshiro128StarStar(std::uint64_t seed) noexcept
476 : Base(seed) {}
477
480 template <class SeedSeq>
481 requires (!std::same_as<std::remove_cvref_t<SeedSeq>, Xoroshiro128StarStar>)
482 [[nodiscard]]
483 explicit constexpr Xoroshiro128StarStar(SeedSeq& seq)
484 : Base(seq) {}
485
488 [[nodiscard]]
489 explicit constexpr Xoroshiro128StarStar(state_type state) noexcept
490 : Base(state) {}
491
494 constexpr result_type operator()() noexcept;
495
499 constexpr void jump() noexcept;
500
504 constexpr void longJump() noexcept;
505 };
506
516 : public detail::EngineBase<Xoshiro128StarStar, std::uint32_t, 4>
517 {
519 public:
520
521 using typename Base::result_type;
522 using typename Base::state_type;
523
525 constexpr Xoshiro128StarStar() noexcept : Base(DefaultSeed) {}
526
529 [[nodiscard]]
530 explicit constexpr Xoshiro128StarStar(std::uint64_t seed) noexcept
531 : Base(seed) {}
532
535 template <class SeedSeq>
536 requires (!std::same_as<std::remove_cvref_t<SeedSeq>, Xoshiro128StarStar>)
537 [[nodiscard]]
538 explicit constexpr Xoshiro128StarStar(SeedSeq& seq)
539 : Base(seq) {}
540
543 [[nodiscard]]
544 explicit constexpr Xoshiro128StarStar(state_type state) noexcept
545 : Base(state) {}
546
549 constexpr result_type operator()() noexcept;
550
554 constexpr void jump() noexcept;
555
559 constexpr void longJump() noexcept;
560 };
561
571 : public detail::EngineBase<Xoroshiro64StarStar, std::uint32_t, 2>
572 {
574 public:
575
576 using typename Base::result_type;
577 using typename Base::state_type;
578
580 constexpr Xoroshiro64StarStar() noexcept : Base(DefaultSeed) {}
581
584 [[nodiscard]]
585 explicit constexpr Xoroshiro64StarStar(std::uint64_t seed) noexcept
586 : Base(seed) {}
587
590 template <class SeedSeq>
591 requires (!std::same_as<std::remove_cvref_t<SeedSeq>, Xoroshiro64StarStar>)
592 [[nodiscard]]
593 explicit constexpr Xoroshiro64StarStar(SeedSeq& seq)
594 : Base(seq) {}
595
598 [[nodiscard]]
599 explicit constexpr Xoroshiro64StarStar(state_type state) noexcept
600 : Base(state) {}
601
604 constexpr result_type operator()() noexcept;
605 };
606
615 class SFC64
616 : public detail::EngineBase<SFC64, std::uint64_t, 4>
617 {
619 public:
620
621 using typename Base::result_type;
622 using typename Base::state_type;
623
625 constexpr SFC64() noexcept : SFC64(DefaultSeed) {}
626
629 [[nodiscard]]
630 explicit constexpr SFC64(std::uint64_t seed) noexcept;
631
634 template <class SeedSeq>
635 requires (!std::same_as<std::remove_cvref_t<SeedSeq>, SFC64>)
636 [[nodiscard]]
637 explicit constexpr SFC64(SeedSeq& seq);
638
641 [[nodiscard]]
642 explicit constexpr SFC64(state_type state) noexcept
643 : Base(state) {}
644
647 constexpr result_type operator()() noexcept;
648 };
649
659 : public detail::EngineBase<RomuDuoJr, std::uint64_t, 2>
660 {
662 public:
663
664 using typename Base::result_type;
665 using typename Base::state_type;
666
668 constexpr RomuDuoJr() noexcept : Base(DefaultSeed) {}
669
672 [[nodiscard]]
673 explicit constexpr RomuDuoJr(std::uint64_t seed) noexcept
674 : Base(seed) {}
675
678 template <class SeedSeq>
679 requires (!std::same_as<std::remove_cvref_t<SeedSeq>, RomuDuoJr>)
680 [[nodiscard]]
681 explicit constexpr RomuDuoJr(SeedSeq& seq)
682 : Base(seq) {}
683
686 [[nodiscard]]
687 explicit constexpr RomuDuoJr(state_type state) noexcept
688 : Base(state) {}
689
692 constexpr result_type operator()() noexcept;
693 };
694
695 // ── 全 PRNG 引擎 TLS 可平凡析构(Trivially Destructible)编译期静态断言 ──
696 static_assert(std::is_trivially_destructible_v<Xoshiro256StarStar>, "Xoshiro256StarStar must be trivially destructible for safe TLS.");
697 static_assert(std::is_trivially_destructible_v<Xoroshiro128StarStar>, "Xoroshiro128StarStar must be trivially destructible for safe TLS.");
698 static_assert(std::is_trivially_destructible_v<Xoshiro128StarStar>, "Xoshiro128StarStar must be trivially destructible for safe TLS.");
699 static_assert(std::is_trivially_destructible_v<Xoroshiro64StarStar>, "Xoroshiro64StarStar must be trivially destructible for safe TLS.");
700 static_assert(std::is_trivially_destructible_v<SplitMix64>, "SplitMix64 must be trivially destructible for safe TLS.");
701 static_assert(std::is_trivially_destructible_v<SFC64>, "SFC64 must be trivially destructible for safe TLS.");
702 static_assert(std::is_trivially_destructible_v<RomuDuoJr>, "RomuDuoJr must be trivially destructible for safe TLS.");
703
716 {
717 public:
718
719 using result_type = std::uint64_t;
720
721 ChaCha20(const ChaCha20&) = delete;
722 ChaCha20& operator=(const ChaCha20&) = delete;
723 ChaCha20(ChaCha20&& other) noexcept;
724 ChaCha20& operator=(ChaCha20&& other) noexcept;
725 ~ChaCha20() noexcept;
726
729 ChaCha20();
730
734 [[nodiscard]]
735 explicit ChaCha20(std::uint64_t seed);
736
744 ChaCha20(const std::uint8_t* key, std::size_t keyLen,
745 const std::uint8_t* nonce, std::size_t nonceLen,
746 std::uint32_t counter = 0);
747
750 result_type operator()();
751
754 void discard(unsigned long long n);
755
758 void reseed();
759
762 [[nodiscard]]
763 static constexpr result_type min() noexcept { return 0; }
764
767 [[nodiscard]]
768 static constexpr result_type max() noexcept { return UINT64_MAX; }
769
770 // 不提供:serialize/deserialize, operator<</>>, jump/longJump(CSPRNG 安全约束)
771
772 private:
773
774 std::array<std::uint32_t, 12> m_state; // key(8) + counter(1) + nonce(3),常数省略(generateBlock 时补齐)
775 std::array<std::uint8_t, 64> m_buffer; // 当前 block 的字节缓存
776 std::size_t m_bufferPos; // 缓存消费位置 [0, 64),==64 时触发新 block
777 std::uint64_t m_bytesSinceReseed; // 自上次 reseed 以来输出的字节数
778 bool m_autoReseed{ false }; // 是否在满 1MB 后自动从 OS 熵重新播种(仅默认无参构造函数启用)
779
780 void generateBlock(); // 跑一次 ChaCha20 block 函数填充 m_buffer
781 void reseedIfNecessary(); // m_bytesSinceReseed >= 阈值时自动 reseed
782 };
783
784 // ── sizeof 守卫:防止引擎 ABI 意外变化 ──
785 static_assert(sizeof(Xoshiro256StarStar) == 32);
786 static_assert(sizeof(Xoroshiro128StarStar) == 16);
787 static_assert(sizeof(Xoshiro128StarStar) == 16);
788 static_assert(sizeof(Xoroshiro64StarStar) == 8);
789 static_assert(sizeof(SFC64) == 32);
790 static_assert(sizeof(RomuDuoJr) == 16);
791 static_assert(sizeof(SplitMix64) == 8);
792}
793
795
796namespace RandX
797{
798 template <std::same_as<std::uint32_t> Uint32>
799 inline constexpr float FloatFromBits(const Uint32 i) noexcept
800 {
801 return (i >> 8) * 0x1.0p-24f;
802 }
803
804 template <std::same_as<std::uint64_t> Uint64>
805 inline constexpr double DoubleFromBits(const Uint64 i) noexcept
806 {
807 return (i >> 11) * 0x1.0p-53;
808 }
809
810 namespace detail
811 {
812 // 安全擦除内存(volatile 防止编译器死存储消除)
813 static void SecureWipe(void* ptr, std::size_t len) noexcept
814 {
815 volatile auto* p = static_cast<volatile std::uint8_t*>(ptr);
816 while (len--) *p++ = 0;
817 }
818
819 // 尝试使用 RDRAND 获取 64 位硬件随机数
820 [[nodiscard]]
821 inline bool HardwareRand64(std::uint64_t& out) noexcept
822 {
823#if defined(__x86_64__) || defined(_M_X64)
824 #if defined(__RDRND__)
825 unsigned long long result;
826 if (__builtin_ia32_rdrand64_step(&result))
827 {
828 out = result;
829 return true;
830 }
831 #elif defined(_MSC_VER)
832 int cpuInfo[4] = {0};
833 __cpuid(cpuInfo, 1);
834 if ((cpuInfo[2] & (1 << 30)) != 0)
835 {
836 unsigned long long result = 0;
837 if (_rdrand64_step(&result))
838 {
839 out = result;
840 return true;
841 }
842 }
843 #endif
844#endif
845 (void)out;
846 return false;
847 }
848
849 // ── A3 跨平台 OS 密码学熵源 ──
850 // 用 OS 密码学 API 填充 [buf, buf+n) 字节;成功返回 true。
851 // 平台优先级:Windows BCryptGenRandom → Linux getrandom → macOS SecRandomCopyBytes → std::random_device 兜底
852 // 注:getrandom 可能短读,内部循环直至填满;BCryptGenRandom/SecRandomCopyBytes 一次填满
853 [[nodiscard]]
854 inline bool GetOsEntropyBytes(void* buf, std::size_t n) noexcept
855 {
856 if (n == 0) return true;
857 auto* p = static_cast<std::uint8_t*>(buf);
858
859# if defined(_WIN32) && __has_include(<bcrypt.h>)
860 // Windows: BCryptGenRandom(分块处理 >4GB 时的 ULONG 截断)
861 // NTSTATUS >= 0 即 NT_SUCCESS(不能 == 0,正向 informational code 也属成功)
862 std::size_t filled = 0;
863 while (filled < n)
864 {
865 const ULONG chunkSize = static_cast<ULONG>((std::min)(n - filled, static_cast<std::size_t>((std::numeric_limits<ULONG>::max)())));
866 if (::BCryptGenRandom(nullptr, p + filled, chunkSize, BCRYPT_USE_SYSTEM_PREFERRED_RNG) < 0)
867 {
868 return false;
869 }
870 filled += chunkSize;
871 }
872 return true;
873
874# elif defined(__linux__) && __has_include(<sys/random.h>)
875 // Linux: getrandom(循环处理短读与 EINTR)
876 std::size_t filled = 0;
877 while (filled < n)
878 {
879 const ssize_t ret = ::getrandom(p + filled, n - filled, 0);
880 if (ret < 0)
881 {
882 if (errno == EINTR) continue; // 被信号打断,重试
883 return false; // ENOSYS/EFAULT 等不可恢复错误
884 }
885 if (ret == 0) return false;
886 filled += static_cast<std::size_t>(ret);
887 }
888 return true;
889
890# elif defined(__APPLE__) && __has_include(<Security/Security.h>)
891 // macOS: SecRandomCopyBytes(一次调用填满)
892 return (::SecRandomCopyBytes(kSecRandomDefault, n, p) == errSecSuccess);
893
894# else
895 // 无可用 OS 密码学熵源 → 返回 false,SecureRandomBytes 将抛出异常
896 // 非安全场景的播种请使用 RandomSeed()(含 random_device → 时间戳回退链)
897 (void)p; (void)n;
898 return false;
899# endif
900 }
901
902 // 返回 true 当且仅当编译期检测到 OS 密码学熵源 API(BCryptGenRandom/getrandom/SecRandomCopyBytes)
903 // 返回 false 表示当前运行在 std::random_device 兜底路径,ChaCha20() 默认构造不保证密码学安全
904 [[nodiscard]]
905 inline bool HasCryptoGradeOsEntropy() noexcept
906 {
907# if (defined(_WIN32) && __has_include(<bcrypt.h>)) || (defined(__linux__) && __has_include(<sys/random.h>)) || (defined(__APPLE__) && __has_include(<Security/Security.h>))
908 return true;
909# else
910 return false;
911# endif
912 }
913
914 // ── A4 ChaCha20 常数与辅助 ──
915 // ChaCha20 常数 "expand 32-byte k"(RFC 8439 §2.3)
916 inline constexpr std::uint32_t ChaCha20Constants[4] = {
917 0x61707865u, 0x3320646eu, 0x79622d32u, 0x6b206574u
918 };
919 // 参考 NIST SP 800-90A reseed_interval 概念(SP 800-90A 涵盖 Hash/HMAC/CTR_DRBG,不含 ChaCha20;
920 // 此处借用其"周期性强制 reseed 提供前向安全"思想,取保守阈值)
921 inline constexpr std::uint64_t ChaCha20ReseedThreshold = 1ULL << 20; // 1 MB
922
923 // ChaCha20 quarter-round(仅 add/xor/rotl,常时间友好)
924 static void ChaCha20QuarterRound(std::uint32_t& a, std::uint32_t& b,
925 std::uint32_t& c, std::uint32_t& d) noexcept
926 {
927 a += b; d ^= a; d = RotL(d, 16);
928 c += d; b ^= c; b = RotL(b, 12);
929 a += b; d ^= a; d = RotL(d, 8);
930 c += d; b ^= c; b = RotL(b, 7);
931 }
932
933 template <class Engine>
934 [[nodiscard]]
935 inline std::uint64_t Generate64Bits(Engine& engine)
936 {
937 if constexpr (sizeof(typename Engine::result_type) >= 8)
938 {
939 return static_cast<std::uint64_t>(engine());
940 }
941 else
942 {
943 const std::uint64_t lo = static_cast<std::uint64_t>(engine());
944 const std::uint64_t hi = static_cast<std::uint64_t>(engine());
945 return (hi << 32) | lo;
946 }
947 }
948
949 // 字符类型 concept(char/wchar_t/char8_t/char16_t/char32_t)
950 // char8_t 仅在 C++20+ 编译器下为基本类型,用特性检测宏条件启用
951 template <class T>
952 concept Character =
953 std::same_as<T, char> ||
954 std::same_as<T, wchar_t> ||
955 std::same_as<T, char16_t> ||
956 std::same_as<T, char32_t>
957#if defined(__cpp_char8_t) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
958 || std::same_as<T, char8_t>
959#endif
960 ;
961
962 // 检测 state_type 是否为可索引容器(排除标量如 SplitMix64 的 uint64_t)
963 template <class S>
964 concept IndexableState = requires(const S& cs, S& s) {
965 { cs.size() } -> std::same_as<std::size_t>;
966 { s[std::size_t{}] } -> std::same_as<typename S::value_type&>;
967 };
968
969 // 可序列化引擎 concept(仅对 state_type 为容器类的引擎生效)
970 template <class E>
971 concept SerializableEngine = requires(const E& ce, E& e) {
972 { ce.serialize() } -> std::same_as<typename E::state_type>;
973 { e.deserialize(std::declval<typename E::state_type>()) } -> std::same_as<void>;
974 typename E::state_type;
976 };
977
986 template <class E>
987 concept JumpableEngine = requires(E& e) {
988 { e.jump() } -> std::same_as<void>;
989 };
990
1001 template <class E>
1003
1004 // 迭代器可填充约束(RandFill 用)
1005 template <class It, class T>
1006 concept RandFillable = std::output_iterator<It, T>
1007 && (std::integral<T> || std::floating_point<T>);
1008
1009 }
1010
1011 // ========================================================================
1012 // 流式运算符 operator<< / operator>>
1013 // 仅对 state_type 为可索引容器类的引擎生效(SerializableEngine concept)
1014 // SplitMix64(state_type = uint64_t 标量)不支持,由 IndexableState 排除
1015 // 格式兼容 std::random_engine:空格分隔的十进制数序列
1016 // ========================================================================
1017
1018 // 流式输出引擎状态
1019 template <class CharT, class Traits, detail::SerializableEngine Engine>
1020 std::basic_ostream<CharT, Traits>&
1021 operator<<(std::basic_ostream<CharT, Traits>& os, const Engine& engine)
1022 {
1023 typename std::basic_ostream<CharT, Traits>::sentry ok(os);
1024 if (!ok) return os;
1025
1026 const auto flags = os.flags();
1027 os.setf(std::ios_base::dec, std::ios_base::basefield);
1028
1029 auto state = engine.serialize();
1030 for (std::size_t i = 0; i < state.size(); ++i)
1031 {
1032 if (i != 0) os << ' ';
1033 os << state[i];
1034 }
1035
1036 os.flags(flags);
1037 return os;
1038 }
1039
1040 // 流式恢复引擎状态
1041 // 若解析失败(读取不足、流错误或状态非法/全零),setstate(failbit) 且引擎状态保持不变
1042 // (与 std::random_engine 一致:先读取到临时 state,全部成功才 deserialize)
1043 template <class CharT, class Traits, detail::SerializableEngine Engine>
1044 std::basic_istream<CharT, Traits>&
1045 operator>>(std::basic_istream<CharT, Traits>& is, Engine& engine)
1046 {
1047 typename std::basic_istream<CharT, Traits>::sentry ok(is);
1048 if (!ok) return is;
1049
1050 const auto flags = is.flags();
1051 is.setf(std::ios_base::dec, std::ios_base::basefield);
1052 is.setf(std::ios_base::skipws);
1053
1054 typename Engine::state_type state{};
1055 std::size_t i = 0;
1056 for (; i < state.size() && is; ++i)
1057 is >> state[i];
1058
1059 if (i == state.size() && is && detail::IsValidState(state))
1060 {
1061 engine.deserialize(state);
1062 }
1063 else
1064 {
1065 is.setstate(std::ios_base::failbit);
1066 }
1067
1068 is.flags(flags);
1069 return is;
1070 }
1071
1073 //
1074 // SplitMix64
1075 //
1076 inline constexpr SplitMix64::SplitMix64(const state_type state) noexcept
1077 : m_state(state) {}
1078
1079 template <class SeedSeq>
1080 requires (!std::same_as<std::remove_cvref_t<SeedSeq>, SplitMix64>)
1081 inline constexpr SplitMix64::SplitMix64(SeedSeq& seq)
1082 {
1083 std::array<std::uint32_t, 2> seeds;
1084 seq.generate(seeds.begin(), seeds.end());
1085 m_state = (static_cast<std::uint64_t>(seeds[0]) << 32) | seeds[1];
1086 }
1087
1089 {
1090 std::uint64_t z = (m_state += 0x9e3779b97f4a7c15);
1091 z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
1092 z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
1093 return z ^ (z >> 31);
1094 }
1095
1096 template <std::size_t N>
1097 inline constexpr std::array<std::uint64_t, N> SplitMix64::generateSeedSequence() noexcept
1098 {
1099 std::array<std::uint64_t, N> seeds = {};
1100
1101 for (auto& seed : seeds)
1102 {
1103 seed = operator()();
1104 }
1105
1106 return seeds;
1107 }
1108
1109 inline constexpr SplitMix64::result_type SplitMix64::min() noexcept
1110 {
1111 return std::numeric_limits<result_type>::lowest();
1112 }
1113
1114 inline constexpr SplitMix64::result_type SplitMix64::max() noexcept
1115 {
1116 return std::numeric_limits<result_type>::max();
1117 }
1118
1119 inline constexpr SplitMix64::state_type SplitMix64::serialize() const noexcept
1120 {
1121 return m_state;
1122 }
1123
1124 inline constexpr void SplitMix64::deserialize(const state_type state) noexcept
1125 {
1126 m_state = state;
1127 }
1128
1129 inline constexpr void SplitMix64::discard(const unsigned long long n) noexcept
1130 {
1131 for (unsigned long long i = 0; i < n; ++i) { operator()(); }
1132 }
1133
1135 //
1136 // xoshiro256**
1137 //
1139 {
1140 const std::uint64_t result = detail::RotL(s_[1] * 5, 7) * 9;
1141 const std::uint64_t t = s_[1] << 17;
1142 s_[2] ^= s_[0];
1143 s_[3] ^= s_[1];
1144 s_[1] ^= s_[2];
1145 s_[0] ^= s_[3];
1146 s_[2] ^= t;
1147 s_[3] = detail::RotL(s_[3], 45);
1148 return result;
1149 }
1150
1151 inline constexpr void Xoshiro256StarStar::jump() noexcept
1152 {
1153 static constexpr std::uint64_t p[] = {
1154 0x180ec6d33cfd0aba, 0xd5a61266f0c9392c,
1155 0xa9582618e03fc9aa, 0x39abdc4529b1661c };
1156 jumpPoly(p);
1157 }
1158
1159 inline constexpr void Xoshiro256StarStar::longJump() noexcept
1160 {
1161 static constexpr std::uint64_t p[] = {
1162 0x76e15d3efefdcbbf, 0xc5004e441c522fb3,
1163 0x77710069854ee241, 0x39109bb02acbe635 };
1164 jumpPoly(p);
1165 }
1166
1168 //
1169 // xoroshiro128**
1170 //
1172 {
1173 const std::uint64_t s0 = s_[0];
1174 std::uint64_t s1 = s_[1];
1175 const std::uint64_t result = detail::RotL(s0 * 5, 7) * 9;
1176 s1 ^= s0;
1177 s_[0] = detail::RotL(s0, 24) ^ s1 ^ (s1 << 16);
1178 s_[1] = detail::RotL(s1, 37);
1179 return result;
1180 }
1181
1182 inline constexpr void Xoroshiro128StarStar::jump() noexcept
1183 {
1184 static constexpr std::uint64_t p[] = { 0xdf900294d8f554a5, 0x170865df4b3201fc };
1185 jumpPoly(p);
1186 }
1187
1188 inline constexpr void Xoroshiro128StarStar::longJump() noexcept
1189 {
1190 static constexpr std::uint64_t p[] = { 0xd2a98b26625eee7b, 0xdddf9b1090aa7ac1 };
1191 jumpPoly(p);
1192 }
1193
1195 //
1196 // xoshiro128**
1197 //
1199 {
1200 const std::uint32_t result = detail::RotL(s_[1] * 5, 7) * 9;
1201 const std::uint32_t t = s_[1] << 9;
1202 s_[2] ^= s_[0];
1203 s_[3] ^= s_[1];
1204 s_[1] ^= s_[2];
1205 s_[0] ^= s_[3];
1206 s_[2] ^= t;
1207 s_[3] = detail::RotL(s_[3], 11);
1208 return result;
1209 }
1210
1211 inline constexpr void Xoshiro128StarStar::jump() noexcept
1212 {
1213 static constexpr std::uint32_t p[] = { 0x8764000bu, 0xf542d2d3u, 0x6fa035c3u, 0x77f2db5bu };
1214 jumpPoly(p);
1215 }
1216
1217 inline constexpr void Xoshiro128StarStar::longJump() noexcept
1218 {
1219 static constexpr std::uint32_t p[] = { 0xb523952eu, 0x0b6f099fu, 0xccf5a0efu, 0x1c580662u };
1220 jumpPoly(p);
1221 }
1222
1224 //
1225 // xoroshiro64**
1226 //
1228 {
1229 const std::uint32_t s0 = s_[0];
1230 std::uint32_t s1 = s_[1];
1231
1232 const std::uint32_t result = detail::RotL(s0 * 0x9E3779BB, 5) * 5;
1233
1234 s1 ^= s0;
1235 s_[0] = detail::RotL(s0, 26) ^ s1 ^ (s1 << 9);
1236 s_[1] = detail::RotL(s1, 13);
1237
1238 return result;
1239 }
1240
1241
1243 //
1244 // SFC64 (Small Fast Counter)
1245 //
1246 inline constexpr SFC64::SFC64(const std::uint64_t seed) noexcept
1247 : Base()
1248 {
1249 // 使用 SplitMix64 播种 + 12 轮预热
1250 SplitMix64 sm{ seed };
1251 s_[0] = sm();
1252 s_[1] = sm();
1253 s_[2] = sm();
1254 s_[3] = 1;
1255 // 全零状态会导致输出可预测,强制修正
1256 if ((s_[0] | s_[1] | s_[2]) == 0) s_[0] = 0x9E3779B97F4A7C15ULL;
1257 for (int i = 0; i < 12; ++i) { operator()(); }
1258 }
1259
1260 template <class SeedSeq>
1261 requires (!std::same_as<std::remove_cvref_t<SeedSeq>, SFC64>)
1262 inline constexpr SFC64::SFC64(SeedSeq& seq)
1263 : Base()
1264 {
1265 std::array<std::uint32_t, 8> seeds;
1266 seq.generate(seeds.begin(), seeds.end());
1267 s_[0] = (static_cast<std::uint64_t>(seeds[0]) << 32) | seeds[1];
1268 s_[1] = (static_cast<std::uint64_t>(seeds[2]) << 32) | seeds[3];
1269 s_[2] = (static_cast<std::uint64_t>(seeds[4]) << 32) | seeds[5];
1270 s_[3] = 1;
1271 // 全零状态会导致输出可预测,强制修正
1272 if ((s_[0] | s_[1] | s_[2]) == 0) s_[0] = 0x9E3779B97F4A7C15ULL;
1273 // 与种子构造函数一致:12 轮预热
1274 for (int i = 0; i < 12; ++i) { operator()(); }
1275 }
1276
1277 inline constexpr SFC64::result_type SFC64::operator()() noexcept
1278 {
1279 const std::uint64_t tmp = s_[0] + s_[1] + s_[3]++;
1280 s_[0] = s_[1] ^ (s_[1] >> 11);
1281 s_[1] = s_[2] + (s_[2] << 3);
1282 s_[2] = detail::RotL(s_[2], 24) + tmp;
1283 return tmp;
1284 }
1285
1287 //
1288 // RomuDuoJr
1289 //
1291 {
1292 const std::uint64_t xp = s_[0];
1293 s_[0] = 15241094284759029579ULL * s_[1];
1294 s_[1] = detail::RotL(s_[1] - xp, 27);
1295 return xp;
1296 }
1297
1299 //
1300 // 便捷工具函数
1301 //
1302
1306 [[nodiscard]]
1307 inline std::uint64_t RandomSeed()
1308 {
1309 std::uint64_t hw;
1310 if (detail::HardwareRand64(hw))
1311 return hw;
1312 if (detail::GetOsEntropyBytes(&hw, sizeof(hw)))
1313 return hw;
1314 std::random_device rd;
1315 try
1316 {
1317 return (static_cast<std::uint64_t>(rd()) << 32) | rd();
1318 }
1319 catch (...)
1320 {
1321 // 最终兜底:多维熵源(非密码学,仅保证 RandomSeed 永不抛异常,且防止 MSVC 15.6ms 时钟窗口下并发种子碰撞)
1322 const auto t1 = std::chrono::high_resolution_clock::now().time_since_epoch().count();
1323 const auto t2 = std::chrono::steady_clock::now().time_since_epoch().count();
1324 const auto threadId = std::hash<std::thread::id>{}(std::this_thread::get_id());
1325 static std::atomic<std::uint64_t> counter{0};
1326 std::uint64_t stackVar = 0;
1327 const std::uint64_t addr = reinterpret_cast<std::uint64_t>(&stackVar);
1328
1329 const std::uint64_t rawSeed = static_cast<std::uint64_t>(t1) ^ static_cast<std::uint64_t>(t2)
1330 ^ threadId ^ addr ^ counter.fetch_add(1, std::memory_order_relaxed);
1331 SplitMix64 sm{ rawSeed };
1332 return sm();
1333 }
1334 }
1335
1336 // 默认线程局部引擎,使用 RandomSeed() 播种(含 RDRAND → OS API → random_device → 时间戳回退链)
1337 [[nodiscard]]
1339 {
1340 thread_local Xoshiro256StarStar engine{ RandomSeed() };
1341 return engine;
1342 }
1343
1346 {
1348 }
1349
1351
1355
1360 inline void SecureRandomBytes(void* buf, std::size_t n)
1361 {
1362 if (n == 0) return;
1363 if (!detail::GetOsEntropyBytes(buf, n))
1364 throw std::runtime_error("SecureRandomBytes: OS entropy source failed");
1365 }
1366
1369 [[nodiscard]]
1370 inline std::uint64_t SecureSeed()
1371 {
1372 std::uint64_t seed;
1373 SecureRandomBytes(&seed, sizeof(seed));
1374 return seed;
1375 }
1376
1380 [[nodiscard]]
1381 inline bool IsOsCryptoEntropyAvailable() noexcept
1382 {
1384 }
1385
1387 //
1388 // ChaCha20 (RFC 8439) — CSPRNG 引擎实现
1389 //
1390 // 状态矩阵布局(16 × uint32,常数省略存于 m_state[0..11]):
1391 // 0 1 2 3 "expa" "nd 3" "2-by" "te k" ← 常数(generateBlock 时补齐)
1392 // 4 5 6 7 key[0] key[1] key[2] key[3] ← m_state[0..3]
1393 // 8 9 10 11 key[4] key[5] key[6] key[7] ← m_state[4..7]
1394 // 12 13 14 15 ctr nonce[0] nonce[1] nonce[2]← m_state[8..11]
1395 //
1396 // 生成流程:operator() → reseedIfNecessary → (缓存耗尽时)generateBlock → 取 8 字节
1397 //
1398
1399 inline ChaCha20::ChaCha20(ChaCha20&& other) noexcept
1400 : m_state(other.m_state),
1401 m_buffer(other.m_buffer),
1402 m_bufferPos(other.m_bufferPos),
1403 m_bytesSinceReseed(other.m_bytesSinceReseed),
1404 m_autoReseed(other.m_autoReseed)
1405 {
1406 detail::SecureWipe(other.m_state.data(), sizeof(other.m_state));
1407 detail::SecureWipe(other.m_buffer.data(), sizeof(other.m_buffer));
1408 other.reseed();
1409 }
1410
1411 inline ChaCha20& ChaCha20::operator=(ChaCha20&& other) noexcept
1412 {
1413 if (this != &other)
1414 {
1415 detail::SecureWipe(m_state.data(), sizeof(m_state));
1416 detail::SecureWipe(m_buffer.data(), sizeof(m_buffer));
1417
1418 m_state = other.m_state;
1419 m_buffer = other.m_buffer;
1420 m_bufferPos = other.m_bufferPos;
1421 m_bytesSinceReseed = other.m_bytesSinceReseed;
1422 m_autoReseed = other.m_autoReseed;
1423
1424 detail::SecureWipe(other.m_state.data(), sizeof(other.m_state));
1425 detail::SecureWipe(other.m_buffer.data(), sizeof(other.m_buffer));
1426 other.reseed();
1427 }
1428 return *this;
1429 }
1430
1431 inline ChaCha20::~ChaCha20() noexcept
1432 {
1433 detail::SecureWipe(m_state.data(), sizeof(m_state));
1434 detail::SecureWipe(m_buffer.data(), sizeof(m_buffer));
1435 }
1436
1437 // 构造方式 1:从 OS 熵自动播种(密码学安全,默认)
1439 : m_state{}, m_buffer{}, m_bufferPos(64), m_bytesSinceReseed(0), m_autoReseed(true)
1440 {
1441 reseed(); // 从 OS 熵获取 key + nonce,重置 counter
1442 }
1443
1444 // 构造方式 2:显式种子(仅测试/复现,非密码学安全)
1445 // 用 SplitMix64 将 64-bit 种子扩展为 32 字节 key + 12 字节 nonce
1446 inline ChaCha20::ChaCha20(const std::uint64_t seed)
1447 : m_state{}, m_buffer{}, m_bufferPos(64), m_bytesSinceReseed(0), m_autoReseed(false)
1448 {
1449 SplitMix64 sm{ seed };
1450 // key: 前 4 次 SplitMix64 输出,每次 8 字节按小端序拆为 2 个 uint32
1451 for (int i = 0; i < 4; ++i)
1452 {
1453 const std::uint64_t v = sm();
1454 m_state[i * 2] = static_cast<std::uint32_t>(v);
1455 m_state[i * 2 + 1] = static_cast<std::uint32_t>(v >> 32);
1456 }
1457 // nonce: 第 5 次输出(8 字节)+ 第 6 次输出低 4 字节(丢弃高 4 字节)
1458 {
1459 const std::uint64_t v5 = sm();
1460 m_state[9] = static_cast<std::uint32_t>(v5);
1461 m_state[10] = static_cast<std::uint32_t>(v5 >> 32);
1462 }
1463 m_state[11] = static_cast<std::uint32_t>(sm());
1464 m_state[8] = 0; // counter 初值 = 0
1465 }
1466
1467 // 构造方式 3:直接指定 key + nonce + counter
1468 inline ChaCha20::ChaCha20(const std::uint8_t* key, std::size_t keyLen,
1469 const std::uint8_t* nonce, std::size_t nonceLen,
1470 const std::uint32_t counter)
1471 : m_state{}, m_buffer{}, m_bufferPos(64), m_bytesSinceReseed(0), m_autoReseed(false)
1472 {
1473 if (keyLen != 32)
1474 throw std::invalid_argument("ChaCha20: key must be 32 bytes");
1475 if (nonceLen != 12)
1476 throw std::invalid_argument("ChaCha20: nonce must be 12 bytes");
1477 // key → m_state[0..7](小端序)
1478 for (int i = 0; i < 8; ++i)
1479 {
1480 m_state[i] = static_cast<std::uint32_t>(key[i * 4])
1481 | (static_cast<std::uint32_t>(key[i * 4 + 1]) << 8)
1482 | (static_cast<std::uint32_t>(key[i * 4 + 2]) << 16)
1483 | (static_cast<std::uint32_t>(key[i * 4 + 3]) << 24);
1484 }
1485 // nonce → m_state[9..11](小端序)
1486 for (int i = 0; i < 3; ++i)
1487 {
1488 m_state[9 + i] = static_cast<std::uint32_t>(nonce[i * 4])
1489 | (static_cast<std::uint32_t>(nonce[i * 4 + 1]) << 8)
1490 | (static_cast<std::uint32_t>(nonce[i * 4 + 2]) << 16)
1491 | (static_cast<std::uint32_t>(nonce[i * 4 + 3]) << 24);
1492 }
1493 m_state[8] = counter; // counter
1494 }
1495
1496 // 生成一个 ChaCha20 block(64 字节)填充 m_buffer
1497 inline void ChaCha20::generateBlock()
1498 {
1499 if (m_state[8] == 0xFFFFFFFFU)
1500 {
1501 throw std::overflow_error("ChaCha20: 32-bit block counter overflow");
1502 }
1503
1504 // 构造完整 16-word 状态:常数 + key + counter + nonce
1505 std::array<std::uint32_t, 16> state{};
1506 state[0] = detail::ChaCha20Constants[0];
1507 state[1] = detail::ChaCha20Constants[1];
1508 state[2] = detail::ChaCha20Constants[2];
1509 state[3] = detail::ChaCha20Constants[3];
1510 for (int i = 0; i < 8; ++i) state[4 + i] = m_state[i]; // key
1511 state[12] = m_state[8]; // counter
1512 state[13] = m_state[9]; // nonce[0]
1513 state[14] = m_state[10]; // nonce[1]
1514 state[15] = m_state[11]; // nonce[2]
1515
1516 std::array<std::uint32_t, 16> working = state;
1517
1518 // 20 轮 = 10 次 double-round(列轮 + 对角轮)
1519 for (int i = 0; i < 10; ++i)
1520 {
1521 // 列轮 QR 顺序:(0,4,8,12) (1,5,9,13) (2,6,10,14) (3,7,11,15)
1522 detail::ChaCha20QuarterRound(working[0], working[4], working[8], working[12]);
1523 detail::ChaCha20QuarterRound(working[1], working[5], working[9], working[13]);
1524 detail::ChaCha20QuarterRound(working[2], working[6], working[10], working[14]);
1525 detail::ChaCha20QuarterRound(working[3], working[7], working[11], working[15]);
1526 // 对角轮 QR 顺序:(0,5,10,15) (1,6,11,12) (2,7,8,13) (3,4,9,14)
1527 detail::ChaCha20QuarterRound(working[0], working[5], working[10], working[15]);
1528 detail::ChaCha20QuarterRound(working[1], working[6], working[11], working[12]);
1529 detail::ChaCha20QuarterRound(working[2], working[7], working[8], working[13]);
1530 detail::ChaCha20QuarterRound(working[3], working[4], working[9], working[14]);
1531 }
1532
1533 // 加初始状态后按小端序输出 64 字节到 m_buffer
1534 for (int i = 0; i < 16; ++i)
1535 {
1536 const std::uint32_t v = working[i] + state[i];
1537 m_buffer[i * 4 + 0] = static_cast<std::uint8_t>(v);
1538 m_buffer[i * 4 + 1] = static_cast<std::uint8_t>(v >> 8);
1539 m_buffer[i * 4 + 2] = static_cast<std::uint8_t>(v >> 16);
1540 m_buffer[i * 4 + 3] = static_cast<std::uint8_t>(v >> 24);
1541 }
1542
1543 ++m_state[8]; // 递增 counter(2^20 字节阈值远早于 2^32 回绕,自动 reseed 防止复用)
1544 m_bufferPos = 0;
1545 }
1546
1547 // 自上次 reseed 以来输出字节数达到阈值时自动 reseed(前向安全)
1548 inline void ChaCha20::reseedIfNecessary()
1549 {
1550 if (m_autoReseed && m_bytesSinceReseed >= detail::ChaCha20ReseedThreshold)
1551 reseed();
1552 }
1553
1554 // 从 OS 熵重新播种:32 字节新 key + 12 字节新 nonce,重置 counter=0、缓存标记耗尽
1555 inline void ChaCha20::reseed()
1556 {
1557 std::array<std::uint8_t, 44> seed; // 32(key) + 12(nonce)
1558 SecureRandomBytes(seed.data(), seed.size());
1559 // key → m_state[0..7](小端序)
1560 for (int i = 0; i < 8; ++i)
1561 {
1562 m_state[i] = static_cast<std::uint32_t>(seed[i * 4])
1563 | (static_cast<std::uint32_t>(seed[i * 4 + 1]) << 8)
1564 | (static_cast<std::uint32_t>(seed[i * 4 + 2]) << 16)
1565 | (static_cast<std::uint32_t>(seed[i * 4 + 3]) << 24);
1566 }
1567 // nonce → m_state[9..11](小端序)
1568 for (int i = 0; i < 3; ++i)
1569 {
1570 m_state[9 + i] = static_cast<std::uint32_t>(seed[32 + i * 4])
1571 | (static_cast<std::uint32_t>(seed[32 + i * 4 + 1]) << 8)
1572 | (static_cast<std::uint32_t>(seed[32 + i * 4 + 2]) << 16)
1573 | (static_cast<std::uint32_t>(seed[32 + i * 4 + 3]) << 24);
1574 }
1575 m_state[8] = 0; // counter 重置
1576 m_bufferPos = 64; // 强制下次 operator() 触发新 block
1577 m_bytesSinceReseed = 0;
1578 detail::SecureWipe(seed.data(), seed.size()); // 擦除栈上密钥材料
1579 detail::SecureWipe(m_buffer.data(), m_buffer.size()); // 擦除旧 keystream
1580 }
1581
1582 // 生成一个 64-bit 随机数(从缓存取 8 字节,缓存耗尽时生成新 block)
1584 {
1585 reseedIfNecessary();
1586 if (m_bufferPos == 64)
1587 generateBlock();
1588 // 从缓存取 8 字节,小端序组装为 uint64_t
1589 std::uint64_t result = 0;
1590 for (int i = 0; i < 8; ++i)
1591 result |= static_cast<std::uint64_t>(m_buffer[m_bufferPos + i]) << (8 * i);
1592 m_bufferPos += 8;
1593 m_bytesSinceReseed += 8;
1594 return result;
1595 }
1596
1597 inline void ChaCha20::discard(const unsigned long long n)
1598 {
1599 for (unsigned long long i = 0; i < n; ++i) operator()();
1600 }
1601
1604 inline void Reseed(std::uint64_t seed)
1605 {
1607 }
1608
1610 inline void ReseedRandom()
1611 {
1613 }
1614
1616
1620
1625 template <std::integral T = int>
1626 [[nodiscard]]
1627 inline T RandInt(T min, T max)
1628 {
1629 return RandInt(DefaultEngine(), min, max);
1630 }
1631
1635 template <std::integral T = int>
1636 [[nodiscard]]
1637 inline T RandInt(T max)
1638 {
1639 assert(max >= T{0});
1640 return RandInt<T>(T{0}, max);
1641 }
1642
1647 template <std::floating_point T = double>
1648 [[nodiscard]]
1649 inline T RandReal(T min = T{0}, T max = T{1})
1650 {
1651 return RandReal(DefaultEngine(), min, max);
1652 }
1653
1657 template <std::floating_point T = double>
1658 [[nodiscard]]
1659 inline T RandCanonical() noexcept
1660 {
1662 }
1663
1665 [[nodiscard]]
1666 inline double RandCanonicalDouble() noexcept
1667 {
1668 return RandCanonical<double>();
1669 }
1670
1672 [[nodiscard]]
1673 inline float RandCanonicalFloat() noexcept
1674 {
1675 return RandCanonical<float>();
1676 }
1677
1681 [[nodiscard]]
1682 inline bool RandBool(double p = 0.5)
1683 {
1684 assert(std::isfinite(p) && p >= 0.0 && p <= 1.0);
1685 std::bernoulli_distribution dist(p);
1686 return dist(DefaultEngine());
1687 }
1688
1693 template <class Engine>
1694 [[nodiscard]]
1695 inline bool RandBool(Engine& engine, double p = 0.5)
1696 {
1697 assert(std::isfinite(p) && p >= 0.0 && p <= 1.0);
1698 std::bernoulli_distribution dist(p);
1699 return dist(engine);
1700 }
1701
1705 [[nodiscard]]
1706 inline bool RandBernoulli(double p = 0.5)
1707 {
1708 assert(p >= 0.0 && p <= 1.0);
1709 return RandBool(p);
1710 }
1711
1716 template <class Engine>
1717 [[nodiscard]]
1718 inline bool RandBernoulli(Engine& engine, double p = 0.5)
1719 {
1720 assert(p >= 0.0 && p <= 1.0);
1721 return RandBool(engine, p);
1722 }
1723
1729 template <detail::Character CharT>
1730 [[nodiscard]]
1731 inline CharT RandChar(CharT min, CharT max)
1732 {
1733 assert(min <= max);
1734 std::uniform_int_distribution<std::int64_t> dist(
1735 static_cast<std::int64_t>(min),
1736 static_cast<std::int64_t>(max));
1737 return static_cast<CharT>(dist(DefaultEngine()));
1738 }
1739
1743 template <detail::Character CharT = char>
1744 [[nodiscard]]
1745 inline CharT RandChar(CharT max)
1746 {
1747 return RandChar<CharT>(CharT{}, max);
1748 }
1749
1755 template <detail::Character CharT, class Engine>
1756 [[nodiscard]]
1757 inline CharT RandChar(Engine& engine, CharT min, CharT max)
1758 {
1759 assert(min <= max);
1760 std::uniform_int_distribution<std::int64_t> dist(
1761 static_cast<std::int64_t>(min),
1762 static_cast<std::int64_t>(max));
1763 return static_cast<CharT>(dist(engine));
1764 }
1765
1770 template <detail::Character CharT = char, class Engine>
1771 [[nodiscard]]
1772 inline CharT RandChar(Engine& engine, CharT max)
1773 {
1774 return RandChar<CharT>(engine, CharT{}, max);
1775 }
1776
1778
1782
1787 template <class Container>
1788 requires std::ranges::random_access_range<Container>
1789 [[nodiscard]]
1790 inline decltype(auto) RandElement(Container& c)
1791 {
1792 if (std::empty(c))
1793 throw std::invalid_argument("RandElement: empty container");
1794 return c[RandInt<std::size_t>(static_cast<std::size_t>(std::size(c) - 1))];
1795 }
1796
1801 template <class Container>
1802 requires std::ranges::random_access_range<Container>
1803 [[nodiscard]]
1804 inline std::ranges::range_value_t<Container> RandElement(Container&& c)
1805 {
1806 if (std::empty(c))
1807 throw std::invalid_argument("RandElement: empty container");
1808 return c[RandInt<std::size_t>(static_cast<std::size_t>(std::size(c) - 1))];
1809 }
1810
1816 template <std::random_access_iterator It>
1817 [[nodiscard]]
1818 inline It RandElement(It first, It last)
1819 {
1820 using Diff = std::iter_difference_t<It>;
1821 const Diff n = std::distance(first, last);
1822 if (n <= 0)
1823 throw std::invalid_argument("RandElement: empty range");
1824 return std::next(first, RandInt<Diff>(Diff{0}, n - 1));
1825 }
1826
1832 template <std::input_iterator It>
1833 requires (!std::random_access_iterator<It>)
1834 [[nodiscard]]
1835 inline std::iter_value_t<It> RandElement(It first, It last)
1836 {
1837 if (first == last)
1838 throw std::invalid_argument("RandElement: empty range");
1839 std::iter_value_t<It> selected = *first;
1840 ++first;
1841 for (std::iter_difference_t<It> i = 1; first != last; ++first, ++i)
1842 {
1843 if (RandInt<std::iter_difference_t<It>>(0, i) == 0)
1844 selected = *first;
1845 }
1846 return selected;
1847 }
1848
1854 template <std::random_access_iterator It, class Engine>
1855 [[nodiscard]]
1856 inline It RandElement(Engine& engine, It first, It last)
1857 {
1858 using Diff = std::iter_difference_t<It>;
1859 const Diff n = std::distance(first, last);
1860 if (n <= 0)
1861 throw std::invalid_argument("RandElement: empty range");
1862 return std::next(first, RandInt<Diff>(engine, Diff{0}, n - 1));
1863 }
1864
1870 template <std::input_iterator It, class Engine>
1871 requires (!std::random_access_iterator<It>)
1872 [[nodiscard]]
1873 inline std::iter_value_t<It> RandElement(Engine& engine, It first, It last)
1874 {
1875 if (first == last)
1876 throw std::invalid_argument("RandElement: empty range");
1877 std::iter_value_t<It> selected = *first;
1878 ++first;
1879 for (std::iter_difference_t<It> i = 1; first != last; ++first, ++i)
1880 {
1881 if (RandInt<std::iter_difference_t<It>>(engine, std::iter_difference_t<It>{0}, i) == 0)
1882 selected = *first;
1883 }
1884 return selected;
1885 }
1886
1887
1889
1893
1898 template <std::floating_point T = double>
1899 [[nodiscard]]
1900 inline T RandNormal(T mean = T{0}, T stddev = T{1})
1901 {
1902 if (!std::isfinite(mean) || !std::isfinite(stddev) || stddev <= T{0})
1903 throw std::invalid_argument("RandNormal: invalid mean or stddev");
1904 std::normal_distribution<T> dist(mean, stddev);
1905 return dist(DefaultEngine());
1906 }
1907
1913 template <class Engine, std::floating_point T = double>
1914 [[nodiscard]]
1915 inline T RandNormal(Engine& engine, T mean = T{0}, T stddev = T{1})
1916 {
1917 if (!std::isfinite(mean) || !std::isfinite(stddev) || stddev <= T{0})
1918 throw std::invalid_argument("RandNormal: invalid mean or stddev");
1919 std::normal_distribution<T> dist(mean, stddev);
1920 return dist(engine);
1921 }
1922
1925 template <std::ranges::random_access_range Container>
1926 inline void RandShuffle(Container&& c)
1927 {
1928 std::shuffle(c.begin(), c.end(), DefaultEngine());
1929 }
1930
1938 template <class It, class T>
1939 requires detail::RandFillable<It, T> && std::integral<T>
1940 inline void RandFill(It first, It last, T min, T max)
1941 {
1942 assert(min <= max);
1943 std::uniform_int_distribution<T> dist(min, max);
1944 for (; first != last; ++first)
1945 *first = dist(DefaultEngine());
1946 }
1947
1953 template <class It, std::floating_point T>
1954 requires std::output_iterator<It, T>
1955 inline void RandFill(It first, It last, T min, T max)
1956 {
1957 assert(min <= max);
1958 std::uniform_real_distribution<T> dist(min, max);
1959 for (; first != last; ++first)
1960 *first = dist(DefaultEngine());
1961 }
1962
1969 template <class It, class T, class Engine>
1970 requires detail::RandFillable<It, T> && std::integral<T>
1971 inline void RandFill(Engine& engine, It first, It last, T min, T max)
1972 {
1973 assert(min <= max);
1974 std::uniform_int_distribution<T> dist(min, max);
1975 for (; first != last; ++first)
1976 *first = dist(engine);
1977 }
1978
1985 template <class It, std::floating_point T, class Engine>
1986 requires std::output_iterator<It, T>
1987 inline void RandFill(Engine& engine, It first, It last, T min, T max)
1988 {
1989 assert(min <= max);
1990 std::uniform_real_distribution<T> dist(min, max);
1991 for (; first != last; ++first)
1992 *first = dist(engine);
1993 }
1994
2000 template <std::integral T = int>
2001 [[nodiscard]]
2002 inline std::vector<T> RandVector(T min, T max, std::size_t n)
2003 {
2004 assert(min <= max);
2005 std::vector<T> v;
2006 v.reserve(n);
2007 std::uniform_int_distribution<T> dist(min, max);
2008 auto& engine = DefaultEngine();
2009 for (std::size_t i = 0; i < n; ++i)
2010 v.push_back(dist(engine));
2011 return v;
2012 }
2013
2019 template <std::floating_point T = double>
2020 [[nodiscard]]
2021 inline std::vector<T> RandVector(T min, T max, std::size_t n)
2022 {
2023 assert(min <= max);
2024 std::vector<T> v;
2025 v.reserve(n);
2026 std::uniform_real_distribution<T> dist(min, max);
2027 auto& engine = DefaultEngine();
2028 for (std::size_t i = 0; i < n; ++i)
2029 v.push_back(dist(engine));
2030 return v;
2031 }
2032
2039 template <std::integral T = int, class Engine>
2040 [[nodiscard]]
2041 inline std::vector<T> RandVector(Engine& engine, T min, T max, std::size_t n)
2042 {
2043 assert(min <= max);
2044 std::vector<T> v;
2045 v.reserve(n);
2046 std::uniform_int_distribution<T> dist(min, max);
2047 for (std::size_t i = 0; i < n; ++i)
2048 v.push_back(dist(engine));
2049 return v;
2050 }
2051
2058 template <std::floating_point T = double, class Engine>
2059 [[nodiscard]]
2060 inline std::vector<T> RandVector(Engine& engine, T min, T max, std::size_t n)
2061 {
2062 assert(min <= max);
2063 std::vector<T> v;
2064 v.reserve(n);
2065 std::uniform_real_distribution<T> dist(min, max);
2066 for (std::size_t i = 0; i < n; ++i)
2067 v.push_back(dist(engine));
2068 return v;
2069 }
2070
2074 template <class WeightContainer>
2075 [[nodiscard]]
2076 inline typename WeightContainer::size_type RandWeighted(const WeightContainer& weights)
2077 {
2078 assert(!weights.empty() && std::all_of(weights.begin(), weights.end(), [](auto w) { return w >= 0; }) && std::any_of(weights.begin(), weights.end(), [](auto w) { return w > 0; }));
2079 using Size = typename WeightContainer::size_type;
2080 std::discrete_distribution<Size> dist(weights.begin(), weights.end());
2081 return dist(DefaultEngine());
2082 }
2083
2088 template <class Engine, class WeightContainer>
2089 [[nodiscard]]
2090 inline typename WeightContainer::size_type RandWeighted(Engine& engine, const WeightContainer& weights)
2091 {
2092 assert(!weights.empty() && std::all_of(weights.begin(), weights.end(), [](auto w) { return w >= 0; }) && std::any_of(weights.begin(), weights.end(), [](auto w) { return w > 0; }));
2093 using Size = typename WeightContainer::size_type;
2094 std::discrete_distribution<Size> dist(weights.begin(), weights.end());
2095 return dist(engine);
2096 }
2097
2101 template <class IntType>
2102 [[nodiscard]]
2103 inline IntType RandWeighted(std::discrete_distribution<IntType>& dist)
2104 {
2105 return dist(DefaultEngine());
2106 }
2107
2112 template <class Engine, class IntType>
2113 [[nodiscard]]
2114 inline IntType RandWeighted(Engine& engine, std::discrete_distribution<IntType>& dist)
2115 {
2116 return dist(engine);
2117 }
2118
2124 template <std::integral T, class Engine>
2125 [[nodiscard]]
2126 inline T RandInt(Engine& engine, T min, T max)
2127 {
2128 assert(min <= max);
2129 using DistType = std::conditional_t<(sizeof(T) < sizeof(short)),
2130 std::conditional_t<std::is_signed_v<T>, int, unsigned int>, T>;
2131 std::uniform_int_distribution<DistType> dist(static_cast<DistType>(min), static_cast<DistType>(max));
2132 return static_cast<T>(dist(engine));
2133 }
2134
2139 template <std::floating_point T, class Engine>
2140 [[nodiscard]]
2141 inline constexpr T RandCanonical(Engine& engine) noexcept
2142 {
2143 using ResultType = typename Engine::result_type;
2144 constexpr std::size_t Bits = sizeof(ResultType) * 8;
2145
2146 if constexpr (std::same_as<T, double>)
2147 {
2148 if constexpr (Bits >= 64)
2149 {
2150 const std::uint64_t r = static_cast<std::uint64_t>(engine());
2151 return static_cast<double>(r >> 11) * 0x1.0p-53;
2152 }
2153 else
2154 {
2155 const std::uint64_t high = static_cast<std::uint64_t>(engine());
2156 const std::uint64_t low = static_cast<std::uint64_t>(engine());
2157 const std::uint64_t r = (high << 32) | low;
2158 return static_cast<double>(r >> 11) * 0x1.0p-53;
2159 }
2160 }
2161 else if constexpr (std::same_as<T, float>)
2162 {
2163 if constexpr (Bits >= 64)
2164 {
2165 const std::uint64_t r = static_cast<std::uint64_t>(engine());
2166 return static_cast<float>(r >> 40) * 0x1.0p-24f;
2167 }
2168 else
2169 {
2170 const std::uint32_t r = static_cast<std::uint32_t>(engine());
2171 return static_cast<float>(r >> 8) * 0x1.0p-24f;
2172 }
2173 }
2174 else
2175 {
2176 return std::generate_canonical<T, std::numeric_limits<T>::digits>(engine);
2177 }
2178 }
2179
2185 template <std::floating_point T, class Engine>
2186 [[nodiscard]]
2187 inline T RandReal(Engine& engine, T min = T{0}, T max = T{1})
2188 {
2189 assert(std::isfinite(min) && std::isfinite(max) && min <= max);
2190 if (min == T{0} && max == T{1})
2191 {
2192 return RandCanonical<T>(engine);
2193 }
2194 std::uniform_real_distribution<T> dist(min, max);
2195 T val = dist(engine);
2196 if (val >= max) val = std::nextafter(max, min);
2197 return val;
2198 }
2199
2200
2201
2202 namespace detail
2203 {
2204 // 前向声明(定义见下方"编译期随机"节)
2205 [[nodiscard]]
2206 inline constexpr std::uint64_t BoundedRand(Xoshiro256StarStar& rng, std::uint64_t range) noexcept;
2207
2208 // RandSample 分支选择阈值:n·K < size 时用 hash-set(实测交叉点 n≈N/127,K=64 留 2× 裕度)
2209 inline constexpr std::uint64_t HashSetThresholdK = 64;
2210 }
2211
2213 //
2214 // RandChar / RandString 预设字符集
2215 //
2216 // 提供常用字符集枚举,避免手写 ASCII 范围或字符串。
2217 //
2218
2219 // 预设字符集枚举
2220 enum class CharSet
2221 {
2222 Alphanumeric, // [A-Za-z0-9] 62 个
2223 Alpha, // [A-Za-z] 52 个
2224 Lower, // [a-z] 26 个
2225 Upper, // [A-Z] 26 个
2226 Digit, // [0-9] 10 个
2227 Hex, // [0-9a-f] 16 个
2228 Printable, // [!-~] 94 个可打印 ASCII
2229 Base64, // [A-Za-z0-9+/] 64 个(RFC 4648 §4 标准变体)
2230 Base64UrlSafe, // [A-Za-z0-9-_] 64 个(RFC 4648 §5 URL-safe 变体)
2231 };
2232
2233 namespace detail
2234 {
2235 // 返回预设字符集的字符串视图(零拷贝,指向静态存储)
2236 [[nodiscard]]
2237 inline std::string_view CharSetString(CharSet cs) noexcept
2238 {
2239 switch (cs)
2240 {
2242 return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
2243 case CharSet::Alpha:
2244 return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
2245 case CharSet::Lower:
2246 return "abcdefghijklmnopqrstuvwxyz";
2247 case CharSet::Upper:
2248 return "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
2249 case CharSet::Digit:
2250 return "0123456789";
2251 case CharSet::Hex:
2252 return "0123456789abcdef";
2253 case CharSet::Printable:
2254 return "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
2255 case CharSet::Base64:
2256 return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
2258 return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
2259 }
2260 return "";
2261 }
2262 }
2263
2268 [[nodiscard]]
2269 inline char RandChar(CharSet cs)
2270 {
2271 const auto charset = detail::CharSetString(cs);
2272 if (charset.empty())
2273 throw std::invalid_argument("RandChar: charset is empty");
2274 auto& rng = DefaultEngine();
2275 std::uniform_int_distribution<std::size_t> dist(0, charset.size() - 1);
2276 return charset[dist(rng)];
2277 }
2278
2283 template <class Engine>
2284 [[nodiscard]]
2285 inline char RandChar(Engine& engine, CharSet cs)
2286 {
2287 const auto charset = detail::CharSetString(cs);
2288 if (charset.empty())
2289 throw std::invalid_argument("RandChar: charset is empty");
2290 std::uniform_int_distribution<std::size_t> dist(0, charset.size() - 1);
2291 return charset[dist(engine)];
2292 }
2293
2295 //
2296 // 扩展便捷 API
2297 //
2298
2303 template <std::ranges::random_access_range Container>
2304 [[nodiscard]]
2305 inline auto RandSample(const Container& c, typename Container::size_type n)
2306 {
2307 using T = typename Container::value_type;
2308 using Size = typename Container::size_type;
2309 std::vector<T> pool(c.begin(), c.end());
2310 const Size size = static_cast<Size>(pool.size());
2311 if (n >= size) return pool;
2312 auto& rng = DefaultEngine();
2313 for (Size i = 0; i < n; ++i)
2314 {
2315 std::uniform_int_distribution<Size> dist(i, size - 1);
2316 const Size j = dist(rng);
2317 auto tmp = std::move(pool[i]);
2318 pool[i] = std::move(pool[j]);
2319 pool[j] = std::move(tmp);
2320 }
2321 pool.resize(n);
2322 return pool;
2323 }
2324
2325 // ============================================================
2326 // RandSample 迭代器版
2327 // 路径 1:随机访问迭代器 —— hash-set / 索引数组双分支
2328 // 路径 2:输入迭代器 —— reservoir sampling (Algorithm R, i+1 修复)
2329 // ============================================================
2330
2336 // 路径 1:随机访问迭代器(hash-set / 索引数组双分支)
2337 template <std::random_access_iterator It>
2338 [[nodiscard]]
2339 inline std::vector<std::iter_value_t<It>>
2340 RandSample(It first, It last, std::iter_difference_t<It> n)
2341 {
2342 using Diff = std::iter_difference_t<It>;
2343 using T = std::iter_value_t<It>;
2344 const Diff size = std::distance(first, last);
2345 if (n <= 0 || size <= 0)
2346 return {};
2347 if (n >= size)
2348 return std::vector<T>(first, last);
2349
2350 auto& rng = DefaultEngine();
2351
2352 // 分支选择:n·K < size 时 hash-set 内存优(O(n));否则索引数组常数优(O(N))
2353 // 用 uint64_t 避免 n*K 溢出(n 是 iter_difference_t,可能 32 位)
2354 const auto sizeU = static_cast<std::uint64_t>(size);
2355 // 线性阈值:n·K < size 时用 hash-set(实测交叉点 n≈N/127,K=64 留 2× 裕度)
2356 if (static_cast<std::uint64_t>(n) * detail::HashSetThresholdK < sizeU)
2357 {
2358 // hash-set 分支:O(n) 内存,O(n) 期望时间
2359 std::unordered_set<Diff> selected;
2360 selected.reserve(static_cast<std::size_t>(n));
2361 std::vector<T> result;
2362 result.reserve(static_cast<std::size_t>(n));
2363 while (result.size() < static_cast<std::size_t>(n))
2364 {
2365 std::uniform_int_distribution<Diff> dist(Diff{0}, static_cast<Diff>(sizeU - 1));
2366 const Diff idx = dist(rng);
2367 if (selected.insert(idx).second)
2368 result.push_back(first[idx]);
2369 }
2370 return result;
2371 }
2372
2373 // 索引数组分支:O(N) 内存,O(N) 时间,无碰撞
2374 std::vector<Diff> indices(static_cast<std::size_t>(size));
2375 for (Diff i = 0; i < size; ++i)
2376 indices[static_cast<std::size_t>(i)] = i;
2377
2378 // Fisher-Yates 前 n 步:j ∈ [i, size-1]
2379 for (Diff i = 0; i < n; ++i)
2380 {
2381 std::uniform_int_distribution<Diff> dist(i, static_cast<Diff>(size - 1));
2382 const Diff j = dist(rng);
2383 std::swap(indices[static_cast<std::size_t>(i)],
2384 indices[static_cast<std::size_t>(j)]);
2385 }
2386
2387 std::vector<T> result;
2388 result.reserve(static_cast<std::size_t>(n));
2389 for (Diff i = 0; i < n; ++i)
2390 result.push_back(first[indices[static_cast<std::size_t>(i)]]);
2391 return result;
2392 }
2393
2399 // 路径 2:输入迭代器(reservoir sampling, Algorithm R, i+1 修复)
2400 template <std::input_iterator It>
2401 requires (!std::random_access_iterator<It>)
2402 [[nodiscard]]
2403 inline std::vector<std::iter_value_t<It>>
2404 RandSample(It first, It last, std::iter_difference_t<It> n)
2405 {
2406 using Diff = std::iter_difference_t<It>;
2407 using T = std::iter_value_t<It>;
2408 if (n <= 0)
2409 return {};
2410
2411 std::vector<T> reservoir;
2412 reservoir.reserve(static_cast<std::size_t>(n));
2413
2414 // 填满蓄水池
2415 Diff i = 0;
2416 for (; i < n && first != last; ++i, ++first)
2417 reservoir.push_back(*first);
2418
2419 if (first == last)
2420 return reservoir; // 元素不足 n,返回全部
2421
2422 // Algorithm R:第 i 个元素(i >= n,0-indexed)以 n/(i+1) 概率替换蓄水池随机位置
2423 // 关键:j ∈ [0, i](闭区间),uniform_int_distribution(0, i) 正好是 [0, i] 闭区间
2424 auto& rng = DefaultEngine();
2425 for (; first != last; ++i, ++first)
2426 {
2427 std::uniform_int_distribution<Diff> dist(Diff{0}, i);
2428 const Diff j = dist(rng);
2429 if (j < n)
2430 reservoir[static_cast<std::size_t>(j)] = *first;
2431 }
2432 return reservoir;
2433 }
2434
2441 // 引擎重载 —— 随机访问迭代器
2442 template <std::random_access_iterator It, class Engine>
2443 [[nodiscard]]
2444 inline std::vector<std::iter_value_t<It>>
2445 RandSample(Engine& engine, It first, It last, std::iter_difference_t<It> n)
2446 {
2447 using Diff = std::iter_difference_t<It>;
2448 using T = std::iter_value_t<It>;
2449 const Diff size = std::distance(first, last);
2450 if (n <= 0 || size <= 0)
2451 return {};
2452 if (n >= size)
2453 return std::vector<T>(first, last);
2454
2455 const auto sizeU = static_cast<std::uint64_t>(size);
2456 // 线性阈值:n·K < size 时用 hash-set(实测交叉点 n≈N/127,K=64 留 2× 裕度)
2457 if (static_cast<std::uint64_t>(n) * detail::HashSetThresholdK < sizeU)
2458 {
2459 // hash-set 分支:用 RandInt 适配任意引擎
2460 std::unordered_set<Diff> selected;
2461 selected.reserve(static_cast<std::size_t>(n));
2462 std::vector<T> result;
2463 result.reserve(static_cast<std::size_t>(n));
2464 while (result.size() < static_cast<std::size_t>(n))
2465 {
2466 const Diff idx = RandInt<Diff>(engine, Diff{0}, static_cast<Diff>(sizeU - 1));
2467 if (selected.insert(idx).second)
2468 result.push_back(first[idx]);
2469 }
2470 return result;
2471 }
2472
2473 // 索引数组分支:Fisher-Yates 前 n 步,j ∈ [i, size-1]
2474 std::vector<Diff> indices(static_cast<std::size_t>(size));
2475 for (Diff i = 0; i < size; ++i)
2476 indices[static_cast<std::size_t>(i)] = i;
2477
2478 for (Diff i = 0; i < n; ++i)
2479 {
2480 const Diff j = RandInt<Diff>(engine, i, static_cast<Diff>(size - 1));
2481 std::swap(indices[static_cast<std::size_t>(i)],
2482 indices[static_cast<std::size_t>(j)]);
2483 }
2484
2485 std::vector<T> result;
2486 result.reserve(static_cast<std::size_t>(n));
2487 for (Diff i = 0; i < n; ++i)
2488 result.push_back(first[indices[static_cast<std::size_t>(i)]]);
2489 return result;
2490 }
2491
2498 // 引擎重载 —— 输入迭代器(reservoir)
2499 template <std::input_iterator It, class Engine>
2500 requires (!std::random_access_iterator<It>)
2501 [[nodiscard]]
2502 inline std::vector<std::iter_value_t<It>>
2503 RandSample(Engine& engine, It first, It last, std::iter_difference_t<It> n)
2504 {
2505 using Diff = std::iter_difference_t<It>;
2506 using T = std::iter_value_t<It>;
2507 if (n <= 0)
2508 return {};
2509
2510 std::vector<T> reservoir;
2511 reservoir.reserve(static_cast<std::size_t>(n));
2512
2513 Diff i = 0;
2514 for (; i < n && first != last; ++i, ++first)
2515 reservoir.push_back(*first);
2516
2517 if (first == last)
2518 return reservoir;
2519
2520 // Algorithm R:j ∈ [0, i] 闭区间,RandInt(a,b) 是闭区间故上界为 i
2521 for (; first != last; ++i, ++first)
2522 {
2523 const Diff j = RandInt<Diff>(engine, Diff{0}, i);
2524 if (j < n)
2525 reservoir[static_cast<std::size_t>(j)] = *first;
2526 }
2527 return reservoir;
2528 }
2529
2533 [[nodiscard]]
2534 inline std::vector<std::size_t> RandPermutation(std::size_t n)
2535 {
2536 std::vector<std::size_t> perm(n);
2537 for (std::size_t i = 0; i < n; ++i) perm[i] = i;
2538 if (n < 2) return perm;
2539 auto& rng = DefaultEngine();
2540 for (std::size_t i = n - 1; i > 0; --i)
2541 {
2542 std::uniform_int_distribution<std::size_t> dist(0, i);
2543 const std::size_t j = dist(rng);
2544 auto tmp = perm[i];
2545 perm[i] = perm[j];
2546 perm[j] = tmp;
2547 }
2548 return perm;
2549 }
2550
2552
2556
2562 [[nodiscard]]
2563 inline std::string RandString(std::size_t length, std::string_view charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
2564 {
2565 if (charset.empty())
2566 throw std::invalid_argument("RandString: charset is empty");
2567 std::string result(length, '\0');
2568 auto& rng = DefaultEngine();
2569 std::uniform_int_distribution<std::size_t> dist(0, charset.size() - 1);
2570 for (std::size_t i = 0; i < length; ++i)
2571 result[i] = charset[dist(rng)];
2572 return result;
2573 }
2574
2579 [[nodiscard]]
2580 inline std::string RandString(std::size_t n, CharSet cs)
2581 {
2582 return RandString(n, detail::CharSetString(cs));
2583 }
2584
2591 template <class Engine>
2592 [[nodiscard]]
2593 inline std::string RandString(Engine& engine, std::size_t n, std::string_view charset)
2594 {
2595 if (charset.empty())
2596 throw std::invalid_argument("RandString: charset is empty");
2597 std::string result(n, '\0');
2598 std::uniform_int_distribution<std::size_t> dist(0, charset.size() - 1);
2599 for (std::size_t i = 0; i < n; ++i)
2600 result[i] = charset[dist(engine)];
2601 return result;
2602 }
2603
2609 template <class Engine>
2610 [[nodiscard]]
2611 inline std::string RandString(Engine& engine, std::size_t n, CharSet cs)
2612 {
2613 return RandString(engine, n, detail::CharSetString(cs));
2614 }
2615
2619 template <std::floating_point T = double>
2620 [[nodiscard]]
2621 inline T RandExp(T lambda = T{1})
2622 {
2623 if (!std::isfinite(lambda) || lambda <= T{0})
2624 throw std::invalid_argument("RandExp: lambda must be positive");
2625 std::exponential_distribution<T> dist(lambda);
2626 return dist(DefaultEngine());
2627 }
2628
2633 template <class Engine, std::floating_point T = double>
2634 [[nodiscard]]
2635 inline T RandExp(Engine& engine, T lambda = T{1})
2636 {
2637 if (!std::isfinite(lambda) || lambda <= T{0})
2638 throw std::invalid_argument("RandExp: lambda must be positive");
2639 std::exponential_distribution<T> dist(lambda);
2640 return dist(engine);
2641 }
2642
2646 template <std::integral T = int>
2647 [[nodiscard]]
2648 inline T RandPoisson(double mean = 1.0)
2649 {
2650 if (!std::isfinite(mean) || mean < 0.0)
2651 throw std::invalid_argument("RandPoisson: mean must be non-negative");
2652 if (mean == 0.0) return T{0};
2653 std::poisson_distribution<T> dist(mean);
2654 return dist(DefaultEngine());
2655 }
2656
2661 template <class Engine, std::integral T = int>
2662 [[nodiscard]]
2663 inline T RandPoisson(Engine& engine, double mean = 1.0)
2664 {
2665 if (!std::isfinite(mean) || mean < 0.0)
2666 throw std::invalid_argument("RandPoisson: mean must be non-negative");
2667 if (mean == 0.0) return T{0};
2668 std::poisson_distribution<T> dist(mean);
2669 return dist(engine);
2670 }
2671
2676 template <std::floating_point T = double>
2677 [[nodiscard]]
2678 inline T RandGamma(T alpha = T{1}, T beta = T{1})
2679 {
2680 if (!std::isfinite(alpha) || !std::isfinite(beta) || alpha <= T{0} || beta <= T{0})
2681 throw std::invalid_argument("RandGamma: alpha and beta must be positive");
2682 std::gamma_distribution<T> dist(alpha, beta);
2683 return dist(DefaultEngine());
2684 }
2685
2691 template <class Engine, std::floating_point T = double>
2692 [[nodiscard]]
2693 inline T RandGamma(Engine& engine, T alpha = T{1}, T beta = T{1})
2694 {
2695 if (!std::isfinite(alpha) || !std::isfinite(beta) || alpha <= T{0} || beta <= T{0})
2696 throw std::invalid_argument("RandGamma: alpha and beta must be positive");
2697 std::gamma_distribution<T> dist(alpha, beta);
2698 return dist(engine);
2699 }
2700
2705 template <std::integral T = int>
2706 [[nodiscard]]
2707 inline T RandBinomial(T t = 1, double p = 0.5)
2708 {
2709 if (t < 0 || !std::isfinite(p) || p < 0.0 || p > 1.0)
2710 throw std::invalid_argument("RandBinomial: invalid t or p");
2711 std::binomial_distribution<T> dist(t, p);
2712 return dist(DefaultEngine());
2713 }
2714
2720 template <class Engine, std::integral T = int>
2721 [[nodiscard]]
2722 inline T RandBinomial(Engine& engine, T t = 1, double p = 0.5)
2723 {
2724 if (t < 0 || !std::isfinite(p) || p < 0.0 || p > 1.0)
2725 throw std::invalid_argument("RandBinomial: invalid t or p");
2726 std::binomial_distribution<T> dist(t, p);
2727 return dist(engine);
2728 }
2729
2734 template <std::floating_point T = double>
2735 [[nodiscard]]
2736 inline T RandLogNormal(T mean = T{0}, T stddev = T{1})
2737 {
2738 if (!std::isfinite(mean) || !std::isfinite(stddev) || stddev <= T{0})
2739 throw std::invalid_argument("RandLogNormal: invalid mean or stddev");
2740 std::lognormal_distribution<T> dist(mean, stddev);
2741 return dist(DefaultEngine());
2742 }
2743
2749 template <class Engine, std::floating_point T = double>
2750 [[nodiscard]]
2751 inline T RandLogNormal(Engine& engine, T mean = T{0}, T stddev = T{1})
2752 {
2753 if (!std::isfinite(mean) || !std::isfinite(stddev) || stddev <= T{0})
2754 throw std::invalid_argument("RandLogNormal: invalid mean or stddev");
2755 std::lognormal_distribution<T> dist(mean, stddev);
2756 return dist(engine);
2757 }
2758
2762 template <std::integral T = int>
2763 [[nodiscard]]
2764 inline T RandGeometric(double p = 0.5)
2765 {
2766 if (!std::isfinite(p) || p <= 0.0 || p > 1.0)
2767 throw std::invalid_argument("RandGeometric: p must be in (0, 1]");
2768 std::geometric_distribution<T> dist(p);
2769 return dist(DefaultEngine());
2770 }
2771
2776 template <class Engine, std::integral T = int>
2777 [[nodiscard]]
2778 inline T RandGeometric(Engine& engine, double p = 0.5)
2779 {
2780 if (!std::isfinite(p) || p <= 0.0 || p > 1.0)
2781 throw std::invalid_argument("RandGeometric: p must be in (0, 1]");
2782 std::geometric_distribution<T> dist(p);
2783 return dist(engine);
2784 }
2785
2790 template <std::floating_point T = double>
2791 [[nodiscard]]
2792 inline T RandCauchy(T a = T{0}, T b = T{1})
2793 {
2794 if (!std::isfinite(a) || !std::isfinite(b) || b <= T{0})
2795 throw std::invalid_argument("RandCauchy: invalid a or b");
2796 std::cauchy_distribution<T> dist(a, b);
2797 return dist(DefaultEngine());
2798 }
2799
2805 template <class Engine, std::floating_point T = double>
2806 [[nodiscard]]
2807 inline T RandCauchy(Engine& engine, T a = T{0}, T b = T{1})
2808 {
2809 if (!std::isfinite(a) || !std::isfinite(b) || b <= T{0})
2810 throw std::invalid_argument("RandCauchy: invalid a or b");
2811 std::cauchy_distribution<T> dist(a, b);
2812 return dist(engine);
2813 }
2814
2819 template <std::floating_point T = double>
2820 [[nodiscard]]
2821 inline T RandWeibull(T a = T{1}, T b = T{1})
2822 {
2823 if (!std::isfinite(a) || !std::isfinite(b) || a <= T{0} || b <= T{0})
2824 throw std::invalid_argument("RandWeibull: invalid a or b");
2825 std::weibull_distribution<T> dist(a, b);
2826 return dist(DefaultEngine());
2827 }
2828
2834 template <class Engine, std::floating_point T = double>
2835 [[nodiscard]]
2836 inline T RandWeibull(Engine& engine, T a = T{1}, T b = T{1})
2837 {
2838 if (!std::isfinite(a) || !std::isfinite(b) || a <= T{0} || b <= T{0})
2839 throw std::invalid_argument("RandWeibull: invalid a or b");
2840 std::weibull_distribution<T> dist(a, b);
2841 return dist(engine);
2842 }
2843
2848 template <std::floating_point T = double>
2849 [[nodiscard]]
2850 inline T RandExtremeValue(T a = T{0}, T b = T{1})
2851 {
2852 if (!std::isfinite(a) || !std::isfinite(b) || b <= T{0})
2853 throw std::invalid_argument("RandExtremeValue: invalid a or b");
2854 std::extreme_value_distribution<T> dist(a, b);
2855 return dist(DefaultEngine());
2856 }
2857
2863 template <class Engine, std::floating_point T = double>
2864 [[nodiscard]]
2865 inline T RandExtremeValue(Engine& engine, T a = T{0}, T b = T{1})
2866 {
2867 if (!std::isfinite(a) || !std::isfinite(b) || b <= T{0})
2868 throw std::invalid_argument("RandExtremeValue: invalid a or b");
2869 std::extreme_value_distribution<T> dist(a, b);
2870 return dist(engine);
2871 }
2872
2876 template <std::floating_point T = double>
2877 [[nodiscard]]
2878 inline T RandChiSquared(T n = T{1})
2879 {
2880 if (!std::isfinite(n) || n <= T{0})
2881 throw std::invalid_argument("RandChiSquared: n must be positive");
2882 std::chi_squared_distribution<T> dist(n);
2883 return dist(DefaultEngine());
2884 }
2885
2890 template <class Engine, std::floating_point T = double>
2891 [[nodiscard]]
2892 inline T RandChiSquared(Engine& engine, T n = T{1})
2893 {
2894 if (!std::isfinite(n) || n <= T{0})
2895 throw std::invalid_argument("RandChiSquared: n must be positive");
2896 std::chi_squared_distribution<T> dist(n);
2897 return dist(engine);
2898 }
2899
2903 template <std::floating_point T = double>
2904 [[nodiscard]]
2905 inline T RandStudentT(T n = T{1})
2906 {
2907 if (!std::isfinite(n) || n <= T{0})
2908 throw std::invalid_argument("RandStudentT: n must be positive");
2909 std::student_t_distribution<T> dist(n);
2910 return dist(DefaultEngine());
2911 }
2912
2917 template <class Engine, std::floating_point T = double>
2918 [[nodiscard]]
2919 inline T RandStudentT(Engine& engine, T n = T{1})
2920 {
2921 if (!std::isfinite(n) || n <= T{0})
2922 throw std::invalid_argument("RandStudentT: n must be positive");
2923 std::student_t_distribution<T> dist(n);
2924 return dist(engine);
2925 }
2926
2931 template <std::floating_point T = double>
2932 [[nodiscard]]
2933 inline T RandFisherF(T m = T{1}, T n = T{1})
2934 {
2935 if (!std::isfinite(m) || !std::isfinite(n) || m <= T{0} || n <= T{0})
2936 throw std::invalid_argument("RandFisherF: invalid m or n");
2937 std::fisher_f_distribution<T> dist(m, n);
2938 return dist(DefaultEngine());
2939 }
2940
2946 template <class Engine, std::floating_point T = double>
2947 [[nodiscard]]
2948 inline T RandFisherF(Engine& engine, T m = T{1}, T n = T{1})
2949 {
2950 if (!std::isfinite(m) || !std::isfinite(n) || m <= T{0} || n <= T{0})
2951 throw std::invalid_argument("RandFisherF: invalid m or n");
2952 std::fisher_f_distribution<T> dist(m, n);
2953 return dist(engine);
2954 }
2955
2961 template <std::floating_point T = double>
2962 [[nodiscard]]
2963 inline T RandBeta(T a = T{1}, T b = T{1})
2964 {
2965 return RandBeta(DefaultEngine(), a, b);
2966 }
2967
2973 template <class Engine, std::floating_point T = double>
2974 [[nodiscard]]
2975 inline T RandBeta(Engine& engine, T a = T{1}, T b = T{1})
2976 {
2977 if (!std::isfinite(a) || !std::isfinite(b) || a <= T{0} || b <= T{0})
2978 throw std::invalid_argument("RandBeta: invalid a or b");
2979 std::gamma_distribution<T> distA(a, T{1});
2980 std::gamma_distribution<T> distB(b, T{1});
2981 const T x = distA(engine);
2982 const T y = distB(engine);
2983 const T sum = x + y;
2984 if (sum == T{0} || !std::isfinite(sum))
2985 {
2986 if (std::isinf(x) && !std::isinf(y)) return T{1};
2987 if (!std::isinf(x) && std::isinf(y)) return T{0};
2988 const double ratio = 1.0 / (1.0 + (static_cast<double>(b) / static_cast<double>(a)));
2989 return RandBool(engine, ratio) ? T{1} : T{0};
2990 }
2991 return x / sum;
2992 }
2993
2997 template <int N, std::integral T = std::uint64_t>
2998 requires (N > 0 && N <= 64 && N <= static_cast<int>(sizeof(T) * 8))
2999 [[nodiscard]]
3000 inline T RandBits() noexcept
3001 {
3002 return RandBits<N, T>(DefaultEngine());
3003 }
3004
3009 template <int N, std::integral T = std::uint64_t, class Engine>
3010 requires (N > 0 && N <= 64 && N <= static_cast<int>(sizeof(T) * 8))
3011 [[nodiscard]]
3012 inline T RandBits(Engine& engine) noexcept
3013 {
3014 if constexpr (N == 64)
3015 return static_cast<T>(engine());
3016 else
3017 return static_cast<T>(engine() & ((N >= 64) ? ~std::uint64_t{0} : ((std::uint64_t{1} << (N & 63)) - 1)));
3018 }
3019
3024 template <class Engine>
3025 [[nodiscard]]
3026 inline std::string RandUUID(Engine& engine)
3027 {
3028 static constexpr char hex[] = "0123456789abcdef";
3029 std::string uuid(36, '-');
3030 const std::uint64_t u1 = detail::Generate64Bits(engine);
3031 const std::uint64_t u2 = detail::Generate64Bits(engine);
3032
3033 for (int i = 0; i < 8; ++i)
3034 uuid[i] = hex[(u1 >> (i * 4)) & 0xFU];
3035 for (int i = 0; i < 4; ++i)
3036 uuid[9 + i] = hex[(u1 >> ((8 + i) * 4)) & 0xFU];
3037 uuid[14] = '4';
3038 for (int i = 1; i < 4; ++i)
3039 uuid[14 + i] = hex[(u1 >> ((12 + i) * 4)) & 0xFU];
3040 uuid[19] = hex[8 + ((u2 >> 0) & 0x3U)];
3041 for (int i = 1; i < 4; ++i)
3042 uuid[19 + i] = hex[(u2 >> (i * 4)) & 0xFU];
3043 for (int i = 0; i < 12; ++i)
3044 uuid[24 + i] = hex[(u2 >> ((4 + i) * 4)) & 0xFU];
3045
3046 return uuid;
3047 }
3048
3049 [[nodiscard]]
3050 inline std::string RandUUID()
3051 {
3052 return RandUUID(DefaultEngine());
3053 }
3054
3056 //
3057 // 多流接口(并行计算)
3058 //
3059
3065 template <class Engine>
3066 requires detail::StreamEngine<Engine>
3067 [[nodiscard]]
3068 inline constexpr Engine MakeStreamEngine(std::uint64_t streamId, std::uint64_t seed = DefaultSeed)
3069 {
3070 Engine rng{ seed };
3071 if constexpr (requires(Engine& e) { e.longJump(); })
3072 {
3073 const std::uint64_t longJumps = streamId >> 32;
3074 const std::uint64_t shortJumps = streamId & 0xFFFFFFFFULL;
3075 for (std::uint64_t i = 0; i < longJumps; ++i)
3076 rng.longJump();
3077 for (std::uint64_t i = 0; i < shortJumps; ++i)
3078 rng.jump();
3079 }
3080 else
3081 {
3082 for (std::uint64_t i = 0; i < streamId; ++i)
3083 rng.jump();
3084 }
3085 return rng;
3086 }
3087
3089 //
3090 // 编译期随机(constexpr)
3091 //
3092
3093 namespace detail
3094 {
3095#ifdef __SIZEOF_INT128__
3096 // Lemire 快速有界法:返回 [0, range) 内均匀分布的随机数,无模偏差
3097 // 使用 __uint128_t(GCC/Clang constexpr 友好)
3098 [[nodiscard]]
3099 inline constexpr std::uint64_t BoundedRand(Xoshiro256StarStar& rng, std::uint64_t range) noexcept
3100 {
3101 if (range == 0) return 0;
3102 __uint128_t product = static_cast<__uint128_t>(rng()) * range;
3103 std::uint64_t low = static_cast<std::uint64_t>(product);
3104 if (low < range)
3105 {
3106 const std::uint64_t threshold = (0ULL - range) % range;
3107 while (low < threshold)
3108 {
3109 product = static_cast<__uint128_t>(rng()) * range;
3110 low = static_cast<std::uint64_t>(product);
3111 }
3112 }
3113 return static_cast<std::uint64_t>(product >> 64);
3114 }
3115#else
3116 // 拒绝采样回退(MSVC 无 __uint128_t)
3117 [[nodiscard]]
3118 inline constexpr std::uint64_t BoundedRand(Xoshiro256StarStar& rng, std::uint64_t range) noexcept
3119 {
3120 if (range == 0) return 0;
3121 const std::uint64_t threshold = (0ULL - range) % range;
3122 std::uint64_t r;
3123 do { r = rng(); } while (r < threshold);
3124 return r % range;
3125 }
3126#endif
3127 }
3128
3133 template <std::integral T = int, std::uint64_t Seed = DefaultSeed>
3134 [[nodiscard]]
3135 inline constexpr T RandIntCE(T min, T max)
3136 {
3137 if (min > max) throw std::invalid_argument("RandIntCE: min > max");
3138 Xoshiro256StarStar rng{ Seed };
3139 using U = std::make_unsigned_t<T>;
3140 const U u_min = static_cast<U>(min);
3141 const U u_max = static_cast<U>(max);
3142 const U diff = u_max - u_min;
3143 if (diff == (std::numeric_limits<U>::max)())
3144 {
3145 return static_cast<T>(u_min + static_cast<U>(rng()));
3146 }
3147 const auto range = static_cast<std::uint64_t>(diff) + 1;
3148 return static_cast<T>(u_min + static_cast<U>(detail::BoundedRand(rng, range)));
3149 }
3150
3154 template <std::integral T = int, std::uint64_t Seed = DefaultSeed>
3155 [[nodiscard]]
3156 inline constexpr T RandIntCE(T max)
3157 {
3158 return RandIntCE<T, Seed>(T{0}, max);
3159 }
3160
3162 //
3163 // 编译期洗牌(constexpr)
3164 //
3165
3172 template <std::random_access_iterator It, std::uint64_t Seed = DefaultSeed>
3173 constexpr void ShuffleCE(It first, It last) noexcept
3174 {
3175 const auto n = static_cast<std::uint64_t>(last - first);
3176 if (n < 2) return;
3177 Xoshiro256StarStar rng{ Seed };
3178 for (std::uint64_t i = n - 1; i > 0; --i)
3179 {
3180 const auto j = detail::BoundedRand(rng, i + 1);
3181 if (i != j)
3182 {
3183 auto tmp = std::move(first[i]);
3184 first[i] = std::move(first[j]);
3185 first[j] = std::move(tmp);
3186 }
3187 }
3188 }
3189
3196 template <class T, std::size_t N, std::uint64_t Seed = DefaultSeed>
3197 [[nodiscard]]
3198 constexpr std::array<T, N> ShuffledArray(std::array<T, N> arr) noexcept
3199 {
3200 ShuffleCE<decltype(arr.begin()), Seed>(arr.begin(), arr.end());
3201 return arr;
3202 }
3203
3205
3207 //
3208 // 静态断言:确认引擎满足 uniform_random_bit_generator 概念
3209 //
3210
3211 static_assert(std::uniform_random_bit_generator<SplitMix64>);
3212 static_assert(std::uniform_random_bit_generator<Xoshiro256StarStar>);
3213 static_assert(std::uniform_random_bit_generator<Xoroshiro128StarStar>);
3214 static_assert(std::uniform_random_bit_generator<Xoshiro128StarStar>);
3215 static_assert(std::uniform_random_bit_generator<Xoroshiro64StarStar>);
3216 static_assert(std::uniform_random_bit_generator<SFC64>);
3217 static_assert(std::uniform_random_bit_generator<RomuDuoJr>);
3218 static_assert(std::uniform_random_bit_generator<ChaCha20>);
3219
3223
3224 namespace ranges
3225 {
3230 template <std::ranges::input_range R>
3231 requires std::ranges::sized_range<R> || std::ranges::forward_range<R>
3232 [[nodiscard]]
3233 inline std::ranges::range_value_t<R>
3235 {
3236 using It = decltype(std::ranges::begin(r));
3237 if constexpr (std::random_access_iterator<It>)
3238 return *RandX::RandElement(std::ranges::begin(r), std::ranges::end(r));
3239 else
3240 return RandX::RandElement(std::ranges::begin(r), std::ranges::end(r));
3241 }
3242
3247 template <std::ranges::input_range R>
3248 [[nodiscard]]
3249 inline std::vector<std::ranges::range_value_t<R>>
3250 RandSample(R&& r, std::ranges::range_difference_t<R> n)
3251 {
3252 return RandX::RandSample(std::ranges::begin(r), std::ranges::end(r), n);
3253 }
3254
3257 template <std::ranges::random_access_range R>
3258 requires std::ranges::sized_range<R>
3259 inline void
3261 {
3262 std::ranges::shuffle(r, RandX::DefaultEngine());
3263 }
3264
3270 template <class T, std::ranges::output_range<const T&> R>
3271 inline void
3272 RandFill(R&& r, T min, T max)
3273 {
3274 RandX::RandFill(std::ranges::begin(r), std::ranges::end(r), min, max);
3275 }
3276 }
3277
3279
3280}
RomuDuoJr 伪随机数生成器,64 位输出,周期估计 >= 2^51。
定义 RandX.hpp:660
std::array< std::uint64_t, N > state_type
< 输出类型
定义 RandX_Cpp17.hpp:290
std::uint64_t result_type
定义 RandX_Cpp17.hpp:289
SFC64(Small Fast Counter)伪随机数生成器,64 位输出,周期 >= 2^64。
定义 RandX.hpp:617
std::uint64_t result_type
定义 RandX_Cpp17.hpp:289
std::array< std::uint64_t, N > state_type
< 输出类型
定义 RandX_Cpp17.hpp:290
SplitMix64 伪随机数生成器,64 位输出,周期 2^64。
定义 RandX.hpp:217
Xoroshiro128** 伪随机数生成器,64 位输出,周期 2^128-1。
定义 RandX.hpp:462
std::uint64_t result_type
定义 RandX_Cpp17.hpp:289
std::array< std::uint64_t, N > state_type
< 输出类型
定义 RandX_Cpp17.hpp:290
Xoroshiro64** 伪随机数生成器,32 位输出,周期 2^64-1。
定义 RandX.hpp:572
std::array< std::uint32_t, N > state_type
< 输出类型
定义 RandX_Cpp17.hpp:290
std::uint32_t result_type
定义 RandX_Cpp17.hpp:289
Xoshiro128** 伪随机数生成器,32 位输出,周期 2^128-1。
定义 RandX.hpp:517
std::uint32_t result_type
定义 RandX_Cpp17.hpp:289
std::array< std::uint32_t, N > state_type
< 输出类型
定义 RandX_Cpp17.hpp:290
Xoshiro256** 伪随机数生成器,64 位输出,周期 2^256-1。
定义 RandX.hpp:407
std::array< std::uint64_t, N > state_type
< 输出类型
定义 RandX_Cpp17.hpp:290
std::uint64_t result_type
定义 RandX_Cpp17.hpp:289
定义 RandX.hpp:952
定义 RandX.hpp:964
可跳跃引擎概念:支持 jump() 前进 2^N 步
定义 RandX.hpp:987
定义 RandX.hpp:1006
流式引擎概念:可通过 MakeStreamEngine 创建互不重叠的子序列流
定义 RandX.hpp:1002
bool RandBernoulli(double p=0.5)
伯努利分布(RandBool 的别名封装,对齐 <random> 命名)
定义 RandX.hpp:1706
double RandCanonicalDouble() noexcept
生成 [0.0, 1.0) 半开区间的双精度浮点数(直通 Bit-Extraction 极速 API)
定义 RandX.hpp:1666
bool RandBool(double p=0.5)
生成随机布尔值
定义 RandX.hpp:1682
float RandCanonicalFloat() noexcept
生成 [0.0f, 1.0f) 半开区间的单精度浮点数(直通 Bit-Extraction 极速 API)
定义 RandX.hpp:1673
T RandReal(T min=T{0}, T max=T{1})
生成 [min, max) 范围内的随机浮点数
定义 RandX.hpp:1649
CharT RandChar(CharT min, CharT max)
生成 [min, max] 范围内的随机字符
定义 RandX.hpp:1731
T RandCanonical() noexcept
采用无偏 Bit-Extraction 直通算法生成 [0, 1) 半开区间的随机浮点数(默认线程引擎)
定义 RandX.hpp:1659
T RandInt(T min, T max)
生成 [min, max] 范围内的随机整数
定义 RandX.hpp:1627
decltype(auto) RandElement(Container &c)
从容器中随机取一个元素(左值容器,返回引用)
定义 RandX.hpp:1790
std::uint64_t SecureSeed()
生成密码学安全的 64 位随机种子
定义 RandX.hpp:1370
void SecureRandomBytes(void *buf, std::size_t n)
用 OS 密码学熵源填充 [buf, buf+n) 字节
定义 RandX.hpp:1360
void ReseedRandom()
重置默认引擎为真随机种子
定义 RandX.hpp:1610
bool IsOsCryptoEntropyAvailable() noexcept
检测 OS 密码学熵源是否可用
定义 RandX.hpp:1381
void Reseed(std::uint64_t seed)
重置默认引擎的种子(用于测试复现)
定义 RandX.hpp:1604
void RandFill(It first, It last, T min, T max)
用 [min, max] 范围的随机整数填充迭代器区间
定义 RandX.hpp:1940
void RandShuffle(Container &&c)
随机打乱容器
定义 RandX.hpp:1926
WeightContainer::size_type RandWeighted(const WeightContainer &weights)
按权重随机选取索引
定义 RandX.hpp:2076
CharSet
定义 RandX.hpp:2221
std::vector< std::size_t > RandPermutation(std::size_t n)
生成 [0, n) 的随机排列
定义 RandX.hpp:2534
auto RandSample(const Container &c, typename Container::size_type n)
无放回抽样:从容器中随机抽取 n 个元素(Fisher-Yates 前 n 步)
定义 RandX.hpp:2305
std::vector< T > RandVector(T min, T max, std::size_t n)
生成含 n 个随机整数的 vector
定义 RandX.hpp:2002
T RandNormal(T mean=T{0}, T stddev=T{1})
生成正态分布随机数
定义 RandX.hpp:1900
@ Upper
定义 RandX.hpp:2225
@ Base64
定义 RandX.hpp:2229
@ Base64UrlSafe
定义 RandX.hpp:2230
@ Printable
定义 RandX.hpp:2228
@ Alpha
定义 RandX.hpp:2223
@ Digit
定义 RandX.hpp:2226
@ Hex
定义 RandX.hpp:2227
@ Lower
定义 RandX.hpp:2224
@ Alphanumeric
定义 RandX.hpp:2222
static constexpr result_type min() noexcept
定义 RandX.hpp:292
constexpr state_type serialize() const noexcept
序列化引擎状态
定义 RandX.hpp:1119
constexpr void longJump() noexcept
前进 2^96 步,用于创建更稀疏的并行子序列
定义 RandX.hpp:1188
constexpr std::array< std::uint64_t, N > generateSeedSequence() noexcept
生成 N 个高质量的 64 位种子序列
定义 RandX.hpp:1097
constexpr result_type operator()() noexcept
生成下一个 32 位随机数
定义 RandX.hpp:1227
constexpr bool IsAllZero(const std::array< std::uint64_t, N > &state) noexcept
定义 RandX.hpp:182
constexpr void jump() noexcept
前进 2^128 步,用于创建并行子序列
定义 RandX.hpp:1151
static constexpr result_type min() noexcept
输出范围下界
定义 RandX.hpp:763
ChaCha20(const ChaCha20 &)=delete
constexpr Xoroshiro64StarStar() noexcept
< 状态类型(2×uint32)
定义 RandX.hpp:580
ChaCha20()
构造方式 1:从 OS 熵自动播种(密码学安全,默认)
定义 RandX.hpp:1438
std::basic_ostream< CharT, Traits > & operator<<(std::basic_ostream< CharT, Traits > &os, const Engine &engine)
定义 RandX.hpp:1021
constexpr EngineBase(std::uint64_t seed) noexcept
定义 RandX.hpp:369
constexpr RomuDuoJr() noexcept
< 状态类型(2×uint64)
定义 RandX.hpp:668
void ResetThreadLocalEngine()
重新播种当前线程的默认引擎(用于 POSIX fork() 产生子进程后重置引擎状态)
定义 RandX.hpp:1345
constexpr Xoroshiro64StarStar(state_type state) noexcept
从状态数组直接构造
定义 RandX.hpp:599
std::basic_istream< CharT, Traits > & operator>>(std::basic_istream< CharT, Traits > &is, Engine &engine)
定义 RandX.hpp:1045
constexpr result_type operator()() noexcept
生成下一个 32 位随机数
定义 RandX.hpp:1198
constexpr result_type operator()() noexcept
生成下一个 64 位随机数
定义 RandX.hpp:1088
constexpr void discard(unsigned long long z) noexcept
定义 RandX.hpp:303
constexpr SFC64() noexcept
< 状态类型(4×uint64)
定义 RandX.hpp:625
constexpr void jump() noexcept
前进 2^64 步,用于创建并行子序列
定义 RandX.hpp:1211
constexpr result_type operator()() noexcept
生成下一个 64 位随机数
定义 RandX.hpp:1171
static constexpr result_type min() noexcept
输出范围下界
定义 RandX.hpp:1109
constexpr EngineBase(SeedSeq &seq)
定义 RandX.hpp:349
constexpr Xoroshiro64StarStar(std::uint64_t seed) noexcept
以指定种子构造引擎
定义 RandX.hpp:585
constexpr void longJump() noexcept
前进 2^192 步,用于创建更稀疏的并行子序列
定义 RandX.hpp:1159
constexpr void discard(unsigned long long n) noexcept
跳过 n 个输出
定义 RandX.hpp:1129
constexpr SFC64(state_type state) noexcept
从状态数组直接构造
定义 RandX.hpp:642
constexpr bool IsValidState(const State &state) noexcept
定义 RandX.hpp:198
result_type operator()()
生成下一个 64 位随机数
定义 RandX.hpp:1583
constexpr SplitMix64(state_type state=DefaultSeed) noexcept
以指定状态构造引擎
定义 RandX.hpp:1076
constexpr Xoshiro128StarStar(std::uint64_t seed) noexcept
以指定种子构造引擎
定义 RandX.hpp:530
constexpr RomuDuoJr(std::uint64_t seed) noexcept
以指定种子构造引擎
定义 RandX.hpp:673
constexpr Xoroshiro128StarStar(state_type state) noexcept
从状态数组直接构造
定义 RandX.hpp:489
constexpr double DoubleFromBits(Uint64 i) noexcept
定义 RandX.hpp:805
ResultType result_type
定义 RandX.hpp:286
constexpr Xoroshiro128StarStar(std::uint64_t seed) noexcept
以指定种子构造引擎
定义 RandX.hpp:475
ChaCha20 & operator=(const ChaCha20 &)=delete
Xoshiro256StarStar & DefaultEngine()
定义 RandX.hpp:1338
void discard(unsigned long long n)
跳过 n 个输出
定义 RandX.hpp:1597
constexpr Xoshiro128StarStar(state_type state) noexcept
从状态数组直接构造
定义 RandX.hpp:544
constexpr state_type serialize() const noexcept
定义 RandX.hpp:310
constexpr result_type operator()() noexcept
生成下一个 64 位随机数
定义 RandX.hpp:1277
constexpr result_type operator()() noexcept
生成下一个 64 位随机数
定义 RandX.hpp:1290
constexpr Xoshiro256StarStar(state_type state) noexcept
从状态数组直接构造
定义 RandX.hpp:434
constexpr Xoshiro128StarStar(SeedSeq &seq)
从 std::seed_seq 播种
定义 RandX.hpp:538
static constexpr result_type max() noexcept
定义 RandX.hpp:298
std::uint64_t result_type
输出类型
定义 RandX.hpp:221
constexpr std::uint64_t RotL(const std::uint64_t x, const int s) noexcept
定义 RandX.hpp:168
constexpr void deserialize(const state_type &s) noexcept
定义 RandX.hpp:315
constexpr Xoshiro256StarStar() noexcept
< 状态类型(4×uint64)
定义 RandX.hpp:415
std::uint64_t RandomSeed()
生成非确定性的 64 位种子
定义 RandX.hpp:1307
constexpr result_type operator()() noexcept
生成下一个 64 位随机数
定义 RandX.hpp:1138
void reseed()
从 OS 熵重新播种
定义 RandX.hpp:1555
constexpr float FloatFromBits(Uint32 i) noexcept
定义 RandX.hpp:799
std::array< ResultType, N > state_type
定义 RandX.hpp:287
constexpr EngineBase(const state_type &state) noexcept
定义 RandX.hpp:335
constexpr void deserialize(state_type state) noexcept
从状态恢复引擎
定义 RandX.hpp:1124
constexpr void jumpPoly(const ResultType(&poly)[K]) noexcept
定义 RandX.hpp:379
std::uint64_t result_type
输出类型
定义 RandX.hpp:719
constexpr void jump() noexcept
前进 2^64 步,用于创建并行子序列
定义 RandX.hpp:1182
constexpr Xoshiro256StarStar(SeedSeq &seq)
从 std::seed_seq 播种
定义 RandX.hpp:428
constexpr Xoroshiro128StarStar(SeedSeq &seq)
从 std::seed_seq 播种
定义 RandX.hpp:483
constexpr Xoshiro128StarStar() noexcept
< 状态类型(4×uint32)
定义 RandX.hpp:525
constexpr RomuDuoJr(state_type state) noexcept
从状态数组直接构造
定义 RandX.hpp:687
constexpr Xoroshiro64StarStar(SeedSeq &seq)
从 std::seed_seq 播种
定义 RandX.hpp:593
std::uint64_t state_type
状态类型(1×uint64)
定义 RandX.hpp:220
static constexpr result_type max() noexcept
输出范围上界
定义 RandX.hpp:768
constexpr RomuDuoJr(SeedSeq &seq)
从 std::seed_seq 播种
定义 RandX.hpp:681
static constexpr result_type max() noexcept
输出范围上界
定义 RandX.hpp:1114
friend auto operator<=>(const EngineBase &, const EngineBase &)=default
constexpr Xoshiro256StarStar(std::uint64_t seed) noexcept
以指定种子构造引擎
定义 RandX.hpp:420
~ChaCha20() noexcept
定义 RandX.hpp:1431
constexpr void longJump() noexcept
前进 2^96 步,用于创建更稀疏的并行子序列
定义 RandX.hpp:1217
constexpr Xoroshiro128StarStar() noexcept
< 状态类型(2×uint64)
定义 RandX.hpp:470
T RandChiSquared(T n=T{1})
生成卡方分布随机数
定义 RandX.hpp:2878
std::string RandString(std::size_t length, std::string_view charset="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
生成指定长度的随机字符串
定义 RandX.hpp:2563
T RandExtremeValue(T a=T{0}, T b=T{1})
生成极值分布(Gumbel)随机数
定义 RandX.hpp:2850
T RandFisherF(T m=T{1}, T n=T{1})
生成 Fisher F 分布随机数
定义 RandX.hpp:2933
T RandCauchy(T a=T{0}, T b=T{1})
生成柯西分布随机数
定义 RandX.hpp:2792
T RandStudentT(T n=T{1})
生成学生 t 分布随机数
定义 RandX.hpp:2905
T RandGamma(T alpha=T{1}, T beta=T{1})
生成伽马分布随机数
定义 RandX.hpp:2678
std::string RandUUID()
定义 RandX.hpp:3050
T RandWeibull(T a=T{1}, T b=T{1})
生成韦布尔分布随机数
定义 RandX.hpp:2821
constexpr std::array< T, N > ShuffledArray(std::array< T, N > arr) noexcept
编译期洗牌数组版本(返回打乱后的副本)
定义 RandX.hpp:3198
T RandExp(T lambda=T{1})
生成指数分布随机数
定义 RandX.hpp:2621
T RandLogNormal(T mean=T{0}, T stddev=T{1})
生成对数正态分布随机数
定义 RandX.hpp:2736
T RandBeta(T a=T{1}, T b=T{1})
生成 Beta 分布随机数
定义 RandX.hpp:2963
constexpr T RandIntCE(T min, T max)
编译期生成 [min, max] 范围内的随机整数
定义 RandX.hpp:3135
T RandBits() noexcept
生成 N 位随机整数
定义 RandX.hpp:3000
constexpr Engine MakeStreamEngine(std::uint64_t streamId, std::uint64_t seed=DefaultSeed)
从同一种子创建第 streamId 个不重叠子序列的引擎
定义 RandX.hpp:3068
constexpr void ShuffleCE(It first, It last) noexcept
编译期 Fisher-Yates 洗牌
定义 RandX.hpp:3173
T RandBinomial(T t=1, double p=0.5)
生成二项分布随机数
定义 RandX.hpp:2707
T RandGeometric(double p=0.5)
生成几何分布随机数(首次成功前的失败次数)
定义 RandX.hpp:2764
T RandPoisson(double mean=1.0)
生成泊松分布随机数
定义 RandX.hpp:2648
定义 RandX.hpp:166
bool GetOsEntropyBytes(void *buf, std::size_t n) noexcept
定义 RandX.hpp:854
constexpr std::uint32_t ChaCha20Constants[4]
定义 RandX.hpp:916
bool HardwareRand64(std::uint64_t &out) noexcept
定义 RandX.hpp:821
constexpr std::uint64_t ChaCha20ReseedThreshold
定义 RandX.hpp:921
static void ChaCha20QuarterRound(std::uint32_t &a, std::uint32_t &b, std::uint32_t &c, std::uint32_t &d) noexcept
定义 RandX.hpp:924
std::string_view CharSetString(CharSet cs) noexcept
定义 RandX.hpp:2237
constexpr std::uint64_t BoundedRand(Xoshiro256StarStar &rng, std::uint64_t range) noexcept
定义 RandX.hpp:3118
std::uint64_t Generate64Bits(Engine &engine)
定义 RandX.hpp:935
bool HasCryptoGradeOsEntropy() noexcept
定义 RandX.hpp:905
static void SecureWipe(void *ptr, std::size_t len) noexcept
定义 RandX.hpp:813
constexpr std::uint64_t HashSetThresholdK
定义 RandX.hpp:2209
定义 RandX.hpp:3225
void RandFill(R &&r, T min, T max)
用随机数填充 range
定义 RandX.hpp:3272
std::vector< std::ranges::range_value_t< R > > RandSample(R &&r, std::ranges::range_difference_t< R > n)
无放回抽样(复用迭代器版实现,自动选择 random_access / input 路径)
定义 RandX.hpp:3250
std::ranges::range_value_t< R > RandElement(R &&r)
随机选取一个元素(返回值拷贝,非迭代器)
定义 RandX.hpp:3234
void RandShuffle(R &&r)
随机打乱 range(要求 random_access + sized)
定义 RandX.hpp:3260
定义 RandX.hpp:150
constexpr std::uint64_t DefaultSeed
定义 RandX.hpp:152
定义 RandX.hpp:285
std::array< std::uint64_t, N > state_type
定义 RandX_Cpp17.hpp:290