001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018package org.apache.commons.rng.core.source32; 019 020import org.apache.commons.rng.core.util.NumberFactory; 021import org.apache.commons.rng.core.BaseProvider; 022 023/** 024 * Base class for all implementations that provide an {@code int}-based 025 * source randomness. 026 */ 027public abstract class IntProvider 028 extends BaseProvider 029 implements RandomIntSource { 030 031 /** Empty boolean source. This is the location of the sign-bit after 31 right shifts on 032 * the boolean source. */ 033 private static final int EMPTY_BOOL_SOURCE = 1; 034 035 /** 036 * Provides a bit source for booleans. 037 * 038 * <p>A cached value from a call to {@link #next()}. 039 * 040 * <p>Only stores 31-bits when full as 1 bit has already been consumed. 041 * The sign bit is a flag that shifts down so the source eventually equals 1 042 * when all bits are consumed and will trigger a refill. 043 */ 044 private int booleanSource = EMPTY_BOOL_SOURCE; 045 046 /** 047 * Creates a new instance. 048 */ 049 public IntProvider() { 050 super(); 051 } 052 053 /** 054 * Creates a new instance copying the state from the source. 055 * 056 * <p>This provides base functionality to allow a generator to create a copy, for example 057 * for use in the {@link org.apache.commons.rng.JumpableUniformRandomProvider 058 * JumpableUniformRandomProvider} interface. 059 * 060 * @param source Source to copy. 061 * @since 1.3 062 */ 063 protected IntProvider(IntProvider source) { 064 booleanSource = source.booleanSource; 065 } 066 067 /** 068 * Reset the cached state used in the default implementation of {@link #nextBoolean()}. 069 * 070 * <p>This should be used when the state is no longer valid, for example after a jump 071 * performed for the {@link org.apache.commons.rng.JumpableUniformRandomProvider 072 * JumpableUniformRandomProvider} interface.</p> 073 * 074 * @since 1.3 075 */ 076 protected void resetCachedState() { 077 booleanSource = EMPTY_BOOL_SOURCE; 078 } 079 080 /** {@inheritDoc} */ 081 @Override 082 protected byte[] getStateInternal() { 083 return composeStateInternal(NumberFactory.makeByteArray(booleanSource), 084 super.getStateInternal()); 085 } 086 087 /** {@inheritDoc} */ 088 @Override 089 protected void setStateInternal(byte[] s) { 090 final byte[][] c = splitStateInternal(s, Integer.BYTES); 091 booleanSource = NumberFactory.makeInt(c[0]); 092 super.setStateInternal(c[1]); 093 } 094 095 /** {@inheritDoc} */ 096 @Override 097 public int nextInt() { 098 return next(); 099 } 100 101 /** {@inheritDoc} */ 102 @Override 103 public boolean nextBoolean() { 104 int bits = booleanSource; 105 if (bits == 1) { 106 // Refill 107 bits = next(); 108 // Store a refill flag in the sign bit and the unused 31 bits, return lowest bit 109 booleanSource = Integer.MIN_VALUE | (bits >>> 1); 110 return (bits & 0x1) == 1; 111 } 112 // Shift down eventually triggering refill, return current lowest bit 113 booleanSource = bits >>> 1; 114 return (bits & 0x1) == 1; 115 } 116 117 /** {@inheritDoc} */ 118 @Override 119 public double nextDouble() { 120 return NumberFactory.makeDouble(next(), next()); 121 } 122 123 /** {@inheritDoc} */ 124 @Override 125 public long nextLong() { 126 return NumberFactory.makeLong(next(), next()); 127 } 128 129 /** {@inheritDoc} */ 130 @Override 131 public void nextBytes(byte[] bytes) { 132 nextBytesFill(this, bytes, 0, bytes.length); 133 } 134 135 /** {@inheritDoc} */ 136 @Override 137 public void nextBytes(byte[] bytes, 138 int start, 139 int len) { 140 checkFromIndexSize(start, len, bytes.length); 141 nextBytesFill(this, bytes, start, len); 142 } 143 144 /** 145 * Generates random bytes and places them into a user-supplied array. 146 * 147 * <p> 148 * The array is filled with bytes extracted from random {@code int} values. 149 * This implies that the number of random bytes generated may be larger than 150 * the length of the byte array. 151 * </p> 152 * 153 * @param source Source of randomness. 154 * @param bytes Array in which to put the generated bytes. Cannot be null. 155 * @param start Index at which to start inserting the generated bytes. 156 * @param len Number of bytes to insert. 157 */ 158 static void nextBytesFill(RandomIntSource source, 159 byte[] bytes, 160 int start, 161 int len) { 162 int index = start; // Index of first insertion. 163 164 // Index of first insertion plus multiple of 4 part of length 165 // (i.e. length with 2 least significant bits unset). 166 final int indexLoopLimit = index + (len & 0x7ffffffc); 167 168 // Start filling in the byte array, 4 bytes at a time. 169 while (index < indexLoopLimit) { 170 final int random = source.next(); 171 bytes[index++] = (byte) random; 172 bytes[index++] = (byte) (random >>> 8); 173 bytes[index++] = (byte) (random >>> 16); 174 bytes[index++] = (byte) (random >>> 24); 175 } 176 177 final int indexLimit = start + len; // Index of last insertion + 1. 178 179 // Fill in the remaining bytes. 180 if (index < indexLimit) { 181 int random = source.next(); 182 while (true) { 183 bytes[index++] = (byte) random; 184 if (index < indexLimit) { 185 random >>>= 8; 186 } else { 187 break; 188 } 189 } 190 } 191 } 192 193 /** 194 * Checks if the sub-range from fromIndex (inclusive) to fromIndex + size (exclusive) is 195 * within the bounds of range from 0 (inclusive) to length (exclusive). 196 * 197 * <p>This function provides the functionality of 198 * {@code java.utils.Objects.checkFromIndexSize} introduced in JDK 9. The 199 * <a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Objects.html#checkFromIndexSize(int,int,int)">Objects</a> 200 * javadoc has been reproduced for reference. 201 * 202 * <p>The sub-range is defined to be out of bounds if any of the following inequalities 203 * is true: 204 * <ul> 205 * <li>{@code fromIndex < 0} 206 * <li>{@code size < 0} 207 * <li>{@code fromIndex + size > length}, taking into account integer overflow 208 * <li>{@code length < 0}, which is implied from the former inequalities 209 * </ul> 210 * 211 * @param fromIndex the lower-bound (inclusive) of the sub-interval 212 * @param size the size of the sub-range 213 * @param length the upper-bound (exclusive) of the range 214 * @return the fromIndex 215 * @throws IndexOutOfBoundsException if the sub-range is out of bounds 216 */ 217 private static int checkFromIndexSize(int fromIndex, int size, int length) { 218 // check for any negatives, 219 // or overflow safe length check given the values are all positive 220 // remaining = length - fromIndex 221 if ((fromIndex | size | length) < 0 || size > length - fromIndex) { 222 throw new IndexOutOfBoundsException( 223 // Note: %<d is 'relative indexing' to re-use the last argument 224 String.format("Range [%d, %<d + %d) out of bounds for length %d", 225 fromIndex, size, length)); 226 } 227 return fromIndex; 228 } 229}