From b798192c158ca8d46e5c04dcb6847facede1a947 Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Fri, 11 Dec 2020 12:20:29 -0800 Subject: [PATCH] ircd::rand: Improve xoshiro256p default values; improve interface consistency. ircd::rand: Reorg iface; deinline mersenne twister so it's not emitted everywhere. --- include/ircd/rand.h | 122 +++++++++++++++++++++++++------------------- ircd/rand.cc | 65 +++++++++++++++++------ 2 files changed, 117 insertions(+), 70 deletions(-) diff --git a/include/ircd/rand.h b/include/ircd/rand.h index 261f20dda..8259a32f9 100644 --- a/include/ircd/rand.h +++ b/include/ircd/rand.h @@ -31,41 +31,90 @@ namespace ircd::rand extern std::mt19937_64 mt; // Random integer - uint64_t integer(); - uint64_t integer(const uint64_t &min, const uint64_t &max); // inclusive + uint64_t integer() noexcept; + uint64_t integer(const uint64_t &min, const uint64_t &max) noexcept; // inclusive + uint64_t integer(xoshiro256p &) noexcept; // Random vector - template T vector() = delete; - template<> u128x1 vector(); - template<> u256x1 vector(); - template<> u512x1 vector(); - - // Random character from dictionary - char character(const std::string &dict = dict::alnum); - - // Random string from dictionary, fills buffer - string_view string(const mutable_buffer &out, const std::string &dict); + template T vector() noexcept = delete; + template<> u128x1 vector() noexcept; + template<> u256x1 vector() noexcept; + template<> u512x1 vector() noexcept; // Random fill of buffer - const_buffer fill(const mutable_buffer &out); + const_buffer fill(const mutable_buffer &out) noexcept; + + // Random fill of array + template + decltype(auto) fill(T (&buf)[S]) noexcept; + + // Random character from dictionary + char character(const std::string &dict = dict::alnum) noexcept; + + // Random string from dictionary, fills buffer + string_view string(const mutable_buffer &out, const std::string &dict) noexcept; } struct ircd::rand::xoshiro256p { - u64x4 s - { - -1UL, -1UL, -1UL, -1UL - }; + uint64_t s[4]; - uint64_t operator()(); + xoshiro256p() noexcept; }; -inline uint64_t -ircd::rand::xoshiro256p::operator()() +template +inline decltype(auto) +ircd::rand::fill(T (&buf)[S]) +noexcept { + static_assert + ( + sizeof(buf) == sizeof(T) * S + ); + + const mutable_buffer mb + { + reinterpret_cast(buf), sizeof(buf) + }; + + fill(mb); + return buf; +} + +/// Random character from dictionary +inline char +ircd::rand::character(const std::string &dict) +noexcept +{ + assert(!dict.empty()); + const auto pos + { + integer(0, dict.size() - 1) + }; + + assert(pos < dict.size()); + return dict[pos]; +} + +inline +ircd::rand::xoshiro256p::xoshiro256p() +noexcept +{ + fill(s); +} + +inline uint64_t +ircd::rand::integer(xoshiro256p &state) +noexcept +{ + auto &s(state.s); + const u64 ret(s[0] + s[3]), t(s[1] << 17); + s[2] ^= s[0]; s[3] ^= s[1]; s[1] ^= s[2]; @@ -79,37 +128,4 @@ ircd::rand::xoshiro256p::operator()() #endif return ret; -}; - -/// Random character from dictionary -inline char -ircd::rand::character(const std::string &dict) -{ - assert(!dict.empty()); - const auto pos - { - integer(0, dict.size() - 1) - }; - - return dict.at(pos); -} - -/// Random integer in range (inclusive) -inline uint64_t -ircd::rand::integer(const uint64_t &min, - const uint64_t &max) -{ - std::uniform_int_distribution dist - { - min, max - }; - - return dist(mt); -} - -/// Random 64-bits -inline uint64_t -ircd::rand::integer() -{ - return mt(); } diff --git a/ircd/rand.cc b/ircd/rand.cc index 947729182..edd0c1690 100644 --- a/ircd/rand.cc +++ b/ircd/rand.cc @@ -44,8 +44,31 @@ decltype(ircd::rand::dict::numeric) ircd::rand::dict::numeric "0123456789" }; +ircd::string_view +ircd::rand::string(const mutable_buffer &out, + const std::string &dict) +noexcept +{ + assert(!dict.empty()); + std::uniform_int_distribution dist + { + 0, dict.size() - 1 + }; + + std::generate(data(out), data(out) + size(out), [&dict, &dist] + () -> char + { + const auto &pos(dist(mt)); + assert(pos < dict.size()); + return dict[pos]; + }); + + return out; +} + ircd::const_buffer ircd::rand::fill(const mutable_buffer &out) +noexcept { uint64_t *const __restrict__ val { @@ -67,26 +90,10 @@ ircd::rand::fill(const mutable_buffer &out) return out; } -ircd::string_view -ircd::rand::string(const mutable_buffer &out, - const std::string &dict) -{ - std::uniform_int_distribution dist - { - 0, dict.size() - 1 - }; - - std::generate(data(out), data(out) + size(out), [&dict, &dist] - { - return char(dict.at(dist(mt))); - }); - - return out; -} - template<> ircd::u512x1 ircd::rand::vector() +noexcept { return u64x8 { @@ -100,6 +107,7 @@ ircd::rand::vector() template<> ircd::u256x1 ircd::rand::vector() +noexcept { return u64x4 { @@ -111,9 +119,32 @@ ircd::rand::vector() template<> ircd::u128x1 ircd::rand::vector() +noexcept { return u64x2 { integer(), integer() }; } + +/// Random integer in range (inclusive) +uint64_t +ircd::rand::integer(const uint64_t &min, + const uint64_t &max) +noexcept +{ + std::uniform_int_distribution dist + { + min, max + }; + + return dist(mt); +} + +/// Random 64-bits +uint64_t +ircd::rand::integer() +noexcept +{ + return mt(); +}