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-rng.git


The following commit(s) were added to refs/heads/master by this push:
     new a2e5e79  RNG-148: Revert detection of infinite length vectors
a2e5e79 is described below

commit a2e5e7937a1ea62f38efa8f270aac378b8286ccf
Author: aherbert <aherb...@apache.org>
AuthorDate: Fri Jul 9 11:08:12 2021 +0100

    RNG-148: Revert detection of infinite length vectors
    
    Due to the change in RNG-154 the underlying Gaussian cannot have
    infinite tails.
---
 .../commons/rng/sampling/UnitSphereSampler.java    | 33 ++-------
 .../rng/sampling/UnitSphereSamplerTest.java        | 78 ++++++++--------------
 src/changes/changes.xml                            |  3 -
 3 files changed, 32 insertions(+), 82 deletions(-)

diff --git 
a/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/UnitSphereSampler.java
 
b/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/UnitSphereSampler.java
index e9b2a2a..76db7b0 100644
--- 
a/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/UnitSphereSampler.java
+++ 
b/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/UnitSphereSampler.java
@@ -104,8 +104,8 @@ public class UnitSphereSampler implements 
SharedStateObjectSampler<double[]> {
             final double y = sampler.sample();
             final double sum = x * x + y * y;
 
-            if (isInvalidSumForNormalization(sum)) {
-                // Invalid vector is discarded.
+            if (sum == 0) {
+                // Zero-norm vector is discarded.
                 return sample();
             }
 
@@ -141,8 +141,8 @@ public class UnitSphereSampler implements 
SharedStateObjectSampler<double[]> {
             final double z = sampler.sample();
             final double sum = x * x + y * y + z * z;
 
-            if (isInvalidSumForNormalization(sum)) {
-                // Invalid vector is discarded.
+            if (sum == 0) {
+                // Zero-norm vector is discarded.
                 return sample();
             }
 
@@ -187,8 +187,8 @@ public class UnitSphereSampler implements 
SharedStateObjectSampler<double[]> {
                 sum += x * x;
             }
 
-            if (isInvalidSumForNormalization(sum)) {
-                // Invalid vector is discarded.
+            if (sum == 0) {
+                // Zero-norm vector is discarded.
                 // Using recursion as it is highly unlikely to generate more
                 // than a few such vectors. It also protects against infinite
                 // loop (in case a buggy generator is used), by eventually
@@ -284,25 +284,4 @@ public class UnitSphereSampler implements 
SharedStateObjectSampler<double[]> {
         }
         return new UnitSphereSamplerND(dimension, rng);
     }
-
-    /**
-     * Returns true if the sum of squared components of a vector is invalid for
-     * normalization.
-     *
-     * <p>This is true for any sum where the factor {@code f = 1.0 / sqrt(sum)}
-     * cannot be used to create a unit length vector by multiplication. The sum
-     * is invalid if:
-     *
-     * <ul>
-     *  <li>{@code sum = 0} then {@code f = infinity}
-     *  <li>{@code sum = infinity} then {@code f = 0}
-     * </ul>
-     *
-     * @param sum Sum of squared components of a vector
-     * @return true if invalid for normalisation
-     */
-    private static boolean isInvalidSumForNormalization(double sum) {
-        // Note: Deliberate floating-point comparison with zero
-        return sum == 0 || sum == Double.POSITIVE_INFINITY;
-    }
 }
diff --git 
a/commons-rng-sampling/src/test/java/org/apache/commons/rng/sampling/UnitSphereSamplerTest.java
 
b/commons-rng-sampling/src/test/java/org/apache/commons/rng/sampling/UnitSphereSamplerTest.java
index 9733858..005d548 100644
--- 
a/commons-rng-sampling/src/test/java/org/apache/commons/rng/sampling/UnitSphereSamplerTest.java
+++ 
b/commons-rng-sampling/src/test/java/org/apache/commons/rng/sampling/UnitSphereSamplerTest.java
@@ -388,72 +388,46 @@ public class UnitSphereSamplerTest {
     }
 
     /**
-     * Test the edge case where the normalisation sum to divide by is zero.
+     * Test the edge case where the normalisation sum to divide by is zero for 
2D.
      */
     @Test
-    public void testInvalidInverseNormalisationWithZeroLength() {
-        for (int dim = 2; dim <= 4; dim++) {
-            testInvalidInverseNormalisationND(dim, true);
-        }
+    public void testInvalidInverseNormalisation2D() {
+        testInvalidInverseNormalisationND(2);
     }
 
     /**
-     * Test the edge case where the normalisation sum to divide by is infinite.
+     * Test the edge case where the normalisation sum to divide by is zero for 
3D.
      */
     @Test
-    public void testInvalidInverseNormalisationWithInfiniteLength() {
-        for (int dim = 2; dim <= 4; dim++) {
-            testInvalidInverseNormalisationND(dim, false);
-        }
+    public void testInvalidInverseNormalisation3D() {
+        testInvalidInverseNormalisationND(3);
     }
 
     /**
-     * Test the edge case where the normalisation sum to divide by is zero or 
infinite. This
-     * test requires generation of Gaussian samples with the value 0 or 
infinity. See RNG-55.
-     *
-     * @param dimension the dimension
-     * @param zeroSum true if the sum for the first vector should be zero
+     * Test the edge case where the normalisation sum to divide by is zero for 
4D.
+     */
+    @Test
+    public void testInvalidInverseNormalisation4D() {
+        testInvalidInverseNormalisationND(4);
+    }
+
+    /**
+     * Test the edge case where the normalisation sum to divide by is zero.
+     * This test requires generation of Gaussian samples with the value 0.
+     * See RNG-55.
      */
-    private static void testInvalidInverseNormalisationND(final int dimension, 
boolean zeroSum) {
+    private static void testInvalidInverseNormalisationND(final int dimension) 
{
         // Create a provider that will create a bad first sample but then 
recover.
         // This checks recursion will return a good value.
+        final UniformRandomProvider bad = new SplitMix64(0x1a2b3cL) {
+            private int count = -2 * dimension;
 
-        // This sampler will createbvalues that manipulate the underlying 
Gaussian sampler.
-        UniformRandomProvider bad;
-        if (zeroSum) {
-            // Create Gaussian samples of zero
-            bad = new SplitMix64(0x1a2b3cL) {
-                private int count = -2 * dimension;
-
-                @Override
-                public long nextLong() {
-                    // Return enough zeros to create Gaussian samples of zero 
for all coordinates.
-                    return count++ < 0 ? 0 : super.nextLong();
-                }
-            };
-        } else {
-            // Create a Gaussian sample of infinity.
-            // This only requires 1 infinite value to create an infinite 
length vector.
-            // Assumes the ZigguratNormalizedGaussianSampler.
-            // To create infinity requires a very large long value with the 
lowest 7 bits as 0,
-            // then two doubles of zero.
-            bad = new SplitMix64(0x1a2b3cL) {
-                private int lcount = -1;
-                private int dcount = -2;
-
-                @Override
-                public long nextLong() {
-                    return lcount++ < 0 ?
-                        (-1L << 7) & Long.MAX_VALUE :
-                        super.nextLong();
-                }
-
-                @Override
-                public double nextDouble() {
-                    return dcount++ < 0 ? 0 : super.nextDouble();
-                }
-            };
-        }
+            @Override
+            public long nextLong() {
+                // Return enough zeros to create Gaussian samples of zero for 
all coordinates.
+                return count++ < 0 ? 0 : super.nextLong();
+            }
+        };
 
         final double[] vector = UnitSphereSampler.of(dimension, bad).sample();
         Assert.assertEquals(dimension, vector.length);
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 77c87dd..e211d01 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -94,9 +94,6 @@ as 'flaky' in the report).
          New "ZigguratSampler" implementation of the modified "Ziggurat" 
algorithm for
          Gaussian and exponential sampling.
       </action>
-      <action dev="aherbert" type="fix" issue="148">
-        "UnitSphereSampler": Detect and discard infinite length vectors.
-      </action>
       <action dev="aherbert" type="add" issue="147">
          New "LevySampler" to sample from a Levy distribution.
       </action>

Reply via email to