Made PRNG pluggable for classes in the random package.

* Added RandomGeneratorinterface extracted from java.util.random.
* Added and abstract implementation, AbstractRandomGenerator providing default
  implementations of methods based on nextDouble().
* Added a constructor taking a RandomGenerator as an argument to RandomDataImpl
* Changed ValueServer to use a RandomData in its constructor.
* Changes to 1.0 classes should be backward compatible
  (including serialization).


git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/math/trunk@170243 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Phil Steitz 2005-05-15 18:23:35 +00:00
parent 9d8f4849c3
commit a4d35ef08b
9 changed files with 553 additions and 40 deletions

View File

@ -0,0 +1,250 @@
/*
* Copyright 2005 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math.random;
/**
* Abstract class implementing the {@link RandomGenerator} interface.
* Default implementations for all methods other than {@link #nextDouble()} and
* {@link #setSeed(long)} are provided.
* <p>
* All data generation methods are based on <code>nextDouble().</code>
* Concrete implementations <strong>must</strong> overrride
* this method and <strong>should</strong> provide better / more
* performant implementations of the other methods if the underlying PRNG
* supplies them.
*
* @version $Revision$ $Date$
*/
public abstract class AbstractRandomGenerator implements RandomGenerator {
/**
* Cached random normal value. The default implementation for
* {@link #nextGaussian} generates pairs of values and this field caches the
* second value so that the full algorithm is not executed for every
* activation. The value <code>Double.NaN</code> signals that there is
* no cached value. Use {@link #clear} to clear the cached value.
*/
private double cachedNormalDeviate = Double.NaN;
/**
* Construct a RandomGenerator.
*/
public AbstractRandomGenerator() {
super();
}
/**
* Clears the cache used by the default implementation of {@link #nextGaussian}.
* Implemementations that do not override the default
* implementation of <code>nextGaussian</code> should call this method
* in the implementation of {@link #setSeed(long)}
*/
public void clear() {
cachedNormalDeviate = Double.NaN;
}
/**
* Sets the seed of the underyling random number generator using a
* <code>long</code> seed. Sequences of values generated starting with the
* same seeds should be identical.
* <p>
* Implementations that do not override the default implementation of
* <code>nextGaussian</code> should include a call to {@link #clear} in the
* implementation of this method.
*
* @param seed the seed value
*/
public abstract void setSeed(long seed);
/**
* Generates random bytes and places them into a user-supplied
* byte array. The number of random bytes produced is equal to
* the length of the byte array.
* <p>
* The default implementation provided here fills the array with bytes
* extracted from random integers generated using {@link #nextInt}.
*
* @param bytes the non-null byte array in which to put the
* random bytes
*/
public void nextBytes(byte[] bytes) {
int bytesOut = 0;
while (bytesOut < bytes.length) {
int randInt = nextInt();
for (int i = 0; i < 3; i++) {
if ( i > 0) {
randInt = randInt >> 8;
}
bytes[bytesOut++] = (byte) randInt;
if (bytesOut == bytes.length) {
return;
}
}
}
}
/**
* Returns the next pseudorandom, uniformly distributed <code>int</code>
* value from this random number generator's sequence.
* All 2<font size="-1"><sup>32</sup></font> possible <tt>int</tt> values
* should be produced with (approximately) equal probability.
* <p>
* The default implementation provided here returns
* <pre>
* <code>(int) (nextDouble() * Integer.MAX_VALUE)</code>
* </pre>
*
* @return the next pseudorandom, uniformly distributed <code>int</code>
* value from this random number generator's sequence
*/
public int nextInt() {
return (int) (nextDouble() * Integer.MAX_VALUE);
}
/**
* Returns a pseudorandom, uniformly distributed <tt>int</tt> value
* between 0 (inclusive) and the specified value (exclusive), drawn from
* this random number generator's sequence.
* <p>
* The default implementation provided here returns
* <pre>
* <code>(int) (nextDouble() * n</code>
* </pre>
*
* @param n the bound on the random number to be returned. Must be
* positive.
* @return a pseudorandom, uniformly distributed <tt>int</tt>
* value between 0 (inclusive) and n (exclusive).
* @throws IllegalArgumentException if n is not positive.
*/
public int nextInt(int n) {
if (n <= 0 ) {
throw new IllegalArgumentException("upper bound must be positive");
}
int result = (int) (nextDouble() * n);
return result < n ? result : n - 1;
}
/**
* Returns the next pseudorandom, uniformly distributed <code>long</code>
* value from this random number generator's sequence. All
* 2<font size="-1"><sup>64</sup></font> possible <tt>long</tt> values
* should be produced with (approximately) equal probability.
* <p>
* The default implementation provided here returns
* <pre>
* <code>(long) (nextDouble() * Long.MAX_VALUE)</code>
* </pre>
*
* @return the next pseudorandom, uniformly distributed <code>long</code>
*value from this random number generator's sequence
*/
public long nextLong() {
return (long) (nextDouble() * Long.MAX_VALUE);
}
/**
* Returns the next pseudorandom, uniformly distributed
* <code>boolean</code> value from this random number generator's
* sequence.
* <p>
* The default implementation provided here returns
* <pre>
* <code>nextDouble() <= 0.5</code>
* </pre>
*
* @return the next pseudorandom, uniformly distributed
* <code>boolean</code> value from this random number generator's
* sequence
*/
public boolean nextBoolean() {
return nextDouble() <= 0.5;
}
/**
* Returns the next pseudorandom, uniformly distributed <code>float</code>
* value between <code>0.0</code> and <code>1.0</code> from this random
* number generator's sequence.
* <p>
* The default implementation provided here returns
* <pre>
* <code>(float) nextDouble() </code>
* </pre>
*
* @return the next pseudorandom, uniformly distributed <code>float</code>
* value between <code>0.0</code> and <code>1.0</code> from this
* random number generator's sequence
*/
public float nextFloat() {
return (float) nextDouble();
}
/**
* Returns the next pseudorandom, uniformly distributed
* <code>double</code> value between <code>0.0</code> and
* <code>1.0</code> from this random number generator's sequence.
* <p>
* This method provides the underlying source of random data used by the
* other methods.
*
* @return the next pseudorandom, uniformly distributed
* <code>double</code> value between <code>0.0</code> and
* <code>1.0</code> from this random number generator's sequence
*/
public abstract double nextDouble();
/**
* Returns the next pseudorandom, Gaussian ("normally") distributed
* <code>double</code> value with mean <code>0.0</code> and standard
* deviation <code>1.0</code> from this random number generator's sequence.
* <p>
* The default implementation provided here uses the <em>Polar Method</em>
* due to G.E.P. Box, M.E. Muller and G. Marsaglia, as described in
* D. Knuth, <u>The Art of Computer Programming</u>, 3.4.1C.
* <p>
* The algorithm generates a pair of independent random values. One of
* these is cached for reuse, so the full algorithm is not executed on each
* activation. Implementations that do not override this method should
* make sure to call {@link #clear} to clear the cached value in the
* implementation of {@link #setSeed(long)}.
*
* @return the next pseudorandom, Gaussian ("normally") distributed
* <code>double</code> value with mean <code>0.0</code> and
* standard deviation <code>1.0</code> from this random number
* generator's sequence
*/
public double nextGaussian() {
if (!Double.isNaN(cachedNormalDeviate)) {
double dev = cachedNormalDeviate;
cachedNormalDeviate = Double.NaN;
return dev;
}
double v1 =0;
double v2 = 0;
double s = 1;
while (s >=1 ) {
v1 = 2 * nextDouble() - 1;
v2 = 2 * nextDouble() - 1;
s = v1 * v1 + v2 * v2;
}
if (s != 0) {
s = Math.sqrt(-2 * Math.log(s)/s);
}
cachedNormalDeviate = v2 * s;
return v1 * s;
}
}

