calc-rewr.el 72 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111
  1. ;;; calc-rewr.el --- rewriting functions for Calc
  2. ;; Copyright (C) 1990-1993, 2001-2012 Free Software Foundation, Inc.
  3. ;; Author: David Gillespie <daveg@synaptics.com>
  4. ;; Maintainer: Jay Belanger <jay.p.belanger@gmail.com>
  5. ;; This file is part of GNU Emacs.
  6. ;; GNU Emacs is free software: you can redistribute it and/or modify
  7. ;; it under the terms of the GNU General Public License as published by
  8. ;; the Free Software Foundation, either version 3 of the License, or
  9. ;; (at your option) any later version.
  10. ;; GNU Emacs is distributed in the hope that it will be useful,
  11. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ;; GNU General Public License for more details.
  14. ;; You should have received a copy of the GNU General Public License
  15. ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
  16. ;;; Commentary:
  17. ;;; Code:
  18. ;; This file is autoloaded from calc-ext.el.
  19. (require 'calc-ext)
  20. (require 'calc-macs)
  21. (defvar math-rewrite-default-iters 100)
  22. ;; The variable calc-rewr-sel is local to calc-rewrite-selection and
  23. ;; calc-rewrite, but is used by calc-locate-selection-marker.
  24. (defvar calc-rewr-sel)
  25. (defun calc-rewrite-selection (rules-str &optional many prefix)
  26. (interactive "sRewrite rule(s): \np")
  27. (calc-slow-wrapper
  28. (calc-preserve-point)
  29. (let* ((num (max 1 (calc-locate-cursor-element (point))))
  30. (reselect t)
  31. (pop-rules nil)
  32. rules
  33. (entry (calc-top num 'entry))
  34. (expr (car entry))
  35. (calc-rewr-sel (calc-auto-selection entry))
  36. (math-rewrite-selections t)
  37. (math-rewrite-default-iters 1))
  38. (if (or (null rules-str) (equal rules-str "") (equal rules-str "$"))
  39. (if (= num 1)
  40. (error "Can't use same stack entry for formula and rules")
  41. (setq rules (calc-top-n 1 t)
  42. pop-rules t))
  43. (setq rules (if (stringp rules-str)
  44. (math-read-exprs rules-str) rules-str))
  45. (if (eq (car-safe rules) 'error)
  46. (error "Bad format in expression: %s" (nth 1 rules)))
  47. (if (= (length rules) 1)
  48. (setq rules (car rules))
  49. (setq rules (cons 'vec rules)))
  50. (or (memq (car-safe rules) '(vec var calcFunc-assign
  51. calcFunc-condition))
  52. (let ((rhs (math-read-expr
  53. (read-string (concat "Rewrite from: " rules-str
  54. " to: ")))))
  55. (if (eq (car-safe rhs) 'error)
  56. (error "Bad format in expression: %s" (nth 1 rhs)))
  57. (setq rules (list 'calcFunc-assign rules rhs))))
  58. (or (eq (car-safe rules) 'var)
  59. (calc-record rules "rule")))
  60. (if (eq many 0)
  61. (setq many '(var inf var-inf))
  62. (if many (setq many (prefix-numeric-value many))))
  63. (if calc-rewr-sel
  64. (setq expr (calc-replace-sub-formula (car entry)
  65. calc-rewr-sel
  66. (list 'calcFunc-select calc-rewr-sel)))
  67. (setq expr (car entry)
  68. reselect nil
  69. math-rewrite-selections nil))
  70. (setq expr (calc-encase-atoms
  71. (calc-normalize
  72. (math-rewrite
  73. (calc-normalize expr)
  74. rules many)))
  75. calc-rewr-sel nil
  76. expr (calc-locate-select-marker expr))
  77. (or (consp calc-rewr-sel) (setq calc-rewr-sel nil))
  78. (if pop-rules (calc-pop-stack 1))
  79. (calc-pop-push-record-list 1 (or prefix "rwrt") (list expr)
  80. (- num (if pop-rules 1 0))
  81. (list (and reselect calc-rewr-sel))))
  82. (calc-handle-whys)))
  83. (defun calc-locate-select-marker (expr)
  84. (if (Math-primp expr)
  85. expr
  86. (if (and (eq (car expr) 'calcFunc-select)
  87. (= (length expr) 2))
  88. (progn
  89. (setq calc-rewr-sel (if calc-rewr-sel t (nth 1 expr)))
  90. (nth 1 expr))
  91. (cons (car expr)
  92. (mapcar 'calc-locate-select-marker (cdr expr))))))
  93. (defun calc-rewrite (rules-str many)
  94. (interactive "sRewrite rule(s): \nP")
  95. (calc-slow-wrapper
  96. (let (n rules expr)
  97. (if (or (null rules-str) (equal rules-str "") (equal rules-str "$"))
  98. (setq expr (calc-top-n 2)
  99. rules (calc-top-n 1 t)
  100. n 2)
  101. (setq rules (if (stringp rules-str)
  102. (math-read-exprs rules-str) rules-str))
  103. (if (eq (car-safe rules) 'error)
  104. (error "Bad format in expression: %s" (nth 1 rules)))
  105. (if (= (length rules) 1)
  106. (setq rules (car rules))
  107. (setq rules (cons 'vec rules)))
  108. (or (memq (car-safe rules) '(vec var calcFunc-assign
  109. calcFunc-condition))
  110. (let ((rhs (math-read-expr
  111. (read-string (concat "Rewrite from: " rules-str
  112. " to: ")))))
  113. (if (eq (car-safe rhs) 'error)
  114. (error "Bad format in expression: %s" (nth 1 rhs)))
  115. (setq rules (list 'calcFunc-assign rules rhs))))
  116. (or (eq (car-safe rules) 'var)
  117. (calc-record rules "rule"))
  118. (setq expr (calc-top-n 1)
  119. n 1))
  120. (if (eq many 0)
  121. (setq many '(var inf var-inf))
  122. (if many (setq many (prefix-numeric-value many))))
  123. (setq expr (calc-normalize (math-rewrite expr rules many)))
  124. (let (calc-rewr-sel)
  125. (setq expr (calc-locate-select-marker expr)))
  126. (calc-pop-push-record-list n "rwrt" (list expr)))
  127. (calc-handle-whys)))
  128. (defun calc-match (pat &optional interactive)
  129. (interactive "sPattern: \np")
  130. (calc-slow-wrapper
  131. (let (n expr)
  132. (if (or (null pat) (equal pat "") (equal pat "$"))
  133. (setq expr (calc-top-n 2)
  134. pat (calc-top-n 1)
  135. n 2)
  136. (setq pat (if (stringp pat) (math-read-expr pat) pat))
  137. (if (eq (car-safe pat) 'error)
  138. (error "Bad format in expression: %s" (nth 1 pat)))
  139. (if (not (eq (car-safe pat) 'var))
  140. (calc-record pat "pat"))
  141. (setq expr (calc-top-n 1)
  142. n 1))
  143. (or (math-vectorp expr) (error "Argument must be a vector"))
  144. (if (calc-is-inverse)
  145. (calc-enter-result n "mtcn" (math-match-patterns pat expr t))
  146. (calc-enter-result n "mtch" (math-match-patterns pat expr nil))))))
  147. (defvar math-mt-many)
  148. ;; The variable math-rewrite-whole-expr is local to math-rewrite,
  149. ;; but is used by math-rewrite-phase
  150. (defvar math-rewrite-whole-expr)
  151. (defun math-rewrite (math-rewrite-whole-expr rules &optional math-mt-many)
  152. (let* ((crules (math-compile-rewrites rules))
  153. (heads (math-rewrite-heads math-rewrite-whole-expr))
  154. (trace-buffer (get-buffer "*Trace*"))
  155. (calc-display-just 'center)
  156. (calc-display-origin 39)
  157. (calc-line-breaking 78)
  158. (calc-line-numbering nil)
  159. (calc-show-selections t)
  160. (calc-why nil)
  161. (math-mt-func (function
  162. (lambda (x)
  163. (let ((result (math-apply-rewrites x (cdr crules)
  164. heads crules)))
  165. (if result
  166. (progn
  167. (if trace-buffer
  168. (let ((fmt (math-format-stack-value
  169. (list result nil nil))))
  170. (with-current-buffer trace-buffer
  171. (insert "\nrewrite to\n" fmt "\n"))))
  172. (setq heads (math-rewrite-heads result heads t))))
  173. result)))))
  174. (if trace-buffer
  175. (let ((fmt (math-format-stack-value (list math-rewrite-whole-expr nil nil))))
  176. (with-current-buffer trace-buffer
  177. (setq truncate-lines t)
  178. (goto-char (point-max))
  179. (insert "\n\nBegin rewriting\n" fmt "\n"))))
  180. (or math-mt-many (setq math-mt-many (or (nth 1 (car crules))
  181. math-rewrite-default-iters)))
  182. (if (equal math-mt-many '(var inf var-inf)) (setq math-mt-many 1000000))
  183. (if (equal math-mt-many '(neg (var inf var-inf))) (setq math-mt-many -1000000))
  184. (math-rewrite-phase (nth 3 (car crules)))
  185. (if trace-buffer
  186. (let ((fmt (math-format-stack-value (list math-rewrite-whole-expr nil nil))))
  187. (with-current-buffer trace-buffer
  188. (insert "\nDone rewriting"
  189. (if (= math-mt-many 0) " (reached iteration limit)" "")
  190. ":\n" fmt "\n"))))
  191. math-rewrite-whole-expr))
  192. (defun math-rewrite-phase (sched)
  193. (while (and sched (/= math-mt-many 0))
  194. (if (listp (car sched))
  195. (while (let ((save-expr math-rewrite-whole-expr))
  196. (math-rewrite-phase (car sched))
  197. (not (equal math-rewrite-whole-expr save-expr))))
  198. (if (symbolp (car sched))
  199. (progn
  200. (setq math-rewrite-whole-expr
  201. (math-normalize (list (car sched) math-rewrite-whole-expr)))
  202. (if trace-buffer
  203. (let ((fmt (math-format-stack-value
  204. (list math-rewrite-whole-expr nil nil))))
  205. (with-current-buffer trace-buffer
  206. (insert "\ncall "
  207. (substring (symbol-name (car sched)) 9)
  208. ":\n" fmt "\n")))))
  209. (let ((math-rewrite-phase (car sched)))
  210. (if trace-buffer
  211. (with-current-buffer trace-buffer
  212. (insert (format "\n(Phase %d)\n" math-rewrite-phase))))
  213. (while (let ((save-expr math-rewrite-whole-expr))
  214. (setq math-rewrite-whole-expr (math-normalize
  215. (math-map-tree-rec math-rewrite-whole-expr)))
  216. (not (equal math-rewrite-whole-expr save-expr)))))))
  217. (setq sched (cdr sched))))
  218. (defun calcFunc-rewrite (expr rules &optional many)
  219. (or (null many) (integerp many)
  220. (equal many '(var inf var-inf)) (equal many '(neg (var inf var-inf)))
  221. (math-reject-arg many 'fixnump))
  222. (condition-case err
  223. (math-rewrite expr rules (or many 1))
  224. (error (math-reject-arg rules (nth 1 err)))))
  225. (defun calcFunc-match (pat vec)
  226. (or (math-vectorp vec) (math-reject-arg vec 'vectorp))
  227. (condition-case err
  228. (math-match-patterns pat vec nil)
  229. (error (math-reject-arg pat (nth 1 err)))))
  230. (defun calcFunc-matchnot (pat vec)
  231. (or (math-vectorp vec) (math-reject-arg vec 'vectorp))
  232. (condition-case err
  233. (math-match-patterns pat vec t)
  234. (error (math-reject-arg pat (nth 1 err)))))
  235. (defun math-match-patterns (pat vec &optional not-flag)
  236. (let ((newvec nil)
  237. (crules (math-compile-patterns pat)))
  238. (while (setq vec (cdr vec))
  239. (if (eq (not (math-apply-rewrites (car vec) crules))
  240. not-flag)
  241. (setq newvec (cons (car vec) newvec))))
  242. (cons 'vec (nreverse newvec))))
  243. (defun calcFunc-matches (expr pat)
  244. (condition-case err
  245. (if (math-apply-rewrites expr (math-compile-patterns pat))
  246. 1
  247. 0)
  248. (error (math-reject-arg pat (nth 1 err)))))
  249. (defun calcFunc-vmatches (expr pat)
  250. (condition-case err
  251. (or (math-apply-rewrites expr (math-compile-patterns pat))
  252. 0)
  253. (error (math-reject-arg pat (nth 1 err)))))
  254. ;; A compiled rule set is an a-list of entries whose cars are functors,
  255. ;; and whose cdrs are lists of rules. If there are rules with no
  256. ;; well-defined head functor, they are included on all lists and also
  257. ;; on an extra list whose car is nil.
  258. ;;
  259. ;; The first entry in the a-list is of the form (schedule A B C ...).
  260. ;;
  261. ;; Rule list entries take the form (regs prog head phases), where:
  262. ;;
  263. ;; regs is a vector of match registers.
  264. ;;
  265. ;; prog is a match program (see below).
  266. ;;
  267. ;; head is a rare function name appearing in the rule body (but not the
  268. ;; head of the whole rule), or nil if none.
  269. ;;
  270. ;; phases is a list of phase numbers for which the rule is enabled.
  271. ;;
  272. ;; A match program is a list of match instructions.
  273. ;;
  274. ;; In the following, "part" is a register number that contains the
  275. ;; subexpression to be operated on.
  276. ;;
  277. ;; Register 0 is the whole expression being matched. The others are
  278. ;; meta-variables in the pattern, temporaries used for matching and
  279. ;; backtracking, and constant expressions.
  280. ;;
  281. ;; (same part reg)
  282. ;; The selected part must be math-equal to the contents of "reg".
  283. ;;
  284. ;; (same-neg part reg)
  285. ;; The selected part must be math-equal to the negative of "reg".
  286. ;;
  287. ;; (copy part reg)
  288. ;; The selected part is copied into "reg". (Rarely used.)
  289. ;;
  290. ;; (copy-neg part reg)
  291. ;; The negative of the selected part is copied into "reg".
  292. ;;
  293. ;; (integer part)
  294. ;; The selected part must be an integer.
  295. ;;
  296. ;; (real part)
  297. ;; The selected part must be a real.
  298. ;;
  299. ;; (constant part)
  300. ;; The selected part must be a constant.
  301. ;;
  302. ;; (negative part)
  303. ;; The selected part must "look" negative.
  304. ;;
  305. ;; (rel part op reg)
  306. ;; The selected part must satisfy "part op reg", where "op"
  307. ;; is one of the 6 relational ops, and "reg" is a register.
  308. ;;
  309. ;; (mod part modulo value)
  310. ;; The selected part must satisfy "part % modulo = value", where
  311. ;; "modulo" and "value" are constants.
  312. ;;
  313. ;; (func part head reg1 reg2 ... regn)
  314. ;; The selected part must be an n-ary call to function "head".
  315. ;; The arguments are stored in "reg1" through "regn".
  316. ;;
  317. ;; (func-def part head defs reg1 reg2 ... regn)
  318. ;; The selected part must be an n-ary call to function "head".
  319. ;; "Defs" is a list of value/register number pairs for default args.
  320. ;; If a match, assign default values to registers and then skip
  321. ;; immediately over any following "func-def" instructions and
  322. ;; the following "func" instruction. If wrong number of arguments,
  323. ;; proceed to the following "func-def" or "func" instruction.
  324. ;;
  325. ;; (func-opt part head defs reg1)
  326. ;; Like func-def with "n=1", except that if the selected part is
  327. ;; not a call to "head", then the part itself successfully matches
  328. ;; "reg1" (and the defaults are assigned).
  329. ;;
  330. ;; (try part heads mark reg1 [def])
  331. ;; The selected part must be a function of the correct type which is
  332. ;; associative and/or commutative. "Heads" is a list of acceptable
  333. ;; types. An initial assignment of arguments to "reg1" is tried.
  334. ;; If the program later fails, it backtracks to this instruction
  335. ;; and tries other assignments of arguments to "reg1".
  336. ;; If "def" exists and normal matching fails, backtrack and assign
  337. ;; "part" to "reg1", and "def" to "reg2" in the following "try2".
  338. ;; The "mark" is a vector of size 5; only "mark[3-4]" are initialized.
  339. ;; "mark[0]" points to the argument list; "mark[1]" points to the
  340. ;; current argument; "mark[2]" is 0 if there are two arguments,
  341. ;; 1 if reg1 is matching single arguments, 2 if reg2 is matching
  342. ;; single arguments (a+b+c+d is never split as (a+b)+(c+d)), or
  343. ;; 3 if reg2 is matching "def"; "mark[3]" is 0 if the function must
  344. ;; have two arguments, 1 if phase-2 can be skipped, 2 if full
  345. ;; backtracking is necessary; "mark[4]" is t if the arguments have
  346. ;; been switched from the order given in the original pattern.
  347. ;;
  348. ;; (try2 try reg2)
  349. ;; Every "try" will be followed by a "try2" whose "try" field is
  350. ;; a pointer to the corresponding "try". The arguments which were
  351. ;; not stored in "reg1" by that "try" are now stored in "reg2".
  352. ;;
  353. ;; (alt instr nil mark)
  354. ;; Basic backtracking. Execute the instruction sequence "instr".
  355. ;; If this fails, back up and execute following the "alt" instruction.
  356. ;; The "mark" must be the vector "[nil nil 4]". The "instr" sequence
  357. ;; should execute "end-alt" at the end.
  358. ;;
  359. ;; (end-alt ptr)
  360. ;; Register success of the first alternative of a previous "alt".
  361. ;; "Ptr" is a pointer to the next instruction following that "alt".
  362. ;;
  363. ;; (apply part reg1 reg2)
  364. ;; The selected part must be a function call. The functor
  365. ;; (as a variable name) is stored in "reg1"; the arguments
  366. ;; (as a vector) are stored in "reg2".
  367. ;;
  368. ;; (cons part reg1 reg2)
  369. ;; The selected part must be a nonempty vector. The first element
  370. ;; of the vector is stored in "reg1"; the rest of the vector
  371. ;; (as another vector) is stored in "reg2".
  372. ;;
  373. ;; (rcons part reg1 reg2)
  374. ;; The selected part must be a nonempty vector. The last element
  375. ;; of the vector is stored in "reg2"; the rest of the vector
  376. ;; (as another vector) is stored in "reg1".
  377. ;;
  378. ;; (select part reg)
  379. ;; If the selected part is a unary call to function "select", its
  380. ;; argument is stored in "reg"; otherwise (provided this is an `a r'
  381. ;; and not a `g r' command) the selected part is stored in "reg".
  382. ;;
  383. ;; (cond expr)
  384. ;; The "expr", with registers substituted, must simplify to
  385. ;; a non-zero value.
  386. ;;
  387. ;; (let reg expr)
  388. ;; Evaluate "expr" and store the result in "reg". Always succeeds.
  389. ;;
  390. ;; (done rhs remember)
  391. ;; Rewrite the expression to "rhs", with register substituted.
  392. ;; Normalize; if the result is different from the original
  393. ;; expression, the match has succeeded. This is the last
  394. ;; instruction of every program. If "remember" is non-nil,
  395. ;; record the result of the match as a new literal rule.
  396. ;; Pseudo-functions related to rewrites:
  397. ;;
  398. ;; In patterns: quote, plain, condition, opt, apply, cons, select
  399. ;;
  400. ;; In righthand sides: quote, plain, eval, evalsimp, evalextsimp,
  401. ;; apply, cons, select
  402. ;;
  403. ;; In conditions: let + same as for righthand sides
  404. ;; Some optimizations that would be nice to have:
  405. ;;
  406. ;; * Merge registers with disjoint lifetimes.
  407. ;; * Merge constant registers with equivalent values.
  408. ;;
  409. ;; * If an argument of a commutative op math-depends neither on the
  410. ;; rest of the pattern nor on any of the conditions, then no backtracking
  411. ;; should be done for that argument. (This won't apply to very many
  412. ;; cases.)
  413. ;;
  414. ;; * If top functor is "select", and its argument is a unique function,
  415. ;; add the rule to the lists for both "select" and that function.
  416. ;; (Currently rules like this go on the "nil" list.)
  417. ;; Same for "func-opt" functions. (Though not urgent for these.)
  418. ;;
  419. ;; * Shouldn't evaluate a "let" condition until the end, or until it
  420. ;; would enable another condition to be evaluated.
  421. ;;
  422. ;; Some additional features to add / things to think about:
  423. ;;;
  424. ;;; * Figure out what happens to "a +/- b" and "a +/- opt(b)".
  425. ;;;
  426. ;;; * Same for interval forms.
  427. ;;;
  428. ;;; * Have a name(v,pat) pattern which matches pat, and gives the
  429. ;;; whole match the name v. Beware of circular structures!
  430. ;;;
  431. (defun math-compile-patterns (pats)
  432. (if (and (eq (car-safe pats) 'var)
  433. (calc-var-value (nth 2 pats)))
  434. (let ((prop (get (nth 2 pats) 'math-pattern-cache)))
  435. (or prop
  436. (put (nth 2 pats) 'math-pattern-cache (setq prop (list nil))))
  437. (or (eq (car prop) (symbol-value (nth 2 pats)))
  438. (progn
  439. (setcdr prop (math-compile-patterns
  440. (symbol-value (nth 2 pats))))
  441. (setcar prop (symbol-value (nth 2 pats)))))
  442. (cdr prop))
  443. (let ((math-rewrite-whole t))
  444. (cdr (math-compile-rewrites (cons
  445. 'vec
  446. (mapcar (function (lambda (x)
  447. (list 'vec x t)))
  448. (if (eq (car-safe pats) 'vec)
  449. (cdr pats)
  450. (list pats)))))))))
  451. (defvar math-rewrite-whole nil)
  452. (defvar math-make-import-list nil)
  453. ;; The variable math-import-list is local to part of math-compile-rewrites,
  454. ;; but is also used in a different part, and so the local version could
  455. ;; be affected by the non-local version when math-compile-rewrites calls itself.
  456. (defvar math-import-list nil)
  457. ;; The variables math-regs, math-num-regs, math-prog-last, math-bound-vars,
  458. ;; math-conds, math-copy-neg, math-rhs, math-pattern, math-remembering and
  459. ;; math-aliased-vars are local to math-compile-rewrites,
  460. ;; but are used by many functions math-rwcomp-*, which are called by
  461. ;; math-compile-rewrites.
  462. (defvar math-regs)
  463. (defvar math-num-regs)
  464. (defvar math-prog-last)
  465. (defvar math-bound-vars)
  466. (defvar math-conds)
  467. (defvar math-copy-neg)
  468. (defvar math-rhs)
  469. (defvar math-pattern)
  470. (defvar math-remembering)
  471. (defvar math-aliased-vars)
  472. (defun math-compile-rewrites (rules &optional name)
  473. (if (eq (car-safe rules) 'var)
  474. (let ((prop (get (nth 2 rules) 'math-rewrite-cache))
  475. (math-import-list nil)
  476. (math-make-import-list t)
  477. p)
  478. (or (calc-var-value (nth 2 rules))
  479. (error "Rules variable %s has no stored value" (nth 1 rules)))
  480. (or prop
  481. (put (nth 2 rules) 'math-rewrite-cache
  482. (setq prop (list (list (cons (nth 2 rules) nil))))))
  483. (setq p (car prop))
  484. (while (and p (eq (symbol-value (car (car p))) (cdr (car p))))
  485. (setq p (cdr p)))
  486. (or (null p)
  487. (progn
  488. (message "Compiling rule set %s..." (nth 1 rules))
  489. (setcdr prop (math-compile-rewrites
  490. (symbol-value (nth 2 rules))
  491. (nth 2 rules)))
  492. (message "Compiling rule set %s...done" (nth 1 rules))
  493. (setcar prop (cons (cons (nth 2 rules)
  494. (symbol-value (nth 2 rules)))
  495. math-import-list))))
  496. (cdr prop))
  497. (if (or (not (eq (car-safe rules) 'vec))
  498. (and (memq (length rules) '(3 4))
  499. (let ((p rules))
  500. (while (and (setq p (cdr p))
  501. (memq (car-safe (car p))
  502. '(vec
  503. calcFunc-assign
  504. calcFunc-condition
  505. calcFunc-import
  506. calcFunc-phase
  507. calcFunc-schedule
  508. calcFunc-iterations))))
  509. p)))
  510. (setq rules (list rules))
  511. (setq rules (cdr rules)))
  512. (if (assq 'calcFunc-import rules)
  513. (let ((pp (setq rules (copy-sequence rules)))
  514. p part)
  515. (while (setq p (car (cdr pp)))
  516. (if (eq (car-safe p) 'calcFunc-import)
  517. (progn
  518. (setcdr pp (cdr (cdr pp)))
  519. (or (and (eq (car-safe (nth 1 p)) 'var)
  520. (setq part (calc-var-value (nth 2 (nth 1 p))))
  521. (memq (car-safe part) '(vec
  522. calcFunc-assign
  523. calcFunc-condition)))
  524. (error "Argument of import() must be a rules variable"))
  525. (if math-make-import-list
  526. (setq math-import-list
  527. (cons (cons (nth 2 (nth 1 p))
  528. (symbol-value (nth 2 (nth 1 p))))
  529. math-import-list)))
  530. (while (setq p (cdr (cdr p)))
  531. (or (cdr p)
  532. (error "import() must have odd number of arguments"))
  533. (setq part (math-rwcomp-substitute part
  534. (car p) (nth 1 p))))
  535. (if (eq (car-safe part) 'vec)
  536. (setq part (cdr part))
  537. (setq part (list part)))
  538. (setcdr pp (append part (cdr pp))))
  539. (setq pp (cdr pp))))))
  540. (let ((rule-set nil)
  541. (all-heads nil)
  542. (nil-rules nil)
  543. (rule-count 0)
  544. (math-schedule nil)
  545. (math-iterations nil)
  546. (math-phases nil)
  547. (math-all-phases nil)
  548. (math-remembering nil)
  549. math-pattern math-rhs math-conds)
  550. (while rules
  551. (cond
  552. ((and (eq (car-safe (car rules)) 'calcFunc-iterations)
  553. (= (length (car rules)) 2))
  554. (or (integerp (nth 1 (car rules)))
  555. (equal (nth 1 (car rules)) '(var inf var-inf))
  556. (equal (nth 1 (car rules)) '(neg (var inf var-inf)))
  557. (error "Invalid argument for iterations(n)"))
  558. (or math-iterations
  559. (setq math-iterations (nth 1 (car rules)))))
  560. ((eq (car-safe (car rules)) 'calcFunc-schedule)
  561. (or math-schedule
  562. (setq math-schedule (math-parse-schedule (cdr (car rules))))))
  563. ((eq (car-safe (car rules)) 'calcFunc-phase)
  564. (setq math-phases (cdr (car rules)))
  565. (if (equal math-phases '((var all var-all)))
  566. (setq math-phases nil))
  567. (let ((p math-phases))
  568. (while p
  569. (or (integerp (car p))
  570. (error "Phase numbers must be small integers"))
  571. (or (memq (car p) math-all-phases)
  572. (setq math-all-phases (cons (car p) math-all-phases)))
  573. (setq p (cdr p)))))
  574. ((or (and (eq (car-safe (car rules)) 'vec)
  575. (cdr (cdr (car rules)))
  576. (not (nthcdr 4 (car rules)))
  577. (setq math-conds (nth 3 (car rules))
  578. math-rhs (nth 2 (car rules))
  579. math-pattern (nth 1 (car rules))))
  580. (progn
  581. (setq math-conds nil
  582. math-pattern (car rules))
  583. (while (and (eq (car-safe math-pattern) 'calcFunc-condition)
  584. (= (length math-pattern) 3))
  585. (let ((cond (nth 2 math-pattern)))
  586. (setq math-conds (if math-conds
  587. (list 'calcFunc-land math-conds cond)
  588. cond)
  589. math-pattern (nth 1 math-pattern))))
  590. (and (eq (car-safe math-pattern) 'calcFunc-assign)
  591. (= (length math-pattern) 3)
  592. (setq math-rhs (nth 2 math-pattern)
  593. math-pattern (nth 1 math-pattern)))))
  594. (let* ((math-prog (list nil))
  595. (math-prog-last math-prog)
  596. (math-num-regs 1)
  597. (math-regs (list (list nil 0 nil nil)))
  598. (math-bound-vars nil)
  599. (math-aliased-vars nil)
  600. (math-copy-neg nil))
  601. (setq math-conds (and math-conds (math-flatten-lands math-conds)))
  602. (math-rwcomp-pattern math-pattern 0)
  603. (while math-conds
  604. (let ((expr (car math-conds)))
  605. (setq math-conds (cdr math-conds))
  606. (math-rwcomp-cond-instr expr)))
  607. (math-rwcomp-instr 'done
  608. (if (eq math-rhs t)
  609. (cons 'vec
  610. (delq
  611. nil
  612. (nreverse
  613. (mapcar
  614. (function
  615. (lambda (v)
  616. (and (car v)
  617. (list
  618. 'calcFunc-assign
  619. (math-build-var-name
  620. (car v))
  621. (math-rwcomp-register-expr
  622. (nth 1 v))))))
  623. math-regs))))
  624. (math-rwcomp-match-vars math-rhs))
  625. math-remembering)
  626. (setq math-prog (cdr math-prog))
  627. (let* ((heads (math-rewrite-heads math-pattern))
  628. (rule (list (vconcat
  629. (nreverse
  630. (mapcar (function (lambda (x) (nth 3 x)))
  631. math-regs)))
  632. math-prog
  633. heads
  634. math-phases))
  635. (head (and (not (Math-primp math-pattern))
  636. (not (and (eq (car (car math-prog)) 'try)
  637. (nth 5 (car math-prog))))
  638. (not (memq (car (car math-prog)) '(func-opt
  639. apply
  640. select
  641. alt)))
  642. (if (memq (car (car math-prog)) '(func
  643. func-def))
  644. (nth 2 (car math-prog))
  645. (if (eq (car math-pattern) 'calcFunc-quote)
  646. (car-safe (nth 1 math-pattern))
  647. (car math-pattern))))))
  648. (let (found)
  649. (while heads
  650. (if (setq found (assq (car heads) all-heads))
  651. (setcdr found (1+ (cdr found)))
  652. (setq all-heads (cons (cons (car heads) 1) all-heads)))
  653. (setq heads (cdr heads))))
  654. (if (eq head '-) (setq head '+))
  655. (if (memq head '(calcFunc-cons calcFunc-rcons)) (setq head 'vec))
  656. (if head
  657. (progn
  658. (nconc (or (assq head rule-set)
  659. (car (setq rule-set (cons (cons head
  660. (copy-sequence
  661. nil-rules))
  662. rule-set))))
  663. (list rule))
  664. (if (eq head '*)
  665. (nconc (or (assq '/ rule-set)
  666. (car (setq rule-set (cons (cons
  667. '/
  668. (copy-sequence
  669. nil-rules))
  670. rule-set))))
  671. (list rule))))
  672. (setq nil-rules (nconc nil-rules (list rule)))
  673. (let ((ptr rule-set))
  674. (while ptr
  675. (nconc (car ptr) (list rule))
  676. (setq ptr (cdr ptr))))))))
  677. (t
  678. (error "Rewrite rule set must be a vector of A := B rules")))
  679. (setq rules (cdr rules)))
  680. (if nil-rules
  681. (setq rule-set (cons (cons nil nil-rules) rule-set)))
  682. (setq all-heads (mapcar 'car
  683. (sort all-heads (function
  684. (lambda (x y)
  685. (< (cdr x) (cdr y)))))))
  686. (let ((set rule-set)
  687. rule heads ptr)
  688. (while set
  689. (setq rule (cdr (car set)))
  690. (while rule
  691. (if (consp (setq heads (nth 2 (car rule))))
  692. (progn
  693. (setq heads (delq (car (car set)) heads)
  694. ptr all-heads)
  695. (while (and ptr (not (memq (car ptr) heads)))
  696. (setq ptr (cdr ptr)))
  697. (setcar (nthcdr 2 (car rule)) (car ptr))))
  698. (setq rule (cdr rule)))
  699. (setq set (cdr set))))
  700. (let ((plus (assq '+ rule-set)))
  701. (if plus
  702. (setq rule-set (cons (cons '- (cdr plus)) rule-set))))
  703. (cons (list 'schedule math-iterations name
  704. (or math-schedule
  705. (sort math-all-phases '<)
  706. (list 1)))
  707. rule-set))))
  708. (defun math-flatten-lands (expr)
  709. (if (eq (car-safe expr) 'calcFunc-land)
  710. (append (math-flatten-lands (nth 1 expr))
  711. (math-flatten-lands (nth 2 expr)))
  712. (list expr)))
  713. ;; The variables math-rewrite-heads-heads (i.e.; heads for math-rewrite-heads)
  714. ;; math-rewrite-heads-blanks and math-rewrite-heads-skips are local to
  715. ;; math-rewrite-heads, but used by math-rewrite-heads-rec, which is called by
  716. ;; math-rewrite-heads.
  717. (defvar math-rewrite-heads-heads)
  718. (defvar math-rewrite-heads-skips)
  719. (defvar math-rewrite-heads-blanks)
  720. (defun math-rewrite-heads (expr &optional more all)
  721. (let ((math-rewrite-heads-heads more)
  722. (math-rewrite-heads-skips (and (not all)
  723. '(calcFunc-apply calcFunc-condition calcFunc-opt
  724. calcFunc-por calcFunc-pnot)))
  725. (math-rewrite-heads-blanks (and (not all)
  726. '(calcFunc-quote calcFunc-plain calcFunc-select
  727. calcFunc-cons calcFunc-rcons
  728. calcFunc-pand))))
  729. (or (Math-primp expr)
  730. (math-rewrite-heads-rec expr))
  731. math-rewrite-heads-heads))
  732. (defun math-rewrite-heads-rec (expr)
  733. (or (memq (car expr) math-rewrite-heads-skips)
  734. (progn
  735. (or (memq (car expr) math-rewrite-heads-heads)
  736. (memq (car expr) math-rewrite-heads-blanks)
  737. (memq 'algebraic (get (car expr) 'math-rewrite-props))
  738. (setq math-rewrite-heads-heads (cons (car expr) math-rewrite-heads-heads)))
  739. (while (setq expr (cdr expr))
  740. (or (Math-primp (car expr))
  741. (math-rewrite-heads-rec (car expr)))))))
  742. (defun math-parse-schedule (sched)
  743. (mapcar (function
  744. (lambda (s)
  745. (if (integerp s)
  746. s
  747. (if (math-vectorp s)
  748. (math-parse-schedule (cdr s))
  749. (if (eq (car-safe s) 'var)
  750. (math-var-to-calcFunc s)
  751. (error "Improper component in rewrite schedule"))))))
  752. sched))
  753. (defun math-rwcomp-match-vars (expr)
  754. (if (Math-primp expr)
  755. (if (eq (car-safe expr) 'var)
  756. (let ((entry (assq (nth 2 expr) math-regs)))
  757. (if entry
  758. (math-rwcomp-register-expr (nth 1 entry))
  759. expr))
  760. expr)
  761. (if (and (eq (car expr) 'calcFunc-quote)
  762. (= (length expr) 2))
  763. (math-rwcomp-match-vars (nth 1 expr))
  764. (if (and (eq (car expr) 'calcFunc-plain)
  765. (= (length expr) 2)
  766. (not (Math-primp (nth 1 expr))))
  767. (list (car expr)
  768. (cons (car (nth 1 expr))
  769. (mapcar 'math-rwcomp-match-vars (cdr (nth 1 expr)))))
  770. (cons (car expr)
  771. (mapcar 'math-rwcomp-match-vars (cdr expr)))))))
  772. (defun math-rwcomp-register-expr (num)
  773. (let ((entry (nth (1- (- math-num-regs num)) math-regs)))
  774. (if (nth 2 entry)
  775. (list 'neg (list 'calcFunc-register (nth 1 entry)))
  776. (list 'calcFunc-register (nth 1 entry)))))
  777. ;; The variables math-rwcomp-subst-old, math-rwcomp-subst-new,
  778. ;; math-rwcomp-subst-old-func and math-rwcomp-subst-new-func
  779. ;; are local to math-rwcomp-substitute, but are used by
  780. ;; math-rwcomp-subst-rec, which is called by math-rwcomp-substitute.
  781. (defvar math-rwcomp-subst-new)
  782. (defvar math-rwcomp-subst-old)
  783. (defvar math-rwcomp-subst-new-func)
  784. (defvar math-rwcomp-subst-old-func)
  785. (defun math-rwcomp-substitute (expr math-rwcomp-subst-old math-rwcomp-subst-new)
  786. (if (and (eq (car-safe math-rwcomp-subst-old) 'var)
  787. (memq (car-safe math-rwcomp-subst-new) '(var calcFunc-lambda)))
  788. (let ((math-rwcomp-subst-old-func (math-var-to-calcFunc math-rwcomp-subst-old))
  789. (math-rwcomp-subst-new-func (math-var-to-calcFunc math-rwcomp-subst-new)))
  790. (math-rwcomp-subst-rec expr))
  791. (let ((math-rwcomp-subst-old-func nil))
  792. (math-rwcomp-subst-rec expr))))
  793. (defun math-rwcomp-subst-rec (expr)
  794. (cond ((equal expr math-rwcomp-subst-old) math-rwcomp-subst-new)
  795. ((Math-primp expr) expr)
  796. (t (if (eq (car expr) math-rwcomp-subst-old-func)
  797. (math-build-call math-rwcomp-subst-new-func
  798. (mapcar 'math-rwcomp-subst-rec
  799. (cdr expr)))
  800. (cons (car expr)
  801. (mapcar 'math-rwcomp-subst-rec (cdr expr)))))))
  802. (defvar math-rwcomp-tracing nil)
  803. (defun math-rwcomp-trace (instr)
  804. (when math-rwcomp-tracing
  805. (terpri) (princ instr))
  806. instr)
  807. (defun math-rwcomp-instr (&rest instr)
  808. (setcdr math-prog-last
  809. (setq math-prog-last (list (math-rwcomp-trace instr)))))
  810. (defun math-rwcomp-multi-instr (tail &rest instr)
  811. (setcdr math-prog-last
  812. (setq math-prog-last (list (math-rwcomp-trace (append instr tail))))))
  813. (defun math-rwcomp-bind-var (reg var)
  814. (setcar (math-rwcomp-reg-entry reg) (nth 2 var))
  815. (setq math-bound-vars (cons (nth 2 var) math-bound-vars))
  816. (math-rwcomp-do-conditions))
  817. (defun math-rwcomp-unbind-vars (mark)
  818. (while (not (eq math-bound-vars mark))
  819. (setcar (assq (car math-bound-vars) math-regs) nil)
  820. (setq math-bound-vars (cdr math-bound-vars))))
  821. (defun math-rwcomp-do-conditions ()
  822. (let ((cond math-conds))
  823. (while cond
  824. (if (math-rwcomp-all-regs-done (car cond))
  825. (let ((expr (car cond)))
  826. (setq math-conds (delq (car cond) math-conds))
  827. (setcar cond 1)
  828. (math-rwcomp-cond-instr expr)))
  829. (setq cond (cdr cond)))))
  830. (defun math-rwcomp-cond-instr (expr)
  831. (let (op arg)
  832. (cond ((and (eq (car-safe expr) 'calcFunc-matches)
  833. (= (length expr) 3)
  834. (eq (car-safe (setq arg (math-rwcomp-match-vars (nth 1 expr))))
  835. 'calcFunc-register))
  836. (math-rwcomp-pattern (nth 2 expr) (nth 1 arg)))
  837. ((math-numberp (setq expr (math-rwcomp-match-vars expr)))
  838. (if (Math-zerop expr)
  839. (math-rwcomp-instr 'backtrack)))
  840. ((and (eq (car expr) 'calcFunc-let)
  841. (= (length expr) 3))
  842. (let ((reg (math-rwcomp-reg)))
  843. (math-rwcomp-instr 'let reg (nth 2 expr))
  844. (math-rwcomp-pattern (nth 1 expr) reg)))
  845. ((and (eq (car expr) 'calcFunc-let)
  846. (= (length expr) 2)
  847. (eq (car-safe (nth 1 expr)) 'calcFunc-assign)
  848. (= (length (nth 1 expr)) 3))
  849. (let ((reg (math-rwcomp-reg)))
  850. (math-rwcomp-instr 'let reg (nth 2 (nth 1 expr)))
  851. (math-rwcomp-pattern (nth 1 (nth 1 expr)) reg)))
  852. ((and (setq op (cdr (assq (car-safe expr)
  853. '( (calcFunc-integer . integer)
  854. (calcFunc-real . real)
  855. (calcFunc-constant . constant)
  856. (calcFunc-negative . negative) ))))
  857. (= (length expr) 2)
  858. (or (and (eq (car-safe (nth 1 expr)) 'neg)
  859. (memq op '(integer real constant))
  860. (setq arg (nth 1 (nth 1 expr))))
  861. (setq arg (nth 1 expr)))
  862. (eq (car-safe (setq arg (nth 1 expr))) 'calcFunc-register))
  863. (math-rwcomp-instr op (nth 1 arg)))
  864. ((and (assq (car-safe expr) calc-tweak-eqn-table)
  865. (= (length expr) 3)
  866. (eq (car-safe (nth 1 expr)) 'calcFunc-register))
  867. (if (math-constp (nth 2 expr))
  868. (let ((reg (math-rwcomp-reg)))
  869. (setcar (nthcdr 3 (car math-regs)) (nth 2 expr))
  870. (math-rwcomp-instr 'rel (nth 1 (nth 1 expr))
  871. (car expr) reg))
  872. (if (eq (car (nth 2 expr)) 'calcFunc-register)
  873. (math-rwcomp-instr 'rel (nth 1 (nth 1 expr))
  874. (car expr) (nth 1 (nth 2 expr)))
  875. (math-rwcomp-instr 'cond expr))))
  876. ((and (eq (car-safe expr) 'calcFunc-eq)
  877. (= (length expr) 3)
  878. (eq (car-safe (nth 1 expr)) '%)
  879. (eq (car-safe (nth 1 (nth 1 expr))) 'calcFunc-register)
  880. (math-constp (nth 2 (nth 1 expr)))
  881. (math-constp (nth 2 expr)))
  882. (math-rwcomp-instr 'mod (nth 1 (nth 1 (nth 1 expr)))
  883. (nth 2 (nth 1 expr)) (nth 2 expr)))
  884. ((equal expr '(var remember var-remember))
  885. (setq math-remembering 1))
  886. ((and (eq (car-safe expr) 'calcFunc-remember)
  887. (= (length expr) 2))
  888. (setq math-remembering (if math-remembering
  889. (list 'calcFunc-lor
  890. math-remembering (nth 1 expr))
  891. (nth 1 expr))))
  892. (t (math-rwcomp-instr 'cond expr)))))
  893. (defun math-rwcomp-same-instr (reg1 reg2 neg)
  894. (math-rwcomp-instr (if (eq (eq (nth 2 (math-rwcomp-reg-entry reg1))
  895. (nth 2 (math-rwcomp-reg-entry reg2)))
  896. neg)
  897. 'same-neg
  898. 'same)
  899. reg1 reg2))
  900. (defun math-rwcomp-copy-instr (reg1 reg2 neg)
  901. (if (eq (eq (nth 2 (math-rwcomp-reg-entry reg1))
  902. (nth 2 (math-rwcomp-reg-entry reg2)))
  903. neg)
  904. (math-rwcomp-instr 'copy-neg reg1 reg2)
  905. (or (eq reg1 reg2)
  906. (math-rwcomp-instr 'copy reg1 reg2))))
  907. (defun math-rwcomp-reg ()
  908. (prog1
  909. math-num-regs
  910. (setq math-regs (cons (list nil math-num-regs nil 0) math-regs)
  911. math-num-regs (1+ math-num-regs))))
  912. (defun math-rwcomp-reg-entry (num)
  913. (nth (1- (- math-num-regs num)) math-regs))
  914. (defun math-rwcomp-pattern (expr part &optional not-direct)
  915. (cond ((or (math-rwcomp-no-vars expr)
  916. (and (eq (car expr) 'calcFunc-quote)
  917. (= (length expr) 2)
  918. (setq expr (nth 1 expr))))
  919. (if (eq (car-safe expr) 'calcFunc-register)
  920. (math-rwcomp-same-instr part (nth 1 expr) nil)
  921. (let ((reg (math-rwcomp-reg)))
  922. (setcar (nthcdr 3 (car math-regs)) expr)
  923. (math-rwcomp-same-instr part reg nil))))
  924. ((eq (car expr) 'var)
  925. (let ((entry (assq (nth 2 expr) math-regs)))
  926. (if entry
  927. (math-rwcomp-same-instr part (nth 1 entry) nil)
  928. (if not-direct
  929. (let ((reg (math-rwcomp-reg)))
  930. (math-rwcomp-pattern expr reg)
  931. (math-rwcomp-copy-instr part reg nil))
  932. (if (setq entry (assq (nth 2 expr) math-aliased-vars))
  933. (progn
  934. (setcar (math-rwcomp-reg-entry (nth 1 entry))
  935. (nth 2 expr))
  936. (setcar entry nil)
  937. (math-rwcomp-copy-instr part (nth 1 entry) nil))
  938. (math-rwcomp-bind-var part expr))))))
  939. ((and (eq (car expr) 'calcFunc-select)
  940. (= (length expr) 2))
  941. (let ((reg (math-rwcomp-reg)))
  942. (math-rwcomp-instr 'select part reg)
  943. (math-rwcomp-pattern (nth 1 expr) reg)))
  944. ((and (eq (car expr) 'calcFunc-opt)
  945. (memq (length expr) '(2 3)))
  946. (error "opt( ) occurs in context where it is not allowed"))
  947. ((eq (car expr) 'neg)
  948. (if (eq (car (nth 1 expr)) 'var)
  949. (let ((entry (assq (nth 2 (nth 1 expr)) math-regs)))
  950. (if entry
  951. (math-rwcomp-same-instr part (nth 1 entry) t)
  952. (if math-copy-neg
  953. (let ((reg (math-rwcomp-best-reg (nth 1 expr))))
  954. (math-rwcomp-copy-instr part reg t)
  955. (math-rwcomp-pattern (nth 1 expr) reg))
  956. (setcar (cdr (cdr (math-rwcomp-reg-entry part))) t)
  957. (math-rwcomp-pattern (nth 1 expr) part))))
  958. (if (math-rwcomp-is-algebraic (nth 1 expr))
  959. (math-rwcomp-cond-instr (list 'calcFunc-eq
  960. (math-rwcomp-register-expr part)
  961. expr))
  962. (let ((reg (math-rwcomp-reg)))
  963. (math-rwcomp-instr 'func part 'neg reg)
  964. (math-rwcomp-pattern (nth 1 expr) reg)))))
  965. ((and (eq (car expr) 'calcFunc-apply)
  966. (= (length expr) 3))
  967. (let ((reg1 (math-rwcomp-reg))
  968. (reg2 (math-rwcomp-reg)))
  969. (math-rwcomp-instr 'apply part reg1 reg2)
  970. (math-rwcomp-pattern (nth 1 expr) reg1)
  971. (math-rwcomp-pattern (nth 2 expr) reg2)))
  972. ((and (eq (car expr) 'calcFunc-cons)
  973. (= (length expr) 3))
  974. (let ((reg1 (math-rwcomp-reg))
  975. (reg2 (math-rwcomp-reg)))
  976. (math-rwcomp-instr 'cons part reg1 reg2)
  977. (math-rwcomp-pattern (nth 1 expr) reg1)
  978. (math-rwcomp-pattern (nth 2 expr) reg2)))
  979. ((and (eq (car expr) 'calcFunc-rcons)
  980. (= (length expr) 3))
  981. (let ((reg1 (math-rwcomp-reg))
  982. (reg2 (math-rwcomp-reg)))
  983. (math-rwcomp-instr 'rcons part reg1 reg2)
  984. (math-rwcomp-pattern (nth 1 expr) reg1)
  985. (math-rwcomp-pattern (nth 2 expr) reg2)))
  986. ((and (eq (car expr) 'calcFunc-condition)
  987. (>= (length expr) 3))
  988. (math-rwcomp-pattern (nth 1 expr) part)
  989. (setq expr (cdr expr))
  990. (while (setq expr (cdr expr))
  991. (let ((cond (math-flatten-lands (car expr))))
  992. (while cond
  993. (if (math-rwcomp-all-regs-done (car cond))
  994. (math-rwcomp-cond-instr (car cond))
  995. (setq math-conds (cons (car cond) math-conds)))
  996. (setq cond (cdr cond))))))
  997. ((and (eq (car expr) 'calcFunc-pand)
  998. (= (length expr) 3))
  999. (math-rwcomp-pattern (nth 1 expr) part)
  1000. (math-rwcomp-pattern (nth 2 expr) part))
  1001. ((and (eq (car expr) 'calcFunc-por)
  1002. (= (length expr) 3))
  1003. (math-rwcomp-instr 'alt nil nil [nil nil 4])
  1004. (let ((math-conds nil)
  1005. (head math-prog-last)
  1006. (mark math-bound-vars)
  1007. (math-copy-neg t))
  1008. (math-rwcomp-pattern (nth 1 expr) part t)
  1009. (let ((amark math-aliased-vars)
  1010. (math-aliased-vars math-aliased-vars)
  1011. (tail math-prog-last)
  1012. (p math-bound-vars)
  1013. entry)
  1014. (while (not (eq p mark))
  1015. (setq entry (assq (car p) math-regs)
  1016. math-aliased-vars (cons (list (car p) (nth 1 entry) nil)
  1017. math-aliased-vars)
  1018. p (cdr p))
  1019. (setcar (math-rwcomp-reg-entry (nth 1 entry)) nil))
  1020. (setcar (cdr (car head)) (cdr head))
  1021. (setcdr head nil)
  1022. (setq math-prog-last head)
  1023. (math-rwcomp-pattern (nth 2 expr) part)
  1024. (math-rwcomp-instr 'same 0 0)
  1025. (setcdr tail math-prog-last)
  1026. (setq p math-aliased-vars)
  1027. (while (not (eq p amark))
  1028. (if (car (car p))
  1029. (setcar (math-rwcomp-reg-entry (nth 1 (car p)))
  1030. (car (car p))))
  1031. (setq p (cdr p)))))
  1032. (math-rwcomp-do-conditions))
  1033. ((and (eq (car expr) 'calcFunc-pnot)
  1034. (= (length expr) 2))
  1035. (math-rwcomp-instr 'alt nil nil [nil nil 4])
  1036. (let ((head math-prog-last)
  1037. (mark math-bound-vars))
  1038. (math-rwcomp-pattern (nth 1 expr) part)
  1039. (math-rwcomp-unbind-vars mark)
  1040. (math-rwcomp-instr 'end-alt head)
  1041. (math-rwcomp-instr 'backtrack)
  1042. (setcar (cdr (car head)) (cdr head))
  1043. (setcdr head nil)
  1044. (setq math-prog-last head)))
  1045. (t (let ((props (get (car expr) 'math-rewrite-props)))
  1046. (if (and (eq (car expr) 'calcFunc-plain)
  1047. (= (length expr) 2)
  1048. (not (math-primp (nth 1 expr))))
  1049. (setq expr (nth 1 expr))) ; but "props" is still nil
  1050. (if (and (memq 'algebraic props)
  1051. (math-rwcomp-is-algebraic expr))
  1052. (math-rwcomp-cond-instr (list 'calcFunc-eq
  1053. (math-rwcomp-register-expr part)
  1054. expr))
  1055. (if (and (memq 'commut props)
  1056. (= (length expr) 3))
  1057. (let ((arg1 (nth 1 expr))
  1058. (arg2 (nth 2 expr))
  1059. try1 def code head (flip nil))
  1060. (if (eq (car expr) '-)
  1061. (setq arg2 (math-rwcomp-neg arg2)))
  1062. (setq arg1 (cons arg1 (math-rwcomp-best-reg arg1))
  1063. arg2 (cons arg2 (math-rwcomp-best-reg arg2)))
  1064. (or (math-rwcomp-order arg1 arg2)
  1065. (setq def arg1 arg1 arg2 arg2 def flip t))
  1066. (if (math-rwcomp-optional-arg (car expr) arg1)
  1067. (error "Too many opt( ) arguments in this context"))
  1068. (setq def (math-rwcomp-optional-arg (car expr) arg2)
  1069. head (if (memq (car expr) '(+ -))
  1070. '(+ -)
  1071. (if (eq (car expr) '*)
  1072. '(* /)
  1073. (list (car expr))))
  1074. code (if (math-rwcomp-is-constrained
  1075. (car arg1) head)
  1076. (if (math-rwcomp-is-constrained
  1077. (car arg2) head)
  1078. 0 1)
  1079. 2))
  1080. (math-rwcomp-multi-instr (and def (list def))
  1081. 'try part head
  1082. (vector nil nil nil code flip)
  1083. (cdr arg1))
  1084. (setq try1 (car math-prog-last))
  1085. (math-rwcomp-pattern (car arg1) (cdr arg1))
  1086. (math-rwcomp-instr 'try2 try1 (cdr arg2))
  1087. (if (and (= part 0) (not def) (not math-rewrite-whole)
  1088. (not (eq math-rhs t))
  1089. (setq def (get (car expr)
  1090. 'math-rewrite-default)))
  1091. (let ((reg1 (math-rwcomp-reg))
  1092. (reg2 (math-rwcomp-reg)))
  1093. (if (= (aref (nth 3 try1) 3) 0)
  1094. (aset (nth 3 try1) 3 1))
  1095. (math-rwcomp-instr 'try (cdr arg2)
  1096. (if (equal head '(* /))
  1097. '(*) head)
  1098. (vector nil nil nil
  1099. (if (= code 0)
  1100. 1 2)
  1101. nil)
  1102. reg1 def)
  1103. (setq try1 (car math-prog-last))
  1104. (math-rwcomp-pattern (car arg2) reg1)
  1105. (math-rwcomp-instr 'try2 try1 reg2)
  1106. (setq math-rhs (list (if (eq (car expr) '-)
  1107. '+ (car expr))
  1108. math-rhs
  1109. (list 'calcFunc-register
  1110. reg2))))
  1111. (math-rwcomp-pattern (car arg2) (cdr arg2))))
  1112. (let* ((args (mapcar (function
  1113. (lambda (x)
  1114. (cons x (math-rwcomp-best-reg x))))
  1115. (cdr expr)))
  1116. (args2 (copy-sequence args))
  1117. (argp (reverse args2))
  1118. (defs nil)
  1119. (num 1))
  1120. (while argp
  1121. (let ((def (math-rwcomp-optional-arg (car expr)
  1122. (car argp))))
  1123. (if def
  1124. (progn
  1125. (setq args2 (delq (car argp) args2)
  1126. defs (cons (cons def (cdr (car argp)))
  1127. defs))
  1128. (math-rwcomp-multi-instr
  1129. (mapcar 'cdr args2)
  1130. (if (or (and (memq 'unary1 props)
  1131. (= (length args2) 1)
  1132. (eq (car args2) (car args)))
  1133. (and (memq 'unary2 props)
  1134. (= (length args) 2)
  1135. (eq (car args2) (nth 1 args))))
  1136. 'func-opt
  1137. 'func-def)
  1138. part (car expr)
  1139. defs))))
  1140. (setq argp (cdr argp)))
  1141. (math-rwcomp-multi-instr (mapcar 'cdr args)
  1142. 'func part (car expr))
  1143. (setq args (sort args 'math-rwcomp-order))
  1144. (while args
  1145. (math-rwcomp-pattern (car (car args)) (cdr (car args)))
  1146. (setq num (1+ num)
  1147. args (cdr args))))))))))
  1148. (defun math-rwcomp-best-reg (x)
  1149. (or (and (eq (car-safe x) 'var)
  1150. (let ((entry (assq (nth 2 x) math-aliased-vars)))
  1151. (and entry
  1152. (not (nth 2 entry))
  1153. (not (nth 2 (math-rwcomp-reg-entry (nth 1 entry))))
  1154. (progn
  1155. (setcar (cdr (cdr entry)) t)
  1156. (nth 1 entry)))))
  1157. (math-rwcomp-reg)))
  1158. (defun math-rwcomp-all-regs-done (expr)
  1159. (if (Math-primp expr)
  1160. (or (not (eq (car-safe expr) 'var))
  1161. (assq (nth 2 expr) math-regs)
  1162. (eq (nth 2 expr) 'var-remember)
  1163. (math-const-var expr))
  1164. (if (and (eq (car expr) 'calcFunc-let)
  1165. (= (length expr) 3))
  1166. (math-rwcomp-all-regs-done (nth 2 expr))
  1167. (if (and (eq (car expr) 'calcFunc-let)
  1168. (= (length expr) 2)
  1169. (eq (car-safe (nth 1 expr)) 'calcFunc-assign)
  1170. (= (length (nth 1 expr)) 3))
  1171. (math-rwcomp-all-regs-done (nth 2 (nth 1 expr)))
  1172. (while (and (setq expr (cdr expr))
  1173. (math-rwcomp-all-regs-done (car expr))))
  1174. (null expr)))))
  1175. (defun math-rwcomp-no-vars (expr)
  1176. (if (Math-primp expr)
  1177. (or (not (eq (car-safe expr) 'var))
  1178. (math-const-var expr))
  1179. (and (not (memq (car expr) '(calcFunc-condition
  1180. calcFunc-select calcFunc-quote
  1181. calcFunc-plain calcFunc-opt
  1182. calcFunc-por calcFunc-pand
  1183. calcFunc-pnot calcFunc-apply
  1184. calcFunc-cons calcFunc-rcons)))
  1185. (progn
  1186. (while (and (setq expr (cdr expr))
  1187. (math-rwcomp-no-vars (car expr))))
  1188. (null expr)))))
  1189. (defun math-rwcomp-is-algebraic (expr)
  1190. (if (Math-primp expr)
  1191. (or (not (eq (car-safe expr) 'var))
  1192. (math-const-var expr)
  1193. (assq (nth 2 expr) math-regs))
  1194. (and (memq 'algebraic (get (car expr) 'math-rewrite-props))
  1195. (progn
  1196. (while (and (setq expr (cdr expr))
  1197. (math-rwcomp-is-algebraic (car expr))))
  1198. (null expr)))))
  1199. (defun math-rwcomp-is-constrained (expr not-these)
  1200. (if (Math-primp expr)
  1201. (not (eq (car-safe expr) 'var))
  1202. (if (eq (car expr) 'calcFunc-plain)
  1203. (math-rwcomp-is-constrained (nth 1 expr) not-these)
  1204. (not (or (memq (car expr) '(neg calcFunc-select))
  1205. (memq (car expr) not-these)
  1206. (and (memq 'commut (get (car expr) 'math-rewrite-props))
  1207. (or (eq (car-safe (nth 1 expr)) 'calcFunc-opt)
  1208. (eq (car-safe (nth 2 expr)) 'calcFunc-opt))))))))
  1209. (defun math-rwcomp-optional-arg (head argp)
  1210. (let ((arg (car argp)))
  1211. (if (eq (car-safe arg) 'calcFunc-opt)
  1212. (and (memq (length arg) '(2 3))
  1213. (progn
  1214. (or (eq (car-safe (nth 1 arg)) 'var)
  1215. (error "First argument of opt( ) must be a variable"))
  1216. (setcar argp (nth 1 arg))
  1217. (if (= (length arg) 2)
  1218. (or (get head 'math-rewrite-default)
  1219. (error "opt( ) must include a default in this context"))
  1220. (nth 2 arg))))
  1221. (and (eq (car-safe arg) 'neg)
  1222. (let* ((part (list (nth 1 arg)))
  1223. (partp (math-rwcomp-optional-arg head part)))
  1224. (and partp
  1225. (setcar argp (math-rwcomp-neg (car part)))
  1226. (math-neg partp)))))))
  1227. (defun math-rwcomp-neg (expr)
  1228. (if (memq (car-safe expr) '(* /))
  1229. (if (eq (car-safe (nth 1 expr)) 'var)
  1230. (list (car expr) (list 'neg (nth 1 expr)) (nth 2 expr))
  1231. (if (eq (car-safe (nth 2 expr)) 'var)
  1232. (list (car expr) (nth 1 expr) (list 'neg (nth 2 expr)))
  1233. (math-neg expr)))
  1234. (math-neg expr)))
  1235. (defun math-rwcomp-assoc-args (expr)
  1236. (if (and (eq (car-safe (nth 1 expr)) (car expr))
  1237. (= (length (nth 1 expr)) 3))
  1238. (math-rwcomp-assoc-args (nth 1 expr)))
  1239. (if (and (eq (car-safe (nth 2 expr)) (car expr))
  1240. (= (length (nth 2 expr)) 3))
  1241. (math-rwcomp-assoc-args (nth 2 expr))))
  1242. (defun math-rwcomp-addsub-args (expr)
  1243. (if (memq (car-safe (nth 1 expr)) '(+ -))
  1244. (math-rwcomp-addsub-args (nth 1 expr)))
  1245. (if (eq (car expr) '-)
  1246. ()
  1247. (if (eq (car-safe (nth 2 expr)) '+)
  1248. (math-rwcomp-addsub-args (nth 2 expr)))))
  1249. (defun math-rwcomp-order (a b)
  1250. (< (math-rwcomp-priority (car a))
  1251. (math-rwcomp-priority (car b))))
  1252. ;; Order of priority: 0 Constants and other exact matches (first)
  1253. ;; 10 Functions (except below)
  1254. ;; 20 Meta-variables which occur more than once
  1255. ;; 30 Algebraic functions
  1256. ;; 40 Commutative/associative functions
  1257. ;; 50 Meta-variables which occur only once
  1258. ;; +100 for every "!!!" (pnot) in the pattern
  1259. ;; 10000 Optional arguments (last)
  1260. (defun math-rwcomp-priority (expr)
  1261. (+ (math-rwcomp-count-pnots expr)
  1262. (cond ((eq (car-safe expr) 'calcFunc-opt)
  1263. 10000)
  1264. ((math-rwcomp-no-vars expr)
  1265. 0)
  1266. ((eq (car expr) 'calcFunc-quote)
  1267. 0)
  1268. ((eq (car expr) 'var)
  1269. (if (assq (nth 2 expr) math-regs)
  1270. 0
  1271. (if (= (math-rwcomp-count-refs expr) 1)
  1272. 50
  1273. 20)))
  1274. (t (let ((props (get (car expr) 'math-rewrite-props)))
  1275. (if (or (memq 'commut props)
  1276. (memq 'assoc props))
  1277. 40
  1278. (if (memq 'algebraic props)
  1279. 30
  1280. 10)))))))
  1281. (defun math-rwcomp-count-refs (var)
  1282. (let ((count (or (math-expr-contains-count math-pattern var) 0))
  1283. (p math-conds))
  1284. (while p
  1285. (if (eq (car-safe (car p)) 'calcFunc-let)
  1286. (if (= (length (car p)) 3)
  1287. (setq count (+ count
  1288. (or (math-expr-contains-count (nth 2 (car p)) var)
  1289. 0)))
  1290. (if (and (= (length (car p)) 2)
  1291. (eq (car-safe (nth 1 (car p))) 'calcFunc-assign)
  1292. (= (length (nth 1 (car p))) 3))
  1293. (setq count (+ count
  1294. (or (math-expr-contains-count
  1295. (nth 2 (nth 1 (car p))) var) 0))))))
  1296. (setq p (cdr p)))
  1297. count))
  1298. (defun math-rwcomp-count-pnots (expr)
  1299. (if (Math-primp expr)
  1300. 0
  1301. (if (eq (car expr) 'calcFunc-pnot)
  1302. 100
  1303. (let ((count 0))
  1304. (while (setq expr (cdr expr))
  1305. (setq count (+ count (math-rwcomp-count-pnots (car expr)))))
  1306. count))))
  1307. ;; In the current implementation, all associative functions must
  1308. ;; also be commutative.
  1309. (put '+ 'math-rewrite-props '(algebraic assoc commut))
  1310. (put '- 'math-rewrite-props '(algebraic assoc commut)) ; see below
  1311. (put '* 'math-rewrite-props '(algebraic assoc commut)) ; see below
  1312. (put '/ 'math-rewrite-props '(algebraic unary1))
  1313. (put '^ 'math-rewrite-props '(algebraic unary1))
  1314. (put '% 'math-rewrite-props '(algebraic))
  1315. (put 'neg 'math-rewrite-props '(algebraic))
  1316. (put 'calcFunc-idiv 'math-rewrite-props '(algebraic))
  1317. (put 'calcFunc-abs 'math-rewrite-props '(algebraic))
  1318. (put 'calcFunc-sign 'math-rewrite-props '(algebraic))
  1319. (put 'calcFunc-round 'math-rewrite-props '(algebraic))
  1320. (put 'calcFunc-rounde 'math-rewrite-props '(algebraic))
  1321. (put 'calcFunc-roundu 'math-rewrite-props '(algebraic))
  1322. (put 'calcFunc-trunc 'math-rewrite-props '(algebraic))
  1323. (put 'calcFunc-floor 'math-rewrite-props '(algebraic))
  1324. (put 'calcFunc-ceil 'math-rewrite-props '(algebraic))
  1325. (put 'calcFunc-re 'math-rewrite-props '(algebraic))
  1326. (put 'calcFunc-im 'math-rewrite-props '(algebraic))
  1327. (put 'calcFunc-conj 'math-rewrite-props '(algebraic))
  1328. (put 'calcFunc-arg 'math-rewrite-props '(algebraic))
  1329. (put 'calcFunc-and 'math-rewrite-props '(assoc commut))
  1330. (put 'calcFunc-or 'math-rewrite-props '(assoc commut))
  1331. (put 'calcFunc-xor 'math-rewrite-props '(assoc commut))
  1332. (put 'calcFunc-eq 'math-rewrite-props '(commut))
  1333. (put 'calcFunc-neq 'math-rewrite-props '(commut))
  1334. (put 'calcFunc-land 'math-rewrite-props '(assoc commut))
  1335. (put 'calcFunc-lor 'math-rewrite-props '(assoc commut))
  1336. (put 'calcFunc-beta 'math-rewrite-props '(commut))
  1337. (put 'calcFunc-gcd 'math-rewrite-props '(assoc commut))
  1338. (put 'calcFunc-lcm 'math-rewrite-props '(assoc commut))
  1339. (put 'calcFunc-max 'math-rewrite-props '(algebraic assoc commut))
  1340. (put 'calcFunc-min 'math-rewrite-props '(algebraic assoc commut))
  1341. (put 'calcFunc-vunion 'math-rewrite-props '(assoc commut))
  1342. (put 'calcFunc-vint 'math-rewrite-props '(assoc commut))
  1343. (put 'calcFunc-vxor 'math-rewrite-props '(assoc commut))
  1344. ;; Note: "*" is not commutative for matrix args, but we pretend it is.
  1345. ;; Also, "-" is not commutative but the code tweaks things so that it is.
  1346. (put '+ 'math-rewrite-default 0)
  1347. (put '- 'math-rewrite-default 0)
  1348. (put '* 'math-rewrite-default 1)
  1349. (put '/ 'math-rewrite-default 1)
  1350. (put '^ 'math-rewrite-default 1)
  1351. (put 'calcFunc-land 'math-rewrite-default 1)
  1352. (put 'calcFunc-lor 'math-rewrite-default 0)
  1353. (put 'calcFunc-vunion 'math-rewrite-default '(vec))
  1354. (put 'calcFunc-vint 'math-rewrite-default '(vec))
  1355. (put 'calcFunc-vdiff 'math-rewrite-default '(vec))
  1356. (put 'calcFunc-vxor 'math-rewrite-default '(vec))
  1357. (defmacro math-rwfail (&optional back)
  1358. (list 'setq 'pc
  1359. (list 'and
  1360. (if back
  1361. '(setq btrack (cdr btrack))
  1362. 'btrack)
  1363. ''((backtrack)))))
  1364. ;; This monstrosity is necessary because the use of static vectors of
  1365. ;; registers makes rewrite rules non-reentrant. Yucko!
  1366. (defmacro math-rweval (form)
  1367. (list 'let '((orig (car rules)))
  1368. '(setcar rules (quote (nil nil nil no-phase)))
  1369. (list 'unwind-protect
  1370. form
  1371. '(setcar rules orig))))
  1372. (defvar math-rewrite-phase 1)
  1373. ;; The variable math-apply-rw-regs is local to math-apply-rewrites,
  1374. ;; but is used by math-rwapply-replace-regs and math-rwapply-reg-looks-negp
  1375. ;; which are called by math-apply-rewrites.
  1376. (defvar math-apply-rw-regs)
  1377. ;; The variable math-apply-rw-ruleset is local to math-apply-rewrites,
  1378. ;; but is used by math-rwapply-remember.
  1379. (defvar math-apply-rw-ruleset)
  1380. (defun math-apply-rewrites (expr rules &optional heads math-apply-rw-ruleset)
  1381. (and
  1382. (setq rules (cdr (or (assq (car-safe expr) rules)
  1383. (assq nil rules))))
  1384. (let ((result nil)
  1385. op math-apply-rw-regs inst part pc mark btrack
  1386. (tracing math-rwcomp-tracing)
  1387. (phase math-rewrite-phase))
  1388. (while rules
  1389. (or
  1390. (and (setq part (nth 2 (car rules)))
  1391. heads
  1392. (not (memq part heads)))
  1393. (and (setq part (nth 3 (car rules)))
  1394. (not (memq phase part)))
  1395. (progn
  1396. (setq math-apply-rw-regs (car (car rules))
  1397. pc (nth 1 (car rules))
  1398. btrack nil)
  1399. (aset math-apply-rw-regs 0 expr)
  1400. (while pc
  1401. (and tracing
  1402. (progn (terpri) (princ (car pc))
  1403. (if (and (natnump (nth 1 (car pc)))
  1404. (< (nth 1 (car pc)) (length math-apply-rw-regs)))
  1405. (princ
  1406. (format "\n part = %s"
  1407. (aref math-apply-rw-regs (nth 1 (car pc))))))))
  1408. (cond ((eq (setq op (car (setq inst (car pc)))) 'func)
  1409. (if (and (consp
  1410. (setq part (aref math-apply-rw-regs (car (cdr inst)))))
  1411. (eq (car part)
  1412. (car (setq inst (cdr (cdr inst)))))
  1413. (progn
  1414. (while (and (setq inst (cdr inst)
  1415. part (cdr part))
  1416. inst)
  1417. (aset math-apply-rw-regs (car inst) (car part)))
  1418. (not (or inst part))))
  1419. (setq pc (cdr pc))
  1420. (math-rwfail)))
  1421. ((eq op 'same)
  1422. (if (or (equal (setq part (aref math-apply-rw-regs (nth 1 inst)))
  1423. (setq mark (aref math-apply-rw-regs (nth 2 inst))))
  1424. (Math-equal part mark))
  1425. (setq pc (cdr pc))
  1426. (math-rwfail)))
  1427. ((and (eq op 'try)
  1428. calc-matrix-mode
  1429. (not (eq calc-matrix-mode 'scalar))
  1430. (eq (car (nth 2 inst)) '*)
  1431. (consp (setq part (aref math-apply-rw-regs (car (cdr inst)))))
  1432. (eq (car part) '*)
  1433. (not (math-known-scalarp part)))
  1434. (setq mark (nth 3 inst)
  1435. pc (cdr pc))
  1436. (if (aref mark 4)
  1437. (progn
  1438. (aset math-apply-rw-regs (nth 4 inst) (nth 2 part))
  1439. (aset mark 1 (cdr (cdr part))))
  1440. (aset math-apply-rw-regs (nth 4 inst) (nth 1 part))
  1441. (aset mark 1 (cdr part)))
  1442. (aset mark 0 (cdr part))
  1443. (aset mark 2 0))
  1444. ((eq op 'try)
  1445. (if (and (consp (setq part
  1446. (aref math-apply-rw-regs (car (cdr inst)))))
  1447. (memq (car part) (nth 2 inst))
  1448. (= (length part) 3)
  1449. (or (not (eq (car part) '/))
  1450. (Math-objectp (nth 2 part))))
  1451. (progn
  1452. (setq op nil
  1453. mark (car (cdr (setq inst (cdr (cdr inst))))))
  1454. (and
  1455. (memq 'assoc (get (car part) 'math-rewrite-props))
  1456. (not (= (aref mark 3) 0))
  1457. (while (if (and (consp (nth 1 part))
  1458. (memq (car (nth 1 part)) (car inst)))
  1459. (setq op (cons (if (eq (car part) '-)
  1460. (math-rwapply-neg
  1461. (nth 2 part))
  1462. (nth 2 part))
  1463. op)
  1464. part (nth 1 part))
  1465. (if (and (consp (nth 2 part))
  1466. (memq (car (nth 2 part))
  1467. (car inst))
  1468. (not (eq (car (nth 2 part)) '-)))
  1469. (setq op (cons (nth 1 part) op)
  1470. part (nth 2 part))))))
  1471. (setq op (cons (nth 1 part)
  1472. (cons (if (eq (car part) '-)
  1473. (math-rwapply-neg
  1474. (nth 2 part))
  1475. (if (eq (car part) '/)
  1476. (math-rwapply-inv
  1477. (nth 2 part))
  1478. (nth 2 part)))
  1479. op))
  1480. btrack (cons pc btrack)
  1481. pc (cdr pc))
  1482. (aset math-apply-rw-regs (nth 2 inst) (car op))
  1483. (aset mark 0 op)
  1484. (aset mark 1 op)
  1485. (aset mark 2 (if (cdr (cdr op)) 1 0)))
  1486. (if (nth 5 inst)
  1487. (if (and (consp part)
  1488. (eq (car part) 'neg)
  1489. (eq (car (nth 2 inst)) '*)
  1490. (eq (nth 5 inst) 1))
  1491. (progn
  1492. (setq mark (nth 3 inst)
  1493. pc (cdr pc))
  1494. (aset math-apply-rw-regs (nth 4 inst) (nth 1 part))
  1495. (aset mark 1 -1)
  1496. (aset mark 2 4))
  1497. (setq mark (nth 3 inst)
  1498. pc (cdr pc))
  1499. (aset math-apply-rw-regs (nth 4 inst) part)
  1500. (aset mark 2 3))
  1501. (math-rwfail))))
  1502. ((eq op 'try2)
  1503. (setq part (nth 1 inst) ; try instr
  1504. mark (nth 3 part)
  1505. op (aref mark 2)
  1506. pc (cdr pc))
  1507. (aset math-apply-rw-regs (nth 2 inst)
  1508. (cond
  1509. ((eq op 0)
  1510. (if (eq (aref mark 0) (aref mark 1))
  1511. (nth 1 (aref mark 0))
  1512. (car (aref mark 0))))
  1513. ((eq op 1)
  1514. (setq mark (delq (car (aref mark 1))
  1515. (copy-sequence (aref mark 0)))
  1516. op (car (nth 2 part)))
  1517. (if (eq op '*)
  1518. (progn
  1519. (setq mark (nreverse mark)
  1520. part (list '* (nth 1 mark) (car mark))
  1521. mark (cdr mark))
  1522. (while (setq mark (cdr mark))
  1523. (setq part (list '* (car mark) part))))
  1524. (setq part (car mark)
  1525. mark (cdr mark)
  1526. part (if (and (eq op '+)
  1527. (consp (car mark))
  1528. (eq (car (car mark)) 'neg))
  1529. (list '- part
  1530. (nth 1 (car mark)))
  1531. (list op part (car mark))))
  1532. (while (setq mark (cdr mark))
  1533. (setq part (if (and (eq op '+)
  1534. (consp (car mark))
  1535. (eq (car (car mark)) 'neg))
  1536. (list '- part
  1537. (nth 1 (car mark)))
  1538. (list op part (car mark))))))
  1539. part)
  1540. ((eq op 2)
  1541. (car (aref mark 1)))
  1542. ((eq op 3) (nth 5 part))
  1543. (t (aref mark 1)))))
  1544. ((eq op 'select)
  1545. (setq pc (cdr pc))
  1546. (if (and (consp (setq part (aref math-apply-rw-regs (nth 1 inst))))
  1547. (eq (car part) 'calcFunc-select))
  1548. (aset math-apply-rw-regs (nth 2 inst) (nth 1 part))
  1549. (if math-rewrite-selections
  1550. (math-rwfail)
  1551. (aset math-apply-rw-regs (nth 2 inst) part))))
  1552. ((eq op 'same-neg)
  1553. (if (or (equal (setq part (aref math-apply-rw-regs (nth 1 inst)))
  1554. (setq mark (math-neg
  1555. (aref math-apply-rw-regs (nth 2 inst)))))
  1556. (Math-equal part mark))
  1557. (setq pc (cdr pc))
  1558. (math-rwfail)))
  1559. ((eq op 'backtrack)
  1560. (setq inst (car (car btrack)) ; "try" or "alt" instr
  1561. pc (cdr (car btrack))
  1562. mark (or (nth 3 inst) [nil nil 4])
  1563. op (aref mark 2))
  1564. (cond ((eq op 0)
  1565. (if (setq op (cdr (aref mark 1)))
  1566. (aset math-apply-rw-regs (nth 4 inst)
  1567. (car (aset mark 1 op)))
  1568. (if (nth 5 inst)
  1569. (progn
  1570. (aset mark 2 3)
  1571. (aset math-apply-rw-regs (nth 4 inst)
  1572. (aref math-apply-rw-regs (nth 1 inst))))
  1573. (math-rwfail t))))
  1574. ((eq op 1)
  1575. (if (setq op (cdr (aref mark 1)))
  1576. (aset math-apply-rw-regs (nth 4 inst)
  1577. (car (aset mark 1 op)))
  1578. (if (= (aref mark 3) 1)
  1579. (if (nth 5 inst)
  1580. (progn
  1581. (aset mark 2 3)
  1582. (aset math-apply-rw-regs (nth 4 inst)
  1583. (aref math-apply-rw-regs (nth 1 inst))))
  1584. (math-rwfail t))
  1585. (aset mark 2 2)
  1586. (aset mark 1 (cons nil (aref mark 0)))
  1587. (math-rwfail))))
  1588. ((eq op 2)
  1589. (if (setq op (cdr (aref mark 1)))
  1590. (progn
  1591. (setq mark (delq (car (aset mark 1 op))
  1592. (copy-sequence
  1593. (aref mark 0)))
  1594. op (car (nth 2 inst)))
  1595. (if (eq op '*)
  1596. (progn
  1597. (setq mark (nreverse mark)
  1598. part (list '* (nth 1 mark)
  1599. (car mark))
  1600. mark (cdr mark))
  1601. (while (setq mark (cdr mark))
  1602. (setq part (list '* (car mark)
  1603. part))))
  1604. (setq part (car mark)
  1605. mark (cdr mark)
  1606. part (if (and (eq op '+)
  1607. (consp (car mark))
  1608. (eq (car (car mark))
  1609. 'neg))
  1610. (list '- part
  1611. (nth 1 (car mark)))
  1612. (list op part (car mark))))
  1613. (while (setq mark (cdr mark))
  1614. (setq part (if (and (eq op '+)
  1615. (consp (car mark))
  1616. (eq (car (car mark))
  1617. 'neg))
  1618. (list '- part
  1619. (nth 1 (car mark)))
  1620. (list op part (car mark))))))
  1621. (aset math-apply-rw-regs (nth 4 inst) part))
  1622. (if (nth 5 inst)
  1623. (progn
  1624. (aset mark 2 3)
  1625. (aset math-apply-rw-regs (nth 4 inst)
  1626. (aref math-apply-rw-regs (nth 1 inst))))
  1627. (math-rwfail t))))
  1628. ((eq op 4)
  1629. (setq btrack (cdr btrack)))
  1630. (t (math-rwfail t))))
  1631. ((eq op 'integer)
  1632. (if (Math-integerp (setq part
  1633. (aref math-apply-rw-regs (nth 1 inst))))
  1634. (setq pc (cdr pc))
  1635. (if (Math-primp part)
  1636. (math-rwfail)
  1637. (setq part (math-rweval (math-simplify part)))
  1638. (if (Math-integerp part)
  1639. (setq pc (cdr pc))
  1640. (math-rwfail)))))
  1641. ((eq op 'real)
  1642. (if (Math-realp (setq part (aref math-apply-rw-regs (nth 1 inst))))
  1643. (setq pc (cdr pc))
  1644. (if (Math-primp part)
  1645. (math-rwfail)
  1646. (setq part (math-rweval (math-simplify part)))
  1647. (if (Math-realp part)
  1648. (setq pc (cdr pc))
  1649. (math-rwfail)))))
  1650. ((eq op 'constant)
  1651. (if (math-constp (setq part (aref math-apply-rw-regs (nth 1 inst))))
  1652. (setq pc (cdr pc))
  1653. (if (Math-primp part)
  1654. (math-rwfail)
  1655. (setq part (math-rweval (math-simplify part)))
  1656. (if (math-constp part)
  1657. (setq pc (cdr pc))
  1658. (math-rwfail)))))
  1659. ((eq op 'negative)
  1660. (if (math-looks-negp (setq part
  1661. (aref math-apply-rw-regs (nth 1 inst))))
  1662. (setq pc (cdr pc))
  1663. (if (Math-primp part)
  1664. (math-rwfail)
  1665. (setq part (math-rweval (math-simplify part)))
  1666. (if (math-looks-negp part)
  1667. (setq pc (cdr pc))
  1668. (math-rwfail)))))
  1669. ((eq op 'rel)
  1670. (setq part (math-compare (aref math-apply-rw-regs (nth 1 inst))
  1671. (aref math-apply-rw-regs (nth 3 inst)))
  1672. op (nth 2 inst))
  1673. (if (= part 2)
  1674. (setq part (math-rweval
  1675. (math-simplify
  1676. (calcFunc-sign
  1677. (math-sub
  1678. (aref math-apply-rw-regs (nth 1 inst))
  1679. (aref math-apply-rw-regs (nth 3 inst))))))))
  1680. (if (cond ((eq op 'calcFunc-eq)
  1681. (eq part 0))
  1682. ((eq op 'calcFunc-neq)
  1683. (memq part '(-1 1)))
  1684. ((eq op 'calcFunc-lt)
  1685. (eq part -1))
  1686. ((eq op 'calcFunc-leq)
  1687. (memq part '(-1 0)))
  1688. ((eq op 'calcFunc-gt)
  1689. (eq part 1))
  1690. ((eq op 'calcFunc-geq)
  1691. (memq part '(0 1))))
  1692. (setq pc (cdr pc))
  1693. (math-rwfail)))
  1694. ((eq op 'func-def)
  1695. (if (and
  1696. (consp (setq part (aref math-apply-rw-regs (car (cdr inst)))))
  1697. (eq (car part)
  1698. (car (setq inst (cdr (cdr inst))))))
  1699. (progn
  1700. (setq inst (cdr inst)
  1701. mark (car inst))
  1702. (while (and (setq inst (cdr inst)
  1703. part (cdr part))
  1704. inst)
  1705. (aset math-apply-rw-regs (car inst) (car part)))
  1706. (if (or inst part)
  1707. (setq pc (cdr pc))
  1708. (while (eq (car (car (setq pc (cdr pc))))
  1709. 'func-def))
  1710. (setq pc (cdr pc)) ; skip over "func"
  1711. (while mark
  1712. (aset math-apply-rw-regs (cdr (car mark)) (car (car mark)))
  1713. (setq mark (cdr mark)))))
  1714. (math-rwfail)))
  1715. ((eq op 'func-opt)
  1716. (if (or (not
  1717. (and
  1718. (consp
  1719. (setq part (aref math-apply-rw-regs (car (cdr inst)))))
  1720. (eq (car part) (nth 2 inst))))
  1721. (and (= (length part) 2)
  1722. (setq part (nth 1 part))))
  1723. (progn
  1724. (setq mark (nth 3 inst))
  1725. (aset math-apply-rw-regs (nth 4 inst) part)
  1726. (while (eq (car (car (setq pc (cdr pc)))) 'func-def))
  1727. (setq pc (cdr pc)) ; skip over "func"
  1728. (while mark
  1729. (aset math-apply-rw-regs (cdr (car mark)) (car (car mark)))
  1730. (setq mark (cdr mark))))
  1731. (setq pc (cdr pc))))
  1732. ((eq op 'mod)
  1733. (if (if (Math-zerop
  1734. (setq part (aref math-apply-rw-regs (nth 1 inst))))
  1735. (Math-zerop (nth 3 inst))
  1736. (and (not (Math-zerop (nth 2 inst)))
  1737. (progn
  1738. (setq part (math-mod part (nth 2 inst)))
  1739. (or (Math-numberp part)
  1740. (setq part (math-rweval
  1741. (math-simplify part))))
  1742. (Math-equal part (nth 3 inst)))))
  1743. (setq pc (cdr pc))
  1744. (math-rwfail)))
  1745. ((eq op 'apply)
  1746. (if (and (consp
  1747. (setq part (aref math-apply-rw-regs (car (cdr inst)))))
  1748. (not (Math-objvecp part))
  1749. (not (eq (car part) 'var)))
  1750. (progn
  1751. (aset math-apply-rw-regs (nth 2 inst)
  1752. (math-calcFunc-to-var (car part)))
  1753. (aset math-apply-rw-regs (nth 3 inst)
  1754. (cons 'vec (cdr part)))
  1755. (setq pc (cdr pc)))
  1756. (math-rwfail)))
  1757. ((eq op 'cons)
  1758. (if (and (consp
  1759. (setq part (aref math-apply-rw-regs (car (cdr inst)))))
  1760. (eq (car part) 'vec)
  1761. (cdr part))
  1762. (progn
  1763. (aset math-apply-rw-regs (nth 2 inst) (nth 1 part))
  1764. (aset math-apply-rw-regs (nth 3 inst)
  1765. (cons 'vec (cdr (cdr part))))
  1766. (setq pc (cdr pc)))
  1767. (math-rwfail)))
  1768. ((eq op 'rcons)
  1769. (if (and (consp
  1770. (setq part (aref math-apply-rw-regs (car (cdr inst)))))
  1771. (eq (car part) 'vec)
  1772. (cdr part))
  1773. (progn
  1774. (aset math-apply-rw-regs (nth 2 inst) (calcFunc-rhead part))
  1775. (aset math-apply-rw-regs (nth 3 inst) (calcFunc-rtail part))
  1776. (setq pc (cdr pc)))
  1777. (math-rwfail)))
  1778. ((eq op 'cond)
  1779. (if (math-is-true
  1780. (math-rweval
  1781. (math-simplify
  1782. (math-rwapply-replace-regs (nth 1 inst)))))
  1783. (setq pc (cdr pc))
  1784. (math-rwfail)))
  1785. ((eq op 'let)
  1786. (aset math-apply-rw-regs (nth 1 inst)
  1787. (math-rweval
  1788. (math-normalize
  1789. (math-rwapply-replace-regs (nth 2 inst)))))
  1790. (setq pc (cdr pc)))
  1791. ((eq op 'copy)
  1792. (aset math-apply-rw-regs (nth 2 inst)
  1793. (aref math-apply-rw-regs (nth 1 inst)))
  1794. (setq pc (cdr pc)))
  1795. ((eq op 'copy-neg)
  1796. (aset math-apply-rw-regs (nth 2 inst)
  1797. (math-rwapply-neg (aref math-apply-rw-regs (nth 1 inst))))
  1798. (setq pc (cdr pc)))
  1799. ((eq op 'alt)
  1800. (setq btrack (cons pc btrack)
  1801. pc (nth 1 inst)))
  1802. ((eq op 'end-alt)
  1803. (while (and btrack (not (eq (car btrack) (nth 1 inst))))
  1804. (setq btrack (cdr btrack)))
  1805. (setq btrack (cdr btrack)
  1806. pc (cdr pc)))
  1807. ((eq op 'done)
  1808. (setq result (math-rwapply-replace-regs (nth 1 inst)))
  1809. (if (or (and (eq (car-safe result) '+)
  1810. (eq (nth 2 result) 0))
  1811. (and (eq (car-safe result) '*)
  1812. (eq (nth 2 result) 1)))
  1813. (setq result (nth 1 result)))
  1814. (setq part (and (nth 2 inst)
  1815. (math-is-true
  1816. (math-rweval
  1817. (math-simplify
  1818. (math-rwapply-replace-regs
  1819. (nth 2 inst)))))))
  1820. (if (or (equal result expr)
  1821. (equal (setq result (math-normalize result)) expr))
  1822. (setq result nil)
  1823. (if part (math-rwapply-remember expr result))
  1824. (setq rules nil))
  1825. (setq pc nil))
  1826. (t (error "%s is not a valid rewrite opcode" op))))))
  1827. (setq rules (cdr rules)))
  1828. result)))
  1829. (defun math-rwapply-neg (expr)
  1830. (if (and (consp expr)
  1831. (memq (car expr) '(* /)))
  1832. (if (Math-objectp (nth 2 expr))
  1833. (list (car expr) (nth 1 expr) (math-neg (nth 2 expr)))
  1834. (list (car expr)
  1835. (if (Math-objectp (nth 1 expr))
  1836. (math-neg (nth 1 expr))
  1837. (list '* -1 (nth 1 expr)))
  1838. (nth 2 expr)))
  1839. (math-neg expr)))
  1840. (defun math-rwapply-inv (expr)
  1841. (if (and (Math-integerp expr)
  1842. calc-prefer-frac)
  1843. (math-make-frac 1 expr)
  1844. (list '/ 1 expr)))
  1845. (defun math-rwapply-replace-regs (expr)
  1846. (cond ((Math-primp expr)
  1847. expr)
  1848. ((eq (car expr) 'calcFunc-register)
  1849. (setq expr (aref math-apply-rw-regs (nth 1 expr)))
  1850. (if (eq (car-safe expr) '*)
  1851. (if (eq (nth 1 expr) -1)
  1852. (math-neg (nth 2 expr))
  1853. (if (eq (nth 1 expr) 1)
  1854. (nth 2 expr)
  1855. expr))
  1856. expr))
  1857. ((and (eq (car expr) 'calcFunc-eval)
  1858. (= (length expr) 2))
  1859. (calc-with-default-simplification
  1860. (math-normalize (math-rwapply-replace-regs (nth 1 expr)))))
  1861. ((and (eq (car expr) 'calcFunc-evalsimp)
  1862. (= (length expr) 2))
  1863. (math-simplify (math-rwapply-replace-regs (nth 1 expr))))
  1864. ((and (eq (car expr) 'calcFunc-evalextsimp)
  1865. (= (length expr) 2))
  1866. (math-simplify-extended (math-rwapply-replace-regs (nth 1 expr))))
  1867. ((and (eq (car expr) 'calcFunc-apply)
  1868. (= (length expr) 3))
  1869. (let ((func (math-rwapply-replace-regs (nth 1 expr)))
  1870. (args (math-rwapply-replace-regs (nth 2 expr)))
  1871. call)
  1872. (if (and (math-vectorp args)
  1873. (not (eq (car-safe (setq call (math-build-call
  1874. (math-var-to-calcFunc func)
  1875. (cdr args))))
  1876. 'calcFunc-call)))
  1877. call
  1878. (list 'calcFunc-apply func args))))
  1879. ((and (eq (car expr) 'calcFunc-cons)
  1880. (= (length expr) 3))
  1881. (let ((head (math-rwapply-replace-regs (nth 1 expr)))
  1882. (tail (math-rwapply-replace-regs (nth 2 expr))))
  1883. (if (math-vectorp tail)
  1884. (cons 'vec (cons head (cdr tail)))
  1885. (list 'calcFunc-cons head tail))))
  1886. ((and (eq (car expr) 'calcFunc-rcons)
  1887. (= (length expr) 3))
  1888. (let ((head (math-rwapply-replace-regs (nth 1 expr)))
  1889. (tail (math-rwapply-replace-regs (nth 2 expr))))
  1890. (if (math-vectorp head)
  1891. (append head (list tail))
  1892. (list 'calcFunc-rcons head tail))))
  1893. ((and (eq (car expr) 'neg)
  1894. (math-rwapply-reg-looks-negp (nth 1 expr)))
  1895. (math-rwapply-reg-neg (nth 1 expr)))
  1896. ((and (eq (car expr) 'neg)
  1897. (eq (car-safe (nth 1 expr)) 'calcFunc-register)
  1898. (math-scalarp (aref math-apply-rw-regs (nth 1 (nth 1 expr)))))
  1899. (math-neg (math-rwapply-replace-regs (nth 1 expr))))
  1900. ((and (eq (car expr) '+)
  1901. (math-rwapply-reg-looks-negp (nth 1 expr)))
  1902. (list '- (math-rwapply-replace-regs (nth 2 expr))
  1903. (math-rwapply-reg-neg (nth 1 expr))))
  1904. ((and (eq (car expr) '+)
  1905. (math-rwapply-reg-looks-negp (nth 2 expr)))
  1906. (list '- (math-rwapply-replace-regs (nth 1 expr))
  1907. (math-rwapply-reg-neg (nth 2 expr))))
  1908. ((and (eq (car expr) '-)
  1909. (math-rwapply-reg-looks-negp (nth 2 expr)))
  1910. (list '+ (math-rwapply-replace-regs (nth 1 expr))
  1911. (math-rwapply-reg-neg (nth 2 expr))))
  1912. ((eq (car expr) '*)
  1913. (cond ((eq (nth 1 expr) -1)
  1914. (if (math-rwapply-reg-looks-negp (nth 2 expr))
  1915. (math-rwapply-reg-neg (nth 2 expr))
  1916. (math-neg (math-rwapply-replace-regs (nth 2 expr)))))
  1917. ((eq (nth 1 expr) 1)
  1918. (math-rwapply-replace-regs (nth 2 expr)))
  1919. ((eq (nth 2 expr) -1)
  1920. (if (math-rwapply-reg-looks-negp (nth 1 expr))
  1921. (math-rwapply-reg-neg (nth 1 expr))
  1922. (math-neg (math-rwapply-replace-regs (nth 1 expr)))))
  1923. ((eq (nth 2 expr) 1)
  1924. (math-rwapply-replace-regs (nth 1 expr)))
  1925. (t
  1926. (let ((arg1 (math-rwapply-replace-regs (nth 1 expr)))
  1927. (arg2 (math-rwapply-replace-regs (nth 2 expr))))
  1928. (cond ((and (eq (car-safe arg1) '/)
  1929. (eq (nth 1 arg1) 1))
  1930. (list '/ arg2 (nth 2 arg1)))
  1931. ((and (eq (car-safe arg2) '/)
  1932. (eq (nth 1 arg2) 1))
  1933. (list '/ arg1 (nth 2 arg2)))
  1934. (t (list '* arg1 arg2)))))))
  1935. ((eq (car expr) '/)
  1936. (let ((arg1 (math-rwapply-replace-regs (nth 1 expr)))
  1937. (arg2 (math-rwapply-replace-regs (nth 2 expr))))
  1938. (if (eq (car-safe arg2) '/)
  1939. (list '/ (list '* arg1 (nth 2 arg2)) (nth 1 arg2))
  1940. (list '/ arg1 arg2))))
  1941. ((and (eq (car expr) 'calcFunc-plain)
  1942. (= (length expr) 2))
  1943. (if (Math-primp (nth 1 expr))
  1944. (nth 1 expr)
  1945. (if (eq (car (nth 1 expr)) 'calcFunc-register)
  1946. (aref math-apply-rw-regs (nth 1 (nth 1 expr)))
  1947. (cons (car (nth 1 expr)) (mapcar 'math-rwapply-replace-regs
  1948. (cdr (nth 1 expr)))))))
  1949. (t (cons (car expr) (mapcar 'math-rwapply-replace-regs (cdr expr))))))
  1950. (defun math-rwapply-reg-looks-negp (expr)
  1951. (if (eq (car-safe expr) 'calcFunc-register)
  1952. (math-looks-negp (aref math-apply-rw-regs (nth 1 expr)))
  1953. (if (memq (car-safe expr) '(* /))
  1954. (or (math-rwapply-reg-looks-negp (nth 1 expr))
  1955. (math-rwapply-reg-looks-negp (nth 2 expr))))))
  1956. (defun math-rwapply-reg-neg (expr) ; expr must satisfy rwapply-reg-looks-negp
  1957. (if (eq (car expr) 'calcFunc-register)
  1958. (math-neg (math-rwapply-replace-regs expr))
  1959. (if (math-rwapply-reg-looks-negp (nth 1 expr))
  1960. (math-rwapply-replace-regs (list (car expr)
  1961. (math-rwapply-reg-neg (nth 1 expr))
  1962. (nth 2 expr)))
  1963. (math-rwapply-replace-regs (list (car expr)
  1964. (nth 1 expr)
  1965. (math-rwapply-reg-neg (nth 2 expr)))))))
  1966. (defun math-rwapply-remember (old new)
  1967. (let ((varval (symbol-value (nth 2 (car math-apply-rw-ruleset))))
  1968. (rules (assq (car-safe old) math-apply-rw-ruleset)))
  1969. (if (and (eq (car-safe varval) 'vec)
  1970. (not (memq (car-safe old) '(nil schedule + -)))
  1971. rules)
  1972. (progn
  1973. (setcdr varval (cons (list 'calcFunc-assign
  1974. (if (math-rwcomp-no-vars old)
  1975. old
  1976. (list 'calcFunc-quote old))
  1977. new)
  1978. (cdr varval)))
  1979. (setcdr rules (cons (list (vector nil old)
  1980. (list (list 'same 0 1)
  1981. (list 'done new nil))
  1982. nil nil)
  1983. (cdr rules)))))))
  1984. (provide 'calc-rewr)
  1985. ;;; calc-rewr.el ends here