1 ;;; -*- Mode: Lisp; Package: Maxima; Syntax: Common-Lisp; Base: 10 -*- ;;;;
2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3 ;;; The data in this file contains enhancments. ;;;;;
5 ;;; Copyright (c) 1984,1987 by William Schelter,University of Texas ;;;;;
6 ;;; All rights reserved ;;;;;
7 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8 ;;; (c) Copyright 1982 Massachusetts Institute of Technology ;;;
9 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
13 (macsyma-module csimp2
)
15 (load-macsyma-macros rzmac
)
17 (declare-top (special var %p%i varlist plogabs half%pi nn
* dn
* $factlim sign
20 (defmvar $gammalim
10000
21 "Controls simplification of gamma for rational number arguments.")
23 (defmvar $gamma_expand nil
24 "Expand gamma(z+n) for n an integer when T.")
26 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
28 ;;; Implementation of the plog function
30 (defun simpplog (x vestigial z
)
31 (declare (ignore vestigial
))
32 (prog (varlist dd check y
)
35 (setq x
(simpcheck (cadr x
) z
))
36 (cond ((equal 0 x
) (merror (intl:gettext
"plog: plog(0) is undefined.")))
37 ((among var x
) ;This is used in DEFINT. 1/19/81. -JIM
38 (return (eqtest (list '(%plog
) x
) check
))))
41 ((and (member '$%i varlist
)
42 (not (some #'(lambda (v)
43 (and (atom v
) (not (eq v
'$%i
))))
45 (setq dd
(trisplit x
))
46 (cond ((setq z
(patan (car dd
) (cdr dd
)))
47 (return (add2* (simpln (list '(%log
)
48 (simpexpt (list '(mexpt)
49 ($expand
(list '(mplus)
50 (list '(mexpt) (car dd
) 2)
51 (list '(mexpt) (cdr dd
) 2)))
52 '((rat) 1 2)) 1 nil
)) 1 t
)
53 (list '(mtimes) z
'$%i
))))))
54 ((and (free x
'$%i
) (eq ($sign x
) '$pnz
))
55 (return (eqtest (list '(%plog
) x
) check
)))
56 ((and (equal ($imagpart x
) 0) (setq y
($asksign x
)))
57 (cond ((eq y
'$pos
) (return (simpln (list '(%log
) x
) 1 t
)))
58 ((and plogabs
(eq y
'$neg
))
59 (return (simpln (list '(%log
) (list '(mtimes) -
1 x
)) 1 nil
)))
62 (simpln (list '(%log
) (list '(mtimes) -
1 x
)) 1 nil
))))
63 (t (merror (intl:gettext
"plog: plog(0) is undefined.")))))
64 ((and (equal ($imagpart
(setq z
(div* x
'$%i
))) 0)
65 (setq y
($asksign z
)))
67 ((equal y
'$zero
) (merror (intl:gettext
"plog: plog(0) is undefined.")))
68 (t (cond ((eq y
'$pos
) (setq y
1))
69 ((eq y
'$neg
) (setq y -
1)))
70 (return (add2* (simpln (list '(%log
)
71 (list '(mtimes) y z
)) 1 nil
)
72 (list '(mtimes) y
'((rat) 1 2) '$%i
'$%pi
)))))))
73 (return (eqtest (list '(%plog
) x
) check
))))
76 (let (($numer $numer
))
78 (setq i
(simplifya i nil
) r
(simplifya r nil
))
80 (if (floatp i
) (setq $numer t
))
82 (cond ((equal i
'$pos
) (return (simplify half%pi
)))
84 (return (mul2 -
1 (simplify half%pi
))))
85 (t (merror (intl:gettext
"plog: encountered atan(0/0).")))))
87 (cond ((floatp r
) (setq $numer t
)))
89 (cond ((equal r
'$pos
) (return 0))
90 ((equal r
'$neg
) (return (simplify '$%pi
)))
91 (t (merror (intl:gettext
"plog: encountered atan(0/0).")))))
92 ((and (among '%cos r
) (among '%sin i
))
93 ;; genvar and varlist, used by the rational function system,
94 ;; are bound in order to prevent the symbol 'xz from leaking
95 ;; out of this function.
96 (let ((var 'xz
) genvar varlist
)
98 (cond ((and (eq (caar nn
*) '%cos
) (eq (caar dn
*) '%sin
))
99 (return (cadr nn
*)))))))
100 (setq a
($sign r
) b
($sign i
))
101 (cond ((eq a
'$pos
) (setq a
1))
102 ((eq a
'$neg
) (setq a -
1))
103 ((eq a
'$zero
) (setq a
0)))
104 (cond ((eq b
'$pos
) (setq b
1))
105 ((eq b
'$neg
) (setq b -
1))
106 ((eq a
'$zero
) (setq b
0)))
108 (return (if (equal a
1) 0 (simplify '$%pi
))))
110 (return (cond ((equal b
1) (simplify half%pi
))
111 (t (mul2 '((rat simp
) -
1 2)
112 (simplify '$%pi
)))))))
113 (setq r
(simptimes (list '(mtimes) a b
(div* i r
)) 1 nil
))
114 (return (cond ((onep1 r
)
115 (archk a b
(list '(mtimes) '((rat) 1 4) '$%pi
)))
116 ((alike1 r
'((mexpt) 3 ((rat) 1 2)))
117 (archk a b
(list '(mtimes) '((rat) 1 3) '$%pi
)))
118 ((alike1 r
'((mexpt) 3 ((rat) -
1 2)))
119 (archk a b
(list '(mtimes) '((rat) 1 6) '$%pi
))))))))
121 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
123 ;;; Implementation of the Binomial coefficient
125 ;; Verb function for the Binomial coefficient
126 (defmfun $binomial
(x y
)
127 (simplify (list '(%binomial
) x y
)))
129 ;; Binomial has Mirror symmetry
130 (defprop %binomial t commutes-with-conjugate
)
132 (defun simpbinocoef (x vestigial z
)
133 (declare (ignore vestigial
))
135 (let ((u (simpcheck (cadr x
) z
))
136 (v (simpcheck (caddr x
) z
))
140 (if (and (integerp u
) (minusp u
) (< v u
))
143 ((or (zerop v
) (equal u v
)) 1)
144 ((and (integerp u
) (not (minusp u
)))
145 (bincomp u
(min v
(- u v
))))
147 ((integerp (setq y
(sub u v
)))
149 ;; u and v are equal, simplify not if argument can be negative
150 (if (member ($csign u
) '($pnz $pn $neg $nz
))
151 (eqtest (list '(%binomial
) u v
) x
)
154 ((complex-float-numerical-eval-p u v
)
155 ;; Numercial evaluation for real and complex floating point numbers.
156 (let (($numer t
) ($float t
))
159 ($makegamma
(list '(%binomial
) ($float u
) ($float v
)))))))
160 ((complex-bigfloat-numerical-eval-p u v
)
161 ;; Numerical evaluation for real and complex bigfloat numbers.
164 ($makegamma
(list '(%binomial
) ($bfloat u
) ($bfloat v
))))))
165 (t (eqtest (list '(%binomial
) u v
) x
)))))
170 ((mnump u
) (binocomp u v
))
171 (t (muln (bincomp1 u v
) nil
))))
173 (defun bincomp1 (u v
)
176 (list* u
(list '(mexpt) v -
1) (bincomp1 (add2 -
1 u
) (1- v
)))))
178 (defun binocomp (u v
)
181 loop
(if (zerop v
) (return ans
))
182 (setq ans
(timesk (timesk u ans
) (simplify (list '(rat) 1 v
))))
183 (setq u
(addk -
1 u
) v
(1- v
))
186 ;;; gradient of binomial
190 ((mtimes) -
1 ((%binomial
) a b
)
193 ((mqapply) (($psi array
) 0) ((mplus) 1 a
)))
194 ((mqapply) (($psi array
) 0)
195 ((mplus) 1 a
((mtimes) -
1 b
)))))
197 ((mtimes) -
1 ((%binomial
) a b
)
200 ((mqapply) (($psi array
) 0)
201 ((mplus) 1 a
((mtimes) -
1 b
))))
202 ((mqapply) (($psi array
) 0) ((mplus) 1 b
))))) grad
)
204 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
206 ;;; Implementation of the Beta function
208 (declare-top (special $numer $gammalim
))
210 (defmvar $beta_args_sum_to_integer nil
)
212 ;;; The Beta function has mirror symmetry
213 (defprop $beta t commutes-with-conjugate
)
215 (defun simpbeta (x vestigial z
&aux check
)
216 (declare (ignore vestigial
))
219 (let ((u (simpcheck (cadr x
) z
)) (v (simpcheck (caddr x
) z
)))
220 (cond ((or (zerop1 u
) (zerop1 v
))
224 (intl:gettext
"beta: expected nonzero arguments; found ~M, ~M")
227 ;; Check for numerical evaluation in float precision
228 ((complex-float-numerical-eval-p u v
)
230 ;; We use gamma(u)*gamma(v)/gamma(u+v) for numerical evaluation.
231 ;; Therefore u, v or u+v can not be a negative integer or a
232 ;; floating point representation of a negative integer.
233 ((and (or (not (numberp u
))
235 (not (= (nth-value 1 (truncate u
)) 0)))
236 (and (or (not (numberp v
))
238 (not (= (nth-value 1 (truncate v
)) 0)))
239 (and (or (not (numberp (add u v
)))
241 (not (= (nth-value 1 ($truncate
(add u v
))) 0))))))
244 (add ($log_gamma
($float u
))
245 ($log_gamma
($float v
))
246 (mul -
1 ($log_gamma
($float
(add u v
))))))))
247 ((or (and (numberp u
)
249 (= (nth-value 1 (truncate u
)) 0)
251 (eq ($sign
(sub ($truncate v
) v
)) '$zero
)
253 (eq ($sign
(add u v
)) '$pos
)))
254 (setq u
(truncate u
)))
257 (= (nth-value 1 (truncate u
)) 0)
259 (eq ($sign
(sub ($truncate u
) u
)) '$zero
)
261 (eq ($sign
(add u v
)) '$pos
)))
262 (setq v
(truncate v
))))
263 ;; One value is representing a negative integer, the other a
264 ;; positive integer and the sum is negative. Expand.
265 ($rectform
($float
(beta-expand-integer u v
))))
267 (eqtest (list '($beta
) u v
) check
))))
269 ;; Check for numerical evaluation in bigfloat precision
270 ((complex-bigfloat-numerical-eval-p u v
)
271 (let (($ratprint nil
))
273 ((and (or (not (mnump u
))
275 (not (eq ($sign
(sub ($truncate u
) u
)) '$zero
)))
278 (not (eq ($sign
(sub ($truncate v
) v
)) '$zero
)))
279 (or (not (mnump (add u v
)))
280 (eq ($sign
(add u v
)) '$pos
)
281 (not (eq ($sign
(sub ($truncate
(add u v
))
286 (add ($log_gamma
($bfloat u
))
287 ($log_gamma
($bfloat v
))
288 (mul -
1 ($log_gamma
($bfloat
(add u v
))))))))
291 (eq ($sign
(sub ($truncate u
) u
)) '$zero
)
293 (eq ($sign
(sub ($truncate v
) v
)) '$zero
)
295 (eq ($sign
(add u v
)) '$pos
)))
296 (setq u
($truncate u
)))
299 (eq ($sign
(sub ($truncate v
) v
)) '$zero
)
301 (eq ($sign
(sub ($truncate u
) u
)) '$zero
)
303 (eq ($sign
(add u v
)) '$pos
)))
304 (setq v
($truncate v
))))
305 ($rectform
($bfloat
(beta-expand-integer u v
))))
307 (eqtest (list '($beta
) u v
) check
)))))
309 ((or (and (and (integerp u
)
312 (eq ($sign
(sub ($truncate v
) v
)) '$zero
)
314 (eq ($sign
(add u v
)) '$pos
))))
315 (and (and (integerp v
)
318 (eq ($sign
(sub ($truncate u
) u
)) '$zero
)
320 (eq ($sign
(add u v
)) '$pos
)))))
321 ;; Expand for a positive integer. But not if the other argument is
322 ;; a negative integer and the sum of the integers is not negative.
323 (beta-expand-integer u v
))
325 ;;; At this point both integers are negative. This code does not work for
326 ;;; negative integers. The factorial function is not defined.
327 ; ((and (integerp u) (integerp v))
328 ; (mul2* (div* (list '(mfactorial) (1- u))
329 ; (list '(mfactorial) (+ u v -1)))
330 ; (list '(mfactorial) (1- v))))
332 ((or (and (ratnump u
) (ratnump v
) (integerp (setq x
(addk u v
))))
333 (and $beta_args_sum_to_integer
334 (integerp (setq x
(expand1 (add2 u v
) 1 1)))))
335 (let ((w (if (symbolp v
) v u
)))
338 (add2 (1- x
) (neg w
))
340 `((%sin
) ((mtimes) ,w $%pi
)))))
342 ((and $beta_expand
(mplusp u
) (integerp (cadr u
)))
343 ;; Expand beta(a+n,b) where n is an integer.
345 (u (simplify (cons '(mplus) (cddr u
)))))
346 (beta-expand-add-integer n u v
)))
348 ((and $beta_expand
(mplusp v
) (integerp (cadr v
)))
349 ;; Expand beta(a,b+n) where n is an integer.
351 (v (simplify (cons '(mplus) (cddr v
)))))
352 (beta-expand-add-integer n v u
)))
354 (t (eqtest (list '($beta
) u v
) check
)))))
356 (defun beta-expand-integer (u v
)
357 ;; One of the arguments is a positive integer. Do an expansion.
358 ;; BUT for a negative integer as second argument the expansion is only
359 ;; possible when the sum of the integers is negative too.
360 ;; This routine expects that the calling routine has checked this.
367 (sub (if (and (integerp u
) (plusp u
)) u v
) 1))))
370 (defun beta-expand-add-integer (n u v
)
372 (mul (simplify (list '($pochhammer
) u n
))
373 (power (simplify (list '($pochhammer
) (add u v
) n
)) -
1)
374 (simplify (list '($beta
) u v
)))
375 (mul (simplify (list '($pochhammer
) (add u v n
) (- n
)))
376 (power (simplify (list '($pochhammer
) (add u n
) (- n
))) -
1)
377 (simplify (list '($beta
) u v
)))))
379 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
381 ;;; Implementation of the Gamma function
383 (defun simpgamma (x vestigial z
)
384 (declare (ignore vestigial
))
386 (let ((j (simpcheck (cadr x
) z
)))
387 (cond ((and (floatp j
)
390 (zerop (nth-value 1 (truncate j
))))))
391 (merror (intl:gettext
"gamma: gamma(~:M) is undefined.") j
))
392 ((float-numerical-eval-p j
) (gammafloat ($float j
)))
395 (and (eq ($sign j
) '$neg
)
396 (zerop1 (sub j
($truncate j
))))))
397 (merror (intl:gettext
"gamma: gamma(~:M) is undefined.") j
))
398 ((bigfloat-numerical-eval-p j
)
399 ;; Adding 4 digits in the call to bffac. For $fpprec up to about 256
400 ;; and an argument up to about 500.0 the accuracy of the result is
401 ;; better than 10^(-$fpprec).
402 (let ((z (bigfloat:to
($bfloat j
))))
404 ((bigfloat:<= (bigfloat:abs z
) (bigfloat:sqrt
(bigfloat:epsilon z
)))
405 ;; For small z, use gamma(z) = gamma(z+1)/z = z!/z
406 (div (mfuncall '$bffac
411 (let ((result (mfuncall '$bffac
(m+ ($bfloat j
) -
1) (+ $fpprec
4))))
412 ;; bigfloatp will round the result to the correct fpprec
413 (bigfloatp result
))))))
414 ((complex-float-numerical-eval-p j
)
415 (complexify (gamma-lanczos (complex ($float
($realpart j
))
416 ($float
($imagpart j
))))))
417 ((complex-bigfloat-numerical-eval-p j
)
418 (let ((z (bigfloat:to
($bfloat j
))))
420 ((bigfloat:<= (bigfloat:abs z
)
421 (bigfloat:sqrt
(bigfloat:epsilon z
)))
422 ;; For small z, use gamma(z) = gamma(z+1)/z = z!/z
423 (to (bigfloat:/ (bigfloat:to
(mfuncall '$cbffac
428 ;; Adding 4 digits in the call to cbffac. See comment above.
431 (add -
1 ($bfloat
($realpart j
))
432 (mul '$%i
($bfloat
($imagpart j
))))
434 (add (bigfloatp ($realpart result
))
435 (mul '$%i
(bigfloatp ($imagpart result
)))))))))
436 ((taylorize (mop x
) (cadr x
)))
437 ((eq j
'$inf
) '$inf
) ; Simplify to $inf to be more consistent.
441 ;; Expand gamma(z+n) for n an integer.
443 (z (simplify (cons '(mplus) (cddr j
)))))
446 (mul (simplify (list '($pochhammer
) z n
))
447 (simplify (list '(%gamma
) z
))))
450 (div (mul (power -
1 n
) (simplify (list '(%gamma
) z
)))
451 ;; We factor to get the order (z-1)*(z-2)*...
452 ;; and not (1-z)*(2-z)*...
454 (simplify (list '($pochhammer
) (sub 1 z
) n
))))))))
457 (cond ((<= j $factlim
)
458 ;; Positive integer less than $factlim. Evaluate.
459 (simplify (list '(mfactorial) (1- j
))))
460 ;; Positive integer greater $factlim. Noun form.
461 (t (eqtest (list '(%gamma
) j
) x
))))
462 ;; Negative integer. Throw a Maxima error.
463 (errorsw (throw 'errorsw t
))
464 (t (merror (intl:gettext
"gamma: gamma(~:M) is undefined.") j
))))
465 ((alike1 j
'((rat) 1 2))
466 (list '(mexpt simp
) '$%pi j
))
468 (ratgreaterp $gammalim
(simplify (list '(mabs) j
)))
469 (or (ratgreaterp j
1) (ratgreaterp 0 j
)))
470 ;; Expand for rational numbers less than $gammalim.
472 (t (eqtest (list '(%gamma
) j
) x
)))))
474 ;; A sign function for gamma(x); when x > 0 return pos; when x < 0 or x > 0, return pn;
475 ;;; otherwise, return pnz (that is, nothing known).
476 (defun gamma-sign (x)
477 (let ((sgn ($csign
(second x
)))) ;; careful! x = ((%gamma) XXX)
479 (cond ((eql sgn
'$pos
) '$pos
)
480 ((or (eql sgn
'$neg
) (eql sgn
'$pn
)) '$pn
)
483 (putprop '%gamma
#'gamma-sign
'sign-function
)
485 (defun gamma (y) ;;; numerical evaluation for 0 < y < 1
487 (setq coefs
(list 0.035868343 -
0.193527817 0.48219939
488 -
0.75670407 0.91820685 -
0.89705693
489 0.98820588 -
0.57719165))
490 (unless (atom y
) (setq y
(fpcofrat y
)))
491 (setq sum
(car coefs
) coefs
(cdr coefs
))
492 loop
(setq sum
(+ (* sum y
) (car coefs
)))
493 (when (setq coefs
(cdr coefs
)) (go loop
))
494 (return (+ (/ y
) sum
))))
496 (defun gammared (a) ;A is assumed to
497 (prog (m q n
) ;be '((RAT) M N)
498 (cond ((floatp a
) (return (gammafloat a
))))
499 (setq m
(cadr a
) ;Numerator
500 n
(caddr a
) ;denominator
501 q
(abs (truncate m n
))) ;integer part
503 (setq q
(1+ q
) m
(+ m
(* n q
)))
505 (simptimes (list '(mtimes)
507 (simpgamma (list '(%gamma
)
511 (list '(mexpt) (gammac m n q
) -
1))
514 (return (m* (gammac m n q
)
515 (simpgamma (list '(%gamma
)
516 (list '(rat) (rem m n
) n
))
520 (defun gammac (m n q
)
523 (setq q
(1- q
) m
(- m n
) ans
(* m ans
))))
526 ;; This implementation is based on Lanczos convergent formula for the
527 ;; gamma function for Re(z) > 0. We can use the reflection formula
529 ;; -z*Gamma(z)*Gamma(-z) = pi/sin(pi*z)
531 ;; to handle the case of Re(z) <= 0.
533 ;; See http://my.fit.edu/~gabdo/gamma.m for some matlab code to
534 ;; compute this and http://my.fit.edu/~gabdo/gamma.txt for a nice
535 ;; discussion of Lanczos method and an improvement of Lanczos method.
538 ;; The document says this should give about 15 digits of accuracy for
539 ;; double-precision IEEE floats. The document also indicates how to
540 ;; compute a new set of coefficients if you need more range or
543 (defun gamma-lanczos (z)
544 (declare (type (complex flonum
) z
)
545 (optimize (safety 3)))
546 (let ((c (make-array 15 :element-type
'flonum
548 '(0.99999999999999709182
549 57.156235665862923517
550 -
59.597960355475491248
551 14.136097974741747174
552 -
0.49191381609762019978
553 .33994649984811888699e-4
554 .46523628927048575665e-4
555 -
.98374475304879564677e-4
556 .15808870322491248884e-3
557 -
.21026444172410488319e-3
558 .21743961811521264320e-3
559 -
.16431810653676389022e-3
560 .84418223983852743293e-4
561 -
.26190838401581408670e-4
562 .36899182659531622704e-5))))
563 (declare (type (simple-array flonum
(15)) c
))
565 ((minusp (realpart z
))
566 ;; Use the reflection formula
567 ;; -z*Gamma(z)*Gamma(-z) = pi/sin(pi*z)
569 ;; Gamma(z) = pi/z/sin(pi*z)/Gamma(-z)
571 ;; If z is a negative integer, Gamma(z) is infinity. Should
572 ;; we test for this? Throw an error?
573 ;; The test must be done by the calling routine.
575 (* (- z
) (sin (* (float pi
) z
))
576 (gamma-lanczos (- z
)))))
577 ((<= (abs z
) (sqrt flonum-epsilon
))
578 ;; For |z| small, use Gamma(z) = Gamma(z+1)/z
579 (/ (gamma-lanczos (+ 1 z
))
587 (pp (1- (length c
)) (1- pp
)))
590 (incf sum
(/ (aref c pp
) (+ z pp
))))))
592 ;; We check for an overflow. The last positive value in
593 ;; double-float precicsion for which Maxima can calculate
594 ;; gamma is ~171.6243 (CLISP 2.46 and GCL 2.6.8)
596 (let ((zp (expt zgh
(/ zh
2))))
597 (* (sqrt (float (* 2 pi
)))
599 (* (/ zp
(exp zgh
)) zp
))))))
601 ;; No result. Overflow.
602 (merror (intl:gettext
"gamma: overflow in GAMMA-LANCZOS.")))
603 ((or (float-nan-p (realpart result
))
604 (float-inf-p (realpart result
)))
605 ;; Result, but beyond extreme values. Overflow.
606 (merror (intl:gettext
"gamma: overflow in GAMMA-LANCZOS.")))
609 (defun gammafloat (a)
612 ;; Reflection formula to make it positive: gamma(x) =
613 ;; %pi/sin(%pi*x)/x/gamma(-x)
615 (* a
(sin (* (float pi
) a
)))
617 ((<= a
(sqrt flonum-epsilon
))
618 ;; Use gamma(x) = gamma(1+x)/x when x is very small
619 (/ (gammafloat (+ 1 a
))
625 (let ((c (* (sqrt (* 2 (float pi
)))
626 (exp (slatec::d9lgmc a
)))))
627 (let ((v (expt a
(- (* .5e0 a
) 0.25e0
))))
631 (if (or (float-nan-p result
)
632 (float-inf-p result
))
633 (merror (intl:gettext
"gamma: overflow in GAMMAFLOAT."))
636 (declare-top (special $numer $trigsign
))
638 (defmfun $zeromatrix
(m n
) ($ematrix m n
0 1 1))
640 (defmfun $ematrix
(m n var i j
)
642 (cond ((equal m
0) (return (ncons '($matrix simp
))))
643 ((and (equal n
0) (fixnump m
) (> m
0))
644 (return (cons '($matrix simp
) (list-of-mlists m
))))
645 ((not (and (fixnump m
) (fixnump n
)
646 (fixnump i
) (fixnump j
)
647 (> m
0) (> n
0) (> i
0) (> j
0)))
648 (merror (intl:gettext
"ematrix: arguments must be positive integers; found ~M")
649 (list '(mlist simp
) m n i j
) )))
650 loop
(cond ((= m i
) (setq row
(onen j n var
0)) (go on
))
651 ((zerop m
) (return (cons '($matrix
) (mxc ans
)))))
653 (do ((n n
(1- n
))) ((zerop n
)) (setq row
(cons 0 row
)))
654 on
(setq ans
(cons row ans
) m
(1- m
))
657 (defun list-of-mlists (n)
659 (l nil
(cons (ncons '(mlist simp
)) l
)))
662 (declare-top (special $ratmx
))
664 (defmfun $coefmatrix
(eql varl
) (coefmatrix eql varl nil
))
666 (defmfun $augcoefmatrix
(eql varl
) (coefmatrix eql varl t
))
668 (defun coefmatrix (eql varl ind
)
669 (prog (ans row a b elem
)
670 (if (not ($listp eql
)) (improper-arg-err eql
'$coefmatrix
))
671 (if (not ($listp varl
)) (improper-arg-err varl
'$coefmatrix
))
672 (dolist (v (cdr varl
))
673 (if (and (not (atom v
)) (member (caar v
) '(mplus mtimes
) :test
#'eq
))
674 (merror (intl:gettext
"coefmatrix: variables cannot be '+' or '*' expressions; found ~M") v
)))
675 (setq eql
(nreverse (mapcar #'meqhk
(cdr eql
)))
676 varl
(reverse (cdr varl
)))
677 loop1
(if (null eql
) (return (cons '($matrix
) (mxc ans
))))
678 (setq a
(car eql
) eql
(cdr eql
) row nil
)
679 (if ind
(setq row
(cons (const1 a varl
) row
)))
681 loop2
(setq elem
(ratcoef a
(car b
)))
682 (setq row
(cons (if $ratmx elem
(ratdisrep elem
)) row
))
683 (if (setq b
(cdr b
)) (go loop2
))
684 (setq ans
(cons row ans
))
687 (defun const1 (e varl
)
688 (dolist (v varl
) (setq e
(maxima-substitute 0 v e
))) e
)
690 (defmfun $entermatrix
(rows columns
)
691 (prog (row column vector matrix sym symvector
)
692 (cond ((or (not (fixnump rows
))
693 (not (fixnump columns
)))
694 (merror (intl:gettext
"entermatrix: arguments must be integers; found ~M, ~M") rows columns
)))
696 (unless (= rows columns
) (setq sym nil
) (go oloop
))
697 quest
(format t
"~%Is the matrix 1. Diagonal 2. Symmetric 3. Antisymmetric 4. General~%")
698 (setq sym
(retrieve "Answer 1, 2, 3 or 4 : " nil
))
699 (unless (member sym
'(1 2 3 4)) (go quest
))
700 oloop
(cond ((> (incf row
) rows
)
701 (format t
"~%Matrix entered.~%")
702 (return (cons '($matrix
) (mxc matrix
)))))
705 (let ((prompt (format nil
"Row ~a Column ~a: " row column
)))
708 (ncons (onen row columns
709 (meval (retrieve prompt nil
)) 0)))))
712 (setq column
(1- row
))
713 (cond ((equal row
1) (go iloop
)))
715 (cons (nthcdr column vector
) symvector
)
716 vector
(nreverse (mapcar 'car symvector
))
717 symvector
(mapcar 'cdr symvector
))
721 (cond ((equal row
1) (setq vector
(ncons 0)) (go iloop
)))
723 (cons (mapcar #'neg
(nthcdr (1- column
) vector
))
725 vector
(nreconc (mapcar 'car symvector
) (ncons 0))
726 symvector
(mapcar 'cdr symvector
))
728 (setq column
0 vector nil
)
729 iloop
(cond ((> (incf column
) columns
)
730 (setq matrix
(nconc matrix
(ncons vector
)))
732 (let ((prompt (format nil
"Row ~a Column ~a: " row column
)))
733 (setq vector
(nconc vector
(ncons (meval (retrieve prompt nil
))))))
736 (declare-top (special sn
* sd
* rsn
*))
740 ((mtimesp e
) (muln (mapcar '$xthru
(cdr e
)) nil
))
741 ((mplusp e
) (simplify (comdenom (mapcar '$xthru
(cdr e
)) t
)))
742 ((mexptp e
) (power ($xthru
(cadr e
)) (caddr e
)))
743 ((mbagp e
) (cons (car e
) (mapcar '$xthru
(cdr e
))))
746 (defun comdenom (l ind
)
749 (setq n
(m*l sn
*) sn
* nil
)
750 (setq d
(m*l sd
*) sd
* nil
)
751 loop
(setq l
(cdr l
))
753 (return (cond (ind (div* (cond (rsn* ($ratsimp n
))
758 (setq d
(comdenom1 n d
(m*l sn
*) (m*l sd
*)))
763 (defun prodnumden (e)
764 (cond ((atom e
) (prodnd (list e
)))
765 ((eq (caar e
) 'mtimes
) (prodnd (cdr e
)))
766 (t (prodnd (list e
)))))
771 (setq sn
* nil sd
* nil
)
772 loop
(cond ((null l
) (return nil
)))
774 (cond ((atom e
) (setq sn
* (cons e sn
*)))
776 (cond ((not (equal 1 (cadr e
)))
777 (setq sn
* (cons (cadr e
) sn
*))))
778 (setq sd
* (cons (caddr e
) sd
*)))
779 ((and (eq (caar e
) 'mexpt
)
781 (setq sd
* (cons (power (cadr e
)
782 (timesk -
1 (caddr e
)))
784 (t (setq sn
* (cons e sn
*))))
788 (defun comdenom1 (a b c d
)
790 (prodnumden (div* b d
))
791 (setq b1
(m*l sn
*) sn
* nil
)
792 (setq c1
(m*l sd
*) sd
* nil
)
794 (list (add2 (m* a c1
) (m* c b1
))
797 (declare-top (special $globalsolve $backsubst $dispflag
798 $linsolve_params $%rnum_list ax
*linelabel
* $linechar
799 $linenum
*mosesflag
))
801 (defun xrutout (ax n m varl ind
)
802 (let (($linsolve_params
(and $backsubst $linsolve_params
)))
803 (prog (ix imin ans zz m-1 sol tim chk zzz
)
804 (setq ax
(get-array-pointer ax
) tim
0)
805 (if $linsolve_params
(setq $%rnum_list
(list '(mlist))))
806 (setq imin
(min (setq m-1
(1- m
)) n
))
807 (setq ix
(max imin
(length varl
)))
808 loop
(if (zerop ix
) (if ind
(go out
) (return (cons '(mlist) zz
))))
809 (when (or (> ix imin
) (equal (car (aref ax ix ix
)) 0))
811 (rform (if $linsolve_params
(make-param) (ith varl ix
))))
812 (if $linsolve_params
(go saval
) (go next
)))
813 (setq ans
(aref ax ix m
))
814 (setf (aref ax ix m
) nil
)
815 (do ((j (1+ ix
) (1+ j
)))
817 (setq ans
(ratdif ans
(rattimes (aref ax ix j
) (aref ax
0 j
) t
)))
818 (setf (aref ax ix j
) nil
))
819 (setf (aref ax
0 ix
) (ratquotient ans
(aref ax ix ix
)))
820 (setf (aref ax ix ix
) nil
)
822 saval
(push (cond (*mosesflag
(aref ax
0 ix
))
823 (t (list (if $globalsolve
'(msetq) '(mequal))
825 (simplify (rdis (aref ax
0 ix
))))))
828 (setf (aref ax
0 ix
) (rform (ith varl ix
))))
829 (and $globalsolve
(meval (car zz
)))
833 (cond ($dispflag
(mtell (intl:gettext
"Solution:~%"))))
834 (setq sol
(list '(mlist)) chk
(checklabel $linechar
))
835 (do ((ll zz
(cdr ll
)))
838 (setq zzz
(list '(mlabel)
843 (let (($nolabels nil
))
844 (makelabel $linechar
))
846 (setf (symbol-value *linelabel
*) zzz
)))
847 (nconc sol
(ncons *linelabel
*))
849 (setq tim
(get-internal-run-time))
850 (mtell-open "~%~M" zzz
)
853 (putprop *linelabel
* t
'nodisp
))))