View File

@ -0,0 +1,27 @@
/*
* Copyright 2005 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math.random;
import java.util.Random;
/**
* Extension of <code>java.util.Random</code> to implement
* {@link RandomGenerator}.
*
* @version $Revision:$ $Date$
*/
public class JDKRandomGenerator extends Random implements RandomGenerator {
}

View File

@ -21,24 +21,28 @@ import java.security.MessageDigest;
import java.security.SecureRandom;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.Random;
import java.util.Collection;
/**
* Implements the {@link RandomData} interface using
* {@link java.util.Random} and {@link java.util.Random.SecureRandom} instances
* to generate data.
* Implements the {@link RandomData} interface using a {@link RandomGenerator}
* instance to generate non-secure data and a
* {@link java.security.SecureRandom} instance to provide data for the
* <code>nextSecureXxx</code> methods. If no <code>RandomGenerator</code>
* is provided in the constructor, the default is to use a generator based on
* {@link java.util.Random}. To plug in a different implementation,
* either implement <code>RandomGenerator</code> directly or extend
* {@link AbstractRandomGenerator}.
* <p>
* Supports reseeding the underlying pseudo-random number generator (PRNG).
* 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 {@link java.util.Random} and
* {@link java.util.Random.SecureRandom}.
* For details on the default PRNGs, see {@link java.util.Random} and
* {@link java.security.SecureRandom}.
* <p>
* <strong>Usage Notes</strong>: <ul>
* <li>
* Instance variables are used to maintain <code>Random</code> and
* Instance variables are used to maintain <code>RandomGenerator</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>
@ -52,15 +56,16 @@ import java.util.Collection;
* it any easier to predict subsequent values.</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>
* number generators are <strong>not</strong> intialized. If you do not
* explicitly seed the default non-secure generator, it is seeded with the current time
* in milliseconds on first use. The same holds for the secure generator.
* If you provide a <code>RandomGenerator</code> to the constructor, however,
* this generator is not reseeded by the constructor nor is it reseeded on
* first use. </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,
* to the corresponding methods on the underlying <code>RandomGenerator</code>
* and<code>SecureRandom</code> instances. Therefore,
* <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)
@ -79,7 +84,7 @@ public class RandomDataImpl implements RandomData, Serializable {
static final long serialVersionUID = -626730818244969716L;
/** underlying random number generator */
private Random rand = null;
private RandomGenerator rand = null;
/** underlying secure random number generator */
private SecureRandom secRand = null;
@ -89,6 +94,17 @@ public class RandomDataImpl implements RandomData, Serializable {
*/
public RandomDataImpl() {
}
/**
* Construct a RandomDataImpl using the supplied {@link RandomGenerator}
* as the source of (non-secure) random data.
*
* @param rand the source of (non-secure) random data
*/
public RandomDataImpl(RandomGenerator rand) {
super();
this.rand = rand;
}
/**
* <strong>Algorithm Description:</strong> hex strings are generated
@ -106,7 +122,7 @@ public class RandomDataImpl implements RandomData, Serializable {
}
//Get a random number generator
Random ran = getRan();
RandomGenerator ran = getRan();
//Initialize output buffer
StringBuffer outBuffer = new StringBuffer();
@ -148,7 +164,7 @@ public class RandomDataImpl implements RandomData, Serializable {
throw new IllegalArgumentException
("upper bound must be > lower bound");
}
Random rand = getRan();
RandomGenerator rand = getRan();
return lower + (int) (rand.nextDouble() * (upper - lower + 1));
}
@ -165,7 +181,7 @@ public class RandomDataImpl implements RandomData, Serializable {
throw new IllegalArgumentException
("upper bound must be > lower bound");
}
Random rand = getRan();
RandomGenerator rand = getRan();
return lower + (long) (rand.nextDouble() * (upper - lower + 1));
}
@ -291,7 +307,7 @@ public class RandomDataImpl implements RandomData, Serializable {
long n = 0;
double r = 1.0d;
double rnd = 1.0d;
Random rand = getRan();
RandomGenerator rand = getRan();
while (n < 1000 * mean) {
rnd = rand.nextDouble();
r = r * rnd;
@ -317,7 +333,7 @@ public class RandomDataImpl implements RandomData, Serializable {
if (sigma <= 0) {
throw new IllegalArgumentException("Gaussian std dev must be > 0");
}
Random rand = getRan();
RandomGenerator rand = getRan();
return sigma * rand.nextGaussian() + mu;
}
@ -338,7 +354,7 @@ public class RandomDataImpl implements RandomData, Serializable {
throw new IllegalArgumentException
("Exponential mean must be >= 0");
}
Random rand = getRan();
RandomGenerator rand = getRan();
double unif = rand.nextDouble();
while (unif == 0.0d) {
unif = rand.nextDouble();
@ -352,18 +368,19 @@ public class RandomDataImpl implements RandomData, Serializable {
* random double if Random.nextDouble() returns 0).
* This is necessary to provide a symmetric output interval
* (both endpoints excluded).
*
* @param lower the lower bound.
* @param upper the upper bound.
* @return the random value.
* @return a uniformly distributed random value from the interval (lower, upper)
*/
public double nextUniform(double lower, double upper) {
if (lower >= upper) {
throw new IllegalArgumentException
("lower bound must be <= upper bound");
}
Random rand = getRan();
RandomGenerator rand = getRan();
// insure nextDouble() isn't 0.0
// ensure nextDouble() isn't 0.0
double u = rand.nextDouble();
while(u <= 0.0){
u = rand.nextDouble();
@ -373,26 +390,27 @@ public class RandomDataImpl implements RandomData, Serializable {
}
/**
* Returns the static Random used to generate random data.
* Returns the RandomGenerator used to generate non-secure
* random data.
* <p>
* Creates and initializes if null.
* Creates and initializes a default generator if null.
*
* @return the static Random used to generate random data
* @return the Random used to generate random data
*/
private Random getRan() {
private RandomGenerator getRan() {
if (rand == null) {
rand = new Random();
rand = new JDKRandomGenerator();
rand.setSeed(System.currentTimeMillis());
}
return rand;
}
/**
* Returns the static SecureRandom used to generate secure random data.
* Returns the SecureRandom used to generate secure random data.
* <p>
* Creates and initializes if null.
*
* @return the static SecureRandom used to generate secure random data
* @return the SecureRandom used to generate secure random data
*/
private SecureRandom getSecRan() {
if (secRand == null) {
@ -411,7 +429,7 @@ public class RandomDataImpl implements RandomData, Serializable {
*/
public void reSeed(long seed) {
if (rand == null) {
rand = new Random();
rand = new JDKRandomGenerator();
}
rand.setSeed(seed);
}
@ -449,7 +467,7 @@ public class RandomDataImpl implements RandomData, Serializable {
*/
public void reSeed() {
if (rand == null) {
rand = new Random();
rand = new JDKRandomGenerator();
}
rand.setSeed(System.currentTimeMillis());
}
@ -574,5 +592,4 @@ public class RandomDataImpl implements RandomData, Serializable {
}
return natural;
}
}
}

View File

@ -0,0 +1,124 @@
/*
* Copyright 2005 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math.random;
/**
* Interface extracted from <code>java.util.Random</code>. This interface is
* implemented by {@link AbstractRandomGenerator}.
*
* @version $Revision:$ $Date$
*/
public interface RandomGenerator {
/**
* Sets the seed of the underyling random number generator using a
* <code>long</code> seed. Sequences of values generated starting with the
* same seeds should be identical.
*
* @param seed the seed value
*/
void setSeed(long seed);
/**
* Generates random bytes and places them into a user-supplied
* byte array. The number of random bytes produced is equal to
* the length of the byte array.
*
* @param bytes the non-null byte array in which to put the
* random bytes
*/
void nextBytes(byte[] bytes);
/**
* Returns the next pseudorandom, uniformly distributed <code>int</code>
* value from this random number generator's sequence.
* All 2<font size="-1"><sup>32</sup></font> possible <tt>int</tt> values
* should be produced with (approximately) equal probability.
*
* @return the next pseudorandom, uniformly distributed <code>int</code>
* value from this random number generator's sequence
*/
int nextInt();
/**
* Returns a pseudorandom, uniformly distributed <tt>int</tt> value
* between 0 (inclusive) and the specified value (exclusive), drawn from
* this random number generator's sequence.
*
* @param n the bound on the random number to be returned. Must be
* positive.
* @return a pseudorandom, uniformly distributed <tt>int</tt>
* value between 0 (inclusive) and n (exclusive).
* @throws IllegalArgumentException if n is not positive.
*/
int nextInt(int n);
/**
* Returns the next pseudorandom, uniformly distributed <code>long</code>
* value from this random number generator's sequence. All
* 2<font size="-1"><sup>64</sup></font> possible <tt>long</tt> values
* should be produced with (approximately) equal probability.
*
* @return the next pseudorandom, uniformly distributed <code>long</code>
*value from this random number generator's sequence
*/
long nextLong();
/**
* Returns the next pseudorandom, uniformly distributed
* <code>boolean</code> value from this random number generator's
* sequence.
*
* @return the next pseudorandom, uniformly distributed
* <code>boolean</code> value from this random number generator's
* sequence
*/
boolean nextBoolean();
/**
* Returns the next pseudorandom, uniformly distributed <code>float</code>
* value between <code>0.0</code> and <code>1.0</code> from this random
* number generator's sequence.
*
* @return the next pseudorandom, uniformly distributed <code>float</code>
* value between <code>0.0</code> and <code>1.0</code> from this
* random number generator's sequence
*/
float nextFloat();
/**
* Returns the next pseudorandom, uniformly distributed
* <code>double</code> value between <code>0.0</code> and
* <code>1.0</code> from this random number generator's sequence.
*
* @return the next pseudorandom, uniformly distributed
* <code>double</code> value between <code>0.0</code> and
* <code>1.0</code> from this random number generator's sequence
*/
double nextDouble();
/**
* Returns the next pseudorandom, Gaussian ("normally") distributed
* <code>double</code> value with mean <code>0.0</code> and standard
* deviation <code>1.0</code> from this random number generator's sequence.
*
* @return the next pseudorandom, Gaussian ("normally") distributed
* <code>double</code> value with mean <code>0.0</code> and
* standard deviation <code>1.0</code> from this random number
* generator's sequence
*/
double nextGaussian();
}

View File

@ -62,7 +62,7 @@ public class ValueServer {
private BufferedReader filePointer = null;
/** RandomDataImpl to use for random data generation */
private RandomDataImpl randomData = new RandomDataImpl();
private RandomData randomData = new RandomDataImpl();
// Data generation modes ======================================
@ -353,4 +353,14 @@ public class ValueServer {
return randomData.nextGaussian(mu, sigma);
}
/**
* Construct a ValueServer instance using a RandomData as its source
* of random data.
*
* @param randomData the RandomData instance used to source random data
*/
public ValueServer(RandomData randomData) {
super();
this.randomData = randomData;
}
}

View File

@ -0,0 +1,37 @@
/*
* Copyright 2005 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math.random;
import junit.framework.Test;
import junit.framework.TestSuite;
/**
* Test cases for the AbstractRandomGenerator class
*
* @version $Revision:$ $Date$
*/
public class AbstractRandomGeneratorTest extends RandomDataTest {
public AbstractRandomGeneratorTest(String name) {
super(name);
randomData = new RandomDataImpl(new TestRandomGenerator());
}
public static Test suite() {
TestSuite suite = new TestSuite(AbstractRandomGeneratorTest.class);
suite.setName("AbstractRandomGenerator Tests");
return suite;
}
}

View File

@ -32,10 +32,11 @@ import org.apache.commons.math.stat.descriptive.SummaryStatistics;
* @version $Revision$ $Date$
*/
public final class RandomDataTest extends RetryTestCase {
public class RandomDataTest extends RetryTestCase {
public RandomDataTest(String name) {
super(name);
randomData = new RandomDataImpl();
}
private long smallSampleSize = 1000;
@ -44,7 +45,7 @@ public final class RandomDataTest extends RetryTestCase {
private int tolerance = 50;
private String[] hex =
{"0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"};
private RandomDataImpl randomData = new RandomDataImpl();
protected RandomDataImpl randomData = null;
private ChiSquareTestImpl testStatistic = new ChiSquareTestImpl();
public void setUp() {
@ -400,7 +401,7 @@ public final class RandomDataTest extends RetryTestCase {
/** test reseeding, algorithm/provider games */
public void testConfig() throws NoSuchProviderException,
NoSuchAlgorithmException{
NoSuchAlgorithmException {
randomData.reSeed(1000);
double v = randomData.nextUniform(0,1);
randomData.reSeed();

View File

@ -0,0 +1,38 @@
/*
* Copyright 2005 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math.random;
import java.util.Random;
/**
* Dummy AbstractRandomGenerator concrete subclass that just wraps a
* java.util.Random instance. Used by AbstractRandomGeneratorTest to test
* default implementations in AbstractRandomGenerator.
*
* @version $Revision:$ $Date$
*/
public class TestRandomGenerator extends AbstractRandomGenerator {
private Random random = new Random();
public void setSeed(long seed) {
clear();
random.setSeed(seed);
}
public double nextDouble() {
return random.nextDouble();
}
}

View File

@ -39,7 +39,16 @@ The <action> type attribute can be add,update,fix,remove.
<body>
<release version="1.1" date="In Development"
description="Jakarta Commons Math 1.1 - Development">
<action dev="psteitz" type="update" due-to="C. Scott Ananian">
<action dev="psteitz" type="update">
Made PRNG pluggable for classes in the random package. Added
RandomGenerator interface extracted from java.util.random and abstract
implementation, AbstractRandomGenerator providing default
implementations of methods based on nextDouble(). Added a constructor
taking a RandomGenerator as an argument to RandomDataImpl. Changed
ValueServer to use a RandomData in its constructor. Changes to
1.0 classes should be backward compatible (including serialization).
</action>
<action dev="psteitz" type="update" due-to="C. Scott Ananian">
Ported numerics improvements in commons lang Fraction implementation.
Added utility methods for overflow-checked integer arithmetic and
improved gcd method in MathUtils.