You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by er...@apache.org on 2016/05/17 13:28:19 UTC

[1/7] [math] MATH-1341

Repository: commons-math
Updated Branches:
  refs/heads/develop 085816b7c -> 57e01f404


MATH-1341

Replacement for "o.a.c.m.random.RandomDataGenerator".
Features:
* No trivial syntactic sugar for sampling from distributions
* No duplicate code (secure vs non-secure data generation share the same code)
* No lazy initialization

New class also obsoletes class "RandomGeneratorFactory".


Project: http://git-wip-us.apache.org/repos/asf/commons-math/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-math/commit/363be2fe
Tree: http://git-wip-us.apache.org/repos/asf/commons-math/tree/363be2fe
Diff: http://git-wip-us.apache.org/repos/asf/commons-math/diff/363be2fe

Branch: refs/heads/develop
Commit: 363be2fea66f861d7ec4f893a05901fa0c7ecf92
Parents: f695c9c
Author: Gilles <er...@apache.org>
Authored: Fri May 13 15:40:26 2016 +0200
Committer: Gilles <er...@apache.org>
Committed: Fri May 13 15:40:26 2016 +0200

----------------------------------------------------------------------
 .../commons/math4/random/RandomUtils.java       | 492 +++++++++++++++++++
 1 file changed, 492 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-math/blob/363be2fe/src/main/java/org/apache/commons/math4/random/RandomUtils.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math4/random/RandomUtils.java b/src/main/java/org/apache/commons/math4/random/RandomUtils.java
