#pragma once
#include <random>
#include <iostream>
#include <stdexcept>
#include <cstdint>
class RNG
{
public:
/* Constructor for RNG class.
*
* @param Amount of numbers to generate
* @param Minimum number in range to generate
* @param Maximum number in range to generate
*
* The constructor also instanstiates the variable m_generator
* with a new random_device.
*/
RNG(const uint64_t &amount, const uint64_t &min, const uint64_t &max)
: m_generator((std::random_device())())
, m_floor(min)
, m_numLeft(amount)
, m_lastInt(min)
, m_ceiling(max)
{
}
// Return a bool to determine if there are any numbers left to generate
const bool HasNext()
{
return m_numLeft > 0;
}
// Generate the next random number
const uint64_t NextInt()
{
if (m_numLeft > 0)
{
// Partition the range of numbers to generate from
uint64_t rangeSize = (m_ceiling - m_lastInt) / m_numLeft;
// Initialize random generator
std::uniform_int_distribution<uint64_t> rg(m_floor, rangeSize);
// Generate random number
uint64_t randomNumber = rg(m_generator) + m_lastInt + 1;
// Set m_lastInt to randomNumber so that randomNumber is not generated again
m_lastInt = randomNumber;
m_numLeft--;
return randomNumber;
}
else
{
throw std::out_of_range("Exceeded amount of random numbers to generate.");
}
}
private:
uint64_t m_floor;
uint64_t m_ceiling;
uint64_t m_lastInt;
uint64_t m_numLeft;
std::mt19937_64 m_generator;
};