99# include <type_traits>
102# include <string_view>
103# include <unordered_set>
108# include <functional>
113# if defined(_MSC_VER) && (defined(__x86_64__) || defined(_M_X64))
114# include <immintrin.h>
118# if defined(_WIN32) && __has_include(<bcrypt.h>)
121# ifndef WIN32_LEAN_AND_MEAN
122# define WIN32_LEAN_AND_MEAN
129# pragma comment(lib, "bcrypt.lib")
131# if(defined(__MINGW32__) || defined(__MINGW64__)) && !defined(RANDX_SUPPRESS_LINK_HINT)
132# pragma message("RandX: MinGW 需手动链接 bcrypt(编译命令添加 -lbcrypt)")
134# elif defined(__linux__) && __has_include(<sys/random.h>)
135# include <sys/random.h>
137# elif defined(__APPLE__)
138# include <TargetConditionals.h>
140# if __has_include(<Security/SecRandom.h>)
141# include <Security/SecRandom.h>
143# elif __has_include(<Security/Security.h>)
144# include <Security/Security.h>
155 template <std::same_as<std::u
int32_t> U
int32>
160 template <std::same_as<std::u
int64_t> U
int64>
168 inline constexpr std::uint64_t
RotL(
const std::uint64_t x,
const int s)
noexcept
170 return std::rotl(x, s);
174 inline constexpr std::uint32_t
RotL(
const std::uint32_t x,
const int s)
noexcept
176 return std::rotl(x, s);
180 template <std::
size_t N>
182 inline constexpr bool IsAllZero(
const std::array<std::uint64_t, N>& state)
noexcept
184 for (
const auto& s : state) {
if (s != 0)
return false; }
188 template <std::
size_t N>
190 inline constexpr bool IsAllZero(
const std::array<std::uint32_t, N>& state)
noexcept
192 for (
const auto& s : state) {
if (s != 0)
return false; }
196 template <
typename State>
230 template <
class SeedSeq>
231 requires (!std::same_as<std::remove_cvref_t<SeedSeq>,
SplitMix64>)
241 constexpr
void discard(
unsigned long long n) noexcept;
246 template <std::
size_t N>
283 template <
class Derived,
class ResultType, std::
size_t N>
294 return std::numeric_limits<result_type>::lowest();
300 return std::numeric_limits<result_type>::max();
303 constexpr void discard(
unsigned long long z)
noexcept
305 for (
unsigned long long i = 0; i < z; ++i)
306 static_cast<Derived*
>(
this)->operator()();
320 s_[0] =
static_cast<ResultType
>(1);
322 assert(!
IsAllZero(
s_) &&
"absorbing all-zero state");
330 static constexpr int Bits =
static_cast<int>(
sizeof(ResultType) * 8);
340 s_[0] =
static_cast<ResultType
>(1);
342 assert(!
IsAllZero(
s_) &&
"absorbing all-zero state");
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>)
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];
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)
372 for (std::size_t i = 0; i < N; ++i)
378 template <std::
size_t K>
379 constexpr void jumpPoly(
const ResultType (&poly)[K])
noexcept
381 std::array<ResultType, N> acc{};
382 for (std::size_t i = 0; i < K; ++i)
383 for (
int b = 0; b <
Bits; ++b)
385 if (poly[i] & (ResultType{ 1 } << b))
386 for (std::size_t j = 0; j < N; ++j)
388 static_cast<Derived*
>(
this)->
operator()();
425 template <
class SeedSeq>
439 constexpr result_type operator()() noexcept;
444 constexpr
void jump() noexcept;
449 constexpr
void longJump() noexcept;
480 template <
class SeedSeq>
494 constexpr result_type operator()() noexcept;
499 constexpr
void jump() noexcept;
504 constexpr
void longJump() noexcept;
535 template <
class SeedSeq>
549 constexpr result_type operator()() noexcept;
554 constexpr
void jump() noexcept;
559 constexpr
void longJump() noexcept;
590 template <
class SeedSeq>
604 constexpr result_type operator()() noexcept;
630 explicit constexpr SFC64(std::uint64_t seed)
noexcept;
634 template <
class SeedSeq>
635 requires (!std::same_as<std::remove_cvref_t<SeedSeq>,
SFC64>)
637 explicit constexpr SFC64(SeedSeq& seq);
647 constexpr result_type operator()() noexcept;
673 explicit constexpr RomuDuoJr(std::uint64_t seed) noexcept
678 template <
class SeedSeq>
679 requires (!std::same_as<std::remove_cvref_t<SeedSeq>,
RomuDuoJr>)
692 constexpr result_type operator()() noexcept;
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.");
735 explicit
ChaCha20(std::uint64_t seed);
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);
754 void discard(
unsigned long long n);
774 std::array<std::uint32_t, 12> m_state;
775 std::array<std::uint8_t, 64> m_buffer;
776 std::size_t m_bufferPos;
777 std::uint64_t m_bytesSinceReseed;
778 bool m_autoReseed{
false };
780 void generateBlock();
781 void reseedIfNecessary();
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);
798 template <std::same_as<std::u
int32_t> U
int32>
801 return (i >> 8) * 0x1.0p-24f;
804 template <std::same_as<std::u
int64_t> U
int64>
807 return (i >> 11) * 0x1.0p-53;
815 volatile auto* p =
static_cast<volatile std::uint8_t*
>(ptr);
816 while (len--) *p++ = 0;
823#if defined(__x86_64__) || defined(_M_X64)
824 #if defined(__RDRND__)
825 unsigned long long result;
826 if (__builtin_ia32_rdrand64_step(&result))
831 #elif defined(_MSC_VER)
832 int cpuInfo[4] = {0};
834 if ((cpuInfo[2] & (1 << 30)) != 0)
836 unsigned long long result = 0;
837 if (_rdrand64_step(&result))
856 if (n == 0)
return true;
857 auto* p =
static_cast<std::uint8_t*
>(buf);
859# if defined(_WIN32) && __has_include(<bcrypt.h>)
862 std::size_t filled = 0;
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)
874# elif defined(__linux__) && __has_include(<sys/random.h>)
876 std::size_t filled = 0;
879 const ssize_t ret = ::getrandom(p + filled, n - filled, 0);
882 if (errno == EINTR)
continue;
885 if (ret == 0)
return false;
886 filled +=
static_cast<std::size_t
>(ret);
890# elif defined(__APPLE__) && __has_include(<Security/Security.h>)
892 return (::SecRandomCopyBytes(kSecRandomDefault, n, p) == errSecSuccess);
907# if (defined(_WIN32) && __has_include(<bcrypt.h>)) || (defined(__linux__) && __has_include(<sys/random.h>)) || (defined(__APPLE__) && __has_include(<Security/Security.h>))
917 0x61707865u, 0x3320646eu, 0x79622d32u, 0x6b206574u
925 std::uint32_t& c, std::uint32_t& d)
noexcept
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);
933 template <
class Engine>
937 if constexpr (
sizeof(
typename Engine::result_type) >= 8)
939 return static_cast<std::uint64_t
>(engine());
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;
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>
965 { cs.size() } -> std::same_as<std::size_t>;
966 { s[std::size_t{}] } -> std::same_as<typename S::value_type&>;
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;
988 { e.jump() } -> std::same_as<void>;
1005 template <
class It,
class T>
1007 && (std::integral<T> || std::floating_point<T>);
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)
1023 typename std::basic_ostream<CharT, Traits>::sentry ok(os);
1026 const auto flags = os.flags();
1027 os.setf(std::ios_base::dec, std::ios_base::basefield);
1029 auto state = engine.serialize();
1030 for (std::size_t i = 0; i < state.size(); ++i)
1032 if (i != 0) os <<
' ';
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)
1047 typename std::basic_istream<CharT, Traits>::sentry ok(is);
1050 const auto flags = is.flags();
1051 is.setf(std::ios_base::dec, std::ios_base::basefield);
1052 is.setf(std::ios_base::skipws);
1054 typename Engine::state_type state{};
1056 for (; i < state.size() && is; ++i)
1061 engine.deserialize(state);
1065 is.setstate(std::ios_base::failbit);
1079 template <
class SeedSeq>
1080 requires (!std::same_as<std::remove_cvref_t<SeedSeq>,
SplitMix64>)
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];
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);
1096 template <std::
size_t N>
1099 std::array<std::uint64_t, N> seeds = {};
1101 for (
auto& seed : seeds)
1111 return std::numeric_limits<result_type>::lowest();
1116 return std::numeric_limits<result_type>::max();
1131 for (
unsigned long long i = 0; i < n; ++i) {
operator()(); }
1141 const std::uint64_t t =
s_[1] << 17;
1153 static constexpr std::uint64_t p[] = {
1154 0x180ec6d33cfd0aba, 0xd5a61266f0c9392c,
1155 0xa9582618e03fc9aa, 0x39abdc4529b1661c };
1161 static constexpr std::uint64_t p[] = {
1162 0x76e15d3efefdcbbf, 0xc5004e441c522fb3,
1163 0x77710069854ee241, 0x39109bb02acbe635 };
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;
1184 static constexpr std::uint64_t p[] = { 0xdf900294d8f554a5, 0x170865df4b3201fc };
1190 static constexpr std::uint64_t p[] = { 0xd2a98b26625eee7b, 0xdddf9b1090aa7ac1 };
1201 const std::uint32_t t =
s_[1] << 9;
1213 static constexpr std::uint32_t p[] = { 0x8764000bu, 0xf542d2d3u, 0x6fa035c3u, 0x77f2db5bu };
1219 static constexpr std::uint32_t p[] = { 0xb523952eu, 0x0b6f099fu, 0xccf5a0efu, 0x1c580662u };
1229 const std::uint32_t s0 =
s_[0];
1230 std::uint32_t s1 =
s_[1];
1232 const std::uint32_t result =
detail::RotL(s0 * 0x9E3779BB, 5) * 5;
1256 if ((
s_[0] |
s_[1] |
s_[2]) == 0)
s_[0] = 0x9E3779B97F4A7C15ULL;
1257 for (
int i = 0; i < 12; ++i) {
operator()(); }
1260 template <
class SeedSeq>
1261 requires (!std::same_as<std::remove_cvref_t<SeedSeq>,
SFC64>)
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];
1272 if ((
s_[0] |
s_[1] |
s_[2]) == 0)
s_[0] = 0x9E3779B97F4A7C15ULL;
1274 for (
int i = 0; i < 12; ++i) {
operator()(); }
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);
1292 const std::uint64_t xp =
s_[0];
1293 s_[0] = 15241094284759029579ULL *
s_[1];
1314 std::random_device rd;
1317 return (
static_cast<std::uint64_t
>(rd()) << 32) | rd();
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);
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);
1364 throw std::runtime_error(
"SecureRandomBytes: OS entropy source failed");
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)
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;
1439 : m_state{}, m_buffer{}, m_bufferPos(64), m_bytesSinceReseed(0), m_autoReseed(true)
1447 : m_state{}, m_buffer{}, m_bufferPos(64), m_bytesSinceReseed(0), m_autoReseed(false)
1451 for (
int i = 0; i < 4; ++i)
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);
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);
1463 m_state[11] =
static_cast<std::uint32_t
>(sm());
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)
1474 throw std::invalid_argument(
"ChaCha20: key must be 32 bytes");
1476 throw std::invalid_argument(
"ChaCha20: nonce must be 12 bytes");
1478 for (
int i = 0; i < 8; ++i)
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);
1486 for (
int i = 0; i < 3; ++i)
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);
1493 m_state[8] = counter;
1497 inline void ChaCha20::generateBlock()
1499 if (m_state[8] == 0xFFFFFFFFU)
1501 throw std::overflow_error(
"ChaCha20: 32-bit block counter overflow");
1505 std::array<std::uint32_t, 16> state{};
1510 for (
int i = 0; i < 8; ++i) state[4 + i] = m_state[i];
1511 state[12] = m_state[8];
1512 state[13] = m_state[9];
1513 state[14] = m_state[10];
1514 state[15] = m_state[11];
1516 std::array<std::uint32_t, 16> working = state;
1519 for (
int i = 0; i < 10; ++i)
1534 for (
int i = 0; i < 16; ++i)
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);
1548 inline void ChaCha20::reseedIfNecessary()
1557 std::array<std::uint8_t, 44> seed;
1560 for (
int i = 0; i < 8; ++i)
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);
1568 for (
int i = 0; i < 3; ++i)
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);
1577 m_bytesSinceReseed = 0;
1585 reseedIfNecessary();
1586 if (m_bufferPos == 64)
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);
1593 m_bytesSinceReseed += 8;
1599 for (
unsigned long long i = 0; i < n; ++i)
operator()();
1625 template <std::
integral T =
int>
1635 template <std::
integral T =
int>
1639 assert(max >= T{0});
1647 template <std::
floating_po
int T =
double>
1657 template <std::
floating_po
int T =
double>
1684 assert(std::isfinite(p) && p >= 0.0 && p <= 1.0);
1685 std::bernoulli_distribution dist(p);
1693 template <
class Engine>
1697 assert(std::isfinite(p) && p >= 0.0 && p <= 1.0);
1698 std::bernoulli_distribution dist(p);
1699 return dist(engine);
1708 assert(p >= 0.0 && p <= 1.0);
1716 template <
class Engine>
1720 assert(p >= 0.0 && p <= 1.0);
1729 template <detail::Character CharT>
1734 std::uniform_int_distribution<std::int64_t> dist(
1735 static_cast<std::int64_t
>(min),
1736 static_cast<std::int64_t
>(max));
1743 template <detail::Character CharT =
char>
1755 template <detail::Character CharT,
class Engine>
1757 inline CharT
RandChar(Engine& engine, CharT min, CharT 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));
1770 template <detail::Character CharT =
char,
class Engine>
1787 template <
class Container>
1788 requires std::ranges::random_access_range<Container>
1793 throw std::invalid_argument(
"RandElement: empty container");
1801 template <
class Container>
1802 requires std::ranges::random_access_range<Container>
1804 inline std::ranges::range_value_t<Container>
RandElement(Container&& c)
1807 throw std::invalid_argument(
"RandElement: empty container");
1816 template <std::random_access_iterator It>
1820 using Diff = std::iter_difference_t<It>;
1821 const Diff n = std::distance(first, last);
1823 throw std::invalid_argument(
"RandElement: empty range");
1832 template <std::input_iterator It>
1833 requires (!std::random_access_iterator<It>)
1838 throw std::invalid_argument(
"RandElement: empty range");
1839 std::iter_value_t<It> selected = *first;
1841 for (std::iter_difference_t<It> i = 1; first != last; ++first, ++i)
1843 if (
RandInt<std::iter_difference_t<It>>(0, i) == 0)
1854 template <std::random_access_iterator It,
class Engine>
1858 using Diff = std::iter_difference_t<It>;
1859 const Diff n = std::distance(first, last);
1861 throw std::invalid_argument(
"RandElement: empty range");
1862 return std::next(first,
RandInt<Diff>(engine, Diff{0}, n - 1));
1870 template <std::input_iterator It,
class Engine>
1871 requires (!std::random_access_iterator<It>)
1873 inline std::iter_value_t<It>
RandElement(Engine& engine, It first, It last)
1876 throw std::invalid_argument(
"RandElement: empty range");
1877 std::iter_value_t<It> selected = *first;
1879 for (std::iter_difference_t<It> i = 1; first != last; ++first, ++i)
1881 if (
RandInt<std::iter_difference_t<It>>(engine, std::iter_difference_t<It>{0}, i) == 0)
1898 template <std::
floating_po
int T =
double>
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);
1913 template <
class Engine, std::
floating_po
int T =
double>
1915 inline T
RandNormal(Engine& engine, T mean = T{0}, T stddev = T{1})
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);
1925 template <std::ranges::random_access_range Container>
1938 template <
class It,
class T>
1939 requires detail::RandFillable<It, T> && std::integral<T>
1943 std::uniform_int_distribution<T> dist(min, max);
1944 for (; first != last; ++first)
1953 template <
class It, std::
floating_po
int T>
1954 requires std::output_iterator<It, T>
1958 std::uniform_real_distribution<T> dist(min, max);
1959 for (; first != last; ++first)
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)
1974 std::uniform_int_distribution<T> dist(min, max);
1975 for (; first != last; ++first)
1976 *first = dist(engine);
1985 template <
class It, std::
floating_po
int T,
class Engine>
1986 requires std::output_iterator<It, T>
1987 inline void RandFill(Engine& engine, It first, It last, T min, T max)
1990 std::uniform_real_distribution<T> dist(min, max);
1991 for (; first != last; ++first)
1992 *first = dist(engine);
2000 template <std::
integral T =
int>
2007 std::uniform_int_distribution<T> dist(min, max);
2009 for (std::size_t i = 0; i < n; ++i)
2010 v.push_back(dist(engine));
2019 template <std::
floating_po
int T =
double>
2026 std::uniform_real_distribution<T> dist(min, max);
2028 for (std::size_t i = 0; i < n; ++i)
2029 v.push_back(dist(engine));
2039 template <std::
integral T =
int,
class Engine>
2041 inline std::vector<T>
RandVector(Engine& engine, T min, T max, std::size_t 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));
2058 template <std::
floating_po
int T =
double,
class Engine>
2060 inline std::vector<T>
RandVector(Engine& engine, T min, T max, std::size_t 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));
2074 template <
class WeightContainer>
2076 inline typename WeightContainer::size_type
RandWeighted(
const WeightContainer& weights)
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());
2088 template <
class Engine,
class WeightContainer>
2090 inline typename WeightContainer::size_type
RandWeighted(Engine& engine,
const WeightContainer& weights)
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);
2101 template <
class IntType>
2112 template <
class Engine,
class IntType>
2114 inline IntType
RandWeighted(Engine& engine, std::discrete_distribution<IntType>& dist)
2116 return dist(engine);
2124 template <std::
integral T,
class Engine>
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));
2139 template <std::
floating_po
int T,
class Engine>
2143 using ResultType =
typename Engine::result_type;
2144 constexpr std::size_t Bits =
sizeof(ResultType) * 8;
2146 if constexpr (std::same_as<T, double>)
2148 if constexpr (Bits >= 64)
2150 const std::uint64_t r =
static_cast<std::uint64_t
>(engine());
2151 return static_cast<double>(r >> 11) * 0x1.0p-53;
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;
2161 else if constexpr (std::same_as<T, float>)
2163 if constexpr (Bits >= 64)
2165 const std::uint64_t r =
static_cast<std::uint64_t
>(engine());
2166 return static_cast<float>(r >> 40) * 0x1.0p-24f;
2170 const std::uint32_t r =
static_cast<std::uint32_t
>(engine());
2171 return static_cast<float>(r >> 8) * 0x1.0p-24f;
2176 return std::generate_canonical<T, std::numeric_limits<T>::digits>(engine);
2185 template <std::
floating_po
int T,
class Engine>
2187 inline T
RandReal(Engine& engine, T min = T{0}, T max = T{1})
2189 assert(std::isfinite(min) && std::isfinite(max) && min <= max);
2190 if (min == T{0} && max == T{1})
2194 std::uniform_real_distribution<T> dist(min, max);
2195 T val = dist(engine);
2196 if (val >= max) val = std::nextafter(max, min);
2206 inline constexpr std::uint64_t
BoundedRand(Xoshiro256StarStar& rng, std::uint64_t range)
noexcept;
2242 return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
2244 return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
2246 return "abcdefghijklmnopqrstuvwxyz";
2248 return "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
2250 return "0123456789";
2252 return "0123456789abcdef";
2254 return "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
2256 return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
2258 return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
2272 if (charset.empty())
2273 throw std::invalid_argument(
"RandChar: charset is empty");
2275 std::uniform_int_distribution<std::size_t> dist(0, charset.size() - 1);
2276 return charset[dist(rng)];
2283 template <
class Engine>
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)];
2303 template <std::ranges::random_access_range Container>
2305 inline auto RandSample(
const Container& c,
typename Container::size_type n)
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;
2313 for (Size i = 0; i < n; ++i)
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);
2337 template <std::random_access_iterator It>
2339 inline std::vector<std::iter_value_t<It>>
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)
2348 return std::vector<T>(first, last);
2354 const auto sizeU =
static_cast<std::uint64_t
>(size);
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))
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]);
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;
2379 for (Diff i = 0; i < n; ++i)
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)]);
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)]]);
2400 template <std::input_iterator It>
2401 requires (!std::random_access_iterator<It>)
2403 inline std::vector<std::iter_value_t<It>>
2406 using Diff = std::iter_difference_t<It>;
2407 using T = std::iter_value_t<It>;
2411 std::vector<T> reservoir;
2412 reservoir.reserve(
static_cast<std::size_t
>(n));
2416 for (; i < n && first != last; ++i, ++first)
2417 reservoir.push_back(*first);
2425 for (; first != last; ++i, ++first)
2427 std::uniform_int_distribution<Diff> dist(Diff{0}, i);
2428 const Diff j = dist(rng);
2430 reservoir[
static_cast<std::size_t
>(j)] = *first;
2442 template <std::random_access_iterator It,
class Engine>
2444 inline std::vector<std::iter_value_t<It>>
2445 RandSample(Engine& engine, It first, It last, std::iter_difference_t<It> n)
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)
2453 return std::vector<T>(first, last);
2455 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 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]);
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 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)]);
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)]]);
2499 template <std::input_iterator It,
class Engine>
2500 requires (!std::random_access_iterator<It>)
2502 inline std::vector<std::iter_value_t<It>>
2503 RandSample(Engine& engine, It first, It last, std::iter_difference_t<It> n)
2505 using Diff = std::iter_difference_t<It>;
2506 using T = std::iter_value_t<It>;
2510 std::vector<T> reservoir;
2511 reservoir.reserve(
static_cast<std::size_t
>(n));
2514 for (; i < n && first != last; ++i, ++first)
2515 reservoir.push_back(*first);
2521 for (; first != last; ++i, ++first)
2525 reservoir[
static_cast<std::size_t
>(j)] = *first;
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;
2540 for (std::size_t i = n - 1; i > 0; --i)
2542 std::uniform_int_distribution<std::size_t> dist(0, i);
2543 const std::size_t j = dist(rng);
2563 inline std::string
RandString(std::size_t length, std::string_view charset =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
2565 if (charset.empty())
2566 throw std::invalid_argument(
"RandString: charset is empty");
2567 std::string result(length,
'\0');
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)];
2591 template <
class Engine>
2593 inline std::string
RandString(Engine& engine, std::size_t n, std::string_view charset)
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)];
2609 template <
class Engine>
2619 template <std::
floating_po
int T =
double>
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);
2633 template <
class Engine, std::
floating_po
int T =
double>
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);
2646 template <std::
integral T =
int>
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);
2661 template <
class Engine, std::
integral T =
int>
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);
2676 template <std::
floating_po
int T =
double>
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);
2691 template <
class Engine, std::
floating_po
int T =
double>
2693 inline T
RandGamma(Engine& engine, T alpha = T{1}, T beta = T{1})
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);
2705 template <std::
integral T =
int>
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);
2720 template <
class Engine, std::
integral T =
int>
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);
2734 template <std::
floating_po
int T =
double>
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);
2749 template <
class Engine, std::
floating_po
int T =
double>
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);
2762 template <std::
integral T =
int>
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);
2776 template <
class Engine, std::
integral T =
int>
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);
2790 template <std::
floating_po
int T =
double>
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);
2805 template <
class Engine, std::
floating_po
int T =
double>
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);
2819 template <std::
floating_po
int T =
double>
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);
2834 template <
class Engine, std::
floating_po
int T =
double>
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);
2848 template <std::
floating_po
int T =
double>
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);
2863 template <
class Engine, std::
floating_po
int T =
double>
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);
2876 template <std::
floating_po
int T =
double>
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);
2890 template <
class Engine, std::
floating_po
int T =
double>
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);
2903 template <std::
floating_po
int T =
double>
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);
2917 template <
class Engine, std::
floating_po
int T =
double>
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);
2931 template <std::
floating_po
int T =
double>
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);
2946 template <
class Engine, std::
floating_po
int T =
double>
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);
2961 template <std::
floating_po
int T =
double>
2973 template <
class Engine, std::
floating_po
int T =
double>
2975 inline T
RandBeta(Engine& engine, T a = T{1}, T b = T{1})
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))
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};
2997 template <
int N, std::
integral T = std::u
int64_t>
2998 requires (N > 0 && N <= 64 && N <= static_cast<int>(
sizeof(T) * 8))
3009 template <
int N, std::
integral T = std::u
int64_t,
class Engine>
3010 requires (N > 0 && N <= 64 && N <= static_cast<int>(
sizeof(T) * 8))
3014 if constexpr (N == 64)
3015 return static_cast<T
>(engine());
3017 return static_cast<T
>(engine() & ((N >= 64) ? ~std::uint64_t{0} : ((std::uint64_t{1} << (N & 63)) - 1)));
3024 template <
class Engine>
3028 static constexpr char hex[] =
"0123456789abcdef";
3029 std::string uuid(36,
'-');
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];
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];
3065 template <
class Engine>
3066 requires detail::StreamEngine<Engine>
3071 if constexpr (
requires(Engine& e) { e.longJump(); })
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)
3077 for (std::uint64_t i = 0; i < shortJumps; ++i)
3082 for (std::uint64_t i = 0; i < streamId; ++i)
3095#ifdef __SIZEOF_INT128__
3099 inline constexpr std::uint64_t
BoundedRand(Xoshiro256StarStar& rng, std::uint64_t range)
noexcept
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);
3106 const std::uint64_t threshold = (0ULL - range) % range;
3107 while (low < threshold)
3109 product =
static_cast<__uint128_t
>(rng()) * range;
3110 low =
static_cast<std::uint64_t
>(product);
3113 return static_cast<std::uint64_t
>(product >> 64);
3120 if (range == 0)
return 0;
3121 const std::uint64_t threshold = (0ULL - range) % range;
3123 do { r = rng(); }
while (r < threshold);
3133 template <std::
integral T =
int, std::u
int64_t Seed = DefaultSeed>
3137 if (min > max)
throw std::invalid_argument(
"RandIntCE: min > max");
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)())
3145 return static_cast<T
>(u_min +
static_cast<U
>(rng()));
3147 const auto range =
static_cast<std::uint64_t
>(diff) + 1;
3154 template <std::
integral T =
int, std::u
int64_t Seed = DefaultSeed>
3172 template <std::random_access_iterator It, std::u
int64_t Seed = DefaultSeed>
3175 const auto n =
static_cast<std::uint64_t
>(last - first);
3178 for (std::uint64_t i = n - 1; i > 0; --i)
3183 auto tmp = std::move(first[i]);
3184 first[i] = std::move(first[j]);
3185 first[j] = std::move(tmp);
3196 template <
class T, std::
size_t N, std::u
int64_t Seed = DefaultSeed>
3200 ShuffleCE<
decltype(arr.begin()), Seed>(arr.begin(), arr.end());
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>);
3230 template <std::ranges::input_range R>
3231 requires std::ranges::sized_range<R> || std::ranges::forward_range<R>
3233 inline std::ranges::range_value_t<R>
3236 using It =
decltype(std::ranges::begin(r));
3237 if constexpr (std::random_access_iterator<It>)
3247 template <std::ranges::input_range R>
3249 inline std::vector<std::ranges::range_value_t<R>>
3257 template <std::ranges::random_access_range R>
3258 requires std::ranges::sized_range<R>
3270 template <
class T, std::ranges::output_range<const T&> R>
3274 RandX::RandFill(std::ranges::begin(r), std::ranges::end(r), min, max);
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
可跳跃引擎概念:支持 jump() 前进 2^N 步
定义 RandX.hpp:987
流式引擎概念:可通过 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
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
@ Base64
定义 RandX.hpp:2229
@ Base64UrlSafe
定义 RandX.hpp:2230
@ Printable
定义 RandX.hpp:2228
@ 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
state_type s_
定义 RandX.hpp:393
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
static constexpr int Bits
定义 RandX.hpp:330
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
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
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
constexpr std::uint64_t DefaultSeed
定义 RandX.hpp:152
std::uint64_t result_type
定义 RandX_Cpp17.hpp:289
std::array< std::uint64_t, N > state_type
定义 RandX_Cpp17.hpp:290