001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.rng.simple.internal; 018 019import org.apache.commons.rng.core.util.NumberFactory; 020import org.apache.commons.rng.core.source32.RandomIntSource; 021import org.apache.commons.rng.core.source32.Well44497b; 022import org.apache.commons.rng.core.source64.RandomLongSource; 023import org.apache.commons.rng.core.source64.SplitMix64; 024 025/** 026 * Utilities related to seeding. 027 * 028 * <p> 029 * This class provides methods to generate random seeds (single values 030 * or arrays of values, of {@code int} or {@code long} types) that can 031 * be passed to the {@link org.apache.commons.rng.simple.RandomSource 032 * methods that create a generator instance}. 033 * <br> 034 * Although the seed-generating methods defined in this class will likely 035 * return different values for all calls, there is no guarantee that the 036 * produced seed will result always in a "good" sequence of numbers (even 037 * if the generator initialized with that seed is good). 038 * <br> 039 * There is <i>no guarantee</i> that sequences will not overlap. 040 * </p> 041 * 042 * @since 1.0 043 */ 044public final class SeedFactory { 045 /** Generator with a long period. */ 046 private static final RandomIntSource SEED_GENERATOR; 047 048 static { 049 // Another RNG for initializing the "SEED_GENERATOR". 050 final long t = System.currentTimeMillis(); 051 final int h = System.identityHashCode(Runtime.getRuntime()); 052 final SplitMix64 rng = new SplitMix64(t ^ NumberFactory.makeLong(h, ~h)); 053 054 final int blockCount = 1391; // Size of the state array of "Well44497b". 055 SEED_GENERATOR = new Well44497b(createIntArray(blockCount, rng)); 056 } 057 058 /** 059 * Class contains only static methods. 060 */ 061 private SeedFactory() {} 062 063 /** 064 * Creates a number for use as a seed. 065 * 066 * @return a random number. 067 */ 068 public static int createInt() { 069 return createInt(SEED_GENERATOR, System.identityHashCode(new Object())); 070 } 071 072 /** 073 * Creates a number for use as a seed. 074 * 075 * @return a random number. 076 */ 077 public static long createLong() { 078 return createLong(SEED_GENERATOR, System.identityHashCode(new Object())); 079 } 080 081 /** 082 * Creates an array of numbers for use as a seed. 083 * 084 * @param n Size of the array to create. 085 * @return an array of {@code n} random numbers. 086 */ 087 public static int[] createIntArray(int n) { 088 return createIntArray(n, SEED_GENERATOR, new Object()); 089 } 090 091 /** 092 * Creates an array of numbers for use as a seed. 093 * 094 * @param n Size of the array to create. 095 * @return an array of {@code n} random numbers. 096 */ 097 public static long[] createLongArray(int n) { 098 return createLongArray(n, SEED_GENERATOR, new Object()); 099 } 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}