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 @Override
61 protected byte[] getStateInternal() {
62
63 final long[] state = new long[] { booleanSource,
64 booleanBitMask,
65 intSource,
66 cachedIntSource ? 1 : 0 };
67 return composeStateInternal(super.getStateInternal(),
68 NumberFactory.makeByteArray(state));
69 }
70
71
72 @Override
73 protected void setStateInternal(byte[] s) {
74 final byte[][] c = splitStateInternal(s, 32);
75 final long[] state = NumberFactory.makeLongArray(c[0]);
76 booleanSource = state[0];
77 booleanBitMask = state[1];
78 intSource = state[2];
79
80 cachedIntSource = state[3] != 0;
81 super.setStateInternal(c[1]);
82 }
83
84
85 @Override
86 public long nextLong() {
87 return next();
88 }
89
90
91 @Override
92 public int nextInt() {
93
94 if (cachedIntSource) {
95
96 cachedIntSource = false;
97
98 return NumberFactory.extractLo(intSource);
99 }
100
101 cachedIntSource = true;
102 intSource = nextLong();
103
104 return NumberFactory.extractHi(intSource);
105 }
106
107
108 @Override
109 public double nextDouble() {
110 return NumberFactory.makeDouble(nextLong());
111 }
112
113
114 @Override
115 public boolean nextBoolean() {
116
117 booleanBitMask <<= 1;
118
119 if (booleanBitMask == 0) {
120
121 booleanBitMask = 1;
122
123 booleanSource = nextLong();
124 }
125
126 return (booleanSource & booleanBitMask) != 0;
127 }
128
129
130 @Override
131 public float nextFloat() {
132 return NumberFactory.makeFloat(nextInt());
133 }
134
135
136 @Override
137 public void nextBytes(byte[] bytes) {
138 nextBytesFill(this, bytes, 0, bytes.length);
139 }
140
141
142 @Override
143 public void nextBytes(byte[] bytes,
144 int start,
145 int len) {
146 checkIndex(0, bytes.length - 1, start);
147 checkIndex(0, bytes.length - start, len);
148
149 nextBytesFill(this, bytes, start, len);
150 }
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166 static void nextBytesFill(RandomLongSource source,
167 byte[] bytes,
168 int start,
169 int len) {
170 int index = start;
171
172
173
174 final int indexLoopLimit = index + (len & 0x7ffffff8);
175
176
177 while (index < indexLoopLimit) {
178 final long random = source.next();
179 bytes[index++] = (byte) random;
180 bytes[index++] = (byte) (random >>> 8);
181 bytes[index++] = (byte) (random >>> 16);
182 bytes[index++] = (byte) (random >>> 24);
183 bytes[index++] = (byte) (random >>> 32);
184 bytes[index++] = (byte) (random >>> 40);
185 bytes[index++] = (byte) (random >>> 48);
186 bytes[index++] = (byte) (random >>> 56);
187 }
188
189 final int indexLimit = start + len;
190
191
192 if (index < indexLimit) {
193 long random = source.next();
194 while (true) {
195 bytes[index++] = (byte) random;
196 if (index < indexLimit) {
197 random >>>= 8;
198 } else {
199 break;
200 }
201 }
202 }
203 }
204 }