001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.rng.simple.internal; 018 019import java.lang.reflect.Array; 020import java.lang.reflect.Constructor; 021import java.lang.reflect.InvocationTargetException; 022 023import org.apache.commons.rng.UniformRandomProvider; 024import org.apache.commons.rng.RestorableUniformRandomProvider; 025import org.apache.commons.rng.core.source32.JDKRandom; 026import org.apache.commons.rng.core.source32.Well512a; 027import org.apache.commons.rng.core.source32.Well1024a; 028import org.apache.commons.rng.core.source32.Well19937a; 029import org.apache.commons.rng.core.source32.Well19937c; 030import org.apache.commons.rng.core.source32.Well44497a; 031import org.apache.commons.rng.core.source32.Well44497b; 032import org.apache.commons.rng.core.source32.ISAACRandom; 033import org.apache.commons.rng.core.source32.MersenneTwister; 034import org.apache.commons.rng.core.source32.MiddleSquareWeylSequence; 035import org.apache.commons.rng.core.source32.MultiplyWithCarry256; 036import org.apache.commons.rng.core.source32.KISSRandom; 037import org.apache.commons.rng.core.source32.XoRoShiRo64Star; 038import org.apache.commons.rng.core.source32.XoRoShiRo64StarStar; 039import org.apache.commons.rng.core.source32.XoShiRo128Plus; 040import org.apache.commons.rng.core.source32.XoShiRo128PlusPlus; 041import org.apache.commons.rng.core.source32.XoShiRo128StarStar; 042import org.apache.commons.rng.core.source32.PcgXshRr32; 043import org.apache.commons.rng.core.source32.PcgXshRs32; 044import org.apache.commons.rng.core.source32.PcgMcgXshRr32; 045import org.apache.commons.rng.core.source32.PcgMcgXshRs32; 046import org.apache.commons.rng.core.source32.DotyHumphreySmallFastCounting32; 047import org.apache.commons.rng.core.source32.JenkinsSmallFast32; 048import org.apache.commons.rng.core.source64.SplitMix64; 049import org.apache.commons.rng.core.source64.XorShift1024Star; 050import org.apache.commons.rng.core.source64.XorShift1024StarPhi; 051import org.apache.commons.rng.core.source64.TwoCmres; 052import org.apache.commons.rng.core.source64.XoRoShiRo1024PlusPlus; 053import org.apache.commons.rng.core.source64.XoRoShiRo1024Star; 054import org.apache.commons.rng.core.source64.XoRoShiRo1024StarStar; 055import org.apache.commons.rng.core.source64.MersenneTwister64; 056import org.apache.commons.rng.core.source64.XoRoShiRo128Plus; 057import org.apache.commons.rng.core.source64.XoRoShiRo128PlusPlus; 058import org.apache.commons.rng.core.source64.XoRoShiRo128StarStar; 059import org.apache.commons.rng.core.source64.XoShiRo256Plus; 060import org.apache.commons.rng.core.source64.XoShiRo256PlusPlus; 061import org.apache.commons.rng.core.source64.XoShiRo256StarStar; 062import org.apache.commons.rng.core.source64.XoShiRo512Plus; 063import org.apache.commons.rng.core.source64.XoShiRo512PlusPlus; 064import org.apache.commons.rng.core.source64.XoShiRo512StarStar; 065import org.apache.commons.rng.core.source64.PcgRxsMXs64; 066import org.apache.commons.rng.core.source64.DotyHumphreySmallFastCounting64; 067import org.apache.commons.rng.core.source64.JenkinsSmallFast64; 068 069/** 070 * RNG builder. 071 * <p> 072 * It uses reflection to find the factory method of the RNG implementation, 073 * and performs seed type conversions. 074 * </p> 075 */ 076public final class ProviderBuilder { 077 /** Error message. */ 078 private static final String INTERNAL_ERROR_MSG = "Internal error: Please file a bug report"; 079 080 /** 081 * Class only contains static method. 082 */ 083 private ProviderBuilder() {} 084 085 /** 086 * Creates a RNG instance. 087 * 088 * @param source RNG specification. 089 * @return a new RNG instance. 090 * @throws IllegalArgumentException if argument data to initialize the 091 * generator implemented by the given {@code source} is missing. 092 * @since 1.3 093 */ 094 public static RestorableUniformRandomProvider create(RandomSourceInternal source) { 095 // Delegate to the random source allowing generator specific implementations. 096 return source.create(); 097 } 098 099 /** 100 * Creates a RNG instance. 101 * 102 * @param source RNG specification. 103 * @param seed Seed value. It can be {@code null} (in which case a 104 * random value will be used). 105 * @param args Additional arguments to the implementation's constructor. 106 * @return a new RNG instance. 107 * @throws UnsupportedOperationException if the seed type is invalid. 108 * @throws IllegalArgumentException if argument data to initialize the 109 * generator implemented by the given {@code source} is invalid. 110 */ 111 public static RestorableUniformRandomProvider create(RandomSourceInternal source, 112 Object seed, 113 Object[] args) { 114 // Delegate to the random source allowing generator specific implementations. 115 // This method checks arguments for null and calls the appropriate internal method. 116 if (args != null) { 117 return source.create(seed, args); 118 } 119 return seed == null ? 120 source.create() : 121 source.create(seed); 122 } 123 124 /** 125 * Identifiers of the generators. 126 */ 127 public enum RandomSourceInternal { 128 /** Source of randomness is {@link JDKRandom}. */ 129 JDK(JDKRandom.class, 130 1, 131 NativeSeedType.LONG), 132 /** Source of randomness is {@link Well512a}. */ 133 WELL_512_A(Well512a.class, 134 16, 135 NativeSeedType.INT_ARRAY), 136 /** Source of randomness is {@link Well1024a}. */ 137 WELL_1024_A(Well1024a.class, 138 32, 139 NativeSeedType.INT_ARRAY), 140 /** Source of randomness is {@link Well19937a}. */ 141 WELL_19937_A(Well19937a.class, 142 624, 143 NativeSeedType.INT_ARRAY), 144 /** Source of randomness is {@link Well19937c}. */ 145 WELL_19937_C(Well19937c.class, 146 624, 147 NativeSeedType.INT_ARRAY), 148 /** Source of randomness is {@link Well44497a}. */ 149 WELL_44497_A(Well44497a.class, 150 1391, 151 NativeSeedType.INT_ARRAY), 152 /** Source of randomness is {@link Well44497b}. */ 153 WELL_44497_B(Well44497b.class, 154 1391, 155 NativeSeedType.INT_ARRAY), 156 /** Source of randomness is {@link MersenneTwister}. */ 157 MT(MersenneTwister.class, 158 624, 159 NativeSeedType.INT_ARRAY), 160 /** Source of randomness is {@link ISAACRandom}. */ 161 ISAAC(ISAACRandom.class, 162 256, 163 NativeSeedType.INT_ARRAY), 164 /** Source of randomness is {@link SplitMix64}. */ 165 SPLIT_MIX_64(SplitMix64.class, 166 1, 167 NativeSeedType.LONG), 168 /** Source of randomness is {@link XorShift1024Star}. */ 169 XOR_SHIFT_1024_S(XorShift1024Star.class, 170 16, 171 NativeSeedType.LONG_ARRAY), 172 /** Source of randomness is {@link TwoCmres}. */ 173 TWO_CMRES(TwoCmres.class, 174 1, 175 NativeSeedType.INT), 176 /** 177 * Source of randomness is {@link TwoCmres} with explicit selection 178 * of the two subcycle generators. 179 */ 180 TWO_CMRES_SELECT(TwoCmres.class, 181 1, 182 NativeSeedType.INT, 183 Integer.TYPE, 184 Integer.TYPE), 185 /** Source of randomness is {@link MersenneTwister64}. */ 186 MT_64(MersenneTwister64.class, 187 312, 188 NativeSeedType.LONG_ARRAY), 189 /** Source of randomness is {@link MultiplyWithCarry256}. */ 190 MWC_256(MultiplyWithCarry256.class, 191 257, 192 NativeSeedType.INT_ARRAY), 193 /** Source of randomness is {@link KISSRandom}. */ 194 KISS(KISSRandom.class, 195 4, 196 NativeSeedType.INT_ARRAY), 197 /** Source of randomness is {@link XorShift1024StarPhi}. */ 198 XOR_SHIFT_1024_S_PHI(XorShift1024StarPhi.class, 199 16, 200 NativeSeedType.LONG_ARRAY), 201 /** Source of randomness is {@link XoRoShiRo64Star}. */ 202 XO_RO_SHI_RO_64_S(XoRoShiRo64Star.class, 203 2, 204 NativeSeedType.INT_ARRAY), 205 /** Source of randomness is {@link XoRoShiRo64StarStar}. */ 206 XO_RO_SHI_RO_64_SS(XoRoShiRo64StarStar.class, 207 2, 208 NativeSeedType.INT_ARRAY), 209 /** Source of randomness is {@link XoShiRo128Plus}. */ 210 XO_SHI_RO_128_PLUS(XoShiRo128Plus.class, 211 4, 212 NativeSeedType.INT_ARRAY), 213 /** Source of randomness is {@link XoShiRo128StarStar}. */ 214 XO_SHI_RO_128_SS(XoShiRo128StarStar.class, 215 4, 216 NativeSeedType.INT_ARRAY), 217 /** Source of randomness is {@link XoRoShiRo128Plus}. */ 218 XO_RO_SHI_RO_128_PLUS(XoRoShiRo128Plus.class, 219 2, 220 NativeSeedType.LONG_ARRAY), 221 /** Source of randomness is {@link XoRoShiRo128StarStar}. */ 222 XO_RO_SHI_RO_128_SS(XoRoShiRo128StarStar.class, 223 2, 224 NativeSeedType.LONG_ARRAY), 225 /** Source of randomness is {@link XoShiRo256Plus}. */ 226 XO_SHI_RO_256_PLUS(XoShiRo256Plus.class, 227 4, 228 NativeSeedType.LONG_ARRAY), 229 /** Source of randomness is {@link XoShiRo256StarStar}. */ 230 XO_SHI_RO_256_SS(XoShiRo256StarStar.class, 231 4, 232 NativeSeedType.LONG_ARRAY), 233 /** Source of randomness is {@link XoShiRo512Plus}. */ 234 XO_SHI_RO_512_PLUS(XoShiRo512Plus.class, 235 8, 236 NativeSeedType.LONG_ARRAY), 237 /** Source of randomness is {@link XoShiRo512StarStar}. */ 238 XO_SHI_RO_512_SS(XoShiRo512StarStar.class, 239 8, 240 NativeSeedType.LONG_ARRAY), 241 /** Source of randomness is {@link PcgXshRr32}. */ 242 PCG_XSH_RR_32(PcgXshRr32.class, 243 2, 244 NativeSeedType.LONG_ARRAY), 245 /** Source of randomness is {@link PcgXshRs32}. */ 246 PCG_XSH_RS_32(PcgXshRs32.class, 247 2, 248 NativeSeedType.LONG_ARRAY), 249 /** Source of randomness is {@link PcgRxsMXs64}. */ 250 PCG_RXS_M_XS_64(PcgRxsMXs64.class, 251 2, 252 NativeSeedType.LONG_ARRAY), 253 /** Source of randomness is {@link PcgMcgXshRr32}. */ 254 PCG_MCG_XSH_RR_32(PcgMcgXshRr32.class, 255 1, 256 NativeSeedType.LONG), 257 /** Source of randomness is {@link PcgMcgXshRs32}. */ 258 PCG_MCG_XSH_RS_32(PcgMcgXshRs32.class, 259 1, 260 NativeSeedType.LONG), 261 /** Source of randomness is {@link MiddleSquareWeylSequence}. */ 262 MSWS(MiddleSquareWeylSequence.class, 263 3, 264 NativeSeedType.LONG_ARRAY) { 265 @Override 266 protected Object createSeed() { 267 return createMswsSeed(SeedFactory.createLong()); 268 } 269 270 @Override 271 protected Object convertSeed(Object seed) { 272 // Allow seeding with primitives to generate a good seed 273 if (seed instanceof Integer) { 274 return createMswsSeed((Integer) seed); 275 } else if (seed instanceof Long) { 276 return createMswsSeed((Long) seed); 277 } 278 // Other types (e.g. the native long[]) are handled by the default conversion 279 return super.convertSeed(seed); 280 } 281 282 @Override 283 protected byte[] createByteArraySeed(UniformRandomProvider source) { 284 return NativeSeedType.convertSeedToBytes(createMswsSeed(source)); 285 } 286 287 /** 288 * Creates the full length seed array from the input seed. 289 * 290 * @param seed the seed 291 * @return the seed array 292 */ 293 private long[] createMswsSeed(long seed) { 294 return createMswsSeed(new SplitMix64(seed)); 295 } 296 297 /** 298 * Creates the full length seed array from the input seed using the method 299 * recommended for the generator. This is a high quality Weyl increment composed 300 * of a hex character permutation. 301 * 302 * @param source Source of randomness. 303 * @return the seed array 304 */ 305 private long[] createMswsSeed(UniformRandomProvider source) { 306 final long increment = SeedUtils.createLongHexPermutation(source); 307 // The initial state should not be low complexity but the Weyl 308 // state can be any number. 309 final long state = increment; 310 final long weylState = source.nextLong(); 311 return new long[] {state, weylState, increment}; 312 } 313 }, 314 /** Source of randomness is {@link DotyHumphreySmallFastCounting32}. */ 315 SFC_32(DotyHumphreySmallFastCounting32.class, 316 3, 317 NativeSeedType.INT_ARRAY), 318 /** Source of randomness is {@link DotyHumphreySmallFastCounting64}. */ 319 SFC_64(DotyHumphreySmallFastCounting64.class, 320 3, 321 NativeSeedType.LONG_ARRAY), 322 /** Source of randomness is {@link JenkinsSmallFast32}. */ 323 JSF_32(JenkinsSmallFast32.class, 324 1, 325 NativeSeedType.INT), 326 /** Source of randomness is {@link JenkinsSmallFast64}. */ 327 JSF_64(JenkinsSmallFast64.class, 328 1, 329 NativeSeedType.LONG), 330 /** Source of randomness is {@link XoShiRo128PlusPlus}. */ 331 XO_SHI_RO_128_PP(XoShiRo128PlusPlus.class, 332 4, 333 NativeSeedType.INT_ARRAY), 334 /** Source of randomness is {@link XoRoShiRo128PlusPlus}. */ 335 XO_RO_SHI_RO_128_PP(XoRoShiRo128PlusPlus.class, 336 2, 337 NativeSeedType.LONG_ARRAY), 338 /** Source of randomness is {@link XoShiRo256PlusPlus}. */ 339 XO_SHI_RO_256_PP(XoShiRo256PlusPlus.class, 340 4, 341 NativeSeedType.LONG_ARRAY), 342 /** Source of randomness is {@link XoShiRo512PlusPlus}. */ 343 XO_SHI_RO_512_PP(XoShiRo512PlusPlus.class, 344 8, 345 NativeSeedType.LONG_ARRAY), 346 /** Source of randomness is {@link XoRoShiRo1024PlusPlus}. */ 347 XO_RO_SHI_RO_1024_PP(XoRoShiRo1024PlusPlus.class, 348 16, 349 NativeSeedType.LONG_ARRAY), 350 /** Source of randomness is {@link XoRoShiRo1024Star}. */ 351 XO_RO_SHI_RO_1024_S(XoRoShiRo1024Star.class, 352 16, 353 NativeSeedType.LONG_ARRAY), 354 /** Source of randomness is {@link XoRoShiRo1024StarStar}. */ 355 XO_RO_SHI_RO_1024_SS(XoRoShiRo1024StarStar.class, 356 16, 357 NativeSeedType.LONG_ARRAY), 358 /** Source of randomness is {@link PcgXshRr32}. */ 359 PCG_XSH_RR_32_OS(PcgXshRr32.class, 360 1, 361 NativeSeedType.LONG), 362 /** Source of randomness is {@link PcgXshRs32}. */ 363 PCG_XSH_RS_32_OS(PcgXshRs32.class, 364 1, 365 NativeSeedType.LONG), 366 /** Source of randomness is {@link PcgRxsMXs64}. */ 367 PCG_RXS_M_XS_64_OS(PcgRxsMXs64.class, 368 1, 369 NativeSeedType.LONG); 370 371 /** Source type. */ 372 private final Class<? extends UniformRandomProvider> rng; 373 /** Native seed size. Used for array seeds. */ 374 private final int nativeSeedSize; 375 /** Define the parameter types of the data needed to build the generator. */ 376 private final Class<?>[] args; 377 /** Native seed type. Used to create a seed or convert input seeds. */ 378 private final NativeSeedType nativeSeedType; 379 /** 380 * The constructor. 381 * This is discovered using the constructor parameter types and stored for re-use. 382 */ 383 private Constructor<?> rngConstructor; 384 385 /** 386 * Create a new instance. 387 * 388 * @param rng Source type. 389 * @param nativeSeedSize Native seed size (array types only). 390 * @param nativeSeedType Native seed type. 391 * @param args Additional data needed to create a generator instance. 392 */ 393 RandomSourceInternal(Class<? extends UniformRandomProvider> rng, 394 int nativeSeedSize, 395 NativeSeedType nativeSeedType, 396 Class<?>... args) { 397 this.rng = rng; 398 this.nativeSeedSize = nativeSeedSize; 399 this.nativeSeedType = nativeSeedType; 400 // Build the complete list of class types for the constructor 401 this.args = (Class<?>[]) Array.newInstance(args.getClass().getComponentType(), 1 + args.length); 402 this.args[0] = nativeSeedType.getType(); 403 System.arraycopy(args, 0, this.args, 1, args.length); 404 } 405 406 /** 407 * Gets the implementing class of the random source. 408 * 409 * @return the random source class. 410 */ 411 public Class<?> getRng() { 412 return rng; 413 } 414 415 /** 416 * Gets the class of the native seed. 417 * 418 * @return the seed class. 419 */ 420 Class<?> getSeed() { 421 return args[0]; 422 } 423 424 /** 425 * Gets the parameter types of the data needed to build the generator. 426 * 427 * @return the data needed to build the generator. 428 */ 429 Class<?>[] getArgs() { 430 return args; 431 } 432 433 /** 434 * Checks whether the type of given {@code seed} is the native type 435 * of the implementation. 436 * 437 * @param <SEED> Seed type. 438 * 439 * @param seed Seed value. 440 * @return {@code true} if the seed can be passed to the builder 441 * for this RNG type. 442 */ 443 public <SEED> boolean isNativeSeed(SEED seed) { 444 return seed != null && getSeed().equals(seed.getClass()); 445 } 446 447 /** 448 * Gets the number of seed bytes required to seed the implementing class represented by 449 * this random source. 450 * 451 * @return the number of seed bytes 452 */ 453 private int getSeedByteSize() { 454 return nativeSeedSize * nativeSeedType.getBytes(); 455 } 456 457 /** 458 * Creates a RNG instance. 459 * 460 * <p>This method can be over-ridden to allow fast construction of a generator 461 * with low seeding cost that has no additional constructor arguments.</p> 462 * 463 * @return a new RNG instance. 464 */ 465 RestorableUniformRandomProvider create() { 466 // Create a seed. 467 final Object nativeSeed = createSeed(); 468 // Instantiate. 469 return create(getConstructor(), new Object[] {nativeSeed}); 470 } 471 472 /** 473 * Creates a RNG instance. It is assumed the seed is not {@code null}. 474 * 475 * <p>This method can be over-ridden to allow fast construction of a generator 476 * with low seed conversion cost that has no additional constructor arguments.</p> 477 * 478 * @param seed Seed value. It must not be {@code null}. 479 * @return a new RNG instance. 480 * @throws UnsupportedOperationException if the seed type is invalid. 481 */ 482 RestorableUniformRandomProvider create(Object seed) { 483 // Convert seed to native type. 484 final Object nativeSeed = convertSeed(seed); 485 // Instantiate. 486 return create(getConstructor(), new Object[] {nativeSeed}); 487 } 488 489 /** 490 * Creates a RNG instance. This constructs a RNG using reflection and will error 491 * if the constructor arguments do not match those required by the RNG's constructor. 492 * 493 * @param seed Seed value. It can be {@code null} (in which case a suitable 494 * seed will be generated). 495 * @param constructorArgs Additional arguments to the implementation's constructor. 496 * It must not be {@code null}. 497 * @return a new RNG instance. 498 * @throws UnsupportedOperationException if the seed type is invalid. 499 */ 500 RestorableUniformRandomProvider create(Object seed, 501 Object[] constructorArgs) { 502 final Object nativeSeed = createNativeSeed(seed); 503 504 // Build a single array with all the arguments to be passed 505 // (in the right order) to the constructor. 506 Object[] all = new Object[constructorArgs.length + 1]; 507 all[0] = nativeSeed; 508 System.arraycopy(constructorArgs, 0, all, 1, constructorArgs.length); 509 510 // Instantiate. 511 return create(getConstructor(), all); 512 } 513 514 /** 515 * Creates a native seed. 516 * 517 * <p>The default implementation creates a seed of the native type and, for array seeds, 518 * ensures not all bits are zero.</p> 519 * 520 * <p>This method should be over-ridden to satisfy seed requirements for the generator.</p> 521 * 522 * @return the native seed 523 * @since 1.3 524 */ 525 protected Object createSeed() { 526 return nativeSeedType.createSeed(nativeSeedSize); 527 } 528 529 /** 530 * Creates a {@code byte[]} seed using the provided source of randomness. 531 * 532 * <p>The default implementation creates a full-length seed and ensures not all bits 533 * are zero.</p> 534 * 535 * <p>This method should be over-ridden to satisfy seed requirements for the generator.</p> 536 * 537 * @param source Source of randomness. 538 * @return the byte[] seed 539 * @since 1.3 540 */ 541 protected byte[] createByteArraySeed(UniformRandomProvider source) { 542 return SeedFactory.createByteArray(source, getSeedByteSize()); 543 } 544 545 /** 546 * Converts a seed from any of the supported seed types to a native seed. 547 * 548 * <p>The default implementation delegates to the native seed type conversion.</p> 549 * 550 * <p>This method should be over-ridden to satisfy seed requirements for the generator.</p> 551 * 552 * @param seed Input seed (must not be null). 553 * @return the native seed 554 * @throws UnsupportedOperationException if the {@code seed} type is invalid. 555 * @since 1.3 556 */ 557 protected Object convertSeed(Object seed) { 558 return nativeSeedType.convertSeed(seed, nativeSeedSize); 559 } 560 561 /** 562 * Creates a native seed from any of the supported seed types. 563 * 564 * @param seed Input seed (may be null). 565 * @return the native seed. 566 * @throws UnsupportedOperationException if the {@code seed} type cannot be converted. 567 */ 568 private Object createNativeSeed(Object seed) { 569 return seed == null ? 570 createSeed() : 571 convertSeed(seed); 572 } 573 574 /** 575 * Creates a seed suitable for the implementing class represented by this random source. 576 * 577 * <p>It will satisfy the seed size and any other seed requirements for the 578 * implementing class. The seed is converted from the native type to bytes.</p> 579 * 580 * @return the seed bytes 581 * @since 1.3 582 */ 583 public final byte[] createSeedBytes() { 584 // Custom implementations can override createSeed 585 final Object seed = createSeed(); 586 return NativeSeedType.convertSeedToBytes(seed); 587 } 588 589 /** 590 * Creates a seed suitable for the implementing class represented by this random source 591 * using the supplied source of randomness. 592 * 593 * <p>It will satisfy the seed size and any other seed requirements for the 594 * implementing class. The seed is converted from the native type to bytes.</p> 595 * 596 * @param source Source of randomness. 597 * @return the seed bytes 598 * @since 1.3 599 */ 600 public final byte[] createSeedBytes(UniformRandomProvider source) { 601 // Custom implementations can override createByteArraySeed 602 return createByteArraySeed(source); 603 } 604 605 /** 606 * Gets the constructor. 607 * 608 * @return the RNG constructor. 609 */ 610 private Constructor<?> getConstructor() { 611 // The constructor never changes so it is stored for re-use. 612 Constructor<?> constructor = rngConstructor; 613 if (constructor == null) { 614 // If null this is either the first attempt to find it or 615 // look-up previously failed and this method will throw 616 // upon each invocation. 617 constructor = createConstructor(); 618 rngConstructor = constructor; 619 } 620 return constructor; 621 } 622 623 /** 624 * Creates a constructor. 625 * 626 * @return a RNG constructor. 627 */ 628 private Constructor<?> createConstructor() { 629 try { 630 return getRng().getConstructor(getArgs()); 631 } catch (NoSuchMethodException e) { 632 // Info in "RandomSourceInternal" is inconsistent with the 633 // constructor of the implementation. 634 throw new IllegalStateException(INTERNAL_ERROR_MSG, e); 635 } 636 } 637 638 /** 639 * Creates a RNG. 640 * 641 * @param rng RNG specification. 642 * @param args Arguments to the implementation's constructor. 643 * @return a new RNG instance. 644 */ 645 private static RestorableUniformRandomProvider create(Constructor<?> rng, 646 Object[] args) { 647 try { 648 return (RestorableUniformRandomProvider) rng.newInstance(args); 649 } catch (InvocationTargetException | InstantiationException | IllegalAccessException e) { 650 throw new IllegalStateException(INTERNAL_ERROR_MSG, e); 651 } 652 } 653 } 654}