MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
Stochastic.cpp
Go to the documentation of this file.
1#include "Stochastic.hpp"
2
4
6
8 : m_engine(std::random_device {}())
9 , m_algorithm(algo)
10 , m_xorshift_state(std::random_device {}() | (static_cast<uint64_t>(std::random_device {}()) << 32))
11{
12 if (m_xorshift_state == 0)
13 m_xorshift_state = 0xDEADBEEFCAFEBABE;
14}
15
16void Stochastic::seed(uint64_t seed)
17{
18 m_engine.seed(static_cast<std::mt19937::result_type>(seed));
20 if (m_xorshift_state == 0)
21 m_xorshift_state = 0xDEADBEEFCAFEBABE;
23}
24
26{
27 if (m_algorithm != algo) {
28 m_algorithm = algo;
30 m_dist_dirty = true;
31 }
32}
33
34void Stochastic::configure(const std::string& key, std::any value)
35{
36 m_config[key] = std::move(value);
37 m_dist_dirty = true;
38}
39
40std::optional<std::any> Stochastic::get_config(const std::string& key) const
41{
42 auto it = m_config.find(key);
43 if (it != m_config.end()) {
44 return it->second;
45 }
46 return std::nullopt;
47}
48
49double Stochastic::operator()(double min, double max)
50{
51 validate_range(min, max);
52
53 switch (m_algorithm) {
58 return generate_memoryless(min, max);
59
61 return generate_perlin_impl(m_state.phase, 0.0, 0.0);
62
64 return generate_gendy_impl(min, max);
65
67 return generate_brownian_impl(min, max);
68
69 case Algorithm::PINK:
70 case Algorithm::BLUE:
71 return generate_colored_noise_impl(min, max);
72
73 default:
74 return generate_memoryless(min, max);
75 }
76}
77
78double Stochastic::at(double x, double y, double z)
79{
81 MF_WARN(Journal::Component::Kinesis, Journal::Context::Runtime, "Multi-dimensional access only supported for PERLIN algorithm. Falling back to memoryless generation.");
82 return (*this)(0.0, 1.0);
83 }
84 return generate_perlin_impl(x, y, z);
85}
86
87std::vector<double> Stochastic::batch(double min, double max, size_t count)
88{
89 validate_range(min, max);
90
91 std::vector<double> result;
92 result.reserve(count);
93
94 for (size_t i = 0; i < count; ++i) {
95 result.push_back((*this)(min, max));
96 }
97
98 return result;
99}
100
102{
103 m_state.reset();
104}
105
106double Stochastic::generate_memoryless(double min, double max)
107{
108 if (min != m_cached_min || max != m_cached_max) {
109 m_cached_min = min;
110 m_cached_max = max;
111 m_dist_dirty = true;
112 }
113
114 double raw_value = 0.0;
115
116 switch (m_algorithm) {
117 [[likely]] case Algorithm::UNIFORM:
118 return min + fast_uniform() * (max - min);
119
120 case Algorithm::NORMAL: {
122 raw_value = m_normal_dist(m_engine);
123 return std::clamp(raw_value, min, max);
124 }
125
128 raw_value = m_exponential_dist(m_engine);
129 raw_value /= max;
130 return min + raw_value * (max - min);
131 }
132
133 case Algorithm::POISSON: {
134 std::poisson_distribution<int> dist(static_cast<int>(max - min));
135 return static_cast<double>(dist(m_engine));
136 }
137
138 default:
139 return min + fast_uniform() * (max - min);
140 }
141}
142
143double Stochastic::generate_stateful(double min, double max)
144{
146 return m_state.current_value;
147}
148
149double Stochastic::generate_perlin_impl(double x, double y, double z)
150{
151 return 0.0;
152}
153
154double Stochastic::generate_gendy_impl(double min, double max)
155{
156 return min + fast_uniform() * (max - min);
157}
158
159double Stochastic::generate_brownian_impl(double min, double max)
160{
161 double step_size = 0.01;
162 if (auto cfg = get_config("step_size"); cfg.has_value()) {
163 step_size = std::any_cast<double>(*cfg);
164 }
165
166 double step = (fast_uniform() - 0.5) * 2.0 * step_size;
167 m_state.current_value += step;
168 m_state.current_value = std::clamp(m_state.current_value, min, max);
169
171 return m_state.current_value;
172}
173
174double Stochastic::generate_colored_noise_impl(double min, double max)
175{
176 return min + fast_uniform() * (max - min);
177}
178
179void Stochastic::validate_range(double min, double max) const
180{
181 if (min > max) {
182 error<std::invalid_argument>(Journal::Component::Kinesis, Journal::Context::Runtime, std::source_location::current(),
183 "Stochastic: min must be <= max. Received min: {}, max: {}", min, max);
184 }
185}
186
188{
189 if (!m_dist_dirty)
190 return;
191
192 const double range = max - min;
193
195 double spread = 4.0;
196 if (auto cfg = get_config("spread"); cfg.has_value()) {
197 spread = std::any_cast<double>(*cfg);
198 }
199 m_normal_dist = std::normal_distribution<double>(0.0, range / spread);
200 } else if (m_algorithm == Algorithm::EXPONENTIAL) {
201 m_exponential_dist = std::exponential_distribution<double>(1.0);
202 }
203
204 m_dist_dirty = false;
205}
206
207}
#define MF_WARN(comp, ctx,...)
size_t count
void validate_range(double min, double max) const
double generate_stateful(double min, double max)
double generate_gendy_impl(double min, double max)
std::map< std::string, std::any > m_config
void configure(const std::string &key, std::any value)
Configures algorithm-specific parameters.
void rebuild_distributions_if_needed(double min, double max)
std::vector< double > batch(double min, double max, size_t count)
Batch generation.
void reset_state()
Resets internal state for stateful algorithms.
double generate_brownian_impl(double min, double max)
std::optional< std::any > get_config(const std::string &key) const
Gets configuration parameter.
double generate_perlin_impl(double x, double y, double z)
double operator()(double min, double max)
Generates single value in range.
std::exponential_distribution< double > m_exponential_dist
double at(double x, double y=0.0, double z=0.0)
Multi-dimensional generation (Perlin, spatial noise)
void set_algorithm(Algorithm algo)
Changes active algorithm.
std::normal_distribution< double > m_normal_dist
double generate_memoryless(double min, double max)
double generate_colored_noise_impl(double min, double max)
void seed(uint64_t seed)
Seeds entropy source.
Unified generative infrastructure for stochastic and procedural algorithms.
@ Runtime
General runtime operations (default fallback)
@ Kinesis
General mathematical and physics algorithns.
Algorithm
Stochastic and procedural generation algorithms.