File indexing completed on 2025-02-21 09:30:07
0001 #pragma once
0002
0003 #include <cstdint>
0004 #include <functional>
0005 #include <mutex>
0006 #include <random>
0007
0008 #include <algorithms/detail/random.h>
0009 #include <algorithms/logger.h>
0010 #include <algorithms/service.h>
0011
0012 namespace algorithms {
0013
0014
0015
0016
0017
0018
0019
0020
0021 using RandomEngineCB = detail::CachedBitGenerator::GenFunc;
0022
0023
0024
0025 class Generator {
0026 public:
0027 Generator(const RandomEngineCB& gen, const size_t cache_size) : m_gen{gen, cache_size} {}
0028
0029 template <class Int = int> Int uniform_int(const Int min, const Int max) const {
0030 std::uniform_int_distribution<Int> d{min, max};
0031 std::lock_guard<std::mutex> lock{m_mutex};
0032 return d(m_gen);
0033 }
0034 template <class Float = double> Float uniform_double(const Float min, const Float max) const {
0035 std::uniform_real_distribution<Float> d{min, max};
0036 std::lock_guard<std::mutex> lock{m_mutex};
0037 return d(m_gen);
0038 }
0039 template <class Int = int> Int poisson(const Int mean) const {
0040 std::poisson_distribution<Int> d{mean};
0041 std::lock_guard<std::mutex> lock{m_mutex};
0042 return d(m_gen);
0043 }
0044 template <class Float = double> Float exponential(const Float lambda) const {
0045 std::exponential_distribution<Float> d{lambda};
0046 std::lock_guard<std::mutex> lock{m_mutex};
0047 return d(m_gen);
0048 }
0049 template <class Float = double> Float gaussian(const Float mu, const Float sigma) const {
0050 std::normal_distribution<Float> d{mu, sigma};
0051 std::lock_guard<std::mutex> lock{m_mutex};
0052 return d(m_gen);
0053 }
0054
0055 private:
0056 mutable detail::CachedBitGenerator m_gen;
0057 mutable std::mutex m_mutex;
0058 };
0059
0060
0061
0062
0063
0064 class RandomSvc : public LoggedService<RandomSvc> {
0065 public:
0066 using value_type = detail::CachedBitGenerator::result_type;
0067
0068 Generator generator() { return {m_gen, m_cache_size}; }
0069
0070 #if 0
0071 void init();
0072 void init(const RandomEngineCB& gen);
0073 #endif
0074 void init() {
0075 if (m_seed.hasValue()) {
0076 info() << "Custom random seed requested: " << m_seed << endmsg;
0077 m_gen = createEngine(m_seed);
0078 }
0079 }
0080 void init(const RandomEngineCB& gen) {
0081 info() << "Loading external generator function." << endmsg;
0082 m_gen = gen;
0083 if (m_seed.hasValue()) {
0084 warning() << "Custom random seed request ignored when using external generator function"
0085 << endmsg;
0086 }
0087 }
0088
0089 #if 0
0090 private:
0091 RandomEngineCB createEngine(const size_t seed = 1);
0092 #endif
0093 RandomEngineCB createEngine(const size_t seed = 1) {
0094 return [=](const size_t size) {
0095 static std::mutex m;
0096 static std::mt19937_64 gen{seed};
0097 std::lock_guard<std::mutex> lock{m};
0098 std::vector<value_type> ret(size);
0099 std::generate(ret.begin(), ret.end(), gen);
0100 return ret;
0101 };
0102 }
0103
0104
0105 private:
0106 RandomEngineCB m_gen{createEngine()};
0107 Property<size_t> m_seed{this, "seed", "Random seed for the internal random engine"};
0108 Property<size_t> m_cache_size{this, "cacheSize", 1024, "Cache size for each generator instance"};
0109 std::mutex m_mutex;
0110
0111 ALGORITHMS_DEFINE_LOGGED_SERVICE(RandomSvc)
0112 };
0113
0114 }