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 IllegalStateException if data is missing to initialize the 091 * generator implemented by the given {@code source}. 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 IllegalStateException if data is missing to initialize the 109 * generator implemented by the given {@code source}. 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 359 /** Source type. */ 360 private final Class<? extends UniformRandomProvider> rng; 361 /** Native seed size. Used for array seeds. */ 362 private final int nativeSeedSize; 363 /** Define the parameter types of the data needed to build the generator. */ 364 private final Class<?>[] args; 365 /** Native seed type. Used to create a seed or convert input seeds. */ 366 private final NativeSeedType nativeSeedType; 367 /** 368 * The constructor. 369 * This is discovered using the constructor parameter types and stored for re-use. 370 */ 371 private Constructor<?> rngConstructor; 372 373 /** 374 * Create a new instance. 375 * 376 * @param rng Source type. 377 * @param nativeSeedSize Native seed size (array types only). 378 * @param nativeSeedType Native seed type. 379 * @param args Additional data needed to create a generator instance. 380 */ 381 RandomSourceInternal(Class<? extends UniformRandomProvider> rng, 382 int nativeSeedSize, 383 NativeSeedType nativeSeedType, 384 Class<?>... args) { 385 this.rng = rng; 386 this.nativeSeedSize = nativeSeedSize; 387 this.nativeSeedType = nativeSeedType; 388 // Build the complete list of class types for the constructor 389 this.args = (Class<?>[]) Array.newInstance(args.getClass().getComponentType(), 1 + args.length); 390 this.args[0] = nativeSeedType.getType(); 391 System.arraycopy(args, 0, this.args, 1, args.length); 392 } 393 394 /** 395 * Gets the implementing class of the random source. 396 * 397 * @return the random source class. 398 */ 399 public Class<?> getRng() { 400 return rng; 401 } 402 403 /** 404 * Gets the class of the native seed. 405 * 406 * @return the seed class. 407 */ 408 Class<?> getSeed() { 409 return args[0]; 410 } 411 412 /** 413 * Gets the parameter types of the data needed to build the generator. 414 * 415 * @return the data needed to build the generator. 416 */ 417 Class<?>[] getArgs() { 418 return args; 419 } 420 421 /** 422 * Checks whether the type of given {@code seed} is the native type 423 * of the implementation. 424 * 425 * @param <SEED> Seed type. 426 * 427 * @param seed Seed value. 428 * @return {@code true} if the seed can be passed to the builder 429 * for this RNG type. 430 */ 431 public <SEED> boolean isNativeSeed(SEED seed) { 432 return seed != null && getSeed().equals(seed.getClass()); 433 } 434 435 /** 436 * Gets the number of seed bytes required to seed the implementing class represented by 437 * this random source. 438 * 439 * @return the number of seed bytes 440 */ 441 private int getSeedByteSize() { 442 return nativeSeedSize * nativeSeedType.getBytes(); 443 } 444 445 /** 446 * Creates a RNG instance. 447 * 448 * <p>This method can be over-ridden to allow fast construction of a generator 449 * with low seeding cost that has no additional constructor arguments.</p> 450 * 451 * @return a new RNG instance. 452 */ 453 RestorableUniformRandomProvider create() { 454 // Create a seed. 455 final Object nativeSeed = createSeed(); 456 // Instantiate. 457 return create(getConstructor(), new Object[] {nativeSeed}); 458 } 459 460 /** 461 * Creates a RNG instance. It is assumed the seed is not {@code null}. 462 * 463 * <p>This method can be over-ridden to allow fast construction of a generator 464 * with low seed conversion cost that has no additional constructor arguments.</p> 465 * 466 * @param seed Seed value. It must not be {@code null}. 467 * @return a new RNG instance. 468 * @throws UnsupportedOperationException if the seed type is invalid. 469 */ 470 RestorableUniformRandomProvider create(Object seed) { 471 // Convert seed to native type. 472 final Object nativeSeed = convertSeed(seed); 473 // Instantiate. 474 return create(getConstructor(), new Object[] {nativeSeed}); 475 } 476 477 /** 478 * Creates a RNG instance. This constructs a RNG using reflection and will error 479 * if the constructor arguments do not match those required by the RNG's constructor. 480 * 481 * @param seed Seed value. It can be {@code null} (in which case a suitable 482 * seed will be generated). 483 * @param constructorArgs Additional arguments to the implementation's constructor. 484 * It must not be {@code null}. 485 * @return a new RNG instance. 486 * @throws UnsupportedOperationException if the seed type is invalid. 487 */ 488 RestorableUniformRandomProvider create(Object seed, 489 Object[] constructorArgs) { 490 final Object nativeSeed = createNativeSeed(seed); 491 492 // Build a single array with all the arguments to be passed 493 // (in the right order) to the constructor. 494 Object[] all = new Object[constructorArgs.length + 1]; 495 all[0] = nativeSeed; 496 System.arraycopy(constructorArgs, 0, all, 1, constructorArgs.length); 497 498 // Instantiate. 499 return create(getConstructor(), all); 500 } 501 502 /** 503 * Creates a native seed. 504 * 505 * <p>The default implementation creates a seed of the native type and, for array seeds, 506 * ensures not all bits are zero.</p> 507 * 508 * <p>This method should be over-ridden to satisfy seed requirements for the generator.</p> 509 * 510 * @return the native seed 511 * @since 1.3 512 */ 513 protected Object createSeed() { 514 return nativeSeedType.createSeed(nativeSeedSize); 515 } 516 517 /** 518 * Creates a {@code byte[]} seed using the provided source of randomness. 519 * 520 * <p>The default implementation creates a full-length seed and ensures not all bits 521 * are zero.</p> 522 * 523 * <p>This method should be over-ridden to satisfy seed requirements for the generator.</p> 524 * 525 * @param source Source of randomness. 526 * @return the byte[] seed 527 * @since 1.3 528 */ 529 protected byte[] createByteArraySeed(UniformRandomProvider source) { 530 return SeedFactory.createByteArray(source, getSeedByteSize()); 531 } 532 533 /** 534 * Converts a seed from any of the supported seed types to a native seed. 535 * 536 * <p>The default implementation delegates to the native seed type conversion.</p> 537 * 538 * <p>This method should be over-ridden to satisfy seed requirements for the generator.</p> 539 * 540 * @param seed Input seed (must not be null). 541 * @return the native seed 542 * @throws UnsupportedOperationException if the {@code seed} type is invalid. 543 * @since 1.3 544 */ 545 protected Object convertSeed(Object seed) { 546 return nativeSeedType.convertSeed(seed, nativeSeedSize); 547 } 548 549 /** 550 * Creates a native seed from any of the supported seed types. 551 * 552 * @param seed Input seed (may be null). 553 * @return the native seed. 554 * @throws UnsupportedOperationException if the {@code seed} type cannot be converted. 555 */ 556 private Object createNativeSeed(Object seed) { 557 return seed == null ? 558 createSeed() : 559 convertSeed(seed); 560 } 561 562 /** 563 * Creates a seed suitable for the implementing class represented by this random source. 564 * 565 * <p>It will satisfy the seed size and any other seed requirements for the 566 * implementing class. The seed is converted from the native type to bytes.</p> 567 * 568 * @return the seed bytes 569 * @since 1.3 570 */ 571 public final byte[] createSeedBytes() { 572 // Custom implementations can override createSeed 573 final Object seed = createSeed(); 574 return NativeSeedType.convertSeedToBytes(seed); 575 } 576 577 /** 578 * Creates a seed suitable for the implementing class represented by this random source 579 * using the supplied source of randomness. 580 * 581 * <p>It will satisfy the seed size and any other seed requirements for the 582 * implementing class. The seed is converted from the native type to bytes.</p> 583 * 584 * @param source Source of randomness. 585 * @return the seed bytes 586 * @since 1.3 587 */ 588 public final byte[] createSeedBytes(UniformRandomProvider source) { 589 // Custom implementations can override createByteArraySeed 590 return createByteArraySeed(source); 591 } 592 593 /** 594 * Gets the constructor. 595 * 596 * @return the RNG constructor. 597 */ 598 private Constructor<?> getConstructor() { 599 // The constructor never changes so it is stored for re-use. 600 Constructor<?> constructor = rngConstructor; 601 if (constructor == null) { 602 // If null this is either the first attempt to find it or 603 // look-up previously failed and this method will throw 604 // upon each invocation. 605 constructor = createConstructor(); 606 rngConstructor = constructor; 607 } 608 return constructor; 609 } 610 611 /** 612 * Creates a constructor. 613 * 614 * @return a RNG constructor. 615 */ 616 private Constructor<?> createConstructor() { 617 try { 618 return getRng().getConstructor(getArgs()); 619 } catch (NoSuchMethodException e) { 620 // Info in "RandomSourceInternal" is inconsistent with the 621 // constructor of the implementation. 622 throw new IllegalStateException(INTERNAL_ERROR_MSG, e); 623 } 624 } 625 626 /** 627 * Creates a RNG. 628 * 629 * @param rng RNG specification. 630 * @param args Arguments to the implementation's constructor. 631 * @return a new RNG instance. 632 */ 633 private static RestorableUniformRandomProvider create(Constructor<?> rng, 634 Object[] args) { 635 try { 636 return (RestorableUniformRandomProvider) rng.newInstance(args); 637 } catch (InvocationTargetException e) { 638 throw new IllegalStateException(INTERNAL_ERROR_MSG, e); 639 } catch (InstantiationException e) { 640 throw new IllegalStateException(INTERNAL_ERROR_MSG, e); 641 } catch (IllegalAccessException e) { 642 throw new IllegalStateException(INTERNAL_ERROR_MSG, e); 643 } 644 } 645 } 646}