Skip to content

Commit 9f99884

Browse files
committed
Improve precision for incompleteGamma
Compute constant in factorP expansion in linear domain when possible. It allows to improve precision by 2-3 digits! Fixes #42
1 parent 0105f92 commit 9f99884

File tree

1 file changed

+17
-2
lines changed

1 file changed

+17
-2
lines changed

Numeric/SpecFunctions/Internal.hs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -411,10 +411,25 @@ incompleteGamma a x
411411
--
412412
-- Evaluate series for P(a,x). See [Temme1994] Eq. 5.5
413413
--
414-
-- FIXME: Term `exp (log x * z - x - logGamma (z+1))` doesn't give full precision
414+
-- Evaluation of constant multiplier is somewhat tricky. On one
415+
-- hand working in linear domain gives markedly better precision
416+
-- than log domain (in log domain we can easily lose 2-3
417+
-- digits). On other it's prone to overflow: we're working with
418+
-- exponents and gamma function here!. Solution is to try to
419+
-- compute value normally and revert to log domain it anything
420+
-- overflowed
421+
factorP
422+
| isInfinite num = logDom
423+
| isInfinite denom = logDom
424+
| otherwise = num / denom
425+
where
426+
num = x ** a
427+
denom = exp x * exp (logGamma (a + 1))
428+
logDom = exp (log x * a - x - logGamma (a+1))
429+
415430
taylorSeriesP
416431
= sumPowerSeries x (scanSequence (/) 1 $ enumSequenceFrom (a+1))
417-
* exp (log x * a - x - logGamma (a+1))
432+
* factorP
418433
-- Series for 1-Q(a,x). See [Temme1994] Eq. 5.5
419434
taylorSeriesComplQ
420435
= sumPowerSeries (-x) (scanSequence (/) 1 (enumSequenceFrom 1) / enumSequenceFrom a)

0 commit comments

Comments
 (0)