[comp.sources.misc] v13i036: Emacs Calculator 1.01, part 10/19

daveg@csvax.caltech.edu (David Gillespie) (06/06/90)

Posting-number: Volume 13, Issue 36
Submitted-by: daveg@csvax.caltech.edu (David Gillespie)
Archive-name: gmcalc/part10

---- Cut Here and unpack ----
#!/bin/sh
# this is part 10 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file calc-ext.el continued
#
CurArch=10
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				       ''math-integral-2)
X				 (list 'list
X				       (list 'function
X					     (append '(lambda (u v))
X						     code)))))))
X		  (if (symbolp funcs) (list funcs) funcs)))
X)
X(put 'math-defintegral-2 'lisp-indent-hook 1)
X
X(math-defintegral calcFunc-inv
X  (math-integral (math-div 1 u)))
X
X(math-defintegral calcFunc-conj
X  (let ((int (math-integral u)))
X    (and int
X	 (list 'calcFunc-conj int))))
X
X(math-defintegral calcFunc-deg
X  (let ((int (math-integral u)))
X    (and int
X	 (list 'calcFunc-deg int))))
X
X(math-defintegral calcFunc-rad
X  (let ((int (math-integral u)))
X    (and int
X	 (list 'calcFunc-rad int))))
X
X(math-defintegral calcFunc-re
X  (let ((int (math-integral u)))
X    (and int
X	 (list 'calcFunc-re int))))
X
X(math-defintegral calcFunc-im
X  (let ((int (math-integral u)))
X    (and int
X	 (list 'calcFunc-im int))))
X
X(math-defintegral calcFunc-sqrt
X  (and (equal u math-integ-var)
X       (math-mul '(frac 2 3)
X		 (list 'calcFunc-sqrt (math-pow u 3)))))
X
X(math-defintegral calcFunc-exp
X  (and (equal u math-integ-var)
X       (list 'calcFunc-exp u)))
X
X(math-defintegral calcFunc-ln
X  (or (and (equal u math-integ-var)
X	   (math-sub (math-mul u (list 'calcFunc-ln u)) u))
X      (and (eq (car u) '*)
X	   (math-integral (math-add (list 'calcFunc-ln (nth 1 u))
X				    (list 'calcFunc-ln (nth 2 u)))))
X      (and (eq (car u) '/)
X	   (math-integral (math-sub (list 'calcFunc-ln (nth 1 u))
X				    (list 'calcFunc-ln (nth 2 u)))))
X      (and (eq (car u) '^)
X	   (math-integral (math-mul (nth 2 u)
X				    (list 'calcFunc-ln (nth 1 u)))))))
X
X(math-defintegral calcFunc-log10
X  (and (equal u math-integ-var)
X       (math-sub (math-mul u (list 'calcFunc-ln u))
X		 (math-div u (list 'calcFunc-ln 10)))))
X
X(math-defintegral-2 calcFunc-log
X  (math-integral (math-div (list 'calcFunc-ln u)
X			   (list 'calcFunc-ln v))))
X
X(math-defintegral calcFunc-sin
X  (and (equal u math-integ-var)
X       (math-neg (math-from-radians-2 (list 'calcFunc-cos u)))))
X
X(math-defintegral calcFunc-cos
X  (and (equal u math-integ-var)
X       (math-from-radians-2 (list 'calcFunc-sin u))))
X
X(math-defintegral calcFunc-tan
X  (and (equal u math-integ-var)
X       (math-neg (math-from-radians-2
X		  (list 'calcFunc-ln (list 'calcFunc-cos u))))))
X
X(math-defintegral calcFunc-arcsin
X  (and (equal u math-integ-var)
X       (math-add (math-mul u (list 'calcFunc-arcsin u))
X		 (math-from-radians-2
X		  (list 'calcFunc-sqrt (math-sub 1 (math-sqr u)))))))
X
X(math-defintegral calcFunc-arccos
X  (and (equal u math-integ-var)
X       (math-sub (math-mul u (list 'calcFunc-arccos u))
X		 (math-from-radians-2
X		  (list 'calcFunc-sqrt (math-sub 1 (math-sqr u)))))))
X
X(math-defintegral calcFunc-arctan
X  (and (equal u math-integ-var)
X       (math-sub (math-mul u (list 'calcFunc-arctan u))
X		 (math-from-radians-2
X		  (math-div (list 'calcFunc-ln (math-add 1 (math-sqr u)))
X			    2)))))
X
X(math-defintegral calcFunc-sinh
X  (and (equal u math-integ-var)
X       (list 'calcFunc-cosh u)))
X
X(math-defintegral calcFunc-cosh
X  (and (equal u math-integ-var)
X       (list 'calcFunc-sinh u)))
X
X(math-defintegral calcFunc-tanh
X  (and (equal u math-integ-var)
X       (list 'calcFunc-ln (list 'calcFunc-cosh u))))
X
X(math-defintegral calcFunc-arcsinh
X  (and (equal u math-integ-var)
X       (math-sub (math-mul u (list 'calcFunc-arcsinh u))
X		 (list 'calcFunc-sqrt (math-add (math-sqr u) 1)))))
X
X(math-defintegral calcFunc-arccosh
X  (and (equal u math-integ-var)
X       (math-sub (math-mul u (list 'calcFunc-arccosh u))
X		 (list 'calcFunc-sqrt (math-sub 1 (math-sqr u))))))
X
X(math-defintegral calcFunc-arctanh
X  (and (equal u math-integ-var)
X       (math-sub (math-mul u (list 'calcFunc-arctan u))
X		 (math-div (list 'calcFunc-ln
X				 (math-add 1 (math-sqr u)))
X			   2))))
X
X;;; 1 / (ax^2 + bx + c) forms.
X(math-defintegral-2 /
X  (and (not (math-expr-contains u math-integ-var))
X       (let ((p1 (math-is-polynomial v math-integ-var 2))
X	     q rq part)
X	 (cond ((null p1) nil)
X	       ((null (cdr (cdr p1)))
X		(math-mul u (math-div (list 'calcFunc-ln v) (nth 1 p1))))
X	       ((math-zerop
X		 (setq part (math-add (math-mul 2
X						(math-mul (nth 2 p1)
X							  math-integ-var))
X				      (nth 1 p1))
X		       q (math-sub (math-mul 4
X					     (math-mul (nth 0 p1)
X						       (nth 2 p1)))
X				   (math-sqr (nth 1 p1)))))
X		(math-div (math-mul -2 u) part))
X	       ((math-negp q)
X		(setq rq (list 'calcFunc-sqrt (math-neg q)))
X		(math-div (math-mul u
X				    (list 'calcFunc-ln
X					  (math-div (math-add part rq)
X						    (math-sub part rq))))
X			  rq))
X	       (t
X		(setq rq (list 'calcFunc-sqrt q))
X		(math-div (math-mul 2
X				    (math-mul u
X					      (list 'calcFunc-arctan
X						    (math-div part rq))))
X			  rq))))))
X
X
X
X;;; Attempt to reduce lhs = rhs to solve-var = rhs', where solve-var appears
X;;; in lhs but not in rhs or rhs'; return rhs'.
X(defun math-try-solve-for (lhs rhs)    ; uses global values: solve-*.
X  (let (t1 t2 t3)
X    (cond ((equal lhs solve-var)
X	   rhs)
X	  ((Math-primp lhs)
X	   nil)
X	  ((setq t2 (math-polynomial-base
X		     lhs
X		     (function (lambda (b)
X				 (and (setq t1 (math-is-polynomial lhs b 2))
X				      (math-expr-depends b solve-var)
X				      (not (equal b lhs)))))))
X	   (if (cdr (cdr t1))
X	       (math-try-solve-for
X		t2
X		(if (math-looks-evenp (nth 1 t1))
X		    (let ((halfb (math-div (nth 1 t1) 2)))
X		      (math-div
X		       (math-add
X			(math-neg halfb)
X			(math-solve-get-sign
X			 (math-normalize
X			  (list 'calcFunc-sqrt
X				(math-add (math-sqr halfb)
X					  (math-mul (math-sub rhs (car t1))
X						    (nth 2 t1)))))))
X		       (nth 2 t1)))
X		  (math-div
X		   (math-add
X		    (math-neg (nth 1 t1))
X		    (math-solve-get-sign
X		     (math-normalize
X		      (list 'calcFunc-sqrt
X			    (math-add (math-sqr (nth 1 t1))
X				      (math-mul 4
X						(math-mul (math-sub rhs
X								    (car t1))
X							  (nth 2 t1))))))))
X		   (math-mul 2 (nth 2 t1)))))
X	     (and (cdr t1)
X		  (math-try-solve-for t2
X				      (math-div (math-sub rhs (car t1))
X						(nth 1 t1))))))
X	  ((eq (car lhs) '+)
X	   (cond ((not (math-expr-depends (nth 1 lhs) solve-var))
X		  (math-try-solve-for (nth 2 lhs)
X				      (math-sub rhs (nth 1 lhs))))
X		 ((not (math-expr-depends (nth 2 lhs) solve-var))
X		  (math-try-solve-for (nth 1 lhs)
X				      (math-sub rhs (nth 2 lhs))))))
X	  ((memq (car lhs) '(- calcFunc-eq))
X	   (cond ((not (math-expr-depends (nth 1 lhs) solve-var))
X		  (math-try-solve-for (nth 2 lhs)
X				      (math-sub (nth 1 lhs) rhs)))
X		 ((not (math-expr-depends (nth 2 lhs) solve-var))
X		  (math-try-solve-for (nth 1 lhs)
X				      (math-add rhs (nth 2 lhs))))))
X	  ((eq (car lhs) 'neg)
X	   (math-try-solve-for (nth 1 lhs) (math-neg rhs)))
X	  ((eq (car lhs) '*)
X	   (cond ((not (math-expr-depends (nth 1 lhs) solve-var))
X		  (math-try-solve-for (nth 2 lhs)
X				      (math-div rhs (nth 1 lhs))))
X		 ((not (math-expr-depends (nth 2 lhs) solve-var))
X		  (math-try-solve-for (nth 1 lhs)
X				      (math-div rhs (nth 2 lhs))))))
X	  ((eq (car lhs) '/)
X	   (cond ((not (math-expr-depends (nth 1 lhs) solve-var))
X		  (math-try-solve-for (nth 2 lhs)
X				      (math-div (nth 1 lhs) rhs)))
X		 ((not (math-expr-depends (nth 2 lhs) solve-var))
X		  (math-try-solve-for (nth 1 lhs)
X				      (math-mul rhs (nth 2 lhs))))
X		 ((and (setq t1 (math-is-polynomial (nth 1 lhs) solve-var 2))
X		       (setq t2 (math-is-polynomial (nth 2 lhs) solve-var 2)))
X		  (math-try-solve-for (math-build-polynomial-expr
X				       (math-poly-mix t2 rhs t1 -1)
X				       solve-var)
X				      0))
X		 ((setq t3 (math-polynomial-base
X			    (nth 1 lhs)
X			    (function (lambda (b)
X					(and (math-expr-depends b solve-var)
X					     (setq t1 (math-is-polynomial
X						       (nth 1 lhs) b 2))
X					     (setq t2 (math-is-polynomial
X						       (nth 2 lhs) b 2)))))))
X		  (math-try-solve-for (math-build-polynomial-expr
X				       (math-poly-mix t2 rhs t1 -1)
X				       t3)
X				      0))))
X	  ((eq (car lhs) '^)
X	   (cond ((not (math-expr-depends (nth 1 lhs) solve-var))
X		  (math-try-solve-for
X		   (nth 2 lhs)
X		   (math-add (math-normalize
X			      (list 'calcFunc-log rhs (nth 1 lhs)))
X			     (math-div
X			      (math-mul 2
X					(math-mul '(var pi var-pi)
X						  (math-solve-get-int
X						   '(var i var-i))))
X			      (math-normalize
X			       (list 'calcFunc-ln (nth 1 lhs)))))))
X		 ((not (math-expr-depends (nth 2 lhs) solve-var))
X		  (cond ((math-equal-int (nth 2 lhs) 2)
X			 (math-try-solve-for
X			  (nth 1 lhs)
X			  (math-solve-get-sign
X			   (math-normalize (list 'calcFunc-sqrt rhs)))))
X			(t (math-try-solve-for
X			    (nth 1 lhs)
X			    (math-mul
X			     (math-normalize
X			      (list 'calcFunc-exp
X				    (if (Math-realp (nth 2 lhs))
X					(math-div (math-mul
X						   '(var pi var-pi)
X						   (math-solve-get-int
X						    '(var i var-i)))
X						  (math-div (nth 2 lhs) 2))
X				      (math-div (math-mul
X						 2
X						 (math-mul
X						  '(var pi var-pi)
X						  (math-solve-get-int
X						   '(var i var-i))))
X						(nth 2 lhs)))))
X			     (math-normalize
X			      (list '^
X				    rhs
X				    (math-div 1 (nth 2 lhs)))))))))))
X	  ((and (eq (car lhs) '%)
X		(not (math-expr-depends (nth 2 lhs) solve-var)))
X	   (math-try-solve-for (nth 1 lhs) (math-add rhs
X						     (math-solve-get-int
X						      (nth 2 lhs)))))
X	  ((and (= (length lhs) 2)
X		(symbolp (car lhs))
X		(setq t1 (get (car lhs) 'math-inverse))
X		(setq t2 (funcall t1 rhs)))
X	   (math-try-solve-for (nth 1 lhs) (math-normalize t2)))
X	  (t
X	   (calc-record-why "No inverse known" lhs)
X	   nil)))
X)
X
X(defun math-get-from-counter (name)
X  (let ((ctr (assq name calc-command-flags)))
X    (if ctr
X	(setcdr ctr (1+ (cdr ctr)))
X      (setq ctr (cons name 1)
X	    calc-command-flags (cons ctr calc-command-flags)))
X    (cdr ctr))
X)
X
X(defun math-solve-get-sign (val)
X  (if solve-full
X      (let ((var (concat "s" (math-get-from-counter 'solve-sign))))
X	(math-mul (list 'var (intern var) (intern (concat "var-" var)))
X		  val))
X    (calc-record-why "Choosing positive solution")
X    val)
X)
X
X(defun math-solve-get-int (val)
X  (if solve-full
X      (let ((var (concat "n" (math-get-from-counter 'solve-int))))
X	(math-mul val
X		  (list 'var (intern var) (intern (concat "var-" var)))))
X    (calc-record-why "Choosing 0 for arbitrary integer in solution")
X    0)
X)
X
X(defun math-looks-evenp (expr)
X  (if (Math-integerp expr)
X      (math-evenp expr)
X    (if (memq (car expr) '(* /))
X	(math-looks-evenp (nth 1 expr))))
X)
X
X(defun math-solve-for (lhs rhs solve-var solve-full)
X  (if (math-expr-contains rhs solve-var)
X      (math-solve-for (math-sub lhs rhs) 0 solve-var solve-full)
X    (and (math-expr-contains lhs solve-var)
X	 (math-try-solve-for lhs rhs)))
X)
X
X(defun calcFunc-solve (expr var)
X  (let ((res (math-solve-for expr 0 var nil)))
X    (if res
X	(list 'calcFunc-eq var res)
X      (list 'calcFunc-solve expr var)))
X)
X
X(defun calcFunc-fsolve (expr var)
X  (let ((res (math-solve-for expr 0 var t)))
X    (if res
X	(list 'calcFunc-eq var res)
X      (list 'calcFunc-fsolve expr var)))
X)
X
X(defun calcFunc-finv (expr var)
X  (let ((res (math-solve-for expr math-integ-var var nil)))
X    (if res
X	(math-normalize (math-expr-subst res math-integ-var var))
X      (list 'calcFunc-finv expr var)))
X)
X
X(defun calcFunc-ffinv (expr var)
X  (let ((res (math-solve-for expr math-integ-var var t)))
X    (if res
X	(math-normalize (math-expr-subst res math-integ-var var))
X      (list 'calcFunc-finv expr var)))
X)
X
X
X(put 'calcFunc-inv 'math-inverse
X     (function (lambda (x) (math-div 1 x))))
X
X(put 'calcFunc-sqrt 'math-inverse
X     (function (lambda (x) (math-sqr x))))
X
X(put 'calcFunc-conj 'math-inverse
X     (function (lambda (x) (list 'calcFunc-conj x))))
X
X(put 'calcFunc-abs 'math-inverse
X     (function (lambda (x) (math-solve-get-sign x))))
X
X(put 'calcFunc-deg 'math-inverse
X     (function (lambda (x) (list 'calcFunc-rad x))))
X
X(put 'calcFunc-rad 'math-inverse
X     (function (lambda (x) (list 'calcFunc-deg x))))
X
X(put 'calcFunc-ln 'math-inverse
X     (function (lambda (x) (list 'calcFunc-exp x))))
X
X(put 'calcFunc-log10 'math-inverse
X     (function (lambda (x) (list 'calcFunc-exp10 x))))
X
X(put 'calcFunc-lnp1 'math-inverse
X     (function (lambda (x) (list 'calcFunc-expm1 x))))
X
X(put 'calcFunc-exp 'math-inverse
X     (function (lambda (x) (math-add (math-normalize (list 'calcFunc-ln x))
X				     (math-mul 2
X					       (math-mul '(var pi var-pi)
X							 (math-solve-get-int
X							  '(var i var-i))))))))
X
X(put 'calcFunc-expm1 'math-inverse
X     (function (lambda (x) (math-add (math-normalize (list 'calcFunc-lnp1 x))
X				     (math-mul 2
X					       (math-mul '(var pi var-pi)
X							 (math-solve-get-int
X							  '(var i var-i))))))))
X
X(put 'calcFunc-sin 'math-inverse
X     (function (lambda (x) (let ((n (math-solve-get-int 1)))
X			     (math-add (math-mul (math-normalize
X						  (list 'calcFunc-arcsin x))
X						 (math-pow -1 n))
X				       (math-mul (math-half-circle t)
X						 n))))))
X
X(put 'calcFunc-cos 'math-inverse
X     (function (lambda (x) (math-add (math-solve-get-sign
X				      (math-normalize
X				       (list 'calcFunc-arccos x)))
X				     (math-solve-get-int
X				      (math-full-circle t))))))
X
X(put 'calcFunc-tan 'math-inverse
X     (function (lambda (x) (math-add (math-normalize (list 'calcFunc-arctan x))
X				     (math-solve-get-int
X				      (math-half-circle t))))))
X
X(put 'calcFunc-arcsin 'math-inverse
X     (function (lambda (x) (math-normalize (list 'calcFunc-sin x)))))
X
X(put 'calcFunc-arccos 'math-inverse
X     (function (lambda (x) (math-normalize (list 'calcFunc-cos x)))))
X
X(put 'calcFunc-arctan 'math-inverse
X     (function (lambda (x) (math-normalize (list 'calcFunc-tan x)))))
X
X(put 'calcFunc-sinh 'math-inverse
X     (function (lambda (x) (let ((n (math-solve-get-int 1)))
X			     (math-add (math-mul (math-normalize
X						  (list 'calcFunc-arctanh x))
X						 (math-pow -1 n))
X				       (math-mul (math-half-circle t)
X						 (math-mul
X						  '(var i var-i)
X						  n)))))))
X
X(put 'calcFunc-cosh 'math-inverse
X     (function (lambda (x) (math-add (math-solve-get-sign
X				      (math-normalize
X				       (list 'calcFunc-arctanh x)))
X				     (math-mul (math-full-circle t)
X					       (math-solve-get-int
X						'(var i var-i)))))))
X
X(put 'calcFunc-tanh 'math-inverse
X     (function (lambda (x) (math-add (math-normalize
X				      (list 'calcFunc-arctanh x))
X				     (math-mul (math-half-circle t)
X					       (math-solve-get-int
X						'(var i var-i)))))))
X
X(put 'calcFunc-arcsinh 'math-inverse
X     (function (lambda (x) (math-normalize (list 'calcFunc-sinh x)))))
X
X(put 'calcFunc-arccosh 'math-inverse
X     (function (lambda (x) (math-normalize (list 'calcFunc-cosh x)))))
X
X(put 'calcFunc-arctanh 'math-inverse
X     (function (lambda (x) (math-normalize (list 'calcFunc-tanh x)))))
X
X
X
X(defun calcFunc-taylor (expr var num)
X  (let ((x0 0) (v var))
X    (if (memq (car-safe var) '(+ - calcFunc-eq))
X	(setq x0 (if (eq (car var) '+) (math-neg (nth 2 var)) (nth 2 var))
X	      v (nth 1 var)))
X    (or (and (eq (car-safe v) 'var)
X	     (math-expr-contains expr v)
X	     (natnump num)
X	     (let ((accum (math-expr-subst expr v x0))
X		   (var2 (if (eq (car var) 'calcFunc-eq)
X			     (cons '- (cdr var))
X			   var))
X		   (n 0)
X		   (nfac 1)
X		   (fprime expr))
X	       (while (and (<= (setq n (1+ n)) num)
X			   (setq fprime (calcFunc-deriv fprime v nil t)))
X		 (setq fprime (math-simplify fprime)
X		       nfac (math-mul nfac n)
X		       accum (math-add accum
X				       (math-div (math-mul (math-pow var2 n)
X							   (math-expr-subst
X							    fprime v x0))
X						 nfac))))
X	       (and fprime
X		    (math-normalize accum))))
X	(list 'calcFunc-taylor expr var num)))
X)
X
X
X
X
X;;; Simple operations on expressions.
X
X;;; Return number of ocurrences of thing in expr, or nil if none.
X(defun math-expr-contains (expr thing)
X  (cond ((equal expr thing) 1)
X	((Math-primp expr) nil)
X	(t
X	 (let ((num 0))
X	   (while (setq expr (cdr expr))
X	     (setq num (+ num (or (math-expr-contains (car expr) thing) 0))))
X	   (and (> num 0)
X		num))))
X)
X
X;;; Return non-nil if any variable of thing occurs in expr.
X(defun math-expr-depends (expr thing)
X  (if (Math-primp thing)
X      (and (eq (car-safe thing) 'var)
X	   (math-expr-contains expr thing))
X    (while (and (setq thing (cdr thing))
X		(not (math-expr-depends expr (car thing)))))
X    thing)
X)
X
X;;; Substitute all occurrences of old for new in expr (non-destructive).
X(defun math-expr-subst (expr old new)
X  (math-expr-subst-rec expr)
X)
X
X(defun math-expr-subst-rec (expr)
X  (cond ((equal expr old) new)
X	((Math-primp expr) expr)
X	((memq (car expr) '(calcFunc-deriv
X			    calcFunc-tderiv))
X	 (if (= (length expr) 2)
X	     (if (equal (nth 1 expr) old)
X		 (append expr (list new))
X	       expr)
X	   (list (car expr) (nth 1 expr)
X		 (math-expr-subst-rec (nth 2 expr)))))
X	(t
X	 (cons (car expr)
X	       (mapcar 'math-expr-subst-rec (cdr expr)))))
X)
X
X;;; Various measures of the size of an expression.
X(defun math-expr-weight (expr)
X  (if (Math-primp expr)
X      1
X    (let ((w 1))
X      (while (setq expr (cdr expr))
X	(setq w (+ w (math-expr-weight (car expr)))))
X      w))
X)
X
X(defun math-expr-height (expr)
X  (if (Math-primp expr)
X      0
X    (let ((h 0))
X      (while (setq expr (cdr expr))
X	(setq h (max h (math-expr-height (car expr)))))
X      (1+ h)))
X)
X
X
X
X
X;;; Polynomial operations (to support the integrator and solve-for).
X
X(defun math-collect-terms (expr base)
X  (let ((p (math-is-polynomial expr base 20 t)))
X    (if (cdr p)
X	(math-build-polynomial-expr p base)
X      expr))
X)
X
X;;; If expr is of the form "a + bx + cx^2 + ...", return the list (a b c ...),
X;;; else return nil if not in polynomial form.  If "loose", coefficients
X;;; may contain x, e.g., sin(x) + cos(x) x^2 is a loose polynomial in x.
X(defun math-is-polynomial (expr var &optional degree loose)
X  (let ((poly (math-is-poly-rec expr)))
X    (and (or (null degree)
X	     (<= (length poly) (1+ degree)))
X	 poly))
X)
X
X(defun math-is-poly-rec (expr)
X  (math-poly-simplify
X   (or (cond ((equal expr var)
X	      (list 0 1))
X	     ((Math-objectp expr)
X	      (list expr))
X	     ((memq (car expr) '(+ -))
X	      (let ((p1 (math-is-poly-rec (nth 1 expr))))
X		(and p1
X		     (let ((p2 (math-is-poly-rec (nth 2 expr))))
X		       (and p2
X			    (math-poly-mix p1 1 p2
X					   (if (eq (car expr) '+) 1 -1)))))))
X	     ((eq (car expr) 'neg)
X	      (mapcar 'math-neg (math-is-poly-rec (nth 1 expr))))
X	     ((eq (car expr) '*)
X	      (let ((p1 (math-is-poly-rec (nth 1 expr))))
X		(and p1
X		     (let ((p2 (math-is-poly-rec (nth 2 expr))))
X		       (and p2
X			    (or (null degree)
X				(<= (- (+ (length p1) (length p2)) 2) degree))
X			    (math-poly-mul p1 p2))))))
X	     ((eq (car expr) '/)
X	      (and (not (math-expr-depends (nth 2 expr) var))
X		   (not (Math-zerop (nth 2 expr)))
X		   (let ((p1 (math-is-poly-rec (nth 1 expr))))
X		     (mapcar (function (lambda (x) (math-div x (nth 2 expr))))
X			     p1))))
X	     ((eq (car expr) '^)
X	      (and (natnump (nth 2 expr))
X		   (let ((p1 (math-is-poly-rec (nth 1 expr)))
X			 (n (nth 2 expr))
X			 (accum (list 1)))
X		     (and p1
X			  (or (null degree)
X			      (<= (* (1- (length p1)) n) degree))
X			  (progn
X			    (while (>= n 1)
X			      (setq accum (math-poly-mul accum p1)
X				    n (1- n)))
X			    accum)))))
X	     (t nil))
X       (and (or (not (math-expr-depends expr var))
X		loose)
X	    (not (memq (car expr) '(vec)))
X	    (list expr))))
X)
X
X;;; Check if expr is a polynomial in var; if so, return its degree.
X(defun math-polynomial-p (expr var)
X  (cond ((equal expr var) 1)
X	((Math-primp expr) 0)
X	((memq (car expr) '(+ -))
X	 (let ((p1 (math-polynomial-p (nth 1 expr) var))
X	       (p2 (math-polynomial-p (nth 2 expr) var)))
X	   (and p1 p2 (max p1 p2))))
X	((eq (car expr) '*)
X	 (let ((p1 (math-polynomial-p (nth 1 expr) var))
X	       (p2 (math-polynomial-p (nth 2 expr) var)))
X	   (and p1 p2 (+ p1 p2))))
X	((eq (car expr) 'neg)
X	 (math-polynomial-p (nth 1 expr) var))
X	((and (eq (car expr) '/)
X	      (not (math-expr-depends (nth 1 expr) var)))
X	 (math-polynomial-p (nth 1 expr) var))
X	((and (eq (car expr) '^)
X	      (natnump (nth 2 expr)))
X	 (let ((p1 (math-polynomial-p (nth 1 expr) var)))
X	   (and p1 (* p1 (nth 2 expr)))))
X	((math-expr-depends expr var) nil)
X	(t 0))
X)
X
X;;; Find the variable (or sub-expression) which is the base of polynomial expr.
X(defun math-polynomial-base (mpb-top-expr &optional mpb-pred)
X  (or mpb-pred
X      (setq mpb-pred (function (lambda (base) (math-polynomial-p
X					       mpb-top-expr base)))))
X  (or (let ((const-ok nil))
X	(math-polynomial-base-rec mpb-top-expr))
X      (let ((const-ok t))
X	(math-polynomial-base-rec mpb-top-expr)))
X)
X
X(defun math-polynomial-base-rec (mpb-expr)
X  (and (not (Math-objvecp mpb-expr))
X       (or (and (memq (car mpb-expr) '(+ - *))
X		(or (math-polynomial-base-rec (nth 1 mpb-expr))
X		    (math-polynomial-base-rec (nth 2 mpb-expr))))
X	   (and (memq (car mpb-expr) '(/ neg))
X		(math-polynomial-base-rec (nth 1 mpb-expr)))
X	   (and (eq (car mpb-expr) '^)
X		(natnump (nth 2 mpb-expr))
X		(math-polynomial-base-rec (nth 1 mpb-expr)))
X	   (and (or const-ok (math-expr-contains-vars mpb-expr))
X		(funcall mpb-pred mpb-expr)
X		mpb-expr)))
X)
X
X;;; Return non-nil if expr refers to any variables.
X(defun math-expr-contains-vars (expr)
X  (or (eq (car-safe expr) 'var)
X      (and (not (Math-primp expr))
X	   (progn
X	     (while (and (setq expr (cdr expr))
X			 (not (math-expr-contains-vars (car expr)))))
X	     expr)))
X)
X
X;;; Simplify a polynomial in list form by stripping off high-end zeros.
X;;; This always leaves the constant part, i.e., nil->nil and nonnil->nonnil.
X(defun math-poly-simplify (p)
X  (and p
X       (if (Math-zerop (nth (1- (length p)) p))
X	   (let ((pp (copy-sequence p)))
X	     (while (and (cdr pp)
X			 (Math-zerop (nth (1- (length pp)) pp)))
X	       (setcdr (nthcdr (- (length pp) 2) pp) nil))
X	     pp)
X	 p))
X)
X
X;;; Compute ac*a + bc*b for polynomials in list form a, b and
X;;; coefficients ac, bc.  Result may be unsimplified.
X(defun math-poly-mix (a ac b bc)
X  (and (or a b)
X       (cons (math-add (math-mul (or (car a) 0) ac)
X		       (math-mul (or (car b) 0) bc))
X	     (math-poly-mix (cdr a) ac (cdr b) bc)))
X)
X
X;;; Multiply two polynomials in list form.
X(defun math-poly-mul (a b)
X  (and a b
X       (math-poly-mix b (car a)
X		      (math-poly-mul (cdr a) (cons 0 b)) 1))
X)
X
X;;; Build an expression from a polynomial list.
X(defun math-build-polynomial-expr (p var)
X  (if p
X      (let ((accum (car p))
X	    (n 0))
X	(while (setq p (cdr p))
X	  (setq n (1+ n)
X		accum (math-add (math-mul (car p) (math-pow var n)) accum)))
X	accum))
X)
X
X
X
X
X;;; Units operations.
X
X(defvar math-standard-units
X  '( ;; Length
X     ( m       nil		     "*Meter" )
X     ( in      "2.54 cm"             "Inch" )
X     ( ft      "12 in"		     "Foot" )
X     ( yd      "3 ft"		     "Yard" )
X     ( mi      "5280 ft"	     "Mile" )
X     ( au      "1.495979e11 m"       "Astronomical Unit" )
X     ( lyr     "9.46052e15 m"	     "Light Year" )
X     ( pc      "3.08568e16 m"	     "Parsec" )
X     ( nmi     "1852 m"		     "Nautical Mile" )
X     ( fath    "6 ft"		     "Fathom" )
X     ( u       "1 um"		     "Micron" )
X     ( mil     "in/1000"	     "Mil" )
X     ( point   "in/72"		     "Point" )
X     ( Ang     "1e-10 m"	     "Angstrom" )
X     
X     ;; Area
X     ( hect    "1000 m^2"	     "*Hectare" )
X     ( acre    "mi^2 / 640"	     "Acre" )
X     ( b       "1e-28 m^2"	     "Barn" )
X     
X     ;; Volume
X     ( l       "1e-3 m^3"	     "*Liter" )
X     ( L       "1e-3 m^3"	     "Liter" )
X     ( gal     "4 qt"		     "US Gallon" )
X     ( qt      "2 pt"		     "Quart" )
X     ( pt      "2 cup"		     "Pint" )
X     ( cup     "8 ozfl"		     "Cup" )
X     ( ozfl    "2 tbsp"		     "Fluid Ounce" )
X     ( tbsp    "3 tsp"		     "Tablespoon" )
X     ( tsp     "4.92892 ml"	     "Teaspoon" )
X     ( galC    "4.54609 l"	     "Canadian Gallon" )
X     ( galUK   "4.546092 l"	     "UK Gallon" )
X     
X     ;; Time
X     ( s       nil		     "*Second" )
X     ( min     "60 s"		     "Minute" )
X     ( hr      "60 min"		     "Hour" )
X     ( day     "24 hr"		     "Day" )
X     ( wk      "7 day"		     "Week" )
X     ( yr      "365.25 day"	     "Year" )
X     ( Hz      "1/s"		     "Hertz" )
X
X     ;; Speed
X     ( mph     "mi/hr"		     "*Miles per hour" )
X     ( kph     "km/hr"		     "Kilometers per hour" )
X     ( knot    "nmi/hr"		     "Knot" )
X     ( c       "2.99792458e8 m/s"    "Speed of light" )     
X     
X     ;; Acceleration
X     ( ga      "9.80665 m/s^2"	     "*\"g\" acceleration" )
X
X     ;; Mass
X     ( g       nil                   "*Gram" )
X     ( lb      "16 oz"		     "Pound (mass)" )
X     ( oz      "28.349523125 g"	     "Ounce (mass)" )
X     ( ton     "2000 lb"	     "Ton" )
X     ( t       "1000 kg"	     "Metric ton" )
X     ( tonUK   "1016.0469088 kg"     "UK ton" )
X     ( lbt     "12 ozt"		     "Troy pound" )
X     ( ozt     "31.103475 g"	     "Troy ounce" )
X     ( ct      ".2 g"		     "Carat" )
X     ( amu     "1.6605655e-24 g"     "Unified atomic mass" )
X
X     ;; Force
X     ( N       "m kg/s^2"	     "*Newton" )
X     ( dyn     "1e-5 N"		     "Dyne" )
X     ( gf      "9.60665e-3 N"	     "Gram (force)" )
X     ( lbf     "4.44822161526 N"     "Pound (force)" )
X     ( kip     "1000 lbf"	     "Kilopound (force)" )
X     ( pdl     "0.138255 N"	     "Poundal" )
X
X     ;; Energy
X     ( J       "N m"		     "*Joule" )
X     ( erg     "1e-7 J"		     "Erg" )
X     ( cal     "4.1868 J"	     "International Table Calorie" )
X     ( Btu     "1055.05585262 J"     "International Table Btu" )
X     ( eV      "1.6021892e-19 J"     "Electron volt" )
X     ( therm   "105506000 J"	     "EEC therm" )
X
X     ;; Power
X     ( W       "J/s"		     "*Watt" )
X     ( hp      "745.7 W"	     "Horsepower" )
X
X     ;; Temperature
X     ( K       nil                   "*Degree Kelvin"     K )
X     ( dK      "K"		     "Degree Kelvin"	  K )
X     ( degK    "K"		     "Degree Kelvin"	  K )
X     ( dC      "K"		     "Degree Celsius"	  C )
X     ( degC    "K"      	     "Degree Celsius"	  C )
X     ( dF      "(5/9) K"	     "Degree Fahrenheit"  F )
X     ( degF    "(5/9) K"	     "Degree Fahrenheit"  F )
X
X     ;; Pressure
X     ( Pa      "N/m^2"		     "*Pascal" )
X     ( bar     "1e5 Pa"		     "Bar" )
X     ( atm     "101325 Pa"	     "Standard atmosphere" )
X     ( torr    "atm/760"	     "Torr" )
X     ( mHg     "1000 torr"	     "Meter of mercury" )
X     ( inHg    "25.4 mmHg"	     "Inch of mercury" )
X     ( inH2O   "248.84 Pa"	     "Inch of water" )
X     ( psi     "6894.75729317 Pa"    "Pound per square inch" )
X
X     ;; Viscosity
X     ( P       "0.1 Pa s"	     "*Poise" )
X     ( St      "1e-4 m^2/s"	     "Stokes" )
X
X     ;; Electromagnetism
X     ( A       nil                   "*Ampere" )
X     ( C       "A s"		     "Coulomb" )
X     ( Fdy     "96487 C"	     "Faraday" )
X     ( e       "1.6021892e-19 C"     "Elementary charge" )
X     ( V       "W/A"		     "Volt" )
X     ( ohm     "V/A"		     "Ohm" )
X     ( mho     "A/V"		     "Mho" )
X     ( S       "A/V"		     "Siemens" )
X     ( F       "C/V"		     "Farad" )
X     ( H       "Wb/A"		     "Henry" )
X     ( T       "Wb/m^2"		     "Tesla" )
X     ( G       "1e-4 T"		     "Gauss" )
X     ( Wb      "V s"		     "Weber" )
X
X     ;; Luminous intensity
X     ( cd      nil                   "*Candela" )
X     ( sb      "1e4 cd/m^2"	     "Stilb" )
X     ( lm      "cd sr"		     "Lumen" )
X     ( lx      "lm/m^2"		     "Lux" )
X     ( ph      "1e4 lx"		     "Phot" )
X     ( fc      "10.76 lx"	     "Footcandle" )
X     ( lam     "1e4 lm/m^2"	     "Lambert" )
X     ( flam    "1.07639104e-3 lam"   "Footlambert" )
X
X     ;; Radioactivity
X     ( Bq      "1/s"  		     "*Becquerel" )
X     ( Ci      "3.7e8 Bq"	     "Curie" )
X     ( Gy      "J/kg"		     "Gray" )
X     ( Sv      "Gy"		     "Sievert" )
X     ( R       "2.58e-4 C/kg"	     "Roentgen" )
X     ( rd      ".01 Sv"		     "Rad" )
X     ( rem     "rd"		     "Rem" )
X
X     ;; Amount of substance
X     ( mol     nil                   "*Mole" )
X
X     ;; Plane angle
X     ( rad     nil                   "*Radian" )
X     ( circ    "2 pi rad"	     "Full circle" )
X     ( deg     "circ/360"            "Degree" )
X     ( arcmin  "deg/60"		     "Arc minute" )
X     ( arcsec  "arcmin/60"	     "Arc second" )
X     ( grad    "circ/400"            "Grade" )
X
X     ;; Solid angle
X     ( sr      nil		     "*Steradian" )
X
X     ;; Other physical quantities (CRC chem & phys, 67th ed)
X     ( h       "6.626176e-34 J s"    "*Planck's constant" )
X     ( hbar    "h / 2 pi"	     "Planck's constant" )
X     ( mu0     "4 pi 1e-7 H/m"       "Permeability of vacuum" )
X     ( Grav    "6.6720e-11 N m^2/kg^2"  "Gravitational constant" )
X     ( Nav     "6.0222e23 / mol"     "Avagadro's constant" )
X     ( me      "9.109534e-31 kg"     "Electron rest mass" )
X     ( mp      "1.6726485e-27 kg"    "Proton rest mass" )
X     ( mn      "1.6749543e-27 kg"    "Neutron rest mass" )
X     ( mu      "1.883566e-28 kg"     "Muon rest mass" )
X     ( Ryd     "1.097373177e7 / m"   "Rydberg's constant" )
X     ( k       "Ryd / Nav"	     "Boltzmann's constant" )
X     ( fsc     "7.2973506e-3"	     "Fine structure constant" )
X     ( mue     "9.284832e-24 J/T"    "Electron magnetic moment" )
X     ( mup     "1.4106171e-26 J/T"   "Proton magnetic moment" )
X     ( R0      "8.31441 J/mol K"     "Molar gas constant" )
X     ( V0      "22.4136 L/mol"	     "Standard volume of ideal gas" )
X))
X
X
X(defvar math-additional-units nil
X  "*Additional units table for user-defined units.
XMust be formatted like math-standard-units.
XIf this is changed, be sure to set math-units-table to nil to ensure
Xthat the combined units table will be rebuilt.")
X
X(defvar math-unit-prefixes
X  '( ( ?E  (float 1 18)  "Exa"    )
X     ( ?P  (float 1 15)  "Peta"   )
X     ( ?T  (float 1 12)  "Tera"	  )
X     ( ?G  (float 1 9)   "Giga"	  )
X     ( ?M  (float 1 6)   "Mega"	  )
X     ( ?k  (float 1 3)   "Kilo"	  )
X     ( ?K  (float 1 3)   "Kilo"	  )
X     ( ?h  (float 1 2)   "Hecto"  )
X     ( ?H  (float 1 2)   "Hecto"  )
X     ( ?D  (float 1 1)   "Deka"	  )
X     ( ?d  (float 1 -1)  "Deci"	  )
X     ( ?c  (float 1 -2)  "Centi"  )
X     ( ?m  (float 1 -3)  "Milli"  )
X     ( ?u  (float 1 -6)  "Micro"  )
X     ( ?n  (float 1 -9)  "Nano"	  )
X     ( ?p  (float 1 -12) "Pico"	  )
X     ( ?f  (float 1 -15) "Femto"  )
X     ( ?a  (float 1 -18) "Atto"   )
X))
X
X(defvar math-standard-units-systems
X  '( ( base  nil )
X     ( si    ( ( g   '(* (var kg var-kg) (float 1 -3)) ) ) )
X     ( mks   ( ( g   '(* (var kg var-kg) (float 1 -3)) ) ) )
X     ( cgs   ( ( m   '(* (var cm var-cm) 100         ) ) ) )
X))
X
X(defvar math-units-table nil
X  "Internal units table derived from math-defined-units.
XEntries are (SYMBOL EXPR DOC-STRING TEMP-TYPE BASE-UNITS).")
X
X(defvar math-units-table-buffer-valid nil)
X
X
X(defun math-build-units-table ()
X  (or math-units-table
X      (let* ((combined-units (append math-additional-units
X				     math-standard-units))
X	     (unit-list (mapcar 'car combined-units))
X	     (calc-language nil)
X	     (math-expr-opers math-standard-opers)
X	     tab)
X	(message "Building units table...")
X	(setq math-units-table-buffer-valid nil)
X	(setq tab (mapcar (function
X			   (lambda (x)
X			     (list (car x)
X				   (and (nth 1 x)
X					(if (stringp (nth 1 x))
X					    (let ((exp (math-read-expr
X							(nth 1 x))))
X					      (if (eq (car-safe exp) 'error)
X						  (error "Format error in definition of %s in units table: %s"
X							 (car x) (nth 2 exp))
X						exp))
X					  (nth 1 x)))
X				   (nth 2 x)
X				   (nth 3 x)
X				   (and (not (nth 1 x))
X					(list (cons (car x) 1))))))
X			  combined-units))
X	(let ((math-units-table tab))
X	  (mapcar 'math-find-base-units tab))
X	(message "Building units table...done")
X	(setq math-units-table tab)))
X)
X
X(defun math-find-base-units (entry)
X  (if (eq (nth 4 entry) 'boom)
X      (error "Circular definition involving unit %s" (car entry)))
X  (or (nth 4 entry)
X      (let (base)
X	(setcar (nthcdr 4 entry) 'boom)
X	(math-find-base-units-rec (nth 1 entry) 1)
X	'(or base
X	    (error "Dimensionless definition for unit %s" (car entry)))
X	(while (eq (cdr (car base)) 0)
X	  (setq base (cdr base)))
X	(let ((b base))
X	  (while (cdr b)
X	    (if (eq (cdr (car (cdr b))) 0)
X		(setcdr b (cdr (cdr b)))
X	      (setq b (cdr b)))))
X	(setq base (sort base 'math-compare-unit-names))
X	(setcar (nthcdr 4 entry) base)
X	base))
X)
X
X(defun math-compare-unit-names (a b)
X  (memq (car b) (cdr (memq (car a) unit-list)))
X)
X
X(defun math-find-base-units-rec (expr pow)
X  (let ((u (math-check-unit-name expr)))
X    (cond (u
X	   (let ((ulist (math-find-base-units u)))
X	     (while ulist
X	       (let ((p (* (cdr (car ulist)) pow))
X		     (old (assq (car (car ulist)) base)))
X		 (if old
X		     (setcdr old (+ (cdr old) p))
X		   (setq base (cons (cons (car (car ulist)) p) base))))
X	       (setq ulist (cdr ulist)))))
X	  ((math-scalarp expr))
X	  ((and (eq (car expr) '^)
X		(integerp (nth 2 expr)))
X	   (math-find-base-units-rec (nth 1 expr) (* pow (nth 2 expr))))
X	  ((eq (car expr) '*)
X	   (math-find-base-units-rec (nth 1 expr) pow)
X	   (math-find-base-units-rec (nth 2 expr) pow))
X	  ((eq (car expr) '/)
X	   (math-find-base-units-rec (nth 1 expr) pow)
X	   (math-find-base-units-rec (nth 2 expr) (- pow)))
X	  ((eq (car expr) 'neg)
X	   (math-find-base-units-rec (nth 1 expr) pow))
X	  ((eq (car expr) 'var)
X	   (or (eq (nth 1 expr) 'pi)
X	       (error "Unknown name %s in defining expression for unit %s"
X		      (nth 1 expr) (car entry))))
X	  (t (error "Malformed defining expression for unit %s" (car entry)))))
X)
X
X
X(defun math-units-in-expr-p (expr sub-exprs)
X  (and (consp expr)
X       (if (eq (car expr) 'var)
X	   (math-check-unit-name expr)
X	 (and (or sub-exprs
X		  (memq (car expr) '(* / ^)))
X	      (or (math-units-in-expr-p (nth 1 expr) sub-exprs)
X		  (math-units-in-expr-p (nth 2 expr) sub-exprs)))))
X)
X
X(defun math-only-units-in-expr-p (expr)
X  (and (consp expr)
X       (if (eq (car expr) 'var)
X	   (math-check-unit-name expr)
X	 (if (memq (car expr) '(* /))
X	     (and (math-only-units-in-expr-p (nth 1 expr))
X		  (math-only-units-in-expr-p (nth 2 expr)))
X	   (and (eq (car expr) '^)
X		(and (math-only-units-in-expr-p (nth 1 expr))
X		     (math-realp (nth 2 expr)))))))
X)
X
X(defun math-single-units-in-expr-p (expr)
X  (cond ((math-scalarp expr) nil)
X	((eq (car expr) 'var)
X	 (math-check-unit-name expr))
X	((eq (car expr) '*)
X	 (let ((u1 (math-single-units-in-expr-p (nth 1 expr)))
X	       (u2 (math-single-units-in-expr-p (nth 2 expr))))
X	   (or (and u1 u2 'wrong)
X	       u1
X	       u2)))
X	((eq (car expr) '/)
X	 (if (math-units-in-expr-p (nth 2 expr))
X	     'wrong
X	   (math-single-units-in-expr-p (nth 1 expr))))
X	(t 'wrong))
X)
X
X(defun math-check-unit-name (v)
X  (and (eq (car-safe v) 'var)
X       (or (assq (nth 1 v) (or math-units-table (math-build-units-table)))
X	   (let ((name (symbol-name (nth 1 v))))
X	     (and (> (length name) 1)
X		  (assq (aref name 0) math-unit-prefixes)
X		  (or (assq (intern (substring name 1)) math-units-table)
X		      (and (eq (aref name 0) ?M)
X			   (> (length name) 3)
X			   (eq (aref name 1) ?e)
X			   (eq (aref name 2) ?g)
X			   (assq (intern (substring name 3))
X				 math-units-table)))))))
X)
X
X
X(defun math-to-standard-units (expr which-standard)
X  (math-to-standard-rec expr)
X)
X
X(defun math-to-standard-rec (expr)
X  (if (eq (car-safe expr) 'var)
X      (let ((u (math-check-unit-name expr))
X	    (base (nth 1 expr)))
X	(if u
X	    (progn
X	      (if (nth 1 u)
X		  (setq expr (math-to-standard-rec (nth 1 u)))
X		(let ((st (assq (car u) which-standard)))
X		  (if st
X		      (setq expr (nth 1 st))
X		    (setq expr (list 'var (car u)
X				     (intern (concat "var-"
X						     (symbol-name
X						      (car u)))))))))
X	      (or (null u)
X		  (eq base (car u))
X		  (setq expr (list '*
X				   (nth 1 (assq (aref (symbol-name base) 0)
X						math-unit-prefixes))
X				   expr)))
X	      expr)
X	  (if (eq base 'pi)
X	      (math-pi)
X	    expr)))
X    (if (Math-primp expr)
X	expr
X      (cons (car expr)
X	    (mapcar 'math-to-standard-rec (cdr expr)))))
X)
X
X(defun math-convert-units (expr new-units)
X  (if (math-units-in-expr-p expr t)
X      (math-convert-units-rec expr)
X    (list '*
X	  (math-to-standard-units (list '/ expr new-units) nil)
X	  new-units))
X)
X
X(defun math-convert-units-rec (expr)
X  (if (math-units-in-expr-p expr nil)
X      (list '*
X	    (math-to-standard-units (list '/ expr new-units) nil)
X	    new-units)
X    (if (Math-primp expr)
X	expr
X      (cons (car expr)
X	    (mapcar 'math-convert-units-rec (cdr expr)))))
X)
X
X(defun math-convert-temperature (expr old new)
X  (let* ((units (math-single-units-in-expr-p expr))
X	 (uold (if old
X		   (if (or (null units)
X			   (equal (nth 1 old) (car units)))
X		       (math-check-unit-name old)
X		     (error "Inconsistent temperature units"))
X		 units))
X	 (unew (math-check-unit-name new)))
X    (or (and (consp unew) (nth 3 unew))
X	(error "Not a valid temperature unit"))
X    (or (and (consp uold) (nth 3 uold))
X	(error "Not a pure temperature expression"))
X    (let ((v (car uold)))
X      (setq expr (list '/ expr (list 'var v
X				     (intern (concat "var-"
X						     (symbol-name v)))))))
X    (or (eq (nth 3 uold) (nth 3 unew))
X	(cond ((eq (nth 3 uold) 'K)
X	       (setq expr (list '- expr '(float 27315 -2)))
X	       (if (eq (nth 3 unew) 'F)
X		   (setq expr (list '+ (list '* expr '(frac 9 5)) 32))))
X	      ((eq (nth 3 uold) 'C)
X	       (if (eq (nth 3 unew) 'F)
X		   (setq expr (list '+ (list '* expr '(frac 9 5)) 32))
X		 (setq expr (list '+ expr '(float 27315 -2)))))
X	      (t
X	       (setq expr (list '* (list '- expr 32) '(frac 5 9)))
X	       (if (eq (nth 3 unew) 'K)
X		   (setq expr (list '+ expr '(float 27315 -2)))))))
X    (list '* expr new))
X)
X
X
X(setq math-simplifying-units nil)
X
X(defun math-simplify-units (a)
X  (let ((math-simplifying-units t))
X    (math-simplify a))
X)
X
X(math-defsimplify (+ -)
X  (and math-simplifying-units
X       (math-units-in-expr-p (nth 1 expr) nil)
X       (let* ((units (math-extract-units (nth 1 expr)))
X	      (ratio (math-simplify (math-to-standard-units
X				     (list '/ (nth 2 expr) units) nil))))
X	 (if (math-units-in-expr-p ratio nil)
X	     (progn
X	       (calc-record-why "Inconsistent units" expr)
X	       expr)
X	   (list '* (math-add (math-remove-units (nth 1 expr)) ratio)
X		 units))))
X)
X
X(math-defsimplify /
X  (and math-simplifying-units
X       (let ((np (cdr expr))
X	     n nn)
X	 (while (eq (car-safe (setq n (car np))) '*)
X	   (math-simplify-units-divisor (cdr n) (cdr (cdr expr)))
X	   (setq np (cdr (cdr n))))
X	 (math-simplify-units-divisor np (cdr (cdr expr)))
X	 expr))
X)
X
X(defun math-simplify-units-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-simplify-units-quotient n (nth 1 d)))
X	  (progn
X	    (setcar np (setq n temp))
X	    (setcar (cdr d) 1)))
X      (setq dp (cdr (cdr d))))
X    (if (setq temp (math-simplify-units-quotient n d))
X	(progn
X	  (setcar np (setq n temp))
X	  (setcar dp 1))))
X)
X
X;; Simplify, e.g., "in / cm" to "2.54" in a units expression.
X(defun math-simplify-units-quotient (n d)
X  (let ((un (math-check-unit-name n))
X	(ud (math-check-unit-name d)))
X    (and un ud
X	 (equal (nth 4 un) (nth 4 ud))
X	 (math-to-standard-units (list '/ n d) nil)))
X)
X
X(math-defsimplify ^
X  (and math-simplifying-units
X       (math-realp (nth 2 expr))
X       (math-simplify-units-pow (nth 1 expr) (nth 2 expr)))
X)
X
X(math-defsimplify calcFunc-sqrt
X  (and math-simplifying-units
X       (if (memq (car-safe (nth 1 expr)) '(* /))
X	   (list (car (nth 1 expr))
X		 (list 'calcFunc-sqrt (nth 1 (nth 1 expr)))
X		 (list 'calcFunc-sqrt (nth 2 (nth 1 expr))))
X	 (math-simplify-units-pow (nth 1 expr) '(frac 1 2))))
X)
X
X(math-defsimplify (calcFunc-floor
X		   calcFunc-ceil
X		   calcFunc-round
X		   calcFunc-trunc
X		   calcFunc-float
X		   calcFunc-frac
X		   calcFunc-abs
X		   calcFunc-clean)
X  (and math-simplifying-units
X       (if (math-only-units-in-expr-p (nth 1 expr))
X	   (nth 1 expr)
X	 (if (and (memq (car-safe (nth 1 expr)) '(* /))
X		  (or (math-only-units-in-expr-p
X		       (nth 1 (nth 1 expr)))
X		      (math-only-units-in-expr-p
X		       (nth 2 (nth 1 expr)))))
X	     (list (car (nth 1 expr))
X		   (cons (car expr)
X			 (cons (nth 1 (nth 1 expr))
X			       (cdr (cdr expr))))
X		   (cons (car expr)
X			 (cons (nth 2 (nth 1 expr))
X			       (cdr (cdr expr)))))))))
X
X(defun math-simplify-units-pow (a pow)
X  (if (and (eq (car-safe a) '^)
X	   (math-check-unit-name (nth 1 a))
X	   (math-realp (nth 2 a)))
X      (list '^ (nth 1 a) (math-mul pow (nth 2 a)))
X    (let* ((u (math-check-unit-name a))
X	   (pf (math-to-simple-fraction pow))
X	   (d (and (eq (car-safe pf) 'frac) (nth 2 pf))))
X      (and u
X	   (eq (car-safe pow) 'frac)
X	   (math-units-are-multiple u d)
X	   (list '^ (math-to-standard-units a nil) pow))))
X)
X
X(defun math-to-simple-fraction (f)
X  (or (and (eq (car-safe f) 'float)
X	   (or (and (>= (nth 2 f) 0)
X		    (math-scale-int (nth 1 f) (nth 2 f)))
X	       (and (integerp (nth 1 f))
X		    (> (nth 1 f) -1000)
X		    (< (nth 1 f) 1000)
X		    (math-make-frac (nth 1 f)
X				    (math-scale-int 1 (- (nth 2 f)))))))
X      f)
X)
X
X(defun math-units-are-multiple (u n)
X  (setq u (nth 4 u))
X  (while (and u (= (% (cdr (car u)) n) 0))
X    (setq u (cdr u)))
X  (null u)
X)
X
X(math-defsimplify calcFunc-sin
X  (and math-simplifying-units
X       (math-units-in-expr-p (nth 1 expr) nil)
X       (let ((rad (math-simplify-units
X		   (math-evaluate-expr
X		    (math-to-standard-units (nth 1 expr) nil))))
X	     (calc-angle-mode 'rad))
X	 (and (eq (car-safe rad) '*)
X	      (Math-realp (nth 1 rad))
X	      (eq (car-safe (nth 2 rad)) 'var)
X	      (eq (nth 1 (nth 2 rad)) 'rad)
X	      (list 'calcFunc-sin (nth 1 rad)))))
X)
X
X(math-defsimplify calcFunc-cos
X  (and math-simplifying-units
X       (math-units-in-expr-p (nth 1 expr) nil)
X       (let ((rad (math-simplify-units
X		   (math-evaluate-expr
X		    (math-to-standard-units (nth 1 expr) nil))))
X	     (calc-angle-mode 'rad))
X	 (and (eq (car-safe rad) '*)
X	      (Math-realp (nth 1 rad))
X	      (eq (car-safe (nth 2 rad)) 'var)
X	      (eq (nth 1 (nth 2 rad)) 'rad)
X	      (list 'calcFunc-cos (nth 1 rad)))))
X)
X
X(math-defsimplify calcFunc-tan
X  (and math-simplifying-units
X       (math-units-in-expr-p (nth 1 expr) nil)
X       (let ((rad (math-simplify-units
X		   (math-evaluate-expr
X		    (math-to-standard-units (nth 1 expr) nil))))
X	     (calc-angle-mode 'rad))
X	 (and (eq (car-safe rad) '*)
X	      (Math-realp (nth 1 rad))
X	      (eq (car-safe (nth 2 rad)) 'var)
X	      (eq (nth 1 (nth 2 rad)) 'rad)
X	      (list 'calcFunc-tan (nth 1 rad)))))
X)
X
X
X(defun math-remove-units (expr)
X  (if (math-check-unit-name expr)
X      1
X    (if (Math-primp expr)
X	expr
X      (cons (car expr)
X	    (mapcar 'math-remove-units (cdr expr)))))
X)
X
X(defun math-extract-units (expr)
X  (if (memq (car-safe expr) '(* /))
X      (cons (car expr)
X	    (mapcar 'math-extract-units (cdr expr)))
X    (if (math-check-unit-name expr) expr 1))
X)
X
X(defun math-build-units-table-buffer (enter-buffer)
X  (if (not (and math-units-table math-units-table-buffer-valid
X		(get-buffer "*Units Table*")))
X      (let ((buf (get-buffer-create "*Units Table*"))
X	    (uptr (math-build-units-table))
X	    (calc-language (if (eq calc-language 'big) nil calc-language))
X	    (calc-float-format '(float 0))
X	    (calc-group-digits nil)
X	    (calc-number-radix 10)
X	    (calc-point-char ".")
X	    (std nil)
X	    u name shadowed)
X	(save-excursion
X	  (message "Formatting units table...")
X	  (set-buffer buf)
X	  (setq buffer-read-only nil)
X	  (erase-buffer)
X	  (insert "Calculator Units Table:\n\n")
X	  (insert "Unit    Type  Definition                  Description\n\n")
X	  (while uptr
X	    (setq u (car uptr)
X		  name (nth 2 u))
X	    (if (eq (car u) 'm)
X		(setq std t))
X	    (setq shadowed (and std (assq (car u) math-additional-units)))
X	    (if (and name
X		     (> (length name) 1)
X		     (eq (aref name 0) ?\*))
X		(progn
X		  (or (eq uptr math-units-table)
X		      (insert "\n"))
X		  (setq name (substring name 1))))
X	    (insert " ")
X	    (and shadowed (insert "("))
X	    (insert (symbol-name (car u)))
X	    (and shadowed (insert ")"))
X	    (if (nth 3 u)
X		(progn
X		  (indent-to 10)
X		  (insert (symbol-name (nth 3 u))))
X	      (or std
X		  (progn
X		    (indent-to 10)
X		    (insert "U"))))
X	    (indent-to 14)
X	    (and shadowed (insert "("))
X	    (if (nth 1 u)
X		(insert (math-format-value (nth 1 u) 80))
X	      (insert (symbol-name (car u))))
X	    (and shadowed (insert ")"))
X	    (indent-to 42)
X	    (if name
X		(insert name))
X	    (if shadowed
X		(insert " (redefined above)")
X	      (or (nth 1 u)
X		  (insert " (base unit)")))
X	    (insert "\n")
X	    (setq uptr (cdr uptr)))
X	  (insert "\n\nUnit Prefix Table:\n\n")
X	  (setq uptr math-unit-prefixes)
X	  (while uptr
X	    (setq u (car uptr))
X	    (insert " " (char-to-string (car u)))
X	    (if (equal (nth 1 u) (nth 1 (nth 1 uptr)))
X		(insert " " (char-to-string (car (car (setq uptr (cdr uptr)))))
X			"   ")
X	      (insert "     "))
X	    (insert "10^" (int-to-string (nth 2 (nth 1 u))))
X	    (indent-to 15)
X	    (insert "   " (nth 2 u) "\n")
X	    (setq uptr (cdr uptr)))
X	  (insert "\n")
X	  (setq buffer-read-only t)
X	  (message "Formatting units table...done"))
X	(setq math-units-table-buffer-valid t)
X	(let ((oldbuf (current-buffer)))
X	  (set-buffer buf)
X	  (goto-char (point-min))
X	  (set-buffer oldbuf))
X	(if enter-buffer
X	    (pop-to-buffer buf)
X	  (display-buffer buf)))
X    (if enter-buffer
X	(pop-to-buffer (get-buffer "*Units Table*"))
X      (display-buffer (get-buffer "*Units Table*"))))
X)
X
X
X
X
X;;;; User-programmability.
X
X;;; Compiling Lisp-like forms to use the math library.
X
X(defun math-do-defmath (func args body)
X  (let* ((fname (intern (concat "calcFunc-" (symbol-name func))))
X	 (doc (if (stringp (car body)) (list (car body))))
X	 (clargs (mapcar 'math-clean-arg args))
X	 (body (math-define-function-body
X		(if (stringp (car body)) (cdr body) body)
X		clargs)))
X    (list 'progn
X	  (if (and (consp (car body))
X		   (eq (car (car body)) 'interactive))
X	      (let ((inter (car body)))
X		(setq body (cdr body))
X		(if (or (> (length inter) 2)
X			(integerp (nth 1 inter)))
X		    (let ((hasprefix nil) (hasmulti nil))
X		      (if (stringp (nth 1 inter))
X			  (progn
X			    (cond ((equal (nth 1 inter) "p")
X				   (setq hasprefix t))
X				  ((equal (nth 1 inter) "m")
X				   (setq hasmulti t))
X				  (t (error
X				      "Can't handle interactive code string \"%s\""
X				      (nth 1 inter))))
X			    (setq inter (cdr inter))))
X		      (if (not (integerp (nth 1 inter)))
X			  (error
X			   "Expected an integer in interactive specification"))
X		      (append (list 'defun
X				    (intern (concat "calc-"
X						    (symbol-name func)))
X				    (if (or hasprefix hasmulti)
X					'(&optional n)
X				      ()))
X			      doc
X			      (if (or hasprefix hasmulti)
X				  '((interactive "P"))
X				'((interactive)))
X			      (list
X			       (append
X				'(calc-slow-wrapper)
X				(and hasmulti
X				     (list
X				      (list 'setq
X					    'n
X					    (list 'if
X						  'n
X						  (list 'prefix-numeric-value
X							'n)
X						  (nth 1 inter)))))
X				(list
X				 (list 'calc-enter-result
X				       (if hasmulti 'n (nth 1 inter))
X				       (nth 2 inter)
X				       (if hasprefix
X					   (list 'append
X						 (list 'quote (list fname))
X						 (list 'calc-top-list-n
X						       (nth 1 inter))
X						 (list 'and
X						       'n
X						       (list
X							'list
X							(list
X							 'math-normalize
X							 (list
X							  'prefix-numeric-value
X							  'n)))))
X					 (list 'cons
X					       (list 'quote fname)
X					       (list 'calc-top-list-n
X						     (if hasmulti
X							 'n
X						       (nth 1 inter)))))))))))
X		  (append (list 'defun
X				(intern (concat "calc-" (symbol-name func)))
X				args)
X			  doc
X			  (list
X			   inter
X			   (cons 'calc-wrapper body))))))
X	  (append (list 'defun fname clargs)
X		  doc
X		  (math-do-arg-list-check args nil nil)
X		  body)))
X)
X
X(defun math-clean-arg (arg)
X  (if (consp arg)
X      (math-clean-arg (nth 1 arg))
X    arg)
X)
X
X(defun math-do-arg-check (arg var is-opt is-rest)
X  (if is-opt
X      (let ((chk (math-do-arg-check arg var nil nil)))
X	(list (cons 'and
X		    (cons var
X			  (if (cdr chk)
X			      (setq chk (list (cons 'progn chk)))
X			    chk)))))
X    (and (consp arg)
X	 (let* ((rest (math-do-arg-check (nth 1 arg) var is-opt is-rest))
X		(qual (car arg))
X		(qqual (list 'quote qual))
X		(qual-name (symbol-name qual))
X		(chk (intern (concat "math-check-" qual-name))))
X	   (if (fboundp chk)
X	       (append rest
X		       (list
X			(if is-rest
X			    (list 'setq var
X				  (list 'mapcar (list 'quote chk) var))
X			  (list 'setq var (list chk var)))))
X	     (if (fboundp (setq chk (intern (concat "math-" qual-name))))
X		 (append rest
X			 (list
X			  (if is-rest
X			      (list 'mapcar
X				    (list 'function
X					  (list 'lambda '(x)
X						(list 'or
X						      (list chk 'x)
X						      (list 'math-reject-arg
X							    'x qqual))))
X				    var)
X			    (list 'or
X				  (list chk var)
X				  (list 'math-reject-arg var qqual)))))
X	       (if (and (string-match "\\`not-\\(.*\\)\\'" qual-name)
X			(fboundp (setq chk (intern
X					    (concat "math-"
X						    (math-match-substring
X						     qual-name 1))))))
X		   (append rest
X			   (list
X			    (if is-rest
X				(list 'mapcar
X				      (list 'function
X					    (list 'lambda '(x)
X						  (list 'and
X							(list chk 'x)
X							(list 'math-reject-arg
X							      'x qqual))))
X				      var)
X			      (list 'and
X				    (list chk var)
X				    (list 'math-reject-arg var qqual)))))
X		 (error "Unknown qualifier `%s'" qual-name)))))))
X)
X
X(defun math-do-arg-list-check (args is-opt is-rest)
X  (cond ((null args) nil)
X	((consp (car args))
X	 (append (math-do-arg-check (car args)
X				    (math-clean-arg (car args))
X				    is-opt is-rest)
X		 (math-do-arg-list-check (cdr args) is-opt is-rest)))
X	((eq (car args) '&optional)
X	 (math-do-arg-list-check (cdr args) t nil))
X	((eq (car args) '&rest)
X	 (math-do-arg-list-check (cdr args) nil t))
X	(t (math-do-arg-list-check (cdr args) is-opt is-rest)))
X)
X
X(defconst math-prim-funcs
X  '( (~= . math-nearly-equal)
X     (% . math-mod)
X     (lsh . math-lshift-binary)
X     (ash . math-shift-binary)
X     (logand . math-and)
X     (logandc2 . math-diff)
X     (logior . math-or)
X     (logxor . math-xor)
X     (lognot . math-not)
X     (equal . equal)   ; need to leave these ones alone!
X     (eq . eq)
X     (and . and)
X     (or . or)
X     (if . if)
X     (^ . math-pow)
X     (expt . math-pow)
X   )
X)
X
X(defconst math-prim-vars
X  '( (nil . nil)
X     (t . t)
X     (&optional . &optional)
X     (&rest . &rest)
X   )
X)
X
X(defun math-define-function-body (body env)
X  (let ((body (math-define-body body env)))
X    (if (math-body-refers-to body 'math-return)
X	(list (cons 'catch (cons '(quote math-return) body)))
X      body))
X)
X
X(defun math-define-body (body exp-env)
X  (math-define-list body)
X)
X
X(defun math-define-list (body &optional quote)
X  (cond ((null body)
X	 nil)
X	((and (eq (car body) ':)
X	      (stringp (nth 1 body)))
X	 (cons (let* ((math-read-expr-quotes t)
X		      (calc-language nil)
X		      (math-expr-opers math-standard-opers)
X		      (exp (math-read-expr (nth 1 body))))
X		 (if (eq (car exp) 'error)
X		     (error "Bad format: %s" (nth 1 body))
X		   (math-define-exp exp)))
X	       (math-define-list (cdr (cdr body)))))
X	(quote
X	 (cons (cond ((consp (car body))
X		      (math-define-list (cdr body) t))
X		     (t
X		      (car body)))
X	       (math-define-list (cdr body))))
X	(t
X	 (cons (math-define-exp (car body))
X	       (math-define-list (cdr body)))))
X)
X
X(defun math-define-exp (exp)
X  (cond ((consp exp)
X	 (let ((func (car exp)))
X	   (cond ((memq func '(quote function))
X		  (if (and (consp (nth 1 exp))
X			   (eq (car (nth 1 exp)) 'lambda))
X		      (cons 'quote
X			    (math-define-lambda (nth 1 exp) exp-env))
X		    exp))
X		 ((memq func '(let let* for foreach))
X		  (let ((head (nth 1 exp))
X			(body (cdr (cdr exp))))
X		    (if (memq func '(let let*))
X			()
X		      (setq func (cdr (assq func '((for . math-for)
X						   (foreach . math-foreach)))))
X		      (if (not (listp (car head)))
X			  (setq head (list head))))
X		    (macroexpand
X		     (cons func
X			   (cons (math-define-let head)
X				 (math-define-body body
X						   (nconc
X						    (math-define-let-env head)
X						    exp-env)))))))
X		 ((and (memq func '(setq setf))
X		       (math-complicated-lhs (cdr exp)))
X		  (if (> (length exp) 3)
X		      (cons 'progn (math-define-setf-list (cdr exp)))
X		    (math-define-setf (nth 1 exp) (nth 2 exp))))
X		 ((eq func 'condition-case)
X		  (cons func
X			(cons (nth 1 exp)
X			      (math-define-body (cdr (cdr exp))
X						(cons (nth 1 exp)
X						      exp-env)))))
X		 ((eq func 'cond)
X		  (cons func
X			(math-define-cond (cdr exp))))
X		 ((and (consp func)   ; ('spam a b) == force use of plain spam
X		       (eq (car func) 'quote))
X		  (cons func (math-define-list (cdr exp))))
X		 ((symbolp func)
X		  (let ((args (math-define-list (cdr exp)))
X			(prim (assq func math-prim-funcs)))
X		    (cond (prim
X			   (cons (cdr prim) args))
X			  ((eq func 'floatp)
X			   (list 'eq (car args) '(quote float)))
X			  ((eq func '+)
X			   (math-define-binop 'math-add 0
X					      (car args) (cdr args)))
X			  ((eq func '-)
X			   (if (= (length args) 1)
X			       (cons 'math-neg args)
X			     (math-define-binop 'math-sub 0
X						(car args) (cdr args))))
X			  ((eq func '*)
X			   (math-define-binop 'math-mul 1
X					      (car args) (cdr args)))
X			  ((eq func '/)
X			   (math-define-binop 'math-div 1
X					      (car args) (cdr args)))
X			  ((eq func 'min)
X			   (math-define-binop 'math-min 0
X					      (car args) (cdr args)))
X			  ((eq func 'max)
X			   (math-define-binop 'math-max 0
X					      (car args) (cdr args)))
X			  ((eq func '<)
X			   (if (and (math-numberp (nth 1 args))
X				    (math-zerop (nth 1 args)))
X			       (list 'math-posp (car args))
X			     (cons 'math-lessp args)))
X			  ((eq func '>)
X			   (if (and (math-numberp (nth 1 args))
X				    (math-zerop (nth 1 args)))
X			       (list 'math-posp (car args))
X			     (list 'math-lessp (nth 1 args) (nth 0 args))))
X			  ((eq func '<=)
X			   (list 'not
X				 (if (and (math-numberp (nth 1 args))
X					  (math-zerop (nth 1 args)))
X				     (list 'math-posp (car args))
X				   (cons 'math-lessp args))))
X			  ((eq func '>=)
X			   (list 'not
X				 (if (and (math-numberp (nth 1 args))
X					  (math-zerop (nth 1 args)))
X				     (list 'math-negp (car args))
X				   (list 'math-lessp
X					 (nth 1 args) (nth 0 args)))))
X			  ((eq func '=)
X			   (if (and (math-numberp (nth 1 args))
X				    (math-zerop (nth 1 args)))
X			       (list 'math-zerop (nth 0 args))
X			     (if (and (integerp (nth 1 args))
X				      (/= (% (nth 1 args) 10) 0))
X				 (cons 'math-equal-int args)
X			       (cons 'math-equal args))))
X			  ((eq func '/=)
X			   (list 'not
X				 (if (and (math-numberp (nth 1 args))
X					  (math-zerop (nth 1 args)))
X				     (list 'math-zerop (nth 0 args))
X				   (if (and (integerp (nth 1 args))
X					    (/= (% (nth 1 args) 10) 0))
X				       (cons 'math-equal-int args)
X				     (cons 'math-equal args)))))
X			  ((eq func '1+)
X			   (list 'math-add (car args) 1))
X			  ((eq func '1-)
X			   (list 'math-add (car args) -1))
X			  ((eq func 'not)   ; optimize (not (not x)) => x
X			   (if (eq (car-safe args) func)
X			       (car (nth 1 args))
X			     (cons func args)))
X			  ((and (eq func 'elt) (cdr (cdr args)))
X			   (math-define-elt (car args) (cdr args)))
X			  (t
X			   (macroexpand
X			    (let* ((name (symbol-name func))
X				   (cfunc (intern (concat "calcFunc-" name)))
X				   (mfunc (intern (concat "math-" name))))
X			      (cond ((fboundp cfunc)
X				     (cons cfunc args))
X				    ((fboundp mfunc)
X				     (cons mfunc args))
X				    ((or (fboundp func)
X					 (string-match "\\`calcFunc-.*" name))
X				     (cons func args))
X				    (t
X				     (cons cfunc args)))))))))
X		 (t (cons func args)))))
X	((symbolp exp)
X	 (let ((prim (assq exp math-prim-vars))
X	       (name (symbol-name exp)))
X	   (cond (prim
X		  (cdr prim))
X		 ((memq exp exp-env)
X		  exp)
X		 ((string-match "-" name)
SHAR_EOF
echo "End of part 10"
echo "File calc-ext.el is continued in part 11"
echo "11" > s2_seq_.tmp
exit 0