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/20 13:01:51 UTC

[commons-statistics] branch master updated (9ce7044 -> 23d17c1)

This is an automated email from the ASF dual-hosted git repository.

aherbert pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/commons-statistics.git.


    from 9ce7044  Add ".asf.yaml".
     new 912bcf7  STATISTICS-31: New "survivalProbability" function for all continuous distributions.
     new 9194721  Merge branch 'benwtrent-STATISTICS-31-SurvivalProbabilityFunction'
     new 23d17c1  Remove unnecessarily nested statements

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../statistics/distribution/BetaDistribution.java  |  12 ++
 .../distribution/CauchyDistribution.java           |  17 ++-
 .../distribution/ChiSquaredDistribution.java       |   6 +
 .../distribution/ContinuousDistribution.java       |  17 +++
 .../distribution/ExponentialDistribution.java      |  12 +-
 .../statistics/distribution/FDistribution.java     |  17 +++
 .../statistics/distribution/GammaDistribution.java |  11 ++
 .../distribution/GeometricDistribution.java        |   9 +-
 .../distribution/GumbelDistribution.java           |   7 ++
 .../distribution/LaplaceDistribution.java          |  12 +-
 .../statistics/distribution/LevyDistribution.java  |  10 ++
 .../distribution/LogNormalDistribution.java        |  17 ++-
 .../distribution/LogisticDistribution.java         |   7 ++
 .../distribution/NakagamiDistribution.java         |  12 ++
 .../distribution/NormalDistribution.java           |  10 ++
 .../distribution/ParetoDistribution.java           |  12 +-
 .../statistics/distribution/TDistribution.java     |  26 ++--
 .../distribution/WeibullDistribution.java          |  12 +-
 .../distribution/BetaDistributionTest.java         | 106 +++++++++++++++-
 .../distribution/CauchyDistributionTest.java       |  24 +++-
 .../distribution/ChiSquaredDistributionTest.java   |  22 ++++
 .../ContinuousDistributionAbstractTest.java        | 138 +++++++++++++++++++++
 .../distribution/ExponentialDistributionTest.java  |  23 ++++
 .../statistics/distribution/FDistributionTest.java |  22 ++++
 .../distribution/GammaDistributionTest.java        |  22 ++++
 .../distribution/GumbelDistributionTest.java       |  22 ++++
 .../distribution/LaplaceDistributionTest.java      |  24 ++++
 .../distribution/LevyDistributionTest.java         |  22 ++++
 .../distribution/LogNormalDistributionTest.java    |  33 ++++-
 .../distribution/LogisticsDistributionTest.java    |  22 ++++
 .../distribution/NakagamiDistributionTest.java     |  22 ++++
 .../distribution/NormalDistributionTest.java       |  24 +++-
 .../distribution/ParetoDistributionTest.java       |  24 +++-
 .../statistics/distribution/TDistributionTest.java |  22 ++++
 .../distribution/WeibullDistributionTest.java      |  28 +++++
 35 files changed, 796 insertions(+), 30 deletions(-)

[commons-statistics] 01/03: STATISTICS-31: New "survivalProbability" function for all continuous distributions.

Posted by ah...@apache.org.
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

commit 912bcf7a19566b711e3c6807255fc2b5ac8587a6
Author: Benjamin Trent <43...@users.noreply.github.com>
AuthorDate: Wed Jul 14 11:54:24 2021 -0400

    STATISTICS-31: New "survivalProbability" function for all continuous distributions.
    
    This commit adds a new function for all continuous
    distributions `survivalProbability`.
    
    While a naive implementation would simply be
    `1-cumulativeProbability`, that would result
    in loss of precision.
    
    For many of the current cont. dist. a higher
    precision survival probability is calculated
    
    For others, it is simply `1-cumulativeProbability`
    
    Many tests were added to verify the following:
    - the precision of cumulativeProbability
    - the precision of survivalProbability
    - That survivalProbabiliy is near 1-cumulative
    - That survival and cumulative probabilities are
      complementary
    
    Through this development, certain distributions
    were found lacking precision for their
    cumulativeProbabilities and were improved.
    
    Those were:
    
    - CauchyDistribution
    - ExponentialDistribution
    - LogNormalDistribution
    - PretoDistribution
    - WeibullDistribution
    
    Addresses Jira: STATISTICS-31
---
 .../statistics/distribution/BetaDistribution.java  |  12 ++
 .../distribution/CauchyDistribution.java           |  17 ++-
 .../distribution/ChiSquaredDistribution.java       |   6 +
 .../distribution/ContinuousDistribution.java       |  17 +++
 .../distribution/ExponentialDistribution.java      |  12 +-
 .../statistics/distribution/FDistribution.java     |  17 +++
 .../statistics/distribution/GammaDistribution.java |  11 ++
 .../distribution/GumbelDistribution.java           |   7 ++
 .../distribution/LaplaceDistribution.java          |  10 ++
 .../statistics/distribution/LevyDistribution.java  |  10 ++
 .../distribution/LogNormalDistribution.java        |  17 ++-
 .../distribution/LogisticDistribution.java         |   7 ++
 .../distribution/NakagamiDistribution.java         |  12 ++
 .../distribution/NormalDistribution.java           |  10 ++
 .../distribution/ParetoDistribution.java           |  12 +-
 .../statistics/distribution/TDistribution.java     |   6 +
 .../distribution/WeibullDistribution.java          |  12 +-
 .../distribution/BetaDistributionTest.java         | 106 +++++++++++++++-
 .../distribution/CauchyDistributionTest.java       |  24 +++-
 .../distribution/ChiSquaredDistributionTest.java   |  22 ++++
 .../ContinuousDistributionAbstractTest.java        | 138 +++++++++++++++++++++
 .../distribution/ExponentialDistributionTest.java  |  23 ++++
 .../statistics/distribution/FDistributionTest.java |  22 ++++
 .../distribution/GammaDistributionTest.java        |  22 ++++
 .../distribution/GumbelDistributionTest.java       |  22 ++++
 .../distribution/LaplaceDistributionTest.java      |  24 ++++
 .../distribution/LevyDistributionTest.java         |  22 ++++
 .../distribution/LogNormalDistributionTest.java    |  33 ++++-
 .../distribution/LogisticsDistributionTest.java    |  22 ++++
 .../distribution/NakagamiDistributionTest.java     |  22 ++++
 .../distribution/NormalDistributionTest.java       |  24 +++-
 .../distribution/ParetoDistributionTest.java       |  24 +++-
 .../statistics/distribution/TDistributionTest.java |  22 ++++
 .../distribution/WeibullDistributionTest.java      |  28 +++++
 34 files changed, 784 insertions(+), 11 deletions(-)

diff --git a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/BetaDistribution.java b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/BetaDistribution.java
index 54e9cf3..0d7653f 100644
--- a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/BetaDistribution.java
+++ b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/BetaDistribution.java
@@ -107,6 +107,18 @@ public class BetaDistribution extends AbstractContinuousDistribution {
         }
     }
 
