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 <[email protected]>
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>