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 }