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 }