View Javadoc
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  
18  package org.apache.commons.rng.core.source64;
19  
20  import org.apache.commons.rng.JumpableUniformRandomProvider;
21  import org.apache.commons.rng.UniformRandomProvider;
22  
23  /**
24   * A fast all-purpose 64-bit generator.
25   *
26   * <p>This is a member of the Xor-Shift-Rotate family of generators. Memory footprint is 128 bits
27   * and the period is 2<sup>128</sup>-1. Speed is expected to be similar to
28   * {@link XoShiRo256StarStar}.</p>
29   *
30   * @see <a href="http://xoshiro.di.unimi.it/xoroshiro128plusplus.c">Original source code</a>
31   * @see <a href="http://xoshiro.di.unimi.it/">xorshiro / xoroshiro generators</a>
32   * @since 1.3
33   */
34  public class XoRoShiRo128PlusPlus extends AbstractXoRoShiRo128 {
35      /** The coefficients for the jump function. */
36      private static final long[] JUMP_COEFFICIENTS = {
37          0x2bd7a6a6e99c2ddcL, 0x0992ccaf6a6fca05L
38      };
39      /** The coefficients for the long jump function. */
40      private static final long[] LONG_JUMP_COEFFICIENTS = {
41          0x360fd5f2cf8d5d99L, 0x9c6e6877736c46e3L
42      };
43  
44      /**
45       * Creates a new instance.
46       *
47       * @param seed Initial seed.
48       * If the length is larger than 2, only the first 2 elements will
49       * be used; if smaller, the remaining elements will be automatically
50       * set. A seed containing all zeros will create a non-functional generator.
51       */
52      public XoRoShiRo128PlusPlus(long[] seed) {
53          super(seed);
54      }
55  
56      /**
57       * Creates a new instance using a 2 element seed.
58       * A seed containing all zeros will create a non-functional generator.
59       *
60       * @param seed0 Initial seed element 0.
61       * @param seed1 Initial seed element 1.
62       */
63      public XoRoShiRo128PlusPlus(long seed0, long seed1) {
64          super(seed0, seed1);
65      }
66  
67      /**
68       * Creates a copy instance.
69       *
70       * @param source Source to copy.
71       */
72      protected XoRoShiRo128PlusPlus(XoRoShiRo128PlusPlus source) {
73          super(source);
74      }
75  
76      /** {@inheritDoc} */
77      @Override
78      public long next() {
79          // Override the abstract class to use a different state update step.
80          // Note: This requires different jump coefficients.
81  
82          final long s0 = state0;
83          long s1 = state1;
84          final long result = Long.rotateLeft(s0 + s1, 17) + s0;
85  
86          s1 ^= s0;
87          state0 = Long.rotateLeft(s0, 49) ^ s1 ^ (s1 << 21); // a, b
88          state1 = Long.rotateLeft(s1, 28); // c
89  
90          return result;
91      }
92  
93      /** {@inheritDoc} */
94      @Override
95      protected long nextOutput() {
96          throw new UnsupportedOperationException("The PlusPlus algorithm redefines the next() method");
97      }
98  
99      /** {@inheritDoc} */
100     @Override
101     public UniformRandomProvider jump() {
102         // Duplicated from the abstract class to change the jump coefficients
103         final UniformRandomProvider copy = copy();
104         performJump(JUMP_COEFFICIENTS);
105         return copy;
106     }
107 
108     /** {@inheritDoc} */
109     @Override
110     public JumpableUniformRandomProvider longJump() {
111         // Duplicated from the abstract class to change the jump coefficients
112         final JumpableUniformRandomProvider copy = copy();
113         performJump(LONG_JUMP_COEFFICIENTS);
114         return copy;
115     }
116 
117     /** {@inheritDoc} */
118     @Override
119     protected XoRoShiRo128PlusPlus copy() {
120         // This exists to ensure the jump function performed in the super class returns
121         // the correct class type. It should not be public.
122         return new XoRoShiRo128PlusPlus(this);
123     }
124 }