001 package com.softnetConsult.utils.random;
002
003 import java.util.Random;
004
005
006 /**
007 * Provides a fast pseudorandom number generator by trading off memory for speed.
008 * Objects of this class generate a large number of random numbers when
009 * they are created and reuse them throughout the life-time. For many
010 * applications the repetition effect does not significantly affect the
011 * quality of the random series given that the size of the buffer sufficiently
012 * large. This class is usefull when a time-critical application requires a
013 * very large number of random numbers; a slight delay for the buffer creation
014 * at the start saves a lot of time during the runtime. <br />
015 * Note that the current version of this class accelerates only the generation of
016 * pseudorandom values of types {@code boolean}, {@code double} and {@code int}:
017 * pseudorandom values are pre-generated and cached, pseudorandom values of other
018 * types are generated on the fly by passing the {@code nextXXX()}-calls to the
019 * default Java pseudorandom number generator.
020 *
021 * <p style="font-size:smaller;">This product includes software developed by the
022 * <strong>SoftNet-Consult Java Utility Library</strong> project and its contributors.<br />
023 * (<a href="http://java-tools.sourceforge.net" target="_blank">http://java-tools.sourceforge.net</a>)<br />
024 * Copyright (c) 2007-2008 SoftNet-Consult.<br />
025 * Copyright (c) 2007-2008 G. Paperin.<br />
026 * All rights reserved.
027 * </p>
028 * <p style="font-size:smaller;">File: FastRandom.java<br />
029 * Library API version: {@value com.softnetConsult.utils.APIProperties#apiVersion}<br />
030 * Java compliance version: {@value com.softnetConsult.utils.APIProperties#javaComplianceVersion}
031 * </p>
032 * <p style="font-size:smaller;">Redistribution and use in source and binary forms, with or
033 * without modification, are permitted provided that the following terms and conditions are met:
034 * </p>
035 * <p style="font-size:smaller;">1. Redistributions of source code must retain the above
036 * acknowledgement of the SoftNet-Consult Java Utility Library project, the above copyright
037 * notice, this list of conditions and the following disclaimer.<br />
038 * 2. Redistributions in binary form must reproduce the above acknowledgement of the
039 * SoftNet-Consult Java Utility Library project, the above copyright notice, this list of
040 * conditions and the following disclaimer in the documentation and/or other materials
041 * provided with the distribution.<br />
042 * 3. All advertising materials mentioning features or use of this software or any derived
043 * software must display the following acknowledgement:<br />
044 * <em>This product includes software developed by the SoftNet-Consult Java Utility Library
045 * project and its contributors.</em>
046 * </p>
047 * <p style="font-size:smaller;">THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY
048 * OF ANY KIND, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
049 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
050 * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
051 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
052 * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
053 * </p>
054 * @author Greg Paperin (<a href="http://www.paperin.org" target="_blank">http://www.paperin.org</a>)
055 * @version {@value com.softnetConsult.utils.APIProperties#apiVersion}
056 *
057 * @see java.util.Random
058 */
059 public class FastRandom extends Random {
060
061 /**
062 * Used internally for debug purposes.
063 */
064 private static final boolean generateDebugPrintout = true;
065
066 /**
067 * Default buffer size for random booleans.
068 */
069 public static final int defaultBooleanBufferSize = 10000000;
070
071 /**
072 * Default buffer size for random doubles.
073 */
074 public static final int defaultDoubleBufferSize = 10000000;
075
076 /**
077 * Default buffer size for random ints.
078 */
079 public static final int defaultIntBufferSize = 10000000;
080
081
082 /**
083 * The buffer for random booleans.
084 */
085 private boolean [] booleanBuffer;
086
087 /**
088 * The buffer for random doubles.
089 */
090 private double [] doubleBuffer;
091
092 /**
093 * The buffer for random ints.
094 */
095 private int [] intBuffer;
096
097
098 /**
099 * Cursor for the boolean random numbers buffer.
100 */
101 private int booleanCursor;
102
103 /**
104 * Cursor for the double random numbers buffer.
105 */
106 private int doubleCursor;
107
108 /**
109 * Cursor for the int random numbers buffer.
110 */
111 private int intCursor;
112
113 /**
114 * Flag to show that this object has readily initialised.
115 */
116 private boolean ready = false;
117
118
119 /**
120 * Creates a new {@code FastRandom} with default buffer sizes.
121 *
122 */
123 public FastRandom() {
124 this(defaultBooleanBufferSize, defaultDoubleBufferSize, defaultIntBufferSize);
125 }
126
127 /**
128 * Creates a new {@code FastRandom} with default buffer sizes and a specified random seed.
129 *
130 * @param seed Inital random seed.
131 */
132 public FastRandom(long seed) {
133 this(seed, defaultBooleanBufferSize, defaultDoubleBufferSize, defaultIntBufferSize);
134 }
135
136
137 /**
138 * Creates a new {@code FastRandom} with buffers of the specified size.
139 *
140 * @param bufferSize The size for the random numbers buffers.
141 */
142 public FastRandom(int bufferSize) {
143 this(bufferSize, bufferSize, bufferSize);
144 }
145
146
147 /**
148 * Creates a new {@code FastRandom} with buffers of the specified size a specified random seed.
149 *
150 * @param seed Inital random seed.
151 * @param bufferSize The size for the random numbers buffers.
152 */
153 public FastRandom(long seed, int bufferSize) {
154 this(seed, bufferSize, bufferSize, bufferSize);
155 }
156
157
158 /**
159 * Creates a new {@code FastRandom} with buffers of the specified size.
160 *
161 * @param booleanBufferSize The size for the random {@code boolean} numbers buffer.
162 * @param doubleBufferSize The size for the random {@code double} numbers buffer.
163 * @param intBufferSize The size for the random {@code int} numbers buffer.
164 */
165 public FastRandom(int booleanBufferSize, int doubleBufferSize, int intBufferSize) {
166 super();
167 createBuffers(booleanBufferSize, doubleBufferSize, intBufferSize);
168 ready = true;
169 resetBuffers();
170 }
171
172
173 /**
174 * Creates a new {@code FastRandom} with buffers of the specified size a specified random seed.
175 *
176 * @param seed Inital random seed.
177 * @param booleanBufferSize The size for the random {@code boolean} numbers buffer.
178 * @param doubleBufferSize The size for the random {@code double} numbers buffer.
179 * @param intBufferSize The size for the random {@code int} numbers buffer.
180 */
181 public FastRandom(long seed, int booleanBufferSize,int doubleBufferSize, int intBufferSize) {
182 super(seed);
183 createBuffers(booleanBufferSize, doubleBufferSize, intBufferSize);
184 ready = true;
185 resetBuffers();
186 }
187
188
189 /**
190 * Allocates the random buffer arrays.
191 *
192 * @param booleanBufferSize The size for the random {@code boolean} numbers buffer.
193 * @param doubleBufferSize The size for the random {@code double} numbers buffer.
194 * @param intBufferSize The size for the random {@code int} numbers buffer.
195 */
196 private void createBuffers(int booleanBufferSize,int doubleBufferSize, int intBufferSize) {
197 booleanBuffer = new boolean[booleanBufferSize];
198 doubleBuffer = new double[doubleBufferSize];
199 intBuffer = new int[intBufferSize];
200 }
201
202
203 /**
204 * Sets the seed of this random number generator and then re-computes all buffers.
205 *
206 * @param seed Inital random seed.
207 * @see java.util.Random#setSeed(long)
208 */
209 @Override
210 public void setSeed(long seed) {
211 super.setSeed(seed);
212 resetBuffers();
213 }
214
215
216 /**
217 * Returns the next pseudorandom {@code boolean}.
218 * The buffered random booleans are used as source.
219 * Once the buffer has been used up, it is used again from the start.
220 *
221 * @return A pseudorandom {@code boolean}.
222 * @see java.util.Random#nextBoolean()
223 */
224 @Override
225 public boolean nextBoolean() {
226 if (booleanBuffer.length == booleanCursor)
227 booleanCursor = 0;
228 return booleanBuffer[booleanCursor++];
229 }
230
231
232 /**
233 * Returns the next pseudorandom {@code double}.
234 * The buffered random doubles are used as source.
235 * Once the buffer has been used up, it is used again from the start.
236 *
237 * @return A pseudorandom {@code double}.
238 * @see java.util.Random#nextDouble()
239 */
240 @Override
241 public double nextDouble() {
242 if (doubleBuffer.length == doubleCursor)
243 doubleCursor = 0;
244 return doubleBuffer[doubleCursor++];
245 }
246
247
248 /**
249 * Returns the next pseudorandom {@code int}.
250 * The buffered random ints are used as source.
251 * Once the buffer has been used up, it is used again from the start.
252 *
253 * @return A pseudorandom {@code int}.
254 * @see java.util.Random#nextInt()
255 */
256 @Override
257 public int nextInt() {
258 if (intBuffer.length == intCursor)
259 intCursor = 0;
260 return intBuffer[intCursor++];
261 }
262
263
264 /**
265 * Used internally to fill the pseudorandom numbers buffers with values.
266 */
267 private void resetBuffers() {
268
269 // Intro:
270
271 if (!ready)
272 return;
273
274 Runtime rt = null;
275 if (generateDebugPrintout) {
276 System.out.println("FastRandom generates buffers...");
277 rt = Runtime.getRuntime();
278 }
279
280 // Booleans:
281
282 if (generateDebugPrintout) {
283 System.out.printf("Current heap size: %,d KB. ", rt.totalMemory() / 1024);
284 System.out.println("Generating boolean random buffer...");
285 }
286
287 booleanCursor = 0;
288 for (int i = 0; i < booleanBuffer.length; i++)
289 booleanBuffer[i] = super.nextBoolean();
290
291 // Doubles:
292
293 if (generateDebugPrintout) {
294 System.out.printf("Current heap size: %,d KB. ", rt.totalMemory() / 1024);
295 System.out.println("Generating double random buffer...");
296 }
297
298 doubleCursor = 0;
299 for (int i = 0; i < doubleBuffer.length; i++)
300 doubleBuffer[i] = super.nextDouble();
301
302 // Ints:
303
304 if (generateDebugPrintout) {
305 System.out.printf("Current heap size: %,d KB. ", rt.totalMemory() / 1024);
306 System.out.println("Generating int random buffer...");
307 }
308
309 intCursor = 0;
310 for (int i = 0; i < intBuffer.length; i++)
311 intBuffer[i] = super.nextInt();
312
313 // Done:
314
315 if (generateDebugPrintout) {
316 System.out.println("FastRandom completed generating buffers.");
317 System.out.printf("Current heap size: %,d KB. ", rt.totalMemory() / 1024);
318 System.out.println();
319 }
320 }
321
322 } // public class FastRandom