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

Make Erf more precise in the tails by providing erfc

    XMLWordPrintableJSON

    Details

    • Type: Improvement
    • Status: Closed
    • Priority: Minor
    • Resolution: Fixed
    • Affects Version/s: 1.1, 1.2, 2.0, 2.1
    • Fix Version/s: 3.0
    • Labels:
      None

      Description

      First I want to thank Phil Steitz for making Erf stable in the tails through adjusting the choices in calculating the regularized gamma functions, see Math-282. However, the precision of Erf in the tails is limitted to fixed point precision because of the closeness to +/-1.0, although the Gamma class could provide much more accuracy. Thus I propose to add the methods erfc(double) and erf(double, double) to the class Erf:

      /**
       * Returns the complementary error function erfc(x).
       * @param x the value
       * @return the complementary error function erfc(x)
       * @throws MathException if the algorithm fails to converge
       */
      public static double erfc(double x) throws MathException {
      double ret = Gamma.regularizedGammaQ(0.5, x * x, 1.0e-15, 10000);
      	if (x < 0) {
      		ret = -ret;
      	}
      	return ret;
      }
      
      /**
       * Returns the difference of the error function values of x1 and x2.
       * @param x1 the first bound
       * @param x2 the second bound
       * @return erf(x2) - erf(x1)
       * @throws MathException
       */
      public static double erf(double x1, double x2) throws MathException {
      	if(x1>x2)
      		return erf(x2, x1);
      	if(x1==x2)
      		return 0.0;
          	
      	double f1 = erf(x1);
      	double f2 = erf(x2);
      	
      	if(f2 > 0.5)
      		if(f1 > 0.5)
      			return erfc(x1) - erfc(x2);
      		else
      			return (0.5-erfc(x2)) + (0.5-f1);
      	else
      		if(f1 < -0.5)
      			if(f2 < -0.5)
      				return erfc(-x2) - erfc(-x1);
      			else
      				return (0.5-erfc(-x1)) + (0.5+f2);
      		else
      			return f2 - f1;
      }
      

      Further this can be used to improve the NormalDistributionImpl through

      @Override
      public double cumulativeProbability(double x0, double x1) throws MathException {
      	return 0.5 * Erf.erf(
      			(x0 - getMean()) / (getStandardDeviation() * sqrt2),
      			(x1 - getMean()) / (getStandardDeviation() * sqrt2) );
      }
      

        Attachments

        1. Math-364_additional_test.patch
          2 kB
          Christian Winter
        2. Math-364_patch.patch
          5 kB
          Christian Winter

          Issue Links

            Activity

              People

              • Assignee:
                Unassigned
                Reporter:
                cwinter Christian Winter
              • Votes:
                0 Vote for this issue
                Watchers:
                0 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: