IntProvider.java

  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.rng.core.source32;

  18. import org.apache.commons.rng.core.util.NumberFactory;
  19. import org.apache.commons.rng.core.BaseProvider;

  20. /**
  21.  * Base class for all implementations that provide an {@code int}-based
  22.  * source randomness.
  23.  */
  24. public abstract class IntProvider
  25.     extends BaseProvider
  26.     implements RandomIntSource {

  27.     /** Empty boolean source. This is the location of the sign-bit after 31 right shifts on
  28.      * the boolean source. */
  29.     private static final int EMPTY_BOOL_SOURCE = 1;

  30.     /**
  31.      * Provides a bit source for booleans.
  32.      *
  33.      * <p>A cached value from a call to {@link #next()}.
  34.      *
  35.      * <p>Only stores 31-bits when full as 1 bit has already been consumed.
  36.      * The sign bit is a flag that shifts down so the source eventually equals 1
  37.      * when all bits are consumed and will trigger a refill.
  38.      */
  39.     private int booleanSource = EMPTY_BOOL_SOURCE;

  40.     /**
  41.      * Creates a new instance.
  42.      */
  43.     public IntProvider() {
  44.         super();
  45.     }

  46.     /**
  47.      * Creates a new instance copying the state from the source.
  48.      *
  49.      * <p>This provides base functionality to allow a generator to create a copy, for example
  50.      * for use in the {@link org.apache.commons.rng.JumpableUniformRandomProvider
  51.      * JumpableUniformRandomProvider} interface.
  52.      *
  53.      * @param source Source to copy.
  54.      * @since 1.3
  55.      */
  56.     protected IntProvider(IntProvider source) {
  57.         booleanSource = source.booleanSource;
  58.     }

  59.     /**
  60.      * Reset the cached state used in the default implementation of {@link #nextBoolean()}.
  61.      *
  62.      * <p>This should be used when the state is no longer valid, for example after a jump
  63.      * performed for the {@link org.apache.commons.rng.JumpableUniformRandomProvider
  64.      * JumpableUniformRandomProvider} interface.</p>
  65.      *
  66.      * @since 1.3
  67.      */
  68.     protected void resetCachedState() {
  69.         booleanSource = EMPTY_BOOL_SOURCE;
  70.     }

  71.     /** {@inheritDoc} */
  72.     @Override
  73.     protected byte[] getStateInternal() {
  74.         return composeStateInternal(NumberFactory.makeByteArray(booleanSource),
  75.                                     super.getStateInternal());
  76.     }

  77.     /** {@inheritDoc} */
  78.     @Override
  79.     protected void setStateInternal(byte[] s) {
  80.         final byte[][] c = splitStateInternal(s, Integer.BYTES);
  81.         booleanSource = NumberFactory.makeInt(c[0]);
  82.         super.setStateInternal(c[1]);
  83.     }

  84.     /** {@inheritDoc} */
  85.     @Override
  86.     public int nextInt() {
  87.         return next();
  88.     }

  89.     /** {@inheritDoc} */
  90.     @Override
  91.     public boolean nextBoolean() {
  92.         int bits = booleanSource;
  93.         if (bits == 1) {
  94.             // Refill
  95.             bits = next();
  96.             // Store a refill flag in the sign bit and the unused 31 bits, return lowest bit
  97.             booleanSource = Integer.MIN_VALUE | (bits >>> 1);
  98.             return (bits & 0x1) == 1;
  99.         }
  100.         // Shift down eventually triggering refill, return current lowest bit
  101.         booleanSource = bits >>> 1;
  102.         return (bits & 0x1) == 1;
  103.     }

  104.     /** {@inheritDoc} */
  105.     @Override
  106.     public double nextDouble() {
  107.         return NumberFactory.makeDouble(next(), next());
  108.     }

  109.     /** {@inheritDoc} */
  110.     @Override
  111.     public long nextLong() {
  112.         return NumberFactory.makeLong(next(), next());
  113.     }

  114.     /** {@inheritDoc} */
  115.     @Override
  116.     public void nextBytes(byte[] bytes) {
  117.         nextBytesFill(this, bytes, 0, bytes.length);
  118.     }

  119.     /** {@inheritDoc} */
  120.     @Override
  121.     public void nextBytes(byte[] bytes,
  122.                           int start,
  123.                           int len) {
  124.         checkFromIndexSize(start, len, bytes.length);
  125.         nextBytesFill(this, bytes, start, len);
  126.     }

  127.     /**
  128.      * Generates random bytes and places them into a user-supplied array.
  129.      *
  130.      * <p>
  131.      * The array is filled with bytes extracted from random {@code int} values.
  132.      * This implies that the number of random bytes generated may be larger than
  133.      * the length of the byte array.
  134.      * </p>
  135.      *
  136.      * @param source Source of randomness.
  137.      * @param bytes Array in which to put the generated bytes. Cannot be null.
  138.      * @param start Index at which to start inserting the generated bytes.
  139.      * @param len Number of bytes to insert.
  140.      */
  141.     static void nextBytesFill(RandomIntSource source,
  142.                               byte[] bytes,
  143.                               int start,
  144.                               int len) {
  145.         int index = start; // Index of first insertion.

  146.         // Index of first insertion plus multiple of 4 part of length
  147.         // (i.e. length with 2 least significant bits unset).
  148.         final int indexLoopLimit = index + (len & 0x7ffffffc);

  149.         // Start filling in the byte array, 4 bytes at a time.
  150.         while (index < indexLoopLimit) {
  151.             final int random = source.next();
  152.             bytes[index++] = (byte) random;
  153.             bytes[index++] = (byte) (random >>> 8);
  154.             bytes[index++] = (byte) (random >>> 16);
  155.             bytes[index++] = (byte) (random >>> 24);
  156.         }

  157.         final int indexLimit = start + len; // Index of last insertion + 1.

  158.         // Fill in the remaining bytes.
  159.         if (index < indexLimit) {
  160.             int random = source.next();
  161.             while (true) {
  162.                 bytes[index++] = (byte) random;
  163.                 if (index < indexLimit) {
  164.                     random >>>= 8;
  165.                 } else {
  166.                     break;
  167.                 }
  168.             }
  169.         }
  170.     }

  171.     /**
  172.      * Checks if the sub-range from fromIndex (inclusive) to fromIndex + size (exclusive) is
  173.      * within the bounds of range from 0 (inclusive) to length (exclusive).
  174.      *
  175.      * <p>This function provides the functionality of
  176.      * {@code java.utils.Objects.checkFromIndexSize} introduced in JDK 9. The
  177.      * <a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Objects.html#checkFromIndexSize(int,int,int)">Objects</a>
  178.      * javadoc has been reproduced for reference.
  179.      *
  180.      * <p>The sub-range is defined to be out of bounds if any of the following inequalities
  181.      * is true:
  182.      * <ul>
  183.      * <li>{@code fromIndex < 0}
  184.      * <li>{@code size < 0}
  185.      * <li>{@code fromIndex + size > length}, taking into account integer overflow
  186.      * <li>{@code length < 0}, which is implied from the former inequalities
  187.      * </ul>
  188.      *
  189.      * @param fromIndex the lower-bound (inclusive) of the sub-interval
  190.      * @param size the size of the sub-range
  191.      * @param length the upper-bound (exclusive) of the range
  192.      * @return the fromIndex
  193.      * @throws IndexOutOfBoundsException if the sub-range is out of bounds
  194.      */
  195.     private static int checkFromIndexSize(int fromIndex, int size, int length) {
  196.         // check for any negatives,
  197.         // or overflow safe length check given the values are all positive
  198.         // remaining = length - fromIndex
  199.         if ((fromIndex | size | length) < 0 || size > length - fromIndex) {
  200.             throw new IndexOutOfBoundsException(
  201.                 // Note: %<d is 'relative indexing' to re-use the last argument
  202.                 String.format("Range [%d, %<d + %d) out of bounds for length %d",
  203.                     fromIndex, size, length));
  204.         }
  205.         return fromIndex;
  206.     }
  207. }