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


The following commit(s) were added to refs/heads/master by this push:
     new 664cc15  Consolidate constants
664cc15 is described below

commit 664cc15a74588884f978f73db5a00d249c9a9a83
Author: Alex Herbert <[email protected]>
AuthorDate: Thu Aug 15 15:16:15 2024 +0100

    Consolidate constants
    
    Add a shared location for common constants.
    
    Add references to extended precision decimal values where applicable.
---
 .../commons/statistics/distribution/Constants.java | 42 +++++++++++++++++++++
 .../distribution/ExponentialDistribution.java      |  4 +-
 .../distribution/FoldedNormalDistribution.java     | 19 +++-------
 .../distribution/GumbelDistribution.java           |  9 +++--
 .../distribution/LogNormalDistribution.java        |  4 +-
 .../distribution/LogisticDistribution.java         |  4 +-
 .../distribution/NakagamiDistribution.java         |  4 +-
 .../distribution/NormalDistribution.java           |  5 +--
 .../distribution/PoissonDistribution.java          |  4 +-
 .../distribution/TruncatedNormalDistribution.java  |  6 +--
 .../statistics/distribution/ConstantsTest.java     | 43 ++++++++++++++++++++++
 .../distribution/ExtendedPrecisionTest.java        |  2 +-
 12 files changed, 107 insertions(+), 39 deletions(-)

diff --git 
a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/Constants.java
 
b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/Constants.java
new file mode 100644
index 0000000..39acf4c
--- /dev/null
+++ 
b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/Constants.java
@@ -0,0 +1,42 @@
+/*
+ * 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.statistics.distribution;
+
+/**
+ * Constants for distribution calculations.
+ *
+ * <p>Constants should evaluate to the closest IEEE {@code double}.
+ * Expressions may have been computed using an arbitrary precision math
+ * library or obtained from existing online resources.
+ * Some expressions will not be the closest {@code double} if evaluated
+ * using the JDK's Math functions using {@code double} precision.
+ */
+final class Constants {
+    /** sqrt(2). https://oeis.org/A002193. */
+    static final double ROOT_TWO        = 1.4142135623730951;
+    /** sqrt(2 / pi). https://oeis.org/A076668. */
+    static final double ROOT_TWO_DIV_PI = 0.7978845608028654;
+    /** sqrt(pi / 2). https://oeis.org/A069998. */
+    static final double ROOT_PI_DIV_TWO = 1.2533141373155003;
+    /** ln(2). https://oeis.org/A002162. */
+    static final double LN_TWO          = 0.6931471805599453;
+    /** 0.5 * ln(2 pi). https://oeis.org/A075700. */
+    static final double HALF_LOG_TWO_PI = 0.9189385332046728;
+
+    /** No instances. */
+    private Constants() {}
+}
diff --git 
a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/ExponentialDistribution.java
 
b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/ExponentialDistribution.java
index 27553e9..d105745 100644
--- 
a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/ExponentialDistribution.java
+++ 
b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/ExponentialDistribution.java
@@ -41,8 +41,6 @@ public final class ExponentialDistribution extends 
AbstractContinuousDistributio
     private static final double SUPPORT_LO = 0;
     /** Support upper bound. */
     private static final double SUPPORT_HI = Double.POSITIVE_INFINITY;
-    /** ln(2). */
-    private static final double LN_2 = 0.6931471805599453094172;
     /** The mean of this distribution. */
     private final double mean;
     /** The logarithm of the mean, stored to reduce computing time. */
@@ -184,7 +182,7 @@ public final class ExponentialDistribution extends 
AbstractContinuousDistributio
         // Overridden for the probability(double, double) method.
         // This is intentionally not a public method.
         // ln(2) / rate = mean * ln(2)
-        return mean * LN_2;
+        return mean * Constants.LN_TWO;
     }
 
     /** {@inheritDoc} */
diff --git 
a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/FoldedNormalDistribution.java
 
b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/FoldedNormalDistribution.java
index 4470f3a..6ea8735 100644
--- 
a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/FoldedNormalDistribution.java
+++ 
b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/FoldedNormalDistribution.java
@@ -49,9 +49,6 @@ import 
org.apache.commons.rng.sampling.distribution.ZigguratSampler;
  * @since 1.1
  */
 public abstract class FoldedNormalDistribution extends 
