iterator-style access to std::normal_distribution produces duplicate samples
If I have a std::normal_distribution
and create a stream and access samples via the iterator interface (random_stream.begin()
, etc.), I often see
the same sample appearing multiple times in a row. This does not happen if I access the values via the sequential functor-style access (random_stream()
). I assume this happens because is not a 1-to-1 mapping but in fact uses multiple uniform samples to generate 1 Gaussian sample.
Example code:
#include <cstdlib>
#include <iostream>
#include <iterator>
#include <random>
#include <random_iterator/Stream.hpp>
int main() {
random_iterator::philox rng(0);
std::normal_distribution<double> dist(0.0, 1.0);
std::cout << "===== fill via iterator =====" << std::endl;
auto rng_stream = random_iterator::make_stream(dist, rng, 0);
auto it = rng_stream.begin();
std::vector<double> samples(it, std::next(it, 30)); // generate 30 samples
std::copy(samples.cbegin(), samples.cend(), std::ostream_iterator<double>{std::cout, "\n"}); // print
std::cout << "===== fill functor-style =====" << std::endl;
auto rng_stream2 = random_iterator::make_stream(dist, rng, 1);
std::vector<double> samples2;
for (int i=0; i<30;++i) { // generate 30 samples
samples2.emplace_back(rng_stream2());
}
std::copy(samples2.cbegin(), samples2.cend(), std::ostream_iterator<double>{std::cout, "\n"}); //print
return EXIT_SUCCESS;
}
Output:
===== fill via iterator =====
-1.13801
-1.13801
1.53871
-0.302973
0.989557
-0.296058
1.30122
-0.876418
-0.876418
-0.876418
-0.876418
0.56402
0.56402
0.459638
1.4153
-2.06938
-0.495889
0.331192
0.73823
0.812443
-1.2216
0.535366
-1.35075
-1.73313
-0.426237
-1.75843
1.51708
1.51708
-1.3769
2.03956
===== fill functor-style =====
1.57125
0.283698
-0.388435
0.754173
0.128439
-1.88833
-0.159893
-0.0614132
-0.33022
0.21003
1.88945
-1.36752
0.230059
-1.24368
-2.58132
-0.2527
-0.0979393
0.0088204
-0.0225316
-0.268162
0.0494556
0.599011
-1.5681
1.96229
0.140006
0.866102
1.33881
0.954568
0.60675
1.64906