You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by er...@apache.org on 2020/04/27 05:46:49 UTC

[commons-math] 02/02: MATH-1531: Avoid spurious exception.

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

erans pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-math.git

commit bbfe7e4ea526e39ba0a79f0258200bc0d898f0de
Author: Gilles Sadowski <gi...@gmail.com>
AuthorDate: Mon Apr 27 07:39:41 2020 +0200

    MATH-1531: Avoid spurious exception.
    
    In the provided use-case, computation resulted in a value slightly above 1,
    thus throwing an exception (invalid probability).
    Workaround replaces the value by 1 when it is up to one ULP away.
---
 src/changes/changes.xml                            |   6 +
 .../math4/distribution/EmpiricalDistribution.java  |  10 +-
 .../distribution/EmpiricalDistributionTest.java    | 129 +++++++++++++++++++++
 3 files changed, 143 insertions(+), 2 deletions(-)

diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index e6c2c8a..800f66c 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -54,6 +54,12 @@ If the output is not quite correct, check for invisible trailing spaces!
     </release>
 
     <release version="4.0" date="XXXX-XX-XX" description="">
+      <action dev="erans" type="fix" issue="MATH-1531">
+        "EmpiricalDistribution": Workaround to avoid spurious exception.
+      </action>
+      <action dev="erans" type="update" issue="MATH-1530" due-to="Yassine Damerdji">
+        "SplineInterpolator": Improved performance.
+      </action>
       <action dev="erans" type="add" issue="MATH-1529">
         "AkimaSplineInterpolator": Option to use alternative weights.
       </action>
diff --git a/src/main/java/org/apache/commons/math4/distribution/EmpiricalDistribution.java b/src/main/java/org/apache/commons/math4/distribution/EmpiricalDistribution.java
index b9434d1..34779db 100644
--- a/src/main/java/org/apache/commons/math4/distribution/EmpiricalDistribution.java
+++ b/src/main/java/org/apache/commons/math4/distribution/EmpiricalDistribution.java
@@ -31,6 +31,8 @@ import java.util.List;
 import org.apache.commons.statistics.distribution.NormalDistribution;
 import org.apache.commons.statistics.distribution.ContinuousDistribution;
 import org.apache.commons.statistics.distribution.ConstantContinuousDistribution;
+import org.apache.commons.numbers.core.Precision;
+import org.apache.commons.rng.UniformRandomProvider;
 import org.apache.commons.math4.exception.MathIllegalStateException;
 import org.apache.commons.math4.exception.MathInternalError;
 import org.apache.commons.math4.exception.NullArgumentException;
@@ -40,7 +42,6 @@ import org.apache.commons.math4.exception.NotStrictlyPositiveException;
 import org.apache.commons.math4.exception.util.LocalizedFormats;
 import org.apache.commons.math4.stat.descriptive.StatisticalSummary;
 import org.apache.commons.math4.stat.descriptive.SummaryStatistics;
-import org.apache.commons.rng.UniformRandomProvider;
 import org.apache.commons.math4.util.FastMath;
 import org.apache.commons.math4.util.MathUtils;
 
@@ -616,7 +617,12 @@ public class EmpiricalDistribution extends AbstractRealDistribution
         if (pCrit <= 0) {
             return lower;
         }
