This is an automated email from the ASF dual-hosted git repository.

aherbert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-numbers.git


The following commit(s) were added to refs/heads/master by this push:
     new 79fbf9d  Added more random distribution types to the Complex 
performance test.
79fbf9d is described below

commit 79fbf9d06bf96bffa841ad3abe7e87acb7e70a71
Author: Alex Herbert <aherb...@apache.org>
AuthorDate: Thu Jan 30 00:50:42 2020 +0000

    Added more random distribution types to the Complex performance test.
    
    This adds commons-rng-sampling to the parent pom for use in data
    generation.
---
 commons-numbers-examples/examples-jmh/pom.xml      | 10 ++++
 .../examples/jmh/complex/ComplexPerformance.java   | 59 +++++++++++++++++-----
 pom.xml                                            |  5 ++
 3 files changed, 61 insertions(+), 13 deletions(-)

diff --git a/commons-numbers-examples/examples-jmh/pom.xml 
b/commons-numbers-examples/examples-jmh/pom.xml
index e29bc68..6d9ff4c 100644
--- a/commons-numbers-examples/examples-jmh/pom.xml
+++ b/commons-numbers-examples/examples-jmh/pom.xml
@@ -47,6 +47,16 @@
     </dependency>
 
     <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-rng-simple</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-rng-sampling</artifactId>
+    </dependency>
+
+    <dependency>
       <groupId>org.openjdk.jmh</groupId>
       <artifactId>jmh-core</artifactId>
       <version>${jmh.version}</version>
diff --git 
a/commons-numbers-examples/examples-jmh/src/main/java/org/apache/commons/numbers/examples/jmh/complex/ComplexPerformance.java
 
b/commons-numbers-examples/examples-jmh/src/main/java/org/apache/commons/numbers/examples/jmh/complex/ComplexPerformance.java
index b22daf7..0517bf3 100644
--- 
a/commons-numbers-examples/examples-jmh/src/main/java/org/apache/commons/numbers/examples/jmh/complex/ComplexPerformance.java
+++ 
b/commons-numbers-examples/examples-jmh/src/main/java/org/apache/commons/numbers/examples/jmh/complex/ComplexPerformance.java
@@ -18,6 +18,9 @@
 package org.apache.commons.numbers.examples.jmh.complex;
 
 import org.apache.commons.numbers.complex.Complex;
+import org.apache.commons.rng.UniformRandomProvider;
+import 
org.apache.commons.rng.sampling.distribution.ZigguratNormalizedGaussianSampler;
+import org.apache.commons.rng.simple.RandomSource;
 import org.openjdk.jmh.annotations.Benchmark;
 import org.openjdk.jmh.annotations.BenchmarkMode;
 import org.openjdk.jmh.annotations.Fork;
@@ -31,7 +34,6 @@ import org.openjdk.jmh.annotations.State;
 import org.openjdk.jmh.annotations.Warmup;
 
 import java.util.Arrays;
-import java.util.SplittableRandom;
 import java.util.concurrent.TimeUnit;
 import java.util.function.BiFunction;
 import java.util.function.Predicate;
@@ -58,6 +60,9 @@ public class ComplexPerformance {
         Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.MAX_VALUE,
         -Double.MAX_VALUE, Double.MIN_VALUE, -Double.MIN_VALUE, 0.0, -0.0, 
Double.NaN};
 
+    /** The range to use for uniform random numbers. */
+    private static final double RANGE = 3.456789;
+
     /**
      * Contains the size of numbers.
      */
