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 import org.apache.commons.rng.core.util.NumberFactory;
23
24 /**
25 * This abstract class is a base for algorithms from the LXM family of
26 * generators with a 64-bit LCG and 128-bit XBG sub-generator. The class implements
27 * the state save/restore functions.
28 *
29 * @since 1.5
30 */
31 abstract class AbstractL64X128 extends AbstractL64 {
32 /** LCG multiplier. */
33 protected static final long M = LXMSupport.M64;
34 /** Size of the seed vector. */
35 private static final int SEED_SIZE = 4;
36 /** Size of the XBG state vector. */
37 private static final int XBG_STATE_SIZE = 2;
38
39 /** State 0 of the XBG. */
40 protected long x0;
41 /** State 1 of the XBG. */
42 protected long x1;
43
44 /**
45 * Creates a new instance.
46 *
47 * @param seed Initial seed.
48 * If the length is larger than 4, only the first 4 elements will
49 * be used; if smaller, the remaining elements will be automatically
50 * set. A seed containing all zeros in the last two elements
51 * will create a non-functional XBG sub-generator and a low
52 * quality output with a period of 2<sup>64</sup>.
53 *
54 * <p>The 1st element is used to set the LCG increment; the least significant bit
55 * is set to odd to ensure a full period LCG. The 2nd element is used
56 * to set the LCG state.</p>
57 */
58 AbstractL64X128(long[] seed) {
59 super(seed = extendSeed(seed, SEED_SIZE));
60 x0 = seed[2];
61 x1 = seed[3];
62 }
63
64 /**
65 * Creates a new instance using a 4 element seed.
66 * A seed containing all zeros in the last two elements
67 * will create a non-functional XBG sub-generator and a low
68 * quality output with a period of 2<sup>64</sup>.
69 *
70 * <p>The 1st element is used to set the LCG increment; the least significant bit
71 * is set to odd to ensure a full period LCG. The 2nd element is used
72 * to set the LCG state.</p>
73 *
74 * @param seed0 Initial seed element 0.
75 * @param seed1 Initial seed element 1.
76 * @param seed2 Initial seed element 2.
77 * @param seed3 Initial seed element 3.
78 */
79 AbstractL64X128(long seed0, long seed1, long seed2, long seed3) {
80 super(seed0, seed1);
81 x0 = seed2;
82 x1 = seed3;
83 }
84
85 /**
86 * Creates a copy instance.
87 *
88 * @param source Source to copy.
89 */
90 AbstractL64X128(AbstractL64X128 source) {
91 super(source);
92 x0 = source.x0;
93 x1 = source.x1;
94 }
95
96 /** {@inheritDoc} */
97 @Override
98 protected byte[] getStateInternal() {
99 return composeStateInternal(NumberFactory.makeByteArray(
100 new long[] {x0, x1}),
101 super.getStateInternal());
102 }
103
104 /** {@inheritDoc} */
105 @Override
106 protected void setStateInternal(byte[] s) {
107 final byte[][] c = splitStateInternal(s, XBG_STATE_SIZE * Long.BYTES);
108 final long[] tmp = NumberFactory.makeLongArray(c[0]);
109 x0 = tmp[0];
110 x1 = tmp[1];
111 super.setStateInternal(c[1]);
112 }
113
114 /**
115 * {@inheritDoc}
116 *
117 * <p>The jump size is the equivalent of moving the state <em>backwards</em> by
118 * (2<sup>128</sup> - 1) positions. It can provide up to 2<sup>64</sup>
119 * non-overlapping subsequences.
120 */
121 @Override
122 public UniformRandomProvider jump() {
123 return super.jump();
124 }
125
126 /**
127 * {@inheritDoc}
128 *
129 * <p>The jump size is the equivalent of moving the state <em>backwards</em> by
130 * 2<sup>32</sup> (2<sup>128</sup> - 1) positions. It can provide up to
131 * 2<sup>32</sup> non-overlapping subsequences of length 2<sup>32</sup>
132 * (2<sup>128</sup> - 1); each subsequence can provide up to 2<sup>32</sup>
133 * non-overlapping subsequences of length (2<sup>128</sup> - 1) using the
134 * {@link #jump()} method.
135 */
136 @Override
137 public JumpableUniformRandomProvider longJump() {
138 return super.longJump();
139 }
140 }