| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.commons.rng.core.source32; |
| |
| import org.apache.commons.rng.core.util.NumberFactory; |
| import org.apache.commons.rng.core.BaseProvider; |
| |
| /** |
| * Base class for all implementations that provide an {@code int}-based |
| * source randomness. |
| */ |
| public abstract class IntProvider |
| extends BaseProvider |
| implements RandomIntSource { |
| |
| /** Empty boolean source. This is the location of the sign-bit after 31 right shifts on |
| * the boolean source. */ |
| private static final int EMPTY_BOOL_SOURCE = 1; |
| |
| /** |
| * Provides a bit source for booleans. |
| * |
| * <p>A cached value from a call to {@link #next()}. |
| * |
| * <p>Only stores 31-bits when full as 1 bit has already been consumed. |
| * The sign bit is a flag that shifts down so the source eventually equals 1 |
| * when all bits are consumed and will trigger a refill. |
| */ |
| private int booleanSource = EMPTY_BOOL_SOURCE; |
| |
| /** |
| * Creates a new instance. |
| */ |
| public IntProvider() { |
| super(); |
| } |
| |
| /** |
| * Creates a new instance copying the state from the source. |
| * |
| * <p>This provides base functionality to allow a generator to create a copy, for example |
| * for use in the {@link org.apache.commons.rng.JumpableUniformRandomProvider |
| * JumpableUniformRandomProvider} interface. |
| * |
| * @param source Source to copy. |
| * @since 1.3 |
| */ |
| protected IntProvider(IntProvider source) { |
| booleanSource = source.booleanSource; |
| } |
| |
| /** |
| * Reset the cached state used in the default implementation of {@link #nextBoolean()}. |
| * |
| * <p>This should be used when the state is no longer valid, for example after a jump |
| * performed for the {@link org.apache.commons.rng.JumpableUniformRandomProvider |
| * JumpableUniformRandomProvider} interface.</p> |
| * |
| * @since 1.3 |
| */ |
| protected void resetCachedState() { |
| booleanSource = EMPTY_BOOL_SOURCE; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override |
| protected byte[] getStateInternal() { |
| return composeStateInternal(NumberFactory.makeByteArray(booleanSource), |
| super.getStateInternal()); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override |
| protected void setStateInternal(byte[] s) { |
| final byte[][] c = splitStateInternal(s, Integer.BYTES); |
| booleanSource = NumberFactory.makeInt(c[0]); |
| super.setStateInternal(c[1]); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override |
| public int nextInt() { |
| return next(); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override |
| public boolean nextBoolean() { |
| int bits = booleanSource; |
| if (bits == 1) { |
| // Refill |
| bits = next(); |
| // Store a refill flag in the sign bit and the unused 31 bits, return lowest bit |
| booleanSource = Integer.MIN_VALUE | (bits >>> 1); |
| return (bits & 0x1) == 1; |
| } |
| // Shift down eventually triggering refill, return current lowest bit |
| booleanSource = bits >>> 1; |
| return (bits & 0x1) == 1; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override |
| public double nextDouble() { |
| return NumberFactory.makeDouble(next(), next()); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override |
| public long nextLong() { |
| return NumberFactory.makeLong(next(), next()); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override |
| public void nextBytes(byte[] bytes) { |
| nextBytesFill(this, bytes, 0, bytes.length); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override |
| public void nextBytes(byte[] bytes, |
| int start, |
| int len) { |
| checkFromIndexSize(start, len, bytes.length); |
| nextBytesFill(this, bytes, start, len); |
| } |
| |
| /** |
| * Generates random bytes and places them into a user-supplied array. |
| * |
| * <p> |
| * The array is filled with bytes extracted from random {@code int} values. |
| * This implies that the number of random bytes generated may be larger than |
| * the length of the byte array. |
| * </p> |
| * |
| * @param source Source of randomness. |
| * @param bytes Array in which to put the generated bytes. Cannot be null. |
| * @param start Index at which to start inserting the generated bytes. |
| * @param len Number of bytes to insert. |
| */ |
| static void nextBytesFill(RandomIntSource source, |
| byte[] bytes, |
| int start, |
| int len) { |
| int index = start; // Index of first insertion. |
| |
| // Index of first insertion plus multiple of 4 part of length |
| // (i.e. length with 2 least significant bits unset). |
| final int indexLoopLimit = index + (len & 0x7ffffffc); |
| |
| // Start filling in the byte array, 4 bytes at a time. |
| while (index < indexLoopLimit) { |
| final int random = source.next(); |
| bytes[index++] = (byte) random; |
| bytes[index++] = (byte) (random >>> 8); |
| bytes[index++] = (byte) (random >>> 16); |
| bytes[index++] = (byte) (random >>> 24); |
| } |
| |
| final int indexLimit = start + len; // Index of last insertion + 1. |
| |
| // Fill in the remaining bytes. |
| if (index < indexLimit) { |
| int random = source.next(); |
| while (true) { |
| bytes[index++] = (byte) random; |
| if (index < indexLimit) { |
| random >>>= 8; |
| } else { |
| break; |
| } |
| } |
| } |
| } |
| |
| /** |
| * Checks if the sub-range from fromIndex (inclusive) to fromIndex + size (exclusive) is |
| * within the bounds of range from 0 (inclusive) to length (exclusive). |
| * |
| * <p>This function provides the functionality of |
| * {@code java.utils.Objects.checkFromIndexSize} introduced in JDK 9. The |
| * <a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Objects.html#checkFromIndexSize(int,int,int)">Objects</a> |
| * javadoc has been reproduced for reference. |
| * |
| * <p>The sub-range is defined to be out of bounds if any of the following inequalities |
| * is true: |
| * <ul> |
| * <li>{@code fromIndex < 0} |
| * <li>{@code size < 0} |
| * <li>{@code fromIndex + size > length}, taking into account integer overflow |
| * <li>{@code length < 0}, which is implied from the former inequalities |
| * </ul> |
| * |
| * @param fromIndex the lower-bound (inclusive) of the sub-interval |
| * @param size the size of the sub-range |
| * @param length the upper-bound (exclusive) of the range |
| * @return the fromIndex |
| * @throws IndexOutOfBoundsException if the sub-range is out of bounds |
| */ |
| private static int checkFromIndexSize(int fromIndex, int size, int length) { |
| // check for any negatives, |
| // or overflow safe length check given the values are all positive |
| // remaining = length - fromIndex |
| if ((fromIndex | size | length) < 0 || size > length - fromIndex) { |
| throw new IndexOutOfBoundsException( |
| // Note: %<d is 'relative indexing' to re-use the last argument |
| String.format("Range [%d, %<d + %d) out of bounds for length %d", |
| fromIndex, size, length)); |
| } |
| return fromIndex; |
| } |
| } |