AbstractContinuousDistribution {
-    /** Normalisation constant sqrt(2 / pi). */
-    private static final double ROOT_TWO_DIV_PI = 0.7978845608028654;
-
     /** The scale. */
     final double sigma;
     /**
@@ -91,7 +88,7 @@ public abstract class FoldedNormalDistribution extends 
AbstractContinuousDistrib
             this.mu = mu;
 
             final double a = mu / sigmaSqrt2;
-            mean = sigma * ROOT_TWO_DIV_PI * Math.exp(-a * a) + mu * 
Erf.value(a);
+            mean = sigma * Constants.ROOT_TWO_DIV_PI * Math.exp(-a * a) + mu * 
Erf.value(a);
             this.variance = mu * mu + sigma * sigma - mean * mean;
         }
 
@@ -170,12 +167,8 @@ public abstract class FoldedNormalDistribution extends 
AbstractContinuousDistrib
      * functions and allows computation of the log density and inverse CDF/SF.
      */
     private static class HalfNormalDistribution extends 
FoldedNormalDistribution {
-        /** Variance constant (1 - 2/pi). */
-        private static final double VAR = 0.363380227632418617567;
-        /** ln(2). */
-        private static final double LN_2 = 0.6931471805599453094172;
-        /** 0.5 * ln(2 * pi). Computed to 25-digits precision. */
-        private static final double HALF_LOG_TWO_PI = 
0.9189385332046727417803297;
+        /** Variance constant (1 - 2/pi). Computed using Matlab's VPA to 30 
digits. */
+        private static final double VAR = 0.36338022763241865692446494650994;
         /** The value of {@code log(sigma) + 0.5 * log(2*PI)} stored for 
faster computation. */
         private final double logSigmaPlusHalfLog2Pi;
 
@@ -184,7 +177,7 @@ public abstract class FoldedNormalDistribution extends 
AbstractContinuousDistrib
          */
         HalfNormalDistribution(double sigma) {
             super(sigma);
-            logSigmaPlusHalfLog2Pi = Math.log(sigma) + HALF_LOG_TWO_PI;
+            logSigmaPlusHalfLog2Pi = Math.log(sigma) + 
Constants.HALF_LOG_TWO_PI;
         }
 
         @Override
@@ -220,7 +213,7 @@ public abstract class FoldedNormalDistribution extends 
AbstractContinuousDistrib
                 return Double.NEGATIVE_INFINITY;
             }
             final double z = x / sigma;
-            return LN_2 - 0.5 * z * z - logSigmaPlusHalfLog2Pi;
+            return Constants.LN_TWO - 0.5 * z * z - logSigmaPlusHalfLog2Pi;
         }
 
         @Override
@@ -255,7 +248,7 @@ public abstract class FoldedNormalDistribution extends 
AbstractContinuousDistrib
 
         @Override
         public double getMean() {
-            return sigma * ROOT_TWO_DIV_PI;
+            return sigma * Constants.ROOT_TWO_DIV_PI;
         }
 
         @Override
diff --git 
a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/GumbelDistribution.java
 
