jetbrains.exodus.util.Random Maven / Gradle / Ivy
/**
* Copyright 2010 - 2022 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jetbrains.exodus.util;
/**
* Non-concurrent replacement of java.util.Random.
*/
public class Random {
private static final long multiplier = 0x5DEECE66DL;
private static final long addend = 0xBL;
private static final long mask = (1L << 48) - 1;
private long seed;
public Random() {
reset();
}
public Random(long seed) {
setSeed(seed);
}
public int nextInt() {
return next(32);
}
public int nextInt(int n) {
if (n <= 0)
throw new IllegalArgumentException("n must be positive");
if ((n & -n) == n) // i.e., n is a power of 2
return (int) ((n * (long) next(31)) >> 31);
int bits, val;
do {
bits = next(31);
val = bits % n;
} while (bits - val + (n - 1) < 0);
return val;
}
public long nextLong() {
// it's okay that the bottom word remains signed.
return ((long) (next(32)) << 32) + next(32);
}
public boolean nextBoolean() {
return next(1) != 0;
}
public float nextFloat() {
return next(24) / ((float) (1 << 24));
}
public double nextDouble() {
return (((long) (next(26)) << 27) + next(27)) / (double) (1L << 53);
}
public void nextBytes(byte[] bytes) {
int i = 0;
int len = bytes.length;
while (i < len)
for (int rnd = nextInt(),
n = Math.min(len - i, Integer.SIZE / Byte.SIZE);
n-- > 0; rnd >>= Byte.SIZE)
bytes[i++] = (byte) rnd;
}
public void setSeed(long seed) {
this.seed = (seed ^ multiplier) & mask;
for (int i = 0; i < 10; ++i) {
nextInt();
}
}
public void reset() {
setSeed(System.currentTimeMillis());
}
public int next(int bits) {
seed = (seed * multiplier + addend) & mask;
return (int) (seed >>> (48 - bits));
}
}