[oct-scm] [oct-git]OCT: A portable Lisp implementation for quad-double precision floats branch master updated. c388f81713d7b2a483000d3cee1af030ed2c1cac
Raymond Toy
rtoy at common-lisp.net
Tue Dec 6 04:03:03 UTC 2011
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "OCT: A portable Lisp implementation for quad-double precision floats".
The branch, master has been updated
via c388f81713d7b2a483000d3cee1af030ed2c1cac (commit)
from 26ef83a4543cdca6f752abca6f68e9d7f586c68e (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit c388f81713d7b2a483000d3cee1af030ed2c1cac
Author: Raymond Toy <toy.raymond at gmail.com>
Date: Mon Dec 5 19:58:44 2011 -0800
Better exp-integral-e computation and fix for incomplete-gamma-tail.
For exp-integral-e, use the series for small z and the
incomplete-gamma-tail for near the negative real axis. Otherwise, use
the continued fraction.
In incomplete-gamma-tail, we were using the continued fraction instead
of the incomplete-gamma function for the region just below the negative
real axis. We should use the cf except in that region.
diff --git a/qd-gamma.lisp b/qd-gamma.lisp
index f13b9a8..48f8345 100644
--- a/qd-gamma.lisp
+++ b/qd-gamma.lisp
@@ -396,7 +396,7 @@
;; Use the incomplete gamma function to evaluate in this
;; region. (Arbitrarily selected the region to be a sector.
;; But what is the correct size of this sector?)
- (if (<= (phase z) 3.1)
+ (if (<= (abs (phase z)) 3.1)
(cf-incomplete-gamma-tail a z)
(- (gamma a) (cf-incomplete-gamma a z)))))))
@@ -460,15 +460,7 @@
(/ (incomplete-gamma 1/2 (* z z))
(sqrt (float-pi z))))))
-(defun exp-integral-e (v z)
- "Exponential integral E:
-
- E(v,z) = integrate(exp(-t)/t^v, t, 1, inf)"
- ;; E(v,z) = z^(v-1) * integrate(t^(-v)*exp(-t), t, z, inf);
- ;;
- ;; for |arg(z)| < pi.
- ;;
- ;;
+(defun cf-exp-integral-e (v z)
;; We use the continued fraction
;;
;; E(v,z) = exp(-z)/cf(z)
@@ -485,7 +477,45 @@
(+ z+v (* 2 k)))
#'(lambda (k)
(* (- k)
- (1- (+ k v))))))))
+ (+ k v -1)))))))
+
+(defun s-exp-integral-e (v z)
+ ;; E(v,z) = gamma(1-v)*z^(v-1) - sum((-1)^k*z^k/(k-v+1)/k!, k, 0, inf)
+ (let ((-z (- z))
+ (-v (- v))
+ (eps (epsilon z)))
+ (loop for k from 0
+ for term = 1 then (* term (/ -z k))
+ for sum = (/ (- 1 v)) then (+ sum (/ term (+ k 1 -v)))
+ when (< (abs term) (* (abs sum) eps))
+ return (- (* (gamma (- 1 v)) (expt z (- v 1)))
+ sum))))
+
+(defun exp-integral-e (v z)
+ "Exponential integral E:
+
+ E(v,z) = integrate(exp(-t)/t^v, t, 1, inf)"
+ ;; E(v,z) = z^(v-1) * integrate(t^(-v)*exp(-t), t, z, inf);
+ ;;
+ ;; for |arg(z)| < pi.
+ ;;
+ ;;
+ (cond ((< (abs z) 1)
+ ;; Use series for small z
+ (s-exp-integral-e v z))
+ ((>= (abs (phase z)) 3.1)
+ ;; The continued fraction doesn't converge on the negative
+ ;; real axis, and converges very slowly near the negative
+ ;; real axis, so use the incomplete-gamma-tail function in
+ ;; this region. "Closeness" to the negative real axis is
+ ;; teken to mean that z is in a sector near the axis.
+ ;;
+ ;; E(v,z) = z^(v-1)*incomplete_gamma_tail(1-v,z)
+ (* (expt z (- v 1))
+ (incomplete-gamma-tail (- 1 v) z)))
+ (t
+ ;; Use continued fraction for everything else.
+ (cf-exp-integral-e v z))))
;; Series for Fresnel S
;;
-----------------------------------------------------------------------
Summary of changes:
qd-gamma.lisp | 52 +++++++++++++++++++++++++++++++++++++++++-----------
1 files changed, 41 insertions(+), 11 deletions(-)
hooks/post-receive
--
OCT: A portable Lisp implementation for quad-double precision floats
More information about the oct-cvs
mailing list