JayBeams  0.1
Another project to have fun coding.
ut_histogram.cpp
Go to the documentation of this file.
1 #include <jb/histogram.hpp>
2 
3 #include <boost/test/unit_test.hpp>
4 
5 #include <limits>
6 
7 /**
8  * Helper types and objects to test the jb::histogram class.
9  */
10 namespace {
11 
12 double t_interpolate(double x_a, double x_b, double y_a, double s, double q) {
13  return x_a + (q - y_a) * (x_b - x_a) / s;
14 }
15 
16 int t_interpolate(int x_a, int x_b, double y_a, double s, double q) {
17  return int(std::floor(x_a + (q - y_a) * (x_b - x_a) / s));
18 }
19 
20 template <typename T>
21 struct test_binning {
22  typedef T sample_type;
23 
24  static sample_type const min;
25  static sample_type const max;
26 
27  sample_type histogram_min() const {
28  return min;
29  }
30  sample_type histogram_max() const {
31  return max;
32  }
33  sample_type theoretical_min() const {
34  return std::numeric_limits<int>::min();
35  }
36  sample_type theoretical_max() const {
37  return std::numeric_limits<int>::max();
38  }
39  std::size_t sample2bin(sample_type x) const {
40  if (x < min or x > max) {
41  throw std::invalid_argument("Invalid sample value in sample2bin()");
42  }
43  return static_cast<std::size_t>(x - min);
44  }
45  sample_type bin2sample(std::size_t i) const {
46  return min + i;
47  }
48  sample_type interpolate(
49  sample_type x_a, sample_type x_b, double y_a, double s, double q) const {
50  return t_interpolate(x_a, x_b, y_a, s, q);
51  }
52 };
53 
54 template <typename T>
55 T const test_binning<T>::min = 20;
56 template <typename T>
57 T const test_binning<T>::max = 30;
58 
59 typedef jb::histogram<test_binning<int>> tested_histogram;
60 
61 } // anonymous namespace
62 
63 /**
64  * @test Verify that a simple histogram can be initialized.
65  */
66 BOOST_AUTO_TEST_CASE(histogram_initialization) {
67  tested_histogram h;
68  BOOST_CHECK_EQUAL(h.nsamples(), 0);
69  BOOST_CHECK_EQUAL(h.underflow_count(), 0);
70  BOOST_CHECK_EQUAL(h.overflow_count(), 0);
71 }
72 
73 /**
74  * @test Verify that a simple histogram underflow operations work.
75  */
76 BOOST_AUTO_TEST_CASE(histogram_underflow) {
77  tested_histogram h;
78  h.sample(10);
79  BOOST_CHECK_EQUAL(h.nsamples(), 1);
80  BOOST_CHECK_EQUAL(h.underflow_count(), 1);
81  BOOST_CHECK_EQUAL(h.overflow_count(), 0);
82  BOOST_CHECK_EQUAL(h.observed_min(), 10);
83  BOOST_CHECK_EQUAL(h.observed_max(), 10);
84 
85  h.sample(5);
86  h.sample(5);
87  h.sample(5);
88  BOOST_CHECK_EQUAL(h.nsamples(), 4);
89  BOOST_CHECK_EQUAL(h.underflow_count(), 4);
90  BOOST_CHECK_EQUAL(h.overflow_count(), 0);
91  BOOST_CHECK_EQUAL(h.observed_min(), 5);
92  BOOST_CHECK_EQUAL(h.observed_max(), 10);
93 
94  h.weighted_sample(5, 2);
95  BOOST_CHECK_EQUAL(h.nsamples(), 6);
96  BOOST_CHECK_EQUAL(h.underflow_count(), 6);
97  BOOST_CHECK_EQUAL(h.overflow_count(), 0);
98  BOOST_CHECK_EQUAL(h.observed_min(), 5);
99  BOOST_CHECK_EQUAL(h.observed_max(), 10);
100 
101  h.weighted_sample(50, 0);
102  BOOST_CHECK_EQUAL(h.nsamples(), 6);
103  BOOST_CHECK_EQUAL(h.underflow_count(), 6);
104  BOOST_CHECK_EQUAL(h.overflow_count(), 0);
105  BOOST_CHECK_EQUAL(h.observed_min(), 5);
106  BOOST_CHECK_EQUAL(h.observed_max(), 10);
107 }
108 
109 /**
110  * @test Verify that a simple histogram overflow operations work.
111  */
112 BOOST_AUTO_TEST_CASE(histogram_overflow) {
113  tested_histogram h;
114  h.sample(40);
115  BOOST_CHECK_EQUAL(h.nsamples(), 1);
116  BOOST_CHECK_EQUAL(h.underflow_count(), 0);
117  BOOST_CHECK_EQUAL(h.overflow_count(), 1);
118  BOOST_CHECK_EQUAL(h.observed_min(), 40);
119  BOOST_CHECK_EQUAL(h.observed_max(), 40);
120 
121  h.sample(45);
122  h.sample(45);
123  h.sample(45);
124  BOOST_CHECK_EQUAL(h.nsamples(), 4);
125  BOOST_CHECK_EQUAL(h.underflow_count(), 0);
126  BOOST_CHECK_EQUAL(h.overflow_count(), 4);
127  BOOST_CHECK_EQUAL(h.observed_min(), 40);
128  BOOST_CHECK_EQUAL(h.observed_max(), 45);
129 
130  h.weighted_sample(45, 2);
131  BOOST_CHECK_EQUAL(h.nsamples(), 6);
132  BOOST_CHECK_EQUAL(h.underflow_count(), 0);
133  BOOST_CHECK_EQUAL(h.overflow_count(), 6);
134  BOOST_CHECK_EQUAL(h.observed_min(), 40);
135  BOOST_CHECK_EQUAL(h.observed_max(), 45);
136 }
137 
138 /**
139  * @test Verify that the mean estimator works as expected.
140  */
141 BOOST_AUTO_TEST_CASE(histogram_mean_simple) {
142  tested_histogram h;
143  BOOST_CHECK_THROW(h.estimated_mean(), std::invalid_argument);
144  h.sample(25);
145  h.sample(25);
146  h.sample(25);
147  h.sample(25);
148  BOOST_CHECK_EQUAL(h.estimated_mean(), 25);
149  h.sample(27);
150  h.sample(27);
151  h.sample(27);
152  h.sample(27);
153  BOOST_CHECK_EQUAL(h.estimated_mean(), 26);
154 }
155 
156 /**
157  * @test Verify that the mean estimator works as expected.
158  */
159 BOOST_AUTO_TEST_CASE(histogram_mean_underflow) {
160  tested_histogram h;
161  h.sample(0);
162  h.sample(0);
163  h.sample(0);
164  BOOST_CHECK_EQUAL(h.estimated_mean(), 10);
165 }
166 
167 /**
168  * @test Verify that the mean estimator works as expected.
169  */
170 BOOST_AUTO_TEST_CASE(histogram_mean_overflow) {
171  tested_histogram h;
172  h.sample(40);
173  h.sample(40);
174  h.sample(40);
175  BOOST_CHECK_EQUAL(h.estimated_mean(), 35);
176 }
177 
178 /**
179  * @test Verify that the mean estimator works as expected.
180  */
181 BOOST_AUTO_TEST_CASE(histogram_mean_complex) {
182  tested_histogram h;
183  h.sample(0);
184  h.sample(0);
185  h.weighted_sample(20, 3);
186  h.sample(50);
187  BOOST_CHECK_EQUAL(h.estimated_mean(), 20);
188 }
189 
190 /**
191  * @test Verify that the quantile estimator works as expected.
192  */
193 BOOST_AUTO_TEST_CASE(histogram_quantile_simple) {
194  tested_histogram h;
195  BOOST_CHECK_THROW(h.estimated_quantile(0.0), std::invalid_argument);
196 
197  h.sample(20);
198  BOOST_CHECK_EQUAL(h.estimated_quantile(0.0), 20);
199  BOOST_CHECK_EQUAL(h.estimated_quantile(0.5), 20);
200  BOOST_CHECK_EQUAL(h.estimated_quantile(1.0), 21);
201 
202  BOOST_CHECK_THROW(h.estimated_quantile(-1.0), std::invalid_argument);
203  BOOST_CHECK_THROW(h.estimated_quantile(2.00), std::invalid_argument);
204 
205  h.sample(21);
206  h.sample(22);
207  BOOST_CHECK_EQUAL(h.estimated_quantile(0.0), 20);
208  BOOST_CHECK_EQUAL(h.estimated_quantile(0.5), 21);
209  BOOST_CHECK_EQUAL(h.estimated_quantile(1.0), 23);
210 
211  h.sample(23);
212  h.sample(24);
213  h.sample(25);
214  h.sample(26);
215  h.sample(27);
216  h.sample(28);
217  BOOST_CHECK_EQUAL(h.estimated_quantile(0.00), 20);
218  BOOST_CHECK_EQUAL(h.estimated_quantile(0.25), 22);
219  BOOST_CHECK_EQUAL(h.estimated_quantile(0.50), 24);
220  BOOST_CHECK_EQUAL(h.estimated_quantile(0.75), 26);
221  BOOST_CHECK_EQUAL(h.estimated_quantile(1.00), 29);
222 }
223 
224 /**
225  * @test Verify that the quantile estimator works as expected.
226  */
227 BOOST_AUTO_TEST_CASE(histogram_quantile_float) {
228  typedef jb::histogram<test_binning<double>> double_histogram;
229  double_histogram h;
230 
231  BOOST_CHECK_THROW(h.estimated_quantile(0), std::invalid_argument);
232 
233  h.sample(20);
234  double eps = 100 * std::numeric_limits<double>::epsilon();
235  BOOST_CHECK_CLOSE(h.estimated_quantile(0.00), 20.00, eps);
236  BOOST_CHECK_CLOSE(h.estimated_quantile(0.25), 20.25, eps);
237  BOOST_CHECK_CLOSE(h.estimated_quantile(0.50), 20.50, eps);
238  BOOST_CHECK_CLOSE(h.estimated_quantile(0.75), 20.75, eps);
239  BOOST_CHECK_CLOSE(h.estimated_quantile(1.00), 21.00, eps);
240 
241  h.sample(21);
242  h.sample(22);
243  h.sample(23);
244  BOOST_CHECK_CLOSE(h.estimated_quantile(0.00), 20.0, eps);
245  BOOST_CHECK_CLOSE(h.estimated_quantile(0.25), 21.0, eps);
246  BOOST_CHECK_CLOSE(h.estimated_quantile(0.50), 22.0, eps);
247  BOOST_CHECK_CLOSE(h.estimated_quantile(0.75), 23.0, eps);
248  BOOST_CHECK_CLOSE(h.estimated_quantile(1.00), 24.0, eps);
249 
250  h.sample(24);
251  h.sample(25);
252  h.sample(26);
253  h.sample(27);
254  BOOST_CHECK_CLOSE(h.estimated_quantile(0.00), 20.0, eps);
255  BOOST_CHECK_CLOSE(h.estimated_quantile(0.25), 22.0, eps);
256  BOOST_CHECK_CLOSE(h.estimated_quantile(0.50), 24.0, eps);
257  BOOST_CHECK_CLOSE(h.estimated_quantile(0.75), 26.0, eps);
258  BOOST_CHECK_CLOSE(h.estimated_quantile(1.00), 28.0, eps);
259 }
260 
261 BOOST_AUTO_TEST_CASE(histogram_quantile_underflow) {
262  typedef jb::histogram<test_binning<double>> double_histogram;
263  double_histogram h;
264  double eps = 100 * std::numeric_limits<double>::epsilon();
265 
266  h.sample(10);
267  BOOST_CHECK_CLOSE(h.estimated_quantile(0.00), 10.0, eps);
268  BOOST_CHECK_CLOSE(h.estimated_quantile(0.25), 12.5, eps);
269  BOOST_CHECK_CLOSE(h.estimated_quantile(0.50), 15.0, eps);
270  BOOST_CHECK_CLOSE(h.estimated_quantile(0.75), 17.5, eps);
271  BOOST_CHECK_CLOSE(h.estimated_quantile(1.00), 20.0, eps);
272 }
273 
274 BOOST_AUTO_TEST_CASE(histogram_quantile_overflow) {
275  typedef jb::histogram<test_binning<double>> double_histogram;
276  double_histogram h;
277  double eps = 100 * std::numeric_limits<double>::epsilon();
278 
279  h.sample(40);
280  BOOST_CHECK_CLOSE(h.estimated_quantile(0.00), 30.0, eps);
281  BOOST_CHECK_CLOSE(h.estimated_quantile(0.25), 32.5, eps);
282  BOOST_CHECK_CLOSE(h.estimated_quantile(0.50), 35.0, eps);
283  BOOST_CHECK_CLOSE(h.estimated_quantile(0.75), 37.5, eps);
284  BOOST_CHECK_CLOSE(h.estimated_quantile(1.00), 40.0, eps);
285 }
286 
287 BOOST_AUTO_TEST_CASE(histogram_quantile_complex) {
288  typedef jb::histogram<test_binning<double>> double_histogram;
289  double_histogram h;
290  double eps = 100 * std::numeric_limits<double>::epsilon();
291 
292  // i : 10 20 21 22 23 24 25 26 27 28 29 30 40
293  // sum(N_i): 0 1 4 4 4 4 4 9 9 9 9 9 10
294  // cum_dens: 0 .1 .4 .5 .6 .7 .8 .82 .84 .86 .88 .9 1.0
295 
296  h.sample(10);
297  h.sample(20);
298  h.sample(20);
299  h.sample(20);
300  h.sample(20);
301  h.sample(25);
302  h.sample(25);
303  h.sample(25);
304  h.sample(25);
305  h.sample(40);
306  BOOST_CHECK_CLOSE(h.estimated_quantile(0.00), 10.0, eps);
307  BOOST_CHECK_CLOSE(h.estimated_quantile(0.05), 15.0, eps);
308  BOOST_CHECK_CLOSE(h.estimated_quantile(0.10), 20.0, eps);
309  BOOST_CHECK_CLOSE(h.estimated_quantile(0.25), 20.375, eps);
310  BOOST_CHECK_CLOSE(h.estimated_quantile(0.50), 21.0, eps);
311  BOOST_CHECK_CLOSE(h.estimated_quantile(0.90), 26.0, eps);
312  BOOST_CHECK_CLOSE(h.estimated_quantile(0.95), 35.0, eps);
313  BOOST_CHECK_CLOSE(h.estimated_quantile(1.00), 40.0, eps);
314 }
void sample(sample_type const &t)
Record a new sample.
Definition: histogram.hpp:197
A histogram class with controllable binning and range strategy.
Definition: histogram.hpp:46
BOOST_AUTO_TEST_CASE(histogram_initialization)