1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.rng.core.source64;
19
20 import org.apache.commons.rng.JumpableUniformRandomProvider;
21 import org.apache.commons.rng.LongJumpableUniformRandomProvider;
22 import org.apache.commons.rng.UniformRandomProvider;
23 import org.apache.commons.rng.core.util.NumberFactory;
24
25
26
27
28
29
30
31
32 abstract class AbstractXoShiRo256 extends LongProvider implements LongJumpableUniformRandomProvider {
33
34 private static final int SEED_SIZE = 4;
35
36 private static final long[] JUMP_COEFFICIENTS = {
37 0x180ec6d33cfd0abaL, 0xd5a61266f0c9392cL, 0xa9582618e03fc9aaL, 0x39abdc4529b1661cL
38 };
39
40 private static final long[] LONG_JUMP_COEFFICIENTS = {
41 0x76e15d3efefdcbbfL, 0xc5004e441c522fb3L, 0x77710069854ee241L, 0x39109bb02acbe635L
42 };
43
44
45
46
47 protected long state0;
48
49 protected long state1;
50
51 protected long state2;
52
53 protected long state3;
54
55
56
57
58
59
60
61
62
63 AbstractXoShiRo256(long[] seed) {
64 if (seed.length < SEED_SIZE) {
65 final long[] state = new long[SEED_SIZE];
66 fillState(state, seed);
67 setState(state);
68 } else {
69 setState(seed);
70 }
71 }
72
73
74
75
76
77
78
79
80
81
82 AbstractXoShiRo256(long seed0, long seed1, long seed2, long seed3) {
83 state0 = seed0;
84 state1 = seed1;
85 state2 = seed2;
86 state3 = seed3;
87 }
88
89
90
91
92
93
94 protected AbstractXoShiRo256(AbstractXoShiRo256 source) {
95 super(source);
96 state0 = source.state0;
97 state1 = source.state1;
98 state2 = source.state2;
99 state3 = source.state3;
100 }
101
102
103
104
105
106
107 private void setState(long[] state) {
108 state0 = state[0];
109 state1 = state[1];
110 state2 = state[2];
111 state3 = state[3];
112 }
113
114
115 @Override
116 protected byte[] getStateInternal() {
117 return composeStateInternal(NumberFactory.makeByteArray(
118 new long[] {state0, state1, state2, state3}),
119 super.getStateInternal());
120 }
121
122
123 @Override
124 protected void setStateInternal(byte[] s) {
125 final byte[][] c = splitStateInternal(s, SEED_SIZE * 8);
126
127 setState(NumberFactory.makeLongArray(c[0]));
128
129 super.setStateInternal(c[1]);
130 }
131
132
133 @Override
134 public long next() {
135 final long result = nextOutput();
136
137 final long t = state1 << 17;
138
139 state2 ^= state0;
140 state3 ^= state1;
141 state1 ^= state2;
142 state0 ^= state3;
143
144 state2 ^= t;
145
146 state3 = Long.rotateLeft(state3, 45);
147
148 return result;
149 }
150
151
152
153
154
155
156
157
158 protected abstract long nextOutput();
159
160
161
162
163
164
165
166
167 @Override
168 public UniformRandomProvider jump() {
169 final UniformRandomProvider copy = copy();
170 performJump(JUMP_COEFFICIENTS);
171 return copy;
172 }
173
174
175
176
177
178
179
180
181
182
183 @Override
184 public JumpableUniformRandomProvider longJump() {
185 final JumpableUniformRandomProvider copy = copy();
186 performJump(LONG_JUMP_COEFFICIENTS);
187 return copy;
188 }
189
190
191
192
193
194
195 protected abstract AbstractXoShiRo256 copy();
196
197
198
199
200
201
202 private void performJump(long[] jumpCoefficients) {
203 long s0 = 0;
204 long s1 = 0;
205 long s2 = 0;
206 long s3 = 0;
207 for (final long jc : jumpCoefficients) {
208 for (int b = 0; b < 64; b++) {
209 if ((jc & (1L << b)) != 0) {
210 s0 ^= state0;
211 s1 ^= state1;
212 s2 ^= state2;
213 s3 ^= state3;
214 }
215 next();
216 }
217 }
218 state0 = s0;
219 state1 = s1;
220 state2 = s2;
221 state3 = s3;
222 resetCachedState();
223 }
224 }