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.core.util.NumberFactory;
21 import org.apache.commons.rng.core.BaseProvider;
22
23
24
25
26
27 public abstract class LongProvider
28 extends BaseProvider
29 implements RandomLongSource {
30
31
32
33
34
35
36 private long booleanSource;
37
38
39
40
41
42
43
44
45
46
47 private long booleanBitMask;
48
49
50
51
52
53
54 private long intSource;
55
56
57 private boolean cachedIntSource;
58
59
60
61
62 public LongProvider() {
63 super();
64 }
65
66
67
68
69
70
71
72
73
74
75
76 protected LongProvider(LongProvider source) {
77 booleanSource = source.booleanSource;
78 booleanBitMask = source.booleanBitMask;
79 intSource = source.intSource;
80 cachedIntSource = source.cachedIntSource;
81 }
82
83
84
85
86
87
88
89
90
91
92
93 protected void resetCachedState() {
94 booleanSource = 0L;
95 booleanBitMask = 0L;
96 intSource = 0L;
97 cachedIntSource = false;
98 }
99
100
101 @Override
102 protected byte[] getStateInternal() {
103
104 final long[] state = new long[] {booleanSource,
105 booleanBitMask,
106 intSource,
107 cachedIntSource ? 1 : 0 };
108 return composeStateInternal(NumberFactory.makeByteArray(state),
109 super.getStateInternal());
110 }
111
112
113 @Override
114 protected void setStateInternal(byte[] s) {
115 final byte[][] c = splitStateInternal(s, 32);
116 final long[] state = NumberFactory.makeLongArray(c[0]);
117 booleanSource = state[0];
118 booleanBitMask = state[1];
119 intSource = state[2];
120
121 cachedIntSource = state[3] != 0;
122 super.setStateInternal(c[1]);
123 }
124
125
126 @Override
127 public long nextLong() {
128 return next();
129 }
130
131
132 @Override
133 public int nextInt() {
134
135 if (cachedIntSource) {
136
137 cachedIntSource = false;
138
139 return NumberFactory.extractLo(intSource);
140 }
141
142 cachedIntSource = true;
143 intSource = nextLong();
144
145 return NumberFactory.extractHi(intSource);
146 }
147
148
149 @Override
150 public double nextDouble() {
151 return NumberFactory.makeDouble(nextLong());
152 }
153
154
155 @Override
156 public boolean nextBoolean() {
157
158 booleanBitMask <<= 1;
159
160 if (booleanBitMask == 0) {
161
162 booleanBitMask = 1;
163
164 booleanSource = nextLong();
165 }
166
167 return (booleanSource & booleanBitMask) != 0;
168 }
169
170
171 @Override
172 public float nextFloat() {
173 return NumberFactory.makeFloat(nextInt());
174 }
175
176
177 @Override
178 public void nextBytes(byte[] bytes) {
179 nextBytesFill(this, bytes, 0, bytes.length);
180 }
181
182
183 @Override
184 public void nextBytes(byte[] bytes,
185 int start,
186 int len) {
187 checkIndex(0, bytes.length - 1, start);
188 checkIndex(0, bytes.length - start, len);
189
190 nextBytesFill(this, bytes, start, len);
191 }
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207 static void nextBytesFill(RandomLongSource source,
208 byte[] bytes,
209 int start,
210 int len) {
211 int index = start;
212
213
214
215 final int indexLoopLimit = index + (len & 0x7ffffff8);
216
217
218 while (index < indexLoopLimit) {
219 final long random = source.next();
220 bytes[index++] = (byte) random;
221 bytes[index++] = (byte) (random >>> 8);
222 bytes[index++] = (byte) (random >>> 16);
223 bytes[index++] = (byte) (random >>> 24);
224 bytes[index++] = (byte) (random >>> 32);
225 bytes[index++] = (byte) (random >>> 40);
226 bytes[index++] = (byte) (random >>> 48);
227 bytes[index++] = (byte) (random >>> 56);
228 }
229
230 final int indexLimit = start + len;
231
232
233 if (index < indexLimit) {
234 long random = source.next();
235 while (true) {
236 bytes[index++] = (byte) random;
237 if (index < indexLimit) {
238 random >>>= 8;
239 } else {
240 break;
241 }
242 }
243 }
244 }
245 }