+    /** {@inheritDoc} */
+    @Override
+    public double survivalProbability(double x) {
+        if (x <= 0) {
+            return 1;
+        } else if (x >= 1) {
+            return 0;
+        } else {
+            return RegularizedBeta.value(1 - x, beta, alpha);
+        }
+    }
+
     /**
      * {@inheritDoc}
      *
diff --git a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/CauchyDistribution.java b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/CauchyDistribution.java
index 1ef4ae1..771ea90 100644
--- a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/CauchyDistribution.java
+++ b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/CauchyDistribution.java
@@ -44,7 +44,22 @@ public class CauchyDistribution extends AbstractContinuousDistribution {
     /** {@inheritDoc} */
     @Override
     public double cumulativeProbability(double x) {
-        return 0.5 + (Math.atan((x - median) / scale) / Math.PI);
+        return cdf((x - median) / scale);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public double survivalProbability(double x) {
+        return cdf(-(x - median) / scale);
+    }
+
+    /**
+     * Compute the CDF of the Cauchy distribution with location 0 and scale 1.
+     * @param x Point at which the CDF is evaluated
+     * @return CDF(x)
+     */
+    private static double cdf(double x) {
+        return 0.5 + (Math.atan(x) / Math.PI);
     }
 
     /**
diff --git a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/ChiSquaredDistribution.java b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/ChiSquaredDistribution.java
index e012281..c10adf5 100644
--- a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/ChiSquaredDistribution.java
+++ b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/ChiSquaredDistribution.java
@@ -61,6 +61,12 @@ public class ChiSquaredDistribution extends AbstractContinuousDistribution {
         return gamma.cumulativeProbability(x);
     }
 
+    /** {@inheritDoc} */
+    @Override
+    public double survivalProbability(double x) {
+        return gamma.survivalProbability(x);
+    }
+
     /**
      * {@inheritDoc}
      *
diff --git a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/ContinuousDistribution.java b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/ContinuousDistribution.java
index 19f7584..129dd14 100644
--- a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/ContinuousDistribution.java
+++ b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/ContinuousDistribution.java
@@ -95,6 +95,23 @@ public interface ContinuousDistribution {
     double cumulativeProbability(double x);
 
     /**
+     * For a random variable {@code X} whose values are distributed according
+     * to this distribution, this method returns {@code P(X > x)}.
+     * In other words, this method represents the complementary cumulative
+     * distribution function.
+     * <p>
+     * By default, this is defined as {@code 1 - cumulativeProbability(x)}, but
+     * the specific implementation may be more accurate.
+     *
+     * @param x Point at which the survival function is evaluated.
+     * @return the probability that a random variable with this
+     * distribution takes a value greater than {@code x}.
+     */
+    default double survivalProbability(double x) {
+        return 1.0 - cumulativeProbability(x);
+    }
+
+    /**
      * Computes the quantile function of this distribution. For a random
      * variable {@code X} distributed according to this distribution, the
      * returned value is
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 20e0d88..e076197 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
@@ -80,7 +80,17 @@ public class ExponentialDistribution extends AbstractContinuousDistribution {
             return 0;
         }
 
-        return 1 - Math.exp(-x / mean);
+        return -Math.expm1(-x / mean);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public double survivalProbability(double x)  {
+        if (x <= SUPPORT_LO) {
+            return 1;
+        }
+
+        return Math.exp(-x / mean);
     }
 
     /**
diff --git a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/FDistribution.java b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/FDistribution.java
index b96511f..0acccbb 100644
--- a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/FDistribution.java
+++ b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/FDistribution.java
@@ -118,6 +118,23 @@ public class FDistribution extends AbstractContinuousDistribution {
                                      0.5 * m);
     }
 
+    /** {@inheritDoc} */
+    @Override
+    public double survivalProbability(double x)  {
+        if (x <= SUPPORT_LO) {
+            return 1;
+        } else if (x >= SUPPORT_HI) {
+            return 0;
+        }
+
+        final double n = numeratorDegreesOfFreedom;
+        final double m = denominatorDegreesOfFreedom;
+
+        return RegularizedBeta.value(m / (m + n * x),
+                0.5 * m,
+                0.5 * n);
+    }
+
     /**
      * Access the numerator degrees of freedom.
      *
diff --git a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/GammaDistribution.java b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/GammaDistribution.java
index 5053955..eb6761c 100644
--- a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/GammaDistribution.java
+++ b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/GammaDistribution.java
@@ -255,6 +255,17 @@ public class GammaDistribution extends AbstractContinuousDistribution {
         return RegularizedGamma.P.value(shape, x / scale);
     }
 
+    /** {@inheritDoc} */
+    @Override
+    public double survivalProbability(double x) {
+        if (x <= SUPPORT_LO) {
+            return 1;
+        } else if (x >= SUPPORT_HI) {
+            return 0;
+        }
+        return RegularizedGamma.Q.value(shape, x / scale);
+    }
+
     /**
      * {@inheritDoc}
      *
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 6b28c06..812ad8e 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
@@ -92,6 +92,13 @@ public class GumbelDistribution extends AbstractContinuousDistribution {
 
     /** {@inheritDoc} */
     @Override
+    public double survivalProbability(double x) {
+        final double z = (x - mu) / beta;
+        return -Math.expm1(-Math.exp(-z));
+    }
+
+    /** {@inheritDoc} */
+    @Override
     public double inverseCumulativeProbability(double p) {
         if (p < 0 || p > 1) {
             throw new DistributionException(DistributionException.INVALID_PROBABILITY, p);
diff --git a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/LaplaceDistribution.java b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/LaplaceDistribution.java
index a4fab52..ef3c76c 100644
--- a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/LaplaceDistribution.java
+++ b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/LaplaceDistribution.java
@@ -80,6 +80,16 @@ public class LaplaceDistribution extends AbstractContinuousDistribution {
 
     /** {@inheritDoc} */
     @Override
+    public double survivalProbability(double x) {
+        if (x <= mu) {
+            return 1.0 - Math.exp((x - mu) / beta) / 2.0;
+        } else {
+            return Math.exp((mu - x) / beta) / 2.0;
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override
     public double inverseCumulativeProbability(double p) {
         if (p < 0 ||
             p > 1) {
diff --git a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/LevyDistribution.java b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/LevyDistribution.java
index 4f59f28..e38d01a 100644
--- a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/LevyDistribution.java
+++ b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/LevyDistribution.java
@@ -16,6 +16,7 @@
  */
 package org.apache.commons.statistics.distribution;
 
+import org.apache.commons.numbers.gamma.Erf;
 import org.apache.commons.numbers.gamma.Erfc;
 import org.apache.commons.numbers.gamma.InverseErfc;
 
@@ -102,6 +103,15 @@ public class LevyDistribution extends AbstractContinuousDistribution {
 
     /** {@inheritDoc} */
     @Override
+    public double survivalProbability(final double x) {
+        if (x < mu) {
+            return 1;
+        }
+        return Erf.value(Math.sqrt(halfC / (x - mu)));
+    }
+
+    /** {@inheritDoc} */
+    @Override
     public double inverseCumulativeProbability(final double p) {
         if (p < 0 ||
             p > 1) {
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 584bdd5..211170b 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
@@ -17,8 +17,8 @@
 
 package org.apache.commons.statistics.distribution;
 
-import org.apache.commons.numbers.gamma.Erf;
 import org.apache.commons.numbers.gamma.ErfDifference;
+import org.apache.commons.numbers.gamma.Erfc;
 import org.apache.commons.rng.UniformRandomProvider;
 import org.apache.commons.rng.sampling.distribution.LogNormalSampler;
 import org.apache.commons.rng.sampling.distribution.ZigguratNormalizedGaussianSampler;
@@ -151,7 +151,20 @@ public class LogNormalDistribution extends AbstractContinuousDistribution {
         if (Math.abs(dev) > 40 * shape) {
             return dev < 0 ? 0.0d : 1.0d;
         }
-        return 0.5 + 0.5 * Erf.value(dev / (shape * SQRT2));
+        return 0.5 * Erfc.value(-dev / (shape * SQRT2));
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public double survivalProbability(double x)  {
+        if (x <= 0) {
+            return 1;
+        }
+        final double dev = Math.log(x) - scale;
+        if (Math.abs(dev) > 40 * shape) {
+            return dev > 0 ? 0.0d : 1.0d;
+        }
+        return 0.5 * Erfc.value(dev / (shape * SQRT2));
     }
 
     /** {@inheritDoc} */
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 0480206..522ccda 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
@@ -92,6 +92,13 @@ public class LogisticDistribution extends AbstractContinuousDistribution {
 
     /** {@inheritDoc} */
     @Override
+    public double survivalProbability(double x) {
+        final double z = oneOverScale * (x - mu);
+        return 1 / (1 + Math.exp(z));
+    }
+
+    /** {@inheritDoc} */
+    @Override
     public double inverseCumulativeProbability(double p) {
         if (p < 0 ||
             p > 1) {
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 da925fb..05429d4 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
@@ -100,6 +100,18 @@ public class NakagamiDistribution extends AbstractContinuousDistribution {
 
     /** {@inheritDoc} */
     @Override
+    public double survivalProbability(double x) {
+        if (x <= SUPPORT_LO) {
+            return 1;
+        } else if (x >= SUPPORT_HI) {
+            return 0;
+        }
+
+        return RegularizedGamma.Q.value(mu, mu * x * x / omega);
+    }
+
+    /** {@inheritDoc} */
+    @Override
     public double getMean() {
         return Gamma.value(mu + 0.5) / Gamma.value(mu) * Math.sqrt(omega / mu);
     }
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 6817a6f..37213ec 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
@@ -96,6 +96,16 @@ public class NormalDistribution extends AbstractContinuousDistribution {
 
     /** {@inheritDoc} */
     @Override
+    public double survivalProbability(double x) {
+        final double dev = x - mean;
+        if (Math.abs(dev) > 40 * standardDeviation) {
+            return dev > 0 ? 0.0d : 1.0d;
+        }
+        return 0.5 * Erfc.value(dev / (standardDeviation * SQRT2));
+    }
+
+    /** {@inheritDoc} */
+    @Override
     public double inverseCumulativeProbability(final double p) {
         if (p < 0 ||
             p > 1) {
diff --git a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/ParetoDistribution.java b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/ParetoDistribution.java
index eb45bd5..51bff39 100644
--- a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/ParetoDistribution.java
+++ b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/ParetoDistribution.java
@@ -126,7 +126,17 @@ public class ParetoDistribution extends AbstractContinuousDistribution {
         if (x <= scale) {
             return 0;
         }
-        return 1 - Math.pow(scale / x, shape);
+        // Can be improved by improving log calculation
+        return -Math.expm1(shape * Math.log(scale / x));
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public double survivalProbability(double x)  {
+        if (x <= scale) {
+            return 1;
+        }
+        return Math.pow(scale / x, shape);
     }
 
     /**
diff --git a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/TDistribution.java b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/TDistribution.java
index 612a89c..f1f90a8 100644
--- a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/TDistribution.java
+++ b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/TDistribution.java
@@ -112,6 +112,12 @@ public class TDistribution extends AbstractContinuousDistribution {
         }
     }
 
+    /** {@inheritDoc} */
+    @Override
+    public double survivalProbability(double x) {
+        return cumulativeProbability(-x);
+    }
+
     /**
      * {@inheritDoc}
      *
diff --git a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/WeibullDistribution.java b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/WeibullDistribution.java
index d79c001..60505d9 100644
--- a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/WeibullDistribution.java
+++ b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/WeibullDistribution.java
@@ -126,7 +126,17 @@ public class WeibullDistribution extends AbstractContinuousDistribution {
             return 0;
         }
 
-        return 1 - Math.exp(-Math.pow(x / scale, shape));
+        return -Math.expm1(-Math.pow(x / scale, shape));
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public double survivalProbability(double x) {
+        if (x <= SUPPORT_LO) {
+            return 1;
+        }
+
+        return Math.exp(-Math.pow(x / scale, shape));
     }
 
     /**
diff --git a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/BetaDistributionTest.java b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/BetaDistributionTest.java
index 8e2ce43..ee0aec1 100644
--- a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/BetaDistributionTest.java
+++ b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/BetaDistributionTest.java
@@ -29,10 +29,13 @@ class BetaDistributionTest {
 
     static final double[] ALPHA_BETAS = {0.1, 1, 10, 100, 1000};
     static final double EPSILON = StatUtils.min(ALPHA_BETAS);
+    static final double[] CUMULATIVE_TEST_POINTS = new double[]{
+        -0.1, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1
+    };
 
     @Test
     void testCumulative() {
-        final double[] x = new double[]{-0.1, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1};
+        final double[] x = CUMULATIVE_TEST_POINTS;
         // all test data computed using R 2.5
         checkCumulative(0.1, 0.1,
                         x, new double[]{
@@ -149,6 +152,72 @@ class BetaDistributionTest {
                             0.710208, 0.873964, 0.966656, 0.997272, 1.000000, 1.000000});
     }
 
+    @Test
+    void testSurvival() {
+        checkSurvival(1, 1, new double[]{
+            0.0, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.0});
+        checkSurvival(4, 1, new double[]{
+            0.0000, 0.0000, 0.0001, 0.0016, 0.0081, 0.0256, 0.0625, 0.1296, 0.2401,
+            0.4096, 0.6561, 1.0000, 1.0000});
+        checkSurvival(2, 4, new double[]{
+            0.00000, 0.00000, 0.08146, 0.26272, 0.47178, 0.66304, 0.81250, 0.91296,
+            0.96922, 0.99328, 0.99954, 1.00000, 1.00000});
+    }
+
+    @Test
+    void testCumulativeAndSurvivalComplement() {
+        checkCumulativeSurvivalComplement(0.1, 0.1);
+        checkCumulativeSurvivalComplement(0.1, 0.5);
+        checkCumulativeSurvivalComplement(0.1, 1.0);
+        checkCumulativeSurvivalComplement(0.1, 2.0);
+        checkCumulativeSurvivalComplement(0.1, 4.0);
+        checkCumulativeSurvivalComplement(0.5, 0.1);
+        checkCumulativeSurvivalComplement(0.5, 0.5);
+        checkCumulativeSurvivalComplement(0.5, 1.0);
+        checkCumulativeSurvivalComplement(0.5, 2.0);
+        checkCumulativeSurvivalComplement(0.5, 4.0);
+        checkCumulativeSurvivalComplement(1.0, 0.1);
+        checkCumulativeSurvivalComplement(1.0, 0.5);
+        checkCumulativeSurvivalComplement(1, 1);
+        checkCumulativeSurvivalComplement(1, 2);
+        checkCumulativeSurvivalComplement(1, 4);
+        checkCumulativeSurvivalComplement(2.0, 0.1);
+        checkCumulativeSurvivalComplement(2, 1);
+        checkCumulativeSurvivalComplement(2.0, 0.5);
+        checkCumulativeSurvivalComplement(2, 2);
+        checkCumulativeSurvivalComplement(2, 4);
+        checkCumulativeSurvivalComplement(4.0, 0.1);
+        checkCumulativeSurvivalComplement(4.0, 0.5);
+        checkCumulativeSurvivalComplement(4, 1);
+        checkCumulativeSurvivalComplement(4, 2);
+        checkCumulativeSurvivalComplement(4, 4);
+    }
+
+    /** Precision tests for verifying that CDF calculates accurately in cases where 1-cdf(x) is inaccurately 1. */
+    @Test
+    void testCumulativePrecision() {
+        // Calculated using WolframAlpha
+        checkCumulativePrecision(5.0, 5.0, 0.0001, 1.2595800539968654e-18);
+        checkCumulativePrecision(4.0, 5.0, 0.00001, 6.999776002800025e-19);
+        checkCumulativePrecision(5.0, 4.0, 0.0001, 5.598600119996539e-19);
+        checkCumulativePrecision(6.0, 2.0, 0.001, 6.994000000000028e-18);
+        checkCumulativePrecision(2.0, 6.0, 1e-9, 2.0999999930000014e-17);
+    }
+
+    /**
+     * Precision tests for verifying that survivalFunction calculates accurately in cases
+     * where 1-sf(x) is inaccurately 1.
+     */
+    @Test
+    void testSurvivalPrecision() {
+        // Calculated using WolframAlpha
+        checkSurvivalPrecision(5.0, 5.0, 0.9999, 1.2595800539961496e-18);
+        checkSurvivalPrecision(4.0, 5.0, 0.9999, 5.598600119993397e-19);
+        checkSurvivalPrecision(5.0, 4.0, 0.99998, 1.1199283217964632e-17);
+        checkSurvivalPrecision(6.0, 2.0, 0.999999999, 2.0999998742158932e-17);
+        checkSurvivalPrecision(2.0, 6.0, 0.999, 6.994000000000077e-18);
+    }
+
     private void checkCumulative(double alpha, double beta, double[] x, double[] cumes) {
         final BetaDistribution d = new BetaDistribution(alpha, beta);
         for (int i = 0; i < x.length; i++) {
@@ -160,6 +229,41 @@ class BetaDistributionTest {
         }
     }
 
+    private void checkSurvival(double alpha, double beta, double[] cumes) {
+        final BetaDistribution d = new BetaDistribution(alpha, beta);
+        for (int i = 0; i < CUMULATIVE_TEST_POINTS.length; i++) {
+            Assertions.assertEquals(1 - cumes[i], d.survivalProbability(CUMULATIVE_TEST_POINTS[i]), 1e-8);
+        }
+    }
+
+    private void checkCumulativeSurvivalComplement(double alpha, double beta) {
+        final BetaDistribution d = new BetaDistribution(alpha, beta);
+        for (int i = 0; i < CUMULATIVE_TEST_POINTS.length; i++) {
+            double x = CUMULATIVE_TEST_POINTS[i];
+            Assertions.assertEquals(1, d.cumulativeProbability(x) + d.survivalProbability(x), 1e-8);
+        }
+    }
+
+    private void checkCumulativePrecision(double alpha, double beta, double value, double expected) {
+        final double tolerance = 1e-22;
+        BetaDistribution d = new BetaDistribution(alpha, beta);
+        TestUtils.assertEquals(
+                "cumulative probability not precise at " + value + " for a=" + alpha + " & b=" + beta,
+                d.cumulativeProbability(value),
+                expected,
+                tolerance);
+    }
+
+    private void checkSurvivalPrecision(double alpha, double beta, double value, double expected) {
+        final double tolerance = 1e-22;
+        BetaDistribution d = new BetaDistribution(alpha, beta);
+        TestUtils.assertEquals(
+                "survival function not precise at " + value + " for a=" + alpha + " & b=" + beta,
+                d.survivalProbability(value),
+                expected,
+                tolerance);
+    }
+
     @Test
     void testDensity() {
         final double[] x = new double[]{1e-6, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9};
diff --git a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/CauchyDistributionTest.java b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/CauchyDistributionTest.java
index 4d07667..61a283e 100644
--- a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/CauchyDistributionTest.java
+++ b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/CauchyDistributionTest.java
@@ -28,7 +28,7 @@ import org.junit.jupiter.api.Test;
  */
 class CauchyDistributionTest extends ContinuousDistributionAbstractTest {
 
-    private static final double DEFAULT_TOLERANCE = 1e-7;
+    private static final double DEFAULT_TOLERANCE = 1e-8;
 
     //---------------------- Override tolerance --------------------------------
 
@@ -67,6 +67,28 @@ class CauchyDistributionTest extends ContinuousDistributionAbstractTest {
                              1.49599158008e-06, 0.000149550440335, 0.000933076881878, 0.00370933207799, 0.0144742330437};
     }
 
+    @Override
+    public double[] makeCumulativePrecisionTestPoints() {
+        return new double[] {-1e16};
+    }
+
+    @Override
+    public double[] makeCumulativePrecisionTestValues() {
+        // These were created using WolframAlpha
+        return new double[] {5.551115123125783e-17};
+    }
+
+    @Override
+    public double[] makeSurvivalPrecisionTestPoints() {
+        return new double[] {1e16};
+    }
+
+    @Override
+    public double[] makeSurvivalPrecisionTestValues() {
+        // These were created using WolframAlpha
+        return makeCumulativePrecisionTestValues();
+    }
+
     //-------------------- Additional test cases -------------------------------
 
     @Test
diff --git a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/ChiSquaredDistributionTest.java b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/ChiSquaredDistributionTest.java
index 921129b..e8030a3 100644
--- a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/ChiSquaredDistributionTest.java
+++ b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/ChiSquaredDistributionTest.java
@@ -79,6 +79,28 @@ class ChiSquaredDistributionTest extends ContinuousDistributionAbstractTest {
                              0.000433630076361, 0.00412780610309, 0.00999340341045, 0.0193246438937, 0.0368460089216};
     }
 
+    @Override
+    public double[] makeCumulativePrecisionTestPoints() {
+        return new double[] {1e-7, 4e-7, 9e-8};
+    }
+
+    @Override
+    public double[] makeCumulativePrecisionTestValues() {
+        // These were created using WolframAlpha
+        return new double[] {1.6820882879388572e-19, 5.382681944688393e-18, 1.292572946953654e-19};
+    }
+
+    @Override
+    public double[] makeSurvivalPrecisionTestPoints() {
+        return new double[] {93, 97.3};
+    }
+
+    @Override
+    public double[] makeSurvivalPrecisionTestValues() {
+        // These were created using WolframAlpha
+        return new double[] {1.5731947657596637e-18, 1.9583114656146269e-19};
+    }
+
     //-------------------- Additional test cases -------------------------------
 
     @Test
diff --git a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/ContinuousDistributionAbstractTest.java b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/ContinuousDistributionAbstractTest.java
index b7044f8..260d7c7 100644
--- a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/ContinuousDistributionAbstractTest.java
+++ b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/ContinuousDistributionAbstractTest.java
@@ -46,6 +46,20 @@ import org.junit.jupiter.api.BeforeEach;
  * makeInverseCumulativeTestPoints() -- arguments used to test inverse cdf
  * makeInverseCumulativeTestValues() -- expected inverse cdf values
  * <p>
+ * If the continuous distribution provides higher precision implementations of cumulativeProbability
+ * and/or survivalProbability, the following methods should be implemented to provide testing.
+ * To use these tests, calculate the cumulativeProbability and survivalProbability such that their naive
+ * complement is exceptionally close to `1` and consequently could lose precision due to floating point
+ * arithmetic.
+ *
+ * NOTE: The default high-precision threshold is 1e-22.
+ * <pre>
+ * makeCumulativePrecisionTestPoints() -- high precision test inputs
+ * makeCumulativePrecisionTestValues() -- high precision expected results
+ * makeSurvivalPrecisionTestPoints() -- high precision test inputs
+ * makeSurvivalPrecisionTestValues() -- high precision expected results
+ * </pre>
+ * <p>
  * To implement additional test cases with different distribution instances and
  * test data, use the setXxx methods for the instance data in test cases and
  * call the verifyXxx methods to verify results.
@@ -69,12 +83,27 @@ abstract class ContinuousDistributionAbstractTest {
     /** Tolerance used in comparing expected and returned values */
     private double tolerance = 1e-4;
 
+    /** Tolerance used in high precision tests */
+    private final double highPrecisionTolerance = 1e-22;
+
     /** Arguments used to test cumulative probability density calculations */
     private double[] cumulativeTestPoints;
 
     /** Values used to test cumulative probability density calculations */
     private double[] cumulativeTestValues;
 
+    /** Arguments used to test cumulative probability precision, effectively any x where 1-cdf(x) would result in 1 */
+    private double[] cumulativePrecisionTestPoints;
+
+    /** Values used to test cumulative probability precision, usually exceptionally tiny values */
+    private double[] cumulativePrecisionTestValues;
+
+    /** Arguments used to test survival probability precision, effectively any x where 1-sf(x) would result in 1 */
+    private double[] survivalPrecisionTestPoints;
+
+    /** Values used to test survival probability precision, usually exceptionally tiny values */
+    private double[] survivalPrecisionTestValues;
+
     /** Arguments used to test inverse cumulative probability density calculations */
     private double[] inverseCumulativeTestPoints;
 
@@ -98,6 +127,34 @@ abstract class ContinuousDistributionAbstractTest {
     /** Creates the default cumulative probability test expected values */
     public abstract double[] makeCumulativeTestValues();
 
+    /** Creates the default cumulative probability precision test input values */
+    public double[] makeCumulativePrecisionTestPoints() {
+        return new double[0];
+    }
+
+    /**
+     * Creates the default cumulative probability precision test expected values.
+     * Note: The default threshold is 1e-22, any expected values with much higher precision may
+     *       not test the desired results without increasing precision threshold.
+     */
+    public double[] makeCumulativePrecisionTestValues() {
+        return new double[0];
+    }
+
+    /** Creates the default survival probability precision test input values */
+    public double[] makeSurvivalPrecisionTestPoints() {
+        return new double[0];
+    }
+
+    /**
+     * Creates the default survival probability precision test expected values.
+     * Note: The default threshold is 1e-22, any expected values with much higher precision may
+     *       not test the desired results without increasing precision threshold.
+     */
+    public double[] makeSurvivalPrecisionTestValues() {
+        return new double[0];
+    }
+
     /** Creates the default density test expected values */
     public abstract double[] makeDensityTestValues();
 
@@ -138,6 +195,10 @@ abstract class ContinuousDistributionAbstractTest {
         distribution = makeDistribution();
         cumulativeTestPoints = makeCumulativeTestPoints();
         cumulativeTestValues = makeCumulativeTestValues();
+        cumulativePrecisionTestPoints = makeCumulativePrecisionTestPoints();
+        cumulativePrecisionTestValues = makeCumulativePrecisionTestValues();
+        survivalPrecisionTestPoints = makeSurvivalPrecisionTestPoints();
+        survivalPrecisionTestValues = makeSurvivalPrecisionTestValues();
         inverseCumulativeTestPoints = makeInverseCumulativeTestPoints();
         inverseCumulativeTestValues = makeInverseCumulativeTestValues();
         densityTestValues = makeDensityTestValues();
@@ -191,6 +252,54 @@ abstract class ContinuousDistributionAbstractTest {
         }
     }
 
+    protected void verifySurvivalProbability() {
+        for (int i = 0; i < cumulativeTestPoints.length; i++) {
+            TestUtils.assertEquals("Incorrect survival probability value returned for " +
+                            cumulativeTestPoints[i], 1 - cumulativeTestValues[i],
+                    distribution.survivalProbability(cumulativeTestPoints[i]),
+                    getTolerance());
+        }
+    }
+
+    protected void verifySurvivalAndCumulativeProbabilityComplement() {
+        for (final double x : cumulativeTestPoints) {
+            TestUtils.assertEquals("survival + cumulative probability were not close to 1.0" +
+                    x, 1.0,
+                distribution.survivalProbability(x) + distribution.cumulativeProbability(x),
+                getTolerance());
+        }
+    }
+
+    /**
+     * Verifies that survival is simply not 1-cdf by testing calculations that would underflow that calculation and
+     * result in an inaccurate answer.
+     */
+    protected void verifySurvivalProbabilityPrecision() {
+        for (int i = 0; i < survivalPrecisionTestPoints.length; i++) {
+            final double x = survivalPrecisionTestPoints[i];
+            TestUtils.assertEquals(
+                    "survival probability is not precise for value " + x,
+                    survivalPrecisionTestValues[i],
+                    distribution.survivalProbability(x),
+                    getHighPrecisionTolerance());
+        }
+    }
+
+    /**
+     * Verifies that CDF is simply not 1-survival function by testing values that would result with inaccurate results
+     * if simply calculating 1-survival function.
+     */
+    protected void verifyCumulativeProbabilityPrecision() {
+        for (int i = 0; i < cumulativePrecisionTestPoints.length; i++) {
+            final double x = cumulativePrecisionTestPoints[i];
+            TestUtils.assertEquals(
+                    "cumulative probability is not precise for value " + x,
+                    cumulativePrecisionTestValues[i],
+                    distribution.cumulativeProbability(x),
+                    getHighPrecisionTolerance());
+        }
+    }
+
     /**
      * Verifies that inverse cumulative probability density calculations match expected values
      * using current test instance data
@@ -239,6 +348,26 @@ abstract class ContinuousDistributionAbstractTest {
         verifyCumulativeProbabilities();
     }
 
+    @Test
+    void testSurvivalProbability() {
+        verifySurvivalProbability();
+    }
+
+    @Test
+    void testSurvivalAndCumulativeProbabilitiesAreComplementary() {
+        verifySurvivalAndCumulativeProbabilityComplement();
+    }
+
+    @Test
+    void testCumulativeProbabilityPrecision() {
+        verifyCumulativeProbabilityPrecision();
+    }
+
+    @Test
+    void testSurvivalProbabilityPrecision() {
+        verifySurvivalProbabilityPrecision();
+    }
+
     /**
      * Verifies that inverse cumulative probability density calculations match expected values
      * using default test instance data
@@ -319,6 +448,8 @@ abstract class ContinuousDistributionAbstractTest {
         Assertions.assertEquals(Double.NEGATIVE_INFINITY, distribution.logDensity(above));
         Assertions.assertEquals(0d, distribution.cumulativeProbability(below));
         Assertions.assertEquals(1d, distribution.cumulativeProbability(above));
+        Assertions.assertEquals(1d, distribution.survivalProbability(below));
+        Assertions.assertEquals(0d, distribution.survivalProbability(above));
     }
 
     /**
@@ -497,6 +628,13 @@ abstract class ContinuousDistributionAbstractTest {
     }
 
     /**
+     * @return Returns the high precision tolerance
+     */
+    protected double getHighPrecisionTolerance() {
+        return highPrecisionTolerance;
+    }
+
+    /**
      * @param tolerance The tolerance to set.
      */
     protected void setTolerance(double tolerance) {
diff --git a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/ExponentialDistributionTest.java b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/ExponentialDistributionTest.java
index c62f638..2be38be 100644
--- a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/ExponentialDistributionTest.java
+++ b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/ExponentialDistributionTest.java
@@ -65,6 +65,29 @@ class ExponentialDistributionTest extends ContinuousDistributionAbstractTest {
                              0.00200000000002, 0.00499999999997, 0.00999999999994, 0.0199999999999};
     }
 
+    @Override
+    public double[] makeCumulativePrecisionTestPoints() {
+        return new double[] {1e-15, 4e-16, 9e-16};
+    }
+
+    @Override
+    public double[] makeCumulativePrecisionTestValues() {
+        // calculated via scipy, specifically expon.cdf(x/5).
+        // WolframAlpha provided either too accurate or inaccurate values
+        return new double[] {2.0000000000000002e-16, 7.999999999999999e-17, 1.8000000000000002e-16};
+    }
+
+    @Override
+    public double[] makeSurvivalPrecisionTestPoints() {
+        return new double[] {183, 197};
+    }
+
+    @Override
+    public double[] makeSurvivalPrecisionTestValues() {
+        // These were created using WolframAlpha. NOTE lambda parameter is 1/mean
+        return new double[] {1.2729811194234181e-16, 7.741006159285781e-18};
+    }
+
     //------------ Additional tests -------------------------------------------
 
     @Test
diff --git a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/FDistributionTest.java b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/FDistributionTest.java
index ae87559..8f692b2 100644
--- a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/FDistributionTest.java
+++ b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/FDistributionTest.java
@@ -63,6 +63,28 @@ class FDistributionTest extends ContinuousDistributionAbstractTest {
                              0.000133443915657, 0.00286681303403, 0.00969192007502, 0.0242883861471, 0.0605491314658};
     }
 
+    @Override
+    public double[] makeCumulativePrecisionTestPoints() {
+        return new double[] {1e-7, 4e-8, 9e-8};
+    }
+
+    @Override
+    public double[] makeCumulativePrecisionTestValues() {
+        // These were created using WolframAlpha
+        return new double[] {1.578691625481747e-17, 1.597523916857153e-18, 1.2131195257872846e-17};
+    }
+
+    @Override
+    public double[] makeSurvivalPrecisionTestPoints() {
+        return new double[] {1e6, 42e5, 63e5};
+    }
+
+    @Override
+    public double[] makeSurvivalPrecisionTestValues() {
+        // These were created using WolframAlpha
+        return new double[] {1.1339943867175144e-17, 1.5306104409634358e-19, 4.535143828961954e-20};
+    }
+
     //-------------------- Additional test cases -------------------------------
 
     @Test
diff --git a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/GammaDistributionTest.java b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/GammaDistributionTest.java
index 11e3b93..72abf34 100644
--- a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/GammaDistributionTest.java
+++ b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/GammaDistributionTest.java
@@ -73,6 +73,28 @@ class GammaDistributionTest extends ContinuousDistributionAbstractTest {
                              0.000394468852816, 0.00366559696761, 0.00874649473311, 0.0166712508128, 0.0311798227954};
     }
 
+    @Override
+    public double[] makeCumulativePrecisionTestPoints() {
+        return new double[] {1e-4, 9e-5};
+    }
+
+    @Override
+    public double[] makeCumulativePrecisionTestValues() {
+        // These were created using WolframAlpha
+        return new double[] {2.6040625021701086e-19, 1.7085322417782863e-19};
+    }
+
+    @Override
+    public double[] makeSurvivalPrecisionTestPoints() {
+        return new double[] {99, 103};
+    }
+
+    @Override
+    public double[] makeSurvivalPrecisionTestValues() {
+        // These were created using WolframAlpha
+        return new double[] {6.833817088979342e-18, 1.0390567840208212e-18};
+    }
+
     //-------------------- Additional test cases -------------------------------
 
     @Test
diff --git a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/GumbelDistributionTest.java b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/GumbelDistributionTest.java
index e90fde0..ea90adf 100644
--- a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/GumbelDistributionTest.java
+++ b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/GumbelDistributionTest.java
@@ -54,6 +54,28 @@ class GumbelDistributionTest extends ContinuousDistributionAbstractTest {
         };
     }
 
+    @Override
+    public double[] makeCumulativePrecisionTestPoints() {
+        return new double[] {-7.0, -7.1};
+    }
+
+    @Override
+    public double[] makeCumulativePrecisionTestValues() {
+        // These were created using WolframAlpha, specifically =CDF[ExtremeValueDistribution[0.5, 2], x]
+        return new double[] {3.414512624812977e-19, 3.859421750095851e-20};
+    }
+
+    @Override
+    public double[] makeSurvivalPrecisionTestPoints() {
+        return new double[] {75};
+    }
+
+    @Override
+    public double[] makeSurvivalPrecisionTestValues() {
+        // Not calculated via WolframAlpha, instead utilizing scipy gumbel_r, Wolframalpha could not get precise enough
+        return new double[] {6.64554417291507e-17};
+    }
+
     //-------------------- Additional test cases -------------------------------
 
     @Test
diff --git a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/LaplaceDistributionTest.java b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/LaplaceDistributionTest.java
index ce066b5..117f4a1 100644
--- a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/LaplaceDistributionTest.java
+++ b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/LaplaceDistributionTest.java
@@ -54,6 +54,30 @@ class LaplaceDistributionTest extends ContinuousDistributionAbstractTest {
         };
     }
 
+    @Override
+    public double[] makeCumulativePrecisionTestPoints() {
+        // Negative values only as anything > 0 falls into an imprecise calculation by being subtracted from 1
+        return new double[] {-42, -43};
+    }
+
+    @Override
+    public double[] makeCumulativePrecisionTestValues() {
+        // These were created using WolframAlpha
+        return new double[] {2.87476113214678e-19, 1.0575655187955402e-19};
+    }
+
+    @Override
+    public double[] makeSurvivalPrecisionTestPoints() {
+        // Positive values only as anything < 0 falls into an imprecise calculation by being subtracted from 1
+        return new double[] {42, 43};
+    }
+
+    @Override
+    public double[] makeSurvivalPrecisionTestValues() {
+        // These were created using WolframAlpha
+        return new double[] {2.87476113214678e-19, 1.0575655187955402e-19};
+    }
+
     //-------------------- Additional test cases -------------------------------
 
     @Test
diff --git a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/LevyDistributionTest.java b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/LevyDistributionTest.java
index 977b4dd..558a3d7 100644
--- a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/LevyDistributionTest.java
+++ b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/LevyDistributionTest.java
@@ -65,6 +65,28 @@ class LevyDistributionTest extends ContinuousDistributionAbstractTest {
             -2.650679030597d, -3.644945255983d};
     }
 
+    @Override
+    public double[] makeCumulativePrecisionTestPoints() {
+        return new double[] {1.205, 1.2049};
+    }
+
+    @Override
+    public double[] makeCumulativePrecisionTestValues() {
+        // These were created using WolframAlpha
+        return new double[] {3.7440973842063723e-19, 1.6388396909072308e-19};
+    }
+
+    @Override
+    public double[] makeSurvivalPrecisionTestPoints() {
+        return new double[] {1e39, 42e37};
+    }
+
+    @Override
+    public double[] makeSurvivalPrecisionTestValues() {
+        // These were created using WolframAlpha
+        return new double[] {1.5957691216057308e-20, 2.4623252122982907e-20};
+    }
+
     //-------------------- Additional test cases -------------------------------
 
     @Test
diff --git a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/LogNormalDistributionTest.java b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/LogNormalDistributionTest.java
index f5c5cb6..711602a 100644
--- a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/LogNormalDistributionTest.java
+++ b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/LogNormalDistributionTest.java
@@ -32,7 +32,7 @@ class LogNormalDistributionTest extends ContinuousDistributionAbstractTest {
 
     @BeforeEach
     void customSetUp() {
-        setTolerance(1e-7);
+        setTolerance(1e-10);
     }
 
     //-------------- Implementations for abstract methods ----------------------
@@ -102,6 +102,28 @@ class LogNormalDistributionTest extends ContinuousDistributionAbstractTest {
         //return Arrays.copyOfRange(points, 1, points.length - 4);
     }
 
+    @Override
+    public double[] makeCumulativePrecisionTestPoints() {
+        return new double[] {4e-5, 7e-5};
+    }
+
+    @Override
+    public double[] makeCumulativePrecisionTestValues() {
+        // These were created using WolframAlpha
+        return new double[] {1.2366527173500762e-18, 3.9216120913158885e-17};
+    }
+
+    @Override
+    public double[] makeSurvivalPrecisionTestPoints() {
+        return new double[] {999999, 2e6};
+    }
+
+    @Override
+    public double[] makeSurvivalPrecisionTestValues() {
+        // These were created using WolframAlpha
+        return new double[] {2.924727705260493e-17, 3.8830698713006447e-19};
+    }
+
     //-------------------- Additional test cases -------------------------------
 
     private void verifyQuantiles() {
@@ -169,6 +191,15 @@ class LogNormalDistributionTest extends ContinuousDistributionAbstractTest {
     }
 
     @Test
+    void testSurvivalProbabilityExtremes() {
+        // Use a small shape parameter so that we can exceed 40 * shape
+        setDistribution(new LogNormalDistribution(1, 0.0001));
+        setCumulativeTestPoints(new double[] {0.5, 10});
+        setCumulativeTestValues(new double[] {0, 1.0});
+        verifySurvivalProbability();
+    }
+
+    @Test
     void testParameterAccessors() {
         final LogNormalDistribution distribution = (LogNormalDistribution)getDistribution();
         Assertions.assertEquals(2.1, distribution.getScale());
diff --git a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/LogisticsDistributionTest.java b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/LogisticsDistributionTest.java
index e334b48..e0d9ef0 100644
--- a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/LogisticsDistributionTest.java
+++ b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/LogisticsDistributionTest.java
@@ -54,6 +54,28 @@ class LogisticsDistributionTest extends ContinuousDistributionAbstractTest {
         };
     }
 
+    @Override
+    public double[] makeCumulativePrecisionTestPoints() {
+        return new double[] {-197, -203};
+    }
+
+    @Override
+    public double[] makeCumulativePrecisionTestValues() {
+        // These were created using WolframAlpha
+        return new double[] {5.188951605054656e-18, 1.5628821893349888e-18};
+    }
+
+    @Override
+    public double[] makeSurvivalPrecisionTestPoints() {
+        return new double[] {197, 203};
+    }
+
+    @Override
+    public double[] makeSurvivalPrecisionTestValues() {
+        // These were created using WolframAlpha
+        return new double[] {1.1548224173015786e-17, 3.478258278776922e-18};
+    }
+
     //-------------------- Additional test cases -------------------------------
 
     @Test
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 d9d5934..a158c80 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
@@ -54,6 +54,28 @@ class NakagamiDistributionTest extends ContinuousDistributionAbstractTest {
         };
     }
 
+    @Override
+    public double[] makeCumulativePrecisionTestPoints() {
+        return new double[] {1e-16, 4e-17};
+    }
+
+    @Override
+    public double[] makeCumulativePrecisionTestValues() {
+        // These were created using WolframAlpha
+        return new double[] {7.978845608028653e-17, 3.1915382432114614e-17};
+    }
+
+    @Override
+    public double[] makeSurvivalPrecisionTestPoints() {
+        return new double[] {9, 8.7};
+    }
+
+    @Override
+    public double[] makeSurvivalPrecisionTestValues() {
+        // These were created using WolframAlpha
+        return new double[] {2.2571768119076845e-19, 3.318841739929575e-18};
+    }
+
     //-------------------- Additional test cases -------------------------------
 
     @Test
diff --git a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/NormalDistributionTest.java b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/NormalDistributionTest.java
index 87fd6a9..940d162 100644
--- a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/NormalDistributionTest.java
+++ b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/NormalDistributionTest.java
@@ -28,7 +28,7 @@ import org.junit.jupiter.api.Test;
  */
 class NormalDistributionTest extends ContinuousDistributionAbstractTest {
 
-    private static final double DEFAULT_TOLERANCE = 1e-7;
+    private static final double DEFAULT_TOLERANCE = 1e-10;
 
     //---------------------- Override tolerance --------------------------------
 
@@ -67,6 +67,28 @@ class NormalDistributionTest extends ContinuousDistributionAbstractTest {
                              0.00240506434076, 0.0190372444310, 0.0417464784322, 0.0736683145538, 0.125355951380};
     }
 
+    @Override
+    public double[] makeCumulativePrecisionTestPoints() {
+        return new double[] {-10, -10.3};
+    }
+
+    @Override
+    public double[] makeCumulativePrecisionTestValues() {
+        // These were created using WolframAlpha
+        return new double[] {2.741222634611109e-18, 4.1045652533919113e-19};
+    }
+
+    @Override
+    public double[] makeSurvivalPrecisionTestPoints() {
+        return new double[] {14.5, 13.9};
+    }
+
+    @Override
+    public double[] makeSurvivalPrecisionTestValues() {
+        // These were created using WolframAlpha
+        return new double[] {4.1045652533919576e-19, 1.749552800697539e-17};
+    }
+
     //-------------------- Additional test cases -------------------------------
 
     private void verifyQuantiles() {
diff --git a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/ParetoDistributionTest.java b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/ParetoDistributionTest.java
index 73b13d3..9d962df 100644
--- a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/ParetoDistributionTest.java
+++ b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/ParetoDistributionTest.java
@@ -31,7 +31,7 @@ class ParetoDistributionTest extends ContinuousDistributionAbstractTest {
 
     @BeforeEach
     void customSetUp() {
-        setTolerance(1e-7);
+        setTolerance(1e-9);
     }
 
     //-------------- Implementations for abstract methods ----------------------
@@ -90,6 +90,28 @@ class ParetoDistributionTest extends ContinuousDistributionAbstractTest {
         return points2;
     }
 
+    @Override
+    public double[] makeCumulativePrecisionTestPoints() {
+        return new double[] {2.100000000000001, 2.100000000000005};
+    }
+
+    @Override
+    public double[] makeCumulativePrecisionTestValues() {
+        // These were not created using WolframAlpha, the calculation for Math.log underflows in java
+        return new double[] {6.217248937900875e-16, 3.2640556923979585e-15};
+    }
+
+    @Override
+    public double[] makeSurvivalPrecisionTestPoints() {
+        return new double[] {42e11, 64e11};
+    }
+
+    @Override
+    public double[] makeSurvivalPrecisionTestValues() {
+        // These were created using WolframAlpha
+        return new double[] {6.005622169907148e-18, 3.330082930386111e-18};
+    }
+
     //-------------------- Additional test cases -------------------------------
 
     private void verifyQuantiles() {
diff --git a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/TDistributionTest.java b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/TDistributionTest.java
index 0ef996a..bcab69f 100644
--- a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/TDistributionTest.java
+++ b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/TDistributionTest.java
@@ -63,6 +63,28 @@ class TDistributionTest extends ContinuousDistributionAbstractTest {
                              0.000756494565517, 0.0109109752919, 0.0303377878006, 0.0637967988952, 0.128289492005};
     }
 
+    @Override
+    public double[] makeCumulativePrecisionTestPoints() {
+        return new double[] {-4200, -6400};
+    }
+
+    @Override
+    public double[] makeCumulativePrecisionTestValues() {
+        // These were created using WolframAlpha
+        return new double[] {7.261513520181652e-18, 8.838404680725267e-19};
+    }
+
+    @Override
+    public double[] makeSurvivalPrecisionTestPoints() {
+        return new double[] {4200, 6400};
+    }
+
+    @Override
+    public double[] makeSurvivalPrecisionTestValues() {
+        // These were created using WolframAlpha
+        return new double[] {7.261513520181652e-18, 8.838404680725267e-19};
+    }
+
     //-------------------- Additional test cases -------------------------------
 
     /**
diff --git a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/WeibullDistributionTest.java b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/WeibullDistributionTest.java
index 02df59a..c35056f 100644
--- a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/WeibullDistributionTest.java
+++ b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/WeibullDistributionTest.java
@@ -19,6 +19,7 @@ package org.apache.commons.statistics.distribution;
 
 import org.apache.commons.numbers.gamma.LogGamma;
 import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
 /**
@@ -28,6 +29,11 @@ import org.junit.jupiter.api.Test;
  */
 class WeibullDistributionTest extends ContinuousDistributionAbstractTest {
 
+    @BeforeEach
+    void customSetUp() {
+        setTolerance(1e-10);
+    }
+
     //-------------- Implementations for abstract methods ----------------------
 
     /** Creates the default continuous distribution instance to use in tests. */
@@ -57,6 +63,28 @@ class WeibullDistributionTest extends ContinuousDistributionAbstractTest {
                              0.353441418887, 0.000788590320203, 0.00737060094841, 0.0177576041516, 0.0343043442574, 0.065664589369};
     }
 
+    @Override
+    public double[] makeCumulativePrecisionTestPoints() {
+        return new double[] {1e-14, 1e-15};
+    }
+
+    @Override
+    public double[] makeCumulativePrecisionTestValues() {
+        // These were created using WolframAlpha
+        return new double[] {6.506341377907031e-18, 4.1052238780858223e-19};
+    }
+
+    @Override
+    public double[] makeSurvivalPrecisionTestPoints() {
+        return new double[] {45, 47.2};
+    }
+
+    @Override
+    public double[] makeSurvivalPrecisionTestValues() {
+        // These were created using WolframAlpha
+        return new double[] {6.6352694710268576e-18, 6.444810903667567e-19};
+    }
+
     //-------------------- Additional test cases -------------------------------
 
     @Test

[commons-statistics] 02/03: Merge branch 'benwtrent-STATISTICS-31-SurvivalProbabilityFunction'

Posted by ah...@apache.org.
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

commit 9194721c62a33f89370d6bd483d701cc497abb04
Merge: 9ce7044 912bcf7
Author: aherbert <ah...@apache.org>
AuthorDate: Tue Jul 20 13:57:45 2021 +0100

    Merge branch 'benwtrent-STATISTICS-31-SurvivalProbabilityFunction'

 .../statistics/distribution/BetaDistribution.java  |  12 ++
 .../distribution/CauchyDistribution.java           |  17 ++-
 .../distribution/ChiSquaredDistribution.java       |   6 +
 .../distribution/ContinuousDistribution.java       |  17 +++
 .../distribution/ExponentialDistribution.java      |  12 +-
 .../statistics/distribution/FDistribution.java     |  17 +++
 .../statistics/distribution/GammaDistribution.java |  11 ++
 .../distribution/GumbelDistribution.java           |   7 ++
 .../distribution/LaplaceDistribution.java          |  10 ++
 .../statistics/distribution/LevyDistribution.java  |  10 ++
 .../distribution/LogNormalDistribution.java        |  17 ++-
 .../distribution/LogisticDistribution.java         |   7 ++
 .../distribution/NakagamiDistribution.java         |  12 ++
 .../distribution/NormalDistribution.java           |  10 ++
 .../distribution/ParetoDistribution.java           |  12 +-
 .../statistics/distribution/TDistribution.java     |   6 +
 .../distribution/WeibullDistribution.java          |  12 +-
 .../distribution/BetaDistributionTest.java         | 106 +++++++++++++++-
 .../distribution/CauchyDistributionTest.java       |  24 +++-
 .../distribution/ChiSquaredDistributionTest.java   |  22 ++++
 .../ContinuousDistributionAbstractTest.java        | 138 +++++++++++++++++++++
 .../distribution/ExponentialDistributionTest.java  |  23 ++++
 .../statistics/distribution/FDistributionTest.java |  22 ++++
 .../distribution/GammaDistributionTest.java        |  22 ++++
 .../distribution/GumbelDistributionTest.java       |  22 ++++
 .../distribution/LaplaceDistributionTest.java      |  24 ++++
 .../distribution/LevyDistributionTest.java         |  22 ++++
 .../distribution/LogNormalDistributionTest.java    |  33 ++++-
 .../distribution/LogisticsDistributionTest.java    |  22 ++++
 .../distribution/NakagamiDistributionTest.java     |  22 ++++
 .../distribution/NormalDistributionTest.java       |  24 +++-
 .../distribution/ParetoDistributionTest.java       |  24 +++-
 .../statistics/distribution/TDistributionTest.java |  22 ++++
 .../distribution/WeibullDistributionTest.java      |  28 +++++
 34 files changed, 784 insertions(+), 11 deletions(-)

[commons-statistics] 03/03: Remove unnecessarily nested statements

Posted by ah...@apache.org.
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

commit 23d17c1a846c036f403e8ce21c890227dc29660a
Author: aherbert <ah...@apache.org>
AuthorDate: Tue Jul 20 14:01:47 2021 +0100

    Remove unnecessarily nested statements
---
 .../distribution/GeometricDistribution.java          |  9 +++------
 .../statistics/distribution/LaplaceDistribution.java |  6 ++----
 .../statistics/distribution/TDistribution.java       | 20 +++++++++-----------
 3 files changed, 14 insertions(+), 21 deletions(-)

diff --git a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/GeometricDistribution.java b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/GeometricDistribution.java
index ad87994..d9e88cc 100644
--- a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/GeometricDistribution.java
+++ b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/GeometricDistribution.java
@@ -57,9 +57,8 @@ public class GeometricDistribution extends AbstractDiscreteDistribution {
     public double probability(int x) {
         if (x < 0) {
             return 0.0;
-        } else {
-            return Math.exp(log1mProbabilityOfSuccess * x) * probabilityOfSuccess;
         }
+        return Math.exp(log1mProbabilityOfSuccess * x) * probabilityOfSuccess;
     }
 
     /** {@inheritDoc} */
@@ -67,9 +66,8 @@ public class GeometricDistribution extends AbstractDiscreteDistribution {
     public double logProbability(int x) {
         if (x < 0) {
             return Double.NEGATIVE_INFINITY;
-        } else {
-            return x * log1mProbabilityOfSuccess + logProbabilityOfSuccess;
         }
+        return x * log1mProbabilityOfSuccess + logProbabilityOfSuccess;
     }
 
     /** {@inheritDoc} */
@@ -77,9 +75,8 @@ public class GeometricDistribution extends AbstractDiscreteDistribution {
     public double cumulativeProbability(int x) {
         if (x < 0) {
             return 0.0;
-        } else {
-            return -Math.expm1(log1mProbabilityOfSuccess * (x + 1));
         }
+        return -Math.expm1(log1mProbabilityOfSuccess * (x + 1));
     }
 
     /**
diff --git a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/LaplaceDistribution.java b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/LaplaceDistribution.java
index ef3c76c..f6deeae 100644
--- a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/LaplaceDistribution.java
+++ b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/LaplaceDistribution.java
@@ -73,9 +73,8 @@ public class LaplaceDistribution extends AbstractContinuousDistribution {
     public double cumulativeProbability(double x) {
         if (x <= mu) {
             return Math.exp((x - mu) / beta) / 2.0;
-        } else {
-            return 1.0 - Math.exp((mu - x) / beta) / 2.0;
         }
+        return 1.0 - Math.exp((mu - x) / beta) / 2.0;
     }
 
     /** {@inheritDoc} */
@@ -83,9 +82,8 @@ public class LaplaceDistribution extends AbstractContinuousDistribution {
     public double survivalProbability(double x) {
         if (x <= mu) {
             return 1.0 - Math.exp((x - mu) / beta) / 2.0;
-        } else {
-            return Math.exp((mu - x) / beta) / 2.0;
         }
+        return Math.exp((mu - x) / beta) / 2.0;
     }
 
     /** {@inheritDoc} */
diff --git a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/TDistribution.java b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/TDistribution.java
index f1f90a8..6373f58 100644
--- a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/TDistribution.java
+++ b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/TDistribution.java
@@ -98,18 +98,16 @@ public class TDistribution extends AbstractContinuousDistribution {
     public double cumulativeProbability(double x) {
         if (x == 0) {
             return 0.5;
-        } else {
-            if (degreesOfFreedom > DOF_THRESHOLD_NORMAL) {
-                return 0.5 * (1 + Erf.value(x * ONE_OVER_SQRT_TWO));
-            } else {
-                final double a = 1 / (1 + x * x / degreesOfFreedom);
-                final double t = RegularizedBeta.value(a, dofOver2, 0.5);
-
-                return x < 0 ?
-                    0.5 * t :
-                    1 - 0.5 * t;
-            }
         }
+        if (degreesOfFreedom > DOF_THRESHOLD_NORMAL) {
+            return 0.5 * (1 + Erf.value(x * ONE_OVER_SQRT_TWO));
+        }
+        final double a = 1 / (1 + x * x / degreesOfFreedom);
+        final double t = RegularizedBeta.value(a, dofOver2, 0.5);
+
+        return x < 0 ?
+            0.5 * t :
+            1 - 0.5 * t;
     }
 
     /** {@inheritDoc} */