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 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
11 ;; ** (c) Copyright 1982 Massachusetts Institute of Technology **
13 (macsyma-module optim
)
15 (defvar *subexp
* (make-array 64 :initial-element nil
))
17 (defmvar $optimprefix
'$%
19 :setting-predicate
#'symbolp
)
21 (defmvar $optimwarn t
"warns if `optimize' encounters a special form.")
23 ;; $OPTIMIZE takes a Macsyma expression and returns a BLOCK form which is
24 ;; equivalent, but which uses local variables to store the results of computing
25 ;; common subexpressions. These subexpressions are found by hashing them.
27 (defmfun $optimize
(x0)
28 (let (($optimwarn $optimwarn
)
32 (*xvars
* (cdr ($listofvars x0
))))
33 (declare (special *optimcount
* *xvars
* *setqs
* vars
))
35 (prog ((x (collapse (opformat (collapse x0
)))))
36 (when (atom x
) (return x
))
39 (return (prog1 (cond ((null vars
) x0
)
40 (t (if (or (not (eq (caar x
) 'mprog
))
41 (and ($listp
(cadr x
)) (cdadr x
)))
42 (setq x
(nreverse (cons x
*setqs
*)))
43 (setq x
(nreconc *setqs
* (cddr x
))))
44 `((mprog simp
) ((mlist) ,@(nreverse vars
)) ,@x
)))
45 (fill *subexp
* nil
))))))
49 ((specrepp x
) (opformat (specdisrep x
)))
52 (prog2 (mtell (intl:gettext
"optimize: encountered a special form; result may be wrong."))
53 (setq $optimwarn nil
))))
54 ((eq (caar x
) 'mexpt
) (opmexpt x
))
55 (t (let ((newargs (mapcar #'opformat
(cdr x
))))
56 (if (alike newargs
(cdr x
)) x
(cons (car x
) newargs
))))))
59 (let ((*base
(opformat (cadr x
))) (exp (opformat (caddr x
))) xnew negexp
)
61 (cond ((and (realp exp
) (minusp exp
)) (- exp
))
62 ((and (ratnump exp
) (minusp (cadr exp
)))
63 (list (car exp
) (- (cadr exp
)) (caddr exp
)))
64 ((and (mtimesp exp
) (realp (cadr exp
)) (minusp (cadr exp
)))
65 (if (equal (cadr exp
) -
1)
66 (if (null (cdddr exp
)) (caddr exp
)
67 (cons (car exp
) (cddr exp
)))
68 (list* (car exp
) (- (cadr exp
)) (cddr exp
))))
69 ((and (mtimesp exp
) (ratnump (cadr exp
)) (minusp (cadadr exp
)))
71 (list (caadr exp
) (- (cadadr exp
)) (caddr (cadr exp
)))
77 ,(cond ((equal negexp
1) *base
)
78 (t (setq xnew
(list (car x
) *base negexp
))
79 (if (and (ratnump negexp
) (equal (caddr negexp
) 2))
82 ((and (ratnump exp
) (equal (caddr exp
) 2))
84 (if (equal exp
1) `((%sqrt
) ,*base
)
85 `((mexpt) ((%sqrt
) ,*base
) ,exp
)))
86 (t (list (car x
) *base exp
))))
87 (if (alike1 x xnew
) x xnew
)))
89 (defmfun $collapse
(x)
91 (prog1 (collapse x
) (fill *subexp
* nil
)))
95 ((specrepp x
) (collapse (specdisrep x
)))
96 (t (let ((n (opt-hash (caar x
))))
97 (do ((l (cdr x
) (cdr l
)))
99 (if (not (eq (collapse (car l
)) (car l
)))
100 (rplaca l
(collapse (car l
))))
101 (setq n
(rem (+ (opt-hash (car l
)) n
) 12553.
)))
102 (setq n
(logand 63 n
))
103 (do ((l (aref *subexp
* n
) (cdr l
)))
104 ((null l
) (setf (aref *subexp
* n
) (cons (list x
) (aref *subexp
* n
))) x
)
105 (if (alike1 x
(caar l
)) (return (caar l
))))))))
108 (if (not (or (atom x
) (eq (caar x
) 'rat
)))
109 (let ((n (opt-hash (caar x
))))
110 (dolist (u (cdr x
)) (setq n
(rem (+ (opt-hash u
) n
) 12553.
)))
111 (setq x
(assol x
(aref *subexp
* (logand 63. n
))))
112 (cond ((null (cdr x
)) (rplacd x
'seen
) (mapc #'comexp
(cdar x
)))
113 (t (rplacd x
'comexp
))))))
116 (declare (special *setqs
*))
118 ((and (member 'array
(cdar x
) :test
#'eq
)
119 (not (eq (caar x
) 'mqapply
))
120 (not (mget (caar x
) 'arrayfun-mode
)))
122 ((eq (caar x
) 'rat
) x
)
123 (t (let ((n (opt-hash (caar x
))) (nx (list (car x
))))
125 (setq n
(rem (+ (opt-hash u
) n
) 12553.
)
126 nx
(cons (optim u
) nx
)))
127 (setq x
(assol x
(aref *subexp
* (logand 63. n
))) nx
(nreverse nx
))
128 (cond ((eq (cdr x
) 'seen
) nx
)
129 ((eq (cdr x
) 'comexp
)
130 (rplacd x
(getoptimvar))
131 (push `((msetq) ,(cdr x
) ,nx
) *setqs
*)
135 (defun opt-hash (exp) ; EXP is in general representation.
138 (do ((n (opt-hash (caar exp
)))
139 (args (cdr exp
) (cdr args
)))
141 (setq n
(rem (+ (opt-hash (car args
)) n
) 12553.
))))
142 12553.
)) ; a prime number < 2^14 ; = PRIME(1500)
145 (defun getoptimvar ()
146 (declare (special *optimcount
* *xvars
* vars
))
150 (setq var
(make-symbol (format nil
"~A~D" $optimprefix
*optimcount
*)))
151 while
(member var
*xvars
* :test
#'eq
)