1 ;;; -*- Mode: Lisp; Package: Maxima; Syntax: Common-Lisp; Base: 10 -*- ;;;;
2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3 ;;; The data in this file contains enhancements. ;;;;;
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 sign
))
19 (defmvar $gammalim
10000
20 "Controls simplification of gamma for rational number arguments.")
22 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
24 ;;; Implementation of the plog function
26 (def-simplifier plog
(x)
27 (prog (varlist dd y z
)
29 (merror (intl:gettext
"plog: plog(0) is undefined.")))
31 ;; This is used in DEFINT. 1/19/81. -JIM
33 ;; In particular, this is the call to KEYHOLE in ZTORAT
34 ;; for an integral like integrate(1/(x^2+x+1),x,0,inf).
35 ;; Without this, the integral is computed incorrectly.
37 ;; FIXME: We should be doing this.
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* (ftake '%log
48 (power ($expand
(add* (power (car dd
) 2)
55 ((and (equal ($imagpart x
) 0)
56 (setq y
($asksign x
)))
58 (return (ftake '%log x
)))
59 ((and plogabs
(eq y
'$neg
))
60 (return (ftake '%log
(list '(mtimes) -
1 x
))))
63 (ftake '%log
(mul -
1 x
)))))
64 (t (merror (intl:gettext
"plog: plog(0) is undefined.")))))
65 ((and (equal ($imagpart
(setq z
(div* x
'$%i
))) 0)
66 (setq y
($asksign z
)))
69 (merror (intl:gettext
"plog: plog(0) is undefined.")))
70 (t (cond ((eq y
'$pos
)
74 (return (add2* (ftake '%log
(mul y z
))
75 (mul y
1//2 '$%i
'$%pi
)))))))
79 (let (($numer $numer
))
81 (setq i
(simplifya i nil
) r
(simplifya r nil
))
83 (if (floatp i
) (setq $numer t
))
85 (cond ((equal i
'$pos
) (return (simplify half%pi
)))
87 (return (mul2 -
1 (simplify half%pi
))))
88 (t (merror (intl:gettext
"plog: encountered atan(0/0).")))))
90 (cond ((floatp r
) (setq $numer t
)))
92 (cond ((equal r
'$pos
) (return 0))
93 ((equal r
'$neg
) (return (simplify '$%pi
)))
94 (t (merror (intl:gettext
"plog: encountered atan(0/0).")))))
95 ((and (among '%cos r
) (among '%sin i
))
96 ;; genvar and varlist, used by the rational function system,
97 ;; are bound in order to prevent the symbol 'xz from leaking
98 ;; out of this function.
99 (let ((var 'xz
) genvar varlist
)
101 (cond ((and (eq (caar nn
*) '%cos
) (eq (caar dn
*) '%sin
))
102 (return (cadr nn
*)))))))
103 (setq a
($sign r
) b
($sign i
))
104 (cond ((eq a
'$pos
) (setq a
1))
105 ((eq a
'$neg
) (setq a -
1))
106 ((eq a
'$zero
) (setq a
0)))
107 (cond ((eq b
'$pos
) (setq b
1))
108 ((eq b
'$neg
) (setq b -
1))
109 ((eq a
'$zero
) (setq b
0)))
111 (return (if (equal a
1) 0 (simplify '$%pi
))))
113 (return (cond ((equal b
1) (simplify half%pi
))
114 (t (mul2 '((rat simp
) -
1 2)
115 (simplify '$%pi
)))))))
116 (setq r
(simptimes (list '(mtimes) a b
(div* i r
)) 1 nil
))
117 (return (cond ((onep1 r
)
118 (archk a b
(list '(mtimes) '((rat) 1 4) '$%pi
)))
119 ((alike1 r
'((mexpt) 3 ((rat) 1 2)))
120 (archk a b
(list '(mtimes) '((rat) 1 3) '$%pi
)))
121 ((alike1 r
'((mexpt) 3 ((rat) -
1 2)))
122 (archk a b
(list '(mtimes) '((rat) 1 6) '$%pi
))))))))
124 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
126 ;;; Implementation of the Binomial coefficient
128 ;; Binomial has Mirror symmetry
129 (defprop %binomial t commutes-with-conjugate
)
131 (def-simplifier binomial
(u v
)
135 (if (and (integerp u
) (minusp u
) (< v u
))
138 ((or (zerop v
) (equal u v
)) 1)
139 ((and (integerp u
) (not (minusp u
)))
140 (bincomp u
(min v
(- u v
))))
142 ((integerp (setq y
(sub u v
)))
144 ;; u and v are equal, simplify not if argument can be negative
145 (if (member ($csign u
) '($pnz $pn $neg $nz
))
149 ((complex-float-numerical-eval-p u v
)
150 ;; Numercial evaluation for real and complex floating point numbers.
151 (let (($numer t
) ($float t
))
154 ($makegamma
(list '(%binomial
) ($float u
) ($float v
)))))))
155 ((complex-bigfloat-numerical-eval-p u v
)
156 ;; Numerical evaluation for real and complex bigfloat numbers.
159 ($makegamma
(list '(%binomial
) ($bfloat u
) ($bfloat v
))))))
165 ((mnump u
) (binocomp u v
))
166 (t (muln (bincomp1 u v
) nil
))))
168 (defun bincomp1 (u v
)
171 (list* u
(list '(mexpt) v -
1) (bincomp1 (add2 -
1 u
) (1- v
)))))
173 (defun binocomp (u v
)
176 loop
(if (zerop v
) (return ans
))
177 (setq ans
(timesk (timesk u ans
) (simplify (list '(rat) 1 v
))))
178 (setq u
(addk -
1 u
) v
(1- v
))
181 ;;; gradient of binomial
185 ((mtimes) -
1 ((%binomial
) a b
)
188 ((mqapply) (($psi array
) 0) ((mplus) 1 a
)))
189 ((mqapply) (($psi array
) 0)
190 ((mplus) 1 a
((mtimes) -
1 b
)))))
192 ((mtimes) -
1 ((%binomial
) a b
)
195 ((mqapply) (($psi array
) 0)
196 ((mplus) 1 a
((mtimes) -
1 b
))))
197 ((mqapply) (($psi array
) 0) ((mplus) 1 b
))))) grad
)
199 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
201 ;;; Implementation of the Beta function
203 (declare-top (special $gammalim
))
205 (defmvar $beta_args_sum_to_integer nil
)
207 ;;; The Beta function has mirror symmetry
208 (defprop %beta t commutes-with-conjugate
)
210 (def-simplifier beta
(u v
)
212 (cond ((or (zerop1 u
) (zerop1 v
))
216 (intl:gettext
"beta: expected nonzero arguments; found ~M, ~M")
219 ;; Check for numerical evaluation in float precision
220 ((complex-float-numerical-eval-p u v
)
222 ;; We use gamma(u)*gamma(v)/gamma(u+v) for numerical evaluation.
223 ;; Therefore u, v or u+v can not be a negative integer or a
224 ;; floating point representation of a negative integer.
225 ((and (or (not (numberp u
))
227 (not (= (nth-value 1 (truncate u
)) 0)))
228 (and (or (not (numberp v
))
230 (not (= (nth-value 1 (truncate v
)) 0)))
231 (and (or (not (numberp (add u v
)))
233 (not (= (nth-value 1 ($truncate
(add u v
))) 0))))))
236 (add ($log_gamma
($float u
))
237 ($log_gamma
($float v
))
238 (mul -
1 ($log_gamma
($float
(add u v
))))))))
239 ((or (and (numberp u
)
241 (= (nth-value 1 (truncate u
)) 0)
243 (eq ($sign
(sub ($truncate v
) v
)) '$zero
)
245 (eq ($sign
(add u v
)) '$pos
)))
246 (setq u
(truncate u
)))
249 (= (nth-value 1 (truncate u
)) 0)
251 (eq ($sign
(sub ($truncate u
) u
)) '$zero
)
253 (eq ($sign
(add u v
)) '$pos
)))
254 (setq v
(truncate v
))))
255 ;; One value is representing a negative integer, the other a
256 ;; positive integer and the sum is negative. Expand.
257 ($rectform
($float
(beta-expand-integer u v
))))
261 ;; Check for numerical evaluation in bigfloat precision
262 ((complex-bigfloat-numerical-eval-p u v
)
263 (let (($ratprint nil
))
265 ((and (or (not (mnump u
))
267 (not (eq ($sign
(sub ($truncate u
) u
)) '$zero
)))
270 (not (eq ($sign
(sub ($truncate v
) v
)) '$zero
)))
271 (or (not (mnump (add u v
)))
272 (eq ($sign
(add u v
)) '$pos
)
273 (not (eq ($sign
(sub ($truncate
(add u v
))
278 (add ($log_gamma
($bfloat u
))
279 ($log_gamma
($bfloat v
))
280 (mul -
1 ($log_gamma
($bfloat
(add u v
))))))))
283 (eq ($sign
(sub ($truncate u
) u
)) '$zero
)
285 (eq ($sign
(sub ($truncate v
) v
)) '$zero
)
287 (eq ($sign
(add u v
)) '$pos
)))
288 (setq u
($truncate u
)))
291 (eq ($sign
(sub ($truncate v
) v
)) '$zero
)
293 (eq ($sign
(sub ($truncate u
) u
)) '$zero
)
295 (eq ($sign
(add u v
)) '$pos
)))
296 (setq v
($truncate v
))))
297 ($rectform
($bfloat
(beta-expand-integer u v
))))
301 ((or (and (and (integerp u
)
304 (eq ($sign
(sub ($truncate v
) v
)) '$zero
)
306 (eq ($sign
(add u v
)) '$pos
))))
307 (and (and (integerp v
)
310 (eq ($sign
(sub ($truncate u
) u
)) '$zero
)
312 (eq ($sign
(add u v
)) '$pos
)))))
313 ;; Expand for a positive integer. But not if the other argument is
314 ;; a negative integer and the sum of the integers is not negative.
315 (beta-expand-integer u v
))
317 ;;; At this point both integers are negative. This code does not work for
318 ;;; negative integers. The factorial function is not defined.
319 ; ((and (integerp u) (integerp v))
320 ; (mul2* (div* (list '(mfactorial) (1- u))
321 ; (list '(mfactorial) (+ u v -1)))
322 ; (list '(mfactorial) (1- v))))
324 ((or (and (ratnump u
) (ratnump v
) (integerp (setq x
(addk u v
))))
325 (and $beta_args_sum_to_integer
326 (integerp (setq x
(expand1 (add2 u v
) 1 1)))))
327 (let ((w (if (symbolp v
) v u
)))
330 (add2 (1- x
) (neg w
))
332 `((%sin
) ((mtimes) ,w $%pi
)))))
334 ((and $beta_expand
(mplusp u
) (integerp (cadr u
)))
335 ;; Expand beta(a+n,b) where n is an integer.
337 (u (simplify (cons '(mplus) (cddr u
)))))
338 (beta-expand-add-integer n u v
)))
340 ((and $beta_expand
(mplusp v
) (integerp (cadr v
)))
341 ;; Expand beta(a,b+n) where n is an integer.
343 (v (simplify (cons '(mplus) (cddr v
)))))
344 (beta-expand-add-integer n v u
)))
348 (defun beta-expand-integer (u v
)
349 ;; One of the arguments is a positive integer. Do an expansion.
350 ;; BUT for a negative integer as second argument the expansion is only
351 ;; possible when the sum of the integers is negative too.
352 ;; This routine expects that the calling routine has checked this.
359 (sub (if (and (integerp u
) (plusp u
)) u v
) 1))))
362 (defun beta-expand-add-integer (n u v
)
364 (mul (simplify (list '($pochhammer
) u n
))
365 (power (simplify (list '($pochhammer
) (add u v
) n
)) -
1)
367 (mul (simplify (list '($pochhammer
) (add u v n
) (- n
)))
368 (power (simplify (list '($pochhammer
) (add u n
) (- n
))) -
1)
369 (ftake* '%beta u v
))))
371 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
373 ;;; Implementation of the Gamma function
375 (def-simplifier gamma
(j)
376 (cond ((and (floatp j
)
379 (zerop (nth-value 1 (truncate j
))))))
380 (merror (intl:gettext
"gamma: gamma(~:M) is undefined.") j
))
381 ((float-numerical-eval-p j
) (gammafloat ($float j
)))
384 (and (eq ($sign j
) '$neg
)
385 (zerop1 (sub j
($truncate j
))))))
386 (merror (intl:gettext
"gamma: gamma(~:M) is undefined.") j
))
387 ((bigfloat-numerical-eval-p j
)
388 ;; Adding 4 digits in the call to bffac. For $fpprec up to about 256
389 ;; and an argument up to about 500.0 the accuracy of the result is
390 ;; better than 10^(-$fpprec).
391 (let ((z (bigfloat:to
($bfloat j
))))
393 ((bigfloat:<= (bigfloat:abs z
) (bigfloat:sqrt
(bigfloat:epsilon z
)))
394 ;; For small z, use gamma(z) = gamma(z+1)/z = z!/z
395 (div (mfuncall '$bffac
400 (let ((result (mfuncall '$bffac
(m+ ($bfloat j
) -
1) (+ $fpprec
4))))
401 ;; bigfloatp will round the result to the correct fpprec
402 (bigfloatp result
))))))
403 ((complex-float-numerical-eval-p j
)
404 (complexify (gamma-lanczos (complex ($float
($realpart j
))
405 ($float
($imagpart j
))))))
406 ((complex-bigfloat-numerical-eval-p j
)
407 (let ((z (bigfloat:to
($bfloat j
))))
409 ((bigfloat:<= (bigfloat:abs z
)
410 (bigfloat:sqrt
(bigfloat:epsilon z
)))
411 ;; For small z, use gamma(z) = gamma(z+1)/z = z!/z
412 (to (bigfloat:/ (bigfloat:to
(mfuncall '$cbffac
417 ;; Adding 4 digits in the call to cbffac. See comment above.
420 (add -
1 ($bfloat
($realpart j
))
421 (mul '$%i
($bfloat
($imagpart j
))))
423 (add (bigfloatp ($realpart result
))
424 (mul '$%i
(bigfloatp ($imagpart result
)))))))))
425 ((taylorize (mop form
) (cadr form
)))
426 ((eq j
'$inf
) '$inf
) ; Simplify to $inf to be more consistent.
430 ;; Expand gamma(z+n) for n an integer.
432 (z (simplify (cons '(mplus) (cddr j
)))))
435 (mul (simplify (list '($pochhammer
) z n
))
436 (simplify (list '(%gamma
) z
))))
439 (div (mul (power -
1 n
) (simplify (list '(%gamma
) z
)))
440 ;; We factor to get the order (z-1)*(z-2)*...
441 ;; and not (1-z)*(2-z)*...
443 (simplify (list '($pochhammer
) (sub 1 z
) n
))))))))
446 (cond ((<= j $factlim
)
447 ;; Positive integer less than $factlim. Evaluate.
448 (simplify (list '(mfactorial) (1- j
))))
449 ;; Positive integer greater $factlim. Noun form.
451 ;; Negative integer. Throw a Maxima error.
452 (errorsw (throw 'errorsw t
))
453 (t (merror (intl:gettext
"gamma: gamma(~:M) is undefined.") j
))))
454 ((alike1 j
'((rat) 1 2))
455 (list '(mexpt simp
) '$%pi j
))
457 (ratgreaterp $gammalim
(simplify (list '(mabs) j
)))
458 (or (ratgreaterp j
1) (ratgreaterp 0 j
)))
459 ;; Expand for rational numbers less than $gammalim.
463 ;; A sign function for gamma(x); when x > 0 return pos; when x < 0 or x > 0, return pn;
464 ;;; otherwise, return pnz (that is, nothing known).
465 (defun gamma-sign (x)
466 (let ((sgn ($csign
(second x
)))) ;; careful! x = ((%gamma) XXX)
468 (cond ((eql sgn
'$pos
) '$pos
)
469 ((or (eql sgn
'$neg
) (eql sgn
'$pn
)) '$pn
)
472 (putprop '%gamma
'gamma-sign
'sign-function
)
474 (defun gamma (y) ;;; numerical evaluation for 0 < y < 1
476 (setq coefs
(list 0.035868343 -
0.193527817 0.48219939
477 -
0.75670407 0.91820685 -
0.89705693
478 0.98820588 -
0.57719165))
479 (unless (atom y
) (setq y
(fpcofrat y
)))
480 (setq sum
(car coefs
) coefs
(cdr coefs
))
481 loop
(setq sum
(+ (* sum y
) (car coefs
)))
482 (when (setq coefs
(cdr coefs
)) (go loop
))
483 (return (+ (/ y
) sum
))))
485 (defun gammared (a) ;A is assumed to
486 (prog (m q n
) ;be '((RAT) M N)
487 (cond ((floatp a
) (return (gammafloat a
))))
488 (setq m
(cadr a
) ;Numerator
489 n
(caddr a
) ;denominator
490 q
(abs (truncate m n
))) ;integer part
492 (setq q
(1+ q
) m
(+ m
(* n q
)))
494 (simptimes (list '(mtimes)
496 (ftake* '%gamma
(list '(rat) m n
))
497 (list '(mexpt) (gammac m n q
) -
1))
500 (return (m* (gammac m n q
)
501 (ftake* '%gamma
(list '(rat) (rem m n
) n
))
504 (defun gammac (m n q
)
507 (setq q
(1- q
) m
(- m n
) ans
(* m ans
))))
510 ;; This implementation is based on Lanczos convergent formula for the
511 ;; gamma function for Re(z) > 0. We can use the reflection formula
513 ;; -z*Gamma(z)*Gamma(-z) = pi/sin(pi*z)
515 ;; to handle the case of Re(z) <= 0.
517 ;; See http://my.fit.edu/~gabdo/gamma.m for some matlab code to
518 ;; compute this and http://my.fit.edu/~gabdo/gamma.txt for a nice
519 ;; discussion of Lanczos method and an improvement of Lanczos method.
522 ;; The document says this should give about 15 digits of accuracy for
523 ;; double-precision IEEE floats. The document also indicates how to
524 ;; compute a new set of coefficients if you need more range or
527 (defun gamma-lanczos (z)
528 (declare (type (complex flonum
) z
)
529 (optimize (safety 3)))
530 (let ((c (make-array 15 :element-type
'flonum
532 '(0.99999999999999709182
533 57.156235665862923517
534 -
59.597960355475491248
535 14.136097974741747174
536 -
0.49191381609762019978
537 .33994649984811888699e-4
538 .46523628927048575665e-4
539 -
.98374475304879564677e-4
540 .15808870322491248884e-3
541 -
.21026444172410488319e-3
542 .21743961811521264320e-3
543 -
.16431810653676389022e-3
544 .84418223983852743293e-4
545 -
.26190838401581408670e-4
546 .36899182659531622704e-5))))
547 (declare (type (simple-array flonum
(15)) c
))
549 ((minusp (realpart z
))
550 ;; Use the reflection formula
551 ;; -z*Gamma(z)*Gamma(-z) = pi/sin(pi*z)
553 ;; Gamma(z) = pi/z/sin(pi*z)/Gamma(-z)
555 ;; If z is a negative integer, Gamma(z) is infinity. Should
556 ;; we test for this? Throw an error?
557 ;; The test must be done by the calling routine.
559 (* (- z
) (sin (* (float pi
) z
))
560 (gamma-lanczos (- z
)))))
561 ((<= (abs z
) (sqrt +flonum-epsilon
+))
562 ;; For |z| small, use Gamma(z) = Gamma(z+1)/z
563 (/ (gamma-lanczos (+ 1 z
))
571 (pp (1- (length c
)) (1- pp
)))
574 (incf sum
(/ (aref c pp
) (+ z pp
))))))
576 ;; We check for an overflow. The last positive value in
577 ;; double-float precicsion for which Maxima can calculate
578 ;; gamma is ~171.6243 (CLISP 2.46 and GCL 2.6.8)
580 (let ((zp (expt zgh
(/ zh
2))))
581 (* (sqrt (float (* 2 pi
)))
583 (* (/ zp
(exp zgh
)) zp
))))))
585 ;; No result. Overflow.
586 (merror (intl:gettext
"gamma: overflow in GAMMA-LANCZOS.")))
587 ((or (float-nan-p (realpart result
))
588 (float-inf-p (realpart result
)))
589 ;; Result, but beyond extreme values. Overflow.
590 (merror (intl:gettext
"gamma: overflow in GAMMA-LANCZOS.")))
593 (defun gammafloat (a)
596 ;; Reflection formula to make it positive: gamma(x) =
597 ;; %pi/sin(%pi*x)/x/gamma(-x)
599 (* a
(sin (* (float pi
) a
)))
601 ((<= a
(sqrt +flonum-epsilon
+))
602 ;; Use gamma(x) = gamma(1+x)/x when x is very small
603 (/ (gammafloat (+ 1 a
))
609 (let ((c (* (sqrt (* 2 (float pi
)))
610 (exp (slatec::d9lgmc a
)))))
611 (let ((v (expt a
(- (* .5e0 a
) 0.25e0
))))
615 (if (or (float-nan-p result
)
616 (float-inf-p result
))
617 (merror (intl:gettext
"gamma: overflow in GAMMAFLOAT."))
620 (defmfun $zeromatrix
(m n
) ($ematrix m n
0 1 1))
622 (defmfun $ematrix
(m n var i j
)
624 (cond ((equal m
0) (return (ncons '($matrix simp
))))
625 ((and (equal n
0) (fixnump m
) (> m
0))
626 (return (cons '($matrix simp
) (list-of-mlists m
))))
627 ((not (and (fixnump m
) (fixnump n
)
628 (fixnump i
) (fixnump j
)
629 (> m
0) (> n
0) (> i
0) (> j
0)))
630 (merror (intl:gettext
"ematrix: arguments must be positive integers; found ~M")
631 (list '(mlist simp
) m n i j
) )))
632 loop
(cond ((= m i
) (setq row
(onen j n var
0)) (go on
))
633 ((zerop m
) (return (cons '($matrix
) (mxc ans
)))))
635 (do ((n n
(1- n
))) ((zerop n
)) (setq row
(cons 0 row
)))
636 on
(setq ans
(cons row ans
) m
(1- m
))
639 (defun list-of-mlists (n)
641 (l nil
(cons (ncons '(mlist simp
)) l
)))
644 (defmfun $coefmatrix
(eql varl
) (coefmatrix eql varl nil
))
646 (defmfun $augcoefmatrix
(eql varl
) (coefmatrix eql varl t
))
648 (defun coefmatrix (eql varl ind
)
649 (prog (ans row a b elem
)
650 (if (not ($listp eql
)) (improper-arg-err eql
'$coefmatrix
))
651 (if (not ($listp varl
)) (improper-arg-err varl
'$coefmatrix
))
652 (dolist (v (cdr varl
))
653 (if (and (not (atom v
)) (member (caar v
) '(mplus mtimes
) :test
#'eq
))
654 (merror (intl:gettext
"coefmatrix: variables cannot be '+' or '*' expressions; found ~M") v
)))
655 (setq eql
(nreverse (mapcar #'meqhk
(cdr eql
)))
656 varl
(reverse (cdr varl
)))
657 loop1
(if (null eql
) (return (cons '($matrix
) (mxc ans
))))
658 (setq a
(car eql
) eql
(cdr eql
) row nil
)
659 (if ind
(setq row
(cons (const1 a varl
) row
)))
661 loop2
(setq elem
(ratcoef a
(car b
)))
662 (setq row
(cons (if $ratmx elem
(ratdisrep elem
)) row
))
663 (if (setq b
(cdr b
)) (go loop2
))
664 (setq ans
(cons row ans
))
667 (defun const1 (e varl
)
668 (dolist (v varl
) (setq e
(maxima-substitute 0 v e
))) e
)
670 (defmfun $entermatrix
(rows columns
)
671 (prog (row column vector matrix sym symvector
)
672 (cond ((or (not (fixnump rows
))
673 (not (fixnump columns
)))
674 (merror (intl:gettext
"entermatrix: arguments must be integers; found ~M, ~M") rows columns
)))
676 (unless (= rows columns
) (setq sym nil
) (go oloop
))
677 quest
(format t
"~%Is the matrix 1. Diagonal 2. Symmetric 3. Antisymmetric 4. General~%")
678 (setq sym
(retrieve "Answer 1, 2, 3 or 4 : " nil
))
679 (unless (member sym
'(1 2 3 4)) (go quest
))
680 oloop
(cond ((> (incf row
) rows
)
681 (format t
"~%Matrix entered.~%")
682 (return (cons '($matrix
) (mxc matrix
)))))
685 (let ((prompt (format nil
"Row ~a Column ~a: " row column
)))
688 (ncons (onen row columns
689 (meval (retrieve prompt nil
)) 0)))))
692 (setq column
(1- row
))
693 (cond ((equal row
1) (go iloop
)))
695 (cons (nthcdr column vector
) symvector
)
696 vector
(nreverse (mapcar 'car symvector
))
697 symvector
(mapcar 'cdr symvector
))
701 (cond ((equal row
1) (setq vector
(ncons 0)) (go iloop
)))
703 (cons (mapcar #'neg
(nthcdr (1- column
) vector
))
705 vector
(nreconc (mapcar 'car symvector
) (ncons 0))
706 symvector
(mapcar 'cdr symvector
))
708 (setq column
0 vector nil
)
709 iloop
(cond ((> (incf column
) columns
)
710 (setq matrix
(nconc matrix
(ncons vector
)))
712 (let ((prompt (format nil
"Row ~a Column ~a: " row column
)))
713 (setq vector
(nconc vector
(ncons (meval (retrieve prompt nil
))))))
716 (declare-top (special sn
* sd
* rsn
*))
720 ((mtimesp e
) (muln (mapcar '$xthru
(cdr e
)) nil
))
721 ((mplusp e
) (simplify (comdenom (mapcar '$xthru
(cdr e
)) t
)))
722 ((mexptp e
) (power ($xthru
(cadr e
)) (caddr e
)))
723 ((mbagp e
) (cons (car e
) (mapcar '$xthru
(cdr e
))))
726 (defun comdenom (l ind
)
729 (setq n
(m*l sn
*) sn
* nil
)
730 (setq d
(m*l sd
*) sd
* nil
)
731 loop
(setq l
(cdr l
))
733 (return (cond (ind (div* (cond (rsn* ($ratsimp n
))
738 (setq d
(comdenom1 n d
(m*l sn
*) (m*l sd
*)))
743 (defun prodnumden (e)
744 (cond ((atom e
) (prodnd (list e
)))
745 ((eq (caar e
) 'mtimes
) (prodnd (cdr e
)))
746 (t (prodnd (list e
)))))
751 (setq sn
* nil sd
* nil
)
752 loop
(cond ((null l
) (return nil
)))
754 (cond ((atom e
) (setq sn
* (cons e sn
*)))
756 (cond ((not (equal 1 (cadr e
)))
757 (setq sn
* (cons (cadr e
) sn
*))))
758 (setq sd
* (cons (caddr e
) sd
*)))
759 ((and (eq (caar e
) 'mexpt
)
761 (setq sd
* (cons (power (cadr e
)
762 (timesk -
1 (caddr e
)))
764 (t (setq sn
* (cons e sn
*))))
768 (defun comdenom1 (a b c d
)
770 (prodnumden (div* b d
))
771 (setq b1
(m*l sn
*) sn
* nil
)
772 (setq c1
(m*l sd
*) sd
* nil
)
774 (list (add2 (m* a c1
) (m* c b1
))
777 (declare-top (special ax
780 (defun xrutout (ax n m varl ind
)
781 (let (($linsolve_params
(and $backsubst $linsolve_params
)))
782 (prog (ix imin ans zz m-1 sol tim chk zzz
)
783 (setq ax
(get-array-pointer ax
) tim
0)
784 (if $linsolve_params
(setq $%rnum_list
(list '(mlist))))
785 (setq imin
(min (setq m-1
(1- m
)) n
))
786 (setq ix
(max imin
(length varl
)))
787 loop
(if (zerop ix
) (if ind
(go out
) (return (cons '(mlist) zz
))))
788 (when (or (> ix imin
) (equal (car (aref ax ix ix
)) 0))
790 (rform (if $linsolve_params
(make-param) (ith varl ix
))))
791 (if $linsolve_params
(go saval
) (go next
)))
792 (setq ans
(aref ax ix m
))
793 (setf (aref ax ix m
) nil
)
794 (do ((j (1+ ix
) (1+ j
)))
796 (setq ans
(ratdif ans
(rattimes (aref ax ix j
) (aref ax
0 j
) t
)))
797 (setf (aref ax ix j
) nil
))
798 (setf (aref ax
0 ix
) (ratquotient ans
(aref ax ix ix
)))
799 (setf (aref ax ix ix
) nil
)
801 saval
(push (cond (*mosesflag
(aref ax
0 ix
))
802 (t (list (if $globalsolve
'(msetq) '(mequal))
804 (simplify (rdis (aref ax
0 ix
))))))
807 (setf (aref ax
0 ix
) (rform (ith varl ix
))))
808 (and $globalsolve
(meval (car zz
)))
812 (cond ($dispflag
(mtell (intl:gettext
"Solution:~%"))))
813 (setq sol
(list '(mlist)) chk
(checklabel $linechar
))
814 (do ((ll zz
(cdr ll
)))
817 (setq zzz
(list '(mlabel)
822 (let (($nolabels nil
))
823 (makelabel $linechar
))
825 (setf (symbol-value *linelabel
*) zzz
)))
826 (nconc sol
(ncons *linelabel
*))
828 (setq tim
(get-internal-run-time))
829 (mtell-open "~%~M" zzz
)
832 (putprop *linelabel
* t
'nodisp
))))