View Javadoc

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.math.random;
18  
19  /**
20   * Abstract class implementing the {@link  RandomGenerator} interface.
21   * Default implementations for all methods other than {@link #nextDouble()} and
22   * {@link #setSeed(long)} are provided. 
23   * <p>
24   * All data generation methods are based on <code>nextDouble().</code>
25   * Concrete implementations <strong>must</strong> override
26   * this method and <strong>should</strong> provide better / more
27   * performant implementations of the other methods if the underlying PRNG
28   * supplies them.</p>
29   *
30   * @since 1.1
31   * @version $Revision: 615734 $ $Date: 2008-01-27 23:10:03 -0700 (Sun, 27 Jan 2008) $
32   */
33  public abstract class AbstractRandomGenerator implements RandomGenerator {
34      
35      /** 
36       * Cached random normal value.  The default implementation for 
37       * {@link #nextGaussian} generates pairs of values and this field caches the
38       * second value so that the full algorithm is not executed for every
39       * activation.  The value <code>Double.NaN</code> signals that there is
40       * no cached value.  Use {@link #clear} to clear the cached value.
41       */
42      private double cachedNormalDeviate = Double.NaN;
43      
44      /**
45       * Construct a RandomGenerator.
46       */
47      public AbstractRandomGenerator() {
48          super();
49          
50      }
51      
52      /**
53       * Clears the cache used by the default implementation of 
54       * {@link #nextGaussian}. Implemementations that do not override the
55       * default implementation of <code>nextGaussian</code> should call this
56       * method in the implementation of {@link #setSeed(long)}
57       */
58      public void clear() {
59          cachedNormalDeviate = Double.NaN;
60      }
61      
62      /**
63       * Sets the seed of the underyling random number generator using a 
64       * <code>long</code> seed.  Sequences of values generated starting with the
65       * same seeds should be identical.
66       * <p>
67       * Implementations that do not override the default implementation of 
68       * <code>nextGaussian</code> should include a call to {@link #clear} in the
69       * implementation of this method.</p>
70       *
71       * @param seed the seed value
72       */
73      public abstract void setSeed(long seed);  
74  
75      /**
76       * Generates random bytes and places them into a user-supplied 
77       * byte array.  The number of random bytes produced is equal to 
78       * the length of the byte array.
79       * <p>
80       * The default implementation fills the array with bytes extracted from
81       * random integers generated using {@link #nextInt}.</p>
82       * 
83       * @param bytes the non-null byte array in which to put the 
84       * random bytes
85       */
86      public void nextBytes(byte[] bytes) {
87          int bytesOut = 0;
88          while (bytesOut < bytes.length) {
89            int randInt = nextInt();
90            for (int i = 0; i < 3; i++) {
91                if ( i > 0) {
92                    randInt = randInt >> 8;
93                }
94                bytes[bytesOut++] = (byte) randInt;
95                if (bytesOut == bytes.length) {
96                    return;
97                }
98            }
99          }
100     }
101 
102      /**
103      * Returns the next pseudorandom, uniformly distributed <code>int</code>
104      * value from this random number generator's sequence.  
105      * All 2<font size="-1"><sup>32</sup></font> possible <tt>int</tt> values
106      * should be produced with  (approximately) equal probability. 
107      * <p>
108      * The default implementation provided here returns 
109      * <pre>
110      * <code>(int) (nextDouble() * Integer.MAX_VALUE)</code>
111      * </pre></p>
112      *
113      * @return the next pseudorandom, uniformly distributed <code>int</code>
114      *  value from this random number generator's sequence
115      */
116     public int nextInt() {
117         return (int) (nextDouble() * Integer.MAX_VALUE);
118     }
119 
120     /**
121      * Returns a pseudorandom, uniformly distributed <tt>int</tt> value
122      * between 0 (inclusive) and the specified value (exclusive), drawn from
123      * this random number generator's sequence. 
124      * <p>  
125      * The default implementation returns 
126      * <pre>
127      * <code>(int) (nextDouble() * n</code>
128      * </pre></p>
129      *
130      * @param n the bound on the random number to be returned.  Must be
131      * positive.
132      * @return  a pseudorandom, uniformly distributed <tt>int</tt>
133      * value between 0 (inclusive) and n (exclusive).
134      * @throws IllegalArgumentException if n is not positive.
135      */
136     public int nextInt(int n) {
137         if (n <= 0 ) {
138             throw new IllegalArgumentException("upper bound must be positive");
139         }
140         int result = (int) (nextDouble() * n);
141         return result < n ? result : n - 1;
142     }
143 
144      /**
145      * Returns the next pseudorandom, uniformly distributed <code>long</code>
146      * value from this random number generator's sequence.  All 
147      * 2<font size="-1"><sup>64</sup></font> possible <tt>long</tt> values 
148      * should be produced with (approximately) equal probability. 
149      * <p>  
150      * The default implementation returns 
151      * <pre>
152      * <code>(long) (nextDouble() * Long.MAX_VALUE)</code>
153      * </pre></p>
154      *
155      * @return  the next pseudorandom, uniformly distributed <code>long</code>
156      *value from this random number generator's sequence
157      */
158     public long nextLong() {
159         return (long) (nextDouble() * Long.MAX_VALUE);
160     }
161 
162     /**
163      * Returns the next pseudorandom, uniformly distributed
164      * <code>boolean</code> value from this random number generator's
165      * sequence.  
166      * <p>  
167      * The default implementation returns 
168      * <pre>
169      * <code>nextDouble() <= 0.5</code>
170      * </pre></p>
171      * 
172      * @return  the next pseudorandom, uniformly distributed
173      * <code>boolean</code> value from this random number generator's
174      * sequence
175      */
176     public boolean nextBoolean() {
177         return nextDouble() <= 0.5;
178     }
179 
180      /**
181      * Returns the next pseudorandom, uniformly distributed <code>float</code>
182      * value between <code>0.0</code> and <code>1.0</code> from this random
183      * number generator's sequence.  
184      * <p>  
185      * The default implementation returns 
186      * <pre>
187      * <code>(float) nextDouble() </code>
188      * </pre></p>
189      *
190      * @return  the next pseudorandom, uniformly distributed <code>float</code>
191      * value between <code>0.0</code> and <code>1.0</code> from this
192      * random number generator's sequence
193      */
194     public float nextFloat() {
195         return (float) nextDouble();
196     }
197 
198     /**
199      * Returns the next pseudorandom, uniformly distributed 
200      * <code>double</code> value between <code>0.0</code> and
201      * <code>1.0</code> from this random number generator's sequence.  
202      * <p>
203      * This method provides the underlying source of random data used by the
204      * other methods.</p>   
205      *
206      * @return  the next pseudorandom, uniformly distributed 
207      *  <code>double</code> value between <code>0.0</code> and
208      *  <code>1.0</code> from this random number generator's sequence
209      */  
210     public abstract double nextDouble();  
211 
212     /**
213      * Returns the next pseudorandom, Gaussian ("normally") distributed
214      * <code>double</code> value with mean <code>0.0</code> and standard
215      * deviation <code>1.0</code> from this random number generator's sequence.
216      * <p>
217      * The default implementation uses the <em>Polar Method</em>
218      * due to G.E.P. Box, M.E. Muller and G. Marsaglia, as described in 
219      * D. Knuth, <u>The Art of Computer Programming</u>, 3.4.1C.</p>
220      * <p>
221      * The algorithm generates a pair of independent random values.  One of
222      * these is cached for reuse, so the full algorithm is not executed on each
223      * activation.  Implementations that do not override this method should
224      * make sure to call {@link #clear} to clear the cached value in the 
225      * implementation of {@link #setSeed(long)}.</p>
226      * 
227      * @return  the next pseudorandom, Gaussian ("normally") distributed
228      * <code>double</code> value with mean <code>0.0</code> and
229      * standard deviation <code>1.0</code> from this random number
230      *  generator's sequence
231      */
232     public double nextGaussian() {
233         if (!Double.isNaN(cachedNormalDeviate)) {
234             double dev = cachedNormalDeviate;
235             cachedNormalDeviate = Double.NaN;
236             return dev;
237         }
238         double v1 = 0;
239         double v2 = 0;
240         double s = 1;
241         while (s >=1 ) { 
242             v1 = 2 * nextDouble() - 1; 
243             v2 = 2 * nextDouble() - 1; 
244             s = v1 * v1 + v2 * v2;
245         }
246         if (s != 0) {
247             s = Math.sqrt(-2 * Math.log(s) / s);   
248         }
249         cachedNormalDeviate = v2 * s;
250         return v1 * s;      
251     }
252 }