MersenneTwister64.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.source64;

  18. import java.util.Arrays;
  19. import org.apache.commons.rng.core.util.NumberFactory;

  20. /**
  21.  * This class provides the 64-bits version of the originally 32-bits
  22.  * {@link org.apache.commons.rng.core.source32.MersenneTwister
  23.  * Mersenne Twister}.
  24.  *
  25.  * <p>
  26.  * This class is mainly a Java port of
  27.  * <a href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt64.html">
  28.  *  the 2014/2/23 version of the generator
  29.  * </a> written in C by Takuji Nishimura and Makoto Matsumoto.
  30.  * </p>
  31.  *
  32.  * <p>
  33.  * Here is their original copyright:
  34.  * </p>
  35.  *
  36.  * <table style="background-color: #E0E0E0; width: 80%">
  37.  * <caption>Mersenne Twister licence</caption>
  38.  * <tr><td style="padding: 10px">Copyright (C) 2004, Makoto Matsumoto and Takuji Nishimura,
  39.  *     All rights reserved.</td></tr>
  40.  *
  41.  * <tr><td style="padding: 10px">Redistribution and use in source and binary forms, with or without
  42.  * modification, are permitted provided that the following conditions
  43.  * are met:
  44.  * <ol>
  45.  *   <li>Redistributions of source code must retain the above copyright
  46.  *       notice, this list of conditions and the following disclaimer.</li>
  47.  *   <li>Redistributions in binary form must reproduce the above copyright
  48.  *       notice, this list of conditions and the following disclaimer in the
  49.  *       documentation and/or other materials provided with the distribution.</li>
  50.  *   <li>The names of its contributors may not be used to endorse or promote
  51.  *       products derived from this software without specific prior written
  52.  *       permission.</li>
  53.  * </ol></td></tr>
  54.  *
  55.  * <tr><td style="padding: 10px"><strong>THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  56.  * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  57.  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  58.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  59.  * DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
  60.  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
  61.  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  62.  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  63.  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  64.  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  65.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  66.  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  67.  * DAMAGE.</strong></td></tr>
  68.  * </table>
  69.  *
  70.  * @see <a href="https://en.wikipedia.org/wiki/Mersenne_Twister">Mersenne Twister (Wikipedia)</a>
  71.  * @since 1.0
  72.  */
  73. public class MersenneTwister64 extends LongProvider {
  74.     /** Size of the bytes pool. */
  75.     private static final int NN = 312;
  76.     /** Period second parameter. */
  77.     private static final int MM = 156;
  78.     /** X * MATRIX_A for X = {0, 1}. */
  79.     private static final long[] MAG01 = {0x0L, 0xb5026f5aa96619e9L};
  80.     /** Most significant 33 bits. */
  81.     private static final long UM = 0xffffffff80000000L;
  82.     /** Least significant 31 bits. */
  83.     private static final long LM = 0x7fffffffL;
  84.     /** Bytes pool. */
  85.     private final long[] mt = new long[NN];
  86.     /** Current index in the bytes pool. */
  87.     private int mti;

  88.     /**
  89.      * Creates a new random number generator.
  90.      *
  91.      * @param seed Initial seed.
  92.      */
  93.     public MersenneTwister64(long[] seed) {
  94.         setSeedInternal(seed);
  95.     }

  96.     /** {@inheritDoc} */
  97.     @Override
  98.     protected byte[] getStateInternal() {
  99.         final long[] s = Arrays.copyOf(mt, NN + 1);
  100.         s[NN] = mti;

  101.         return composeStateInternal(NumberFactory.makeByteArray(s),
  102.                                     super.getStateInternal());
  103.     }

  104.     /** {@inheritDoc} */
  105.     @Override
  106.     protected void setStateInternal(byte[] s) {
  107.         final byte[][] c = splitStateInternal(s, (NN + 1) * 8);

  108.         final long[] tmp = NumberFactory.makeLongArray(c[0]);
  109.         System.arraycopy(tmp, 0, mt, 0, NN);
  110.         mti = (int) tmp[NN];

  111.         super.setStateInternal(c[1]);
  112.     }

  113.     /**
  114.      * Initializes the generator with the given seed.
  115.      *
  116.      * @param inputSeed Initial seed.
  117.      */
  118.     private void setSeedInternal(long[] inputSeed) {
  119.         // Accept empty seed.
  120.         final long[] seed = (inputSeed.length == 0) ? new long[1] : inputSeed;

  121.         initState(19650218L);
  122.         int i = 1;
  123.         int j = 0;

  124.         for (int k = Math.max(NN, seed.length); k != 0; k--) {
  125.             final long mm1 = mt[i - 1];
  126.             mt[i] = (mt[i] ^ ((mm1 ^ (mm1 >>> 62)) * 0x369dea0f31a53f85L)) + seed[j] + j; // non linear
  127.             i++;
  128.             j++;
  129.             if (i >= NN) {
  130.                 mt[0] = mt[NN - 1];
  131.                 i = 1;
  132.             }
  133.             if (j >= seed.length) {
  134.                 j = 0;
  135.             }
  136.         }
  137.         for (int k = NN - 1; k != 0; k--) {
  138.             final long mm1 = mt[i - 1];
  139.             mt[i] = (mt[i] ^ ((mm1 ^ (mm1 >>> 62)) * 0x27bb2ee687b0b0fdL)) - i; // non linear
  140.             i++;
  141.             if (i >= NN) {
  142.                 mt[0] = mt[NN - 1];
  143.                 i = 1;
  144.             }
  145.         }

  146.         mt[0] = 0x8000000000000000L; // MSB is 1; assuring non-zero initial array
  147.     }

  148.     /**
  149.      * Initialize the internal state of this instance.
  150.      *
  151.      * @param seed Seed.
  152.      */
  153.     private void initState(long seed) {
  154.         mt[0] = seed;
  155.         for (mti = 1; mti < NN; mti++) {
  156.             final long mm1 = mt[mti - 1];
  157.             mt[mti] = 0x5851f42d4c957f2dL * (mm1 ^ (mm1 >>> 62)) + mti;
  158.         }
  159.     }

  160.     /** {@inheritDoc} */
  161.     @Override
  162.     public long next() {
  163.         long x;

  164.         if (mti >= NN) { // generate NN words at one time
  165.             for (int i = 0; i < NN - MM; i++) {
  166.                 x = (mt[i] & UM) | (mt[i + 1] & LM);
  167.                 mt[i] = mt[i + MM] ^ (x >>> 1) ^ MAG01[(int)(x & 0x1L)];
  168.             }
  169.             for (int i = NN - MM; i < NN - 1; i++) {
  170.                 x = (mt[i] & UM) | (mt[i + 1] & LM);
  171.                 mt[i] = mt[ i + (MM - NN)] ^ (x >>> 1) ^ MAG01[(int)(x & 0x1L)];
  172.             }

  173.             x = (mt[NN - 1] & UM) | (mt[0] & LM);
  174.             mt[NN - 1] = mt[MM - 1] ^ (x >>> 1) ^ MAG01[(int)(x & 0x1L)];

  175.             mti = 0;
  176.         }

  177.         x = mt[mti++];

  178.         x ^= (x >>> 29) & 0x5555555555555555L;
  179.         x ^= (x << 17) & 0x71d67fffeda60000L;
  180.         x ^= (x << 37) & 0xfff7eee000000000L;
  181.         x ^= x >>> 43;

  182.         return x;
  183.     }
  184. }