Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8282928

provide adapter from RandomGenerator to Random

XMLWordPrintable

    • Icon: CSR CSR
    • Resolution: Approved
    • Icon: P4 P4
    • 19
    • core-libs
    • None
    • source
    • minimal
    • Minimal risk: addition of a new static method that takes a parameter of a recently-introduced type is unlikely to collide with any existing methods.
    • Java API
    • SE

      Summary

      Provide an adapter so that any RandomGenerator can be used where an instance of Random is required. Adjust other areas of the Random class specification to provide flexibility to subclasses.

      Problem

      JEP 356 introduced the RandomGenerator interface as well as a collection of new pseudorandom number generation algorithms and support APIs. However, many APIs consume an instance of java.util.Random; they cannot be used if one has an instance of RandomGenerator. This includes some APIs in the JDK:

      • two BigInteger constructors
      • BigInteger::probablePrime
      • Collections::shuffle

      Eventually these may be retrofitted to consume RandomGenerator, but they aren't as yet. In third-party libraries, it might be difficult to retrofit Random-consuming APIs also to consume RandomGenerator if those libraries need to run on Java SE releases prior to the integration of JEP 356.

      An issue that emerged from this work was how to handle the setSeed method. Its current specification imposes a requirement of setting the entire state of the generator, which in general is not possible for an arbitrary RandomGenerator instance. The setSeed method in the existing subclass SecureRandom uses the seed value to update but not to set its entire state. The existing subclass ThreadLocalRandom rejects calls to the setSeed method entirely. These inconsistencies between the specification and actual behavior should be rectified.

      The protected method next(int) is intended to be overridden by subclasses, but it appears to impose a general contract on subclasses. This inconsistency should be clarified.

      Solution

      Add a method that takes a RandomGenerator instance and wraps it inside a Random instance. The random-producing methods of the returned Random instance are delegated to the enclosed RandomGenerator instance.

      Adjust the specification of the setSeed method to allow flexibility or non-implementation by subclasses, including the wrapper class introduced here.

      Clarify the specification of the protected next(int) method.

      Specification

      Add the following method to the java.util.Random class:

      /**
       * Returns an instance of {@code Random} that delegates method calls to the {@link RandomGenerator}
       * argument. If the generator is an instance of {@code Random}, it is returned. Otherwise, this method
       * returns an instance of {@code Random} that delegates all methods except {@code setSeed} to the generator.
       * The returned instance's {@code setSeed} method always throws {@link UnsupportedOperationException}.
       * The returned instance is not serializable.
       *
       * @param generator the {@code RandomGenerator} calls are delegated to
       * @return the delegating {@code Random} instance
       * @throws NullPointerException if generator is null
       * @since 19
       */
      public static Random from(RandomGenerator generator)

      Modify the specification of the Random::setSeed method as follows:

      /**
       * Sets or updates the seed of this random number generator using the
       * provided {@code long} seed value (optional operation).
       *
       * @implSpec
       * The implementation in this class alters the state of this random number
       * generator so that it is in the same state as if it had just been created with
       * {@link #Random(long) new Random(seed)}. It atomically updates the seed to
       *  <pre>{@code (seed ^ 0x5DEECE66DL) & ((1L << 48) - 1)}</pre>
       * and clears the {@code haveNextNextGaussian} flag used by {@link #nextGaussian}.
       * Note that this uses only 48 bits of the given seed value.
       *
       * @param seed the seed value
       * @throws UnsupportedOperationException if the {@code setSeed}
       *         operation is not supported by this random number generator
       */
      public synchronized void setSeed(long seed)

      Modify the specification of the Random::next method as follows:

      /**
       * Generates the next pseudorandom number. This method returns an
       * {@code int} value such that, if the argument {@code bits} is between
       * {@code 1} and {@code 32} (inclusive), then that many low-order
       * bits of the returned value will be (approximately) independently
       * chosen bit values, each of which is (approximately) equally
       * likely to be {@code 0} or {@code 1}.
       *
       * @apiNote
       * The other random-producing methods in this class are implemented
       * in terms of this method, so subclasses can override just this
       * method to provide a different source of pseudorandom numbers for
       * the entire class.
       *
       * @implSpec
       * The implementation in this class atomically updates the seed to
       *  <pre>{@code (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1)}</pre>
       * and returns
       *  <pre>{@code (int)(seed >>> (48 - bits))}.</pre>
       *
       * <p>This is a linear congruential pseudorandom number generator, as
       * defined by D. H. Lehmer and described by Donald E. Knuth in
       * <cite>The Art of Computer Programming, Volume 2, Third edition:
       * Seminumerical Algorithms</cite>, section 3.2.1.
       *
       * @param  bits random bits
       * @return the next pseudorandom value from this random number
       *         generator's sequence
       * @since  1.1
       */
      protected int next(int bits)

            smarks Stuart Marks
            smarks Stuart Marks
            Lance Andersen
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: