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