Add explicit logDensity computation
Expands the range where computation is possible to allow logDensity(x)
when density(x) == 0 for:
- Logistic
- Nakagami
Added tests to demonstrate this.
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 7bbdebd..f945274 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
@@ -85,6 +85,19 @@
/** {@inheritDoc} */
@Override
+ public double logDensity(double x) {
+ if (x <= SUPPORT_LO ||
+ x >= SUPPORT_HI) {
+ return Double.NEGATIVE_INFINITY;
+ }
+
+ final double z = oneOverScale * (x - mu);
+ final double v = Math.exp(-z);
+ return -Math.log(scale) - z - 2 * Math.log(1 + v);
+ }
+
+ /** {@inheritDoc} */
+ @Override
public double cumulativeProbability(double x) {
final double z = oneOverScale * (x - mu);
return 1 / (1 + Math.exp(-z));
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 05429d4..db838b2 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
@@ -17,6 +17,7 @@
package org.apache.commons.statistics.distribution;
import org.apache.commons.numbers.gamma.Gamma;
+import org.apache.commons.numbers.gamma.LogGamma;
import org.apache.commons.numbers.gamma.RegularizedGamma;
/**
@@ -29,6 +30,8 @@
private static final double SUPPORT_HI = Double.POSITIVE_INFINITY;
/** The minimum allowed for the shape parameter. */
private static final double MIN_SHAPE = 0.5;
+ /** Natural logarithm of 2. */
+ private static final double LN_2 = 0.6931471805599453094172321;
/** The shape parameter. */
private final double mu;
@@ -88,6 +91,18 @@
/** {@inheritDoc} */
@Override
+ public double logDensity(double x) {
+ if (x <= SUPPORT_LO ||
+ x >= SUPPORT_HI) {
+ return Double.NEGATIVE_INFINITY;
+ }
+
+ return LN_2 + Math.log(mu) * mu - LogGamma.value(mu) - Math.log(omega) * mu +
+ Math.log(x) * (2 * mu - 1) - (mu * x * x / omega);
+ }
+
+ /** {@inheritDoc} */
+ @Override
public double cumulativeProbability(double x) {
if (x <= SUPPORT_LO) {
return 0;
diff --git a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/LogisticDistributionTest.java b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/LogisticDistributionTest.java
index b367283..25b5c51 100644
--- a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/LogisticDistributionTest.java
+++ b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/LogisticDistributionTest.java
@@ -79,6 +79,16 @@
//-------------------- Additional test cases -------------------------------
@Test
+ void testExtremeLogDensity() {
+ final double scale = 2.5;
+ final LogisticDistribution dist = new LogisticDistribution(0, scale);
+ final double x = 1e160;
+ Assertions.assertEquals(0.0, dist.density(x));
+ final double expected = -Math.log(scale) - x / scale;
+ Assertions.assertEquals(expected, dist.logDensity(x), Math.abs(expected) * 1e-14);
+ }
+
+ @Test
void testInverseCumulativeProbabilityExtremes() {
setInverseCumulativeTestPoints(new double[] {0, 1});
setInverseCumulativeTestValues(new double[] {Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY});
diff --git a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/NakagamiDistributionTest.java b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/NakagamiDistributionTest.java
index 9382de0..4ff0bba 100644
--- a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/NakagamiDistributionTest.java
+++ b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/NakagamiDistributionTest.java
@@ -79,6 +79,15 @@
//-------------------- Additional test cases -------------------------------
@Test
+ void testExtremeLogDensity() {
+ // XXX: Verify with more test data from a reference distribution
+ final NakagamiDistribution dist = new NakagamiDistribution(0.5, 1);
+ final double x = 50;
+ Assertions.assertEquals(0.0, dist.density(x));
+ Assertions.assertEquals(-1250.22579, dist.logDensity(x), 1e-4);
+ }
+
+ @Test
void testParameterAccessors() {
final NakagamiDistribution dist = makeDistribution();
Assertions.assertEquals(0.5, dist.getShape());