Lumiera 0.pre.04
»edit your freedom«
Loading...
Searching...
No Matches
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"
24
25#include <array>
26
27
28
29namespace lib {
30namespace test{
31
32 using util::_Fmt;
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
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
A component and builder to draw limited parameter values based on some source of randomness (or hash ...
RandomDraw && probability(double p)
A front-end for using printf-style formatting.
Front-end for printf-style string template interpolation.
#define hash
unsigned int uint
Definition integral.hpp:29
_Fun< FUN >::Ret _FunRet
abbreviation for referring to a function's return type
Definition function.hpp:253
RandomDraw< SymmetricFive > Draw
Implementation namespace for support and library code.
Test runner and basic definitions for tests.
Build a component to select limited values randomly.
Simplistic test class runner.
#define LAUNCHER(_TEST_CLASS_, _GROUPS_)
Definition run.hpp:116
static size_t defaultSrc(size_t hash)
by default use the hash directly as source of randomness
A collection of frequently used helper functions to support unit testing.
#define VERIFY_ERROR(ERROR_ID, ERRONEOUS_STATEMENT)
Macro to verify that a statement indeed raises an exception.