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 import java.lang.reflect.Array;
20 import java.lang.reflect.Constructor;
21 import java.lang.reflect.InvocationTargetException;
22
23 import org.apache.commons.rng.UniformRandomProvider;
24 import org.apache.commons.rng.RestorableUniformRandomProvider;
25 import org.apache.commons.rng.core.source32.JDKRandom;
26 import org.apache.commons.rng.core.source32.Well512a;
27 import org.apache.commons.rng.core.source32.Well1024a;
28 import org.apache.commons.rng.core.source32.Well19937a;
29 import org.apache.commons.rng.core.source32.Well19937c;
30 import org.apache.commons.rng.core.source32.Well44497a;
31 import org.apache.commons.rng.core.source32.Well44497b;
32 import org.apache.commons.rng.core.source32.ISAACRandom;
33 import org.apache.commons.rng.core.source32.MersenneTwister;
34 import org.apache.commons.rng.core.source32.MiddleSquareWeylSequence;
35 import org.apache.commons.rng.core.source32.MultiplyWithCarry256;
36 import org.apache.commons.rng.core.source32.KISSRandom;
37 import org.apache.commons.rng.core.source32.XoRoShiRo64Star;
38 import org.apache.commons.rng.core.source32.XoRoShiRo64StarStar;
39 import org.apache.commons.rng.core.source32.XoShiRo128Plus;
40 import org.apache.commons.rng.core.source32.XoShiRo128PlusPlus;
41 import org.apache.commons.rng.core.source32.XoShiRo128StarStar;
42 import org.apache.commons.rng.core.source32.PcgXshRr32;
43 import org.apache.commons.rng.core.source32.PcgXshRs32;
44 import org.apache.commons.rng.core.source32.PcgMcgXshRr32;
45 import org.apache.commons.rng.core.source32.PcgMcgXshRs32;
46 import org.apache.commons.rng.core.source32.DotyHumphreySmallFastCounting32;
47 import org.apache.commons.rng.core.source32.JenkinsSmallFast32;
48 import org.apache.commons.rng.core.source64.SplitMix64;
49 import org.apache.commons.rng.core.source64.XorShift1024Star;
50 import org.apache.commons.rng.core.source64.XorShift1024StarPhi;
51 import org.apache.commons.rng.core.source64.TwoCmres;
52 import org.apache.commons.rng.core.source64.XoRoShiRo1024PlusPlus;
53 import org.apache.commons.rng.core.source64.XoRoShiRo1024Star;
54 import org.apache.commons.rng.core.source64.XoRoShiRo1024StarStar;
55 import org.apache.commons.rng.core.source64.MersenneTwister64;
56 import org.apache.commons.rng.core.source64.XoRoShiRo128Plus;
57 import org.apache.commons.rng.core.source64.XoRoShiRo128PlusPlus;
58 import org.apache.commons.rng.core.source64.XoRoShiRo128StarStar;
59 import org.apache.commons.rng.core.source64.XoShiRo256Plus;
60 import org.apache.commons.rng.core.source64.XoShiRo256PlusPlus;
61 import org.apache.commons.rng.core.source64.XoShiRo256StarStar;
62 import org.apache.commons.rng.core.source64.XoShiRo512Plus;
63 import org.apache.commons.rng.core.source64.XoShiRo512PlusPlus;
64 import org.apache.commons.rng.core.source64.XoShiRo512StarStar;
65 import org.apache.commons.rng.core.source64.PcgRxsMXs64;
66 import org.apache.commons.rng.core.source64.DotyHumphreySmallFastCounting64;
67 import org.apache.commons.rng.core.source64.JenkinsSmallFast64;
68
69 /**
70 * RNG builder.
71 * <p>
72 * It uses reflection to find the factory method of the RNG implementation,
73 * and performs seed type conversions.
74 * </p>
75 */
76 public final class ProviderBuilder {
77 /** Error message. */
78 private static final String INTERNAL_ERROR_MSG = "Internal error: Please file a bug report";
79
80 /**
81 * Class only contains static method.
82 */
83 private ProviderBuilder() {}
84
85 /**
86 * Creates a RNG instance.
87 *
88 * @param source RNG specification.
89 * @return a new RNG instance.
90 * @throws IllegalStateException if data is missing to initialize the
91 * generator implemented by the given {@code source}.
92 * @since 1.3
93 */
94 public static RestorableUniformRandomProvider create(RandomSourceInternal source) {
95 // Delegate to the random source allowing generator specific implementations.
96 return source.create();
97 }
98
99 /**
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 }