(define (log1pmx x)
(- (log1p x) x))
(define twopi (* 2.0 pi))
(define (gamma-inc-D a x)
(if (< a 10.0)
(let* ((lg (lngamma (+ a 1.0)))
(lnr (- (* a (log x)) x lg)))
(exp lnr))
(let ((gstar (gammastar a))
(ln-term 0.0)
(term1 0.0))
(if (< x a)
(let ((u (/ x a)))
(set! ln-term (+ (log u) (- u) 1.0)))
(let ((mu (/ (- x a) a)))
(set! ln-term (log1pmx mu))))
(set! term1 (/ (exp (* a ln-term))
(sqrt (* twopi a))))
(/ term1 gstar))))
(define (gamma-inc-P-series a x)
(define nmax 5000)
(let ((D (gamma-inc-D a x))
(sum 1.0)
(term 1.0)
(n 1))
(let loop ()
(when (< n nmax)
(set! term (* term (/ x (+ a n))))
(set! sum (+ sum term))
(when (>= (abs (/ term sum)) double-epsilon)
(set! n (+ n 1))
(loop))))
(if (= n nmax)
(error 'gamma-inc-P-series
"maximum iterations exceeded"))
(* D sum)))
(define (gamma-inc-Q-large-x a x)
(define nmax 5000)
(let ((D (gamma-inc-D a x))
(sum 1.0)
(term 1.0)
(last 1.0)
(n 1))
(let loop ()
(when (< n nmax)
(set! term (* term (/ (- a n) x)))
(when (and (<= (abs (/ term last)) 1.0)
(>= (abs (/ term sum))) double-epsilon)
(set! sum (+ sum term))
(set! last term)
(set! n (+ n 1))
(loop))))
(if (= n nmax)
(error 'gamma=inc-Q-large-x
"maximim iterations exceeded"))
(* D (/ a x) sum)))
(define (gamma-inc-Q-asymp-unif a x)
(let* ((rta (sqrt a))
(eps (/ (- x a) a))
(ln-term (log1pmx eps))
(eta (* eps (sqrt (/ (* -2.0 ln-term) (* eps eps)))))
(erfc-val (erfc (* eta sqrt2 rta)))
(r 0.0)
(c0 0.0)
(c1 0.0))
(if (< (abs eps) root5-double-epsilon)
(begin
(set! c0 (+ (/ -1.0 3.0)
(* eps
(- (/ 1.0 12.0)
(* eps
(- (/ 23.0 540.0)
(* eps
(- (/ 353.0 12960.0)
(* eps (/ 589.0 30240.0))))))))))
(set! c1 0.0))
(let ((rt-term (sqrt (/ (* -2.0 ln-term) (* eps eps)))))
(set! c0 (/ (- 1.0 (/ 1.0 rt-term)) eps))
(set! c1 0.0)))
(set! r (* (/ (exp (* -0.5 a eta eta)) (* sqrt2 sqrtpi rta))
(+ c0 (/ c1 a))))
(+ (* 0.5 erfc) r)))
(define (gamma-inc-F-CF a x)
(define nmax 5000)
(define small (exp double-epsilon 3))
(let ((hn 1.0) (cn (/ 1.0 small))
(dn 1.0)
(n 2))
(let loop ()
(when (< n nmax)
(let ((an 0.0)
(delta 0.0))
(if (odd? n)
(set! an (/ (* 0.5 (- n 1)) x))
(set! an (/ (- (* 0.5 n) a) x)))
(set! dn (+ 1.0 (* an dn)))
(if (< (abs dn) small)
(set! dn small))
(set! cn (+ 1.0 (/ an cn)))
(if (< (abs cn) small)
(set! cn small))
(set! dn (/ 1.0 dn))
(set! delta (* cn dn))
(set! hn (* hn delta))
(when (>= (abs (- delta 1.0)) double-epsilon)
(set! n (+ n 1))
(loop)))))
(if (= n nmax)
(error 'gamma-inc-F-CF
"maximum iterations exceeded"))
hn))
(define (gamma-inc-Q-CF a x)
(let ((D (gamma-inc-D a x))
(F (gamma-inc-F-CF a x)))
(* D (/ a x) F)))
(define (gamma-inc-Q-series a x)
(define nmax 5000)
(let* ((pg21 -2.404113806319188570799476) (lnx (log x))
(e1 (+ euler lnx))
(c1 (- e1))
(c2 (- (/ (* pi pi) 12.0) (* 0.5 e1 e1)))
(c3 (+ (* e1 (- (/ (* pi pi) 12.0) (/ (* e1 e1) 6.0)))
(/ pg21 6.0)))
(c4 (* -0.04166666666666666667
(+ -1.758243446661483480 lnx)
(+ -0.764428657272716373 lnx)
(+ 0.723980571623507657 lnx)
(+ 4.107554191916823640 lnx)))
(c5 (* -0.0083333333333333333
(+ -2.06563396085715900 lnx)
(+ -1.28459889470864700 lnx)
(+ -0.27583535756454143 lnx)
(+ 1.33677371336239618 lnx)
(+ 5.17537282427561550 lnx)))
(c6 (* -0.0013888888888888889
(+ -2.30814336454783200 lnx)
(+ -1.65846557706987300 lnx)
(+ -0.88768082560020400 lnx)
(+ 0.17043847751371778 lnx)
(+ 1.92135970115863890 lnx)
(+ 6.22578557795474900 lnx)))
(c7 (* -0.00019841269841269841
(+ -2.5078657901291800 lnx)
(+ -1.9478900888958200 lnx)
(+ -1.3194837322612730 lnx)
(+ -0.5281322700249279 lnx)
(+ 0.5913834939078759 lnx)
(+ 2.4876819633378140 lnx)
(+ 7.2648160783762400 lnx)))
(c8 (* -0.00002480158730158730
(+ -2.677341544966400 lnx)
(+ -2.182810448271700 lnx)
(+ -1.649350342277400 lnx)
(+ -1.014099048290790 lnx)
(+ -0.191366955370652 lnx)
(+ 0.995403817918724 lnx)
(+ 3.041323283529310 lnx)
(+ 8.295966556941250 lnx)))
(c9 (* -2.75573192239859e-6
(+ -2.8243487670469080 lnx)
(+ -2.3798494322701120 lnx)
(+ -1.9143674728689960 lnx)
(+ -1.3814529102920370 lnx)
(+ -0.7294312810261694 lnx)
(+ 0.1299079285269565 lnx)
(+ 1.3873333251885240 lnx)
(+ 3.5857258865210760 lnx)
(+ 9.3214237073814600 lnx)))
(c10 (* -2.75573192239859e-7
(+ -2.9540329644556910 lnx)
(+ -2.5491366926991850 lnx)
(+ -2.1348279229279880 lnx)
(+ -1.6741881076349450 lnx)
(+ -1.1325949616098420 lnx)
(+ -0.4590034650618494 lnx)
(+ 0.4399352987435699 lnx)
(+ 1.7702236517651670 lnx)
(+ 4.1231539047474080 lnx)
(+ 10.342627908148680 lnx)))
(sum5 (+ c5
(* a
(+ c6
(* a
(+ c7
(* a
(+ c8
(* a
(+ c9
(* a
c10)))))))))))
(term1 (* a
(+ c1
(* a
(+ c2
(* a
(+ c3
(* a
(+ c4
(* a sum5))))))))))
(term2 0.0)
(sum 1.0)
(t 1.0)
(n 1))
(let loop ()
(when (< n nmax)
(set! t (* t (/ (- x) (+ n 1.0))))
(set! sum (+ sum (* (/ (+ a 1.0) (+ a n 1.0)) t)))
(when (>= (abs (/ t sum)) double-epsilon)
(set! n (+ n 1))
(loop))))
(if (= n nmax)
(error 'gamma-inc-Q-series
"maximum iterations exceeded"))
(set! term2 (* (- 1.0 term1) (/ a (+ a 1.0)) x sum))
(+ term1 term2)))
(define (gamma-inc-series a x)
(let ((Q (gamma-inc-Q-series a x))
(G (gamma a)))
(* Q G)))
(define (gamma-inc-a-gt-0 a x)
(let ((Q (gamma-inc-Q a x))
(G (gamma a)))
(* G Q)))
(define (gamma-inc-CF a x)
(let ((F (gamma-inc-F-CF a x))
(pre (exp (- (* (- a 1.0) (log x)) x))))
(* F pre)))
(define (gamma-inc-a-0 x)
(expint-E1 x))
(define (gamma-inc-Q a x)
(cond ((= x 0.0)
1.0)
((= a 0.0)
0.0)
((<= x (+ 0.5 a))
(- 1.0 (gamma-inc-P-series a x)))
((and (>= a 1.0e06)
(< (* (- x a) (- x a)) a))
(gamma-inc-Q-asymp-unif a x))
((and (< a 0.2)
(< x 5.0))
(gamma-inc-Q-series a x))
((<= a x)
(if (<= x 1.0e06)
(gamma-inc-Q-CF a x)
(gamma-inc-Q-large-x a x)))
(else
(if (< a (* 0.8 x))
(gamma-inc-Q-CF a x)
(- 1.0 (gamma-inc-P-series a x))))))
(define (gamma-inc-P a x)
(cond ((= x 0.0)
0.0)
((or (< x 20.0)
(< x (* 0.5 a)))
(gamma-inc-P-series a x))
((and (> a 1.0e06)
(< (* (- x a) (- x a)) a))
(- 1.0 (gamma-inc-Q-asymp-unif a x)))
((<= a x)
(let ((Q 0.0))
(if (> a (* 0.2 x))
(set! Q (gamma-inc-Q-CF a x))
(set! Q (gamma-inc-Q-large-x a x)))
(- 1.0 Q)))
((< (* (- x a)(- x a)) a)
(let ((Q (gamma-inc-Q-CF a x)))
(- 1.0 Q)))
(else
(gamma-inc-P-series a x))))
(define (gamma-inc a x)
(cond ((= x 0.0)
(gamma a))
((= a 0.0)
(gamma-inc-a-0 x))
((> a 0.0)
(gamma-inc-a-gt-0 a x))
((> x 0.25)
(gamma-inc-CF a x))
((< (abs a) 0.5)
(gamma-inc-series a x))
(else
(let* ((fa (floor a))
(da (- a fa))
(g-da (if (> da 0.0)
(gamma-inc-a-gt-0 da x)
(gamma-inc-a-0 x)))
(alpha da)
(gax g-da))
(let loop ()
(when (> alpha a)
(let ((shift (exp (+ (- x) (* (- alpha 1.0) (log x))))))
(set! gax (/ (- gax shift) (- alpha 1.0)))
(set! alpha (- alpha 1.0))
(loop))))
gax))))