idmiddle on Wed, 09 Apr 2008 09:21:35 +0200 |
[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]
patch for bug in lngamma |
Hello, I reported a bug in the lngamma function a while back: http://pari.math.u-bordeaux.fr/cgi-bin/bugreport.cgi?bug=655Recently I got motivated to fix it, and wrote a short description of the fix:
http://umich.edu/~idmiddle/lngamma/I've appended a patch against the latest development SVN. (file src/basemath/trans2.c)
best, Ivan Middleton --- trans2.c.orig 2008-04-09 01:17:31.000000000 -0400 +++ trans2.c 2008-04-09 01:23:12.000000000 -0400 @@ -1143,17 +1143,29 @@ if (dolog) { if (funeq) - { /* 2 Pi ceil( (2Re(s) - 3)/4 ) */ - GEN z = mulri(pi2, ceilr(shiftr(subrs(shiftr(sig,1), 3), -2))); - /* y --> y + log Pi - log sqrt(2Pi) - log sin(Pi s) - * = y - log( sin(Pi s) / (sqrt(2Pi)/2) ) */ - y = gsub(y, glog(gdiv(gsin(gmul(pi,s0),prec), shiftr(sqrtpi2,-1)), prec)); + { + /* (recall that s = 1 - s0) */ + + /* We compute log(sin(Pi s0)) so that it has branch cuts along + * (-oo, 0] and [1, oo). To do this in a numerically stable way + * we must compute the log first and then mangle its imaginary + * part. The rounding operation below is quite stable because + * we're rounding a number which is already within 1/4 of an + * integer. */ + + /* z = log( sin(Pi s0) / (sqrt(2Pi)/2) ) */ + GEN z = glog(gdiv(gsin(gmul(pi,s0),prec), shiftr(sqrtpi2,-1)), prec); + /* b = (2 Re(s) - 1) / 4 */ + GEN b = shiftr(subrs(shiftr(sig, 1), 1), -2); + y = gsub(y, z); + if (gsigne(imag_i(s)) > 0) togglesign(b); + /* z = 2Pi round( Im(z)/2Pi - b ) */ + z = gmul(roundr(gsub(gdiv(imag_i(z), pi2), b)), pi2); if (signe(z)) { - if (gsigne(imag_i(s)) < 0) togglesign(z); - if (typ(y) == t_COMPLEX) - gel(y,2) = gadd(gel(y,2), z); - else - y = gadd(y, pureimag(z)); + if (typ(y) == t_COMPLEX) + gel(y,2) = gadd(gel(y,2), z); + else + y = gadd(y, pureimag(z)); } p1 = gneg(p1); }