ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/SplittableRandom.java
(Generate patch)

Comparing jsr166/src/main/java/util/SplittableRandom.java (file contents):
Revision 1.10 by jsr166, Sun Jul 14 08:06:49 2013 UTC vs.
Revision 1.11 by dl, Tue Jul 16 12:32:05 2013 UTC

# Line 51 | Line 51 | import java.util.stream.DoubleStream;
51   * href="http://www.phy.duke.edu/~rgb/General/dieharder.php"> version
52   * 3.31.1</a>.) These tests validate only the methods for certain
53   * types and ranges, but similar properties are expected to hold, at
54 < * least approximately, for others as well.  </li>
54 > * least approximately, for others as well. The <em>period</em>
55 > * (length of any series of generated values before it repeats) is at
56 > * least 2<sup>64</sup>. </li>
57   *
58   * <li> Method {@link #split} constructs and returns a new
59   * SplittableRandom instance that shares no mutable state with the
# Line 156 | Line 158 | public class SplittableRandom {
158       * SplittableRandom. Unlike other cases, this split must be
159       * performed in a thread-safe manner. We use
160       * AtomicLong.compareAndSet as the (typically) most efficient
161 <     * mechanism. To bootstrap, we start off using System.nanotime(),
162 <     * and update using another "genuinely random" constant
163 <     * DEFAULT_SEED_GAMMA. The default constructor uses GAMMA_GAMMA,
164 <     * not 0, for its splitSeed argument (addGammaModGeorge(0,
165 <     * GAMMA_GAMMA) == GAMMA_GAMMA) to reflect that each is split from
166 <     * this root generator, even though the root is not explicitly
167 <     * represented as a SplittableRandom.
161 >     * mechanism. To bootstrap, we start off using a function of the
162 >     * current System time as seed, and update using another
163 >     * "genuinely random" constant DEFAULT_SEED_GAMMA. The default
164 >     * constructor uses GAMMA_GAMMA, not 0, for its splitSeed argument
165 >     * (addGammaModGeorge(0, GAMMA_GAMMA) == GAMMA_GAMMA) to reflect
166 >     * that each is split from this root generator, even though the
167 >     * root is not explicitly represented as a SplittableRandom.  When
168 >     * establishing the initial seed, we use both
169 >     * System.currentTimeMillis and System.nanoTime(), to avoid
170 >     * regularities that may occur if using either alone.
171       */
172  
173      /**
# Line 180 | Line 185 | public class SplittableRandom {
185      private static final long DEFAULT_SEED_GAMMA = 0xBD24B73A95FB84D9L;
186  
187      /**
188 +     * The value 13 with 64bit sign bit set. Used in the signed
189 +     * comparison in addGammaModGeorge.
190 +     */
191 +    private static final long BOTTOM13 = 0x800000000000000DL;
192 +
193 +    /**
194       * The least non-zero value returned by nextDouble(). This value
195       * is scaled by a random value of 53 bits to produce a result.
196       */
# Line 189 | Line 200 | public class SplittableRandom {
200       * The next seed for default constructors.
201       */
202      private static final AtomicLong defaultSeedGenerator =
203 <        new AtomicLong(System.nanoTime());
203 >        new AtomicLong(mix64(System.currentTimeMillis()) ^
204 >                       mix64(System.nanoTime()));
205  
206      /**
207       * The seed, updated only via method nextSeed.
# Line 217 | Line 229 | public class SplittableRandom {
229       * George < 2^64; thus we need only a conditional, not a loop,
230       * to be sure of getting a representable value.
231       *
232 <     * @param s a seed value
232 >     * Because Java comparison operators are signed, we implement this
233 >     * by conceptually offsetting seed values downwards by 2^63, so
234 >     * 0..13 is represented as Long.MIN_VALUE..BOTTOM13.
235 >     *
236 >     * @param s a seed value, viewed as a signed long
237       * @param g a gamma value, 13 <= g (as unsigned)
238       */
239      private static long addGammaModGeorge(long s, long g) {
240          long p = s + g;
241 <        if (Long.compareUnsigned(p, g) >= 0)
226 <            return p;
227 <        long q = p - 13L;
228 <        return (Long.compareUnsigned(p, 13L) >= 0) ? q : (q + g);
241 >        return (p >= s) ? p : ((p >= BOTTOM13) ? p  : p + g) - 13L;
242      }
243  
244      /**
# Line 264 | Line 277 | public class SplittableRandom {
277          do { // ensure gamma >= 13, considered as an unsigned integer
278              s = addGammaModGeorge(s, GAMMA_GAMMA);
279              g = mix64(s);
280 <        } while (Long.compareUnsigned(g, 13L) < 0);
280 >        } while (g >= 0L && g < 13L);
281          this.gamma = g;
282          this.nextSplit = s;
283      }
# Line 403 | Line 416 | public class SplittableRandom {
416      /**
417       * Creates a new SplittableRandom instance using the specified
418       * initial seed. SplittableRandom instances created with the same
419 <     * seed generate identical sequences of values.
419 >     * seed in the same program generate identical sequences of values.
420       *
421       * @param seed the initial seed
422       */
# Line 553 | Line 566 | public class SplittableRandom {
566       * (inclusive) and one (exclusive)
567       */
568      public double nextDouble() {
569 <        return (nextLong() >>> 11) * DOUBLE_UNIT;
569 >        return (mix64(nextSeed()) >>> 11) * DOUBLE_UNIT;
570      }
571  
572      /**
# Line 569 | Line 582 | public class SplittableRandom {
582      public double nextDouble(double bound) {
583          if (!(bound > 0.0))
584              throw new IllegalArgumentException("bound must be positive");
585 <        double result = nextDouble() * bound;
585 >        double result = (mix64(nextSeed()) >>> 11) * DOUBLE_UNIT * bound;
586          return (result < bound) ?  result : // correct for rounding
587              Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1);
588      }
# Line 591 | Line 604 | public class SplittableRandom {
604          return internalNextDouble(origin, bound);
605      }
606  
607 +    /**
608 +     * Returns a pseudorandom {@code boolean} value.
609 +     *
610 +     * @return a pseudorandom {@code boolean} value
611 +     */
612 +    public boolean nextBoolean() {
613 +        return mix32(nextSeed()) < 0;
614 +    }
615 +
616      // stream methods, coded in a way intended to better isolate for
617      // maintenance purposes the small differences across forms.
618  
# Line 854 | Line 876 | public class SplittableRandom {
876       * approach. The long and double versions of this class are
877       * identical except for types.
878       */
879 <    static class RandomIntsSpliterator implements Spliterator.OfInt {
879 >    static final class RandomIntsSpliterator implements Spliterator.OfInt {
880          final SplittableRandom rng;
881          long index;
882          final long fence;
# Line 908 | Line 930 | public class SplittableRandom {
930      /**
931       * Spliterator for long streams.
932       */
933 <    static class RandomLongsSpliterator implements Spliterator.OfLong {
933 >    static final class RandomLongsSpliterator implements Spliterator.OfLong {
934          final SplittableRandom rng;
935          long index;
936          final long fence;
# Line 963 | Line 985 | public class SplittableRandom {
985      /**
986       * Spliterator for double streams.
987       */
988 <    static class RandomDoublesSpliterator implements Spliterator.OfDouble {
988 >    static final class RandomDoublesSpliterator implements Spliterator.OfDouble {
989          final SplittableRandom rng;
990          long index;
991          final long fence;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines