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 * http://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 package org.apache.commons.rng.core.util;
18
19 /**
20 * Utility for creating number types from one or two {@code int} values
21 * or one {@code long} value, or a sequence of bytes.
22 */
23 public final class NumberFactory {
24 /**
25 * The multiplier to convert the least significant 24-bits of an {@code int} to a {@code float}.
26 * See {@link #makeFloat(int)}.
27 *
28 * <p>This is equivalent to {@code 1.0f / (1 << 24)}.
29 */
30 private static final float FLOAT_MULTIPLIER = 0x1.0p-24f;
31 /**
32 * The multiplier to convert the least significant 53-bits of a {@code long} to a {@code double}.
33 * See {@link #makeDouble(long)} and {@link #makeDouble(int, int)}.
34 *
35 * <p>This is equivalent to {@code 1.0 / (1L << 53)}.
36 */
37 private static final double DOUBLE_MULTIPLIER = 0x1.0p-53d;
38 /** Lowest byte mask. */
39 private static final long LONG_LOWEST_BYTE_MASK = 0xffL;
40 /** Number of bytes in a {@code long}. */
41 private static final int LONG_SIZE = 8;
42 /** Lowest byte mask. */
43 private static final int INT_LOWEST_BYTE_MASK = 0xff;
44 /** Number of bytes in a {@code int}. */
45 private static final int INT_SIZE = 4;
46
47 /**
48 * Class contains only static methods.
49 */
50 private NumberFactory() {}
51
52 /**
53 * Creates a {@code boolean} from an {@code int} value.
54 *
55 * @param v Number.
56 * @return a boolean.
57 *
58 * @deprecated Since version 1.2. Method has become obsolete following
59 * <a href="https://issues.apache.org/jira/browse/RNG-57">RNG-57</a>.
60 */
61 @Deprecated
62 public static boolean makeBoolean(int v) {
63 return v < 0;
64 }
65
66 /**
67 * Creates a {@code boolean} from a {@code long} value.
68 *
69 * @param v Number.
70 * @return a boolean.
71 *
72 * @deprecated Since version 1.2. Method has become obsolete following
73 * <a href="https://issues.apache.org/jira/browse/RNG-57">RNG-57</a>.
74 */
75 @Deprecated
76 public static boolean makeBoolean(long v) {
77 return v < 0;
78 }
79
80 /**
81 * Creates a {@code double} from a {@code long} value.
82 *
83 * @param v Number.
84 * @return a {@code double} value in the interval {@code [0, 1]}.
85 */
86 public static double makeDouble(long v) {
87 // Require the least significant 53-bits so shift the higher bits across
88 return (v >>> 11) * DOUBLE_MULTIPLIER;
89 }
90
91 /**
92 * Creates a {@code double} from two {@code int} values.
93 *
94 * @param v Number (high order bits).
95 * @param w Number (low order bits).
96 * @return a {@code double} value in the interval {@code [0, 1]}.
97 */
98 public static double makeDouble(int v,
99 int w) {
100 // Require the least significant 53-bits from a long.
101 // Join the most significant 26 from v with 27 from w.
102 final long high = ((long) (v >>> 6)) << 27; // 26-bits remain
103 final int low = w >>> 5; // 27-bits remain
104 return (high | low) * DOUBLE_MULTIPLIER;
105 }
106
107 /**
108 * Creates a {@code float} from an {@code int} value.
109 *
110 * @param v Number.
111 * @return a {@code float} value in the interval {@code [0, 1]}.
112 */
113 public static float makeFloat(int v) {
114 // Require the least significant 24-bits so shift the higher bits across
115 return (v >>> 8) * FLOAT_MULTIPLIER;
116 }
117
118 /**
119 * Creates a {@code long} from two {@code int} values.
120 *
121 * @param v Number (high order bits).
122 * @param w Number (low order bits).
123 * @return a {@code long} value.
124 */
125 public static long makeLong(int v,
126 int w) {
127 return (((long) v) << 32) | (w & 0xffffffffL);
128 }
129
130 /**
131 * Creates an {@code int} from a {@code long}.
132 *
133 * @param v Number.
134 * @return an {@code int} value made from the "xor" of the
135 * {@link #extractHi(long) high order bits} and
136 * {@link #extractLo(long) low order bits} of {@code v}.
137 *
138 * @deprecated Since version 1.2. Method has become obsolete following
139 * <a href="https://issues.apache.org/jira/browse/RNG-57">RNG-57</a>.
140 */
141 @Deprecated
142 public static int makeInt(long v) {
143 return extractHi(v) ^ extractLo(v);
144 }
145
146 /**
147 * Creates an {@code int} from a {@code long}, using the high order bits.
148 *
149 * <p>The returned value is such that if</p>
150 * <pre><code>
151 * vL = extractLo(v);
152 * vH = extractHi(v);
153 * </code></pre>
154 *
155 * <p>then {@code v} is equal to {@link #makeLong(int,int) makeLong(vH, vL)}.</p>
156 *
157 * @param v Number.
158 * @return an {@code int} value made from the most significant bits
159 * of {@code v}.
160 */
161 public static int extractHi(long v) {
162 return (int) (v >>> 32);
163 }
164
165 /**
166 * Creates an {@code int} from a {@code long}, using the low order bits.
167 *
168 * <p>The returned value is such that if</p>
169 *
170 * <pre><code>
171 * vL = extractLo(v);
172 * vH = extractHi(v);
173 * </code></pre>
174 *
175 * <p>then {@code v} is equal to {@link #makeLong(int,int) makeLong(vH, vL)}.</p>
176 *
177 * @param v Number.
178 * @return an {@code int} value made from the least significant bits
179 * of {@code v}.
180 */
181 public static int extractLo(long v) {
182 return (int) v;
183 }
184
185 /**
186 * Splits a {@code long} into 8 bytes.
187 *
188 * @param v Value.
189 * @return the bytes that compose the given value (least-significant
190 * byte first).
191 */
192 public static byte[] makeByteArray(long v) {
193 final byte[] b = new byte[LONG_SIZE];
194 putLong(v, b, 0);
195 return b;
196 }
197
198 /**
199 * Puts the {@code long} into the buffer starting at the given position.
200 * Adds 8 bytes (least-significant first).
201 *
202 * @param v Value.
203 * @param buffer the buffer.
204 * @param index the index.
205 */
206 private static void putLong(long v,
207 byte[] buffer,
208 int index) {
209 buffer[index ] = (byte) (v & LONG_LOWEST_BYTE_MASK);
210 buffer[index + 1] = (byte)((v >>> 8) & LONG_LOWEST_BYTE_MASK);
211 buffer[index + 2] = (byte)((v >>> 16) & LONG_LOWEST_BYTE_MASK);
212 buffer[index + 3] = (byte)((v >>> 24) & LONG_LOWEST_BYTE_MASK);
213 buffer[index + 4] = (byte)((v >>> 32) & LONG_LOWEST_BYTE_MASK);
214 buffer[index + 5] = (byte)((v >>> 40) & LONG_LOWEST_BYTE_MASK);
215 buffer[index + 6] = (byte)((v >>> 48) & LONG_LOWEST_BYTE_MASK);
216 buffer[index + 7] = (byte) (v >>> 56);
217 }
218
219 /**
220 * Creates a {@code long} from 8 bytes.
221 *
222 * @param input Input.
223 * @return the value that correspond to the given bytes assuming
224 * that the order is in increasing byte significance (i.e. the
225 * first byte in the array is the least-significant).
226 * @throws IllegalArgumentException if {@code input.length != 8}.
227 */
228 public static long makeLong(byte[] input) {
229 checkSize(LONG_SIZE, input.length);
230 return getLong(input, 0);
231 }
232
233 /**
234 * Gets the {@code long} from the buffer starting at the given position.
235 * Uses 8 bytes (least-significant first).
236 *
237 * @param input the input bytes.
238 * @param index the index.
239 * @return the value that correspond to the given bytes assuming
240 * that the order is in increasing byte significance (i.e. the
241 * first byte in the array is the least-significant).
242 */
243 private static long getLong(byte[] input,
244 int index) {
245 return (input[index ] & LONG_LOWEST_BYTE_MASK) |
246 (input[index + 1] & LONG_LOWEST_BYTE_MASK) << 8 |
247 (input[index + 2] & LONG_LOWEST_BYTE_MASK) << 16 |
248 (input[index + 3] & LONG_LOWEST_BYTE_MASK) << 24 |
249 (input[index + 4] & LONG_LOWEST_BYTE_MASK) << 32 |
250 (input[index + 5] & LONG_LOWEST_BYTE_MASK) << 40 |
251 (input[index + 6] & LONG_LOWEST_BYTE_MASK) << 48 |
252 (input[index + 7] & LONG_LOWEST_BYTE_MASK) << 56;
253 }
254
255 /**
256 * Splits an array of {@code long} values into a sequence of bytes.
257 * This method calls {@link #makeByteArray(long)} for each element of
258 * the {@code input}.
259 *
260 * @param input Input.
261 * @return an array of bytes.
262 */
263 public static byte[] makeByteArray(long[] input) {
264 final int size = input.length * LONG_SIZE;
265 final byte[] b = new byte[size];
266
267 for (int i = 0; i < input.length; i++) {
268 putLong(input[i], b, i * LONG_SIZE);
269 }
270
271 return b;
272 }
273
274 /**
275 * Creates an array of {@code long} values from a sequence of bytes.
276 * This method calls {@link #makeLong(byte[])} for each subsequence
277 * of 8 bytes.
278 *
279 * @param input Input.
280 * @return an array of {@code long}.
281 * @throws IllegalArgumentException if {@code input.length} is not
282 * a multiple of 8.
283 */
284 public static long[] makeLongArray(byte[] input) {
285 final int size = input.length;
286 final int num = size / LONG_SIZE;
287 checkSize(num * LONG_SIZE, size);
288
289 final long[] output = new long[num];
290 for (int i = 0; i < num; i++) {
291 output[i] = getLong(input, i * LONG_SIZE);
292 }
293
294 return output;
295 }
296
297 /**
298 * Splits an {@code int} into 4 bytes.
299 *
300 * @param v Value.
301 * @return the bytes that compose the given value (least-significant
302 * byte first).
303 */
304 public static byte[] makeByteArray(int v) {
305 final byte[] b = new byte[INT_SIZE];
306 putInt(v, b, 0);
307 return b;
308 }
309
310 /**
311 * Puts the {@code int} into the buffer starting at the given position.
312 * Adds 4 bytes (least-significant first).
313 *
314 * @param v the value.
315 * @param buffer the buffer.
316 * @param index the index.
317 */
318 private static void putInt(int v,
319 byte[] buffer,
320 int index) {
321 buffer[index ] = (byte) (v & INT_LOWEST_BYTE_MASK);
322 buffer[index + 1] = (byte)((v >>> 8) & INT_LOWEST_BYTE_MASK);
323 buffer[index + 2] = (byte)((v >>> 16) & INT_LOWEST_BYTE_MASK);
324 buffer[index + 3] = (byte) (v >>> 24);
325 }
326 /**
327 * Creates an {@code int} from 4 bytes.
328 *
329 * @param input Input.
330 * @return the value that correspond to the given bytes assuming
331 * that the order is in increasing byte significance (i.e. the
332 * first byte in the array is the least-significant).
333 * @throws IllegalArgumentException if {@code input.length != 4}.
334 */
335 public static int makeInt(byte[] input) {
336 checkSize(INT_SIZE, input.length);
337 return getInt(input, 0);
338 }
339
340 /**
341 * Gets the {@code int} from the buffer starting at the given position.
342 * Uses 4 bytes (least-significant first).
343 *
344 * @param input the input bytes.
345 * @param index the index.
346 * @return the value that correspond to the given bytes assuming
347 * that the order is in increasing byte significance (i.e. the
348 * first byte in the array is the least-significant).
349 */
350 private static int getInt(byte[] input,
351 int index) {
352 return (input[index ] & INT_LOWEST_BYTE_MASK) |
353 (input[index + 1] & INT_LOWEST_BYTE_MASK) << 8 |
354 (input[index + 2] & INT_LOWEST_BYTE_MASK) << 16 |
355 (input[index + 3] & INT_LOWEST_BYTE_MASK) << 24;
356 }
357
358 /**
359 * Splits an array of {@code int} values into a sequence of bytes.
360 * This method calls {@link #makeByteArray(int)} for each element of
361 * the {@code input}.
362 *
363 * @param input Input.
364 * @return an array of bytes.
365 */
366 public static byte[] makeByteArray(int[] input) {
367 final int size = input.length * INT_SIZE;
368 final byte[] b = new byte[size];
369
370 for (int i = 0; i < input.length; i++) {
371 putInt(input[i], b, i * INT_SIZE);
372 }
373
374 return b;
375 }
376
377 /**
378 * Creates an array of {@code int} values from a sequence of bytes.
379 * This method calls {@link #makeInt(byte[])} for each subsequence
380 * of 4 bytes.
381 *
382 * @param input Input. Length must be a multiple of 4.
383 * @return an array of {@code int}.
384 * @throws IllegalArgumentException if {@code input.length} is not
385 * a multiple of 4.
386 */
387 public static int[] makeIntArray(byte[] input) {
388 final int size = input.length;
389 final int num = size / INT_SIZE;
390 checkSize(num * INT_SIZE, size);
391
392 final int[] output = new int[num];
393 for (int i = 0; i < num; i++) {
394 output[i] = getInt(input, i * INT_SIZE);
395 }
396
397 return output;
398 }
399
400 /**
401 * @param expected Expected value.
402 * @param actual Actual value.
403 * @throws IllegalArgumentException if {@code expected != actual}.
404 */
405 private static void checkSize(int expected,
406 int actual) {
407 if (expected != actual) {
408 throw new IllegalArgumentException("Array size: Expected " + expected +
409 " but was " + actual);
410 }
411 }
412 }