-        return kernel.inverseCumulativeProbability(kBminus + pCrit * kB / pB);
+
+        final double cP = kBminus + pCrit * kB / pB;
+
+        return Precision.equals(cP, 1d) ?
+            kernel.inverseCumulativeProbability(1d) :
+            kernel.inverseCumulativeProbability(cP);
     }
 
     /**
diff --git a/src/test/java/org/apache/commons/math4/distribution/EmpiricalDistributionTest.java b/src/test/java/org/apache/commons/math4/distribution/EmpiricalDistributionTest.java
index 5b0f492..a7b5825 100644
--- a/src/test/java/org/apache/commons/math4/distribution/EmpiricalDistributionTest.java
+++ b/src/test/java/org/apache/commons/math4/distribution/EmpiricalDistributionTest.java
@@ -142,6 +142,135 @@ public final class EmpiricalDistributionTest extends RealDistributionAbstractTes
 
     }
 
+
+    // MATH-1531
+    @Test
+    public void testMath1531() {
+        final EmpiricalDistribution inputDistribution = new EmpiricalDistribution(120);
+        inputDistribution.load(new double[] {
+                50.993456376721454,
+                49.455345691918055,
+                49.527276095295804,
+                50.017183448668845,
+                49.10508147470046,
+                49.813998274118696,
+                50.87195348756139,
+                50.419474110037,
+                50.63614906979689,
+                49.49694777179407,
+                50.71799078406067,
+                50.03192853759164,
+                49.915092423165994,
+                49.56895392597687,
+                51.034638001064934,
+                50.681227971275945,
+                50.43749845081759,
+                49.86513120270245,
+                50.21475262482965,
+                49.99202971042547,
+                50.02382189838519,
+                49.386888585302884,
+                49.45585010202781,
+                49.988009479855435,
+                49.8136712206123,
+                49.6715197127997,
+                50.1981278397565,
+                49.842297508010276,
+                49.62491227740015,
+                50.05101916097176,
+                48.834912763303926,
+                49.806787657848574,
+                49.478236106374695,
+                49.56648347371614,
+                49.95069238081982,
+                49.71845132077346,
+                50.6097468705947,
+                49.80724637775541,
+                49.90448813086025,
+                49.39641861662603,
+                50.434295712893714,
+                49.227176959566734,
+                49.541126466050905,
+                49.03416593170446,
+                49.11584328494423,
+                49.61387482435674,
+                49.92877857995328,
+                50.70638552955101,
+                50.60078208448842,
+                49.39326233277838,
+                49.21488424364095,
+                49.69503351015096,
+                50.13733214001718,
+                50.22084761458942,
+                51.09804435604931,
+                49.18559131120419,
+                49.52286371605357,
+                49.34804374996689,
+                49.6901827776375,
+                50.01316351359638,
+                48.7751460520373,
+                50.12961836291053,
+                49.9978419772511,
+                49.885658399408584,
+                49.673438879979834,
+                49.45565980965606,
+                50.429747484906564,
+                49.40129274804164,
+                50.13034614008073,
+                49.87685735146651,
+                50.12967905393557,
+                50.323560376181696,
+                49.83519233651367,
+                49.37333369733053,
+                49.70074301611427,
+                50.11626105774947,
+                50.28249500380083,
+                50.543354367136466,
+                50.05866241335002,
+                50.39516515672527,
+                49.4838561463057,
+                50.451757089234796,
+                50.31370674203726,
+                49.79063762614284,
+                50.19652349768548,
+                49.75881420748814,
+                49.98371855036422,
+                49.82171344472916,
+                48.810793204162415,
+                49.37040569084592,
+                50.050641186203976,
+                50.48360952263646,
+                50.86666450358076,
+                50.463268776129844,
+                50.137489751888666,
+                50.23823061444118,
+                49.881460479468004,
+                50.641174398764356,
+                49.09314136851421,
+                48.80877928574451,
+                50.46197084844826,
+                49.97691704141741,
+                49.99933997561926,
+                50.25692254481885,
+                49.52973451252715,
+                49.81229858420664,
+                48.996112655915994,
+                48.740531054814674,
+                50.026642633066416,
+                49.98696633604899,
+                49.61307159972952,
+                50.5115278979726,
+                50.75245152442404,
+                50.51807785445929,
+                49.60929671768147,
+                49.1079533564074,
+                49.65347196551866,
+                49.31684818724059,
+                50.4906368627049,
+                50.37483603684714});
+        inputDistribution.inverseCumulativeProbability(0.7166666666666669);
+    }
+
     /**
       * Generate 1000 random values and make sure they look OK.<br>
       * Note that there is a non-zero (but very small) probability that