1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.rng.core;
19
20 import org.apache.commons.rng.RestorableUniformRandomProvider;
21 import org.apache.commons.rng.RandomProviderState;
22
23
24
25
26 public abstract class BaseProvider
27 implements RestorableUniformRandomProvider {
28
29 @Override
30 public int nextInt(int n) {
31 checkStrictlyPositive(n);
32
33 if ((n & -n) == n) {
34 return (int) ((n * (long) (nextInt() >>> 1)) >> 31);
35 }
36 int bits;
37 int val;
38 do {
39 bits = nextInt() >>> 1;
40 val = bits % n;
41 } while (bits - val + (n - 1) < 0);
42
43 return val;
44 }
45
46
47 @Override
48 public long nextLong(long n) {
49 checkStrictlyPositive(n);
50
51 long bits;
52 long val;
53 do {
54 bits = nextLong() >>> 1;
55 val = bits % n;
56 } while (bits - val + (n - 1) < 0);
57
58 return val;
59 }
60
61
62 @Override
63 public RandomProviderState saveState() {
64 return new RandomProviderDefaultState(getStateInternal());
65 }
66
67
68 @Override
69 public void restoreState(RandomProviderState state) {
70 if (state instanceof RandomProviderDefaultState) {
71 setStateInternal(((RandomProviderDefaultState) state).getState());
72 } else {
73 throw new IllegalArgumentException("Foreign instance");
74 }
75 }
76
77
78 @Override
79 public String toString() {
80 return getClass().getName();
81 }
82
83
84
85
86
87
88
89 protected byte[] getStateInternal() {
90 throw new UnsupportedOperationException();
91 }
92
93
94
95
96
97
98
99
100
101
102 protected void setStateInternal(byte[] state) {
103 throw new UnsupportedOperationException();
104 }
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124 protected void fillState(int[] state,
125 int[] seed) {
126 final int stateSize = state.length;
127 final int seedSize = seed.length;
128 System.arraycopy(seed, 0, state, 0, Math.min(seedSize, stateSize));
129
130 if (seedSize < stateSize) {
131 for (int i = seedSize; i < stateSize; i++) {
132 state[i] = (int) (scrambleWell(state[i - seed.length], i) & 0xffffffffL);
133 }
134 }
135 }
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155 protected void fillState(long[] state,
156 long[] seed) {
157 final int stateSize = state.length;
158 final int seedSize = seed.length;
159 System.arraycopy(seed, 0, state, 0, Math.min(seedSize, stateSize));
160
161 if (seedSize < stateSize) {
162 for (int i = seedSize; i < stateSize; i++) {
163 state[i] = scrambleWell(state[i - seed.length], i);
164 }
165 }
166 }
167
168
169
170
171
172
173
174
175 protected void checkStateSize(byte[] state,
176 int expected) {
177 if (state.length != expected) {
178 throw new IllegalArgumentException("State size must be " + expected +
179 " but was " + state.length);
180 }
181 }
182
183
184
185
186
187
188
189
190
191
192 protected void checkIndex(int min,
193 int max,
194 int index) {
195 if (index < min ||
196 index > max) {
197 throw new IndexOutOfBoundsException(index + " is out of interval [" +
198 min + ", " +
199 max + "]");
200 }
201 }
202
203
204
205
206
207
208
209 private void checkStrictlyPositive(long n) {
210 if (n <= 0) {
211 throw new IllegalArgumentException("Must be strictly positive: " + n);
212 }
213 }
214
215
216
217
218
219
220
221
222
223
224
225 private static long scramble(long n,
226 long mult,
227 int shift,
228 int add) {
229
230 return mult * (n ^ (n >> shift)) + add;
231 }
232
233
234
235
236
237
238
239
240
241
242 private static long scrambleWell(long n,
243 int add) {
244
245 return scramble(n, 1812433253L, 30, add);
246 }
247 }