mirror of
https://github.com/microsoft/vcpkg.git
synced 2025-01-14 12:14:14 +08:00
delete the random number generator
This commit is contained in:
parent
2d6df16849
commit
43493b56df
@ -1,199 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <random>
|
||||
|
||||
namespace vcpkg::Rng {
|
||||
|
||||
namespace detail {
|
||||
template <class T>
|
||||
constexpr std::size_t bitsize = sizeof(T) * CHAR_BITS;
|
||||
|
||||
template <class T>
|
||||
constexpr bool is_valid_shift(int k) {
|
||||
return 0 <= k && k <= bitsize<T>;
|
||||
}
|
||||
|
||||
// precondition: 0 <= k < bitsize<T>
|
||||
template <class T>
|
||||
constexpr T ror(T x, int k) {
|
||||
if (k == 0) {
|
||||
return x;
|
||||
}
|
||||
return (x >> k) | (x << (bitsize<T> - k));
|
||||
}
|
||||
|
||||
// precondition: 0 <= k < bitsize<T>
|
||||
template <class T>
|
||||
constexpr T rol(T x, int k) {
|
||||
if (k == 0) {
|
||||
return x;
|
||||
}
|
||||
return (x << k) | (x >> (bitsize<T> - k));
|
||||
}
|
||||
|
||||
// there _is_ a way to do this generally, but I don't know how to
|
||||
template <class UIntType, int e>
|
||||
struct XoshiroJumpTable;
|
||||
|
||||
template <>
|
||||
struct XoshiroJumpTable<std::uint64_t, 128> {
|
||||
constexpr static std::uint64_t value[4] = {
|
||||
0x180ec6d33cfd0aba, 0xd5a61266f0c9392c, 0xa9582618e03fc9aa, 0x39abdc4529b1661c
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
NOTE(ubsan): taken from the xoshiro paper
|
||||
initialized from random_device by default
|
||||
actual code is copied from wikipedia, since I wrote that code
|
||||
*/
|
||||
struct splitmix {
|
||||
splitmix() noexcept;
|
||||
|
||||
constexpr splitmix(std::uint64_t seed) noexcept
|
||||
: state(seed) {}
|
||||
|
||||
constexpr std::uint64_t operator()() noexcept {
|
||||
state += 0x9E3779B97F4A7C15;
|
||||
|
||||
std::uint64_t result = state;
|
||||
result = (result ^ (result >> 30)) * 0xBF58476D1CE4E5B9;
|
||||
result = (result ^ (result >> 27)) * 0x94D049BB133111EB;
|
||||
|
||||
return result ^ (result >> 31);
|
||||
}
|
||||
|
||||
constexpr std::uint64_t max() const noexcept {
|
||||
return std::numeric_limits<std::uint64_t>::max();
|
||||
}
|
||||
|
||||
constexpr std::uint64_t min() const noexcept {
|
||||
return std::numeric_limits<std::uint64_t>::min();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
constexpr void fill(T* first, T* last) {
|
||||
constexpr auto mask =
|
||||
static_cast<std::uint64_t>(std::numeric_limits<T>::max());
|
||||
|
||||
const auto remaining =
|
||||
(last - first) % (sizeof(std::uint64_t) / sizeof(T));
|
||||
|
||||
for (auto it = first; it != last - remaining;) {
|
||||
const auto item = (*this)();
|
||||
for (
|
||||
int shift = 0;
|
||||
shift < 64;
|
||||
shift += detail::bitsize<T>, ++it
|
||||
) {
|
||||
*it = static_cast<T>((item >> shift) & mask);
|
||||
}
|
||||
}
|
||||
|
||||
if (remaining == 0) return;
|
||||
|
||||
int shift = 0;
|
||||
const auto item = (*this)();
|
||||
for (auto it = last - remaining;
|
||||
it != last;
|
||||
shift += detail::bitsize<T>, ++it
|
||||
) {
|
||||
*it = static_cast<T>((item >> shift) & mask);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::uint64_t state;
|
||||
};
|
||||
|
||||
template <class UIntType, int S, int R, int T>
|
||||
struct starstar_scrambler {
|
||||
constexpr static UIntType scramble(UIntType n) noexcept {
|
||||
return detail::rol(n * S, R) * T;
|
||||
}
|
||||
};
|
||||
|
||||
// Sebastian Vigna's xorshift-based xoshiro engine
|
||||
// fast and really good
|
||||
// uses the splitmix to initialize state
|
||||
template <class UIntType, class Scrambler, int A, int B>
|
||||
struct xoshiro_engine {
|
||||
static_assert(detail::is_valid_shift<UIntType>(A));
|
||||
static_assert(detail::is_valid_shift<UIntType>(B));
|
||||
static_assert(std::is_unsigned_v<UIntType>);
|
||||
|
||||
// splitmix will be initialized with random_device
|
||||
xoshiro_engine() noexcept {
|
||||
splitmix sm{};
|
||||
|
||||
sm.fill(&state[0], &state[4]);
|
||||
}
|
||||
|
||||
constexpr xoshiro_engine(std::uint64_t seed) noexcept : state() {
|
||||
splitmix sm{seed};
|
||||
|
||||
sm.fill(&state[0], &state[4]);
|
||||
}
|
||||
|
||||
constexpr UIntType operator()() noexcept {
|
||||
const UIntType result = Scrambler::scramble(state[0]);
|
||||
|
||||
const UIntType t = state[1] << A;
|
||||
|
||||
state[2] ^= state[0];
|
||||
state[3] ^= state[1];
|
||||
state[1] ^= state[2];
|
||||
state[0] ^= state[3];
|
||||
|
||||
state[2] ^= t;
|
||||
state[3] ^= detail::rol(state[3], B);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
constexpr UIntType max() const noexcept {
|
||||
return std::numeric_limits<UIntType>::max();
|
||||
}
|
||||
|
||||
constexpr std::uint64_t min() const noexcept {
|
||||
return std::numeric_limits<UIntType>::min();
|
||||
}
|
||||
|
||||
// quickly jump ahead 2^e steps
|
||||
// takes 4 * bitsize<UIntType> rng next operations
|
||||
template <int e>
|
||||
constexpr void discard_e() noexcept {
|
||||
using JT = detail::XoshiroJumpTable<UIntType, e>;
|
||||
|
||||
UIntType s[4] = {};
|
||||
for (const auto& jump : JT::value) {
|
||||
for (std::size_t i = 0; i < bitsize<UIntType>; ++i) {
|
||||
if ((jump >> i) & 1) {
|
||||
s[0] ^= state[0];
|
||||
s[1] ^= state[1];
|
||||
s[2] ^= state[2];
|
||||
s[3] ^= state[3];
|
||||
}
|
||||
(*this)();
|
||||
}
|
||||
}
|
||||
|
||||
state[0] = s[0];
|
||||
state[1] = s[1];
|
||||
state[2] = s[2];
|
||||
state[3] = s[3];
|
||||
}
|
||||
private:
|
||||
// rotate left
|
||||
UIntType state[4];
|
||||
};
|
||||
|
||||
using xoshiro256ss = xoshiro_engine<
|
||||
std::uint64_t,
|
||||
starstar_scrambler<std::uint64_t, 5, 7, 9>,
|
||||
17,
|
||||
45>;
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
#include <base/rng.h>
|
||||
|
||||
namespace vcpkg::Rng {
|
||||
namespace {
|
||||
std::random_device system_entropy{};
|
||||
}
|
||||
|
||||
splitmix::splitmix() {
|
||||
std::uint64_t top_half = system_entropy();
|
||||
std::uint64_t bottom_half = system_entropy();
|
||||
|
||||
state = (top_half << 32) | bottom_half;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user