[comp.sources.misc] v15i036: Patch for GNU Emacs Calc, version 1.04 -> 1.05, part 09/20

daveg@csvax.cs.caltech.edu (David Gillespie) (10/15/90)

Posting-number: Volume 15, Issue 36
Submitted-by: daveg@csvax.cs.caltech.edu (David Gillespie)
Archive-name: calc-1.05/part09

#!/bin/sh
# this is part 9 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file calc.patch 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
sed 's/^X//' << 'SHAR_EOF' >> calc.patch
X+       (math-bernoulli-number n)))
X+ )
X+ 
X+ (defun calcFunc-euler (n &optional x)
X+   (or (math-num-natnump n) (math-reject-arg n 'natnump))
X+   (if x
X+       (let* ((n1 (math-add n 1))
X+ 	     (coefs (math-bernoulli-coefs n1))
X+ 	     (fac (math-div (math-pow 2 n1) n1))
X+ 	     (k -1)
X+ 	     (x1 (math-div (math-add x 1) 2))
X+ 	     (x2 (math-div x 2)))
X+ 	(if (math-numberp x)
X+ 	    (if (and calc-symbolic-mode (math-floatp x))
X+ 		(math-inexact-result)
X+ 	      (math-mul fac
X+ 			(math-sub (math-build-polynomial-expr coefs x1)
X+ 				  (math-build-polynomial-expr coefs x2))))
X+ 	  (math-collect-terms
X+ 	   (math-reduce-vec
X+ 	    'math-add
X+ 	    (cons 'vec
X+ 		  (mapcar (function
X+ 			   (lambda (c)
X+ 			     (setq k (1+ k))
X+ 			     (math-mul (math-mul fac c)
X+ 				       (math-sub (math-pow x1 k)
X+ 						 (math-pow x2 k)))))
X+ 			  coefs)))
X+ 	   x)))
X+     (math-mul (math-pow 2 n)
X+ 	      (if (consp n)
X+ 		  (progn
X+ 		    (math-inexact-result)
X+ 		    (calcFunc-euler n '(float 5 -1)))
X+ 		(calcFunc-euler n '(frac 1 2)))))
X+ )
X+ 
X+ (defun math-bernoulli-coefs (n)
X+   (let* ((coefs (list (calcFunc-bern n)))
X+ 	 (nn (math-trunc n))
X+ 	 (k nn)
X+ 	 (term nn)
X+ 	 coef
X+ 	 (calc-prefer-frac (or (integerp n) calc-prefer-frac)))
X+     (while (>= (setq k (1- k)) 0)
X+       (setq term (math-div term (- nn k))
X+ 	    coef (math-mul term (math-bernoulli-number k))
X+ 	    coefs (cons (if (consp n) (math-float coef) coef) coefs)
X+ 	    term (math-mul term k)))
X+     (nreverse coefs))
X+ )
X+ 
X+ (defun math-bernoulli-number (n)
X+   (if (= (% n 2) 1)
X+       (if (= n 1)
X+ 	  '(frac -1 2)
X+ 	0)
X+     (setq n (/ n 2))
X+     (while (>= n math-bernoulli-cache-size)
X+       (let* ((sum 0)
X+ 	     (nk 1)     ; nk = n-k+1
X+ 	     (fact 1)   ; fact = (n-k+1)!
X+ 	     ofact
X+ 	     (p math-bernoulli-b-cache)
X+ 	     (calc-prefer-frac t))
X+ 	(math-working "bernoulli B" (* 2 math-bernoulli-cache-size))
X+ 	(while p
X+ 	  (setq nk (+ nk 2)
X+ 		ofact fact
X+ 		fact (math-mul fact (* nk (1- nk)))
X+ 		sum (math-add sum (math-div (car p) fact))
X+ 		p (cdr p)))
X+ 	(setq ofact (math-mul ofact (1- nk))
X+ 	      sum (math-sub (math-div '(frac 1 2) ofact) sum)
X+ 	      math-bernoulli-b-cache (cons sum math-bernoulli-b-cache)
X+ 	      math-bernoulli-B-cache (cons (math-mul sum ofact)
X+ 					   math-bernoulli-B-cache)
X+ 	      math-bernoulli-cache-size (1+ math-bernoulli-cache-size))))
X+     (nth (- math-bernoulli-cache-size n 1) math-bernoulli-B-cache))
X+ )
X+ 
X+ ;;;   Bn = n! bn
X+ ;;;   bn = - sum_k=0^n-1 bk / (n-k+1)!
X+ 
X+ ;;; A faster method would be to use "tangent numbers", c.f., Concrete
X+ ;;; Mathematics pg. 273.
X+ 
X+ (setq math-bernoulli-b-cache '( (frac -174611
X+ 				      (bigpos 0 200 291 698 662 857 802))
X+ 				(frac 43867 (bigpos 0 944 170 217 94 109 5))
X+ 				(frac -3617 (bigpos 0 880 842 622 670 10))
X+ 				(frac 1 (bigpos 600 249 724 74))
X+ 				(frac -691 (bigpos 0 368 674 307 1))
X+ 				(frac 1 (bigpos 160 900 47))
X+ 				(frac -1 (bigpos 600 209 1))
X+ 				(frac 1 30240) (frac -1 720)
X+ 				(frac 1 12) 1 ))
X+ 
X+ (setq math-bernoulli-B-cache '( (frac -174611 330) (frac 43867 798)
X+ 				(frac -3617 510) (frac 7 6) (frac -691 2730)
X+ 				(frac 5 66) (frac -1 30) (frac 1 42)
X+ 				(frac -1 30) (frac 1 6) 1 ))
X+ 
X+ (setq math-bernoulli-cache-size 11)
X+ 
X+ 
X+ 
X+ ;;; Probability distributions.
X+ 
X+ ;;; Binomial.
X+ (defun calcFunc-utpb (x n p)
X+   (calcFunc-betaI p x (math-add (math-sub n x) 1))
X+ )
X+ 
X+ (defun calcFunc-ltpb (x n p)
X+   (math-sub 1 (calcFunc-betaI p x (math-add (math-sub n x) 1)))
X+ )
X+ 
X+ ;;; Chi-square.
X+ (defun calcFunc-utpc (chisq v)
X+   (calcFunc-gammaQ (math-div v 2) (math-div chisq 2))
X+ )
X+ 
X+ (defun calcFunc-ltpc (chisq v)
X+   (calcFunc-gammaP (math-div v 2) (math-div chisq 2))
X+ )
X+ 
X+ ;;; F-distribution.
X+ (defun calcFunc-utpf (f v1 v2)
X+   (calcFunc-betaI (math-div v2 (math-add v2 (math-mul v1 f)))
X+ 		  (math-div v2 2)
X+ 		  (math-div v1 2))
X+ )
X+ 
X+ (defun calcFunc-ltpf (f v1 v2)
X+   (math-sub 1 (calcFunc-utpf f v1 v2))
X+ )
X+ 
X+ ;;; Normal.
X+ (defun calcFunc-utpn (x mean sdev)
X+   (math-mul (math-add '(float 1 0)
X+ 		      (calcFunc-erf (math-div (math-sub mean x)
X+ 					      (math-mul sdev (math-sqrt-2)))))
X+ 	    '(float 5 -1))
X+ )
X+ 
X+ (defun calcFunc-ltpn (x mean sdev)
X+   (math-mul (math-add '(float 1 0)
X+ 		      (calcFunc-erf (math-div (math-sub x mean)
X+ 					      (math-mul sdev (math-sqrt-2)))))
X+ 	    '(float 5 -1))
X+ )
X+ 
X+ ;;; Poisson.
X+ (fset 'calcFunc-utpp (symbol-function 'calcFunc-gammaP))
X+ (fset 'calcFunc-ltpp (symbol-function 'calcFunc-gammaQ))
X+ 
X+ ;;; Student's t.  (As defined in Abramowitz & Stegun and Numerical Recipes.)
X+ (defun calcFunc-utpt (tt v)
X+   (calcFunc-betaI (math-div v (math-add v (math-sqr tt)))
X+ 		  (math-div v 2)
X+ 		  '(float 5 -1))
X+ )
X+ 
X+ (defun calcFunc-ltpt (tt v)
X+   (math-sub 1 (calcFunc-utpt tt v))
X+ )
X+ 
X+ 
X+ 
X+ 
X  ;;;; [calc-arith.el]
X  
X  ;;;; Number theory.
X***************
X*** 10112,10134 ****
X  
X  (defun math-factorial (n)   ; [I I] [F F] [Public]
X    (let (temp)
X!     (cond ((Math-integer-negp n) (list 'calcFunc-fact n))
X! 	  ((Math-zerop n) 1)
X! 	  ((integerp n) (math-factorial-iter (1- n) 2 1))
X  	  ((and (math-messy-integerp n)
X  		(Math-lessp (setq temp (math-trunc n)) 100))
X! 	   (if (natnump temp)
X! 	       (math-with-extra-prec 1
X! 		 (math-factorial-iter (1- temp) 2 '(float 1 0)))
X! 	     (list 'calcFunc-fact max)))
X! 	  ((math-realp n)
X! 	   (math-with-extra-prec 3
X! 	     (math-gammap1-raw (math-float n))))
X! 	  (t (calc-record-why 'realp n)
X  	     (list 'calcFunc-fact n))))
X  )
X  (fset 'calcFunc-fact (symbol-function 'math-factorial))
X  
X  (defun math-factorial-iter (count n f)
X    (if (= (% n 5) 1)
X        (math-working (format "factorial(%d)" (1- n)) f))
X--- 15575,15636 ----
X  
X  (defun math-factorial (n)   ; [I I] [F F] [Public]
X    (let (temp)
X!     (cond ((Math-integer-negp n)
X! 	   (math-reject-arg n 'natnump))
X! 	  ((integerp n)
X! 	   (if (<= n 20)
X! 	       (aref '[1 1 2 6 24 120 720 5040 40320 362880
X! 			 (bigpos 800 628 3) (bigpos 800 916 39)
X! 			 (bigpos 600 1 479) (bigpos 800 20 227 6)
X! 			 (bigpos 200 291 178 87) (bigpos 0 368 674 307 1)
X! 			 (bigpos 0 888 789 922 20) (bigpos 0 96 428 687 355)
X! 			 (bigpos 0 728 705 373 402 6)
X! 			 (bigpos 0 832 408 100 645 121)
X! 			 (bigpos 0 640 176 8 902 432 2)] n)
X! 	     (math-factorial-iter (1- n) 2 1)))
X  	  ((and (math-messy-integerp n)
X  		(Math-lessp (setq temp (math-trunc n)) 100))
X! 	   (math-inexact-result)
X! 	   (if (>= temp 0)
X! 	       (if (<= temp 20)
X! 		   (math-float (math-factorial temp))
X! 		 (math-with-extra-prec 1
X! 		   (math-factorial-iter (1- temp) 2 '(float 1 0))))
X! 	     (math-reject-arg n 'natnump)))
X! 	  ((math-numberp n)
X! 	   (let* ((q (math-quarter-integer n))
X! 		  (tn (and q (math-floor n))))
X! 	     (if (and tn (>= (setq tn (1+ tn)) 0) (< tn 20))
X! 		 (if (= q 2)
X! 		     (math-div
X! 		      (math-mul (math-double-factorial-iter (* 2 tn) 3 1 2)
X! 				(if calc-symbolic-mode
X! 				    (list 'calcFunc-sqrt '(var pi var-pi))
X! 				  (math-sqrt-pi)))
X! 		      (math-pow 2 tn))
X! 		   (math-inexact-result)
X! 		   (math-div
X! 		    (math-mul (math-double-factorial-iter (* 4 tn) q 1 4)
X! 			      (if (= q 1) (math-gamma-1q) (math-gamma-3q)))
X! 		    (math-pow 4 tn)))
X! 	       (math-inexact-result)
X! 	       (math-with-extra-prec 3
X! 		 (math-gammap1-raw (math-float n)
X! 				   (math-float calc-internal-prec)
X! 				   (math-float (- calc-internal-prec)))))))
X! 	  (t (calc-record-why 'numberp n)
X  	     (list 'calcFunc-fact n))))
X  )
X  (fset 'calcFunc-fact (symbol-function 'math-factorial))
X  
X+ (math-defcache math-gamma-1q nil
X+   (math-with-extra-prec 3
X+     (math-gammap1-raw '(float -75 -2))))
X+ 
X+ (math-defcache math-gamma-3q nil
X+   (math-with-extra-prec 3
X+     (math-gammap1-raw '(float -25 -2))))
X+ 
X  (defun math-factorial-iter (count n f)
X    (if (= (% n 5) 1)
X        (math-working (format "factorial(%d)" (1- n)) f))
X***************
X*** 10137,10219 ****
X      f)
X  )
X  
X- (math-defcache math-sqrt-two-pi nil
X-   (math-sqrt (math-two-pi)))
X- 
X- (defun math-gammap1-raw (x)   ; compute gamma(1 + x)
X-   (cond ((math-lessp-float x '(float 1 1))
X- 	 (if (math-lessp-float x '(float -10 0))
X- 	     (setq x (math-neg-float
X- 		      (math-div-float
X- 		       (math-pi)
X- 		       (math-mul-float (math-gammap1-raw
X- 					(math-add-float (math-neg-float x)
X- 							'(float -1 0)))
X- 				       (math-sin-raw
X- 					(math-mul (math-pi) x)))))))
X- 	 (let ((xplus1 (math-add-float x '(float 1 0))))
X- 	   (math-div-float (math-gammap1-raw xplus1) xplus1)))
X- 	(t   ; x now >= 10.0
X- 	 (let ((xinv (math-div 1 x))
X- 	       (lnx (math-ln-raw x)))
X- 	   (math-mul (math-sqrt-two-pi)
X- 		     (math-exp-raw
X- 		      (math-gamma-series
X- 		       (math-sub (math-mul (math-add x '(float 5 -1))
X- 					   lnx)
X- 				 x)
X- 		       xinv
X- 		       (math-sqr xinv)
X- 		       2))))))
X- )
X- 
X- (defun calcFunc-gamma (x)
X-   (calcFunc-fact (math-add x -1))
X- )
X- 
X- (defun math-gamma-series (sum x xinvsqr n)
X-   (math-working "gamma" sum)
X-   (let* ((bn (math-bernoulli-number n))   ; this will always be a "frac" form.
X- 	 (next (math-add-float
X- 		sum
X- 		(math-mul-float (math-div-float (math-float (nth 1 bn))
X- 						(math-float (* (nth 2 bn)
X- 							       (* n (1- n)))))
X- 				x))))
X-     (if (math-nearly-equal-float sum next)
X- 	next
X-       (if (= n 24)
X- 	  (progn
X- 	    (calc-record-why "Gamma computation stopped early, not all digits may be valid")
X- 	    next)
X- 	(math-gamma-series next (math-mul-float x xinvsqr) xinvsqr (+ n 2)))))
X- )
X- 
X- (defun math-bernoulli-number (n)
X-   (if (= n 1)
X-       '(frac -1 2)
X-     (if (= (% n 2) 1)
X- 	0
X-       (aref '[ 1 (frac 1 6) (frac -1 30) (frac 1 42) (frac -1 30)
X- 	       (frac 5 66) (frac -691 2730) (frac 7 6) (frac -3617 510)
X- 	       (frac 43867 798) (frac -174611 330) (frac 854513 138)
X- 	       (frac (bigneg 91 364 236) 2730) ]
X- 	    (/ n 2))))
X- )
X- ;;; To come up with more, we could use this rule:
X- ;;;   Bn = n! bn
X- ;;;   bn = - sum_k=0^n-1 bk / (n-k+1)!
X- 
X  (defun math-double-factorial (n)   ; [I I] [F F] [Public]
X    (cond ((Math-integer-negp n) (list 'calcFunc-dfact n))
X  	((Math-zerop n) 1)
X! 	((integerp n) (math-double-factorial-iter n (+ 2 (% n 2)) 1))
X  	((math-messy-integerp n)
X  	 (let ((temp (math-trunc n)))
X  	   (if (natnump temp)
X! 	       (math-with-extra-prec 1
X! 		 (math-double-factorial-iter temp (+ 2 (% temp 2))
X! 					     '(float 1 0)))
X  	     (list 'calcFunc-dfact max))))
X  	(t (calc-record-why 'natnump n)
X  	   (list 'calcFunc-dfact n)))
X--- 15639,15662 ----
X      f)
X  )
X  
X  (defun math-double-factorial (n)   ; [I I] [F F] [Public]
X    (cond ((Math-integer-negp n) (list 'calcFunc-dfact n))
X  	((Math-zerop n) 1)
X! 	((integerp n) (math-double-factorial-iter n (+ 2 (% n 2)) 1 2))
X  	((math-messy-integerp n)
X  	 (let ((temp (math-trunc n)))
X+ 	   (math-inexact-result)
X  	   (if (natnump temp)
X! 	       (if (Math-lessp temp 200)
X! 		   (math-with-extra-prec 1
X! 		     (math-double-factorial-iter temp (+ 2 (% temp 2))
X! 						 '(float 1 0) 2))
X! 		 (let* ((half (math-div2 temp))
X! 			(even (math-mul (math-pow 2 half)
X! 					(math-factorial (math-float half)))))
X! 		   (if (math-evenp temp)
X! 		       even
X! 		     (math-div (math-factorial n) even))))
X  	     (list 'calcFunc-dfact max))))
X  	(t (calc-record-why 'natnump n)
X  	   (list 'calcFunc-dfact n)))
X***************
X*** 10220,10236 ****
X  )
X  (fset 'calcFunc-dfact (symbol-function 'math-double-factorial))
X  
X! (defun math-double-factorial-iter (max n f)
X!   (if (< (% n 10) 2)
X!       (math-working (format "dfact(%d)" (- n 2)) f))
X    (if (<= n max)
X!       (math-double-factorial-iter max (+ n 2) (math-mul n f))
X      f)
X  )
X  
X  (defun math-permutations (n m)   ; [I I I] [F F F] [Public]
X    (cond ((and (integerp n) (integerp m) (<= m n) (>= m 0))
X! 	 (math-factorial-iter n (1+ (- n m)) 1))
X  	((or (not (math-num-integerp n))
X  	     (not (math-num-integerp m)))
X  	 (or (math-realp n) (math-reject-arg n 'realp))
X--- 15663,15679 ----
X  )
X  (fset 'calcFunc-dfact (symbol-function 'math-double-factorial))
X  
X! (defun math-double-factorial-iter (max n f step)
X!   (if (< (% n 12) step)
X!       (math-working (format "dfact(%d)" (- n step)) f))
X    (if (<= n max)
X!       (math-double-factorial-iter max (+ n step) (math-mul n f) step)
X      f)
X  )
X  
X  (defun math-permutations (n m)   ; [I I I] [F F F] [Public]
X    (cond ((and (integerp n) (integerp m) (<= m n) (>= m 0))
X! 	 (math-factorial-iter m (1+ (- n m)) 1))
X  	((or (not (math-num-integerp n))
X  	     (not (math-num-integerp m)))
X  	 (or (math-realp n) (math-reject-arg n 'realp))
X***************
X*** 10237,10246 ****
X  	 (or (math-realp m) (math-reject-arg m 'realp))
X  	 (and (math-num-integerp n) (math-negp n) (math-reject-arg n 'range))
X  	 (and (math-num-integerp m) (math-negp m) (math-reject-arg m 'range))
X! 	 (math-div (math-factorial n) (math-factorial m)))
X  	(t
X  	 (let ((tn (math-trunc n))
X  	       (tm (math-trunc m)))
X  	   (or (integerp tn) (math-reject-arg tn 'fixnump))
X  	   (or (integerp tm) (math-reject-arg tm 'fixnump))
X  	   (or (and (<= tm tn) (>= tm 0)) (math-reject-arg tm 'range))
X--- 15680,15690 ----
X  	 (or (math-realp m) (math-reject-arg m 'realp))
X  	 (and (math-num-integerp n) (math-negp n) (math-reject-arg n 'range))
X  	 (and (math-num-integerp m) (math-negp m) (math-reject-arg m 'range))
X! 	 (math-div (math-factorial n) (math-factorial (math-sub n m))))
X  	(t
X  	 (let ((tn (math-trunc n))
X  	       (tm (math-trunc m)))
X+ 	   (math-inexact-result)
X  	   (or (integerp tn) (math-reject-arg tn 'fixnump))
X  	   (or (integerp tm) (math-reject-arg tm 'fixnump))
X  	   (or (and (<= tm tn) (>= tm 0)) (math-reject-arg tm 'range))
X***************
X*** 10274,10279 ****
X--- 15718,15724 ----
X  	      (Math-lessp n m))
X  	 0)
X  	(t
X+ 	 (math-inexact-result)
X  	 (let ((tm (math-trunc m)))
X  	   (or (integerp tm) (math-reject-arg tm 'fixnump))
X  	   (if (> tm 100)
X***************
X*** 10282,10288 ****
X  				   (math-factorial (math-float
X  						    (math-sub n m)))))
X  	     (math-with-extra-prec 1
X! 	       (math-choose-float-iter tm n 1 '(float 1 0)))))))
X  )
X  (fset 'calcFunc-choose (symbol-function 'math-choose))
X  
X--- 15727,15733 ----
X  				   (math-factorial (math-float
X  						    (math-sub n m)))))
X  	     (math-with-extra-prec 1
X! 	       (math-choose-float-iter tm n 1 1))))))
X  )
X  (fset 'calcFunc-choose (symbol-function 'math-choose))
X  
X***************
X*** 10305,10310 ****
X--- 15750,15805 ----
X  )
X  
X  
X+ ;;; Stirling numbers.
X+ 
X+ (defun calcFunc-stir1 (n m)
X+   (math-stirling-number n m 1)
X+ )
X+ 
X+ (defun calcFunc-stir2 (n m)
X+   (math-stirling-number n m 0)
X+ )
X+ 
X+ (defun math-stirling-number (n m k)
X+   (or (math-num-natnump n) (math-reject-arg n 'natnump))
X+   (or (math-num-natnump m) (math-reject-arg m 'natnump))
X+   (if (consp n) (setq n (math-trunc n)))
X+   (or (integerp n) (math-reject-arg n 'fixnump))
X+   (if (consp m) (setq m (math-trunc m)))
X+   (or (integerp m) (math-reject-arg m 'fixnump))
X+   (if (< n m)
X+       0
X+     (let ((cache (aref math-stirling-cache k)))
X+       (while (<= (length cache) n)
X+ 	(let ((i (1- (length cache)))
X+ 	      row)
X+ 	  (setq cache (vconcat cache (make-vector (length cache) nil)))
X+ 	  (aset math-stirling-cache k cache)
X+ 	  (while (< (setq i (1+ i)) (length cache))
X+ 	    (aset cache i (setq row (make-vector (1+ i) nil)))
X+ 	    (aset row 0 0)
X+ 	    (aset row i 1))))
X+       (if (= k 1)
X+ 	  (math-stirling-1 n m)
X+ 	(math-stirling-2 n m))))
X+ )
X+ (setq math-stirling-cache (vector [[1]] [[1]]))
X+ 
X+ (defun math-stirling-1 (n m)
X+   (or (aref (aref cache n) m)
X+       (aset (aref cache n) m
X+ 	    (math-add (math-stirling-1 (1- n) (1- m))
X+ 		      (math-mul (- 1 n) (math-stirling-1 (1- n) m)))))
X+ )
X+ 
X+ (defun math-stirling-2 (n m)
X+   (or (aref (aref cache n) m)
X+       (aset (aref cache n) m
X+ 	    (math-add (math-stirling-2 (1- n) (1- m))
X+ 		      (math-mul m (math-stirling-2 (1- n) m)))))
X+ )
X+ 
X+ 
X  ;;; Produce a random digit in the range 0..999.
X  ;;; Avoid various pitfalls that may lurk in the built-in (random) function!
X  (defun math-random-digit ()
X***************
X*** 10386,10395 ****
X--- 15881,15979 ----
X  	     (if (Math-lessp lo hi)
X  		 (math-add (math-random (math-sub hi lo)) lo)
X  	       (math-reject-arg max "Empty interval")))))
X+ 	((eq (car max) 'vec)
X+ 	 (if (cdr max)
X+ 	     (nth (1+ (math-random (1- (length max)))) max)
X+ 	   (math-reject-arg max "Empty list")))
X+ 	((and (eq (car max) 'sdev) (math-constp max))
X+ 	 (math-add (math-mul (math-gaussian-float) (nth 2 max)) (nth 1 max)))
X  	(t (math-reject-arg max 'realp)))
X  )
X  (fset 'calcFunc-random (symbol-function 'math-random))
X  
X+ ;;; Choose N objects at random from the set MAX without duplicates.
X+ (defun math-shuffle (n max)
X+   (or (and (Math-num-integerp n)
X+ 	   (or (natnump (setq n (math-trunc n))) (eq n -1)))
X+       (math-reject-arg n 'integerp))
X+   (cond ((or (math-zerop max)
X+ 	     (math-floatp max)
X+ 	     (eq (car-safe max) 'sdev))
X+ 	 (if (< n 0)
X+ 	     (math-reject-arg n 'natnump)
X+ 	   (math-simple-shuffle n max)))
X+ 	((and (<= n 1) (>= n 0))
X+ 	 (math-simple-shuffle n max))
X+ 	((eq (car-safe max) 'intv)
X+ 	 (let ((num (math-add (math-sub (nth 3 max) (nth 2 max))
X+ 			      (cdr (assq (nth 1 max)
X+ 					 '((0 . -1) (1 . 0)
X+ 					   (2 . 0) (3 . 1))))))
X+ 	       (min (math-add (nth 2 max) (if (memq (nth 1 max) '(0 1))
X+ 					      1 0))))
X+ 	   (if (< n 0) (setq n num))
X+ 	   (or (math-posp num) (math-reject-arg max 'range))
X+ 	   (and (math-lessp num n) (math-reject-arg n 'range))
X+ 	   (if (math-lessp n (math-quotient num 3))
X+ 	       (math-simple-shuffle n max)
X+ 	     (if (> (* n 4) (* num 3))
X+ 		 (math-add (math-sub min 1)
X+ 			   (math-shuffle-list n num (math-vec-index num)))
X+ 	       (let ((tot 0)
X+ 		     (m 0)
X+ 		     (vec nil))
X+ 		 (while (< m n)
X+ 		   (if (< (math-random (- num tot)) (- n m))
X+ 		       (setq vec (cons (math-add min tot) vec)
X+ 			     m (1+ m)))
X+ 		   (setq tot (1+ tot)))
X+ 		 (math-shuffle-list n n (cons 'vec vec)))))))
X+ 	((eq (car-safe max) 'vec)
X+ 	 (let ((size (1- (length max))))
X+ 	   (if (< n 0) (setq n size))
X+ 	   (if (and (> n (/ size 2)) (<= n size))
X+ 	       (math-shuffle-list n size (copy-sequence max))
X+ 	     (let* ((vals (math-shuffle n (list 'intv 3 1 (1- (length max)))))
X+ 		    (p vals))
X+ 	       (while (setq p (cdr p))
X+ 		 (setcar p (nth (car p) max)))
X+ 	       vals))))
X+ 	((math-integerp max)
X+ 	 (if (math-posp max)
X+ 	     (math-shuffle n (list 'intv 2 0 max))
X+ 	   (math-shuffle n (list 'intv 1 max 0))))
X+ 	(t (math-reject-arg max 'realp)))
X+ )
X+ (fset 'calcFunc-shuffle (symbol-function 'math-shuffle))
X+ 
X+ (defun math-simple-shuffle (n max)
X+   (let ((vec nil)
X+ 	val)
X+     (while (>= (setq n (1- n)) 0)
X+       (while (math-member (setq val (math-random max)) vec))
X+       (setq vec (cons val vec)))
X+     (cons 'vec vec))
X+ )
X+ 
X+ (defun math-shuffle-list (n size vec)
X+   (let ((j size)
X+ 	k temp
X+ 	(p vec))
X+     (while (cdr (setq p (cdr p)))
X+       (setq k (math-random j)
X+ 	    j (1- j)
X+ 	    temp (nth k p))
X+       (setcar (nthcdr k p) (car p))
X+       (setcar p temp))
X+     (cons 'vec (nthcdr (- size n -1) vec)))
X+ )
X+ 
X+ (defun math-member (x list)
X+   (while (and list (not (equal x (car list))))
X+     (setq list (cdr list)))
X+   list
X+ )
X+ 
X  
X  ;;; Check if the integer N is prime.  [X I]
X  ;;; Return (nil) if non-prime,
X***************
X*** 10484,10489 ****
X--- 16068,16081 ----
X  )
X  (defvar math-prime-test-cache '(-1))
X  
X+ (defun calcFunc-prime (n &optional iters)
X+   (or (math-num-integerp n) (math-reject-arg 'integerp n))
X+   (or (not iters) (math-num-integerp iters) (math-reject-arg 'integerp iters))
X+   (if (car (math-prime-test (math-trunc n) (math-trunc (or iters 1))))
X+       1
X+     0)
X+ )
X+ 
X  ;;; Theory: summing base-10^6 digits modulo 111111 is "casting out 999999s".
X  ;;; Initial probability that N is prime is 1/ln(N) = log10(e)/log10(N).
X  ;;; After culling [2,3,5,7,11,13,37], probability of primality is 5.36 x more.
X***************
X*** 10572,10578 ****
X  (fset 'calcFunc-moebius (symbol-function 'math-moebius))
X  
X  
X! (defun math-next-prime (n iters)
X    (if (Math-integerp n)
X        (if (Math-integer-negp n)
X  	  2
X--- 16164,16170 ----
X  (fset 'calcFunc-moebius (symbol-function 'math-moebius))
X  
X  
X! (defun math-next-prime (n &optional iters)
X    (if (Math-integerp n)
X        (if (Math-integer-negp n)
X  	  2
X***************
X*** 10582,10588 ****
X  	      (setq n (math-add n -1)))
X  	  (let (res)
X  	    (while (not (car (setq res (math-prime-test
X! 					(setq n (math-add n 2)) iters)))))
X  	    (if (and calc-verbose-nextprime
X  		     (eq (car res) 'maybe))
X  		(calc-report-prime-test res)))
X--- 16174,16181 ----
X  	      (setq n (math-add n -1)))
X  	  (let (res)
X  	    (while (not (car (setq res (math-prime-test
X! 					(setq n (math-add n 2))
X! 					(or iters 1))))))
X  	    (if (and calc-verbose-nextprime
X  		     (eq (car res) 'maybe))
X  		(calc-report-prime-test res)))
X***************
X*** 10594,10600 ****
X  (fset 'calcFunc-nextprime (symbol-function 'math-next-prime))
X  (setq calc-verbose-nextprime nil)
X  
X! (defun math-prev-prime (n iters)
X    (if (Math-integerp n)
X        (if (Math-lessp n 4)
X  	  2
X--- 16187,16193 ----
X  (fset 'calcFunc-nextprime (symbol-function 'math-next-prime))
X  (setq calc-verbose-nextprime nil)
X  
X! (defun math-prev-prime (n &optional iters)
X    (if (Math-integerp n)
X        (if (Math-lessp n 4)
X  	  2
X***************
X*** 10602,10608 ****
X  	    (setq n (math-add n 1)))
X  	(let (res)
X  	  (while (not (car (setq res (math-prime-test
X! 				      (setq n (math-add n -2)) iters)))))
X  	  (if (and calc-verbose-nextprime
X  		   (eq (car res) 'maybe))
X  	      (calc-report-prime-test res)))
X--- 16195,16202 ----
X  	    (setq n (math-add n 1)))
X  	(let (res)
X  	  (while (not (car (setq res (math-prime-test
X! 				      (setq n (math-add n -2))
X! 				      (or iters 1))))))
X  	  (if (and calc-verbose-nextprime
X  		   (eq (car res) 'maybe))
X  	      (calc-report-prime-test res)))
X***************
X*** 11018,11025 ****
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--- 16612,16618 ----
X        (setq x (cons (car x)
X  		    (mapcar 'math-evaluate-expr-rec (cdr x)))))
X    (if (eq (car-safe x) 'var)
X!       (if (and (calc-var-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***************
X*** 11037,11042 ****
X--- 16630,16637 ----
X  )
X  
X  
X+ ;;;; [calc-arith.el]
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***************
X*** 11143,11148 ****
X--- 16738,16745 ----
X  )
X  
X  
X+ ;;;; [calc-alg.el]
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***************
X*** 11172,11180 ****
X  )
X  
X  
X- 
X- ;;;; [calc-alg.el]
X- 
X  (setq math-living-dangerously nil)   ; true if unsafe simplifications are okay.
X  
X  (defun math-simplify-extended (a)
X--- 16769,16774 ----
X***************
X*** 11181,11186 ****
X--- 16775,16781 ----
X    (let ((math-living-dangerously t))
X      (math-simplify a))
X  )
X+ (fset 'calcFunc-esimplify (symbol-function 'math-simplify-extended))
X  
X  (defun math-simplify (top-expr)
X    (calc-with-default-simplification
X***************
X*** 11191,11196 ****
X--- 16786,16792 ----
X         (setq top-expr res))))
X    top-expr
X  )
X+ (fset 'calcFunc-simplify (symbol-function 'math-simplify))
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***************
X*** 11309,11356 ****
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--- 16905,16981 ----
X  
X  (defun math-simplify-divide ()
X    (let ((np (cdr expr))
X! 	(nover nil)
X! 	(nn (math-common-constant-factor (nth 2 expr)))
X! 	n op)
X      (if nn
X  	(progn
X  	  (setq n (math-common-constant-factor (nth 1 expr)))
X! 	  (if (and (eq (car-safe nn) 'frac) (eq (nth 1 nn) 1) (not n))
X  	      (progn
X! 		(setcar (cdr expr) (math-mul (nth 2 nn) (nth 1 expr)))
X  		(setcar (cdr (cdr expr))
X! 			(math-cancel-common-factor (nth 2 expr) nn))
X! 		(if (and (math-negp nn)
X! 			 (setq op (assq (car expr) calc-tweak-eqn-table)))
X! 		    (setcar expr (nth 1 op))))
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! 		  (if (and (math-negp n)
X! 			   (setq op (assq (car expr) calc-tweak-eqn-table)))
X! 		      (setcar expr (nth 1 op))))))))
X!     (if (eq (car-safe (car np)) '/)
X! 	(progn
X! 	  (setq np (cdr (nth 1 expr)))
X! 	  (while (eq (car-safe (setq n (car np))) '*)
X! 	    (math-simplify-divisor (cdr n) (cdr (cdr expr)) nil t)
X! 	    (setq np (cdr (cdr n))))
X! 	  (math-simplify-divisor np (cdr (cdr expr)) nil t)
X! 	  (setq nover t
X! 		np (cdr (cdr (nth 1 expr))))))
X      (while (eq (car-safe (setq n (car np))) '*)
X!       (math-simplify-divisor (cdr n) (cdr (cdr expr)) nover t)
X        (setq np (cdr (cdr n))))
X!     (math-simplify-divisor np (cdr (cdr expr)) nover t)
X      expr)
X  )
X  
X! (defun math-simplify-divisor (np dp nover dover)
X!   (cond ((eq (car-safe (car dp)) '/)
X! 	 (math-simplify-divisor np (cdr (car dp)) nover dover)
X! 	 (math-simplify-divisor np (cdr (cdr (car dp))) nover (not dover)))
X! 	((or (or (eq (car expr) '/)
X! 		 (and (memq (car expr) '(calcFunc-eq calcFunc-neq))
X! 		      math-living-dangerously))
X! 	     (math-numberp (car np)))
X! 	 (let ((n (car np))
X! 	       d dd temp op)
X! 	   (while (eq (car-safe (setq d (car dp))) '*)
X! 	     (if (setq temp (math-combine-prod n (nth 1 d) nover dover t))
X! 		 (progn
X! 		   (and (math-negp (nth 1 d))
X! 			(setq op (assq (car expr) calc-tweak-eqn-table))
X! 			(setcar expr (nth 1 op)))
X! 		   (setcar np (setq n (if nover (math-div 1 temp) temp)))
X! 		   (setcar (cdr d) 1)))
X! 	     (setq dp (cdr (cdr d))))
X! 	   (if (setq temp (math-combine-prod n d nover dover t))
X! 	       (progn
X! 		 (and (math-negp (car dp))
X! 		      (setq op (assq (car expr) calc-tweak-eqn-table))
X! 		      (setcar expr (nth 1 op)))
X! 		 (setcar np (setq n (if nover (math-div 1 temp) 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 -1)))
X  	       (math-abs expr))
X  	(if (Math-ratp (setq expr (math-to-simple-fraction expr)))
X  	    (math-common-constant-factor expr)))
X***************
X*** 11374,11388 ****
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--- 16999,17055 ----
X  )
X  
X  (defun math-frac-gcd (a b)
X!   (if (or (and (Math-integerp a)
X! 	       (Math-integerp b))
X! 	  (Math-zerop a)
X! 	  (Math-zerop b))
X        (math-gcd a b)
X!     (and (Math-integerp a) (setq a (list 'frac a 1)))
X!     (and (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-eq calcFunc-neq calcFunc-lt
X+ 			       calcFunc-gt calcFunc-leq calcFunc-geq)
X+   (math-simplify-ineq))
X+ 
X+ (defun math-simplify-ineq ()
X+   (math-simplify-divide)
X+   (let ((np (cdr expr)))
X+     (while (memq (car-safe (setq n (car np))) '(+ -))
X+       (math-simplify-add-term (cdr (cdr n)) (cdr (cdr expr)) (eq (car n) '-))
X+       (setq np (cdr n)))
X+     (math-simplify-add-term np (cdr (cdr expr)) nil)
X+     expr)
X+ )
X+ 
X+ (defun math-simplify-add-term (np dp minus)
X+   (let ((n (car np))
X+ 	d dd temp)
X+     (while (memq (car-safe (setq d (car dp))) '(+ -))
X+       (if (setq temp (math-combine-sum n (nth 2 d)
X+ 				       minus (eq (car d) '+) t))
X+ 	  (if (eq (math-looks-negp temp) minus)
X+ 	      (progn
X+ 		(setcar np (setq n (if minus (math-neg temp) temp)))
X+ 		(setcar (cdr (cdr d)) 0))
X+ 	    (progn
X+ 	      (setcar np 0)
X+ 	      (setcar (cdr (cdr d)) (setq n (if (eq (car d) '+)
X+ 						(math-neg temp)
X+ 					      temp))))))
X+       (setq dp (cdr d)))
X+     (if (setq temp (math-combine-sum n d minus t t))
X+ 	(if (eq (math-looks-negp temp) minus)
X+ 	    (progn
X+ 	      (setcar np (setq n (if minus (math-neg temp) temp)))
X+ 	      (setcar dp 0))
X+ 	  (progn
X+ 	    (setcar np 0)
X+ 	    (setcar dp (setq n (math-neg temp)))))))
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***************
X*** 11453,11459 ****
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--- 17120,17126 ----
X  	   (nth 1 (nth 1 expr)))
X        (and math-living-dangerously
X  	   (eq (car-safe (nth 1 expr)) 'calcFunc-cos)
X! 	   (math-sub (math-quarter-circle t)
X  		     (nth 1 (nth 1 expr)))))
X  )
X  
X***************
X*** 11463,11469 ****
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--- 17130,17136 ----
X  	   (nth 1 (nth 1 expr)))
X        (and math-living-dangerously
X  	   (eq (car-safe (nth 1 expr)) 'calcFunc-sin)
X! 	   (math-sub (math-quarter-circle t)
X  		     (nth 1 (nth 1 expr)))))
X  )
X  
X***************
X*** 11518,11535 ****
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--- 17185,17202 ----
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***************
X*** 11550,11556 ****
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--- 17217,17223 ----
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***************
X*** 11622,11714 ****
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  ;;;; [calc-ext.el]
X  
X  (defun math-is-true (expr)
X    (and (Math-realp expr)
X         (not (Math-zerop expr)))
X  )
X  
X  
X  
X  
X--- 17289,18634 ----
X  
X  
X  
X! ;;;; [calc-rewr.el]
X! 
X  
X  (defun math-rewrite (expr rules &optional many)
X!   (let ((crules (math-compile-rewrites rules))
X! 	(heads (math-rewrite-heads expr))
X! 	result)
X!     (math-map-tree (function
X! 		    (lambda (x)
X! 		      (if (setq result (math-apply-rewrites x crules heads))
X! 			  (setq heads (math-rewrite-heads result heads)))
X! 		      result))
X! 		   expr many))
X! )
X! 
X! (defun calcFunc-rewrite (expr rules &optional many)
X!   (or (null many) (integerp many) (math-reject-arg 'integerp many))
X!   (condition-case err
X!       (math-rewrite expr rules (or many 1))
X!     (error (math-reject-arg rules (nth 1 err))))
X! )
X! 
X! (defun calcFunc-match (pat vec)
X!   (or (math-vectorp vec) (math-reject-arg vec 'vectorp))
X!   (condition-case err
X!       (math-match-patterns pat vec nil)
X!     (error (math-reject-arg pat (nth 1 err))))
X! )
X! 
X! (defun calcFunc-matchnot (pat vec)
X!   (or (math-vectorp vec) (math-reject-arg vec 'vectorp))
X!   (condition-case err
X!       (math-match-patterns pat vec t)
X!     (error (math-reject-arg pat (nth 1 err))))
X! )
X! 
X! (defun math-match-patterns (pat vec &optional not-flag)
X!   (let ((newvec nil)
X! 	(crules (math-compile-patterns pat)))
X!     (while (setq vec (cdr vec))
X!       (if (eq (not (math-apply-rewrites (car vec) crules))
X! 	      not-flag)
X! 	  (setq newvec (cons (car vec) newvec))))
X!     (cons 'vec (nreverse newvec)))
X! )
X! 
X! 
X! 
X! ;;; A compiled rule set is an a-list of entries whose cars are functors,
X! ;;; and whose cdrs are lists of rules.  If there are rules with no
X! ;;; well-defined head functor, they are included on all lists and also
X! ;;; on an extra list whose car is nil.
X! ;;;
X! ;;; Rule list entries take the form (regs prog head), where:
X! ;;;
X! ;;;   regs   is a vector of match registers.
X! ;;;
X! ;;;   prog   is a match program (see below).
X! ;;;
X! ;;;   head   is a rare function name appearing in the rule body (but not the
X! ;;;	     head of the whole rule), or nil if none.
X! ;;;
X! ;;; A match program is a list of match instructions.
X! ;;;
X! ;;; In the following, "part" is a register number that contains the
X! ;;; subexpression to be operated on.
X! ;;;
X! ;;; Register 0 is the whole expression being matched.  The others are
X! ;;; meta-variables in the pattern, temporaries used for matching and
X! ;;; backtracking, and constant expressions.
X! ;;;
X! ;;; (same part reg)
X! ;;;         The selected part must be math-equal to the contents of "reg".
X! ;;;
X! ;;; (same-neg part reg)
X! ;;;         The selected part must be math-equal to the negative of "reg".
X! ;;;
X! ;;; (integer part)
X! ;;;         The selected part must be an integer.
X! ;;;
X! ;;; (real part)
X! ;;;         The selected part must be a real.
X! ;;;
X! ;;; (constant part)
X! ;;;         The selected part must be a constant.
X! ;;;
X! ;;; (negative part)
X! ;;;	    The selected part must "look" negative.
X! ;;;
X! ;;; (rel part op reg)
X! ;;;         The selected part must satisfy "part op reg", where "op"
X! ;;;	    is one of the 6 relational ops, and "reg" is a register.
X! ;;;
X! ;;; (mod part modulo value)
X! ;;;         The selected part must satisfy "part % modulo = value", where
X! ;;;         "modulo" and "value" are constants.
X! ;;;
X! ;;; (func part head reg1 reg2 ... regn)
X! ;;;         The selected part must be an n-ary call to function "head".
X! ;;;         The arguments are stored in "reg1" through "regn".
X! ;;;
X! ;;; (func-def part head defs reg1 reg2 ... regn)
X! ;;;	    The selected part must be an n-ary call to function "head".
X! ;;;	    "Defs" is a list of value/register number pairs for default args.
X! ;;;	    If a match, assign default values to registers and then skip
X! ;;;	    immediately over any following "func-def" instructions and
X! ;;;	    the following "func" instruction.  If wrong number of arguments,
X! ;;;	    proceed to the following "func-def" or "func" instruction.
X! ;;;
X! ;;; (func-opt part head defs reg1)
X! ;;;	    Like func-def with "n=1", except that if the selected part is
X! ;;;	    not a call to "head", then the part itself successfully matches
X! ;;;	    "reg1" (and the defaults are assigned).
X! ;;;
X! ;;; (try part heads mark reg1 [def])
X! ;;;         The selected part must be a function of the correct type which is
X! ;;;         associative and/or commutative.  "Heads" is a list of acceptable
X! ;;;         types.  An initial assignment of arguments to "reg1" is tried.
X! ;;;	    If the program later fails, it backtracks to this instruction
X! ;;;	    and tries other assignments of arguments to "reg1".
X! ;;;	    If "def" exists and normal matching fails, backtrack and assign
X! ;;;	    "part" to "reg1", and "def" to "reg2" in the following "try2".
X! ;;;	    The "mark" is a vector of size 4; only "mark[3]" is initialized.
X! ;;;	    "mark[0]" points to the argument list; "mark[1]" points to the
X! ;;;	    current argument; "mark[2]" is 0 if there are two arguments,
X! ;;;	    1 if reg1 is matching single arguments, 2 if reg2 is matching
X! ;;;	    single arguments (a+b+c+d is never split as (a+b)+(c+d)), or
X! ;;;         3 if reg2 is matching "def"; "mark[3]" is 0 if the function must
X! ;;;	    have two arguments, 1 if phase-2 can be skipped, 2 if full
X! ;;;	    backtracking is necessary.
X! ;;;
X! ;;; (try2 try reg2)
X! ;;;         Every "try" will be followed by a "try2" whose "try" field is
X! ;;;	    a pointer to the corresponding "try".  The arguments which were
X! ;;;	    not stored in "reg1" by that "try" are now stored in "reg2".
X! ;;;
X! ;;; (apply part reg1 reg2)
X! ;;;         The selected part must be a function call.  The functor
X! ;;;	    (as a variable name) is stored in "reg1"; the arguments
X! ;;;	    (as a vector) are stored in "reg2".
X! ;;;
X! ;;; (cons part reg1 reg2)
X! ;;;	    The selected part must be a vector.  The first element of
X! ;;;	    the vector is stored in "reg1"; the rest of the vector
X! ;;;	    (as another vector) is stored in "reg2".
X! ;;;
X! ;;; (select part reg)
X! ;;;         If the selected part is a unary call to function "select", its
X! ;;;         argument is stored in "reg"; otherwise (provided this is an `a r'
X! ;;;         and not a `g r' command) the selected part is stored in "reg".
X! ;;;
X! ;;; (cond expr)
X! ;;;         The "expr", with registers substituted, must simplify to
X! ;;;         a non-zero value.
X! ;;;
X! ;;; (done rhs)
X! ;;;         Rewrite the expression to "rhs", with register substituted.
X! ;;;	    Normalize; if the result is different from the original
X! ;;;	    expression, the match has succeeded.  This is the last
X! ;;;	    instruction of every program.
X! ;;;
X! 
X! ;;; Pseudo-functions related to rewrites:
X! ;;;  In patterns:  quote, plain, condition, opt, apply, cons, select
X! ;;;  In righthand sides:  quote, plain, eval, evalsimp, apply, cons, select
X! 
X! ;;; Some optimizations that would be nice to have:
X! ;;;
X! ;;;  * Merge registers with disjoint lifetimes.
X! ;;;  * Merge constant registers with equivalent values.
X! ;;;
X! ;;;  * If an argument of a commutative op math-depends neither on the
X! ;;;    rest of the pattern nor on any of the conditions, then no backtracking
X! ;;;    should be done for that argument.  (This won't apply to very many
X! ;;;    cases.)
X! ;;;
X! ;;;  * If top functor is "select", and its argument is a unique function,
X! ;;;    add the rule to the lists for both "select" and that function.
X! ;;;    (Currently rules like this go on the "nil" list.)
X! ;;;    Same for "func-opt" functions.  (Though not urgent for these.)
X! ;;;
X! 
X! ;;; Some additional features to add / things to think about:
X! ;;;
X! ;;;  * Figure out what happens to "a +/- b" and "a +/- opt(b)".
X! ;;;
X! ;;;  * Same for interval forms.
X! ;;;
X! ;;;  * Have a name(v,pat) pattern which matches pat, and gives the
X! ;;;    whole match the name v.  Beware of circular structures!
X! ;;;
X! 
X! (defun math-compile-patterns (pats)
X!   (if (and (eq (car-safe pats) 'var)
X! 	   (calc-var-value (nth 2 pats)))
X!       (let ((prop (get (nth 2 pats) 'math-pattern-cache)))
X! 	(or prop
X! 	    (put (nth 2 pats) 'math-pattern-cache (setq prop (list nil))))
X! 	(or (eq (car prop) (symbol-value (nth 2 pats)))
X! 	    (progn
X! 	      (setcdr prop (math-compile-patterns
X! 			    (symbol-value (nth 2 pats))))
X! 	      (setcar prop (symbol-value (nth 2 pats)))))
X! 	(cdr prop))
X!     (let ((math-rewrite-whole t))
X!       (math-compile-rewrites (cons
X! 			      'vec
X! 			      (mapcar (function (lambda (x)
X! 						  (list 'vec x
X! 							'(var XXX XXX))))
X! 				      (if (eq (car-safe pats) 'vec)
X! 					  (cdr pats)
X! 					(list pats)))))))
X  )
X+ (setq math-rewrite-whole nil)
X+ (setq math-make-import-list nil)
X  
X! (defun math-compile-rewrites (rules)
X    (if (and (eq (car-safe rules) 'var)
X! 	   (calc-var-value (nth 2 rules)))
X!       (let ((prop (get (nth 2 rules) 'math-rewrite-cache))
X! 	    (math-import-list nil)
X! 	    (math-make-import-list t)
X! 	    p)
X! 	(or prop
X! 	    (put (nth 2 rules) 'math-rewrite-cache
X! 		 (setq prop (list (list (cons (nth 2 rules) nil))))))
X! 	(setq p (car prop))
X! 	(while (and p (eq (symbol-value (car (car p))) (cdr (car p))))
X! 	  (setq p (cdr p)))
X! 	(or (null p)
X! 	    (progn
X! 	      (message "Compiling rule set %s..." (nth 1 rules))
X! 	      (setcdr prop (math-compile-rewrites
X! 			    (symbol-value (nth 2 rules))))
X! 	      (message "Compiling rule set %s...done" (nth 1 rules))
X! 	      (setcar prop (cons (cons (nth 2 rules)
X! 				       (symbol-value (nth 2 rules)))
X! 				 math-import-list))))
X! 	(cdr prop))
X!     (or (eq (car-safe rules) 'vec)
X! 	(error "Rewrite rules must be a vector"))
X!     (if (assq 'calcFunc-import rules)
X! 	(let ((pp (setq rules (copy-sequence rules)))
X! 	      p part)
X! 	  (while (setq p (car (cdr pp)))
X! 	    (if (eq (car-safe p) 'calcFunc-import)
X! 		(progn
X! 		  (setcdr pp (cdr (cdr pp)))
X! 		  (or (and (eq (car-safe (nth 1 p)) 'var)
X! 			   (setq part (calc-var-value (nth 2 (nth 1 p))))
X! 			   (eq (car-safe part) 'vec))
X! 		      (error "Argument of import() must be a rules variable"))
X! 		  (if math-make-import-list
X! 		      (setq math-import-list
X! 			    (cons (cons (nth 2 (nth 1 p))
X! 					(symbol-value (nth 2 (nth 1 p))))
X! 				  math-import-list)))
X! 		  (while (setq p (cdr (cdr p)))
X! 		    (or (cdr p)
X! 			(error "import() must have odd number of arguments"))
X! 		    (setq part (math-rwcomp-substitute part
X! 						       (car p) (nth 1 p))))
X! 		  (if (memq (car-safe (nth 1 part)) '(vec calcFunc-import))
X! 		      (setq part (cdr part))
X! 		    (setq part (list part)))
X! 		  (setcdr pp (append part (cdr pp))))
X! 	      (setq pp (cdr pp))))))
X!     (if (eq (car-safe (nth 1 rules)) 'vec)
X! 	(setq rules (cdr rules))
X!       (setq rules (list rules)))
X!     (let ((rule-set nil)
X! 	  (all-heads nil)
X! 	  (nil-rules nil)
X! 	  (rule-count 0))
X!       (while rules
X! 	;; (message "Compiling rule %d..." (setq rule-count (1+ rule-count)))
X! 	(or (and (eq (car-safe (car rules)) 'vec)
X! 		 (cdr (cdr (car rules)))
X! 		 (not (nthcdr 4 (car rules))))
X! 	    (error "Rewrite rule set must be a vector of vectors"))
X! 	(let ((math-pattern (nth 1 (car rules)))
X! 	      (math-rhs (nth 2 (car rules)))
X! 	      (math-prog nil)
X! 	      (math-num-regs 1)
X! 	      (math-regs (list (list nil 0 nil nil)))
X! 	      (math-conds nil))
X! 	  (let ((cond (nth 3 (car rules))))
X! 	    (if (and (eq (car-safe cond) 'calcFunc-quote)
X! 		     (= (length cond) 2))
X! 		(setq cond (nth 1 cond)))
X! 	    (while (eq (car-safe cond) 'calcFunc-land)
X! 	      (setq math-conds (cons (nth 2 cond) math-conds)
X! 		    cond (nth 1 cond)))
X! 	    (if cond
X! 		(setq math-conds (cons cond math-conds))))
X! 	  (math-rwcomp-pattern math-pattern 0)
X! 	  (while math-conds
X! 	    (math-rwcomp-cond-instr (car math-conds))
X! 	    (setq math-conds (cdr math-conds)))
X! 	  (math-rwcomp-instr 'done (math-rwcomp-match-vars math-rhs))
X! 	  (setq math-prog (nreverse math-prog))
X! 	  (let* ((heads (math-rewrite-heads math-pattern))
X! 		 (rule (list (vconcat
X! 			      (nreverse
X! 			       (mapcar (function (lambda (x) (nth 3 x)))
X! 				       math-regs)))
X! 			     math-prog
X! 			     heads))
X! 		 (head (and (not (Math-primp math-pattern))
X! 			    (not (and (eq (car (car math-prog)) 'try)
X! 				      (nth 5 (car math-prog))))
X! 			    (not (memq (car (car math-prog)) '(func-opt
X! 							       apply
X! 							       select)))
X! 			    (if (memq (car (car math-prog)) '(func
X! 							      func-def))
X! 				(nth 2 (car math-prog))
X! 			      (car math-pattern)))))
X! 	    (let (found)
X! 	      (while heads
X! 		(if (setq found (assq (car heads) all-heads))
X! 		    (setcdr found (1+ (cdr found)))
X! 		  (setq all-heads (cons (cons (car heads) 1) all-heads)))
X! 		(setq heads (cdr heads))))
X! 	    (if (eq head '-) (setq head '+))
X! 	    (if (eq head 'calcFunc-cons) (setq head 'vec))
X! 	    (if head
X! 		(nconc (or (assq head rule-set)
X! 			   (car (setq rule-set (cons (cons head
X! 							   (copy-sequence
X! 							    nil-rules))
X! 						     rule-set))))
X! 		       (list rule))
X! 	      (setq nil-rules (nconc nil-rules (list rule)))
X! 	      (let ((ptr rule-set))
X! 		(while ptr
X! 		  (nconc (car ptr) (list rule))
X! 		  (setq ptr (cdr ptr))))))
X! 	  (setq rules (cdr rules))))
X!       ;; (message "Collating rule heads...")
X!       (if nil-rules
X! 	  (setq rule-set (cons (cons nil nil-rules) rule-set)))
X!       (setq all-heads (mapcar 'car
X! 			      (sort all-heads (function
X! 					       (lambda (x y)
X! 						 (< (cdr x) (cdr y)))))))
X!       (let ((set rule-set)
X! 	    rule heads ptr)
X! 	(while set
X! 	  (setq rule (cdr (car set)))
X! 	  (while rule
X! 	    (if (consp (setq heads (nth 2 (car rule))))
X! 		(progn
X! 		  (setq heads (delq (car (car set)) heads)
X! 			ptr all-heads)
X! 		  (while (and ptr (not (memq (car ptr) heads)))
X! 		    (setq ptr (cdr ptr)))
X! 		  (setcar (nthcdr 2 (car rule)) (car ptr))))
X! 	    (setq rule (cdr rule)))
X! 	  (setq set (cdr set))))
X!       (let ((plus (assq '+ rule-set)))
X! 	(if plus
X! 	    (setq rule-set (cons (cons '- (cdr plus)) rule-set))))
X!       rule-set))
X! )
X! 
X! (defun math-rewrite-heads (expr &optional more)
X!   (let ((heads more))
X!     (or (Math-primp expr)
X! 	(math-rewrite-heads-rec expr))
X!     heads)
X! )
X! 
X! (defun math-rewrite-heads-rec (expr)
X!   (or (memq (car expr) heads)
X!       (memq (car expr) '(calcFunc-quote calcFunc-plain calcFunc-opt
X! 					calcFunc-select calcFunc-apply
X! 					calcFunc-cons calcFunc-condition))
X!       (memq 'algebraic (get (car expr) 'math-rewrite-props))
X!       (setq heads (cons (car expr) heads)))
X!   (while (setq expr (cdr expr))
X!     (or (Math-primp (car expr))
X! 	(math-rewrite-heads-rec (car expr))))
X  )
X  
X! (defun math-rwcomp-match-vars (expr)
X    (if (Math-primp expr)
X        (if (eq (car-safe expr) 'var)
X! 	  (let ((entry (assq (nth 2 expr) math-regs)))
X! 	    (if entry
X! 		(math-rwcomp-register-expr (nth 1 entry))
X  	      expr))
X  	expr)
X!     (if (and (eq (car expr) 'calcFunc-quote)
X! 	     (= (length expr) 2))
X! 	(math-rwcomp-match-vars (nth 1 expr))
X!       (cons (car expr)
X! 	    (mapcar 'math-rwcomp-match-vars (cdr expr)))))
X! )
X! 
X! (defun math-rwcomp-register-expr (num)
X!   (let ((entry (nth (1- (- math-num-regs num)) math-regs)))
X!     (if (nth 2 entry)
X! 	(list 'neg (list 'calcFunc-register (nth 1 entry)))
X!       (list 'calcFunc-register (nth 1 entry))))
X! )
X! 
X! (defun math-rwcomp-substitute (expr old new)
X!   (if (and (eq (car-safe old) 'var)
X! 	   (memq (car-safe new) '(var calcFunc-lambda)))
X!       (let ((old-func (math-var-to-calcFunc old))
X! 	    (new-func (math-var-to-calcFunc new)))
X! 	(math-rwcomp-subst-rec expr))
X!     (let ((old-func nil))
X!       (math-rwcomp-subst-rec expr)))
X! )
X! 
X! (defun math-rwcomp-subst-rec (expr)
X!   (cond ((equal expr old) new)
X! 	((Math-primp expr) expr)
X! 	(t (if (eq (car expr) old-func)
X! 	       (math-build-call new-func (mapcar 'math-rwcomp-subst-rec
X! 						 (cdr expr)))
X! 	     (cons (car expr)
X! 		   (mapcar 'math-rwcomp-subst-rec (cdr expr))))))
X! )
X! 
X! (setq math-rwcomp-tracing nil)
X! (defun math-rwcomp-trace (instr)
X!   (if math-rwcomp-tracing (progn (terpri) (princ instr)))
X!   instr
X! )
X! 
X! (defun math-rwcomp-instr (&rest instr)
X!   (setq math-prog (cons (math-rwcomp-trace instr) math-prog))
X! )
X! 
X! (defun math-rwcomp-multi-instr (tail &rest instr)
X!   (setq math-prog (cons (math-rwcomp-trace (append instr tail))
X! 			math-prog))
X! )
X! 
X! (defun math-rwcomp-cond-instr (expr)
X!   (setq expr (math-rwcomp-match-vars expr))
X!   (let (op arg)
X!     (cond ((and (setq op (cdr (assq (car-safe expr)
X! 				    '( (calcFunc-integer  . integer)
X! 				       (calcFunc-real     . real)
X! 				       (calcFunc-constant . constant)
X! 				       (calcFunc-negative . negative) ))))
X! 		(= (length expr) 2)
X! 		(or (and (eq (car-safe (nth 1 expr)) 'neg)
X! 			 (memq op '(integer real constant))
X! 			 (setq arg (nth 1 (nth 1 expr))))
X! 		    (setq arg (nth 1 expr)))
X! 		(eq (car-safe (setq arg (nth 1 expr))) 'calcFunc-register))
X! 	   (math-rwcomp-instr op (nth 1 arg)))
X! 	  ((and (assq (car-safe expr) calc-tweak-eqn-table)
X! 		(= (length expr) 3)
X! 		(eq (car-safe (nth 1 expr)) 'calcFunc-register))
X! 	   (if (math-constp (nth 2 expr))
X! 	       (let ((reg (math-rwcomp-reg)))
X! 		 (setcar (nthcdr 3 (car math-regs)) (nth 2 expr))
X! 		 (math-rwcomp-instr 'rel (nth 1 (nth 1 expr))
X! 				    (car expr) reg))
X! 	     (if (eq (car (nth 2 expr)) 'calcFunc-register)
X! 		 (math-rwcomp-instr 'rel (nth 1 (nth 1 expr))
X! 				    (car expr) (nth 1 (nth 2 expr)))
X! 	       (math-rwcomp-instr 'cond expr))))
X! 	  ((and (eq (car-safe expr) 'calcFunc-eq)
X! 		(= (length expr) 3)
X! 		(eq (car-safe (nth 1 expr)) '%)
X! 		(eq (car-safe (nth 1 (nth 1 expr))) 'calcFunc-register)
X! 		(math-constp (nth 2 (nth 1 expr)))
X! 		(math-constp (nth 2 expr)))
X! 	   (math-rwcomp-instr 'mod (nth 1 (nth 1 (nth 1 expr)))
X! 			      (nth 2 (nth 1 expr)) (nth 2 expr)))
X! 	  (t (math-rwcomp-instr 'cond expr))))
X! )
X! 
X! (defun math-rwcomp-same-instr (reg1 reg2 neg)
X!   (math-rwcomp-instr (if (eq (eq (nth 2 (math-rwcomp-reg-entry reg1))
X! 				 (nth 2 (math-rwcomp-reg-entry reg2)))
X! 			     neg)
X! 			 'same-neg
X! 		       'same)
X! 		     reg1 reg2)
X! )
X! 
X! (defun math-rwcomp-reg ()
X!   (prog1
X!       math-num-regs
X!     (setq math-regs (cons (list nil math-num-regs nil nil) math-regs)
X! 	  math-num-regs (1+ math-num-regs)))
X! )
X! 
X! (defun math-rwcomp-reg-entry (num)
X!   (nth (1- (- math-num-regs num)) math-regs)
X! )
X! 
X! (defun math-rwcomp-pattern (expr part)
X!   (cond ((or (math-rwcomp-no-vars expr)
X! 	     (and (eq (car expr) 'calcFunc-quote)
SHAR_EOF
echo "End of part 9, continue with part 10"
echo "10" > s2_seq_.tmp
exit 0