[comp.sources.misc] v13i027: Emacs Calculator 1.01, part 01/19

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

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

---- Cut Here and unpack ----
#!/bin/sh
# shar:	Shell Archiver  (v1.22)
#
# This is part 1 of a multipart archive                                    
# do not concatenate these parts, unpack them in order with /bin/sh        
#
#	Run the following text with /bin/sh to create:
#	  README
#	  INSTALL
#	  calc.el
#	  calc-ext.el
#	  calc.texinfo
#
if test -r s2_seq_.tmp
then echo "Must unpack archives in sequence!"
     next=`cat s2_seq_.tmp`; echo "Please unpack part $next next"
     exit 1; fi
echo "x - extracting README (Text)"
sed 's/^X//' << 'SHAR_EOF' > README &&
X
XThis tar file contains version 1.01 of Calc, an advanced desk
Xcalculator for GNU Emacs.
X
X"Calc"  Copyright 1990  Dave Gillespie
X                        256-80 Caltech
X                        Pasadena CA 91125
X                        daveg@csvax.caltech.edu, cit-vax!daveg
X
X
X
XFrom the Introduction to the manual:
X
X  "Calc" is an advanced calculator and mathematical tool that runs as
X  part of the GNU Emacs environment.  Very roughly based on the HP-28/48
X  series of calculators, its many features include:
X
X    * Choice of algebraic or RPN style entry of calculations.
X 
X    * Arbitrary precision integers and floating-point numbers.
X 
X    * Arithmetic on rational numbers, complex numbers (rectangular and polar),
X      error forms with standard deviations, open and closed intervals, vectors
X      and matrices, quantities with units, and simple algebraic expressions.
X 
X    * Mathematical operations such as logarithms and trig functions.
X 
X    * Programmer's features (bitwise operations, non-decimal integers).
X 
X    * Number theoretical features such as prime factorization and arithmetic
X      modulo M for any M.
X 
X    * Algebraic manipulation features, including symbolic calculus.
X 
X    * Kill and yank to and from regular editing buffers.
X 
X    * Easy programming using keyboard macros, algebraic formulas,
X      algebraic rewrite rules, or Lisp code.
X
X
X
XTo install Calc:
X
X  1. Create a directory for Calc
X  2. "cd" to that directory
X  3. Place calc-1.01.tar.Z in the directory (be sure to ftp it in binary mode)
X  4. Type "uncompress calc-1.01.tar.Z"
X  5. Type "tar xvf calc-1.01.tar"
X4,5. Alternatively: "zcat calc1.01.tar.Z | tar xvf -"
X  6. Follow the instructions in the file "INSTALL".
X
X
X
XThe files contained in this tar file are:
X
X  README		This very file.
X
X  INSTALL		Installation instructions (excerpted from the manual).
X
X  calc.el		The main source file.  This contains just the basic
X			arithmetic functions, and is kept small for fast
X			loading.  124K.
X
X  calc-ext.el		The rest of the Calculator source.  This file is
X			auto-loaded the first time you use an advanced Calc
X			command.  460K.
X
X  calc.elc		The byte-compiled version of Calc.  You can make
X  calc-ext.elc		these yourself from calc.el and calc-ext.el if you
X			prefer; use the M-x byte-compile-file command.
X			(Not available in shar distribution; 82K + 358K.)
X
X  calc.texinfo  	Documentation for Calc.  This can be turned into
X			a printed manual and also into on-line help.  465K.
X			Beware: printed, this is over 200 pages!
X
X  macedit.el		A handy utility for editing keyboard macros; good
X			for using Calc as a programmable calculator.  19K.
X
X
XCalc is written entirely in Emacs Lisp, for maximum portability.
XYou do not need to recompile Emacs to install and use Calc.
X
XYou will need about two megabytes of disk space to hold Calc with
Xits Info documentation.
X
XSee the file INSTALL for installation instructions.  If you're impatient,
Xuse `M-x load-file' to load `calc.elc' and `calc-ext.elc', then type
X`M-x calc' to run the Calculator.  Type `?' for help; read `calc.texinfo'
Xfor the complete documentation.
X
XDon't even try to run Calc in uncompiled (.el) form!  It's far too slow.
X
X
XI am anxious to hear about your experiences using Calc.  Send mail to
X"daveg@csvax.caltech.edu", or "cit-vax!daveg".  A bug report is most
Xuseful if you include the exact input and output that occurred, any
Xmodes in effect (such as the current precision), and so on.  If you
Xfind Calc is difficult to operate in any way, or if you have other
Xsuggestions, don't hesitate to let me know.  If you find errors
X(including simple typos) in the manual, let me know.  Even if you find
Xno bugs at all I would love to hear your opinions.
X
XThe latest Calc tar files and patches are available for anonymous FTP
Xon csvax.caltech.edu.  Look in the "pub" subdirectory.
X
XThanks,
X
X								-- Dave
X
X
X
X
X
XSummary of changes to "Calc"
X------- -- ------- --  ----
X
X
XVersion 1.01:
X
X * Added a tutorial section to the manual.
X
X * Next and Prev for node Strings in the manual were reversed; fixed.
X
X * Changed "'bignum" in calc-isqrt-bignum-iter to "'bigpos".
X
X * Fixed a bug that prevented "$" from working during algebraic entry.
X
X * Fixed a bug caused by an X (last-X) command following a K (macro) command.
X
X * Fixed a bug in which K command incorrectly formatted stack in Big mode.
X
X * Added space between unary operators and non-flat compositions.
X   (Otherwise, "-(a/b)" in Big mode blended the minus sign into the rule!)
X
X * Fixed formatting of (-1)^n in Big mode.
X
X * Fixed some problems relating to "not" operator in Pascal language mode.
X
X * Fixed several bugs relating to V M ' and V M $ sequences.
X
X * Fixed matrix-vector multiplication to produce a vector.
X
X * Introduced Z ` ... Z ' commands; renamed old Z ' to Z #.
X
X * Fixed various other bugs.
X
X * Added calc-settings-file variable suggested by C. Witty.
X
XVersion 1.00:
X
X * First official release of Calc.
X
X * If you used the Beta test version (0.01), you will find that this
X   version of Calc is over 50% larger than the original release.
X   General areas of improvement include much better algebra features;
X   operations on units; language modes; simplification modes; interval
X   arithmetic; vector mapping and reduction.  Other new commands include
X   calc-fraction and calc-grab-region.  The program has been split into
X   two parts for faster loading, and the manual is more complete.
X
SHAR_EOF
chmod 0664 README || echo "restore of README fails"
set `wc -c README`;Sum=$1
if test "$Sum" != "5418"
then echo original size 5418, current size $Sum;fi
echo "x - extracting INSTALL (Text)"
sed 's/^X//' << 'SHAR_EOF' > INSTALL &&
X
XInstallation
X************
X
XCalc comes as a pair of Emacs Lisp files, generally called `calc.el' and
X`calc-ext.el'.  The first contains the basic foundations of the
XCalculator, and is as small as possible to promote quick loading.  The
Xsecond contains all the more advanced commands and functions.  Calc is
Xusually installed so that the `M-x calc' or `M-#' command auto-loads
Xonly the first part, and the second part is auto-loaded whenever the
Xfirst advanced feature is used.
X
XCalc is written in a way that maximizes performance when its code has been
Xbyte-compiled; a side effect is that performance is seriously degraded if
Xit *isn't* compiled.  Thus, it is essential to compile the Calculator
Xbefore trying to use it.  The Emacs command `M-x byte-compile-file'
Xis used to compile an Emacs Lisp file.  Compile each of `calc.el' and
X`calc-ext.el' to obtain byte-code files `calc.elc' and
X`calc-ext.elc'.  You may find you need to do `M-x load-file
Xcalc.elc' before compiling `calc-ext.el' will work.
X
XFor your convenience, the FTP distribution of Calc, obtainable from
Xanonymous FTP on `csvax.caltech.edu', includes already-compiled
Xversions of both of these files.
X
XTo teach Emacs how to load in Calc when you type `M-x calc' for the
Xfirst time, include these lines in your `.emacs' file (if you are
Xinstalling Calc just for your own use), or the system's `lisp/default'
Xfile (if you are installing Calc publicly).
X
X     (autoload 'calc             ".../calc.elc"     "Calculator Mode" t nil)
X     (autoload 'calc-extensions  ".../calc-ext.elc" nil nil nil)
X     (autoload 'quick-calc       ".../calc.elc"     "Quick Calculator" t nil)
X     (autoload 'calc-grab-region ".../calc-ext.elc" nil t nil)
X     (autoload 'defmath          ".../calc-ext.elc" nil t t)
X
Xwhere `.../calc.elc' represents the full path to the `calc.elc'
Xfile, and similarly for `.../calc-ext.elc'.  If you have installed
Xthese files in Emacs' main `lisp/' directory, you can just write
X`"calc.elc"' and `"calc-ext.elc"'.
X
XThe `autoload' command for `calc' is what loads `calc.elc'
Xwhen you type `M-x calc'.  The `autoload' for `calc-extensions'
Xbrings in the extensions module; Calc takes care to call the
X`calc-extensions' function (which doesn't actually do anything)
Xbefore any operation that requires the extensions to be present.
XThe other three `autoload' commands are for functions which might
Xreasonably be used before the user has typed `M-x calc' for the
Xfirst time.
X
XIf you don't want to bother with a split Calculator, you can simply
Xconcatenate `calc-ext.elc' onto the end of `calc.elc', rewrite
Xthe above `autoload' commands all to point to the combined file,
Xand treat Calc as one big program.  You may need to do this if
X`autoload' is giving you problems.
X
XYou may also wish to bind the `calc' command to a key.  The
Xrecommended keystroke is `M-#' (i.e., Meta-Shift-3).  To set up
Xthis key binding, include this command in your `.emacs' or
X`lisp/default' file:
X
X     (global-set-key "\e#" 'calc)
X
XThere are no standard key assignments for `quick-calc' and
X`calc-grab-region', but you may wish to define some.
X
XThe file `macedit.el' contains another useful Emacs extension
Xcalled `edit-kbd-macro'.  It allows you to edit a keyboard macro
Xin human-readable form.  The `Z E' command in Calc knows how to
Xuse it to edit user commands that have been defined by keyboard macros.
XTo autoload it, you will want to include the commands,
X
X     (autoload 'edit-kbd-macro      ".../macedit.elc" "Edit Keyboard Macro" t nil)
X     (autoload 'edit-last-kbd-macro ".../macedit.elc" "Edit Keyboard Macro" t nil)
X
XThe documentation for Calc (i.e., this manual) comes in a file
X`calc.texinfo'.  To format this for use as an on-line manual,
Xopen this file for editing in Emacs and give the command
X`M-x texinfo-format-buffer'.  When this finishes, type `C-x C-s'
Xto save.  The result will be a collection of files whose names begin
Xwith `calc-info'.  You can also format this into a printable
Xdocument using TeX, but beware, the manual is about 170 printed pages!
X
XThere is a Lisp variable called `calc-info-filename' which holds
Xthe name of the Info file containing Calc's on-line documentation.
XIts default value is `calc-info', which will work correctly if
Xthe Info files are stored in Emacs' main `info/' directory.  If
Xyou keep them elsewhere, you will want to put a command of the form,
X
X     (setq calc-info-filename ".../calc-info")
X
Xin your `.emacs' or `lisp/default' file, where again `...'
Xrepresents the directory containing the Info files.
X
XAnother variable you might want to set is `calc-settings-file', which
Xholds the file name in which commands like `m m' and `Z P' store
X"permanent" definitions.  The default value for this variable is
X`"~/.emacs"'.  If `calc-settings-file' does not contain `".emacs"' as a
Xsubstring, and if the variable `calc-loaded-settings-file' is `nil',
Xthen Calc will automatically load your settings file (if it exists) the
Xfirst time Calc is invoked.
X
XTo test your installation of Calc, start a fresh Emacs and type `M-#'
Xto make sure the autoload commands and key bindings work.  Now, type
X`i' to make sure Calc can find its Info documentation.  Press `q'
Xto exit the Info system.  Type `20 S' to compute the sine of
X20 degrees; this will test the autoloading of the extensions module.
XThe result should be 0.342020143326.  Finally, press `M-#' again to
Xmake sure the Calculator can exit.
X
X(The above text is included in both the Calc documentation and the
Xfile INSTALL in the Calc distribution directory.)
SHAR_EOF
chmod 0644 INSTALL || echo "restore of INSTALL fails"
set `wc -c INSTALL`;Sum=$1
if test "$Sum" != "5522"
then echo original size 5522, current size $Sum;fi
echo "x - extracting calc.el (Text)"
sed 's/^X//' << 'SHAR_EOF' > calc.el &&
X;; Calculator for GNU Emacs
X;; Copyright (C) 1990 Dave Gillespie
X
X;; This file is part of GNU Emacs.
X
X;; GNU Emacs is distributed in the hope that it will be useful,
X;; but WITHOUT ANY WARRANTY.  No author or distributor
X;; accepts responsibility to anyone for the consequences of using it
X;; or for whether it serves any particular purpose or works at all,
X;; unless he says so in writing.  Refer to the GNU Emacs General Public
X;; License for full details.
X
X;; Everyone is granted permission to copy, modify and redistribute
X;; GNU Emacs, but only under the conditions described in the
X;; GNU Emacs General Public License.   A copy of this license is
X;; supposed to have been given to you along with GNU Emacs so you
X;; can know your rights and responsibilities.  It should be in a
X;; file named COPYING.  Among other things, the copyright notice
X;; and this notice must be preserved on all copies.
X
X
X;;; This is part I of the Emacs Calculator.  It defines simple arithmetic
X;;; commands only.  Assuming the autoload commands shown below have been
X;;; done, the Calculator will autoload the remaining commands from calc-ext.elc
X;;; whenever one is first needed.  If you wish, you can concatenate calc-ext
X;;; onto the end of calc (.el or .elc) to make one big file.
X
X;;; Suggested usage:
X;;;
X;;;   (autoload 'calc ".../calc.elc" "Calculator Mode" t nil)
X;;;   (autoload 'quick-calc ".../calc.elc" "Quick Calculator" t nil)
X;;;   (autoload 'calc-grab-region ".../calc-ext.elc" nil t nil)
X;;;   (autoload 'defmath ".../calc-ext.elc" nil t t)
X;;;   (autoload 'calc-extensions ".../calc-ext.elc" nil nil nil)
X;;;   (global-set-key "\e#" 'calc)
X;;;   M-x calc
X;;;
X;;; where ".../calc.elc" represents the full path for "calc.elc",
X;;; and ".../calc-ext.elc" is the path of the companion file containing
X;;; all of the more advanced Calc commands.
X
X
X;;; Author's address:
X;;;   Dave Gillespie, 256-80 Caltech, Pasadena CA 91125.
X;;;   daveg@csvax.caltech.edu, ...!cit-vax!daveg.
X;;;
X;;; This file and the manual, calc.texinfo, are available from anonymous FTP
X;;; on csvax.caltech.edu [192.12.18.1]; look in ~ftp/pub/calc.
X;;;
X;;; Bug reports and suggestions are always welcome!
X
X
X;;; All functions, macros, and Lisp variables defined here begin with one
X;;; of the prefixes "math", "Math", or "calc", with the exception of
X;;; "another-calc".  User-accessible variables begin with "var-".
X
X
X
X(provide 'calc)
X
X(defmacro calc-record-compilation-date-macro ()
X  (` (setq calc-version (concat "Emacs Calc Mode"
X				" v1.01 by Dave Gillespie"
X				", installed "
X				(, (current-time-string))
X				" by "
X				(, (user-full-name)))))
X)
X(defun calc-record-compilation-date ()
X  (calc-record-compilation-date-macro)
X)
X(calc-record-compilation-date)
X
X
X(defvar calc-info-filename "calc-info"
X  "*File name in which to look for the Calculator's Info documentation.")
X
X
X(defvar calc-extensions-loaded nil)
X
X
X
X;;; IDEAS:
X;;;
X;;;   Consider breaking calc-ext.el into several extension modules:
X;;;      Base extensions, algebra/units, scientific, programming
X;;;
X;;;   How about putting cursor on an operator or functor in stack window
X;;;      to indicate the subterm to which a command should apply?
X;;;   Make math-simplify faster!
X;;;   Provide analogues of Mathematica's polynomial-munching ops:
X;;;      Together, Apart, Cancel, Factor, GCD, quotient/remainder.
X;;;   Automatically generate derivatives for functions defined with Z F.
X;;;   Handle commutativity and associativity among +, -, *, / in rewrite rules.
X;;;
X;;;   In no-simplify mode, have a key which executes the top-level call
X;;;      once, but does not execute any of the arguments' calls.
X;;;   Put a set of evaluations in the c-prefix menu, analogous to m-prefix.
X;;;
X;;;   During algebraic entry, hit ` to switch to calc-edit entry.
X;;;
X;;;   When the stack is truncated, put the "." on the *second*-to-bottom line.
X;;;   When formatting formulas, suppress extra spaces inside vectors!
X;;;   Implement line-breaking in non-flat compositions.
X;;;   Implement structured line-breaking using level information.
X;;;   Implement matrix formatting with multi-line components.
X;;;
X;;;   Support lambda notation in Z F and Z G commands.
X;;;   Have "Z R" define a user command based on a set of rewrite rules.
X;;;   Support "incf" and "decf" in defmath definitions.
X;;;   Have defmath generate calls to calc-binary-op or calc-unary-op.
X;;;
X;;;   Allow calc-word-size=0 => Common Lisp-style signed bitwise arithmetic.
X;;;   Consider implementing some other special functions.
X;;;   May as well make continued-fractions stuff available to the user.
X;;;   Provide date arithmetic a la HP 48.
X;;;
X;;;   Implement some more built-in statistical functions:
X;;;      mean, median, variance, std dev of a list.
X;;;   How about fitting a list or Nx2 matrix to a line or curve.
X;;;
X;;;   How about matrix eigenvalues, SVD, pseudo-inverse, etc.?
X;;;   Should cache matrix inverses as well as decompositions.
X;;;   Allow calc-edit to edit a matrix in a more convenient form.
X;;;
X;;;   Replace hokey formulas for complex functions with formulas designed
X;;;      to minimize roundoff while maintaining the proper branch cuts.
X;;;   Provide a better implementation for math-sin-cos-raw.
X;;;   Provide a better implementation for math-hypot.
X;;;   Provide a better implementation for math-make-frac.
X;;;   Provide a better implementation for math-prime-factors.
X;;;   Provide a better implementation for math-integral.
X;;;   Clean up some of the definitions in the units table.
X;;;   Implement dfact for large inputs using gamma function.
X;;;
X;;;   Provide more examples in the tutorial section of the manual.
X;;;   Cover in the tutorial:  language modes, simplification modes,
X;;;       bitwise stuff, rewrite rules.
X;;;   Provide more Lisp programming examples in the manual.
X;;;   Finish the Internals section of the manual.
X;;;
X;;;   Tim suggests adding spreadsheet-like features.
X;;;   How about ultra-low-resolution plots?  (Probably too slow.)
X;;;   Implement language modes for Lisp, Ada, ...?
X;;;
X
X
X;;; Graphically manipulating a composed expression:
X;;;   Have an option in math-compose-expr which wraps each term with a
X;;;   "(tag C X)" form where C is the composition term and X is the
X;;;   sub-expression that generated it.  Now, call a variant of
X;;;   math-simplify-comp which returns the innermost X whose C contained
X;;;   a given (x,y) location.  In addition, have a variant of
X;;;   math-simplify-comp which replaces every non-blank character inside
X;;;   a tag form for a given X with some highlight character like "#".
X;;;   (Consider supporting Epoch's true highlighting here.)
X
X;;; Idea: Have "{" and "}" mean select next larger or smaller sub-formula
X;;;   around the cursor; when a sub-formula is selected, the next command
X;;;   (of any sort) applies to that sub-formula.  Have calc-top-n and
X;;;   calc-enter-result fake this up.  Print a warning if a stack entry is
X;;;   highlighted which is not touched by the next command.
X
X
X;;; For atan series, if x > tan(pi/12) (about 0.268) reduce using the identity
X;;;   atan(x) = atan((x * sqrt(3) - 1) / (sqrt(3) + x)) + pi/6.
X
X
X;;; A better integration algorithm:
X;;;   Use breadth-first instead of depth-first search, as follows:
X;;;	The integral cache allows unfinished integrals in symbolic notation
X;;;	on the righthand side.  An entry with no unfinished integrals on the
X;;;	RHS is "complete"; references to it elsewhere are replaced by the
X;;;	integrated value.  More than one cache entry for the same integral
X;;;	may exist, though if one becomes complete, the others may be deleted.
X;;;	The integrator works by using every applicable rule (such as
X;;;	substitution, parts, linearity, etc.) to generate possible righthand
X;;;	sides, all of which are entered into the cache.  Now, as long as the
X;;;	target integral is not complete (and the time limit has not run out)
X;;;	choose an incomplete integral from the cache and, for every integral
X;;;	appearing in its RHS's, add those integrals to the cache using the
X;;;	same substitition, parts, etc. rules.  The cache should be organized
X;;;	as a priority queue, choosing the "simplest" incomplete integral at
X;;;	each step, or choosing randomly among equally simple integrals.
X;;;	Simplicity equals small size, and few steps removed from the original
X;;;	target integral.  Note that when the integrator finishes, incomplete
X;;;	integrals can be left in the cache, so the algorithm can start where
X;;;	it left off if another similar integral is later requested.
X;;;   Breadth-first search would avoid the nagging problem of, e.g., whether
X;;;   to use parts or substitution first, and which decomposition is best.
X;;;   All are tried, and any path that diverges will quickly be put on the
X;;;   back burner by the priority queue.
X;;;   Note: Probably a good idea to call math-simplify-extended before
X;;;   measuring a formula's simplicity.
X
X
X
X
X
X
X;;; NOTE: The default values listed below and those defined in
X;;;       calc-mode-vars-list must match.
X
X(defvar calc-mode-map nil "Keymap for calc-mode.")
X(defvar calc-digit-map nil "Keymap for digit entry in calc-mode.")
X
X(defvar calc-trail-pointer nil "\"Current\" entry in trail buffer.")
X
X(defvar calc-stack '((top-of-stack 1)) "Calculator stack.")
X(defvar calc-undo-list nil "List of previous operations in calc-mode.")
X(defvar calc-redo-list nil "List of recent undo operations in calc-mode.")
X(defvar calc-main-buffer nil "The Calculator buffer.")
X(defvar calc-why nil "Explanations of most recent errors.")
X(defvar calc-next-why nil)
X
X(defvar calc-last-kill nil "Last number killed in calc-mode.")
X(defvar calc-previous-alg-entry nil "Previous string entered with algebraic entry.")
X(defvar calc-dollar-values nil "Values to be used for '$' in expressions.")
X(defvar calc-dollar-used nil "Highest order of '$' that occur in expression.")
X(defvar calc-quick-prev-results nil "Previous results from Quick Calc.")
X
X(defvar calc-always-load-extensions nil
X  "*If non-NIL, load the calc-ext module automatically when calc is loaded.")
X
X(defvar calc-stack-top 1
X  "Index into calc-stack of \"top\" of stack.
XThis is 1 unless calc-truncate-stack has been used.")
X
X(defvar calc-line-numbering t
X  "*If non-NIL, display line numbers in Calculator stack.")
X
X(defvar calc-line-breaking t
X  "*If non-NIL, break long values across multiple lines in Calculator stack.")
X
X(defvar calc-display-just nil
X  "*If NIL, stack display is left-justified.
XIf 'right, stack display is right-justified.
XIf 'center, stack display is centered."
X)
X
X(defvar calc-number-radix 10
X  "*Radix for entry and display of numbers in calc-mode, 2-36.")
X
X(defvar calc-leading-zeros nil
X  "*If non-NIL, leading zeros are provided to pad integers to calc-word-size.")
X
X(defvar calc-group-digits nil
X  "*If non-NIL, group digits in large displayed integers by inserting spaces.
XIf an integer, group that many digits at a time.
XIf 't', use 4 for binary and hex, 3 otherwise.")
X
X(defvar calc-group-char ","
X  "*The character (in the form of a string) to be used for grouping digits.
XThis is used only when calc-group-digits mode is on.")
X
X(defvar calc-point-char "."
X  "*The character (in the form of a string) to be used as a decimal point.")
X
X(defvar calc-frac-format ":"
X  "*Format of displayed fractions; a string of one or two of \":\" or \"/\".")
X
X(defvar calc-prefer-frac nil
X  "*If non-NIL, prefer fractional over floating-point results.")
X
X(defvar calc-hms-format "%s@ %s' %s\""
X  "*Format of display hours-minutes-seconds angles, a format string.
XString must contain three %s marks, for hours, minutes, seconds respectively.")
X
X(defvar calc-float-format '(float 0)
X  "*Format to use for display of floating-point numbers in calc-mode.
XMust be a list of one of the following forms:
X   (float 0)      Floating point format, display full precision.
X   (float N)      N > 0: Floating point format, at most N significant figures.
X   (float -N)     -N < 0: Floating point format, calc-internal-prec - N figs.
X   (fix N)        N >= 0: Fixed point format, N places after decimal point.
X   (sci 0)        Scientific notation, full precision.
X   (sci N)        N > 0: Scientific notation, N significant figures.
X   (sci -N)       -N < 0: Scientific notation, calc-internal-prec - N figs.
X   (eng 0)        Engineering notation, full precision.
X   (eng N)        N > 0: Engineering notation, N significant figures.
X   (eng -N)       -N < 0: Engineering notation, calc-internal-prec - N figs.")
X
X(defvar calc-full-float-format '(float 0)
X  "*Format to use when full precision must be displayed.")
X
X(defvar calc-complex-format nil
X  "*Format to use for display of complex numbers in calc-mode.  Must be one of:
X   nil            Use (x, y) form.
X   i              Use x + yi form.
X   j              Use x + yj form.")
X
X(defvar calc-complex-mode 'cplx
X  "*Preferred form, either 'cplx or 'polar, for complex numbers.")
X
X(defvar calc-display-strings nil
X  "*If non-NIL, display vectors of byte-sized integers as strings.")
X
X(defvar calc-matrix-just 'center
X  "*If NIL, vector elements are left-justified.
XIf 'right, vector elements are right-justified.
XIf 'center, vector elements are centered."
X)
X
X(defvar calc-vector-commas ","
X  "*If non-NIL, separate elements of displayed vectors with this string.")
X
X(defvar calc-vector-brackets "[]"
X  "*If non-NIL, surround displayed vectors with these characters.")
X
X(defvar calc-function-open "("
X  "*Open-parenthesis string for function call notation.")
X
X(defvar calc-function-close ")"
X  "*Close-parenthesis string for function call notation.")
X
X(defvar calc-language nil
X  "*Language or format for entry and display of stack values.  Must be one of:
X   nil            Use standard Calc notation.
X   flat           Use standard Calc notation, one-line format.
X   big 	          Display formulas in 2-d notation (enter w/standard notation).
X   unform	  Use unformatted display: add(a, mul(b,c)).
X   c              Use C language notation.
X   pascal         Use Pascal language notation.
X   fortran        Use Fortran language notation.
X   tex            Use TeX notation.
X   math           Use Mathematica(tm) notation.")
X
X(defvar calc-language-option nil
X  "*Numeric prefix argument for the command that set calc-language.")
X
X(defvar calc-language-output-filter nil
X  "Function through which to pass strings after formatting.")
X
X(defvar calc-language-input-filter nil
X  "Function through which to pass strings before parsing.")
X
X(defvar calc-radix-formatter nil
X  "*Formatting function used for non-decimal integers.")
X
X(defvar calc-word-size 32
X  "*Minimum number of bits per word, if any, for binary operations in calc-mode.")
X
X(defvar calc-previous-modulo nil
X  "*Most recently used value of M in a modulo form.")
X
X(defvar calc-simplify-mode nil
X  "*Type of simplification applied to results.
XIf 'none, results are not simplified when pushed on the stack.
XIf 'num, functions are simplified only when args are constant.
XIf NIL, only fast simplifications are applied.
XIf 'binary, math-clip is applied if appropriate.
XIf 'alg, math-simplify is applied.
XIf 'ext, math-simplify-extended is applied.
XIf 'units, math-simplify-units is applied.")
X
X(defvar calc-mapping-dir nil
X  "*Last direction specified in a Map or Reduce command.")
X
X(defvar calc-display-raw nil
X  "*If non-NIL, calculator display shows unformatted Lisp exprs.  (For debugging)")
X
X(defvar calc-display-sci-high 0
X  "*Floating-point numbers with this positive exponent or higher above the
Xcurrent precision are displayed in scientific notation in calc-mode.")
X
X(defvar calc-display-sci-low -3
X  "*Floating-point numbers with this negative exponent or lower are displayed
Xscientific notation in calc-mode.")
X
X(defvar calc-internal-prec 12
X  "*Number of digits of internal precision for calc-mode calculations.")
X
X(defvar calc-inverse-flag nil
X  "*If non-NIL, next operation is Inverse.")
X
X(defvar calc-hyperbolic-flag nil
X  "*If non-NIL, next operation is Hyperbolic.")
X
X(defvar calc-angle-mode 'deg
X  "*If deg, angles are in degrees; if rad, angles are in radians.
XIf hms, angles are in degrees-minutes-seconds.")
X
X(defvar calc-algebraic-mode nil
X  "*If non-NIL, numeric entry accepts whole algebraic expressions.
XIf NIL, algebraic expressions must be preceded by \"'\".")
X
X(defvar calc-symbolic-mode nil
X  "*If non-NIL, inexact numeric computations like sqrt(2) are postponed.
XIf NIL, computations on numbers always yield numbers where possible.")
X
X(defvar calc-integral-limit 3
X  "*An integer which governs how long calc-integral will look for an integral.
XThe integrator often uses substitution or integration by parts to transform
Xan integral into another one; this controls how many levels of nested
Xsub-integrations are allowed before a given path is abandoned.")
X
X(defvar calc-window-height 7
X  "*Initial height of Calculator window.")
X
X(defvar calc-display-trail t
X  "*If non-NIL, M-x calc creates a window to display Calculator trail.")
X
X(defvar calc-display-working-message 'lots
X  "*If non-NIL, display \"Working...\" for potentially slow Calculator commands.")
X
X(defvar calc-auto-why nil
X  "*If non-NIL, automatically execute a \"why\" command to explain odd results.")
X
X(defvar calc-said-hello nil)
X(defvar calc-executing-macro nil)
X
X
X(defvar calc-other-modes nil
X  "List of used-defined strings to append to Calculator mode line.")
X
X
X(defvar calc-settings-file "~/.emacs"
X  "*File in which to record permanent settings; default is \"~/.emacs\".")
X
X(defvar calc-loaded-settings-file nil)
X
X
X(defvar calc-bug-address "daveg@csvax.caltech.edu"
X  "*Address of the author of Calc, for use by report-calc-bug.")
X
X
X(defvar var-i '(special-const (math-imaginary 1))
X  "*Calculator variable representing the imaginary constant 'i'.")
X
X(defvar var-pi '(special-const (math-pi))
X  "*Calculator variable representing the constant 'pi'.")
X
X(defvar var-e '(special-const (math-e))
X  "*Calculator variable representing the constant 'e'.")
X
X
X
X;;; Set up the standard keystroke (M-#) to run the Calculator, if that key
X;;; has not yet been bound to anything.  For best results, the user should
X;;; do this before Calc is even loaded, so that M-# can auto-load Calc.
X(or (global-key-binding "\e#")
X    (global-set-key "\e#" 'calc))
X
X
X(defun calc-define-del (map func)
X  (define-key map "\C-d" func)
X  (mapcar (function (lambda (x) (define-key map x func)))
X	  (append (where-is-internal 'delete-backward-char global-map)
X		  (where-is-internal 'backward-delete-char global-map)))
X)
X
X;; Still unused: f g j O W Y { }
X(if calc-mode-map
X    nil
X  (setq calc-mode-map (make-keymap))
X  (suppress-keymap calc-mode-map t)
X  (define-key calc-mode-map "+" 'calc-plus)
X  (define-key calc-mode-map "-" 'calc-minus)
X  (define-key calc-mode-map "*" 'calc-times)
X  (define-key calc-mode-map "/" 'calc-divide)
X  (define-key calc-mode-map "%" 'calc-mod)
X  (define-key calc-mode-map "&" 'calc-inv)
X  (define-key calc-mode-map "^" 'calc-power)
X  (define-key calc-mode-map "e" 'calcDigit-start)
X  (define-key calc-mode-map "h" 'describe-mode)
X  (define-key calc-mode-map "i" 'calc-info)
X  (define-key calc-mode-map "n" 'calc-change-sign)
X  (define-key calc-mode-map "o" 'calc-realign)
X  (define-key calc-mode-map "p" 'calc-precision)
X  (define-key calc-mode-map "q" 'calc-quit)
X  (define-key calc-mode-map "w" 'calc-why)
X  (define-key calc-mode-map "?" 'calc-help)
X  (define-key calc-mode-map " " 'calc-enter)
X  (define-key calc-mode-map "<" 'calc-scroll-left)
X  (define-key calc-mode-map ">" 'calc-scroll-right)
X  (define-key calc-mode-map "'" 'calc-algebraic-entry)
X  (define-key calc-mode-map "$" 'calc-auto-alg-entry)
X  (define-key calc-mode-map "\"" 'calc-auto-alg-entry)
X  (define-key calc-mode-map "\t" 'calc-roll-down)
X  (define-key calc-mode-map "\M-\t" 'calc-roll-up)
X  (define-key calc-mode-map "\C-m" 'calc-enter)
X  (define-key calc-mode-map "\C-j" 'calc-over)
X  (calc-define-del calc-mode-map 'calc-pop)
X  (mapcar (function
X	   (lambda (x)
X	     (define-key calc-mode-map (char-to-string x) 'undefined)))
X	  "fgjOWY{}")
X  (mapcar (function
X	   (lambda (x)
X	     (define-key calc-mode-map (char-to-string x) 'calc-missing-key)))
X	  (concat "ABCDEFGHIJKLMNPQRSTUVXZabcdklmrstuvxyz"
X		  ":\\|!()[],;=~`\C-k\M-k\C-w\M-w\C-y\C-_"))
X  (mapcar (function
X	   (lambda (x)
X	     (define-key calc-mode-map (char-to-string x) 'calcDigit-start)))
X	  "_0123456789.#@")
X)
X
X(if calc-digit-map
X    nil
X  (setq calc-digit-map (make-keymap))
X  (let ((i 0))
X    (while (< i 128)
X      (aset calc-digit-map i
X	    (if (eq (aref calc-mode-map i) 'undefined)
X		'undefined 'calcDigit-nondigit))
X      (setq i (1+ i))))
X  (mapcar (function
X	   (lambda (x)
X	     (define-key calc-digit-map (char-to-string x) 'calcDigit-key)))
X	  "_0123456789.e+-:n#@oh'\"mspM")
X  (mapcar (function
X	   (lambda (x)
X	     (define-key calc-digit-map (char-to-string x) 'calcDigit-letter)))
X	  "abcdfgijklqrtuvwxyzABCDEFGHIJKLNOPQRSTUVWXYZ")
X  (define-key calc-digit-map "'" 'calcDigit-algebraic)
X  (define-key calc-digit-map "\C-g" 'abort-recursive-edit)
X  (calc-define-del calc-digit-map 'calcDigit-backspace)
X)
X
X(put 'calc-mode 'mode-class 'special)
X(put 'calc-trail-mode 'mode-class 'special)
X
X(defconst calc-mode-var-list '((calc-always-load-extensions nil)
X			       (calc-line-numbering t)
X			       (calc-line-breaking t)
X			       (calc-display-just nil)
X			       (calc-number-radix 10)
X			       (calc-leading-zeros nil)
X			       (calc-group-digits nil)
X			       (calc-group-char ",")
X			       (calc-point-char ".")
X			       (calc-frac-format ":")
X			       (calc-prefer-frac nil)
X			       (calc-hms-format "%s@ %s' %s\"")
X			       (calc-float-format (float 0))
X			       (calc-full-float-format (float 0))
X			       (calc-complex-format nil)
X			       (calc-matrix-just center)
X			       (calc-vector-commas ",")
X			       (calc-vector-brackets "[]")
X			       (calc-complex-mode cplx)
X			       (calc-simplify-mode nil)
X			       (calc-mapping-dir nil)
X			       (calc-word-size 32)
X			       (calc-previous-modulo nil)
X			       (calc-internal-prec 12)
X			       (calc-angle-mode deg)
X			       (calc-algebraic-mode nil)
X			       (calc-symbolic-mode nil)
X			       (calc-integral-limit 3)
X			       (calc-window-height 7)
X			       (calc-language nil)
X			       (calc-language-option nil)
X			       (calc-display-trail t)
X			       (calc-display-working-message lots)
X			       (calc-auto-why nil)))
X
X(defconst calc-local-var-list '(calc-stack
X				calc-stack-top
X				calc-undo-list
X				calc-redo-list
X				calc-always-load-extensions
X				calc-display-raw
X				calc-line-numbering
X				calc-line-breaking
X				calc-display-just
X				calc-auto-why
X				calc-algebraic-mode
X				calc-symbolic-mode
X				calc-integral-limit
X				calc-inverse-flag
X				calc-hyperbolic-flag
X				calc-angle-mode
X				calc-number-radix
X				calc-leading-zeros
X				calc-group-digits
X				calc-group-char
X				calc-point-char
X				calc-frac-format
X				calc-prefer-frac
X				calc-hms-format
X				calc-float-format
X				calc-full-float-format
X				calc-complex-format
X				calc-matrix-just
X				calc-vector-commas
X				calc-vector-brackets
X				calc-complex-mode
X				calc-simplify-mode
X				calc-mapping-dir
X				calc-word-size
X				calc-internal-prec))
X
X
X(defun calc-mode ()
X  "Calculator major mode.
X
XThis is an RPN calculator featuring arbitrary-precision integer, rational,
Xfloating-point, complex, matrix, and symbolic arithmetic.
X
XRPN calculation:  2 RET 3 +    produces 5.
XAlgebraic style:  ' 2+3 RET    produces 5.
X
XOperators are +, -, *, /, ^ (power), % (modulo), n (change-sign).
X
XPress ? repeatedly for more complete help.
X
XNotations:  3.14e6     3.14 * 10^6
X            _23        negative number -23
X            17:3       the fraction 17/3
X            5:2:3      the fraction 5 and 2/3
X            16#12C     the integer 12C base 16 = 300 base 10
X            8#177:100  the fraction 177:100 base 8 = 127:64 base 10
X            (2, 4)     complex number 2 + 4i
X            (2; 4)     polar complex number (r; theta)
X            [1, 2, 3]  vector  ([[1, 2], [3, 4]] is a matrix)
X            [1 .. 4)   semi-open interval, 1 <= x < 4
X            2 +/- 3    (p key) number with mean 2, standard deviation 3
X            2 mod 3    (M key) number 2 computed modulo 3
X
X\\{calc-mode-map}
X"
X  (interactive)
X  (mapcar (function
X	   (lambda (v) (set-default v (symbol-value v)))) calc-local-var-list)
X  (kill-all-local-variables)
X  (use-local-map calc-mode-map)
X  (mapcar (function (lambda (v) (make-local-variable v))) calc-local-var-list)
X  (setq truncate-lines t)
X  (setq buffer-read-only t)
X  (setq major-mode 'calc-mode)
X  (setq mode-name "Calculator")
X  (if (memq 'top-of-stack (mapcar 'car-safe calc-stack))
X      (setq calc-stack (copy-sequence calc-stack))
X    (setq calc-stack '((top-of-stack 1))
X	  calc-stack-top 1))   ; backward compatibility
X  (or calc-loaded-settings-file
X      (string-match "\\.emacs" calc-settings-file)
X      (progn
X	(setq calc-loaded-settings-file t)
X	(load calc-settings-file t)))   ; t = missing-ok
X  (run-hooks 'calc-mode-hook)
X  (calc-refresh t)
X  (calc-set-mode-line)
X  (if (and (boundp 'calc-defs)
X	   calc-defs)
X      (progn
X	(message "Evaluating calc-defs...")
X	(eval (cons 'progn calc-defs))
X	(setq calc-defs nil)
X	(calc-refresh t)
X	(calc-set-mode-line)))
X)
X
X(defun calc-trail-mode (&optional buf)
X  (interactive)
X  (fundamental-mode)
X  (use-local-map calc-mode-map)
X  (setq major-mode 'calc-trail-mode)
X  (setq mode-name "Calc Trail")
X  (setq truncate-lines nil)
X  (setq buffer-read-only t)
X  (if buf
X      (progn
X	(make-local-variable 'calc-main-buffer)
X	(setq calc-main-buffer buf)))
X  (if (= (buffer-size) 0)
X      (let ((buffer-read-only nil))
X	(insert calc-version
X		"\n")))
X  (or (and calc-trail-pointer
X	   (eq (marker-buffer calc-trail-pointer) (current-buffer)))
X      (save-excursion
X	(goto-line 2)
X	(setq calc-trail-pointer (point-marker))))
X  (run-hooks 'calc-trail-mode-hook)
X)
X
X(defun calc-create-buffer ()
X  (set-buffer (get-buffer-create "*Calculator*"))
X  (if (or (not (eq major-mode 'calc-mode))
X	  (and (boundp 'calc-defs) calc-defs))
X      (calc-mode))
X  (if calc-always-load-extensions
X      (calc-extensions))
X  (if calc-language
X      (progn
X	(calc-extensions)
X	(calc-set-language calc-language calc-language-option t)))
X)
X
X(defun calc (&optional arg no-display)
X  "The Emacs Calculator.  Full documentation is listed under \"calc-mode\"."
X  (interactive "P")
X  (or (fboundp 'calc-extensions)
X      (autoload 'calc-extensions "calc-ext"))
X  (if arg
X      (or (eq arg 0)
X	  (progn
X	    (calc-extensions)
X	    (if (< (prefix-numeric-value arg) 0)
X		(calc-grab-region (region-beginning) (region-end)))))
X    (if (eq major-mode 'calc-mode)
X	(calc-quit)
X      (let ((oldbuf (current-buffer)))
X	(calc-create-buffer)
X	(if (get-buffer-window (current-buffer))
X	    (select-window (get-buffer-window (current-buffer)))
X	  (if (and (boundp 'calc-window-hook) calc-window-hook)
X	      (run-hooks 'calc-window-hook)
X	    (let ((w (get-largest-window)))
X	      (if (and pop-up-windows
X		       (> (window-height w)
X			  (+ window-min-height calc-window-height 2)))
X		  (progn
X		    (setq w (split-window w
X					  (- (window-height w)
X					     calc-window-height 2)
X					  nil))
X		    (set-window-buffer w (current-buffer))
X		    (select-window w))
X		(pop-to-buffer (current-buffer))))))
X	(save-excursion
X	  (let ((buf (current-buffer)))
X	    (set-buffer (get-buffer-create "*Calc Trail*"))
X	    (calc-trail-mode buf)
X	    (and calc-display-trail
X		 (= (window-width) (screen-width))
X		 (calc-trail-display 1 t))))
X	(setq max-lisp-eval-depth (max max-lisp-eval-depth 1000))
X	(calc-summary)
X	(and calc-said-hello
X	     (interactive-p)
X	     (progn
X	       (sit-for 2)
X	       (message "")))
X	(setq calc-said-hello t)
X	(run-hooks 'calc-start-hook))))
X)
X
X(defun another-calc ()
X  "Create another, independent Calculator buffer."
X  (interactive)
X  (if (eq major-mode 'calc-mode)
X      (mapcar (function
X	       (lambda (v)
X		 (set-default v (symbol-value v)))) calc-local-var-list))
X  (set-buffer (generate-new-buffer "*Calculator*"))
X  (pop-to-buffer (current-buffer))
X  (calc-mode)
X)
X
X(defun calc-quit ()
X  "Close the Calculator window(s).
XThis does not destroy the Calculator buffers or forget the stack contents,
Xit only closes the windows."
X  (interactive)
X  (calc-select-buffer)
X  (run-hooks 'calc-end-hook)
X  (setq calc-undo-list nil calc-redo-list nil)
X  (mapcar (function
X	   (lambda (v) (set-default v (symbol-value v)))) calc-local-var-list)
X  (let ((buf (current-buffer))
X	(tbuf (get-buffer-create "*Calc Trail*"))
X	(win (get-buffer-window (current-buffer))))
X    (if (and win
X	     (< (window-height win) (1- (screen-height))))
X	(setq calc-window-height (- (window-height win) 2)))
X    (delete-windows-on buf)
X    (delete-windows-on tbuf)
X    (bury-buffer buf)
X    (bury-buffer tbuf))
X)
X
X(defun quick-calc ()
X  "Do a quick calculation in the minibuffer without invoking full Calculator."
X  (interactive)
X  (save-excursion
X    (calc-create-buffer)
X    (let* ((calc-command-flags nil)
X	   (calc-language (if (memq calc-language '(nil big))
X			      'flat calc-language))
X	   (calc-dollar-values calc-quick-prev-results)
X	   (calc-dollar-used 0)
X	   (alg-exp (calc-do-alg-entry "" "Quick calc: ")))
X      (let ((buf ""))
X	(setq calc-quick-prev-results alg-exp)
X	(while alg-exp
X	  (setq buf (concat buf
X			    (if calc-extensions-loaded
X				(math-format-value (car alg-exp) 1000)
X			      (math-format-flat-expr (car alg-exp) 0))
X			    " ")
X		alg-exp (cdr alg-exp)))
X	(calc-handle-whys)
X	(message buf))))
X)
X
X(defun calc-summary ()
X  (interactive)
X  (message "Welcome to the GNU Emacs Calculator!  Press ? for help, q to quit.")
X)
X
X(defun calc-info ()
X  "Run the Emacs Info system on the Calculator documentation."
X  (interactive)
X  (require 'info)
X  (select-window (get-largest-window))
X  (Info-find-node calc-info-filename "Top")
X)
X
X(defun calc-help ()
X  (interactive)
X  (let ((msgs
X	 '("Letter keys: Help, Info, Why; Xtended cmd; Yank; Quit"
X	   "Letter keys: Negate; Precision; Store, Recall, Let"
X	   "Letter keys: SHIFT + Undo, reDo, last-X; Inverse, Hyperbolic"
X	   "Letter keys: SHIFT + sQrt; Sin, Cos, Tan; Exp, Ln, logB"
X	   "Letter keys: SHIFT + Floor, Round; Abs, conJ, arG; Pi"
X	   "Letter keys: SHIFT + Num-eval; More-recn; Kbd-macro"
X	   "Other keys: +, -, *, /, ^, \\ (int div), : (frac div)"
X	   "Other keys: & (1/x), | (concat), % (modulo), ! (factorial)"
X	   "Other keys: ' (alg-entry), = (evaluate), ` (edit)"
X	   "Other keys: RET (enter), DEL (drop), TAB (swap), M-TAB (roll)"
X	   "Other keys: [ ] (vector), ( ) (complex); < > (hscroll)"
X	   "Prefix keys: Algebra, Binary, Convert, Display, Kombinatorics"
X	   "Prefix keys: Modes, Trail, Units, Vectors"
X	   "Prefix keys: Z (user), SHIFT + Z (define-user)"
X	   "Prefix keys: prefix + ? gives further help for that prefix"
X	   "  Copyright (C) 1990 Dave Gillespie, daveg@csvax.caltech.edu")))
X    (setq calc-help-phase
X	  (if (eq this-command last-command)
X	      (% (1+ calc-help-phase) (1+ (length msgs)))
X	    0))
X    (let ((msg (nth calc-help-phase msgs)))
X      (message "%s" (if msg
X			(concat msg ":"
X				(make-string (- (apply 'max
X						       (mapcar 'length msgs))
X						(length msg)) 32)
X				"  [?=MORE]")
X		      ""))))
X)
X(setq calc-help-phase 0)
X
X
X(defun calc-scroll-left (n)
X  "Horizontally scroll one half-screen to the left."
X  (interactive "P")
X  (scroll-left (or n (/ (window-width) 2)))
X)
X
X(defun calc-scroll-right (n)
X  "Horizontally scroll one half-screen to the right."
X  (interactive "P")
X  (scroll-right (or n (/ (window-width) 2)))
X)
X
X
X(defmacro calc-with-default-simplification (body)
X  (list 'let
X	'((calc-simplify-mode (and (not (memq calc-simplify-mode '(none num)))
X				   calc-simplify-mode)))
X	body)
X)
X
X
X
X
X;;;; Stack and buffer management.
X
X(defmacro calc-wrapper (&rest body)
X  (` (let ((calc-command-flags nil))
X       (unwind-protect
X	   (progn
X	     (, (append '(save-excursion (calc-select-buffer))
X			body
X			'((calc-finish-command)))))
X	 (calc-cleanup-command))))
X)
X
X(defmacro calc-slow-wrapper (&rest body)
X  (` (let ((calc-command-flags (list 'clear-message)))
X       (if calc-display-working-message (message "Working..."))
X       (unwind-protect
X	   (progn
X	     (, (append '(save-excursion (calc-select-buffer))
X			body
X			'((calc-finish-command)))))
X	 (calc-cleanup-command))))
X)
X
X(defun calc-set-command-flag (f)
X  (if (not (memq f calc-command-flags))
X      (setq calc-command-flags (cons f calc-command-flags)))
X)
X
X(defun calc-clear-command-flag (f)
X  (setq calc-command-flags (delq f calc-command-flags))
X)
X
X(defun calc-select-buffer ()
X  (if (not (eq major-mode 'calc-mode))
X      (if calc-main-buffer
X	  (set-buffer calc-main-buffer)
X	(let ((buf (get-buffer "*Calculator*")))
X	  (if buf
X	      (set-buffer buf)
X	    (error "Calculator buffer not available")))))
X)
X
X(defun calc-finish-command ()
X  (and (memq 'renum-stack calc-command-flags)
X       (calc-renumber-stack))
X  (and (memq 'clear-message calc-command-flags)
X       (message ""))
X)
X
X(defun calc-cleanup-command ()
X  (or (memq 'no-align calc-command-flags)
X      (calc-align-stack-window))
X  (or (memq 'keep-flags calc-command-flags)
X      (setq calc-inverse-flag nil
X	    calc-hyperbolic-flag nil))
X  (calc-set-mode-line)
X)
X
X(defun calc-cursor-stack-index (&optional index)
X  (goto-char (point-max))
X  (forward-line (- (calc-substack-height (or index 1))))
X)
X
X(defun calc-stack-size ()
X  (- (length calc-stack) calc-stack-top)
X)
X
X(defun calc-substack-height (n)
X  (let ((sum 0)
X	(stack calc-stack))
X    (setq n (+ n calc-stack-top))
X    (while (and (> n 0) stack)
X      (setq sum (+ sum (nth 1 (car stack)))
X	    n (1- n)
X	    stack (cdr stack)))
X    sum)
X)
X
X(defun calc-set-mode-line ()
X  (save-excursion
X    (calc-select-buffer)
X    (let* ((fmt (car calc-float-format))
X	   (figs (nth 1 calc-float-format))
X	   (new-mode-string
X	    (format "Calc%s: %d %s %-14s"
X		    (if (and (> (length (buffer-name)) 12)
X			     (equal (substring (buffer-name) 0 12)
X				    "*Calculator*"))
X			(substring (buffer-name) 12)
X		      "")
X		    calc-internal-prec
X		    (capitalize (symbol-name calc-angle-mode))
X		    (concat
X		     (cond ((= calc-number-radix 10) "")
X			   ((= calc-number-radix 2) "Bin ")
X			   ((= calc-number-radix 8) "Oct ")
X			   ((= calc-number-radix 16) "Hex ")
X			   (t (format "Radix%d " calc-number-radix)))
X		     (if calc-algebraic-mode "Alg " "")
X		     (if calc-symbolic-mode "Symb " "")
X		     (cond ((eq calc-simplify-mode 'none) "NoSimp ")
X			   ((eq calc-simplify-mode 'num) "NumSimp ")
X			   ((eq calc-simplify-mode 'binary)
X			    (format "BinSimp%d " calc-word-size))
X			   ((eq calc-simplify-mode 'alg) "AlgSimp ")
X			   ((eq calc-simplify-mode 'units) "UnitSimp ")
X			   (t ""))
X		     (cond ((null calc-language) "")
X			   ((eq calc-language 'tex) "TeX ")
X			   (t (concat
X			       (capitalize (symbol-name calc-language))
X			       " ")))
X		     (if (eq calc-complex-mode 'polar) "Polar " "")
X		     (if calc-prefer-frac "Frac " "")
X		     (cond ((eq fmt 'float)
X			    (if (zerop figs) "" (format "Norm%d " figs)))
X			   ((eq fmt 'fix) (format "Fix%d " figs))
X			   ((eq fmt 'sci)
X			    (if (zerop figs) "Sci " (format "Sci%d " figs)))
X			   ((eq fmt 'eng)
X			    (if (zerop figs) "Eng " (format "Eng%d " figs))))
X		     (if calc-inverse-flag "Inv " "")
X		     (if calc-hyperbolic-flag "Hyp " "")
X		     (if (/= calc-stack-top 1) "Narrow " "")
X		     (apply 'concat calc-other-modes)))))
X      (if (equal new-mode-string mode-line-buffer-identification)
X	  nil
X	(setq mode-line-buffer-identification new-mode-string)
X	(set-buffer-modified-p (buffer-modified-p)))))
X)
X
X(defun calc-align-stack-window ()
X  (let ((win (get-buffer-window (current-buffer))))
X    (if win
X	(progn
X	  (calc-cursor-stack-index 0)
X	  (vertical-motion (- 2 (window-height)))
X	  (set-window-start win (point)))))
X  (calc-cursor-stack-index 0)
X  (if (looking-at " *\\.$")
X      (goto-char (1- (match-end 0))))
X)
X
X(defun calc-check-stack (n)
X  (if (> n (calc-stack-size))
X      (error "Too few elements on stack"))
X  (if (< n 0)
X      (error "Invalid argument"))
X)
X
X(defun calc-push (&rest vals)
X  (if (memq nil vals)
X      (error "Invalid operation")
X    (calc-push-list vals))
X)
X
X(defun calc-push-list (vals &optional m)
X  (while vals
X    (if calc-executing-macro
X	(let ((entry (list (car vals) 1))
X	      (mm (+ (or m 1) calc-stack-top)))
X	  (if (> mm 1)
X	      (setcdr (nthcdr (- mm 2) calc-stack)
X		      (cons entry (nthcdr (1- mm) calc-stack)))
X	    (setq calc-stack (cons entry calc-stack))))
X      (save-excursion
X	(calc-select-buffer)
X	(let* ((val (car vals))
X	       (fmt (math-format-stack-value val))
X	       (entry (list val (calc-count-lines fmt)))
X	       (mm (+ (or m 1) calc-stack-top)))
X	  (calc-cursor-stack-index (1- (or m 1)))
X	  (if (> mm 1)
X	      (setcdr (nthcdr (- mm 2) calc-stack)
X		      (cons entry (nthcdr (1- mm) calc-stack)))
X	    (setq calc-stack (cons entry calc-stack)))
X	  (let ((buffer-read-only nil))
X	    (insert fmt "\n"))
X	  (calc-record-undo (list 'push mm))
X	  (calc-set-command-flag 'renum-stack))))
X    (setq vals (cdr vals)))
X)
X
X(defun calc-count-lines (s)
X  (let ((pos 0)
X	(num 1))
X    (while (setq newpos (string-match "\n" s pos))
X      (setq pos (1+ newpos)
X	    num (1+ num)))
X    num)
X)
X
X(defun calc-pop-push-list (n vals)
X  (if (memq nil vals)
X      (error "Invalid operation"))
X  (calc-pop-stack n)
X  (calc-push-list vals)
X)
X
X(defun calc-pop-push (n &rest vals)
X  (calc-pop-push-list n vals)
X)
X
X(defun calc-pop-push-record-list (n prefix vals)
X  (if (and (consp vals)
X	   (or (integerp (car vals))
X	       (consp (car vals))))
X      (if (memq nil vals)
X	  (error "Invalid operation"))
X    (and vals (setq vals (list vals))))
X  (calc-check-stack n)
X  (if prefix
X      (if vals
X	  (calc-record-list vals prefix)
X	(calc-record nil prefix)))
X  (calc-pop-push-list n vals)
X)
X
X(defun calc-enter-result (n prefix vals)
X  (if (and (consp vals)
X	   (or (integerp (car vals))
X	       (consp (car vals))))
X      (setq vals (mapcar 'calc-normalize vals))
X    (setq vals (calc-normalize vals)))
X  (or (and (consp vals)
X	   (or (integerp (car vals))
X	       (consp (car vals))))
X      (setq vals (list vals)))
X  (if (equal vals '((nil)))
X      (setq vals nil))
X  (calc-pop-push-record-list n prefix vals)
X  (calc-handle-whys)
X)
X
X(defun calc-normalize (val)
X  (if (memq calc-simplify-mode '(nil none num))
X      (math-normalize val)
X    (calc-extensions)
X    (cond ((eq calc-simplify-mode 'binary)
X	   (let ((s (math-normalize val)))
X	     (if (math-realp s)
X		 (math-clip (math-round s))
X	       s)))
X	  ((eq calc-simplify-mode 'alg)
X	   (math-simplify val))
X	  ((eq calc-simplify-mode 'ext)
X	   (math-simplify-extended val))
X	  ((eq calc-simplify-mode 'units)
X	   (math-simplify-units val))))
X)
X
X(defun calc-handle-whys ()
X  (setq calc-why calc-next-why
X	calc-next-why nil)
X  (if (and calc-why calc-auto-why)
X      (progn
X	(calc-explain-why (car calc-why))
X	(calc-clear-command-flag 'clear-message)))
X)
X
X(defun calc-explain-why (why)
X  (let* ((pred (car why))
X	 (msg (cond ((not pred) "Wrong type of argument")
X		    ((stringp pred) pred)
X		    ((eq pred 'integerp) "Integer expected")
X		    ((eq pred 'natnump) "Nonnegative integer expected")
X		    ((eq pred 'fixnump) "Small integer expected")
X		    ((eq pred 'posp) "Positive number expected")
X		    ((eq pred 'negp) "Negative number expected")
X		    ((eq pred 'realp) "Real number expected")
X		    ((eq pred 'anglep) "Real number expected")
X		    ((eq pred 'hmsp) "HMS form expected")
X		    ((eq pred 'numberp) "Number expected")
X		    ((eq pred 'scalarp) "Number expected")
X		    ((eq pred 'vectorp) "Vector or matrix expected")
X		    ((eq pred 'numvecp) "Number or vector expected")
X		    ((eq pred 'square-matrixp) "Square matrix expected")
X		    ((eq pred 'objectp) "Number expected")
X		    ((eq pred 'constp) "Constant expected")
X		    ((eq pred 'range) "Argument out of range")
X		    (t (format "%s expected" pred))))
X	 (punc ": "))
X    (while (setq why (cdr why))
X      (setq msg (concat msg punc (if (stringp (car why))
X				     (car why)
X				   (math-format-flat-expr (car why) 0)))
X	    punc ", "))
X    (message "%s" msg))
X)
X
X(defun calc-record-why (&rest stuff)
X  (setq calc-next-why (cons stuff calc-next-why))
X  nil
X)
X
X(defun calc-pop-push-record (n prefix &rest vals)
X  (calc-pop-push-record-list n prefix vals)
X)
X
X(defun calc-pop-stack (&optional n m)   ; pop N objects at level M of stack.
X  (or n (setq n 1))
X  (or m (setq m 1))
X  (let ((mm (+ m calc-stack-top)))
X    (if calc-executing-macro
X	(if (> mm 1)
X	    (setcdr (nthcdr (- mm 2) calc-stack)
X		    (nthcdr (+ n mm -1) calc-stack))
X	  (setq calc-stack (nthcdr n calc-stack)))
X      (calc-record-undo (list 'pop mm (calc-top-list n m)))
X      (save-excursion
X	(calc-select-buffer)
X	(let ((buffer-read-only nil))
X	  (if (> mm 1)
X	      (progn
X		(calc-cursor-stack-index (1- m))
X		(let ((bot (point)))
X		  (calc-cursor-stack-index (+ n m -1))
X		  (delete-region (point) bot))
X		(setcdr (nthcdr (- mm 2) calc-stack)
X			(nthcdr (+ n mm -1) calc-stack)))
X	    (calc-cursor-stack-index n)
X	    (setq calc-stack (nthcdr n calc-stack))
X	    (delete-region (point) (point-max)))
X	  (calc-set-command-flag 'renum-stack)))))
X)
X
X(defun calc-top (&optional n)
X  "Get the Nth element of the stack (N=1 is the top element)."
X  (or n (setq n 1))
X  (calc-check-stack n)
X  (car-safe (nth (+ n calc-stack-top -1) calc-stack))
X)
X
X(defun calc-top-n (&optional n)    ; in case precision has changed
X  (math-check-complete (calc-normalize (calc-top n)))
X)
X
X(defun calc-top-list (&optional n m)
X  (or n (setq n 1))
X  (or m (setq m 1))
X  (calc-check-stack (+ n m -1))
X  (and (> n 0)
X       (let ((top (copy-sequence (nthcdr (+ m calc-stack-top -1)
X					 calc-stack))))
X	 (setcdr (nthcdr (1- n) top) nil)
X	 (nreverse (mapcar 'car-safe top))))
X)
X
X(defun calc-top-list-n (&optional n m)
X  (mapcar 'math-check-complete
X	  (mapcar 'calc-normalize (calc-top-list n m)))
X)
X
X(defun calc-roll-down-stack (n &optional m)
X  (if (< n 0)
X      (calc-roll-up-stack (- n) m)
X    (if (or (= n 0) (> n (calc-stack-size))) (setq n (calc-stack-size)))
X    (or m (setq m 1))
X    (and (> n 1)
X	 (< m n)
X	 (calc-pop-push-list n
X			     (append (calc-top-list m 1)
X				     (calc-top-list (- n m) (1+ m))))))
X)
X
X(defun calc-roll-up-stack (n &optional m)
X  (if (< n 0)
X      (calc-roll-down-stack (- n) m)
X    (if (or (= n 0) (> n (calc-stack-size))) (setq n (calc-stack-size)))
X    (or m (setq m 1))
X    (and (> n 1)
X	 (< m n)
X	 (calc-pop-push-list n
X			     (append (calc-top-list (- n m) 1)
X				     (calc-top-list m (- n m -1))))))
X)
X
X(defun calc-renumber-stack ()
X  (if calc-line-numbering
X      (save-excursion
X	(calc-cursor-stack-index 0)
X	(let ((lnum 1)
X	      (buffer-read-only nil))
X	  (if (re-search-forward "^[0-9]+:" nil t)
X	      (progn
X		(beginning-of-line)
X		(while (re-search-forward "^[0-9]+:" nil t)
X		  (let ((buffer-read-only nil))
X		    (beginning-of-line)
X		    (delete-char 4)
X		    (insert "    ")))
X		(calc-cursor-stack-index 0)))
X	  (while (re-search-backward "^[0-9]+:" nil t)
X	    (delete-char 4)
X	    (if (> lnum 999)
X		(insert (format "%03d:" (% lnum 1000)))
X	      (let ((prefix (int-to-string lnum)))
X		(insert prefix ":" (make-string (- 3 (length prefix)) 32))))
X	    (beginning-of-line)
X	    (setq lnum (1+ lnum))))))
X)
X
X(defun calc-refresh (&optional align)
X  "Refresh the contents of the Calculator buffer from memory."
X  (interactive)
X  (if (and (eq major-mode 'calc-mode)
X	   (not calc-executing-macro))
X      (let ((buffer-read-only nil)
X	    (save-point (point))
X	    (save-mark (mark))
X	    (save-aligned (looking-at "\\.$"))
X	    (thing calc-stack))
X	(erase-buffer)
X	(insert "--- Emacs Calculator Mode ---\n")
X	(while thing
X	  (goto-char (point-min))
X	  (forward-line 1)
X	  (let ((fmt (math-format-stack-value (car (car thing)))))
X	    (setcar (cdr (car thing)) (calc-count-lines fmt))
X	    (insert fmt "\n"))
X	  (setq thing (cdr thing)))
X	(calc-renumber-stack)
X	(if (or align save-aligned)
X	    (calc-align-stack-window)
X	  (goto-char save-point))
X	(set-mark save-mark)))
X  (setq calc-refresh-count (1+ calc-refresh-count))
X)
X(setq calc-refresh-count 0)
X
X(defun calc-realign ()
X  "Realign Calc window with cursor and top-of-stack at the bottom."
X  (interactive)
X  (calc-wrapper)
X)
X
X
X
X;;;; The Calc Trail buffer.
X
X(defun calc-check-trail-aligned ()
X  (save-excursion
X    (let ((win (get-buffer-window (current-buffer))))
X      (and win
X	   (pos-visible-in-window-p (1- (point-max)) win)
X	   ; (not (pos-visible-in-window-p (point-max) win))
X	   )))
X)
X
X(defmacro math-showing-full-precision (body)
X  (list 'let
X	'((calc-float-format calc-full-float-format))
X	body)
SHAR_EOF
echo "End of part 1"
echo "File calc.el is continued in part 2"
echo "2" > s2_seq_.tmp
exit 0