Skip to content

Commit 14eb7d7

Browse files
authored
ofRandomDistributions: modularization of Mersenne-Twister engine (#8145)
1 parent 2bd8b45 commit 14eb7d7

6 files changed

Lines changed: 687 additions & 480 deletions

File tree

apps/devApps/RandomExplorer/src/Dist.hpp

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
struct Dist {
88

9-
inline static std::string base_url_ { "https://en.cppreference.com/w/cpp/numeric/random/" };
9+
inline static const std::string base_url_ { "https://en.cppreference.com/w/cpp/numeric/random/" };
1010
std::optional<std::string> url_;
1111
ofParameterGroup parameters_;
1212
ofColor color_ { 128, 128, 128 };
@@ -102,9 +102,6 @@ struct ConcreteDist : public Dist {
102102
ofSetColor(color_);
103103
ofDrawRectangle(0, 0, w, h);
104104

105-
ofSetColor(ofColor::darkRed);
106-
if (underflow_) ofDrawBitmapString("undershoot: " + ofToString(underflow_), w + 5, 58);
107-
if (overflow_) ofDrawBitmapString("overshoot: " + ofToString(overflow_), w + 5, 74);
108105

109106
ofSetColor(192, 192, 192, 255);
110107
ofDrawBitmapString(info_, w + 5, 35);
@@ -144,13 +141,20 @@ struct ConcreteDist : public Dist {
144141
} else if constexpr (std::is_same_v<T, glm::vec2>) {
145142

146143
ofSetColor(255, 255, 255, 96);
147-
for (const auto & d : data_)
148-
ofDrawCircle(d, .5);
144+
for (const auto & d : data_) {
145+
if (d.x > w || d.y > h) underflow_++;
146+
if (d.x < 0 || d.y < 0) overflow_++;
147+
ofDrawCircle(d, 0.5);
148+
}
149149

150150
} else if constexpr (std::is_same_v<T, glm::vec3>) {
151151

152152
ofSetColor(255, 255, 255, 32);
153153
of3dPrimitive prim;
154+
for (const auto & d : data_) {
155+
if (d.x > w || d.y > h) underflow_++;
156+
if (d.x < 0 || d.y < 0) overflow_++;
157+
}
154158
prim.getMesh().getVertices() = data_;
155159
prim.getMesh().setMode(OF_PRIMITIVE_POINTS);
156160
prim.rotateDeg(70, { 0.2, 0.3, 0.5 }); // just some perspective
@@ -165,6 +169,10 @@ struct ConcreteDist : public Dist {
165169
} else {
166170
ofDrawBitmapString("unsupported visualisation", 10, 10);
167171
}
172+
ofSetColor(ofColor::deepPink);
173+
if (underflow_) ofDrawBitmapString("undershoot: " + ofToString(underflow_), w + 5, 70);
174+
if (overflow_) ofDrawBitmapString("overshoot: " + ofToString(overflow_), w + 5, 86);
175+
168176
}
169177
ofPopMatrix();
170178
ofPopStyle();

apps/devApps/RandomExplorer/src/ofApp.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ void ofApp::setup() {
3030

3131
colorize();
3232

33-
auto y = panel_.getPosition().y + panel_.getHeight() + 120;
33+
auto y = panel_.getPosition().y + panel_.getHeight() + 110;
3434

3535
dists_["core"]->panel_.setPosition(10, y);
3636
dists_["special"]->panel_.setPosition(10 + col_w_, y);

apps/devApps/RandomExplorer/src/ofApp.h

Lines changed: 71 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ class ofApp : public ofBaseApp {
2020
ofParameter<size_t> size_ { "size (cube root)", 25, 1, 50 };
2121
ofParameter<unsigned long> seed_ { "seed", 0, 0, 1000 };
2222
ofParameter<void> reinit_ { "re-init engine" };
23-
ofParameter<bool> ok_color_ { "ok_color" };
24-
ofParameter<float> saturation_ { "saturation", 0.9 };
25-
ofParameter<float> value_ { "value", .25 };
23+
ofParameter<bool> ok_color_ { "ok_color", true };
24+
ofParameter<float> saturation_ { "saturation", 0.95 };
25+
ofParameter<float> value_ { "value", .45 };
2626
ofParameter<float> offset_ { "offset", 0 };
2727

2828
size_t col_w_ = 640;
@@ -66,74 +66,79 @@ class ofApp : public ofBaseApp {
6666
std::map<std::string, std::shared_ptr<DistGroup>> dists_ {
6767
{ "old",
6868
std::make_shared<DistGroup>(std::vector<std::shared_ptr<Dist>> {
69-
70-
std::make_shared<ConcreteDist<float>>("rand()", "old-skool (thread risky)\nbased on srand()", std::nullopt, std::vector<ofAbstractParameter *> { &rand_min_, &rand_max_ },
71-
[&] { return ofOldRandom(rand_min_, rand_max_); }) }) },
72-
73-
{ "core",
69+
std::make_shared<ConcreteDist<float>>("rand()", "old-skool (thread risky)\nbased on srand()",
70+
std::nullopt, std::vector<ofAbstractParameter *> { &rand_min_, &rand_max_ },
71+
[&] { return ofOldRandom(rand_min_, rand_max_); })
72+
})
73+
}, { "core",
7474
std::make_shared<DistGroup>(std::vector<std::shared_ptr<Dist>> {
75-
76-
std::make_shared<ConcreteDist<float>>("uniform <real>", "modern, thread safe\nright bound improbable", "uniform_real_distribution", std::vector<ofAbstractParameter *> { &uni_min_, &uni_max_ },
77-
[&] { return of::random::uniform<float>(uni_min_, uni_max_); }),
78-
79-
std::make_shared<ConcreteDist<int>>(
80-
"uniform <int>", "unambiguously\nincludes bounds", "uniform_int_distribution", std::vector<ofAbstractParameter *> { &uni_int_min_, &uni_int_max_ },
81-
[&] { return of::random::uniform<int>(uni_int_min_, uni_int_max_); }, 11, glm::vec2 { 0, 10 }, true),
82-
83-
std::make_shared<ConcreteDist<double>>(
84-
"normal", "also aliased to random::gaussian\for stochastic familiarity", "normal_distribution", std::vector<ofAbstractParameter *> { &norm_mean_, &norm_dev_ },
85-
[&] { return of::random::normal<double>(norm_mean_, norm_dev_); }, 101, glm::vec2 { 0, 200 }),
86-
87-
std::make_shared<ConcreteDist<float>>("exponential", "all in the title", "exponential_distribution", std::vector<ofAbstractParameter *> { &exp_lambda_ },
88-
[&] { return of::random::exponential<float>(exp_lambda_); }),
89-
90-
std::make_shared<ConcreteDist<int>>(
91-
"poisson", "for sparse, \npositive discrete\n(if mean > 12: ~= normal)", "poisson_distribution", std::vector<ofAbstractParameter *> { &poiss_mean_ },
92-
[&] { return of::random::poisson<int>(poiss_mean_); }, 21, glm::vec2 { 0, 20 }, true),
93-
75+
std::make_shared<ConcreteDist<float>>("uniform <real>", "modern, thread safe\nright bound improbable", "uniform_real_distribution",
76+
std::vector<ofAbstractParameter *> { &uni_min_, &uni_max_ },
77+
[&] { return of::random::uniform<float>(uni_min_, uni_max_); }),
78+
79+
std::make_shared<ConcreteDist<int>>("uniform <int>", "unambiguously\nincludes bounds", "uniform_int_distribution",
80+
std::vector<ofAbstractParameter *> { &uni_int_min_, &uni_int_max_ },
81+
[&] { return of::random::uniform<int>(uni_int_min_, uni_int_max_); }, 11, glm::vec2 { 0, 10 }, true),
82+
83+
std::make_shared<ConcreteDist<double>>("normal", "aliased to random::gaussian\nfor stochastic familiarity", "normal_distribution",
84+
std::vector<ofAbstractParameter *> { &norm_mean_, &norm_dev_ },
85+
[&] { return of::random::normal<double>(norm_mean_, norm_dev_); }, 101, glm::vec2 { 0, 200 }),
86+
87+
std::make_shared<ConcreteDist<float>>("exponential", "all in the title", "exponential_distribution",
88+
std::vector<ofAbstractParameter *> { &exp_lambda_ },
89+
[&] { return of::random::exponential<float>(exp_lambda_); }),
90+
91+
std::make_shared<ConcreteDist<int>>("poisson", "for sparse, \npositive discrete\n(if mean > 12: ~= normal)", "poisson_distribution",
92+
std::vector<ofAbstractParameter *> { &poiss_mean_ },
93+
[&] { return of::random::poisson<int>(poiss_mean_); }, 21, glm::vec2 { 0, 20 }, true),
94+
9495
// note int is used here instead of bool because of compiler complaints about "bit values" whatever
95-
std::make_shared<ConcreteDist<int>>(
96-
"bernoulli", "binary prob\ne.g. toss of a coin\naliased to of::random::yes", "bernoulli_distribution", std::vector<ofAbstractParameter *> { &yes_ },
97-
[&] { return of::random::bernoulli(yes_); }, 2, glm::vec2 { 0, 1 }, true) }) },
98-
99-
{ "special",
96+
std::make_shared<ConcreteDist<int>>("bernoulli", "binary prob\ne.g. toss of a coin\naliased to random::sometimes", "bernoulli_distribution",
97+
std::vector<ofAbstractParameter *> { &yes_ },
98+
[&] { return of::random::bernoulli(yes_); }, 2, glm::vec2 { 0, 1 }, true) })
99+
}, { "special",
100100
std::make_shared<DistGroup>(std::vector<std::shared_ptr<Dist>> {
101-
102-
std::make_shared<ConcreteDist<int>>(
103-
"lognormal", "like normal but log", "lognormal_distribution", std::vector<ofAbstractParameter *> { &log_mean_, &log_dev_ },
104-
[&] { return of::random::lognormal<int>(log_mean_, log_dev_); }, 21, glm::vec2 { 0, 20 }, true),
105-
106-
std::make_shared<ConcreteDist<float>>("gamma", "for special purposes", "gamma_distribution", std::vector<ofAbstractParameter *> { &gamma_alpha_, &gamma_beta_ },
107-
[&] { return of::random::gamma<int>(gamma_alpha_, gamma_beta_); }),
108-
109-
std::make_shared<ConcreteDist<float>>(
110-
"chi-squared", "cool energy bulge", "chi_squared_distribution", std::vector<ofAbstractParameter *> { &chi_n_ },
111-
[&] { return of::random::chi_squared<float>(chi_n_); }, 101, glm::vec2 { 0, 20 }),
112-
113-
std::make_shared<ConcreteDist<int>>(
114-
"binomial", "~normal for ints\nsquashes nicely on zero", "binomial_distribution", std::vector<ofAbstractParameter *> { &bin_p_, &bin_t_ },
115-
[&] { return of::random::binomial(bin_p_, bin_t_); }, 21, glm::vec2 { 0, 20 }, true),
116-
117-
std::make_shared<ConcreteDist<int>>(
118-
"geometric", "~expon for sparse ints\nwith no parameter", "geometric_distribution", std::vector<ofAbstractParameter *> {},
119-
[&] { return of::random::geometric<int>(); }, 21, glm::vec2 { 0, 20 }, true) }) },
120-
121-
{ "of",
101+
std::make_shared<ConcreteDist<int>>("lognormal", "like normal but log", "lognormal_distribution",
102+
std::vector<ofAbstractParameter *> { &log_mean_, &log_dev_ },
103+
[&] { return of::random::lognormal<int>(log_mean_, log_dev_); }, 21, glm::vec2 { 0, 20 }, true),
104+
105+
std::make_shared<ConcreteDist<float>>("gamma", "for special purposes", "gamma_distribution",
106+
std::vector<ofAbstractParameter *> { &gamma_alpha_, &gamma_beta_ },
107+
[&] { return of::random::gamma<float>(gamma_alpha_, gamma_beta_); }),
108+
109+
std::make_shared<ConcreteDist<float>>("chi-squared", "cool energy bulge", "chi_squared_distribution",
110+
std::vector<ofAbstractParameter *> { &chi_n_ },
111+
[&] { return of::random::chi_squared<float>(chi_n_); }, 101, glm::vec2 { 0, 20 }),
112+
113+
std::make_shared<ConcreteDist<int>>("binomial", "~normal for ints\nsquashes nicely on zero", "binomial_distribution",
114+
std::vector<ofAbstractParameter *> { &bin_p_, &bin_t_ },
115+
[&] { return of::random::binomial(bin_p_, bin_t_); }, 21, glm::vec2 { 0, 20 }, true),
116+
117+
std::make_shared<ConcreteDist<int>>("geometric", "~expon for sparse ints\nwith no parameter", "geometric_distribution",
118+
std::vector<ofAbstractParameter *> {},
119+
[&] { return of::random::geometric<int>(); }, 21, glm::vec2 { 0, 20 }, true)
120+
})
121+
}, { "of",
122122
std::make_shared<DistGroup>(std::vector<std::shared_ptr<Dist>> {
123-
124-
std::make_shared<ConcreteDist<float>>(
125-
"bound normal", "practical min/max\nwith enforced limits\n(allows to \"focus\")\nintuitiver", "normal_distribution", std::vector<ofAbstractParameter *> { &bn_min_, &bn_max_, &bn_focus_ }, [&] { return ofRandomBoundNormal<int>(bn_min_, bn_max_, bn_focus_); }, 101, glm::vec2 { 0, 200 }),
126-
127-
std::make_shared<ConcreteDist<glm::vec2>>(
128-
"vec2 uniform/axis", "all generators can\nbe typed vec2, 3 or 4", "uniform_int_distribution", std::vector<ofAbstractParameter *> { &vec_min_, &vec_max_ }, [&] { return of::random::uniform<glm::vec2>(vec_min_, vec_max_); }, 101, glm::vec2 { 0, 200 }),
129-
130-
std::make_shared<ConcreteDist<glm::vec2>>(
131-
"vec2 normal/axis", "vecN version can be\nrefined to vecN axis", "normal_distribution", std::vector<ofAbstractParameter *> { &vec_mean_, &vec_dev_ }, [&] { return of::random::gaussian<glm::vec2>(vec_mean_, vec_dev_); }, 101, glm::vec2 { 0, 200 }),
132-
133-
std::make_shared<ConcreteDist<glm::vec3>>(
134-
"vec3 gamma", "", "gamma_distribution", std::vector<ofAbstractParameter *> { &vec_gamma_a_, &vec_gamma_b_ }, [&] { return of::random::gamma<glm::vec3>(vec_gamma_a_, vec_gamma_b_); }, 101, glm::vec2 { 0, 200 }) }) }
123+
std::make_shared<ConcreteDist<float>>("bound normal", "practical min/max\nwith enforced limits\n(allows to \"focus\")\nintuitiver", "normal_distribution",
124+
std::vector<ofAbstractParameter *> { &bn_min_, &bn_max_, &bn_focus_ },
125+
[&] { return ofRandomBoundNormal<float>(bn_min_, bn_max_, bn_focus_); }, 101, glm::vec2 { 0, 200 }),
126+
127+
std::make_shared<ConcreteDist<glm::vec2>>("vec2 uniform/axis", "all generators can\nbe typed vec2, 3 or 4", "uniform_int_distribution",
128+
std::vector<ofAbstractParameter *> { &vec_min_, &vec_max_ },
129+
[&] { return of::random::uniform<glm::vec2>(vec_min_, vec_max_); }, 101, glm::vec2 { 0, 200 }),
130+
131+
std::make_shared<ConcreteDist<glm::vec2>>("vec2 normal/axis", "vecN version can be\nrefined to vecN axis", "normal_distribution",
132+
std::vector<ofAbstractParameter *> { &vec_mean_, &vec_dev_ },
133+
[&] { return of::random::gaussian<glm::vec2>(vec_mean_, vec_dev_); }, 101, glm::vec2 { 0, 200 }),
134+
135+
std::make_shared<ConcreteDist<glm::vec3>>("vec3 gamma", "", "gamma_distribution",
136+
std::vector<ofAbstractParameter *> { &vec_gamma_a_, &vec_gamma_b_ },
137+
[&] { return of::random::gamma<glm::vec3>(vec_gamma_a_, vec_gamma_b_); }, 101, glm::vec2 { 0, 200 })
138+
})
139+
}
135140
};
136-
141+
137142
public:
138143
auto rebuild_signatures() {
139144
dna_string_ = "1. first 8 numbers: ";
870 KB
Loading

0 commit comments

Comments
 (0)