Hi Roban,
Basically, _gamma3 uses two different formulas: it either computes a
difference of two upper incomplete gamma functions, or a difference of
two lower incomplete gamma functions.
Right now it just tries one formula with a fixed precision and checks
if it's good, and otherwise it tries the other with the same fixed
precision. If neither is good, it raises NotImplementedError rather
than returning an inaccurate value.
A better algorithm would be to increase the precision in a loop until
either formula gives full accuracy (and maybe raise NoConvergence when
the precision gets too large). This could be done by changing a few
lines in the existing code. You're very welcome to write a patch.
To improve efficiency further, one could switch to a series expansion
for computing gamma(z,a,b) when b = a+epsilon for sufficiently small
epsilon, say |epsilon| < max(|a|,|z|) * 2^(-prec/4). The series wrt
epsilon goes something like
gamma(z,a,a+epsilon) = exp(-a) * a^z * (epsilon / a) * (1 + epsilon *
(3z-3-3a) / (6*a) + ...)
This should also be quite straightforward, in case you are interested
in writing a patch.
Fredrik