Example #1
0
  /**
   * {@inheritDoc}
   *
   * <p><strong>Algorithm Description</strong>: if the lower bound is excluded, scales the output of
   * Random.nextDouble(), but rejects 0 values (i.e., will generate another random double if
   * Random.nextDouble() returns 0). This is necessary to provide a symmetric output interval (both
   * endpoints excluded).
   *
   * @throws NumberIsTooLargeException if {@code lower >= upper}
   * @throws NotFiniteNumberException if one of the bounds is infinite
   * @throws NotANumberException if one of the bounds is NaN
   */
  public double nextUniform(double lower, double upper, boolean lowerInclusive)
      throws NumberIsTooLargeException, NotFiniteNumberException, NotANumberException {

    if (lower >= upper) {
      throw new NumberIsTooLargeException(
          LocalizedFormats.LOWER_BOUND_NOT_BELOW_UPPER_BOUND, lower, upper, false);
    }

    if (Double.isInfinite(lower)) {
      throw new NotFiniteNumberException(LocalizedFormats.INFINITE_BOUND, lower);
    }
    if (Double.isInfinite(upper)) {
      throw new NotFiniteNumberException(LocalizedFormats.INFINITE_BOUND, upper);
    }

    if (Double.isNaN(lower) || Double.isNaN(upper)) {
      throw new NotANumberException();
    }

    final RandomGenerator generator = getRandomGenerator();

    // ensure nextDouble() isn't 0.0
    double u = generator.nextDouble();
    while (!lowerInclusive && u <= 0.0) {
      u = generator.nextDouble();
    }

    return u * upper + (1.0 - u) * lower;
  }
Example #2
0
  /**
   * {@inheritDoc}
   *
   * <p><strong>Algorithm Description:</strong> hex strings are generated using a 2-step process.
   *
   * <ol>
   *   <li>{@code len / 2 + 1} binary bytes are generated using the underlying Random
   *   <li>Each binary byte is translated into 2 hex digits
   * </ol>
   *
   * @param len the desired string length.
   * @return the random string.
   * @throws NotStrictlyPositiveException if {@code len <= 0}.
   */
  public String nextHexString(int len) throws NotStrictlyPositiveException {
    if (len <= 0) {
      throw new NotStrictlyPositiveException(LocalizedFormats.LENGTH, len);
    }

    // Get a random number generator
    RandomGenerator ran = getRandomGenerator();

    // Initialize output buffer
    StringBuilder outBuffer = new StringBuilder();

    // Get int(len/2)+1 random bytes
    byte[] randomBytes = new byte[(len / 2) + 1];
    ran.nextBytes(randomBytes);

    // Convert each byte to 2 hex digits
    for (int i = 0; i < randomBytes.length; i++) {
      Integer c = Integer.valueOf(randomBytes[i]);

      /*
       * Add 128 to byte value to make interval 0-255 before doing hex
       * conversion. This guarantees <= 2 hex digits from toHexString()
       * toHexString would otherwise add 2^32 to negative arguments.
       */
      String hex = Integer.toHexString(c.intValue() + 128);

      // Make sure we add 2 hex digits for each byte
      if (hex.length() == 1) {
        hex = "0" + hex;
      }
      outBuffer.append(hex);
    }
    return outBuffer.toString().substring(0, len);
  }
