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             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 }