b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/GumbelDistribution.java
index 571bd6b..2a0200b 100644
--- 
a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/GumbelDistribution.java
+++ 
b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/GumbelDistribution.java
@@ -37,14 +37,15 @@ public final class GumbelDistribution extends 
AbstractContinuousDistribution {
     private static final double SUPPORT_LO = Double.NEGATIVE_INFINITY;
     /** Support upper bound. */
     private static final double SUPPORT_HI = Double.POSITIVE_INFINITY;
-    /** &pi;<sup>2</sup>/6. */
-    private static final double PI_SQUARED_OVER_SIX = Math.PI * Math.PI / 6;
+    /** &pi;<sup>2</sup>/6. https://oeis.org/A013661. */
+    private static final double PI_SQUARED_OVER_SIX = 
1.644934066848226436472415166646;
     /**
      * <a href="https://en.wikipedia.org/wiki/Euler%27s_constant";>
      * Approximation of Euler's constant</a>.
+     * https://oeis.org/A001620.
      */
-    private static final double EULER = 0.57721566490153286060;
-    /** ln(ln(2)). */
+    private static final double EULER = 0.5772156649015328606065;
+    /** ln(ln(2)). https://oeis.org/A074785. */
     private static final double LN_LN_2 = -0.3665129205816643270124;
     /** Location parameter. */
     private final double mu;
diff --git 
a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/LogNormalDistribution.java
 
b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/LogNormalDistribution.java
index f8e55c2..4444725 100644
--- 
a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/LogNormalDistribution.java
+++ 
b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/LogNormalDistribution.java
@@ -41,8 +41,6 @@ import 
org.apache.commons.rng.sampling.distribution.ZigguratSampler;
  * @see <a 
href="https://mathworld.wolfram.com/LogNormalDistribution.html";>Log-normal 
distribution (MathWorld)</a>
  */
 public final class LogNormalDistribution extends 
AbstractContinuousDistribution {
-    /** 0.5 * ln(2 * pi). Computed to 25-digits precision. */
-    private static final double HALF_LOG_TWO_PI = 0.9189385332046727417803297;
     /** &radic;(2 &pi;). */
     private static final double SQRT2PI = Math.sqrt(2 * Math.PI);
     /** The mu parameter of this distribution. */
@@ -64,7 +62,7 @@ public final class LogNormalDistribution extends 
AbstractContinuousDistribution
                                   double sigma) {
         this.mu = mu;
         this.sigma = sigma;
-        logSigmaPlusHalfLog2Pi = Math.log(sigma) + HALF_LOG_TWO_PI;
+        logSigmaPlusHalfLog2Pi = Math.log(sigma) + Constants.HALF_LOG_TWO_PI;
         sigmaSqrt2 = ExtendedPrecision.sqrt2xx(sigma);
         sigmaSqrt2Pi = sigma * SQRT2PI;
     }
diff --git 
a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/LogisticDistribution.java
 
b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/LogisticDistribution.java
index a372fa1..e7e9677 100644
--- 
a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/LogisticDistribution.java
+++ 
b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/LogisticDistribution.java
@@ -35,8 +35,8 @@ public final class LogisticDistribution extends 
AbstractContinuousDistribution {
     private static final double SUPPORT_LO = Double.NEGATIVE_INFINITY;
     /** Support upper bound. */
     private static final double SUPPORT_HI = Double.POSITIVE_INFINITY;
-    /** &pi;<sup>2</sup>/3. */
-    private static final double PI_SQUARED_OVER_THREE = Math.PI * Math.PI / 3;
+    /** &pi;<sup>2</sup>/3. https://oeis.org/A195055. */
+    private static final double PI_SQUARED_OVER_THREE = 
3.289868133696452872944830;
     /** Location parameter. */
     private final double mu;
     /** Scale parameter. */
diff --git 
a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/NakagamiDistribution.java
 
b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/NakagamiDistribution.java
index 21faa09..ba15810 100644
--- 
a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/NakagamiDistribution.java
+++ 
b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/NakagamiDistribution.java
@@ -42,8 +42,6 @@ public final class NakagamiDistribution extends 
AbstractContinuousDistribution {
     private static final double SUPPORT_LO = 0;
     /** Support upper bound. */
     private static final double SUPPORT_HI = Double.POSITIVE_INFINITY;
-    /** Natural logarithm of 2. */
-    private static final double LN_2 = 0.6931471805599453094172321;
 
     /** The shape parameter. */
     private final double mu;
@@ -67,7 +65,7 @@ public final class NakagamiDistribution extends 
AbstractContinuousDistribution {
         this.mu = mu;
         this.omega = omega;
         densityPrefactor = 2.0 * Math.pow(mu, mu) / (Gamma.value(mu) * 
Math.pow(omega, mu));
-        logDensityPrefactor = LN_2 + Math.log(mu) * mu - LogGamma.value(mu) - 
Math.log(omega) * mu;
+        logDensityPrefactor = Constants.LN_TWO + Math.log(mu) * mu - 
LogGamma.value(mu) - Math.log(omega) * mu;
         final double v = GammaRatio.delta(mu, 0.5);
         mean = Math.sqrt(omega / mu) / v;
         variance = omega - (omega / mu) / v / v;
diff --git 
a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/NormalDistribution.java
 
b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/NormalDistribution.java
index b7cf7d0..a0baa3f 100644
--- 
a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/NormalDistribution.java
+++ 
b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/NormalDistribution.java
@@ -39,9 +39,6 @@ import 
org.apache.commons.rng.sampling.distribution.ZigguratSampler;
  * @see <a href="https://mathworld.wolfram.com/NormalDistribution.html";>Normal 
distribution (MathWorld)</a>
  */
 public final class NormalDistribution extends AbstractContinuousDistribution {
-    /** 0.5 * ln(2 * pi). Computed to 25-digits precision. */
-    private static final double HALF_LOG_TWO_PI = 0.9189385332046727417803297;
-
     /** Mean of this distribution. */
     private final double mean;
     /** Standard deviation of this distribution. */
@@ -73,7 +70,7 @@ public final class NormalDistribution extends 
AbstractContinuousDistribution {
                                double sd) {
         this.mean = mean;
         standardDeviation = sd;
-        logStandardDeviationPlusHalfLog2Pi = Math.log(sd) + HALF_LOG_TWO_PI;
+        logStandardDeviationPlusHalfLog2Pi = Math.log(sd) + 
Constants.HALF_LOG_TWO_PI;
         // Minimise rounding error by computing sqrt(2 * sd * sd) exactly.
         // Compute using extended precision with care to avoid over/underflow.
         sdSqrt2 = ExtendedPrecision.sqrt2xx(sd);
diff --git 
a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/PoissonDistribution.java
 
b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/PoissonDistribution.java
index 8c6d17c..93310b3 100644
--- 
a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/PoissonDistribution.java
+++ 
b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/PoissonDistribution.java
@@ -37,8 +37,6 @@ import 
org.apache.commons.rng.sampling.distribution.ZigguratSampler;
  * @see <a 
href="https://mathworld.wolfram.com/PoissonDistribution.html";>Poisson 
distribution (MathWorld)</a>
  */
 public final class PoissonDistribution extends AbstractDiscreteDistribution {
-    /** 0.5 * ln(2 * pi). Computed to 25-digits precision. */
-    private static final double HALF_LOG_TWO_PI = 0.9189385332046727417803297;
     /** Upper bound on the mean to use the PoissonSampler. */
     private static final double MAX_MEAN = 0.5 * Integer.MAX_VALUE;
     /** Mean of the distribution. */
@@ -82,7 +80,7 @@ public final class PoissonDistribution extends 
AbstractDiscreteDistribution {
         }
         return -SaddlePointExpansionUtils.getStirlingError(x) -
               SaddlePointExpansionUtils.getDeviancePart(x, mean) -
-              HALF_LOG_TWO_PI - 0.5 * Math.log(x);
+              Constants.HALF_LOG_TWO_PI - 0.5 * Math.log(x);
     }
 
     /** {@inheritDoc} */
diff --git 
a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/TruncatedNormalDistribution.java
 
b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/TruncatedNormalDistribution.java
index e6eb2a4..395e288 100644
--- 
a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/TruncatedNormalDistribution.java
+++ 
b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/TruncatedNormalDistribution.java
@@ -54,11 +54,11 @@ public final class TruncatedNormalDistribution extends 
AbstractContinuousDistrib
     private static final double MIN_P = 0.0;
 
     /** sqrt(2). */
-    private static final double ROOT2 = 1.414213562373095048801688724209698078;
+    private static final double ROOT2 = Constants.ROOT_TWO;
     /** Normalisation constant 2 / sqrt(2 pi) = sqrt(2 / pi). */
-    private static final double ROOT_2_PI = 
0.797884560802865405726436165423365309;
+    private static final double ROOT_2_PI = Constants.ROOT_TWO_DIV_PI;
     /** Normalisation constant sqrt(2 pi) / 2 = sqrt(pi / 2). */
-    private static final double ROOT_PI_2 = 
1.253314137315500251207882642405522626;
+    private static final double ROOT_PI_2 = Constants.ROOT_PI_DIV_TWO;
 
     /**
      * The threshold to switch to a rejection sampler. When the truncated
diff --git 
a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/ConstantsTest.java
 
b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/ConstantsTest.java
new file mode 100644
index 0000000..e0304a2
--- /dev/null
+++ 
b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/ConstantsTest.java
@@ -0,0 +1,43 @@
+/*
+ * 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.statistics.distribution;
+
+import java.util.stream.Stream;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+/**
+ * Test for {@link Constants}.
+ */
+class ConstantsTest {
+    @ParameterizedTest
+    @MethodSource
+    void testConstant(double expected, double x, int ulp) {
+        TestUtils.assertEquals(expected, x, DoubleTolerances.ulps(ulp));
+    }
+
+    static Stream<Arguments> testConstant() {
+        final Stream.Builder<Arguments> builder = Stream.builder();
+        builder.add(Arguments.of(Math.sqrt(2), Constants.ROOT_TWO, 0));
+        builder.add(Arguments.of(Math.sqrt(2 / Math.PI), 
Constants.ROOT_TWO_DIV_PI, 0));
+        builder.add(Arguments.of(Math.sqrt(Math.PI / 2), 
Constants.ROOT_PI_DIV_TWO, 1));
+        builder.add(Arguments.of(Math.log(2), Constants.LN_TWO, 0));
+        builder.add(Arguments.of(0.5 * Math.log(2 * Math.PI), 
Constants.HALF_LOG_TWO_PI, 1));
+        return builder.build();
+    }
+}
diff --git 
a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/ExtendedPrecisionTest.java
 
b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/ExtendedPrecisionTest.java
index 8f7a25b..da0fc3d 100644
--- 
a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/ExtendedPrecisionTest.java
+++ 
b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/ExtendedPrecisionTest.java
@@ -34,7 +34,7 @@ import org.junit.jupiter.params.provider.ValueSource;
 class ExtendedPrecisionTest {
     /** sqrt(2). */
     private static final double ROOT2 = Math.sqrt(2.0);
-    /** sqrt(2 pi) as a String. Computed to 64-digits. */
+    /** sqrt(2 pi) as a String. Computed to 64-digits. 
https://oeis.org/A019727. */
     private static final String SQRT_TWO_PI = 
"2.506628274631000502415765284811045253006986740609938316629923576";
     /** sqrt(2 pi) as a double. Note: This is 1 ULP different from Math.sqrt(2 
* Math.PI). */
     private static final double ROOT2PI = Double.parseDouble(SQRT_TWO_PI);

Reply via email to