@@ -90,7 +95,7 @@ public class ComplexPerformance {
         /**
          * The type of the data.
          */
-        @Param({"cis", "random", "edge"})
+        @Param({"cis", "vector", "log-uniform", "uniform", "edge"})
         private String type;
 
         /**
@@ -107,7 +112,7 @@ public class ComplexPerformance {
          */
         @Setup
         public void setup() {
-            numbers = createNumbers(new SplittableRandom());
+            numbers = 
createNumbers(RandomSource.create(RandomSource.XO_RO_SHI_RO_128_PP));
         }
 
         /**
@@ -116,12 +121,22 @@ public class ComplexPerformance {
          * @param rng Random number generator.
          * @return the random complex number
          */
-        Complex[] createNumbers(SplittableRandom rng) {
+        Complex[] createNumbers(UniformRandomProvider rng) {
             Supplier<Complex> generator;
             if ("cis".equals(type)) {
                 generator = () -> Complex.ofCis(rng.nextDouble() * 2 * 
Math.PI);
-            } else if ("random".equals(type)) {
-                generator = () -> Complex.ofCartesian(createRandomNumber(rng), 
createRandomNumber(rng));
+            } else if ("vector".equals(type)) {
+                // An unnormalised random vector is created using a Gaussian 
sample
+                // for each dimension. Normalisation would create a cis number.
+                // This is effectively a polar complex number with random 
modulus
+                // in [-pi, pi] and random magnitude in a range defined by a 
Chi-squared
+                // distribution with 2 degrees of freedom.
+                final ZigguratNormalizedGaussianSampler s = 
ZigguratNormalizedGaussianSampler.of(rng);
+                generator = () -> Complex.ofCartesian(s.sample(), s.sample());
+            } else if ("log-uniform".equals(type)) {
+                generator = () -> 
Complex.ofCartesian(createLogUniformNumber(rng), createLogUniformNumber(rng));
+            } else if ("uniform".equals(type)) {
+                generator = () -> 
Complex.ofCartesian(createUniformNumber(rng), createUniformNumber(rng));
             } else if ("edge".equals(type)) {
                 generator = () -> Complex.ofCartesian(createEdgeNumber(rng), 
createEdgeNumber(rng));
             } else {
@@ -155,7 +170,7 @@ public class ComplexPerformance {
         @Setup
         public void setup() {
             // Do not call super.setup() so we recycle the RNG and avoid 
duplicates
-            final SplittableRandom rng = new SplittableRandom();
+            final UniformRandomProvider rng = 
RandomSource.create(RandomSource.XO_RO_SHI_RO_128_PP);
             numbers = createNumbers(rng);
             numbers2 = createNumbers(rng);
         }
@@ -185,7 +200,7 @@ public class ComplexPerformance {
         @Setup
         public void setup() {
             // Do not call super.setup() so we recycle the RNG and avoid 
duplicates
-            final SplittableRandom rng = new SplittableRandom();
+            final UniformRandomProvider rng = 
RandomSource.create(RandomSource.XO_RO_SHI_RO_128_PP);
             numbers = createNumbers(rng);
             numbers2 = 
Arrays.stream(createNumbers(rng)).mapToDouble(Complex::real).toArray();
         }
@@ -207,12 +222,14 @@ public class ComplexPerformance {
 
     /**
      * Creates a random double number with a random sign and mantissa and a 
large range for
-     * the exponent. The numbers will not be uniform over the range.
+     * the exponent. The numbers will not be uniform over the range. This 
samples randomly
+     * using the components of a double. The limiting distribution is the 
log-uniform distribution.
      *
      * @param rng Random number generator.
      * @return the random number
+     * @see <a 
href="https://en.wikipedia.org/wiki/Reciprocal_distribution";>Reciprocal 
(log-uniform) distribution</a>
      */
-    private static double createRandomNumber(SplittableRandom rng) {
+    private static double createLogUniformNumber(UniformRandomProvider rng) {
         // Create random doubles using random bits in the sign bit and the 
mantissa.
         // Then create an exponent in the range -64 to 64. Thus the sum product
         // of 4 max or min values will not over or underflow.
@@ -224,13 +241,29 @@ public class ComplexPerformance {
     }
 
     /**
+     * Creates a random double number with a random sign and uniform range.
+     *
+     * @param rng Random number generator.
+     * @return the random number
+     */
+    private static double createUniformNumber(UniformRandomProvider rng) {
+        // Note: [0, 1) - 1 is [-1, 0).
+        // Since the 1 is a 50/50 sample the result is the interval [-1, 1)
+        // using the 2^54 dyadic rationals in the interval.
+        // The range is not critical. The numbers will have approximately 50%
+        // with the same exponent, max, matching that of RANGE and the rest 
smaller
+        // exponents down to (max - 53) since the uniform deviate is limited 
to 2^-53.
+        return (rng.nextDouble() - rng.nextInt(1)) * RANGE;
+    }
+
+    /**
      * Creates a random double number that will be an edge case:
      * {@code +/-inf, +/-max, +/-min, +/-0, nan}.
      *
      * @param rng Random number generator.
      * @return the random number
      */
-    private static double createEdgeNumber(SplittableRandom rng) {
+    private static double createEdgeNumber(UniformRandomProvider rng) {
         return EDGE_NUMBERS[rng.nextInt(EDGE_NUMBERS.length)];
     }
 
@@ -591,8 +624,8 @@ public class ComplexPerformance {
     }
 
     // Binary operations on a complex and a real number.
-    // These only benchmark methods on the real component as the 
-    // following are expected to be the same speed as the real-only operations 
+    // These only benchmark methods on the real component as the
+    // following are expected to be the same speed as the real-only operations
     // given the equivalent primitive operations:
     // - multiplyImaginary
     // - divideImaginary
diff --git a/pom.xml b/pom.xml
index 7e6f48d..9d13e2e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -179,6 +179,11 @@
         <artifactId>commons-rng-simple</artifactId>
         <version>${numbers.commons.rng.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.apache.commons</groupId>
+        <artifactId>commons-rng-sampling</artifactId>
+        <version>${numbers.commons.rng.version}</version>
+      </dependency>
     </dependencies>
   </dependencyManagement>
 

Reply via email to