Home | History | Annotate | Download | only in random
      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 import org.apache.commons.math.exception.NotStrictlyPositiveException;
     20 import org.apache.commons.math.util.FastMath;
     21 
     22 /** Base class for random number generators that generates bits streams.
     23 
     24  * @version $Revision: 990655 $ $Date: 2010-08-29 23:49:40 +0200 (dim. 29 aot 2010) $
     25  * @since 2.0
     26 
     27  */
     28 public abstract class BitsStreamGenerator implements RandomGenerator {
     29 
     30     /** Next gaussian. */
     31     private double nextGaussian;
     32 
     33     /** Creates a new random number generator.
     34      */
     35     public BitsStreamGenerator() {
     36         nextGaussian = Double.NaN;
     37     }
     38 
     39     /** {@inheritDoc} */
     40     public abstract void setSeed(int seed);
     41 
     42     /** {@inheritDoc} */
     43     public abstract void setSeed(int[] seed);
     44 
     45     /** {@inheritDoc} */
     46     public abstract void setSeed(long seed);
     47 
     48     /** Generate next pseudorandom number.
     49      * <p>This method is the core generation algorithm. It is used by all the
     50      * public generation methods for the various primitive types {@link
     51      * #nextBoolean()}, {@link #nextBytes(byte[])}, {@link #nextDouble()},
     52      * {@link #nextFloat()}, {@link #nextGaussian()}, {@link #nextInt()},
     53      * {@link #next(int)} and {@link #nextLong()}.</p>
     54      * @param bits number of random bits to produce
     55      * @return random bits generated
     56      */
     57     protected abstract int next(int bits);
     58 
     59     /** {@inheritDoc} */
     60     public boolean nextBoolean() {
     61         return next(1) != 0;
     62     }
     63 
     64     /** {@inheritDoc} */
     65     public void nextBytes(byte[] bytes) {
     66         int i = 0;
     67         final int iEnd = bytes.length - 3;
     68         while (i < iEnd) {
     69             final int random = next(32);
     70             bytes[i]     = (byte) (random & 0xff);
     71             bytes[i + 1] = (byte) ((random >>  8) & 0xff);
     72             bytes[i + 2] = (byte) ((random >> 16) & 0xff);
     73             bytes[i + 3] = (byte) ((random >> 24) & 0xff);
     74             i += 4;
     75         }
     76         int random = next(32);
     77         while (i < bytes.length) {
     78             bytes[i++] = (byte) (random & 0xff);
     79             random     = random >> 8;
     80         }
     81     }
     82 
     83     /** {@inheritDoc} */
     84     public double nextDouble() {
     85         final long high = ((long) next(26)) << 26;
     86         final int  low  = next(26);
     87         return (high | low) * 0x1.0p-52d;
     88     }
     89 
     90     /** {@inheritDoc} */
     91     public float nextFloat() {
     92         return next(23) * 0x1.0p-23f;
     93     }
     94 
     95     /** {@inheritDoc} */
     96     public double nextGaussian() {
     97 
     98         final double random;
     99         if (Double.isNaN(nextGaussian)) {
    100             // generate a new pair of gaussian numbers
    101             final double x = nextDouble();
    102             final double y = nextDouble();
    103             final double alpha = 2 * FastMath.PI * x;
    104             final double r      = FastMath.sqrt(-2 * FastMath.log(y));
    105             random       = r * FastMath.cos(alpha);
    106             nextGaussian = r * FastMath.sin(alpha);
    107         } else {
    108             // use the second element of the pair already generated
    109             random = nextGaussian;
    110             nextGaussian = Double.NaN;
    111         }
    112 
    113         return random;
    114 
    115     }
    116 
    117     /** {@inheritDoc} */
    118     public int nextInt() {
    119         return next(32);
    120     }
    121 
    122     /** {@inheritDoc} */
    123     public int nextInt(int n) throws IllegalArgumentException {
    124 
    125         if (n < 1) {
    126             throw new NotStrictlyPositiveException(n);
    127         }
    128 
    129         // find bit mask for n
    130         int mask = n;
    131         mask |= mask >> 1;
    132         mask |= mask >> 2;
    133         mask |= mask >> 4;
    134         mask |= mask >> 8;
    135         mask |= mask >> 16;
    136 
    137         while (true) {
    138             final int random = next(32) & mask;
    139             if (random < n) {
    140                 return random;
    141             }
    142         }
    143 
    144     }
    145 
    146     /** {@inheritDoc} */
    147     public long nextLong() {
    148         final long high  = ((long) next(32)) << 32;
    149         final long  low  = ((long) next(32)) & 0xffffffffL;
    150         return high | low;
    151     }
    152 
    153 }
    154