AbstractL64X128.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 org.apache.commons.rng.JumpableUniformRandomProvider;
  19. import org.apache.commons.rng.UniformRandomProvider;
  20. import org.apache.commons.rng.core.util.NumberFactory;

  21. /**
  22.  * This abstract class is a base for algorithms from the LXM family of
  23.  * generators with a 64-bit LCG and 128-bit XBG sub-generator. The class implements
  24.  * the state save/restore functions.
  25.  *
  26.  * @since 1.5
  27.  */
  28. abstract class AbstractL64X128 extends AbstractL64 {
  29.     /** LCG multiplier. */
  30.     protected static final long M = LXMSupport.M64;
  31.     /** Size of the seed vector. */
  32.     private static final int SEED_SIZE = 4;
  33.     /** Size of the XBG state vector. */
  34.     private static final int XBG_STATE_SIZE = 2;

  35.     /** State 0 of the XBG. */
  36.     protected long x0;
  37.     /** State 1 of the XBG. */
  38.     protected long x1;

  39.     /**
  40.      * Creates a new instance.
  41.      *
  42.      * @param seed Initial seed.
  43.      * If the length is larger than 4, only the first 4 elements will
  44.      * be used; if smaller, the remaining elements will be automatically
  45.      * set. A seed containing all zeros in the last two elements
  46.      * will create a non-functional XBG sub-generator and a low
  47.      * quality output with a period of 2<sup>64</sup>.
  48.      *
  49.      * <p>The 1st element is used to set the LCG increment; the least significant bit
  50.      * is set to odd to ensure a full period LCG. The 2nd element is used
  51.      * to set the LCG state.</p>
  52.      */
  53.     AbstractL64X128(long[] seed) {
  54.         super(seed = extendSeed(seed, SEED_SIZE));
  55.         x0 = seed[2];
  56.         x1 = seed[3];
  57.     }

  58.     /**
  59.      * Creates a new instance using a 4 element seed.
  60.      * A seed containing all zeros in the last two elements
  61.      * will create a non-functional XBG sub-generator and a low
  62.      * quality output with a period of 2<sup>64</sup>.
  63.      *
  64.      * <p>The 1st element is used to set the LCG increment; the least significant bit
  65.      * is set to odd to ensure a full period LCG. The 2nd element is used
  66.      * to set the LCG state.</p>
  67.      *
  68.      * @param seed0 Initial seed element 0.
  69.      * @param seed1 Initial seed element 1.
  70.      * @param seed2 Initial seed element 2.
  71.      * @param seed3 Initial seed element 3.
  72.      */
  73.     AbstractL64X128(long seed0, long seed1, long seed2, long seed3) {
  74.         super(seed0, seed1);
  75.         x0 = seed2;
  76.         x1 = seed3;
  77.     }

  78.     /**
  79.      * Creates a copy instance.
  80.      *
  81.      * @param source Source to copy.
  82.      */
  83.     AbstractL64X128(AbstractL64X128 source) {
  84.         super(source);
  85.         x0 = source.x0;
  86.         x1 = source.x1;
  87.     }

  88.     /** {@inheritDoc} */
  89.     @Override
  90.     protected byte[] getStateInternal() {
  91.         return composeStateInternal(NumberFactory.makeByteArray(
  92.                                         new long[] {x0, x1}),
  93.                                     super.getStateInternal());
  94.     }

  95.     /** {@inheritDoc} */
  96.     @Override
  97.     protected void setStateInternal(byte[] s) {
  98.         final byte[][] c = splitStateInternal(s, XBG_STATE_SIZE * Long.BYTES);
  99.         final long[] tmp = NumberFactory.makeLongArray(c[0]);
  100.         x0 = tmp[0];
  101.         x1 = tmp[1];
  102.         super.setStateInternal(c[1]);
  103.     }

  104.     /**
  105.      * {@inheritDoc}
  106.      *
  107.      * <p>The jump size is the equivalent of moving the state <em>backwards</em> by
  108.      * (2<sup>128</sup> - 1) positions. It can provide up to 2<sup>64</sup>
  109.      * non-overlapping subsequences.
  110.      */
  111.     @Override
  112.     public UniformRandomProvider jump() {
  113.         return super.jump();
  114.     }

  115.     /**
  116.      * {@inheritDoc}
  117.      *
  118.      * <p>The jump size is the equivalent of moving the state <em>backwards</em> by
  119.      * 2<sup>32</sup> (2<sup>128</sup> - 1) positions. It can provide up to
  120.      * 2<sup>32</sup> non-overlapping subsequences of length 2<sup>32</sup>
  121.      * (2<sup>128</sup> - 1); each subsequence can provide up to 2<sup>32</sup>
  122.      * non-overlapping subsequences of length (2<sup>128</sup> - 1) using the
  123.      * {@link #jump()} method.
  124.      */
  125.     @Override
  126.     public JumpableUniformRandomProvider longJump() {
  127.         return super.longJump();
  128.     }
  129. }