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  
18  package org.apache.commons.rng.core.source32;
19  
20  import org.apache.commons.rng.core.util.NumberFactory;
21  import org.apache.commons.rng.core.BaseProvider;
22  
23  /**
24   * Base class for all implementations that provide an {@code int}-based
25   * source randomness.
26   */
27  public abstract class IntProvider
28      extends BaseProvider
29      implements RandomIntSource {
30  
31      /** {@inheritDoc} */
32      @Override
33      public int nextInt() {
34          return next();
35      }
36  
37      /** {@inheritDoc} */
38      @Override
39      public boolean nextBoolean() {
40          return NumberFactory.makeBoolean(nextInt());
41      }
42  
43      /** {@inheritDoc} */
44      @Override
45      public double nextDouble() {
46          return NumberFactory.makeDouble(nextInt(), nextInt());
47      }
48  
49      /** {@inheritDoc} */
50      @Override
51      public float nextFloat() {
52          return NumberFactory.makeFloat(nextInt());
53      }
54  
55      /** {@inheritDoc} */
56      @Override
57      public long nextLong() {
58          return NumberFactory.makeLong(nextInt(), nextInt());
59      }
60  
61      /** {@inheritDoc} */
62      @Override
63      public void nextBytes(byte[] bytes) {
64          nextBytesFill(this, bytes, 0, bytes.length);
65      }
66  
67      /** {@inheritDoc} */
68      @Override
69      public void nextBytes(byte[] bytes,
70                            int start,
71                            int len) {
72          checkIndex(0, bytes.length - 1, start);
73          checkIndex(0, bytes.length - start, len);
74  
75          nextBytesFill(this, bytes, start, len);
76      }
77  
78      /**
79       * Generates random bytes and places them into a user-supplied array.
80       *
81       * <p>
82       * The array is filled with bytes extracted from random {@code int} values.
83       * This implies that the number of random bytes generated may be larger than
84       * the length of the byte array.
85       * </p>
86       *
87       * @param source Source of randomness.
88       * @param bytes Array in which to put the generated bytes. Cannot be null.
89       * @param start Index at which to start inserting the generated bytes.
90       * @param len Number of bytes to insert.
91       */
92      static void nextBytesFill(RandomIntSource source,
93                                byte[] bytes,
94                                int start,
95                                int len) {
96          int index = start; // Index of first insertion.
97  
98          // Index of first insertion plus multiple of 4 part of length
99          // (i.e. length with 2 least significant bits unset).
100         final int indexLoopLimit = index + (len & 0x7ffffffc);
101 
102         // Start filling in the byte array, 4 bytes at a time.
103         while (index < indexLoopLimit) {
104             final int random = source.next();
105             bytes[index++] = (byte) random;
106             bytes[index++] = (byte) (random >>> 8);
107             bytes[index++] = (byte) (random >>> 16);
108             bytes[index++] = (byte) (random >>> 24);
109         }
110 
111         final int indexLimit = start + len; // Index of last insertion + 1.
112 
113         // Fill in the remaining bytes.
114         if (index < indexLimit) {
115             int random = source.next();
116             while (true) {
117                 bytes[index++] = (byte) random;
118                 if (index < indexLimit) {
119                     random >>>= 8;
120                 } else {
121                     break;
122                 }
123             }
124         }
125     }
126 }