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
)
13 #-gcl
(:load-toplevel
:execute
)
14 (or (get 'expens
'version
)
17 (defmvar $const_eqns
(list '(mlist simp
))
18 "List of equations of constant expressions found by REDUCE_CONSTS."
19 modified-commands
'$reduce_consts
)
21 (defmvar $const_prefix
'$xx
22 "String used to prefix all symbols generated by REDUCE_CONSTS to
23 represent constant expressions."
24 modified-commands
'$reduce_consts
)
26 (defmvar $const_counter
1
27 "Integer index used to uniquely identify all constant expressions
28 found by calling REDUCE_CONSTS."
30 modified-commands
'$reduce_consts
)
32 (defmacro minus-constantp
(x)
33 `(and (eq (caar ,x
) 'mtimes
)
35 (equal (cadr ,x
) -
1)))
37 (defun query-const-table (x)
38 (do ((p (cdr $const_eqns
) (cdr p
)))
40 (and (alike1 (caddar p
) x
)
43 (defun new-name (default-name)
44 (let ((name (or default-name
46 (implode (nconc (exploden $const_prefix
)
47 (exploden $const_counter
)))
48 (incf $const_counter
)))))
49 (MFUNCALL '$declare name
'$constant
)
52 (defun log-const (exp name
)
53 (let ((inconst (new-name name
)))
54 (setq $const_eqns
`(,.$const_eqns
,`((mequal simp
) ,inconst
,exp
)))
57 (defun obtain-constant (key curr-const
)
59 (or (query-const-table key
)
60 (do ((pursue (cdr $const_eqns
) (cdr pursue
))
64 (expense ($expense key
))
65 (negative (mul -
1 key
))
70 (cond ((eq op
'sum
) (add (cadar pointer
) hold
))
71 ((eq op
'neg
) (mul -
1 (add (cadar pointer
) hold
)))
72 (t (mul (cadar pointer
) hold
))))
73 (do ((recheck (cdr $const_eqns
) (cdr recheck
))
74 (minkey (mul -
1 inkey
)))
76 (let ((exp (caddar recheck
))
77 (lab (cadar recheck
)))
78 (cond ((alike1 exp inkey
) (return lab
))
80 (return (mul -
1 lab
))))))))
81 (let ((rhs (caddar pursue
)))
82 (cond ((alike1 negative rhs
) (return (mul -
1 (cadar pursue
))))
85 (let ((trial (sub key rhs
))
86 (trial-2 (sub negative rhs
)))
87 (let ((estim (1+ ($expense trial
)))
88 (estim-2 (1+ ($expense trial-2
))))
89 (cond ((< estim estim-2
)
90 (and (< estim expense
)
96 (and (< estim-2 expense
)
102 (let* ((trial (div key rhs
))
103 (estim (1+ ($expense trial
))))
104 (and (< estim expense
)
109 (log-const inkey curr-const
))))
111 (defun find-constant (x)
112 (cond ((and (symbolp x
) ($constantp x
)) x
)
114 (do ((fcon x
(cdr fcon
)))
116 (let ((qcon (cadr fcon
)))
117 (and (symbolp qcon
) ($constantp qcon
) (return qcon
)))))
120 (defun reduce-constants (x &optional newconst
)
121 (cond ((or ($mapatom x
)
122 (and (eq (caar x
) 'mtimes
)
127 ((query-const-table x
))
128 ((and (eq (caar x
) 'mexpt
)
130 (let ((xexpon (caddr x
)) (xbase (cadr x
)))
131 (do ((p (cdr $const_eqns
) (cdr p
))
132 (nstate (integerp xexpon
))
133 (follow $const_eqns p
))
135 (let ((obj (caddar p
)))
137 (alike1 xbase
(cadr obj
))
138 (let ((inquir-expon (caddr obj
)))
139 (let ((both-fix (and nstate
(integerp inquir-expon
))))
140 (let ((dif (cond (both-fix (- xexpon inquir-expon
))
141 (t (sub xexpon inquir-expon
))))
142 (gcd (cond (both-fix (gcd xexpon inquir-expon
))
143 (t ($gcd xexpon inquir-expon
)))))
144 (or (and (integerp dif
)
146 (let ((new-exp (mul (cadar p
) xbase
)))
147 (return (or (query-const-table new-exp
)
148 (log-const new-exp newconst
)))))
150 (let ((inc (new-name newconst
)))
151 (rplaca (cddar p
) (mul inc xbase
))
152 (rplacd follow
(append `(((mequal simp
) ,inc
,x
)) p
))
154 (or (and (integerp gcd
) (equal gcd
1))
155 (let ((pw1 (cond (both-fix (quotient xexpon gcd
))
156 (t (div xexpon gcd
))))
157 (pw2 (cond (both-fix (quotient inquir-expon gcd
))
158 (t (div inquir-expon gcd
)))))
159 (cond ((and (integerp pw2
) (equal pw2
1))
160 (let ((new-exp (power (cadar p
) pw1
)))
161 (return (or (query-const-table new-exp
)
162 (log-const new-exp newconst
)))))
163 ((and (integerp pw1
) (equal pw1
1))
164 (let ((inc (new-name newconst
)))
165 (rplaca (cddar p
) (power inc pw2
))
166 (rplacd follow
(append `(((mequal simp
) ,inc
,x
)) p
))
168 (t (let ((inc (new-name nil
)))
169 (rplaca (cddar p
) (power inc pw2
))
170 (rplacd follow
(append `(((mequal simp
) ,inc
,(power xbase gcd
))) p
))
171 (return (log-const (power inc pw1
) newconst
)))))))))))))))))
172 (($constantp x
) (obtain-constant x newconst
))
174 (let ((opr (caar x
)))
175 (cond ((member opr
'(mtimes mplus
) :test
#'eq
)
176 (let* ((product (eq opr
'mtimes
))
177 (negative (and product
(equal (cadr x
) -
1))))
178 (or (and negative
(null (cdddr x
))
179 (let ((new?
(query-const-table (caddr x
))))
180 (and new?
(mul -
1 new?
))))
181 (do ((next (cdr x
) (cdr next
))
186 (cond ((and product
(= (length new
) 2) (equal (car new
) -
1))
187 (muln (nconc new non-constants
) nil
))
189 (let ((nc (obtain-constant (cond (product (muln new nil
))
192 (cond ((not product
) (addn `(,.non-constants
,nc
) nil
))
193 ((atom nc
) (muln `(,.non-constants
,nc
) nil
))
194 (t (muln (nconc (cdr nc
) non-constants
) nil
)))))
195 ((or new non-constants
)
196 (let ((tot (nconc new non-constants
)))
197 (cond (product (muln tot nil
))
198 (t (addn tot nil
)))))
200 (declare (fixnum itot
))
201 (let* ((exam (car next
))
202 (result (reduce-constants exam
)))
203 (cond ((eq exam result
)
204 (cond (($constantp exam
)
207 (cond (negative (> itot
2))
209 (do ((seplist (cdr x
) (cdr seplist
)))
211 (let ((element (car seplist
)))
212 (cond (($constantp element
)
213 (setq new
`(,.new
,element
)))
214 (t (setq non-constants
`(,.non-constants
,element
)))))))
215 (and new
(setq new
`(,.new
,exam
))))
216 ((or new non-constants
) (setq non-constants
`(,.non-constants
,exam
)))))
218 (or new non-constants
219 (do ((seplist (cdr x
) (cdr seplist
)))
221 (let ((element (car seplist
)))
222 (cond (($constantp element
)
223 (setq new
`(,.new
,element
)))
224 (t (setq non-constants
`(,.non-constants
,element
)))))))
225 (cond ((or (atom result
) (minus-constantp result
))
227 (cond ((or (atom result
) (not product
)) `(,.new
,result
))
229 (let ((number?
(car new
)))
230 (cond (($numberp number?
)
231 (let ((new-prod (mul number? result
)))
232 (cond ((mtimesp new-prod
)
233 (nconc (cdr new-prod
) (ncons new-prod
)))
234 (t (nconc (cdr new
) (ncons new-prod
))))))
235 (t (nconc (cdr result
) new
))))))))
236 (t (setq non-constants
`(,.non-constants
,result
)))))))))))
238 (do ((next (cdr x
) (cdr next
))
242 ((not (eq opr
'mquotient
))
243 (nconc (ncons (car x
)) new
))
245 (let ((cnum (find-constant (car new
)))
246 (cden (find-constant (cadr new
))))
247 (cond ((and cnum cden
)
248 (let* ((ratio (obtain-constant (div cnum cden
) newconst
))
249 (numerator (cond ((mtimesp (car new
))
250 (mul ratio
(remove cnum
(car new
) :test
#'eq
)))
252 (cond ((mtimesp (cadr new
))
253 (div numerator
(muln (remove cden
(cdadr new
) :test
#'eq
) nil
)))
256 (let* ((exam (car next
))
257 (result (reduce-constants exam
)))
258 (cond ((eq exam result
)
259 (and new
(setq new
`(,.new
,exam
))))
262 (do ((copy (cdr x
) (cdr copy
)))
264 (setq new
`(,.new
,(car copy
)))))
265 (setq new
`(,.new
,result
))))))))))))
267 (defun $reduce_consts
(x &optional newconstant
)
269 (t (reduce-constants x newconstant
))))