IntRandomGenerator.java
/*
* 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
*
* https://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.
*/
/*
* This is not the original file distributed by the Apache Software Foundation
* It has been modified by the Hipparchus project
*/
package org.hipparchus.random;
import org.hipparchus.exception.LocalizedCoreFormats;
import org.hipparchus.exception.MathIllegalArgumentException;
/**
* Base class for all {@code int}-based (32-bit) random generator
* implementations.
*/
abstract class IntRandomGenerator extends BaseRandomGenerator {
/** {@inheritDoc} */
@Override
public abstract int nextInt();
/** {@inheritDoc} */
@Override
public boolean nextBoolean() {
return (nextInt() >>> 31) != 0;
}
/** {@inheritDoc} */
@Override
public double nextDouble() {
final long high = ((long) (nextInt() >>> 6)) << 26;
final int low = nextInt() >>> 6;
return (high | low) * 0x1.0p-52d;
}
/** {@inheritDoc} */
@Override
public float nextFloat() {
return (nextInt() >>> 9) * 0x1.0p-23f;
}
/** {@inheritDoc} */
@Override
public long nextLong() {
return (((long) nextInt()) << 32) | (nextInt() & 0xffffffffL);
}
/** {@inheritDoc} */
@Override
public void nextBytes(byte[] bytes) {
nextBytesFill(bytes, 0, bytes.length);
}
/** {@inheritDoc} */
@Override
public void nextBytes(byte[] bytes, int start, int len) {
if (start < 0 ||
start >= bytes.length) {
throw new MathIllegalArgumentException(LocalizedCoreFormats.OUT_OF_RANGE_SIMPLE,
start, 0, bytes.length);
}
if (len < 0 ||
len > bytes.length - start) {
throw new MathIllegalArgumentException(LocalizedCoreFormats.OUT_OF_RANGE_SIMPLE,
len, 0, bytes.length - start);
}
nextBytesFill(bytes, start, len);
}
/**
* Generates random bytes and places them into a user-supplied array.
*
* @see #nextBytes(byte[], int, int)
*
* @param bytes the non-null byte array in which to put the random bytes
* @param offset the starting index for inserting the generated bytes into
* the array
* @param len the number of bytes to generate
* @throws MathIllegalArgumentException if {@code offset < 0} or
* {@code offset + len >= bytes.length}
*/
private void nextBytesFill(byte[] bytes, int offset, int len) {
int index = offset; // 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 = nextInt();
bytes[index++] = (byte) random;
bytes[index++] = (byte) (random >>> 8);
bytes[index++] = (byte) (random >>> 16);
bytes[index++] = (byte) (random >>> 24);
}
final int indexLimit = offset + len; // Index of last insertion + 1.
// Fill in the remaining bytes.
if (index < indexLimit) {
int random = nextInt();
while (true) {
bytes[index++] = (byte) random;
if (index < indexLimit) {
random >>>= 8;
} else {
break;
}
}
}
}
}