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.math3.random;
18  
19  import java.io.Serializable;
20  
21  import org.apache.commons.math3.exception.NotStrictlyPositiveException;
22  import org.apache.commons.math3.util.FastMath;
23  
24  /** Base class for random number generators that generates bits streams.
25   *
26   * @since 2.0
27   */
28  public abstract class BitsStreamGenerator
29      implements RandomGenerator,
30                 Serializable {
31      /** Serializable version identifier */
32      private static final long serialVersionUID = 20130104L;
33      /** Next gaussian. */
34      private double nextGaussian;
35  
36      /**
37       * Creates a new random number generator.
38       */
39      public BitsStreamGenerator() {
40          nextGaussian = Double.NaN;
41      }
42  
43      /** {@inheritDoc} */
44      public abstract void setSeed(int seed);
45  
46      /** {@inheritDoc} */
47      public abstract void setSeed(int[] seed);
48  
49      /** {@inheritDoc} */
50      public abstract void setSeed(long seed);
51  
52      /** Generate next pseudorandom number.
53       * <p>This method is the core generation algorithm. It is used by all the
54       * public generation methods for the various primitive types {@link
55       * #nextBoolean()}, {@link #nextBytes(byte[])}, {@link #nextDouble()},
56       * {@link #nextFloat()}, {@link #nextGaussian()}, {@link #nextInt()},
57       * {@link #next(int)} and {@link #nextLong()}.</p>
58       * @param bits number of random bits to produce
59       * @return random bits generated
60       */
61      protected abstract int next(int bits);
62  
63      /** {@inheritDoc} */
64      public boolean nextBoolean() {
65          return next(1) != 0;
66      }
67  
68      /** {@inheritDoc} */
69      public void nextBytes(byte[] bytes) {
70          int i = 0;
71          final int iEnd = bytes.length - 3;
72          while (i < iEnd) {
73              final int random = next(32);
74              bytes[i]     = (byte) (random & 0xff);
75              bytes[i + 1] = (byte) ((random >>  8) & 0xff);
76              bytes[i + 2] = (byte) ((random >> 16) & 0xff);
77              bytes[i + 3] = (byte) ((random >> 24) & 0xff);
78              i += 4;
79          }
80          int random = next(32);
81          while (i < bytes.length) {
82              bytes[i++] = (byte) (random & 0xff);
83              random >>= 8;
84          }
85      }
86  
87      /** {@inheritDoc} */
88      public double nextDouble() {
89          final long high = ((long) next(26)) << 26;
90          final int  low  = next(26);
91          return (high | low) * 0x1.0p-52d;
92      }
93  
94      /** {@inheritDoc} */
95      public float nextFloat() {
96          return next(23) * 0x1.0p-23f;
97      }
98  
99      /** {@inheritDoc} */
100     public double nextGaussian() {
101 
102         final double random;
103         if (Double.isNaN(nextGaussian)) {
104             // generate a new pair of gaussian numbers
105             final double x = nextDouble();
106             final double y = nextDouble();
107             final double alpha = 2 * FastMath.PI * x;
108             final double r      = FastMath.sqrt(-2 * FastMath.log(y));
109             random       = r * FastMath.cos(alpha);
110             nextGaussian = r * FastMath.sin(alpha);
111         } else {
112             // use the second element of the pair already generated
113             random = nextGaussian;
114             nextGaussian = Double.NaN;
115         }
116 
117         return random;
118 
119     }
120 
121     /** {@inheritDoc} */
122     public int nextInt() {
123         return next(32);
124     }
125 
126     /**
127      * {@inheritDoc}
128      * <p>This default implementation is copied from Apache Harmony
129      * java.util.Random (r929253).</p>
130      *
131      * <p>Implementation notes: <ul>
132      * <li>If n is a power of 2, this method returns
133      * {@code (int) ((n * (long) next(31)) >> 31)}.</li>
134      *
135      * <li>If n is not a power of 2, what is returned is {@code next(31) % n}
136      * with {@code next(31)} values rejected (i.e. regenerated) until a
137      * value that is larger than the remainder of {@code Integer.MAX_VALUE / n}
138      * is generated. Rejection of this initial segment is necessary to ensure
139      * a uniform distribution.</li></ul></p>
140      */
141     public int nextInt(int n) throws IllegalArgumentException {
142         if (n > 0) {
143             if ((n & -n) == n) {
144                 return (int) ((n * (long) next(31)) >> 31);
145             }
146             int bits;
147             int val;
148             do {
149                 bits = next(31);
150                 val = bits % n;
151             } while (bits - val + (n - 1) < 0);
152             return val;
153         }
154         throw new NotStrictlyPositiveException(n);
155     }
156 
157     /** {@inheritDoc} */
158     public long nextLong() {
159         final long high  = ((long) next(32)) << 32;
160         final long  low  = ((long) next(32)) & 0xffffffffL;
161         return high | low;
162     }
163 
164     /**
165      * Returns a pseudorandom, uniformly distributed {@code long} value
166      * between 0 (inclusive) and the specified value (exclusive), drawn from
167      * this random number generator's sequence.
168      *
169      * @param n the bound on the random number to be returned.  Must be
170      * positive.
171      * @return  a pseudorandom, uniformly distributed {@code long}
172      * value between 0 (inclusive) and n (exclusive).
173      * @throws IllegalArgumentException  if n is not positive.
174      */
175     public long nextLong(long n) throws IllegalArgumentException {
176         if (n > 0) {
177             long bits;
178             long val;
179             do {
180                 bits = ((long) next(31)) << 32;
181                 bits |= ((long) next(32)) & 0xffffffffL;
182                 val  = bits % n;
183             } while (bits - val + (n - 1) < 0);
184             return val;
185         }
186         throw new NotStrictlyPositiveException(n);
187     }
188 
189     /**
190      * Clears the cache used by the default implementation of
191      * {@link #nextGaussian}.
192      */
193     public void clear() {
194         nextGaussian = Double.NaN;
195     }
196 
197 }