26 package ca.uqac.lif.synthia.random;
27 import java.util.Spliterator;
28 import java.util.concurrent.atomic.AtomicLong;
29 import java.util.function.DoubleConsumer;
30 import java.util.function.IntConsumer;
31 import java.util.function.LongConsumer;
32 import java.util.stream.DoubleStream;
33 import java.util.stream.IntStream;
34 import java.util.stream.LongStream;
35 import java.util.stream.StreamSupport;
77 static final long serialVersionUID = 3905348978240129619L;
84 private final AtomicLong seed;
86 private static final long multiplier = 0x5DEECE66DL;
87 private static final long addend = 0xBL;
88 private static final long mask = (1L << 48) - 1;
90 private static final double DOUBLE_UNIT = 0x1.0p-53;
93 static final String BadBound =
"bound must be positive";
94 static final String BadRange =
"bound must be greater than origin";
95 static final String BadSize =
"size must be non-negative";
103 this(seedUniquifier() ^ System.nanoTime());
113 private Random(AtomicLong seed,
double nextNextGaussian,
boolean haveNextNextGaussian) {
115 this.nextNextGaussian = nextNextGaussian;
116 this.haveNextNextGaussian = haveNextNextGaussian;
124 return new Random(
new AtomicLong(this.seed.get()),
this.nextNextGaussian
125 ,
this.haveNextNextGaussian);
128 private static long seedUniquifier() {
132 long current = seedUniquifier.get();
133 long next = current * 181783497276652981L;
134 if (seedUniquifier.compareAndSet(current,
next))
139 private static final AtomicLong seedUniquifier
140 =
new AtomicLong(8682522807148012L);
156 if (getClass() ==
Random.class)
157 this.seed =
new AtomicLong(initialScramble(seed));
160 this.seed =
new AtomicLong();
165 private static long initialScramble(
long seed) {
166 return (seed ^ multiplier) & mask;
189 this.seed.set(initialScramble(seed));
190 haveNextNextGaussian =
false;
219 long oldseed, nextseed;
220 AtomicLong seed = this.seed;
222 oldseed = seed.get();
223 nextseed = (oldseed * multiplier + addend) & mask;
224 }
while (!seed.compareAndSet(oldseed, nextseed));
225 return (
int)(nextseed >>> (48 - bits));
248 for (
int i = 0, len = bytes.length; i < len; )
250 n = Math.min(len - i, Integer.SIZE/Byte.SIZE);
251 n-- > 0; rnd >>= Byte.SIZE)
252 bytes[i++] = (byte)rnd;
264 final long internalNextLong(
long origin,
long bound) {
266 if (origin < bound) {
267 long n = bound - origin, m = n - 1;
269 r = (r & m) + origin;
271 for (
long u = r >>> 1;
272 u + m - (r = u % n) < 0L;
278 while (r < origin || r >= bound)
295 final int internalNextInt(
int origin,
int bound) {
296 if (origin < bound) {
297 int n = bound - origin;
305 }
while (r < origin || r >= bound);
321 final double internalNextDouble(
double origin,
double bound) {
323 if (origin < bound) {
324 r = r * (bound - origin) + origin;
326 r = Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1);
408 throw new IllegalArgumentException(BadBound);
412 if ((bound & m) == 0)
413 r = (int)((bound * (
long)r) >> 31);
416 u - (r = u % bound) + m < 0;
444 return ((
long)(
next(32)) << 32) +
next(32);
509 return next(24) / ((float)(1 << 24));
552 return (((
long)(
next(26)) << 27) +
next(27)) * DOUBLE_UNIT;
555 private double nextNextGaussian;
556 private boolean haveNextNextGaussian =
false;
605 if (haveNextNextGaussian) {
606 haveNextNextGaussian =
false;
607 return nextNextGaussian;
613 s = v1 * v1 + v2 * v2;
614 }
while (s >= 1 || s == 0);
615 double multiplier = StrictMath.sqrt(-2 * StrictMath.log(s)/s);
616 nextNextGaussian = v2 * multiplier;
617 haveNextNextGaussian =
true;
618 return v1 * multiplier;
638 public IntStream
ints(
long streamSize) {
640 throw new IllegalArgumentException(BadSize);
641 return StreamSupport.intStream
642 (
new RandomIntsSpliterator
643 (
this, 0L, streamSize, Integer.MAX_VALUE, 0),
661 return StreamSupport.intStream
662 (
new RandomIntsSpliterator
663 (
this, 0L, Long.MAX_VALUE, Integer.MAX_VALUE, 0),
699 public IntStream
ints(
long streamSize,
int randomNumberOrigin,
700 int randomNumberBound) {
702 throw new IllegalArgumentException(BadSize);
703 if (randomNumberOrigin >= randomNumberBound)
704 throw new IllegalArgumentException(BadRange);
705 return StreamSupport.intStream
706 (
new RandomIntsSpliterator
707 (
this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
744 public IntStream
ints(
int randomNumberOrigin,
int randomNumberBound) {
745 if (randomNumberOrigin >= randomNumberBound)
746 throw new IllegalArgumentException(BadRange);
747 return StreamSupport.intStream
748 (
new RandomIntsSpliterator
749 (
this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
766 public LongStream
longs(
long streamSize) {
768 throw new IllegalArgumentException(BadSize);
769 return StreamSupport.longStream
770 (
new RandomLongsSpliterator
771 (
this, 0L, streamSize, Long.MAX_VALUE, 0L),
789 return StreamSupport.longStream
790 (
new RandomLongsSpliterator
791 (
this, 0L, Long.MAX_VALUE, Long.MAX_VALUE, 0L),
832 public LongStream
longs(
long streamSize,
long randomNumberOrigin,
833 long randomNumberBound) {
835 throw new IllegalArgumentException(BadSize);
836 if (randomNumberOrigin >= randomNumberBound)
837 throw new IllegalArgumentException(BadRange);
838 return StreamSupport.longStream
839 (
new RandomLongsSpliterator
840 (
this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
882 public LongStream
longs(
long randomNumberOrigin,
long randomNumberBound) {
883 if (randomNumberOrigin >= randomNumberBound)
884 throw new IllegalArgumentException(BadRange);
885 return StreamSupport.longStream
886 (
new RandomLongsSpliterator
887 (
this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
905 public DoubleStream
doubles(
long streamSize) {
907 throw new IllegalArgumentException(BadSize);
908 return StreamSupport.doubleStream
909 (
new RandomDoublesSpliterator
910 (
this, 0L, streamSize, Double.MAX_VALUE, 0.0),
929 return StreamSupport.doubleStream
930 (
new RandomDoublesSpliterator
931 (
this, 0L, Long.MAX_VALUE, Double.MAX_VALUE, 0.0),
962 public DoubleStream
doubles(
long streamSize,
double randomNumberOrigin,
963 double randomNumberBound) {
965 throw new IllegalArgumentException(BadSize);
966 if (!(randomNumberOrigin < randomNumberBound))
967 throw new IllegalArgumentException(BadRange);
968 return StreamSupport.doubleStream
969 (
new RandomDoublesSpliterator
970 (
this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
1001 public DoubleStream
doubles(
double randomNumberOrigin,
double randomNumberBound) {
1002 if (!(randomNumberOrigin < randomNumberBound))
1003 throw new IllegalArgumentException(BadRange);
1004 return StreamSupport.doubleStream
1005 (
new RandomDoublesSpliterator
1006 (
this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
1018 static final class RandomIntsSpliterator
implements Spliterator.OfInt {
1024 RandomIntsSpliterator(
Random rng,
long index,
long fence,
1025 int origin,
int bound) {
1026 this.rng = rng; this.index = index; this.fence = fence;
1027 this.origin = origin; this.bound = bound;
1030 public RandomIntsSpliterator trySplit() {
1031 long i = index, m = (i + fence) >>> 1;
1032 return (m <= i) ? null :
1033 new RandomIntsSpliterator(rng, i, index = m, origin, bound);
1036 public long estimateSize() {
1037 return fence - index;
1040 public int characteristics() {
1041 return (Spliterator.SIZED | Spliterator.SUBSIZED |
1042 Spliterator.NONNULL | Spliterator.IMMUTABLE);
1045 public boolean tryAdvance(IntConsumer consumer) {
1046 if (consumer ==
null)
throw new NullPointerException();
1047 long i = index, f = fence;
1049 consumer.accept(rng.internalNextInt(origin, bound));
1056 public void forEachRemaining(IntConsumer consumer) {
1057 if (consumer ==
null)
throw new NullPointerException();
1058 long i = index, f = fence;
1062 int o = origin, b = bound;
1064 consumer.accept(r.internalNextInt(o, b));
1073 static final class RandomLongsSpliterator
implements Spliterator.OfLong {
1079 RandomLongsSpliterator(
Random rng,
long index,
long fence,
1080 long origin,
long bound) {
1081 this.rng = rng; this.index = index; this.fence = fence;
1082 this.origin = origin; this.bound = bound;
1085 public RandomLongsSpliterator trySplit() {
1086 long i = index, m = (i + fence) >>> 1;
1087 return (m <= i) ? null :
1088 new RandomLongsSpliterator(rng, i, index = m, origin, bound);
1091 public long estimateSize() {
1092 return fence - index;
1095 public int characteristics() {
1096 return (Spliterator.SIZED | Spliterator.SUBSIZED |
1097 Spliterator.NONNULL | Spliterator.IMMUTABLE);
1100 public boolean tryAdvance(LongConsumer consumer) {
1101 if (consumer ==
null)
throw new NullPointerException();
1102 long i = index, f = fence;
1104 consumer.accept(rng.internalNextLong(origin, bound));
1111 public void forEachRemaining(LongConsumer consumer) {
1112 if (consumer ==
null)
throw new NullPointerException();
1113 long i = index, f = fence;
1117 long o = origin, b = bound;
1119 consumer.accept(r.internalNextLong(o, b));
1129 static final class RandomDoublesSpliterator
implements Spliterator.OfDouble {
1133 final double origin;
1135 RandomDoublesSpliterator(
Random rng,
long index,
long fence,
1136 double origin,
double bound) {
1137 this.rng = rng; this.index = index; this.fence = fence;
1138 this.origin = origin; this.bound = bound;
1141 public RandomDoublesSpliterator trySplit() {
1142 long i = index, m = (i + fence) >>> 1;
1143 return (m <= i) ? null :
1144 new RandomDoublesSpliterator(rng, i, index = m, origin, bound);
1147 public long estimateSize() {
1148 return fence - index;
1151 public int characteristics() {
1152 return (Spliterator.SIZED | Spliterator.SUBSIZED |
1153 Spliterator.NONNULL | Spliterator.IMMUTABLE);
1156 public boolean tryAdvance(DoubleConsumer consumer) {
1157 if (consumer ==
null)
throw new NullPointerException();
1158 long i = index, f = fence;
1160 consumer.accept(rng.internalNextDouble(origin, bound));
1167 public void forEachRemaining(DoubleConsumer consumer) {
1168 if (consumer ==
null)
throw new NullPointerException();
1169 long i = index, f = fence;
1173 double o = origin, b = bound;
1175 consumer.accept(r.internalNextDouble(o, b));