Example #3
0
  /**
   * {@inheritDoc}
   *
   * <p><strong>Algorithm Description:</strong> hex strings are generated in 40-byte segments using
   * a 3-step process.
   *
   * <ol>
   *   <li>20 random bytes are generated using the underlying <code>SecureRandom</code>.
   *   <li>SHA-1 hash is applied to yield a 20-byte binary digest.
   *   <li>Each byte of the binary digest is converted to 2 hex digits.
   * </ol>
   *
   * @throws NotStrictlyPositiveException if {@code len <= 0}
   */
  public String nextSecureHexString(int len) throws NotStrictlyPositiveException {
    if (len <= 0) {
      throw new NotStrictlyPositiveException(LocalizedFormats.LENGTH, len);
    }

    // Get SecureRandom and setup Digest provider
    final RandomGenerator secRan = getSecRan();
    MessageDigest alg = null;
    try {
      alg = MessageDigest.getInstance("SHA-1");
    } catch (NoSuchAlgorithmException ex) {
      // this should never happen
      throw new MathInternalError(ex);
    }
    alg.reset();

    // Compute number of iterations required (40 bytes each)
    int numIter = (len / 40) + 1;

    StringBuilder outBuffer = new StringBuilder();
    for (int iter = 1; iter < numIter + 1; iter++) {
      byte[] randomBytes = new byte[40];
      secRan.nextBytes(randomBytes);
      alg.update(randomBytes);

      // Compute hash -- will create 20-byte binary hash
      byte[] hash = alg.digest();

      // Loop over the hash, converting each byte to 2 hex digits
      for (int i = 0; i < hash.length; i++) {
        Integer c = Integer.valueOf(hash[i]);

        /*
         * Add 128 to byte value to make interval 0-255 This guarantees
         * <= 2 hex digits from toHexString() toHexString would
         * otherwise add 2^32 to negative arguments
         */
        String hex = Integer.toHexString(c.intValue() + 128);

        // Keep strings uniform length -- guarantees 40 bytes
        if (hex.length() == 1) {
          hex = "0" + hex;
        }
        outBuffer.append(hex);
      }
    }
    return outBuffer.toString().substring(0, len);
  }
Example #4
0
 /**
  * Returns the SecureRandom used to generate secure random data.
  *
  * <p>Creates and initializes if null. Uses {@code System.currentTimeMillis() +
  * System.identityHashCode(this)} as the default seed.
  *
  * @return the SecureRandom used to generate secure random data, wrapped in a {@link
  *     RandomGenerator}.
  */
 private RandomGenerator getSecRan() {
   if (secRand == null) {
     secRand = RandomGeneratorFactory.createRandomGenerator(new SecureRandom());
     secRand.setSeed(System.currentTimeMillis() + System.identityHashCode(this));
   }
   return secRand;
 }
Example #5
0
 /** {@inheritDoc} */
 public long nextSecureLong(final long lower, final long upper) throws NumberIsTooLargeException {
   if (lower >= upper) {
     throw new NumberIsTooLargeException(
         LocalizedFormats.LOWER_BOUND_NOT_BELOW_UPPER_BOUND, lower, upper, false);
   }
   final RandomGenerator rng = getSecRan();
   final long max = (upper - lower) + 1;
   if (max <= 0) {
     // the range is too wide to fit in a positive long (larger than 2^63); as it covers
     // more than half the long range, we use directly a simple rejection method
     while (true) {
       final long r = rng.nextLong();
       if (r >= lower && r <= upper) {
         return r;
       }
     }
   } else if (max < Integer.MAX_VALUE) {
     // we can shift the range and generate directly a positive int
     return lower + rng.nextInt((int) max);
   } else {
     // we can shift the range and generate directly a positive long
     return lower + nextLong(rng, max);
   }
 }
Example #6
0
 /**
  * Returns a pseudorandom, uniformly distributed {@code long} value between 0 (inclusive) and the
  * specified value (exclusive), drawn from this random number generator's sequence.
  *
  * @param rng random generator to use
  * @param n the bound on the random number to be returned. Must be positive.
  * @return a pseudorandom, uniformly distributed {@code long} value between 0 (inclusive) and n
  *     (exclusive).
  * @throws IllegalArgumentException if n is not positive.
  */
 private static long nextLong(final RandomGenerator rng, final long n)
     throws IllegalArgumentException {
   if (n > 0) {
     final byte[] byteArray = new byte[8];
     long bits;
     long val;
     do {
       rng.nextBytes(byteArray);
       bits = 0;
       for (final byte b : byteArray) {
         bits = (bits << 8) | (((long) b) & 0xffL);
       }
       bits &= 0x7fffffffffffffffL;
       val = bits % n;
     } while (bits - val + (n - 1) < 0);
     return val;
   }
   throw new NotStrictlyPositiveException(n);
 }