Uploaded image for project: 'Commons Math'
  1. Commons Math
  2. MATH-456

Erf.erf - handle infinities and large values

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Minor
    • Resolution: Fixed
    • 2.2
    • 2.2
    • None
    • None

    Description

      Erf.erf(double) crashes when presented with infinities or large values, as follows:

      org.apache.commons.math.ConvergenceException: Continued fraction diverged to NaN for value ∞
      	at org.apache.commons.math.util.ContinuedFraction.evaluate(ContinuedFraction.java:186)
      	at org.apache.commons.math.special.Gamma.regularizedGammaQ(Gamma.java:266)
      	at org.apache.commons.math.special.Gamma.regularizedGammaP(Gamma.java:173)
      	at org.apache.commons.math.special.Erf.erf(Erf.java:56)
      	at TestInfErf.main(TestInfErf.java:9)
      

      The following code demonstrates this crash:

      import org.apache.commons.math.MathException;
      import org.apache.commons.math.special.Erf;
      
      public class TestInfErf {
          public static void main(String[] args) {
              try {
                  System.out.println("erf(Inf) = " + Erf.erf(Double.POSITIVE_INFINITY));
                  System.out.println("erf(-Inf) = " + Erf.erf(Double.NEGATIVE_INFINITY));
                  System.out.println("erf(Huge) = " + Erf.erf(1e300));
              } catch (MathException e) { 
                  e.printStackTrace(); 
              }
          }
      }
      

      At double precision, erf(x) = 1.0 for x > 6.0 and erf(x) = -1.0 for x < -6.0. Therefore Erf.java could be patched as follows:

      Index: src/main/java/org/apache/commons/math/special/Erf.java
      ===================================================================
      --- src/main/java/org/apache/commons/math/special/Erf.java	(revision 1043888)
      +++ src/main/java/org/apache/commons/math/special/Erf.java	(working copy)
      @@ -48,6 +48,12 @@
            * @throws MathException if the algorithm fails to converge.
            */
           public static double erf(double x) throws MathException {
      +        // at double precision, erf(x) = (+/-)1.0 for |x| > 6.0
      +        if (x > 6.0) {
      +            return 1.0;
      +        } else if (x <-6.0) {
      +            return -1.0;
      +        }
               double ret = Gamma.regularizedGammaP(0.5, x * x, 1.0e-15, 10000);
               if (x < 0) {
                   ret = -ret;
      

      Attachments

        Issue Links

          Activity

            People

              Unassigned Unassigned
              josh.milthorpe Josh Milthorpe
              Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: