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 }