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
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
))
95 (cond ((and (eq (caar nn
*) '%cos
) (eq (caar dn
*) '%sin
))
96 (return (cadr nn
*))))))
97 (setq a
($sign r
) b
($sign i
))
98 (cond ((eq a
'$pos
) (setq a
1))
99 ((eq a
'$neg
) (setq a -
1))
100 ((eq a
'$zero
) (setq a
0)))
101 (cond ((eq b
'$pos
) (setq b
1))
102 ((eq b
'$neg
) (setq b -
1))
103 ((eq a
'$zero
) (setq b
0)))
105 (return (if (equal a
1) 0 (simplify '$%pi
))))
107 (return (cond ((equal b
1) (simplify half%pi
))
108 (t (mul2 '((rat simp
) -
1 2)
109 (simplify '$%pi
)))))))
110 (setq r
(simptimes (list '(mtimes) a b
(div* i r
)) 1 nil
))
111 (return (cond ((onep1 r
)
112 (archk a b
(list '(mtimes) '((rat) 1 4) '$%pi
)))
113 ((alike1 r
'((mexpt) 3 ((rat) 1 2)))
114 (archk a b
(list '(mtimes) '((rat) 1 3) '$%pi
)))
115 ((alike1 r
'((mexpt) 3 ((rat) -
1 2)))
116 (archk a b
(list '(mtimes) '((rat) 1 6) '$%pi
))))))))
118 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
120 ;;; Implementation of the Binomial coefficient
122 ;; Verb function for the Binomial coefficient
123 (defmfun $binomial
(x y
)
124 (simplify (list '(%binomial
) x y
)))
126 ;; Binomial has Mirror symmetry
127 (defprop %binomial t commutes-with-conjugate
)
129 (defun simpbinocoef (x vestigial z
)
130 (declare (ignore vestigial
))
132 (let ((u (simpcheck (cadr x
) z
))
133 (v (simpcheck (caddr x
) z
))
137 (if (and (integerp u
) (minusp u
) (< v u
))
140 ((or (zerop v
) (equal u v
)) 1)
141 ((and (integerp u
) (not (minusp u
)))
142 (bincomp u
(min v
(- u v
))))
144 ((integerp (setq y
(sub u v
)))
146 ;; u and v are equal, simplify not if argument can be negative
147 (if (member ($csign u
) '($pnz $pn $neg $nz
))
148 (eqtest (list '(%binomial
) u v
) x
)
151 ((complex-float-numerical-eval-p u v
)
152 ;; Numercial evaluation for real and complex floating point numbers.
153 (let (($numer t
) ($float t
))
156 ($makegamma
(list '(%binomial
) ($float u
) ($float v
)))))))
157 ((complex-bigfloat-numerical-eval-p u v
)
158 ;; Numerical evaluation for real and complex bigfloat numbers.
161 ($makegamma
(list '(%binomial
) ($bfloat u
) ($bfloat v
))))))
162 (t (eqtest (list '(%binomial
) u v
) x
)))))
167 ((mnump u
) (binocomp u v
))
168 (t (muln (bincomp1 u v
) nil
))))
170 (defun bincomp1 (u v
)
173 (list* u
(list '(mexpt) v -
1) (bincomp1 (add2 -
1 u
) (1- v
)))))
175 (defun binocomp (u v
)
178 loop
(if (zerop v
) (return ans
))
179 (setq ans
(timesk (timesk u ans
) (simplify (list '(rat) 1 v
))))
180 (setq u
(addk -
1 u
) v
(1- v
))
183 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
185 ;;; Implementation of the Beta function
187 (declare-top (special $numer $gammalim
))
189 (defmvar $beta_args_sum_to_integer nil
)
191 ;;; The Beta function has mirror symmetry
192 (defprop $beta t commutes-with-conjugate
)
194 (defun simpbeta (x vestigial z
&aux check
)
195 (declare (ignore vestigial
))
198 (let ((u (simpcheck (cadr x
) z
)) (v (simpcheck (caddr x
) z
)))
199 (cond ((or (zerop1 u
) (zerop1 v
))
203 (intl:gettext
"beta: expected nonzero arguments; found ~M, ~M")
206 ;; Check for numerical evaluation in float precision
207 ((complex-float-numerical-eval-p u v
)
209 ;; We use gamma(u)*gamma(v)/gamma(u+v) for numerical evaluation.
210 ;; Therefore u, v or u+v can not be a negative integer or a
211 ;; floating point representation of a negative integer.
212 ((and (or (not (numberp u
))
214 (not (= (nth-value 1 (truncate u
)) 0)))
215 (and (or (not (numberp v
))
217 (not (= (nth-value 1 (truncate v
)) 0)))
218 (and (or (not (numberp (add u v
)))
220 (not (= (nth-value 1 ($truncate
(add u v
))) 0))))))
223 (add ($log_gamma
($float u
))
224 ($log_gamma
($float v
))
225 (mul -
1 ($log_gamma
($float
(add u v
))))))))
226 ((or (and (numberp u
)
228 (= (nth-value 1 (truncate u
)) 0)
230 (eq ($sign
(sub ($truncate v
) v
)) '$zero
)
232 (eq ($sign
(add u v
)) '$pos
)))
233 (setq u
(truncate u
)))
236 (= (nth-value 1 (truncate u
)) 0)
238 (eq ($sign
(sub ($truncate u
) u
)) '$zero
)
240 (eq ($sign
(add u v
)) '$pos
)))
241 (setq v
(truncate v
))))
242 ;; One value is representing a negative integer, the other a
243 ;; positive integer and the sum is negative. Expand.
244 ($rectform
($float
(beta-expand-integer u v
))))
246 (eqtest (list '($beta
) u v
) check
))))
248 ;; Check for numerical evaluation in bigfloat precision
249 ((complex-bigfloat-numerical-eval-p u v
)
250 (let (($ratprint nil
))
252 ((and (or (not (mnump u
))
254 (not (eq ($sign
(sub ($truncate u
) u
)) '$zero
)))
257 (not (eq ($sign
(sub ($truncate v
) v
)) '$zero
)))
258 (or (not (mnump (add u v
)))
259 (eq ($sign
(add u v
)) '$pos
)
260 (not (eq ($sign
(sub ($truncate
(add u v
))
265 (add ($log_gamma
($bfloat u
))
266 ($log_gamma
($bfloat v
))
267 (mul -
1 ($log_gamma
($bfloat
(add u v
))))))))
270 (eq ($sign
(sub ($truncate u
) u
)) '$zero
)
272 (eq ($sign
(sub ($truncate v
) v
)) '$zero
)
274 (eq ($sign
(add u v
)) '$pos
)))
275 (setq u
($truncate u
)))
278 (eq ($sign
(sub ($truncate v
) v
)) '$zero
)
280 (eq ($sign
(sub ($truncate u
) u
)) '$zero
)
282 (eq ($sign
(add u v
)) '$pos
)))
283 (setq v
($truncate v
))))
284 ($rectform
($bfloat
(beta-expand-integer u v
))))
286 (eqtest (list '($beta
) u v
) check
)))))
288 ((or (and (and (integerp u
)
291 (eq ($sign
(sub ($truncate v
) v
)) '$zero
)
293 (eq ($sign
(add u v
)) '$pos
))))
294 (and (and (integerp v
)
297 (eq ($sign
(sub ($truncate u
) u
)) '$zero
)
299 (eq ($sign
(add u v
)) '$pos
)))))
300 ;; Expand for a positive integer. But not if the other argument is
301 ;; a negative integer and the sum of the integers is not negative.
302 (beta-expand-integer u v
))
304 ;;; At this point both integers are negative. This code does not work for
305 ;;; negative integers. The factorial function is not defined.
306 ; ((and (integerp u) (integerp v))
307 ; (mul2* (div* (list '(mfactorial) (1- u))
308 ; (list '(mfactorial) (+ u v -1)))
309 ; (list '(mfactorial) (1- v))))
311 ((or (and (ratnump u
) (ratnump v
) (integerp (setq x
(addk u v
))))
312 (and $beta_args_sum_to_integer
313 (integerp (setq x
(expand1 (add2 u v
) 1 1)))))
314 (let ((w (if (symbolp v
) v u
)))
317 (add2 (1- x
) (neg w
))
319 `((%sin
) ((mtimes) ,w $%pi
)))))
321 ((and $beta_expand
(mplusp u
) (integerp (cadr u
)))
322 ;; Expand beta(a+n,b) where n is an integer.
324 (u (simplify (cons '(mplus) (cddr u
)))))
325 (beta-expand-add-integer n u v
)))
327 ((and $beta_expand
(mplusp v
) (integerp (cadr v
)))
328 ;; Expand beta(a,b+n) where n is an integer.
330 (v (simplify (cons '(mplus) (cddr v
)))))
331 (beta-expand-add-integer n v u
)))
333 (t (eqtest (list '($beta
) u v
) check
)))))
335 (defun beta-expand-integer (u v
)
336 ;; One of the arguments is a positive integer. Do an expansion.
337 ;; BUT for a negative integer as second argument the expansion is only
338 ;; possible when the sum of the integers is negative too.
339 ;; This routine expects that the calling routine has checked this.
346 (sub (if (and (integerp u
) (plusp u
)) u v
) 1))))
349 (defun beta-expand-add-integer (n u v
)
351 (mul (simplify (list '($pochhammer
) u n
))
352 (power (simplify (list '($pochhammer
) (add u v
) n
)) -
1)
353 (simplify (list '($beta
) u v
)))
354 (mul (simplify (list '($pochhammer
) (add u v n
) (- n
)))
355 (power (simplify (list '($pochhammer
) (add u n
) (- n
))) -
1)
356 (simplify (list '($beta
) u v
)))))
358 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
360 ;;; Implementation of the Gamma function
362 (defun simpgamma (x vestigial z
)
363 (declare (ignore vestigial
))
365 (let ((j (simpcheck (cadr x
) z
)))
366 (cond ((and (floatp j
)
369 (zerop (nth-value 1 (truncate j
))))))
370 (merror (intl:gettext
"gamma: gamma(~:M) is undefined.") j
))
371 ((float-numerical-eval-p j
) (gammafloat ($float j
)))
374 (and (eq ($sign j
) '$neg
)
375 (zerop1 (sub j
($truncate j
))))))
376 (merror (intl:gettext
"gamma: gamma(~:M) is undefined.") j
))
377 ((bigfloat-numerical-eval-p j
)
378 ;; Adding 4 digits in the call to bffac. For $fpprec up to about 256
379 ;; and an argument up to about 500.0 the accuracy of the result is
380 ;; better than 10^(-$fpprec).
381 (let ((z (bigfloat:to
($bfloat j
))))
383 ((bigfloat:<= (bigfloat:abs z
) (bigfloat:sqrt
(bigfloat:epsilon z
)))
384 ;; For small z, use gamma(z) = gamma(z+1)/z = z!/z
385 (div (mfuncall '$bffac
390 (let ((result (mfuncall '$bffac
(m+ ($bfloat j
) -
1) (+ $fpprec
4))))
391 ;; bigfloatp will round the result to the correct fpprec
392 (bigfloatp result
))))))
393 ((complex-float-numerical-eval-p j
)
394 (complexify (gamma-lanczos (complex ($float
($realpart j
))
395 ($float
($imagpart j
))))))
396 ((complex-bigfloat-numerical-eval-p j
)
397 (let ((z (bigfloat:to
($bfloat j
))))
399 ((bigfloat:<= (bigfloat:abs z
)
400 (bigfloat:sqrt
(bigfloat:epsilon z
)))
401 ;; For small z, use gamma(z) = gamma(z+1)/z = z!/z
402 (to (bigfloat:/ (bigfloat:to
(mfuncall '$cbffac
407 ;; Adding 4 digits in the call to cbffac. See comment above.
410 (add -
1 ($bfloat
($realpart j
))
411 (mul '$%i
($bfloat
($imagpart j
))))
413 (add (bigfloatp ($realpart result
))
414 (mul '$%i
(bigfloatp ($imagpart result
)))))))))
415 ((taylorize (mop x
) (cadr x
)))
416 ((eq j
'$inf
) '$inf
) ; Simplify to $inf to be more consistent.
420 ;; Expand gamma(z+n) for n an integer.
422 (z (simplify (cons '(mplus) (cddr j
)))))
425 (mul (simplify (list '($pochhammer
) z n
))
426 (simplify (list '(%gamma
) z
))))
429 (div (mul (power -
1 n
) (simplify (list '(%gamma
) z
)))
430 ;; We factor to get the order (z-1)*(z-2)*...
431 ;; and not (1-z)*(2-z)*...
433 (simplify (list '($pochhammer
) (sub 1 z
) n
))))))))
436 (cond ((<= j $factlim
)
437 ;; Positive integer less than $factlim. Evaluate.
438 (simplify (list '(mfactorial) (1- j
))))
439 ;; Positive integer greater $factlim. Noun form.
440 (t (eqtest (list '(%gamma
) j
) x
))))
441 ;; Negative integer. Throw a Maxima error.
442 (errorsw (throw 'errorsw t
))
443 (t (merror (intl:gettext
"gamma: gamma(~:M) is undefined.") j
))))
444 ((alike1 j
'((rat) 1 2))
445 (list '(mexpt simp
) '$%pi j
))
447 (ratgreaterp $gammalim
(simplify (list '(mabs) j
)))
448 (or (ratgreaterp j
1) (ratgreaterp 0 j
)))
449 ;; Expand for rational numbers less than $gammalim.
451 (t (eqtest (list '(%gamma
) j
) x
)))))
453 (defun gamma (y) ;;; numerical evaluation for 0 < y < 1
455 (setq coefs
(list 0.035868343 -
0.193527817 0.48219939
456 -
0.75670407 0.91820685 -
0.89705693
457 0.98820588 -
0.57719165))
458 (unless (atom y
) (setq y
(fpcofrat y
)))
459 (setq sum
(car coefs
) coefs
(cdr coefs
))
460 loop
(setq sum
(+ (* sum y
) (car coefs
)))
461 (when (setq coefs
(cdr coefs
)) (go loop
))
462 (return (+ (/ y
) sum
))))
464 (defun gammared (a) ;A is assumed to
465 (prog (m q n
) ;be '((RAT) M N)
466 (cond ((floatp a
) (return (gammafloat a
))))
467 (setq m
(cadr a
) ;Numerator
468 n
(caddr a
) ;denominator
469 q
(abs (truncate m n
))) ;integer part
471 (setq q
(1+ q
) m
(+ m
(* n q
)))
473 (simptimes (list '(mtimes)
475 (simpgamma (list '(%gamma
)
479 (list '(mexpt) (gammac m n q
) -
1))
482 (return (m* (gammac m n q
)
483 (simpgamma (list '(%gamma
)
484 (list '(rat) (rem m n
) n
))
488 (defun gammac (m n q
)
491 (setq q
(1- q
) m
(- m n
) ans
(* m ans
))))
494 ;; This implementation is based on Lanczos convergent formula for the
495 ;; gamma function for Re(z) > 0. We can use the reflection formula
497 ;; -z*Gamma(z)*Gamma(-z) = pi/sin(pi*z)
499 ;; to handle the case of Re(z) <= 0.
501 ;; See http://my.fit.edu/~gabdo/gamma.m for some matlab code to
502 ;; compute this and http://my.fit.edu/~gabdo/gamma.txt for a nice
503 ;; discussion of Lanczos method and an improvement of Lanczos method.
506 ;; The document says this should give about 15 digits of accuracy for
507 ;; double-precision IEEE floats. The document also indicates how to
508 ;; compute a new set of coefficients if you need more range or
511 (defun gamma-lanczos (z)
512 (declare (type (complex flonum
) z
)
513 (optimize (safety 3)))
514 (let ((c (make-array 15 :element-type
'flonum
516 '(0.99999999999999709182
517 57.156235665862923517
518 -
59.597960355475491248
519 14.136097974741747174
520 -
0.49191381609762019978
521 .33994649984811888699e-4
522 .46523628927048575665e-4
523 -
.98374475304879564677e-4
524 .15808870322491248884e-3
525 -
.21026444172410488319e-3
526 .21743961811521264320e-3
527 -
.16431810653676389022e-3
528 .84418223983852743293e-4
529 -
.26190838401581408670e-4
530 .36899182659531622704e-5))))
531 (declare (type (simple-array flonum
(15)) c
))
533 ((minusp (realpart z
))
534 ;; Use the reflection formula
535 ;; -z*Gamma(z)*Gamma(-z) = pi/sin(pi*z)
537 ;; Gamma(z) = pi/z/sin(pi*z)/Gamma(-z)
539 ;; If z is a negative integer, Gamma(z) is infinity. Should
540 ;; we test for this? Throw an error?
541 ;; The test must be done by the calling routine.
543 (* (- z
) (sin (* (float pi
) z
))
544 (gamma-lanczos (- z
)))))
545 ((<= (abs z
) (sqrt flonum-epsilon
))
546 ;; For |z| small, use Gamma(z) = Gamma(z+1)/z
547 (/ (gamma-lanczos (+ 1 z
))
555 (pp (1- (length c
)) (1- pp
)))
558 (incf sum
(/ (aref c pp
) (+ z pp
))))))
560 ;; We check for an overflow. The last positive value in
561 ;; double-float precicsion for which Maxima can calculate
562 ;; gamma is ~171.6243 (CLISP 2.46 and GCL 2.6.8)
564 (let ((zp (expt zgh
(/ zh
2))))
565 (* (sqrt (float (* 2 pi
)))
567 (* (/ zp
(exp zgh
)) zp
))))))
569 ;; No result. Overflow.
570 (merror (intl:gettext
"gamma: overflow in GAMMA-LANCZOS.")))
571 ((or (float-nan-p (realpart result
))
572 (float-inf-p (realpart result
)))
573 ;; Result, but beyond extreme values. Overflow.
574 (merror (intl:gettext
"gamma: overflow in GAMMA-LANCZOS.")))
577 (defun gammafloat (a)
580 ;; Reflection formula to make it positive: gamma(x) =
581 ;; %pi/sin(%pi*x)/x/gamma(-x)
583 (* a
(sin (* (float pi
) a
)))
585 ((<= a
(sqrt flonum-epsilon
))
586 ;; Use gamma(x) = gamma(1+x)/x when x is very small
587 (/ (gammafloat (+ 1 a
))
593 (let ((c (* (sqrt (* 2 (float pi
)))
594 (exp (slatec::d9lgmc a
)))))
595 (let ((v (expt a
(- (* .5e0 a
) 0.25e0
))))
599 (if (or (float-nan-p result
)
600 (float-inf-p result
))
601 (merror (intl:gettext
"gamma: overflow in GAMMAFLOAT."))
604 (declare-top (special $numer $trigsign
))
606 (defmfun $zeromatrix
(m n
) ($ematrix m n
0 1 1))
608 (defmfun $ematrix
(m n var i j
)
610 (cond ((equal m
0) (return (ncons '($matrix simp
))))
611 ((and (equal n
0) (fixnump m
) (> m
0))
612 (return (cons '($matrix simp
) (list-of-mlists m
))))
613 ((not (and (fixnump m
) (fixnump n
)
614 (fixnump i
) (fixnump j
)
615 (> m
0) (> n
0) (> i
0) (> j
0)))
616 (merror (intl:gettext
"ematrix: arguments must be positive integers; found ~M")
617 (list '(mlist simp
) m n i j
) )))
618 loop
(cond ((= m i
) (setq row
(onen j n var
0)) (go on
))
619 ((zerop m
) (return (cons '($matrix
) (mxc ans
)))))
621 (do ((n n
(1- n
))) ((zerop n
)) (setq row
(cons 0 row
)))
622 on
(setq ans
(cons row ans
) m
(1- m
))
625 (defun list-of-mlists (n)
627 (l nil
(cons (ncons '(mlist simp
)) l
)))
630 (declare-top (special $ratmx
))
632 (defmfun $coefmatrix
(eql varl
) (coefmatrix eql varl nil
))
634 (defmfun $augcoefmatrix
(eql varl
) (coefmatrix eql varl t
))
636 (defun coefmatrix (eql varl ind
)
637 (prog (ans row a b elem
)
638 (if (not ($listp eql
)) (improper-arg-err eql
'$coefmatrix
))
639 (if (not ($listp varl
)) (improper-arg-err varl
'$coefmatrix
))
640 (dolist (v (cdr varl
))
641 (if (and (not (atom v
)) (member (caar v
) '(mplus mtimes
) :test
#'eq
))
642 (merror (intl:gettext
"coefmatrix: variables cannot be '+' or '*' expressions; found ~M") v
)))
643 (setq eql
(nreverse (mapcar #'meqhk
(cdr eql
)))
644 varl
(reverse (cdr varl
)))
645 loop1
(if (null eql
) (return (cons '($matrix
) (mxc ans
))))
646 (setq a
(car eql
) eql
(cdr eql
) row nil
)
647 (if ind
(setq row
(cons (const1 a varl
) row
)))
649 loop2
(setq elem
(ratcoef a
(car b
)))
650 (setq row
(cons (if $ratmx elem
(ratdisrep elem
)) row
))
651 (if (setq b
(cdr b
)) (go loop2
))
652 (setq ans
(cons row ans
))
655 (defun const1 (e varl
)
656 (dolist (v varl
) (setq e
(maxima-substitute 0 v e
))) e
)
658 (defmfun $entermatrix
(rows columns
)
659 (prog (row column vector matrix sym symvector
)
660 (cond ((or (not (fixnump rows
))
661 (not (fixnump columns
)))
662 (merror (intl:gettext
"entermatrix: arguments must be integers; found ~M, ~M") rows columns
)))
664 (unless (= rows columns
) (setq sym nil
) (go oloop
))
665 quest
(format t
"~%Is the matrix 1. Diagonal 2. Symmetric 3. Antisymmetric 4. General~%")
666 (setq sym
(retrieve "Answer 1, 2, 3 or 4 : " nil
))
667 (unless (member sym
'(1 2 3 4)) (go quest
))
668 oloop
(cond ((> (incf row
) rows
)
669 (format t
"~%Matrix entered.~%")
670 (return (cons '($matrix
) (mxc matrix
)))))
673 (let ((prompt (format nil
"Row ~a Column ~a: " row column
)))
676 (ncons (onen row columns
677 (meval (retrieve prompt nil
)) 0)))))
680 (setq column
(1- row
))
681 (cond ((equal row
1) (go iloop
)))
683 (cons (nthcdr column vector
) symvector
)
684 vector
(nreverse (mapcar 'car symvector
))
685 symvector
(mapcar 'cdr symvector
))
689 (cond ((equal row
1) (setq vector
(ncons 0)) (go iloop
)))
691 (cons (mapcar #'neg
(nthcdr (1- column
) vector
))
693 vector
(nreconc (mapcar 'car symvector
) (ncons 0))
694 symvector
(mapcar 'cdr symvector
))
696 (setq column
0 vector nil
)
697 iloop
(cond ((> (incf column
) columns
)
698 (setq matrix
(nconc matrix
(ncons vector
)))
700 (let ((prompt (format nil
"Row ~a Column ~a: " row column
)))
701 (setq vector
(nconc vector
(ncons (meval (retrieve prompt nil
))))))
704 (declare-top (special sn
* sd
* rsn
*))
708 ((mtimesp e
) (muln (mapcar '$xthru
(cdr e
)) nil
))
709 ((mplusp e
) (simplify (comdenom (mapcar '$xthru
(cdr e
)) t
)))
710 ((mexptp e
) (power ($xthru
(cadr e
)) (caddr e
)))
711 ((mbagp e
) (cons (car e
) (mapcar '$xthru
(cdr e
))))
714 (defun comdenom (l ind
)
717 (setq n
(m*l sn
*) sn
* nil
)
718 (setq d
(m*l sd
*) sd
* nil
)
719 loop
(setq l
(cdr l
))
721 (return (cond (ind (div* (cond (rsn* ($ratsimp n
))
726 (setq d
(comdenom1 n d
(m*l sn
*) (m*l sd
*)))
731 (defun prodnumden (e)
732 (cond ((atom e
) (prodnd (list e
)))
733 ((eq (caar e
) 'mtimes
) (prodnd (cdr e
)))
734 (t (prodnd (list e
)))))
739 (setq sn
* nil sd
* nil
)
740 loop
(cond ((null l
) (return nil
)))
742 (cond ((atom e
) (setq sn
* (cons e sn
*)))
744 (cond ((not (equal 1 (cadr e
)))
745 (setq sn
* (cons (cadr e
) sn
*))))
746 (setq sd
* (cons (caddr e
) sd
*)))
747 ((and (eq (caar e
) 'mexpt
)
749 (setq sd
* (cons (power (cadr e
)
750 (timesk -
1 (caddr e
)))
752 (t (setq sn
* (cons e sn
*))))
756 (defun comdenom1 (a b c d
)
758 (prodnumden (div* b d
))
759 (setq b1
(m*l sn
*) sn
* nil
)
760 (setq c1
(m*l sd
*) sd
* nil
)
762 (list (add2 (m* a c1
) (m* c b1
))
765 (declare-top (special $globalsolve $backsubst $dispflag
766 $linsolve_params $%rnum_list ax
*linelabel
* $linechar
767 $linenum
*mosesflag
))
769 (defun xrutout (ax n m varl ind
)
770 (let (($linsolve_params
(and $backsubst $linsolve_params
)))
771 (prog (ix imin ans zz m-1 sol tim chk zzz
)
772 (setq ax
(get-array-pointer ax
) tim
0)
773 (if $linsolve_params
(setq $%rnum_list
(list '(mlist))))
774 (setq imin
(min (setq m-1
(1- m
)) n
))
775 (setq ix
(max imin
(length varl
)))
776 loop
(if (zerop ix
) (if ind
(go out
) (return (cons '(mlist) zz
))))
777 (when (or (> ix imin
) (equal (car (aref ax ix ix
)) 0))
779 (rform (if $linsolve_params
(make-param) (ith varl ix
))))
780 (if $linsolve_params
(go saval
) (go next
)))
781 (setq ans
(aref ax ix m
))
782 (setf (aref ax ix m
) nil
)
783 (do ((j (1+ ix
) (1+ j
)))
785 (setq ans
(ratdif ans
(rattimes (aref ax ix j
) (aref ax
0 j
) t
)))
786 (setf (aref ax ix j
) nil
))
787 (setf (aref ax
0 ix
) (ratquotient ans
(aref ax ix ix
)))
788 (setf (aref ax ix ix
) nil
)
790 saval
(push (cond (*mosesflag
(aref ax
0 ix
))
791 (t (list (if $globalsolve
'(msetq) '(mequal))
793 (simplify (rdis (aref ax
0 ix
))))))
796 (setf (aref ax
0 ix
) (rform (ith varl ix
))))
797 (and $globalsolve
(meval (car zz
)))
801 (cond ($dispflag
(mtell (intl:gettext
"Solution:~%"))))
802 (setq sol
(list '(mlist)) chk
(checklabel $linechar
))
803 (do ((ll zz
(cdr ll
)))
806 (setq zzz
(list '(mlabel)
811 (let (($nolabels nil
))
812 (makelabel $linechar
))
814 (setf (symbol-value *linelabel
*) zzz
)))
815 (nconc sol
(ncons *linelabel
*))
817 (setq tim
(get-internal-run-time))
818 (mtell-open "~%~M" zzz
)
821 (putprop *linelabel
* t
'nodisp
))))