1 package org.lcsim.recon.tracking.trfutil; 2 3 import java.util.Random; 4 5 /** 6 * A generator produces objects with random parameters. 7 * 8 * This class is abstract and contains the interface for 9 * the random number generator. Each instance will maintain 10 * its own sequence of random numbers. 11 * 12 * We use the default Java random number generator. 13 * 14 * The calls to rand are encapsulated so that we can keep count of 15 * the number of calls to reproduce the state. 16 * 17 * @author Norman A. Graf 18 * @version 1.0 19 */ 20 public class RandomGenerator 21 { 22 23 // attributes 24 25 // Random number generator. 26 private Random _rand; 27 28 // Number of calls since seed was set. 29 private int _ncall; 30 31 // The seed 32 private long _seed; 33 34 // methods 35 36 /** 37 * Set the state = seed and number of calls. 38 * 39 * @param seed Random number seed 40 * @param ncall Number of calls to this generator 41 */ 42 private void setState(long seed, int ncall) 43 { 44 setSeed(seed); 45 for ( int i=0; i<ncall; ++i ) flat(0.0,1.0); 46 } 47 48 49 /** 50 * Return a flat value in range (min.max). 51 * 52 * @param min The minimum of the range. 53 * @param max The maximum of the range. 54 * @return A double value flat between <em>min</em> and <em >max </em>. 55 */ 56 protected double flat(double min, double max) 57 { 58 ++_ncall; 59 return min + (max-min)*_rand.nextDouble(); 60 } 61 62 63 /** 64 * Return a random number according to a Gaussian distribution 65 * with sigma = 1.0. 66 * We do it this way to ensure that we can reproduce the same sequence. 67 * 68 * @return A double value gaussian distributed with mean 0 and sigma 1. 69 */ 70 protected double gauss() 71 { 72 double v1, v2, r; 73 do 74 { 75 v1 = flat( -1.0, 1.0 ); 76 v2 = flat( -1.0, 1.0 ); 77 r = v1*v1 + v2*v2; 78 } while ( r > 1.0 ); 79 double fac = Math.sqrt( -2.0*Math.log(r)/r); 80 return v2*fac; 81 } 82 83 /** 84 * Default constructor. 85 * 86 */ 87 public RandomGenerator() 88 { 89 _rand = new Random(); 90 setSeed(19970729); 91 } 92 93 /** 94 * Constructor from seed. 95 * 96 * @param seed long value seeding the random number generator. 97 */ 98 public RandomGenerator(long seed) 99 { 100 _rand = new Random(); 101 setSeed(seed); 102 } 103 104 /** 105 * Copy constructor. 106 * The new generator is independent from the original and is in the 107 * same state. 108 * Set the original seed and skip through the same number of 109 * values to obtain the same state. 110 * 111 * @param rgen The RandomGenerator to copy. 112 */ 113 public RandomGenerator( RandomGenerator rgen) 114 { 115 _rand = new Random(); 116 setState(rgen); 117 } 118 119 /** 120 * Set the seed. 121 * Generator is positioned at the beginning of the sequence. 122 * This reinitializes the generator engine, positioning it at the 123 * first value in the sequence. 124 * 125 * @param seed long value seeding the random number generator. 126 */ 127 public void setSeed(long seed) 128 { 129 _ncall = 0; 130 _seed = seed; 131 _rand.setSeed(seed); 132 } 133 134 135 /** 136 * Get the seed. 137 * 138 * @return long value which seeded this random number generator. 139 */ 140 public long seed() 141 { 142 return _seed; 143 } 144 145 /** 146 * Set the state (seed + ncall) to be the same as that of the argument. 147 * 148 * @param rgen RandomGenerator used to set the state of this RandomGenerator. 149 */ 150 public void setState(RandomGenerator rgen) 151 { 152 setState(rgen.seed(),rgen._ncall); 153 } 154 155 156 /** 157 * String representation of this RandomGenerator. 158 * 159 * @return String representation of this RandomGenerator. 160 */ 161 public String toString() 162 { 163 String className = getClass().getName(); 164 int lastDot = className.lastIndexOf('.'); 165 if(lastDot!=-1)className = className.substring(lastDot+1); 166 167 return className+"\nSeed: " + seed() + "\n # calls: " + _ncall; 168 } 169 170 }