You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ah...@apache.org on 2021/07/04 07:56:04 UTC

[commons-rng] 03/03: Update to match ZigguratExponentialSampler

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

commit a1a95bf66335df6679c92d4753eefd928afd809b
Author: aherbert <ah...@apache.org>
AuthorDate: Sun Jul 4 08:54:04 2021 +0100

    Update to match ZigguratExponentialSampler
    
    - Remove unnecessary nested statements
    - Move fill table code inside the static block
    - Update the branch frequencies
    - Rename gauss to pdf
    - Primitive cast before the mask is applied to obtain the index
---
 .../ZigguratNormalizedGaussianSampler.java         | 73 +++++++++++-----------
 1 file changed, 37 insertions(+), 36 deletions(-)

diff --git a/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/ZigguratNormalizedGaussianSampler.java b/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/ZigguratNormalizedGaussianSampler.java
index a8b3e5d..7b62be8 100644
--- a/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/ZigguratNormalizedGaussianSampler.java
+++ b/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/ZigguratNormalizedGaussianSampler.java
@@ -43,52 +43,54 @@ public class ZigguratNormalizedGaussianSampler
     private static final double R = 3.442619855899;
     /** Inverse of R. */
     private static final double ONE_OVER_R = 1 / R;
-    /** Rectangle area. */
-    private static final double V = 9.91256303526217e-3;
-    /** 2^63. */
-    private static final double MAX = Math.pow(2, 63);
-    /** 2^-63. */
-    private static final double ONE_OVER_MAX = 1d / MAX;
-    /** Number of entries. */
-    private static final int LEN = 128;
-    /** Index of last entry. */
-    private static final int LAST = LEN - 1;
+    /** Index of last entry in the tables (which have a size that is a power of 2). */
+    private static final int LAST = 127;
     /** Auxiliary table. */
-    private static final long[] K = new long[LEN];
+    private static final long[] K;
     /** Auxiliary table. */
-    private static final double[] W = new double[LEN];
+    private static final double[] W;
     /** Auxiliary table. */
-    private static final double[] F = new double[LEN];
+    private static final double[] F;
+
     /** Underlying source of randomness. */
     private final UniformRandomProvider rng;
 
     static {
         // Filling the tables.
+        // Rectangle area.
+        final double v = 9.91256303526217e-3;
+        // Direction support uses the sign bit so the maximum magnitude from the long is 2^63
+        final double max = Math.pow(2, 63);
+        final double oneOverMax = 1d / max;
+
+        K = new long[LAST + 1];
+        W = new double[LAST + 1];
+        F = new double[LAST + 1];
 
         double d = R;
         double t = d;
-        double fd = gauss(d);
-        final double q = V / fd;
+        double fd = pdf(d);
+        final double q = v / fd;
 
-        K[0] = (long) ((d / q) * MAX);
+        K[0] = (long) ((d / q) * max);
         K[1] = 0;
 
-        W[0] = q * ONE_OVER_MAX;
-        W[LAST] = d * ONE_OVER_MAX;
+        W[0] = q * oneOverMax;
+        W[LAST] = d * oneOverMax;
 
         F[0] = 1;
         F[LAST] = fd;
 
         for (int i = LAST - 1; i >= 1; i--) {
-            d = Math.sqrt(-2 * Math.log(V / d + fd));
-            fd = gauss(d);
+            d = Math.sqrt(-2 * Math.log(v / d + fd));
+            fd = pdf(d);
 
-            K[i + 1] = (long) ((d / t) * MAX);
+            K[i + 1] = (long) ((d / t) * max);
             t = d;
 
             F[i] = fd;
 
-            W[i] = d * ONE_OVER_MAX;
+            W[i] = d * oneOverMax;
         }
     }
 
@@ -103,12 +105,11 @@ public class ZigguratNormalizedGaussianSampler
     @Override
     public double sample() {
         final long j = rng.nextLong();
-        final int i = (int) (j & LAST);
+        final int i = ((int) j) & LAST;
         if (Math.abs(j) < K[i]) {
             return j * W[i];
-        } else {
-            return fix(j, i);
         }
+        return fix(j, i);
     }
 
     /** {@inheritDoc} */
@@ -140,24 +141,24 @@ public class ZigguratNormalizedGaussianSampler
 
             final double out = R + x;
             return hz > 0 ? out : -out;
-        } else {
-            // Wedge of other strips.
-            // This branch is called about 0.027323 times per sample.
-            if (F[iz] + rng.nextDouble() * (F[iz - 1] - F[iz]) < gauss(x)) {
-                return x;
-            } else {
-                // Try again.
-                // This branch is called about 0.012362 times per sample.
-                return sample();
-            }
         }
+        // Wedge of other strips.
+        // This branch is called about 0.027323 times per sample.
+        if (F[iz] + rng.nextDouble() * (F[iz - 1] - F[iz]) < pdf(x)) {
+            return x;
+        }
+        // Try again.
+        // This branch is called about 0.012362 times per sample.
+        return sample();
     }
 
     /**
+     * Compute the Gaussian probability density function {@code f(x) = e^-0.5x^2}.
+     *
      * @param x Argument.
      * @return \( e^{-\frac{x^2}{2}} \)
      */
-    private static double gauss(double x) {
+    private static double pdf(double x) {
         return Math.exp(-0.5 * x * x);
     }