new file mode 100644
index 0000000..e72655a
--- /dev/null
+++ b/src/main/java/org/apache/commons/math4/random/RandomUtils.java
@@ -0,0 +1,492 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.math4.random;
+
+import java.util.Random;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import org.apache.commons.math4.exception.MathInternalError;
+import org.apache.commons.math4.exception.NotANumberException;
+import org.apache.commons.math4.exception.NotFiniteNumberException;
+import org.apache.commons.math4.exception.NotStrictlyPositiveException;
+import org.apache.commons.math4.exception.NumberIsTooLargeException;
+import org.apache.commons.math4.exception.util.LocalizedFormats;
+import org.apache.commons.math4.rng.UniformRandomProvider;
+import org.apache.commons.math4.util.MathArrays;
+
+/**
+ * Factory for creating generators of miscellaneous data.
+ *
+ * @since 4.0
+ */
+public class RandomUtils {
+    /**
+     * Class contains only static methods.
+     */
+    private RandomUtils() {}
+
+    /**
+     * @param rng Underlying generator. Reference is copied so the RNG
+     * is shared with the caller.
+     * @return a {@link DataGenerator data generator}.
+     */
+    public static DataGenerator createDataGenerator(final UniformRandomProvider rng) {
+        return new DataGenerator(rng);
+    }
+
+    /**
+     * Wraps an instance of the JDK's {@link Random} class.
+     * The actual generation of random numbers will be delegated to that
+     * instance.
+     * <p>
+     * If cryptographically secure data is required, one can use this
+     * factory method, with an instance of the {@link java.security.SecureRandom}
+     * class as the argument.
+     * Note that data generation will be much slower in this case.
+     * </p>
+     *
+     * @param rng Underlying generator. Reference is copied so the RNG
+     * is shared with the caller.
+     * @return a {@link DataGenerator data generator}.
+     */
+    public static DataGenerator createDataGenerator(final Random rng) {
+        return createDataGenerator(asUniformRandomProvider(rng));
+    }
+
+    /**
+     * Wraps a {@link Random} instance.
+     *
+     * @param rng JDK {@link Random} instance to which the random number
+     * generation is delegated. Reference is copied so the RNG is shared
+     * with the caller.
+     * @return a {@link UniformRandomProvider} instance.
+     */
+    public static UniformRandomProvider asUniformRandomProvider(final Random rng) {
+        return new UniformRandomProvider() {
+            /** {@inheritDoc} */
+            @Override
+            public void nextBytes(byte[] bytes) {
+                rng.nextBytes(bytes);
+            }
+
+            /** {@inheritDoc} */
+            @Override
+            public void nextBytes(byte[] bytes,
+                                  int start,
+                                  int len) {
+                final byte[] reduced = new byte[len];
+                rng.nextBytes(reduced);
+                System.arraycopy(reduced, 0, bytes, start, len);
+            }
+
+            /** {@inheritDoc} */
+            @Override
+            public int nextInt() {
+                return rng.nextInt();
+            }
+
+            /** {@inheritDoc} */
+            @Override
+            public int nextInt(int n) {
+                if (n <= 0) {
+                    throw new NotStrictlyPositiveException(n);
+                }
+                return rng.nextInt(n);
+            }
+
+            /** {@inheritDoc} */
+            @Override
+            public long nextLong() {
+                return rng.nextLong();
+            }
+
+            /** {@inheritDoc} */
+            @Override
+            public long nextLong(long n) {
+                // Code copied from "o.a.c.m.rng.internal.BaseProvider".
+
+                if (n > 0) {
+                    long bits;
+                    long val;
+                    do {
+                        bits = rng.nextLong() >>> 1;
+                        val  = bits % n;
+                    } while (bits - val + (n - 1) < 0);
+                    return val;
+                }
+
+                throw new NotStrictlyPositiveException(n);
+            }
+
+            /** {@inheritDoc} */
+            @Override
+            public boolean nextBoolean() {
+                return rng.nextBoolean();
+            }
+
+            /** {@inheritDoc} */
+            @Override
+            public float nextFloat() {
+                return rng.nextFloat();
+            }
+
+            /** {@inheritDoc} */
+            @Override
+            public double nextDouble() {
+                return rng.nextDouble();
+            }
+        };
+    }
+
+    /**
+     * Various random data generation routines.
+     */
+    public static class DataGenerator {
+        /** Underlying RNG. */
+        private final UniformRandomProvider rng;
+
+        /**
+         * @param rng Underlying generator.
+         */
+        DataGenerator(UniformRandomProvider rng) {
+            this.rng = rng;
+        }
+
+        /**
+         * Generates a random string of hex characters of length {@code len}.
+         *
+         * <strong>Algorithm Description:</strong> how hexadecimal strings are
+         * generated depends on the value of the {@code useSha1} argument.
+         *
+         * <ul>
+         *  <li>If {@code useSha1 == false}, a 2-step process is used:
+         *   <ol>
+         *    <li>
+         *     {@code len / 2 + 1} binary bytes are generated using the underlying
+         *     generator.
+         *    </li>
+         *    <li>
+         *     Each binary byte is translated into 2 hex digits.
+         *    </li>
+         *   </ol>
+         *  </li>
+         *  <li>
+         *   If {@code useSha1 == true}, hex strings are generated in 40-byte
+         *   segments using a 3-step process:
+         *   <ol>
+         *    <li>
+         *     20 random bytes are generated using the underlying generator.
+         *    </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>
+         *  </li>
+         * </ul>
+         *
+         * @param len Length of the generated string.
+         * @param useSha1 Whether to use a digest.
+         * If {@code true} (resp. {@code false}), the 3-step (resp. 2-step)
+         * process will be used.
+         * @return the random string.
+         * @throws NotStrictlyPositiveException if {@code len <= 0}.
+         */
+        public String nextHexString(int len,
+                                    boolean useSha1) {
+            if (len <= 0) {
+                throw new NotStrictlyPositiveException(LocalizedFormats.LENGTH, len);
+            }
+
+            // Initialize output buffer.
+            final StringBuilder outBuffer = new StringBuilder();
+
+            if (!useSha1) {
+                // Generate int(len/2)+1 random bytes.
+                final byte[] randomBytes = new byte[(len / 2) + 1];
+                rng.nextBytes(randomBytes);
+
+                // Convert each byte to 2 hex digits.
+                for (int i = 0; i < randomBytes.length; i++) {
+                    final Integer c = Integer.valueOf(randomBytes[i]);
+
+                    // Add 128 to byte value to make interval 0-255 before
+                    // conversion to hex.
+                    // 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);
+                }
+            } else {
+                MessageDigest alg = null;
+                try {
+                    alg = MessageDigest.getInstance("SHA-1");
+                } catch (NoSuchAlgorithmException ex) {
+                    // Should never happen.
+                    throw new MathInternalError(ex);
+                }
+                alg.reset();
+
+                // Compute number of iterations required (40 bytes each).
+                final int numIter = (len / 40) + 1;
+
+                for (int iter = 1; iter < numIter + 1; iter++) {
+                    final byte[] randomBytes = new byte[40];
+                    rng.nextBytes(randomBytes);
+                    alg.update(randomBytes);
+
+                    // Create 20-byte binary hash.
+                    final byte[] hash = alg.digest();
+
+                    // Loop over the hash, converting each byte to 2 hex digits
+                    for (int i = 0; i < hash.length; i++) {
+                        final 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);
+        }
+
+        /**
+         * Generates a uniformly distributed random long integer between {@code lower}
+         * and {@code upper} (endpoints included).
+         *
+         * @param lower Lower bound for generated long integer.
+         * @param upper Upper bound for generated long integer.
+         * @return a random long integer greater than or equal to {@code lower}
+         * and less than or equal to {@code upper}
+         * @throws NumberIsTooLargeException if {@code lower >= upper}
+         */
+        public long nextLong(final long lower,
+                             final long upper) {
+            if (lower >= upper) {
+                throw new NumberIsTooLargeException(LocalizedFormats.LOWER_BOUND_NOT_BELOW_UPPER_BOUND,
+                                                    lower, upper, false);
+            }
+            final long max = (upper - lower) + 1;
+            if (max <= 0) {
+                // 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 + rng.nextLong(max);
+            }
+        }
+
+        /**
+         * Generates a uniformly distributed random value from the open interval
+         * {@code (lower, upper)} (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} and {@code upper - lower} are the
+         * <a href = "http://www.itl.nist.gov/div898/handbook/eda/section3/eda364.htm">
+         * location and scale parameters</a>, respectively.</p>
+         * <p>
+         * <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).
+         * </p>
+         *
+         * @param lower Lower bound of the support (excluded).
+         * @param upper Upper bound of the support (excluded).
+         * @return a uniformly distributed random value between lower and upper
+         * (both 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) {
+            return nextUniform(lower, upper, false);
+        }
+
+        /**
+         * Generates a uniformly distributed random value from the interval
+         * {@code (lower, upper)} or the interval {@code [lower, upper)}. The lower
+         * bound is thus optionally included, while the upper bound is always
+         * excluded.
+         * <p>
+         * <strong>Definition</strong>:
+         * <a href="http://www.itl.nist.gov/div898/handbook/eda/section3/eda3662.htm">
+         * Uniform Distribution</a> {@code lower} and {@code upper - lower} are the
+         * <a href = "http://www.itl.nist.gov/div898/handbook/eda/section3/eda364.htm">
+         * location and scale parameters</a>, respectively.</p>
+         * <p>
+         * <strong>Algorithm Description</strong>: if the lower bound is excluded,
+         * scales the output of "nextDouble()", but rejects 0 values (i.e. it
+         * will generate another random double if "nextDouble()" returns 0).
+         * This is necessary to provide a symmetric output interval (both
+         * endpoints excluded).
+         * </p>
+         *
+         * @param lower Lower bound of the support.
+         * @param upper Exclusive upper bound of the support.
+         * @param lowerInclusive {@code true} if the lower bound is inclusive.
+         * @return a uniformly distributed random value in the {@code (lower, upper)}
+         * interval, if {@code lowerInclusive} is {@code false}, or in the
+         * {@code [lower, upper)} interval, if {@code lowerInclusive} is
+         * {@code true}.
+         * @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) {
+            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();
+            }
+
+            // Ensure nextDouble() isn't 0.0
+            double u = rng.nextDouble();
+            while (!lowerInclusive && u <= 0.0) {
+                u = rng.nextDouble();
+            }
+
+            return u * upper + (1.0 - u) * lower;
+        }
+
+        /**
+         * Generates an integer array of length {@code k} whose entries are selected
+         * randomly, without repetition, from the integers {@code 0, ..., n - 1}
+         * (inclusive).
+         * <p>
+         * Generated arrays represent permutations of {@code n} taken {@code k} at a
+         * time.
+         * </p>
+         * <p>
+         * This method calls {@link MathArrays#shuffle(int[],UniformRandomProvider)
+         * MathArrays.shuffle} in order to create a random shuffle of the set
+         * of natural numbers {@code { 0, 1, ..., n - 1 }}.
+         * </p>
+         *
+         * @param n Domain of the permutation.
+         * @param k Size of the permutation.
+         * @return a random {@code k}-permutation of {@code n}, as an array of
+         * integers.
+         * @throws NumberIsTooLargeException if {@code k > n}.
+         * @throws NotStrictlyPositiveException if {@code k <= 0}.
+         */
+        public int[] nextPermutation(int n,
+                                     int k)
+            throws NumberIsTooLargeException, NotStrictlyPositiveException {
+            if (k > n) {
+                throw new NumberIsTooLargeException(LocalizedFormats.PERMUTATION_EXCEEDS_N,
+                                                    k, n, true);
+            }
+            if (k <= 0) {
+                throw new NotStrictlyPositiveException(LocalizedFormats.PERMUTATION_SIZE,
+                                                       k);
+            }
+
+            final int[] index = MathArrays.natural(n);
+            MathArrays.shuffle(index, rng);
+
+            // Return a new array containing the first "k" entries of "index".
+            return MathArrays.copyOf(index, k);
+        }
+
+        /**
+         * Returns a list of {@code k} objects selected randomly from the
+         * given {@code collection}.
+         *
+         * <p>
+         * Sampling is without replacement; but if {@code collection} contains
+         * identical objects, the sample may include repeats.  If all elements
+         * are distinct, the resulting object array represents a
+         * <a href="http://rkb.home.cern.ch/rkb/AN16pp/node250.html#SECTION0002500000000000000000">
+         * Simple Random Sample</a> of size {@code k} from the elements of
+         * the {@code collection}.
+         * </p>
+         * <p>
+         * This method calls {@link #nextPermutation(int,int) nextPermutation(c.size(), k)}
+         * in order to sample the collection.
+         * </p>
+         *
+         * @param <T> Type of objects held in the {@code collection}.
+         * @param collection Collection to be sampled.
+         * @param k Size of the sample.
+         * @return a random sample of {@code k} elements from the {@code collection}.
+         * @throws NumberIsTooLargeException if {@code k > collection.size()}.
+         * @throws NotStrictlyPositiveException if {@code k <= 0}.
+         */
+        public <T> List<T> nextSample(Collection<T> collection,
+                                      int k) {
+            final int len = collection.size();
+            if (k > len) {
+                throw new NumberIsTooLargeException(LocalizedFormats.SAMPLE_SIZE_EXCEEDS_COLLECTION_SIZE,
+                                                    k, len, true);
+            }
+            if (k <= 0) {
+                throw new NotStrictlyPositiveException(LocalizedFormats.NUMBER_OF_SAMPLES, k);
+            }
+
+            final T[] objects = (T[]) collection.toArray(new Object[len]);
+            final int[] index = nextPermutation(len, k);
+            final List<T> result = new ArrayList<T>(k);
+            for (int i = 0; i < k; i++) {
+                result.add(objects[index[i]]);
+            }
+
+            return result;
+        }
+    }
+}


[5/7] [math] MATH-1341

Posted by er...@apache.org.
MATH-1341

Use "RandomUtils" instead of "RandomDataGenerator".


Project: http://git-wip-us.apache.org/repos/asf/commons-math/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-math/commit/748cb609
Tree: http://git-wip-us.apache.org/repos/asf/commons-math/tree/748cb609
Diff: http://git-wip-us.apache.org/repos/asf/commons-math/diff/748cb609

Branch: refs/heads/develop
Commit: 748cb609306ee5a046a952a0ca13974ef0b6e770
Parents: 653b468
Author: Gilles <er...@apache.org>
Authored: Mon May 16 00:59:13 2016 +0200
Committer: Gilles <er...@apache.org>
Committed: Mon May 16 00:59:13 2016 +0200

----------------------------------------------------------------------
 .../math4/stat/ranking/NaturalRanking.java      | 29 ++++++++++++--------
 .../math4/stat/ranking/NaturalRankingTest.java  |  9 +++---
 2 files changed, 21 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-math/blob/748cb609/src/main/java/org/apache/commons/math4/stat/ranking/NaturalRanking.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math4/stat/ranking/NaturalRanking.java b/src/main/java/org/apache/commons/math4/stat/ranking/NaturalRanking.java
index d0c2ac2..404ac00 100644
--- a/src/main/java/org/apache/commons/math4/stat/ranking/NaturalRanking.java
+++ b/src/main/java/org/apache/commons/math4/stat/ranking/NaturalRanking.java
@@ -24,9 +24,9 @@ import java.util.List;
 
 import org.apache.commons.math4.exception.MathInternalError;
 import org.apache.commons.math4.exception.NotANumberException;
-import org.apache.commons.math4.random.RandomDataGenerator;
-import org.apache.commons.math4.random.RandomGenerator;
-import org.apache.commons.math4.random.Well19937c;
+import org.apache.commons.math4.rng.UniformRandomProvider;
+import org.apache.commons.math4.rng.RandomSource;
+import org.apache.commons.math4.random.RandomUtils;
 import org.apache.commons.math4.util.FastMath;
 
 
@@ -83,7 +83,7 @@ public class NaturalRanking implements RankingAlgorithm {
     private final TiesStrategy tiesStrategy;
 
     /** Source of random data - used only when ties strategy is RANDOM */
-    private final RandomDataGenerator randomData;
+    private final RandomUtils.DataGenerator randomData;
 
     /**
      * Create a NaturalRanking with default strategies for handling ties and NaNs.
@@ -98,7 +98,9 @@ public class NaturalRanking implements RankingAlgorithm {
      * @param tiesStrategy the TiesStrategy to use
      */
     public NaturalRanking(TiesStrategy tiesStrategy) {
-        this(DEFAULT_NAN_STRATEGY, tiesStrategy, new Well19937c());
+        this(DEFAULT_NAN_STRATEGY,
+             tiesStrategy,
+             RandomSource.create(RandomSource.WELL_19937_C));
     }
 
     /**
@@ -116,8 +118,11 @@ public class NaturalRanking implements RankingAlgorithm {
      * @param nanStrategy NaNStrategy to use
      * @param tiesStrategy TiesStrategy to use
      */
-    public NaturalRanking(NaNStrategy nanStrategy, TiesStrategy tiesStrategy) {
-        this(nanStrategy, tiesStrategy, new Well19937c());
+    public NaturalRanking(NaNStrategy nanStrategy,
+                          TiesStrategy tiesStrategy) {
+        this(nanStrategy,
+             tiesStrategy,
+             RandomSource.create(RandomSource.WELL_19937_C));
     }
 
     /**
@@ -126,7 +131,7 @@ public class NaturalRanking implements RankingAlgorithm {
      *
      * @param randomGenerator source of random data
      */
-    public NaturalRanking(RandomGenerator randomGenerator) {
+    public NaturalRanking(UniformRandomProvider randomGenerator) {
         this(DEFAULT_NAN_STRATEGY, TiesStrategy.RANDOM, randomGenerator);
     }
 
@@ -138,21 +143,21 @@ public class NaturalRanking implements RankingAlgorithm {
      * @param randomGenerator source of random data
      */
     public NaturalRanking(NaNStrategy nanStrategy,
-                          RandomGenerator randomGenerator) {
+                          UniformRandomProvider randomGenerator) {
         this(nanStrategy, TiesStrategy.RANDOM, randomGenerator);
     }
 
     /**
      * @param nanStrategy NaN strategy.
-     * @param randomGenerator RNG.
      * @param tiesStrategy Tie strategy.
+     * @param randomGenerator RNG.
      */
     private NaturalRanking(NaNStrategy nanStrategy,
                            TiesStrategy tiesStrategy,
-                           RandomGenerator randomGenerator) {
+                           UniformRandomProvider randomGenerator) {
         this.nanStrategy = nanStrategy;
         this.tiesStrategy = tiesStrategy;
-        randomData = new RandomDataGenerator(randomGenerator);
+        randomData = RandomUtils.createDataGenerator(randomGenerator);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/commons-math/blob/748cb609/src/test/java/org/apache/commons/math4/stat/ranking/NaturalRankingTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/math4/stat/ranking/NaturalRankingTest.java b/src/test/java/org/apache/commons/math4/stat/ranking/NaturalRankingTest.java
index 73e0370..46b2ede 100644
--- a/src/test/java/org/apache/commons/math4/stat/ranking/NaturalRankingTest.java
+++ b/src/test/java/org/apache/commons/math4/stat/ranking/NaturalRankingTest.java
@@ -19,8 +19,8 @@ package org.apache.commons.math4.stat.ranking;
 import org.junit.Assert;
 import org.apache.commons.math4.TestUtils;
 import org.apache.commons.math4.exception.NotANumberException;
-import org.apache.commons.math4.random.JDKRandomGenerator;
-import org.apache.commons.math4.random.RandomGenerator;
+import org.apache.commons.math4.rng.UniformRandomProvider;
+import org.apache.commons.math4.rng.RandomSource;
 import org.apache.commons.math4.stat.ranking.NaNStrategy;
 import org.apache.commons.math4.stat.ranking.NaturalRanking;
 import org.apache.commons.math4.stat.ranking.TiesStrategy;
@@ -172,10 +172,9 @@ public class NaturalRankingTest {
 
     @Test
     public void testNaNsFixedTiesRandom() {
-        RandomGenerator randomGenerator = new JDKRandomGenerator();
-        randomGenerator.setSeed(1000);
+        UniformRandomProvider randomGenerator = RandomSource.create(RandomSource.JDK, 1000L);
         NaturalRanking ranking = new NaturalRanking(NaNStrategy.FIXED,
-                randomGenerator);
+                                                    randomGenerator);
         double[] ranks = ranking.rank(exampleData);
         double[] correctRanks = { 5, 3, 6, 7, 3, 8, Double.NaN, 1, 2 };
         TestUtils.assertEquals(correctRanks, ranks, 0d);


[2/7] [math] MATH-1341

Posted by er...@apache.org.
MATH-1341

Unit tests.


Project: http://git-wip-us.apache.org/repos/asf/commons-math/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-math/commit/412a8a0b
Tree: http://git-wip-us.apache.org/repos/asf/commons-math/tree/412a8a0b
Diff: http://git-wip-us.apache.org/repos/asf/commons-math/diff/412a8a0b

Branch: refs/heads/develop
Commit: 412a8a0ba61c84d71c0cc740ba7e50c10f3bf9ae
Parents: 363be2f
Author: Gilles <er...@apache.org>
Authored: Fri May 13 15:45:34 2016 +0200
Committer: Gilles <er...@apache.org>
Committed: Fri May 13 15:45:34 2016 +0200

----------------------------------------------------------------------
 .../RandomUtilsDataGeneratorAbstractTest.java   | 453 +++++++++++++++++++
 .../RandomUtilsDataGeneratorJDKRandomTest.java  |  31 ++
 ...omUtilsDataGeneratorJDKSecureRandomTest.java |  31 ++
 3 files changed, 515 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-math/blob/412a8a0b/src/test/java/org/apache/commons/math4/random/RandomUtilsDataGeneratorAbstractTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/math4/random/RandomUtilsDataGeneratorAbstractTest.java b/src/test/java/org/apache/commons/math4/random/RandomUtilsDataGeneratorAbstractTest.java
new file mode 100644
index 0000000..f64d0fa
--- /dev/null
+++ b/src/test/java/org/apache/commons/math4/random/RandomUtilsDataGeneratorAbstractTest.java
@@ -0,0 +1,453 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.math4.random;
+
+import java.text.DecimalFormat;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Random;
+import java.util.List;
+
+import org.apache.commons.math4.TestUtils;
+import org.apache.commons.math4.exception.MathIllegalArgumentException;
+import org.apache.commons.math4.stat.Frequency;
+import org.apache.commons.math4.stat.inference.ChiSquareTest;
+import org.apache.commons.math4.util.FastMath;
+import org.apache.commons.math4.rng.UniformRandomProvider;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Test cases for the {@link RandomUtils#DataGenerator} class.
+ */
+public abstract class RandomUtilsDataGeneratorAbstractTest {
+    private final long smallSampleSize = 1000;
+    private final double[] expected = { 250, 250, 250, 250 };
+    private final int largeSampleSize = 10000;
+    private final String[] hex = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
+                                   "a", "b", "c", "d", "e", "f" };
+    private final ChiSquareTest testStatistic = new ChiSquareTest();
+    /** Data generator. */
+    private final RandomUtils.DataGenerator randomData;
+
+    /**
+     * @param rng RNG.
+     */
+    protected RandomUtilsDataGeneratorAbstractTest(UniformRandomProvider rng) {
+        randomData = RandomUtils.createDataGenerator(rng);
+    }
+
+    @Test
+    public void testNextLongExtremeValues() {
+        long x = randomData.nextLong(Long.MIN_VALUE, Long.MAX_VALUE);
+        long y = randomData.nextLong(Long.MIN_VALUE, Long.MAX_VALUE);
+        Assert.assertFalse(x == y);
+    }
+
+    @Test
+    public void testNextUniformExtremeValues() {
+        double x = randomData.nextUniform(-Double.MAX_VALUE, Double.MAX_VALUE);
+        double y = randomData.nextUniform(-Double.MAX_VALUE, Double.MAX_VALUE);
+        Assert.assertFalse(x == y);
+        Assert.assertFalse(Double.isNaN(x));
+        Assert.assertFalse(Double.isNaN(y));
+        Assert.assertFalse(Double.isInfinite(x));
+        Assert.assertFalse(Double.isInfinite(y));
+    }
+
+    @Test
+    public void testNextLongIAE() {
+        try {
+            randomData.nextLong(4, 3);
+            Assert.fail("MathIllegalArgumentException expected");
+        } catch (MathIllegalArgumentException ex) {
+            // ignored
+        }
+    }
+
+    @Test
+    public void testNextLongNegativeToPositiveRange() {
+        for (int i = 0; i < 5; i++) {
+            checkNextLongUniform(-3, 5);
+            checkNextLongUniform(-3, 6);
+        }
+    }
+
+    @Test
+    public void testNextLongNegativeRange() {
+        for (int i = 0; i < 5; i++) {
+            checkNextLongUniform(-7, -4);
+            checkNextLongUniform(-15, -2);
+            checkNextLongUniform(Long.MIN_VALUE + 1, Long.MIN_VALUE + 12);
+        }
+    }
+
+    @Test
+    public void testNextLongPositiveRange() {
+        for (int i = 0; i < 5; i++) {
+            checkNextLongUniform(0, 3);
+            checkNextLongUniform(2, 12);
+            checkNextLongUniform(Long.MAX_VALUE - 12, Long.MAX_VALUE - 1);
+        }
+    }
+
+    private void checkNextLongUniform(long min, long max) {
+        final Frequency freq = new Frequency();
+        for (int i = 0; i < smallSampleSize; i++) {
+            final long value = randomData.nextLong(min, max);
+            Assert.assertTrue("nextLong range: " + value + " " + min + " " + max,
+                              (value >= min) && (value <= max));
+            freq.addValue(value);
+        }
+        final int len = ((int) (max - min)) + 1;
+        final long[] observed = new long[len];
+        for (int i = 0; i < len; i++) {
+            observed[i] = freq.getCount(min + i);
+        }
+        final double[] expected = new double[len];
+        for (int i = 0; i < len; i++) {
+            expected[i] = 1d / len;
+        }
+
+        TestUtils.assertChiSquareAccept(expected, observed, 0.01);
+    }
+
+    @Test
+    public void testNextLongWideRange() {
+        long lower = -0x6543210FEDCBA987L;
+        long upper =  0x456789ABCDEF0123L;
+        long max = Long.MIN_VALUE;
+        long min = Long.MAX_VALUE;
+        for (int i = 0; i < 10000000; ++i) {
+            long r = randomData.nextLong(lower, upper);
+            max = FastMath.max(max, r);
+            min = FastMath.min(min, r);
+            Assert.assertTrue(r >= lower);
+            Assert.assertTrue(r <= upper);
+        }
+        double ratio = (((double) max)   - ((double) min)) /
+                       (((double) upper) - ((double) lower));
+        Assert.assertTrue(ratio > 0.99999);
+    }
+ 
+   /** Test dispersion and failure modes for "nextHex". */
+    @Test
+    public void testNextHexWithoutSha1() {
+        checkNextHex(false);
+    }
+    @Test
+    public void testNextHexWithSha1() {
+        checkNextHex(true);
+    }
+
+    /**
+     * @param useSha1 Alternative.
+     */
+    private void checkNextHex(boolean useSha1) {
+        try {
+            randomData.nextHexString(-1, useSha1);
+            Assert.fail("negative length supplied -- MathIllegalArgumentException expected");
+        } catch (MathIllegalArgumentException ex) {
+            // ignored
+        }
+        try {
+            randomData.nextHexString(0, useSha1);
+            Assert.fail("zero length supplied -- MathIllegalArgumentException expected");
+        } catch (MathIllegalArgumentException ex) {
+            // ignored
+        }
+        String hexString = randomData.nextHexString(3, useSha1);
+        if (hexString.length() != 3) {
+            Assert.fail("incorrect length for generated string");
+        }
+        hexString = randomData.nextHexString(1, useSha1);
+        if (hexString.length() != 1) {
+            Assert.fail("incorrect length for generated string");
+        }
+        try {
+            hexString = randomData.nextHexString(0, useSha1);
+            Assert.fail("zero length requested -- expecting MathIllegalArgumentException");
+        } catch (MathIllegalArgumentException ex) {
+            // ignored
+        }
+        Frequency f = new Frequency();
+        for (int i = 0; i < smallSampleSize; i++) {
+            hexString = randomData.nextHexString(100, useSha1);
+            if (hexString.length() != 100) {
+                Assert.fail("incorrect length for generated string");
+            }
+            for (int j = 0; j < hexString.length(); j++) {
+                f.addValue(hexString.substring(j, j + 1));
+            }
+        }
+        double[] expected = new double[16];
+        long[] observed = new long[16];
+        for (int i = 0; i < 16; i++) {
+            expected[i] = (double) smallSampleSize * 100 / 16;
+            observed[i] = f.getCount(hex[i]);
+        }
+        TestUtils.assertChiSquareAccept(expected, observed, 0.001);
+    }
+
+    @Test
+    public void testNextUniformIAE() {
+        try {
+            randomData.nextUniform(4, 3);
+            Assert.fail("MathIllegalArgumentException expected");
+        } catch (MathIllegalArgumentException ex) {
+            // ignored
+        }
+        try {
+            randomData.nextUniform(0, Double.POSITIVE_INFINITY);
+            Assert.fail("MathIllegalArgumentException expected");
+        } catch (MathIllegalArgumentException ex) {
+            // ignored
+        }
+        try {
+            randomData.nextUniform(Double.NEGATIVE_INFINITY, 0);
+            Assert.fail("MathIllegalArgumentException expected");
+        } catch (MathIllegalArgumentException ex) {
+            // ignored
+        }
+        try {
+            randomData.nextUniform(0, Double.NaN);
+            Assert.fail("MathIllegalArgumentException expected");
+        } catch (MathIllegalArgumentException ex) {
+            // ignored
+        }
+        try {
+            randomData.nextUniform(Double.NaN, 0);
+            Assert.fail("MathIllegalArgumentException expected");
+        } catch (MathIllegalArgumentException ex) {
+            // ignored
+        }
+    }
+
+    @Test
+    public void testNextUniformUniformPositiveBounds() {
+        for (int i = 0; i < 5; i++) {
+            checkNextUniformUniform(0, 10);
+        }
+    }
+
+    @Test
+    public void testNextUniformUniformNegativeToPositiveBounds() {
+        for (int i = 0; i < 5; i++) {
+            checkNextUniformUniform(-3, 5);
+        }
+    }
+
+    @Test
+    public void testNextUniformUniformNegaiveBounds() {
+        for (int i = 0; i < 5; i++) {
+            checkNextUniformUniform(-7, -3);
+        }
+    }
+
+    @Test
+    public void testNextUniformUniformMaximalInterval() {
+        for (int i = 0; i < 5; i++) {
+            checkNextUniformUniform(-Double.MAX_VALUE, Double.MAX_VALUE);
+        }
+    }
+
+    private void checkNextUniformUniform(double min, double max) {
+        // Set up bin bounds - min, binBound[0], ..., binBound[binCount-2], max
+        final int binCount = 5;
+        final double binSize = max / binCount - min/binCount; // Prevent overflow in extreme value case
+        final double[] binBounds = new double[binCount - 1];
+        binBounds[0] = min + binSize;
+        for (int i = 1; i < binCount - 1; i++) {
+            binBounds[i] = binBounds[i - 1] + binSize;  // + instead of * to avoid overflow in extreme case
+        }
+
+        final Frequency freq = new Frequency();
+        for (int i = 0; i < smallSampleSize; i++) {
+            final double value = randomData.nextUniform(min, max);
+            Assert.assertTrue("nextUniform range", (value > min) && (value < max));
+            // Find bin
+            int j = 0;
+            while (j < binCount - 1 && value > binBounds[j]) {
+                j++;
+            }
+            freq.addValue(j);
+        }
+
+        final long[] observed = new long[binCount];
+        for (int i = 0; i < binCount; i++) {
+            observed[i] = freq.getCount(i);
+        }
+        final double[] expected = new double[binCount];
+        for (int i = 0; i < binCount; i++) {
+            expected[i] = 1d / binCount;
+        }
+
+        TestUtils.assertChiSquareAccept(expected, observed, 0.01);
+    }
+
+    /** test exclusive endpoints of nextUniform **/
+    @Test
+    public void testNextUniformExclusiveEndpoints() {
+        for (int i = 0; i < 1000; i++) {
+            double u = randomData.nextUniform(0.99, 1);
+            Assert.assertTrue(u > 0.99 && u < 1);
+        }
+    }
+
+    /** Tests for "nextSample" (sampling from Collection). */
+    @Test
+    public void testNextSample() {
+        Object[][] c = { { "0", "1" }, { "0", "2" }, { "0", "3" },
+                { "0", "4" }, { "1", "2" }, { "1", "3" }, { "1", "4" },
+                { "2", "3" }, { "2", "4" }, { "3", "4" } };
+        long[] observed = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+        double[] expected = { 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 };
+
+        HashSet<Object> cPop = new HashSet<Object>(); // {0,1,2,3,4}
+        for (int i = 0; i < 5; i++) {
+            cPop.add(Integer.toString(i));
+        }
+
+        Object[] sets = new Object[10]; // 2-sets from 5
+        for (int i = 0; i < 10; i++) {
+            HashSet<Object> hs = new HashSet<Object>();
+            hs.add(c[i][0]);
+            hs.add(c[i][1]);
+            sets[i] = hs;
+        }
+
+        for (int i = 0; i < 1000; i++) {
+            List<Object> cSamp = randomData.nextSample(cPop, 2);
+            observed[findSample(sets, cSamp)]++;
+        }
+
+        // Use ChiSquare dist with df = 10-1 = 9, alpha = 0.001
+        // Change to 21.67 for alpha = 0.01
+        Assert.assertTrue("chi-square test -- will fail about 1 in 1000 times",
+                          testStatistic.chiSquare(expected, observed) < 27.88);
+
+        // Make sure sample of size = size of collection returns same collection
+        HashSet<Object> hs = new HashSet<Object>();
+        hs.add("one");
+        List<Object> one = randomData.nextSample(hs, 1);
+        String oneString = (String) one.get(0);
+        if (one.size() != 1 ||
+            !oneString.equals("one")) {
+            Assert.fail("bad sample for set size = 1, sample size = 1");
+        }
+
+        // Make sure we fail for sample size > collection size.
+        try {
+            one = randomData.nextSample(hs, 2);
+            Assert.fail("sample size > set size, expecting MathIllegalArgumentException");
+        } catch (MathIllegalArgumentException ex) {
+            // ignored
+        }
+
+        // Make sure we fail for empty collection.
+        try {
+            hs = new HashSet<Object>();
+            one = randomData.nextSample(hs, 0);
+            Assert.fail("n = k = 0, expecting MathIllegalArgumentException");
+        } catch (MathIllegalArgumentException ex) {
+            // ignored
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private int findSample(Object[] u, List<Object> sampList) {
+        Object[] samp = sampList.toArray(new Object[sampList.size()]);
+        for (int i = 0; i < u.length; i++) {
+            HashSet<Object> set = (HashSet<Object>) u[i];
+            HashSet<Object> sampSet = new HashSet<Object>();
+            for (int j = 0; j < samp.length; j++) {
+                sampSet.add(samp[j]);
+            }
+            if (set.equals(sampSet)) {
+                return i;
+            }
+        }
+        Assert.fail("sample not found:{" + samp[0] + "," + samp[1] + "}");
+        return -1;
+    }
+
+    /** tests for nextPermutation */
+    @Test
+    public void testNextPermutation() {
+        int[][] p = { { 0, 1, 2 }, { 0, 2, 1 }, { 1, 0, 2 }, { 1, 2, 0 },
+                      { 2, 0, 1 }, { 2, 1, 0 } };
+        long[] observed = { 0, 0, 0, 0, 0, 0 };
+        double[] expected = { 100, 100, 100, 100, 100, 100 };
+
+        for (int i = 0; i < 600; i++) {
+            int[] perm = randomData.nextPermutation(3, 3);
+            observed[findPerm(p, perm)]++;
+        }
+
+        String[] labels = {"{0, 1, 2}", "{ 0, 2, 1 }", "{ 1, 0, 2 }",
+                           "{ 1, 2, 0 }", "{ 2, 0, 1 }", "{ 2, 1, 0 }"};
+        TestUtils.assertChiSquareAccept(labels, expected, observed, 0.001);
+
+        // Check size = 1 boundary case
+        int[] perm = randomData.nextPermutation(1, 1);
+        if ((perm.length != 1) || (perm[0] != 0)) {
+            Assert.fail("bad permutation for n = 1, sample k = 1");
+
+            // Make sure we fail for k size > n
+            try {
+                perm = randomData.nextPermutation(2, 3);
+                Assert.fail("permutation k > n, expecting MathIllegalArgumentException");
+            } catch (MathIllegalArgumentException ex) {
+                // ignored
+            }
+
+            // Make sure we fail for n = 0
+            try {
+                perm = randomData.nextPermutation(0, 0);
+                Assert.fail("permutation k = n = 0, expecting MathIllegalArgumentException");
+            } catch (MathIllegalArgumentException ex) {
+                // ignored
+            }
+
+            // Make sure we fail for k < n < 0
+            try {
+                perm = randomData.nextPermutation(-1, -3);
+                Assert.fail("permutation k < n < 0, expecting MathIllegalArgumentException");
+            } catch (MathIllegalArgumentException ex) {
+                // ignored
+            }
+
+        }
+    }
+
+    private int findPerm(int[][] p, int[] samp) {
+        for (int i = 0; i < p.length; i++) {
+            boolean good = true;
+            for (int j = 0; j < samp.length; j++) {
+                if (samp[j] != p[i][j]) {
+                    good = false;
+                }
+            }
+            if (good) {
+                return i;
+            }
+        }
+        Assert.fail("permutation not found");
+        return -1;
+    }
+}

http://git-wip-us.apache.org/repos/asf/commons-math/blob/412a8a0b/src/test/java/org/apache/commons/math4/random/RandomUtilsDataGeneratorJDKRandomTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/math4/random/RandomUtilsDataGeneratorJDKRandomTest.java b/src/test/java/org/apache/commons/math4/random/RandomUtilsDataGeneratorJDKRandomTest.java
new file mode 100644
index 0000000..a511826
--- /dev/null
+++ b/src/test/java/org/apache/commons/math4/random/RandomUtilsDataGeneratorJDKRandomTest.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.math4.random;
+
+import java.util.Random;
+
+/**
+ * Test cases for the {@link RandomUtils#DataGenerator} class, using
+ * {@link Random} as the underlying source of randomness.
+ */
+public class RandomUtilsDataGeneratorJDKRandomTest
+    extends RandomUtilsDataGeneratorAbstractTest {
+
+    public RandomUtilsDataGeneratorJDKRandomTest() {
+        super(RandomUtils.asUniformRandomProvider(new Random(1000)));
+    }
+}

http://git-wip-us.apache.org/repos/asf/commons-math/blob/412a8a0b/src/test/java/org/apache/commons/math4/random/RandomUtilsDataGeneratorJDKSecureRandomTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/math4/random/RandomUtilsDataGeneratorJDKSecureRandomTest.java b/src/test/java/org/apache/commons/math4/random/RandomUtilsDataGeneratorJDKSecureRandomTest.java
new file mode 100644
index 0000000..3df4435
--- /dev/null
+++ b/src/test/java/org/apache/commons/math4/random/RandomUtilsDataGeneratorJDKSecureRandomTest.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.math4.random;
+
+import java.security.SecureRandom;
+
+/**
+ * Test cases for the {@link RandomUtils#DataGenerator} class, using
+ * {@link SecureRandom} as the underlying source of randomness.
+ */
+public class RandomUtilsDataGeneratorJDKSecureRandomTest
+    extends RandomUtilsDataGeneratorAbstractTest {
+
+    public RandomUtilsDataGeneratorJDKSecureRandomTest() {
+        super(RandomUtils.asUniformRandomProvider(new SecureRandom(new byte[] {-12, 34, -56, 78})));
+    }
+}


[7/7] [math] Merge branch 'feature-MATH-1341' into develop

Posted by er...@apache.org.
Merge branch 'feature-MATH-1341' into develop

Completes issue MATH-1341 (see JIRA).


Project: http://git-wip-us.apache.org/repos/asf/commons-math/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-math/commit/57e01f40
Tree: http://git-wip-us.apache.org/repos/asf/commons-math/tree/57e01f40
Diff: http://git-wip-us.apache.org/repos/asf/commons-math/diff/57e01f40

Branch: refs/heads/develop
Commit: 57e01f404ecf77b31d301231bf09184ee87e69f7
Parents: 085816b 0f9ce49
Author: Gilles <er...@apache.org>
Authored: Tue May 17 14:53:36 2016 +0200
Committer: Gilles <er...@apache.org>
Committed: Tue May 17 14:53:36 2016 +0200

----------------------------------------------------------------------
 .../commons/math4/random/RandomUtils.java       | 492 +++++++++++++++++++
 .../math4/stat/ranking/NaturalRanking.java      |  60 +--
 .../RandomUtilsDataGeneratorAbstractTest.java   | 453 +++++++++++++++++
 .../RandomUtilsDataGeneratorJDKRandomTest.java  |  31 ++
 ...omUtilsDataGeneratorJDKSecureRandomTest.java |  31 ++
 .../math4/stat/ranking/NaturalRankingTest.java  |   9 +-
 6 files changed, 1041 insertions(+), 35 deletions(-)
----------------------------------------------------------------------



[6/7] [math] MATH-1341

Posted by er...@apache.org.
MATH-1341

Avoid "unchecked cast" warning.


Project: http://git-wip-us.apache.org/repos/asf/commons-math/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-math/commit/0f9ce497
Tree: http://git-wip-us.apache.org/repos/asf/commons-math/tree/0f9ce497
Diff: http://git-wip-us.apache.org/repos/asf/commons-math/diff/0f9ce497

Branch: refs/heads/develop
Commit: 0f9ce497b0c6841e3aca845336ad095012c41da7
Parents: 748cb60
Author: Gilles <er...@apache.org>
Authored: Mon May 16 02:23:00 2016 +0200
Committer: Gilles <er...@apache.org>
Committed: Mon May 16 02:23:00 2016 +0200

----------------------------------------------------------------------
 src/main/java/org/apache/commons/math4/random/RandomUtils.java | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-math/blob/0f9ce497/src/main/java/org/apache/commons/math4/random/RandomUtils.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math4/random/RandomUtils.java b/src/main/java/org/apache/commons/math4/random/RandomUtils.java
index e72655a..610b320 100644
--- a/src/main/java/org/apache/commons/math4/random/RandomUtils.java
+++ b/src/main/java/org/apache/commons/math4/random/RandomUtils.java
@@ -479,11 +479,11 @@ public class RandomUtils {
                 throw new NotStrictlyPositiveException(LocalizedFormats.NUMBER_OF_SAMPLES, k);
             }
 
-            final T[] objects = (T[]) collection.toArray(new Object[len]);
+            final ArrayList<T> objects = new ArrayList<T>(collection);
             final int[] index = nextPermutation(len, k);
             final List<T> result = new ArrayList<T>(k);
             for (int i = 0; i < k; i++) {
-                result.add(objects[index[i]]);
+                result.add(objects.get(index[i]));
             }
 
             return result;


[4/7] [math] MATH-1341

Posted by er...@apache.org.
MATH-1341

Select a seed that make unit tests pass.


Project: http://git-wip-us.apache.org/repos/asf/commons-math/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-math/commit/653b4685
Tree: http://git-wip-us.apache.org/repos/asf/commons-math/tree/653b4685
Diff: http://git-wip-us.apache.org/repos/asf/commons-math/diff/653b4685

Branch: refs/heads/develop
Commit: 653b46857a4a48252bfb094e39ee9937b2079fa2
Parents: 0338025
Author: Gilles <er...@apache.org>
Authored: Mon May 16 00:58:01 2016 +0200
Committer: Gilles <er...@apache.org>
Committed: Mon May 16 00:58:01 2016 +0200

----------------------------------------------------------------------
 .../math4/random/RandomUtilsDataGeneratorJDKSecureRandomTest.java  | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-math/blob/653b4685/src/test/java/org/apache/commons/math4/random/RandomUtilsDataGeneratorJDKSecureRandomTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/math4/random/RandomUtilsDataGeneratorJDKSecureRandomTest.java b/src/test/java/org/apache/commons/math4/random/RandomUtilsDataGeneratorJDKSecureRandomTest.java
index 3df4435..cd4696b 100644
--- a/src/test/java/org/apache/commons/math4/random/RandomUtilsDataGeneratorJDKSecureRandomTest.java
+++ b/src/test/java/org/apache/commons/math4/random/RandomUtilsDataGeneratorJDKSecureRandomTest.java
@@ -26,6 +26,6 @@ public class RandomUtilsDataGeneratorJDKSecureRandomTest
     extends RandomUtilsDataGeneratorAbstractTest {
 
     public RandomUtilsDataGeneratorJDKSecureRandomTest() {
-        super(RandomUtils.asUniformRandomProvider(new SecureRandom(new byte[] {-12, 34, -56, 78})));
+        super(RandomUtils.asUniformRandomProvider(new SecureRandom(new byte[] {1, 2, 3, 4})));
     }
 }


[3/7] [math] Use explicit constructor invocation ("this").

Posted by er...@apache.org.
Use explicit constructor invocation ("this").


Project: http://git-wip-us.apache.org/repos/asf/commons-math/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-math/commit/03380256
Tree: http://git-wip-us.apache.org/repos/asf/commons-math/tree/03380256
Diff: http://git-wip-us.apache.org/repos/asf/commons-math/diff/03380256

Branch: refs/heads/develop
Commit: 03380256795725c7d17db97d882a4c4da3b76b8d
Parents: 412a8a0
Author: Gilles <er...@apache.org>
Authored: Sat May 14 01:03:54 2016 +0200
Committer: Gilles <er...@apache.org>
Committed: Sat May 14 14:20:14 2016 +0200

----------------------------------------------------------------------
 .../math4/stat/ranking/NaturalRanking.java      | 43 +++++++++-----------
 1 file changed, 19 insertions(+), 24 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-math/blob/03380256/src/main/java/org/apache/commons/math4/stat/ranking/NaturalRanking.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math4/stat/ranking/NaturalRanking.java b/src/main/java/org/apache/commons/math4/stat/ranking/NaturalRanking.java
index d6efc09..d0c2ac2 100644
--- a/src/main/java/org/apache/commons/math4/stat/ranking/NaturalRanking.java
+++ b/src/main/java/org/apache/commons/math4/stat/ranking/NaturalRanking.java
@@ -26,6 +26,7 @@ import org.apache.commons.math4.exception.MathInternalError;
 import org.apache.commons.math4.exception.NotANumberException;
 import org.apache.commons.math4.random.RandomDataGenerator;
 import org.apache.commons.math4.random.RandomGenerator;
+import org.apache.commons.math4.random.Well19937c;
 import org.apache.commons.math4.util.FastMath;
 
 
@@ -88,10 +89,7 @@ public class NaturalRanking implements RankingAlgorithm {
      * Create a NaturalRanking with default strategies for handling ties and NaNs.
      */
     public NaturalRanking() {
-        super();
-        tiesStrategy = DEFAULT_TIES_STRATEGY;
-        nanStrategy = DEFAULT_NAN_STRATEGY;
-        randomData = null;
+        this(DEFAULT_NAN_STRATEGY, DEFAULT_TIES_STRATEGY, null);
     }
 
     /**
@@ -100,10 +98,7 @@ public class NaturalRanking implements RankingAlgorithm {
      * @param tiesStrategy the TiesStrategy to use
      */
     public NaturalRanking(TiesStrategy tiesStrategy) {
-        super();
-        this.tiesStrategy = tiesStrategy;
-        nanStrategy = DEFAULT_NAN_STRATEGY;
-        randomData = new RandomDataGenerator();
+        this(DEFAULT_NAN_STRATEGY, tiesStrategy, new Well19937c());
     }
 
     /**
@@ -112,10 +107,7 @@ public class NaturalRanking implements RankingAlgorithm {
      * @param nanStrategy the NaNStrategy to use
      */
     public NaturalRanking(NaNStrategy nanStrategy) {
-        super();
-        this.nanStrategy = nanStrategy;
-        tiesStrategy = DEFAULT_TIES_STRATEGY;
-        randomData = null;
+        this(nanStrategy, DEFAULT_TIES_STRATEGY, null);
     }
 
     /**
@@ -125,10 +117,7 @@ public class NaturalRanking implements RankingAlgorithm {
      * @param tiesStrategy TiesStrategy to use
      */
     public NaturalRanking(NaNStrategy nanStrategy, TiesStrategy tiesStrategy) {
-        super();
-        this.nanStrategy = nanStrategy;
-        this.tiesStrategy = tiesStrategy;
-        randomData = new RandomDataGenerator();
+        this(nanStrategy, tiesStrategy, new Well19937c());
     }
 
     /**
@@ -138,13 +127,9 @@ public class NaturalRanking implements RankingAlgorithm {
      * @param randomGenerator source of random data
      */
     public NaturalRanking(RandomGenerator randomGenerator) {
-        super();
-        this.tiesStrategy = TiesStrategy.RANDOM;
-        nanStrategy = DEFAULT_NAN_STRATEGY;
-        randomData = new RandomDataGenerator(randomGenerator);
+        this(DEFAULT_NAN_STRATEGY, TiesStrategy.RANDOM, randomGenerator);
     }
 
-
     /**
      * Create a NaturalRanking with the given NaNStrategy, TiesStrategy.RANDOM
      * and the given source of random data.
@@ -153,10 +138,20 @@ public class NaturalRanking implements RankingAlgorithm {
      * @param randomGenerator source of random data
      */
     public NaturalRanking(NaNStrategy nanStrategy,
-            RandomGenerator randomGenerator) {
-        super();
+                          RandomGenerator randomGenerator) {
+        this(nanStrategy, TiesStrategy.RANDOM, randomGenerator);
+    }
+
+    /**
+     * @param nanStrategy NaN strategy.
+     * @param randomGenerator RNG.
+     * @param tiesStrategy Tie strategy.
+     */
+    private NaturalRanking(NaNStrategy nanStrategy,
+                           TiesStrategy tiesStrategy,
+                           RandomGenerator randomGenerator) {
         this.nanStrategy = nanStrategy;
-        this.tiesStrategy = TiesStrategy.RANDOM;
+        this.tiesStrategy = tiesStrategy;
         randomData = new RandomDataGenerator(randomGenerator);
     }