daveg@csvax.caltech.edu (David Gillespie) (06/06/90)
Posting-number: Volume 13, Issue 35 Submitted-by: daveg@csvax.caltech.edu (David Gillespie) Archive-name: gmcalc/part09 ---- Cut Here and unpack ---- #!/bin/sh # this is part 9 of a multipart archive # do not concatenate these parts, unpack them in order with /bin/sh # file calc-ext.el continued # CurArch=9 if test ! -r s2_seq_.tmp then echo "Please unpack part 1 first!" exit 1; fi ( read Scheck if test "$Scheck" != $CurArch then echo "Please unpack part $Scheck next!" exit 1; else exit 0; fi ) < s2_seq_.tmp || exit 1 echo "x - Continuing file calc-ext.el" sed 's/^X//' << 'SHAR_EOF' >> calc-ext.el X 1153 1163 1171 1181 1187 1193 1201 1213 1217 1223 1229 1231 1237 1249 X 1259 1277 1279 1283 1289 1291 1297 1301 1303 1307 1319 1321 1327 1361 X 1367 1373 1381 1399 1409 1423 1427 1429 1433 1439 1447 1451 1453 1459 X 1471 1481 1483 1487 1489 1493 1499 1511 1523 1531 1543 1549 1553 1559 X 1567 1571 1579 1583 1597 1601 1607 1609 1613 1619 1621 1627 1637 1657 X 1663 1667 1669 1693 1697 1699 1709 1721 1723 1733 1741 1747 1753 1759 X 1777 1783 1787 1789 1801 1811 1823 1831 1847 1861 1867 1871 1873 1877 X 1879 1889 1901 1907 1913 1931 1933 1949 1951 1973 1979 1987 1993 1997 X 1999 2003 2011 2017 2027 2029 2039 2053 2063 2069 2081 2083 2087 2089 X 2099 2111 2113 2129 2131 2137 2141 2143 2153 2161 2179 2203 2207 2213 X 2221 2237 2239 2243 2251 2267 2269 2273 2281 2287 2293 2297 2309 2311 X 2333 2339 2341 2347 2351 2357 2371 2377 2381 2383 2389 2393 2399 2411 X 2417 2423 2437 2441 2447 2459 2467 2473 2477 2503 2521 2531 2539 2543 X 2549 2551 2557 2579 2591 2593 2609 2617 2621 2633 2647 2657 2659 2663 X 2671 2677 2683 2687 2689 2693 2699 2707 2711 2713 2719 2729 2731 2741 X 2749 2753 2767 2777 2789 2791 2797 2801 2803 2819 2833 2837 2843 2851 X 2857 2861 2879 2887 2897 2903 2909 2917 2927 2939 2953 2957 2963 2969 X 2971 2999 3001 3011 3019 3023 3037 3041 3049 3061 3067 3079 3083 3089 X 3109 3119 3121 3137 3163 3167 3169 3181 3187 3191 3203 3209 3217 3221 X 3229 3251 3253 3257 3259 3271 3299 3301 3307 3313 3319 3323 3329 3331 X 3343 3347 3359 3361 3371 3373 3389 3391 3407 3413 3433 3449 3457 3461 X 3463 3467 3469 3491 3499 3511 3517 3527 3529 3533 3539 3541 3547 3557 X 3559 3571 3581 3583 3593 3607 3613 3617 3623 3631 3637 3643 3659 3671 X 3673 3677 3691 3697 3701 3709 3719 3727 3733 3739 3761 3767 3769 3779 X 3793 3797 3803 3821 3823 3833 3847 3851 3853 3863 3877 3881 3889 3907 X 3911 3917 3919 3923 3929 3931 3943 3947 3967 3989 4001 4003 4007 4013 X 4019 4021 4027 4049 4051 4057 4073 4079 4091 4093 4099 4111 4127 4129 X 4133 4139 4153 4157 4159 4177 4201 4211 4217 4219 4229 4231 4241 4243 X 4253 4259 4261 4271 4273 4283 4289 4297 4327 4337 4339 4349 4357 4363 X 4373 4391 4397 4409 4421 4423 4441 4447 4451 4457 4463 4481 4483 4493 X 4507 4513 4517 4519 4523 4547 4549 4561 4567 4583 4591 4597 4603 4621 X 4637 4639 4643 4649 4651 4657 4663 4673 4679 4691 4703 4721 4723 4729 X 4733 4751 4759 4783 4787 4789 4793 4799 4801 4813 4817 4831 4861 4871 X 4877 4889 4903 4909 4919 4931 4933 4937 4943 4951 4957 4967 4969 4973 X 4987 4993 4999 5003]) X X X X X;;; Bitwise operations. X X(defun math-and (a b &optional w) ; [I I I] [Public] X (cond ((Math-messy-integerp w) X (math-and a b (math-trunc w))) X ((and w (not (integerp w))) X (math-reject-arg w 'integerp)) X ((and (integerp a) (integerp b)) X (math-clip (logand a b) w)) X ((or (eq (car-safe a) 'mod) (eq (car-safe b) 'mod)) X (math-binary-modulo-args 'math-and a b w)) X ((not (Math-num-integerp a)) X (math-reject-arg a 'integerp)) X ((not (Math-num-integerp b)) X (math-reject-arg b 'integerp)) X (t (math-clip (cons 'bigpos X (math-and-bignum (math-binary-arg a w) X (math-binary-arg b w))) X w))) X) X(fset 'calcFunc-and (symbol-function 'math-and)) X X(defun math-binary-arg (a w) X (if (not (Math-integerp a)) X (setq a (math-trunc a))) X (if (Math-integer-negp a) X (math-not-bignum (cdr (math-bignum-test (math-sub -1 a))) X (math-abs (if w (math-trunc w) calc-word-size))) X (cdr (Math-bignum-test a))) X) X X(defun math-binary-modulo-args (f a b w) X (let (mod) X (if (eq (car-safe a) 'mod) X (progn X (setq mod (nth 2 a) X a (nth 1 a)) X (if (eq (car-safe b) 'mod) X (if (equal mod (nth 2 b)) X (setq b (nth 1 b)) X (math-reject-arg b "Inconsistent modulos")))) X (setq mod (nth 2 b) X b (nth 1 b))) X (if (Math-messy-integerp mod) X (setq mod (math-trunc mod)) X (or (Math-integerp mod) X (math-reject-arg mod 'integerp))) X (let ((bits (math-integer-log2 mod))) X (if bits X (if w X (if (/= w bits) X (calc-record-why X "Warning: Modulo inconsistent with word size")) X (setq w bits)) X (calc-record-why "Warning: Modulo is not a power of 2")) X (math-make-mod (if b X (funcall f a b w) X (funcall f a w)) X mod))) X) X X(defun math-and-bignum (a b) ; [l l l] X (and a b X (let ((qa (math-div-bignum-digit a 512)) X (qb (math-div-bignum-digit b 512))) X (math-mul-bignum-digit (math-and-bignum (math-norm-bignum (car qa)) X (math-norm-bignum (car qb))) X 512 X (logand (cdr qa) (cdr qb))))) X) X X(defun math-or (a b &optional w) ; [I I I] [Public] X (cond ((Math-messy-integerp w) X (math-or a b (math-trunc w))) X ((and w (not (integerp w))) X (math-reject-arg w 'integerp)) X ((and (integerp a) (integerp b)) X (math-clip (logior a b) w)) X ((or (eq (car-safe a) 'mod) (eq (car-safe b) 'mod)) X (math-binary-modulo-args 'math-or a b w)) X ((not (Math-num-integerp a)) X (math-reject-arg a 'integerp)) X ((not (Math-num-integerp b)) X (math-reject-arg b 'integerp)) X (t (math-clip (cons 'bigpos X (math-or-bignum (math-binary-arg a w) X (math-binary-arg b w))) X w))) X) X(fset 'calcFunc-or (symbol-function 'math-or)) X X(defun math-or-bignum (a b) ; [l l l] X (and (or a b) X (let ((qa (math-div-bignum-digit a 512)) X (qb (math-div-bignum-digit b 512))) X (math-mul-bignum-digit (math-or-bignum (math-norm-bignum (car qa)) X (math-norm-bignum (car qb))) X 512 X (logior (cdr qa) (cdr qb))))) X) X X(defun math-xor (a b &optional w) ; [I I I] [Public] X (cond ((Math-messy-integerp w) X (math-xor a b (math-trunc w))) X ((and w (not (integerp w))) X (math-reject-arg w 'integerp)) X ((and (integerp a) (integerp b)) X (math-clip (logxor a b) w)) X ((or (eq (car-safe a) 'mod) (eq (car-safe b) 'mod)) X (math-binary-modulo-args 'math-xor a b w)) X ((not (Math-num-integerp a)) X (math-reject-arg a 'integerp)) X ((not (Math-num-integerp b)) X (math-reject-arg b 'integerp)) X (t (math-clip (cons 'bigpos X (math-xor-bignum (math-binary-arg a w) X (math-binary-arg b w))) X w))) X) X(fset 'calcFunc-xor (symbol-function 'math-xor)) X X(defun math-xor-bignum (a b) ; [l l l] X (and (or a b) X (let ((qa (math-div-bignum-digit a 512)) X (qb (math-div-bignum-digit b 512))) X (math-mul-bignum-digit (math-xor-bignum (math-norm-bignum (car qa)) X (math-norm-bignum (car qb))) X 512 X (logxor (cdr qa) (cdr qb))))) X) X X(defun math-diff (a b &optional w) ; [I I I] [Public] X (cond ((Math-messy-integerp w) X (math-diff a b (math-trunc w))) X ((and w (not (integerp w))) X (math-reject-arg w 'integerp)) X ((and (integerp a) (integerp b)) X (math-clip (logand a (lognot b)) w)) X ((or (eq (car-safe a) 'mod) (eq (car-safe b) 'mod)) X (math-binary-modulo-args 'math-diff a b w)) X ((not (Math-num-integerp a)) X (math-reject-arg a 'integerp)) X ((not (Math-num-integerp b)) X (math-reject-arg b 'integerp)) X (t (math-clip (cons 'bigpos X (math-diff-bignum (math-binary-arg a w) X (math-binary-arg b w))) X w))) X) X(fset 'calcFunc-diff (symbol-function 'math-diff)) X X(defun math-diff-bignum (a b) ; [l l l] X (and a X (let ((qa (math-div-bignum-digit a 512)) X (qb (math-div-bignum-digit b 512))) X (math-mul-bignum-digit (math-diff-bignum (math-norm-bignum (car qa)) X (math-norm-bignum (car qb))) X 512 X (logand (cdr qa) (lognot (cdr qb)))))) X) X X(defun math-not (a &optional w) ; [I I] [Public] X (cond ((Math-messy-integerp w) X (math-not a (math-trunc w))) X ((eq (car-safe a) 'mod) X (math-binary-modulo-args 'math-not a nil w)) X ((and w (not (integerp w))) X (math-reject-arg w 'integerp)) X ((not (Math-num-integerp a)) X (math-reject-arg a 'integerp)) X ((< (or w (setq w calc-word-size)) 0) X (math-clip (math-not a (- w)) w)) X (t (math-normalize X (cons 'bigpos X (math-not-bignum (math-binary-arg a w) X w))))) X) X(fset 'calcFunc-not (symbol-function 'math-not)) X X(defun math-not-bignum (a w) ; [l l] X (let ((q (math-div-bignum-digit a 512))) X (if (<= w 9) X (list (logand (lognot (cdr q)) X (1- (lsh 1 w)))) X (math-mul-bignum-digit (math-not-bignum (math-norm-bignum (car q)) X (- w 9)) X 512 X (logxor (cdr q) 511)))) X) X X(defun math-lshift-binary (a &optional n w) ; [I I] [Public] X (setq a (math-trunc a) X n (if n (math-trunc n) 1)) X (if (eq (car-safe a) 'mod) X (math-binary-modulo-args 'math-lshift-binary a n w) X (setq w (if w (math-trunc w) calc-word-size)) X (or (integerp w) X (math-reject-arg w 'integerp)) X (or (Math-integerp a) X (math-reject-arg a 'integerp)) X (or (Math-integerp n) X (math-reject-arg n 'integerp)) X (if (< w 0) X (math-clip (math-lshift-binary a n (- w)) w) X (if (Math-integer-negp a) X (setq a (math-clip a w))) X (cond ((or (Math-lessp n (- w)) X (Math-lessp w n)) X 0) X ((< n 0) X (math-quotient (math-clip a w) (math-power-of-2 (- n)))) X (t X (math-clip (math-mul a (math-power-of-2 n)) w))))) X) X(fset 'calcFunc-lsh (symbol-function 'math-lshift-binary)) X X(defun math-rshift-binary (a &optional n w) ; [I I] [Public] X (math-lshift-binary a (math-neg (or n 1)) w) X) X(fset 'calcFunc-rsh (symbol-function 'math-rshift-binary)) X X(defun math-shift-binary (a &optional n w) ; [I I] [Public] X (if (not (Math-negp n)) X (math-lshift-binary a n w) X (setq a (math-trunc a) X n (if n (math-trunc n) 1)) X (if (eq (car-safe a) 'mod) X (math-binary-modulo-args 'math-shift-binary a n w) X (setq w (if w (math-trunc w) calc-word-size)) X (or (integerp w) X (math-reject-arg w 'integerp)) X (or (Math-integerp a) X (math-reject-arg a 'integerp)) X (or (Math-integerp n) X (math-reject-arg n 'integerp)) X (if (< w 0) X (math-clip (math-shift-binary a n (- w)) w) X (if (Math-integer-negp a) X (setq a (math-clip a w))) X (let ((two-to-sizem1 (math-power-of-2 (1- w))) X (sh (math-lshift-binary a n w))) X (cond ((Math-natnum-lessp a two-to-sizem1) X sh) X ((Math-lessp n (- 1 w)) X (math-add (math-mul two-to-sizem1 2) -1)) X (t (let ((two-to-n (math-power-of-2 (- n)))) X (math-add (math-lshift-binary (math-add two-to-n -1) X (+ w n) w) X sh)))))))) X) X(fset 'calcFunc-ash (symbol-function 'math-shift-binary)) X X(defun math-rotate-binary (a &optional n w) ; [I I] [Public] X (setq a (math-trunc a) X n (if n (math-trunc n) 1)) X (if (eq (car-safe a) 'mod) X (math-binary-modulo-args 'math-rotate-binary a n w) X (setq w (if w (math-trunc w) calc-word-size)) X (or (integerp w) X (math-reject-arg w 'integerp)) X (or (Math-integerp a) X (math-reject-arg a 'integerp)) X (or (Math-integerp n) X (math-reject-arg n 'integerp)) X (if (< w 0) X (math-clip (math-rotate-binary a n (- w)) w) X (if (Math-integer-negp a) X (setq a (math-clip a w))) X (cond ((or (Math-integer-negp n) X (not (Math-natnum-lessp n w))) X (math-rotate-binary a (math-mod n w) w)) X (t X (math-add (math-lshift-binary a (- n w) w) X (math-lshift-binary a n w)))))) X) X(fset 'calcFunc-rot (symbol-function 'math-rotate-binary)) X X(defun math-clip (a &optional w) ; [I I] [Public] X (cond ((Math-messy-integerp w) X (math-clip a (math-trunc w))) X ((eq (car-safe a) 'mod) X (math-binary-modulo-args 'math-clip a nil w)) X ((and w (not (integerp w))) X (math-reject-arg w 'integerp)) X ((not (Math-num-integerp a)) X (math-reject-arg a 'integerp)) X ((< (or w (setq w calc-word-size)) 0) X (setq a (math-clip a (- w))) X (if (Math-natnum-lessp a (math-power-of-2 (- -1 w))) X a X (math-sub a (math-power-of-2 (- w))))) X ((Math-negp a) X (math-normalize (cons 'bigpos (math-binary-arg a w)))) X ((and (integerp a) (< a 1000000)) X (if (>= w 20) X a X (logand a (1- (lsh 1 w))))) X (t X (math-normalize X (cons 'bigpos X (math-clip-bignum (cdr (math-bignum-test (math-trunc a))) X w))))) X) X(fset 'calcFunc-clip (symbol-function 'math-clip)) X X(defun math-clip-bignum (a w) ; [l l] X (let ((q (math-div-bignum-digit a 512))) X (if (<= w 9) X (list (logand (cdr q) X (1- (lsh 1 w)))) X (math-mul-bignum-digit (math-clip-bignum (math-norm-bignum (car q)) X (- w 9)) X 512 X (cdr q)))) X) X X X X;;;; Algebra. X X;;; Evaluate variables in an expression. X(defun math-evaluate-expr (x) ; [Public] X (math-normalize (math-evaluate-expr-rec x)) X) X X(defun math-evaluate-expr-rec (x) X (if (consp x) X (setq x (cons (car x) X (mapcar 'math-evaluate-expr-rec (cdr x))))) X (if (eq (car-safe x) 'var) X (if (and (boundp (nth 2 x)) X (symbol-value (nth 2 x)) X (not (eq (car-safe (symbol-value (nth 2 x))) X 'incomplete))) X (let ((val (symbol-value (nth 2 x)))) X (if (eq (car-safe val) 'special-const) X (if calc-symbolic-mode X x X val) X val)) X x) X x) X) X X X;;; Combine two terms being added, if possible. X(defun math-combine-sum (a b nega negb scalar-okay) X (if (and scalar-okay (Math-objvecp a) (Math-objvecp b)) X (math-add-or-sub a b nega negb) X (let ((amult 1) (bmult 1)) X (and (consp a) X (cond ((and (eq (car a) '*) X (Math-numberp (nth 1 a))) X (setq amult (nth 1 a) X a (nth 2 a))) X ((and (eq (car a) '/) X (Math-numberp (nth 2 a))) X (setq amult (if (Math-integerp (nth 2 a)) X (list 'frac 1 (nth 2 a)) X (math-div 1 (nth 2 a))) X a (nth 1 a))) X ((eq (car a) 'neg) X (setq amult -1 X a (nth 1 a))))) X (and (consp b) X (cond ((and (eq (car b) '*) X (Math-numberp (nth 1 b))) X (setq bmult (nth 1 b) X b (nth 2 b))) X ((and (eq (car b) '/) X (Math-numberp (nth 2 b))) X (setq bmult (if (Math-integerp (nth 2 b)) X (list 'frac 1 (nth 2 b)) X (math-div 1 (nth 2 b))) X b (nth 1 b))) X ((eq (car b) 'neg) X (setq bmult -1 X b (nth 1 b))))) X (and (equal a b) X (progn X (if nega (setq amult (math-neg amult))) X (if negb (setq bmult (math-neg bmult))) X (setq amult (math-add amult bmult)) X (math-mul amult a))))) X) X X(defun math-add-or-sub (a b aneg bneg) X (if aneg (setq a (math-neg a))) X (if bneg (setq b (math-neg b))) X (math-add a b) X) X X;;; The following is expanded out four ways for speed. X(defun math-combine-prod (a b inva invb scalar-okay) X (cond X ((and scalar-okay (Math-objvecp a) (Math-objvecp b)) X (math-mul-or-div a b inva invb)) X ((and (eq (car-safe a) '^) X inva X (math-looks-negp (nth 2 a))) X (math-mul (math-pow (nth 1 a) (math-neg (nth 2 a))) b)) X ((and (eq (car-safe b) '^) X invb X (math-looks-negp (nth 2 b))) X (math-mul a (math-pow (nth 1 b) (math-neg (nth 2 b))))) X (t (let ((apow 1) (bpow 1)) X (and (consp a) X (cond ((and (eq (car a) '^) X (or math-simplify-symbolic-powers X (Math-numberp (nth 2 a)))) X (setq apow (nth 2 a) X a (nth 1 a))) X ((and (eq (car a) 'calcFunc-sqrt)) X (setq apow '(frac 1 2) X a (nth 1 a))))) X (and (consp b) X (cond ((and (eq (car b) '^) X (or math-simplify-symbolic-powers X (Math-numberp (nth 2 b)))) X (setq bpow (nth 2 b) X b (nth 1 b))) X ((and (eq (car b) 'calcFunc-sqrt)) X (setq bpow '(frac 1 2) X b (nth 1 b))))) X (and (equal a b) X (progn X (if inva (setq apow (math-neg apow))) X (if invb (setq bpow (math-neg bpow))) X (setq apow (math-add apow bpow)) X (cond ((equal apow '(frac 1 2)) X (list 'calcFunc-sqrt a)) X ((equal apow '(frac -1 2)) X (math-div 1 (list 'calcFunc-sqrt a))) X (t (math-pow a apow)))))))) X) X(setq math-simplify-symbolic-powers nil) X X(defun math-mul-or-div (a b ainv binv) X (if ainv X (if binv X (math-div (math-div 1 a) b) X (math-div b a)) X (if binv X (math-div a b) X (math-mul a b))) X) X X X X;;; True if A comes before B in a canonical ordering of expressions. [P X X] X(defun math-beforep (a b) ; [Public] X (cond ((and (Math-realp a) (Math-realp b)) X (let ((comp (math-compare a b))) X (or (eq comp -1) X (and (eq comp 0) X (not (equal a b)) X (> (length (memq (car-safe a) X '(bigneg nil bigpos frac float))) X (length (memq (car-safe b) X '(bigneg nil bigpos frac float)))))))) X ((Math-realp a) t) X ((Math-realp b) nil) X ((eq (car a) 'var) X (if (eq (car b) 'var) X (string-lessp (symbol-name (nth 1 a)) (symbol-name (nth 1 b))) X (not (Math-numberp b)))) X ((eq (car b) 'var) (Math-numberp a)) X ((eq (car a) (car b)) X (while (and (setq a (cdr a) b (cdr b)) a X (equal (car a) (car b)))) X (and b X (or (null a) X (math-beforep (car a) (car b))))) X (t (string-lessp (symbol-name (car a)) (symbol-name (car b))))) X) X X X X(setq math-living-dangerously nil) ; true if unsafe simplifications are okay. X X(defun math-simplify-extended (a) X (let ((math-living-dangerously t)) X (math-simplify a)) X) X X(defun math-simplify (top-expr) X (calc-with-default-simplification X (let ((math-simplify-symbolic-powers t) X res) X (while (not (equal top-expr (setq res (math-simplify-step X (math-normalize top-expr))))) X (setq top-expr res)))) X top-expr X) X X;;; The following has a "bug" in that if any recursive simplifications X;;; occur only the first handler will be tried; this doesn't really X;;; matter, since math-simplify-step is iterated to a fixed point anyway. X(defun math-simplify-step (a) X (if (Math-primp a) X a X (let ((aa (cons (car a) (mapcar 'math-simplify-step (cdr a))))) X (and (symbolp (car aa)) X (let ((handler (get (car aa) 'math-simplify))) X (and handler X (progn X (while (and handler X (equal (setq aa (or (funcall (car handler) aa) X aa)) X a)) X (setq handler (cdr handler))) X res)))) X aa)) X) X X(defmacro math-defsimplify (funcs &rest code) X "Define a simplification rule for the specified function. XIf FUNCS is a list of functions, the same rule is applied for each function. XCODE is a body of Lisp code that returns a simpler form of EXPR. XMore than one definition may be made per function. All definitions are tried Xin the order they were encountered; the first non-NIL value which is different Xfrom the original expression returned is used. The argument EXPR may be Xdestructively modified." X (append '(progn) X (mapcar (function X (lambda (func) X (list 'put (list 'quote func) ''math-simplify X (list 'nconc X (list 'get (list 'quote func) ''math-simplify) X (list 'list X (list 'function X (append '(lambda (expr)) X code))))))) X (if (symbolp funcs) (list funcs) funcs))) X) X(put 'math-defsimplify 'lisp-indent-hook 1) X X(math-defsimplify (+ -) X (math-simplify-plus)) X X(defun math-simplify-plus () X (cond ((and (memq (car-safe (nth 1 expr)) '(+ -)) X (Math-numberp (nth 2 (nth 1 expr))) X (not (Math-numberp (nth 2 expr)))) X (let ((x (nth 2 expr)) X (op (car expr))) X (setcar (cdr (cdr expr)) (nth 2 (nth 1 expr))) X (setcar expr (car (nth 1 expr))) X (setcar (cdr (cdr (nth 1 expr))) x) X (setcar (nth 1 expr) op))) X ((and (eq (car expr) '+) X (Math-numberp (nth 1 expr)) X (not (Math-numberp (nth 2 expr)))) X (let ((x (nth 2 expr))) X (setcar (cdr (cdr expr)) (nth 1 expr)) X (setcar (cdr expr) x)))) X (let ((aa expr) X aaa temp) X (while (memq (car-safe (setq aaa (nth 1 aa))) '(+ -)) X (if (setq temp (math-combine-sum (nth 2 aaa) (nth 2 expr) X (eq (car aaa) '-) (eq (car expr) '-) t)) X (progn X (setcar (cdr (cdr expr)) temp) X (setcar expr '+) X (setcar (cdr (cdr aaa)) 0))) X (setq aa (nth 1 aa))) X (if (setq temp (math-combine-sum aaa (nth 2 expr) X nil (eq (car expr) '-) t)) X (progn X (setcar (cdr (cdr expr)) temp) X (setcar expr '+) X (setcar (cdr aa) 0))) X expr) X) X X(math-defsimplify * X (math-simplify-times)) X X(defun math-simplify-times () X (if (eq (car-safe (nth 2 expr)) '*) X (and (math-beforep (nth 1 (nth 2 expr)) (nth 1 expr)) X (let ((x (nth 1 expr))) X (setcar (cdr expr) (nth 1 (nth 2 expr))) X (setcar (cdr (nth 2 expr)) x))) X (and (math-beforep (nth 2 expr) (nth 1 expr)) X (let ((x (nth 2 expr))) X (setcar (cdr (cdr expr)) (nth 1 expr)) X (setcar (cdr expr) x)))) X (let ((aa expr) X aaa temp) X (while (eq (car-safe (setq aaa (nth 2 aa))) '*) X (if (setq temp (math-combine-prod (nth 1 expr) (nth 1 aaa) nil nil t)) X (progn X (setcar (cdr expr) temp) X (setcar (cdr aaa) 1))) X (setq aa (nth 2 aa))) X (if (setq temp (math-combine-prod aaa (nth 1 expr) nil nil t)) X (progn X (setcar (cdr expr) temp) X (setcar (cdr (cdr aa)) 1))) X expr) X) X X(math-defsimplify / X (math-simplify-divide)) X X(defun math-simplify-divide () X (let ((np (cdr expr)) X n nn) X (setq nn (math-common-constant-factor (nth 2 expr))) X (if nn X (progn X (setq n (math-common-constant-factor (nth 1 expr))) X (if (and (consp nn) (eq (nth 1 nn) 1) (not n)) X (progn X (setcar (cdr expr) (math-mul (nth 1 expr) nn)) X (setcar (cdr (cdr expr)) X (math-cancel-common-factor (nth 2 expr) nn))) X (if (and n (not (eq (setq n (math-frac-gcd n nn)) 1))) X (progn X (setcar (cdr expr) X (math-cancel-common-factor (nth 1 expr) n)) X (setcar (cdr (cdr expr)) X (math-cancel-common-factor (nth 2 expr) n))))))) X (while (eq (car-safe (setq n (car np))) '*) X (math-simplify-divisor (cdr n) (cdr (cdr expr))) X (setq np (cdr (cdr n)))) X (math-simplify-divisor np (cdr (cdr expr))) X expr) X) X X(defun math-simplify-divisor (np dp) X (let ((n (car np)) X d dd temp) X (while (eq (car-safe (setq d (car dp))) '*) X (if (setq temp (math-combine-prod n (nth 1 d) nil t t)) X (progn X (setcar np (setq n temp)) X (setcar (cdr d) 1))) X (setq dp (cdr (cdr d)))) X (if (setq temp (math-combine-prod n d nil t t)) X (progn X (setcar np (setq n temp)) X (setcar dp 1)))) X) X X(defun math-common-constant-factor (expr) X (if (Math-primp expr) X (if (Math-ratp expr) X (and (not (memq expr '(0 1))) X (math-abs expr)) X (if (Math-ratp (setq expr (math-to-simple-fraction expr))) X (math-common-constant-factor expr))) X (if (memq (car expr) '(+ -)) X (let ((f1 (math-common-constant-factor (nth 1 expr))) X (f2 (math-common-constant-factor (nth 2 expr)))) X (and f1 f2 X (not (eq (setq f1 (math-frac-gcd f1 f2)) 1)) X f1)) X (if (memq (car expr) '(* /)) X (math-common-constant-factor (nth 1 expr))))) X) X X(defun math-cancel-common-factor (expr val) X (if (memq (car-safe expr) '(+ -)) X (progn X (setcar (cdr expr) (math-cancel-common-factor (nth 1 expr) val)) X (setcar (cdr (cdr expr)) (math-cancel-common-factor (nth 2 expr) val)) X expr) X (math-div expr val)) X) X X(defun math-frac-gcd (a b) X (if (and (Math-integerp a) X (Math-integerp b)) X (math-gcd a b) X (or (Math-integerp a) (setq a (list 'frac a 1))) X (or (Math-integerp b) (setq b (list 'frac b 1))) X (math-make-frac (math-gcd (nth 1 a) (nth 1 b)) X (math-gcd (nth 2 a) (nth 2 b)))) X) X X(math-defsimplify calcFunc-sin X (or (and (eq (car-safe (nth 1 expr)) 'calcFunc-arcsin) X (nth 1 (nth 1 expr))) X (and (math-looks-negp (nth 1 expr)) X (math-neg (list 'calcFunc-sin (math-neg (nth 1 expr))))) X (and math-living-dangerously X (eq (car-safe (nth 1 expr)) 'calcFunc-arccos) X (list 'calcFunc-sqrt (math-sub 1 (math-sqr (nth 1 (nth 1 expr)))))) X (and math-living-dangerously X (eq (car-safe (nth 1 expr)) 'calcFunc-arctan) X (math-div (nth 1 (nth 1 expr)) X (list 'calcFunc-sqrt X (math-add 1 (math-sqr (nth 1 (nth 1 expr)))))))) X) X X(math-defsimplify calcFunc-cos X (or (and (eq (car-safe (nth 1 expr)) 'calcFunc-arccos) X (nth 1 (nth 1 expr))) X (and (math-looks-negp (nth 1 expr)) X (list 'calcFunc-cos (math-neg (nth 1 expr)))) X (and math-living-dangerously X (eq (car-safe (nth 1 expr)) 'calcFunc-arcsin) X (list 'calcFunc-sqrt (math-sub 1 (math-sqr (nth 1 (nth 1 expr)))))) X (and math-living-dangerously X (eq (car-safe (nth 1 expr)) 'calcFunc-arctan) X (math-div 1 X (list 'calcFunc-sqrt X (math-add 1 (math-sqr (nth 1 (nth 1 expr)))))))) X) X X(math-defsimplify calcFunc-tan X (or (and (eq (car-safe (nth 1 expr)) 'calcFunc-arctan) X (nth 1 (nth 1 expr))) X (and (math-looks-negp (nth 1 expr)) X (math-neg (list 'calcFunc-tan (math-neg (nth 1 expr))))) X (and math-living-dangerously X (eq (car-safe (nth 1 expr)) 'calcFunc-arcsin) X (math-div (nth 1 (nth 1 expr)) X (list 'calcFunc-sqrt X (math-sub 1 (math-sqr (nth 1 (nth 1 expr))))))) X (and math-living-dangerously X (eq (car-safe (nth 1 expr)) 'calcFunc-arccos) X (math-div (list 'calcFunc-sqrt X (math-sub 1 (math-sqr (nth 1 (nth 1 expr))))) X (nth 1 (nth 1 expr))))) X) X X(math-defsimplify calcFunc-sinh X (and (eq (car-safe (nth 1 expr)) 'calcFunc-arcsinh) X (nth 1 (nth 1 expr))) X) X X(math-defsimplify calcFunc-cosh X (and (eq (car-safe (nth 1 expr)) 'calcFunc-arccosh) X (nth 1 (nth 1 expr))) X) X X(math-defsimplify calcFunc-tanh X (and (eq (car-safe (nth 1 expr)) 'calcFunc-arctanh) X (nth 1 (nth 1 expr))) X) X X(math-defsimplify calcFunc-arcsin X (or (and (math-looks-negp (nth 1 expr)) X (math-neg (list 'calcFunc-arcsin (math-neg (nth 1 expr))))) X (and math-living-dangerously X (eq (car-safe (nth 1 expr)) 'calcFunc-sin) X (nth 1 (nth 1 expr))) X (and math-living-dangerously X (eq (car-safe (nth 1 expr)) 'calcFunc-cos) X (math-sub (math-div '(var pi var-pi) 2) X (nth 1 (nth 1 expr))))) X) X X(math-defsimplify calcFunc-arccos X (or (and math-living-dangerously X (eq (car-safe (nth 1 expr)) 'calcFunc-cos) X (nth 1 (nth 1 expr))) X (and math-living-dangerously X (eq (car-safe (nth 1 expr)) 'calcFunc-sin) X (math-sub (math-div '(var pi var-pi) 2) X (nth 1 (nth 1 expr))))) X) X X(math-defsimplify calcFunc-arctan X (or (and (math-looks-negp (nth 1 expr)) X (math-neg (list 'calcFunc-arctan (math-neg (nth 1 expr))))) X (and math-living-dangerously X (eq (car-safe (nth 1 expr)) 'calcFunc-tan) X (nth 1 (nth 1 expr)))) X) X X(math-defsimplify calcFunc-arcsinh X (and math-living-dangerously X (eq (car-safe (nth 1 expr)) 'calcFunc-sinh) X (nth 1 (nth 1 expr))) X) X X(math-defsimplify calcFunc-arccosh X (and math-living-dangerously X (eq (car-safe (nth 1 expr)) 'calcFunc-cosh) X (nth 1 (nth 1 expr))) X) X X(math-defsimplify calcFunc-arctanh X (and math-living-dangerously X (eq (car-safe (nth 1 expr)) 'calcFunc-tanh) X (nth 1 (nth 1 expr))) X) X X(math-defsimplify calcFunc-sqrt X (or (let ((fac (math-common-constant-factor (nth 1 expr)))) X (and fac X (math-mul (list 'calcFunc-sqrt fac) X (list 'calcFunc-sqrt X (math-cancel-common-factor (nth 1 expr) fac))))) X (and (eq (car-safe (nth 1 expr)) '-) X (math-equal-int (nth 1 (nth 1 expr)) 1) X (eq (car-safe (nth 2 (nth 1 expr))) '^) X (math-equal-int (nth 2 (nth 2 (nth 1 expr))) 2) X (or (and (eq (car-safe (nth 1 (nth 2 (nth 1 expr)))) 'calcFunc-sin) X (list 'calcFunc-cos X (nth 1 (nth 1 (nth 2 (nth 1 expr)))))) X (and (eq (car-safe (nth 1 (nth 2 (nth 1 expr)))) 'calcFunc-cos) X (list 'calcFunc-sin X (nth 1 (nth 1 (nth 2 (nth 1 expr)))))))) X (and math-living-dangerously X (or (and (eq (car-safe (nth 1 expr)) '^) X (list '^ X (nth 1 (nth 1 expr)) X (math-div (nth 2 (nth 1 expr)) 2))) X (and (eq (car-safe (nth 1 expr)) 'calcFunc-sqrt) X (list '^ (nth 1 (nth 1 expr)) (math-div 1 4)))))) X) X X(math-defsimplify 'calcFunc-exp X (and (eq (car-safe (nth 1 expr)) 'calcFunc-ln) X (nth 1 (nth 1 expr))) X) X X(math-defsimplify 'calcFunc-ln X (and math-living-dangerously X (eq (car-safe (nth 1 expr)) 'calcFunc-exp) X (nth 1 (nth 1 expr))) X) X X(math-defsimplify '^ X (math-simplify-pow)) X X(defun math-simplify-pow () X (or (and math-living-dangerously X (or (and (eq (car-safe (nth 1 expr)) '^) X (list '^ X (nth 1 (nth 1 expr)) X (math-mul (nth 2 expr) (nth 2 (nth 1 expr))))) X (and (eq (car-safe (nth 1 expr)) 'calcFunc-sqrt) X (list '^ X (nth 1 (nth 1 expr)) X (math-div (nth 2 expr) 2))))) X (and (math-equal-int (nth 1 expr) 10) X (eq (car-safe (nth 2 expr)) 'calcFunc-log10) X (nth 1 (nth 2 expr))) X (and (equal (nth 1 expr) '(var e var-e)) X (eq (car-safe (nth 2 expr)) 'calcFunc-ln) X (nth 1 (nth 2 expr)))) X) X X(math-defsimplify 'calcFunc-log10 X (and math-living-dangerously X (eq (car-safe (nth 1 expr)) '^) X (math-equal-int (nth 1 (nth 1 expr)) 10) X (nth 2 (nth 1 expr))) X) X X X X X(defun math-expand-term (expr) X (cond ((and (eq (car-safe expr) '*) X (memq (car-safe (nth 1 expr)) '(+ -))) X (math-add-or-sub (math-mul (nth 1 (nth 1 expr)) (nth 2 expr)) X (math-mul (nth 2 (nth 1 expr)) (nth 2 expr)) X nil (eq (car (nth 1 expr)) '-))) X ((and (eq (car-safe expr) '*) X (memq (car-safe (nth 2 expr)) '(+ -))) X (math-add-or-sub (math-mul (nth 1 expr) (nth 1 (nth 2 expr))) X (math-mul (nth 1 expr) (nth 2 (nth 2 expr))) X nil (eq (car (nth 2 expr)) '-))) X ((and (eq (car-safe expr) '/) X (memq (car-safe (nth 1 expr)) '(+ -))) X (math-add-or-sub (math-div (nth 1 (nth 1 expr)) (nth 2 expr)) X (math-div (nth 2 (nth 1 expr)) (nth 2 expr)) X nil (eq (car (nth 1 expr)) '-))) X ((and (eq (car-safe expr) '^) X (memq (car-safe (nth 1 expr)) '(+ -)) X (integerp (nth 2 expr)) X (if (> (nth 2 expr) 0) X (list '* X (nth 1 expr) X (math-pow (nth 1 expr) (1- (nth 2 expr)))) X (if (< (nth 2 expr) 0) X (math-div 1 (math-pow (nth 1 expr) X (- (nth 2 expr)))))))) X (t expr)) X) X X(defun math-expand-tree (expr &optional many) X (math-map-tree 'math-expand-term expr many) X) X X(defun math-map-tree (mmt-func mmt-expr &optional mmt-many) X (or mmt-many (setq mmt-many 1000000)) X (math-map-tree-rec mmt-expr) X) X X(defun math-map-tree-rec (mmt-expr) X (or (= mmt-many 0) X (let ((mmt-done nil) X mmt-nextval) X (while (not mmt-done) X (while (and (/= mmt-many 0) X (setq mmt-nextval (funcall mmt-func mmt-expr)) X (not (equal mmt-expr mmt-nextval))) X (setq mmt-expr mmt-nextval X mmt-many (if (> mmt-many 0) (1- mmt-many) (1+ mmt-many)))) X (if (or (Math-primp mmt-expr) X (<= mmt-many 0)) X (setq mmt-done t) X (setq mmt-nextval (cons (car mmt-expr) X (mapcar 'math-map-tree-rec (cdr mmt-expr)))) X (if (equal mmt-nextval mmt-expr) X (setq mmt-done t) X (setq mmt-expr mmt-nextval)))))) X mmt-expr X) X X X X X(defun math-apply-rewrite (expr lhs rhs &optional cond) X (let ((matches-found nil)) X (and (math-match-pattern expr lhs) X (or (null cond) X (math-is-true (math-simplify (math-replace-variables cond)))) X (math-replace-variables rhs))) X) X X(defun math-apply-rewrite-rules (expr rules) X (let ((r rules) X next) X (while (and r X (or (not (setq next (math-apply-rewrite expr X (nth 1 (car r)) X (nth 2 (car r)) X (nth 3 (car r))))) X (equal expr (setq next (math-normalize next))))) X (setq r (cdr r))) X (and r X next)) X) X X(defun math-rewrite (expr rules &optional many) X (setq rules (math-check-rewrite-rules rules)) X (math-map-tree (function (lambda (x) (math-apply-rewrite-rules x rules))) X expr many) X) X X(defun math-check-rewrite-rules (rules) X (if (and (eq (car-safe rules) 'var) X (boundp (nth 2 rules)) X (symbol-value (nth 2 rules))) X (setq rules (symbol-value (nth 2 rules)))) X (or (Math-vectorp rules) X (error "Rules must be a vector")) X (setq rules (if (Math-vectorp (nth 1 rules)) X (cdr rules) X (list rules))) X (let ((r rules)) X (while r X (or (and (Math-vectorp (car r)) X (cdr (cdr (car r))) X (not (nthcdr 4 (car r)))) X (error "Malformed rules vector")) X (setq r (cdr r)))) X rules X) X X(defun math-match-pattern (expr pat) X (cond ((Math-primp pat) X (or (math-equal expr pat) X (and (eq (car-safe pat) 'var) X (let ((match (assq (nth 1 pat) matches-found))) X (if match X (equal expr (nth 1 match)) X (setq matches-found (cons (list (nth 1 pat) X expr) X matches-found))))))) X ((eq (car pat) 'calcFunc-quote) X (equal expr (nth 1 pat))) X (t X (and (eq (car pat) (car-safe expr)) X (progn X (while (and (setq expr (cdr expr) pat (cdr pat)) X expr X (math-match-pattern (car expr) (car pat)))) X (and (null expr) (null pat)))))) X) X X(defun math-replace-variables (expr) X (if (Math-primp expr) X (if (eq (car-safe expr) 'var) X (let ((match (assq (nth 1 expr) matches-found))) X (if match X (nth 1 match) X expr)) X expr) X (cons (car expr) (mapcar 'math-replace-variables (cdr expr)))) X) X X(defun math-is-true (expr) X (and (Math-realp expr) X (not (Math-zerop expr))) X) X X X X X(defun math-derivative (expr) ; uses global values: deriv-var, deriv-total. X (cond ((equal expr deriv-var) X 1) X ((or (Math-scalarp expr) X (eq (car expr) 'sdev) X (and (eq (car expr) 'var) X (not deriv-total))) X 0) X ((eq (car expr) '+) X (math-add (math-derivative (nth 1 expr)) X (math-derivative (nth 2 expr)))) X ((eq (car expr) '-) X (math-sub (math-derivative (nth 1 expr)) X (math-derivative (nth 2 expr)))) X ((eq (car expr) 'neg) X (math-neg (math-derivative (nth 1 expr)))) X ((eq (car expr) '*) X (math-add (math-mul (nth 2 expr) X (math-derivative (nth 1 expr))) X (math-mul (nth 1 expr) X (math-derivative (nth 2 expr))))) X ((eq (car expr) '/) X (math-sub (math-div (math-derivative (nth 1 expr)) X (nth 2 expr)) X (math-div (math-mul (nth 1 expr) X (math-derivative (nth 2 expr))) X (math-sqr (nth 2 expr))))) X ((eq (car expr) '^) X (let ((du (math-derivative (nth 1 expr))) X (dv (math-derivative (nth 2 expr)))) X (or (Math-zerop du) X (setq du (math-mul (nth 2 expr) X (math-mul (math-normalize X (list '^ X (nth 1 expr) X (math-add (nth 2 expr) -1))) X du)))) X (or (Math-zerop dv) X (setq dv (math-mul (math-normalize X (list 'calcFunc-ln (nth 1 expr))) X (math-mul expr dv)))) X (math-add du dv))) X ((eq (car expr) '%) X (math-derivative (nth 1 expr))) ; a reasonable definition X ((eq (car expr) 'vec) X (math-map-vec 'math-derivative expr)) X ((and (eq (car expr) 'calcFunc-log) X (= (length expr) 3) X (not (Math-zerop (nth 2 expr)))) X (let ((lnv (math-normalize (list 'calcFunc-ln (nth 2 expr))))) X (math-sub (math-div (math-derivative (nth 1 expr)) X (math-mul lnv (nth 1 expr))) X (math-div (math-derivative (nth 2 expr)) X (math-mul (math-sqr lnv) X (nth 2 expr)))))) X (t (or (and (= (length expr) 2) X (symbolp (car expr)) X (let ((handler (get (car expr) 'math-derivative))) X (and handler X (let ((deriv (math-derivative (nth 1 expr)))) X (if (Math-zerop deriv) X deriv X (math-mul (funcall handler (nth 1 expr)) X deriv)))))) X (if deriv-symb X (throw 'math-deriv nil) X (if (or (Math-objvecp expr) X (not (symbolp (car expr)))) X (list (if deriv-total 'calcFunc-tderiv 'calcFunc-deriv) X expr X deriv-var) X (let ((accum 0) X (arg expr) X (n 1) X derv) X (while (setq arg (cdr arg)) X (or (Math-zerop (setq derv (math-derivative (car arg)))) X (let ((func (intern (concat (symbol-name (car expr)) X "'" X (if (> n 1) X (int-to-string n) X ""))))) X (setq accum (math-add X accum X (math-mul derv X (cons func X (cdr expr))))))) X (setq n (1+ n))) X accum)))))) X) X X(defun calcFunc-deriv (expr deriv-var &optional deriv-value deriv-symb) X (let* ((deriv-total nil) X (res (catch 'math-deriv (math-derivative expr)))) X (or (eq (car-safe res) 'calcFunc-deriv) X (null res) X (setq res (math-normalize res))) X (and res X (if deriv-value X (math-expr-subst res deriv-var deriv-value) X res))) X) X X(defun calcFunc-tderiv (expr deriv-var &optional deriv-value deriv-symb) X (let* ((deriv-total t) X (res (catch 'math-deriv (math-derivative expr)))) X (or (eq (car-safe res) 'calcFunc-tderiv) X (null res) X (setq res (math-normalize res))) X (and res X (if deriv-value X (math-expr-subst res deriv-var deriv-value) X res))) X) X X(put 'calcFunc-inv 'math-derivative X (function (lambda (u) (math-neg (math-div 1 (math-sqr u)))))) X X(put 'calcFunc-sqrt 'math-derivative X (function (lambda (u) (math-div 1 (math-mul 2 (list 'calcFunc-sqrt u)))))) X X(put 'calcFunc-conj 'math-derivative X (function (lambda (u) (math-normalize (list 'calcFunc-conj u))))) X X(put 'calcFunc-deg 'math-derivative X (function (lambda (u) (math-div (math-pi-over-180) u)))) X X(put 'calcFunc-rad 'math-derivative X (function (lambda (u) (math-mul (math-pi-over-180) u)))) X X(put 'calcFunc-ln 'math-derivative X (function (lambda (u) (math-div 1 u)))) X X(put 'calcFunc-log10 'math-derivative X (function (lambda (u) X (math-div (math-div 1 (math-normalize '(calcFunc-ln 10))) X u)))) X X(put 'calcFunc-lnp1 'math-derivative X (function (lambda (u) (math-div 1 (math-add u 1))))) X X(put 'calcFunc-exp 'math-derivative X (function (lambda (u) (math-normalize (list 'calcFunc-exp u))))) X X(put 'calcFunc-expm1 'math-derivative X (function (lambda (u) (math-normalize (list 'calcFunc-expm1 u))))) X X(put 'calcFunc-sin 'math-derivative X (function (lambda (u) (math-to-radians-2 (math-normalize X (list 'calcFunc-cos u)))))) X X(put 'calcFunc-cos 'math-derivative X (function (lambda (u) (math-neg (math-to-radians-2 X (math-normalize X (list 'calcFunc-sin u))))))) X X(put 'calcFunc-tan 'math-derivative X (function (lambda (u) (math-to-radians-2 X (math-div 1 (math-sqr X (math-normalize X (list 'calcFunc-cos u)))))))) X X(put 'calcFunc-arcsin 'math-derivative X (function (lambda (u) X (math-from-radians-2 X (math-div 1 (math-normalize X (list 'calcFunc-sqrt X (math-sub 1 (math-sqr u))))))))) X X(put 'calcFunc-arccos 'math-derivative X (function (lambda (u) X (math-from-radians-2 X (math-div -1 (math-normalize X (list 'calcFunc-sqrt X (math-sub 1 (math-sqr u))))))))) X X(put 'calcFunc-arctan 'math-derivative X (function (lambda (u) (math-from-radians-2 X (math-div 1 (math-add 1 (math-sqr u))))))) X X(put 'calcFunc-sinh 'math-derivative X (function (lambda (u) (math-normalize (list 'calcFunc-cosh u))))) X X(put 'calcFunc-cosh 'math-derivative X (function (lambda (u) (math-normalize (list 'calcFunc-sinh u))))) X X(put 'calcFunc-tanh 'math-derivative X (function (lambda (u) (math-div 1 (math-sqr X (math-normalize X (list 'calcFunc-cosh u))))))) X X(put 'calcFunc-arcsinh 'math-derivative X (function (lambda (u) X (math-div 1 (math-normalize X (list 'calcFunc-sqrt X (math-add (math-sqr u) 1))))))) X X(put 'calcFunc-arccosh 'math-derivative X (function (lambda (u) X (math-div 1 (math-normalize X (list 'calcFunc-sqrt X (math-add (math-sqr u) -1))))))) X X(put 'calcFunc-arctanh 'math-derivative X (function (lambda (u) (math-div 1 (math-sub 1 (math-sqr u)))))) X X X X(setq math-integ-var '(var X ---)) X(setq math-integ-var-2 '(var Y ---)) X(setq math-integ-vars (list 'f math-integ-var math-integ-var-2)) X X(defmacro math-tracing-integral (&rest parts) X (list 'and X 'trace-buffer X (list 'save-excursion X '(set-buffer trace-buffer) X '(goto-char (point-max)) X (list 'and X '(bolp) X '(insert (make-string (- calc-integral-limit X math-integ-level) 32) X (format "%2d " math-integ-depth) X (make-string math-integ-level 32))) X (cons 'insert parts) X '(sit-for 0))) X) X X;;; The following wrapper caches results and avoids infinite recursion. X;;; Each cache entry is: ( A B ) Integral of A is B; X;;; ( A N ) Integral of A failed at level N; X;;; ( A busy ) Currently working on integral of A; X;;; ( A parts ) Currently working, integ-by-parts; X;;; ( A parts2 ) Currently working, integ-by-parts; X;;; ( A cancelled ) Ignore this cache entry; X;;; ( A [B] ) Same result as for cur-record = B. X(defun math-integral (expr &optional simplify same-as-above) X (let* ((simp cur-record) X (cur-record (assoc expr math-integral-cache)) X (math-integ-depth (1+ math-integ-depth)) X (val 'cancelled)) X (math-tracing-integral "Integrating " X (math-format-value expr 1000) X "...\n") X (and cur-record X (progn X (math-tracing-integral "Found " X (math-format-value (nth 1 cur-record) 1000)) X (and (consp (nth 1 cur-record)) X (math-replace-integral-parts cur-record)) X (math-tracing-integral " => " X (math-format-value (nth 1 cur-record) 1000) X "\n"))) X (or (and cur-record X (not (eq (nth 1 cur-record) 'cancelled)) X (or (not (integerp (nth 1 cur-record))) X (>= (nth 1 cur-record) math-integ-level))) X (and (consp expr) X (eq (car expr) 'var) X (eq (nth 1 expr) 'PARTS) X (listp (nth 2 expr)) X (progn X (setq val nil) X t)) X (unwind-protect X (progn X (let (math-integ-msg) X (if (eq calc-display-working-message 'lots) X (progn X (calc-set-command-flag 'clear-message) X (setq math-integ-msg (format X "Working... Integrating %s" X (math-format-flat-expr expr 0))) X (message math-integ-msg))) X (if cur-record X (setcar (cdr cur-record) X (if same-as-above (vector simp) 'busy)) X (setq cur-record X (list expr (if same-as-above (vector simp) 'busy)) X math-integral-cache (cons cur-record X math-integral-cache))) X (if (eq simplify 'yes) X (progn X (math-tracing-integral "Simplifying...") X (setq simp (math-simplify expr)) X (setq val (if (equal simp expr) X (progn X (math-tracing-integral " no change\n") X (math-do-integral expr)) X (math-tracing-integral " simplified\n") X (math-integral simp 'no t)))) X (or (setq val (math-do-integral expr)) X (eq simplify 'no) X (let ((simp (math-simplify expr))) X (or (equal simp expr) X (progn X (math-tracing-integral "Trying again after " X "simplification...\n") X (setq val (math-integral simp 'no t)))))))) X (if (eq calc-display-working-message 'lots) X (message math-integ-msg))) X (setcar (cdr cur-record) (or val math-integ-level)))) X (setq val cur-record) X (while (vectorp (nth 1 val)) X (setq val (aref (nth 1 val) 0))) X (setq val (if (memq (nth 1 val) '(parts parts2)) X (progn X (setcar (cdr val) 'parts2) X (list 'var 'PARTS val)) X (and (not (eq (nth 1 val) 'busy)) X (not (integerp (nth 1 val))) X (nth 1 val)))) X (math-tracing-integral "Integral of " X (math-format-value expr 1000) X " is " X (math-format-value val 1000) X "\n") X val) X) X(defvar math-integral-cache nil) X(defvar math-integral-cache-state nil) X X(defun math-replace-integral-parts (expr) X (or (Math-primp expr) X (while (setq expr (cdr expr)) X (and (consp (car expr)) X (if (eq (car (car expr)) 'var) X (and (eq (nth 1 (car expr)) 'PARTS) X (consp (nth 2 (car expr))) X (if (listp (nth 1 (nth 2 (car expr)))) X (progn X (setcar expr (nth 1 (nth 2 (car expr)))) X (math-replace-integral-parts (cons 'foo expr))) X (setcar (cdr cur-record) 'cancelled))) X (math-replace-integral-parts (car expr)))))) X) X X(defun math-do-integral (expr) X (let (t1 t2) X (or (cond ((not (math-expr-contains expr math-integ-var)) X (math-mul expr math-integ-var)) X ((equal expr math-integ-var) X (math-div (math-sqr expr) 2)) X ((eq (car expr) '+) X (and (setq t1 (math-integral (nth 1 expr))) X (setq t2 (math-integral (nth 2 expr))) X (math-add t1 t2))) X ((eq (car expr) '-) X (and (setq t1 (math-integral (nth 1 expr))) X (setq t2 (math-integral (nth 2 expr))) X (math-sub t1 t2))) X ((eq (car expr) 'neg) X (and (setq t1 (math-integral (nth 1 expr))) X (math-neg t1))) X ((eq (car expr) '*) X (cond ((not (math-expr-contains (nth 1 expr) math-integ-var)) X (and (setq t1 (math-integral (nth 2 expr))) X (math-mul (nth 1 expr) t1))) X ((not (math-expr-contains (nth 2 expr) math-integ-var)) X (and (setq t1 (math-integral (nth 1 expr))) X (math-mul t1 (nth 2 expr)))) X ((memq (car-safe (nth 1 expr)) '(+ -)) X (math-integral (list (car (nth 1 expr)) X (math-mul (nth 1 (nth 1 expr)) X (nth 2 expr)) X (math-mul (nth 2 (nth 1 expr)) X (nth 2 expr))) X 'yes t)) X ((memq (car-safe (nth 2 expr)) '(+ -)) X (math-integral (list (car (nth 2 expr)) X (math-mul (nth 1 (nth 2 expr)) X (nth 1 expr)) X (math-mul (nth 2 (nth 2 expr)) X (nth 1 expr))) X 'yes t)))) X ((eq (car expr) '/) X (cond ((not (math-expr-contains (nth 2 expr) math-integ-var)) X (and (setq t1 (math-integral (nth 1 expr))) X (math-div t1 (nth 2 expr)))) X ((and (eq (car-safe (nth 1 expr)) '*) X (not (math-expr-contains (nth 1 (nth 1 expr)) X math-integ-var))) X (and (setq t1 (math-integral X (math-div (nth 2 (nth 1 expr)) X (nth 2 expr)))) X (math-mul t1 (nth 1 (nth 1 expr))))) X ((and (eq (car-safe (nth 2 expr)) '*) X (not (math-expr-contains (nth 1 (nth 2 expr)) X math-integ-var))) X (and (setq t1 (math-integral X (math-div (nth 1 expr) X (nth 2 (nth 2 expr))))) X (math-div t1 (nth 1 (nth 2 expr))))) X ((memq (car-safe (nth 1 expr)) '(+ -)) X (math-integral (list (car (nth 1 expr)) X (math-div (nth 1 (nth 1 expr)) X (nth 2 expr)) X (math-div (nth 2 (nth 1 expr)) X (nth 2 expr))) X 'yes t)))) X ((eq (car expr) '^) X (cond ((not (math-expr-contains (nth 1 expr) math-integ-var)) X (or (and (setq t1 (math-is-polynomial (nth 2 expr) X math-integ-var 1)) X (math-div expr X (math-mul (nth 1 t1) X (math-normalize X (list 'calcFunc-ln X (nth 1 expr)))))) X (math-integral X (list 'calcFunc-exp X (math-mul (nth 2 expr) X (math-normalize X (list 'calcFunc-ln X (nth 1 expr))))) X 'yes t))) X ((not (math-expr-contains (nth 2 expr) math-integ-var)) X (if (Math-equal-int (nth 2 expr) -1) X (math-integral (math-div 1 (nth 1 expr)) nil t) X (or (and (setq t1 (math-is-polynomial (nth 1 expr) X math-integ-var X 1)) X (setq t2 (math-add (nth 2 expr) 1)) X (math-div (math-pow (nth 1 expr) t2) X (math-mul t2 (nth 1 t1)))) X (and (Math-negp (nth 2 expr)) X (math-integral X (math-div 1 X (math-pow (nth 1 expr) X (math-neg X (nth 2 expr)))) X nil t)) X nil)))))) X X ;; Integral of a polynomial. X (and (setq t1 (math-is-polynomial expr math-integ-var 20)) X (let ((accum 0) X (n 1)) X (while t1 X (if (setq accum (math-add accum X (math-div (math-mul (car t1) X (math-pow X math-integ-var X n)) X n)) X t1 (cdr t1)) X (setq n (1+ n)))) X accum)) X X ;; Try looking it up! X (cond ((= (length expr) 2) X (and (symbolp (car expr)) X (setq t1 (get (car expr) 'math-integral)) X (progn X (while (and t1 X (not (setq t2 (funcall (car t1) X (nth 1 expr))))) X (setq t1 (cdr t1))) X (and t2 (math-normalize t2))))) X ((= (length expr) 3) X (and (symbolp (car expr)) X (setq t1 (get (car expr) 'math-integral-2)) X (progn X (while (and t1 X (not (setq t2 (funcall (car t1) X (nth 1 expr) X (nth 2 expr))))) X (setq t1 (cdr t1))) X (and t2 (math-normalize t2)))))) X X ;; Integration by substitution, for various likely sub-expressions. X ;; (We should also try some of the classic non-obvious substitutions.) X (let ((so-far nil)) X (math-integ-try-substitutions expr)) X X ;; Integration by parts: X ;; integ(f(x) g(x),x) = f(x) h(x) - integ(h(x) f'(x),x) X ;; where h(x) = integ(g(x),x). X (and (eq (car expr) '*) X (not (math-polynomial-p (nth 2 expr) math-integ-var)) X (math-integrate-by-parts (nth 1 expr) (nth 2 expr))) X (and (eq (car expr) '/) X (math-expr-contains (nth 1 expr) math-integ-var) X (let ((recip (math-div 1 (nth 2 expr)))) X (or (math-integrate-by-parts (nth 1 expr) recip) X (math-integrate-by-parts recip (nth 1 expr))))) X (and (eq (car expr) '^) X (math-integrate-by-parts (nth 1 expr) X (math-pow (nth 1 expr) X (math-sub (nth 2 expr) 1)))) X X ;; Symmetries. X (and (eq (car expr) '*) X (math-integral (list '* (nth 2 expr) (nth 1 expr)) 'no t)) X X ;; Give up. X nil)) X) X X(defun math-integrate-by-parts (u vprime) X (and (> math-integ-level 0) X (not (boundp 'math-disable-parts)) X (let ((math-integ-level (1- math-integ-level)) X v temp) X (unwind-protect X (progn X (setcar (cdr cur-record) 'parts) X (math-tracing-integral "Integrating by parts, u = " X (math-format-value u 1000) X ", v' = " X (math-format-value vprime 1000) X "\n") X (and (setq v (math-integral vprime)) X (setq temp (calcFunc-deriv u X math-integ-var X nil t)) X (setq temp (math-integral (math-mul v temp) 'yes)) X (setq temp (math-sub (math-mul u v) temp)) X (if (eq (nth 1 cur-record) 'parts) X temp X (setq v (list 'var 'PARTS cur-record) X temp (math-solve-for (math-sub v temp) 0 v nil)) X (and temp (math-simplify-extended temp))))) X (setcar (cdr cur-record) 'busy)))) X) X X;;; This tries two different formulations, hoping the algebraic simplifier X;;; will be strong enough to handle at least one. X(defun math-integrate-by-substitution (expr u) X (and (> math-integ-level 0) X (let ((math-integ-level (1- math-integ-level)) X (math-living-dangerously t) X uinv deriv temp) X (and (setq uinv (math-solve-for u X math-integ-var-2 X math-integ-var nil)) X (progn X (math-tracing-integral "Integrating by substitution, u = " X (math-format-value u 1000) X "\n") X (or (and (not (boundp 'math-disable-subst1)) X (setq deriv (calcFunc-deriv u X math-integ-var nil t)) X (setq temp (math-integral (math-expr-subst X (math-expr-subst X (math-expr-subst X (math-div expr deriv) X u X math-integ-var-2) X math-integ-var X uinv) X math-integ-var-2 X math-integ-var) X 'yes))) X (and (not (boundp 'math-disable-subst2)) X (setq deriv (calcFunc-deriv uinv X math-integ-var-2 X math-integ-var t)) X (setq temp (math-integral (math-mul X (math-expr-subst X (math-expr-subst X (math-expr-subst X expr X u X math-integ-var-2) X math-integ-var X uinv) X math-integ-var-2 X math-integ-var) X deriv) X 'yes))))) X (math-simplify-extended X (math-expr-subst temp math-integ-var u))))) X) X X;;; Recursively try different substitutions based on various sub-expressions. X(defun math-integ-try-substitutions (sub-expr) X (and (not (Math-primp sub-expr)) X (math-expr-contains sub-expr math-integ-var) X (not (equal sub-expr math-integ-var)) X (not (assoc sub-expr so-far)) X (or (and (not (eq sub-expr expr)) X (math-integrate-by-substitution expr sub-expr)) X (let ((res nil)) X (setq so-far (cons (list sub-expr) so-far)) X (while (and (setq sub-expr (cdr sub-expr)) X (not (setq res (math-integ-try-substitutions X (car sub-expr)))))) X res))) X) X X(defun math-fix-const-terms (expr except-vars) X (cond ((not (math-expr-depends expr except-vars)) 0) X ((Math-primp expr) expr) X ((eq (car expr) '+) X (math-add (math-fix-const-terms (nth 1 expr) except-vars) X (math-fix-const-terms (nth 2 expr) except-vars))) X ((eq (car expr) '-) X (math-sub (math-fix-const-terms (nth 1 expr) except-vars) X (math-fix-const-terms (nth 2 expr) except-vars))) X (t expr)) X) X X(defun calc-dump-integral-cache (&optional arg) X "Command for debugging the Calculator's symbolic integrator." X (interactive "P") X (let ((buf (current-buffer))) X (unwind-protect X (let ((p math-integral-cache) X cur-record) X (display-buffer (get-buffer-create "*Integral Cache*")) X (set-buffer (get-buffer "*Integral Cache*")) X (erase-buffer) X (while p X (setq cur-record (car p)) X (or arg (math-replace-integral-parts cur-record)) X (insert (math-format-flat-expr (car cur-record) 0) X " --> " X (if (symbolp (nth 1 cur-record)) X (concat "(" (symbol-name (nth 1 cur-record)) ")") X (math-format-flat-expr (nth 1 cur-record) 0)) X "\n") X (setq p (cdr p))) X (goto-char (point-min))) X (set-buffer buf))) X) X X(defun calcFunc-integ (expr var &optional low high) X (let ((state (list calc-angle-mode X calc-symbolic-mode X calc-prefer-frac X calc-internal-prec))) X (or (equal state math-integral-cache-state) X (setq math-integral-cache-state state X math-integral-cache nil))) X (let* ((math-integ-level calc-integral-limit) X (math-integ-depth 0) X (math-integ-msg "Working...done") X (cur-record nil) ; a technicality X (sexpr (math-expr-subst expr var math-integ-var)) X (trace-buffer (get-buffer "*Trace*")) X (calc-language (if (eq calc-language 'big) nil calc-language)) X (res (if trace-buffer X (let ((calcbuf (current-buffer)) X (calcwin (selected-window))) X (unwind-protect X (progn X (if (get-buffer-window trace-buffer) X (select-window (get-buffer-window trace-buffer))) X (set-buffer trace-buffer) X (goto-char (point-max)) X (or (assq 'scroll-stop (buffer-local-variables)) X (progn X (make-local-variable 'scroll-step) X (setq scroll-step 3))) X (insert "\n\n\n") X (set-buffer calcbuf) X (math-integral sexpr 'yes)) X (select-window calcwin) X (set-buffer calcbuf))) X (math-integral sexpr 'yes)))) X (if res X (math-normalize X (if (and low high) X (math-sub (math-expr-subst res math-integ-var high) X (math-expr-subst res math-integ-var low)) X (setq res (math-fix-const-terms res math-integ-vars)) X (if low X (math-expr-subst res math-integ-var low) X (math-expr-subst res math-integ-var var)))) X (append (list 'calcFunc-integ expr var) X (and low (list low)) X (and high (list high))))) X) X X(defmacro math-defintegral (funcs &rest code) X "Define an integration rule for the specified function. XIf FUNCS is a list of functions, the same rule is applied for each function. XCODE is a body of Lisp code that returns the integral of FUNCS(U). XMore than one definition may be made per function. All definitions are tried Xin the order they were encountered; the first non-NIL value returned is used." X (setq math-integral-cache nil) X (append '(progn) X (mapcar (function X (lambda (func) X (list 'put (list 'quote func) ''math-integral X (list 'nconc X (list 'get (list 'quote func) ''math-integral) X (list 'list X (list 'function X (append '(lambda (u)) X code))))))) X (if (symbolp funcs) (list funcs) funcs))) X) X(put 'math-defintegral 'lisp-indent-hook 1) X X(defmacro math-defintegral-2 (funcs &rest code) X "Define an integration rule for the specified function. XIf FUNCS is a list of functions, the same rule is applied for each function. XCODE is a body of Lisp code that returns the integral of FUNCS(U,V). XMore than one definition may be made per function. All definitions are tried Xin the order they were encountered; the first non-NIL value returned is used." X (setq math-integral-cache nil) X (append '(progn) X (mapcar (function X (lambda (func) X (list 'put (list 'quote func) ''math-integral-2 X (list 'nconc X (list 'get (list 'quote func) SHAR_EOF echo "End of part 9" echo "File calc-ext.el is continued in part 10" echo "10" > s2_seq_.tmp exit 0