NumberFactory.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.  *      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.  * Utility for creating number types from one or two {@code int} values
  20.  * or one {@code long} value, or a sequence of bytes.
  21.  */
  22. public final class NumberFactory {
  23.     /**
  24.      * The multiplier to convert the least significant 24-bits of an {@code int} to a {@code float}.
  25.      * See {@link #makeFloat(int)}.
  26.      *
  27.      * <p>This is equivalent to {@code 1.0f / (1 << 24)}.
  28.      */
  29.     private static final float FLOAT_MULTIPLIER = 0x1.0p-24f;
  30.     /**
  31.      * The multiplier to convert the least significant 53-bits of a {@code long} to a {@code double}.
  32.      * See {@link #makeDouble(long)} and {@link #makeDouble(int, int)}.
  33.      *
  34.      * <p>This is equivalent to {@code 1.0 / (1L << 53)}.
  35.      */
  36.     private static final double DOUBLE_MULTIPLIER = 0x1.0p-53d;
  37.     /** Lowest byte mask. */
  38.     private static final long LONG_LOWEST_BYTE_MASK = 0xffL;
  39.     /** Number of bytes in a {@code long}. */
  40.     private static final int LONG_SIZE = 8;
  41.     /** Lowest byte mask. */
  42.     private static final int INT_LOWEST_BYTE_MASK = 0xff;
  43.     /** Number of bytes in a {@code int}. */
  44.     private static final int INT_SIZE = 4;

  45.     /**
  46.      * Class contains only static methods.
  47.      */
  48.     private NumberFactory() {}

  49.     /**
  50.      * Creates a {@code boolean} from an {@code int} value.
  51.      *
  52.      * @param v Number.
  53.      * @return a boolean.
  54.      *
  55.      * @deprecated Since version 1.2. Method has become obsolete following
  56.      * <a href="https://issues.apache.org/jira/browse/RNG-57">RNG-57</a>.
  57.      */
  58.     @Deprecated
  59.     public static boolean makeBoolean(int v) {
  60.         return v < 0;
  61.     }

  62.     /**
  63.      * Creates a {@code boolean} from a {@code long} value.
  64.      *
  65.      * @param v Number.
  66.      * @return a boolean.
  67.      *
  68.      * @deprecated Since version 1.2. Method has become obsolete following
  69.      * <a href="https://issues.apache.org/jira/browse/RNG-57">RNG-57</a>.
  70.      */
  71.     @Deprecated
  72.     public static boolean makeBoolean(long v) {
  73.         return v < 0;
  74.     }

  75.     /**
  76.      * Creates a {@code double} from a {@code long} value.
  77.      *
  78.      * @param v Number.
  79.      * @return a {@code double} value in the interval {@code [0, 1]}.
  80.      */
  81.     public static double makeDouble(long v) {
  82.         // Require the least significant 53-bits so shift the higher bits across
  83.         return (v >>> 11) * DOUBLE_MULTIPLIER;
  84.     }

  85.     /**
  86.      * Creates a {@code double} from two {@code int} values.
  87.      *
  88.      * @param v Number (high order bits).
  89.      * @param w Number (low order bits).
  90.      * @return a {@code double} value in the interval {@code [0, 1]}.
  91.      */
  92.     public static double makeDouble(int v,
  93.                                     int w) {
  94.         // Require the least significant 53-bits from a long.
  95.         // Join the most significant 26 from v with 27 from w.
  96.         final long high = ((long) (v >>> 6)) << 27;  // 26-bits remain
  97.         final int low = w >>> 5;                     // 27-bits remain
  98.         return (high | low) * DOUBLE_MULTIPLIER;
  99.     }

  100.     /**
  101.      * Creates a {@code float} from an {@code int} value.
  102.      *
  103.      * @param v Number.
  104.      * @return a {@code float} value in the interval {@code [0, 1]}.
  105.      */
  106.     public static float makeFloat(int v) {
  107.         // Require the least significant 24-bits so shift the higher bits across
  108.         return (v >>> 8) * FLOAT_MULTIPLIER;
  109.     }

  110.     /**
  111.      * Creates a {@code long} from two {@code int} values.
  112.      *
  113.      * @param v Number (high order bits).
  114.      * @param w Number (low order bits).
  115.      * @return a {@code long} value.
  116.      */
  117.     public static long makeLong(int v,
  118.                                 int w) {
  119.         return (((long) v) << 32) | (w & 0xffffffffL);
  120.     }

  121.     /**
  122.      * Creates an {@code int} from a {@code long}.
  123.      *
  124.      * @param v Number.
  125.      * @return an {@code int} value made from the "xor" of the
  126.      * {@link #extractHi(long) high order bits} and
  127.      * {@link #extractLo(long) low order bits} of {@code v}.
  128.      *
  129.      * @deprecated Since version 1.2. Method has become obsolete following
  130.      * <a href="https://issues.apache.org/jira/browse/RNG-57">RNG-57</a>.
  131.      */
  132.     @Deprecated
  133.     public static int makeInt(long v) {
  134.         return extractHi(v) ^ extractLo(v);
  135.     }

  136.     /**
  137.      * Creates an {@code int} from a {@code long}, using the high order bits.
  138.      *
  139.      * <p>The returned value is such that if</p>
  140.      * <pre><code>
  141.      *  vL = extractLo(v);
  142.      *  vH = extractHi(v);
  143.      * </code></pre>
  144.      *
  145.      * <p>then {@code v} is equal to {@link #makeLong(int,int) makeLong(vH, vL)}.</p>
  146.      *
  147.      * @param v Number.
  148.      * @return an {@code int} value made from the most significant bits
  149.      * of {@code v}.
  150.      */
  151.     public static int extractHi(long v) {
  152.         return (int) (v >>> 32);
  153.     }

  154.     /**
  155.      * Creates an {@code int} from a {@code long}, using the low order bits.
  156.      *
  157.      * <p>The returned value is such that if</p>
  158.      *
  159.      * <pre><code>
  160.      *  vL = extractLo(v);
  161.      *  vH = extractHi(v);
  162.      * </code></pre>
  163.      *
  164.      * <p>then {@code v} is equal to {@link #makeLong(int,int) makeLong(vH, vL)}.</p>
  165.      *
  166.      * @param v Number.
  167.      * @return an {@code int} value made from the least significant bits
  168.      * of {@code v}.
  169.      */
  170.     public static int extractLo(long v) {
  171.         return (int) v;
  172.     }

  173.     /**
  174.      * Splits a {@code long} into 8 bytes.
  175.      *
  176.      * @param v Value.
  177.      * @return the bytes that compose the given value (least-significant
  178.      * byte first).
  179.      */
  180.     public static byte[] makeByteArray(long v) {
  181.         final byte[] b = new byte[LONG_SIZE];
  182.         putLong(v, b, 0);
  183.         return b;
  184.     }

  185.     /**
  186.      * Puts the {@code long} into the buffer starting at the given position.
  187.      * Adds 8 bytes (least-significant first).
  188.      *
  189.      * @param v      Value.
  190.      * @param buffer the buffer.
  191.      * @param index  the index.
  192.      */
  193.     private static void putLong(long v,
  194.                                 byte[] buffer,
  195.                                 int index) {
  196.         buffer[index    ] = (byte) (v         & LONG_LOWEST_BYTE_MASK);
  197.         buffer[index + 1] = (byte)((v >>>  8) & LONG_LOWEST_BYTE_MASK);
  198.         buffer[index + 2] = (byte)((v >>> 16) & LONG_LOWEST_BYTE_MASK);
  199.         buffer[index + 3] = (byte)((v >>> 24) & LONG_LOWEST_BYTE_MASK);
  200.         buffer[index + 4] = (byte)((v >>> 32) & LONG_LOWEST_BYTE_MASK);
  201.         buffer[index + 5] = (byte)((v >>> 40) & LONG_LOWEST_BYTE_MASK);
  202.         buffer[index + 6] = (byte)((v >>> 48) & LONG_LOWEST_BYTE_MASK);
  203.         buffer[index + 7] = (byte) (v >>> 56);
  204.     }

  205.     /**
  206.      * Creates a {@code long} from 8 bytes.
  207.      *
  208.      * @param input Input.
  209.      * @return the value that correspond to the given bytes assuming
  210.      * that the order is in increasing byte significance (i.e. the
  211.      * first byte in the array is the least-significant).
  212.      * @throws IllegalArgumentException if {@code input.length != 8}.
  213.      */
  214.     public static long makeLong(byte[] input) {
  215.         checkSize(LONG_SIZE, input.length);
  216.         return getLong(input, 0);
  217.     }

  218.     /**
  219.      * Gets the {@code long} from the buffer starting at the given position.
  220.      * Uses 8 bytes (least-significant first).
  221.      *
  222.      * @param input the input bytes.
  223.      * @param index the index.
  224.      * @return the value that correspond to the given bytes assuming
  225.      * that the order is in increasing byte significance (i.e. the
  226.      * first byte in the array is the least-significant).
  227.      */
  228.     private static long getLong(byte[] input,
  229.                                 int index) {
  230.         return (input[index    ] & LONG_LOWEST_BYTE_MASK)       |
  231.                (input[index + 1] & LONG_LOWEST_BYTE_MASK) <<  8 |
  232.                (input[index + 2] & LONG_LOWEST_BYTE_MASK) << 16 |
  233.                (input[index + 3] & LONG_LOWEST_BYTE_MASK) << 24 |
  234.                (input[index + 4] & LONG_LOWEST_BYTE_MASK) << 32 |
  235.                (input[index + 5] & LONG_LOWEST_BYTE_MASK) << 40 |
  236.                (input[index + 6] & LONG_LOWEST_BYTE_MASK) << 48 |
  237.                (input[index + 7] & LONG_LOWEST_BYTE_MASK) << 56;
  238.     }

  239.     /**
  240.      * Splits an array of {@code long} values into a sequence of bytes.
  241.      * This method calls {@link #makeByteArray(long)} for each element of
  242.      * the {@code input}.
  243.      *
  244.      * @param input Input.
  245.      * @return an array of bytes.
  246.      */
  247.     public static byte[] makeByteArray(long[] input) {
  248.         final int size = input.length * LONG_SIZE;
  249.         final byte[] b = new byte[size];

  250.         for (int i = 0; i < input.length; i++) {
  251.             putLong(input[i], b, i * LONG_SIZE);
  252.         }

  253.         return b;
  254.     }

  255.     /**
  256.      * Creates an array of {@code long} values from a sequence of bytes.
  257.      * This method calls {@link #makeLong(byte[])} for each subsequence
  258.      * of 8 bytes.
  259.      *
  260.      * @param input Input.
  261.      * @return an array of {@code long}.
  262.      * @throws IllegalArgumentException if {@code input.length} is not
  263.      * a multiple of 8.
  264.      */
  265.     public static long[] makeLongArray(byte[] input) {
  266.         final int size = input.length;
  267.         final int num = size / LONG_SIZE;
  268.         checkSize(num * LONG_SIZE, size);

  269.         final long[] output = new long[num];
  270.         for (int i = 0; i < num; i++) {
  271.             output[i] = getLong(input, i * LONG_SIZE);
  272.         }

  273.         return output;
  274.     }

  275.     /**
  276.      * Splits an {@code int} into 4 bytes.
  277.      *
  278.      * @param v Value.
  279.      * @return the bytes that compose the given value (least-significant
  280.      * byte first).
  281.      */
  282.     public static byte[] makeByteArray(int v) {
  283.         final byte[] b = new byte[INT_SIZE];
  284.         putInt(v, b, 0);
  285.         return b;
  286.     }

  287.     /**
  288.      * Puts the {@code int} into the buffer starting at the given position.
  289.      * Adds 4 bytes (least-significant first).
  290.      *
  291.      * @param v      the value.
  292.      * @param buffer the buffer.
  293.      * @param index  the index.
  294.      */
  295.     private static void putInt(int v,
  296.                                byte[] buffer,
  297.                                int index) {
  298.         buffer[index    ] = (byte) (v         & INT_LOWEST_BYTE_MASK);
  299.         buffer[index + 1] = (byte)((v >>>  8) & INT_LOWEST_BYTE_MASK);
  300.         buffer[index + 2] = (byte)((v >>> 16) & INT_LOWEST_BYTE_MASK);
  301.         buffer[index + 3] = (byte) (v >>> 24);
  302.     }
  303.     /**
  304.      * Creates an {@code int} from 4 bytes.
  305.      *
  306.      * @param input Input.
  307.      * @return the value that correspond to the given bytes assuming
  308.      * that the order is in increasing byte significance (i.e. the
  309.      * first byte in the array is the least-significant).
  310.      * @throws IllegalArgumentException if {@code input.length != 4}.
  311.      */
  312.     public static int makeInt(byte[] input) {
  313.         checkSize(INT_SIZE, input.length);
  314.         return getInt(input, 0);
  315.     }

  316.     /**
  317.      * Gets the {@code int} from the buffer starting at the given position.
  318.      * Uses 4 bytes (least-significant first).
  319.      *
  320.      * @param input the input bytes.
  321.      * @param index the index.
  322.      * @return the value that correspond to the given bytes assuming
  323.      * that the order is in increasing byte significance (i.e. the
  324.      * first byte in the array is the least-significant).
  325.      */
  326.     private static int getInt(byte[] input,
  327.                               int index) {
  328.         return (input[index    ] & INT_LOWEST_BYTE_MASK)       |
  329.                (input[index + 1] & INT_LOWEST_BYTE_MASK) <<  8 |
  330.                (input[index + 2] & INT_LOWEST_BYTE_MASK) << 16 |
  331.                (input[index + 3] & INT_LOWEST_BYTE_MASK) << 24;
  332.     }

  333.     /**
  334.      * Splits an array of {@code int} values into a sequence of bytes.
  335.      * This method calls {@link #makeByteArray(int)} for each element of
  336.      * the {@code input}.
  337.      *
  338.      * @param input Input.
  339.      * @return an array of bytes.
  340.      */
  341.     public static byte[] makeByteArray(int[] input) {
  342.         final int size = input.length * INT_SIZE;
  343.         final byte[] b = new byte[size];

  344.         for (int i = 0; i < input.length; i++) {
  345.             putInt(input[i], b, i * INT_SIZE);
  346.         }

  347.         return b;
  348.     }

  349.     /**
  350.      * Creates an array of {@code int} values from a sequence of bytes.
  351.      * This method calls {@link #makeInt(byte[])} for each subsequence
  352.      * of 4 bytes.
  353.      *
  354.      * @param input Input. Length must be a multiple of 4.
  355.      * @return an array of {@code int}.
  356.      * @throws IllegalArgumentException if {@code input.length} is not
  357.      * a multiple of 4.
  358.      */
  359.     public static int[] makeIntArray(byte[] input) {
  360.         final int size = input.length;
  361.         final int num = size / INT_SIZE;
  362.         checkSize(num * INT_SIZE, size);

  363.         final int[] output = new int[num];
  364.         for (int i = 0; i < num; i++) {
  365.             output[i] = getInt(input, i * INT_SIZE);
  366.         }

  367.         return output;
  368.     }

  369.     /**
  370.      * @param expected Expected value.
  371.      * @param actual Actual value.
  372.      * @throws IllegalArgumentException if {@code expected != actual}.
  373.      */
  374.     private static void checkSize(int expected,
  375.                                   int actual) {
  376.         if (expected != actual) {
  377.             throw new IllegalArgumentException("Array size: Expected " + expected +
  378.                                                " but was " + actual);
  379.         }
  380.     }
  381. }