forked from boostorg/random
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhistogram.cpp
165 lines (151 loc) · 5.25 KB
/
histogram.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/* boost histogram.cpp graphical verification of distribution functions
*
* Copyright Jens Maurer 2000
* Distributed under the Boost Software License, Version 1.0. (See
* accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* $Id$
*
* This test program allows to visibly examine the results of the
* distribution functions.
*/
#include <iostream>
#include <iomanip>
#include <vector>
#include <algorithm>
#include <cmath>
#include <string>
#include <boost/random.hpp>
void plot_histogram(const std::vector<int>& slots, int samples,
double from, double to)
{
int m = *std::max_element(slots.begin(), slots.end());
const int nRows = 20;
std::cout.setf(std::ios::fixed|std::ios::left);
std::cout.precision(5);
for(int r = 0; r < nRows; r++) {
double y = ((nRows - r) * double(m))/(nRows * samples);
std::cout << std::setw(10) << y << " ";
for(unsigned int col = 0; col < slots.size(); col++) {
char out = ' ';
if(slots[col]/double(samples) >= y)
out = 'x';
std::cout << out;
}
std::cout << std::endl;
}
std::cout << std::setw(12) << " "
<< std::setw(10) << from;
std::cout.setf(std::ios::right, std::ios::adjustfield);
std::cout << std::setw(slots.size()-10) << to << std::endl;
}
// I am not sure whether these two should be in the library as well
// maintain sum of NumberGenerator results
template<class NumberGenerator,
class Sum = typename NumberGenerator::result_type>
class sum_result
{
public:
typedef NumberGenerator base_type;
typedef typename base_type::result_type result_type;
explicit sum_result(const base_type & g) : gen(g), _sum(0) { }
result_type operator()() { result_type r = gen(); _sum += r; return r; }
base_type & base() { return gen; }
Sum sum() const { return _sum; }
void reset() { _sum = 0; }
private:
base_type gen;
Sum _sum;
};
// maintain square sum of NumberGenerator results
template<class NumberGenerator,
class Sum = typename NumberGenerator::result_type>
class squaresum_result
{
public:
typedef NumberGenerator base_type;
typedef typename base_type::result_type result_type;
explicit squaresum_result(const base_type & g) : gen(g), _sum(0) { }
result_type operator()() { result_type r = gen(); _sum += r*r; return r; }
base_type & base() { return gen; }
Sum squaresum() const { return _sum; }
void reset() { _sum = 0; }
private:
base_type gen;
Sum _sum;
};
template<class RNG>
void histogram(RNG base, int samples, double from, double to,
const std::string & name)
{
typedef squaresum_result<sum_result<RNG, double>, double > SRNG;
SRNG gen((sum_result<RNG, double>(base)));
const int nSlots = 60;
std::vector<int> slots(nSlots,0);
for(int i = 0; i < samples; i++) {
double val = gen();
if(val < from || val >= to) // early check avoids overflow
continue;
int slot = int((val-from)/(to-from) * nSlots);
if(slot < 0 || slot > (int)slots.size())
continue;
slots[slot]++;
}
std::cout << name << std::endl;
plot_histogram(slots, samples, from, to);
double mean = gen.base().sum() / samples;
std::cout << "mean: " << mean
<< " sigma: " << std::sqrt(gen.squaresum()/samples-mean*mean)
<< "\n" << std::endl;
}
template<class PRNG, class Dist>
inline boost::variate_generator<PRNG&, Dist> make_gen(PRNG & rng, Dist d)
{
return boost::variate_generator<PRNG&, Dist>(rng, d);
}
template<class PRNG>
void histograms()
{
PRNG rng;
using namespace boost;
histogram(make_gen(rng, uniform_smallint<>(0, 5)), 100000, -1, 6,
"uniform_smallint(0,5)");
histogram(make_gen(rng, uniform_int<>(0, 5)), 100000, -1, 6,
"uniform_int(0,5)");
histogram(make_gen(rng, uniform_real<>(0,1)), 100000, -0.5, 1.5,
"uniform_real(0,1)");
histogram(make_gen(rng, bernoulli_distribution<>(0.2)), 100000, -0.5, 1.5,
"bernoulli(0.2)");
histogram(make_gen(rng, binomial_distribution<>(4, 0.2)), 100000, -1, 5,
"binomial(4, 0.2)");
histogram(make_gen(rng, triangle_distribution<>(1, 2, 8)), 100000, 0, 10,
"triangle(1,2,8)");
histogram(make_gen(rng, geometric_distribution<>(5.0/6.0)), 100000, 0, 10,
"geometric(5/6)");
histogram(make_gen(rng, exponential_distribution<>(0.3)), 100000, 0, 10,
"exponential(0.3)");
histogram(make_gen(rng, cauchy_distribution<>()), 100000, -5, 5,
"cauchy");
histogram(make_gen(rng, lognormal_distribution<>(3, 2)), 100000, 0, 10,
"lognormal");
histogram(make_gen(rng, normal_distribution<>()), 100000, -3, 3,
"normal");
histogram(make_gen(rng, normal_distribution<>(0.5, 0.5)), 100000, -3, 3,
"normal(0.5, 0.5)");
histogram(make_gen(rng, poisson_distribution<>(1.5)), 100000, 0, 5,
"poisson(1.5)");
histogram(make_gen(rng, poisson_distribution<>(10)), 100000, 0, 20,
"poisson(10)");
histogram(make_gen(rng, gamma_distribution<>(0.5)), 100000, 0, 0.5,
"gamma(0.5)");
histogram(make_gen(rng, gamma_distribution<>(1)), 100000, 0, 3,
"gamma(1)");
histogram(make_gen(rng, gamma_distribution<>(2)), 100000, 0, 6,
"gamma(2)");
}
int main()
{
histograms<boost::mt19937>();
// histograms<boost::lagged_fibonacci607>();
}