Given a random number engine e
of arbitrary type E
, how can I generate a random uint64_t
over the full range?
Something like this, where the needs_random()
function wants a random uint64_t
and the blah()
function is written in the modern <random>
style which accepts a random engine of any type E
.
void needs_random(uint64_t r);
template <typename E>
void blah(E& engine) {
// ...
needs_random(???);
}
Specifically, I am trying to seed an xorshift random number generator from an arbitrary engine e
, and the xorshift generator needs two uint64_t
values as seeds.
To be portable, just use unsigned long long
with std::uniform_int_distribution
(or any other distribution you need):
#include <type_traits>
#include <cstdint>
#include <random>
#include <iostream>
void needs_random(uint64_t r) {
std::cout << r << "\n";
}
template <typename E>
void blah(E& engine) {
std::uniform_int_distribution<unsigned long long> dis(
std::numeric_limits<std::uint64_t>::min(),
std::numeric_limits<std::uint64_t>::max()
);
needs_random(dis(engine));
}
int main() {
std::random_device rd;
std::mt19937 gen(rd());
blah(gen);
blah(gen);
}
The type unsigned long long
is guaranteed to be at least 64-bits wide. The implicit integer conversion from unsigned long long
to uint64_t
should extract only the least significant 64 bits of the number.
This code will only be sub-optimal on platforms where like sizeof(unsigned long long) * CHAR_BIT > 64
, cause the higher bits will just be unused. But the code will still be portable to such platforms and will still work.