LXMSupport.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.source32;

  18. /**
  19.  * Utility support for the LXM family of generators. The LXM family is described
  20.  * in further detail in:
  21.  *
  22.  * <blockquote>Steele and Vigna (2021) LXM: better splittable pseudorandom number generators
  23.  * (and almost as fast). Proceedings of the ACM on Programming Languages, Volume 5,
  24.  * Article 148, pp 1–31.</blockquote>
  25.  *
  26.  * <p>Constants are provided to advance the state of an LCG by a power of 2 in a single
  27.  * multiply operation to support jump operations.
  28.  *
  29.  * @see <a href="https://doi.org/10.1145/3485525">Steele &amp; Vigna (2021) Proc. ACM Programming
  30.  *      Languages 5, 1-31</a>
  31.  * @since 1.5
  32.  */
  33. final class LXMSupport {
  34.     /** 32-bit LCG multiplier. Note: (M % 8) = 5. */
  35.     static final int M32 = 0xadb4a92d;
  36.     /** Jump constant {@code m'} for an advance of the 32-bit LCG by 2^16.
  37.      * Computed as: {@code m' = m^(2^16) (mod 2^32)}. */
  38.     static final int M32P = 0x65640001;
  39.     /** Jump constant precursor for {@code c'} for an advance of the 32-bit LCG by 2^16.
  40.      * Computed as:
  41.      * <pre>
  42.      * product_{i=0}^{15} { M^(2^i) + 1 } (mod 2^32)
  43.      * </pre>
  44.      * <p>The jump is computed for the LCG with an update step of {@code s = m * s + c} as:
  45.      * <pre>
  46.      * s = m' * s + c' * c
  47.      * </pre>
  48.      */
  49.     static final int C32P = 0x046b0000;
  50.     /**
  51.      * The fractional part of the golden ratio, phi, scaled to 32-bits and rounded to odd.
  52.      * <pre>
  53.      * phi = (sqrt(5) - 1) / 2) * 2^32
  54.      * </pre>
  55.      * @see <a href="https://en.wikipedia.org/wiki/Golden_ratio">Golden ratio</a>
  56.      */
  57.     static final int GOLDEN_RATIO_32 = 0x9e3779b9;

  58.     /** No instances. */
  59.     private LXMSupport() {}

  60.     /**
  61.      * Perform a 32-bit mixing function using Doug Lea's 32-bit mix constants and shifts.
  62.      *
  63.      * <p>This is based on the original 32-bit mix function of Austin Appleby's
  64.      * MurmurHash3 modified to use a single mix constant and 16-bit shifts, which may have
  65.      * a performance advantage on some processors.
  66.      *
  67.      * <p>The code was kindly provided by Guy Steele as a printing constraint led to
  68.      * its omission from Steele and Vigna's paper.
  69.      *
  70.      * <p>Note from Guy Steele:
  71.      * <blockquote>
  72.      * The constant 0xd36d884b was chosen by Doug Lea by taking the (two’s-complement)
  73.      * negation of the decimal constant 747796405, which appears in Table 5 of L’Ecuyer’s
  74.      * classic paper “Tables of Linear Congruential Generators of Different Sizes and Good
  75.      * Lattice Structure” (January 1999); the constant in lea64 was chosen in a similar manner.
  76.      * These choices were based on his engineering intuition and then validated by testing.
  77.      * </blockquote>
  78.      *
  79.      * @param x the input value
  80.      * @return the output value
  81.      */
  82.     static int lea32(int x) {
  83.         x = (x ^ (x >>> 16)) * 0xd36d884b;
  84.         x = (x ^ (x >>> 16)) * 0xd36d884b;
  85.         return x ^ (x >>> 16);
  86.     }
  87. }