Submitted by: Phil Steitz git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/math/trunk@140885 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
fe27566380
commit
ba74c2510f
|
@ -58,196 +58,260 @@ import java.util.Collection;
|
|||
/**
|
||||
* Random data generation utilities
|
||||
* @author Phil Steitz
|
||||
* @version $Revision: 1.2 $ $Date: 2003/05/29 19:45:35 $
|
||||
* @version $Revision: 1.3 $ $Date: 2003/06/04 02:45:49 $
|
||||
*/
|
||||
public interface RandomData {
|
||||
/**
|
||||
* Generates a random string of hex characters of length
|
||||
* <code>len</code>.<br>
|
||||
* <code>len</code>.
|
||||
* <p>
|
||||
* The generated string will be random, but not cryptographically
|
||||
* secure. To generate cryptographically secure strings, use
|
||||
* <code>nextSecureHexString</code>
|
||||
* <p>
|
||||
* <strong>Preconditions</strong>:<ul>
|
||||
* <li><code>len > 0</code> (otherwise an IllegalArgumentException
|
||||
* is thrown.)</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param len the length of the string to be generated
|
||||
* @throws IllegalArgumentException if <code>len</code> is not positive.
|
||||
* @return random string of hex characters of length <code>len</code>
|
||||
*/
|
||||
public String nextHexString(int len);
|
||||
String nextHexString(int len);
|
||||
|
||||
/**
|
||||
* Generates a uniformly distributed random integer between
|
||||
* <code>lower</code> and <code>upper</code> (endpoints included).<br>
|
||||
* <code>lower</code> and <code>upper</code> (endpoints included).
|
||||
* <p>
|
||||
* The generated integer will be random, but not cryptographically secure.
|
||||
* To generate cryptographically secure integer sequences, use
|
||||
* <code>nextSecureInt</code>.
|
||||
* <p>
|
||||
* <strong>Preconditions</strong>:<ul>
|
||||
* <li><code>lower < upper</code> (otherwise an IllegalArgumentException
|
||||
* is thrown.)</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param lower lower bound for generated integer
|
||||
* @param upper upper bound for generated integer
|
||||
* @exception IllegalArgumentException thrown if
|
||||
* <code>lower</code> is not strictly less than <code>upper</code>.
|
||||
* @return a random integer greater than or equal to <code>lower</code>
|
||||
* and less than or equal to <code>upper</code>.
|
||||
*/
|
||||
public int nextInt(int lower, int upper);
|
||||
int nextInt(int lower, int upper);
|
||||
|
||||
/**
|
||||
* Generates a uniformly distributed random long integer between <
|
||||
* code>lower</code> and <code>upper</code> (endpoints included).
|
||||
* Generates a uniformly distributed random long integer between
|
||||
* <code>lower</code> and <code>upper</code> (endpoints included).
|
||||
* <p>
|
||||
* The generated long integer values will be random, but not
|
||||
* cryptographically secure.<br>
|
||||
* cryptographically secure.
|
||||
* To generate cryptographically secure sequences of longs, use
|
||||
* <code>nextSecureLong</code>
|
||||
* <p>
|
||||
* <strong>Preconditions</strong>:<ul>
|
||||
* <li><code>lower < upper</code> (otherwise an IllegalArgumentException
|
||||
* is thrown.)</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param lower lower bound for generated integer
|
||||
* @param upper upper bound for generated integer
|
||||
* @exception IllegalArgumentException Thrown if lower > upper
|
||||
* @return a random integer greater than or equal to <code>lower</code>
|
||||
* and less than or equal to <code>upper</code>.
|
||||
*/
|
||||
public long nextLong(long lower, long upper);
|
||||
long nextLong(long lower, long upper);
|
||||
|
||||
/**
|
||||
* Generates a random string of hex characters from a secure random sequence.
|
||||
* Generates a random string of hex characters from a secure random
|
||||
* sequence.
|
||||
* <p>
|
||||
* If cryptographic security is not required,
|
||||
* use <code>nextHexString()</code>.
|
||||
* <p>
|
||||
* <strong>Preconditions</strong>:<ul>
|
||||
* <li><code>len > 0</code> (otherwise an IllegalArgumentException
|
||||
* is thrown.)</li>
|
||||
* </ul>
|
||||
* @param len length of return string
|
||||
* @exception IllegalArgumentException thrown if len <= 0
|
||||
* @return the random hex string
|
||||
*/
|
||||
public String nextSecureHexString(int len);
|
||||
String nextSecureHexString(int len);
|
||||
|
||||
/**
|
||||
* Generates a uniformly distributed random integer between
|
||||
* <code>lower</code> and <code>upper</code> (endpoints included)
|
||||
* from a secure random sequence.<br>
|
||||
* The generated sequence will be cryptographically secure.<br>
|
||||
* If cryptographic security is not required, <code>nextInt</code>
|
||||
* should be used.<br>
|
||||
* <strong>Definition</strong>(secure random sequence):
|
||||
* http://www.wikipedia.org/wiki/Cryptographically_secure_pseudo-random_number_generator<br>
|
||||
* from a secure random sequence.
|
||||
* <p>
|
||||
* Sequences of integers generated using this method will be
|
||||
* cryptographically secure. If cryptographic security is not required,
|
||||
* <code>nextInt</code> should be used instead of this method.
|
||||
* <p>
|
||||
* <strong>Definition</strong>:
|
||||
* <a href="http://www.wikipedia.org/wiki/
|
||||
* Cryptographically_secure_pseudo-random_number_generator">
|
||||
* Secure Random Sequence</a>
|
||||
* <p>
|
||||
* <strong>Preconditions</strong>:<ul>
|
||||
* <li><code>lower < upper</code> (otherwise an IllegalArgumentException
|
||||
* is thrown.)</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param lower lower bound for generated integer
|
||||
* @param upper upper bound for generated integer
|
||||
* @exception IllegalArgumentException thrown if
|
||||
* <code>lower</code> is not strictly less than <code>upper</code>.
|
||||
* @return a random integer greater than or equal to <code>lower</code>
|
||||
* and less than or equal to <code>upper</code>.
|
||||
*/
|
||||
public int nextSecureInt(int lower, int upper);
|
||||
int nextSecureInt(int lower, int upper);
|
||||
|
||||
/**
|
||||
* Generates a random long integer between <code>lower</code>
|
||||
* and <code>upper</code> (endpoints included).<br>
|
||||
* The generated long sequence will be cryptographically secure.<br>
|
||||
* If cryptographic security is not required,
|
||||
* use <code>nextLong</code><br>
|
||||
* and <code>upper</code> (endpoints included).<p>
|
||||
* Sequences of long values generated using this method will be
|
||||
* cryptographically secure. If cryptographic security is not required,
|
||||
* <code>nextLong</code> should be used instead of this method.
|
||||
* <p>
|
||||
* <strong>Definition</strong>:
|
||||
* <a href=http://www.wikipedia.org/wiki/Cryptographically_secure_pseudo-random_number_generator>
|
||||
* <a href="http://www.wikipedia.org/wiki/
|
||||
* Cryptographically_secure_pseudo-random_number_generator">
|
||||
* Secure Random Sequence</a>
|
||||
* <p>
|
||||
* <strong>Preconditions</strong>:<ul>
|
||||
* <li><code>lower < upper</code> (otherwise an IllegalArgumentException
|
||||
* is thrown.)</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param lower lower bound for generated integer
|
||||
* @param upper upper bound for generated integer
|
||||
* @exception IllegalArgumentException thrown if
|
||||
* <code>lower</code> is not strictly less than <code>upper</code>.
|
||||
* @return a long integer greater than or equal to <code>lower</code>
|
||||
* and less than or equal to <code>upper</code>.
|
||||
*/
|
||||
public long nextSecureLong(long lower, long upper);
|
||||
long nextSecureLong(long lower, long upper);
|
||||
|
||||
/**
|
||||
* Generates a random value from the Poisson distribution with
|
||||
* the given mean.<br>
|
||||
* the given mean.
|
||||
* <p>
|
||||
* <strong>Definition</strong>:
|
||||
* <a href=http://www.itl.nist.gov/div898/handbook/eda/section3/eda366j.htm>
|
||||
* Poisson Distribution</a><br>
|
||||
* <a href="http://www.itl.nist.gov/div898/handbook/
|
||||
* eda/section3/eda366j.htm">
|
||||
* Poisson Distribution</a>
|
||||
* <p>
|
||||
* <strong>Preconditions</strong>: <ul>
|
||||
* <li>The specified mean <i>must</i> be positive </li>
|
||||
* <li>The specified mean <i>must</i> be positive (otherwise an
|
||||
* IllegalArgumentException is thrown.)</li>
|
||||
* </ul>
|
||||
* @param mean Mean of the distribution
|
||||
* @returns long
|
||||
* @throws IllegalArgumentException if mean <= 0
|
||||
* @return poisson deviate with the specified mean
|
||||
*/
|
||||
public long nextPoisson(double mean);
|
||||
long nextPoisson(double mean);
|
||||
|
||||
/**
|
||||
* Generates a random value from the
|
||||
* Normal (a.k.a. Gaussian) distribution with the given mean
|
||||
* and standard deviation.<br>
|
||||
* Normal (or Gaussian) distribution with the given mean
|
||||
* and standard deviation.
|
||||
* <p>
|
||||
* <strong>Definition</strong>:
|
||||
* <a href=http://www.itl.nist.gov/div898/handbook/eda/section3/eda3661.htm>
|
||||
* Normal Distribution</a><br>
|
||||
* <a href="http://www.itl.nist.gov/div898/handbook/
|
||||
* eda/section3/eda3661.htm">
|
||||
* Normal Distribution</a>
|
||||
* <p>
|
||||
* <strong>Preconditions</strong>: <ul>
|
||||
* <li>The specified standard deviation <i>must</i> be positive </li>
|
||||
* <li><code>sigma > 0</code> (otherwise an IllegalArgumentException
|
||||
* is thrown.)</li>
|
||||
* </ul>
|
||||
* @param mu Mean of the distribution
|
||||
* @param sigma Standard deviation of the distribution
|
||||
* @return random value from Gaussian distribution with mean = mu,
|
||||
* standard deviation = sigma
|
||||
* @throws IllegalArgumentExcption if sigma <= 0
|
||||
*/
|
||||
public double nextGaussian(double mu,double sigma);
|
||||
double nextGaussian(double mu, double sigma);
|
||||
|
||||
/**
|
||||
* Generates a random value from the exponential distribution
|
||||
* with expected value = <code>mean</code><br>
|
||||
* with expected value = <code>mean</code>.
|
||||
* <p>
|
||||
* <strong>Definition</strong>:
|
||||
* <a href=http://www.itl.nist.gov/div898/handbook/eda/section3/eda3667.htm>
|
||||
* Exponential Distribution</a><br>
|
||||
* <a href="http://www.itl.nist.gov/div898/handbook/
|
||||
* eda/section3/eda3667.htm">
|
||||
* Exponential Distribution</a>
|
||||
* <p>
|
||||
* <strong>Preconditions</strong>: <ul>
|
||||
* <li>The specified mean <i>must</i> be non-negative</li>
|
||||
* <li><code>mu >= 0</code> (otherwise an IllegalArgumentException
|
||||
* is thrown.)</li>
|
||||
* </ul>
|
||||
* @param mu Mean of the distribution
|
||||
* @param mean Mean of the distribution
|
||||
* @return random value from exponential distribution
|
||||
*/
|
||||
public double nextExponential(double mean);
|
||||
double nextExponential(double mean);
|
||||
|
||||
/**
|
||||
* Generates a uniformly distributed random value from the open interval
|
||||
* (<code>lower</code>,<code>upper</code>) (i.e., endpoints excluded)
|
||||
* (<code>lower</code>,<code>upper</code>) (i.e., endpoints excluded).
|
||||
* <p>
|
||||
* <strong>Definition</strong>:
|
||||
* <a href=http://www.itl.nist.gov/div898/handbook/eda/section3/eda3662.htm>
|
||||
* Uniform Distribution</a> <code>lower</code> and <code>upper - lower</code>
|
||||
* are the
|
||||
* <a href = http://www.itl.nist.gov/div898/handbook/eda/section3/eda364.htm>
|
||||
* location and scale parameters</a>, respectively<br>
|
||||
* <a href="http://www.itl.nist.gov/div898/handbook/
|
||||
* eda/section3/eda3662.htm">
|
||||
* Uniform Distribution</a> <code>lower</code> and
|
||||
* <code>upper - lower</code> are the
|
||||
* <a href = "http://www.itl.nist.gov/div898/handbook/eda/
|
||||
* section3/eda364.htm">
|
||||
* location and scale parameters</a>, respectively.
|
||||
* <p>
|
||||
* <strong>Preconditions</strong>:<ul>
|
||||
* <li><code>lower < upper</code> (otherwise an IllegalArgumentException
|
||||
* is thrown.)</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param lower lower endpoint of the interval of support
|
||||
* @param upper upper endpoint of the interval of support
|
||||
* @return uniformly distributed random value between lower
|
||||
* and upper (exclusive)
|
||||
* @exception IllegalArgumentException thrown if
|
||||
* <code>lower</code> is not strictly less than <code>upper</code>.
|
||||
*/
|
||||
public double nextUniform(double lower, double upper);
|
||||
double nextUniform(double lower, double upper);
|
||||
|
||||
/**
|
||||
* Generates an integer array of length <code>k</code> whose entries
|
||||
* are selected randomly, without repetition, from the integers
|
||||
* {0, ... , n-1} -- i.e., generated arrays represent permutations
|
||||
* of <code>n</code> taken <code>k</code> at a time. <p>
|
||||
*
|
||||
* are selected randomly, without repetition, from the integers <code>
|
||||
* 0 through n-1</code> (inclusive).
|
||||
* <p>
|
||||
* Generated arrays represent permutations
|
||||
* of <code>n</code> taken <code>k</code> at a time.
|
||||
* <p>
|
||||
* <strong>Preconditions:</strong><ul>
|
||||
* <li> k must be less than or equal to n </li>
|
||||
* <li> n must be positive (i.e. greater than 0) </li>
|
||||
* <li> <code>k <= n</code></li>
|
||||
* <li> <code>n > 0</code> </li>
|
||||
* </ul>
|
||||
* If the preconditions are not met, an IllegalArgumentException is
|
||||
* thrown.
|
||||
*
|
||||
* @param n domain of the permutation
|
||||
* @param k size of the permutation
|
||||
* @return random k-permutation of n
|
||||
*/
|
||||
public int[] nextPermutation(int n, int k);
|
||||
int[] nextPermutation(int n, int k);
|
||||
|
||||
/**
|
||||
* Returns an array of <code>k</code> objects selected randomly
|
||||
* from the Collection <code>c</code>. Sampling from <code>c</code>
|
||||
* from the Collection <code>c</code>.
|
||||
* <p>
|
||||
* Sampling from <code>c</code>
|
||||
* is without replacement; but if <code>c</code> contains identical
|
||||
* objects, the sample may include repeats. If all elements of <code>
|
||||
* c</code> are distinct, the resulting object array represents a
|
||||
* <a href=http://rkb.home.cern.ch/rkb/AN16pp/node250.html#SECTION0002500000000000000000>
|
||||
* <a href="http://rkb.home.cern.ch/rkb/AN16pp/
|
||||
* node250.html#SECTION0002500000000000000000">
|
||||
* Simple Random Sample</a> of size
|
||||
* <code>k</code> from the elements of <code>c</code>.<p>
|
||||
*
|
||||
* <code>k</code> from the elements of <code>c</code>.
|
||||
* <p>
|
||||
* <strong>Preconditions:</strong><ul>
|
||||
* <li> k must be less than or equal to the size of c </li>
|
||||
* <li> c must not be empty </li>
|
||||
* </ul>
|
||||
* If the preconditions are not met, an IllegalArgumentException is
|
||||
* thrown.
|
||||
*
|
||||
* @param c collection to be sampled
|
||||
* @param k size of the sample
|
||||
* @return random sample of k elements from c
|
||||
*/
|
||||
public Object[] nextSample(Collection c, int k);
|
||||
Object[] nextSample(Collection c, int k);
|
||||
}
|
||||
|
|
|
@ -64,42 +64,50 @@ import java.util.Collection;
|
|||
/**
|
||||
* Implements the <code>RandomData</code> interface using
|
||||
* <code>java.util.Random</code> and
|
||||
* <code>java.util.Random.SecureRandom</code> instances to generate data.
|
||||
* <code>java.util.Random.SecureRandom</code> instances to generate data.
|
||||
* <p>
|
||||
* Supports reseeding the underlying
|
||||
* <a href=http://www.wikipedia.org/wiki/Pseudo-random_number_generator>PRNG</a>.
|
||||
* The <code>SecurityProvider</code> and <code>Algorithm</code>
|
||||
* used by the <code>SecureRandom</code> instance can also be reset.<p>
|
||||
* <a href="http://www.wikipedia.org/wiki/Pseudo-random_number_generator">
|
||||
* PRNG</a>. The <code>SecurityProvider</code> and <code>Algorithm</code>
|
||||
* used by the <code>SecureRandom</code> instance can also be reset.
|
||||
* <p>
|
||||
* For details on the PRNGs, see the JDK documentation for
|
||||
* <code>java.util.Random</code> and
|
||||
* <code>java.util.Random.SecureRandom</code></p><p>
|
||||
* <code>java.util.Random.SecureRandom</code>
|
||||
* <p>
|
||||
* <strong>Usage Notes</strong>: <ul>
|
||||
* <li>Instance variables are used to maintain <code>Random</code> and
|
||||
* <li>
|
||||
* Instance variables are used to maintain <code>Random</code> and
|
||||
* <code>SecureRandom</code> instances used in data generation. Therefore,
|
||||
* to generate a random sequence of values or strings, you should use just
|
||||
* <strong>one</strong> <code>RandomDataImpl</code> instance repeatedly.</li>
|
||||
* <li>The "secure" methods are *much* slower. These should be used only when
|
||||
* a <a href=http://www.wikipedia.org/wiki/Cryptographically_secure_pseudo-random_number_generator>
|
||||
* Secure Random Sequence</a> is required.</li>
|
||||
*<li>When a new <code>RandomDataImpl</code> is created, the underlying random
|
||||
* <li>
|
||||
* The "secure" methods are *much* slower. These should be used only when
|
||||
* a <a href="http://www.wikipedia.org/wiki/
|
||||
* Cryptographically_secure_pseudo-random_number_generator"> Secure Random
|
||||
* Sequence</a> is required.</li>
|
||||
* <li>
|
||||
* When a new <code>RandomDataImpl</code> is created, the underlying random
|
||||
* number generators are <strong>not</strong> intialized. The first call to a
|
||||
* data generation method, or to a <code>reSeed()</code> method instantiates
|
||||
* the appropriate generator. If you do not explicitly seed the generator, it
|
||||
* is by default seeded with the current time in milliseconds</li>
|
||||
* <li>The <code>reSeed</code> and <code>reSeedSecure</code> methods delegate to
|
||||
* the corresponding methods on the underlying <code>Random</code> and <code>
|
||||
* SecureRandom</code> instances. Therefore, the contracts of these methods
|
||||
* are as defined in the JDK documentation. In particular, <code>reSeed(long)
|
||||
* </code> fully resets the initial state of the non-secure random number
|
||||
* generator (so that reseeding with a specific value always results in the
|
||||
* same subsequent random sequence); whereas reSeedSecure(long) does <strong> not
|
||||
* </strong> reinitialize the secure random number generator (so secure sequences
|
||||
* started with calls to reseedSecure(long) won't be identical).</li></ul>
|
||||
*</p>
|
||||
* <li>
|
||||
* The <code>reSeed</code> and <code>reSeedSecure</code> methods delegate
|
||||
* to the corresponding methods on the underlying <code>Random</code> and
|
||||
* <code>SecureRandom</code> instances. Therefore, the contracts of these
|
||||
* methods are as defined in the JDK documentation. In particular,
|
||||
* <code>reSeed(long)</code> fully resets the initial state of the non-secure
|
||||
* random number generator (so that reseeding with a specific value always
|
||||
* results in the same subsequent random sequence); whereas reSeedSecure(long)
|
||||
* does <strong>not</strong> reinitialize the secure random number generator
|
||||
* (so secure sequences started with calls to reseedSecure(long) won't be
|
||||
* identical).</li></ul>
|
||||
*
|
||||
* @author Phil Steitz
|
||||
* @version $Revision: 1.2 $ $Date: 2003/05/29 19:45:35 $
|
||||
* @version $Revision: 1.3 $ $Date: 2003/06/04 02:45:49 $
|
||||
*/
|
||||
public class RandomDataImpl implements RandomData{
|
||||
public class RandomDataImpl implements RandomData {
|
||||
|
||||
/** underlying random number generator */
|
||||
private Random rand = null;
|
||||
|
@ -107,20 +115,19 @@ public class RandomDataImpl implements RandomData{
|
|||
/** underlying secure random number generator */
|
||||
private SecureRandom secRand = null;
|
||||
|
||||
public RandomDataImpl(){
|
||||
/**
|
||||
* Construct a RandomDataImpl.
|
||||
*/
|
||||
public RandomDataImpl() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a random string of hex characters
|
||||
* If cryptographic security is required, use
|
||||
* <code>nextSecureHexString()</code>.<br>
|
||||
* <strong>Algorithm Description:</strong> hex strings are generated
|
||||
* using a 2-step process. <ol>
|
||||
* <li>len/2+1 binary bytes are generated using the underlying Random</li>
|
||||
* <li>Each binary byte is translated into 2 hex digits</li></ol>
|
||||
* @param len length of return string
|
||||
* @exception IllegalArgumentException thrown if len <= 0
|
||||
* @return the random hex string
|
||||
* <li>
|
||||
* len/2+1 binary bytes are generated using the underlying Random</li>
|
||||
* <li>
|
||||
* Each binary byte is translated into 2 hex digits</li></ol>
|
||||
*/
|
||||
public String nextHexString(int len) {
|
||||
if (len <= 0) {
|
||||
|
@ -146,23 +153,24 @@ public class RandomDataImpl implements RandomData{
|
|||
* This guarantees <= 2 hex digits from toHexString()
|
||||
* toHexString would otherwise add 2^32 to negative arguments.
|
||||
*/
|
||||
String hex = Integer.toHexString(c.intValue()+128);
|
||||
String hex = Integer.toHexString(c.intValue() + 128);
|
||||
|
||||
// Make sure we add 2 hex digits for each byte
|
||||
if (hex.length() == 1) hex = "0" + hex;
|
||||
if (hex.length() == 1) {
|
||||
hex = "0" + hex;
|
||||
}
|
||||
outBuffer.append(hex);
|
||||
}
|
||||
return outBuffer.toString().substring(0, len);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public int nextInt(int lower, int upper) {
|
||||
if (lower >= upper) {
|
||||
throw new IllegalArgumentException
|
||||
("upper bound must be > lower bound");
|
||||
}
|
||||
Random rand = getRan();
|
||||
return lower + (int)(Math.random() * (upper-lower+1));
|
||||
return lower + (int) (Math.random() * (upper - lower + 1));
|
||||
}
|
||||
|
||||
public long nextLong(long lower, long upper) {
|
||||
|
@ -171,23 +179,22 @@ public class RandomDataImpl implements RandomData{
|
|||
("upper bound must be > lower bound");
|
||||
}
|
||||
Random rand = getRan();
|
||||
return lower + (long)(rand.nextDouble() * (upper-lower+1));
|
||||
return lower + (long) (rand.nextDouble() * (upper - lower + 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a random string of hex characters from a secure random sequence.
|
||||
* If cryptographic security is not required,
|
||||
* use <code>nextHexString()</code>.<br>
|
||||
* <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 SecureRandom</li>
|
||||
* <li>SHA-1 hash is applied to yield a 20-byte binary digest</li>
|
||||
* <li>Each byte of the binary digest is converted to 2 hex digits</li></ol><p>
|
||||
* TODO: find external reference or provide justification for the claim that this
|
||||
* yields a cryptographically secure sequence of hex strings.</p>
|
||||
* @param len length of return string
|
||||
* @exception IllegalArgumentException thrown if len <= 0
|
||||
* @return the random hex string
|
||||
* <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>
|
||||
* <li>
|
||||
* SHA-1 hash is applied to yield a 20-byte binary digest.</li>
|
||||
* <li>
|
||||
* Each byte of the binary digest is converted to 2 hex digits</li></ol>
|
||||
* <p>
|
||||
* TODO: find external reference or provide justification for the claim
|
||||
* that this yields a cryptographically secure sequence of hex strings.
|
||||
*/
|
||||
public String nextSecureHexString(int len) {
|
||||
if (len <= 0) {
|
||||
|
@ -200,7 +207,7 @@ public class RandomDataImpl implements RandomData{
|
|||
try {
|
||||
alg = MessageDigest.getInstance("SHA-1");
|
||||
} catch (NoSuchAlgorithmException ex) {
|
||||
return null; // gulp FIXME? -- this *should* never fail. OK to swallow????
|
||||
return null; // gulp FIXME? -- this *should* never fail.
|
||||
}
|
||||
alg.reset();
|
||||
|
||||
|
@ -225,48 +232,43 @@ public class RandomDataImpl implements RandomData{
|
|||
* toHexString would otherwise add 2^32 to negative
|
||||
* arguments
|
||||
*/
|
||||
String hex = Integer.toHexString(c.intValue()+128);
|
||||
String hex = Integer.toHexString(c.intValue() + 128);
|
||||
|
||||
//Keep strings uniform length -- guarantees 40 bytes
|
||||
if (hex.length() == 1) hex = "0" + hex;
|
||||
if (hex.length() == 1) {
|
||||
hex = "0" + hex;
|
||||
}
|
||||
outBuffer.append(hex);
|
||||
}
|
||||
}
|
||||
return outBuffer.toString().substring(0, len);
|
||||
}
|
||||
|
||||
|
||||
public int nextSecureInt(int lower, int upper) {
|
||||
if (lower >= upper) {
|
||||
throw new IllegalArgumentException
|
||||
("lower bound must be < upper bound");
|
||||
}
|
||||
SecureRandom sec = getSecRan();
|
||||
return lower + (int)(sec.nextDouble() * (upper-lower+1));
|
||||
return lower + (int) (sec.nextDouble() * (upper - lower + 1));
|
||||
}
|
||||
|
||||
|
||||
|
||||
public long nextSecureLong(long lower, long upper) {
|
||||
if (lower >= upper) {
|
||||
throw new IllegalArgumentException
|
||||
("lower bound must be < upper bound");
|
||||
}
|
||||
SecureRandom sec = getSecRan();
|
||||
return lower + (long)(sec.nextDouble() * (upper-lower+1));
|
||||
return lower + (long) (sec.nextDouble() * (upper - lower + 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a random value from the Poisson distribution with
|
||||
* the given mean.<br>
|
||||
* <strong>Definition</strong>:
|
||||
* <a href=http://www.itl.nist.gov/div898/handbook/eda/section3/eda366j.htm>
|
||||
* Poisson Distribution</a><br>
|
||||
* <strong>Algorithm Description</strong>:
|
||||
* Uses simulation of a Poisson process using Uniform deviates, as described
|
||||
* <a href = http://dmawww.epfl.ch/benarous/Pmmi/interactive/rng7.htm>
|
||||
* Uses simulation of a Poisson process using Uniform deviates, as
|
||||
* described
|
||||
* <a href ="http://dmawww.epfl.ch/benarous/Pmmi/interactive/rng7.htm">
|
||||
* here</a>
|
||||
* @param mean Mean of the distribution
|
||||
* @returns long
|
||||
* @throws IllegalArgumentException if mean <= 0
|
||||
*
|
||||
*/
|
||||
public long nextPoisson(double mean) {
|
||||
double p = Math.exp(-mean);
|
||||
|
@ -287,59 +289,38 @@ public class RandomDataImpl implements RandomData{
|
|||
}
|
||||
}
|
||||
|
||||
public double nextGaussian(double mu,double sigma) {
|
||||
public double nextGaussian(double mu, double sigma) {
|
||||
if (sigma <= 0) {
|
||||
throw new IllegalArgumentException("Gaussian std dev must be > 0");
|
||||
}
|
||||
Random rand = getRan();
|
||||
return sigma*rand.nextGaussian() + mu;
|
||||
return sigma * rand.nextGaussian() + mu;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a random value from the exponential distribution
|
||||
* with expected value = <code>mean</code><br>
|
||||
* <strong>Definition</strong>:
|
||||
* <a href=http://www.itl.nist.gov/div898/handbook/eda/section3/eda3667.htm>
|
||||
* Exponential Distribution</a><br>
|
||||
* <strong>Preconditions</strong>: <ul>
|
||||
* <li>The specified mean <i>must</i> be non-negative</li>
|
||||
* </ul>
|
||||
* <strong>Algorithm Description</strong>: Uses the
|
||||
* <a href=http://www.jesus.ox.ac.uk/~clifford/a5/chap1/node5.html>
|
||||
* <a href="http://www.jesus.ox.ac.uk/~clifford/a5/chap1/node5.html">
|
||||
* Inversion Method</a> to generate exponential from uniform deviates.
|
||||
* @param mu Mean of the distribution
|
||||
* @return random value from exponential distribution
|
||||
*/
|
||||
public double nextExponential(double mean) {
|
||||
if (mean < 0.0) throw new IllegalArgumentException
|
||||
("Exponential mean must be >= 0");
|
||||
if (mean < 0.0) {
|
||||
throw new IllegalArgumentException
|
||||
("Exponential mean must be >= 0");
|
||||
}
|
||||
Random rand = getRan();
|
||||
double unif = rand.nextDouble();
|
||||
while (unif == 0.0d) {
|
||||
unif = rand.nextDouble();
|
||||
}
|
||||
return -mean*Math.log(unif);
|
||||
return -mean * Math.log(unif);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a uniformly distributed random value from the open interval
|
||||
* (<code>lower</code>,<code>upper</code>) (i.e., endpoints excluded)
|
||||
* <strong>Definition</strong>:
|
||||
* <a href=http://www.itl.nist.gov/div898/handbook/eda/section3/eda3662.htm>
|
||||
* Uniform Distribution</a> <code>lower</code> and <code>upper - lower</code>
|
||||
* are the
|
||||
* <a href = http://www.itl.nist.gov/div898/handbook/eda/section3/eda364.htm>
|
||||
* location and scale parameters</a>, respectively<br>
|
||||
* <strong>Algorithm Description</strong>: 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).
|
||||
* @param lower lower endpoint of the interval of support
|
||||
* @param upper upper endpoint of the interval of support
|
||||
* @return uniformly distributed random value between lower
|
||||
* and upper (exclusive)
|
||||
* @exception IllegalArgumentException thrown if
|
||||
* <code>lower</code> is not strictly less than <code>upper</code>.
|
||||
* random double if Random.nextDouble() returns 0).
|
||||
* This is necessary to provide a symmetric output interval
|
||||
* (both endpoints excluded).
|
||||
*/
|
||||
public double nextUniform(double lower, double upper) {
|
||||
if (lower >= upper) {
|
||||
|
@ -347,16 +328,18 @@ public class RandomDataImpl implements RandomData{
|
|||
("lower bound must be <= upper bound");
|
||||
}
|
||||
Random rand = getRan();
|
||||
double result = lower + rand.nextDouble()*(upper-lower);
|
||||
double result = lower + rand.nextDouble() * (upper - lower);
|
||||
while (result == lower) {
|
||||
result = lower + rand.nextDouble()*(upper-lower);
|
||||
result = lower + rand.nextDouble() * (upper - lower);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the static Random used to generate random data.<br>
|
||||
* Creates and initializes if null
|
||||
* Returns the static Random used to generate random data.
|
||||
* <p>
|
||||
* Creates and initializes if null.
|
||||
*
|
||||
* @return the static Random used to generate random data
|
||||
*/
|
||||
private Random getRan() {
|
||||
|
@ -368,8 +351,10 @@ public class RandomDataImpl implements RandomData{
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the static SecureRandom used to generate secure random data.<br>
|
||||
* Returns the static SecureRandom used to generate secure random data.
|
||||
* <p>
|
||||
* Creates and initializes if null.
|
||||
*
|
||||
* @return the static SecureRandom used to generate secure random data
|
||||
*/
|
||||
private SecureRandom getSecRan() {
|
||||
|
@ -381,8 +366,10 @@ public class RandomDataImpl implements RandomData{
|
|||
}
|
||||
|
||||
/**
|
||||
* Reseeds the random number generator with the supplied seed. Will
|
||||
* create and initialize if null.
|
||||
* Reseeds the random number generator with the supplied seed.
|
||||
* <p>
|
||||
* Will create and initialize if null.
|
||||
*
|
||||
* @param seed the seed value to use
|
||||
*/
|
||||
public void reSeed(long seed) {
|
||||
|
@ -394,18 +381,22 @@ public class RandomDataImpl implements RandomData{
|
|||
|
||||
/**
|
||||
* Reseeds the secure random number generator with the current time
|
||||
* in milliseconds. Will create and initialize if null.
|
||||
* in milliseconds.
|
||||
* <p>
|
||||
* Will create and initialize if null.
|
||||
*/
|
||||
public void reSeedSecure() {
|
||||
if (rand == null) {
|
||||
rand = new Random();
|
||||
if (secRand == null) {
|
||||
secRand = new SecureRandom();
|
||||
}
|
||||
rand.setSeed(System.currentTimeMillis());
|
||||
secRand.setSeed(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
/**
|
||||
* Reseeds the secure random number generator with the supplied seed.
|
||||
* <p>
|
||||
* Will create and initialize if null.
|
||||
*
|
||||
* @param seed the seed value to use
|
||||
*/
|
||||
public void reSeedSecure(long seed) {
|
||||
|
@ -417,7 +408,7 @@ public class RandomDataImpl implements RandomData{
|
|||
|
||||
/**
|
||||
* Reseeds the random number generator with the current time
|
||||
* in milliseconds
|
||||
* in milliseconds.
|
||||
*/
|
||||
public void reSeed() {
|
||||
if (rand == null) {
|
||||
|
@ -429,18 +420,23 @@ public class RandomDataImpl implements RandomData{
|
|||
/**
|
||||
* Sets the PRNG algorithm for the underlying SecureRandom instance
|
||||
* using the Security Provider API, as defined in
|
||||
* <a href=http://java.sun.com/j2se/1.3/docs/guide/security/CryptoSpec.html#AppA>
|
||||
* Java Cryptography Architecture API Specification & Reference</a><p>
|
||||
* <strong>USAGE NOTE:</strong> This method carries <i>significant</i> overhead
|
||||
* and may take several seconds to execute.</p>
|
||||
* <a href="http://java.sun.com/j2se/1.3/docs/guide/security/
|
||||
* CryptoSpec.html#AppA">
|
||||
* Java Cryptography Architecture API Specification & Reference.</a>
|
||||
* <p>
|
||||
* <strong>USAGE NOTE:</strong> This method carries <i>significant</i>
|
||||
* overhead and may take several seconds to execute.
|
||||
*
|
||||
* @param algorithm the name of the PRNG algorithm
|
||||
* @param provider the name of the provider
|
||||
* @throws NoSuchAlgorithmException if the specified algorithm is not available
|
||||
* @throws NoSuchProviderException if the specified provider is not installed
|
||||
* @throws NoSuchAlgorithmException if the specified algorithm
|
||||
* is not available
|
||||
* @throws NoSuchProviderException if the specified provider
|
||||
* is not installed
|
||||
*/
|
||||
public void setSecureAlgorithm(String algorithm, String provider)
|
||||
throws NoSuchAlgorithmException,NoSuchProviderException {
|
||||
secRand = SecureRandom.getInstance(algorithm,provider);
|
||||
throws NoSuchAlgorithmException, NoSuchProviderException {
|
||||
secRand = SecureRandom.getInstance(algorithm, provider);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -460,22 +456,22 @@ public class RandomDataImpl implements RandomData{
|
|||
}
|
||||
|
||||
int[] index = getNatural(n);
|
||||
shuffle(index,n-k);
|
||||
shuffle(index, n - k);
|
||||
int[] result = new int[k];
|
||||
for (int i = 0; i < k; i++) {
|
||||
result[i] = index[n-i-1];
|
||||
result[i] = index[n - i - 1];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses a 2-cycle permutation shuffle to generate a random
|
||||
* permutation of <code>c.size()</code> and then returns the
|
||||
* elements whose indexes correspond to the elements of the
|
||||
* generated permutation. This technique is described, and
|
||||
* proven to generate random samples,
|
||||
* <a href=http://www.maths.abdn.ac.uk/~igc/tch/mx4002/notes/node83.html>
|
||||
* <strong>Algorithm Description</strong>: Uses a 2-cycle permutation
|
||||
* shuffle to generate a random permutation of <code>c.size()</code> and
|
||||
* then returns the elements whose indexes correspond to the elements of
|
||||
* the generated permutation.
|
||||
* This technique is described, and proven to generate random samples,
|
||||
* <a href="http://www.maths.abdn.ac.uk/~igc/tch/mx4002/notes/node83.html">
|
||||
* here</a>
|
||||
*/
|
||||
public Object[] nextSample(Collection c, int k) {
|
||||
|
@ -490,9 +486,9 @@ public class RandomDataImpl implements RandomData{
|
|||
}
|
||||
|
||||
Object[] objects = c.toArray();
|
||||
int[] index = nextPermutation(len,k);
|
||||
int[] index = nextPermutation(len, k);
|
||||
Object[] result = new Object[k];
|
||||
for (int i = 0; i < k; i ++) {
|
||||
for (int i = 0; i < k; i++) {
|
||||
result[i] = objects[index[i]];
|
||||
}
|
||||
return result;
|
||||
|
@ -501,19 +497,19 @@ public class RandomDataImpl implements RandomData{
|
|||
//------------------------Private methods----------------------------------
|
||||
|
||||
/**
|
||||
* Uses a 2-cycle permutation shuffle to randomly re-order the last
|
||||
* end elements of list
|
||||
* <strong>Algorithm Description</strong>: Uses a 2-cycle permutation
|
||||
* shuffle to randomly re-order the last <code>end</code> elements of list.
|
||||
*
|
||||
* @param list list to be shuffled
|
||||
* @end element past which shuffling begins
|
||||
*/
|
||||
private void shuffle(int[] list, int end) {
|
||||
int target = 0;
|
||||
for (int i = list.length-1 ; i >= end; i--) {
|
||||
for (int i = list.length - 1 ; i >= end; i--) {
|
||||
if (i == 0) {
|
||||
target = 0;
|
||||
} else {
|
||||
target = nextInt(0,i);
|
||||
target = nextInt(0, i);
|
||||
}
|
||||
int temp = list[target];
|
||||
list[target] = list[i];
|
||||
|
@ -522,7 +518,7 @@ public class RandomDataImpl implements RandomData{
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns an array representing n
|
||||
* Returns an array representing n.
|
||||
*
|
||||
* @param n the natural number to represent
|
||||
* @return array with entries = elements of n
|
||||
|
|
|
@ -69,7 +69,7 @@ import org.apache.commons.math.stat.UnivariateImpl;
|
|||
* Test cases for the RandomData class.
|
||||
*
|
||||
* @author Phil Steitz
|
||||
* @version $Revision: 1.4 $ $Date: 2003/05/29 20:35:45 $
|
||||
* @version $Revision: 1.5 $ $Date: 2003/06/04 02:45:49 $
|
||||
*/
|
||||
|
||||
public final class RandomDataTest extends TestCase {
|
||||
|
@ -462,9 +462,9 @@ public final class RandomDataTest extends TestCase {
|
|||
assertTrue("same seeds",
|
||||
!hex.equals(randomData.nextSecureHexString(40)));
|
||||
|
||||
/* TODO: probably should remove this test as the package grows,
|
||||
* since it takes about 4 seconds
|
||||
*/
|
||||
/* remove this test back soon,
|
||||
* since it takes about 4 seconds */
|
||||
|
||||
randomData.setSecureAlgorithm("SHA1PRNG","SUN");
|
||||
assertTrue("different seeds",
|
||||
!hex.equals(randomData.nextSecureHexString(40)));
|
||||
|
@ -480,7 +480,21 @@ public final class RandomDataTest extends TestCase {
|
|||
fail("expecting NoSuchProviderException");
|
||||
} catch (NoSuchProviderException ex) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
// test reseeding without first using the generators
|
||||
RandomDataImpl rd = new RandomDataImpl();
|
||||
rd.reSeed(100);
|
||||
double ret = rd.nextLong(1,2);
|
||||
RandomDataImpl rd2 = new RandomDataImpl();
|
||||
rd2.reSeedSecure(2000);
|
||||
ret = rd2.nextSecureLong(1,2);
|
||||
rd = new RandomDataImpl();
|
||||
rd.reSeed();
|
||||
ret = rd.nextLong(1,2);
|
||||
rd2 = new RandomDataImpl();
|
||||
rd2.reSeedSecure();
|
||||
ret = rd2.nextSecureLong(1,2);
|
||||
}
|
||||
|
||||
/** tests for nextSample() sampling from Collection */
|
||||
|
|
Loading…
Reference in New Issue