[comp.sources.misc] v13i031: Emacs Calculator 1.01, part 05/19

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

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

---- Cut Here and unpack ----
#!/bin/sh
# this is part 5 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file calc-ext.el continued
#
CurArch=5
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     ( atan	   . calcFunc-arctan )
X     ( atan2	   . calcFunc-arctan2 )
X     ( atanh	   . calcFunc-arctanh )
X))
X
X(put 'c 'math-variable-table
X  '( ( M_PI	   . var-pi )
X     ( M_E	   . var-e )
X))
X
X(put 'c 'math-vector-brackets "{}")
X
X(put 'c 'math-radix-formatter
X     (function (lambda (r s)
X		 (if (= r 16) (format "0x%s" s)
X		   (if (= r 8) (format "0%s" s)
X		     (format "%d#%s" r s))))))
X
X
X(defun calc-pascal-language (n)
X  "Set Pascal-language entry and display notation."
X  (interactive "P")
X  (calc-wrapper
X   (calc-set-language 'pascal n))
X)
X
X(put 'pascal 'math-oper-table
X  '( ( "not"   calcFunc-lnot -1 1000 )
X     ( "*"     *	     190 191 )
X     ( "/"     /	     190 191 )
X     ( "and"   calcFunc-and  190 191 )
X     ( "div"   calcFunc-idiv 190 191 )
X     ( "mod"   %	     190 191 )
X     ( "u+"    ident	     -1  185 )
X     ( "u-"    neg	     -1  185 )
X     ( "+"     +	     180 181 )
X     ( "-"     -	     180 181 )
X     ( "or"    calcFunc-or   180 181 )
X     ( "xor"   calcFunc-xor  180 181 )
X     ( "shl"   calcFunc-lsh  180 181 )
X     ( "shr"   calcFunc-rsh  180 181 )
X     ( "in"    calcFunc-in   160 161 )
X     ( "<"     calcFunc-lt   160 161 )
X     ( ">"     calcFunc-gt   160 161 )
X     ( "<="    calcFunc-leq  160 161 )
X     ( ">="    calcFunc-geq  160 161 )
X     ( "="     calcFunc-eq   160 161 )
X     ( "<>"    calcFunc-neq  160 161 )
X     ( ":="    calcFunc-assign 81 80 )
X))
X
X(put 'pascal 'math-input-filter 'calc-input-case-filter)
X(put 'pascal 'math-output-filter 'calc-output-case-filter)
X
X(defun calc-input-case-filter (str)
X  (cond ((or (null calc-language-option) (= calc-language-option 0))
X	 str)
X	(t
X	 (downcase str)))
X)
X
X(defun calc-output-case-filter (str)
X  (cond ((or (null calc-language-option) (= calc-language-option 0))
X	 str)
X	((> calc-language-option 0)
X	 (upcase str))
X	(t
X	 (downcase str)))
X)
X
X
X(defun calc-fortran-language (n)
X  "Set Fortran-language entry and display notation."
X  (interactive "P")
X  (calc-wrapper
X   (calc-set-language 'fortran n))
X)
X
X(put 'fortran 'math-oper-table
X  '( ( "**"    ^             201 200 )
X     ( "u+"    ident	     -1  191 )
X     ( "u-"    neg	     -1  191 )
X     ( "*"     *	     190 191 )
X     ( "/"     /	     190 191 )
X     ( "+"     +	     180 181 )
X     ( "-"     -	     180 181 )
X))
X
X(put 'fortran 'math-vector-brackets "//")
X
X(put 'fortran 'math-function-table
X  '( ( acos	   . calcFunc-arccos )
X     ( acosh	   . calcFunc-arccosh )
X     ( aimag	   . calcFunc-im )
X     ( aint	   . calcFunc-ftrunc )
X     ( asin	   . calcFunc-arcsin )
X     ( asinh	   . calcFunc-arcsinh )
X     ( atan	   . calcFunc-arctan )
X     ( atan2	   . calcFunc-arctan2 )
X     ( atanh	   . calcFunc-arctanh )
X     ( conjg	   . calcFunc-conj )
X     ( log	   . calcFunc-ln )
X     ( nint	   . calcFunc-round )
X     ( real	   . calcFunc-re )
X))
X
X(put 'fortran 'math-input-filter 'calc-input-case-filter)
X(put 'fortran 'math-output-filter 'calc-output-case-filter)
X
X
X(defun calc-tex-language (n)
X  "Set TeX entry and display notation."
X  (interactive "P")
X  (calc-wrapper
X   (calc-set-language 'tex n))
X)
X
X(put 'tex 'math-oper-table
X  '( ( "u+"       ident		   -1 1000 )
X     ( "u-"       neg		   -1 1000 )
X     ( "u|"       calcFunc-abs	   -1    0 )
X     ( "|"        ident		    0   -1 )
X     ( "\\lfloor" calcFunc-floor   -1    0 )
X     ( "\\rfloor" ident             0   -1 )
X     ( "\\lceil"  calcFunc-ceil    -1    0 )
X     ( "\\rceil"  ident             0   -1 )
X     ( "\\pm"	  sdev		   300 300 )
X     ( "!"        calcFunc-fact	   210  -1 )
X     ( "^"	  ^		   201 200 )
X     ( "_"	  calcFunc-subscr  201 200 )
X     ( "\\times"  *		   191 190 )
X     ( "2x"	  *		   191 190 )
X     ( "+"	  +		   180 181 )
X     ( "-"	  -		   180 181 )
X     ( "\\over"	  /		   170 171 )
X     ( "/"	  /		   170 171 )
X     ( "\\choose" calcFunc-choose  170 171 )
X     ( "\\mod"	  %		   170 171 )
X))
X
X(put 'tex 'math-function-table
X  '( ( \\arccos	   . calcFunc-arccos )
X     ( \\arcsin	   . calcFunc-arcsin )
X     ( \\arctan	   . calcFunc-arctan )
X     ( \\arg	   . calcFunc-arg )
X     ( \\cos	   . calcFunc-cos )
X     ( \\cosh	   . calcFunc-cosh )
X     ( \\det	   . calcFunc-det )
X     ( \\exp	   . calcFunc-exp )
X     ( \\gcd	   . calcFunc-gcd )
X     ( \\ln	   . calcFunc-ln )
X     ( \\log	   . calcFunc-log10 )
X     ( \\max	   . calcFunc-max )
X     ( \\min	   . calcFunc-min )
X     ( \\tan	   . calcFunc-tan )
X     ( \\sin	   . calcFunc-sin )
X     ( \\sinh	   . calcFunc-sinh )
X     ( \\tanh	   . calcFunc-tanh )
X     ( \\phi	   . calcFunc-totient )
X     ( \\mu	   . calcFunc-moebius )
X))
X
X(put 'tex 'math-variable-table
X  '( ( \\pi	   . var-pi )
X))
X
X(put 'tex 'math-complex-format 'i)
X
X
X(defun calc-mathematica-language ()
X  "Set Mathematica(tm) entry and display notation."
X  (interactive)
X  (calc-wrapper
X   (calc-set-language 'math))
X)
X
X(put 'math 'math-oper-table
X  '( ( "!"     calcFunc-fact  210 -1 )
X     ( "!!"    calcFunc-dfact 210 -1 )
X     ( "^"     ^	     201 200 )
X     ( "u+"    ident	     -1  197 )
X     ( "u-"    neg	     -1  197 )
X     ( "/"     /	     195 196 )
X     ( "*"     *	     190 191 )
X     ( "2x"    *	     190 191 )
X     ( "+"     +	     180 181 )
X     ( "-"     -	     180 181 )
X     ( "<"     calcFunc-lt   160 161 )
X     ( ">"     calcFunc-gt   160 161 )
X     ( "<="    calcFunc-leq  160 161 )
X     ( ">="    calcFunc-geq  160 161 )
X     ( "=="    calcFunc-eq   150 151 )
X     ( "!="    calcFunc-neq  150 151 )
X     ( "&&"    calcFunc-land 110 111 )
X     ( "||"    calcFunc-lor  100 101 )
X))
X
X(put 'math 'math-function-table
X  '( ( Abs	   . calcFunc-abs )
X     ( ArcCos	   . calcFunc-arccos )
X     ( ArcCosh	   . calcFunc-arccosh )
X     ( ArcSin	   . calcFunc-arcsin )
X     ( ArcSinh	   . calcFunc-arcsinh )
X     ( ArcTan	   . calcFunc-arctan )
X     ( ArcTanh	   . calcFunc-arctanh )
X     ( Arg	   . calcFunc-arg )
X     ( Binomial	   . calcFunc-choose )
X     ( Ceiling	   . calcFunc-ceil )
X     ( Conjugate   . calcFunc-conj )
X     ( Cos	   . calcFunc-cos )
X     ( Cosh	   . calcFunc-cosh )
X     ( D	   . calcFunc-deriv )
X     ( Dt	   . calcFunc-tderiv )
X     ( Det	   . calcFunc-det )
X     ( Exp	   . calcFunc-exp )
X     ( EulerPhi	   . calcFunc-totient )
X     ( Floor	   . calcFunc-floor )
X     ( Gamma	   . calcFunc-gamma )
X     ( GCD	   . calcFunc-gcd )
X     ( If	   . calcFunc-if )
X     ( Im	   . calcFunc-im )
X     ( Inverse	   . calcFunc-inv )
X     ( Join	   . calcFunc-vconcat )
X     ( LCM	   . calcFunc-lcm )
X     ( Log	   . calcFunc-ln )
X     ( Max	   . calcFunc-max )
X     ( Min	   . calcFunc-min )
X     ( Mod	   . calcFunc-mod )
X     ( MoebiusMu   . calcFunc-moebius )
X     ( Random	   . calcFunc-random )
X     ( Round	   . calcFunc-round )
X     ( Re	   . calcFunc-re )
X     ( Sign	   . calcFunc-sign )
X     ( Sin	   . calcFunc-sin )
X     ( Sinh	   . calcFunc-sinh )
X     ( Sqrt	   . calcFunc-sqrt )
X     ( Tan	   . calcFunc-tan )
X     ( Tanh	   . calcFunc-tanh )
X     ( Transpose   . calcFunc-trn )
X     ( Length	   . calcFunc-vlen )
X))
X
X(put 'math 'math-variable-table
X  '( ( I	   . var-i )
X     ( Pi	   . var-pi )
X     ( E	   . var-e )
X))
X
X(put 'math 'math-vector-brackets "{}")
X(put 'math 'math-complex-format 'I)
X(put 'math 'math-function-open "[")
X(put 'math 'math-function-close "]")
X
X(put 'math 'math-radix-formatter
X     (function (lambda (r s) (format "%d^^%s" r s))))
X
X
X
X
X;;; Combinatorics
X
X(defun calc-k-prefix-help ()
X  (interactive)
X  (calc-do-prefix-help
X   '("GCD, LCM; Binomial, Dbl-fact; Random, random-Again"
X     "Factors, Prime-test, Next-prime, Totient, Moebius"
X     "SHIFT + extended-GCD")
X   "combinatorics" ?k)
X)
X
X(defun calc-gcd (arg)
X  "Compute the GCD of the top two elements of the Calculator stack."
X  (interactive "P")
X  (calc-slow-wrapper
X   (calc-binary-op "gcd" 'calcFunc-gcd arg))
X)
X
X(defun calc-lcm (arg)
X  "Compute the LCM of the top two elements of the Calculator stack."
X  (interactive "P")
X  (calc-slow-wrapper
X   (calc-binary-op "lcm" 'calcFunc-lcm arg))
X)
X
X(defun calc-extended-gcd ()
X  "Compute the extended GCD of the top two elements of the Calculator stack.
XThis is a list [g,a,b] where g = gcd(x,y) = ax + by, and x and y are the
Xsecond-to-top and top values on the stack, respectively."
X  (interactive)
X  (calc-slow-wrapper
X   (calc-enter-result 2 "egcd" (cons 'calcFunc-egcd (calc-top-list-n 2))))
X)
X
X(defun calc-factorial (arg)
X  "Compute the factorial of the number on the top of the Calculator stack.
XIf the number is an integer, computes an exact result.
XIf the number is floating-point, computes a floating-point approximate result."
X  (interactive "P")
X  (calc-slow-wrapper
X   (calc-unary-op "fact" 'calcFunc-fact arg))
X)
X
X(defun calc-gamma (arg)
X  "Compute the Euler Gamma function of the number on the Calculator stack."
X  (interactive "P")
X  (calc-slow-wrapper
X   (calc-unary-op "gmma" 'calcFunc-gamma arg))
X)
X
X(defun calc-double-factorial (arg)
X  "Compute the double factorial of the number on the Calculator stack.
XFor even numbers, this is the product of even integers up to N.
XFor odd numbers, this is the product of odd integers up to N.
XIf the number is an integer, computes an exact result.
XIf the number is floating-point, computes a floating-point approximate result."
X  (interactive "P")
X  (calc-slow-wrapper
X   (calc-unary-op "dfac" 'calcFunc-dfact arg))
X)
X
X(defun calc-choose (arg)
X  "Compute the binomial coefficient C(N,M) of the numbers on the stack.
XIf the numbers are integers, computes an exact result.
XIf either number is floating-point, computes an approximate result.
XWith Hyperbolic flag, computes number-of-permutations instead."
X  (interactive "P")
X  (calc-slow-wrapper
X   (if (calc-is-hyperbolic)
X       (calc-binary-op "perm" 'calcFunc-perm arg)
X     (calc-binary-op "chos" 'calcFunc-choose arg)))
X)
X
X(defun calc-perm (arg)
X  "Compute the number-of-permutations P(N,M) of the numbers on the stack.
XIf the numbers are integers, computes an exact result.
XIf either number is floating-point, computes an approximate result.
XWith Hyperbolic flag, computes binomial coefficient instead."
X  (interactive "P")
X  (calc-hyperbolic-func)
X  (calc-choose arg)
X)
X
X(defvar calc-last-random-limit '(float 1 0))
X(defun calc-random (n)
X  "Produce a random integer between 0 (inclusive) and N (exclusive).
XN is the numeric prefix argument, if any, otherwise it is taken from the stack.
XIf N is real, produce a random real number in the specified range.
XIf N is zero, produce a Gaussian-distributed value with mean 0, variance 1."
X  (interactive "P")
X  (calc-slow-wrapper
X   (if n
X       (calc-enter-result 0 "rand" (list 'calcFunc-random
X					 (setq calc-last-random-limit
X					       (prefix-numeric-value n))))
X     (calc-enter-result 1 "rand" (list 'calcFunc-random
X				       (setq calc-last-random-limit
X					     (calc-top-n 1))))))
X)
X
X(defun calc-rrandom ()
X  "Produce a random real between 0 and 1."
X  (interactive)
X  (calc-slow-wrapper
X   (setq calc-last-random-limit '(float 1 0))
X   (calc-enter-result 0 "rand" (list 'calcFunc-random '(float 1 0))))
X)
X
X(defun calc-random-again ()
X  "Produce another random number in the same range as the last one generated."
X  (interactive)
X  (calc-slow-wrapper
X   (calc-enter-result 0 "rand" (list 'calcFunc-random calc-last-random-limit)))
X)
X
X(defun calc-report-prime-test (res)
X  (cond ((eq (car res) t)
X	 (calc-record-message "prim" "Prime (guaranteed)"))
X	((eq (car res) nil)
X	 (if (cdr res)
X	     (if (eq (nth 1 res) 'unknown)
X		 (calc-record-message
X		  "prim" "Non-prime (factors unknown)")
X	       (calc-record-message
X		"prim" "Non-prime (%s is a factor)"
X		(math-format-number (nth 1 res))))
X	   (calc-record-message "prim" "Non-prime")))
X	(t
X	 (calc-record-message
X	  "prim" "Probably prime (%d iters; %s%% chance of error)"
X	  (nth 1 res)
X	  (let ((calc-float-format '(fix 2)))
X	    (math-format-number (nth 2 res))))))
X)
X
X(defun calc-prime-test (iters)
X  "Determine whether the number on the top of the stack is prime.
XFor large numbers (> 8 million), this test is probabilistic.
XExecute this command repeatedly to improve certainty of result.
XWith a numeric prefix argument, execute (up to) N iterations at once."
X  (interactive "p")
X  (calc-slow-wrapper
X   (let* ((n (calc-top-n 1))
X	  (res (math-prime-test n iters)))
X     (calc-report-prime-test res)))
X)
X
X(defun calc-next-prime (iters)
X  "Determine the next prime greater than the number on the top of the stack.
XThe top-of-stack is replaced by this number.
XFor numbers above 8 million, this finds the next number that passes one
Xiteration of calc-prime-test.  With a prefix argument, the number must
Xpass the specified number of calc-prime-test iterations.
XWith Inverse flag, find the previous prime instead."
X  (interactive "p")
X  (calc-slow-wrapper
X   (let ((calc-verbose-nextprime t))
X     (if (calc-is-inverse)
X	 (calc-enter-result 1 "prvp" (list 'calcFunc-prevprime
X					   (calc-top-n 1) (math-abs iters)))
X       (calc-enter-result 1 "nxtp" (list 'calcFunc-nextprime
X					 (calc-top-n 1) (math-abs iters))))))
X)
X
X(defun calc-prev-prime (iters)
X  "Determine the next prime less than the number on the top of the stack.
XWith Inverse flag, find the next greater prime instead."
X  (interactive "p")
X  (calc-invert-func)
X  (calc-next-prime iters)
X)
X
X(defun calc-prime-factors (iters)
X  "Attempt to reduce the integer at top of stack to a list of its prime factors.
XThis algorithm is guaranteed for N up to 25 million.  For larger N, it may
Xnot find all of the prime factors."
X  (interactive "p")
X  (calc-slow-wrapper
X   (let ((res (math-prime-factors (calc-top-n 1))))
X     (if (not math-prime-factors-finished)
X	 (calc-record-message "pfac" "Warning:  May not be fully factored"))
X     (calc-enter-result 1 "pfac" res)))
X)
X
X(defun calc-totient (arg)
X  "Compute the Euler Totient function phi(n).
XThis is the number of integers less than n which are relatively prime to n."
X  (interactive "P")
X  (calc-slow-wrapper
X   (calc-unary-op "phi" 'calcFunc-totient arg))
X)
X
X(defun calc-moebius (arg)
X  "Compute the Moebius Mu function mu(n).
XThis is (-1)^k if n has k distinct prime factors, or 0 if n has some
Xduplicate factors."
X  (interactive "P")
X  (calc-slow-wrapper
X   (calc-unary-op "mu" 'calcFunc-moebius arg))
X)
X
X
X
X
X;;; Mode commands.
X
X(defun calc-m-prefix-help ()
X  (interactive)
X  (calc-do-prefix-help
X   '("Deg, Rad, HMS; Frac; Polar; Algebraic; Symbolic"
X     "Working; Xtensions; M=save"
X     "SHIFT + simplify: Off, Num, Default, Bin-clip, Alg, Units")
X   "mode" ?m)
X)
X
X(defun calc-save-modes ()
X  "Save all mode variables' values in your .emacs file."
X  (interactive)
X  (calc-wrapper
X   (let (pos
X	 (vals (mapcar (function (lambda (v) (symbol-value (car v))))
X		       calc-mode-var-list)))
X     (set-buffer (find-file-noselect (substitute-in-file-name
X				      calc-settings-file)))
X     (goto-char (point-min))
X     (if (and (search-forward ";;; Mode settings stored by Calc" nil t)
X	      (progn
X		(beginning-of-line)
X		(setq pos (point))
X		(search-forward "\n;;; End of mode settings" nil t)))
X	 (progn
X	   (beginning-of-line)
X	   (forward-line 1)
X	   (delete-region pos (point)))
X       (goto-char (point-max))
X       (insert "\n\n")
X       (forward-char -1))
X     (insert ";;; Mode settings stored by Calc on " (current-time-string) "\n")
X     (let ((list calc-mode-var-list))
X       (while list
X	 (let* ((v (car (car list)))
X		(def (nth 1 (car list)))
X		(val (car vals)))
X	   (or (equal val def)
X	       (progn
X		 (insert "(setq " (symbol-name v) " ")
X		 (if (and (or (listp val)
X			      (symbolp val))
X			  (not (memq val '(nil t))))
X		     (insert "'"))
X		 (insert (prin1-to-string val) ")\n"))))
X	 (setq list (cdr list)
X	       vals (cdr vals))))
X     (run-hooks 'calc-mode-save-hook)
X     (insert ";;; End of mode settings\n")
X     (save-buffer)))
X)
X
X(defun calc-algebraic-mode ()
X  "Turn Algebraic mode on or off.
XIn algebraic mode, numeric entry accepts whole expressions without needing \"'\"."
X  (interactive)
X  (calc-wrapper
X   (setq calc-algebraic-mode (not calc-algebraic-mode)))
X)
X
X(defun calc-symbolic-mode ()
X  "Turn Symbolic mode on or off.
XIn symbolic mode, inexact numeric computations like sqrt(2) are postponed."
X  (interactive)
X  (calc-wrapper
X   (setq calc-symbolic-mode (not calc-symbolic-mode)))
X)
X
X(defun calc-set-simplify-mode (mode arg)
X  (setq calc-simplify-mode (if arg
X			       (and (> (prefix-numeric-value arg) 0)
X				    mode)
X			     (and (not (eq calc-simplify-mode mode))
X				  mode)))
X)
X
X(defun calc-no-simplify-mode (arg)
X  "Turn off automatic simplification of algebraic expressions."
X  (interactive "P")
X  (calc-wrapper
X   (calc-set-simplify-mode 'none arg))
X)
X
X(defun calc-num-simplify-mode (arg)
X  "Enable automatic simplification of expressions with constant argments only."
X  (interactive "P")
X  (calc-wrapper
X   (calc-set-simplify-mode 'num arg))
X)
X
X(defun calc-default-simplify-mode ()
X  "Turn on default automatic simplification of algebraic expressions."
X  (interactive)
X  (calc-wrapper
X   (setq calc-simplify-mode nil))
X)
X
X(defun calc-bin-simplify-mode (arg)
X  "Turn on automatic simplification with math-clip."
X  (interactive "P")
X  (calc-wrapper
X   (calc-set-simplify-mode 'binary arg))
X)
X
X(defun calc-alg-simplify-mode (arg)
X  "Turn on automatic algebraic simplification of expressions."
X  (interactive "P")
X  (calc-wrapper
X   (calc-set-simplify-mode 'alg arg))
X)
X
X(defun calc-ext-simplify-mode (arg)
X  "Turn on automatic \"extended\" algebraic simplification of expressions."
X  (interactive "P")
X  (calc-wrapper
X   (calc-set-simplify-mode 'ext arg))
X)
X
X(defun calc-units-simplify-mode (arg)
X  "Turn on automatic units-simplification of expressions."
X  (interactive "P")
X  (calc-wrapper
X   (calc-set-simplify-mode 'units arg))
X)
X
X(defun calc-working (n)
X  "Display level of \"Working...\" messages, or set level to N.
XWith numeric prefix argument 0, disables messages.
XWith argument 1, enables messages.
XWith argument 2, enables more detailed messages."
X  (interactive "P")
X  (calc-wrapper
X   (cond ((consp n)
X	  (calc-pop-push-record 0 "work"
X				(cond ((eq calc-display-working-message t) 1)
X				      (calc-display-working-message 2)
X				      (t 0))))
X	 ((eq n 2) (setq calc-display-working-message 'lots))
X	 ((eq n 0) (setq calc-display-working-message nil))
X	 ((eq n 1) (setq calc-display-working-message t)))
X   (cond ((eq calc-display-working-message t)
X	  (message "\"Working...\" messages enabled."))
X	 (calc-display-working-message
X	  (message "Detailed \"Working...\" messages enabled."))
X	 (t
X	  (message "\"Working...\" messages disabled."))))
X)
X
X(defun calc-always-load-extensions ()
X  "Toggle mode in which calc-ext extensions are loaded automatically with calc."
X  (interactive)
X  (calc-wrapper
X   (if (setq calc-always-load-extensions (not calc-always-load-extensions))
X       (message "Always loading extensions package.")
X     (message "Loading extensions package on demand only.")))
X)
X
X(defun calc-degrees-mode ()
X  "Set Calculator to use degrees for all angles."
X  (interactive)
X  (calc-wrapper
X   (setq calc-angle-mode 'deg)
X   (message "Angles measured in degrees."))
X)
X
X(defun calc-radians-mode ()
X  "Set Calculator to use degrees for all angles."
X  (interactive)
X  (calc-wrapper
X   (setq calc-angle-mode 'rad)
X   (message "Angles measured in radians."))
X)
X
X(defun calc-hms-mode ()
X  "Set Calculator to use degrees-minutes-seconds for all angles."
X  (interactive)
X  (calc-wrapper
X   (setq calc-angle-mode 'hms)
X   (message "Angles measured in degrees-minutes-seconds."))
X)
X
X(defun calc-polar-mode (n)
X  "Toggle mode complex number preference between rectangular and polar forms."
X  (interactive "P")
X  (calc-wrapper
X   (if (if n
X	   (> (prefix-numeric-value n) 0)
X	 (eq calc-complex-mode 'cplx))
X       (progn
X	 (setq calc-complex-mode 'polar)
X	 (message "Preferred complex form is polar."))
X     (setq calc-complex-mode 'cplx)
X     (message "Preferred complex form is rectangular.")))
X)
X
X(defun calc-frac-mode (n)
X  "Toggle mode in which Calculator prefers fractions over floats.
XWith positive prefix argument, sets mode on (fractions).
XWith negative or zero prefix argument, sets mode off (floats)."
X  (interactive "P")
X  (calc-wrapper
X   (if (if n
X	   (> (prefix-numeric-value n) 0)
X	 (not calc-prefer-frac))
X       (progn
X	 (setq calc-prefer-frac t)
X	 (message "Integer division will now generate fractions."))
X     (setq calc-prefer-frac nil)
X     (message "Integer division will now generate floating-point results.")))
X)
X
X
X
X
X;;; Trail commands.
X
X(defun calc-t-prefix-help ()
X  (interactive)
X  (calc-do-prefix-help
X   '("Display; Fwd, Back; Next, Prev, Here, [, ]; Yank"
X     "Search, Reverse; In, Out; <, >; Kill; Marker")
X   "trail" ?t)
X)
X
X(defun calc-trail-in ()
X  "Switch to the Calc Trail window."
X  (interactive)
X  (let ((win (get-buffer-window (calc-trail-display t))))
X    (and win (select-window win)))
X)
X
X(defun calc-trail-out ()
X  "Switch back to the main Calculator window."
X  (interactive)
X  (calc-select-buffer)
X  (let ((win (get-buffer-window (current-buffer))))
X    (if win
X	(select-window win)
X      (calc)))
X)
X
X(defmacro calc-with-trail-buffer (&rest body)
X  (` (let ((save-buf (current-buffer))
X	   (calc-command-flags nil))
X       (unwind-protect
X	   (, (append '(progn
X			 (set-buffer (calc-trail-display t))
X			 (or (eq major-mode 'calc-trail-mode)
X			     (error "Calc Trail buffer is not usable"))
X			 (goto-char calc-trail-pointer))
X		      body))
X	 (set-buffer save-buf))))
X)
X
X(defun calc-trail-next (n)
X  "Move the trail pointer down one line."
X  (interactive "p")
X  (calc-with-trail-buffer
X   (forward-line n)
X   (calc-trail-here))
X)
X
X(defun calc-trail-previous (n)
X  "Move the trail pointer up one line."
X  (interactive "p")
X  (calc-with-trail-buffer
X   (forward-line (- n))
X   (calc-trail-here))
X)
X
X(defun calc-trail-first (n)
X  "Move the trail pointer to the beginning of the trail."
X  (interactive "p")
X  (calc-with-trail-buffer
X   (goto-char (point-min))
X   (forward-line n)
X   (calc-trail-here))
X)
X
X(defun calc-trail-last (n)
X  "Move the trail pointer to the end of the trail."
X  (interactive "p")
X  (calc-with-trail-buffer
X   (goto-char (point-max))
X   (forward-line (- n))
X   (calc-trail-here))
X)
X
X(defun calc-trail-scroll-left (n)
X  "Scroll the trail window horizontally to the left."
X  (interactive "P")
X  (let ((curwin (selected-window)))
X    (calc-with-trail-buffer
X     (unwind-protect
X	 (progn
X	   (select-window (get-buffer-window (current-buffer)))
X	   (calc-scroll-left n))
X       (select-window curwin))))
X)
X
X(defun calc-trail-scroll-right (n)
X  "Scroll the trail window horizontally to the right."
X  (interactive "P")
X  (let ((curwin (selected-window)))
X    (calc-with-trail-buffer
X     (unwind-protect
X	 (progn
X	   (select-window (get-buffer-window (current-buffer)))
X	   (calc-scroll-right n))
X       (select-window curwin))))
X)
X
X(defun calc-trail-forward (n)
X  "Move the trail pointer forward one page."
X  (interactive "p")
X  (calc-with-trail-buffer
X   (forward-line (* n (1- (window-height))))
X   (calc-trail-here))
X)
X
X(defun calc-trail-backward (n)
X  "Move the trail pointer backward one page."
X  (interactive "p")
X  (calc-with-trail-buffer
X   (forward-line (- (* n (1- (window-height)))))
X   (calc-trail-here))
X)
X
X(defun calc-trail-isearch-forward ()
X  "Search incrementally forward in the trail buffer."
X  (interactive)
X  (calc-with-trail-buffer
X   (save-window-excursion
X     (select-window (get-buffer-window (current-buffer)))
X     (isearch t nil))
X   (calc-trail-here))
X)
X
X(defun calc-trail-isearch-backward ()
X  "Search incrementally backward in the trail buffer."
X  (interactive)
X  (calc-with-trail-buffer
X   (save-window-excursion
X     (select-window (get-buffer-window (current-buffer)))
X     (isearch nil nil))
X   (calc-trail-here))
X)
X
X(defun calc-trail-yank ()
X  "Yank the value indicated by the trail pointer onto the Calculator stack."
X  (interactive)
X  (calc-wrapper
X   (calc-set-command-flag 'hold-trail)
X   (calc-enter-result 0 "yank"
X		      (calc-with-trail-buffer
X		       (if (or (looking-at "Emacs Calc")
X			       (looking-at "----")
X			       (looking-at " ? ? ?[^ \n]* *$")
X			       (looking-at "..?.?$"))
X			   (error "Can't yank that line"))
X		       (forward-char 4)
X		       (search-forward " ")
X		       (let* ((next (save-excursion (forward-line 1) (point)))
X			      (str (buffer-substring (point) (1- next)))
X			      (calc-language nil)
X			      (math-expr-opers math-standard-opers)
X			      (val (math-read-expr str)))
X			 (if (eq (car-safe val) 'error)
X			     (error "Can't yank that line: " (nth 2 val))
X			   val)))))
X)
X
X(defun calc-trail-marker (str)
X  "Put a textual marker into the Calculator trail."
X  (interactive "sText to insert in trail: ")
X  (calc-with-trail-buffer
X   (forward-line 1)
X   (let ((buffer-read-only nil))
X     (insert "---- " str "\n"))
X   (forward-line -1)
X   (calc-trail-here))
X)
X
X(defun calc-trail-kill (n)
X  "Kill one line from the Calculator trail.
XThis line can be yanked into text buffers, but cannot be yanked back into
Xthe trail."
X  (interactive "p")
X  (calc-with-trail-buffer
X   (let ((buffer-read-only nil))
X     (save-restriction
X       (narrow-to-region   ; don't delete "Emacs Trail" header
X	(save-excursion
X	  (goto-char (point-min))
X	  (forward-line 1)
X	  (point))
X	(point-max))
X       (kill-line n)))
X   (calc-trail-here))
X)
X
X
X
X;;; Units commands.
X
X(defun calc-u-prefix-help ()
X  (interactive)
X  (calc-do-prefix-help
X   '("Simplify, Convert, Temperature-convert, Base-units"
X     "Remove, eXtract; Explain; View-table"
X     "Define, Undefine, Get-defn, Permanent")
X   "units" ?u)
X)
X
X(defun calc-base-units ()
X  "Convert the value on the stack into \"base\" units, like m, g, and s."
X  (interactive)
X  (calc-slow-wrapper
X   (calc-enter-result 1 "bsun" (math-simplify-units
X				(math-to-standard-units (calc-top-n 1) nil))))
X)
X
X(defun calc-convert-units (&optional old-units new-units)
X  "Convert the value on the stack to the specified new units.
XUnit name may also be \"si\", \"mks\", or \"cgs\" to convert to that system.
XTemperature units are converted as relative temperatures."
X  (interactive)
X  (calc-slow-wrapper
X   (let ((expr (calc-top-n 1))
X	 (uoldname nil)
X	 unew)
X     (or (math-units-in-expr-p expr t)
X	 (let ((uold (or old-units
X			 (progn
X			   (setq uoldname (read-string "Old units: "))
X			   (if (equal uoldname "")
X			       (progn
X				 (setq uoldname "1")
X				 1)
X			     (math-read-expr uoldname))))))
X	   (if (eq (car-safe uold) 'error)
X	       (error "Bad format in units expression: %s" (nth 1 uold)))
X	   (setq expr (math-mul expr uold))))
X     (or new-units
X	 (setq new-units (read-string (if uoldname
X					  (concat "Old units: "
X						  uoldname
X						  ", new units: ")
X					"New units: "))))
X     (setq units (math-read-expr new-units))
X     (if (eq (car-safe units) 'error)
X	 (error "Bad format in units expression: %s" (nth 2 units)))
X     (let ((unew (math-units-in-expr-p units t))
X	   (std (and (eq (car-safe units) 'var)
X		     (assq (nth 1 units) math-standard-units-systems))))
X       (if std
X	   (calc-enter-result 1 "cvun" (math-simplify-units
X					(math-to-standard-units expr
X								(nth 1 std))))
X	 (or unew
X	     (error "No units specified"))
X	 (calc-enter-result 1 "cvun" (math-simplify-units
X				      (math-convert-units expr units)))))))
X)
X
X(defun calc-convert-temperature (&optional old-units new-units)
X  "Convert the value on the stack to the specified new temperature units.
XThis converts absolute temperature, i.e., \"0 degC\" converts to \"32 degF\"."
X  (interactive)
X  (calc-slow-wrapper
X   (let ((expr (calc-top-n 1))
X	 (uold nil)
X	 (uoldname nil)
X	 unew)
X     (setq uold (or old-units
X		    (let ((units (math-single-units-in-expr-p expr)))
X		      (if units
X			  (if (consp units)
X			      (list 'var (car units)
X				    (intern (concat "var-"
X						    (symbol-name
X						     (car units)))))
X			    (error "Not a pure temperature expression"))
X			(math-read-expr
X			 (setq uoldname (read-string
X					 "Old temperature units: ")))))))
X     (if (eq (car-safe uold) 'error)
X	 (error "Bad format in units expression: %s" (nth 2 uold)))
X     (or (math-units-in-expr-p expr nil)
X	 (setq expr (math-mul expr uold)))
X     (setq unew (or new-units
X		    (math-read-expr
X		     (read-string (if uoldname
X				      (concat "Old temperature units: "
X					      uoldname
X					      ", new units: ")
X				    "New temperature units: ")))))
X     (if (eq (car-safe unew) 'error)
X	 (error "Bad format in units expression: %s" (nth 2 unew)))
X     (calc-enter-result 1 "cvtm" (math-simplify-units
X				  (math-convert-temperature expr uold unew)))))
X)
X
X(defun calc-remove-units ()
X  "Remove all unit names from the value on the top of the stack."
X  (interactive)
X  (calc-slow-wrapper
X   (calc-enter-result 1 "rmun" (math-simplify-units
X				(math-remove-units (calc-top-n 1)))))
X)
X
X(defun calc-extract-units ()
X  "Extract the units from the unit expression on the top of the stack."
X  (interactive)
X  (calc-slow-wrapper
X   (calc-enter-result 1 "rmun" (math-simplify-units
X				(math-extract-units (calc-top-n 1)))))
X)
X
X(defun calc-explain-units ()
X  "Produce an English explanation of the units of the expression on the stack."
X  (interactive)
X  (calc-wrapper
X   (let ((num-units nil)
X	 (den-units nil))
X     (calc-explain-units-rec (calc-top-n 1) 1)
X     (and den-units (string-match "^[^(].* .*[^)]$" den-units)
X	  (setq den-units (concat "(" den-units ")")))
X     (if num-units
X	 (if den-units
X	     (message "%s per %s" num-units den-units)
X	   (message "%s" num-units))
X       (if den-units
X	   (message "1 per %s" den-units)
X	 (message "No units in expression")))))
X)
X
X(defun calc-explain-units-rec (expr pow)
X  (let ((u (math-check-unit-name expr))
X	pos)
X    (if (and u (not (math-zerop pow)))
X	(let ((name (or (nth 2 u) (symbol-name (car u)))))
X	  (if (eq (aref name 0) ?\*)
X	      (setq name (substring name 1)))
X	  (if (string-match "[^a-zA-Z0-9']" name)
X	      (if (string-match "^[a-zA-Z0-9' ()]*$" name)
X		  (while (setq pos (string-match "[ ()]" name))
X		    (setq name (concat (substring name 0 pos)
X				       (if (eq (aref name pos) 32) "-" "")
X				       (substring name (1+ pos)))))
X		(setq name (concat "(" name ")"))))
X	  (or (eq (nth 1 expr) (car u))
X	      (setq name (concat (nth 2 (assq (aref (symbol-name
X						     (nth 1 expr)) 0)
X					      math-unit-prefixes))
X				 (if (and (string-match "[^a-zA-Z0-9']" name)
X					  (not (memq (car u) '(mHg gf))))
X				     (concat "-" name)
X				   (downcase name)))))
X	  (cond ((or (math-equal-int pow 1)
X		     (math-equal-int pow -1)))
X		((or (math-equal-int pow 2)
X		     (math-equal-int pow -2))
X		 (if (equal (nth 4 u) '((m . 1)))
X		     (setq name (concat "Square-" name))
X		   (setq name (concat name "-squared"))))
X		((or (math-equal-int pow 3)
X		     (math-equal-int pow -3))
X		 (if (equal (nth 4 u) '((m . 1)))
X		     (setq name (concat "Cubic-" name))
X		   (setq name (concat name "-cubed"))))
X		(t
X		 (setq name (concat name "^"
X				    (math-format-number (math-abs pow))))))
X	  (if (math-posp pow)
X	      (setq num-units (if num-units
X				  (concat num-units " " name)
X				name))
X	    (setq den-units (if den-units
X				(concat den-units " " name)
X			      name))))
X      (cond ((eq (car-safe expr) '*)
X	     (calc-explain-units-rec (nth 1 expr) pow)
X	     (calc-explain-units-rec (nth 2 expr) pow))
X	    ((eq (car-safe expr) '/)
X	     (calc-explain-units-rec (nth 1 expr) pow)
X	     (calc-explain-units-rec (nth 2 expr) (- pow)))
X	    ((memq (car-safe expr) '(neg + -))
X	     (calc-explain-units-rec (nth 1 expr) pow))
X	    ((and (eq (car-safe expr) '^)
X		  (math-realp (nth 2 expr)))
X	     (calc-explain-units-rec (nth 1 expr)
X				     (math-mul pow (nth 2 expr)))))))
X)
X
X(defun calc-simplify-units ()
X  "Simplify the units expression on top of the stack."
X  (interactive)
X  (calc-slow-wrapper
X   (calc-with-default-simplification
X    (calc-enter-result 1 "smun" (math-simplify-units (calc-top-n 1)))))
X)
X
X(defun calc-view-units-table (n)
X  "Display a temporary buffer for displaying the Units Table."
X  (interactive "P")
X  (and n (setq math-units-table-buffer-valid nil))
X  (math-build-units-table-buffer nil)
X)
X
X(defun calc-enter-units-table (n)
X  "Switch to a temporary buffer for displaying the Units Table."
X  (interactive "P")
X  (and n (setq math-units-table-buffer-valid nil))
X  (math-build-units-table-buffer t)
X  (message (substitute-command-keys "Type \\[calc] to return to the Calculator."))
X)
X
X(defun calc-define-unit (uname desc)
X  "Define a new type of unit using the formula on the top of the stack."
X  (interactive "SDefine unit name: \nsDescription: ")
X  (calc-wrapper
X   (let ((form (calc-top-n 1))
X	 (unit (assq uname math-additional-units)))
X     (or unit
X	 (setq math-additional-units
X	       (cons (setq unit (list uname nil nil))
X		     math-additional-units)
X	       math-units-table nil))
X     (setcar (cdr unit) (and (not (and (eq (car-safe form) 'var)
X				       (eq (nth 1 form) uname)))
X			     (not (math-equal-int form 1))
X			     (math-format-flat-expr form 0)))
X     (setcar (cdr (cdr unit)) (and (not (equal desc ""))
X				   desc))))
X  (calc-invalidate-units-table)
X)
X
X(defun calc-undefine-unit (uname)
X  "Remove the definition of a user-defined unit."
X  (interactive "SUndefine unit name: ")
X  (calc-wrapper
X   (let ((unit (assq uname math-additional-units)))
X     (or unit
X	 (if (assq uname math-standard-units)
X	     (error "\"%s\" is a predefined unit name" uname)
X	   (error "Unit name \"%s\" not found" uname)))
X     (setq math-additional-units (delq unit math-additional-units)
X	   math-units-table nil)))
X  (calc-invalidate-units-table)
X)
X
X(defun calc-invalidate-units-table ()
X  (setq math-units-table nil)
X  (let ((buf (get-buffer "*Units Table*")))
X    (save-excursion
X      (set-buffer buf)
X      (save-excursion
X	(goto-char (point-min))
X	(if (looking-at "Calculator Units Table")
X	    (let ((buffer-read-only nil))
X	      (insert "(Obsolete) "))))))
X)
X
X(defun calc-get-unit-definition (uname)
X  "Push the definition of a unit as a formula on the Calculator stack."
X  (interactive "SGet definition for unit: ")
X  (calc-wrapper
X   (math-build-units-table)
X   (let ((unit (assq uname math-units-table)))
X     (or unit
X	 (error "Unit name \"%s\" not found" uname))
X     (let ((msg (nth 2 unit)))
X       (if (stringp msg)
X	   (if (string-match "^\\*" msg)
X	       (setq msg (substring msg 1)))
X	 (setq msg (symbol-name uname)))
X       (if (nth 1 unit)
X	   (progn
X	     (calc-enter-result 0 "ugdf" (nth 1 unit))
X	     (message "Derived unit: %s" msg))
X	 (calc-enter-result 0 "ugdf" (list 'var uname
X					   (intern
X					    (concat "var-"
X						    (symbol-name uname)))))
X	 (message "Base unit: %s" msg)))))
X)
X
X(defun calc-permanent-units ()
X  "Save all user-defined units in your .emacs file."
X  (interactive)
X  (calc-wrapper
X   (let (pos)
X     (set-buffer (find-file-noselect (substitute-in-file-name
X				      calc-settings-file)))
X     (goto-char (point-min))
X     (if (and (search-forward ";;; Custom units stored by Calc" nil t)
X	      (progn
X		(beginning-of-line)
X		(setq pos (point))
X		(search-forward "\n;;; End of custom units" nil t)))
X	 (progn
X	   (beginning-of-line)
X	   (forward-line 1)
X	   (delete-region pos (point)))
X       (goto-char (point-max))
X       (insert "\n\n")
X       (forward-char -1))
X     (insert ";;; Custom units stored by Calc on " (current-time-string) "\n")
X     (if math-additional-units
X	 (progn
X	   (insert "(setq math-additional-units '(\n")
X	   (let ((list math-additional-units))
X	     (while list
X	       (insert "  (" (symbol-name (car (car list))) " "
X		       (if (nth 1 (car list))
X			   (if (stringp (nth 1 (car list)))
X			       (prin1-to-string (nth 1 (car list)))
X			     (prin1-to-string (math-format-flat-expr
X					       (nth 1 (car list)) 0)))
X			 "nil")
X		       " "
X		       (prin1-to-string (nth 2 (car list)))
X		       ")\n")
X	       (setq list (cdr list))))
X	   (insert "))\n"))
X       (insert ";;; (no custom units defined)\n"))
X     (insert ";;; End of custom units\n")
X     (save-buffer)))
X)
X
X
X
X
X;;; Vector commands.
X
X(defun calc-v-prefix-help ()
X  (interactive)
X  (calc-do-prefix-help
X   '("Pack, Unpack, Identity, Diagonal, indeX, Build"
X     "Row, Col, Length; rNorm"
X     "Tranpose, Arrange; Sort, Histogram"
X     "SHIFT + Det, Inv, LUD, Trace, conJtrn, Cross, cNorm"
X     "SHIFT + Reduce, Map, Apply"
X     "<, =, > (justification); , (commas); [, {, ( (brackets)")
X   "vec/mat" ?v)
X)
X
X(defun calc-concat (arg)
X  "Concatenate the two vectors at the top of the stack.
XOr concatenate a scalar value and a vector."
X  (interactive "P")
X  (calc-wrapper
X   (calc-binary-op "|" 'calcFunc-vconcat arg '(vec)))
X)
X
X(defun calc-matrix-left-justify ()
X  "Left-justify elements of matrices."
X  (interactive)
X  (calc-wrapper
X   (setq calc-matrix-just nil)
X   (calc-refresh))
X)
X
X(defun calc-matrix-center-justify ()
X  "Center elements of matrices."
X  (interactive)
X  (calc-wrapper
X   (setq calc-matrix-just 'center)
X   (calc-refresh))
X)
X
X(defun calc-matrix-right-justify ()
X  "Right-justify elements of matrices."
X  (interactive)
X  (calc-wrapper
X   (setq calc-matrix-just 'right)
X   (calc-refresh))
X)
X
X(defun calc-vector-commas ()
X  "Turn separating commas in vectors on and off."
X  (interactive)
X  (calc-wrapper
X   (setq calc-vector-commas (if calc-vector-commas nil ","))
X   (calc-refresh))
X)
X
X(defun calc-vector-brackets ()
X  "Surround vectors and matrices with square brackets.
XIf already using brackets, turn the brackets off."
X  (interactive)
X  (calc-wrapper
X   (setq calc-vector-brackets (if (equal calc-vector-brackets "[]") nil "[]"))
X   (calc-refresh))
X)
X
X(defun calc-vector-braces ()
X  "Surround vectors and matrices with curly braces.
XIf already using braces, turn the braces off."
X  (interactive)
X  (calc-wrapper
X   (setq calc-vector-brackets (if (equal calc-vector-brackets "{}") nil "{}"))
X   (calc-refresh))
X)
X
X(defun calc-vector-parens ()
X  "Surround vectors and matrices with parentheses.
XIf already using parens, turn the parens off."
X  (interactive)
X  (calc-wrapper
X   (setq calc-vector-brackets (if (equal calc-vector-brackets "()") nil "()"))
X   (calc-refresh))
X)
X
X(defun calc-pack (n)
X  "Pack the top two numbers on the Calculator stack into a complex number.
XGiven a numeric prefix, pack the top N numbers into a vector.
XGiven a -1 prefix, pack the top 2 numbers into a rectangular complex number.
XGiven a -2 prefix, pack the top 2 numbers into a polar complex number.
XGiven a -3 prefix, pack the top 3 numbers into an HMS form.
XGiven a -4 prefix, pack the top 2 numbers into an error form.
XGiven a -5 prefix, pack the top 2 numbers into a modulo form.
XGiven a -6 prefix, pack the top 2 numbers into a [ .. ] interval form.
XGiven a -7 prefix, pack the top 2 numbers into a [ .. ) interval form.
XGiven a -8 prefix, pack the top 2 numbers into a ( .. ] interval form.
XGiven a -9 prefix, pack the top 2 numbers into a ( .. ) interval form."
X  (interactive "P")
X  (calc-wrapper
X   (let ((num (prefix-numeric-value n)))
X     (cond ((and n (>= num 0))
X	    (calc-enter-result num nil (cons 'vec (calc-top-list num))))
X	   ((= num -3)
X	    (let ((h (calc-top 3))
X		  (m (calc-top 2))
X		  (s (calc-top 1)))
X	      (if (and (math-num-integerp h)
X		       (math-num-integerp m))
X		  (calc-enter-result 3 nil (list 'hms h m s))
X		(error "Hours and minutes must be integers"))))
X	   ((= num -4)
X	    (let ((x (calc-top-n 2))
X		  (sigma (calc-top-n 1)))
X	      (if (and (or (math-anglep x) (not (math-objvecp x)))
X		       (or (math-anglep sigma) (not (math-objvecp sigma))))
X		  (calc-enter-result 2 nil (math-make-sdev x sigma))
X		(error "Components must be real"))))
X	   ((= num -5)
X	    (let ((a (calc-top-n 2))
X		  (m (calc-top-n 1)))
X	      (if (and (math-anglep a) (math-anglep m))
X		  (if (math-posp m)
X		      (calc-enter-result 2 nil (math-make-mod a m))
X		    (error "Modulus must be positive"))
X		(error "Components must be real"))))
X	   ((memq num '(-6 -7 -8 -9))
X	    (let ((lo (calc-top-n 2))
X		  (hi (calc-top-n 1)))
X	      (if (and (or (math-anglep lo) (not (math-objvecp lo)))
X		       (or (math-anglep hi) (not (math-objvecp hi))))
X		  (calc-enter-result 2 nil (math-make-intv (+ num 6) lo hi))
X		(error "Components must be real"))))
X	   ((or (= num -2)
X		(and (eq calc-complex-mode 'polar)
X		     (= num 0)))
X	    (let ((r (calc-top 2))
X		  (theta (calc-top 1)))
X	      (if (and (math-realp r) (math-anglep theta))
X		  (calc-enter-result 2 nil (list 'polar r theta))
X		(error "Components must be real"))))
X	   (t
X	    (let ((real (calc-top 2))
X		  (imag (calc-top 1)))
X	      (if (and (math-realp real) (math-realp imag))
X		  (calc-enter-result 2 nil (list 'cplx real imag))
X		(error "Components must be real")))))))
X)
X
X(defun calc-unpack ()
X  "Unpack complex number, vector, HMS form, error form, etc. at top of stack."
X  (interactive)
X  (calc-wrapper
X   (let ((num (calc-top)))
X     (if (or (and (not (memq (car-safe num) '(cplx polar vec hms sdev mod)))
X		  (math-objvecp num))
X	     (eq (car-safe num) 'var))
X	 (error "Argument must be a vector, complex number, or HMS, error, or modulo form"))
X     (calc-pop-push-list 1 (cdr num))))
X)
X
X(defun calc-diag (n)
X  "Build an NxN element diagonal matrix out of top-of-stack.
XIf top-of-stack is a vector, numeric prefix N must match or be omitted.
XIf top-of-stack is a scalar, numeric prefix N is required."
X  (interactive "P")
X  (calc-wrapper
X   (calc-enter-result 1 "diag" (if n
X				   (list 'calcFunc-diag (calc-top-n 1)
X					 (prefix-numeric-value n))
X				 (list 'calcFunc-diag (calc-top-n 1)))))
X)
X
X(defun calc-ident (n)
X  "Push an NxN element identity matrix on the stack."
X  (interactive "NDimension of identity matrix = ")
X  (calc-wrapper
X   (calc-enter-result 0 "idn" (list 'calcFunc-diag 1
X				    (prefix-numeric-value n))))
X)
X
X(defun calc-index (n)
X  "Generate a vector of the form [1, 2, ..., N]."
X  (interactive "NSize of vector = ")
X  (calc-wrapper
X   (calc-enter-result 0 "indx" (list 'calcFunc-index
X				     (prefix-numeric-value n))))
X)
X
X(defun calc-build-vector (n)
X  "Generate a vector of N copies of top-of-stack."
X  (interactive "NSize of vector = ")
X  (calc-wrapper
X   (calc-enter-result 1 "bldv" (list 'calcFunc-cvec
X				     (calc-top-n 1)
X				     (prefix-numeric-value n))))
X)
X
X(defun calc-vlength (arg)
X  "Replace a vector with its length, in the form of an integer."
X  (interactive "P")
X  (calc-wrapper
X   (calc-unary-op "len" 'calcFunc-vlen arg))
X)
X
X(defun calc-arrange-vector (n)
X  "Rearrange a matrix to have a specific number of columns."
X  (interactive "NNumber of columns = ")
X  (calc-wrapper
X   (calc-enter-result 1 "arng" (list 'calcFunc-arrange (calc-top-n 1)
X				     (prefix-numeric-value n))))
X)
X
X(defun calc-sort ()
X  "Sort the matrix at top of stack into increasing order.
XWith Inverse flag or a negative numeric prefix, sort into decreasing order."
X  (interactive)
X  (calc-slow-wrapper
X   (if (calc-is-inverse)
X       (calc-enter-result 1 "rsrt" (list 'calcFunc-rsort (calc-top-n 1)))
X     (calc-enter-result 1 "sort" (list 'calcFunc-sort (calc-top-n 1)))))
X)
X
X(defun calc-histogram (n)
X  "Compile a histogram of a vector of integers in the range [0..N).
XN is the numeric prefix argument.
XWith Hyperbolic flag, top-of-stack is a vector of weights to associate
Xwith elements of next-to-top."
X  (interactive "NNumber of bins: ")
X  (calc-slow-wrapper
X   (if calc-hyperbolic-flag
X       (calc-enter-result 2 "hist" (list 'calcFunc-histogram
X					 (calc-top-n 2)
X					 (calc-top-n 1)
X					 (prefix-numeric-value n)))
X     (calc-enter-result 1 "hist" (list 'calcFunc-histogram
X				       (calc-top-n 1)
X				       1
X				       (prefix-numeric-value n)))))
X)
X
X(defun calc-transpose (arg)
X  "Replace the matrix at top of stack with its transpose."
X  (interactive "P")
X  (calc-wrapper
X   (calc-unary-op "trn" 'calcFunc-trn arg))
X)
X
X(defun calc-conj-transpose (arg)
X  "Replace the matrix at top of stack with its conjugate transpose."
X  (interactive "P")
X  (calc-wrapper
X   (calc-unary-op "ctrn" 'calcFunc-ctrn arg))
X)
X
X(defun calc-cross (arg)
X  "Compute the right-handed cross product of two 3-vectors."
X  (interactive "P")
X  (calc-wrapper
X   (calc-binary-op "cros" 'calcFunc-cross arg))
X)
X
X(defun calc-mdet (arg)
X  "Compute the determinant of the square matrix on the top of the stack."
X  (interactive "P")
X  (calc-slow-wrapper
X   (calc-unary-op "mdet" 'calcFunc-det arg))
X)
X
X(defun calc-mtrace (arg)
X  "Compute the trace of the square matrix on the top of the stack."
X  (interactive "P")
X  (calc-slow-wrapper
X   (calc-unary-op "mtr" 'calcFunc-tr arg))
X)
X
X(defun calc-mlud (arg)
X  "Perform an L-U decomposition of the matrix on the top of the stack.
XResult is a vector of two matrices, L and U."
X  (interactive "P")
X  (calc-slow-wrapper
X   (calc-unary-op "mlud" 'calcFunc-lud arg))
X)
X
X(defun calc-rnorm (arg)
X  "Compute the row norm of the vector or matrix on the top of the stack.
XThis is the maximum row-absolute-value-sum of the matrix.
XFor a vector, this is the maximum of the absolute values of the elements."
X  (interactive "P")
X  (calc-wrapper
X   (calc-unary-op "rnrm" 'calcFunc-rnorm arg))
X)
X
X(defun calc-cnorm (arg)
X  "Compute the column norm of the vector or matrix on the top of the stack.
XThis is the maximum column-absolute-value-sum of the matrix.
XFor a vector, this is the sum of the absolute values of the elements."
X  (interactive "P")
X  (calc-wrapper
X   (calc-unary-op "cnrm" 'calcFunc-cnorm arg))
X)
X
X(defun calc-mrow (n)
X  "Replace matrix at top of stack with its Nth row.
XNumeric prefix N must be between 1 and the height of the matrix.
XIf top of stack is a non-matrix vector, extract its Nth element.
XIf N is negative, remove the Nth row (or element)."
X  (interactive "NRow number: ")
X  (calc-wrapper
X   (setq n (prefix-numeric-value n))
X   (if (= n 0)
X       (calc-enter-result 1 "getd" (list 'calcFunc-getdiag (calc-top-n 1)))
X     (if (< n 0)
X	 (calc-enter-result 1 "rrow" (list 'calcFunc-mrrow
X					   (calc-top-n 1) (- n)))
X       (calc-enter-result 1 "mrow" (list 'calcFunc-mrow (calc-top-n 1) n)))))
X)
X
X(defun calc-mcol (n)
X  "Replace matrix at top of stack with its Nth column.
XNumeric prefix N must be between 1 and the width of the matrix.
XIf top of stack is a non-matrix vector, extract its Nth element.
XIf N is negative, remove the Nth column (or element)."
X  (interactive "NColumn number: ")
X  (calc-wrapper
X   (setq n (prefix-numeric-value n))
X   (if (= n 0)
X       (calc-enter-result 1 "getd" (list 'calcFunc-getdiag (calc-top-n 1)))
X     (if (< n 0)
X	 (calc-enter-result 1 "rcol" (list 'calcFunc-mrcol
X					   (calc-top-n 1) (- n)))
X       (calc-enter-result 1 "mcol" (list 'calcFunc-mcol (calc-top-n 1) n)))))
X)
X
X(defun calc-apply (&optional oper)
X  "Apply an operator to the elements of a vector.
XFor example, applying f to [1, 2, 3] produces f(1, 2, 3)."
X  (interactive)
X  (calc-wrapper
X   (let* ((calc-dollar-values (mapcar 'car-safe
X				      (nthcdr calc-stack-top calc-stack)))
X	  (calc-dollar-used 0)
X	  (oper (or oper (calc-get-operator "Apply"
X					    (and (math-vectorp (calc-top 1))
X						 (1- (length (calc-top 1)))))))
X	  (expr (calc-top-n (1+ calc-dollar-used))))
X     (message "Working...")
X     (calc-set-command-flag 'clear-message)
X     (calc-enter-result (1+ calc-dollar-used)
X			(concat (substring "apl" 0 (- 4 (length (nth 2 oper))))
X				(nth 2 oper))
X			(list 'calcFunc-apply
X			      (math-calcFunc-to-var (nth 1 oper))
X			      expr))))
X)
X
X(defun calc-reduce (&optional oper)
X  "Apply a binary operator across all elements of a vector.
XFor example, applying + computes the sum of vector elements."
X  (interactive)
X  (calc-wrapper
X   (let* ((calc-dollar-values (mapcar 'car-safe
X				      (nthcdr calc-stack-top calc-stack)))
X	  (calc-dollar-used 0)
X	  (oper (or oper (calc-get-operator "Reduce" 2))))
X     (message "Working...")
X     (calc-set-command-flag 'clear-message)
X     (calc-enter-result (1+ calc-dollar-used)
X			(concat (substring "red" 0 (- 4 (length (nth 2 oper))))
X				(nth 2 oper))
X			(list (intern (concat "calcFunc-reduce"
X					      (or calc-mapping-dir "")))
X			      (math-calcFunc-to-var (nth 1 oper))
X			      (calc-top-n (1+ calc-dollar-used))))))
X)
X
X(defun calc-map (&optional oper)
X  "Apply an operator elementwise to one or two vectors.
XFor example, applying * computes a vector of products."
X  (interactive)
X  (calc-wrapper
X   (let* ((calc-dollar-values (mapcar 'car-safe
X				      (nthcdr calc-stack-top calc-stack)))
X	  (calc-dollar-used 0)
X	  (oper (or oper (calc-get-operator "Map")))
X	  (nargs (if (or (equal calc-mapping-dir "a")
X			 (equal calc-mapping-dir "d"))
X		     1
X		   (car oper))))
X     (message "Working...")
X     (calc-set-command-flag 'clear-message)
X     (calc-enter-result (+ nargs calc-dollar-used)
X			(concat (substring "map" 0 (- 4 (length (nth 2 oper))))
X				(nth 2 oper))
X			(cons (intern (concat "calcFunc-map"
X					      (or calc-mapping-dir "")))
X			      (cons (math-calcFunc-to-var (nth 1 oper))
X				    (calc-top-list-n
X				     nargs
X				     (1+ calc-dollar-used)))))))
X)
X
X;;; Return a list of the form (nargs func name)
X(defun calc-get-operator (msg &optional nargs)
X  (let ((inv nil) (hyp nil) (prefix nil)
X	done key oper (which 0)
X	(msgs '( "(Press ? for help)"
X		 "+, -, *, /, ^, %, \\, :, !, |, Neg"
X		 "SHIFT + Abs, conJ, arG; maX, miN; Floor, Round; sQrt"
X		 "SHIFT + Inv, Hyp; Sin, Cos, Tan; Exp, Ln, logB"
X		 "Binary + And, Or, Xor, Diff; Not, Clip"
X		 "Conversions + Deg, Rad, HMS; Float; SHIFT + Fraction"
X		 "Kombinatorics + Dfact, Lcm, Gcd, Binomial, Perms; Random"
X		 "Matrix-dir + Elements, Rows, Cols, Across, Down"
X		 "X or Z = any function by name; ' = alg entry; $ = stack")))
X    (while (not done)
X      (message "%s%s: %s: %s%s%s"
X	       msg
X	       (cond ((equal calc-mapping-dir "r") " rows")
X		     ((equal calc-mapping-dir "c") " columns")
X		     ((equal calc-mapping-dir "a") " across")
X		     ((equal calc-mapping-dir "d") " down")
X		     (t ""))
X	       (nth which msgs)
X	       (if inv "Inv " "") (if hyp "Hyp " "")
X	       (if prefix (concat (char-to-string prefix) "-") ""))
X      (setq key (read-char))
X      (cond ((= key ?\C-g)
X	     (keyboard-quit))
X	    ((= key ??)
X	     (setq which (% (1+ which) (length msgs))))
X	    ((= key ?I)
X	     (setq inv (not inv)
X		   prefix nil))
X	    ((= key ?H)
X	     (setq hyp (not hyp)
X		   prefix nil))
X	    ((eq key prefix)
X	     (setq prefix nil))
X	    ((and (memq key '(?b ?c ?k ?m)) (null prefix))
X	     (setq inv nil hyp nil
X		   prefix key))
X	    ((eq prefix ?m)
X	     (setq prefix nil)
X	     (if (eq key ?e)
X		 (setq calc-mapping-dir nil)
X	       (if (memq key '(?r ?c ?a ?d))
X		   (setq calc-mapping-dir (char-to-string key))
X		 (beep))))
X	    ((memq key '(?\$ ?\'))
X	     (let ((expr (if (eq key ?\$)
X			     (progn
X			       (setq calc-dollar-used 1)
X			       (if calc-dollar-values
X				   (list (car calc-dollar-values))
X				 (error "Stack underflow")))
X			   (calc-do-alg-entry "" "Function: ")))
X		   (arglist nil))
X	       (if (/= (length expr) 1)
X		   (error "Bad format"))
X	       (if (eq (car-safe (car expr)) 'calcFunc-lambda)
X		   (setq oper (list "$" (- (length (car expr)) 2) (car expr))
X			 done t)
X		 (calc-default-formula-arglist (car expr))
X		 (setq arglist (sort arglist 'string-lessp)
X		       arglist (read-from-minibuffer
X				"Function argument list: "
X				(if arglist
X				    (prin1-to-string arglist)
X				  "()")
X				minibuffer-local-map
X				t))
X		 (setq oper (list "$"
X				  (length arglist)
X				  (append '(calcFunc-lambda)
X					  (mapcar
X					   (function
X					    (lambda (x)
X					      (list 'var
X						    x
X						    (intern
X						     (concat
X						      "var-"
X						      (symbol-name x))))))
X					   arglist)
X					  expr))
X		       done t))))
X	    ((setq oper (assq key (cond ((eq prefix ?b) calc-b-oper-keys)
X					((eq prefix ?c) calc-c-oper-keys)
X					((eq prefix ?k) calc-k-oper-keys)
X					(inv (if hyp
X						 calc-inv-hyp-oper-keys
X					       calc-inv-oper-keys))
X					(t (if hyp
X					       calc-hyp-oper-keys
X					     calc-oper-keys)))))
X	     (if (eq (nth 1 oper) 'user)
X		 (let ((func (intern
X			      (completing-read "Function name: "
X					       obarray 'fboundp
X					       nil "calcFunc-"))))
X		   (if nargs
X		       (setq oper (list "z" nargs func)
X			     done t)
X		     (if (and (fboundp func)
X			      (consp (symbol-function func)))
X			 (let* ((defn (symbol-function func))
X				(args (nth 1 defn)))
X			   (if (and (eq (car defn) 'lambda)
X				    args
X				    (not (memq (car args)
X					       '(&optional &rest)))
X				    (or (memq (nth 2 args)
X					      '(&optional &rest nil))
X					(memq (nth 1 args)
X					      '(&optional &rest))))
X			       (setq oper (list "z"
X						(if (memq (nth 1 args)
X							  '(&optional
X							    &rest nil))
X						    1 2)
X						func)
X				     done t)
X			     (error "Function is not suitable for this operation")))
X		       (message "Number of arguments: ")
X		       (let ((nargs (read-char)))
X			 (if (and (>= nargs ?0) (<= nargs ?9))
X			     (setq oper (list "z" (- nargs ?0) func)
X				   done t)
X			   (beep))))))
X	       (setq done t)))
X	    (t (beep))))
X    (and nargs
X	 (/= nargs (nth 1 oper))
X	 (error "Must be a %d-argument operator" nargs))
X    (append (cdr oper)
X	    (list
X	     (concat (if prefix (char-to-string prefix) "")
X		     (if inv "I" "") (if hyp "H" "")
X		     (char-to-string key)))))
X)
X
X(defconst calc-oper-keys '( ( ?+ 2 calcFunc-add )
X			    ( ?- 2 calcFunc-sub )
X			    ( ?* 2 calcFunc-mul )
X			    ( ?/ 2 calcFunc-div )
X			    ( ?^ 2 calcFunc-pow )
X			    ( ?| 2 calcFunc-vconcat )
X			    ( ?% 2 calcFunc-mod )
X			    ( ?\\ 2 calcFunc-idiv )
X			    ( ?: 2 calcFunc-fdiv )
X			    ( ?! 1 calcFunc-fact )
X			    ( ?n 1 calcFunc-neg )
X			    ( ?x user )
X			    ( ?z user )
X			    ( ?A 1 calcFunc-abs )
X			    ( ?J 1 calcFunc-conj )
X			    ( ?G 1 calcFunc-arg )
X			    ( ?Q 1 calcFunc-sqrt )
X			    ( ?N 2 calcFunc-min )
X			    ( ?X 2 calcFunc-max )
X			    ( ?F 1 calcFunc-floor )
X			    ( ?R 1 calcFunc-round )
X			    ( ?S 1 calcFunc-sin )
X			    ( ?C 1 calcFunc-cos )
X			    ( ?T 1 calcFunc-tan )
X			    ( ?L 1 calcFunc-ln )
X			    ( ?E 1 calcFunc-exp )
X			    ( ?B 2 calcFunc-log )
X))
X(defconst calc-b-oper-keys '( ( ?a 2 calcFunc-and )
X			      ( ?o 2 calcFunc-or )
X			      ( ?x 2 calcFunc-xor )
X			      ( ?d 2 calcFunc-diff )
X			      ( ?n 1 calcFunc-not )
X			      ( ?c 1 calcFunc-clip )
X))
X(defconst calc-c-oper-keys '( ( ?d 1 calcFunc-deg )
X			      ( ?r 1 calcFunc-rad )
X			      ( ?h 1 calcFunc-hms )
X			      ( ?f 1 calcFunc-float )
X			      ( ?F 1 calcFunc-frac )
X))
X(defconst calc-k-oper-keys '( ( ?g 2 calcFunc-gcd )
X			      ( ?l 2 calcFunc-lcm )
X			      ( ?b 2 calcFunc-choose )
X			      ( ?d 1 calcFunc-dfact )
X			      ( ?m 1 calcFunc-moebius )
X			      ( ?p 2 calcFunc-perm )
X			      ( ?r 1 calcFunc-random )
X			      ( ?t 1 calcFunc-totient )
X))
X(defconst calc-inv-oper-keys '( ( ?F 1 calcFunc-ceil )
X				( ?R 1 calcFunc-trunc )
X				( ?Q 1 calcFunc-sqr )
X				( ?S 1 calcFunc-arcsin )
X				( ?C 1 calcFunc-arccos )
X				( ?T 1 calcFunc-arctan )
X				( ?L 1 calcFunc-exp )
X				( ?E 1 calcFunc-ln )
X))
X(defconst calc-hyp-oper-keys '( ( ?F 1 calcFunc-ffloor )
X				( ?R 1 calcFunc-fround )
X				( ?S 1 calcFunc-sinh )
X				( ?C 1 calcFunc-cosh )
X				( ?T 1 calcFunc-tanh )
X				( ?L 1 calcFunc-log10 )
X				( ?E 1 calcFunc-exp10 )
X))
X(defconst calc-inv-hyp-oper-keys '( ( ?F 1 calcFunc-fceil )
X				    ( ?R 1 calcFunc-ftrunc )
X				    ( ?S 1 calcFunc-arcsinh )
X				    ( ?C 1 calcFunc-arccosh )
X				    ( ?T 1 calcFunc-arctanh )
X				    ( ?L 1 calcFunc-exp10 )
X				    ( ?E 1 calcFunc-log10 )
X))
X
X
X
X
X;;; User menu.
X
X(defun calc-user-key-map ()
X  (cdr (elt calc-mode-map ?z))
X)
X
X(defun calc-z-prefix-help ()
X  (interactive)
X  (let* ((msgs nil)
X	 (buf "")
X	 (kmap (sort (copy-sequence (calc-user-key-map))
X		     (function (lambda (x y) (< (car x) (car y))))))
X	 (flags (apply 'logior
X		       (mapcar (function
X				(lambda (k)
X				  (calc-user-function-classify (car k))))
X			       kmap))))
X    (if (= (logand flags 8) 0)
X	(calc-user-function-list kmap 7)
X      (calc-user-function-list kmap 1)
SHAR_EOF
echo "End of part 5"
echo "File calc-ext.el is continued in part 6"
echo "6" > s2_seq_.tmp
exit 0