I'm using std::random_device
and would like to check for its remaining entropy. According to cppreference.com:
std::random_device::entropy
double entropy() const noexcept;
[...]
Return value
The value of the device entropy, or zero if not applicable.
Notes
This function is not fully implemented in some standard libraries. For example, LLVM libc++ always returns zero even though the device is non-deterministic. In comparison, Microsoft Visual C++ implementation always returns 32, and boost.random returns 10.
The entropy of the Linux kernel device /dev/urandom may be obtained using ioctl RNDGETENTCNT - that's what std::random_device::entropy() in GNU libstdc++ uses as of version 8.1
So under Linux ang g++ >= 8.1, I should be good... but I'm not:
#include <random>
#include <iostream>
void drain_entropy(std::random_device& rd, std::size_t count = 1)
{
while (count --> 0) {
volatile const int discard = rd();
(void) discard;
}
}
int main()
{
std::random_device rd;
std::cout << "Entropy: " << rd.entropy() << '\n'; // Entropy: 32
drain_entropy(rd, 1'000'000);
std::cout << "Entropy: " << rd.entropy() << '\n'; // Entropy: 32
}
Live demo on Coliru (which runs under Linux, right?)
I'm expecting that generating numbers from the device drains its entropy. But it doesn't.
What's happening?
The library will not return an entropy value greater than the number of bits in its result type, which is 32 in this case.
See libstd code:
const int max = sizeof(result_type) * __CHAR_BIT__;
if (ent > max)
ent = max;
The documentation you linked to explains this:
Obtains an estimate of the random number device entropy, which is a floating-point value between 0 and log 2(max()+1) (which is equal to std::numeric_limits::digits).