View Javadoc
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             final long x = MixFunctions.stafford13(v += GOLDEN_RATIO);
175             output[i] = (int) x;
176             output[i + 1] = (int) (x >>> 32);
177         }
178         // Final value
179         if (n < length) {
180             output[n] = (int) MixFunctions.stafford13(v + GOLDEN_RATIO);
181         }
182         return output;
183     }
184 
185     /**
186      * Creates a {@code long[]} value from a {@code long}. The conversion
187      * is made as if seeding a SplitMix64 RNG and calling nextLong() to
188      * generate the sequence.
189      *
190      * @param input Input
191      * @param length Array length
192      * @return a {@code long}.
193      */
194     static long[] long2LongArray(long input, int length) {
195         long v = input;
196         final long[] output = new long[length];
197         for (int i = 0; i < length; i++) {
198             output[i] = MixFunctions.stafford13(v += GOLDEN_RATIO);
199         }
200         return output;
201     }
202 
203     /**
204      * Creates an {@code int} value from a sequence of ints. The conversion
205      * is made by combining all the longs with a xor operation.
206      *
207      * @param input Input bytes
208      * @return an {@code int}.
209      */
210     static int intArray2Int(int[] input) {
211         int output = 0;
212         for (final int i : input) {
213             output ^= i;
214         }
215         return output;
216     }
217 
218     /**
219      * Creates a {@code long} value from a sequence of ints. The conversion
220      * is made as if converting to a {@code long[]} array by filling the longs
221      * in little-endian order (least significant byte first), then combining
222      * all the longs with a xor operation.
223      *
224      * @param input Input bytes
225      * @return a {@code long}.
226      */
227     static long intArray2Long(int[] input) {
228         long output = 0;
229 
230         final int n = input.length;
231         // xor in the bits to a long in little-endian order
232         for (int i = 0; i < n; i++) {
233             // i              = int index
234             // i >> 1         = long index
235             // i & 0x1        = int number in the long  [0, 1]
236             // (i & 0x1) << 5 = little-endian byte shift to the long {0, 32}
237             output ^= (input[i] & 0xffffffffL) << ((i & 0x1) << 5);
238         }
239 
240         return output;
241     }
242 
243     /**
244      * Creates a {@code long[]} value from a sequence of ints. The longs are
245      * filled in little-endian order (least significant byte first).
246      *
247      * @param input Input ints
248      * @param length Output array length
249      * @return a {@code long[]}.
250      */
251     static long[] intArray2LongArray(int[] input, int length) {
252         final long[] output = new long[length];
253 
254         // Overflow-safe minimum using long
255         final int n = (int) Math.min(input.length, length * 2L);
256         // Little-endian fill
257         for (int i = 0; i < n; i++) {
258             // i              = int index
259             // i >> 1         = long index
260             // i & 0x1        = int number in the long  [0, 1]
261             // (i & 0x1) << 5 = little-endian byte shift to the long {0, 32}
262             output[i >> 1] |= (input[i] & 0xffffffffL) << ((i & 0x1) << 5);
263         }
264 
265         return output;
266     }
267 
268     /**
269      * Creates an {@code int} value from a sequence of longs. The conversion
270      * is made as if combining all the longs with a xor operation, then folding
271      * the long high and low parts using a xor operation.
272      *
273      * @param input Input longs
274      * @return an {@code int}.
275      */
276     static int longArray2Int(long[] input) {
277         return Conversions.long2Int(longArray2Long(input));
278     }
279 
280     /**
281      * Creates a {@code long} value from a sequence of longs. The conversion
282      * is made by combining all the longs with a xor operation.
283      *
284      * @param input Input longs
285      * @return a {@code long}.
286      */
287     static long longArray2Long(long[] input) {
288         long output = 0;
289         for (final long i : input) {
290             output ^= i;
291         }
292         return output;
293     }
294 
295     /**
296      * Creates a {@code int[]} value from a sequence of longs. The ints are
297      * filled in little-endian order (least significant byte first).
298      *
299      * @param input Input longs
300      * @param length Output array length
301      * @return an {@code int[]}.
302      */
303     static int[] longArray2IntArray(long[] input, int length) {
304         final int[] output = new int[length];
305 
306         // Overflow-safe minimum using long
307         final int n = (int) Math.min(input.length * 2L, length);
308         // Little-endian fill
309         // Alternate low/high 32-bits from each long
310         for (int i = 0; i < n; i++) {
311             // i              = int index
312             // i >> 1         = long index
313             // i & 0x1        = int number in the long  [0, 1]
314             // (i & 0x1) << 5 = little-endian long shift to the int {0, 32}
315             output[i] = (int)((input[i >> 1]) >>> ((i & 0x1) << 5));
316         }
317 
318         return output;
319     }
320 
321     /**
322      * Creates an {@code int} value from a sequence of bytes. The conversion
323      * is made as if converting to a {@code int[]} array by filling the ints
324      * in little-endian order (least significant byte first), then combining
325      * all the ints with a xor operation.
326      *
327      * @param input Input bytes
328      * @return an {@code int}.
329      */
330     static int byteArray2Int(byte[] input) {
331         int output = 0;
332 
333         final int n = input.length;
334         // xor in the bits to an int in little-endian order
335         for (int i = 0; i < n; i++) {
336             // i              = byte index
337             // i >> 2         = integer index
338             // i & 0x3        = byte number in the integer  [0, 3]
339             // (i & 0x3) << 3 = little-endian byte shift to the integer {0, 8, 16, 24}
340             output ^= (input[i] & 0xff) << ((i & 0x3) << 3);
341         }
342 
343         return output;
344     }
345 
346     /**
347      * Creates an {@code int[]} value from a sequence of bytes. The ints are
348      * filled in little-endian order (least significant byte first).
349      *
350      * @param input Input bytes
351      * @param length Output array length
352      * @return a {@code int[]}.
353      */
354     static int[] byteArray2IntArray(byte[] input, int length) {
355         final int[] output = new int[length];
356 
357         // Overflow-safe minimum using long
358         final int n = (int) Math.min(input.length, length * (long) Integer.BYTES);
359         // Little-endian fill
360         for (int i = 0; i < n; i++) {
361             // i              = byte index
362             // i >> 2         = integer index
363             // i & 0x3        = byte number in the integer  [0, 3]
364             // (i & 0x3) << 3 = little-endian byte shift to the integer {0, 8, 16, 24}
365             output[i >> 2] |= (input[i] & 0xff) << ((i & 0x3) << 3);
366         }
367 
368         return output;
369     }
370 
371     /**
372      * Creates a {@code long} value from a sequence of bytes. The conversion
373      * is made as if converting to a {@code long[]} array by filling the longs
374      * in little-endian order (least significant byte first), then combining
375      * all the longs with a xor operation.
376      *
377      * @param input Input bytes
378      * @return a {@code long}.
379      */
380     static long byteArray2Long(byte[] input) {
381         long output = 0;
382 
383         final int n = input.length;
384         // xor in the bits to a long in little-endian order
385         for (int i = 0; i < n; i++) {
386             // i              = byte index
387             // i >> 3         = long index
388             // i & 0x7        = byte number in the long  [0, 7]
389             // (i & 0x7) << 3 = little-endian byte shift to the long {0, 8, 16, 24, 32, 36, 40, 48, 56}
390             output ^= (input[i] & 0xffL) << ((i & 0x7) << 3);
391         }
392 
393         return output;
394     }
395 
396     /**
397      * Creates a {@code long[]} value from a sequence of bytes. The longs are
398      * filled in little-endian order (least significant byte first).
399      *
400      * @param input Input bytes
401      * @param length Output array length
402      * @return a {@code long[]}.
403      */
404     static long[] byteArray2LongArray(byte[] input, int length) {
405         final long[] output = new long[length];
406 
407         // Overflow-safe minimum using long
408         final int n = (int) Math.min(input.length, length * (long) Long.BYTES);
409         // Little-endian fill
410         for (int i = 0; i < n; i++) {
411             // i              = byte index
412             // i >> 3         = long index
413             // i & 0x7        = byte number in the long  [0, 7]
414             // (i & 0x7) << 3 = little-endian byte shift to the long {0, 8, 16, 24, 32, 36, 40, 48, 56}
415             output[i >> 3] |= (input[i] & 0xffL) << ((i & 0x7) << 3);
416         }
417 
418         return output;
419     }
420 }