1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package org.apache.commons.rng.simple.internal; 18 19 import org.apache.commons.rng.core.util.NumberFactory; 20 import org.apache.commons.rng.core.source32.RandomIntSource; 21 import org.apache.commons.rng.core.source32.Well44497b; 22 import org.apache.commons.rng.core.source64.RandomLongSource; 23 import org.apache.commons.rng.core.source64.SplitMix64; 24 25 /** 26 * Utilities related to seeding. 27 * 28 * <p> 29 * This class provides methods to generate random seeds (single values 30 * or arrays of values, of {@code int} or {@code long} types) that can 31 * be passed to the {@link org.apache.commons.rng.simple.RandomSource 32 * methods that create a generator instance}. 33 * <br> 34 * Although the seed-generating methods defined in this class will likely 35 * return different values for all calls, there is no guarantee that the 36 * produced seed will result always in a "good" sequence of numbers (even 37 * if the generator initialized with that seed is good). 38 * <br> 39 * There is <i>no guarantee</i> that sequences will not overlap. 40 * </p> 41 * 42 * @since 1.0 43 */ 44 public final class SeedFactory { 45 /** Generator with a long period. */ 46 private static final RandomIntSource SEED_GENERATOR; 47 48 static { 49 // Another RNG for initializing the "SEED_GENERATOR". 50 final long t = System.currentTimeMillis(); 51 final int h = System.identityHashCode(Runtime.getRuntime()); 52 final SplitMix64 rng = new SplitMix64(t ^ NumberFactory.makeLong(h, ~h)); 53 54 final int blockCount = 1391; // Size of the state array of "Well44497b". 55 SEED_GENERATOR = new Well44497b(createIntArray(blockCount, rng)); 56 } 57 58 /** 59 * Class contains only static methods. 60 */ 61 private SeedFactory() {} 62 63 /** 64 * Creates a number for use as a seed. 65 * 66 * @return a random number. 67 */ 68 public static int createInt() { 69 return createInt(SEED_GENERATOR, System.identityHashCode(new Object())); 70 } 71 72 /** 73 * Creates a number for use as a seed. 74 * 75 * @return a random number. 76 */ 77 public static long createLong() { 78 return createLong(SEED_GENERATOR, System.identityHashCode(new Object())); 79 } 80 81 /** 82 * Creates an array of numbers for use as a seed. 83 * 84 * @param n Size of the array to create. 85 * @return an array of {@code n} random numbers. 86 */ 87 public static int[] createIntArray(int n) { 88 return createIntArray(n, SEED_GENERATOR, new Object()); 89 } 90 91 /** 92 * Creates an array of numbers for use as a seed. 93 * 94 * @param n Size of the array to create. 95 * @return an array of {@code n} random numbers. 96 */ 97 public static long[] createLongArray(int n) { 98 return createLongArray(n, SEED_GENERATOR, new Object()); 99 } 100 101 /** 102 * Creates an array of numbers for use as a seed. 103 * 104 * @param n Size of the array to create. 105 * @param source Source of randomness. 106 * @return an array of {@code n} random numbers drawn from the 107 * {@code source}. 108 */ 109 static long[] createLongArray(int n, 110 RandomIntSource source) { 111 return createLongArray(n, source, null); 112 } 113 114 /** 115 * Creates an array of numbers for use as a seed. 116 * 117 * @param n Size of the array to create. 118 * @param source Source of randomness. 119 * @return an array of {@code n} random numbers drawn from the 120 * {@code source}. 121 */ 122 static int[] createIntArray(int n, 123 RandomLongSource source) { 124 return createIntArray(n, source, null); 125 } 126 127 /** 128 * Creates an array of numbers for use as a seed. 129 * 130 * @param n Size of the array to create. 131 * @param source Source of randomness. 132 * @return an array of {@code n} random numbers drawn from the 133 * {@code source}. 134 */ 135 static int[] createIntArray(int n, 136 RandomIntSource source) { 137 return createIntArray(n, source, null); 138 } 139 140 /** 141 * Creates an array of numbers for use as a seed. 142 * 143 * @param n Size of the array to create. 144 * @param source Source of randomness. 145 * @param h Arbitrary object whose {@link System#identityHashCode(Object) 146 * hash code} will be combined with the next number drawn from 147 * the {@code source}. 148 * @return an array of {@code n} random numbers. 149 */ 150 private static long[] createLongArray(int n, 151 RandomIntSource source, 152 Object h) { 153 final long[] array = new long[n]; 154 155 final int hash = System.identityHashCode(h); 156 for (int i = 0; i < n; i++) { 157 array[i] = createLong(source, hash); 158 } 159 160 return array; 161 } 162 163 /** 164 * Creates an array of numbers for use as a seed. 165 * 166 * @param n Size of the array to create. 167 * @param source Source of randomness. 168 * @param h Arbitrary object whose {@link System#identityHashCode(Object) 169 * hash code} will be combined with the next number drawn from 170 * the {@code source}. 171 * @return an array of {@code n} random numbers. 172 */ 173 private static int[] createIntArray(int n, 174 RandomLongSource source, 175 Object h) { 176 final int[] array = new int[n]; 177 178 final int hash = System.identityHashCode(h); 179 for (int i = 0; i < n; i += 2) { 180 final long v = createLong(source, hash); 181 182 array[i] = NumberFactory.extractHi(v); 183 184 if (i + 1 < n) { 185 array[i + 1] = NumberFactory.extractLo(v); 186 } 187 } 188 189 return array; 190 } 191 192 /** 193 * Creates an array of numbers for use as a seed. 194 * 195 * @param n Size of the array to create. 196 * @param source Source of randomness. 197 * @param h Arbitrary object whose {@link System#identityHashCode(Object) 198 * hash code} will be combined with the next number drawn from 199 * the {@code source}. 200 * @return an array of {@code n} random numbers. 201 */ 202 private static int[] createIntArray(int n, 203 RandomIntSource source, 204 Object h) { 205 final int[] array = new int[n]; 206 207 final int hash = System.identityHashCode(h); 208 for (int i = 0; i < n; i++) { 209 array[i] = createInt(source, hash); 210 } 211 212 return array; 213 } 214 215 /** 216 * Creates a random number by performing an "xor" between the 217 * next value in the sequence of the {@code source} and the 218 * given {@code number}. 219 * 220 * @param source Source of randomness. 221 * @param number Arbitrary number. 222 * @return a random number. 223 */ 224 private static long createLong(RandomLongSource source, 225 int number) { 226 synchronized (source) { 227 return source.next() ^ NumberFactory.makeLong(number, number); 228 } 229 } 230 231 /** 232 * Creates a random number by performing an "xor" between the 233 * the next value in the sequence of the {@code source} and the 234 * given {@code number}. 235 * 236 * @param source Source of randomness. 237 * @param number Arbitrary number. 238 * @return a random number. 239 */ 240 private static long createLong(RandomIntSource source, 241 int number) { 242 synchronized (source) { 243 return NumberFactory.makeLong(source.next() ^ number, 244 source.next() ^ number); 245 } 246 } 247 248 /** 249 * Creates a random number by performing an "xor" between the 250 * next value in the sequence of the {@code source} and the 251 * given {@code number}. 252 * 253 * @param source Source of randomness. 254 * @param number Arbitrary number. 255 * @return a random number. 256 */ 257 private static int createInt(RandomIntSource source, 258 int number) { 259 synchronized (source) { 260 return source.next() ^ number; 261 } 262 } 263 }