Lumiera  0.pre.03
»edit your freedom«
random-draw-test.cpp
Go to the documentation of this file.
1 /*
2  RandomDraw(Test) - verify the component builder for random selected values
3 
4  Copyright (C)
5  2023, Hermann Vosseler <Ichthyostega@web.de>
6 
7   **Lumiera** is free software; you can redistribute it and/or modify it
8   under the terms of the GNU General Public License as published by the
9   Free Software Foundation; either version 2 of the License, or (at your
10   option) any later version. See the file COPYING for further details.
11 
12 * *****************************************************************/
13 
20 #include "lib/test/run.hpp"
21 #include "lib/random-draw.hpp"
22 #include "lib/format-string.hpp"
23 #include "lib/test/test-helper.hpp"
24 
25 #include <array>
26 
27 
28 
29 namespace lib {
30 namespace test{
31 
32  using util::_Fmt;
33  using lib::meta::_FunRet;
34  using err::LUMIERA_ERROR_LIFECYCLE;
35 
36 
37 
38  namespace { // policy and configuration for test...
39 
40  double ctxParameter = 1.0;
41 
50  : function<Limited<int, 2,-2, 0>(size_t)>
51  {
53  static size_t defaultSrc (size_t hash) { return hash; }
54 
56  template<class SIG>
57  struct Adaptor
58  {
59  static_assert (not sizeof(SIG), "Unable to adapt given functor.");
60  };
61 
63  template<typename RES>
64  struct Adaptor<RES(uint,uint)>
65  {
66  template<typename FUN>
67  static auto
68  build (FUN&& fun)
69  {
70  return [functor=std::forward<FUN>(fun)]
71  (size_t hash) -> _FunRet<FUN>
72  {
73  return functor(uint(hash/64), uint(hash%64));
74  };
75  }
76  };
77 
79  template<typename RES>
80  struct Adaptor<RES(size_t, double)>
81  {
82  template<typename FUN>
83  static auto
84  build (FUN&& fun)
85  {
86  return [functor=std::forward<FUN>(fun)]
87  (size_t hash) -> _FunRet<FUN>
88  {
89  return functor(hash, ctxParameter);
90  };
91  }
92  };
93  };
94  //
95  }//(End) Test config
96 
97 
99 
100 
101 
102  /***********************************************************************************/
114  : public Test
115  {
116 
117  void
118  run (Arg)
119  {
120  simpleUse();
121 
122  verify_policy();
123  verify_numerics();
124  verify_adaptMapping();
125  verify_dynamicChange();
126  }
127 
128 
129 
132  void
134  {
135  auto draw = Draw().probability(0.5);
136  CHECK (draw( 0) == 0);
137  CHECK (draw( 16) == 0);
138  CHECK (draw( 32) == 1);
139  CHECK (draw( 40) == 2);
140  CHECK (draw( 48) == -2);
141  CHECK (draw( 56) == -1);
142  CHECK (draw( 64) == 0); // values repeat after 64 steps
143  CHECK (draw( 95) == 0); // ~ half of each cycle yields the »neutral value«
144  CHECK (draw( 96) == 1);
145  CHECK (draw(127) == -1);
146  CHECK (draw(128) == 0);
147  CHECK (draw(168) == 2);
148  CHECK (draw(256) == 0);
149  }
150 
151 
152 
164  void
166  {
167  auto d1 = RandomDraw<random_draw::LimitedRandomGenerate<5>>().probability(1.0);
168  uint v1 = d1();
169  CHECK (0 < v1 and v1 <=5);
170 
171  struct SpecialPolicy
172  : function<Limited<char, 'Z','A'>(char,uint)>
173  {
174  static double defaultSrc (char b, uint off) { return fmod ((b-'A'+off)/double('Z'-'A'), 1.0); }
175  };
176 
177  auto d2 = RandomDraw<SpecialPolicy>().probability(1.0);
178  CHECK (d2('A', 2) == 'D');
179  CHECK (d2('M',10) == 'X');
180  CHECK (d2('Y', 0) == 'Z');
181  CHECK (d2('Y',15) == 'P');
182  }
183 
184 
185 
196  void
198  {
199  auto distribution = [](Draw const& draw)
200  { // investigate value distribution
201  using Arr = std::array<int,5>;
202  Arr step{-1,-1,-1,-1,-1};
203  Arr freq{0};
204  for (uint i=0; i<128; ++i)
205  {
206  int res = draw(i);
207  CHECK (-2 <= res and res <= +2);
208  int idx = res+2;
209  freq[idx] += 1;
210  if (step[idx] < 0)
211  step[idx] = i;
212  }
213  _Fmt line{"val:%+d (%02d|%5.2f%%)\n"};
214  string report;
215  for (int idx=0; idx<5; ++idx)
216  {
217  report += line % (idx-2) % step[idx] % (100.0*freq[idx]/128);
218  }
219  return report;
220  };
221 
222  auto draw = Draw();
223  string report{"+++| --empty-- \n"};
224 
225  CHECK (draw( 0) == 0);
226  CHECK (draw( 32) == 0);
227  CHECK (draw( 96) == 0);
228 
229  report += distribution(draw);
230  CHECK (report ==
231  "+++| --empty-- \n"
232  "val:-2 (-1| 0.00%)\n"
233  "val:-1 (-1| 0.00%)\n"
234  "val:+0 (00|100.00%)\n"
235  "val:+1 (-1| 0.00%)\n"
236  "val:+2 (-1| 0.00%)\n"_expect);
237 
238 
239  draw.probability(1.0);
240  CHECK (draw( 0) == +1);
241  CHECK (draw( 15) == +1);
242  CHECK (draw( 16) == +2);
243  CHECK (draw( 31) == +2);
244  CHECK (draw( 32) == -2);
245  CHECK (draw( 47) == -2);
246  CHECK (draw( 48) == -1);
247  CHECK (draw( 63) == -1);
248  CHECK (draw( 64) == +1);
249  CHECK (draw( 96) == -2);
250 
251  report = "+++| p ≔ 1.0 \n";
252  report += distribution(draw);
253  CHECK (report ==
254  "+++| p ≔ 1.0 \n"
255  "val:-2 (32|25.00%)\n"
256  "val:-1 (48|25.00%)\n"
257  "val:+0 (-1| 0.00%)\n"
258  "val:+1 (00|25.00%)\n"
259  "val:+2 (16|25.00%)\n"_expect);
260 
261 
262  draw.probability(0.99);
263  CHECK (draw( 0) == 0);
264  CHECK (draw( 1) == +1);
265  CHECK (draw( 16) == +1);
266  CHECK (draw( 17) == +2);
267  CHECK (draw( 32) == +2);
268  CHECK (draw( 33) == -2);
269  CHECK (draw( 48) == -2);
270  CHECK (draw( 49) == -1);
271  CHECK (draw( 63) == -1);
272  CHECK (draw( 64) == 0);
273  CHECK (draw( 65) == +1);
274  CHECK (draw( 80) == +1); // 64+16
275  CHECK (draw( 82) == +2); // 64+17
276  CHECK (draw( 97) == -2); // 64+33
277  CHECK (draw(352) == +2); // 64+32+256
278  CHECK (draw(353) == -2); // 64+33+256
279 
280  report = "+++| p ≔ 0.99 \n";
281  report += distribution(draw);
282  CHECK (report ==
283  "+++| p ≔ 0.99 \n"
284  "val:-2 (33|25.00%)\n"
285  "val:-1 (49|23.44%)\n"
286  "val:+0 (00| 1.56%)\n"
287  "val:+1 (01|25.00%)\n"
288  "val:+2 (17|25.00%)\n"_expect);
289 
290 
291  draw.probability(0.98);
292  CHECK (draw( 0) == 0);
293  CHECK (draw( 1) == 0);
294  CHECK (draw( 2) == +1);
295  CHECK (draw( 63) == -1);
296  CHECK (draw( 64) == 0);
297  CHECK (draw( 65) == 0);
298  CHECK (draw( 66) == +1);
299 
300  report = "+++| p ≔ 0.98 \n";
301  report += distribution(draw);
302  CHECK (report ==
303  "+++| p ≔ 0.98 \n"
304  "val:-2 (33|25.00%)\n"
305  "val:-1 (49|23.44%)\n"
306  "val:+0 (00| 3.12%)\n"
307  "val:+1 (02|23.44%)\n"
308  "val:+2 (17|25.00%)\n"_expect);
309 
310 
311  draw.probability(0.97);
312  report = "+++| p ≔ 0.97 \n";
313  report += distribution(draw);
314  CHECK (report ==
315  "+++| p ≔ 0.97 \n"
316  "val:-2 (33|25.00%)\n"
317  "val:-1 (49|23.44%)\n"
318  "val:+0 (00| 3.12%)\n"
319  "val:+1 (02|25.00%)\n"
320  "val:+2 (18|23.44%)\n"_expect);
321 
322 
323  draw.probability(0.75);
324  report = "+++| p ≔ 0.75 \n";
325  report += distribution(draw);
326  CHECK (report ==
327  "+++| p ≔ 0.75 \n"
328  "val:-2 (40|18.75%)\n"
329  "val:-1 (52|18.75%)\n"
330  "val:+0 (00|25.00%)\n"
331  "val:+1 (16|18.75%)\n"
332  "val:+2 (28|18.75%)\n"_expect);
333 
334 
335  draw.probability(0.5);
336  report = "+++| p ≔ 0.50 \n";
337  report += distribution(draw);
338  CHECK (report ==
339  "+++| p ≔ 0.50 \n"
340  "val:-2 (48|12.50%)\n"
341  "val:-1 (56|12.50%)\n"
342  "val:+0 (00|50.00%)\n"
343  "val:+1 (32|12.50%)\n"
344  "val:+2 (40|12.50%)\n"_expect);
345 
346 
347  draw.probability(0.2);
348  report = "+++| p ≔ 0.20 \n";
349  report += distribution(draw);
350  CHECK (report ==
351  "+++| p ≔ 0.20 \n"
352  "val:-2 (58| 4.69%)\n"
353  "val:-1 (61| 4.69%)\n"
354  "val:+0 (00|81.25%)\n"
355  "val:+1 (52| 4.69%)\n"
356  "val:+2 (55| 4.69%)\n"_expect);
357 
358 
359  draw.probability(0.1);
360  report = "+++| p ≔ 0.10 \n";
361  report += distribution(draw);
362  CHECK (report ==
363  "+++| p ≔ 0.10 \n"
364  "val:-2 (61| 3.12%)\n"
365  "val:-1 (63| 1.56%)\n"
366  "val:+0 (00|90.62%)\n"
367  "val:+1 (58| 3.12%)\n"
368  "val:+2 (60| 1.56%)\n"_expect);
369 
370 
371  // ══════════
372  draw.probability(1.0).shuffle(1);
373  CHECK (draw( 6) == +1); // 6*1
374  CHECK (draw( 6) == +1); // 6*2
375  CHECK (draw( 6) == +2); // 6*3
376  CHECK (draw( 6) == +2); // 6*4
377  CHECK (draw( 6) == +2); // 6*5
378  CHECK (draw( 6) == -2); // 6*6
379  CHECK (draw(16) == -1); // 16*7 %64 = 48
380  CHECK (draw(16) == +1); // 16*8 %64 = 0
381 
382  report = "+++| p ≔ 1.0 +shuffle \n";
383  report += distribution(draw);
384  CHECK (report ==
385  "+++| p ≔ 1.0 +shuffle \n"
386  "val:-2 (03|25.00%)\n"
387  "val:-1 (04|25.00%)\n"
388  "val:+0 (-1| 0.00%)\n"
389  "val:+1 (00|25.00%)\n"
390  "val:+2 (02|25.00%)\n"_expect);
391  draw.shuffle(0);
392  CHECK (draw(16) == +2); // shuffling disabled
393  CHECK (draw(16) == +2); // values reproducible
394  CHECK (draw(32) == -2);
395  CHECK (draw(32) == -2);
396  CHECK (draw(16) == +2);
397  CHECK (draw(16) == +2);
398 
399 
400 
401  // ═════════
402  draw.probability(0.5).maxVal(1);
403  CHECK (draw( 0) == 0);
404  CHECK (draw( 16) == 0);
405  CHECK (draw( 31) == 0);
406  CHECK (draw( 32) == +1);
407  CHECK (draw( 42) == +1);
408  CHECK (draw( 43) == -2);
409  CHECK (draw( 53) == -2);
410  CHECK (draw( 54) == -1);
411  CHECK (draw( 63) == -1);
412  CHECK (draw( 64) == 0);
413  CHECK (draw( 95) == 0);
414  CHECK (draw( 96) == +1);
415 
416  report = "+++| p ≔ 0.50 max ≔ 1 \n";
417  report += distribution(draw);
418  CHECK (report ==
419  "+++| p ≔ 0.50 max ≔ 1 \n"
420  "val:-2 (43|17.19%)\n"
421  "val:-1 (54|15.62%)\n"
422  "val:+0 (00|50.00%)\n"
423  "val:+1 (32|17.19%)\n"
424  "val:+2 (-1| 0.00%)\n"_expect);
425 
426 
427  draw.probability(1.0).maxVal(1);
428  CHECK (draw( 0) == +1);
429  CHECK (draw( 16) == +1);
430  CHECK (draw( 21) == +1);
431  CHECK (draw( 22) == -2);
432  CHECK (draw( 42) == -2);
433  CHECK (draw( 43) == -1);
434  CHECK (draw( 63) == -1);
435  CHECK (draw( 64) == +1);
436  CHECK (draw( 85) == +1);
437  CHECK (draw( 86) == -2);
438  CHECK (draw( 96) == -2);
439 
440  report = "+++| p ≔ 1.0 max ≔ 1 \n";
441  report += distribution(draw);
442  CHECK (report ==
443  "+++| p ≔ 1.0 max ≔ 1 \n"
444  "val:-2 (22|32.81%)\n"
445  "val:-1 (43|32.81%)\n"
446  "val:+0 (-1| 0.00%)\n"
447  "val:+1 (00|34.38%)\n"
448  "val:+2 (-1| 0.00%)\n"_expect);
449 
450 
451  // ═════════
452  draw.probability(0.5).maxVal(0);
453  CHECK (draw( 0) == 0);
454  CHECK (draw( 31) == 0);
455  CHECK (draw( 32) == -2);
456  CHECK (draw( 47) == -2);
457  CHECK (draw( 48) == -1);
458  CHECK (draw( 63) == -1);
459  CHECK (draw( 64) == 0);
460  CHECK (draw( 95) == 0);
461  CHECK (draw( 96) == -2);
462 
463  report = "+++| p ≔ 0.50 max ≔ 0 \n";
464  report += distribution(draw);
465  CHECK (report ==
466  "+++| p ≔ 0.50 max ≔ 0 \n"
467  "val:-2 (32|25.00%)\n"
468  "val:-1 (48|25.00%)\n"
469  "val:+0 (00|50.00%)\n"
470  "val:+1 (-1| 0.00%)\n"
471  "val:+2 (-1| 0.00%)\n"_expect);
472 
473 
474  draw.probability(1.0).maxVal(0);
475  CHECK (draw( 0) == -2);
476  CHECK (draw( 31) == -2);
477  CHECK (draw( 32) == -1);
478  CHECK (draw( 63) == -1);
479  CHECK (draw( 64) == -2);
480  CHECK (draw( 96) == -1);
481 
482  report = "+++| p ≔ 1.0 max ≔ 0 \n";
483  report += distribution(draw);
484  CHECK (report ==
485  "+++| p ≔ 1.0 max ≔ 0 \n"
486  "val:-2 (00|50.00%)\n"
487  "val:-1 (32|50.00%)\n"
488  "val:+0 (-1| 0.00%)\n"
489  "val:+1 (-1| 0.00%)\n"
490  "val:+2 (-1| 0.00%)\n"_expect);
491 
492 
493  // ═════════
494  draw.probability(0.5).maxVal(-1);
495  CHECK (draw( 32) == -2);
496  CHECK (draw( 47) == -2);
497  CHECK (draw( 48) == -1);
498  CHECK (draw( 63) == -1);
499  CHECK (draw( 64) == 0);
500  CHECK (draw( 95) == 0);
501  CHECK (draw( 96) == -2);
502 
503  report = "+++| p ≔ 0.50 max ≔ -1 \n";
504  report += distribution(draw);
505  CHECK (report ==
506  "+++| p ≔ 0.50 max ≔ -1 \n"
507  "val:-2 (32|25.00%)\n"
508  "val:-1 (48|25.00%)\n"
509  "val:+0 (00|50.00%)\n"
510  "val:+1 (-1| 0.00%)\n"
511  "val:+2 (-1| 0.00%)\n"_expect);
512 
513 
514  draw.probability(1.0).maxVal(-1);
515  CHECK (draw( 0) == -2);
516  CHECK (draw( 31) == -2);
517  CHECK (draw( 32) == -1);
518  CHECK (draw( 63) == -1);
519  CHECK (draw( 64) == -2);
520 
521  report = "+++| p ≔ 1.0 max ≔ -1 \n";
522  report += distribution(draw);
523  CHECK (report ==
524  "+++| p ≔ 1.0 max ≔ -1 \n"
525  "val:-2 (00|50.00%)\n"
526  "val:-1 (32|50.00%)\n"
527  "val:+0 (-1| 0.00%)\n"
528  "val:+1 (-1| 0.00%)\n"
529  "val:+2 (-1| 0.00%)\n"_expect);
530 
531 
532  // ═════════
533  draw.probability(0.5).maxVal(2).minVal(1);
534  CHECK (draw( 32) == +1);
535  CHECK (draw( 48) == +2);
536  CHECK (draw( 63) == +2);
537  CHECK (draw( 64) == 0);
538 
539  report = "+++| p ≔ 0.50 min ≔ 1 max ≔ 2 \n";
540  report += distribution(draw);
541  CHECK (report ==
542  "+++| p ≔ 0.50 min ≔ 1 max ≔ 2 \n"
543  "val:-2 (-1| 0.00%)\n"
544  "val:-1 (-1| 0.00%)\n"
545  "val:+0 (00|50.00%)\n"
546  "val:+1 (32|25.00%)\n"
547  "val:+2 (48|25.00%)\n"_expect);
548 
549 
550  draw.probability(1.0).maxVal(2).minVal(1);
551  CHECK (draw( 0) == +1);
552  CHECK (draw( 32) == +2);
553  CHECK (draw( 63) == +2);
554  CHECK (draw( 64) == +1);
555 
556  report = "+++| p ≔ 1.0 min ≔ 1 max ≔ 2 \n";
557  report += distribution(draw);
558  CHECK (report ==
559  "+++| p ≔ 1.0 min ≔ 1 max ≔ 2 \n"
560  "val:-2 (-1| 0.00%)\n"
561  "val:-1 (-1| 0.00%)\n"
562  "val:+0 (-1| 0.00%)\n"
563  "val:+1 (00|50.00%)\n"
564  "val:+2 (32|50.00%)\n"_expect);
565 
566 
567  // ═════════
568  draw.probability(0.5).maxVal(0);
569  CHECK (draw( 32) == -1);
570  CHECK (draw( 63) == -1);
571  CHECK (draw( 64) == 0);
572 
573  report = "+++| p ≔ 0.50 max ≔ 0 (-> min ≔ -1) \n";
574  report += distribution(draw);
575  CHECK (report ==
576  "+++| p ≔ 0.50 max ≔ 0 (-> min ≔ -1) \n"
577  "val:-2 (-1| 0.00%)\n"
578  "val:-1 (32|50.00%)\n"
579  "val:+0 (00|50.00%)\n"
580  "val:+1 (-1| 0.00%)\n"
581  "val:+2 (-1| 0.00%)\n"_expect);
582 
583 
584  // ═════════
585  draw.fixedVal(1);
586  report = "+++| fixedVal(1) \n";
587  report += distribution(draw);
588  CHECK (report ==
589  "+++| fixedVal(1) \n"
590  "val:-2 (-1| 0.00%)\n"
591  "val:-1 (-1| 0.00%)\n"
592  "val:+0 (-1| 0.00%)\n"
593  "val:+1 (00|100.00%)\n"
594  "val:+2 (-1| 0.00%)\n"_expect);
595  }
596 
597 
598 
608  void
610  {
611  // Note: no special Adapter required for the following function,
612  // since it takes the same arguments as our RandomDraw (size_t);
613  // moreover, since the function yields a double, the adapter scheme
614  // concludes that this function wants to feed directly into the
615  // primary mapping function RandomDraw::limited(double)
616  auto d1 = Draw([](size_t hash) -> double { return hash / 10.0; });
617  CHECK (d1( 0) == +1);
618  CHECK (d1( 1) == +1);
619  CHECK (d1( 2) == +1);
620  CHECK (d1( 3) == +2);
621  CHECK (d1( 4) == +2);
622  CHECK (d1( 5) == -2);
623  CHECK (d1( 6) == -2);
624  CHECK (d1( 7) == -2);
625  CHECK (d1( 8) == -1);
626  CHECK (d1( 9) == -1);
627  CHECK (d1(10) == 0);
628  CHECK (d1(11) == 0);
629  CHECK (d1(12) == 0);
630  CHECK (d1(13) == 0);
631 
632  d1.probability(0.4);
633  CHECK (d1( 0) == 0);
634  CHECK (d1( 1) == 0);
635  CHECK (d1( 2) == 0);
636  CHECK (d1( 3) == 0);
637  CHECK (d1( 4) == 0);
638  CHECK (d1( 5) == 0);
639  CHECK (d1( 6) == +1); // probability 0.4
640  CHECK (d1( 7) == +2);
641  CHECK (d1( 8) == -2);
642  CHECK (d1( 9) == -1);
643  CHECK (d1(10) == 0);
644 
645  d1.minVal(-1).probability(0.7);
646  CHECK (d1( 0) == 0);
647  CHECK (d1( 1) == 0);
648  CHECK (d1( 2) == 0);
649  CHECK (d1( 3) == 0);
650  CHECK (d1( 4) == +1); // probability 0.7
651  CHECK (d1( 5) == +1);
652  CHECK (d1( 6) == +2);
653  CHECK (d1( 7) == +2);
654  CHECK (d1( 8) == -1);
655  CHECK (d1( 9) == -1);
656  CHECK (d1(10) == 0);
657 
658  // The next example demonstrates accepting special input arguments;
659  // as defined in the policy, this function will get the `(div, mod)`
660  // of the hash with modulus 64
661  auto d2 = Draw([](uint cycle, uint rem){ return double(rem) / ((cycle+1)*5); });
662  CHECK (d2( 0) == +1);
663  CHECK (d2( 1) == +1);
664  CHECK (d2( 2) == +2);
665  CHECK (d2( 3) == -2);
666  CHECK (d2( 4) == -1); // the first cycle is only 5 steps long (0+1)*5
667  CHECK (d2( 5) == 0);
668  CHECK (d2( 6) == 0);
669  CHECK (d2( 7) == 0);
670  CHECK (d2( 8) == 0);
671  CHECK (d2( 9) == 0);
672  CHECK (d2(10) == 0);
673  CHECK (d2(63) == 0);
674  CHECK (d2(64) == +1); // the second cycle starts here...
675  CHECK (d2(65) == +1);
676  CHECK (d2(66) == +1);
677  CHECK (d2(67) == +2);
678  CHECK (d2(68) == +2);
679  CHECK (d2(69) == -2);
680  CHECK (d2(70) == -2);
681  CHECK (d2(71) == -2);
682  CHECK (d2(72) == -1);
683  CHECK (d2(73) == -1);
684  CHECK (d2(74) == 0); // and is 10 steps long (same pattern as in the first example above)
685  CHECK (d2(75) == 0);
686 
687  // The next example uses the other Adapter variant, which „sneaks in“ a context value
688  // Moreover, we can change the mapping function of an existing RandomDraw, as demonstrated here
689  d2.mapping([](size_t hash, double ctx){ return hash / ctx; });
690 
691  ctxParameter = 4.0;
692  CHECK (d2( 0) == +1);
693  CHECK (d2( 1) == +2);
694  CHECK (d2( 2) == -2);
695  CHECK (d2( 3) == -1); // cycle-length: 4
696  CHECK (d2( 4) == 0);
697  CHECK (d2( 5) == 0);
698  CHECK (d2( 6) == 0);
699  CHECK (d2( 7) == 0);
700  CHECK (d2( 8) == 0);
701  CHECK (d2( 9) == 0);
702  CHECK (d2(10) == 0);
703 
704  ctxParameter = 8.0;
705  CHECK (d2( 0) == +1);
706  CHECK (d2( 1) == +1);
707  CHECK (d2( 2) == +2);
708  CHECK (d2( 3) == +2);
709  CHECK (d2( 4) == -2);
710  CHECK (d2( 5) == -2);
711  CHECK (d2( 6) == -1);
712  CHECK (d2( 7) == -1); // cycle-length: 8
713  CHECK (d2( 8) == 0);
714  CHECK (d2( 9) == 0);
715  CHECK (d2(10) == 0);
716 
717  // and can of course dynamically tweak the mapping profile...
718  d2.maxVal(0).probability(0.5);
719  CHECK (d2( 0) == 0);
720  CHECK (d2( 1) == 0);
721  CHECK (d2( 2) == 0);
722  CHECK (d2( 3) == 0);
723  CHECK (d2( 4) == -2); // start here due to probability 0.5
724  CHECK (d2( 5) == -2);
725  CHECK (d2( 6) == -1);
726  CHECK (d2( 7) == -1); // cycle-length: 8
727  CHECK (d2( 8) == 0);
728  CHECK (d2( 9) == 0);
729  CHECK (d2(10) == 0);
730 
731  // NOTE: once a custom mapping function has been installed,
732  // the object can no longer be moved, due to reference binding.
733  VERIFY_ERROR (LIFECYCLE, Draw dx{move(d2)} );
734  }
735 
736 
737 
738 
742  void
744  {
745  auto d1 = Draw([](uint cycle, uint)
746  { // dynamically control probability
747  return Draw().probability((cycle+1)*0.25);
748  });
749 
750  CHECK (d1( 0) == 0);
751  CHECK (d1( 8) == 0);
752  CHECK (d1( 16) == 0);
753  CHECK (d1( 24) == 0);
754  CHECK (d1( 32) == 0);
755  CHECK (d1( 40) == 0);
756  CHECK (d1( 48) == 1); // 1st cycle: 25% probability
757  CHECK (d1( 56) == -2);
758  CHECK (d1( 63) == -1);
759  CHECK (d1( 64 +0) == 0);
760  CHECK (d1( 64 +8) == 0);
761  CHECK (d1( 64+16) == 0);
762  CHECK (d1( 64+24) == 0);
763  CHECK (d1( 64+32) == 1); // 2nd cycle: 50% probability
764  CHECK (d1( 64+40) == 2);
765  CHECK (d1( 64+48) == -2);
766  CHECK (d1( 64+56) == -1);
767  CHECK (d1( 64+63) == -1);
768  CHECK (d1(128 +0) == 0);
769  CHECK (d1(128 +8) == 0);
770  CHECK (d1(128 +16) == 1); // 3rd cycle: 75% probability
771  CHECK (d1(128 +24) == 1);
772  CHECK (d1(128 +32) == 2);
773  CHECK (d1(128 +40) == -2);
774  CHECK (d1(128 +48) == -2);
775  CHECK (d1(128 +56) == -1);
776  CHECK (d1(128 +63) == -1);
777  CHECK (d1(128+64 +0) == 1); // 4rth cycle: 100% probability
778  CHECK (d1(128+64 +8) == 1);
779  CHECK (d1(128+64+16) == 2);
780  CHECK (d1(128+64+24) == 2);
781  CHECK (d1(128+64+32) == -2);
782  CHECK (d1(128+64+40) == -2);
783  CHECK (d1(128+64+48) == -1);
784  CHECK (d1(128+64+56) == -1);
785  CHECK (d1(128+64+63) == -1);
786  CHECK (d1(128+64+64) == 1);
787  }
788  };
789 
790 
792  LAUNCHER (RandomDraw_test, "unit common");
793 
794 
795 }} // namespace lib::test
Definition: run.hpp:40
static size_t defaultSrc(size_t hash)
by default use the hash directly as source of randomness
Front-end for printf-style string template interpolation.
#define VERIFY_ERROR(ERROR_ID, ERRONEOUS_STATEMENT)
Macro to verify that a statement indeed raises an exception.
A front-end for using printf-style formatting.
Implementation namespace for support and library code.
A component and builder to draw limited parameter values based on some source of randomness (or hash ...
Simplistic test class runner.
A collection of frequently used helper functions to support unit testing.
Build a component to select limited values randomly.
typename _Fun< FUN >::Ret _FunRet
abbreviation for referring to a function&#39;s return type
Definition: function.hpp:187