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 (defun simpplog (x vestigial z
)
27 (declare (ignore vestigial
))
28 (prog (varlist dd check y
)
31 (setq x
(simpcheck (cadr x
) z
))
32 (cond ((equal 0 x
) (merror (intl:gettext
"plog: plog(0) is undefined.")))
33 ((among var x
) ;This is used in DEFINT. 1/19/81. -JIM
34 (return (eqtest (list '(%plog
) x
) check
))))
37 ((and (member '$%i varlist
)
38 (not (some #'(lambda (v)
39 (and (atom v
) (not (eq v
'$%i
))))
41 (setq dd
(trisplit x
))
42 (cond ((setq z
(patan (car dd
) (cdr dd
)))
43 (return (add2* (simpln (list '(%log
)
44 (simpexpt (list '(mexpt)
45 ($expand
(list '(mplus)
46 (list '(mexpt) (car dd
) 2)
47 (list '(mexpt) (cdr dd
) 2)))
48 '((rat) 1 2)) 1 nil
)) 1 t
)
49 (list '(mtimes) z
'$%i
))))))
50 ((and (free x
'$%i
) (eq ($sign x
) '$pnz
))
51 (return (eqtest (list '(%plog
) x
) check
)))
52 ((and (equal ($imagpart x
) 0) (setq y
($asksign x
)))
53 (cond ((eq y
'$pos
) (return (simpln (list '(%log
) x
) 1 t
)))
54 ((and plogabs
(eq y
'$neg
))
55 (return (simpln (list '(%log
) (list '(mtimes) -
1 x
)) 1 nil
)))
58 (simpln (list '(%log
) (list '(mtimes) -
1 x
)) 1 nil
))))
59 (t (merror (intl:gettext
"plog: plog(0) is undefined.")))))
60 ((and (equal ($imagpart
(setq z
(div* x
'$%i
))) 0)
61 (setq y
($asksign z
)))
63 ((equal y
'$zero
) (merror (intl:gettext
"plog: plog(0) is undefined.")))
64 (t (cond ((eq y
'$pos
) (setq y
1))
65 ((eq y
'$neg
) (setq y -
1)))
66 (return (add2* (simpln (list '(%log
)
67 (list '(mtimes) y z
)) 1 nil
)
68 (list '(mtimes) y
'((rat) 1 2) '$%i
'$%pi
)))))))
69 (return (eqtest (list '(%plog
) x
) check
))))
72 (let (($numer $numer
))
74 (setq i
(simplifya i nil
) r
(simplifya r nil
))
76 (if (floatp i
) (setq $numer t
))
78 (cond ((equal i
'$pos
) (return (simplify half%pi
)))
80 (return (mul2 -
1 (simplify half%pi
))))
81 (t (merror (intl:gettext
"plog: encountered atan(0/0).")))))
83 (cond ((floatp r
) (setq $numer t
)))
85 (cond ((equal r
'$pos
) (return 0))
86 ((equal r
'$neg
) (return (simplify '$%pi
)))
87 (t (merror (intl:gettext
"plog: encountered atan(0/0).")))))
88 ((and (among '%cos r
) (among '%sin i
))
89 ;; genvar and varlist, used by the rational function system,
90 ;; are bound in order to prevent the symbol 'xz from leaking
91 ;; out of this function.
92 (let ((var 'xz
) genvar varlist
)
94 (cond ((and (eq (caar nn
*) '%cos
) (eq (caar dn
*) '%sin
))
95 (return (cadr nn
*)))))))
96 (setq a
($sign r
) b
($sign i
))
97 (cond ((eq a
'$pos
) (setq a
1))
98 ((eq a
'$neg
) (setq a -
1))
99 ((eq a
'$zero
) (setq a
0)))
100 (cond ((eq b
'$pos
) (setq b
1))
101 ((eq b
'$neg
) (setq b -
1))
102 ((eq a
'$zero
) (setq b
0)))
104 (return (if (equal a
1) 0 (simplify '$%pi
))))
106 (return (cond ((equal b
1) (simplify half%pi
))
107 (t (mul2 '((rat simp
) -
1 2)
108 (simplify '$%pi
)))))))
109 (setq r
(simptimes (list '(mtimes) a b
(div* i r
)) 1 nil
))
110 (return (cond ((onep1 r
)
111 (archk a b
(list '(mtimes) '((rat) 1 4) '$%pi
)))
112 ((alike1 r
'((mexpt) 3 ((rat) 1 2)))
113 (archk a b
(list '(mtimes) '((rat) 1 3) '$%pi
)))
114 ((alike1 r
'((mexpt) 3 ((rat) -
1 2)))
115 (archk a b
(list '(mtimes) '((rat) 1 6) '$%pi
))))))))
117 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
119 ;;; Implementation of the Binomial coefficient
121 ;; Verb function for the Binomial coefficient
122 (defmfun $binomial
(x y
)
123 (simplify (list '(%binomial
) x y
)))
125 ;; Binomial has Mirror symmetry
126 (defprop %binomial t commutes-with-conjugate
)
128 (defun simpbinocoef (x vestigial z
)
129 (declare (ignore vestigial
))
131 (let ((u (simpcheck (cadr x
) z
))
132 (v (simpcheck (caddr x
) z
))
136 (if (and (integerp u
) (minusp u
) (< v u
))
139 ((or (zerop v
) (equal u v
)) 1)
140 ((and (integerp u
) (not (minusp u
)))
141 (bincomp u
(min v
(- u v
))))
143 ((integerp (setq y
(sub u v
)))
145 ;; u and v are equal, simplify not if argument can be negative
146 (if (member ($csign u
) '($pnz $pn $neg $nz
))
147 (eqtest (list '(%binomial
) u v
) x
)
150 ((complex-float-numerical-eval-p u v
)
151 ;; Numercial evaluation for real and complex floating point numbers.
152 (let (($numer t
) ($float t
))
155 ($makegamma
(list '(%binomial
) ($float u
) ($float v
)))))))
156 ((complex-bigfloat-numerical-eval-p u v
)
157 ;; Numerical evaluation for real and complex bigfloat numbers.
160 ($makegamma
(list '(%binomial
) ($bfloat u
) ($bfloat v
))))))
161 (t (eqtest (list '(%binomial
) u v
) x
)))))
166 ((mnump u
) (binocomp u v
))
167 (t (muln (bincomp1 u v
) nil
))))
169 (defun bincomp1 (u v
)
172 (list* u
(list '(mexpt) v -
1) (bincomp1 (add2 -
1 u
) (1- v
)))))
174 (defun binocomp (u v
)
177 loop
(if (zerop v
) (return ans
))
178 (setq ans
(timesk (timesk u ans
) (simplify (list '(rat) 1 v
))))
179 (setq u
(addk -
1 u
) v
(1- v
))
182 ;;; gradient of binomial
186 ((mtimes) -
1 ((%binomial
) a b
)
189 ((mqapply) (($psi array
) 0) ((mplus) 1 a
)))
190 ((mqapply) (($psi array
) 0)
191 ((mplus) 1 a
((mtimes) -
1 b
)))))
193 ((mtimes) -
1 ((%binomial
) a b
)
196 ((mqapply) (($psi array
) 0)
197 ((mplus) 1 a
((mtimes) -
1 b
))))
198 ((mqapply) (($psi array
) 0) ((mplus) 1 b
))))) grad
)
200 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
202 ;;; Implementation of the Beta function
204 (declare-top (special $gammalim
))
206 (defmvar $beta_args_sum_to_integer nil
)
208 ;;; The Beta function has mirror symmetry
209 (defprop $beta t commutes-with-conjugate
)
211 (defun simpbeta (x vestigial z
&aux check
)
212 (declare (ignore vestigial
))
215 (let ((u (simpcheck (cadr x
) z
)) (v (simpcheck (caddr x
) z
)))
216 (cond ((or (zerop1 u
) (zerop1 v
))
220 (intl:gettext
"beta: expected nonzero arguments; found ~M, ~M")
223 ;; Check for numerical evaluation in float precision
224 ((complex-float-numerical-eval-p u v
)
226 ;; We use gamma(u)*gamma(v)/gamma(u+v) for numerical evaluation.
227 ;; Therefore u, v or u+v can not be a negative integer or a
228 ;; floating point representation of a negative integer.
229 ((and (or (not (numberp u
))
231 (not (= (nth-value 1 (truncate u
)) 0)))
232 (and (or (not (numberp v
))
234 (not (= (nth-value 1 (truncate v
)) 0)))
235 (and (or (not (numberp (add u v
)))
237 (not (= (nth-value 1 ($truncate
(add u v
))) 0))))))
240 (add ($log_gamma
($float u
))
241 ($log_gamma
($float v
))
242 (mul -
1 ($log_gamma
($float
(add u v
))))))))
243 ((or (and (numberp u
)
245 (= (nth-value 1 (truncate u
)) 0)
247 (eq ($sign
(sub ($truncate v
) v
)) '$zero
)
249 (eq ($sign
(add u v
)) '$pos
)))
250 (setq u
(truncate u
)))
253 (= (nth-value 1 (truncate u
)) 0)
255 (eq ($sign
(sub ($truncate u
) u
)) '$zero
)
257 (eq ($sign
(add u v
)) '$pos
)))
258 (setq v
(truncate v
))))
259 ;; One value is representing a negative integer, the other a
260 ;; positive integer and the sum is negative. Expand.
261 ($rectform
($float
(beta-expand-integer u v
))))
263 (eqtest (list '($beta
) u v
) check
))))
265 ;; Check for numerical evaluation in bigfloat precision
266 ((complex-bigfloat-numerical-eval-p u v
)
267 (let (($ratprint nil
))
269 ((and (or (not (mnump u
))
271 (not (eq ($sign
(sub ($truncate u
) u
)) '$zero
)))
274 (not (eq ($sign
(sub ($truncate v
) v
)) '$zero
)))
275 (or (not (mnump (add u v
)))
276 (eq ($sign
(add u v
)) '$pos
)
277 (not (eq ($sign
(sub ($truncate
(add u v
))
282 (add ($log_gamma
($bfloat u
))
283 ($log_gamma
($bfloat v
))
284 (mul -
1 ($log_gamma
($bfloat
(add u v
))))))))
287 (eq ($sign
(sub ($truncate u
) u
)) '$zero
)
289 (eq ($sign
(sub ($truncate v
) v
)) '$zero
)
291 (eq ($sign
(add u v
)) '$pos
)))
292 (setq u
($truncate u
)))
295 (eq ($sign
(sub ($truncate v
) v
)) '$zero
)
297 (eq ($sign
(sub ($truncate u
) u
)) '$zero
)
299 (eq ($sign
(add u v
)) '$pos
)))
300 (setq v
($truncate v
))))
301 ($rectform
($bfloat
(beta-expand-integer u v
))))
303 (eqtest (list '($beta
) u v
) check
)))))
305 ((or (and (and (integerp u
)
308 (eq ($sign
(sub ($truncate v
) v
)) '$zero
)
310 (eq ($sign
(add u v
)) '$pos
))))
311 (and (and (integerp v
)
314 (eq ($sign
(sub ($truncate u
) u
)) '$zero
)
316 (eq ($sign
(add u v
)) '$pos
)))))
317 ;; Expand for a positive integer. But not if the other argument is
318 ;; a negative integer and the sum of the integers is not negative.
319 (beta-expand-integer u v
))
321 ;;; At this point both integers are negative. This code does not work for
322 ;;; negative integers. The factorial function is not defined.
323 ; ((and (integerp u) (integerp v))
324 ; (mul2* (div* (list '(mfactorial) (1- u))
325 ; (list '(mfactorial) (+ u v -1)))
326 ; (list '(mfactorial) (1- v))))
328 ((or (and (ratnump u
) (ratnump v
) (integerp (setq x
(addk u v
))))
329 (and $beta_args_sum_to_integer
330 (integerp (setq x
(expand1 (add2 u v
) 1 1)))))
331 (let ((w (if (symbolp v
) v u
)))
334 (add2 (1- x
) (neg w
))
336 `((%sin
) ((mtimes) ,w $%pi
)))))
338 ((and $beta_expand
(mplusp u
) (integerp (cadr u
)))
339 ;; Expand beta(a+n,b) where n is an integer.
341 (u (simplify (cons '(mplus) (cddr u
)))))
342 (beta-expand-add-integer n u v
)))
344 ((and $beta_expand
(mplusp v
) (integerp (cadr v
)))
345 ;; Expand beta(a,b+n) where n is an integer.
347 (v (simplify (cons '(mplus) (cddr v
)))))
348 (beta-expand-add-integer n v u
)))
350 (t (eqtest (list '($beta
) u v
) check
)))))
352 (defun beta-expand-integer (u v
)
353 ;; One of the arguments is a positive integer. Do an expansion.
354 ;; BUT for a negative integer as second argument the expansion is only
355 ;; possible when the sum of the integers is negative too.
356 ;; This routine expects that the calling routine has checked this.
363 (sub (if (and (integerp u
) (plusp u
)) u v
) 1))))
366 (defun beta-expand-add-integer (n u v
)
368 (mul (simplify (list '($pochhammer
) u n
))
369 (power (simplify (list '($pochhammer
) (add u v
) n
)) -
1)
370 (simplify (list '($beta
) u v
)))
371 (mul (simplify (list '($pochhammer
) (add u v n
) (- n
)))
372 (power (simplify (list '($pochhammer
) (add u n
) (- n
))) -
1)
373 (simplify (list '($beta
) u v
)))))
375 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
377 ;;; Implementation of the Gamma function
379 (defun simpgamma (x vestigial z
)
380 (declare (ignore vestigial
))
382 (let ((j (simpcheck (cadr x
) z
)))
383 (cond ((and (floatp j
)
386 (zerop (nth-value 1 (truncate j
))))))
387 (merror (intl:gettext
"gamma: gamma(~:M) is undefined.") j
))
388 ((float-numerical-eval-p j
) (gammafloat ($float j
)))
391 (and (eq ($sign j
) '$neg
)
392 (zerop1 (sub j
($truncate j
))))))
393 (merror (intl:gettext
"gamma: gamma(~:M) is undefined.") j
))
394 ((bigfloat-numerical-eval-p j
)
395 ;; Adding 4 digits in the call to bffac. For $fpprec up to about 256
396 ;; and an argument up to about 500.0 the accuracy of the result is
397 ;; better than 10^(-$fpprec).
398 (let ((z (bigfloat:to
($bfloat j
))))
400 ((bigfloat:<= (bigfloat:abs z
) (bigfloat:sqrt
(bigfloat:epsilon z
)))
401 ;; For small z, use gamma(z) = gamma(z+1)/z = z!/z
402 (div (mfuncall '$bffac
407 (let ((result (mfuncall '$bffac
(m+ ($bfloat j
) -
1) (+ $fpprec
4))))
408 ;; bigfloatp will round the result to the correct fpprec
409 (bigfloatp result
))))))
410 ((complex-float-numerical-eval-p j
)
411 (complexify (gamma-lanczos (complex ($float
($realpart j
))
412 ($float
($imagpart j
))))))
413 ((complex-bigfloat-numerical-eval-p j
)
414 (let ((z (bigfloat:to
($bfloat j
))))
416 ((bigfloat:<= (bigfloat:abs z
)
417 (bigfloat:sqrt
(bigfloat:epsilon z
)))
418 ;; For small z, use gamma(z) = gamma(z+1)/z = z!/z
419 (to (bigfloat:/ (bigfloat:to
(mfuncall '$cbffac
424 ;; Adding 4 digits in the call to cbffac. See comment above.
427 (add -
1 ($bfloat
($realpart j
))
428 (mul '$%i
($bfloat
($imagpart j
))))
430 (add (bigfloatp ($realpart result
))
431 (mul '$%i
(bigfloatp ($imagpart result
)))))))))
432 ((taylorize (mop x
) (cadr x
)))
433 ((eq j
'$inf
) '$inf
) ; Simplify to $inf to be more consistent.
437 ;; Expand gamma(z+n) for n an integer.
439 (z (simplify (cons '(mplus) (cddr j
)))))
442 (mul (simplify (list '($pochhammer
) z n
))
443 (simplify (list '(%gamma
) z
))))
446 (div (mul (power -
1 n
) (simplify (list '(%gamma
) z
)))
447 ;; We factor to get the order (z-1)*(z-2)*...
448 ;; and not (1-z)*(2-z)*...
450 (simplify (list '($pochhammer
) (sub 1 z
) n
))))))))
453 (cond ((<= j $factlim
)
454 ;; Positive integer less than $factlim. Evaluate.
455 (simplify (list '(mfactorial) (1- j
))))
456 ;; Positive integer greater $factlim. Noun form.
457 (t (eqtest (list '(%gamma
) j
) x
))))
458 ;; Negative integer. Throw a Maxima error.
459 (errorsw (throw 'errorsw t
))
460 (t (merror (intl:gettext
"gamma: gamma(~:M) is undefined.") j
))))
461 ((alike1 j
'((rat) 1 2))
462 (list '(mexpt simp
) '$%pi j
))
464 (ratgreaterp $gammalim
(simplify (list '(mabs) j
)))
465 (or (ratgreaterp j
1) (ratgreaterp 0 j
)))
466 ;; Expand for rational numbers less than $gammalim.
468 (t (eqtest (list '(%gamma
) j
) x
)))))
470 ;; A sign function for gamma(x); when x > 0 return pos; when x < 0 or x > 0, return pn;
471 ;;; otherwise, return pnz (that is, nothing known).
472 (defun gamma-sign (x)
473 (let ((sgn ($csign
(second x
)))) ;; careful! x = ((%gamma) XXX)
475 (cond ((eql sgn
'$pos
) '$pos
)
476 ((or (eql sgn
'$neg
) (eql sgn
'$pn
)) '$pn
)
479 (putprop '%gamma
'gamma-sign
'sign-function
)
481 (defun gamma (y) ;;; numerical evaluation for 0 < y < 1
483 (setq coefs
(list 0.035868343 -
0.193527817 0.48219939
484 -
0.75670407 0.91820685 -
0.89705693
485 0.98820588 -
0.57719165))
486 (unless (atom y
) (setq y
(fpcofrat y
)))
487 (setq sum
(car coefs
) coefs
(cdr coefs
))
488 loop
(setq sum
(+ (* sum y
) (car coefs
)))
489 (when (setq coefs
(cdr coefs
)) (go loop
))
490 (return (+ (/ y
) sum
))))
492 (defun gammared (a) ;A is assumed to
493 (prog (m q n
) ;be '((RAT) M N)
494 (cond ((floatp a
) (return (gammafloat a
))))
495 (setq m
(cadr a
) ;Numerator
496 n
(caddr a
) ;denominator
497 q
(abs (truncate m n
))) ;integer part
499 (setq q
(1+ q
) m
(+ m
(* n q
)))
501 (simptimes (list '(mtimes)
503 (simpgamma (list '(%gamma
)
507 (list '(mexpt) (gammac m n q
) -
1))
510 (return (m* (gammac m n q
)
511 (simpgamma (list '(%gamma
)
512 (list '(rat) (rem m n
) n
))
516 (defun gammac (m n q
)
519 (setq q
(1- q
) m
(- m n
) ans
(* m ans
))))
522 ;; This implementation is based on Lanczos convergent formula for the
523 ;; gamma function for Re(z) > 0. We can use the reflection formula
525 ;; -z*Gamma(z)*Gamma(-z) = pi/sin(pi*z)
527 ;; to handle the case of Re(z) <= 0.
529 ;; See http://my.fit.edu/~gabdo/gamma.m for some matlab code to
530 ;; compute this and http://my.fit.edu/~gabdo/gamma.txt for a nice
531 ;; discussion of Lanczos method and an improvement of Lanczos method.
534 ;; The document says this should give about 15 digits of accuracy for
535 ;; double-precision IEEE floats. The document also indicates how to
536 ;; compute a new set of coefficients if you need more range or
539 (defun gamma-lanczos (z)
540 (declare (type (complex flonum
) z
)
541 (optimize (safety 3)))
542 (let ((c (make-array 15 :element-type
'flonum
544 '(0.99999999999999709182
545 57.156235665862923517
546 -
59.597960355475491248
547 14.136097974741747174
548 -
0.49191381609762019978
549 .33994649984811888699e-4
550 .46523628927048575665e-4
551 -
.98374475304879564677e-4
552 .15808870322491248884e-3
553 -
.21026444172410488319e-3
554 .21743961811521264320e-3
555 -
.16431810653676389022e-3
556 .84418223983852743293e-4
557 -
.26190838401581408670e-4
558 .36899182659531622704e-5))))
559 (declare (type (simple-array flonum
(15)) c
))
561 ((minusp (realpart z
))
562 ;; Use the reflection formula
563 ;; -z*Gamma(z)*Gamma(-z) = pi/sin(pi*z)
565 ;; Gamma(z) = pi/z/sin(pi*z)/Gamma(-z)
567 ;; If z is a negative integer, Gamma(z) is infinity. Should
568 ;; we test for this? Throw an error?
569 ;; The test must be done by the calling routine.
571 (* (- z
) (sin (* (float pi
) z
))
572 (gamma-lanczos (- z
)))))
573 ((<= (abs z
) (sqrt +flonum-epsilon
+))
574 ;; For |z| small, use Gamma(z) = Gamma(z+1)/z
575 (/ (gamma-lanczos (+ 1 z
))
583 (pp (1- (length c
)) (1- pp
)))
586 (incf sum
(/ (aref c pp
) (+ z pp
))))))
588 ;; We check for an overflow. The last positive value in
589 ;; double-float precicsion for which Maxima can calculate
590 ;; gamma is ~171.6243 (CLISP 2.46 and GCL 2.6.8)
592 (let ((zp (expt zgh
(/ zh
2))))
593 (* (sqrt (float (* 2 pi
)))
595 (* (/ zp
(exp zgh
)) zp
))))))
597 ;; No result. Overflow.
598 (merror (intl:gettext
"gamma: overflow in GAMMA-LANCZOS.")))
599 ((or (float-nan-p (realpart result
))
600 (float-inf-p (realpart result
)))
601 ;; Result, but beyond extreme values. Overflow.
602 (merror (intl:gettext
"gamma: overflow in GAMMA-LANCZOS.")))
605 (defun gammafloat (a)
608 ;; Reflection formula to make it positive: gamma(x) =
609 ;; %pi/sin(%pi*x)/x/gamma(-x)
611 (* a
(sin (* (float pi
) a
)))
613 ((<= a
(sqrt +flonum-epsilon
+))
614 ;; Use gamma(x) = gamma(1+x)/x when x is very small
615 (/ (gammafloat (+ 1 a
))
621 (let ((c (* (sqrt (* 2 (float pi
)))
622 (exp (slatec::d9lgmc a
)))))
623 (let ((v (expt a
(- (* .5e0 a
) 0.25e0
))))
627 (if (or (float-nan-p result
)
628 (float-inf-p result
))
629 (merror (intl:gettext
"gamma: overflow in GAMMAFLOAT."))
632 (defmfun $zeromatrix
(m n
) ($ematrix m n
0 1 1))
634 (defmfun $ematrix
(m n var i j
)
636 (cond ((equal m
0) (return (ncons '($matrix simp
))))
637 ((and (equal n
0) (fixnump m
) (> m
0))
638 (return (cons '($matrix simp
) (list-of-mlists m
))))
639 ((not (and (fixnump m
) (fixnump n
)
640 (fixnump i
) (fixnump j
)
641 (> m
0) (> n
0) (> i
0) (> j
0)))
642 (merror (intl:gettext
"ematrix: arguments must be positive integers; found ~M")
643 (list '(mlist simp
) m n i j
) )))
644 loop
(cond ((= m i
) (setq row
(onen j n var
0)) (go on
))
645 ((zerop m
) (return (cons '($matrix
) (mxc ans
)))))
647 (do ((n n
(1- n
))) ((zerop n
)) (setq row
(cons 0 row
)))
648 on
(setq ans
(cons row ans
) m
(1- m
))
651 (defun list-of-mlists (n)
653 (l nil
(cons (ncons '(mlist simp
)) l
)))
656 (defmfun $coefmatrix
(eql varl
) (coefmatrix eql varl nil
))
658 (defmfun $augcoefmatrix
(eql varl
) (coefmatrix eql varl t
))
660 (defun coefmatrix (eql varl ind
)
661 (prog (ans row a b elem
)
662 (if (not ($listp eql
)) (improper-arg-err eql
'$coefmatrix
))
663 (if (not ($listp varl
)) (improper-arg-err varl
'$coefmatrix
))
664 (dolist (v (cdr varl
))
665 (if (and (not (atom v
)) (member (caar v
) '(mplus mtimes
) :test
#'eq
))
666 (merror (intl:gettext
"coefmatrix: variables cannot be '+' or '*' expressions; found ~M") v
)))
667 (setq eql
(nreverse (mapcar #'meqhk
(cdr eql
)))
668 varl
(reverse (cdr varl
)))
669 loop1
(if (null eql
) (return (cons '($matrix
) (mxc ans
))))
670 (setq a
(car eql
) eql
(cdr eql
) row nil
)
671 (if ind
(setq row
(cons (const1 a varl
) row
)))
673 loop2
(setq elem
(ratcoef a
(car b
)))
674 (setq row
(cons (if $ratmx elem
(ratdisrep elem
)) row
))
675 (if (setq b
(cdr b
)) (go loop2
))
676 (setq ans
(cons row ans
))
679 (defun const1 (e varl
)
680 (dolist (v varl
) (setq e
(maxima-substitute 0 v e
))) e
)
682 (defmfun $entermatrix
(rows columns
)
683 (prog (row column vector matrix sym symvector
)
684 (cond ((or (not (fixnump rows
))
685 (not (fixnump columns
)))
686 (merror (intl:gettext
"entermatrix: arguments must be integers; found ~M, ~M") rows columns
)))
688 (unless (= rows columns
) (setq sym nil
) (go oloop
))
689 quest
(format t
"~%Is the matrix 1. Diagonal 2. Symmetric 3. Antisymmetric 4. General~%")
690 (setq sym
(retrieve "Answer 1, 2, 3 or 4 : " nil
))
691 (unless (member sym
'(1 2 3 4)) (go quest
))
692 oloop
(cond ((> (incf row
) rows
)
693 (format t
"~%Matrix entered.~%")
694 (return (cons '($matrix
) (mxc matrix
)))))
697 (let ((prompt (format nil
"Row ~a Column ~a: " row column
)))
700 (ncons (onen row columns
701 (meval (retrieve prompt nil
)) 0)))))
704 (setq column
(1- row
))
705 (cond ((equal row
1) (go iloop
)))
707 (cons (nthcdr column vector
) symvector
)
708 vector
(nreverse (mapcar 'car symvector
))
709 symvector
(mapcar 'cdr symvector
))
713 (cond ((equal row
1) (setq vector
(ncons 0)) (go iloop
)))
715 (cons (mapcar #'neg
(nthcdr (1- column
) vector
))
717 vector
(nreconc (mapcar 'car symvector
) (ncons 0))
718 symvector
(mapcar 'cdr symvector
))
720 (setq column
0 vector nil
)
721 iloop
(cond ((> (incf column
) columns
)
722 (setq matrix
(nconc matrix
(ncons vector
)))
724 (let ((prompt (format nil
"Row ~a Column ~a: " row column
)))
725 (setq vector
(nconc vector
(ncons (meval (retrieve prompt nil
))))))
728 (declare-top (special sn
* sd
* rsn
*))
732 ((mtimesp e
) (muln (mapcar '$xthru
(cdr e
)) nil
))
733 ((mplusp e
) (simplify (comdenom (mapcar '$xthru
(cdr e
)) t
)))
734 ((mexptp e
) (power ($xthru
(cadr e
)) (caddr e
)))
735 ((mbagp e
) (cons (car e
) (mapcar '$xthru
(cdr e
))))
738 (defun comdenom (l ind
)
741 (setq n
(m*l sn
*) sn
* nil
)
742 (setq d
(m*l sd
*) sd
* nil
)
743 loop
(setq l
(cdr l
))
745 (return (cond (ind (div* (cond (rsn* ($ratsimp n
))
750 (setq d
(comdenom1 n d
(m*l sn
*) (m*l sd
*)))
755 (defun prodnumden (e)
756 (cond ((atom e
) (prodnd (list e
)))
757 ((eq (caar e
) 'mtimes
) (prodnd (cdr e
)))
758 (t (prodnd (list e
)))))
763 (setq sn
* nil sd
* nil
)
764 loop
(cond ((null l
) (return nil
)))
766 (cond ((atom e
) (setq sn
* (cons e sn
*)))
768 (cond ((not (equal 1 (cadr e
)))
769 (setq sn
* (cons (cadr e
) sn
*))))
770 (setq sd
* (cons (caddr e
) sd
*)))
771 ((and (eq (caar e
) 'mexpt
)
773 (setq sd
* (cons (power (cadr e
)
774 (timesk -
1 (caddr e
)))
776 (t (setq sn
* (cons e sn
*))))
780 (defun comdenom1 (a b c d
)
782 (prodnumden (div* b d
))
783 (setq b1
(m*l sn
*) sn
* nil
)
784 (setq c1
(m*l sd
*) sd
* nil
)
786 (list (add2 (m* a c1
) (m* c b1
))
789 (declare-top (special ax
792 (defun xrutout (ax n m varl ind
)
793 (let (($linsolve_params
(and $backsubst $linsolve_params
)))
794 (prog (ix imin ans zz m-1 sol tim chk zzz
)
795 (setq ax
(get-array-pointer ax
) tim
0)
796 (if $linsolve_params
(setq $%rnum_list
(list '(mlist))))
797 (setq imin
(min (setq m-1
(1- m
)) n
))
798 (setq ix
(max imin
(length varl
)))
799 loop
(if (zerop ix
) (if ind
(go out
) (return (cons '(mlist) zz
))))
800 (when (or (> ix imin
) (equal (car (aref ax ix ix
)) 0))
802 (rform (if $linsolve_params
(make-param) (ith varl ix
))))
803 (if $linsolve_params
(go saval
) (go next
)))
804 (setq ans
(aref ax ix m
))
805 (setf (aref ax ix m
) nil
)
806 (do ((j (1+ ix
) (1+ j
)))
808 (setq ans
(ratdif ans
(rattimes (aref ax ix j
) (aref ax
0 j
) t
)))
809 (setf (aref ax ix j
) nil
))
810 (setf (aref ax
0 ix
) (ratquotient ans
(aref ax ix ix
)))
811 (setf (aref ax ix ix
) nil
)
813 saval
(push (cond (*mosesflag
(aref ax
0 ix
))
814 (t (list (if $globalsolve
'(msetq) '(mequal))
816 (simplify (rdis (aref ax
0 ix
))))))
819 (setf (aref ax
0 ix
) (rform (ith varl ix
))))
820 (and $globalsolve
(meval (car zz
)))
824 (cond ($dispflag
(mtell (intl:gettext
"Solution:~%"))))
825 (setq sol
(list '(mlist)) chk
(checklabel $linechar
))
826 (do ((ll zz
(cdr ll
)))
829 (setq zzz
(list '(mlabel)
834 (let (($nolabels nil
))
835 (makelabel $linechar
))
837 (setf (symbol-value *linelabel
*) zzz
)))
838 (nconc sol
(ncons *linelabel
*))
840 (setq tim
(get-internal-run-time))
841 (mtell-open "~%~M" zzz
)
844 (putprop *linelabel
* t
'nodisp
))))