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