[cvs] / jsr166 / src / main / java / util / SplittableRandom.java Repository:
ViewVC logotype

Diff of /jsr166/src/main/java/util/SplittableRandom.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.10, Sun Jul 14 08:06:49 2013 UTC revision 1.11, Tue Jul 16 12:32:05 2013 UTC
# Line 51  Line 51 
51   * href="http://www.phy.duke.edu/~rgb/General/dieharder.php"> version   * href="http://www.phy.duke.edu/~rgb/General/dieharder.php"> version
52   * 3.31.1</a>.) These tests validate only the methods for certain   * 3.31.1</a>.) These tests validate only the methods for certain
53   * types and ranges, but similar properties are expected to hold, at   * types and ranges, but similar properties are expected to hold, at
54   * least approximately, for others as well.  </li>   * 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   * <li> Method {@link #split} constructs and returns a new
59   * SplittableRandom instance that shares no mutable state with the   * SplittableRandom instance that shares no mutable state with the
# Line 156  Line 158 
158       * SplittableRandom. Unlike other cases, this split must be       * SplittableRandom. Unlike other cases, this split must be
159       * performed in a thread-safe manner. We use       * performed in a thread-safe manner. We use
160       * AtomicLong.compareAndSet as the (typically) most efficient       * AtomicLong.compareAndSet as the (typically) most efficient
161       * mechanism. To bootstrap, we start off using System.nanotime(),       * mechanism. To bootstrap, we start off using a function of the
162       * and update using another "genuinely random" constant       * current System time as seed, and update using another
163       * DEFAULT_SEED_GAMMA. The default constructor uses GAMMA_GAMMA,       * "genuinely random" constant DEFAULT_SEED_GAMMA. The default
164       * not 0, for its splitSeed argument (addGammaModGeorge(0,       * constructor uses GAMMA_GAMMA, not 0, for its splitSeed argument
165       * GAMMA_GAMMA) == GAMMA_GAMMA) to reflect that each is split from       * (addGammaModGeorge(0, GAMMA_GAMMA) == GAMMA_GAMMA) to reflect
166       * this root generator, even though the root is not explicitly       * that each is split from this root generator, even though the
167       * represented as a SplittableRandom.       * 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 
185      private static final long DEFAULT_SEED_GAMMA = 0xBD24B73A95FB84D9L;      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       * The least non-zero value returned by nextDouble(). This value
195       * is scaled by a random value of 53 bits to produce a result.       * is scaled by a random value of 53 bits to produce a result.
196       */       */
# Line 189  Line 200 
200       * The next seed for default constructors.       * The next seed for default constructors.
201       */       */
202      private static final AtomicLong defaultSeedGenerator =      private static final AtomicLong defaultSeedGenerator =
203          new AtomicLong(System.nanoTime());          new AtomicLong(mix64(System.currentTimeMillis()) ^
204                           mix64(System.nanoTime()));
205    
206      /**      /**
207       * The seed, updated only via method nextSeed.       * The seed, updated only via method nextSeed.
# Line 217  Line 229 
229       * George < 2^64; thus we need only a conditional, not a loop,       * George < 2^64; thus we need only a conditional, not a loop,
230       * to be sure of getting a representable value.       * to be sure of getting a representable value.
231       *       *
232       * @param s a seed value       * 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)       * @param g a gamma value, 13 <= g (as unsigned)
238       */       */
239      private static long addGammaModGeorge(long s, long g) {      private static long addGammaModGeorge(long s, long g) {
240          long p = s + g;          long p = s + g;
241          if (Long.compareUnsigned(p, g) >= 0)          return (p >= s) ? p : ((p >= BOTTOM13) ? p  : p + g) - 13L;
             return p;  
         long q = p - 13L;  
         return (Long.compareUnsigned(p, 13L) >= 0) ? q : (q + g);  
242      }      }
243    
244      /**      /**
# Line 264  Line 277 
277          do { // ensure gamma >= 13, considered as an unsigned integer          do { // ensure gamma >= 13, considered as an unsigned integer
278              s = addGammaModGeorge(s, GAMMA_GAMMA);              s = addGammaModGeorge(s, GAMMA_GAMMA);
279              g = mix64(s);              g = mix64(s);
280          } while (Long.compareUnsigned(g, 13L) < 0);          } while (g >= 0L && g < 13L);
281          this.gamma = g;          this.gamma = g;
282          this.nextSplit = s;          this.nextSplit = s;
283      }      }
# Line 403  Line 416 
416      /**      /**
417       * Creates a new SplittableRandom instance using the specified       * Creates a new SplittableRandom instance using the specified
418       * initial seed. SplittableRandom instances created with the same       * initial seed. SplittableRandom instances created with the same
419       * seed generate identical sequences of values.       * seed in the same program generate identical sequences of values.
420       *       *
421       * @param seed the initial seed       * @param seed the initial seed
422       */       */
# Line 553  Line 566 
566       * (inclusive) and one (exclusive)       * (inclusive) and one (exclusive)
567       */       */
568      public double nextDouble() {      public double nextDouble() {
569          return (nextLong() >>> 11) * DOUBLE_UNIT;          return (mix64(nextSeed()) >>> 11) * DOUBLE_UNIT;
570      }      }
571    
572      /**      /**
# Line 569  Line 582 
582      public double nextDouble(double bound) {      public double nextDouble(double bound) {
583          if (!(bound > 0.0))          if (!(bound > 0.0))
584              throw new IllegalArgumentException("bound must be positive");              throw new IllegalArgumentException("bound must be positive");
585          double result = nextDouble() * bound;          double result = (mix64(nextSeed()) >>> 11) * DOUBLE_UNIT * bound;
586          return (result < bound) ?  result : // correct for rounding          return (result < bound) ?  result : // correct for rounding
587              Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1);              Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1);
588      }      }
# Line 591  Line 604 
604          return internalNextDouble(origin, bound);          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      // stream methods, coded in a way intended to better isolate for
617      // maintenance purposes the small differences across forms.      // maintenance purposes the small differences across forms.
618    
# Line 854  Line 876 
876       * approach. The long and double versions of this class are       * approach. The long and double versions of this class are
877       * identical except for types.       * identical except for types.
878       */       */
879      static class RandomIntsSpliterator implements Spliterator.OfInt {      static final class RandomIntsSpliterator implements Spliterator.OfInt {
880          final SplittableRandom rng;          final SplittableRandom rng;
881          long index;          long index;
882          final long fence;          final long fence;
# Line 908  Line 930 
930      /**      /**
931       * Spliterator for long streams.       * Spliterator for long streams.
932       */       */
933      static class RandomLongsSpliterator implements Spliterator.OfLong {      static final class RandomLongsSpliterator implements Spliterator.OfLong {
934          final SplittableRandom rng;          final SplittableRandom rng;
935          long index;          long index;
936          final long fence;          final long fence;
# Line 963  Line 985 
985      /**      /**
986       * Spliterator for double streams.       * Spliterator for double streams.
987       */       */
988      static class RandomDoublesSpliterator implements Spliterator.OfDouble {      static final class RandomDoublesSpliterator implements Spliterator.OfDouble {
989          final SplittableRandom rng;          final SplittableRandom rng;
990          long index;          long index;
991          final long fence;          final long fence;

Legend:
Removed from v.1.10  
changed lines
  Added in v.1.11

Doug Lea
ViewVC Help
Powered by ViewVC 1.0.8