Mercurial > emacs
comparison lisp/calc/calc-rewr.el @ 105792:2c12fbae77c2
* calc/calc.el (calc, calc-refresh, calc-trail-buffer, calc-record)
(calcDigit-nondigit):
* calc/calc-yank.el (calc-copy-to-buffer):
* calc/calc-units.el (calc-invalidate-units-table):
* calc/calc-trail.el (calc-trail-yank):
* calc/calc-store.el (calc-insert-variables):
* calc/calc-rewr.el (math-rewrite, math-rewrite-phase):
* calc/calc-prog.el (calc-read-parse-table):
* calc/calc-keypd.el (calc-do-keypad, calc-keypad-right-click):
* calc/calc-help.el (calc-describe-bindings, calc-describe-key):
* calc/calc-graph.el (calc-graph-delete, calc-graph-add-curve)
(calc-graph-juggle, calc-graph-count-curves, calc-graph-plot)
(calc-graph-plot, calc-graph-format-data, calc-graph-set-styles)
(calc-graph-name, calc-graph-find-command, calc-graph-view)
(calc-graph-view, calc-gnuplot-command, calc-graph-init):
* calc/calc-ext.el (calc-realign):
* calc/calc-embed.el (calc-do-embedded, calc-do-embedded)
(calc-embedded-finish-edit, calc-embedded-make-info)
(calc-embedded-finish-command, calc-embedded-stack-change):
* calc/calc-aent.el (calcAlg-enter): Use with-current-buffer.
author | Stefan Monnier <monnier@iro.umontreal.ca> |
---|---|
date | Wed, 28 Oct 2009 18:35:33 +0000 |
parents | a9dc0e7c3f2b |
children | 1d1d5d9bd884 |
comparison
equal
deleted
inserted
replaced
105791:84d7bc7104ac | 105792:2c12fbae77c2 |
---|---|
188 (if result | 188 (if result |
189 (progn | 189 (progn |
190 (if trace-buffer | 190 (if trace-buffer |
191 (let ((fmt (math-format-stack-value | 191 (let ((fmt (math-format-stack-value |
192 (list result nil nil)))) | 192 (list result nil nil)))) |
193 (save-excursion | 193 (with-current-buffer trace-buffer |
194 (set-buffer trace-buffer) | |
195 (insert "\nrewrite to\n" fmt "\n")))) | 194 (insert "\nrewrite to\n" fmt "\n")))) |
196 (setq heads (math-rewrite-heads result heads t)))) | 195 (setq heads (math-rewrite-heads result heads t)))) |
197 result))))) | 196 result))))) |
198 (if trace-buffer | 197 (if trace-buffer |
199 (let ((fmt (math-format-stack-value (list math-rewrite-whole-expr nil nil)))) | 198 (let ((fmt (math-format-stack-value (list math-rewrite-whole-expr nil nil)))) |
200 (save-excursion | 199 (with-current-buffer trace-buffer |
201 (set-buffer trace-buffer) | |
202 (setq truncate-lines t) | 200 (setq truncate-lines t) |
203 (goto-char (point-max)) | 201 (goto-char (point-max)) |
204 (insert "\n\nBegin rewriting\n" fmt "\n")))) | 202 (insert "\n\nBegin rewriting\n" fmt "\n")))) |
205 (or math-mt-many (setq math-mt-many (or (nth 1 (car crules)) | 203 (or math-mt-many (setq math-mt-many (or (nth 1 (car crules)) |
206 math-rewrite-default-iters))) | 204 math-rewrite-default-iters))) |
207 (if (equal math-mt-many '(var inf var-inf)) (setq math-mt-many 1000000)) | 205 (if (equal math-mt-many '(var inf var-inf)) (setq math-mt-many 1000000)) |
208 (if (equal math-mt-many '(neg (var inf var-inf))) (setq math-mt-many -1000000)) | 206 (if (equal math-mt-many '(neg (var inf var-inf))) (setq math-mt-many -1000000)) |
209 (math-rewrite-phase (nth 3 (car crules))) | 207 (math-rewrite-phase (nth 3 (car crules))) |
210 (if trace-buffer | 208 (if trace-buffer |
211 (let ((fmt (math-format-stack-value (list math-rewrite-whole-expr nil nil)))) | 209 (let ((fmt (math-format-stack-value (list math-rewrite-whole-expr nil nil)))) |
212 (save-excursion | 210 (with-current-buffer trace-buffer |
213 (set-buffer trace-buffer) | |
214 (insert "\nDone rewriting" | 211 (insert "\nDone rewriting" |
215 (if (= math-mt-many 0) " (reached iteration limit)" "") | 212 (if (= math-mt-many 0) " (reached iteration limit)" "") |
216 ":\n" fmt "\n")))) | 213 ":\n" fmt "\n")))) |
217 math-rewrite-whole-expr)) | 214 math-rewrite-whole-expr)) |
218 | 215 |
227 (setq math-rewrite-whole-expr | 224 (setq math-rewrite-whole-expr |
228 (math-normalize (list (car sched) math-rewrite-whole-expr))) | 225 (math-normalize (list (car sched) math-rewrite-whole-expr))) |
229 (if trace-buffer | 226 (if trace-buffer |
230 (let ((fmt (math-format-stack-value | 227 (let ((fmt (math-format-stack-value |
231 (list math-rewrite-whole-expr nil nil)))) | 228 (list math-rewrite-whole-expr nil nil)))) |
232 (save-excursion | 229 (with-current-buffer trace-buffer |
233 (set-buffer trace-buffer) | |
234 (insert "\ncall " | 230 (insert "\ncall " |
235 (substring (symbol-name (car sched)) 9) | 231 (substring (symbol-name (car sched)) 9) |
236 ":\n" fmt "\n"))))) | 232 ":\n" fmt "\n"))))) |
237 (let ((math-rewrite-phase (car sched))) | 233 (let ((math-rewrite-phase (car sched))) |
238 (if trace-buffer | 234 (if trace-buffer |
239 (save-excursion | 235 (with-current-buffer trace-buffer |
240 (set-buffer trace-buffer) | |
241 (insert (format "\n(Phase %d)\n" math-rewrite-phase)))) | 236 (insert (format "\n(Phase %d)\n" math-rewrite-phase)))) |
242 (while (let ((save-expr math-rewrite-whole-expr)) | 237 (while (let ((save-expr math-rewrite-whole-expr)) |
243 (setq math-rewrite-whole-expr (math-normalize | 238 (setq math-rewrite-whole-expr (math-normalize |
244 (math-map-tree-rec math-rewrite-whole-expr))) | 239 (math-map-tree-rec math-rewrite-whole-expr))) |
245 (not (equal math-rewrite-whole-expr save-expr))))))) | 240 (not (equal math-rewrite-whole-expr save-expr))))))) |
287 0) | 282 0) |
288 (error (math-reject-arg pat (nth 1 err))))) | 283 (error (math-reject-arg pat (nth 1 err))))) |
289 | 284 |
290 | 285 |
291 | 286 |
292 ;;; A compiled rule set is an a-list of entries whose cars are functors, | 287 ;; A compiled rule set is an a-list of entries whose cars are functors, |
293 ;;; and whose cdrs are lists of rules. If there are rules with no | 288 ;; and whose cdrs are lists of rules. If there are rules with no |
294 ;;; well-defined head functor, they are included on all lists and also | 289 ;; well-defined head functor, they are included on all lists and also |
295 ;;; on an extra list whose car is nil. | 290 ;; on an extra list whose car is nil. |
296 ;;; | 291 ;; |
297 ;;; The first entry in the a-list is of the form (schedule A B C ...). | 292 ;; The first entry in the a-list is of the form (schedule A B C ...). |
298 ;;; | 293 ;; |
299 ;;; Rule list entries take the form (regs prog head phases), where: | 294 ;; Rule list entries take the form (regs prog head phases), where: |
300 ;;; | 295 ;; |
301 ;;; regs is a vector of match registers. | 296 ;; regs is a vector of match registers. |
302 ;;; | 297 ;; |
303 ;;; prog is a match program (see below). | 298 ;; prog is a match program (see below). |
304 ;;; | 299 ;; |
305 ;;; head is a rare function name appearing in the rule body (but not the | 300 ;; head is a rare function name appearing in the rule body (but not the |
306 ;;; head of the whole rule), or nil if none. | 301 ;; head of the whole rule), or nil if none. |
307 ;;; | 302 ;; |
308 ;;; phases is a list of phase numbers for which the rule is enabled. | 303 ;; phases is a list of phase numbers for which the rule is enabled. |
309 ;;; | 304 ;; |
310 ;;; A match program is a list of match instructions. | 305 ;; A match program is a list of match instructions. |
311 ;;; | 306 ;; |
312 ;;; In the following, "part" is a register number that contains the | 307 ;; In the following, "part" is a register number that contains the |
313 ;;; subexpression to be operated on. | 308 ;; subexpression to be operated on. |
314 ;;; | 309 ;; |
315 ;;; Register 0 is the whole expression being matched. The others are | 310 ;; Register 0 is the whole expression being matched. The others are |
316 ;;; meta-variables in the pattern, temporaries used for matching and | 311 ;; meta-variables in the pattern, temporaries used for matching and |
317 ;;; backtracking, and constant expressions. | 312 ;; backtracking, and constant expressions. |
318 ;;; | 313 ;; |
319 ;;; (same part reg) | 314 ;; (same part reg) |
320 ;;; The selected part must be math-equal to the contents of "reg". | 315 ;; The selected part must be math-equal to the contents of "reg". |
321 ;;; | 316 ;; |
322 ;;; (same-neg part reg) | 317 ;; (same-neg part reg) |
323 ;;; The selected part must be math-equal to the negative of "reg". | 318 ;; The selected part must be math-equal to the negative of "reg". |
324 ;;; | 319 ;; |
325 ;;; (copy part reg) | 320 ;; (copy part reg) |
326 ;;; The selected part is copied into "reg". (Rarely used.) | 321 ;; The selected part is copied into "reg". (Rarely used.) |
327 ;;; | 322 ;; |
328 ;;; (copy-neg part reg) | 323 ;; (copy-neg part reg) |
329 ;;; The negative of the selected part is copied into "reg". | 324 ;; The negative of the selected part is copied into "reg". |
330 ;;; | 325 ;; |
331 ;;; (integer part) | 326 ;; (integer part) |
332 ;;; The selected part must be an integer. | 327 ;; The selected part must be an integer. |
333 ;;; | 328 ;; |
334 ;;; (real part) | 329 ;; (real part) |
335 ;;; The selected part must be a real. | 330 ;; The selected part must be a real. |
336 ;;; | 331 ;; |
337 ;;; (constant part) | 332 ;; (constant part) |
338 ;;; The selected part must be a constant. | 333 ;; The selected part must be a constant. |
339 ;;; | 334 ;; |
340 ;;; (negative part) | 335 ;; (negative part) |
341 ;;; The selected part must "look" negative. | 336 ;; The selected part must "look" negative. |
342 ;;; | 337 ;; |
343 ;;; (rel part op reg) | 338 ;; (rel part op reg) |
344 ;;; The selected part must satisfy "part op reg", where "op" | 339 ;; The selected part must satisfy "part op reg", where "op" |
345 ;;; is one of the 6 relational ops, and "reg" is a register. | 340 ;; is one of the 6 relational ops, and "reg" is a register. |
346 ;;; | 341 ;; |
347 ;;; (mod part modulo value) | 342 ;; (mod part modulo value) |
348 ;;; The selected part must satisfy "part % modulo = value", where | 343 ;; The selected part must satisfy "part % modulo = value", where |
349 ;;; "modulo" and "value" are constants. | 344 ;; "modulo" and "value" are constants. |
350 ;;; | 345 ;; |
351 ;;; (func part head reg1 reg2 ... regn) | 346 ;; (func part head reg1 reg2 ... regn) |
352 ;;; The selected part must be an n-ary call to function "head". | 347 ;; The selected part must be an n-ary call to function "head". |
353 ;;; The arguments are stored in "reg1" through "regn". | 348 ;; The arguments are stored in "reg1" through "regn". |
354 ;;; | 349 ;; |
355 ;;; (func-def part head defs reg1 reg2 ... regn) | 350 ;; (func-def part head defs reg1 reg2 ... regn) |
356 ;;; The selected part must be an n-ary call to function "head". | 351 ;; The selected part must be an n-ary call to function "head". |
357 ;;; "Defs" is a list of value/register number pairs for default args. | 352 ;; "Defs" is a list of value/register number pairs for default args. |
358 ;;; If a match, assign default values to registers and then skip | 353 ;; If a match, assign default values to registers and then skip |
359 ;;; immediately over any following "func-def" instructions and | 354 ;; immediately over any following "func-def" instructions and |
360 ;;; the following "func" instruction. If wrong number of arguments, | 355 ;; the following "func" instruction. If wrong number of arguments, |
361 ;;; proceed to the following "func-def" or "func" instruction. | 356 ;; proceed to the following "func-def" or "func" instruction. |
362 ;;; | 357 ;; |
363 ;;; (func-opt part head defs reg1) | 358 ;; (func-opt part head defs reg1) |
364 ;;; Like func-def with "n=1", except that if the selected part is | 359 ;; Like func-def with "n=1", except that if the selected part is |
365 ;;; not a call to "head", then the part itself successfully matches | 360 ;; not a call to "head", then the part itself successfully matches |
366 ;;; "reg1" (and the defaults are assigned). | 361 ;; "reg1" (and the defaults are assigned). |
367 ;;; | 362 ;; |
368 ;;; (try part heads mark reg1 [def]) | 363 ;; (try part heads mark reg1 [def]) |
369 ;;; The selected part must be a function of the correct type which is | 364 ;; The selected part must be a function of the correct type which is |
370 ;;; associative and/or commutative. "Heads" is a list of acceptable | 365 ;; associative and/or commutative. "Heads" is a list of acceptable |
371 ;;; types. An initial assignment of arguments to "reg1" is tried. | 366 ;; types. An initial assignment of arguments to "reg1" is tried. |
372 ;;; If the program later fails, it backtracks to this instruction | 367 ;; If the program later fails, it backtracks to this instruction |
373 ;;; and tries other assignments of arguments to "reg1". | 368 ;; and tries other assignments of arguments to "reg1". |
374 ;;; If "def" exists and normal matching fails, backtrack and assign | 369 ;; If "def" exists and normal matching fails, backtrack and assign |
375 ;;; "part" to "reg1", and "def" to "reg2" in the following "try2". | 370 ;; "part" to "reg1", and "def" to "reg2" in the following "try2". |
376 ;;; The "mark" is a vector of size 5; only "mark[3-4]" are initialized. | 371 ;; The "mark" is a vector of size 5; only "mark[3-4]" are initialized. |
377 ;;; "mark[0]" points to the argument list; "mark[1]" points to the | 372 ;; "mark[0]" points to the argument list; "mark[1]" points to the |
378 ;;; current argument; "mark[2]" is 0 if there are two arguments, | 373 ;; current argument; "mark[2]" is 0 if there are two arguments, |
379 ;;; 1 if reg1 is matching single arguments, 2 if reg2 is matching | 374 ;; 1 if reg1 is matching single arguments, 2 if reg2 is matching |
380 ;;; single arguments (a+b+c+d is never split as (a+b)+(c+d)), or | 375 ;; single arguments (a+b+c+d is never split as (a+b)+(c+d)), or |
381 ;;; 3 if reg2 is matching "def"; "mark[3]" is 0 if the function must | 376 ;; 3 if reg2 is matching "def"; "mark[3]" is 0 if the function must |
382 ;;; have two arguments, 1 if phase-2 can be skipped, 2 if full | 377 ;; have two arguments, 1 if phase-2 can be skipped, 2 if full |
383 ;;; backtracking is necessary; "mark[4]" is t if the arguments have | 378 ;; backtracking is necessary; "mark[4]" is t if the arguments have |
384 ;;; been switched from the order given in the original pattern. | 379 ;; been switched from the order given in the original pattern. |
385 ;;; | 380 ;; |
386 ;;; (try2 try reg2) | 381 ;; (try2 try reg2) |
387 ;;; Every "try" will be followed by a "try2" whose "try" field is | 382 ;; Every "try" will be followed by a "try2" whose "try" field is |
388 ;;; a pointer to the corresponding "try". The arguments which were | 383 ;; a pointer to the corresponding "try". The arguments which were |
389 ;;; not stored in "reg1" by that "try" are now stored in "reg2". | 384 ;; not stored in "reg1" by that "try" are now stored in "reg2". |
390 ;;; | 385 ;; |
391 ;;; (alt instr nil mark) | 386 ;; (alt instr nil mark) |
392 ;;; Basic backtracking. Execute the instruction sequence "instr". | 387 ;; Basic backtracking. Execute the instruction sequence "instr". |
393 ;;; If this fails, back up and execute following the "alt" instruction. | 388 ;; If this fails, back up and execute following the "alt" instruction. |
394 ;;; The "mark" must be the vector "[nil nil 4]". The "instr" sequence | 389 ;; The "mark" must be the vector "[nil nil 4]". The "instr" sequence |
395 ;;; should execute "end-alt" at the end. | 390 ;; should execute "end-alt" at the end. |
396 ;;; | 391 ;; |
397 ;;; (end-alt ptr) | 392 ;; (end-alt ptr) |
398 ;;; Register success of the first alternative of a previous "alt". | 393 ;; Register success of the first alternative of a previous "alt". |
399 ;;; "Ptr" is a pointer to the next instruction following that "alt". | 394 ;; "Ptr" is a pointer to the next instruction following that "alt". |
400 ;;; | 395 ;; |
401 ;;; (apply part reg1 reg2) | 396 ;; (apply part reg1 reg2) |
402 ;;; The selected part must be a function call. The functor | 397 ;; The selected part must be a function call. The functor |
403 ;;; (as a variable name) is stored in "reg1"; the arguments | 398 ;; (as a variable name) is stored in "reg1"; the arguments |
404 ;;; (as a vector) are stored in "reg2". | 399 ;; (as a vector) are stored in "reg2". |
405 ;;; | 400 ;; |
406 ;;; (cons part reg1 reg2) | 401 ;; (cons part reg1 reg2) |
407 ;;; The selected part must be a nonempty vector. The first element | 402 ;; The selected part must be a nonempty vector. The first element |
408 ;;; of the vector is stored in "reg1"; the rest of the vector | 403 ;; of the vector is stored in "reg1"; the rest of the vector |
409 ;;; (as another vector) is stored in "reg2". | 404 ;; (as another vector) is stored in "reg2". |
410 ;;; | 405 ;; |
411 ;;; (rcons part reg1 reg2) | 406 ;; (rcons part reg1 reg2) |
412 ;;; The selected part must be a nonempty vector. The last element | 407 ;; The selected part must be a nonempty vector. The last element |
413 ;;; of the vector is stored in "reg2"; the rest of the vector | 408 ;; of the vector is stored in "reg2"; the rest of the vector |
414 ;;; (as another vector) is stored in "reg1". | 409 ;; (as another vector) is stored in "reg1". |
415 ;;; | 410 ;; |
416 ;;; (select part reg) | 411 ;; (select part reg) |
417 ;;; If the selected part is a unary call to function "select", its | 412 ;; If the selected part is a unary call to function "select", its |
418 ;;; argument is stored in "reg"; otherwise (provided this is an `a r' | 413 ;; argument is stored in "reg"; otherwise (provided this is an `a r' |
419 ;;; and not a `g r' command) the selected part is stored in "reg". | 414 ;; and not a `g r' command) the selected part is stored in "reg". |
420 ;;; | 415 ;; |
421 ;;; (cond expr) | 416 ;; (cond expr) |
422 ;;; The "expr", with registers substituted, must simplify to | 417 ;; The "expr", with registers substituted, must simplify to |
423 ;;; a non-zero value. | 418 ;; a non-zero value. |
424 ;;; | 419 ;; |
425 ;;; (let reg expr) | 420 ;; (let reg expr) |
426 ;;; Evaluate "expr" and store the result in "reg". Always succeeds. | 421 ;; Evaluate "expr" and store the result in "reg". Always succeeds. |
427 ;;; | 422 ;; |
428 ;;; (done rhs remember) | 423 ;; (done rhs remember) |
429 ;;; Rewrite the expression to "rhs", with register substituted. | 424 ;; Rewrite the expression to "rhs", with register substituted. |
430 ;;; Normalize; if the result is different from the original | 425 ;; Normalize; if the result is different from the original |
431 ;;; expression, the match has succeeded. This is the last | 426 ;; expression, the match has succeeded. This is the last |
432 ;;; instruction of every program. If "remember" is non-nil, | 427 ;; instruction of every program. If "remember" is non-nil, |
433 ;;; record the result of the match as a new literal rule. | 428 ;; record the result of the match as a new literal rule. |
434 | 429 |
435 | 430 |
436 ;;; Pseudo-functions related to rewrites: | 431 ;; Pseudo-functions related to rewrites: |
437 ;;; | 432 ;; |
438 ;;; In patterns: quote, plain, condition, opt, apply, cons, select | 433 ;; In patterns: quote, plain, condition, opt, apply, cons, select |
439 ;;; | 434 ;; |
440 ;;; In righthand sides: quote, plain, eval, evalsimp, evalextsimp, | 435 ;; In righthand sides: quote, plain, eval, evalsimp, evalextsimp, |
441 ;;; apply, cons, select | 436 ;; apply, cons, select |
442 ;;; | 437 ;; |
443 ;;; In conditions: let + same as for righthand sides | 438 ;; In conditions: let + same as for righthand sides |
444 | 439 |
445 ;;; Some optimizations that would be nice to have: | 440 ;; Some optimizations that would be nice to have: |
446 ;;; | 441 ;; |
447 ;;; * Merge registers with disjoint lifetimes. | 442 ;; * Merge registers with disjoint lifetimes. |
448 ;;; * Merge constant registers with equivalent values. | 443 ;; * Merge constant registers with equivalent values. |
449 ;;; | 444 ;; |
450 ;;; * If an argument of a commutative op math-depends neither on the | 445 ;; * If an argument of a commutative op math-depends neither on the |
451 ;;; rest of the pattern nor on any of the conditions, then no backtracking | 446 ;; rest of the pattern nor on any of the conditions, then no backtracking |
452 ;;; should be done for that argument. (This won't apply to very many | 447 ;; should be done for that argument. (This won't apply to very many |
453 ;;; cases.) | 448 ;; cases.) |
454 ;;; | 449 ;; |
455 ;;; * If top functor is "select", and its argument is a unique function, | 450 ;; * If top functor is "select", and its argument is a unique function, |
456 ;;; add the rule to the lists for both "select" and that function. | 451 ;; add the rule to the lists for both "select" and that function. |
457 ;;; (Currently rules like this go on the "nil" list.) | 452 ;; (Currently rules like this go on the "nil" list.) |
458 ;;; Same for "func-opt" functions. (Though not urgent for these.) | 453 ;; Same for "func-opt" functions. (Though not urgent for these.) |
459 ;;; | 454 ;; |
460 ;;; * Shouldn't evaluate a "let" condition until the end, or until it | 455 ;; * Shouldn't evaluate a "let" condition until the end, or until it |
461 ;;; would enable another condition to be evaluated. | 456 ;; would enable another condition to be evaluated. |
462 ;;; | 457 ;; |
463 | 458 |
464 ;;; Some additional features to add / things to think about: | 459 ;; Some additional features to add / things to think about: |
465 ;;; | 460 ;;; |
466 ;;; * Figure out what happens to "a +/- b" and "a +/- opt(b)". | 461 ;;; * Figure out what happens to "a +/- b" and "a +/- opt(b)". |
467 ;;; | 462 ;;; |
468 ;;; * Same for interval forms. | 463 ;;; * Same for interval forms. |
469 ;;; | 464 ;;; |
1329 | 1324 |
1330 (defun math-rwcomp-order (a b) | 1325 (defun math-rwcomp-order (a b) |
1331 (< (math-rwcomp-priority (car a)) | 1326 (< (math-rwcomp-priority (car a)) |
1332 (math-rwcomp-priority (car b)))) | 1327 (math-rwcomp-priority (car b)))) |
1333 | 1328 |
1334 ;;; Order of priority: 0 Constants and other exact matches (first) | 1329 ;; Order of priority: 0 Constants and other exact matches (first) |
1335 ;;; 10 Functions (except below) | 1330 ;; 10 Functions (except below) |
1336 ;;; 20 Meta-variables which occur more than once | 1331 ;; 20 Meta-variables which occur more than once |
1337 ;;; 30 Algebraic functions | 1332 ;; 30 Algebraic functions |
1338 ;;; 40 Commutative/associative functions | 1333 ;; 40 Commutative/associative functions |
1339 ;;; 50 Meta-variables which occur only once | 1334 ;; 50 Meta-variables which occur only once |
1340 ;;; +100 for every "!!!" (pnot) in the pattern | 1335 ;; +100 for every "!!!" (pnot) in the pattern |
1341 ;;; 10000 Optional arguments (last) | 1336 ;; 10000 Optional arguments (last) |
1342 | 1337 |
1343 (defun math-rwcomp-priority (expr) | 1338 (defun math-rwcomp-priority (expr) |
1344 (+ (math-rwcomp-count-pnots expr) | 1339 (+ (math-rwcomp-count-pnots expr) |
1345 (cond ((eq (car-safe expr) 'calcFunc-opt) | 1340 (cond ((eq (car-safe expr) 'calcFunc-opt) |
1346 10000) | 1341 10000) |
1388 (let ((count 0)) | 1383 (let ((count 0)) |
1389 (while (setq expr (cdr expr)) | 1384 (while (setq expr (cdr expr)) |
1390 (setq count (+ count (math-rwcomp-count-pnots (car expr))))) | 1385 (setq count (+ count (math-rwcomp-count-pnots (car expr))))) |
1391 count)))) | 1386 count)))) |
1392 | 1387 |
1393 ;;; In the current implementation, all associative functions must | 1388 ;; In the current implementation, all associative functions must |
1394 ;;; also be commutative. | 1389 ;; also be commutative. |
1395 | 1390 |
1396 (put '+ 'math-rewrite-props '(algebraic assoc commut)) | 1391 (put '+ 'math-rewrite-props '(algebraic assoc commut)) |
1397 (put '- 'math-rewrite-props '(algebraic assoc commut)) ; see below | 1392 (put '- 'math-rewrite-props '(algebraic assoc commut)) ; see below |
1398 (put '* 'math-rewrite-props '(algebraic assoc commut)) ; see below | 1393 (put '* 'math-rewrite-props '(algebraic assoc commut)) ; see below |
1399 (put '/ 'math-rewrite-props '(algebraic unary1)) | 1394 (put '/ 'math-rewrite-props '(algebraic unary1)) |
1427 (put 'calcFunc-min 'math-rewrite-props '(algebraic assoc commut)) | 1422 (put 'calcFunc-min 'math-rewrite-props '(algebraic assoc commut)) |
1428 (put 'calcFunc-vunion 'math-rewrite-props '(assoc commut)) | 1423 (put 'calcFunc-vunion 'math-rewrite-props '(assoc commut)) |
1429 (put 'calcFunc-vint 'math-rewrite-props '(assoc commut)) | 1424 (put 'calcFunc-vint 'math-rewrite-props '(assoc commut)) |
1430 (put 'calcFunc-vxor 'math-rewrite-props '(assoc commut)) | 1425 (put 'calcFunc-vxor 'math-rewrite-props '(assoc commut)) |
1431 | 1426 |
1432 ;;; Note: "*" is not commutative for matrix args, but we pretend it is. | 1427 ;; Note: "*" is not commutative for matrix args, but we pretend it is. |
1433 ;;; Also, "-" is not commutative but the code tweaks things so that it is. | 1428 ;; Also, "-" is not commutative but the code tweaks things so that it is. |
1434 | 1429 |
1435 (put '+ 'math-rewrite-default 0) | 1430 (put '+ 'math-rewrite-default 0) |
1436 (put '- 'math-rewrite-default 0) | 1431 (put '- 'math-rewrite-default 0) |
1437 (put '* 'math-rewrite-default 1) | 1432 (put '* 'math-rewrite-default 1) |
1438 (put '/ 'math-rewrite-default 1) | 1433 (put '/ 'math-rewrite-default 1) |
1450 (if back | 1445 (if back |
1451 '(setq btrack (cdr btrack)) | 1446 '(setq btrack (cdr btrack)) |
1452 'btrack) | 1447 'btrack) |
1453 ''((backtrack))))) | 1448 ''((backtrack))))) |
1454 | 1449 |
1455 ;;; This monstrosity is necessary because the use of static vectors of | 1450 ;; This monstrosity is necessary because the use of static vectors of |
1456 ;;; registers makes rewrite rules non-reentrant. Yucko! | 1451 ;; registers makes rewrite rules non-reentrant. Yucko! |
1457 (defmacro math-rweval (form) | 1452 (defmacro math-rweval (form) |
1458 (list 'let '((orig (car rules))) | 1453 (list 'let '((orig (car rules))) |
1459 '(setcar rules (quote (nil nil nil no-phase))) | 1454 '(setcar rules (quote (nil nil nil no-phase))) |
1460 (list 'unwind-protect | 1455 (list 'unwind-protect |
1461 form | 1456 form |