1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.rng.core.source32;
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 AbstractXoShiRo128 extends IntProvider implements LongJumpableUniformRandomProvider {
33
34 private static final int SEED_SIZE = 4;
35
36 private static final int[] JUMP_COEFFICIENTS = {
37 0x8764000b, 0xf542d2d3, 0x6fa035c3, 0x77f2db5b
38 };
39
40 private static final int[] LONG_JUMP_COEFFICIENTS = {
41 0xb523952e, 0x0b6f099f, 0xccf5a0ef, 0x1c580662
42 };
43
44
45
46
47 protected int state0;
48
49 protected int state1;
50
51 protected int state2;
52
53 protected int state3;
54
55
56
57
58
59
60
61
62
63 AbstractXoShiRo128(int[] seed) {
64 if (seed.length < SEED_SIZE) {
65 final int[] state = new int[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 AbstractXoShiRo128(int seed0, int seed1, int seed2, int seed3) {
83 state0 = seed0;
84 state1 = seed1;
85 state2 = seed2;
86 state3 = seed3;
87 }
88
89
90
91
92
93
94 protected AbstractXoShiRo128(AbstractXoShiRo128 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(int[] 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 int[] {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 * 4);
126
127 setState(NumberFactory.makeIntArray(c[0]));
128
129 super.setStateInternal(c[1]);
130 }
131
132
133 @Override
134 public int next() {
135 final int result = nextOutput();
136
137 final int t = state1 << 9;
138
139 state2 ^= state0;
140 state3 ^= state1;
141 state1 ^= state2;
142 state0 ^= state3;
143
144 state2 ^= t;
145
146 state3 = Integer.rotateLeft(state3, 11);
147
148 return result;
149 }
150
151
152
153
154
155
156
157
158 protected abstract int 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 AbstractXoShiRo128 copy();
196
197
198
199
200
201
202 private void performJump(int[] jumpCoefficients) {
203 int s0 = 0;
204 int s1 = 0;
205 int s2 = 0;
206 int s3 = 0;
207 for (final int jc : jumpCoefficients) {
208 for (int b = 0; b < 32; b++) {
209 if ((jc & (1 << 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 }