Enum RandomSource

  • All Implemented Interfaces:
    Serializable, Comparable<RandomSource>

    public enum RandomSource
    extends Enum<RandomSource>
    This class provides the API for creating generators of random numbers.

    Usage examples:

    
      UniformRandomProvider rng = RandomSource.XO_RO_SHI_RO_128_PP.create();
     
    or
    
      final int[] seed = new int[] { 196, 9, 0, 226 };
      UniformRandomProvider rng = RandomSource.XO_RO_SHI_RO_128_PP.create(seed);
     
    or
    
      final int[] seed = RandomSource.createIntArray(256);
      UniformRandomProvider rng = RandomSource.XO_RO_SHI_RO_128_PP.create(seed);
     
    where the enum value is the identifier of the generator's concrete implementation, and the argument to method create is the (optional) seed.

    In the first form, a random seed will be generated automatically; in the second form, a fixed seed is used; a random seed is explicitly generated in the third form.

    Seeding

    Seeding is the procedure by which a value (or set of values) is used to initialize a generator instance. The requirement that a given seed will always result in the same internal state allows to create different instances of a generator that will produce the same sequence of pseudo-random numbers.

    The type of data used as a seed depends on the concrete implementation as some types may not provide enough information to fully initialize the generator's internal state.
    The reference algorithm's seeding procedure (if provided) operates on a value of a (single) native type: Each concrete implementation's constructor creates an instance using the native type whose information contents is used to set the internal state.
    When the seed value passed by the caller is of the native type, it is expected that the sequences produced will be identical to those produced by other implementations of the same reference algorithm.
    However, when the seed value passed by the caller is not of the native type, a transformation is performed by this library and the resulting native type value will not contain more information than the original seed value. If the algorithm's native type is "simpler" than the type passed by the caller, then some (unused) information will even be lost.
    The transformation from non-native to native seed type is arbitrary, as long as it does not reduce the amount of information required by the algorithm to initialize its state. The consequence of the transformation is that sequences produced by this library may not be the same as the sequences produced by other implementations of the same algorithm!

    For each algorithm, the Javadoc mentions the "ideal" size of the seed, meaning the number of int or long values that is neither too large (i.e. some of the seed is useless) or too small (i.e. an internal procedure will fill the state with redundant information computed from the given seed).

    Note that some algorithms are inherently sensitive to having too low diversity in their initial state. For example, it is often a bad idea to use a seed that is mostly composed of zeroes, or of repeated values.

    This class provides methods to generate random seeds (single values or arrays of values, of int or long types) that can be passed to the generator's factory method.

    Although the seed-generating methods defined in this class will likely return different values each time they are called, there is no guarantee:

    • In any sub-sequence, it is expected that the same numbers can occur, with a probability getting higher as the range of allowed values is smaller and the sequence becomes longer.
    • It possible that the resulting "seed" will not be good (i.e. it will not generate a sufficiently uniformly random sequence for the intended purpose), even if the generator is good! The only way to ensure that the selected seed will make the generator produce a good sequence is to submit that sequence to a series of stringent tests, as provided by tools such as dieharder or TestU01.

    Note: Seeding is not equivalent to restoring the internal state of an already initialized generator. Indeed, generators can have a state that is more complex than the seed, and seeding is thus a transformation (from seed to state). Implementations do not provide the inverse transformation (from state to seed), hence it is not generally possible to know the seed that would initialize a new generator instance to the current state of another instance. Reseeding is also inefficient if the purpose is to continue the same sequence where another instance left off, as it would require to "replay" all the calls performed by that other instance (and it would require to know the number of calls to the primary source of randomness, which is also not usually accessible).

    Parallel applications

    For parallel applications, some implementations have provision for producing non-overlapping sequences by copying the generator and then advancing a large number of steps in the generator sequence. Repeated jumps can create a series of child generators that will output non-overlapping sequences over a specified number of outputs. These implementations are identified using the isJumpable() and isLongJumpable() methods.

    
      RandomSource source = RandomSource.XO_RO_SHI_RO_128_SS; // Known to be jumpable.
    
      JumpableUniformRandomProvider jumpable = (JumpableUniformRandomProvider) source.create();
    
      // For use in parallel
      UniformRandomProvider[] rngs = new UniformRandomProvider[10];
      for (int i = 0; i < rngs.length; i++) {
          rngs[i] = jumpable.jump();
      }
     

    For implementations that have no provision for producing non-overlapping sequences, a possible workaround is that each thread uses a generator of a different type (see TWO_CMRES_SELECT).

    Since:
    1.0
    • Method Detail

      • values

        public static RandomSource[] values()
        Returns an array containing the constants of this enum type, in the order they are declared. This method may be used to iterate over the constants as follows:
        for (RandomSource c : RandomSource.values())
            System.out.println(c);
        
        Returns:
        an array containing the constants of this enum type, in the order they are declared
      • valueOf

        public static RandomSource valueOf​(String name)
        Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
        Parameters:
        name - the name of the enum constant to be returned.
        Returns:
        the enum constant with the specified name
        Throws:
        IllegalArgumentException - if this enum type has no constant with the specified name
        NullPointerException - if the argument is null
      • isNativeSeed

        public boolean isNativeSeed​(Object seed)
        Checks whether the type of given seed is the native type of the implementation.
        Parameters:
        seed - Seed value.
        Returns:
        true if the type of seed is the native type for this RNG source.
      • createSeed

        public byte[] createSeed()
        Creates a seed suitable for the implementing class represented by this random source.

        The seed will be created as if passing a null seed to the method create(Object, Object...). It will satisfy the seed size and any other seed requirements for the implementing class. The seed is converted from the native type to a byte representation.

        Usage example:

        
          RandomSource source = ...;
          byte[] seed = source.createSeed();
          UniformRandomProvider rng = source.create(seed);
         
        Returns:
        the seed
        Since:
        1.3
      • createSeed

        public byte[] createSeed​(UniformRandomProvider rng)
        Creates a seed suitable for the implementing class represented by this random source using the supplied source of randomness.

        The seed will satisfy the seed size and any other seed requirements for the implementing class.

        Usage example:

        
          RandomSource source = ...;
          UniformRandomProvider seedRng = new JDKRandomWrapper(new SecureRandom());
          byte[] seed = source.createSeed(seedRng);
          UniformRandomProvider rng = source.create(seed);
         
        Parameters:
        rng - Source of randomness.
        Returns:
        the seed
        Since:
        1.3
      • isJumpable

        public boolean isJumpable()
        Checks whether the implementing class represented by this random source supports the JumpableUniformRandomProvider interface. If true the instance returned by create(RandomSource) may be cast to the interface; otherwise a class cast exception will occur.

        Usage example:

        
          RandomSource source = ...;
          if (source.isJumpable()) {
              JumpableUniformRandomProvider rng =
                  (JumpableUniformRandomProvider) source.create();
          }
         
        Returns:
        true if jumpable
        Since:
        1.3
      • isLongJumpable

        public boolean isLongJumpable()
        Checks whether the implementing class represented by this random source supports the LongJumpableUniformRandomProvider interface. If true the instance returned by create(RandomSource) may be cast to the interface; otherwise a class cast exception will occur.

        Usage example:

        
          RandomSource source = ...;
          if (source.isJumpable()) {
              LongJumpableUniformRandomProvider rng =
                  (LongJumpableUniformRandomProvider) source.create();
          }
         
        Returns:
        true if long jumpable
        Since:
        1.3
      • isSplittable

        public boolean isSplittable()
        Checks whether the implementing class represented by this random source supports the SplittableUniformRandomProvider interface. If true the instance returned by create(RandomSource) may be cast to the interface; otherwise a class cast exception will occur.

        Usage example:

        
          RandomSource source = ...;
          if (source.isSplittable()) {
              SplittableUniformRandomProvider rng =
                  (SplittableUniformRandomProvider) source.create();
          }
         
        Returns:
        true if splittable
        Since:
        1.5
      • create

        public RestorableUniformRandomProvider create()
        Creates a random number generator with a random seed.

        Usage example:

        
          UniformRandomProvider rng = RandomSource.XO_RO_SHI_RO_128_PP.create();
         

        or, if a "save/restore" functionality is needed,

        
          RestorableUniformRandomProvider rng = RandomSource.XO_RO_SHI_RO_128_PP.create();
         

        This method will raise an exception if the generator requires arguments in addition to a seed (e.g. TWO_CMRES_SELECT).

        Returns:
        the RNG.
        Throws:
        IllegalArgumentException - if the generator requires arguments in addition to a seed.
        Since:
        1.4
        See Also:
        create(Object,Object[])
      • create

        public RestorableUniformRandomProvider create​(Object seed,
                                                      Object... data)
        Creates a random number generator with the given seed.

        Usage example:

        
          UniformRandomProvider rng = RandomSource.XO_RO_SHI_RO_128_PP.create(0x123abcL);
          UniformRandomProvider rng = RandomSource.TWO_CMRES_SELECT.create(26219, 6, 9);
          // null seed with arguments
          UniformRandomProvider rng = RandomSource.TWO_CMRES_SELECT.create((Object) null, 6, 9);
         

        Valid types for the seed are:

        • Integer (or int)
        • Long (or long)
        • int[]
        • long[]
        • byte[]

        Notes:

        • When the seed type passed as argument is more complex (i.e. more bits can be independently chosen) than the generator's native type, the conversion of a set of different seeds will necessarily result in the same value of the native seed type.
        • When the native seed type is an array, the same remark applies when the array contains more bits than the state of the generator.
        • When the seed is null, a seed of the native type will be generated. If the native type is an array, the generated size is limited a maximum of 128.

        This method will raise an exception if the additional arguments for the implementation's constructor are incorrect (e.g. TWO_CMRES_SELECT). This includes the case where arguments are supplied and the implementation does not require additional arguments.

        Parameters:
        seed - Seed value. It can be null (in which case a random value will be used).
        data - Additional arguments to the implementation's constructor. Please refer to the documentation of each specific implementation.
        Returns:
        the RNG.
        Throws:
        IllegalArgumentException - if the argument data required to initialize the generator is incorrect.
        UnsupportedOperationException - if the type of the seed is invalid.
        Since:
        1.4
        See Also:
        create()
      • create

        @Deprecated
        public static RestorableUniformRandomProvider create​(RandomSource source,
                                                             Object seed,
                                                             Object... data)
        Deprecated.
        It is preferred to use the create(Object, Object...) instance method.
        Creates a random number generator with the given seed.

        Usage example:

        
          UniformRandomProvider rng = RandomSource.create(RandomSource.XO_RO_SHI_RO_128_PP, 0x123abcL);
          UniformRandomProvider rng = RandomSource.create(RandomSource.TWO_CMRES_SELECT, 26219, 6, 9);
         

        Valid types for the seed are:

        • Integer (or int)
        • Long (or long)
        • int[]
        • long[]
        • byte[]

        Notes:

        • When the seed type passed as argument is more complex (i.e. more bits can be independently chosen) than the generator's native type, the conversion of a set of different seeds will necessarily result in the same value of the native seed type.
        • When the native seed type is an array, the same remark applies when the array contains more bits than the state of the generator.
        • When the seed is null, a seed of the native type will be generated. If the native type is an array, the generated size is limited a maximum of 128.

        This method will raise an exception if the additional arguments for the implementation's constructor are incorrect (e.g. TWO_CMRES_SELECT). This includes the case where arguments are supplied and the implementation does not require additional arguments.

        Parameters:
        source - RNG type.
        seed - Seed value. It can be null (in which case a random value will be used).
        data - Additional arguments to the implementation's constructor. Please refer to the documentation of each specific implementation.
        Returns:
        the RNG.
        Throws:
        IllegalArgumentException - if the argument data required to initialize the generator is incorrect.
        UnsupportedOperationException - if the type of the seed is invalid.
        See Also:
        create(RandomSource)
      • createInt

        public static int createInt()
        Creates a number for use as a seed.
        Returns:
        a random number.
      • createLong

        public static long createLong()
        Creates a number for use as a seed.
        Returns:
        a random number.
      • createIntArray

        public static int[] createIntArray​(int n)
        Creates an array of numbers for use as a seed.
        Parameters:
        n - Size of the array to create.
        Returns:
        an array of n random numbers.
      • createLongArray

        public static long[] createLongArray​(int n)
        Creates an array of numbers for use as a seed.
        Parameters:
        n - Size of the array to create.
        Returns:
        an array of n random numbers.
      • unrestorable

        public static UniformRandomProvider unrestorable​(UniformRandomProvider delegate)
        Wraps the given delegate generator in a new instance that only provides access to the UniformRandomProvider methods.

        This method can be used to prevent access to any methods of the delegate that are not defined in the UniformRandomProvider interface. For example this will prevent access to the "save/restore" functionality of any RestorableUniformRandomProvider created by the RandomSource factory methods, or will prevent access to the jump functionality of generators.

        Since the method applies to more than the RestorableUniformRandomProvider interface it is left to the caller to determine if any methods require hiding, for example:

        
         UniformRandomProvider rng = ...;
         if (rng instanceof JumpableUniformRandomProvider) {
            rng = RandomSource.unrestorable(rng);
         }
         
        Parameters:
        delegate - Generator to which calls will be delegated.
        Returns:
        a new instance