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 /*
19 * This is not the original file distributed by the Apache Software Foundation
20 * It has been modified by the Hipparchus project
21 */
22
23 package org.hipparchus.random;
24
25 import org.hipparchus.exception.LocalizedCoreFormats;
26 import org.hipparchus.exception.MathIllegalArgumentException;
27
28 /**
29 * Base class for all {@code int}-based (32-bit) random generator
30 * implementations.
31 */
32 abstract class IntRandomGenerator extends BaseRandomGenerator {
33
34 /** {@inheritDoc} */
35 @Override
36 public abstract int nextInt();
37
38 /** {@inheritDoc} */
39 @Override
40 public boolean nextBoolean() {
41 return (nextInt() >>> 31) != 0;
42 }
43
44 /** {@inheritDoc} */
45 @Override
46 public double nextDouble() {
47 final long high = ((long) (nextInt() >>> 6)) << 26;
48 final int low = nextInt() >>> 6;
49 return (high | low) * 0x1.0p-52d;
50 }
51
52 /** {@inheritDoc} */
53 @Override
54 public float nextFloat() {
55 return (nextInt() >>> 9) * 0x1.0p-23f;
56 }
57
58 /** {@inheritDoc} */
59 @Override
60 public long nextLong() {
61 return (((long) nextInt()) << 32) | (nextInt() & 0xffffffffL);
62 }
63
64 /** {@inheritDoc} */
65 @Override
66 public void nextBytes(byte[] bytes) {
67 nextBytesFill(bytes, 0, bytes.length);
68 }
69
70 /** {@inheritDoc} */
71 @Override
72 public void nextBytes(byte[] bytes, int start, int len) {
73 if (start < 0 ||
74 start >= bytes.length) {
75 throw new MathIllegalArgumentException(LocalizedCoreFormats.OUT_OF_RANGE_SIMPLE,
76 start, 0, bytes.length);
77 }
78 if (len < 0 ||
79 len > bytes.length - start) {
80 throw new MathIllegalArgumentException(LocalizedCoreFormats.OUT_OF_RANGE_SIMPLE,
81 len, 0, bytes.length - start);
82 }
83
84 nextBytesFill(bytes, start, len);
85 }
86
87 /**
88 * Generates random bytes and places them into a user-supplied array.
89 *
90 * @see #nextBytes(byte[], int, int)
91 *
92 * @param bytes the non-null byte array in which to put the random bytes
93 * @param offset the starting index for inserting the generated bytes into
94 * the array
95 * @param len the number of bytes to generate
96 * @throws MathIllegalArgumentException if {@code offset < 0} or
97 * {@code offset + len >= bytes.length}
98 */
99 private void nextBytesFill(byte[] bytes, int offset, int len) {
100 int index = offset; // Index of first insertion.
101
102 // Index of first insertion plus multiple of 4 part of length
103 // (i.e. length with 2 least significant bits unset).
104 final int indexLoopLimit = index + (len & 0x7ffffffc);
105
106 // Start filling in the byte array, 4 bytes at a time.
107 while (index < indexLoopLimit) {
108 final int random = nextInt();
109 bytes[index++] = (byte) random;
110 bytes[index++] = (byte) (random >>> 8);
111 bytes[index++] = (byte) (random >>> 16);
112 bytes[index++] = (byte) (random >>> 24);
113 }
114
115 final int indexLimit = offset + len; // Index of last insertion + 1.
116
117 // Fill in the remaining bytes.
118 if (index < indexLimit) {
119 int random = nextInt();
120 while (true) {
121 bytes[index++] = (byte) random;
122 if (index < indexLimit) {
123 random >>>= 8;
124 } else {
125 break;
126 }
127 }
128 }
129 }
130 }