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;
- /** π<sup>2</sup>/6. */
- private static final double PI_SQUARED_OVER_SIX = Math.PI * Math.PI / 6;
+ /** π<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;
/** √(2 π). */
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;
- /** π<sup>2</sup>/3. */
- private static final double PI_SQUARED_OVER_THREE = Math.PI * Math.PI / 3;
+ /** π<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);