82# include <type_traits>
87# include <string_view>
88# include <unordered_set>
98# if defined(_MSC_VER) && (defined(__x86_64__) || defined(_M_X64))
99# include <immintrin.h>
103# if defined(_WIN32) && __has_include(<bcrypt.h>)
106# ifndef WIN32_LEAN_AND_MEAN
107# define WIN32_LEAN_AND_MEAN
114# pragma comment(lib, "bcrypt.lib")
116# if(defined(__MINGW32__) || defined(__MINGW64__)) && !defined(RANDX_SUPPRESS_LINK_HINT)
117# pragma message("RandX: MinGW 需手动链接 bcrypt(编译命令添加 -lbcrypt)")
119# elif defined(__linux__) && __has_include(<sys/random.h>)
120# include <sys/random.h>
122# elif defined(__APPLE__)
123# include <TargetConditionals.h>
125# if __has_include(<Security/SecRandom.h>)
126# include <Security/SecRandom.h>
128# elif __has_include(<Security/Security.h>)
129# include <Security/Security.h>
134# if __has_cpp_attribute(nodiscard) >= 201907L
135# define RANDX_NODISCARD_CXX20 [[nodiscard]]
137# define RANDX_NODISCARD_CXX20
143 inline constexpr std::uint64_t
DefaultSeed = 1234567890ULL;
147 template <
class U
int32, std::enable_if_t<std::is_same_v<U
int32, std::u
int32_t>>* =
nullptr>
153 template <
class U
int64, std::enable_if_t<std::is_same_v<U
int64, std::u
int64_t>>* =
nullptr>
161 inline constexpr std::uint64_t
RotL(
const std::uint64_t x,
const int s)
noexcept
163 const int count = s & 63;
164 return count == 0 ? x : ((x << count) | (x >> (64 - count)));
168 inline constexpr std::uint32_t
RotL(
const std::uint32_t x,
const int s)
noexcept
170 const int count = s & 31;
171 return count == 0 ? x : ((x << count) | (x >> (32 - count)));
174 template <std::
size_t N>
176 inline constexpr bool IsAllZero(
const std::array<std::uint64_t, N>& state)
noexcept
178 for (
const auto& s : state) {
if (s != 0)
return false; }
182 template <std::
size_t N>
184 inline constexpr bool IsAllZero(
const std::array<std::uint32_t, N>& state)
noexcept
186 for (
const auto& s : state) {
if (s != 0)
return false; }
190 template <
typename State>
192 inline constexpr bool IsValidState(
const State& state)
noexcept
223 template <
class SeedSeq,
224 std::enable_if_t<!std::is_same_v<std::decay_t<SeedSeq>,
SplitMix64>>* =
nullptr>
234 constexpr
void discard(
unsigned long long n) noexcept;
239 template <std::
size_t N>
267 return (lhs.m_state == rhs.m_state);
273 return (lhs.m_state != rhs.m_state);
286 template <
class Derived,
class ResultType, std::
size_t N>
297 return std::numeric_limits<result_type>::lowest();
303 return std::numeric_limits<result_type>::max();
306 constexpr void discard(
unsigned long long z)
noexcept
308 for (
unsigned long long i = 0; i < z; ++i)
309 static_cast<Derived*
>(
this)->operator()();
323 s_[0] =
static_cast<ResultType
>(1);
325 assert(!
IsAllZero(
s_) &&
"absorbing all-zero state");
331 return lhs.s_ == rhs.s_;
336 return lhs.s_ != rhs.s_;
341 static constexpr int Bits =
static_cast<int>(
sizeof(ResultType) * 8);
351 s_[0] =
static_cast<ResultType
>(1);
353 assert(!
IsAllZero(
s_) &&
"absorbing all-zero state");
357 template <
class SeedSeq,
358 std::enable_if_t<!std::is_same_v<std::decay_t<SeedSeq>,
state_type>
359 && !std::is_same_v<std::decay_t<SeedSeq>, Derived>>* =
nullptr>
364 std::array<std::uint32_t, N * 2> raw;
365 seq.generate(raw.begin(), raw.end());
366 for (std::size_t i = 0; i < N; ++i)
367 s_[i] = (
static_cast<result_type>(raw[2 * i]) << 32) | raw[2 * i + 1];
371 std::array<std::uint32_t, N> raw;
372 seq.generate(raw.begin(), raw.end());
373 for (std::size_t i = 0; i < N; ++i)
383 for (std::size_t i = 0; i < N; ++i)
389 template <std::
size_t K>
390 constexpr void jumpPoly(
const ResultType (&poly)[K])
noexcept
392 std::array<ResultType, N> acc{};
393 for (std::size_t i = 0; i < K; ++i)
394 for (
int b = 0; b <
Bits; ++b)
396 if (poly[i] & (ResultType{ 1 } << b))
397 for (std::size_t j = 0; j < N; ++j)
399 static_cast<Derived*
>(
this)->
operator()();
419 using Base = detail::EngineBase<Xoshiro256StarStar, std::uint64_t, 4>;
436 template <
class SeedSeq,
437 std::enable_if_t<!std::is_same_v<std::decay_t<SeedSeq>,
Xoshiro256StarStar>>* =
nullptr>
455 constexpr
void jump() noexcept;
491 template <
class SeedSeq,
510 constexpr
void jump() noexcept;
546 template <
class SeedSeq,
547 std::enable_if_t<!std::is_same_v<std::decay_t<SeedSeq>,
Xoshiro128StarStar>>* =
nullptr>
565 constexpr
void jump() noexcept;
601 template <
class SeedSeq,
640 explicit constexpr SFC64(std::uint64_t seed)
noexcept;
644 template <
class SeedSeq,
645 std::enable_if_t<!std::is_same_v<std::decay_t<SeedSeq>,
SFC64>>* =
nullptr>
647 explicit constexpr SFC64(SeedSeq& seq);
683 explicit constexpr RomuDuoJr(std::uint64_t seed) noexcept
688 template <
class SeedSeq,
689 std::enable_if_t<!std::is_same_v<std::decay_t<SeedSeq>,
RomuDuoJr>>* =
nullptr>
706 static_assert(std::is_trivially_destructible_v<
Xoshiro256StarStar>,
"Xoshiro256StarStar must be trivially destructible for safe TLS.");
707 static_assert(std::is_trivially_destructible_v<
Xoroshiro128StarStar>,
"Xoroshiro128StarStar must be trivially destructible for safe TLS.");
708 static_assert(std::is_trivially_destructible_v<
Xoshiro128StarStar>,
"Xoshiro128StarStar must be trivially destructible for safe TLS.");
709 static_assert(std::is_trivially_destructible_v<
Xoroshiro64StarStar>,
"Xoroshiro64StarStar must be trivially destructible for safe TLS.");
710 static_assert(std::is_trivially_destructible_v<
SplitMix64>,
"SplitMix64 must be trivially destructible for safe TLS.");
711 static_assert(std::is_trivially_destructible_v<
SFC64>,
"SFC64 must be trivially destructible for safe TLS.");
712 static_assert(std::is_trivially_destructible_v<
RomuDuoJr>,
"RomuDuoJr must be trivially destructible for safe TLS.");
754 ChaCha20(const std::uint8_t* key, std::
size_t keyLen,
755 const std::uint8_t* nonce, std::
size_t nonceLen,
756 std::uint32_t counter = 0);
784 std::array<std::uint32_t, 12> m_state;
785 std::array<std::uint8_t, 64> m_buffer;
786 std::size_t m_bufferPos;
787 std::uint64_t m_bytesSinceReseed;
788 bool m_autoReseed{
false };
790 void generateBlock();
791 void reseedIfNecessary();
796 static_assert(
sizeof(Xoroshiro128StarStar) == 16,
"Xoroshiro128StarStar size changed");
797 static_assert(
sizeof(Xoshiro128StarStar) == 16,
"Xoshiro128StarStar size changed");
798 static_assert(
sizeof(Xoroshiro64StarStar) == 8,
"Xoroshiro64StarStar size changed");
799 static_assert(
sizeof(SFC64) == 32,
"SFC64 size changed");
800 static_assert(
sizeof(RomuDuoJr) == 16,
"RomuDuoJr size changed");
801 static_assert(
sizeof(SplitMix64) == 8,
"SplitMix64 size changed");
808 template <
class U
int32, std::enable_if_t<std::is_same_v<U
int32, std::u
int32_t>>*>
811 return (i >> 8) * 0x1.0p-24f;
814 template <
class U
int64, std::enable_if_t<std::is_same_v<U
int64, std::u
int64_t>>*>
817 return (i >> 11) * 0x1.0p-53;
825 volatile auto* p =
static_cast<volatile std::uint8_t*
>(ptr);
826 while (len--) *p++ = 0;
833#if defined(__x86_64__) || defined(_M_X64)
834 #if defined(__RDRND__)
835 unsigned long long result;
836 if (__builtin_ia32_rdrand64_step(&result))
841 #elif defined(_MSC_VER)
842 int cpuInfo[4] = {0};
844 if ((cpuInfo[2] & (1 << 30)) != 0)
846 unsigned long long result = 0;
847 if (_rdrand64_step(&result))
866 if (n == 0)
return true;
867 auto* p =
static_cast<std::uint8_t*
>(buf);
869# if defined(_WIN32) && __has_include(<bcrypt.h>)
872 std::size_t filled = 0;
875 const ULONG chunkSize =
static_cast<ULONG
>((std::min)(n - filled,
static_cast<std::size_t
>((std::numeric_limits<ULONG>::max)())));
876 const auto status = ::BCryptGenRandom(
nullptr, p + filled, chunkSize, BCRYPT_USE_SYSTEM_PREFERRED_RNG);
877# if defined(BCRYPT_SUCCESS)
878 if (!BCRYPT_SUCCESS(status))
return false;
880 if (
static_cast<NTSTATUS
>(status) < 0)
return false;
886# elif defined(__linux__) && __has_include(<sys/random.h>)
888 std::size_t filled = 0;
891 const ssize_t ret = ::getrandom(p + filled, n - filled, 0);
894 if (errno == EINTR)
continue;
897 if (ret == 0)
return false;
898 filled +=
static_cast<std::size_t
>(ret);
902# elif defined(__APPLE__) && __has_include(<Security/Security.h>)
904 return (::SecRandomCopyBytes(kSecRandomDefault, n, p) == errSecSuccess);
919# if (defined(_WIN32) && __has_include(<bcrypt.h>)) || (defined(__linux__) && __has_include(<sys/random.h>)) || (defined(__APPLE__) && __has_include(<Security/Security.h>))
929 0x61707865u, 0x3320646eu, 0x79622d32u, 0x6b206574u
937 std::uint32_t& c, std::uint32_t& d)
noexcept
939 a += b; d ^= a; d =
RotL(d, 16);
940 c += d; b ^= c; b =
RotL(b, 12);
941 a += b; d ^= a; d =
RotL(d, 8);
942 c += d; b ^= c; b =
RotL(b, 7);
953 template <
class SeedSeq, std::enable_if_t<!std::is_same_v<std::decay_t<SeedSeq>, SplitMix64>>*>
956 std::array<std::uint32_t, 2> seeds;
957 seq.generate(seeds.begin(), seeds.end());
958 m_state = (
static_cast<std::uint64_t
>(seeds[0]) << 32) | seeds[1];
963 std::uint64_t z = (m_state += 0x9e3779b97f4a7c15);
964 z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
965 z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
966 return z ^ (z >> 31);
969 template <std::
size_t N>
972 std::array<std::uint64_t, N> seeds = {};
974 for (
auto& seed : seeds)
984 return std::numeric_limits<result_type>::lowest();
989 return std::numeric_limits<result_type>::max();
1004 for (
unsigned long long i = 0; i < n; ++i) { operator()(); }
1014 const std::uint64_t t =
s_[1] << 17;
1026 constexpr std::uint64_t p[] = {
1027 0x180ec6d33cfd0aba, 0xd5a61266f0c9392c,
1028 0xa9582618e03fc9aa, 0x39abdc4529b1661c };
1034 constexpr std::uint64_t p[] = {
1035 0x76e15d3efefdcbbf, 0xc5004e441c522fb3,
1036 0x77710069854ee241, 0x39109bb02acbe635 };
1046 const std::uint64_t s0 =
s_[0];
1047 std::uint64_t s1 =
s_[1];
1048 const std::uint64_t result =
detail::RotL(s0 * 5, 7) * 9;
1057 constexpr std::uint64_t p[] = { 0xdf900294d8f554a5, 0x170865df4b3201fc };
1063 constexpr std::uint64_t p[] = { 0xd2a98b26625eee7b, 0xdddf9b1090aa7ac1 };
1074 const std::uint32_t t =
s_[1] << 9;
1086 constexpr std::uint32_t p[] = { 0x8764000bu, 0xf542d2d3u, 0x6fa035c3u, 0x77f2db5bu };
1092 constexpr std::uint32_t p[] = { 0xb523952eu, 0x0b6f099fu, 0xccf5a0efu, 0x1c580662u };
1102 const std::uint32_t s0 =
s_[0];
1103 std::uint32_t s1 =
s_[1];
1105 const std::uint32_t result =
detail::RotL(s0 * 0x9E3779BB, 5) * 5;
1118 inline constexpr SFC64::SFC64(
const std::uint64_t seed) noexcept
1128 if ((s_[0] | s_[1] | s_[2]) == 0) s_[0] = 0x9E3779B97F4A7C15ULL;
1129 for (
int i = 0; i < 12; ++i) { operator()(); }
1132 template <
class SeedSeq, std::enable_if_t<!std::is_same_v<std::decay_t<SeedSeq>, SFC64>>*>
1136 std::array<std::uint32_t, 8> seeds;
1137 seq.generate(seeds.begin(), seeds.end());
1138 s_[0] = (
static_cast<std::uint64_t
>(seeds[0]) << 32) | seeds[1];
1139 s_[1] = (
static_cast<std::uint64_t
>(seeds[2]) << 32) | seeds[3];
1140 s_[2] = (
static_cast<std::uint64_t
>(seeds[4]) << 32) | seeds[5];
1143 if ((
s_[0] |
s_[1] |
s_[2]) == 0)
s_[0] = 0x9E3779B97F4A7C15ULL;
1145 for (
int i = 0; i < 12; ++i) {
operator()(); }
1150 const std::uint64_t tmp =
s_[0] +
s_[1] +
s_[3]++;
1151 s_[0] =
s_[1] ^ (
s_[1] >> 11);
1152 s_[1] =
s_[2] + (
s_[2] << 3);
1163 const std::uint64_t xp =
s_[0];
1164 s_[0] = 15241094284759029579ULL *
s_[1];
1179 template <
class Engine,
class =
void>
1181 template <
class Engine>
1182 struct HasJump<Engine, std::void_t<decltype(std::declval<Engine&>().jump())>> : std::true_type {};
1184 template <
class Engine,
class =
void>
1186 template <
class Engine>
1187 struct HasLongJump<Engine, std::void_t<decltype(std::declval<Engine&>().longJump())>> : std::true_type {};
1195 std::is_same_v<T, char>
1196 || std::is_same_v<T, wchar_t>
1197 || std::is_same_v<T, char16_t>
1198 || std::is_same_v<T, char32_t>
1199# if defined(__cpp_char8_t) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
1200 || std::is_same_v<T, char8_t>
1208 template <
class It,
class =
void>
1213 typename std::iterator_traits<It>::iterator_category>>
1214 : std::is_base_of<std::random_access_iterator_tag,
1215 typename std::iterator_traits<It>::iterator_category> {};
1218 template <
class It,
class =
void>
1223 typename std::iterator_traits<It>::iterator_category>>
1224 : std::is_base_of<std::input_iterator_tag,
1225 typename std::iterator_traits<It>::iterator_category> {};
1236 template <
class C,
class =
void>
1241 decltype(std::begin(std::declval<C&>())),
1242 decltype(std::end(std::declval<C&>()))>>
1249 template <
class Engine>
1253 if (
sizeof(
typename Engine::result_type) >= 8)
1255 return static_cast<std::uint64_t
>(engine());
1257 const std::uint64_t lo =
static_cast<std::uint64_t
>(engine());
1258 const std::uint64_t hi =
static_cast<std::uint64_t
>(engine());
1259 return (hi << 32) | lo;
1263 template <
class It,
class T,
class =
void>
1266 template <
class It,
class T>
1268 decltype(*std::declval<It&>() = std::declval<T>())
1269 >> : std::bool_constant<
1270 std::is_integral_v<T> || std::is_floating_point_v<T>
1273 template <
class It,
class T>
1277 template <
class S,
class =
void>
1282 decltype(std::declval<const S&>().size()),
1283 decltype(std::declval<S&>()[std::size_t{}]),
1284 typename S::value_type
1286 decltype(std::declval<const S&>().size()),
1293 template <
class E,
class =
void>
1298 decltype(std::declval<const E&>().serialize()),
1299 decltype(std::declval<E&>().deserialize(
1300 std::declval<typename E::state_type>())),
1301 typename E::state_type
1302 >> : std::bool_constant<
1304 decltype(std::declval<const E&>().serialize()),
1305 typename E::state_type>
1306 && is_indexable_state_v<typename E::state_type>
1313 template <class Engine, std::enable_if_t<detail::HasJump<Engine>::value>* =
nullptr>
1320 const std::uint64_t longJumps = streamId >> 32;
1321 const std::uint64_t shortJumps = streamId & 0xFFFFFFFFULL;
1322 for (std::uint64_t i = 0; i < longJumps; ++i)
1324 for (std::uint64_t i = 0; i < shortJumps; ++i)
1329 for (std::uint64_t i = 0; i < streamId; ++i)
1350 std::random_device rd;
1353 return (
static_cast<std::uint64_t
>(rd()) << 32) | rd();
1358 const auto t1 = std::chrono::high_resolution_clock::now().time_since_epoch().count();
1359 const auto t2 = std::chrono::steady_clock::now().time_since_epoch().count();
1360 const auto threadId = std::hash<std::thread::id>{}(std::this_thread::get_id());
1361 static std::atomic<std::uint64_t> counter{0};
1362 std::uint64_t stackVar = 0;
1363 const std::uint64_t addr =
reinterpret_cast<std::uint64_t
>(&stackVar);
1365 const std::uint64_t rawSeed =
static_cast<std::uint64_t
>(t1) ^
static_cast<std::uint64_t
>(t2)
1366 ^ threadId ^ addr ^ counter.fetch_add(1, std::memory_order_relaxed);
1397 throw std::runtime_error(
"SecureRandomBytes: OS entropy source failed");
1433 : m_state(other.m_state),
1434 m_buffer(other.m_buffer),
1435 m_bufferPos(other.m_bufferPos),
1436 m_bytesSinceReseed(other.m_bytesSinceReseed),
1437 m_autoReseed(other.m_autoReseed)
1451 m_state = other.m_state;
1452 m_buffer = other.m_buffer;
1453 m_bufferPos = other.m_bufferPos;
1454 m_bytesSinceReseed = other.m_bytesSinceReseed;
1455 m_autoReseed = other.m_autoReseed;
1472 : m_state{}, m_buffer{}, m_bufferPos(64), m_bytesSinceReseed(0), m_autoReseed(true)
1479 inline ChaCha20::ChaCha20(
const std::uint64_t seed)
1480 : m_state{}, m_buffer{}, m_bufferPos(64), m_bytesSinceReseed(0), m_autoReseed(false)
1484 for (
int i = 0; i < 4; ++i)
1486 const std::uint64_t v = sm();
1487 m_state[i * 2] =
static_cast<std::uint32_t
>(v);
1488 m_state[i * 2 + 1] =
static_cast<std::uint32_t
>(v >> 32);
1492 const std::uint64_t v5 = sm();
1493 m_state[9] =
static_cast<std::uint32_t
>(v5);
1494 m_state[10] =
static_cast<std::uint32_t
>(v5 >> 32);
1496 m_state[11] =
static_cast<std::uint32_t
>(sm());
1501 inline ChaCha20::ChaCha20(
const std::uint8_t* key, std::size_t keyLen,
1502 const std::uint8_t* nonce, std::size_t nonceLen,
1503 const std::uint32_t counter)
1504 : m_state{}, m_buffer{}, m_bufferPos(64), m_bytesSinceReseed(0), m_autoReseed(false)
1507 throw std::invalid_argument(
"ChaCha20: key must be 32 bytes");
1509 throw std::invalid_argument(
"ChaCha20: nonce must be 12 bytes");
1511 for (
int i = 0; i < 8; ++i)
1513 m_state[i] =
static_cast<std::uint32_t
>(key[i * 4])
1514 | (
static_cast<std::uint32_t
>(key[i * 4 + 1]) << 8)
1515 | (
static_cast<std::uint32_t
>(key[i * 4 + 2]) << 16)
1516 | (
static_cast<std::uint32_t
>(key[i * 4 + 3]) << 24);
1519 for (
int i = 0; i < 3; ++i)
1521 m_state[9 + i] =
static_cast<std::uint32_t
>(nonce[i * 4])
1522 | (
static_cast<std::uint32_t
>(nonce[i * 4 + 1]) << 8)
1523 | (
static_cast<std::uint32_t
>(nonce[i * 4 + 2]) << 16)
1524 | (
static_cast<std::uint32_t
>(nonce[i * 4 + 3]) << 24);
1526 m_state[8] = counter;
1530 inline void ChaCha20::generateBlock()
1532 if (m_state[8] == 0xFFFFFFFFU)
1534 throw std::overflow_error(
"ChaCha20: 32-bit block counter overflow");
1538 std::array<std::uint32_t, 16> state{};
1539 state[0] = detail::ChaCha20Constants[0];
1540 state[1] = detail::ChaCha20Constants[1];
1541 state[2] = detail::ChaCha20Constants[2];
1542 state[3] = detail::ChaCha20Constants[3];
1543 for (
int i = 0; i < 8; ++i) state[4 + i] = m_state[i];
1544 state[12] = m_state[8];
1545 state[13] = m_state[9];
1546 state[14] = m_state[10];
1547 state[15] = m_state[11];
1549 std::array<std::uint32_t, 16> working = state;
1552 for (
int i = 0; i < 10; ++i)
1555 detail::ChaCha20QuarterRound(working[0], working[4], working[8], working[12]);
1556 detail::ChaCha20QuarterRound(working[1], working[5], working[9], working[13]);
1557 detail::ChaCha20QuarterRound(working[2], working[6], working[10], working[14]);
1558 detail::ChaCha20QuarterRound(working[3], working[7], working[11], working[15]);
1560 detail::ChaCha20QuarterRound(working[0], working[5], working[10], working[15]);
1561 detail::ChaCha20QuarterRound(working[1], working[6], working[11], working[12]);
1562 detail::ChaCha20QuarterRound(working[2], working[7], working[8], working[13]);
1563 detail::ChaCha20QuarterRound(working[3], working[4], working[9], working[14]);
1567 for (
int i = 0; i < 16; ++i)
1569 const std::uint32_t v = working[i] + state[i];
1570 m_buffer[i * 4 + 0] =
static_cast<std::uint8_t
>(v);
1571 m_buffer[i * 4 + 1] =
static_cast<std::uint8_t
>(v >> 8);
1572 m_buffer[i * 4 + 2] =
static_cast<std::uint8_t
>(v >> 16);
1573 m_buffer[i * 4 + 3] =
static_cast<std::uint8_t
>(v >> 24);
1581 inline void ChaCha20::reseedIfNecessary()
1583 if (m_autoReseed && m_bytesSinceReseed >= detail::ChaCha20ReseedThreshold)
1588 inline void ChaCha20::reseed()
1590 std::array<std::uint8_t, 44> seed;
1593 for (
int i = 0; i < 8; ++i)
1595 m_state[i] =
static_cast<std::uint32_t
>(seed[i * 4])
1596 | (
static_cast<std::uint32_t
>(seed[i * 4 + 1]) << 8)
1597 | (
static_cast<std::uint32_t
>(seed[i * 4 + 2]) << 16)
1598 | (
static_cast<std::uint32_t
>(seed[i * 4 + 3]) << 24);
1601 for (
int i = 0; i < 3; ++i)
1603 m_state[9 + i] =
static_cast<std::uint32_t
>(seed[32 + i * 4])
1604 | (
static_cast<std::uint32_t
>(seed[32 + i * 4 + 1]) << 8)
1605 | (
static_cast<std::uint32_t
>(seed[32 + i * 4 + 2]) << 16)
1606 | (
static_cast<std::uint32_t
>(seed[32 + i * 4 + 3]) << 24);
1610 m_bytesSinceReseed = 0;
1611 detail::SecureWipe(seed.data(), seed.size());
1612 detail::SecureWipe(m_buffer.data(), m_buffer.size());
1616 inline ChaCha20::result_type ChaCha20::operator()()
1618 reseedIfNecessary();
1619 if (m_bufferPos == 64)
1622 std::uint64_t result = 0;
1623 for (
int i = 0; i < 8; ++i)
1624 result |=
static_cast<std::uint64_t
>(m_buffer[m_bufferPos + i]) << (8 * i);
1626 m_bytesSinceReseed += 8;
1630 inline void ChaCha20::discard(
const unsigned long long n)
1632 for (
unsigned long long i = 0; i < n; ++i)
operator()();
1636 inline void Reseed(std::uint64_t seed)
1654 template <
class T =
int, std::enable_if_t<std::is_
integral_v<T>>* =
nullptr>
1664 template <
class T =
int, std::enable_if_t<std::is_
integral_v<T>>* =
nullptr>
1668 assert(max >= T{0});
1676 template <
class T =
double, std::enable_if_t<std::is_
floating_po
int_v<T>>* =
nullptr>
1686 template <
class T =
double, std::enable_if_t<std::is_
floating_po
int_v<T>>* =
nullptr>
1695 inline double RandCanonicalDouble() noexcept
1697 return RandCanonical<double>();
1704 return RandCanonical<float>();
1711 inline bool RandBool(
double p = 0.5)
1713 assert(std::isfinite(p) && p >= 0.0 && p <= 1.0);
1714 std::bernoulli_distribution dist(p);
1722 template <
class Engine>
1724 inline bool RandBool(Engine& engine,
double p = 0.5)
1726 assert(std::isfinite(p) && p >= 0.0 && p <= 1.0);
1727 std::bernoulli_distribution dist(p);
1728 return dist(engine);
1737 assert(p >= 0.0 && p <= 1.0);
1745 template <
class Engine>
1749 assert(p >= 0.0 && p <= 1.0);
1758 template <
class CharT,
1759 std::enable_if_t<detail::is_character_v<CharT>>* =
nullptr>
1764 using IntT = std::int64_t;
1765 std::uniform_int_distribution<IntT> dist(
1766 static_cast<IntT
>(min),
static_cast<IntT
>(max));
1773 template <
class CharT,
1774 std::enable_if_t<detail::is_character_v<CharT>>* =
nullptr>
1786 template <
class CharT,
class Engine,
1787 std::enable_if_t<detail::is_character_v<CharT>>* =
nullptr>
1789 inline CharT
RandChar(Engine& engine, CharT min, CharT max)
1792 using IntT = std::int64_t;
1793 std::uniform_int_distribution<IntT> dist(
1794 static_cast<IntT
>(min),
static_cast<IntT
>(max));
1795 return static_cast<CharT
>(dist(engine));
1802 template <
class CharT,
class Engine,
1803 std::enable_if_t<detail::is_character_v<CharT>>* =
nullptr>
1834 inline constexpr std::uint64_t HashSetThresholdK = 64;
1838 inline std::string_view CharSetString(CharSet cs)
noexcept
1842 case CharSet::Alphanumeric:
1843 return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
1844 case CharSet::Alpha:
1845 return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
1846 case CharSet::Lower:
1847 return "abcdefghijklmnopqrstuvwxyz";
1848 case CharSet::Upper:
1849 return "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1850 case CharSet::Digit:
1851 return "0123456789";
1853 return "0123456789abcdef";
1854 case CharSet::Printable:
1855 return "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
1856 case CharSet::Base64:
1857 return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1858 case CharSet::Base64UrlSafe:
1859 return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
1872 const auto charset = detail::CharSetString(cs);
1873 if (charset.empty())
1874 throw std::invalid_argument(
"RandChar: charset is empty");
1876 std::uniform_int_distribution<std::size_t> dist(0, charset.size() - 1);
1877 return charset[dist(rng)];
1884 template <
class Engine>
1886 inline char RandChar(Engine& engine, CharSet cs)
1888 const auto charset = detail::CharSetString(cs);
1889 if (charset.empty())
1890 throw std::invalid_argument(
"RandChar: charset is empty");
1891 std::uniform_int_distribution<std::size_t> dist(0, charset.size() - 1);
1892 return charset[dist(engine)];
1902 template <
class Container,
1903 std::enable_if_t<detail::is_random_access_container_v<Container>>* =
nullptr>
1908 throw std::invalid_argument(
"RandElement: empty container");
1916 template <
class Container,
1917 std::enable_if_t<detail::is_random_access_container_v<std::decay_t<Container>>>* =
nullptr>
1919 inline typename std::iterator_traits<decltype(std::begin(std::declval<Container&>()))>::value_type
RandElement(Container&& c)
1922 throw std::invalid_argument(
"RandElement: empty container");
1932 std::enable_if_t<detail::is_random_access_iterator_v<It>>* =
nullptr>
1936 using Diff =
typename std::iterator_traits<It>::difference_type;
1937 const Diff n = std::distance(first, last);
1939 throw std::invalid_argument(
"RandElement: empty range");
1949 std::enable_if_t<detail::is_input_iterator_v<It>
1950 && !detail::is_random_access_iterator_v<It>>* =
nullptr>
1952 inline typename std::iterator_traits<It>::value_type
RandElement(It first, It last)
1955 throw std::invalid_argument(
"RandElement: empty range");
1956 typename std::iterator_traits<It>::value_type selected = *first;
1958 for (
typename std::iterator_traits<It>::difference_type i = 1;
1959 first != last; ++first, ++i)
1961 if (
RandInt<
typename std::iterator_traits<It>::difference_type>(0, i) == 0)
1972 template <
class It,
class Engine,
1973 std::enable_if_t<detail::is_random_access_iterator_v<It>>* =
nullptr>
1977 using Diff =
typename std::iterator_traits<It>::difference_type;
1978 const Diff n = std::distance(first, last);
1980 throw std::invalid_argument(
"RandElement: empty range");
1981 return std::next(first,
RandInt<Diff>(engine, Diff{0}, n - 1));
1989 template <
class It,
class Engine,
1990 std::enable_if_t<detail::is_input_iterator_v<It>
1991 && !detail::is_random_access_iterator_v<It>>* =
nullptr>
1993 inline typename std::iterator_traits<It>::value_type
RandElement(Engine& engine, It first, It last)
1996 throw std::invalid_argument(
"RandElement: empty range");
1997 typename std::iterator_traits<It>::value_type selected = *first;
1999 for (
typename std::iterator_traits<It>::difference_type i = 1;
2000 first != last; ++first, ++i)
2002 if (
RandInt<
typename std::iterator_traits<It>::difference_type>(
2003 engine,
typename std::iterator_traits<It>::difference_type{0}, i) == 0)
2017 template <
class T =
double, std::enable_if_t<std::is_
floating_po
int_v<T>>* =
nullptr>
2021 if (!std::isfinite(mean) || !std::isfinite(stddev) || stddev <= T{0})
2022 throw std::invalid_argument(
"RandNormal: invalid mean or stddev");
2023 std::normal_distribution<T> dist(mean, stddev);
2032 template <
class Engine,
class T =
double, std::enable_if_t<std::is_
floating_po
int_v<T>>* =
nullptr>
2034 inline T
RandNormal(Engine& engine, T mean = T{0}, T stddev = T{1})
2036 if (!std::isfinite(mean) || !std::isfinite(stddev) || stddev <= T{0})
2037 throw std::invalid_argument(
"RandNormal: invalid mean or stddev");
2038 std::normal_distribution<T> dist(mean, stddev);
2039 return dist(engine);
2044 template <
class Container,
2045 std::enable_if_t<detail::is_random_access_container_v<Container>>* =
nullptr>
2058 template <
class It,
class T,
2059 std::enable_if_t<detail::is_rand_fillable_v<It, T>>* =
nullptr>
2064 if constexpr (std::is_integral_v<T>)
2066 std::uniform_int_distribution<T> dist(min, max);
2067 for (; first != last; ++first) *first = dist(rng);
2071 std::uniform_real_distribution<T> dist(min, max);
2072 for (; first != last; ++first) *first = dist(rng);
2082 template <
class It,
class T,
class Engine,
2083 std::enable_if_t<detail::is_rand_fillable_v<It, T>>* =
nullptr>
2084 inline void RandFill(Engine& engine, It first, It last, T min, T max)
2087 if constexpr (std::is_integral_v<T>)
2089 std::uniform_int_distribution<T> dist(min, max);
2090 for (; first != last; ++first) *first = dist(engine);
2094 std::uniform_real_distribution<T> dist(min, max);
2095 for (; first != last; ++first) *first = dist(engine);
2105 std::enable_if_t<std::is_integral_v<T>>* =
nullptr>
2113 std::uniform_int_distribution<T> dist(min, max);
2114 for (std::size_t i = 0; i < n; ++i)
2115 v.push_back(dist(rng));
2125 std::enable_if_t<std::is_floating_point_v<T>>* =
nullptr>
2133 std::uniform_real_distribution<T> dist(min, max);
2134 for (std::size_t i = 0; i < n; ++i)
2135 v.push_back(dist(rng));
2145 template <
class T,
class Engine,
2146 std::enable_if_t<std::is_integral_v<T>>* =
nullptr>
2148 inline std::vector<T>
RandVector(Engine& engine, T min, T max, std::size_t n)
2153 std::uniform_int_distribution<T> dist(min, max);
2154 for (std::size_t i = 0; i < n; ++i)
2155 v.push_back(dist(engine));
2165 template <
class T,
class Engine,
2166 std::enable_if_t<std::is_floating_point_v<T>>* =
nullptr>
2168 inline std::vector<T>
RandVector(Engine& engine, T min, T max, std::size_t n)
2173 std::uniform_real_distribution<T> dist(min, max);
2174 for (std::size_t i = 0; i < n; ++i)
2175 v.push_back(dist(engine));
2182 template <
class WeightContainer>
2184 inline typename WeightContainer::size_type RandWeighted(
const WeightContainer& weights)
2186 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; }));
2187 using Size =
typename WeightContainer::size_type;
2188 std::discrete_distribution<Size> dist(weights.begin(), weights.end());
2189 return dist(DefaultEngine());
2196 template <
class Engine,
class WeightContainer>
2198 inline typename WeightContainer::size_type
RandWeighted(Engine& engine,
const WeightContainer& weights)
2200 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; }));
2201 using Size =
typename WeightContainer::size_type;
2202 std::discrete_distribution<Size> dist(weights.begin(), weights.end());
2203 return dist(engine);
2209 template <
class IntType>
2211 inline IntType
RandWeighted(std::discrete_distribution<IntType>& dist)
2220 template <
class Engine,
class IntType>
2222 inline IntType
RandWeighted(Engine& engine, std::discrete_distribution<IntType>& dist)
2224 return dist(engine);
2232 template <
class T,
class Engine, std::enable_if_t<std::is_
integral_v<T>>* =
nullptr>
2237 using DistType = std::conditional_t<(
sizeof(T) <
sizeof(short)),
2238 std::conditional_t<std::is_signed_v<T>,
int,
unsigned int>, T>;
2239 std::uniform_int_distribution<DistType> dist(
static_cast<DistType
>(min),
static_cast<DistType
>(max));
2240 return static_cast<T
>(dist(engine));
2247 template <
typename T = double,
class Engine,
2248 typename std::enable_if_t<std::is_floating_point_v<T>,
int> = 0>
2251 using ResultType =
typename Engine::result_type;
2252 constexpr std::size_t Bits =
sizeof(ResultType) * 8;
2254 if constexpr (std::is_same_v<T, double>)
2256 if constexpr (Bits >= 64)
2258 const std::uint64_t r =
static_cast<std::uint64_t
>(engine());
2259 return static_cast<double>(r >> 11) * 0x1.0p-53;
2263 const std::uint64_t high =
static_cast<std::uint64_t
>(engine());
2264 const std::uint64_t low =
static_cast<std::uint64_t
>(engine());
2265 const std::uint64_t r = (high << 32) | low;
2266 return static_cast<double>(r >> 11) * 0x1.0p-53;
2269 else if constexpr (std::is_same_v<T, float>)
2271 if constexpr (Bits >= 64)
2273 const std::uint64_t r =
static_cast<std::uint64_t
>(engine());
2274 return static_cast<float>(r >> 40) * 0x1.0p-24f;
2278 const std::uint32_t r =
static_cast<std::uint32_t
>(engine());
2279 return static_cast<float>(r >> 8) * 0x1.0p-24f;
2284 return std::generate_canonical<T, std::numeric_limits<T>::digits>(engine);
2293 template <
class T =
double,
class Engine, std::enable_if_t<std::is_
floating_po
int_v<T>>* =
nullptr>
2295 inline T
RandReal(Engine& engine, T min = T{0}, T max = T{1})
2297 assert(std::isfinite(min) && std::isfinite(max) && min <= max);
2298 if (min == T{0} && max == T{1})
2300 return RandCanonical<T>(engine);
2302 std::uniform_real_distribution<T> dist(min, max);
2303 T val = dist(engine);
2304 if (val >= max) val = std::nextafter(max, min);
2317 template <
class Container,
2318 std::enable_if_t<detail::is_random_access_container_v<Container>>* =
nullptr>
2322 using T =
typename std::iterator_traits<
decltype(std::begin(c))>::value_type;
2323 using Size = std::size_t;
2324 std::vector<T> pool(std::begin(c), std::end(c));
2325 const Size size = pool.size();
2326 if (n >= size)
return pool;
2328 for (Size i = 0; i < n; ++i)
2330 std::uniform_int_distribution<Size> dist(i, size - 1);
2331 const Size j = dist(rng);
2332 auto tmp = std::move(pool[i]);
2333 pool[i] = std::move(pool[j]);
2334 pool[j] = std::move(tmp);
2348 std::enable_if_t<detail::is_random_access_iterator_v<It>>* =
nullptr>
2350 inline std::vector<typename std::iterator_traits<It>::value_type>
2351 RandSample(It first, It last,
typename std::iterator_traits<It>::difference_type n)
2353 using Diff =
typename std::iterator_traits<It>::difference_type;
2354 using T =
typename std::iterator_traits<It>::value_type;
2355 const Diff size = std::distance(first, last);
2356 if (n <= 0 || size <= 0)
2359 return std::vector<T>(first, last);
2364 const auto sizeU =
static_cast<std::uint64_t
>(size);
2369 std::unordered_set<Diff> selected;
2370 selected.reserve(
static_cast<std::size_t
>(n));
2371 std::vector<T> result;
2372 result.reserve(
static_cast<std::size_t
>(n));
2373 while (result.size() <
static_cast<std::size_t
>(n))
2375 std::uniform_int_distribution<Diff> dist(Diff{0},
static_cast<Diff
>(sizeU - 1));
2376 const Diff idx = dist(rng);
2377 if (selected.insert(idx).second)
2378 result.push_back(first[idx]);
2384 std::vector<Diff> indices(
static_cast<std::size_t
>(size));
2385 for (Diff i = 0; i < size; ++i)
2386 indices[
static_cast<std::size_t
>(i)] = i;
2389 for (Diff i = 0; i < n; ++i)
2391 std::uniform_int_distribution<Diff> dist(i,
static_cast<Diff
>(size - 1));
2392 const Diff j = dist(rng);
2393 std::swap(indices[
static_cast<std::size_t
>(i)],
2394 indices[
static_cast<std::size_t
>(j)]);
2397 std::vector<T> result;
2398 result.reserve(
static_cast<std::size_t
>(n));
2399 for (Diff i = 0; i < n; ++i)
2400 result.push_back(first[indices[
static_cast<std::size_t
>(i)]]);
2406 std::enable_if_t<detail::is_input_iterator_v<It>
2407 && !detail::is_random_access_iterator_v<It>>* =
nullptr>
2409 inline std::vector<typename std::iterator_traits<It>::value_type>
2410 RandSample(It first, It last,
typename std::iterator_traits<It>::difference_type n)
2412 using Diff =
typename std::iterator_traits<It>::difference_type;
2413 using T =
typename std::iterator_traits<It>::value_type;
2417 std::vector<T> reservoir;
2418 reservoir.reserve(
static_cast<std::size_t
>(n));
2422 for (; i < n && first != last; ++i, ++first)
2423 reservoir.push_back(*first);
2431 for (; first != last; ++i, ++first)
2433 std::uniform_int_distribution<Diff> dist(Diff{0}, i);
2434 const Diff j = dist(rng);
2436 reservoir[
static_cast<std::size_t
>(j)] = *first;
2442 template <
class It,
class Engine,
2443 std::enable_if_t<detail::is_random_access_iterator_v<It>>* =
nullptr>
2445 inline std::vector<typename std::iterator_traits<It>::value_type>
2446 RandSample(Engine& engine, It first, It last,
typename std::iterator_traits<It>::difference_type n)
2448 using Diff =
typename std::iterator_traits<It>::difference_type;
2449 using T =
typename std::iterator_traits<It>::value_type;
2450 const Diff size = std::distance(first, last);
2451 if (n <= 0 || size <= 0)
2454 return std::vector<T>(first, last);
2456 const auto sizeU =
static_cast<std::uint64_t
>(size);
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))
2466 std::uniform_int_distribution<Diff> dist(Diff{0},
static_cast<Diff
>(sizeU - 1));
2467 const Diff idx = dist(engine);
2468 if (selected.insert(idx).second)
2469 result.push_back(first[idx]);
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;
2478 for (Diff i = 0; i < n; ++i)
2480 std::uniform_int_distribution<Diff> dist(i,
static_cast<Diff
>(size - 1));
2481 const Diff j = dist(engine);
2482 std::swap(indices[
static_cast<std::size_t
>(i)],
2483 indices[
static_cast<std::size_t
>(j)]);
2486 std::vector<T> result;
2487 result.reserve(
static_cast<std::size_t
>(n));
2488 for (Diff i = 0; i < n; ++i)
2489 result.push_back(first[indices[
static_cast<std::size_t
>(i)]]);
2494 template <
class It,
class Engine,
2495 std::enable_if_t<detail::is_input_iterator_v<It>
2496 && !detail::is_random_access_iterator_v<It>>* =
nullptr>
2498 inline std::vector<typename std::iterator_traits<It>::value_type>
2499 RandSample(Engine& engine, It first, It last,
typename std::iterator_traits<It>::difference_type n)
2501 using Diff =
typename std::iterator_traits<It>::difference_type;
2502 using T =
typename std::iterator_traits<It>::value_type;
2506 std::vector<T> reservoir;
2507 reservoir.reserve(
static_cast<std::size_t
>(n));
2510 for (; i < n && first != last; ++i, ++first)
2511 reservoir.push_back(*first);
2517 for (; first != last; ++i, ++first)
2519 std::uniform_int_distribution<Diff> dist(Diff{0}, i);
2520 const Diff j = dist(engine);
2522 reservoir[
static_cast<std::size_t
>(j)] = *first;
2531 inline std::vector<std::size_t> RandPermutation(std::size_t n)
2533 std::vector<std::size_t> perm(n);
2534 for (std::size_t i = 0; i < n; ++i) perm[i] = i;
2535 if (n < 2)
return perm;
2536 auto& rng = DefaultEngine();
2537 for (std::size_t i = n - 1; i > 0; --i)
2539 std::uniform_int_distribution<std::size_t> dist(0, i);
2540 const std::size_t j = dist(rng);
2557 inline std::string
RandString(std::size_t length, std::string_view charset =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
2559 if (charset.empty())
2560 throw std::invalid_argument(
"RandString: charset is empty");
2561 std::string result(length,
'\0');
2563 std::uniform_int_distribution<std::size_t> dist(0, charset.size() - 1);
2564 for (std::size_t i = 0; i < length; ++i)
2565 result[i] = charset[dist(rng)];
2574 inline std::string
RandString(std::size_t n, CharSet cs)
2576 return RandString(n, detail::CharSetString(cs));
2585 template <
class Engine>
2587 inline std::string
RandString(Engine& engine, std::size_t n, std::string_view charset)
2589 if (charset.empty())
2590 throw std::invalid_argument(
"RandString: charset is empty");
2591 std::string result(n,
'\0');
2592 std::uniform_int_distribution<std::size_t> dist(0, charset.size() - 1);
2593 for (std::size_t i = 0; i < n; ++i)
2594 result[i] = charset[dist(engine)];
2603 template <
class Engine>
2605 inline std::string
RandString(Engine& engine, std::size_t n, CharSet cs)
2607 return RandString(engine, n, detail::CharSetString(cs));
2613 template <
class T =
double, std::enable_if_t<std::is_
floating_po
int_v<T>>* =
nullptr>
2617 if (!std::isfinite(lambda) || lambda <= T{0})
2618 throw std::invalid_argument(
"RandExp: lambda must be positive");
2619 std::exponential_distribution<T> dist(lambda);
2627 template <
class Engine,
class T =
double, std::enable_if_t<std::is_
floating_po
int_v<T>>* =
nullptr>
2631 if (!std::isfinite(lambda) || lambda <= T{0})
2632 throw std::invalid_argument(
"RandExp: lambda must be positive");
2633 std::exponential_distribution<T> dist(lambda);
2634 return dist(engine);
2640 template <
class T =
int, std::enable_if_t<std::is_
integral_v<T>>* =
nullptr>
2644 if (!std::isfinite(mean) || mean < 0.0)
2645 throw std::invalid_argument(
"RandPoisson: mean must be non-negative");
2646 if (mean == 0.0)
return T{0};
2647 std::poisson_distribution<T> dist(mean);
2655 template <
class Engine,
class T =
int, std::enable_if_t<std::is_
integral_v<T>>* =
nullptr>
2659 if (!std::isfinite(mean) || mean < 0.0)
2660 throw std::invalid_argument(
"RandPoisson: mean must be non-negative");
2661 if (mean == 0.0)
return T{0};
2662 std::poisson_distribution<T> dist(mean);
2663 return dist(engine);
2670 template <
class T =
double, std::enable_if_t<std::is_
floating_po
int_v<T>>* =
nullptr>
2674 if (!std::isfinite(alpha) || !std::isfinite(beta) || alpha <= T{0} || beta <= T{0})
2675 throw std::invalid_argument(
"RandGamma: alpha and beta must be positive");
2676 std::gamma_distribution<T> dist(alpha, beta);
2685 template <
class Engine,
class T =
double, std::enable_if_t<std::is_
floating_po
int_v<T>>* =
nullptr>
2687 inline T
RandGamma(Engine& engine, T alpha = T{1}, T beta = T{1})
2689 if (!std::isfinite(alpha) || !std::isfinite(beta) || alpha <= T{0} || beta <= T{0})
2690 throw std::invalid_argument(
"RandGamma: alpha and beta must be positive");
2691 std::gamma_distribution<T> dist(alpha, beta);
2692 return dist(engine);
2699 template <
class T =
int, std::enable_if_t<std::is_
integral_v<T>>* =
nullptr>
2703 if (t < 0 || !std::isfinite(p) || p < 0.0 || p > 1.0)
2704 throw std::invalid_argument(
"RandBinomial: invalid t or p");
2705 std::binomial_distribution<T> dist(t, p);
2714 template <
class Engine,
class T =
int, std::enable_if_t<std::is_
integral_v<T>>* =
nullptr>
2718 if (t < 0 || !std::isfinite(p) || p < 0.0 || p > 1.0)
2719 throw std::invalid_argument(
"RandBinomial: invalid t or p");
2720 std::binomial_distribution<T> dist(t, p);
2721 return dist(engine);
2728 template <
class T =
double, std::enable_if_t<std::is_
floating_po
int_v<T>>* =
nullptr>
2732 if (!std::isfinite(mean) || !std::isfinite(stddev) || stddev <= T{0})
2733 throw std::invalid_argument(
"RandLogNormal: invalid mean or stddev");
2734 std::lognormal_distribution<T> dist(mean, stddev);
2743 template <
class Engine,
class T =
double, std::enable_if_t<std::is_
floating_po
int_v<T>>* =
nullptr>
2747 if (!std::isfinite(mean) || !std::isfinite(stddev) || stddev <= T{0})
2748 throw std::invalid_argument(
"RandLogNormal: invalid mean or stddev");
2749 std::lognormal_distribution<T> dist(mean, stddev);
2750 return dist(engine);
2756 template <
class T =
int, std::enable_if_t<std::is_
integral_v<T>>* =
nullptr>
2760 if (!std::isfinite(p) || p <= 0.0 || p > 1.0)
2761 throw std::invalid_argument(
"RandGeometric: p must be in (0, 1]");
2762 std::geometric_distribution<T> dist(p);
2770 template <
class Engine,
class T =
int, std::enable_if_t<std::is_
integral_v<T>>* =
nullptr>
2774 if (!std::isfinite(p) || p <= 0.0 || p > 1.0)
2775 throw std::invalid_argument(
"RandGeometric: p must be in (0, 1]");
2776 std::geometric_distribution<T> dist(p);
2777 return dist(engine);
2784 template <
class T =
double, std::enable_if_t<std::is_
floating_po
int_v<T>>* =
nullptr>
2788 if (!std::isfinite(a) || !std::isfinite(b) || b <= T{0})
2789 throw std::invalid_argument(
"RandCauchy: invalid a or b");
2790 std::cauchy_distribution<T> dist(a, b);
2799 template <
class Engine,
class T =
double, std::enable_if_t<std::is_
floating_po
int_v<T>>* =
nullptr>
2803 if (!std::isfinite(a) || !std::isfinite(b) || b <= T{0})
2804 throw std::invalid_argument(
"RandCauchy: invalid a or b");
2805 std::cauchy_distribution<T> dist(a, b);
2806 return dist(engine);
2813 template <
class T =
double, std::enable_if_t<std::is_
floating_po
int_v<T>>* =
nullptr>
2817 if (!std::isfinite(a) || !std::isfinite(b) || a <= T{0} || b <= T{0})
2818 throw std::invalid_argument(
"RandWeibull: invalid a or b");
2819 std::weibull_distribution<T> dist(a, b);
2828 template <
class Engine,
class T =
double, std::enable_if_t<std::is_
floating_po
int_v<T>>* =
nullptr>
2832 if (!std::isfinite(a) || !std::isfinite(b) || a <= T{0} || b <= T{0})
2833 throw std::invalid_argument(
"RandWeibull: invalid a or b");
2834 std::weibull_distribution<T> dist(a, b);
2835 return dist(engine);
2842 template <
class T =
double, std::enable_if_t<std::is_
floating_po
int_v<T>>* =
nullptr>
2846 if (!std::isfinite(a) || !std::isfinite(b) || b <= T{0})
2847 throw std::invalid_argument(
"RandExtremeValue: invalid a or b");
2848 std::extreme_value_distribution<T> dist(a, b);
2857 template <
class Engine,
class T =
double, std::enable_if_t<std::is_
floating_po
int_v<T>>* =
nullptr>
2861 if (!std::isfinite(a) || !std::isfinite(b) || b <= T{0})
2862 throw std::invalid_argument(
"RandExtremeValue: invalid a or b");
2863 std::extreme_value_distribution<T> dist(a, b);
2864 return dist(engine);
2870 template <
class T =
double, std::enable_if_t<std::is_
floating_po
int_v<T>>* =
nullptr>
2874 if (!std::isfinite(n) || n <= T{0})
2875 throw std::invalid_argument(
"RandChiSquared: n must be positive");
2876 std::chi_squared_distribution<T> dist(n);
2884 template <
class Engine,
class T =
double, std::enable_if_t<std::is_
floating_po
int_v<T>>* =
nullptr>
2888 if (!std::isfinite(n) || n <= T{0})
2889 throw std::invalid_argument(
"RandChiSquared: n must be positive");
2890 std::chi_squared_distribution<T> dist(n);
2891 return dist(engine);
2897 template <
class T =
double, std::enable_if_t<std::is_
floating_po
int_v<T>>* =
nullptr>
2901 if (!std::isfinite(n) || n <= T{0})
2902 throw std::invalid_argument(
"RandStudentT: n must be positive");
2903 std::student_t_distribution<T> dist(n);
2911 template <
class Engine,
class T =
double, std::enable_if_t<std::is_
floating_po
int_v<T>>* =
nullptr>
2915 if (!std::isfinite(n) || n <= T{0})
2916 throw std::invalid_argument(
"RandStudentT: n must be positive");
2917 std::student_t_distribution<T> dist(n);
2918 return dist(engine);
2925 template <
class T =
double, std::enable_if_t<std::is_
floating_po
int_v<T>>* =
nullptr>
2929 if (!std::isfinite(m) || !std::isfinite(n) || m <= T{0} || n <= T{0})
2930 throw std::invalid_argument(
"RandFisherF: invalid m or n");
2931 std::fisher_f_distribution<T> dist(m, n);
2940 template <
class Engine,
class T =
double, std::enable_if_t<std::is_
floating_po
int_v<T>>* =
nullptr>
2944 if (!std::isfinite(m) || !std::isfinite(n) || m <= T{0} || n <= T{0})
2945 throw std::invalid_argument(
"RandFisherF: invalid m or n");
2946 std::fisher_f_distribution<T> dist(m, n);
2947 return dist(engine);
2955 template <
class T =
double, std::enable_if_t<std::is_
floating_po
int_v<T>>* =
nullptr>
2967 template <
class Engine,
class T =
double, std::enable_if_t<std::is_
floating_po
int_v<T>>* =
nullptr>
2969 inline T
RandBeta(Engine& engine, T a = T{1}, T b = T{1})
2971 if (!std::isfinite(a) || !std::isfinite(b) || a <= T{0} || b <= T{0})
2972 throw std::invalid_argument(
"RandBeta: invalid a or b");
2973 std::gamma_distribution<T> distA(a, T{1});
2974 std::gamma_distribution<T> distB(b, T{1});
2975 const T x = distA(engine);
2976 const T y = distB(engine);
2977 const T sum = x + y;
2978 if (sum == T{0} || !std::isfinite(sum))
2980 if (std::isinf(x) && !std::isinf(y))
return T{1};
2981 if (!std::isinf(x) && std::isinf(y))
return T{0};
2982 const double ratio = 1.0 / (1.0 + (
static_cast<double>(b) /
static_cast<double>(a)));
2983 return RandBool(engine, ratio) ? T{1} : T{0};
2991 template <
int N,
class T = std::u
int64_t, std::enable_if_t<std::is_
integral_v<T> && (N > 0) && (N <= 64) && (N <= static_cast<
int>(sizeof(T) * 8))>* =
nullptr>
2993 inline T RandBits() noexcept
2995 return RandBits<N, T>(DefaultEngine());
3002 template <
int N,
class T = std::u
int64_t,
class Engine, std::enable_if_t<std::is_
integral_v<T> && (N > 0) && (N <= 64) && (N <= static_cast<
int>(sizeof(T) * 8))>* =
nullptr>
3004 inline T RandBits(Engine& engine) noexcept
3006 if constexpr (N == 64)
3007 return static_cast<T>(engine());
3009 return static_cast<T>(engine() & ((N >= 64) ? ~std::uint64_t{0} : ((std::uint64_t{1} << (N & 63)) - 1)));
3016 template <
class Engine>
3018 inline std::string
RandUUID(Engine& engine)
3020 static constexpr char hex[] =
"0123456789abcdef";
3021 std::string uuid(36,
'-');
3022 const std::uint64_t u1 = detail::Generate64Bits(engine);
3023 const std::uint64_t u2 = detail::Generate64Bits(engine);
3025 for (
int i = 0; i < 8; ++i)
3026 uuid[i] = hex[(u1 >> (i * 4)) & 0xFU];
3027 for (
int i = 0; i < 4; ++i)
3028 uuid[9 + i] = hex[(u1 >> ((8 + i) * 4)) & 0xFU];
3030 for (
int i = 1; i < 4; ++i)
3031 uuid[14 + i] = hex[(u1 >> ((12 + i) * 4)) & 0xFU];
3032 uuid[19] = hex[8 + ((u2 >> 0) & 0x3U)];
3033 for (
int i = 1; i < 4; ++i)
3034 uuid[19 + i] = hex[(u2 >> (i * 4)) & 0xFU];
3035 for (
int i = 0; i < 12; ++i)
3036 uuid[24 + i] = hex[(u2 >> ((4 + i) * 4)) & 0xFU];
3052 static_assert(std::is_same_v<SplitMix64::result_type, std::uint64_t>);
3053 static_assert(std::is_same_v<Xoshiro256StarStar::result_type, std::uint64_t>);
3054 static_assert(std::is_same_v<Xoroshiro128StarStar::result_type, std::uint64_t>);
3055 static_assert(std::is_same_v<Xoshiro128StarStar::result_type, std::uint32_t>);
3056 static_assert(std::is_same_v<Xoroshiro64StarStar::result_type, std::uint32_t>);
3057 static_assert(std::is_same_v<SFC64::result_type, std::uint64_t>);
3058 static_assert(std::is_same_v<RomuDuoJr::result_type, std::uint64_t>);
3059 static_assert(std::is_same_v<ChaCha20::result_type, std::uint64_t>);
3060 static_assert(SplitMix64::min() < SplitMix64::max());
3061 static_assert(Xoshiro256StarStar::min() < Xoshiro256StarStar::max());
3062 static_assert(Xoroshiro128StarStar::min() < Xoroshiro128StarStar::max());
3063 static_assert(Xoshiro128StarStar::min() < Xoshiro128StarStar::max());
3064 static_assert(Xoroshiro64StarStar::min() < Xoroshiro64StarStar::max());
3065 static_assert(SFC64::min() < SFC64::max());
3066 static_assert(RomuDuoJr::min() < RomuDuoJr::max());
3077 template <
class CharT,
class Traits,
class Engine,
3078 std::enable_if_t<detail::is_serializable_engine_v<Engine>>* =
nullptr>
3079 std::basic_ostream<CharT, Traits>&
3080 operator<<(std::basic_ostream<CharT, Traits>& os,
const Engine& engine)
3082 typename std::basic_ostream<CharT, Traits>::sentry ok(os);
3085 const auto flags = os.flags();
3086 os.setf(std::ios_base::dec, std::ios_base::basefield);
3088 auto state = engine.serialize();
3089 auto it = state.begin();
3090 if (it != state.end())
3093 for (++it; it != state.end(); ++it)
3094 os << os.widen(
' ') << *it;
3104 template <
class CharT,
class Traits,
class Engine,
3105 std::enable_if_t<detail::is_serializable_engine_v<Engine>>* =
nullptr>
3106 std::basic_istream<CharT, Traits>&
3107 operator>>(std::basic_istream<CharT, Traits>& is, Engine& engine)
3109 typename std::basic_istream<CharT, Traits>::sentry ok(is);
3112 const auto flags = is.flags();
3113 is.setf(std::ios_base::dec, std::ios_base::basefield);
3114 is.setf(std::ios_base::skipws);
3116 typename Engine::state_type state{};
3118 for (; i < state.size() && is; ++i)
3123 engine.deserialize(state);
3127 is.setstate(std::ios_base::failbit);
3136#undef RANDX_NODISCARD_CXX20
#define RANDX_NODISCARD_CXX20
定义 RandX_Cpp17.hpp:137
ChaCha20 密码学安全伪随机数生成器(CSPRNG),64 位输出,符合 RFC 8439。
定义 RandX.hpp:716
ChaCha20(const ChaCha20 &)=delete
ChaCha20 & operator=(ChaCha20 &&other) noexcept
ChaCha20 & operator=(const ChaCha20 &)=delete
static RANDX_NODISCARD_CXX20 constexpr result_type max() noexcept
输出范围上界
定义 RandX_Cpp17.hpp:778
ChaCha20(ChaCha20 &&other) noexcept
RomuDuoJr 伪随机数生成器,64 位输出,周期估计 >= 2^51。
定义 RandX.hpp:660
std::array< std::uint64_t, N > state_type
< 输出类型
定义 RandX_Cpp17.hpp:290
RANDX_NODISCARD_CXX20 constexpr RomuDuoJr(state_type state) noexcept
从状态数组直接构造
定义 RandX_Cpp17.hpp:697
constexpr RomuDuoJr() noexcept
< 状态类型(2×uint64)
定义 RandX_Cpp17.hpp:678
RANDX_NODISCARD_CXX20 constexpr RomuDuoJr(SeedSeq &seq)
从 std::seed_seq 播种
定义 RandX_Cpp17.hpp:691
RANDX_NODISCARD_CXX20 constexpr RomuDuoJr(std::uint64_t seed) noexcept
以指定种子构造引擎
定义 RandX_Cpp17.hpp:683
std::uint64_t result_type
定义 RandX_Cpp17.hpp:289
constexpr result_type operator()() noexcept
生成下一个 64 位随机数
SFC64(Small Fast Counter)伪随机数生成器,64 位输出,周期 >= 2^64。
定义 RandX.hpp:617
RANDX_NODISCARD_CXX20 constexpr SFC64(SeedSeq &seq)
从 std::seed_seq 播种(填充 3 状态字 + counter=1 + 12 轮预热)
std::uint64_t result_type
定义 RandX_Cpp17.hpp:289
RANDX_NODISCARD_CXX20 constexpr SFC64(std::uint64_t seed) noexcept
以指定种子构造引擎(SplitMix64 填充 3 状态字 + counter=1 + 12 轮预热)
constexpr SFC64() noexcept
< 状态类型(4×uint64)
定义 RandX_Cpp17.hpp:635
RANDX_NODISCARD_CXX20 constexpr SFC64(state_type state) noexcept
从状态数组直接构造
定义 RandX_Cpp17.hpp:652
constexpr result_type operator()() noexcept
生成下一个 64 位随机数
std::array< std::uint64_t, N > state_type
< 输出类型
定义 RandX_Cpp17.hpp:290
SplitMix64 伪随机数生成器,64 位输出,周期 2^64。
定义 RandX.hpp:217
constexpr result_type operator()() noexcept
生成下一个 64 位随机数
RANDX_NODISCARD_CXX20 constexpr SplitMix64(state_type state=DefaultSeed) noexcept
以指定状态构造引擎
friend bool operator!=(const SplitMix64 &lhs, const SplitMix64 &rhs) noexcept
定义 RandX_Cpp17.hpp:271
RANDX_NODISCARD_CXX20 constexpr SplitMix64(SeedSeq &seq)
从 std::seed_seq 播种
Xoroshiro128** 伪随机数生成器,64 位输出,周期 2^128-1。
定义 RandX.hpp:462
RANDX_NODISCARD_CXX20 constexpr Xoroshiro128StarStar(state_type state) noexcept
从状态数组直接构造
定义 RandX_Cpp17.hpp:500
std::uint64_t result_type
定义 RandX_Cpp17.hpp:289
constexpr result_type operator()() noexcept
生成下一个 64 位随机数
RANDX_NODISCARD_CXX20 constexpr Xoroshiro128StarStar(SeedSeq &seq)
从 std::seed_seq 播种
定义 RandX_Cpp17.hpp:494
RANDX_NODISCARD_CXX20 constexpr Xoroshiro128StarStar(std::uint64_t seed) noexcept
以指定种子构造引擎
定义 RandX_Cpp17.hpp:486
constexpr Xoroshiro128StarStar() noexcept
< 状态类型(2×uint64)
定义 RandX_Cpp17.hpp:481
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
constexpr Xoroshiro64StarStar() noexcept
< 状态类型(2×uint32)
定义 RandX_Cpp17.hpp:591
RANDX_NODISCARD_CXX20 constexpr Xoroshiro64StarStar(state_type state) noexcept
从状态数组直接构造
定义 RandX_Cpp17.hpp:610
constexpr result_type operator()() noexcept
生成下一个 32 位随机数
RANDX_NODISCARD_CXX20 constexpr Xoroshiro64StarStar(SeedSeq &seq)
从 std::seed_seq 播种
定义 RandX_Cpp17.hpp:604
std::uint32_t result_type
定义 RandX_Cpp17.hpp:289
RANDX_NODISCARD_CXX20 constexpr Xoroshiro64StarStar(std::uint64_t seed) noexcept
以指定种子构造引擎
定义 RandX_Cpp17.hpp:596
Xoshiro128** 伪随机数生成器,32 位输出,周期 2^128-1。
定义 RandX.hpp:517
std::uint32_t result_type
定义 RandX_Cpp17.hpp:289
RANDX_NODISCARD_CXX20 constexpr Xoshiro128StarStar(std::uint64_t seed) noexcept
以指定种子构造引擎
定义 RandX_Cpp17.hpp:541
constexpr result_type operator()() noexcept
生成下一个 32 位随机数
RANDX_NODISCARD_CXX20 constexpr Xoshiro128StarStar(SeedSeq &seq)
从 std::seed_seq 播种
定义 RandX_Cpp17.hpp:549
RANDX_NODISCARD_CXX20 constexpr Xoshiro128StarStar(state_type state) noexcept
从状态数组直接构造
定义 RandX_Cpp17.hpp:555
std::array< std::uint32_t, N > state_type
< 输出类型
定义 RandX_Cpp17.hpp:290
constexpr Xoshiro128StarStar() noexcept
< 状态类型(4×uint32)
定义 RandX_Cpp17.hpp:536
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_NODISCARD_CXX20 constexpr Xoshiro256StarStar(state_type state) noexcept
从状态数组直接构造
定义 RandX_Cpp17.hpp:445
RANDX_NODISCARD_CXX20 constexpr Xoshiro256StarStar(SeedSeq &seq)
从 std::seed_seq 播种
定义 RandX_Cpp17.hpp:439
constexpr Xoshiro256StarStar() noexcept
< 状态类型(4×uint64)
定义 RandX_Cpp17.hpp:426
RANDX_NODISCARD_CXX20 constexpr Xoshiro256StarStar(std::uint64_t seed) noexcept
以指定种子构造引擎
定义 RandX_Cpp17.hpp:431
constexpr result_type operator()() noexcept
生成下一个 64 位随机数
bool RandBernoulli(double p=0.5)
伯努利分布(RandBool 的别名封装,对齐 <random> 命名)
定义 RandX.hpp:1706
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
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
@ Base64
定义 RandX.hpp:2229
@ Base64UrlSafe
定义 RandX.hpp:2230
@ Printable
定义 RandX.hpp:2228
@ Alphanumeric
定义 RandX.hpp:2222
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
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 RomuDuoJr() noexcept
< 状态类型(2×uint64)
定义 RandX.hpp:668
void ResetThreadLocalEngine()
重新播种当前线程的默认引擎(用于 POSIX fork() 产生子进程后重置引擎状态)
定义 RandX.hpp:1345
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 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 void longJump() noexcept
前进 2^192 步,用于创建更稀疏的并行子序列
定义 RandX.hpp:1159
constexpr void discard(unsigned long long n) noexcept
跳过 n 个输出
定义 RandX.hpp:1129
constexpr bool IsValidState(const State &state) noexcept
定义 RandX.hpp:198
constexpr SplitMix64(state_type state=DefaultSeed) noexcept
以指定状态构造引擎
定义 RandX.hpp:1076
state_type s_
定义 RandX.hpp:393
constexpr double DoubleFromBits(Uint64 i) noexcept
定义 RandX.hpp:805
static constexpr int Bits
定义 RandX.hpp:330
ChaCha20 & operator=(const ChaCha20 &)=delete
Xoshiro256StarStar & DefaultEngine()
定义 RandX.hpp:1338
void discard(unsigned long long n)
跳过 n 个输出
定义 RandX.hpp:1597
constexpr result_type operator()() noexcept
生成下一个 64 位随机数
定义 RandX.hpp:1277
constexpr result_type operator()() noexcept
生成下一个 64 位随机数
定义 RandX.hpp:1290
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 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 void deserialize(state_type state) noexcept
从状态恢复引擎
定义 RandX.hpp:1124
constexpr void jumpPoly(const std::uint64_t(&poly)[K]) noexcept
定义 RandX.hpp:379
std::uint64_t result_type
输出类型
定义 RandX.hpp:719
constexpr void jump() noexcept
前进 2^64 步,用于创建并行子序列
定义 RandX.hpp:1182
std::uint64_t state_type
状态类型(1×uint64)
定义 RandX.hpp:220
static constexpr result_type max() noexcept
输出范围上界
定义 RandX.hpp:768
static constexpr result_type max() noexcept
输出范围上界
定义 RandX.hpp:1114
~ChaCha20() noexcept
定义 RandX.hpp:1431
constexpr void longJump() noexcept
前进 2^96 步,用于创建更稀疏的并行子序列
定义 RandX.hpp:1217
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
T RandWeibull(T a=T{1}, T b=T{1})
生成韦布尔分布随机数
定义 RandX.hpp:2821
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 Engine MakeStreamEngine(std::uint64_t streamId, std::uint64_t seed=DefaultSeed)
从同一种子创建第 streamId 个不重叠子序列的引擎
定义 RandX.hpp:3068
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
std::string RandUUID(Engine &engine)
生成随机 UUID v4 字符串
定义 RandX.hpp:3026
bool GetOsEntropyBytes(void *buf, std::size_t n) noexcept
定义 RandX.hpp:854
constexpr std::uint32_t ChaCha20Constants[4]
定义 RandX.hpp:916
constexpr bool is_rand_fillable_v
定义 RandX_Cpp17.hpp:1274
bool HardwareRand64(std::uint64_t &out) noexcept
定义 RandX.hpp:821
constexpr bool is_serializable_engine_v
定义 RandX_Cpp17.hpp:1310
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
constexpr bool is_random_access_iterator_v
定义 RandX_Cpp17.hpp:1228
constexpr bool is_input_iterator_v
定义 RandX_Cpp17.hpp:1232
constexpr bool is_character_v
定义 RandX_Cpp17.hpp:1205
std::uint64_t Generate64Bits(Engine &engine)
定义 RandX.hpp:935
bool HasCryptoGradeOsEntropy() noexcept
定义 RandX.hpp:905
constexpr bool is_random_access_container_v
定义 RandX_Cpp17.hpp:1246
static void SecureWipe(void *ptr, std::size_t len) noexcept
定义 RandX.hpp:813
constexpr std::uint64_t HashSetThresholdK
定义 RandX.hpp:2209
constexpr bool is_indexable_state_v
定义 RandX_Cpp17.hpp:1290
constexpr std::uint64_t DefaultSeed
定义 RandX.hpp:152
static constexpr result_type min() noexcept
定义 RandX_Cpp17.hpp:295
constexpr EngineBase(SeedSeq &seq)
定义 RandX_Cpp17.hpp:360
constexpr EngineBase(std::uint64_t seed) noexcept
定义 RandX_Cpp17.hpp:380
constexpr void discard(unsigned long long z) noexcept
定义 RandX_Cpp17.hpp:306
std::uint64_t result_type
定义 RandX_Cpp17.hpp:289
constexpr state_type serialize() const noexcept
定义 RandX_Cpp17.hpp:313
static constexpr result_type max() noexcept
定义 RandX_Cpp17.hpp:301
constexpr void deserialize(const state_type &s) noexcept
定义 RandX_Cpp17.hpp:318
std::array< std::uint64_t, N > state_type
定义 RandX_Cpp17.hpp:290
constexpr EngineBase(const state_type &state) noexcept
定义 RandX_Cpp17.hpp:346
constexpr void jumpPoly(const ResultType(&poly)[K]) noexcept
定义 RandX_Cpp17.hpp:390
friend bool operator!=(const EngineBase &lhs, const EngineBase &rhs) noexcept
定义 RandX_Cpp17.hpp:334
friend bool operator==(const EngineBase &lhs, const EngineBase &rhs) noexcept
定义 RandX_Cpp17.hpp:329