mirror of
https://github.com/matrix-construct/construct
synced 2025-04-08 02:41:45 +02:00
ircd::rand: Improve xoshiro256p default values; improve interface consistency.
ircd::rand: Reorg iface; deinline mersenne twister so it's not emitted everywhere.
This commit is contained in:
parent
20204d5917
commit
b798192c15
2 changed files with 117 additions and 70 deletions
|
@ -31,41 +31,90 @@ namespace ircd::rand
|
||||||
extern std::mt19937_64 mt;
|
extern std::mt19937_64 mt;
|
||||||
|
|
||||||
// Random integer
|
// Random integer
|
||||||
uint64_t integer();
|
uint64_t integer() noexcept;
|
||||||
uint64_t integer(const uint64_t &min, const uint64_t &max); // inclusive
|
uint64_t integer(const uint64_t &min, const uint64_t &max) noexcept; // inclusive
|
||||||
|
uint64_t integer(xoshiro256p &) noexcept;
|
||||||
|
|
||||||
// Random vector
|
// Random vector
|
||||||
template<class T> T vector() = delete;
|
template<class T> T vector() noexcept = delete;
|
||||||
template<> u128x1 vector();
|
template<> u128x1 vector() noexcept;
|
||||||
template<> u256x1 vector();
|
template<> u256x1 vector() noexcept;
|
||||||
template<> u512x1 vector();
|
template<> u512x1 vector() noexcept;
|
||||||
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
// Random fill of buffer
|
// Random fill of buffer
|
||||||
const_buffer fill(const mutable_buffer &out);
|
const_buffer fill(const mutable_buffer &out) noexcept;
|
||||||
|
|
||||||
|
// Random fill of array
|
||||||
|
template<class T,
|
||||||
|
size_t S>
|
||||||
|
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
|
struct ircd::rand::xoshiro256p
|
||||||
{
|
{
|
||||||
u64x4 s
|
uint64_t s[4];
|
||||||
{
|
|
||||||
-1UL, -1UL, -1UL, -1UL
|
|
||||||
};
|
|
||||||
|
|
||||||
uint64_t operator()();
|
xoshiro256p() noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline uint64_t
|
template<class T,
|
||||||
ircd::rand::xoshiro256p::operator()()
|
size_t S>
|
||||||
|
inline decltype(auto)
|
||||||
|
ircd::rand::fill(T (&buf)[S])
|
||||||
|
noexcept
|
||||||
{
|
{
|
||||||
|
static_assert
|
||||||
|
(
|
||||||
|
sizeof(buf) == sizeof(T) * S
|
||||||
|
);
|
||||||
|
|
||||||
|
const mutable_buffer mb
|
||||||
|
{
|
||||||
|
reinterpret_cast<char *>(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
|
const u64
|
||||||
ret(s[0] + s[3]),
|
ret(s[0] + s[3]),
|
||||||
t(s[1] << 17);
|
t(s[1] << 17);
|
||||||
|
|
||||||
s[2] ^= s[0];
|
s[2] ^= s[0];
|
||||||
s[3] ^= s[1];
|
s[3] ^= s[1];
|
||||||
s[1] ^= s[2];
|
s[1] ^= s[2];
|
||||||
|
@ -79,37 +128,4 @@ ircd::rand::xoshiro256p::operator()()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return ret;
|
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<uint64_t> dist
|
|
||||||
{
|
|
||||||
min, max
|
|
||||||
};
|
|
||||||
|
|
||||||
return dist(mt);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Random 64-bits
|
|
||||||
inline uint64_t
|
|
||||||
ircd::rand::integer()
|
|
||||||
{
|
|
||||||
return mt();
|
|
||||||
}
|
}
|
||||||
|
|
65
ircd/rand.cc
65
ircd/rand.cc
|
@ -44,8 +44,31 @@ decltype(ircd::rand::dict::numeric) ircd::rand::dict::numeric
|
||||||
"0123456789"
|
"0123456789"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ircd::string_view
|
||||||
|
ircd::rand::string(const mutable_buffer &out,
|
||||||
|
const std::string &dict)
|
||||||
|
noexcept
|
||||||
|
{
|
||||||
|
assert(!dict.empty());
|
||||||
|
std::uniform_int_distribution<size_t> 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::const_buffer
|
||||||
ircd::rand::fill(const mutable_buffer &out)
|
ircd::rand::fill(const mutable_buffer &out)
|
||||||
|
noexcept
|
||||||
{
|
{
|
||||||
uint64_t *const __restrict__ val
|
uint64_t *const __restrict__ val
|
||||||
{
|
{
|
||||||
|
@ -67,26 +90,10 @@ ircd::rand::fill(const mutable_buffer &out)
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ircd::string_view
|
|
||||||
ircd::rand::string(const mutable_buffer &out,
|
|
||||||
const std::string &dict)
|
|
||||||
{
|
|
||||||
std::uniform_int_distribution<size_t> dist
|
|
||||||
{
|
|
||||||
0, dict.size() - 1
|
|
||||||
};
|
|
||||||
|
|
||||||
std::generate(data(out), data(out) + size(out), [&dict, &dist]
|
|
||||||
{
|
|
||||||
return char(dict.at(dist(mt)));
|
|
||||||
});
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
ircd::u512x1
|
ircd::u512x1
|
||||||
ircd::rand::vector()
|
ircd::rand::vector()
|
||||||
|
noexcept
|
||||||
{
|
{
|
||||||
return u64x8
|
return u64x8
|
||||||
{
|
{
|
||||||
|
@ -100,6 +107,7 @@ ircd::rand::vector()
|
||||||
template<>
|
template<>
|
||||||
ircd::u256x1
|
ircd::u256x1
|
||||||
ircd::rand::vector()
|
ircd::rand::vector()
|
||||||
|
noexcept
|
||||||
{
|
{
|
||||||
return u64x4
|
return u64x4
|
||||||
{
|
{
|
||||||
|
@ -111,9 +119,32 @@ ircd::rand::vector()
|
||||||
template<>
|
template<>
|
||||||
ircd::u128x1
|
ircd::u128x1
|
||||||
ircd::rand::vector()
|
ircd::rand::vector()
|
||||||
|
noexcept
|
||||||
{
|
{
|
||||||
return u64x2
|
return u64x2
|
||||||
{
|
{
|
||||||
integer(), integer()
|
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<uint64_t> dist
|
||||||
|
{
|
||||||
|
min, max
|
||||||
|
};
|
||||||
|
|
||||||
|
return dist(mt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Random 64-bits
|
||||||
|
uint64_t
|
||||||
|
ircd::rand::integer()
|
||||||
|
noexcept
|
||||||
|
{
|
||||||
|
return mt();
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue