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 nisimp
)
15 ;;;programs for the LET LETSIMP LETRULES and REMLET commands
16 ;;;these programs use the names LETSIMPTREE and LETRULES on the
17 ;;;property list of atoms
18 ;;;except for the top level programs all program names have the prefix NIS
20 (declare-top (special nistree nisrules nisflag
))
22 (defmvar $letvarsimp nil
)
26 :properties
((evflag t
)))
28 (setq nisrules nil nistree nil
)
30 (defun let-rule-setter (var val
)
31 (cond ((eq var
'$default_let_rule_package
)
32 (merror (intl:gettext
"assignment: cannot assign to default_let_rule_package.")))
33 ((and (eq var
'$current_let_rule_package
)
34 (not (memalike val
(cdr $let_rule_packages
))))
35 (merror (intl:gettext
"assignment: ~M is not a rule package.") val
))
36 ((eq var
'$let_rule_packages
)
37 (merror (intl:gettext
"assignment: cannot assign to let_rule_packages.~%assignment: call 'let' to create let rule packages.")))))
39 (defmspec $let
(l) (setq l
(cdr l
))
40 (if (null (cdr l
)) (wna-err '$let
))
41 ;;LET([PATTERN,REPL,PRED,ARG1,...,ARGN],NAME)
42 (prog (pattern pat replacement treename text $ratfac
)
43 ;;LET(PATTERN,REPL,PRED,ARG1,...,ARGN)
45 (setq treename $current_let_rule_package
))
46 ((eq 'mlist
(caaar l
))
47 (setq treename
(cadr l
))
48 (if (not (symbolp treename
))
49 (improper-arg-err treename
'$let
))
51 (t (setq treename $current_let_rule_package
)))
52 (let ((nistree (mget treename
'letsimptree
))
53 (nisrules (mget treename
'letrules
)))
54 (setq pat
(strip-lineinfo (meval (car l
))))
55 (setq replacement
(cdr l
))
56 (setq pattern
(cond ((atom pat
) (list pat
))
57 ((eq (caar pat
) 'mtimes
)
60 (setq nistree
(nislet nistree pattern replacement
))
61 (cond (treename (mputprop treename
64 (add2lnc treename $let_rule_packages
)))
65 (nonsymchk (caddr l
) '$let
)
67 (append (list '(mtext) pat
'| --
> |
)
70 '#.
(intern (format nil
" ~A " 'where
))
71 (cons (list (caddr l
))
74 (setq nisrules
(append (list text
) nisrules
))
75 (cond (treename (mputprop treename
80 (defun nislet (tree list function
)
82 (setq permlist
(nispermutations list
))
83 step
(cond ((eq nil permlist
) (return tree
)))
84 (setq tree
(nistreebuilder tree
(car permlist
) function
))
85 (setq permlist
(cdr permlist
))
88 (defun nispermutations (llist)
90 ((null (cdr llist
)) (list llist
))
96 (nispermutations (append a
(cdr llist
))))
98 (if (null (cdr llist
)) (return permlist
))
100 (setq llist
(cdr llist
))
103 (defun nisaddon (x llist
)
104 (if llist
(cons (cons x
(car llist
)) (nisaddon x
(cdr llist
)))))
106 (defun nistreebuilder (tree perm function
)
107 (cond ((null perm
) (cons (list function
) tree
))
109 (list (cons (car perm
)
110 (nistreebuilder nil
(cdr perm
) function
))))
111 ((equal (car perm
) (caar tree
))
114 (nistreebuilder (cdar tree
)
118 (nistreebuilder (cdr tree
)
122 (defun nisswcar (x y
)
125 (defun nisswcdr (x y
)
128 (defmspec $remlet
(x)
130 ;; REMLET(PROD,NAME) REMLET(PROD) REMLET() REMLET(FALSE,NAME)
131 (prog (pattern text treename
)
132 (cond ((cddr x
) (wna-err '$remlet
))
133 ((null (cdr x
)) (setq treename $current_let_rule_package
))
134 (t (setq treename
(cadr x
))
135 (if (not (symbolp treename
))
136 (improper-arg-err treename
'$remlet
))))
137 (setq pattern
(strip-lineinfo (meval (car x
))))
138 (when (or (not pattern
) (eq '$all pattern
))
139 (setq nisrules nil nistree nil
)
140 (unless (eq treename
'$default_let_rule_package
)
141 (setq $let_rule_packages
(delete treename $let_rule_packages
:count
1 :test
#'eq
)))
143 (setq nistree
(mget treename
'letsimptree
))
144 (if (setq text
(nisremlet pattern
)) (return text
))
147 (nistreelister (mget treename
'letrules
) pattern
))
149 a
(mputprop treename nistree
'letsimptree
)
150 (mputprop treename nisrules
'letrules
)
153 (defun nistreelister (llist pattern
)
155 a
(if (alike1 pattern
(cadar llist
)) (return (append x
(cdr llist
))))
156 (setq x
(append x
(list (car llist
))) llist
(cdr llist
))
159 (defun nisremlet (pat)
160 (prog (llist permlist x
)
161 (setq llist
(if (mtimesp pat
) (cdr pat
) (ncons pat
)))
162 (setq nisflag t x nistree
)
163 (setq permlist
(nispermutations llist
))
164 step
(when (null permlist
) (setq nistree x
) (return nil
))
165 (setq x
(nistreetrimmer (car permlist
) x
))
166 (if (null nisflag
) (merror (intl:gettext
"remlet: no rule found: ~M") pat
))
167 (setq permlist
(cdr permlist
))
170 (defun nistreetrimmer (perm tree
)
172 (cond ((null tree
) (setq nisflag nil
))
174 (setq nisflag
(caar tree
)) (cdr tree
))
175 (t (nisswcdr tree
(nistreetrimmer nil
(cdr tree
))))))
176 ((null tree
) (setq nisflag nil
))
177 ((equal (car perm
) (caar tree
))
179 (setq x
(nistreetrimmer (cdr perm
) (cdar tree
)))
180 (if (null x
) (return (cdr tree
)))
181 (return (nisswcar tree
(nisswcdr (car tree
) x
)))))
182 (t (nisswcdr tree
(nistreetrimmer perm
(cdr tree
))))))
184 (defmspec $letrules
(name)
185 (setq name
(cdr name
)) ;LETRULES(NAME)
186 (let ((treename (if name
(car name
) $current_let_rule_package
)))
187 (if (not (symbolp treename
)) (improper-arg-err treename
'$letrules
))
188 (setq nistree
(mget treename
'letsimptree
)
189 nisrules
(mget treename
'letrules
))
190 (apply #'$disp nisrules
)))
192 (defmspec $letsimp
(form) ;letsimp(expr,tree1,...,treen)
193 (setq form
(cdr form
))
194 (let* ((expr (strip-lineinfo (meval (pop form
))))
197 (progv (unless sw
'(varlist genvar
))
198 (unless sw
(list varlist genvar
))
199 (when (and sw
(member 'trunc
(cdar expr
) :test
#'eq
))
200 (setq expr
($taytorat expr
)))
201 (dolist (rulepackage (or form
(list $current_let_rule_package
))
202 (if sw
(ratf expr
) expr
))
203 (unless (symbolp rulepackage
)
204 (improper-arg-err rulepackage
'$letsimp
))
205 (when (setq nistree
(mget rulepackage
'letsimptree
))
206 ;; Whereas nisletsimp returns an expression in general
207 ;; representation, the original expr might be in CRE form.
208 ;; Regardless, we use ratf to make sure varlist and genvar
209 ;; know of expr's kernels.
210 (setq expr
(nisletsimp (if (atom expr
)
214 (defun nisletsimp (e)
217 ((or (and (atom e
) (setq x
(ncons e
)))
218 (and (eq (caar e
) 'mtimes
) (setq x
(cdr e
))))
219 (setq x
(nisnewlist x
))
220 (if x
(nisletsimp ($ratexpand
(cons '(mtimes) x
))) e
))
221 ((member (caar e
) '(mplus mequal mlist $matrix
) :test
#'eq
)
222 (cons (if (eq (caar e
) 'mplus
) '(mplus) (car e
))
223 (mapcar #'nisletsimp
(cdr e
))))
224 ((or (eq (caar e
) 'mrat
)
225 (and (eq (caar e
) 'mquotient
) (setq e
(ratf e
))))
227 (t ;; A kernel (= product of 1 element)
228 (setq x
(nisnewlist (ncons e
)))
229 (if x
(nisletsimp ($ratexpand
(cons '(mtimes) x
))) e
)))))
231 (defun nisletsimprat (e)
232 (let ((num (cadr e
)) (denom (cddr e
)) $ratexpand
)
233 (if $letvarsimp
(setq varlist
(mapcar #'nisletsimp varlist
)))
234 (let (($ratexpand t
))
235 ; Construct new CREs based on the numerator and denominator
236 ; of E and disrep them in the VARLIST and GENVAR context from
239 ; NISLETSIMP can change VARLIST and GENVAR, so the order of
240 ; the PDIS and NISLETSIMP forms matter here. PDISing and
241 ; NISLETSIMPing the numerator before moving on to the
242 ; denominator is not correct.
243 (let ((varlist (mrat-varlist e
))
244 (genvar (mrat-genvar e
)))
247 (setq num
(nisletsimp num
)
248 denom
(nisletsimp denom
)))
249 (setq e
(list '(mquotient) num denom
))
250 (if $letrat
(nisletsimp ($ratexpand e
)) e
)))
252 (defun nisnewlist (llist)
253 (let ((x (nissearch llist nistree nil
))) (if x
(nisreplace llist x
))))
255 (defun nissearch (x y z
)
257 ((nisinnernull y
) (nisfix (nisinnernull y
) z
))
259 (t (prog (xx yy path bind
)
262 b
(cond ((and (setq bind
(nismatch (car xx
)
269 (return (cons (car bind
) path
))))
273 (cond ((null yy
) (return nil
)))
276 (defun nisinnernull (x)
278 ((null (cdar x
)) (caar x
))
279 (t (nisinnernull (cdr x
)))))
281 (defun nisfix (funperd argasslist
)
282 (prog (function args bindings perd flag
)
283 (if (not argasslist
) (return (car funperd
)))
284 (setq argasslist
(nisnumberpicker argasslist
))
285 (setq args
(maplist 'caar argasslist
))
286 (setq bindings
(maplist 'cdar argasslist
))
287 (mbinding (args bindings
)
288 (setq function
(car funperd
))
289 (if (setq perd
(cdr funperd
))
290 (if (not (meval perd
)) (setq flag t
)))
291 (if (null flag
) (setq function
(meval function
))))
292 (return (if flag nil
(list function
)))))
294 (defun nisnumberpicker (x)
296 ((or (not (symbolp (caar x
)))
297 (kindp (caar x
) '$constant
))
298 ;; Skip over numbers and constants
299 (nisnumberpicker (cdr x
)))
300 (t (nisswcdr x
(nisnumberpicker (cdr x
))))))
302 (defun nismatch (a b c
)
304 (setq x
(nisextract a
))
305 (setq y
(nisextract b
))
308 (cond ((and (listp (cadr x
))
309 (equal (car x
) (car y
))
310 (setq c
(cons (cons (car x
) (car y
)) c
))
311 (setq c
(nisargschecker (cadr x
)
314 (setq newexpt
(nisexpocheck (cddr x
)
317 (cond ((equal '(rat) (car newexpt
))
318 (return (cons (cons a
(nisbuild x newexpt
))
320 (t (return (cons (cons a
'(dummy 0 (0 0)))
323 (cond ((and (setq c
(nisargmatch (niskernel a
) (car y
) c
))
324 (setq newexpt
(nisexpocheck (cddr x
)
327 (cond ((equal '(rat) (car newexpt
))
328 (return (cons (cons a
(nisbuild x newexpt
))
330 (t (return (cons (cons a
'(dummy 0 (0 0)))
335 (if (mexptp a
) (cadr a
) a
))
337 (defun nisextract (x)
338 (cond ((or (atom x
) (eq (caar x
) 'rat
))
340 ((eq 'mexpt
(caar x
))
341 (cond ((atom (cadr x
))
342 (cons (cadr x
) (cons t
(caddr x
))))
343 (t (cons (if (member 'array
(cdaadr x
) :test
#'eq
)
344 (list (caaadr x
) 'array
)
346 (cons (cdadr x
) (caddr x
))))))
347 (t (cons (if (member 'array
(cdar x
) :test
#'eq
)
348 (list (caar x
) 'array
)
352 (defun nisargschecker (listargs treeargs argasslist
)
354 (cond ((and listargs treeargs
) (go check
))
355 ((or listargs treeargs
) (return nil
))
356 (t (return argasslist
)))
357 check
(setq c
(nisargmatch (car listargs
)
360 (cond (c (return (nisargschecker (cdr listargs
)
365 (defun nisexpocheck (listpower treepower argasslist
)
366 (prog (p q r s a b xx
)
367 (cond ((atom treepower
)
368 (cond ((numberp treepower
)
369 (prog2 (setq r treepower s
1) (go math
)))
370 (t (return (nisargmatch listpower
373 (setq r
(cadr treepower
) s
(caddr treepower
))
374 (if (not (numberp s
)) (return nil
))
375 math
(cond ((numberp listpower
) (setq p listpower q
1))
376 ((atom listpower
) (return nil
))
377 ((eq 'rat
(caar listpower
))
378 (setq p
(cadr listpower
) q
(caddr listpower
)))
380 (setq xx
(* (* q s
) (- (* p s
) (* q r
))))
381 (setq a
(< (* r s
) 0))
383 (cond ((or (not (or a b
)) (and a
(or b
(equal 0 xx
))))
384 (return (list '(rat) xx
(* q s
)))))
387 (defun nisargmatch (x y c
)
390 up
(if (null w
) (go down
))
391 (cond ((eq (caar w
) y
)
392 (cond ((alike1 (cdar w
) x
) (return c
))
396 down
(setq w
(mget y
'matchdeclare
))
397 (cond ((null w
) (if (equal x y
) (go out
) (return nil
)))
398 ((member (car w
) '($true t
) :test
#'eq
) (go out
))
400 (meval (cons (ncons (car w
))
401 (append (cdr w
) (list x
)))))
403 ((and (not (atom (car w
)))
404 (not (atom (caar w
)))
406 ; If we arrive here, (CAR W) is a Maxima expression like ((FOO) ...)
407 ; If (CAR W) is a Maxima lambda expression, evaluate it via MFUNCALL.
408 ; Otherwise, append X and call MEVAL.
409 ; Note that "otherwise" includes Maxima lambda expressions with missing arguments;
410 ; in that case the expression is ((MQAPPLY) ((LAMBDA) ...)) and MEVAL is the way to go.
411 (if (eq (caaar w
) 'lambda
)
413 (meval (append (car w
) (list x
)))))
416 out
(return (cons (cons y x
) c
))))
418 (defun nisbuild (x newexpt
)
421 (cons (if (symbolp (car x
)) (ncons (car x
)) (car x
))
426 (defun nisreplace (llist asslist
)
427 (cond ((eq (cdr asslist
) nil
) (cons (car asslist
) llist
))
428 ((equal (car llist
) (caar asslist
))
429 (cond ((equal 0 (cadar (cdddar asslist
)))
430 (nisreplace (cdr llist
) (cdr asslist
)))
431 (t (cons (cdar asslist
)
432 (nisreplace (cdr llist
) (cdr asslist
))))))
433 (t (cons (car llist
) (nisreplace (cdr llist
) asslist
)))))