1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.commons.rng.simple.internal;
18
19 /**
20 * Performs seed conversions.
21 *
22 * <p>Note: Legacy converters from version 1.0 use instances of
23 * the {@link SeedConverter} interface. Instances are no longer
24 * required as no state is used during conversion and converters
25 * can use static methods.
26 *
27 * @since 1.5
28 */
29 final class Conversions {
30 /**
31 * The fractional part of the golden ratio, phi, scaled to 64-bits and rounded to odd.
32 * <pre>
33 * phi = (sqrt(5) - 1) / 2) * 2^64
34 * </pre>
35 * @see <a href="https://en.wikipedia.org/wiki/Golden_ratio">Golden ratio</a>
36 */
37 private static final long GOLDEN_RATIO = MixFunctions.GOLDEN_RATIO_64;
38
39 /** No instances. */
40 private Conversions() {}
41
42 /**
43 * Compute the size of an {@code int} array required to hold the specified number of bytes.
44 * Allows space for any remaining bytes that do not fit exactly in a 4 byte integer.
45 * <pre>
46 * n = ceil(size / 4)
47 * </pre>
48 *
49 * @param size the size in bytes (assumed to be positive)
50 * @return the size in ints
51 */
52 static int intSizeFromByteSize(int size) {
53 return (size + 3) >>> 2;
54 }
55
56 /**
57 * Compute the size of an {@code long} array required to hold the specified number of bytes.
58 * Allows space for any remaining bytes that do not fit exactly in an 8 byte long.
59 * <pre>
60 * n = ceil(size / 8)
61 * </pre>
62 *
63 * @param size the size in bytes (assumed to be positive)
64 * @return the size in longs
65 */
66 static int longSizeFromByteSize(int size) {
67 return (size + 7) >>> 3;
68 }
69
70 /**
71 * Compute the size of an {@code int} array required to hold the specified number of longs.
72 * Prevents overflow to a negative number when doubling the size.
73 * <pre>
74 * n = min(size * 2, 2^31 - 1)
75 * </pre>
76 *
77 * @param size the size in longs (assumed to be positive)
78 * @return the size in ints
79 */
80 static int intSizeFromLongSize(int size) {
81 // Avoid overflow when doubling the length.
82 // If n is negative the signed shift creates a mask with all bits set;
83 // otherwise it is zero and n is unchanged after the or operation.
84 // The final mask clears the sign bit in the event n did overflow.
85 final int n = size << 1;
86 return (n | (n >> 31)) & Integer.MAX_VALUE;
87 }
88
89 /**
90 * Compute the size of an {@code long} array required to hold the specified number of ints.
91 * Allows space for an odd int.
92 * <pre>
93 * n = ceil(size / 2)
94 * </pre>
95 *
96 * @param size the size in ints (assumed to be positive)
97 * @return the size in longs
98 */
99 static int longSizeFromIntSize(int size) {
100 return (size + 1) >>> 1;
101 }
102
103 /**
104 * Creates a {@code long} value from an {@code int}. The conversion
105 * is made as if seeding a SplitMix64 RNG and calling nextLong().
106 *
107 * @param input Input
108 * @return a {@code long}.
109 */
110 static long int2Long(int input) {
111 return MixFunctions.stafford13(input + GOLDEN_RATIO);
112 }
113
114 /**
115 * Creates an {@code int[]} value from an {@code int}. The conversion
116 * is made as if seeding a SplitMix64 RNG and calling nextLong() to
117 * generate the sequence and filling the ints
118 * in little-endian order (least significant byte first).
119 *
120 * @param input Input
121 * @param length Array length
122 * @return an {@code int[]}.
123 */
124 static int[] int2IntArray(int input, int length) {
125 return long2IntArray(input, length);
126 }
127
128 /**
129 * Creates a {@code long[]} value from an {@code int}. The conversion
130 * is made as if seeding a SplitMix64 RNG and calling nextLong() to
131 * generate the sequence.
132 *
133 * @param input Input
134 * @param length Array length
135 * @return a {@code long[]}.
136 */
137 static long[] int2LongArray(int input, int length) {
138 return long2LongArray(input, length);
139 }
140
141 /**
142 * Creates an {@code int} value from a {@code long}. The conversion
143 * is made by xoring the upper and lower bits.
144 *
145 * @param input Input
146 * @return an {@code int}.
147 */
148 static int long2Int(long input) {
149 return (int) input ^ (int) (input >>> 32);
150 }
151
152 /**
153 * Creates an {@code int[]} value from a {@code long}. The conversion
154 * is made as if seeding a SplitMix64 RNG and calling nextLong() to
155 * generate the sequence and filling the ints
156 * in little-endian order (least significant byte first).
157 *
158 * <p>A special case is made to avoid an array filled with zeros for
159 * the initial 2 positions. It is still possible to create a zero in
160 * position 0. However any RNG with an int[] native type is expected to
161 * require at least 2 int values.
162 *
163 * @param input Input
164 * @param length Array length
165 * @return an {@code int[]}.
166 */
167 static int[] long2IntArray(long input, int length) {
168 // Special case to avoid creating a zero-filled array of length 2.
169 long v = input == -GOLDEN_RATIO ? ~input : input;
170 final int[] output = new int[length];
171 // Process pairs
172 final int n = length & ~0x1;
173 for (int i = 0; i < n; i += 2) {
174 v += GOLDEN_RATIO;
175 final long x = MixFunctions.stafford13(v);
176 output[i] = (int) x;
177 output[i + 1] = (int) (x >>> 32);
178 }
179 // Final value
180 if (n < length) {
181 output[n] = (int) MixFunctions.stafford13(v + GOLDEN_RATIO);
182 }
183 return output;
184 }
185
186 /**
187 * Creates a {@code long[]} value from a {@code long}. The conversion
188 * is made as if seeding a SplitMix64 RNG and calling nextLong() to
189 * generate the sequence.
190 *
191 * @param input Input
192 * @param length Array length
193 * @return a {@code long}.
194 */
195 static long[] long2LongArray(long input, int length) {
196 long v = input;
197 final long[] output = new long[length];
198 for (int i = 0; i < length; i++) {
199 v += GOLDEN_RATIO;
200 output[i] = MixFunctions.stafford13(v);
201 }
202 return output;
203 }
204
205 /**
206 * Creates an {@code int} value from a sequence of ints. The conversion
207 * is made by combining all the longs with a xor operation.
208 *
209 * @param input Input bytes
210 * @return an {@code int}.
211 */
212 static int intArray2Int(int[] input) {
213 int output = 0;
214 for (final int i : input) {
215 output ^= i;
216 }
217 return output;
218 }
219
220 /**
221 * Creates a {@code long} value from a sequence of ints. The conversion
222 * is made as if converting to a {@code long[]} array by filling the longs
223 * in little-endian order (least significant byte first), then combining
224 * all the longs with a xor operation.
225 *
226 * @param input Input bytes
227 * @return a {@code long}.
228 */
229 static long intArray2Long(int[] input) {
230 long output = 0;
231
232 final int n = input.length;
233 // xor in the bits to a long in little-endian order
234 for (int i = 0; i < n; i++) {
235 // i = int index
236 // i >> 1 = long index
237 // i & 0x1 = int number in the long [0, 1]
238 // (i & 0x1) << 5 = little-endian byte shift to the long {0, 32}
239 output ^= (input[i] & 0xffffffffL) << ((i & 0x1) << 5);
240 }
241
242 return output;
243 }
244
245 /**
246 * Creates a {@code long[]} value from a sequence of ints. The longs are
247 * filled in little-endian order (least significant byte first).
248 *
249 * @param input Input ints
250 * @param length Output array length
251 * @return a {@code long[]}.
252 */
253 static long[] intArray2LongArray(int[] input, int length) {
254 final long[] output = new long[length];
255
256 // Overflow-safe minimum using long
257 final int n = (int) Math.min(input.length, length * 2L);
258 // Little-endian fill
259 for (int i = 0; i < n; i++) {
260 // i = int index
261 // i >> 1 = long index
262 // i & 0x1 = int number in the long [0, 1]
263 // (i & 0x1) << 5 = little-endian byte shift to the long {0, 32}
264 output[i >> 1] |= (input[i] & 0xffffffffL) << ((i & 0x1) << 5);
265 }
266
267 return output;
268 }
269
270 /**
271 * Creates an {@code int} value from a sequence of longs. The conversion
272 * is made as if combining all the longs with a xor operation, then folding
273 * the long high and low parts using a xor operation.
274 *
275 * @param input Input longs
276 * @return an {@code int}.
277 */
278 static int longArray2Int(long[] input) {
279 return long2Int(longArray2Long(input));
280 }
281
282 /**
283 * Creates a {@code long} value from a sequence of longs. The conversion
284 * is made by combining all the longs with a xor operation.
285 *
286 * @param input Input longs
287 * @return a {@code long}.
288 */
289 static long longArray2Long(long[] input) {
290 long output = 0;
291 for (final long i : input) {
292 output ^= i;
293 }
294 return output;
295 }
296
297 /**
298 * Creates a {@code int[]} value from a sequence of longs. The ints are
299 * filled in little-endian order (least significant byte first).
300 *
301 * @param input Input longs
302 * @param length Output array length
303 * @return an {@code int[]}.
304 */
305 static int[] longArray2IntArray(long[] input, int length) {
306 final int[] output = new int[length];
307
308 // Overflow-safe minimum using long
309 final int n = (int) Math.min(input.length * 2L, length);
310 // Little-endian fill
311 // Alternate low/high 32-bits from each long
312 for (int i = 0; i < n; i++) {
313 // i = int index
314 // i >> 1 = long index
315 // i & 0x1 = int number in the long [0, 1]
316 // (i & 0x1) << 5 = little-endian long shift to the int {0, 32}
317 output[i] = (int)((input[i >> 1]) >>> ((i & 0x1) << 5));
318 }
319
320 return output;
321 }
322
323 /**
324 * Creates an {@code int} value from a sequence of bytes. The conversion
325 * is made as if converting to a {@code int[]} array by filling the ints
326 * in little-endian order (least significant byte first), then combining
327 * all the ints with a xor operation.
328 *
329 * @param input Input bytes
330 * @return an {@code int}.
331 */
332 static int byteArray2Int(byte[] input) {
333 int output = 0;
334
335 final int n = input.length;
336 // xor in the bits to an int in little-endian order
337 for (int i = 0; i < n; i++) {
338 // i = byte index
339 // i >> 2 = integer index
340 // i & 0x3 = byte number in the integer [0, 3]
341 // (i & 0x3) << 3 = little-endian byte shift to the integer {0, 8, 16, 24}
342 output ^= (input[i] & 0xff) << ((i & 0x3) << 3);
343 }
344
345 return output;
346 }
347
348 /**
349 * Creates an {@code int[]} value from a sequence of bytes. The ints are
350 * filled in little-endian order (least significant byte first).
351 *
352 * @param input Input bytes
353 * @param length Output array length
354 * @return a {@code int[]}.
355 */
356 static int[] byteArray2IntArray(byte[] input, int length) {
357 final int[] output = new int[length];
358
359 // Overflow-safe minimum using long
360 final int n = (int) Math.min(input.length, length * (long) Integer.BYTES);
361 // Little-endian fill
362 for (int i = 0; i < n; i++) {
363 // i = byte index
364 // i >> 2 = integer index
365 // i & 0x3 = byte number in the integer [0, 3]
366 // (i & 0x3) << 3 = little-endian byte shift to the integer {0, 8, 16, 24}
367 output[i >> 2] |= (input[i] & 0xff) << ((i & 0x3) << 3);
368 }
369
370 return output;
371 }
372
373 /**
374 * Creates a {@code long} value from a sequence of bytes. The conversion
375 * is made as if converting to a {@code long[]} array by filling the longs
376 * in little-endian order (least significant byte first), then combining
377 * all the longs with a xor operation.
378 *
379 * @param input Input bytes
380 * @return a {@code long}.
381 */
382 static long byteArray2Long(byte[] input) {
383 long output = 0;
384
385 final int n = input.length;
386 // xor in the bits to a long in little-endian order
387 for (int i = 0; i < n; i++) {
388 // i = byte index
389 // i >> 3 = long index
390 // i & 0x7 = byte number in the long [0, 7]
391 // (i & 0x7) << 3 = little-endian byte shift to the long {0, 8, 16, 24, 32, 36, 40, 48, 56}
392 output ^= (input[i] & 0xffL) << ((i & 0x7) << 3);
393 }
394
395 return output;
396 }
397
398 /**
399 * Creates a {@code long[]} value from a sequence of bytes. The longs are
400 * filled in little-endian order (least significant byte first).
401 *
402 * @param input Input bytes
403 * @param length Output array length
404 * @return a {@code long[]}.
405 */
406 static long[] byteArray2LongArray(byte[] input, int length) {
407 final long[] output = new long[length];
408
409 // Overflow-safe minimum using long
410 final int n = (int) Math.min(input.length, length * (long) Long.BYTES);
411 // Little-endian fill
412 for (int i = 0; i < n; i++) {
413 // i = byte index
414 // i >> 3 = long index
415 // i & 0x7 = byte number in the long [0, 7]
416 // (i & 0x7) << 3 = little-endian byte shift to the long {0, 8, 16, 24, 32, 36, 40, 48, 56}
417 output[i >> 3] |= (input[i] & 0xffL) << ((i & 0x7) << 3);
418 }
419
420 return output;
421 }
422 }