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

Add uniform and spatially equidistributed bounded double streams to RandomGenerator

XMLWordPrintable

    • Icon: CSR CSR
    • Resolution: Approved
    • Icon: P4 P4
    • 22
    • core-libs
    • None
    • minimal
    • This is an additional default method to a public interface. The name and type signature has been chosen to considerably lower the risk of conflicts with implementations outside the JDK.
    • Java API
    • SE

      Summary

      Applying an affine transform to a uniform and spatially equidistributed random float/double in the range [0, 1) to obtain values in a user specified range [left, right), as currently done in the JDK, results in a slightly deformed distribution due to rounding error.

      Problem

      See JDK-8302987 for a more detailed description of the problem.

      Solution

      Add a new public API point to java.util.random.RandomGenerator to obtain a stream that generates a uniform and equidistributed flow of doubles in a given interval.

      Specification

      +    /**
      +     * Returns an effectively unlimited stream of pseudorandomly chosen
      +     * {@code double} values, where each value is between the specified
      +     * {@code left} boundary and the specified {@code right} boundary.
      +     * The {@code left} boundary is included as indicated by
      +     * {@code isLeftIncluded}; similarly, the {@code right} boundary is included
      +     * as indicated by {@code isRightIncluded}.
      +     *
      +     * <p>The stream potentially produces all multiples <i>k</i> &delta;
      +     * (<i>k</i> integer) lying in the interval specified by the parameters,
      +     * where &delta; > 0 is the smallest number for which all these multiples
      +     * are exact {@code double}s.
      +     * They are therefore all equidistant.
      +     * The uniformity of the distribution of the {@code double}s produced by
      +     * the stream depends on the quality of the underlying {@link #nextLong(long)}.
      +     *
      +     * @implSpec The default implementation first determines the &delta; above.
      +     * It then computes both the smallest integer <i>k</i><sub><i>l</i></sub>
      +     * such that <i>k</i><sub><i>l</i></sub> &delta; lies <em>inside</em>
      +     * the given interval, and the smallest integer <i>n</i> > 0 such that
      +     * (<i>k</i><sub><i>l</i></sub> + <i>n</i>) &delta; lies
      +     * <em>outside</em> the interval.
      +     * Finally, it returns a stream which generates the {@code double}s
      +     * according to (<i>k</i><sub><i>l</i></sub> + {@code nextLong(}<i>n</i>{@code )})
      +     * &delta;.
      +     * The stream never produces {@code -0.0}, although it may produce
      +     * {@code 0.0} if the specified interval contains 0.
      +     *
      +     * @param left the left boundary
      +     * @param right the right boundary
      +     * @param isLeftIncluded whether the {@code left} boundary is included
      +     * @param isRightIncluded whether the {@code right} boundary is included
      +     *
      +     * @return a stream of pseudorandomly chosen {@code double} values, each
      +     *         between {@code left} and {@code right}, as specified above.
      +     *
      +     * @throws IllegalArgumentException if {@code left} is not finite,
      +     *         or {@code right} is not finite, or if the specified interval
      +     *         is empty.
      +     */
      +    default DoubleStream equiDoubles(double left, double right,
      +        boolean isLeftIncluded, boolean isRightIncluded) {

            rgiulietti Raffaello Giulietti
            rgiulietti Raffaello Giulietti
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: