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