176
182
(defmfun simpgamma (x vestigial z)
177
183
(declare (ignore vestigial))
179
(let* ((j (simpcheck (cadr x) z))
182
(cond ((floatp j) (gammafloat j))
185
(or $numer (floatp jr) (floatp ji)))
186
(complexify (gamma-lanczos (complex (float jr)
189
(ratgreaterp (simpabs (list '(%abs) j) 1 t) $gammalim))
190
(eqtest (list '(%gamma) j) x))
185
(let ((j (simpcheck (cadr x) z)))
186
(cond ((and (floatp j)
189
(zerop (nth-value 1 (truncate j))))))
190
(merror "gamma(~:M) is undefined." j))
191
((floatp j) (gammafloat j))
194
(and (eq ($sign j) '$neg)
195
(zerop1 (sub j ($truncate j))))))
196
(merror "gamma(~:M) is undefined." j))
198
;; Adding 4 digits in the call to bffac. For $fpprec up to about 256
199
;; and an argument up to about 500.0 the accuracy of the result is
200
;; better than 10^(-$fpprec).
201
(mfuncall '$bffac (m+ j -1) (+ $fpprec 4)))
202
((and (complex-number-p j 'float-or-rational-p)
203
(or $numer (floatp ($realpart j)) (floatp ($imagpart j))))
204
(complexify (gamma-lanczos (complex ($float ($realpart j))
205
($float ($imagpart j))))))
206
((and (complex-number-p j 'bigfloat-or-number-p)
207
(or $numer ($bfloatp ($realpart j))
208
($bfloatp ($imagpart j))))
209
;; Adding 4 digits in the call to cbffac. See comment above.
211
(add -1 ($bfloat ($realpart j))
212
(mul '$%i ($bfloat ($imagpart j))))
214
((eq j '$inf) '$inf) ; Simplify to $inf to be more consistent.
218
;; Expand gamma(z+n) for n an integer.
220
(z (simplify (cons '(mplus) (cddr j)))))
223
(mul (simplify (list '($pochhammer) z n))
224
(simplify (list '(%gamma) z))))
227
(div (mul (power -1 n) (simplify (list '(%gamma) z)))
228
;; We factor to get the order (z-1)*(z-2)*...
229
;; and not (1-z)*(2-z)*...
231
(simplify (list '($pochhammer) (sub 1 z) n))))))))
192
(cond ((> j 0) (simpfact (list '(mfactorial) (1- j)) 1 nil))
234
(cond ((<= j $factlim)
235
;; Positive integer less than $factlim. Evaluate.
236
(simplify (list '(mfactorial) (1- j))))
237
;; Positive integer greater $factlim. Noun form.
238
(t (eqtest (list '(%gamma) j) x))))
239
;; Negative integer. Throw a Maxima error.
193
240
(errorsw (throw 'errorsw t))
194
241
(t (merror "gamma(~:M) is undefined" j))))
195
242
($numer (gammafloat (fpcofrat j)))
196
243
((alike1 j '((rat) 1 2))
197
244
(list '(mexpt simp) '$%pi j))
198
((or (ratgreaterp j 1) (ratgreaterp 0 j)) (gammared j))
246
(ratgreaterp $gammalim (simplify (list '(mabs) j)))
247
(or (ratgreaterp j 1) (ratgreaterp 0 j)))
248
;; Expand for rational numbers less than $gammalim.
199
250
(t (eqtest (list '(%gamma) j) x)))))
201
252
(defun gamma (y) ;;; numerical evaluation for 0 < y < 1
202
253
(prog (sum coefs)
203
(setq coefs (list 0.035868343d0 -0.193527817d0 0.48219939d0
204
-0.75670407d0 0.91820685d0 -0.89705693d0
205
0.98820588d0 -0.57719165d0))
254
(setq coefs (list 0.035868343 -0.193527817 0.48219939
255
-0.75670407 0.91820685 -0.89705693
256
0.98820588 -0.57719165))
206
257
(unless (atom y) (setq y (fpcofrat y)))
207
258
(setq sum (car coefs) coefs (cdr coefs))
208
259
loop (setq sum (+ (* sum y) (car coefs)))
259
310
(defun gamma-lanczos (z)
260
(declare (type (complex double-float) z)
311
(declare (type (complex flonum) z)
261
312
(optimize (safety 3)))
262
(let ((c (make-array 15 :element-type 'double-float
313
(let ((c (make-array 15 :element-type 'flonum
263
314
:initial-contents
264
'(0.99999999999999709182d0
265
57.156235665862923517d0
266
-59.597960355475491248d0
267
14.136097974741747174d0
268
-0.49191381609762019978d0
269
.33994649984811888699d-4
270
.46523628927048575665d-4
271
-.98374475304879564677d-4
272
.15808870322491248884d-3
273
-.21026444172410488319d-3
274
.21743961811521264320d-3
275
-.16431810653676389022d-3
276
.84418223983852743293d-4
277
-.26190838401581408670d-4
278
.36899182659531622704d-5))))
279
(declare (type (simple-array double-float (15)) c))
315
'(0.99999999999999709182
316
57.156235665862923517
317
-59.597960355475491248
318
14.136097974741747174
319
-0.49191381609762019978
320
.33994649984811888699e-4
321
.46523628927048575665e-4
322
-.98374475304879564677e-4
323
.15808870322491248884e-3
324
-.21026444172410488319e-3
325
.21743961811521264320e-3
326
-.16431810653676389022e-3
327
.84418223983852743293e-4
328
-.26190838401581408670e-4
329
.36899182659531622704e-5))))
330
(declare (type (simple-array flonum (15)) c))
280
331
(if (minusp (realpart z))
281
332
;; Use the reflection formula
282
333
;; -z*Gamma(z)*Gamma(-z) = pi/sin(pi*z)
284
335
;; Gamma(z) = pi/z/sin(pi*z)/Gamma(-z)
286
337
;; If z is a negative integer, Gamma(z) is infinity. Should
287
;; we test for this? Throw an error? What
289
(* (- z) (sin (* (float pi 1d0) z))
338
;; we test for this? Throw an error?
339
;; The test must be done by the calling routine.
341
(* (- z) (sin (* (float pi) z))
290
342
(gamma-lanczos (- z))))
291
343
(let* ((z (- z 1))
293
345
(zgh (+ zh 607/128))
294
(zp (expt zgh (/ zh 2)))
297
348
(pp (1- (length c)) (1- pp)))
300
351
(incf sum (/ (aref c pp) (+ z pp))))))
301
(* (sqrt (float (* 2 pi) 1d0))
303
(* zp (exp (- zgh)) zp))))))
353
;; We check for an overflow. The last positive value in
354
;; double-float precicsion for which Maxima can calculate
355
;; gamma is ~171.6243 (CLISP 2.46 and GCL 2.6.8)
357
(let ((zp (expt zgh (/ zh 2))))
358
(* (sqrt (float (* 2 pi)))
360
(* (/ zp (exp zgh)) zp))))))
362
;; No result. Overflow.
363
(merror "Overflow in `gamma-lanczos'."))
364
((or (float-nan-p (realpart result))
365
(float-inf-p (realpart result)))
366
;; Result, but beyond extreme values. Overflow.
367
(merror "Overflow in `gamma-lanczos'."))
305
370
(defun gammafloat (a)
306
(realpart (gamma-lanczos (complex a 0d0))))
374
(* a (sin (* (float pi) a)))
380
(let ((c (* (sqrt (* 2 (float pi)))
381
(exp (slatec::d9lgmc a)))))
382
(let ((v (expt a (- (* .5d0 a) 0.25d0))))
386
(if (or (float-nan-p result)
387
(float-inf-p result))
388
(merror "Overflow in `gammafloat'")
308
392
(declare-top (special $numer $trigsign))
310
(defmfun simperf (x vestigial z &aux y)
311
(declare (ignore vestigial))
313
(setq y (simpcheck (cadr x) z))
315
((or (floatp y) (and $numer (integerp y))) (erf (float y)))
318
((and $trigsign (mminusp* y)) (neg (list '(%erf simp) (neg y))))
319
(t (eqtest (list '(%erf) y) x))))
323
(slatec:derf (float y 1d0)))
326
(slatec:derfc (float y 1d0)))
394
;;; The Error functions Erf, Erfc, Erfi and the function Generalized Erf have
395
;;; been implemented as simplifying functions. The code is moved to the file
396
;;; gamma.lisp and commented out at this place. 10/2008 DK.
398
;(defmfun simperf (x vestigial z &aux y)
399
; (declare (ignore vestigial))
401
; (setq y (simpcheck (cadr x) z))
402
; (cond ((zerop1 y) y)
403
; ((or (floatp y) (and $numer (integerp y))) (erf (float y)))
406
; ;;((and $trigsign (mminusp* y)) (neg (list '(%erf simp) (neg y))))
407
; ((and $trigsign (great (neg y) y)) (neg (take '(%erf) (neg y))))
408
; (t (eqtest (list '(%erf) y) x))))
412
; (slatec:derf (float y)))
415
; (slatec:derfc (float y)))
328
417
(defmfun $zeromatrix (m n) ($ematrix m n 0 1 1))