Conversions.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.simple.internal;

  18. /**
  19.  * Performs seed conversions.
  20.  *
  21.  * <p>Note: Legacy converters from version 1.0 use instances of
  22.  * the {@link SeedConverter} interface. Instances are no longer
  23.  * required as no state is used during conversion and converters
  24.  * can use static methods.
  25.  *
  26.  * @since 1.5
  27.  */
  28. final class Conversions {
  29.     /**
  30.      * The fractional part of the golden ratio, phi, scaled to 64-bits and rounded to odd.
  31.      * <pre>
  32.      * phi = (sqrt(5) - 1) / 2) * 2^64
  33.      * </pre>
  34.      * @see <a href="https://en.wikipedia.org/wiki/Golden_ratio">Golden ratio</a>
  35.      */
  36.     private static final long GOLDEN_RATIO = MixFunctions.GOLDEN_RATIO_64;

  37.     /** No instances. */
  38.     private Conversions() {}

  39.     /**
  40.      * Compute the size of an {@code int} array required to hold the specified number of bytes.
  41.      * Allows space for any remaining bytes that do not fit exactly in a 4 byte integer.
  42.      * <pre>
  43.      * n = ceil(size / 4)
  44.      * </pre>
  45.      *
  46.      * @param size the size in bytes (assumed to be positive)
  47.      * @return the size in ints
  48.      */
  49.     static int intSizeFromByteSize(int size) {
  50.         return (size + 3) >>> 2;
  51.     }

  52.     /**
  53.      * Compute the size of an {@code long} array required to hold the specified number of bytes.
  54.      * Allows space for any remaining bytes that do not fit exactly in an 8 byte long.
  55.      * <pre>
  56.      * n = ceil(size / 8)
  57.      * </pre>
  58.      *
  59.      * @param size the size in bytes (assumed to be positive)
  60.      * @return the size in longs
  61.      */
  62.     static int longSizeFromByteSize(int size) {
  63.         return (size + 7) >>> 3;
  64.     }

  65.     /**
  66.      * Compute the size of an {@code int} array required to hold the specified number of longs.
  67.      * Prevents overflow to a negative number when doubling the size.
  68.      * <pre>
  69.      * n = min(size * 2, 2^31 - 1)
  70.      * </pre>
  71.      *
  72.      * @param size the size in longs (assumed to be positive)
  73.      * @return the size in ints
  74.      */
  75.     static int intSizeFromLongSize(int size) {
  76.         // Avoid overflow when doubling the length.
  77.         // If n is negative the signed shift creates a mask with all bits set;
  78.         // otherwise it is zero and n is unchanged after the or operation.
  79.         // The final mask clears the sign bit in the event n did overflow.
  80.         final int n = size << 1;
  81.         return (n | (n >> 31)) & Integer.MAX_VALUE;
  82.     }

  83.     /**
  84.      * Compute the size of an {@code long} array required to hold the specified number of ints.
  85.      * Allows space for an odd int.
  86.      * <pre>
  87.      * n = ceil(size / 2)
  88.      * </pre>
  89.      *
  90.      * @param size the size in ints (assumed to be positive)
  91.      * @return the size in longs
  92.      */
  93.     static int longSizeFromIntSize(int size) {
  94.         return (size + 1) >>> 1;
  95.     }

  96.     /**
  97.      * Creates a {@code long} value from an {@code int}. The conversion
  98.      * is made as if seeding a SplitMix64 RNG and calling nextLong().
  99.      *
  100.      * @param input Input
  101.      * @return a {@code long}.
  102.      */
  103.     static long int2Long(int input) {
  104.         return MixFunctions.stafford13(input + GOLDEN_RATIO);
  105.     }

  106.     /**
  107.      * Creates an {@code int[]} value from an {@code int}. The conversion
  108.      * is made as if seeding a SplitMix64 RNG and calling nextLong() to
  109.      * generate the sequence and filling the ints
  110.      * in little-endian order (least significant byte first).
  111.      *
  112.      * @param input Input
  113.      * @param length Array length
  114.      * @return an {@code int[]}.
  115.      */
  116.     static int[] int2IntArray(int input, int length) {
  117.         return long2IntArray(input, length);
  118.     }

  119.     /**
  120.      * Creates a {@code long[]} value from an {@code int}. The conversion
  121.      * is made as if seeding a SplitMix64 RNG and calling nextLong() to
  122.      * generate the sequence.
  123.      *
  124.      * @param input Input
  125.      * @param length Array length
  126.      * @return a {@code long[]}.
  127.      */
  128.     static long[] int2LongArray(int input, int length) {
  129.         return long2LongArray(input, length);
  130.     }

  131.     /**
  132.      * Creates an {@code int} value from a {@code long}. The conversion
  133.      * is made by xoring the upper and lower bits.
  134.      *
  135.      * @param input Input
  136.      * @return an {@code int}.
  137.      */
  138.     static int long2Int(long input) {
  139.         return (int) input ^ (int) (input >>> 32);
  140.     }

  141.     /**
  142.      * Creates an {@code int[]} value from a {@code long}. The conversion
  143.      * is made as if seeding a SplitMix64 RNG and calling nextLong() to
  144.      * generate the sequence and filling the ints
  145.      * in little-endian order (least significant byte first).
  146.      *
  147.      * <p>A special case is made to avoid an array filled with zeros for
  148.      * the initial 2 positions. It is still possible to create a zero in
  149.      * position 0. However any RNG with an int[] native type is expected to
  150.      * require at least 2 int values.
  151.      *
  152.      * @param input Input
  153.      * @param length Array length
  154.      * @return an {@code int[]}.
  155.      */
  156.     static int[] long2IntArray(long input, int length) {
  157.         // Special case to avoid creating a zero-filled array of length 2.
  158.         long v = input == -GOLDEN_RATIO ? ~input : input;
  159.         final int[] output = new int[length];
  160.         // Process pairs
  161.         final int n = length & ~0x1;
  162.         for (int i = 0; i < n; i += 2) {
  163.             v += GOLDEN_RATIO;
  164.             final long x = MixFunctions.stafford13(v);
  165.             output[i] = (int) x;
  166.             output[i + 1] = (int) (x >>> 32);
  167.         }
  168.         // Final value
  169.         if (n < length) {
  170.             output[n] = (int) MixFunctions.stafford13(v + GOLDEN_RATIO);
  171.         }
  172.         return output;
  173.     }

  174.     /**
  175.      * Creates a {@code long[]} value from a {@code long}. The conversion
  176.      * is made as if seeding a SplitMix64 RNG and calling nextLong() to
  177.      * generate the sequence.
  178.      *
  179.      * @param input Input
  180.      * @param length Array length
  181.      * @return a {@code long}.
  182.      */
  183.     static long[] long2LongArray(long input, int length) {
  184.         long v = input;
  185.         final long[] output = new long[length];
  186.         for (int i = 0; i < length; i++) {
  187.             v += GOLDEN_RATIO;
  188.             output[i] = MixFunctions.stafford13(v);
  189.         }
  190.         return output;
  191.     }

  192.     /**
  193.      * Creates an {@code int} value from a sequence of ints. The conversion
  194.      * is made by combining all the longs with a xor operation.
  195.      *
  196.      * @param input Input bytes
  197.      * @return an {@code int}.
  198.      */
  199.     static int intArray2Int(int[] input) {
  200.         int output = 0;
  201.         for (final int i : input) {
  202.             output ^= i;
  203.         }
  204.         return output;
  205.     }

  206.     /**
  207.      * Creates a {@code long} value from a sequence of ints. The conversion
  208.      * is made as if converting to a {@code long[]} array by filling the longs
  209.      * in little-endian order (least significant byte first), then combining
  210.      * all the longs with a xor operation.
  211.      *
  212.      * @param input Input bytes
  213.      * @return a {@code long}.
  214.      */
  215.     static long intArray2Long(int[] input) {
  216.         long output = 0;

  217.         final int n = input.length;
  218.         // xor in the bits to a long in little-endian order
  219.         for (int i = 0; i < n; i++) {
  220.             // i              = int index
  221.             // i >> 1         = long index
  222.             // i & 0x1        = int number in the long  [0, 1]
  223.             // (i & 0x1) << 5 = little-endian byte shift to the long {0, 32}
  224.             output ^= (input[i] & 0xffffffffL) << ((i & 0x1) << 5);
  225.         }

  226.         return output;
  227.     }

  228.     /**
  229.      * Creates a {@code long[]} value from a sequence of ints. The longs are
  230.      * filled in little-endian order (least significant byte first).
  231.      *
  232.      * @param input Input ints
  233.      * @param length Output array length
  234.      * @return a {@code long[]}.
  235.      */
  236.     static long[] intArray2LongArray(int[] input, int length) {
  237.         final long[] output = new long[length];

  238.         // Overflow-safe minimum using long
  239.         final int n = (int) Math.min(input.length, length * 2L);
  240.         // Little-endian fill
  241.         for (int i = 0; i < n; i++) {
  242.             // i              = int index
  243.             // i >> 1         = long index
  244.             // i & 0x1        = int number in the long  [0, 1]
  245.             // (i & 0x1) << 5 = little-endian byte shift to the long {0, 32}
  246.             output[i >> 1] |= (input[i] & 0xffffffffL) << ((i & 0x1) << 5);
  247.         }

  248.         return output;
  249.     }

  250.     /**
  251.      * Creates an {@code int} value from a sequence of longs. The conversion
  252.      * is made as if combining all the longs with a xor operation, then folding
  253.      * the long high and low parts using a xor operation.
  254.      *
  255.      * @param input Input longs
  256.      * @return an {@code int}.
  257.      */
  258.     static int longArray2Int(long[] input) {
  259.         return long2Int(longArray2Long(input));
  260.     }

  261.     /**
  262.      * Creates a {@code long} value from a sequence of longs. The conversion
  263.      * is made by combining all the longs with a xor operation.
  264.      *
  265.      * @param input Input longs
  266.      * @return a {@code long}.
  267.      */
  268.     static long longArray2Long(long[] input) {
  269.         long output = 0;
  270.         for (final long i : input) {
  271.             output ^= i;
  272.         }
  273.         return output;
  274.     }

  275.     /**
  276.      * Creates a {@code int[]} value from a sequence of longs. The ints are
  277.      * filled in little-endian order (least significant byte first).
  278.      *
  279.      * @param input Input longs
  280.      * @param length Output array length
  281.      * @return an {@code int[]}.
  282.      */
  283.     static int[] longArray2IntArray(long[] input, int length) {
  284.         final int[] output = new int[length];

  285.         // Overflow-safe minimum using long
  286.         final int n = (int) Math.min(input.length * 2L, length);
  287.         // Little-endian fill
  288.         // Alternate low/high 32-bits from each long
  289.         for (int i = 0; i < n; i++) {
  290.             // i              = int index
  291.             // i >> 1         = long index
  292.             // i & 0x1        = int number in the long  [0, 1]
  293.             // (i & 0x1) << 5 = little-endian long shift to the int {0, 32}
  294.             output[i] = (int)((input[i >> 1]) >>> ((i & 0x1) << 5));
  295.         }

  296.         return output;
  297.     }

  298.     /**
  299.      * Creates an {@code int} value from a sequence of bytes. The conversion
  300.      * is made as if converting to a {@code int[]} array by filling the ints
  301.      * in little-endian order (least significant byte first), then combining
  302.      * all the ints with a xor operation.
  303.      *
  304.      * @param input Input bytes
  305.      * @return an {@code int}.
  306.      */
  307.     static int byteArray2Int(byte[] input) {
  308.         int output = 0;

  309.         final int n = input.length;
  310.         // xor in the bits to an int in little-endian order
  311.         for (int i = 0; i < n; i++) {
  312.             // i              = byte index
  313.             // i >> 2         = integer index
  314.             // i & 0x3        = byte number in the integer  [0, 3]
  315.             // (i & 0x3) << 3 = little-endian byte shift to the integer {0, 8, 16, 24}
  316.             output ^= (input[i] & 0xff) << ((i & 0x3) << 3);
  317.         }

  318.         return output;
  319.     }

  320.     /**
  321.      * Creates an {@code int[]} value from a sequence of bytes. The ints are
  322.      * filled in little-endian order (least significant byte first).
  323.      *
  324.      * @param input Input bytes
  325.      * @param length Output array length
  326.      * @return a {@code int[]}.
  327.      */
  328.     static int[] byteArray2IntArray(byte[] input, int length) {
  329.         final int[] output = new int[length];

  330.         // Overflow-safe minimum using long
  331.         final int n = (int) Math.min(input.length, length * (long) Integer.BYTES);
  332.         // Little-endian fill
  333.         for (int i = 0; i < n; i++) {
  334.             // i              = byte index
  335.             // i >> 2         = integer index
  336.             // i & 0x3        = byte number in the integer  [0, 3]
  337.             // (i & 0x3) << 3 = little-endian byte shift to the integer {0, 8, 16, 24}
  338.             output[i >> 2] |= (input[i] & 0xff) << ((i & 0x3) << 3);
  339.         }

  340.         return output;
  341.     }

  342.     /**
  343.      * Creates a {@code long} value from a sequence of bytes. The conversion
  344.      * is made as if converting to a {@code long[]} array by filling the longs
  345.      * in little-endian order (least significant byte first), then combining
  346.      * all the longs with a xor operation.
  347.      *
  348.      * @param input Input bytes
  349.      * @return a {@code long}.
  350.      */
  351.     static long byteArray2Long(byte[] input) {
  352.         long output = 0;

  353.         final int n = input.length;
  354.         // xor in the bits to a long in little-endian order
  355.         for (int i = 0; i < n; i++) {
  356.             // i              = byte index
  357.             // i >> 3         = long index
  358.             // i & 0x7        = byte number in the long  [0, 7]
  359.             // (i & 0x7) << 3 = little-endian byte shift to the long {0, 8, 16, 24, 32, 36, 40, 48, 56}
  360.             output ^= (input[i] & 0xffL) << ((i & 0x7) << 3);
  361.         }

  362.         return output;
  363.     }

  364.     /**
  365.      * Creates a {@code long[]} value from a sequence of bytes. The longs are
  366.      * filled in little-endian order (least significant byte first).
  367.      *
  368.      * @param input Input bytes
  369.      * @param length Output array length
  370.      * @return a {@code long[]}.
  371.      */
  372.     static long[] byteArray2LongArray(byte[] input, int length) {
  373.         final long[] output = new long[length];

  374.         // Overflow-safe minimum using long
  375.         final int n = (int) Math.min(input.length, length * (long) Long.BYTES);
  376.         // Little-endian fill
  377.         for (int i = 0; i < n; i++) {
  378.             // i              = byte index
  379.             // i >> 3         = long index
  380.             // i & 0x7        = byte number in the long  [0, 7]
  381.             // (i & 0x7) << 3 = little-endian byte shift to the long {0, 8, 16, 24, 32, 36, 40, 48, 56}
  382.             output[i >> 3] |= (input[i] & 0xffL) << ((i & 0x7) << 3);
  383.         }

  384.         return output;
  385.     }
  386. }