001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.rng.core.util;
018
019/**
020 * Utility for creating number types from one or two {@code int} values
021 * or one {@code long} value, or a sequence of bytes.
022 */
023public final class NumberFactory {
024    /**
025     * The multiplier to convert the least significant 24-bits of an {@code int} to a {@code float}.
026     * See {@link #makeFloat(int)}.
027     *
028     * <p>This is equivalent to 1.0f / (1 << 24).
029     */
030    private static final float FLOAT_MULTIPLIER = 0x1.0p-24f;
031    /**
032     * The multiplier to convert the least significant 53-bits of a {@code long} to a {@code double}.
033     * See {@link #makeDouble(long)} and {@link #makeDouble(int, int)}.
034     *
035     * <p>This is equivalent to 1.0 / (1L << 53).
036     */
037    private static final double DOUBLE_MULTIPLIER = 0x1.0p-53d;
038    /** Lowest byte mask. */
039    private static final long LONG_LOWEST_BYTE_MASK = 0xffL;
040    /** Number of bytes in a {@code long}. */
041    private static final int LONG_SIZE = 8;
042    /** Lowest byte mask. */
043    private static final int INT_LOWEST_BYTE_MASK = 0xff;
044    /** Number of bytes in a {@code int}. */
045    private static final int INT_SIZE = 4;
046
047    /**
048     * Class contains only static methods.
049     */
050    private NumberFactory() {}
051
052    /**
053     * Creates a {@code boolean} from an {@code int} value.
054     *
055     * @param v Number.
056     * @return a boolean.
057     *
058     * @deprecated Since version 1.2. Method has become obsolete following
059     * <a href="https://issues.apache.org/jira/browse/RNG-57">RNG-57</a>.
060     */
061    @Deprecated
062    public static boolean makeBoolean(int v) {
063        return v < 0;
064    }
065
066    /**
067     * Creates a {@code boolean} from a {@code long} value.
068     *
069     * @param v Number.
070     * @return a boolean.
071     *
072     * @deprecated Since version 1.2. Method has become obsolete following
073     * <a href="https://issues.apache.org/jira/browse/RNG-57">RNG-57</a>.
074     */
075    @Deprecated
076    public static boolean makeBoolean(long v) {
077        return v < 0;
078    }
079
080    /**
081     * Creates a {@code double} from a {@code long} value.
082     *
083     * @param v Number.
084     * @return a {@code double} value in the interval {@code [0, 1]}.
085     */
086    public static double makeDouble(long v) {
087        // Require the least significant 53-bits so shift the higher bits across
088        return (v >>> 11) * DOUBLE_MULTIPLIER;
089    }
090
091    /**
092     * Creates a {@code double} from two {@code int} values.
093     *
094     * @param v Number (high order bits).
095     * @param w Number (low order bits).
096     * @return a {@code double} value in the interval {@code [0, 1]}.
097     */
098    public static double makeDouble(int v,
099                                    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}