org.apache.commons.rng.simple.internal.SeedFactory Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of virtdata-lib-curves4 Show documentation
Show all versions of virtdata-lib-curves4 Show documentation
Statistical sampling library for use in virtdata libraries, based
on apache commons math 4
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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
*
* http://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 org.apache.commons.rng.simple.internal;
import org.apache.commons.rng.core.source32.RandomIntSource;
import org.apache.commons.rng.core.source32.Well44497b;
import org.apache.commons.rng.core.source64.RandomLongSource;
import org.apache.commons.rng.core.source64.SplitMix64;
import org.apache.commons.rng.core.util.NumberFactory;
import java.security.SecureRandom;
/**
* Utilities related to seeding.
*
*
* This class provides methods to generate random seeds (single values
* or arrays of values, of {@code int} or {@code long} types) that can
* be passed to the {@link org.apache.commons.rng.simple.RandomSource
* methods that create a generator instance}.
*
* Although the seed-generating methods defined in this class will likely
* return different values for all calls, there is no guarantee that the
* produced seed will result always in a "good" sequence of numbers (even
* if the generator initialized with that seed is good).
*
* There is no guarantee that sequences will not overlap.
*
*
* @since 1.0
*/
public final class SeedFactory {
/** Generator with a long period. */
private static final RandomIntSource SEED_GENERATOR;
static {
// Use a secure RNG so that different instances (e.g. in multiple JVM
// instances started in rapid succession) will have different seeds.
final SecureRandom seedGen = new SecureRandom();
final long initSeed = NumberFactory.makeLong(seedGen.generateSeed(8));
final SplitMix64 rng = new SplitMix64(initSeed);
final int blockCount = 1391; // Size of the state array of "Well44497b".
SEED_GENERATOR = new Well44497b(createIntArray(blockCount, rng));
}
/**
* Class contains only static methods.
*/
private SeedFactory() {}
/**
* Creates a number for use as a seed.
*
* @return a random number.
*/
public static int createInt() {
return createInt(SEED_GENERATOR, System.identityHashCode(new Object()));
}
/**
* Creates a number for use as a seed.
*
* @return a random number.
*/
public static long createLong() {
return createLong(SEED_GENERATOR, System.identityHashCode(new Object()));
}
/**
* Creates an array of numbers for use as a seed.
*
* @param n Size of the array to create.
* @return an array of {@code n} random numbers.
*/
public static int[] createIntArray(int n) {
return createIntArray(n, SEED_GENERATOR, new Object());
}
/**
* Creates an array of numbers for use as a seed.
*
* @param n Size of the array to create.
* @return an array of {@code n} random numbers.
*/
public static long[] createLongArray(int n) {
return createLongArray(n, SEED_GENERATOR, new Object());
}
/**
* Creates an array of numbers for use as a seed.
*
* @param n Size of the array to create.
* @param source Source of randomness.
* @return an array of {@code n} random numbers drawn from the
* {@code source}.
*/
static long[] createLongArray(int n,
RandomIntSource source) {
return createLongArray(n, source, null);
}
/**
* Creates an array of numbers for use as a seed.
*
* @param n Size of the array to create.
* @param source Source of randomness.
* @return an array of {@code n} random numbers drawn from the
* {@code source}.
*/
static int[] createIntArray(int n,
RandomLongSource source) {
return createIntArray(n, source, null);
}
/**
* Creates an array of numbers for use as a seed.
*
* @param n Size of the array to create.
* @param source Source of randomness.
* @return an array of {@code n} random numbers drawn from the
* {@code source}.
*/
static int[] createIntArray(int n,
RandomIntSource source) {
return createIntArray(n, source, null);
}
/**
* Creates an array of numbers for use as a seed.
*
* @param n Size of the array to create.
* @param source Source of randomness.
* @param h Arbitrary object whose {@link System#identityHashCode(Object)
* hash code} will be combined with the next number drawn from
* the {@code source}.
* @return an array of {@code n} random numbers.
*/
private static long[] createLongArray(int n,
RandomIntSource source,
Object h) {
final long[] array = new long[n];
final int hash = System.identityHashCode(h);
for (int i = 0; i < n; i++) {
array[i] = createLong(source, hash);
}
return array;
}
/**
* Creates an array of numbers for use as a seed.
*
* @param n Size of the array to create.
* @param source Source of randomness.
* @param h Arbitrary object whose {@link System#identityHashCode(Object)
* hash code} will be combined with the next number drawn from
* the {@code source}.
* @return an array of {@code n} random numbers.
*/
private static int[] createIntArray(int n,
RandomLongSource source,
Object h) {
final int[] array = new int[n];
final int hash = System.identityHashCode(h);
for (int i = 0; i < n; i += 2) {
final long v = createLong(source, hash);
array[i] = NumberFactory.extractHi(v);
if (i + 1 < n) {
array[i + 1] = NumberFactory.extractLo(v);
}
}
return array;
}
/**
* Creates an array of numbers for use as a seed.
*
* @param n Size of the array to create.
* @param source Source of randomness.
* @param h Arbitrary object whose {@link System#identityHashCode(Object)
* hash code} will be combined with the next number drawn from
* the {@code source}.
* @return an array of {@code n} random numbers.
*/
private static int[] createIntArray(int n,
RandomIntSource source,
Object h) {
final int[] array = new int[n];
final int hash = System.identityHashCode(h);
for (int i = 0; i < n; i++) {
array[i] = createInt(source, hash);
}
return array;
}
/**
* Creates a random number by performing an "xor" between the
* next value in the sequence of the {@code source} and the
* given {@code number}.
*
* @param source Source of randomness.
* @param number Arbitrary number.
* @return a random number.
*/
private static long createLong(RandomLongSource source,
int number) {
synchronized (source) {
return source.next() ^ NumberFactory.makeLong(number, number);
}
}
/**
* Creates a random number by performing an "xor" between the
* the next value in the sequence of the {@code source} and the
* given {@code number}.
*
* @param source Source of randomness.
* @param number Arbitrary number.
* @return a random number.
*/
private static long createLong(RandomIntSource source,
int number) {
synchronized (source) {
return NumberFactory.makeLong(source.next() ^ number,
source.next() ^ number);
}
}
/**
* Creates a random number by performing an "xor" between the
* next value in the sequence of the {@code source} and the
* given {@code number}.
*
* @param source Source of randomness.
* @param number Arbitrary number.
* @return a random number.
*/
private static int createInt(RandomIntSource source,
int number) {
synchronized (source) {
return source.next() ^ number;
}
}
}