1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.rng.sampling;
19
20 import java.util.Arrays;
21 import java.util.concurrent.atomic.AtomicInteger;
22 import org.apache.commons.math3.stat.inference.ChiSquareTest;
23 import org.apache.commons.rng.UniformRandomProvider;
24 import org.apache.commons.rng.sampling.CompositeSamplers.Builder;
25 import org.apache.commons.rng.sampling.CompositeSamplers.DiscreteProbabilitySampler;
26 import org.apache.commons.rng.sampling.CompositeSamplers.DiscreteProbabilitySamplerFactory;
27 import org.apache.commons.rng.sampling.distribution.AliasMethodDiscreteSampler;
28 import org.apache.commons.rng.sampling.distribution.ContinuousSampler;
29 import org.apache.commons.rng.sampling.distribution.DiscreteSampler;
30 import org.apache.commons.rng.sampling.distribution.GuideTableDiscreteSampler;
31 import org.apache.commons.rng.sampling.distribution.LongSampler;
32 import org.apache.commons.rng.sampling.distribution.SharedStateContinuousSampler;
33 import org.apache.commons.rng.sampling.distribution.SharedStateDiscreteSampler;
34 import org.apache.commons.rng.sampling.distribution.SharedStateLongSampler;
35 import org.junit.jupiter.api.Assertions;
36 import org.junit.jupiter.api.Test;
37
38
39
40
41 class CompositeSamplersTest {
42
43
44
45 @Test
46 void testDiscreteProbabilitySampler() {
47 final UniformRandomProvider rng = RandomAssert.createRNG();
48 final double[] probabilities = {0.1, 0.2, 0.3, 0.4};
49
50 final ChiSquareTest chisq = new ChiSquareTest();
51
52 final int n = 1000000;
53 for (final DiscreteProbabilitySampler item : DiscreteProbabilitySampler.values()) {
54 final DiscreteSampler sampler = item.create(rng, probabilities.clone());
55 final long[] observed = new long[probabilities.length];
56 for (int i = 0; i < n; i++) {
57 observed[sampler.sample()]++;
58 }
59 final double p = chisq.chiSquareTest(probabilities, observed);
60 Assertions.assertFalse(p < 0.001, () -> item + " p-value too small: " + p);
61 }
62 }
63
64
65
66
67 @Test
68 void testEmptyBuilderThrows() {
69 final UniformRandomProvider rng = RandomAssert.seededRNG();
70 final Builder<SharedStateObjectSampler<Integer>> builder = CompositeSamplers
71 .newSharedStateObjectSamplerBuilder();
72 Assertions.assertEquals(0, builder.size());
73 Assertions.assertThrows(IllegalStateException.class,
74 () -> builder.build(rng));
75 }
76
77
78
79
80 @Test
81 void testNullSharedStateObjectSamplerThrows() {
82 final Builder<SharedStateObjectSampler<Integer>> builder = CompositeSamplers
83 .newSharedStateObjectSamplerBuilder();
84 Assertions.assertThrows(NullPointerException.class,
85 () -> builder.add(null, 1.0));
86 }
87
88
89
90
91 @Test
92 void testInvalidWeights() {
93 final UniformRandomProvider rng = RandomAssert.seededRNG();
94 final Builder<SharedStateObjectSampler<Integer>> builder = CompositeSamplers
95 .newSharedStateObjectSamplerBuilder();
96 final RangeSampler sampler = new RangeSampler(45, 63, rng);
97
98 Assertions.assertEquals(0, builder.size());
99 builder.add(sampler, 0.0);
100 Assertions.assertEquals(0, builder.size());
101
102 final double[] bad = {-1, Double.NaN, Double.POSITIVE_INFINITY};
103 for (final double weight : bad) {
104 Assertions.assertThrows(IllegalArgumentException.class,
105 () -> builder.add(sampler, weight),
106 () -> "Did not detect invalid weight: " + weight);
107 }
108 }
109
110
111
112
113 @Test
114 void testSingleSharedStateObjectSampler() {
115 final UniformRandomProvider rng = RandomAssert.seededRNG();
116 final Builder<SharedStateObjectSampler<Integer>> builder = CompositeSamplers
117 .newSharedStateObjectSamplerBuilder();
118 final RangeSampler sampler = new RangeSampler(45, 63, rng);
119 builder.add(sampler, 1.0);
120 Assertions.assertEquals(1, builder.size());
121 final SharedStateObjectSampler<Integer> composite = builder.build(rng);
122 Assertions.assertSame(sampler, composite);
123 }
124
125
126
127
128 @Test
129 void testObjectSamplerSamples() {
130 final Builder<ObjectSampler<Integer>> builder = CompositeSamplers.newObjectSamplerBuilder();
131 final UniformRandomProvider rng = RandomAssert.createRNG();
132 final int n = 15;
133 final int min = -134;
134 final int max = 2097;
135 addObjectSamplers(builder, n, min, max, rng);
136 assertObjectSamplerSamples(builder.build(rng), min, max);
137 }
138
139
140
141
142 @Test
143 void testSharedStateObjectSamplerSamples() {
144 final Builder<SharedStateObjectSampler<Integer>> builder = CompositeSamplers
145 .newSharedStateObjectSamplerBuilder();
146 final UniformRandomProvider rng = RandomAssert.createRNG();
147 final int n = 11;
148 final int min = 42;
149 final int max = 678;
150 addObjectSamplers(builder, n, min, max, rng);
151
152 final UniformRandomProvider rng1 = RandomAssert.createRNG();
153 assertObjectSamplerSamples(builder.build(rng).withUniformRandomProvider(rng1), min, max);
154 }
155
156
157
158
159
160 @Test
161 void testSharedStateObjectSamplerSamplesWithCustomSharedStateDiscreteSamplerFactory() {
162 final Builder<SharedStateObjectSampler<Integer>> builder = CompositeSamplers
163 .newSharedStateObjectSamplerBuilder();
164 final AtomicInteger factoryCount = new AtomicInteger();
165 builder.setFactory(new DiscreteProbabilitySamplerFactory() {
166 @Override
167 public DiscreteSampler create(UniformRandomProvider rng, double[] probabilities) {
168 factoryCount.incrementAndGet();
169
170 return AliasMethodDiscreteSampler.of(rng, probabilities, 2);
171 }
172 });
173 final UniformRandomProvider rng = RandomAssert.createRNG();
174 final int n = 7;
175 final int min = -610;
176 final int max = 745;
177 addObjectSamplers(builder, n, min, max, rng);
178
179
180 final UniformRandomProvider rng1 = RandomAssert.createRNG();
181 assertObjectSamplerSamples(builder.build(rng).withUniformRandomProvider(rng1), min, max);
182
183 Assertions.assertEquals(1, factoryCount.get(), "Factory should not be used to create the shared state sampler");
184 }
185
186
187
188
189
190 @Test
191 void testSharedStateObjectSamplerSamplesWithCustomDiscreteSamplerFactory() {
192 final Builder<SharedStateObjectSampler<Integer>> builder = CompositeSamplers
193 .newSharedStateObjectSamplerBuilder();
194 final AtomicInteger factoryCount = new AtomicInteger();
195 builder.setFactory(new DiscreteProbabilitySamplerFactory() {
196 @Override
197 public DiscreteSampler create(UniformRandomProvider rng, double[] probabilities) {
198 factoryCount.incrementAndGet();
199
200 final DiscreteSampler sampler = GuideTableDiscreteSampler.of(rng, probabilities, 2);
201
202 Arrays.fill(probabilities, Double.NaN);
203 return new DiscreteSampler() {
204 @Override
205 public int sample() {
206 return sampler.sample();
207 }
208 };
209 }
210 });
211 final UniformRandomProvider rng = RandomAssert.createRNG();
212 final int n = 14;
213 final int min = 56;
214 final int max = 2033;
215 addObjectSamplers(builder, n, min, max, rng);
216
217
218
219 final UniformRandomProvider rng1 = RandomAssert.createRNG();
220 assertObjectSamplerSamples(builder.build(rng).withUniformRandomProvider(rng1), min, max);
221
222 Assertions.assertEquals(2, factoryCount.get(), "Factory should be used to create the shared state sampler");
223 }
224
225
226
227
228
229
230
231 @Test
232 void testObjectSamplerSamplesWithUniformWeights() {
233 final Builder<ObjectSampler<Integer>> builder = CompositeSamplers.newObjectSamplerBuilder();
234 final UniformRandomProvider rng = RandomAssert.createRNG();
235 final int max = 60;
236 final int interval = 10;
237 for (int min = 0; min < max; min += interval) {
238 builder.add(new RangeSampler(min, min + interval, rng), 1.0);
239 }
240 assertObjectSamplerSamples(builder.build(rng), 0, max);
241 }
242
243
244
245
246
247
248 @Test
249 void testObjectSamplerSamplesWithVeryLargeWeights() {
250 final Builder<ObjectSampler<Integer>> builder = CompositeSamplers.newObjectSamplerBuilder();
251 final UniformRandomProvider rng = RandomAssert.createRNG();
252
253
254 final double w4 = 0x1.0p1023;
255 final double w2 = 0x1.0p1022;
256 final double w1 = 0x1.0p1021;
257 Assertions.assertEquals(Double.POSITIVE_INFINITY, w4 + w4 + w2 + w1);
258 builder.add(new RangeSampler(0, 40, rng), w4);
259 builder.add(new RangeSampler(40, 80, rng), w4);
260 builder.add(new RangeSampler(80, 100, rng), w2);
261 builder.add(new RangeSampler(100, 110, rng), w1);
262 assertObjectSamplerSamples(builder.build(rng), 0, 110);
263 }
264
265
266
267
268
269
270
271 @Test
272 void testObjectSamplerSamplesWithSubNormalWeights() {
273 final Builder<ObjectSampler<Integer>> builder = CompositeSamplers.newObjectSamplerBuilder();
274 final UniformRandomProvider rng = RandomAssert.createRNG();
275
276
277 final double w4 = Double.MIN_VALUE * 4;
278 final double w2 = Double.MIN_VALUE * 2;
279 final double w1 = Double.MIN_VALUE;
280 final double sum = w4 + w4 + w2 + w1;
281
282 Assertions.assertEquals(Double.POSITIVE_INFINITY, 1.0 / sum);
283
284 Assertions.assertEquals(4.0 / 11, w4 / sum);
285 Assertions.assertEquals(2.0 / 11, w2 / sum);
286 Assertions.assertEquals(1.0 / 11, w1 / sum);
287 builder.add(new RangeSampler(0, 40, rng), w4);
288 builder.add(new RangeSampler(40, 80, rng), w4);
289 builder.add(new RangeSampler(80, 100, rng), w2);
290 builder.add(new RangeSampler(100, 110, rng), w1);
291 assertObjectSamplerSamples(builder.build(rng), 0, 110);
292 }
293
294
295
296
297
298
299
300
301
302
303
304 private static void addObjectSamplers(Builder<? super SharedStateObjectSampler<Integer>> builder, int n, int min,
305 int max, UniformRandomProvider rng) {
306
307
308
309
310
311
312
313
314
315
316
317 final int range = max - min - 1;
318 int[] ticks = new CombinationSampler(rng, range, n - 1).sample();
319
320 for (int i = 0; i < ticks.length; i++) {
321 ticks[i] += min + 1;
322 }
323
324 ticks = Arrays.copyOf(ticks, n + 1);
325 ticks[n - 1] = min;
326 ticks[n] = max;
327 Arrays.sort(ticks);
328
329
330 final int before = builder.size();
331 for (int i = 1; i < ticks.length; i++) {
332 final RangeSampler sampler = new RangeSampler(ticks[i - 1], ticks[i], rng);
333
334 builder.add(sampler, sampler.range);
335 }
336
337 Assertions.assertEquals(n, builder.size() - before, "Failed to add the correct number of samplers");
338 }
339
340
341
342
343
344
345
346
347 private static void assertObjectSamplerSamples(ObjectSampler<Integer> sampler, int min, int max) {
348 final int n = 100000;
349 final long[] observed = new long[max - min];
350 for (int i = 0; i < n; i++) {
351 observed[sampler.sample() - min]++;
352 }
353
354 final double[] expected = new double[observed.length];
355 Arrays.fill(expected, (double) n / expected.length);
356 final double p = new ChiSquareTest().chiSquareTest(expected, observed);
357 Assertions.assertFalse(p < 0.001, () -> "p-value too small: " + p);
358 }
359
360
361
362
363 @Test
364 void testDiscreteSamplerSamples() {
365 final Builder<DiscreteSampler> builder = CompositeSamplers.newDiscreteSamplerBuilder();
366 final UniformRandomProvider rng = RandomAssert.createRNG();
367 final int n = 15;
368 final int min = -134;
369 final int max = 2097;
370 addDiscreteSamplers(builder, n, min, max, rng);
371 assertDiscreteSamplerSamples(builder.build(rng), min, max);
372 }
373
374
375
376
377 @Test
378 void testSharedStateDiscreteSamplerSamples() {
379 final Builder<SharedStateDiscreteSampler> builder = CompositeSamplers.newSharedStateDiscreteSamplerBuilder();
380 final UniformRandomProvider rng = RandomAssert.createRNG();
381 final int n = 11;
382 final int min = 42;
383 final int max = 678;
384 addDiscreteSamplers(builder, n, min, max, rng);
385 assertDiscreteSamplerSamples(builder.build(rng), min, max);
386 }
387
388
389
390
391
392
393
394
395
396
397
398 private static void addDiscreteSamplers(Builder<? super SharedStateDiscreteSampler> builder, int n, int min,
399 int max, UniformRandomProvider rng) {
400
401
402
403
404
405
406
407
408
409
410
411 final int range = max - min - 1;
412 int[] ticks = new CombinationSampler(rng, range, n - 1).sample();
413
414 for (int i = 0; i < ticks.length; i++) {
415 ticks[i] += min + 1;
416 }
417
418 ticks = Arrays.copyOf(ticks, n + 1);
419 ticks[n - 1] = min;
420 ticks[n] = max;
421 Arrays.sort(ticks);
422
423
424 final int before = builder.size();
425 for (int i = 1; i < ticks.length; i++) {
426 final IntRangeSampler sampler = new IntRangeSampler(rng, ticks[i - 1], ticks[i]);
427
428 builder.add(sampler, sampler.range);
429 }
430
431 Assertions.assertEquals(n, builder.size() - before, "Failed to add the correct number of samplers");
432 }
433
434
435
436
437
438
439
440
441 private static void assertDiscreteSamplerSamples(DiscreteSampler sampler, int min, int max) {
442 final int n = 100000;
443 final long[] observed = new long[max - min];
444 for (int i = 0; i < n; i++) {
445 observed[sampler.sample() - min]++;
446 }
447
448 final double[] expected = new double[observed.length];
449 Arrays.fill(expected, (double) n / expected.length);
450 final double p = new ChiSquareTest().chiSquareTest(expected, observed);
451 Assertions.assertFalse(p < 0.001, () -> "p-value too small: " + p);
452 }
453
454
455
456
457 @Test
458 void testContinuousSamplerSamples() {
459 final Builder<ContinuousSampler> builder = CompositeSamplers.newContinuousSamplerBuilder();
460 final UniformRandomProvider rng = RandomAssert.createRNG();
461 final int n = 15;
462 final double min = 67.2;
463 final double max = 2033.8;
464 addContinuousSamplers(builder, n, min, max, rng);
465 assertContinuousSamplerSamples(builder.build(rng), min, max);
466 }
467
468
469
470
471 @Test
472 void testSharedStateContinuousSamplerSamples() {
473 final Builder<SharedStateContinuousSampler> builder = CompositeSamplers
474 .newSharedStateContinuousSamplerBuilder();
475 final UniformRandomProvider rng = RandomAssert.createRNG();
476 final int n = 11;
477 final double min = -15.7;
478 final double max = 123.4;
479 addContinuousSamplers(builder, n, min, max, rng);
480 assertContinuousSamplerSamples(builder.build(rng), min, max);
481 }
482
483
484
485
486
487
488
489
490
491
492
493 private static void addContinuousSamplers(Builder<? super SharedStateContinuousSampler> builder, int n, double min,
494 double max, UniformRandomProvider rng) {
495
496
497
498
499
500
501
502
503
504
505
506 DoubleRangeSampler sampler = new DoubleRangeSampler(rng, min, max);
507 final double[] ticks = new double[n + 1];
508 ticks[0] = min;
509 ticks[1] = max;
510
511 for (int i = 2; i < ticks.length; i++) {
512 ticks[i] = sampler.sample();
513 }
514 Arrays.sort(ticks);
515
516
517 final int before = builder.size();
518 for (int i = 1; i < ticks.length; i++) {
519 sampler = new DoubleRangeSampler(rng, ticks[i - 1], ticks[i]);
520
521 builder.add(sampler, sampler.range());
522 }
523
524 Assertions.assertEquals(n, builder.size() - before, "Failed to add the correct number of samplers");
525 }
526
527
528
529
530
531
532
533
534 private static void assertContinuousSamplerSamples(ContinuousSampler sampler, double min, double max) {
535 final int n = 100000;
536 final int bins = 200;
537 final long[] observed = new long[bins];
538 final double scale = bins / (max - min);
539 for (int i = 0; i < n; i++) {
540
541
542 observed[(int) (scale * (sampler.sample() - min))]++;
543 }
544
545 final double[] expected = new double[observed.length];
546 Arrays.fill(expected, (double) n / expected.length);
547 final double p = new ChiSquareTest().chiSquareTest(expected, observed);
548 Assertions.assertFalse(p < 0.001, () -> "p-value too small: " + p);
549 }
550
551
552
553
554 @Test
555 void testLongSamplerSamples() {
556 final Builder<LongSampler> builder = CompositeSamplers.newLongSamplerBuilder();
557 final UniformRandomProvider rng = RandomAssert.createRNG();
558 final int n = 15;
559 final long min = -134;
560 final long max = 1L << 54;
561 addLongSamplers(builder, n, min, max, rng);
562 assertLongSamplerSamples(builder.build(rng), min, max);
563 }
564
565
566
567
568 @Test
569 void testSharedStateLongSamplerSamples() {
570 final Builder<SharedStateLongSampler> builder = CompositeSamplers.newSharedStateLongSamplerBuilder();
571 final UniformRandomProvider rng = RandomAssert.createRNG();
572 final int n = 11;
573 final long min = 42;
574 final long max = 1L << 53;
575 addLongSamplers(builder, n, min, max, rng);
576 assertLongSamplerSamples(builder.build(rng), min, max);
577 }
578
579
580
581
582
583
584
585
586
587
588
589 private static void addLongSamplers(Builder<? super SharedStateLongSampler> builder, int n, long min,
590 long max, UniformRandomProvider rng) {
591
592
593
594
595
596
597
598
599
600
601
602 LongRangeSampler sampler = new LongRangeSampler(rng, min, max);
603 final long[] ticks = new long[n + 1];
604 ticks[0] = min;
605 ticks[1] = max;
606
607 for (int i = 2; i < ticks.length; i++) {
608 ticks[i] = sampler.sample();
609 }
610 Arrays.sort(ticks);
611
612
613
614 final int before = builder.size();
615 for (int i = 1; i < ticks.length; i++) {
616 sampler = new LongRangeSampler(rng, ticks[i - 1], ticks[i]);
617
618 builder.add(sampler, sampler.range);
619 }
620
621 Assertions.assertEquals(n, builder.size() - before, "Failed to add the correct number of samplers");
622 }
623
624
625
626
627
628
629
630
631 private static void assertLongSamplerSamples(LongSampler sampler, long min, long max) {
632 final int n = 100000;
633 final int bins = 200;
634 final long[] observed = new long[bins];
635 final long range = max - min;
636 for (int i = 0; i < n; i++) {
637
638 observed[(int) (bins * (sampler.sample() - min) / range)]++;
639 }
640
641 final double[] expected = new double[observed.length];
642 Arrays.fill(expected, (double) n / expected.length);
643 final double p = new ChiSquareTest().chiSquareTest(expected, observed);
644 Assertions.assertFalse(p < 0.001, () -> "p-value too small: " + p);
645 }
646
647
648
649
650
651 @Test
652 void testSharedStateObjectSampler() {
653 testSharedStateObjectSampler(false);
654 }
655
656
657
658
659
660 @Test
661 void testSharedStateObjectSamplerWithCustomFactory() {
662 testSharedStateObjectSampler(true);
663 }
664
665
666
667
668
669
670
671
672 private static void testSharedStateObjectSampler(boolean customFactory) {
673 final UniformRandomProvider rng1 = RandomAssert.seededRNG();
674 final UniformRandomProvider rng2 = RandomAssert.seededRNG();
675
676 final Builder<SharedStateObjectSampler<Integer>> builder = CompositeSamplers
677 .newSharedStateObjectSamplerBuilder();
678
679 if (customFactory) {
680 addFactoryWithNoSharedStateSupport(builder);
681 }
682
683
684 final int[] ticks = {6, 13, 42, 99};
685 for (int i = 1; i < ticks.length; i++) {
686 final RangeSampler sampler = new RangeSampler(ticks[i - 1], ticks[i], rng1);
687
688 builder.add(sampler, sampler.range);
689 }
690
691 final SharedStateObjectSampler<Integer> sampler1 = builder.build(rng1);
692 final SharedStateObjectSampler<Integer> sampler2 = sampler1.withUniformRandomProvider(rng2);
693 RandomAssert.assertProduceSameSequence(sampler1, sampler2);
694 }
695
696
697
698
699
700 @Test
701 void testSharedStateDiscreteSampler() {
702 testSharedStateDiscreteSampler(false);
703 }
704
705
706
707
708
709 @Test
710 void testSharedStateDiscreteSamplerWithCustomFactory() {
711 testSharedStateDiscreteSampler(true);
712 }
713
714
715
716
717
718
719
720
721 private static void testSharedStateDiscreteSampler(boolean customFactory) {
722 final UniformRandomProvider rng1 = RandomAssert.seededRNG();
723 final UniformRandomProvider rng2 = RandomAssert.seededRNG();
724
725 final Builder<SharedStateDiscreteSampler> builder = CompositeSamplers.newSharedStateDiscreteSamplerBuilder();
726
727 if (customFactory) {
728 addFactoryWithNoSharedStateSupport(builder);
729 }
730
731
732 final int[] ticks = {-3, 5, 14, 22};
733 for (int i = 1; i < ticks.length; i++) {
734 final IntRangeSampler sampler = new IntRangeSampler(rng1, ticks[i - 1], ticks[i]);
735
736 builder.add(sampler, sampler.range);
737 }
738
739 final SharedStateDiscreteSampler sampler1 = builder.build(rng1);
740 final SharedStateDiscreteSampler sampler2 = sampler1.withUniformRandomProvider(rng2);
741 RandomAssert.assertProduceSameSequence(sampler1, sampler2);
742 }
743
744
745
746
747
748 @Test
749 void testSharedStateContinuousSampler() {
750 testSharedStateContinuousSampler(false);
751 }
752
753
754
755
756
757 @Test
758 void testSharedStateContinuousSamplerWithCustomFactory() {
759 testSharedStateContinuousSampler(true);
760 }
761
762
763
764
765
766
767
768
769 private static void testSharedStateContinuousSampler(boolean customFactory) {
770 final UniformRandomProvider rng1 = RandomAssert.seededRNG();
771 final UniformRandomProvider rng2 = RandomAssert.seededRNG();
772
773 final Builder<SharedStateContinuousSampler> builder = CompositeSamplers
774 .newSharedStateContinuousSamplerBuilder();
775
776 if (customFactory) {
777 addFactoryWithNoSharedStateSupport(builder);
778 }
779
780
781 final double[] ticks = {7.89, 13.99, 21.7, 35.6, 45.5};
782 for (int i = 1; i < ticks.length; i++) {
783 final DoubleRangeSampler sampler = new DoubleRangeSampler(rng1, ticks[i - 1], ticks[i]);
784
785 builder.add(sampler, sampler.range());
786 }
787
788 final SharedStateContinuousSampler sampler1 = builder.build(rng1);
789 final SharedStateContinuousSampler sampler2 = sampler1.withUniformRandomProvider(rng2);
790 RandomAssert.assertProduceSameSequence(sampler1, sampler2);
791 }
792
793
794
795
796
797
798 private static void addFactoryWithNoSharedStateSupport(Builder<?> builder) {
799 builder.setFactory(new DiscreteProbabilitySamplerFactory() {
800 @Override
801 public DiscreteSampler create(UniformRandomProvider rng, double[] probabilities) {
802
803 final DiscreteSampler sampler = GuideTableDiscreteSampler.of(rng, probabilities, 2);
804
805 Arrays.fill(probabilities, Double.NaN);
806 return new DiscreteSampler() {
807 @Override
808 public int sample() {
809 return sampler.sample();
810 }
811 };
812 }
813 });
814 }
815
816
817
818
819
820 @Test
821 void testSharedStateLongSampler() {
822 testSharedStateLongSampler(false);
823 }
824
825
826
827
828
829 @Test
830 void testSharedStateLongSamplerWithCustomFactory() {
831 testSharedStateLongSampler(true);
832 }
833
834
835
836
837
838
839
840
841 private static void testSharedStateLongSampler(boolean customFactory) {
842 final UniformRandomProvider rng1 = RandomAssert.seededRNG();
843 final UniformRandomProvider rng2 = RandomAssert.seededRNG();
844
845 final Builder<SharedStateLongSampler> builder = CompositeSamplers.newSharedStateLongSamplerBuilder();
846
847 if (customFactory) {
848 addFactoryWithNoSharedStateSupport(builder);
849 }
850
851
852 final long[] ticks = {-32634628368L, 516234712, 1472839427384234L, 72364572187368423L};
853 for (int i = 1; i < ticks.length; i++) {
854 final LongRangeSampler sampler = new LongRangeSampler(rng1, ticks[i - 1], ticks[i]);
855
856 builder.add(sampler, sampler.range);
857 }
858
859 final SharedStateLongSampler sampler1 = builder.build(rng1);
860 final SharedStateLongSampler sampler2 = sampler1.withUniformRandomProvider(rng2);
861 RandomAssert.assertProduceSameSequence(sampler1, sampler2);
862 }
863
864
865
866
867 private static class RangeSampler implements SharedStateObjectSampler<Integer> {
868 private final int min;
869 private final int range;
870 private final UniformRandomProvider rng;
871
872
873
874
875
876
877 RangeSampler(int min, int max, UniformRandomProvider rng) {
878 this.min = min;
879 this.range = max - min;
880 this.rng = rng;
881 }
882
883 @Override
884 public Integer sample() {
885 return min + rng.nextInt(range);
886 }
887
888 @Override
889 public SharedStateObjectSampler<Integer> withUniformRandomProvider(UniformRandomProvider generator) {
890 return new RangeSampler(min, min + range, generator);
891 }
892 }
893
894
895
896
897 private static class IntRangeSampler implements SharedStateDiscreteSampler {
898 private final int min;
899 private final int range;
900 private final UniformRandomProvider rng;
901
902
903
904
905
906
907 IntRangeSampler(UniformRandomProvider rng, int min, int max) {
908 this.min = min;
909 this.range = max - min;
910 this.rng = rng;
911 }
912
913 @Override
914 public int sample() {
915 return min + rng.nextInt(range);
916 }
917
918 @Override
919 public SharedStateDiscreteSampler withUniformRandomProvider(UniformRandomProvider generator) {
920 return new IntRangeSampler(generator, min, min + range);
921 }
922 }
923
924
925
926
927 private static class DoubleRangeSampler implements SharedStateContinuousSampler {
928 private final double a;
929 private final double b;
930 private final UniformRandomProvider rng;
931
932
933
934
935
936
937 DoubleRangeSampler(UniformRandomProvider rng, double a, double b) {
938 this.a = a;
939 this.b = b;
940 this.rng = rng;
941 }
942
943
944
945
946
947
948 double range() {
949 return Math.abs(b - a);
950 }
951
952 @Override
953 public double sample() {
954
955 final double u = rng.nextDouble();
956 return u * b + (1 - u) * a;
957 }
958
959 @Override
960 public SharedStateContinuousSampler withUniformRandomProvider(UniformRandomProvider generator) {
961 return new DoubleRangeSampler(generator, a, b);
962 }
963 }
964
965
966
967
968 private static class LongRangeSampler implements SharedStateLongSampler {
969 private final long min;
970 private final long range;
971 private final UniformRandomProvider rng;
972
973
974
975
976
977
978 LongRangeSampler(UniformRandomProvider rng, long min, long max) {
979 this.min = min;
980 this.range = max - min;
981 this.rng = rng;
982 }
983
984 @Override
985 public long sample() {
986 return min + rng.nextLong(range);
987 }
988
989 @Override
990 public SharedStateLongSampler withUniformRandomProvider(UniformRandomProvider generator) {
991 return new LongRangeSampler(generator, min, min + range);
992 }
993 }
994 }