View Javadoc
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 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 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 }