Skip to content

Instantly share code, notes, and snippets.

@Sam-Belliveau
Last active February 7, 2019 00:50
Show Gist options
  • Select an option

  • Save Sam-Belliveau/e14c364f7b07b7ec63d0d3a1c357501b to your computer and use it in GitHub Desktop.

Select an option

Save Sam-Belliveau/e14c364f7b07b7ec63d0d3a1c357501b to your computer and use it in GitHub Desktop.
a replacement for std::random_device that lets you change the result type, and uses a buffer.
#ifndef SAMS_RANDOM_DEVICE_HPP
#define SAMS_RANDOM_DEVICE_HPP
#include <cstddef> // std::size_t
#include <fstream> // std::ifstream
#include <ostream> // std::ostream
#include <limits> // min and max
#include <cmath> // std::log2 - entropy
template<class RT = unsigned, std::size_t BufferSize = 0x100 / sizeof(RT)>
class RandomDevice
{
public:
// types
typedef RT result_type;
// generator characteristics
static inline constexpr result_type min() { return std::numeric_limits<RT>::min(); }
static inline constexpr result_type max() { return std::numeric_limits<RT>::max(); }
// constructors
RandomDevice(const char* __token = "/dev/urandom")
{
_random_data = std::ifstream(__token, std::ios::in | std::ios::binary);
_buffer = new result_type[BufferSize];
updateBuffer();
}
~RandomDevice()
{
_random_data.close();
delete[] _buffer;
}
// generating functions
result_type operator() ()
{
if(_index >= BufferSize) { updateBuffer(); }
return _buffer[_index++];
}
friend std::ostream& operator<<(std::ostream& out, const RandomDevice& rng)
{
out << rng();
return out;
}
// entropy
double entropy() const noexcept
{
std::size_t byte_count[0x100] = {};
const std::uint8_t* raw_array = reinterpret_cast<const std::uint8_t*>(_buffer);
const std::size_t raw_size = BufferSize * sizeof(result_type);
for(std::size_t i = 0; i < raw_size; ++i)
++byte_count[raw_array[i]];
double entropy = 0;
for(double count : byte_count)
{
if(count != 0)
{
const double p = double(count) / double(raw_size);
entropy -= p * std::log2(p) / 8.0;
}
}
return entropy;
}
private:
// no copy functions
RandomDevice(const RandomDevice&); // = delete;
RandomDevice& operator=(const RandomDevice&); // = delete;
// random device file
std::ifstream _random_data;
// random buffer
std::size_t _index;
result_type* _buffer;
void updateBuffer()
{
_index = 0;
_random_data.read(reinterpret_cast<char*>(_buffer), BufferSize * sizeof(result_type));
}
};
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment