1 ;;; -*- Mode: Lisp; Package: Macsyma -*- ;;;
2 ;;; (c) Copyright 1984 the Regents of the University of California. ;;;
3 ;;; All Rights Reserved. ;;;
4 ;;; This work was produced under the sponsorship of the ;;;
5 ;;; U.S. Department of Energy. The Government retains ;;;
6 ;;; certain rights therein. ;;;
7 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9 (macsyma-module rducon
)
12 (:load-toplevel
:execute
)
13 (or (get 'expens
'version
)
16 (defmvar $const_eqns
(list '(mlist simp
))
17 "List of equations of constant expressions found by REDUCE_CONSTS."
18 modified-commands
'$reduce_consts
)
20 (defmvar $const_prefix
'$xx
21 "String used to prefix all symbols generated by REDUCE_CONSTS to
22 represent constant expressions."
23 modified-commands
'$reduce_consts
)
25 (defmvar $const_counter
1
26 "Integer index used to uniquely identify all constant expressions
27 found by calling REDUCE_CONSTS."
29 modified-commands
'$reduce_consts
)
31 (defmacro minus-constantp
(x)
32 `(and (eq (caar ,x
) 'mtimes
)
34 (equal (cadr ,x
) -
1)))
36 (defun query-const-table (x)
37 (do ((p (cdr $const_eqns
) (cdr p
)))
39 (and (alike1 (caddar p
) x
)
42 (defun new-name (default-name)
43 (let ((name (or default-name
45 (implode (nconc (exploden $const_prefix
)
46 (exploden $const_counter
)))
47 (incf $const_counter
)))))
48 (MFUNCALL '$declare name
'$constant
)
51 (defun log-const (exp name
)
52 (let ((inconst (new-name name
)))
53 (setq $const_eqns
`(,.$const_eqns
,`((mequal simp
) ,inconst
,exp
)))
56 (defun obtain-constant (key curr-const
)
58 (or (query-const-table key
)
59 (do ((pursue (cdr $const_eqns
) (cdr pursue
))
63 (expense ($expense key
))
64 (negative (mul -
1 key
))
69 (cond ((eq op
'sum
) (add (cadar pointer
) hold
))
70 ((eq op
'neg
) (mul -
1 (add (cadar pointer
) hold
)))
71 (t (mul (cadar pointer
) hold
))))
72 (do ((recheck (cdr $const_eqns
) (cdr recheck
))
73 (minkey (mul -
1 inkey
)))
75 (let ((exp (caddar recheck
))
76 (lab (cadar recheck
)))
77 (cond ((alike1 exp inkey
) (return lab
))
79 (return (mul -
1 lab
))))))))
80 (let ((rhs (caddar pursue
)))
81 (cond ((alike1 negative rhs
) (return (mul -
1 (cadar pursue
))))
84 (let ((trial (sub key rhs
))
85 (trial-2 (sub negative rhs
)))
86 (let ((estim (1+ ($expense trial
)))
87 (estim-2 (1+ ($expense trial-2
))))
88 (cond ((< estim estim-2
)
89 (and (< estim expense
)
95 (and (< estim-2 expense
)
101 (let* ((trial (div key rhs
))
102 (estim (1+ ($expense trial
))))
103 (and (< estim expense
)
108 (log-const inkey curr-const
))))
110 (defun find-constant (x)
111 (cond ((and (symbolp x
) ($constantp x
)) x
)
113 (do ((fcon x
(cdr fcon
)))
115 (let ((qcon (cadr fcon
)))
116 (and (symbolp qcon
) ($constantp qcon
) (return qcon
)))))
119 (defun reduce-constants (x &optional newconst
)
120 (cond ((or ($mapatom x
)
121 (and (eq (caar x
) 'mtimes
)
126 ((query-const-table x
))
127 ((and (eq (caar x
) 'mexpt
)
129 (let ((xexpon (caddr x
)) (xbase (cadr x
)))
130 (do ((p (cdr $const_eqns
) (cdr p
))
131 (nstate (integerp xexpon
))
132 (follow $const_eqns p
))
134 (let ((obj (caddar p
)))
136 (alike1 xbase
(cadr obj
))
137 (let ((inquir-expon (caddr obj
)))
138 (let ((both-fix (and nstate
(integerp inquir-expon
))))
139 (let ((dif (cond (both-fix (- xexpon inquir-expon
))
140 (t (sub xexpon inquir-expon
))))
141 (gcd (cond (both-fix (gcd xexpon inquir-expon
))
142 (t ($gcd xexpon inquir-expon
)))))
143 (or (and (integerp dif
)
145 (let ((new-exp (mul (cadar p
) xbase
)))
146 (return (or (query-const-table new-exp
)
147 (log-const new-exp newconst
)))))
149 (let ((inc (new-name newconst
)))
150 (rplaca (cddar p
) (mul inc xbase
))
151 (rplacd follow
(append `(((mequal simp
) ,inc
,x
)) p
))
153 (or (and (integerp gcd
) (equal gcd
1))
154 (let ((pw1 (cond (both-fix (quotient xexpon gcd
))
155 (t (div xexpon gcd
))))
156 (pw2 (cond (both-fix (quotient inquir-expon gcd
))
157 (t (div inquir-expon gcd
)))))
158 (cond ((and (integerp pw2
) (equal pw2
1))
159 (let ((new-exp (power (cadar p
) pw1
)))
160 (return (or (query-const-table new-exp
)
161 (log-const new-exp newconst
)))))
162 ((and (integerp pw1
) (equal pw1
1))
163 (let ((inc (new-name newconst
)))
164 (rplaca (cddar p
) (power inc pw2
))
165 (rplacd follow
(append `(((mequal simp
) ,inc
,x
)) p
))
167 (t (let ((inc (new-name nil
)))
168 (rplaca (cddar p
) (power inc pw2
))
169 (rplacd follow
(append `(((mequal simp
) ,inc
,(power xbase gcd
))) p
))
170 (return (log-const (power inc pw1
) newconst
)))))))))))))))))
171 (($constantp x
) (obtain-constant x newconst
))
173 (let ((opr (caar x
)))
174 (cond ((member opr
'(mtimes mplus
) :test
#'eq
)
175 (let* ((product (eq opr
'mtimes
))
176 (negative (and product
(equal (cadr x
) -
1))))
177 (or (and negative
(null (cdddr x
))
178 (let ((new?
(query-const-table (caddr x
))))
179 (and new?
(mul -
1 new?
))))
180 (do ((next (cdr x
) (cdr next
))
185 (cond ((and product
(= (length new
) 2) (equal (car new
) -
1))
186 (muln (nconc new non-constants
) nil
))
188 (let ((nc (obtain-constant (cond (product (muln new nil
))
191 (cond ((not product
) (addn `(,.non-constants
,nc
) nil
))
192 ((atom nc
) (muln `(,.non-constants
,nc
) nil
))
193 (t (muln (nconc (cdr nc
) non-constants
) nil
)))))
194 ((or new non-constants
)
195 (let ((tot (nconc new non-constants
)))
196 (cond (product (muln tot nil
))
197 (t (addn tot nil
)))))
199 (declare (fixnum itot
))
200 (let* ((exam (car next
))
201 (result (reduce-constants exam
)))
202 (cond ((eq exam result
)
203 (cond (($constantp exam
)
206 (cond (negative (> itot
2))
208 (do ((seplist (cdr x
) (cdr seplist
)))
210 (let ((element (car seplist
)))
211 (cond (($constantp element
)
212 (setq new
`(,.new
,element
)))
213 (t (setq non-constants
`(,.non-constants
,element
)))))))
214 (and new
(setq new
`(,.new
,exam
))))
215 ((or new non-constants
) (setq non-constants
`(,.non-constants
,exam
)))))
217 (or new non-constants
218 (do ((seplist (cdr x
) (cdr seplist
)))
220 (let ((element (car seplist
)))
221 (cond (($constantp element
)
222 (setq new
`(,.new
,element
)))
223 (t (setq non-constants
`(,.non-constants
,element
)))))))
224 (cond ((or (atom result
) (minus-constantp result
))
226 (cond ((or (atom result
) (not product
)) `(,.new
,result
))
228 (let ((number?
(car new
)))
229 (cond (($numberp number?
)
230 (let ((new-prod (mul number? result
)))
231 (cond ((mtimesp new-prod
)
232 (nconc (cdr new-prod
) (ncons new-prod
)))
233 (t (nconc (cdr new
) (ncons new-prod
))))))
234 (t (nconc (cdr result
) new
))))))))
235 (t (setq non-constants
`(,.non-constants
,result
)))))))))))
237 (do ((next (cdr x
) (cdr next
))
241 ((not (eq opr
'mquotient
))
242 (nconc (ncons (car x
)) new
))
244 (let ((cnum (find-constant (car new
)))
245 (cden (find-constant (cadr new
))))
246 (cond ((and cnum cden
)
247 (let* ((ratio (obtain-constant (div cnum cden
) newconst
))
248 (numerator (cond ((mtimesp (car new
))
249 (mul ratio
(remove cnum
(car new
) :test
#'eq
)))
251 (cond ((mtimesp (cadr new
))
252 (div numerator
(muln (remove cden
(cdadr new
) :test
#'eq
) nil
)))
255 (let* ((exam (car next
))
256 (result (reduce-constants exam
)))
257 (cond ((eq exam result
)
258 (and new
(setq new
`(,.new
,exam
))))
261 (do ((copy (cdr x
) (cdr copy
)))
263 (setq new
`(,.new
,(car copy
)))))
264 (setq new
`(,.new
,result
))))))))))))
266 (defun $reduce_consts
(x &optional newconstant
)
268 (t (reduce-constants x newconstant
))))