qgamma precision (PR#2214)

terra@diku.dk terra@diku.dk
Fri, 25 Oct 2002 16:50:18 +0200 (MET DST)


Full_Name: Morten Welinder
Version: 1.5.1
OS: Solaris
Submission from: (NULL) (65.213.85.136)


I was having problems with qgamma's precision in the sense that
pgamma(qpgamma(x))
was not as close to the identity function as I would like.  I was seeing
relative
errors with random input of about 1e-8.  This fits nicely with the code'd EPS2
value of 5e-7.

To solve this I added a newton step at the end.  This seems far cheaper than
the
current iterations.  Here's the code I added (to replace the final return):


    /* Special Gnumeric patch to improve precision.  */
    {
	gnum_float x0 = 0.5*scale*ch;
	gnum_float e0 = pgamma (x0, alpha, scale, lower_tail, log_p) - p;

	if (e0 != 0 && lower_tail && !log_p) {
	    gnum_float d0 = dgamma (x0, alpha, scale, log_p);
	    if (d0) {
		gnum_float x1 = x0 - e0 / d0;
		gnum_float e1 = pgamma (x1, alpha, scale, lower_tail, log_p) - p;
		if (gnumabs (e1) < gnumabs (e0))
		    x0 = x1;
	    }
	}

	return x0;
    }

(Just read "gnum_float" as "double" and "gnumabs" as "fabs".)

The test for lower_tail is because (a) that is where I use it, and (b) the d0
calculation is probably wrong otherwise.

With this change, the relative precision improves to something like 1e-15.


-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
r-devel mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html
Send "info", "help", or "[un]subscribe"
(in the "body", not the subject !)  To: r-devel-request@stat.math.ethz.ch
_._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._