• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===----------------------------------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 // <random>
11 
12 // template<class RealType = double>
13 // class piecewise_constant_distribution
14 
15 // template<class _URNG> result_type operator()(_URNG& g);
16 
17 #include <random>
18 #include <vector>
19 #include <iterator>
20 #include <numeric>
21 #include <cassert>
22 
23 template <class T>
24 inline
25 T
sqr(T x)26 sqr(T x)
27 {
28     return x*x;
29 }
30 
main()31 int main()
32 {
33     {
34         typedef std::piecewise_constant_distribution<> D;
35         typedef std::mt19937_64 G;
36         G g;
37         double b[] = {10, 14, 16, 17};
38         double p[] = {25, 62.5, 12.5};
39         const size_t Np = sizeof(p) / sizeof(p[0]);
40         D d(b, b+Np+1, p);
41         const int N = 1000000;
42         std::vector<D::result_type> u;
43         for (int i = 0; i < N; ++i)
44         {
45             D::result_type v = d(g);
46             assert(d.min() <= v && v < d.max());
47             u.push_back(v);
48         }
49         std::vector<double> prob(std::begin(p), std::end(p));
50         double s = std::accumulate(prob.begin(), prob.end(), 0.0);
51         for (int i = 0; i < prob.size(); ++i)
52             prob[i] /= s;
53         std::sort(u.begin(), u.end());
54         for (int i = 0; i < Np; ++i)
55         {
56             typedef std::vector<D::result_type>::iterator I;
57             I lb = std::lower_bound(u.begin(), u.end(), b[i]);
58             I ub = std::lower_bound(u.begin(), u.end(), b[i+1]);
59             const size_t Ni = ub - lb;
60             if (prob[i] == 0)
61                 assert(Ni == 0);
62             else
63             {
64                 assert(std::abs((double)Ni/N - prob[i]) / prob[i] < .01);
65                 double mean = std::accumulate(lb, ub, 0.0) / Ni;
66                 double var = 0;
67                 double skew = 0;
68                 double kurtosis = 0;
69                 for (I j = lb; j != ub; ++j)
70                 {
71                     double d = (*j - mean);
72                     double d2 = sqr(d);
73                     var += d2;
74                     skew += d * d2;
75                     kurtosis += d2 * d2;
76                 }
77                 var /= Ni;
78                 double dev = std::sqrt(var);
79                 skew /= Ni * dev * var;
80                 kurtosis /= Ni * var * var;
81                 kurtosis -= 3;
82                 double x_mean = (b[i+1] + b[i]) / 2;
83                 double x_var = sqr(b[i+1] - b[i]) / 12;
84                 double x_skew = 0;
85                 double x_kurtosis = -6./5;
86                 assert(std::abs((mean - x_mean) / x_mean) < 0.01);
87                 assert(std::abs((var - x_var) / x_var) < 0.01);
88                 assert(std::abs(skew - x_skew) < 0.01);
89                 assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.01);
90             }
91         }
92     }
93     {
94         typedef std::piecewise_constant_distribution<> D;
95         typedef std::mt19937_64 G;
96         G g;
97         double b[] = {10, 14, 16, 17};
98         double p[] = {0, 62.5, 12.5};
99         const size_t Np = sizeof(p) / sizeof(p[0]);
100         D d(b, b+Np+1, p);
101         const int N = 1000000;
102         std::vector<D::result_type> u;
103         for (int i = 0; i < N; ++i)
104         {
105             D::result_type v = d(g);
106             assert(d.min() <= v && v < d.max());
107             u.push_back(v);
108         }
109         std::vector<double> prob(std::begin(p), std::end(p));
110         double s = std::accumulate(prob.begin(), prob.end(), 0.0);
111         for (int i = 0; i < prob.size(); ++i)
112             prob[i] /= s;
113         std::sort(u.begin(), u.end());
114         for (int i = 0; i < Np; ++i)
115         {
116             typedef std::vector<D::result_type>::iterator I;
117             I lb = std::lower_bound(u.begin(), u.end(), b[i]);
118             I ub = std::lower_bound(u.begin(), u.end(), b[i+1]);
119             const size_t Ni = ub - lb;
120             if (prob[i] == 0)
121                 assert(Ni == 0);
122             else
123             {
124                 assert(std::abs((double)Ni/N - prob[i]) / prob[i] < .01);
125                 double mean = std::accumulate(lb, ub, 0.0) / Ni;
126                 double var = 0;
127                 double skew = 0;
128                 double kurtosis = 0;
129                 for (I j = lb; j != ub; ++j)
130                 {
131                     double d = (*j - mean);
132                     double d2 = sqr(d);
133                     var += d2;
134                     skew += d * d2;
135                     kurtosis += d2 * d2;
136                 }
137                 var /= Ni;
138                 double dev = std::sqrt(var);
139                 skew /= Ni * dev * var;
140                 kurtosis /= Ni * var * var;
141                 kurtosis -= 3;
142                 double x_mean = (b[i+1] + b[i]) / 2;
143                 double x_var = sqr(b[i+1] - b[i]) / 12;
144                 double x_skew = 0;
145                 double x_kurtosis = -6./5;
146                 assert(std::abs((mean - x_mean) / x_mean) < 0.01);
147                 assert(std::abs((var - x_var) / x_var) < 0.01);
148                 assert(std::abs(skew - x_skew) < 0.01);
149                 assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.01);
150             }
151         }
152     }
153     {
154         typedef std::piecewise_constant_distribution<> D;
155         typedef std::mt19937_64 G;
156         G g;
157         double b[] = {10, 14, 16, 17};
158         double p[] = {25, 0, 12.5};
159         const size_t Np = sizeof(p) / sizeof(p[0]);
160         D d(b, b+Np+1, p);
161         const int N = 1000000;
162         std::vector<D::result_type> u;
163         for (int i = 0; i < N; ++i)
164         {
165             D::result_type v = d(g);
166             assert(d.min() <= v && v < d.max());
167             u.push_back(v);
168         }
169         std::vector<double> prob(std::begin(p), std::end(p));
170         double s = std::accumulate(prob.begin(), prob.end(), 0.0);
171         for (int i = 0; i < prob.size(); ++i)
172             prob[i] /= s;
173         std::sort(u.begin(), u.end());
174         for (int i = 0; i < Np; ++i)
175         {
176             typedef std::vector<D::result_type>::iterator I;
177             I lb = std::lower_bound(u.begin(), u.end(), b[i]);
178             I ub = std::lower_bound(u.begin(), u.end(), b[i+1]);
179             const size_t Ni = ub - lb;
180             if (prob[i] == 0)
181                 assert(Ni == 0);
182             else
183             {
184                 assert(std::abs((double)Ni/N - prob[i]) / prob[i] < .01);
185                 double mean = std::accumulate(lb, ub, 0.0) / Ni;
186                 double var = 0;
187                 double skew = 0;
188                 double kurtosis = 0;
189                 for (I j = lb; j != ub; ++j)
190                 {
191                     double d = (*j - mean);
192                     double d2 = sqr(d);
193                     var += d2;
194                     skew += d * d2;
195                     kurtosis += d2 * d2;
196                 }
197                 var /= Ni;
198                 double dev = std::sqrt(var);
199                 skew /= Ni * dev * var;
200                 kurtosis /= Ni * var * var;
201                 kurtosis -= 3;
202                 double x_mean = (b[i+1] + b[i]) / 2;
203                 double x_var = sqr(b[i+1] - b[i]) / 12;
204                 double x_skew = 0;
205                 double x_kurtosis = -6./5;
206                 assert(std::abs((mean - x_mean) / x_mean) < 0.01);
207                 assert(std::abs((var - x_var) / x_var) < 0.01);
208                 assert(std::abs(skew - x_skew) < 0.01);
209                 assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.01);
210             }
211         }
212     }
213     {
214         typedef std::piecewise_constant_distribution<> D;
215         typedef std::mt19937_64 G;
216         G g;
217         double b[] = {10, 14, 16, 17};
218         double p[] = {25, 62.5, 0};
219         const size_t Np = sizeof(p) / sizeof(p[0]);
220         D d(b, b+Np+1, p);
221         const int N = 1000000;
222         std::vector<D::result_type> u;
223         for (int i = 0; i < N; ++i)
224         {
225             D::result_type v = d(g);
226             assert(d.min() <= v && v < d.max());
227             u.push_back(v);
228         }
229         std::vector<double> prob(std::begin(p), std::end(p));
230         double s = std::accumulate(prob.begin(), prob.end(), 0.0);
231         for (int i = 0; i < prob.size(); ++i)
232             prob[i] /= s;
233         std::sort(u.begin(), u.end());
234         for (int i = 0; i < Np; ++i)
235         {
236             typedef std::vector<D::result_type>::iterator I;
237             I lb = std::lower_bound(u.begin(), u.end(), b[i]);
238             I ub = std::lower_bound(u.begin(), u.end(), b[i+1]);
239             const size_t Ni = ub - lb;
240             if (prob[i] == 0)
241                 assert(Ni == 0);
242             else
243             {
244                 assert(std::abs((double)Ni/N - prob[i]) / prob[i] < .01);
245                 double mean = std::accumulate(lb, ub, 0.0) / Ni;
246                 double var = 0;
247                 double skew = 0;
248                 double kurtosis = 0;
249                 for (I j = lb; j != ub; ++j)
250                 {
251                     double d = (*j - mean);
252                     double d2 = sqr(d);
253                     var += d2;
254                     skew += d * d2;
255                     kurtosis += d2 * d2;
256                 }
257                 var /= Ni;
258                 double dev = std::sqrt(var);
259                 skew /= Ni * dev * var;
260                 kurtosis /= Ni * var * var;
261                 kurtosis -= 3;
262                 double x_mean = (b[i+1] + b[i]) / 2;
263                 double x_var = sqr(b[i+1] - b[i]) / 12;
264                 double x_skew = 0;
265                 double x_kurtosis = -6./5;
266                 assert(std::abs((mean - x_mean) / x_mean) < 0.01);
267                 assert(std::abs((var - x_var) / x_var) < 0.01);
268                 assert(std::abs(skew - x_skew) < 0.01);
269                 assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.01);
270             }
271         }
272     }
273     {
274         typedef std::piecewise_constant_distribution<> D;
275         typedef std::mt19937_64 G;
276         G g;
277         double b[] = {10, 14, 16, 17};
278         double p[] = {25, 0, 0};
279         const size_t Np = sizeof(p) / sizeof(p[0]);
280         D d(b, b+Np+1, p);
281         const int N = 100000;
282         std::vector<D::result_type> u;
283         for (int i = 0; i < N; ++i)
284         {
285             D::result_type v = d(g);
286             assert(d.min() <= v && v < d.max());
287             u.push_back(v);
288         }
289         std::vector<double> prob(std::begin(p), std::end(p));
290         double s = std::accumulate(prob.begin(), prob.end(), 0.0);
291         for (int i = 0; i < prob.size(); ++i)
292             prob[i] /= s;
293         std::sort(u.begin(), u.end());
294         for (int i = 0; i < Np; ++i)
295         {
296             typedef std::vector<D::result_type>::iterator I;
297             I lb = std::lower_bound(u.begin(), u.end(), b[i]);
298             I ub = std::lower_bound(u.begin(), u.end(), b[i+1]);
299             const size_t Ni = ub - lb;
300             if (prob[i] == 0)
301                 assert(Ni == 0);
302             else
303             {
304                 assert(std::abs((double)Ni/N - prob[i]) / prob[i] < .01);
305                 double mean = std::accumulate(lb, ub, 0.0) / Ni;
306                 double var = 0;
307                 double skew = 0;
308                 double kurtosis = 0;
309                 for (I j = lb; j != ub; ++j)
310                 {
311                     double d = (*j - mean);
312                     double d2 = sqr(d);
313                     var += d2;
314                     skew += d * d2;
315                     kurtosis += d2 * d2;
316                 }
317                 var /= Ni;
318                 double dev = std::sqrt(var);
319                 skew /= Ni * dev * var;
320                 kurtosis /= Ni * var * var;
321                 kurtosis -= 3;
322                 double x_mean = (b[i+1] + b[i]) / 2;
323                 double x_var = sqr(b[i+1] - b[i]) / 12;
324                 double x_skew = 0;
325                 double x_kurtosis = -6./5;
326                 assert(std::abs((mean - x_mean) / x_mean) < 0.01);
327                 assert(std::abs((var - x_var) / x_var) < 0.01);
328                 assert(std::abs(skew - x_skew) < 0.01);
329                 assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.01);
330             }
331         }
332     }
333     {
334         typedef std::piecewise_constant_distribution<> D;
335         typedef std::mt19937_64 G;
336         G g;
337         double b[] = {10, 14, 16, 17};
338         double p[] = {0, 25, 0};
339         const size_t Np = sizeof(p) / sizeof(p[0]);
340         D d(b, b+Np+1, p);
341         const int N = 100000;
342         std::vector<D::result_type> u;
343         for (int i = 0; i < N; ++i)
344         {
345             D::result_type v = d(g);
346             assert(d.min() <= v && v < d.max());
347             u.push_back(v);
348         }
349         std::vector<double> prob(std::begin(p), std::end(p));
350         double s = std::accumulate(prob.begin(), prob.end(), 0.0);
351         for (int i = 0; i < prob.size(); ++i)
352             prob[i] /= s;
353         std::sort(u.begin(), u.end());
354         for (int i = 0; i < Np; ++i)
355         {
356             typedef std::vector<D::result_type>::iterator I;
357             I lb = std::lower_bound(u.begin(), u.end(), b[i]);
358             I ub = std::lower_bound(u.begin(), u.end(), b[i+1]);
359             const size_t Ni = ub - lb;
360             if (prob[i] == 0)
361                 assert(Ni == 0);
362             else
363             {
364                 assert(std::abs((double)Ni/N - prob[i]) / prob[i] < .01);
365                 double mean = std::accumulate(lb, ub, 0.0) / Ni;
366                 double var = 0;
367                 double skew = 0;
368                 double kurtosis = 0;
369                 for (I j = lb; j != ub; ++j)
370                 {
371                     double d = (*j - mean);
372                     double d2 = sqr(d);
373                     var += d2;
374                     skew += d * d2;
375                     kurtosis += d2 * d2;
376                 }
377                 var /= Ni;
378                 double dev = std::sqrt(var);
379                 skew /= Ni * dev * var;
380                 kurtosis /= Ni * var * var;
381                 kurtosis -= 3;
382                 double x_mean = (b[i+1] + b[i]) / 2;
383                 double x_var = sqr(b[i+1] - b[i]) / 12;
384                 double x_skew = 0;
385                 double x_kurtosis = -6./5;
386                 assert(std::abs((mean - x_mean) / x_mean) < 0.01);
387                 assert(std::abs((var - x_var) / x_var) < 0.01);
388                 assert(std::abs(skew - x_skew) < 0.01);
389                 assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.01);
390             }
391         }
392     }
393     {
394         typedef std::piecewise_constant_distribution<> D;
395         typedef std::mt19937_64 G;
396         G g;
397         double b[] = {10, 14, 16, 17};
398         double p[] = {0, 0, 1};
399         const size_t Np = sizeof(p) / sizeof(p[0]);
400         D d(b, b+Np+1, p);
401         const int N = 100000;
402         std::vector<D::result_type> u;
403         for (int i = 0; i < N; ++i)
404         {
405             D::result_type v = d(g);
406             assert(d.min() <= v && v < d.max());
407             u.push_back(v);
408         }
409         std::vector<double> prob(std::begin(p), std::end(p));
410         double s = std::accumulate(prob.begin(), prob.end(), 0.0);
411         for (int i = 0; i < prob.size(); ++i)
412             prob[i] /= s;
413         std::sort(u.begin(), u.end());
414         for (int i = 0; i < Np; ++i)
415         {
416             typedef std::vector<D::result_type>::iterator I;
417             I lb = std::lower_bound(u.begin(), u.end(), b[i]);
418             I ub = std::lower_bound(u.begin(), u.end(), b[i+1]);
419             const size_t Ni = ub - lb;
420             if (prob[i] == 0)
421                 assert(Ni == 0);
422             else
423             {
424                 assert(std::abs((double)Ni/N - prob[i]) / prob[i] < .01);
425                 double mean = std::accumulate(lb, ub, 0.0) / Ni;
426                 double var = 0;
427                 double skew = 0;
428                 double kurtosis = 0;
429                 for (I j = lb; j != ub; ++j)
430                 {
431                     double d = (*j - mean);
432                     double d2 = sqr(d);
433                     var += d2;
434                     skew += d * d2;
435                     kurtosis += d2 * d2;
436                 }
437                 var /= Ni;
438                 double dev = std::sqrt(var);
439                 skew /= Ni * dev * var;
440                 kurtosis /= Ni * var * var;
441                 kurtosis -= 3;
442                 double x_mean = (b[i+1] + b[i]) / 2;
443                 double x_var = sqr(b[i+1] - b[i]) / 12;
444                 double x_skew = 0;
445                 double x_kurtosis = -6./5;
446                 assert(std::abs((mean - x_mean) / x_mean) < 0.01);
447                 assert(std::abs((var - x_var) / x_var) < 0.01);
448                 assert(std::abs(skew - x_skew) < 0.01);
449                 assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.01);
450             }
451         }
452     }
453     {
454         typedef std::piecewise_constant_distribution<> D;
455         typedef std::mt19937_64 G;
456         G g;
457         double b[] = {10, 14, 16};
458         double p[] = {75, 25};
459         const size_t Np = sizeof(p) / sizeof(p[0]);
460         D d(b, b+Np+1, p);
461         const int N = 100000;
462         std::vector<D::result_type> u;
463         for (int i = 0; i < N; ++i)
464         {
465             D::result_type v = d(g);
466             assert(d.min() <= v && v < d.max());
467             u.push_back(v);
468         }
469         std::vector<double> prob(std::begin(p), std::end(p));
470         double s = std::accumulate(prob.begin(), prob.end(), 0.0);
471         for (int i = 0; i < prob.size(); ++i)
472             prob[i] /= s;
473         std::sort(u.begin(), u.end());
474         for (int i = 0; i < Np; ++i)
475         {
476             typedef std::vector<D::result_type>::iterator I;
477             I lb = std::lower_bound(u.begin(), u.end(), b[i]);
478             I ub = std::lower_bound(u.begin(), u.end(), b[i+1]);
479             const size_t Ni = ub - lb;
480             if (prob[i] == 0)
481                 assert(Ni == 0);
482             else
483             {
484                 assert(std::abs((double)Ni/N - prob[i]) / prob[i] < .01);
485                 double mean = std::accumulate(lb, ub, 0.0) / Ni;
486                 double var = 0;
487                 double skew = 0;
488                 double kurtosis = 0;
489                 for (I j = lb; j != ub; ++j)
490                 {
491                     double d = (*j - mean);
492                     double d2 = sqr(d);
493                     var += d2;
494                     skew += d * d2;
495                     kurtosis += d2 * d2;
496                 }
497                 var /= Ni;
498                 double dev = std::sqrt(var);
499                 skew /= Ni * dev * var;
500                 kurtosis /= Ni * var * var;
501                 kurtosis -= 3;
502                 double x_mean = (b[i+1] + b[i]) / 2;
503                 double x_var = sqr(b[i+1] - b[i]) / 12;
504                 double x_skew = 0;
505                 double x_kurtosis = -6./5;
506                 assert(std::abs((mean - x_mean) / x_mean) < 0.01);
507                 assert(std::abs((var - x_var) / x_var) < 0.01);
508                 assert(std::abs(skew - x_skew) < 0.01);
509                 assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.01);
510             }
511         }
512     }
513     {
514         typedef std::piecewise_constant_distribution<> D;
515         typedef std::mt19937_64 G;
516         G g;
517         double b[] = {10, 14, 16};
518         double p[] = {0, 25};
519         const size_t Np = sizeof(p) / sizeof(p[0]);
520         D d(b, b+Np+1, p);
521         const int N = 100000;
522         std::vector<D::result_type> u;
523         for (int i = 0; i < N; ++i)
524         {
525             D::result_type v = d(g);
526             assert(d.min() <= v && v < d.max());
527             u.push_back(v);
528         }
529         std::vector<double> prob(std::begin(p), std::end(p));
530         double s = std::accumulate(prob.begin(), prob.end(), 0.0);
531         for (int i = 0; i < prob.size(); ++i)
532             prob[i] /= s;
533         std::sort(u.begin(), u.end());
534         for (int i = 0; i < Np; ++i)
535         {
536             typedef std::vector<D::result_type>::iterator I;
537             I lb = std::lower_bound(u.begin(), u.end(), b[i]);
538             I ub = std::lower_bound(u.begin(), u.end(), b[i+1]);
539             const size_t Ni = ub - lb;
540             if (prob[i] == 0)
541                 assert(Ni == 0);
542             else
543             {
544                 assert(std::abs((double)Ni/N - prob[i]) / prob[i] < .01);
545                 double mean = std::accumulate(lb, ub, 0.0) / Ni;
546                 double var = 0;
547                 double skew = 0;
548                 double kurtosis = 0;
549                 for (I j = lb; j != ub; ++j)
550                 {
551                     double d = (*j - mean);
552                     double d2 = sqr(d);
553                     var += d2;
554                     skew += d * d2;
555                     kurtosis += d2 * d2;
556                 }
557                 var /= Ni;
558                 double dev = std::sqrt(var);
559                 skew /= Ni * dev * var;
560                 kurtosis /= Ni * var * var;
561                 kurtosis -= 3;
562                 double x_mean = (b[i+1] + b[i]) / 2;
563                 double x_var = sqr(b[i+1] - b[i]) / 12;
564                 double x_skew = 0;
565                 double x_kurtosis = -6./5;
566                 assert(std::abs((mean - x_mean) / x_mean) < 0.01);
567                 assert(std::abs((var - x_var) / x_var) < 0.01);
568                 assert(std::abs(skew - x_skew) < 0.01);
569                 assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.01);
570             }
571         }
572     }
573     {
574         typedef std::piecewise_constant_distribution<> D;
575         typedef std::mt19937_64 G;
576         G g;
577         double b[] = {10, 14, 16};
578         double p[] = {1, 0};
579         const size_t Np = sizeof(p) / sizeof(p[0]);
580         D d(b, b+Np+1, p);
581         const int N = 100000;
582         std::vector<D::result_type> u;
583         for (int i = 0; i < N; ++i)
584         {
585             D::result_type v = d(g);
586             assert(d.min() <= v && v < d.max());
587             u.push_back(v);
588         }
589         std::vector<double> prob(std::begin(p), std::end(p));
590         double s = std::accumulate(prob.begin(), prob.end(), 0.0);
591         for (int i = 0; i < prob.size(); ++i)
592             prob[i] /= s;
593         std::sort(u.begin(), u.end());
594         for (int i = 0; i < Np; ++i)
595         {
596             typedef std::vector<D::result_type>::iterator I;
597             I lb = std::lower_bound(u.begin(), u.end(), b[i]);
598             I ub = std::lower_bound(u.begin(), u.end(), b[i+1]);
599             const size_t Ni = ub - lb;
600             if (prob[i] == 0)
601                 assert(Ni == 0);
602             else
603             {
604                 assert(std::abs((double)Ni/N - prob[i]) / prob[i] < .01);
605                 double mean = std::accumulate(lb, ub, 0.0) / Ni;
606                 double var = 0;
607                 double skew = 0;
608                 double kurtosis = 0;
609                 for (I j = lb; j != ub; ++j)
610                 {
611                     double d = (*j - mean);
612                     double d2 = sqr(d);
613                     var += d2;
614                     skew += d * d2;
615                     kurtosis += d2 * d2;
616                 }
617                 var /= Ni;
618                 double dev = std::sqrt(var);
619                 skew /= Ni * dev * var;
620                 kurtosis /= Ni * var * var;
621                 kurtosis -= 3;
622                 double x_mean = (b[i+1] + b[i]) / 2;
623                 double x_var = sqr(b[i+1] - b[i]) / 12;
624                 double x_skew = 0;
625                 double x_kurtosis = -6./5;
626                 assert(std::abs((mean - x_mean) / x_mean) < 0.01);
627                 assert(std::abs((var - x_var) / x_var) < 0.01);
628                 assert(std::abs(skew - x_skew) < 0.01);
629                 assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.01);
630             }
631         }
632     }
633     {
634         typedef std::piecewise_constant_distribution<> D;
635         typedef std::mt19937_64 G;
636         G g;
637         double b[] = {10, 14};
638         double p[] = {1};
639         const size_t Np = sizeof(p) / sizeof(p[0]);
640         D d(b, b+Np+1, p);
641         const int N = 100000;
642         std::vector<D::result_type> u;
643         for (int i = 0; i < N; ++i)
644         {
645             D::result_type v = d(g);
646             assert(d.min() <= v && v < d.max());
647             u.push_back(v);
648         }
649         std::vector<double> prob(std::begin(p), std::end(p));
650         double s = std::accumulate(prob.begin(), prob.end(), 0.0);
651         for (int i = 0; i < prob.size(); ++i)
652             prob[i] /= s;
653         std::sort(u.begin(), u.end());
654         for (int i = 0; i < Np; ++i)
655         {
656             typedef std::vector<D::result_type>::iterator I;
657             I lb = std::lower_bound(u.begin(), u.end(), b[i]);
658             I ub = std::lower_bound(u.begin(), u.end(), b[i+1]);
659             const size_t Ni = ub - lb;
660             if (prob[i] == 0)
661                 assert(Ni == 0);
662             else
663             {
664                 assert(std::abs((double)Ni/N - prob[i]) / prob[i] < .01);
665                 double mean = std::accumulate(lb, ub, 0.0) / Ni;
666                 double var = 0;
667                 double skew = 0;
668                 double kurtosis = 0;
669                 for (I j = lb; j != ub; ++j)
670                 {
671                     double d = (*j - mean);
672                     double d2 = sqr(d);
673                     var += d2;
674                     skew += d * d2;
675                     kurtosis += d2 * d2;
676                 }
677                 var /= Ni;
678                 double dev = std::sqrt(var);
679                 skew /= Ni * dev * var;
680                 kurtosis /= Ni * var * var;
681                 kurtosis -= 3;
682                 double x_mean = (b[i+1] + b[i]) / 2;
683                 double x_var = sqr(b[i+1] - b[i]) / 12;
684                 double x_skew = 0;
685                 double x_kurtosis = -6./5;
686                 assert(std::abs((mean - x_mean) / x_mean) < 0.01);
687                 assert(std::abs((var - x_var) / x_var) < 0.01);
688                 assert(std::abs(skew - x_skew) < 0.01);
689                 assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.01);
690             }
691         }
692     }
693 }
694