View Javadoc
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 }