[comp.sources.misc] v13i028: Emacs Calculator 1.01, part 02/19

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

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

---- Cut Here and unpack ----
#!/bin/sh
# this is part 2 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file calc.el continued
#
CurArch=2
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.el"
sed 's/^X//' << 'SHAR_EOF' >> calc.el
X)
X
X(defun calc-record (val &optional prefix)
X  (or calc-executing-macro
X      (let* ((mainbuf (current-buffer))
X	     (buf (get-buffer-create "*Calc Trail*"))
X	     (calc-display-raw (eq calc-display-raw t))
X	     (fval (if val
X		       (if (stringp val)
X			   val
X			 (math-showing-full-precision
X			  (math-format-flat-expr val 0)))
X		     "")))
X	(save-excursion
X	  (set-buffer buf)
X	  (if (not (eq major-mode 'calc-trail-mode))
X	      (calc-trail-mode mainbuf))
X	  (let ((aligned (calc-check-trail-aligned))
X		(buffer-read-only nil))
X	    (goto-char (point-max))
X	    (cond ((null prefix) (insert "     "))
X		  ((> (length prefix) 5) (insert (substring prefix 0 5) " "))
X		  (t (insert (format "%4s " prefix))))
X	    (insert fval "\n")
X	    (let ((win (get-buffer-window buf)))
X	      (if (and aligned win (not (memq 'hold-trail calc-command-flags)))
X		  (progn
X		    (calc-trail-here))))
X	    (goto-char (1- (point-max)))))))
X  val
X)
X
X(defun calc-record-list (vals &optional prefix)
X  (while vals
X    (or (eq (car vals) 'top-of-stack)
X	(progn
X	  (calc-record (car vals) prefix)
X	  (setq prefix "...")))
X    (setq vals (cdr vals)))
X)
X
X(defun calc-trail-display (flag &optional no-refresh)
X  "Turn the Trail display on or off.
XWith prefix argument 1, turn it on; with argument 0, turn it off."
X  (interactive "P")
X  (let* ((trail (get-buffer-create "*Calc Trail*"))
X	 (win (get-buffer-window trail)))
X    (if (setq calc-display-trail
X	      (not (if flag (memq flag '(nil 0)) win)))
X	(if (null win)
X	    (progn
X	      (if (and (boundp 'calc-trail-window-hook) calc-trail-window-hook)
X		  (run-hooks 'calc-trail-window-hook)
X		(let ((w (split-window nil (/ (* (window-width) 2) 3) t)))
X		  (set-window-buffer w trail)))
X	      (calc-wrapper
X	       (or no-refresh
X		   (calc-refresh)))))
X      (if win
X	  (progn
X	    (delete-window win)
X	    (calc-wrapper
X	     (or no-refresh
X		 (calc-refresh)))))
X      (if (and (boundp 'overlay-arrow-position)
X	       (eq overlay-arrow-position calc-trail-pointer))
X	  (setq overlay-arrow-position nil)))
X    trail)
X)
X
X(defun calc-trail-here ()
X  "Move the trail pointer to the current cursor line."
X  (interactive)
X  (if (eq major-mode 'calc-trail-mode)
X      (progn
X	(beginning-of-line)
X	(if (bobp)
X	    (forward-line 1)
X	  (if (eobp)
X	      (forward-line -1)))
X	(if (or (bobp) (eobp))
X	    (setq overlay-arrow-position nil)   ; trail is empty
X	  (set-marker calc-trail-pointer (point) (current-buffer))
X	  (setq overlay-arrow-string (concat (buffer-substring (point)
X							       (+ (point) 4))
X					     ">")
X		overlay-arrow-position calc-trail-pointer)
X	  (forward-char 4)
X	  (let ((win (get-buffer-window (current-buffer))))
X	    (if win
X		(save-excursion
X		  (forward-line (/ (window-height) 2))
X		  (forward-line (- 1 (window-height)))
X		  (set-window-start win (point))
X		  (set-window-point win (+ calc-trail-pointer 4)))))))
X    (error "Not in Calc Trail buffer"))
X)
X
X
X
X
X;;;; The Undo list.
X
X(defun calc-record-undo (rec)
X  (or calc-executing-macro
X      (if (memq 'undo calc-command-flags)
X	  (setq calc-undo-list (cons (cons rec (car calc-undo-list))
X				     (cdr calc-undo-list)))
X	(setq calc-undo-list (cons (list rec) calc-undo-list)
X	      calc-redo-list nil)
X	(calc-set-command-flag 'undo)))
X)
X
X
X
X;;; Arithmetic commands.
X
X(defun calc-binary-op (name func arg &optional ident unary)
X  (if (null arg)
X      (calc-enter-result 2 name (cons func (calc-top-list-n 2)))
X    (calc-extensions)
X    (calc-binary-op-fancy name func arg ident unary))
X)
X
X(defun calc-unary-op (name func arg)
X  (if (null arg)
X      (calc-enter-result 1 name (list func (calc-top-n 1)))
X    (calc-extensions)
X    (calc-unary-op-fancy name func arg))
X)
X
X
X(defun calc-plus (arg)
X  "Add the top two elements of the Calculator stack."
X  (interactive "P")
X  (calc-slow-wrapper
X   (calc-binary-op "+" 'calcFunc-add arg 0))
X)
X
X(defun calc-minus (arg)
X  "Subtract the top two elements of the Calculator stack."
X  (interactive "P")
X  (calc-slow-wrapper
X   (calc-binary-op "-" 'calcFunc-sub arg 0 'calcFunc-neg))
X)
X
X(defun calc-times (arg)
X  "Multiply the top two elements of the Calculator stack."
X  (interactive "P")
X  (calc-slow-wrapper
X   (calc-binary-op "*" 'calcFunc-mul arg 1))
X)
X
X(defun calc-divide (arg)
X  "Divide the top two elements of the Calculator stack."
X  (interactive "P")
X  (calc-slow-wrapper
X   (calc-binary-op "/" 'calcFunc-div arg 0 'calcFunc-inv))
X)
X
X(defun calc-power (arg)
X  "Compute y^x for the top two elements of the Calculator stack."
X  (interactive "P")
X  (calc-slow-wrapper
X   (calc-binary-op "^" 'calcFunc-pow arg))
X)
X
X(defun calc-mod (arg)
X  "Compute the modulo of the top two elements of the Calculator stack."
X  (interactive "P")
X  (calc-slow-wrapper
X   (calc-binary-op "%" 'calcFunc-mod arg))
X)
X
X(defun calc-inv (arg)
X  "Invert the number or square matrix on the top of the stack."
X  (interactive "P")
X  (calc-slow-wrapper
X   (calc-unary-op "inv" 'calcFunc-inv arg))
X)
X
X(defun calc-change-sign (arg)
X  "Change the sign of the top element of the Calculator stack."
X  (interactive "P")
X  (calc-wrapper
X   (calc-unary-op "chs" 'calcFunc-neg arg))
X)
X
X
X
X;;; Stack management commands.
X
X(defun calc-enter (n)
X  "Duplicate the top N elements of the Calculator stack.
XWith a negative argument -N, duplicate the Nth element of the stack."
X  (interactive "p")
X  (calc-wrapper
X   (cond ((< n 0)
X	  (calc-push (calc-top (- n))))
X	 ((= n 0)
X	  (calc-push-list (calc-top-list (calc-stack-size))))
X	 (t
X	  (calc-push-list (calc-top-list n)))))
X)
X
X(defun calc-over (n)
X  "Duplicate the Nth element of the Calculator stack.
XWith a negative argument -N, duplicate the top N elements of the stack."
X  (interactive "P")
X  (if n
X      (calc-enter (- (prefix-numeric-value n)))
X    (calc-enter -2))
X)
X
X(defun calc-pop (n)
X  "Pop (and discard) the top N elements of the stack.
XWith a negative argument -N, remove the Nth element from the stack."
X  (interactive "P")
X  (calc-wrapper
X   (let* ((nn (prefix-numeric-value n))
X	  (top (and (null n) (calc-top 1))))
X     (cond ((and (null n)
X		 (eq (car-safe top) 'incomplete)
X		 (> (length top) (if (eq (nth 1 top) 'intv) 3 2)))
X	    (calc-pop-push 1 (let ((tt (copy-sequence top)))
X			       (setcdr (nthcdr (- (length tt) 2) tt) nil)
X			       tt)))
X	   ((< nn 0)
X	    (calc-pop-stack 1 (- nn)))
X	   ((= nn 0)
X	    (calc-pop-stack (calc-stack-size)))
X	   (t
X	    (calc-pop-stack nn)))))
X)
X
X(defun calc-roll-down (n)
X  "Exchange the top two elements of the Calculator stack.
XWith a numeric prefix, roll down the top N elements."
X  (interactive "P")
X  (calc-wrapper
X   (let ((nn (prefix-numeric-value n)))
X     (cond ((null n)
X	    (calc-roll-down-stack 2))
X	   ((> nn 0)
X	    (calc-roll-down-stack nn))
X	   ((= nn 0)
X	    (calc-pop-push-list (calc-stack-size)
X				(reverse
X				 (calc-top-list (calc-stack-size)))))
X	   (t
X	    (calc-roll-down-stack (calc-stack-size) (- nn))))))
X)
X
X(defun calc-roll-up (n)
X  "Roll up the top three elements of the Calculator stack.
XWith a numeric prefix, roll up the top N elements."
X  (interactive "P")
X  (calc-wrapper
X   (let ((nn (prefix-numeric-value n)))
X     (cond ((null n)
X	    (calc-roll-up-stack 3))
X	   ((> nn 0)
X	    (calc-roll-up-stack nn))
X	   ((= nn 0)
X	    (calc-pop-push-list (calc-stack-size)
X				(reverse
X				 (calc-top-list (calc-stack-size)))))
X	   (t
X	    (calc-roll-up-stack (calc-stack-size) (- nn))))))
X)
X
X
X
X
X;;; Miscellaneous commands.
X
X(defun calc-precision (n)
X  "Display current float precision for Calculator, or set precision to N digits."
X  (interactive "NPrecision: ")
X  (calc-wrapper
X   (if (< (prefix-numeric-value n) 3)
X       (error "Precision must be at least 3 digits.")
X     (setq calc-internal-prec (prefix-numeric-value n))
X     (calc-record calc-internal-prec "prec"))
X   (message "Floating-point precision is %d digits." calc-internal-prec))
X)
X
X
X(defun calc-num-prefix-name (n)
X  (cond ((eq n '-) "- ")
X	((equal n '(4)) "C-u ")
X	((consp n) (format "%d " (car n)))
X	((integerp n) (format "%d " n))
X	(t ""))
X)
X
X(defun calc-missing-key (n)
X  "This is a placeholder for a command which needs to be loaded from calc-ext.
XWhen this key is used, calc-ext (the Calculator extensions module) will be
Xloaded and the keystroke automatically re-typed."
X  (interactive "P")
X  (calc-extensions)
X  (if (keymapp (key-binding (char-to-string last-command-char)))
X      (message "%s%c-" (calc-num-prefix-name n) last-command-char))
X  (setq unread-command-char last-command-char
X	prefix-arg n)
X)
X
X(defun calc-why ()
X  "Explain why the last result was unusual."
X  (interactive)
X  (if (not (eq this-command last-command))
X      (setq calc-which-why calc-why))
X  (if calc-which-why
X      (progn
X	(calc-explain-why (car calc-which-why))
X	(setq calc-which-why (cdr calc-which-why)))
X    (if calc-why
X	(progn
X	  (message "(No further explanations available)")
X	  (setq calc-which-why calc-why))
X      (message "No explanations available")))
X)
X(setq calc-which-why nil)
X
X(defun calc-flush-caches ()
X  "Clear all caches used internally by the Calculator, such as the values of
Xpi and e.  These values will be recomputed next time they are requested."
X  (interactive)
X  (calc-wrapper
X   (setq math-lud-cache nil
X	 math-log2-cache nil
X	 math-max-digits-cache nil
X	 math-integral-cache nil
X	 math-units-table nil)
X   (mapcar (function (lambda (x) (set x -100))) math-cache-list)
X   (message "All internal calculator caches have been reset."))
X)
X(setq math-cache-list nil)
X
X
X
X;;;; Reading an expression in algebraic form.
X
X(defun calc-algebraic-entry ()
X  "Read an algebraic expression (e.g., 1+2*3) and push the result on the stack."
X  (interactive)
X  (calc-wrapper
X   (calc-alg-entry))
X)
X
X(defun calc-auto-alg-entry ()
X  "Begin entering an algebraic expression with a '$' or '\"' character."
X  (interactive)
X  (calc-wrapper
X   (calc-alg-entry (char-to-string last-command-char)))
X)
X
X(defun calc-alg-entry (&optional initial prompt)
X  (let* ((calc-dollar-values (mapcar 'car-safe
X				     (nthcdr calc-stack-top calc-stack)))
X	 (calc-dollar-used 0)
X	 (alg-exp (calc-do-alg-entry initial prompt t)))
X    (let ((nvals (mapcar 'calc-normalize alg-exp)))
X      (while alg-exp
X	(calc-record (car alg-exp) "alg'")
X	(calc-pop-push-record calc-dollar-used "" (car nvals))
X	(setq alg-exp (cdr alg-exp)
X	      nvals (cdr nvals)
X	      calc-dollar-used 0)))
X    (calc-handle-whys))
X)
X
X(defun calc-do-alg-entry (&optional initial prompt no-normalize)
X  (let* ((alg-exp 'error)
X	 (alg (read-from-minibuffer (or prompt "Algebraic: ")
X				    (or initial "")
X				    calc-alg-ent-map nil)))
X    (if (eq alg-exp 'error)
X	(if (eq (car (setq alg-exp (math-read-exprs alg)))
X		'error)
X	    (error "Error: %s" (or (nth 2 exp) "Bad format"))))
X    (or no-normalize
X	(setq alg-exp (mapcar 'calc-normalize alg-exp)))
X    alg-exp)
X)
X
X(defvar calc-alg-ent-map nil "Keymap for use by the calc-algebraic-entry command.")
X(if calc-alg-ent-map
X    ()
X  (setq calc-alg-ent-map (copy-keymap minibuffer-local-map))
X  (define-key calc-alg-ent-map "'" 'calcAlg-previous)
X  (define-key calc-alg-ent-map "\ep" 'calcAlg-plus-minus)
X  (define-key calc-alg-ent-map "\em" 'calcAlg-mod)
X  (define-key calc-alg-ent-map "\C-m" 'calcAlg-enter)
X  (define-key calc-alg-ent-map "\C-j" 'calcAlg-enter)
X)
X
X(defun calcAlg-plus-minus ()
X  (interactive)
X  (if (calc-minibuffer-contains ".* \\'")
X      (insert "+/- ")
X    (insert " +/- "))
X)
X
X(defun calcAlg-mod ()
X  (interactive)
X  (if (not (calc-minibuffer-contains ".* \\'"))
X      (insert " "))
X  (if (calc-minibuffer-contains ".* mod +\\'")
X      (if calc-previous-modulo
X	  (insert (math-format-flat-expr calc-previous-modulo 0))
X	(beep))
X    (insert "mod "))
X)
X
X(defun calcAlg-previous ()
X  (interactive)
X  (if (calc-minibuffer-contains "\\`\\'")
X      (if calc-previous-alg-entry
X	  (insert calc-previous-alg-entry)
X	(beep))
X    (insert "'"))
X)
X
X(defun calcAlg-enter ()
X  (interactive)
X  (let ((exp (and (> (buffer-size) 0)
X		  (math-read-exprs (buffer-string)))))
X    (if (eq (car-safe exp) 'error)
X	(progn
X	  (goto-char (point-min))
X	  (forward-char (nth 1 exp))
X	  (beep)
X	  (calc-temp-minibuffer-message
X	   (concat " [" (or (nth 2 exp) "Error") "]"))
X	  (setq unread-command-char -1))
X      (setq alg-exp (if (calc-minibuffer-contains "\\` *\\[ *\\'")
X			'((incomplete vec))
X		      exp)
X	    calc-previous-alg-entry (buffer-string))
X      (exit-minibuffer)))
X)
X
X
X
X;;;; Reading a number using the minibuffer.
X
X(defun calcDigit-start ()
X  "Begin digit entry in the Calculator."
X  (interactive)
X  (calc-wrapper
X   (if calc-algebraic-mode
X       (cond ((eq last-command-char ?e) (calc-alg-entry "1e"))
X	     ((eq last-command-char ?#) (calc-alg-entry
X					 (format "%d#" calc-number-radix)))
X	     ((eq last-command-char ?_) (calc-alg-entry "-"))
X	     ((eq last-command-char ?@) (calc-alg-entry "0@ "))
X	     (t (calc-alg-entry (char-to-string last-command-char))))
X     (let ((calc-digit-value 'yow)
X	   (calc-prev-char nil)
X	   (calc-prev-prev-char nil))
X       (setq unread-command-char last-command-char)
X       (let ((str (read-from-minibuffer "Calc: " ""
X					calc-digit-map)))
X	 (if (eq calc-digit-value 'yow)
X	     (setq calc-digit-value (math-read-number str))))
X       (if (stringp calc-digit-value)
X	   (calc-alg-entry calc-digit-value)
X	 (if calc-digit-value
X	     (calc-push (calc-record (calc-normalize calc-digit-value)))))
X       (if (eq calc-prev-char 'dots)
X	   (progn
X	     (calc-extensions)
X	     (calc-dots))))))
X)
X
X(defun calcDigit-nondigit ()
X  (interactive)
X  (setq calc-digit-value (math-read-number (buffer-string)))
X  (if (and (null calc-digit-value) (> (buffer-size) 0))
X      (progn
X	(beep)
X	(calc-temp-minibuffer-message " [Bad format]"))
X    (or (memq last-command-char '(32 10 13))
X	(setq prefix-arg current-prefix-arg
X	      unread-command-char last-command-char))
X    (exit-minibuffer))
X)
X
X(defun calcDigit-algebraic ()
X  (interactive)
X  (if (calc-minibuffer-contains ".*[@oh] *[^'m ]+[^'m]*\\'")
X      (calcDigit-key)
X    (setq calc-digit-value (buffer-string))
X    (exit-minibuffer))
X)
X
X(defun calc-minibuffer-contains (rex)
X  (save-excursion
X    (goto-char (point-min))
X    (looking-at rex))
X)
X
X(defun calcDigit-key ()
X  (interactive)
X  (goto-char (point-max))
X  (if (or (and (memq last-command-char '(?+ ?-))
X	       (> (buffer-size) 0)
X	       (/= (preceding-char) ?e))
X	  (and (memq last-command-char '(?m ?s))
X	       (not (calc-minibuffer-contains "[-+]?[0-9]+\\.?0*[@oh].*"))
X	       (not (calc-minibuffer-contains "[-+]?\\(1[1-9]\\|[2-9][0-9]\\)#.*"))))
X      (calcDigit-nondigit)
X    (if (calc-minibuffer-contains "\\([-+]?\\|.* \\)\\'")
X	(cond ((memq last-command-char '(?. ?@)) (insert "0"))
X	      ((and (memq last-command-char '(?o ?h ?m))
X		    (not (calc-minibuffer-contains ".*#.*"))) (insert "0"))
X	      ((memq last-command-char '(?: ?e)) (insert "1"))
X	      ((eq last-command-char ?#)
X	       (insert (int-to-string calc-number-radix)))))
X    (if (and (calc-minibuffer-contains "\\([-+]?[0-9]+#\\|[^:]*:\\)\\'")
X	     (eq last-command-char ?:))
X	(insert "1"))
X    (if (or (and (memq last-command-char '(?e ?h ?o ?m ?s ?p))
X		 (calc-minibuffer-contains ".*#.*"))
X	    (and (eq last-command-char ?n)
X		 (calc-minibuffer-contains "[-+]?\\(2[4-9]\\|[3-9][0-9]\\)#.*")))
X	(setq last-command-char (upcase last-command-char)))
X    (cond
X     ((memq last-command-char '(?_ ?n))
X      (goto-char (point-min))
X      (if (and (search-forward " +/- " nil t)
X	       (not (search-forward "e" nil t)))
X	  (beep)
X	(and (not (calc-minibuffer-contains ".*#.*"))
X	     (search-forward "e" nil t))
X	(if (looking-at "+")
X	    (delete-char 1))
X	(if (looking-at "-")
X	    (delete-char 1)
X	  (insert "-")))
X      (goto-char (point-max)))
X     ((eq last-command-char ?p)
X      (if (or (calc-minibuffer-contains ".*\\+/-.*")
X	      (calc-minibuffer-contains ".*mod.*")
X	      (calc-minibuffer-contains ".*#.*")
X	      (calc-minibuffer-contains ".*[-+e:]\\'"))
X	  (beep)
X	(if (not (calc-minibuffer-contains ".* \\'"))
X	    (insert " "))
X	(insert "+/- ")))
X     ((and (eq last-command-char ?M)
X	   (not (calc-minibuffer-contains
X		 "[-+]?\\(2[3-9]\\|[3-9][0-9]\\)#.*")))
X      (if (or (calc-minibuffer-contains ".*\\+/-.*")
X	      (calc-minibuffer-contains ".*mod *[^ ]+")
X	      (calc-minibuffer-contains ".*[-+e:]\\'"))
X	  (beep)
X	(if (calc-minibuffer-contains ".*mod \\'")
X	    (if calc-previous-modulo
X		(insert (math-format-flat-expr calc-previous-modulo 0))
X	      (beep))
X	  (if (not (calc-minibuffer-contains ".* \\'"))
X	      (insert " "))
X	  (insert "mod "))))
X     (t
X      (insert (char-to-string last-command-char))
X      (if (or (and (calc-minibuffer-contains "[-+]?\\(.*\\+/- *\\|.*mod *\\)?\\([0-9][0-9]?\\)#[0-9a-zA-Z]*\\(:[0-9a-zA-Z]*\\)?\\(:[0-9a-zA-Z]*\\)?\\'")
X		   (let ((radix (string-to-int
X				 (buffer-substring
X				  (match-beginning 2) (match-end 2)))))
X		     (and (>= radix 2)
X			  (<= radix 36)
X			  (or (memq last-command-char '(?# ?:))
X			      (let ((dig (math-read-radix-digit
X					  (upcase last-command-char))))
X				(and dig
X				     (< dig radix)))))))
X	      (save-excursion
X		(goto-char (point-min))
X         	(looking-at
X		 "[-+]?\\(.*\\+/- *\\|.*mod *\\)?\\([0-9]+\\.?0*[@oh] *\\)?\\([0-9]+\\.?0*['m] *\\)?[0-9]*\\(\\.?[0-9]*\\(e[-+]?[0-9]*\\)?\\|[0-9]:\\([0-9]+:\\)?[0-9]*\\)?[\"s]?\\'")))
X	  (if (and (memq last-command-char '(?@ ?o ?h ?\' ?m))
X		   (string-match " " calc-hms-format))
X	      (insert " "))
X	(if (and (eq this-command last-command)
X		 (eq last-command-char ?.))
X	    (if (eq calc-prev-char ?.)
X		(progn
X		  (delete-backward-char 1)
X		  (if (calc-minibuffer-contains ".*\\.\\'")
X		      (delete-backward-char 1))
X		  (setq calc-prev-char 'dots
X			last-command-char 32)
X		  (if calc-prev-prev-char
X		      (calcDigit-nondigit)
X		    (setq calc-digit-value nil)
X		    (exit-minibuffer)))
X	      ;; just ignore extra decimal point, anticipating ".."
X	      (delete-backward-char 1))
X	  (delete-backward-char 1)
X	  (beep)
X	  (calc-temp-minibuffer-message " [Bad format]"))))))
X  (setq calc-prev-prev-char calc-prev-char
X	calc-prev-char last-command-char)
X)
X
X(defun calcDigit-letter ()
X  (interactive)
X  (if (calc-minibuffer-contains "[-+]?\\(1[1-9]\\|[2-9][0-9]\\)#.*")
X      (progn
X	(setq last-command-char (upcase last-command-char))
X	(calcDigit-key))
X    (calcDigit-nondigit))
X)
X
X(defun calcDigit-backspace ()
X  (interactive)
X  (goto-char (point-max))
X  (cond ((calc-minibuffer-contains ".* \\+/- \\'")
X	 (backward-delete-char 5))
X	((calc-minibuffer-contains ".* mod \\'")
X	 (backward-delete-char 5))
X	((calc-minibuffer-contains ".* \\'")
X	 (backward-delete-char 2))
X	(t (backward-delete-char 1)))
X  (if (= (buffer-size) 0)
X      (progn
X	(setq last-command-char 10)
X	(calcDigit-nondigit)))
X)
X
X(defun calc-temp-minibuffer-message (m)
X  "A Lisp version of temp_minibuffer_message from minibuf.c."
X  (let ((savemax (point-max)))
X    (save-excursion
X      (goto-char (point-max))
X      (insert m))
X    (let ((inhibit-quit t))
X      (sit-for 2)
X      (delete-region savemax (point-max))
X      (if quit-flag
X	  (setq quit-flag nil
X		unread-command-char 7))))
X)
X
X
X
X
X
X
X
X;;;; Arithmetic routines.
X;;;
X;;; An object as manipulated by one of these routines may take any of the
X;;; following forms:
X;;;
X;;; integer                 An integer.  For normalized numbers, this format
X;;;			    is used only for -999999 ... 999999.
X;;;
X;;; (bigpos N0 N1 N2 ...)   A big positive integer, N0 + N1*1000 + N2*10^6 ...
X;;; (bigneg N0 N1 N2 ...)   A big negative integer, - N0 - N1*1000 ...
X;;;			    Each digit N is in the range 0 ... 999.
X;;;			    Normalized, always at least three N present,
X;;;			    and the most significant N is nonzero.
X;;;
X;;; (frac NUM DEN)          A fraction.  NUM and DEN are small or big integers.
X;;;                         Normalized, DEN > 1.
X;;;
X;;; (float NUM EXP)         A floating-point number, NUM * 10^EXP;
X;;;                         NUM is a small or big integer, EXP is a small int.
X;;;			    Normalized, NUM is not a multiple of 10, and
X;;;			    abs(NUM) < 10^calc-internal-prec.
X;;;			    Normalized zero is stored as (float 0 0).
X;;;
X;;; (cplx REAL IMAG)        A complex number; REAL and IMAG are any of above.
X;;;			    Normalized, IMAG is nonzero.
X;;;
X;;; (polar R THETA)         Polar complex number.  Normalized, R > 0 and THETA
X;;;                         is neither zero nor 180 degrees (pi radians).
X;;;
X;;; (vec A B C ...)         Vector of objects A, B, C, ...  A matrix is a
X;;;                         vector of vectors.
X;;;
X;;; (hms H M S)             Angle in hours-minutes-seconds form.  All three
X;;;                         components have the same sign; H and M must be
X;;;                         numerically integers; M and S are expected to
X;;;                         lie in the range [0,60).
X;;;
X;;; (sdev X SIGMA)          Error form, X +/- SIGMA.  When normalized,
X;;;                         SIGMA > 0.  X and SIGMA are any real numbers,
X;;;                         or symbolic expressions which are assumed real.
X;;;
X;;; (intv MASK LO HI)       Interval form.  MASK is 0=(), 1=(], 2=[), or 3=[].
X;;;                         LO and HI are any real numbers, or symbolic
X;;;			    expressions which are assumed real, and LO < HI.
X;;;			    For [LO..HI], if LO = HI normalization produces LO,
X;;;			    and if LO > HI normalization produces [LO..LO).
X;;;			    For other intervals, if LO > HI normalization
X;;;			    sets HI equal to LO.
X;;;
X;;; (mod N M)	    	    Number modulo M.  When normalized, 0 <= N < M.
X;;;			    N and M are real numbers.
X;;;
X;;; (var V S)		    Symbolic variable.  V is a Lisp symbol which
X;;;			    represents the variable's visible name.  S is
X;;;			    the symbol which actually stores the variable's
X;;;			    value:  (var pi var-pi).
X;;;
X;;; In general, combining rational numbers in a calculation always produces
X;;; a rational result, but if either argument is a float, result is a float.
X
X;;; In the following comments, [x y z] means result is x, args must be y, z,
X;;; respectively, where the code letters are:
X;;;
X;;;    O  Normalized object (vector or number)
X;;;    V  Normalized vector
X;;;    N  Normalized number of any type
X;;;    N  Normalized complex number
X;;;    R  Normalized real number (float or rational)
X;;;    F  Normalized floating-point number
X;;;    T  Normalized rational number
X;;;    I  Normalized integer
X;;;    B  Normalized big integer
X;;;    S  Normalized small integer
X;;;    D  Digit (small integer, 0..999)
X;;;    L  Normalized bignum digit list (without "bigpos" or "bigneg" symbol)
X;;;       or normalized vector element list (without "vec")
X;;;    P  Predicate (truth value)
X;;;    X  Any Lisp object
X;;;    Z  "nil"
X;;;
X;;; Lower-case letters signify possibly un-normalized values.
X;;; "L.D" means a cons of an L and a D.
X;;; [N N; n n] means result will be normalized if argument is.
X;;; Also, [Public] marks routines intended to be called from outside.
X;;; [This notation has been neglected in many recent routines.]
X
X;;; Reduce an object to canonical (normalized) form.  [O o; Z Z] [Public]
X(defun math-normalize (a)
X  (cond
X   ((not (consp a))
X    (if (integerp a)
X	(if (or (>= a 1000000) (<= a -1000000))
X	    (math-bignum a)
X	  a)
X      a))
X   ((eq (car a) 'bigpos)
X    (if (eq (nth (1- (length a)) a) 0)
X	(let* ((last (setq a (copy-sequence a))) (digs a))
X	  (while (setq digs (cdr digs))
X	    (or (eq (car digs) 0) (setq last digs)))
X	  (setcdr last nil)))
X    (if (cdr (cdr (cdr a)))
X	a
X      (cond
X       ((cdr (cdr a)) (+ (nth 1 a) (* (nth 2 a) 1000)))
X       ((cdr a) (nth 1 a))
X       (t 0))))
X   ((eq (car a) 'bigneg)
X    (if (eq (nth (1- (length a)) a) 0)
X	(let* ((last (setq a (copy-sequence a))) (digs a))
X	  (while (setq digs (cdr digs))
X	    (or (eq (car digs) 0) (setq last digs)))
X	  (setcdr last nil)))
X    (if (cdr (cdr (cdr a)))
X	a
X      (cond
X       ((cdr (cdr a)) (- (+ (nth 1 a) (* (nth 2 a) 1000))))
X       ((cdr a) (- (nth 1 a)))
X       (t 0))))
X   ((eq (car a) 'frac)
X    (math-make-frac (math-normalize (nth 1 a))
X		    (math-normalize (nth 2 a))))
X   ((eq (car a) 'float)
X    (math-make-float (math-normalize (nth 1 a)) (nth 2 a)))
X   ((eq (car a) 'cplx)
X    (let ((real (math-normalize (nth 1 a)))
X	  (imag (math-normalize (nth 2 a))))
X      (if (math-zerop imag) real (list 'cplx real imag))))
X   ((eq (car a) 'polar)
X    (calc-extensions)
X    (math-normalize-polar a))
X   ((eq (car a) 'hms)
X    (calc-extensions)
X    (math-normalize-hms a))
X   ((eq (car a) 'mod)
X    (calc-extensions)
X    (math-normalize-mod a))
X   ((eq (car a) 'sdev)
X    (calc-extensions)
X    (math-make-sdev (math-normalize (nth 1 a))
X		    (math-normalize (nth 2 a))))
X   ((eq (car a) 'intv)
X    (calc-extensions)
X    (math-make-intv (nth 1 a)
X		    (math-normalize (nth 2 a))
X		    (math-normalize (nth 3 a))))
X   ((eq (car a) 'vec)
X    (cons 'vec (mapcar 'math-normalize (cdr a))))
X   ((memq (car a) '(quote special-const))
X    (math-normalize (nth 1 a)))
X   ((eq (car a) 'var)
X    a)
X   ((or (integerp (car a)) (and (consp (car a))
X				(not (eq (car (car a)) 'lambda))))
X    (if (null (cdr a))
X	(math-normalize (car a))
X      (error "Can't use multi-valued function in an expression")))
X   ((eq (car a) 'calcFunc-if)
X    (calc-extensions)
X    (math-normalize-logical-op a))
X   (t
X    (let ((args (mapcar 'math-normalize (cdr a))))
X      (or (and calc-simplify-mode
X	       (symbolp (car a))
X	       (or (eq calc-simplify-mode 'none)
X		   (and (eq calc-simplify-mode 'num)
X			(let ((aptr args))
X			  (while (and aptr (or (math-scalarp (car aptr))
X					       (eq (car-safe (car aptr))
X						   'mod)))
X			    (setq aptr (cdr aptr)))
X			  aptr)))
X	       (cons (car a) args))
X	  (condition-case err
X	      (let ((func (assq (car a) '( ( + . math-add )
X					   ( - . math-sub )
X					   ( * . math-mul )
X					   ( / . math-div )
X					   ( % . math-mod )
X					   ( ^ . math-pow )
X					   ( neg . math-neg )
X					   ( | . math-concat ) ))))
X		(if func
X		    (apply (cdr func) args)
X		  (and (or (consp (car a))
X			   (fboundp (car a))
X			   (and (not calc-extensions-loaded)
X				(calc-extensions)
X				(fboundp (car a))))
X		       (apply (car a) args))))
X	    (wrong-number-of-arguments
X	     (calc-record-why "Wrong number of arguments") nil)
X	    (wrong-type-argument
X	     (or calc-next-why (calc-record-why "Wrong type of argument"))
X	     nil)
X	    (args-out-of-range
X	     (calc-record-why "Argument out of range") nil)
X	    (inexact-result
X	     (calc-record-why "No exact representation for result") nil))
X	  (if (consp (car a))
X	      (math-dimension-error)
X	    (cons (car a) args))))))
X)
X
X(defmacro math-with-extra-prec (delta &rest body)
X  (` (math-normalize
X      (let ((calc-internal-prec (+ calc-internal-prec (, delta))))
X	(,@ body))))
X)
X(put 'math-with-extra-prec 'lisp-indent-hook 1)
X
X;;; Define "inexact-result" as an e-lisp error symbol.
X(put 'inexact-result 'error-conditions '(error inexact-result calc-error))
X(put 'inexact-result 'error-message "Calc internal error (inexact-result)")
X
X;;; Normalize a bignum digit list by trimming high-end zeros.  [L l]
X(defun math-norm-bignum (a)
X  (let ((digs a) (last nil))
X    (while digs
X      (or (eq (car digs) 0) (setq last digs))
X      (setq digs (cdr digs)))
X    (and last
X	 (progn
X	   (setcdr last nil)
X	   a)))
X)
X
X
X;;; Concatenate two vectors, or a vector and an object.  [V O O] [Public]
X(defun math-concat (v1 v2)
X  (if (stringp v1)
X      (concat v1 v2)
X    (calc-extensions)
X    (if (and (math-objvecp v1) (math-objvecp v2))
X	(append (if (and (math-vectorp v1)
X			 (or (math-matrixp v1)
X			     (not (math-matrixp v2))))
X		    v1
X		  (list 'vec v1))
X		(if (and (math-vectorp v2)
X			 (or (math-matrixp v2)
X			     (not (math-matrixp v1))))
X		    (cdr v2)
X		  (list v2)))
X      (list '| v1 v2)))
X)
X(defun calcFunc-vconcat (a b)
X  (math-normalize (list '| a b))
X)
X
X
X;;; True if A is zero.  Works for un-normalized values.  [P n] [Public]
X(defun math-zerop (a)
X  (if (consp a)
X      (cond ((memq (car a) '(bigpos bigneg))
X	     (while (eq (car (setq a (cdr a))) 0))
X	     (null a))
X	    ((memq (car a) '(frac float polar mod))
X	     (math-zerop (nth 1 a)))
X	    ((eq (car a) 'cplx)
X	     (and (math-zerop (nth 1 a)) (math-zerop (nth 2 a))))
X	    ((eq (car a) 'hms)
X	     (and (math-zerop (nth 1 a))
X		  (math-zerop (nth 2 a))
X		  (math-zerop (nth 3 a)))))
X    (eq a 0))
X)
X;;; Faster in-line version zerop, normalized values only.
X(defmacro Math-zerop (a)   ; [P N]
X  (` (if (consp (, a))
X	 (and (not (memq (car (, a)) '(bigpos bigneg)))
X	      (if (eq (car (, a)) 'float)
X		  (eq (nth 1 (, a)) 0)
X		(math-zerop (, a))))
X       (eq (, a) 0)))
X)
X
X(defun math-zerop-bignum (a)
X  (and (eq (car a) 0)
X       (progn
X	 (while (eq (car (setq a (cdr a))) 0))
X	 (null a)))
X)
X
X(defmacro Math-natnum-lessp (a b)
X  (` (if (consp (, a))
X	 (and (consp (, b))
X	      (= (math-compare-bignum (cdr (, a)) (cdr (, b))) -1))
X       (or (consp (, b))
X	   (< (, a) (, b)))))
X)
X
X(defmacro Math-integer-negp (a)
X  (` (if (consp (, a))
X	 (eq (car (, a)) 'bigneg)
X       (< (, a) 0)))
X)
X
X(defmacro Math-integer-posp (a)
X  (` (if (consp (, a))
X	 (eq (car (, a)) 'bigpos)
X       (> (, a) 0)))
X)
X
X;;; True if A is real and negative.  [P n] [Public]
X(defun math-negp (a)
X  (if (consp a)
X      (cond ((eq (car a) 'bigpos) nil)
X	    ((eq (car a) 'bigneg) (cdr a))
X	    ((eq (car a) 'frac)
X	     (if (Math-integer-negp (nth 2 a))
X		 (Math-integer-posp (nth 1 a))
X	       (Math-integer-negp (nth 1 a))))
X	    ((eq (car a) 'float)
X	     (Math-integer-negp (nth 1 a)))
X	    ((eq (car a) 'hms)
X	     (if (math-zerop (nth 1 a))
X		 (if (math-zerop (nth 2 a))
X		     (math-negp (nth 3 a))
X		   (math-negp (nth 2 a)))
X	       (math-negp (nth 1 a))))
X	    ((eq (car a) 'intv)
X	     (or (math-negp (nth 3 a))
X		 (and (math-zerop (nth 3 a))
X		      (memq (nth 1 a) '(0 2))))))
X    (< a 0))
X)
X(defmacro Math-negp (a)
X  (` (if (consp (, a))
X	 (or (eq (car (, a)) 'bigneg)
X	     (and (not (eq (car (, a)) 'bigpos))
X		  (if (memq (car (, a)) '(frac float))
X		      (Math-integer-negp (nth 1 (, a)))
X		    (math-negp (, a)))))
X       (< (, a) 0)))
X)
X
X;;; True if A is a negative number or an expression the starts with '-'.
X(defun math-looks-negp (a)   ; [P x] [Public]
X  (or (Math-negp a)
X      (eq (car-safe a) 'neg)
X      (and (memq (car-safe a) '(* /))
X	   (or (math-looks-negp (nth 1 a))
X	       (math-looks-negp (nth 2 a)))))
X)
X(defmacro Math-looks-negp (a)   ; [P x] [Public]
X  (` (or (Math-negp (, a))
X	 (and (consp (, a)) (or (eq (car (, a)) 'neg)
X				(and (memq (car (, a)) '(* /))
X				     (or (math-looks-negp (nth 1 (, a)))
X					 (math-looks-negp (nth 2 (, a)))))))))
X)
X
X;;; True if A is real and positive.  [P n] [Public]
X(defun math-posp (a)
X  (if (consp a)
X      (cond ((eq (car a) 'bigpos) (cdr a))
X	    ((eq (car a) 'bigneg) nil)
X	    ((eq (car a) 'frac)
X	     (if (Math-integer-negp (nth 2 a))
X		 (Math-integer-negp (nth 1 a))
X	       (Math-integer-posp (nth 1 a))))
X	    ((eq (car a) 'float)
X	     (Math-integer-posp (nth 1 a)))
X	    ((eq (car a) 'hms)
X	     (if (math-zerop (nth 1 a))
X		 (if (math-zerop (nth 2 a))
X		     (math-posp (nth 3 a))
X		   (math-posp (nth 2 a)))
X	       (math-posp (nth 1 a))))
X	    ((eq (car a) 'mod)
X	     (not (math-zerop (nth 1 a))))
X	    ((eq (car a) 'intv)
X	     (or (math-posp (nth 2 a))
X		 (and (math-zerop (nth 2 a))
X		      (memq (nth 1 a) '(0 1))))))
X    (> a 0))
X)
X(defmacro Math-posp (a)
X  (` (if (consp (, a))
X	 (or (eq (car (, a)) 'bigpos)
X	     (and (not (eq (car (, a)) 'bigneg))
X		  (if (memq (car (, a)) '(frac float))
X		      (Math-integer-posp (nth 1 (, a)))
X		    (math-posp (, a)))))
X       (> (, a) 0)))
X)
X
X;;; True if A is a small or big integer.  [P x] [Public]
X(defun math-integerp (a)
X  (or (integerp a)
X      (memq (car-safe a) '(bigpos bigneg)))
X)
X(defmacro Math-integerp (a)
X  (` (or (not (consp (, a)))
X	 (memq (car (, a)) '(bigpos bigneg))))
X)
X
X(fset 'math-fixnump (symbol-function 'integerp))
X(fset 'math-fixnatnump (symbol-function 'natnump))
X
X;;; True if A is (numerically) a non-negative integer.  [P N] [Public]
X(defun math-natnump (a)
X  (or (natnump a)
X      (eq (car-safe a) 'bigpos))
X)
X(defmacro Math-natnump (a)
X  (` (if (consp (, a))
X	 (eq (car (, a)) 'bigpos)
X       (>= (, a) 0)))
X)
X
X;;; True if A is a rational (or integer).  [P x] [Public]
X(defun math-ratp (a)
X  (or (integerp a)
X      (memq (car-safe a) '(bigpos bigneg frac)))
X)
X(defmacro Math-ratp (a)
X  (` (or (not (consp (, a)))
X	 (memq (car (, a)) '(bigpos bigneg frac))))
X)
X
X;;; True if A is a real (or rational).  [P x] [Public]
X(defun math-realp (a)
X  (or (integerp a)
X      (memq (car-safe a) '(bigpos bigneg frac float)))
X)
X(defmacro Math-realp (a)
X  (` (or (not (consp (, a)))
X	 (memq (car (, a)) '(bigpos bigneg frac float))))
X)
X
X;;; True if A is a real or HMS form.  [P x] [Public]
X(defun math-anglep (a)
X  (or (integerp a)
X      (memq (car-safe a) '(bigpos bigneg frac float hms)))
X)
X(defmacro Math-anglep (a)
X  (` (or (not (consp (, a)))
X	 (memq (car (, a)) '(bigpos bigneg frac float hms))))
X)
X
X;;; True if A is a floating-point real or complex number.  [P x] [Public]
X(defun math-floatp (a)
X  (or (eq (car-safe a) 'float)
X      (and (memq (car-safe a) '(cplx polar mod sdev intv))
X	   (or (math-floatp (nth 1 a))
X	       (math-floatp (nth 2 a))
X	       (and (eq (car a) 'intv) (math-floatp (nth 3 a))))))
X)
X
X;;; True if A is a number of any kind.  [P x] [Public]
X(defun math-numberp (a)
X  (or (integerp a)
X      (memq (car-safe a) '(bigpos bigneg frac float cplx polar)))
X)
X(defmacro Math-numberp (a)
X  (` (or (not (consp (, a)))
X	 (memq (car (, a)) '(bigpos bigneg frac float cplx polar))))
X)
X
X;;; True if A is a complex number or angle.  [P x] [Public]
X(defun math-scalarp (a)
X  (or (integerp a)
X      (memq (car-safe a) '(bigpos bigneg frac float cplx polar hms)))
X)
X(defmacro Math-scalarp (a)
X  (` (or (not (consp (, a)))
X	 (memq (car (, a)) '(bigpos bigneg frac float cplx polar hms))))
X)
X
X;;; True if A is a vector.  [P x] [Public]
X(defun math-vectorp (a)
X  (eq (car-safe a) 'vec)
X)
X(defmacro Math-vectorp (a)
X  (` (and (consp (, a)) (eq (car (, a)) 'vec)))
X)
X
X;;; True if A is a number or a vector.  [P x] [Public]
X(defun math-numvecp (a)
X  (or (Math-numberp a)
X      (Math-vectorp a))
X)
X
X;;; True if A is numerically (but not literally) an integer.  [P x] [Public]
X(defun math-messy-integerp (a)
X  (cond
X   ((eq (car-safe a) 'float) (>= (nth 2 a) 0))
X   ((eq (car-safe a) 'frac) (Math-integerp (math-normalize a))))
X)
X(defmacro Math-messy-integerp (a)
X  (` (and (consp (, a))
X	  (eq (car (, a)) 'float)
X	  (>= (nth 2 (, a)) 0)))
X)
X
X;;; True if A is any scalar data object.  [P x]
X(defun math-objectp (a)    ;  [Public]
X  (or (integerp a)
X      (memq (car-safe a) '(bigpos bigneg frac float cplx
X				  polar hms sdev intv mod)))
X)
X(defmacro Math-objectp (a)    ;  [Public]
X  (` (or (not (consp (, a)))
X	 (memq (car (, a))
X	       '(bigpos bigneg frac float cplx polar hms sdev intv mod))))
X)
X
X;;; True if A is any vector or scalar data object.  [P x]
X(defun math-objvecp (a)    ;  [Public]
X  (or (integerp a)
X      (memq (car-safe a) '(bigpos bigneg frac float cplx polar
X				  hms sdev intv mod vec incomplete)))
X)
X(defmacro Math-objvecp (a)    ;  [Public]
X  (` (or (not (consp (, a)))
X	 (memq (car (, a))
X	       '(bigpos bigneg frac float cplx polar hms sdev intv mod vec))))
X)
X
X
X;;; True if A is an even integer.  [P R R] [Public]
X(defun math-evenp (a)
X  (if (consp a)
X      (and (memq (car a) '(bigpos bigneg))
X	   (= (% (nth 1 a) 2) 0))
X    (= (% a 2) 0))
X)
X
X;;; Compute A / 2, for small or big integer A.  [I i]
X;;; If A is negative, type of truncation is undefined.
X(defun math-div2 (a)
X  (if (consp a)
X      (if (cdr a)
X	  (math-normalize (cons (car a) (math-div2-bignum (cdr a))))
X	0)
X    (/ a 2))
X)
X
X(defun math-div2-bignum (a)   ; [l l]
X  (cond
X   ((null (cdr a)) (list (/ (car a) 2)))
X   (t (cons (+ (/ (car a) 2) (* (% (nth 1 a) 2) 500))
X	    (math-div2-bignum (cdr a)))))
X)
X
X
X;;; Verify that A is a complete object and return A.  [x x] [Public]
X(defun math-check-complete (a)
X  (cond ((integerp a) a)
X	((eq (car-safe a) 'incomplete)
X	 (cond ((memq (nth 1 a) '(cplx polar))
X		(error "Complex number is incomplete"))
X	       ((eq (nth 1 a) 'vec)
X		(error "Vector is incomplete"))
X	       ((eq (nth 1 a) 'intv)
X		(error "Interval form is incomplete"))
X	       (t (error "Object is incomplete"))))
X	((consp a) a)
X	(t (error "Invalid data object encountered")))
X)
X
X;;; Reject an argument to a calculator function.  [Public]
X(defun math-reject-arg (&optional a p)
X  (calc-record-why p a)
X  (signal 'wrong-type-argument (and a (if p (list p a) (list a))))
X)
X
X
X;;; Coerce A to be an integer (by truncation toward zero).  [I N] [Public]
X(defun math-trunc (a)
X  (cond ((Math-integerp a) a)
X	((Math-looks-negp a)
X	 (math-neg (math-trunc (math-neg a))))
X	((eq (car a) 'float) (math-scale-int (nth 1 a) (nth 2 a)))
X	((eq (car a) 'frac) (math-quotient (nth 1 a) (nth 2 a)))
X	(t (calc-extensions)
X	   (math-trunc-fancy a)))
X)
X(fset 'calcFunc-trunc (symbol-function 'math-trunc))
X
X;;; Coerce A to be an integer (by truncation toward minus infinity).  [I N]
X(defun math-floor (a)    ;  [Public]
X  (cond ((Math-integerp a) a)
X	((Math-messy-integerp a) (math-trunc a))
X	((Math-realp a)
X	 (if (Math-negp a)
X	     (math-add (math-trunc a) -1)
X	   (math-trunc a)))
X	(t (calc-extensions)
X	   (math-floor-fancy a)))
X)
X(fset 'calcFunc-floor (symbol-function 'math-floor))
X
X
X;;; Coerce integer A to be a bignum.  [B S]
X(defun math-bignum (a)
X  (if (>= a 0)
X      (cons 'bigpos (math-bignum-big a))
X    (cons 'bigneg (math-bignum-big (- a))))
X)
X
X(defun math-bignum-big (a)   ; [L s]
X  (if (= a 0)
X      nil
X    (cons (% a 1000) (math-bignum-big (/ a 1000))))
X)
X
X
X;;; Build a normalized fraction.  [R I I]
X;;; (This could probably be implemented more efficiently than using the
X;;;  the plain gcd algorithm.)
X(defun math-make-frac (num den)
X  (if (Math-integer-negp den)
X      (setq num (math-neg num)
X	    den (math-neg den)))
X  (let ((gcd (math-gcd num den)))
X    (if (eq gcd 1)
X	(if (eq den 1)
X	    num
X	  (list 'frac num den))
X      (if (equal gcd den)
X	  (math-quotient num gcd)
X	(list 'frac (math-quotient num gcd) (math-quotient den gcd)))))
X)
X
X;;; Build a normalized floating-point number.  [F I S]
X(defun math-make-float (mant exp)
X  (if (eq mant 0)
X      '(float 0 0)
X    (let* ((ldiff (- calc-internal-prec (math-numdigs mant))))
X      (if (< ldiff 0)
X	  (setq mant (math-scale-rounding mant ldiff)
X		exp (- exp ldiff))))
X    (if (consp mant)
X	(let ((digs (cdr mant)))
X	  (if (= (% (car digs) 10) 0)
X	      (progn
X		(while (= (car digs) 0)
X		  (setq digs (cdr digs)
X			exp (+ exp 3)))
X		(while (= (% (car digs) 10) 0)
X		  (setq digs (math-div10-bignum digs)
X			exp (1+ exp)))
X		(setq mant (math-normalize (cons (car mant) digs))))))
X      (while (= (% mant 10) 0)
X	(setq mant (/ mant 10)
X	      exp (1+ exp))))
X    (list 'float mant exp))
X)
X
X(defun math-div10-bignum (a)   ; [l l]
X  (cond
X   ((null (cdr a)) (list (/ (car a) 10)))
X   (t (cons (+ (/ (car a) 10) (* (% (nth 1 a) 10) 100))
X	    (math-div10-bignum (cdr a)))))
X)
X
X;;; Coerce A to be a float.  [F N; V V] [Public]
X(defun math-float (a)
X  (cond ((Math-integerp a) (math-make-float a 0))
X	((eq (car a) 'frac) (math-div (math-float (nth 1 a)) (nth 2 a)))
X	((eq (car a) 'float) a)
X	((memq (car a) '(cplx polar vec hms sdev intv mod))
X	 (cons (car a) (mapcar 'math-float (cdr a))))
X	(t (math-reject-arg a 'objectp)))
X)
X(fset 'calcFunc-float (symbol-function 'math-float))
X
X
X;;; Compute the negative of A.  [O O; o o] [Public]
X(defmacro Math-integer-neg (a)
X  (` (if (consp (, a))
X	 (if (eq (car (, a)) 'bigpos)
X	     (cons 'bigneg (cdr (, a)))
X	   (cons 'bigpos (cdr (, a))))
X       (- (, a))))
X)
X(defun math-neg (a)
X  (cond ((not (consp a)) (- a))
X	((eq (car a) 'bigpos) (cons 'bigneg (cdr a)))
X	((eq (car a) 'bigneg) (cons 'bigpos (cdr a)))
X	((memq (car a) '(frac float))
X	 (list (car a) (Math-integer-neg (nth 1 a)) (nth 2 a)))
X	((memq (car a) '(cplx vec hms))
X	 (cons (car a) (mapcar 'math-neg (cdr a))))
X	(t (math-neg-fancy a)))
X)
X(defun calcFunc-neg (a)
X  (math-normalize (list 'neg a))
X)
X
X
X;;; Compute the number of decimal digits in integer A.  [S I]
X(defun math-numdigs (a)
X  (if (consp a)
X      (if (cdr a)
X	  (let* ((len (1- (length a)))
X		 (top (nth len a)))
X	    (+ (* len 3) (cond ((>= top 100) 0) ((>= top 10) -1) (t -2))))
X	0)
X    (cond ((>= a 100) (+ (math-numdigs (/ a 1000)) 3))
X	  ((>= a 10) 2)
X	  ((>= a 1) 1)
X	  ((= a 0) 0)
X	  ((> a -10) 1)
X	  ((> a -100) 2)
X	  (t (math-numdigs (- a)))))
X)
X
X;;; Multiply (with truncation toward 0) the integer A by 10^N.  [I i S]
X(defun math-scale-int (a n)
X  (cond ((= n 0) a)
X	((> n 0) (math-scale-left a n))
X	(t (math-normalize (math-scale-right a (- n)))))
X)
X
X(defun math-scale-left (a n)   ; [I I S]
X  (if (= n 0)
X      a
X    (if (consp a)
X	(cons (car a) (math-scale-left-bignum (cdr a) n))
X      (if (>= n 3)
X	  (if (or (>= a 1000) (<= a -1000))
X	      (math-scale-left (math-bignum a) n)
X	    (math-scale-left (* a 1000) (- n 3)))
X	(if (= n 2)
X	    (if (or (>= a 10000) (<= a -10000))
X		(math-scale-left (math-bignum a) 2)
X	      (* a 100))
X	  (if (or (>= a 100000) (<= a -100000))
X	      (math-scale-left (math-bignum a) 1)
X	    (* a 10))))))
X)
X
X(defun math-scale-left-bignum (a n)
X  (if (>= n 3)
X      (while (>= (setq a (cons 0 a)
X		       n (- n 3)) 3)))
X  (if (> n 0)
X      (math-mul-bignum-digit a (if (= n 2) 100 10) 0)
X    a)
X)
X
X(defun math-scale-right (a n)   ; [i i S]
X  (if (= n 0)
X      a
X    (if (consp a)
X	(cons (car a) (math-scale-right-bignum (cdr a) n))
X      (if (<= a 0)
X	  (if (= a 0)
X	      0
X	    (- (math-scale-right (- a) n)))
X	(if (>= n 3)
X	    (while (and (> (setq a (/ a 1000)) 0)
X			(>= (setq n (- n 3)) 3))))
X	(if (= n 2)
X	    (/ a 100)
X	  (if (= n 1)
X	      (/ a 10)
X	    a)))))
X)
X
X(defun math-scale-right-bignum (a n)   ; [L L S; l l S]
X  (if (>= n 3)
X      (setq a (nthcdr (/ n 3) a)
X	    n (% n 3)))
X  (if (> n 0)
X      (cdr (math-mul-bignum-digit a (if (= n 2) 10 100) 0))
X    a)
X)
X
X;;; Multiply (with rounding) the integer A by 10^N.   [I i S]
X(defun math-scale-rounding (a n)
X  (cond ((>= n 0)
X	 (math-scale-left a n))
X	((consp a)
X	 (math-normalize
X	  (cons (car a)
X		(let ((val (if (< n -3)
X			       (math-scale-right-bignum (cdr a) (- -3 n))
X			     (if (= n -2)
X				 (math-mul-bignum-digit (cdr a) 10 0)
X			       (if (= n -1)
X				   (math-mul-bignum-digit (cdr a) 100 0)
X				 (cdr a))))))  ; n = -3
X		  (if (and val (>= (car val) 500))
X		      (if (cdr val)
X			  (if (eq (car (cdr val)) 999)
X			      (math-add-bignum (cdr val) '(1))
X			    (cons (1+ (car (cdr val))) (cdr (cdr val))))
X			'(1))
X		    (cdr val))))))
X	(t
X	 (if (< a 0)
X	     (- (math-scale-rounding (- a) n))
X	   (if (= n -1)
X	       (/ (+ a 5) 10)
X	     (/ (+ (math-scale-right a (- -1 n)) 5) 10)))))
X)
X
X
X;;; Compute the sum of A and B.  [O O O] [Public]
X(defun math-add (a b)
X  (or
X   (and (not (or (consp a) (consp b)))
X	(progn
X	  (setq a (+ a b))
X	  (if (or (<= a -1000000) (>= a 1000000))
X	      (math-bignum a)
X	    a)))
X   (and (Math-zerop a) (not (eq (car-safe a) 'mod))
X	(if (and (math-floatp a) (Math-ratp b)) (math-float b) b))
X   (and (Math-zerop b) (not (eq (car-safe b) 'mod))
X	(if (and (math-floatp b) (Math-ratp a)) (math-float a) a))
X   (and (Math-objvecp a) (Math-objvecp b)
X	(or
X	 (and (Math-integerp a) (Math-integerp b)
X	      (progn
X		(or (consp a) (setq a (math-bignum a)))
X		(or (consp b) (setq b (math-bignum b)))
X		(if (eq (car a) 'bigneg)
X		    (if (eq (car b) 'bigneg)
X			(cons 'bigneg (math-add-bignum (cdr a) (cdr b)))
X		      (math-normalize
X		       (let ((diff (math-sub-bignum (cdr b) (cdr a))))
X			 (if (eq diff 'neg)
X			     (cons 'bigneg (math-sub-bignum (cdr a) (cdr b)))
X			   (cons 'bigpos diff)))))
X		  (if (eq (car b) 'bigneg)
X		      (math-normalize
X		       (let ((diff (math-sub-bignum (cdr a) (cdr b))))
X			 (if (eq diff 'neg)
X			     (cons 'bigneg (math-sub-bignum (cdr b) (cdr a)))
X			   (cons 'bigpos diff))))
X		    (cons 'bigpos (math-add-bignum (cdr a) (cdr b)))))))
X	 (and (Math-ratp a) (Math-ratp b)
X	      (if (eq (car-safe a) 'frac)
X		  (if (eq (car-safe b) 'frac)
X		      (math-make-frac (math-add (math-mul (nth 1 a) (nth 2 b))
X						(math-mul (nth 2 a) (nth 1 b)))
X				      (math-mul (nth 2 a) (nth 2 b)))
X		    (math-make-frac (math-add (nth 1 a)
X					      (math-mul (nth 2 a) b))
X				    (nth 2 a)))
X		(math-make-frac (math-add (math-mul a (nth 2 b))
X					  (nth 1 b))
X				(nth 2 b))))
X	 (and (Math-realp a) (Math-realp b)
X	      (progn
X		(or (and (consp a) (eq (car a) 'float))
X		    (setq a (math-float a)))
X		(or (and (consp b) (eq (car b) 'float))
X		    (setq b (math-float b)))
X		(math-add-float a b)))
X	 (and (calc-extensions)
X	      (math-add-objects-fancy a b))))
X   (and (calc-extensions)
X	(math-add-symb-fancy a b)))
X)
X(defun calcFunc-add (&rest rest)
X  (if rest
X      (let ((a (car rest)))
X	(while (setq rest (cdr rest))
X	  (setq a (list '+ a (car rest))))
X	(math-normalize a))
X    0)
X)
X
X(defun math-add-bignum (a b)   ; [L L L; l l l]
X  (if a
X      (if b
X	  (let* ((a (copy-sequence a)) (aa a) (carry nil) sum)
X	    (while (and aa b)
X	      (if carry
X		  (if (< (setq sum (+ (car aa) (car b))) 999)
X		      (progn
X			(setcar aa (1+ sum))
X			(setq carry nil))
X		    (setcar aa (+ sum -999)))
X		(if (< (setq sum (+ (car aa) (car b))) 1000)
X		    (setcar aa sum)
X		  (setcar aa (+ sum -1000))
X		  (setq carry t)))
X	      (setq aa (cdr aa)
X		    b (cdr b)))
X	    (if carry
X		(if b
X		    (nconc a (math-add-bignum b '(1)))
X		  (while (eq (car aa) 999)
X		    (setcar aa 0)
X		    (setq aa (cdr aa)))
X		  (if aa
X		      (progn
X			(setcar aa (1+ (car aa)))
X			a)
X		    (nconc a '(1))))
X	      (if b
X		  (nconc a b)
X		a)))
X	a)
X    b)
X)
X
X(defun math-sub-bignum (a b)   ; [l l l]
X  (if b
X      (if a
X	  (let* ((a (copy-sequence a)) (aa a) (borrow nil) sum)
X	    (while (and aa b)
X	      (if borrow
X		  (if (>= (setq diff (- (car aa) (car b))) 1)
X		      (progn
X			(setcar aa (1- diff))
X			(setq borrow nil))
X		    (setcar aa (+ diff 999)))
X		(if (>= (setq diff (- (car aa) (car b))) 0)
X		    (setcar aa diff)
X		  (setcar aa (+ diff 1000))
X		  (setq borrow t)))
X	      (setq aa (cdr aa)
X		    b (cdr b)))
X	    (if borrow
X		(progn
X		  (while (eq (car aa) 0)
X		    (setcar aa 999)
X		    (setq aa (cdr aa)))
X		  (if aa
X		      (progn
X			(setcar aa (1- (car aa)))
X			a)
X		    'neg))
X	      (while (eq (car b) 0)
X		(setq b (cdr b)))
X	      (if b
X		  'neg
X		a)))
X	(while (eq (car b) 0)
X	  (setq b (cdr b)))
X	(and b
X	     'neg))
X    a)
X)
X
X(defun math-add-float (a b)   ; [F F F]
X  (let ((ediff (- (nth 2 a) (nth 2 b))))
X    (if (>= ediff 0)
X	(if (>= ediff (+ calc-internal-prec calc-internal-prec))
X	    a
X	  (math-make-float (math-add (nth 1 b)
X				     (math-scale-int (nth 1 a) ediff))
X			   (nth 2 b)))
X      (if (>= (setq ediff (- ediff))
X	      (+ calc-internal-prec calc-internal-prec))
X	  b
X	(math-make-float (math-add (nth 1 a)
X				   (math-scale-int (nth 1 b) ediff))
X			 (nth 2 a)))))
X)
X
X;;; Compute the difference of A and B.  [O O O] [Public]
X(defun math-sub (a b)
X  (if (or (consp a) (consp b))
X      (math-add a (math-neg b))
X    (setq a (- a b))
X    (if (or (<= a -1000000) (>= a 1000000))
X	(math-bignum a)
X      a))
X)
X(defun calcFunc-sub (&rest rest)
X  (if rest
X      (let ((a (car rest)))
X	(while (setq rest (cdr rest))
X	  (setq a (list '- a (car rest))))
X	(math-normalize a))
X    0)
X)
X
X(defun math-sub-float (a b)   ; [F F F]
X  (let ((ediff (- (nth 2 a) (nth 2 b))))
X    (if (>= ediff 0)
X	(if (>= ediff (+ calc-internal-prec calc-internal-prec))
X	    a
X	  (math-make-float (math-add (Math-integer-neg (nth 1 b))
X				     (math-scale-int (nth 1 a) ediff))
X			   (nth 2 b)))
X      (if (>= (setq ediff (- ediff))
X	      (+ calc-internal-prec calc-internal-prec))
X	  b
X	(math-make-float (math-add (nth 1 a)
X				   (Math-integer-neg
X				    (math-scale-int (nth 1 b) ediff)))
X			 (nth 2 a)))))
X)
X
X
X;;; Compute the product of A and B.  [O O O] [Public]
X(defun math-mul (a b)
X  (or
X   (and (not (consp a)) (not (consp b))
X	(< a 1000) (> a -1000) (< b 1000) (> b -1000)
X	(* a b))
X   (and (Math-zerop a) (not (eq (car-safe b) 'mod))
X	(if (and (math-floatp b) (Math-ratp a)) (math-float a) a))
X   (and (Math-zerop b) (not (eq (car-safe a) 'mod))
X	(if (and (math-floatp a) (Math-ratp b)) (math-float b) b))
X   (and (Math-objvecp a) (Math-objvecp b)
X	(or
X	 (and (Math-integerp a) (Math-integerp b)
X	      (progn
X		(or (consp a) (setq a (math-bignum a)))
X		(or (consp b) (setq b (math-bignum b)))
X		(math-normalize
X		 (cons (if (eq (car a) (car b)) 'bigpos 'bigneg)
X		       (if (cdr (cdr a))
X			   (if (cdr (cdr b))
X			       (math-mul-bignum (cdr a) (cdr b))
X			     (math-mul-bignum-digit (cdr a) (nth 1 b) 0))
X			 (math-mul-bignum-digit (cdr b) (nth 1 a) 0))))))
X	 (and (Math-ratp a) (Math-ratp b)
X	      (if (eq (car-safe a) 'frac)
X		  (if (eq (car-safe b) 'frac)
X		      (math-make-frac (math-mul (nth 1 a) (nth 1 b))
X				      (math-mul (nth 2 a) (nth 2 b)))
X		    (math-make-frac (math-mul (nth 1 a) b)
X				    (nth 2 a)))
X		(math-make-frac (math-mul a (nth 1 b))
X				(nth 2 b))))
X	 (and (Math-realp a) (Math-realp b)
X	      (progn
X		(or (and (consp a) (eq (car a) 'float))
X		    (setq a (math-float a)))
X		(or (and (consp b) (eq (car b) 'float))
X		    (setq b (math-float b)))
X		(math-make-float (math-mul (nth 1 a) (nth 1 b))
X				 (+ (nth 2 a) (nth 2 b)))))
X	 (and (calc-extensions)
X	      (math-mul-objects-fancy a b))))
X   (and (calc-extensions)
X	(math-mul-symb-fancy a b)))
X)
X
X(defun calcFunc-mul (&rest rest)
X  (if rest
X      (let ((a (car rest)))
X	(while (setq rest (cdr rest))
X	  (setq a (list '* a (car rest))))
X	(math-normalize a))
X    1)
X)
X
X;;; Multiply digit lists A and B.  [L L L; l l l]
X(defun math-mul-bignum (a b)
X  (and a b
X       (let* ((sum (if (<= (car b) 1)
X		       (if (= (car b) 0)
X			   (list 0)
X			 (copy-sequence a))
X		     (math-mul-bignum-digit a (car b) 0)))
X	      (sump sum) c d aa prod)
X	 (while (setq b (cdr b))
X	   (setq ss (setq sump (or (cdr sump) (setcdr sump (list 0))))
X		 d (car b)
X		 c 0
X		 aa a)
X	   (while (progn
X		    (setcar ss (% (setq prod (+ (+ (car ss) (* (car aa) d))
X						c)) 1000))
X		    (setq aa (cdr aa)))
X	     (setq c (/ prod 1000)
X		   ss (or (cdr ss) (setcdr ss (list 0)))))
X	   (if (>= prod 1000)
X	       (if (cdr ss)
X		   (setcar (cdr ss) (+ (/ prod 1000) (car (cdr ss))))
X		 (setcdr ss (list (/ prod 1000))))))
X	 sum))
X)
X
X;;; Multiply digit list A by digit D.  [L L D D; l l D D]
X(defun math-mul-bignum-digit (a d c)
X  (and a
X       (if (<= d 1)
X	   (and (= d 1) a)
X	 (let* ((a (copy-sequence a)) (aa a) prod)
X	   (while (progn
X		    (setcar aa (% (setq prod (+ (* (car aa) d) c)) 1000))
X		    (cdr aa))
X	     (setq aa (cdr aa)
X		   c (/ prod 1000)))
X	   (if (>= prod 1000)
X	       (setcdr aa (list (/ prod 1000))))
X	   a)))
X)
X
X
X;;; Compute the square of A.  [O O] [Public]
X(defun math-sqr (a)
X  (if (eq (car-safe a) 'calcFunc-sqrt)
X      (nth 1 a)
X    (math-mul a a))
X)
X
X
X;;; Compute the integer (quotient . remainder) of A and B, which may be
X;;; small or big integers.  Type and consistency of truncation is undefined
X;;; if A or B is negative.  B must be nonzero.  [I.I I I] [Public]
X(defun math-idivmod (a b)
X  (if (eq b 0)
X      (math-reject-arg a "Division by zero"))
X  (if (or (consp a) (consp b))
X      (if (and (natnump b) (< b 1000))
X	  (let ((res (math-div-bignum-digit (cdr a) b)))
X	    (cons
X	     (math-normalize (cons (car a) (car res)))
X	     (cdr res)))
X	(or (consp a) (setq a (math-bignum a)))
X	(or (consp b) (setq b (math-bignum b)))
X	(let ((res (math-div-bignum (cdr a) (cdr b))))
X	  (cons
X	   (math-normalize (cons (if (eq (car a) (car b)) 'bigpos 'bigneg)
X				 (car res)))
X	   (math-normalize (cons (car a) (cdr res))))))
X    (cons (/ a b) (% a b)))
X)
X
X(defun math-quotient (a b)   ; [I I I] [Public]
X  (if (and (not (consp a)) (not (consp b)))
X      (if (= b 0)
X	  (math-reject-arg a "Division by zero")
X	(/ a b))
X    (if (and (natnump b) (< b 1000))
X	(if (= b 0)
X	    (math-reject-arg a "Division by zero")
X	  (math-normalize (cons (car a)
X				(car (math-div-bignum-digit (cdr a) b)))))
X      (or (consp a) (setq a (math-bignum a)))
X      (or (consp b) (setq b (math-bignum b)))
X      (let* ((alen (1- (length a)))
X	     (blen (1- (length b)))
X	     (d (/ 1000 (1+ (nth (1- blen) (cdr b)))))
X	     (res (math-div-bignum-big (math-mul-bignum-digit (cdr a) d 0)
X				       (math-mul-bignum-digit (cdr b) d 0)
X				       alen blen)))
X	(math-normalize (cons (if (eq (car a) (car b)) 'bigpos 'bigneg)
X			      (car res))))))
X)
X
X(defun math-imod (a b)   ; [I I I] [Public]
X  (if (and (not (consp a)) (not (consp b)))
X      (if (= b 0)
X	  (math-reject-arg a "Division by zero")
X	(% a b))
X    (cdr (math-idivmod a b)))
X)
X
X;;; Divide a bignum digit list by another.  [l.l l L]
X;;; The following division algorithm is borrowed from Knuth vol. II, sec. 4.3.1
X(defun math-div-bignum (a b)
X  (if (null (cdr b))
X      (let ((res (math-div-bignum-digit a (car b))))
X	(cons (car res) (list (cdr res))))
X    (let* ((alen (length a))
X	   (blen (length b))
X	   (d (/ 1000 (1+ (nth (1- blen) b))))
X	   (res (math-div-bignum-big (math-mul-bignum-digit a d 0)
X				     (math-mul-bignum-digit b d 0)
X				     alen blen)))
X      (if (= d 1)
X	  res
X	(cons (car res)
X	      (car (math-div-bignum-digit (cdr res) d))))))
X)
X
X;;; Divide a bignum digit list by a digit.  [l.D l D]
X(defun math-div-bignum-digit (a b)
X  (if (null a)
X      '(nil . 0)
X    (let* ((res (math-div-bignum-digit (cdr a) b))
X	   (num (+ (* (cdr res) 1000) (car a))))
X      (cons
X       (cons (/ num b) (car res))
X       (% num b))))
X)
X
X(defun math-div-bignum-big (a b alen blen)   ; [l.l l L]
X  (if (< alen blen)
X      (cons nil a)
X    (let* ((res (math-div-bignum-big (cdr a) b (1- alen) blen))
X	   (num (cons (car a) (cdr res)))
X	   (res2 (math-div-bignum-part num b blen)))
X      (cons
X       (cons (car res2) (car res))
X       (cdr res2))))
X)
X
X(defun math-div-bignum-part (a b blen)   ; a < b*1000  [D.l l L]
X  (let* ((num (+ (* (or (nth blen a) 0) 1000) (or (nth (1- blen) a) 0)))
X	 (den (nth (1- blen) b))
X	 (guess (min (/ num den) 999)))
X    (math-div-bignum-try a b (math-mul-bignum-digit b guess 0) guess))
X)
X
X(defun math-div-bignum-try (a b c guess)   ; [D.l l l D]
X  (let ((rem (math-sub-bignum a c)))
X    (if (eq rem 'neg)
X	(math-div-bignum-try a b (math-sub-bignum c b) (1- guess))
X      (cons guess rem)))
X)
X
X
X;;; Compute the quotient of A and B.  [O O N] [Public]
X(defun math-div (a b)
X  (or
X   (and (Math-zerop b)
X	(math-reject-arg a "Division by zero"))
X   (and (Math-zerop a) (not (eq (car-safe b) 'mod))
X	(if (and (math-floatp b) (Math-ratp a)) (math-float a) a))
X   (and (Math-objvecp a) (Math-objvecp b)
X	(or
X	 (and (Math-integerp a) (Math-integerp b)
X	      (if calc-prefer-frac
X		  (math-make-frac a b)
X		(let ((q (math-idivmod a b)))
X		  (if (eq (cdr q) 0)
X		      (car q)
X		    (math-div-float (math-make-float a 0)
X				    (math-make-float b 0))))))
X	 (and (Math-ratp a) (Math-ratp b)
X	      (if (eq (car-safe a) 'frac)
X		  (if (eq (car-safe b) 'frac)
X		      (math-make-frac (math-mul (nth 1 a) (nth 2 b))
X				      (math-mul (nth 2 a) (nth 1 b)))
X		    (math-make-frac (nth 1 a)
X				    (math-mul (nth 2 a) b)))
X		(math-make-frac (math-mul a (nth 2 b))
X				(nth 1 b))))
X	 (and (Math-realp a) (Math-realp b)
X	      (progn
X		(or (and (consp a) (eq (car a) 'float))
X		    (setq a (math-float a)))
X		(or (and (consp b) (eq (car b) 'float))
X		    (setq b (math-float b)))
X		(math-div-float a b)))
X	 (and (calc-extensions)
X	      (math-div-objects-fancy a b))))
X   (and (calc-extensions)
X	(math-div-symb-fancy a b)))
X)
X(defun calcFunc-div (a &rest rest)
X  (while rest
X    (setq a (list '/ a (car rest))
X	  rest (cdr rest)))
X  (math-normalize a)
X)
X
X(defun math-div-float (a b)   ; [F F F]
X  (let ((ldiff (max (- (1+ calc-internal-prec)
X		       (- (math-numdigs (nth 1 a)) (math-numdigs (nth 1 b))))
SHAR_EOF
echo "End of part 2"
echo "File calc.el is continued in part 3"
echo "3" > s2_seq_.tmp
exit 0