IntRandomGenerator.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.  *      https://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.  * This is not the original file distributed by the Apache Software Foundation
  19.  * It has been modified by the Hipparchus project
  20.  */

  21. package org.hipparchus.random;

  22. import org.hipparchus.exception.LocalizedCoreFormats;
  23. import org.hipparchus.exception.MathIllegalArgumentException;

  24. /**
  25.  * Base class for all {@code int}-based (32-bit) random generator
  26.  * implementations.
  27.  */
  28. abstract class IntRandomGenerator extends BaseRandomGenerator {

  29.     /** {@inheritDoc} */
  30.     @Override
  31.     public abstract int nextInt();

  32.     /** {@inheritDoc} */
  33.     @Override
  34.     public boolean nextBoolean() {
  35.         return (nextInt() >>> 31) != 0;
  36.     }

  37.     /** {@inheritDoc} */
  38.     @Override
  39.     public double nextDouble() {
  40.         final long high = ((long) (nextInt() >>> 6)) << 26;
  41.         final int low = nextInt() >>> 6;
  42.         return (high | low) * 0x1.0p-52d;
  43.     }

  44.     /** {@inheritDoc} */
  45.     @Override
  46.     public float nextFloat() {
  47.         return (nextInt() >>> 9) * 0x1.0p-23f;
  48.     }

  49.     /** {@inheritDoc} */
  50.     @Override
  51.     public long nextLong() {
  52.         return (((long) nextInt()) << 32) | (nextInt() & 0xffffffffL);
  53.     }

  54.     /** {@inheritDoc} */
  55.     @Override
  56.     public void nextBytes(byte[] bytes) {
  57.         nextBytesFill(bytes, 0, bytes.length);
  58.     }

  59.     /** {@inheritDoc} */
  60.     @Override
  61.     public void nextBytes(byte[] bytes, int start, int len) {
  62.         if (start < 0 ||
  63.             start >= bytes.length) {
  64.             throw new MathIllegalArgumentException(LocalizedCoreFormats.OUT_OF_RANGE_SIMPLE,
  65.                                                    start, 0, bytes.length);
  66.         }
  67.         if (len < 0 ||
  68.             len > bytes.length - start) {
  69.             throw new MathIllegalArgumentException(LocalizedCoreFormats.OUT_OF_RANGE_SIMPLE,
  70.                                                    len, 0, bytes.length - start);
  71.         }

  72.         nextBytesFill(bytes, start, len);
  73.     }

  74.     /**
  75.      * Generates random bytes and places them into a user-supplied array.
  76.      *
  77.      * @see #nextBytes(byte[], int, int)
  78.      *
  79.      * @param bytes the non-null byte array in which to put the random bytes
  80.      * @param offset the starting index for inserting the generated bytes into
  81.      * the array
  82.      * @param len the number of bytes to generate
  83.      * @throws MathIllegalArgumentException if {@code offset < 0} or
  84.      * {@code offset + len >= bytes.length}
  85.      */
  86.     private void nextBytesFill(byte[] bytes, int offset, int len) {
  87.         int index = offset; // Index of first insertion.

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

  91.         // Start filling in the byte array, 4 bytes at a time.
  92.         while (index < indexLoopLimit) {
  93.             final int random = nextInt();
  94.             bytes[index++] = (byte) random;
  95.             bytes[index++] = (byte) (random >>> 8);
  96.             bytes[index++] = (byte) (random >>> 16);
  97.             bytes[index++] = (byte) (random >>> 24);
  98.         }

  99.         final int indexLimit = offset + len; // Index of last insertion + 1.

  100.         // Fill in the remaining bytes.
  101.         if (index < indexLimit) {
  102.             int random = nextInt();
  103.             while (true) {
  104.                 bytes[index++] = (byte) random;
  105.                 if (index < indexLimit) {
  106.                     random >>>= 8;
  107.                 } else {
  108.                     break;
  109.                 }
  110.             }
  111.         }
  112.     }
  113. }