Program Listing for File random_generator.h¶
↰ Return to documentation for file (include/random_generator.h)
//
// Created by stuermer on 3/27/17.
//
#ifndef ECHELLESIMULATOR_RANDOM_GENERATOR_H
#define ECHELLESIMULATOR_RANDOM_GENERATOR_H
#include <vector>
#include "stdlib.h"
#include <random>
#include <algorithm>
#include <type_traits>
template<class T>
class RandomGenerator {
public:
virtual T draw() = 0;
virtual std::vector<T> draw(size_t n) = 0;
virtual T operator()() = 0;
};
template<class T>
class RG_uniform_real : RandomGenerator<T> {
public:
RG_uniform_real() {
this->distribution = std::uniform_real_distribution<T>();
std::random_device rdev{};
this->generator.seed(rdev());
};
RG_uniform_real(int seed) {
this->distribution = std::uniform_real_distribution<T>();
this->generator.seed(seed);
};
RG_uniform_real(T min, T max) {
this->distribution = std::uniform_real_distribution<T>(min, max);
std::random_device rdev{};
this->generator.seed(rdev());
};
RG_uniform_real(int seed, T min, T max) {
this->distribution = std::uniform_real_distribution<T>(min, max);
this->generator.seed(seed);
}
std::vector<T> draw(size_t n) {
std::vector<T> data(n);
std::generate(data.begin(), data.end(), [this]() { return distribution(generator); });
return data;
};
private:
std::uniform_real_distribution<T> distribution;
std::default_random_engine generator;
};
template<class T>
class RG_uniform_int : RandomGenerator<T> {
public:
RG_uniform_int() {
this->distribution = std::uniform_int_distribution<T>();
std::random_device rdev{};
this->generator.seed(rdev());
};
RG_uniform_int(int seed) {
this->distribution = std::uniform_int_distribution<T>();
this->generator.seed(seed);
};
RG_uniform_int(T min, T max) {
this->distribution = std::uniform_int_distribution<T>(min, max);
std::random_device rdev{};
this->generator.seed(rdev());
};
RG_uniform_int(int seed, T min, T max) {
this->distribution = std::uniform_int_distribution<T>(min, max);
this->generator.seed(seed);
};
std::vector<T> draw(size_t n) {
std::vector<T> data(n);
std::generate(data.begin(), data.end(), [this]() { return distribution(generator); });
return data;
}
private:
std::uniform_int_distribution<T> distribution;
std::default_random_engine generator;
};
template<class FloatType = double,
class Generator = std::mt19937>
class piecewise_linear_RNG : public RandomGenerator<FloatType> {
public:
typedef FloatType result_type;
typedef Generator generator_type;
typedef std::piecewise_constant_distribution<FloatType> distribution_type;
// default constructor
explicit piecewise_linear_RNG(std::vector<FloatType> values, std::vector<FloatType> weights,
Generator &&_eng = Generator{std::random_device{}()}) : eng(std::move(_eng)),
dist(values.begin(),
values.end(),
weights.begin()) {}
// construct from existing pre-defined engine
explicit piecewise_linear_RNG(std::vector<FloatType> values, std::vector<FloatType> weights, const Generator &_eng)
: eng(_eng), dist(values.begin(), values.end(), weights.begin()) {}
// generate next random value in distribution (equivalent to next() in above code)
result_type draw() { return dist(eng); }
std::vector<result_type> draw(size_t n) {
std::vector<result_type> data(n);
std::generate(data.begin(), data.end(), [this]() { return dist(eng); });
return data;
}
result_type operator()() { return dist(eng); }
private:
generator_type eng;
distribution_type dist;
};
template<class FloatType = double,
class Generator = std::mt19937>
class discrete_RNG : public RandomGenerator<FloatType> {
public:
typedef FloatType result_type;
typedef Generator generator_type;
typedef std::discrete_distribution<int> distribution_type;
// default constructor
explicit discrete_RNG(std::vector<FloatType> _values, std::vector<FloatType> _weights,
Generator &&_eng = Generator{std::random_device{}()}) : eng(std::move(_eng)), values(_values),
dist(_weights.begin(),
_weights.end()) {}
// construct from existing pre-defined engine
explicit discrete_RNG(std::vector<FloatType> _values, std::vector<FloatType> _weights, const Generator &_eng)
: eng(_eng), values(_values), dist(_weights.begin(), _weights.end()) {}
// generate next random value in distribution (equivalent to next() in above code)
result_type draw() { return values[dist(eng)]; }
std::vector<result_type> draw(size_t n) {
std::vector<result_type> data(n);
std::generate(data.begin(), data.end(), [this]() { return values[dist(eng)]; });
return data;
}
result_type operator()() { return values[dist(eng)]; }
private:
generator_type eng;
std::vector<result_type> values;
distribution_type dist;
};
#endif //ECHELLESIMULATOR_RANDOM_GENERATOR_H