changeset 40785:2fb9d407ae73

Initial import of Calc 2.02f.
author Eli Zaretskii <eliz@gnu.org>
date Tue, 06 Nov 2001 18:59:06 +0000
parents d57f74c55909
children 7917695c31da
files lisp/calc/INSTALL lisp/calc/Makefile lisp/calc/README lisp/calc/README.prev lisp/calc/calc-aent.el lisp/calc/calc-alg.el lisp/calc/calc-arith.el lisp/calc/calc-bin.el lisp/calc/calc-comb.el lisp/calc/calc-cplx.el lisp/calc/calc-embed.el lisp/calc/calc-ext.el lisp/calc/calc-fin.el lisp/calc/calc-forms.el lisp/calc/calc-frac.el lisp/calc/calc-funcs.el lisp/calc/calc-graph.el lisp/calc/calc-help.el lisp/calc/calc-incom.el lisp/calc/calc-keypd.el lisp/calc/calc-lang.el lisp/calc/calc-macs.el lisp/calc/calc-maint.el lisp/calc/calc-map.el lisp/calc/calc-math.el lisp/calc/calc-misc.el lisp/calc/calc-mode.el lisp/calc/calc-mtx.el lisp/calc/calc-poly.el lisp/calc/calc-prog.el lisp/calc/calc-rewr.el lisp/calc/calc-rules.el lisp/calc/calc-sel.el lisp/calc/calc-stat.el lisp/calc/calc-store.el lisp/calc/calc-stuff.el lisp/calc/calc-trail.el lisp/calc/calc-undo.el lisp/calc/calc-units.el lisp/calc/calc-vec.el lisp/calc/calc-yank.el lisp/calc/calc.el lisp/calc/calcalg2.el lisp/calc/calcalg3.el lisp/calc/calccomp.el lisp/calc/calcsel2.el lisp/calc/macedit.el
diffstat 47 files changed, 52458 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/INSTALL	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,413 @@
+
+Installation
+************
+
+Calc 2.02 comes as a set of GNU Emacs Lisp files, with names like
+`calc.el' and `calc-ext.el', and also as a `calc.texinfo' file which
+can be used to generate both on-line and printed documentation.
+
+   To install Calc, just follow these simple steps.  If you want more
+information, each step is discussed at length in the sections below.
+
+  1. Change (`cd') to the Calc "home" directory.  This directory was
+     created when you unbundled the Calc `.tar' or `.shar' file.
+
+  2. Type `make' to install Calc privately for your own use, or type
+     `make install' to install Calc system-wide.  This will compile all
+     the Calc component files, modify your `.emacs' or the system-wide
+     `lisp/default' file to install Calc as appropriate, and format
+     the on-line Calc manual.
+
+     Both variants are shorthand for the following three steps:
+
+        * `make compile' to run the byte-compiler.
+
+        * `make private' or `make public', corresponding to `make' and
+          `make install', respectively.  (If `make public' fails
+          because your system doesn't already have a `default' or
+          `default.el' file, use Emacs or the Unix `touch' command to
+          create a zero-sized one first.)
+
+        * `make info' to format the on-line Calc manual.  This first
+          tries to use the `makeinfo' program; if that program is not
+          present, it uses the Emacs `texinfo-format-buffer' command
+          instead.
+
+          The Unix `make' utility looks in the file `Makefile' in the
+     current directory to see what Unix commands correspond to the
+     various "targets" like `install' or `public'.  If your system
+     doesn't have `make', you will have to examine the `Makefile' and
+     type in the corresponding commands by hand.
+
+  3. If you ever move Calc to a new home directory, just give the
+     `make private' or `make public' command again in the new
+     directory.
+
+  4. Test your installation as described at the end of these
+     instructions.
+
+  5. (Optional.)  To print a hardcopy of the Calc manual (over 500
+     pages) or just the Calc Summary (about 20 pages), follow the
+     instructions under "Printed Documentation" below.
+
+Calc is now installed and ready to go!
+
+
+Upgrading from Calc 1.07
+=========================
+
+If you have Calc version 1.07 or earlier, you will find that Calc 2.00
+is organized quite differently.  For one, Calc 2.00 is now distributed
+already split into many parts; formerly this was done as part of the
+installation procedure.  Also, some new functions must be autoloaded
+and the `M-#' key must be bound to `calc-dispatch' instead of to
+`calc'.
+
+   The easiest way to upgrade is to delete your old Calc files and then
+install Calc 2.00 from scratch using the above instructions.  You
+should then go into your `.emacs' or `default' file and remove the old
+`autoload' and `global-set-key' commands for Calc, since `make
+public'/`make private' has added new, better ones.
+
+   See the `README' and `README.prev' files in the Calc distribution
+for more information about what has changed since version 1.07. 
+(`README.prev' describes changes before 2.00, and is present only in
+the FTP and tape versions of the distribution.)
+
+
+The `make public' Command
+==========================
+
+If you are not the regular Emacs administrator on your system, your
+account may not be allowed to execute the `make public' command, since
+the system-wide `default' file may be write-protected.  If this is the
+case, you will have to ask your Emacs installer to execute this
+command.  (Just `cd' to the Calc home directory and type `make
+public'.)
+
+   The `make private' command adds exactly the same set of commands to
+your `.emacs' file as `make public' adds to `default'.  If your Emacs
+installer is concerned about typing this command out of the blue, you
+can ask her/him instead to copy the necessary text from your `.emacs'
+file.  (It will be marked by a comment that says "Commands added by
+`calc-private-autoloads' on (date and time).")
+
+
+Compilation
+============
+
+Calc is written in a way that maximizes performance when its code has
+been byte-compiled; a side effect is that performance is seriously
+degraded if it *isn't* compiled.  Thus, it is essential to compile the
+Calculator before trying to use it.  The function `calc-compile' in
+the file `calc-maint.el' runs the Emacs byte-compiler on all the Calc
+source files.  (Specifically, it runs `M-x byte-compile-file' on all
+files in the current directory with names of the form `calc*.el', and
+also on the file `macedit.el'.)
+
+   If `calc-compile' finds that certain files have already been
+compiled and have not been changed since, then it will not bother to
+recompile those files.
+
+   The `calc-compile' command also pre-builds certain tables, such as
+the units table (see "The Units Table") and the built-in rewrite
+rules (see "Rearranging with Selections") which Calc would otherwise
+need to rebuild every time those features were used.
+
+   The `make compile' shell command is simply a convenient way to
+start an Emacs and give it a `calc-compile' command.
+
+
+Auto-loading
+=============
+
+To teach Emacs how to load in Calc when you type `M-#' for the first
+time, add these lines to your `.emacs' file (if you are installing
+Calc just for your own use), or the system's `lisp/default' file (if
+you are installing Calc publicly).  The `make private' and `make
+public' commands, respectively, take care of this.  (Note that `make'
+runs `make private', and `make install' runs `make public'.)
+
+     (autoload 'calc-dispatch          "calc" "Calculator Options" t)
+     (autoload 'full-calc              "calc" "Full-screen Calculator" t)
+     (autoload 'full-calc-keypad       "calc" "Full-screen X Calculator" t)
+     (autoload 'calc-eval              "calc" "Use Calculator from Lisp")
+     (autoload 'defmath                "calc" nil t t)
+     (autoload 'calc                   "calc" "Calculator Mode" t)
+     (autoload 'quick-calc             "calc" "Quick Calculator" t)
+     (autoload 'calc-keypad            "calc" "X windows Calculator" t)
+     (autoload 'calc-embedded          "calc" "Use Calc from any buffer" t)
+     (autoload 'calc-embedded-activate "calc" "Activate =>'s in buffer" t)
+     (autoload 'calc-grab-region       "calc" "Grab region of Calc data" t)
+     (autoload 'calc-grab-rectangle    "calc" "Grab rectangle of data" t)
+
+   Unless you have installed the Calc files in Emacs' main `lisp/'
+directory, you will also have to add a command that looks like the
+following to tell Emacs where to find them.  In this example, we have
+put the files in directory `/usr/gnu/src/calc-2.00'.
+
+     (setq load-path (append load-path (list "/usr/gnu/src/calc-2.00")))
+
+The `make public' and `make private' commands also do this (they use
+the then-current directory as the name to add to the path).  If you
+move Calc to a new location, just repeat the `make public' or `make
+private' command to have this new location added to the `load-path'.
+
+   The `autoload' command for `calc-dispatch' is what loads `calc.elc'
+when you type `M-#'.  It is the only `autoload' that is absolutely
+necessary for Calc to work.  The others are for commands and features
+that you may wish to use before typing `M-#' for the first time.  In
+particular, `full-calc' and `full-calc-keypad' are autoloaded to
+support "standalone" operation (see "Standalone Operation"),
+`calc-eval' and `defmath' are autoloaded to allow other Emacs Lisp
+programs to use Calc facilities (see "Calling Calc from Your
+Programs"), and `calc-embedded-activate' is autoloaded because some
+Embedded Mode files may call it as soon as they are read into Emacs
+(see "Assignments in Embedded Mode").
+
+
+Finding Component Files
+========================
+
+There is no need to write `autoload' commands that point to all the
+various Calc component files like `calc-misc.elc' and `calc-alg.elc'. 
+The main file, `calc.elc', contains all the necessary `autoload'
+commands for these files.
+
+   (Actually, to conserve space `calc.elc' only autoloads a few of the
+component files, plus `calc-ext.elc', which in turn autoloads the rest
+of the components.  This allows Calc to load a little faster in the
+beginning, but the net effect is the same.)
+
+   This autoloading mechanism assumes that all the component files can
+be found on the `load-path'.  The `make public' and `make private'
+commands take care of this, but Calc has a few other strategies in
+case you have installed it in an unusual way.
+
+   If, when Calc is loaded, it is unable to find its components on the
+`load-path' it is given, it checks the file name in the original
+`autoload' command for `calc-dispatch'.  If that name included
+directory information, Calc adds that directory to the `load-path':
+
+     (autoload 'calc-dispatch "calc-2.00/calc" "Calculator" t)
+
+Suppose the directory `/usr/gnu/src/emacs/lisp' is on the path, and
+the above `autoload' allows Emacs to find Calc under the name
+`/usr/gnu/src/emacs/lisp/calc-2.00/calc.elc'.  Then when Calc starts
+up it will add `/usr/gnu/src/emacs/lisp/calc-2.00' to the path so that
+it will later be able to find its component files.
+
+   If the above strategy does not locate the component files, Calc
+examines the variable `calc-autoload-directory'.  This is initially
+`nil', but you can store the name of Calc's home directory in it as a
+sure-fire way of getting Calc to find its components.
+
+
+Merging Source Files
+=====================
+
+If the `autoload' mechanism is not managing to load each part of Calc
+when it is needed, you can concatenate all the `.el' files into one
+big file.  The order should be `calc.el', then `calc-ext.el', then all
+the other files in any order.  Byte-compile the resulting big file. 
+This merged Calculator ought to work just like Calc normally does,
+though it will be *substantially* slower to load.
+
+
+Key Bindings
+=============
+
+Calc is normally bound to the `M-#' key.  To set up this key binding,
+include the following command in your `.emacs' or `lisp/default' file.
+ (This is done automatically by `make private' or `make public',
+respectively.)
+
+     (global-set-key "\e#" 'calc-dispatch)
+
+   Note that `calc-dispatch' actually works as a prefix for various
+two-key sequences.  If you have a convenient unused function key on
+your keyboard, you may wish to bind `calc-dispatch' to that as well. 
+You may even wish to bind other specific Calc functions like `calc' or
+`quick-calc' to other handy function keys.
+
+   Even if you bind `calc-dispatch' to other keys, it is best to bind
+it to `M-#' as well if you possibly can:  There are references to
+`M-#' all throughout the Calc manual which would confuse novice users
+if they didn't work as advertised.
+
+   Another key binding issue is the DEL key.  Some installations use a
+different key (such as backspace) for this purpose.  Calc normally
+scans the entire keymap and maps all keys defined like DEL to the
+`calc-pop' command.  However, this may be slow.  You can set the
+variable `calc-scan-for-dels' to `nil' to cause only the actual DEL
+key to be mapped to `calc-pop'; this will speed loading of Calc.
+
+
+The `macedit' Package
+======================
+
+The file `macedit.el' contains another useful Emacs extension called
+`edit-kbd-macro'.  It allows you to edit a keyboard macro in
+human-readable form.  The `Z E' command in Calc knows how to use it to
+edit user commands that have been defined by keyboard macros.  To
+autoload it, you will want to include the commands,
+
+     (autoload 'edit-kbd-macro      "macedit" "Edit Keyboard Macro" t)
+     (autoload 'edit-last-kbd-macro "macedit" "Edit Keyboard Macro" t)
+     (autoload 'read-kbd-macro      "macedit" "Read Keyboard Macro" t)
+
+The `make public' and `make private' commands do this.
+
+
+The GNUPLOT Program
+====================
+
+Calc's graphing commands use the GNUPLOT program.  If you have GNUPLOT
+but you must type some command other than `gnuplot' to get it, you
+should add a command to set the Lisp variable `calc-gnuplot-name' to
+the appropriate file name.  You may also need to change the variables
+`calc-gnuplot-plot-command' and `calc-gnuplot-print-command' in order
+to get correct displays and hardcopies, respectively, of your plots.
+
+
+On-Line Documentation
+======================
+
+The documentation for Calc (this manual) comes in a file called
+`calc.texinfo'.  To format this for use as an on-line manual, type
+`make info' (to use the `makeinfo' program), or `make texinfo' (to use
+the `texinfmt.el' program which runs inside of Emacs).  The former
+command is recommended if it works on your system; it is faster and
+produces nicer-looking output.
+
+   The `makeinfo' program will report inconsistencies involving the
+nodes "Copying" and "Interactive Tutorial"; these messages should be
+ignored.
+
+   The result will be a collection of files whose names begin with
+`calc.info'.  You may wish to add a reference to the first of these,
+`calc.info' itself, to your Info system's `dir' file.  (This is
+optional since the `M-# i' command can access `calc.info' whether or
+not it appears in the `dir' file.)
+
+   There is a Lisp variable called `calc-info-filename' which holds
+the name of the Info file containing Calc's on-line documentation. 
+Its default value is `"calc.info"', which will work correctly if the
+Info files are stored in Emacs' main `info/' directory, or if they are
+in any of the directories listed in the `load-path'.  If you keep them
+elsewhere, you will want to put a command of the form,
+
+     (setq calc-info-filename ".../calc.info")
+
+in your `.emacs' or `lisp/default' file, where `...' represents the
+directory containing the Info files.  This will not be necessary if
+you follow the normal installation procedures.
+
+   The `make info' and `make texinfo' commands compare the dates on
+the files `calc.texinfo' and `calc.info', and run the appropriate
+program only if the latter file is older or does not exist.
+
+
+Printed Documentation
+======================
+
+Because the Calc manual is so large, you should only make a printed
+copy if you really need it.  To print the manual, you will need the
+TeX typesetting program (this is a free program by Donald Knuth at
+Stanford University) as well as the `texindex' program and
+`texinfo.tex' file, both of which can be obtained from the FSF as part
+of the `texinfo2' package.
+
+   To print the Calc manual in one huge 550 page tome, type `make tex'. 
+This will take care of running the manual through TeX twice so that
+references to later parts of the manual will have correct page numbers. 
+(Don't worry if you get some "overfull box" warnings.)
+
+   The result will be a device-independent output file called
+`calc.dvi', which you must print in whatever way is right for your
+system.  On many systems, the command is
+
+     lpr -d calc.dvi
+
+   Marginal notes for each function and key sequence normally alternate
+between the left and right sides of the page, which is correct if the
+manual is going to be bound as double-sided pages.  Near the top of
+the file `calc.texinfo' you will find alternate definitions of the
+`\bumpoddpages' macro that put the marginal notes always on the same
+side, best if you plan to be binding single-sided pages.
+
+   Some people find the Calc manual to be too large to handle easily. 
+In fact, some versions of TeX have too little memory to print it.  So
+Calc includes a `calc-split-manual' command that splits `calc.texinfo'
+into two volumes, the Calc Tutorial and the Calc Reference.  The
+easiest way to use it is to type `make tex2' instead of `make tex'. 
+The result will be two smaller files, `calctut.dvi' and `calcref.dvi'.
+ The former contains the tutorial part of the manual; the latter
+contains the reference part.  Both volumes include copies of the
+"Getting Started" chapter and licensing information.
+
+   To save disk space, you may wish to delete `calctut.*' and
+`calcref.*' after you're done.  Don't delete `calc.texinfo', because
+you will need it to install future patches to Calc.  The `make tex2'
+command takes care of all of this for you.
+
+   The `make textut' command formats only the Calc Tutorial volume,
+producing `calctut.dvi' but not `calcref.dvi'.  Likewise, `make
+texref' formats only the Calc Reference volume.
+
+   Finally, there is a `calc-split-summary' command that splits off
+just the Calc Summary appendix suitable for printing by itself.  Type
+`make summary' instead of `make tex'.  The resulting `calcsum.dvi'
+file will print in less than 20 pages.  If the Key Index file
+`calc.ky' is present, left over from a previous `make tex' command,
+then `make summary' will insert a column of page numbers into the
+summary using that information.
+
+   The `make isummary' command is like `make summary', but it prints a
+summary that is designed to be substituted into the regular manual. 
+(The two summaries will be identical except for the additional column
+of page numbers.)  To make a complete manual, run `make tex' and `make
+isummary', print the two resulting `.dvi' files, then discard the
+Summary pages that came from `calc.dvi' and insert the ones from
+`calcsum.dvi' in their place.  Also, remember that the table of
+contents prints at the end of the manual but should generally be moved
+to the front (after the title and copyright pages).
+
+   If you don't have TeX, you can print the summary as a plain text
+file by going to the "Summary" node in Calc's Info file, then typing
+`M-x print-buffer' (see "Summary").
+
+
+Settings File
+==============
+
+Another variable you might want to set is `calc-settings-file', which
+holds the file name in which commands like `m m' and `Z P' store
+"permanent" definitions.  The default value for this variable is
+`"~/.emacs"'.  If `calc-settings-file' does not contain `".emacs"' as
+a substring, and if the variable `calc-loaded-settings-file' is `nil',
+then Calc will automatically load your settings file (if it exists)
+the first time Calc is invoked.
+
+
+Testing the Installation
+=========================
+
+To test your installation of Calc, start a new Emacs and type `M-# c'
+to make sure the autoloads and key bindings work.  Type `M-# i' to
+make sure Calc can find its Info documentation.  Press `q' to exit the
+Info system and `M-# c' to re-enter the Calculator.  Type `20 S' to
+compute the sine of 20 degrees; this will test the autoloading of the
+extensions modules.  The result should be 0.342020143326.  Finally,
+press `M-# c' again to make sure the Calculator can exit.
+
+   You may also wish to test the GNUPLOT interface; to plot a sine
+wave, type `' [0 .. 360], sin(x) RET g f'.  Type `g q' when you are
+done viewing the plot.
+
+   Calc is now ready to use.  If you wish to go through the Calc
+Tutorial, press `M-# t' to begin.
+
+
+(The above text is included in both the Calc documentation and the
+file INSTALL in the Calc distribution directory.)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/Makefile	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,186 @@
+# Makefile for "Calc", the GNU Emacs Calculator.
+#  Copyright (C) 1991, 1992, 1993 Free Software Foundation.
+#  Author: Dave Gillespie.
+#  Author's address: daveg@synaptics.com.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation (any version).
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GNU Emacs; see the file COPYING.  If not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+
+# To install Calc for private use, type `make'.
+# To install Calc for public use, type `make install'.
+
+# How to read a Makefile:
+#   The command `make target' looks for `target:' in the Makefile.
+#   First, any sub-targets after the `:' are made.
+#   Then, the Unix commands on the following lines are executed.
+#   `$(SYMBOL)' expands according to the `SYMBOL =' definition below.
+
+
+# Programs.
+EMACS    = emacs
+TEX      = tex
+TEXINDEX = texindex
+MAKEINFO = makeinfo
+MAKE	 = make
+ECHO	 = @echo
+REMOVE	 = -rm -f
+# (The leading `@' tells "make" not to echo the command itself during make;
+#  The leading `-' tells "make" to keep going if the command fails.)
+
+# Other macros.
+EFLAGS   = -batch
+MAINT	 = -l calc-maint.elc
+
+# Control whether intermediate files are kept.
+PURGE	 = -rm -f
+#PURGE	 = echo Not deleting:
+
+
+
+# Do full Calc installation.  (Note that `make' == `make all'.)
+# These are written this way instead of `all: compile private info'
+# to make the steps more explicit while the `make' is in progress.
+all:
+	$(MAKE) compile
+	$(MAKE) private
+	$(MAKE) info
+	$(ECHO) "Calc is now installed."
+
+install:
+	$(MAKE) compile
+	$(MAKE) public
+	$(MAKE) info
+	$(ECHO) "Calc is now installed."
+
+
+# Compile Calc.
+compile: maint
+	$(EMACS) $(EFLAGS) $(MAINT) -f calc-compile
+
+
+# Add autoload and set-global-key commands to system default file.
+public: maint
+	$(EMACS) $(EFLAGS) $(MAINT) -f calc-public-autoloads
+
+
+# Add autoload and set-global-key commands to ~/.emacs file.
+private: maint
+	$(EMACS) $(EFLAGS) $(MAINT) -f calc-private-autoloads
+
+
+# Format the Calc manual for the Info system using makeinfo.
+info: calc.info
+calc.info: calc.texinfo
+	-$(MAKEINFO) calc.texinfo
+	$(ECHO) "Please ignore warnings for Copying, Getting Started, and Interactive Tutorial."
+	$(MAKE) texinfo
+
+
+# Format the Calc manual for the Info system using texinfo.el.
+# (Use this only if you do not have makeinfo.)
+texinfo: calc.info-2
+calc.info-2: calc.texinfo
+	$(EMACS) $(EFLAGS) calc.texinfo -f texinfo-format-buffer -f save-buffer
+
+
+# Format the Calc manual as one printable volume using TeX.
+tex:
+	$(REMOVE) calc.aux
+	$(TEX) calc.texinfo
+	$(TEXINDEX) calc.[cfkptv]?
+	$(TEX) calc.texinfo
+	$(PURGE) calc.cp calc.fn calc.pg calc.tp calc.vr
+	$(PURGE) calc.cps calc.fns calc.kys calc.pgs calc.tps calc.vrs
+	$(PURGE) calc.toc
+# Note, calc.aux and calc.ky are left behind for the benefit of "make summary".
+
+# Format the Calc manual as two printable volumes (Tutorial and Reference).
+tex2: texsplit texvol1 texvol2
+
+# Format the Calc Tutorial volume only.
+textut: texsplit1 texvol1
+
+# Format the Calc Reference volume only.
+texref: texsplit2 texvol2
+
+texsplit: maint
+	$(EMACS) $(EFLAGS) $(MAINT) calc.texinfo -f calc-split-manual
+
+texsplit1: maint
+	$(EMACS) $(EFLAGS) $(MAINT) calc.texinfo -f calc-split-tutorial
+
+texsplit2: maint
+	$(EMACS) $(EFLAGS) $(MAINT) calc.texinfo -f calc-split-reference
+
+texvol1:
+	$(TEX) calctut.tex
+	$(TEXINDEX) calctut.??
+	$(TEX) calctut.tex
+	$(PURGE) calctut.tex calctut.?? calctut.??s calctut.aux calctut.toc
+
+texvol2:
+	$(TEX) calcref.tex
+	$(TEXINDEX) calcref.??
+	$(TEX) calcref.tex
+	$(PURGE) calcref.tex calcref.?? calcref.??s calcref.aux calcref.toc
+
+
+# Format the Calc summary separately using TeX.
+summary: texsum
+	$(TEX) calcsum.tex
+	$(PURGE) calcsum.?? calcsum.aux calcsum.toc
+
+texsum: maint
+	$(EMACS) $(EFLAGS) $(MAINT) calc.texinfo -f calc-split-summary
+
+isummary: texisum
+	$(TEX) calcsum.tex
+	$(PURGE) calcsum.?? calcsum.aux calcsum.toc
+
+texisum: maint
+	$(EMACS) $(EFLAGS) $(MAINT) calc.texinfo -f calc-inline-summary
+
+
+# All this because "-l calc-maint" doesn't work.
+maint: calc-maint.elc
+calc-maint.elc: calc-maint.el
+	cp calc-maint.el calc-maint.elc
+
+
+# Create an Emacs TAGS file
+tags: TAGS
+TAGS:
+	etags *.el
+
+
+# Delete .elc files and other reconstructible files.
+clean:  clean.elc clean.info clean.tex
+
+clean.elc:
+	$(REMOVE) calc-*.elc
+	$(REMOVE) macedit.elc
+
+clean.info:
+	$(REMOVE) calc.info*
+
+clean.tex:
+	$(REMOVE) calc.cp calc.fn calc.ky calc.pg calc.tp calc.vr
+	$(REMOVE) calc.cps calc.fns calc.kys calc.pgs calc.tps calc.vrs
+	$(REMOVE) calc.aux calc.log calc.toc calc.dvi
+	$(REMOVE) calcref.*
+	$(REMOVE) calctut.*
+	$(REMOVE) calcsum.*
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/README	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,235 @@
+
+This directory contains version 2.02c of Calc, an advanced desk
+calculator for GNU Emacs.
+
+"Calc"  Copyright 1990, 1991, 1992, 1993  Free Software Foundation, Inc.
+
+Written and maintained by:   Dave Gillespie
+			     c/o Synaptics, Inc.
+			     2698 Orchard Parkway
+			     San Jose CA 95134
+			     daveg@synaptics.com, uunet!synaptx!daveg
+
+
+
+From the introduction to the manual:
+
+  "Calc" is an advanced calculator and mathematical tool that runs as
+  part of the GNU Emacs environment.  Very roughly based on the HP-28/48
+  series of calculators, its many features include:
+
+    * Choice of algebraic or RPN (stack-based) entry of calculations.
+
+    * Arbitrary precision integers and floating-point numbers.
+
+    * Arithmetic on rational numbers, complex numbers (rectangular and
+      polar), error forms with standard deviations, open and closed
+      intervals, vectors and matrices, dates and times, infinities,
+      sets, quantities with units, and algebraic formulas.
+
+    * Mathematical operations such as logarithms and trigonometric functions.
+
+    * Programmer's features (bitwise operations, non-decimal numbers).
+
+    * Financial functions such as future value and internal rate of return.
+
+    * Number theoretical features such as prime factorization and
+      arithmetic modulo M for any M.
+
+    * Algebraic manipulation features, including symbolic calculus.
+
+    * Moving data to and from regular editing buffers.
+
+    * "Embedded mode" for manipulating Calc formulas and data directly
+      inside any editing buffer.
+
+    * Graphics using GNUPLOT, a versatile (and free) plotting program.
+
+    * Easy programming using keyboard macros, algebraic formulas,
+      algebraic rewrite rules, or extended Emacs Lisp.
+
+
+
+
+To install Calc:
+
+  1. Type "uncompress calc-2.02.tar.Z"
+
+  2. Type "tar xvf calc-2.02.tar"
+
+1,2. Alternatively: "zcat calc-2.02.tar.Z | tar xvf -"
+
+  3. Note that the Calc tar file now creates a "calc-2.02" subdirectory
+     of the current directory in which to place its files.
+
+  4. Follow the instructions in the file "INSTALL".
+
+
+
+Calc is written entirely in Emacs Lisp, for maximum portability.
+You do not need to recompile Emacs to install and use Calc.
+
+You will need about six megabytes of disk space to install Calc
+and its Info documentation.
+
+See the file INSTALL for installation instructions.  The instructions
+may seem long, but on typical systems you will only need to follow the
+steps shown in the first section.
+
+Don't even try to run Calc in uncompiled (.el) form!  It's far too slow.
+
+
+I am anxious to hear about your experiences using Calc.  Send mail to
+"daveg@synaptics.com".  A bug report is most useful if you include the
+exact input and output that occurred, any modes in effect (such as the
+current precision), and so on.  If you find Calc is difficult to operate
+in any way, or if you have other suggestions, don't hesitate to let me
+know.  If you find errors (including simple typos) in the manual, let
+me know.  Even if you find no bugs at all I would love to hear your
+opinions.
+
+The latest Calc tar files and patches are always available for anonymous
+FTP on prep.ai.mit.edu.
+
+Thanks,
+
+								-- Dave
+
+
+
+
+
+Summary of changes to "Calc"
+------- -- ------- --  ----
+
+
+Version 2.02f:
+
+ * Fixed a bug which broke `I', `H', `K' prefix keys in recent Emacs.
+
+ * Fixed a bug in calc.texinfo which prevented "make tex2" from working.
+
+ * Updated `C-y' (calc-yank) to understand Emacs 19 generalized kill ring.
+
+ * Added a copy of "calccard.tex", the Calc quick reference card.
+
+
+Version 2.02e:
+
+ * Fixed an installation bug caused by recent changes to `write-region'.
+
+
+Version 2.02d:
+
+ * Fixed a minor installation problem with a Emacs 19.29 byte-compiler bug.
+
+ * Removed archaic "macedit" package (superseded by "edmacro").
+
+
+Version 2.02c:
+
+ * Patch to port Calc to Lucid Emacs 19; still works with GNU 18 and GNU 19.
+
+ * Fixed a bug that broke `C-x C-c' after Calc graphics had been used.
+
+
+Version 2.02b:
+
+ * Minor patch to port Calc to GNU Emacs 19.  Will be superseded by Calc 3.00.
+
+
+Version 2.02:
+
+ * Revamped the manual a bit; rearranged some sections.
+
+ * Added marginal notes for Key/Function Index refs in printed manual.
+
+ * Changed `M-# r' to deal more gracefully with blank lines.
+
+ * Made reductions like `V R +' and `M-# :' considerably faster.
+
+ * Improved parsing and display of cases like "[a + b]".
+
+ * Added `t +' and `t -' for doing business date arithmetic.
+
+ * Added "syntax tables," the opposite of compositions.
+
+ * Added another Rewrites Tutorial exercise.
+
+ * Added the "vmatches" function.
+
+ * Added the `Modes' variable and `m g' command.
+
+ * Improved `u s' to cancel, e.g., "11 mph hr / yd" to get a number.
+
+ * Added "quick units" commands "u 0" through "u 9".
+
+ * Moved `M-%' to calc.el to avoid autoloading problems.
+
+ * Added `M-=' during algebraic entry, acts like `RET ='.
+
+ * Made `LFD' prevent evaluation when finishing a calc-edit command.
+
+ * Changed calc-store commands to use `t .' mode for trail display.
+
+ * Improved integrator to understand forms involving "erf".
+
+ * Fixed parser to make sense of "[1....1e2]" input.
+
+ * Fixed FORTRAN parser to treat a(i,j) as a_i_j if a is declared matrix.
+
+ * Got rid of some version number stamps to reduce size of patches.
+
+ * Fixed a bug in defmath treating "<=" and ">=" predicates.
+
+ * Fixed a bug in which Calc crashed multiplying two date forms.
+
+ * Fixed a bug in line breaker that crashed for large, nested formulas.
+
+ * Fixed a bug using ` to edit string("foo").
+
+ * Fixed a bug where `M-# y' in Big mode copied stack level number.
+
+ * Fixed a bug where `g O' used wrong default directory, no completion.
+
+ * Fixed a bug where "foo_bar(i)" parsed in C mode but showed as foo#bar.
+
+ * Fixed several bugs where large calculations got "computation too long."
+
+
+Version 2.01:
+
+ * Added percentage commands `M-%', `b %', and `c %'.
+
+ * Changed Big mode to force radix-10 in superscripts.
+
+ * Improved display of fractions in various language modes.
+
+ * Changed `a n' to work properly with equations and inequalities.
+
+ * The problem with cross references to Index nodes in TeX has been fixed.
+
+ * Fixed a bug where recursive esc-maps make calc-ext/-aent unloadable.
+
+ * Fixed a bug in `M-# k', then `OFF' right away, with fresh Emacs.
+
+ * Fixed a bug in which "S_i_j" was formatted wrong after `j s'.
+
+ * Fixed a bug in which `h k u c' positioned cursor on wrong line.
+
+ * Fixed a bug where `z ?' crashed if `z %' was defined.
+
+ * Fixed a bug in `j O' (calc-select-once-maybe).
+
+ * Fixed "make private" not to ask "Delete excess versions" and crash.
+
+
+Version 2.00:
+
+ * First complete posting of Calc since 1.01.
+
+ * Most parts of Calc have seen changes since version 1.07.  See
+   section "New for Calc 2.00" in the manual for a summary.  In
+   the FTP version of the Calc distribution, the file README.prev
+   contains a detailed change history from 1.00 up to 2.00.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/README.prev	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,981 @@
+
+
+Summary of changes to "Calc" Preceding 2.00
+------- -- ------- --  ----  --------- ----
+
+
+Version 2.00:
+
+ * Changed to compile calc-macs/-maint, to allow "cp *.elc new-dir".
+
+ * Improved calc-describe-bindings to avoid showing redundant ESC maps.
+
+
+Version 2.00 beta 3:
+
+ * Removed version numbers from most .el files to reduce size of patches.
+
+ * Added a "calc-version" command.
+
+ * Changed `M-# ? ?' to allow for modified describe-function.
+
+ * Changed date parser to accept "Sept" as an alternative for "Sep".
+
+ * Inhibited answers to exercise from showing up in table of contents.
+
+ * Changed Makefile to say "texindex calc.[cfkptv]?" to avoid "calc.el".
+
+ * Fixed up the Makefile in various other ways.
+
+ * Rearranged banner at top of `h h' command's output.
+
+ * Changed "make summary" to print "Calc Summary" on the title page.
+
+ * Added "IntegSimpRules".
+
+ * Added `M-# :', `M-# _', and `M-# Z' options.
+
+ * Changed `^' to evaluate "[-3..-1]^-2" properly.
+
+ * Improved `f g' to give symbolic answers for, e.g., 101:2 and -3:2.
+
+ * Fixed a bug where `h k RET' didn't find the right place on the page.
+
+ * Fixed a bug that formatted "x*(y ? a : b)" as "x y ? a : b".
+
+ * Fixed a bug where defmath translated (< x 0) as (math-posp x)!
+
+ * Fixed a bug that prevented quick-calc from working sometimes.
+
+ * Fixed the `z ?' bug again (maybe this time for good?).
+
+ * Fixed a bug in which `V ^' (vint) was just plain wrong, wrong, wrong!
+
+ * Scanned for and fixed remaining bugs relating to autoloading.
+
+
+Version 2.00 beta 2:
+
+ * Changed "make info" to try "make texinfo" if "makeinfo" not found.
+
+ * Changed to "New for Calc 2.00"; texinfo.tex chokes on apostrophes.
+
+ * Added List Tutorial Exercise 14 (just in case there weren't enough!).
+
+ * Added a discussion of the `Z F' command to the Programming Tutorial.
+
+ * Improved `H a f' not to lose info if input is partially pre-factored.
+
+ * Improved simplification of expressions like sqrt(3) + 3^3:2.
+
+ * Changed Big mode to omit "*" in expressions like 2 sqrt(3) 5^3:4.
+
+ * Replaced European date format D/M/Y with D.M.Y.
+
+ * Changed `a N' and `a X' to consider the endpoints of the interval.
+
+ * Fixed a bug where TeX mode made c*(1+a/b) look like a function call.
+
+ * Fixed a bug formatting top-level evalto's while using selections.
+
+ * Fixed a bug that caused `z ?' to crash.
+
+ * Fixed a bug where `Z F' broke for argument names "t" and "nil".
+
+ * Fixed several bugs relating to autoloading.
+
+
+Version 2.00 beta 1:
+
+ * Added "What's new in Calc 2.00" to the manual (summary of info below).
+
+ * Added support for many GNUPLOT 3.0 features.
+
+ * Tweaked the Makefile and calc-compile a bit more.
+
+ * Modified to work with Zawinski's/Furuseth's optimizing byte compiler.
+
+ * Modified Calc to garbage-collect less often (raised gc-cons-threshold).
+
+ * Changed quick-calc to avoid autoloading so many parts of Calc.
+
+ * Changed Calc subfiles to work properly if not byte-compiled.
+
+ * Renamed `M-# s' to `M-# j', made `M-# s' be equivalent to `h s'.
+
+ * Changed calc-quit to avoid reapportioning space among other windows.
+
+ * Added `M-DEL' (calc-pop-above) key, to DEL as LFD is to RET.
+
+ * Added `{' and `}' to scroll vertically, analogous to `<' and `>'.
+
+ * Added `m t' for "total" algebraic mode.
+
+ * Added `d , \' option to group digits with "\,".
+
+ * Improved support of "prime" accent in "eqn" language mode.
+
+ * Changed macedit's read-kbd-macro to accept a string argument in Lisp.
+
+ * Changed calc-check-defines to use a more concise run-hooks linkage.
+
+ * Changed auto-why mode not to say [w=more] if next msg is not urgent.
+
+ * Made `a d' able to differentiate "a?b:c" and "a_i" formulas.
+
+ * Changed probability dist. functions to work with `a f' and `a d'.
+
+ * Added special constants "phi" and "gamma".
+
+ * Added "poly" function, simpler cousin of "gpoly".
+
+ * Added "pdeg", "plead", "pcont", "pprim"; cleaned up "pdiv" and "pgcd".
+
+ * Added `a p' command for polynomial interpolation.
+
+ * Added `a I' command for numerical integration; made IntegLimit variable.
+
+ * Added `a f' to factor polynomials; moved old `a f' to `a "'.
+
+ * Added `a a' to do partial fraction decompositions.
+
+ * Improved `a i' to integrate many more kinds of formulas.
+
+ * Modified `a P' to find numerical roots of high-degree polynomials.
+
+ * Modified `c 0' through `c 9' to convert int-valued floats to integers.
+
+ * Made sinh, arctanh, etc., expandable into exps/logs by `a f'.
+
+ * Added more algebraic simplifications having to do with logs and exps.
+
+ * Changed `s s', `s t', `s x', `s l' to accept an equation at prompt.
+
+ * Changed `s i' not to store Decls if its value is the default, [].
+
+ * Changed `s i' to store in `d O' language mode if in Normal or Big mode.
+
+ * Rearranged `V M'/`V R' matrix mapping modes.
+
+ * Added <#1+#2> notation for lambda expressions.
+
+ * Extended `b l' and other binary shifts to have a 2-argument version.
+
+ * Changed `u c' and `u t' to give unitless result for unitless input.
+
+ * Changed sqrt(1-cos(x)^2)-to-sin(x) to be an unsafe simplification.
+
+ * Improved simplification of sqrts, e.g., sqrt(a^2 x + a^2 y).
+
+ * Changed solver to treat (x-a)(x-b)(x-c) more intelligently.
+
+ * Changed Pascal language mode to use "$FFFF" for hexadecimal numbers.
+
+ * Added support for non-decimal display of floats.
+
+ * Changed `p' to refresh stack display if current float format uses it.
+
+ * Changed Big mode to use subscript notation for log10(x), log(x,b), r#nnn.
+
+ * Changed Big mode to format deriv(u,x) and tderiv(u,x) as du/dx.
+
+ * Changed Big mode to format integ(1/x,x) as "dx/x" instead of "1/x dx".
+
+ * Added "tty" output type for graphics commands.
+
+ * Documented Calc's random number generation algorithm in the manual.
+
+ * Fixed a bug involving having "(setq calc-timing t)" in .emacs.
+
+ * Fixed a bug that incorrectly parsed "|x| - 1" in TeX mode.
+
+ * Fixed bugs and made improvements in `a R' when widening the guess.
+
+ * Fixed a bug that where `a S' didn't solve (x - a)^2 = (x - b)^2.
+
+ * Fixed a bug that sometimes crashed `a P' on systems of equations.
+
+ * Fixed a bug that prevented `b p' (calc-pack-bits) from working.
+
+ * Fixed some bugs in which certain functions didn't get autoloaded.
+
+ * Fixed a bug in which the date <1/1/13> was incorrectly parsed.
+
+ * Fixed a bug which prevented `j D' from expanding (a+b)/c.
+
+ * Fixed a bug in solver: bad inverses for sinh and cosh.
+
+ * Fixed a bug in math-possible-signs that failed for x*0.
+
+ * Fixed a bug where sqrt(-a) was rewritten sqrt(a)*i even if a<0.
+
+ * Fixed a bug in line breaker when first "word" of line was too long.
+
+ * Worked around a makeinfo bug that handled @end group/@group badly.
+
+
+Version 2.00 alpha 3:
+
+ * Changed logic for locating component .elc files to be even smarter.
+
+ * Changed "make install" to "make compile"; added different "make install".
+
+ * Improved "make compile" to check file dates and compile only when needed.
+
+ * Made output of "make compile" in batch mode more compact and readable.
+
+ * Replaced "Quick Overview" in manual with "Demonstration of Calc".
+
+ * Changed to use keymaps for dispatching M-# and h prefix keys.
+
+ * Added TAGS target to the Calc Makefile.
+
+ * Removed most doc strings from functions; new help commands are better.
+
+ * Got rid of some crufty "fset" calls that were cluttering the code.
+
+ * Split calc-grab-region into two functions, calc-grab-region/-rectangle.
+
+ * Swapped positions of stack and trail in full-calc-keypad display.
+
+ * Improved line-breaking algorithm for displaying long formulas.
+
+ * Improved display of control characters in vectors shown as strings.
+
+ * Changed `d o' to allow fraction format to specify desired denominator.
+
+ * Changed `M-# y' to respect overwrite mode in target buffer.
+
+ * Added `H' prefix to display-mode commands to suppress stack refresh.
+
+ * Changed "calc-why" mechanism to display urgent messages automatically.
+
+ * Handled taking derivatives of symbolic integrals and vice-versa.
+
+ * Handled integrating vectors of formulas.
+
+ * Incorporated Ewerlid's polynomial division and GCD functions into Calc.
+
+ * Improved algebraic operations on "mod" forms, esp. polynomials.
+
+ * Added some more financial functions (sln, syd, ddb).
+
+ * Added nest, anest, fixp, and afixp (`H V R' and `H V U') functions.
+
+ * Added `a .' (calc-remove-equal) command to take apart equations.
+
+ * Generalized dfact to work for negative odd integers; added !! syntax.
+
+ * Changed `k f' to factor 1, 0, and negative integers.
+
+ * Changed `u M', etc., to accept +/- and [ .. ] forms as distributions.
+
+ * Changed `g q' to remove *Gnuplot Commands/Trail* window if present.
+
+ * Added support for Francois Pinard's "dumb terminal" driver for GNUPLOT.
+
+ * Added ":: remember" feature for rewrite rules.
+
+ * Changed rewrites to let pattern "a*b" match "x/2" with a=x, b=1/2.
+
+ * Added ability to put function names like "simplify" in rewrite schedule.
+
+ * Added "Rewrites Tutorial" to the manual.
+
+ * Changed ` to bind RET as newline instead of finish if editing a vector.
+
+ * Added some new exercises to the List Tutorial.
+
+ * Changed `Z F', `V M', etc. not to remove stored vars from def arg list.
+
+ * Added parsing for /1, 2, 3/ notation for Fortran mode vectors.
+
+ * Added a "%%" syntax for comments in formulas being read.
+
+ * Fixed a bug in which failing `h k' removed an existing Info window.
+
+ * Fixed a bug in `j /' operating on subformulas like "a + b".
+
+ * Fixed a bug in which "inf = inf" undesirably evaluated to 1.
+
+ * Fixed a bug that simplified "0 = 1 + a + 2" to "0 = a".
+
+ * Fixed a bug that failed for rewrite patterns like "fib(1 ||| 2)".
+
+ * Fixed a bug that arose because rewrite programs are non-reentrant.
+
+
+Version 2.00 alpha 2:
+
+ * Changed LFD terminating algebraic entry to push in no-simplify mode.
+
+ * Changed so that `K -' interprets `-' as calc-minus, not neg prefix arg.
+
+ * Improved `h c' command to understand all Calc key sequences.
+
+ * Fixed problems with DistribRules, NegateRules, and FitRules.
+
+ * Fixed several bad node pointers in the manual.
+
+ * Fixed a bug in `h C-w' when used with makeinfo-formatted manuals.
+
+ * Fixed a bug in sqrt(-1) when Polar and HMS modes are enabled.
+
+ * Fixed/improved dscalar and deven functions; added dodd.
+
+ * Fixed a bug in polynomial handling that also affected sum(sin(k),k,1,n).
+
+ * Fixed various other glitches in the manual.
+
+
+Version 2.00 alpha 1:
+
+ * Calc's tar file now creates a calc-(version) directory to unpack into.
+
+ * Calc now comes with a Makefile; install with "make install".
+
+ * Calc now comes already split into many files; installation is much simpler.
+
+ * Changed base file name of the manual from "calc-info" to "calc.info".
+
+ * Key binding for `M-# w' was documented but not implemented.
+
+ * Bound M-# ' to be synonymous with `M-# f' (used to be `M-# q').
+
+ * Changed M-# M-# to use last interface of C or K; E no longer counts.
+
+ * Changed `i' (and `M-# i') not to return to Top node unnecessarily.
+
+ * Changed `h' to be a prefix key with various help commands.
+
+ * Changed `s' to be a prefix key with various store and recall commands.
+
+ * Keys `i', `r', and `l' are obsolete (moved to `h' and `s' prefixes).
+
+ * Rearranged `K', `X', and `M-RET' keys; `K' is now calc-keep-args.
+
+ * Changed quick-calc to display input formula as well as output if room.
+
+ * Changed quick-calc to interact with the editing buffer and kill ring.
+
+ * Created pack, unpack, unpackt function equivalents of `v p', `v u'.
+
+ * Changed to expand (a/b)^x to a^x/b^x only if b > 0 (not if a > 0).
+
+ * Changed math-possible-signs to understand sqrt function.
+
+ * Changed Z [, rewrites to consider any provably non-zero value as true.
+
+ * Changed normal language modes to accept ** as a synonym for ^.
+
+ * Added "maple" language mode.
+
+ * Changed, e.g., Mathematica "(2 + 3 I)^(1.23*10^20)" to include parens.
+
+ * Generalized math-compose-big properties for all language modes.
+
+ * Introduced "string" and other function for composing expressions.
+
+ * Changed many recursive vector routines to use loops instead.
+
+ * Added evalv, evalvn function equivalents to `=', `N'.
+
+ * Changed "expr =>" not to evaluate at all if in no-simplify mode.
+
+ * Redesigned user interface of `a F' (calc-curve-fit) command.
+
+ * Added "phase" feature to the rewrite rule system. 
+
+ * Added "&&&", "|||", "!!!" to the rewrite rule system.
+
+ * Introduced a new notation for rewrites:  LHS := RHS :: COND.
+
+ * Changed `a r' (but not `j r') to repeat 100 times by default.
+
+ * Integrated EvalRules more cleanly into the default simplifications.
+
+ * Added `H v l' [mdims] to measure the dimensions of a matrix.
+
+ * Changed `u c' to interpret "/units" as "1/units".
+
+ * Added `u a' to adjust unit prefix letters automatically.
+
+ * Changed `u s' to enable scalar mode while simplifying.
+
+ * Changed `c f' [pfloat] not to float integer powers or subscripts.
+
+ * Added a three-argument form for the "hms" function.
+
+ * Changed, e.g., sin(90) degrees to produce 1 instead of 1.0.
+
+ * Changed symbolic mode to prefer sqrt(int): abs([1 2 3]) => sqrt(14).
+
+ * Enhanced solver to handle, e.g., x + 1/x = a; exp(x) + exp(-x) = a.
+
+ * Enhanced simplifier to handle, e.g., exp(a+2) / e^a => e^2.
+
+ * Enhanced `a s' to simplify sqrt(x) - x^1:2 and exp(x) - e^x to 0.
+
+ * Added -(a + b) to -a - b as a default simplification.
+
+ * Added rules for differentiating sum() and prod() functions.
+
+ * Added a few more energy units (due to Przemek Klosowski).
+
+ * Added overflow/underflow checking for all floating-point arithmetic.
+
+ * Extended error forms to work with complex numbers.
+
+ * Generalized GCD to handle fractional arguments.
+
+ * Changed graphics routines to evaluate "x" values, e.g., [-pi .. pi].
+
+ * Added `g q', like `g K' but without viewing the Gnuplot Trail.
+
+ * Changed `g p' and `V M' to display better "Working..." messages.
+
+ * Modified `M-# g' to be more robust about grabbing formulas.
+
+ * Added `Y' prefix key reserved for user-written extensions.
+
+ * Added calc-load-hook and calc-ext-load-hook.
+
+ * Prevented calc-install from leaving large ~ files behind.
+
+ * Changed @bullet to @bullet{} in manual to conform to texinfo spec.
+
+ * Rearranged some chapters in the manual to be a bit more logical.
+
+ * Added calc-split-summary command.
+
+ * Fixed several bugs in embedded mode.
+
+ * Fixed a bug in calc-vector-covariance that required a prefix arg.
+
+ * Fixed a bug that prevented parsing "a=>" with no right-hand side.
+
+ * Fixed a bug which allowed incorrectly dividing a vector by a vector.
+
+ * Fixed a bug formatting sum(...)^2 in Big mode.
+
+ * Fixed a bug that prevented Calc from deleting old graphics temp files.
+
+ * Fixed some typos calling calc-inverse-func instead of calc-invert-func.
+
+ * Fixed bugs in the derivatives of conj, deg, and rad; added re, im.
+
+ * Fixed a bug where (r;theta) parsed as r exp(theta i) even in Deg mode.
+
+ * Fixed a bug which gave wrong answer for exp of a polar complex number.
+
+ * Fixed a bug in `Z F' that failed if formula used non-arg variables.
+
+ * Fixed a bad pointer to Info node "Assignments in Embedded Mode".
+
+ * Fixed several errors in the Calc Summary.
+
+
+Version 1.08 beta 1:
+
+ * Calc's copyright has been assigned to FSF, for inclusion in Emacs 19!
+
+ * Changed M-# to be a two-key sequence; use M-# M-# to start Calc now.
+
+ * Rewrote and expanded the introductory chapter of the manual.
+
+ * Added a key and function summary to the manual.
+
+ * Changed the manual to take better advantage of TeX's math formatting.
+
+ * Changed manual to be printable in @smallbook format.
+
+ * Added "calc-embedded" mode.
+
+ * Added "=>" [evalto] operator.
+
+ * Added facilities for date and date/time arithmetic.
+
+ * Added a set of financial functions (pv, fv, etc.).
+
+ * Added infinite quantities inf, uinf, and nan (plus infinite intervals).
+
+ * Added "EvalRules", "SimpRules", and "ExtSimpRules" variables.
+
+ * Added sum and product commands `a +', `a -', `a *', `a T'.
+
+ * Enhanced `a S' and `a P' to solve systems of equations.
+
+ * Enhanced solver to handle eqns like sin(x) = cos(2 x), sqrt(x) + x = 1.
+
+ * Added `a M' (calc-map-equation) command.
+
+ * Added new statistical functions: mean, standard deviation, etc.
+
+ * Added line, polynomial, and curve fitting commands (`a L' and `a F').
+
+ * Added support for composite units, e.g., "mi+ft+in".
+
+ * Enhanced "Big" mode to format square roots, choose, and powers better.
+
+ * Enhanced "Big" mode to display fractions in large notation.
+
+ * Added several alternate formats for matrix display.
+
+ * Changed TeX mode to write "(1 + x^2)" instead of "\left(1 + x^2\right)".
+
+ * Added support for relational operators in TeX and FORTRAN modes.
+
+ * Added recognition of accents like \dot, \tilde, \underline in TeX mode.
+
+ * Added "eqn" language mode.
+
+ * Added extra control over display justification with `d <', `d =', `d >'.
+
+ * Added calc-left-label and calc-right-label (`d {', `d }').
+
+ * Added "nn%" syntax for algebraic formulas; equivalent to "nn * .01".
+
+ * Added input syntaxes like a = b = c, a != b != c, a <= b < c.
+
+ * Changed "_" to mean subscripts; old use of "_" in vars is now "#".
+
+ * Introduced "matrix mode" and "scalar mode" (`m v').
+
+ * Introduced generic identity matrices (idn(1)).
+
+ * Added a method for declaring variables to be real, integer, > 0, etc.
+
+ * Added `Z S' command for editing stored value of a variable.
+
+ * Added "subst" algebraic function equivalent to the `a b' command.
+
+ * Added `a f' command, changed deriv/integ/solve-for to use it.
+
+ * Improved `a s' to simplify (x + y) (y + x) to (x + y)^2.
+
+ * Improved `a s' to simplify i^2 to -1.
+
+ * Improved `a s' to simplify, e.g., sin(pi/3) in Symbolic mode.
+
+ * Improved `a s' to simplify sqrt(8) to 2 sqrt(2), 1/sqrt(2) to sqrt(2)/2.
+
+ * Moved sin(arccos(x)) from `a e' to `a s'; not unsafe after all!
+
+ * Changed (x y)^z => x^z y^z to be a usually-unsafe simplification.
+
+ * Added thorough documentation of `a s' and `a e' to the manual.
+
+ * Improved `a c' to collect "f(a)" even if "a" also appears elsewhere.
+
+ * Introduced lin, linnt, islin, islinnt functions for linearity testing.
+
+ * Improved `a x' to use binomial theorem to give simpler answers.
+
+ * Improved `j D' to distribute powers of sums: (a + b)^n.
+
+ * Improved `j M' to merge products of powers (may need no-simplify mode).
+
+ * Changed to use defvar for DistribRules etc. so `Z V' works with them.
+
+ * Improved `j *' and `j /' to work properly in a few more cases.
+
+ * Improved `V R' to use identity value when reducing empty vectors.
+
+ * Improved `v p' and `v u' to support more complex packing operations.
+
+ * Disabled automatic simplification of sqrt(2)/2 to 1/sqrt(2).
+
+ * Bound SPC and RET to press, TAB to next-menu in *Calc Keypad* buffer.
+
+ * Added C-u ' to do algebraic entry with language mode forced to normal.
+
+ * Added "$1", "$2", etc. input notation for algebraic entry.
+
+ * Changed unary operators like `n', `&' to treat neg prefix args like RET.
+
+ * Changed ` (calc-edit) to show full precision regardless of float format.
+
+ * Enhanced quick-calc to display integers in several formats.
+
+ * Documented `g H' (calc-graph-hide) command (had been left from manual).
+
+ * Enhanced floor/ceil/trunc/round in several ways.
+
+ * Added rounde and roundu functions.
+
+ * Changed `c 1' through `c 9' to change small floats to 0.0; added `c 0'.
+
+ * Enhanced set operations to work on sets of intervals.
+
+ * Fixed erf(0), utpn(x,x,y), and arccosh(-1) to work properly.
+
+ * Changed complex arctan and arctanh to follow Steele 2nd edition.
+
+ * Expanded "Branch Cuts" section of the manual with some useful tables.
+
+ * Rearranged order of words in mode line to be a bit more logical.
+
+ * Changed `m N' (num-simplify) mode to evaluate constant vectors, too.
+
+ * Changed `a r'/`j r' to prompt twice for separate LHS/RHS if necessary.
+
+ * Enhanced `let(v,x)' in rewrites by allowing arbitrary patterns for v.
+
+ * Changed cursor positioning in second prompt for `a b' (calc-substitute).
+
+ * Changed `y' to omit line numbers more consistently.
+
+ * Changed `o' (calc-realign) to reset horizontal scrolling to zero, also.
+
+ * Added "pred" mode for calc-eval.
+
+ * Added "calc-report-bug" as an alias for "report-calc-bug".
+
+ * Added `Z T' and "calc-pass-errors" to aid debugging Calc-related code.
+
+ * Added "calc-load-everything" (`m X' or `M-# L') command.
+
+ * Enhanced calc-install to pre-build units table, CommuteRules, etc.
+
+ * Changed Calc to interact more gracefully with load-path.
+
+ * Changed Lisp Variable Index in manual to include user variables, too.
+
+ * Fixed a bug that prevented calc-install from working under VMS.
+
+ * Fixed a bug that sometimes crashed rewrites dealing with subtractions.
+
+ * Fixed a bug that prevented `a S' from solving "3 - x = 1 + x"!
+
+ * Fixed a bug in solver that crashed for certain cubics and quartics.
+
+ * Fixed a bug in calc-simplify that crashed for equations and ineqs.
+
+ * Fixed a bug which placed the "[" oddly in `d B' + `v /' mode.
+
+ * Fixed a bug where finishing calc-edit improperly obeyed language mode.
+
+ * Fixed a bug formatting (-1)^n in Big mode after selection commands.
+
+ * Fixed a bug that got ">=" and "<=" backwards in rewrite conditions.
+
+ * Fixed a bug that broke the `"x"' key in calc-keypad mode.
+
+ * Fixed a bug in which `MAP$' in calc-keypad didn't display "Working...".
+
+ * Fixed a bug where matrix division gave bad result for singular matrix.
+
+ * Fixed a bug which closed Calc window if calc-grab-region got an error.
+
+ * Fixed a bug where `a s' failed on formulas containing dimension errors.
+
+ * Fixed a bug that caused `m F' to hang.
+
+ * Fixed a bug in complex arithmetic that caused problems with solver.
+
+ * Fixed a bug which raised intervals to interval powers incorrectly.
+
+ * Fixed a bug in utpp/ltpp (order of arguments did not match the manual).
+
+ * Fixed a bug in which `t y' rounded yanked data with old precision.
+
+ * Fixed a bug in which "in(3, [3 .. 3))" returned true.
+
+ * Fixed a bug which simplified abs(abs(x)) incorrectly.
+
+ * Fixed a bug in which (a^2)^1:3 was unsafely simplified to a^2:3.
+
+ * Fixed a bug in rewrite system which missed pattern "2 sin(x) cos(x)".
+
+ * Fixed a bug in rewrite system which missed pattern "a - a cos(x)^2".
+
+ * Fixed obsolete trail tags gsmp, gneg, ginv to jsmp, jneg, jinv.
+
+ * Fixed some errors and made improvements in units table [Ulrich Mueller].
+
+
+Version 1.07:
+
+ * Added `m F' (calc-settings-file-name) command.
+
+ * Added calc-autoload-directory variable.
+
+ * Extended Z ` to accept a prefix argument.
+
+ * Added keystrokes (v h, v k) for head, tail, cons.
+
+ * Extended `v e' to accept a vector as the filler.
+
+ * Changed `V M', `V R' to accept mapping-mode keys in uppercase, too.
+
+ * Changed V M ' etc. to accept $, $$, ... as argument indicators.
+
+ * Changed `t y' to accept a prefix argument.
+
+ * Put in a cleaner and safer random number generator for `k r' et al.
+
+ * Fixed a bug which completely broke `a r' command!
+
+ * Fixed "0 * matrix" to generate a zero matrix instead of 0.
+
+ * Fixed a bug in `a R' which sometimes caused it to crash.
+
+ * Fixed a fatal typo in the TeX version of the manual.
+
+ * Fixed a bug that prevented C-k, C-w, M-w from working in Trail buffer.
+
+ * Fixed another bug in `Z P' command.
+
+ * Fixed a bug in `u s' which incorrectly simplified subtractions.
+
+ * Fixed an argument-name aliasing bug evaluating lambda( ) formulas.
+
+ * Fixed overfull hboxes in the manual.
+
+ * Fixed various other bugs in the manual.
+
+
+Version 1.06:
+
+ * Added "calc-keypad" mode for X window system users (try it!).
+
+ * Improved "calc-eval" for calling/operating Calc from user-written Lisp.
+
+ * Moved vector accumulate command to `V U' (old `H V R' still supported).
+
+ * Added right-to-left reductions: `I V R' and `I V U'.
+
+ * Added set operations on vectors: intersect, union, diff, xor.
+
+ * Added `I v s' to remove a subvector from a vector.
+
+ * Introduced `H |' to append two vectors with no magical special cases.
+
+ * Introduced rhead, rtail, and rcons for isolating last vector element.
+
+ * Changed `g p' to keep temp files around until data actually change.
+
+ * Improved `a S' to solve many higher-order polynomial equations.
+
+ * Added `a P' to produce a vector of all solutions to an equation.
+
+ * Enhanced `a v' and `j v' to allow top-level-only evaluation.
+
+ * Changed `j DEL' to delete a side of an eqn or ineq, leaving other side.
+
+ * Fixed binding for keys `j 1' through `j 9'.
+
+ * Introduced "let" marker in rewrite rules.
+
+ * Enhanced the "sign" function to provide a two-argument version.
+
+ * Changed "max-specpdl-size exceeded" error message to be user-friendly.
+
+ * Put "<Aborted>" in the trail in above case and when user presses C-g.
+
+ * Changed TeX mode to generate \ldots instead of \dots, recognize both.
+
+ * Changed "sin(0)" etc. (for integer 0) to generate "0" instead of "0.".
+
+ * Enhanced Programming Tutorial exercise 2.
+
+ * Fixed an error in the answer to Types Tutorial exercise 3.
+
+ * Fixed several bugs relating to head, tail, and cons functions.
+
+ * Fixed some other minor typos in the manual.
+
+ * Fixed several bugs in `Z P' (calc-user-define-permanent).
+
+ * Fixed several bugs that broke the `g P' command.
+
+
+Version 1.05:
+
+ * Created a calc-install command to ease installation.
+
+ * Added lots of exercises to the Tutorial section of the manual.
+
+ * Added ability to select and operate on sub-formulas.
+
+ * Substantially improved the algebraic rewrite-rule system.
+
+ * Added a set of graphing commands that use GNUPLOT.
+
+ * Added a command (`a R') for finding numerical roots to equations.
+
+ * Added several new math functions, such as erf and Bessel functions.
+
+ * Added key bindings for miscellaneous commands using the "f" prefix key.
+
+ * Added lots of new vector operations, many of them in the spirit of APL.
+
+ * Added more control over vector display, including an abbreviated mode.
+
+ * Improved keyboard macro editing; added read-kbd-macro to macedit.el.
+
+ * Introduced the `m S' (calc-shift-prefix) command.
+
+ * Enhanced the calc-edit command in several ways.
+
+ * Made it possible to hit ` (calc-edit) during numeric/algebraic entry.
+
+ * Enhanced the calc-solve-for command to handle inequalities.
+
+ * Enhanced calc-simplify to handle equations and inequalities.
+
+ * Taught log10 and log to look for exact integer or rational results.
+
+ * Added ability to take Nth roots directly.
+
+ * Added "increment" and "decrement" commands for integers and floats.
+
+ * Added "full-help" command, changed "h" key to invoke it.
+
+ * Added special help for Inverse and Hyperbolic prefixes.
+
+ * Added an optional prefix argument to `o' (calc-realign).
+
+ * Changed `t s' and `t r' to use RET as the search exit key.
+
+ * Made handling of operator keys for V M, V R, etc. more regular.
+
+ * Improved TeX mode; added support for \matrix format.
+
+ * Added a variant of `m a' mode that only affects ( and [ keys.
+
+ * Fixed "Mismatch" message for algebraic entry of semi-open intervals.
+
+ * Trimmed fat from calc.el to speed loading, moved more to calc-ext.el.
+
+ * Fixed a bug in which minibuffer entry rounded to out-of-date precision.
+
+ * Fixed a bug which crashed Calc 1.04 under Epoch.
+
+ * Fixed a bug which messed up Calc Trail's mode line, among other things.
+
+ * Fixed a bug which caused trail ">" to show only when in Trail buffer.
+
+ * Fixed a bug in which "calc" called "calc-grab-region" with too few args.
+
+ * Fixed bugs in both implementation and documentation of calc-perm.
+
+ * Fixed a bug in which calc-simplify-extended always used radians.
+
+ * Fixed a bug where calc-comma failed to override "polar" mode.
+
+ * Fixed a bug doing mixed arithmetic on rectangular+polar complex numbers.
+
+ * Fixed several bugs in transcendental functions with complex arguments.
+
+ * Fixed a bug in which `a s' simplified "x / .5" to ".5 x".
+
+ * Fixed numerous other bugs in various parts of Calc.
+
+ * Completed the "Hooks" section of the "Internals" chapter of the manual.
+
+
+Version 1.04:
+
+ * Included a copy of revision history (from README) in calc.el.
+
+ * Added the "calc-split" feature to split calc-ext.el into smaller bits.
+
+ * Changed calc-unpack to unpack floats and fractions, too.
+
+ * Added "mant", "xpon", and "scf" functions for decomposing floats.
+
+ * Fixed a bug in the "y" command with positive prefix arguments.
+
+ * Rearranged binary shift/rotate command keys to be a bit more convenient.
+
+ * Fixed a bug in which simplifying "(0/0) * 2" crashed with a Lisp error.
+
+ * Made `H F' [ffloor] and friends faster for very large arguments.
+
+ * Made calc-define-del more robust.
+
+ * Handled pasting of data into the Calculator using the mouse under X.
+
+ * Made overlay-arrow variables buffer-local to avoid interference.
+
+ * Fixed a problem in which Calc Trail buffer got stuck after a C-x C-w.
+
+
+Version 1.03:
+
+ * Changed math-choose to compute n-choose-m faster when m is large.
+
+ * Fixed some problems with TeX mode.
+
+ * Fixed a bug that prevented `b s' from working without a prefix argument.
+
+ * Added "calc-eval" function.
+
+ * Improved calc-grab-region.
+
+
+Version 1.02:
+
+ * Fixed a bug in Tutorial: telephone pole height/distance were switched!
+
+ * Fixed a few other things in the manual.
+
+ * Added "full-calc" command.
+
+ * Added "calc-insert-variables" (`Z I') command.
+
+ * Quick Calc now works even if you are already in the minibuffer.
+
+ * Fixed a bug in math-mul-bignum-digit which affected math-and, etc.
+
+ * Definition of "Hectares" was wrong in units table.
+
+ * Fixed a bug in calc-execute-kbd-macro concerning undo and refresh.
+
+ * Bound "calc-undo" to `C-x u' as well as `C-_' and `U'.
+
+Version 1.01:
+
+ * Added a tutorial section to the manual.
+
+ * Next and Prev for node Strings in the manual were reversed; fixed.
+
+ * Changed "'bignum" in calc-isqrt-bignum-iter to "'bigpos".
+
+ * Fixed a bug that prevented "$" from working during algebraic entry.
+
+ * Fixed a bug caused by an X (last-X) command following a K (macro) cmd.
+
+ * Fixed a bug in which K command incorrectly formatted stack in Big mode.
+
+ * Added space between unary operators and non-flat compositions.
+   (Otherwise, "-(a/b)" in Big mode blended the minus sign into the rule!)
+
+ * Fixed formatting of (-1)^n in Big mode.
+
+ * Fixed some problems relating to "not" operator in Pascal language mode.
+
+ * Fixed several bugs relating to V M ' and V M $ sequences.
+
+ * Fixed matrix-vector multiplication to produce a vector.
+
+ * Introduced Z ` ... Z ' commands; renamed old Z ' to Z #.
+
+ * Fixed various other bugs.
+
+ * Added calc-settings-file variable suggested by C. Witty.
+
+
+Version 1.00:
+
+ * First official release of Calc.
+
+ * If you used the Beta test version (0.01), you will find that this
+   version of Calc is over 50% larger than the original release.
+   General areas of improvement include much better algebra features;
+   operations on units; language modes; simplification modes; interval
+   arithmetic; vector mapping and reduction.  Other new commands include
+   calc-fraction and calc-grab-region.  The program has been split into
+   two parts for faster loading, and the manual is more complete.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/calc-aent.el	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,1163 @@
+;; Calculator for GNU Emacs, part I [calc-aent.el]
+;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+;; Written by Dave Gillespie, daveg@synaptics.com.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY.  No author or distributor
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing.  Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License.   A copy of this license is
+;; supposed to have been given to you along with GNU Emacs so you
+;; can know your rights and responsibilities.  It should be in a
+;; file named COPYING.  Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+
+
+
+;; This file is autoloaded from calc.el.
+(require 'calc)
+
+(require 'calc-macs)
+
+(defun calc-Need-calc-aent () nil)
+
+
+(defun calc-do-quick-calc ()
+  (calc-check-defines)
+  (if (eq major-mode 'calc-mode)
+      (calc-algebraic-entry t)
+    (let (buf shortbuf)
+      (save-excursion
+	(calc-create-buffer)
+	(let* ((calc-command-flags nil)
+	       (calc-dollar-values calc-quick-prev-results)
+	       (calc-dollar-used 0)
+	       (enable-recursive-minibuffers t)
+	       (calc-language (if (memq calc-language '(nil big))
+				  'flat calc-language))
+	       (entry (calc-do-alg-entry "" "Quick calc: " t))
+	       (alg-exp (mapcar (function
+				 (lambda (x)
+				   (if (and (not calc-extensions-loaded)
+					    calc-previous-alg-entry
+					    (string-match
+					     "\\`[-0-9._+*/^() ]+\\'"
+					     calc-previous-alg-entry))
+				       (calc-normalize x)
+				     (calc-extensions)
+				     (math-evaluate-expr x))))
+				entry)))
+	  (if (and (= (length alg-exp) 1)
+		   (eq (car-safe (car alg-exp)) 'calcFunc-assign)
+		   (= (length (car alg-exp)) 3)
+		   (eq (car-safe (nth 1 (car alg-exp))) 'var))
+	      (progn
+		(calc-extensions)
+		(set (nth 2 (nth 1 (car alg-exp))) (nth 2 (car alg-exp)))
+		(calc-refresh-evaltos (nth 2 (nth 1 (car alg-exp))))
+		(setq alg-exp (list (nth 2 (car alg-exp))))))
+	  (setq calc-quick-prev-results alg-exp
+		buf (mapconcat (function (lambda (x)
+					   (math-format-value x 1000)))
+			       alg-exp
+			       " ")
+		shortbuf buf)
+	  (if (and (= (length alg-exp) 1)
+		   (memq (car-safe (car alg-exp)) '(nil bigpos bigneg))
+		   (< (length buf) 20)
+		   (= calc-number-radix 10))
+	      (setq buf (concat buf "  ("
+				(let ((calc-number-radix 16))
+				  (math-format-value (car alg-exp) 1000))
+				", "
+				(let ((calc-number-radix 8))
+				  (math-format-value (car alg-exp) 1000))
+				(if (and (integerp (car alg-exp))
+					 (> (car alg-exp) 0)
+					 (< (car alg-exp) 127))
+				    (format ", \"%c\"" (car alg-exp))
+				  "")
+				")")))
+	  (if (and (< (length buf) (screen-width)) (= (length entry) 1)
+		   calc-extensions-loaded)
+	      (let ((long (concat (math-format-value (car entry) 1000)
+				  " =>  " buf)))
+		(if (<= (length long) (- (screen-width) 8))
+		    (setq buf long))))
+	  (calc-handle-whys)
+	  (message "Result: %s" buf)))
+      (if (eq last-command-char 10)
+	  (insert shortbuf)
+	(setq kill-ring (cons shortbuf kill-ring))
+	(if (> (length kill-ring) kill-ring-max)
+	    (setcdr (nthcdr (1- kill-ring-max) kill-ring) nil))
+	(setq kill-ring-yank-pointer kill-ring))))
+)
+
+(defun calc-do-calc-eval (str separator args)
+  (calc-check-defines)
+  (catch 'calc-error
+    (save-excursion
+      (calc-create-buffer)
+      (cond
+       ((and (consp str) (not (symbolp (car str))))
+	(let ((calc-language nil)
+	      (math-expr-opers math-standard-opers)
+	      (calc-internal-prec 12)
+	      (calc-word-size 32)
+	      (calc-symbolic-mode nil)
+	      (calc-matrix-mode nil)
+	      (calc-angle-mode 'deg)
+	      (calc-number-radix 10)
+	      (calc-leading-zeros nil)
+	      (calc-group-digits nil)
+	      (calc-point-char ".")
+	      (calc-frac-format '(":" nil))
+	      (calc-prefer-frac nil)
+	      (calc-hms-format "%s@ %s' %s\"")
+	      (calc-date-format '((H ":" mm C SS pp " ")
+				  Www " " Mmm " " D ", " YYYY))
+	      (calc-float-format '(float 0))
+	      (calc-full-float-format '(float 0))
+	      (calc-complex-format nil)
+	      (calc-matrix-just nil)
+	      (calc-full-vectors t)
+	      (calc-break-vectors nil)
+	      (calc-vector-commas ",")
+	      (calc-vector-brackets "[]")
+	      (calc-matrix-brackets '(R O))
+	      (calc-complex-mode 'cplx)
+	      (calc-infinite-mode nil)
+	      (calc-display-strings nil)
+	      (calc-simplify-mode nil)
+	      (calc-display-working-message 'lots)
+	      (strp (cdr str)))
+	  (while strp
+	    (set (car strp) (nth 1 strp))
+	    (setq strp (cdr (cdr strp))))
+	  (calc-do-calc-eval (car str) separator args)))
+       ((eq separator 'eval)
+	(eval str))
+       ((eq separator 'macro)
+	(calc-extensions)
+	(let* ((calc-buffer (current-buffer))
+	       (calc-window (get-buffer-window calc-buffer))
+	       (save-window (selected-window)))
+	  (if calc-window
+	      (unwind-protect
+		  (progn
+		    (select-window calc-window)
+		    (calc-execute-kbd-macro str nil (car args)))
+		(and (window-point save-window)
+		     (select-window save-window)))
+	    (save-window-excursion
+	      (select-window (get-largest-window))
+	      (switch-to-buffer calc-buffer)
+	      (calc-execute-kbd-macro str nil (car args)))))
+	nil)
+       ((eq separator 'pop)
+	(or (not (integerp str))
+	    (= str 0)
+	    (calc-pop (min str (calc-stack-size))))
+	(calc-stack-size))
+       ((eq separator 'top)
+	(and (integerp str)
+	     (> str 0)
+	     (<= str (calc-stack-size))
+	     (math-format-value (calc-top-n str (car args)) 1000)))
+       ((eq separator 'rawtop)
+	(and (integerp str)
+	     (> str 0)
+	     (<= str (calc-stack-size))
+	     (calc-top-n str (car args))))
+       (t
+	(let* ((calc-command-flags nil)
+	       (calc-next-why nil)
+	       (calc-language (if (memq calc-language '(nil big))
+				  'flat calc-language))
+	       (calc-dollar-values (mapcar
+				    (function
+				     (lambda (x)
+				       (if (stringp x)
+					   (progn
+					     (setq x (math-read-exprs x))
+					     (if (eq (car-safe x)
+						     'error)
+						 (throw 'calc-error
+							(calc-eval-error
+							 (cdr x)))
+					       (car x)))
+					 x)))
+				    args))
+	       (calc-dollar-used 0)
+	       (res (if (stringp str)
+			(math-read-exprs str)
+		      (list str)))
+	       buf)
+	  (if (eq (car res) 'error)
+	      (calc-eval-error (cdr res))
+	    (setq res (mapcar 'calc-normalize res))
+	    (and (memq 'clear-message calc-command-flags)
+		 (message ""))
+	    (cond ((eq separator 'pred)
+		   (calc-extensions)
+		   (if (= (length res) 1)
+		       (math-is-true (car res))
+		     (calc-eval-error '(0 "Single value expected"))))
+		  ((eq separator 'raw)
+		   (if (= (length res) 1)
+		       (car res)
+		     (calc-eval-error '(0 "Single value expected"))))
+		  ((eq separator 'list)
+		   res)
+		  ((memq separator '(num rawnum))
+		   (if (= (length res) 1)
+		       (if (math-constp (car res))
+			   (if (eq separator 'num)
+			       (math-format-value (car res) 1000)
+			     (car res))
+			 (calc-eval-error
+			  (list 0
+				(if calc-next-why
+				    (calc-explain-why (car calc-next-why))
+				  "Number expected"))))
+		     (calc-eval-error '(0 "Single value expected"))))
+		  ((eq separator 'push)
+		   (calc-push-list res)
+		   nil)
+		  (t (while res
+		       (setq buf (concat buf
+					 (and buf (or separator ", "))
+					 (math-format-value (car res) 1000))
+			     res (cdr res)))
+		     buf))))))))
+)
+
+(defun calc-eval-error (msg)
+  (if (and (boundp 'calc-eval-error)
+	   calc-eval-error)
+      (if (eq calc-eval-error 'string)
+	  (nth 1 msg)
+	(error "%s" (nth 1 msg)))
+    msg)
+)
+
+
+;;;; Reading an expression in algebraic form.
+
+(defun calc-auto-algebraic-entry (&optional prefix)
+  (interactive "P")
+  (calc-algebraic-entry prefix t)
+)
+
+(defun calc-algebraic-entry (&optional prefix auto)
+  (interactive "P")
+  (calc-wrapper
+   (let ((calc-language (if prefix nil calc-language))
+	 (math-expr-opers (if prefix math-standard-opers math-expr-opers)))
+     (calc-alg-entry (and auto (char-to-string last-command-char)))))
+)
+
+(defun calc-alg-entry (&optional initial prompt)
+  (let* ((sel-mode nil)
+	 (calc-dollar-values (mapcar 'calc-get-stack-element
+				     (nthcdr calc-stack-top calc-stack)))
+	 (calc-dollar-used 0)
+	 (calc-plain-entry t)
+	 (alg-exp (calc-do-alg-entry initial prompt t)))
+    (if (stringp alg-exp)
+	(progn
+	  (calc-extensions)
+	  (calc-alg-edit alg-exp))
+      (let* ((calc-simplify-mode (if (eq last-command-char ?\C-j)
+				     'none
+				   calc-simplify-mode))
+	     (nvals (mapcar 'calc-normalize alg-exp)))
+	(while alg-exp
+	  (calc-record (if calc-extensions-loaded (car alg-exp) (car nvals))
+		       "alg'")
+	  (calc-pop-push-record-list calc-dollar-used
+				     (and (not (equal (car alg-exp)
+						      (car nvals)))
+					  calc-extensions-loaded
+					  "")
+				     (list (car nvals)))
+	  (setq alg-exp (cdr alg-exp)
+		nvals (cdr nvals)
+		calc-dollar-used 0)))
+      (calc-handle-whys)))
+)
+
+(defun calc-do-alg-entry (&optional initial prompt no-normalize)
+  (let* ((calc-buffer (current-buffer))
+	 (blink-paren-hook 'calcAlg-blink-matching-open)
+	 (alg-exp 'error))
+    (if (boundp 'calc-alg-ent-map)
+	()
+      (setq calc-alg-ent-map (copy-keymap minibuffer-local-map))
+      (define-key calc-alg-ent-map "'" 'calcAlg-previous)
+      (define-key calc-alg-ent-map "`" 'calcAlg-edit)
+      (define-key calc-alg-ent-map "\C-m" 'calcAlg-enter)
+      (define-key calc-alg-ent-map "\C-j" 'calcAlg-enter)
+      (or calc-emacs-type-19
+	  (let ((i 33))
+	    (setq calc-alg-ent-esc-map (copy-sequence esc-map))
+	    (while (< i 127)
+	      (aset calc-alg-ent-esc-map i 'calcAlg-escape)
+	      (setq i (1+ i))))))
+    (or calc-emacs-type-19
+	(define-key calc-alg-ent-map "\e" nil))
+    (if (eq calc-algebraic-mode 'total)
+	(define-key calc-alg-ent-map "\e" calc-alg-ent-esc-map)
+      (define-key calc-alg-ent-map "\ep" 'calcAlg-plus-minus)
+      (define-key calc-alg-ent-map "\em" 'calcAlg-mod)
+      (define-key calc-alg-ent-map "\e=" 'calcAlg-equals)
+      (define-key calc-alg-ent-map "\e\r" 'calcAlg-equals)
+      (define-key calc-alg-ent-map "\e%" 'self-insert-command))
+    (setq calc-aborted-prefix nil)
+    (let ((buf (read-from-minibuffer (or prompt "Algebraic: ")
+				     (or initial "")
+				     calc-alg-ent-map nil)))
+      (if (eq alg-exp 'error)
+	  (if (eq (car-safe (setq alg-exp (math-read-exprs buf))) 'error)
+	      (setq alg-exp nil)))
+      (setq calc-aborted-prefix "alg'")
+      (or no-normalize
+	  (and alg-exp (setq alg-exp (mapcar 'calc-normalize alg-exp))))
+      alg-exp))
+)
+
+(defun calcAlg-plus-minus ()
+  (interactive)
+  (if (calc-minibuffer-contains ".* \\'")
+      (insert "+/- ")
+    (insert " +/- "))
+)
+
+(defun calcAlg-mod ()
+  (interactive)
+  (if (not (calc-minibuffer-contains ".* \\'"))
+      (insert " "))
+  (if (calc-minibuffer-contains ".* mod +\\'")
+      (if calc-previous-modulo
+	  (insert (math-format-flat-expr calc-previous-modulo 0))
+	(beep))
+    (insert "mod "))
+)
+
+(defun calcAlg-previous ()
+  (interactive)
+  (if (calc-minibuffer-contains "\\`\\'")
+      (if calc-previous-alg-entry
+	  (insert calc-previous-alg-entry)
+	(beep))
+    (insert "'"))
+)
+
+(defun calcAlg-equals ()
+  (interactive)
+  (unwind-protect
+      (calcAlg-enter)
+    (if (consp alg-exp)
+	(progn (setq prefix-arg (length alg-exp))
+	       (calc-unread-command ?=))))
+)
+
+(defun calcAlg-escape ()
+  (interactive)
+  (calc-unread-command)
+  (save-excursion
+    (calc-select-buffer)
+    (use-local-map calc-mode-map))
+  (calcAlg-enter)
+)
+
+(defun calcAlg-edit ()
+  (interactive)
+  (if (or (not calc-plain-entry)
+	  (calc-minibuffer-contains
+	   "\\`\\([^\"]*\"[^\"]*\"\\)*[^\"]*\"[^\"]*\\'"))
+      (insert "`")
+    (setq alg-exp (buffer-string))
+    (and (> (length alg-exp) 0) (setq calc-previous-alg-entry alg-exp))
+    (exit-minibuffer))
+)
+(setq calc-plain-entry nil)
+
+(defun calcAlg-enter ()
+  (interactive)
+  (let* ((str (buffer-string))
+	 (exp (and (> (length str) 0)
+		   (save-excursion
+		     (set-buffer calc-buffer)
+		     (math-read-exprs str)))))
+    (if (eq (car-safe exp) 'error)
+	(progn
+	  (goto-char (point-min))
+	  (forward-char (nth 1 exp))
+	  (beep)
+	  (calc-temp-minibuffer-message
+	   (concat " [" (or (nth 2 exp) "Error") "]"))
+	  (calc-clear-unread-commands))
+      (setq alg-exp (if (calc-minibuffer-contains "\\` *\\[ *\\'")
+			'((incomplete vec))
+		      exp))
+      (and (> (length str) 0) (setq calc-previous-alg-entry str))
+      (exit-minibuffer)))
+)
+
+(defun calcAlg-blink-matching-open ()
+  (let ((oldpos (point))
+	(blinkpos nil))
+    (save-excursion
+      (condition-case ()
+	  (setq blinkpos (scan-sexps oldpos -1))
+	(error nil)))
+    (if (and blinkpos
+	     (> oldpos (1+ (point-min)))
+	     (or (and (= (char-after (1- oldpos)) ?\))
+		      (= (char-after blinkpos) ?\[))
+		 (and (= (char-after (1- oldpos)) ?\])
+		      (= (char-after blinkpos) ?\()))
+	     (save-excursion
+	       (goto-char blinkpos)
+	       (looking-at ".+\\(\\.\\.\\|\\\\dots\\|\\\\ldots\\)")))
+	(let ((saved (aref (syntax-table) (char-after blinkpos))))
+	  (unwind-protect
+	      (progn
+		(aset (syntax-table) (char-after blinkpos)
+		      (+ (logand saved 255)
+			 (lsh (char-after (1- oldpos)) 8)))
+		(blink-matching-open))
+	    (aset (syntax-table) (char-after blinkpos) saved)))
+      (blink-matching-open)))
+)
+
+
+(defun calc-alg-digit-entry ()
+  (calc-alg-entry 
+   (cond ((eq last-command-char ?e)
+	  (if (> calc-number-radix 14) (format "%d.^" calc-number-radix) "1e"))
+	 ((eq last-command-char ?#) (format "%d#" calc-number-radix))
+	 ((eq last-command-char ?_) "-")
+	 ((eq last-command-char ?@) "0@ ")
+	 (t (char-to-string last-command-char))))
+)
+
+(defun calcDigit-algebraic ()
+  (interactive)
+  (if (calc-minibuffer-contains ".*[@oh] *[^'m ]+[^'m]*\\'")
+      (calcDigit-key)
+    (setq calc-digit-value (buffer-string))
+    (exit-minibuffer))
+)
+
+(defun calcDigit-edit ()
+  (interactive)
+  (calc-unread-command)
+  (setq calc-digit-value (buffer-string))
+  (exit-minibuffer)
+)
+
+
+;;; Algebraic expression parsing.   [Public]
+
+(defun math-read-exprs (exp-str)
+  (let ((exp-pos 0)
+	(exp-old-pos 0)
+	(exp-keep-spaces nil)
+	exp-token exp-data)
+    (if calc-language-input-filter
+	(setq exp-str (funcall calc-language-input-filter exp-str)))
+    (while (setq exp-token (string-match "\\.\\.\\([^.]\\|.[^.]\\)" exp-str))
+      (setq exp-str (concat (substring exp-str 0 exp-token) "\\dots"
+			    (substring exp-str (+ exp-token 2)))))
+    (math-build-parse-table)
+    (math-read-token)
+    (let ((val (catch 'syntax (math-read-expr-list))))
+      (if (stringp val)
+	  (list 'error exp-old-pos val)
+	(if (equal exp-token 'end)
+	    val
+	  (list 'error exp-old-pos "Syntax error")))))
+)
+
+(defun math-read-expr-list ()
+  (let* ((exp-keep-spaces nil)
+	 (val (list (math-read-expr-level 0)))
+	 (last val))
+    (while (equal exp-data ",")
+      (math-read-token)
+      (let ((rest (list (math-read-expr-level 0))))
+	(setcdr last rest)
+	(setq last rest)))
+    val)
+)
+
+(setq calc-user-parse-table nil)
+(setq calc-last-main-parse-table nil)
+(setq calc-last-lang-parse-table nil)
+(setq calc-user-tokens nil)
+(setq calc-user-token-chars nil)
+
+(defun math-build-parse-table ()
+  (let ((mtab (cdr (assq nil calc-user-parse-tables)))
+	(ltab (cdr (assq calc-language calc-user-parse-tables))))
+    (or (and (eq mtab calc-last-main-parse-table)
+	     (eq ltab calc-last-lang-parse-table))
+	(let ((p (append mtab ltab))
+	      (toks nil))
+	  (setq calc-user-parse-table p)
+	  (setq calc-user-token-chars nil)
+	  (while p
+	    (math-find-user-tokens (car (car p)))
+	    (setq p (cdr p)))
+	  (setq calc-user-tokens (mapconcat 'identity
+					    (sort (mapcar 'car toks)
+						  (function (lambda (x y)
+							      (> (length x)
+								 (length y)))))
+					    "\\|")
+		calc-last-main-parse-table mtab
+		calc-last-lang-parse-table ltab))))
+)
+
+(defun math-find-user-tokens (p)   ; uses "toks"
+  (while p
+    (cond ((and (stringp (car p))
+		(or (> (length (car p)) 1) (equal (car p) "$")
+		    (equal (car p) "\""))
+		(string-match "[^a-zA-Z0-9]" (car p)))
+	   (let ((s (regexp-quote (car p))))
+	     (if (string-match "\\`[a-zA-Z0-9]" s)
+		 (setq s (concat "\\<" s)))
+	     (if (string-match "[a-zA-Z0-9]\\'" s)
+		 (setq s (concat s "\\>")))
+	     (or (assoc s toks)
+		 (progn
+		   (setq toks (cons (list s) toks))
+		   (or (memq (aref (car p) 0) calc-user-token-chars)
+		       (setq calc-user-token-chars
+			     (cons (aref (car p) 0)
+				   calc-user-token-chars)))))))
+	  ((consp (car p))
+	   (math-find-user-tokens (nth 1 (car p)))
+	   (or (eq (car (car p)) '\?)
+	       (math-find-user-tokens (nth 2 (car p))))))
+    (setq p (cdr p)))
+)
+
+(defun math-read-token ()
+  (if (>= exp-pos (length exp-str))
+      (setq exp-old-pos exp-pos
+	    exp-token 'end
+	    exp-data "\000")
+    (let ((ch (aref exp-str exp-pos)))
+      (setq exp-old-pos exp-pos)
+      (cond ((memq ch '(32 10 9))
+	     (setq exp-pos (1+ exp-pos))
+	     (if exp-keep-spaces
+		 (setq exp-token 'space
+		       exp-data " ")
+	       (math-read-token)))
+	    ((and (memq ch calc-user-token-chars)
+		  (let ((case-fold-search nil))
+		    (eq (string-match calc-user-tokens exp-str exp-pos)
+			exp-pos)))
+	     (setq exp-token 'punc
+		   exp-data (math-match-substring exp-str 0)
+		   exp-pos (match-end 0)))
+	    ((or (and (>= ch ?a) (<= ch ?z))
+		 (and (>= ch ?A) (<= ch ?Z)))
+	     (string-match (if (memq calc-language '(c fortran pascal maple))
+			       "[a-zA-Z0-9_#]*"
+			     "[a-zA-Z0-9'#]*")
+			   exp-str exp-pos)
+	     (setq exp-token 'symbol
+		   exp-pos (match-end 0)
+		   exp-data (math-restore-dashes
+			     (math-match-substring exp-str 0)))
+	     (if (eq calc-language 'eqn)
+		 (let ((code (assoc exp-data math-eqn-ignore-words)))
+		   (cond ((null code))
+			 ((null (cdr code))
+			  (math-read-token))
+			 ((consp (nth 1 code))
+			  (math-read-token)
+			  (if (assoc exp-data (cdr code))
+			      (setq exp-data (format "%s %s"
+						     (car code) exp-data))))
+			 ((eq (nth 1 code) 'punc)
+			  (setq exp-token 'punc
+				exp-data (nth 2 code)))
+			 (t
+			  (math-read-token)
+			  (math-read-token))))))
+	    ((or (and (>= ch ?0) (<= ch ?9))
+		 (and (eq ch '?\.)
+		      (eq (string-match "\\.[0-9]" exp-str exp-pos) exp-pos))
+		 (and (eq ch '?_)
+		      (eq (string-match "_\\.?[0-9]" exp-str exp-pos) exp-pos)
+		      (or (eq exp-pos 0)
+			  (and (memq calc-language '(nil flat big unform
+							 tex eqn))
+			       (eq (string-match "[^])}\"a-zA-Z0-9'$]_"
+						 exp-str (1- exp-pos))
+				   (1- exp-pos))))))
+	     (or (and (eq calc-language 'c)
+		      (string-match "0[xX][0-9a-fA-F]+" exp-str exp-pos))
+		 (string-match "_?\\([0-9]+.?0*@ *\\)?\\([0-9]+.?0*' *\\)?\\(0*\\([2-9]\\|1[0-4]\\)\\(#\\|\\^\\^\\)[0-9a-dA-D.]+[eE][-+_]?[0-9]+\\|0*\\([2-9]\\|[0-2][0-9]\\|3[0-6]\\)\\(#\\|\\^\\^\\)[0-9a-zA-Z:.]+\\|[0-9]+:[0-9:]+\\|[0-9.]+\\([eE][-+_]?[0-9]+\\)?\"?\\)?" exp-str exp-pos))
+	     (setq exp-token 'number
+		   exp-data (math-match-substring exp-str 0)
+		   exp-pos (match-end 0)))
+	    ((eq ch ?\$)
+	     (if (and (eq calc-language 'pascal)
+		      (eq (string-match
+			   "\\(\\$[0-9a-fA-F]+\\)\\($\\|[^0-9a-zA-Z]\\)"
+			   exp-str exp-pos)
+			  exp-pos))
+		 (setq exp-token 'number
+		       exp-data (math-match-substring exp-str 1)
+		       exp-pos (match-end 1))
+	       (if (eq (string-match "\\$\\([1-9][0-9]*\\)" exp-str exp-pos)
+		       exp-pos)
+		   (setq exp-data (- (string-to-int (math-match-substring
+						     exp-str 1))))
+		 (string-match "\\$+" exp-str exp-pos)
+		 (setq exp-data (- (match-end 0) (match-beginning 0))))
+	       (setq exp-token 'dollar
+		     exp-pos (match-end 0))))
+	    ((eq ch ?\#)
+	     (if (eq (string-match "#\\([1-9][0-9]*\\)" exp-str exp-pos)
+		     exp-pos)
+		 (setq exp-data (string-to-int
+				 (math-match-substring exp-str 1))
+		       exp-pos (match-end 0))
+	       (setq exp-data 1
+		     exp-pos (1+ exp-pos)))
+	     (setq exp-token 'hash))
+	    ((eq (string-match "~=\\|<=\\|>=\\|<>\\|/=\\|\\+/-\\|\\\\dots\\|\\\\ldots\\|\\*\\*\\|<<\\|>>\\|==\\|!=\\|&&&\\||||\\|!!!\\|&&\\|||\\|!!\\|:=\\|::\\|=>"
+			       exp-str exp-pos)
+		 exp-pos)
+	     (setq exp-token 'punc
+		   exp-data (math-match-substring exp-str 0)
+		   exp-pos (match-end 0)))
+	    ((and (eq ch ?\")
+		  (string-match "\\(\"\\([^\"\\]\\|\\\\.\\)*\\)\\(\"\\|\\'\\)" exp-str exp-pos))
+	     (if (eq calc-language 'eqn)
+		 (progn
+		   (setq exp-str (copy-sequence exp-str))
+		   (aset exp-str (match-beginning 1) ?\{)
+		   (if (< (match-end 1) (length exp-str))
+		       (aset exp-str (match-end 1) ?\}))
+		   (math-read-token))
+	       (setq exp-token 'string
+		     exp-data (math-match-substring exp-str 1)
+		     exp-pos (match-end 0))))
+	    ((and (= ch ?\\) (eq calc-language 'tex)
+		  (< exp-pos (1- (length exp-str))))
+	     (or (string-match "\\\\hbox *{\\([a-zA-Z0-9]+\\)}" exp-str exp-pos)
+		 (string-match "\\(\\\\\\([a-zA-Z]+\\|[^a-zA-Z]\\)\\)" exp-str exp-pos))
+	     (setq exp-token 'symbol
+		   exp-pos (match-end 0)
+		   exp-data (math-restore-dashes
+			     (math-match-substring exp-str 1)))
+	     (let ((code (assoc exp-data math-tex-ignore-words)))
+	       (cond ((null code))
+		     ((null (cdr code))
+		      (math-read-token))
+		     ((eq (nth 1 code) 'punc)
+		      (setq exp-token 'punc
+			    exp-data (nth 2 code)))
+		     ((and (eq (nth 1 code) 'mat)
+			   (string-match " *{" exp-str exp-pos))
+		      (setq exp-pos (match-end 0)
+			    exp-token 'punc
+			    exp-data "[")
+		      (let ((right (string-match "}" exp-str exp-pos)))
+			(and right
+			     (setq exp-str (copy-sequence exp-str))
+			     (aset exp-str right ?\])))))))
+	    ((and (= ch ?\.) (eq calc-language 'fortran)
+		  (eq (string-match "\\.[a-zA-Z][a-zA-Z][a-zA-Z]?\\."
+				    exp-str exp-pos) exp-pos))
+	     (setq exp-token 'punc
+		   exp-data (upcase (math-match-substring exp-str 0))
+		   exp-pos (match-end 0)))
+	    ((and (eq calc-language 'math)
+		  (eq (string-match "\\[\\[\\|->\\|:>" exp-str exp-pos)
+		      exp-pos))
+	     (setq exp-token 'punc
+		   exp-data (math-match-substring exp-str 0)
+		   exp-pos (match-end 0)))
+	    ((and (eq calc-language 'eqn)
+		  (eq (string-match "->\\|<-\\|+-\\|\\\\dots\\|~\\|\\^"
+				    exp-str exp-pos)
+		      exp-pos))
+	     (setq exp-token 'punc
+		   exp-data (math-match-substring exp-str 0)
+		   exp-pos (match-end 0))
+	     (and (eq (string-match "\\\\dots\\." exp-str exp-pos) exp-pos)
+		  (setq exp-pos (match-end 0)))
+	     (if (memq (aref exp-data 0) '(?~ ?^))
+		 (math-read-token)))
+	    ((eq (string-match "%%.*$" exp-str exp-pos) exp-pos)
+	     (setq exp-pos (match-end 0))
+	     (math-read-token))
+	    (t
+	     (if (and (eq ch ?\{) (memq calc-language '(tex eqn)))
+		 (setq ch ?\())
+	     (if (and (eq ch ?\}) (memq calc-language '(tex eqn)))
+		 (setq ch ?\)))
+	     (if (and (eq ch ?\&) (eq calc-language 'tex))
+		 (setq ch ?\,))
+	     (setq exp-token 'punc
+		   exp-data (char-to-string ch)
+		   exp-pos (1+ exp-pos))))))
+)
+
+
+(defun math-read-expr-level (exp-prec &optional exp-term)
+  (let* ((x (math-read-factor)) (first t) op op2)
+    (while (and (or (and calc-user-parse-table
+			 (setq op (calc-check-user-syntax x exp-prec))
+			 (setq x op
+			       op '("2x" ident 999999 -1)))
+		    (and (setq op (assoc exp-data math-expr-opers))
+			 (/= (nth 2 op) -1)
+			 (or (and (setq op2 (assoc
+					     exp-data
+					     (cdr (memq op math-expr-opers))))
+				  (eq (= (nth 3 op) -1)
+				      (/= (nth 3 op2) -1))
+				  (eq (= (nth 3 op2) -1)
+				      (not (math-factor-after)))
+				  (setq op op2))
+			     t))
+		    (and (or (eq (nth 2 op) -1)
+			     (memq exp-token '(symbol number dollar hash))
+			     (equal exp-data "(")
+			     (and (equal exp-data "[")
+				  (not (eq calc-language 'math))
+				  (not (and exp-keep-spaces
+					    (eq (car-safe x) 'vec)))))
+			 (or (not (setq op (assoc exp-data math-expr-opers)))
+			     (/= (nth 2 op) -1))
+			 (or (not calc-user-parse-table)
+			     (not (eq exp-token 'symbol))
+			     (let ((p calc-user-parse-table))
+			       (while (and p
+					   (or (not (integerp
+						     (car (car (car p)))))
+					       (not (equal
+						     (nth 1 (car (car p)))
+						     exp-data))))
+				 (setq p (cdr p)))
+			       (not p)))
+			 (setq op (assoc "2x" math-expr-opers))))
+		(not (and exp-term (equal exp-data exp-term)))
+		(>= (nth 2 op) exp-prec))
+      (if (not (equal (car op) "2x"))
+	  (math-read-token))
+      (and (memq (nth 1 op) '(sdev mod))
+	   (calc-extensions))
+      (setq x (cond ((consp (nth 1 op))
+		     (funcall (car (nth 1 op)) x op))
+		    ((eq (nth 3 op) -1)
+		     (if (eq (nth 1 op) 'ident)
+			 x
+		       (if (eq (nth 1 op) 'closing)
+			   (if (eq (nth 2 op) exp-prec)
+			       (progn
+				 (setq exp-prec 1000)
+				 x)
+			     (throw 'syntax "Mismatched delimiters"))
+			 (list (nth 1 op) x))))
+		    ((and (not first)
+			  (memq (nth 1 op) math-alg-inequalities)
+			  (memq (car-safe x) math-alg-inequalities))
+		     (calc-extensions)
+		     (math-composite-inequalities x op))
+		    (t (list (nth 1 op)
+			     x
+			     (math-read-expr-level (nth 3 op) exp-term))))
+	    first nil))
+    x)
+)
+
+(defun calc-check-user-syntax (&optional x prec)
+  (let ((p calc-user-parse-table)
+	(matches nil)
+	match rule)
+    (while (and p
+		(or (not (progn
+			   (setq rule (car (car p)))
+			   (if x
+			       (and (integerp (car rule))
+				    (>= (car rule) prec)
+				    (equal exp-data
+					   (car (setq rule (cdr rule)))))
+			     (equal exp-data (car rule)))))
+		    (let ((save-exp-pos exp-pos)
+			  (save-exp-old-pos exp-old-pos)
+			  (save-exp-token exp-token)
+			  (save-exp-data exp-data))
+		      (or (not (listp
+				(setq matches (calc-match-user-syntax rule))))
+			  (let ((args (progn
+					(calc-extensions)
+					calc-arg-values))
+				(conds nil)
+				temp)
+			    (if x
+				(setq matches (cons x matches)))
+			    (setq match (cdr (car p)))
+			    (while (and (eq (car-safe match)
+					    'calcFunc-condition)
+					(= (length match) 3))
+			      (setq conds (append (math-flatten-lands
+						   (nth 2 match))
+						  conds)
+				    match (nth 1 match)))
+			    (while (and conds match)
+			      (calc-extensions)
+			      (cond ((eq (car-safe (car conds))
+					 'calcFunc-let)
+				     (setq temp (car conds))
+				     (or (= (length temp) 3)
+					 (and (= (length temp) 2)
+					      (eq (car-safe (nth 1 temp))
+						  'calcFunc-assign)
+					      (= (length (nth 1 temp)) 3)
+					      (setq temp (nth 1 temp)))
+					 (setq match nil))
+				     (setq matches (cons
+						    (math-normalize
+						     (math-multi-subst
+						      (nth 2 temp)
+						      args matches))
+						    matches)
+					   args (cons (nth 1 temp)
+						      args)))
+				    ((and (eq (car-safe (car conds))
+					      'calcFunc-matches)
+					  (= (length (car conds)) 3))
+				     (setq temp (calcFunc-vmatches
+						 (math-multi-subst
+						  (nth 1 (car conds))
+						  args matches)
+						 (nth 2 (car conds))))
+				     (if (eq temp 0)
+					 (setq match nil)
+				       (while (setq temp (cdr temp))
+					 (setq matches (cons (nth 2 (car temp))
+							     matches)
+					       args (cons (nth 1 (car temp))
+							  args)))))
+				    (t
+				     (or (math-is-true (math-simplify
+							(math-multi-subst
+							 (car conds)
+							 args matches)))
+					 (setq match nil))))
+			      (setq conds (cdr conds)))
+			    (if match
+				(not (setq match (math-multi-subst
+						  match args matches)))
+			      (setq exp-old-pos save-exp-old-pos
+				    exp-token save-exp-token
+				    exp-data save-exp-data
+				    exp-pos save-exp-pos)))))))
+      (setq p (cdr p)))
+    (and p match))
+)
+
+(defun calc-match-user-syntax (p &optional term)
+  (let ((matches nil)
+	(save-exp-pos exp-pos)
+	(save-exp-old-pos exp-old-pos)
+	(save-exp-token exp-token)
+	(save-exp-data exp-data))
+    (while (and p
+		(cond ((stringp (car p))
+		       (and (equal exp-data (car p))
+			    (progn
+			      (math-read-token)
+			      t)))
+		      ((integerp (car p))
+		       (and (setq m (catch 'syntax
+				      (math-read-expr-level
+				       (car p)
+				       (if (cdr p)
+					   (if (consp (nth 1 p))
+					       (car (nth 1 (nth 1 p)))
+					     (nth 1 p))
+					 term))))
+			    (not (stringp m))
+			    (setq matches (nconc matches (list m)))))
+		      ((eq (car (car p)) '\?)
+		       (setq m (calc-match-user-syntax (nth 1 (car p))))
+		       (or (nth 2 (car p))
+			   (setq matches
+				 (nconc matches
+					(list
+					 (cons 'vec (and (listp m) m))))))
+		       (or (listp m) (not (nth 2 (car p)))
+			   (not (eq (aref (car (nth 2 (car p))) 0) ?\$))
+			   (eq exp-token 'end)))
+		      (t
+		       (setq m (calc-match-user-syntax (nth 1 (car p))
+						       (car (nth 2 (car p)))))
+		       (if (listp m)
+			   (let ((vec (cons 'vec m))
+				 opos mm)
+			     (while (and (listp
+					  (setq opos exp-pos
+						mm (calc-match-user-syntax
+						    (or (nth 2 (car p))
+							(nth 1 (car p)))
+						    (car (nth 2 (car p))))))
+					 (> exp-pos opos))
+			       (setq vec (nconc vec mm)))
+			     (setq matches (nconc matches (list vec))))
+			 (and (eq (car (car p)) '*)
+			      (setq matches (nconc matches (list '(vec)))))))))
+      (setq p (cdr p)))
+    (if p
+	(setq exp-pos save-exp-pos
+	      exp-old-pos save-exp-old-pos
+	      exp-token save-exp-token
+	      exp-data save-exp-data
+	      matches "Failed"))
+    matches)
+)
+
+(defconst math-alg-inequalities
+  '(calcFunc-lt calcFunc-gt calcFunc-leq calcFunc-geq
+		calcFunc-eq calcFunc-neq))
+
+(defun math-remove-dashes (x)
+  (if (string-match "\\`\\(.*\\)-\\(.*\\)\\'" x)
+      (math-remove-dashes
+       (concat (math-match-substring x 1) "#" (math-match-substring x 2)))
+    x)
+)
+
+(defun math-restore-dashes (x)
+  (if (string-match "\\`\\(.*\\)[#_]\\(.*\\)\\'" x)
+      (math-restore-dashes
+       (concat (math-match-substring x 1) "-" (math-match-substring x 2)))
+    x)
+)
+
+(defun math-read-if (cond op)
+  (let ((then (math-read-expr-level 0)))
+    (or (equal exp-data ":")
+	(throw 'syntax "Expected ':'"))
+    (math-read-token)
+    (list 'calcFunc-if cond then (math-read-expr-level (nth 3 op))))
+)
+
+(defun math-factor-after ()
+  (let ((exp-pos exp-pos)
+	exp-old-pos exp-token exp-data)
+    (math-read-token)
+    (or (memq exp-token '(number symbol dollar hash string))
+	(and (assoc exp-data '(("-") ("+") ("!") ("|") ("/")))
+	     (assoc (concat "u" exp-data) math-expr-opers))
+	(eq (nth 2 (assoc exp-data math-expr-opers)) -1)
+	(assoc exp-data '(("(") ("[") ("{")))))
+)
+
+(defun math-read-factor ()
+  (let (op)
+    (cond ((eq exp-token 'number)
+	   (let ((num (math-read-number exp-data)))
+	     (if (not num)
+		 (progn
+		   (setq exp-old-pos exp-pos)
+		   (throw 'syntax "Bad format")))
+	     (math-read-token)
+	     (if (and math-read-expr-quotes
+		      (consp num))
+		 (list 'quote num)
+	       num)))
+	  ((and calc-user-parse-table
+		(setq op (calc-check-user-syntax)))
+	   op)
+	  ((or (equal exp-data "-")
+	       (equal exp-data "+")
+	       (equal exp-data "!")
+	       (equal exp-data "|")
+	       (equal exp-data "/"))
+	   (setq exp-data (concat "u" exp-data))
+	   (math-read-factor))
+	  ((and (setq op (assoc exp-data math-expr-opers))
+		(eq (nth 2 op) -1))
+	   (if (consp (nth 1 op))
+	       (funcall (car (nth 1 op)) op)
+	     (math-read-token)
+	     (let ((val (math-read-expr-level (nth 3 op))))
+	       (cond ((eq (nth 1 op) 'ident)
+		      val)
+		     ((and (Math-numberp val)
+			   (equal (car op) "u-"))
+		      (math-neg val))
+		     (t (list (nth 1 op) val))))))
+	  ((eq exp-token 'symbol)
+	   (let ((sym (intern exp-data)))
+	     (math-read-token)
+	     (if (equal exp-data calc-function-open)
+		 (let ((f (assq sym math-expr-function-mapping)))
+		   (math-read-token)
+		   (if (consp (cdr f))
+		       (funcall (car (cdr f)) f sym)
+		     (let ((args (if (or (equal exp-data calc-function-close)
+					 (eq exp-token 'end))
+				     nil
+				   (math-read-expr-list))))
+		       (if (not (or (equal exp-data calc-function-close)
+				    (eq exp-token 'end)))
+			   (throw 'syntax "Expected `)'"))
+		       (math-read-token)
+		       (if (and (eq calc-language 'fortran) args
+				(calc-extensions)
+				(let ((calc-matrix-mode 'scalar))
+				  (math-known-matrixp
+				   (list 'var sym
+					 (intern
+					  (concat "var-"
+						  (symbol-name sym)))))))
+			   (math-parse-fortran-subscr sym args)
+			 (if f
+			     (setq sym (cdr f))
+			   (and (= (aref (symbol-name sym) 0) ?\\)
+				(< (prefix-numeric-value calc-language-option)
+				   0)
+				(setq sym (intern (substring (symbol-name sym)
+							     1))))
+			   (or (string-match "-" (symbol-name sym))
+			       (setq sym (intern
+					  (concat "calcFunc-"
+						  (symbol-name sym))))))
+			 (cons sym args)))))
+	       (if math-read-expr-quotes
+		   sym
+		 (let ((val (list 'var
+				  (intern (math-remove-dashes
+					   (symbol-name sym)))
+				  (if (string-match "-" (symbol-name sym))
+				      sym
+				    (intern (concat "var-"
+						    (symbol-name sym)))))))
+		   (let ((v (assq (nth 1 val) math-expr-variable-mapping)))
+		     (and v (setq val (if (consp (cdr v))
+					  (funcall (car (cdr v)) v val)
+					(list 'var
+					      (intern
+					       (substring (symbol-name (cdr v))
+							  4))
+					      (cdr v))))))
+		   (while (and (memq calc-language '(c pascal maple))
+			       (equal exp-data "["))
+		     (math-read-token)
+		     (setq val (append (list 'calcFunc-subscr val)
+				       (math-read-expr-list)))
+		     (if (equal exp-data "]")
+			 (math-read-token)
+		       (throw 'syntax "Expected ']'")))
+		   val)))))
+	  ((eq exp-token 'dollar)
+	   (let ((abs (if (> exp-data 0) exp-data (- exp-data))))
+	     (if (>= (length calc-dollar-values) abs)
+		 (let ((num exp-data))
+		   (math-read-token)
+		   (setq calc-dollar-used (max calc-dollar-used num))
+		   (math-check-complete (nth (1- abs) calc-dollar-values)))
+	       (throw 'syntax (if calc-dollar-values
+				  "Too many $'s"
+				"$'s not allowed in this context")))))
+	  ((eq exp-token 'hash)
+	   (or calc-hashes-used
+	       (throw 'syntax "#'s not allowed in this context"))
+	   (calc-extensions)
+	   (if (<= exp-data (length calc-arg-values))
+	       (let ((num exp-data))
+		 (math-read-token)
+		 (setq calc-hashes-used (max calc-hashes-used num))
+		 (nth (1- num) calc-arg-values))
+	     (throw 'syntax "Too many # arguments")))
+	  ((equal exp-data "(")
+	   (let* ((exp (let ((exp-keep-spaces nil))
+			 (math-read-token)
+			 (if (or (equal exp-data "\\dots")
+				 (equal exp-data "\\ldots"))
+			     '(neg (var inf var-inf))
+			   (math-read-expr-level 0)))))
+	     (let ((exp-keep-spaces nil))
+	       (cond
+		((equal exp-data ",")
+		 (progn
+		   (math-read-token)
+		   (let ((exp2 (math-read-expr-level 0)))
+		     (setq exp
+			   (if (and exp2 (Math-realp exp) (Math-realp exp2))
+			       (math-normalize (list 'cplx exp exp2))
+			     (list '+ exp (list '* exp2 '(var i var-i))))))))
+		((equal exp-data ";")
+		 (progn
+		   (math-read-token)
+		   (let ((exp2 (math-read-expr-level 0)))
+		     (setq exp (if (and exp2 (Math-realp exp)
+					(Math-anglep exp2))
+				   (math-normalize (list 'polar exp exp2))
+				 (calc-extensions)
+				 (list '* exp
+				       (list 'calcFunc-exp
+					     (list '*
+						   (math-to-radians-2 exp2)
+						   '(var i var-i)))))))))
+		((or (equal exp-data "\\dots")
+		     (equal exp-data "\\ldots"))
+		 (progn
+		   (math-read-token)
+		   (let ((exp2 (if (or (equal exp-data ")")
+				       (equal exp-data "]")
+				       (eq exp-token 'end))
+				   '(var inf var-inf)
+				 (math-read-expr-level 0))))
+		     (setq exp
+			   (list 'intv
+				 (if (equal exp-data ")") 0 1)
+				 exp
+				 exp2)))))))
+	     (if (not (or (equal exp-data ")")
+			  (and (equal exp-data "]") (eq (car-safe exp) 'intv))
+			  (eq exp-token 'end)))
+		 (throw 'syntax "Expected `)'"))
+	     (math-read-token)
+	     exp))
+	  ((eq exp-token 'string)
+	   (calc-extensions)
+	   (math-read-string))
+	  ((equal exp-data "[")
+	   (calc-extensions)
+	   (math-read-brackets t "]"))
+	  ((equal exp-data "{")
+	   (calc-extensions)
+	   (math-read-brackets nil "}"))
+	  ((equal exp-data "<")
+	   (calc-extensions)
+	   (math-read-angle-brackets))
+	  (t (throw 'syntax "Expected a number"))))
+)
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/calc-alg.el	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,1699 @@
+;; Calculator for GNU Emacs, part II [calc-alg.el]
+;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+;; Written by Dave Gillespie, daveg@synaptics.com.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY.  No author or distributor
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing.  Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License.   A copy of this license is
+;; supposed to have been given to you along with GNU Emacs so you
+;; can know your rights and responsibilities.  It should be in a
+;; file named COPYING.  Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+
+
+
+;; This file is autoloaded from calc-ext.el.
+(require 'calc-ext)
+
+(require 'calc-macs)
+
+(defun calc-Need-calc-alg () nil)
+
+
+;;; Algebra commands.
+
+(defun calc-alg-evaluate (arg)
+  (interactive "p")
+  (calc-slow-wrapper
+   (calc-with-default-simplification
+    (let ((math-simplify-only nil))
+      (calc-modify-simplify-mode arg)
+      (calc-enter-result 1 "dsmp" (calc-top 1)))))
+)
+
+(defun calc-modify-simplify-mode (arg)
+  (if (= (math-abs arg) 2)
+      (setq calc-simplify-mode 'alg)
+    (if (>= (math-abs arg) 3)
+	(setq calc-simplify-mode 'ext)))
+  (if (< arg 0)
+      (setq calc-simplify-mode (list calc-simplify-mode)))
+)
+
+(defun calc-simplify ()
+  (interactive)
+  (calc-slow-wrapper
+   (calc-with-default-simplification
+    (calc-enter-result 1 "simp" (math-simplify (calc-top-n 1)))))
+)
+
+(defun calc-simplify-extended ()
+  (interactive)
+  (calc-slow-wrapper
+   (calc-with-default-simplification
+    (calc-enter-result 1 "esmp" (math-simplify-extended (calc-top-n 1)))))
+)
+
+(defun calc-expand-formula (arg)
+  (interactive "p")
+  (calc-slow-wrapper
+   (calc-with-default-simplification
+    (let ((math-simplify-only nil))
+      (calc-modify-simplify-mode arg)
+      (calc-enter-result 1 "expf" 
+			 (if (> arg 0)
+			     (let ((math-expand-formulas t))
+			       (calc-top-n 1))
+			   (let ((top (calc-top-n 1)))
+			     (or (math-expand-formula top)
+				 top)))))))
+)
+
+(defun calc-factor (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-unary-op "fctr" (if (calc-is-hyperbolic)
+			     'calcFunc-factors 'calcFunc-factor)
+		  arg))
+)
+
+(defun calc-expand (n)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-enter-result 1 "expa"
+		      (append (list 'calcFunc-expand
+				    (calc-top-n 1))
+			      (and n (list (prefix-numeric-value n))))))
+)
+
+(defun calc-collect (&optional var)
+  (interactive "sCollect terms involving: ")
+  (calc-slow-wrapper
+   (if (or (equal var "") (equal var "$") (null var))
+       (calc-enter-result 2 "clct" (cons 'calcFunc-collect
+					 (calc-top-list-n 2)))
+     (let ((var (math-read-expr var)))
+       (if (eq (car-safe var) 'error)
+	   (error "Bad format in expression: %s" (nth 1 var)))
+       (calc-enter-result 1 "clct" (list 'calcFunc-collect
+					 (calc-top-n 1)
+					 var)))))
+)
+
+(defun calc-apart (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-unary-op "aprt" 'calcFunc-apart arg))
+)
+
+(defun calc-normalize-rat (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-unary-op "nrat" 'calcFunc-nrat arg))
+)
+
+(defun calc-poly-gcd (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-binary-op "pgcd" 'calcFunc-pgcd arg))
+)
+
+(defun calc-poly-div (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (setq calc-poly-div-remainder nil)
+   (calc-binary-op "pdiv" 'calcFunc-pdiv arg)
+   (if (and calc-poly-div-remainder (null arg))
+       (progn
+	 (calc-clear-command-flag 'clear-message)
+	 (calc-record calc-poly-div-remainder "prem")
+	 (if (not (Math-zerop calc-poly-div-remainder))
+	     (message "(Remainder was %s)"
+		      (math-format-flat-expr calc-poly-div-remainder 0))
+	   (message "(No remainder)")))))
+)
+
+(defun calc-poly-rem (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-binary-op "prem" 'calcFunc-prem arg))
+)
+
+(defun calc-poly-div-rem (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (if (calc-is-hyperbolic)
+       (calc-binary-op "pdvr" 'calcFunc-pdivide arg)
+     (calc-binary-op "pdvr" 'calcFunc-pdivrem arg)))
+)
+
+(defun calc-substitute (&optional oldname newname)
+  (interactive "sSubstitute old: ")
+  (calc-slow-wrapper
+   (let (old new (num 1) expr)
+     (if (or (equal oldname "") (equal oldname "$") (null oldname))
+	 (setq new (calc-top-n 1)
+	       old (calc-top-n 2)
+	       expr (calc-top-n 3)
+	       num 3)
+       (or newname
+	   (progn (calc-unread-command ?\C-a)
+		  (setq newname (read-string (concat "Substitute old: "
+						     oldname
+						     ", new: ")
+					     oldname))))
+       (if (or (equal newname "") (equal newname "$") (null newname))
+	   (setq new (calc-top-n 1)
+		 expr (calc-top-n 2)
+		 num 2)
+	 (setq new (if (stringp newname) (math-read-expr newname) newname))
+	 (if (eq (car-safe new) 'error)
+	     (error "Bad format in expression: %s" (nth 1 new)))
+	 (setq expr (calc-top-n 1)))
+       (setq old (if (stringp oldname) (math-read-expr oldname) oldname))
+       (if (eq (car-safe old) 'error)
+	   (error "Bad format in expression: %s" (nth 1 old)))
+       (or (math-expr-contains expr old)
+	   (error "No occurrences found.")))
+     (calc-enter-result num "sbst" (math-expr-subst expr old new))))
+)
+
+
+(defun calc-has-rules (name)
+  (setq name (calc-var-value name))
+  (and (consp name)
+       (memq (car name) '(vec calcFunc-assign calcFunc-condition))
+       name)
+)
+
+(defun math-recompile-eval-rules ()
+  (setq math-eval-rules-cache (and (calc-has-rules 'var-EvalRules)
+				   (math-compile-rewrites
+				    '(var EvalRules var-EvalRules)))
+	math-eval-rules-cache-other (assq nil math-eval-rules-cache)
+	math-eval-rules-cache-tag (calc-var-value 'var-EvalRules))
+)
+
+
+;;; Try to expand a formula according to its definition.
+(defun math-expand-formula (expr)
+  (and (consp expr)
+       (symbolp (car expr))
+       (or (get (car expr) 'calc-user-defn)
+	   (get (car expr) 'math-expandable))
+       (let ((res (let ((math-expand-formulas t))
+		    (apply (car expr) (cdr expr)))))
+	 (and (not (eq (car-safe res) (car expr)))
+	      res)))
+)
+
+
+
+
+;;; True if A comes before B in a canonical ordering of expressions.  [P X X]
+(defun math-beforep (a b)   ; [Public]
+  (cond ((and (Math-realp a) (Math-realp b))
+	 (let ((comp (math-compare a b)))
+	   (or (eq comp -1)
+	       (and (eq comp 0)
+		    (not (equal a b))
+		    (> (length (memq (car-safe a)
+				     '(bigneg nil bigpos frac float)))
+		       (length (memq (car-safe b)
+				     '(bigneg nil bigpos frac float))))))))
+	((equal b '(neg (var inf var-inf))) nil)
+	((equal a '(neg (var inf var-inf))) t)
+	((equal a '(var inf var-inf)) nil)
+	((equal b '(var inf var-inf)) t)
+	((Math-realp a)
+	 (if (and (eq (car-safe b) 'intv) (math-intv-constp b))
+	     (if (or (math-beforep a (nth 2 b)) (Math-equal a (nth 2 b)))
+		 t
+	       nil)
+	   t))
+	((Math-realp b)
+	 (if (and (eq (car-safe a) 'intv) (math-intv-constp a))
+	     (if (math-beforep (nth 2 a) b)
+		 t
+	       nil)
+	   nil))
+	((and (eq (car a) 'intv) (eq (car b) 'intv)
+	      (math-intv-constp a) (math-intv-constp b))
+	 (let ((comp (math-compare (nth 2 a) (nth 2 b))))
+	   (cond ((eq comp -1) t)
+		 ((eq comp 1) nil)
+		 ((and (memq (nth 1 a) '(2 3)) (memq (nth 1 b) '(0 1))) t)
+		 ((and (memq (nth 1 a) '(0 1)) (memq (nth 1 b) '(2 3))) nil)
+		 ((eq (setq comp (math-compare (nth 3 a) (nth 3 b))) -1) t)
+		 ((eq comp 1) nil)
+		 ((and (memq (nth 1 a) '(0 2)) (memq (nth 1 b) '(1 3))) t)
+		 (t nil))))
+	((not (eq (not (Math-objectp a)) (not (Math-objectp b))))
+	 (Math-objectp a))
+	((eq (car a) 'var)
+	 (if (eq (car b) 'var)
+	     (string-lessp (symbol-name (nth 1 a)) (symbol-name (nth 1 b)))
+	   (not (Math-numberp b))))
+	((eq (car b) 'var) (Math-numberp a))
+	((eq (car a) (car b))
+	 (while (and (setq a (cdr a) b (cdr b)) a
+		     (equal (car a) (car b))))
+	 (and b
+	      (or (null a)
+		  (math-beforep (car a) (car b)))))
+	(t (string-lessp (symbol-name (car a)) (symbol-name (car b)))))
+)
+
+
+(defun math-simplify-extended (a)
+  (let ((math-living-dangerously t))
+    (math-simplify a))
+)
+(fset 'calcFunc-esimplify (symbol-function 'math-simplify-extended))
+
+(defun math-simplify (top-expr)
+  (let ((math-simplifying t)
+	(top-only (consp calc-simplify-mode))
+	(simp-rules (append (and (calc-has-rules 'var-AlgSimpRules)
+				 '((var AlgSimpRules var-AlgSimpRules)))
+			    (and math-living-dangerously
+				 (calc-has-rules 'var-ExtSimpRules)
+				 '((var ExtSimpRules var-ExtSimpRules)))
+			    (and math-simplifying-units
+				 (calc-has-rules 'var-UnitSimpRules)
+				 '((var UnitSimpRules var-UnitSimpRules)))
+			    (and math-integrating
+				 (calc-has-rules 'var-IntegSimpRules)
+				 '((var IntegSimpRules var-IntegSimpRules)))))
+	res)
+    (if top-only
+	(let ((r simp-rules))
+	  (setq res (math-simplify-step (math-normalize top-expr))
+		calc-simplify-mode '(nil)
+		top-expr (math-normalize res))
+	  (while r
+	    (setq top-expr (math-rewrite top-expr (car r)
+					 '(neg (var inf var-inf)))
+		  r (cdr r))))
+      (calc-with-default-simplification
+       (while (let ((r simp-rules))
+		(setq res (math-normalize top-expr))
+		(while r
+		  (setq res (math-rewrite res (car r))
+			r (cdr r)))
+		(not (equal top-expr (setq res (math-simplify-step res)))))
+	 (setq top-expr res)))))
+  top-expr
+)
+(fset 'calcFunc-simplify (symbol-function 'math-simplify))
+
+;;; The following has a "bug" in that if any recursive simplifications
+;;; occur only the first handler will be tried; this doesn't really
+;;; matter, since math-simplify-step is iterated to a fixed point anyway.
+(defun math-simplify-step (a)
+  (if (Math-primp a)
+      a
+    (let ((aa (if (or top-only
+		      (memq (car a) '(calcFunc-quote calcFunc-condition
+						     calcFunc-evalto)))
+		  a
+		(cons (car a) (mapcar 'math-simplify-step (cdr a))))))
+      (and (symbolp (car aa))
+	   (let ((handler (get (car aa) 'math-simplify)))
+	     (and handler
+		  (while (and handler
+			      (equal (setq aa (or (funcall (car handler) aa)
+						  aa))
+				     a))
+		    (setq handler (cdr handler))))))
+      aa))
+)
+
+
+(defun math-need-std-simps ()
+  ;; Placeholder, to synchronize autoloading.
+)
+
+(math-defsimplify (+ -)
+  (math-simplify-plus))
+
+(defun math-simplify-plus ()
+  (cond ((and (memq (car-safe (nth 1 expr)) '(+ -))
+	      (Math-numberp (nth 2 (nth 1 expr)))
+	      (not (Math-numberp (nth 2 expr))))
+	 (let ((x (nth 2 expr))
+	       (op (car expr)))
+	   (setcar (cdr (cdr expr)) (nth 2 (nth 1 expr)))
+	   (setcar expr (car (nth 1 expr)))
+	   (setcar (cdr (cdr (nth 1 expr))) x)
+	   (setcar (nth 1 expr) op)))
+	((and (eq (car expr) '+)
+	      (Math-numberp (nth 1 expr))
+	      (not (Math-numberp (nth 2 expr))))
+	 (let ((x (nth 2 expr)))
+	   (setcar (cdr (cdr expr)) (nth 1 expr))
+	   (setcar (cdr expr) x))))
+  (let ((aa expr)
+	aaa temp)
+    (while (memq (car-safe (setq aaa (nth 1 aa))) '(+ -))
+      (if (setq temp (math-combine-sum (nth 2 aaa) (nth 2 expr)
+				       (eq (car aaa) '-) (eq (car expr) '-) t))
+	  (progn
+	    (setcar (cdr (cdr expr)) temp)
+	    (setcar expr '+)
+	    (setcar (cdr (cdr aaa)) 0)))
+      (setq aa (nth 1 aa)))
+    (if (setq temp (math-combine-sum aaa (nth 2 expr)
+				     nil (eq (car expr) '-) t))
+	(progn
+	  (setcar (cdr (cdr expr)) temp)
+	  (setcar expr '+)
+	  (setcar (cdr aa) 0)))
+    expr)
+)
+
+(math-defsimplify *
+  (math-simplify-times))
+
+(defun math-simplify-times ()
+  (if (eq (car-safe (nth 2 expr)) '*)
+      (and (math-beforep (nth 1 (nth 2 expr)) (nth 1 expr))
+	   (or (math-known-scalarp (nth 1 expr) t)
+	       (math-known-scalarp (nth 1 (nth 2 expr)) t))
+	   (let ((x (nth 1 expr)))
+	     (setcar (cdr expr) (nth 1 (nth 2 expr)))
+	     (setcar (cdr (nth 2 expr)) x)))
+    (and (math-beforep (nth 2 expr) (nth 1 expr))
+	 (or (math-known-scalarp (nth 1 expr) t)
+	     (math-known-scalarp (nth 2 expr) t))
+	 (let ((x (nth 2 expr)))
+	   (setcar (cdr (cdr expr)) (nth 1 expr))
+	   (setcar (cdr expr) x))))
+  (let ((aa expr)
+	aaa temp
+	(safe t) (scalar (math-known-scalarp (nth 1 expr))))
+    (if (and (Math-ratp (nth 1 expr))
+	     (setq temp (math-common-constant-factor (nth 2 expr))))
+	(progn
+	  (setcar (cdr (cdr expr))
+		  (math-cancel-common-factor (nth 2 expr) temp))
+	  (setcar (cdr expr) (math-mul (nth 1 expr) temp))))
+    (while (and (eq (car-safe (setq aaa (nth 2 aa))) '*)
+		safe)
+      (if (setq temp (math-combine-prod (nth 1 expr) (nth 1 aaa) nil nil t))
+	  (progn
+	    (setcar (cdr expr) temp)
+	    (setcar (cdr aaa) 1)))
+      (setq safe (or scalar (math-known-scalarp (nth 1 aaa) t))
+	    aa (nth 2 aa)))
+    (if (and (setq temp (math-combine-prod aaa (nth 1 expr) nil nil t))
+	     safe)
+	(progn
+	  (setcar (cdr expr) temp)
+	  (setcar (cdr (cdr aa)) 1)))
+    (if (and (eq (car-safe (nth 1 expr)) 'frac)
+	     (memq (nth 1 (nth 1 expr)) '(1 -1)))
+	(math-div (math-mul (nth 2 expr) (nth 1 (nth 1 expr)))
+		  (nth 2 (nth 1 expr)))
+      expr))
+)
+
+(math-defsimplify /
+  (math-simplify-divide))
+
+(defun math-simplify-divide ()
+  (let ((np (cdr expr))
+	(nover nil)
+	(nn (and (or (eq (car expr) '/) (not (Math-realp (nth 2 expr))))
+		 (math-common-constant-factor (nth 2 expr))))
+	n op)
+    (if nn
+	(progn
+	  (setq n (and (or (eq (car expr) '/) (not (Math-realp (nth 1 expr))))
+		       (math-common-constant-factor (nth 1 expr))))
+	  (if (and (eq (car-safe nn) 'frac) (eq (nth 1 nn) 1) (not n))
+	      (progn
+		(setcar (cdr expr) (math-mul (nth 2 nn) (nth 1 expr)))
+		(setcar (cdr (cdr expr))
+			(math-cancel-common-factor (nth 2 expr) nn))
+		(if (and (math-negp nn)
+			 (setq op (assq (car expr) calc-tweak-eqn-table)))
+		    (setcar expr (nth 1 op))))
+	    (if (and n (not (eq (setq n (math-frac-gcd n nn)) 1)))
+		(progn
+		  (setcar (cdr expr)
+			  (math-cancel-common-factor (nth 1 expr) n))
+		  (setcar (cdr (cdr expr))
+			  (math-cancel-common-factor (nth 2 expr) n))
+		  (if (and (math-negp n)
+			   (setq op (assq (car expr) calc-tweak-eqn-table)))
+		      (setcar expr (nth 1 op))))))))
+    (if (and (eq (car-safe (car np)) '/)
+	     (math-known-scalarp (nth 2 expr) t))
+	(progn
+	  (setq np (cdr (nth 1 expr)))
+	  (while (eq (car-safe (setq n (car np))) '*)
+	    (and (math-known-scalarp (nth 2 n) t)
+		 (math-simplify-divisor (cdr n) (cdr (cdr expr)) nil t))
+	    (setq np (cdr (cdr n))))
+	  (math-simplify-divisor np (cdr (cdr expr)) nil t)
+	  (setq nover t
+		np (cdr (cdr (nth 1 expr))))))
+    (while (eq (car-safe (setq n (car np))) '*)
+      (and (math-known-scalarp (nth 2 n) t)
+	   (math-simplify-divisor (cdr n) (cdr (cdr expr)) nover t))
+      (setq np (cdr (cdr n))))
+    (math-simplify-divisor np (cdr (cdr expr)) nover t)
+    expr)
+)
+
+(defun math-simplify-divisor (np dp nover dover)
+  (cond ((eq (car-safe (car dp)) '/)
+	 (math-simplify-divisor np (cdr (car dp)) nover dover)
+	 (and (math-known-scalarp (nth 1 (car dp)) t)
+	      (math-simplify-divisor np (cdr (cdr (car dp)))
+				     nover (not dover))))
+	((or (or (eq (car expr) '/)
+		 (let ((signs (math-possible-signs (car np))))
+		   (or (memq signs '(1 4))
+		       (and (memq (car expr) '(calcFunc-eq calcFunc-neq))
+			    (eq signs 5))
+		       math-living-dangerously)))
+	     (math-numberp (car np)))
+	 (let ((n (car np))
+	       d dd temp op
+	       (safe t) (scalar (math-known-scalarp n)))
+	   (while (and (eq (car-safe (setq d (car dp))) '*)
+		       safe)
+	     (math-simplify-one-divisor np (cdr d))
+	     (setq safe (or scalar (math-known-scalarp (nth 1 d) t))
+		   dp (cdr (cdr d))))
+	   (if safe
+	       (math-simplify-one-divisor np dp)))))
+)
+
+(defun math-simplify-one-divisor (np dp)
+  (if (setq temp (math-combine-prod (car np) (car dp) nover dover t))
+      (progn
+	(and (not (memq (car expr) '(/ calcFunc-eq calcFunc-neq)))
+	     (math-known-negp (car dp))
+	     (setq op (assq (car expr) calc-tweak-eqn-table))
+	     (setcar expr (nth 1 op)))
+	(setcar np (if nover (math-div 1 temp) temp))
+	(setcar dp 1))
+    (and dover (not nover) (eq (car expr) '/)
+	 (eq (car-safe (car dp)) 'calcFunc-sqrt)
+	 (Math-integerp (nth 1 (car dp)))
+	 (progn
+	   (setcar np (math-mul (car np)
+				(list 'calcFunc-sqrt (nth 1 (car dp)))))
+	   (setcar dp (nth 1 (car dp))))))
+)
+
+(defun math-common-constant-factor (expr)
+  (if (Math-realp expr)
+      (if (Math-ratp expr)
+	  (and (not (memq expr '(0 1 -1)))
+	       (math-abs expr))
+	(if (math-ratp (setq expr (math-to-simple-fraction expr)))
+	    (math-common-constant-factor expr)))
+    (if (memq (car expr) '(+ - cplx sdev))
+	(let ((f1 (math-common-constant-factor (nth 1 expr)))
+	      (f2 (math-common-constant-factor (nth 2 expr))))
+	  (and f1 f2
+	       (not (eq (setq f1 (math-frac-gcd f1 f2)) 1))
+	       f1))
+      (if (memq (car expr) '(* polar))
+	  (math-common-constant-factor (nth 1 expr))
+	(if (eq (car expr) '/)
+	    (or (math-common-constant-factor (nth 1 expr))
+		(and (Math-integerp (nth 2 expr))
+		     (list 'frac 1 (math-abs (nth 2 expr)))))))))
+)
+
+(defun math-cancel-common-factor (expr val)
+  (if (memq (car-safe expr) '(+ - cplx sdev))
+      (progn
+	(setcar (cdr expr) (math-cancel-common-factor (nth 1 expr) val))
+	(setcar (cdr (cdr expr)) (math-cancel-common-factor (nth 2 expr) val))
+	expr)
+    (if (eq (car-safe expr) '*)
+	(math-mul (math-cancel-common-factor (nth 1 expr) val) (nth 2 expr))
+      (math-div expr val)))
+)
+
+(defun math-frac-gcd (a b)
+  (if (Math-zerop a)
+      b
+    (if (Math-zerop b)
+	a
+      (if (and (Math-integerp a)
+	       (Math-integerp b))
+	  (math-gcd a b)
+	(and (Math-integerp a) (setq a (list 'frac a 1)))
+	(and (Math-integerp b) (setq b (list 'frac b 1)))
+	(math-make-frac (math-gcd (nth 1 a) (nth 1 b))
+			(math-gcd (nth 2 a) (nth 2 b))))))
+)
+
+(math-defsimplify %
+  (math-simplify-mod))
+
+(defun math-simplify-mod ()
+  (and (Math-realp (nth 2 expr))
+       (Math-posp (nth 2 expr))
+       (let ((lin (math-is-linear (nth 1 expr)))
+	     t1 t2 t3)
+	 (or (and lin
+		  (or (math-negp (car lin))
+		      (not (Math-lessp (car lin) (nth 2 expr))))
+		  (list '%
+			(list '+
+			      (math-mul (nth 1 lin) (nth 2 lin))
+			      (math-mod (car lin) (nth 2 expr)))
+			(nth 2 expr)))
+	     (and lin
+		  (not (math-equal-int (nth 1 lin) 1))
+		  (math-num-integerp (nth 1 lin))
+		  (math-num-integerp (nth 2 expr))
+		  (setq t1 (calcFunc-gcd (nth 1 lin) (nth 2 expr)))
+		  (not (math-equal-int t1 1))
+		  (list '*
+			t1
+			(list '%
+			      (list '+
+				    (math-mul (math-div (nth 1 lin) t1)
+					      (nth 2 lin))
+				    (let ((calc-prefer-frac t))
+				      (math-div (car lin) t1)))
+			      (math-div (nth 2 expr) t1))))
+	     (and (math-equal-int (nth 2 expr) 1)
+		  (math-known-integerp (if lin
+					   (math-mul (nth 1 lin) (nth 2 lin))
+					 (nth 1 expr)))
+		  (if lin (math-mod (car lin) 1) 0)))))
+)
+
+(math-defsimplify (calcFunc-eq calcFunc-neq calcFunc-lt
+			       calcFunc-gt calcFunc-leq calcFunc-geq)
+  (if (= (length expr) 3)
+      (math-simplify-ineq)))
+
+(defun math-simplify-ineq ()
+  (let ((np (cdr expr))
+	n)
+    (while (memq (car-safe (setq n (car np))) '(+ -))
+      (math-simplify-add-term (cdr (cdr n)) (cdr (cdr expr))
+			      (eq (car n) '-) nil)
+      (setq np (cdr n)))
+    (math-simplify-add-term np (cdr (cdr expr)) nil (eq np (cdr expr)))
+    (math-simplify-divide)
+    (let ((signs (math-possible-signs (cons '- (cdr expr)))))
+      (or (cond ((eq (car expr) 'calcFunc-eq)
+		 (or (and (eq signs 2) 1)
+		     (and (memq signs '(1 4 5)) 0)))
+		((eq (car expr) 'calcFunc-neq)
+		 (or (and (eq signs 2) 0)
+		     (and (memq signs '(1 4 5)) 1)))
+		((eq (car expr) 'calcFunc-lt)
+		 (or (and (eq signs 1) 1)
+		     (and (memq signs '(2 4 6)) 0)))
+		((eq (car expr) 'calcFunc-gt)
+		 (or (and (eq signs 4) 1)
+		     (and (memq signs '(1 2 3)) 0)))
+		((eq (car expr) 'calcFunc-leq)
+		 (or (and (eq signs 4) 0)
+		     (and (memq signs '(1 2 3)) 1)))
+		((eq (car expr) 'calcFunc-geq)
+		 (or (and (eq signs 1) 0)
+		     (and (memq signs '(2 4 6)) 1))))
+	  expr)))
+)
+
+(defun math-simplify-add-term (np dp minus lplain)
+  (or (math-vectorp (car np))
+      (let ((rplain t)
+	    n d dd temp)
+	(while (memq (car-safe (setq n (car np) d (car dp))) '(+ -))
+	  (setq rplain nil)
+	  (if (setq temp (math-combine-sum n (nth 2 d)
+					   minus (eq (car d) '+) t))
+	      (if (or lplain (eq (math-looks-negp temp) minus))
+		  (progn
+		    (setcar np (setq n (if minus (math-neg temp) temp)))
+		    (setcar (cdr (cdr d)) 0))
+		(progn
+		  (setcar np 0)
+		  (setcar (cdr (cdr d)) (setq n (if (eq (car d) '+)
+						    (math-neg temp)
+						  temp))))))
+	  (setq dp (cdr d)))
+	(if (setq temp (math-combine-sum n d minus t t))
+	    (if (or lplain
+		    (and (not rplain)
+			 (eq (math-looks-negp temp) minus)))
+		(progn
+		  (setcar np (setq n (if minus (math-neg temp) temp)))
+		  (setcar dp 0))
+	      (progn
+		(setcar np 0)
+		(setcar dp (setq n (math-neg temp))))))))
+)
+
+(math-defsimplify calcFunc-sin
+  (or (and (eq (car-safe (nth 1 expr)) 'calcFunc-arcsin)
+	   (nth 1 (nth 1 expr)))
+      (and (math-looks-negp (nth 1 expr))
+	   (math-neg (list 'calcFunc-sin (math-neg (nth 1 expr)))))
+      (and (eq calc-angle-mode 'rad)
+	   (let ((n (math-linear-in (nth 1 expr) '(var pi var-pi))))
+	     (and n
+		  (math-known-sin (car n) (nth 1 n) 120 0))))
+      (and (eq calc-angle-mode 'deg)
+	   (let ((n (math-integer-plus (nth 1 expr))))
+	     (and n
+		  (math-known-sin (car n) (nth 1 n) '(frac 2 3) 0))))
+      (and (eq (car-safe (nth 1 expr)) 'calcFunc-arccos)
+	   (list 'calcFunc-sqrt (math-sub 1 (math-sqr (nth 1 (nth 1 expr))))))
+      (and (eq (car-safe (nth 1 expr)) 'calcFunc-arctan)
+	   (math-div (nth 1 (nth 1 expr))
+		     (list 'calcFunc-sqrt
+			   (math-add 1 (math-sqr (nth 1 (nth 1 expr)))))))
+      (let ((m (math-should-expand-trig (nth 1 expr))))
+	(and m (integerp (car m))
+	     (let ((n (car m)) (a (nth 1 m)))
+	       (list '+
+		     (list '* (list 'calcFunc-sin (list '* (1- n) a))
+			   (list 'calcFunc-cos a))
+		     (list '* (list 'calcFunc-cos (list '* (1- n) a))
+			   (list 'calcFunc-sin a)))))))
+)
+
+(math-defsimplify calcFunc-cos
+  (or (and (eq (car-safe (nth 1 expr)) 'calcFunc-arccos)
+	   (nth 1 (nth 1 expr)))
+      (and (math-looks-negp (nth 1 expr))
+	   (list 'calcFunc-cos (math-neg (nth 1 expr))))
+      (and (eq calc-angle-mode 'rad)
+	   (let ((n (math-linear-in (nth 1 expr) '(var pi var-pi))))
+	     (and n
+		  (math-known-sin (car n) (nth 1 n) 120 300))))
+      (and (eq calc-angle-mode 'deg)
+	   (let ((n (math-integer-plus (nth 1 expr))))
+	     (and n
+		  (math-known-sin (car n) (nth 1 n) '(frac 2 3) 300))))
+      (and (eq (car-safe (nth 1 expr)) 'calcFunc-arcsin)
+	   (list 'calcFunc-sqrt (math-sub 1 (math-sqr (nth 1 (nth 1 expr))))))
+      (and (eq (car-safe (nth 1 expr)) 'calcFunc-arctan)
+	   (math-div 1
+		     (list 'calcFunc-sqrt
+			   (math-add 1 (math-sqr (nth 1 (nth 1 expr)))))))
+      (let ((m (math-should-expand-trig (nth 1 expr))))
+	(and m (integerp (car m))
+	     (let ((n (car m)) (a (nth 1 m)))
+	       (list '-
+		     (list '* (list 'calcFunc-cos (list '* (1- n) a))
+			   (list 'calcFunc-cos a))
+		     (list '* (list 'calcFunc-sin (list '* (1- n) a))
+			   (list 'calcFunc-sin a)))))))
+)
+
+(defun math-should-expand-trig (x &optional hyperbolic)
+  (let ((m (math-is-multiple x)))
+    (and math-living-dangerously
+	 m (or (and (integerp (car m)) (> (car m) 1))
+	       (equal (car m) '(frac 1 2)))
+	 (or math-integrating
+	     (memq (car-safe (nth 1 m))
+		   (if hyperbolic
+		       '(calcFunc-arcsinh calcFunc-arccosh calcFunc-arctanh)
+		     '(calcFunc-arcsin calcFunc-arccos calcFunc-arctan)))
+	     (and (eq (car-safe (nth 1 m)) 'calcFunc-ln)
+		  (eq hyperbolic 'exp)))
+	 m))
+)
+
+(defun math-known-sin (plus n mul off)
+  (setq n (math-mul n mul))
+  (and (math-num-integerp n)
+       (setq n (math-mod (math-add (math-trunc n) off) 240))
+       (if (>= n 120)
+	   (and (setq n (math-known-sin plus (- n 120) 1 0))
+		(math-neg n))
+	 (if (> n 60)
+	     (setq n (- 120 n)))
+	 (if (math-zerop plus)
+	     (and (or calc-symbolic-mode
+		      (memq n '(0 20 60)))
+		  (cdr (assq n
+			     '( (0 . 0)
+				(10 . (/ (calcFunc-sqrt
+					  (- 2 (calcFunc-sqrt 3))) 2))
+				(12 . (/ (- (calcFunc-sqrt 5) 1) 4))
+				(15 . (/ (calcFunc-sqrt
+					  (- 2 (calcFunc-sqrt 2))) 2))
+				(20 . (/ 1 2))
+				(24 . (* (^ (/ 1 2) (/ 3 2))
+					 (calcFunc-sqrt
+					  (- 5 (calcFunc-sqrt 5)))))
+				(30 . (/ (calcFunc-sqrt 2) 2))
+				(36 . (/ (+ (calcFunc-sqrt 5) 1) 4))
+				(40 . (/ (calcFunc-sqrt 3) 2))
+				(45 . (/ (calcFunc-sqrt
+					  (+ 2 (calcFunc-sqrt 2))) 2))
+				(48 . (* (^ (/ 1 2) (/ 3 2))
+					 (calcFunc-sqrt
+					  (+ 5 (calcFunc-sqrt 5)))))
+				(50 . (/ (calcFunc-sqrt
+					  (+ 2 (calcFunc-sqrt 3))) 2))
+				(60 . 1)))))
+	   (cond ((eq n 0) (math-normalize (list 'calcFunc-sin plus)))
+		 ((eq n 60) (math-normalize (list 'calcFunc-cos plus)))
+		 (t nil)))))
+)
+
+(math-defsimplify calcFunc-tan
+  (or (and (eq (car-safe (nth 1 expr)) 'calcFunc-arctan)
+	   (nth 1 (nth 1 expr)))
+      (and (math-looks-negp (nth 1 expr))
+	   (math-neg (list 'calcFunc-tan (math-neg (nth 1 expr)))))
+      (and (eq calc-angle-mode 'rad)
+	   (let ((n (math-linear-in (nth 1 expr) '(var pi var-pi))))
+	     (and n
+		  (math-known-tan (car n) (nth 1 n) 120))))
+      (and (eq calc-angle-mode 'deg)
+	   (let ((n (math-integer-plus (nth 1 expr))))
+	     (and n
+		  (math-known-tan (car n) (nth 1 n) '(frac 2 3)))))
+      (and (eq (car-safe (nth 1 expr)) 'calcFunc-arcsin)
+	   (math-div (nth 1 (nth 1 expr))
+		     (list 'calcFunc-sqrt
+			   (math-sub 1 (math-sqr (nth 1 (nth 1 expr)))))))
+      (and (eq (car-safe (nth 1 expr)) 'calcFunc-arccos)
+	   (math-div (list 'calcFunc-sqrt
+			   (math-sub 1 (math-sqr (nth 1 (nth 1 expr)))))
+		     (nth 1 (nth 1 expr))))
+      (let ((m (math-should-expand-trig (nth 1 expr))))
+	(and m
+	     (if (equal (car m) '(frac 1 2))
+		 (math-div (math-sub 1 (list 'calcFunc-cos (nth 1 m)))
+			   (list 'calcFunc-sin (nth 1 m)))
+	       (math-div (list 'calcFunc-sin (nth 1 expr))
+			 (list 'calcFunc-cos (nth 1 expr)))))))
+)
+
+(defun math-known-tan (plus n mul)
+  (setq n (math-mul n mul))
+  (and (math-num-integerp n)
+       (setq n (math-mod (math-trunc n) 120))
+       (if (> n 60)
+	   (and (setq n (math-known-tan plus (- 120 n) 1))
+		(math-neg n))
+	 (if (math-zerop plus)
+	     (and (or calc-symbolic-mode
+		      (memq n '(0 30 60)))
+		  (cdr (assq n '( (0 . 0)
+				  (10 . (- 2 (calcFunc-sqrt 3)))
+				  (12 . (calcFunc-sqrt
+					 (- 1 (* (/ 2 5) (calcFunc-sqrt 5)))))
+				  (15 . (- (calcFunc-sqrt 2) 1))
+				  (20 . (/ (calcFunc-sqrt 3) 3))
+				  (24 . (calcFunc-sqrt
+					 (- 5 (* 2 (calcFunc-sqrt 5)))))
+				  (30 . 1)
+				  (36 . (calcFunc-sqrt
+					 (+ 1 (* (/ 2 5) (calcFunc-sqrt 5)))))
+				  (40 . (calcFunc-sqrt 3))
+				  (45 . (+ (calcFunc-sqrt 2) 1))
+				  (48 . (calcFunc-sqrt
+					 (+ 5 (* 2 (calcFunc-sqrt 5)))))
+				  (50 . (+ 2 (calcFunc-sqrt 3)))
+				  (60 . (var uinf var-uinf))))))
+	   (cond ((eq n 0) (math-normalize (list 'calcFunc-tan plus)))
+		 ((eq n 60) (math-normalize (list '/ -1
+						  (list 'calcFunc-tan plus))))
+		 (t nil)))))
+)
+
+(math-defsimplify calcFunc-sinh
+  (or (and (eq (car-safe (nth 1 expr)) 'calcFunc-arcsinh)
+	   (nth 1 (nth 1 expr)))
+      (and (math-looks-negp (nth 1 expr))
+	   (math-neg (list 'calcFunc-sinh (math-neg (nth 1 expr)))))
+      (and (eq (car-safe (nth 1 expr)) 'calcFunc-arccosh)
+	   math-living-dangerously
+	   (list 'calcFunc-sqrt (math-sub (math-sqr (nth 1 (nth 1 expr))) 1)))
+      (and (eq (car-safe (nth 1 expr)) 'calcFunc-arctanh)
+	   math-living-dangerously
+	   (math-div (nth 1 (nth 1 expr))
+		     (list 'calcFunc-sqrt
+			   (math-sub 1 (math-sqr (nth 1 (nth 1 expr)))))))
+      (let ((m (math-should-expand-trig (nth 1 expr) t)))
+	(and m (integerp (car m))
+	     (let ((n (car m)) (a (nth 1 m)))
+	       (if (> n 1)
+		   (list '+
+			 (list '* (list 'calcFunc-sinh (list '* (1- n) a))
+			       (list 'calcFunc-cosh a))
+			 (list '* (list 'calcFunc-cosh (list '* (1- n) a))
+			       (list 'calcFunc-sinh a))))))))
+)
+
+(math-defsimplify calcFunc-cosh
+  (or (and (eq (car-safe (nth 1 expr)) 'calcFunc-arccosh)
+	   (nth 1 (nth 1 expr)))
+      (and (math-looks-negp (nth 1 expr))
+	   (list 'calcFunc-cosh (math-neg (nth 1 expr))))
+      (and (eq (car-safe (nth 1 expr)) 'calcFunc-arcsinh)
+	   math-living-dangerously
+	   (list 'calcFunc-sqrt (math-add (math-sqr (nth 1 (nth 1 expr))) 1)))
+      (and (eq (car-safe (nth 1 expr)) 'calcFunc-arctanh)
+	   math-living-dangerously
+	   (math-div 1
+		     (list 'calcFunc-sqrt
+			   (math-sub 1 (math-sqr (nth 1 (nth 1 expr)))))))
+      (let ((m (math-should-expand-trig (nth 1 expr) t)))
+	(and m (integerp (car m))
+	     (let ((n (car m)) (a (nth 1 m)))
+	       (if (> n 1)
+		   (list '+
+			 (list '* (list 'calcFunc-cosh (list '* (1- n) a))
+			       (list 'calcFunc-cosh a))
+			 (list '* (list 'calcFunc-sinh (list '* (1- n) a))
+			       (list 'calcFunc-sinh a))))))))
+)
+
+(math-defsimplify calcFunc-tanh
+  (or (and (eq (car-safe (nth 1 expr)) 'calcFunc-arctanh)
+	   (nth 1 (nth 1 expr)))
+      (and (math-looks-negp (nth 1 expr))
+	   (math-neg (list 'calcFunc-tanh (math-neg (nth 1 expr)))))
+      (and (eq (car-safe (nth 1 expr)) 'calcFunc-arcsinh)
+	   math-living-dangerously
+	   (math-div (nth 1 (nth 1 expr))
+		     (list 'calcFunc-sqrt
+			   (math-add (math-sqr (nth 1 (nth 1 expr))) 1))))
+      (and (eq (car-safe (nth 1 expr)) 'calcFunc-arccosh)
+	   math-living-dangerously
+	   (math-div (list 'calcFunc-sqrt
+			   (math-sub (math-sqr (nth 1 (nth 1 expr))) 1))
+		     (nth 1 (nth 1 expr))))
+      (let ((m (math-should-expand-trig (nth 1 expr) t)))
+	(and m
+	     (if (equal (car m) '(frac 1 2))
+		 (math-div (math-sub (list 'calcFunc-cosh (nth 1 m)) 1)
+			   (list 'calcFunc-sinh (nth 1 m)))
+	       (math-div (list 'calcFunc-sinh (nth 1 expr))
+			 (list 'calcFunc-cosh (nth 1 expr)))))))
+)
+
+(math-defsimplify calcFunc-arcsin
+  (or (and (math-looks-negp (nth 1 expr))
+	   (math-neg (list 'calcFunc-arcsin (math-neg (nth 1 expr)))))
+      (and (eq (nth 1 expr) 1)
+	   (math-quarter-circle t))
+      (and (equal (nth 1 expr) '(frac 1 2))
+	   (math-div (math-half-circle t) 6))
+      (and math-living-dangerously
+	   (eq (car-safe (nth 1 expr)) 'calcFunc-sin)
+	   (nth 1 (nth 1 expr)))
+      (and math-living-dangerously
+	   (eq (car-safe (nth 1 expr)) 'calcFunc-cos)
+	   (math-sub (math-quarter-circle t)
+		     (nth 1 (nth 1 expr)))))
+)
+
+(math-defsimplify calcFunc-arccos
+  (or (and (eq (nth 1 expr) 0)
+	   (math-quarter-circle t))
+      (and (eq (nth 1 expr) -1)
+	   (math-half-circle t))
+      (and (equal (nth 1 expr) '(frac 1 2))
+	   (math-div (math-half-circle t) 3))
+      (and (equal (nth 1 expr) '(frac -1 2))
+	   (math-div (math-mul (math-half-circle t) 2) 3))
+      (and math-living-dangerously
+	   (eq (car-safe (nth 1 expr)) 'calcFunc-cos)
+	   (nth 1 (nth 1 expr)))
+      (and math-living-dangerously
+	   (eq (car-safe (nth 1 expr)) 'calcFunc-sin)
+	   (math-sub (math-quarter-circle t)
+		     (nth 1 (nth 1 expr)))))
+)
+
+(math-defsimplify calcFunc-arctan
+  (or (and (math-looks-negp (nth 1 expr))
+	   (math-neg (list 'calcFunc-arctan (math-neg (nth 1 expr)))))
+      (and (eq (nth 1 expr) 1)
+	   (math-div (math-half-circle t) 4))
+      (and math-living-dangerously
+	   (eq (car-safe (nth 1 expr)) 'calcFunc-tan)
+	   (nth 1 (nth 1 expr))))
+)
+
+(math-defsimplify calcFunc-arcsinh
+  (or (and (math-looks-negp (nth 1 expr))
+	   (math-neg (list 'calcFunc-arcsinh (math-neg (nth 1 expr)))))
+      (and (eq (car-safe (nth 1 expr)) 'calcFunc-sinh)
+	   (or math-living-dangerously
+	       (math-known-realp (nth 1 (nth 1 expr))))
+	   (nth 1 (nth 1 expr))))
+)
+
+(math-defsimplify calcFunc-arccosh
+  (and (eq (car-safe (nth 1 expr)) 'calcFunc-cosh)
+       (or math-living-dangerously
+	   (math-known-realp (nth 1 (nth 1 expr))))
+       (nth 1 (nth 1 expr)))
+)
+
+(math-defsimplify calcFunc-arctanh
+  (or (and (math-looks-negp (nth 1 expr))
+	   (math-neg (list 'calcFunc-arctanh (math-neg (nth 1 expr)))))
+      (and (eq (car-safe (nth 1 expr)) 'calcFunc-tanh)
+	   (or math-living-dangerously
+	       (math-known-realp (nth 1 (nth 1 expr))))
+	   (nth 1 (nth 1 expr))))
+)
+
+(math-defsimplify calcFunc-sqrt
+  (math-simplify-sqrt)
+)
+
+(defun math-simplify-sqrt ()
+  (or (and (eq (car-safe (nth 1 expr)) 'frac)
+	   (math-div (list 'calcFunc-sqrt (math-mul (nth 1 (nth 1 expr))
+						    (nth 2 (nth 1 expr))))
+		     (nth 2 (nth 1 expr))))
+      (let ((fac (if (math-objectp (nth 1 expr))
+		     (math-squared-factor (nth 1 expr))
+		   (math-common-constant-factor (nth 1 expr)))))
+	(and fac (not (eq fac 1))
+	     (math-mul (math-normalize (list 'calcFunc-sqrt fac))
+		       (math-normalize
+			(list 'calcFunc-sqrt
+			      (math-cancel-common-factor (nth 1 expr) fac))))))
+      (and math-living-dangerously
+	   (or (and (eq (car-safe (nth 1 expr)) '-)
+		    (math-equal-int (nth 1 (nth 1 expr)) 1)
+		    (eq (car-safe (nth 2 (nth 1 expr))) '^)
+		    (math-equal-int (nth 2 (nth 2 (nth 1 expr))) 2)
+		    (or (and (eq (car-safe (nth 1 (nth 2 (nth 1 expr))))
+				 'calcFunc-sin)
+			     (list 'calcFunc-cos
+				   (nth 1 (nth 1 (nth 2 (nth 1 expr))))))
+			(and (eq (car-safe (nth 1 (nth 2 (nth 1 expr))))
+				 'calcFunc-cos)
+			     (list 'calcFunc-sin
+				   (nth 1 (nth 1 (nth 2 (nth 1 expr))))))))
+	       (and (eq (car-safe (nth 1 expr)) '-)
+		    (math-equal-int (nth 2 (nth 1 expr)) 1)
+		    (eq (car-safe (nth 1 (nth 1 expr))) '^)
+		    (math-equal-int (nth 2 (nth 1 (nth 1 expr))) 2)
+		    (and (eq (car-safe (nth 1 (nth 1 (nth 1 expr))))
+			     'calcFunc-cosh)
+			 (list 'calcFunc-sinh
+			       (nth 1 (nth 1 (nth 1 (nth 1 expr)))))))
+	       (and (eq (car-safe (nth 1 expr)) '+)
+		    (let ((a (nth 1 (nth 1 expr)))
+			  (b (nth 2 (nth 1 expr))))
+		      (and (or (and (math-equal-int a 1)
+				    (setq a b b (nth 1 (nth 1 expr))))
+			       (math-equal-int b 1))
+			   (eq (car-safe a) '^)
+			   (math-equal-int (nth 2 a) 2)
+			   (or (and (eq (car-safe (nth 1 a)) 'calcFunc-sinh)
+				    (list 'calcFunc-cosh (nth 1 (nth 1 a))))
+			       (and (eq (car-safe (nth 1 a)) 'calcFunc-tan)
+				    (list '/ 1 (list 'calcFunc-cos
+						     (nth 1 (nth 1 a)))))))))
+	       (and (eq (car-safe (nth 1 expr)) '^)
+		    (list '^
+			  (nth 1 (nth 1 expr))
+			  (math-div (nth 2 (nth 1 expr)) 2)))
+	       (and (eq (car-safe (nth 1 expr)) 'calcFunc-sqrt)
+		    (list '^ (nth 1 (nth 1 expr)) (math-div 1 4)))
+	       (and (memq (car-safe (nth 1 expr)) '(* /))
+		    (list (car (nth 1 expr))
+			  (list 'calcFunc-sqrt (nth 1 (nth 1 expr)))
+			  (list 'calcFunc-sqrt (nth 2 (nth 1 expr)))))
+	       (and (memq (car-safe (nth 1 expr)) '(+ -))
+		    (not (math-any-floats (nth 1 expr)))
+		    (let ((f (calcFunc-factors (calcFunc-expand
+						(nth 1 expr)))))
+		      (and (math-vectorp f)
+			   (or (> (length f) 2)
+			       (> (nth 2 (nth 1 f)) 1))
+			   (let ((out 1) (rest 1) (sums 1) fac pow)
+			     (while (setq f (cdr f))
+			       (setq fac (nth 1 (car f))
+				     pow (nth 2 (car f)))
+			       (if (> pow 1)
+				   (setq out (math-mul out (math-pow
+							    fac (/ pow 2)))
+					 pow (% pow 2)))
+			       (if (> pow 0)
+				   (if (memq (car-safe fac) '(+ -))
+				       (setq sums (math-mul-thru sums fac))
+				     (setq rest (math-mul rest fac)))))
+			     (and (not (and (eq out 1) (memq rest '(1 -1))))
+				  (math-mul
+				   out
+				   (list 'calcFunc-sqrt
+					 (math-mul sums rest)))))))))))
+)
+
+;;; Rather than factoring x into primes, just check for the first ten primes.
+(defun math-squared-factor (x)
+  (if (Math-integerp x)
+      (let ((prsqr '(4 9 25 49 121 169 289 361 529 841))
+	    (fac 1)
+	    res)
+	(while prsqr
+	  (if (eq (cdr (setq res (math-idivmod x (car prsqr)))) 0)
+	      (setq x (car res)
+		    fac (math-mul fac (car prsqr)))
+	    (setq prsqr (cdr prsqr))))
+	fac))
+)
+
+(math-defsimplify calcFunc-exp
+  (math-simplify-exp (nth 1 expr))
+)
+
+(defun math-simplify-exp (x)
+  (or (and (eq (car-safe x) 'calcFunc-ln)
+	   (nth 1 x))
+      (and math-living-dangerously
+	   (or (and (eq (car-safe x) 'calcFunc-arcsinh)
+		    (math-add (nth 1 x)
+			      (list 'calcFunc-sqrt
+				    (math-add (math-sqr (nth 1 x)) 1))))
+	       (and (eq (car-safe x) 'calcFunc-arccosh)
+		    (math-add (nth 1 x)
+			      (list 'calcFunc-sqrt
+				    (math-sub (math-sqr (nth 1 x)) 1))))
+	       (and (eq (car-safe x) 'calcFunc-arctanh)
+		    (math-div (list 'calcFunc-sqrt (math-add 1 (nth 1 x)))
+			      (list 'calcFunc-sqrt (math-sub 1 (nth 1 x)))))
+	       (let ((m (math-should-expand-trig x 'exp)))
+		 (and m (integerp (car m))
+		      (list '^ (list 'calcFunc-exp (nth 1 m)) (car m))))))
+      (and calc-symbolic-mode
+	   (math-known-imagp x)
+	   (let* ((ip (calcFunc-im x))
+		  (n (math-linear-in ip '(var pi var-pi)))
+		  s c)
+	     (and n
+		  (setq s (math-known-sin (car n) (nth 1 n) 120 0))
+		  (setq c (math-known-sin (car n) (nth 1 n) 120 300))
+		  (list '+ c (list '* s '(var i var-i)))))))
+)
+
+(math-defsimplify calcFunc-ln
+  (or (and (eq (car-safe (nth 1 expr)) 'calcFunc-exp)
+	   (or math-living-dangerously
+	       (math-known-realp (nth 1 (nth 1 expr))))
+	   (nth 1 (nth 1 expr)))
+      (and (eq (car-safe (nth 1 expr)) '^)
+	   (equal (nth 1 (nth 1 expr)) '(var e var-e))
+	   (or math-living-dangerously
+	       (math-known-realp (nth 2 (nth 1 expr))))
+	   (nth 2 (nth 1 expr)))
+      (and calc-symbolic-mode
+	   (math-known-negp (nth 1 expr))
+	   (math-add (list 'calcFunc-ln (math-neg (nth 1 expr)))
+		     '(var pi var-pi)))
+      (and calc-symbolic-mode
+	   (math-known-imagp (nth 1 expr))
+	   (let* ((ip (calcFunc-im (nth 1 expr)))
+		  (ips (math-possible-signs ip)))
+	     (or (and (memq ips '(4 6))
+		      (math-add (list 'calcFunc-ln ip)
+				'(/ (* (var pi var-pi) (var i var-i)) 2)))
+		 (and (memq ips '(1 3))
+		      (math-sub (list 'calcFunc-ln (math-neg ip))
+				'(/ (* (var pi var-pi) (var i var-i)) 2)))))))
+)
+
+(math-defsimplify ^
+  (math-simplify-pow))
+
+(defun math-simplify-pow ()
+  (or (and math-living-dangerously
+	   (or (and (eq (car-safe (nth 1 expr)) '^)
+		    (list '^
+			  (nth 1 (nth 1 expr))
+			  (math-mul (nth 2 expr) (nth 2 (nth 1 expr)))))
+	       (and (eq (car-safe (nth 1 expr)) 'calcFunc-sqrt)
+		    (list '^
+			  (nth 1 (nth 1 expr))
+			  (math-div (nth 2 expr) 2)))
+	       (and (memq (car-safe (nth 1 expr)) '(* /))
+		    (list (car (nth 1 expr))
+			  (list '^ (nth 1 (nth 1 expr)) (nth 2 expr))
+			  (list '^ (nth 2 (nth 1 expr)) (nth 2 expr))))))
+      (and (math-equal-int (nth 1 expr) 10)
+	   (eq (car-safe (nth 2 expr)) 'calcFunc-log10)
+	   (nth 1 (nth 2 expr)))
+      (and (equal (nth 1 expr) '(var e var-e))
+	   (math-simplify-exp (nth 2 expr)))
+      (and (eq (car-safe (nth 1 expr)) 'calcFunc-exp)
+	   (not math-integrating)
+	   (list 'calcFunc-exp (math-mul (nth 1 (nth 1 expr)) (nth 2 expr))))
+      (and (equal (nth 1 expr) '(var i var-i))
+	   (math-imaginary-i)
+	   (math-num-integerp (nth 2 expr))
+	   (let ((x (math-mod (math-trunc (nth 2 expr)) 4)))
+	     (cond ((eq x 0) 1)
+		   ((eq x 1) (nth 1 expr))
+		   ((eq x 2) -1)
+		   ((eq x 3) (math-neg (nth 1 expr))))))
+      (and math-integrating
+	   (integerp (nth 2 expr))
+	   (>= (nth 2 expr) 2)
+	   (or (and (eq (car-safe (nth 1 expr)) 'calcFunc-cos)
+		    (math-mul (math-pow (nth 1 expr) (- (nth 2 expr) 2))
+			      (math-sub 1
+					(math-sqr
+					 (list 'calcFunc-sin
+					       (nth 1 (nth 1 expr)))))))
+	       (and (eq (car-safe (nth 1 expr)) 'calcFunc-cosh)
+		    (math-mul (math-pow (nth 1 expr) (- (nth 2 expr) 2))
+			      (math-add 1
+					(math-sqr
+					 (list 'calcFunc-sinh
+					       (nth 1 (nth 1 expr)))))))))
+      (and (eq (car-safe (nth 2 expr)) 'frac)
+	   (Math-ratp (nth 1 expr))
+	   (Math-posp (nth 1 expr))
+	   (if (equal (nth 2 expr) '(frac 1 2))
+	       (list 'calcFunc-sqrt (nth 1 expr))
+	     (let ((flr (math-floor (nth 2 expr))))
+	       (and (not (Math-zerop flr))
+		    (list '* (list '^ (nth 1 expr) flr)
+			  (list '^ (nth 1 expr)
+				(math-sub (nth 2 expr) flr)))))))
+      (and (eq (math-quarter-integer (nth 2 expr)) 2)
+	   (let ((temp (math-simplify-sqrt)))
+	     (and temp
+		  (list '^ temp (math-mul (nth 2 expr) 2))))))
+)
+
+(math-defsimplify calcFunc-log10
+  (and (eq (car-safe (nth 1 expr)) '^)
+       (math-equal-int (nth 1 (nth 1 expr)) 10)
+       (or math-living-dangerously
+	   (math-known-realp (nth 2 (nth 1 expr))))
+       (nth 2 (nth 1 expr)))
+)
+
+
+(math-defsimplify calcFunc-erf
+  (or (and (math-looks-negp (nth 1 expr))
+	   (math-neg (list 'calcFunc-erf (math-neg (nth 1 expr)))))
+      (and (eq (car-safe (nth 1 expr)) 'calcFunc-conj)
+	   (list 'calcFunc-conj (list 'calcFunc-erf (nth 1 (nth 1 expr))))))
+)
+
+(math-defsimplify calcFunc-erfc
+  (or (and (math-looks-negp (nth 1 expr))
+	   (math-sub 2 (list 'calcFunc-erfc (math-neg (nth 1 expr)))))
+      (and (eq (car-safe (nth 1 expr)) 'calcFunc-conj)
+	   (list 'calcFunc-conj (list 'calcFunc-erfc (nth 1 (nth 1 expr))))))
+)
+
+
+(defun math-linear-in (expr term &optional always)
+  (if (math-expr-contains expr term)
+      (let* ((calc-prefer-frac t)
+	     (p (math-is-polynomial expr term 1)))
+	(and (cdr p)
+	     p))
+    (and always (list expr 0)))
+)
+
+(defun math-multiple-of (expr term)
+  (let ((p (math-linear-in expr term)))
+    (and p
+	 (math-zerop (car p))
+	 (nth 1 p)))
+)
+
+(defun math-integer-plus (expr)
+  (cond ((Math-integerp expr)
+	 (list 0 expr))
+	((and (memq (car expr) '(+ -))
+	      (Math-integerp (nth 1 expr)))
+	 (list (if (eq (car expr) '+) (nth 2 expr) (math-neg (nth 2 expr)))
+	       (nth 1 expr)))
+	((and (memq (car expr) '(+ -))
+	      (Math-integerp (nth 2 expr)))
+	 (list (nth 1 expr)
+	       (if (eq (car expr) '+) (nth 2 expr) (math-neg (nth 2 expr)))))
+	(t nil))   ; not perfect, but it'll do
+)
+
+(defun math-is-linear (expr &optional always)
+  (let ((offset nil)
+	(coef nil))
+    (if (eq (car-safe expr) '+)
+	(if (Math-objectp (nth 1 expr))
+	    (setq offset (nth 1 expr)
+		  expr (nth 2 expr))
+	  (if (Math-objectp (nth 2 expr))
+	      (setq offset (nth 2 expr)
+		    expr (nth 1 expr))))
+      (if (eq (car-safe expr) '-)
+	  (if (Math-objectp (nth 1 expr))
+	      (setq offset (nth 1 expr)
+		    expr (math-neg (nth 2 expr)))
+	    (if (Math-objectp (nth 2 expr))
+		(setq offset (math-neg (nth 2 expr))
+		      expr (nth 1 expr))))))
+    (setq coef (math-is-multiple expr always))
+    (if offset
+	(list offset (or (car coef) 1) (or (nth 1 coef) expr))
+      (if coef
+	  (cons 0 coef))))
+)
+
+(defun math-is-multiple (expr &optional always)
+  (or (if (eq (car-safe expr) '*)
+	  (if (Math-objectp (nth 1 expr))
+	      (list (nth 1 expr) (nth 2 expr)))
+	(if (eq (car-safe expr) '/)
+	    (if (and (Math-objectp (nth 1 expr))
+		     (not (math-equal-int (nth 1 expr) 1)))
+		(list (nth 1 expr) (math-div 1 (nth 2 expr)))
+	      (if (Math-objectp (nth 2 expr))
+		  (list (math-div 1 (nth 2 expr)) (nth 1 expr))
+		(let ((res (math-is-multiple (nth 1 expr))))
+		  (if res
+		      (list (car res)
+			    (math-div (nth 2 (nth 1 expr)) (nth 2 expr)))
+		    (setq res (math-is-multiple (nth 2 expr)))
+		    (if res
+			(list (math-div 1 (car res))
+			      (math-div (nth 1 expr)
+					(nth 2 (nth 2 expr)))))))))
+	  (if (eq (car-safe expr) 'neg)
+	      (list -1 (nth 1 expr)))))
+      (if (Math-objvecp expr)
+	  (and (eq always 1)
+	       (list expr 1))
+	(and always 
+	     (list 1 expr))))
+)
+
+(defun calcFunc-lin (expr &optional var)
+  (if var
+      (let ((res (math-linear-in expr var t)))
+	(or res (math-reject-arg expr "Linear term expected"))
+	(list 'vec (car res) (nth 1 res) var))
+    (let ((res (math-is-linear expr t)))
+      (or res (math-reject-arg expr "Linear term expected"))
+      (cons 'vec res)))
+)
+
+(defun calcFunc-linnt (expr &optional var)
+  (if var
+      (let ((res (math-linear-in expr var)))
+	(or res (math-reject-arg expr "Linear term expected"))
+	(list 'vec (car res) (nth 1 res) var))
+    (let ((res (math-is-linear expr)))
+      (or res (math-reject-arg expr "Linear term expected"))
+      (cons 'vec res)))
+)
+
+(defun calcFunc-islin (expr &optional var)
+  (if (and (Math-objvecp expr) (not var))
+      0
+    (calcFunc-lin expr var)
+    1)
+)
+
+(defun calcFunc-islinnt (expr &optional var)
+  (if (Math-objvecp expr)
+      0
+    (calcFunc-linnt expr var)
+    1)
+)
+
+
+
+
+;;; Simple operations on expressions.
+
+;;; Return number of ocurrences of thing in expr, or nil if none.
+(defun math-expr-contains-count (expr thing)
+  (cond ((equal expr thing) 1)
+	((Math-primp expr) nil)
+	(t
+	 (let ((num 0))
+	   (while (setq expr (cdr expr))
+	     (setq num (+ num (or (math-expr-contains-count
+				   (car expr) thing) 0))))
+	   (and (> num 0)
+		num))))
+)
+
+(defun math-expr-contains (expr thing)
+  (cond ((equal expr thing) 1)
+	((Math-primp expr) nil)
+	(t
+	 (while (and (setq expr (cdr expr))
+		     (not (math-expr-contains (car expr) thing))))
+	 expr))
+)
+
+;;; Return non-nil if any variable of thing occurs in expr.
+(defun math-expr-depends (expr thing)
+  (if (Math-primp thing)
+      (and (eq (car-safe thing) 'var)
+	   (math-expr-contains expr thing))
+    (while (and (setq thing (cdr thing))
+		(not (math-expr-depends expr (car thing)))))
+    thing)
+)
+
+;;; Substitute all occurrences of old for new in expr (non-destructive).
+(defun math-expr-subst (expr old new)
+  (math-expr-subst-rec expr)
+)
+(fset 'calcFunc-subst (symbol-function 'math-expr-subst))
+
+(defun math-expr-subst-rec (expr)
+  (cond ((equal expr old) new)
+	((Math-primp expr) expr)
+	((memq (car expr) '(calcFunc-deriv
+			    calcFunc-tderiv))
+	 (if (= (length expr) 2)
+	     (if (equal (nth 1 expr) old)
+		 (append expr (list new))
+	       expr)
+	   (list (car expr) (nth 1 expr)
+		 (math-expr-subst-rec (nth 2 expr)))))
+	(t
+	 (cons (car expr)
+	       (mapcar 'math-expr-subst-rec (cdr expr)))))
+)
+
+;;; Various measures of the size of an expression.
+(defun math-expr-weight (expr)
+  (if (Math-primp expr)
+      1
+    (let ((w 1))
+      (while (setq expr (cdr expr))
+	(setq w (+ w (math-expr-weight (car expr)))))
+      w))
+)
+
+(defun math-expr-height (expr)
+  (if (Math-primp expr)
+      0
+    (let ((h 0))
+      (while (setq expr (cdr expr))
+	(setq h (max h (math-expr-height (car expr)))))
+      (1+ h)))
+)
+
+
+
+
+;;; Polynomial operations (to support the integrator and solve-for).
+
+(defun calcFunc-collect (expr base)
+  (let ((p (math-is-polynomial expr base 50 t)))
+    (if (cdr p)
+	(math-normalize   ; fix selection bug
+	 (math-build-polynomial-expr p base))
+      expr))
+)
+
+;;; If expr is of the form "a + bx + cx^2 + ...", return the list (a b c ...),
+;;; else return nil if not in polynomial form.  If "loose", coefficients
+;;; may contain x, e.g., sin(x) + cos(x) x^2 is a loose polynomial in x.
+(defun math-is-polynomial (expr var &optional degree loose)
+  (let* ((math-poly-base-variable (if loose
+				      (if (eq loose 'gen) var '(var XXX XXX))
+				    math-poly-base-variable))
+	 (poly (math-is-poly-rec expr math-poly-neg-powers)))
+    (and (or (null degree)
+	     (<= (length poly) (1+ degree)))
+	 poly))
+)
+
+(defun math-is-poly-rec (expr negpow)
+  (math-poly-simplify
+   (or (cond ((or (equal expr var)
+		  (eq (car-safe expr) '^))
+	      (let ((pow 1)
+		    (expr expr))
+		(or (equal expr var)
+		    (setq pow (nth 2 expr)
+			  expr (nth 1 expr)))
+		(or (eq math-poly-mult-powers 1)
+		    (setq pow (let ((m (math-is-multiple pow 1)))
+				(and (eq (car-safe (car m)) 'cplx)
+				     (Math-zerop (nth 1 (car m)))
+				     (setq m (list (nth 2 (car m))
+						   (math-mul (nth 1 m)
+							     '(var i var-i)))))
+				(and (if math-poly-mult-powers
+					 (equal math-poly-mult-powers
+						(nth 1 m))
+				       (setq math-poly-mult-powers (nth 1 m)))
+				     (or (equal expr var)
+					 (eq math-poly-mult-powers 1))
+				     (car m)))))
+		(if (consp pow)
+		    (progn
+		      (setq pow (math-to-simple-fraction pow))
+		      (and (eq (car-safe pow) 'frac)
+			   math-poly-frac-powers
+			   (equal expr var)
+			   (setq math-poly-frac-powers
+				 (calcFunc-lcm math-poly-frac-powers
+					       (nth 2 pow))))))
+		(or (memq math-poly-frac-powers '(1 nil))
+		    (setq pow (math-mul pow math-poly-frac-powers)))
+		(if (integerp pow)
+		    (if (and (= pow 1)
+			     (equal expr var))
+			(list 0 1)
+		      (if (natnump pow)
+			  (let ((p1 (if (equal expr var)
+					(list 0 1)
+				      (math-is-poly-rec expr nil)))
+				(n pow)
+				(accum (list 1)))
+			    (and p1
+				 (or (null degree)
+				     (<= (* (1- (length p1)) n) degree))
+				 (progn
+				   (while (>= n 1)
+				     (setq accum (math-poly-mul accum p1)
+					   n (1- n)))
+				   accum)))
+			(and negpow
+			     (math-is-poly-rec expr nil)
+			     (setq math-poly-neg-powers
+				   (cons (math-pow expr (- pow))
+					 math-poly-neg-powers))
+			     (list (list '^ expr pow))))))))
+	     ((Math-objectp expr)
+	      (list expr))
+	     ((memq (car expr) '(+ -))
+	      (let ((p1 (math-is-poly-rec (nth 1 expr) negpow)))
+		(and p1
+		     (let ((p2 (math-is-poly-rec (nth 2 expr) negpow)))
+		       (and p2
+			    (math-poly-mix p1 1 p2
+					   (if (eq (car expr) '+) 1 -1)))))))
+	     ((eq (car expr) 'neg)
+	      (mapcar 'math-neg (math-is-poly-rec (nth 1 expr) negpow)))
+	     ((eq (car expr) '*)
+	      (let ((p1 (math-is-poly-rec (nth 1 expr) negpow)))
+		(and p1
+		     (let ((p2 (math-is-poly-rec (nth 2 expr) negpow)))
+		       (and p2
+			    (or (null degree)
+				(<= (- (+ (length p1) (length p2)) 2) degree))
+			    (math-poly-mul p1 p2))))))
+	     ((eq (car expr) '/)
+	      (and (or (not (math-poly-depends (nth 2 expr) var))
+		       (and negpow
+			    (math-is-poly-rec (nth 2 expr) nil)
+			    (setq math-poly-neg-powers
+				  (cons (nth 2 expr) math-poly-neg-powers))))
+		   (not (Math-zerop (nth 2 expr)))
+		   (let ((p1 (math-is-poly-rec (nth 1 expr) negpow)))
+		     (mapcar (function (lambda (x) (math-div x (nth 2 expr))))
+			     p1))))
+	     ((and (eq (car expr) 'calcFunc-exp)
+		   (equal var '(var e var-e)))
+	      (math-is-poly-rec (list '^ var (nth 1 expr)) negpow))
+	     ((and (eq (car expr) 'calcFunc-sqrt)
+		   math-poly-frac-powers)
+	      (math-is-poly-rec (list '^ (nth 1 expr) '(frac 1 2)) negpow))
+	     (t nil))
+       (and (or (not (math-poly-depends expr var))
+		loose)
+	    (not (eq (car expr) 'vec))
+	    (list expr))))
+)
+
+;;; Check if expr is a polynomial in var; if so, return its degree.
+(defun math-polynomial-p (expr var)
+  (cond ((equal expr var) 1)
+	((Math-primp expr) 0)
+	((memq (car expr) '(+ -))
+	 (let ((p1 (math-polynomial-p (nth 1 expr) var))
+	       p2)
+	   (and p1 (setq p2 (math-polynomial-p (nth 2 expr) var))
+		(max p1 p2))))
+	((eq (car expr) '*)
+	 (let ((p1 (math-polynomial-p (nth 1 expr) var))
+	       p2)
+	   (and p1 (setq p2 (math-polynomial-p (nth 2 expr) var))
+		(+ p1 p2))))
+	((eq (car expr) 'neg)
+	 (math-polynomial-p (nth 1 expr) var))
+	((and (eq (car expr) '/)
+	      (not (math-poly-depends (nth 2 expr) var)))
+	 (math-polynomial-p (nth 1 expr) var))
+	((and (eq (car expr) '^)
+	      (natnump (nth 2 expr)))
+	 (let ((p1 (math-polynomial-p (nth 1 expr) var)))
+	   (and p1 (* p1 (nth 2 expr)))))
+	((math-poly-depends expr var) nil)
+	(t 0))
+)
+
+(defun math-poly-depends (expr var)
+  (if math-poly-base-variable
+      (math-expr-contains expr math-poly-base-variable)
+    (math-expr-depends expr var))
+)
+
+;;; Find the variable (or sub-expression) which is the base of polynomial expr.
+(defun math-polynomial-base (mpb-top-expr &optional mpb-pred)
+  (or mpb-pred
+      (setq mpb-pred (function (lambda (base) (math-polynomial-p
+					       mpb-top-expr base)))))
+  (or (let ((const-ok nil))
+	(math-polynomial-base-rec mpb-top-expr))
+      (let ((const-ok t))
+	(math-polynomial-base-rec mpb-top-expr)))
+)
+
+(defun math-polynomial-base-rec (mpb-expr)
+  (and (not (Math-objvecp mpb-expr))
+       (or (and (memq (car mpb-expr) '(+ - *))
+		(or (math-polynomial-base-rec (nth 1 mpb-expr))
+		    (math-polynomial-base-rec (nth 2 mpb-expr))))
+	   (and (memq (car mpb-expr) '(/ neg))
+		(math-polynomial-base-rec (nth 1 mpb-expr)))
+	   (and (eq (car mpb-expr) '^)
+		(math-polynomial-base-rec (nth 1 mpb-expr)))
+	   (and (eq (car mpb-expr) 'calcFunc-exp)
+		(math-polynomial-base-rec '(var e var-e)))
+	   (and (or const-ok (math-expr-contains-vars mpb-expr))
+		(funcall mpb-pred mpb-expr)
+		mpb-expr)))
+)
+
+;;; Return non-nil if expr refers to any variables.
+(defun math-expr-contains-vars (expr)
+  (or (eq (car-safe expr) 'var)
+      (and (not (Math-primp expr))
+	   (progn
+	     (while (and (setq expr (cdr expr))
+			 (not (math-expr-contains-vars (car expr)))))
+	     expr)))
+)
+
+;;; Simplify a polynomial in list form by stripping off high-end zeros.
+;;; This always leaves the constant part, i.e., nil->nil and nonnil->nonnil.
+(defun math-poly-simplify (p)
+  (and p
+       (if (Math-zerop (nth (1- (length p)) p))
+	   (let ((pp (copy-sequence p)))
+	     (while (and (cdr pp)
+			 (Math-zerop (nth (1- (length pp)) pp)))
+	       (setcdr (nthcdr (- (length pp) 2) pp) nil))
+	     pp)
+	 p))
+)
+
+;;; Compute ac*a + bc*b for polynomials in list form a, b and
+;;; coefficients ac, bc.  Result may be unsimplified.
+(defun math-poly-mix (a ac b bc)
+  (and (or a b)
+       (cons (math-add (math-mul (or (car a) 0) ac)
+		       (math-mul (or (car b) 0) bc))
+	     (math-poly-mix (cdr a) ac (cdr b) bc)))
+)
+
+(defun math-poly-zerop (a)
+  (or (null a)
+      (and (null (cdr a)) (Math-zerop (car a))))
+)
+
+;;; Multiply two polynomials in list form.
+(defun math-poly-mul (a b)
+  (and a b
+       (math-poly-mix b (car a)
+		      (math-poly-mul (cdr a) (cons 0 b)) 1))
+)
+
+;;; Build an expression from a polynomial list.
+(defun math-build-polynomial-expr (p var)
+  (if p
+      (if (Math-numberp var)
+	  (math-with-extra-prec 1
+	    (let* ((rp (reverse p))
+		   (accum (car rp)))
+	      (while (setq rp (cdr rp))
+		(setq accum (math-add (car rp) (math-mul accum var))))
+	      accum))
+	(let* ((rp (reverse p))
+	       (n (1- (length rp)))
+	       (accum (math-mul (car rp) (math-pow var n)))
+	       term)
+	  (while (setq rp (cdr rp))
+	    (setq n (1- n))
+	    (or (math-zerop (car rp))
+		(setq accum (list (if (math-looks-negp (car rp)) '- '+)
+				  accum
+				  (math-mul (if (math-looks-negp (car rp))
+						(math-neg (car rp))
+					      (car rp))
+					    (math-pow var n))))))
+	  accum))
+    0)
+)
+
+
+(defun math-to-simple-fraction (f)
+  (or (and (eq (car-safe f) 'float)
+	   (or (and (>= (nth 2 f) 0)
+		    (math-scale-int (nth 1 f) (nth 2 f)))
+	       (and (integerp (nth 1 f))
+		    (> (nth 1 f) -1000)
+		    (< (nth 1 f) 1000)
+		    (math-make-frac (nth 1 f)
+				    (math-scale-int 1 (- (nth 2 f)))))))
+      f)
+)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/calc-arith.el	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,2924 @@
+;; Calculator for GNU Emacs, part II [calc-arith.el]
+;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+;; Written by Dave Gillespie, daveg@synaptics.com.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY.  No author or distributor
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing.  Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License.   A copy of this license is
+;; supposed to have been given to you along with GNU Emacs so you
+;; can know your rights and responsibilities.  It should be in a
+;; file named COPYING.  Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+
+
+
+;; This file is autoloaded from calc-ext.el.
+(require 'calc-ext)
+
+(require 'calc-macs)
+
+(defun calc-Need-calc-arith () nil)
+
+
+;;; Arithmetic.
+
+(defun calc-min (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-binary-op "min" 'calcFunc-min arg '(var inf var-inf)))
+)
+
+(defun calc-max (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-binary-op "max" 'calcFunc-max arg '(neg (var inf var-inf))))
+)
+
+(defun calc-abs (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-unary-op "abs" 'calcFunc-abs arg))
+)
+
+
+(defun calc-idiv (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-binary-op "\\" 'calcFunc-idiv arg 1))
+)
+
+
+(defun calc-floor (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (if (calc-is-inverse)
+       (if (calc-is-hyperbolic)
+	   (calc-unary-op "ceil" 'calcFunc-fceil arg)
+	 (calc-unary-op "ceil" 'calcFunc-ceil arg))
+     (if (calc-is-hyperbolic)
+	 (calc-unary-op "flor" 'calcFunc-ffloor arg)
+       (calc-unary-op "flor" 'calcFunc-floor arg))))
+)
+
+(defun calc-ceiling (arg)
+  (interactive "P")
+  (calc-invert-func)
+  (calc-floor arg)
+)
+
+(defun calc-round (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (if (calc-is-inverse)
+       (if (calc-is-hyperbolic)
+	   (calc-unary-op "trnc" 'calcFunc-ftrunc arg)
+	 (calc-unary-op "trnc" 'calcFunc-trunc arg))
+     (if (calc-is-hyperbolic)
+	 (calc-unary-op "rond" 'calcFunc-fround arg)
+       (calc-unary-op "rond" 'calcFunc-round arg))))
+)
+
+(defun calc-trunc (arg)
+  (interactive "P")
+  (calc-invert-func)
+  (calc-round arg)
+)
+
+(defun calc-mant-part (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-unary-op "mant" 'calcFunc-mant arg))
+)
+
+(defun calc-xpon-part (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-unary-op "xpon" 'calcFunc-xpon arg))
+)
+
+(defun calc-scale-float (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-binary-op "scal" 'calcFunc-scf arg))
+)
+
+(defun calc-abssqr (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-unary-op "absq" 'calcFunc-abssqr arg))
+)
+
+(defun calc-sign (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-unary-op "sign" 'calcFunc-sign arg))
+)
+
+(defun calc-increment (arg)
+  (interactive "p")
+  (calc-wrapper
+   (calc-enter-result 1 "incr" (list 'calcFunc-incr (calc-top-n 1) arg)))
+)
+
+(defun calc-decrement (arg)
+  (interactive "p")
+  (calc-wrapper
+   (calc-enter-result 1 "decr" (list 'calcFunc-decr (calc-top-n 1) arg)))
+)
+
+
+(defun math-abs-approx (a)
+  (cond ((Math-negp a)
+	 (math-neg a))
+	((Math-anglep a)
+	 a)
+	((eq (car a) 'cplx)
+	 (math-add (math-abs (nth 1 a)) (math-abs (nth 2 a))))
+	((eq (car a) 'polar)
+	 (nth 1 a))
+	((eq (car a) 'sdev)
+	 (math-abs-approx (nth 1 a)))
+	((eq (car a) 'intv)
+	 (math-max (math-abs (nth 2 a)) (math-abs (nth 3 a))))
+	((eq (car a) 'date)
+	 a)
+	((eq (car a) 'vec)
+	 (math-reduce-vec 'math-add-abs-approx a))
+	((eq (car a) 'calcFunc-abs)
+	 (car a))
+	(t a))
+)
+
+(defun math-add-abs-approx (a b)
+  (math-add (math-abs-approx a) (math-abs-approx b))
+)
+
+
+;;;; Declarations.
+
+(setq math-decls-cache-tag nil)
+(setq math-decls-cache nil)
+(setq math-decls-all nil)
+
+;;; Math-decls-cache is an a-list where each entry is a list of the form:
+;;;   (VAR TYPES RANGE)
+;;; where VAR is a variable name (with var- prefix) or function name;
+;;;       TYPES is a list of type symbols (any, int, frac, ...)
+;;;	  RANGE is a sorted vector of intervals describing the range.
+
+(defun math-setup-declarations ()
+  (or (eq math-decls-cache-tag (calc-var-value 'var-Decls))
+      (let ((p (calc-var-value 'var-Decls))
+	    vec type range)
+	(setq math-decls-cache-tag p
+	      math-decls-cache nil)
+	(and (eq (car-safe p) 'vec)
+	     (while (setq p (cdr p))
+	       (and (eq (car-safe (car p)) 'vec)
+		    (setq vec (nth 2 (car p)))
+		    (condition-case err
+			(let ((v (nth 1 (car p))))
+			  (setq type nil range nil)
+			  (or (eq (car-safe vec) 'vec)
+			      (setq vec (list 'vec vec)))
+			  (while (and (setq vec (cdr vec))
+				      (not (Math-objectp (car vec))))
+			    (and (eq (car-safe (car vec)) 'var)
+				 (let ((st (assq (nth 1 (car vec))
+						 math-super-types)))
+				   (cond (st (setq type (append type st)))
+					 ((eq (nth 1 (car vec)) 'pos)
+					  (setq type (append type
+							     '(real number))
+						range
+						'(intv 1 0 (var inf var-inf))))
+					 ((eq (nth 1 (car vec)) 'nonneg)
+					  (setq type (append type
+							     '(real number))
+						range
+						'(intv 3 0
+						       (var inf var-inf))))))))
+			  (if vec
+			      (setq type (append type '(real number))
+				    range (math-prepare-set (cons 'vec vec))))
+			  (setq type (list type range))
+			  (or (eq (car-safe v) 'vec)
+			      (setq v (list 'vec v)))
+			  (while (setq v (cdr v))
+			    (if (or (eq (car-safe (car v)) 'var)
+				    (not (Math-primp (car v))))
+				(setq math-decls-cache
+				      (cons (cons (if (eq (car (car v)) 'var)
+						      (nth 2 (car v))
+						    (car (car v)))
+						  type)
+					    math-decls-cache)))))
+		      (error nil)))))
+	(setq math-decls-all (assq 'var-All math-decls-cache))))
+)
+
+(defvar math-super-types
+  '( ( int     numint rat real number )
+     ( numint  real number )
+     ( frac    rat real number )
+     ( rat     real number )
+     ( float   real number )
+     ( real    number )
+     ( number  )
+     ( scalar  )
+     ( matrix  vector )
+     ( vector )
+     ( const )
+))
+
+
+(defun math-known-scalarp (a &optional assume-scalar)
+  (math-setup-declarations)
+  (if (if calc-matrix-mode
+	  (eq calc-matrix-mode 'scalar)
+	assume-scalar)
+      (not (math-check-known-matrixp a))
+    (math-check-known-scalarp a))
+)
+
+(defun math-known-matrixp (a)
+  (and (not (Math-scalarp a))
+       (not (math-known-scalarp a t)))
+)
+
+;;; Try to prove that A is a scalar (i.e., a non-vector).
+(defun math-check-known-scalarp (a)
+  (cond ((Math-objectp a) t)
+	((memq (car a) math-scalar-functions)
+	 t)
+	((memq (car a) math-real-scalar-functions)
+	 t)
+	((memq (car a) math-scalar-if-args-functions)
+	 (while (and (setq a (cdr a))
+		     (math-check-known-scalarp (car a))))
+	 (null a))
+	((eq (car a) '^)
+	 (math-check-known-scalarp (nth 1 a)))
+	((math-const-var a) t)
+	(t
+	 (let ((decl (if (eq (car a) 'var)
+			 (or (assq (nth 2 a) math-decls-cache)
+			     math-decls-all)
+		       (assq (car a) math-decls-cache))))
+	   (memq 'scalar (nth 1 decl)))))
+)
+
+;;; Try to prove that A is *not* a scalar.
+(defun math-check-known-matrixp (a)
+  (cond ((Math-objectp a) nil)
+	((memq (car a) math-nonscalar-functions)
+	 t)
+	((memq (car a) math-scalar-if-args-functions)
+	 (while (and (setq a (cdr a))
+		     (not (math-check-known-matrixp (car a)))))
+	 a)
+	((eq (car a) '^)
+	 (math-check-known-matrixp (nth 1 a)))
+	((math-const-var a) nil)
+	(t
+	 (let ((decl (if (eq (car a) 'var)
+			 (or (assq (nth 2 a) math-decls-cache)
+			     math-decls-all)
+		       (assq (car a) math-decls-cache))))
+	   (memq 'vector (nth 1 decl)))))
+)
+
+
+;;; Try to prove that A is a real (i.e., not complex).
+(defun math-known-realp (a)
+  (< (math-possible-signs a) 8)
+)
+
+;;; Try to prove that A is real and positive.
+(defun math-known-posp (a)
+  (eq (math-possible-signs a) 4)
+)
+
+;;; Try to prove that A is real and negative.
+(defun math-known-negp (a)
+  (eq (math-possible-signs a) 1)
+)
+
+;;; Try to prove that A is real and nonnegative.
+(defun math-known-nonnegp (a)
+  (memq (math-possible-signs a) '(2 4 6))
+)
+
+;;; Try to prove that A is real and nonpositive.
+(defun math-known-nonposp (a)
+  (memq (math-possible-signs a) '(1 2 3))
+)
+
+;;; Try to prove that A is nonzero.
+(defun math-known-nonzerop (a)
+  (memq (math-possible-signs a) '(1 4 5 8 9 12 13))
+)
+
+;;; Return true if A is negative, or looks negative but we don't know.
+(defun math-guess-if-neg (a)
+  (let ((sgn (math-possible-signs a)))
+    (if (memq sgn '(1 3))
+	t
+      (if (memq sgn '(2 4 6))
+	  nil
+	(math-looks-negp a))))
+)
+
+;;; Find the possible signs of A, assuming A is a number of some kind.
+;;; Returns an integer with bits:  1  may be negative,
+;;;				   2  may be zero,
+;;;				   4  may be positive,
+;;;				   8  may be nonreal.
+
+(defun math-possible-signs (a &optional origin)
+  (cond ((Math-objectp a)
+	 (if origin (setq a (math-sub a origin)))
+	 (cond ((Math-posp a) 4)
+	       ((Math-negp a) 1)
+	       ((Math-zerop a) 2)
+	       ((eq (car a) 'intv)
+		(cond ((Math-zerop (nth 2 a)) 6)
+		      ((Math-zerop (nth 3 a)) 3)
+		      (t 7)))
+	       ((eq (car a) 'sdev)
+		(if (math-known-realp (nth 1 a)) 7 15))
+	       (t 8)))
+	((memq (car a) '(+ -))
+	 (cond ((Math-realp (nth 1 a))
+		(if (eq (car a) '-)
+		    (math-neg-signs
+		     (math-possible-signs (nth 2 a)
+					  (if origin
+					      (math-add origin (nth 1 a))
+					    (nth 1 a))))
+		  (math-possible-signs (nth 2 a)
+				       (if origin
+					   (math-sub origin (nth 1 a))
+					 (math-neg (nth 1 a))))))
+	       ((Math-realp (nth 2 a))
+		(let ((org (if (eq (car a) '-)
+			       (nth 2 a)
+			     (math-neg (nth 2 a)))))
+		  (math-possible-signs (nth 1 a)
+				       (if origin
+					   (math-add origin org)
+					 org))))
+	       (t
+		(let ((s1 (math-possible-signs (nth 1 a) origin))
+		      (s2 (math-possible-signs (nth 2 a))))
+		  (if (eq (car a) '-) (setq s2 (math-neg-signs s2)))
+		  (cond ((eq s1 s2) s1)
+			((eq s1 2) s2)
+			((eq s2 2) s1)
+			((>= s1 8) 15)
+			((>= s2 8) 15)
+			((and (eq s1 4) (eq s2 6)) 4)
+			((and (eq s2 4) (eq s1 6)) 4)
+			((and (eq s1 1) (eq s2 3)) 1)
+			((and (eq s2 1) (eq s1 3)) 1)
+			(t 7))))))
+	((eq (car a) 'neg)
+	 (math-neg-signs (math-possible-signs
+			  (nth 1 a)
+			  (and origin (math-neg origin)))))
+	((and origin (Math-zerop origin) (setq origin nil)
+	      nil))
+	((and (or (eq (car a) '*)
+		  (and (eq (car a) '/) origin))
+	      (Math-realp (nth 1 a)))
+	 (let ((s (if (eq (car a) '*)
+		      (if (Math-zerop (nth 1 a))
+			  (math-possible-signs 0 origin)
+			(math-possible-signs (nth 2 a)
+					     (math-div (or origin 0)
+						       (nth 1 a))))
+		    (math-neg-signs
+		     (math-possible-signs (nth 2 a)
+					  (math-div (nth 1 a)
+						    origin))))))
+	   (if (Math-negp (nth 1 a)) (math-neg-signs s) s)))
+	((and (memq (car a) '(* /)) (Math-realp (nth 2 a)))
+	 (let ((s (math-possible-signs (nth 1 a)
+				       (if (eq (car a) '*)
+					   (math-mul (or origin 0) (nth 2 a))
+					 (math-div (or origin 0) (nth 2 a))))))
+	   (if (Math-negp (nth 2 a)) (math-neg-signs s) s)))
+	((eq (car a) 'vec)
+	 (let ((signs 0))
+	   (while (and (setq a (cdr a)) (< signs 15))
+	     (setq signs (logior signs (math-possible-signs
+					(car a) origin))))
+	   signs))
+	(t (let ((sign
+		  (cond
+		   ((memq (car a) '(* /))
+		    (let ((s1 (math-possible-signs (nth 1 a)))
+			  (s2 (math-possible-signs (nth 2 a))))
+		      (cond ((>= s1 8) 15)
+			    ((>= s2 8) 15)
+			    ((and (eq (car a) '/) (memq s2 '(2 3 6 7))) 15)
+			    (t
+			     (logior (if (memq s1 '(4 5 6 7)) s2 0)
+				     (if (memq s1 '(2 3 6 7)) 2 0)
+				     (if (memq s1 '(1 3 5 7))
+					 (math-neg-signs s2) 0))))))
+		   ((eq (car a) '^)
+		    (let ((s1 (math-possible-signs (nth 1 a)))
+			  (s2 (math-possible-signs (nth 2 a))))
+		      (cond ((>= s1 8) 15)
+			    ((>= s2 8) 15)
+			    ((eq s1 4) 4)
+			    ((eq s1 2) (if (eq s2 4) 2 15))
+			    ((eq s2 2) (if (memq s1 '(1 5)) 2 15))
+			    ((Math-integerp (nth 2 a))
+			     (if (math-evenp (nth 2 a))
+				 (if (memq s1 '(3 6 7)) 6 4)
+			       s1))
+			    ((eq s1 6) (if (eq s2 4) 6 15))
+			    (t 7))))
+		   ((eq (car a) '%)
+		    (let ((s2 (math-possible-signs (nth 2 a))))
+		      (cond ((>= s2 8) 7)
+			    ((eq s2 2) 2)
+			    ((memq s2 '(4 6)) 6)
+			    ((memq s2 '(1 3)) 3)
+			    (t 7))))
+		   ((and (memq (car a) '(calcFunc-abs calcFunc-abssqr))
+			 (= (length a) 2))
+		    (let ((s1 (math-possible-signs (nth 1 a))))
+		      (cond ((eq s1 2) 2)
+			    ((memq s1 '(1 4 5)) 4)
+			    (t 6))))
+		   ((and (eq (car a) 'calcFunc-exp) (= (length a) 2))
+		    (let ((s1 (math-possible-signs (nth 1 a))))
+		      (if (>= s1 8)
+			  15
+			(if (or (not origin) (math-negp origin))
+			    4
+			  (setq origin (math-sub (or origin 0) 1))
+			  (if (Math-zerop origin) (setq origin nil))
+			  s1))))
+		   ((or (and (memq (car a) '(calcFunc-ln calcFunc-log10))
+			     (= (length a) 2))
+			(and (eq (car a) 'calcFunc-log)
+			     (= (length a) 3)
+			     (math-known-posp (nth 2 a))))
+		    (if (math-known-nonnegp (nth 1 a))
+			(math-possible-signs (nth 1 a) 1)
+		      15))
+		   ((and (eq (car a) 'calcFunc-sqrt) (= (length a) 2))
+		    (let ((s1 (math-possible-signs (nth 1 a))))
+		      (if (memq s1 '(2 4 6)) s1 15)))
+		   ((memq (car a) math-nonnegative-functions) 6)
+		   ((memq (car a) math-positive-functions) 4)
+		   ((memq (car a) math-real-functions) 7)
+		   ((memq (car a) math-real-scalar-functions) 7)
+		   ((and (memq (car a) math-real-if-arg-functions)
+			 (= (length a) 2))
+		    (if (math-known-realp (nth 1 a)) 7 15)))))
+	     (cond (sign
+		    (if origin
+			(+ (logand sign 8)
+			   (if (Math-posp origin)
+			       (if (memq sign '(1 2 3 8 9 10 11)) 1 7)
+			     (if (memq sign '(2 4 6 8 10 12 14)) 4 7)))
+		      sign))
+		   ((math-const-var a)
+		    (cond ((eq (nth 2 a) 'var-pi)
+			   (if origin
+			       (math-possible-signs (math-pi) origin)
+			     4))
+			  ((eq (nth 2 a) 'var-e)
+			   (if origin
+			       (math-possible-signs (math-e) origin)
+			     4))
+			  ((eq (nth 2 a) 'var-inf) 4)
+			  ((eq (nth 2 a) 'var-uinf) 13)
+			  ((eq (nth 2 a) 'var-i) 8)
+			  (t 15)))
+		   (t
+		    (math-setup-declarations)
+		    (let ((decl (if (eq (car a) 'var)
+				    (or (assq (nth 2 a) math-decls-cache)
+					math-decls-all)
+				  (assq (car a) math-decls-cache))))
+		      (if (and origin
+			       (memq 'int (nth 1 decl))
+			       (not (Math-num-integerp origin)))
+			  5
+			(if (nth 2 decl)
+			    (math-possible-signs (nth 2 decl) origin)
+			  (if (memq 'real (nth 1 decl))
+			      7
+			    15)))))))))
+)
+
+(defun math-neg-signs (s1)
+  (if (>= s1 8)
+      (+ 8 (math-neg-signs (- s1 8)))
+    (+ (if (memq s1 '(1 3 5 7)) 4 0)
+       (if (memq s1 '(2 3 6 7)) 2 0)
+       (if (memq s1 '(4 5 6 7)) 1 0)))
+)
+
+
+;;; Try to prove that A is an integer.
+(defun math-known-integerp (a)
+  (eq (math-possible-types a) 1)
+)
+
+(defun math-known-num-integerp (a)
+  (<= (math-possible-types a t) 3)
+)
+
+(defun math-known-imagp (a)
+  (= (math-possible-types a) 16)
+)
+
+
+;;; Find the possible types of A.
+;;; Returns an integer with bits:  1  may be integer.
+;;;				   2  may be integer-valued float.
+;;;				   4  may be fraction.
+;;;				   8  may be non-integer-valued float.
+;;;				  16  may be imaginary.
+;;;				  32  may be non-real, non-imaginary.
+;;; Real infinities count as integers for the purposes of this function.
+(defun math-possible-types (a &optional num)
+  (cond ((Math-objectp a)
+	 (cond ((Math-integerp a) (if num 3 1))
+	       ((Math-messy-integerp a) (if num 3 2))
+	       ((eq (car a) 'frac) (if num 12 4))
+	       ((eq (car a) 'float) (if num 12 8))
+	       ((eq (car a) 'intv)
+		(if (equal (nth 2 a) (nth 3 a))
+		    (math-possible-types (nth 2 a))
+		  15))
+	       ((eq (car a) 'sdev)
+		(if (math-known-realp (nth 1 a)) 15 63))
+	       ((eq (car a) 'cplx)
+		(if (math-zerop (nth 1 a)) 16 32))
+	       ((eq (car a) 'polar)
+		(if (or (Math-equal (nth 2 a) (math-quarter-circle nil))
+			(Math-equal (nth 2 a)
+				    (math-neg (math-quarter-circle nil))))
+		    16 48))
+	       (t 63)))
+	((eq (car a) '/)
+	 (let* ((t1 (math-possible-types (nth 1 a) num))
+		(t2 (math-possible-types (nth 2 a) num))
+		(t12 (logior t1 t2)))
+	   (if (< t12 16)
+	       (if (> (logand t12 10) 0)
+		   10
+		 (if (or (= t1 4) (= t2 4) calc-prefer-frac)
+		     5
+		   15))
+	     (if (< t12 32)
+		 (if (= t1 16)
+		     (if (= t2 16) 15
+		       (if (< t2 16) 16 31))
+		   (if (= t2 16)
+		       (if (< t1 16) 16 31)
+		     31))
+	       63))))
+	((memq (car a) '(+ - * %))
+	 (let* ((t1 (math-possible-types (nth 1 a) num))
+		(t2 (math-possible-types (nth 2 a) num))
+		(t12 (logior t1 t2)))
+	   (if (eq (car a) '%)
+	       (setq t1 (logand t1 15) t2 (logand t2 15) t12 (logand t12 15)))
+	   (if (< t12 16)
+	       (let ((mask (if (<= t12 3)
+			       1
+			     (if (and (or (and (<= t1 3) (= (logand t2 3) 0))
+					  (and (<= t2 3) (= (logand t1 3) 0)))
+				      (memq (car a) '(+ -)))
+				 4
+			       5))))
+		 (if num
+		     (* mask 3)
+		   (logior (if (and (> (logand t1 5) 0) (> (logand t2 5) 0))
+			       mask 0)
+			   (if (> (logand t12 10) 0)
+			       (* mask 2) 0))))
+	     (if (< t12 32)
+		 (if (eq (car a) '*)
+		     (if (= t1 16)
+			 (if (= t2 16) 15
+			   (if (< t2 16) 16 31))
+		       (if (= t2 16)
+			   (if (< t1 16) 16 31)
+			 31))
+		   (if (= t12 16) 16
+		     (if (or (and (= t1 16) (< t2 16))
+			     (and (= t2 16) (< t1 16))) 32 63)))
+	       63))))
+	((eq (car a) 'neg)
+	 (math-possible-types (nth 1 a)))
+	((eq (car a) '^)
+	 (let* ((t1 (math-possible-types (nth 1 a) num))
+		(t2 (math-possible-types (nth 2 a) num))
+		(t12 (logior t1 t2)))
+	   (if (and (<= t2 3) (math-known-nonnegp (nth 2 a)) (< t1 16))
+	       (let ((mask (logior (if (> (logand t1 3) 0) 1 0)
+				   (logand t1 4)
+				   (if (> (logand t1 12) 0) 5 0))))
+		 (if num
+		     (* mask 3)
+		   (logior (if (and (> (logand t1 5) 0) (> (logand t2 5) 0))
+			       mask 0)
+			   (if (> (logand t12 10) 0)
+			       (* mask 2) 0))))
+	     (if (and (math-known-nonnegp (nth 1 a))
+		      (math-known-posp (nth 2 a)))
+		 15
+	       63))))
+	((eq (car a) 'calcFunc-sqrt)
+	 (let ((t1 (math-possible-signs (nth 1 a))))
+	   (logior (if (> (logand t1 2) 0) 3 0)
+		   (if (> (logand t1 1) 0) 16 0)
+		   (if (> (logand t1 4) 0) 15 0)
+		   (if (> (logand t1 8) 0) 32 0))))
+	((eq (car a) 'vec)
+	 (let ((types 0))
+	   (while (and (setq a (cdr a)) (< types 63))
+	     (setq types (logior types (math-possible-types (car a) t))))
+	   types))
+	((or (memq (car a) math-integer-functions)
+	     (and (memq (car a) math-rounding-functions)
+		  (math-known-nonnegp (or (nth 2 a) 0))))
+	 1)
+	((or (memq (car a) math-num-integer-functions)
+	     (and (memq (car a) math-float-rounding-functions)
+		  (math-known-nonnegp (or (nth 2 a) 0))))
+	 2)
+	((eq (car a) 'calcFunc-frac)
+	 5)
+	((and (eq (car a) 'calcFunc-float) (= (length a) 2))
+	 (let ((t1 (math-possible-types (nth 1 a))))
+	   (logior (if (> (logand t1 3) 0) 2 0)
+		   (if (> (logand t1 12) 0) 8 0)
+		   (logand t1 48))))
+	((and (memq (car a) '(calcFunc-abs calcFunc-abssqr))
+	      (= (length a) 2))
+	 (let ((t1 (math-possible-types (nth 1 a))))
+	   (if (>= t1 16)
+	       15
+	     t1)))
+	((math-const-var a)
+	 (cond ((memq (nth 2 a) '(var-e var-pi var-phi var-gamma)) 8)
+	       ((eq (nth 2 a) 'var-inf) 1)
+	       ((eq (nth 2 a) 'var-i) 16)
+	       (t 63)))
+	(t
+	 (math-setup-declarations)
+	 (let ((decl (if (eq (car a) 'var)
+			 (or (assq (nth 2 a) math-decls-cache)
+			     math-decls-all)
+		       (assq (car a) math-decls-cache))))
+	   (cond ((memq 'int (nth 1 decl))
+		  1)
+		 ((memq 'numint (nth 1 decl))
+		  3)
+		 ((memq 'frac (nth 1 decl))
+		  4)
+		 ((memq 'rat (nth 1 decl))
+		  5)
+		 ((memq 'float (nth 1 decl))
+		  10)
+		 ((nth 2 decl)
+		  (math-possible-types (nth 2 decl)))
+		 ((memq 'real (nth 1 decl))
+		  15)
+		 (t 63)))))
+)
+
+(defun math-known-evenp (a)
+  (cond ((Math-integerp a)
+	 (math-evenp a))
+	((Math-messy-integerp a)
+	 (or (> (nth 2 a) 0)
+	     (math-evenp (math-trunc a))))
+	((eq (car a) '*)
+	 (if (math-known-evenp (nth 1 a))
+	     (math-known-num-integerp (nth 2 a))
+	   (if (math-known-num-integerp (nth 1 a))
+	       (math-known-evenp (nth 2 a)))))
+	((memq (car a) '(+ -))
+	 (or (and (math-known-evenp (nth 1 a))
+		  (math-known-evenp (nth 2 a)))
+	     (and (math-known-oddp (nth 1 a))
+		  (math-known-oddp (nth 2 a)))))
+	((eq (car a) 'neg)
+	 (math-known-evenp (nth 1 a))))
+)
+
+(defun math-known-oddp (a)
+  (cond ((Math-integerp a)
+	 (math-oddp a))
+	((Math-messy-integerp a)
+	 (and (<= (nth 2 a) 0)
+	      (math-oddp (math-trunc a))))
+	((memq (car a) '(+ -))
+	 (or (and (math-known-evenp (nth 1 a))
+		  (math-known-oddp (nth 2 a)))
+	     (and (math-known-oddp (nth 1 a))
+		  (math-known-evenp (nth 2 a)))))
+	((eq (car a) 'neg)
+	 (math-known-oddp (nth 1 a))))
+)
+
+
+(defun calcFunc-dreal (expr)
+  (let ((types (math-possible-types expr)))
+    (if (< types 16) 1
+      (if (= (logand types 15) 0) 0
+	(math-reject-arg expr 'realp 'quiet))))
+)
+
+(defun calcFunc-dimag (expr)
+  (let ((types (math-possible-types expr)))
+    (if (= types 16) 1
+      (if (= (logand types 16) 0) 0
+	(math-reject-arg expr "Expected an imaginary number"))))
+)
+
+(defun calcFunc-dpos (expr)
+  (let ((signs (math-possible-signs expr)))
+    (if (eq signs 4) 1
+      (if (memq signs '(1 2 3)) 0
+	(math-reject-arg expr 'posp 'quiet))))
+)
+
+(defun calcFunc-dneg (expr)
+  (let ((signs (math-possible-signs expr)))
+    (if (eq signs 1) 1
+      (if (memq signs '(2 4 6)) 0
+	(math-reject-arg expr 'negp 'quiet))))
+)
+
+(defun calcFunc-dnonneg (expr)
+  (let ((signs (math-possible-signs expr)))
+    (if (memq signs '(2 4 6)) 1
+      (if (eq signs 1) 0
+	(math-reject-arg expr 'posp 'quiet))))
+)
+
+(defun calcFunc-dnonzero (expr)
+  (let ((signs (math-possible-signs expr)))
+    (if (memq signs '(1 4 5 8 9 12 13)) 1
+      (if (eq signs 2) 0
+	(math-reject-arg expr 'nonzerop 'quiet))))
+)
+
+(defun calcFunc-dint (expr)
+  (let ((types (math-possible-types expr)))
+    (if (= types 1) 1
+      (if (= (logand types 1) 0) 0
+	(math-reject-arg expr 'integerp 'quiet))))
+)
+
+(defun calcFunc-dnumint (expr)
+  (let ((types (math-possible-types expr t)))
+    (if (<= types 3) 1
+      (if (= (logand types 3) 0) 0
+	(math-reject-arg expr 'integerp 'quiet))))
+)
+
+(defun calcFunc-dnatnum (expr)
+  (let ((res (calcFunc-dint expr)))
+    (if (eq res 1)
+	(calcFunc-dnonneg expr)
+      res))
+)
+
+(defun calcFunc-deven (expr)
+  (if (math-known-evenp expr)
+      1
+    (if (or (math-known-oddp expr)
+	    (= (logand (math-possible-types expr) 3) 0))
+	0
+      (math-reject-arg expr "Can't tell if expression is odd or even")))
+)
+
+(defun calcFunc-dodd (expr)
+  (if (math-known-oddp expr)
+      1
+    (if (or (math-known-evenp expr)
+	    (= (logand (math-possible-types expr) 3) 0))
+	0
+      (math-reject-arg expr "Can't tell if expression is odd or even")))
+)
+
+(defun calcFunc-drat (expr)
+  (let ((types (math-possible-types expr)))
+    (if (memq types '(1 4 5)) 1
+      (if (= (logand types 5) 0) 0
+	(math-reject-arg expr "Rational number expected"))))
+)
+
+(defun calcFunc-drange (expr)
+  (math-setup-declarations)
+  (let (range)
+    (if (Math-realp expr)
+	(list 'vec expr)
+      (if (eq (car-safe expr) 'intv)
+	  expr
+	(if (eq (car-safe expr) 'var)
+	    (setq range (nth 2 (or (assq (nth 2 expr) math-decls-cache)
+				   math-decls-all)))
+	  (setq range (nth 2 (assq (car-safe expr) math-decls-cache))))
+	(if range
+	    (math-clean-set (copy-sequence range))
+	  (setq range (math-possible-signs expr))
+	  (if (< range 8)
+	      (aref [(vec)
+		     (intv 2 (neg (var inf var-inf)) 0)
+		     (vec 0)
+		     (intv 3 (neg (var inf var-inf)) 0)
+		     (intv 1 0 (var inf var-inf))
+		     (vec (intv 2 (neg (var inf var-inf)) 0)
+			  (intv 1 0 (var inf var-inf)))
+		     (intv 3 0 (var inf var-inf))
+		     (intv 3 (neg (var inf var-inf)) (var inf var-inf))] range)
+	    (math-reject-arg expr 'realp 'quiet))))))
+)
+
+(defun calcFunc-dscalar (a)
+  (if (math-known-scalarp a) 1
+    (if (math-known-matrixp a) 0
+      (math-reject-arg a 'objectp 'quiet)))
+)
+
+
+;;; The following lists are not exhaustive.
+(defvar math-scalar-functions '(calcFunc-det
+				calcFunc-cnorm calcFunc-rnorm
+				calcFunc-vlen calcFunc-vcount
+				calcFunc-vsum calcFunc-vprod
+				calcFunc-vmin calcFunc-vmax
+))
+
+(defvar math-nonscalar-functions '(vec calcFunc-idn calcFunc-diag
+				       calcFunc-cvec calcFunc-index
+				       calcFunc-trn
+				       | calcFunc-append
+				       calcFunc-cons calcFunc-rcons
+				       calcFunc-tail calcFunc-rhead
+))
+
+(defvar math-scalar-if-args-functions '(+ - * / neg))
+
+(defvar math-real-functions '(calcFunc-arg
+			      calcFunc-re calcFunc-im
+			      calcFunc-floor calcFunc-ceil
+			      calcFunc-trunc calcFunc-round
+			      calcFunc-rounde calcFunc-roundu
+			      calcFunc-ffloor calcFunc-fceil
+			      calcFunc-ftrunc calcFunc-fround
+			      calcFunc-frounde calcFunc-froundu
+))
+
+(defvar math-positive-functions '(
+))
+
+(defvar math-nonnegative-functions '(calcFunc-cnorm calcFunc-rnorm
+				     calcFunc-vlen calcFunc-vcount
+))
+
+(defvar math-real-scalar-functions '(% calcFunc-idiv calcFunc-abs
+				       calcFunc-choose calcFunc-perm
+				       calcFunc-eq calcFunc-neq
+				       calcFunc-lt calcFunc-gt
+				       calcFunc-leq calcFunc-geq
+				       calcFunc-lnot
+				       calcFunc-max calcFunc-min
+))
+
+(defvar math-real-if-arg-functions '(calcFunc-sin calcFunc-cos
+				     calcFunc-tan calcFunc-arctan
+				     calcFunc-sinh calcFunc-cosh
+				     calcFunc-tanh calcFunc-exp
+				     calcFunc-gamma calcFunc-fact
+))
+
+(defvar math-integer-functions '(calcFunc-idiv
+				 calcFunc-isqrt calcFunc-ilog
+				 calcFunc-vlen calcFunc-vcount
+))
+
+(defvar math-num-integer-functions '(
+))
+
+(defvar math-rounding-functions '(calcFunc-floor
+				  calcFunc-ceil
+				  calcFunc-round calcFunc-trunc
+				  calcFunc-rounde calcFunc-roundu
+))
+
+(defvar math-float-rounding-functions '(calcFunc-ffloor
+					calcFunc-fceil
+					calcFunc-fround calcFunc-ftrunc
+					calcFunc-frounde calcFunc-froundu
+))
+
+(defvar math-integer-if-args-functions '(+ - * % neg calcFunc-abs
+					   calcFunc-min calcFunc-max
+					   calcFunc-choose calcFunc-perm
+))
+
+
+;;;; Arithmetic.
+
+(defun calcFunc-neg (a)
+  (math-normalize (list 'neg a))
+)
+
+(defun math-neg-fancy (a)
+  (cond ((eq (car a) 'polar)
+	 (list 'polar
+	       (nth 1 a)
+	       (if (math-posp (nth 2 a))
+		   (math-sub (nth 2 a) (math-half-circle nil))
+		 (math-add (nth 2 a) (math-half-circle nil)))))
+	((eq (car a) 'mod)
+	 (if (math-zerop (nth 1 a))
+	     a
+	   (list 'mod (math-sub (nth 2 a) (nth 1 a)) (nth 2 a))))
+	((eq (car a) 'sdev)
+	 (list 'sdev (math-neg (nth 1 a)) (nth 2 a)))
+	((eq (car a) 'intv)
+	 (math-make-intv (aref [0 2 1 3] (nth 1 a))
+			 (math-neg (nth 3 a))
+			 (math-neg (nth 2 a))))
+	((and math-simplify-only
+	      (not (equal a math-simplify-only)))
+	 (list 'neg a))
+	((eq (car a) '+)
+	 (math-sub (math-neg (nth 1 a)) (nth 2 a)))
+	((eq (car a) '-)
+	 (math-sub (nth 2 a) (nth 1 a)))
+	((and (memq (car a) '(* /))
+	      (math-okay-neg (nth 1 a)))
+	 (list (car a) (math-neg (nth 1 a)) (nth 2 a)))
+	((and (memq (car a) '(* /))
+	      (math-okay-neg (nth 2 a)))
+	 (list (car a) (nth 1 a) (math-neg (nth 2 a))))
+	((and (memq (car a) '(* /))
+	      (or (math-objectp (nth 1 a))
+		  (and (eq (car (nth 1 a)) '*)
+		       (math-objectp (nth 1 (nth 1 a))))))
+	 (list (car a) (math-neg (nth 1 a)) (nth 2 a)))
+	((and (eq (car a) '/)
+	      (or (math-objectp (nth 2 a))
+		  (and (eq (car (nth 2 a)) '*)
+		       (math-objectp (nth 1 (nth 2 a))))))
+	 (list (car a) (nth 1 a) (math-neg (nth 2 a))))
+	((and (eq (car a) 'var) (memq (nth 2 a) '(var-uinf var-nan)))
+	 a)
+	((eq (car a) 'neg)
+	 (nth 1 a))
+	(t (list 'neg a)))
+)
+
+(defun math-okay-neg (a)
+  (or (math-looks-negp a)
+      (eq (car-safe a) '-))
+)
+
+(defun math-neg-float (a)
+  (list 'float (Math-integer-neg (nth 1 a)) (nth 2 a))
+)
+
+
+(defun calcFunc-add (&rest rest)
+  (if rest
+      (let ((a (car rest)))
+	(while (setq rest (cdr rest))
+	  (setq a (list '+ a (car rest))))
+	(math-normalize a))
+    0)
+)
+
+(defun calcFunc-sub (&rest rest)
+  (if rest
+      (let ((a (car rest)))
+	(while (setq rest (cdr rest))
+	  (setq a (list '- a (car rest))))
+	(math-normalize a))
+    0)
+)
+
+(defun math-add-objects-fancy (a b)
+  (cond ((and (Math-numberp a) (Math-numberp b))
+	 (let ((aa (math-complex a))
+	       (bb (math-complex b)))
+	   (math-normalize
+	    (let ((res (list 'cplx
+			     (math-add (nth 1 aa) (nth 1 bb))
+			     (math-add (nth 2 aa) (nth 2 bb)))))
+	      (if (math-want-polar a b)
+		  (math-polar res)
+		res)))))
+	((or (Math-vectorp a) (Math-vectorp b))
+	 (math-map-vec-2 'math-add a b))
+	((eq (car-safe a) 'sdev)
+	 (if (eq (car-safe b) 'sdev)
+	     (math-make-sdev (math-add (nth 1 a) (nth 1 b))
+			     (math-hypot (nth 2 a) (nth 2 b)))
+	   (and (or (Math-scalarp b)
+		    (not (Math-objvecp b)))
+		(math-make-sdev (math-add (nth 1 a) b) (nth 2 a)))))
+	((and (eq (car-safe b) 'sdev)
+	      (or (Math-scalarp a)
+		  (not (Math-objvecp a))))
+	 (math-make-sdev (math-add a (nth 1 b)) (nth 2 b)))
+	((eq (car-safe a) 'intv)
+	 (if (eq (car-safe b) 'intv)
+	     (math-make-intv (logior (logand (nth 1 a) (nth 1 b))
+				     (if (equal (nth 2 a)
+						'(neg (var inf var-inf)))
+					 (logand (nth 1 a) 2) 0)
+				     (if (equal (nth 2 b)
+						'(neg (var inf var-inf)))
+					 (logand (nth 1 b) 2) 0)
+				     (if (equal (nth 3 a) '(var inf var-inf))
+					 (logand (nth 1 a) 1) 0)
+				     (if (equal (nth 3 b) '(var inf var-inf))
+					 (logand (nth 1 b) 1) 0))
+			     (math-add (nth 2 a) (nth 2 b))
+			     (math-add (nth 3 a) (nth 3 b)))
+	   (and (or (Math-anglep b)
+		    (eq (car b) 'date)
+		    (not (Math-objvecp b)))
+		(math-make-intv (nth 1 a)
+				(math-add (nth 2 a) b)
+				(math-add (nth 3 a) b)))))
+	((and (eq (car-safe b) 'intv)
+	      (or (Math-anglep a)
+		  (eq (car a) 'date)
+		  (not (Math-objvecp a))))
+	 (math-make-intv (nth 1 b)
+			 (math-add a (nth 2 b))
+			 (math-add a (nth 3 b))))
+	((eq (car-safe a) 'date)
+	 (cond ((eq (car-safe b) 'date)
+		(math-add (nth 1 a) (nth 1 b)))
+	       ((eq (car-safe b) 'hms)
+		(let ((parts (math-date-parts (nth 1 a))))
+		  (list 'date
+			(math-add (car parts)   ; this minimizes roundoff
+				  (math-div (math-add
+					     (math-add (nth 1 parts)
+						       (nth 2 parts))
+					     (math-add
+					      (math-mul (nth 1 b) 3600)
+					      (math-add (math-mul (nth 2 b) 60)
+							(nth 3 b))))
+					    86400)))))
+	       ((Math-realp b)
+		(list 'date (math-add (nth 1 a) b)))
+	       (t nil)))
+	((eq (car-safe b) 'date)
+	 (math-add-objects-fancy b a))
+	((and (eq (car-safe a) 'mod)
+	      (eq (car-safe b) 'mod)
+	      (equal (nth 2 a) (nth 2 b)))
+	 (math-make-mod (math-add (nth 1 a) (nth 1 b)) (nth 2 a)))
+	((and (eq (car-safe a) 'mod)
+	      (Math-anglep b))
+	 (math-make-mod (math-add (nth 1 a) b) (nth 2 a)))
+	((and (eq (car-safe b) 'mod)
+	      (Math-anglep a))
+	 (math-make-mod (math-add a (nth 1 b)) (nth 2 b)))
+	((and (or (eq (car-safe a) 'hms) (eq (car-safe b) 'hms))
+	      (and (Math-anglep a) (Math-anglep b)))
+	 (or (eq (car-safe a) 'hms) (setq a (math-to-hms a)))
+	 (or (eq (car-safe b) 'hms) (setq b (math-to-hms b)))
+	 (math-normalize
+	  (if (math-negp a)
+	      (math-neg (math-add (math-neg a) (math-neg b)))
+	    (if (math-negp b)
+		(let* ((s (math-add (nth 3 a) (nth 3 b)))
+		       (m (math-add (nth 2 a) (nth 2 b)))
+		       (h (math-add (nth 1 a) (nth 1 b))))
+		  (if (math-negp s)
+		      (setq s (math-add s 60)
+			    m (math-add m -1)))
+		  (if (math-negp m)
+		      (setq m (math-add m 60)
+			    h (math-add h -1)))
+		  (if (math-negp h)
+		      (math-add b a)
+		    (list 'hms h m s)))
+	      (let* ((s (math-add (nth 3 a) (nth 3 b)))
+		     (m (math-add (nth 2 a) (nth 2 b)))
+		     (h (math-add (nth 1 a) (nth 1 b))))
+		(list 'hms h m s))))))
+	(t (calc-record-why "*Incompatible arguments for +" a b)))
+)
+
+(defun math-add-symb-fancy (a b)
+  (or (and math-simplify-only
+	   (not (equal a math-simplify-only))
+	   (list '+ a b))
+      (and (eq (car-safe b) '+)
+	   (math-add (math-add a (nth 1 b))
+		     (nth 2 b)))
+      (and (eq (car-safe b) '-)
+	   (math-sub (math-add a (nth 1 b))
+		     (nth 2 b)))
+      (and (eq (car-safe b) 'neg)
+	   (eq (car-safe (nth 1 b)) '+)
+	   (math-sub (math-sub a (nth 1 (nth 1 b)))
+		     (nth 2 (nth 1 b))))
+      (and (or (and (Math-vectorp a) (math-known-scalarp b))
+	       (and (Math-vectorp b) (math-known-scalarp a)))
+	   (math-map-vec-2 'math-add a b))
+      (let ((inf (math-infinitep a)))
+	(cond
+	 (inf
+	  (let ((inf2 (math-infinitep b)))
+	    (if inf2
+		(if (or (memq (nth 2 inf) '(var-uinf var-nan))
+			(memq (nth 2 inf2) '(var-uinf var-nan)))
+		    '(var nan var-nan)
+		  (let ((dir (math-infinite-dir a inf))
+			(dir2 (math-infinite-dir b inf2)))
+		    (if (and (Math-objectp dir) (Math-objectp dir2))
+			(if (Math-equal dir dir2)
+			    a
+			  '(var nan var-nan)))))
+	      (if (and (equal a '(var inf var-inf))
+		       (eq (car-safe b) 'intv)
+		       (memq (nth 1 b) '(2 3))
+		       (equal (nth 2 b) '(neg (var inf var-inf))))
+		  (list 'intv 3 (nth 2 b) a)
+		(if (and (equal a '(neg (var inf var-inf)))
+			 (eq (car-safe b) 'intv)
+			 (memq (nth 1 b) '(1 3))
+			 (equal (nth 3 b) '(var inf var-inf)))
+		    (list 'intv 3 a (nth 3 b))
+		  a)))))
+	 ((math-infinitep b)
+	  (if (eq (car-safe a) 'intv)
+	      (math-add b a)
+	    b))
+	 ((eq (car-safe a) '+)
+	  (let ((temp (math-combine-sum (nth 2 a) b nil nil t)))
+	    (and temp
+		 (math-add (nth 1 a) temp))))
+	 ((eq (car-safe a) '-)
+	  (let ((temp (math-combine-sum (nth 2 a) b t nil t)))
+	    (and temp
+		 (math-add (nth 1 a) temp))))
+	 ((and (Math-objectp a) (Math-objectp b))
+	  nil)
+	 (t
+	  (math-combine-sum a b nil nil nil))))
+      (and (Math-looks-negp b)
+	   (list '- a (math-neg b)))
+      (and (Math-looks-negp a)
+	   (list '- b (math-neg a)))
+      (and (eq (car-safe a) 'calcFunc-idn)
+	   (= (length a) 2)
+	   (or (and (eq (car-safe b) 'calcFunc-idn)
+		    (= (length b) 2)
+		    (list 'calcFunc-idn (math-add (nth 1 a) (nth 1 b))))
+	       (and (math-square-matrixp b)
+		    (math-add (math-mimic-ident (nth 1 a) b) b))
+	       (and (math-known-scalarp b)
+		    (math-add (nth 1 a) b))))
+      (and (eq (car-safe b) 'calcFunc-idn)
+	   (= (length a) 2)
+	   (or (and (math-square-matrixp a)
+		    (math-add a (math-mimic-ident (nth 1 b) a)))
+	       (and (math-known-scalarp a)
+		    (math-add a (nth 1 b)))))
+      (list '+ a b))
+)
+
+
+(defun calcFunc-mul (&rest rest)
+  (if rest
+      (let ((a (car rest)))
+	(while (setq rest (cdr rest))
+	  (setq a (list '* a (car rest))))
+	(math-normalize a))
+    1)
+)
+
+(defun math-mul-objects-fancy (a b)
+  (cond ((and (Math-numberp a) (Math-numberp b))
+	 (math-normalize
+	  (if (math-want-polar a b)
+	      (let ((a (math-polar a))
+		    (b (math-polar b)))
+		(list 'polar
+		      (math-mul (nth 1 a) (nth 1 b))
+		      (math-fix-circular (math-add (nth 2 a) (nth 2 b)))))
+	    (setq a (math-complex a)
+		  b (math-complex b))
+	    (list 'cplx
+		  (math-sub (math-mul (nth 1 a) (nth 1 b))
+			    (math-mul (nth 2 a) (nth 2 b)))
+		  (math-add (math-mul (nth 1 a) (nth 2 b))
+			    (math-mul (nth 2 a) (nth 1 b)))))))
+	((Math-vectorp a)
+	 (if (Math-vectorp b)
+	     (if (math-matrixp a)
+		 (if (math-matrixp b)
+		     (if (= (length (nth 1 a)) (length b))
+			 (math-mul-mats a b)
+		       (math-dimension-error))
+		   (if (= (length (nth 1 a)) 2)
+		       (if (= (length a) (length b))
+			   (math-mul-mats a (list 'vec b))
+			 (math-dimension-error))
+		     (if (= (length (nth 1 a)) (length b))
+			 (math-mul-mat-vec a b)
+		       (math-dimension-error))))
+	       (if (math-matrixp b)
+		   (if (= (length a) (length b))
+		       (nth 1 (math-mul-mats (list 'vec a) b))
+		     (math-dimension-error))
+		 (if (= (length a) (length b))
+		     (math-dot-product a b)
+		   (math-dimension-error))))
+	   (math-map-vec-2 'math-mul a b)))
+	((Math-vectorp b)
+	 (math-map-vec-2 'math-mul a b))
+	((eq (car-safe a) 'sdev)
+	 (if (eq (car-safe b) 'sdev)
+	     (math-make-sdev (math-mul (nth 1 a) (nth 1 b))
+			     (math-hypot (math-mul (nth 2 a) (nth 1 b))
+					 (math-mul (nth 2 b) (nth 1 a))))
+	   (and (or (Math-scalarp b)
+		    (not (Math-objvecp b)))
+		(math-make-sdev (math-mul (nth 1 a) b)
+				(math-mul (nth 2 a) b)))))
+	((and (eq (car-safe b) 'sdev)
+	      (or (Math-scalarp a)
+		  (not (Math-objvecp a))))
+	 (math-make-sdev (math-mul a (nth 1 b)) (math-mul a (nth 2 b))))
+	((and (eq (car-safe a) 'intv) (Math-anglep b))
+	 (if (Math-negp b)
+	     (math-neg (math-mul a (math-neg b)))
+	   (math-make-intv (nth 1 a)
+			   (math-mul (nth 2 a) b)
+			   (math-mul (nth 3 a) b))))
+	((and (eq (car-safe b) 'intv) (Math-anglep a))
+	 (math-mul b a))
+	((and (eq (car-safe a) 'intv) (math-intv-constp a)
+	      (eq (car-safe b) 'intv) (math-intv-constp b))
+	 (let ((lo (math-mul a (nth 2 b)))
+	       (hi (math-mul a (nth 3 b))))
+	   (or (eq (car-safe lo) 'intv)
+	       (setq lo (list 'intv (if (memq (nth 1 b) '(2 3)) 3 0) lo lo)))
+	   (or (eq (car-safe hi) 'intv)
+	       (setq hi (list 'intv (if (memq (nth 1 b) '(1 3)) 3 0) hi hi)))
+	   (math-combine-intervals
+	    (nth 2 lo) (and (or (memq (nth 1 b) '(2 3))
+				(math-infinitep (nth 2 lo)))
+			    (memq (nth 1 lo) '(2 3)))
+	    (nth 3 lo) (and (or (memq (nth 1 b) '(2 3))
+				(math-infinitep (nth 3 lo)))
+			    (memq (nth 1 lo) '(1 3)))
+	    (nth 2 hi) (and (or (memq (nth 1 b) '(1 3))
+				(math-infinitep (nth 2 hi)))
+			    (memq (nth 1 hi) '(2 3)))
+	    (nth 3 hi) (and (or (memq (nth 1 b) '(1 3))
+				(math-infinitep (nth 3 hi)))
+			    (memq (nth 1 hi) '(1 3))))))
+	((and (eq (car-safe a) 'mod)
+	      (eq (car-safe b) 'mod)
+	      (equal (nth 2 a) (nth 2 b)))
+	 (math-make-mod (math-mul (nth 1 a) (nth 1 b)) (nth 2 a)))
+	((and (eq (car-safe a) 'mod)
+	      (Math-anglep b))
+	 (math-make-mod (math-mul (nth 1 a) b) (nth 2 a)))
+	((and (eq (car-safe b) 'mod)
+	      (Math-anglep a))
+	 (math-make-mod (math-mul a (nth 1 b)) (nth 2 b)))
+	((and (eq (car-safe a) 'hms) (Math-realp b))
+	 (math-with-extra-prec 2
+	   (math-to-hms (math-mul (math-from-hms a 'deg) b) 'deg)))
+	((and (eq (car-safe b) 'hms) (Math-realp a))
+	 (math-mul b a))
+	(t (calc-record-why "*Incompatible arguments for *" a b)))
+)
+
+;;; Fast function to multiply floating-point numbers.
+(defun math-mul-float (a b)   ; [F F F]
+  (math-make-float (math-mul (nth 1 a) (nth 1 b))
+		   (+ (nth 2 a) (nth 2 b)))
+)
+
+(defun math-sqr-float (a)   ; [F F]
+  (math-make-float (math-mul (nth 1 a) (nth 1 a))
+		   (+ (nth 2 a) (nth 2 a)))
+)
+
+(defun math-intv-constp (a &optional finite)
+  (and (or (Math-anglep (nth 2 a))
+	   (and (equal (nth 2 a) '(neg (var inf var-inf)))
+		(or (not finite)
+		    (memq (nth 1 a) '(0 1)))))
+       (or (Math-anglep (nth 3 a))
+	   (and (equal (nth 3 a) '(var inf var-inf))
+		(or (not finite)
+		    (memq (nth 1 a) '(0 2))))))
+)
+
+(defun math-mul-zero (a b)
+  (if (math-known-matrixp b)
+      (if (math-vectorp b)
+	  (math-map-vec-2 'math-mul a b)
+	(math-mimic-ident 0 b))
+    (if (math-infinitep b)
+	'(var nan var-nan)
+      (let ((aa nil) (bb nil))
+	(if (and (eq (car-safe b) 'intv)
+		 (progn
+		   (and (equal (nth 2 b) '(neg (var inf var-inf)))
+			(memq (nth 1 b) '(2 3))
+			(setq aa (nth 2 b)))
+		   (and (equal (nth 3 b) '(var inf var-inf))
+			(memq (nth 1 b) '(1 3))
+			(setq bb (nth 3 b)))
+		   (or aa bb)))
+	    (if (or (math-posp a)
+		    (and (math-zerop a)
+			 (or (memq calc-infinite-mode '(-1 1))
+			     (setq aa '(neg (var inf var-inf))
+				   bb '(var inf var-inf)))))
+		(list 'intv 3 (or aa 0) (or bb 0))
+	      (if (math-negp a)
+		  (math-neg (list 'intv 3 (or aa 0) (or bb 0)))
+		'(var nan var-nan)))
+	  (if (or (math-floatp a) (math-floatp b)) '(float 0 0) 0)))))
+)
+
+
+(defun math-mul-symb-fancy (a b)
+  (or (and math-simplify-only
+	   (not (equal a math-simplify-only))
+	   (list '* a b))
+      (and (Math-equal-int a 1)
+	   b)
+      (and (Math-equal-int a -1)
+	   (math-neg b))
+      (and (or (and (Math-vectorp a) (math-known-scalarp b))
+	       (and (Math-vectorp b) (math-known-scalarp a)))
+	   (math-map-vec-2 'math-mul a b))
+      (and (Math-objectp b) (not (Math-objectp a))
+	   (math-mul b a))
+      (and (eq (car-safe a) 'neg)
+	   (math-neg (math-mul (nth 1 a) b)))
+      (and (eq (car-safe b) 'neg)
+	   (math-neg (math-mul a (nth 1 b))))
+      (and (eq (car-safe a) '*)
+	   (math-mul (nth 1 a)
+		     (math-mul (nth 2 a) b)))
+      (and (eq (car-safe a) '^)
+	   (Math-looks-negp (nth 2 a))
+	   (not (and (eq (car-safe b) '^) (Math-looks-negp (nth 2 b))))
+	   (math-known-scalarp b t)
+	   (math-div b (math-normalize
+			(list '^ (nth 1 a) (math-neg (nth 2 a))))))
+      (and (eq (car-safe b) '^)
+	   (Math-looks-negp (nth 2 b))
+	   (not (and (eq (car-safe a) '^) (Math-looks-negp (nth 2 a))))
+	   (math-div a (math-normalize
+			(list '^ (nth 1 b) (math-neg (nth 2 b))))))
+      (and (eq (car-safe a) '/)
+	   (or (math-known-scalarp a t) (math-known-scalarp b t))
+	   (let ((temp (math-combine-prod (nth 2 a) b t nil t)))
+	     (if temp
+		 (math-mul (nth 1 a) temp)
+	       (math-div (math-mul (nth 1 a) b) (nth 2 a)))))
+      (and (eq (car-safe b) '/)
+	   (math-div (math-mul a (nth 1 b)) (nth 2 b)))
+      (and (eq (car-safe b) '+)
+	   (Math-numberp a)
+	   (or (Math-numberp (nth 1 b))
+	       (Math-numberp (nth 2 b)))
+	   (math-add (math-mul a (nth 1 b))
+		     (math-mul a (nth 2 b))))
+      (and (eq (car-safe b) '-)
+	   (Math-numberp a)
+	   (or (Math-numberp (nth 1 b))
+	       (Math-numberp (nth 2 b)))
+	   (math-sub (math-mul a (nth 1 b))
+		     (math-mul a (nth 2 b))))
+      (and (eq (car-safe b) '*)
+	   (Math-numberp (nth 1 b))
+	   (not (Math-numberp a))
+	   (math-mul (nth 1 b) (math-mul a (nth 2 b))))
+      (and (eq (car-safe a) 'calcFunc-idn)
+	   (= (length a) 2)
+	   (or (and (eq (car-safe b) 'calcFunc-idn)
+		    (= (length b) 2)
+		    (list 'calcFunc-idn (math-mul (nth 1 a) (nth 1 b))))
+	       (and (math-known-scalarp b)
+		    (list 'calcFunc-idn (math-mul (nth 1 a) b)))
+	       (and (math-known-matrixp b)
+		    (math-mul (nth 1 a) b))))
+      (and (eq (car-safe b) 'calcFunc-idn)
+	   (= (length b) 2)
+	   (or (and (math-known-scalarp a)
+		    (list 'calcFunc-idn (math-mul a (nth 1 b))))
+	       (and (math-known-matrixp a)
+		    (math-mul a (nth 1 b)))))
+      (and (math-looks-negp b)
+	   (math-mul (math-neg a) (math-neg b)))
+      (and (eq (car-safe b) '-)
+	   (math-looks-negp a)
+	   (math-mul (math-neg a) (math-neg b)))
+      (cond
+       ((eq (car-safe b) '*)
+	(let ((temp (math-combine-prod a (nth 1 b) nil nil t)))
+	  (and temp
+	       (math-mul temp (nth 2 b)))))
+       (t
+	(math-combine-prod a b nil nil nil)))
+      (and (equal a '(var nan var-nan))
+	   a)
+      (and (equal b '(var nan var-nan))
+	   b)
+      (and (equal a '(var uinf var-uinf))
+	   a)
+      (and (equal b '(var uinf var-uinf))
+	   b)
+      (and (equal b '(var inf var-inf))
+	   (let ((s1 (math-possible-signs a)))
+	     (cond ((eq s1 4)
+		    b)
+		   ((eq s1 6)
+		    '(intv 3 0 (var inf var-inf)))
+		   ((eq s1 1)
+		    (math-neg b))
+		   ((eq s1 3)
+		    '(intv 3 (neg (var inf var-inf)) 0))
+		   ((and (eq (car a) 'intv) (math-intv-constp a))
+		    '(intv 3 (neg (var inf var-inf)) (var inf var-inf)))
+		   ((and (eq (car a) 'cplx)
+			 (math-zerop (nth 1 a)))
+		    (list '* (list 'cplx 0 (calcFunc-sign (nth 2 a))) b))
+		   ((eq (car a) 'polar)
+		    (list '* (list 'polar 1 (nth 2 a)) b)))))
+      (and (equal a '(var inf var-inf))
+	   (math-mul b a))
+      (list '* a b))
+)
+
+
+(defun calcFunc-div (a &rest rest)
+  (while rest
+    (setq a (list '/ a (car rest))
+	  rest (cdr rest)))
+  (math-normalize a)
+)
+
+(defun math-div-objects-fancy (a b)
+  (cond ((and (Math-numberp a) (Math-numberp b))
+	 (math-normalize
+	  (cond ((math-want-polar a b)
+		 (let ((a (math-polar a))
+		       (b (math-polar b)))
+		   (list 'polar
+			 (math-div (nth 1 a) (nth 1 b))
+			 (math-fix-circular (math-sub (nth 2 a)
+						      (nth 2 b))))))
+		((Math-realp b)
+		 (setq a (math-complex a))
+		 (list 'cplx (math-div (nth 1 a) b)
+		       (math-div (nth 2 a) b)))
+		(t
+		 (setq a (math-complex a)
+		       b (math-complex b))
+		 (math-div
+		  (list 'cplx
+			(math-add (math-mul (nth 1 a) (nth 1 b))
+				  (math-mul (nth 2 a) (nth 2 b)))
+			(math-sub (math-mul (nth 2 a) (nth 1 b))
+				  (math-mul (nth 1 a) (nth 2 b))))
+		  (math-add (math-sqr (nth 1 b))
+			    (math-sqr (nth 2 b))))))))
+	((math-matrixp b)
+	 (if (math-square-matrixp b)
+	     (let ((n1 (length b)))
+	       (if (Math-vectorp a)
+		   (if (math-matrixp a)
+		       (if (= (length a) n1)
+			   (math-lud-solve (math-matrix-lud b) a b)
+			 (if (= (length (nth 1 a)) n1)
+			     (math-transpose
+			      (math-lud-solve (math-matrix-lud
+					       (math-transpose b))
+					      (math-transpose a) b))
+			   (math-dimension-error)))
+		     (if (= (length a) n1)
+			 (math-mat-col (math-lud-solve (math-matrix-lud b)
+						       (math-col-matrix a) b)
+				       1)
+		       (math-dimension-error)))
+		 (if (Math-equal-int a 1)
+		     (calcFunc-inv b)
+		   (math-mul a (calcFunc-inv b)))))
+	   (math-reject-arg b 'square-matrixp)))
+	((and (Math-vectorp a) (Math-objectp b))
+	 (math-map-vec-2 'math-div a b))
+	((eq (car-safe a) 'sdev)
+	 (if (eq (car-safe b) 'sdev)
+	     (let ((x (math-div (nth 1 a) (nth 1 b))))
+	       (math-make-sdev x
+			       (math-div (math-hypot (nth 2 a)
+						     (math-mul (nth 2 b) x))
+					 (nth 1 b))))
+	   (if (or (Math-scalarp b)
+		   (not (Math-objvecp b)))
+	       (math-make-sdev (math-div (nth 1 a) b) (math-div (nth 2 a) b))
+	     (math-reject-arg 'realp b))))
+	((and (eq (car-safe b) 'sdev)
+	      (or (Math-scalarp a)
+		  (not (Math-objvecp a))))
+	 (let ((x (math-div a (nth 1 b))))
+	   (math-make-sdev x
+			   (math-div (math-mul (nth 2 b) x) (nth 1 b)))))
+	((and (eq (car-safe a) 'intv) (Math-anglep b))
+	 (if (Math-negp b)
+	     (math-neg (math-div a (math-neg b)))
+	   (math-make-intv (nth 1 a)
+			   (math-div (nth 2 a) b)
+			   (math-div (nth 3 a) b))))
+	((and (eq (car-safe b) 'intv) (Math-anglep a))
+	 (if (or (Math-posp (nth 2 b))
+		 (and (Math-zerop (nth 2 b)) (or (memq (nth 1 b) '(0 1))
+						 calc-infinite-mode)))
+	     (if (Math-negp a)
+		 (math-neg (math-div (math-neg a) b))
+	       (let ((calc-infinite-mode 1))
+		 (math-make-intv (aref [0 2 1 3] (nth 1 b))
+				 (math-div a (nth 3 b))
+				 (math-div a (nth 2 b)))))
+	   (if (or (Math-negp (nth 3 b))
+		   (and (Math-zerop (nth 3 b)) (or (memq (nth 1 b) '(0 2))
+						   calc-infinite-mode)))
+	       (math-neg (math-div a (math-neg b)))
+	     (if calc-infinite-mode
+		 '(intv 3 (neg (var inf var-inf)) (var inf var-inf))
+	       (math-reject-arg b "*Division by zero")))))
+	((and (eq (car-safe a) 'intv) (math-intv-constp a)
+	      (eq (car-safe b) 'intv) (math-intv-constp b))
+	 (if (or (Math-posp (nth 2 b))
+		 (and (Math-zerop (nth 2 b)) (or (memq (nth 1 b) '(0 1))
+						 calc-infinite-mode)))
+	     (let* ((calc-infinite-mode 1)
+		    (lo (math-div a (nth 2 b)))
+		    (hi (math-div a (nth 3 b))))
+	       (or (eq (car-safe lo) 'intv)
+		   (setq lo (list 'intv (if (memq (nth 1 b) '(2 3)) 3 0)
+				  lo lo)))
+	       (or (eq (car-safe hi) 'intv)
+		   (setq hi (list 'intv (if (memq (nth 1 b) '(1 3)) 3 0)
+				  hi hi)))
+	       (math-combine-intervals
+		(nth 2 lo) (and (or (memq (nth 1 b) '(2 3))
+				    (and (math-infinitep (nth 2 lo))
+					 (not (math-zerop (nth 2 b)))))
+				(memq (nth 1 lo) '(2 3)))
+		(nth 3 lo) (and (or (memq (nth 1 b) '(2 3))
+				    (and (math-infinitep (nth 3 lo))
+					 (not (math-zerop (nth 2 b)))))
+				(memq (nth 1 lo) '(1 3)))
+		(nth 2 hi) (and (or (memq (nth 1 b) '(1 3))
+				    (and (math-infinitep (nth 2 hi))
+					 (not (math-zerop (nth 3 b)))))
+				(memq (nth 1 hi) '(2 3)))
+		(nth 3 hi) (and (or (memq (nth 1 b) '(1 3))
+				    (and (math-infinitep (nth 3 hi))
+					 (not (math-zerop (nth 3 b)))))
+				(memq (nth 1 hi) '(1 3)))))
+	   (if (or (Math-negp (nth 3 b))
+		   (and (Math-zerop (nth 3 b)) (or (memq (nth 1 b) '(0 2))
+						   calc-infinite-mode)))
+	       (math-neg (math-div a (math-neg b)))
+	     (if calc-infinite-mode
+		 '(intv 3 (neg (var inf var-inf)) (var inf var-inf))
+	       (math-reject-arg b "*Division by zero")))))
+	((and (eq (car-safe a) 'mod)
+	      (eq (car-safe b) 'mod)
+	      (equal (nth 2 a) (nth 2 b)))
+	 (math-make-mod (math-div-mod (nth 1 a) (nth 1 b) (nth 2 a))
+			(nth 2 a)))
+	((and (eq (car-safe a) 'mod)
+	      (Math-anglep b))
+	 (math-make-mod (math-div-mod (nth 1 a) b (nth 2 a)) (nth 2 a)))
+	((and (eq (car-safe b) 'mod)
+	      (Math-anglep a))
+	 (math-make-mod (math-div-mod a (nth 1 b) (nth 2 b)) (nth 2 b)))
+	((eq (car-safe a) 'hms)
+	 (if (eq (car-safe b) 'hms)
+	     (math-with-extra-prec 1
+	       (math-div (math-from-hms a 'deg)
+			 (math-from-hms b 'deg)))
+	   (math-with-extra-prec 2
+	     (math-to-hms (math-div (math-from-hms a 'deg) b) 'deg))))
+	(t (calc-record-why "*Incompatible arguments for /" a b)))
+)
+
+(defun math-div-by-zero (a b)
+  (if (math-infinitep a)
+      (if (or (equal a '(var nan var-nan))
+	      (equal b '(var uinf var-uinf))
+	      (memq calc-infinite-mode '(-1 1)))
+	  a
+	'(var uinf var-uinf))
+    (if calc-infinite-mode
+	(if (math-zerop a)
+	    '(var nan var-nan)
+	  (if (eq calc-infinite-mode 1)
+	      (math-mul a '(var inf var-inf))
+	    (if (eq calc-infinite-mode -1)
+		(math-mul a '(neg (var inf var-inf)))
+	      (if (eq (car-safe a) 'intv)
+		  '(intv 3 (neg (var inf var-inf)) (var inf var-inf))
+		'(var uinf var-uinf)))))
+      (math-reject-arg a "*Division by zero")))
+)
+
+(defun math-div-zero (a b)
+  (if (math-known-matrixp b)
+      (if (math-vectorp b)
+	  (math-map-vec-2 'math-div a b)
+	(math-mimic-ident 0 b))
+    (if (equal b '(var nan var-nan))
+	b
+      (if (and (eq (car-safe b) 'intv) (math-intv-constp b)
+	       (not (math-posp b)) (not (math-negp b)))
+	  (if calc-infinite-mode
+	      (list 'intv 3
+		    (if (and (math-zerop (nth 2 b))
+			     (memq calc-infinite-mode '(1 -1)))
+			(nth 2 b) '(neg (var inf var-inf)))
+		    (if (and (math-zerop (nth 3 b))
+			     (memq calc-infinite-mode '(1 -1)))
+			(nth 3 b) '(var inf var-inf)))
+	    (math-reject-arg b "*Division by zero"))
+	a)))
+)
+
+(defun math-div-symb-fancy (a b)
+  (or (and math-simplify-only
+	   (not (equal a math-simplify-only))
+	   (list '/ a b))
+      (and (Math-equal-int b 1) a)
+      (and (Math-equal-int b -1) (math-neg a))
+      (and (Math-vectorp a) (math-known-scalarp b)
+	   (math-map-vec-2 'math-div a b))
+      (and (eq (car-safe b) '^)
+	   (or (Math-looks-negp (nth 2 b)) (Math-equal-int a 1))
+	   (math-mul a (math-normalize
+			(list '^ (nth 1 b) (math-neg (nth 2 b))))))
+      (and (eq (car-safe a) 'neg)
+	   (math-neg (math-div (nth 1 a) b)))
+      (and (eq (car-safe b) 'neg)
+	   (math-neg (math-div a (nth 1 b))))
+      (and (eq (car-safe a) '/)
+	   (math-div (nth 1 a) (math-mul (nth 2 a) b)))
+      (and (eq (car-safe b) '/)
+	   (or (math-known-scalarp (nth 1 b) t)
+	       (math-known-scalarp (nth 2 b) t))
+	   (math-div (math-mul a (nth 2 b)) (nth 1 b)))
+      (and (eq (car-safe b) 'frac)
+	   (math-mul (math-make-frac (nth 2 b) (nth 1 b)) a))
+      (and (eq (car-safe a) '+)
+	   (or (Math-numberp (nth 1 a))
+	       (Math-numberp (nth 2 a)))
+	   (Math-numberp b)
+	   (math-add (math-div (nth 1 a) b)
+		     (math-div (nth 2 a) b)))
+      (and (eq (car-safe a) '-)
+	   (or (Math-numberp (nth 1 a))
+	       (Math-numberp (nth 2 a)))
+	   (Math-numberp b)
+	   (math-sub (math-div (nth 1 a) b)
+		     (math-div (nth 2 a) b)))
+      (and (or (eq (car-safe a) '-)
+	       (math-looks-negp a))
+	   (math-looks-negp b)
+	   (math-div (math-neg a) (math-neg b)))
+      (and (eq (car-safe b) '-)
+	   (math-looks-negp a)
+	   (math-div (math-neg a) (math-neg b)))
+      (and (eq (car-safe a) 'calcFunc-idn)
+	   (= (length a) 2)
+	   (or (and (eq (car-safe b) 'calcFunc-idn)
+		    (= (length b) 2)
+		    (list 'calcFunc-idn (math-div (nth 1 a) (nth 1 b))))
+	       (and (math-known-scalarp b)
+		    (list 'calcFunc-idn (math-div (nth 1 a) b)))
+	       (and (math-known-matrixp b)
+		    (math-div (nth 1 a) b))))
+      (and (eq (car-safe b) 'calcFunc-idn)
+	   (= (length b) 2)
+	   (or (and (math-known-scalarp a)
+		    (list 'calcFunc-idn (math-div a (nth 1 b))))
+	       (and (math-known-matrixp a)
+		    (math-div a (nth 1 b)))))
+      (if (and calc-matrix-mode
+	       (or (math-known-matrixp a) (math-known-matrixp b)))
+	  (math-combine-prod a b nil t nil)
+	(if (eq (car-safe a) '*)
+	    (if (eq (car-safe b) '*)
+		(let ((c (math-combine-prod (nth 1 a) (nth 1 b) nil t t)))
+		  (and c
+		       (math-div (math-mul c (nth 2 a)) (nth 2 b))))
+	      (let ((c (math-combine-prod (nth 1 a) b nil t t)))
+		(and c
+		     (math-mul c (nth 2 a)))))
+	  (if (eq (car-safe b) '*)
+	      (let ((c (math-combine-prod a (nth 1 b) nil t t)))
+		(and c
+		     (math-div c (nth 2 b))))
+	    (math-combine-prod a b nil t nil))))
+      (and (math-infinitep a)
+	   (if (math-infinitep b)
+	       '(var nan var-nan)
+	     (if (or (equal a '(var nan var-nan))
+		     (equal a '(var uinf var-uinf)))
+		 a
+	       (if (equal a '(var inf var-inf))
+		   (if (or (math-posp b)
+			   (and (eq (car-safe b) 'intv)
+				(math-zerop (nth 2 b))))
+		       (if (and (eq (car-safe b) 'intv)
+				(not (math-intv-constp b t)))
+			   '(intv 3 0 (var inf var-inf))
+			 a)
+		     (if (or (math-negp b)
+			     (and (eq (car-safe b) 'intv)
+			      (math-zerop (nth 3 b))))
+			 (if (and (eq (car-safe b) 'intv)
+				  (not (math-intv-constp b t)))
+			     '(intv 3 (neg (var inf var-inf)) 0)
+			   (math-neg a))
+		       (if (and (eq (car-safe b) 'intv)
+				(math-negp (nth 2 b)) (math-posp (nth 3 b)))
+			   '(intv 3 (neg (var inf var-inf))
+				  (var inf var-inf)))))))))
+      (and (math-infinitep b)
+	   (if (equal b '(var nan var-nan))
+	       b
+	     (let ((calc-infinite-mode 1))
+	       (math-mul-zero b a))))
+      (list '/ a b))
+)
+
+
+(defun calcFunc-mod (a b)
+  (math-normalize (list '% a b))
+)
+
+(defun math-mod-fancy (a b)
+  (cond ((equal b '(var inf var-inf))
+	 (if (or (math-posp a) (math-zerop a))
+	     a
+	   (if (math-negp a)
+	       b
+	     (if (eq (car-safe a) 'intv)
+		 (if (math-negp (nth 2 a))
+		     '(intv 3 0 (var inf var-inf))
+		   a)
+	       (list '% a b)))))
+	((and (eq (car-safe a) 'mod) (Math-realp b) (math-posp b))
+	 (math-make-mod (nth 1 a) b))
+	((and (eq (car-safe a) 'intv) (math-intv-constp a t) (math-posp b))
+	 (math-mod-intv a b))
+	(t
+	 (if (Math-anglep a)
+	     (calc-record-why 'anglep b)
+	   (calc-record-why 'anglep a))
+	 (list '% a b)))
+)
+
+
+(defun calcFunc-pow (a b)
+  (math-normalize (list '^ a b))
+)
+
+(defun math-pow-of-zero (a b)
+  (if (Math-zerop b)
+      (if calc-infinite-mode
+	  '(var nan var-nan)
+	(math-reject-arg (list '^ a b) "*Indeterminate form"))
+    (if (math-floatp b) (setq a (math-float a)))
+    (if (math-posp b)
+	a
+      (if (math-negp b)
+	  (math-div 1 a)
+	(if (math-infinitep b)
+	    '(var nan var-nan)
+	  (if (and (eq (car b) 'intv) (math-intv-constp b)
+		   calc-infinite-mode)
+	      '(intv 3 (neg (var inf var-inf)) (var inf var-inf))
+	    (if (math-objectp b)
+		(list '^ a b)
+	      a))))))
+)
+
+(defun math-pow-zero (a b)
+  (if (eq (car-safe a) 'mod)
+      (math-make-mod 1 (nth 2 a))
+    (if (math-known-matrixp a)
+	(math-mimic-ident 1 a)
+      (if (math-infinitep a)
+	  '(var nan var-nan)
+	(if (and (eq (car a) 'intv) (math-intv-constp a)
+		 (or (and (not (math-posp a)) (not (math-negp a)))
+		     (not (math-intv-constp a t))))
+	    '(intv 3 (neg (var inf var-inf)) (var inf var-inf))
+	  (if (or (math-floatp a) (math-floatp b))
+	      '(float 1 0) 1)))))
+)
+
+(defun math-pow-fancy (a b)
+  (cond ((and (Math-numberp a) (Math-numberp b))
+	 (or (if (memq (math-quarter-integer b) '(1 2 3))
+		 (let ((sqrt (math-sqrt (if (math-floatp b)
+					    (math-float a) a))))
+		   (and (Math-numberp sqrt)
+			(math-pow sqrt (math-mul 2 b))))
+	       (and (eq (car b) 'frac)
+		    (integerp (nth 2 b))
+		    (<= (nth 2 b) 10)
+		    (let ((root (math-nth-root a (nth 2 b))))
+		      (and root (math-ipow root (nth 1 b))))))
+	     (and (or (eq a 10) (equal a '(float 1 1)))
+		  (math-num-integerp b)
+		  (calcFunc-scf '(float 1 0) b))
+	     (and calc-symbolic-mode
+		  (list '^ a b))
+	     (math-with-extra-prec 2
+	       (math-exp-raw
+		(math-float (math-mul b (math-ln-raw (math-float a))))))))
+	((or (not (Math-objvecp a))
+	     (not (Math-objectp b)))
+	 (let (temp)
+	   (cond ((and math-simplify-only
+		       (not (equal a math-simplify-only)))
+		  (list '^ a b))
+		 ((and (eq (car-safe a) '*)
+		       (or (math-known-num-integerp b)
+			   (math-known-nonnegp (nth 1 a))
+			   (math-known-nonnegp (nth 2 a))))
+		  (math-mul (math-pow (nth 1 a) b)
+			    (math-pow (nth 2 a) b)))
+		 ((and (eq (car-safe a) '/)
+		       (or (math-known-num-integerp b)
+			   (math-known-nonnegp (nth 2 a))))
+		  (math-div (math-pow (nth 1 a) b)
+			    (math-pow (nth 2 a) b)))
+		 ((and (eq (car-safe a) '/)
+		       (math-known-nonnegp (nth 1 a))
+		       (not (math-equal-int (nth 1 a) 1)))
+		  (math-mul (math-pow (nth 1 a) b)
+			    (math-pow (math-div 1 (nth 2 a)) b)))
+		 ((and (eq (car-safe a) '^)
+		       (or (math-known-num-integerp b)
+			   (math-known-nonnegp (nth 1 a))))
+		  (math-pow (nth 1 a) (math-mul (nth 2 a) b)))
+		 ((and (eq (car-safe a) 'calcFunc-sqrt)
+		       (or (math-known-num-integerp b)
+			   (math-known-nonnegp (nth 1 a))))
+		  (math-pow (nth 1 a) (math-div b 2)))
+		 ((and (eq (car-safe a) '^)
+		       (math-known-evenp (nth 2 a))
+		       (memq (math-quarter-integer b) '(1 2 3))
+		       (math-known-realp (nth 1 a)))
+		  (math-abs (math-pow (nth 1 a) (math-mul (nth 2 a) b))))
+		 ((and (math-looks-negp a)
+		       (math-known-integerp b)
+		       (setq temp (or (and (math-known-evenp b)
+					   (math-pow (math-neg a) b))
+				      (and (math-known-oddp b)
+					   (math-neg (math-pow (math-neg a)
+							       b))))))
+		  temp)
+		 ((and (eq (car-safe a) 'calcFunc-abs)
+		       (math-known-realp (nth 1 a))
+		       (math-known-evenp b))
+		  (math-pow (nth 1 a) b))
+		 ((math-infinitep a)
+		  (cond ((equal a '(var nan var-nan))
+			 a)
+			((eq (car a) 'neg)
+			 (math-mul (math-pow -1 b) (math-pow (nth 1 a) b)))
+			((math-posp b)
+			 a)
+			((math-negp b)
+			 (if (math-floatp b) '(float 0 0) 0))
+			((and (eq (car-safe b) 'intv)
+			      (math-intv-constp b))
+			 '(intv 3 0 (var inf var-inf)))
+			(t
+			 '(var nan var-nan))))
+		 ((math-infinitep b)
+		  (let (scale)
+		    (cond ((math-negp b)
+			   (math-pow (math-div 1 a) (math-neg b)))
+			  ((not (math-posp b))
+			   '(var nan var-nan))
+			  ((math-equal-int (setq scale (calcFunc-abssqr a)) 1)
+			   '(var nan var-nan))
+			  ((Math-lessp scale 1)
+			   (if (math-floatp a) '(float 0 0) 0))
+			  ((Math-lessp 1 a)
+			   b)
+			  ((Math-lessp a -1)
+			   '(var uinf var-uinf))
+			  ((and (eq (car a) 'intv)
+				(math-intv-constp a))
+			   (if (Math-lessp -1 a)
+			       (if (math-equal-int (nth 3 a) 1)
+				   '(intv 3 0 1)
+				 '(intv 3 0 (var inf var-inf)))
+			     '(intv 3 (neg (var inf var-inf))
+				    (var inf var-inf))))
+			  (t (list '^ a b)))))
+		 ((and (eq (car-safe a) 'calcFunc-idn)
+		       (= (length a) 2)
+		       (math-known-num-integerp b))
+		  (list 'calcFunc-idn (math-pow (nth 1 a) b)))
+		 (t (if (Math-objectp a)
+			(calc-record-why 'objectp b)
+		      (calc-record-why 'objectp a))
+		    (list '^ a b)))))
+	((and (eq (car-safe a) 'sdev) (eq (car-safe b) 'sdev))
+	 (if (and (math-constp a) (math-constp b))
+	     (math-with-extra-prec 2
+	       (let* ((ln (math-ln-raw (math-float (nth 1 a))))
+		      (pow (math-exp-raw
+			    (math-float (math-mul (nth 1 b) ln)))))
+		 (math-make-sdev
+		  pow
+		  (math-mul
+		   pow
+		   (math-hypot (math-mul (nth 2 a)
+					 (math-div (nth 1 b) (nth 1 a)))
+			       (math-mul (nth 2 b) ln))))))
+	   (let ((pow (math-pow (nth 1 a) (nth 1 b))))
+	     (math-make-sdev
+	      pow
+	      (math-mul pow
+			(math-hypot (math-mul (nth 2 a)
+					      (math-div (nth 1 b) (nth 1 a)))
+				    (math-mul (nth 2 b) (calcFunc-ln
+							 (nth 1 a)))))))))
+	((and (eq (car-safe a) 'sdev) (Math-numberp b))
+	 (if (math-constp a)
+	     (math-with-extra-prec 2
+	       (let ((pow (math-pow (nth 1 a) (math-sub b 1))))
+		 (math-make-sdev (math-mul pow (nth 1 a))
+				 (math-mul pow (math-mul (nth 2 a) b)))))
+	   (math-make-sdev (math-pow (nth 1 a) b)
+			   (math-mul (math-pow (nth 1 a) (math-add b -1))
+				     (math-mul (nth 2 a) b)))))
+	((and (eq (car-safe b) 'sdev) (Math-numberp a))
+	 (math-with-extra-prec 2
+	   (let* ((ln (math-ln-raw (math-float a)))
+		  (pow (calcFunc-exp (math-mul (nth 1 b) ln))))
+	     (math-make-sdev pow (math-mul pow (math-mul (nth 2 b) ln))))))
+	((and (eq (car-safe a) 'intv) (math-intv-constp a)
+	      (Math-realp b)
+	      (or (Math-natnump b)
+		  (Math-posp (nth 2 a))
+		  (and (math-zerop (nth 2 a))
+		       (or (Math-posp b)
+			   (and (Math-integerp b) calc-infinite-mode)))
+		  (Math-negp (nth 3 a))
+		  (and (math-zerop (nth 3 a))
+		       (or (Math-posp b)
+			   (and (Math-integerp b) calc-infinite-mode)))))
+	 (if (math-evenp b)
+	     (setq a (math-abs a)))
+	 (let ((calc-infinite-mode (if (math-zerop (nth 3 a)) -1 1)))
+	   (math-sort-intv (nth 1 a)
+			   (math-pow (nth 2 a) b)
+			   (math-pow (nth 3 a) b))))
+	((and (eq (car-safe b) 'intv) (math-intv-constp b)
+	      (Math-realp a) (Math-posp a))
+	 (math-sort-intv (nth 1 b)
+			 (math-pow a (nth 2 b))
+			 (math-pow a (nth 3 b))))
+	((and (eq (car-safe a) 'intv) (math-intv-constp a)
+	      (eq (car-safe b) 'intv) (math-intv-constp b)
+	      (or (and (not (Math-negp (nth 2 a)))
+		       (not (Math-negp (nth 2 b))))
+		  (and (Math-posp (nth 2 a))
+		       (not (Math-posp (nth 3 b))))))
+	 (let ((lo (math-pow a (nth 2 b)))
+	       (hi (math-pow a (nth 3 b))))
+	   (or (eq (car-safe lo) 'intv)
+	       (setq lo (list 'intv (if (memq (nth 1 b) '(2 3)) 3 0) lo lo)))
+	   (or (eq (car-safe hi) 'intv)
+	       (setq hi (list 'intv (if (memq (nth 1 b) '(1 3)) 3 0) hi hi)))
+	   (math-combine-intervals
+	    (nth 2 lo) (and (or (memq (nth 1 b) '(2 3))
+				(math-infinitep (nth 2 lo)))
+			    (memq (nth 1 lo) '(2 3)))
+	    (nth 3 lo) (and (or (memq (nth 1 b) '(2 3))
+				(math-infinitep (nth 3 lo)))
+			    (memq (nth 1 lo) '(1 3)))
+	    (nth 2 hi) (and (or (memq (nth 1 b) '(1 3))
+				(math-infinitep (nth 2 hi)))
+			    (memq (nth 1 hi) '(2 3)))
+	    (nth 3 hi) (and (or (memq (nth 1 b) '(1 3))
+				(math-infinitep (nth 3 hi)))
+			    (memq (nth 1 hi) '(1 3))))))
+	((and (eq (car-safe a) 'mod) (eq (car-safe b) 'mod)
+	      (equal (nth 2 a) (nth 2 b)))
+	 (math-make-mod (math-pow-mod (nth 1 a) (nth 1 b) (nth 2 a))
+			(nth 2 a)))
+	((and (eq (car-safe a) 'mod) (Math-anglep b))
+	 (math-make-mod (math-pow-mod (nth 1 a) b (nth 2 a)) (nth 2 a)))
+	((and (eq (car-safe b) 'mod) (Math-anglep a))
+	 (math-make-mod (math-pow-mod a (nth 1 b) (nth 2 b)) (nth 2 b)))
+	((not (Math-numberp a))
+	 (math-reject-arg a 'numberp))
+	(t
+	 (math-reject-arg b 'numberp)))
+)
+
+(defun math-quarter-integer (x)
+  (if (Math-integerp x)
+      0
+    (if (math-negp x)
+	(progn
+	  (setq x (math-quarter-integer (math-neg x)))
+	  (and x (- 4 x)))
+      (if (eq (car x) 'frac)
+	  (if (eq (nth 2 x) 2)
+	      2
+	    (and (eq (nth 2 x) 4)
+		 (progn
+		   (setq x (nth 1 x))
+		   (% (if (consp x) (nth 1 x) x) 4))))
+	(if (eq (car x) 'float)
+	    (if (>= (nth 2 x) 0)
+		0
+	      (if (= (nth 2 x) -1)
+		  (progn
+		    (setq x (nth 1 x))
+		    (and (= (% (if (consp x) (nth 1 x) x) 10) 5) 2))
+		(if (= (nth 2 x) -2)
+		    (progn
+		      (setq x (nth 1 x)
+			    x (% (if (consp x) (nth 1 x) x) 100))
+		      (if (= x 25) 1
+			(if (= x 75) 3))))))))))
+)
+
+;;; This assumes A < M and M > 0.
+(defun math-pow-mod (a b m)   ; [R R R R]
+  (if (and (Math-integerp a) (Math-integerp b) (Math-integerp m))
+      (if (Math-negp b)
+	  (math-div-mod 1 (math-pow-mod a (Math-integer-neg b) m) m)
+	(if (eq m 1)
+	    0
+	  (math-pow-mod-step a b m)))
+    (math-mod (math-pow a b) m))
+)
+
+(defun math-pow-mod-step (a n m)   ; [I I I I]
+  (math-working "pow" a)
+  (let ((val (cond
+	      ((eq n 0) 1)
+	      ((eq n 1) a)
+	      (t
+	       (let ((rest (math-pow-mod-step
+			    (math-imod (math-mul a a) m)
+			    (math-div2 n)
+			    m)))
+		 (if (math-evenp n)
+		     rest
+		   (math-mod (math-mul a rest) m)))))))
+    (math-working "pow" val)
+    val)
+)
+
+
+;;; Compute the minimum of two real numbers.  [R R R] [Public]
+(defun math-min (a b)
+  (if (and (consp a) (eq (car a) 'intv))
+      (if (and (consp b) (eq (car b) 'intv))
+	  (let ((lo (nth 2 a))
+		(lom (memq (nth 1 a) '(2 3)))
+		(hi (nth 3 a))
+		(him (memq (nth 1 a) '(1 3)))
+		res)
+	    (if (= (setq res (math-compare (nth 2 b) lo)) -1)
+		(setq lo (nth 2 b) lom (memq (nth 1 b) '(2 3)))
+	      (if (= res 0)
+		  (setq lom (or lom (memq (nth 1 b) '(2 3))))))
+	    (if (= (setq res (math-compare (nth 3 b) hi)) -1)
+		(setq hi (nth 3 b) him (memq (nth 1 b) '(1 3)))
+	      (if (= res 0)
+		  (setq him (or him (memq (nth 1 b) '(1 3))))))
+	    (math-make-intv (+ (if lom 2 0) (if him 1 0)) lo hi))
+	(math-min a (list 'intv 3 b b)))
+    (if (and (consp b) (eq (car b) 'intv))
+	(math-min (list 'intv 3 a a) b)
+      (let ((res (math-compare a b)))
+	(if (= res 1)
+	    b
+	  (if (= res 2)
+	      '(var nan var-nan)
+	    a)))))
+)
+
+(defun calcFunc-min (&optional a &rest b)
+  (if (not a)
+      '(var inf var-inf)
+    (if (not (or (Math-anglep a) (eq (car a) 'date)
+		 (and (eq (car a) 'intv) (math-intv-constp a))
+		 (math-infinitep a)))
+	(math-reject-arg a 'anglep))
+    (math-min-list a b))
+)
+
+(defun math-min-list (a b)
+  (if b
+      (if (or (Math-anglep (car b)) (eq (car b) 'date)
+	      (and (eq (car (car b)) 'intv) (math-intv-constp (car b)))
+	      (math-infinitep (car b)))
+	  (math-min-list (math-min a (car b)) (cdr b))
+	(math-reject-arg (car b) 'anglep))
+    a)
+)
+
+;;; Compute the maximum of two real numbers.  [R R R] [Public]
+(defun math-max (a b)
+  (if (or (and (consp a) (eq (car a) 'intv))
+	  (and (consp b) (eq (car b) 'intv)))
+      (math-neg (math-min (math-neg a) (math-neg b)))
+    (let ((res (math-compare a b)))
+      (if (= res -1)
+	  b
+	(if (= res 2)
+	      '(var nan var-nan)
+	  a))))
+)
+
+(defun calcFunc-max (&optional a &rest b)
+  (if (not a)
+      '(neg (var inf var-inf))
+    (if (not (or (Math-anglep a) (eq (car a) 'date)
+		 (and (eq (car a) 'intv) (math-intv-constp a))
+		 (math-infinitep a)))
+	(math-reject-arg a 'anglep))
+    (math-max-list a b))
+)
+
+(defun math-max-list (a b)
+  (if b
+      (if (or (Math-anglep (car b)) (eq (car b) 'date)
+	      (and (eq (car (car b)) 'intv) (math-intv-constp (car b)))
+	      (math-infinitep (car b)))
+	  (math-max-list (math-max a (car b)) (cdr b))
+	(math-reject-arg (car b) 'anglep))
+    a)
+)
+
+
+;;; Compute the absolute value of A.  [O O; r r] [Public]
+(defun math-abs (a)
+  (cond ((Math-negp a)
+	 (math-neg a))
+	((Math-anglep a)
+	 a)
+	((eq (car a) 'cplx)
+	 (math-hypot (nth 1 a) (nth 2 a)))
+	((eq (car a) 'polar)
+	 (nth 1 a))
+	((eq (car a) 'vec)
+	 (if (cdr (cdr (cdr a)))
+	     (math-sqrt (calcFunc-abssqr a))
+	   (if (cdr (cdr a))
+	       (math-hypot (nth 1 a) (nth 2 a))
+	     (if (cdr a)
+		 (math-abs (nth 1 a))
+	       a))))
+	((eq (car a) 'sdev)
+	 (list 'sdev (math-abs (nth 1 a)) (nth 2 a)))
+	((and (eq (car a) 'intv) (math-intv-constp a))
+	 (if (Math-posp a)
+	     a
+	   (let* ((nlo (math-neg (nth 2 a)))
+		  (res (math-compare nlo (nth 3 a))))
+	     (cond ((= res 1)
+		    (math-make-intv (if (memq (nth 1 a) '(0 1)) 2 3) 0 nlo))
+		   ((= res 0)
+		    (math-make-intv (if (eq (nth 1 a) 0) 2 3) 0 nlo))
+		   (t
+		    (math-make-intv (if (memq (nth 1 a) '(0 2)) 2 3)
+				    0 (nth 3 a)))))))
+	((math-looks-negp a)
+	 (list 'calcFunc-abs (math-neg a)))
+	((let ((signs (math-possible-signs a)))
+	   (or (and (memq signs '(2 4 6)) a)
+	       (and (memq signs '(1 3)) (math-neg a)))))
+	((let ((inf (math-infinitep a)))
+	   (and inf
+		(if (equal inf '(var nan var-nan))
+		    inf
+		  '(var inf var-inf)))))
+	(t (calc-record-why 'numvecp a)
+	   (list 'calcFunc-abs a)))
+)
+(fset 'calcFunc-abs (symbol-function 'math-abs))
+
+
+(defun math-float-fancy (a)
+  (cond ((eq (car a) 'intv)
+	 (cons (car a) (cons (nth 1 a) (mapcar 'math-float (nthcdr 2 a)))))
+	((and (memq (car a) '(* /))
+	      (math-numberp (nth 1 a)))
+	 (list (car a) (math-float (nth 1 a))
+	       (list 'calcFunc-float (nth 2 a))))
+	((and (eq (car a) '/)
+	      (eq (car (nth 1 a)) '*)
+	      (math-numberp (nth 1 (nth 1 a))))
+	 (list '* (math-float (nth 1 (nth 1 a)))
+	       (list 'calcFunc-float (list '/ (nth 2 (nth 1 a)) (nth 2 a)))))
+	((math-infinitep a) a)
+	((eq (car a) 'calcFunc-float) a)
+	((let ((func (assq (car a) '((calcFunc-floor  . calcFunc-ffloor)
+				     (calcFunc-ceil   . calcFunc-fceil)
+				     (calcFunc-trunc  . calcFunc-ftrunc)
+				     (calcFunc-round  . calcFunc-fround)
+				     (calcFunc-rounde . calcFunc-frounde)
+				     (calcFunc-roundu . calcFunc-froundu)))))
+	   (and func (cons (cdr func) (cdr a)))))
+	(t (math-reject-arg a 'objectp)))
+)
+(fset 'calcFunc-float (symbol-function 'math-float))
+
+
+(defun math-trunc-fancy (a)
+  (cond ((eq (car a) 'frac) (math-quotient (nth 1 a) (nth 2 a)))
+	((eq (car a) 'cplx) (math-trunc (nth 1 a)))
+	((eq (car a) 'polar) (math-trunc (math-complex a)))
+	((eq (car a) 'hms) (list 'hms (nth 1 a) 0 0))
+	((eq (car a) 'date) (list 'date (math-trunc (nth 1 a))))
+	((eq (car a) 'mod)
+	 (if (math-messy-integerp (nth 2 a))
+	     (math-trunc (math-make-mod (nth 1 a) (math-trunc (nth 2 a))))
+	   (math-make-mod (math-trunc (nth 1 a)) (nth 2 a))))
+	((eq (car a) 'intv)
+	 (math-make-intv (+ (if (and (equal (nth 2 a) '(neg (var inf var-inf)))
+				     (memq (nth 1 a) '(0 1)))
+				0 2)
+			    (if (and (equal (nth 3 a) '(var inf var-inf))
+				     (memq (nth 1 a) '(0 2)))
+				0 1))
+			 (if (and (Math-negp (nth 2 a))
+				  (Math-num-integerp (nth 2 a))
+				  (memq (nth 1 a) '(0 1)))
+			     (math-add (math-trunc (nth 2 a)) 1)
+			   (math-trunc (nth 2 a)))
+			 (if (and (Math-posp (nth 3 a))
+				  (Math-num-integerp (nth 3 a))
+				  (memq (nth 1 a) '(0 2)))
+			     (math-add (math-trunc (nth 3 a)) -1)
+			   (math-trunc (nth 3 a)))))
+	((math-provably-integerp a) a)
+	((Math-vectorp a)
+	 (math-map-vec (function (lambda (x) (math-trunc x prec))) a))
+	((math-infinitep a)
+	 (if (or (math-posp a) (math-negp a))
+	     a
+	   '(var nan var-nan)))
+	((math-to-integer a))
+	(t (math-reject-arg a 'numberp)))
+)
+
+(defun math-trunc-special (a prec)
+  (if (Math-messy-integerp prec)
+      (setq prec (math-trunc prec)))
+  (or (integerp prec)
+      (math-reject-arg prec 'fixnump))
+  (if (and (<= prec 0)
+	   (math-provably-integerp a))
+      a
+    (calcFunc-scf (math-trunc (let ((calc-prefer-frac t))
+				(calcFunc-scf a prec)))
+		  (- prec)))
+)
+
+(defun math-to-integer (a)
+  (let ((func (assq (car-safe a) '((calcFunc-ffloor  . calcFunc-floor)
+				   (calcFunc-fceil   . calcFunc-ceil)
+				   (calcFunc-ftrunc  . calcFunc-trunc)
+				   (calcFunc-fround  . calcFunc-round)
+				   (calcFunc-frounde . calcFunc-rounde)
+				   (calcFunc-froundu . calcFunc-roundu)))))
+    (and func (= (length a) 2)
+	 (cons (cdr func) (cdr a))))
+)
+
+(defun calcFunc-ftrunc (a &optional prec)
+  (if (and (Math-messy-integerp a)
+	   (or (not prec) (and (integerp prec)
+			       (<= prec 0))))
+      a
+    (math-float (math-trunc a prec)))
+)
+
+(defun math-floor-fancy (a)
+  (cond ((math-provably-integerp a) a)
+	((eq (car a) 'hms)
+	 (if (or (math-posp a)
+		 (and (math-zerop (nth 2 a))
+		      (math-zerop (nth 3 a))))
+	     (math-trunc a)
+	   (math-add (math-trunc a) -1)))
+	((eq (car a) 'date) (list 'date (math-floor (nth 1 a))))
+	((eq (car a) 'intv)
+	 (math-make-intv (+ (if (and (equal (nth 2 a) '(neg (var inf var-inf)))
+				     (memq (nth 1 a) '(0 1)))
+				0 2)
+			    (if (and (equal (nth 3 a) '(var inf var-inf))
+				     (memq (nth 1 a) '(0 2)))
+				0 1))
+			 (math-floor (nth 2 a))
+			 (if (and (Math-num-integerp (nth 3 a))
+				  (memq (nth 1 a) '(0 2)))
+			     (math-add (math-floor (nth 3 a)) -1)
+			   (math-floor (nth 3 a)))))
+	((Math-vectorp a)
+	 (math-map-vec (function (lambda (x) (math-floor x prec))) a))
+	((math-infinitep a)
+	 (if (or (math-posp a) (math-negp a))
+	     a
+	   '(var nan var-nan)))
+	((math-to-integer a))
+	(t (math-reject-arg a 'anglep)))
+)
+
+(defun math-floor-special (a prec)
+  (if (Math-messy-integerp prec)
+      (setq prec (math-trunc prec)))
+  (or (integerp prec)
+      (math-reject-arg prec 'fixnump))
+  (if (and (<= prec 0)
+	   (math-provably-integerp a))
+      a
+    (calcFunc-scf (math-floor (let ((calc-prefer-frac t))
+				(calcFunc-scf a prec)))
+		  (- prec)))
+)
+
+(defun calcFunc-ffloor (a &optional prec)
+  (if (and (Math-messy-integerp a)
+	   (or (not prec) (and (integerp prec)
+			       (<= prec 0))))
+      a
+    (math-float (math-floor a prec)))
+)
+
+;;; Coerce A to be an integer (by truncation toward plus infinity).  [I N]
+(defun math-ceiling (a &optional prec)   ;  [Public]
+  (cond (prec
+	 (if (Math-messy-integerp prec)
+	     (setq prec (math-trunc prec)))
+	 (or (integerp prec)
+	     (math-reject-arg prec 'fixnump))
+	 (if (and (<= prec 0)
+		  (math-provably-integerp a))
+	     a
+	   (calcFunc-scf (math-ceiling (let ((calc-prefer-frac t))
+					 (calcFunc-scf a prec)))
+			 (- prec))))
+	((Math-integerp a) a)
+	((Math-messy-integerp a) (math-trunc a))
+	((Math-realp a)
+	 (if (Math-posp a)
+	     (math-add (math-trunc a) 1)
+	   (math-trunc a)))
+	((math-provably-integerp a) a)
+	((eq (car a) 'hms)
+	 (if (or (math-negp a)
+		 (and (math-zerop (nth 2 a))
+		      (math-zerop (nth 3 a))))
+	     (math-trunc a)
+	   (math-add (math-trunc a) 1)))
+	((eq (car a) 'date) (list 'date (math-ceiling (nth 1 a))))
+	((eq (car a) 'intv)
+	 (math-make-intv (+ (if (and (equal (nth 2 a) '(neg (var inf var-inf)))
+				     (memq (nth 1 a) '(0 1)))
+				0 2)
+			    (if (and (equal (nth 3 a) '(var inf var-inf))
+				     (memq (nth 1 a) '(0 2)))
+				0 1))
+			 (if (and (Math-num-integerp (nth 2 a))
+				  (memq (nth 1 a) '(0 1)))
+			     (math-add (math-floor (nth 2 a)) 1)
+			   (math-ceiling (nth 2 a)))
+			 (math-ceiling (nth 3 a))))
+	((Math-vectorp a)
+	 (math-map-vec (function (lambda (x) (math-ceiling x prec))) a))
+	((math-infinitep a)
+	 (if (or (math-posp a) (math-negp a))
+	     a
+	   '(var nan var-nan)))
+	((math-to-integer a))
+	(t (math-reject-arg a 'anglep)))
+)
+(fset 'calcFunc-ceil (symbol-function 'math-ceiling))
+
+(defun calcFunc-fceil (a &optional prec)
+  (if (and (Math-messy-integerp a)
+	   (or (not prec) (and (integerp prec)
+			       (<= prec 0))))
+      a
+    (math-float (math-ceiling a prec)))
+)
+
+(setq math-rounding-mode nil)
+
+;;; Coerce A to be an integer (by rounding to nearest integer).  [I N] [Public]
+(defun math-round (a &optional prec)
+  (cond (prec
+	 (if (Math-messy-integerp prec)
+	     (setq prec (math-trunc prec)))
+	 (or (integerp prec)
+	     (math-reject-arg prec 'fixnump))
+	 (if (and (<= prec 0)
+		  (math-provably-integerp a))
+	     a
+	   (calcFunc-scf (math-round (let ((calc-prefer-frac t))
+				       (calcFunc-scf a prec)))
+			 (- prec))))
+	((Math-anglep a)
+	 (if (Math-num-integerp a)
+	     (math-trunc a)
+	   (if (and (Math-negp a) (not (eq math-rounding-mode 'up)))
+	       (math-neg (math-round (math-neg a)))
+	     (setq a (let ((calc-angle-mode 'deg))   ; in case of HMS forms
+		       (math-add a (if (Math-ratp a)
+				       '(frac 1 2)
+				     '(float 5 -1)))))
+	     (if (and (Math-num-integerp a) (eq math-rounding-mode 'even))
+		 (progn
+		   (setq a (math-floor a))
+		   (or (math-evenp a)
+		       (setq a (math-sub a 1)))
+		   a)
+	       (math-floor a)))))
+	((math-provably-integerp a) a)
+	((eq (car a) 'date) (list 'date (math-round (nth 1 a))))
+	((eq (car a) 'intv)
+	 (math-floor (math-add a '(frac 1 2))))
+	((Math-vectorp a)
+	 (math-map-vec (function (lambda (x) (math-round x prec))) a))
+	((math-infinitep a)
+	 (if (or (math-posp a) (math-negp a))
+	     a
+	   '(var nan var-nan)))
+	((math-to-integer a))
+	(t (math-reject-arg a 'anglep)))
+)
+(fset 'calcFunc-round (symbol-function 'math-round))
+
+(defun calcFunc-rounde (a &optional prec)
+  (let ((math-rounding-mode 'even))
+    (math-round a prec))
+)
+
+(defun calcFunc-roundu (a &optional prec)
+  (let ((math-rounding-mode 'up))
+    (math-round a prec))
+)
+
+(defun calcFunc-fround (a &optional prec)
+  (if (and (Math-messy-integerp a)
+	   (or (not prec) (and (integerp prec)
+			       (<= prec 0))))
+      a
+    (math-float (math-round a prec)))
+)
+
+(defun calcFunc-frounde (a &optional prec)
+  (let ((math-rounding-mode 'even))
+    (calcFunc-fround a prec))
+)
+
+(defun calcFunc-froundu (a &optional prec)
+  (let ((math-rounding-mode 'up))
+    (calcFunc-fround a prec))
+)
+
+
+;;; Pull floating-point values apart into mantissa and exponent.
+(defun calcFunc-mant (x)
+  (if (Math-realp x)
+      (if (or (Math-ratp x)
+	      (eq (nth 1 x) 0))
+	  x
+	(list 'float (nth 1 x) (- 1 (math-numdigs (nth 1 x)))))
+    (calc-record-why 'realp x)
+    (list 'calcFunc-mant x))
+)
+
+(defun calcFunc-xpon (x)
+  (if (Math-realp x)
+      (if (or (Math-ratp x)
+	      (eq (nth 1 x) 0))
+	  0
+	(math-normalize (+ (nth 2 x) (1- (math-numdigs (nth 1 x))))))
+    (calc-record-why 'realp x)
+    (list 'calcFunc-xpon x))
+)
+
+(defun calcFunc-scf (x n)
+  (if (integerp n)
+      (cond ((eq n 0)
+	     x)
+	    ((Math-integerp x)
+	     (if (> n 0)
+		 (math-scale-int x n)
+	       (math-div x (math-scale-int 1 (- n)))))
+	    ((eq (car x) 'frac)
+	     (if (> n 0)
+		 (math-make-frac (math-scale-int (nth 1 x) n) (nth 2 x))
+	       (math-make-frac (nth 1 x) (math-scale-int (nth 2 x) (- n)))))
+	    ((eq (car x) 'float)
+	     (math-make-float (nth 1 x) (+ (nth 2 x) n)))
+	    ((memq (car x) '(cplx sdev))
+	     (math-normalize
+	      (list (car x)
+		    (calcFunc-scf (nth 1 x) n)
+		    (calcFunc-scf (nth 2 x) n))))
+	    ((memq (car x) '(polar mod))
+	     (math-normalize
+	      (list (car x)
+		    (calcFunc-scf (nth 1 x) n)
+		    (nth 2 x))))
+	    ((eq (car x) 'intv)
+	     (math-normalize
+	      (list (car x)
+		    (nth 1 x)
+		    (calcFunc-scf (nth 2 x) n)
+		    (calcFunc-scf (nth 3 x) n))))
+	    ((eq (car x) 'vec)
+	     (math-map-vec (function (lambda (x) (calcFunc-scf x n))) x))
+	    ((math-infinitep x)
+	     x)
+	    (t
+	     (calc-record-why 'realp x)
+	     (list 'calcFunc-scf x n)))
+    (if (math-messy-integerp n)
+	(if (< (nth 2 n) 10)
+	    (calcFunc-scf x (math-trunc n))
+	  (math-overflow n))
+      (if (math-integerp n)
+	  (math-overflow n)
+	(calc-record-why 'integerp n)
+	(list 'calcFunc-scf x n))))
+)
+
+
+(defun calcFunc-incr (x &optional step relative-to)
+  (or step (setq step 1))
+  (cond ((not (Math-integerp step))
+	 (math-reject-arg step 'integerp))
+	((Math-integerp x)
+	 (math-add x step))
+	((eq (car x) 'float)
+	 (if (and (math-zerop x)
+		  (eq (car-safe relative-to) 'float))
+	     (math-mul step
+		       (calcFunc-scf relative-to (- 1 calc-internal-prec)))
+	   (math-add-float x (math-make-float
+			      step
+			      (+ (nth 2 x)
+				 (- (math-numdigs (nth 1 x))
+				    calc-internal-prec))))))
+	((eq (car x) 'date)
+	 (if (Math-integerp (nth 1 x))
+	     (math-add x step)
+	   (math-add x (list 'hms 0 0 step))))
+	(t
+	 (math-reject-arg x 'realp)))
+)
+
+(defun calcFunc-decr (x &optional step relative-to)
+  (calcFunc-incr x (math-neg (or step 1)) relative-to)
+)
+
+
+(defun calcFunc-percent (x)
+  (if (math-objectp x)
+      (let ((calc-prefer-frac nil))
+	(math-div x 100))
+    (list 'calcFunc-percent x))
+)
+
+(defun calcFunc-relch (x y)
+  (if (and (math-objectp x) (math-objectp y))
+      (math-div (math-sub y x) x)
+    (list 'calcFunc-relch x y))
+)
+
+
+
+;;; Compute the absolute value squared of A.  [F N] [Public]
+(defun calcFunc-abssqr (a)
+  (cond ((Math-realp a)
+	 (math-mul a a))
+	((eq (car a) 'cplx)
+	 (math-add (math-sqr (nth 1 a))
+		   (math-sqr (nth 2 a))))
+	((eq (car a) 'polar)
+	 (math-sqr (nth 1 a)))
+	((and (memq (car a) '(sdev intv)) (math-constp a))
+	 (math-sqr (math-abs a)))
+	((eq (car a) 'vec)
+	 (math-reduce-vec 'math-add (math-map-vec 'calcFunc-abssqr a)))
+	((math-known-realp a)
+	 (math-pow a 2))
+	((let ((inf (math-infinitep a)))
+	   (and inf
+		(math-mul (calcFunc-abssqr (math-infinite-dir a inf)) inf))))
+	(t (calc-record-why 'numvecp a)
+	   (list 'calcFunc-abssqr a)))
+)
+(defun math-sqr (a)
+  (math-mul a a)
+)
+
+
+;;;; Number theory.
+
+(defun calcFunc-idiv (a b)   ; [I I I] [Public]
+  (cond ((and (Math-natnump a) (Math-natnump b) (not (eq b 0)))
+	 (math-quotient a b))
+	((Math-realp a)
+	 (if (Math-realp b)
+	     (let ((calc-prefer-frac t))
+	       (math-floor (math-div a b)))
+	   (math-reject-arg b 'realp)))
+	((eq (car-safe a) 'hms)
+	 (if (eq (car-safe b) 'hms)
+	     (let ((calc-prefer-frac t))
+	       (math-floor (math-div a b)))
+	   (math-reject-arg b 'hmsp)))
+	((and (or (eq (car-safe a) 'intv) (Math-realp a))
+	      (or (eq (car-safe b) 'intv) (Math-realp b)))
+	 (math-floor (math-div a b)))
+	((or (math-infinitep a)
+	     (math-infinitep b))
+	 (math-div a b))
+	(t (math-reject-arg a 'anglep)))
+)
+
+
+;;; Combine two terms being added, if possible.
+(defun math-combine-sum (a b nega negb scalar-okay)
+  (if (and scalar-okay (Math-objvecp a) (Math-objvecp b))
+      (math-add-or-sub a b nega negb)
+    (let ((amult 1) (bmult 1))
+      (and (consp a)
+	   (cond ((and (eq (car a) '*)
+		       (Math-objectp (nth 1 a)))
+		  (setq amult (nth 1 a)
+			a (nth 2 a)))
+		 ((and (eq (car a) '/)
+		       (Math-objectp (nth 2 a)))
+		  (setq amult (if (Math-integerp (nth 2 a))
+				  (list 'frac 1 (nth 2 a))
+				(math-div 1 (nth 2 a)))
+			a (nth 1 a)))
+		 ((eq (car a) 'neg)
+		  (setq amult -1
+			a (nth 1 a)))))
+      (and (consp b)
+	   (cond ((and (eq (car b) '*)
+		       (Math-objectp (nth 1 b)))
+		  (setq bmult (nth 1 b)
+			b (nth 2 b)))
+		 ((and (eq (car b) '/)
+		       (Math-objectp (nth 2 b)))
+		  (setq bmult (if (Math-integerp (nth 2 b))
+				  (list 'frac 1 (nth 2 b))
+				(math-div 1 (nth 2 b)))
+			b (nth 1 b)))
+		 ((eq (car b) 'neg)
+		  (setq bmult -1
+			b (nth 1 b)))))
+      (and (if math-simplifying
+	       (Math-equal a b)
+	     (equal a b))
+	   (progn
+	     (if nega (setq amult (math-neg amult)))
+	     (if negb (setq bmult (math-neg bmult)))
+	     (setq amult (math-add amult bmult))
+	     (math-mul amult a)))))
+)
+
+(defun math-add-or-sub (a b aneg bneg)
+  (if aneg (setq a (math-neg a)))
+  (if bneg (setq b (math-neg b)))
+  (if (or (Math-vectorp a) (Math-vectorp b))
+      (math-normalize (list '+ a b))
+    (math-add a b))
+)
+
+;;; The following is expanded out four ways for speed.
+(defun math-combine-prod (a b inva invb scalar-okay)
+  (cond
+   ((or (and inva (Math-zerop a))
+	(and invb (Math-zerop b)))
+    nil)
+   ((and scalar-okay (Math-objvecp a) (Math-objvecp b))
+    (setq a (math-mul-or-div a b inva invb))
+    (and (Math-objvecp a)
+	 a))
+   ((and (eq (car-safe a) '^)
+	 inva
+	 (math-looks-negp (nth 2 a)))
+    (math-mul (math-pow (nth 1 a) (math-neg (nth 2 a))) b))
+   ((and (eq (car-safe b) '^)
+	 invb
+	 (math-looks-negp (nth 2 b)))
+    (math-mul a (math-pow (nth 1 b) (math-neg (nth 2 b)))))
+   (t (let ((apow 1) (bpow 1))
+	(and (consp a)
+	     (cond ((and (eq (car a) '^)
+			 (or math-simplifying
+			     (Math-numberp (nth 2 a))))
+		    (setq apow (nth 2 a)
+			  a (nth 1 a)))
+		   ((eq (car a) 'calcFunc-sqrt)
+		    (setq apow '(frac 1 2)
+			  a (nth 1 a)))
+		   ((and (eq (car a) 'calcFunc-exp)
+			 (or math-simplifying
+			     (Math-numberp (nth 1 a))))
+		    (setq apow (nth 1 a)
+			  a math-combine-prod-e))))
+	(and (consp a) (eq (car a) 'frac)
+	     (Math-lessp (nth 1 a) (nth 2 a))
+	     (setq a (math-div 1 a) apow (math-neg apow)))
+	(and (consp b)
+	     (cond ((and (eq (car b) '^)
+			 (or math-simplifying
+			     (Math-numberp (nth 2 b))))
+		    (setq bpow (nth 2 b)
+			  b (nth 1 b)))
+		   ((eq (car b) 'calcFunc-sqrt)
+		    (setq bpow '(frac 1 2)
+			  b (nth 1 b)))
+		   ((and (eq (car b) 'calcFunc-exp)
+			 (or math-simplifying
+			     (Math-numberp (nth 1 b))))
+		    (setq bpow (nth 1 b)
+			  b math-combine-prod-e))))
+	(and (consp b) (eq (car b) 'frac)
+	     (Math-lessp (nth 1 b) (nth 2 b))
+	     (setq b (math-div 1 b) bpow (math-neg bpow)))
+	(if inva (setq apow (math-neg apow)))
+	(if invb (setq bpow (math-neg bpow)))
+	(or (and (if math-simplifying
+		     (math-commutative-equal a b)
+		   (equal a b))
+		 (let ((sumpow (math-add apow bpow)))
+		   (and (or (not (Math-integerp a))
+			    (Math-zerop sumpow)
+			    (eq (eq (car-safe apow) 'frac)
+				(eq (car-safe bpow) 'frac)))
+			(progn
+			  (and (math-looks-negp sumpow)
+			       (Math-ratp a) (Math-posp a)
+			       (setq a (math-div 1 a)
+				     sumpow (math-neg sumpow)))
+			  (cond ((equal sumpow '(frac 1 2))
+				 (list 'calcFunc-sqrt a))
+				((equal sumpow '(frac -1 2))
+				 (math-div 1 (list 'calcFunc-sqrt a)))
+				((and (eq a math-combine-prod-e)
+				      (eq a b))
+				 (list 'calcFunc-exp sumpow))
+				(t
+				 (condition-case err
+				     (math-pow a sumpow)
+				   (inexact-result (list '^ a sumpow)))))))))
+	    (and math-simplifying-units
+		 math-combining-units
+		 (let* ((ua (math-check-unit-name a))
+			ub)
+		   (and ua
+			(eq ua (setq ub (math-check-unit-name b)))
+			(progn
+			  (setq ua (if (eq (nth 1 a) (car ua))
+				       1
+				     (nth 1 (assq (aref (symbol-name (nth 1 a))
+							0)
+						  math-unit-prefixes)))
+				ub (if (eq (nth 1 b) (car ub))
+				       1
+				     (nth 1 (assq (aref (symbol-name (nth 1 b))
+							0)
+						  math-unit-prefixes))))
+			  (if (Math-lessp ua ub)
+			      (let (temp)
+				(setq temp a a b b temp
+				      temp ua ua ub ub temp
+				      temp apow apow bpow bpow temp)))
+			  (math-mul (math-pow (math-div ua ub) apow)
+				    (math-pow b (math-add apow bpow)))))))
+	    (and (equal apow bpow)
+		 (Math-natnump a) (Math-natnump b)
+		 (cond ((equal apow '(frac 1 2))
+			(list 'calcFunc-sqrt (math-mul a b)))
+		       ((equal apow '(frac -1 2))
+			(math-div 1 (list 'calcFunc-sqrt (math-mul a b))))
+		       (t
+			(setq a (math-mul a b))
+			(condition-case err
+			    (math-pow a apow)
+			  (inexact-result (list '^ a apow))))))))))
+)
+(setq math-combine-prod-e '(var e var-e))
+
+(defun math-mul-or-div (a b ainv binv)
+  (if (or (Math-vectorp a) (Math-vectorp b))
+      (math-normalize
+       (if ainv
+	   (if binv
+	       (list '/ (math-div 1 a) b)
+	     (list '/ b a))
+	 (if binv
+	     (list '/ a b)
+	   (list '* a b))))
+    (if ainv
+	(if binv
+	    (math-div (math-div 1 a) b)
+	  (math-div b a))
+      (if binv
+	  (math-div a b)
+	(math-mul a b))))
+)
+
+(defun math-commutative-equal (a b)
+  (if (memq (car-safe a) '(+ -))
+      (and (memq (car-safe b) '(+ -))
+	   (let ((bterms nil) aterms p)
+	     (math-commutative-collect b nil)
+	     (setq aterms bterms bterms nil)
+	     (math-commutative-collect a nil)
+	     (and (= (length aterms) (length bterms))
+		  (progn
+		    (while (and aterms
+				(progn
+				  (setq p bterms)
+				  (while (and p (not (equal (car aterms)
+							    (car p))))
+				    (setq p (cdr p)))
+				  p))
+		      (setq bterms (delq (car p) bterms)
+			    aterms (cdr aterms)))
+		    (not aterms)))))
+    (equal a b))
+)
+
+(defun math-commutative-collect (b neg)
+  (if (eq (car-safe b) '+)
+      (progn
+	(math-commutative-collect (nth 1 b) neg)
+	(math-commutative-collect (nth 2 b) neg))
+    (if (eq (car-safe b) '-)
+	(progn
+	  (math-commutative-collect (nth 1 b) neg)
+	  (math-commutative-collect (nth 2 b) (not neg)))
+      (setq bterms (cons (if neg (math-neg b) b) bterms))))
+)
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/calc-bin.el	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,847 @@
+;; Calculator for GNU Emacs, part II [calc-bin.el]
+;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+;; Written by Dave Gillespie, daveg@synaptics.com.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY.  No author or distributor
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing.  Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License.   A copy of this license is
+;; supposed to have been given to you along with GNU Emacs so you
+;; can know your rights and responsibilities.  It should be in a
+;; file named COPYING.  Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+
+
+
+;; This file is autoloaded from calc-ext.el.
+(require 'calc-ext)
+
+(require 'calc-macs)
+
+(defun calc-Need-calc-bin () nil)
+
+
+;;; b-prefix binary commands.
+
+(defun calc-and (n)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-enter-result 2 "and"
+		      (append '(calcFunc-and)
+			      (calc-top-list-n 2)
+			      (and n (list (prefix-numeric-value n))))))
+)
+
+(defun calc-or (n)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-enter-result 2 "or"
+		      (append '(calcFunc-or)
+			      (calc-top-list-n 2)
+			      (and n (list (prefix-numeric-value n))))))
+)
+
+(defun calc-xor (n)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-enter-result 2 "xor"
+		      (append '(calcFunc-xor)
+			      (calc-top-list-n 2)
+			      (and n (list (prefix-numeric-value n))))))
+)
+
+(defun calc-diff (n)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-enter-result 2 "diff"
+		      (append '(calcFunc-diff)
+			      (calc-top-list-n 2)
+			      (and n (list (prefix-numeric-value n))))))
+)
+
+(defun calc-not (n)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-enter-result 1 "not"
+		      (append '(calcFunc-not)
+			      (calc-top-list-n 1)
+			      (and n (list (prefix-numeric-value n))))))
+)
+
+(defun calc-lshift-binary (n)
+  (interactive "P")
+  (calc-slow-wrapper
+   (let ((hyp (if (calc-is-hyperbolic) 2 1)))
+     (calc-enter-result hyp "lsh"
+			(append '(calcFunc-lsh)
+				(calc-top-list-n hyp)
+				(and n (list (prefix-numeric-value n)))))))
+)
+
+(defun calc-rshift-binary (n)
+  (interactive "P")
+  (calc-slow-wrapper
+   (let ((hyp (if (calc-is-hyperbolic) 2 1)))
+     (calc-enter-result hyp "rsh"
+			(append '(calcFunc-rsh)
+				(calc-top-list-n hyp)
+				(and n (list (prefix-numeric-value n)))))))
+)
+
+(defun calc-lshift-arith (n)
+  (interactive "P")
+  (calc-slow-wrapper
+   (let ((hyp (if (calc-is-hyperbolic) 2 1)))
+     (calc-enter-result hyp "ash"
+			(append '(calcFunc-ash)
+				(calc-top-list-n hyp)
+				(and n (list (prefix-numeric-value n)))))))
+)
+
+(defun calc-rshift-arith (n)
+  (interactive "P")
+  (calc-slow-wrapper
+   (let ((hyp (if (calc-is-hyperbolic) 2 1)))
+     (calc-enter-result hyp "rash"
+			(append '(calcFunc-rash)
+				(calc-top-list-n hyp)
+				(and n (list (prefix-numeric-value n)))))))
+)
+
+(defun calc-rotate-binary (n)
+  (interactive "P")
+  (calc-slow-wrapper
+   (let ((hyp (if (calc-is-hyperbolic) 2 1)))
+     (calc-enter-result hyp "rot"
+			(append '(calcFunc-rot)
+				(calc-top-list-n hyp)
+				(and n (list (prefix-numeric-value n)))))))
+)
+
+(defun calc-clip (n)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-enter-result 1 "clip"
+		      (append '(calcFunc-clip)
+			      (calc-top-list-n 1)
+			      (and n (list (prefix-numeric-value n))))))
+)
+
+(defun calc-word-size (n)
+  (interactive "P")
+  (calc-wrapper
+   (or n (setq n (read-string (format "Binary word size: (default %d) "
+				      calc-word-size))))
+   (setq n (if (stringp n)
+	       (if (equal n "")
+		   calc-word-size
+		 (if (string-match "\\`[-+]?[0-9]+\\'" n)
+		     (string-to-int n)
+		   (error "Expected an integer")))
+	     (prefix-numeric-value n)))
+   (or (= n calc-word-size)
+       (if (> (math-abs n) 100)
+	   (calc-change-mode 'calc-word-size n calc-leading-zeros)
+	 (calc-change-mode '(calc-word-size calc-previous-modulo)
+			   (list n (math-power-of-2 (math-abs n)))
+			   calc-leading-zeros)))
+   (if (< n 0)
+       (message "Binary word size is %d bits (2's complement)." (- n))
+     (message "Binary word size is %d bits." n)))
+)
+
+
+
+
+
+;;; d-prefix mode commands.
+
+(defun calc-radix (n)
+  (interactive "NDisplay radix (2-36): ")
+  (calc-wrapper
+   (if (and (>= n 2) (<= n 36))
+       (progn
+	 (calc-change-mode 'calc-number-radix n t)
+	 ;; also change global value so minibuffer sees it
+	 (setq-default calc-number-radix calc-number-radix))
+     (setq n calc-number-radix))
+   (message "Number radix is %d." n))
+)
+
+(defun calc-decimal-radix ()
+  (interactive)
+  (calc-radix 10)
+)
+
+(defun calc-binary-radix ()
+  (interactive)
+  (calc-radix 2)
+)
+
+(defun calc-octal-radix ()
+  (interactive)
+  (calc-radix 8)
+)
+
+(defun calc-hex-radix ()
+  (interactive)
+  (calc-radix 16)
+)
+
+(defun calc-leading-zeros (n)
+  (interactive "P")
+  (calc-wrapper
+   (if (calc-change-mode 'calc-leading-zeros n t t)
+       (message "Zero-padding integers to %d digits (assuming radix %d)."
+		(let* ((calc-internal-prec 6))
+		  (math-compute-max-digits (math-abs calc-word-size)
+					   calc-number-radix))
+		calc-number-radix)
+     (message "Omitting leading zeros on integers.")))
+)
+
+
+(defvar math-power-of-2-cache (list 1 2 4 8 16 32 64 128 256 512 1024))
+(defvar math-big-power-of-2-cache nil)
+(defun math-power-of-2 (n)    ;  [I I] [Public]
+  (if (and (natnump n) (<= n 100))
+      (or (nth n math-power-of-2-cache)
+	  (let* ((i (length math-power-of-2-cache))
+		 (val (nth (1- i) math-power-of-2-cache)))
+	    (while (<= i n)
+	      (setq val (math-mul val 2)
+		    math-power-of-2-cache (nconc math-power-of-2-cache
+						 (list val))
+		    i (1+ i)))
+	    val))
+    (let ((found (assq n math-big-power-of-2-cache)))
+      (if found
+	  (cdr found)
+	(let ((po2 (math-ipow 2 n)))
+	  (setq math-big-power-of-2-cache
+		(cons (cons n po2) math-big-power-of-2-cache))
+	  po2))))
+)
+
+(defun math-integer-log2 (n)    ; [I I] [Public]
+  (let ((i 0)
+	(p math-power-of-2-cache)
+	val)
+    (while (and p (Math-natnum-lessp (setq val (car p)) n))
+      (setq p (cdr p)
+	    i (1+ i)))
+    (if p
+	(and (equal val n)
+	     i)
+      (while (Math-natnum-lessp
+	      (prog1
+		  (setq val (math-mul val 2))
+		(setq math-power-of-2-cache (nconc math-power-of-2-cache
+						   (list val))))
+	      n)
+	(setq i (1+ i)))
+      (and (equal val n)
+	   i)))
+)
+
+
+
+
+;;; Bitwise operations.
+
+(defun calcFunc-and (a b &optional w)   ; [I I I] [Public]
+  (cond ((Math-messy-integerp w)
+	 (calcFunc-and a b (math-trunc w)))
+	((and w (not (integerp w)))
+	 (math-reject-arg w 'fixnump))
+	((and (integerp a) (integerp b))
+	 (math-clip (logand a b) w))
+	((or (eq (car-safe a) 'mod) (eq (car-safe b) 'mod))
+	 (math-binary-modulo-args 'calcFunc-and a b w))
+	((not (Math-num-integerp a))
+	 (math-reject-arg a 'integerp))
+	((not (Math-num-integerp b))
+	 (math-reject-arg b 'integerp))
+	(t (math-clip (cons 'bigpos
+			    (math-and-bignum (math-binary-arg a w)
+					     (math-binary-arg b w)))
+		      w)))
+)
+
+(defun math-binary-arg (a w)
+  (if (not (Math-integerp a))
+      (setq a (math-trunc a)))
+  (if (Math-integer-negp a)
+      (math-not-bignum (cdr (math-bignum-test (math-sub -1 a)))
+		       (math-abs (if w (math-trunc w) calc-word-size)))
+    (cdr (Math-bignum-test a)))
+)
+
+(defun math-binary-modulo-args (f a b w)
+  (let (mod)
+    (if (eq (car-safe a) 'mod)
+	(progn
+	  (setq mod (nth 2 a)
+		a (nth 1 a))
+	  (if (eq (car-safe b) 'mod)
+	      (if (equal mod (nth 2 b))
+		  (setq b (nth 1 b))
+		(math-reject-arg b "*Inconsistent modulos"))))
+      (setq mod (nth 2 b)
+	    b (nth 1 b)))
+    (if (Math-messy-integerp mod)
+	(setq mod (math-trunc mod))
+      (or (Math-integerp mod)
+	  (math-reject-arg mod 'integerp)))
+    (let ((bits (math-integer-log2 mod)))
+      (if bits
+	  (if w
+	      (if (/= w bits)
+		  (calc-record-why
+		   "*Warning: Modulo inconsistent with word size"))
+	    (setq w bits))
+	(calc-record-why "*Warning: Modulo is not a power of 2"))
+      (math-make-mod (if b
+			 (funcall f a b w)
+		       (funcall f a w))
+		     mod)))
+)
+
+(defun math-and-bignum (a b)   ; [l l l]
+  (and a b
+       (let ((qa (math-div-bignum-digit a 512))
+	     (qb (math-div-bignum-digit b 512)))
+	 (math-mul-bignum-digit (math-and-bignum (math-norm-bignum (car qa))
+						  (math-norm-bignum (car qb)))
+				 512
+				 (logand (cdr qa) (cdr qb)))))
+)
+
+(defun calcFunc-or (a b &optional w)   ; [I I I] [Public]
+  (cond ((Math-messy-integerp w)
+	 (calcFunc-or a b (math-trunc w)))
+	((and w (not (integerp w)))
+	 (math-reject-arg w 'fixnump))
+	((and (integerp a) (integerp b))
+	 (math-clip (logior a b) w))
+	((or (eq (car-safe a) 'mod) (eq (car-safe b) 'mod))
+	 (math-binary-modulo-args 'calcFunc-or a b w))
+	((not (Math-num-integerp a))
+	 (math-reject-arg a 'integerp))
+	((not (Math-num-integerp b))
+	 (math-reject-arg b 'integerp))
+	(t (math-clip (cons 'bigpos
+			    (math-or-bignum (math-binary-arg a w)
+					    (math-binary-arg b w)))
+		      w)))
+)
+
+(defun math-or-bignum (a b)   ; [l l l]
+  (and (or a b)
+       (let ((qa (math-div-bignum-digit a 512))
+	     (qb (math-div-bignum-digit b 512)))
+	 (math-mul-bignum-digit (math-or-bignum (math-norm-bignum (car qa))
+						 (math-norm-bignum (car qb)))
+				 512
+				 (logior (cdr qa) (cdr qb)))))
+)
+
+(defun calcFunc-xor (a b &optional w)   ; [I I I] [Public]
+  (cond ((Math-messy-integerp w)
+	 (calcFunc-xor a b (math-trunc w)))
+	((and w (not (integerp w)))
+	 (math-reject-arg w 'fixnump))
+	((and (integerp a) (integerp b))
+	 (math-clip (logxor a b) w))
+	((or (eq (car-safe a) 'mod) (eq (car-safe b) 'mod))
+	 (math-binary-modulo-args 'calcFunc-xor a b w))
+	((not (Math-num-integerp a))
+	 (math-reject-arg a 'integerp))
+	((not (Math-num-integerp b))
+	 (math-reject-arg b 'integerp))
+	(t (math-clip (cons 'bigpos
+			    (math-xor-bignum (math-binary-arg a w)
+					     (math-binary-arg b w)))
+		      w)))
+)
+
+(defun math-xor-bignum (a b)   ; [l l l]
+  (and (or a b)
+       (let ((qa (math-div-bignum-digit a 512))
+	     (qb (math-div-bignum-digit b 512)))
+	 (math-mul-bignum-digit (math-xor-bignum (math-norm-bignum (car qa))
+						  (math-norm-bignum (car qb)))
+				 512
+				 (logxor (cdr qa) (cdr qb)))))
+)
+
+(defun calcFunc-diff (a b &optional w)   ; [I I I] [Public]
+  (cond ((Math-messy-integerp w)
+	 (calcFunc-diff a b (math-trunc w)))
+	((and w (not (integerp w)))
+	 (math-reject-arg w 'fixnump))
+	((and (integerp a) (integerp b))
+	 (math-clip (logand a (lognot b)) w))
+	((or (eq (car-safe a) 'mod) (eq (car-safe b) 'mod))
+	 (math-binary-modulo-args 'calcFunc-diff a b w))
+	((not (Math-num-integerp a))
+	 (math-reject-arg a 'integerp))
+	((not (Math-num-integerp b))
+	 (math-reject-arg b 'integerp))
+	(t (math-clip (cons 'bigpos
+			    (math-diff-bignum (math-binary-arg a w)
+					      (math-binary-arg b w)))
+		      w)))
+)
+
+(defun math-diff-bignum (a b)   ; [l l l]
+  (and a
+       (let ((qa (math-div-bignum-digit a 512))
+	     (qb (math-div-bignum-digit b 512)))
+	 (math-mul-bignum-digit (math-diff-bignum (math-norm-bignum (car qa))
+						   (math-norm-bignum (car qb)))
+				 512
+				 (logand (cdr qa) (lognot (cdr qb))))))
+)
+
+(defun calcFunc-not (a &optional w)   ; [I I] [Public]
+  (cond ((Math-messy-integerp w)
+	 (calcFunc-not a (math-trunc w)))
+	((eq (car-safe a) 'mod)
+	 (math-binary-modulo-args 'calcFunc-not a nil w))
+	((and w (not (integerp w)))
+	 (math-reject-arg w 'fixnump))
+	((not (Math-num-integerp a))
+	 (math-reject-arg a 'integerp))
+	((< (or w (setq w calc-word-size)) 0)
+	 (math-clip (calcFunc-not a (- w)) w))
+	(t (math-normalize
+	    (cons 'bigpos
+		  (math-not-bignum (math-binary-arg a w)
+				   w)))))
+)
+
+(defun math-not-bignum (a w)   ; [l l]
+  (let ((q (math-div-bignum-digit a 512)))
+    (if (<= w 9)
+	(list (logand (lognot (cdr q))
+		      (1- (lsh 1 w))))
+      (math-mul-bignum-digit (math-not-bignum (math-norm-bignum (car q))
+					       (- w 9))
+			      512
+			      (logxor (cdr q) 511))))
+)
+
+(defun calcFunc-lsh (a &optional n w)   ; [I I] [Public]
+  (setq a (math-trunc a)
+	n (if n (math-trunc n) 1))
+  (if (eq (car-safe a) 'mod)
+      (math-binary-modulo-args 'calcFunc-lsh a n w)
+    (setq w (if w (math-trunc w) calc-word-size))
+    (or (integerp w)
+	(math-reject-arg w 'fixnump))
+    (or (Math-integerp a)
+	(math-reject-arg a 'integerp))
+    (or (Math-integerp n)
+	(math-reject-arg n 'integerp))
+    (if (< w 0)
+	(math-clip (calcFunc-lsh a n (- w)) w)
+      (if (Math-integer-negp a)
+	  (setq a (math-clip a w)))
+      (cond ((or (Math-lessp n (- w))
+		 (Math-lessp w n))
+	     0)
+	    ((< n 0)
+	     (math-quotient (math-clip a w) (math-power-of-2 (- n))))
+	    (t
+	     (math-clip (math-mul a (math-power-of-2 n)) w)))))
+)
+
+(defun calcFunc-rsh (a &optional n w)   ; [I I] [Public]
+  (calcFunc-lsh a (math-neg (or n 1)) w)
+)
+
+(defun calcFunc-ash (a &optional n w)   ; [I I] [Public]
+  (if (or (null n)
+	  (not (Math-negp n)))
+      (calcFunc-lsh a n w)
+    (setq a (math-trunc a)
+	  n (if n (math-trunc n) 1))
+    (if (eq (car-safe a) 'mod)
+	(math-binary-modulo-args 'calcFunc-ash a n w)
+      (setq w (if w (math-trunc w) calc-word-size))
+      (or (integerp w)
+	  (math-reject-arg w 'fixnump))
+      (or (Math-integerp a)
+	  (math-reject-arg a 'integerp))
+      (or (Math-integerp n)
+	  (math-reject-arg n 'integerp))
+      (if (< w 0)
+	  (math-clip (calcFunc-ash a n (- w)) w)
+	(if (Math-integer-negp a)
+	    (setq a (math-clip a w)))
+	(let ((two-to-sizem1 (math-power-of-2 (1- w)))
+	      (sh (calcFunc-lsh a n w)))
+	  (cond ((Math-natnum-lessp a two-to-sizem1)
+		 sh)
+		((Math-lessp n (- 1 w))
+		 (math-add (math-mul two-to-sizem1 2) -1))
+		(t (let ((two-to-n (math-power-of-2 (- n))))
+		     (math-add (calcFunc-lsh (math-add two-to-n -1)
+					     (+ w n) w)
+			       sh))))))))
+)
+
+(defun calcFunc-rash (a &optional n w)   ; [I I] [Public]
+  (calcFunc-ash a (math-neg (or n 1)) w)
+)
+
+(defun calcFunc-rot (a &optional n w)   ; [I I] [Public]
+  (setq a (math-trunc a)
+	n (if n (math-trunc n) 1))
+  (if (eq (car-safe a) 'mod)
+      (math-binary-modulo-args 'calcFunc-rot a n w)
+    (setq w (if w (math-trunc w) calc-word-size))
+    (or (integerp w)
+	(math-reject-arg w 'fixnump))
+    (or (Math-integerp a)
+	(math-reject-arg a 'integerp))
+    (or (Math-integerp n)
+	(math-reject-arg n 'integerp))
+    (if (< w 0)
+	(math-clip (calcFunc-rot a n (- w)) w)
+      (if (Math-integer-negp a)
+	  (setq a (math-clip a w)))
+      (cond ((or (Math-integer-negp n)
+		 (not (Math-natnum-lessp n w)))
+	     (calcFunc-rot a (math-mod n w) w))
+	    (t
+	     (math-add (calcFunc-lsh a (- n w) w)
+		       (calcFunc-lsh a n w))))))
+)
+
+(defun math-clip (a &optional w)   ; [I I] [Public]
+  (cond ((Math-messy-integerp w)
+	 (math-clip a (math-trunc w)))
+	((eq (car-safe a) 'mod)
+	 (math-binary-modulo-args 'math-clip a nil w))
+	((and w (not (integerp w)))
+	 (math-reject-arg w 'fixnump))
+	((not (Math-num-integerp a))
+	 (math-reject-arg a 'integerp))
+	((< (or w (setq w calc-word-size)) 0)
+	 (setq a (math-clip a (- w)))
+	 (if (Math-natnum-lessp a (math-power-of-2 (- -1 w)))
+	     a
+	   (math-sub a (math-power-of-2 (- w)))))
+	((Math-negp a)
+	 (math-normalize (cons 'bigpos (math-binary-arg a w))))
+	((and (integerp a) (< a 1000000))
+	 (if (>= w 20)
+	     a
+	   (logand a (1- (lsh 1 w)))))
+	(t
+	 (math-normalize
+	  (cons 'bigpos
+		(math-clip-bignum (cdr (math-bignum-test (math-trunc a)))
+				  w)))))
+)
+(fset 'calcFunc-clip (symbol-function 'math-clip))
+
+(defun math-clip-bignum (a w)   ; [l l]
+  (let ((q (math-div-bignum-digit a 512)))
+    (if (<= w 9)
+	(list (logand (cdr q)
+		      (1- (lsh 1 w))))
+      (math-mul-bignum-digit (math-clip-bignum (math-norm-bignum (car q))
+						(- w 9))
+			      512
+			      (cdr q))))
+)
+
+
+
+
+(defvar math-max-digits-cache nil)
+(defun math-compute-max-digits (w r)
+  (let* ((pair (+ (* r 100000) w))
+	 (res (assq pair math-max-digits-cache)))
+    (if res
+	(cdr res)
+      (let* ((calc-command-flags nil)
+	     (digs (math-ceiling (math-div w (math-real-log2 r)))))
+	(setq math-max-digits-cache (cons (cons pair digs)
+					  math-max-digits-cache))
+	digs)))
+)
+
+(defvar math-log2-cache (list '(2 . 1)
+			      '(4 . 2)
+			      '(8 . 3)
+			      '(10 . (float 332193 -5))
+			      '(16 . 4)
+			      '(32 . 5)))
+(defun math-real-log2 (x)   ;;; calc-internal-prec must be 6
+  (let ((res (assq x math-log2-cache)))
+    (if res
+	(cdr res)
+      (let* ((calc-symbolic-mode nil)
+	     (calc-display-working-message nil)
+	     (log (calcFunc-log x 2)))
+	(setq math-log2-cache (cons (cons x log) math-log2-cache))
+	log)))
+)
+
+(defconst math-radix-digits ["0" "1" "2" "3" "4" "5" "6" "7" "8" "9"
+			     "A" "B" "C" "D" "E" "F" "G" "H" "I" "J"
+			     "K" "L" "M" "N" "O" "P" "Q" "R" "S" "T"
+			     "U" "V" "W" "X" "Y" "Z"])
+
+(defun math-format-radix (a)   ; [X S]
+  (if (< a calc-number-radix)
+      (if (< a 0)
+	  (concat "-" (math-format-radix (- a)))
+	(math-format-radix-digit a))
+    (let ((s ""))
+      (while (> a 0)
+	(setq s (concat (math-format-radix-digit (% a calc-number-radix)) s)
+	      a (/ a calc-number-radix)))
+      s))
+)
+
+(defconst math-binary-digits ["000" "001" "010" "011"
+			      "100" "101" "110" "111"])
+(defun math-format-binary (a)   ; [X S]
+  (if (< a 8)
+      (if (< a 0)
+	  (concat "-" (math-format-binary (- a)))
+	(math-format-radix a))
+    (let ((s ""))
+      (while (> a 7)
+	(setq s (concat (aref math-binary-digits (% a 8)) s)
+	      a (/ a 8)))
+      (concat (math-format-radix a) s)))
+)
+
+(defun math-format-bignum-radix (a)   ; [X L]
+  (cond ((null a) "0")
+	((and (null (cdr a))
+	      (< (car a) calc-number-radix))
+	 (math-format-radix-digit (car a)))
+	(t
+	 (let ((q (math-div-bignum-digit a calc-number-radix)))
+	   (concat (math-format-bignum-radix (math-norm-bignum (car q)))
+		   (math-format-radix-digit (cdr q))))))
+)
+
+(defun math-format-bignum-binary (a)   ; [X L]
+  (cond ((null a) "0")
+	((null (cdr a))
+	 (math-format-binary (car a)))
+	(t
+	 (let ((q (math-div-bignum-digit a 512)))
+	   (concat (math-format-bignum-binary (math-norm-bignum (car q)))
+		   (aref math-binary-digits (/ (cdr q) 64))
+		   (aref math-binary-digits (% (/ (cdr q) 8) 8))
+		   (aref math-binary-digits (% (cdr q) 8))))))
+)
+
+(defun math-format-bignum-octal (a)   ; [X L]
+  (cond ((null a) "0")
+	((null (cdr a))
+	 (math-format-radix (car a)))
+	(t
+	 (let ((q (math-div-bignum-digit a 512)))
+	   (concat (math-format-bignum-octal (math-norm-bignum (car q)))
+		   (math-format-radix-digit (/ (cdr q) 64))
+		   (math-format-radix-digit (% (/ (cdr q) 8) 8))
+		   (math-format-radix-digit (% (cdr q) 8))))))
+)
+
+(defun math-format-bignum-hex (a)   ; [X L]
+  (cond ((null a) "0")
+	((null (cdr a))
+	 (math-format-radix (car a)))
+	(t
+	 (let ((q (math-div-bignum-digit a 256)))
+	   (concat (math-format-bignum-hex (math-norm-bignum (car q)))
+		   (math-format-radix-digit (/ (cdr q) 16))
+		   (math-format-radix-digit (% (cdr q) 16))))))
+)
+
+;;; Decompose into integer and fractional parts, without depending
+;;; on calc-internal-prec.
+(defun math-float-parts (a need-frac)    ; returns ( int frac fracdigs )
+  (if (>= (nth 2 a) 0)
+      (list (math-scale-rounding (nth 1 a) (nth 2 a)) '(float 0 0) 0)
+    (let* ((d (math-numdigs (nth 1 a)))
+	   (n (- (nth 2 a))))
+      (if need-frac
+	  (if (>= n d)
+	      (list 0 a n)
+	    (let ((qr (math-idivmod (nth 1 a) (math-scale-int 1 n))))
+	      (list (car qr) (math-make-float (cdr qr) (- n)) n)))
+	(list (math-scale-rounding (nth 1 a) (nth 2 a))
+	      '(float 0 0) 0))))
+)
+
+(defun math-format-radix-float (a prec)
+  (let ((fmt (car calc-float-format))
+	(figs (nth 1 calc-float-format))
+	(point calc-point-char)
+	(str nil))
+    (if (eq fmt 'fix)
+	(let* ((afigs (math-abs figs))
+	       (fp (math-float-parts a (> afigs 0)))
+	       (calc-internal-prec (+ 3 (max (nth 2 fp)
+					     (math-convert-radix-digits
+					      afigs t))))
+	       (int (car fp))
+	       (frac (math-round (math-mul (math-normalize (nth 1 fp))
+					   (math-radix-float-power afigs)))))
+	  (if (not (and (math-zerop frac) (math-zerop int) (< figs 0)))
+	      (let ((math-radix-explicit-format nil))
+		(let ((calc-group-digits nil))
+		  (setq str (if (> afigs 0) (math-format-number frac) ""))
+		  (if (< (length str) afigs)
+		      (setq str (concat (make-string (- afigs (length str)) ?0)
+					str))
+		    (if (> (length str) afigs)
+			(setq str (substring str 1)
+			      int (math-add int 1))))
+		  (setq str (concat (math-format-number int) point str)))
+		(if calc-group-digits
+		    (setq str (math-group-float str))))
+	    (setq figs 0))))
+    (or str
+	(let* ((prec calc-internal-prec)
+	       (afigs (if (> figs 0)
+			  figs
+			(max 1 (+ figs
+				  (1- (math-convert-radix-digits
+				       (max prec
+					    (math-numdigs (nth 1 a)))))))))
+	       (calc-internal-prec (+ 3 (math-convert-radix-digits afigs t)))
+	       (explo -1) (vlo (math-radix-float-power explo))
+	       (exphi 1) (vhi (math-radix-float-power exphi))
+	       expmid vmid eadj)
+	  (setq a (math-normalize a))
+	  (if (Math-zerop a)
+	      (setq explo 0)
+	    (if (math-lessp-float '(float 1 0) a)
+		(while (not (math-lessp-float a vhi))
+		  (setq explo exphi vlo vhi
+			exphi (math-mul exphi 2)
+			vhi (math-radix-float-power exphi)))
+	      (while (math-lessp-float a vlo)
+		(setq exphi explo vhi vlo
+		      explo (math-mul explo 2)
+		      vlo (math-radix-float-power explo))))
+	    (while (not (eq (math-sub exphi explo) 1))
+	      (setq expmid (math-div2 (math-add explo exphi))
+		    vmid (math-radix-float-power expmid))
+	      (if (math-lessp-float a vmid)
+		  (setq exphi expmid vhi vmid)
+		(setq explo expmid vlo vmid)))
+	    (setq a (math-div-float a vlo)))
+	  (let* ((sc (math-round (math-mul a (math-radix-float-power
+					      (1- afigs)))))
+		 (math-radix-explicit-format nil))
+	    (let ((calc-group-digits nil))
+	      (setq str (math-format-number sc))))
+	  (if (> (length str) afigs)
+	      (setq str (substring str 0 -1)
+		    explo (1+ explo)))
+	  (if (and (eq fmt 'float)
+		   (math-lessp explo (+ (if (= figs 0)
+					    (1- (math-convert-radix-digits
+						 prec))
+					  afigs)
+					calc-display-sci-high 1))
+		   (math-lessp calc-display-sci-low explo))
+	      (let ((dpos (1+ explo)))
+		(cond ((<= dpos 0)
+		       (setq str (concat "0" point (make-string (- dpos) ?0)
+					 str)))
+		      ((> dpos (length str))
+		       (setq str (concat str (make-string (- dpos (length str))
+							  ?0) point)))
+		      (t
+		       (setq str (concat (substring str 0 dpos) point
+					 (substring str dpos)))))
+		(setq explo nil))
+	    (setq eadj (if (eq fmt 'eng)
+			   (min (math-mod explo 3) (length str))
+			 0)
+		  str (concat (substring str 0 (1+ eadj)) point
+			      (substring str (1+ eadj)))))
+	  (setq pos (length str))
+	  (while (eq (aref str (1- pos)) ?0) (setq pos (1- pos)))
+	  (and explo (eq (aref str (1- pos)) ?.) (setq pos (1- pos)))
+	  (setq str (substring str 0 pos))
+	  (if calc-group-digits
+	      (setq str (math-group-float str)))
+	  (if explo
+	      (let ((estr (let ((calc-number-radix 10)
+				(calc-group-digits nil))
+			    (setq estr (math-format-number
+					(math-sub explo eadj))))))
+		(setq str (if (or (memq calc-language '(math maple))
+				  (> calc-number-radix 14))
+			      (format "%s*%d.^%s" str calc-number-radix estr)
+			    (format "%se%s" str estr)))))))
+    str)
+)
+
+(defun math-convert-radix-digits (n &optional to-dec)
+  (let ((key (cons n (cons to-dec calc-number-radix))))
+    (or (cdr (assoc key math-radix-digits-cache))
+	(let* ((calc-internal-prec 6)
+	       (log (math-div (math-real-log2 calc-number-radix)
+			      '(float 332193 -5))))
+	  (cdr (car (setq math-radix-digits-cache
+			  (cons (cons key (math-ceiling (if to-dec
+							    (math-mul n log)
+							  (math-div n log))))
+				math-radix-digits-cache)))))))
+)
+(setq math-radix-digits-cache nil)
+
+(defun math-radix-float-power (n)
+  (if (eq n 0)
+      '(float 1 0)
+    (or (and (eq calc-number-radix (car math-radix-float-cache-tag))
+	     (<= calc-internal-prec (cdr math-radix-float-cache-tag)))
+	(setq math-radix-float-cache-tag (cons calc-number-radix
+					       calc-internal-prec)
+	      math-radix-float-cache nil))
+    (math-normalize
+     (or (cdr (assoc n math-radix-float-cache))
+	 (cdr (car (setq math-radix-float-cache
+			 (cons (cons
+				n
+				(let ((calc-internal-prec
+				       (cdr math-radix-float-cache-tag)))
+				  (if (math-negp n)
+				      (math-div-float '(float 1 0)
+						      (math-radix-float-power
+						       (math-neg n)))
+				    (math-mul-float (math-sqr-float
+						     (math-radix-float-power
+						      (math-div2 n)))
+						    (if (math-evenp n)
+							'(float 1 0)
+						      (math-float
+						       calc-number-radix))))))
+			       math-radix-float-cache)))))))
+)
+(setq math-radix-float-cache-tag nil)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/calc-comb.el	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,1056 @@
+;; Calculator for GNU Emacs, part II [calc-comb.el]
+;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+;; Written by Dave Gillespie, daveg@synaptics.com.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY.  No author or distributor
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing.  Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License.   A copy of this license is
+;; supposed to have been given to you along with GNU Emacs so you
+;; can know your rights and responsibilities.  It should be in a
+;; file named COPYING.  Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+
+
+
+;; This file is autoloaded from calc-ext.el.
+(require 'calc-ext)
+
+(require 'calc-macs)
+
+(defun calc-Need-calc-comb () nil)
+
+
+;;; Combinatorics
+
+(defun calc-gcd (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-binary-op "gcd" 'calcFunc-gcd arg))
+)
+
+(defun calc-lcm (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-binary-op "lcm" 'calcFunc-lcm arg))
+)
+
+(defun calc-extended-gcd ()
+  (interactive)
+  (calc-slow-wrapper
+   (calc-enter-result 2 "egcd" (cons 'calcFunc-egcd (calc-top-list-n 2))))
+)
+
+(defun calc-factorial (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-unary-op "fact" 'calcFunc-fact arg))
+)
+
+(defun calc-gamma (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-unary-op "gmma" 'calcFunc-gamma arg))
+)
+
+(defun calc-double-factorial (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-unary-op "dfac" 'calcFunc-dfact arg))
+)
+
+(defun calc-choose (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (if (calc-is-hyperbolic)
+       (calc-binary-op "perm" 'calcFunc-perm arg)
+     (calc-binary-op "chos" 'calcFunc-choose arg)))
+)
+
+(defun calc-perm (arg)
+  (interactive "P")
+  (calc-hyperbolic-func)
+  (calc-choose arg)
+)
+
+(defvar calc-last-random-limit '(float 1 0))
+(defun calc-random (n)
+  (interactive "P")
+  (calc-slow-wrapper
+   (if n
+       (calc-enter-result 0 "rand" (list 'calcFunc-random
+					 (calc-get-random-limit
+					  (prefix-numeric-value n))))
+     (calc-enter-result 1 "rand" (list 'calcFunc-random
+				       (calc-get-random-limit
+					(calc-top-n 1))))))
+)
+
+(defun calc-get-random-limit (val)
+  (if (eq val 0)
+      calc-last-random-limit
+    (setq calc-last-random-limit val))
+)
+
+(defun calc-rrandom ()
+  (interactive)
+  (calc-slow-wrapper
+   (setq calc-last-random-limit '(float 1 0))
+   (calc-enter-result 0 "rand" (list 'calcFunc-random '(float 1 0))))
+)
+
+(defun calc-random-again (arg)
+  (interactive "p")
+  (calc-slow-wrapper
+   (while (>= (setq arg (1- arg)) 0)
+     (calc-enter-result 0 "rand" (list 'calcFunc-random
+				       calc-last-random-limit))))
+)
+
+(defun calc-shuffle (n)
+  (interactive "P")
+  (calc-slow-wrapper
+   (if n
+       (calc-enter-result 1 "shuf" (list 'calcFunc-shuffle
+					 (prefix-numeric-value n)
+					 (calc-get-random-limit
+					  (calc-top-n 1))))
+     (calc-enter-result 2 "shuf" (list 'calcFunc-shuffle
+				       (calc-top-n 1)
+				       (calc-get-random-limit
+					(calc-top-n 2))))))
+)
+
+(defun calc-report-prime-test (res)
+  (cond ((eq (car res) t)
+	 (calc-record-message "prim" "Prime (guaranteed)"))
+	((eq (car res) nil)
+	 (if (cdr res)
+	     (if (eq (nth 1 res) 'unknown)
+		 (calc-record-message
+		  "prim" "Non-prime (factors unknown)")
+	       (calc-record-message
+		"prim" "Non-prime (%s is a factor)"
+		(math-format-number (nth 1 res))))
+	   (calc-record-message "prim" "Non-prime")))
+	(t
+	 (calc-record-message
+	  "prim" "Probably prime (%d iters; %s%% chance of error)"
+	  (nth 1 res)
+	  (let ((calc-float-format '(fix 2)))
+	    (math-format-number (nth 2 res))))))
+)
+
+(defun calc-prime-test (iters)
+  (interactive "p")
+  (calc-slow-wrapper
+   (let* ((n (calc-top-n 1))
+	  (res (math-prime-test n iters)))
+     (calc-report-prime-test res)))
+)
+
+(defun calc-next-prime (iters)
+  (interactive "p")
+  (calc-slow-wrapper
+   (let ((calc-verbose-nextprime t))
+     (if (calc-is-inverse)
+	 (calc-enter-result 1 "prvp" (list 'calcFunc-prevprime
+					   (calc-top-n 1) (math-abs iters)))
+       (calc-enter-result 1 "nxtp" (list 'calcFunc-nextprime
+					 (calc-top-n 1) (math-abs iters))))))
+)
+
+(defun calc-prev-prime (iters)
+  (interactive "p")
+  (calc-invert-func)
+  (calc-next-prime iters)
+)
+
+(defun calc-prime-factors (iters)
+  (interactive "p")
+  (calc-slow-wrapper
+   (let ((res (calcFunc-prfac (calc-top-n 1))))
+     (if (not math-prime-factors-finished)
+	 (calc-record-message "pfac" "Warning:  May not be fully factored"))
+     (calc-enter-result 1 "pfac" res)))
+)
+
+(defun calc-totient (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-unary-op "phi" 'calcFunc-totient arg))
+)
+
+(defun calc-moebius (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-unary-op "mu" 'calcFunc-moebius arg))
+)
+
+
+
+
+
+(defun calcFunc-gcd (a b)
+  (if (Math-messy-integerp a)
+      (setq a (math-trunc a)))
+  (if (Math-messy-integerp b)
+      (setq b (math-trunc b)))
+  (cond ((and (Math-integerp a) (Math-integerp b))
+	 (math-gcd a b))
+	((Math-looks-negp a)
+	 (calcFunc-gcd (math-neg a) b))
+	((Math-looks-negp b)
+	 (calcFunc-gcd a (math-neg b)))
+	((Math-zerop a) b)
+	((Math-zerop b) a)
+	((and (Math-ratp a)
+	      (Math-ratp b))
+	 (math-make-frac (math-gcd (if (eq (car-safe a) 'frac) (nth 1 a) a)
+				   (if (eq (car-safe b) 'frac) (nth 1 b) b))
+			 (calcFunc-lcm
+			  (if (eq (car-safe a) 'frac) (nth 2 a) 1)
+			  (if (eq (car-safe b) 'frac) (nth 2 b) 1))))
+	((not (Math-integerp a))
+	 (calc-record-why 'integerp a)
+	 (list 'calcFunc-gcd a b))
+	(t
+	 (calc-record-why 'integerp b)
+	 (list 'calcFunc-gcd a b)))
+)
+
+(defun calcFunc-lcm (a b)
+  (let ((g (calcFunc-gcd a b)))
+    (if (Math-numberp g)
+	(math-div (math-mul a b) g)
+      (list 'calcFunc-lcm a b)))
+)
+
+(defun calcFunc-egcd (a b)   ; Knuth section 4.5.2
+  (cond
+   ((not (Math-integerp a))
+    (if (Math-messy-integerp a)
+	(calcFunc-egcd (math-trunc a) b)
+      (calc-record-why 'integerp a)
+      (list 'calcFunc-egcd a b)))
+   ((not (Math-integerp b))
+    (if (Math-messy-integerp b)
+	(calcFunc-egcd a (math-trunc b))
+      (calc-record-why 'integerp b)
+      (list 'calcFunc-egcd a b)))
+   (t
+    (let ((u1 1) (u2 0) (u3 a)
+	  (v1 0) (v2 1) (v3 b)
+	  t1 t2 q)
+      (while (not (eq v3 0))
+	(setq q (math-idivmod u3 v3)
+	      t1 (math-sub u1 (math-mul v1 (car q)))
+	      t2 (math-sub u2 (math-mul v2 (car q)))
+	      u1 v1  u2 v2  u3 v3
+	      v1 t1  v2 t2  v3 (cdr q)))
+      (list 'vec u3 u1 u2))))
+)
+
+
+;;; Factorial and related functions.
+
+(defun calcFunc-fact (n)   ; [I I] [F F] [Public]
+  (let (temp)
+    (cond ((Math-integer-negp n)
+	   (if calc-infinite-mode
+	       '(var uinf var-uinf)
+	     (math-reject-arg n 'range)))
+	  ((integerp n)
+	   (if (<= n 20)
+	       (aref '[1 1 2 6 24 120 720 5040 40320 362880
+			 (bigpos 800 628 3) (bigpos 800 916 39)
+			 (bigpos 600 1 479) (bigpos 800 20 227 6)
+			 (bigpos 200 291 178 87) (bigpos 0 368 674 307 1)
+			 (bigpos 0 888 789 922 20) (bigpos 0 96 428 687 355)
+			 (bigpos 0 728 705 373 402 6)
+			 (bigpos 0 832 408 100 645 121)
+			 (bigpos 0 640 176 8 902 432 2)] n)
+	     (math-factorial-iter (1- n) 2 1)))
+	  ((and (math-messy-integerp n)
+		(Math-lessp n 100))
+	   (math-inexact-result)
+	   (setq temp (math-trunc n))
+	   (if (>= temp 0)
+	       (if (<= temp 20)
+		   (math-float (calcFunc-fact temp))
+		 (math-with-extra-prec 1
+		   (math-factorial-iter (1- temp) 2 '(float 1 0))))
+	     (math-reject-arg n 'range)))
+	  ((math-numberp n)
+	   (let* ((q (math-quarter-integer n))
+		  (tn (and q (Math-lessp n 1000) (Math-lessp -1000 n)
+			   (1+ (math-floor n)))))
+	     (cond ((and tn (= q 2)
+			 (or calc-symbolic-mode (< (math-abs tn) 20)))
+		    (let ((q (if (< tn 0)
+				 (math-div
+				  (math-pow -2 (- tn))
+				  (math-double-factorial-iter (* -2 tn) 3 1 2))
+			       (math-div 
+				(math-double-factorial-iter (* 2 tn) 3 1 2)
+				(math-pow 2 tn)))))
+		      (math-mul q (if calc-symbolic-mode
+				      (list 'calcFunc-sqrt '(var pi var-pi))
+				    (math-sqrt-pi)))))
+		   ((and tn (>= tn 0) (< tn 20)
+			 (memq q '(1 3)))
+		    (math-inexact-result)
+		    (math-div
+		     (math-mul (math-double-factorial-iter (* 4 tn) q 1 4)
+			       (if (= q 1) (math-gamma-1q) (math-gamma-3q)))
+		     (math-pow 4 tn)))
+		   (t
+		    (math-inexact-result)
+		    (math-with-extra-prec 3
+		      (math-gammap1-raw (math-float n)))))))
+	  ((equal n '(var inf var-inf)) n)
+	  (t (calc-record-why 'numberp n)
+	     (list 'calcFunc-fact n))))
+)
+
+(math-defcache math-gamma-1q nil
+  (math-with-extra-prec 3
+    (math-gammap1-raw '(float -75 -2))))
+
+(math-defcache math-gamma-3q nil
+  (math-with-extra-prec 3
+    (math-gammap1-raw '(float -25 -2))))
+
+(defun math-factorial-iter (count n f)
+  (if (= (% n 5) 1)
+      (math-working (format "factorial(%d)" (1- n)) f))
+  (if (> count 0)
+      (math-factorial-iter (1- count) (1+ n) (math-mul n f))
+    f)
+)
+
+(defun calcFunc-dfact (n)   ; [I I] [F F] [Public]
+  (cond ((Math-integer-negp n)
+	 (if (math-oddp n)
+	     (if (eq n -1)
+		 1
+	       (math-div (if (eq (math-mod n 4) 3) 1 -1)
+			 (calcFunc-dfact (math-sub -2 n))))
+	   (list 'calcFunc-dfact n)))
+	((Math-zerop n) 1)
+	((integerp n) (math-double-factorial-iter n (+ 2 (% n 2)) 1 2))
+	((math-messy-integerp n)
+	 (let ((temp (math-trunc n)))
+	   (math-inexact-result)
+	   (if (natnump temp)
+	       (if (Math-lessp temp 200)
+		   (math-with-extra-prec 1
+		     (math-double-factorial-iter temp (+ 2 (% temp 2))
+						 '(float 1 0) 2))
+		 (let* ((half (math-div2 temp))
+			(even (math-mul (math-pow 2 half)
+					(calcFunc-fact (math-float half)))))
+		   (if (math-evenp temp)
+		       even
+		     (math-div (calcFunc-fact n) even))))
+	     (list 'calcFunc-dfact max))))
+	((equal n '(var inf var-inf)) n)
+	(t (calc-record-why 'natnump n)
+	   (list 'calcFunc-dfact n)))
+)
+
+(defun math-double-factorial-iter (max n f step)
+  (if (< (% n 12) step)
+      (math-working (format "dfact(%d)" (- n step)) f))
+  (if (<= n max)
+      (math-double-factorial-iter max (+ n step) (math-mul n f) step)
+    f)
+)
+
+(defun calcFunc-perm (n m)   ; [I I I] [F F F] [Public]
+  (cond ((and (integerp n) (integerp m) (<= m n) (>= m 0))
+	 (math-factorial-iter m (1+ (- n m)) 1))
+	((or (not (math-num-integerp n))
+	     (and (math-messy-integerp n) (Math-lessp 100 n))
+	     (not (math-num-integerp m))
+	     (and (math-messy-integerp m) (Math-lessp 100 m)))
+	 (or (math-realp n) (equal n '(var inf var-inf))
+	     (math-reject-arg n 'realp))
+	 (or (math-realp m) (equal m '(var inf var-inf))
+	     (math-reject-arg m 'realp))
+	 (and (math-num-integerp n) (math-negp n) (math-reject-arg n 'range))
+	 (and (math-num-integerp m) (math-negp m) (math-reject-arg m 'range))
+	 (math-div (calcFunc-fact n) (calcFunc-fact (math-sub n m))))
+	(t
+	 (let ((tn (math-trunc n))
+	       (tm (math-trunc m)))
+	   (math-inexact-result)
+	   (or (integerp tn) (math-reject-arg tn 'fixnump))
+	   (or (integerp tm) (math-reject-arg tm 'fixnump))
+	   (or (and (<= tm tn) (>= tm 0)) (math-reject-arg tm 'range))
+	   (math-with-extra-prec 1
+	     (math-factorial-iter tm (1+ (- tn tm)) '(float 1 0))))))
+)
+
+(defun calcFunc-choose (n m)   ; [I I I] [F F F] [Public]
+  (cond ((and (integerp n) (integerp m) (<= m n) (>= m 0))
+	 (if (> m (/ n 2))
+	     (math-choose-iter (- n m) n 1 1)
+	   (math-choose-iter m n 1 1)))
+	((not (math-realp n))
+	 (math-reject-arg n 'realp))
+	((not (math-realp m))
+	 (math-reject-arg m 'realp))
+	((not (math-num-integerp m))
+	 (if (and (math-num-integerp n) (math-negp n))
+	     (list 'calcFunc-choose n m)
+	   (math-div (calcFunc-fact (math-float n))
+		     (math-mul (calcFunc-fact m)
+			       (calcFunc-fact (math-sub n m))))))
+	((math-negp m) 0)
+	((math-negp n)
+	 (let ((val (calcFunc-choose (math-add (math-add n m) -1) m)))
+	   (if (math-evenp (math-trunc m))
+	       val
+	     (math-neg val))))
+	((and (math-num-integerp n)
+	      (Math-lessp n m))
+	 0)
+	(t
+	 (math-inexact-result)
+	 (let ((tm (math-trunc m)))
+	   (or (integerp tm) (math-reject-arg tm 'fixnump))
+	   (if (> tm 100)
+	       (math-div (calcFunc-fact (math-float n))
+			 (math-mul (calcFunc-fact (math-float m))
+				   (calcFunc-fact (math-float
+						   (math-sub n m)))))
+	     (math-with-extra-prec 1
+	       (math-choose-float-iter tm n 1 1))))))
+)
+
+(defun math-choose-iter (m n i c)
+  (if (and (= (% i 5) 1) (> i 5))
+      (math-working (format "choose(%d)" (1- i)) c))
+  (if (<= i m)
+      (math-choose-iter m (1- n) (1+ i)
+			(math-quotient (math-mul c n) i))
+    c)
+)
+
+(defun math-choose-float-iter (count n i c)
+  (if (= (% i 5) 1)
+      (math-working (format "choose(%d)" (1- i)) c))
+  (if (> count 0)
+      (math-choose-float-iter (1- count) (math-sub n 1) (1+ i)
+			      (math-div (math-mul c n) i))
+    c)
+)
+
+
+;;; Stirling numbers.
+
+(defun calcFunc-stir1 (n m)
+  (math-stirling-number n m 1)
+)
+
+(defun calcFunc-stir2 (n m)
+  (math-stirling-number n m 0)
+)
+
+(defun math-stirling-number (n m k)
+  (or (math-num-natnump n) (math-reject-arg n 'natnump))
+  (or (math-num-natnump m) (math-reject-arg m 'natnump))
+  (if (consp n) (setq n (math-trunc n)))
+  (or (integerp n) (math-reject-arg n 'fixnump))
+  (if (consp m) (setq m (math-trunc m)))
+  (or (integerp m) (math-reject-arg m 'fixnump))
+  (if (< n m)
+      0
+    (let ((cache (aref math-stirling-cache k)))
+      (while (<= (length cache) n)
+	(let ((i (1- (length cache)))
+	      row)
+	  (setq cache (vconcat cache (make-vector (length cache) nil)))
+	  (aset math-stirling-cache k cache)
+	  (while (< (setq i (1+ i)) (length cache))
+	    (aset cache i (setq row (make-vector (1+ i) nil)))
+	    (aset row 0 0)
+	    (aset row i 1))))
+      (if (= k 1)
+	  (math-stirling-1 n m)
+	(math-stirling-2 n m))))
+)
+(setq math-stirling-cache (vector [[1]] [[1]]))
+
+(defun math-stirling-1 (n m)
+  (or (aref (aref cache n) m)
+      (aset (aref cache n) m
+	    (math-add (math-stirling-1 (1- n) (1- m))
+		      (math-mul (- 1 n) (math-stirling-1 (1- n) m)))))
+)
+
+(defun math-stirling-2 (n m)
+  (or (aref (aref cache n) m)
+      (aset (aref cache n) m
+	    (math-add (math-stirling-2 (1- n) (1- m))
+		      (math-mul m (math-stirling-2 (1- n) m)))))
+)
+
+
+;;; Produce a random 10-bit integer, with (random) if no seed provided,
+;;; or else with Numerical Recipes algorithm ran3 / Knuth 3.2.2-A.
+(defun math-init-random-base ()
+  (if (and (boundp 'var-RandSeed) var-RandSeed)
+      (if (eq (car-safe var-RandSeed) 'vec)
+	  nil
+	(if (Math-integerp var-RandSeed)
+	    (let* ((seed (math-sub 161803 var-RandSeed))
+		   (mj (1+ (math-mod seed '(bigpos 0 0 1))))
+		   (mk (1+ (math-mod (math-quotient seed '(bigpos 0 0 1))
+				     '(bigpos 0 0 1))))
+		   (i 0))
+	      (setq math-random-table (cons 'vec (make-list 55 mj)))
+	      (while (<= (setq i (1+ i)) 54)
+		(let* ((ii (% (* i 21) 55))
+		       (p (nthcdr ii math-random-table)))
+		  (setcar p mk)
+		  (setq mk (- mj mk)
+			mj (car p)))))
+	  (math-reject-arg var-RandSeed "*RandSeed must be an integer"))
+	(setq var-RandSeed (list 'vec var-RandSeed)
+	      math-random-ptr1 math-random-table
+	      math-random-cache nil
+	      math-random-ptr2 (nthcdr 31 math-random-table))
+	(let ((i 200))
+	  (while (> (setq i (1- i)) 0)
+	    (math-random-base))))
+    (random t)
+    (setq var-RandSeed nil
+	  math-random-cache nil
+	  i 0
+	  math-random-shift -4)  ; assume RAND_MAX >= 16383
+    ;; This exercises the random number generator and also helps
+    ;; deduce a better value for RAND_MAX.
+    (while (< (setq i (1+ i)) 30)
+      (if (> (lsh (math-abs (random)) math-random-shift) 4095)
+	  (setq math-random-shift (1- math-random-shift)))))
+  (setq math-last-RandSeed var-RandSeed
+	math-gaussian-cache nil)
+)
+
+(defun math-random-base ()
+  (if var-RandSeed
+      (progn
+	(setq math-random-ptr1 (or (cdr math-random-ptr1)
+				   (cdr math-random-table))
+	      math-random-ptr2 (or (cdr math-random-ptr2)
+				   (cdr math-random-table)))
+	(logand (lsh (setcar math-random-ptr1
+			     (logand (- (car math-random-ptr1)
+					(car math-random-ptr2)) 524287))
+		     -6) 1023))
+    (logand (lsh (random) math-random-shift) 1023))
+)
+(setq math-random-table nil)
+(setq math-last-RandSeed nil)
+(setq math-random-ptr1 nil)
+(setq math-random-ptr2 nil)
+(setq math-random-shift nil)
+
+
+;;; Produce a random digit in the range 0..999.
+;;; Avoid various pitfalls that may lurk in the built-in (random) function!
+;;; Shuffling algorithm from Numerical Recipes, section 7.1.
+(defun math-random-digit ()
+  (let (i)
+    (or (and (boundp 'var-RandSeed) (eq var-RandSeed math-last-RandSeed))
+	(math-init-random-base))
+    (or math-random-cache
+	(progn
+	  (setq math-random-last (math-random-base)
+		math-random-cache (make-vector 13 nil)
+		i -1)
+	  (while (< (setq i (1+ i)) 13)
+	    (aset math-random-cache i (math-random-base)))))
+    (while (progn
+	     (setq i (/ math-random-last 79)   ; 0 <= i < 13
+		   math-random-last (aref math-random-cache i))
+	     (aset math-random-cache i (math-random-base))
+	     (>= math-random-last 1000)))
+    math-random-last)
+)
+(setq math-random-cache nil)
+
+;;; Produce an N-digit random integer.
+(defun math-random-digits (n)
+  (cond ((<= n 6)
+	 (math-scale-right (+ (* (math-random-digit) 1000) (math-random-digit))
+			   (- 6 n)))
+	(t (let* ((slop (% (- 900003 n) 3))
+		  (i (/ (+ n slop) 3))
+		  (digs nil))
+	     (while (> i 0)
+	       (setq digs (cons (math-random-digit) digs)
+		     i (1- i)))
+	     (math-normalize (math-scale-right (cons 'bigpos digs)
+					       slop)))))
+)
+
+;;; Produce a uniformly-distributed random float 0 <= N < 1.
+(defun math-random-float ()
+  (math-make-float (math-random-digits calc-internal-prec)
+		   (- calc-internal-prec))
+)
+
+;;; Produce a Gaussian-distributed random float with mean=0, sigma=1.
+(defun math-gaussian-float ()
+  (math-with-extra-prec 2
+    (if (and math-gaussian-cache
+	     (= (car math-gaussian-cache) calc-internal-prec))
+	(prog1
+	    (cdr math-gaussian-cache)
+	  (setq math-gaussian-cache nil))
+      (let* ((v1 (math-add (math-mul (math-random-float) 2) -1))
+	     (v2 (math-add (math-mul (math-random-float) 2) -1))
+	     (r (math-add (math-sqr v1) (math-sqr v2))))
+	(while (or (not (Math-lessp r 1)) (math-zerop r))
+	  (setq v1 (math-add (math-mul (math-random-float) 2) -1)
+		v2 (math-add (math-mul (math-random-float) 2) -1)
+		r (math-add (math-sqr v1) (math-sqr v2))))
+	(let ((fac (math-sqrt (math-mul (math-div (calcFunc-ln r) r) -2))))
+	  (setq math-gaussian-cache (cons calc-internal-prec
+					  (math-mul v1 fac)))
+	  (math-mul v2 fac)))))
+)
+(setq math-gaussian-cache nil)
+
+;;; Produce a random integer or real 0 <= N < MAX.
+(defun calcFunc-random (max)
+  (cond ((Math-zerop max)
+	 (math-gaussian-float))
+	((Math-integerp max)
+	 (let* ((digs (math-numdigs max))
+		(r (math-random-digits (+ digs 3))))
+	   (math-mod r max)))
+	((Math-realp max)
+	 (math-mul (math-random-float) max))
+	((and (eq (car max) 'intv) (math-constp max)
+	      (Math-lessp (nth 2 max) (nth 3 max)))
+	 (if (math-floatp max)
+	     (let ((val (math-add (math-mul (math-random-float)
+					    (math-sub (nth 3 max) (nth 2 max)))
+				  (nth 2 max))))
+	       (if (or (and (memq (nth 1 max) '(0 1))      ; almost not worth
+			    (Math-equal val (nth 2 max)))  ;   checking!
+		       (and (memq (nth 1 max) '(0 2))
+			    (Math-equal val (nth 3 max))))
+		   (calcFunc-random max)
+		 val))
+	   (let ((lo (if (memq (nth 1 max) '(0 1))
+			 (math-add (nth 2 max) 1) (nth 2 max)))
+		 (hi (if (memq (nth 1 max) '(1 3))
+			 (math-add (nth 3 max) 1) (nth 3 max))))
+	     (if (Math-lessp lo hi)
+		 (math-add (calcFunc-random (math-sub hi lo)) lo)
+	       (math-reject-arg max "*Empty interval")))))
+	((eq (car max) 'vec)
+	 (if (cdr max)
+	     (nth (1+ (calcFunc-random (1- (length max)))) max)
+	   (math-reject-arg max "*Empty list")))
+	((and (eq (car max) 'sdev) (math-constp max) (Math-realp (nth 1 max)))
+	 (math-add (math-mul (math-gaussian-float) (nth 2 max)) (nth 1 max)))
+	(t (math-reject-arg max 'realp)))
+)
+
+;;; Choose N objects at random from the set MAX without duplicates.
+(defun calcFunc-shuffle (n &optional max)
+  (or max (setq max n n -1))
+  (or (and (Math-num-integerp n)
+	   (or (natnump (setq n (math-trunc n))) (eq n -1)))
+      (math-reject-arg n 'integerp))
+  (cond ((or (math-zerop max)
+	     (math-floatp max)
+	     (eq (car-safe max) 'sdev))
+	 (if (< n 0)
+	     (math-reject-arg n 'natnump)
+	   (math-simple-shuffle n max)))
+	((and (<= n 1) (>= n 0))
+	 (math-simple-shuffle n max))
+	((and (eq (car-safe max) 'intv) (math-constp max))
+	 (let ((num (math-add (math-sub (nth 3 max) (nth 2 max))
+			      (cdr (assq (nth 1 max)
+					 '((0 . -1) (1 . 0)
+					   (2 . 0) (3 . 1))))))
+	       (min (math-add (nth 2 max) (if (memq (nth 1 max) '(0 1))
+					      1 0))))
+	   (if (< n 0) (setq n num))
+	   (or (math-posp num) (math-reject-arg max 'range))
+	   (and (Math-lessp num n) (math-reject-arg n 'range))
+	   (if (Math-lessp n (math-quotient num 3))
+	       (math-simple-shuffle n max)
+	     (if (> (* n 4) (* num 3))
+		 (math-add (math-sub min 1)
+			   (math-shuffle-list n num (calcFunc-index num)))
+	       (let ((tot 0)
+		     (m 0)
+		     (vec nil))
+		 (while (< m n)
+		   (if (< (calcFunc-random (- num tot)) (- n m))
+		       (setq vec (cons (math-add min tot) vec)
+			     m (1+ m)))
+		   (setq tot (1+ tot)))
+		 (math-shuffle-list n n (cons 'vec vec)))))))
+	((eq (car-safe max) 'vec)
+	 (let ((size (1- (length max))))
+	   (if (< n 0) (setq n size))
+	   (if (and (> n (/ size 2)) (<= n size))
+	       (math-shuffle-list n size (copy-sequence max))
+	     (let* ((vals (calcFunc-shuffle
+			   n (list 'intv 3 1 (1- (length max)))))
+		    (p vals))
+	       (while (setq p (cdr p))
+		 (setcar p (nth (car p) max)))
+	       vals))))
+	((math-integerp max)
+	 (if (math-posp max)
+	     (calcFunc-shuffle n (list 'intv 2 0 max))
+	   (calcFunc-shuffle n (list 'intv 1 max 0))))
+	(t (math-reject-arg max 'realp)))
+)
+
+(defun math-simple-shuffle (n max)
+  (let ((vec nil)
+	val)
+    (while (>= (setq n (1- n)) 0)
+      (while (math-member (setq val (calcFunc-random max)) vec))
+      (setq vec (cons val vec)))
+    (cons 'vec vec))
+)
+
+(defun math-shuffle-list (n size vec)
+  (let ((j size)
+	k temp
+	(p vec))
+    (while (cdr (setq p (cdr p)))
+      (setq k (calcFunc-random j)
+	    j (1- j)
+	    temp (nth k p))
+      (setcar (nthcdr k p) (car p))
+      (setcar p temp))
+    (cons 'vec (nthcdr (- size n -1) vec)))
+)
+
+(defun math-member (x list)
+  (while (and list (not (equal x (car list))))
+    (setq list (cdr list)))
+  list
+)
+
+
+;;; Check if the integer N is prime.  [X I]
+;;; Return (nil) if non-prime,
+;;;        (nil N) if non-prime with known factor N,
+;;;        (nil unknown) if non-prime with no known factors,
+;;;        (t) if prime,
+;;;        (maybe N P) if probably prime (after N iters with probability P%)
+(defun math-prime-test (n iters)
+  (if (and (Math-vectorp n) (cdr n))
+      (setq n (nth (1- (length n)) n)))
+  (if (Math-messy-integerp n)
+      (setq n (math-trunc n)))
+  (let ((res))
+    (while (> iters 0)
+      (setq res
+	    (cond ((and (integerp n) (<= n 5003))
+		   (list (= (math-next-small-prime n) n)))
+		  ((not (Math-integerp n))
+		   (error "Argument must be an integer"))
+		  ((Math-integer-negp n)
+		   '(nil))
+		  ((Math-natnum-lessp n '(bigpos 0 0 8))
+		   (setq n (math-fixnum n))
+		   (let ((i -1) v)
+		     (while (and (> (% n (setq v (aref math-primes-table
+						       (setq i (1+ i)))))
+				    0)
+				 (< (* v v) n)))
+		     (if (= (% n v) 0)
+			 (list nil v)
+		       '(t))))
+		  ((not (equal n (car math-prime-test-cache)))
+		   (cond ((= (% (nth 1 n) 2) 0) '(nil 2))
+			 ((= (% (nth 1 n) 5) 0) '(nil 5))
+			 (t (let ((dig (cdr n)) (sum 0))
+			      (while dig
+				(if (cdr dig)
+				    (setq sum (% (+ (+ sum (car dig))
+						    (* (nth 1 dig) 1000))
+						 111111)
+					  dig (cdr (cdr dig)))
+				  (setq sum (% (+ sum (car dig)) 111111)
+					dig nil)))
+			      (cond ((= (% sum 3) 0) '(nil 3))
+				    ((= (% sum 7) 0) '(nil 7))
+				    ((= (% sum 11) 0) '(nil 11))
+				    ((= (% sum 13) 0) '(nil 13))
+				    ((= (% sum 37) 0) '(nil 37))
+				    (t
+				     (setq math-prime-test-cache-k 1
+					   math-prime-test-cache-q
+					   (math-div2 n)
+					   math-prime-test-cache-nm1
+					   (math-add n -1))
+				     (while (math-evenp
+					     math-prime-test-cache-q)
+				       (setq math-prime-test-cache-k
+					     (1+ math-prime-test-cache-k)
+					     math-prime-test-cache-q
+					     (math-div2
+					      math-prime-test-cache-q)))
+				     (setq iters (1+ iters))
+				     (list 'maybe
+					   0
+					   (math-sub
+					    100
+					    (math-div
+					     '(float 232 0)
+					     (math-numdigs n))))))))))
+		  ((not (eq (car (nth 1 math-prime-test-cache)) 'maybe))
+		   (nth 1 math-prime-test-cache))
+		  (t   ; Fermat step
+		   (let* ((x (math-add (calcFunc-random (math-add n -2)) 2))
+			  (y (math-pow-mod x math-prime-test-cache-q n))
+			  (j 0))
+		     (while (and (not (eq y 1))
+				 (not (equal y math-prime-test-cache-nm1))
+				 (< (setq j (1+ j)) math-prime-test-cache-k))
+		       (setq y (math-mod (math-mul y y) n)))
+		     (if (or (equal y math-prime-test-cache-nm1)
+			     (and (eq y 1) (eq j 0)))
+			 (list 'maybe
+			       (1+ (nth 1 (nth 1 math-prime-test-cache)))
+			       (math-mul (nth 2 (nth 1 math-prime-test-cache))
+					 '(float 25 -2)))
+		       '(nil unknown))))))
+      (setq math-prime-test-cache (list n res)
+	    iters (if (eq (car res) 'maybe)
+		      (1- iters)
+		    0)))
+    res)
+)
+(defvar math-prime-test-cache '(-1))
+
+(defun calcFunc-prime (n &optional iters)
+  (or (math-num-integerp n) (math-reject-arg n 'integerp))
+  (or (not iters) (math-num-integerp iters) (math-reject-arg iters 'integerp))
+  (if (car (math-prime-test (math-trunc n) (math-trunc (or iters 1))))
+      1
+    0)
+)
+
+;;; Theory: summing base-10^6 digits modulo 111111 is "casting out 999999s".
+;;; Initial probability that N is prime is 1/ln(N) = log10(e)/log10(N).
+;;; After culling [2,3,5,7,11,13,37], probability of primality is 5.36 x more.
+;;; Initial reported probability of non-primality is thus 100% - this.
+;;; Each Fermat step multiplies this probability by 25%.
+;;; The Fermat step is algorithm P from Knuth section 4.5.4.
+
+
+(defun calcFunc-prfac (n)
+  (setq math-prime-factors-finished t)
+  (if (Math-messy-integerp n)
+      (setq n (math-trunc n)))
+  (if (Math-natnump n)
+      (if (Math-natnum-lessp 2 n)
+	  (let (factors res p (i 0))
+	    (while (and (not (eq n 1))
+			(< i (length math-primes-table)))
+	      (setq p (aref math-primes-table i))
+	      (while (eq (cdr (setq res (cond ((eq n p) (cons 1 0))
+					      ((eq n 1) (cons 0 1))
+					      ((consp n) (math-idivmod n p))
+					      (t (cons (/ n p) (% n p))))))
+			 0)
+		(math-working "factor" p)
+		(setq factors (nconc factors (list p))
+		      n (car res)))
+	      (or (eq n 1)
+		  (Math-natnum-lessp p (car res))
+		  (setq factors (nconc factors (list n))
+			n 1))
+	      (setq i (1+ i)))
+	    (or (setq math-prime-factors-finished (eq n 1))
+		(setq factors (nconc factors (list n))))
+	    (cons 'vec factors))
+	(list 'vec n))
+    (if (Math-integerp n)
+	(if (eq n -1)
+	    (list 'vec n)
+	  (cons 'vec (cons -1 (cdr (calcFunc-prfac (math-neg n))))))
+      (calc-record-why 'integerp n)
+      (list 'calcFunc-prfac n)))
+)
+
+(defun calcFunc-totient (n)
+  (if (Math-messy-integerp n)
+      (setq n (math-trunc n)))
+  (if (Math-natnump n)
+      (if (Math-natnum-lessp n 2)
+	  (if (Math-negp n)
+	      (calcFunc-totient (math-abs n))
+	    n)
+	(let ((factors (cdr (calcFunc-prfac n)))
+	      p)
+	  (if math-prime-factors-finished
+	      (progn
+		(while factors
+		  (setq p (car factors)
+			n (math-mul (math-div n p) (math-add p -1)))
+		  (while (equal p (car factors))
+		    (setq factors (cdr factors))))
+		n)
+	    (calc-record-why "*Number too big to factor" n)
+	    (list 'calcFunc-totient n))))
+    (calc-record-why 'natnump n)
+    (list 'calcFunc-totient n))
+)
+
+(defun calcFunc-moebius (n)
+  (if (Math-messy-integerp n)
+      (setq n (math-trunc n)))
+  (if (and (Math-natnump n) (not (eq n 0)))
+      (if (Math-natnum-lessp n 2)
+	  (if (Math-negp n)
+	      (calcFunc-moebius (math-abs n))
+	    1)
+	(let ((factors (cdr (calcFunc-prfac n)))
+	      (mu 1))
+	  (if math-prime-factors-finished
+	      (progn
+		(while factors
+		  (setq mu (if (equal (car factors) (nth 1 factors))
+			       0 (math-neg mu))
+			factors (cdr factors)))
+		mu)
+	    (calc-record-why "Number too big to factor" n)
+	    (list 'calcFunc-moebius n))))
+    (calc-record-why 'posintp n)
+    (list 'calcFunc-moebius n))
+)
+
+
+(defun calcFunc-nextprime (n &optional iters)
+  (if (Math-integerp n)
+      (if (Math-integer-negp n)
+	  2
+	(if (and (integerp n) (< n 5003))
+	    (math-next-small-prime (1+ n))
+	  (if (math-evenp n)
+	      (setq n (math-add n -1)))
+	  (let (res)
+	    (while (not (car (setq res (math-prime-test
+					(setq n (math-add n 2))
+					(or iters 1))))))
+	    (if (and calc-verbose-nextprime
+		     (eq (car res) 'maybe))
+		(calc-report-prime-test res)))
+	  n))
+    (if (Math-realp n)
+	(calcFunc-nextprime (math-trunc n) iters)
+      (math-reject-arg n 'integerp)))
+)
+(setq calc-verbose-nextprime nil)
+
+(defun calcFunc-prevprime (n &optional iters)
+  (if (Math-integerp n)
+      (if (Math-lessp n 4)
+	  2
+	(if (math-evenp n)
+	    (setq n (math-add n 1)))
+	(let (res)
+	  (while (not (car (setq res (math-prime-test
+				      (setq n (math-add n -2))
+				      (or iters 1))))))
+	  (if (and calc-verbose-nextprime
+		   (eq (car res) 'maybe))
+	      (calc-report-prime-test res)))
+	n)
+    (if (Math-realp n)
+	(calcFunc-prevprime (math-ceiling n) iters)
+      (math-reject-arg n 'integerp)))
+)
+
+(defun math-next-small-prime (n)
+  (if (and (integerp n) (> n 2))
+      (let ((lo -1)
+	    (hi (length math-primes-table))
+	    mid)
+	(while (> (- hi lo) 1)
+	  (if (> n (aref math-primes-table
+			 (setq mid (ash (+ lo hi) -1))))
+	      (setq lo mid)
+	    (setq hi mid)))
+	(aref math-primes-table hi))
+    2)
+)
+
+(defconst math-primes-table
+  [2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89
+     97 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181
+     191 193 197 199 211 223 227 229 233 239 241 251 257 263 269 271 277
+     281 283 293 307 311 313 317 331 337 347 349 353 359 367 373 379 383
+     389 397 401 409 419 421 431 433 439 443 449 457 461 463 467 479 487
+     491 499 503 509 521 523 541 547 557 563 569 571 577 587 593 599 601
+     607 613 617 619 631 641 643 647 653 659 661 673 677 683 691 701 709
+     719 727 733 739 743 751 757 761 769 773 787 797 809 811 821 823 827
+     829 839 853 857 859 863 877 881 883 887 907 911 919 929 937 941 947
+     953 967 971 977 983 991 997 1009 1013 1019 1021 1031 1033 1039 1049
+     1051 1061 1063 1069 1087 1091 1093 1097 1103 1109 1117 1123 1129 1151
+     1153 1163 1171 1181 1187 1193 1201 1213 1217 1223 1229 1231 1237 1249
+     1259 1277 1279 1283 1289 1291 1297 1301 1303 1307 1319 1321 1327 1361
+     1367 1373 1381 1399 1409 1423 1427 1429 1433 1439 1447 1451 1453 1459
+     1471 1481 1483 1487 1489 1493 1499 1511 1523 1531 1543 1549 1553 1559
+     1567 1571 1579 1583 1597 1601 1607 1609 1613 1619 1621 1627 1637 1657
+     1663 1667 1669 1693 1697 1699 1709 1721 1723 1733 1741 1747 1753 1759
+     1777 1783 1787 1789 1801 1811 1823 1831 1847 1861 1867 1871 1873 1877
+     1879 1889 1901 1907 1913 1931 1933 1949 1951 1973 1979 1987 1993 1997
+     1999 2003 2011 2017 2027 2029 2039 2053 2063 2069 2081 2083 2087 2089
+     2099 2111 2113 2129 2131 2137 2141 2143 2153 2161 2179 2203 2207 2213
+     2221 2237 2239 2243 2251 2267 2269 2273 2281 2287 2293 2297 2309 2311
+     2333 2339 2341 2347 2351 2357 2371 2377 2381 2383 2389 2393 2399 2411
+     2417 2423 2437 2441 2447 2459 2467 2473 2477 2503 2521 2531 2539 2543
+     2549 2551 2557 2579 2591 2593 2609 2617 2621 2633 2647 2657 2659 2663
+     2671 2677 2683 2687 2689 2693 2699 2707 2711 2713 2719 2729 2731 2741
+     2749 2753 2767 2777 2789 2791 2797 2801 2803 2819 2833 2837 2843 2851
+     2857 2861 2879 2887 2897 2903 2909 2917 2927 2939 2953 2957 2963 2969
+     2971 2999 3001 3011 3019 3023 3037 3041 3049 3061 3067 3079 3083 3089
+     3109 3119 3121 3137 3163 3167 3169 3181 3187 3191 3203 3209 3217 3221
+     3229 3251 3253 3257 3259 3271 3299 3301 3307 3313 3319 3323 3329 3331
+     3343 3347 3359 3361 3371 3373 3389 3391 3407 3413 3433 3449 3457 3461
+     3463 3467 3469 3491 3499 3511 3517 3527 3529 3533 3539 3541 3547 3557
+     3559 3571 3581 3583 3593 3607 3613 3617 3623 3631 3637 3643 3659 3671
+     3673 3677 3691 3697 3701 3709 3719 3727 3733 3739 3761 3767 3769 3779
+     3793 3797 3803 3821 3823 3833 3847 3851 3853 3863 3877 3881 3889 3907
+     3911 3917 3919 3923 3929 3931 3943 3947 3967 3989 4001 4003 4007 4013
+     4019 4021 4027 4049 4051 4057 4073 4079 4091 4093 4099 4111 4127 4129
+     4133 4139 4153 4157 4159 4177 4201 4211 4217 4219 4229 4231 4241 4243
+     4253 4259 4261 4271 4273 4283 4289 4297 4327 4337 4339 4349 4357 4363
+     4373 4391 4397 4409 4421 4423 4441 4447 4451 4457 4463 4481 4483 4493
+     4507 4513 4517 4519 4523 4547 4549 4561 4567 4583 4591 4597 4603 4621
+     4637 4639 4643 4649 4651 4657 4663 4673 4679 4691 4703 4721 4723 4729
+     4733 4751 4759 4783 4787 4789 4793 4799 4801 4813 4817 4831 4861 4871
+     4877 4889 4903 4909 4919 4931 4933 4937 4943 4951 4957 4967 4969 4973
+     4987 4993 4999 5003])
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/calc-cplx.el	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,377 @@
+;; Calculator for GNU Emacs, part II [calc-cplx.el]
+;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+;; Written by Dave Gillespie, daveg@synaptics.com.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY.  No author or distributor
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing.  Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License.   A copy of this license is
+;; supposed to have been given to you along with GNU Emacs so you
+;; can know your rights and responsibilities.  It should be in a
+;; file named COPYING.  Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+
+
+
+;; This file is autoloaded from calc-ext.el.
+(require 'calc-ext)
+
+(require 'calc-macs)
+
+(defun calc-Need-calc-cplx () nil)
+
+
+(defun calc-argument (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-unary-op "arg" 'calcFunc-arg arg))
+)
+
+(defun calc-re (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-unary-op "re" 'calcFunc-re arg))
+)
+
+(defun calc-im (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-unary-op "im" 'calcFunc-im arg))
+)
+
+
+(defun calc-polar ()
+  (interactive)
+  (calc-slow-wrapper
+   (let ((arg (calc-top-n 1)))
+     (if (or (calc-is-inverse)
+	     (eq (car-safe arg) 'polar))
+	 (calc-enter-result 1 "p-r" (list 'calcFunc-rect arg))
+       (calc-enter-result 1 "r-p" (list 'calcFunc-polar arg)))))
+)
+
+
+
+
+(defun calc-complex-notation ()
+  (interactive)
+  (calc-wrapper
+   (calc-change-mode 'calc-complex-format nil t)
+   (message "Displaying complex numbers in (X,Y) format."))
+)
+
+(defun calc-i-notation ()
+  (interactive)
+  (calc-wrapper
+   (calc-change-mode 'calc-complex-format 'i t)
+   (message "Displaying complex numbers in X+Yi format."))
+)
+
+(defun calc-j-notation ()
+  (interactive)
+  (calc-wrapper
+   (calc-change-mode 'calc-complex-format 'j t)
+   (message "Displaying complex numbers in X+Yj format."))
+)
+
+
+(defun calc-polar-mode (n)
+  (interactive "P")
+  (calc-wrapper
+   (if (if n
+	   (> (prefix-numeric-value n) 0)
+	 (eq calc-complex-mode 'cplx))
+       (progn
+	 (calc-change-mode 'calc-complex-mode 'polar)
+	 (message "Preferred complex form is polar."))
+     (calc-change-mode 'calc-complex-mode 'cplx)
+     (message "Preferred complex form is rectangular.")))
+)
+
+
+;;;; Complex numbers.
+
+(defun math-normalize-polar (a)
+  (let ((r (math-normalize (nth 1 a)))
+	(th (math-normalize (nth 2 a))))
+    (cond ((math-zerop r)
+	   '(polar 0 0))
+	  ((or (math-zerop th))
+	   r)
+	  ((and (not (eq calc-angle-mode 'rad))
+		(or (equal th '(float 18 1))
+		    (equal th 180)))
+	   (math-neg r))
+	  ((math-negp r)
+	   (math-neg (list 'polar (math-neg r) th)))
+	  (t
+	   (list 'polar r th))))
+)
+
+
+;;; Coerce A to be complex (rectangular form).  [c N]
+(defun math-complex (a)
+  (cond ((eq (car-safe a) 'cplx) a)
+	((eq (car-safe a) 'polar)
+	 (if (math-zerop (nth 1 a))
+	     (nth 1 a)
+	   (let ((sc (calcFunc-sincos (nth 2 a))))
+	     (list 'cplx
+		   (math-mul (nth 1 a) (nth 1 sc))
+		   (math-mul (nth 1 a) (nth 2 sc))))))
+	(t (list 'cplx a 0)))
+)
+
+;;; Coerce A to be complex (polar form).  [c N]
+(defun math-polar (a)
+  (cond ((eq (car-safe a) 'polar) a)
+	((math-zerop a) '(polar 0 0))
+	(t
+	 (list 'polar
+	       (math-abs a)
+	       (calcFunc-arg a))))
+)
+
+;;; Multiply A by the imaginary constant i.  [N N] [Public]
+(defun math-imaginary (a)
+  (if (and (or (Math-objvecp a) (math-infinitep a))
+	   (not calc-symbolic-mode))
+      (math-mul a
+		(if (or (eq (car-safe a) 'polar)
+			(and (not (eq (car-safe a) 'cplx))
+			     (eq calc-complex-mode 'polar)))
+		    (list 'polar 1 (math-quarter-circle nil))
+		  '(cplx 0 1)))
+    (math-mul a '(var i var-i)))
+)
+
+
+
+
+(defun math-want-polar (a b)
+  (cond ((eq (car-safe a) 'polar)
+	 (if (eq (car-safe b) 'cplx)
+	     (eq calc-complex-mode 'polar)
+	   t))
+	((eq (car-safe a) 'cplx)
+	 (if (eq (car-safe b) 'polar)
+	     (eq calc-complex-mode 'polar)
+	   nil))
+	((eq (car-safe b) 'polar)
+	 t)
+	((eq (car-safe b) 'cplx)
+	 nil)
+	(t (eq calc-complex-mode 'polar)))
+)
+
+;;; Force A to be in the (-pi,pi] or (-180,180] range.
+(defun math-fix-circular (a &optional dir)   ; [R R]
+  (cond ((eq (car-safe a) 'hms)
+	 (cond ((and (Math-lessp 180 (nth 1 a)) (not (eq dir 1)))
+		(math-fix-circular (math-add a '(float -36 1)) -1))
+	       ((or (Math-lessp -180 (nth 1 a)) (eq dir -1))
+		a)
+	       (t
+		(math-fix-circular (math-add a '(float 36 1)) 1))))
+	((eq calc-angle-mode 'rad)
+	 (cond ((and (Math-lessp (math-pi) a) (not (eq dir 1)))
+		(math-fix-circular (math-sub a (math-two-pi)) -1))
+	       ((or (Math-lessp (math-neg (math-pi)) a) (eq dir -1))
+		a)
+	       (t
+		(math-fix-circular (math-add a (math-two-pi)) 1))))
+	(t
+	 (cond ((and (Math-lessp '(float 18 1) a) (not (eq dir 1)))
+		(math-fix-circular (math-add a '(float -36 1)) -1))
+	       ((or (Math-lessp '(float -18 1) a) (eq dir -1))
+		a)
+	       (t
+		(math-fix-circular (math-add a '(float 36 1)) 1)))))
+)
+
+
+;;;; Complex numbers.
+
+(defun calcFunc-polar (a)   ; [C N] [Public]
+  (cond ((Math-vectorp a)
+	 (math-map-vec 'calcFunc-polar a))
+	((Math-realp a) a)
+	((Math-numberp a)
+	 (math-normalize (math-polar a)))
+	(t (list 'calcFunc-polar a)))
+)
+
+(defun calcFunc-rect (a)   ; [N N] [Public]
+  (cond ((Math-vectorp a)
+	 (math-map-vec 'calcFunc-rect a))
+	((Math-realp a) a)
+	((Math-numberp a)
+	 (math-normalize (math-complex a)))
+	(t (list 'calcFunc-rect a)))
+)
+
+;;; Compute the complex conjugate of A.  [O O] [Public]
+(defun calcFunc-conj (a)
+  (let (aa bb)
+    (cond ((Math-realp a)
+	   a)
+	  ((eq (car a) 'cplx)
+	   (list 'cplx (nth 1 a) (math-neg (nth 2 a))))
+	  ((eq (car a) 'polar)
+	   (list 'polar (nth 1 a) (math-neg (nth 2 a))))
+	  ((eq (car a) 'vec)
+	   (math-map-vec 'calcFunc-conj a))
+	  ((eq (car a) 'calcFunc-conj)
+	   (nth 1 a))
+	  ((math-known-realp a)
+	   a)
+	  ((and (equal a '(var i var-i))
+		(math-imaginary-i))
+	   (math-neg a))
+	  ((and (memq (car a) '(+ - * /))
+		(progn
+		  (setq aa (calcFunc-conj (nth 1 a))
+			bb (calcFunc-conj (nth 2 a)))
+		  (or (not (eq (car-safe aa) 'calcFunc-conj))
+		      (not (eq (car-safe bb) 'calcFunc-conj)))))
+	   (if (eq (car a) '+)
+	       (math-add aa bb)
+	     (if (eq (car a) '-)
+		 (math-sub aa bb)
+	       (if (eq (car a) '*)
+		   (math-mul aa bb)
+		 (math-div aa bb)))))
+	  ((eq (car a) 'neg)
+	   (math-neg (calcFunc-conj (nth 1 a))))
+	  ((let ((inf (math-infinitep a)))
+	     (and inf
+		  (math-mul (calcFunc-conj (math-infinite-dir a inf)) inf))))
+	  (t (calc-record-why 'numberp a)
+	     (list 'calcFunc-conj a))))
+)
+
+
+;;; Compute the complex argument of A.  [F N] [Public]
+(defun calcFunc-arg (a)
+  (cond ((Math-anglep a)
+	 (if (math-negp a) (math-half-circle nil) 0))
+	((eq (car-safe a) 'cplx)
+	 (calcFunc-arctan2 (nth 2 a) (nth 1 a)))
+	((eq (car-safe a) 'polar)
+	 (nth 2 a))
+	((eq (car a) 'vec)
+	 (math-map-vec 'calcFunc-arg a))
+	((and (equal a '(var i var-i))
+	      (math-imaginary-i))
+	 (math-quarter-circle t))
+	((and (equal a '(neg (var i var-i)))
+	      (math-imaginary-i))
+	 (math-neg (math-quarter-circle t)))
+	((let ((signs (math-possible-signs a)))
+	   (or (and (memq signs '(2 4 6)) 0)
+	       (and (eq signs 1) (math-half-circle nil)))))
+	((math-infinitep a)
+	 (if (or (equal a '(var uinf var-uinf))
+		 (equal a '(var nan var-nan)))
+	     '(var nan var-nan)
+	   (calcFunc-arg (math-infinite-dir a))))
+	(t (calc-record-why 'numvecp a)
+	   (list 'calcFunc-arg a)))
+)
+
+(defun math-imaginary-i ()
+  (let ((val (calc-var-value 'var-i)))
+    (or (eq (car-safe val) 'special-const)
+	(equal val '(cplx 0 1))
+	(and (eq (car-safe val) 'polar)
+	     (eq (nth 1 val) 0)
+	     (Math-equal (nth 1 val) (math-quarter-circle nil)))))
+)
+
+;;; Extract the real or complex part of a complex number.  [R N] [Public]
+;;; Also extracts the real part of a modulo form.
+(defun calcFunc-re (a)
+  (let (aa bb)
+    (cond ((Math-realp a) a)
+	  ((memq (car a) '(mod cplx))
+	   (nth 1 a))
+	  ((eq (car a) 'polar)
+	   (math-mul (nth 1 a) (calcFunc-cos (nth 2 a))))
+	  ((eq (car a) 'vec)
+	   (math-map-vec 'calcFunc-re a))
+	  ((math-known-realp a) a)
+	  ((eq (car a) 'calcFunc-conj)
+	   (calcFunc-re (nth 1 a)))
+	  ((and (equal a '(var i var-i))
+		(math-imaginary-i))
+	   0)
+	  ((and (memq (car a) '(+ - *))
+		(progn
+		  (setq aa (calcFunc-re (nth 1 a))
+			bb (calcFunc-re (nth 2 a)))
+		  (or (not (eq (car-safe aa) 'calcFunc-re))
+		      (not (eq (car-safe bb) 'calcFunc-re)))))
+	   (if (eq (car a) '+)
+	       (math-add aa bb)
+	     (if (eq (car a) '-)
+		 (math-sub aa bb)
+	       (math-sub (math-mul aa bb)
+			 (math-mul (calcFunc-im (nth 1 a))
+				   (calcFunc-im (nth 2 a)))))))
+	  ((and (eq (car a) '/)
+		(math-known-realp (nth 2 a)))
+	   (math-div (calcFunc-re (nth 1 a)) (nth 2 a)))
+	  ((eq (car a) 'neg)
+	   (math-neg (calcFunc-re (nth 1 a))))
+	  (t (calc-record-why 'numberp a)
+	     (list 'calcFunc-re a))))
+)
+
+(defun calcFunc-im (a)
+  (let (aa bb)
+    (cond ((Math-realp a)
+	   (if (math-floatp a) '(float 0 0) 0))
+	  ((eq (car a) 'cplx)
+	   (nth 2 a))
+	  ((eq (car a) 'polar)
+	   (math-mul (nth 1 a) (calcFunc-sin (nth 2 a))))
+	  ((eq (car a) 'vec)
+	   (math-map-vec 'calcFunc-im a))
+	  ((math-known-realp a)
+	   0)
+	  ((eq (car a) 'calcFunc-conj)
+	   (math-neg (calcFunc-im (nth 1 a))))
+	  ((and (equal a '(var i var-i))
+		(math-imaginary-i))
+	   1)
+	  ((and (memq (car a) '(+ - *))
+		(progn
+		  (setq aa (calcFunc-im (nth 1 a))
+			bb (calcFunc-im (nth 2 a)))
+		  (or (not (eq (car-safe aa) 'calcFunc-im))
+		      (not (eq (car-safe bb) 'calcFunc-im)))))
+	   (if (eq (car a) '+)
+	       (math-add aa bb)
+	     (if (eq (car a) '-)
+		 (math-sub aa bb)
+	       (math-add (math-mul (calcFunc-re (nth 1 a)) bb)
+			 (math-mul aa (calcFunc-re (nth 2 a)))))))
+	  ((and (eq (car a) '/)
+		(math-known-realp (nth 2 a)))
+	   (math-div (calcFunc-im (nth 1 a)) (nth 2 a)))
+	  ((eq (car a) 'neg)
+	   (math-neg (calcFunc-im (nth 1 a))))
+	  (t (calc-record-why 'numberp a)
+	     (list 'calcFunc-im a))))
+)
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/calc-embed.el	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,1256 @@
+;; Calculator for GNU Emacs, part II [calc-embed.el]
+;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+;; Written by Dave Gillespie, daveg@synaptics.com.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY.  No author or distributor
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing.  Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License.   A copy of this license is
+;; supposed to have been given to you along with GNU Emacs so you
+;; can know your rights and responsibilities.  It should be in a
+;; file named COPYING.  Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+
+
+
+;; This file is autoloaded from calc-ext.el.
+(require 'calc-ext)
+
+(require 'calc-macs)
+
+(defun calc-Need-calc-embed () nil)
+
+
+(defun calc-show-plain (n)
+  (interactive "P")
+  (calc-wrapper
+   (calc-set-command-flag 'renum-stack)
+   (message (if (calc-change-mode 'calc-show-plain n nil t)
+		"Including \"plain\" formulas in Calc Embedded mode."
+	      "Omitting \"plain\" formulas in Calc Embedded mode.")))
+)
+
+
+
+
+;;; Things to do for Embedded Mode:
+;;; 
+;;;  Detect and strip off unexpected labels during reading.
+;;;
+;;;  Get calc-grab-region to use math-read-big-expr.
+;;;  If calc-show-plain, main body should have only righthand side of => expr.
+;;;  Handle tabs that have crept into embedded formulas.
+;;;  After "switching to new formula", home cursor to that formula.
+;;;  Do something like \evalto ... \to for \gets operators.
+;;;
+
+
+(defvar calc-embedded-modes nil)
+(defvar calc-embedded-globals nil)
+(defvar calc-embedded-active nil)
+
+(make-variable-buffer-local 'calc-embedded-all-active)
+(make-variable-buffer-local 'calc-embedded-some-active)
+
+
+(defvar calc-embedded-open-formula "\\`\\|^\n\\|\\$\\$?\\|\\\\\\[\\|^\\\\begin.*\n\\|^@.*\n\\|^\\.EQ.*\n\\|\\\\(\\|^%\n\\|^\\.\\\\\"\n"
+  "*A regular expression for the opening delimiter of a formula used by
+calc-embedded.")
+
+(defvar calc-embedded-close-formula "\\'\\|\n$\\|\\$\\$?\\|\\\\]\\|^\\\\end.*\n\\|^@.*\n\\|^\\.EN.*\n\\|\\\\)\\|\n%\n\\|^\\.\\\\\"\n"
+  "*A regular expression for the closing delimiter of a formula used by
+calc-embedded.")
+
+(defvar calc-embedded-open-word "^\\|[^-+0-9.eE]"
+  "*A regular expression for the opening delimiter of a formula used by
+calc-embedded-word.")
+
+(defvar calc-embedded-close-word "$\\|[^-+0-9.eE]"
+  "*A regular expression for the closing delimiter of a formula used by
+calc-embedded-word.")
+
+(defvar calc-embedded-open-plain "%%% "
+  "*A string which is the opening delimiter for a \"plain\" formula.
+If calc-show-plain mode is enabled, this is inserted at the front of
+each formula.")
+
+(defvar calc-embedded-close-plain " %%%\n"
+  "*A string which is the closing delimiter for a \"plain\" formula.
+See calc-embedded-open-plain.")
+
+(defvar calc-embedded-open-new-formula "\n\n"
+  "*A string which is inserted at front of formula by calc-embedded-new-formula.")
+
+(defvar calc-embedded-close-new-formula "\n\n"
+  "*A string which is inserted at end of formula by calc-embedded-new-formula.")
+
+(defvar calc-embedded-announce-formula "%Embed\n\\(% .*\n\\)*"
+  "*A regular expression which is sure to be followed by a calc-embedded formula." )
+
+(defvar calc-embedded-open-mode "% "
+  "*A string which should precede calc-embedded mode annotations.
+This is not required to be present for user-written mode annotations.")
+
+(defvar calc-embedded-close-mode "\n"
+  "*A string which should follow calc-embedded mode annotations.
+This is not required to be present for user-written mode annotations.")
+
+
+(defconst calc-embedded-mode-vars '(("precision" . calc-internal-prec)
+				    ("word-size" . calc-word-size)
+				    ("angles" . calc-angle-mode)
+				    ("symbolic" . calc-symbolic-mode)
+				    ("matrix" . calc-matrix-mode)
+				    ("fractions" . calc-prefer-frac)
+				    ("complex" . calc-complex-mode)
+				    ("simplify" . calc-simplify-mode)
+				    ("language" . the-language)
+				    ("plain" . calc-show-plain)
+				    ("break" . calc-line-breaking)
+				    ("justify" . the-display-just)
+				    ("left-label" . calc-left-label)
+				    ("right-label" . calc-right-label)
+				    ("radix" . calc-number-radix)
+				    ("leading-zeros" . calc-leading-zeros)
+				    ("grouping" . calc-group-digits)
+				    ("group-char" . calc-group-char)
+				    ("point-char" . calc-point-char)
+				    ("frac-format" . calc-frac-format)
+				    ("float-format" . calc-float-format)
+				    ("complex-format" . calc-complex-format)
+				    ("hms-format" . calc-hms-format)
+				    ("date-format" . calc-date-format)
+				    ("matrix-justify" . calc-matrix-just)
+				    ("full-vectors" . calc-full-vectors)
+				    ("break-vectors" . calc-break-vectors)
+				    ("vector-commas" . calc-vector-commas)
+				    ("vector-brackets" . calc-vector-brackets)
+				    ("matrix-brackets" . calc-matrix-brackets)
+				    ("strings" . calc-display-strings)
+))
+
+
+;;; Format of calc-embedded-info vector:
+;;;    0   Editing buffer.
+;;;    1   Calculator buffer.
+;;;    2   Top of current formula (marker).
+;;;    3   Bottom of current formula (marker).
+;;;    4   Top of current formula's delimiters (marker).
+;;;    5   Bottom of current formula's delimiters (marker).
+;;;    6   String representation of current formula.
+;;;    7   Non-nil if formula is embedded within a single line.
+;;;    8   Internal representation of current formula.
+;;;    9   Variable assigned by this formula, or nil.
+;;;   10   List of variables upon which this formula depends.
+;;;   11   Evaluated value of the formula, or nil.
+;;;   12   Mode settings for current formula.
+;;;   13   Local mode settings for current formula.
+;;;   14   Permanent mode settings for current formula.
+;;;   15   Global mode settings for editing buffer.
+
+
+;;; calc-embedded-active is an a-list keyed on buffers; each cdr is a
+;;; sorted list of calc-embedded-infos in that buffer.  We do this
+;;; rather than using buffer-local variables because the latter are
+;;; thrown away when a buffer changes major modes.
+
+
+(defun calc-do-embedded (arg end obeg oend)
+  (if calc-embedded-info
+
+      ;; Turn embedded mode off or switch to a new buffer.
+      (cond ((eq (current-buffer) (aref calc-embedded-info 1))
+	     (let ((calcbuf (current-buffer))
+		   (buf (aref calc-embedded-info 0)))
+	       (calc-embedded-original-buffer t)
+	       (calc-embedded nil)
+	       (switch-to-buffer calcbuf)))
+
+	    ((eq (current-buffer) (aref calc-embedded-info 0))
+	     (let* ((info calc-embedded-info)
+		    (mode calc-embedded-modes))
+	       (save-excursion
+		 (set-buffer (aref info 1))
+		 (if (and (> (calc-stack-size) 0)
+			  (equal (calc-top 1 'full) (aref info 8)))
+		     (let ((calc-no-refresh-evaltos t))
+		       (if (calc-top 1 'sel)
+			   (calc-unselect 1))
+		       (calc-embedded-set-modes
+			(aref info 15) (aref info 12) (aref info 14))
+		       (let ((calc-embedded-info nil))
+			 (calc-wrapper (calc-pop-stack))))
+		   (calc-set-mode-line)))
+	       (setq calc-embedded-info nil
+		     mode-line-buffer-identification (car mode)
+		     truncate-lines (nth 2 mode)
+		     buffer-read-only nil)
+	       (use-local-map (nth 1 mode))
+	       (set-buffer-modified-p (buffer-modified-p))
+	       (or calc-embedded-quiet
+		   (message "Back to %s mode." mode-name))))
+
+	    (t
+	     (if (buffer-name (aref calc-embedded-info 0))
+		 (save-excursion
+		   (set-buffer (aref calc-embedded-info 0))
+		   (or (y-or-n-p "Cancel Calc Embedded mode in buffer %s? "
+				 (buffer-name))
+		       (keyboard-quit))
+		   (calc-embedded nil)))
+	     (calc-embedded arg end obeg oend)))
+
+    ;; Turn embedded mode on.
+    (calc-plain-buffer-only)
+    (let ((modes (list mode-line-buffer-identification
+		       (current-local-map)
+		       truncate-lines))
+	  top bot outer-top outer-bot
+	  info chg ident)
+      (barf-if-buffer-read-only)
+      (or calc-embedded-globals
+	  (calc-find-globals))
+      (setq info (calc-embedded-make-info (point) nil t arg end obeg oend))
+      (if (eq (car-safe (aref info 8)) 'error)
+	  (progn
+	    (goto-char (nth 1 (aref info 8)))
+	    (error (nth 2 (aref info 8)))))
+      (let ((mode-line-buffer-identification mode-line-buffer-identification)
+	    (calc-embedded-info info)
+	    (calc-embedded-no-reselect t))
+	(calc-wrapper
+	 (let* ((okay nil)
+		(calc-no-refresh-evaltos t))
+	   (setq chg (calc-embedded-set-modes
+		      (aref info 15) (aref info 12) (aref info 13)))
+	   (if (aref info 8)
+	       (calc-push (calc-normalize (aref info 8)))
+	     (calc-alg-entry)))
+	 (setq calc-undo-list nil
+	       calc-redo-list nil
+	       ident mode-line-buffer-identification)))
+      (setq calc-embedded-info info
+	    calc-embedded-modes modes
+	    mode-line-buffer-identification ident
+	    truncate-lines t
+	    buffer-read-only t)
+      (set-buffer-modified-p (buffer-modified-p))
+      (use-local-map calc-mode-map)
+      (setq calc-no-refresh-evaltos nil)
+      (and chg calc-any-evaltos (calc-wrapper (calc-refresh-evaltos)))
+      (or (eq calc-embedded-quiet t)
+	  (message "Embedded Calc mode enabled.  %s to return to normal."
+		   (if calc-embedded-quiet
+		       "Type `M-# x'"
+		     "Give this command again")))))
+  (scroll-down 0)    ; fix a bug which occurs when truncate-lines is changed.
+)
+(setq calc-embedded-quiet nil)
+
+
+(defun calc-embedded-select (arg)
+  (interactive "P")
+  (calc-embedded arg)
+  (and calc-embedded-info
+       (eq (car-safe (aref calc-embedded-info 8)) 'calcFunc-evalto)
+       (calc-select-part 1))
+  (and calc-embedded-info
+       (or (eq (car-safe (aref calc-embedded-info 8)) 'calcFunc-assign)
+	   (and (eq (car-safe (aref calc-embedded-info 8)) 'calcFunc-evalto)
+		(eq (car-safe (nth 1 (aref calc-embedded-info 8)))
+		    'calcFunc-assign)))
+       (calc-select-part 2))
+)
+
+
+(defun calc-embedded-update-formula (arg)
+  (interactive "P")
+  (if arg
+      (let ((entry (assq (current-buffer) calc-embedded-active)))
+	(while (setq entry (cdr entry))
+	  (and (eq (car-safe (aref (car entry) 8)) 'calcFunc-evalto)
+	       (or (not (consp arg))
+		   (and (<= (aref (car entry) 2) (region-beginning))
+			(>= (aref (car entry) 3) (region-end))))
+	       (save-excursion
+		 (calc-embedded-update (car entry) 14 t t)))))
+    (if (and calc-embedded-info
+	     (eq (current-buffer) (aref calc-embedded-info 0))
+	     (>= (point) (aref calc-embedded-info 4))
+	     (<= (point) (aref calc-embedded-info 5)))
+	(calc-evaluate 1)
+      (let* ((opt (point))
+	     (info (calc-embedded-make-info (point) nil t))
+	     (pt (- opt (aref info 4))))
+	(or (eq (car-safe (aref info 8)) 'error)
+	    (progn
+	      (save-excursion
+		(calc-embedded-update info 14 'eval t))
+	      (goto-char (+ (aref info 4) pt)))))))
+)
+
+
+(defun calc-embedded-edit (arg)
+  (interactive "P")
+  (let ((info (calc-embedded-make-info (point) nil t arg))
+	str)
+    (if (eq (car-safe (aref info 8)) 'error)
+	(progn
+	  (goto-char (nth 1 (aref info 8)))
+	  (error (nth 2 (aref info 8)))))
+    (calc-wrapper
+     (setq str (math-showing-full-precision
+		(math-format-nice-expr (aref info 8) (screen-width))))
+     (calc-edit-mode (list 'calc-embedded-finish-edit info))
+     (insert str "\n")))
+  (calc-show-edit-buffer)
+)
+
+(defun calc-embedded-finish-edit (info)
+  (let ((buf (current-buffer))
+	(str (buffer-substring (point) (point-max)))
+	(start (point))
+	pos)
+    (switch-to-buffer calc-original-buffer)
+    (let ((val (save-excursion
+		 (set-buffer (aref info 1))
+		 (let ((calc-language nil)
+		       (math-expr-opers math-standard-opers))
+		   (math-read-expr str)))))
+      (if (eq (car-safe val) 'error)
+	  (progn
+	    (switch-to-buffer buf)
+	    (goto-char (+ start (nth 1 val)))
+	    (error (nth 2 val))))
+      (calc-embedded-original-buffer t info)
+      (aset info 8 val)
+      (calc-embedded-update info 14 t t)))
+)
+
+(defun calc-do-embedded-activate (arg cbuf)
+  (calc-plain-buffer-only)
+  (if arg
+      (calc-embedded-forget))
+  (calc-find-globals)
+  (if (< (prefix-numeric-value arg) 0)
+      (message "Deactivating %s for Calc Embedded mode." (buffer-name))
+    (message "Activating %s for Calc Embedded mode..." (buffer-name))
+    (save-excursion
+      (let* ((active (assq (current-buffer) calc-embedded-active))
+	     (info active)
+	     (pat " := \\| \\\\gets \\| => \\| \\\\evalto "))
+	(if calc-embedded-announce-formula
+	    (setq pat (format "%s\\|\\(%s\\)"
+			      pat calc-embedded-announce-formula)))
+	(while (setq info (cdr info))
+	  (or (equal (buffer-substring (aref (car info) 2) (aref (car info) 3))
+		     (aref (car info) 6))
+	      (setcdr active (delq (car info) (cdr active)))))
+	(goto-char (point-min))
+	(while (re-search-forward pat nil t)
+	  (if (looking-at calc-embedded-open-formula)
+	      (goto-char (match-end 1)))
+	  (setq info (calc-embedded-make-info (point) cbuf nil))
+	  (or (eq (car-safe (aref info 8)) 'error)
+	      (goto-char (aref info 5))))))
+    (message "Activating %s for Calc Embedded mode...done" (buffer-name)))
+  (calc-embedded-active-state t)
+)
+
+(defun calc-plain-buffer-only ()
+  (if (memq major-mode '(calc-mode calc-trail-mode calc-edit-mode))
+      (error "This command should be used in a normal editing buffer"))
+)
+
+(defun calc-embedded-active-state (state)
+  (or (assq 'calc-embedded-all-active minor-mode-alist)
+      (setq minor-mode-alist
+	    (cons '(calc-embedded-all-active " Active")
+		  (cons '(calc-embedded-some-active " ~Active")
+			minor-mode-alist))))
+  (let ((active (assq (current-buffer) calc-embedded-active)))
+    (or (cdr active)
+	(setq state nil)))
+  (and (eq state 'more) calc-embedded-all-active (setq state t))
+  (setq calc-embedded-all-active (eq state t)
+	calc-embedded-some-active (not (memq state '(nil t))))
+  (set-buffer-modified-p (buffer-modified-p))
+)
+
+
+(defun calc-embedded-original-buffer (switch &optional info)
+  (or info (setq info calc-embedded-info))
+  (or (buffer-name (aref info 0))
+      (progn
+	(error "Calc embedded mode: Original buffer has been killed")))
+  (if switch
+      (set-buffer (aref info 0)))
+)
+
+(defun calc-embedded-word ()
+  (interactive)
+  (calc-embedded '(4))
+)
+
+(defun calc-embedded-mark-formula (&optional body-only)
+  "Put point at the beginning of this Calc formula, mark at the end.
+This normally marks the whole formula, including surrounding delimiters.
+With any prefix argument, marks only the formula itself."
+  (interactive "P")
+  (and (eq major-mode 'calc-mode)
+       (error "This command should be used in a normal editing buffer"))
+  (let (top bot outer-top outer-bot)
+    (save-excursion
+      (calc-embedded-find-bounds body-only))
+    (push-mark (if body-only bot outer-bot) t)
+    (goto-char (if body-only top outer-top)))
+)
+
+(defun calc-embedded-find-bounds (&optional plain)
+  ;; (while (and (bolp) (eq (following-char) ?\n))
+  ;;  (forward-char 1))
+  (and (eolp) (bolp) (not (eq (char-after (- (point) 2)) ?\n))
+       (forward-char -1))
+  (let ((home (point)))
+    (or (and (looking-at calc-embedded-open-formula)
+	     (not (looking-at calc-embedded-close-formula)))
+	(re-search-backward calc-embedded-open-formula nil t)
+	(error "Can't find start of formula"))
+    (and (eq (preceding-char) ?\$)  ; backward search for \$\$? won't back
+	 (eq (following-char) ?\$)  ; up over a second $, so do it by hand.
+	 (forward-char -1))
+    (setq outer-top (point))
+    (goto-char (match-end 0))
+    (if (eq (following-char) ?\n)
+	(forward-char 1))
+    (or (bolp)
+	(while (eq (following-char) ?\ )
+	  (forward-char 1)))
+    (or (eq plain 'plain)
+	(if (looking-at (regexp-quote calc-embedded-open-plain))
+	    (progn
+	      (goto-char (match-end 0))
+	      (search-forward calc-embedded-close-plain))))
+    (setq top (point))
+    (or (re-search-forward calc-embedded-close-formula nil t)
+	(error "Can't find end of formula"))
+    (if (< (point) home)
+	(error "Not inside a formula"))
+    (and (eq (following-char) ?\n) (not (bolp))
+	 (forward-char 1))
+    (setq outer-bot (point))
+    (goto-char (match-beginning 0))
+    (if (eq (preceding-char) ?\n)
+	(backward-char 1))
+    (or (eolp)
+	(while (eq (preceding-char) ?\ )
+	  (backward-char 1)))
+    (setq bot (point)))
+)
+
+(defun calc-embedded-kill-formula ()
+  "Kill the formula surrounding point.
+If Calc Embedded mode was active, this deactivates it.
+The formula (including its surrounding delimiters) is saved in the kill ring.
+The command \\[yank] can retrieve it from there."
+  (interactive)
+  (and calc-embedded-info
+       (calc-embedded nil))
+  (calc-embedded-mark-formula)
+  (kill-region (point) (mark))
+  (pop-mark)
+)
+
+(defun calc-embedded-copy-formula-as-kill ()
+  "Save the formula surrounding point as if killed, but don't kill it."
+  (interactive)
+  (save-excursion
+    (calc-embedded-mark-formula)
+    (copy-region-as-kill (point) (mark))
+    (pop-mark))
+)
+
+(defun calc-embedded-duplicate ()
+  (interactive)
+  (let ((already calc-embedded-info)
+	top bot outer-top outer-bot new-top)
+    (if calc-embedded-info
+	(progn
+	  (setq top (+ (aref calc-embedded-info 2))
+		bot (+ (aref calc-embedded-info 3))
+		outer-top (+ (aref calc-embedded-info 4))
+		outer-bot (+ (aref calc-embedded-info 5)))
+	  (calc-embedded nil))
+      (calc-embedded-find-bounds))
+    (goto-char outer-bot)
+    (insert "\n")
+    (setq new-top (point))
+    (insert-buffer-substring (current-buffer) outer-top outer-bot)
+    (goto-char (+ new-top (- top outer-top)))
+    (let ((calc-embedded-quiet (if already t 'x)))
+      (calc-embedded (+ new-top (- top outer-top))
+		     (+ new-top (- bot outer-top))
+		     new-top
+		     (+ new-top (- outer-bot outer-top)))))
+)
+
+(defun calc-embedded-next (arg)
+  (interactive "P")
+  (setq arg (prefix-numeric-value arg))
+  (let* ((active (cdr (assq (current-buffer) calc-embedded-active)))
+	 (p active)
+	 (num (length active)))
+    (or active
+	(error "No active formulas in buffer"))
+    (cond ((= arg 0))
+	  ((= arg -1)
+	   (if (<= (point) (aref (car active) 3))
+	       (goto-char (aref (nth (1- num) active) 2))
+	     (while (and (cdr p)
+			 (> (point) (aref (nth 1 p) 3)))
+	       (setq p (cdr p)))
+	     (goto-char (aref (car p) 2))))
+	  ((< arg -1)
+	   (calc-embedded-next -1)
+	   (calc-embedded-next (+ (* num 1000) arg 1)))
+	  (t
+	   (setq arg (1+ (% (1- arg) num)))
+	   (while (and p (>= (point) (aref (car p) 2)))
+	     (setq p (cdr p)))
+	   (while (> (setq arg (1- arg)) 0)
+	     (setq p (if p (cdr p) (cdr active))))
+	   (goto-char (aref (car (or p active)) 2)))))
+)
+
+(defun calc-embedded-previous (arg)
+  (interactive "p")
+  (calc-embedded-next (- (prefix-numeric-value arg)))
+)
+
+(defun calc-embedded-new-formula ()
+  (interactive)
+  (and (eq major-mode 'calc-mode)
+       (error "This command should be used in a normal editing buffer"))
+  (if calc-embedded-info
+      (calc-embedded nil))
+  (let (top bot outer-top outer-bot)
+    (if (and (eq (preceding-char) ?\n)
+	     (string-match "\\`\n" calc-embedded-open-new-formula))
+	(progn
+	  (setq outer-top (1- (point)))
+	  (forward-char -1)
+	  (insert (substring calc-embedded-open-new-formula 1)))
+      (setq outer-top (point))
+      (insert calc-embedded-open-new-formula))
+    (setq top (point))
+    (insert " ")
+    (setq bot (point))
+    (insert calc-embedded-close-new-formula)
+    (if (and (eq (following-char) ?\n)
+	     (string-match "\n\\'" calc-embedded-close-new-formula))
+	(delete-char 1))
+    (setq outer-bot (point))
+    (goto-char top)
+    (let ((calc-embedded-quiet 'x))
+      (calc-embedded top bot outer-top outer-bot)))
+)
+
+(defun calc-embedded-forget ()
+  (interactive)
+  (setq calc-embedded-active (delq (assq (current-buffer) calc-embedded-active)
+				   calc-embedded-active))
+  (calc-embedded-active-state nil)
+)
+
+
+(defun calc-embedded-set-modes (gmodes modes local-modes &optional temp)
+  (let ((the-language (calc-embedded-language))
+	(the-display-just (calc-embedded-justify))
+	(v gmodes)
+	(changed nil)
+	found value)
+    (while v
+      (or (symbolp (car v))
+	  (and (setq found (assq (car (car v)) modes))
+	       (not (eq (cdr found) 'default)))
+	  (and (setq found (assq (car (car v)) local-modes))
+	       (not (eq (cdr found) 'default)))
+	  (progn
+	    (if (eq (setq value (cdr (car v))) 'default)
+		(setq value (cdr (assq (car (car v)) calc-mode-var-list))))
+	    (equal (symbol-value (car (car v))) value))
+	  (progn
+	    (setq changed t)
+	    (if temp (setq prev-modes (cons (cons (car (car v))
+						  (symbol-value (car (car v))))
+					    prev-modes)))
+	    (set (car (car v)) value)))
+      (setq v (cdr v)))
+    (setq v modes)
+    (while v
+      (or (and (setq found (assq (car (car v)) local-modes))
+	       (not (eq (cdr found) 'default)))
+	  (eq (setq value (cdr (car v))) 'default)
+	  (equal (symbol-value (car (car v))) value)
+	  (progn
+	    (setq changed t)
+	    (if temp (setq prev-modes (cons (cons (car (car v))
+						  (symbol-value (car (car v))))
+					    prev-modes)))
+	    (set (car (car v)) value)))
+      (setq v (cdr v)))
+    (setq v local-modes)
+    (while v
+      (or (eq (setq value (cdr (car v))) 'default)
+	  (equal (symbol-value (car (car v))) value)
+	  (progn
+	    (setq changed t)
+	    (if temp (setq prev-modes (cons (cons (car (car v))
+						  (symbol-value (car (car v))))
+					    prev-modes)))
+	    (set (car (car v)) value)))
+      (setq v (cdr v)))
+    (and changed (not (eq temp t))
+	 (progn
+	   (calc-embedded-set-justify the-display-just)
+	   (calc-embedded-set-language the-language)))
+    (and changed (not temp)
+	 (progn
+	   (setq calc-full-float-format (list (if (eq (car calc-float-format)
+						      'fix)
+						  'float
+						(car calc-float-format))
+					      0))
+	   (calc-refresh)))
+    changed)
+)
+
+(defun calc-embedded-language ()
+  (if calc-language-option
+      (list calc-language calc-language-option)
+    calc-language)
+)
+
+(defun calc-embedded-set-language (lang)
+  (let ((option nil))
+    (if (consp lang)
+	(setq option (nth 1 lang)
+	      lang (car lang)))
+    (or (and (eq lang calc-language)
+	     (equal option calc-language-option))
+	(calc-set-language lang option t)))
+)
+
+(defun calc-embedded-justify ()
+  (if calc-display-origin
+      (list calc-display-just calc-display-origin)
+    calc-display-just)
+)
+
+(defun calc-embedded-set-justify (just)
+  (if (consp just)
+      (setq calc-display-origin (nth 1 just)
+	    calc-display-just (car just))
+    (setq calc-display-just just
+	  calc-display-origin nil))
+)
+
+
+(defun calc-find-globals ()
+  (interactive)
+  (and (eq major-mode 'calc-mode)
+       (error "This command should be used in a normal editing buffer"))
+  (make-local-variable 'calc-embedded-globals)
+  (let ((case-fold-search nil)
+	(modes nil)
+	(save-pt (point))
+	found value)
+    (goto-char (point-min))
+    (while (re-search-forward "\\[calc-global-mode: *\\([-a-z]+\\): *\\(\"\\([^\"\n\\]\\|\\\\.\\)*\"\\|[- ()a-zA-Z0-9]+\\)\\]" nil t)
+      (and (setq found (assoc (buffer-substring (match-beginning 1)
+						(match-end 1))
+			      calc-embedded-mode-vars))
+	   (or (assq (cdr found) modes)
+	       (setq modes (cons (cons (cdr found)
+				       (car (read-from-string
+					     (buffer-substring
+					      (match-beginning 2)
+					      (match-end 2)))))
+				 modes)))))
+    (setq calc-embedded-globals (cons t modes))
+    (goto-char save-pt))
+)
+
+(defun calc-embedded-find-modes ()
+  (let ((case-fold-search nil)
+	(save-pt (point))
+	(no-defaults t)
+	(modes nil)
+	(emodes nil)
+	(pmodes nil)
+	found value)
+    (while (and no-defaults (search-backward "[calc-" nil t))
+      (forward-char 6)
+      (or (and (looking-at "mode: *\\([-a-z]+\\): *\\(\"\\([^\"\n\\]\\|\\\\.\\)*\"\\|[- ()a-zA-Z0-9]+\\)]")
+	       (setq found (assoc (buffer-substring (match-beginning 1)
+						    (match-end 1))
+				  calc-embedded-mode-vars))
+	       (or (assq (cdr found) modes)
+		   (setq modes (cons (cons (cdr found)
+					   (car (read-from-string
+						 (buffer-substring
+						  (match-beginning 2)
+						  (match-end 2)))))
+				     modes))))
+	  (and (looking-at "perm-mode: *\\([-a-z]+\\): *\\(\"\\([^\"\n\\]\\|\\\\.\\)*\"\\|[- ()a-zA-Z0-9]+\\)]")
+	       (setq found (assoc (buffer-substring (match-beginning 1)
+						    (match-end 1))
+				  calc-embedded-mode-vars))
+	       (or (assq (cdr found) pmodes)
+		   (setq pmodes (cons (cons (cdr found)
+					    (car (read-from-string
+						  (buffer-substring
+						   (match-beginning 2)
+						   (match-end 2)))))
+				      pmodes))))
+	  (and (looking-at "edit-mode: *\\([-a-z]+\\): *\\(\"\\([^\"\n\\]\\|\\\\.\\)*\"\\|[- ()a-zA-Z0-9]+\\)]")
+	       (setq found (assoc (buffer-substring (match-beginning 1)
+						    (match-end 1))
+				  calc-embedded-mode-vars))
+	       (or (assq (cdr found) emodes)
+		   (setq emodes (cons (cons (cdr found)
+					    (car (read-from-string
+						  (buffer-substring
+						   (match-beginning 2)
+						   (match-end 2)))))
+				      emodes))))
+	  (and (looking-at "defaults]")
+	       (setq no-defaults nil)))
+      (backward-char 6))
+    (goto-char save-pt)
+    (list modes emodes pmodes))
+)
+
+
+(defun calc-embedded-make-info (point cbuf fresh &optional
+				      top bot outer-top outer-bot)
+  (let* ((bufentry (assq (current-buffer) calc-embedded-active))
+	 (found bufentry)
+	 (force (and fresh top))
+	 (fixed top)
+	 (new-info nil)
+	 info str)
+    (or found
+	(setq found (list (current-buffer))
+	      calc-embedded-active (cons found calc-embedded-active)))
+    (while (and (cdr found)
+		(> point (aref (car (cdr found)) 3)))
+      (setq found (cdr found)))
+    (if (and (cdr found)
+	     (>= point (aref (nth 1 found) 2)))
+	(setq info (nth 1 found))
+      (setq info (make-vector 16 nil)
+	    new-info t
+	    fresh t)
+      (aset info 0 (current-buffer))
+      (aset info 1 (or cbuf (save-excursion
+			      (calc-create-buffer)
+			      (current-buffer)))))
+    (if (and (integerp top) (not bot))  ; started with a user-supplied argument
+	(progn
+	  (if (= (setq arg (prefix-numeric-value arg)) 0)
+	      (progn
+		(aset info 2 (copy-marker (region-beginning)))
+		(aset info 3 (copy-marker (region-end))))
+	    (aset info (if (> arg 0) 2 3) (point-marker))
+	    (forward-line arg)
+	    (aset info (if (> arg 0) 3 2) (point-marker)))
+	  (aset info 4 (copy-marker (aref info 2)))
+	  (aset info 5 (copy-marker (aref info 3))))
+      (if (aref info 4)
+	  (setq top (aref info 2)
+		fixed top)
+	(if (consp top)
+	    (let ((calc-embedded-open-formula calc-embedded-open-word)
+		  (calc-embedded-close-formula calc-embedded-close-word))
+	      (calc-embedded-find-bounds 'plain))
+	  (or top
+	      (calc-embedded-find-bounds 'plain)))
+	(aset info 2 (copy-marker (min top bot)))
+	(aset info 3 (copy-marker (max top bot)))
+	(aset info 4 (copy-marker (or outer-top (aref info 2))))
+	(aset info 5 (copy-marker (or outer-bot (aref info 3))))))
+    (goto-char (aref info 2))
+    (if new-info
+	(progn
+	  (or (bolp) (aset info 7 t))
+	  (goto-char (aref info 3))
+	  (or (bolp) (eolp) (aset info 7 t))))
+    (if fresh
+	(let ((modes (calc-embedded-find-modes)))
+	  (aset info 12 (car modes))
+	  (aset info 13 (nth 1 modes))
+	  (aset info 14 (nth 2 modes))))
+    (aset info 15 calc-embedded-globals)
+    (setq str (buffer-substring (aref info 2) (aref info 3)))
+    (if (or force
+	    (not (equal str (aref info 6))))
+	(if (and fixed (aref info 6))
+	    (progn
+	      (aset info 4 nil)
+	      (calc-embedded-make-info point cbuf nil)
+	      (setq new-info nil))
+	  (let* ((open-plain calc-embedded-open-plain)
+		 (close-plain calc-embedded-close-plain)
+		 (pref-len (length open-plain))
+		 (vars-used nil)
+		 suff-pos val temp)
+	    (save-excursion
+	      (set-buffer (aref info 1))
+	      (calc-embedded-set-modes (aref info 15)
+				       (aref info 12) (aref info 14))
+	      (if (and (> (length str) pref-len)
+		       (equal (substring str 0 pref-len) open-plain)
+		       (setq suff-pos (string-match (regexp-quote close-plain)
+						    str pref-len)))
+		  (setq val (math-read-plain-expr
+			     (substring str pref-len suff-pos)))
+		(if (string-match "[^ \t\n]" str)
+		    (setq pref-len 0
+			  val (math-read-big-expr str))
+		  (setq val nil))))
+	    (if (eq (car-safe val) 'error)
+		(setq val (list 'error
+				(+ (aref info 2) pref-len (nth 1 val))
+				(nth 2 val))))
+	    (aset info 6 str)
+	    (aset info 8 val)
+	    (setq temp val)
+	    (if (eq (car-safe temp) 'calcFunc-evalto)
+		(setq temp (nth 1 temp))
+	      (if (eq (car-safe temp) 'error)
+		  (if new-info
+		      (setq new-info nil)
+		    (setcdr found (delq info (cdr found)))
+		    (calc-embedded-active-state 'less))))
+	    (aset info 9 (and (eq (car-safe temp) 'calcFunc-assign)
+			      (nth 1 temp)))
+	    (if (memq (car-safe val) '(calcFunc-evalto calcFunc-assign))
+		(calc-embedded-find-vars val))
+	    (aset info 10 vars-used)
+	    (aset info 11 nil))))
+    (if new-info
+	(progn
+	  (setcdr found (cons info (cdr found)))
+	  (calc-embedded-active-state 'more)))
+    info)
+)
+
+(defun calc-embedded-find-vars (x)
+  (cond ((Math-primp x)
+	 (and (eq (car-safe x) 'var)
+	      (not (assoc x vars-used))
+	      (setq vars-used (cons (list x) vars-used))))
+	((eq (car x) 'calcFunc-evalto)
+	 (calc-embedded-find-vars (nth 1 x)))
+	((eq (car x) 'calcFunc-assign)
+	 (calc-embedded-find-vars (nth 2 x)))
+	(t
+	 (and (eq (car x) 'calcFunc-subscr)
+	      (eq (car-safe (nth 1 x)) 'var)
+	      (Math-primp (nth 2 x))
+	      (not (assoc x vars-used))
+	      (setq vars-used (cons (list x) vars-used)))
+	 (while (setq x (cdr x))
+	   (calc-embedded-find-vars (car x)))))
+)
+
+
+(defun calc-embedded-evaluate-expr (x)
+  (let ((vars-used (aref calc-embedded-info 10)))
+    (or vars-used (calc-embedded-find-vars x))
+    (if vars-used
+	(let ((active (assq (aref calc-embedded-info 0) calc-embedded-active))
+	      (args nil))
+	  (save-excursion
+	    (calc-embedded-original-buffer t)
+	    (or active
+		(progn
+		  (calc-embedded-activate)
+		  (setq active (assq (aref calc-embedded-info 0)
+				     calc-embedded-active))))
+	    (while vars-used
+	      (calc-embedded-eval-get-var (car (car vars-used)) active)
+	      (setq vars-used (cdr vars-used))))
+	  (calc-embedded-subst x))
+      (calc-normalize (math-evaluate-expr-rec x))))
+)
+
+(defun calc-embedded-subst (x)
+  (if (and (eq (car-safe x) 'calcFunc-evalto) (cdr x))
+      (let ((rhs (calc-embedded-subst (nth 1 x))))
+	(list 'calcFunc-evalto
+	      (nth 1 x)
+	      (if (eq (car-safe rhs) 'calcFunc-assign) (nth 2 rhs) rhs)))
+    (if (and (eq (car-safe x) 'calcFunc-assign) (= (length x) 3))
+	(list 'calcFunc-assign
+	      (nth 1 x)
+	      (calc-embedded-subst (nth 2 x)))
+      (calc-normalize (math-evaluate-expr-rec (math-multi-subst-rec x)))))
+)
+
+(defun calc-embedded-eval-get-var (var base)
+  (let ((entry base)
+	(point (aref calc-embedded-info 2))
+	(last nil)
+	val)
+    (while (and (setq entry (cdr entry))
+		(or (not (equal var (aref (car entry) 9)))
+		    (and (> point (aref (car entry) 3))
+			 (setq last entry)))))
+    (if last
+	(setq entry last))
+    (if entry
+	(progn
+	  (setq entry (car entry))
+	  (if (equal (buffer-substring (aref entry 2) (aref entry 3))
+		     (aref entry 6))
+	      (progn
+		(or (aref entry 11)
+		    (save-excursion
+		      (calc-embedded-update entry 14 t nil)))
+		(setq val (aref entry 11))
+		(if (eq (car-safe val) 'calcFunc-evalto)
+		    (setq val (nth 2 val)))
+		(if (eq (car-safe val) 'calcFunc-assign)
+		    (setq val (nth 2 val)))
+		(setq args (cons (cons var val) args)))
+	    (calc-embedded-activate)
+	    (calc-embedded-eval-get-var var base)))))
+)
+
+
+(defun calc-embedded-update (info which need-eval need-display
+				  &optional str entry old-val)
+  (let* ((prev-modes nil)
+	 (open-plain calc-embedded-open-plain)
+	 (close-plain calc-embedded-close-plain)
+	 (vars-used nil)
+	 (evalled nil)
+	 (val (aref info 8))
+	 (old-eval (aref info 11)))
+    (or old-val (setq old-val val))
+    (if (eq (car-safe val) 'calcFunc-evalto)
+	(setq need-display t))
+    (unwind-protect
+	(progn
+	  (set-buffer (aref info 1))
+	  (and which
+	       (calc-embedded-set-modes (aref info 15) (aref info 12)
+					(aref info which)
+					(if need-display 'full t)))
+	  (if (memq (car-safe val) '(calcFunc-evalto calcFunc-assign))
+	      (calc-embedded-find-vars val))
+	  (if need-eval
+	      (let ((calc-embedded-info info))
+		(setq val (math-evaluate-expr val)
+		      evalled val)))
+	  (if (or (eq need-eval 'eval) (eq (car-safe val) 'calcFunc-evalto))
+	      (aset info 8 val))
+	  (aset info 9 nil)
+	  (aset info 10 vars-used)
+	  (aset info 11 nil)
+	  (if (or need-display (eq (car-safe val) 'calcFunc-evalto))
+	      (let ((extra (if (eq calc-language 'big) 1 0)))
+		(or entry (setq entry (list val 1 nil)))
+		(or str (progn
+			  (setq str (let ((calc-line-numbering nil))
+				      (math-format-stack-value entry)))
+			  (if (eq calc-language 'big)
+			      (setq str (substring str 0 -1)))))
+		(and calc-show-plain
+		     (setq str (concat open-plain
+				       (math-showing-full-precision
+					(math-format-flat-expr val 0))
+				       close-plain
+				       str)))
+		(save-excursion
+		  (calc-embedded-original-buffer t info)
+		  (or (equal str (aref info 6))
+		      (let ((delta (- (aref info 5) (aref info 3)))
+			    (buffer-read-only nil))
+			(goto-char (aref info 2))
+			(delete-region (point) (aref info 3))
+			(and (> (nth 1 entry) (1+ extra))
+			     (aref info 7)
+			     (progn
+			       (aset info 7 nil)
+			       (delete-horizontal-space)
+			       (insert "\n\n")
+			       (delete-horizontal-space)
+			       (backward-char 1)))
+			(insert str)
+			(set-marker (aref info 3) (point))
+			(set-marker (aref info 5) (+ (point) delta))
+			(aset info 6 str))))))
+	  (if (eq (car-safe val) 'calcFunc-evalto)
+	      (progn
+		(setq evalled (nth 2 val)
+		      val (nth 1 val))))
+	  (if (eq (car-safe val) 'calcFunc-assign)
+	      (progn
+		(aset info 9 (nth 1 val))
+		(aset info 11 (or evalled
+				  (let ((calc-embedded-info info))
+				    (math-evaluate-expr (nth 2 val)))))
+		(or (equal old-eval (aref info 11))
+		    (calc-embedded-var-change (nth 1 val) (aref info 0))))
+	    (if (eq (car-safe old-val) 'calcFunc-evalto)
+		(setq old-val (nth 1 old-val)))
+	    (if (eq (car-safe old-val) 'calcFunc-assign)
+		(calc-embedded-var-change (nth 1 old-val) (aref info 0)))))
+      (set-buffer (aref info 1))
+      (while prev-modes
+	(cond ((eq (car (car prev-modes)) 'the-language)
+	       (if need-display
+		   (calc-embedded-set-language (cdr (car prev-modes)))))
+	      ((eq (car (car prev-modes)) 'the-display-just)
+	       (if need-display
+		   (calc-embedded-set-justify (cdr (car prev-modes)))))
+	      (t
+	       (set (car (car prev-modes)) (cdr (car prev-modes)))))
+	(setq prev-modes (cdr prev-modes)))))
+)
+
+
+
+
+;;; These are hooks called by the main part of Calc.
+
+(defun calc-embedded-select-buffer ()
+  (if (eq (current-buffer) (aref calc-embedded-info 0))
+      (let ((info calc-embedded-info)
+	    horiz vert)
+	(if (and (or (< (point) (aref info 4))
+		     (> (point) (aref info 5)))
+		 (not calc-embedded-no-reselect))
+	    (let ((calc-embedded-quiet t))
+	      (message "(Switching Calc Embedded mode to new formula.)")
+	      (calc-embedded nil)
+	      (calc-embedded nil)))
+	(setq horiz (max (min (current-column) (- (point) (aref info 2))) 0)
+	      vert (if (<= (aref info 2) (point))
+		       (- (count-lines (aref info 2) (point))
+			  (if (bolp) 0 1))
+		     0))
+	(set-buffer (aref info 1))
+	(if calc-show-plain
+	    (if (= vert 0)
+		(setq horiz 0)
+	      (setq vert (1- vert))))
+	(calc-cursor-stack-index 1)
+	(if calc-line-numbering
+	    (setq horiz (+ horiz 4)))
+	(if (> vert 0)
+	    (forward-line vert))
+	(forward-char (min horiz
+			   (- (point-max) (point)))))
+    (calc-select-buffer))
+)
+(setq calc-embedded-no-reselect nil)
+
+(defun calc-embedded-finish-command ()
+  (let ((buf (current-buffer))
+	horiz vert)
+    (save-excursion
+      (set-buffer (aref calc-embedded-info 1))
+      (if (> (calc-stack-size) 0)
+	  (let ((pt (point))
+		(col (current-column))
+		(bol (bolp)))
+	    (calc-cursor-stack-index 0)
+	    (if (< pt (point))
+		(progn
+		  (calc-cursor-stack-index 1)
+		  (if (>= pt (point))
+		      (progn
+			(setq horiz (- col (if calc-line-numbering 4 0))
+			      vert (- (count-lines (point) pt)
+				      (if bol 0 1)))
+			(if calc-show-plain
+			    (setq vert (max 1 (1+ vert))))))))
+	    (goto-char pt))))
+    (if horiz
+	(progn
+	  (set-buffer (aref calc-embedded-info 0))
+	  (goto-char (aref calc-embedded-info 2))
+	  (if (> vert 0)
+	      (forward-line vert))
+	  (forward-char (max horiz 0))
+	  (set-buffer buf))))
+)
+
+(defun calc-embedded-stack-change ()
+  (or calc-executing-macro
+      (save-excursion
+	(set-buffer (aref calc-embedded-info 1))
+	(let* ((info calc-embedded-info)
+	       (extra-line (if (eq calc-language 'big) 1 0))
+	       (the-point (point))
+	       (empty (= (calc-stack-size) 0))
+	       (entry (if empty
+			  (list '(var empty var-empty) 1 nil)
+			(calc-top 1 'entry)))
+	       (old-val (aref info 8))
+	       top bot str)
+	  (if empty
+	      (setq str "empty")
+	    (save-excursion
+	      (calc-cursor-stack-index 1)
+	      (setq top (point))
+	      (calc-cursor-stack-index 0)
+	      (setq bot (- (point) extra-line))
+	      (setq str (buffer-substring top (- bot 1))))
+	    (if calc-line-numbering
+		(let ((pos 0))
+		  (setq str (substring str 4))
+		  (while (setq pos (string-match "\n...." str pos))
+		    (setq str (concat (substring str 0 (1+ pos))
+				      (substring str (+ pos 5)))
+			  pos (1+ pos))))))
+	  (calc-embedded-original-buffer t)
+	  (aset info 8 (car entry))
+	  (calc-embedded-update info 13 nil t str entry old-val))))
+)
+
+(defun calc-embedded-mode-line-change ()
+  (let ((str mode-line-buffer-identification))
+    (save-excursion
+      (calc-embedded-original-buffer t)
+      (setq mode-line-buffer-identification str)
+      (set-buffer-modified-p (buffer-modified-p))))
+)
+
+(defun calc-embedded-modes-change (vars)
+  (if (eq (car vars) 'calc-language) (setq vars '(the-language)))
+  (if (eq (car vars) 'calc-display-just) (setq vars '(the-display-just)))
+  (while (and vars
+	      (not (rassq (car vars) calc-embedded-mode-vars)))
+    (setq vars (cdr vars)))
+  (if (and vars calc-mode-save-mode (not (eq calc-mode-save-mode 'save)))
+      (save-excursion
+	(let* ((save-mode calc-mode-save-mode)
+	       (header (if (eq save-mode 'local)
+			   "calc-mode:"
+			 (format "calc-%s-mode:" save-mode)))
+	       (the-language (calc-embedded-language))
+	       (the-display-just (calc-embedded-justify))
+	       (values (mapcar 'symbol-value vars))
+	       (num (cond ((eq save-mode 'local) 12)
+			  ((eq save-mode 'edit) 13)
+			  ((eq save-mode 'perm) 14)
+			  (t nil)))
+	       base limit mname mlist)
+	  (calc-embedded-original-buffer t)
+	  (save-excursion
+	    (if (eq save-mode 'global)
+		(setq base (point-max)
+		      limit (point-min)
+		      mlist calc-embedded-globals)
+	      (goto-char (aref calc-embedded-info 4))
+	      (beginning-of-line)
+	      (setq base (point)
+		    limit (max (- (point) 1000) (point-min))
+		    mlist (and num (aref calc-embedded-info num)))
+	      (and (re-search-backward
+		    (format "\\(%s\\)[^\001]*\\(%s\\)\\|\\[calc-defaults]"
+			    calc-embedded-open-formula
+			    calc-embedded-close-formula) limit t)
+		   (setq limit (point))))
+	    (while vars
+	      (goto-char base)
+	      (if (setq mname (car (rassq (car vars)
+					  calc-embedded-mode-vars)))
+		  (let ((buffer-read-only nil)
+			(found (assq (car vars) mlist)))
+		    (if found
+			(setcdr found (car values))
+		      (setq mlist (cons (cons (car vars) (car values)) mlist))
+		      (if num
+			  (aset calc-embedded-info num mlist)
+			(if (eq save-mode 'global)
+			    (setq calc-embedded-globals mlist))))
+		    (if (re-search-backward
+			 (format "\\[%s *%s: *\\(\"\\([^\"\n\\]\\|\\\\.\\)*\"\\|[- ()a-zA-Z0-9]+\\)]"
+				 header mname)
+			 limit t)
+			(progn
+			  (goto-char (match-beginning 1))
+			  (delete-region (point) (match-end 1))
+			  (insert (prin1-to-string (car values))))
+		      (goto-char base)
+		      (insert-before-markers
+		       calc-embedded-open-mode
+		       "[" header " " mname ": "
+		       (prin1-to-string (car values)) "]"
+		       calc-embedded-close-mode))))
+	      (setq vars (cdr vars)
+		    values (cdr values)))))))
+)
+
+(defun calc-embedded-var-change (var &optional buf)
+  (if (symbolp var)
+      (setq var (list 'var
+		      (if (string-match "\\`var-.+\\'"
+					(symbol-name var))
+			  (intern (substring (symbol-name var) 4))
+			var)
+		      var)))
+  (save-excursion
+    (let ((manual (not calc-auto-recompute))
+	  (bp calc-embedded-active)
+	  (first t))
+      (if buf (setq bp (memq (assq buf bp) bp)))
+      (while bp
+	(let ((calc-embedded-no-reselect t)
+	      (p (and (buffer-name (car (car bp)))
+		      (cdr (car bp)))))
+	  (while p
+	    (if (assoc var (aref (car p) 10))
+		(if manual
+		    (if (aref (car p) 11)
+			(progn
+			  (aset (car p) 11 nil)
+			  (if (aref (car p) 9)
+			      (calc-embedded-var-change (aref (car p) 9)))))
+		  (set-buffer (aref (car p) 0))
+		  (if (equal (buffer-substring (aref (car p) 2)
+					       (aref (car p) 3))
+			     (aref (car p) 6))
+		      (let ((calc-embedded-info nil))
+			(or calc-embedded-quiet
+			    (message "Recomputing..."))
+			(setq first nil)
+			(calc-wrapper
+			 (set-buffer (aref (car p) 0))
+			 (calc-embedded-update (car p) 14 t nil)))
+		    (setcdr (car bp) (delq (car p) (cdr (car bp))))
+		    (message
+		     "(Tried to recompute but formula was changed or missing.)"))))
+	    (setq p (cdr p))))
+	(setq bp (if buf nil (cdr bp))))
+      (or first calc-embedded-quiet (message ""))))
+)
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/calc-ext.el	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,3439 @@
+;; Calculator for GNU Emacs, part II
+;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+;; Written by Dave Gillespie, daveg@synaptics.com.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY.  No author or distributor
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing.  Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License.   A copy of this license is
+;; supposed to have been given to you along with GNU Emacs so you
+;; can know your rights and responsibilities.  It should be in a
+;; file named COPYING.  Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+
+
+
+(provide 'calc-ext)
+
+(setq calc-extensions-loaded t)
+
+;;; This function is the autoload "hook" to cause this file to be loaded.
+;;;###autoload
+(defun calc-extensions ()
+  "This function is part of the autoload linkage for parts of Calc."
+  t
+)
+
+;;; Auto-load calc.el part, in case this part was loaded first.
+(if (fboundp 'calc-dispatch)
+    (and (eq (car-safe (symbol-function 'calc-dispatch)) 'autoload)
+	 (load (nth 1 (symbol-function 'calc-dispatch))))
+  (if (fboundp 'calc)
+      (and (eq (car-safe (symbol-function 'calc)) 'autoload)
+	   (load (nth 1 (symbol-function 'calc))))
+    (error "Main part of Calc must be present in order to load this file.")))
+
+(require 'calc-macs)
+
+;;; The following was made a function so that it could be byte-compiled.
+(defun calc-init-extensions ()
+
+  (setq gc-cons-threshold (max gc-cons-threshold 250000))
+
+  (define-key calc-mode-map ":" 'calc-fdiv)
+  (define-key calc-mode-map "\\" 'calc-idiv)
+  (define-key calc-mode-map "|" 'calc-concat)
+  (define-key calc-mode-map "!" 'calc-factorial)
+  (define-key calc-mode-map "C" 'calc-cos)
+  (define-key calc-mode-map "E" 'calc-exp)
+  (define-key calc-mode-map "H" 'calc-hyperbolic)
+  (define-key calc-mode-map "I" 'calc-inverse)
+  (define-key calc-mode-map "J" 'calc-conj)
+  (define-key calc-mode-map "L" 'calc-ln)
+  (define-key calc-mode-map "N" 'calc-eval-num)
+  (define-key calc-mode-map "P" 'calc-pi)
+  (define-key calc-mode-map "Q" 'calc-sqrt)
+  (define-key calc-mode-map "R" 'calc-round)
+  (define-key calc-mode-map "S" 'calc-sin)
+  (define-key calc-mode-map "T" 'calc-tan)
+  (define-key calc-mode-map "U" 'calc-undo)
+  (define-key calc-mode-map "X" 'calc-call-last-kbd-macro)
+  (define-key calc-mode-map "o" 'calc-realign)
+  (define-key calc-mode-map "p" 'calc-precision)
+  (define-key calc-mode-map "w" 'calc-why)
+  (define-key calc-mode-map "x" 'calc-execute-extended-command)
+  (define-key calc-mode-map "y" 'calc-copy-to-buffer)
+
+  (define-key calc-mode-map "(" 'calc-begin-complex)
+  (define-key calc-mode-map ")" 'calc-end-complex)
+  (define-key calc-mode-map "[" 'calc-begin-vector)
+  (define-key calc-mode-map "]" 'calc-end-vector)
+  (define-key calc-mode-map "," 'calc-comma)
+  (define-key calc-mode-map ";" 'calc-semi)
+  (define-key calc-mode-map "`" 'calc-edit)
+  (define-key calc-mode-map "=" 'calc-evaluate)
+  (define-key calc-mode-map "~" 'calc-num-prefix)
+  (define-key calc-mode-map "<" 'calc-scroll-left)
+  (define-key calc-mode-map ">" 'calc-scroll-right)
+  (define-key calc-mode-map "{" 'calc-scroll-down)
+  (define-key calc-mode-map "}" 'calc-scroll-up)
+  (define-key calc-mode-map "\C-k" 'calc-kill)
+  (define-key calc-mode-map "\M-k" 'calc-copy-as-kill)
+  (define-key calc-mode-map "\C-w" 'calc-kill-region)
+  (define-key calc-mode-map "\M-w" 'calc-copy-region-as-kill)
+  (define-key calc-mode-map "\C-y" 'calc-yank)
+  (define-key calc-mode-map "\C-_" 'calc-undo)
+  (define-key calc-mode-map "\C-xu" 'calc-undo)
+  (define-key calc-mode-map "\M-\C-m" 'calc-last-args)
+
+  (define-key calc-mode-map "a" nil)
+  (define-key calc-mode-map "a?" 'calc-a-prefix-help)
+  (define-key calc-mode-map "aa" 'calc-apart)
+  (define-key calc-mode-map "ab" 'calc-substitute)
+  (define-key calc-mode-map "ac" 'calc-collect)
+  (define-key calc-mode-map "ad" 'calc-derivative)
+  (define-key calc-mode-map "ae" 'calc-simplify-extended)
+  (define-key calc-mode-map "af" 'calc-factor)
+  (define-key calc-mode-map "ag" 'calc-poly-gcd)
+  (define-key calc-mode-map "ai" 'calc-integral)
+  (define-key calc-mode-map "am" 'calc-match)
+  (define-key calc-mode-map "an" 'calc-normalize-rat)
+  (define-key calc-mode-map "ap" 'calc-poly-interp)
+  (define-key calc-mode-map "ar" 'calc-rewrite)
+  (define-key calc-mode-map "as" 'calc-simplify)
+  (define-key calc-mode-map "at" 'calc-taylor)
+  (define-key calc-mode-map "av" 'calc-alg-evaluate)
+  (define-key calc-mode-map "ax" 'calc-expand)
+  (define-key calc-mode-map "aA" 'calc-abs)
+  (define-key calc-mode-map "aF" 'calc-curve-fit)
+  (define-key calc-mode-map "aI" 'calc-num-integral)
+  (define-key calc-mode-map "aM" 'calc-map-equation)
+  (define-key calc-mode-map "aN" 'calc-find-minimum)
+  (define-key calc-mode-map "aP" 'calc-poly-roots)
+  (define-key calc-mode-map "aS" 'calc-solve-for)
+  (define-key calc-mode-map "aR" 'calc-find-root)
+  (define-key calc-mode-map "aT" 'calc-tabulate)
+  (define-key calc-mode-map "aX" 'calc-find-maximum)
+  (define-key calc-mode-map "a+" 'calc-summation)
+  (define-key calc-mode-map "a-" 'calc-alt-summation)
+  (define-key calc-mode-map "a*" 'calc-product)
+  (define-key calc-mode-map "a\\" 'calc-poly-div)
+  (define-key calc-mode-map "a%" 'calc-poly-rem)
+  (define-key calc-mode-map "a/" 'calc-poly-div-rem)
+  (define-key calc-mode-map "a=" 'calc-equal-to)
+  (define-key calc-mode-map "a#" 'calc-not-equal-to)
+  (define-key calc-mode-map "a<" 'calc-less-than)
+  (define-key calc-mode-map "a>" 'calc-greater-than)
+  (define-key calc-mode-map "a[" 'calc-less-equal)
+  (define-key calc-mode-map "a]" 'calc-greater-equal)
+  (define-key calc-mode-map "a." 'calc-remove-equal)
+  (define-key calc-mode-map "a{" 'calc-in-set)
+  (define-key calc-mode-map "a&" 'calc-logical-and)
+  (define-key calc-mode-map "a|" 'calc-logical-or)
+  (define-key calc-mode-map "a!" 'calc-logical-not)
+  (define-key calc-mode-map "a:" 'calc-logical-if)
+  (define-key calc-mode-map "a_" 'calc-subscript)
+  (define-key calc-mode-map "a\"" 'calc-expand-formula)
+
+  (define-key calc-mode-map "b" nil)
+  (define-key calc-mode-map "b?" 'calc-b-prefix-help)
+  (define-key calc-mode-map "ba" 'calc-and)
+  (define-key calc-mode-map "bc" 'calc-clip)
+  (define-key calc-mode-map "bd" 'calc-diff)
+  (define-key calc-mode-map "bl" 'calc-lshift-binary)
+  (define-key calc-mode-map "bn" 'calc-not)
+  (define-key calc-mode-map "bo" 'calc-or)
+  (define-key calc-mode-map "bp" 'calc-pack-bits)
+  (define-key calc-mode-map "br" 'calc-rshift-binary)
+  (define-key calc-mode-map "bt" 'calc-rotate-binary)
+  (define-key calc-mode-map "bu" 'calc-unpack-bits)
+  (define-key calc-mode-map "bw" 'calc-word-size)
+  (define-key calc-mode-map "bx" 'calc-xor)
+  (define-key calc-mode-map "bB" 'calc-log)
+  (define-key calc-mode-map "bD" 'calc-fin-ddb)
+  (define-key calc-mode-map "bF" 'calc-fin-fv)
+  (define-key calc-mode-map "bI" 'calc-fin-irr)
+  (define-key calc-mode-map "bL" 'calc-lshift-arith)
+  (define-key calc-mode-map "bM" 'calc-fin-pmt)
+  (define-key calc-mode-map "bN" 'calc-fin-npv)
+  (define-key calc-mode-map "bP" 'calc-fin-pv)
+  (define-key calc-mode-map "bR" 'calc-rshift-arith)
+  (define-key calc-mode-map "bS" 'calc-fin-sln)
+  (define-key calc-mode-map "bT" 'calc-fin-rate)
+  (define-key calc-mode-map "bY" 'calc-fin-syd)
+  (define-key calc-mode-map "b#" 'calc-fin-nper)
+  (define-key calc-mode-map "b%" 'calc-percent-change)
+
+  (define-key calc-mode-map "c" nil)
+  (define-key calc-mode-map "c?" 'calc-c-prefix-help)
+  (define-key calc-mode-map "cc" 'calc-clean)
+  (define-key calc-mode-map "cd" 'calc-to-degrees)
+  (define-key calc-mode-map "cf" 'calc-float)
+  (define-key calc-mode-map "ch" 'calc-to-hms)
+  (define-key calc-mode-map "cp" 'calc-polar)
+  (define-key calc-mode-map "cr" 'calc-to-radians)
+  (define-key calc-mode-map "cC" 'calc-cos)
+  (define-key calc-mode-map "cF" 'calc-fraction)
+  (define-key calc-mode-map "c%" 'calc-convert-percent)
+
+  (define-key calc-mode-map "d" nil)
+  (define-key calc-mode-map "d?" 'calc-d-prefix-help)
+  (define-key calc-mode-map "d0" 'calc-decimal-radix)
+  (define-key calc-mode-map "d2" 'calc-binary-radix)
+  (define-key calc-mode-map "d6" 'calc-hex-radix)
+  (define-key calc-mode-map "d8" 'calc-octal-radix)
+  (define-key calc-mode-map "db" 'calc-line-breaking)
+  (define-key calc-mode-map "dc" 'calc-complex-notation)
+  (define-key calc-mode-map "dd" 'calc-date-notation)
+  (define-key calc-mode-map "de" 'calc-eng-notation)
+  (define-key calc-mode-map "df" 'calc-fix-notation)
+  (define-key calc-mode-map "dg" 'calc-group-digits)
+  (define-key calc-mode-map "dh" 'calc-hms-notation)
+  (define-key calc-mode-map "di" 'calc-i-notation)
+  (define-key calc-mode-map "dj" 'calc-j-notation)
+  (define-key calc-mode-map "dl" 'calc-line-numbering)
+  (define-key calc-mode-map "dn" 'calc-normal-notation)
+  (define-key calc-mode-map "do" 'calc-over-notation)
+  (define-key calc-mode-map "dp" 'calc-show-plain)
+  (define-key calc-mode-map "dr" 'calc-radix)
+  (define-key calc-mode-map "ds" 'calc-sci-notation)
+  (define-key calc-mode-map "dt" 'calc-truncate-stack)
+  (define-key calc-mode-map "dw" 'calc-auto-why)
+  (define-key calc-mode-map "dz" 'calc-leading-zeros)
+  (define-key calc-mode-map "dB" 'calc-big-language)
+  (define-key calc-mode-map "dD" 'calc-redo)
+  (define-key calc-mode-map "dC" 'calc-c-language)
+  (define-key calc-mode-map "dE" 'calc-eqn-language)
+  (define-key calc-mode-map "dF" 'calc-fortran-language)
+  (define-key calc-mode-map "dM" 'calc-mathematica-language)
+  (define-key calc-mode-map "dN" 'calc-normal-language)
+  (define-key calc-mode-map "dO" 'calc-flat-language)
+  (define-key calc-mode-map "dP" 'calc-pascal-language)
+  (define-key calc-mode-map "dT" 'calc-tex-language)
+  (define-key calc-mode-map "dU" 'calc-unformatted-language)
+  (define-key calc-mode-map "dW" 'calc-maple-language)
+  (define-key calc-mode-map "d[" 'calc-truncate-up)
+  (define-key calc-mode-map "d]" 'calc-truncate-down)
+  (define-key calc-mode-map "d." 'calc-point-char)
+  (define-key calc-mode-map "d," 'calc-group-char)
+  (define-key calc-mode-map "d\"" 'calc-display-strings)
+  (define-key calc-mode-map "d<" 'calc-left-justify)
+  (define-key calc-mode-map "d=" 'calc-center-justify)
+  (define-key calc-mode-map "d>" 'calc-right-justify)
+  (define-key calc-mode-map "d{" 'calc-left-label)
+  (define-key calc-mode-map "d}" 'calc-right-label)
+  (define-key calc-mode-map "d'" 'calc-display-raw)
+  (define-key calc-mode-map "d " 'calc-refresh)
+  (define-key calc-mode-map "d\r" 'calc-refresh-top)
+
+  (define-key calc-mode-map "f" nil)
+  (define-key calc-mode-map "f?" 'calc-f-prefix-help)
+  (define-key calc-mode-map "fb" 'calc-beta)
+  (define-key calc-mode-map "fe" 'calc-erf)
+  (define-key calc-mode-map "fg" 'calc-gamma)
+  (define-key calc-mode-map "fh" 'calc-hypot)
+  (define-key calc-mode-map "fi" 'calc-im)
+  (define-key calc-mode-map "fj" 'calc-bessel-J)
+  (define-key calc-mode-map "fn" 'calc-min)
+  (define-key calc-mode-map "fr" 'calc-re)
+  (define-key calc-mode-map "fs" 'calc-sign)
+  (define-key calc-mode-map "fx" 'calc-max)
+  (define-key calc-mode-map "fy" 'calc-bessel-Y)
+  (define-key calc-mode-map "fA" 'calc-abssqr)
+  (define-key calc-mode-map "fB" 'calc-inc-beta)
+  (define-key calc-mode-map "fE" 'calc-expm1)
+  (define-key calc-mode-map "fF" 'calc-floor)
+  (define-key calc-mode-map "fG" 'calc-inc-gamma)
+  (define-key calc-mode-map "fI" 'calc-ilog)
+  (define-key calc-mode-map "fL" 'calc-lnp1)
+  (define-key calc-mode-map "fM" 'calc-mant-part)
+  (define-key calc-mode-map "fQ" 'calc-isqrt)
+  (define-key calc-mode-map "fS" 'calc-scale-float)
+  (define-key calc-mode-map "fT" 'calc-arctan2)
+  (define-key calc-mode-map "fX" 'calc-xpon-part)
+  (define-key calc-mode-map "f[" 'calc-decrement)
+  (define-key calc-mode-map "f]" 'calc-increment)
+
+  (define-key calc-mode-map "g" nil)
+  (define-key calc-mode-map "g?" 'calc-g-prefix-help)
+  (define-key calc-mode-map "ga" 'calc-graph-add)
+  (define-key calc-mode-map "gb" 'calc-graph-border)
+  (define-key calc-mode-map "gc" 'calc-graph-clear)
+  (define-key calc-mode-map "gd" 'calc-graph-delete)
+  (define-key calc-mode-map "gf" 'calc-graph-fast)
+  (define-key calc-mode-map "gg" 'calc-graph-grid)
+  (define-key calc-mode-map "gh" 'calc-graph-header)
+  (define-key calc-mode-map "gk" 'calc-graph-key)
+  (define-key calc-mode-map "gj" 'calc-graph-juggle)
+  (define-key calc-mode-map "gl" 'calc-graph-log-x)
+  (define-key calc-mode-map "gn" 'calc-graph-name)
+  (define-key calc-mode-map "gp" 'calc-graph-plot)
+  (define-key calc-mode-map "gq" 'calc-graph-quit)
+  (define-key calc-mode-map "gr" 'calc-graph-range-x)
+  (define-key calc-mode-map "gs" 'calc-graph-line-style)
+  (define-key calc-mode-map "gt" 'calc-graph-title-x)
+  (define-key calc-mode-map "gv" 'calc-graph-view-commands)
+  (define-key calc-mode-map "gx" 'calc-graph-display)
+  (define-key calc-mode-map "gz" 'calc-graph-zero-x)
+  (define-key calc-mode-map "gA" 'calc-graph-add-3d)
+  (define-key calc-mode-map "gC" 'calc-graph-command)
+  (define-key calc-mode-map "gD" 'calc-graph-device)
+  (define-key calc-mode-map "gF" 'calc-graph-fast-3d)
+  (define-key calc-mode-map "gG" 'calc-argument)
+  (define-key calc-mode-map "gH" 'calc-graph-hide)
+  (define-key calc-mode-map "gK" 'calc-graph-kill)
+  (define-key calc-mode-map "gL" 'calc-graph-log-y)
+  (define-key calc-mode-map "gN" 'calc-graph-num-points)
+  (define-key calc-mode-map "gO" 'calc-graph-output)
+  (define-key calc-mode-map "gP" 'calc-graph-print)
+  (define-key calc-mode-map "gR" 'calc-graph-range-y)
+  (define-key calc-mode-map "gS" 'calc-graph-point-style)
+  (define-key calc-mode-map "gT" 'calc-graph-title-y)
+  (define-key calc-mode-map "gV" 'calc-graph-view-trail)
+  (define-key calc-mode-map "gX" 'calc-graph-geometry)
+  (define-key calc-mode-map "gZ" 'calc-graph-zero-y)
+  (define-key calc-mode-map "g\C-l" 'calc-graph-log-z)
+  (define-key calc-mode-map "g\C-r" 'calc-graph-range-z)
+  (define-key calc-mode-map "g\C-t" 'calc-graph-title-z)
+
+  (define-key calc-mode-map "h" 'calc-help-prefix)
+
+  (define-key calc-mode-map "j" nil)
+  (define-key calc-mode-map "j?" 'calc-j-prefix-help)
+  (define-key calc-mode-map "ja" 'calc-select-additional)
+  (define-key calc-mode-map "jb" 'calc-break-selections)
+  (define-key calc-mode-map "jc" 'calc-clear-selections)
+  (define-key calc-mode-map "jd" 'calc-show-selections)
+  (define-key calc-mode-map "je" 'calc-enable-selections)
+  (define-key calc-mode-map "jl" 'calc-select-less)
+  (define-key calc-mode-map "jm" 'calc-select-more)
+  (define-key calc-mode-map "jn" 'calc-select-next)
+  (define-key calc-mode-map "jo" 'calc-select-once)
+  (define-key calc-mode-map "jp" 'calc-select-previous)
+  (define-key calc-mode-map "jr" 'calc-rewrite-selection)
+  (define-key calc-mode-map "js" 'calc-select-here)
+  (define-key calc-mode-map "jv" 'calc-sel-evaluate)
+  (define-key calc-mode-map "ju" 'calc-unselect)
+  (define-key calc-mode-map "jC" 'calc-sel-commute)
+  (define-key calc-mode-map "jD" 'calc-sel-distribute)
+  (define-key calc-mode-map "jE" 'calc-sel-jump-equals)
+  (define-key calc-mode-map "jI" 'calc-sel-isolate)
+  (define-key calc-mode-map "jJ" 'calc-conj)
+  (define-key calc-mode-map "jL" 'calc-commute-left)
+  (define-key calc-mode-map "jM" 'calc-sel-merge)
+  (define-key calc-mode-map "jN" 'calc-sel-negate)
+  (define-key calc-mode-map "jO" 'calc-select-once-maybe)
+  (define-key calc-mode-map "jR" 'calc-commute-right)
+  (define-key calc-mode-map "jS" 'calc-select-here-maybe)
+  (define-key calc-mode-map "jU" 'calc-sel-unpack)
+  (define-key calc-mode-map "j&" 'calc-sel-invert)
+  (define-key calc-mode-map "j\r" 'calc-copy-selection)
+  (define-key calc-mode-map "j\n" 'calc-copy-selection)
+  (define-key calc-mode-map "j\010" 'calc-del-selection)
+  (define-key calc-mode-map "j\177" 'calc-del-selection)
+  (define-key calc-mode-map "j'" 'calc-enter-selection)
+  (define-key calc-mode-map "j`" 'calc-edit-selection)
+  (define-key calc-mode-map "j+" 'calc-sel-add-both-sides)
+  (define-key calc-mode-map "j-" 'calc-sel-sub-both-sides)
+  (define-key calc-mode-map "j*" 'calc-sel-mult-both-sides)
+  (define-key calc-mode-map "j/" 'calc-sel-div-both-sides)
+  (define-key calc-mode-map "j\"" 'calc-sel-expand-formula)
+
+  (define-key calc-mode-map "k" nil)
+  (define-key calc-mode-map "k?" 'calc-k-prefix-help)
+  (define-key calc-mode-map "ka" 'calc-random-again)
+  (define-key calc-mode-map "kb" 'calc-bernoulli-number)
+  (define-key calc-mode-map "kc" 'calc-choose)
+  (define-key calc-mode-map "kd" 'calc-double-factorial)
+  (define-key calc-mode-map "ke" 'calc-euler-number)
+  (define-key calc-mode-map "kf" 'calc-prime-factors)
+  (define-key calc-mode-map "kg" 'calc-gcd)
+  (define-key calc-mode-map "kh" 'calc-shuffle)
+  (define-key calc-mode-map "kl" 'calc-lcm)
+  (define-key calc-mode-map "km" 'calc-moebius)
+  (define-key calc-mode-map "kn" 'calc-next-prime)
+  (define-key calc-mode-map "kp" 'calc-prime-test)
+  (define-key calc-mode-map "kr" 'calc-random)
+  (define-key calc-mode-map "ks" 'calc-stirling-number)
+  (define-key calc-mode-map "kt" 'calc-totient)
+  (define-key calc-mode-map "kB" 'calc-utpb)
+  (define-key calc-mode-map "kC" 'calc-utpc)
+  (define-key calc-mode-map "kE" 'calc-extended-gcd)
+  (define-key calc-mode-map "kF" 'calc-utpf)
+  (define-key calc-mode-map "kK" 'calc-keep-args)
+  (define-key calc-mode-map "kN" 'calc-utpn)
+  (define-key calc-mode-map "kP" 'calc-utpp)
+  (define-key calc-mode-map "kT" 'calc-utpt)
+
+  (define-key calc-mode-map "m" nil)
+  (define-key calc-mode-map "m?" 'calc-m-prefix-help)
+  (define-key calc-mode-map "ma" 'calc-algebraic-mode)
+  (define-key calc-mode-map "md" 'calc-degrees-mode)
+  (define-key calc-mode-map "mf" 'calc-frac-mode)
+  (define-key calc-mode-map "mg" 'calc-get-modes)
+  (define-key calc-mode-map "mh" 'calc-hms-mode)
+  (define-key calc-mode-map "mi" 'calc-infinite-mode)
+  (define-key calc-mode-map "mm" 'calc-save-modes)
+  (define-key calc-mode-map "mp" 'calc-polar-mode)
+  (define-key calc-mode-map "mr" 'calc-radians-mode)
+  (define-key calc-mode-map "ms" 'calc-symbolic-mode)
+  (define-key calc-mode-map "mt" 'calc-total-algebraic-mode)
+  (define-key calc-mode-map "\emt" 'calc-total-algebraic-mode)
+  (define-key calc-mode-map "\em\et" 'calc-total-algebraic-mode)
+  (define-key calc-mode-map "mv" 'calc-matrix-mode)
+  (define-key calc-mode-map "mw" 'calc-working)
+  (define-key calc-mode-map "mx" 'calc-always-load-extensions)
+  (define-key calc-mode-map "mA" 'calc-alg-simplify-mode)
+  (define-key calc-mode-map "mB" 'calc-bin-simplify-mode)
+  (define-key calc-mode-map "mC" 'calc-auto-recompute)
+  (define-key calc-mode-map "mD" 'calc-default-simplify-mode)
+  (define-key calc-mode-map "mE" 'calc-ext-simplify-mode)
+  (define-key calc-mode-map "mF" 'calc-settings-file-name)
+  (define-key calc-mode-map "mM" 'calc-more-recursion-depth)
+  (define-key calc-mode-map "mN" 'calc-num-simplify-mode)
+  (define-key calc-mode-map "mO" 'calc-no-simplify-mode)
+  (define-key calc-mode-map "mR" 'calc-mode-record-mode)
+  (define-key calc-mode-map "mS" 'calc-shift-prefix)
+  (define-key calc-mode-map "mU" 'calc-units-simplify-mode)
+  (define-key calc-mode-map "mX" 'calc-load-everything)
+
+  (define-key calc-mode-map "r" nil)
+  (define-key calc-mode-map "r?" 'calc-r-prefix-help)
+
+  (define-key calc-mode-map "s" nil)
+  (define-key calc-mode-map "s?" 'calc-s-prefix-help)
+  (define-key calc-mode-map "sc" 'calc-copy-variable)
+  (define-key calc-mode-map "sd" 'calc-declare-variable)
+  (define-key calc-mode-map "se" 'calc-edit-variable)
+  (define-key calc-mode-map "si" 'calc-insert-variables)
+  (define-key calc-mode-map "sl" 'calc-let)
+  (define-key calc-mode-map "sm" 'calc-store-map)
+  (define-key calc-mode-map "sn" 'calc-store-neg)
+  (define-key calc-mode-map "sp" 'calc-permanent-variable)
+  (define-key calc-mode-map "sr" 'calc-recall)
+  (define-key calc-mode-map "ss" 'calc-store)
+  (define-key calc-mode-map "st" 'calc-store-into)
+  (define-key calc-mode-map "su" 'calc-unstore)
+  (define-key calc-mode-map "sx" 'calc-store-exchange)
+  (define-key calc-mode-map "sA" 'calc-edit-AlgSimpRules)
+  (define-key calc-mode-map "sD" 'calc-edit-Decls)
+  (define-key calc-mode-map "sE" 'calc-edit-EvalRules)
+  (define-key calc-mode-map "sF" 'calc-edit-FitRules)
+  (define-key calc-mode-map "sG" 'calc-edit-GenCount)
+  (define-key calc-mode-map "sH" 'calc-edit-Holidays)
+  (define-key calc-mode-map "sI" 'calc-edit-IntegLimit)
+  (define-key calc-mode-map "sL" 'calc-edit-LineStyles)
+  (define-key calc-mode-map "sP" 'calc-edit-PointStyles)
+  (define-key calc-mode-map "sR" 'calc-edit-PlotRejects)
+  (define-key calc-mode-map "sS" 'calc-sin)
+  (define-key calc-mode-map "sT" 'calc-edit-TimeZone)
+  (define-key calc-mode-map "sU" 'calc-edit-Units)
+  (define-key calc-mode-map "sX" 'calc-edit-ExtSimpRules)
+  (define-key calc-mode-map "s+" 'calc-store-plus)
+  (define-key calc-mode-map "s-" 'calc-store-minus)
+  (define-key calc-mode-map "s*" 'calc-store-times)
+  (define-key calc-mode-map "s/" 'calc-store-div)
+  (define-key calc-mode-map "s^" 'calc-store-power)
+  (define-key calc-mode-map "s|" 'calc-store-concat)
+  (define-key calc-mode-map "s&" 'calc-store-inv)
+  (define-key calc-mode-map "s[" 'calc-store-decr)
+  (define-key calc-mode-map "s]" 'calc-store-incr)
+  (define-key calc-mode-map "s:" 'calc-assign)
+  (define-key calc-mode-map "s=" 'calc-evalto)
+
+  (define-key calc-mode-map "t" nil)
+  (define-key calc-mode-map "t?" 'calc-t-prefix-help)
+  (define-key calc-mode-map "tb" 'calc-trail-backward)
+  (define-key calc-mode-map "td" 'calc-trail-display)
+  (define-key calc-mode-map "tf" 'calc-trail-forward)
+  (define-key calc-mode-map "th" 'calc-trail-here)
+  (define-key calc-mode-map "ti" 'calc-trail-in)
+  (define-key calc-mode-map "tk" 'calc-trail-kill)
+  (define-key calc-mode-map "tm" 'calc-trail-marker)
+  (define-key calc-mode-map "tn" 'calc-trail-next)
+  (define-key calc-mode-map "to" 'calc-trail-out)
+  (define-key calc-mode-map "tp" 'calc-trail-previous)
+  (define-key calc-mode-map "tr" 'calc-trail-isearch-backward)
+  (define-key calc-mode-map "ts" 'calc-trail-isearch-forward)
+  (define-key calc-mode-map "ty" 'calc-trail-yank)
+  (define-key calc-mode-map "t[" 'calc-trail-first)
+  (define-key calc-mode-map "t]" 'calc-trail-last)
+  (define-key calc-mode-map "t<" 'calc-trail-scroll-left)
+  (define-key calc-mode-map "t>" 'calc-trail-scroll-right)
+  (define-key calc-mode-map "t{" 'calc-trail-backward)
+  (define-key calc-mode-map "t}" 'calc-trail-forward)
+  (define-key calc-mode-map "t." 'calc-full-trail-vectors)
+  (define-key calc-mode-map "tC" 'calc-convert-time-zones)
+  (define-key calc-mode-map "tD" 'calc-date)
+  (define-key calc-mode-map "tI" 'calc-inc-month)
+  (define-key calc-mode-map "tJ" 'calc-julian)
+  (define-key calc-mode-map "tM" 'calc-new-month)
+  (define-key calc-mode-map "tN" 'calc-now)
+  (define-key calc-mode-map "tP" 'calc-date-part)
+  (define-key calc-mode-map "tT" 'calc-tan)
+  (define-key calc-mode-map "tU" 'calc-unix-time)
+  (define-key calc-mode-map "tW" 'calc-new-week)
+  (define-key calc-mode-map "tY" 'calc-new-year)
+  (define-key calc-mode-map "tZ" 'calc-time-zone)
+  (define-key calc-mode-map "t+" 'calc-business-days-plus)
+  (define-key calc-mode-map "t-" 'calc-business-days-minus)
+
+  (define-key calc-mode-map "u" 'nil)
+  (define-key calc-mode-map "u?" 'calc-u-prefix-help)
+  (define-key calc-mode-map "ua" 'calc-autorange-units)
+  (define-key calc-mode-map "ub" 'calc-base-units)
+  (define-key calc-mode-map "uc" 'calc-convert-units)
+  (define-key calc-mode-map "ud" 'calc-define-unit)
+  (define-key calc-mode-map "ue" 'calc-explain-units)
+  (define-key calc-mode-map "ug" 'calc-get-unit-definition)
+  (define-key calc-mode-map "up" 'calc-permanent-units)
+  (define-key calc-mode-map "ur" 'calc-remove-units)
+  (define-key calc-mode-map "us" 'calc-simplify-units)
+  (define-key calc-mode-map "ut" 'calc-convert-temperature)
+  (define-key calc-mode-map "uu" 'calc-undefine-unit)
+  (define-key calc-mode-map "uv" 'calc-enter-units-table)
+  (define-key calc-mode-map "ux" 'calc-extract-units)
+  (define-key calc-mode-map "uV" 'calc-view-units-table)
+  (define-key calc-mode-map "uC" 'calc-vector-covariance)
+  (define-key calc-mode-map "uG" 'calc-vector-geometric-mean)
+  (define-key calc-mode-map "uM" 'calc-vector-mean)
+  (define-key calc-mode-map "uN" 'calc-vector-min)
+  (define-key calc-mode-map "uS" 'calc-vector-sdev)
+  (define-key calc-mode-map "uU" 'calc-undo)
+  (define-key calc-mode-map "uX" 'calc-vector-max)
+  (define-key calc-mode-map "u#" 'calc-vector-count)
+  (define-key calc-mode-map "u+" 'calc-vector-sum)
+  (define-key calc-mode-map "u*" 'calc-vector-product)
+
+  (define-key calc-mode-map "v" 'nil)
+  (define-key calc-mode-map "v?" 'calc-v-prefix-help)
+  (define-key calc-mode-map "va" 'calc-arrange-vector)
+  (define-key calc-mode-map "vb" 'calc-build-vector)
+  (define-key calc-mode-map "vc" 'calc-mcol)
+  (define-key calc-mode-map "vd" 'calc-diag)
+  (define-key calc-mode-map "ve" 'calc-expand-vector)
+  (define-key calc-mode-map "vf" 'calc-vector-find)
+  (define-key calc-mode-map "vh" 'calc-head)
+  (define-key calc-mode-map "vi" 'calc-ident)
+  (define-key calc-mode-map "vk" 'calc-cons)
+  (define-key calc-mode-map "vl" 'calc-vlength)
+  (define-key calc-mode-map "vm" 'calc-mask-vector)
+  (define-key calc-mode-map "vn" 'calc-rnorm)
+  (define-key calc-mode-map "vp" 'calc-pack)
+  (define-key calc-mode-map "vr" 'calc-mrow)
+  (define-key calc-mode-map "vs" 'calc-subvector)
+  (define-key calc-mode-map "vt" 'calc-transpose)
+  (define-key calc-mode-map "vu" 'calc-unpack)
+  (define-key calc-mode-map "vv" 'calc-reverse-vector)
+  (define-key calc-mode-map "vx" 'calc-index)
+  (define-key calc-mode-map "vA" 'calc-apply)
+  (define-key calc-mode-map "vC" 'calc-cross)
+  (define-key calc-mode-map "vD" 'calc-mdet)
+  (define-key calc-mode-map "vE" 'calc-set-enumerate)
+  (define-key calc-mode-map "vF" 'calc-set-floor)
+  (define-key calc-mode-map "vG" 'calc-grade)
+  (define-key calc-mode-map "vH" 'calc-histogram)
+  (define-key calc-mode-map "vI" 'calc-inner-product)
+  (define-key calc-mode-map "vJ" 'calc-conj-transpose)
+  (define-key calc-mode-map "vL" 'calc-mlud)
+  (define-key calc-mode-map "vM" 'calc-map)
+  (define-key calc-mode-map "vN" 'calc-cnorm)
+  (define-key calc-mode-map "vO" 'calc-outer-product)
+  (define-key calc-mode-map "vR" 'calc-reduce)
+  (define-key calc-mode-map "vS" 'calc-sort)
+  (define-key calc-mode-map "vT" 'calc-mtrace)
+  (define-key calc-mode-map "vU" 'calc-accumulate)
+  (define-key calc-mode-map "vV" 'calc-set-union)
+  (define-key calc-mode-map "vX" 'calc-set-xor)
+  (define-key calc-mode-map "v^" 'calc-set-intersect)
+  (define-key calc-mode-map "v-" 'calc-set-difference)
+  (define-key calc-mode-map "v~" 'calc-set-complement)
+  (define-key calc-mode-map "v:" 'calc-set-span)
+  (define-key calc-mode-map "v#" 'calc-set-cardinality)
+  (define-key calc-mode-map "v+" 'calc-remove-duplicates)
+  (define-key calc-mode-map "v&" 'calc-inv)
+  (define-key calc-mode-map "v<" 'calc-matrix-left-justify)
+  (define-key calc-mode-map "v=" 'calc-matrix-center-justify)
+  (define-key calc-mode-map "v>" 'calc-matrix-right-justify)
+  (define-key calc-mode-map "v." 'calc-full-vectors)
+  (define-key calc-mode-map "v/" 'calc-break-vectors)
+  (define-key calc-mode-map "v," 'calc-vector-commas)
+  (define-key calc-mode-map "v[" 'calc-vector-brackets)
+  (define-key calc-mode-map "v]" 'calc-matrix-brackets)
+  (define-key calc-mode-map "v{" 'calc-vector-braces)
+  (define-key calc-mode-map "v}" 'calc-matrix-brackets)
+  (define-key calc-mode-map "v(" 'calc-vector-parens)
+  (define-key calc-mode-map "v)" 'calc-matrix-brackets)
+  (define-key calc-mode-map "V" (lookup-key calc-mode-map "v"))
+
+  (define-key calc-mode-map "z" 'nil)
+  (define-key calc-mode-map "z?" 'calc-z-prefix-help)
+
+  (define-key calc-mode-map "Z" 'nil)
+  (define-key calc-mode-map "Z?" 'calc-shift-Z-prefix-help)
+  (define-key calc-mode-map "ZC" 'calc-user-define-composition)
+  (define-key calc-mode-map "ZD" 'calc-user-define)
+  (define-key calc-mode-map "ZE" 'calc-user-define-edit)
+  (define-key calc-mode-map "ZF" 'calc-user-define-formula)
+  (define-key calc-mode-map "ZG" 'calc-get-user-defn)
+  (define-key calc-mode-map "ZI" 'calc-user-define-invocation)
+  (define-key calc-mode-map "ZK" 'calc-user-define-kbd-macro)
+  (define-key calc-mode-map "ZP" 'calc-user-define-permanent)
+  (define-key calc-mode-map "ZS" 'calc-edit-user-syntax)
+  (define-key calc-mode-map "ZT" 'calc-timing)
+  (define-key calc-mode-map "ZU" 'calc-user-undefine)
+  (define-key calc-mode-map "Z[" 'calc-kbd-if)
+  (define-key calc-mode-map "Z:" 'calc-kbd-else)
+  (define-key calc-mode-map "Z|" 'calc-kbd-else-if)
+  (define-key calc-mode-map "Z]" 'calc-kbd-end-if)
+  (define-key calc-mode-map "Z<" 'calc-kbd-repeat)
+  (define-key calc-mode-map "Z>" 'calc-kbd-end-repeat)
+  (define-key calc-mode-map "Z(" 'calc-kbd-for)
+  (define-key calc-mode-map "Z)" 'calc-kbd-end-for)
+  (define-key calc-mode-map "Z{" 'calc-kbd-loop)
+  (define-key calc-mode-map "Z}" 'calc-kbd-end-loop)
+  (define-key calc-mode-map "Z/" 'calc-kbd-break)
+  (define-key calc-mode-map "Z`" 'calc-kbd-push)
+  (define-key calc-mode-map "Z'" 'calc-kbd-pop)
+  (define-key calc-mode-map "Z=" 'calc-kbd-report)
+  (define-key calc-mode-map "Z#" 'calc-kbd-query)
+
+  (calc-init-prefixes)
+
+  (mapcar (function
+	   (lambda (x)
+	     (define-key calc-mode-map (format "c%c" x) 'calc-clean-num)
+	     (define-key calc-mode-map (format "j%c" x) 'calc-select-part)
+	     (define-key calc-mode-map (format "r%c" x) 'calc-recall-quick)
+	     (define-key calc-mode-map (format "s%c" x) 'calc-store-quick)
+	     (define-key calc-mode-map (format "t%c" x) 'calc-store-into-quick)
+	     (define-key calc-mode-map (format "u%c" x) 'calc-quick-units)))
+	  "0123456789")
+
+ (or calc-emacs-type-19 (progn
+  (let ((i ?A))
+    (while (and (<= i ?z) (vectorp calc-mode-map))
+      (if (eq (car-safe (aref calc-mode-map i)) 'keymap)
+	  (aset calc-mode-map i
+		(cons 'keymap (cons (cons ?\e (aref calc-mode-map i))
+				    (cdr (aref calc-mode-map i))))))
+      (setq i (1+ i))))
+
+  (setq calc-alg-map (copy-sequence calc-mode-map)
+	calc-alg-esc-map (copy-sequence esc-map))
+  (let ((i 32))
+    (while (< i 127)
+      (or (memq i '(?' ?` ?= ??))
+	  (aset calc-alg-map i 'calc-auto-algebraic-entry))
+      (or (memq i '(?# ?x ?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9))
+	  (aset calc-alg-esc-map i (aref calc-mode-map i)))
+      (setq i (1+ i))))
+  (define-key calc-alg-map "\e" calc-alg-esc-map)
+  (define-key calc-alg-map "\e\t" 'calc-roll-up)
+  (define-key calc-alg-map "\e\C-m" 'calc-last-args-stub)
+  (define-key calc-alg-map "\e\177" 'calc-pop-above)
+ ))
+ 
+  ;; The following is a relic for backward compatability only.
+  ;; The calc-define property list is now the recommended method.
+  (if (and (boundp 'calc-ext-defs)
+	   calc-ext-defs)
+      (progn
+	(calc-need-macros)
+	(message "Evaluating calc-ext-defs...")
+	(eval (cons 'progn calc-ext-defs))
+	(setq calc-ext-defs nil)))
+
+;;;; (Autoloads here)
+  (mapcar (function (lambda (x)
+    (mapcar (function (lambda (func)
+      (autoload func (car x)))) (cdr x))))
+    '(
+
+ ("calc-alg" calc-Need-calc-alg calc-has-rules
+calc-modify-simplify-mode calcFunc-collect calcFunc-esimplify
+calcFunc-islin calcFunc-islinnt calcFunc-lin calcFunc-linnt
+calcFunc-simplify calcFunc-subst math-beforep
+math-build-polynomial-expr math-expand-formula math-expr-contains
+math-expr-contains-count math-expr-depends math-expr-height
+math-expr-subst math-expr-weight math-integer-plus math-is-linear
+math-is-multiple math-is-polynomial math-linear-in math-multiple-of
+math-need-std-simps math-poly-depends math-poly-mix math-poly-mul
+math-poly-simplify math-poly-zerop math-polynomial-base
+math-polynomial-p math-recompile-eval-rules math-simplify
+math-simplify-exp math-simplify-extended math-simplify-sqrt
+math-to-simple-fraction)
+
+ ("calc-alg-2" calc-Need-calc-alg-2 calcFunc-asum calcFunc-deriv
+calcFunc-ffinv calcFunc-finv calcFunc-fsolve calcFunc-gpoly
+calcFunc-integ calcFunc-poly calcFunc-prod calcFunc-roots
+calcFunc-solve calcFunc-sum calcFunc-table calcFunc-taylor
+calcFunc-tderiv math-expr-calls math-integral-q02 math-integral-q12
+math-integral-rational-funcs math-lcm-denoms math-looks-evenp
+math-poly-all-roots math-prod-rec math-reject-solution math-solve-eqn
+math-solve-for math-sum-rec math-try-integral)
+
+ ("calc-alg-3" calc-Need-calc-alg-3 calcFunc-efit calcFunc-fit
+calcFunc-fitdummy calcFunc-fitparam calcFunc-fitvar
+calcFunc-hasfitparams calcFunc-hasfitvars calcFunc-maximize
+calcFunc-minimize calcFunc-ninteg calcFunc-polint calcFunc-ratint
+calcFunc-root calcFunc-wmaximize calcFunc-wminimize calcFunc-wroot
+calcFunc-xfit math-find-minimum math-find-root math-ninteg-evaluate
+math-ninteg-midpoint math-ninteg-romberg math-poly-interp)
+
+ ("calc-arith" calc-Need-calc-arith calcFunc-abs calcFunc-abssqr
+calcFunc-add calcFunc-ceil calcFunc-decr calcFunc-deven calcFunc-dimag
+calcFunc-dint calcFunc-div calcFunc-dnatnum calcFunc-dneg
+calcFunc-dnonneg calcFunc-dnonzero calcFunc-dnumint calcFunc-dodd
+calcFunc-dpos calcFunc-drange calcFunc-drat calcFunc-dreal
+calcFunc-dscalar calcFunc-fceil calcFunc-ffloor calcFunc-float
+calcFunc-fround calcFunc-frounde calcFunc-froundu calcFunc-ftrunc
+calcFunc-idiv calcFunc-incr calcFunc-mant calcFunc-max calcFunc-min
+calcFunc-mod calcFunc-mul calcFunc-neg calcFunc-percent calcFunc-pow
+calcFunc-relch calcFunc-round calcFunc-rounde calcFunc-roundu
+calcFunc-scf calcFunc-sub calcFunc-xpon math-abs math-abs-approx
+math-add-objects-fancy math-add-or-sub math-add-symb-fancy
+math-ceiling math-combine-prod math-combine-sum math-div-by-zero
+math-div-objects-fancy math-div-symb-fancy math-div-zero
+math-float-fancy math-floor-fancy math-floor-special math-guess-if-neg
+math-intv-constp math-known-evenp math-known-imagp math-known-integerp
+math-known-matrixp math-known-negp math-known-nonnegp
+math-known-nonposp math-known-nonzerop math-known-num-integerp
+math-known-oddp math-known-posp math-known-realp math-known-scalarp
+math-max math-min math-mod-fancy math-mul-float math-mul-objects-fancy
+math-mul-or-div math-mul-symb-fancy math-mul-zero math-neg-fancy
+math-neg-float math-okay-neg math-possible-signs math-possible-types
+math-pow-fancy math-pow-mod math-pow-of-zero math-pow-zero
+math-quarter-integer math-round math-setup-declarations math-sqr
+math-sqr-float math-trunc-fancy math-trunc-special)
+
+ ("calc-bin" calc-Need-calc-bin calcFunc-and calcFunc-ash
+calcFunc-clip calcFunc-diff calcFunc-lsh calcFunc-not calcFunc-or
+calcFunc-rash calcFunc-rot calcFunc-rsh calcFunc-xor math-clip
+math-compute-max-digits math-convert-radix-digits math-float-parts
+math-format-bignum-binary math-format-bignum-hex
+math-format-bignum-octal math-format-bignum-radix math-format-binary
+math-format-radix math-format-radix-float math-integer-log2
+math-power-of-2 math-radix-float-power)
+
+ ("calc-comb" calc-Need-calc-comb calc-report-prime-test
+calcFunc-choose calcFunc-dfact calcFunc-egcd calcFunc-fact
+calcFunc-gcd calcFunc-lcm calcFunc-moebius calcFunc-nextprime
+calcFunc-perm calcFunc-prevprime calcFunc-prfac calcFunc-prime
+calcFunc-random calcFunc-shuffle calcFunc-stir1 calcFunc-stir2
+calcFunc-totient math-init-random-base math-member math-prime-test
+math-random-base)
+
+ ("calc-comp" calc-Need-calc-comp calcFunc-cascent calcFunc-cdescent
+calcFunc-cheight calcFunc-cwidth math-comp-ascent math-comp-descent
+math-comp-height math-comp-width math-compose-expr
+math-composition-to-string math-stack-value-offset-fancy
+math-vector-is-string math-vector-to-string)
+
+ ("calc-cplx" calc-Need-calc-cplx calcFunc-arg calcFunc-conj
+calcFunc-im calcFunc-polar calcFunc-re calcFunc-rect math-complex
+math-fix-circular math-imaginary math-imaginary-i math-normalize-polar
+math-polar math-want-polar)
+
+ ("calc-embed" calc-Need-calc-embed calc-do-embedded
+calc-do-embedded-activate calc-embedded-evaluate-expr
+calc-embedded-modes-change calc-embedded-var-change)
+
+ ("calc-fin" calc-Need-calc-fin calc-to-percentage calcFunc-ddb
+calcFunc-fv calcFunc-fvb calcFunc-fvl calcFunc-irr calcFunc-irrb
+calcFunc-nper calcFunc-nperb calcFunc-nperl calcFunc-npv calcFunc-npvb
+calcFunc-pmt calcFunc-pmtb calcFunc-pv calcFunc-pvb calcFunc-pvl
+calcFunc-rate calcFunc-rateb calcFunc-ratel calcFunc-sln calcFunc-syd)
+
+ ("calc-forms" calc-Need-calc-forms calcFunc-badd calcFunc-bsub
+calcFunc-date calcFunc-day calcFunc-dsadj calcFunc-hms
+calcFunc-holiday calcFunc-hour calcFunc-incmonth calcFunc-incyear
+calcFunc-intv calcFunc-julian calcFunc-makemod calcFunc-minute
+calcFunc-month calcFunc-newmonth calcFunc-newweek calcFunc-newyear
+calcFunc-now calcFunc-pwday calcFunc-sdev calcFunc-second
+calcFunc-time calcFunc-tzconv calcFunc-tzone calcFunc-unixtime
+calcFunc-weekday calcFunc-year calcFunc-yearday math-combine-intervals
+math-date-parts math-date-to-dt math-div-mod math-dt-to-date
+math-format-date math-from-business-day math-from-hms math-make-intv
+math-make-mod math-make-sdev math-mod-intv math-normalize-hms
+math-normalize-mod math-parse-date math-read-angle-brackets
+math-setup-add-holidays math-setup-holidays math-setup-year-holidays
+math-sort-intv math-to-business-day math-to-hms)
+
+ ("calc-frac" calc-Need-calc-frac calc-add-fractions
+calc-div-fractions calc-mul-fractions calcFunc-fdiv calcFunc-frac
+math-make-frac)
+
+ ("calc-funcs" calc-Need-calc-funcs calc-prob-dist calcFunc-bern
+calcFunc-besJ calcFunc-besY calcFunc-beta calcFunc-betaB
+calcFunc-betaI calcFunc-erf calcFunc-erfc calcFunc-euler
+calcFunc-gamma calcFunc-gammaG calcFunc-gammaP calcFunc-gammaQ
+calcFunc-gammag calcFunc-ltpb calcFunc-ltpc calcFunc-ltpf
+calcFunc-ltpn calcFunc-ltpp calcFunc-ltpt calcFunc-utpb calcFunc-utpc
+calcFunc-utpf calcFunc-utpn calcFunc-utpp calcFunc-utpt
+math-bernoulli-number math-gammap1-raw)
+
+ ("calc-graph" calc-Need-calc-graph calc-graph-show-tty)
+
+ ("calc-help" calc-Need-calc-help)
+
+ ("calc-incom" calc-Need-calc-incom calc-digit-dots)
+
+ ("calc-keypd" calc-Need-calc-keypd calc-do-keypad
+calc-keypad-x-left-click calc-keypad-x-middle-click
+calc-keypad-x-right-click)
+
+ ("calc-lang" calc-Need-calc-lang calc-set-language
+math-read-big-balance math-read-big-rec)
+
+ ("calc-map" calc-Need-calc-map calc-get-operator calcFunc-accum
+calcFunc-afixp calcFunc-anest calcFunc-apply calcFunc-call
+calcFunc-fixp calcFunc-inner calcFunc-map calcFunc-mapa calcFunc-mapc
+calcFunc-mapd calcFunc-mapeq calcFunc-mapeqp calcFunc-mapeqr
+calcFunc-mapr calcFunc-nest calcFunc-outer calcFunc-raccum
+calcFunc-reduce calcFunc-reducea calcFunc-reducec calcFunc-reduced
+calcFunc-reducer calcFunc-rreduce calcFunc-rreducea calcFunc-rreducec
+calcFunc-rreduced calcFunc-rreducer math-build-call
+math-calcFunc-to-var math-multi-subst math-multi-subst-rec
+math-var-to-calcFunc)
+
+ ("calc-mat" calc-Need-calc-mat calcFunc-det calcFunc-lud calcFunc-tr
+math-col-matrix math-lud-solve math-matrix-inv-raw math-matrix-lud
+math-mul-mat-vec math-mul-mats math-row-matrix)
+
+ ("calc-math" calc-Need-calc-math calcFunc-alog calcFunc-arccos
+calcFunc-arccosh calcFunc-arcsin calcFunc-arcsincos calcFunc-arcsinh
+calcFunc-arctan calcFunc-arctan2 calcFunc-arctanh calcFunc-cos
+calcFunc-cosh calcFunc-deg calcFunc-exp calcFunc-exp10 calcFunc-expm1
+calcFunc-hypot calcFunc-ilog calcFunc-isqrt calcFunc-ln calcFunc-lnp1
+calcFunc-log calcFunc-log10 calcFunc-nroot calcFunc-rad calcFunc-sin
+calcFunc-sincos calcFunc-sinh calcFunc-sqr calcFunc-sqrt calcFunc-tan
+calcFunc-tanh math-arccos-raw math-arcsin-raw math-arctan-raw
+math-arctan2-raw math-cos-raw math-exp-minus-1-raw math-exp-raw
+math-from-radians math-from-radians-2 math-hypot math-infinite-dir
+math-isqrt-small math-ln-raw math-nearly-equal math-nearly-equal-float
+math-nearly-zerop math-nearly-zerop-float math-nth-root
+math-sin-cos-raw math-sin-raw math-sqrt math-sqrt-float math-sqrt-raw
+math-tan-raw math-to-radians math-to-radians-2)
+
+ ("calc-mode" calc-Need-calc-mode math-get-modes-vec)
+
+ ("calc-poly" calc-Need-calc-poly calcFunc-apart calcFunc-expand
+calcFunc-expandpow calcFunc-factor calcFunc-factors calcFunc-nrat
+calcFunc-pcont calcFunc-pdeg calcFunc-pdiv calcFunc-pdivide
+calcFunc-pdivrem calcFunc-pgcd calcFunc-plead calcFunc-pprim
+calcFunc-prem math-accum-factors math-atomic-factorp
+math-div-poly-const math-div-thru math-expand-power math-expand-term
+math-factor-contains math-factor-expr math-factor-expr-part
+math-factor-expr-try math-factor-finish math-factor-poly-coefs
+math-factor-protect math-mul-thru math-padded-polynomial
+math-partial-fractions math-poly-degree math-poly-deriv-coefs
+math-poly-gcd-frac-list math-poly-modulus-rec math-ratpoly-p
+math-to-ratpoly math-to-ratpoly-rec)
+
+ ("calc-prog" calc-Need-calc-prog calc-default-formula-arglist
+calc-execute-kbd-macro calc-finish-user-syntax-edit
+calc-fix-token-name calc-fix-user-formula calc-read-parse-table
+calc-read-parse-table-part calc-subsetp calc-write-parse-table
+calc-write-parse-table-part calcFunc-constant calcFunc-eq calcFunc-geq
+calcFunc-gt calcFunc-if calcFunc-in calcFunc-integer calcFunc-istrue
+calcFunc-land calcFunc-leq calcFunc-lnot calcFunc-lor calcFunc-lt
+calcFunc-negative calcFunc-neq calcFunc-nonvar calcFunc-real
+calcFunc-refers calcFunc-rmeq calcFunc-typeof calcFunc-variable
+math-body-refers-to math-break math-composite-inequalities
+math-do-defmath math-handle-for math-handle-foreach
+math-normalize-logical-op math-return)
+
+ ("calc-rewr" calc-Need-calc-rewr calcFunc-match calcFunc-matches
+calcFunc-matchnot calcFunc-rewrite calcFunc-vmatches
+math-apply-rewrites math-compile-patterns math-compile-rewrites
+math-flatten-lands math-match-patterns math-rewrite
+math-rewrite-heads)
+
+ ("calc-rules" calc-CommuteRules calc-DistribRules calc-FactorRules
+calc-FitRules calc-IntegAfterRules calc-InvertRules calc-JumpRules
+calc-MergeRules calc-Need-calc-rules calc-NegateRules
+calc-compile-rule-set)
+
+ ("calc-sel" calc-Need-calc-sel calc-auto-selection
+calc-delete-selection calc-encase-atoms calc-find-assoc-parent-formula
+calc-find-parent-formula calc-find-sub-formula calc-prepare-selection
+calc-preserve-point calc-replace-selections calc-replace-sub-formula
+calc-roll-down-with-selections calc-roll-up-with-selections
+calc-sel-error)
+
+ ("calc-sel-2" calc-Need-calc-sel-2)
+
+ ("calc-stat" calc-Need-calc-stat calc-vector-op calcFunc-agmean
+calcFunc-vcorr calcFunc-vcount calcFunc-vcov calcFunc-vflat
+calcFunc-vgmean calcFunc-vhmean calcFunc-vmax calcFunc-vmean
+calcFunc-vmeane calcFunc-vmedian calcFunc-vmin calcFunc-vpcov
+calcFunc-vprod calcFunc-vpsdev calcFunc-vpvar calcFunc-vsdev
+calcFunc-vsum calcFunc-vvar math-flatten-many-vecs)
+
+ ("calc-store" calc-Need-calc-store calc-read-var-name
+calc-store-value calc-var-name)
+
+ ("calc-stuff" calc-Need-calc-stuff calc-explain-why calcFunc-clean
+calcFunc-pclean calcFunc-pfloat calcFunc-pfrac)
+
+ ("calc-trail" calc-Need-calc-trail)
+
+ ("calc-undo" calc-Need-calc-undo)
+
+ ("calc-units" calc-Need-calc-units calcFunc-usimplify
+math-build-units-table math-build-units-table-buffer
+math-check-unit-name math-convert-temperature math-convert-units
+math-extract-units math-remove-units math-simplify-units
+math-single-units-in-expr-p math-to-standard-units
+math-units-in-expr-p)
+
+ ("calc-vec" calc-Need-calc-vec calcFunc-append calcFunc-appendrev
+calcFunc-arrange calcFunc-cnorm calcFunc-cons calcFunc-cross
+calcFunc-ctrn calcFunc-cvec calcFunc-diag calcFunc-find
+calcFunc-getdiag calcFunc-grade calcFunc-head calcFunc-histogram
+calcFunc-idn calcFunc-index calcFunc-mcol calcFunc-mdims
+calcFunc-mrcol calcFunc-mrow calcFunc-mrrow calcFunc-pack
+calcFunc-rcons calcFunc-rdup calcFunc-rev calcFunc-rgrade
+calcFunc-rhead calcFunc-rnorm calcFunc-rsort calcFunc-rsubvec
+calcFunc-rtail calcFunc-sort calcFunc-subscr calcFunc-subvec
+calcFunc-tail calcFunc-trn calcFunc-unpack calcFunc-unpackt
+calcFunc-vcard calcFunc-vcompl calcFunc-vconcat calcFunc-vconcatrev
+calcFunc-vdiff calcFunc-vec calcFunc-venum calcFunc-vexp
+calcFunc-vfloor calcFunc-vint calcFunc-vlen calcFunc-vmask
+calcFunc-vpack calcFunc-vspan calcFunc-vunion calcFunc-vunpack
+calcFunc-vxor math-check-for-commas math-clean-set math-copy-matrix
+math-dimension-error math-dot-product math-flatten-vector math-map-vec
+math-map-vec-2 math-mat-col math-mimic-ident math-prepare-set
+math-read-brackets math-reduce-cols math-reduce-vec math-transpose)
+
+ ("calc-yank" calc-Need-calc-yank calc-alg-edit calc-clean-newlines
+calc-do-grab-rectangle calc-do-grab-region calc-finish-stack-edit
+calc-force-refresh calc-locate-cursor-element calc-show-edit-buffer)
+
+))
+
+  (mapcar (function (lambda (x)
+    (mapcar (function (lambda (cmd)
+      (autoload cmd (car x) nil t))) (cdr x))))
+    '(
+
+ ("calc-alg" calc-alg-evaluate calc-apart calc-collect calc-expand
+calc-expand-formula calc-factor calc-normalize-rat calc-poly-div
+calc-poly-div-rem calc-poly-gcd calc-poly-rem calc-simplify
+calc-simplify-extended calc-substitute)
+
+ ("calc-alg-2" calc-alt-summation calc-derivative
+calc-dump-integral-cache calc-integral calc-num-integral
+calc-poly-roots calc-product calc-solve-for calc-summation
+calc-tabulate calc-taylor)
+
+ ("calc-alg-3" calc-curve-fit calc-find-maximum calc-find-minimum
+calc-find-root calc-poly-interp)
+
+ ("calc-arith" calc-abs calc-abssqr calc-ceiling calc-decrement
+calc-floor calc-idiv calc-increment calc-mant-part calc-max calc-min
+calc-round calc-scale-float calc-sign calc-trunc calc-xpon-part)
+
+ ("calc-bin" calc-and calc-binary-radix calc-clip calc-decimal-radix
+calc-diff calc-hex-radix calc-leading-zeros calc-lshift-arith
+calc-lshift-binary calc-not calc-octal-radix calc-or calc-radix
+calc-rotate-binary calc-rshift-arith calc-rshift-binary calc-word-size
+calc-xor)
+
+ ("calc-comb" calc-choose calc-double-factorial calc-extended-gcd
+calc-factorial calc-gamma calc-gcd calc-lcm calc-moebius
+calc-next-prime calc-perm calc-prev-prime calc-prime-factors
+calc-prime-test calc-random calc-random-again calc-rrandom
+calc-shuffle calc-totient)
+
+ ("calc-cplx" calc-argument calc-complex-notation calc-i-notation
+calc-im calc-j-notation calc-polar calc-polar-mode calc-re)
+
+ ("calc-embed" calc-embedded-copy-formula-as-kill
+calc-embedded-duplicate calc-embedded-edit calc-embedded-forget
+calc-embedded-kill-formula calc-embedded-mark-formula
+calc-embedded-new-formula calc-embedded-next calc-embedded-previous
+calc-embedded-select calc-embedded-update-formula calc-embedded-word
+calc-find-globals calc-show-plain)
+
+ ("calc-fin" calc-convert-percent calc-fin-ddb calc-fin-fv
+calc-fin-irr calc-fin-nper calc-fin-npv calc-fin-pmt calc-fin-pv
+calc-fin-rate calc-fin-sln calc-fin-syd calc-percent-change)
+
+ ("calc-forms" calc-business-days-minus calc-business-days-plus
+calc-convert-time-zones calc-date calc-date-notation calc-date-part
+calc-from-hms calc-hms-mode calc-hms-notation calc-inc-month
+calc-julian calc-new-month calc-new-week calc-new-year calc-now
+calc-time calc-time-zone calc-to-hms calc-unix-time)
+
+ ("calc-frac" calc-fdiv calc-frac-mode calc-fraction
+calc-over-notation calc-slash-notation)
+
+ ("calc-funcs" calc-bernoulli-number calc-bessel-J calc-bessel-Y
+calc-beta calc-erf calc-erfc calc-euler-number calc-inc-beta
+calc-inc-gamma calc-stirling-number calc-utpb calc-utpc calc-utpf
+calc-utpn calc-utpp calc-utpt)
+
+ ("calc-graph" calc-graph-add calc-graph-add-3d calc-graph-border
+calc-graph-clear calc-graph-command calc-graph-delete
+calc-graph-device calc-graph-display calc-graph-fast
+calc-graph-fast-3d calc-graph-geometry calc-graph-grid
+calc-graph-header calc-graph-hide calc-graph-juggle calc-graph-key
+calc-graph-kill calc-graph-line-style calc-graph-log-x
+calc-graph-log-y calc-graph-log-z calc-graph-name
+calc-graph-num-points calc-graph-output calc-graph-plot
+calc-graph-point-style calc-graph-print calc-graph-quit
+calc-graph-range-x calc-graph-range-y calc-graph-range-z
+calc-graph-show-dumb calc-graph-title-x calc-graph-title-y
+calc-graph-title-z calc-graph-view-commands calc-graph-view-trail
+calc-graph-zero-x calc-graph-zero-y)
+
+ ("calc-help" calc-a-prefix-help calc-b-prefix-help calc-c-prefix-help
+calc-d-prefix-help calc-describe-function calc-describe-key
+calc-describe-key-briefly calc-describe-variable calc-f-prefix-help
+calc-full-help calc-g-prefix-help calc-help-prefix
+calc-hyperbolic-prefix-help calc-inv-hyp-prefix-help
+calc-inverse-prefix-help calc-j-prefix-help calc-k-prefix-help
+calc-m-prefix-help calc-r-prefix-help calc-s-prefix-help
+calc-t-prefix-help calc-u-prefix-help calc-v-prefix-help)
+
+ ("calc-incom" calc-begin-complex calc-begin-vector calc-comma
+calc-dots calc-end-complex calc-end-vector calc-semi)
+
+ ("calc-keypd" calc-keypad-menu calc-keypad-menu-back
+calc-keypad-press)
+
+ ("calc-lang" calc-big-language calc-c-language calc-eqn-language
+calc-flat-language calc-fortran-language calc-maple-language
+calc-mathematica-language calc-normal-language calc-pascal-language
+calc-tex-language calc-unformatted-language)
+
+ ("calc-map" calc-accumulate calc-apply calc-inner-product calc-map
+calc-map-equation calc-map-stack calc-outer-product calc-reduce)
+
+ ("calc-mat" calc-mdet calc-mlud calc-mtrace)
+
+ ("calc-math" calc-arccos calc-arccosh calc-arcsin calc-arcsinh
+calc-arctan calc-arctan2 calc-arctanh calc-conj calc-cos calc-cosh
+calc-degrees-mode calc-exp calc-expm1 calc-hypot calc-ilog
+calc-imaginary calc-isqrt calc-ln calc-lnp1 calc-log calc-log10
+calc-pi calc-radians-mode calc-sin calc-sincos calc-sinh calc-sqrt
+calc-tan calc-tanh calc-to-degrees calc-to-radians)
+
+ ("calc-mode" calc-alg-simplify-mode calc-algebraic-mode
+calc-always-load-extensions calc-auto-recompute calc-auto-why
+calc-bin-simplify-mode calc-break-vectors calc-center-justify
+calc-default-simplify-mode calc-display-raw calc-eng-notation
+calc-ext-simplify-mode calc-fix-notation calc-full-trail-vectors
+calc-full-vectors calc-get-modes calc-group-char calc-group-digits
+calc-infinite-mode calc-left-justify calc-left-label
+calc-line-breaking calc-line-numbering calc-matrix-brackets
+calc-matrix-center-justify calc-matrix-left-justify calc-matrix-mode
+calc-matrix-right-justify calc-mode-record-mode calc-no-simplify-mode
+calc-normal-notation calc-num-simplify-mode calc-point-char
+calc-right-justify calc-right-label calc-save-modes calc-sci-notation
+calc-settings-file-name calc-shift-prefix calc-symbolic-mode
+calc-total-algebraic-mode calc-truncate-down calc-truncate-stack
+calc-truncate-up calc-units-simplify-mode calc-vector-braces
+calc-vector-brackets calc-vector-commas calc-vector-parens
+calc-working)
+
+ ("calc-prog" calc-call-last-kbd-macro calc-edit-user-syntax
+calc-equal-to calc-get-user-defn calc-greater-equal calc-greater-than
+calc-in-set calc-kbd-break calc-kbd-else calc-kbd-else-if
+calc-kbd-end-for calc-kbd-end-if calc-kbd-end-loop calc-kbd-end-repeat
+calc-kbd-for calc-kbd-if calc-kbd-loop calc-kbd-pop calc-kbd-push
+calc-kbd-query calc-kbd-repeat calc-kbd-report calc-less-equal
+calc-less-than calc-logical-and calc-logical-if calc-logical-not
+calc-logical-or calc-not-equal-to calc-pass-errors calc-remove-equal
+calc-timing calc-user-define calc-user-define-composition
+calc-user-define-edit calc-user-define-formula
+calc-user-define-invocation calc-user-define-kbd-macro
+calc-user-define-permanent calc-user-undefine)
+
+ ("calc-rewr" calc-match calc-rewrite calc-rewrite-selection)
+
+ ("calc-sel" calc-break-selections calc-clear-selections
+calc-copy-selection calc-del-selection calc-edit-selection
+calc-enable-selections calc-enter-selection calc-sel-add-both-sides
+calc-sel-div-both-sides calc-sel-evaluate calc-sel-expand-formula
+calc-sel-mult-both-sides calc-sel-sub-both-sides
+calc-select-additional calc-select-here calc-select-here-maybe
+calc-select-less calc-select-more calc-select-next calc-select-once
+calc-select-once-maybe calc-select-part calc-select-previous
+calc-show-selections calc-unselect)
+
+ ("calc-sel-2" calc-commute-left calc-commute-right calc-sel-commute
+calc-sel-distribute calc-sel-invert calc-sel-isolate
+calc-sel-jump-equals calc-sel-merge calc-sel-negate calc-sel-unpack)
+
+ ("calc-stat" calc-vector-correlation calc-vector-count
+calc-vector-covariance calc-vector-geometric-mean
+calc-vector-harmonic-mean calc-vector-max calc-vector-mean
+calc-vector-mean-error calc-vector-median calc-vector-min
+calc-vector-pop-covariance calc-vector-pop-sdev
+calc-vector-pop-variance calc-vector-product calc-vector-sdev
+calc-vector-sum calc-vector-variance)
+
+ ("calc-store" calc-assign calc-copy-variable calc-declare-variable
+calc-edit-AlgSimpRules calc-edit-Decls calc-edit-EvalRules
+calc-edit-ExtSimpRules calc-edit-FitRules calc-edit-GenCount
+calc-edit-Holidays calc-edit-IntegLimit calc-edit-LineStyles
+calc-edit-PlotRejects calc-edit-PointStyles calc-edit-TimeZone
+calc-edit-Units calc-edit-variable calc-evalto calc-insert-variables
+calc-let calc-permanent-variable calc-recall calc-recall-quick
+calc-store calc-store-concat calc-store-decr calc-store-div
+calc-store-exchange calc-store-incr calc-store-into
+calc-store-into-quick calc-store-inv calc-store-map calc-store-minus
+calc-store-neg calc-store-plus calc-store-power calc-store-quick
+calc-store-times calc-subscript calc-unstore)
+
+ ("calc-stuff" calc-clean calc-clean-num calc-flush-caches
+calc-less-recursion-depth calc-more-recursion-depth calc-num-prefix
+calc-version calc-why)
+
+ ("calc-trail" calc-trail-backward calc-trail-first calc-trail-forward
+calc-trail-in calc-trail-isearch-backward calc-trail-isearch-forward
+calc-trail-kill calc-trail-last calc-trail-marker calc-trail-next
+calc-trail-out calc-trail-previous calc-trail-scroll-left
+calc-trail-scroll-right calc-trail-yank)
+
+ ("calc-undo" calc-last-args calc-redo calc-undo)
+
+ ("calc-units" calc-autorange-units calc-base-units
+calc-convert-temperature calc-convert-units calc-define-unit
+calc-enter-units-table calc-explain-units calc-extract-units
+calc-get-unit-definition calc-permanent-units calc-quick-units
+calc-remove-units calc-simplify-units calc-undefine-unit
+calc-view-units-table)
+
+ ("calc-vec" calc-arrange-vector calc-build-vector calc-cnorm
+calc-conj-transpose calc-cons calc-cross calc-diag
+calc-display-strings calc-expand-vector calc-grade calc-head
+calc-histogram calc-ident calc-index calc-mask-vector calc-mcol
+calc-mrow calc-pack calc-pack-bits calc-remove-duplicates
+calc-reverse-vector calc-rnorm calc-set-cardinality
+calc-set-complement calc-set-difference calc-set-enumerate
+calc-set-floor calc-set-intersect calc-set-span calc-set-union
+calc-set-xor calc-sort calc-subvector calc-tail calc-transpose
+calc-unpack calc-unpack-bits calc-vector-find calc-vlength)
+
+ ("calc-yank" calc-copy-as-kill calc-copy-region-as-kill
+calc-copy-to-buffer calc-edit calc-edit-cancel calc-edit-mode
+calc-kill calc-kill-region calc-yank)
+
+))
+
+)
+
+(defun calc-init-prefixes ()
+  (if calc-shift-prefix
+      (progn
+	(define-key calc-mode-map "A" (lookup-key calc-mode-map "a"))
+	(define-key calc-mode-map "B" (lookup-key calc-mode-map "b"))
+	(define-key calc-mode-map "C" (lookup-key calc-mode-map "c"))
+	(define-key calc-mode-map "D" (lookup-key calc-mode-map "d"))
+	(define-key calc-mode-map "F" (lookup-key calc-mode-map "f"))
+	(define-key calc-mode-map "G" (lookup-key calc-mode-map "g"))
+	(define-key calc-mode-map "J" (lookup-key calc-mode-map "j"))
+	(define-key calc-mode-map "K" (lookup-key calc-mode-map "k"))
+	(define-key calc-mode-map "M" (lookup-key calc-mode-map "m"))
+	(define-key calc-mode-map "S" (lookup-key calc-mode-map "s"))
+	(define-key calc-mode-map "T" (lookup-key calc-mode-map "t"))
+	(define-key calc-mode-map "U" (lookup-key calc-mode-map "u")))
+    (define-key calc-mode-map "A" 'calc-abs)
+    (define-key calc-mode-map "B" 'calc-log)
+    (define-key calc-mode-map "C" 'calc-cos)
+    (define-key calc-mode-map "D" 'calc-redo)
+    (define-key calc-mode-map "F" 'calc-floor)
+    (define-key calc-mode-map "G" 'calc-argument)
+    (define-key calc-mode-map "J" 'calc-conj)
+    (define-key calc-mode-map "K" 'calc-keep-args)
+    (define-key calc-mode-map "M" 'calc-more-recursion-depth)
+    (define-key calc-mode-map "S" 'calc-sin)
+    (define-key calc-mode-map "T" 'calc-tan)
+    (define-key calc-mode-map "U" 'calc-undo))
+)
+
+(calc-init-extensions)
+
+
+
+
+;;;; Miscellaneous.
+
+(defun calc-clear-command-flag (f)
+  (setq calc-command-flags (delq f calc-command-flags))
+)
+
+
+(defun calc-record-message (tag &rest args)
+  (let ((msg (apply 'format args)))
+    (message "%s" msg)
+    (calc-record msg tag))
+  (calc-clear-command-flag 'clear-message)
+)
+
+
+(defun calc-normalize-fancy (val)
+  (let ((simp (if (consp calc-simplify-mode)
+		  (car calc-simplify-mode)
+		calc-simplify-mode)))
+    (cond ((eq simp 'binary)
+	   (let ((s (math-normalize val)))
+	     (if (math-realp s)
+		 (math-clip (math-round s))
+	       s)))
+	  ((eq simp 'alg)
+	   (math-simplify val))
+	  ((eq simp 'ext)
+	   (math-simplify-extended val))
+	  ((eq simp 'units)
+	   (math-simplify-units val))
+	  (t  ; nil, none, num
+	   (math-normalize val))))
+)
+
+
+
+(if (boundp 'calc-help-map)
+    nil
+  (setq calc-help-map (make-keymap))
+  (define-key calc-help-map "b" 'calc-describe-bindings)
+  (define-key calc-help-map "c" 'calc-describe-key-briefly)
+  (define-key calc-help-map "f" 'calc-describe-function)
+  (define-key calc-help-map "h" 'calc-full-help)
+  (define-key calc-help-map "i" 'calc-info)
+  (define-key calc-help-map "k" 'calc-describe-key)
+  (define-key calc-help-map "n" 'calc-view-news)
+  (define-key calc-help-map "s" 'calc-info-summary)
+  (define-key calc-help-map "t" 'calc-tutorial)
+  (define-key calc-help-map "v" 'calc-describe-variable)
+  (define-key calc-help-map "\C-c" 'calc-describe-copying)
+  (define-key calc-help-map "\C-d" 'calc-describe-distribution)
+  (define-key calc-help-map "\C-n" 'calc-view-news)
+  (define-key calc-help-map "\C-w" 'calc-describe-no-warranty)
+  (define-key calc-help-map "?" 'calc-help-for-help)
+  (define-key calc-help-map "\C-h" 'calc-help-for-help)
+)
+
+
+(defun calc-do-prefix-help (msgs group key)
+  (if calc-full-help-flag
+      (list msgs group key)
+    (if (cdr msgs)
+	(progn
+	  (setq calc-prefix-help-phase
+		(if (eq this-command last-command)
+		    (% (1+ calc-prefix-help-phase) (1+ (length msgs)))
+		  0))
+	  (let ((msg (nth calc-prefix-help-phase msgs)))
+	    (message "%s" (if msg
+			      (concat group ": " msg ":"
+				      (make-string
+				       (- (apply 'max (mapcar 'length msgs))
+					  (length msg)) 32)
+				      "  [MORE]"
+				      (if key
+					  (concat "  " (char-to-string key)
+						  "-")
+					""))
+			    (if key (format "%c-" key) "")))))
+      (setq calc-prefix-help-phase 0)
+      (if key
+	  (if msgs
+	      (message "%s: %s: %c-" group (car msgs) key)
+	    (message "%s: (none)  %c-" group (car msgs) key))
+	(message "%s: %s" group (car msgs))))
+    (and key (calc-unread-command key)))
+)
+(defvar calc-prefix-help-phase 0)
+
+
+
+
+;;;; Commands.
+
+
+;;; General.
+
+(defun calc-reset (arg)
+  (interactive "P")
+  (save-excursion
+    (or (eq major-mode 'calc-mode)
+	(calc-create-buffer))
+    (if calc-embedded-info
+	(calc-embedded nil))
+    (or arg
+	(setq calc-stack nil))
+    (setq calc-undo-list nil
+	  calc-redo-list nil)
+    (let (calc-stack calc-user-parse-tables calc-standard-date-formats
+		     calc-invocation-macro)
+      (mapcar (function (lambda (v) (set v nil))) calc-local-var-list)
+      (mapcar (function (lambda (v) (set (car v) (nth 1 v))))
+	      calc-mode-var-list))
+    (calc-set-language nil nil t)
+    (calc-mode)
+    (let ((executing-kbd-macro ""))  ; inhibit message
+      (calc-flush-caches))
+    (run-hooks 'calc-reset-hook))
+  (calc-wrapper
+   (let ((win (get-buffer-window (current-buffer))))
+     (calc-realign 0)
+     (if win
+	 (let ((height (- (window-height win) 2)))
+	   (set-window-point win (point))
+	   (or (= height calc-window-height)
+	       (let ((swin (selected-window)))
+		 (select-window win)
+		 (enlarge-window (- calc-window-height height))
+		 (select-window swin)))))))
+  (message "(Calculator reset)")
+)
+
+
+(defun calc-scroll-left (n)
+  (interactive "P")
+  (scroll-left (or n (/ (window-width) 2)))
+)
+
+(defun calc-scroll-right (n)
+  (interactive "P")
+  (scroll-right (or n (/ (window-width) 2)))
+)
+
+(defun calc-scroll-up (n)
+  (interactive "P")
+  (condition-case err
+      (scroll-up (or n (/ (window-height) 2)))
+    (error nil))
+  (if (pos-visible-in-window-p (max 1 (- (point-max) 2)))
+      (if (eq major-mode 'calc-mode)
+	  (calc-realign)
+	(goto-char (point-max))
+	(set-window-start (selected-window)
+			  (save-excursion
+			    (forward-line (- (1- (window-height))))
+			    (point)))
+	(forward-line -1)))
+)
+
+(defun calc-scroll-down (n)
+  (interactive "P")
+  (or (pos-visible-in-window-p 1)
+      (scroll-down (or n (/ (window-height) 2))))
+)
+
+
+(defun calc-precision (n)
+  (interactive "NPrecision: ")
+  (calc-wrapper
+   (if (< (prefix-numeric-value n) 3)
+       (error "Precision must be at least 3 digits.")
+     (calc-change-mode 'calc-internal-prec (prefix-numeric-value n)
+		       (and (memq (car calc-float-format) '(float sci eng))
+			    (< (nth 1 calc-float-format)
+				(if (= calc-number-radix 10) 0 1))))
+     (calc-record calc-internal-prec "prec"))
+   (message "Floating-point precision is %d digits." calc-internal-prec))
+)
+
+
+(defun calc-inverse (&optional n)
+  (interactive "P")
+  (calc-fancy-prefix 'calc-inverse-flag "Inverse..." n)
+)
+
+(defun calc-fancy-prefix (flag msg n)
+  (let (prefix)
+    (calc-wrapper
+     (calc-set-command-flag 'keep-flags)
+     (calc-set-command-flag 'no-align)
+     (setq prefix (set flag (not (symbol-value flag)))
+	   prefix-arg n)
+     (message (if prefix msg "")))
+    (and prefix
+         nil   ; Excise broken code we can live without.  -- daveg 12/12/96
+	 (not calc-is-keypad-press)
+	 (let ((event (calc-read-key t)))
+	   (if (eq (setq last-command-char (car event)) ?\C-u)
+	       (universal-argument)
+	     (if (or (not (integerp last-command-char))
+		     (and (>= last-command-char 0) (< last-command-char ? )
+			  (not (memq last-command-char '(?\e)))))
+		 (calc-wrapper))  ; clear flags if not a Calc command.
+	     (if calc-emacs-type-19
+		 (setq last-command-event (cdr event)))
+	     (if (or (not (integerp last-command-char))
+		     (eq last-command-char ?-))
+		 (calc-unread-command)
+	       (digit-argument n))))))
+)
+(setq calc-is-keypad-press nil)
+
+(defun calc-invert-func ()
+  (save-excursion
+    (calc-select-buffer)
+    (setq calc-inverse-flag (not (calc-is-inverse))
+	  calc-hyperbolic-flag (calc-is-hyperbolic)
+	  current-prefix-arg nil))
+)
+
+(defun calc-is-inverse ()
+  calc-inverse-flag
+)
+
+(defun calc-hyperbolic (&optional n)
+  (interactive "P")
+  (calc-fancy-prefix 'calc-hyperbolic-flag "Hyperbolic..." n)
+)
+
+(defun calc-hyperbolic-func ()
+  (save-excursion
+    (calc-select-buffer)
+    (setq calc-inverse-flag (calc-is-inverse)
+	  calc-hyperbolic-flag (not (calc-is-hyperbolic))
+	  current-prefix-arg nil))
+)
+
+(defun calc-is-hyperbolic ()
+  calc-hyperbolic-flag
+)
+
+(defun calc-keep-args (&optional n)
+  (interactive "P")
+  (calc-fancy-prefix 'calc-keep-args-flag "Keep args..." n)
+)
+
+
+(defun calc-change-mode (var value &optional refresh option)
+  (if option
+      (setq value (if value
+		      (> (prefix-numeric-value value) 0)
+		    (not (symbol-value var)))))
+  (or (consp var) (setq var (list var) value (list value)))
+  (if calc-inverse-flag
+      (let ((old nil))
+	(or refresh (error "Not a display-mode command"))
+	(calc-check-stack 1)
+	(unwind-protect
+	    (let ((v var))
+	      (while v
+		(setq old (cons (symbol-value (car v)) old))
+		(set (car v) (car value))
+		(setq v (cdr v)
+		      value (cdr value)))
+	      (calc-refresh-top 1)
+	      (calc-refresh-evaltos)
+	      (symbol-value (car var)))
+	  (let ((v var))
+	    (setq old (nreverse old))
+	    (while v
+	      (set (car v) (car old))
+	      (setq v (cdr v)
+		    old (cdr old)))
+	    (if (eq (car var) 'calc-language)
+		(calc-set-language calc-language calc-language-option t)))))
+    (let ((chg nil)
+	  (v var))
+      (while v
+	(or (equal (symbol-value (car v)) (car value))
+	    (progn
+	      (set (car v) (car value))
+	      (if (eq (car v) 'calc-float-format)
+		  (setq calc-full-float-format
+			(list (if (eq (car (car value)) 'fix)
+				  'float
+				(car (car value)))
+			      0)))
+	      (setq chg t)))
+	(setq v (cdr v)
+	      value (cdr value)))
+      (if chg
+	  (progn
+	    (or (and refresh (calc-do-refresh))
+		(calc-refresh-evaltos))
+	    (and (eq calc-mode-save-mode 'save)
+		 (not (equal var '(calc-mode-save-mode)))
+		 (calc-save-modes t))))
+      (if calc-embedded-info (calc-embedded-modes-change var))
+      (symbol-value (car var))))
+)
+
+(defun calc-refresh-top (n)
+  (interactive "p")
+  (calc-wrapper
+   (cond ((< n 0)
+	  (setq n (- n))
+	  (let ((entry (calc-top n 'entry))
+		(calc-undo-list nil) (calc-redo-list nil))
+	    (calc-pop-stack 1 n t)
+	    (calc-push-list (list (car entry)) n (list (nth 2 entry)))))
+	 ((= n 0)
+	  (calc-refresh))
+	 (t
+	  (let ((entries (calc-top-list n 1 'entry))
+		(calc-undo-list nil) (calc-redo-list nil))
+	    (calc-pop-stack n 1 t)
+	    (calc-push-list (mapcar 'car entries)
+			    1
+			    (mapcar (function (lambda (x) (nth 2 x)))
+				    entries))))))
+)
+
+(defun calc-refresh-evaltos (&optional which-var)
+  (and calc-any-evaltos calc-auto-recompute (not calc-no-refresh-evaltos)
+       (let ((calc-refreshing-evaltos t)
+	     (num (calc-stack-size))
+	     (calc-undo-list nil) (calc-redo-list nil)
+	     value new-val)
+	 (while (> num 0)
+	   (setq value (calc-top num 'entry))
+	   (if (and (not (nth 2 value))
+		    (setq value (car value))
+		    (or (eq (car-safe value) 'calcFunc-evalto)
+			(and (eq (car-safe value) 'vec)
+			     (eq (car-safe (nth 1 value)) 'calcFunc-evalto))))
+	       (progn
+		 (setq new-val (math-normalize value))
+		 (or (equal new-val value)
+		     (progn
+		       (calc-push-list (list new-val) num)
+		       (calc-pop-stack 1 (1+ num) t)))))
+	   (setq num (1- num)))))
+  (and calc-embedded-active which-var
+       (calc-embedded-var-change which-var))
+)
+(setq calc-refreshing-evaltos nil)
+(setq calc-no-refresh-evaltos nil)
+
+
+(defun calc-push (&rest vals)
+  (calc-push-list vals)
+)
+
+(defun calc-pop-push (n &rest vals)
+  (calc-pop-push-list n vals)
+)
+
+(defun calc-pop-push-record (n prefix &rest vals)
+  (calc-pop-push-record-list n prefix vals)
+)
+
+
+(defun calc-evaluate (n)
+  (interactive "p")
+  (calc-slow-wrapper
+   (if (= n 0)
+       (setq n (calc-stack-size)))
+   (calc-with-default-simplification
+    (if (< n 0)
+	(calc-pop-push-record-list 1 "eval"
+				   (math-evaluate-expr (calc-top (- n)))
+				   (- n))
+      (calc-pop-push-record-list n "eval" (mapcar 'math-evaluate-expr
+						  (calc-top-list n)))))
+   (calc-handle-whys))
+)
+
+
+(defun calc-eval-num (n)
+  (interactive "P")
+  (calc-slow-wrapper
+   (let* ((nn (prefix-numeric-value n))
+	  (calc-internal-prec (cond ((>= nn 3) nn)
+				    ((< nn 0) (max (+ calc-internal-prec nn)
+						   3))
+				    (t calc-internal-prec)))
+	  (calc-symbolic-mode nil))
+     (calc-with-default-simplification
+      (calc-pop-push-record 1 "num" (math-evaluate-expr (calc-top 1)))))
+   (calc-handle-whys))
+)
+
+
+(defun calc-execute-extended-command (n)
+  (interactive "P")
+  (let* ((prompt (concat (calc-num-prefix-name n) "M-x "))
+	 (cmd (intern (completing-read prompt obarray 'commandp t "calc-"))))
+    (setq prefix-arg n)
+    (command-execute cmd))
+)
+
+
+(defun calc-realign (&optional num)
+  (interactive "P")
+  (if (and num (eq major-mode 'calc-mode))
+      (progn
+	(calc-check-stack num)
+	(calc-cursor-stack-index num)
+	(and calc-line-numbering
+	     (forward-char 4)))
+    (if (and calc-embedded-info
+	     (eq (current-buffer) (aref calc-embedded-info 0)))
+	(progn
+	  (goto-char (aref calc-embedded-info 2))
+	  (if (save-excursion (set-buffer (aref calc-embedded-info 1))
+			      calc-show-plain)
+	      (forward-line 1)))
+      (calc-wrapper
+       (if (get-buffer-window (current-buffer))
+	   (set-window-hscroll (get-buffer-window (current-buffer)) 0)))))
+)
+
+
+
+(setq math-cache-list nil)
+
+
+
+
+(defun calc-var-value (v)
+  (and (symbolp v)
+       (boundp v)
+       (symbol-value v)
+       (if (symbolp (symbol-value v))
+	   (set v (funcall (symbol-value v)))
+	 (if (stringp (symbol-value v))
+	     (let ((val (math-read-expr (symbol-value v))))
+	       (if (eq (car-safe val) 'error)
+		   (error "Bad format in variable contents: %s" (nth 2 val))
+		 (set v val)))
+	   (symbol-value v))))
+)
+
+
+
+
+
+;;; In the following table, ( OP LOPS ROPS ) means that if an OP
+;;; term appears as the first argument to any LOPS term, or as the
+;;; second argument to any ROPS term, then they should be treated
+;;; as one large term for purposes of associative selection.
+(defconst calc-assoc-ops '( ( + ( + - ) ( + ) )
+			    ( - ( + - ) ( + ) )
+			    ( * ( * )   ( * ) )
+			    ( / ( / )   (   ) )
+			    ( | ( | )   ( | ) )
+			    ( calcFunc-land ( calcFunc-land ) 
+					    ( calcFunc-land ) )
+			    ( calcFunc-lor ( calcFunc-lor ) 
+					   ( calcFunc-lor ) ) ))
+
+
+(defvar var-CommuteRules 'calc-CommuteRules)
+(defvar var-JumpRules    'calc-JumpRules)
+(defvar var-DistribRules 'calc-DistribRules)
+(defvar var-MergeRules   'calc-MergeRules)
+(defvar var-NegateRules  'calc-NegateRules)
+(defvar var-InvertRules  'calc-InvertRules)
+
+
+(defconst calc-tweak-eqn-table '( ( calcFunc-eq  calcFunc-eq  calcFunc-neq )
+				  ( calcFunc-neq calcFunc-neq calcFunc-eq  )
+				  ( calcFunc-lt  calcFunc-gt  calcFunc-geq )
+				  ( calcFunc-gt  calcFunc-lt  calcFunc-leq )
+				  ( calcFunc-leq calcFunc-geq calcFunc-gt  )
+				  ( calcFunc-geq calcFunc-leq calcFunc-lt  ) ))
+
+
+
+
+(defun calc-float (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-unary-op "flt"
+		  (if (calc-is-hyperbolic) 'calcFunc-float 'calcFunc-pfloat)
+		  arg))
+)
+
+
+(defvar calc-gnuplot-process nil)
+
+
+(defun calc-gnuplot-alive ()
+  (and calc-gnuplot-process
+       calc-gnuplot-buffer
+       (buffer-name calc-gnuplot-buffer)
+       calc-gnuplot-input
+       (buffer-name calc-gnuplot-input)
+       (memq (process-status calc-gnuplot-process) '(run stop)))
+)
+
+
+
+
+
+(defun calc-load-everything ()
+  (interactive)
+  (calc-need-macros)       ; calc-macs.el
+  (calc-record-list nil)   ; calc-misc.el
+  (math-read-exprs "0")    ; calc-aent.el
+
+;;;; (Loads here)
+  (calc-Need-calc-alg-2)
+  (calc-Need-calc-alg-3)
+  (calc-Need-calc-alg)
+  (calc-Need-calc-arith)
+  (calc-Need-calc-bin)
+  (calc-Need-calc-comb)
+  (calc-Need-calc-comp)
+  (calc-Need-calc-cplx)
+  (calc-Need-calc-embed)
+  (calc-Need-calc-fin)
+  (calc-Need-calc-forms)
+  (calc-Need-calc-frac)
+  (calc-Need-calc-funcs)
+  (calc-Need-calc-graph)
+  (calc-Need-calc-help)
+  (calc-Need-calc-incom)
+  (calc-Need-calc-keypd)
+  (calc-Need-calc-lang)
+  (calc-Need-calc-map)
+  (calc-Need-calc-mat)
+  (calc-Need-calc-math)
+  (calc-Need-calc-mode)
+  (calc-Need-calc-poly)
+  (calc-Need-calc-prog)
+  (calc-Need-calc-rewr)
+  (calc-Need-calc-rules)
+  (calc-Need-calc-sel-2)
+  (calc-Need-calc-sel)
+  (calc-Need-calc-stat)
+  (calc-Need-calc-store)
+  (calc-Need-calc-stuff)
+  (calc-Need-calc-trail)
+  (calc-Need-calc-undo)
+  (calc-Need-calc-units)
+  (calc-Need-calc-vec)
+  (calc-Need-calc-yank)
+
+  (message "All parts of Calc are now loaded.")
+)
+
+
+;;; Vector commands.
+
+(defun calc-concat (arg)
+  (interactive "P")
+  (calc-wrapper
+   (if (calc-is-inverse)
+       (if (calc-is-hyperbolic)
+	   (calc-enter-result 2 "apnd" (list 'calcFunc-append
+					  (calc-top 1) (calc-top 2)))
+	 (calc-enter-result 2 "|" (list 'calcFunc-vconcat
+					(calc-top 1) (calc-top 2))))
+     (if (calc-is-hyperbolic)
+	 (calc-binary-op "apnd" 'calcFunc-append arg '(vec))
+       (calc-binary-op "|" 'calcFunc-vconcat arg '(vec) nil '|))))
+)
+
+(defun calc-append (arg)
+  (interactive "P")
+  (calc-hyperbolic-func)
+  (calc-concat arg)
+)
+
+
+(defconst calc-arg-values '( ( var ArgA var-ArgA ) ( var ArgB var-ArgB )
+			     ( var ArgC var-ArgC ) ( var ArgD var-ArgD )
+			     ( var ArgE var-ArgE ) ( var ArgF var-ArgF )
+			     ( var ArgG var-ArgG ) ( var ArgH var-ArgH )
+			     ( var ArgI var-ArgI ) ( var ArgJ var-ArgJ )
+))
+
+(defun calc-invent-args (n)
+  (nreverse (nthcdr (- (length calc-arg-values) n) (reverse calc-arg-values)))
+)
+
+
+
+
+;;; User menu.
+
+(defun calc-user-key-map ()
+  (if calc-emacs-type-lucid
+      (error "User-defined keys are not supported in Lucid Emacs"))
+  (let ((res (cdr (lookup-key calc-mode-map "z"))))
+    (if (eq (car (car res)) 27)
+	(cdr res)
+      res))
+)
+
+(defun calc-z-prefix-help ()
+  (interactive)
+  (let* ((msgs nil)
+	 (buf "")
+	 (kmap (sort (copy-sequence (calc-user-key-map))
+		     (function (lambda (x y) (< (car x) (car y))))))
+	 (flags (apply 'logior
+		       (mapcar (function
+				(lambda (k)
+				  (calc-user-function-classify (car k))))
+			       kmap))))
+    (if (= (logand flags 8) 0)
+	(calc-user-function-list kmap 7)
+      (calc-user-function-list kmap 1)
+      (setq msgs (cons buf msgs)
+	    buf "")
+      (calc-user-function-list kmap 6))
+    (if (/= flags 0)
+	(setq msgs (cons buf msgs)))
+    (calc-do-prefix-help (nreverse msgs) "user" ?z))
+)
+
+(defun calc-user-function-classify (key)
+  (cond ((/= key (downcase key))    ; upper-case
+	 (if (assq (downcase key) (calc-user-key-map)) 9 1))
+	((/= key (upcase key)) 2)   ; lower-case
+	((= key ??) 0)
+	(t 4))   ; other
+)
+
+(defun calc-user-function-list (map flags)
+  (and map
+       (let* ((key (car (car map)))
+	      (kind (calc-user-function-classify key))
+	      (func (cdr (car map))))
+	 (if (or (= (logand kind flags) 0)
+		 (not (symbolp func)))
+	     ()
+	   (let* ((name (symbol-name func))
+		  (name (if (string-match "\\`calc-" name)
+			    (substring name 5) name))
+		  (pos (string-match (char-to-string key) name))
+		  (desc
+		   (if (symbolp func)
+		       (if (= (logand kind 3) 0)
+			   (format "`%c' = %s" key name)
+			 (if pos
+			     (format "%s%c%s"
+				     (downcase (substring name 0 pos))
+				     (upcase key)
+				     (downcase (substring name (1+ pos))))
+			   (format "%c = %s"
+				   (upcase key)
+				   (downcase name))))
+		     (char-to-string (upcase key)))))
+	     (if (= (length buf) 0)
+		 (setq buf (concat (if (= flags 1) "SHIFT + " "")
+				   desc))
+	       (if (> (+ (length buf) (length desc)) 58)
+		   (setq msgs (cons buf msgs)
+			 buf (concat (if (= flags 1) "SHIFT + " "")
+				     desc))
+		 (setq buf (concat buf ", " desc))))))
+	 (calc-user-function-list (cdr map) flags)))
+)
+
+
+
+(defun calc-shift-Z-prefix-help ()
+  (interactive)
+  (calc-do-prefix-help
+   '("Define, Undefine, Formula, Kbd-macro, Edit, Get-defn"
+     "Composition, Syntax; Invocation; Permanent; Timing"
+     "kbd-macros: [ (if), : (else), | (else-if), ] (end-if)"
+     "kbd-macros: < > (repeat), ( ) (for), { } (loop)"
+     "kbd-macros: / (break)"
+     "kbd-macros: ` (save), ' (restore)")
+   "user" ?Z)
+)
+
+
+;;;; Caches.
+
+(defmacro math-defcache (name init form)
+  (let ((cache-prec (intern (concat (symbol-name name) "-cache-prec")))
+	(cache-val (intern (concat (symbol-name name) "-cache")))
+	(last-prec (intern (concat (symbol-name name) "-last-prec")))
+	(last-val (intern (concat (symbol-name name) "-last"))))
+    (list 'progn
+	  (list 'setq cache-prec (if init (math-numdigs (nth 1 init)) -100))
+	  (list 'setq cache-val (list 'quote init))
+	  (list 'setq last-prec -100)
+	  (list 'setq last-val nil)
+	  (list 'setq 'math-cache-list
+		(list 'cons
+		      (list 'quote cache-prec)
+		      (list 'cons
+			    (list 'quote last-prec)
+			    'math-cache-list)))
+	  (list 'defun
+		name ()
+		(list 'or
+		      (list '= last-prec 'calc-internal-prec)
+		      (list 'setq
+			    last-val
+			    (list 'math-normalize
+				  (list 'progn
+					(list 'or
+					      (list '>= cache-prec
+						    'calc-internal-prec)
+					      (list 'setq
+						    cache-val
+						    (list 'let
+							  '((calc-internal-prec
+							     (+ calc-internal-prec
+								4)))
+							  form)
+						    cache-prec
+						    '(+ calc-internal-prec 2)))
+					cache-val))
+			    last-prec 'calc-internal-prec))
+		last-val)))
+)
+(put 'math-defcache 'lisp-indent-hook 2)
+
+;;; Betcha didn't know that pi = 16 atan(1/5) - 4 atan(1/239).   [F] [Public]
+(math-defcache math-pi (float (bigpos 463 238 793 589 653 592 141 3) -21)
+  (math-add-float (math-mul-float '(float 16 0)
+				  (math-arctan-raw '(float 2 -1)))
+		  (math-mul-float '(float -4 0)
+				  (math-arctan-raw
+				   (math-float '(frac 1 239))))))
+
+(math-defcache math-two-pi nil
+  (math-mul-float (math-pi) '(float 2 0)))
+
+(math-defcache math-pi-over-2 nil
+  (math-mul-float (math-pi) '(float 5 -1)))
+
+(math-defcache math-pi-over-4 nil
+  (math-mul-float (math-pi) '(float 25 -2)))
+
+(math-defcache math-pi-over-180 nil
+  (math-div-float (math-pi) '(float 18 1)))
+
+(math-defcache math-sqrt-pi nil
+  (math-sqrt-float (math-pi)))
+
+(math-defcache math-sqrt-2 nil
+  (math-sqrt-float '(float 2 0)))
+
+(math-defcache math-sqrt-12 nil
+  (math-sqrt-float '(float 12 0)))
+
+(math-defcache math-sqrt-two-pi nil
+  (math-sqrt-float (math-two-pi)))
+
+(math-defcache math-sqrt-e (float (bigpos 849 146 128 700 270 721 648 1) -21)
+  (math-add-float '(float 1 0) (math-exp-minus-1-raw '(float 5 -1))))
+
+(math-defcache math-e nil
+  (math-pow (math-sqrt-e) 2))
+
+(math-defcache math-phi nil
+  (math-mul-float (math-add-float (math-sqrt-raw '(float 5 0)) '(float 1 0))
+		  '(float 5 -1)))
+
+(math-defcache math-gamma-const nil
+  '(float (bigpos 495 467 917 632 470 369 709 646 776 267 677 848 348 672
+		  057 988 235 399 359 593 421 310 024 824 900 120 065 606
+		  328 015 649 156 772 5) -100))
+
+(defun math-half-circle (symb)
+  (if (eq calc-angle-mode 'rad)
+      (if symb
+	  '(var pi var-pi)
+	(math-pi))
+    180)
+)
+
+(defun math-full-circle (symb)
+  (math-mul 2 (math-half-circle symb))
+)
+
+(defun math-quarter-circle (symb)
+  (math-div (math-half-circle symb) 2)
+)
+
+
+
+
+;;;; Miscellaneous math routines.
+
+;;; True if A is an odd integer.  [P R R] [Public]
+(defun math-oddp (a)
+  (if (consp a)
+      (and (memq (car a) '(bigpos bigneg))
+	   (= (% (nth 1 a) 2) 1))
+    (/= (% a 2) 0))
+)
+
+;;; True if A is a small or big integer.  [P x] [Public]
+(defun math-integerp (a)
+  (or (integerp a)
+      (memq (car-safe a) '(bigpos bigneg)))
+)
+
+;;; True if A is (numerically) a non-negative integer.  [P N] [Public]
+(defun math-natnump (a)
+  (or (natnump a)
+      (eq (car-safe a) 'bigpos))
+)
+
+;;; True if A is a rational (or integer).  [P x] [Public]
+(defun math-ratp (a)
+  (or (integerp a)
+      (memq (car-safe a) '(bigpos bigneg frac)))
+)
+
+;;; True if A is a real (or rational).  [P x] [Public]
+(defun math-realp (a)
+  (or (integerp a)
+      (memq (car-safe a) '(bigpos bigneg frac float)))
+)
+
+;;; True if A is a real or HMS form.  [P x] [Public]
+(defun math-anglep (a)
+  (or (integerp a)
+      (memq (car-safe a) '(bigpos bigneg frac float hms)))
+)
+
+;;; True if A is a number of any kind.  [P x] [Public]
+(defun math-numberp (a)
+  (or (integerp a)
+      (memq (car-safe a) '(bigpos bigneg frac float cplx polar)))
+)
+
+;;; True if A is a complex number or angle.  [P x] [Public]
+(defun math-scalarp (a)
+  (or (integerp a)
+      (memq (car-safe a) '(bigpos bigneg frac float cplx polar hms)))
+)
+
+;;; True if A is a vector.  [P x] [Public]
+(defun math-vectorp (a)
+  (eq (car-safe a) 'vec)
+)
+
+;;; True if A is any vector or scalar data object.  [P x]
+(defun math-objvecp (a)    ;  [Public]
+  (or (integerp a)
+      (memq (car-safe a) '(bigpos bigneg frac float cplx polar
+				  hms date sdev intv mod vec incomplete)))
+)
+
+;;; True if A is an object not composed of sub-formulas .  [P x] [Public]
+(defun math-primp (a)
+  (or (integerp a)
+      (memq (car-safe a) '(bigpos bigneg frac float cplx polar
+				  hms date mod var)))
+)
+
+;;; True if A is numerically (but not literally) an integer.  [P x] [Public]
+(defun math-messy-integerp (a)
+  (cond
+   ((eq (car-safe a) 'float) (>= (nth 2 a) 0))
+   ((eq (car-safe a) 'frac) (Math-integerp (math-normalize a))))
+)
+
+;;; True if A is numerically an integer.  [P x] [Public]
+(defun math-num-integerp (a)
+  (or (Math-integerp a)
+      (Math-messy-integerp a))
+)
+
+;;; True if A is (numerically) a non-negative integer.  [P N] [Public]
+(defun math-num-natnump (a)
+  (or (natnump a)
+      (eq (car-safe a) 'bigpos)
+      (and (eq (car-safe a) 'float)
+	   (Math-natnump (nth 1 a))
+	   (>= (nth 2 a) 0)))
+)
+
+;;; True if A is an integer or will evaluate to an integer.  [P x] [Public]
+(defun math-provably-integerp (a)
+  (or (Math-integerp a)
+      (and (memq (car-safe a) '(calcFunc-trunc
+				calcFunc-round
+				calcFunc-rounde
+				calcFunc-roundu
+				calcFunc-floor
+				calcFunc-ceil))
+	   (= (length a) 2)))
+)
+
+;;; True if A is a real or will evaluate to a real.  [P x] [Public]
+(defun math-provably-realp (a)
+  (or (Math-realp a)
+      (math-provably-integer a)
+      (memq (car-safe a) '(abs arg)))
+)
+
+;;; True if A is a non-real, complex number.  [P x] [Public]
+(defun math-complexp (a)
+  (memq (car-safe a) '(cplx polar))
+)
+
+;;; True if A is a non-real, rectangular complex number.  [P x] [Public]
+(defun math-rect-complexp (a)
+  (eq (car-safe a) 'cplx)
+)
+
+;;; True if A is a non-real, polar complex number.  [P x] [Public]
+(defun math-polar-complexp (a)
+  (eq (car-safe a) 'polar)
+)
+
+;;; True if A is a matrix.  [P x] [Public]
+(defun math-matrixp (a)
+  (and (Math-vectorp a)
+       (Math-vectorp (nth 1 a))
+       (cdr (nth 1 a))
+       (let ((len (length (nth 1 a))))
+	 (setq a (cdr a))
+	 (while (and (setq a (cdr a))
+		     (Math-vectorp (car a))
+		     (= (length (car a)) len)))
+	 (null a)))
+)
+
+(defun math-matrixp-step (a len)   ; [P L]
+  (or (null a)
+      (and (Math-vectorp (car a))
+	   (= (length (car a)) len)
+	   (math-matrixp-step (cdr a) len)))
+)
+
+;;; True if A is a square matrix.  [P V] [Public]
+(defun math-square-matrixp (a)
+  (let ((dims (math-mat-dimens a)))
+    (and (cdr dims)
+	 (= (car dims) (nth 1 dims))))
+)
+
+;;; True if A is any scalar data object.  [P x]
+(defun math-objectp (a)    ;  [Public]
+  (or (integerp a)
+      (memq (car-safe a) '(bigpos bigneg frac float cplx
+				  polar hms date sdev intv mod)))
+)
+
+;;; Verify that A is an integer and return A in integer form.  [I N; - x]
+(defun math-check-integer (a)   ;  [Public]
+  (cond ((integerp a) a)  ; for speed
+	((math-integerp a) a)
+	((math-messy-integerp a)
+	 (math-trunc a))
+	(t (math-reject-arg a 'integerp)))
+)
+
+;;; Verify that A is a small integer and return A in integer form.  [S N; - x]
+(defun math-check-fixnum (a &optional allow-inf)   ;  [Public]
+  (cond ((integerp a) a)  ; for speed
+	((Math-num-integerp a)
+	 (let ((a (math-trunc a)))
+	   (if (integerp a)
+	       a
+	     (if (or (Math-lessp (lsh -1 -1) a)
+		     (Math-lessp a (- (lsh -1 -1))))
+		 (math-reject-arg a 'fixnump)
+	       (math-fixnum a)))))
+	((and allow-inf (equal a '(var inf var-inf)))
+	 (lsh -1 -1))
+	((and allow-inf (equal a '(neg (var inf var-inf))))
+	 (- (lsh -1 -1)))
+	(t (math-reject-arg a 'fixnump)))
+)
+
+;;; Verify that A is an integer >= 0 and return A in integer form.  [I N; - x]
+(defun math-check-natnum (a)    ;  [Public]
+  (cond ((natnump a) a)
+	((and (not (math-negp a))
+	      (Math-num-integerp a))
+	 (math-trunc a))
+	(t (math-reject-arg a 'natnump)))
+)
+
+;;; Verify that A is in floating-point form, or force it to be a float.  [F N]
+(defun math-check-float (a)    ; [Public]
+  (cond ((eq (car-safe a) 'float) a)
+	((Math-vectorp a) (math-map-vec 'math-check-float a))
+	((Math-objectp a) (math-float a))
+	(t a))
+)
+
+;;; Verify that A is a constant.
+(defun math-check-const (a &optional exp-ok)
+  (if (or (math-constp a)
+	  (and exp-ok math-expand-formulas))
+      a
+    (math-reject-arg a 'constp))
+)
+
+
+;;; Coerce integer A to be a small integer.  [S I]
+(defun math-fixnum (a)
+  (if (consp a)
+      (if (cdr a)
+	  (if (eq (car a) 'bigneg)
+	      (- (math-fixnum-big (cdr a)))
+	    (math-fixnum-big (cdr a)))
+	0)
+    a)
+)
+
+(defun math-fixnum-big (a)
+  (if (cdr a)
+      (+ (car a) (* (math-fixnum-big (cdr a)) 1000))
+    (car a))
+)
+
+
+(defun math-normalize-fancy (a)
+  (cond ((eq (car a) 'frac)
+	 (math-make-frac (math-normalize (nth 1 a))
+			 (math-normalize (nth 2 a))))
+	((eq (car a) 'cplx)
+	 (let ((real (math-normalize (nth 1 a)))
+	       (imag (math-normalize (nth 2 a))))
+	   (if (and (math-zerop imag)
+		    (not math-simplify-only))   ; oh, what a kludge!
+	       real
+	     (list 'cplx real imag))))
+	((eq (car a) 'polar)
+	 (math-normalize-polar a))
+	((eq (car a) 'hms)
+	 (math-normalize-hms a))
+	((eq (car a) 'date)
+	 (list 'date (math-normalize (nth 1 a))))
+	((eq (car a) 'mod)
+	 (math-normalize-mod a))
+	((eq (car a) 'sdev)
+	 (let ((x (math-normalize (nth 1 a)))
+	       (s (math-normalize (nth 2 a))))
+	   (if (or (and (Math-objectp x) (not (Math-scalarp x)))
+		   (and (Math-objectp s) (not (Math-scalarp s))))
+	       (list 'calcFunc-sdev x s)
+	     (math-make-sdev x s))))
+	((eq (car a) 'intv)
+	 (let ((mask (math-normalize (nth 1 a)))
+	       (lo (math-normalize (nth 2 a)))
+	       (hi (math-normalize (nth 3 a))))
+	   (if (if (eq (car-safe lo) 'date)
+		   (not (eq (car-safe hi) 'date))
+		 (or (and (Math-objectp lo) (not (Math-anglep lo)))
+		     (and (Math-objectp hi) (not (Math-anglep hi)))))
+	       (list 'calcFunc-intv mask lo hi)
+	     (math-make-intv mask lo hi))))
+	((eq (car a) 'vec)
+	 (cons 'vec (mapcar 'math-normalize (cdr a))))
+	((eq (car a) 'quote)
+	 (math-normalize (nth 1 a)))
+	((eq (car a) 'special-const)
+	 (calc-with-default-simplification
+	  (math-normalize (nth 1 a))))
+	((eq (car a) 'var)
+	 (cons 'var (cdr a)))   ; need to re-cons for selection routines
+	((eq (car a) 'calcFunc-if)
+	 (math-normalize-logical-op a))
+	((memq (car a) '(calcFunc-lambda calcFunc-quote calcFunc-condition))
+	 (let ((calc-simplify-mode 'none))
+	   (cons (car a) (mapcar 'math-normalize (cdr a)))))
+	((eq (car a) 'calcFunc-evalto)
+	 (setq a (or (nth 1 a) 0))
+	 (or calc-refreshing-evaltos
+	     (setq a (let ((calc-simplify-mode 'none)) (math-normalize a))))
+	 (let ((b (if (and (eq (car-safe a) 'calcFunc-assign)
+			   (= (length a) 3))
+		      (nth 2 a)
+		    a)))
+	   (list 'calcFunc-evalto
+		 a
+		 (if (eq calc-simplify-mode 'none)
+		     (math-normalize b)
+		   (calc-with-default-simplification
+		    (math-evaluate-expr b))))))
+	((or (integerp (car a)) (consp (car a)))
+	 (if (null (cdr a))
+	     (math-normalize (car a))
+	   (error "Can't use multi-valued function in an expression"))))
+)
+
+(defun math-normalize-nonstandard ()   ; uses "a"
+  (if (consp calc-simplify-mode)
+      (progn
+	(setq calc-simplify-mode 'none
+	      math-simplify-only (car-safe (cdr-safe a)))
+	nil)
+    (and (symbolp (car a))
+	 (or (eq calc-simplify-mode 'none)
+	     (and (eq calc-simplify-mode 'num)
+		  (let ((aptr (setq a (cons
+				       (car a)
+				       (mapcar 'math-normalize (cdr a))))))
+		    (while (and aptr (math-constp (car aptr)))
+		      (setq aptr (cdr aptr)))
+		    aptr)))
+	 (cons (car a) (mapcar 'math-normalize (cdr a)))))
+)
+
+
+
+(setq math-expand-formulas nil)
+
+
+;;; Normalize a bignum digit list by trimming high-end zeros.  [L l]
+(defun math-norm-bignum (a)
+  (let ((digs a) (last nil))
+    (while digs
+      (or (eq (car digs) 0) (setq last digs))
+      (setq digs (cdr digs)))
+    (and last
+	 (progn
+	   (setcdr last nil)
+	   a)))
+)
+
+(defun math-bignum-test (a)   ; [B N; B s; b b]
+  (if (consp a)
+      a
+    (math-bignum a))
+)
+
+
+;;; Return 0 for zero, -1 for negative, 1 for positive.  [S n] [Public]
+(defun calcFunc-sign (a &optional x)
+  (let ((signs (math-possible-signs a)))
+    (cond ((eq signs 4) (or x 1))
+	  ((eq signs 2) 0)
+	  ((eq signs 1) (if x (math-neg x) -1))
+	  ((math-looks-negp a) (math-neg (calcFunc-sign (math-neg a))))
+	  (t (calc-record-why 'realp a)
+	     (if x
+		 (list 'calcFunc-sign a x)
+	       (list 'calcFunc-sign a)))))
+)
+
+;;; Return 0 if A is numerically equal to B, <0 if less, >0 if more.
+;;; Arguments must be normalized!  [S N N]
+(defun math-compare (a b)
+  (cond ((equal a b)
+	 (if (and (consp a)
+		  (memq (car a) '(var neg * /))
+		  (math-infinitep a))
+	     2
+	   0))
+	((and (integerp a) (Math-integerp b))
+	 (if (consp b)
+	     (if (eq (car b) 'bigpos) -1 1)
+	   (if (< a b) -1 1)))
+	((and (eq (car-safe a) 'bigpos) (Math-integerp b))
+	 (if (eq (car-safe b) 'bigpos)
+	     (math-compare-bignum (cdr a) (cdr b))
+	   1))
+	((and (eq (car-safe a) 'bigneg) (Math-integerp b))
+	 (if (eq (car-safe b) 'bigneg)
+	     (math-compare-bignum (cdr b) (cdr a))
+	   -1))
+	((eq (car-safe a) 'frac)
+	 (if (eq (car-safe b) 'frac)
+	     (math-compare (math-mul (nth 1 a) (nth 2 b))
+			   (math-mul (nth 1 b) (nth 2 a)))
+	   (math-compare (nth 1 a) (math-mul b (nth 2 a)))))
+	((eq (car-safe b) 'frac)
+	 (math-compare (math-mul a (nth 2 b)) (nth 1 b)))
+	((and (eq (car-safe a) 'float) (eq (car-safe b) 'float))
+	 (if (math-lessp-float a b) -1 1))
+	((and (eq (car-safe a) 'date) (eq (car-safe b) 'date))
+	 (math-compare (nth 1 a) (nth 1 b)))
+	((and (or (Math-anglep a)
+		  (and (eq (car a) 'cplx) (eq (nth 2 a) 0)))
+	      (or (Math-anglep b)
+		  (and (eq (car b) 'cplx) (eq (nth 2 b) 0))))
+	 (calcFunc-sign (math-add a (math-neg b))))
+	((and (eq (car-safe a) 'intv)
+	      (or (Math-anglep b) (eq (car-safe b) 'date)))
+	 (let ((res (math-compare (nth 2 a) b)))
+	   (cond ((eq res 1) 1)
+		 ((and (eq res 0) (memq (nth 1 a) '(0 1))) 1)
+		 ((eq (setq res (math-compare (nth 3 a) b)) -1) -1)
+		 ((and (eq res 0) (memq (nth 1 a) '(0 2))) -1)
+		 (t 2))))
+	((and (eq (car-safe b) 'intv)
+	      (or (Math-anglep a) (eq (car-safe a) 'date)))
+	 (let ((res (math-compare a (nth 2 b))))
+	   (cond ((eq res -1) -1)
+		 ((and (eq res 0) (memq (nth 1 b) '(0 1))) -1)
+		 ((eq (setq res (math-compare a (nth 3 b))) 1) 1)
+		 ((and (eq res 0) (memq (nth 1 b) '(0 2))) 1)
+		 (t 2))))
+	((and (eq (car-safe a) 'intv) (eq (car-safe b) 'intv))
+	 (let ((res (math-compare (nth 3 a) (nth 2 b))))
+	   (cond ((eq res -1) -1)
+		 ((and (eq res 0) (or (memq (nth 1 a) '(0 2))
+				      (memq (nth 1 b) '(0 1)))) -1)
+		 ((eq (setq res (math-compare (nth 2 a) (nth 3 b))) 1) 1)
+		 ((and (eq res 0) (or (memq (nth 1 a) '(0 1))
+				      (memq (nth 1 b) '(0 2)))) 1)
+		 (t 2))))
+	((math-infinitep a)
+	 (if (or (equal a '(var uinf var-uinf))
+		 (equal a '(var nan var-nan)))
+	     2
+	   (let ((dira (math-infinite-dir a)))
+	     (if (math-infinitep b)
+		 (if (or (equal b '(var uinf var-uinf))
+			 (equal b '(var nan var-nan)))
+		     2
+		   (let ((dirb (math-infinite-dir b)))
+		     (cond ((and (eq dira 1) (eq dirb -1)) 1)
+			   ((and (eq dira -1) (eq dirb 1)) -1)
+			   (t 2))))
+	       (cond ((eq dira 1) 1)
+		     ((eq dira -1) -1)
+		     (t 2))))))
+	((math-infinitep b)
+	 (if (or (equal b '(var uinf var-uinf))
+		 (equal b '(var nan var-nan)))
+	     2
+	   (let ((dirb (math-infinite-dir b)))
+	     (cond ((eq dirb 1) -1)
+		   ((eq dirb -1) 1)
+		   (t 2)))))
+	((and (eq (car-safe a) 'calcFunc-exp)
+	      (eq (car-safe b) '^)
+	      (equal (nth 1 b) '(var e var-e)))
+	 (math-compare (nth 1 a) (nth 2 b)))
+	((and (eq (car-safe b) 'calcFunc-exp)
+	      (eq (car-safe a) '^)
+	      (equal (nth 1 a) '(var e var-e)))
+	 (math-compare (nth 2 a) (nth 1 b)))
+	((or (and (eq (car-safe a) 'calcFunc-sqrt)
+		  (eq (car-safe b) '^)
+		  (or (equal (nth 2 b) '(frac 1 2))
+		      (equal (nth 2 b) '(float 5 -1))))
+	     (and (eq (car-safe b) 'calcFunc-sqrt)
+		  (eq (car-safe a) '^)
+		  (or (equal (nth 2 a) '(frac 1 2))
+		      (equal (nth 2 a) '(float 5 -1)))))
+	 (math-compare (nth 1 a) (nth 1 b)))
+	((eq (car-safe a) 'var)
+	 2)
+	(t
+	 (if (and (consp a) (consp b)
+		  (eq (car a) (car b))
+		  (math-compare-lists (cdr a) (cdr b)))
+	     0
+	   2)))
+)
+
+;;; Compare two bignum digit lists, return -1 for A<B, 0 for A=B, 1 for A>B.
+(defun math-compare-bignum (a b)   ; [S l l]
+  (let ((res 0))
+    (while (and a b)
+      (if (< (car a) (car b))
+	  (setq res -1)
+	(if (> (car a) (car b))
+	    (setq res 1)))
+      (setq a (cdr a)
+	    b (cdr b)))
+    (if a
+	(progn
+	  (while (eq (car a) 0) (setq a (cdr a)))
+	  (if a 1 res))
+      (while (eq (car b) 0) (setq b (cdr b)))
+      (if b -1 res)))
+)
+
+(defun math-compare-lists (a b)
+  (cond ((null a) (null b))
+	((null b) nil)
+	(t (and (Math-equal (car a) (car b))
+		(math-compare-lists (cdr a) (cdr b)))))
+)
+
+(defun math-lessp-float (a b)   ; [P F F]
+  (let ((ediff (- (nth 2 a) (nth 2 b))))
+    (if (>= ediff 0)
+	(if (>= ediff (+ calc-internal-prec calc-internal-prec))
+	    (if (eq (nth 1 a) 0)
+		(Math-integer-posp (nth 1 b))
+	      (Math-integer-negp (nth 1 a)))
+	  (Math-lessp (math-scale-int (nth 1 a) ediff)
+		      (nth 1 b)))
+      (if (>= (setq ediff (- ediff))
+	      (+ calc-internal-prec calc-internal-prec))
+	  (if (eq (nth 1 b) 0)
+	      (Math-integer-negp (nth 1 a))
+	    (Math-integer-posp (nth 1 b)))
+	(Math-lessp (nth 1 a)
+		    (math-scale-int (nth 1 b) ediff)))))
+)
+
+;;; True if A is numerically equal to B.  [P N N] [Public]
+(defun math-equal (a b)
+  (= (math-compare a b) 0)
+)
+
+;;; True if A is numerically less than B.  [P R R] [Public]
+(defun math-lessp (a b)
+  (= (math-compare a b) -1)
+)
+
+;;; True if A is numerically equal to the integer B.  [P N S] [Public]
+;;; B must not be a multiple of 10.
+(defun math-equal-int (a b)
+  (or (eq a b)
+      (and (eq (car-safe a) 'float)
+	   (eq (nth 1 a) b)
+	   (= (nth 2 a) 0)))
+)
+
+
+
+
+;;; Return the dimensions of a matrix as a list.  [l x] [Public]
+(defun math-mat-dimens (m)
+  (if (math-vectorp m)
+      (if (math-matrixp m)
+	  (cons (1- (length m))
+		(math-mat-dimens (nth 1 m)))
+	(list (1- (length m))))
+    nil)
+)
+
+
+
+(defun calc-binary-op-fancy (name func arg ident unary)
+  (let ((n (prefix-numeric-value arg)))
+    (cond ((> n 1)
+	   (calc-enter-result n
+			      name
+			      (list 'calcFunc-reduce
+				    (math-calcFunc-to-var func)
+				    (cons 'vec (calc-top-list-n n)))))
+	  ((= n 1)
+	   (if unary
+	       (calc-enter-result 1 name (list unary (calc-top-n 1)))))
+	  ((= n 0)
+	   (if ident
+	       (calc-enter-result 0 name ident)
+	     (error "Argument must be nonzero")))
+	  (t
+	   (let ((rhs (calc-top-n 1)))
+	     (calc-enter-result (- 1 n)
+				name
+				(mapcar (function
+					 (lambda (x)
+					   (list func x rhs)))
+					(calc-top-list-n (- n) 2)))))))
+)
+
+(defun calc-unary-op-fancy (name func arg)
+  (let ((n (prefix-numeric-value arg)))
+    (if (= n 0) (setq n (calc-stack-size)))
+    (cond ((> n 0)
+	   (calc-enter-result n
+			      name
+			      (mapcar (function
+				       (lambda (x)
+					 (list func x)))
+				      (calc-top-list-n n))))
+	  ((< n 0)
+	   (calc-enter-result 1
+			      name
+			      (list func (calc-top-n (- n)))
+			      (- n)))))
+)
+
+
+
+(defvar var-Holidays '(vec (var sat var-sat) (var sun var-sun)))
+
+
+
+(defvar var-Decls (list 'vec))
+
+
+
+(setq math-simplify-only nil)
+
+(defun math-inexact-result ()
+  (and calc-symbolic-mode
+       (signal 'inexact-result nil))
+)
+
+(defun math-overflow (&optional exp)
+  (if (and exp (math-negp exp))
+      (math-underflow)
+    (signal 'math-overflow nil))
+)
+
+(defun math-underflow ()
+  (signal 'math-underflow nil)
+)
+
+
+
+;;; Compute the greatest common divisor of A and B.   [I I I] [Public]
+(defun math-gcd (a b)
+  (cond ((not (or (consp a) (consp b)))
+	 (if (< a 0) (setq a (- a)))
+	 (if (< b 0) (setq b (- b)))
+	 (let (c)
+	   (if (< a b)
+	       (setq c b b a a c))
+	   (while (> b 0)
+	     (setq c b
+		   b (% a b)
+		   a c))
+	   a))
+	((eq a 0) b)
+	((eq b 0) a)
+	(t
+	 (if (Math-integer-negp a) (setq a (math-neg a)))
+	 (if (Math-integer-negp b) (setq b (math-neg b)))
+	 (let (c)
+	   (if (Math-natnum-lessp a b)
+	       (setq c b b a a c))
+	   (while (and (consp a) (not (eq b 0)))
+	     (setq c b
+		   b (math-imod a b)
+		   a c))
+	   (while (> b 0)
+	     (setq c b
+		   b (% a b)
+		   a c))
+	   a)))
+)
+
+
+;;;; Algebra.
+
+;;; Evaluate variables in an expression.
+(defun math-evaluate-expr (x)  ; [Public]
+  (if calc-embedded-info
+      (calc-embedded-evaluate-expr x)
+    (calc-normalize (math-evaluate-expr-rec x)))
+)
+(fset 'calcFunc-evalv (symbol-function 'math-evaluate-expr))
+
+(defun calcFunc-evalvn (x &optional prec)
+  (if prec
+      (progn
+	(or (math-num-integerp prec)
+	    (if (and (math-vectorp prec)
+		     (= (length prec) 2)
+		     (math-num-integerp (nth 1 prec)))
+		(setq prec (math-add (nth 1 prec) calc-internal-prec))
+	      (math-reject-arg prec 'integerp)))
+	(setq prec (math-trunc prec))
+	(if (< prec 3) (setq prec 3))
+	(if (> prec calc-internal-prec)
+	    (math-normalize
+	     (let ((calc-internal-prec prec))
+	       (calcFunc-evalvn x)))
+	  (let ((calc-internal-prec prec))
+	    (calcFunc-evalvn x))))
+    (let ((calc-symbolic-mode nil))
+      (math-evaluate-expr x)))
+)
+
+(defun math-evaluate-expr-rec (x)
+  (if (consp x)
+      (if (memq (car x) '(calcFunc-quote calcFunc-condition
+					 calcFunc-evalto calcFunc-assign))
+	  (if (and (eq (car x) 'calcFunc-assign)
+		   (= (length x) 3))
+	      (list (car x) (nth 1 x) (math-evaluate-expr-rec (nth 2 x)))
+	    x)
+	(if (eq (car x) 'var)
+	    (if (and (calc-var-value (nth 2 x))
+		     (not (eq (car-safe (symbol-value (nth 2 x)))
+			      'incomplete)))
+		(let ((val (symbol-value (nth 2 x))))
+		  (if (eq (car-safe val) 'special-const)
+		      (if calc-symbolic-mode
+			  x
+			val)
+		    val))
+	      x)
+	  (if (Math-primp x)
+	      x
+	    (cons (car x) (mapcar 'math-evaluate-expr-rec (cdr x))))))
+    x)
+)
+
+
+
+(setq math-simplifying nil)
+(setq math-living-dangerously nil)   ; true if unsafe simplifications are okay.
+(setq math-integrating nil)
+
+
+
+
+(defmacro math-defsimplify (funcs &rest code)
+  (append '(progn (math-need-std-simps))
+	  (mapcar (function
+		   (lambda (func)
+		     (list 'put (list 'quote func) ''math-simplify
+			   (list 'nconc
+				 (list 'get (list 'quote func) ''math-simplify)
+				 (list 'list
+				       (list 'function
+					     (append '(lambda (expr))
+						     code)))))))
+		  (if (symbolp funcs) (list funcs) funcs)))
+)
+(put 'math-defsimplify 'lisp-indent-hook 1)
+
+
+(defun math-any-floats (expr)
+  (if (Math-primp expr)
+      (math-floatp expr)
+    (while (and (setq expr (cdr expr)) (not (math-any-floats (car expr)))))
+    expr)
+)
+
+(defvar var-FactorRules 'calc-FactorRules)
+
+
+
+(defun math-map-tree (mmt-func mmt-expr &optional mmt-many)
+  (or mmt-many (setq mmt-many 1000000))
+  (math-map-tree-rec mmt-expr)
+)
+
+(defun math-map-tree-rec (mmt-expr)
+  (or (= mmt-many 0)
+      (let ((mmt-done nil)
+	    mmt-nextval)
+	(while (not mmt-done)
+	  (while (and (/= mmt-many 0)
+		      (setq mmt-nextval (funcall mmt-func mmt-expr))
+		      (not (equal mmt-expr mmt-nextval)))
+	    (setq mmt-expr mmt-nextval
+		  mmt-many (if (> mmt-many 0) (1- mmt-many) (1+ mmt-many))))
+	  (if (or (Math-primp mmt-expr)
+		  (<= mmt-many 0))
+	      (setq mmt-done t)
+	    (setq mmt-nextval (cons (car mmt-expr)
+				    (mapcar 'math-map-tree-rec
+					    (cdr mmt-expr))))
+	    (if (equal mmt-nextval mmt-expr)
+		(setq mmt-done t)
+	      (setq mmt-expr mmt-nextval))))))
+  mmt-expr
+)
+
+
+
+
+(setq math-rewrite-selections nil)
+
+(defun math-is-true (expr)
+  (if (Math-numberp expr)
+      (not (Math-zerop expr))
+    (math-known-nonzerop expr))
+)
+
+(defun math-const-var (expr)
+  (and (consp expr)
+       (eq (car expr) 'var)
+       (or (and (symbolp (nth 2 expr))
+		(boundp (nth 2 expr))
+		(eq (car-safe (symbol-value (nth 2 expr))) 'special-const))
+	   (memq (nth 2 expr) '(var-inf var-uinf var-nan))))
+)
+
+
+
+
+(defmacro math-defintegral (funcs &rest code)
+  (setq math-integral-cache nil)
+  (append '(progn)
+	  (mapcar (function
+		   (lambda (func)
+		     (list 'put (list 'quote func) ''math-integral
+			   (list 'nconc
+				 (list 'get (list 'quote func) ''math-integral)
+				 (list 'list
+				       (list 'function
+					     (append '(lambda (u))
+						     code)))))))
+		  (if (symbolp funcs) (list funcs) funcs)))
+)
+(put 'math-defintegral 'lisp-indent-hook 1)
+
+(defmacro math-defintegral-2 (funcs &rest code)
+  (setq math-integral-cache nil)
+  (append '(progn)
+	  (mapcar (function
+		   (lambda (func)
+		     (list 'put (list 'quote func) ''math-integral-2
+			   (list 'nconc
+				 (list 'get (list 'quote func)
+				       ''math-integral-2)
+				 (list 'list
+				       (list 'function
+					     (append '(lambda (u v))
+						     code)))))))
+		  (if (symbolp funcs) (list funcs) funcs)))
+)
+(put 'math-defintegral-2 'lisp-indent-hook 1)
+
+
+(defvar var-IntegAfterRules 'calc-IntegAfterRules)
+
+
+(defvar var-FitRules 'calc-FitRules)
+
+
+(setq math-poly-base-variable nil)
+(setq math-poly-neg-powers nil)
+(setq math-poly-mult-powers 1)
+(setq math-poly-frac-powers nil)
+(setq math-poly-exp-base nil)
+
+
+
+
+(defun math-build-var-name (name)
+  (if (stringp name)
+      (setq name (intern name)))
+  (if (string-match "\\`var-." (symbol-name name))
+      (list 'var (intern (substring (symbol-name name) 4)) name)
+    (list 'var name (intern (concat "var-" (symbol-name name)))))
+)
+
+(setq math-simplifying-units nil)
+(setq math-combining-units t)
+
+
+(put 'math-while 'lisp-indent-hook 1)
+(put 'math-for 'lisp-indent-hook 1)
+(put 'math-foreach 'lisp-indent-hook 1)
+
+
+;;; Nontrivial number parsing.
+
+(defun math-read-number-fancy (s)
+  (cond
+
+   ;; Integer+fractions
+   ((string-match "^\\([0-9]*\\)[:/]\\([0-9]*\\)[:/]\\([0-9]*\\)$" s)
+    (let ((int (math-match-substring s 1))
+	  (num (math-match-substring s 2))
+	  (den (math-match-substring s 3)))
+      (let ((int (if (> (length int) 0) (math-read-number int) 0))
+	    (num (if (> (length num) 0) (math-read-number num) 1))
+	    (den (if (> (length num) 0) (math-read-number den) 1)))
+	(and int num den
+	     (math-integerp int) (math-integerp num) (math-integerp den)
+	     (not (math-zerop den))
+	     (list 'frac (math-add num (math-mul int den)) den)))))
+   
+   ;; Fractions
+   ((string-match "^\\([0-9]*\\)[:/]\\([0-9]*\\)$" s)
+    (let ((num (math-match-substring s 1))
+	  (den (math-match-substring s 2)))
+      (let ((num (if (> (length num) 0) (math-read-number num) 1))
+	    (den (if (> (length num) 0) (math-read-number den) 1)))
+	(and num den (math-integerp num) (math-integerp den)
+	     (not (math-zerop den))
+	     (list 'frac num den)))))
+   
+   ;; Modulo forms
+   ((string-match "^\\(.*\\) *mod *\\(.*\\)$" s)
+    (let* ((n (math-match-substring s 1))
+	   (m (math-match-substring s 2))
+	   (n (math-read-number n))
+	   (m (math-read-number m)))
+      (and n m (math-anglep n) (math-anglep m)
+	   (list 'mod n m))))
+
+   ;; Error forms
+   ((string-match "^\\(.*\\) *\\+/- *\\(.*\\)$" s)
+    (let* ((x (math-match-substring s 1))
+	   (sigma (math-match-substring s 2))
+	   (x (math-read-number x))
+	   (sigma (math-read-number sigma)))
+      (and x sigma (math-scalarp x) (math-anglep sigma)
+	   (list 'sdev x sigma))))
+
+   ;; Hours (or degrees)
+   ((or (string-match "^\\([^#^]+\\)[@oOhH]\\(.*\\)$" s)
+	(string-match "^\\([^#^]+\\)[dD][eE]?[gG]?\\(.*\\)$" s))
+    (let* ((hours (math-match-substring s 1))
+	   (minsec (math-match-substring s 2))
+	   (hours (math-read-number hours))
+	   (minsec (if (> (length minsec) 0) (math-read-number minsec) 0)))
+      (and hours minsec
+	   (math-num-integerp hours)
+	   (not (math-negp hours)) (not (math-negp minsec))
+	   (cond ((math-num-integerp minsec)
+		  (and (Math-lessp minsec 60)
+		       (list 'hms hours minsec 0)))
+		 ((and (eq (car-safe minsec) 'hms)
+		       (math-zerop (nth 1 minsec)))
+		  (math-add (list 'hms hours 0 0) minsec))
+		 (t nil)))))
+   
+   ;; Minutes
+   ((string-match "^\\([^'#^]+\\)[mM']\\(.*\\)$" s)
+    (let* ((minutes (math-match-substring s 1))
+	   (seconds (math-match-substring s 2))
+	   (minutes (math-read-number minutes))
+	   (seconds (if (> (length seconds) 0) (math-read-number seconds) 0)))
+      (and minutes seconds
+	   (math-num-integerp minutes)
+	   (not (math-negp minutes)) (not (math-negp seconds))
+	   (cond ((math-realp seconds)
+		  (and (Math-lessp minutes 60)
+		       (list 'hms 0 minutes seconds)))
+		 ((and (eq (car-safe seconds) 'hms)
+		       (math-zerop (nth 1 seconds))
+		       (math-zerop (nth 2 seconds)))
+		  (math-add (list 'hms 0 minutes 0) seconds))
+		 (t nil)))))
+   
+   ;; Seconds
+   ((string-match "^\\([^\"#^]+\\)[sS\"]$" s)
+    (let ((seconds (math-read-number (math-match-substring s 1))))
+      (and seconds (math-realp seconds)
+	   (not (math-negp seconds))
+	   (Math-lessp seconds 60)
+	   (list 'hms 0 0 seconds))))
+   
+   ;; Integer+fraction with explicit radix
+   ((string-match "^\\([0-9]+\\)\\(#\\|\\^\\^\\)\\([0-9a-zA-Z]*\\)[:/]\\([0-9a-zA-Z]*\\)[:/]\\([0-9a-zA-Z]\\)$" s)
+    (let ((radix (string-to-int (math-match-substring s 1)))
+	  (int (math-match-substring s 3))
+	  (num (math-match-substring s 4))
+	  (den (math-match-substring s 5)))
+      (let ((int (if (> (length int) 0) (math-read-radix int radix) 0))
+	    (num (if (> (length num) 0) (math-read-radix num radix) 1))
+	    (den (if (> (length den) 0) (math-read-radix den radix) 1)))
+	(and int num den (not (math-zerop den))
+	     (list 'frac
+		   (math-add num (math-mul int den))
+		   den)))))
+   
+   ;; Fraction with explicit radix
+   ((string-match "^\\([0-9]+\\)\\(#\\|\\^\\^\\)\\([0-9a-zA-Z]*\\)[:/]\\([0-9a-zA-Z]*\\)$" s)
+    (let ((radix (string-to-int (math-match-substring s 1)))
+	  (num (math-match-substring s 3))
+	  (den (math-match-substring s 4)))
+      (let ((num (if (> (length num) 0) (math-read-radix num radix) 1))
+	    (den (if (> (length den) 0) (math-read-radix den radix) 1)))
+	(and num den (not (math-zerop den)) (list 'frac num den)))))
+   
+   ;; Float with explicit radix and exponent
+   ((or (string-match "^0*\\(\\([2-9]\\|1[0-4]\\)\\(#\\|\\^\\^\\)[0-9a-dA-D.]+\\)[eE]\\([-+]?[0-9]+\\)$" s)
+	(string-match "^\\(\\([0-9]+\\)\\(#\\|\\^\\^\\)[0-9a-zA-Z.]+\\) *\\* *\\2\\.? *\\^ *\\([-+]?[0-9]+\\)$" s))
+    (let ((radix (string-to-int (math-match-substring s 2)))    
+	  (mant (math-match-substring s 1))
+	  (exp (math-match-substring s 4)))
+      (let ((mant (math-read-number mant))
+	    (exp (math-read-number exp)))
+	(and mant exp
+	     (math-mul mant (math-pow (math-float radix) exp))))))
+
+   ;; Float with explicit radix, no exponent
+   ((string-match "^\\([0-9]+\\)\\(#\\|\\^\\^\\)\\([0-9a-zA-Z]*\\)\\.\\([0-9a-zA-Z]*\\)$" s)
+    (let ((radix (string-to-int (math-match-substring s 1)))
+	  (int (math-match-substring s 3))
+	  (fracs (math-match-substring s 4)))
+      (let ((int (if (> (length int) 0) (math-read-radix int radix) 0))
+	    (frac (if (> (length fracs) 0) (math-read-radix fracs radix) 0))
+	    (calc-prefer-frac nil))
+	(and int frac
+	     (math-add int (math-div frac (math-pow radix (length fracs))))))))
+
+   ;; Integer with explicit radix
+   ((string-match "^\\([0-9]+\\)\\(#\\|\\^\\^\\)\\([0-9a-zA-Z]+\\)$" s)
+    (math-read-radix (math-match-substring s 3)
+		     (string-to-int (math-match-substring s 1))))
+
+   ;; C language hexadecimal notation
+   ((and (eq calc-language 'c)
+	 (string-match "^0[xX]\\([0-9a-fA-F]+\\)$" s))
+    (let ((digs (math-match-substring s 1)))
+      (math-read-radix digs 16)))
+
+   ;; Pascal language hexadecimal notation
+   ((and (eq calc-language 'pascal)
+	 (string-match "^\\$\\([0-9a-fA-F]+\\)$" s))
+    (let ((digs (math-match-substring s 1)))
+      (math-read-radix digs 16)))
+
+   ;; Fraction using "/" instead of ":"
+   ((string-match "^\\([0-9]+\\)/\\([0-9/]+\\)$" s)
+    (math-read-number (concat (math-match-substring s 1) ":"
+			      (math-match-substring s 2))))
+
+   ;; Syntax error!
+   (t nil))
+)
+
+(defun math-read-radix (s r)   ; [I X D]
+  (setq s (upcase s))
+  (let ((i 0)
+	(res 0)
+	dig)
+    (while (and (< i (length s))
+		(setq dig (math-read-radix-digit (elt s i)))
+		(< dig r))
+      (setq res (math-add (math-mul res r) dig)
+	    i (1+ i)))
+    (and (= i (length s))
+	 res))
+)
+
+
+
+;;; Expression parsing.
+
+(defun math-read-expr (exp-str)
+  (let ((exp-pos 0)
+	(exp-old-pos 0)
+	(exp-keep-spaces nil)
+	exp-token exp-data)
+    (while (setq exp-token (string-match "\\.\\.\\([^.]\\|.[^.]\\)" exp-str))
+      (setq exp-str (concat (substring exp-str 0 exp-token) "\\dots"
+			    (substring exp-str (+ exp-token 2)))))
+    (math-build-parse-table)
+    (math-read-token)
+    (let ((val (catch 'syntax (math-read-expr-level 0))))
+      (if (stringp val)
+	  (list 'error exp-old-pos val)
+	(if (equal exp-token 'end)
+	    val
+	  (list 'error exp-old-pos "Syntax error")))))
+)
+
+(defun math-read-plain-expr (exp-str &optional error-check)
+  (let* ((calc-language nil)
+	 (math-expr-opers math-standard-opers)
+	 (val (math-read-expr exp-str)))
+    (and error-check
+	 (eq (car-safe val) 'error)
+	 (error "%s: %s" (nth 2 val) exp-str))
+    val)
+)
+
+
+(defun math-read-string ()
+  (let ((str (read-from-string (concat exp-data "\""))))
+    (or (and (= (cdr str) (1+ (length exp-data)))
+	     (stringp (car str)))
+	(throw 'syntax "Error in string constant"))
+    (math-read-token)
+    (append '(vec) (car str) nil))
+)
+
+
+
+;;; They said it couldn't be done...
+
+(defun math-read-big-expr (str)
+  (and (> (length calc-left-label) 0)
+       (string-match (concat "^" (regexp-quote calc-left-label)) str)
+       (setq str (concat (substring str 0 (match-beginning 0))
+			 (substring str (match-end 0)))))
+  (and (> (length calc-right-label) 0)
+       (string-match (concat (regexp-quote calc-right-label) " *$") str)
+       (setq str (concat (substring str 0 (match-beginning 0))
+			 (substring str (match-end 0)))))
+  (if (string-match "\\\\[^ \n|]" str)
+      (if (eq calc-language 'tex)
+	  (math-read-expr str)
+	(let ((calc-language 'tex)
+	      (calc-language-option nil)
+	      (math-expr-opers (get 'tex 'math-oper-table))
+	      (math-expr-function-mapping (get 'tex 'math-function-table))
+	      (math-expr-variable-mapping (get 'tex 'math-variable-table)))
+	  (math-read-expr str)))
+    (let ((lines nil)
+	  (pos 0)
+	  (width 0)
+	  (err-msg nil)
+	  the-baseline the-h2
+	  new-pos p)
+      (while (setq new-pos (string-match "\n" str pos))
+	(setq lines (cons (substring str pos new-pos) lines)
+	      pos (1+ new-pos)))
+      (setq lines (nreverse (cons (substring str pos) lines))
+	    p lines)
+      (while p
+	(setq width (max width (length (car p)))
+	      p (cdr p)))
+      (if (math-read-big-bigp lines)
+	  (or (catch 'syntax
+		(math-read-big-rec 0 0 width (length lines)))
+	      err-msg
+	      '(error 0 "Syntax error"))
+	(math-read-expr str))))
+)
+
+(defun math-read-big-bigp (lines)
+  (and (cdr lines)
+       (let ((matrix nil)
+	     (v 0)
+	     (height (if (> (length (car lines)) 0) 1 0)))
+	 (while (and (cdr lines)
+		     (let* ((i 0)
+			    j
+			    (l1 (car lines))
+			    (l2 (nth 1 lines))
+			    (len (min (length l1) (length l2))))
+		       (if (> (length l2) 0)
+			   (setq height (1+ height)))
+		       (while (and (< i len)
+				   (or (memq (aref l1 i) '(?\  ?\- ?\_))
+				       (memq (aref l2 i) '(?\  ?\-))
+				       (and (memq (aref l1 i) '(?\| ?\,))
+					    (= (aref l2 i) (aref l1 i)))
+				       (and (eq (aref l1 i) ?\[)
+					    (eq (aref l2 i) ?\[)
+					    (let ((h2 (length l1)))
+					      (setq j (math-read-big-balance
+						       (1+ i) v "[")))
+					    (setq i (1- j)))))
+			 (setq i (1+ i)))
+		       (or (= i len)
+			   (and (eq (aref l1 i) ?\[)
+				(eq (aref l2 i) ?\[)
+				(setq matrix t)
+				nil))))
+	   (setq lines (cdr lines)
+		 v (1+ v)))
+	 (or (and (> height 1)
+		  (not (cdr lines)))
+	     matrix)))
+)
+
+
+
+;;; Nontrivial "flat" formatting.
+
+(defun math-format-flat-expr-fancy (a prec)
+  (cond
+   ((eq (car a) 'incomplete)
+    (format "<incomplete %s>" (nth 1 a)))
+   ((eq (car a) 'vec)
+    (if (or calc-full-trail-vectors (not calc-can-abbrev-vectors)
+	    (< (length a) 7))
+	(concat "[" (math-format-flat-vector (cdr a) ", "
+					     (if (cdr (cdr a)) 0 1000)) "]")
+      (concat "["
+	      (math-format-flat-expr (nth 1 a) 0) ", "
+	      (math-format-flat-expr (nth 2 a) 0) ", "
+	      (math-format-flat-expr (nth 3 a) 0) ", ..., "
+	      (math-format-flat-expr (nth (1- (length a)) a) 0) "]")))
+   ((eq (car a) 'intv)
+    (concat (if (memq (nth 1 a) '(0 1)) "(" "[")
+	    (math-format-flat-expr (nth 2 a) 1000)
+	    " .. "
+	    (math-format-flat-expr (nth 3 a) 1000)
+	    (if (memq (nth 1 a) '(0 2)) ")" "]")))
+   ((eq (car a) 'date)
+    (concat "<" (math-format-date a) ">"))
+   ((and (eq (car a) 'calcFunc-lambda) (> (length a) 2))
+    (let ((p (cdr a))
+	  (ap calc-arg-values)
+	  (math-format-hash-args (if (= (length a) 3) 1 t)))
+      (while (and (cdr p) (equal (car p) (car ap)))
+	(setq p (cdr p) ap (cdr ap)))
+      (concat "<"
+	      (if (cdr p)
+		  (concat (math-format-flat-vector
+			   (nreverse (cdr (reverse (cdr a)))) ", " 0)
+			  " : ")
+		"")
+	      (math-format-flat-expr (nth (1- (length a)) a) 0)
+	      ">")))
+   ((eq (car a) 'var)
+    (or (and math-format-hash-args
+	     (let ((p calc-arg-values) (v 1))
+	       (while (and p (not (equal (car p) a)))
+		 (setq p (and (eq math-format-hash-args t) (cdr p))
+		       v (1+ v)))
+	       (and p
+		    (if (eq math-format-hash-args 1)
+			"#"
+		      (format "#%d" v)))))
+	(symbol-name (nth 1 a))))
+   ((and (memq (car a) '(calcFunc-string calcFunc-bstring))
+	 (= (length a) 2)
+	 (math-vectorp (nth 1 a))
+	 (math-vector-is-string (nth 1 a)))
+    (concat (substring (symbol-name (car a)) 9)
+	    "(" (math-vector-to-string (nth 1 a) t) ")"))
+   (t
+    (let ((op (math-assq2 (car a) math-standard-opers)))
+      (cond ((and op (= (length a) 3))
+	     (if (> prec (min (nth 2 op) (nth 3 op)))
+		 (concat "(" (math-format-flat-expr a 0) ")")
+	       (let ((lhs (math-format-flat-expr (nth 1 a) (nth 2 op)))
+		     (rhs (math-format-flat-expr (nth 2 a) (nth 3 op))))
+		 (setq op (car op))
+		 (if (or (equal op "^") (equal op "_"))
+		     (if (= (aref lhs 0) ?-)
+			 (setq lhs (concat "(" lhs ")")))
+		   (setq op (concat " " op " ")))
+		 (concat lhs op rhs))))
+	    ((eq (car a) 'neg)
+	     (concat "-" (math-format-flat-expr (nth 1 a) 1000)))
+	    (t
+	     (concat (math-remove-dashes
+		      (if (string-match "\\`calcFunc-\\([a-zA-Z0-9']+\\)\\'"
+					(symbol-name (car a)))
+			  (math-match-substring (symbol-name (car a)) 1)
+			(symbol-name (car a))))
+		     "("
+		     (math-format-flat-vector (cdr a) ", " 0)
+		     ")"))))))
+)
+(setq math-format-hash-args nil)
+
+(defun math-format-flat-vector (vec sep prec)
+  (if vec
+      (let ((buf (math-format-flat-expr (car vec) prec)))
+	(while (setq vec (cdr vec))
+	  (setq buf (concat buf sep (math-format-flat-expr (car vec) prec))))
+	buf)
+    "")
+)
+(setq calc-can-abbrev-vectors nil)
+
+(defun math-format-nice-expr (x w)
+  (cond ((and (eq (car-safe x) 'vec)
+	      (cdr (cdr x))
+	      (let ((ops '(vec calcFunc-assign calcFunc-condition
+			       calcFunc-schedule calcFunc-iterations
+			       calcFunc-phase)))
+		(or (memq (car-safe (nth 1 x)) ops)
+		    (memq (car-safe (nth 2 x)) ops)
+		    (memq (car-safe (nth 3 x)) ops)
+		    calc-break-vectors)))
+	 (concat "[ " (math-format-flat-vector (cdr x) ",\n  " 0) " ]"))
+	(t
+	 (let ((str (math-format-flat-expr x 0))
+	       (pos 0) p)
+	   (or (string-match "\"" str)
+	       (while (<= (setq p (+ pos w)) (length str))
+		 (while (and (> (setq p (1- p)) pos)
+			     (not (= (aref str p) ? ))))
+		 (if (> p (+ pos 5))
+		     (setq str (concat (substring str 0 p)
+				       "\n "
+				       (substring str p))
+			   pos (1+ p))
+		   (setq pos (+ pos w)))))
+	   str)))
+)
+
+(defun math-assq2 (v a)
+  (while (and a (not (eq v (nth 1 (car a)))))
+    (setq a (cdr a)))
+  (car a)
+)
+
+
+(defun math-format-number-fancy (a prec)
+  (cond
+   ((eq (car a) 'float)    ; non-decimal radix
+    (if (Math-integer-negp (nth 1 a))
+	(concat "-" (math-format-number (math-neg a)))
+      (let ((str (if (and calc-radix-formatter
+			  (not (memq calc-language '(c pascal))))
+		     (funcall calc-radix-formatter
+			      calc-number-radix
+			      (math-format-radix-float a prec))
+		   (format "%d#%s" calc-number-radix
+			   (math-format-radix-float a prec)))))
+	(if (and prec (> prec 191) (string-match "\\*" str))
+	    (concat "(" str ")")
+	  str))))
+   ((eq (car a) 'frac)
+    (setq a (math-adjust-fraction a))
+    (if (> (length (car calc-frac-format)) 1)
+	(if (Math-integer-negp (nth 1 a))
+	    (concat "-" (math-format-number (math-neg a)))
+	  (let ((q (math-idivmod (nth 1 a) (nth 2 a))))
+	    (concat (let ((calc-frac-format nil))
+		      (math-format-number (car q)))
+		    (substring (car calc-frac-format) 0 1)
+		    (let ((math-radix-explicit-format nil)
+			  (calc-frac-format nil))
+		      (math-format-number (cdr q)))
+		    (substring (car calc-frac-format) 1 2)
+		    (let ((math-radix-explicit-format nil)
+			  (calc-frac-format nil))
+		      (math-format-number (nth 2 a))))))
+      (concat (let ((calc-frac-format nil))
+		(math-format-number (nth 1 a)))
+	      (car calc-frac-format)
+	      (let ((math-radix-explicit-format nil)
+		    (calc-frac-format nil))
+		(math-format-number (nth 2 a))))))
+   ((eq (car a) 'cplx)
+    (if (math-zerop (nth 2 a))
+	(math-format-number (nth 1 a))
+      (if (null calc-complex-format)
+	  (concat "(" (math-format-number (nth 1 a))
+		  ", " (math-format-number (nth 2 a)) ")")
+	(if (math-zerop (nth 1 a))
+	    (if (math-equal-int (nth 2 a) 1)
+		(symbol-name calc-complex-format)
+	      (if (math-equal-int (nth 2 a) -1)
+		  (concat "-" (symbol-name calc-complex-format))
+		(if prec
+		    (math-compose-expr (list '* (nth 2 a) '(cplx 0 1)) prec)
+		  (concat (math-format-number (nth 2 a)) " "
+			  (symbol-name calc-complex-format)))))
+	  (if prec
+	      (math-compose-expr (list (if (math-negp (nth 2 a)) '- '+)
+				       (nth 1 a)
+				       (list 'cplx 0 (math-abs (nth 2 a))))
+				 prec)
+	    (concat (math-format-number (nth 1 a))
+		    (if (math-negp (nth 2 a)) " - " " + ")
+		    (math-format-number
+		     (list 'cplx 0 (math-abs (nth 2 a))))))))))
+   ((eq (car a) 'polar)
+    (concat "(" (math-format-number (nth 1 a))
+	    "; " (math-format-number (nth 2 a)) ")"))
+   ((eq (car a) 'hms)
+    (if (math-negp a)
+	(concat "-" (math-format-number (math-neg a)))
+      (let ((calc-number-radix 10)
+	    (calc-leading-zeros nil)
+	    (calc-group-digits nil))
+	(format calc-hms-format
+		(let ((calc-frac-format '(":" nil)))
+		  (math-format-number (nth 1 a)))
+		(let ((calc-frac-format '(":" nil)))
+		  (math-format-number (nth 2 a)))
+		(math-format-number (nth 3 a))))))
+   ((eq (car a) 'intv)
+    (concat (if (memq (nth 1 a) '(0 1)) "(" "[")
+	    (math-format-number (nth 2 a))
+	    " .. "
+	    (math-format-number (nth 3 a))
+	    (if (memq (nth 1 a) '(0 2)) ")" "]")))
+   ((eq (car a) 'sdev)
+    (concat (math-format-number (nth 1 a))
+	    " +/- "
+	    (math-format-number (nth 2 a))))
+   ((eq (car a) 'vec)
+    (math-format-flat-expr a 0))
+   (t (format "%s" a)))
+)
+
+(defun math-adjust-fraction (a)
+  (if (nth 1 calc-frac-format)
+      (progn
+	(if (Math-integerp a) (setq a (list 'frac a 1)))
+	(let ((g (math-quotient (nth 1 calc-frac-format)
+				(math-gcd (nth 2 a)
+					  (nth 1 calc-frac-format)))))
+	  (list 'frac (math-mul (nth 1 a) g) (math-mul (nth 2 a) g))))
+    a)
+)
+
+(defun math-format-bignum-fancy (a)   ; [X L]
+  (let ((str (cond ((= calc-number-radix 10)
+		    (math-format-bignum-decimal a))
+		   ((= calc-number-radix 2)
+		    (math-format-bignum-binary a))
+		   ((= calc-number-radix 8)
+		    (math-format-bignum-octal a))
+		   ((= calc-number-radix 16)
+		    (math-format-bignum-hex a))
+		   (t (math-format-bignum-radix a)))))
+    (if calc-leading-zeros
+	(let* ((calc-internal-prec 6)
+	       (digs (math-compute-max-digits (math-abs calc-word-size)
+					      calc-number-radix))
+	       (len (length str)))
+	  (if (< len digs)
+	      (setq str (concat (make-string (- digs len) ?0) str)))))
+    (if calc-group-digits
+	(let ((i (length str))
+	      (g (if (integerp calc-group-digits)
+		     (math-abs calc-group-digits)
+		   (if (memq calc-number-radix '(2 16)) 4 3))))
+	  (while (> i g)
+	    (setq i (- i g)
+		  str (concat (substring str 0 i)
+			      calc-group-char
+			      (substring str i))))
+	  str))
+    (if (and (/= calc-number-radix 10)
+	     math-radix-explicit-format)
+	(if calc-radix-formatter
+	    (funcall calc-radix-formatter calc-number-radix str)
+	  (format "%d#%s" calc-number-radix str))
+      str))
+)
+
+
+(defun math-group-float (str)   ; [X X]
+  (let* ((pt (or (string-match "[^0-9a-zA-Z]" str) (length str)))
+	 (g (if (integerp calc-group-digits) (math-abs calc-group-digits) 3))
+	 (i pt))
+    (if (and (integerp calc-group-digits) (< calc-group-digits 0))
+	(while (< (setq i (+ (1+ i) g)) (length str))
+	  (setq str (concat (substring str 0 i)
+			    calc-group-char
+			    (substring str i))
+		i (+ i (1- (length calc-group-char))))))
+    (setq i pt)
+    (while (> i g)
+      (setq i (- i g)
+	    str (concat (substring str 0 i)
+			calc-group-char
+			(substring str i))))
+    str)
+)
+
+
+
+
+
+
+
+
+(setq math-compose-level 0)
+(setq math-comp-selected nil)
+(setq math-comp-tagged nil)
+(setq math-comp-sel-hpos nil)
+(setq math-comp-sel-vpos nil)
+(setq math-comp-sel-cpos nil)
+(setq math-compose-hash-args nil)
+
+
+;;; Users can redefine this in their .emacs files.
+(defvar calc-keypad-user-menu nil
+  "If not NIL, this describes an additional menu for calc-keypad.
+It should contain a list of three rows.
+Each row should be a list of six keys.
+Each key should be a list of a label string, plus a Calc command name spec.
+A command spec is a command name symbol, a keyboard macro string, a
+list containing a numeric entry string, or nil.
+A key may contain additional specs for Inverse, Hyperbolic, and Inv+Hyp.")
+
+
+
+
+
+(run-hooks 'calc-ext-load-hook)
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/calc-fin.el	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,452 @@
+;; Calculator for GNU Emacs, part II [calc-fin.el]
+;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+;; Written by Dave Gillespie, daveg@synaptics.com.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY.  No author or distributor
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing.  Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License.   A copy of this license is
+;; supposed to have been given to you along with GNU Emacs so you
+;; can know your rights and responsibilities.  It should be in a
+;; file named COPYING.  Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+
+
+
+;; This file is autoloaded from calc-ext.el.
+(require 'calc-ext)
+
+(require 'calc-macs)
+
+(defun calc-Need-calc-fin () nil)
+
+
+;;; Financial functions.
+
+(defun calc-fin-pv ()
+  (interactive)
+  (calc-slow-wrapper
+   (if (calc-is-hyperbolic)
+       (calc-enter-result 3 "pvl" (cons 'calcFunc-pvl (calc-top-list-n 3)))
+     (if (calc-is-inverse)
+	 (calc-enter-result 3 "pvb" (cons 'calcFunc-pvb (calc-top-list-n 3)))
+       (calc-enter-result 3 "pv" (cons 'calcFunc-pv (calc-top-list-n 3))))))
+)
+
+(defun calc-fin-npv (arg)
+  (interactive "p")
+  (calc-slow-wrapper
+   (if (calc-is-inverse)
+       (calc-vector-op "npvb" 'calcFunc-npvb (1+ arg))
+     (calc-vector-op "npv" 'calcFunc-npv (1+ arg))))
+)
+
+(defun calc-fin-fv ()
+  (interactive)
+  (calc-slow-wrapper
+   (if (calc-is-hyperbolic)
+       (calc-enter-result 3 "fvl" (cons 'calcFunc-fvl (calc-top-list-n 3)))
+     (if (calc-is-inverse)
+	 (calc-enter-result 3 "fvb" (cons 'calcFunc-fvb (calc-top-list-n 3)))
+       (calc-enter-result 3 "fv" (cons 'calcFunc-fv (calc-top-list-n 3))))))
+)
+
+(defun calc-fin-pmt ()
+  (interactive)
+  (calc-slow-wrapper
+   (if (calc-is-hyperbolic)
+       (calc-enter-result 3 "fvl" (cons 'calcFunc-fvl (calc-top-list-n 3)))
+     (if (calc-is-inverse)
+	 (calc-enter-result 3 "pmtb" (cons 'calcFunc-pmtb (calc-top-list-n 3)))
+       (calc-enter-result 3 "pmt" (cons 'calcFunc-pmt (calc-top-list-n 3))))))
+)
+
+(defun calc-fin-nper ()
+  (interactive)
+  (calc-slow-wrapper
+   (if (calc-is-hyperbolic)
+       (calc-enter-result 3 "nprl" (cons 'calcFunc-nperl (calc-top-list-n 3)))
+     (if (calc-is-inverse)
+	 (calc-enter-result 3 "nprb" (cons 'calcFunc-nperb
+					   (calc-top-list-n 3)))
+       (calc-enter-result 3 "nper" (cons 'calcFunc-nper
+					 (calc-top-list-n 3))))))
+)
+
+(defun calc-fin-rate ()
+  (interactive)
+  (calc-slow-wrapper
+   (calc-pop-push-record 3
+			 (if (calc-is-hyperbolic) "ratl"
+			   (if (calc-is-inverse) "ratb" "rate"))
+			 (calc-to-percentage
+			  (calc-normalize
+			   (cons (if (calc-is-hyperbolic) 'calcFunc-ratel
+				   (if (calc-is-hyperbolic) 'calcFunc-rateb
+				     'calcFunc-rate))
+				 (calc-top-list-n 3))))))
+)
+
+(defun calc-fin-irr (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (if (calc-is-inverse)
+       (calc-vector-op "irrb" 'calcFunc-irrb arg)
+     (calc-vector-op "irr" 'calcFunc-irr arg)))
+)
+
+(defun calc-fin-sln ()
+  (interactive)
+  (calc-slow-wrapper
+   (calc-enter-result 3 "sln" (cons 'calcFunc-sln (calc-top-list-n 3))))
+)
+
+(defun calc-fin-syd ()
+  (interactive)
+  (calc-slow-wrapper
+   (calc-enter-result 4 "syd" (cons 'calcFunc-syd (calc-top-list-n 4))))
+)
+
+(defun calc-fin-ddb ()
+  (interactive)
+  (calc-slow-wrapper
+   (calc-enter-result 4 "ddb" (cons 'calcFunc-ddb (calc-top-list-n 4))))
+)
+
+
+(defun calc-to-percentage (x)
+  (cond ((Math-objectp x)
+	 (setq x (math-mul x 100))
+	 (if (Math-num-integerp x)
+	     (setq x (math-trunc x)))
+	 (list 'calcFunc-percent x))
+	((Math-vectorp x)
+	 (cons 'vec (mapcar 'calc-to-percentage (cdr x))))
+	(t x))
+)
+
+(defun calc-convert-percent ()
+  (interactive)
+  (calc-slow-wrapper
+   (calc-pop-push-record 1 "c%" (calc-to-percentage (calc-top-n 1))))
+)
+
+(defun calc-percent-change ()
+  (interactive)
+  (calc-slow-wrapper
+   (let ((res (calc-normalize (cons 'calcFunc-relch (calc-top-list 2)))))
+     (calc-pop-push-record 2 "%ch" (calc-to-percentage res))))
+)
+
+
+
+
+
+;;; Financial functions.
+
+(defun calcFunc-pv (rate num amount &optional lump)
+  (math-check-financial rate num)
+  (math-with-extra-prec 2
+    (let ((p (math-pow (math-add 1 rate) num)))
+      (math-add (math-mul amount
+			  (math-div (math-sub 1 (math-div 1 p))
+				    rate))
+		(math-div (or lump 0) p))))
+)
+(put 'calcFunc-pv 'math-expandable t)
+
+(defun calcFunc-pvl (rate num amount)
+  (calcFunc-pv rate num 0 amount)
+)
+(put 'calcFunc-pvl 'math-expandable t)
+
+(defun calcFunc-pvb (rate num amount &optional lump)
+  (math-check-financial rate num)
+  (math-with-extra-prec 2
+    (let* ((p (math-pow (math-add 1 rate) num)))
+      (math-add (math-mul amount
+			  (math-div (math-mul (math-sub 1 (math-div 1 p))
+					      (math-add 1 rate))
+				    rate))
+		(math-div (or lump 0) p))))
+)
+(put 'calcFunc-pvb 'math-expandable t)
+
+(defun calcFunc-npv (rate &rest flows)
+  (math-check-financial rate 1)
+  (math-with-extra-prec 2
+    (let* ((flat (math-flatten-many-vecs flows))
+	   (pp (math-add 1 rate))
+	   (p pp)
+	   (accum 0))
+      (while (setq flat (cdr flat))
+	(setq accum (math-add accum (math-div (car flat) p))
+	      p (math-mul p pp)))
+      accum))
+)
+(put 'calcFunc-npv 'math-expandable t)
+
+(defun calcFunc-npvb (rate &rest flows)
+  (math-check-financial rate 1)
+  (math-with-extra-prec 2
+    (let* ((flat (math-flatten-many-vecs flows))
+	   (pp (math-add 1 rate))
+	   (p 1)
+	   (accum 0))
+      (while (setq flat (cdr flat))
+	(setq accum (math-add accum (math-div (car flat) p))
+	      p (math-mul p pp)))
+      accum))
+)
+(put 'calcFunc-npvb 'math-expandable t)
+
+(defun calcFunc-fv (rate num amount &optional initial)
+  (math-check-financial rate num)
+  (math-with-extra-prec 2
+    (let ((p (math-pow (math-add 1 rate) num)))
+      (math-add (math-mul amount
+			  (math-div (math-sub p 1)
+				    rate))
+		(math-mul (or initial 0) p))))
+)
+(put 'calcFunc-fv 'math-expandable t)
+
+(defun calcFunc-fvl (rate num amount)
+  (calcFunc-fv rate num 0 amount)
+)
+(put 'calcFunc-fvl 'math-expandable t)
+
+(defun calcFunc-fvb (rate num amount &optional initial)
+  (math-check-financial rate num)
+  (math-with-extra-prec 2
+    (let ((p (math-pow (math-add 1 rate) num)))
+      (math-add (math-mul amount
+			  (math-div (math-mul (math-sub p 1)
+					      (math-add 1 rate))
+				    rate))
+		(math-mul (or initial 0) p))))
+)
+(put 'calcFunc-fvb 'math-expandable t)
+
+(defun calcFunc-pmt (rate num amount &optional lump)
+  (math-check-financial rate num)
+  (math-with-extra-prec 2
+    (let ((p (math-pow (math-add 1 rate) num)))
+      (math-div (math-mul (math-sub amount
+				    (math-div (or lump 0) p))
+			  rate)
+		(math-sub 1 (math-div 1 p)))))
+)
+(put 'calcFunc-pmt 'math-expandable t)
+
+(defun calcFunc-pmtb (rate num amount &optional lump)
+  (math-check-financial rate num)
+  (math-with-extra-prec 2
+    (let ((p (math-pow (math-add 1 rate) num)))
+      (math-div (math-mul (math-sub amount (math-div (or lump 0) p)) rate)
+		(math-mul (math-sub 1 (math-div 1 p))
+			  (math-add 1 rate)))))
+)
+(put 'calcFunc-pmtb 'math-expandable t)
+
+(defun calcFunc-nper (rate pmt amount &optional lump)
+  (math-compute-nper rate pmt amount lump nil)
+)
+(put 'calcFunc-nper 'math-expandable t)
+
+(defun calcFunc-nperb (rate pmt amount &optional lump)
+  (math-compute-nper rate pmt amount lump 'b)
+)
+(put 'calcFunc-nperb 'math-expandable t)
+
+(defun calcFunc-nperl (rate pmt amount)
+  (math-compute-nper rate pmt amount nil 'l)
+)
+(put 'calcFunc-nperl 'math-expandable t)
+
+(defun math-compute-nper (rate pmt amount lump bflag)
+  (and lump (math-zerop lump)
+       (setq lump nil))
+  (and lump (math-zerop pmt)
+       (setq amount lump
+	     lump nil
+	     bflag 'l))
+  (or (math-objectp rate) (and math-expand-formulas (null lump))
+      (math-reject-arg rate 'numberp))
+  (and (math-zerop rate)
+       (math-reject-arg rate 'nonzerop))
+  (or (math-objectp pmt) (and math-expand-formulas (null lump))
+      (math-reject-arg pmt 'numberp))
+  (or (math-objectp amount) (and math-expand-formulas (null lump))
+      (math-reject-arg amount 'numberp))
+  (if lump
+      (progn
+	(or (math-objectp lump)
+	    (math-reject-arg lump 'numberp))
+	(let ((root (math-find-root (list 'calcFunc-eq
+					  (list (if bflag
+						    'calcFunc-pvb
+						  'calcFunc-pv)
+						rate
+						'(var DUMMY var-DUMMY)
+						pmt
+						lump)
+					  amount)
+				    '(var DUMMY var-DUMMY)
+				    '(intv 3 0 100)
+				    t)))
+	  (if (math-vectorp root)
+	      (nth 1 root)
+	    root)))
+    (math-with-extra-prec 2
+      (let ((temp (if (eq bflag 'l)
+		      (math-div amount pmt)
+		    (math-sub 1 (math-div (math-mul amount rate)
+					  (if bflag
+					      (math-mul pmt (math-add 1 rate))
+					    pmt))))))
+	(if (or (math-posp temp) math-expand-formulas)
+	    (math-neg (calcFunc-log temp (math-add 1 rate)))
+	  (math-reject-arg pmt "*Payment too small to cover interest rate")))))
+)
+
+(defun calcFunc-rate (num pmt amount &optional lump)
+  (math-compute-rate num pmt amount lump 'calcFunc-pv)
+)
+
+(defun calcFunc-rateb (num pmt amount &optional lump)
+  (math-compute-rate num pmt amount lump 'calcFunc-pvb)
+)
+
+(defun math-compute-rate (num pmt amount lump func)
+  (or (math-objectp num)
+      (math-reject-arg num 'numberp))
+  (or (math-objectp pmt)
+      (math-reject-arg pmt 'numberp))
+  (or (math-objectp amount)
+      (math-reject-arg amount 'numberp))
+  (or (null lump)
+      (math-objectp lump)
+      (math-reject-arg lump 'numberp))
+  (let ((root (math-find-root (list 'calcFunc-eq
+				    (list func
+					  '(var DUMMY var-DUMMY)
+					  num
+					  pmt
+					  (or lump 0))
+				    amount)
+			      '(var DUMMY var-DUMMY)
+			      '(intv 3 (float 1 -4) 1)
+			      t)))
+    (if (math-vectorp root)
+	(nth 1 root)
+      root))
+)
+
+(defun calcFunc-ratel (num pmt amount)
+  (or (math-objectp num) math-expand-formulas
+      (math-reject-arg num 'numberp))
+  (or (math-objectp pmt) math-expand-formulas
+      (math-reject-arg pmt 'numberp))
+  (or (math-objectp amount) math-expand-formulas
+      (math-reject-arg amount 'numberp))
+  (math-with-extra-prec 2
+    (math-sub (math-pow (math-div pmt amount) (math-div 1 num)) 1))
+)
+
+(defun calcFunc-irr (&rest vecs)
+  (math-compute-irr vecs 'calcFunc-npv)
+)
+
+(defun calcFunc-irrb (&rest vecs)
+  (math-compute-irr vecs 'calcFunc-npvb)
+)
+
+(defun math-compute-irr (vecs func)
+  (let* ((flat (math-flatten-many-vecs vecs))
+	 (root (math-find-root (list func
+				     '(var DUMMY var-DUMMY)
+				     flat)
+			       '(var DUMMY var-DUMMY)
+			       '(intv 3 (float 1 -4) 1)
+			       t)))
+    (if (math-vectorp root)
+	(nth 1 root)
+      root))
+)
+
+(defun math-check-financial (rate num)
+  (or (math-objectp rate) math-expand-formulas
+      (math-reject-arg rate 'numberp))
+  (and (math-zerop rate)
+       (math-reject-arg rate 'nonzerop))
+  (or (math-objectp num) math-expand-formulas
+      (math-reject-arg num 'numberp))
+)
+
+
+(defun calcFunc-sln (cost salvage life &optional period)
+  (or (math-realp cost) math-expand-formulas
+      (math-reject-arg cost 'realp))
+  (or (math-realp salvage) math-expand-formulas
+      (math-reject-arg salvage 'realp))
+  (or (math-realp life) math-expand-formulas
+      (math-reject-arg life 'realp))
+  (if (math-zerop life) (math-reject-arg life 'nonzerop))
+  (if (and period
+	   (if (math-num-integerp period)
+	       (or (Math-lessp life period) (not (math-posp period)))
+	     (math-reject-arg period 'integerp)))
+      0
+    (math-div (math-sub cost salvage) life))
+)
+(put 'calcFunc-sln 'math-expandable t)
+
+(defun calcFunc-syd (cost salvage life period)
+  (or (math-realp cost) math-expand-formulas
+      (math-reject-arg cost 'realp))
+  (or (math-realp salvage) math-expand-formulas
+      (math-reject-arg salvage 'realp))
+  (or (math-realp life) math-expand-formulas
+      (math-reject-arg life 'realp))
+  (if (math-zerop life) (math-reject-arg life 'nonzerop))
+  (or (math-realp period) math-expand-formulas
+      (math-reject-arg period 'realp))
+  (if (or (Math-lessp life period) (not (math-posp period)))
+      0
+    (math-div (math-mul (math-sub cost salvage)
+			(math-add (math-sub life period) 1))
+	      (math-div (math-mul life (math-add life 1)) 2)))
+)
+(put 'calcFunc-syd 'math-expandable t)
+
+(defun calcFunc-ddb (cost salvage life period)
+  (if (math-messy-integerp period) (setq period (math-trunc period)))
+  (or (integerp period) (math-reject-arg period 'fixnump))
+  (or (math-realp cost) (math-reject-arg cost 'realp))
+  (or (math-realp salvage) (math-reject-arg salvage 'realp))
+  (or (math-realp life) (math-reject-arg life 'realp))
+  (if (math-zerop life) (math-reject-arg life 'nonzerop))
+  (if (or (Math-lessp life period) (<= period 0))
+      0
+    (let ((book cost)
+	  (res 0))
+      (while (>= (setq period (1- period)) 0)
+	(setq res (math-div (math-mul book 2) life)
+	      book (math-sub book res))
+	(if (Math-lessp book salvage)
+	    (setq res (math-add res (math-sub book salvage))
+		  book salvage)))
+      res))
+)
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/calc-forms.el	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,1914 @@
+;; Calculator for GNU Emacs, part II [calc-forms.el]
+;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+;; Written by Dave Gillespie, daveg@synaptics.com.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY.  No author or distributor
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing.  Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License.   A copy of this license is
+;; supposed to have been given to you along with GNU Emacs so you
+;; can know your rights and responsibilities.  It should be in a
+;; file named COPYING.  Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+
+
+
+;; This file is autoloaded from calc-ext.el.
+(require 'calc-ext)
+
+(require 'calc-macs)
+
+(defun calc-Need-calc-forms () nil)
+
+
+(defun calc-time ()
+  (interactive)
+  (calc-wrapper
+   (let ((time (current-time-string)))
+     (calc-enter-result 0 "time"
+			(list 'mod
+			      (list 'hms
+				    (string-to-int (substring time 11 13))
+				    (string-to-int (substring time 14 16))
+				    (string-to-int (substring time 17 19)))
+			      (list 'hms 24 0 0)))))
+)
+
+
+
+
+(defun calc-to-hms (arg)
+  (interactive "P")
+  (calc-wrapper
+   (if (calc-is-inverse)
+       (if (eq calc-angle-mode 'rad)
+	   (calc-unary-op ">rad" 'calcFunc-rad arg)
+	 (calc-unary-op ">deg" 'calcFunc-deg arg))
+     (calc-unary-op ">hms" 'calcFunc-hms arg)))
+)
+
+(defun calc-from-hms (arg)
+  (interactive "P")
+  (calc-invert-func)
+  (calc-to-hms arg)
+)
+
+
+(defun calc-hms-notation (fmt)
+  (interactive "sHours-minutes-seconds format (hms, @ ' \", etc.): ")
+  (calc-wrapper
+   (if (string-match "\\`\\([^,; ]+\\)\\([,; ]*\\)\\([^,; ]\\)\\([,; ]*\\)\\([^,; ]\\)\\'" fmt)
+       (progn
+	 (calc-change-mode 'calc-hms-format
+			   (concat "%s" (math-match-substring fmt 1)
+				   (math-match-substring fmt 2)
+				   "%s" (math-match-substring fmt 3)
+				   (math-match-substring fmt 4)
+				   "%s" (math-match-substring fmt 5))
+			   t)
+	 (setq-default calc-hms-format calc-hms-format))  ; for minibuffer
+     (error "Bad hours-minutes-seconds format.")))
+)
+
+(defun calc-date-notation (fmt arg)
+  (interactive "sDate format (e.g., M/D/YY h:mm:ss): \nP")
+  (calc-wrapper
+   (if (equal fmt "")
+       (setq fmt "1"))
+   (if (string-match "\\` *[0-9] *\\'" fmt)
+       (setq fmt (nth (string-to-int fmt) calc-standard-date-formats)))
+   (or (string-match "[a-zA-Z]" fmt)
+       (error "Bad date format specifier"))
+   (and arg
+	(>= (setq arg (prefix-numeric-value arg)) 0)
+	(<= arg 9)
+	(setq calc-standard-date-formats
+	      (copy-sequence calc-standard-date-formats))
+	(setcar (nthcdr arg calc-standard-date-formats) fmt))
+   (let ((case-fold-search nil))
+     (and (not (string-match "<.*>" fmt))
+	  (string-match "\\`[^hHspP]*\\([^ac-gi-lnoqrt-zAC-GI-OQRT-Z]*[bBhHmpPsS]+[^ac-gi-lnoqrt-zAC-GI-OQRT-Z]*\\)[^hHspP]*\\'" fmt)
+	  (string-match (concat "[^ac-gi-lnoqrt-zAC-GI-OQRT-Z]*"
+				(regexp-quote (math-match-substring fmt 1))
+				"[^ac-gi-lnoqrt-zAC-GI-OQRT-Z]*") fmt)
+	  (setq fmt (concat (substring fmt 0 (match-beginning 0))
+			    "<"
+			    (substring fmt (match-beginning 0) (match-end 0))
+			    ">"
+			    (substring fmt (match-end 0))))))
+   (let ((lfmt nil)
+	 (fullfmt nil)
+	 (time nil)
+	 pos pos2 sym temp)
+     (let ((case-fold-search nil))
+       (and (setq temp (string-match ":[BS]S" fmt))
+	    (aset fmt temp ?C)))
+     (while (setq pos (string-match "[<>a-zA-Z]" fmt))
+       (if (> pos 0)
+	   (setq lfmt (cons (substring fmt 0 pos) lfmt)))
+       (setq pos2 (1+ pos))
+       (cond ((= (aref fmt pos) ?\<)
+	      (and time (error "Nested <'s not allowed"))
+	      (and lfmt (setq fullfmt (nconc lfmt fullfmt)
+			      lfmt nil))
+	      (setq time t))
+	     ((= (aref fmt pos) ?\>)
+	      (or time (error "Misplaced > in format"))
+	      (and lfmt (setq fullfmt (cons (nreverse lfmt) fullfmt)
+			      lfmt nil))
+	      (setq time nil))
+	     (t
+	      (if (string-match "\\`[^a-zA-Z]*[bB][a-zA-Z]" fmt)
+		  (setq pos2 (1+ pos2)))
+	      (while (and (< pos2 (length fmt))
+			  (= (upcase (aref fmt pos2))
+			     (upcase (aref fmt (1- pos2)))))
+		(setq pos2 (1+ pos2)))
+	      (setq sym (intern (substring fmt pos pos2)))
+	      (or (memq sym '(Y YY BY YYY YYYY
+				aa AA aaa AAA aaaa AAAA
+				bb BB bbb BBB bbbb BBBB
+				M MM BM mmm Mmm Mmmm MMM MMMM
+				D DD BD d ddd bdd
+				W www Www Wwww WWW WWWW
+				h hh bh H HH BH
+				p P pp PP pppp PPPP
+				m mm bm s ss bss SS BS C
+				N n J j U b))
+		  (and (eq sym 'X) (not lfmt) (not fullfmt))
+		  (error "Bad format code: %s" sym))
+	      (and (memq sym '(bb BB bbb BBB bbbb BBBB))
+		   (setq lfmt (cons 'b lfmt)))
+	      (setq lfmt (cons sym lfmt))))
+       (setq fmt (substring fmt pos2)))
+     (or (equal fmt "")
+	 (setq lfmt (cons fmt lfmt)))
+     (and lfmt (if time
+		   (setq fullfmt (cons (nreverse lfmt) fullfmt))
+		 (setq fullfmt (nconc lfmt fullfmt))))
+     (calc-change-mode 'calc-date-format (nreverse fullfmt) t)))
+)
+
+
+(defun calc-hms-mode ()
+  (interactive)
+  (calc-wrapper
+   (calc-change-mode 'calc-angle-mode 'hms)
+   (message "Angles measured in degrees-minutes-seconds."))
+)
+
+
+(defun calc-now (arg)
+  (interactive "P")
+  (calc-date-zero-args "now" 'calcFunc-now arg)
+)
+
+(defun calc-date-part (arg)
+  (interactive "NPart code (1-9 = Y,M,D,H,M,S,Wd,Yd,Hms): ")
+  (if (or (< arg 1) (> arg 9))
+      (error "Part code out of range"))
+  (calc-wrapper
+   (calc-enter-result 1
+		      (nth arg '(nil "year" "mnth" "day" "hour" "minu"
+				      "sec" "wday" "yday" "hmst"))
+		      (list (nth arg '(nil calcFunc-year calcFunc-month
+					   calcFunc-day calcFunc-hour
+					   calcFunc-minute calcFunc-second
+					   calcFunc-weekday calcFunc-yearday
+					   calcFunc-time))
+			    (calc-top-n 1))))
+)
+
+(defun calc-date (arg)
+  (interactive "p")
+  (if (or (< arg 1) (> arg 6))
+      (error "Between one and six arguments are allowed"))
+  (calc-wrapper
+   (calc-enter-result arg "date" (cons 'calcFunc-date (calc-top-list-n arg))))
+)
+
+(defun calc-julian (arg)
+  (interactive "P")
+  (calc-date-one-arg "juln" 'calcFunc-julian arg)
+)
+
+(defun calc-unix-time (arg)
+  (interactive "P")
+  (calc-date-one-arg "unix" 'calcFunc-unixtime arg)
+)
+
+(defun calc-time-zone (arg)
+  (interactive "P")
+  (calc-date-zero-args "zone" 'calcFunc-tzone arg)
+)
+
+(defun calc-convert-time-zones (old &optional new)
+  (interactive "sFrom time zone: ")
+  (calc-wrapper
+   (if (equal old "$")
+       (calc-enter-result 3 "tzcv" (cons 'calcFunc-tzconv (calc-top-list-n 3)))
+     (if (equal old "") (setq old "local"))
+     (or new
+	 (setq new (read-string (concat "From time zone: " old
+					", to zone: "))))
+     (if (stringp old) (setq old (math-read-expr old)))
+     (if (eq (car-safe old) 'error)
+	 (error "Error in expression: " (nth 1 old)))
+     (if (equal new "") (setq new "local"))
+     (if (stringp new) (setq new (math-read-expr new)))
+     (if (eq (car-safe new) 'error)
+	 (error "Error in expression: " (nth 1 new)))
+     (calc-enter-result 1 "tzcv" (list 'calcFunc-tzconv
+				       (calc-top-n 1) old new))))
+)
+
+(defun calc-new-week (arg)
+  (interactive "P")
+  (calc-date-one-arg "nwwk" 'calcFunc-newweek arg)
+)
+
+(defun calc-new-month (arg)
+  (interactive "P")
+  (calc-date-one-arg "nwmn" 'calcFunc-newmonth arg)
+)
+
+(defun calc-new-year (arg)
+  (interactive "P")
+  (calc-date-one-arg "nwyr" 'calcFunc-newyear arg)
+)
+
+(defun calc-inc-month (arg)
+  (interactive "p")
+  (calc-date-one-arg "incm" 'calcFunc-incmonth arg)
+)
+
+(defun calc-business-days-plus (arg)
+  (interactive "P")
+  (calc-wrapper
+   (calc-binary-op "bus+" 'calcFunc-badd arg))
+)
+
+(defun calc-business-days-minus (arg)
+  (interactive "P")
+  (calc-wrapper
+   (calc-binary-op "bus-" 'calcFunc-bsub arg))
+)
+
+(defun calc-date-zero-args (prefix func arg)
+  (calc-wrapper
+   (if (consp arg)
+       (calc-enter-result 1 prefix (list func (calc-top-n 1)))
+     (calc-enter-result 0 prefix (if arg
+				     (list func (prefix-numeric-value arg))
+				   (list func)))))
+)
+
+(defun calc-date-one-arg (prefix func arg)
+  (calc-wrapper
+   (if (consp arg)
+       (calc-enter-result 2 prefix (cons func (calc-top-list-n 2)))
+     (calc-enter-result 1 prefix (if arg
+				     (list func (calc-top-n 1)
+					   (prefix-numeric-value arg))
+				   (list func (calc-top-n 1))))))
+)
+
+
+
+
+
+
+
+
+;;;; Hours-minutes-seconds forms.
+
+(defun math-normalize-hms (a)
+  (let ((h (math-normalize (nth 1 a)))
+	(m (math-normalize (nth 2 a)))
+	(s (let ((calc-internal-prec (max (- calc-internal-prec 4) 3)))
+	     (math-normalize (nth 3 a)))))
+    (if (math-negp h)
+	(progn
+	  (if (math-posp s)
+	      (setq s (math-add s -60)
+		    m (math-add m 1)))
+	  (if (math-posp m)
+	      (setq m (math-add m -60)
+		    h (math-add h 1)))
+	  (if (not (Math-lessp -60 s))
+	      (setq s (math-add s 60)
+		    m (math-add m -1)))
+	  (if (not (Math-lessp -60 m))
+	      (setq m (math-add m 60)
+		    h (math-add h -1))))
+      (if (math-negp s)
+	  (setq s (math-add s 60)
+		m (math-add m -1)))
+      (if (math-negp m)
+	  (setq m (math-add m 60)
+		h (math-add h -1)))
+      (if (not (Math-lessp s 60))
+	  (setq s (math-add s -60)
+		m (math-add m 1)))
+      (if (not (Math-lessp m 60))
+	  (setq m (math-add m -60)
+		h (math-add h 1))))
+    (if (and (eq (car-safe s) 'float)
+	     (<= (+ (math-numdigs (nth 1 s)) (nth 2 s))
+		 (- 2 calc-internal-prec)))
+	(setq s 0))
+    (list 'hms h m s))
+)
+
+;;; Convert A from ANG or current angular mode to HMS format.
+(defun math-to-hms (a &optional ang)   ; [X R] [Public]
+  (cond ((eq (car-safe a) 'hms) a)
+	((eq (car-safe a) 'sdev)
+	 (math-make-sdev (math-to-hms (nth 1 a))
+			 (math-to-hms (nth 2 a))))
+	((not (Math-numberp a))
+	 (list 'calcFunc-hms a))
+	((math-negp a)
+	 (math-neg (math-to-hms (math-neg a) ang)))
+	((eq (or ang calc-angle-mode) 'rad)
+	 (math-to-hms (math-div a (math-pi-over-180)) 'deg))
+	((memq (car-safe a) '(cplx polar)) a)
+	(t
+	 ;(setq a (let ((calc-internal-prec (max (1- calc-internal-prec) 3)))
+	 ;	    (math-normalize a)))
+	 (math-normalize
+	  (let* ((b (math-mul a 3600))
+		 (hm (math-trunc (math-div b 60)))
+		 (hmd (math-idivmod hm 60)))
+	    (list 'hms
+		  (car hmd)
+		  (cdr hmd)
+		  (math-sub b (math-mul hm 60)))))))
+)
+(defun calcFunc-hms (h &optional m s)
+  (or (Math-realp h) (math-reject-arg h 'realp))
+  (or m (setq m 0))
+  (or (Math-realp m) (math-reject-arg m 'realp))
+  (or s (setq s 0))
+  (or (Math-realp s) (math-reject-arg s 'realp))
+  (if (and (not (Math-lessp m 0)) (Math-lessp m 60)
+	   (not (Math-lessp s 0)) (Math-lessp s 60))
+      (math-add (math-to-hms h)
+		(list 'hms 0 m s))
+    (math-to-hms (math-add h
+			   (math-add (math-div (or m 0) 60)
+				     (math-div (or s 0) 3600)))
+		 'deg))
+)
+
+;;; Convert A from HMS format to ANG or current angular mode.
+(defun math-from-hms (a &optional ang)   ; [R X] [Public]
+  (cond ((not (eq (car-safe a) 'hms))
+	 (if (Math-numberp a)
+	     a
+	   (if (eq (car-safe a) 'sdev)
+	       (math-make-sdev (math-from-hms (nth 1 a) ang)
+			       (math-from-hms (nth 2 a) ang))
+	     (if (eq (or ang calc-angle-mode) 'rad)
+		 (list 'calcFunc-rad a)
+	       (list 'calcFunc-deg a)))))
+	((math-negp a)
+	 (math-neg (math-from-hms (math-neg a) ang)))
+	((eq (or ang calc-angle-mode) 'rad)
+	 (math-mul (math-from-hms a 'deg) (math-pi-over-180)))
+	(t
+	 (math-add (math-div (math-add (math-div (nth 3 a)
+						 '(float 6 1))
+				       (nth 2 a))
+			     60)
+		   (nth 1 a))))
+)
+
+
+
+;;;; Date forms.
+
+
+;;; Some of these functions are adapted from Edward Reingold's "calendar.el".
+;;; These versions are rewritten to use arbitrary-size integers.
+;;; The Julian calendar is used up to 9/2/1752, after which the Gregorian
+;;; calendar is used; the first day after 9/2/1752 is 9/14/1752.
+
+;;; A numerical date is the number of days since midnight on
+;;; the morning of January 1, 1 A.D.  If the date is a non-integer,
+;;; it represents a specific date and time.
+;;; A "dt" is a list of the form, (year month day), corresponding to
+;;; an integer code, or (year month day hour minute second), corresponding
+;;; to a non-integer code.
+
+(defun math-date-to-dt (value)
+  (if (eq (car-safe value) 'date)
+      (setq value (nth 1 value)))
+  (or (math-realp value)
+      (math-reject-arg value 'datep))
+  (let* ((parts (math-date-parts value))
+	 (date (car parts))
+	 (time (nth 1 parts))
+	 (month 1)
+	 day
+	 (year (math-quotient (math-add date (if (Math-lessp date 711859)
+						 365  ; for speed, we take
+					       -108)) ; >1950 as a special case
+			      (if (math-negp value) 366 365)))
+					; this result may be an overestimate
+	 temp)
+    (while (Math-lessp date (setq temp (math-absolute-from-date year 1 1)))
+      (setq year (math-add year -1)))
+    (if (eq year 0) (setq year -1))
+    (setq date (1+ (math-sub date temp)))
+    (and (eq year 1752) (>= date 247)
+	 (setq date (+ date 11)))
+    (setq temp (if (math-leap-year-p year)
+		   [1 32 61 92 122 153 183 214 245 275 306 336 999]
+		 [1 32 60 91 121 152 182 213 244 274 305 335 999]))
+    (while (>= date (aref temp month))
+      (setq month (1+ month)))
+    (setq day (1+ (- date (aref temp (1- month)))))
+    (if (math-integerp value)
+	(list year month day)
+      (list year month day
+	    (/ time 3600)
+	    (% (/ time 60) 60)
+	    (math-add (% time 60) (nth 2 parts)))))
+)
+
+(defun math-dt-to-date (dt)
+  (or (integerp (nth 1 dt))
+      (math-reject-arg (nth 1 dt) 'fixnump))
+  (if (or (< (nth 1 dt) 1) (> (nth 1 dt) 12))
+      (math-reject-arg (nth 1 dt) "Month value is out of range"))
+  (or (integerp (nth 2 dt))
+      (math-reject-arg (nth 2 dt) 'fixnump))
+  (if (or (< (nth 2 dt) 1) (> (nth 2 dt) 31))
+      (math-reject-arg (nth 2 dt) "Day value is out of range"))
+  (let ((date (math-absolute-from-date (car dt) (nth 1 dt) (nth 2 dt))))
+    (if (nth 3 dt)
+	(math-add (math-float date)
+		  (math-div (math-add (+ (* (nth 3 dt) 3600)
+					 (* (nth 4 dt) 60))
+				      (nth 5 dt))
+			    '(float 864 2)))
+      date))
+)
+
+(defun math-date-parts (value &optional offset)
+  (let* ((date (math-floor value))
+	 (time (math-round (math-mul (math-sub value (or offset date)) 86400)
+			   (and (> calc-internal-prec 12)
+				(- calc-internal-prec 12))))
+	 (ftime (math-floor time)))
+    (list date
+	  ftime
+	  (math-sub time ftime)))
+)
+
+
+(defun math-this-year ()
+  (string-to-int (substring (current-time-string) -4))
+)
+
+(defun math-leap-year-p (year)
+  (if (Math-lessp year 1752)
+      (if (math-negp year)
+	  (= (math-imod (math-neg year) 4) 1)
+	(= (math-imod year 4) 0))
+    (setq year (math-imod year 400))
+    (or (and (= (% year 4) 0) (/= (% year 100) 0))
+	(= year 0)))
+)
+
+(defun math-days-in-month (year month)
+  (if (and (= month 2) (math-leap-year-p year))
+      29
+    (aref [31 28 31 30 31 30 31 31 30 31 30 31] (1- month)))
+)
+
+(defun math-day-number (year month day)
+  (let ((day-of-year (+ day (* 31 (1- month)))))
+    (if (> month 2)
+	(progn
+	  (setq day-of-year (- day-of-year (/ (+ 23 (* 4 month)) 10)))
+	  (if (math-leap-year-p year)
+	      (setq day-of-year (1+ day-of-year)))))
+    (and (eq year 1752)
+	 (or (> month 9)
+	     (and (= month 9) (>= day 14)))
+	 (setq day-of-year (- day-of-year 11)))
+    day-of-year)
+)
+
+(defun math-absolute-from-date (year month day)
+  (if (eq year 0) (setq year -1))
+  (let ((yearm1 (math-sub year 1)))
+    (math-sub (math-add (math-day-number year month day)
+			(math-add (math-mul 365 yearm1)
+				  (if (math-posp year)
+				      (math-quotient yearm1 4)
+				    (math-sub 365
+					      (math-quotient (math-sub 3 year)
+							     4)))))
+	      (if (or (Math-lessp year 1753)
+		      (and (eq year 1752) (<= month 9)))
+		  1
+		(let ((correction (math-mul (math-quotient yearm1 100) 3)))
+		  (let ((res (math-idivmod correction 4)))
+		    (math-add (if (= (cdr res) 0)
+				  -1
+				0)
+			      (car res)))))))
+)
+
+
+;;; It is safe to redefine these in your .emacs file to use a different
+;;; language.
+
+(defvar math-long-weekday-names '( "Sunday" "Monday" "Tuesday" "Wednesday"
+				   "Thursday" "Friday" "Saturday" ))
+(defvar math-short-weekday-names '( "Sun" "Mon" "Tue" "Wed"
+				    "Thu" "Fri" "Sat" ))
+
+(defvar math-long-month-names '( "January" "February" "March" "April"
+				 "May" "June" "July" "August"
+				 "September" "October" "November" "December" ))
+(defvar math-short-month-names '( "Jan" "Feb" "Mar" "Apr" "May" "Jun"
+				  "Jul" "Aug" "Sep" "Oct" "Nov" "Dec" ))
+
+
+(defun math-format-date (date)
+  (if (eq (car-safe date) 'date)
+      (setq date (nth 1 date)))
+  (let ((entry (list date calc-internal-prec calc-date-format)))
+    (or (cdr (assoc entry math-format-date-cache))
+	(let* ((dt nil)
+	       (calc-group-digits nil)
+	       (calc-leading-zeros nil)
+	       (calc-number-radix 10)
+	       year month day weekday hour minute second
+	       (bc-flag nil)
+	       (fmt (apply 'concat (mapcar 'math-format-date-part
+					   calc-date-format))))
+	  (setq math-format-date-cache (cons (cons entry fmt)
+					     math-format-date-cache))
+	  (and (setq dt (nthcdr 10 math-format-date-cache))
+	       (setcdr dt nil))
+	  fmt)))
+)
+(setq math-format-date-cache nil)
+
+(defun math-format-date-part (x)
+  (cond ((stringp x)
+	 x)
+	((listp x)
+	 (if (math-integerp date)
+	     ""
+	   (apply 'concat (mapcar 'math-format-date-part x))))
+	((eq x 'X)
+	 "")
+	((eq x 'N)
+	 (math-format-number date))
+	((eq x 'n)
+	 (math-format-number (math-floor date)))
+	((eq x 'J)
+	 (math-format-number (math-add date '(float (bigpos 235 214 17) -1))))
+	((eq x 'j)
+	 (math-format-number (math-add (math-floor date) '(bigpos 424 721 1))))
+	((eq x 'U)
+	 (math-format-number (nth 1 (math-date-parts date 719164))))
+	((progn
+	   (or dt
+	       (progn
+		 (setq dt (math-date-to-dt date)
+		       year (car dt)
+		       month (nth 1 dt)
+		       day (nth 2 dt)
+		       weekday (math-mod (math-add (math-floor date) 6) 7)
+		       hour (nth 3 dt)
+		       minute (nth 4 dt)
+		       second (nth 5 dt))
+		 (and (memq 'b calc-date-format)
+		      (math-negp year)
+		      (setq year (math-neg year)
+			    bc-flag t))))
+	   (memq x '(Y YY BY)))
+	 (if (and (integerp year) (> year 1940) (< year 2040))
+	     (format (cond ((eq x 'YY) "%02d")
+			   ((eq x 'BYY) "%2d")
+			   (t "%d"))
+		     (% year 100))
+	   (if (and (natnump year) (< year 100))
+	       (format "+%d" year)
+	     (math-format-number year))))
+	((eq x 'YYY)
+	 (math-format-number year))
+	((eq x 'YYYY)
+	 (if (and (natnump year) (< year 100))
+	     (format "+%d" year)
+	   (math-format-number year)))
+	((eq x 'b) "")
+	((eq x 'aa)
+	 (and (not bc-flag) "ad"))
+	((eq x 'AA)
+	 (and (not bc-flag) "AD"))
+	((eq x 'aaa)
+	 (and (not bc-flag) "ad "))
+	((eq x 'AAA)
+	 (and (not bc-flag) "AD "))
+	((eq x 'aaaa)
+	 (and (not bc-flag) "a.d."))
+	((eq x 'AAAA)
+	 (and (not bc-flag) "A.D."))
+	((eq x 'bb)
+	 (and bc-flag "bc"))
+	((eq x 'BB)
+	 (and bc-flag "BC"))
+	((eq x 'bbb)
+	 (and bc-flag " bc"))
+	((eq x 'BBB)
+	 (and bc-flag " BC"))
+	((eq x 'bbbb)
+	 (and bc-flag "b.c."))
+	((eq x 'BBBB)
+	 (and bc-flag "B.C."))
+	((eq x 'M)
+	 (format "%d" month))
+	((eq x 'MM)
+	 (format "%02d" month))
+	((eq x 'BM)
+	 (format "%2d" month))
+	((eq x 'mmm)
+	 (downcase (nth (1- month) math-short-month-names)))
+	((eq x 'Mmm)
+	 (nth (1- month) math-short-month-names))
+	((eq x 'MMM)
+	 (upcase (nth (1- month) math-short-month-names)))
+	((eq x 'Mmmm)
+	 (nth (1- month) math-long-month-names))
+	((eq x 'MMMM)
+	 (upcase (nth (1- month) math-long-month-names)))
+	((eq x 'D)
+	 (format "%d" day))
+	((eq x 'DD)
+	 (format "%02d" day))
+	((eq x 'BD)
+	 (format "%2d" day))
+	((eq x 'W)
+	 (format "%d" weekday))
+	((eq x 'www)
+	 (downcase (nth weekday math-short-weekday-names)))
+	((eq x 'Www)
+	 (nth weekday math-short-weekday-names))
+	((eq x 'WWW)
+	 (upcase (nth weekday math-short-weekday-names)))
+	((eq x 'Wwww)
+	 (nth weekday math-long-weekday-names))
+	((eq x 'WWWW)
+	 (upcase (nth weekday math-long-weekday-names)))
+	((eq x 'd)
+	 (format "%d" (math-day-number year month day)))
+	((eq x 'ddd)
+	 (format "%03d" (math-day-number year month day)))
+	((eq x 'bdd)
+	 (format "%3d" (math-day-number year month day)))
+	((eq x 'h)
+	 (and hour (format "%d" hour)))
+	((eq x 'hh)
+	 (and hour (format "%02d" hour)))
+	((eq x 'bh)
+	 (and hour (format "%2d" hour)))
+	((eq x 'H)
+	 (and hour (format "%d" (1+ (% (+ hour 11) 12)))))
+	((eq x 'HH)
+	 (and hour (format "%02d" (1+ (% (+ hour 11) 12)))))
+	((eq x 'BH)
+	 (and hour (format "%2d" (1+ (% (+ hour 11) 12)))))
+	((eq x 'p)
+	 (and hour (if (< hour 12) "a" "p")))
+	((eq x 'P)
+	 (and hour (if (< hour 12) "A" "P")))
+	((eq x 'pp)
+	 (and hour (if (< hour 12) "am" "pm")))
+	((eq x 'PP)
+	 (and hour (if (< hour 12) "AM" "PM")))
+	((eq x 'pppp)
+	 (and hour (if (< hour 12) "a.m." "p.m.")))
+	((eq x 'PPPP)
+	 (and hour (if (< hour 12) "A.M." "P.M.")))
+	((eq x 'm)
+	 (and minute (format "%d" minute)))
+	((eq x 'mm)
+	 (and minute (format "%02d" minute)))
+	((eq x 'bm)
+	 (and minute (format "%2d" minute)))
+	((eq x 'C)
+	 (and second (not (math-zerop second))
+	      ":"))
+	((memq x '(s ss bs SS BS))
+	 (and second
+	      (not (and (memq x '(SS BS)) (math-zerop second)))
+	      (if (integerp second)
+		  (format (cond ((memq x '(ss SS)) "%02d")
+				((memq x '(bs BS)) "%2d")
+				(t "%d"))
+			  second)
+		(concat (if (Math-lessp second 10)
+			    (cond ((memq x '(ss SS)) "0")
+				  ((memq x '(bs BS)) " ")
+				  (t ""))
+			  "")
+			(let ((calc-float-format
+			       (list 'fix (min (- 12 calc-internal-prec)
+					       0))))
+			  (math-format-number second)))))))
+)
+
+
+(defun math-parse-date (str)
+  (catch 'syntax
+    (or (math-parse-standard-date str t)
+	(math-parse-standard-date str nil)
+	(and (string-match "\\`[^-+/0-9a-zA-Z]*\\([-+]?[0-9]+\\.?[0-9]*\\([eE][-+]?[0-9]+\\)?\\)[^-+/0-9a-zA-Z]*\\'" str)
+	     (list 'date (math-read-number (math-match-substring str 1))))
+	(let ((case-fold-search t)
+	      (year nil) (month nil) (day nil) (weekday nil)
+	      (hour nil) (minute nil) (second nil) (bc-flag nil)
+	      (a nil) (b nil) (c nil) (bigyear nil) temp)
+
+	  ;; Extract the time, if any.
+	  (if (or (string-match "\\([0-9][0-9]?\\):\\([0-9][0-9]?\\)\\(:\\([0-9][0-9]?\\(\\.[0-9]+\\)?\\)\\)? *\\([ap]m?\\|[ap]\\. *m\\.\\|noon\\|n\\>\\|midnight\\|mid\\>\\|m\\>\\)?" str)
+		  (string-match "\\([0-9][0-9]?\\)\\(\\)\\(\\(\\(\\)\\)\\) *\\([ap]m?\\|[ap]\\. *m\\.\\|noon\\|n\\>\\|midnight\\|mid\\>\\|m\\>\\)" str))
+	      (let ((ampm (math-match-substring str 6)))
+		(setq hour (string-to-int (math-match-substring str 1))
+		      minute (math-match-substring str 2)
+		      second (math-match-substring str 4)
+		      str (concat (substring str 0 (match-beginning 0))
+				  (substring str (match-end 0))))
+		(if (equal minute "")
+		    (setq minute 0)
+		  (setq minute (string-to-int minute)))
+		(if (equal second "")
+		    (setq second 0)
+		  (setq second (math-read-number second)))
+		(if (equal ampm "")
+		    (if (> hour 23)
+			(throw 'syntax "Hour value out of range"))
+		  (setq ampm (upcase (aref ampm 0)))
+		  (if (memq ampm '(?N ?M))
+		      (if (and (= hour 12) (= minute 0) (eq second 0))
+			  (if (eq ampm ?M) (setq hour 0))
+			(throw 'syntax
+			       "Time must be 12:00:00 in this context"))
+		    (if (or (= hour 0) (> hour 12))
+			(throw 'syntax "Hour value out of range"))
+		    (if (eq (= ampm ?A) (= hour 12))
+			(setq hour (% (+ hour 12) 24)))))))
+
+	  ;; Rewrite xx-yy-zz to xx/yy/zz to avoid seeing "-" as a minus sign.
+	  (while (string-match "[0-9a-zA-Z]\\(-\\)[0-9a-zA-Z]" str)
+	    (progn
+	      (setq str (copy-sequence str))
+	      (aset str (match-beginning 1) ?\/)))
+
+	  ;; Extract obvious month or weekday names.
+	  (if (string-match "[a-zA-Z]" str)
+	      (progn
+		(setq month (math-parse-date-word math-long-month-names))
+		(setq weekday (math-parse-date-word math-long-weekday-names))
+		(or month (setq month
+				(math-parse-date-word math-short-month-names)))
+		(or weekday (math-parse-date-word math-short-weekday-names))
+		(or hour
+		    (if (setq temp (math-parse-date-word
+				    '( "noon" "midnight" "mid" )))
+			(setq hour (if (= temp 1) 12 0) minute 0 second 0)))
+		(or (math-parse-date-word '( "ad" "a.d." ))
+		    (if (math-parse-date-word '( "bc" "b.c." ))
+			(setq bc-flag t)))
+		(if (string-match "[a-zA-Z]+" str)
+		    (throw 'syntax (format "Bad word in date: \"%s\""
+					   (math-match-substring str 0))))))
+
+	  ;; If there is a huge number other than the year, ignore it.
+	  (while (and (string-match "[-+]?0*[1-9][0-9][0-9][0-9][0-9]+" str)
+		      (setq temp (concat (substring str 0 (match-beginning 0))
+					 (substring str (match-end 0))))
+		      (string-match "[4-9][0-9]\\|[0-9][0-9][0-9]\\|[-+][0-9]+[^-]*\\'" temp))
+	    (setq str temp))
+
+	  ;; If there is a number with a sign or a large number, it is a year.
+	  (if (or (string-match "\\([-+][0-9]+\\)[^-]*\\'" str)
+		  (string-match "\\(0*[1-9][0-9][0-9]+\\)" str))
+	      (setq year (math-match-substring str 1)
+		    str (concat (substring str 0 (match-beginning 1))
+				(substring str (match-end 1)))
+		    year (math-read-number year)
+		    bigyear t))
+
+	  ;; Collect remaining numbers.
+	  (setq temp 0)
+	  (while (string-match "[0-9]+" str temp)
+	    (and c (throw 'syntax "Too many numbers in date"))
+	    (setq c (string-to-int (math-match-substring str 0)))
+	    (or b (setq b c c nil))
+	    (or a (setq a b b nil))
+	    (setq temp (match-end 0)))
+
+	  ;; Check that we have the right amount of information.
+	  (setq temp (+ (if year 1 0) (if month 1 0) (if day 1 0)
+			(if a 1 0) (if b 1 0) (if c 1 0)))
+	  (if (> temp 3)
+	      (throw 'syntax "Too many numbers in date")
+	    (if (or (< temp 2) (and year (= temp 2)))
+		(throw 'syntax "Not enough numbers in date")
+	      (if (= temp 2)   ; if year omitted, assume current year
+		  (setq year (math-this-year)))))
+
+	  ;; A large number must be a year.
+	  (or year
+	      (if (and a (or (> a 31) (< a 1)))
+		  (setq year a a b b c c nil)
+		(if (and b (or (> b 31) (< b 1)))
+		    (setq year b b c c nil)
+		  (if (and c (or (> c 31) (< c 1)))
+		      (setq year c c nil)))))
+
+	  ;; A medium-large number must be a day.
+	  (if year
+	      (if (and a (> a 12))
+		  (setq day a a b b c c nil)
+		(if (and b (> b 12))
+		    (setq day b b c c nil)
+		  (if (and c (> c 12))
+		      (setq day c c nil)))))
+
+	  ;; We may know enough to sort it out now.
+	  (if (and year day)
+	      (or month (setq month a))
+	    (if (and year month)
+		(setq day a)
+
+	      ;; Interpret order of numbers as same as for display format.
+	      (setq temp calc-date-format)
+	      (while temp
+		(cond ((not (symbolp (car temp))))
+		      ((memq (car temp) '(Y YY BY YYY YYYY))
+		       (or year (setq year a a b b c)))
+		      ((memq (car temp) '(M MM BM mmm Mmm Mmmm MMM MMMM))
+		       (or month (setq month a a b b c)))
+		      ((memq (car temp) '(D DD BD))
+		       (or day (setq day a a b b c))))
+		(setq temp (cdr temp)))
+
+	      ;; If display format was not complete, assume American style.
+	      (or month (setq month a a b b c))
+	      (or day (setq day a a b b c))
+	      (or year (setq year a a b b c))))
+
+	  (if bc-flag
+	      (setq year (math-neg (math-abs year))))
+
+	  (math-parse-date-validate year bigyear month day
+				    hour minute second))))
+)
+
+(defun math-parse-date-validate (year bigyear month day hour minute second)
+  (and (not bigyear) (natnump year) (< year 100)
+       (setq year (+ year (if (< year 40) 2000 1900))))
+  (if (eq year 0)
+      (throw 'syntax "Year value is out of range"))
+  (if (or (< month 1) (> month 12))
+      (throw 'syntax "Month value is out of range"))
+  (if (or (< day 1) (> day (math-days-in-month year month)))
+      (throw 'syntax "Day value is out of range"))
+  (and hour
+       (progn
+	 (if (or (< hour 0) (> hour 23))
+	     (throw 'syntax "Hour value is out of range"))
+	 (if (or (< minute 0) (> minute 59))
+	     (throw 'syntax "Minute value is out of range"))
+	 (if (or (math-negp second) (not (Math-lessp second 60)))
+	     (throw 'syntax "Seconds value is out of range"))))
+  (list 'date (math-dt-to-date (append (list year month day)
+				       (and hour (list hour minute second)))))
+)
+
+(defun math-parse-date-word (names &optional front)
+  (let ((n 1))
+    (while (and names (not (string-match (if (equal (car names) "Sep")
+					     "Sept?"
+					   (regexp-quote (car names)))
+					 str)))
+      (setq names (cdr names)
+	    n (1+ n)))
+    (and names
+	 (or (not front) (= (match-beginning 0) 0))
+	 (progn
+	   (setq str (concat (substring str 0 (match-beginning 0))
+			     (if front "" " ")
+			     (substring str (match-end 0))))
+	   n)))
+)
+
+(defun math-parse-standard-date (str with-time)
+  (let ((case-fold-search t)
+	(okay t) num
+	(fmt calc-date-format) this next (gnext nil)
+	(year nil) (month nil) (day nil) (bigyear nil) (yearday nil)
+	(hour nil) (minute nil) (second nil) (bc-flag nil))
+    (while (and fmt okay)
+      (setq this (car fmt)
+	    fmt (setq fmt (or (cdr fmt)
+				(prog1
+				    gnext
+				  (setq gnext nil))))
+	    next (car fmt))
+      (if (consp next) (setq next (car next)))
+      (or (cond ((listp this)
+		 (or (not with-time)
+		     (not this)
+		     (setq gnext fmt
+			   fmt this)))
+		((stringp this)
+		 (if (and (<= (length this) (length str))
+			  (equal this
+				 (substring str 0 (length this))))
+		     (setq str (substring str (length this)))))
+		((eq this 'X)
+		 t)
+		((memq this '(n N j J))
+		 (and (string-match "\\`[-+]?[0-9.]+\\([eE][-+]?[0-9]+\\)?" str)
+		      (setq num (math-match-substring str 0)
+			    str (substring str (match-end 0))
+			    num (math-date-to-dt (math-read-number num))
+			    num (math-sub num
+					  (if (memq this '(n N))
+					      0
+					    (if (or (eq this 'j)
+						    (math-integerp num))
+						'(bigpos 424 721 1)
+					      '(float (bigpos 235 214 17)
+						      -1))))
+			    hour (or (nth 3 num) hour)
+			    minute (or (nth 4 num) minute)
+			    second (or (nth 5 num) second)
+			    year (car num)
+			    month (nth 1 num)
+			    day (nth 2 num))))
+		((eq this 'U)
+		 (and (string-match "\\`[-+]?[0-9]+" str)
+		      (setq num (math-match-substring str 0)
+			    str (substring str (match-end 0))
+			    num (math-date-to-dt
+				 (math-add 719164
+					   (math-div (math-read-number num)
+						     '(float 864 2))))
+			    hour (nth 3 num)
+			    minute (nth 4 num)
+			    second (nth 5 num)
+			    year (car num)
+			    month (nth 1 num)
+			    day (nth 2 num))))
+		((memq this '(mmm Mmm MMM))
+		 (setq month (math-parse-date-word math-short-month-names t)))
+		((memq this '(Mmmm MMMM))
+		 (setq month (math-parse-date-word math-long-month-names t)))
+		((memq this '(www Www WWW))
+		 (math-parse-date-word math-short-weekday-names t))
+		((memq this '(Wwww WWWW))
+		 (math-parse-date-word math-long-weekday-names t))
+		((memq this '(p P))
+		 (if (string-match "\\`a" str)
+		     (setq hour (if (= hour 12) 0 hour)
+			   str (substring str 1))
+		   (if (string-match "\\`p" str)
+		       (setq hour (if (= hour 12) 12 (% (+ hour 12) 24))
+			     str (substring str 1)))))
+		((memq this '(pp PP pppp PPPP))
+		 (if (string-match "\\`am\\|a\\.m\\." str)
+		     (setq hour (if (= hour 12) 0 hour)
+			   str (substring str (match-end 0)))
+		   (if (string-match "\\`pm\\|p\\.m\\." str)
+		       (setq hour (if (= hour 12) 12 (% (+ hour 12) 24))
+			     str (substring str (match-end 0))))))
+		((memq this '(Y YY BY YYY YYYY))
+		 (and (if (memq next '(MM DD ddd hh HH mm ss SS))
+			  (if (memq this '(Y YY BYY))
+			      (string-match "\\` *[0-9][0-9]" str)
+			    (string-match "\\`[0-9][0-9][0-9][0-9]" str))
+			(string-match "\\`[-+]?[0-9]+" str))
+		      (setq year (math-match-substring str 0)
+			    bigyear (or (eq this 'YYY)
+					(memq (aref str 0) '(?\+ ?\-)))
+			    str (substring str (match-end 0))
+			    year (math-read-number year))))
+		((eq this 'b)
+		 t)
+		((memq this '(aa AA aaaa AAAA))
+		 (if (string-match "\\` *\\(ad\\|a\\.d\\.\\)" str)
+		     (setq str (substring str (match-end 0)))))
+		((memq this '(aaa AAA))
+		 (if (string-match "\\` *ad *" str)
+		     (setq str (substring str (match-end 0)))))
+		((memq this '(bb BB bbb BBB bbbb BBBB))
+		 (if (string-match "\\` *\\(bc\\|b\\.c\\.\\)" str)
+		     (setq str (substring str (match-end 0))
+			   bc-flag t)))
+		((memq this '(s ss bs SS BS))
+		 (and (if (memq next '(YY YYYY MM DD hh HH mm))
+			  (string-match "\\` *[0-9][0-9]\\(\\.[0-9]+\\)?" str)
+			(string-match "\\` *[0-9][0-9]?\\(\\.[0-9]+\\)?" str))
+		      (setq second (math-match-substring str 0)
+			    str (substring str (match-end 0))
+			    second (math-read-number second))))
+		((eq this 'C)
+		 (if (string-match "\\`:[0-9][0-9]" str)
+		     (setq str (substring str 1))
+		   t))
+		((or (not (if (and (memq this '(ddd MM DD hh HH mm))
+				   (memq next '(YY YYYY MM DD ddd
+						   hh HH mm ss SS)))
+			      (if (eq this 'ddd)
+				  (string-match "\\` *[0-9][0-9][0-9]" str)
+				(string-match "\\` *[0-9][0-9]" str))
+			    (string-match "\\` *[0-9]+" str)))
+		     (and (setq num (string-to-int
+				     (math-match-substring str 0))
+				str (substring str (match-end 0)))
+			  nil))
+		 nil)
+		((eq this 'W)
+		 (and (>= num 0) (< num 7)))
+		((memq this '(d ddd bdd))
+		 (setq yearday num))
+		((memq this '(M MM BM))
+		 (setq month num))
+		((memq this '(D DD BD))
+		 (setq day num))
+		((memq this '(h hh bh H HH BH))
+		 (setq hour num))
+		((memq this '(m mm bm))
+		 (setq minute num)))
+	  (setq okay nil)))
+    (if yearday
+	(if (and month day)
+	    (setq yearday nil)
+	  (setq month 1 day 1)))
+    (if (and okay (equal str ""))
+	(and month day (or (not (or hour minute second))
+			   (and hour minute))
+	     (progn
+	       (or year (setq year (math-this-year)))
+	       (or second (setq second 0))
+	       (if bc-flag
+		   (setq year (math-neg (math-abs year))))
+	       (setq day (math-parse-date-validate year bigyear month day
+						   hour minute second))
+	       (if yearday
+		   (setq day (math-add day (1- yearday))))
+	       day))))
+)
+
+
+(defun calcFunc-now (&optional zone)
+  (let ((date (let ((calc-date-format nil))
+		(math-parse-date (current-time-string)))))
+    (if (consp date)
+	(if zone
+	    (math-add date (math-div (math-sub (calcFunc-tzone nil date)
+					       (calcFunc-tzone zone date))
+				     '(float 864 2)))
+	  date)
+      (calc-record-why "*Unable to interpret current date from system")
+      (append (list 'calcFunc-now) (and zone (list zone)))))
+)
+
+(defun calcFunc-year (date)
+  (car (math-date-to-dt date))
+)
+
+(defun calcFunc-month (date)
+  (nth 1 (math-date-to-dt date))
+)
+
+(defun calcFunc-day (date)
+  (nth 2 (math-date-to-dt date))
+)
+
+(defun calcFunc-weekday (date)
+  (if (eq (car-safe date) 'date)
+      (setq date (nth 1 date)))
+  (or (math-realp date)
+      (math-reject-arg date 'datep))
+  (math-mod (math-add (math-floor date) 6) 7)
+)
+
+(defun calcFunc-yearday (date)
+  (let ((dt (math-date-to-dt date)))
+    (math-day-number (car dt) (nth 1 dt) (nth 2 dt)))
+)
+
+(defun calcFunc-hour (date)
+  (if (eq (car-safe date) 'hms)
+      (nth 1 date)
+    (or (nth 3 (math-date-to-dt date)) 0))
+)
+
+(defun calcFunc-minute (date)
+  (if (eq (car-safe date) 'hms)
+      (nth 2 date)
+    (or (nth 4 (math-date-to-dt date)) 0))
+)
+
+(defun calcFunc-second (date)
+  (if (eq (car-safe date) 'hms)
+      (nth 3 date)
+    (or (nth 5 (math-date-to-dt date)) 0))
+)
+
+(defun calcFunc-time (date)
+  (let ((dt (math-date-to-dt date)))
+    (if (nth 3 dt)
+	(cons 'hms (nthcdr 3 dt))
+      (list 'hms 0 0 0)))
+)
+
+(defun calcFunc-date (date &optional month day hour minute second)
+  (and (math-messy-integerp month) (setq month (math-trunc month)))
+  (and month (not (integerp month)) (math-reject-arg month 'fixnump))
+  (and (math-messy-integerp day) (setq day (math-trunc day)))
+  (and day (not (integerp day)) (math-reject-arg day 'fixnump))
+  (if (and (eq (car-safe hour) 'hms) (not minute))
+      (setq second (nth 3 hour)
+	    minute (nth 2 hour)
+	    hour (nth 1 hour)))
+  (and (math-messy-integerp hour) (setq hour (math-trunc hour)))
+  (and hour (not (integerp hour)) (math-reject-arg hour 'fixnump))
+  (and (math-messy-integerp minute) (setq minute (math-trunc minute)))
+  (and minute (not (integerp minute)) (math-reject-arg minute 'fixnump))
+  (and (math-messy-integerp second) (setq second (math-trunc second)))
+  (and second (not (math-realp second)) (math-reject-arg second 'realp))
+  (if month
+      (progn
+	(and (math-messy-integerp date) (setq date (math-trunc date)))
+	(and date (not (math-integerp date)) (math-reject-arg date 'integerp))
+	(if day
+	    (if hour
+		(list 'date (math-dt-to-date (list date month day hour
+						   (or minute 0)
+						   (or second 0))))
+	      (list 'date (math-dt-to-date (list date month day))))
+	  (list 'date (math-dt-to-date (list (math-this-year) date month)))))
+    (if (math-realp date)
+	(list 'date date)
+      (if (eq (car date) 'date)
+	  (nth 1 date)
+	(math-reject-arg date 'datep))))
+)
+
+(defun calcFunc-julian (date &optional zone)
+  (if (math-realp date)
+      (list 'date (if (math-integerp date)
+		      (math-sub date '(bigpos 424 721 1))
+		    (setq date (math-sub date '(float (bigpos 235 214 17) -1)))
+		    (math-sub date (math-div (calcFunc-tzone zone date)
+					     '(float 864 2)))))
+    (if (eq (car date) 'date)
+	(math-add (nth 1 date) (if (math-integerp (nth 1 date))
+				   '(bigpos 424 721 1)
+				 (math-add '(float (bigpos 235 214 17) -1)
+					   (math-div (calcFunc-tzone zone date)
+						     '(float 864 2)))))
+      (math-reject-arg date 'datep)))
+)
+
+(defun calcFunc-unixtime (date &optional zone)
+  (if (math-realp date)
+      (progn
+	(setq date (math-add 719164 (math-div date '(float 864 2))))
+	(list 'date (math-sub date (math-div (calcFunc-tzone zone date)
+					     '(float 864 2)))))
+    (if (eq (car date) 'date)
+	(math-add (nth 1 (math-date-parts (nth 1 date) 719164))
+		  (calcFunc-tzone zone date))
+      (math-reject-arg date 'datep)))
+)
+
+(defun calcFunc-tzone (&optional zone date)
+  (if zone
+      (cond ((math-realp zone)
+	     (math-round (math-mul zone 3600)))
+	    ((eq (car zone) 'hms)
+	     (math-round (math-mul (math-from-hms zone 'deg) 3600)))
+	    ((eq (car zone) '+)
+	     (math-add (calcFunc-tzone (nth 1 zone) date)
+		       (calcFunc-tzone (nth 2 zone) date)))
+	    ((eq (car zone) '-)
+	     (math-sub (calcFunc-tzone (nth 1 zone) date)
+		       (calcFunc-tzone (nth 2 zone) date)))
+	    ((eq (car zone) 'var)
+	     (let ((name (upcase (symbol-name (nth 1 zone))))
+		   found)
+	       (if (setq found (assoc name math-tzone-names))
+		   (calcFunc-tzone (math-add (nth 1 found)
+					     (if (integerp (nth 2 found))
+						 (nth 2 found)
+					       (or
+						(math-daylight-savings-adjust
+						 date (car found))
+						0)))
+				   date)
+		 (if (equal name "LOCAL")
+		     (calcFunc-tzone nil date)
+		   (math-reject-arg zone "*Unrecognized time zone name")))))
+	    (t (math-reject-arg zone "*Expected a time zone")))
+    (if (calc-var-value 'var-TimeZone)
+	(calcFunc-tzone (calc-var-value 'var-TimeZone) date)
+      (let ((p math-tzone-names)
+	    (offset 0)
+	    (tz '(var error var-error)))
+	(save-excursion
+	  (set-buffer (get-buffer-create " *Calc Temporary*"))
+	  (erase-buffer)
+	  (call-process "date" nil t)
+	  (goto-char 1)
+	  (let ((case-fold-search t))
+	    (while (and p (not (search-forward (car (car p)) nil t)))
+	      (setq p (cdr p))))
+	  (if (looking-at "\\([-+][0-9]?[0-9]\\)\\([0-9][0-9]\\)?\\(\\'\\|[^0-9]\\)")
+	      (setq offset (math-add
+			    (string-to-int (buffer-substring
+					    (match-beginning 1)
+					    (match-end 1)))
+			    (if (match-beginning 2)
+				(math-div (string-to-int (buffer-substring
+							  (match-beginning 2)
+							  (match-end 2)))
+					  60)
+			      0)))))
+	(if p
+	    (progn
+	      (setq p (car p))
+	      ;; Try to convert to a generalized time zone.
+	      (if (integerp (nth 2 p))
+		  (let ((gen math-tzone-names))
+		    (while (and gen
+				(not (equal (nth 2 (car gen)) (car p)))
+				(not (equal (nth 3 (car gen)) (car p)))
+				(not (equal (nth 4 (car gen)) (car p)))
+				(not (equal (nth 5 (car gen)) (car p))))
+		      (setq gen (cdr gen)))
+		    (and gen
+			 (setq gen (car gen))
+			 (equal (math-daylight-savings-adjust nil (car gen))
+				(nth 2 p))
+			 (setq p gen))))
+	      (setq tz (math-add (list 'var
+				       (intern (car p))
+				       (intern (concat "var-" (car p))))
+				 offset))))
+	(kill-buffer " *Calc Temporary*")
+	(setq var-TimeZone tz)
+	(calc-refresh-evaltos 'var-TimeZone)
+	(calcFunc-tzone tz date))))
+)
+
+;;; Note: Longer names must appear before shorter names which are
+;;;       substrings of them.
+(defvar math-tzone-names
+  '( ( "MEGT" -1 "MET" "METDST" )                          ; Middle Europe
+     ( "METDST" -1 -1 ) ( "MET" -1 0 )
+     ( "MEGZ" -1 "MEZ" "MESZ" ) ( "MEZ" -1 0 ) ( "MESZ" -1 -1 )
+     ( "WEGT" 0 "WET" "WETDST" )                           ; Western Europe
+     ( "WETDST" 0 -1 ) ( "WET" 0 0 )
+     ( "BGT" 0 "GMT" "BST" ) ( "GMT" 0 0 ) ( "BST" 0 -1 )  ; Britain
+     ( "NGT" (float 35 -1) "NST" "NDT" )                   ; Newfoundland
+     ( "NST" (float 35 -1) 0 ) ( "NDT" (float 35 -1) -1 )
+     ( "AGT" 4 "AST" "ADT" ) ( "AST" 4 0 ) ( "ADT" 4 -1 )  ; Atlantic
+     ( "EGT" 5 "EST" "EDT" ) ( "EST" 5 0 ) ( "EDT" 5 -1 )  ; Eastern
+     ( "CGT" 6 "CST" "CDT" ) ( "CST" 6 0 ) ( "CDT" 6 -1 )  ; Central
+     ( "MGT" 7 "MST" "MDT" ) ( "MST" 7 0 ) ( "MDT" 7 -1 )  ; Mountain
+     ( "PGT" 8 "PST" "PDT" ) ( "PST" 8 0 ) ( "PDT" 8 -1 )  ; Pacific
+     ( "YGT" 9 "YST" "YDT" ) ( "YST" 9 0 ) ( "YDT" 9 -1 )  ; Yukon
+))
+
+
+(defun math-daylight-savings-adjust (date zone &optional dt)
+  (or date (setq date (nth 1 (calcFunc-now))))
+  (let (bump)
+    (if (eq (car-safe date) 'date)
+	(setq bump 0
+	      date (nth 1 date))
+      (if (and date (math-realp date))
+	  (let ((zadj (assoc zone math-tzone-names)))
+	    (if zadj (setq bump -1
+			   date (math-sub date (math-div (nth 1 zadj)
+							 '(float 24 0))))))
+	(math-reject-arg date 'datep)))
+    (setq date (math-float date))
+    (or dt (setq dt (math-date-to-dt date)))
+    (and math-daylight-savings-hook
+	 (funcall math-daylight-savings-hook date dt zone bump)))
+)
+
+(defun calcFunc-dsadj (date &optional zone)
+  (if zone
+      (or (eq (car-safe zone) 'var)
+	  (math-reject-arg zone "*Time zone variable expected"))
+    (setq zone (or (calc-var-value 'var-TimeZone)
+		   (progn
+		     (calcFunc-tzone)
+		     (calc-var-value 'var-TimeZone)))))
+  (setq zone (and (eq (car-safe zone) 'var)
+		  (upcase (symbol-name (nth 1 zone)))))
+  (let ((zadj (assoc zone math-tzone-names)))
+    (or zadj (math-reject-arg zone "*Unrecognized time zone name"))
+    (if (integerp (nth 2 zadj))
+	(nth 2 zadj)
+      (math-daylight-savings-adjust date zone)))
+)
+
+(defun calcFunc-tzconv (date z1 z2)
+  (if (math-realp date)
+      (nth 1 (calcFunc-tzconv (list 'date date) z1 z2))
+    (calcFunc-unixtime (calcFunc-unixtime date z1) z2))
+)
+
+(defvar math-daylight-savings-hook 'math-std-daylight-savings)
+
+(defun math-std-daylight-savings (date dt zone bump)
+  "Standard North American daylight savings algorithm.
+This implements the rules for the U.S. and Canada as of 1987.
+Daylight savings begins on the first Sunday of April at 2 a.m.,
+and ends on the last Sunday of October at 2 a.m."
+  (cond ((< (nth 1 dt) 4) 0)
+	((= (nth 1 dt) 4)
+	 (let ((sunday (math-prev-weekday-in-month date dt 7 0)))
+	   (cond ((< (nth 2 dt) sunday) 0)
+		 ((= (nth 2 dt) sunday)
+		  (if (>= (nth 3 dt) (+ 3 bump)) -1 0))
+		 (t -1))))
+	((< (nth 1 dt) 10) -1)
+	((= (nth 1 dt) 10)
+	 (let ((sunday (math-prev-weekday-in-month date dt 31 0)))
+	   (cond ((< (nth 2 dt) sunday) -1)
+		 ((= (nth 2 dt) sunday)
+		  (if (>= (nth 3 dt) (+ 2 bump)) 0 -1))
+		 (t 0))))
+	(t 0))
+)
+
+;;; Compute the day (1-31) of the WDAY (0-6) on or preceding the given
+;;; day of the given month.
+(defun math-prev-weekday-in-month (date dt day wday)
+  (or day (setq day (nth 2 dt)))
+  (if (> day (math-days-in-month (car dt) (nth 1 dt)))
+      (setq day (math-days-in-month (car dt) (nth 1 dt))))
+  (let ((zeroth (math-sub (math-floor date) (nth 2 dt))))
+    (math-sub (nth 1 (calcFunc-newweek (math-add zeroth day))) zeroth))
+)
+
+(defun calcFunc-pwday (date &optional day weekday)
+  (if (eq (car-safe date) 'date)
+      (setq date (nth 1 date)))
+  (or (math-realp date)
+      (math-reject-arg date 'datep))
+  (if (math-messy-integerp day) (setq day (math-trunc day)))
+  (or (integerp day) (math-reject-arg day 'fixnump))
+  (if (= day 0) (setq day 31))
+  (and (or (< day 7) (> day 31)) (math-reject-arg day 'range))
+  (math-prev-weekday-in-month date (math-date-to-dt date) day (or weekday 0))
+)
+
+
+(defun calcFunc-newweek (date &optional weekday)
+  (if (eq (car-safe date) 'date)
+      (setq date (nth 1 date)))
+  (or (math-realp date)
+      (math-reject-arg date 'datep))
+  (or weekday (setq weekday 0))
+  (and (math-messy-integerp weekday) (setq weekday (math-trunc weekday)))
+  (or (integerp weekday) (math-reject-arg weekday 'fixnump))
+  (and (or (< weekday 0) (> weekday 6)) (math-reject-arg weekday 'range))
+  (setq date (math-floor date))
+  (list 'date (math-sub date (calcFunc-weekday (math-sub date weekday))))
+)
+
+(defun calcFunc-newmonth (date &optional day)
+  (or day (setq day 1))
+  (and (math-messy-integerp day) (setq day (math-trunc day)))
+  (or (integerp day) (math-reject-arg day 'fixnump))
+  (and (or (< day 0) (> day 31)) (math-reject-arg day 'range))
+  (let ((dt (math-date-to-dt date)))
+    (if (or (= day 0) (> day (math-days-in-month (car dt) (nth 1 dt))))
+	(setq day (math-days-in-month (car dt) (nth 1 dt))))
+    (and (eq (car dt) 1752) (= (nth 1 dt) 9)
+	 (if (>= day 14) (setq day (- day 11))))
+    (list 'date (math-add (math-dt-to-date (list (car dt) (nth 1 dt) 1))
+			  (1- day))))
+)
+
+(defun calcFunc-newyear (date &optional day)
+  (or day (setq day 1))
+  (and (math-messy-integerp day) (setq day (math-trunc day)))
+  (or (integerp day) (math-reject-arg day 'fixnump))
+  (let ((dt (math-date-to-dt date)))
+    (if (and (>= day 0) (<= day 366))
+	(let ((max (if (eq (car dt) 1752) 355
+		     (if (math-leap-year-p (car dt)) 366 365))))
+	  (if (or (= day 0) (> day max)) (setq day max))
+	  (list 'date (math-add (math-dt-to-date (list (car dt) 1 1))
+				(1- day))))
+      (if (and (>= day -12) (<= day -1))
+	  (list 'date (math-dt-to-date (list (car dt) (- day) 1)))
+	(math-reject-arg day 'range))))
+)
+
+(defun calcFunc-incmonth (date &optional step)
+  (or step (setq step 1))
+  (and (math-messy-integerp step) (setq step (math-trunc step)))
+  (or (math-integerp step) (math-reject-arg step 'integerp))
+  (let* ((dt (math-date-to-dt date))
+	 (year (car dt))
+	 (month (math-add (1- (nth 1 dt)) step))
+	 (extra (calcFunc-idiv month 12))
+	 (day (nth 2 dt)))
+    (setq month (1+ (math-sub month (math-mul extra 12)))
+	  year (math-add year extra)
+	  day (min day (math-days-in-month year month)))
+    (and (math-posp (car dt)) (not (math-posp year))
+	 (setq year (math-sub year 1)))   ; did we go past the year zero?
+    (and (math-negp (car dt)) (not (math-negp year))
+	 (setq year (math-add year 1)))
+    (list 'date (math-dt-to-date
+		 (cons year (cons month (cons day (cdr (cdr (cdr dt)))))))))
+)
+
+(defun calcFunc-incyear (date &optional step)
+  (calcFunc-incmonth date (math-mul (or step 1) 12))
+)
+
+
+
+(defun calcFunc-bsub (a b)
+  (or (eq (car-safe a) 'date)
+      (math-reject-arg a 'datep))
+  (if (eq (car-safe b) 'date)
+      (if (math-lessp (nth 1 a) (nth 1 b))
+	  (math-neg (calcFunc-bsub b a))
+	(math-setup-holidays b)
+	(let* ((da (math-to-business-day a))
+	       (db (math-to-business-day b)))
+	  (math-add (math-sub (car da) (car db))
+		    (if (and (cdr db) (not (cdr da))) 1 0))))
+    (calcFunc-badd a (math-neg b)))
+)
+
+(defun calcFunc-badd (a b)
+  (if (eq (car-safe b) 'date)
+      (if (eq (car-safe a) 'date)
+	  (math-reject-arg nil "*Illegal combination in date arithmetic")
+	(calcFunc-badd b a))
+    (if (eq (car-safe a) 'date)
+	(if (Math-realp b)
+	    (if (Math-zerop b)
+		a
+	      (let* ((d (math-to-business-day a))
+		     (bb (math-add (car d)
+				   (if (and (cdr d) (Math-posp b))
+				       (math-sub b 1) b))))
+		(or (math-from-business-day bb)
+		    (calcFunc-badd a b))))
+	  (if (eq (car-safe b) 'hms)
+	      (let ((hours (nth 7 math-holidays-cache)))
+		(setq b (math-div (math-from-hms b 'deg) 24))
+		(if hours
+		    (setq b (math-div b (cdr hours))))
+		(calcFunc-badd a b))
+	    (math-reject-arg nil "*Illegal combination in date arithmetic")))
+      (math-reject-arg a 'datep)))
+)
+
+(defun calcFunc-holiday (a)
+  (if (cdr (math-to-business-day a)) 1 0)
+)
+
+
+(setq math-holidays-cache nil)
+(setq math-holidays-cache-tag t)
+
+
+;;; Compute the number of business days since Jan 1, 1 AD.
+
+(defun math-to-business-day (date &optional need-year)
+  (if (eq (car-safe date) 'date)
+      (setq date (nth 1 date)))
+  (or (Math-realp date)
+      (math-reject-arg date 'datep))
+  (let* ((day (math-floor date))
+	 (time (math-sub date day))
+	 (dt (math-date-to-dt day))
+	 (delta 0)
+	 (holiday nil))
+    (or (not need-year) (eq (car dt) need-year)
+	(math-reject-arg (list 'date day) "*Generated holiday has wrong year"))
+    (math-setup-holidays date)
+    (let ((days (car math-holidays-cache)))
+      (while (and (setq days (cdr days)) (< (car days) day))
+	(setq delta (1+ delta)))
+      (and days (= day (car days))
+	   (setq holiday t)))
+    (let* ((weekdays (nth 3 math-holidays-cache))
+	   (weeks (1- (/ (+ day 6) 7)))
+	   (wkday (- day 1 (* weeks 7))))
+      (setq delta (+ delta (* weeks (length weekdays))))
+      (while (and weekdays (< (car weekdays) wkday))
+	(setq weekdays (cdr weekdays)
+	      delta (1+ delta)))
+      (and weekdays (eq wkday (car weekdays))
+	   (setq holiday t)))
+    (let ((hours (nth 7 math-holidays-cache)))
+      (if hours
+	  (progn
+	    (setq time (math-div (math-sub time (car hours)) (cdr hours)))
+	    (if (Math-lessp time 0) (setq time 0))
+	    (or (Math-lessp time 1)
+		(setq time
+		      (math-sub 1
+				(math-div 1 (math-mul 86400 (cdr hours)))))))))
+    (cons (math-add (math-sub day delta) time) holiday))
+)
+
+
+;;; Compute the date a certain number of business days since Jan 1, 1 AD.
+;;; If this returns NIL, holiday table was adjusted; redo calculation.
+
+(defun math-from-business-day (num)
+  (let* ((day (math-floor num))
+	 (time (math-sub num day)))
+    (or (integerp day)
+	(math-reject-arg nil "*Date is outside valid range"))
+    (math-setup-holidays)
+    (let ((days (nth 1 math-holidays-cache))
+	  (delta 0))
+      (while (and (setq days (cdr days)) (< (car days) day))
+	(setq delta (1+ delta)))
+      (setq day (+ day delta)))
+    (let* ((weekdays (nth 3 math-holidays-cache))
+	   (bweek (- 7 (length weekdays)))
+	   (weeks (1- (/ (+ day (1- bweek)) bweek)))
+	   (wkday (- day 1 (* weeks bweek)))
+	   (w 0))
+      (setq day (+ day (* weeks (length weekdays))))
+      (while (if (memq w weekdays)
+		 (setq day (1+ day))
+	       (> (setq wkday (1- wkday)) 0))
+	(setq w (1+ w)))
+      (let ((hours (nth 7 math-holidays-cache)))
+	(if hours
+	    (setq time (math-add (math-mul time (cdr hours)) (car hours)))))
+      (and (not (math-setup-holidays day))
+	   (list 'date (math-add day time)))))
+)
+
+
+(defun math-setup-holidays (&optional date)
+  (or (eq (calc-var-value 'var-Holidays) math-holidays-cache-tag)
+      (let ((h (calc-var-value 'var-Holidays))
+	    (wdnames '( (sun . 0) (mon . 1) (tue . 2) (wed . 3)
+			(thu . 4) (fri . 5) (sat . 6) ))
+	    (days nil) (weekdays nil) (exprs nil) (limit nil) (hours nil))
+	(or (math-vectorp h)
+	    (math-reject-arg h "*Holidays variable must be a vector"))
+	(while (setq h (cdr h))
+	  (cond ((or (and (eq (car-safe (car h)) 'date)
+			  (integerp (nth 1 (car h))))
+		     (and (eq (car-safe (car h)) 'intv)
+			  (eq (car-safe (nth 2 (car h))) 'date))
+		     (eq (car-safe (car h)) 'vec))
+		 (setq days (cons (car h) days)))
+		((and (eq (car-safe (car h)) 'var)
+		      (assq (nth 1 (car h)) wdnames))
+		 (setq weekdays (cons (cdr (assq (nth 1 (car h)) wdnames))
+				      weekdays)))
+		((and (eq (car-safe (car h)) 'intv)
+		      (eq (car-safe (nth 2 (car h))) 'hms)
+		      (eq (car-safe (nth 3 (car h))) 'hms))
+		 (if hours
+		     (math-reject-arg
+		      (car h) "*Only one hours interval allowed in Holidays"))
+		 (setq hours (math-div (car h) '(hms 24 0 0)))
+		 (if (or (Math-lessp (nth 2 hours) 0)
+			 (Math-lessp 1 (nth 3 hours)))
+		     (math-reject-arg
+		      (car h) "*Hours interval out of range"))
+		 (setq hours (cons (nth 2 hours)
+				   (math-sub (nth 3 hours) (nth 2 hours))))
+		 (if (Math-zerop (cdr hours))
+		     (math-reject-arg
+		      (car h) "*Degenerate hours interval")))
+		((or (and (eq (car-safe (car h)) 'intv)
+			  (Math-integerp (nth 2 (car h)))
+			  (Math-integerp (nth 3 (car h))))
+		     (and (integerp (car h))
+			  (> (car h) 1900) (< (car h) 2100)))
+		 (if limit
+		     (math-reject-arg
+		      (car h) "*Only one limit allowed in Holidays"))
+		 (setq limit (calcFunc-vint (car h) '(intv 3 1 2737)))
+		 (if (equal limit '(vec))
+		     (math-reject-arg (car h) "*Limit is out of range")))
+		((or (math-expr-contains (car h) '(var y var-y))
+		     (math-expr-contains (car h) '(var m var-m)))
+		 (setq exprs (cons (car h) exprs)))
+		(t (math-reject-arg
+		    (car h) "*Holidays must contain a vector of holidays"))))
+	(if (= (length weekdays) 7)
+	    (math-reject-arg nil "*Too many weekend days"))
+	(setq math-holidays-cache (list (list -1)  ; 0: days list
+					(list -1)  ; 1: inverse-days list
+					nil        ; 2: exprs
+					(sort weekdays '<)
+					(or limit '(intv 3 1 2737))
+					nil        ; 5: (lo.hi) expanded years
+					(cons exprs days)
+					hours)     ; 7: business hours
+	      math-holidays-cache-tag (calc-var-value 'var-Holidays))))
+  (if date
+      (let ((year (calcFunc-year date))
+	    (limits (nth 5 math-holidays-cache))
+	    (done nil))
+	(or (eq (calcFunc-in year (nth 4 math-holidays-cache)) 1)
+	    (progn
+	      (or (eq (car-safe date) 'date) (setq date (list 'date date)))
+	      (math-reject-arg date "*Date is outside valid range")))
+	(unwind-protect
+	    (let ((days (nth 6 math-holidays-cache)))
+	      (if days
+		  (let ((year nil))   ; see below
+		    (setcar (nthcdr 6 math-holidays-cache) nil)
+		    (math-setup-add-holidays (cons 'vec (cdr days)))
+		    (setcar (nthcdr 2 math-holidays-cache) (car days))))
+	      (cond ((not (nth 2 math-holidays-cache))
+		     (setq done t)
+		     nil)
+		    ((not limits)
+		     (setcar (nthcdr 5 math-holidays-cache) (cons year year))
+		     (math-setup-year-holidays year)
+		     (setq done t))
+		    ((< year (car limits))
+		     (message "Computing holidays, %d .. %d"
+			      year (1- (car limits)))
+		     (calc-set-command-flag 'clear-message)
+		     (while (< year (car limits))
+		       (setcar limits (1- (car limits)))
+		       (math-setup-year-holidays (car limits)))
+		     (setq done t))
+		    ((> year (cdr limits))
+		     (message "Computing holidays, %d .. %d"
+			      (1+ (cdr limits)) year)
+		     (calc-set-command-flag 'clear-message)
+		     (while (> year (cdr limits))
+		       (setcdr limits (1+ (cdr limits)))
+		       (math-setup-year-holidays (cdr limits)))
+		     (setq done t))
+		    (t
+		     (setq done t)
+		     nil)))
+	  (or done (setq math-holidays-cache-tag t)))))
+)
+
+(defun math-setup-year-holidays (year)
+  (let ((exprs (nth 2 math-holidays-cache)))
+    (while exprs
+      (let* ((var-y year)
+	     (var-m nil)
+	     (expr (math-evaluate-expr (car exprs))))
+	(if (math-expr-contains expr '(var m var-m))
+	    (let ((var-m 0))
+	      (while (<= (setq var-m (1+ var-m)) 12)
+		(math-setup-add-holidays (math-evaluate-expr expr))))
+	  (math-setup-add-holidays expr)))
+      (setq exprs (cdr exprs))))
+)
+
+(defun math-setup-add-holidays (days)   ; uses "year"
+  (cond ((eq (car-safe days) 'vec)
+	 (while (setq days (cdr days))
+	   (math-setup-add-holidays (car days))))
+	((eq (car-safe days) 'intv)
+	 (let ((day (math-ceiling (nth 2 days))))
+	   (or (eq (calcFunc-in day days) 1)
+	       (setq day (math-add day 1)))
+	   (while (eq (calcFunc-in day days) 1)
+	     (math-setup-add-holidays day)
+	     (setq day (math-add day 1)))))
+	((eq (car-safe days) 'date)
+	 (math-setup-add-holidays (nth 1 days)))
+	((eq days 0))
+	((integerp days)
+	 (let ((b (math-to-business-day days year)))
+	   (or (cdr b)   ; don't register holidays twice!
+	       (let ((prev (car math-holidays-cache))
+		     (iprev (nth 1 math-holidays-cache)))
+		 (while (and (cdr prev) (< (nth 1 prev) days))
+		   (setq prev (cdr prev) iprev (cdr iprev)))
+		 (setcdr prev (cons days (cdr prev)))
+		 (setcdr iprev (cons (car b) (cdr iprev)))
+		 (while (setq iprev (cdr iprev))
+		   (setcar iprev (1- (car iprev))))))))
+	((Math-realp days)
+	 (math-reject-arg (list 'date days) "*Invalid holiday value"))
+	(t
+	 (math-reject-arg days "*Holiday formula failed to evaluate")))
+)
+
+
+
+
+;;;; Error forms.
+
+;;; Build a standard deviation form.  [X X X]
+(defun math-make-sdev (x sigma)
+  (if (memq (car-safe x) '(date mod sdev intv vec))
+      (math-reject-arg x 'realp))
+  (if (memq (car-safe sigma) '(date mod sdev intv vec))
+      (math-reject-arg sigma 'realp))
+  (if (or (Math-negp sigma) (memq (car-safe sigma) '(cplx polar)))
+      (setq sigma (math-abs sigma)))
+  (if (and (Math-zerop sigma) (Math-scalarp x))
+      x
+    (list 'sdev x sigma))
+)
+(defun calcFunc-sdev (x sigma)
+  (math-make-sdev x sigma)
+)
+
+
+
+;;;; Modulo forms.
+
+(defun math-normalize-mod (a)
+  (let ((n (math-normalize (nth 1 a)))
+	(m (math-normalize (nth 2 a))))
+    (if (and (math-anglep n) (math-anglep m) (math-posp m))
+	(math-make-mod n m)
+      (math-normalize (list 'calcFunc-makemod n m))))
+)
+
+;;; Build a modulo form.  [N R R]
+(defun math-make-mod (n m)
+  (setq calc-previous-modulo m)
+  (and n
+       (cond ((not (Math-anglep m))
+	      (math-reject-arg m 'anglep))
+	     ((not (math-posp m))
+	      (math-reject-arg m 'posp))
+	     ((Math-anglep n)
+	      (if (or (Math-negp n)
+		      (not (Math-lessp n m)))
+		  (list 'mod (math-mod n m) m)
+		(list 'mod n m)))
+	     ((memq (car n) '(+ - / vec neg))
+	      (math-normalize
+	       (cons (car n)
+		     (mapcar (function (lambda (x) (math-make-mod x m)))
+			     (cdr n)))))
+	     ((and (eq (car n) '*) (Math-anglep (nth 1 n)))
+	      (math-mul (math-make-mod (nth 1 n) m) (nth 2 n)))
+	     ((memq (car n) '(* ^ var calcFunc-subscr))
+	      (math-mul (math-make-mod 1 m) n))
+	     (t (math-reject-arg n 'anglep))))
+)
+(defun calcFunc-makemod (n m)
+  (math-make-mod n m)
+)
+
+
+
+;;;; Interval forms.
+
+;;; Build an interval form.  [X S X X]
+(defun math-make-intv (mask lo hi)
+  (if (memq (car-safe lo) '(cplx polar mod sdev intv vec))
+      (math-reject-arg lo 'realp))
+  (if (memq (car-safe hi) '(cplx polar mod sdev intv vec))
+      (math-reject-arg hi 'realp))
+  (or (eq (eq (car-safe lo) 'date) (eq (car-safe hi) 'date))
+      (math-reject-arg (if (eq (car-safe lo) 'date) hi lo) 'datep))
+  (if (and (or (Math-realp lo) (eq (car lo) 'date))
+	   (or (Math-realp hi) (eq (car hi) 'date)))
+      (let ((cmp (math-compare lo hi)))
+	(if (= cmp 0)
+	    (if (= mask 3)
+		lo
+	      (list 'intv mask lo hi))
+	  (if (> cmp 0)
+	      (if (= mask 3)
+		  (list 'intv 2 lo lo)
+		(list 'intv mask lo lo))
+	    (list 'intv mask lo hi))))
+    (list 'intv mask lo hi))
+)
+(defun calcFunc-intv (mask lo hi)
+  (if (math-messy-integerp mask) (setq mask (math-trunc mask)))
+  (or (natnump mask) (math-reject-arg mask 'fixnatnump))
+  (or (<= mask 3) (math-reject-arg mask 'range))
+  (math-make-intv mask lo hi)
+)
+
+(defun math-sort-intv (mask lo hi)
+  (if (Math-lessp hi lo)
+      (math-make-intv (aref [0 2 1 3] mask) hi lo)
+    (math-make-intv mask lo hi))
+)
+
+
+
+
+(defun math-combine-intervals (a am b bm c cm d dm)
+  (let (res)
+    (if (= (setq res (math-compare a c)) 1)
+	(setq a c am cm)
+      (if (= res 0)
+	  (setq am (or am cm))))
+    (if (= (setq res (math-compare b d)) -1)
+	(setq b d bm dm)
+      (if (= res 0)
+	  (setq bm (or bm dm))))
+    (math-make-intv (+ (if am 2 0) (if bm 1 0)) a b))
+)
+
+
+(defun math-div-mod (a b m)   ; [R R R R]  (Returns nil if no solution)
+  (and (Math-integerp a) (Math-integerp b) (Math-integerp m)
+       (let ((u1 1) (u3 b) (v1 0) (v3 m))
+	 (while (not (eq v3 0))   ; See Knuth sec 4.5.2, exercise 15
+	   (let* ((q (math-idivmod u3 v3))
+		  (t1 (math-sub u1 (math-mul v1 (car q)))))
+	     (setq u1 v1  u3 v3  v1 t1  v3 (cdr q))))
+	 (let ((q (math-idivmod a u3)))
+	   (and (eq (cdr q) 0)
+		(math-mod (math-mul (car q) u1) m)))))
+)
+
+(defun math-mod-intv (a b)
+  (let* ((q1 (math-floor (math-div (nth 2 a) b)))
+	 (q2 (math-floor (math-div (nth 3 a) b)))
+	 (m1 (math-sub (nth 2 a) (math-mul q1 b)))
+	 (m2 (math-sub (nth 3 a) (math-mul q2 b))))
+    (cond ((equal q1 q2)
+	   (math-sort-intv (nth 1 a) m1 m2))
+	  ((and (math-equal-int (math-sub q2 q1) 1)
+		(math-zerop m2)
+		(memq (nth 1 a) '(0 2)))
+	   (math-make-intv (nth 1 a) m1 b))
+	  (t
+	   (math-make-intv 2 0 b))))
+)
+
+
+(defun math-read-angle-brackets ()
+  (let* ((last (or (math-check-for-commas t) (length exp-str)))
+	 (str (substring exp-str exp-pos last))
+	 (res
+	  (if (string-match "\\` *\\([a-zA-Z#][a-zA-Z0-9#]* *,? *\\)*:" str)
+	      (let ((str1 (substring str 0 (1- (match-end 0))))
+		    (str2 (substring str (match-end 0)))
+		    (calc-hashes-used 0))
+		(setq str1 (math-read-expr (concat "[" str1 "]")))
+		(if (eq (car-safe str1) 'error)
+		    str1
+		  (setq str2 (math-read-expr str2))
+		  (if (eq (car-safe str2) 'error)
+		      str2
+		    (append '(calcFunc-lambda) (cdr str1) (list str2)))))
+	    (if (string-match "#" str)
+		(let ((calc-hashes-used 0))
+		  (and (setq str (math-read-expr str))
+		       (if (eq (car-safe str) 'error)
+			   str
+			 (append '(calcFunc-lambda)
+				 (calc-invent-args calc-hashes-used)
+				 (list str)))))
+	      (math-parse-date str)))))
+    (if (stringp res)
+	(throw 'syntax res))
+    (if (eq (car-safe res) 'error)
+	(throw 'syntax (nth 2 res)))
+    (setq exp-pos (1+ last))
+    (math-read-token)
+    res)
+)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/calc-frac.el	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,235 @@
+;; Calculator for GNU Emacs, part II [calc-frac.el]
+;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+;; Written by Dave Gillespie, daveg@synaptics.com.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY.  No author or distributor
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing.  Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License.   A copy of this license is
+;; supposed to have been given to you along with GNU Emacs so you
+;; can know your rights and responsibilities.  It should be in a
+;; file named COPYING.  Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+
+
+
+;; This file is autoloaded from calc-ext.el.
+(require 'calc-ext)
+
+(require 'calc-macs)
+
+(defun calc-Need-calc-frac () nil)
+
+
+(defun calc-fdiv (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-binary-op ":" 'calcFunc-fdiv arg 1))
+)
+
+
+(defun calc-fraction (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (let ((func (if (calc-is-hyperbolic) 'calcFunc-frac 'calcFunc-pfrac)))
+     (if (eq arg 0)
+	 (calc-enter-result 2 "frac" (list func
+					   (calc-top-n 2)
+					   (calc-top-n 1)))
+       (calc-enter-result 1 "frac" (list func
+					 (calc-top-n 1)
+					 (prefix-numeric-value (or arg 0)))))))
+)
+
+
+(defun calc-over-notation (fmt)
+  (interactive "sFraction separator (:, ::, /, //, :/): ")
+  (calc-wrapper
+   (if (string-match "\\`\\([^ 0-9][^ 0-9]?\\)[0-9]*\\'" fmt)
+       (let ((n nil))
+	 (if (/= (match-end 0) (match-end 1))
+	     (setq n (string-to-int (substring fmt (match-end 1)))
+		   fmt (math-match-substring fmt 1)))
+	 (if (eq n 0) (error "Bad denominator"))
+	 (calc-change-mode 'calc-frac-format (list fmt n) t))
+     (error "Bad fraction separator format.")))
+)
+
+(defun calc-slash-notation (n)
+  (interactive "P")
+  (calc-wrapper
+   (calc-change-mode 'calc-frac-format (if n '("//" nil) '("/" nil)) t))
+)
+
+
+(defun calc-frac-mode (n)
+  (interactive "P")
+  (calc-wrapper
+   (calc-change-mode 'calc-prefer-frac n nil t)
+   (message (if calc-prefer-frac
+		"Integer division will now generate fractions."
+	      "Integer division will now generate floating-point results.")))
+)
+
+
+
+
+
+;;;; Fractions.
+
+;;; Build a normalized fraction.  [R I I]
+;;; (This could probably be implemented more efficiently than using
+;;;  the plain gcd algorithm.)
+(defun math-make-frac (num den)
+  (if (Math-integer-negp den)
+      (setq num (math-neg num)
+	    den (math-neg den)))
+  (let ((gcd (math-gcd num den)))
+    (if (eq gcd 1)
+	(if (eq den 1)
+	    num
+	  (list 'frac num den))
+      (if (equal gcd den)
+	  (math-quotient num gcd)
+	(list 'frac (math-quotient num gcd) (math-quotient den gcd)))))
+)
+
+(defun calc-add-fractions (a b)
+  (if (eq (car-safe a) 'frac)
+      (if (eq (car-safe b) 'frac)
+	  (math-make-frac (math-add (math-mul (nth 1 a) (nth 2 b))
+				    (math-mul (nth 2 a) (nth 1 b)))
+			  (math-mul (nth 2 a) (nth 2 b)))
+	(math-make-frac (math-add (nth 1 a)
+				  (math-mul (nth 2 a) b))
+			(nth 2 a)))
+    (math-make-frac (math-add (math-mul a (nth 2 b))
+			      (nth 1 b))
+		    (nth 2 b)))
+)
+
+(defun calc-mul-fractions (a b)
+  (if (eq (car-safe a) 'frac)
+      (if (eq (car-safe b) 'frac)
+	  (math-make-frac (math-mul (nth 1 a) (nth 1 b))
+			  (math-mul (nth 2 a) (nth 2 b)))
+	(math-make-frac (math-mul (nth 1 a) b)
+			(nth 2 a)))
+    (math-make-frac (math-mul a (nth 1 b))
+		    (nth 2 b)))
+)
+
+(defun calc-div-fractions (a b)
+  (if (eq (car-safe a) 'frac)
+      (if (eq (car-safe b) 'frac)
+	  (math-make-frac (math-mul (nth 1 a) (nth 2 b))
+			  (math-mul (nth 2 a) (nth 1 b)))
+	(math-make-frac (nth 1 a)
+			(math-mul (nth 2 a) b)))
+    (math-make-frac (math-mul a (nth 2 b))
+		    (nth 1 b)))
+)
+
+
+
+
+;;; Convert a real value to fractional form.  [T R I; T R F] [Public]
+(defun calcFunc-frac (a &optional tol)
+  (or tol (setq tol 0))
+  (cond ((Math-ratp a)
+	 a)
+	((memq (car a) '(cplx polar vec hms date sdev intv mod))
+	 (cons (car a) (mapcar (function
+				(lambda (x)
+				  (calcFunc-frac x tol)))
+			       (cdr a))))
+	((Math-messy-integerp a)
+	 (math-trunc a))
+	((Math-negp a)
+	 (math-neg (calcFunc-frac (math-neg a) tol)))
+	((not (eq (car a) 'float))
+	 (if (math-infinitep a)
+	     a
+	   (if (math-provably-integerp a)
+	       a
+	     (math-reject-arg a 'numberp))))
+	((integerp tol)
+	 (if (<= tol 0)
+	     (setq tol (+ tol calc-internal-prec)))
+	 (calcFunc-frac a (list 'float 5
+				(- (+ (math-numdigs (nth 1 a))
+				      (nth 2 a))
+				   (1+ tol)))))
+	((not (eq (car tol) 'float))
+	 (if (Math-realp tol)
+	     (calcFunc-frac a (math-float tol))
+	   (math-reject-arg tol 'realp)))
+	((Math-negp tol)
+	 (calcFunc-frac a (math-neg tol)))
+	((Math-zerop tol)
+	 (calcFunc-frac a 0))
+	((not (math-lessp-float tol '(float 1 0)))
+	 (math-trunc a))
+	((Math-zerop a)
+	 0)
+	(t
+	 (let ((cfrac (math-continued-fraction a tol))
+	       (calc-prefer-frac t))
+	   (math-eval-continued-fraction cfrac))))
+)
+
+(defun math-continued-fraction (a tol)
+  (let ((calc-internal-prec (+ calc-internal-prec 2)))
+    (let ((cfrac nil)
+	  (aa a)
+	  (calc-prefer-frac nil)
+	  int)
+      (while (or (null cfrac)
+		 (and (not (Math-zerop aa))
+		      (not (math-lessp-float
+			    (math-abs
+			     (math-sub a
+				       (let ((f (math-eval-continued-fraction
+						 cfrac)))
+					 (math-working "Fractionalize" f)
+					 f)))
+			    tol))))
+	(setq int (math-trunc aa)
+	      aa (math-sub aa int)
+	      cfrac (cons int cfrac))
+	(or (Math-zerop aa)
+	    (setq aa (math-div 1 aa))))
+      cfrac))
+)
+
+(defun math-eval-continued-fraction (cf)
+  (let ((n (car cf))
+	(d 1)
+	temp)
+    (while (setq cf (cdr cf))
+      (setq temp (math-add (math-mul (car cf) n) d)
+	    d n
+	    n temp))
+    (math-div n d))
+)
+
+
+
+(defun calcFunc-fdiv (a b)   ; [R I I] [Public]
+  (if (Math-num-integerp a)
+      (if (Math-num-integerp b)
+	  (if (Math-zerop b)
+	      (math-reject-arg a "*Division by zero")
+	    (math-make-frac (math-trunc a) (math-trunc b)))
+	(math-reject-arg b 'integerp))
+    (math-reject-arg a 'integerp))
+)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/calc-funcs.el	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,1034 @@
+;; Calculator for GNU Emacs, part II [calc-funcs.el]
+;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+;; Written by Dave Gillespie, daveg@synaptics.com.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY.  No author or distributor
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing.  Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License.   A copy of this license is
+;; supposed to have been given to you along with GNU Emacs so you
+;; can know your rights and responsibilities.  It should be in a
+;; file named COPYING.  Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+
+
+
+;; This file is autoloaded from calc-ext.el.
+(require 'calc-ext)
+
+(require 'calc-macs)
+
+(defun calc-Need-calc-funcs () nil)
+
+
+(defun calc-inc-gamma (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (if (calc-is-inverse)
+       (if (calc-is-hyperbolic)
+	   (calc-binary-op "gamG" 'calcFunc-gammaG arg)
+	 (calc-binary-op "gamQ" 'calcFunc-gammaQ arg))
+       (if (calc-is-hyperbolic)
+	   (calc-binary-op "gamg" 'calcFunc-gammag arg)
+	 (calc-binary-op "gamP" 'calcFunc-gammaP arg))))
+)
+
+(defun calc-erf (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (if (calc-is-inverse)
+       (calc-unary-op "erfc" 'calcFunc-erfc arg)
+     (calc-unary-op "erf" 'calcFunc-erf arg)))
+)
+
+(defun calc-erfc (arg)
+  (interactive "P")
+  (calc-invert-func)
+  (calc-erf arg)
+)
+
+(defun calc-beta (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-binary-op "beta" 'calcFunc-beta arg))
+)
+
+(defun calc-inc-beta ()
+  (interactive)
+  (calc-slow-wrapper
+   (if (calc-is-hyperbolic)
+       (calc-enter-result 3 "betB" (cons 'calcFunc-betaB (calc-top-list-n 3)))
+     (calc-enter-result 3 "betI" (cons 'calcFunc-betaI (calc-top-list-n 3)))))
+)
+
+(defun calc-bessel-J (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-binary-op "besJ" 'calcFunc-besJ arg))
+)
+
+(defun calc-bessel-Y (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-binary-op "besY" 'calcFunc-besY arg))
+)
+
+(defun calc-bernoulli-number (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (if (calc-is-hyperbolic)
+       (calc-binary-op "bern" 'calcFunc-bern arg)
+     (calc-unary-op "bern" 'calcFunc-bern arg)))
+)
+
+(defun calc-euler-number (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (if (calc-is-hyperbolic)
+       (calc-binary-op "eulr" 'calcFunc-euler arg)
+     (calc-unary-op "eulr" 'calcFunc-euler arg)))
+)
+
+(defun calc-stirling-number (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (if (calc-is-hyperbolic)
+       (calc-binary-op "str2" 'calcFunc-stir2 arg)
+     (calc-binary-op "str1" 'calcFunc-stir1 arg)))
+)
+
+(defun calc-utpb ()
+  (interactive)
+  (calc-prob-dist "b" 3)
+)
+
+(defun calc-utpc ()
+  (interactive)
+  (calc-prob-dist "c" 2)
+)
+
+(defun calc-utpf ()
+  (interactive)
+  (calc-prob-dist "f" 3)
+)
+
+(defun calc-utpn ()
+  (interactive)
+  (calc-prob-dist "n" 3)
+)
+
+(defun calc-utpp ()
+  (interactive)
+  (calc-prob-dist "p" 2)
+)
+
+(defun calc-utpt ()
+  (interactive)
+  (calc-prob-dist "t" 2)
+)
+
+(defun calc-prob-dist (letter nargs)
+  (calc-slow-wrapper
+   (if (calc-is-inverse)
+       (calc-enter-result nargs (concat "ltp" letter)
+			  (append (list (intern (concat "calcFunc-ltp" letter))
+					(calc-top-n 1))
+				  (calc-top-list-n (1- nargs) 2)))
+     (calc-enter-result nargs (concat "utp" letter)
+			(append (list (intern (concat "calcFunc-utp" letter))
+				      (calc-top-n 1))
+				(calc-top-list-n (1- nargs) 2)))))
+)
+
+
+
+
+;;; Sources:  Numerical Recipes, Press et al;
+;;;           Handbook of Mathematical Functions, Abramowitz & Stegun.
+
+
+;;; Gamma function.
+
+(defun calcFunc-gamma (x)
+  (or (math-numberp x) (math-reject-arg x 'numberp))
+  (calcFunc-fact (math-add x -1))
+)
+
+(defun math-gammap1-raw (x &optional fprec nfprec)   ; compute gamma(1 + x)
+  (or fprec
+      (setq fprec (math-float calc-internal-prec)
+	    nfprec (math-float (- calc-internal-prec))))
+  (cond ((math-lessp-float (calcFunc-re x) fprec)
+	 (if (math-lessp-float (calcFunc-re x) nfprec)
+	     (math-neg (math-div
+			(math-pi)
+			(math-mul (math-gammap1-raw
+				   (math-add (math-neg x)
+					     '(float -1 0))
+				   fprec nfprec)
+				  (math-sin-raw
+				   (math-mul (math-pi) x)))))
+	   (let ((xplus1 (math-add x '(float 1 0))))
+	     (math-div (math-gammap1-raw xplus1 fprec nfprec) xplus1))))
+	((and (math-realp x)
+	      (math-lessp-float '(float 736276 0) x))
+	 (math-overflow))
+	(t   ; re(x) now >= 10.0
+	 (let ((xinv (math-div 1 x))
+	       (lnx (math-ln-raw x)))
+	   (math-mul (math-sqrt-two-pi)
+		     (math-exp-raw
+		      (math-gamma-series
+		       (math-sub (math-mul (math-add x '(float 5 -1))
+					   lnx)
+				 x)
+		       xinv
+		       (math-sqr xinv)
+		       '(float 0 0)
+		       2))))))
+)
+
+(defun math-gamma-series (sum x xinvsqr oterm n)
+  (math-working "gamma" sum)
+  (let* ((bn (math-bernoulli-number n))
+	 (term (math-mul (math-div-float (math-float (nth 1 bn))
+					 (math-float (* (nth 2 bn)
+							(* n (1- n)))))
+			 x))
+	 (next (math-add sum term)))
+    (if (math-nearly-equal sum next)
+	next
+      (if (> n (* 2 calc-internal-prec))
+	  (progn
+	    ;; Need this because series eventually diverges for large enough n.
+	    (calc-record-why
+	     "*Gamma computation stopped early, not all digits may be valid")
+	    next)
+	(math-gamma-series next (math-mul x xinvsqr) xinvsqr term (+ n 2)))))
+)
+
+
+;;; Incomplete gamma function.
+
+(defun calcFunc-gammaP (a x)
+  (if (equal x '(var inf var-inf))
+      '(float 1 0)
+    (math-inexact-result)
+    (or (Math-numberp a) (math-reject-arg a 'numberp))
+    (or (math-numberp x) (math-reject-arg x 'numberp))
+    (if (and (math-num-integerp a)
+	     (integerp (setq a (math-trunc a)))
+	     (> a 0) (< a 20))
+	(math-sub 1 (calcFunc-gammaQ a x))
+      (let ((math-current-gamma-value (calcFunc-gamma a)))
+	(math-div (calcFunc-gammag a x) math-current-gamma-value))))
+)
+
+(defun calcFunc-gammaQ (a x)
+  (if (equal x '(var inf var-inf))
+      '(float 0 0)
+    (math-inexact-result)
+    (or (Math-numberp a) (math-reject-arg a 'numberp))
+    (or (math-numberp x) (math-reject-arg x 'numberp))
+    (if (and (math-num-integerp a)
+	     (integerp (setq a (math-trunc a)))
+	     (> a 0) (< a 20))
+	(let ((n 0)
+	      (sum '(float 1 0))
+	      (term '(float 1 0)))
+	  (math-with-extra-prec 1
+	    (while (< (setq n (1+ n)) a)
+	      (setq term (math-div (math-mul term x) n)
+		    sum (math-add sum term))
+	      (math-working "gamma" sum))
+	    (math-mul sum (calcFunc-exp (math-neg x)))))
+      (let ((math-current-gamma-value (calcFunc-gamma a)))
+	(math-div (calcFunc-gammaG a x) math-current-gamma-value))))
+)
+
+(defun calcFunc-gammag (a x)
+  (if (equal x '(var inf var-inf))
+      (calcFunc-gamma a)
+    (math-inexact-result)
+    (or (Math-numberp a) (math-reject-arg a 'numberp))
+    (or (Math-numberp x) (math-reject-arg x 'numberp))
+    (math-with-extra-prec 2
+      (setq a (math-float a))
+      (setq x (math-float x))
+      (if (or (math-negp (calcFunc-re a))
+	      (math-lessp-float (calcFunc-re x)
+				(math-add-float (calcFunc-re a)
+						'(float 1 0))))
+	  (math-inc-gamma-series a x)
+	(math-sub (or math-current-gamma-value (calcFunc-gamma a))
+		  (math-inc-gamma-cfrac a x)))))
+)
+(setq math-current-gamma-value nil)
+
+(defun calcFunc-gammaG (a x)
+  (if (equal x '(var inf var-inf))
+      '(float 0 0)
+    (math-inexact-result)
+    (or (Math-numberp a) (math-reject-arg a 'numberp))
+    (or (Math-numberp x) (math-reject-arg x 'numberp))
+    (math-with-extra-prec 2
+      (setq a (math-float a))
+      (setq x (math-float x))
+      (if (or (math-negp (calcFunc-re a))
+	      (math-lessp-float (calcFunc-re x)
+				(math-add-float (math-abs-approx a)
+						'(float 1 0))))
+	  (math-sub (or math-current-gamma-value (calcFunc-gamma a))
+		    (math-inc-gamma-series a x))
+	(math-inc-gamma-cfrac a x))))
+)
+
+(defun math-inc-gamma-series (a x)
+  (if (Math-zerop x)
+      '(float 0 0)
+    (math-mul (math-exp-raw (math-sub (math-mul a (math-ln-raw x)) x))
+	      (math-with-extra-prec 2
+		(let ((start (math-div '(float 1 0) a)))
+		  (math-inc-gamma-series-step start start a x)))))
+)
+
+(defun math-inc-gamma-series-step (sum term a x)
+  (math-working "gamma" sum)
+  (setq a (math-add a '(float 1 0))
+	term (math-div (math-mul term x) a))
+  (let ((next (math-add sum term)))
+    (if (math-nearly-equal sum next)
+	next
+      (math-inc-gamma-series-step next term a x)))
+)
+
+(defun math-inc-gamma-cfrac (a x)
+  (if (Math-zerop x)
+      (or math-current-gamma-value (calcFunc-gamma a))
+    (math-mul (math-exp-raw (math-sub (math-mul a (math-ln-raw x)) x))
+	      (math-inc-gamma-cfrac-step '(float 1 0) x
+					 '(float 0 0) '(float 1 0)
+					 '(float 1 0) '(float 1 0) '(float 0 0)
+					 a x)))
+)
+
+(defun math-inc-gamma-cfrac-step (a0 a1 b0 b1 n fac g a x)
+  (let ((ana (math-sub n a))
+	(anf (math-mul n fac)))
+    (setq n (math-add n '(float 1 0))
+	  a0 (math-mul (math-add a1 (math-mul a0 ana)) fac)
+	  b0 (math-mul (math-add b1 (math-mul b0 ana)) fac)
+	  a1 (math-add (math-mul x a0) (math-mul anf a1))
+	  b1 (math-add (math-mul x b0) (math-mul anf b1)))
+    (if (math-zerop a1)
+	(math-inc-gamma-cfrac-step a0 a1 b0 b1 n fac g a x)
+      (setq fac (math-div '(float 1 0) a1))
+      (let ((next (math-mul b1 fac)))
+	(math-working "gamma" next)
+	(if (math-nearly-equal next g)
+	    next
+	  (math-inc-gamma-cfrac-step a0 a1 b0 b1 n fac next a x)))))
+)
+
+
+;;; Error function.
+
+(defun calcFunc-erf (x)
+  (if (equal x '(var inf var-inf))
+      '(float 1 0)
+    (if (equal x '(neg (var inf var-inf)))
+	'(float -1 0)
+      (if (Math-zerop x)
+	  x
+	(let ((math-current-gamma-value (math-sqrt-pi)))
+	  (math-to-same-complex-quad
+	   (math-div (calcFunc-gammag '(float 5 -1)
+				      (math-sqr (math-to-complex-quad-one x)))
+		     math-current-gamma-value)
+	   x)))))
+)
+
+(defun calcFunc-erfc (x)
+  (if (equal x '(var inf var-inf))
+      '(float 0 0)
+    (if (math-posp x)
+	(let ((math-current-gamma-value (math-sqrt-pi)))
+	  (math-div (calcFunc-gammaG '(float 5 -1) (math-sqr x))
+		    math-current-gamma-value))
+      (math-sub 1 (calcFunc-erf x))))
+)
+
+(defun math-to-complex-quad-one (x)
+  (if (eq (car-safe x) 'polar) (setq x (math-complex x)))
+  (if (eq (car-safe x) 'cplx)
+      (list 'cplx (math-abs (nth 1 x)) (math-abs (nth 2 x)))
+    x)
+)
+
+(defun math-to-same-complex-quad (x y)
+  (if (eq (car-safe y) 'cplx)
+      (if (eq (car-safe x) 'cplx)
+	  (list 'cplx
+		(if (math-negp (nth 1 y)) (math-neg (nth 1 x)) (nth 1 x))
+		(if (math-negp (nth 2 y)) (math-neg (nth 2 x)) (nth 2 x)))
+	(if (math-negp (nth 1 y)) (math-neg x) x))
+    (if (math-negp y)
+	(if (eq (car-safe x) 'cplx)
+	    (list 'cplx (math-neg (nth 1 x)) (nth 2 x))
+	  (math-neg x))
+      x))
+)
+
+
+;;; Beta function.
+
+(defun calcFunc-beta (a b)
+  (if (math-num-integerp a)
+      (let ((am (math-add a -1)))
+	(or (math-numberp b) (math-reject-arg b 'numberp))
+	(math-div 1 (math-mul b (calcFunc-choose (math-add b am) am))))
+    (if (math-num-integerp b)
+	(calcFunc-beta b a)
+      (math-div (math-mul (calcFunc-gamma a) (calcFunc-gamma b))
+		(calcFunc-gamma (math-add a b)))))
+)
+
+
+;;; Incomplete beta function.
+
+(defun calcFunc-betaI (x a b)
+  (cond ((math-zerop x)
+	 '(float 0 0))
+	((math-equal-int x 1)
+	 '(float 1 0))
+	((or (math-zerop a)
+	     (and (math-num-integerp a)
+		  (math-negp a)))
+	 (if (or (math-zerop b)
+		 (and (math-num-integerp b)
+		      (math-negp b)))
+	     (math-reject-arg b 'range)
+	   '(float 1 0)))
+	((or (math-zerop b)
+	     (and (math-num-integerp b)
+		  (math-negp b)))
+	 '(float 0 0))
+	((not (math-numberp a)) (math-reject-arg a 'numberp))
+	((not (math-numberp b)) (math-reject-arg b 'numberp))
+	((math-inexact-result))
+	(t (let ((math-current-beta-value (calcFunc-beta a b)))
+	     (math-div (calcFunc-betaB x a b) math-current-beta-value))))
+)
+
+(defun calcFunc-betaB (x a b)
+  (cond
+   ((math-zerop x)
+    '(float 0 0))
+   ((math-equal-int x 1)
+    (calcFunc-beta a b))
+   ((not (math-numberp x)) (math-reject-arg x 'numberp))
+   ((not (math-numberp a)) (math-reject-arg a 'numberp))
+   ((not (math-numberp b)) (math-reject-arg b 'numberp))
+   ((math-zerop a) (math-reject-arg a 'nonzerop))
+   ((math-zerop b) (math-reject-arg b 'nonzerop))
+   ((and (math-num-integerp b)
+	 (if (math-negp b)
+	     (math-reject-arg b 'range)
+	   (Math-natnum-lessp (setq b (math-trunc b)) 20)))
+    (and calc-symbolic-mode (or (math-floatp a) (math-floatp b))
+	 (math-inexact-result))
+    (math-mul
+     (math-with-extra-prec 2
+       (let* ((i 0)
+	      (term 1)
+	      (sum (math-div term a)))
+	 (while (< (setq i (1+ i)) b)
+	   (setq term (math-mul (math-div (math-mul term (- i b)) i) x)
+		 sum (math-add sum (math-div term (math-add a i))))
+	   (math-working "beta" sum))
+	 sum))
+     (math-pow x a)))
+   ((and (math-num-integerp a)
+	 (if (math-negp a)
+	     (math-reject-arg a 'range)
+	   (Math-natnum-lessp (setq a (math-trunc a)) 20)))
+    (math-sub (or math-current-beta-value (calcFunc-beta a b))
+	      (calcFunc-betaB (math-sub 1 x) b a)))
+   (t
+    (math-inexact-result)
+    (math-with-extra-prec 2
+      (setq x (math-float x))
+      (setq a (math-float a))
+      (setq b (math-float b))
+      (let ((bt (math-exp-raw (math-add (math-mul a (math-ln-raw x))
+					(math-mul b (math-ln-raw
+						     (math-sub '(float 1 0)
+							       x)))))))
+	(if (Math-lessp x (math-div (math-add a '(float 1 0))
+				    (math-add (math-add a b) '(float 2 0))))
+	    (math-div (math-mul bt (math-beta-cfrac a b x)) a)
+	  (math-sub (or math-current-beta-value (calcFunc-beta a b))
+		    (math-div (math-mul bt
+					(math-beta-cfrac b a (math-sub 1 x)))
+			      b)))))))
+)
+(setq math-current-beta-value nil)
+
+(defun math-beta-cfrac (a b x)
+  (let ((qab (math-add a b))
+	(qap (math-add a '(float 1 0)))
+	(qam (math-add a '(float -1 0))))
+    (math-beta-cfrac-step '(float 1 0)
+			  (math-sub '(float 1 0)
+				    (math-div (math-mul qab x) qap))
+			  '(float 1 0) '(float 1 0)
+			  '(float 1 0)
+			  qab qap qam a b x))
+)
+
+(defun math-beta-cfrac-step (az bz am bm m qab qap qam a b x)
+  (let* ((two-m (math-mul m '(float 2 0)))
+	 (d (math-div (math-mul (math-mul (math-sub b m) m) x)
+		      (math-mul (math-add qam two-m) (math-add a two-m))))
+	 (ap (math-add az (math-mul d am)))
+	 (bp (math-add bz (math-mul d bm)))
+	 (d2 (math-neg
+	      (math-div (math-mul (math-mul (math-add a m) (math-add qab m)) x)
+			(math-mul (math-add qap two-m) (math-add a two-m)))))
+	 (app (math-add ap (math-mul d2 az)))
+	 (bpp (math-add bp (math-mul d2 bz)))
+	 (next (math-div app bpp)))
+    (math-working "beta" next)
+    (if (math-nearly-equal next az)
+	next
+      (math-beta-cfrac-step next '(float 1 0)
+			    (math-div ap bpp) (math-div bp bpp)
+			    (math-add m '(float 1 0))
+			    qab qap qam a b x)))
+)
+
+
+;;; Bessel functions.
+
+;;; Should generalize this to handle arbitrary precision!
+
+(defun calcFunc-besJ (v x)
+  (or (math-numberp v) (math-reject-arg v 'numberp))
+  (or (math-numberp x) (math-reject-arg x 'numberp))
+  (let ((calc-internal-prec (min 8 calc-internal-prec)))
+    (math-with-extra-prec 3
+      (setq x (math-float (math-normalize x)))
+      (setq v (math-float (math-normalize v)))
+      (cond ((math-zerop x)
+	     (if (math-zerop v)
+		 '(float 1 0)
+	       '(float 0 0)))
+	    ((math-inexact-result))
+	    ((not (math-num-integerp v))
+	     (let ((start (math-div 1 (calcFunc-fact v))))
+	       (math-mul (math-besJ-series start start
+					   0
+					   (math-mul '(float -25 -2)
+						     (math-sqr x))
+					   v)
+			 (math-pow (math-div x 2) v))))
+	    ((math-negp (setq v (math-trunc v)))
+	     (if (math-oddp v)
+		 (math-neg (calcFunc-besJ (math-neg v) x))
+	       (calcFunc-besJ (math-neg v) x)))
+	    ((eq v 0)
+	     (math-besJ0 x))
+	    ((eq v 1)
+	     (math-besJ1 x))
+	    ((Math-lessp v (math-abs-approx x))
+	     (let ((j 0)
+		   (bjm (math-besJ0 x))
+		   (bj (math-besJ1 x))
+		   (two-over-x (math-div 2 x))
+		   bjp)
+	       (while (< (setq j (1+ j)) v)
+		 (setq bjp (math-sub (math-mul (math-mul j two-over-x) bj)
+				     bjm)
+		       bjm bj
+		       bj bjp))
+	       bj))
+	    (t
+	     (if (Math-lessp 100 v) (math-reject-arg v 'range))
+	     (let* ((j (logior (+ v (math-isqrt-small (* 40 v))) 1))
+		    (two-over-x (math-div 2 x))
+		    (jsum nil)
+		    (bjp '(float 0 0))
+		    (sum '(float 0 0))
+		    (bj '(float 1 0))
+		    bjm ans)
+	       (while (> (setq j (1- j)) 0)
+		 (setq bjm (math-sub (math-mul (math-mul j two-over-x) bj)
+				     bjp)
+		       bjp bj
+		       bj bjm)
+		 (if (> (nth 2 (math-abs-approx bj)) 10)
+		     (setq bj (math-mul bj '(float 1 -10))
+			   bjp (math-mul bjp '(float 1 -10))
+			   ans (and ans (math-mul ans '(float 1 -10)))
+			   sum (math-mul sum '(float 1 -10))))
+		 (or (setq jsum (not jsum))
+		     (setq sum (math-add sum bj)))
+		 (if (= j v)
+		     (setq ans bjp)))
+	       (math-div ans (math-sub (math-mul 2 sum) bj)))))))
+)
+
+(defun math-besJ-series (sum term k zz vk)
+  (math-working "besJ" sum)
+  (setq k (1+ k)
+	vk (math-add 1 vk)
+	term (math-div (math-mul term zz) (math-mul k vk)))
+  (let ((next (math-add sum term)))
+    (if (math-nearly-equal next sum)
+	next
+      (math-besJ-series next term k zz vk)))
+)
+
+(defun math-besJ0 (x &optional yflag)
+  (cond ((and (not yflag) (math-negp (calcFunc-re x)))
+	 (math-besJ0 (math-neg x)))
+	((Math-lessp '(float 8 0) (math-abs-approx x))
+	 (let* ((z (math-div '(float 8 0) x))
+		(y (math-sqr z))
+		(xx (math-add x '(float (bigneg 164 398 785) -9)))
+		(a1 (math-poly-eval y
+				    '((float (bigpos 211 887 093 2) -16)
+				      (float (bigneg 639 370 073 2) -15)
+				      (float (bigpos 407 510 734 2) -14)
+				      (float (bigneg 627 628 098 1) -12)
+				      (float 1 0))))
+		(a2 (math-poly-eval y
+				    '((float (bigneg 152 935 934) -16)
+				      (float (bigpos 161 095 621 7) -16)
+				      (float (bigneg 651 147 911 6) -15)
+				      (float (bigpos 765 488 430 1) -13)
+				      (float (bigneg 995 499 562 1) -11))))
+		(sc (math-sin-cos-raw xx)))
+	       (if yflag
+		   (setq sc (cons (math-neg (cdr sc)) (car sc))))
+	       (math-mul (math-sqrt
+			  (math-div '(float (bigpos 722 619 636) -9) x))
+			 (math-sub (math-mul (cdr sc) a1)
+				   (math-mul (car sc) (math-mul z a2))))))
+	 (t
+	  (let ((y (math-sqr x)))
+	    (math-div (math-poly-eval y
+				      '((float (bigneg 456 052 849 1) -7)
+					(float (bigpos 017 233 739 7) -5)
+					(float (bigneg 418 442 121 1) -2)
+					(float (bigpos 407 196 516 6) -1)
+					(float (bigneg 354 590 362 13) 0)
+					(float (bigpos 574 490 568 57) 0)))
+		      (math-poly-eval y
+				      '((float 1 0)
+					(float (bigpos 712 532 678 2) -7)
+					(float (bigpos 853 264 927 5) -5)
+					(float (bigpos 718 680 494 9) -3)
+					(float (bigpos 985 532 029 1) 0)
+					(float (bigpos 411 490 568 57) 0)))))))
+)
+
+(defun math-besJ1 (x &optional yflag)
+  (cond ((and (math-negp (calcFunc-re x)) (not yflag))
+	 (math-neg (math-besJ1 (math-neg x))))
+	((Math-lessp '(float 8 0) (math-abs-approx x))
+	 (let* ((z (math-div '(float 8 0) x))
+		(y (math-sqr z))
+		(xx (math-add x '(float (bigneg 491 194 356 2) -9)))
+		(a1 (math-poly-eval y
+				    '((float (bigneg 019 337 240) -15)
+				      (float (bigpos 174 520 457 2) -15)
+				      (float (bigneg 496 396 516 3) -14)
+				      (float 183105 -8)
+				      (float 1 0))))
+		(a2 (math-poly-eval y
+				    '((float (bigpos 412 787 105) -15)
+				      (float (bigneg 987 228 88) -14)
+				      (float (bigpos 096 199 449 8) -15)
+				      (float (bigneg 873 690 002 2) -13)
+				      (float (bigpos 995 499 687 4) -11))))
+		(sc (math-sin-cos-raw xx)))
+	   (if yflag
+	       (setq sc (cons (math-neg (cdr sc)) (car sc)))
+	     (if (math-negp x)
+		 (setq sc (cons (math-neg (car sc)) (math-neg (cdr sc))))))
+	   (math-mul (math-sqrt (math-div '(float (bigpos 722 619 636) -9) x))
+		     (math-sub (math-mul (cdr sc) a1)
+			       (math-mul (car sc) (math-mul z a2))))))
+	(t
+	 (let ((y (math-sqr x)))
+	   (math-mul
+	    x
+	    (math-div (math-poly-eval y
+				      '((float (bigneg 606 036 016 3) -8)
+					(float (bigpos 826 044 157) -4)
+					(float (bigneg 439 611 972 2) -3)
+					(float (bigpos 531 968 423 2) -1)
+					(float (bigneg 235 059 895 7) 0)
+					(float (bigpos 232 614 362 72) 0)))
+		      (math-poly-eval y
+				      '((float 1 0)
+					(float (bigpos 397 991 769 3) -7)
+					(float (bigpos 394 743 944 9) -5)
+					(float (bigpos 474 330 858 1) -2)
+					(float (bigpos 178 535 300 2) 0)
+					(float (bigpos 442 228 725 144)
+					       0))))))))
+)
+
+(defun calcFunc-besY (v x)
+  (math-inexact-result)
+  (or (math-numberp v) (math-reject-arg v 'numberp))
+  (or (math-numberp x) (math-reject-arg x 'numberp))
+  (let ((calc-internal-prec (min 8 calc-internal-prec)))
+    (math-with-extra-prec 3
+      (setq x (math-float (math-normalize x)))
+      (setq v (math-float (math-normalize v)))
+      (cond ((not (math-num-integerp v))
+	     (let ((sc (math-sin-cos-raw (math-mul v (math-pi)))))
+	       (math-div (math-sub (math-mul (calcFunc-besJ v x) (cdr sc))
+				   (calcFunc-besJ (math-neg v) x))
+			 (car sc))))
+	    ((math-negp (setq v (math-trunc v)))
+	     (if (math-oddp v)
+		 (math-neg (calcFunc-besY (math-neg v) x))
+	       (calcFunc-besY (math-neg v) x)))
+	    ((eq v 0)
+	     (math-besY0 x))
+	    ((eq v 1)
+	     (math-besY1 x))
+	    (t
+	     (let ((j 0)
+		   (bym (math-besY0 x))
+		   (by (math-besY1 x))
+		   (two-over-x (math-div 2 x))
+		   byp)
+	       (while (< (setq j (1+ j)) v)
+		 (setq byp (math-sub (math-mul (math-mul j two-over-x) by)
+				     bym)
+		       bym by
+		       by byp))
+	       by)))))
+)
+
+(defun math-besY0 (x)
+  (cond ((Math-lessp (math-abs-approx x) '(float 8 0))
+	 (let ((y (math-sqr x)))
+	   (math-add
+	    (math-div (math-poly-eval y
+				      '((float (bigpos 733 622 284 2) -7)
+					(float (bigneg 757 792 632 8) -5)
+					(float (bigpos 129 988 087 1) -2)
+					(float (bigneg 036 598 123 5) -1)
+					(float (bigpos 065 834 062 7) 0)
+					(float (bigneg 389 821 957 2) 0)))
+		      (math-poly-eval y
+				      '((float 1 0)
+					(float (bigpos 244 030 261 2) -7)
+					(float (bigpos 647 472 474) -4)
+					(float (bigpos 438 466 189 7) -3)
+					(float (bigpos 648 499 452 7) -1)
+					(float (bigpos 269 544 076 40) 0))))
+	    (math-mul '(float (bigpos 772 619 636) -9)
+		      (math-mul (math-besJ0 x) (math-ln-raw x))))))
+	((math-negp (calcFunc-re x))
+	 (math-add (math-besJ0 (math-neg x) t)
+		   (math-mul '(cplx 0 2)
+			     (math-besJ0 (math-neg x)))))
+	(t
+	 (math-besJ0 x t)))
+)
+
+(defun math-besY1 (x)
+  (cond ((Math-lessp (math-abs-approx x) '(float 8 0))
+	 (let ((y (math-sqr x)))
+	   (math-add
+	    (math-mul
+	     x
+	     (math-div (math-poly-eval y
+				       '((float (bigpos 935 937 511 8) -6)
+					 (float (bigneg 726 922 237 4) -3)
+					 (float (bigpos 551 264 349 7) -1)
+					 (float (bigneg 139 438 153 5) 1)
+					 (float (bigpos 439 527 127) 4)
+					 (float (bigneg 943 604 900 4) 3)))
+		       (math-poly-eval y
+				       '((float 1 0)
+					 (float (bigpos 885 632 549 3) -7)
+					 (float (bigpos 605 042 102) -3)
+					 (float (bigpos 002 904 245 2) -2)
+					 (float (bigpos 367 650 733 3) 0)
+					 (float (bigpos 664 419 244 4) 2)
+					 (float (bigpos 057 958 249) 5)))))
+	    (math-mul '(float (bigpos 772 619 636) -9)
+		      (math-sub (math-mul (math-besJ1 x) (math-ln-raw x))
+				(math-div 1 x))))))
+	((math-negp (calcFunc-re x))
+	 (math-neg
+	  (math-add (math-besJ1 (math-neg x) t)
+		    (math-mul '(cplx 0 2)
+			      (math-besJ1 (math-neg x))))))
+	(t
+	 (math-besJ1 x t)))
+)
+
+(defun math-poly-eval (x coefs)
+  (let ((accum (car coefs)))
+    (while (setq coefs (cdr coefs))
+      (setq accum (math-add (car coefs) (math-mul accum x))))
+    accum)
+)
+
+
+;;;; Bernoulli and Euler polynomials and numbers.
+
+(defun calcFunc-bern (n &optional x)
+  (if (and x (not (math-zerop x)))
+      (if (and calc-symbolic-mode (math-floatp x))
+	  (math-inexact-result)
+	(math-build-polynomial-expr (math-bernoulli-coefs n) x))
+    (or (math-num-natnump n) (math-reject-arg n 'natnump))
+    (if (consp n)
+	(progn
+	  (math-inexact-result)
+	  (math-float (math-bernoulli-number (math-trunc n))))
+      (math-bernoulli-number n)))
+)
+
+(defun calcFunc-euler (n &optional x)
+  (or (math-num-natnump n) (math-reject-arg n 'natnump))
+  (if x
+      (let* ((n1 (math-add n 1))
+	     (coefs (math-bernoulli-coefs n1))
+	     (fac (math-div (math-pow 2 n1) n1))
+	     (k -1)
+	     (x1 (math-div (math-add x 1) 2))
+	     (x2 (math-div x 2)))
+	(if (math-numberp x)
+	    (if (and calc-symbolic-mode (math-floatp x))
+		(math-inexact-result)
+	      (math-mul fac
+			(math-sub (math-build-polynomial-expr coefs x1)
+				  (math-build-polynomial-expr coefs x2))))
+	  (calcFunc-collect
+	   (math-reduce-vec
+	    'math-add
+	    (cons 'vec
+		  (mapcar (function
+			   (lambda (c)
+			     (setq k (1+ k))
+			     (math-mul (math-mul fac c)
+				       (math-sub (math-pow x1 k)
+						 (math-pow x2 k)))))
+			  coefs)))
+	   x)))
+    (math-mul (math-pow 2 n)
+	      (if (consp n)
+		  (progn
+		    (math-inexact-result)
+		    (calcFunc-euler n '(float 5 -1)))
+		(calcFunc-euler n '(frac 1 2)))))
+)
+
+(defun math-bernoulli-coefs (n)
+  (let* ((coefs (list (calcFunc-bern n)))
+	 (nn (math-trunc n))
+	 (k nn)
+	 (term nn)
+	 coef
+	 (calc-prefer-frac (or (integerp n) calc-prefer-frac)))
+    (while (>= (setq k (1- k)) 0)
+      (setq term (math-div term (- nn k))
+	    coef (math-mul term (math-bernoulli-number k))
+	    coefs (cons (if (consp n) (math-float coef) coef) coefs)
+	    term (math-mul term k)))
+    (nreverse coefs))
+)
+
+(defun math-bernoulli-number (n)
+  (if (= (% n 2) 1)
+      (if (= n 1)
+	  '(frac -1 2)
+	0)
+    (setq n (/ n 2))
+    (while (>= n math-bernoulli-cache-size)
+      (let* ((sum 0)
+	     (nk 1)     ; nk = n-k+1
+	     (fact 1)   ; fact = (n-k+1)!
+	     ofact
+	     (p math-bernoulli-b-cache)
+	     (calc-prefer-frac t))
+	(math-working "bernoulli B" (* 2 math-bernoulli-cache-size))
+	(while p
+	  (setq nk (+ nk 2)
+		ofact fact
+		fact (math-mul fact (* nk (1- nk)))
+		sum (math-add sum (math-div (car p) fact))
+		p (cdr p)))
+	(setq ofact (math-mul ofact (1- nk))
+	      sum (math-sub (math-div '(frac 1 2) ofact) sum)
+	      math-bernoulli-b-cache (cons sum math-bernoulli-b-cache)
+	      math-bernoulli-B-cache (cons (math-mul sum ofact)
+					   math-bernoulli-B-cache)
+	      math-bernoulli-cache-size (1+ math-bernoulli-cache-size))))
+    (nth (- math-bernoulli-cache-size n 1) math-bernoulli-B-cache))
+)
+
+;;;   Bn = n! bn
+;;;   bn = - sum_k=0^n-1 bk / (n-k+1)!
+
+;;; A faster method would be to use "tangent numbers", c.f., Concrete
+;;; Mathematics pg. 273.
+
+(setq math-bernoulli-b-cache '( (frac -174611
+				      (bigpos 0 200 291 698 662 857 802))
+				(frac 43867 (bigpos 0 944 170 217 94 109 5))
+				(frac -3617 (bigpos 0 880 842 622 670 10))
+				(frac 1 (bigpos 600 249 724 74))
+				(frac -691 (bigpos 0 368 674 307 1))
+				(frac 1 (bigpos 160 900 47))
+				(frac -1 (bigpos 600 209 1))
+				(frac 1 30240) (frac -1 720)
+				(frac 1 12) 1 ))
+
+(setq math-bernoulli-B-cache '( (frac -174611 330) (frac 43867 798)
+				(frac -3617 510) (frac 7 6) (frac -691 2730)
+				(frac 5 66) (frac -1 30) (frac 1 42)
+				(frac -1 30) (frac 1 6) 1 ))
+
+(setq math-bernoulli-cache-size 11)
+
+
+
+;;; Probability distributions.
+
+;;; Binomial.
+(defun calcFunc-utpb (x n p)
+  (if math-expand-formulas
+      (math-normalize (list 'calcFunc-betaI p x (list '+ (list '- n x) 1)))
+    (calcFunc-betaI p x (math-add (math-sub n x) 1)))
+)
+(put 'calcFunc-utpb 'math-expandable t)
+
+(defun calcFunc-ltpb (x n p)
+  (math-sub 1 (calcFunc-utpb x n p))
+)
+(put 'calcFunc-ltpb 'math-expandable t)
+
+;;; Chi-square.
+(defun calcFunc-utpc (chisq v)
+  (if math-expand-formulas
+      (math-normalize (list 'calcFunc-gammaQ (list '/ v 2) (list '/ chisq 2)))
+    (calcFunc-gammaQ (math-div v 2) (math-div chisq 2)))
+)
+(put 'calcFunc-utpc 'math-expandable t)
+
+(defun calcFunc-ltpc (chisq v)
+  (if math-expand-formulas
+      (math-normalize (list 'calcFunc-gammaP (list '/ v 2) (list '/ chisq 2)))
+    (calcFunc-gammaP (math-div v 2) (math-div chisq 2)))
+)
+(put 'calcFunc-ltpc 'math-expandable t)
+
+;;; F-distribution.
+(defun calcFunc-utpf (f v1 v2)
+  (if math-expand-formulas
+      (math-normalize (list 'calcFunc-betaI
+			    (list '/ v2 (list '+ v2 (list '* v1 f)))
+			    (list '/ v2 2)
+			    (list '/ v1 2)))
+    (calcFunc-betaI (math-div v2 (math-add v2 (math-mul v1 f)))
+		    (math-div v2 2)
+		    (math-div v1 2)))
+)
+(put 'calcFunc-utpf 'math-expandable t)
+
+(defun calcFunc-ltpf (f v1 v2)
+  (math-sub 1 (calcFunc-utpf f v1 v2))
+)
+(put 'calcFunc-ltpf 'math-expandable t)
+
+;;; Normal.
+(defun calcFunc-utpn (x mean sdev)
+  (if math-expand-formulas
+      (math-normalize
+       (list '/
+	     (list '+ 1
+		   (list 'calcFunc-erf
+			 (list '/ (list '- mean x)
+			       (list '* sdev (list 'calcFunc-sqrt 2)))))
+	     2))
+    (math-mul (math-add '(float 1 0)
+			(calcFunc-erf
+			 (math-div (math-sub mean x)
+				   (math-mul sdev (math-sqrt-2)))))
+	      '(float 5 -1)))
+)
+(put 'calcFunc-utpn 'math-expandable t)
+
+(defun calcFunc-ltpn (x mean sdev)
+  (if math-expand-formulas
+      (math-normalize
+       (list '/
+	     (list '+ 1
+		   (list 'calcFunc-erf
+			 (list '/ (list '- x mean)
+			       (list '* sdev (list 'calcFunc-sqrt 2)))))
+	     2))
+    (math-mul (math-add '(float 1 0)
+			(calcFunc-erf
+			 (math-div (math-sub x mean)
+				   (math-mul sdev (math-sqrt-2)))))
+	      '(float 5 -1)))
+)
+(put 'calcFunc-ltpn 'math-expandable t)
+
+;;; Poisson.
+(defun calcFunc-utpp (n x)
+  (if math-expand-formulas
+      (math-normalize (list 'calcFunc-gammaP x n))
+    (calcFunc-gammaP x n))
+)
+(put 'calcFunc-utpp 'math-expandable t)
+
+(defun calcFunc-ltpp (n x)
+  (if math-expand-formulas
+      (math-normalize (list 'calcFunc-gammaQ x n))
+    (calcFunc-gammaQ x n))
+)
+(put 'calcFunc-ltpp 'math-expandable t)
+
+;;; Student's t.  (As defined in Abramowitz & Stegun and Numerical Recipes.)
+(defun calcFunc-utpt (tt v)
+  (if math-expand-formulas
+      (math-normalize (list 'calcFunc-betaI
+			    (list '/ v (list '+ v (list '^ tt 2)))
+			    (list '/ v 2)
+			    '(float 5 -1)))
+    (calcFunc-betaI (math-div v (math-add v (math-sqr tt)))
+		    (math-div v 2)
+		    '(float 5 -1)))
+)
+(put 'calcFunc-utpt 'math-expandable t)
+
+(defun calcFunc-ltpt (tt v)
+  (math-sub 1 (calcFunc-utpt tt v))
+)
+(put 'calcFunc-ltpt 'math-expandable t)
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/calc-graph.el	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,1496 @@
+;; Calculator for GNU Emacs, part II [calc-graph.el]
+;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+;; Written by Dave Gillespie, daveg@synaptics.com.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY.  No author or distributor
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing.  Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License.   A copy of this license is
+;; supposed to have been given to you along with GNU Emacs so you
+;; can know your rights and responsibilities.  It should be in a
+;; file named COPYING.  Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+
+
+
+;; This file is autoloaded from calc-ext.el.
+(require 'calc-ext)
+
+(require 'calc-macs)
+
+(defun calc-Need-calc-graph () nil)
+
+
+;;; Graphics
+
+;;; Note that some of the following initial values also occur in calc.el.
+(defvar calc-gnuplot-tempfile "/tmp/calc")
+
+(defvar calc-gnuplot-default-device "default")
+(defvar calc-gnuplot-default-output "STDOUT")
+(defvar calc-gnuplot-print-device "postscript")
+(defvar calc-gnuplot-print-output "auto")
+(defvar calc-gnuplot-keep-outfile nil)
+(defvar calc-gnuplot-version nil)
+
+(defvar calc-gnuplot-display (getenv "DISPLAY"))
+(defvar calc-gnuplot-geometry nil)
+
+(defvar calc-graph-default-resolution 15)
+(defvar calc-graph-default-resolution-3d 5)
+(defvar calc-graph-default-precision 5)
+
+(defvar calc-gnuplot-buffer nil)
+(defvar calc-gnuplot-input nil)
+
+(defvar calc-gnuplot-last-error-pos 1)
+(defvar calc-graph-last-device nil)
+(defvar calc-graph-last-output nil)
+(defvar calc-graph-file-cache nil)
+(defvar calc-graph-var-cache nil)
+(defvar calc-graph-data-cache nil)
+(defvar calc-graph-data-cache-limit 10)
+
+(defun calc-graph-fast (many)
+  (interactive "P")
+  (let ((calc-graph-no-auto-view t))
+    (calc-graph-delete t)
+    (calc-graph-add many)
+    (calc-graph-plot nil))
+)
+
+(defun calc-graph-fast-3d (many)
+  (interactive "P")
+  (let ((calc-graph-no-auto-view t))
+    (calc-graph-delete t)
+    (calc-graph-add-3d many)
+    (calc-graph-plot nil))
+)
+
+(defun calc-graph-delete (all)
+  (interactive "P")
+  (calc-wrapper
+   (calc-graph-init)
+   (save-excursion
+     (set-buffer calc-gnuplot-input)
+     (and (calc-graph-find-plot t all)
+	  (progn
+	    (if (looking-at "s?plot")
+		(progn
+		  (setq calc-graph-var-cache nil)
+		  (delete-region (point) (point-max)))
+	      (delete-region (point) (1- (point-max)))))))
+   (calc-graph-view-commands))
+)
+
+(defun calc-graph-find-plot (&optional before all)
+  (goto-char (point-min))
+  (and (re-search-forward "^s?plot[ \t]+" nil t)
+       (let ((beg (point)))
+	 (goto-char (point-max))
+	 (if (or all
+		 (not (search-backward "," nil t))
+		 (< (point) beg))
+	     (progn
+	       (goto-char beg)
+	       (if before
+		   (beginning-of-line)))
+	   (or before
+	       (re-search-forward ",[ \t]+")))
+	 t))
+)
+
+(defun calc-graph-add (many)
+  (interactive "P")
+  (calc-wrapper
+   (calc-graph-init)
+   (cond ((null many)
+	  (calc-graph-add-curve (calc-graph-lookup (calc-top-n 2))
+				(calc-graph-lookup (calc-top-n 1))))
+	 ((or (consp many) (eq many 0))
+	  (let ((xdata (calc-graph-lookup (calc-top-n 2)))
+		(ylist (calc-top-n 1)))
+	    (or (eq (car-safe ylist) 'vec)
+		(error "Y argument must be a vector"))
+	    (while (setq ylist (cdr ylist))
+	      (calc-graph-add-curve xdata (calc-graph-lookup (car ylist))))))
+	 ((> (setq many (prefix-numeric-value many)) 0)
+	  (let ((xdata (calc-graph-lookup (calc-top-n (1+ many)))))
+	    (while (> many 0)
+	      (calc-graph-add-curve xdata
+				    (calc-graph-lookup (calc-top-n many)))
+	      (setq many (1- many)))))
+	 (t
+	  (let (pair)
+	    (setq many (- many))
+	    (while (> many 0)
+	      (setq pair (calc-top-n many))
+	      (or (and (eq (car-safe pair) 'vec)
+		       (= (length pair) 3))
+		  (error "Argument must be an [x,y] vector"))
+	      (calc-graph-add-curve (calc-graph-lookup (nth 1 pair))
+				    (calc-graph-lookup (nth 2 pair)))
+	      (setq many (1- many))))))
+   (calc-graph-view-commands))
+)
+
+(defun calc-graph-add-3d (many)
+  (interactive "P")
+  (calc-wrapper
+   (calc-graph-init)
+   (cond ((null many)
+	  (calc-graph-add-curve (calc-graph-lookup (calc-top-n 3))
+				(calc-graph-lookup (calc-top-n 2))
+				(calc-graph-lookup (calc-top-n 1))))
+	 ((or (consp many) (eq many 0))
+	  (let ((xdata (calc-graph-lookup (calc-top-n 3)))
+		(ydata (calc-graph-lookup (calc-top-n 2)))
+		(zlist (calc-top-n 1)))
+	    (or (eq (car-safe zlist) 'vec)
+		(error "Z argument must be a vector"))
+	    (while (setq zlist (cdr zlist))
+	      (calc-graph-add-curve xdata ydata
+				    (calc-graph-lookup (car zlist))))))
+	 ((> (setq many (prefix-numeric-value many)) 0)
+	  (let ((xdata (calc-graph-lookup (calc-top-n (+ many 2))))
+		(ydata (calc-graph-lookup (calc-top-n (+ many 1)))))
+	    (while (> many 0)
+	      (calc-graph-add-curve xdata ydata
+				    (calc-graph-lookup (calc-top-n many)))
+	      (setq many (1- many)))))
+	 (t
+	  (let (curve)
+	    (setq many (- many))
+	    (while (> many 0)
+	      (setq curve (calc-top-n many))
+	      (or (and (eq (car-safe curve) 'vec)
+		       (= (length curve) 4))
+		  (error "Argument must be an [x,y,z] vector"))
+	      (calc-graph-add-curve (calc-graph-lookup (nth 1 curve))
+				    (calc-graph-lookup (nth 2 curve))
+				    (calc-graph-lookup (nth 3 curve)))
+	      (setq many (1- many))))))
+   (calc-graph-view-commands))
+)
+
+(defun calc-graph-add-curve (xdata ydata &optional zdata)
+  (let ((num (calc-graph-count-curves))
+	(pstyle (calc-var-value 'var-PointStyles))
+	(lstyle (calc-var-value 'var-LineStyles)))
+    (save-excursion
+      (set-buffer calc-gnuplot-input)
+      (goto-char (point-min))
+      (if (re-search-forward (if zdata "^plot[ \t]" "^splot[ \t]")
+			     nil t)
+	  (error "Can't mix 2d and 3d curves on one graph"))
+      (if (re-search-forward "^s?plot[ \t]" nil t)
+	  (progn
+	    (end-of-line)
+	    (insert ", "))
+	(goto-char (point-max))
+	(or (eq (preceding-char) ?\n)
+	    (insert "\n"))
+	(insert (if zdata "splot" "plot") " \n")
+	(forward-char -1))
+      (insert "{" (symbol-name (nth 1 xdata))
+	      ":" (symbol-name (nth 1 ydata)))
+      (if zdata
+	  (insert ":" (symbol-name (nth 1 zdata))))
+      (insert "} "
+	      "title \"" (symbol-name (nth 1 ydata)) "\" "
+	      "with dots")
+      (setq pstyle (and (eq (car-safe pstyle) 'vec) (nth (1+ num) pstyle)))
+      (setq lstyle (and (eq (car-safe lstyle) 'vec) (nth (1+ num) lstyle)))
+      (calc-graph-set-styles
+       (or (and (Math-num-integerp lstyle) (math-trunc lstyle))
+	   0)
+       (or (and (Math-num-integerp pstyle) (math-trunc pstyle))
+	   (if (eq (car-safe (calc-var-value (nth 2 ydata))) 'vec)
+	       0 -1)))))
+)
+
+(defun calc-graph-lookup (thing)
+  (if (and (eq (car-safe thing) 'var)
+	   (calc-var-value (nth 2 thing)))
+      thing
+    (let ((found (assoc thing calc-graph-var-cache)))
+      (or found
+	  (progn
+	    (setq varname (concat "PlotData"
+				  (int-to-string
+				   (1+ (length calc-graph-var-cache))))
+		  var (list 'var (intern varname)
+			    (intern (concat "var-" varname)))
+		  found (cons thing var)
+		  calc-graph-var-cache (cons found calc-graph-var-cache))
+	    (set (nth 2 var) thing)))
+      (cdr found)))
+)
+
+(defun calc-graph-juggle (arg)
+  (interactive "p")
+  (calc-graph-init)
+  (save-excursion
+    (set-buffer calc-gnuplot-input)
+    (if (< arg 0)
+	(let ((num (calc-graph-count-curves)))
+	  (if (> num 0)
+	      (while (< arg 0)
+		(setq arg (+ arg num))))))
+    (while (>= (setq arg (1- arg)) 0)
+      (calc-graph-do-juggle)))
+)
+
+(defun calc-graph-count-curves ()
+  (save-excursion
+    (set-buffer calc-gnuplot-input)
+    (if (re-search-forward "^s?plot[ \t]" nil t)
+	(let ((num 1))
+	  (goto-char (point-min))
+	  (while (search-forward "," nil t)
+	    (setq num (1+ num)))
+	  num)
+      0))
+)
+
+(defun calc-graph-do-juggle ()
+  (let (base)
+    (and (calc-graph-find-plot t t)
+	 (progn
+	   (setq base (point))
+	   (calc-graph-find-plot t nil)
+	   (or (eq base (point))
+	       (let ((str (buffer-substring (+ (point) 2) (1- (point-max)))))
+		 (delete-region (point) (1- (point-max)))
+		 (goto-char (+ base 5))
+		 (insert str ", "))))))
+)
+
+(defun calc-graph-print (flag)
+  (interactive "P")
+  (calc-graph-plot flag t)
+)
+
+(defun calc-graph-plot (flag &optional printing)
+  (interactive "P")
+  (calc-slow-wrapper
+   (let ((calcbuf (current-buffer))
+	 (tempbuf (get-buffer-create "*Gnuplot Temp-2*"))
+	 (tempbuftop 1)
+	 (tempoutfile nil)
+	 (curve-num 0)
+	 (refine (and flag (> (prefix-numeric-value flag) 0)))
+	 (recompute (and flag (< (prefix-numeric-value flag) 0)))
+	 (surprise-splot nil)
+	 (tty-output nil)
+	 cache-env is-splot device output resolution precision samples-pos)
+     (or (boundp 'calc-graph-prev-kill-hook)
+	 (if calc-emacs-type-19
+	     (progn
+	       (setq calc-graph-prev-kill-hook nil)
+	       (add-hook 'kill-emacs-hook 'calc-graph-kill-hook))
+	   (setq calc-graph-prev-kill-hook kill-emacs-hook)
+	   (setq kill-emacs-hook 'calc-graph-kill-hook)))
+     (save-excursion
+       (calc-graph-init)
+       (set-buffer tempbuf)
+       (erase-buffer)
+       (set-buffer calc-gnuplot-input)
+       (goto-char (point-min))
+       (setq is-splot (re-search-forward "^splot[ \t]" nil t))
+       (let ((str (buffer-string))
+	     (ver calc-gnuplot-version))
+	 (set-buffer (get-buffer-create "*Gnuplot Temp*"))
+	 (erase-buffer)
+	 (insert "# (Note: This is a temporary copy---do not edit!)\n")
+	 (if (>= ver 2)
+	     (insert "set noarrow\nset nolabel\n"
+		     "set autoscale xy\nset nologscale xy\n"
+		     "set xlabel\nset ylabel\nset title\n"
+		     "set noclip points\nset clip one\nset clip two\n"
+		     "set format \"%g\"\nset tics\nset xtics\nset ytics\n"
+		     "set data style linespoints\n"
+		     "set nogrid\nset nokey\nset nopolar\n"))
+	 (if (>= ver 3)
+	     (insert "set surface\nset nocontour\n"
+		     "set " (if is-splot "" "no") "parametric\n"
+		     "set notime\nset border\nset ztics\nset zeroaxis\n"
+		     "set view 60,30,1,1\nset offsets 0,0,0,0\n"))
+	 (setq samples-pos (point))
+	 (insert "\n\n" str))
+       (goto-char (point-min))
+       (if is-splot
+	   (if refine
+	       (error "This option works only for 2d plots")
+	     (setq recompute t)))
+       (let ((calc-gnuplot-input (current-buffer))
+	     (calc-graph-no-auto-view t))
+	 (if printing
+	     (setq device calc-gnuplot-print-device
+		   output calc-gnuplot-print-output)
+	   (setq device (calc-graph-find-command "terminal")
+		 output (calc-graph-find-command "output"))
+	   (or device
+	       (setq device calc-gnuplot-default-device))
+	   (if output
+	       (setq output (car (read-from-string output)))
+	     (setq output calc-gnuplot-default-output)))
+	 (if (or (equal device "") (equal device "default"))
+	     (setq device (if printing
+			      "postscript"
+			    (if (or (eq window-system 'x) (getenv "DISPLAY"))
+				"x11"
+			      (if (>= calc-gnuplot-version 3)
+				  "dumb" "postscript")))))
+	 (if (equal device "dumb")
+	     (setq device (format "dumb %d %d"
+				  (1- (screen-width)) (1- (screen-height)))))
+	 (if (equal device "big")
+	     (setq device (format "dumb %d %d"
+				  (* 4 (- (screen-width) 3))
+				  (* 4 (- (screen-height) 3)))))
+	 (if (stringp output)
+	     (if (or (equal output "auto")
+		     (and (equal output "tty") (setq tty-output t)))
+		 (setq tempoutfile (calc-temp-file-name -1)
+		       output tempoutfile))
+	   (setq output (eval output)))
+	 (or (equal device calc-graph-last-device)
+	     (progn
+	       (setq calc-graph-last-device device)
+	       (calc-gnuplot-command "set terminal" device)))
+	 (or (equal output calc-graph-last-output)
+	     (progn
+	       (setq calc-graph-last-output output)
+	       (calc-gnuplot-command "set output"
+				     (if (equal output "STDOUT")
+					 ""
+				       (prin1-to-string output)))))
+	 (setq resolution (calc-graph-find-command "samples"))
+	 (if resolution
+	     (setq resolution (string-to-int resolution))
+	   (setq resolution (if is-splot
+				calc-graph-default-resolution-3d
+			      calc-graph-default-resolution)))
+	 (setq precision (calc-graph-find-command "precision"))
+	 (if precision
+	     (setq precision (string-to-int precision))
+	   (setq precision calc-graph-default-precision))
+	 (calc-graph-set-command "terminal")
+	 (calc-graph-set-command "output")
+	 (calc-graph-set-command "samples")
+	 (calc-graph-set-command "precision"))
+       (goto-char samples-pos)
+       (insert "set samples " (int-to-string (max (if is-splot 20 200)
+						  (+ 5 resolution))) "\n")
+       (while (re-search-forward "{\\*[^}]+}[^,\n]*" nil t)
+	 (delete-region (match-beginning 0) (match-end 0))
+	 (if (looking-at ",")
+	     (delete-char 1)
+	   (while (memq (preceding-char) '(?\ ?\t))
+	     (forward-char -1))
+	   (if (eq (preceding-char) ?\,)
+	       (delete-backward-char 1))))
+       (save-excursion
+	 (set-buffer calcbuf)
+	 (setq cache-env (list calc-angle-mode
+			       calc-complex-mode
+			       calc-simplify-mode
+			       calc-infinite-mode
+			       calc-word-size
+			       precision is-splot))
+	 (if (and (not recompute)
+		  (equal (cdr (car calc-graph-data-cache)) cache-env))
+	     (while (> (length calc-graph-data-cache)
+		       calc-graph-data-cache-limit)
+	       (setcdr calc-graph-data-cache
+		       (cdr (cdr calc-graph-data-cache))))
+	   (setq calc-graph-data-cache (list (cons nil cache-env)))))
+       (calc-graph-find-plot t t)
+       (while (re-search-forward
+	       (if is-splot
+		   "{\\([^{}:\n]+\\):\\([^{}:\n]+\\):\\([^{}:\n]+\\)}"
+		 "{\\([^{}:\n]+\\)\\(:\\)\\([^{}:\n]+\\)}")
+	       nil t)
+	 (setq curve-num (1+ curve-num))
+	 (let* ((xname (buffer-substring (match-beginning 1) (match-end 1)))
+		(xvar (intern (concat "var-" xname)))
+		(xvalue (math-evaluate-expr (calc-var-value xvar)))
+		(y3name (and is-splot
+			     (buffer-substring (match-beginning 2)
+					       (match-end 2))))
+		(y3var (and is-splot (intern (concat "var-" y3name))))
+		(y3value (and is-splot (calc-var-value y3var)))
+		(yname (buffer-substring (match-beginning 3) (match-end 3)))
+		(yvar (intern (concat "var-" yname)))
+		(yvalue (calc-var-value yvar))
+		filename)
+	   (delete-region (match-beginning 0) (match-end 0))
+	   (setq filename (calc-temp-file-name curve-num))
+	   (save-excursion
+	     (set-buffer calcbuf)
+	     (let (tempbuftop
+		   (xp xvalue)
+		   (yp yvalue)
+		   (zp nil)
+		   (xlow nil) (xhigh nil) (y3low nil) (y3high nil)
+		   xvec xval xstep var-DUMMY
+		   y3vec y3val y3step var-DUMMY2 (zval nil)
+		   yvec yval ycache ycacheptr yvector
+		   numsteps numsteps3
+		   (keep-file (and (not is-splot) (file-exists-p filename)))
+		   (stepcount 0)
+		   (calc-symbolic-mode nil)
+		   (calc-prefer-frac nil)
+		   (calc-internal-prec (max 3 precision))
+		   (calc-simplify-mode (and (not (memq calc-simplify-mode
+						       '(none num)))
+					    calc-simplify-mode))
+		   (blank t)
+		   (non-blank nil)
+		   (math-working-step 0)
+		   (math-working-step-2 nil))
+	       (save-excursion
+		 (if is-splot
+		     (calc-graph-compute-3d)
+		   (calc-graph-compute-2d))
+		 (set-buffer tempbuf)
+		 (goto-char (point-max))
+		 (insert "\n" xname)
+		 (if is-splot
+		     (insert ":" y3name))
+		 (insert ":" yname "\n\n")
+		 (setq tempbuftop (point))
+		 (let ((calc-group-digits nil)
+		       (calc-leading-zeros nil)
+		       (calc-number-radix 10)
+		       (entry (and (not is-splot)
+				   (list xp yp xhigh numsteps))))
+		   (or (equal entry
+			      (nth 1 (nth (1+ curve-num)
+					  calc-graph-file-cache)))
+		       (setq keep-file nil))
+		   (setcar (cdr (nth (1+ curve-num) calc-graph-file-cache))
+			   entry)
+		   (or keep-file
+		       (calc-graph-format-data)))
+		 (or keep-file
+		     (progn
+		       (or non-blank
+			   (error "No valid data points for %s:%s"
+				  xname yname))
+		       (write-region tempbuftop (point-max) filename
+				     nil 'quiet))))))
+	   (insert (prin1-to-string filename))))
+       (if surprise-splot
+	   (setcdr cache-env nil))
+       (if (= curve-num 0)
+	   (progn
+	     (calc-gnuplot-command "clear")
+	     (calc-clear-command-flag 'clear-message)
+	     (message "No data to plot!"))
+	 (setq calc-graph-data-cache-limit (max curve-num
+						calc-graph-data-cache-limit)
+	       filename (calc-temp-file-name 0))
+	 (write-region (point-min) (point-max) filename nil 'quiet)
+	 (calc-gnuplot-command "load" (prin1-to-string filename))
+	 (or (equal output "STDOUT")
+	     calc-gnuplot-keep-outfile
+	     (progn   ; need to close the output file before printing/plotting
+	       (setq calc-graph-last-output "STDOUT")
+	       (calc-gnuplot-command "set output")))
+	 (let ((command (if printing
+			    calc-gnuplot-print-command
+			  (or calc-gnuplot-plot-command
+			      (and (string-match "^dumb" device)
+				   'calc-graph-show-dumb)
+			      (and tty-output
+				   'calc-graph-show-tty)))))
+	   (if command
+	       (if (stringp command)
+		   (calc-gnuplot-command
+		    "!" (format command
+				(or tempoutfile
+				    calc-gnuplot-print-output)))
+		 (if (symbolp command)
+		     (funcall command output)
+		   (eval command)))))))))
+)
+
+(defun calc-graph-compute-2d ()
+  (if (setq yvec (eq (car-safe yvalue) 'vec))
+      (if (= (setq numsteps (1- (length yvalue))) 0)
+	  (error "Can't plot an empty vector")
+	(if (setq xvec (eq (car-safe xvalue) 'vec))
+	    (or (= (1- (length xvalue)) numsteps)
+		(error "%s and %s have different lengths" xname yname))
+	  (if (and (eq (car-safe xvalue) 'intv)
+		   (math-constp xvalue))
+	      (setq xstep (math-div (math-sub (nth 3 xvalue)
+					      (nth 2 xvalue))
+				    (1- numsteps))
+		    xvalue (nth 2 xvalue))
+	    (if (math-realp xvalue)
+		(setq xstep 1)
+	      (error "%s is not a suitable basis for %s" xname yname)))))
+    (or (math-realp yvalue)
+	(let ((arglist nil))
+	  (setq yvalue (math-evaluate-expr yvalue))
+	  (calc-default-formula-arglist yvalue)
+	  (or arglist
+	      (error "%s does not contain any unassigned variables" yname))
+	  (and (cdr arglist)
+	       (error "%s contains more than one variable: %s"
+		      yname arglist))
+	  (setq yvalue (math-expr-subst yvalue
+					(math-build-var-name (car arglist))
+					'(var DUMMY var-DUMMY)))))
+    (setq ycache (assoc yvalue calc-graph-data-cache))
+    (delq ycache calc-graph-data-cache)
+    (nconc calc-graph-data-cache
+	   (list (or ycache (setq ycache (list yvalue)))))
+    (if (and (not (setq xvec (eq (car-safe xvalue) 'vec)))
+	     refine (cdr (cdr ycache)))
+	(calc-graph-refine-2d)
+      (calc-graph-recompute-2d)))
+)
+
+(defun calc-graph-refine-2d ()
+  (setq keep-file nil
+	ycacheptr (cdr ycache))
+  (if (and (setq xval (calc-graph-find-command "xrange"))
+	   (string-match "\\`\\[\\([0-9.eE+-]*\\):\\([0-9.eE+-]*\\)\\]\\'"
+			 xval))
+      (let ((b2 (match-beginning 2))
+	    (e2 (match-end 2)))
+	(setq xlow (math-read-number (substring xval
+						(match-beginning 1)
+						(match-end 1)))
+	      xhigh (math-read-number (substring xval b2 e2))))
+    (if xlow
+	(while (and (cdr ycacheptr)
+		    (Math-lessp (car (nth 1 ycacheptr)) xlow))
+	  (setq ycacheptr (cdr ycacheptr)))))
+  (setq math-working-step-2 (1- (length ycacheptr)))
+  (while (and (cdr ycacheptr)
+	      (or (not xhigh)
+		  (Math-lessp (car (car ycacheptr)) xhigh)))
+    (setq var-DUMMY (math-div (math-add (car (car ycacheptr))
+					(car (nth 1 ycacheptr)))
+			      2)
+	  math-working-step (1+ math-working-step)
+	  yval (math-evaluate-expr yvalue))
+    (setcdr ycacheptr (cons (cons var-DUMMY yval)
+			    (cdr ycacheptr)))
+    (setq ycacheptr (cdr (cdr ycacheptr))))
+  (setq yp ycache
+	numsteps 1000000)
+)
+
+(defun calc-graph-recompute-2d ()
+  (setq ycacheptr ycache)
+  (if xvec
+      (setq numsteps (1- (length xvalue))
+	    yvector nil)
+    (if (and (eq (car-safe xvalue) 'intv)
+	     (math-constp xvalue))
+	(setq numsteps resolution
+	      yp nil
+	      xlow (nth 2 xvalue)
+	      xhigh (nth 3 xvalue)
+	      xstep (math-div (math-sub xhigh xlow)
+			      (1- numsteps))
+	      xvalue (nth 2 xvalue))
+      (error "%s is not a suitable basis for %s"
+	     xname yname)))
+  (setq math-working-step-2 numsteps)
+  (while (>= (setq numsteps (1- numsteps)) 0)
+    (setq math-working-step (1+ math-working-step))
+    (if xvec
+	(progn
+	  (setq xp (cdr xp)
+		xval (car xp))
+	  (and (not (eq ycacheptr ycache))
+	       (consp (car ycacheptr))
+	       (not (Math-lessp (car (car ycacheptr)) xval))
+	       (setq ycacheptr ycache)))
+      (if (= numsteps 0)
+	  (setq xval xhigh)   ; avoid cumulative roundoff
+	(setq xval xvalue
+	      xvalue (math-add xvalue xstep))))
+    (while (and (cdr ycacheptr)
+		(Math-lessp (car (nth 1 ycacheptr)) xval))
+      (setq ycacheptr (cdr ycacheptr)))
+    (or (and (cdr ycacheptr)
+	     (Math-equal (car (nth 1 ycacheptr)) xval))
+	(progn
+	  (setq keep-file nil
+		var-DUMMY xval)
+	  (setcdr ycacheptr (cons (cons xval (math-evaluate-expr yvalue))
+				  (cdr ycacheptr)))))
+    (setq ycacheptr (cdr ycacheptr))
+    (if xvec
+	(setq yvector (cons (cdr (car ycacheptr)) yvector))
+      (or yp (setq yp ycacheptr))))
+  (if xvec
+      (setq xp xvalue
+	    yvec t
+	    yp (cons 'vec (nreverse yvector))
+	    numsteps (1- (length xp)))
+    (setq numsteps 1000000))
+)
+
+(defun calc-graph-compute-3d ()
+  (if (setq yvec (eq (car-safe yvalue) 'vec))
+      (if (math-matrixp yvalue)
+	  (progn
+	    (setq numsteps (1- (length yvalue))
+		  numsteps3 (1- (length (nth 1 yvalue))))
+	    (if (eq (car-safe xvalue) 'vec)
+		(or (= (1- (length xvalue)) numsteps)
+		    (error "%s has wrong length" xname))
+	      (if (and (eq (car-safe xvalue) 'intv)
+		       (math-constp xvalue))
+		  (setq xvalue (calcFunc-index numsteps
+					       (nth 2 xvalue)
+					       (math-div
+						(math-sub (nth 3 xvalue)
+							  (nth 2 xvalue))
+						(1- numsteps))))
+		(if (math-realp xvalue)
+		    (setq xvalue (calcFunc-index numsteps xvalue 1))
+		  (error "%s is not a suitable basis for %s" xname yname))))
+	    (if (eq (car-safe y3value) 'vec)
+		(or (= (1- (length y3value)) numsteps3)
+		    (error "%s has wrong length" y3name))
+	      (if (and (eq (car-safe y3value) 'intv)
+		       (math-constp y3value))
+		  (setq y3value (calcFunc-index numsteps3
+						(nth 2 y3value)
+						(math-div
+						 (math-sub (nth 3 y3value)
+							   (nth 2 y3value))
+						 (1- numsteps3))))
+		(if (math-realp y3value)
+		    (setq y3value (calcFunc-index numsteps3 y3value 1))
+		  (error "%s is not a suitable basis for %s" y3name yname))))
+	    (setq xp nil
+		  yp nil
+		  zp nil
+		  xvec t)
+	    (while (setq xvalue (cdr xvalue) yvalue (cdr yvalue))
+	      (setq xp (nconc xp (make-list (1+ numsteps3) (car xvalue)))
+		    yp (nconc yp (cons 0 (copy-sequence (cdr y3value))))
+		    zp (nconc zp (cons '(skip)
+				       (copy-sequence (cdr (car yvalue)))))))
+	    (setq numsteps (1- (* numsteps (1+ numsteps3)))))
+	(if (= (setq numsteps (1- (length yvalue))) 0)
+	    (error "Can't plot an empty vector"))
+	(or (and (eq (car-safe xvalue) 'vec)
+		 (= (1- (length xvalue)) numsteps))
+	    (error "%s is not a suitable basis for %s" xname yname))
+	(or (and (eq (car-safe y3value) 'vec)
+		 (= (1- (length y3value)) numsteps))
+	    (error "%s is not a suitable basis for %s" y3name yname))
+	(setq xp xvalue
+	      yp y3value
+	      zp yvalue
+	      xvec t))
+    (or (math-realp yvalue)
+	(let ((arglist nil))
+	  (setq yvalue (math-evaluate-expr yvalue))
+	  (calc-default-formula-arglist yvalue)
+	  (setq arglist (sort arglist 'string-lessp))
+	  (or (cdr arglist)
+	      (error "%s does not contain enough unassigned variables" yname))
+	  (and (cdr (cdr arglist))
+	       (error "%s contains too many variables: %s" yname arglist))
+	  (setq yvalue (math-multi-subst yvalue
+					 (mapcar 'math-build-var-name
+						 arglist)
+					 '((var DUMMY var-DUMMY)
+					   (var DUMMY2 var-DUMMY2))))))
+    (if (setq xvec (eq (car-safe xvalue) 'vec))
+	(setq numsteps (1- (length xvalue)))
+      (if (and (eq (car-safe xvalue) 'intv)
+	       (math-constp xvalue))
+	  (setq numsteps resolution
+		xvalue (calcFunc-index numsteps
+				       (nth 2 xvalue)
+				       (math-div (math-sub (nth 3 xvalue)
+							   (nth 2 xvalue))
+						 (1- numsteps))))
+	(error "%s is not a suitable basis for %s"
+	       xname yname)))
+    (if (setq y3vec (eq (car-safe y3value) 'vec))
+	(setq numsteps3 (1- (length y3value)))
+      (if (and (eq (car-safe y3value) 'intv)
+	       (math-constp y3value))
+	  (setq numsteps3 resolution
+		y3value (calcFunc-index numsteps3
+					(nth 2 y3value)
+					(math-div (math-sub (nth 3 y3value)
+							    (nth 2 y3value))
+						  (1- numsteps3))))
+	(error "%s is not a suitable basis for %s"
+	       y3name yname)))
+    (setq xp nil
+	  yp nil
+	  zp nil
+	  xvec t)
+    (setq math-working-step 0)
+    (while (setq xvalue (cdr xvalue))
+      (setq xp (nconc xp (make-list (1+ numsteps3) (car xvalue)))
+	    yp (nconc yp (cons 0 (copy-sequence (cdr y3value))))
+	    zp (cons '(skip) zp)
+	    y3step y3value
+	    var-DUMMY (car xvalue)
+	    math-working-step-2 0
+	    math-working-step (1+ math-working-step))
+      (while (setq y3step (cdr y3step))
+	(setq math-working-step-2 (1+ math-working-step-2)
+	      var-DUMMY2 (car y3step)
+	      zp (cons (math-evaluate-expr yvalue) zp))))
+    (setq zp (nreverse zp)
+	  numsteps (1- (* numsteps (1+ numsteps3)))))
+)
+
+(defun calc-graph-format-data ()
+  (while (<= (setq stepcount (1+ stepcount)) numsteps)
+    (if xvec
+	(setq xp (cdr xp)
+	      xval (car xp)
+	      yp (cdr yp)
+	      yval (car yp)
+	      zp (cdr zp)
+	      zval (car zp))
+      (if yvec
+	  (setq xval xvalue
+		xvalue (math-add xvalue xstep)
+		yp (cdr yp)
+		yval (car yp))
+	(setq xval (car (car yp))
+	      yval (cdr (car yp))
+	      yp (cdr yp))
+	(if (or (not yp)
+		(and xhigh (equal xval xhigh)))
+	    (setq numsteps 0))))
+    (if is-splot
+	(if (and (eq (car-safe zval) 'calcFunc-xyz)
+		 (= (length zval) 4))
+	    (setq xval (nth 1 zval)
+		  yval (nth 2 zval)
+		  zval (nth 3 zval)))
+      (if (and (eq (car-safe yval) 'calcFunc-xyz)
+	       (= (length yval) 4))
+	  (progn
+	    (or surprise-splot
+		(save-excursion
+		  (set-buffer (get-buffer-create "*Gnuplot Temp*"))
+		  (save-excursion
+		    (goto-char (point-max))
+		    (re-search-backward "^plot[ \t]")
+		    (insert "set parametric\ns")
+		    (setq surprise-splot t))))
+	    (setq xval (nth 1 yval)
+		  zval (nth 3 yval)
+		  yval (nth 2 yval)))
+	(if (and (eq (car-safe yval) 'calcFunc-xy)
+		 (= (length yval) 3))
+	    (setq xval (nth 1 yval)
+		  yval (nth 2 yval)))))
+    (if (and (Math-realp xval)
+	     (Math-realp yval)
+	     (or (not zval) (Math-realp zval)))
+	(progn
+	  (setq blank nil
+		non-blank t)
+	  (if (Math-integerp xval)
+	      (insert (math-format-number xval))
+	    (if (eq (car xval) 'frac)
+		(setq xval (math-float xval)))
+	    (insert (math-format-number (nth 1 xval))
+		    "e" (int-to-string (nth 2 xval))))
+	  (insert " ")
+	  (if (Math-integerp yval)
+	      (insert (math-format-number yval))
+	    (if (eq (car yval) 'frac)
+		(setq yval (math-float yval)))
+	    (insert (math-format-number (nth 1 yval))
+		    "e" (int-to-string (nth 2 yval))))
+	  (if zval
+	      (progn
+		(insert " ")
+		(if (Math-integerp zval)
+		    (insert (math-format-number zval))
+		  (if (eq (car zval) 'frac)
+		      (setq zval (math-float zval)))
+		  (insert (math-format-number (nth 1 zval))
+			  "e" (int-to-string (nth 2 zval))))))
+	  (insert "\n"))
+      (and (not (equal zval '(skip)))
+	   (boundp 'var-PlotRejects)
+	   (eq (car-safe var-PlotRejects) 'vec)
+	   (nconc var-PlotRejects
+		  (list (list 'vec
+			      curve-num
+			      stepcount
+			      xval yval)))
+	   (calc-refresh-evaltos 'var-PlotRejects))
+      (or blank
+	  (progn
+	    (insert "\n")
+	    (setq blank t)))))
+)
+
+(defun calc-temp-file-name (num)
+  (while (<= (length calc-graph-file-cache) (1+ num))
+    (setq calc-graph-file-cache (nconc calc-graph-file-cache (list nil))))
+  (car (or (nth (1+ num) calc-graph-file-cache)
+	   (setcar (nthcdr (1+ num) calc-graph-file-cache)
+		   (list (make-temp-name
+			  (concat calc-gnuplot-tempfile
+				  (if (<= num 0)
+				      (char-to-string (- ?A num))
+				    (int-to-string num))))
+			 nil))))
+)
+
+(defun calc-graph-delete-temps ()
+  (while calc-graph-file-cache
+    (and (car calc-graph-file-cache)
+	 (file-exists-p (car (car calc-graph-file-cache)))
+	 (condition-case err
+	     (delete-file (car (car calc-graph-file-cache)))
+	   (error nil)))
+    (setq calc-graph-file-cache (cdr calc-graph-file-cache)))
+)
+
+(defun calc-graph-kill-hook ()
+  (calc-graph-delete-temps)
+  (if calc-graph-prev-kill-hook
+      (funcall calc-graph-prev-kill-hook))
+)
+
+(defun calc-graph-show-tty (output)
+  "Default calc-gnuplot-plot-command for \"tty\" output mode.
+This is useful for tek40xx and other graphics-terminal types."
+  (call-process-region 1 1 shell-file-name
+		       nil calc-gnuplot-buffer nil
+		       "-c" (format "cat %s >/dev/tty; rm %s" output output))
+)
+
+(defun calc-graph-show-dumb (&optional output)
+  "Default calc-gnuplot-plot-command for Pinard's \"dumb\" terminal type.
+This \"dumb\" driver will be present in Gnuplot 3.0."
+  (interactive)
+  (save-window-excursion
+    (switch-to-buffer calc-gnuplot-buffer)
+    (delete-other-windows)
+    (goto-char calc-gnuplot-trail-mark)
+    (or (search-forward "\f" nil t)
+	(sleep-for 1))
+    (goto-char (point-max))
+    (re-search-backward "\f\\|^[ \t]+\\^$\\|G N U P L O T")
+    (setq found-pt (point))
+    (if (looking-at "\f")
+	(progn
+	  (forward-char 1)
+	  (if (eolp) (forward-line 1))
+	  (or (calc-graph-find-command "time")
+	      (calc-graph-find-command "title")
+	      (calc-graph-find-command "ylabel")
+	      (let ((pt (point)))
+		(insert-before-markers (format "(%s)" (current-time-string)))
+		(goto-char pt)))
+	  (set-window-start (selected-window) (point))
+	  (goto-char (point-max)))
+      (end-of-line)
+      (backward-char 1)
+      (recenter '(4)))
+    (or (boundp 'calc-dumb-map)
+	(progn
+	  (setq calc-dumb-map (make-sparse-keymap))
+	  (define-key calc-dumb-map "\n" 'scroll-up)
+	  (define-key calc-dumb-map " " 'scroll-up)
+	  (define-key calc-dumb-map "\177" 'scroll-down)
+	  (define-key calc-dumb-map "<" 'scroll-left)
+	  (define-key calc-dumb-map ">" 'scroll-right)
+	  (define-key calc-dumb-map "{" 'scroll-down)
+	  (define-key calc-dumb-map "}" 'scroll-up)
+	  (define-key calc-dumb-map "q" 'exit-recursive-edit)
+	  (define-key calc-dumb-map "\C-c\C-c" 'exit-recursive-edit)))
+    (use-local-map calc-dumb-map)
+    (setq truncate-lines t)
+    (message "Type `q'%s to return to Calc."
+	     (if (eq (lookup-key (current-global-map) "\e#") 'calc-dispatch)
+		    " or `M-# M-#'" ""))
+    (recursive-edit)
+    (bury-buffer "*Gnuplot Trail*"))
+)
+
+(defun calc-graph-clear ()
+  (interactive)
+  (if calc-graph-last-device
+      (if (or (equal calc-graph-last-device "x11")
+	      (equal calc-graph-last-device "X11"))
+	  (calc-gnuplot-command "set output"
+				(if (equal calc-graph-last-output "STDOUT")
+				    ""
+				  (prin1-to-string calc-graph-last-output)))
+	(calc-gnuplot-command "clear")))
+)
+
+(defun calc-graph-title-x (title)
+  (interactive "sX axis title: ")
+  (calc-graph-set-command "xlabel" (if (not (equal title ""))
+				       (prin1-to-string title)))
+)
+
+(defun calc-graph-title-y (title)
+  (interactive "sY axis title: ")
+  (calc-graph-set-command "ylabel" (if (not (equal title ""))
+				       (prin1-to-string title)))
+)
+
+(defun calc-graph-title-z (title)
+  (interactive "sZ axis title: ")
+  (calc-graph-set-command "zlabel" (if (not (equal title ""))
+				       (prin1-to-string title)))
+)
+
+(defun calc-graph-range-x (range)
+  (interactive "sX axis range: ")
+  (calc-graph-set-range "xrange" range)
+)
+
+(defun calc-graph-range-y (range)
+  (interactive "sY axis range: ")
+  (calc-graph-set-range "yrange" range)
+)
+
+(defun calc-graph-range-z (range)
+  (interactive "sZ axis range: ")
+  (calc-graph-set-range "zrange" range)
+)
+
+(defun calc-graph-set-range (cmd range)
+  (if (equal range "$")
+      (calc-wrapper
+       (let ((val (calc-top-n 1)))
+	 (if (and (eq (car-safe val) 'intv) (math-constp val))
+	     (setq range (concat
+			  (math-format-number (math-float (nth 2 val))) ":"
+			  (math-format-number (math-float (nth 3 val)))))
+	   (if (and (eq (car-safe val) 'vec)
+		    (= (length val) 3))
+	       (setq range (concat
+			    (math-format-number (math-float (nth 1 val))) ":"
+			    (math-format-number (math-float (nth 2 val)))))
+	     (error "Range specification must be an interval or 2-vector")))
+	 (calc-pop-stack 1))))
+  (if (string-match "\\[.+\\]" range)
+      (setq range (substring range 1 -1)))
+  (if (and (not (string-match ":" range))
+	   (or (string-match "," range)
+	       (string-match " " range)))
+      (aset range (match-beginning 0) ?\:))
+  (calc-graph-set-command cmd (if (not (equal range ""))
+				  (concat "[" range "]")))
+)
+
+(defun calc-graph-log-x (flag)
+  (interactive "P")
+  (calc-graph-set-log flag 0 0)
+)
+
+(defun calc-graph-log-y (flag)
+  (interactive "P")
+  (calc-graph-set-log 0 flag 0)
+)
+
+(defun calc-graph-log-z (flag)
+  (interactive "P")
+  (calc-graph-set-log 0 0 flag)
+)
+
+(defun calc-graph-set-log (xflag yflag zflag)
+  (let* ((old (or (calc-graph-find-command "logscale") ""))
+	 (xold (string-match "x" old))
+	 (yold (string-match "y" old))
+	 (zold (string-match "z" old))
+	 str)
+    (setq str (concat (if (if xflag
+			      (if (eq xflag 0) xold
+				(> (prefix-numeric-value xflag) 0))
+			    (not xold)) "x" "")
+		      (if (if yflag
+			      (if (eq yflag 0) yold
+				(> (prefix-numeric-value yflag) 0))
+			    (not yold)) "y" "")
+		      (if (if zflag
+			      (if (eq zflag 0) zold
+				(> (prefix-numeric-value zflag) 0))
+			    (not zold)) "z" "")))
+    (calc-graph-set-command "logscale" (if (not (equal str "")) str)))
+)
+
+(defun calc-graph-line-style (style)
+  (interactive "P")
+  (calc-graph-set-styles (and style (prefix-numeric-value style)) t)
+)
+
+(defun calc-graph-point-style (style)
+  (interactive "P")
+  (calc-graph-set-styles t (and style (prefix-numeric-value style)))
+)
+
+(defun calc-graph-set-styles (lines points)
+  (calc-graph-init)
+  (save-excursion
+    (set-buffer calc-gnuplot-input)
+    (or (calc-graph-find-plot nil nil)
+	(error "No data points have been set!"))
+    (let ((base (point))
+	  (mode nil) (lstyle nil) (pstyle nil)
+	  start end lenbl penbl)
+      (re-search-forward "[,\n]")
+      (forward-char -1)
+      (setq end (point) start end)
+      (goto-char base)
+      (if (looking-at "[^,\n]*[^,\n \t]\\([ \t]+with\\)")
+	  (progn
+	    (setq start (match-beginning 1))
+	    (goto-char (match-end 0))
+	    (if (looking-at "[ \t]+\\([a-z]+\\)")
+		(setq mode (buffer-substring (match-beginning 1)
+					     (match-end 1))))
+	    (if (looking-at "[ \ta-z]+\\([0-9]+\\)")
+		(setq lstyle (string-to-int
+			      (buffer-substring (match-beginning 1)
+						(match-end 1)))))
+	    (if (looking-at "[ \ta-z]+[0-9]+[ \t]+\\([0-9]+\\)")
+		(setq pstyle (string-to-int
+			      (buffer-substring (match-beginning 1)
+						(match-end 1)))))))
+      (setq lenbl (or (equal mode "lines") (equal mode "linespoints"))
+	    penbl (or (equal mode "points") (equal mode "linespoints")))
+      (if lines
+	  (or (eq lines t)
+	      (setq lstyle lines
+		    lenbl (>= lines 0)))
+	(setq lenbl (not lenbl)))
+      (if points
+	  (or (eq points t)
+	      (setq pstyle points
+		    penbl (>= points 0)))
+	(setq penbl (not penbl)))
+      (delete-region start end)
+      (goto-char start)
+      (insert " with "
+	      (if lenbl
+		  (if penbl "linespoints" "lines")
+		(if penbl "points" "dots")))
+      (if (and pstyle (> pstyle 0))
+	  (insert " " (if (and lstyle (> lstyle 0)) (int-to-string lstyle) "1")
+		  " " (int-to-string pstyle))
+	(if (and lstyle (> lstyle 0))
+	    (insert " " (int-to-string lstyle))))))
+  (calc-graph-view-commands)
+)
+
+(defun calc-graph-zero-x (flag)
+  (interactive "P")
+  (calc-graph-set-command "noxzeroaxis"
+			  (and (if flag
+				   (<= (prefix-numeric-value flag) 0)
+				 (not (calc-graph-find-command "noxzeroaxis")))
+			       " "))
+)
+
+(defun calc-graph-zero-y (flag)
+  (interactive "P")
+  (calc-graph-set-command "noyzeroaxis"
+			  (and (if flag
+				   (<= (prefix-numeric-value flag) 0)
+				 (not (calc-graph-find-command "noyzeroaxis")))
+			       " "))
+)
+
+(defun calc-graph-name (name)
+  (interactive "sTitle for current curve: ")
+  (calc-graph-init)
+  (save-excursion
+    (set-buffer calc-gnuplot-input)
+    (or (calc-graph-find-plot nil nil)
+	(error "No data points have been set!"))
+    (let ((base (point))
+	  start)
+      (re-search-forward "[,\n]\\|[ \t]+with")
+      (setq end (match-beginning 0))
+      (goto-char base)
+      (if (looking-at "[^,\n]*[^,\n \t]\\([ \t]+title\\)")
+	  (progn
+	    (goto-char (match-beginning 1))
+	    (delete-region (point) end))
+	(goto-char end))
+      (insert " title " (prin1-to-string name))))
+  (calc-graph-view-commands)
+)
+
+(defun calc-graph-hide (flag)
+  (interactive "P")
+  (calc-graph-init)
+  (and (calc-graph-find-plot nil nil)
+       (progn
+	 (or (looking-at "{")
+	     (error "Can't hide this curve (wrong format)"))
+	 (forward-char 1)
+	 (if (looking-at "*")
+	     (if (or (null flag) (<= (prefix-numeric-value flag) 0))
+		 (delete-char 1))
+	   (if (or (null flag) (> (prefix-numeric-value flag) 0))
+	       (insert "*")))))
+)
+
+(defun calc-graph-header (title)
+  (interactive "sTitle for entire graph: ")
+  (calc-graph-set-command "title" (if (not (equal title ""))
+				      (prin1-to-string title)))
+)
+
+(defun calc-graph-border (flag)
+  (interactive "P")
+  (calc-graph-set-command "noborder"
+			  (and (if flag
+				   (<= (prefix-numeric-value flag) 0)
+				 (not (calc-graph-find-command "noborder")))
+			       " "))
+)
+
+(defun calc-graph-grid (flag)
+  (interactive "P")
+  (calc-graph-set-command "grid" (and (if flag
+					  (> (prefix-numeric-value flag) 0)
+					(not (calc-graph-find-command "grid")))
+				      " "))
+)
+
+(defun calc-graph-key (flag)
+  (interactive "P")
+  (calc-graph-set-command "key" (and (if flag
+					 (> (prefix-numeric-value flag) 0)
+				       (not (calc-graph-find-command "key")))
+				     " "))
+)
+
+(defun calc-graph-num-points (res flag)
+  (interactive "sNumber of data points: \nP")
+  (if flag
+      (if (> (prefix-numeric-value flag) 0)
+	  (if (equal res "")
+	      (message "Default resolution is %d."
+		       calc-graph-default-resolution)
+	    (setq calc-graph-default-resolution (string-to-int res)))
+	(if (equal res "")
+	    (message "Default 3D resolution is %d."
+		     calc-graph-default-resolution-3d)
+	  (setq calc-graph-default-resolution-3d (string-to-int res))))
+    (calc-graph-set-command "samples" (if (not (equal res "")) res)))
+)
+
+(defun calc-graph-device (name flag)
+  (interactive "sDevice name: \nP")
+  (if (equal name "?")
+      (progn
+	(calc-gnuplot-command "set terminal")
+	(calc-graph-view-trail))
+    (if flag
+	(if (> (prefix-numeric-value flag) 0)
+	    (if (equal name "")
+		(message "Default GNUPLOT device is \"%s\"."
+			 calc-gnuplot-default-device)
+	      (setq calc-gnuplot-default-device name))
+	  (if (equal name "")
+	      (message "GNUPLOT device for Print command is \"%s\"."
+		       calc-gnuplot-print-device)
+	    (setq calc-gnuplot-print-device name)))
+      (calc-graph-set-command "terminal" (if (not (equal name ""))
+					     name))))
+)
+
+(defun calc-graph-output (name flag)
+  (interactive "FOutput file name: \np")
+  (cond ((string-match "\\<[aA][uU][tT][oO]$" name)
+	 (setq name "auto"))
+	((string-match "\\<[tT][tT][yY]$" name)
+	 (setq name "tty"))
+	((string-match "\\<[sS][tT][dD][oO][uU][tT]$" name)
+	 (setq name "STDOUT"))
+	((equal (file-name-nondirectory name) "")
+	 (setq name ""))
+	(t (setq name (expand-file-name name))))
+  (if flag
+      (if (> (prefix-numeric-value flag) 0)
+	  (if (equal name "")
+	      (message "Default GNUPLOT output file is \"%s\"."
+		       calc-gnuplot-default-output)
+	    (setq calc-gnuplot-default-output name))
+	(if (equal name "")
+	    (message "GNUPLOT output file for Print command is \"%s\"."
+		     calc-gnuplot-print-output)
+	  (setq calc-gnuplot-print-output name)))
+    (calc-graph-set-command "output" (if (not (equal name ""))
+					 (prin1-to-string name))))
+)
+
+(defun calc-graph-display (name)
+  (interactive "sX display name: ")
+  (if (equal name "")
+      (message "Current X display is \"%s\"."
+	       (or calc-gnuplot-display "<none>"))
+    (setq calc-gnuplot-display name)
+    (if (calc-gnuplot-alive)
+	(calc-gnuplot-command "exit")))
+)
+
+(defun calc-graph-geometry (name)
+  (interactive "sX geometry spec (or \"default\"): ")
+  (if (equal name "")
+      (message "Current X geometry is \"%s\"."
+	       (or calc-gnuplot-geometry "default"))
+    (setq calc-gnuplot-geometry (and (not (equal name "default")) name))
+    (if (calc-gnuplot-alive)
+	(calc-gnuplot-command "exit")))
+)
+
+(defun calc-graph-find-command (cmd)
+  (calc-graph-init)
+  (save-excursion
+    (set-buffer calc-gnuplot-input)
+    (goto-char (point-min))
+    (if (re-search-forward (concat "^set[ \t]+" cmd "[ \t]*\\(.*\\)$") nil t)
+	(buffer-substring (match-beginning 1) (match-end 1))))
+)
+
+(defun calc-graph-set-command (cmd &rest args)
+  (calc-graph-init)
+  (save-excursion
+    (set-buffer calc-gnuplot-input)
+    (goto-char (point-min))
+    (if (re-search-forward (concat "^set[ \t]+" cmd "[ \t\n]") nil t)
+	(progn
+	  (forward-char -1)
+	  (end-of-line)
+	  (let ((end (point)))
+	    (beginning-of-line)
+	    (delete-region (point) (1+ end))))
+      (if (calc-graph-find-plot t t)
+	  (if (eq (preceding-char) ?\n)
+	      (forward-char -1))
+	(goto-char (1- (point-max)))))
+    (if (and args (car args))
+	(progn
+	  (or (bolp)
+	      (insert "\n"))
+	  (insert "set " (mapconcat 'identity (cons cmd args) " ") "\n"))))
+  (calc-graph-view-commands)
+)
+
+(defun calc-graph-command (cmd)
+  (interactive "sGNUPLOT command: ")
+  (calc-wrapper
+   (calc-graph-init)
+   (calc-graph-view-trail)
+   (calc-gnuplot-command cmd)
+   (accept-process-output)
+   (calc-graph-view-trail))
+)
+
+(defun calc-graph-kill (&optional no-view)
+  (interactive)
+  (calc-graph-delete-temps)
+  (if (calc-gnuplot-alive)
+      (calc-wrapper
+       (or no-view (calc-graph-view-trail))
+       (let ((calc-graph-no-wait t))
+	 (calc-gnuplot-command "exit"))
+       (sit-for 1)
+       (if (process-status calc-gnuplot-process)
+	   (delete-process calc-gnuplot-process))
+       (setq calc-gnuplot-process nil)))
+)
+
+(defun calc-graph-quit ()
+  (interactive)
+  (if (get-buffer-window calc-gnuplot-input)
+      (calc-graph-view-commands t))
+  (if (get-buffer-window calc-gnuplot-buffer)
+      (calc-graph-view-trail t))
+  (calc-graph-kill t)
+)
+
+(defun calc-graph-view-commands (&optional no-need)
+  (interactive "p")
+  (or calc-graph-no-auto-view (calc-graph-init-buffers))
+  (calc-graph-view calc-gnuplot-input calc-gnuplot-buffer (null no-need))
+)
+
+(defun calc-graph-view-trail (&optional no-need)
+  (interactive "p")
+  (or calc-graph-no-auto-view (calc-graph-init-buffers))
+  (calc-graph-view calc-gnuplot-buffer calc-gnuplot-input (null no-need))
+)
+
+(defun calc-graph-view (buf other-buf need)
+  (let (win)
+    (or calc-graph-no-auto-view
+	(if (setq win (get-buffer-window buf))
+	    (or need
+		(and (eq buf calc-gnuplot-buffer)
+		     (save-excursion
+		       (set-buffer buf)
+		       (not (pos-visible-in-window-p (point-max) win))))
+		(progn
+		  (bury-buffer buf)
+		  (bury-buffer other-buf)
+		  (let ((curwin (selected-window)))
+		    (select-window win)
+		    (switch-to-buffer nil)
+		    (select-window curwin))))
+	  (if (setq win (get-buffer-window other-buf))
+	      (set-window-buffer win buf)
+	    (if (eq major-mode 'calc-mode)
+		(if (or need
+			(< (window-height) (1- (screen-height))))
+		    (display-buffer buf))
+	      (switch-to-buffer buf)))))
+    (save-excursion
+      (set-buffer buf)
+      (if (and (eq buf calc-gnuplot-buffer)
+	       (setq win (get-buffer-window buf))
+	       (not (pos-visible-in-window-p (point-max) win)))
+	  (progn
+	    (goto-char (point-max))
+	    (vertical-motion (- 6 (window-height win)))
+	    (set-window-start win (point))
+	    (goto-char (point-max)))))
+    (or calc-graph-no-auto-view (sit-for 0)))
+)
+(setq calc-graph-no-auto-view nil)
+
+(defun calc-gnuplot-check-for-errors ()
+  (if (save-excursion
+	(prog2
+	 (progn
+	   (set-buffer calc-gnuplot-buffer)
+	   (goto-char calc-gnuplot-last-error-pos))
+	 (re-search-forward "^[ \t]+\\^$" nil t)
+	 (goto-char (point-max))
+	 (setq calc-gnuplot-last-error-pos (point-max))))
+      (calc-graph-view-trail))
+)
+
+(defun calc-gnuplot-command (&rest args)
+  (calc-graph-init)
+  (let ((cmd (concat (mapconcat 'identity args " ") "\n")))
+    (accept-process-output)
+    (save-excursion
+      (set-buffer calc-gnuplot-buffer)
+      (calc-gnuplot-check-for-errors)
+      (goto-char (point-max))
+      (setq calc-gnuplot-trail-mark (point))
+      (or (>= calc-gnuplot-version 3)
+	  (insert cmd))
+      (set-marker (process-mark calc-gnuplot-process) (point))
+      (process-send-string calc-gnuplot-process cmd)
+      (if (get-buffer-window calc-gnuplot-buffer)
+	  (calc-graph-view-trail))
+      (accept-process-output (and (not calc-graph-no-wait)
+				  calc-gnuplot-process))
+      (calc-gnuplot-check-for-errors)
+      (if (get-buffer-window calc-gnuplot-buffer)
+	  (calc-graph-view-trail))))
+)
+(setq calc-graph-no-wait nil)
+
+(defun calc-graph-init-buffers ()
+  (or (and calc-gnuplot-buffer
+	   (buffer-name calc-gnuplot-buffer))
+      (setq calc-gnuplot-buffer (get-buffer-create "*Gnuplot Trail*")))
+  (or (and calc-gnuplot-input
+	   (buffer-name calc-gnuplot-input))
+      (setq calc-gnuplot-input (get-buffer-create "*Gnuplot Commands*")))
+)
+
+(defun calc-graph-init ()
+  (or (calc-gnuplot-alive)
+      (let ((process-connection-type t)
+	    origin)
+	(if calc-gnuplot-process
+	    (progn
+	      (delete-process calc-gnuplot-process)
+	      (setq calc-gnuplot-process nil)))
+	(calc-graph-init-buffers)
+	(save-excursion
+	  (set-buffer calc-gnuplot-buffer)
+	  (insert "\nStarting gnuplot...\n")
+	  (setq origin (point)))
+	(setq calc-graph-last-device nil)
+	(setq calc-graph-last-output nil)
+	(condition-case err
+	    (let ((args (append (and calc-gnuplot-display
+				     (not (equal calc-gnuplot-display
+						 (getenv "DISPLAY")))
+				     (list "-display"
+					   calc-gnuplot-display))
+				(and calc-gnuplot-geometry
+				     (list "-geometry"
+					   calc-gnuplot-geometry)))))
+	      (setq calc-gnuplot-process 
+		    (apply 'start-process
+			   "gnuplot"
+			   calc-gnuplot-buffer
+			   calc-gnuplot-name
+			   args))
+	      (process-kill-without-query calc-gnuplot-process))
+	  (file-error
+	   (error "Sorry, can't find \"%s\" on your system."
+		  calc-gnuplot-name)))
+	(save-excursion
+	  (set-buffer calc-gnuplot-buffer)
+	  (while (and (not (save-excursion
+			     (goto-char origin)
+			     (search-forward "gnuplot> " nil t)))
+		      (memq (process-status calc-gnuplot-process) '(run stop)))
+	    (accept-process-output calc-gnuplot-process))
+	  (or (memq (process-status calc-gnuplot-process) '(run stop))
+	      (error "Unable to start GNUPLOT process."))
+	  (if (save-excursion
+		(goto-char origin)
+		(re-search-forward
+		 "G N U P L O T.*\n.*version \\([0-9]+\\)\\." nil t))
+	      (setq calc-gnuplot-version (string-to-int (buffer-substring
+							 (match-beginning 1)
+							 (match-end 1))))
+	    (setq calc-gnuplot-version 1))
+	  (goto-char (point-max)))))
+  (save-excursion
+    (set-buffer calc-gnuplot-input)
+    (if (= (buffer-size) 0)
+	(insert "# Commands for running gnuplot\n\n\n")
+      (or calc-graph-no-auto-view
+	  (eq (char-after (1- (point-max))) ?\n)
+	  (progn
+	    (goto-char (point-max))
+	    (insert "\n")))))
+)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/calc-help.el	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,686 @@
+;; Calculator for GNU Emacs, part II [calc-help.el]
+;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+;; Written by Dave Gillespie, daveg@synaptics.com.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY.  No author or distributor
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing.  Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License.   A copy of this license is
+;; supposed to have been given to you along with GNU Emacs so you
+;; can know your rights and responsibilities.  It should be in a
+;; file named COPYING.  Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+
+
+
+;; This file is autoloaded from calc-ext.el.
+(require 'calc-ext)
+
+(require 'calc-macs)
+
+(defun calc-Need-calc-help () nil)
+
+
+(defun calc-help-prefix (arg)
+  "This key is the prefix for Calc help functions.  See calc-help-for-help."
+  (interactive "P")
+  (or calc-dispatch-help (sit-for echo-keystrokes))
+  (let ((key (calc-read-key-sequence
+	      (if calc-dispatch-help
+		  "Calc Help options: Help, Info, Tutorial, Summary; Key, Function; ?=more"
+		(format "%s  (Type ? for a list of Calc Help options)"
+			(key-description (this-command-keys))))
+	      calc-help-map)))
+    (setq key (lookup-key calc-help-map key))
+    (message "")
+    (if key
+	(call-interactively key)
+      (beep)))
+)
+
+(defun calc-help-for-help (arg)
+  "You have typed `h', the Calc help character.  Type a Help option:
+
+B  calc-describe-bindings.  Display a table of all key bindings.
+H  calc-full-help.  Display all `?' key messages at once.
+
+I  calc-info.  Read the Calc manual using the Info system.
+T  calc-tutorial.  Read the Calc tutorial using the Info system.
+S  calc-info-summary.  Read the Calc summary using the Info system.
+
+C  calc-describe-key-briefly.  Look up the command name for a given key.
+K  calc-describe-key.  Look up a key's documentation in the manual.
+F  calc-describe-function.  Look up a function's documentation in the manual.
+V  calc-describe-variable.  Look up a variable's documentation in the manual.
+
+N  calc-view-news.  Display Calc history of changes.
+
+C-c  Describe conditions for copying Calc.
+C-d  Describe how you can get a new copy of Calc or report a bug.
+C-w  Describe how there is no warranty for Calc."
+  (interactive "P")
+  (if calc-dispatch-help
+      (let (key)
+	(save-window-excursion
+	  (describe-function 'calc-help-for-help)
+	  (select-window (get-buffer-window "*Help*"))
+	  (while (progn
+		   (message "Calc Help options: Help, Info, ...  press SPC, DEL to scroll, C-g to cancel")
+		   (memq (car (setq key (calc-read-key t)))
+			 '(?  ?\C-h ?\C-? ?\C-v ?\M-v)))
+	    (condition-case err
+		(if (memq (car key) '(?  ?\C-v))
+		    (scroll-up)
+		  (scroll-down))
+	      (error (beep)))))
+	(calc-unread-command (cdr key))
+	(calc-help-prefix nil))
+    (let ((calc-dispatch-help t))
+      (calc-help-prefix arg)))
+)
+
+(defun calc-describe-copying ()
+  (interactive)
+  (calc-info)
+  (Info-goto-node "Copying")
+)
+
+(defun calc-describe-distribution ()
+  (interactive)
+  (calc-info)
+  (Info-goto-node "Reporting Bugs")
+)
+
+(defun calc-describe-no-warranty ()
+  (interactive)
+  (calc-info)
+  (Info-goto-node "Copying")
+  (let ((case-fold-search nil))
+    (search-forward "     NO WARRANTY"))
+  (beginning-of-line)
+  (recenter 0)
+)
+
+(defun calc-describe-bindings ()
+  (interactive)
+  (describe-bindings)
+  (save-excursion
+    (set-buffer "*Help*")
+    (goto-char (point-min))
+    (if (search-forward "Global bindings:" nil t)
+	(delete-region (match-beginning 0) (point-max)))
+    (goto-char (point-min))
+    (while (re-search-forward "\n[a-z] ESC" nil t)
+      (end-of-line)
+      (delete-region (match-beginning 0) (point)))
+    (goto-char (point-min))
+    (while (re-search-forward "\nESC m" nil t)
+      (end-of-line)
+      (delete-region (match-beginning 0) (point)))
+    (goto-char (point-min))
+    (while (search-forward "\n\n\n" nil t)
+      (backward-delete-char 1)
+      (backward-char 2))
+    (goto-char (point-min))
+    (while
+	(re-search-forward
+	 "\n[a-z] [0-9]\\(\t\t.*\n\\)\\([a-z] [0-9]\\1\\)*[a-z] \\([0-9]\\)\\1"
+	 nil t)
+      (let ((dig1 (char-after (1- (match-beginning 1))))
+	    (dig2 (char-after (match-beginning 3))))
+	(delete-region (match-end 1) (match-end 0))
+	(goto-char (match-beginning 1))
+	(delete-backward-char 1)
+	(delete-char 1)
+	(insert (format "%c .. %c" (min dig1 dig2) (max dig1 dig2)))))
+    (goto-char (point-min)))
+)
+
+(defun calc-describe-key-briefly (key)
+  (interactive "kDescribe key briefly: ")
+  (calc-describe-key key t)
+)
+
+(defun calc-describe-key (key &optional briefly)
+  (interactive "kDescribe key: ")
+  (let ((defn (if (eq (key-binding key) 'calc-dispatch)
+		  (let ((key2 (calc-read-key-sequence
+			       (format "Describe key briefly: %s-"
+				       (key-description key))
+			       calc-dispatch-map)))
+		    (setq key (concat key key2))
+		    (lookup-key calc-dispatch-map key2))
+		(if (eq (key-binding key) 'calc-help-prefix)
+		    (let ((key2 (calc-read-key-sequence
+				 (format "Describe key briefly: %s-"
+					 (key-description key))
+				 calc-help-map)))
+		      (setq key (concat key key2))
+		      (lookup-key calc-help-map key2))
+		  (key-binding key))))
+	(inv nil)
+	(hyp nil))
+    (while (or (equal key "I") (equal key "H"))
+      (if (equal key "I")
+	  (setq inv (not inv))
+	(setq hyp (not hyp)))
+      (setq key (read-key-sequence (format "Describe key%s:%s%s "
+					   (if briefly " briefly" "")
+					   (if inv " I" "")
+					   (if hyp " H" "")))
+	    defn (key-binding key)))
+    (let ((desc (key-description key))
+	  target)
+      (if (string-match "^ESC " desc)
+	  (setq desc (concat "M-" (substring desc 4))))
+      (while (string-match "^M-# \\(ESC \\|C-\\)" desc)
+	(setq desc (concat "M-# " (substring desc (match-end 0)))))
+      (if briefly
+	  (let ((msg (save-excursion
+		       (set-buffer (get-buffer-create "*Calc Summary*"))
+		       (if (= (buffer-size) 0)
+			   (progn
+			     (message "Reading Calc summary from manual...")
+			     (save-window-excursion
+			       (save-excursion
+				 (calc-info)
+				 (Info-goto-node "Summary")
+				 (goto-char (point-min))
+				 (forward-line 1)
+				 (copy-to-buffer "*Calc Summary*"
+						 (point) (point-max))
+				 (Info-last)))
+			     (setq case-fold-search nil)
+			     (re-search-forward "^\\(.*\\)\\[\\.\\. a b")
+			     (setq calc-summary-indentation
+				   (- (match-end 1) (match-beginning 1)))))
+		       (goto-char (point-min))
+		       (setq target (if (and (string-match "[0-9]\\'" desc)
+					     (not (string-match "[d#]" desc)))
+					(concat (substring desc 0 -1) "0-9")
+				      desc))
+		       (if (re-search-forward
+			    (format "\n%s%s%s%s[ a-zA-Z]"
+				    (make-string (+ calc-summary-indentation 9)
+						 ?\.)
+				    (if (string-match "M-#" desc) "   "
+				      (if inv
+					  (if hyp "I H " "  I ")
+					(if hyp "  H " "    ")))
+				    (regexp-quote target)
+				    (make-string (max (- 6 (length target)) 0)
+						 ?\ ))
+			    nil t)
+			   (let (pt)
+			     (beginning-of-line)
+			     (forward-char calc-summary-indentation)
+			     (setq pt (point))
+			     (end-of-line)
+			     (buffer-substring pt (point)))))))
+	    (if msg
+		(let ((args (substring msg 0 9))
+		      (keys (substring msg 9 19))
+		      (prompts (substring msg 19 38))
+		      (notes "")
+		      (cmd (substring msg 40))
+		      msg)
+		  (if (string-match "\\` +" args)
+		      (setq args (substring args (match-end 0))))
+		  (if (string-match " +\\'" args)
+		      (setq args (substring args 0 (match-beginning 0))))
+		  (if (string-match "\\` +" keys)
+		      (setq keys (substring keys (match-end 0))))
+		  (if (string-match " +\\'" keys)
+		      (setq keys (substring keys 0 (match-beginning 0))))
+		  (if (string-match " [0-9,]+\\'" prompts)
+		      (setq notes (substring prompts (1+ (match-beginning 0)))
+			    prompts (substring prompts 0 (match-beginning 0))))
+		  (if (string-match " +\\'" prompts)
+		      (setq prompts (substring prompts 0 (match-beginning 0))))
+		  (if (string-match "\\` +" prompts)
+		      (setq prompts (substring prompts (match-end 0))))
+		  (setq msg (format
+			     "%s:  %s%s`%s'%s%s %s%s"
+			     (if (string-match
+				  "\\`\\(calc-[-a-zA-Z0-9]+\\) *\\(.*\\)\\'"
+				  cmd)
+				 (prog1 (math-match-substring cmd 1)
+				   (setq cmd (math-match-substring cmd 2)))
+			       defn)
+			     args (if (equal args "") "" " ")
+			     keys
+			     (if (equal prompts "") "" " ") prompts
+			     (if (equal cmd "") "" " => ") cmd))
+		  (message "%s%s%s runs %s%s"
+			   (if inv "I " "") (if hyp "H " "") desc
+			   msg
+			   (if (equal notes "") ""
+			     (format "  (?=notes %s)" notes)))
+		  (let ((key (calc-read-key t)))
+		    (if (eq (car key) ??)
+			(if (equal notes "")
+			    (message "No notes for this command")
+			  (while (string-match "," notes)
+			    (aset notes (match-beginning 0) ? ))
+			  (setq notes (sort (car (read-from-string
+						  (format "(%s)" notes)))
+					    '<))
+			  (with-output-to-temp-buffer "*Help*"
+			    (princ (format "%s\n\n" msg))
+			    (set-buffer "*Calc Summary*")
+			    (re-search-forward "^ *NOTES")
+			    (while notes
+			      (re-search-forward
+			       (format "^ *%d\\. " (car notes)))
+			      (beginning-of-line)
+			      (let ((pt (point)))
+				(forward-line 1)
+				(or (re-search-forward "^ ? ?[0-9]+\\. " nil t)
+				    (goto-char (point-max)))
+				(beginning-of-line)
+				(princ (buffer-substring pt (point))))
+			      (setq notes (cdr notes)))
+			    (print-help-return-message)))
+		      (calc-unread-command (cdr key)))))
+	      (if (or (null defn) (integerp defn))
+		  (message "%s is undefined" desc)
+		(message "%s runs the command %s"
+			 desc
+			 (if (symbolp defn) defn (prin1-to-string defn))))))
+	(if inv (setq desc (concat "I " desc)))
+	(if hyp (setq desc (concat "H " desc)))
+	(calc-describe-thing desc "Key Index" nil
+			     (string-match "[A-Z][A-Z][A-Z]" desc)))))
+)
+
+(defun calc-describe-function (&optional func)
+  (interactive)
+  (or func
+      (setq func (intern (completing-read "Describe function: "
+					  obarray nil t "calcFunc-"))))
+  (setq func (symbol-name func))
+  (if (string-match "\\`calc-." func)
+      (calc-describe-thing func "Command Index")
+    (calc-describe-thing (if (string-match "\\`calcFunc-." func)
+			     (substring func 9)
+			   func)
+			 "Function Index"))
+)
+
+(defun calc-describe-variable (&optional var)
+  (interactive)
+  (or var
+      (setq var (intern (completing-read "Describe variable: "
+					 obarray nil t "var-"))))
+  (setq var (symbol-name var))
+  (calc-describe-thing var "Variable Index"
+		       (if (string-match "\\`var-." var)
+			   (substring var 4)
+			 var))
+)
+
+(defun calc-describe-thing (thing where &optional target not-quoted)
+  (message "Looking for `%s' in %s..." thing where)
+  (let ((savewin (current-window-configuration)))
+    (calc-info)
+    (Info-goto-node where)
+    (or (let ((case-fold-search nil))
+	  (re-search-forward (format "\n\\* +%s: \\(.*\\)\\."
+				     (regexp-quote thing))
+			     nil t))
+	(and (string-match "\\`\\([a-z ]*\\)[0-9]\\'" thing)
+	     (re-search-forward (format "\n\\* +%s[01]-9: \\(.*\\)\\."
+					(substring thing 0 -1))
+				nil t)
+	     (setq thing (format "%s9" (substring thing 0 -1))))
+	(progn
+	  (Info-last)
+	  (set-window-configuration savewin)
+	  (error "Can't find `%s' in %s" thing where)))
+    (let (Info-history)
+      (Info-goto-node (buffer-substring (match-beginning 1) (match-end 1))))
+    (or (let ((case-fold-search nil))
+	  (or (search-forward (format "\\[`%s'\\]\\|(`%s')\\|\\<The[ \n]`%s'"
+				      (or target thing)
+				      (or target thing)
+				      (or target thing)) nil t)
+	      (and not-quoted
+		   (let ((case-fold-search t))
+		     (search-forward (or target thing) nil t)))
+	      (search-forward (format "`%s'" (or target thing)) nil t)
+	      (search-forward (or target thing) nil t)))
+	(let ((case-fold-search t))
+	  (or (search-forward (format "\\[`%s'\\]\\|(`%s')\\|\\<The[ \n]`%s'"
+				      (or target thing)
+				      (or target thing)
+				      (or target thing)) nil t)
+	      (search-forward (format "`%s'" (or target thing)) nil t)
+	      (search-forward (or target thing) nil t))))
+    (beginning-of-line)
+    (message "Found `%s' in %s" thing where))
+)
+
+(defun calc-view-news ()
+  (interactive)
+  (let ((path load-path))
+    (while (and path
+		(not (file-exists-p (expand-file-name "calc.el" (car path)))))
+      (setq path (cdr path)))
+    (or (and path
+	     (file-exists-p (expand-file-name "README" (car path))))
+	(error "Can't locate Calc sources"))
+    (calc-quit)
+    (switch-to-buffer "*Help*")
+    (erase-buffer)
+    (insert-file-contents (expand-file-name "README" (car path)))
+    (search-forward "Summary of changes")
+    (forward-line -1)
+    (delete-region (point-min) (point))
+    (goto-char (point-min)))
+)
+
+
+
+(defun calc-full-help ()
+  (interactive)
+  (with-output-to-temp-buffer "*Help*"
+    (princ (format "GNU Emacs Calculator version %s of %s.\n"
+		   calc-version calc-version-date))
+    (princ "  By Dave Gillespie, daveg@synaptics.com.\n")
+    (princ (format "  Installed %s.\n" calc-installed-date))
+    (princ "  Copyright (C) 1990, 1993 Free Software Foundation, Inc.\n\n")
+    (princ "Type `h s' for a more detailed summary.\n")
+    (princ "Or type `h i' to read the full Calc manual on-line.\n\n")
+    (princ "Basic keys:\n")
+    (let* ((calc-full-help-flag t))
+      (mapcar (function (lambda (x) (princ (format "  %s\n" x))))
+	      (nreverse (cdr (reverse (cdr (calc-help))))))
+      (mapcar (function (lambda (prefix)
+			  (let ((msgs (condition-case err
+					  (funcall prefix)
+					(error nil))))
+			    (if (car msgs)
+				(princ
+				 (if (eq (nth 2 msgs) ?v)
+				     "\n`v' or `V' prefix (vector/matrix) keys: \n"
+				   (if (nth 2 msgs)
+				       (format
+					"\n`%c' prefix (%s) keys:\n"
+					(nth 2 msgs)
+					(or (cdr (assq (nth 2 msgs)
+						       calc-help-long-names))
+					    (nth 1 msgs)))
+				     (format "\n%s-modified keys:\n"
+					     (capitalize (nth 1 msgs)))))))
+			    (mapcar (function (lambda (x)
+						(princ (format "  %s\n" x))))
+				    (car msgs)))))
+	      '(calc-inverse-prefix-help
+		calc-hyperbolic-prefix-help
+		calc-inv-hyp-prefix-help
+		calc-a-prefix-help
+		calc-b-prefix-help
+		calc-c-prefix-help
+		calc-d-prefix-help
+		calc-f-prefix-help
+		calc-g-prefix-help
+		calc-h-prefix-help
+		calc-j-prefix-help
+		calc-k-prefix-help
+		calc-m-prefix-help
+		calc-r-prefix-help
+		calc-s-prefix-help
+		calc-t-prefix-help
+		calc-u-prefix-help
+		calc-v-prefix-help
+		calc-shift-Y-prefix-help
+		calc-shift-Z-prefix-help
+		calc-z-prefix-help)))
+    (print-help-return-message))
+)
+
+(defvar calc-help-long-names '( ( ?b . "binary/business" )
+				( ?g . "graphics" )
+				( ?j . "selection" )
+				( ?k . "combinatorics/statistics" )
+				( ?u . "units/statistics" )
+))
+
+(defun calc-h-prefix-help ()
+  (interactive)
+  (calc-do-prefix-help
+   '("Help; Bindings; Info, Tutorial, Summary; News"
+     "describe: Key, C (briefly), Function, Variable")
+   "help" ?h)
+)
+
+(defun calc-inverse-prefix-help ()
+  (interactive)
+  (calc-do-prefix-help
+   '("I + S (arcsin), C (arccos), T (arctan); Q (square)"
+     "I + E (ln), L (exp), B (alog: B^X); f E (lnp1), f L (expm1)"
+     "I + F (ceiling), R (truncate); a S (invert func)"
+     "I + a m (match-not); c h (from-hms); k n (prev prime)"
+     "I + f G (gamma-Q); f e (erfc); k B (etc., lower-tail dists)"
+     "I + V S (reverse sort); V G (reverse grade)"
+     "I + v s (remove subvec); v h (tail)"
+     "I + t + (alt sum), t M (mean with error)"
+     "I + t S (pop std dev), t C (pop covar)")
+   "inverse" nil)
+)
+
+(defun calc-hyperbolic-prefix-help ()
+  (interactive)
+  (calc-do-prefix-help
+   '("H + S (sinh), C (cosh), T (tanh); E (exp10), L (log10)"
+     "H + F (float floor), R (float round); P (constant \"e\")"
+     "H + a d (total derivative); k c (permutations)"
+     "H + k b (bern-poly), k e (euler-poly); k s (stirling-2)"
+     "H + f G (gamma-g), f B (beta-B); v h (rhead), v k (rcons)"
+     "H + v e (expand w/filler); V H (weighted histogram)"
+     "H + a S (general solve eqn), j I (general isolate)"
+     "H + a R (widen/root), a N (widen/min), a X (widen/max)"
+     "H + t M (median), t S (variance), t C (correlation coef)"
+     "H + c f/F/c (pervasive float/frac/clean)")
+   "hyperbolic" nil)
+)
+
+(defun calc-inv-hyp-prefix-help ()
+  (interactive)
+  (calc-do-prefix-help
+   '("I H + S (arcsinh), C (arccosh), T (arctanh)"
+     "I H + E (log10), L (exp10); f G (gamma-G)"
+     "I H + F (float ceiling), R (float truncate)"
+     "I H + t S (pop variance)"
+     "I H + a S (general invert func); v h (rtail)")
+   "inverse-hyperbolic" nil)
+)
+
+
+(defun calc-f-prefix-help ()
+  (interactive)
+  (calc-do-prefix-help
+   '("miN, maX; Hypot; Im, Re; Sign; [, ] (incr/decr)"
+     "Gamma, Beta, Erf, besselJ, besselY"
+     "SHIFT + int-sQrt; Int-log, Exp(x)-1, Ln(x+1); arcTan2"
+     "SHIFT + Abssqr; Mantissa, eXponent, Scale"
+     "SHIFT + incomplete: Gamma-P, Beta-I")
+   "functions" ?f)
+)
+
+
+(defun calc-s-prefix-help ()
+  (interactive)
+  (calc-do-prefix-help
+   '("Store, inTo, Xchg, Unstore; Recall, 0-9; : (:=); = (=>)"
+     "Let; Copy; Declare; Insert, Perm; Edit"
+     "Negate, +, -, *, /, ^, &, |, [, ]; Map"
+     "SHIFT + Decls, GenCount, TimeZone, Holidays; IntegLimit"
+     "SHIFT + LineStyles, PointStyles, plotRejects; Units"
+     "SHIFT + Eval-, AlgSimp-, ExtSimp-, FitRules")
+   "store" ?s)
+)
+
+(defun calc-r-prefix-help ()
+  (interactive)
+  (calc-do-prefix-help
+   '("digits 0-9: recall, same as `s r 0-9'")
+   "recall" ?r)
+)
+
+
+(defun calc-j-prefix-help ()
+  (interactive)
+  (calc-do-prefix-help
+   '("Select, Additional, Once; eVal, Formula; Rewrite"
+     "More, Less, 1-9, Next, Previous"
+     "Unselect, Clear; Display; Enable; Breakable"
+     "' (replace), ` (edit), +, -, *, /, RET (grab), DEL"
+     "SHIFT + swap: Left, Right; maybe: Select, Once"
+     "SHIFT + Commute, Merge, Distrib, jump-Eqn, Isolate"
+     "SHIFT + Negate, & (invert); Unpack")
+   "select" ?j)
+)
+
+
+(defun calc-a-prefix-help ()
+  (interactive)
+  (calc-do-prefix-help
+   '("Simplify, Extended-simplify, eVal; \" (exp-formula)"
+     "eXpand, Collect, Factor, Apart, Norm-rat"
+     "GCD, /, \\, % (polys); Polint"
+     "Derivative, Integral, Taylor; _ (subscr)"
+     "suBstitute; Rewrite, Match"
+     "SHIFT + Solve; Root, miN, maX; Poly-roots; Fit"
+     "SHIFT + Map; Tabulate, + (sum), * (prod); num-Integ"
+     "relations: =, # (not =), <, >, [ (< or =), ] (> or =)"
+     "logical: & (and), | (or), ! (not); : (if)"
+     "misc: { (in-set); . (rmeq)")
+   "algebra" ?a)
+)
+
+
+(defun calc-b-prefix-help ()
+  (interactive)
+  (calc-do-prefix-help
+   '("And, Or, Xor, Diff, Not; Wordsize, Clip"
+     "Lshift, Rshift, roTate; SHIFT + signed Lshift, Rshift"
+     "SHIFT + business: Pv, Npv, Fv, pMt, #pmts, raTe, Irr"
+     "SHIFT + business: Sln, sYd, Ddb; %ch")
+   "binary/bus" ?b)
+)
+
+
+(defun calc-c-prefix-help ()
+  (interactive)
+  (calc-do-prefix-help
+   '("Deg, Rad, HMS; Float; Polar/rect; Clean, 0-9; %"
+     "SHIFT + Fraction")
+   "convert" ?c)
+)
+
+
+(defun calc-d-prefix-help ()
+  (interactive)
+  (calc-do-prefix-help
+   '("Group, \",\"; Normal, Fix, Sci, Eng, \".\"; Over"
+     "Radix, Zeros, 2, 8, 0, 6; Hms; Date; Complex, I, J"
+     "Why; Line-nums, line-Breaks; <, =, > (justify); Plain"
+     "\" (strings); Truncate, [, ]; SPC (refresh), RET"
+     "SHIFT + language: Normal, One-line, Big, Unformatted"
+     "SHIFT + language: C, Pascal, Fortran; TeX, Eqn"
+     "SHIFT + language: Mathematica, W=Maple")
+   "display" ?d)
+)
+
+
+(defun calc-g-prefix-help ()
+  (interactive)
+  (calc-do-prefix-help
+   '("Fast; Add, Delete, Juggle; Plot, Clear; Quit"
+     "Header, Name, Grid, Border, Key; View-commands, X-display"
+     "x-axis: Range, Title, Log, Zero; lineStyle"
+     "SHIFT + y-axis: Range, Title, Log, Zero; pointStyle"
+     "SHIFT + Print; Device, Output-file; X-geometry"
+     "SHIFT + Num-pts; Command, Kill, View-trail"
+     "SHIFT + 3d: Fast, Add; CTRL + z-axis: Range, Title, Log")
+   "graph" ?g)
+)
+
+
+(defun calc-k-prefix-help ()
+  (interactive)
+  (calc-do-prefix-help
+   '("GCD, LCM; Choose (binomial), Double-factorial"
+     "Random, random-Again, sHuffle"
+     "Factors, Prime-test, Next-prime, Totient, Moebius"
+     "Bernoulli, Euler, Stirling"
+     "SHIFT + Extended-gcd"
+     "SHIFT + dists: Binomial, Chi-square, F, Normal"
+     "SHIFT + dists: Poisson, student's-T")
+   "combinatorics" ?k)
+)
+
+
+(defun calc-m-prefix-help ()
+  (interactive)
+  (calc-do-prefix-help
+   '("Deg, Rad, HMS; Frac; Polar; Inf; Alg, Total; Symb; Vec/mat"
+     "Working; Xtensions; Mode-save"
+     "SHIFT + Shifted-prefixes, mode-Filename; Record; reCompute"
+     "SHIFT + simplify: Off, Num, Default, Bin, Alg, Ext, Units")
+   "mode" ?m)
+)
+
+
+(defun calc-t-prefix-help ()
+  (interactive)
+  (calc-do-prefix-help
+   '("Display; Fwd, Back; Next, Prev, Here, [, ]; Yank"
+     "Search, Rev; In, Out; <, >; Kill; Marker; . (abbrev)"
+     "SHIFT + time: Now; Part; Date, Julian, Unix, Czone"
+     "SHIFT + time: newWeek, newMonth, newYear; Incmonth"
+     "SHIFT + time: +, - (business days)"
+     "digits 0-9: store-to, same as `s t 0-9'")
+   "trail/time" ?t)
+)
+
+
+(defun calc-u-prefix-help ()
+  (interactive)
+  (calc-do-prefix-help
+   '("Simplify, Convert, Temperature-convert, Base-units"
+     "Autorange; Remove, eXtract; Explain; View-table; 0-9"
+     "Define, Undefine, Get-defn, Permanent"
+     "SHIFT + View-table-other-window"
+     "SHIFT + stat: Mean, G-mean, Std-dev, Covar, maX, miN"
+     "SHIFT + stat: + (sum), - (asum), * (prod), # (count)")
+   "units/stat" ?u)
+)
+
+
+(defun calc-v-prefix-help ()
+  (interactive)
+  (calc-do-prefix-help
+   '("Pack, Unpack, Identity, Diagonal, indeX, Build"
+     "Row, Column, Subvector; Length; Find; Mask, Expand"
+     "Tranpose, Arrange, reVerse; Head, Kons; rNorm"
+     "SHIFT + Det, & (inverse), LUD, Trace, conJtrn, Cross"
+     "SHIFT + Sort, Grade, Histogram; cNorm"
+     "SHIFT + Apply, Map, Reduce, accUm, Inner-, Outer-prod"
+     "SHIFT + sets: V (union), ^ (intersection), - (diff)"
+     "SHIFT + sets: Xor, ~ (complement), Floor, Enum"
+     "SHIFT + sets: : (span), # (card), + (rdup)"
+     "<, =, > (justification); , (commas); [, {, ( (brackets)"
+     "} (matrix brackets); . (abbreviate); / (multi-lines)")
+   "vec/mat" ?v)
+)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/calc-incom.el	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,234 @@
+;; Calculator for GNU Emacs, part II [calc-incom.el]
+;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+;; Written by Dave Gillespie, daveg@synaptics.com.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY.  No author or distributor
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing.  Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License.   A copy of this license is
+;; supposed to have been given to you along with GNU Emacs so you
+;; can know your rights and responsibilities.  It should be in a
+;; file named COPYING.  Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+
+
+
+;; This file is autoloaded from calc-ext.el.
+(require 'calc-ext)
+
+(require 'calc-macs)
+
+(defun calc-Need-calc-incom () nil)
+
+
+;;; Incomplete forms.
+
+(defun calc-begin-complex ()
+  (interactive)
+  (calc-wrapper
+   (if (or calc-algebraic-mode calc-incomplete-algebraic-mode)
+       (calc-alg-entry "(")
+     (calc-push (list 'incomplete calc-complex-mode))))
+)
+
+(defun calc-end-complex ()
+  (interactive)
+  (calc-comma t)
+  (calc-wrapper
+   (let ((top (calc-top 1)))
+     (if (and (eq (car-safe top) 'incomplete)
+	      (eq (nth 1 top) 'intv))
+	 (progn
+	   (if (< (length top) 4)
+	       (setq top (append top '((neg (var inf var-inf))))))
+	   (if (< (length top) 5)
+	       (setq top (append top '((var inf var-inf)))))
+	   (calc-enter-result 1 "..)" (cdr top)))
+       (if (not (and (eq (car-safe top) 'incomplete)
+		     (memq (nth 1 top) '(cplx polar))))
+	   (error "Not entering a complex number"))
+       (while (< (length top) 4)
+	 (setq top (append top '(0))))
+       (if (not (and (math-realp (nth 2 top))
+		     (math-anglep (nth 3 top))))
+	   (error "Components must be real"))
+       (calc-enter-result 1 "()" (cdr top)))))
+)
+
+(defun calc-begin-vector ()
+  (interactive)
+  (calc-wrapper
+   (if (or calc-algebraic-mode calc-incomplete-algebraic-mode)
+       (calc-alg-entry "[")
+     (calc-push '(incomplete vec))))
+)
+
+(defun calc-end-vector ()
+  (interactive)
+  (calc-comma t)
+  (calc-wrapper
+   (let ((top (calc-top 1)))
+     (if (and (eq (car-safe top) 'incomplete)
+	      (eq (nth 1 top) 'intv))
+	 (progn
+	   (if (< (length top) 4)
+	       (setq top (append top '((neg (var inf var-inf))))))
+	   (if (< (length top) 5)
+	       (setq top (append top '((var inf var-inf)))))
+	   (setcar (cdr (cdr top)) (1+ (nth 2 top)))
+	   (calc-enter-result 1 "..]" (cdr top)))
+       (if (not (and (eq (car-safe top) 'incomplete)
+		     (eq (nth 1 top) 'vec)))
+	   (error "Not entering a vector"))
+       (calc-pop-push-record 1 "[]" (cdr top)))))
+)
+
+(defun calc-comma (&optional allow-polar)
+  (interactive)
+  (calc-wrapper
+   (let ((num (calc-find-first-incomplete
+	       (nthcdr calc-stack-top calc-stack) 1)))
+     (if (= num 0)
+	 (error "Not entering a vector or complex number"))
+     (let* ((inc (calc-top num))
+	    (stuff (calc-top-list (1- num)))
+	    (new (append inc stuff)))
+       (if (and (null stuff)
+		(not allow-polar)
+		(or (eq (nth 1 inc) 'vec)
+		    (< (length new) 4)))
+	   (setq new (append new
+			     (if (= (length new) 2)
+				 '(0)
+			       (nthcdr (1- (length new)) new)))))
+       (or allow-polar
+	   (if (eq (nth 1 new) 'polar)
+	       (setq new (append '(incomplete cplx) (cdr (cdr new))))
+	     (if (eq (nth 1 new) 'intv)
+		 (setq new (append '(incomplete cplx)
+				   (cdr (cdr (cdr new))))))))
+       (if (and (memq (nth 1 new) '(cplx polar))
+		(> (length new) 4))
+	   (error "Too many components in complex number"))
+       (if (and (eq (nth 1 new) 'intv)
+		(> (length new) 5))
+	   (error "Too many components in interval form"))
+       (calc-pop-push num new))))
+)
+
+(defun calc-semi ()
+  (interactive)
+  (calc-wrapper
+   (let ((num (calc-find-first-incomplete
+	       (nthcdr calc-stack-top calc-stack) 1)))
+     (if (= num 0)
+	 (error "Not entering a vector or complex number"))
+     (let ((inc (calc-top num))
+	   (stuff (calc-top-list (1- num))))
+       (if (eq (nth 1 inc) 'cplx)
+	   (setq inc (append '(incomplete polar) (cdr (cdr inc))))
+	 (if (eq (nth 1 inc) 'intv)
+	     (setq inc (append '(incomplete polar) (cdr (cdr (cdr inc)))))))
+       (cond ((eq (nth 1 inc) 'polar)
+	      (let ((new (append inc stuff)))
+		(if (> (length new) 4)
+		    (error "Too many components in complex number")
+		  (if (= (length new) 2)
+		      (setq new (append new '(1)))))
+		(calc-pop-push num new)))
+	     ((null stuff)
+	      (if (> (length inc) 2)
+		  (if (math-vectorp (nth 2 inc))
+		      (calc-comma)
+		    (calc-pop-push 1
+				   (list 'incomplete 'vec (cdr (cdr inc)))
+				   (list 'incomplete 'vec)))))
+	     ((math-vectorp (car stuff))
+	      (calc-comma))
+	     ((eq (car-safe (car-safe (nth (+ num calc-stack-top)
+					   calc-stack))) 'incomplete)
+	      (calc-end-vector)
+	      (calc-comma)
+	      (let ((calc-algebraic-mode nil)
+		    (calc-incomplete-algebraic-mode nil))
+		(calc-begin-vector)))
+	     ((or (= (length inc) 2)
+		  (math-vectorp (nth 2 inc)))
+	      (calc-pop-push num
+			     (append inc (list (cons 'vec stuff)))
+			     (list 'incomplete 'vec)))
+	     (t
+	      (calc-pop-push num
+			     (list 'incomplete 'vec
+				   (cons 'vec (append (cdr (cdr inc)) stuff)))
+			     (list 'incomplete 'vec)))))))
+)
+
+(defun calc-digit-dots ()
+  (if (eq calc-prev-char ?.)
+      (progn
+	(delete-backward-char 1)
+	(if (calc-minibuffer-contains ".*\\.\\'")
+	    (delete-backward-char 1))
+	(setq calc-prev-char 'dots
+	      last-command-char 32)
+	(if calc-prev-prev-char
+	    (calcDigit-nondigit)
+	  (setq calc-digit-value nil)
+	  (erase-buffer)
+	  (exit-minibuffer)))
+    ;; just ignore extra decimal point, anticipating ".."
+    (delete-backward-char 1))
+)
+
+(defun calc-dots ()
+  (interactive)
+  (calc-wrapper
+   (let ((num (calc-find-first-incomplete
+	       (nthcdr calc-stack-top calc-stack) 1)))
+     (if (= num 0)
+	 (error "Not entering an interval form"))
+     (let* ((inc (calc-top num))
+	    (stuff (calc-top-list (1- num)))
+	    (new (append inc stuff)))
+       (if (not (eq (nth 1 new) 'intv))
+	   (setq new (append '(incomplete intv)
+			     (if (eq (nth 1 new) 'vec) '(2) '(0))
+			     (cdr (cdr new)))))
+       (if (and (null stuff)
+		(= (length new) 3))
+	   (setq new (append new '((neg (var inf var-inf))))))
+       (if (> (length new) 5)
+	   (error "Too many components in interval form"))
+       (calc-pop-push num new))))
+)
+
+(defun calc-find-first-incomplete (stack n)
+  (cond ((null stack)
+	 0)
+	((eq (car-safe (car-safe (car stack))) 'incomplete)
+	 n)
+	(t
+	 (calc-find-first-incomplete (cdr stack) (1+ n))))
+)
+
+(defun calc-incomplete-error (a)
+  (cond ((memq (nth 1 a) '(cplx polar))
+	 (error "Complex number is incomplete"))
+	((eq (nth 1 a) 'vec)
+	 (error "Vector is incomplete"))
+	((eq (nth 1 a) 'intv)
+	 (error "Interval form is incomplete"))
+	(t (error "Object is incomplete")))
+)
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/calc-keypd.el	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,682 @@
+;; Calculator for GNU Emacs, part II [calc-keypd.el]
+;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+;; Written by Dave Gillespie, daveg@synaptics.com.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY.  No author or distributor
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing.  Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License.   A copy of this license is
+;; supposed to have been given to you along with GNU Emacs so you
+;; can know your rights and responsibilities.  It should be in a
+;; file named COPYING.  Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+
+
+
+;; This file is autoloaded from calc-ext.el.
+(require 'calc-ext)
+
+(require 'calc-macs)
+
+(defun calc-Need-calc-keypd () nil)
+
+
+
+;;; Pictorial interface to Calc using the X window system mouse.
+
+(defvar calc-keypad-buffer nil)
+(defvar calc-keypad-menu 0)
+(defvar calc-keypad-full-layout nil)
+(defvar calc-keypad-input nil)
+(defvar calc-keypad-prev-input nil)
+(defvar calc-keypad-prev-x-left-click nil)
+(defvar calc-keypad-prev-x-middle-click nil)
+(defvar calc-keypad-prev-x-right-click nil)
+(defvar calc-keypad-said-hello nil)
+
+(defvar calc-keypad-map nil)
+(if calc-keypad-map
+    ()
+  (setq calc-keypad-map (make-sparse-keymap))
+  (define-key calc-keypad-map " " 'calc-keypad-press)
+  (define-key calc-keypad-map "\r" 'calc-keypad-press)
+  (define-key calc-keypad-map "\t" 'calc-keypad-menu)
+  (define-key calc-keypad-map "q" 'calc-keypad-off))
+
+(defun calc-do-keypad (&optional full-display interactive)
+  (if (string-match "^19" emacs-version)
+      (error "Sorry, calc-keypad not yet implemented for Emacs 19"))
+  (calc-create-buffer)
+  (let ((calcbuf (current-buffer)))
+    (or (and calc-keypad-buffer
+	     (buffer-name calc-keypad-buffer))
+	(progn
+	  (setq calc-keypad-buffer (get-buffer-create "*Calc Keypad*"))
+	  (set-buffer calc-keypad-buffer)
+	  (use-local-map calc-keypad-map)
+	  (setq major-mode 'calc-keypad)
+	  (setq mode-name "Calculator")
+	  (put 'calc-keypad 'mode-class 'special)
+	  (make-local-variable 'calc-main-buffer)
+	  (setq calc-main-buffer calcbuf)
+	  (calc-keypad-redraw)
+	  (calc-trail-buffer)))
+    (let ((width 29)
+	  (height 17)
+	  win old-win)
+      (if (setq win (get-buffer-window "*Calculator*"))
+	  (delete-window win))
+      (if (setq win (get-buffer-window "*Calc Trail*"))
+	  (if (one-window-p)
+	      (switch-to-buffer (other-buffer))
+	    (delete-window win)))
+      (if (setq win (get-buffer-window calc-keypad-buffer))
+	  (progn
+	    (bury-buffer "*Calculator*")
+	    (bury-buffer "*Calc Trail*")
+	    (bury-buffer calc-keypad-buffer)
+	    (if (one-window-p)
+		(switch-to-buffer (other-buffer))
+	      (delete-window win))
+	    (if (and calc-keypad-prev-x-left-click
+		     (eq (aref mouse-map 0) 'calc-keypad-x-right-click)
+		     (eq (aref mouse-map 1) 'calc-keypad-x-middle-click)
+		     (eq (aref mouse-map 2) 'calc-keypad-x-left-click))
+		(progn
+		  (aset mouse-map 0 calc-keypad-prev-x-right-click)
+		  (aset mouse-map 1 calc-keypad-prev-x-middle-click)
+		  (aset mouse-map 2 calc-keypad-prev-x-left-click)
+		  (setq calc-keypad-prev-x-left-click nil))))
+	(setq calc-was-keypad-mode t
+	      old-win (get-largest-window))
+	(if (or (< (window-height old-win) (+ height 6))
+		(< (window-width old-win) (+ width 15))
+		full-display)
+	    (delete-other-windows old-win))
+	(if (< (window-height old-win) (+ height 4))
+	    (error "Screen is not tall enough for this mode"))
+	(if full-display
+	    (progn
+	      (setq win (split-window old-win (- (window-height old-win)
+						 height 1)))
+	      (set-window-buffer old-win (calc-trail-buffer))
+	      (set-window-buffer win calc-keypad-buffer)
+	      (set-window-start win 1)
+	      (setq win (split-window win (+ width 3) t))
+	      (set-window-buffer win calcbuf))
+	  (if (or t  ; left-side keypad not yet fully implemented
+		  (< (save-excursion
+		       (set-buffer (window-buffer old-win))
+		       (current-column))
+		     (/ (window-width) 2)))
+	      (setq win (split-window old-win (- (window-width old-win)
+						 width 2)
+				      t))
+	    (setq old-win (split-window old-win (+ width 2) t)))
+	  (set-window-buffer win calc-keypad-buffer)
+	  (set-window-start win 1)
+	  (split-window win (- (window-height win) height 1))
+	  (set-window-buffer win calcbuf))
+	(select-window old-win)
+	(if (and (eq window-system 'x)
+		 (not calc-keypad-prev-x-left-click))
+	    (progn
+	      (setq calc-keypad-prev-x-right-click (aref mouse-map 0)
+		    calc-keypad-prev-x-middle-click (aref mouse-map 1)
+		    calc-keypad-prev-x-left-click (aref mouse-map 2))
+	      (aset mouse-map 0 'calc-keypad-x-right-click)
+	      (aset mouse-map 1 'calc-keypad-x-middle-click)
+	      (aset mouse-map 2 'calc-keypad-x-left-click)))
+	(message "Welcome to GNU Emacs Calc!  Use the left and right mouse buttons.")
+	(run-hooks 'calc-keypad-start-hook)
+	(and calc-keypad-said-hello interactive
+	     (progn
+	       (sit-for 2)
+	       (message "")))
+	(setq calc-keypad-said-hello t))))
+  (setq calc-keypad-input nil)
+)
+
+(defun calc-keypad-off ()
+  (interactive)
+  (if calc-standalone-flag
+      (save-buffers-kill-emacs nil)
+    (calc-keypad))
+)
+
+(defun calc-keypad-redraw ()
+  (set-buffer calc-keypad-buffer)
+  (setq buffer-read-only t)
+  (setq calc-keypad-full-layout (append (symbol-value (nth calc-keypad-menu
+							   calc-keypad-menus))
+					calc-keypad-layout))
+  (let ((buffer-read-only nil)
+	(row calc-keypad-full-layout)
+	(y 0))
+    (erase-buffer)
+    (insert "\n")
+    (while row
+      (let ((col (car row)))
+	(while col
+	  (let* ((key (car col))
+		 (cwid (if (>= y 4)
+			   5
+			 (if (and (= y 3) (eq col (car row)))
+			     (progn (setq col (cdr col)) 9)
+			   4)))
+		 (name (if (and calc-standalone-flag
+				(eq (nth 1 key) 'calc-keypad-off))
+			   "EXIT"
+			 (if (> (length (car key)) cwid)
+			     (substring (car key) 0 cwid)
+			   (car key))))
+		 (wid (length name))
+		 (pad (- cwid (/ wid 2))))
+	    (insert (make-string (/ (- cwid wid) 2) 32)
+		    name
+		    (make-string (/ (- cwid wid -1) 2) 32)
+		    (if (equal name "MENU")
+			(int-to-string (1+ calc-keypad-menu))
+		      "|")))
+	  (or (setq col (cdr col))
+	      (insert "\n")))
+	(insert (if (>= y 4)
+		    "-----+-----+-----+-----+-----"
+		  (if (= y 3)
+		      "-----+---+-+--+--+-+---++----"
+		    "----+----+----+----+----+----"))
+		(if (= y 7) "+\n" "|\n"))
+	(setq y (1+ y)
+	      row (cdr row)))))
+  (setq calc-keypad-prev-input t)
+  (calc-keypad-show-input)
+  (goto-char (point-min))
+)
+
+(defun calc-keypad-show-input ()
+  (or (equal calc-keypad-input calc-keypad-prev-input)
+      (let ((buffer-read-only nil))
+	(save-excursion
+	  (goto-char (point-min))
+	  (forward-line 1)
+	  (delete-region (point-min) (point))
+	  (if calc-keypad-input
+	      (insert "Calc: " calc-keypad-input "\n")
+	    (insert "----+-----Calc " calc-version "-----+----"
+		    (int-to-string (1+ calc-keypad-menu))
+		    "\n")))))
+  (setq calc-keypad-prev-input calc-keypad-input)
+)
+
+(defun calc-keypad-press ()
+  (interactive)
+  (or (eq major-mode 'calc-keypad)
+      (error "Must be in *Calc Keypad* buffer for this command"))
+  (let* ((row (save-excursion
+		(beginning-of-line)
+		(count-lines (point-min) (point))))
+	 (y (/ row 2))
+	 (x (/ (current-column) (if (>= y 4) 6 5)))
+	 radix frac inv
+	 (hyp (save-excursion
+		(set-buffer calc-main-buffer)
+		(setq radix calc-number-radix
+		      frac calc-prefer-frac
+		      inv calc-inverse-flag)
+		calc-hyperbolic-flag))
+	 (invhyp t)
+	 (menu (symbol-value (nth calc-keypad-menu calc-keypad-menus)))
+	 (input calc-keypad-input)
+	 (iexpon (and input
+		      (or (string-match "\\*[0-9]+\\.\\^" input)
+			  (and (<= radix 14) (string-match "e" input)))
+		      (match-end 0)))
+	 (key (nth x (nth y calc-keypad-full-layout)))
+	 (cmd (or (nth (if inv (if hyp 4 2) (if hyp 3 99)) key)
+		  (setq invhyp nil)
+		  (nth 1 key)))
+	 (isstring (and (consp cmd) (stringp (car cmd))))
+	 (calc-is-keypad-press t))
+    (if invhyp (calc-wrapper))  ; clear Inv and Hyp flags
+    (unwind-protect
+	(cond ((or (null cmd)
+		   (= (% row 2) 0))
+	       (beep))
+	      ((and (> (minibuffer-depth) 0))
+	       (cond (isstring
+		      (setq unread-command-char (aref (car cmd) 0)))
+		     ((eq cmd 'calc-pop)
+		      (setq unread-command-char ?\177))
+		     ((eq cmd 'calc-enter)
+		      (setq unread-command-char 13))
+		     ((eq cmd 'calc-undo)
+		      (setq unread-command-char 7))
+		     (t
+		      (beep))))
+	      ((and input (string-match "STO\\|RCL" input))
+	       (cond ((and isstring (string-match "[0-9]" (car cmd)))
+		      (setq calc-keypad-input nil)
+		      (let ((var (intern (concat "var-q" (car cmd)))))
+			(cond ((equal input "STO+") (calc-store-plus var))
+			      ((equal input "STO-") (calc-store-minus var))
+			      ((equal input "STO*") (calc-store-times var))
+			      ((equal input "STO/") (calc-store-div var))
+			      ((equal input "STO^") (calc-store-power var))
+			      ((equal input "STOn") (calc-store-neg 1 var))
+			      ((equal input "STO&") (calc-store-inv 1 var))
+			      ((equal input "STO") (calc-store-into var))
+			      (t (calc-recall var)))))
+		     ((memq cmd '(calc-pop calc-undo))
+		      (setq calc-keypad-input nil))
+		     ((and (equal input "STO")
+			   (setq frac (assq cmd '( ( calc-plus . "+" )
+						   ( calc-minus . "-" )
+						   ( calc-times . "*" )
+						   ( calc-divide . "/" )
+						   ( calc-power . "^")
+						   ( calc-change-sign . "n")
+						   ( calc-inv . "&") ))))
+		      (setq calc-keypad-input (concat input (cdr frac))))
+		     (t
+		      (beep))))
+	      (isstring
+	       (setq cmd (car cmd))
+	       (if (or (and (equal cmd ".")
+			    input
+			    (string-match "[.:e^]" input))
+		       (and (equal cmd "e")
+			    input
+			    (or (and (<= radix 14) (string-match "e" input))
+				(string-match "\\^\\|[-.:]\\'" input)))
+		       (and (not (equal cmd "."))
+			    (let ((case-fold-search nil))
+			      (string-match cmd "0123456789ABCDEF"
+					    (if (string-match
+						 "[e^]" (or input ""))
+						10 radix)))))
+		   (beep)
+		 (setq calc-keypad-input (concat
+					  (and (/= radix 10)
+					       (or (not input)
+						   (equal input "-"))
+					       (format "%d#" radix))
+					  (and (or (not input)
+						   (equal input "-"))
+					       (or (and (equal cmd "e") "1")
+						   (and (equal cmd ".")
+							(if frac "1" "0"))))
+					  input
+					  (if (and (equal cmd ".") frac)
+					      ":"
+					    (if (and (equal cmd "e")
+						     (or (not input)
+							 (string-match
+							  "#" input))
+						     (> radix 14))
+						(format "*%d.^" radix)
+					      cmd))))))
+	      ((and (eq cmd 'calc-change-sign)
+		    input)
+	       (let* ((epos (or iexpon 0))
+		      (suffix (substring input epos)))
+		 (setq calc-keypad-input (concat
+					  (substring input 0 epos)
+					  (if (string-match "\\`-" suffix)
+					      (substring suffix 1)
+					    (concat "-" suffix))))))
+	      ((and (eq cmd 'calc-pop)
+		    input)
+	       (if (equal input "")
+		   (beep)
+		 (setq calc-keypad-input (substring input 0
+						    (or (string-match
+							 "\\*[0-9]+\\.\\^\\'"
+							 input)
+							-1)))))
+	      ((and (eq cmd 'calc-undo)
+		    input)
+	       (setq calc-keypad-input nil))
+	      (t
+	       (if input
+		   (let ((val (math-read-number input)))
+		     (setq calc-keypad-input nil)
+		     (if val
+			 (calc-wrapper
+			  (calc-push-list (list (calc-record
+						 (calc-normalize val)))))
+		       (or (equal input "")
+			   (beep))
+		       (setq cmd nil))
+		     (if (eq cmd 'calc-enter) (setq cmd nil))))
+	       (setq prefix-arg current-prefix-arg)
+	       (if cmd
+		   (if (and (consp cmd) (eq (car cmd) 'progn))
+		       (while (setq cmd (cdr cmd))
+			 (if (integerp (car cmd))
+			     (setq prefix-arg (car cmd))
+			   (command-execute (car cmd))))
+		     (command-execute cmd)))))
+      (set-buffer calc-keypad-buffer)
+      (calc-keypad-show-input)))
+)
+
+(defun calc-keypad-x-left-click (arg)
+  "Handle a left-button mouse click in Calc Keypad window."
+  (let (coords)
+    (if (and calc-keypad-buffer
+	     (buffer-name calc-keypad-buffer)
+	     (get-buffer-window calc-keypad-buffer)
+	     (setq coords (coordinates-in-window-p
+			   arg (get-buffer-window calc-keypad-buffer))))
+	(let ((win (selected-window)))
+	  (unwind-protect
+	      (progn
+		(x-mouse-set-point arg)
+		(calc-keypad-press))
+	    (and (window-point win)
+		 (select-window win))))
+      (funcall calc-keypad-prev-x-left-click arg)))
+)
+
+(defun calc-keypad-x-right-click (arg)
+  "Handle a right-button mouse click in Calc Keypad window."
+  (if (and calc-keypad-buffer
+	   (buffer-name calc-keypad-buffer)
+	   (get-buffer-window calc-keypad-buffer)
+	   (coordinates-in-window-p
+	    arg (get-buffer-window calc-keypad-buffer)))
+      (save-excursion
+	(set-buffer calc-keypad-buffer)
+	(calc-keypad-menu))
+    (funcall calc-keypad-prev-x-right-click arg))
+)
+
+(defun calc-keypad-x-middle-click (arg)
+  "Handle a middle-button mouse click in Calc Keypad window."
+  (if (and calc-keypad-buffer
+	   (buffer-name calc-keypad-buffer)
+	   (get-buffer-window calc-keypad-buffer)
+	   (coordinates-in-window-p
+	    arg (get-buffer-window calc-keypad-buffer)))
+      (save-excursion
+	(set-buffer calc-keypad-buffer)
+	(calc-keypad-menu-back))
+    (funcall calc-keypad-prev-x-middle-click arg))
+)
+
+(defun calc-keypad-menu ()
+  (interactive)
+  (or (eq major-mode 'calc-keypad)
+      (error "Must be in *Calc Keypad* buffer for this command"))
+  (while (progn (setq calc-keypad-menu (% (1+ calc-keypad-menu)
+					  (length calc-keypad-menus)))
+		(not (symbol-value (nth calc-keypad-menu calc-keypad-menus)))))
+  (calc-keypad-redraw)
+)
+
+(defun calc-keypad-menu-back ()
+  (interactive)
+  (or (eq major-mode 'calc-keypad)
+      (error "Must be in *Calc Keypad* buffer for this command"))
+  (while (progn (setq calc-keypad-menu (% (1- (+ calc-keypad-menu
+						 (length calc-keypad-menus)))
+					  (length calc-keypad-menus)))
+		(not (symbol-value (nth calc-keypad-menu calc-keypad-menus)))))
+  (calc-keypad-redraw)
+)
+
+(defun calc-keypad-store ()
+  (interactive)
+  (setq calc-keypad-input "STO")
+)
+
+(defun calc-keypad-recall ()
+  (interactive)
+  (setq calc-keypad-input "RCL")
+)
+
+(defun calc-pack-interval (mode)
+  (interactive "p")
+  (if (or (< mode 0) (> mode 3))
+      (error "Open/close code should be in the range from 0 to 3."))
+  (calc-pack (- -6 mode))
+)
+
+(defun calc-keypad-execute ()
+  (interactive)
+  (let* ((prompt "Calc keystrokes: ")
+	 (flush 'x-flush-mouse-queue)
+	 (prefix nil)
+	 keys cmd)
+    (save-excursion
+      (calc-select-buffer)
+      (while (progn
+	       (setq keys (read-key-sequence prompt))
+	       (setq cmd (key-binding keys))
+	       (if (or (memq cmd '(calc-inverse
+				   calc-hyperbolic
+				   universal-argument
+				   digit-argument
+				   negative-argument))
+		       (and prefix (string-match "\\`\e?[-0-9]\\'" keys)))
+		   (progn
+		     (setq last-command-char (aref keys (1- (length keys))))
+		     (command-execute cmd)
+		     (setq flush 'not-any-more
+			   prefix t
+			   prompt (concat prompt (key-description keys) " ")))
+		 (eq cmd flush)))))  ; skip mouse-up event
+    (message "")
+    (if (commandp cmd)
+	(command-execute cmd)
+      (error "Not a Calc command: %s" (key-description keys))))
+)
+
+
+;;; |----+----+----+----+----+----|
+;;; |  ENTER  |+/- |EEX |UNDO| <- |
+;;; |-----+---+-+--+--+-+---++----|
+;;; | INV |  7  |  8  |  9  |  /  |
+;;; |-----+-----+-----+-----+-----|
+;;; | HYP |  4  |  5  |  6  |  *  |
+;;; |-----+-----+-----+-----+-----|
+;;; |EXEC |  1  |  2  |  3  |  -  |
+;;; |-----+-----+-----+-----+-----|
+;;; | OFF |  0  |  .  | PI  |  +  |
+;;; |-----+-----+-----+-----+-----|
+
+(defvar calc-keypad-layout
+  '( ( ( "ENTER" calc-enter calc-roll-down calc-roll-up calc-over )
+       ( "ENTER" calc-enter calc-roll-down calc-roll-up calc-over )
+       ( "+/-"	 calc-change-sign calc-inv (progn -4 calc-pack) )
+       ( "EEX"	 ("e") (progn calc-num-prefix calc-pack-interval)
+                 (progn -5 calc-pack)  )
+       ( "UNDO"	 calc-undo calc-redo calc-last-args )
+       ( "<-"	 calc-pop (progn 0 calc-pop)
+	         (progn calc-num-prefix calc-pop) ) )
+     ( ( "INV"   calc-inverse )
+       ( "7"	 ("7") calc-round )
+       ( "8"	 ("8") (progn 2 calc-clean-num) )
+       ( "9"	 ("9") calc-float )
+       ( "/"	 calc-divide (progn calc-inverse calc-power) ) )
+     ( ( "HYP"   calc-hyperbolic )
+       ( "4"	 ("4") calc-ln calc-log10 )
+       ( "5"	 ("5") calc-exp calc-exp10 )
+       ( "6"	 ("6") calc-abs )
+       ( "*"	 calc-times calc-power ) )
+     ( ( "EXEC"	 calc-keypad-execute )
+       ( "1"	 ("1") calc-arcsin calc-sin )
+       ( "2"	 ("2") calc-arccos calc-cos )
+       ( "3"	 ("3") calc-arctan calc-tan )
+       ( "-"	 calc-minus calc-conj ) )
+     ( ( "OFF"   calc-keypad-off )
+       ( "0"	 ("0") calc-imaginary )
+       ( "."	 (".") calc-precision )
+       ( "PI"	 calc-pi )
+       ( "+"	 calc-plus calc-sqrt ) ) )
+)
+
+(defvar calc-keypad-menus '( calc-keypad-math-menu
+			     calc-keypad-funcs-menu
+			     calc-keypad-binary-menu
+			     calc-keypad-vector-menu
+			     calc-keypad-modes-menu
+			     calc-keypad-user-menu ) )
+
+;;; |----+----+----+----+----+----|
+;;; |FLR |CEIL|RND |TRNC|CLN2|FLT |
+;;; |----+----+----+----+----+----|
+;;; | LN |EXP |    |ABS |IDIV|MOD |
+;;; |----+----+----+----+----+----|
+;;; |SIN |COS |TAN |SQRT|y^x |1/x |
+
+(defvar calc-keypad-math-menu
+  '( ( ( "FLR"   calc-floor )
+       ( "CEIL"  calc-ceiling )
+       ( "RND"   calc-round )
+       ( "TRNC"  calc-trunc )
+       ( "CLN2"  (progn 2 calc-clean-num) )
+       ( "FLT"   calc-float ) )
+     ( ( "LN"    calc-ln )
+       ( "EXP"   calc-exp )
+       ( ""	 nil )
+       ( "ABS"   calc-abs )
+       ( "IDIV"  calc-idiv )
+       ( "MOD"   calc-mod ) )
+     ( ( "SIN"   calc-sin )
+       ( "COS"   calc-cos )
+       ( "TAN"   calc-tan )
+       ( "SQRT"  calc-sqrt )
+       ( "y^x"   calc-power )
+       ( "1/x"   calc-inv ) ) )
+)
+
+;;; |----+----+----+----+----+----|
+;;; |IGAM|BETA|IBET|ERF |BESJ|BESY|
+;;; |----+----+----+----+----+----|
+;;; |IMAG|CONJ| RE |ATN2|RAND|RAGN|
+;;; |----+----+----+----+----+----|
+;;; |GCD |FACT|DFCT|BNOM|PERM|NXTP|
+
+(defvar calc-keypad-funcs-menu
+  '( ( ( "IGAM"  calc-inc-gamma )
+       ( "BETA"  calc-beta )
+       ( "IBET"  calc-inc-beta )
+       ( "ERF"   calc-erf )
+       ( "BESJ"  calc-bessel-J )
+       ( "BESY"  calc-bessel-Y ) )
+     ( ( "IMAG"  calc-imaginary )
+       ( "CONJ"  calc-conj )
+       ( "RE"	 calc-re calc-im )
+       ( "ATN2"  calc-arctan2 )
+       ( "RAND"  calc-random )
+       ( "RAGN"  calc-random-again ) )
+     ( ( "GCD"   calc-gcd calc-lcm )
+       ( "FACT"  calc-factorial calc-gamma )
+       ( "DFCT"  calc-double-factorial )
+       ( "BNOM"  calc-choose )
+       ( "PERM"  calc-perm )
+       ( "NXTP"	 calc-next-prime calc-prev-prime ) ) )
+)
+
+;;; |----+----+----+----+----+----|
+;;; |AND | OR |XOR |NOT |LSH |RSH |
+;;; |----+----+----+----+----+----|
+;;; |DEC |HEX |OCT |BIN |WSIZ|ARSH|
+;;; |----+----+----+----+----+----|
+;;; | A  | B  | C  | D  | E  | F  |
+
+(defvar calc-keypad-binary-menu
+  '( ( ( "AND"   calc-and calc-diff )
+       ( "OR"    calc-or )
+       ( "XOR"   calc-xor )
+       ( "NOT"   calc-not calc-clip )
+       ( "LSH"   calc-lshift-binary calc-rotate-binary )
+       ( "RSH"   calc-rshift-binary ) )
+     ( ( "DEC"   calc-decimal-radix )
+       ( "HEX"   calc-hex-radix )
+       ( "OCT"   calc-octal-radix )
+       ( "BIN"   calc-binary-radix )
+       ( "WSIZ"  calc-word-size )
+       ( "ARSH"  calc-rshift-arith ) )
+     ( ( "A"     ("A") )
+       ( "B"     ("B") )
+       ( "C"     ("C") )
+       ( "D"     ("D") )
+       ( "E"     ("E") )
+       ( "F"     ("F") ) ) )
+)
+
+;;; |----+----+----+----+----+----|
+;;; |SUM |PROD|MAX |MAP*|MAP^|MAP$|
+;;; |----+----+----+----+----+----|
+;;; |INV |DET |TRN |IDNT|CRSS|"x" |
+;;; |----+----+----+----+----+----|
+;;; |PACK|UNPK|INDX|BLD |LEN |... |
+
+(defvar calc-keypad-vector-menu
+  '( ( ( "SUM"   calc-vector-sum calc-vector-alt-sum calc-vector-mean )
+       ( "PROD"  calc-vector-product nil calc-vector-sdev )
+       ( "MAX"   calc-vector-max calc-vector-min calc-vector-median )
+       ( "MAP*"  (lambda () (interactive)
+		   (calc-map '(2 calcFunc-mul "*"))) )
+       ( "MAP^"  (lambda () (interactive)
+		   (calc-map '(2 calcFunc-pow "^"))) )
+       ( "MAP$"  calc-map-stack ) )
+     ( ( "MINV"  calc-inv )
+       ( "MDET"  calc-mdet )
+       ( "MTRN"  calc-transpose calc-conj-transpose )
+       ( "IDNT"  (progn calc-num-prefix calc-ident) )
+       ( "CRSS"  calc-cross )
+       ( "\"x\"" "\excalc-algebraic-entry\rx\r"
+	         "\excalc-algebraic-entry\ry\r"
+		 "\excalc-algebraic-entry\rz\r"
+		 "\excalc-algebraic-entry\rt\r") )
+     ( ( "PACK"  calc-pack )
+       ( "UNPK"  calc-unpack )
+       ( "INDX"  (progn calc-num-prefix calc-index) "\C-u\excalc-index\r" )
+       ( "BLD"   (progn calc-num-prefix calc-build-vector) )
+       ( "LEN"   calc-vlength )
+       ( "..."   calc-full-vectors ) ) )
+)
+
+;;; |----+----+----+----+----+----|
+;;; |FLT |FIX |SCI |ENG |GRP |    |
+;;; |----+----+----+----+----+----|
+;;; |RAD |DEG |FRAC|POLR|SYMB|PREC|
+;;; |----+----+----+----+----+----|
+;;; |SWAP|RLL3|RLL4|OVER|STO |RCL |
+
+(defvar calc-keypad-modes-menu
+  '( ( ( "FLT"   calc-normal-notation
+	         (progn calc-num-prefix calc-normal-notation) )
+       ( "FIX"   (progn 2 calc-fix-notation)
+	         (progn calc-num-prefix calc-fix-notation) )
+       ( "SCI"   calc-sci-notation
+	         (progn calc-num-prefix calc-sci-notation) )
+       ( "ENG"   calc-eng-notation
+	         (progn calc-num-prefix calc-eng-notation) )
+       ( "GRP"   calc-group-digits "\C-u-3\excalc-group-digits\r" )
+       ( ""	 nil ) )
+     ( ( "RAD"   calc-radians-mode )
+       ( "DEG"   calc-degrees-mode )
+       ( "FRAC"  calc-frac-mode )
+       ( "POLR"  calc-polar-mode )
+       ( "SYMB"	 calc-symbolic-mode )
+       ( "PREC"  calc-precision ) )
+     ( ( "SWAP"  calc-roll-down )
+       ( "RLL3"  (progn 3 calc-roll-up) (progn 3 calc-roll-down) )
+       ( "RLL4"  (progn 4 calc-roll-up) (progn 4 calc-roll-down) )
+       ( "OVER"  calc-over )
+       ( "STO"   calc-keypad-store )
+       ( "RCL"   calc-keypad-recall ) ) )
+)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/calc-lang.el	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,1151 @@
+;; Calculator for GNU Emacs, part II [calc-lang.el]
+;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+;; Written by Dave Gillespie, daveg@synaptics.com.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY.  No author or distributor
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing.  Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License.   A copy of this license is
+;; supposed to have been given to you along with GNU Emacs so you
+;; can know your rights and responsibilities.  It should be in a
+;; file named COPYING.  Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+
+
+
+;; This file is autoloaded from calc-ext.el.
+(require 'calc-ext)
+
+(require 'calc-macs)
+
+(defun calc-Need-calc-lang () nil)
+
+
+;;; Alternate entry/display languages.
+
+(defun calc-set-language (lang &optional option no-refresh)
+  (setq math-expr-opers (or (get lang 'math-oper-table) math-standard-opers)
+	math-expr-function-mapping (get lang 'math-function-table)
+	math-expr-variable-mapping (get lang 'math-variable-table)
+	calc-language-input-filter (get lang 'math-input-filter)
+	calc-language-output-filter (get lang 'math-output-filter)
+	calc-vector-brackets (or (get lang 'math-vector-brackets) "[]")
+	calc-complex-format (get lang 'math-complex-format)
+	calc-radix-formatter (get lang 'math-radix-formatter)
+	calc-function-open (or (get lang 'math-function-open) "(")
+	calc-function-close (or (get lang 'math-function-close) ")"))
+  (if no-refresh
+      (setq calc-language lang
+	    calc-language-option option)
+    (calc-change-mode '(calc-language calc-language-option)
+		      (list lang option) t))
+)
+
+(defun calc-normal-language ()
+  (interactive)
+  (calc-wrapper
+   (calc-set-language nil)
+   (message "Normal language mode."))
+)
+
+(defun calc-flat-language ()
+  (interactive)
+  (calc-wrapper
+   (calc-set-language 'flat)
+   (message "Flat language mode (all stack entries shown on one line)."))
+)
+
+(defun calc-big-language ()
+  (interactive)
+  (calc-wrapper
+   (calc-set-language 'big)
+   (message "\"Big\" language mode."))
+)
+
+(defun calc-unformatted-language ()
+  (interactive)
+  (calc-wrapper
+   (calc-set-language 'unform)
+   (message "Unformatted language mode."))
+)
+
+
+(defun calc-c-language ()
+  (interactive)
+  (calc-wrapper
+   (calc-set-language 'c)
+   (message "`C' language mode."))
+)
+
+(put 'c 'math-oper-table
+  '( ( "u+"    ident	     -1 1000 )
+     ( "u-"    neg	     -1 1000 )
+     ( "u!"    calcFunc-lnot -1 1000 )
+     ( "~"     calcFunc-not  -1 1000 )
+     ( "*"     *	     190 191 )
+     ( "/"     /	     190 191 )
+     ( "%"     %	     190 191 )
+     ( "+"     +	     180 181 )
+     ( "-"     -	     180 181 )
+     ( "<<"    calcFunc-lsh  170 171 )
+     ( ">>"    calcFunc-rsh  170 171 )
+     ( "<"     calcFunc-lt   160 161 )
+     ( ">"     calcFunc-gt   160 161 )
+     ( "<="    calcFunc-leq  160 161 )
+     ( ">="    calcFunc-geq  160 161 )
+     ( "=="    calcFunc-eq   150 151 )
+     ( "!="    calcFunc-neq  150 151 )
+     ( "&"     calcFunc-and  140 141 )
+     ( "^"     calcFunc-xor  131 130 )
+     ( "|"     calcFunc-or   120 121 )
+     ( "&&"    calcFunc-land 110 111 )
+     ( "||"    calcFunc-lor  100 101 )
+     ( "?"     (math-read-if)  91  90 )
+     ( "!!!"   calcFunc-pnot  -1  88 )
+     ( "&&&"   calcFunc-pand  85  86 )
+     ( "|||"   calcFunc-por   75  76 )
+     ( "="     calcFunc-assign 51 50 )
+     ( ":="    calcFunc-assign 51 50 )
+     ( "::"    calcFunc-condition 45 46 )
+)) ; should support full assignments
+
+(put 'c 'math-function-table
+  '( ( acos	   . calcFunc-arccos )
+     ( acosh	   . calcFunc-arccosh )
+     ( asin	   . calcFunc-arcsin )
+     ( asinh	   . calcFunc-arcsinh )
+     ( atan	   . calcFunc-arctan )
+     ( atan2	   . calcFunc-arctan2 )
+     ( atanh	   . calcFunc-arctanh )
+))
+
+(put 'c 'math-variable-table
+  '( ( M_PI	   . var-pi )
+     ( M_E	   . var-e )
+))
+
+(put 'c 'math-vector-brackets "{}")
+
+(put 'c 'math-radix-formatter
+     (function (lambda (r s)
+		 (if (= r 16) (format "0x%s" s)
+		   (if (= r 8) (format "0%s" s)
+		     (format "%d#%s" r s))))))
+
+
+(defun calc-pascal-language (n)
+  (interactive "P")
+  (calc-wrapper
+   (and n (setq n (prefix-numeric-value n)))
+   (calc-set-language 'pascal n)
+   (message (if (and n (/= n 0))
+		(if (> n 0)
+		    "Pascal language mode (all uppercase)."
+		  "Pascal language mode (all lowercase).")
+	      "Pascal language mode.")))
+)
+
+(put 'pascal 'math-oper-table
+  '( ( "not"   calcFunc-lnot -1 1000 )
+     ( "*"     *	     190 191 )
+     ( "/"     /	     190 191 )
+     ( "and"   calcFunc-and  190 191 )
+     ( "div"   calcFunc-idiv 190 191 )
+     ( "mod"   %	     190 191 )
+     ( "u+"    ident	     -1  185 )
+     ( "u-"    neg	     -1  185 )
+     ( "+"     +	     180 181 )
+     ( "-"     -	     180 181 )
+     ( "or"    calcFunc-or   180 181 )
+     ( "xor"   calcFunc-xor  180 181 )
+     ( "shl"   calcFunc-lsh  180 181 )
+     ( "shr"   calcFunc-rsh  180 181 )
+     ( "in"    calcFunc-in   160 161 )
+     ( "<"     calcFunc-lt   160 161 )
+     ( ">"     calcFunc-gt   160 161 )
+     ( "<="    calcFunc-leq  160 161 )
+     ( ">="    calcFunc-geq  160 161 )
+     ( "="     calcFunc-eq   160 161 )
+     ( "<>"    calcFunc-neq  160 161 )
+     ( "!!!"   calcFunc-pnot  -1  85 )
+     ( "&&&"   calcFunc-pand  80  81 )
+     ( "|||"   calcFunc-por   75  76 )
+     ( ":="    calcFunc-assign 51 50 )
+     ( "::"    calcFunc-condition 45 46 )
+))
+
+(put 'pascal 'math-input-filter 'calc-input-case-filter)
+(put 'pascal 'math-output-filter 'calc-output-case-filter)
+
+(put 'pascal 'math-radix-formatter
+     (function (lambda (r s)
+		 (if (= r 16) (format "$%s" s)
+		   (format "%d#%s" r s)))))
+
+(defun calc-input-case-filter (str)
+  (cond ((or (null calc-language-option) (= calc-language-option 0))
+	 str)
+	(t
+	 (downcase str)))
+)
+
+(defun calc-output-case-filter (str)
+  (cond ((or (null calc-language-option) (= calc-language-option 0))
+	 str)
+	((> calc-language-option 0)
+	 (upcase str))
+	(t
+	 (downcase str)))
+)
+
+
+(defun calc-fortran-language (n)
+  (interactive "P")
+  (calc-wrapper
+   (and n (setq n (prefix-numeric-value n)))
+   (calc-set-language 'fortran n)
+   (message (if (and n (/= n 0))
+		(if (> n 0)
+		    "FORTRAN language mode (all uppercase)."
+		  "FORTRAN language mode (all lowercase).")
+	      "FORTRAN language mode.")))
+)
+
+(put 'fortran 'math-oper-table
+  '( ( "u/"    (math-parse-fortran-vector) -1 1 )
+     ( "/"     (math-parse-fortran-vector-end) 1 -1 )
+     ( "**"    ^             201 200 )
+     ( "u+"    ident	     -1  191 )
+     ( "u-"    neg	     -1  191 )
+     ( "*"     *	     190 191 )
+     ( "/"     /	     190 191 )
+     ( "+"     +	     180 181 )
+     ( "-"     -	     180 181 )
+     ( ".LT."  calcFunc-lt   160 161 )
+     ( ".GT."  calcFunc-gt   160 161 )
+     ( ".LE."  calcFunc-leq  160 161 )
+     ( ".GE."  calcFunc-geq  160 161 )
+     ( ".EQ."  calcFunc-eq   160 161 )
+     ( ".NE."  calcFunc-neq  160 161 )
+     ( ".NOT." calcFunc-lnot -1  121 )
+     ( ".AND." calcFunc-land 110 111 )
+     ( ".OR."  calcFunc-lor  100 101 )
+     ( "!!!"   calcFunc-pnot  -1  85 )
+     ( "&&&"   calcFunc-pand  80  81 )
+     ( "|||"   calcFunc-por   75  76 )
+     ( "="     calcFunc-assign 51 50 )
+     ( ":="    calcFunc-assign 51 50 )
+     ( "::"    calcFunc-condition 45 46 )
+))
+
+(put 'fortran 'math-vector-brackets "//")
+
+(put 'fortran 'math-function-table
+  '( ( acos	   . calcFunc-arccos )
+     ( acosh	   . calcFunc-arccosh )
+     ( aimag	   . calcFunc-im )
+     ( aint	   . calcFunc-ftrunc )
+     ( asin	   . calcFunc-arcsin )
+     ( asinh	   . calcFunc-arcsinh )
+     ( atan	   . calcFunc-arctan )
+     ( atan2	   . calcFunc-arctan2 )
+     ( atanh	   . calcFunc-arctanh )
+     ( conjg	   . calcFunc-conj )
+     ( log	   . calcFunc-ln )
+     ( nint	   . calcFunc-round )
+     ( real	   . calcFunc-re )
+))
+
+(put 'fortran 'math-input-filter 'calc-input-case-filter)
+(put 'fortran 'math-output-filter 'calc-output-case-filter)
+
+(defun math-parse-fortran-vector (op)
+  (let ((math-parsing-fortran-vector '(end . "\000")))
+    (prog1
+	(math-read-brackets t "]")
+      (setq exp-token (car math-parsing-fortran-vector)
+	    exp-data (cdr math-parsing-fortran-vector))))
+)
+
+(defun math-parse-fortran-vector-end (x op)
+  (if math-parsing-fortran-vector
+      (progn
+	(setq math-parsing-fortran-vector (cons exp-token exp-data)
+	      exp-token 'end
+	      exp-data "\000")
+	x)
+    (throw 'syntax "Unmatched closing `/'"))
+)
+(setq math-parsing-fortran-vector nil)
+
+(defun math-parse-fortran-subscr (sym args)
+  (setq sym (math-build-var-name sym))
+  (while args
+    (setq sym (list 'calcFunc-subscr sym (car args))
+	  args (cdr args)))
+  sym
+)
+
+
+(defun calc-tex-language (n)
+  (interactive "P")
+  (calc-wrapper
+   (and n (setq n (prefix-numeric-value n)))
+   (calc-set-language 'tex n)
+   (message (if (and n (/= n 0))
+		(if (> n 0)
+		    "TeX language mode with \\hbox{func}(\\hbox{var})."
+		  "TeX language mode with \\func{\\hbox{var}}.")
+	      "TeX language mode.")))
+)
+
+(put 'tex 'math-oper-table
+  '( ( "u+"       ident		   -1 1000 )
+     ( "u-"       neg		   -1 1000 )
+     ( "\\hat"    calcFunc-hat     -1  950 )
+     ( "\\check"  calcFunc-check   -1  950 )
+     ( "\\tilde"  calcFunc-tilde   -1  950 )
+     ( "\\acute"  calcFunc-acute   -1  950 )
+     ( "\\grave"  calcFunc-grave   -1  950 )
+     ( "\\dot"    calcFunc-dot     -1  950 )
+     ( "\\ddot"   calcFunc-dotdot  -1  950 )
+     ( "\\breve"  calcFunc-breve   -1  950 )
+     ( "\\bar"    calcFunc-bar     -1  950 )
+     ( "\\vec"    calcFunc-Vec     -1  950 )
+     ( "\\underline" calcFunc-under -1  950 )
+     ( "u|"       calcFunc-abs	   -1    0 )
+     ( "|"        closing	    0   -1 )
+     ( "\\lfloor" calcFunc-floor   -1    0 )
+     ( "\\rfloor" closing           0   -1 )
+     ( "\\lceil"  calcFunc-ceil    -1    0 )
+     ( "\\rceil"  closing           0   -1 )
+     ( "\\pm"	  sdev		   300 300 )
+     ( "!"        calcFunc-fact	   210  -1 )
+     ( "^"	  ^		   201 200 )
+     ( "_"	  calcFunc-subscr  201 200 )
+     ( "\\times"  *		   191 190 )
+     ( "*"        *		   191 190 )
+     ( "2x"	  *		   191 190 )
+     ( "+"	  +		   180 181 )
+     ( "-"	  -		   180 181 )
+     ( "\\over"	  /		   170 171 )
+     ( "/"	  /		   170 171 )
+     ( "\\choose" calcFunc-choose  170 171 )
+     ( "\\mod"	  %		   170 171 )
+     ( "<"	  calcFunc-lt	   160 161 )
+     ( ">"	  calcFunc-gt	   160 161 )
+     ( "\\leq"	  calcFunc-leq	   160 161 )
+     ( "\\geq"	  calcFunc-geq	   160 161 )
+     ( "="	  calcFunc-eq	   160 161 )
+     ( "\\neq"	  calcFunc-neq	   160 161 )
+     ( "\\ne"	  calcFunc-neq	   160 161 )
+     ( "\\lnot"   calcFunc-lnot     -1 121 )
+     ( "\\land"	  calcFunc-land    110 111 )
+     ( "\\lor"	  calcFunc-lor     100 101 )
+     ( "?"	  (math-read-if)    91  90 )
+     ( "!!!"	  calcFunc-pnot	    -1  85 )
+     ( "&&&"	  calcFunc-pand	    80  81 )
+     ( "|||"	  calcFunc-por	    75  76 )
+     ( "\\gets"	  calcFunc-assign   51  50 )
+     ( ":="	  calcFunc-assign   51  50 )
+     ( "::"       calcFunc-condition 45 46 )
+     ( "\\to"	  calcFunc-evalto   40  41 )
+     ( "\\to"	  calcFunc-evalto   40  -1 )
+     ( "=>" 	  calcFunc-evalto   40  41 )
+     ( "=>" 	  calcFunc-evalto   40  -1 )
+))
+
+(put 'tex 'math-function-table
+  '( ( \\arccos	   . calcFunc-arccos )
+     ( \\arcsin	   . calcFunc-arcsin )
+     ( \\arctan	   . calcFunc-arctan )
+     ( \\arg	   . calcFunc-arg )
+     ( \\cos	   . calcFunc-cos )
+     ( \\cosh	   . calcFunc-cosh )
+     ( \\det	   . calcFunc-det )
+     ( \\exp	   . calcFunc-exp )
+     ( \\gcd	   . calcFunc-gcd )
+     ( \\ln	   . calcFunc-ln )
+     ( \\log	   . calcFunc-log10 )
+     ( \\max	   . calcFunc-max )
+     ( \\min	   . calcFunc-min )
+     ( \\tan	   . calcFunc-tan )
+     ( \\sin	   . calcFunc-sin )
+     ( \\sinh	   . calcFunc-sinh )
+     ( \\sqrt	   . calcFunc-sqrt )
+     ( \\tanh	   . calcFunc-tanh )
+     ( \\phi	   . calcFunc-totient )
+     ( \\mu	   . calcFunc-moebius )
+))
+
+(put 'tex 'math-variable-table
+  '( ( \\pi	   . var-pi )
+     ( \\infty	   . var-inf )
+     ( \\infty	   . var-uinf )
+     ( \\phi       . var-phi )
+     ( \\gamma     . var-gamma )
+     ( \\sum       . (math-parse-tex-sum calcFunc-sum) )
+     ( \\prod      . (math-parse-tex-sum calcFunc-prod) )
+))
+
+(put 'tex 'math-complex-format 'i)
+
+(defun math-parse-tex-sum (f val)
+  (let (low high save)
+    (or (equal exp-data "_") (throw 'syntax "Expected `_'"))
+    (math-read-token)
+    (setq save exp-old-pos)
+    (setq low (math-read-factor))
+    (or (eq (car-safe low) 'calcFunc-eq)
+	(progn
+	  (setq exp-old-pos (1+ save))
+	  (throw 'syntax "Expected equation")))
+    (or (equal exp-data "^") (throw 'syntax "Expected `^'"))
+    (math-read-token)
+    (setq high (math-read-factor))
+    (list (nth 2 f) (math-read-factor) (nth 1 low) (nth 2 low) high))
+)
+
+(defun math-tex-input-filter (str)   ; allow parsing of 123\,456\,789.
+  (while (string-match "[0-9]\\\\,[0-9]" str)
+    (setq str (concat (substring str 0 (1+ (match-beginning 0)))
+		      (substring str (1- (match-end 0))))))
+  str
+)
+(put 'tex 'math-input-filter 'math-tex-input-filter)
+
+
+(defun calc-eqn-language (n)
+  (interactive "P")
+  (calc-wrapper
+   (calc-set-language 'eqn)
+   (message "Eqn language mode."))
+)
+
+(put 'eqn 'math-oper-table
+  '( ( "u+"       ident		   -1 1000 )
+     ( "u-"       neg		   -1 1000 )
+     ( "prime"    (math-parse-eqn-prime) 950  -1 )
+     ( "prime"    calcFunc-Prime   950  -1 )
+     ( "dot"      calcFunc-dot     950  -1 )
+     ( "dotdot"   calcFunc-dotdot  950  -1 )
+     ( "hat"      calcFunc-hat     950  -1 )
+     ( "tilde"    calcFunc-tilde   950  -1 )
+     ( "vec"      calcFunc-Vec     950  -1 )
+     ( "dyad"     calcFunc-dyad    950  -1 )
+     ( "bar"      calcFunc-bar     950  -1 )
+     ( "under"    calcFunc-under   950  -1 )
+     ( "sub"	  calcFunc-subscr  931 930 )
+     ( "sup"	  ^		   921 920 )
+     ( "sqrt"	  calcFunc-sqrt    -1  910 )
+     ( "over"	  /		   900 901 )
+     ( "u|"       calcFunc-abs	   -1    0 )
+     ( "|"        closing	    0   -1 )
+     ( "left floor"  calcFunc-floor -1   0 )
+     ( "right floor" closing        0   -1 )
+     ( "left ceil"   calcFunc-ceil  -1   0 )
+     ( "right ceil"  closing        0   -1 )
+     ( "+-"	  sdev		   300 300 )
+     ( "!"        calcFunc-fact	   210  -1 )
+     ( "times"    *		   191 190 )
+     ( "*"        *		   191 190 )
+     ( "2x"	  *		   191 190 )
+     ( "/"	  /		   180 181 )
+     ( "%"	  %		   180 181 )
+     ( "+"	  +		   170 171 )
+     ( "-"	  -		   170 171 )
+     ( "<"	  calcFunc-lt	   160 161 )
+     ( ">"	  calcFunc-gt	   160 161 )
+     ( "<="	  calcFunc-leq	   160 161 )
+     ( ">="	  calcFunc-geq	   160 161 )
+     ( "="	  calcFunc-eq	   160 161 )
+     ( "=="	  calcFunc-eq	   160 161 )
+     ( "!="	  calcFunc-neq	   160 161 )
+     ( "u!"       calcFunc-lnot     -1 121 )
+     ( "&&"	  calcFunc-land    110 111 )
+     ( "||"	  calcFunc-lor     100 101 )
+     ( "?"	  (math-read-if)    91  90 )
+     ( "!!!"	  calcFunc-pnot	    -1  85 )
+     ( "&&&"	  calcFunc-pand	    80  81 )
+     ( "|||"	  calcFunc-por	    75  76 )
+     ( "<-"	  calcFunc-assign   51  50 )
+     ( ":="	  calcFunc-assign   51  50 )
+     ( "::"	  calcFunc-condition 45 46 )
+     ( "->"	  calcFunc-evalto   40  41 )
+     ( "->"	  calcFunc-evalto   40  -1 )
+     ( "=>" 	  calcFunc-evalto   40  41 )
+     ( "=>" 	  calcFunc-evalto   40  -1 )
+))
+
+(put 'eqn 'math-function-table
+  '( ( arc\ cos	   . calcFunc-arccos )
+     ( arc\ cosh   . calcFunc-arccosh )
+     ( arc\ sin	   . calcFunc-arcsin )
+     ( arc\ sinh   . calcFunc-arcsinh )
+     ( arc\ tan	   . calcFunc-arctan )
+     ( arc\ tanh   . calcFunc-arctanh )
+     ( GAMMA	   . calcFunc-gamma )
+     ( phi	   . calcFunc-totient )
+     ( mu	   . calcFunc-moebius )
+     ( matrix	   . (math-parse-eqn-matrix) )
+))
+
+(put 'eqn 'math-variable-table
+  '( ( inf	   . var-uinf )
+))
+
+(put 'eqn 'math-complex-format 'i)
+
+(defun math-parse-eqn-matrix (f sym)
+  (let ((vec nil))
+    (while (assoc exp-data '(("ccol") ("lcol") ("rcol")))
+      (math-read-token)
+      (or (equal exp-data calc-function-open)
+	  (throw 'syntax "Expected `{'"))
+      (math-read-token)
+      (setq vec (cons (cons 'vec (math-read-expr-list)) vec))
+      (or (equal exp-data calc-function-close)
+	  (throw 'syntax "Expected `}'"))
+      (math-read-token))
+    (or (equal exp-data calc-function-close)
+	(throw 'syntax "Expected `}'"))
+    (math-read-token)
+    (math-transpose (cons 'vec (nreverse vec))))
+)
+
+(defun math-parse-eqn-prime (x sym)
+  (if (eq (car-safe x) 'var)
+      (if (equal exp-data calc-function-open)
+	  (progn
+	    (math-read-token)
+	    (let ((args (if (or (equal exp-data calc-function-close)
+				(eq exp-token 'end))
+			    nil
+			  (math-read-expr-list))))
+	      (if (not (or (equal exp-data calc-function-close)
+			   (eq exp-token 'end)))
+		  (throw 'syntax "Expected `)'"))
+	      (math-read-token)
+	      (cons (intern (format "calcFunc-%s'" (nth 1 x))) args)))
+	(list 'var
+	      (intern (concat (symbol-name (nth 1 x)) "'"))
+	      (intern (concat (symbol-name (nth 2 x)) "'"))))
+    (list 'calcFunc-Prime x))
+)
+
+
+(defun calc-mathematica-language ()
+  (interactive)
+  (calc-wrapper
+   (calc-set-language 'math)
+   (message "Mathematica language mode."))
+)
+
+(put 'math 'math-oper-table
+  '( ( "[["    (math-read-math-subscr) 250 -1 )
+     ( "!"     calcFunc-fact  210 -1 )
+     ( "!!"    calcFunc-dfact 210 -1 )
+     ( "^"     ^	     201 200 )
+     ( "u+"    ident	     -1  197 )
+     ( "u-"    neg	     -1  197 )
+     ( "/"     /	     195 196 )
+     ( "*"     *	     190 191 )
+     ( "2x"    *	     190 191 )
+     ( "+"     +	     180 181 )
+     ( "-"     -	     180 181 )
+     ( "<"     calcFunc-lt   160 161 )
+     ( ">"     calcFunc-gt   160 161 )
+     ( "<="    calcFunc-leq  160 161 )
+     ( ">="    calcFunc-geq  160 161 )
+     ( "=="    calcFunc-eq   150 151 )
+     ( "!="    calcFunc-neq  150 151 )
+     ( "u!"    calcFunc-lnot -1  121 )
+     ( "&&"    calcFunc-land 110 111 )
+     ( "||"    calcFunc-lor  100 101 )
+     ( "!!!"   calcFunc-pnot  -1  85 )
+     ( "&&&"   calcFunc-pand  80  81 )
+     ( "|||"   calcFunc-por   75  76 )
+     ( ":="    calcFunc-assign 51 50 )
+     ( "="     calcFunc-assign 51 50 )
+     ( "->"    calcFunc-assign 51 50 )
+     ( ":>"    calcFunc-assign 51 50 )
+     ( "::"    calcFunc-condition 45 46 )
+))
+
+(put 'math 'math-function-table
+  '( ( Abs	   . calcFunc-abs )
+     ( ArcCos	   . calcFunc-arccos )
+     ( ArcCosh	   . calcFunc-arccosh )
+     ( ArcSin	   . calcFunc-arcsin )
+     ( ArcSinh	   . calcFunc-arcsinh )
+     ( ArcTan	   . calcFunc-arctan )
+     ( ArcTanh	   . calcFunc-arctanh )
+     ( Arg	   . calcFunc-arg )
+     ( Binomial	   . calcFunc-choose )
+     ( Ceiling	   . calcFunc-ceil )
+     ( Conjugate   . calcFunc-conj )
+     ( Cos	   . calcFunc-cos )
+     ( Cosh	   . calcFunc-cosh )
+     ( D	   . calcFunc-deriv )
+     ( Dt	   . calcFunc-tderiv )
+     ( Det	   . calcFunc-det )
+     ( Exp	   . calcFunc-exp )
+     ( EulerPhi	   . calcFunc-totient )
+     ( Floor	   . calcFunc-floor )
+     ( Gamma	   . calcFunc-gamma )
+     ( GCD	   . calcFunc-gcd )
+     ( If	   . calcFunc-if )
+     ( Im	   . calcFunc-im )
+     ( Inverse	   . calcFunc-inv )
+     ( Integrate   . calcFunc-integ )
+     ( Join	   . calcFunc-vconcat )
+     ( LCM	   . calcFunc-lcm )
+     ( Log	   . calcFunc-ln )
+     ( Max	   . calcFunc-max )
+     ( Min	   . calcFunc-min )
+     ( Mod	   . calcFunc-mod )
+     ( MoebiusMu   . calcFunc-moebius )
+     ( Random	   . calcFunc-random )
+     ( Round	   . calcFunc-round )
+     ( Re	   . calcFunc-re )
+     ( Sign	   . calcFunc-sign )
+     ( Sin	   . calcFunc-sin )
+     ( Sinh	   . calcFunc-sinh )
+     ( Sqrt	   . calcFunc-sqrt )
+     ( Tan	   . calcFunc-tan )
+     ( Tanh	   . calcFunc-tanh )
+     ( Transpose   . calcFunc-trn )
+     ( Length	   . calcFunc-vlen )
+))
+
+(put 'math 'math-variable-table
+  '( ( I	   . var-i )
+     ( Pi	   . var-pi )
+     ( E	   . var-e )
+     ( GoldenRatio . var-phi )
+     ( EulerGamma  . var-gamma )
+     ( Infinity	   . var-inf )
+     ( ComplexInfinity . var-uinf )
+     ( Indeterminate . var-nan )
+))
+
+(put 'math 'math-vector-brackets "{}")
+(put 'math 'math-complex-format 'I)
+(put 'math 'math-function-open "[")
+(put 'math 'math-function-close "]")
+
+(put 'math 'math-radix-formatter
+     (function (lambda (r s) (format "%d^^%s" r s))))
+
+(defun math-read-math-subscr (x op)
+  (let ((idx (math-read-expr-level 0)))
+    (or (and (equal exp-data "]")
+	     (progn
+	       (math-read-token)
+	       (equal exp-data "]")))
+	(throw 'syntax "Expected ']]'"))
+    (math-read-token)
+    (list 'calcFunc-subscr x idx))
+)
+
+
+(defun calc-maple-language ()
+  (interactive)
+  (calc-wrapper
+   (calc-set-language 'maple)
+   (message "Maple language mode."))
+)
+
+(put 'maple 'math-oper-table
+  '( ( "matrix" ident	     -1  300 )
+     ( "MATRIX" ident	     -1  300 )
+     ( "!"     calcFunc-fact  210 -1 )
+     ( "^"     ^	     201 200 )
+     ( "**"    ^	     201 200 )
+     ( "u+"    ident	     -1  197 )
+     ( "u-"    neg	     -1  197 )
+     ( "/"     /	     191 192 )
+     ( "*"     *	     191 192 )
+     ( "intersect" calcFunc-vint 191 192 )
+     ( "+"     +	     180 181 )
+     ( "-"     -	     180 181 )
+     ( "union" calcFunc-vunion 180 181 )
+     ( "minus" calcFunc-vdiff 180 181 )
+     ( "mod"   %	     170 170 )
+     ( ".."    (math-read-maple-dots) 165 165 )
+     ( "\\dots" (math-read-maple-dots) 165 165 )
+     ( "<"     calcFunc-lt   160 160 )
+     ( ">"     calcFunc-gt   160 160 )
+     ( "<="    calcFunc-leq  160 160 )
+     ( ">="    calcFunc-geq  160 160 )
+     ( "="     calcFunc-eq   160 160 )
+     ( "<>"    calcFunc-neq  160 160 )
+     ( "not"   calcFunc-lnot -1  121 )
+     ( "and"   calcFunc-land 110 111 )
+     ( "or"    calcFunc-lor  100 101 )
+     ( "!!!"   calcFunc-pnot  -1  85 )
+     ( "&&&"   calcFunc-pand  80  81 )
+     ( "|||"   calcFunc-por   75  76 )
+     ( ":="    calcFunc-assign 51 50 )
+     ( "::"    calcFunc-condition 45 46 )
+))
+
+(put 'maple 'math-function-table
+  '( ( bernoulli   . calcFunc-bern )
+     ( binomial	   . calcFunc-choose )
+     ( diff	   . calcFunc-deriv )
+     ( GAMMA	   . calcFunc-gamma )
+     ( ifactor	   . calcFunc-prfac )
+     ( igcd 	   . calcFunc-gcd )
+     ( ilcm	   . calcFunc-lcm )
+     ( int  	   . calcFunc-integ )
+     ( modp	   . % )
+     ( irem	   . % )
+     ( iquo	   . calcFunc-idiv )
+     ( isprime	   . calcFunc-prime )
+     ( length	   . calcFunc-vlen )
+     ( member	   . calcFunc-in )
+     ( crossprod   . calcFunc-cross )
+     ( inverse	   . calcFunc-inv )
+     ( trace	   . calcFunc-tr )
+     ( transpose   . calcFunc-trn )
+     ( vectdim	   . calcFunc-vlen )
+))
+
+(put 'maple 'math-variable-table
+  '( ( I	   . var-i )
+     ( Pi	   . var-pi )
+     ( E	   . var-e )
+     ( infinity	   . var-inf )
+     ( infinity    . var-uinf )
+     ( infinity    . var-nan )
+))
+
+(put 'maple 'math-complex-format 'I)
+
+(defun math-read-maple-dots (x op)
+  (list 'intv 3 x (math-read-expr-level (nth 3 op)))
+)
+
+
+
+
+
+(defun math-read-big-rec (h1 v1 h2 v2 &optional baseline prec short)
+  (or prec (setq prec 0))
+
+  ;; Clip whitespace above or below.
+  (while (and (< v1 v2) (math-read-big-emptyp h1 v1 h2 (1+ v1)))
+    (setq v1 (1+ v1)))
+  (while (and (< v1 v2) (math-read-big-emptyp h1 (1- v2) h2 v2))
+    (setq v2 (1- v2)))
+
+  ;; If formula is a single line high, normal parser can handle it.
+  (if (<= v2 (1+ v1))
+      (if (or (<= v2 v1)
+	      (> h1 (length (setq v2 (nth v1 lines)))))
+	  (math-read-big-error h1 v1)
+	(setq the-baseline v1
+	      the-h2 h2
+	      v2 (nth v1 lines)
+	      h2 (math-read-expr (substring v2 h1 (min h2 (length v2)))))
+	(if (eq (car-safe h2) 'error)
+	    (math-read-big-error (+ h1 (nth 1 h2)) v1 (nth 2 h2))
+	  h2))
+
+    ;; Clip whitespace at left or right.
+    (while (and (< h1 h2) (math-read-big-emptyp h1 v1 (1+ h1) v2))
+      (setq h1 (1+ h1)))
+    (while (and (< h1 h2) (math-read-big-emptyp (1- h2) v1 h2 v2))
+      (setq h2 (1- h2)))
+
+    ;; Scan to find widest left-justified "----" in the region.
+    (let* ((widest nil)
+	   (widest-h2 0)
+	   (lines-v1 (nthcdr v1 lines))
+	   (p lines-v1)
+	   (v v1)
+	   (other-v nil)
+	   other-char line len h)
+      (while (< v v2)
+	(setq line (car p)
+	      len (min h2 (length line)))
+	(and (< h1 len)
+	     (/= (aref line h1) ?\ )
+	     (if (and (= (aref line h1) ?\-)
+		      ;; Make sure it's not a minus sign.
+		      (or (and (< (1+ h1) len) (= (aref line (1+ h1)) ?\-))
+			  (/= (math-read-big-char h1 (1- v)) ?\ )
+			  (/= (math-read-big-char h1 (1+ v)) ?\ )))
+		 (progn
+		   (setq h h1)
+		   (while (and (< (setq h (1+ h)) len)
+			       (= (aref line h) ?\-)))
+		   (if (> h widest-h2)
+		       (setq widest v
+			     widest-h2 h)))
+	       (or other-v (setq other-v v other-char (aref line h1)))))
+	(setq v (1+ v)
+	      p (cdr p)))
+
+      (cond ((not (setq v other-v))
+	     (math-read-big-error h1 v1))   ; Should never happen!
+
+	    ;; Quotient.
+	    (widest
+	     (setq h widest-h2
+		   v widest)
+	     (let ((num (math-read-big-rec h1 v1 h v))
+		   (den (math-read-big-rec h1 (1+ v) h v2)))
+	       (setq p (if (and (math-integerp num) (math-integerp den))
+			   (math-make-frac num den)
+			 (list '/ num den)))))
+
+	    ;; Big radical sign.
+	    ((= other-char ?\\)
+	     (or (= (math-read-big-char (1+ h1) v) ?\|)
+		 (math-read-big-error (1+ h1) v "Malformed root sign"))
+	     (math-read-big-emptyp h1 v1 (1+ h1) v nil t)
+	     (while (= (math-read-big-char (1+ h1) (setq v (1- v))) ?\|))
+	     (or (= (math-read-big-char (setq h (+ h1 2)) v) ?\_)
+		 (math-read-big-error h v "Malformed root sign"))
+	     (while (= (math-read-big-char (setq h (1+ h)) v) ?\_))
+	     (math-read-big-emptyp h1 v1 (1+ h1) v nil t)
+	     (math-read-big-emptyp h1 (1+ other-v) h v2 nil t)
+	     (setq p (list 'calcFunc-sqrt (math-read-big-rec
+					   (+ h1 2) (1+ v)
+					   h (1+ other-v) baseline))
+		   v the-baseline))
+
+	    ;; Small radical sign.
+	    ((and (= other-char ?V)
+		  (= (math-read-big-char (1+ h1) (1- v)) ?\_))
+	     (setq h (1+ h1))
+	     (math-read-big-emptyp h1 v1 h (1- v) nil t)
+	     (math-read-big-emptyp h1 (1+ v) h v2 nil t)
+	     (math-read-big-emptyp h1 v1 (1+ h1) v nil t)
+	     (while (= (math-read-big-char (setq h (1+ h)) (1- v)) ?\_))
+	     (setq p (list 'calcFunc-sqrt (math-read-big-rec
+					   (1+ h1) v h (1+ v) t))
+		   v the-baseline))
+
+	    ;; Binomial coefficient.
+	    ((and (= other-char ?\()
+		  (= (math-read-big-char (1+ h1) v) ?\ )
+		  (= (string-match "( *)" (nth v lines) h1) h1))
+	     (setq h (match-end 0))
+	     (math-read-big-emptyp h1 v1 (1+ h1) v nil t)
+	     (math-read-big-emptyp h1 (1+ v) (1+ h1) v2 nil t)
+	     (math-read-big-emptyp (1- h) v1 h v nil t)
+	     (math-read-big-emptyp (1- h) (1+ v) h v2 nil t)
+	     (setq p (list 'calcFunc-choose
+			   (math-read-big-rec (1+ h1) v1 (1- h) v)
+			   (math-read-big-rec (1+ h1) (1+ v)
+					      (1- h) v2))))
+
+	    ;; Minus sign.
+	    ((= other-char ?\-)
+	     (setq p (list 'neg (math-read-big-rec (1+ h1) v1 h2 v2 v 250 t))
+		   v the-baseline
+		   h the-h2))
+
+	    ;; Parentheses.
+	    ((= other-char ?\()
+	     (math-read-big-emptyp h1 v1 (1+ h1) v nil t)
+	     (math-read-big-emptyp h1 (1+ v) (1+ h1) v2 nil t)
+	     (setq h (math-read-big-balance (1+ h1) v "(" t))
+	     (math-read-big-emptyp (1- h) v1 h v nil t)
+	     (math-read-big-emptyp (1- h) (1+ v) h v2 nil t)
+	     (let ((sep (math-read-big-char (1- h) v))
+		   hmid)
+	       (if (= sep ?\.)
+		   (setq h (1+ h)))
+	       (if (= sep ?\])
+		   (math-read-big-error (1- h) v "Expected `)'"))
+	       (if (= sep ?\))
+		   (setq p (math-read-big-rec (1+ h1) v1 (1- h) v2 v))
+		 (setq hmid (math-read-big-balance h v "(")
+		       p (list p (math-read-big-rec h v1 (1- hmid) v2 v))
+		       h hmid)
+		 (cond ((= sep ?\.)
+			(setq p (cons 'intv (cons (if (= (math-read-big-char
+							  (1- h) v)
+							 ?\))
+						      0 1)
+						  p))))
+		       ((= (math-read-big-char (1- h) v) ?\])
+			(math-read-big-error (1- h) v "Expected `)'"))
+		       ((= sep ?\,)
+			(or (and (math-realp (car p)) (math-realp (nth 1 p)))
+			    (math-read-big-error
+			     h1 v "Complex components must be real"))
+			(setq p (cons 'cplx p)))
+		       ((= sep ?\;)
+			(or (and (math-realp (car p)) (math-anglep (nth 1 p)))
+			    (math-read-big-error
+			     h1 v "Complex components must be real"))
+			(setq p (cons 'polar p)))))))
+
+	    ;; Matrix.
+	    ((and (= other-char ?\[)
+		  (or (= (math-read-big-char (setq h h1) (1+ v)) ?\[)
+		      (= (math-read-big-char (setq h (1+ h)) v) ?\[)
+		      (and (= (math-read-big-char h v) ?\ )
+			   (= (math-read-big-char (setq h (1+ h)) v) ?\[)))
+		  (= (math-read-big-char h (1+ v)) ?\[))
+	     (math-read-big-emptyp h1 v1 h v nil t)
+	     (let ((vtop v)
+		   (hleft h)
+		   (hright nil))
+	       (setq p nil)
+	       (while (progn
+			(setq h (math-read-big-balance (1+ hleft) v "["))
+			(if hright
+			    (or (= h hright)
+				(math-read-big-error hright v "Expected `]'"))
+			  (setq hright h))
+			(setq p (cons (math-read-big-rec
+				       hleft v h (1+ v)) p))
+			(and (memq (math-read-big-char h v) '(?\  ?\,))
+			     (= (math-read-big-char hleft (1+ v)) ?\[)))
+		 (setq v (1+ v)))
+	       (or (= hleft h1)
+		   (progn
+		     (if (= (math-read-big-char h v) ?\ )
+			 (setq h (1+ h)))
+		     (and (= (math-read-big-char h v) ?\])
+			  (setq h (1+ h))))
+		   (math-read-big-error (1- h) v "Expected `]'"))
+	       (if (= (math-read-big-char h vtop) ?\,)
+		   (setq h (1+ h)))
+	       (math-read-big-emptyp h1 (1+ v) (1- h) v2 nil t)
+	       (setq v (+ vtop (/ (- v vtop) 2))
+		     p (cons 'vec (nreverse p)))))
+
+	    ;; Square brackets.
+	    ((= other-char ?\[)
+	     (math-read-big-emptyp h1 v1 (1+ h1) v nil t)
+	     (math-read-big-emptyp h1 (1+ v) (1+ h1) v2 nil t)
+	     (setq p nil
+		   h (1+ h1))
+	     (while (progn
+		      (setq widest (math-read-big-balance h v "[" t))
+		      (math-read-big-emptyp (1- h) v1 h v nil t)
+		      (math-read-big-emptyp (1- h) (1+ v) h v2 nil t)
+		      (setq p (cons (math-read-big-rec
+				     h v1 (1- widest) v2 v) p)
+			    h widest)
+		      (= (math-read-big-char (1- h) v) ?\,)))
+	     (setq widest (math-read-big-char (1- h) v))
+	     (if (or (memq widest '(?\; ?\)))
+		     (and (eq widest ?\.) (cdr p)))
+		 (math-read-big-error (1- h) v "Expected `]'"))
+	     (if (= widest ?\.)
+		 (setq h (1+ h)
+		       widest (math-read-big-balance h v "[")
+		       p (nconc p (list (math-read-big-big-rec
+					 h v1 (1- widest) v2 v)))
+		       h widest
+		       p (cons 'intv (cons (if (= (math-read-big-char (1- h) v)
+						  ?\])
+					       3 2)
+					   p)))
+	       (setq p (cons 'vec (nreverse p)))))
+
+	    ;; Date form.
+	    ((= other-char ?\<)
+	     (setq line (nth v lines))
+	     (string-match ">" line h1)
+	     (setq h (match-end 0))
+	     (math-read-big-emptyp h1 v1 h v nil t)
+	     (math-read-big-emptyp h1 (1+ v) h v2 nil t)
+	     (setq p (math-read-big-rec h1 v h (1+ v) v)))
+
+	    ;; Variable name or function call.
+	    ((or (and (>= other-char ?a) (<= other-char ?z))
+		 (and (>= other-char ?A) (<= other-char ?Z)))
+	     (setq line (nth v lines))
+	     (string-match "\\([a-zA-Z'_]+\\) *" line h1)
+	     (setq h (match-end 1)
+		   widest (match-end 0)
+		   p (math-match-substring line 1))
+	     (math-read-big-emptyp h1 v1 h v nil t)
+	     (math-read-big-emptyp h1 (1+ v) h v2 nil t)
+	     (if (= (math-read-big-char widest v) ?\()
+		 (progn
+		   (setq line (if (string-match "-" p)
+				  (intern p)
+				(intern (concat "calcFunc-" p)))
+			 h (1+ widest)
+			 p nil)
+		   (math-read-big-emptyp widest v1 h v nil t)
+		   (math-read-big-emptyp widest (1+ v) h v2 nil t)
+		   (while (progn
+			    (setq widest (math-read-big-balance h v "(" t))
+			    (math-read-big-emptyp (1- h) v1 h v nil t)
+			    (math-read-big-emptyp (1- h) (1+ v) h v2 nil t)
+			    (setq p (cons (math-read-big-rec
+					   h v1 (1- widest) v2 v) p)
+				  h widest)
+			    (= (math-read-big-char (1- h) v) ?\,)))
+		   (or (= (math-read-big-char (1- h) v) ?\))
+		       (math-read-big-error (1- h) v "Expected `)'"))
+		   (setq p (cons line (nreverse p))))
+	       (setq p (list 'var
+			     (intern (math-remove-dashes p))
+			     (if (string-match "-" p)
+				 (intern p)
+			       (intern (concat "var-" p)))))))
+
+	    ;; Number.
+	    (t
+	     (setq line (nth v lines))
+	     (or (= (string-match "_?\\([0-9]+.?0*@ *\\)?\\([0-9]+.?0*' *\\)?\\([0-9]+\\(#\\|\\^\\^\\)[0-9a-zA-Z:]+\\|[0-9]+:[0-9:]+\\|[0-9.]+\\([eE][-+_]?[0-9]+\\)?\"?\\)?" line h1) h1)
+		 (math-read-big-error h v "Expected a number"))
+	     (setq h (match-end 0)
+		   p (math-read-number (math-match-substring line 0)))
+	     (math-read-big-emptyp h1 v1 h v nil t)
+	     (math-read-big-emptyp h1 (1+ v) h v2 nil t)))
+
+      ;; Now left term is bounded by h1, v1, h, v2; baseline = v.
+      (if baseline
+	  (or (= v baseline)
+	      (math-read-big-error h1 v "Inconsistent baseline in formula"))
+	(setq baseline v))
+
+      ;; Look for superscripts or subscripts.
+      (setq line (nth baseline lines)
+	    len (min h2 (length line))
+	    widest h)
+      (while (and (< widest len)
+		  (= (aref line widest) ?\ ))
+	(setq widest (1+ widest)))
+      (and (>= widest len) (setq widest h2))
+      (if (math-read-big-emptyp h v widest v2)
+	  (if (math-read-big-emptyp h v1 widest v)
+	      (setq h widest)
+	    (setq p (list '^ p (math-read-big-rec h v1 widest v))
+		  h widest))
+	  (if (math-read-big-emptyp h v1 widest v)
+	      (setq p (list 'calcFunc-subscr p
+			    (math-read-big-rec h v widest v2))
+		    h widest)))
+
+      ;; Look for an operator name and grab additional terms.
+      (while (and (< h len)
+		  (if (setq widest (and (math-read-big-emptyp
+					 h v1 (1+ h) v)
+					(math-read-big-emptyp
+					 h (1+ v) (1+ h) v2)
+					(string-match "<=\\|>=\\|\\+/-\\|!=\\|&&\\|||\\|:=\\|=>\\|." line h)
+					(assoc (math-match-substring line 0)
+					       math-standard-opers)))
+		      (and (>= (nth 2 widest) prec)
+			   (setq h (match-end 0)))
+		    (and (not (eq (string-match ",\\|;\\|\\.\\.\\|)\\|\\]\\|:" line h)
+				  h))
+			 (setq widest '("2x" * 196 195)))))
+	(cond ((eq (nth 3 widest) -1)
+	       (setq p (list (nth 1 widest) p)))
+	      ((equal (car widest) "?")
+	       (let ((y (math-read-big-rec h v1 h2 v2 baseline nil t)))
+		 (or (= (math-read-big-char the-h2 baseline) ?\:)
+		     (math-read-big-error the-h2 baseline "Expected `:'"))
+		 (setq p (list (nth 1 widest) p y
+			       (math-read-big-rec (1+ the-h2) v1 h2 v2
+						  baseline (nth 3 widest) t))
+		       h the-h2)))
+	      (t
+	       (setq p (list (nth 1 widest) p
+			     (math-read-big-rec h v1 h2 v2
+						baseline (nth 3 widest) t))
+		     h the-h2))))
+
+      ;; Return all relevant information to caller.
+      (setq the-baseline baseline
+	    the-h2 h)
+      (or short (= the-h2 h2)
+	  (math-read-big-error h baseline))
+      p))
+)
+
+(defun math-read-big-char (h v)
+  (or (and (>= h h1)
+	   (< h h2)
+	   (>= v v1)
+	   (< v v2)
+	   (let ((line (nth v lines)))
+	     (and line
+		  (< h (length line))
+		  (aref line h))))
+      ?\ )
+)
+
+(defun math-read-big-emptyp (eh1 ev1 eh2 ev2 &optional what error)
+  (and (< ev1 v1) (setq ev1 v1))
+  (and (< eh1 h1) (setq eh1 h1))
+  (and (> ev2 v2) (setq ev2 v2))
+  (and (> eh2 h2) (setq eh2 h2))
+  (or what (setq what ?\ ))
+  (let ((p (nthcdr ev1 lines))
+	h)
+    (while (and (< ev1 ev2)
+		(progn
+		  (setq h (min eh2 (length (car p))))
+		  (while (and (>= (setq h (1- h)) eh1)
+			      (= (aref (car p) h) what)))
+		  (and error (>= h eh1)
+		       (math-read-big-error h ev1 (if (stringp error)
+						      error
+						    "Whitespace expected")))
+		  (< h eh1)))
+      (setq ev1 (1+ ev1)
+	    p (cdr p)))
+    (>= ev1 ev2))
+)
+
+(defun math-read-big-error (h v &optional msg)
+  (let ((pos 0)
+	(p lines))
+    (while (> v 0)
+      (setq pos (+ pos 1 (length (car p)))
+	    p (cdr p)
+	    v (1- v)))
+    (setq h (+ pos (min h (length (car p))))
+	  err-msg (list 'error h (or msg "Syntax error")))
+    (throw 'syntax nil))
+)
+
+(defun math-read-big-balance (h v what &optional commas)
+  (let* ((line (nth v lines))
+	 (len (min h2 (length line)))
+	 (count 1))
+    (while (> count 0)
+      (if (>= h len)
+	  (if what
+	      (math-read-big-error h1 v (format "Unmatched `%s'" what))
+	    (setq count 0))
+	(if (memq (aref line h) '(?\( ?\[))
+	    (setq count (1+ count))
+	  (if (if (and commas (= count 1))
+		  (or (memq (aref line h) '(?\) ?\] ?\, ?\;))
+		      (and (eq (aref line h) ?\.)
+			   (< (1+ h) len)
+			   (eq (aref line (1+ h)) ?\.)))
+		(memq (aref line h) '(?\) ?\])))
+	      (setq count (1- count))))
+	(setq h (1+ h))))
+    h)
+)
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/calc-macs.el	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,262 @@
+;; Calculator for GNU Emacs, part I [calc-macs.el]
+;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+;; Written by Dave Gillespie, daveg@synaptics.com.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY.  No author or distributor
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing.  Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License.   A copy of this license is
+;; supposed to have been given to you along with GNU Emacs so you
+;; can know your rights and responsibilities.  It should be in a
+;; file named COPYING.  Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+
+
+(provide 'calc-macs)
+
+(defun calc-need-macros () nil)
+
+
+(defmacro calc-record-compilation-date-macro ()
+  (` (setq calc-installed-date (, (concat (current-time-string)
+					  " by "
+					  (user-full-name)))))
+)
+
+
+(defmacro calc-wrapper (&rest body)
+  (list 'calc-do (list 'function (append (list 'lambda ()) body)))
+)
+
+;; We use "point" here to generate slightly smaller byte-code than "t".
+(defmacro calc-slow-wrapper (&rest body)
+  (list 'calc-do (list 'function (append (list 'lambda ()) body)) (point))
+)
+
+
+(defmacro math-showing-full-precision (body)
+  (list 'let
+	'((calc-float-format calc-full-float-format))
+	body)
+)
+
+
+(defmacro math-with-extra-prec (delta &rest body)
+  (` (math-normalize
+      (let ((calc-internal-prec (+ calc-internal-prec (, delta))))
+	(,@ body))))
+)
+
+
+;;; Faster in-line version zerop, normalized values only.
+(defmacro Math-zerop (a)   ; [P N]
+  (` (if (consp (, a))
+	 (and (not (memq (car (, a)) '(bigpos bigneg)))
+	      (if (eq (car (, a)) 'float)
+		  (eq (nth 1 (, a)) 0)
+		(math-zerop (, a))))
+       (eq (, a) 0)))
+)
+
+(defmacro Math-integer-negp (a)
+  (` (if (consp (, a))
+	 (eq (car (, a)) 'bigneg)
+       (< (, a) 0)))
+)
+
+(defmacro Math-integer-posp (a)
+  (` (if (consp (, a))
+	 (eq (car (, a)) 'bigpos)
+       (> (, a) 0)))
+)
+
+
+(defmacro Math-negp (a)
+  (` (if (consp (, a))
+	 (or (eq (car (, a)) 'bigneg)
+	     (and (not (eq (car (, a)) 'bigpos))
+		  (if (memq (car (, a)) '(frac float))
+		      (Math-integer-negp (nth 1 (, a)))
+		    (math-negp (, a)))))
+       (< (, a) 0)))
+)
+
+
+(defmacro Math-looks-negp (a)   ; [P x] [Public]
+  (` (or (Math-negp (, a))
+	 (and (consp (, a)) (or (eq (car (, a)) 'neg)
+				(and (memq (car (, a)) '(* /))
+				     (or (math-looks-negp (nth 1 (, a)))
+					 (math-looks-negp (nth 2 (, a)))))))))
+)
+
+
+(defmacro Math-posp (a)
+  (` (if (consp (, a))
+	 (or (eq (car (, a)) 'bigpos)
+	     (and (not (eq (car (, a)) 'bigneg))
+		  (if (memq (car (, a)) '(frac float))
+		      (Math-integer-posp (nth 1 (, a)))
+		    (math-posp (, a)))))
+       (> (, a) 0)))
+)
+
+
+(defmacro Math-integerp (a)
+  (` (or (not (consp (, a)))
+	 (memq (car (, a)) '(bigpos bigneg))))
+)
+
+
+(defmacro Math-natnump (a)
+  (` (if (consp (, a))
+	 (eq (car (, a)) 'bigpos)
+       (>= (, a) 0)))
+)
+
+(defmacro Math-ratp (a)
+  (` (or (not (consp (, a)))
+	 (memq (car (, a)) '(bigpos bigneg frac))))
+)
+
+(defmacro Math-realp (a)
+  (` (or (not (consp (, a)))
+	 (memq (car (, a)) '(bigpos bigneg frac float))))
+)
+
+(defmacro Math-anglep (a)
+  (` (or (not (consp (, a)))
+	 (memq (car (, a)) '(bigpos bigneg frac float hms))))
+)
+
+(defmacro Math-numberp (a)
+  (` (or (not (consp (, a)))
+	 (memq (car (, a)) '(bigpos bigneg frac float cplx polar))))
+)
+
+(defmacro Math-scalarp (a)
+  (` (or (not (consp (, a)))
+	 (memq (car (, a)) '(bigpos bigneg frac float cplx polar hms))))
+)
+
+(defmacro Math-vectorp (a)
+  (` (and (consp (, a)) (eq (car (, a)) 'vec)))
+)
+
+(defmacro Math-messy-integerp (a)
+  (` (and (consp (, a))
+	  (eq (car (, a)) 'float)
+	  (>= (nth 2 (, a)) 0)))
+)
+
+(defmacro Math-objectp (a)    ;  [Public]
+  (` (or (not (consp (, a)))
+	 (memq (car (, a))
+	       '(bigpos bigneg frac float cplx polar hms date sdev intv mod))))
+)
+
+(defmacro Math-objvecp (a)    ;  [Public]
+  (` (or (not (consp (, a)))
+	 (memq (car (, a))
+	       '(bigpos bigneg frac float cplx polar hms date
+			sdev intv mod vec))))
+)
+
+
+;;; Compute the negative of A.  [O O; o o] [Public]
+(defmacro Math-integer-neg (a)
+  (` (if (consp (, a))
+	 (if (eq (car (, a)) 'bigpos)
+	     (cons 'bigneg (cdr (, a)))
+	   (cons 'bigpos (cdr (, a))))
+       (- (, a))))
+)
+
+
+(defmacro Math-equal (a b)
+  (` (= (math-compare (, a) (, b)) 0))
+)
+
+(defmacro Math-lessp (a b)
+  (` (= (math-compare (, a) (, b)) -1))
+)
+
+
+(defmacro math-working (msg arg)    ; [Public]
+  (` (if (eq calc-display-working-message 'lots)
+	 (math-do-working (, msg) (, arg))))
+)
+
+
+(defmacro calc-with-default-simplification (body)
+  (list 'let
+	'((calc-simplify-mode (and (not (memq calc-simplify-mode '(none num)))
+				   calc-simplify-mode)))
+	body)
+)
+
+
+(defmacro Math-primp (a)
+  (` (or (not (consp (, a)))
+	 (memq (car (, a)) '(bigpos bigneg frac float cplx polar
+				    hms date mod var))))
+)
+
+
+(defmacro calc-with-trail-buffer (&rest body)
+  (` (let ((save-buf (current-buffer))
+	   (calc-command-flags nil))
+       (unwind-protect
+	   (, (append '(progn
+			 (set-buffer (calc-trail-display t))
+			 (goto-char calc-trail-pointer))
+		      body))
+	 (set-buffer save-buf))))
+)
+
+
+(defmacro Math-num-integerp (a)
+  (` (or (not (consp (, a)))
+	 (memq (car (, a)) '(bigpos bigneg))
+	 (and (eq (car (, a)) 'float)
+	      (>= (nth 2 (, a)) 0))))
+)
+
+
+(defmacro Math-bignum-test (a)   ; [B N; B s; b b]
+  (` (if (consp (, a))
+	 (, a)
+       (math-bignum (, a))))
+)
+
+
+(defmacro Math-equal-int (a b)
+  (` (or (eq (, a) (, b))
+	 (and (consp (, a))
+	      (eq (car (, a)) 'float)
+	      (eq (nth 1 (, a)) (, b))
+	      (= (nth 2 (, a)) 0))))
+)
+
+(defmacro Math-natnum-lessp (a b)
+  (` (if (consp (, a))
+	 (and (consp (, b))
+	      (= (math-compare-bignum (cdr (, a)) (cdr (, b))) -1))
+       (or (consp (, b))
+	   (< (, a) (, b)))))
+)
+
+
+(defmacro math-format-radix-digit (a)   ; [X D]
+  (` (aref math-radix-digits (, a)))
+)
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/calc-maint.el	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,466 @@
+;; Calculator for GNU Emacs, maintenance routines
+;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+;; Written by Dave Gillespie, daveg@synaptics.com.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY.  No author or distributor
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing.  Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License.   A copy of this license is
+;; supposed to have been given to you along with GNU Emacs so you
+;; can know your rights and responsibilities.  It should be in a
+;; file named COPYING.  Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+
+
+
+
+(defun calc-compile ()
+  "Compile all parts of Calc.
+Unix usage:
+     emacs -batch -l calc-maint -f calc-compile"
+  (interactive)
+  (if (equal (user-full-name) "David Gillespie")
+      (load "~/lisp/newbytecomp"))
+  (setq byte-compile-verbose t)
+  (if noninteractive
+      (let ((old-message (symbol-function 'message))
+	    (old-write-region (symbol-function 'write-region))
+	    (comp-was-func nil)
+	    (comp-len 0))
+	(unwind-protect
+	    (progn
+	      (fset 'message (symbol-function 'calc-compile-message))
+	      (fset 'write-region (symbol-function 'calc-compile-write-region))
+	      (calc-do-compile))
+	  (fset 'message old-message)
+	  (fset 'write-region old-write-region)))
+    (calc-do-compile))
+)
+
+(defun calc-do-compile ()
+  (let ((make-backup-files nil)
+	(changed-rules nil)
+	(changed-units nil)
+	(message-bug (string-match "^18.\\([0-4][0-9]\\|5[0-6]\\)"
+				   emacs-version)))
+    (setq max-lisp-eval-depth (max 400 max-lisp-eval-depth))
+    ;; Enable some irrelevant warnings to avoid compiler bug in 19.29:
+    (setq byte-compile-warnings (and (string-match "^19.29" emacs-version)
+				     '(obsolete)))
+
+    ;; Make sure we're in the right directory.
+    (find-file "calc.el")
+    (if (= (buffer-size) 0)
+	(error "This command must be used in the Calc source directory."))
+
+    ;; Make sure current directory is in load-path.
+    (setq load-path (cons default-directory load-path))
+    (load "calc-macs.el" nil t t)
+    (provide 'calc)
+    (provide 'calc-ext)
+
+    ;; Compile all the source files.
+    (let ((files (append
+		  '("calc.el" "calc-ext.el")
+		  (sort (directory-files
+			 default-directory nil
+			 "\\`calc-.[^x].*\\.el\\'")
+			'string<))))
+      (while files
+	(if (file-newer-than-file-p (car files) (concat (car files) "c"))
+	    (progn
+	      (if (string-match "calc-rules" (car files))
+		  (setq changed-rules t))
+	      (if (string-match "calc-units" (car files))
+		  (setq changed-units t))
+	      (or message-bug (message ""))
+	      (byte-compile-file (car files)))
+	  (message "File %s is up to date." (car files)))
+	(if (string-match "calc\\(-ext\\)?.el" (car files))
+	    (load (concat (car files) "c") nil t t))
+	(setq files (cdr files))))
+
+    (if (or changed-units changed-rules)
+	(condition-case err
+	    (progn
+
+	      ;; Pre-build the units table.
+	      (if (and changed-units
+		       (not (string-match "Lucid" emacs-version)))
+		  (progn
+		    (or message-bug (message ""))
+		    (save-excursion
+		      (calc-create-buffer)
+		      (math-build-units-table))
+		    (find-file "calc-units.elc")
+		    (goto-char (point-max))
+		    (insert "\n(setq math-units-table '"
+			    (prin1-to-string math-units-table)
+			    ")\n")
+		    (save-buffer)))
+
+	      ;; Pre-build rewrite rules for j D, j M, etc.
+	      (if (and changed-rules (not (string-match "^19" emacs-version)))
+		  (let ((rules nil))
+		    (or message-bug (message ""))
+		    (find-file "calc-rules.elc")
+		    (goto-char (point-min))
+		    (while (re-search-forward "defun calc-\\([A-Za-z]*Rules\\)"
+					      nil t)
+		      (setq rules (cons (buffer-substring (match-beginning 1)
+							  (match-end 1))
+					rules)))
+		    (goto-char (point-min))
+		    (re-search-forward "\n(defun calc-[A-Za-z]*Rules")
+		    (beginning-of-line)
+		    (delete-region (point) (point-max))
+		    (mapcar (function
+			     (lambda (v)
+			       (let* ((vv (intern (concat "var-" v)))
+				      (val (save-excursion
+					     (calc-create-buffer)
+					     (calc-var-value vv))))
+				 (insert "\n(defun calc-" v " () '"
+					 (prin1-to-string val) ")\n"))))
+			    (sort rules 'string<))
+		    (save-buffer))))
+	  (error (message "Unable to pre-build tables %s" err))))
+    (message "Done.  Don't forget to install with \"make public\" or \"make private\"."))
+)
+
+(defun calc-compile-message (fmt &rest args)
+  (cond ((and (= (length args) 2)
+	      (stringp (car args))
+	      (string-match ".elc?\\'" (car args))
+	      (symbolp (nth 1 args)))
+	 (let ((name (symbol-name (nth 1 args))))
+	   (princ (if comp-was-func ", " "  "))
+	   (if (and comp-was-func (eq (string-match comp-was-func name) 0))
+	       (setq name (substring name (1- (length comp-was-func))))
+	     (setq comp-was-func (if (string-match "\\`[a-zA-Z]+-" name)
+				     (substring name 0 (match-end 0))
+				   " ")))
+	   (if (> (+ comp-len (length name)) 75)
+	       (progn
+		 (princ "\n  ")
+		 (setq comp-len 0)))
+	   (princ name)
+	   (send-string-to-terminal "")  ; cause an fflush(stdout)
+	   (setq comp-len (+ comp-len 2 (length name)))))
+	((and (setq comp-was-func nil
+		    comp-len 0)
+	      (= (length args) 1)
+	      (stringp (car args))
+	      (string-match ".elc?\\'" (car args)))
+	 (or (string-match "Saving file %s..." fmt)
+	     (funcall old-message fmt (file-name-nondirectory (car args)))))
+	((string-match "\\(Preparing\\|Building\\).*\\.\\.\\.$" fmt)
+	 (send-string-to-terminal (apply 'format fmt args)))
+	((string-match "\\(Preparing\\|Building\\).*\\.\\.\\. *done$" fmt)
+	 (send-string-to-terminal "done\n"))
+	(t (apply old-message fmt args)))
+)
+
+(defun calc-compile-write-region (start end filename &optional append visit &rest rest)
+  (if (eq visit t)
+      (set-buffer-auto-saved))
+  (if (and (string-match "\\.elc" filename)
+	   (= start (point-min))
+	   (= end (point-max)))
+      (save-excursion
+	(goto-char (point-min))
+	(if (search-forward "\n(require (quote calc-macs))\n" nil t)
+	    (replace-match ""))
+	(setq end (point-max))))
+  (apply old-write-region start end filename append 'quietly rest)
+  (message "Wrote %s" filename)
+  nil
+)
+
+
+
+(defun calc-split-tutorial (&optional force)
+  (interactive "P")
+  (calc-split-manual force 1))
+
+
+(defun calc-split-reference (&optional force)
+  (interactive "P")
+  (calc-split-manual force 2))
+
+
+(defun calc-split-manual (&optional force part)
+  "Split the Calc manual into separate Tutorial and Reference manuals.
+Use this if your TeX installation is too small-minded to handle
+calc.texinfo all at once.
+Usage:  C-x C-f calc.texinfo RET
+        M-x calc-split-manual RET"
+  (interactive "P")
+  (or (let ((case-fold-search t))
+	(string-match "calc\\.texinfo" (buffer-name)))
+      force
+      (error "This command should be used in the calc.texinfo buffer."))
+  (let ((srcbuf (current-buffer))
+	tutpos refpos endpos (maxpos (point-max)))
+    (goto-char 1)
+    (search-forward "@c [tutorial]")
+    (beginning-of-line)
+    (setq tutpos (point))
+    (search-forward "@c [reference]")
+    (beginning-of-line)
+    (setq refpos (point))
+    (search-forward "@c [end]")
+    (beginning-of-line)
+    (setq endpos (point))
+    (or (eq part 2)
+	(progn
+	  (find-file "calctut.tex")
+	  (erase-buffer)
+	  (insert-buffer-substring srcbuf 1 refpos)
+	  (insert-buffer-substring srcbuf endpos maxpos)
+	  (calc-split-volume "I" "ref" "Tutorial" "Reference")
+	  (save-buffer)))
+    (or (eq part 1)
+	(progn
+	  (find-file "calcref.tex")
+	  (erase-buffer)
+	  (insert-buffer-substring srcbuf 1 tutpos)
+	  (insert "\n@tex\n\\global\\advance\\chapno by 1\n@end tex\n")
+	  (insert-buffer-substring srcbuf refpos maxpos)
+	  (calc-split-volume "II" "tut" "Reference" "Tutorial")
+	  (save-buffer)))
+    (switch-to-buffer srcbuf)
+    (goto-char 1))
+  (message (cond ((eq part 1) "Wrote file calctut.tex")
+		 ((eq part 2) "Wrote file calcref.tex")
+		 (t "Wrote files calctut.tex and calcref.tex")))
+)
+
+(defun calc-split-volume (number fix name other-name)
+  (goto-char 1)
+  (search-forward "@c [title]\n")
+  (search-forward "Manual")
+  (delete-backward-char 6)
+  (insert name)
+  (search-forward "@c [volume]\n")
+  (insert "@sp 1\n@center Volume " number ": " name "\n")
+  (let ((pat (format "@c \\[fix-%s \\(.*\\)\\]\n" fix)))
+    (while (re-search-forward pat nil t)
+      (let ((topic (buffer-substring (match-beginning 1) (match-end 1))))
+	(re-search-forward "@\\(p?xref\\){[^}]*}")
+	(let ((cmd (buffer-substring (match-beginning 1) (match-end 1))))
+	  (delete-region (match-beginning 0) (match-end 0))
+	  (insert (if (equal cmd "pxref") "see" "See")
+		  " ``" topic "'' in @emph{the Calc "
+		  other-name "}")))))
+  (goto-char 1)
+  (while (search-forward "@c [when-split]\n" nil t)
+    (while (looking-at "@c ")
+      (delete-char 3)
+      (forward-line 1)))
+  (goto-char 1)
+  (while (search-forward "@c [not-split]\n" nil t)
+    (while (not (looking-at "@c"))
+      (insert "@c ")
+      (forward-line 1)))
+)
+
+
+(defun calc-inline-summary ()
+  "Make a special \"calcsum.tex\" file to be used with main manual."
+  (calc-split-summary nil t)
+)
+
+(defun calc-split-summary (&optional force in-line)
+  "Make a special \"calcsum.tex\" file with just the Calc summary."
+  (interactive "P")
+  (or (let ((case-fold-search t))
+	(string-match "calc\\.texinfo" (buffer-name)))
+      force
+      (error "This command should be used in the calc.texinfo buffer."))
+  (let ((srcbuf (current-buffer))
+	begpos sumpos endpos midpos)
+    (goto-char 1)
+    (search-forward "{Calc Manual}")
+    (backward-char 1)
+    (delete-backward-char 6)
+    (insert "Summary")
+    (search-forward "@c [begin]")
+    (beginning-of-line)
+    (setq begpos (point))
+    (search-forward "@c [summary]")
+    (beginning-of-line)
+    (setq sumpos (point))
+    (search-forward "@c [end-summary]")
+    (beginning-of-line)
+    (setq endpos (point))
+    (find-file "calcsum.tex")
+    (erase-buffer)
+    (insert-buffer-substring srcbuf 1 begpos)
+    (insert "@tex\n"
+	    "\\global\\advance\\appendixno2\n"
+	    "\\gdef\\xref#1.{See ``#1.''}\n")
+    (setq midpos (point))
+    (insert "@end tex\n")
+    (insert-buffer-substring srcbuf sumpos endpos)
+    (insert "@bye\n")
+    (goto-char 1)
+    (if (search-forward "{. a b c" nil t)
+	(replace-match "{... a b c"))
+    (goto-char 1)
+    (if in-line
+	(let ((buf (current-buffer))
+	      (page nil))
+	  (find-file "calc.aux")
+	  (if (> (buffer-size) 0)
+	      (progn
+		(goto-char 1)
+		(re-search-forward "{Summary-pg}{\\([0-9]+\\)}")
+		(setq page (string-to-int (buffer-substring (match-beginning 1)
+							    (match-end 1))))))
+	  (switch-to-buffer buf)
+	  (if page
+	      (progn
+		(message "Adjusting starting page number to %d" page)
+		(goto-char midpos)
+		(insert (format "\\global\\pageno=%d\n" page)))
+	    (message "Unable to find page number from calc.aux")))
+      (if (search-forward "@c smallbook" nil t)
+	  (progn   ; activate "smallbook" format for compactness
+	    (beginning-of-line)
+	    (forward-char 1)
+	    (delete-char 2))))
+    (let ((buf (current-buffer)))
+      (find-file "calc.ky")
+      (if (> (buffer-size) 0)
+	  (let ((ibuf (current-buffer)))
+	    (message "Mixing in page numbers from Key Index (calc.ky)")
+	    (switch-to-buffer buf)
+	    (goto-char 1)
+	    (search-forward "notes at the end")
+	    (insert "; the number in italics is\n"
+		    "the page number where the command is described")
+	    (while (re-search-forward
+		    "@r{.*@: *\\([^ ]\\(.*[^ ]\\)?\\) *@:.*@:.*@:\\(.*\\)@:.*}"
+		    nil t)
+	      (let ((key (buffer-substring (match-beginning 1) (match-end 1)))
+		    (pos (match-beginning 3))
+		    num)
+		(set-buffer ibuf)
+		(goto-char 1)
+		(let ((p '( ( "I H " . "H I " )  ; oops!
+			    ( "@@ ' \"" . "@@" ) ( "h m s" . "@@" )
+			    ( "\\\\" . "{\\tt\\indexbackslash }" )
+			    ( "_" . "{\\_}" )
+			    ( "\\^" . "{\\tt\\hat}" )
+			    ( "<" . "{\\tt\\less}" )
+			    ( ">" . "{\\tt\\gtr}" )
+			    ( "\"" ) ( "@{" ) ( "@}" )
+			    ( "~" ) ( "|" ) ( "@@" )
+			    ( "\\+" . "{\\tt\\char43}" )
+			    ( "# l" . "# L" )
+			    ( "I f I" . "f I" ) ( "I f Q" . "f Q" )
+			    ( "V &" . "&" ) ( "C-u " . "" ) ))
+		      (case-fold-search nil))
+		  (while p
+		    (if (string-match (car (car p)) key)
+			(setq key (concat (substring key 0 (match-beginning 0))
+					  (or (cdr (car p))
+					      (format "{\\tt\\char'%03o}"
+						      (aref key (1- (match-end
+								     0)))))
+					  (substring key (match-end 0)))))
+		    (setq p (cdr p)))
+		  (setq num (and (search-forward (format "\\entry {%s}{" key)
+						 nil t)
+				 (looking-at "[0-9]+")
+				 (buffer-substring (point) (match-end 0)))))
+		(set-buffer buf)
+		(goto-char pos)
+		(insert "@pgref{" (or num "") "}")))
+	    (goto-char midpos)
+	    (insert "\\gdef\\pgref#1{\\hbox to 2em{\\indsl\\hss#1}\\ \\ }\n"))
+	(message
+	 "Unable to find Key Index (calc.ky); no page numbers inserted"))
+      (switch-to-buffer buf))
+    (save-buffer))
+  (message "Wrote file calcsum.tex")
+)
+
+
+
+(defun calc-public-autoloads ()
+  "Modify the public \"default\" file to contain the necessary autoload and
+global-set-key commands for Calc."
+  (interactive)
+  (let ((home default-directory)
+	(p load-path)
+	instbuf name)
+    (while (and p
+		(not (file-exists-p
+		      (setq name (expand-file-name "default" (car p)))))
+		(not (file-exists-p
+		      (setq name (expand-file-name "default.el" (car p))))))
+      (setq p (cdr p)))
+    (or p (error "Unable to find \"default\" file.  Create one and try again."))
+    (find-file name)
+    (if buffer-read-only (error "No write permission for \"%s\"" buffer-file-name))
+    (goto-char (point-max))
+    (calc-add-autoloads home "calc-public-autoloads"))
+)
+
+(defun calc-private-autoloads ()
+  "Modify the user's \".emacs\" file to contain the necessary autoload and
+global-set-key commands for Calc."
+  (interactive)
+  (let ((home default-directory))
+    (find-file "~/.emacs")
+    (goto-char (point-max))
+    (calc-add-autoloads home "calc-private-autoloads"))
+)
+
+(defun calc-add-autoloads (home cmd)
+  (barf-if-buffer-read-only)
+  (let (top)
+    (if (and (re-search-backward ";;; Commands added by calc-.*-autoloads"
+				 nil t)
+	     (setq top (point))
+	     (search-forward ";;; End of Calc autoloads" nil t))
+	(progn
+	  (forward-line 1)
+	  (message "(Removing previous autoloads)")
+	  (delete-region top (point)))
+      (insert "\n\n")
+      (backward-char 1)))
+  (insert ";;; Commands added by " cmd " on "
+	  (current-time-string) ".
+\(autoload 'calc-dispatch	   \"calc\" \"Calculator Options\" t)
+\(autoload 'full-calc		   \"calc\" \"Full-screen Calculator\" t)
+\(autoload 'full-calc-keypad	   \"calc\" \"Full-screen X Calculator\" t)
+\(autoload 'calc-eval		   \"calc\" \"Use Calculator from Lisp\")
+\(autoload 'defmath		   \"calc\" nil t t)
+\(autoload 'calc			   \"calc\" \"Calculator Mode\" t)
+\(autoload 'quick-calc		   \"calc\" \"Quick Calculator\" t)
+\(autoload 'calc-keypad		   \"calc\" \"X windows Calculator\" t)
+\(autoload 'calc-embedded	   \"calc\" \"Use Calc inside any buffer\" t)
+\(autoload 'calc-embedded-activate  \"calc\" \"Activate =>'s in buffer\" t)
+\(autoload 'calc-grab-region	   \"calc\" \"Grab region of Calc data\" t)
+\(autoload 'calc-grab-rectangle	   \"calc\" \"Grab rectangle of data\" t)
+\(setq load-path (nconc load-path (list \"" (directory-file-name home) "\")))
+\(global-set-key \"\\e#\" 'calc-dispatch)
+;;; End of Calc autoloads.\n")
+  (let ((trim-versions-without-asking t))
+    (save-buffer))
+)
+
+
+
+;;; End.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/calc-map.el	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,1305 @@
+;; Calculator for GNU Emacs, part II [calc-map.el]
+;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+;; Written by Dave Gillespie, daveg@synaptics.com.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY.  No author or distributor
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing.  Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License.   A copy of this license is
+;; supposed to have been given to you along with GNU Emacs so you
+;; can know your rights and responsibilities.  It should be in a
+;; file named COPYING.  Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+
+
+
+;; This file is autoloaded from calc-ext.el.
+(require 'calc-ext)
+
+(require 'calc-macs)
+
+(defun calc-Need-calc-map () nil)
+
+
+(defun calc-apply (&optional oper)
+  (interactive)
+  (calc-wrapper
+   (let* ((sel-mode nil)
+	  (calc-dollar-values (mapcar 'calc-get-stack-element
+				      (nthcdr calc-stack-top calc-stack)))
+	  (calc-dollar-used 0)
+	  (oper (or oper (calc-get-operator "Apply"
+					    (if (math-vectorp (calc-top 1))
+						(1- (length (calc-top 1)))
+					      -1))))
+	  (expr (calc-top-n (1+ calc-dollar-used))))
+     (message "Working...")
+     (calc-set-command-flag 'clear-message)
+     (calc-enter-result (1+ calc-dollar-used)
+			(concat (substring "apl" 0 (- 4 (length (nth 2 oper))))
+				(nth 2 oper))
+			(list 'calcFunc-apply
+			      (math-calcFunc-to-var (nth 1 oper))
+			      expr))))
+)
+
+(defun calc-reduce (&optional oper accum)
+  (interactive)
+  (calc-wrapper
+   (let* ((sel-mode nil)
+	  (nest (calc-is-hyperbolic))
+	  (rev (calc-is-inverse))
+	  (nargs (if (and nest (not rev)) 2 1))
+	  (calc-dollar-values (mapcar 'calc-get-stack-element
+				      (nthcdr calc-stack-top calc-stack)))
+	  (calc-dollar-used 0)
+	  (calc-mapping-dir (and (not accum) (not nest) ""))
+	  (oper (or oper (calc-get-operator
+			  (if nest
+			      (concat (if accum "Accumulate " "")
+				      (if rev "Fixed Point" "Nest"))
+			    (concat (if rev "Inv " "")
+				    (if accum "Accumulate" "Reduce")))
+			  (if nest 1 2)))))
+     (message "Working...")
+     (calc-set-command-flag 'clear-message)
+     (calc-enter-result (+ calc-dollar-used nargs)
+			(concat (substring (if nest
+					       (if rev "fxp" "nst")
+					     (if accum "acc" "red"))
+					   0 (- 4 (length (nth 2 oper))))
+				(nth 2 oper))
+			(if nest
+			    (cons (if rev
+				      (if accum 'calcFunc-afixp 'calcFunc-fixp)
+				    (if accum 'calcFunc-anest 'calcFunc-nest))
+				  (cons (math-calcFunc-to-var (nth 1 oper))
+					(calc-top-list-n
+					 nargs (1+ calc-dollar-used))))
+			  (list (if accum
+				    (if rev 'calcFunc-raccum 'calcFunc-accum)
+				  (intern (concat "calcFunc-"
+						  (if rev "r" "")
+						  "reduce"
+						  calc-mapping-dir)))
+				(math-calcFunc-to-var (nth 1 oper))
+				(calc-top-n (1+ calc-dollar-used)))))))
+)
+
+(defun calc-accumulate (&optional oper)
+  (interactive)
+  (calc-reduce oper t)
+)
+
+(defun calc-map (&optional oper)
+  (interactive)
+  (calc-wrapper
+   (let* ((sel-mode nil)
+	  (calc-dollar-values (mapcar 'calc-get-stack-element
+				      (nthcdr calc-stack-top calc-stack)))
+	  (calc-dollar-used 0)
+	  (calc-mapping-dir "")
+	  (oper (or oper (calc-get-operator "Map")))
+	  (nargs (car oper)))
+     (message "Working...")
+     (calc-set-command-flag 'clear-message)
+     (calc-enter-result (+ nargs calc-dollar-used)
+			(concat (substring "map" 0 (- 4 (length (nth 2 oper))))
+				(nth 2 oper))
+			(cons (intern (concat "calcFunc-map" calc-mapping-dir))
+			      (cons (math-calcFunc-to-var (nth 1 oper))
+				    (calc-top-list-n
+				     nargs
+				     (1+ calc-dollar-used)))))))
+)
+
+(defun calc-map-equation (&optional oper)
+  (interactive)
+  (calc-wrapper
+   (let* ((sel-mode nil)
+	  (calc-dollar-values (mapcar 'calc-get-stack-element
+				      (nthcdr calc-stack-top calc-stack)))
+	  (calc-dollar-used 0)
+	  (oper (or oper (calc-get-operator "Map-equation")))
+	  (nargs (car oper)))
+     (message "Working...")
+     (calc-set-command-flag 'clear-message)
+     (calc-enter-result (+ nargs calc-dollar-used)
+			(concat (substring "map" 0 (- 4 (length (nth 2 oper))))
+				(nth 2 oper))
+			(cons (if (calc-is-inverse)
+				  'calcFunc-mapeqr
+				(if (calc-is-hyperbolic)
+				    'calcFunc-mapeqp 'calcFunc-mapeq))
+			      (cons (math-calcFunc-to-var (nth 1 oper))
+				    (calc-top-list-n
+				     nargs
+				     (1+ calc-dollar-used)))))))
+)
+
+(defun calc-map-stack ()
+  "This is meant to be called by calc-keypad mode."
+  (interactive)
+  (let ((calc-verify-arglist nil))
+    (calc-unread-command ?\$)
+    (calc-map))
+)
+
+(defun calc-outer-product (&optional oper)
+  (interactive)
+  (calc-wrapper
+   (let* ((sel-mode nil)
+	  (calc-dollar-values (mapcar 'calc-get-stack-element
+				      (nthcdr calc-stack-top calc-stack)))
+	  (calc-dollar-used 0)
+	  (oper (or oper (calc-get-operator "Outer" 2))))
+     (message "Working...")
+     (calc-set-command-flag 'clear-message)
+     (calc-enter-result (+ 2 calc-dollar-used)
+			(concat (substring "out" 0 (- 4 (length (nth 2 oper))))
+				(nth 2 oper))
+			(cons 'calcFunc-outer
+			      (cons (math-calcFunc-to-var (nth 1 oper))
+				    (calc-top-list-n
+				     2 (1+ calc-dollar-used)))))))
+)
+
+(defun calc-inner-product (&optional mul-oper add-oper)
+  (interactive)
+  (calc-wrapper
+   (let* ((sel-mode nil)
+	  (calc-dollar-values (mapcar 'calc-get-stack-element
+				      (nthcdr calc-stack-top calc-stack)))
+	  (calc-dollar-used 0)
+	  (mul-oper (or mul-oper (calc-get-operator "Inner (Mult)" 2)))
+	  (mul-used calc-dollar-used)
+	  (calc-dollar-values (if (> mul-used 0)
+				  (cdr calc-dollar-values)
+				calc-dollar-values))
+	  (calc-dollar-used 0)
+	  (add-oper (or add-oper (calc-get-operator "Inner (Add)" 2))))
+     (message "Working...")
+     (calc-set-command-flag 'clear-message)
+     (calc-enter-result (+ 2 mul-used calc-dollar-used)
+			(concat "in"
+				(substring (nth 2 mul-oper) 0 1)
+				(substring (nth 2 add-oper) 0 1))
+			(nconc (list 'calcFunc-inner
+				     (math-calcFunc-to-var (nth 1 mul-oper))
+				     (math-calcFunc-to-var (nth 1 add-oper)))
+			       (calc-top-list-n
+				2 (+ 1 mul-used calc-dollar-used))))))
+)
+
+;;; Return a list of the form (nargs func name)
+(defun calc-get-operator (msg &optional nargs)
+  (setq calc-aborted-prefix nil)
+  (let ((inv nil) (hyp nil) (prefix nil) (forcenargs nil)
+	done key oper (which 0)
+	(msgs '( "(Press ? for help)"
+		 "+, -, *, /, ^, %, \\, :, &, !, |, Neg"
+		 "SHIFT + Abs, conJ, arG; maX, miN; Floor, Round; sQrt"
+		 "SHIFT + Inv, Hyp; Sin, Cos, Tan; Exp, Ln, logB"
+		 "Algebra + Simp, Esimp, Deriv, Integ, !, =, etc."
+		 "Binary + And, Or, Xor, Diff; l/r/t/L/R shifts; Not, Clip"
+		 "Conversions + Deg, Rad, HMS; Float; SHIFT + Fraction"
+		 "Functions + Re, Im; Hypot; Mant, Expon, Scale; etc."
+		 "Kombinatorics + Dfact, Lcm, Gcd, Choose; Random; etc."
+		 "Time/date + newYear, Incmonth, etc."
+		 "Vectors + Length, Row, Col, Diag, Mask, etc."
+		 "_ = mapr/reducea, : = mapc/reduced, = = reducer"
+		 "X or Z = any function by name; ' = alg entry; $ = stack")))
+    (while (not done)
+      (message "%s%s: %s: %s%s%s"
+	       msg
+	       (cond ((equal calc-mapping-dir "r") " rows")
+		     ((equal calc-mapping-dir "c") " columns")
+		     ((equal calc-mapping-dir "a") " across")
+		     ((equal calc-mapping-dir "d") " down")
+		     (t ""))
+	       (if forcenargs
+		   (format "(%d arg%s)"
+			   forcenargs (if (= forcenargs 1) "" "s"))
+		 (nth which msgs))
+	       (if inv "Inv " "") (if hyp "Hyp " "")
+	       (if prefix (concat (char-to-string prefix) "-") ""))
+      (setq key (read-char))
+      (if (>= key 128) (setq key (- key 128)))
+      (cond ((memq key '(?\C-g ?q))
+	     (keyboard-quit))
+	    ((memq key '(?\C-u ?\e)))
+	    ((= key ??)
+	     (setq which (% (1+ which) (length msgs))))
+	    ((and (= key ?I) (null prefix))
+	     (setq inv (not inv)))
+	    ((and (= key ?H) (null prefix))
+	     (setq hyp (not hyp)))
+	    ((and (eq key prefix) (not (eq key ?v)))
+	     (setq prefix nil))
+	    ((and (memq key '(?a ?b ?c ?f ?k ?s ?t ?u ?v ?V))
+		  (null prefix))
+	     (setq prefix (downcase key)))
+	    ((and (eq key ?\=) (null prefix))
+	     (if calc-mapping-dir
+		 (setq calc-mapping-dir (if (equal calc-mapping-dir "r")
+					    "" "r"))
+	       (beep)))
+	    ((and (eq key ?\_) (null prefix))
+	     (if calc-mapping-dir
+		 (if (string-match "map$" msg)
+		     (setq calc-mapping-dir (if (equal calc-mapping-dir "r")
+						"" "r"))
+		   (setq calc-mapping-dir (if (equal calc-mapping-dir "a")
+					      "" "a")))
+	       (beep)))
+	    ((and (eq key ?\:) (null prefix))
+	     (if calc-mapping-dir
+		 (if (string-match "map$" msg)
+		     (setq calc-mapping-dir (if (equal calc-mapping-dir "c")
+						"" "c"))
+		   (setq calc-mapping-dir (if (equal calc-mapping-dir "d")
+					      "" "d")))
+	       (beep)))
+	    ((and (>= key ?0) (<= key ?9) (null prefix))
+	     (setq forcenargs (if (eq forcenargs (- key ?0)) nil (- key ?0)))
+	     (and nargs forcenargs (/= nargs forcenargs) (>= nargs 0)
+		  (error "Must be a %d-argument operator" nargs)))
+	    ((memq key '(?\$ ?\'))
+	     (let* ((arglist nil)
+		    (has-args nil)
+		    (record-entry nil)
+		    (expr (if (eq key ?\$)
+			      (progn
+				(setq calc-dollar-used 1)
+				(if calc-dollar-values
+				    (car calc-dollar-values)
+				  (error "Stack underflow")))
+			    (let* ((calc-dollar-values calc-arg-values)
+				   (calc-dollar-used 0)
+				   (calc-hashes-used 0)
+				   (func (calc-do-alg-entry "" "Function: ")))
+			      (setq record-entry t)
+			      (or (= (length func) 1)
+				  (error "Bad format"))
+			      (if (> calc-dollar-used 0)
+				  (progn
+				    (setq has-args calc-dollar-used
+					  arglist (calc-invent-args has-args))
+				    (math-multi-subst (car func)
+						      (reverse arglist)
+						      arglist))
+				(if (> calc-hashes-used 0)
+				    (setq has-args calc-hashes-used
+					  arglist (calc-invent-args has-args)))
+				(car func))))))
+	       (if (eq (car-safe expr) 'calcFunc-lambda)
+		   (setq oper (list "$" (- (length expr) 2) expr)
+			 done t)
+		 (or has-args
+		     (progn
+		       (calc-default-formula-arglist expr)
+		       (setq record-entry t
+			     arglist (sort arglist 'string-lessp))
+		       (if calc-verify-arglist
+			   (setq arglist (read-from-minibuffer
+					  "Function argument list: "
+					  (if arglist
+					      (prin1-to-string arglist)
+					    "()")
+					  minibuffer-local-map
+					  t)))
+		       (setq arglist (mapcar (function
+					      (lambda (x)
+						(list 'var
+						      x
+						      (intern
+						       (concat
+							"var-"
+							(symbol-name x))))))
+					     arglist))))
+		 (setq oper (list "$"
+				  (length arglist)
+				  (append '(calcFunc-lambda) arglist
+					  (list expr)))
+		       done t))
+	       (if record-entry
+		   (calc-record (nth 2 oper) "oper"))))
+	    ((setq oper (assq key (nth (if inv (if hyp 3 1) (if hyp 2 0))
+				       (if prefix
+					   (symbol-value
+					    (intern (format "calc-%c-oper-keys"
+							    prefix)))
+					 calc-oper-keys))))
+	     (if (eq (nth 1 oper) 'user)
+		 (let ((func (intern
+			      (completing-read "Function name: "
+					       obarray 'fboundp
+					       nil "calcFunc-"))))
+		   (if (or forcenargs nargs)
+		       (setq oper (list "z" (or forcenargs nargs) func)
+			     done t)
+		     (if (fboundp func)
+			 (let* ((defn (symbol-function func)))
+			   (and (symbolp defn)
+				(setq defn (symbol-function defn)))
+			   (if (eq (car-safe defn) 'lambda)
+			       (let ((args (nth 1 defn))
+				     (nargs 0))
+				 (while (not (memq (car args) '(&optional
+								&rest nil)))
+				   (setq nargs (1+ nargs)
+					 args (cdr args)))
+				 (setq oper (list "z" nargs func)
+				       done t))
+			     (error
+			      "Function is not suitable for this operation")))
+		       (message "Number of arguments: ")
+		       (let ((nargs (read-char)))
+			 (if (and (>= nargs ?0) (<= nargs ?9))
+			     (setq oper (list "z" (- nargs ?0) func)
+				   done t)
+			   (beep))))))
+	       (if (or (and (eq prefix ?v) (memq key '(?A ?I ?M ?O ?R ?U)))
+		       (and (eq prefix ?a) (eq key ?M)))
+		   (let* ((dir (cond ((and (equal calc-mapping-dir "")
+					   (string-match "map$" msg))
+				      (setq calc-mapping-dir "r")
+				      " rows")
+				     ((equal calc-mapping-dir "r") " rows")
+				     ((equal calc-mapping-dir "c") " columns")
+				     ((equal calc-mapping-dir "a") " across")
+				     ((equal calc-mapping-dir "d") " down")
+				     (t "")))
+			  (calc-mapping-dir (and (memq (nth 2 oper)
+						       '(calcFunc-map
+							 calcFunc-reduce
+							 calcFunc-rreduce))
+						 ""))
+			  (oper2 (calc-get-operator
+				  (format "%s%s, %s%s" msg dir
+					  (substring (symbol-name (nth 2 oper))
+						     9)
+					  (if (eq key ?I) " (mult)" ""))
+				  (cdr (assq (nth 2 oper)
+					     '((calcFunc-reduce  . 2)
+					       (calcFunc-rreduce . 2)
+					       (calcFunc-accum   . 2)
+					       (calcFunc-raccum  . 2)
+					       (calcFunc-nest    . 2)
+					       (calcFunc-anest   . 2)
+					       (calcFunc-fixp    . 2)
+					       (calcFunc-afixp   . 2))))))
+			  (oper3 (if (eq (nth 2 oper) 'calcFunc-inner)
+				     (calc-get-operator
+				      (format "%s%s, inner (add)" msg dir
+					      (substring
+					       (symbol-name (nth 2 oper))
+					       9)))
+				   '(0 0 0)))
+			  (args nil)
+			  (nargs (if (> (nth 1 oper) 0)
+				     (nth 1 oper)
+				   (car oper2)))
+			  (n nargs)
+			  (p calc-arg-values))
+		     (while (and p (> n 0))
+		       (or (math-expr-contains (nth 1 oper2) (car p))
+			   (math-expr-contains (nth 1 oper3) (car p))
+			   (setq args (nconc args (list (car p)))
+				 n (1- n)))
+		       (setq p (cdr p)))
+		     (setq oper (list "" nargs
+				      (append
+				       '(calcFunc-lambda)
+				       args
+				       (list (math-build-call
+					      (intern
+					       (concat
+						(symbol-name (nth 2 oper))
+						calc-mapping-dir))
+					      (cons (math-calcFunc-to-var
+						     (nth 1 oper2))
+						    (if (eq key ?I)
+							(cons
+							 (math-calcFunc-to-var
+							  (nth 1 oper3))
+							 args)
+						      args))))))
+			   done t))
+		 (setq done t))))
+	    (t (beep))))
+    (and nargs (>= nargs 0)
+	 (/= nargs (nth 1 oper))
+	 (error "Must be a %d-argument operator" nargs))
+    (append (if forcenargs
+		(cons forcenargs (cdr (cdr oper)))
+	      (cdr oper))
+	    (list
+	     (let ((name (concat (if inv "I" "") (if hyp "H" "")
+				 (if prefix (char-to-string prefix) "")
+				 (char-to-string key))))
+	       (if (> (length name) 3)
+		   (substring name 0 3)
+		 name)))))
+)
+(setq calc-verify-arglist t)
+(setq calc-mapping-dir nil)
+
+(defconst calc-oper-keys '( ( ( ?+ 2 calcFunc-add )
+			      ( ?- 2 calcFunc-sub )
+			      ( ?* 2 calcFunc-mul )
+			      ( ?/ 2 calcFunc-div )
+			      ( ?^ 2 calcFunc-pow )
+			      ( ?| 2 calcFunc-vconcat )
+			      ( ?% 2 calcFunc-mod )
+			      ( ?\\ 2 calcFunc-idiv )
+			      ( ?! 1 calcFunc-fact )
+			      ( ?& 1 calcFunc-inv )
+			      ( ?n 1 calcFunc-neg )
+			      ( ?x user )
+			      ( ?z user )
+			      ( ?A 1 calcFunc-abs )
+			      ( ?J 1 calcFunc-conj )
+			      ( ?G 1 calcFunc-arg )
+			      ( ?Q 1 calcFunc-sqrt )
+			      ( ?N 2 calcFunc-min )
+			      ( ?X 2 calcFunc-max )
+			      ( ?F 1 calcFunc-floor )
+			      ( ?R 1 calcFunc-round )
+			      ( ?S 1 calcFunc-sin )
+			      ( ?C 1 calcFunc-cos )
+			      ( ?T 1 calcFunc-tan )
+			      ( ?L 1 calcFunc-ln )
+			      ( ?E 1 calcFunc-exp )
+			      ( ?B 2 calcFunc-log ) )
+			    ( ( ?F 1 calcFunc-ceil )     ; inverse
+			      ( ?R 1 calcFunc-trunc )
+			      ( ?Q 1 calcFunc-sqr )
+			      ( ?S 1 calcFunc-arcsin )
+			      ( ?C 1 calcFunc-arccos )
+			      ( ?T 1 calcFunc-arctan )
+			      ( ?L 1 calcFunc-exp )
+			      ( ?E 1 calcFunc-ln )
+			      ( ?B 2 calcFunc-alog )
+			      ( ?^ 2 calcFunc-nroot )
+			      ( ?| 2 calcFunc-vconcatrev ) )
+			    ( ( ?F 1 calcFunc-ffloor )   ; hyperbolic
+			      ( ?R 1 calcFunc-fround )
+			      ( ?S 1 calcFunc-sinh )
+			      ( ?C 1 calcFunc-cosh )
+			      ( ?T 1 calcFunc-tanh )
+			      ( ?L 1 calcFunc-log10 )
+			      ( ?E 1 calcFunc-exp10 )
+			      ( ?| 2 calcFunc-append ) )
+			    ( ( ?F 1 calcFunc-fceil )    ; inverse-hyperbolic
+			      ( ?R 1 calcFunc-ftrunc )
+			      ( ?S 1 calcFunc-arcsinh )
+			      ( ?C 1 calcFunc-arccosh )
+			      ( ?T 1 calcFunc-arctanh )
+			      ( ?L 1 calcFunc-exp10 )
+			      ( ?E 1 calcFunc-log10 )
+			      ( ?| 2 calcFunc-appendrev ) )
+))
+(defconst calc-a-oper-keys '( ( ( ?a 3 calcFunc-apart )
+				( ?b 3 calcFunc-subst )
+				( ?c 2 calcFunc-collect )
+				( ?d 2 calcFunc-deriv )
+				( ?e 1 calcFunc-esimplify )
+				( ?f 2 calcFunc-factor )
+				( ?g 2 calcFunc-pgcd )
+				( ?i 2 calcFunc-integ )
+				( ?m 2 calcFunc-match )
+				( ?n 1 calcFunc-nrat )
+				( ?r 2 calcFunc-rewrite )
+				( ?s 1 calcFunc-simplify )
+				( ?t 3 calcFunc-taylor )
+				( ?x 1 calcFunc-expand )
+				( ?M 2 calcFunc-mapeq )
+				( ?N 3 calcFunc-minimize )
+				( ?P 2 calcFunc-roots )
+				( ?R 3 calcFunc-root )
+				( ?S 2 calcFunc-solve )
+				( ?T 4 calcFunc-table )
+				( ?X 3 calcFunc-maximize )
+				( ?= 2 calcFunc-eq )
+				( ?\# 2 calcFunc-neq )
+				( ?< 2 calcFunc-lt )
+				( ?> 2 calcFunc-gt )
+				( ?\[ 2 calcFunc-leq )
+				( ?\] 2 calcFunc-geq )
+				( ?{ 2 calcFunc-in )
+				( ?! 1 calcFunc-lnot )
+				( ?& 2 calcFunc-land )
+				( ?\| 2 calcFunc-lor )
+				( ?: 3 calcFunc-if )
+				( ?. 2 calcFunc-rmeq )
+				( ?+ 4 calcFunc-sum )
+				( ?- 4 calcFunc-asum )
+				( ?* 4 calcFunc-prod )
+				( ?_ 2 calcFunc-subscr )
+				( ?\\ 2 calcFunc-pdiv )
+				( ?% 2 calcFunc-prem )
+				( ?/ 2 calcFunc-pdivrem ) )
+			      ( ( ?m 2 calcFunc-matchnot )
+				( ?M 2 calcFunc-mapeqr )
+				( ?S 2 calcFunc-finv ) )
+			      ( ( ?d 2 calcFunc-tderiv )
+				( ?f 2 calcFunc-factors )
+				( ?M 2 calcFunc-mapeqp )
+				( ?N 3 calcFunc-wminimize )
+				( ?R 3 calcFunc-wroot )
+				( ?S 2 calcFunc-fsolve )
+				( ?X 3 calcFunc-wmaximize )
+				( ?/ 2 calcFunc-pdivide ) )
+			      ( ( ?S 2 calcFunc-ffinv ) )
+))
+(defconst calc-b-oper-keys '( ( ( ?a 2 calcFunc-and )
+				( ?o 2 calcFunc-or )
+				( ?x 2 calcFunc-xor )
+				( ?d 2 calcFunc-diff )
+				( ?n 1 calcFunc-not )
+				( ?c 1 calcFunc-clip )
+				( ?l 2 calcFunc-lsh )
+				( ?r 2 calcFunc-rsh )
+				( ?L 2 calcFunc-ash )
+				( ?R 2 calcFunc-rash )
+				( ?t 2 calcFunc-rot )
+				( ?p 1 calcFunc-vpack )
+				( ?u 1 calcFunc-vunpack )
+				( ?D 4 calcFunc-ddb )
+				( ?F 3 calcFunc-fv )
+				( ?I 1 calcFunc-irr )
+				( ?M 3 calcFunc-pmt )
+				( ?N 2 calcFunc-npv )
+				( ?P 3 calcFunc-pv )
+				( ?S 3 calcFunc-sln )
+				( ?T 3 calcFunc-rate )
+				( ?Y 4 calcFunc-syd )
+				( ?\# 3 calcFunc-nper )
+				( ?\% 2 calcFunc-relch ) )
+			      ( ( ?F 3 calcFunc-fvb )
+				( ?I 1 calcFunc-irrb )
+				( ?M 3 calcFunc-pmtb )
+				( ?N 2 calcFunc-npvb )
+				( ?P 3 calcFunc-pvb )
+				( ?T 3 calcFunc-rateb )
+				( ?\# 3 calcFunc-nperb ) )
+			      ( ( ?F 3 calcFunc-fvl )
+				( ?M 3 calcFunc-pmtl )
+				( ?P 3 calcFunc-pvl )
+				( ?T 3 calcFunc-ratel )
+				( ?\# 3 calcFunc-nperl ) )
+))
+(defconst calc-c-oper-keys '( ( ( ?d 1 calcFunc-deg )
+				( ?r 1 calcFunc-rad )
+				( ?h 1 calcFunc-hms )
+				( ?f 1 calcFunc-float )
+				( ?F 1 calcFunc-frac ) )
+))
+(defconst calc-f-oper-keys '( ( ( ?b 2 calcFunc-beta )
+				( ?e 1 calcFunc-erf )
+				( ?g 1 calcFunc-gamma )
+				( ?h 2 calcFunc-hypot )
+				( ?i 1 calcFunc-im )
+				( ?j 2 calcFunc-besJ )
+				( ?n 2 calcFunc-min )
+				( ?r 1 calcFunc-re )
+				( ?s 1 calcFunc-sign )
+				( ?x 2 calcFunc-max )
+				( ?y 2 calcFunc-besY )
+				( ?A 1 calcFunc-abssqr )
+				( ?B 3 calcFunc-betaI )
+				( ?E 1 calcFunc-expm1 )
+				( ?G 2 calcFunc-gammaP )
+				( ?I 2 calcFunc-ilog )
+				( ?L 1 calcFunc-lnp1 )
+				( ?M 1 calcFunc-mant )
+				( ?Q 1 calcFunc-isqrt )
+				( ?S 1 calcFunc-scf )
+				( ?T 2 calcFunc-arctan2 )
+				( ?X 1 calcFunc-xpon )
+				( ?\[ 2 calcFunc-decr )
+				( ?\] 2 calcFunc-incr ) )
+			      ( ( ?e 1 calcFunc-erfc )
+				( ?E 1 calcFunc-lnp1 )
+				( ?G 2 calcFunc-gammaQ )
+				( ?L 1 calcFunc-expm1 ) )
+			      ( ( ?B 3 calcFunc-betaB )
+				( ?G 2 calcFunc-gammag) )
+			      ( ( ?G 2 calcFunc-gammaG ) )
+))
+(defconst calc-k-oper-keys '( ( ( ?b 1 calcFunc-bern )
+				( ?c 2 calcFunc-choose )
+				( ?d 1 calcFunc-dfact )
+				( ?e 1 calcFunc-euler )
+				( ?f 1 calcFunc-prfac )
+				( ?g 2 calcFunc-gcd )
+				( ?h 2 calcFunc-shuffle )
+				( ?l 2 calcFunc-lcm )
+				( ?m 1 calcFunc-moebius )
+				( ?n 1 calcFunc-nextprime )
+				( ?r 1 calcFunc-random )
+				( ?s 2 calcFunc-stir1 )
+				( ?t 1 calcFunc-totient )
+				( ?B 3 calcFunc-utpb )
+				( ?C 2 calcFunc-utpc )
+				( ?F 3 calcFunc-utpf )
+				( ?N 3 calcFunc-utpn )
+				( ?P 2 calcFunc-utpp )
+				( ?T 2 calcFunc-utpt ) )
+			      ( ( ?n 1 calcFunc-prevprime )
+				( ?B 3 calcFunc-ltpb )
+				( ?C 2 calcFunc-ltpc )
+				( ?F 3 calcFunc-ltpf )
+				( ?N 3 calcFunc-ltpn )
+				( ?P 2 calcFunc-ltpp )
+				( ?T 2 calcFunc-ltpt ) )
+			      ( ( ?b 2 calcFunc-bern )
+				( ?c 2 calcFunc-perm )
+				( ?e 2 calcFunc-euler )
+				( ?s 2 calcFunc-stir2 ) )
+))
+(defconst calc-s-oper-keys '( ( ( ?: 2 calcFunc-assign )
+				( ?= 1 calcFunc-evalto ) )
+))
+(defconst calc-t-oper-keys '( ( ( ?C 3 calcFunc-tzconv )
+				( ?D 1 calcFunc-date )
+				( ?I 2 calcFunc-incmonth )
+				( ?J 1 calcFunc-julian )
+				( ?M 1 calcFunc-newmonth )
+				( ?W 1 calcFunc-newweek )
+				( ?U 1 calcFunc-unixtime )
+				( ?Y 1 calcFunc-newyear ) )
+))
+(defconst calc-u-oper-keys '( ( ( ?C 2 calcFunc-vcov )
+				( ?G 1 calcFunc-vgmean )
+				( ?M 1 calcFunc-vmean )
+				( ?N 1 calcFunc-vmin )
+				( ?S 1 calcFunc-vsdev )
+				( ?X 1 calcFunc-vmax ) )
+			      ( ( ?C 2 calcFunc-vpcov )
+				( ?M 1 calcFunc-vmeane )
+				( ?S 1 calcFunc-vpsdev ) )
+			      ( ( ?C 2 calcFunc-vcorr )
+				( ?G 1 calcFunc-agmean )
+				( ?M 1 calcFunc-vmedian )
+				( ?S 1 calcFunc-vvar ) )
+			      ( ( ?M 1 calcFunc-vhmean )
+				( ?S 1 calcFunc-vpvar ) )
+))
+(defconst calc-v-oper-keys '( ( ( ?a 2 calcFunc-arrange )
+				( ?b 2 calcFunc-cvec )
+				( ?c 2 calcFunc-mcol )
+				( ?d 2 calcFunc-diag )
+				( ?e 2 calcFunc-vexp )
+				( ?f 2 calcFunc-find )
+				( ?h 1 calcFunc-head )
+				( ?k 2 calcFunc-cons )
+				( ?l 1 calcFunc-vlen )
+				( ?m 2 calcFunc-vmask )
+				( ?n 1 calcFunc-rnorm )
+				( ?p 2 calcFunc-pack )
+				( ?r 2 calcFunc-mrow )
+				( ?s 3 calcFunc-subvec )
+				( ?t 1 calcFunc-trn )
+				( ?u 1 calcFunc-unpack )
+				( ?v 1 calcFunc-rev )
+				( ?x 1 calcFunc-index )
+				( ?A 1 calcFunc-apply )
+				( ?C 1 calcFunc-cross )
+				( ?D 1 calcFunc-det )
+				( ?E 1 calcFunc-venum )
+				( ?F 1 calcFunc-vfloor )
+				( ?G 1 calcFunc-grade )
+				( ?H 2 calcFunc-histogram )
+				( ?I 2 calcFunc-inner )
+				( ?L 1 calcFunc-lud )
+				( ?M 0 calcFunc-map )
+				( ?N 1 calcFunc-cnorm )
+				( ?O 2 calcFunc-outer )
+				( ?R 1 calcFunc-reduce )
+				( ?S 1 calcFunc-sort )
+				( ?T 1 calcFunc-tr )
+				( ?U 1 calcFunc-accum )
+				( ?V 2 calcFunc-vunion )
+				( ?X 2 calcFunc-vxor )
+				( ?- 2 calcFunc-vdiff )
+				( ?^ 2 calcFunc-vint )
+				( ?~ 1 calcFunc-vcompl )
+				( ?# 1 calcFunc-vcard )
+				( ?: 1 calcFunc-vspan )
+				( ?+ 1 calcFunc-rdup ) )
+			      ( ( ?h 1 calcFunc-tail )
+				( ?s 3 calcFunc-rsubvec )
+				( ?G 1 calcFunc-rgrade )
+				( ?R 1 calcFunc-rreduce )
+				( ?S 1 calcFunc-rsort )
+				( ?U 1 calcFunc-raccum ) )
+			      ( ( ?e 3 calcFunc-vexp )
+				( ?h 1 calcFunc-rhead )
+				( ?k 2 calcFunc-rcons )
+				( ?H 3 calcFunc-histogram )
+				( ?R 2 calcFunc-nest )
+				( ?U 2 calcFunc-anest ) )
+			      ( ( ?h 1 calcFunc-rtail )
+				( ?R 1 calcFunc-fixp )
+				( ?U 1 calcFunc-afixp ) )
+))
+
+
+;;; Convert a variable name (as a formula) into a like-looking function name.
+(defun math-var-to-calcFunc (f)
+  (if (eq (car-safe f) 'var)
+      (if (fboundp (nth 2 f))
+	  (nth 2 f)
+	(intern (concat "calcFunc-" (symbol-name (nth 1 f)))))
+    (if (memq (car-safe f) '(lambda calcFunc-lambda))
+	f
+      (math-reject-arg f "*Expected a function name")))
+)
+
+;;; Convert a function name into a like-looking variable name formula.
+(defun math-calcFunc-to-var (f)
+  (if (symbolp f)
+      (let* ((func (or (cdr (assq f '( ( + . calcFunc-add )
+				       ( - . calcFunc-sub )
+				       ( * . calcFunc-mul )
+				       ( / . calcFunc-div )
+				       ( ^ . calcFunc-pow )
+				       ( % . calcFunc-mod )
+				       ( neg . calcFunc-neg )
+				       ( | . calcFunc-vconcat ) )))
+		       f))
+	     (base (if (string-match "\\`calcFunc-\\(.+\\)\\'"
+				     (symbol-name func))
+		       (math-match-substring (symbol-name func) 1)
+		     (symbol-name func))))
+	(list 'var
+	      (intern base)
+	      (intern (concat "var-" base))))
+    f)
+)
+
+;;; Expand a function call using "lambda" notation.
+(defun math-build-call (f args)
+  (if (eq (car-safe f) 'calcFunc-lambda)
+      (if (= (length args) (- (length f) 2))
+	  (math-multi-subst (nth (1- (length f)) f) (cdr f) args)
+	(calc-record-why "*Wrong number of arguments" f)
+	(cons 'calcFunc-call (cons (math-calcFunc-to-var f) args)))
+    (if (and (eq f 'calcFunc-neg)
+	     (= (length args) 1))
+	(list 'neg (car args))
+      (let ((func (assq f '( ( calcFunc-add . + )
+			     ( calcFunc-sub . - )
+			     ( calcFunc-mul . * )
+			     ( calcFunc-div . / )
+			     ( calcFunc-pow . ^ )
+			     ( calcFunc-mod . % )
+			     ( calcFunc-vconcat . | ) ))))
+	(if (and func (= (length args) 2))
+	    (cons (cdr func) args)
+	  (cons f args)))))
+)
+
+;;; Do substitutions in parallel to avoid crosstalk.
+(defun math-multi-subst (expr olds news)
+  (let ((args nil)
+	temp)
+    (while (and olds news)
+      (setq args (cons (cons (car olds) (car news)) args)
+	    olds (cdr olds)
+	    news (cdr news)))
+    (math-multi-subst-rec expr))
+)
+
+(defun math-multi-subst-rec (expr)
+  (cond ((setq temp (assoc expr args)) (cdr temp))
+	((Math-primp expr) expr)
+	((and (eq (car expr) 'calcFunc-lambda) (> (length expr) 2))
+	 (let ((new (list (car expr)))
+	       (args args))
+	   (while (cdr (setq expr (cdr expr)))
+	     (setq new (cons (car expr) new))
+	     (if (assoc (car expr) args)
+		 (setq args (cons (cons (car expr) (car expr)) args))))
+	   (nreverse (cons (math-multi-subst-rec (car expr)) new))))
+	(t
+	 (cons (car expr)
+	       (mapcar 'math-multi-subst-rec (cdr expr)))))
+)
+
+(defun calcFunc-call (f &rest args)
+  (setq args (math-build-call (math-var-to-calcFunc f) args))
+  (if (eq (car-safe args) 'calcFunc-call)
+      args
+    (math-normalize args))
+)
+
+(defun calcFunc-apply (f args)
+  (or (Math-vectorp args)
+      (math-reject-arg args 'vectorp))
+  (apply 'calcFunc-call (cons f (cdr args)))
+)
+
+
+
+
+;;; Map a function over a vector symbolically. [Public]
+(defun math-symb-map (f mode args)
+  (let* ((func (math-var-to-calcFunc f))
+	 (nargs (length args))
+	 (ptrs (vconcat args))
+	 (vflags (make-vector nargs nil))
+	 (heads '(vec))
+	 (head nil)
+	 (vec nil)
+	 (i -1)
+	 (math-working-step 0)
+	 (math-working-step-2 nil)
+	 len cols obj expr)
+    (if (eq mode 'eqn)
+	(setq mode 'elems
+	      heads '(calcFunc-eq calcFunc-neq calcFunc-lt calcFunc-gt
+				  calcFunc-leq calcFunc-geq))
+      (while (and (< (setq i (1+ i)) nargs)
+		  (not (math-matrixp (aref ptrs i)))))
+      (if (< i nargs)
+	  (if (eq mode 'elems)
+	      (setq func (list 'lambda '(&rest x)
+			       (list 'math-symb-map
+				     (list 'quote f) '(quote elems) 'x))
+		    mode 'rows)
+	    (if (eq mode 'cols)
+		(while (< i nargs)
+		  (if (math-matrixp (aref ptrs i))
+		      (aset ptrs i (math-transpose (aref ptrs i))))
+		  (setq i (1+ i)))))
+	(setq mode 'elems))
+      (setq i -1))
+    (while (< (setq i (1+ i)) nargs)
+      (setq obj (aref ptrs i))
+      (if (and (memq (car-safe obj) heads)
+	       (or (eq mode 'elems)
+		   (math-matrixp obj)))
+	  (progn
+	    (aset vflags i t)
+	    (if head
+		(if (cdr heads)
+		    (setq head (nth
+				(aref (aref [ [0 1 2 3 4 5]
+					      [1 1 2 3 2 3]
+					      [2 2 2 1 2 1]
+					      [3 3 1 3 1 3]
+					      [4 2 2 1 4 1]
+					      [5 3 1 3 1 5] ]
+					    (- 6 (length (memq head heads))))
+				      (- 6 (length (memq (car obj) heads))))
+				heads)))
+	      (setq head (car obj)))
+	    (if len
+		(or (= (length obj) len)
+		    (math-dimension-error))
+	      (setq len (length obj))))))
+    (or len
+	(if (= nargs 1)
+	    (math-reject-arg (aref ptrs 0) 'vectorp)
+	  (math-reject-arg nil "At least one argument must be a vector")))
+    (setq math-working-step-2 (1- len))
+    (while (> (setq len (1- len)) 0)
+      (setq expr nil
+	    i -1)
+      (while (< (setq i (1+ i)) nargs)
+	(if (aref vflags i)
+	    (progn
+	      (aset ptrs i (cdr (aref ptrs i)))
+	      (setq expr (nconc expr (list (car (aref ptrs i))))))
+	  (setq expr (nconc expr (list (aref ptrs i))))))
+      (setq math-working-step (1+ math-working-step)
+	    vec (cons (math-normalize (math-build-call func expr)) vec)))
+    (setq vec (cons head (nreverse vec)))
+    (if (and (eq mode 'cols) (math-matrixp vec))
+	(math-transpose vec)
+      vec))
+)
+
+(defun calcFunc-map (func &rest args)
+  (math-symb-map func 'elems args)
+)
+
+(defun calcFunc-mapr (func &rest args)
+  (math-symb-map func 'rows args)
+)
+
+(defun calcFunc-mapc (func &rest args)
+  (math-symb-map func 'cols args)
+)
+
+(defun calcFunc-mapa (func arg)
+  (if (math-matrixp arg)
+      (math-symb-map func 'elems (cdr (math-transpose arg)))
+    (math-symb-map func 'elems arg))
+)
+
+(defun calcFunc-mapd (func arg)
+  (if (math-matrixp arg)
+      (math-symb-map func 'elems (cdr arg))
+    (math-symb-map func 'elems arg))
+)
+
+(defun calcFunc-mapeq (func &rest args)
+  (if (and (or (equal func '(var mul var-mul))
+	       (equal func '(var div var-div)))
+	   (= (length args) 2))
+      (if (math-negp (car args))
+	  (let ((func (nth 1 (assq (car-safe (nth 1 args))
+				   calc-tweak-eqn-table))))
+	    (and func (setq args (list (car args)
+				       (cons func (cdr (nth 1 args)))))))
+	(if (math-negp (nth 1 args))
+	    (let ((func (nth 1 (assq (car-safe (car args))
+				     calc-tweak-eqn-table))))
+	      (and func (setq args (list (cons func (cdr (car args)))
+					 (nth 1 args))))))))
+  (if (or (and (equal func '(var div var-div))
+	       (assq (car-safe (nth 1 args)) calc-tweak-eqn-table))
+	  (equal func '(var neg var-neg))
+	  (equal func '(var inv var-inv)))
+      (apply 'calcFunc-mapeqr func args)
+    (apply 'calcFunc-mapeqp func args))
+)
+
+(defun calcFunc-mapeqr (func &rest args)
+  (setq args (mapcar (function (lambda (x)
+				 (let ((func (assq (car-safe x)
+						   calc-tweak-eqn-table)))
+				   (if func
+				       (cons (nth 1 func) (cdr x))
+				     x))))
+		     args))
+  (apply 'calcFunc-mapeqp func args)
+)
+
+(defun calcFunc-mapeqp (func &rest args)
+  (if (or (and (memq (car-safe (car args)) '(calcFunc-lt calcFunc-leq))
+	       (memq (car-safe (nth 1 args)) '(calcFunc-gt calcFunc-geq)))
+	  (and (memq (car-safe (car args)) '(calcFunc-gt calcFunc-geq))
+	       (memq (car-safe (nth 1 args)) '(calcFunc-lt calcFunc-leq))))
+      (setq args (cons (car args)
+		       (cons (list (nth 1 (assq (car (nth 1 args))
+						calc-tweak-eqn-table))
+				   (nth 2 (nth 1 args))
+				   (nth 1 (nth 1 args)))
+			     (cdr (cdr args))))))
+  (math-symb-map func 'eqn args)
+)
+
+
+
+;;; Reduce a function over a vector symbolically. [Public]
+(defun calcFunc-reduce (func vec)
+  (if (math-matrixp vec)
+      (let (expr row)
+	(setq func (math-var-to-calcFunc func))
+	(while (setq vec (cdr vec))
+	  (setq row (car vec))
+	  (while (setq row (cdr row))
+	    (setq expr (if expr
+			   (if (Math-numberp expr)
+			       (math-normalize
+				(math-build-call func (list expr (car row))))
+			     (math-build-call func (list expr (car row))))
+			 (car row)))))
+	(math-normalize expr))
+    (calcFunc-reducer func vec))
+)
+
+(defun calcFunc-rreduce (func vec)
+  (if (math-matrixp vec)
+      (let (expr row)
+	(setq func (math-var-to-calcFunc func)
+	      vec (reverse (cdr vec)))
+	(while vec
+	  (setq row (reverse (cdr (car vec))))
+	  (while row
+	    (setq expr (if expr
+			   (math-build-call func (list (car row) expr))
+			 (car row))
+		  row (cdr row)))
+	  (setq vec (cdr vec)))
+	(math-normalize expr))
+    (calcFunc-rreducer func vec))
+)
+
+(defun calcFunc-reducer (func vec)
+  (setq func (math-var-to-calcFunc func))
+  (or (math-vectorp vec)
+      (math-reject-arg vec 'vectorp))
+  (let ((expr (car (setq vec (cdr vec)))))
+    (if expr
+	(progn
+	  (condition-case err
+	      (and (symbolp func)
+		   (let ((lfunc (or (cdr (assq func
+					       '( (calcFunc-add . math-add)
+						  (calcFunc-sub . math-sub)
+						  (calcFunc-mul . math-mul)
+						  (calcFunc-div . math-div)
+						  (calcFunc-pow . math-pow)
+						  (calcFunc-mod . math-mod)
+						  (calcFunc-vconcat .
+						   math-concat) )))
+				    lfunc)))
+		     (while (cdr vec)
+		       (setq expr (funcall lfunc expr (nth 1 vec))
+			     vec (cdr vec)))))
+	    (error nil))
+	  (while (setq vec (cdr vec))
+	    (setq expr (math-build-call func (list expr (car vec)))))
+	  (math-normalize expr))
+      (or (math-identity-value func)
+	  (math-reject-arg vec "*Vector is empty"))))
+)
+
+(defun math-identity-value (func)
+  (cdr (assq func '( (calcFunc-add . 0) (calcFunc-sub . 0)
+		     (calcFunc-mul . 1) (calcFunc-div . 1)
+		     (calcFunc-idiv . 1) (calcFunc-fdiv . 1)
+		     (calcFunc-min . (var inf var-inf))
+		     (calcFunc-max . (neg (var inf var-inf)))
+		     (calcFunc-vconcat . (vec))
+		     (calcFunc-append . (vec)) )))
+)
+
+(defun calcFunc-rreducer (func vec)
+  (setq func (math-var-to-calcFunc func))
+  (or (math-vectorp vec)
+      (math-reject-arg vec 'vectorp))
+  (if (eq func 'calcFunc-sub)   ; do this in a way that looks nicer
+      (let ((expr (car (setq vec (cdr vec)))))
+	(if expr
+	    (progn
+	      (while (setq vec (cdr vec))
+		(setq expr (math-build-call func (list expr (car vec)))
+		      func (if (eq func 'calcFunc-sub)
+			       'calcFunc-add 'calcFunc-sub)))
+	      (math-normalize expr))
+	  0))
+    (let ((expr (car (setq vec (reverse (cdr vec))))))
+      (if expr
+	  (progn
+	    (while (setq vec (cdr vec))
+	      (setq expr (math-build-call func (list (car vec) expr))))
+	    (math-normalize expr))
+	(or (math-identity-value func)
+	    (math-reject-arg vec "*Vector is empty")))))
+)
+
+(defun calcFunc-reducec (func vec)
+  (if (math-matrixp vec)
+      (calcFunc-reducer func (math-transpose vec))
+    (calcFunc-reducer func vec))
+)
+
+(defun calcFunc-rreducec (func vec)
+  (if (math-matrixp vec)
+      (calcFunc-rreducer func (math-transpose vec))
+    (calcFunc-rreducer func vec))
+)
+
+(defun calcFunc-reducea (func vec)
+  (if (math-matrixp vec)
+      (cons 'vec
+	    (mapcar (function (lambda (x) (calcFunc-reducer func x)))
+		    (cdr vec)))
+    (calcFunc-reducer func vec))
+)
+
+(defun calcFunc-rreducea (func vec)
+  (if (math-matrixp vec)
+      (cons 'vec
+	    (mapcar (function (lambda (x) (calcFunc-rreducer func x)))
+		    (cdr vec)))
+    (calcFunc-rreducer func vec))
+)
+
+(defun calcFunc-reduced (func vec)
+  (if (math-matrixp vec)
+      (cons 'vec
+	    (mapcar (function (lambda (x) (calcFunc-reducer func x)))
+		    (cdr (math-transpose vec))))
+    (calcFunc-reducer func vec))
+)
+
+(defun calcFunc-rreduced (func vec)
+  (if (math-matrixp vec)
+      (cons 'vec
+	    (mapcar (function (lambda (x) (calcFunc-rreducer func x)))
+		    (cdr (math-transpose vec))))
+    (calcFunc-rreducer func vec))
+)
+
+(defun calcFunc-accum (func vec)
+  (setq func (math-var-to-calcFunc func))
+  (or (math-vectorp vec)
+      (math-reject-arg vec 'vectorp))
+  (let* ((expr (car (setq vec (cdr vec))))
+	 (res (list 'vec expr)))
+    (or expr
+	(math-reject-arg vec "*Vector is empty"))
+    (while (setq vec (cdr vec))
+      (setq expr (math-build-call func (list expr (car vec)))
+	    res (nconc res (list expr))))
+    (math-normalize res))
+)
+
+(defun calcFunc-raccum (func vec)
+  (setq func (math-var-to-calcFunc func))
+  (or (math-vectorp vec)
+      (math-reject-arg vec 'vectorp))
+  (let* ((expr (car (setq vec (reverse (cdr vec)))))
+	 (res (list expr)))
+    (or expr
+	(math-reject-arg vec "*Vector is empty"))
+    (while (setq vec (cdr vec))
+      (setq expr (math-build-call func (list (car vec) expr))
+	    res (cons (list expr) res)))
+    (math-normalize (cons 'vec res)))
+)
+
+
+(defun math-nest-calls (func base iters accum tol)
+  (or (symbolp tol)
+      (if (math-realp tol)
+	  (or (math-numberp base) (math-reject-arg base 'numberp))
+	(math-reject-arg tol 'realp)))
+  (setq func (math-var-to-calcFunc func))
+  (or (null iters)
+      (if (equal iters '(var inf var-inf))
+	  (setq iters nil)
+	(progn
+	  (if (math-messy-integerp iters)
+	      (setq iters (math-trunc iters)))
+	  (or (integerp iters) (math-reject-arg iters 'fixnump))
+	  (or (not tol) (natnump iters) (math-reject-arg iters 'fixnatnump))
+	  (if (< iters 0)
+	      (let* ((dummy '(var DummyArg var-DummyArg))
+		     (dummy2 '(var DummyArg2 var-DummyArg2))
+		     (finv (math-solve-for (math-build-call func (list dummy2))
+					   dummy dummy2 nil)))
+		(or finv (math-reject-arg nil "*Unable to find an inverse"))
+		(if (and (= (length finv) 2)
+			 (equal (nth 1 finv) dummy))
+		    (setq func (car finv))
+		  (setq func (list 'calcFunc-lambda dummy finv)))
+		(setq iters (- iters)))))))
+  (math-with-extra-prec 1
+    (let ((value base)
+	  (ovalue nil)
+	  (avalues (list base))
+	  (math-working-step 0)
+	  (math-working-step-2 iters))
+      (while (and (or (null iters)
+		      (>= (setq iters (1- iters)) 0))
+		  (or (null tol)
+		      (null ovalue)
+		      (if (eq tol t)
+			  (not (if (and (Math-numberp value)
+					(Math-numberp ovalue))
+				   (math-nearly-equal value ovalue)
+				 (Math-equal value ovalue)))
+			(if (math-numberp value)
+			    (Math-lessp tol (math-abs (math-sub value ovalue)))
+			  (math-reject-arg value 'numberp)))))
+	(setq ovalue value
+	      math-working-step (1+ math-working-step)
+	      value (math-normalize (math-build-call func (list value))))
+	(if accum
+	    (setq avalues (cons value avalues))))
+      (if accum
+	  (cons 'vec (nreverse avalues))
+	value)))
+)
+
+(defun calcFunc-nest (func base iters)
+  (math-nest-calls func base iters nil nil)
+)
+
+(defun calcFunc-anest (func base iters)
+  (math-nest-calls func base iters t nil)
+)
+
+(defun calcFunc-fixp (func base &optional iters tol)
+  (math-nest-calls func base iters nil (or tol t))
+)
+
+(defun calcFunc-afixp (func base &optional iters tol)
+  (math-nest-calls func base iters t (or tol t))
+)
+
+
+(defun calcFunc-outer (func a b)
+  (or (math-vectorp a) (math-reject-arg a 'vectorp))
+  (or (math-vectorp b) (math-reject-arg b 'vectorp))
+  (setq func (math-var-to-calcFunc func))
+  (let ((mat nil))
+    (while (setq a (cdr a))
+      (setq mat (cons (cons 'vec
+			    (mapcar (function (lambda (x)
+						(math-build-call func
+								 (list (car a)
+								       x))))
+				    (cdr b)))
+		      mat)))
+    (math-normalize (cons 'vec (nreverse mat))))
+)
+
+
+(defun calcFunc-inner (mul-func add-func a b)
+  (or (math-vectorp a) (math-reject-arg a 'vectorp))
+  (or (math-vectorp b) (math-reject-arg b 'vectorp))
+  (if (math-matrixp a)
+      (if (math-matrixp b)
+	  (if (= (length (nth 1 a)) (length b))
+	      (math-inner-mats a b)
+	    (math-dimension-error))
+	(if (= (length (nth 1 a)) 2)
+	    (if (= (length a) (length b))
+		(math-inner-mats a (list 'vec b))
+	      (math-dimension-error))
+	  (if (= (length (nth 1 a)) (length b))
+	      (math-mat-col (math-inner-mats a (math-col-matrix b))
+			    1)
+	    (math-dimension-error))))
+    (if (math-matrixp b)
+	(nth 1 (math-inner-mats (list 'vec a) b))
+      (calcFunc-reduce add-func (calcFunc-map mul-func a b))))
+)
+
+(defun math-inner-mats (a b)
+  (let ((mat nil)
+	(cols (length (nth 1 b)))
+	row col ap bp accum)
+    (while (setq a (cdr a))
+      (setq col cols
+	    row nil)
+      (while (> (setq col (1- col)) 0)
+	(setq row (cons (calcFunc-reduce add-func
+					 (calcFunc-map mul-func
+						       (car a)
+						       (math-mat-col b col)))
+			row)))
+      (setq mat (cons (cons 'vec row) mat)))
+    (cons 'vec (nreverse mat)))
+)
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/calc-math.el	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,1783 @@
+;; Calculator for GNU Emacs, part II [calc-math.el]
+;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+;; Written by Dave Gillespie, daveg@synaptics.com.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY.  No author or distributor
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing.  Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License.   A copy of this license is
+;; supposed to have been given to you along with GNU Emacs so you
+;; can know your rights and responsibilities.  It should be in a
+;; file named COPYING.  Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+
+
+
+;; This file is autoloaded from calc-ext.el.
+(require 'calc-ext)
+
+(require 'calc-macs)
+
+(defun calc-Need-calc-math () nil)
+
+
+(defun calc-sqrt (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (if (calc-is-inverse)
+       (calc-unary-op "^2" 'calcFunc-sqr arg)
+     (calc-unary-op "sqrt" 'calcFunc-sqrt arg)))
+)
+
+(defun calc-isqrt (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (if (calc-is-inverse)
+       (calc-unary-op "^2" 'calcFunc-sqr arg)
+     (calc-unary-op "isqt" 'calcFunc-isqrt arg)))
+)
+
+
+(defun calc-hypot (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-binary-op "hypt" 'calcFunc-hypot arg))
+)
+
+(defun calc-ln (arg)
+  (interactive "P")
+  (calc-invert-func)
+  (calc-exp arg)
+)
+
+(defun calc-log10 (arg)
+  (interactive "P")
+  (calc-hyperbolic-func)
+  (calc-ln arg)
+)
+
+(defun calc-log (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (if (calc-is-inverse)
+       (calc-binary-op "alog" 'calcFunc-alog arg)
+     (calc-binary-op "log" 'calcFunc-log arg)))
+)
+
+(defun calc-ilog (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (if (calc-is-inverse)
+       (calc-binary-op "alog" 'calcFunc-alog arg)
+     (calc-binary-op "ilog" 'calcFunc-ilog arg)))
+)
+
+(defun calc-lnp1 (arg)
+  (interactive "P")
+  (calc-invert-func)
+  (calc-expm1 arg)
+)
+
+(defun calc-exp (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (if (calc-is-hyperbolic)
+       (if (calc-is-inverse)
+	   (calc-unary-op "lg10" 'calcFunc-log10 arg)
+	 (calc-unary-op "10^" 'calcFunc-exp10 arg))
+     (if (calc-is-inverse)
+	 (calc-unary-op "ln" 'calcFunc-ln arg)
+       (calc-unary-op "exp" 'calcFunc-exp arg))))
+)
+
+(defun calc-expm1 (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (if (calc-is-inverse)
+       (calc-unary-op "ln+1" 'calcFunc-lnp1 arg)
+     (calc-unary-op "ex-1" 'calcFunc-expm1 arg)))
+)
+
+(defun calc-pi ()
+  (interactive)
+  (calc-slow-wrapper
+   (if (calc-is-inverse)
+       (if (calc-is-hyperbolic)
+	   (if calc-symbolic-mode
+	       (calc-pop-push-record 0 "phi" '(var phi var-phi))
+	     (calc-pop-push-record 0 "phi" (math-phi)))
+	 (if calc-symbolic-mode
+	     (calc-pop-push-record 0 "gmma" '(var gamma var-gamma))
+	   (calc-pop-push-record 0 "gmma" (math-gamma-const))))
+     (if (calc-is-hyperbolic)
+	 (if calc-symbolic-mode
+	     (calc-pop-push-record 0 "e" '(var e var-e))
+	   (calc-pop-push-record 0 "e" (math-e)))
+       (if calc-symbolic-mode
+	   (calc-pop-push-record 0 "pi" '(var pi var-pi))
+	 (calc-pop-push-record 0 "pi" (math-pi))))))
+)
+
+(defun calc-sin (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (if (calc-is-hyperbolic)
+       (if (calc-is-inverse)
+	   (calc-unary-op "asnh" 'calcFunc-arcsinh arg)
+	 (calc-unary-op "sinh" 'calcFunc-sinh arg))
+     (if (calc-is-inverse)
+	 (calc-unary-op "asin" 'calcFunc-arcsin arg)
+       (calc-unary-op "sin" 'calcFunc-sin arg))))
+)
+
+(defun calc-arcsin (arg)
+  (interactive "P")
+  (calc-invert-func)
+  (calc-sin arg)
+)
+
+(defun calc-sinh (arg)
+  (interactive "P")
+  (calc-hyperbolic-func)
+  (calc-sin arg)
+)
+
+(defun calc-arcsinh (arg)
+  (interactive "P")
+  (calc-invert-func)
+  (calc-hyperbolic-func)
+  (calc-sin arg)
+)
+
+(defun calc-cos (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (if (calc-is-hyperbolic)
+       (if (calc-is-inverse)
+	   (calc-unary-op "acsh" 'calcFunc-arccosh arg)
+	 (calc-unary-op "cosh" 'calcFunc-cosh arg))
+     (if (calc-is-inverse)
+	 (calc-unary-op "acos" 'calcFunc-arccos arg)
+       (calc-unary-op "cos" 'calcFunc-cos arg))))
+)
+
+(defun calc-arccos (arg)
+  (interactive "P")
+  (calc-invert-func)
+  (calc-cos arg)
+)
+
+(defun calc-cosh (arg)
+  (interactive "P")
+  (calc-hyperbolic-func)
+  (calc-cos arg)
+)
+
+(defun calc-arccosh (arg)
+  (interactive "P")
+  (calc-invert-func)
+  (calc-hyperbolic-func)
+  (calc-cos arg)
+)
+
+(defun calc-sincos ()
+  (interactive)
+  (calc-slow-wrapper
+   (if (calc-is-inverse)
+       (calc-enter-result 1 "asnc" (list 'calcFunc-arcsincos (calc-top-n 1)))
+     (calc-enter-result 1 "sncs" (list 'calcFunc-sincos (calc-top-n 1)))))
+)
+
+(defun calc-tan (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (if (calc-is-hyperbolic)
+       (if (calc-is-inverse)
+	   (calc-unary-op "atnh" 'calcFunc-arctanh arg)
+	 (calc-unary-op "tanh" 'calcFunc-tanh arg))
+     (if (calc-is-inverse)
+	 (calc-unary-op "atan" 'calcFunc-arctan arg)
+       (calc-unary-op "tan" 'calcFunc-tan arg))))
+)
+
+(defun calc-arctan (arg)
+  (interactive "P")
+  (calc-invert-func)
+  (calc-tan arg)
+)
+
+(defun calc-tanh (arg)
+  (interactive "P")
+  (calc-hyperbolic-func)
+  (calc-tan arg)
+)
+
+(defun calc-arctanh (arg)
+  (interactive "P")
+  (calc-invert-func)
+  (calc-hyperbolic-func)
+  (calc-tan arg)
+)
+
+(defun calc-arctan2 ()
+  (interactive)
+  (calc-slow-wrapper
+   (calc-enter-result 2 "atn2" (cons 'calcFunc-arctan2 (calc-top-list-n 2))))
+)
+
+(defun calc-conj (arg)
+  (interactive "P")
+  (calc-wrapper
+   (calc-unary-op "conj" 'calcFunc-conj arg))
+)
+
+(defun calc-imaginary ()
+  (interactive)
+  (calc-slow-wrapper
+   (calc-pop-push-record 1 "i*" (math-imaginary (calc-top-n 1))))
+)
+
+
+
+(defun calc-to-degrees (arg)
+  (interactive "P")
+  (calc-wrapper
+   (calc-unary-op ">deg" 'calcFunc-deg arg))
+)
+
+(defun calc-to-radians (arg)
+  (interactive "P")
+  (calc-wrapper
+   (calc-unary-op ">rad" 'calcFunc-rad arg))
+)
+
+
+(defun calc-degrees-mode (arg)
+  (interactive "p")
+  (cond ((= arg 1)
+	 (calc-wrapper
+	  (calc-change-mode 'calc-angle-mode 'deg)
+	  (message "Angles measured in degrees.")))
+	((= arg 2) (calc-radians-mode))
+	((= arg 3) (calc-hms-mode))
+	(t (error "Prefix argument out of range")))
+)
+
+(defun calc-radians-mode ()
+  (interactive)
+  (calc-wrapper
+   (calc-change-mode 'calc-angle-mode 'rad)
+   (message "Angles measured in radians."))
+)
+
+
+;;; Compute the integer square-root floor(sqrt(A)).  A > 0.  [I I] [Public]
+;;; This method takes advantage of the fact that Newton's method starting
+;;; with an overestimate always works, even using truncating integer division!
+(defun math-isqrt (a)
+  (cond ((Math-zerop a) a)
+	((not (math-natnump a))
+	 (math-reject-arg a 'natnump))
+	((integerp a)
+	 (math-isqrt-small a))
+	(t
+	 (math-normalize (cons 'bigpos (cdr (math-isqrt-bignum (cdr a)))))))
+)
+
+(defun calcFunc-isqrt (a)
+  (if (math-realp a)
+      (math-isqrt (math-floor a))
+    (math-floor (math-sqrt a)))
+)
+
+
+;;; This returns (flag . result) where the flag is T if A is a perfect square.
+(defun math-isqrt-bignum (a)   ; [P.l L]
+  (let ((len (length a)))
+    (if (= (% len 2) 0)
+	(let* ((top (nthcdr (- len 2) a)))
+	  (math-isqrt-bignum-iter
+	   a
+	   (math-scale-bignum-3
+	    (math-bignum-big
+	     (1+ (math-isqrt-small
+		  (+ (* (nth 1 top) 1000) (car top)))))
+	    (1- (/ len 2)))))
+      (let* ((top (nth (1- len) a)))
+	(math-isqrt-bignum-iter
+	 a
+	 (math-scale-bignum-3
+	  (list (1+ (math-isqrt-small top)))
+	  (/ len 2))))))
+)
+
+(defun math-isqrt-bignum-iter (a guess)   ; [l L l]
+  (math-working "isqrt" (cons 'bigpos guess))
+  (let* ((q (math-div-bignum a guess))
+	 (s (math-add-bignum (car q) guess))
+	 (g2 (math-div2-bignum s))
+	 (comp (math-compare-bignum g2 guess)))
+    (if (< comp 0)
+	(math-isqrt-bignum-iter a g2)
+      (cons (and (= comp 0)
+		 (math-zerop-bignum (cdr q))
+		 (= (% (car s) 2) 0))
+	    guess)))
+)
+
+(defun math-zerop-bignum (a)
+  (and (eq (car a) 0)
+       (progn
+	 (while (eq (car (setq a (cdr a))) 0))
+	 (null a)))
+)
+
+(defun math-scale-bignum-3 (a n)   ; [L L S]
+  (while (> n 0)
+    (setq a (cons 0 a)
+	  n (1- n)))
+  a
+)
+
+(defun math-isqrt-small (a)   ; A > 0.  [S S]
+  (let ((g (cond ((>= a 10000) 1000)
+		 ((>= a 100) 100)
+		 (t 10)))
+	g2)
+    (while (< (setq g2 (/ (+ g (/ a g)) 2)) g)
+      (setq g g2))
+    g)
+)
+
+
+
+
+;;; Compute the square root of a number.
+;;; [T N] if possible, else [F N] if possible, else [C N].  [Public]
+(defun math-sqrt (a)
+  (or
+   (and (Math-zerop a) a)
+   (and (math-known-nonposp a)
+	(math-imaginary (math-sqrt (math-neg a))))
+   (and (integerp a)
+	(let ((sqrt (math-isqrt-small a)))
+	  (if (= (* sqrt sqrt) a)
+	      sqrt
+	    (if calc-symbolic-mode
+		(list 'calcFunc-sqrt a)
+	      (math-sqrt-float (math-float a) (math-float sqrt))))))
+   (and (eq (car-safe a) 'bigpos)
+	(let* ((res (math-isqrt-bignum (cdr a)))
+	       (sqrt (math-normalize (cons 'bigpos (cdr res)))))
+	  (if (car res)
+	      sqrt
+	    (if calc-symbolic-mode
+		(list 'calcFunc-sqrt a)
+	      (math-sqrt-float (math-float a) (math-float sqrt))))))
+   (and (eq (car-safe a) 'frac)
+	(let* ((num-res (math-isqrt-bignum (cdr (Math-bignum-test (nth 1 a)))))
+	       (num-sqrt (math-normalize (cons 'bigpos (cdr num-res))))
+	       (den-res (math-isqrt-bignum (cdr (Math-bignum-test (nth 2 a)))))
+	       (den-sqrt (math-normalize (cons 'bigpos (cdr den-res)))))
+	  (if (and (car num-res) (car den-res))
+	      (list 'frac num-sqrt den-sqrt)
+	    (if calc-symbolic-mode
+		(if (or (car num-res) (car den-res))
+		    (math-div (if (car num-res)
+				  num-sqrt (list 'calcFunc-sqrt (nth 1 a)))
+			      (if (car den-res)
+				  den-sqrt (list 'calcFunc-sqrt (nth 2 a))))
+		  (list 'calcFunc-sqrt a))
+	      (math-sqrt-float (math-float a)
+			       (math-div (math-float num-sqrt) den-sqrt))))))
+   (and (eq (car-safe a) 'float)
+	(if calc-symbolic-mode
+	    (if (= (% (nth 2 a) 2) 0)
+		(let ((res (math-isqrt-bignum
+			    (cdr (Math-bignum-test (nth 1 a))))))
+		  (if (car res)
+		      (math-make-float (math-normalize
+					(cons 'bigpos (cdr res)))
+				       (/ (nth 2 a) 2))
+		    (signal 'inexact-result nil)))
+	      (signal 'inexact-result nil))
+	  (math-sqrt-float a)))
+   (and (eq (car-safe a) 'cplx)
+	(math-with-extra-prec 2
+	  (let* ((d (math-abs a))
+		 (imag (math-sqrt (math-mul (math-sub d (nth 1 a))
+					    '(float 5 -1)))))
+	    (list 'cplx
+		  (math-sqrt (math-mul (math-add d (nth 1 a)) '(float 5 -1)))
+		  (if (math-negp (nth 2 a)) (math-neg imag) imag)))))
+   (and (eq (car-safe a) 'polar)
+	(list 'polar
+	      (math-sqrt (nth 1 a))
+	      (math-mul (nth 2 a) '(float 5 -1))))
+   (and (eq (car-safe a) 'sdev)
+	(let ((sqrt (math-sqrt (nth 1 a))))
+	  (math-make-sdev sqrt
+			  (math-div (nth 2 a) (math-mul sqrt 2)))))
+   (and (eq (car-safe a) 'intv)
+	(not (math-negp (nth 2 a)))
+	(math-make-intv (nth 1 a) (math-sqrt (nth 2 a)) (math-sqrt (nth 3 a))))
+   (and (eq (car-safe a) '*)
+	(or (math-known-nonnegp (nth 1 a))
+	    (math-known-nonnegp (nth 2 a)))
+	(math-mul (math-sqrt (nth 1 a)) (math-sqrt (nth 2 a))))
+   (and (eq (car-safe a) '/)
+	(or (and (math-known-nonnegp (nth 2 a))
+		 (math-div (math-sqrt (nth 1 a)) (math-sqrt (nth 2 a))))
+	    (and (math-known-nonnegp (nth 1 a))
+		 (not (math-equal-int (nth 1 a) 1))
+		 (math-mul (math-sqrt (nth 1 a))
+			   (math-sqrt (math-div 1 (nth 2 a)))))))
+   (and (eq (car-safe a) '^)
+	(math-known-evenp (nth 2 a))
+	(math-known-realp (nth 1 a))
+	(math-abs (math-pow (nth 1 a) (math-div (nth 2 a) 2))))
+   (let ((inf (math-infinitep a)))
+     (and inf
+	  (math-mul (math-sqrt (math-infinite-dir a inf)) inf)))
+   (progn
+     (calc-record-why 'numberp a)
+     (list 'calcFunc-sqrt a)))
+)
+(fset 'calcFunc-sqrt (symbol-function 'math-sqrt))
+
+(defun math-infinite-dir (a &optional inf)
+  (or inf (setq inf (math-infinitep a)))
+  (math-normalize (math-expr-subst a inf 1))
+)
+
+(defun math-sqrt-float (a &optional guess)   ; [F F F]
+  (if calc-symbolic-mode
+      (signal 'inexact-result nil)
+    (math-with-extra-prec 1 (math-sqrt-raw a guess)))
+)
+
+(defun math-sqrt-raw (a &optional guess)   ; [F F F]
+  (if (not (Math-posp a))
+      (math-sqrt a)
+    (if (null guess)
+	(let ((ldiff (- (math-numdigs (nth 1 a)) 6)))
+	  (or (= (% (+ (nth 2 a) ldiff) 2) 0) (setq ldiff (1+ ldiff)))
+	  (setq guess (math-make-float (math-isqrt-small
+					(math-scale-int (nth 1 a) (- ldiff)))
+				       (/ (+ (nth 2 a) ldiff) 2)))))
+    (math-sqrt-float-iter a guess))
+)
+
+(defun math-sqrt-float-iter (a guess)   ; [F F F]
+  (math-working "sqrt" guess)
+  (let ((g2 (math-mul-float (math-add-float guess (math-div-float a guess))
+			    '(float 5 -1))))
+     (if (math-nearly-equal-float g2 guess)
+	 g2
+       (math-sqrt-float-iter a g2)))
+)
+
+;;; True if A and B differ only in the last digit of precision.  [P F F]
+(defun math-nearly-equal-float (a b)
+  (let ((ediff (- (nth 2 a) (nth 2 b))))
+    (cond ((= ediff 0)   ;; Expanded out for speed
+	   (setq ediff (math-add (Math-integer-neg (nth 1 a)) (nth 1 b)))
+	   (or (eq ediff 0)
+	       (and (not (consp ediff))
+		    (< ediff 10)
+		    (> ediff -10)
+		    (= (math-numdigs (nth 1 a)) calc-internal-prec))))
+	  ((= ediff 1)
+	   (setq ediff (math-add (Math-integer-neg (nth 1 b))
+				 (math-scale-int (nth 1 a) 1)))
+	   (and (not (consp ediff))
+		(< ediff 10)
+		(> ediff -10)
+		(= (math-numdigs (nth 1 b)) calc-internal-prec)))
+	  ((= ediff -1)
+	   (setq ediff (math-add (Math-integer-neg (nth 1 a))
+				 (math-scale-int (nth 1 b) 1)))
+	   (and (not (consp ediff))
+		(< ediff 10)
+		(> ediff -10)
+		(= (math-numdigs (nth 1 a)) calc-internal-prec)))))
+)
+
+(defun math-nearly-equal (a b)   ;  [P N N] [Public]
+  (setq a (math-float a))
+  (setq b (math-float b))
+  (if (eq (car a) 'polar) (setq a (math-complex a)))
+  (if (eq (car b) 'polar) (setq b (math-complex b)))
+  (if (eq (car a) 'cplx)
+      (if (eq (car b) 'cplx)
+	  (and (or (math-nearly-equal-float (nth 1 a) (nth 1 b))
+		   (and (math-nearly-zerop-float (nth 1 a) (nth 2 a))
+			(math-nearly-zerop-float (nth 1 b) (nth 2 b))))
+	       (or (math-nearly-equal-float (nth 2 a) (nth 2 b))
+		   (and (math-nearly-zerop-float (nth 2 a) (nth 1 a))
+			(math-nearly-zerop-float (nth 2 b) (nth 1 b)))))
+	(and (math-nearly-equal-float (nth 1 a) b)
+	     (math-nearly-zerop-float (nth 2 a) b)))
+      (if (eq (car b) 'cplx)
+	  (and (math-nearly-equal-float a (nth 1 b))
+	       (math-nearly-zerop-float a (nth 2 b)))
+	(math-nearly-equal-float a b)))
+)
+
+;;; True if A is nearly zero compared to B.  [P F F]
+(defun math-nearly-zerop-float (a b)
+  (or (eq (nth 1 a) 0)
+      (<= (+ (math-numdigs (nth 1 a)) (nth 2 a))
+	  (1+ (- (+ (math-numdigs (nth 1 b)) (nth 2 b)) calc-internal-prec))))
+)
+
+(defun math-nearly-zerop (a b)   ; [P N R] [Public]
+  (setq a (math-float a))
+  (setq b (math-float b))
+  (if (eq (car a) 'cplx)
+      (and (math-nearly-zerop-float (nth 1 a) b)
+	   (math-nearly-zerop-float (nth 2 a) b))
+    (if (eq (car a) 'polar)
+	(math-nearly-zerop-float (nth 1 a) b)
+      (math-nearly-zerop-float a b)))
+)
+
+;;; This implementation could be improved, accuracy-wise.
+(defun math-hypot (a b)
+  (cond ((Math-zerop a) (math-abs b))
+	((Math-zerop b) (math-abs a))
+	((not (Math-scalarp a))
+	 (if (math-infinitep a)
+	     (if (math-infinitep b)
+		 (if (equal a b)
+		     a
+		   '(var nan var-nan))
+	       a)
+	   (calc-record-why 'scalarp a)
+	   (list 'calcFunc-hypot a b)))
+	((not (Math-scalarp b))
+	 (if (math-infinitep b)
+	     b
+	   (calc-record-why 'scalarp b)
+	   (list 'calcFunc-hypot a b)))
+	((and (Math-numberp a) (Math-numberp b))
+	 (math-with-extra-prec 1
+	   (math-sqrt (math-add (calcFunc-abssqr a) (calcFunc-abssqr b)))))
+	((eq (car-safe a) 'hms)
+	 (if (eq (car-safe b) 'hms)   ; this helps sdev's of hms forms
+	     (math-to-hms (math-hypot (math-from-hms a 'deg)
+				      (math-from-hms b 'deg)))
+	   (math-to-hms (math-hypot (math-from-hms a 'deg) b))))
+	((eq (car-safe b) 'hms)
+	 (math-to-hms (math-hypot a (math-from-hms b 'deg))))
+	(t nil))
+)
+(fset 'calcFunc-hypot (symbol-function 'math-hypot))
+
+(defun calcFunc-sqr (x)
+  (math-pow x 2)
+)
+
+
+
+(defun math-nth-root (a n)
+  (cond ((= n 2) (math-sqrt a))
+	((Math-zerop a) a)
+	((Math-negp a) nil)
+	((Math-integerp a)
+	 (let ((root (math-nth-root-integer a n)))
+	   (if (car root)
+	       (cdr root)
+	     (and (not calc-symbolic-mode)
+		  (math-nth-root-float (math-float a) n
+				       (math-float (cdr root)))))))
+	((eq (car-safe a) 'frac)
+	 (let* ((num-root (math-nth-root-integer (nth 1 a) n))
+		(den-root (math-nth-root-integer (nth 2 a) n)))
+	   (if (and (car num-root) (car den-root))
+	       (list 'frac (cdr num-root) (cdr den-root))
+	     (and (not calc-symbolic-mode)
+		  (math-nth-root-float
+		   (math-float a) n
+		   (math-div-float (math-float (cdr num-root))
+				   (math-float (cdr den-root))))))))
+	((eq (car-safe a) 'float)
+	 (and (not calc-symbolic-mode)
+	      (math-nth-root-float a n)))
+	((eq (car-safe a) 'polar)
+	 (let ((root (math-nth-root (nth 1 a) n)))
+	   (and root (list 'polar root (math-div (nth 2 a) n)))))
+	(t nil))
+)
+
+(defun math-nth-root-float (a n &optional guess)
+  (math-inexact-result)
+  (math-with-extra-prec 1
+    (let ((nf (math-float n))
+	  (nfm1 (math-float (1- n))))
+      (math-nth-root-float-iter a (or guess
+				      (math-make-float
+				       1 (/ (+ (math-numdigs (nth 1 a))
+					       (nth 2 a)
+					       (/ n 2))
+					    n))))))
+)
+
+(defun math-nth-root-float-iter (a guess)   ; uses "n", "nf", "nfm1"
+  (math-working "root" guess)
+  (let ((g2 (math-div-float (math-add-float (math-mul nfm1 guess)
+					    (math-div-float
+					     a (math-ipow guess (1- n))))
+			    nf)))
+    (if (math-nearly-equal-float g2 guess)
+	g2
+      (math-nth-root-float-iter a g2)))
+)
+
+(defun math-nth-root-integer (a n &optional guess)   ; [I I S]
+  (math-nth-root-int-iter a (or guess
+				(math-scale-int 1 (/ (+ (math-numdigs a)
+							(1- n))
+						     n))))
+)
+
+(defun math-nth-root-int-iter (a guess)   ; uses "n"
+  (math-working "root" guess)
+  (let* ((q (math-idivmod a (math-ipow guess (1- n))))
+	 (s (math-add (car q) (math-mul (1- n) guess)))
+	 (g2 (math-idivmod s n)))
+    (if (Math-natnum-lessp (car g2) guess)
+	(math-nth-root-int-iter a (car g2))
+      (cons (and (equal (car g2) guess)
+		 (eq (cdr q) 0)
+		 (eq (cdr g2) 0))
+	    guess)))
+)
+
+(defun calcFunc-nroot (x n)
+  (calcFunc-pow x (if (integerp n)
+		      (math-make-frac 1 n)
+		    (math-div 1 n)))
+)
+
+
+
+
+;;;; Transcendental functions.
+
+;;; All of these functions are defined on the complex plane.
+;;; (Branch cuts, etc. follow Steele's Common Lisp book.)
+
+;;; Most functions increase calc-internal-prec by 2 digits, then round
+;;; down afterward.  "-raw" functions use the current precision, require
+;;; their arguments to be in float (or complex float) format, and always
+;;; work in radians (where applicable).
+
+(defun math-to-radians (a)   ; [N N]
+  (cond ((eq (car-safe a) 'hms)
+	 (math-from-hms a 'rad))
+	((memq calc-angle-mode '(deg hms))
+	 (math-mul a (math-pi-over-180)))
+	(t a))
+)
+
+(defun math-from-radians (a)   ; [N N]
+  (cond ((eq calc-angle-mode 'deg)
+	 (if (math-constp a)
+	     (math-div a (math-pi-over-180))
+	   (list 'calcFunc-deg a)))
+	((eq calc-angle-mode 'hms)
+	 (math-to-hms a 'rad))
+	(t a))
+)
+
+(defun math-to-radians-2 (a)   ; [N N]
+  (cond ((eq (car-safe a) 'hms)
+	 (math-from-hms a 'rad))
+	((memq calc-angle-mode '(deg hms))
+	 (if calc-symbolic-mode
+	     (math-div (math-mul a '(var pi var-pi)) 180)
+	   (math-mul a (math-pi-over-180))))
+	(t a))
+)
+
+(defun math-from-radians-2 (a)   ; [N N]
+  (cond ((memq calc-angle-mode '(deg hms))
+	 (if calc-symbolic-mode
+	     (math-div (math-mul 180 a) '(var pi var-pi))
+	   (math-div a (math-pi-over-180))))
+	(t a))
+)
+
+
+
+;;; Sine, cosine, and tangent.
+
+(defun calcFunc-sin (x)   ; [N N] [Public]
+  (cond ((and (integerp x)
+	      (if (eq calc-angle-mode 'deg)
+		  (= (% x 90) 0)
+		(= x 0)))
+	 (aref [0 1 0 -1] (math-mod (/ x 90) 4)))
+	((Math-scalarp x)
+	 (math-with-extra-prec 2
+	   (math-sin-raw (math-to-radians (math-float x)))))
+	((eq (car x) 'sdev)
+	 (if (math-constp x)
+	     (math-with-extra-prec 2
+	       (let* ((xx (math-to-radians (math-float (nth 1 x))))
+		      (xs (math-to-radians (math-float (nth 2 x))))
+		      (sc (math-sin-cos-raw xx)))
+		 (math-make-sdev (car sc) (math-mul xs (cdr sc)))))
+	   (math-make-sdev (calcFunc-sin (nth 1 x))
+			   (math-mul (nth 2 x) (calcFunc-cos (nth 1 x))))))
+	((and (eq (car x) 'intv) (math-intv-constp x))
+	 (calcFunc-cos (math-sub x (math-quarter-circle nil))))
+	((equal x '(var nan var-nan))
+	 x)
+	(t (calc-record-why 'scalarp x)
+	   (list 'calcFunc-sin x)))
+)
+
+(defun calcFunc-cos (x)   ; [N N] [Public]
+  (cond ((and (integerp x)
+	      (if (eq calc-angle-mode 'deg)
+		  (= (% x 90) 0)
+		(= x 0)))
+	 (aref [1 0 -1 0] (math-mod (/ x 90) 4)))
+	((Math-scalarp x)
+	 (math-with-extra-prec 2
+	   (math-cos-raw (math-to-radians (math-float x)))))
+	((eq (car x) 'sdev)
+	 (if (math-constp x)
+	     (math-with-extra-prec 2
+	       (let* ((xx (math-to-radians (math-float (nth 1 x))))
+		      (xs (math-to-radians (math-float (nth 2 x))))
+		      (sc (math-sin-cos-raw xx)))
+		 (math-make-sdev (cdr sc) (math-mul xs (car sc)))))
+	   (math-make-sdev (calcFunc-cos (nth 1 x))
+			   (math-mul (nth 2 x) (calcFunc-sin (nth 1 x))))))
+	((and (eq (car x) 'intv) (math-intv-constp x))
+	 (math-with-extra-prec 2
+	   (let* ((xx (math-to-radians (math-float x)))
+		  (na (math-floor (math-div (nth 2 xx) (math-pi))))
+		  (nb (math-floor (math-div (nth 3 xx) (math-pi))))
+		  (span (math-sub nb na)))
+	     (if (memq span '(0 1))
+		 (let ((int (math-sort-intv (nth 1 x)
+					    (math-cos-raw (nth 2 xx))
+					    (math-cos-raw (nth 3 xx)))))
+		   (if (eq span 1)
+		       (if (math-evenp na)
+			   (math-make-intv (logior (nth 1 x) 2)
+					   -1
+					   (nth 3 int))
+			 (math-make-intv (logior (nth 1 x) 1)
+					 (nth 2 int)
+					 1))
+		     int))
+	       (list 'intv 3 -1 1)))))
+	((equal x '(var nan var-nan))
+	 x)
+	(t (calc-record-why 'scalarp x)
+	   (list 'calcFunc-cos x)))
+)
+
+(defun calcFunc-sincos (x)   ; [V N] [Public]
+  (if (Math-scalarp x)
+      (math-with-extra-prec 2
+	(let ((sc (math-sin-cos-raw (math-to-radians (math-float x)))))
+	  (list 'vec (cdr sc) (car sc))))    ; the vector [cos, sin]
+    (list 'vec (calcFunc-sin x) (calcFunc-cos x)))
+)
+
+(defun calcFunc-tan (x)   ; [N N] [Public]
+  (cond ((and (integerp x)
+	      (if (eq calc-angle-mode 'deg)
+		  (= (% x 180) 0)
+		(= x 0)))
+	 0)
+	((Math-scalarp x)
+	 (math-with-extra-prec 2
+	   (math-tan-raw (math-to-radians (math-float x)))))
+	((eq (car x) 'sdev)
+	 (if (math-constp x)
+	     (math-with-extra-prec 2
+	       (let* ((xx (math-to-radians (math-float (nth 1 x))))
+		      (xs (math-to-radians (math-float (nth 2 x))))
+		      (sc (math-sin-cos-raw xx)))
+		 (if (and (math-zerop (cdr sc)) (not calc-infinite-mode))
+		     (progn
+		       (calc-record-why "*Division by zero")
+		       (list 'calcFunc-tan x))
+		   (math-make-sdev (math-div-float (car sc) (cdr sc))
+				   (math-div-float xs (math-sqr (cdr sc)))))))
+	   (math-make-sdev (calcFunc-tan (nth 1 x))
+			   (math-div (nth 2 x)
+				     (math-sqr (calcFunc-cos (nth 1 x)))))))
+	((and (eq (car x) 'intv) (math-intv-constp x))
+	 (or (math-with-extra-prec 2
+	       (let* ((xx (math-to-radians (math-float x)))
+		      (na (math-floor (math-div (math-sub (nth 2 xx)
+							  (math-pi-over-2))
+						(math-pi))))
+		      (nb (math-floor (math-div (math-sub (nth 3 xx)
+							  (math-pi-over-2))
+						(math-pi)))))
+		 (and (equal na nb)
+		      (math-sort-intv (nth 1 x)
+				      (math-tan-raw (nth 2 xx))
+				      (math-tan-raw (nth 3 xx))))))
+	     '(intv 3 (neg (var inf var-inf)) (var inf var-inf))))
+	((equal x '(var nan var-nan))
+	 x)
+	(t (calc-record-why 'scalarp x)
+	   (list 'calcFunc-tan x)))
+)
+
+(defun math-sin-raw (x)   ; [N N]
+  (cond ((eq (car x) 'cplx)
+	 (let* ((expx (math-exp-raw (nth 2 x)))
+		(expmx (math-div-float '(float 1 0) expx))
+		(sc (math-sin-cos-raw (nth 1 x))))
+	   (list 'cplx
+		 (math-mul-float (car sc)
+				 (math-mul-float (math-add-float expx expmx)
+						 '(float 5 -1)))
+		 (math-mul-float (cdr sc)
+				 (math-mul-float (math-sub-float expx expmx)
+						 '(float 5 -1))))))
+	((eq (car x) 'polar)
+	 (math-polar (math-sin-raw (math-complex x))))
+	((Math-integer-negp (nth 1 x))
+	 (math-neg-float (math-sin-raw (math-neg-float x))))
+	((math-lessp-float '(float 7 0) x)  ; avoid inf loops due to roundoff
+	 (math-sin-raw (math-mod x (math-two-pi))))
+	(t (math-sin-raw-2 x x)))
+)
+
+(defun math-cos-raw (x)   ; [N N]
+  (if (eq (car-safe x) 'polar)
+      (math-polar (math-cos-raw (math-complex x)))
+    (math-sin-raw (math-sub (math-pi-over-2) x)))
+)
+
+;;; This could use a smarter method:  Reduce x as in math-sin-raw, then
+;;;   compute either sin(x) or cos(x), whichever is smaller, and compute
+;;;   the other using the identity sin(x)^2 + cos(x)^2 = 1.
+(defun math-sin-cos-raw (x)   ; [F.F F]  (result is (sin x . cos x))
+  (cons (math-sin-raw x) (math-cos-raw x))
+)
+
+(defun math-tan-raw (x)   ; [N N]
+  (cond ((eq (car x) 'cplx)
+	 (let* ((x (math-mul x '(float 2 0)))
+		(expx (math-exp-raw (nth 2 x)))
+		(expmx (math-div-float '(float 1 0) expx))
+		(sc (math-sin-cos-raw (nth 1 x)))
+		(d (math-add-float (cdr sc)
+				   (math-mul-float (math-add-float expx expmx)
+						   '(float 5 -1)))))
+	   (and (not (eq (nth 1 d) 0))
+		(list 'cplx
+		      (math-div-float (car sc) d)
+		      (math-div-float (math-mul-float (math-sub-float expx
+								      expmx)
+						      '(float 5 -1)) d)))))
+	((eq (car x) 'polar)
+	 (math-polar (math-tan-raw (math-complex x))))
+	(t
+	 (let ((sc (math-sin-cos-raw x)))
+	   (if (eq (nth 1 (cdr sc)) 0)
+	       (math-div (car sc) 0)
+	     (math-div-float (car sc) (cdr sc))))))
+)
+
+(defun math-sin-raw-2 (x orgx)   ; This avoids poss of inf recursion.  [F F]
+  (let ((xmpo2 (math-sub-float (math-pi-over-2) x)))
+    (cond ((Math-integer-negp (nth 1 xmpo2))
+	   (math-neg-float (math-sin-raw-2 (math-sub-float x (math-pi))
+					   orgx)))
+	  ((math-lessp-float (math-pi-over-4) x)
+	   (math-cos-raw-2 xmpo2 orgx))
+	  ((math-lessp-float x (math-neg (math-pi-over-4)))
+	   (math-neg (math-cos-raw-2 (math-add (math-pi-over-2) x) orgx)))
+	  ((math-nearly-zerop-float x orgx) '(float 0 0))
+	  (calc-symbolic-mode (signal 'inexact-result nil))
+	  (t (math-sin-series x 6 4 x (math-neg-float (math-sqr-float x))))))
+)
+
+(defun math-cos-raw-2 (x orgx)   ; [F F]
+  (cond ((math-nearly-zerop-float x orgx) '(float 1 0))
+	(calc-symbolic-mode (signal 'inexact-result nil))
+	(t (let ((xnegsqr (math-neg-float (math-sqr-float x))))
+	     (math-sin-series
+	      (math-add-float '(float 1 0)
+			      (math-mul-float xnegsqr '(float 5 -1)))
+	      24 5 xnegsqr xnegsqr))))
+)
+
+(defun math-sin-series (sum nfac n x xnegsqr)
+  (math-working "sin" sum)
+  (let* ((nextx (math-mul-float x xnegsqr))
+	 (nextsum (math-add-float sum (math-div-float nextx
+						      (math-float nfac)))))
+    (if (math-nearly-equal-float sum nextsum)
+	sum
+      (math-sin-series nextsum (math-mul nfac (* n (1+ n)))
+		       (+ n 2) nextx xnegsqr)))
+)
+
+
+;;; Inverse sine, cosine, tangent.
+
+(defun calcFunc-arcsin (x)   ; [N N] [Public]
+  (cond ((eq x 0) 0)
+	((and (eq x 1) (eq calc-angle-mode 'deg)) 90)
+	((and (eq x -1) (eq calc-angle-mode 'deg)) -90)
+	(calc-symbolic-mode (signal 'inexact-result nil))
+	((Math-numberp x)
+	 (math-with-extra-prec 2
+	   (math-from-radians (math-arcsin-raw (math-float x)))))
+	((eq (car x) 'sdev)
+	 (math-make-sdev (calcFunc-arcsin (nth 1 x))
+			 (math-from-radians
+			  (math-div (nth 2 x)
+				    (math-sqrt
+				     (math-sub 1 (math-sqr (nth 1 x))))))))
+	((eq (car x) 'intv)
+	 (math-sort-intv (nth 1 x)
+			 (calcFunc-arcsin (nth 2 x))
+			 (calcFunc-arcsin (nth 3 x))))
+	((equal x '(var nan var-nan))
+	 x)
+	(t (calc-record-why 'numberp x)
+	   (list 'calcFunc-arcsin x)))
+)
+
+(defun calcFunc-arccos (x)   ; [N N] [Public]
+  (cond ((eq x 1) 0)
+	((and (eq x 0) (eq calc-angle-mode 'deg)) 90)
+	((and (eq x -1) (eq calc-angle-mode 'deg)) 180)
+	(calc-symbolic-mode (signal 'inexact-result nil))
+	((Math-numberp x)
+	 (math-with-extra-prec 2
+	   (math-from-radians (math-arccos-raw (math-float x)))))
+	((eq (car x) 'sdev)
+	 (math-make-sdev (calcFunc-arccos (nth 1 x))
+			 (math-from-radians
+			  (math-div (nth 2 x)
+				    (math-sqrt
+				     (math-sub 1 (math-sqr (nth 1 x))))))))
+	((eq (car x) 'intv)
+	 (math-sort-intv (nth 1 x)
+			 (calcFunc-arccos (nth 2 x))
+			 (calcFunc-arccos (nth 3 x))))
+	((equal x '(var nan var-nan))
+	 x)
+	(t (calc-record-why 'numberp x)
+	   (list 'calcFunc-arccos x)))
+)
+
+(defun calcFunc-arctan (x)   ; [N N] [Public]
+  (cond ((eq x 0) 0)
+	((and (eq x 1) (eq calc-angle-mode 'deg)) 45)
+	((and (eq x -1) (eq calc-angle-mode 'deg)) -45)
+	((Math-numberp x)
+	 (math-with-extra-prec 2
+	   (math-from-radians (math-arctan-raw (math-float x)))))
+	((eq (car x) 'sdev)
+	 (math-make-sdev (calcFunc-arctan (nth 1 x))
+			 (math-from-radians
+			  (math-div (nth 2 x)
+				    (math-add 1 (math-sqr (nth 1 x)))))))
+	((eq (car x) 'intv)
+	 (math-sort-intv (nth 1 x)
+			 (calcFunc-arctan (nth 2 x))
+			 (calcFunc-arctan (nth 3 x))))
+	((equal x '(var inf var-inf))
+	 (math-quarter-circle t))
+	((equal x '(neg (var inf var-inf)))
+	 (math-neg (math-quarter-circle t)))
+	((equal x '(var nan var-nan))
+	 x)
+	(t (calc-record-why 'numberp x)
+	   (list 'calcFunc-arctan x)))
+)
+
+(defun math-arcsin-raw (x)   ; [N N]
+  (let ((a (math-sqrt-raw (math-sub '(float 1 0) (math-sqr x)))))
+    (if (or (memq (car x) '(cplx polar))
+	    (memq (car a) '(cplx polar)))
+	(math-with-extra-prec 2   ; use extra precision for difficult case
+	  (math-mul '(cplx 0 -1)
+		    (math-ln-raw (math-add (math-mul '(cplx 0 1) x) a))))
+      (math-arctan2-raw x a)))
+)
+
+(defun math-arccos-raw (x)   ; [N N]
+  (math-sub (math-pi-over-2) (math-arcsin-raw x))
+)
+
+(defun math-arctan-raw (x)   ; [N N]
+  (cond ((memq (car x) '(cplx polar))
+	 (math-with-extra-prec 2   ; extra-extra
+	   (math-div (math-sub
+		      (math-ln-raw (math-add 1 (math-mul '(cplx 0 1) x)))
+		      (math-ln-raw (math-add 1 (math-mul '(cplx 0 -1) x))))
+		     '(cplx 0 2))))
+	((Math-integer-negp (nth 1 x))
+	 (math-neg-float (math-arctan-raw (math-neg-float x))))
+	((math-zerop x) x)
+	(calc-symbolic-mode (signal 'inexact-result nil))
+	((math-equal-int x 1) (math-pi-over-4))
+	((math-equal-int x -1) (math-neg (math-pi-over-4)))
+	((math-lessp-float '(float 414214 -6) x)  ; if x > sqrt(2) - 1, reduce
+	 (if (math-lessp-float '(float 1 0) x)
+	     (math-sub-float (math-mul-float (math-pi) '(float 5 -1))
+			     (math-arctan-raw (math-div-float '(float 1 0) x)))
+	   (math-sub-float (math-mul-float (math-pi) '(float 25 -2))
+			   (math-arctan-raw (math-div-float
+					     (math-sub-float '(float 1 0) x)
+					     (math-add-float '(float 1 0)
+							     x))))))
+	(t (math-arctan-series x 3 x (math-neg-float (math-sqr-float x)))))
+)
+
+(defun math-arctan-series (sum n x xnegsqr)
+  (math-working "arctan" sum)
+  (let* ((nextx (math-mul-float x xnegsqr))
+	 (nextsum (math-add-float sum (math-div-float nextx (math-float n)))))
+    (if (math-nearly-equal-float sum nextsum)
+	sum
+      (math-arctan-series nextsum (+ n 2) nextx xnegsqr)))
+)
+
+(defun calcFunc-arctan2 (y x)   ; [F R R] [Public]
+  (if (Math-anglep y)
+      (if (Math-anglep x)
+	  (math-with-extra-prec 2
+	    (math-from-radians (math-arctan2-raw (math-float y)
+						 (math-float x))))
+	(calc-record-why 'anglep x)
+	(list 'calcFunc-arctan2 y x))
+    (if (and (or (math-infinitep x) (math-anglep x))
+	     (or (math-infinitep y) (math-anglep y)))
+	(progn
+	  (if (math-posp x)
+	      (setq x 1)
+	    (if (math-negp x)
+		(setq x -1)
+	      (or (math-zerop x)
+		  (setq x nil))))
+	  (if (math-posp y)
+	      (setq y 1)
+	    (if (math-negp y)
+		(setq y -1)
+	      (or (math-zerop y)
+		  (setq y nil))))
+	  (if (and y x)
+	      (calcFunc-arctan2 y x)
+	    '(var nan var-nan)))
+      (calc-record-why 'anglep y)
+      (list 'calcFunc-arctan2 y x)))
+)
+
+(defun math-arctan2-raw (y x)   ; [F R R]
+  (cond ((math-zerop y)
+	 (if (math-negp x) (math-pi)
+	   (if (or (math-floatp x) (math-floatp y)) '(float 0 0) 0)))
+	((math-zerop x)
+	 (if (math-posp y)
+	     (math-pi-over-2)
+	   (math-neg (math-pi-over-2))))
+	((math-posp x)
+	 (math-arctan-raw (math-div-float y x)))
+	((math-posp y)
+	 (math-add-float (math-arctan-raw (math-div-float y x))
+			 (math-pi)))
+	(t
+	 (math-sub-float (math-arctan-raw (math-div-float y x))
+			 (math-pi))))
+)
+
+(defun calcFunc-arcsincos (x)   ; [V N] [Public]
+  (if (and (Math-vectorp x)
+	   (= (length x) 3))
+      (calcFunc-arctan2 (nth 2 x) (nth 1 x))
+    (math-reject-arg x "*Two-element vector expected"))
+)
+
+
+
+;;; Exponential function.
+
+(defun calcFunc-exp (x)   ; [N N] [Public]
+  (cond ((eq x 0) 1)
+	((and (memq x '(1 -1)) calc-symbolic-mode)
+	 (if (eq x 1) '(var e var-e) (math-div 1 '(var e var-e))))
+	((Math-numberp x)
+	 (math-with-extra-prec 2 (math-exp-raw (math-float x))))
+	((eq (car-safe x) 'sdev)
+	 (let ((ex (calcFunc-exp (nth 1 x))))
+	   (math-make-sdev ex (math-mul (nth 2 x) ex))))
+	((eq (car-safe x) 'intv)
+	 (math-make-intv (nth 1 x) (calcFunc-exp (nth 2 x))
+			 (calcFunc-exp (nth 3 x))))
+	((equal x '(var inf var-inf))
+	 x)
+	((equal x '(neg (var inf var-inf)))
+	 0)
+	((equal x '(var nan var-nan))
+	 x)
+	(t (calc-record-why 'numberp x)
+	   (list 'calcFunc-exp x)))
+)
+
+(defun calcFunc-expm1 (x)   ; [N N] [Public]
+  (cond ((eq x 0) 0)
+	((math-zerop x) '(float 0 0))
+	(calc-symbolic-mode (signal 'inexact-result nil))
+	((Math-numberp x)
+	 (math-with-extra-prec 2
+	   (let ((x (math-float x)))
+	     (if (and (eq (car x) 'float)
+		      (math-lessp-float x '(float 1 0))
+		      (math-lessp-float '(float -1 0) x))
+		 (math-exp-minus-1-raw x)
+	       (math-add (math-exp-raw x) -1)))))
+	((eq (car-safe x) 'sdev)
+	 (if (math-constp x)
+	     (let ((ex (calcFunc-expm1 (nth 1 x))))
+	       (math-make-sdev ex (math-mul (nth 2 x) (math-add ex 1))))
+	   (math-make-sdev (calcFunc-expm1 (nth 1 x))
+			   (math-mul (nth 2 x) (calcFunc-exp (nth 1 x))))))
+	((eq (car-safe x) 'intv)
+	 (math-make-intv (nth 1 x)
+			 (calcFunc-expm1 (nth 2 x))
+			 (calcFunc-expm1 (nth 3 x))))
+	((equal x '(var inf var-inf))
+	 x)
+	((equal x '(neg (var inf var-inf)))
+	 -1)
+	((equal x '(var nan var-nan))
+	 x)
+	(t (calc-record-why 'numberp x)
+	   (list 'calcFunc-expm1 x)))
+)
+
+(defun calcFunc-exp10 (x)   ; [N N] [Public]
+  (if (eq x 0)
+      1
+    (math-pow '(float 1 1) x))
+)
+
+(defun math-exp-raw (x)   ; [N N]
+  (cond ((math-zerop x) '(float 1 0))
+	(calc-symbolic-mode (signal 'inexact-result nil))
+	((eq (car x) 'cplx)
+	 (let ((expx (math-exp-raw (nth 1 x)))
+	       (sc (math-sin-cos-raw (nth 2 x))))
+	   (list 'cplx
+		 (math-mul-float expx (cdr sc))
+		 (math-mul-float expx (car sc)))))
+	((eq (car x) 'polar)
+	 (let ((xc (math-complex x)))
+	   (list 'polar
+		 (math-exp-raw (nth 1 xc))
+		 (math-from-radians (nth 2 xc)))))
+	((or (math-lessp-float '(float 5 -1) x)
+	     (math-lessp-float x '(float -5 -1)))
+	 (if (math-lessp-float '(float 921035 1) x)
+	     (math-overflow)
+	   (if (math-lessp-float x '(float -921035 1))
+	       (math-underflow)))
+	 (let* ((two-x (math-mul-float x '(float 2 0)))
+		(hint (math-scale-int (nth 1 two-x) (nth 2 two-x)))
+		(hfrac (math-sub-float x (math-mul-float (math-float hint)
+							 '(float 5 -1)))))
+	   (math-mul-float (math-ipow (math-sqrt-e) hint)
+			   (math-add-float '(float 1 0)
+					   (math-exp-minus-1-raw hfrac)))))
+	(t (math-add-float '(float 1 0) (math-exp-minus-1-raw x))))
+)
+
+(defun math-exp-minus-1-raw (x)   ; [F F]
+  (math-exp-series x 2 3 x x)
+)
+
+(defun math-exp-series (sum nfac n xpow x)
+  (math-working "exp" sum)
+  (let* ((nextx (math-mul-float xpow x))
+	 (nextsum (math-add-float sum (math-div-float nextx
+						      (math-float nfac)))))
+    (if (math-nearly-equal-float sum nextsum)
+	sum
+      (math-exp-series nextsum (math-mul nfac n) (1+ n) nextx x)))
+)
+
+
+
+;;; Logarithms.
+
+(defun calcFunc-ln (x)   ; [N N] [Public]
+  (cond ((math-zerop x)
+	 (if calc-infinite-mode
+	     '(neg (var inf var-inf))
+	   (math-reject-arg x "*Logarithm of zero")))
+	((eq x 1) 0)
+	((Math-numberp x)
+	 (math-with-extra-prec 2 (math-ln-raw (math-float x))))
+	((eq (car-safe x) 'sdev)
+	 (math-make-sdev (calcFunc-ln (nth 1 x))
+			 (math-div (nth 2 x) (nth 1 x))))
+	((and (eq (car-safe x) 'intv) (or (Math-posp (nth 2 x))
+					  (Math-zerop (nth 2 x))
+					  (not (math-intv-constp x))))
+	 (let ((calc-infinite-mode t))
+	   (math-make-intv (nth 1 x) (calcFunc-ln (nth 2 x))
+			   (calcFunc-ln (nth 3 x)))))
+	((equal x '(var e var-e))
+	 1)
+	((and (eq (car-safe x) '^)
+	      (equal (nth 1 x) '(var e var-e))
+	      (math-known-realp (nth 2 x)))
+	 (nth 2 x))
+	((math-infinitep x)
+	 (if (equal x '(var nan var-nan))
+	     x
+	   '(var inf var-inf)))
+	(t (calc-record-why 'numberp x)
+	   (list 'calcFunc-ln x)))
+)
+
+(defun calcFunc-log10 (x)   ; [N N] [Public]
+  (cond ((math-equal-int x 1)
+	 (if (math-floatp x) '(float 0 0) 0))
+	((and (Math-integerp x)
+	      (math-posp x)
+	      (let ((res (math-integer-log x 10)))
+		(and (car res)
+		     (setq x (cdr res)))))
+	 x)
+	((and (eq (car-safe x) 'frac)
+	      (eq (nth 1 x) 1)
+	      (let ((res (math-integer-log (nth 2 x) 10)))
+		(and (car res)
+		     (setq x (- (cdr res))))))
+	 x)
+	((math-zerop x)
+	 (if calc-infinite-mode
+	     '(neg (var inf var-inf))
+	   (math-reject-arg x "*Logarithm of zero")))
+	(calc-symbolic-mode (signal 'inexact-result nil))
+	((Math-numberp x)
+	 (math-with-extra-prec 2
+	   (let ((xf (math-float x)))
+	     (if (eq (nth 1 xf) 0)
+		 (math-reject-arg x "*Logarithm of zero"))
+	     (if (Math-integer-posp (nth 1 xf))
+		 (if (eq (nth 1 xf) 1)    ; log10(1*10^n) = n
+		     (math-float (nth 2 xf))
+		   (let ((xdigs (1- (math-numdigs (nth 1 xf)))))
+		     (math-add-float
+		      (math-div-float (math-ln-raw-2
+				       (list 'float (nth 1 xf) (- xdigs)))
+				      (math-ln-10))
+		      (math-float (+ (nth 2 xf) xdigs)))))
+	       (math-div (calcFunc-ln xf) (math-ln-10))))))
+	((eq (car-safe x) 'sdev)
+	 (math-make-sdev (calcFunc-log10 (nth 1 x))
+			 (math-div (nth 2 x)
+				   (math-mul (nth 1 x) (math-ln-10)))))
+	((and (eq (car-safe x) 'intv) (or (Math-posp (nth 2 x))
+					  (not (math-intv-constp x))))
+	 (math-make-intv (nth 1 x)
+			 (calcFunc-log10 (nth 2 x))
+			 (calcFunc-log10 (nth 3 x))))
+	((math-infinitep x)
+	 (if (equal x '(var nan var-nan))
+	     x
+	   '(var inf var-inf)))
+	(t (calc-record-why 'numberp x)
+	   (list 'calcFunc-log10 x)))
+)
+
+(defun calcFunc-log (x &optional b)   ; [N N N] [Public]
+  (cond ((or (null b) (equal b '(var e var-e)))
+	 (math-normalize (list 'calcFunc-ln x)))
+	((or (eq b 10) (equal b '(float 1 1)))
+	 (math-normalize (list 'calcFunc-log10 x)))
+	((math-zerop x)
+	 (if calc-infinite-mode
+	     (math-div (calcFunc-ln x) (calcFunc-ln b))
+	   (math-reject-arg x "*Logarithm of zero")))
+	((math-zerop b)
+	 (if calc-infinite-mode
+	     (math-div (calcFunc-ln x) (calcFunc-ln b))
+	   (math-reject-arg b "*Logarithm of zero")))
+	((math-equal-int b 1)
+	 (if calc-infinite-mode
+	     (math-div (calcFunc-ln x) 0)
+	   (math-reject-arg b "*Logarithm base one")))
+	((math-equal-int x 1)
+	 (if (or (math-floatp a) (math-floatp b)) '(float 0 0) 0))
+	((and (Math-ratp x) (Math-ratp b)
+	      (math-posp x) (math-posp b)
+	      (let* ((sign 1) (inv nil)
+		     (xx (if (Math-lessp 1 x)
+			     x
+			   (setq sign -1)
+			   (math-div 1 x)))
+		     (bb (if (Math-lessp 1 b)
+			     b
+			   (setq sign (- sign))
+			   (math-div 1 b)))
+		     (res (if (Math-lessp xx bb)
+			      (setq inv (math-integer-log bb xx))
+			    (math-integer-log xx bb))))
+		(and (car res)
+		     (setq x (if inv
+				 (math-div 1 (* sign (cdr res)))
+			       (* sign (cdr res)))))))
+	 x)
+	(calc-symbolic-mode (signal 'inexact-result nil))
+	((and (Math-numberp x) (Math-numberp b))
+	 (math-with-extra-prec 2
+	   (math-div (math-ln-raw (math-float x))
+		     (math-log-base-raw b))))
+	((and (eq (car-safe x) 'sdev)
+	      (Math-numberp b))
+	 (math-make-sdev (calcFunc-log (nth 1 x) b)
+			 (math-div (nth 2 x)
+				   (math-mul (nth 1 x)
+					     (math-log-base-raw b)))))
+	((and (eq (car-safe x) 'intv) (or (Math-posp (nth 2 x))
+					  (not (math-intv-constp x)))
+	      (math-realp b))
+	 (math-make-intv (nth 1 x)
+			 (calcFunc-log (nth 2 x) b)
+			 (calcFunc-log (nth 3 x) b)))
+	((or (eq (car-safe x) 'intv) (eq (car-safe b) 'intv))
+	 (math-div (calcFunc-ln x) (calcFunc-ln b)))
+	((or (math-infinitep x)
+	     (math-infinitep b))
+	 (math-div (calcFunc-ln x) (calcFunc-ln b)))
+	(t (if (Math-numberp b)
+	       (calc-record-why 'numberp x)
+	     (calc-record-why 'numberp b))
+	   (list 'calcFunc-log x b)))
+)
+
+(defun calcFunc-alog (x &optional b)
+  (cond ((or (null b) (equal b '(var e var-e)))
+	 (math-normalize (list 'calcFunc-exp x)))
+	(t (math-pow b x)))
+)
+
+(defun calcFunc-ilog (x b)
+  (if (and (math-natnump x) (not (eq x 0))
+	   (math-natnump b) (not (eq b 0)))
+      (if (eq b 1)
+	  (math-reject-arg x "*Logarithm base one")
+	(if (Math-natnum-lessp x b)
+	    0
+	  (cdr (math-integer-log x b))))
+    (math-floor (calcFunc-log x b)))
+)
+
+(defun math-integer-log (x b)
+  (let ((pows (list b))
+	(pow (math-sqr b))
+	next
+	sum n)
+    (while (not (Math-lessp x pow))
+      (setq pows (cons pow pows)
+	    pow (math-sqr pow)))
+    (setq n (lsh 1 (1- (length pows)))
+	  sum n
+	  pow (car pows))
+    (while (and (setq pows (cdr pows))
+		(Math-lessp pow x))
+      (setq n (/ n 2)
+	    next (math-mul pow (car pows)))
+      (or (Math-lessp x next)
+	  (setq pow next
+		sum (+ sum n))))
+    (cons (equal pow x) sum))
+)
+
+
+(defun math-log-base-raw (b)   ; [N N]
+  (if (not (and (equal (car math-log-base-cache) b)
+		(eq (nth 1 math-log-base-cache) calc-internal-prec)))
+      (setq math-log-base-cache (list b calc-internal-prec
+				      (math-ln-raw (math-float b)))))
+  (nth 2 math-log-base-cache)
+)
+(setq math-log-base-cache nil)
+
+(defun calcFunc-lnp1 (x)   ; [N N] [Public]
+  (cond ((Math-equal-int x -1)
+	 (if calc-infinite-mode
+	     '(neg (var inf var-inf))
+	   (math-reject-arg x "*Logarithm of zero")))
+	((eq x 0) 0)
+	((math-zerop x) '(float 0 0))
+	(calc-symbolic-mode (signal 'inexact-result nil))
+	((Math-numberp x)
+	 (math-with-extra-prec 2
+	   (let ((x (math-float x)))
+	     (if (and (eq (car x) 'float)
+		      (math-lessp-float x '(float 5 -1))
+		      (math-lessp-float '(float -5 -1) x))
+		 (math-ln-plus-1-raw x)
+	       (math-ln-raw (math-add-float x '(float 1 0)))))))
+	((eq (car-safe x) 'sdev)
+	 (math-make-sdev (calcFunc-lnp1 (nth 1 x))
+			 (math-div (nth 2 x) (math-add (nth 1 x) 1))))
+	((and (eq (car-safe x) 'intv) (or (Math-posp (nth 2 x))
+					  (not (math-intv-constp x))))
+	 (math-make-intv (nth 1 x)
+			 (calcFunc-lnp1 (nth 2 x))
+			 (calcFunc-lnp1 (nth 3 x))))
+	((math-infinitep x)
+	 (if (equal x '(var nan var-nan))
+	     x
+	   '(var inf var-inf)))
+	(t (calc-record-why 'numberp x)
+	   (list 'calcFunc-lnp1 x)))
+)
+
+(defun math-ln-raw (x)    ; [N N] --- must be float format!
+  (cond ((eq (car-safe x) 'cplx)
+	 (list 'cplx
+	       (math-mul-float (math-ln-raw
+				(math-add-float (math-sqr-float (nth 1 x))
+						(math-sqr-float (nth 2 x))))
+			       '(float 5 -1))
+	       (math-arctan2-raw (nth 2 x) (nth 1 x))))
+	((eq (car x) 'polar)
+	 (math-polar (list 'cplx
+			   (math-ln-raw (nth 1 x))
+			   (math-to-radians (nth 2 x)))))
+	((Math-equal-int x 1)
+	 '(float 0 0))
+	(calc-symbolic-mode (signal 'inexact-result nil))
+	((math-posp (nth 1 x))    ; positive and real
+	 (let ((xdigs (1- (math-numdigs (nth 1 x)))))
+	   (math-add-float (math-ln-raw-2 (list 'float (nth 1 x) (- xdigs)))
+			   (math-mul-float (math-float (+ (nth 2 x) xdigs))
+					   (math-ln-10)))))
+	((math-zerop x)
+	 (math-reject-arg x "*Logarithm of zero"))
+	((eq calc-complex-mode 'polar)    ; negative and real
+	 (math-polar
+	  (list 'cplx   ; negative and real
+		(math-ln-raw (math-neg-float x))
+		(math-pi))))
+	(t (list 'cplx   ; negative and real
+		 (math-ln-raw (math-neg-float x))
+		 (math-pi))))
+)
+
+(defun math-ln-raw-2 (x)    ; [F F]
+  (cond ((math-lessp-float '(float 14 -1) x)
+	 (math-add-float (math-ln-raw-2 (math-mul-float x '(float 5 -1)))
+			 (math-ln-2)))
+	(t    ; now .7 < x <= 1.4
+	 (math-ln-raw-3 (math-div-float (math-sub-float x '(float 1 0))
+					(math-add-float x '(float 1 0))))))
+)
+
+(defun math-ln-raw-3 (x)   ; [F F]
+  (math-mul-float (math-ln-raw-series x 3 x (math-sqr-float x))
+		  '(float 2 0))
+)
+
+;;; Compute ln((1+x)/(1-x))
+(defun math-ln-raw-series (sum n x xsqr)
+  (math-working "log" sum)
+  (let* ((nextx (math-mul-float x xsqr))
+	 (nextsum (math-add-float sum (math-div-float nextx (math-float n)))))
+    (if (math-nearly-equal-float sum nextsum)
+	sum
+      (math-ln-raw-series nextsum (+ n 2) nextx xsqr)))
+)
+
+(defun math-ln-plus-1-raw (x)
+  (math-lnp1-series x 2 x (math-neg x))
+)
+
+(defun math-lnp1-series (sum n xpow x)
+  (math-working "lnp1" sum)
+  (let* ((nextx (math-mul-float xpow x))
+	 (nextsum (math-add-float sum (math-div-float nextx (math-float n)))))
+    (if (math-nearly-equal-float sum nextsum)
+	sum
+      (math-lnp1-series nextsum (1+ n) nextx x)))
+)
+
+(math-defcache math-ln-10 (float (bigpos 018 684 045 994 092 585 302 2) -21)
+  (math-ln-raw-2 '(float 1 1)))
+
+(math-defcache math-ln-2 (float (bigpos 417 309 945 559 180 147 693) -21)
+  (math-ln-raw-3 (math-float '(frac 1 3))))
+
+
+
+;;; Hyperbolic functions.
+
+(defun calcFunc-sinh (x)   ; [N N] [Public]
+  (cond ((eq x 0) 0)
+	(math-expand-formulas
+	 (math-normalize
+	  (list '/ (list '- (list 'calcFunc-exp x)
+			 (list 'calcFunc-exp (list 'neg x))) 2)))
+	((Math-numberp x)
+	 (if calc-symbolic-mode (signal 'inexact-result nil))
+	 (math-with-extra-prec 2
+	   (let ((expx (math-exp-raw (math-float x))))
+	     (math-mul (math-add expx (math-div -1 expx)) '(float 5 -1)))))
+	((eq (car-safe x) 'sdev)
+	 (math-make-sdev (calcFunc-sinh (nth 1 x))
+			 (math-mul (nth 2 x) (calcFunc-cosh (nth 1 x)))))
+	((eq (car x) 'intv)
+	 (math-sort-intv (nth 1 x)
+			 (calcFunc-sinh (nth 2 x))
+			 (calcFunc-sinh (nth 3 x))))
+	((or (equal x '(var inf var-inf))
+	     (equal x '(neg (var inf var-inf)))
+	     (equal x '(var nan var-nan)))
+	 x)
+	(t (calc-record-why 'numberp x)
+	   (list 'calcFunc-sinh x)))
+)
+(put 'calcFunc-sinh 'math-expandable t)
+
+(defun calcFunc-cosh (x)   ; [N N] [Public]
+  (cond ((eq x 0) 1)
+	(math-expand-formulas
+	 (math-normalize
+	  (list '/ (list '+ (list 'calcFunc-exp x)
+			 (list 'calcFunc-exp (list 'neg x))) 2)))
+	((Math-numberp x)
+	 (if calc-symbolic-mode (signal 'inexact-result nil))
+	 (math-with-extra-prec 2
+	   (let ((expx (math-exp-raw (math-float x))))
+	     (math-mul (math-add expx (math-div 1 expx)) '(float 5 -1)))))
+	((eq (car-safe x) 'sdev)
+	 (math-make-sdev (calcFunc-cosh (nth 1 x))
+			 (math-mul (nth 2 x)
+				   (calcFunc-sinh (nth 1 x)))))
+	((and (eq (car x) 'intv) (math-intv-constp x))
+	 (setq x (math-abs x))
+	 (math-sort-intv (nth 1 x)
+			 (calcFunc-cosh (nth 2 x))
+			 (calcFunc-cosh (nth 3 x))))
+	((or (equal x '(var inf var-inf))
+	     (equal x '(neg (var inf var-inf)))
+	     (equal x '(var nan var-nan)))
+	 (math-abs x))
+	(t (calc-record-why 'numberp x)
+	   (list 'calcFunc-cosh x)))
+)
+(put 'calcFunc-cosh 'math-expandable t)
+
+(defun calcFunc-tanh (x)   ; [N N] [Public]
+  (cond ((eq x 0) 0)
+	(math-expand-formulas
+	 (math-normalize
+	  (let ((expx (list 'calcFunc-exp x))
+		(expmx (list 'calcFunc-exp (list 'neg x))))
+	    (math-normalize
+	     (list '/ (list '- expx expmx) (list '+ expx expmx))))))
+	((Math-numberp x)
+	 (if calc-symbolic-mode (signal 'inexact-result nil))
+	 (math-with-extra-prec 2
+	   (let* ((expx (calcFunc-exp (math-float x)))
+		  (expmx (math-div 1 expx)))
+	     (math-div (math-sub expx expmx)
+		       (math-add expx expmx)))))
+	((eq (car-safe x) 'sdev)
+	 (math-make-sdev (calcFunc-tanh (nth 1 x))
+			 (math-div (nth 2 x)
+				   (math-sqr (calcFunc-cosh (nth 1 x))))))
+	((eq (car x) 'intv)
+	 (math-sort-intv (nth 1 x)
+			 (calcFunc-tanh (nth 2 x))
+			 (calcFunc-tanh (nth 3 x))))
+	((equal x '(var inf var-inf))
+	 1)
+	((equal x '(neg (var inf var-inf)))
+	 -1)
+	((equal x '(var nan var-nan))
+	 x)
+	(t (calc-record-why 'numberp x)
+	   (list 'calcFunc-tanh x)))
+)
+(put 'calcFunc-tanh 'math-expandable t)
+
+(defun calcFunc-arcsinh (x)   ; [N N] [Public]
+  (cond ((eq x 0) 0)
+	(math-expand-formulas
+	 (math-normalize
+	  (list 'calcFunc-ln (list '+ x (list 'calcFunc-sqrt
+					      (list '+ (list '^ x 2) 1))))))
+	((Math-numberp x)
+	 (if calc-symbolic-mode (signal 'inexact-result nil))
+	 (math-with-extra-prec 2
+	   (math-ln-raw (math-add x (math-sqrt-raw (math-add (math-sqr x)
+							     '(float 1 0)))))))
+	((eq (car-safe x) 'sdev)
+	 (math-make-sdev (calcFunc-arcsinh (nth 1 x))
+			 (math-div (nth 2 x)
+				   (math-sqrt
+				    (math-add (math-sqr (nth 1 x)) 1)))))
+	((eq (car x) 'intv)
+	 (math-sort-intv (nth 1 x)
+			 (calcFunc-arcsinh (nth 2 x))
+			 (calcFunc-arcsinh (nth 3 x))))
+	((or (equal x '(var inf var-inf))
+	     (equal x '(neg (var inf var-inf)))
+	     (equal x '(var nan var-nan)))
+	 x)
+	(t (calc-record-why 'numberp x)
+	   (list 'calcFunc-arcsinh x)))
+)
+(put 'calcFunc-arcsinh 'math-expandable t)
+
+(defun calcFunc-arccosh (x)   ; [N N] [Public]
+  (cond ((eq x 1) 0)
+	((and (eq x -1) calc-symbolic-mode)
+	 '(var pi var-pi))
+	((and (eq x 0) calc-symbolic-mode)
+	 (math-div (math-mul '(var pi var-pi) '(var i var-i)) 2))
+	(math-expand-formulas
+	 (math-normalize
+	  (list 'calcFunc-ln (list '+ x (list 'calcFunc-sqrt
+					      (list '- (list '^ x 2) 1))))))
+	((Math-numberp x)
+	 (if calc-symbolic-mode (signal 'inexact-result nil))
+	 (if (Math-equal-int x -1)
+	     (math-imaginary (math-pi))
+	   (math-with-extra-prec 2
+	     (if (or t    ; need to do this even in the real case!
+		     (memq (car-safe x) '(cplx polar)))
+		 (let ((xp1 (math-add 1 x)))  ; this gets the branch cuts right
+		   (math-ln-raw
+		    (math-add x (math-mul xp1
+					  (math-sqrt-raw
+					   (math-div (math-sub
+						      x
+						      '(float 1 0))
+						     xp1))))))
+	       (math-ln-raw
+		(math-add x (math-sqrt-raw (math-add (math-sqr x)
+						     '(float -1 0)))))))))
+	((eq (car-safe x) 'sdev)
+	 (math-make-sdev (calcFunc-arccosh (nth 1 x))
+			 (math-div (nth 2 x)
+				   (math-sqrt
+				    (math-add (math-sqr (nth 1 x)) -1)))))
+	((eq (car x) 'intv)
+	 (math-sort-intv (nth 1 x)
+			 (calcFunc-arccosh (nth 2 x))
+			 (calcFunc-arccosh (nth 3 x))))
+	((or (equal x '(var inf var-inf))
+	     (equal x '(neg (var inf var-inf)))
+	     (equal x '(var nan var-nan)))
+	 x)
+	(t (calc-record-why 'numberp x)
+	   (list 'calcFunc-arccosh x)))
+)
+(put 'calcFunc-arccosh 'math-expandable t)
+
+(defun calcFunc-arctanh (x)   ; [N N] [Public]
+  (cond ((eq x 0) 0)
+	((and (Math-equal-int x 1) calc-infinite-mode)
+	 '(var inf var-inf))
+	((and (Math-equal-int x -1) calc-infinite-mode)
+	 '(neg (var inf var-inf)))
+	(math-expand-formulas
+	 (list '/ (list '-
+			(list 'calcFunc-ln (list '+ 1 x))
+			(list 'calcFunc-ln (list '- 1 x))) 2))
+	((Math-numberp x)
+	 (if calc-symbolic-mode (signal 'inexact-result nil))
+	 (math-with-extra-prec 2
+	   (if (or (memq (car-safe x) '(cplx polar))
+		   (Math-lessp 1 x))
+	       (math-mul (math-sub (math-ln-raw (math-add '(float 1 0) x))
+				   (math-ln-raw (math-sub '(float 1 0) x)))
+			 '(float 5 -1))
+	     (if (and (math-equal-int x 1) calc-infinite-mode)
+		 '(var inf var-inf)
+	       (if (and (math-equal-int x -1) calc-infinite-mode)
+		   '(neg (var inf var-inf))
+		 (math-mul (math-ln-raw (math-div (math-add '(float 1 0) x)
+						  (math-sub 1 x)))
+			   '(float 5 -1)))))))
+	((eq (car-safe x) 'sdev)
+	 (math-make-sdev (calcFunc-arctanh (nth 1 x))
+			 (math-div (nth 2 x)
+				   (math-sub 1 (math-sqr (nth 1 x))))))
+	((eq (car x) 'intv)
+	 (math-sort-intv (nth 1 x)
+			 (calcFunc-arctanh (nth 2 x))
+			 (calcFunc-arctanh (nth 3 x))))
+	((equal x '(var nan var-nan))
+	 x)
+	(t (calc-record-why 'numberp x)
+	   (list 'calcFunc-arctanh x)))
+)
+(put 'calcFunc-arctanh 'math-expandable t)
+
+
+;;; Convert A from HMS or degrees to radians.
+(defun calcFunc-rad (a)   ; [R R] [Public]
+  (cond ((or (Math-numberp a)
+	     (eq (car a) 'intv))
+	 (math-with-extra-prec 2
+	   (math-mul a (math-pi-over-180))))
+	((eq (car a) 'hms)
+	 (math-from-hms a 'rad))
+	((eq (car a) 'sdev)
+	 (math-make-sdev (calcFunc-rad (nth 1 a))
+			 (calcFunc-rad (nth 2 a))))
+	(math-expand-formulas
+	 (math-div (math-mul a '(var pi var-pi)) 180))
+	((math-infinitep a) a)
+	(t (list 'calcFunc-rad a)))
+)
+(put 'calcFunc-rad 'math-expandable t)
+
+;;; Convert A from HMS or radians to degrees.
+(defun calcFunc-deg (a)   ; [R R] [Public]
+  (cond ((or (Math-numberp a)
+	     (eq (car a) 'intv))
+	 (math-with-extra-prec 2
+	   (math-div a (math-pi-over-180))))
+	((eq (car a) 'hms)
+	 (math-from-hms a 'deg))
+	((eq (car a) 'sdev)
+	 (math-make-sdev (calcFunc-deg (nth 1 a))
+			 (calcFunc-deg (nth 2 a))))
+	(math-expand-formulas
+	 (math-div (math-mul 180 a) '(var pi var-pi)))
+	((math-infinitep a) a)
+	(t (list 'calcFunc-deg a)))
+)
+(put 'calcFunc-deg 'math-expandable t)
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/calc-misc.el	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,877 @@
+;; Calculator for GNU Emacs, part I [calc-misc.el]
+;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+;; Written by Dave Gillespie, daveg@synaptics.com.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY.  No author or distributor
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing.  Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License.   A copy of this license is
+;; supposed to have been given to you along with GNU Emacs so you
+;; can know your rights and responsibilities.  It should be in a
+;; file named COPYING.  Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+
+
+
+;; This file is autoloaded from calc.el.
+(require 'calc)
+
+(require 'calc-macs)
+
+(defun calc-Need-calc-misc () nil)
+
+
+(defun calc-dispatch-help (arg)
+  "M-# is a prefix key; follow it with one of these letters:
+
+For turning Calc on and off:
+  C  calc.  Start the Calculator in a window at the bottom of the screen.
+  O  calc-other-window.  Start the Calculator but don't select its window.
+  B  calc-big-or-small.  Control whether to use the full Emacs screen for Calc.
+  Q  quick-calc.  Use the Calculator in the minibuffer.
+  K  calc-keypad.  Start the Calculator in keypad mode (X window system only).
+  E  calc-embedded.  Use the Calculator on a formula in this editing buffer.
+  J  calc-embedded-select.  Like E, but select appropriate half of => or :=.
+  W  calc-embedded-word.  Like E, but activate a single word, i.e., a number.
+  Z  calc-user-invocation.  Invoke Calc in the way you defined with `Z I' cmd.
+  X  calc-quit.  Turn Calc off.
+
+For moving data into and out of Calc:
+  G  calc-grab-region.  Grab the region defined by mark and point into Calc.
+  R  calc-grab-rectangle.  Grab the rectangle defined by mark, point into Calc.
+  :  calc-grab-sum-down.  Grab a rectangle and sum the columns.
+  _  calc-grab-sum-across.  Grab a rectangle and sum the rows.
+  Y  calc-copy-to-buffer.  Copy a value from the stack into the editing buffer.
+
+For use with Embedded mode:
+  A  calc-embedded-activate.  Find and activate all :='s and =>'s in buffer.
+  D  calc-embedded-duplicate.  Make a copy of this formula and select it.
+  F  calc-embedded-new-formula.  Insert a new formula at current point.
+  N  calc-embedded-next.  Advance cursor to next known formula in buffer.
+  P  calc-embedded-previous.  Advance cursor to previous known formula.
+  U  calc-embedded-update-formula.  Re-evaluate formula at point.
+  `  calc-embedded-edit.  Use calc-edit to edit formula at point.
+
+Documentation:
+  I  calc-info.  Read the Calculator manual in the Emacs Info system.
+  T  calc-tutorial.  Run the Calculator Tutorial using the Emacs Info system.
+  S  calc-summary.  Read the Summary from the Calculator manual in Info.
+
+Miscellaneous:
+  L  calc-load-everything.  Load all parts of the Calculator into memory.
+  M  read-kbd-macro.  Read a region of keystroke names as a keyboard macro.
+  0  (zero) calc-reset.  Reset Calc stack and modes to default state.
+
+Press twice (`M-# M-#' or `M-# #') to turn Calc on or off using the same
+Calc user interface as before (either M-# C or M-# K; initially M-# C)."
+  (interactive "P")
+  (calc-check-defines)
+  (if calc-dispatch-help
+      (progn
+	(save-window-excursion
+	  (describe-function 'calc-dispatch-help)
+	  (let ((win (get-buffer-window "*Help*")))
+	    (if win
+		(let (key)
+		  (select-window win)
+		  (while (progn
+			   (message "Calc options: Calc, Keypad, ...  %s"
+				    "press SPC, DEL to scroll, C-g to cancel")
+			   (memq (car (setq key (calc-read-key t)))
+				 '(?  ?\C-h ?\C-? ?\C-v ?\M-v)))
+		    (condition-case err
+			(if (memq (car key) '(?  ?\C-v))
+			    (scroll-up)
+			  (scroll-down))
+		      (error (beep))))
+		      (calc-unread-command (cdr key))))))
+	(calc-do-dispatch nil))
+    (let ((calc-dispatch-help t))
+      (calc-do-dispatch arg)))
+)
+
+
+(defun calc-big-or-small (arg)
+  "Toggle Calc between full-screen and regular mode."
+  (interactive "P")
+  (let ((cwin (get-buffer-window "*Calculator*"))
+	(twin (get-buffer-window "*Calc Trail*"))
+	(kwin (get-buffer-window "*Calc Keypad*")))
+    (if cwin
+	(setq calc-full-mode
+	      (if kwin
+		  (and twin (eq (window-width twin) (screen-width)))
+		(eq (window-height cwin) (1- (screen-height))))))
+    (setq calc-full-mode (if arg
+			     (> (prefix-numeric-value arg) 0)
+			   (not calc-full-mode)))
+    (if kwin
+	(progn
+	  (calc-quit)
+	  (calc-do-keypad calc-full-mode nil))
+      (if cwin
+	  (progn
+	    (calc-quit)
+	    (calc nil calc-full-mode nil))))
+    (message (if calc-full-mode
+		 "Now using full screen for Calc."
+	       "Now using partial screen for Calc.")))
+)
+
+(defun calc-other-window ()
+  "Invoke the Calculator in another window."
+  (interactive)
+  (if (memq major-mode '(calc-mode calc-trail-mode))
+      (progn
+	(other-window 1)
+	(if (memq major-mode '(calc-mode calc-trail-mode))
+	    (other-window 1)))
+    (if (get-buffer-window "*Calculator*")
+	(calc-quit)
+      (let ((win (selected-window)))
+	(calc nil win (interactive-p)))))
+)
+
+(defun another-calc ()
+  "Create another, independent Calculator buffer."
+  (interactive)
+  (if (eq major-mode 'calc-mode)
+      (mapcar (function
+	       (lambda (v)
+		 (set-default v (symbol-value v)))) calc-local-var-list))
+  (set-buffer (generate-new-buffer "*Calculator*"))
+  (pop-to-buffer (current-buffer))
+  (calc-mode)
+)
+
+
+;;; Make an attempt to preserve the window configuration, while deleting
+;;; windows on "bufs".  Emacs 19's delete-window function will probably
+;;; make this kludgery unnecessary, but Emacs 18's tendency to grow all
+;;; windows on the screen to take up the slack from the deleted windows
+;;; can be annoying when Calc was called during another multi-window
+;;; application, such as GNUS.
+
+(defun calc-delete-windows-keep (&rest bufs)
+  (if (one-window-p)
+      (mapcar 'delete-windows-on bufs)
+    (let* ((w (car calc-was-split))
+	   (e (window-edges w))
+	   (wins nil)
+	   w2 e2)
+      (while (progn
+	       (setq w2 (previous-window w)
+		     e2 (window-edges w2))
+	       (and (= (car e2) (car e))
+		    (= (nth 2 e2) (nth 2 e))
+		    (< (nth 1 e2) (nth 1 e))))
+	(setq w w2 e e2))
+      (setq w2 w e2 e)
+      (while (progn
+	       (setq wins (cons (list w (nth 1 e) (window-buffer w)
+				      (window-point w) (window-start w))
+				wins)
+		     w (next-window w)
+		     e (window-edges w))
+	       (and (not (eq w w2))
+		    (= (car e2) (car e))
+		    (= (nth 2 e2) (nth 2 e)))))
+      (setq wins (nreverse wins))
+      (mapcar 'delete-windows-on bufs)
+      (or (one-window-p)
+	  (let ((w wins)
+		(main nil)
+		(mainpos 0)
+		(sel (if (window-point (nth 2 calc-was-split))
+			 (nth 2 calc-was-split)
+		       (selected-window))))
+	    (while w
+	      (if (window-point (car (car w)))
+		  (if main
+		      (delete-window (car (car w)))
+		    (setq main (car (car w))
+			  mainpos (nth 1 (car w))
+			  wins (cdr wins)))
+		(setq wins (delq (car w) wins)))
+	      (setq w (cdr w)))
+	    (while wins
+	      (setq w (split-window main
+				    (if (eq main (car calc-was-split))
+					(nth 1 calc-was-split)
+				      (- (nth 1 (car wins)) mainpos))))
+	      (set-window-buffer w (nth 2 (car wins)))
+	      (set-window-point w (nth 3 (car wins)))
+	      (set-window-start w (nth 4 (car wins)))
+	      (if (eq sel (car (car wins)))
+		  (select-window w))
+	      (setq main w
+		    mainpos (nth 1 (car wins))
+		    wins (cdr wins)))
+	    (if (window-point sel)
+		(select-window sel))))))
+)
+
+
+(defun calc-info ()
+  "Run the Emacs Info system on the Calculator documentation."
+  (interactive)
+  (require 'info)
+  (select-window (get-largest-window))
+  (or (file-name-absolute-p calc-info-filename)
+       (let ((p load-path)
+	     name)
+	 (if (boundp 'Info-directory)
+	     (setq p (cons Info-directory p)))
+	 (while (and p (not (file-exists-p
+			     (setq name (expand-file-name calc-info-filename
+							  (car p))))))
+	   (setq p (cdr p)))
+	 (if p (setq calc-info-filename name))))
+  (condition-case err
+      (info)
+    (error nil))
+  (or (and (boundp 'Info-current-file)
+	   (stringp Info-current-file)
+	   (string-match "calc" Info-current-file))
+      (Info-find-node calc-info-filename "Top"))
+)
+
+(defun calc-tutorial ()
+  "Run the Emacs Info system on the Calculator Tutorial."
+  (interactive)
+  (if (get-buffer-window "*Calculator*")
+      (calc-quit))
+  (calc-info)
+  (Info-goto-node "Interactive Tutorial")
+  (calc-other-window)
+  (message "Welcome to the Calc Tutorial!")
+)
+
+(defun calc-info-summary ()
+  "Run the Emacs Info system on the Calculator Summary."
+  (interactive)
+  (calc-info)
+  (Info-goto-node "Summary")
+)
+
+(defun calc-help ()
+  (interactive)
+  (let ((msgs (append
+	 '("Press `h' for complete help; press `?' repeatedly for a summary"
+	   "Letter keys: Negate; Precision; Yank; Why; Xtended cmd; Quit"
+	   "Letter keys: SHIFT + Undo, reDo; Keep-args; Inverse, Hyperbolic"
+	   "Letter keys: SHIFT + sQrt; Sin, Cos, Tan; Exp, Ln, logB"
+	   "Letter keys: SHIFT + Floor, Round; Abs, conJ, arG; Pi"
+	   "Letter keys: SHIFT + Num-eval; More-recn; eXec-kbd-macro"
+	   "Other keys: +, -, *, /, ^, \\ (int div), : (frac div)"
+	   "Other keys: & (1/x), | (concat), % (modulo), ! (factorial)"
+	   "Other keys: ' (alg-entry), = (eval), ` (edit); M-RET (last-args)"
+	   "Other keys: SPC/RET (enter/dup), LFD (over); < > (scroll horiz)"
+	   "Other keys: DEL (drop), M-DEL (drop-above); { } (scroll vert)"
+	   "Other keys: TAB (swap/roll-dn), M-TAB (roll-up)"
+	   "Other keys: [ , ; ] (vector), ( , ) (complex), ( ; ) (polar)"
+	   "Prefix keys: Algebra, Binary/business, Convert, Display"
+	   "Prefix keys: Functions, Graphics, Help, J (select)"
+	   "Prefix keys: Kombinatorics/statistics, Modes, Store/recall"
+	   "Prefix keys: Trail/time, Units/statistics, Vector/matrix"
+	   "Prefix keys: Z (user), SHIFT + Z (define)"
+	   "Prefix keys: prefix + ? gives further help for that prefix")
+	 (list (format
+		"  Calc %s by Dave Gillespie, daveg@synaptics.com"
+		calc-version)))))
+    (if calc-full-help-flag
+	msgs
+      (if (or calc-inverse-flag calc-hyperbolic-flag)
+	  (if calc-inverse-flag
+	      (if calc-hyperbolic-flag
+		  (calc-inv-hyp-prefix-help)
+		(calc-inverse-prefix-help))
+	    (calc-hyperbolic-prefix-help))
+	(setq calc-help-phase
+	      (if (eq this-command last-command)
+		  (% (1+ calc-help-phase) (1+ (length msgs)))
+		0))
+	(let ((msg (nth calc-help-phase msgs)))
+	  (message "%s" (if msg
+			    (concat msg ":"
+				    (make-string (- (apply 'max
+							   (mapcar 'length
+								   msgs))
+						    (length msg)) 32)
+				    "  [?=MORE]")
+			  ""))))))
+)
+
+
+
+
+;;;; Stack and buffer management.
+
+
+(defun calc-do-handle-whys ()
+  (setq calc-why (sort calc-next-why
+		       (function
+			(lambda (x y)
+			  (and (eq (car x) '*) (not (eq (car y) '*))))))
+	calc-next-why nil)
+  (if (and calc-why (or (eq calc-auto-why t)
+			(and (eq (car (car calc-why)) '*)
+			     calc-auto-why)))
+      (progn
+	(calc-extensions)
+	(calc-explain-why (car calc-why)
+			  (if (eq calc-auto-why t)
+			      (cdr calc-why)
+			    (if calc-auto-why
+				(eq (car (nth 1 calc-why)) '*))))
+	(setq calc-last-why-command this-command)
+	(calc-clear-command-flag 'clear-message)))
+)
+
+(defun calc-record-why (&rest stuff)
+  (if (eq (car stuff) 'quiet)
+      (setq stuff (cdr stuff))
+    (if (and (symbolp (car stuff))
+	     (cdr stuff)
+	     (or (Math-objectp (nth 1 stuff))
+		 (and (Math-vectorp (nth 1 stuff))
+		      (math-constp (nth 1 stuff)))
+		 (math-infinitep (nth 1 stuff))))
+	(setq stuff (cons '* stuff))
+      (if (and (stringp (car stuff))
+	       (string-match "\\`\\*" (car stuff)))
+	  (setq stuff (cons '* (cons (substring (car stuff) 1)
+				     (cdr stuff)))))))
+  (setq calc-next-why (cons stuff calc-next-why))
+  nil
+)
+
+;;; True if A is a constant or vector of constants.  [P x] [Public]
+(defun math-constp (a)
+  (or (Math-scalarp a)
+      (and (memq (car a) '(sdev intv mod vec))
+	   (progn
+	     (while (and (setq a (cdr a))
+			 (or (Math-scalarp (car a))  ; optimization
+			     (math-constp (car a)))))
+	     (null a))))
+)
+
+
+(defun calc-roll-down-stack (n &optional m)
+  (if (< n 0)
+      (calc-roll-up-stack (- n) m)
+    (if (or (= n 0) (> n (calc-stack-size))) (setq n (calc-stack-size)))
+    (or m (setq m 1))
+    (and (> n 1)
+	 (< m n)
+	 (if (and calc-any-selections
+		  (not calc-use-selections))
+	     (calc-roll-down-with-selections n m)
+	   (calc-pop-push-list n
+			       (append (calc-top-list m 1)
+				       (calc-top-list (- n m) (1+ m)))))))
+)
+
+(defun calc-roll-up-stack (n &optional m)
+  (if (< n 0)
+      (calc-roll-down-stack (- n) m)
+    (if (or (= n 0) (> n (calc-stack-size))) (setq n (calc-stack-size)))
+    (or m (setq m 1))
+    (and (> n 1)
+	 (< m n)
+	 (if (and calc-any-selections
+		  (not calc-use-selections))
+	     (calc-roll-up-with-selections n m)
+	   (calc-pop-push-list n
+			       (append (calc-top-list (- n m) 1)
+				       (calc-top-list m (- n m -1)))))))
+)
+
+
+(defun calc-do-refresh ()
+  (if calc-hyperbolic-flag
+      (progn
+	(setq calc-display-dirty t)
+	nil)
+    (calc-refresh)
+    t)
+)
+
+
+(defun calc-record-list (vals &optional prefix)
+  (while vals
+    (or (eq (car vals) 'top-of-stack)
+	(progn
+	  (calc-record (car vals) prefix)
+	  (setq prefix "...")))
+    (setq vals (cdr vals)))
+)
+
+
+(defun calc-last-args-stub (arg)
+  (interactive "p")
+  (calc-extensions)
+  (calc-last-args arg)
+)
+
+
+(defun calc-power (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (if (and calc-extensions-loaded
+	    (calc-is-inverse))
+       (calc-binary-op "root" 'calcFunc-nroot arg nil nil)
+     (calc-binary-op "^" 'calcFunc-pow arg nil nil '^)))
+)
+
+(defun calc-mod (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-binary-op "%" 'calcFunc-mod arg nil nil '%))
+)
+
+(defun calc-inv (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-unary-op "inv" 'calcFunc-inv arg))
+)
+
+(defun calc-percent ()
+  (interactive)
+  (calc-slow-wrapper
+   (calc-pop-push-record-list
+    1 "%" (list (list 'calcFunc-percent (calc-top-n 1)))))
+)
+
+
+(defun calc-over (n)
+  (interactive "P")
+  (if n
+      (calc-enter (- (prefix-numeric-value n)))
+    (calc-enter -2))
+)
+
+
+(defun calc-pop-above (n)
+  (interactive "P")
+  (if n
+      (calc-pop (- (prefix-numeric-value n)))
+    (calc-pop -2))
+)
+
+(defun calc-roll-down (n)
+  (interactive "P")
+  (calc-wrapper
+   (let ((nn (prefix-numeric-value n)))
+     (cond ((null n)
+	    (calc-roll-down-stack 2))
+	   ((> nn 0)
+	    (calc-roll-down-stack nn))
+	   ((= nn 0)
+	    (calc-pop-push-list (calc-stack-size)
+				(reverse
+				 (calc-top-list (calc-stack-size)))))
+	   (t
+	    (calc-roll-down-stack (calc-stack-size) (- nn))))))
+)
+
+(defun calc-roll-up (n)
+  (interactive "P")
+  (calc-wrapper
+   (let ((nn (prefix-numeric-value n)))
+     (cond ((null n)
+	    (calc-roll-up-stack 3))
+	   ((> nn 0)
+	    (calc-roll-up-stack nn))
+	   ((= nn 0)
+	    (calc-pop-push-list (calc-stack-size)
+				(reverse
+				 (calc-top-list (calc-stack-size)))))
+	   (t
+	    (calc-roll-up-stack (calc-stack-size) (- nn))))))
+)
+
+
+
+
+;;; Other commands.
+
+(defun calc-num-prefix-name (n)
+  (cond ((eq n '-) "- ")
+	((equal n '(4)) "C-u ")
+	((consp n) (format "%d " (car n)))
+	((integerp n) (format "%d " n))
+	(t ""))
+)
+
+(defun calc-missing-key (n)
+  "This is a placeholder for a command which needs to be loaded from calc-ext.
+When this key is used, calc-ext (the Calculator extensions module) will be
+loaded and the keystroke automatically re-typed."
+  (interactive "P")
+  (calc-extensions)
+  (if (keymapp (key-binding (char-to-string last-command-char)))
+      (message "%s%c-" (calc-num-prefix-name n) last-command-char))
+  (calc-unread-command)
+  (setq prefix-arg n)
+)
+
+(defun calc-shift-Y-prefix-help ()
+  (interactive)
+  (calc-extensions)
+  (calc-do-prefix-help calc-Y-help-msgs "other" ?Y)
+)
+
+
+
+
+(defun calcDigit-letter ()
+  (interactive)
+  (if (calc-minibuffer-contains "[-+]?\\(1[1-9]\\|[2-9][0-9]\\)#.*")
+      (progn
+	(setq last-command-char (upcase last-command-char))
+	(calcDigit-key))
+    (calcDigit-nondigit))
+)
+
+
+;; A Lisp version of temp_minibuffer_message from minibuf.c.
+(defun calc-temp-minibuffer-message (m)
+  (let ((savemax (point-max)))
+    (save-excursion
+      (goto-char (point-max))
+      (insert m))
+    (let ((okay nil))
+      (unwind-protect
+	  (progn
+	    (sit-for 2)
+	    (identity 1)   ; this forces a call to QUIT; in bytecode.c.
+	    (setq okay t))
+	(progn
+	  (delete-region savemax (point-max))
+	  (or okay (abort-recursive-edit))))))
+)
+
+
+(put 'math-with-extra-prec 'lisp-indent-hook 1)
+
+
+;;; Concatenate two vectors, or a vector and an object.  [V O O] [Public]
+(defun math-concat (v1 v2)
+  (if (stringp v1)
+      (concat v1 v2)
+    (calc-extensions)
+    (if (and (or (math-objvecp v1) (math-known-scalarp v1))
+	     (or (math-objvecp v2) (math-known-scalarp v2)))
+	(append (if (and (math-vectorp v1)
+			 (or (math-matrixp v1)
+			     (not (math-matrixp v2))))
+		    v1
+		  (list 'vec v1))
+		(if (and (math-vectorp v2)
+			 (or (math-matrixp v2)
+			     (not (math-matrixp v1))))
+		    (cdr v2)
+		  (list v2)))
+      (list '| v1 v2)))
+)
+
+
+;;; True if A is zero.  Works for un-normalized values.  [P n] [Public]
+(defun math-zerop (a)
+  (if (consp a)
+      (cond ((memq (car a) '(bigpos bigneg))
+	     (while (eq (car (setq a (cdr a))) 0))
+	     (null a))
+	    ((memq (car a) '(frac float polar mod))
+	     (math-zerop (nth 1 a)))
+	    ((eq (car a) 'cplx)
+	     (and (math-zerop (nth 1 a)) (math-zerop (nth 2 a))))
+	    ((eq (car a) 'hms)
+	     (and (math-zerop (nth 1 a))
+		  (math-zerop (nth 2 a))
+		  (math-zerop (nth 3 a)))))
+    (eq a 0))
+)
+
+
+;;; True if A is real and negative.  [P n] [Public]
+
+(defun math-negp (a)
+  (if (consp a)
+      (cond ((eq (car a) 'bigpos) nil)
+	    ((eq (car a) 'bigneg) (cdr a))
+	    ((memq (car a) '(float frac))
+	     (Math-integer-negp (nth 1 a)))
+	    ((eq (car a) 'hms)
+	     (if (math-zerop (nth 1 a))
+		 (if (math-zerop (nth 2 a))
+		     (math-negp (nth 3 a))
+		   (math-negp (nth 2 a)))
+	       (math-negp (nth 1 a))))
+	    ((eq (car a) 'date)
+	     (math-negp (nth 1 a)))
+	    ((eq (car a) 'intv)
+	     (or (math-negp (nth 3 a))
+		 (and (math-zerop (nth 3 a))
+		      (memq (nth 1 a) '(0 2)))))
+	    ((equal a '(neg (var inf var-inf))) t))
+    (< a 0))
+)
+
+;;; True if A is a negative number or an expression the starts with '-'.
+(defun math-looks-negp (a)   ; [P x] [Public]
+  (or (Math-negp a)
+      (eq (car-safe a) 'neg)
+      (and (memq (car-safe a) '(* /))
+	   (or (math-looks-negp (nth 1 a))
+	       (math-looks-negp (nth 2 a))))
+      (and (eq (car-safe a) '-)
+	   (math-looks-negp (nth 1 a))))
+)
+
+
+;;; True if A is real and positive.  [P n] [Public]
+(defun math-posp (a)
+  (if (consp a)
+      (cond ((eq (car a) 'bigpos) (cdr a))
+	    ((eq (car a) 'bigneg) nil)
+	    ((memq (car a) '(float frac))
+	     (Math-integer-posp (nth 1 a)))
+	    ((eq (car a) 'hms)
+	     (if (math-zerop (nth 1 a))
+		 (if (math-zerop (nth 2 a))
+		     (math-posp (nth 3 a))
+		   (math-posp (nth 2 a)))
+	       (math-posp (nth 1 a))))
+	    ((eq (car a) 'date)
+	     (math-posp (nth 1 a)))
+	    ((eq (car a) 'mod)
+	     (not (math-zerop (nth 1 a))))
+	    ((eq (car a) 'intv)
+	     (or (math-posp (nth 2 a))
+		 (and (math-zerop (nth 2 a))
+		      (memq (nth 1 a) '(0 1)))))
+	    ((equal a '(var inf var-inf)) t))
+    (> a 0))
+)
+
+(fset 'math-fixnump (symbol-function 'integerp))
+(fset 'math-fixnatnump (symbol-function 'natnump))
+
+
+;;; True if A is an even integer.  [P R R] [Public]
+(defun math-evenp (a)
+  (if (consp a)
+      (and (memq (car a) '(bigpos bigneg))
+	   (= (% (nth 1 a) 2) 0))
+    (= (% a 2) 0))
+)
+
+;;; Compute A / 2, for small or big integer A.  [I i]
+;;; If A is negative, type of truncation is undefined.
+(defun math-div2 (a)
+  (if (consp a)
+      (if (cdr a)
+	  (math-normalize (cons (car a) (math-div2-bignum (cdr a))))
+	0)
+    (/ a 2))
+)
+
+(defun math-div2-bignum (a)   ; [l l]
+  (if (cdr a)
+      (cons (+ (/ (car a) 2) (* (% (nth 1 a) 2) 500))
+	    (math-div2-bignum (cdr a)))
+    (list (/ (car a) 2)))
+)
+
+
+;;; Reject an argument to a calculator function.  [Public]
+(defun math-reject-arg (&optional a p option)
+  (if option
+      (calc-record-why option p a)
+    (if p
+	(calc-record-why p a)))
+  (signal 'wrong-type-argument (and a (if p (list p a) (list a))))
+)
+
+
+;;; Coerce A to be an integer (by truncation toward zero).  [I N] [Public]
+(defun math-trunc (a &optional prec)
+  (cond (prec
+	 (calc-extensions)
+	 (math-trunc-special a prec))
+	((Math-integerp a) a)
+	((Math-looks-negp a)
+	 (math-neg (math-trunc (math-neg a))))
+	((eq (car a) 'float)
+	 (math-scale-int (nth 1 a) (nth 2 a)))
+	(t (calc-extensions)
+	   (math-trunc-fancy a)))
+)
+(fset 'calcFunc-trunc (symbol-function 'math-trunc))
+
+;;; Coerce A to be an integer (by truncation toward minus infinity).  [I N]
+(defun math-floor (a &optional prec)    ;  [Public]
+  (cond (prec
+	 (calc-extensions)
+	 (math-floor-special a prec))
+	((Math-integerp a) a)
+	((Math-messy-integerp a) (math-trunc a))
+	((Math-realp a)
+	 (if (Math-negp a)
+	     (math-add (math-trunc a) -1)
+	   (math-trunc a)))
+	(t (calc-extensions)
+	   (math-floor-fancy a)))
+)
+(fset 'calcFunc-floor (symbol-function 'math-floor))
+
+
+(defun math-imod (a b)   ; [I I I] [Public]
+  (if (and (not (consp a)) (not (consp b)))
+      (if (= b 0)
+	  (math-reject-arg a "*Division by zero")
+	(% a b))
+    (cdr (math-idivmod a b)))
+)
+
+
+(defun calcFunc-inv (m)
+  (if (Math-vectorp m)
+      (progn
+	(calc-extensions)
+	(if (math-square-matrixp m)
+	    (or (math-with-extra-prec 2 (math-matrix-inv-raw m))
+		(math-reject-arg m "*Singular matrix"))
+	  (math-reject-arg m 'square-matrixp)))
+    (math-div 1 m))
+)
+
+
+(defun math-do-working (msg arg)
+  (or executing-macro
+      (progn
+	(calc-set-command-flag 'clear-message)
+	(if math-working-step
+	    (if math-working-step-2
+		(setq msg (format "[%d/%d] %s"
+				  math-working-step math-working-step-2 msg))
+	      (setq msg (format "[%d] %s" math-working-step msg))))
+	(message "Working... %s = %s" msg
+		 (math-showing-full-precision (math-format-number arg)))))
+)
+
+
+;;; Compute A modulo B, defined in terms of truncation toward minus infinity.
+(defun math-mod (a b)   ; [R R R] [Public]
+  (cond ((and (Math-zerop a) (not (eq (car-safe a) 'mod))) a)
+	((Math-zerop b)
+	 (math-reject-arg a "*Division by zero"))
+	((and (Math-natnump a) (Math-natnump b))
+	 (math-imod a b))
+	((and (Math-anglep a) (Math-anglep b))
+	 (math-sub a (math-mul (math-floor (math-div a b)) b)))
+	(t (calc-extensions)
+	   (math-mod-fancy a b)))
+)
+
+
+
+;;; General exponentiation.
+
+(defun math-pow (a b)   ; [O O N] [Public]
+  (cond ((equal b '(var nan var-nan))
+	 b)
+	((Math-zerop a)
+	 (if (and (Math-scalarp b) (Math-posp b))
+	     (if (math-floatp b) (math-float a) a)
+	   (calc-extensions)
+	   (math-pow-of-zero a b)))
+	((or (eq a 1) (eq b 1)) a)
+	((or (equal a '(float 1 0)) (equal b '(float 1 0))) a)
+	((Math-zerop b)
+	 (if (Math-scalarp a)
+	     (if (or (math-floatp a) (math-floatp b))
+		 '(float 1 0) 1)
+	   (calc-extensions)
+	   (math-pow-zero a b)))
+	((and (Math-integerp b) (or (Math-numberp a) (Math-vectorp a)))
+	 (if (and (equal a '(float 1 1)) (integerp b))
+	     (math-make-float 1 b)
+	   (math-with-extra-prec 2
+	     (math-ipow a b))))
+	(t
+	 (calc-extensions)
+	 (math-pow-fancy a b)))
+)
+
+(defun math-ipow (a n)   ; [O O I] [Public]
+  (cond ((Math-integer-negp n)
+	 (math-ipow (math-div 1 a) (Math-integer-neg n)))
+	((not (consp n))
+	 (if (and (Math-ratp a) (> n 20))
+	     (math-iipow-show a n)
+	   (math-iipow a n)))
+	((math-evenp n)
+	 (math-ipow (math-mul a a) (math-div2 n)))
+	(t
+	 (math-mul a (math-ipow (math-mul a a)
+				(math-div2 (math-add n -1))))))
+)
+
+(defun math-iipow (a n)   ; [O O S]
+  (cond ((= n 0) 1)
+	((= n 1) a)
+	((= (% n 2) 0) (math-iipow (math-mul a a) (/ n 2)))
+	(t (math-mul a (math-iipow (math-mul a a) (/ n 2)))))
+)
+
+(defun math-iipow-show (a n)   ; [O O S]
+  (math-working "pow" a)
+  (let ((val (cond
+	      ((= n 0) 1)
+	      ((= n 1) a)
+	      ((= (% n 2) 0) (math-iipow-show (math-mul a a) (/ n 2)))
+	      (t (math-mul a (math-iipow-show (math-mul a a) (/ n 2)))))))
+    (math-working "pow" val)
+    val)
+)
+
+
+(defun math-read-radix-digit (dig)   ; [D S; Z S]
+  (if (> dig ?9)
+      (if (< dig ?A)
+	  nil
+	(- dig 55))
+    (if (>= dig ?0)
+	(- dig ?0)
+      nil))
+)
+
+
+
+
+
+;;; Bug reporting
+
+(defun report-calc-bug (topic)
+  "Report a bug in Calc, the GNU Emacs calculator.
+Prompts for bug subject.  Leaves you in a mail buffer."
+  (interactive "sBug Subject: ")
+  (mail nil calc-bug-address topic)
+  (goto-char (point-max))
+  (insert "\nIn Calc " calc-version ", Emacs " (emacs-version) "\n\n")
+  (message (substitute-command-keys "Type \\[mail-send] to send bug report."))
+)
+(fset 'calc-report-bug (symbol-function 'report-calc-bug))
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/calc-mode.el	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,714 @@
+;; Calculator for GNU Emacs, part II [calc-mode.el]
+;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+;; Written by Dave Gillespie, daveg@synaptics.com.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY.  No author or distributor
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing.  Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License.   A copy of this license is
+;; supposed to have been given to you along with GNU Emacs so you
+;; can know your rights and responsibilities.  It should be in a
+;; file named COPYING.  Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+
+
+
+;; This file is autoloaded from calc-ext.el.
+(require 'calc-ext)
+
+(require 'calc-macs)
+
+(defun calc-Need-calc-mode () nil)
+
+
+(defun calc-line-numbering (n)
+  (interactive "P")
+  (calc-wrapper
+   (message (if (calc-change-mode 'calc-line-numbering n t t)
+		"Displaying stack level numbers."
+	      "Hiding stack level numbers.")))
+)
+
+(defun calc-line-breaking (n)
+  (interactive "P")
+  (calc-wrapper
+   (setq n (if n
+	       (and (> (setq n (prefix-numeric-value n)) 0)
+		    (or (< n 5)
+			n))
+	     (not calc-line-breaking)))
+   (if (calc-change-mode 'calc-line-breaking n t)
+       (if (integerp calc-line-breaking)
+	   (message "Breaking lines longer than %d characters." n)
+	 (message "Breaking long lines in Stack display."))
+     (message "Not breaking long lines in Stack display.")))
+)
+
+
+(defun calc-left-justify (n)
+  (interactive "P")
+  (calc-wrapper
+   (and n (setq n (prefix-numeric-value n)))
+   (calc-change-mode '(calc-display-just calc-display-origin)
+		     (list nil n) t)
+   (if n
+       (message "Displaying stack entries indented by %d." n)
+     (message "Displaying stack entries left-justified.")))
+)
+
+(defun calc-center-justify (n)
+  (interactive "P")
+  (calc-wrapper
+   (and n (setq n (prefix-numeric-value n)))
+   (calc-change-mode '(calc-display-just calc-display-origin)
+		     (list 'center n) t)
+   (if n
+       (message "Displaying stack entries centered on column %d." n)
+     (message "Displaying stack entries centered in window.")))
+)
+
+(defun calc-right-justify (n)
+  (interactive "P")
+  (calc-wrapper
+   (and n (setq n (prefix-numeric-value n)))
+   (calc-change-mode '(calc-display-just calc-display-origin)
+		     (list 'right n) t)
+   (if n
+       (message "Displaying stack entries right-justified to column %d." n)
+     (message "Displaying stack entries right-justified in window.")))
+)
+
+(defun calc-left-label (s)
+  (interactive "sLefthand label: ")
+  (calc-wrapper
+   (or (equal s "")
+       (setq s (concat s " ")))
+   (calc-change-mode 'calc-left-label s t))
+)
+
+(defun calc-right-label (s)
+  (interactive "sRighthand label: ")
+  (calc-wrapper
+   (or (equal s "")
+       (setq s (concat " " s)))
+   (calc-change-mode 'calc-right-label s t))
+)
+
+(defun calc-auto-why (n)
+  (interactive "P")
+  (calc-wrapper
+   (if n
+       (progn
+	 (setq n (prefix-numeric-value n))
+	 (if (<= n 0) (setq n nil)
+	   (if (> n 1) (setq n t))))
+     (setq n (and (not (eq calc-auto-why t)) (if calc-auto-why t 1))))
+   (calc-change-mode 'calc-auto-why n nil)
+   (cond ((null n)
+	  (message "User must press `w' to explain unsimplified results."))
+	 ((eq n t)
+	  (message "Automatically doing `w' to explain unsimplified results."))
+	 (t
+	  (message "Automatically doing `w' only for unusual messages."))))
+)
+
+(defun calc-group-digits (n)
+  (interactive "P")
+  (calc-wrapper
+   (if n
+       (progn
+	 (setq n (prefix-numeric-value n))
+	 (cond ((or (> n 0) (< n -1)))
+	       ((= n -1)
+		(setq n nil))
+	       (t
+		(setq n calc-group-digits))))
+     (setq n (not calc-group-digits)))
+   (calc-change-mode 'calc-group-digits n t)
+   (cond ((null n)
+	  (message "Grouping is off."))
+	 ((integerp n)
+	  (message "Grouping every %d digits." (math-abs n)))
+	 (t
+	  (message "Grouping is on."))))
+)
+
+(defun calc-group-char (ch)
+  (interactive "cGrouping character: ")
+  (calc-wrapper
+   (or (>= ch 32)
+       (error "Control characters not allowed for grouping."))
+   (if (= ch ?\\)
+       (setq ch "\\,")
+     (setq ch (char-to-string ch)))
+   (calc-change-mode 'calc-group-char ch calc-group-digits)
+   (message "Digit grouping character is \"%s\"." ch))
+)
+
+(defun calc-point-char (ch)
+  (interactive "cCharacter to use as decimal point: ")
+  (calc-wrapper
+   (or (>= ch 32)
+       (error "Control characters not allowed as decimal point."))
+   (calc-change-mode 'calc-point-char (char-to-string ch) t)
+   (message "Decimal point character is \"%c\"." ch))
+)
+
+(defun calc-normal-notation (n)
+  (interactive "P")
+  (calc-wrapper
+   (calc-change-mode 'calc-float-format
+		     (let* ((val (if n (prefix-numeric-value n) 0))
+			    (mode (/ (+ val 5000) 10000)))
+		       (if (or (< val -5000) (> mode 3))
+			   (error "Prefix out of range"))
+		       (setq n (list (aref [float sci eng fix] mode)
+				     (- (% (+ val 5000) 10000) 5000))))
+		     t)
+   (if (eq (nth 1 n) 0)
+       (message "Displaying floating-point numbers normally.")
+     (if (> (nth 1 n) 0)
+	 (message
+	  "Displaying floating-point numbers with %d significant digits."
+	  (nth 1 n))
+       (message "Displaying floating-point numbers with (precision%d)."
+		(nth 1 n)))))
+)
+
+(defun calc-fix-notation (n)
+  (interactive "NDigits after decimal point: ")
+  (calc-wrapper
+   (calc-change-mode 'calc-float-format
+		     (setq n (list 'fix (if n (prefix-numeric-value n) 0)))
+		     t)
+   (message "Displaying floats with %d digits after decimal."
+	    (math-abs (nth 1 n))))
+)
+
+(defun calc-sci-notation (n)
+  (interactive "P")
+  (calc-wrapper
+   (calc-change-mode 'calc-float-format
+		     (setq n (list 'sci (if n (prefix-numeric-value n) 0)))
+		     t)
+   (if (eq (nth 1 n) 0)
+       (message "Displaying floats in scientific notation.")
+     (if (> (nth 1 n) 0)
+	 (message "Displaying scientific notation with %d significant digits."
+		  (nth 1 n))
+       (message "Displaying scientific notation with (precision%d)."
+		(nth 1 n)))))
+)
+
+(defun calc-eng-notation (n)
+  (interactive "P")
+  (calc-wrapper
+   (calc-change-mode 'calc-float-format
+		     (setq n (list 'eng (if n (prefix-numeric-value n) 0)))
+		     t)
+   (if (eq (nth 1 n) 0)
+       (message "Displaying floats in engineering notation.")
+     (if (> (nth 1 n) 0)
+	 (message "Displaying engineering notation with %d significant digits."
+		  (nth 1 n))
+       (message "Displaying engineering notation with (precision%d)."
+		(nth 1 n)))))
+)
+
+
+(defun calc-truncate-stack (n &optional rel)
+  (interactive "P")
+  (calc-wrapper
+   (let ((oldtop calc-stack-top)
+	 (newtop calc-stack-top))
+     (calc-record-undo (list 'set 'saved-stack-top calc-stack-top))
+     (let ((calc-stack-top 0)
+	   (nn (prefix-numeric-value n)))
+       (setq newtop
+	     (if n
+		 (progn
+		   (if rel
+		       (setq nn (+ oldtop nn))
+		     (if (< nn 0)
+			 (setq nn (+ nn (calc-stack-size)))
+		       (setq nn (1+ nn))))
+		   (if (< nn 1)
+		       1
+		     (if (> nn (calc-stack-size))
+			 (calc-stack-size)
+		       nn)))
+	       (max 1 (calc-locate-cursor-element (point)))))
+       (if (= newtop oldtop)
+	   ()
+	 (calc-pop-stack 1 oldtop t)
+	 (calc-push-list '(top-of-stack) newtop)
+	 (if calc-line-numbering
+	     (calc-refresh))))
+     (calc-record-undo (list 'set 'saved-stack-top 0))
+     (setq calc-stack-top newtop)))
+)
+
+(defun calc-truncate-up (n)
+  (interactive "p")
+  (calc-truncate-stack n t)
+)
+
+(defun calc-truncate-down (n)
+  (interactive "p")
+  (calc-truncate-stack (- n) t)
+)
+
+(defun calc-display-raw (arg)
+  (interactive "P")
+  (calc-wrapper
+   (setq calc-display-raw (if calc-display-raw nil (if arg 0 t)))
+   (calc-do-refresh)
+   (if calc-display-raw
+       (message "Press d ' again to cancel \"raw\" display mode.")))
+)
+
+
+
+
+;;; Mode commands.
+
+(defun calc-save-modes (&optional quiet)
+  (interactive)
+  (calc-wrapper
+   (let (pos
+	 (vals (mapcar (function (lambda (v) (symbol-value (car v))))
+		       calc-mode-var-list)))
+     (set-buffer (find-file-noselect (substitute-in-file-name
+				      calc-settings-file)))
+     (goto-char (point-min))
+     (if (and (search-forward ";;; Mode settings stored by Calc" nil t)
+	      (progn
+		(beginning-of-line)
+		(setq pos (point))
+		(search-forward "\n;;; End of mode settings" nil t)))
+	 (progn
+	   (beginning-of-line)
+	   (forward-line 1)
+	   (delete-region pos (point)))
+       (goto-char (point-max))
+       (insert "\n\n")
+       (forward-char -1))
+     (insert ";;; Mode settings stored by Calc on " (current-time-string) "\n")
+     (let ((list calc-mode-var-list))
+       (while list
+	 (let* ((v (car (car list)))
+		(def (nth 1 (car list)))
+		(val (car vals)))
+	   (or (equal val def)
+	       (progn
+		 (insert "(setq " (symbol-name v) " ")
+		 (if (and (or (listp val)
+			      (symbolp val))
+			  (not (memq val '(nil t))))
+		     (insert "'"))
+		 (insert (prin1-to-string val) ")\n"))))
+	 (setq list (cdr list)
+	       vals (cdr vals))))
+     (run-hooks 'calc-mode-save-hook)
+     (insert ";;; End of mode settings\n")
+     (if quiet
+	 (let ((executing-macro ""))   ; what a kludge!
+	   (save-buffer))
+       (save-buffer))))
+)
+
+(defun calc-settings-file-name (name &optional arg)
+  (interactive "sSettings file name (normally ~/.emacs): \nP")
+  (calc-wrapper
+   (setq arg (if arg (prefix-numeric-value arg) 0))
+   (if (equal name "")
+       (message "Calc settings file is \"%s\"" calc-settings-file)
+     (if (< (math-abs arg) 2)
+	 (let ((list calc-mode-var-list))
+	   (while list
+	     (set (car (car list)) (nth 1 (car list)))
+	     (setq list (cdr list)))))
+     (setq calc-settings-file name)
+     (or (and (string-match "\\.emacs" calc-settings-file)
+	      (> arg 0))
+	 (< arg 0)
+	 (load name t)
+	 (message "New file"))))
+)
+
+(defun math-get-modes-vec ()
+  (list 'vec
+	calc-internal-prec
+	calc-word-size
+	(calc-stack-size)
+	calc-number-radix
+	(+ (if (<= (nth 1 calc-float-format) 0)
+	       (+ calc-internal-prec (nth 1 calc-float-format))
+	     (nth 1 calc-float-format))
+	   (cdr (assq (car calc-float-format)
+		      '((float . 0) (sci . 10000)
+			(eng . 20000) (fix . 30000)))))
+	(cond ((eq calc-angle-mode 'rad) 2)
+	      ((eq calc-angle-mode 'hms) 3)
+	      (t 1))
+	(if calc-symbolic-mode 1 0)
+	(if calc-prefer-frac 1 0)
+	(if (eq calc-complex-mode 'polar) 1 0)
+	(cond ((eq calc-matrix-mode 'scalar) 0)
+	      ((eq calc-matrix-mode 'matrix) -2)
+	      (calc-matrix-mode)
+	      (t -1))
+	(cond ((eq calc-simplify-mode 'none) -1)
+	      ((eq calc-simplify-mode 'num) 0)
+	      ((eq calc-simplify-mode 'binary) 2)
+	      ((eq calc-simplify-mode 'alg) 3)
+	      ((eq calc-simplify-mode 'ext) 4)
+	      ((eq calc-simplify-mode 'units) 5)
+	      (t 1))
+	(cond ((eq calc-infinite-mode 1) 0)
+	      (calc-infinite-mode 1)
+	      (t -1)))
+)
+
+(defun calc-get-modes (n)
+  (interactive "P")
+  (calc-wrapper
+   (let ((modes (math-get-modes-vec)))
+     (calc-enter-result 0 "mode"
+			(if n
+			    (if (and (>= (setq n (prefix-numeric-value n)) 1)
+				     (< n (length modes)))
+				(nth n modes)
+			      (error "Prefix out of range"))
+			  modes))))
+)
+
+(defun calc-shift-prefix (arg)
+  (interactive "P")
+  (calc-wrapper
+   (setq calc-shift-prefix (if arg
+			       (> (prefix-numeric-value arg) 0)
+			     (not calc-shift-prefix)))
+   (calc-init-prefixes)
+   (message (if calc-shift-prefix
+		"Prefix keys are now case-insensitive"
+	      "Prefix keys must be unshifted (except V, Z)")))
+)
+
+(defun calc-mode-record-mode (n)
+  (interactive "P")
+  (calc-wrapper
+   (calc-change-mode 'calc-mode-save-mode
+		     (cond ((null n)
+			    (cond ((not calc-embedded-info)
+				   (if (eq calc-mode-save-mode 'save)
+				       'local 'save))
+				  ((eq calc-mode-save-mode 'local)  'edit)
+				  ((eq calc-mode-save-mode 'edit)   'perm)
+				  ((eq calc-mode-save-mode 'perm)   'global)
+				  ((eq calc-mode-save-mode 'global) 'save)
+				  ((eq calc-mode-save-mode 'save)   nil)
+				  ((eq calc-mode-save-mode nil)     'local)))
+			   ((= (setq n (prefix-numeric-value n)) 0) nil)
+			   ((= n 2) 'edit)
+			   ((= n 3) 'perm)
+			   ((= n 4) 'global)
+			   ((= n 5) 'save)
+			   (t 'local)))
+   (message (cond ((and (eq calc-mode-save-mode 'local) calc-embedded-info)
+		   "Recording mode changes with [calc-mode: ...]")
+		  ((eq calc-mode-save-mode 'edit)
+		   "Recording mode changes with [calc-edit-mode: ...]")
+		  ((eq calc-mode-save-mode 'perm)
+		   "Recording mode changes with [calc-perm-mode: ...]")
+		  ((eq calc-mode-save-mode 'global)
+		   "Recording mode changes with [calc-global-mode: ...]")
+		  ((eq calc-mode-save-mode 'save)
+		   (format "Recording mode changes in \"%s\"."
+			   calc-settings-file))
+		  (t
+		   "Not recording mode changes permanently."))))
+)
+
+(defun calc-total-algebraic-mode (flag)
+  (interactive "P")
+  (if calc-emacs-type-19
+      (error "Total algebraic mode not yet supported for Emacs 19"))
+  (calc-wrapper
+   (if (eq calc-algebraic-mode 'total)
+       (calc-algebraic-mode nil)
+     (calc-change-mode '(calc-algebraic-mode calc-incomplete-algebraic-mode)
+		       '(total nil))
+     (use-local-map calc-alg-map)
+     (message
+      "All keys begin algebraic entry; use Meta (ESC) for Calc keys.")))
+)
+
+(defun calc-algebraic-mode (flag)
+  (interactive "P")
+  (calc-wrapper
+   (if flag
+       (calc-change-mode '(calc-algebraic-mode
+			   calc-incomplete-algebraic-mode)
+			 (list nil (not calc-incomplete-algebraic-mode)))
+     (calc-change-mode '(calc-algebraic-mode calc-incomplete-algebraic-mode)
+		       (list (not calc-algebraic-mode) nil)))
+   (use-local-map calc-mode-map)
+   (message (if calc-algebraic-mode
+		"Numeric keys and ( and [ begin algebraic entry."
+	      (if calc-incomplete-algebraic-mode
+		  "Only ( and [ begin algebraic entry."
+		"No keys except ' and $ begin algebraic entry."))))
+)
+
+(defun calc-symbolic-mode (n)
+  (interactive "P")
+  (calc-wrapper
+   
+   (message (if (calc-change-mode 'calc-symbolic-mode n nil t)
+		"Inexact computations like sqrt(2) are deferred."
+	      "Numerical computations are always done immediately.")))
+)
+
+(defun calc-infinite-mode (n)
+  (interactive "P")
+  (calc-wrapper
+   (if (eq n 0)
+       (progn
+	 (calc-change-mode 'calc-infinite-mode 1)
+	 (message "Computations like 1 / 0 produce \"inf\"."))
+     (message (if (calc-change-mode 'calc-infinite-mode n nil t)
+		  "Computations like 1 / 0 produce \"uinf\"."
+		"Computations like 1 / 0 are left unsimplified."))))
+)
+
+(defun calc-matrix-mode (arg)
+  (interactive "P")
+  (calc-wrapper
+   (calc-change-mode 'calc-matrix-mode
+		     (cond ((eq arg 0) 'scalar)
+			   ((< (prefix-numeric-value arg) 1)
+			    (and (< (prefix-numeric-value arg) -1) 'matrix))
+			   (arg (prefix-numeric-value arg))
+			   ((eq calc-matrix-mode 'matrix) 'scalar)
+			   ((eq calc-matrix-mode 'scalar) nil)
+			   (t 'matrix)))
+   (if (integerp calc-matrix-mode)
+       (message "Variables are assumed to be %dx%d matrices."
+		calc-matrix-mode calc-matrix-mode)
+     (message (if (eq calc-matrix-mode 'matrix)
+		  "Variables are assumed to be matrices."
+		(if calc-matrix-mode
+		    "Variables are assumed to be scalars (non-matrices)."
+		  "Variables are not assumed to be matrix or scalar.")))))
+)
+
+(defun calc-set-simplify-mode (mode arg msg)
+  (calc-change-mode 'calc-simplify-mode
+		    (if arg
+			(and (> (prefix-numeric-value arg) 0)
+			     mode)
+		      (and (not (eq calc-simplify-mode mode))
+			   mode)))
+  (message (if (eq calc-simplify-mode mode)
+	       msg
+	     "Default simplifications enabled."))
+)
+
+(defun calc-no-simplify-mode (arg)
+  (interactive "P")
+  (calc-wrapper
+   (calc-set-simplify-mode 'none arg
+			   "All default simplifications are disabled."))
+)
+
+(defun calc-num-simplify-mode (arg)
+  (interactive "P")
+  (calc-wrapper
+   (calc-set-simplify-mode 'num arg
+			   "Default simplifications apply only if arguments are numeric."))
+)
+
+(defun calc-default-simplify-mode (arg)
+  (interactive "p")
+  (cond ((= arg 1)
+	 (calc-wrapper
+	  (calc-set-simplify-mode
+	   nil nil "Usual default simplifications are enabled.")))
+	((= arg 0) (calc-num-simplify-mode 1))
+	((< arg 0) (calc-no-simplify-mode 1))
+	((= arg 2) (calc-bin-simplify-mode 1))
+	((= arg 3) (calc-alg-simplify-mode 1))
+	((= arg 4) (calc-ext-simplify-mode 1))
+	((= arg 5) (calc-units-simplify-mode 1))
+	(t (error "Prefix argument out of range")))
+)
+
+(defun calc-bin-simplify-mode (arg)
+  (interactive "P")
+  (calc-wrapper
+   (calc-set-simplify-mode 'binary arg
+			   (format "Binary simplification occurs by default (word size=%d)."
+				   calc-word-size)))
+)
+
+(defun calc-alg-simplify-mode (arg)
+  (interactive "P")
+  (calc-wrapper
+   (calc-set-simplify-mode 'alg arg
+			   "Algebraic simplification occurs by default."))
+)
+
+(defun calc-ext-simplify-mode (arg)
+  (interactive "P")
+  (calc-wrapper
+   (calc-set-simplify-mode 'ext arg
+			   "Extended algebraic simplification occurs by default."))
+)
+
+(defun calc-units-simplify-mode (arg)
+  (interactive "P")
+  (calc-wrapper
+   (calc-set-simplify-mode 'units arg
+			   "Units simplification occurs by default."))
+)
+
+(defun calc-auto-recompute (arg)
+  (interactive "P")
+  (calc-wrapper
+   (calc-change-mode 'calc-auto-recompute arg nil t)
+   (calc-refresh-evaltos)
+   (message (if calc-auto-recompute
+		"Automatically recomputing `=>' forms when necessary."
+	      "Not recomputing `=>' forms automatically.")))
+)
+
+(defun calc-working (n)
+  (interactive "P")
+  (calc-wrapper
+   (cond ((consp n)
+	  (calc-pop-push-record 0 "work"
+				(cond ((eq calc-display-working-message t) 1)
+				      (calc-display-working-message 2)
+				      (t 0))))
+	 ((eq n 2) (calc-change-mode 'calc-display-working-message 'lots))
+	 ((eq n 0) (calc-change-mode 'calc-display-working-message nil))
+	 ((eq n 1) (calc-change-mode 'calc-display-working-message t)))
+   (cond ((eq calc-display-working-message t)
+	  (message "\"Working...\" messages enabled."))
+	 (calc-display-working-message
+	  (message "Detailed \"Working...\" messages enabled."))
+	 (t
+	  (message "\"Working...\" messages disabled."))))
+)
+
+(defun calc-always-load-extensions ()
+  (interactive)
+  (calc-wrapper
+   (if (setq calc-always-load-extensions (not calc-always-load-extensions))
+       (message "Always loading extensions package.")
+     (message "Loading extensions package on demand only.")))
+)
+
+
+(defun calc-matrix-left-justify ()
+  (interactive)
+  (calc-wrapper
+   (calc-change-mode 'calc-matrix-just nil t)
+   (message "Matrix elements will be left-justified in columns."))
+)
+
+(defun calc-matrix-center-justify ()
+  (interactive)
+  (calc-wrapper
+   (calc-change-mode 'calc-matrix-just 'center t)
+   (message "Matrix elements will be centered in columns."))
+)
+
+(defun calc-matrix-right-justify ()
+  (interactive)
+  (calc-wrapper
+   (calc-change-mode 'calc-matrix-just 'right t)
+   (message "Matrix elements will be right-justified in columns."))
+)
+
+(defun calc-full-vectors (n)
+  (interactive "P")
+  (calc-wrapper
+   (message (if (calc-change-mode 'calc-full-vectors n t t)
+		"Displaying long vectors in full."
+	      "Displaying long vectors in [a, b, c, ..., z] notation.")))
+)
+
+(defun calc-full-trail-vectors (n)
+  (interactive "P")
+  (calc-wrapper
+   (message (if (calc-change-mode 'calc-full-trail-vectors n nil t)
+		"Recording long vectors in full."
+	      "Recording long vectors in [a, b, c, ..., z] notation.")))
+)
+
+(defun calc-break-vectors (n)
+  (interactive "P")
+  (calc-wrapper
+   (message (if (calc-change-mode 'calc-break-vectors n t t)
+		"Displaying vector elements one-per-line."
+	      "Displaying vector elements all on one line.")))
+)
+
+(defun calc-vector-commas ()
+  (interactive)
+  (calc-wrapper
+   (if (calc-change-mode 'calc-vector-commas (if calc-vector-commas nil ",") t)
+       (message "Separating vector elements with \",\".")
+     (message "Separating vector elements with spaces.")))
+)
+
+(defun calc-vector-brackets ()
+  (interactive)
+  (calc-wrapper
+   (if (calc-change-mode 'calc-vector-brackets
+			 (if (equal calc-vector-brackets "[]") nil "[]") t)
+       (message "Surrounding vectors with \"[]\".")
+     (message "Not surrounding vectors with brackets.")))
+)
+
+(defun calc-vector-braces ()
+  (interactive)
+  (calc-wrapper
+   (if (calc-change-mode 'calc-vector-brackets
+			 (if (equal calc-vector-brackets "{}") nil "{}") t)
+       (message "Surrounding vectors with \"{}\".")
+     (message "Not surrounding vectors with brackets.")))
+)
+
+(defun calc-vector-parens ()
+  (interactive)
+  (calc-wrapper
+   (if (calc-change-mode 'calc-vector-brackets
+			 (if (equal calc-vector-brackets "()") nil "()") t)
+       (message "Surrounding vectors with \"()\".")
+     (message "Not surrounding vectors with brackets.")))
+)
+
+(defun calc-matrix-brackets (arg)
+  (interactive "sCode letters (R, O, C, P): ")
+  (calc-wrapper
+   (let ((code (append (and (string-match "[rR]" arg) '(R))
+		       (and (string-match "[oO]" arg) '(O))
+		       (and (string-match "[cC]" arg) '(C))
+		       (and (string-match "[pP]" arg) '(P))))
+	 (bad (string-match "[^rRoOcCpP ]" arg)))
+     (if bad
+	 (error "Unrecognized character: %c" (aref arg bad)))
+     (calc-change-mode 'calc-matrix-brackets code t)))
+)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/calc-mtx.el	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,378 @@
+;; Calculator for GNU Emacs, part II [calc-mat.el]
+;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+;; Written by Dave Gillespie, daveg@synaptics.com.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY.  No author or distributor
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing.  Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License.   A copy of this license is
+;; supposed to have been given to you along with GNU Emacs so you
+;; can know your rights and responsibilities.  It should be in a
+;; file named COPYING.  Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+
+
+
+;; This file is autoloaded from calc-ext.el.
+(require 'calc-ext)
+
+(require 'calc-macs)
+
+(defun calc-Need-calc-mat () nil)
+
+
+(defun calc-mdet (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-unary-op "mdet" 'calcFunc-det arg))
+)
+
+(defun calc-mtrace (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-unary-op "mtr" 'calcFunc-tr arg))
+)
+
+(defun calc-mlud (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-unary-op "mlud" 'calcFunc-lud arg))
+)
+
+
+;;; Coerce row vector A to be a matrix.  [V V]
+(defun math-row-matrix (a)
+  (if (and (Math-vectorp a)
+	   (not (math-matrixp a)))
+      (list 'vec a)
+    a)
+)
+
+;;; Coerce column vector A to be a matrix.  [V V]
+(defun math-col-matrix (a)
+  (if (and (Math-vectorp a)
+	   (not (math-matrixp a)))
+      (cons 'vec (mapcar (function (lambda (x) (list 'vec x))) (cdr a)))
+    a)
+)
+
+
+
+;;; Multiply matrices A and B.  [V V V]
+(defun math-mul-mats (a b)
+  (let ((mat nil)
+	(cols (length (nth 1 b)))
+	row col ap bp accum)
+    (while (setq a (cdr a))
+      (setq col cols
+	    row nil)
+      (while (> (setq col (1- col)) 0)
+	(setq ap (cdr (car a))
+	      bp (cdr b)
+	      accum (math-mul (car ap) (nth col (car bp))))
+	(while (setq ap (cdr ap) bp (cdr bp))
+	  (setq accum (math-add accum (math-mul (car ap) (nth col (car bp))))))
+	(setq row (cons accum row)))
+      (setq mat (cons (cons 'vec row) mat)))
+    (cons 'vec (nreverse mat)))
+)
+
+(defun math-mul-mat-vec (a b)
+  (cons 'vec (mapcar (function (lambda (row)
+				 (math-dot-product row b)))
+		     (cdr a)))
+)
+
+
+
+(defun calcFunc-tr (mat)   ; [Public]
+  (if (math-square-matrixp mat)
+      (math-matrix-trace-step 2 (1- (length mat)) mat (nth 1 (nth 1 mat)))
+    (math-reject-arg mat 'square-matrixp))
+)
+
+(defun math-matrix-trace-step (n size mat sum)
+  (if (<= n size)
+      (math-matrix-trace-step (1+ n) size mat
+			      (math-add sum (nth n (nth n mat))))
+    sum)
+)
+
+
+;;; Matrix inverse and determinant.
+(defun math-matrix-inv-raw (m)
+  (let ((n (1- (length m))))
+    (if (<= n 3)
+	(let ((det (math-det-raw m)))
+	  (and (not (math-zerop det))
+	       (math-div
+		(cond ((= n 1) 1)
+		      ((= n 2)
+		       (list 'vec
+			     (list 'vec
+				   (nth 2 (nth 2 m))
+				   (math-neg (nth 2 (nth 1 m))))
+			     (list 'vec
+				   (math-neg (nth 1 (nth 2 m)))
+				   (nth 1 (nth 1 m)))))
+		      ((= n 3)
+		       (list 'vec
+			     (list 'vec
+				   (math-sub (math-mul (nth 3 (nth 3 m))
+						       (nth 2 (nth 2 m)))
+					     (math-mul (nth 3 (nth 2 m))
+						       (nth 2 (nth 3 m))))
+				   (math-sub (math-mul (nth 3 (nth 1 m))
+						       (nth 2 (nth 3 m)))
+					     (math-mul (nth 3 (nth 3 m))
+						       (nth 2 (nth 1 m))))
+				   (math-sub (math-mul (nth 3 (nth 2 m))
+						       (nth 2 (nth 1 m)))
+					     (math-mul (nth 3 (nth 1 m))
+						       (nth 2 (nth 2 m)))))
+			     (list 'vec
+				   (math-sub (math-mul (nth 3 (nth 2 m))
+						       (nth 1 (nth 3 m)))
+					     (math-mul (nth 3 (nth 3 m))
+						       (nth 1 (nth 2 m))))
+				   (math-sub (math-mul (nth 3 (nth 3 m))
+						       (nth 1 (nth 1 m)))
+					     (math-mul (nth 3 (nth 1 m))
+						       (nth 1 (nth 3 m))))
+				   (math-sub (math-mul (nth 3 (nth 1 m))
+						       (nth 1 (nth 2 m)))
+					     (math-mul (nth 3 (nth 2 m))
+						       (nth 1 (nth 1 m)))))
+			     (list 'vec
+				   (math-sub (math-mul (nth 2 (nth 3 m))
+						       (nth 1 (nth 2 m)))
+					     (math-mul (nth 2 (nth 2 m))
+						       (nth 1 (nth 3 m))))
+				   (math-sub (math-mul (nth 2 (nth 1 m))
+						       (nth 1 (nth 3 m)))
+					     (math-mul (nth 2 (nth 3 m))
+						       (nth 1 (nth 1 m))))
+				   (math-sub (math-mul (nth 2 (nth 2 m))
+						       (nth 1 (nth 1 m)))
+					     (math-mul (nth 2 (nth 1 m))
+						       (nth 1 (nth 2 m))))))))
+		det)))
+      (let ((lud (math-matrix-lud m)))
+	(and lud
+	     (math-lud-solve lud (calcFunc-idn 1 n))))))
+)
+
+(defun calcFunc-det (m)
+  (if (math-square-matrixp m)
+      (math-with-extra-prec 2 (math-det-raw m))
+    (if (and (eq (car-safe m) 'calcFunc-idn)
+	     (or (math-zerop (nth 1 m))
+		 (math-equal-int (nth 1 m) 1)))
+	(nth 1 m)
+      (math-reject-arg m 'square-matrixp)))
+)
+
+(defun math-det-raw (m)
+  (let ((n (1- (length m))))
+    (cond ((= n 1)
+	   (nth 1 (nth 1 m)))
+	  ((= n 2)
+	   (math-sub (math-mul (nth 1 (nth 1 m))
+			       (nth 2 (nth 2 m)))
+		     (math-mul (nth 2 (nth 1 m))
+			       (nth 1 (nth 2 m)))))
+	  ((= n 3)
+	   (math-sub
+	    (math-sub
+	     (math-sub
+	      (math-add
+	       (math-add
+		(math-mul (nth 1 (nth 1 m))
+			  (math-mul (nth 2 (nth 2 m))
+				    (nth 3 (nth 3 m))))
+		(math-mul (nth 2 (nth 1 m))
+			  (math-mul (nth 3 (nth 2 m))
+				    (nth 1 (nth 3 m)))))
+	       (math-mul (nth 3 (nth 1 m))
+			 (math-mul (nth 1 (nth 2 m))
+				   (nth 2 (nth 3 m)))))
+	      (math-mul (nth 3 (nth 1 m))
+			(math-mul (nth 2 (nth 2 m))
+				  (nth 1 (nth 3 m)))))
+	     (math-mul (nth 1 (nth 1 m))
+		       (math-mul (nth 3 (nth 2 m))
+				 (nth 2 (nth 3 m)))))
+	    (math-mul (nth 2 (nth 1 m))
+		      (math-mul (nth 1 (nth 2 m))
+				(nth 3 (nth 3 m))))))
+	  (t (let ((lud (math-matrix-lud m)))
+	       (if lud
+		   (let ((lu (car lud)))
+		     (math-det-step n (nth 2 lud)))
+		 0)))))
+)
+
+(defun math-det-step (n prod)
+  (if (> n 0)
+      (math-det-step (1- n) (math-mul prod (nth n (nth n lu))))
+    prod)
+)
+
+;;; This returns a list (LU index d), or NIL if not possible.
+;;; Argument M must be a square matrix.
+(defun math-matrix-lud (m)
+  (let ((old (assoc m math-lud-cache))
+	(context (list calc-internal-prec calc-prefer-frac)))
+    (if (and old (equal (nth 1 old) context))
+	(cdr (cdr old))
+      (let* ((lud (catch 'singular (math-do-matrix-lud m)))
+	     (entry (cons context lud)))
+	(if old
+	    (setcdr old entry)
+	  (setq math-lud-cache (cons (cons m entry) math-lud-cache)))
+	lud)))
+)
+(defvar math-lud-cache nil)
+
+;;; Numerical Recipes section 2.3; implicit pivoting omitted.
+(defun math-do-matrix-lud (m)
+  (let* ((lu (math-copy-matrix m))
+	 (n (1- (length lu)))
+	 i (j 1) k imax sum big
+	 (d 1) (index nil))
+    (while (<= j n)
+      (setq i 1
+	    big 0
+	    imax j)
+      (while (< i j)
+	(math-working "LUD step" (format "%d/%d" j i))
+	(setq sum (nth j (nth i lu))
+	      k 1)
+	(while (< k i)
+	  (setq sum (math-sub sum (math-mul (nth k (nth i lu))
+					    (nth j (nth k lu))))
+		k (1+ k)))
+	(setcar (nthcdr j (nth i lu)) sum)
+	(setq i (1+ i)))
+      (while (<= i n)
+	(math-working "LUD step" (format "%d/%d" j i))
+	(setq sum (nth j (nth i lu))
+	      k 1)
+	(while (< k j)
+	  (setq sum (math-sub sum (math-mul (nth k (nth i lu))
+					    (nth j (nth k lu))))
+		k (1+ k)))
+	(setcar (nthcdr j (nth i lu)) sum)
+	(let ((dum (math-abs-approx sum)))
+	  (if (Math-lessp big dum)
+	      (setq big dum
+		    imax i)))
+	(setq i (1+ i)))
+      (if (> imax j)
+	  (setq lu (math-swap-rows lu j imax)
+		d (- d)))
+      (setq index (cons imax index))
+      (let ((pivot (nth j (nth j lu))))
+	(if (math-zerop pivot)
+	    (throw 'singular nil)
+	  (setq i j)
+	  (while (<= (setq i (1+ i)) n)
+	    (setcar (nthcdr j (nth i lu))
+		    (math-div (nth j (nth i lu)) pivot)))))
+      (setq j (1+ j)))
+    (list lu (nreverse index) d))
+)
+
+(defun math-swap-rows (m r1 r2)
+  (or (= r1 r2)
+      (let* ((r1prev (nthcdr (1- r1) m))
+	     (row1 (cdr r1prev))
+	     (r2prev (nthcdr (1- r2) m))
+	     (row2 (cdr r2prev))
+	     (r2next (cdr row2)))
+	(setcdr r2prev row1)
+	(setcdr r1prev row2)
+	(setcdr row2 (cdr row1))
+	(setcdr row1 r2next)))
+  m
+)
+
+
+(defun math-lud-solve (lud b &optional need)
+  (if lud
+      (let* ((x (math-copy-matrix b))
+	     (n (1- (length x)))
+	     (m (1- (length (nth 1 x))))
+	     (lu (car lud))
+	     (col 1)
+	     i j ip ii index sum)
+	(while (<= col m)
+	  (math-working "LUD solver step" col)
+	  (setq i 1
+		ii nil
+		index (nth 1 lud))
+	  (while (<= i n)
+	    (setq ip (car index)
+		  index (cdr index)
+		  sum (nth col (nth ip x)))
+	    (setcar (nthcdr col (nth ip x)) (nth col (nth i x)))
+	    (if (null ii)
+		(or (math-zerop sum)
+		    (setq ii i))
+	      (setq j ii)
+	      (while (< j i)
+		(setq sum (math-sub sum (math-mul (nth j (nth i lu))
+						  (nth col (nth j x))))
+		      j (1+ j))))
+	    (setcar (nthcdr col (nth i x)) sum)
+	    (setq i (1+ i)))
+	  (while (>= (setq i (1- i)) 1)
+	    (setq sum (nth col (nth i x))
+		  j i)
+	    (while (<= (setq j (1+ j)) n)
+	      (setq sum (math-sub sum (math-mul (nth j (nth i lu))
+						(nth col (nth j x))))))
+	    (setcar (nthcdr col (nth i x))
+		    (math-div sum (nth i (nth i lu)))))
+	  (setq col (1+ col)))
+	x)
+    (and need
+	 (math-reject-arg need "*Singular matrix")))
+)
+
+(defun calcFunc-lud (m)
+  (if (math-square-matrixp m)
+      (or (math-with-extra-prec 2
+	    (let ((lud (math-matrix-lud m)))
+	      (and lud
+		   (let* ((lmat (math-copy-matrix (car lud)))
+			  (umat (math-copy-matrix (car lud)))
+			  (n (1- (length (car lud))))
+			  (perm (calcFunc-idn 1 n))
+			  i (j 1))
+		     (while (<= j n)
+		       (setq i 1)
+		       (while (< i j)
+			 (setcar (nthcdr j (nth i lmat)) 0)
+			 (setq i (1+ i)))
+		       (setcar (nthcdr j (nth j lmat)) 1)
+		       (while (<= (setq i (1+ i)) n)
+			 (setcar (nthcdr j (nth i umat)) 0))
+		       (setq j (1+ j)))
+		     (while (>= (setq j (1- j)) 1)
+		       (let ((pos (nth (1- j) (nth 1 lud))))
+			 (or (= pos j)
+			     (setq perm (math-swap-rows perm j pos)))))
+		     (list 'vec perm lmat umat)))))
+	  (math-reject-arg m "*Singular matrix"))
+    (math-reject-arg m 'square-matrixp))
+)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/calc-poly.el	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,1195 @@
+;; Calculator for GNU Emacs, part II [calc-poly.el]
+;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+;; Written by Dave Gillespie, daveg@synaptics.com.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY.  No author or distributor
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing.  Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License.   A copy of this license is
+;; supposed to have been given to you along with GNU Emacs so you
+;; can know your rights and responsibilities.  It should be in a
+;; file named COPYING.  Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+
+
+
+;; This file is autoloaded from calc-ext.el.
+(require 'calc-ext)
+
+(require 'calc-macs)
+
+(defun calc-Need-calc-poly () nil)
+
+
+(defun calcFunc-pcont (expr &optional var)
+  (cond ((Math-primp expr)
+	 (cond ((Math-zerop expr) 1)
+	       ((Math-messy-integerp expr) (math-trunc expr))
+	       ((Math-objectp expr) expr)
+	       ((or (equal expr var) (not var)) 1)
+	       (t expr)))
+	((eq (car expr) '*)
+	 (math-mul (calcFunc-pcont (nth 1 expr) var)
+		   (calcFunc-pcont (nth 2 expr) var)))
+	((eq (car expr) '/)
+	 (math-div (calcFunc-pcont (nth 1 expr) var)
+		   (calcFunc-pcont (nth 2 expr) var)))
+	((and (eq (car expr) '^) (Math-natnump (nth 2 expr)))
+	 (math-pow (calcFunc-pcont (nth 1 expr) var) (nth 2 expr)))
+	((memq (car expr) '(neg polar))
+	 (calcFunc-pcont (nth 1 expr) var))
+	((consp var)
+	 (let ((p (math-is-polynomial expr var)))
+	   (if p
+	       (let ((lead (nth (1- (length p)) p))
+		     (cont (math-poly-gcd-list p)))
+		 (if (math-guess-if-neg lead)
+		     (math-neg cont)
+		   cont))
+	     1)))
+	((memq (car expr) '(+ - cplx sdev))
+	 (let ((cont (calcFunc-pcont (nth 1 expr) var)))
+	   (if (eq cont 1)
+	       1
+	     (let ((c2 (calcFunc-pcont (nth 2 expr) var)))
+	       (if (and (math-negp cont)
+			(if (eq (car expr) '-) (math-posp c2) (math-negp c2)))
+		   (math-neg (math-poly-gcd cont c2))
+		 (math-poly-gcd cont c2))))))
+	(var expr)
+	(t 1))
+)
+
+(defun calcFunc-pprim (expr &optional var)
+  (let ((cont (calcFunc-pcont expr var)))
+    (if (math-equal-int cont 1)
+	expr
+      (math-poly-div-exact expr cont var)))
+)
+
+(defun math-div-poly-const (expr c)
+  (cond ((memq (car-safe expr) '(+ -))
+	 (list (car expr)
+	       (math-div-poly-const (nth 1 expr) c)
+	       (math-div-poly-const (nth 2 expr) c)))
+	(t (math-div expr c)))
+)
+
+(defun calcFunc-pdeg (expr &optional var)
+  (if (Math-zerop expr)
+      '(neg (var inf var-inf))
+    (if var
+	(or (math-polynomial-p expr var)
+	    (math-reject-arg expr "Expected a polynomial"))
+      (math-poly-degree expr)))
+)
+
+(defun math-poly-degree (expr)
+  (cond ((Math-primp expr)
+	 (if (eq (car-safe expr) 'var) 1 0))
+	((eq (car expr) 'neg)
+	 (math-poly-degree (nth 1 expr)))
+	((eq (car expr) '*)
+	 (+ (math-poly-degree (nth 1 expr))
+	    (math-poly-degree (nth 2 expr))))
+	((eq (car expr) '/)
+	 (- (math-poly-degree (nth 1 expr))
+	    (math-poly-degree (nth 2 expr))))
+	((and (eq (car expr) '^) (natnump (nth 2 expr)))
+	 (* (math-poly-degree (nth 1 expr)) (nth 2 expr)))
+	((memq (car expr) '(+ -))
+	 (max (math-poly-degree (nth 1 expr))
+	      (math-poly-degree (nth 2 expr))))
+	(t 1))
+)
+
+(defun calcFunc-plead (expr var)
+  (cond ((eq (car-safe expr) '*)
+	 (math-mul (calcFunc-plead (nth 1 expr) var)
+		   (calcFunc-plead (nth 2 expr) var)))
+	((eq (car-safe expr) '/)
+	 (math-div (calcFunc-plead (nth 1 expr) var)
+		   (calcFunc-plead (nth 2 expr) var)))
+	((and (eq (car-safe expr) '^) (math-natnump (nth 2 expr)))
+	 (math-pow (calcFunc-plead (nth 1 expr) var) (nth 2 expr)))
+	((Math-primp expr)
+	 (if (equal expr var)
+	     1
+	   expr))
+	(t
+	 (let ((p (math-is-polynomial expr var)))
+	   (if (cdr p)
+	       (nth (1- (length p)) p)
+	     1))))
+)
+
+
+
+
+
+;;; Polynomial quotient, remainder, and GCD.
+;;; Originally by Ove Ewerlid (ewerlid@mizar.DoCS.UU.SE).
+;;; Modifications and simplifications by daveg.
+
+(setq math-poly-modulus 1)
+
+;;; Return gcd of two polynomials
+(defun calcFunc-pgcd (pn pd)
+  (if (math-any-floats pn)
+      (math-reject-arg pn "Coefficients must be rational"))
+  (if (math-any-floats pd)
+      (math-reject-arg pd "Coefficients must be rational"))
+  (let ((calc-prefer-frac t)
+	(math-poly-modulus (math-poly-modulus pn pd)))
+    (math-poly-gcd pn pd))
+)
+
+;;; Return only quotient to top of stack (nil if zero)
+(defun calcFunc-pdiv (pn pd &optional base)
+  (let* ((calc-prefer-frac t)
+	 (math-poly-modulus (math-poly-modulus pn pd))
+	 (res (math-poly-div pn pd base)))
+    (setq calc-poly-div-remainder (cdr res))
+    (car res))
+)
+
+;;; Return only remainder to top of stack
+(defun calcFunc-prem (pn pd &optional base)
+  (let ((calc-prefer-frac t)
+	(math-poly-modulus (math-poly-modulus pn pd)))
+    (cdr (math-poly-div pn pd base)))
+)
+
+(defun calcFunc-pdivrem (pn pd &optional base)
+  (let* ((calc-prefer-frac t)
+	 (math-poly-modulus (math-poly-modulus pn pd))
+	 (res (math-poly-div pn pd base)))
+    (list 'vec (car res) (cdr res)))
+)
+
+(defun calcFunc-pdivide (pn pd &optional base)
+  (let* ((calc-prefer-frac t)
+	 (math-poly-modulus (math-poly-modulus pn pd))
+	 (res (math-poly-div pn pd base)))
+    (math-add (car res) (math-div (cdr res) pd)))
+)
+
+
+;;; Multiply two terms, expanding out products of sums.
+(defun math-mul-thru (lhs rhs)
+  (if (memq (car-safe lhs) '(+ -))
+      (list (car lhs)
+	    (math-mul-thru (nth 1 lhs) rhs)
+	    (math-mul-thru (nth 2 lhs) rhs))
+    (if (memq (car-safe rhs) '(+ -))
+	(list (car rhs)
+	      (math-mul-thru lhs (nth 1 rhs))
+	      (math-mul-thru lhs (nth 2 rhs)))
+      (math-mul lhs rhs)))
+)
+
+(defun math-div-thru (num den)
+  (if (memq (car-safe num) '(+ -))
+      (list (car num)
+	    (math-div-thru (nth 1 num) den)
+	    (math-div-thru (nth 2 num) den))
+    (math-div num den))
+)
+
+
+;;; Sort the terms of a sum into canonical order.
+(defun math-sort-terms (expr)
+  (if (memq (car-safe expr) '(+ -))
+      (math-list-to-sum
+       (sort (math-sum-to-list expr)
+	     (function (lambda (a b) (math-beforep (car a) (car b))))))
+    expr)
+)
+
+(defun math-list-to-sum (lst)
+  (if (cdr lst)
+      (list (if (cdr (car lst)) '- '+)
+	    (math-list-to-sum (cdr lst))
+	    (car (car lst)))
+    (if (cdr (car lst))
+	(math-neg (car (car lst)))
+      (car (car lst))))
+)
+
+(defun math-sum-to-list (tree &optional neg)
+  (cond ((eq (car-safe tree) '+)
+	 (nconc (math-sum-to-list (nth 1 tree) neg)
+		(math-sum-to-list (nth 2 tree) neg)))
+	((eq (car-safe tree) '-)
+	 (nconc (math-sum-to-list (nth 1 tree) neg)
+		(math-sum-to-list (nth 2 tree) (not neg))))
+	(t (list (cons tree neg))))
+)
+
+;;; Check if the polynomial coefficients are modulo forms.
+(defun math-poly-modulus (expr &optional expr2)
+  (or (math-poly-modulus-rec expr)
+      (and expr2 (math-poly-modulus-rec expr2))
+      1)
+)
+
+(defun math-poly-modulus-rec (expr)
+  (if (and (eq (car-safe expr) 'mod) (Math-natnump (nth 2 expr)))
+      (list 'mod 1 (nth 2 expr))
+    (and (memq (car-safe expr) '(+ - * /))
+	 (or (math-poly-modulus-rec (nth 1 expr))
+	     (math-poly-modulus-rec (nth 2 expr)))))
+)
+
+
+;;; Divide two polynomials.  Return (quotient . remainder).
+(defun math-poly-div (u v &optional math-poly-div-base)
+  (if math-poly-div-base
+      (math-do-poly-div u v)
+    (math-do-poly-div (calcFunc-expand u) (calcFunc-expand v)))
+)
+(setq math-poly-div-base nil)
+
+(defun math-poly-div-exact (u v &optional base)
+  (let ((res (math-poly-div u v base)))
+    (if (eq (cdr res) 0)
+	(car res)
+      (math-reject-arg (list 'vec u v) "Argument is not a polynomial")))
+)
+
+(defun math-do-poly-div (u v)
+  (cond ((math-constp u)
+	 (if (math-constp v)
+	     (cons (math-div u v) 0)
+	   (cons 0 u)))
+	((math-constp v)
+	 (cons (if (eq v 1)
+		   u
+		 (if (memq (car-safe u) '(+ -))
+		     (math-add-or-sub (math-poly-div-exact (nth 1 u) v)
+				      (math-poly-div-exact (nth 2 u) v)
+				      nil (eq (car u) '-))
+		   (math-div u v)))
+	       0))
+	((Math-equal u v)
+	 (cons math-poly-modulus 0))
+	((and (math-atomic-factorp u) (math-atomic-factorp v))
+	 (cons (math-simplify (math-div u v)) 0))
+	(t
+	 (let ((base (or math-poly-div-base
+			 (math-poly-div-base u v)))
+	       vp up res)
+	   (if (or (null base)
+		   (null (setq vp (math-is-polynomial v base nil 'gen))))
+	       (cons 0 u)
+	     (setq up (math-is-polynomial u base nil 'gen)
+		   res (math-poly-div-coefs up vp))
+	     (cons (math-build-polynomial-expr (car res) base)
+		   (math-build-polynomial-expr (cdr res) base))))))
+)
+
+(defun math-poly-div-rec (u v)
+  (cond ((math-constp u)
+	 (math-div u v))
+	((math-constp v)
+	 (if (eq v 1)
+	     u
+	   (if (memq (car-safe u) '(+ -))
+	       (math-add-or-sub (math-poly-div-rec (nth 1 u) v)
+				(math-poly-div-rec (nth 2 u) v)
+				nil (eq (car u) '-))
+	     (math-div u v))))
+	((Math-equal u v) math-poly-modulus)
+	((and (math-atomic-factorp u) (math-atomic-factorp v))
+	 (math-simplify (math-div u v)))
+	(math-poly-div-base
+	 (math-div u v))
+	(t
+	 (let ((base (math-poly-div-base u v))
+	       vp up res)
+	   (if (or (null base)
+		   (null (setq vp (math-is-polynomial v base nil 'gen))))
+	       (math-div u v)
+	     (setq up (math-is-polynomial u base nil 'gen)
+		   res (math-poly-div-coefs up vp))
+	     (math-add (math-build-polynomial-expr (car res) base)
+		       (math-div (math-build-polynomial-expr (cdr res) base)
+				 v))))))
+)
+
+;;; Divide two polynomials in coefficient-list form.  Return (quot . rem).
+(defun math-poly-div-coefs (u v)
+  (cond ((null v) (math-reject-arg nil "Division by zero"))
+	((< (length u) (length v)) (cons nil u))
+	((cdr u)
+	 (let ((q nil)
+	       (urev (reverse u))
+	       (vrev (reverse v)))
+	   (while
+	       (let ((qk (math-poly-div-rec (math-simplify (car urev))
+					    (car vrev)))
+		     (up urev)
+		     (vp vrev))
+		 (if (or q (not (math-zerop qk)))
+		     (setq q (cons qk q)))
+		 (while (setq up (cdr up) vp (cdr vp))
+		   (setcar up (math-sub (car up) (math-mul-thru qk (car vp)))))
+		 (setq urev (cdr urev))
+		 up))
+	   (while (and urev (Math-zerop (car urev)))
+	     (setq urev (cdr urev)))
+	   (cons q (nreverse (mapcar 'math-simplify urev)))))
+	(t
+	 (cons (list (math-poly-div-rec (car u) (car v)))
+	       nil)))
+)
+
+;;; Perform a pseudo-division of polynomials.  (See Knuth section 4.6.1.)
+;;; This returns only the remainder from the pseudo-division.
+(defun math-poly-pseudo-div (u v)
+  (cond ((null v) nil)
+	((< (length u) (length v)) u)
+	((or (cdr u) (cdr v))
+	 (let ((urev (reverse u))
+	       (vrev (reverse v))
+	       up)
+	   (while
+	       (let ((vp vrev))
+		 (setq up urev)
+		 (while (setq up (cdr up) vp (cdr vp))
+		   (setcar up (math-sub (math-mul-thru (car vrev) (car up))
+					(math-mul-thru (car urev) (car vp)))))
+		 (setq urev (cdr urev))
+		 up)
+	     (while up
+	       (setcar up (math-mul-thru (car vrev) (car up)))
+	       (setq up (cdr up))))
+	   (while (and urev (Math-zerop (car urev)))
+	     (setq urev (cdr urev)))
+	   (nreverse (mapcar 'math-simplify urev))))
+	(t nil))
+)
+
+;;; Compute the GCD of two multivariate polynomials.
+(defun math-poly-gcd (u v)
+  (cond ((Math-equal u v) u)
+	((math-constp u)
+	 (if (Math-zerop u)
+	     v
+	   (calcFunc-gcd u (calcFunc-pcont v))))
+	((math-constp v)
+	 (if (Math-zerop v)
+	     v
+	   (calcFunc-gcd v (calcFunc-pcont u))))
+	(t
+	 (let ((base (math-poly-gcd-base u v)))
+	   (if base
+	       (math-simplify
+		(calcFunc-expand
+		 (math-build-polynomial-expr
+		  (math-poly-gcd-coefs (math-is-polynomial u base nil 'gen)
+				       (math-is-polynomial v base nil 'gen))
+		  base)))
+	     (calcFunc-gcd (calcFunc-pcont u) (calcFunc-pcont u))))))
+)
+
+(defun math-poly-div-list (lst a)
+  (if (eq a 1)
+      lst
+    (if (eq a -1)
+	(math-mul-list lst a)
+      (mapcar (function (lambda (x) (math-poly-div-exact x a))) lst)))
+)
+
+(defun math-mul-list (lst a)
+  (if (eq a 1)
+      lst
+    (if (eq a -1)
+	(mapcar 'math-neg lst)
+      (and (not (eq a 0))
+	   (mapcar (function (lambda (x) (math-mul x a))) lst))))
+)
+
+;;; Run GCD on all elements in a list.
+(defun math-poly-gcd-list (lst)
+  (if (or (memq 1 lst) (memq -1 lst))
+      (math-poly-gcd-frac-list lst)
+    (let ((gcd (car lst)))
+      (while (and (setq lst (cdr lst)) (not (eq gcd 1)))
+	(or (eq (car lst) 0)
+	    (setq gcd (math-poly-gcd gcd (car lst)))))
+      (if lst (setq lst (math-poly-gcd-frac-list lst)))
+      gcd))
+)
+
+(defun math-poly-gcd-frac-list (lst)
+  (while (and lst (not (eq (car-safe (car lst)) 'frac)))
+    (setq lst (cdr lst)))
+  (if lst
+      (let ((denom (nth 2 (car lst))))
+	(while (setq lst (cdr lst))
+	  (if (eq (car-safe (car lst)) 'frac)
+	      (setq denom (calcFunc-lcm denom (nth 2 (car lst))))))
+	(list 'frac 1 denom))
+    1)
+)
+
+;;; Compute the GCD of two monovariate polynomial lists.
+;;; Knuth section 4.6.1, algorithm C.
+(defun math-poly-gcd-coefs (u v)
+  (let ((d (math-poly-gcd (math-poly-gcd-list u)
+			  (math-poly-gcd-list v)))
+	(g 1) (h 1) (z 0) hh r delta ghd)
+    (while (and u v (Math-zerop (car u)) (Math-zerop (car v)))
+      (setq u (cdr u) v (cdr v) z (1+ z)))
+    (or (eq d 1)
+	(setq u (math-poly-div-list u d)
+	      v (math-poly-div-list v d)))
+    (while (progn
+	     (setq delta (- (length u) (length v)))
+	     (if (< delta 0)
+		 (setq r u u v v r delta (- delta)))
+	     (setq r (math-poly-pseudo-div u v))
+	     (cdr r))
+      (setq u v
+	    v (math-poly-div-list r (math-mul g (math-pow h delta)))
+	    g (nth (1- (length u)) u)
+	    h (if (<= delta 1)
+		  (math-mul (math-pow g delta) (math-pow h (- 1 delta)))
+		(math-poly-div-exact (math-pow g delta)
+				     (math-pow h (1- delta))))))
+    (setq v (if r
+		(list d)
+	      (math-mul-list (math-poly-div-list v (math-poly-gcd-list v)) d)))
+    (if (math-guess-if-neg (nth (1- (length v)) v))
+	(setq v (math-mul-list v -1)))
+    (while (>= (setq z (1- z)) 0)
+      (setq v (cons 0 v)))
+    v)
+)
+
+
+;;; Return true if is a factor containing no sums or quotients.
+(defun math-atomic-factorp (expr)
+  (cond ((eq (car-safe expr) '*)
+	 (and (math-atomic-factorp (nth 1 expr))
+	      (math-atomic-factorp (nth 2 expr))))
+	((memq (car-safe expr) '(+ - /))
+	 nil)
+	((memq (car-safe expr) '(^ neg))
+	 (math-atomic-factorp (nth 1 expr)))
+	(t t))
+)
+
+;;; Find a suitable base for dividing a by b.
+;;; The base must exist in both expressions.
+;;; The degree in the numerator must be higher or equal than the
+;;; degree in the denominator.
+;;; If the above conditions are not met the quotient is just a remainder.
+;;; Return nil if this is the case.
+
+(defun math-poly-div-base (a b)
+  (let (a-base b-base)
+    (and (setq a-base (math-total-polynomial-base a))
+	 (setq b-base (math-total-polynomial-base b))
+	 (catch 'return
+	   (while a-base
+	     (let ((maybe (assoc (car (car a-base)) b-base)))
+	       (if maybe
+		   (if (>= (nth 1 (car a-base)) (nth 1 maybe))
+		       (throw 'return (car (car a-base))))))
+	     (setq a-base (cdr a-base))))))
+)
+
+;;; Same as above but for gcd algorithm.
+;;; Here there is no requirement that degree(a) > degree(b).
+;;; Take the base that has the highest degree considering both a and b.
+;;; ("a^20+b^21+x^3+a+b", "a+b^2+x^5+a^22+b^10") --> (a 22)
+
+(defun math-poly-gcd-base (a b)
+  (let (a-base b-base)
+    (and (setq a-base (math-total-polynomial-base a))
+	 (setq b-base (math-total-polynomial-base b))
+	 (catch 'return
+	   (while (and a-base b-base)
+	     (if (> (nth 1 (car a-base)) (nth 1 (car b-base)))
+		 (if (assoc (car (car a-base)) b-base)
+		     (throw 'return (car (car a-base)))
+		   (setq a-base (cdr a-base)))
+	       (if (assoc (car (car b-base)) a-base)
+		   (throw 'return (car (car b-base)))
+		 (setq b-base (cdr b-base))))))))
+)
+
+;;; Sort a list of polynomial bases.
+(defun math-sort-poly-base-list (lst)
+  (sort lst (function (lambda (a b)
+			(or (> (nth 1 a) (nth 1 b))
+			    (and (= (nth 1 a) (nth 1 b))
+				 (math-beforep (car a) (car b)))))))
+)
+
+;;; Given an expression find all variables that are polynomial bases.
+;;; Return list in the form '( (var1 degree1) (var2 degree2) ... ).
+;;; Note dynamic scope of mpb-total-base.
+(defun math-total-polynomial-base (expr)
+  (let ((mpb-total-base nil))
+    (math-polynomial-base expr 'math-polynomial-p1)
+    (math-sort-poly-base-list mpb-total-base))
+)
+
+(defun math-polynomial-p1 (subexpr)
+  (or (assoc subexpr mpb-total-base)
+      (memq (car subexpr) '(+ - * / neg))
+      (and (eq (car subexpr) '^) (natnump (nth 2 subexpr)))
+      (let* ((math-poly-base-variable subexpr)
+	     (exponent (math-polynomial-p mpb-top-expr subexpr)))
+	(if exponent
+	    (setq mpb-total-base (cons (list subexpr exponent)
+				       mpb-total-base)))))
+  nil
+)
+
+
+
+
+(defun calcFunc-factors (expr &optional var)
+  (let ((math-factored-vars (if var t nil))
+	(math-to-list t)
+	(calc-prefer-frac t))
+    (or var
+	(setq var (math-polynomial-base expr)))
+    (let ((res (math-factor-finish
+		(or (catch 'factor (math-factor-expr-try var))
+		    expr))))
+      (math-simplify (if (math-vectorp res)
+			 res
+		       (list 'vec (list 'vec res 1))))))
+)
+
+(defun calcFunc-factor (expr &optional var)
+  (let ((math-factored-vars nil)
+	(math-to-list nil)
+	(calc-prefer-frac t))
+    (math-simplify (math-factor-finish
+		    (if var
+			(let ((math-factored-vars t))
+			  (or (catch 'factor (math-factor-expr-try var)) expr))
+		      (math-factor-expr expr)))))
+)
+
+(defun math-factor-finish (x)
+  (if (Math-primp x)
+      x
+    (if (eq (car x) 'calcFunc-Fac-Prot)
+	(math-factor-finish (nth 1 x))
+      (cons (car x) (mapcar 'math-factor-finish (cdr x)))))
+)
+
+(defun math-factor-protect (x)
+  (if (memq (car-safe x) '(+ -))
+      (list 'calcFunc-Fac-Prot x)
+    x)
+)
+
+(defun math-factor-expr (expr)
+  (cond ((eq math-factored-vars t) expr)
+	((or (memq (car-safe expr) '(* / ^ neg))
+	     (assq (car-safe expr) calc-tweak-eqn-table))
+	 (cons (car expr) (mapcar 'math-factor-expr (cdr expr))))
+	((memq (car-safe expr) '(+ -))
+	 (let* ((math-factored-vars math-factored-vars)
+		(y (catch 'factor (math-factor-expr-part expr))))
+	   (if y
+	       (math-factor-expr y)
+	     expr)))
+	(t expr))
+)
+
+(defun math-factor-expr-part (x)    ; uses "expr"
+  (if (memq (car-safe x) '(+ - * / ^ neg))
+      (while (setq x (cdr x))
+	(math-factor-expr-part (car x)))
+    (and (not (Math-objvecp x))
+	 (not (assoc x math-factored-vars))
+	 (> (math-factor-contains expr x) 1)
+	 (setq math-factored-vars (cons (list x) math-factored-vars))
+	 (math-factor-expr-try x)))
+)
+
+(defun math-factor-expr-try (x)
+  (if (eq (car-safe expr) '*)
+      (let ((res1 (catch 'factor (let ((expr (nth 1 expr)))
+				   (math-factor-expr-try x))))
+	    (res2 (catch 'factor (let ((expr (nth 2 expr)))
+				   (math-factor-expr-try x)))))
+	(and (or res1 res2)
+	     (throw 'factor (math-accum-factors (or res1 (nth 1 expr)) 1
+						(or res2 (nth 2 expr))))))
+    (let* ((p (math-is-polynomial expr x 30 'gen))
+	   (math-poly-modulus (math-poly-modulus expr))
+	   res)
+      (and (cdr p)
+	   (setq res (math-factor-poly-coefs p))
+	   (throw 'factor res))))
+)
+
+(defun math-accum-factors (fac pow facs)
+  (if math-to-list
+      (if (math-vectorp fac)
+	  (progn
+	    (while (setq fac (cdr fac))
+	      (setq facs (math-accum-factors (nth 1 (car fac))
+					     (* pow (nth 2 (car fac)))
+					     facs)))
+	    facs)
+	(if (and (eq (car-safe fac) '^) (natnump (nth 2 fac)))
+	    (setq pow (* pow (nth 2 fac))
+		  fac (nth 1 fac)))
+	(if (eq fac 1)
+	    facs
+	  (or (math-vectorp facs)
+	      (setq facs (if (eq facs 1) '(vec)
+			   (list 'vec (list 'vec facs 1)))))
+	  (let ((found facs))
+	    (while (and (setq found (cdr found))
+			(not (equal fac (nth 1 (car found))))))
+	    (if found
+		(progn
+		  (setcar (cdr (cdr (car found))) (+ pow (nth 2 (car found))))
+		  facs)
+	      ;; Put constant term first.
+	      (if (and (cdr facs) (Math-ratp (nth 1 (nth 1 facs))))
+		  (cons 'vec (cons (nth 1 facs) (cons (list 'vec fac pow)
+						      (cdr (cdr facs)))))
+		(cons 'vec (cons (list 'vec fac pow) (cdr facs))))))))
+    (math-mul (math-pow fac pow) facs))
+)
+
+(defun math-factor-poly-coefs (p &optional square-free)    ; uses "x"
+  (let (t1 t2)
+    (cond ((not (cdr p))
+	   (or (car p) 0))
+
+	  ;; Strip off multiples of x.
+	  ((Math-zerop (car p))
+	   (let ((z 0))
+	     (while (and p (Math-zerop (car p)))
+	       (setq z (1+ z) p (cdr p)))
+	     (if (cdr p)
+		 (setq p (math-factor-poly-coefs p square-free))
+	       (setq p (math-sort-terms (math-factor-expr (car p)))))
+	     (math-accum-factors x z (math-factor-protect p))))
+
+	  ;; Factor out content.
+	  ((and (not square-free)
+		(not (eq 1 (setq t1 (math-mul (math-poly-gcd-list p)
+					      (if (math-guess-if-neg
+						   (nth (1- (length p)) p))
+						  -1 1))))))
+	   (math-accum-factors t1 1 (math-factor-poly-coefs
+				     (math-poly-div-list p t1) 'cont)))
+
+	  ;; Check if linear in x.
+	  ((not (cdr (cdr p)))
+	   (math-add (math-factor-protect
+		      (math-sort-terms
+		       (math-factor-expr (car p))))
+		     (math-mul x (math-factor-protect
+				  (math-sort-terms
+				   (math-factor-expr (nth 1 p)))))))
+
+	  ;; If symbolic coefficients, use FactorRules.
+	  ((let ((pp p))
+	     (while (and pp (or (Math-ratp (car pp))
+				(and (eq (car (car pp)) 'mod)
+				     (Math-integerp (nth 1 (car pp)))
+				     (Math-integerp (nth 2 (car pp))))))
+	       (setq pp (cdr pp)))
+	     pp)
+	   (let ((res (math-rewrite
+		       (list 'calcFunc-thecoefs x (cons 'vec p))
+		       '(var FactorRules var-FactorRules))))
+	     (or (and (eq (car-safe res) 'calcFunc-thefactors)
+		      (= (length res) 3)
+		      (math-vectorp (nth 2 res))
+		      (let ((facs 1)
+			    (vec (nth 2 res)))
+			(while (setq vec (cdr vec))
+			  (setq facs (math-accum-factors (car vec) 1 facs)))
+			facs))
+		 (math-build-polynomial-expr p x))))
+
+	  ;; Check if rational coefficients (i.e., not modulo a prime).
+	  ((eq math-poly-modulus 1)
+
+	   ;; Check if there are any squared terms, or a content not = 1.
+	   (if (or (eq square-free t)
+		   (equal (setq t1 (math-poly-gcd-coefs
+				    p (setq t2 (math-poly-deriv-coefs p))))
+			  '(1)))
+
+	       ;; We now have a square-free polynomial with integer coefs.
+	       ;; For now, we use a kludgey method that finds linear and
+	       ;; quadratic terms using floating-point root-finding.
+	       (if (setq t1 (let ((calc-symbolic-mode nil))
+			      (math-poly-all-roots nil p t)))
+		   (let ((roots (car t1))
+			 (csign (if (math-negp (nth (1- (length p)) p)) -1 1))
+			 (expr 1)
+			 (unfac (nth 1 t1))
+			 (scale (nth 2 t1)))
+		     (while roots
+		       (let ((coef0 (car (car roots)))
+			     (coef1 (cdr (car roots))))
+			 (setq expr (math-accum-factors
+				     (if coef1
+					 (let ((den (math-lcm-denoms
+						     coef0 coef1)))
+					   (setq scale (math-div scale den))
+					   (math-add
+					    (math-add
+					     (math-mul den (math-pow x 2))
+					     (math-mul (math-mul coef1 den) x))
+					    (math-mul coef0 den)))
+				       (let ((den (math-lcm-denoms coef0)))
+					 (setq scale (math-div scale den))
+					 (math-add (math-mul den x)
+						   (math-mul coef0 den))))
+				     1 expr)
+			       roots (cdr roots))))
+		     (setq expr (math-accum-factors
+				 expr 1
+				 (math-mul csign
+					   (math-build-polynomial-expr
+					    (math-mul-list (nth 1 t1) scale)
+					    x)))))
+		 (math-build-polynomial-expr p x))   ; can't factor it.
+
+	     ;; Separate out the squared terms (Knuth exercise 4.6.2-34).
+	     ;; This step also divides out the content of the polynomial.
+	     (let* ((cabs (math-poly-gcd-list p))
+		    (csign (if (math-negp (nth (1- (length p)) p)) -1 1))
+		    (t1s (math-mul-list t1 csign))
+		    (uu nil)
+		    (v (car (math-poly-div-coefs p t1s)))
+		    (w (car (math-poly-div-coefs t2 t1s))))
+	       (while
+		   (not (math-poly-zerop
+			 (setq t2 (math-poly-simplify
+				   (math-poly-mix
+				    w 1 (math-poly-deriv-coefs v) -1)))))
+		 (setq t1 (math-poly-gcd-coefs v t2)
+		       uu (cons t1 uu)
+		       v (car (math-poly-div-coefs v t1))
+		       w (car (math-poly-div-coefs t2 t1))))
+	       (setq t1 (length uu)
+		     t2 (math-accum-factors (math-factor-poly-coefs v t)
+					    (1+ t1) 1))
+	       (while uu
+		 (setq t2 (math-accum-factors (math-factor-poly-coefs
+					       (car uu) t)
+					      t1 t2)
+		       t1 (1- t1)
+		       uu (cdr uu)))
+	       (math-accum-factors (math-mul cabs csign) 1 t2))))
+
+	  ;; Factoring modulo a prime.
+	  ((and (= (length (setq temp (math-poly-gcd-coefs
+				       p (math-poly-deriv-coefs p))))
+		   (length p)))
+	   (setq p (car temp))
+	   (while (cdr temp)
+	     (setq temp (nthcdr (nth 2 math-poly-modulus) temp)
+		   p (cons (car temp) p)))
+	   (and (setq temp (math-factor-poly-coefs p))
+		(math-pow temp (nth 2 math-poly-modulus))))
+	  (t
+	   (math-reject-arg nil "*Modulo factorization not yet implemented"))))
+)
+
+(defun math-poly-deriv-coefs (p)
+  (let ((n 1)
+	(dp nil))
+    (while (setq p (cdr p))
+      (setq dp (cons (math-mul (car p) n) dp)
+	    n (1+ n)))
+    (nreverse dp))
+)
+
+(defun math-factor-contains (x a)
+  (if (equal x a)
+      1
+    (if (memq (car-safe x) '(+ - * / neg))
+	(let ((sum 0))
+	  (while (setq x (cdr x))
+	    (setq sum (+ sum (math-factor-contains (car x) a))))
+	  sum)
+      (if (and (eq (car-safe x) '^)
+	       (natnump (nth 2 x)))
+	  (* (math-factor-contains (nth 1 x) a) (nth 2 x))
+	0)))
+)
+
+
+
+
+
+;;; Merge all quotients and expand/simplify the numerator
+(defun calcFunc-nrat (expr)
+  (if (math-any-floats expr)
+      (setq expr (calcFunc-pfrac expr)))
+  (if (or (math-vectorp expr)
+	  (assq (car-safe expr) calc-tweak-eqn-table))
+      (cons (car expr) (mapcar 'calcFunc-nrat (cdr expr)))
+    (let* ((calc-prefer-frac t)
+	   (res (math-to-ratpoly expr))
+	   (num (math-simplify (math-sort-terms (calcFunc-expand (car res)))))
+	   (den (math-simplify (math-sort-terms (calcFunc-expand (cdr res)))))
+	   (g (math-poly-gcd num den)))
+      (or (eq g 1)
+	  (let ((num2 (math-poly-div num g))
+		(den2 (math-poly-div den g)))
+	    (and (eq (cdr num2) 0) (eq (cdr den2) 0)
+		 (setq num (car num2) den (car den2)))))
+      (math-simplify (math-div num den))))
+)
+
+;;; Returns expressions (num . denom).
+(defun math-to-ratpoly (expr)
+  (let ((res (math-to-ratpoly-rec expr)))
+    (cons (math-simplify (car res)) (math-simplify (cdr res))))
+)
+
+(defun math-to-ratpoly-rec (expr)
+  (cond ((Math-primp expr)
+	 (cons expr 1))
+	((memq (car expr) '(+ -))
+	 (let ((r1 (math-to-ratpoly-rec (nth 1 expr)))
+	       (r2 (math-to-ratpoly-rec (nth 2 expr))))
+	   (if (equal (cdr r1) (cdr r2))
+	       (cons (list (car expr) (car r1) (car r2)) (cdr r1))
+	     (if (eq (cdr r1) 1)
+		 (cons (list (car expr)
+			     (math-mul (car r1) (cdr r2))
+			     (car r2))
+		       (cdr r2))
+	       (if (eq (cdr r2) 1)
+		   (cons (list (car expr)
+			       (car r1)
+			       (math-mul (car r2) (cdr r1)))
+			 (cdr r1))
+		 (let ((g (math-poly-gcd (cdr r1) (cdr r2))))
+		   (let ((d1 (and (not (eq g 1)) (math-poly-div (cdr r1) g)))
+			 (d2 (and (not (eq g 1)) (math-poly-div
+						  (math-mul (car r1) (cdr r2))
+						  g))))
+		     (if (and (eq (cdr d1) 0) (eq (cdr d2) 0))
+			 (cons (list (car expr) (car d2)
+				     (math-mul (car r2) (car d1)))
+			       (math-mul (car d1) (cdr r2)))
+		       (cons (list (car expr)
+				   (math-mul (car r1) (cdr r2))
+				   (math-mul (car r2) (cdr r1)))
+			     (math-mul (cdr r1) (cdr r2)))))))))))
+	((eq (car expr) '*)
+	 (let* ((r1 (math-to-ratpoly-rec (nth 1 expr)))
+		(r2 (math-to-ratpoly-rec (nth 2 expr)))
+		(g (math-mul (math-poly-gcd (car r1) (cdr r2))
+			     (math-poly-gcd (cdr r1) (car r2)))))
+	   (if (eq g 1)
+	       (cons (math-mul (car r1) (car r2))
+		     (math-mul (cdr r1) (cdr r2)))
+	     (cons (math-poly-div-exact (math-mul (car r1) (car r2)) g)
+		   (math-poly-div-exact (math-mul (cdr r1) (cdr r2)) g)))))
+	((eq (car expr) '/)
+	 (let* ((r1 (math-to-ratpoly-rec (nth 1 expr)))
+		(r2 (math-to-ratpoly-rec (nth 2 expr))))
+	   (if (and (eq (cdr r1) 1) (eq (cdr r2) 1))
+	       (cons (car r1) (car r2))
+	     (let ((g (math-mul (math-poly-gcd (car r1) (car r2))
+				(math-poly-gcd (cdr r1) (cdr r2)))))
+	       (if (eq g 1)
+		   (cons (math-mul (car r1) (cdr r2))
+			 (math-mul (cdr r1) (car r2)))
+		 (cons (math-poly-div-exact (math-mul (car r1) (cdr r2)) g)
+		       (math-poly-div-exact (math-mul (cdr r1) (car r2))
+					    g)))))))
+	((and (eq (car expr) '^) (integerp (nth 2 expr)))
+	 (let ((r1 (math-to-ratpoly-rec (nth 1 expr))))
+	   (if (> (nth 2 expr) 0)
+	       (cons (math-pow (car r1) (nth 2 expr))
+		     (math-pow (cdr r1) (nth 2 expr)))
+	     (cons (math-pow (cdr r1) (- (nth 2 expr)))
+		   (math-pow (car r1) (- (nth 2 expr)))))))
+	((eq (car expr) 'neg)
+	 (let ((r1 (math-to-ratpoly-rec (nth 1 expr))))
+	   (cons (math-neg (car r1)) (cdr r1))))
+	(t (cons expr 1)))
+)
+
+
+(defun math-ratpoly-p (expr &optional var)
+  (cond ((equal expr var) 1)
+	((Math-primp expr) 0)
+	((memq (car expr) '(+ -))
+	 (let ((p1 (math-ratpoly-p (nth 1 expr) var))
+	       p2)
+	   (and p1 (setq p2 (math-ratpoly-p (nth 2 expr) var))
+		(max p1 p2))))
+	((eq (car expr) '*)
+	 (let ((p1 (math-ratpoly-p (nth 1 expr) var))
+	       p2)
+	   (and p1 (setq p2 (math-ratpoly-p (nth 2 expr) var))
+		(+ p1 p2))))
+	((eq (car expr) 'neg)
+	 (math-ratpoly-p (nth 1 expr) var))
+	((eq (car expr) '/)
+	 (let ((p1 (math-ratpoly-p (nth 1 expr) var))
+	       p2)
+	   (and p1 (setq p2 (math-ratpoly-p (nth 2 expr) var))
+		(- p1 p2))))
+	((and (eq (car expr) '^)
+	      (integerp (nth 2 expr)))
+	 (let ((p1 (math-ratpoly-p (nth 1 expr) var)))
+	   (and p1 (* p1 (nth 2 expr)))))
+	((not var) 1)
+	((math-poly-depends expr var) nil)
+	(t 0))
+)
+
+
+(defun calcFunc-apart (expr &optional var)
+  (cond ((Math-primp expr) expr)
+	((eq (car expr) '+)
+	 (math-add (calcFunc-apart (nth 1 expr) var)
+		   (calcFunc-apart (nth 2 expr) var)))
+	((eq (car expr) '-)
+	 (math-sub (calcFunc-apart (nth 1 expr) var)
+		   (calcFunc-apart (nth 2 expr) var)))
+	((not (math-ratpoly-p expr var))
+	 (math-reject-arg expr "Expected a rational function"))
+	(t
+	 (let* ((calc-prefer-frac t)
+		(rat (math-to-ratpoly expr))
+		(num (car rat))
+		(den (cdr rat))
+		(qr (math-poly-div num den))
+		(q (car qr))
+		(r (cdr qr)))
+	   (or var
+	       (setq var (math-polynomial-base den)))
+	   (math-add q (or (and var
+				(math-expr-contains den var)
+				(math-partial-fractions r den var))
+			   (math-div r den))))))
+)
+
+
+(defun math-padded-polynomial (expr var deg)
+  (let ((p (math-is-polynomial expr var deg)))
+    (append p (make-list (- deg (length p)) 0)))
+)
+
+(defun math-partial-fractions (r den var)
+  (let* ((fden (calcFunc-factors den var))
+	 (tdeg (math-polynomial-p den var))
+	 (fp fden)
+	 (dlist nil)
+	 (eqns 0)
+	 (lz nil)
+	 (tz (make-list (1- tdeg) 0))
+	 (calc-matrix-mode 'scalar))
+    (and (not (and (= (length fden) 2) (eq (nth 2 (nth 1 fden)) 1)))
+	 (progn
+	   (while (setq fp (cdr fp))
+	     (let ((rpt (nth 2 (car fp)))
+		   (deg (math-polynomial-p (nth 1 (car fp)) var))
+		   dnum dvar deg2)
+	       (while (> rpt 0)
+		 (setq deg2 deg
+		       dnum 0)
+		 (while (> deg2 0)
+		   (setq dvar (append '(vec) lz '(1) tz)
+			 lz (cons 0 lz)
+			 tz (cdr tz)
+			 deg2 (1- deg2)
+			 dnum (math-add dnum (math-mul dvar
+						       (math-pow var deg2)))
+			 dlist (cons (and (= deg2 (1- deg))
+					  (math-pow (nth 1 (car fp)) rpt))
+				     dlist)))
+		 (let ((fpp fden)
+		       (mult 1))
+		   (while (setq fpp (cdr fpp))
+		     (or (eq fpp fp)
+			 (setq mult (math-mul mult
+					      (math-pow (nth 1 (car fpp))
+							(nth 2 (car fpp)))))))
+		   (setq dnum (math-mul dnum mult)))
+		 (setq eqns (math-add eqns (math-mul dnum
+						     (math-pow
+						      (nth 1 (car fp))
+						      (- (nth 2 (car fp))
+							 rpt))))
+		       rpt (1- rpt)))))
+	   (setq eqns (math-div (cons 'vec (math-padded-polynomial r var tdeg))
+				(math-transpose
+				 (cons 'vec
+				       (mapcar
+					(function
+					 (lambda (x)
+					   (cons 'vec (math-padded-polynomial
+						       x var tdeg))))
+					(cdr eqns))))))
+	   (and (math-vectorp eqns)
+		(let ((res 0)
+		      (num nil))
+		  (setq eqns (nreverse eqns))
+		  (while eqns
+		    (setq num (cons (car eqns) num)
+			  eqns (cdr eqns))
+		    (if (car dlist)
+			(setq num (math-build-polynomial-expr
+				   (nreverse num) var)
+			      res (math-add res (math-div num (car dlist)))
+			      num nil))
+		    (setq dlist (cdr dlist)))
+		  (math-normalize res))))))
+)
+
+
+
+(defun math-expand-term (expr)
+  (cond ((and (eq (car-safe expr) '*)
+	      (memq (car-safe (nth 1 expr)) '(+ -)))
+	 (math-add-or-sub (list '* (nth 1 (nth 1 expr)) (nth 2 expr))
+			  (list '* (nth 2 (nth 1 expr)) (nth 2 expr))
+			  nil (eq (car (nth 1 expr)) '-)))
+	((and (eq (car-safe expr) '*)
+	      (memq (car-safe (nth 2 expr)) '(+ -)))
+	 (math-add-or-sub (list '* (nth 1 expr) (nth 1 (nth 2 expr)))
+			  (list '* (nth 1 expr) (nth 2 (nth 2 expr)))
+			  nil (eq (car (nth 2 expr)) '-)))
+	((and (eq (car-safe expr) '/)
+	      (memq (car-safe (nth 1 expr)) '(+ -)))
+	 (math-add-or-sub (list '/ (nth 1 (nth 1 expr)) (nth 2 expr))
+			  (list '/ (nth 2 (nth 1 expr)) (nth 2 expr))
+			  nil (eq (car (nth 1 expr)) '-)))
+	((and (eq (car-safe expr) '^)
+	      (memq (car-safe (nth 1 expr)) '(+ -))
+	      (integerp (nth 2 expr))
+	      (if (> (nth 2 expr) 0)
+		  (or (and (or (> mmt-many 500000) (< mmt-many -500000))
+			   (math-expand-power (nth 1 expr) (nth 2 expr)
+					      nil t))
+		      (list '*
+			    (nth 1 expr)
+			    (list '^ (nth 1 expr) (1- (nth 2 expr)))))
+		(if (< (nth 2 expr) 0)
+		    (list '/ 1 (list '^ (nth 1 expr) (- (nth 2 expr))))))))
+	(t expr))
+)
+
+(defun calcFunc-expand (expr &optional many)
+  (math-normalize (math-map-tree 'math-expand-term expr many))
+)
+
+(defun math-expand-power (x n &optional var else-nil)
+  (or (and (natnump n)
+	   (memq (car-safe x) '(+ -))
+	   (let ((terms nil)
+		 (cterms nil))
+	     (while (memq (car-safe x) '(+ -))
+	       (setq terms (cons (if (eq (car x) '-)
+				     (math-neg (nth 2 x))
+				   (nth 2 x))
+				 terms)
+		     x (nth 1 x)))
+	     (setq terms (cons x terms))
+	     (if var
+		 (let ((p terms))
+		   (while p
+		     (or (math-expr-contains (car p) var)
+			 (setq terms (delq (car p) terms)
+			       cterms (cons (car p) cterms)))
+		     (setq p (cdr p)))
+		   (if cterms
+		       (setq terms (cons (apply 'calcFunc-add cterms)
+					 terms)))))
+	     (if (= (length terms) 2)
+		 (let ((i 0)
+		       (accum 0))
+		   (while (<= i n)
+		     (setq accum (list '+ accum
+				       (list '* (calcFunc-choose n i)
+					     (list '*
+						   (list '^ (nth 1 terms) i)
+						   (list '^ (car terms)
+							 (- n i)))))
+			   i (1+ i)))
+		   accum)
+	       (if (= n 2)
+		   (let ((accum 0)
+			 (p1 terms)
+			 p2)
+		     (while p1
+		       (setq accum (list '+ accum
+					 (list '^ (car p1) 2))
+			     p2 p1)
+		       (while (setq p2 (cdr p2))
+			 (setq accum (list '+ accum
+					   (list '* 2 (list '*
+							    (car p1)
+							    (car p2))))))
+		       (setq p1 (cdr p1)))
+		     accum)
+		 (if (= n 3)
+		     (let ((accum 0)
+			   (p1 terms)
+			   p2 p3)
+		       (while p1
+			 (setq accum (list '+ accum (list '^ (car p1) 3))
+			       p2 p1)
+			 (while (setq p2 (cdr p2))
+			   (setq accum (list '+
+					     (list '+
+						   accum
+						   (list '* 3
+							 (list
+							  '*
+							  (list '^ (car p1) 2)
+							  (car p2))))
+					     (list '* 3
+						   (list
+						    '* (car p1)
+						    (list '^ (car p2) 2))))
+				 p3 p2)
+			   (while (setq p3 (cdr p3))
+			     (setq accum (list '+ accum
+					       (list '* 6
+						     (list '*
+							   (car p1)
+							   (list
+							    '* (car p2)
+							    (car p3))))))))
+			 (setq p1 (cdr p1)))
+		       accum))))))
+      (and (not else-nil)
+	   (list '^ x n)))
+)
+
+(defun calcFunc-expandpow (x n)
+  (math-normalize (math-expand-power x n))
+)
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/calc-prog.el	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,2364 @@
+;; Calculator for GNU Emacs, part II [calc-prog.el]
+;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+;; Written by Dave Gillespie, daveg@synaptics.com.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY.  No author or distributor
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing.  Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License.   A copy of this license is
+;; supposed to have been given to you along with GNU Emacs so you
+;; can know your rights and responsibilities.  It should be in a
+;; file named COPYING.  Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+
+
+
+;; This file is autoloaded from calc-ext.el.
+(require 'calc-ext)
+
+(require 'calc-macs)
+
+(defun calc-Need-calc-prog () nil)
+
+
+(defun calc-equal-to (arg)
+  (interactive "P")
+  (calc-wrapper
+   (if (and (integerp arg) (> arg 2))
+       (calc-enter-result arg "eq" (cons 'calcFunc-eq (calc-top-list-n arg)))
+     (calc-binary-op "eq" 'calcFunc-eq arg)))
+)
+
+(defun calc-remove-equal (arg)
+  (interactive "P")
+  (calc-wrapper
+   (calc-unary-op "rmeq" 'calcFunc-rmeq arg))
+)
+
+(defun calc-not-equal-to (arg)
+  (interactive "P")
+  (calc-wrapper
+   (if (and (integerp arg) (> arg 2))
+       (calc-enter-result arg "neq" (cons 'calcFunc-neq (calc-top-list-n arg)))
+     (calc-binary-op "neq" 'calcFunc-neq arg)))
+)
+
+(defun calc-less-than (arg)
+  (interactive "P")
+  (calc-wrapper
+   (calc-binary-op "lt" 'calcFunc-lt arg))
+)
+
+(defun calc-greater-than (arg)
+  (interactive "P")
+  (calc-wrapper
+   (calc-binary-op "gt" 'calcFunc-gt arg))
+)
+
+(defun calc-less-equal (arg)
+  (interactive "P")
+  (calc-wrapper
+   (calc-binary-op "leq" 'calcFunc-leq arg))
+)
+
+(defun calc-greater-equal (arg)
+  (interactive "P")
+  (calc-wrapper
+   (calc-binary-op "geq" 'calcFunc-geq arg))
+)
+
+(defun calc-in-set (arg)
+  (interactive "P")
+  (calc-wrapper
+   (calc-binary-op "in" 'calcFunc-in arg))
+)
+
+(defun calc-logical-and (arg)
+  (interactive "P")
+  (calc-wrapper
+   (calc-binary-op "land" 'calcFunc-land arg 1))
+)
+
+(defun calc-logical-or (arg)
+  (interactive "P")
+  (calc-wrapper
+   (calc-binary-op "lor" 'calcFunc-lor arg 0))
+)
+
+(defun calc-logical-not (arg)
+  (interactive "P")
+  (calc-wrapper
+   (calc-unary-op "lnot" 'calcFunc-lnot arg))
+)
+
+(defun calc-logical-if ()
+  (interactive)
+  (calc-wrapper
+   (calc-enter-result 3 "if" (cons 'calcFunc-if (calc-top-list-n 3))))
+)
+
+
+
+
+
+(defun calc-timing (n)
+  (interactive "P")
+  (calc-wrapper
+   (calc-change-mode 'calc-timing n nil t)
+   (message (if calc-timing
+		"Reporting timing of slow commands in Trail."
+	      "Not reporting timing of commands.")))
+)
+
+(defun calc-pass-errors ()
+  (interactive)
+  ;; The following two cases are for the new, optimizing byte compiler
+  ;; or the standard 18.57 byte compiler, respectively.
+  (condition-case err
+      (let ((place (aref (nth 2 (nth 2 (symbol-function 'calc-do))) 15)))
+	(or (memq (car-safe (car-safe place)) '(error xxxerror))
+	    (setq place (aref (nth 2 (nth 2 (symbol-function 'calc-do))) 27)))
+	(or (memq (car (car place)) '(error xxxerror))
+	    (error "foo"))
+	(setcar (car place) 'xxxerror))
+    (error (error "The calc-do function has been modified; unable to patch.")))
+)
+
+(defun calc-user-define ()
+  (interactive)
+  (message "Define user key: z-")
+  (let ((key (read-char)))
+    (if (= (calc-user-function-classify key) 0)
+	(error "Can't redefine \"?\" key"))
+    (let ((func (intern (completing-read (concat "Set key z "
+						 (char-to-string key)
+						 " to command: ")
+					 obarray
+					 'commandp
+					 t
+					 "calc-"))))
+      (let* ((kmap (calc-user-key-map))
+	     (old (assq key kmap)))
+	(if old
+	    (setcdr old func)
+	  (setcdr kmap (cons (cons key func) (cdr kmap)))))))
+)
+
+(defun calc-user-undefine ()
+  (interactive)
+  (message "Undefine user key: z-")
+  (let ((key (read-char)))
+    (if (= (calc-user-function-classify key) 0)
+	(error "Can't undefine \"?\" key"))
+    (let* ((kmap (calc-user-key-map)))
+      (delq (or (assq key kmap)
+		(assq (upcase key) kmap)
+		(assq (downcase key) kmap)
+		(error "No such user key is defined"))
+	    kmap)))
+)
+
+(defun calc-user-define-formula ()
+  (interactive)
+  (calc-wrapper
+   (let* ((form (calc-top 1))
+	  (arglist nil)
+	  (is-lambda (and (eq (car-safe form) 'calcFunc-lambda)
+			  (>= (length form) 2)))
+	  odef key keyname cmd cmd-base func alist is-symb)
+     (if is-lambda
+	 (setq arglist (mapcar (function (lambda (x) (nth 1 x)))
+			       (nreverse (cdr (reverse (cdr form)))))
+	       form (nth (1- (length form)) form))
+       (calc-default-formula-arglist form)
+       (setq arglist (sort arglist 'string-lessp)))
+     (message "Define user key: z-")
+     (setq key (read-char))
+     (if (= (calc-user-function-classify key) 0)
+	 (error "Can't redefine \"?\" key"))
+     (setq key (and (not (memq key '(13 32))) key)
+	   keyname (and key
+			(if (or (and (<= ?0 key) (<= key ?9))
+				(and (<= ?a key) (<= key ?z))
+				(and (<= ?A key) (<= key ?Z)))
+			    (char-to-string key)
+			  (format "%03d" key)))
+	   odef (assq key (calc-user-key-map)))
+     (while
+	 (progn
+	   (setq cmd (completing-read "Define M-x command name: "
+				      obarray 'commandp nil
+				      (if (and odef (symbolp (cdr odef)))
+					  (symbol-name (cdr odef))
+					"calc-"))
+		 cmd-base (and (string-match "\\`calc-\\(.+\\)\\'" cmd)
+			       (math-match-substring cmd 1))
+		 cmd (and (not (or (string-equal cmd "")
+				   (string-equal cmd "calc-")))
+			  (intern cmd)))
+	   (and cmd
+		(fboundp cmd)
+		odef
+		(not
+		 (y-or-n-p
+		  (if (get cmd 'calc-user-defn)
+		      (concat "Replace previous definition for "
+			      (symbol-name cmd) "? ")
+		    "That name conflicts with a built-in Emacs function.  Replace this function? "))))))
+     (if (and key (not cmd))
+	 (setq cmd (intern (concat "calc-User-" keyname))))
+     (while
+	 (progn
+	   (setq func (completing-read "Define algebraic function name: "
+				       obarray 'fboundp nil
+				       (concat "calcFunc-"
+					       (if cmd-base
+						   (if (string-match
+							"\\`User-.+" cmd-base)
+						       (concat
+							"User"
+							(substring cmd-base 5))
+						     cmd-base)
+						 "")))
+		 func (and (not (or (string-equal func "")
+				    (string-equal func "calcFunc-")))
+			   (intern func)))
+	   (and func
+		(fboundp func)
+		(not (fboundp cmd))
+		odef
+		(not
+		 (y-or-n-p
+		  (if (get func 'calc-user-defn)
+		      (concat "Replace previous definition for "
+			      (symbol-name func) "? ")
+		    "That name conflicts with a built-in Emacs function.  Replace this function? "))))))
+     (if (not func)
+	 (setq func (intern (concat "calcFunc-User"
+				    (or keyname
+					(and cmd (symbol-name cmd))
+					(format "%05d" (% (random) 10000)))))))
+     (if is-lambda
+	 (setq alist arglist)
+       (while
+	   (progn
+	     (setq alist (read-from-minibuffer "Function argument list: "
+					       (if arglist
+						   (prin1-to-string arglist)
+						 "()")
+					       minibuffer-local-map
+					       t))
+	     (and (not (calc-subsetp alist arglist))
+		  (not (y-or-n-p
+			"Okay for arguments that don't appear in formula to be ignored? "))))))
+     (setq is-symb (and alist
+			func
+			(y-or-n-p
+			 "Leave it symbolic for non-constant arguments? ")))
+     (setq alist (mapcar (function (lambda (x)
+				     (or (cdr (assq x '((nil . arg-nil)
+							(t . arg-t))))
+					 x))) alist))
+     (if cmd
+	 (progn
+	   (calc-need-macros)
+	   (fset cmd
+		 (list 'lambda
+		       '()
+		       '(interactive)
+		       (list 'calc-wrapper
+			     (list 'calc-enter-result
+				   (length alist)
+				   (let ((name (symbol-name (or func cmd))))
+				     (and (string-match
+					   "\\([^-][^-]?[^-]?[^-]?\\)[^-]*\\'"
+					   name)
+					  (math-match-substring name 1)))
+				   (list 'cons
+					 (list 'quote func)
+					 (list 'calc-top-list-n
+					       (length alist)))))))
+	   (put cmd 'calc-user-defn t)))
+     (let ((body (list 'math-normalize (calc-fix-user-formula form))))
+       (fset func
+	     (append
+	      (list 'lambda alist)
+	      (and is-symb
+		   (mapcar (function (lambda (v)
+				       (list 'math-check-const v t)))
+			   alist))
+	      (list body))))
+     (put func 'calc-user-defn form)
+     (setq math-integral-cache-state nil)
+     (if key
+	 (let* ((kmap (calc-user-key-map))
+		(old (assq key kmap)))
+	   (if old
+	       (setcdr old cmd)
+	     (setcdr kmap (cons (cons key cmd) (cdr kmap)))))))
+   (message ""))
+)
+
+(defun calc-default-formula-arglist (form)
+  (if (consp form)
+      (if (eq (car form) 'var)
+	  (if (or (memq (nth 1 form) arglist)
+		  (math-const-var form))
+	      ()
+	    (setq arglist (cons (nth 1 form) arglist)))
+	(calc-default-formula-arglist-step (cdr form))))
+)
+
+(defun calc-default-formula-arglist-step (l)
+  (and l
+       (progn
+	 (calc-default-formula-arglist (car l))
+	 (calc-default-formula-arglist-step (cdr l))))
+)
+
+(defun calc-subsetp (a b)
+  (or (null a)
+      (and (memq (car a) b)
+	   (calc-subsetp (cdr a) b)))
+)
+
+(defun calc-fix-user-formula (f)
+  (if (consp f)
+      (let (temp)
+	(cond ((and (eq (car f) 'var)
+		    (memq (setq temp (or (cdr (assq (nth 1 f) '((nil . arg-nil)
+								(t . arg-t))))
+					 (nth 1 f)))
+			  alist))
+	       temp)
+	      ((or (math-constp f) (eq (car f) 'var))
+	       (list 'quote f))
+	      ((and (eq (car f) 'calcFunc-eval)
+		    (= (length f) 2))
+	       (list 'let '((calc-simplify-mode nil))
+		     (list 'math-normalize (calc-fix-user-formula (nth 1 f)))))
+	      ((and (eq (car f) 'calcFunc-evalsimp)
+		    (= (length f) 2))
+	       (list 'math-simplify (calc-fix-user-formula (nth 1 f))))
+	      ((and (eq (car f) 'calcFunc-evalextsimp)
+		    (= (length f) 2))
+	       (list 'math-simplify-extended
+		     (calc-fix-user-formula (nth 1 f))))
+	      (t
+	       (cons 'list
+		     (cons (list 'quote (car f))
+			   (mapcar 'calc-fix-user-formula (cdr f)))))))
+    f)
+)
+
+(defun calc-user-define-composition ()
+  (interactive)
+  (calc-wrapper
+   (if (eq calc-language 'unform)
+       (error "Can't define formats for unformatted mode"))
+   (let* ((comp (calc-top 1))
+	  (func (intern (completing-read "Define format for which function: "
+					 obarray 'fboundp nil "calcFunc-")))
+	  (comps (get func 'math-compose-forms))
+	  entry entry2
+	  (arglist nil)
+	  (alist nil))
+     (if (math-zerop comp)
+	 (if (setq entry (assq calc-language comps))
+	     (put func 'math-compose-forms (delq entry comps)))
+       (calc-default-formula-arglist comp)
+       (setq arglist (sort arglist 'string-lessp))
+       (while
+	   (progn
+	     (setq alist (read-from-minibuffer "Composition argument list: "
+					       (if arglist
+						   (prin1-to-string arglist)
+						 "()")
+					       minibuffer-local-map
+					       t))
+	     (and (not (calc-subsetp alist arglist))
+		  (y-or-n-p
+		   "Okay for arguments that don't appear in formula to be invisible? "))))
+       (or (setq entry (assq calc-language comps))
+	   (put func 'math-compose-forms
+		(cons (setq entry (list calc-language)) comps)))
+       (or (setq entry2 (assq (length alist) (cdr entry)))
+	   (setcdr entry
+		   (cons (setq entry2 (list (length alist))) (cdr entry))))
+       (setcdr entry2 (list 'lambda alist (calc-fix-user-formula comp))))
+     (calc-pop-stack 1)
+     (calc-do-refresh)))
+)
+
+
+(defun calc-user-define-kbd-macro (arg)
+  (interactive "P")
+  (or last-kbd-macro
+      (error "No keyboard macro defined"))
+  (message "Define last kbd macro on user key: z-")
+  (let ((key (read-char)))
+    (if (= (calc-user-function-classify key) 0)
+	(error "Can't redefine \"?\" key"))
+    (let ((cmd (intern (completing-read "Full name for new command: "
+					obarray
+					'commandp
+					nil
+					(concat "calc-User-"
+						(if (or (and (>= key ?a)
+							     (<= key ?z))
+							(and (>= key ?A)
+							     (<= key ?Z))
+							(and (>= key ?0)
+							     (<= key ?9)))
+						    (char-to-string key)
+						  (format "%03d" key)))))))
+      (and (fboundp cmd)
+	   (not (let ((f (symbol-function cmd)))
+		  (or (stringp f)
+		      (and (consp f)
+			   (eq (car-safe (nth 3 f))
+			       'calc-execute-kbd-macro)))))
+	   (error "Function %s is already defined and not a keyboard macro"
+		  cmd))
+      (put cmd 'calc-user-defn t)
+      (fset cmd (if (< (prefix-numeric-value arg) 0)
+		    last-kbd-macro
+		  (list 'lambda
+			'(arg)
+			'(interactive "P")
+			(list 'calc-execute-kbd-macro
+			      (vector (key-description last-kbd-macro)
+				      last-kbd-macro)
+			      'arg
+			      (format "z%c" key)))))
+      (let* ((kmap (calc-user-key-map))
+	     (old (assq key kmap)))
+	(if old
+	    (setcdr old cmd)
+	  (setcdr kmap (cons (cons key cmd) (cdr kmap)))))))
+)
+
+
+(defun calc-edit-user-syntax ()
+  (interactive)
+  (calc-wrapper
+   (let ((lang calc-language))
+     (calc-edit-mode (list 'calc-finish-user-syntax-edit (list 'quote lang))
+		     t
+		     (format "Editing %s-Mode Syntax Table"
+			     (cond ((null lang) "Normal")
+				   ((eq lang 'tex) "TeX")
+				   (t (capitalize (symbol-name lang))))))
+     (calc-write-parse-table (cdr (assq lang calc-user-parse-tables))
+			     lang)))
+  (calc-show-edit-buffer)
+)
+
+(defun calc-finish-user-syntax-edit (lang)
+  (let ((tab (calc-read-parse-table calc-original-buffer lang))
+	(entry (assq lang calc-user-parse-tables)))
+    (if tab
+	(setcdr (or entry
+		    (car (setq calc-user-parse-tables
+			       (cons (list lang) calc-user-parse-tables))))
+		tab)
+      (if entry
+	  (setq calc-user-parse-tables
+		(delq entry calc-user-parse-tables)))))
+  (switch-to-buffer calc-original-buffer)
+)
+
+(defun calc-write-parse-table (tab calc-lang)
+  (let ((p tab))
+    (while p
+      (calc-write-parse-table-part (car (car p)))
+      (insert ":= "
+	      (let ((math-format-hash-args t))
+		(math-format-flat-expr (cdr (car p)) 0))
+	      "\n")
+      (setq p (cdr p))))
+)
+
+(defun calc-write-parse-table-part (p)
+  (while p
+    (cond ((stringp (car p))
+	   (let ((s (car p)))
+	     (if (and (string-match "\\`\\\\dots\\>" s)
+		      (not (eq calc-lang 'tex)))
+		 (setq s (concat ".." (substring s 5))))
+	     (if (or (and (string-match
+			   "[a-zA-Z0-9\"{}]\\|\\`:=\\'\\|\\`#\\|\\`%%" s)
+			  (string-match "[^a-zA-Z0-9\\]" s))
+		     (and (assoc s '((")") ("]") (">")))
+			  (not (cdr p))))
+		 (insert (prin1-to-string s) " ")
+	       (insert s " "))))
+	  ((integerp (car p))
+	   (insert "#")
+	   (or (= (car p) 0)
+	       (insert "/" (int-to-string (car p))))
+	   (insert " "))
+	  ((and (eq (car (car p)) '\?) (equal (car (nth 2 (car p))) "$$"))
+	   (insert (car (nth 1 (car p))) " "))
+	  (t
+	   (insert "{ ")
+	   (calc-write-parse-table-part (nth 1 (car p)))
+	   (insert "}" (symbol-name (car (car p))))
+	   (if (nth 2 (car p))
+	       (calc-write-parse-table-part (list (car (nth 2 (car p)))))
+	     (insert " "))))
+    (setq p (cdr p)))
+)
+
+(defun calc-read-parse-table (calc-buf calc-lang)
+  (let ((tab nil))
+    (while (progn
+	     (skip-chars-forward "\n\t ")
+	     (not (eobp)))
+      (if (looking-at "%%")
+	  (end-of-line)
+	(let ((pt (point))
+	      (p (calc-read-parse-table-part ":=[\n\t ]+" ":=")))
+	  (or (stringp (car p))
+	      (and (integerp (car p))
+		   (stringp (nth 1 p)))
+	      (progn
+		(goto-char pt)
+		(error "Malformed syntax rule")))
+	  (let ((pos (point)))
+	    (end-of-line)
+	    (let* ((str (buffer-substring pos (point)))
+		   (exp (save-excursion
+			  (set-buffer calc-buf)
+			  (let ((calc-user-parse-tables nil)
+				(calc-language nil)
+				(math-expr-opers math-standard-opers)
+				(calc-hashes-used 0))
+			    (math-read-expr
+			     (if (string-match ",[ \t]*\\'" str)
+				 (substring str 0 (match-beginning 0))
+			       str))))))
+	      (if (eq (car-safe exp) 'error)
+		  (progn
+		    (goto-char (+ pos (nth 1 exp)))
+		    (error (nth 2 exp))))
+	      (setq tab (nconc tab (list (cons p exp)))))))))
+    tab)
+)
+
+(defun calc-fix-token-name (name &optional unquoted)
+  (cond ((string-match "\\`\\.\\." name)
+	 (concat "\\dots" (substring name 2)))
+	((and (equal name "{") (memq calc-lang '(tex eqn)))
+	 "(")
+	((and (equal name "}") (memq calc-lang '(tex eqn)))
+	 ")")
+	((and (equal name "&") (eq calc-lang 'tex))
+	 ",")
+	((equal name "#")
+	 (search-backward "#")
+	 (error "Token '#' is reserved"))
+	((and unquoted (string-match "#" name))
+	 (error "Tokens containing '#' must be quoted"))
+	((not (string-match "[^ ]" name))
+	 (search-backward "\"" nil t)
+	 (error "Blank tokens are not allowed"))
+	(t name))
+)
+
+(defun calc-read-parse-table-part (term eterm)
+  (let ((part nil)
+	(quoted nil))
+    (while (progn
+	     (skip-chars-forward "\n\t ")
+	     (if (eobp) (error "Expected '%s'" eterm))
+	     (not (looking-at term)))
+      (cond ((looking-at "%%")
+	     (end-of-line))
+	    ((looking-at "{[\n\t ]")
+	     (forward-char 2)
+	     (let ((p (calc-read-parse-table-part "}" "}")))
+	       (or (looking-at "[+*?]")
+		   (error "Expected '+', '*', or '?'"))
+	       (let ((sym (intern (buffer-substring (point) (1+ (point))))))
+		 (forward-char 1)
+		 (looking-at "[^\n\t ]*")
+		 (let ((sep (buffer-substring (point) (match-end 0))))
+		   (goto-char (match-end 0))
+		   (and (eq sym '\?) (> (length sep) 0)
+			(not (equal sep "$")) (not (equal sep "."))
+			(error "Separator not allowed with { ... }?"))
+		   (if (string-match "\\`\"" sep)
+		       (setq sep (read-from-string sep)))
+		   (setq sep (calc-fix-token-name sep))
+		   (setq part (nconc part
+				     (list (list sym p
+						 (and (> (length sep) 0)
+						      (cons sep p))))))))))
+	    ((looking-at "}")
+	     (error "Too many }'s"))
+	    ((looking-at "\"")
+	     (setq quoted (calc-fix-token-name (read (current-buffer)))
+		   part (nconc part (list quoted))))
+	    ((looking-at "#\\(\\(/[0-9]+\\)?\\)[\n\t ]")
+	     (setq part (nconc part (list (if (= (match-beginning 1)
+						 (match-end 1))
+					      0
+					    (string-to-int
+					     (buffer-substring
+					      (1+ (match-beginning 1))
+					      (match-end 1)))))))
+	     (goto-char (match-end 0)))
+	    ((looking-at ":=[\n\t ]")
+	     (error "Misplaced ':='"))
+	    (t
+	     (looking-at "[^\n\t ]*")
+	     (let ((end (match-end 0)))
+	       (setq part (nconc part (list (calc-fix-token-name
+					     (buffer-substring
+					      (point) end) t))))
+	       (goto-char end)))))
+    (goto-char (match-end 0))
+    (let ((len (length part)))
+      (while (and (> len 1)
+		  (let ((last (nthcdr (setq len (1- len)) part)))
+		    (and (assoc (car last) '((")") ("]") (">")))
+			 (not (eq (car last) quoted))
+			 (setcar last
+				 (list '\? (list (car last)) '("$$"))))))))
+    part)
+)
+
+
+(defun calc-user-define-invocation ()
+  (interactive)
+  (or last-kbd-macro
+      (error "No keyboard macro defined"))
+  (setq calc-invocation-macro last-kbd-macro)
+  (message "Use `M-# Z' to invoke this macro")
+)
+
+
+(defun calc-user-define-edit (prefix)
+  (interactive "P")  ; but no calc-wrapper!
+  (message "Edit definition of command: z-")
+  (let* ((key (read-char))
+	 (def (or (assq key (calc-user-key-map))
+		  (assq (upcase key) (calc-user-key-map))
+		  (assq (downcase key) (calc-user-key-map))
+		  (error "No command defined for that key")))
+	 (cmd (cdr def)))
+    (if (symbolp cmd)
+	(setq cmd (symbol-function cmd)))
+    (cond ((or (stringp cmd)
+	       (and (consp cmd)
+		    (eq (car-safe (nth 3 cmd)) 'calc-execute-kbd-macro)))
+	   (if (and (>= (prefix-numeric-value prefix) 0)
+		    (fboundp 'edit-kbd-macro)
+		    (symbolp (cdr def))
+		    (eq major-mode 'calc-mode))
+	       (progn
+		 (if (and (< (window-width) (screen-width))
+			  calc-display-trail)
+		     (let ((win (get-buffer-window (calc-trail-buffer))))
+		       (if win
+			   (delete-window win))))
+		 (edit-kbd-macro (cdr def) prefix nil
+				 (function
+				  (lambda (x)
+				    (and calc-display-trail
+					 (calc-wrapper
+					  (calc-trail-display 1 t)))))
+				 (function
+				  (lambda (cmd)
+				    (if (stringp (symbol-function cmd))
+					(symbol-function cmd)
+				      (let ((mac (nth 1 (nth 3 (symbol-function
+								cmd)))))
+					(if (vectorp mac)
+					    (aref mac 1)
+					  mac)))))
+				 (function
+				  (lambda (new cmd)
+				    (if (stringp (symbol-function cmd))
+					(fset cmd new)
+				      (let ((mac (cdr (nth 3 (symbol-function
+							      cmd)))))
+					(if (vectorp (car mac))
+					    (progn
+					      (aset (car mac) 0
+						    (key-description new))
+					      (aset (car mac) 1 new))
+					  (setcar mac new))))))))
+	     (let ((keys (progn (and (fboundp 'edit-kbd-macro)
+				     (edit-kbd-macro nil))
+				(fboundp 'MacEdit-parse-keys))))
+	       (calc-wrapper
+		(calc-edit-mode (list 'calc-finish-macro-edit
+				      (list 'quote def)
+				      keys)
+				t)
+		(if keys
+		    (let (top
+			  (fill-column 70)
+			  (fill-prefix nil))
+		      (insert "Notations: RET, SPC, TAB, DEL, LFD, NUL"
+			      ", C-xxx, M-xxx.\n\n")
+		      (setq top (point))
+		      (insert (if (stringp cmd)
+				  (key-description cmd)
+				(if (vectorp (nth 1 (nth 3 cmd)))
+				    (aref (nth 1 (nth 3 cmd)) 0)
+				  (key-description (nth 1 (nth 3 cmd)))))
+			      "\n")
+		      (if (>= (prog2 (forward-char -1)
+				     (current-column)
+				     (forward-char 1))
+			      (screen-width))
+			  (fill-region top (point))))
+		  (insert "Press C-q to quote control characters like RET"
+			  " and TAB.\n"
+			  (if (stringp cmd)
+			      cmd
+			    (if (vectorp (nth 1 (nth 3 cmd)))
+				(aref (nth 1 (nth 3 cmd)) 1)
+			      (nth 1 (nth 3 cmd)))))))
+	       (calc-show-edit-buffer)
+	       (forward-line (if keys 2 1)))))
+	  (t (let* ((func (calc-stack-command-p cmd))
+		    (defn (and func
+			       (symbolp func)
+			       (get func 'calc-user-defn))))
+	       (if (and defn (calc-valid-formula-func func))
+		   (progn
+		     (calc-wrapper
+		      (calc-edit-mode (list 'calc-finish-formula-edit
+					    (list 'quote func)))
+		      (insert (math-showing-full-precision
+			       (math-format-nice-expr defn (screen-width)))
+			      "\n"))
+		     (calc-show-edit-buffer))
+		 (error "That command's definition cannot be edited"))))))
+)
+
+(defun calc-finish-macro-edit (def keys)
+  (forward-line 1)
+  (if (and keys (looking-at "\n")) (forward-line 1))
+  (let* ((true-str (buffer-substring (point) (point-max)))
+	 (str true-str))
+    (if keys (setq str (MacEdit-parse-keys str)))
+    (if (symbolp (cdr def))
+	(if (stringp (symbol-function (cdr def)))
+	    (fset (cdr def) str)
+	  (let ((mac (cdr (nth 3 (symbol-function (cdr def))))))
+	    (if (vectorp (car mac))
+		(progn
+		  (aset (car mac) 0 (if keys true-str (key-description str)))
+		  (aset (car mac) 1 str))
+	      (setcar mac str))))
+      (setcdr def str)))
+)
+
+;;; The following are hooks into the MacEdit package from macedit.el.
+(put 'calc-execute-extended-command 'MacEdit-print
+     (function (lambda ()
+		 (setq macro-str (concat "\excalc-" macro-str))))
+)
+
+(put 'calcDigit-start 'MacEdit-print
+     (function (lambda ()
+		 (if calc-algebraic-mode
+		     (calc-macro-edit-algebraic)
+		   (MacEdit-unread-chars key-last)
+		   (let ((str "")
+			 (min-bsp 0)
+			 ch last)
+		     (while (and (setq ch (MacEdit-read-char))
+				 (or (and (>= ch ?0) (<= ch ?9))
+				     (memq ch '(?\. ?e ?\_ ?n ?\: ?\# ?M
+						    ?o ?h ?\@ ?\"))
+				     (and (memq ch '(?\' ?m ?s))
+					  (string-match "[@oh]" str))
+				     (and (or (and (>= ch ?a) (<= ch ?z))
+					      (and (>= ch ?A) (<= ch ?Z)))
+					  (string-match
+					   "^[-+]?\\(1[1-9]\\|[2-9][0-9]\\)#"
+					   str))
+				     (and (memq ch '(?\177 ?\C-h))
+					  (> (length str) 0))
+				     (and (memq ch '(?+ ?-))
+					  (> (length str) 0)
+					  (eq (aref str (1- (length str)))
+					      ?e))))
+		       (if (or (and (>= ch ?0) (<= ch ?9))
+			       (and (or (not (memq ch '(?\177 ?\C-h)))
+					(<= (length str) min-bsp))
+				    (setq min-bsp (1+ (length str)))))
+			   (setq str (concat str (char-to-string ch)))
+			 (setq str (substring str 0 -1))))
+		     (if (memq ch '(32 10 13))
+			 (setq str (concat str (char-to-string ch)))
+		       (MacEdit-unread-chars ch))
+		     (insert "type \"")
+		     (MacEdit-insert-string str)
+		     (insert "\"\n")))))
+)
+
+(defun calc-macro-edit-algebraic ()
+  (MacEdit-unread-chars key-last)
+  (let ((str "")
+	(min-bsp 0))
+    (while (progn
+	     (MacEdit-lookup-key calc-alg-ent-map)
+	     (or (and (memq key-symbol '(self-insert-command
+					 calcAlg-previous))
+		      (< (length str) 60))
+		 (memq key-symbol
+			    '(backward-delete-char
+			      delete-backward-char
+			      backward-delete-char-untabify))
+		 (eq key-last 9)))
+      (setq macro-str (substring macro-str (length key-str)))
+      (if (or (eq key-symbol 'self-insert-command)
+	      (and (or (not (memq key-symbol '(backward-delete-char
+					       delete-backward-char
+					       backward-delete-char-untabify)))
+		       (<= (length str) min-bsp))
+		   (setq min-bsp (+ (length str) (length key-str)))))
+	  (setq str (concat str key-str))
+	(setq str (substring str 0 -1))))
+    (if (memq key-last '(10 13))
+	(setq str (concat str key-str)
+	      macro-str (substring macro-str (length key-str))))
+    (if (> (length str) 0)
+	(progn
+	  (insert "type \"")
+	  (MacEdit-insert-string str)
+	  (insert "\"\n"))))
+)
+(put 'calc-algebraic-entry 'MacEdit-print 'calc-macro-edit-algebraic)
+(put 'calc-auto-algebraic-entry 'MacEdit-print 'calc-macro-edit-algebraic)
+
+(defun calc-macro-edit-variable (&optional no-cmd)
+  (let ((str "") ch)
+    (or no-cmd (insert (symbol-name key-symbol) "\n"))
+    (if (memq (MacEdit-peek-char) '(?\+ ?\- ?\* ?\/ ?\^ ?\|))
+	(setq str (char-to-string (MacEdit-read-char))))
+    (if (and (setq ch (MacEdit-peek-char))
+	     (>= ch ?0) (<= ch ?9))
+	(insert "type \"" str
+		(char-to-string (MacEdit-read-char)) "\"\n")
+      (if (> (length str) 0)
+	  (insert "type \"" str "\"\n"))
+      (MacEdit-read-argument)))
+)
+(put 'calc-store 'MacEdit-print 'calc-macro-edit-variable)
+(put 'calc-store-into 'MacEdit-print 'calc-macro-edit-variable)
+(put 'calc-store-neg 'MacEdit-print 'calc-macro-edit-variable)
+(put 'calc-store-plus 'MacEdit-print 'calc-macro-edit-variable)
+(put 'calc-store-minus 'MacEdit-print 'calc-macro-edit-variable)
+(put 'calc-store-times 'MacEdit-print 'calc-macro-edit-variable)
+(put 'calc-store-div 'MacEdit-print 'calc-macro-edit-variable)
+(put 'calc-store-power 'MacEdit-print 'calc-macro-edit-variable)
+(put 'calc-store-concat 'MacEdit-print 'calc-macro-edit-variable)
+(put 'calc-store-inv 'MacEdit-print 'calc-macro-edit-variable)
+(put 'calc-store-decr 'MacEdit-print 'calc-macro-edit-variable)
+(put 'calc-store-incr 'MacEdit-print 'calc-macro-edit-variable)
+(put 'calc-store-exchange 'MacEdit-print 'calc-macro-edit-variable)
+(put 'calc-unstore 'MacEdit-print 'calc-macro-edit-variable)
+(put 'calc-recall 'MacEdit-print 'calc-macro-edit-variable)
+(put 'calc-let 'MacEdit-print 'calc-macro-edit-variable)
+(put 'calc-permanent-variable 'MacEdit-print 'calc-macro-edit-variable)
+
+(defun calc-macro-edit-variable-2 ()
+  (calc-macro-edit-variable)
+  (calc-macro-edit-variable t)
+)
+(put 'calc-copy-variable 'MacEdit-print 'calc-macro-edit-variable-2)
+(put 'calc-declare-variable 'MacEdit-print 'calc-macro-edit-variable-2)
+
+(defun calc-macro-edit-quick-digit ()
+  (insert "type \"" key-str "\"  # " (symbol-name key-symbol) "\n")
+)
+(put 'calc-store-quick 'MacEdit-print 'calc-macro-edit-quick-digit)
+(put 'calc-store-into-quick 'MacEdit-print 'calc-macro-edit-quick-digit)
+(put 'calc-recall-quick 'MacEdit-print 'calc-macro-edit-quick-digit)
+(put 'calc-select-part 'MacEdit-print 'calc-macro-edit-quick-digit)
+(put 'calc-clean-num 'MacEdit-print 'calc-macro-edit-quick-digit)
+
+
+(defun calc-finish-formula-edit (func)
+  (let ((buf (current-buffer))
+	(str (buffer-substring (point) (point-max)))
+	(start (point))
+	(body (calc-valid-formula-func func)))
+    (set-buffer calc-original-buffer)
+    (let ((val (math-read-expr str)))
+      (if (eq (car-safe val) 'error)
+	  (progn
+	    (set-buffer buf)
+	    (goto-char (+ start (nth 1 val)))
+	    (error (nth 2 val))))
+      (setcar (cdr body)
+	      (let ((alist (nth 1 (symbol-function func))))
+		(calc-fix-user-formula val)))
+      (put func 'calc-user-defn val)))
+)
+
+(defun calc-valid-formula-func (func)
+  (let ((def (symbol-function func)))
+    (and (consp def)
+	 (eq (car def) 'lambda)
+	 (progn
+	   (setq def (cdr (cdr def)))
+	   (while (and def
+		       (not (eq (car (car def)) 'math-normalize)))
+	     (setq def (cdr def)))
+	   (car def))))
+)
+
+
+(defun calc-get-user-defn ()
+  (interactive)
+  (calc-wrapper
+   (message "Get definition of command: z-")
+   (let* ((key (read-char))
+	  (def (or (assq key (calc-user-key-map))
+		   (assq (upcase key) (calc-user-key-map))
+		   (assq (downcase key) (calc-user-key-map))
+		   (error "No command defined for that key")))
+	  (cmd (cdr def)))
+     (if (symbolp cmd)
+	 (setq cmd (symbol-function cmd)))
+     (cond ((stringp cmd)
+	    (message "Keyboard macro: %s" cmd))
+	   (t (let* ((func (calc-stack-command-p cmd))
+		     (defn (and func
+				(symbolp func)
+				(get func 'calc-user-defn))))
+		(if defn
+		    (progn
+		      (and (calc-valid-formula-func func)
+			   (setq defn (append '(calcFunc-lambda)
+					      (mapcar 'math-build-var-name
+						      (nth 1 (symbol-function
+							      func)))
+					      (list defn))))
+		      (calc-enter-result 0 "gdef" defn))
+		  (error "That command is not defined by a formula")))))))
+)
+
+
+(defun calc-user-define-permanent ()
+  (interactive)
+  (calc-wrapper
+   (message "Record in %s the command: z-" calc-settings-file)
+   (let* ((key (read-char))
+	  (def (or (assq key (calc-user-key-map))
+		   (assq (upcase key) (calc-user-key-map))
+		   (assq (downcase key) (calc-user-key-map))
+		   (and (eq key ?\') 
+			(cons nil
+			      (intern (completing-read
+				       (format "Record in %s the function: "
+					       calc-settings-file)
+				       obarray 'fboundp nil "calcFunc-"))))
+		   (error "No command defined for that key"))))
+     (set-buffer (find-file-noselect (substitute-in-file-name
+				      calc-settings-file)))
+     (goto-char (point-max))
+     (let* ((cmd (cdr def))
+	    (fcmd (and cmd (symbolp cmd) (symbol-function cmd)))
+	    (func nil)
+	    (pt (point))
+	    (fill-column 70)
+	    (fill-prefix nil)
+	    str q-ok)
+       (insert "\n;;; Definition stored by Calc on " (current-time-string)
+	       "\n(put 'calc-define '"
+	       (if (symbolp cmd) (symbol-name cmd) (format "key%d" key))
+	       " '(progn\n")
+       (if (and fcmd
+		(eq (car-safe fcmd) 'lambda)
+		(get cmd 'calc-user-defn))
+	   (let ((pt (point)))
+	     (and (eq (car-safe (nth 3 fcmd)) 'calc-execute-kbd-macro)
+		  (vectorp (nth 1 (nth 3 fcmd)))
+		  (progn (and (fboundp 'edit-kbd-macro)
+			      (edit-kbd-macro nil))
+			 (fboundp 'MacEdit-parse-keys))
+		  (setq q-ok t)
+		  (aset (nth 1 (nth 3 fcmd)) 1 nil))
+	     (insert (setq str (prin1-to-string
+				(cons 'defun (cons cmd (cdr fcmd)))))
+		     "\n")
+	     (or (and (string-match "\"" str) (not q-ok))
+		 (fill-region pt (point)))
+	     (indent-rigidly pt (point) 2)
+	     (delete-region pt (1+ pt))
+	     (insert " (put '" (symbol-name cmd)
+		     " 'calc-user-defn '"
+		     (prin1-to-string (get cmd 'calc-user-defn))
+		     ")\n")
+	     (setq func (calc-stack-command-p cmd))
+	     (let ((ffunc (and func (symbolp func) (symbol-function func)))
+		   (pt (point)))
+	       (and ffunc
+		    (eq (car-safe ffunc) 'lambda)
+		    (get func 'calc-user-defn)
+		    (progn
+		      (insert (setq str (prin1-to-string
+					 (cons 'defun (cons func
+							    (cdr ffunc)))))
+			      "\n")
+		      (or (and (string-match "\"" str) (not q-ok))
+			  (fill-region pt (point)))
+		      (indent-rigidly pt (point) 2)
+		      (delete-region pt (1+ pt))
+		      (setq pt (point))
+		      (insert "(put '" (symbol-name func)
+			      " 'calc-user-defn '"
+			      (prin1-to-string (get func 'calc-user-defn))
+			      ")\n")
+		      (fill-region pt (point))
+		      (indent-rigidly pt (point) 2)
+		      (delete-region pt (1+ pt))))))
+	 (and (stringp fcmd)
+	      (insert " (fset '" (prin1-to-string cmd)
+		      " " (prin1-to-string fcmd) ")\n")))
+       (or func (setq func (and cmd (symbolp cmd) (fboundp cmd) cmd)))
+       (if (get func 'math-compose-forms)
+	   (let ((pt (point)))
+	     (insert "(put '" (symbol-name cmd)
+		     " 'math-compose-forms '"
+		     (prin1-to-string (get func 'math-compose-forms))
+		     ")\n")
+	     (fill-region pt (point))
+	     (indent-rigidly pt (point) 2)
+	     (delete-region pt (1+ pt))))
+       (if (car def)
+	   (insert " (define-key calc-mode-map "
+		   (prin1-to-string (concat "z" (char-to-string key)))
+		   " '"
+		   (prin1-to-string cmd)
+		   ")\n")))
+     (insert "))\n")
+     (save-buffer)))
+)
+
+(defun calc-stack-command-p (cmd)
+  (if (and cmd (symbolp cmd))
+      (and (fboundp cmd)
+	   (calc-stack-command-p (symbol-function cmd)))
+    (and (consp cmd)
+	 (eq (car cmd) 'lambda)
+	 (setq cmd (or (assq 'calc-wrapper cmd)
+		       (assq 'calc-slow-wrapper cmd)))
+	 (setq cmd (assq 'calc-enter-result cmd))
+	 (memq (car (nth 3 cmd)) '(cons list))
+	 (eq (car (nth 1 (nth 3 cmd))) 'quote)
+	 (nth 1 (nth 1 (nth 3 cmd)))))
+)
+
+
+(defun calc-call-last-kbd-macro (arg)
+  (interactive "P")
+  (and defining-kbd-macro
+       (error "Can't execute anonymous macro while defining one"))
+  (or last-kbd-macro
+      (error "No kbd macro has been defined"))
+  (calc-execute-kbd-macro last-kbd-macro arg)
+)
+
+(defun calc-execute-kbd-macro (mac arg &rest prefix)
+  (if (and (vectorp mac) (> (length mac) 0) (stringp (aref mac 0)))
+      (setq mac (or (aref mac 1)
+		    (aset mac 1 (progn (and (fboundp 'edit-kbd-macro)
+					    (edit-kbd-macro nil))
+				       (MacEdit-parse-keys (aref mac 0)))))))
+  (if (< (prefix-numeric-value arg) 0)
+      (execute-kbd-macro mac (- (prefix-numeric-value arg)))
+    (if calc-executing-macro
+	(execute-kbd-macro mac arg)
+      (calc-slow-wrapper
+       (let ((old-stack-whole (copy-sequence calc-stack))
+	     (old-stack-top calc-stack-top)
+	     (old-buffer-size (buffer-size))
+	     (old-refresh-count calc-refresh-count))
+	 (unwind-protect
+	     (let ((calc-executing-macro mac))
+	       (execute-kbd-macro mac arg))
+	   (calc-select-buffer)
+	   (let ((new-stack (reverse calc-stack))
+		 (old-stack (reverse old-stack-whole)))
+	     (while (and new-stack old-stack
+			 (equal (car new-stack) (car old-stack)))
+	       (setq new-stack (cdr new-stack)
+		     old-stack (cdr old-stack)))
+	     (or (equal prefix '(nil))
+		 (calc-record-list (if (> (length new-stack) 1)
+				       (mapcar 'car new-stack)
+				     '(""))
+				   (or (car prefix) "kmac")))
+	     (calc-record-undo (list 'set 'saved-stack-top old-stack-top))
+	     (and old-stack
+		  (calc-record-undo (list 'pop 1 (mapcar 'car old-stack))))
+	     (let ((calc-stack old-stack-whole)
+		   (calc-stack-top 0))
+	       (calc-cursor-stack-index (length old-stack)))
+	     (if (and (= old-buffer-size (buffer-size))
+		      (= old-refresh-count calc-refresh-count))
+		 (let ((buffer-read-only nil))
+		   (delete-region (point) (point-max))
+		   (while new-stack
+		     (calc-record-undo (list 'push 1))
+		     (insert (math-format-stack-value (car new-stack)) "\n")
+		     (setq new-stack (cdr new-stack)))
+		   (calc-renumber-stack))
+	       (while new-stack
+		 (calc-record-undo (list 'push 1))
+		 (setq new-stack (cdr new-stack)))
+	       (calc-refresh))
+	     (calc-record-undo (list 'set 'saved-stack-top 0))))))))
+)
+
+(defun calc-push-list-in-macro (vals m sels)
+  (let ((entry (list (car vals) 1 (car sels)))
+	(mm (+ (or m 1) calc-stack-top)))
+    (if (> mm 1)
+	(setcdr (nthcdr (- mm 2) calc-stack)
+		(cons entry (nthcdr (1- mm) calc-stack)))
+      (setq calc-stack (cons entry calc-stack))))
+)
+
+(defun calc-pop-stack-in-macro (n mm)
+  (if (> mm 1)
+      (setcdr (nthcdr (- mm 2) calc-stack)
+	      (nthcdr (+ n mm -1) calc-stack))
+    (setq calc-stack (nthcdr n calc-stack)))
+)
+
+
+(defun calc-kbd-if ()
+  (interactive)
+  (calc-wrapper
+   (let ((cond (calc-top-n 1)))
+     (calc-pop-stack 1)
+     (if (math-is-true cond)
+	 (if defining-kbd-macro
+	     (message "If true..."))
+       (if defining-kbd-macro
+	   (message "Condition is false; skipping to Z: or Z] ..."))
+       (calc-kbd-skip-to-else-if t))))
+)
+
+(defun calc-kbd-else-if ()
+  (interactive)
+  (calc-kbd-if)
+)
+
+(defun calc-kbd-skip-to-else-if (else-okay)
+  (let ((count 0)
+	ch)
+    (while (>= count 0)
+      (setq ch (read-char))
+      (if (= ch -1)
+	  (error "Unterminated Z[ in keyboard macro"))
+      (if (= ch ?Z)
+	  (progn
+	    (setq ch (read-char))
+	    (cond ((= ch ?\[)
+		   (setq count (1+ count)))
+		  ((= ch ?\])
+		   (setq count (1- count)))
+		  ((= ch ?\:)
+		   (and (= count 0)
+			else-okay
+			(setq count -1)))
+		  ((eq ch 7)
+		   (keyboard-quit))))))
+    (and defining-kbd-macro
+	 (if (= ch ?\:)
+	     (message "Else...")
+	   (message "End-if..."))))
+)
+
+(defun calc-kbd-end-if ()
+  (interactive)
+  (if defining-kbd-macro
+      (message "End-if..."))
+)
+
+(defun calc-kbd-else ()
+  (interactive)
+  (if defining-kbd-macro
+      (message "Else; skipping to Z] ..."))
+  (calc-kbd-skip-to-else-if nil)
+)
+
+
+(defun calc-kbd-repeat ()
+  (interactive)
+  (let (count)
+    (calc-wrapper
+     (setq count (math-trunc (calc-top-n 1)))
+     (or (Math-integerp count)
+	 (error "Count must be an integer"))
+     (if (Math-integer-negp count)
+	 (setq count 0))
+     (or (integerp count)
+	 (setq count 1000000))
+     (calc-pop-stack 1))
+    (calc-kbd-loop count))
+)
+
+(defun calc-kbd-for (dir)
+  (interactive "P")
+  (let (init final)
+    (calc-wrapper
+     (setq init (calc-top-n 2)
+	   final (calc-top-n 1))
+     (or (and (math-anglep init) (math-anglep final))
+	 (error "Initial and final values must be real numbers"))
+     (calc-pop-stack 2))
+    (calc-kbd-loop nil init final (and dir (prefix-numeric-value dir))))
+)
+
+(defun calc-kbd-loop (rpt-count &optional initial final dir)
+  (interactive "P")
+  (setq rpt-count (if rpt-count (prefix-numeric-value rpt-count) 1000000))
+  (let* ((count 0)
+	 (parts nil)
+	 (body "")
+	 (open last-command-char)
+	 (counter initial)
+	 ch)
+    (or executing-macro
+	(message "Reading loop body..."))
+    (while (>= count 0)
+      (setq ch (read-char))
+      (if (= ch -1)
+	  (error "Unterminated Z%c in keyboard macro" open))
+      (if (= ch ?Z)
+	  (progn
+	    (setq ch (read-char)
+		  body (concat body "Z" (char-to-string ch)))
+	    (cond ((memq ch '(?\< ?\( ?\{))
+		   (setq count (1+ count)))
+		  ((memq ch '(?\> ?\) ?\}))
+		   (setq count (1- count)))
+		  ((and (= ch ?/)
+			(= count 0))
+		   (setq parts (nconc parts (list (concat (substring body 0 -2)
+							  "Z]")))
+			 body ""))
+		  ((eq ch 7)
+		   (keyboard-quit))))
+	(setq body (concat body (char-to-string ch)))))
+    (if (/= ch (cdr (assq open '( (?\< . ?\>) (?\( . ?\)) (?\{ . ?\}) ))))
+	(error "Mismatched Z%c and Z%c in keyboard macro" open ch))
+    (or executing-macro
+	(message "Looping..."))
+    (setq body (concat (substring body 0 -2) "Z]"))
+    (and (not executing-macro)
+	 (= rpt-count 1000000)
+	 (null parts)
+	 (null counter)
+	 (progn
+	   (message "Warning: Infinite loop!  Not executing.")
+	   (setq rpt-count 0)))
+    (or (not initial) dir
+	(setq dir (math-compare final initial)))
+    (calc-wrapper
+     (while (> rpt-count 0)
+       (let ((part parts))
+	 (if counter
+	     (if (cond ((eq dir 0) (Math-equal final counter))
+		       ((eq dir 1) (Math-lessp final counter))
+		       ((eq dir -1) (Math-lessp counter final)))
+		 (setq rpt-count 0)
+	       (calc-push counter)))
+	 (while (and part (> rpt-count 0))
+	   (execute-kbd-macro (car part))
+	   (if (math-is-true (calc-top-n 1))
+	       (setq rpt-count 0)
+	     (setq part (cdr part)))
+	   (calc-pop-stack 1))
+	 (if (> rpt-count 0)
+	     (progn
+	       (execute-kbd-macro body)
+	       (if counter
+		   (let ((step (calc-top-n 1)))
+		     (calc-pop-stack 1)
+		     (setq counter (calcFunc-add counter step)))
+		 (setq rpt-count (1- rpt-count))))))))
+    (or executing-macro
+	(message "Looping...done")))
+)
+
+(defun calc-kbd-end-repeat ()
+  (interactive)
+  (error "Unbalanced Z> in keyboard macro")
+)
+
+(defun calc-kbd-end-for ()
+  (interactive)
+  (error "Unbalanced Z) in keyboard macro")
+)
+
+(defun calc-kbd-end-loop ()
+  (interactive)
+  (error "Unbalanced Z} in keyboard macro")
+)
+
+(defun calc-kbd-break ()
+  (interactive)
+  (calc-wrapper
+   (let ((cond (calc-top-n 1)))
+     (calc-pop-stack 1)
+     (if (math-is-true cond)
+	 (error "Keyboard macro aborted."))))
+)
+
+
+(defun calc-kbd-push (arg)
+  (interactive "P")
+  (calc-wrapper
+   (let* ((defs (and arg (> (prefix-numeric-value arg) 0)))
+	  (var-q0 (and (boundp 'var-q0) var-q0))
+	  (var-q1 (and (boundp 'var-q1) var-q1))
+	  (var-q2 (and (boundp 'var-q2) var-q2))
+	  (var-q3 (and (boundp 'var-q3) var-q3))
+	  (var-q4 (and (boundp 'var-q4) var-q4))
+	  (var-q5 (and (boundp 'var-q5) var-q5))
+	  (var-q6 (and (boundp 'var-q6) var-q6))
+	  (var-q7 (and (boundp 'var-q7) var-q7))
+	  (var-q8 (and (boundp 'var-q8) var-q8))
+	  (var-q9 (and (boundp 'var-q9) var-q9))
+	  (calc-internal-prec (if defs 12 calc-internal-prec))
+	  (calc-word-size (if defs 32 calc-word-size))
+	  (calc-angle-mode (if defs 'deg calc-angle-mode))
+	  (calc-simplify-mode (if defs nil calc-simplify-mode))
+	  (calc-algebraic-mode (if arg nil calc-algebraic-mode))
+	  (calc-incomplete-algebraic-mode (if arg nil
+					    calc-incomplete-algebraic-mode))
+	  (calc-symbolic-mode (if defs nil calc-symbolic-mode))
+	  (calc-matrix-mode (if defs nil calc-matrix-mode))
+	  (calc-prefer-frac (if defs nil calc-prefer-frac))
+	  (calc-complex-mode (if defs nil calc-complex-mode))
+	  (calc-infinite-mode (if defs nil calc-infinite-mode))
+	  (count 0)
+	  (body "")
+	  ch)
+     (if (or executing-macro defining-kbd-macro)
+	 (progn
+	   (if defining-kbd-macro
+	       (message "Reading body..."))
+	   (while (>= count 0)
+	     (setq ch (read-char))
+	     (if (= ch -1)
+		 (error "Unterminated Z` in keyboard macro"))
+	     (if (= ch ?Z)
+		 (progn
+		   (setq ch (read-char)
+			 body (concat body "Z" (char-to-string ch)))
+		   (cond ((eq ch ?\`)
+			  (setq count (1+ count)))
+			 ((eq ch ?\')
+			  (setq count (1- count)))
+			 ((eq ch 7)
+			  (keyboard-quit))))
+	       (setq body (concat body (char-to-string ch)))))
+	   (if defining-kbd-macro
+	       (message "Reading body...done"))
+	   (let ((calc-kbd-push-level 0))
+	     (execute-kbd-macro (substring body 0 -2))))
+       (let ((calc-kbd-push-level (1+ calc-kbd-push-level)))
+	 (message "Saving modes; type Z' to restore")
+	 (recursive-edit)))))
+)
+(setq calc-kbd-push-level 0)
+
+(defun calc-kbd-pop ()
+  (interactive)
+  (if (> calc-kbd-push-level 0)
+      (progn
+	(message "Mode settings restored")
+	(exit-recursive-edit))
+    (error "Unbalanced Z' in keyboard macro"))
+)
+
+
+(defun calc-kbd-report (msg)
+  (interactive "sMessage: ")
+  (calc-wrapper
+   (let ((executing-macro nil)
+	 (defining-kbd-macro nil))
+     (math-working msg (calc-top-n 1))))
+)
+
+(defun calc-kbd-query (msg)
+  (interactive "sPrompt: ")
+  (calc-wrapper
+   (let ((executing-macro nil)
+	 (defining-kbd-macro nil))
+     (calc-alg-entry nil (and (not (equal msg "")) msg))))
+)
+
+
+
+
+
+
+
+;;;; Logical operations.
+
+(defun calcFunc-eq (a b &rest more)
+  (if more
+      (let* ((args (cons a (cons b (copy-sequence more))))
+	     (res 1)
+	     (p args)
+	     p2)
+	(while (and (cdr p) (not (eq res 0)))
+	  (setq p2 p)
+	  (while (and (setq p2 (cdr p2)) (not (eq res 0)))
+	    (setq res (math-two-eq (car p) (car p2)))
+	    (if (eq res 1)
+		(setcdr p (delq (car p2) (cdr p)))))
+	  (setq p (cdr p)))
+	(if (eq res 0)
+	    0
+	  (if (cdr args)
+	      (cons 'calcFunc-eq args)
+	    1)))
+    (or (math-two-eq a b)
+	(if (and (or (math-looks-negp a) (math-zerop a))
+		 (or (math-looks-negp b) (math-zerop b)))
+	    (list 'calcFunc-eq (math-neg a) (math-neg b))
+	  (list 'calcFunc-eq a b))))
+)
+
+(defun calcFunc-neq (a b &rest more)
+  (if more
+      (let* ((args (cons a (cons b more)))
+	     (res 0)
+	     (all t)
+	     (p args)
+	     p2)
+	(while (and (cdr p) (not (eq res 1)))
+	  (setq p2 p)
+	  (while (and (setq p2 (cdr p2)) (not (eq res 1)))
+	    (setq res (math-two-eq (car p) (car p2)))
+	    (or res (setq all nil)))
+	  (setq p (cdr p)))
+	(if (eq res 1)
+	    0
+	  (if all
+	      1
+	    (cons 'calcFunc-neq args))))
+    (or (cdr (assq (math-two-eq a b) '((0 . 1) (1 . 0))))
+	(if (and (or (math-looks-negp a) (math-zerop a))
+		 (or (math-looks-negp b) (math-zerop b)))
+	    (list 'calcFunc-neq (math-neg a) (math-neg b))
+	  (list 'calcFunc-neq a b))))
+)
+
+(defun math-two-eq (a b)
+  (if (eq (car-safe a) 'vec)
+      (if (eq (car-safe b) 'vec)
+	  (if (= (length a) (length b))
+	      (let ((res 1))
+		(while (and (setq a (cdr a) b (cdr b)) (not (eq res 0)))
+		  (if res
+		      (setq res (math-two-eq (car a) (car b)))
+		    (if (eq (math-two-eq (car a) (car b)) 0)
+			(setq res 0))))
+		res)
+	    0)
+	(if (Math-objectp b)
+	    0
+	  nil))
+    (if (eq (car-safe b) 'vec)
+	(if (Math-objectp a)
+	    0
+	  nil)
+      (let ((res (math-compare a b)))
+	(if (= res 0)
+	    1
+	  (if (and (= res 2) (not (and (Math-scalarp a) (Math-scalarp b))))
+	      nil
+	    0)))))
+)
+
+(defun calcFunc-lt (a b)
+  (let ((res (math-compare a b)))
+    (if (= res -1)
+	1
+      (if (= res 2)
+	  (if (and (or (math-looks-negp a) (math-zerop a))
+		   (or (math-looks-negp b) (math-zerop b)))
+	      (list 'calcFunc-gt (math-neg a) (math-neg b))
+	    (list 'calcFunc-lt a b))
+	0)))
+)
+
+(defun calcFunc-gt (a b)
+  (let ((res (math-compare a b)))
+    (if (= res 1)
+	1
+      (if (= res 2)
+	  (if (and (or (math-looks-negp a) (math-zerop a))
+		   (or (math-looks-negp b) (math-zerop b)))
+	      (list 'calcFunc-lt (math-neg a) (math-neg b))
+	    (list 'calcFunc-gt a b))
+	0)))
+)
+
+(defun calcFunc-leq (a b)
+  (let ((res (math-compare a b)))
+    (if (= res 1)
+	0
+      (if (= res 2)
+	  (if (and (or (math-looks-negp a) (math-zerop a))
+		   (or (math-looks-negp b) (math-zerop b)))
+	      (list 'calcFunc-geq (math-neg a) (math-neg b))
+	    (list 'calcFunc-leq a b))
+	1)))
+)
+
+(defun calcFunc-geq (a b)
+  (let ((res (math-compare a b)))
+    (if (= res -1)
+	0
+      (if (= res 2)
+	  (if (and (or (math-looks-negp a) (math-zerop a))
+		   (or (math-looks-negp b) (math-zerop b)))
+	      (list 'calcFunc-leq (math-neg a) (math-neg b))
+	    (list 'calcFunc-geq a b))
+	1)))
+)
+
+(defun calcFunc-rmeq (a)
+  (if (math-vectorp a)
+      (math-map-vec 'calcFunc-rmeq a)
+    (if (assq (car-safe a) calc-tweak-eqn-table)
+	(if (and (eq (car-safe (nth 2 a)) 'var)
+		 (math-objectp (nth 1 a)))
+	    (nth 1 a)
+	  (nth 2 a))
+      (if (eq (car-safe a) 'calcFunc-assign)
+	  (nth 2 a)
+	(if (eq (car-safe a) 'calcFunc-evalto)
+	    (nth 1 a)
+	  (list 'calcFunc-rmeq a)))))
+)
+
+(defun calcFunc-land (a b)
+  (cond ((Math-zerop a)
+	 a)
+	((Math-zerop b)
+	 b)
+	((math-is-true a)
+	 b)
+	((math-is-true b)
+	 a)
+	(t (list 'calcFunc-land a b)))
+)
+
+(defun calcFunc-lor (a b)
+  (cond ((Math-zerop a)
+	 b)
+	((Math-zerop b)
+	 a)
+	((math-is-true a)
+	 a)
+	((math-is-true b)
+	 b)
+	(t (list 'calcFunc-lor a b)))
+)
+
+(defun calcFunc-lnot (a)
+  (if (Math-zerop a)
+      1
+    (if (math-is-true a)
+	0
+      (let ((op (and (= (length a) 3)
+		     (assq (car a) calc-tweak-eqn-table))))
+	(if op
+	    (cons (nth 2 op) (cdr a))
+	  (list 'calcFunc-lnot a)))))
+)
+
+(defun calcFunc-if (c e1 e2)
+  (if (Math-zerop c)
+      e2
+    (if (and (math-is-true c) (not (Math-vectorp c)))
+	e1
+      (or (and (Math-vectorp c)
+	       (math-constp c)
+	       (let ((ee1 (if (Math-vectorp e1)
+			      (if (= (length c) (length e1))
+				  (cdr e1)
+				(calc-record-why "*Dimension error" e1))
+			    (list e1)))
+		     (ee2 (if (Math-vectorp e2)
+			      (if (= (length c) (length e2))
+				  (cdr e2)
+				(calc-record-why "*Dimension error" e2))
+			    (list e2))))
+		 (and ee1 ee2
+		      (cons 'vec (math-if-vector (cdr c) ee1 ee2)))))
+	  (list 'calcFunc-if c e1 e2))))
+)
+
+(defun math-if-vector (c e1 e2)
+  (and c
+       (cons (if (Math-zerop (car c)) (car e2) (car e1))
+	     (math-if-vector (cdr c)
+			     (or (cdr e1) e1)
+			     (or (cdr e2) e2))))
+)
+
+(defun math-normalize-logical-op (a)
+  (or (and (eq (car a) 'calcFunc-if)
+	   (= (length a) 4)
+	   (let ((a1 (math-normalize (nth 1 a))))
+	     (if (Math-zerop a1)
+		 (math-normalize (nth 3 a))
+	       (if (Math-numberp a1)
+		   (math-normalize (nth 2 a))
+		 (if (and (Math-vectorp (nth 1 a))
+			  (math-constp (nth 1 a)))
+		     (calcFunc-if (nth 1 a)
+				  (math-normalize (nth 2 a))
+				  (math-normalize (nth 3 a)))
+		   (let ((calc-simplify-mode 'none))
+		     (list 'calcFunc-if a1
+			   (math-normalize (nth 2 a))
+			   (math-normalize (nth 3 a)))))))))
+      a)
+)
+
+(defun calcFunc-in (a b)
+  (or (and (eq (car-safe b) 'vec)
+	   (let ((bb b))
+	     (while (and (setq bb (cdr bb))
+			 (not (if (memq (car-safe (car bb)) '(vec intv))
+				  (eq (calcFunc-in a (car bb)) 1)
+				(Math-equal a (car bb))))))
+	     (if bb 1 (and (math-constp a) (math-constp bb) 0))))
+      (and (eq (car-safe b) 'intv)
+	   (let ((res (math-compare a (nth 2 b))) res2)
+	     (cond ((= res -1)
+		    0)
+		   ((and (= res 0)
+			 (or (/= (nth 1 b) 2)
+			     (Math-lessp (nth 2 b) (nth 3 b))))
+		    (if (memq (nth 1 b) '(2 3)) 1 0))
+		   ((= (setq res2 (math-compare a (nth 3 b))) 1)
+		    0)
+		   ((and (= res2 0)
+			 (or (/= (nth 1 b) 1)
+			     (Math-lessp (nth 2 b) (nth 3 b))))
+		    (if (memq (nth 1 b) '(1 3)) 1 0))
+		   ((/= res 1)
+		    nil)
+		   ((/= res2 -1)
+		    nil)
+		   (t 1))))
+      (and (Math-equal a b)
+	   1)
+      (and (math-constp a) (math-constp b)
+	   0)
+      (list 'calcFunc-in a b))
+)
+
+(defun calcFunc-typeof (a)
+  (cond ((Math-integerp a) 1)
+	((eq (car a) 'frac) 2)
+	((eq (car a) 'float) 3)
+	((eq (car a) 'hms) 4)
+	((eq (car a) 'cplx) 5)
+	((eq (car a) 'polar) 6)
+	((eq (car a) 'sdev) 7)
+	((eq (car a) 'intv) 8)
+	((eq (car a) 'mod) 9)
+	((eq (car a) 'date) (if (Math-integerp (nth 1 a)) 10 11))
+	((eq (car a) 'var)
+	 (if (memq (nth 2 a) '(var-inf var-uinf var-nan)) 12 100))
+	((eq (car a) 'vec) (if (math-matrixp a) 102 101))
+	(t (math-calcFunc-to-var func)))
+)
+
+(defun calcFunc-integer (a)
+  (if (Math-integerp a)
+      1
+    (if (Math-objvecp a)
+	0
+      (list 'calcFunc-integer a)))
+)
+
+(defun calcFunc-real (a)
+  (if (Math-realp a)
+      1
+    (if (Math-objvecp a)
+	0
+      (list 'calcFunc-real a)))
+)
+
+(defun calcFunc-constant (a)
+  (if (math-constp a)
+      1
+    (if (Math-objvecp a)
+	0
+      (list 'calcFunc-constant a)))
+)
+
+(defun calcFunc-refers (a b)
+  (if (math-expr-contains a b)
+      1
+    (if (eq (car-safe a) 'var)
+	(list 'calcFunc-refers a b)
+      0))
+)
+
+(defun calcFunc-negative (a)
+  (if (math-looks-negp a)
+      1
+    (if (or (math-zerop a)
+	    (math-posp a))
+	0
+      (list 'calcFunc-negative a)))
+)
+
+(defun calcFunc-variable (a)
+  (if (eq (car-safe a) 'var)
+      1
+    (if (Math-objvecp a)
+	0
+      (list 'calcFunc-variable a)))
+)
+
+(defun calcFunc-nonvar (a)
+  (if (eq (car-safe a) 'var)
+      (list 'calcFunc-nonvar a)
+    1)
+)
+
+(defun calcFunc-istrue (a)
+  (if (math-is-true a)
+      1
+    0)
+)
+
+
+
+
+;;;; User-programmability.
+
+;;; Compiling Lisp-like forms to use the math library.
+
+(defun math-do-defmath (func args body)
+  (calc-need-macros)
+  (let* ((fname (intern (concat "calcFunc-" (symbol-name func))))
+	 (doc (if (stringp (car body)) (list (car body))))
+	 (clargs (mapcar 'math-clean-arg args))
+	 (body (math-define-function-body
+		(if (stringp (car body)) (cdr body) body)
+		clargs)))
+    (list 'progn
+	  (if (and (consp (car body))
+		   (eq (car (car body)) 'interactive))
+	      (let ((inter (car body)))
+		(setq body (cdr body))
+		(if (or (> (length inter) 2)
+			(integerp (nth 1 inter)))
+		    (let ((hasprefix nil) (hasmulti nil))
+		      (if (stringp (nth 1 inter))
+			  (progn
+			    (cond ((equal (nth 1 inter) "p")
+				   (setq hasprefix t))
+				  ((equal (nth 1 inter) "m")
+				   (setq hasmulti t))
+				  (t (error
+				      "Can't handle interactive code string \"%s\""
+				      (nth 1 inter))))
+			    (setq inter (cdr inter))))
+		      (if (not (integerp (nth 1 inter)))
+			  (error
+			   "Expected an integer in interactive specification"))
+		      (append (list 'defun
+				    (intern (concat "calc-"
+						    (symbol-name func)))
+				    (if (or hasprefix hasmulti)
+					'(&optional n)
+				      ()))
+			      doc
+			      (if (or hasprefix hasmulti)
+				  '((interactive "P"))
+				'((interactive)))
+			      (list
+			       (append
+				'(calc-slow-wrapper)
+				(and hasmulti
+				     (list
+				      (list 'setq
+					    'n
+					    (list 'if
+						  'n
+						  (list 'prefix-numeric-value
+							'n)
+						  (nth 1 inter)))))
+				(list
+				 (list 'calc-enter-result
+				       (if hasmulti 'n (nth 1 inter))
+				       (nth 2 inter)
+				       (if hasprefix
+					   (list 'append
+						 (list 'quote (list fname))
+						 (list 'calc-top-list-n
+						       (nth 1 inter))
+						 (list 'and
+						       'n
+						       (list
+							'list
+							(list
+							 'math-normalize
+							 (list
+							  'prefix-numeric-value
+							  'n)))))
+					 (list 'cons
+					       (list 'quote fname)
+					       (list 'calc-top-list-n
+						     (if hasmulti
+							 'n
+						       (nth 1 inter)))))))))))
+		  (append (list 'defun
+				(intern (concat "calc-" (symbol-name func)))
+				args)
+			  doc
+			  (list
+			   inter
+			   (cons 'calc-wrapper body))))))
+	  (append (list 'defun fname clargs)
+		  doc
+		  (math-do-arg-list-check args nil nil)
+		  body)))
+)
+
+(defun math-clean-arg (arg)
+  (if (consp arg)
+      (math-clean-arg (nth 1 arg))
+    arg)
+)
+
+(defun math-do-arg-check (arg var is-opt is-rest)
+  (if is-opt
+      (let ((chk (math-do-arg-check arg var nil nil)))
+	(list (cons 'and
+		    (cons var
+			  (if (cdr chk)
+			      (setq chk (list (cons 'progn chk)))
+			    chk)))))
+    (and (consp arg)
+	 (let* ((rest (math-do-arg-check (nth 1 arg) var is-opt is-rest))
+		(qual (car arg))
+		(qqual (list 'quote qual))
+		(qual-name (symbol-name qual))
+		(chk (intern (concat "math-check-" qual-name))))
+	   (if (fboundp chk)
+	       (append rest
+		       (list
+			(if is-rest
+			    (list 'setq var
+				  (list 'mapcar (list 'quote chk) var))
+			  (list 'setq var (list chk var)))))
+	     (if (fboundp (setq chk (intern (concat "math-" qual-name))))
+		 (append rest
+			 (list
+			  (if is-rest
+			      (list 'mapcar
+				    (list 'function
+					  (list 'lambda '(x)
+						(list 'or
+						      (list chk 'x)
+						      (list 'math-reject-arg
+							    'x qqual))))
+				    var)
+			    (list 'or
+				  (list chk var)
+				  (list 'math-reject-arg var qqual)))))
+	       (if (and (string-match "\\`not-\\(.*\\)\\'" qual-name)
+			(fboundp (setq chk (intern
+					    (concat "math-"
+						    (math-match-substring
+						     qual-name 1))))))
+		   (append rest
+			   (list
+			    (if is-rest
+				(list 'mapcar
+				      (list 'function
+					    (list 'lambda '(x)
+						  (list 'and
+							(list chk 'x)
+							(list 'math-reject-arg
+							      'x qqual))))
+				      var)
+			      (list 'and
+				    (list chk var)
+				    (list 'math-reject-arg var qqual)))))
+		 (error "Unknown qualifier `%s'" qual-name)))))))
+)
+
+(defun math-do-arg-list-check (args is-opt is-rest)
+  (cond ((null args) nil)
+	((consp (car args))
+	 (append (math-do-arg-check (car args)
+				    (math-clean-arg (car args))
+				    is-opt is-rest)
+		 (math-do-arg-list-check (cdr args) is-opt is-rest)))
+	((eq (car args) '&optional)
+	 (math-do-arg-list-check (cdr args) t nil))
+	((eq (car args) '&rest)
+	 (math-do-arg-list-check (cdr args) nil t))
+	(t (math-do-arg-list-check (cdr args) is-opt is-rest)))
+)
+
+(defconst math-prim-funcs
+  '( (~= . math-nearly-equal)
+     (% . math-mod)
+     (lsh . calcFunc-lsh)
+     (ash . calcFunc-ash)
+     (logand . calcFunc-and)
+     (logandc2 . calcFunc-diff)
+     (logior . calcFunc-or)
+     (logxor . calcFunc-xor)
+     (lognot . calcFunc-not)
+     (equal . equal)   ; need to leave these ones alone!
+     (eq . eq)
+     (and . and)
+     (or . or)
+     (if . if)
+     (^ . math-pow)
+     (expt . math-pow)
+   )
+)
+
+(defconst math-prim-vars
+  '( (nil . nil)
+     (t . t)
+     (&optional . &optional)
+     (&rest . &rest)
+   )
+)
+
+(defun math-define-function-body (body env)
+  (let ((body (math-define-body body env)))
+    (if (math-body-refers-to body 'math-return)
+	(list (cons 'catch (cons '(quote math-return) body)))
+      body))
+)
+
+(defun math-define-body (body exp-env)
+  (math-define-list body)
+)
+
+(defun math-define-list (body &optional quote)
+  (cond ((null body)
+	 nil)
+	((and (eq (car body) ':)
+	      (stringp (nth 1 body)))
+	 (cons (let* ((math-read-expr-quotes t)
+		      (exp (math-read-plain-expr (nth 1 body) t)))
+		 (math-define-exp exp))
+	       (math-define-list (cdr (cdr body)))))
+	(quote
+	 (cons (cond ((consp (car body))
+		      (math-define-list (cdr body) t))
+		     (t
+		      (car body)))
+	       (math-define-list (cdr body))))
+	(t
+	 (cons (math-define-exp (car body))
+	       (math-define-list (cdr body)))))
+)
+
+(defun math-define-exp (exp)
+  (cond ((consp exp)
+	 (let ((func (car exp)))
+	   (cond ((memq func '(quote function))
+		  (if (and (consp (nth 1 exp))
+			   (eq (car (nth 1 exp)) 'lambda))
+		      (cons 'quote
+			    (math-define-lambda (nth 1 exp) exp-env))
+		    exp))
+		 ((memq func '(let let* for foreach))
+		  (let ((head (nth 1 exp))
+			(body (cdr (cdr exp))))
+		    (if (memq func '(let let*))
+			()
+		      (setq func (cdr (assq func '((for . math-for)
+						   (foreach . math-foreach)))))
+		      (if (not (listp (car head)))
+			  (setq head (list head))))
+		    (macroexpand
+		     (cons func
+			   (cons (math-define-let head)
+				 (math-define-body body
+						   (nconc
+						    (math-define-let-env head)
+						    exp-env)))))))
+		 ((and (memq func '(setq setf))
+		       (math-complicated-lhs (cdr exp)))
+		  (if (> (length exp) 3)
+		      (cons 'progn (math-define-setf-list (cdr exp)))
+		    (math-define-setf (nth 1 exp) (nth 2 exp))))
+		 ((eq func 'condition-case)
+		  (cons func
+			(cons (nth 1 exp)
+			      (math-define-body (cdr (cdr exp))
+						(cons (nth 1 exp)
+						      exp-env)))))
+		 ((eq func 'cond)
+		  (cons func
+			(math-define-cond (cdr exp))))
+		 ((and (consp func)   ; ('spam a b) == force use of plain spam
+		       (eq (car func) 'quote))
+		  (cons func (math-define-list (cdr exp))))
+		 ((symbolp func)
+		  (let ((args (math-define-list (cdr exp)))
+			(prim (assq func math-prim-funcs)))
+		    (cond (prim
+			   (cons (cdr prim) args))
+			  ((eq func 'floatp)
+			   (list 'eq (car args) '(quote float)))
+			  ((eq func '+)
+			   (math-define-binop 'math-add 0
+					      (car args) (cdr args)))
+			  ((eq func '-)
+			   (if (= (length args) 1)
+			       (cons 'math-neg args)
+			     (math-define-binop 'math-sub 0
+						(car args) (cdr args))))
+			  ((eq func '*)
+			   (math-define-binop 'math-mul 1
+					      (car args) (cdr args)))
+			  ((eq func '/)
+			   (math-define-binop 'math-div 1
+					      (car args) (cdr args)))
+			  ((eq func 'min)
+			   (math-define-binop 'math-min 0
+					      (car args) (cdr args)))
+			  ((eq func 'max)
+			   (math-define-binop 'math-max 0
+					      (car args) (cdr args)))
+			  ((eq func '<)
+			   (if (and (math-numberp (nth 1 args))
+				    (math-zerop (nth 1 args)))
+			       (list 'math-negp (car args))
+			     (cons 'math-lessp args)))
+			  ((eq func '>)
+			   (if (and (math-numberp (nth 1 args))
+				    (math-zerop (nth 1 args)))
+			       (list 'math-posp (car args))
+			     (list 'math-lessp (nth 1 args) (nth 0 args))))
+			  ((eq func '<=)
+			   (list 'not
+				 (if (and (math-numberp (nth 1 args))
+					  (math-zerop (nth 1 args)))
+				     (list 'math-posp (car args))
+				   (list 'math-lessp
+					 (nth 1 args) (nth 0 args)))))
+			  ((eq func '>=)
+			   (list 'not
+				 (if (and (math-numberp (nth 1 args))
+					  (math-zerop (nth 1 args)))
+				     (list 'math-negp (car args))
+				   (cons 'math-lessp args))))
+			  ((eq func '=)
+			   (if (and (math-numberp (nth 1 args))
+				    (math-zerop (nth 1 args)))
+			       (list 'math-zerop (nth 0 args))
+			     (if (and (integerp (nth 1 args))
+				      (/= (% (nth 1 args) 10) 0))
+				 (cons 'math-equal-int args)
+			       (cons 'math-equal args))))
+			  ((eq func '/=)
+			   (list 'not
+				 (if (and (math-numberp (nth 1 args))
+					  (math-zerop (nth 1 args)))
+				     (list 'math-zerop (nth 0 args))
+				   (if (and (integerp (nth 1 args))
+					    (/= (% (nth 1 args) 10) 0))
+				       (cons 'math-equal-int args)
+				     (cons 'math-equal args)))))
+			  ((eq func '1+)
+			   (list 'math-add (car args) 1))
+			  ((eq func '1-)
+			   (list 'math-add (car args) -1))
+			  ((eq func 'not)   ; optimize (not (not x)) => x
+			   (if (eq (car-safe args) func)
+			       (car (nth 1 args))
+			     (cons func args)))
+			  ((and (eq func 'elt) (cdr (cdr args)))
+			   (math-define-elt (car args) (cdr args)))
+			  (t
+			   (macroexpand
+			    (let* ((name (symbol-name func))
+				   (cfunc (intern (concat "calcFunc-" name)))
+				   (mfunc (intern (concat "math-" name))))
+			      (cond ((fboundp cfunc)
+				     (cons cfunc args))
+				    ((fboundp mfunc)
+				     (cons mfunc args))
+				    ((or (fboundp func)
+					 (string-match "\\`calcFunc-.*" name))
+				     (cons func args))
+				    (t
+				     (cons cfunc args)))))))))
+		 (t (cons func args)))))
+	((symbolp exp)
+	 (let ((prim (assq exp math-prim-vars))
+	       (name (symbol-name exp)))
+	   (cond (prim
+		  (cdr prim))
+		 ((memq exp exp-env)
+		  exp)
+		 ((string-match "-" name)
+		  exp)
+		 (t
+		  (intern (concat "var-" name))))))
+	((integerp exp)
+	 (if (or (<= exp -1000000) (>= exp 1000000))
+	     (list 'quote (math-normalize exp))
+	   exp))
+	(t exp))
+)
+
+(defun math-define-cond (forms)
+  (and forms
+       (cons (math-define-list (car forms))
+	     (math-define-cond (cdr forms))))
+)
+
+(defun math-complicated-lhs (body)
+  (and body
+       (or (not (symbolp (car body)))
+	   (math-complicated-lhs (cdr (cdr body)))))
+)
+
+(defun math-define-setf-list (body)
+  (and body
+       (cons (math-define-setf (nth 0 body) (nth 1 body))
+	     (math-define-setf-list (cdr (cdr body)))))
+)
+
+(defun math-define-setf (place value)
+  (setq place (math-define-exp place)
+	value (math-define-exp value))
+  (cond ((symbolp place)
+	 (list 'setq place value))
+	((eq (car-safe place) 'nth)
+	 (list 'setcar (list 'nthcdr (nth 1 place) (nth 2 place)) value))
+	((eq (car-safe place) 'elt)
+	 (list 'setcar (list 'nthcdr (nth 2 place) (nth 1 place)) value))
+	((eq (car-safe place) 'car)
+	 (list 'setcar (nth 1 place) value))
+	((eq (car-safe place) 'cdr)
+	 (list 'setcdr (nth 1 place) value))
+	(t
+	 (error "Bad place form for setf: %s" place)))
+)
+
+(defun math-define-binop (op ident arg1 rest)
+  (if rest
+      (math-define-binop op ident
+			 (list op arg1 (car rest))
+			 (cdr rest))
+    (or arg1 ident))
+)
+
+(defun math-define-let (vlist)
+  (and vlist
+       (cons (if (consp (car vlist))
+		 (cons (car (car vlist))
+		       (math-define-list (cdr (car vlist))))
+	       (car vlist))
+	     (math-define-let (cdr vlist))))
+)
+
+(defun math-define-let-env (vlist)
+  (and vlist
+       (cons (if (consp (car vlist))
+		 (car (car vlist))
+	       (car vlist))
+	     (math-define-let-env (cdr vlist))))
+)
+
+(defun math-define-lambda (exp exp-env)
+  (nconc (list (nth 0 exp)   ; 'lambda
+	       (nth 1 exp))  ; arg list
+	 (math-define-function-body (cdr (cdr exp))
+				    (append (nth 1 exp) exp-env)))
+)
+
+(defun math-define-elt (seq idx)
+  (if idx
+      (math-define-elt (list 'elt seq (car idx)) (cdr idx))
+    seq)
+)
+
+
+
+;;; Useful programming macros.
+
+(defmacro math-while (head &rest body)
+  (let ((body (cons 'while (cons head body))))
+    (if (math-body-refers-to body 'math-break)
+	(cons 'catch (cons '(quote math-break) (list body)))
+      body))
+)
+
+
+(defmacro math-for (head &rest body)
+  (let ((body (if head
+		  (math-handle-for head body)
+		(cons 'while (cons t body)))))
+    (if (math-body-refers-to body 'math-break)
+	(cons 'catch (cons '(quote math-break) (list body)))
+      body))
+)
+
+(defun math-handle-for (head body)
+  (let* ((var (nth 0 (car head)))
+	 (init (nth 1 (car head)))
+	 (limit (nth 2 (car head)))
+	 (step (or (nth 3 (car head)) 1))
+	 (body (if (cdr head)
+		   (list (math-handle-for (cdr head) body))
+		 body))
+	 (all-ints (and (integerp init) (integerp limit) (integerp step)))
+	 (const-limit (or (integerp limit)
+			  (and (eq (car-safe limit) 'quote)
+			       (math-realp (nth 1 limit)))))
+	 (const-step (or (integerp step)
+			 (and (eq (car-safe step) 'quote)
+			      (math-realp (nth 1 step)))))
+	 (save-limit (if const-limit limit (make-symbol "<limit>")))
+	 (save-step (if const-step step (make-symbol "<step>"))))
+    (cons 'let
+	  (cons (append (if const-limit nil (list (list save-limit limit)))
+			(if const-step nil (list (list save-step step)))
+			(list (list var init)))
+		(list
+		 (cons 'while
+		       (cons (if all-ints
+				 (if (> step 0)
+				     (list '<= var save-limit)
+				   (list '>= var save-limit))
+			       (list 'not
+				     (if const-step
+					 (if (or (math-posp step)
+						 (math-posp
+						  (cdr-safe step)))
+					     (list 'math-lessp
+						   save-limit
+						   var)
+					   (list 'math-lessp
+						 var
+						 save-limit))
+				       (list 'if
+					     (list 'math-posp
+						   save-step)
+					     (list 'math-lessp
+						   save-limit
+						   var)
+					     (list 'math-lessp
+						   var
+						   save-limit)))))
+			     (append body
+				     (list (list 'setq
+						 var
+						 (list (if all-ints
+							   '+
+							 'math-add)
+						       var
+						       save-step))))))))))
+)
+
+
+(defmacro math-foreach (head &rest body)
+  (let ((body (math-handle-foreach head body)))
+    (if (math-body-refers-to body 'math-break)
+	(cons 'catch (cons '(quote math-break) (list body)))
+      body))
+)
+
+
+(defun math-handle-foreach (head body)
+  (let ((var (nth 0 (car head)))
+	(data (nth 1 (car head)))
+	(body (if (cdr head)
+		  (list (math-handle-foreach (cdr head) body))
+		body)))
+    (cons 'let
+	  (cons (list (list var data))
+		(list
+		 (cons 'while
+		       (cons var
+			     (append body
+				     (list (list 'setq
+						 var
+						 (list 'cdr var))))))))))
+)
+
+
+(defun math-body-refers-to (body thing)
+  (or (equal body thing)
+      (and (consp body)
+	   (or (math-body-refers-to (car body) thing)
+	       (math-body-refers-to (cdr body) thing))))
+)
+
+(defun math-break (&optional value)
+  (throw 'math-break value)
+)
+
+(defun math-return (&optional value)
+  (throw 'math-return value)
+)
+
+
+
+
+
+(defun math-composite-inequalities (x op)
+  (if (memq (nth 1 op) '(calcFunc-eq calcFunc-neq))
+      (if (eq (car x) (nth 1 op))
+	  (append x (list (math-read-expr-level (nth 3 op))))
+	(throw 'syntax "Syntax error"))
+    (list 'calcFunc-in
+	  (nth 2 x)
+	  (if (memq (nth 1 op) '(calcFunc-lt calcFunc-leq))
+	      (if (memq (car x) '(calcFunc-lt calcFunc-leq))
+		  (math-make-intv
+		   (+ (if (eq (car x) 'calcFunc-leq) 2 0)
+		      (if (eq (nth 1 op) 'calcFunc-leq) 1 0))
+		   (nth 1 x) (math-read-expr-level (nth 3 op)))
+		(throw 'syntax "Syntax error"))
+	    (if (memq (car x) '(calcFunc-gt calcFunc-geq))
+		(math-make-intv
+		 (+ (if (eq (nth 1 op) 'calcFunc-geq) 2 0)
+		    (if (eq (car x) 'calcFunc-geq) 1 0))
+		 (math-read-expr-level (nth 3 op)) (nth 1 x))
+	      (throw 'syntax "Syntax error")))))
+)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/calc-rewr.el	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,2097 @@
+;; Calculator for GNU Emacs, part II [calc-rewr.el]
+;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+;; Written by Dave Gillespie, daveg@synaptics.com.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY.  No author or distributor
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing.  Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License.   A copy of this license is
+;; supposed to have been given to you along with GNU Emacs so you
+;; can know your rights and responsibilities.  It should be in a
+;; file named COPYING.  Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+
+
+
+;; This file is autoloaded from calc-ext.el.
+(require 'calc-ext)
+
+(require 'calc-macs)
+
+(defun calc-Need-calc-rewr () nil)
+
+
+(defun calc-rewrite-selection (rules-str &optional many prefix)
+  (interactive "sRewrite rule(s): \np")
+  (calc-slow-wrapper
+   (calc-preserve-point)
+   (let* ((num (max 1 (calc-locate-cursor-element (point))))
+	  (reselect t)
+	  (pop-rules nil)
+	  (entry (calc-top num 'entry))
+	  (expr (car entry))
+	  (sel (calc-auto-selection entry))
+	  (math-rewrite-selections t)
+	  (math-rewrite-default-iters 1))
+     (if (or (null rules-str) (equal rules-str "") (equal rules-str "$"))
+	 (if (= num 1)
+	     (error "Can't use same stack entry for formula and rules.")
+	   (setq rules (calc-top-n 1 t)
+		 pop-rules t))
+       (setq rules (if (stringp rules-str)
+		       (math-read-exprs rules-str) rules-str))
+       (if (eq (car-safe rules) 'error)
+	   (error "Bad format in expression: %s" (nth 1 rules)))
+       (if (= (length rules) 1)
+	   (setq rules (car rules))
+	 (setq rules (cons 'vec rules)))
+       (or (memq (car-safe rules) '(vec var calcFunc-assign
+					calcFunc-condition))
+	   (let ((rhs (math-read-expr
+		       (read-string (concat "Rewrite from:    " rules-str
+					    "  to: ")))))
+	     (if (eq (car-safe rhs) 'error)
+		 (error "Bad format in expression: %s" (nth 1 rhs)))
+	     (setq rules (list 'calcFunc-assign rules rhs))))
+       (or (eq (car-safe rules) 'var)
+	   (calc-record rules "rule")))
+     (if (eq many 0)
+	 (setq many '(var inf var-inf))
+       (if many (setq many (prefix-numeric-value many))))
+     (if sel
+	 (setq expr (calc-replace-sub-formula (car entry)
+					      sel
+					      (list 'calcFunc-select sel)))
+       (setq expr (car entry)
+	     reselect nil
+	     math-rewrite-selections nil))
+     (setq expr (calc-encase-atoms
+		 (calc-normalize
+		  (math-rewrite
+		   (calc-normalize expr)
+		   rules many)))
+	   sel nil
+	   expr (calc-locate-select-marker expr))
+     (or (consp sel) (setq sel nil))
+     (if pop-rules (calc-pop-stack 1))
+     (calc-pop-push-record-list 1 (or prefix "rwrt") (list expr)
+				(- num (if pop-rules 1 0))
+				(list (and reselect sel))))
+   (calc-handle-whys))
+)
+
+(defun calc-locate-select-marker (expr)    ; changes "sel"
+  (if (Math-primp expr)
+      expr
+    (if (and (eq (car expr) 'calcFunc-select)
+	     (= (length expr) 2))
+	(progn
+	  (setq sel (if sel t (nth 1 expr)))
+	  (nth 1 expr))
+      (cons (car expr)
+	    (mapcar 'calc-locate-select-marker (cdr expr)))))
+)
+
+
+
+(defun calc-rewrite (rules-str many)
+  (interactive "sRewrite rule(s): \nP")
+  (calc-slow-wrapper
+   (let (n rules expr)
+     (if (or (null rules-str) (equal rules-str "") (equal rules-str "$"))
+	 (setq expr (calc-top-n 2)
+	       rules (calc-top-n 1 t)
+	       n 2)
+       (setq rules (if (stringp rules-str)
+		       (math-read-exprs rules-str) rules-str))
+       (if (eq (car-safe rules) 'error)
+	   (error "Bad format in expression: %s" (nth 1 rules)))
+       (if (= (length rules) 1)
+	   (setq rules (car rules))
+	 (setq rules (cons 'vec rules)))
+       (or (memq (car-safe rules) '(vec var calcFunc-assign
+					calcFunc-condition))
+	   (let ((rhs (math-read-expr
+		       (read-string (concat "Rewrite from:    " rules-str
+					    " to: ")))))
+	     (if (eq (car-safe rhs) 'error)
+		 (error "Bad format in expression: %s" (nth 1 rhs)))
+	     (setq rules (list 'calcFunc-assign rules rhs))))
+       (or (eq (car-safe rules) 'var)
+	   (calc-record rules "rule"))
+       (setq expr (calc-top-n 1)
+	     n 1))
+     (if (eq many 0)
+	 (setq many '(var inf var-inf))
+       (if many (setq many (prefix-numeric-value many))))
+     (setq expr (calc-normalize (math-rewrite expr rules many)))
+     (let (sel)
+       (setq expr (calc-locate-select-marker expr)))
+     (calc-pop-push-record-list n "rwrt" (list expr)))
+   (calc-handle-whys))
+)
+
+(defun calc-match (pat)
+  (interactive "sPattern: \n")
+  (calc-slow-wrapper
+   (let (n expr)
+     (if (or (null pat) (equal pat "") (equal pat "$"))
+	 (setq expr (calc-top-n 2)
+	       pat (calc-top-n 1)
+	       n 2)
+       (if (interactive-p) (setq calc-previous-alg-entry pat))
+       (setq pat (if (stringp pat) (math-read-expr pat) pat))
+       (if (eq (car-safe pat) 'error)
+	   (error "Bad format in expression: %s" (nth 1 pat)))
+       (if (not (eq (car-safe pat) 'var))
+	   (calc-record pat "pat"))
+       (setq expr (calc-top-n 1)
+	     n 1))
+     (or (math-vectorp expr) (error "Argument must be a vector"))
+     (if (calc-is-inverse)
+	 (calc-enter-result n "mtcn" (math-match-patterns pat expr t))
+       (calc-enter-result n "mtch" (math-match-patterns pat expr nil)))))
+)
+
+
+
+(defun math-rewrite (whole-expr rules &optional mmt-many)
+  (let ((crules (math-compile-rewrites rules))
+	(heads (math-rewrite-heads whole-expr))
+	(trace-buffer (get-buffer "*Trace*"))
+	(calc-display-just 'center)
+	(calc-display-origin 39)
+	(calc-line-breaking 78)
+	(calc-line-numbering nil)
+	(calc-show-selections t)
+	(calc-why nil)
+	(mmt-func (function
+		   (lambda (x)
+		     (let ((result (math-apply-rewrites x (cdr crules)
+							heads crules)))
+		       (if result
+			   (progn
+			     (if trace-buffer
+				 (let ((fmt (math-format-stack-value
+					     (list result nil nil))))
+				   (save-excursion
+				     (set-buffer trace-buffer)
+				     (insert "\nrewrite to\n" fmt "\n"))))
+			     (setq heads (math-rewrite-heads result heads t))))
+		       result)))))
+    (if trace-buffer
+	(let ((fmt (math-format-stack-value (list whole-expr nil nil))))
+	  (save-excursion
+	    (set-buffer trace-buffer)
+	    (setq truncate-lines t)
+	    (goto-char (point-max))
+	    (insert "\n\nBegin rewriting\n" fmt "\n"))))
+    (or mmt-many (setq mmt-many (or (nth 1 (car crules))
+				    math-rewrite-default-iters)))
+    (if (equal mmt-many '(var inf var-inf)) (setq mmt-many 1000000))
+    (if (equal mmt-many '(neg (var inf var-inf))) (setq mmt-many -1000000))
+    (math-rewrite-phase (nth 3 (car crules)))
+    (if trace-buffer
+	(let ((fmt (math-format-stack-value (list whole-expr nil nil))))
+	  (save-excursion
+	    (set-buffer trace-buffer)
+	    (insert "\nDone rewriting"
+		    (if (= mmt-many 0) " (reached iteration limit)" "")
+		    ":\n" fmt "\n"))))
+    whole-expr)
+)
+(setq math-rewrite-default-iters 100)
+
+(defun math-rewrite-phase (sched)
+  (while (and sched (/= mmt-many 0))
+    (if (listp (car sched))
+	(while (let ((save-expr whole-expr))
+		 (math-rewrite-phase (car sched))
+		 (not (equal whole-expr save-expr))))
+      (if (symbolp (car sched))
+	  (progn
+	    (setq whole-expr (math-normalize (list (car sched) whole-expr)))
+	    (if trace-buffer
+		(let ((fmt (math-format-stack-value
+			    (list whole-expr nil nil))))
+		  (save-excursion
+		    (set-buffer trace-buffer)
+		    (insert "\ncall "
+			    (substring (symbol-name (car sched)) 9)
+			    ":\n" fmt "\n")))))
+	(let ((math-rewrite-phase (car sched)))
+	  (if trace-buffer
+	      (save-excursion
+		(set-buffer trace-buffer)
+		(insert (format "\n(Phase %d)\n" math-rewrite-phase))))
+	  (while (let ((save-expr whole-expr))
+		   (setq whole-expr (math-normalize
+				     (math-map-tree-rec whole-expr)))
+		   (not (equal whole-expr save-expr)))))))
+    (setq sched (cdr sched)))
+)
+
+(defun calcFunc-rewrite (expr rules &optional many)
+  (or (null many) (integerp many)
+      (equal many '(var inf var-inf)) (equal many '(neg (var inf var-inf)))
+      (math-reject-arg many 'fixnump))
+  (condition-case err
+      (math-rewrite expr rules (or many 1))
+    (error (math-reject-arg rules (nth 1 err))))
+)
+
+(defun calcFunc-match (pat vec)
+  (or (math-vectorp vec) (math-reject-arg vec 'vectorp))
+  (condition-case err
+      (math-match-patterns pat vec nil)
+    (error (math-reject-arg pat (nth 1 err))))
+)
+
+(defun calcFunc-matchnot (pat vec)
+  (or (math-vectorp vec) (math-reject-arg vec 'vectorp))
+  (condition-case err
+      (math-match-patterns pat vec t)
+    (error (math-reject-arg pat (nth 1 err))))
+)
+
+(defun math-match-patterns (pat vec &optional not-flag)
+  (let ((newvec nil)
+	(crules (math-compile-patterns pat)))
+    (while (setq vec (cdr vec))
+      (if (eq (not (math-apply-rewrites (car vec) crules))
+	      not-flag)
+	  (setq newvec (cons (car vec) newvec))))
+    (cons 'vec (nreverse newvec)))
+)
+
+(defun calcFunc-matches (expr pat)
+  (condition-case err
+      (if (math-apply-rewrites expr (math-compile-patterns pat))
+	  1
+	0)
+    (error (math-reject-arg pat (nth 1 err))))
+)
+
+(defun calcFunc-vmatches (expr pat)
+  (condition-case err
+      (or (math-apply-rewrites expr (math-compile-patterns pat))
+	  0)
+    (error (math-reject-arg pat (nth 1 err))))
+)
+
+
+
+;;; A compiled rule set is an a-list of entries whose cars are functors,
+;;; and whose cdrs are lists of rules.  If there are rules with no
+;;; well-defined head functor, they are included on all lists and also
+;;; on an extra list whose car is nil.
+;;;
+;;; The first entry in the a-list is of the form (schedule A B C ...).
+;;;
+;;; Rule list entries take the form (regs prog head phases), where:
+;;;
+;;;   regs   is a vector of match registers.
+;;;
+;;;   prog   is a match program (see below).
+;;;
+;;;   head   is a rare function name appearing in the rule body (but not the
+;;;	     head of the whole rule), or nil if none.
+;;;
+;;;   phases is a list of phase numbers for which the rule is enabled.
+;;;
+;;; A match program is a list of match instructions.
+;;;
+;;; In the following, "part" is a register number that contains the
+;;; subexpression to be operated on.
+;;;
+;;; Register 0 is the whole expression being matched.  The others are
+;;; meta-variables in the pattern, temporaries used for matching and
+;;; backtracking, and constant expressions.
+;;;
+;;; (same part reg)
+;;;         The selected part must be math-equal to the contents of "reg".
+;;;
+;;; (same-neg part reg)
+;;;         The selected part must be math-equal to the negative of "reg".
+;;;
+;;; (copy part reg)
+;;;	    The selected part is copied into "reg".  (Rarely used.)
+;;;
+;;; (copy-neg part reg)
+;;;	    The negative of the selected part is copied into "reg".
+;;;
+;;; (integer part)
+;;;         The selected part must be an integer.
+;;;
+;;; (real part)
+;;;         The selected part must be a real.
+;;;
+;;; (constant part)
+;;;         The selected part must be a constant.
+;;;
+;;; (negative part)
+;;;	    The selected part must "look" negative.
+;;;
+;;; (rel part op reg)
+;;;         The selected part must satisfy "part op reg", where "op"
+;;;	    is one of the 6 relational ops, and "reg" is a register.
+;;;
+;;; (mod part modulo value)
+;;;         The selected part must satisfy "part % modulo = value", where
+;;;         "modulo" and "value" are constants.
+;;;
+;;; (func part head reg1 reg2 ... regn)
+;;;         The selected part must be an n-ary call to function "head".
+;;;         The arguments are stored in "reg1" through "regn".
+;;;
+;;; (func-def part head defs reg1 reg2 ... regn)
+;;;	    The selected part must be an n-ary call to function "head".
+;;;	    "Defs" is a list of value/register number pairs for default args.
+;;;	    If a match, assign default values to registers and then skip
+;;;	    immediately over any following "func-def" instructions and
+;;;	    the following "func" instruction.  If wrong number of arguments,
+;;;	    proceed to the following "func-def" or "func" instruction.
+;;;
+;;; (func-opt part head defs reg1)
+;;;	    Like func-def with "n=1", except that if the selected part is
+;;;	    not a call to "head", then the part itself successfully matches
+;;;	    "reg1" (and the defaults are assigned).
+;;;
+;;; (try part heads mark reg1 [def])
+;;;         The selected part must be a function of the correct type which is
+;;;         associative and/or commutative.  "Heads" is a list of acceptable
+;;;         types.  An initial assignment of arguments to "reg1" is tried.
+;;;	    If the program later fails, it backtracks to this instruction
+;;;	    and tries other assignments of arguments to "reg1".
+;;;	    If "def" exists and normal matching fails, backtrack and assign
+;;;	    "part" to "reg1", and "def" to "reg2" in the following "try2".
+;;;	    The "mark" is a vector of size 5; only "mark[3-4]" are initialized.
+;;;	    "mark[0]" points to the argument list; "mark[1]" points to the
+;;;	    current argument; "mark[2]" is 0 if there are two arguments,
+;;;	    1 if reg1 is matching single arguments, 2 if reg2 is matching
+;;;	    single arguments (a+b+c+d is never split as (a+b)+(c+d)), or
+;;;         3 if reg2 is matching "def"; "mark[3]" is 0 if the function must
+;;;	    have two arguments, 1 if phase-2 can be skipped, 2 if full
+;;;	    backtracking is necessary; "mark[4]" is t if the arguments have
+;;;	    been switched from the order given in the original pattern.
+;;;
+;;; (try2 try reg2)
+;;;         Every "try" will be followed by a "try2" whose "try" field is
+;;;	    a pointer to the corresponding "try".  The arguments which were
+;;;	    not stored in "reg1" by that "try" are now stored in "reg2".
+;;;
+;;; (alt instr nil mark)
+;;;	    Basic backtracking.  Execute the instruction sequence "instr".
+;;;	    If this fails, back up and execute following the "alt" instruction.
+;;;	    The "mark" must be the vector "[nil nil 4]".  The "instr" sequence
+;;;	    should execute "end-alt" at the end.
+;;;
+;;; (end-alt ptr)
+;;; 	    Register success of the first alternative of a previous "alt".
+;;;	    "Ptr" is a pointer to the next instruction following that "alt".
+;;;
+;;; (apply part reg1 reg2)
+;;;         The selected part must be a function call.  The functor
+;;;	    (as a variable name) is stored in "reg1"; the arguments
+;;;	    (as a vector) are stored in "reg2".
+;;;
+;;; (cons part reg1 reg2)
+;;;	    The selected part must be a nonempty vector.  The first element
+;;;	    of the vector is stored in "reg1"; the rest of the vector
+;;;	    (as another vector) is stored in "reg2".
+;;;
+;;; (rcons part reg1 reg2)
+;;;	    The selected part must be a nonempty vector.  The last element
+;;;	    of the vector is stored in "reg2"; the rest of the vector
+;;;	    (as another vector) is stored in "reg1".
+;;;
+;;; (select part reg)
+;;;         If the selected part is a unary call to function "select", its
+;;;         argument is stored in "reg"; otherwise (provided this is an `a r'
+;;;         and not a `g r' command) the selected part is stored in "reg".
+;;;
+;;; (cond expr)
+;;;         The "expr", with registers substituted, must simplify to
+;;;         a non-zero value.
+;;;
+;;; (let reg expr)
+;;;         Evaluate "expr" and store the result in "reg".  Always succeeds.
+;;;
+;;; (done rhs remember)
+;;;         Rewrite the expression to "rhs", with register substituted.
+;;;	    Normalize; if the result is different from the original
+;;;	    expression, the match has succeeded.  This is the last
+;;;	    instruction of every program.  If "remember" is non-nil,
+;;;         record the result of the match as a new literal rule.
+
+
+;;; Pseudo-functions related to rewrites:
+;;;
+;;;  In patterns:  quote, plain, condition, opt, apply, cons, select
+;;;
+;;;  In righthand sides:  quote, plain, eval, evalsimp, evalextsimp,
+;;;                       apply, cons, select
+;;;
+;;;  In conditions:  let + same as for righthand sides
+
+;;; Some optimizations that would be nice to have:
+;;;
+;;;  * Merge registers with disjoint lifetimes.
+;;;  * Merge constant registers with equivalent values.
+;;;
+;;;  * If an argument of a commutative op math-depends neither on the
+;;;    rest of the pattern nor on any of the conditions, then no backtracking
+;;;    should be done for that argument.  (This won't apply to very many
+;;;    cases.)
+;;;
+;;;  * If top functor is "select", and its argument is a unique function,
+;;;    add the rule to the lists for both "select" and that function.
+;;;    (Currently rules like this go on the "nil" list.)
+;;;    Same for "func-opt" functions.  (Though not urgent for these.)
+;;;
+;;;  * Shouldn't evaluate a "let" condition until the end, or until it
+;;;    would enable another condition to be evaluated.
+;;;
+
+;;; Some additional features to add / things to think about:
+;;;
+;;;  * Figure out what happens to "a +/- b" and "a +/- opt(b)".
+;;;
+;;;  * Same for interval forms.
+;;;
+;;;  * Have a name(v,pat) pattern which matches pat, and gives the
+;;;    whole match the name v.  Beware of circular structures!
+;;;
+
+(defun math-compile-patterns (pats)
+  (if (and (eq (car-safe pats) 'var)
+	   (calc-var-value (nth 2 pats)))
+      (let ((prop (get (nth 2 pats) 'math-pattern-cache)))
+	(or prop
+	    (put (nth 2 pats) 'math-pattern-cache (setq prop (list nil))))
+	(or (eq (car prop) (symbol-value (nth 2 pats)))
+	    (progn
+	      (setcdr prop (math-compile-patterns
+			    (symbol-value (nth 2 pats))))
+	      (setcar prop (symbol-value (nth 2 pats)))))
+	(cdr prop))
+    (let ((math-rewrite-whole t))
+      (cdr (math-compile-rewrites (cons
+				   'vec
+				   (mapcar (function (lambda (x)
+						       (list 'vec x t)))
+					   (if (eq (car-safe pats) 'vec)
+					       (cdr pats)
+					     (list pats))))))))
+)
+(setq math-rewrite-whole nil)
+(setq math-make-import-list nil)
+
+(defun math-compile-rewrites (rules &optional name)
+  (if (eq (car-safe rules) 'var)
+      (let ((prop (get (nth 2 rules) 'math-rewrite-cache))
+	    (math-import-list nil)
+	    (math-make-import-list t)
+	    p)
+	(or (calc-var-value (nth 2 rules))
+	    (error "Rules variable %s has no stored value" (nth 1 rules)))
+	(or prop
+	    (put (nth 2 rules) 'math-rewrite-cache
+		 (setq prop (list (list (cons (nth 2 rules) nil))))))
+	(setq p (car prop))
+	(while (and p (eq (symbol-value (car (car p))) (cdr (car p))))
+	  (setq p (cdr p)))
+	(or (null p)
+	    (progn
+	      (message "Compiling rule set %s..." (nth 1 rules))
+	      (setcdr prop (math-compile-rewrites
+			    (symbol-value (nth 2 rules))
+			    (nth 2 rules)))
+	      (message "Compiling rule set %s...done" (nth 1 rules))
+	      (setcar prop (cons (cons (nth 2 rules)
+				       (symbol-value (nth 2 rules)))
+				 math-import-list))))
+	(cdr prop))
+    (if (or (not (eq (car-safe rules) 'vec))
+	    (and (memq (length rules) '(3 4))
+		 (let ((p rules))
+		   (while (and (setq p (cdr p))
+			       (memq (car-safe (car p))
+				     '(vec
+				       calcFunc-assign
+				       calcFunc-condition
+				       calcFunc-import
+				       calcFunc-phase
+				       calcFunc-schedule
+				       calcFunc-iterations))))
+		   p)))
+	(setq rules (list rules))
+      (setq rules (cdr rules)))
+    (if (assq 'calcFunc-import rules)
+	(let ((pp (setq rules (copy-sequence rules)))
+	      p part)
+	  (while (setq p (car (cdr pp)))
+	    (if (eq (car-safe p) 'calcFunc-import)
+		(progn
+		  (setcdr pp (cdr (cdr pp)))
+		  (or (and (eq (car-safe (nth 1 p)) 'var)
+			   (setq part (calc-var-value (nth 2 (nth 1 p))))
+			   (memq (car-safe part) '(vec
+						   calcFunc-assign
+						   calcFunc-condition)))
+		      (error "Argument of import() must be a rules variable"))
+		  (if math-make-import-list
+		      (setq math-import-list
+			    (cons (cons (nth 2 (nth 1 p))
+					(symbol-value (nth 2 (nth 1 p))))
+				  math-import-list)))
+		  (while (setq p (cdr (cdr p)))
+		    (or (cdr p)
+			(error "import() must have odd number of arguments"))
+		    (setq part (math-rwcomp-substitute part
+						       (car p) (nth 1 p))))
+		  (if (eq (car-safe part) 'vec)
+		      (setq part (cdr part))
+		    (setq part (list part)))
+		  (setcdr pp (append part (cdr pp))))
+	      (setq pp (cdr pp))))))
+    (let ((rule-set nil)
+	  (all-heads nil)
+	  (nil-rules nil)
+	  (rule-count 0)
+	  (math-schedule nil)
+	  (math-iterations nil)
+	  (math-phases nil)
+	  (math-all-phases nil)
+	  (math-remembering nil)
+	  math-pattern math-rhs math-conds)
+      (while rules
+	(cond
+	 ((and (eq (car-safe (car rules)) 'calcFunc-iterations)
+	       (= (length (car rules)) 2))
+	  (or (integerp (nth 1 (car rules)))
+	      (equal (nth 1 (car rules)) '(var inf var-inf))
+	      (equal (nth 1 (car rules)) '(neg (var inf var-inf)))
+	      (error "Invalid argument for iterations(n)"))
+	  (or math-iterations
+	      (setq math-iterations (nth 1 (car rules)))))
+	 ((eq (car-safe (car rules)) 'calcFunc-schedule)
+	  (or math-schedule
+	      (setq math-schedule (math-parse-schedule (cdr (car rules))))))
+	 ((eq (car-safe (car rules)) 'calcFunc-phase)
+	  (setq math-phases (cdr (car rules)))
+	  (if (equal math-phases '((var all var-all)))
+	      (setq math-phases nil))
+	  (let ((p math-phases))
+	    (while p
+	      (or (integerp (car p))
+		  (error "Phase numbers must be small integers"))
+	      (or (memq (car p) math-all-phases)
+		  (setq math-all-phases (cons (car p) math-all-phases)))
+	      (setq p (cdr p)))))
+	 ((or (and (eq (car-safe (car rules)) 'vec)
+		   (cdr (cdr (car rules)))
+		   (not (nthcdr 4 (car rules)))
+		   (setq math-conds (nth 3 (car rules))
+			 math-rhs (nth 2 (car rules))
+			 math-pattern (nth 1 (car rules))))
+	      (progn
+		(setq math-conds nil
+		      math-pattern (car rules))
+		(while (and (eq (car-safe math-pattern) 'calcFunc-condition)
+			    (= (length math-pattern) 3))
+		  (let ((cond (nth 2 math-pattern)))
+		    (setq math-conds (if math-conds
+					 (list 'calcFunc-land math-conds cond)
+				       cond)
+			  math-pattern (nth 1 math-pattern))))
+		(and (eq (car-safe math-pattern) 'calcFunc-assign)
+		     (= (length math-pattern) 3)
+		     (setq math-rhs (nth 2 math-pattern)
+			   math-pattern (nth 1 math-pattern)))))
+	  (let* ((math-prog (list nil))
+		 (math-prog-last math-prog)
+		 (math-num-regs 1)
+		 (math-regs (list (list nil 0 nil nil)))
+		 (math-bound-vars nil)
+		 (math-aliased-vars nil)
+		 (math-copy-neg nil))
+	    (setq math-conds (and math-conds (math-flatten-lands math-conds)))
+	    (math-rwcomp-pattern math-pattern 0)
+	    (while math-conds
+	      (let ((expr (car math-conds)))
+		(setq math-conds (cdr math-conds))
+		(math-rwcomp-cond-instr expr)))
+	    (math-rwcomp-instr 'done
+			       (if (eq math-rhs t)
+				   (cons 'vec
+					 (delq
+					  nil
+					  (nreverse
+					   (mapcar
+					    (function
+					     (lambda (v)
+					       (and (car v)
+						    (list
+						     'calcFunc-assign
+						     (math-build-var-name
+						      (car v))
+						     (math-rwcomp-register-expr
+						      (nth 1 v))))))
+					    math-regs))))
+				 (math-rwcomp-match-vars math-rhs))
+			       math-remembering)
+	    (setq math-prog (cdr math-prog))
+	    (let* ((heads (math-rewrite-heads math-pattern))
+		   (rule (list (vconcat
+				(nreverse
+				 (mapcar (function (lambda (x) (nth 3 x)))
+					 math-regs)))
+			       math-prog
+			       heads
+			       math-phases))
+		   (head (and (not (Math-primp math-pattern))
+			      (not (and (eq (car (car math-prog)) 'try)
+					(nth 5 (car math-prog))))
+			      (not (memq (car (car math-prog)) '(func-opt
+								 apply
+								 select
+								 alt)))
+			      (if (memq (car (car math-prog)) '(func
+								func-def))
+				  (nth 2 (car math-prog))
+				(if (eq (car math-pattern) 'calcFunc-quote)
+				    (car-safe (nth 1 math-pattern))
+				  (car math-pattern))))))
+	      (let (found)
+		(while heads
+		  (if (setq found (assq (car heads) all-heads))
+		      (setcdr found (1+ (cdr found)))
+		    (setq all-heads (cons (cons (car heads) 1) all-heads)))
+		  (setq heads (cdr heads))))
+	      (if (eq head '-) (setq head '+))
+	      (if (memq head '(calcFunc-cons calcFunc-rcons)) (setq head 'vec))
+	      (if head
+		  (progn
+		    (nconc (or (assq head rule-set)
+			       (car (setq rule-set (cons (cons head
+							       (copy-sequence
+								nil-rules))
+							 rule-set))))
+			   (list rule))
+		    (if (eq head '*)
+			(nconc (or (assq '/ rule-set)
+				   (car (setq rule-set (cons (cons
+							      '/
+							      (copy-sequence
+							       nil-rules))
+							     rule-set))))
+			       (list rule))))
+		(setq nil-rules (nconc nil-rules (list rule)))
+		(let ((ptr rule-set))
+		  (while ptr
+		    (nconc (car ptr) (list rule))
+		    (setq ptr (cdr ptr))))))))
+	 (t
+	  (error "Rewrite rule set must be a vector of A := B rules")))
+	(setq rules (cdr rules)))
+      (if nil-rules
+	  (setq rule-set (cons (cons nil nil-rules) rule-set)))
+      (setq all-heads (mapcar 'car
+			      (sort all-heads (function
+					       (lambda (x y)
+						 (< (cdr x) (cdr y)))))))
+      (let ((set rule-set)
+	    rule heads ptr)
+	(while set
+	  (setq rule (cdr (car set)))
+	  (while rule
+	    (if (consp (setq heads (nth 2 (car rule))))
+		(progn
+		  (setq heads (delq (car (car set)) heads)
+			ptr all-heads)
+		  (while (and ptr (not (memq (car ptr) heads)))
+		    (setq ptr (cdr ptr)))
+		  (setcar (nthcdr 2 (car rule)) (car ptr))))
+	    (setq rule (cdr rule)))
+	  (setq set (cdr set))))
+      (let ((plus (assq '+ rule-set)))
+	(if plus
+	    (setq rule-set (cons (cons '- (cdr plus)) rule-set))))
+      (cons (list 'schedule math-iterations name
+		  (or math-schedule
+		      (sort math-all-phases '<)
+		      (list 1)))
+	    rule-set)))
+)
+
+(defun math-flatten-lands (expr)
+  (if (eq (car-safe expr) 'calcFunc-land)
+      (append (math-flatten-lands (nth 1 expr))
+	      (math-flatten-lands (nth 2 expr)))
+    (list expr))
+)
+
+(defun math-rewrite-heads (expr &optional more all)
+  (let ((heads more)
+	(skips (and (not all)
+		    '(calcFunc-apply calcFunc-condition calcFunc-opt
+				     calcFunc-por calcFunc-pnot)))
+	(blanks (and (not all)
+		     '(calcFunc-quote calcFunc-plain calcFunc-select
+				      calcFunc-cons calcFunc-rcons
+				      calcFunc-pand))))
+    (or (Math-primp expr)
+	(math-rewrite-heads-rec expr))
+    heads)
+)
+
+(defun math-rewrite-heads-rec (expr)
+  (or (memq (car expr) skips)
+      (progn
+	(or (memq (car expr) heads)
+	    (memq (car expr) blanks)
+	    (memq 'algebraic (get (car expr) 'math-rewrite-props))
+	    (setq heads (cons (car expr) heads)))
+	(while (setq expr (cdr expr))
+	  (or (Math-primp (car expr))
+	      (math-rewrite-heads-rec (car expr))))))
+)
+
+(defun math-parse-schedule (sched)
+  (mapcar (function
+	   (lambda (s)
+	     (if (integerp s)
+		 s
+	       (if (math-vectorp s)
+		   (math-parse-schedule (cdr s))
+		 (if (eq (car-safe s) 'var)
+		     (math-var-to-calcFunc s)
+		   (error "Improper component in rewrite schedule"))))))
+	  sched)
+)
+
+(defun math-rwcomp-match-vars (expr)
+  (if (Math-primp expr)
+      (if (eq (car-safe expr) 'var)
+	  (let ((entry (assq (nth 2 expr) math-regs)))
+	    (if entry
+		(math-rwcomp-register-expr (nth 1 entry))
+	      expr))
+	expr)
+    (if (and (eq (car expr) 'calcFunc-quote)
+	     (= (length expr) 2))
+	(math-rwcomp-match-vars (nth 1 expr))
+      (if (and (eq (car expr) 'calcFunc-plain)
+	       (= (length expr) 2)
+	       (not (Math-primp (nth 1 expr))))
+	  (list (car expr)
+		(cons (car (nth 1 expr))
+		      (mapcar 'math-rwcomp-match-vars (cdr (nth 1 expr)))))
+	(cons (car expr)
+	      (mapcar 'math-rwcomp-match-vars (cdr expr))))))
+)
+
+(defun math-rwcomp-register-expr (num)
+  (let ((entry (nth (1- (- math-num-regs num)) math-regs)))
+    (if (nth 2 entry)
+	(list 'neg (list 'calcFunc-register (nth 1 entry)))
+      (list 'calcFunc-register (nth 1 entry))))
+)
+
+(defun math-rwcomp-substitute (expr old new)
+  (if (and (eq (car-safe old) 'var)
+	   (memq (car-safe new) '(var calcFunc-lambda)))
+      (let ((old-func (math-var-to-calcFunc old))
+	    (new-func (math-var-to-calcFunc new)))
+	(math-rwcomp-subst-rec expr))
+    (let ((old-func nil))
+      (math-rwcomp-subst-rec expr)))
+)
+
+(defun math-rwcomp-subst-rec (expr)
+  (cond ((equal expr old) new)
+	((Math-primp expr) expr)
+	(t (if (eq (car expr) old-func)
+	       (math-build-call new-func (mapcar 'math-rwcomp-subst-rec
+						 (cdr expr)))
+	     (cons (car expr)
+		   (mapcar 'math-rwcomp-subst-rec (cdr expr))))))
+)
+
+(setq math-rwcomp-tracing nil)
+
+(defun math-rwcomp-trace (instr)
+  (if math-rwcomp-tracing (progn (terpri) (princ instr)))
+  instr
+)
+
+(defun math-rwcomp-instr (&rest instr)
+  (setcdr math-prog-last
+	  (setq math-prog-last (list (math-rwcomp-trace instr))))
+)
+
+(defun math-rwcomp-multi-instr (tail &rest instr)
+  (setcdr math-prog-last
+	  (setq math-prog-last (list (math-rwcomp-trace (append instr tail)))))
+)
+
+(defun math-rwcomp-bind-var (reg var)
+  (setcar (math-rwcomp-reg-entry reg) (nth 2 var))
+  (setq math-bound-vars (cons (nth 2 var) math-bound-vars))
+  (math-rwcomp-do-conditions)
+)
+
+(defun math-rwcomp-unbind-vars (mark)
+  (while (not (eq math-bound-vars mark))
+    (setcar (assq (car math-bound-vars) math-regs) nil)
+    (setq math-bound-vars (cdr math-bound-vars)))
+)
+
+(defun math-rwcomp-do-conditions ()
+  (let ((cond math-conds))
+    (while cond
+      (if (math-rwcomp-all-regs-done (car cond))
+	  (let ((expr (car cond)))
+	    (setq math-conds (delq (car cond) math-conds))
+	    (setcar cond 1)
+	    (math-rwcomp-cond-instr expr)))
+      (setq cond (cdr cond))))
+)
+
+(defun math-rwcomp-cond-instr (expr)
+  (let (op arg)
+    (cond ((and (eq (car-safe expr) 'calcFunc-matches)
+		(= (length expr) 3)
+		(eq (car-safe (setq arg (math-rwcomp-match-vars (nth 1 expr))))
+		    'calcFunc-register))
+	   (math-rwcomp-pattern (nth 2 expr) (nth 1 arg)))
+	  ((math-numberp (setq expr (math-rwcomp-match-vars expr)))
+	   (if (Math-zerop expr)
+	       (math-rwcomp-instr 'backtrack)))
+	  ((and (eq (car expr) 'calcFunc-let)
+		(= (length expr) 3))
+	   (let ((reg (math-rwcomp-reg)))
+	     (math-rwcomp-instr 'let reg (nth 2 expr))
+	     (math-rwcomp-pattern (nth 1 expr) reg)))
+	  ((and (eq (car expr) 'calcFunc-let)
+		(= (length expr) 2)
+		(eq (car-safe (nth 1 expr)) 'calcFunc-assign)
+		(= (length (nth 1 expr)) 3))
+	   (let ((reg (math-rwcomp-reg)))
+	     (math-rwcomp-instr 'let reg (nth 2 (nth 1 expr)))
+	     (math-rwcomp-pattern (nth 1 (nth 1 expr)) reg)))
+	  ((and (setq op (cdr (assq (car-safe expr)
+				    '( (calcFunc-integer  . integer)
+				       (calcFunc-real     . real)
+				       (calcFunc-constant . constant)
+				       (calcFunc-negative . negative) ))))
+		(= (length expr) 2)
+		(or (and (eq (car-safe (nth 1 expr)) 'neg)
+			 (memq op '(integer real constant))
+			 (setq arg (nth 1 (nth 1 expr))))
+		    (setq arg (nth 1 expr)))
+		(eq (car-safe (setq arg (nth 1 expr))) 'calcFunc-register))
+	   (math-rwcomp-instr op (nth 1 arg)))
+	  ((and (assq (car-safe expr) calc-tweak-eqn-table)
+		(= (length expr) 3)
+		(eq (car-safe (nth 1 expr)) 'calcFunc-register))
+	   (if (math-constp (nth 2 expr))
+	       (let ((reg (math-rwcomp-reg)))
+		 (setcar (nthcdr 3 (car math-regs)) (nth 2 expr))
+		 (math-rwcomp-instr 'rel (nth 1 (nth 1 expr))
+				    (car expr) reg))
+	     (if (eq (car (nth 2 expr)) 'calcFunc-register)
+		 (math-rwcomp-instr 'rel (nth 1 (nth 1 expr))
+				    (car expr) (nth 1 (nth 2 expr)))
+	       (math-rwcomp-instr 'cond expr))))
+	  ((and (eq (car-safe expr) 'calcFunc-eq)
+		(= (length expr) 3)
+		(eq (car-safe (nth 1 expr)) '%)
+		(eq (car-safe (nth 1 (nth 1 expr))) 'calcFunc-register)
+		(math-constp (nth 2 (nth 1 expr)))
+		(math-constp (nth 2 expr)))
+	   (math-rwcomp-instr 'mod (nth 1 (nth 1 (nth 1 expr)))
+			      (nth 2 (nth 1 expr)) (nth 2 expr)))
+	  ((equal expr '(var remember var-remember))
+	   (setq math-remembering 1))
+	  ((and (eq (car-safe expr) 'calcFunc-remember)
+		(= (length expr) 2))
+	   (setq math-remembering (if math-remembering
+				      (list 'calcFunc-lor
+					    math-remembering (nth 1 expr))
+				    (nth 1 expr))))
+	  (t (math-rwcomp-instr 'cond expr))))
+)
+
+(defun math-rwcomp-same-instr (reg1 reg2 neg)
+  (math-rwcomp-instr (if (eq (eq (nth 2 (math-rwcomp-reg-entry reg1))
+				 (nth 2 (math-rwcomp-reg-entry reg2)))
+			     neg)
+			 'same-neg
+		       'same)
+		     reg1 reg2)
+)
+
+(defun math-rwcomp-copy-instr (reg1 reg2 neg)
+  (if (eq (eq (nth 2 (math-rwcomp-reg-entry reg1))
+	      (nth 2 (math-rwcomp-reg-entry reg2)))
+	  neg)
+      (math-rwcomp-instr 'copy-neg reg1 reg2)
+    (or (eq reg1 reg2)
+	(math-rwcomp-instr 'copy reg1 reg2)))
+)
+
+(defun math-rwcomp-reg ()
+  (prog1
+      math-num-regs
+    (setq math-regs (cons (list nil math-num-regs nil 0) math-regs)
+	  math-num-regs (1+ math-num-regs)))
+)
+
+(defun math-rwcomp-reg-entry (num)
+  (nth (1- (- math-num-regs num)) math-regs)
+)
+
+
+(defun math-rwcomp-pattern (expr part &optional not-direct)
+  (cond ((or (math-rwcomp-no-vars expr)
+	     (and (eq (car expr) 'calcFunc-quote)
+		  (= (length expr) 2)
+		  (setq expr (nth 1 expr))))
+ 	 (if (eq (car-safe expr) 'calcFunc-register)
+	     (math-rwcomp-same-instr part (nth 1 expr) nil)
+	   (let ((reg (math-rwcomp-reg)))
+	     (setcar (nthcdr 3 (car math-regs)) expr)
+	     (math-rwcomp-same-instr part reg nil))))
+ 	((eq (car expr) 'var)
+ 	 (let ((entry (assq (nth 2 expr) math-regs)))
+	   (if entry
+	       (math-rwcomp-same-instr part (nth 1 entry) nil)
+	     (if not-direct
+ 		 (let ((reg (math-rwcomp-reg)))
+		   (math-rwcomp-pattern expr reg)
+		   (math-rwcomp-copy-instr part reg nil))
+	       (if (setq entry (assq (nth 2 expr) math-aliased-vars))
+		   (progn
+		     (setcar (math-rwcomp-reg-entry (nth 1 entry))
+			     (nth 2 expr))
+		     (setcar entry nil)
+		     (math-rwcomp-copy-instr part (nth 1 entry) nil))
+ 		 (math-rwcomp-bind-var part expr))))))
+ 	((and (eq (car expr) 'calcFunc-select)
+	      (= (length expr) 2))
+ 	 (let ((reg (math-rwcomp-reg)))
+	   (math-rwcomp-instr 'select part reg)
+	   (math-rwcomp-pattern (nth 1 expr) reg)))
+ 	((and (eq (car expr) 'calcFunc-opt)
+	      (memq (length expr) '(2 3)))
+ 	 (error "opt( ) occurs in context where it is not allowed"))
+ 	((eq (car expr) 'neg)
+ 	 (if (eq (car (nth 1 expr)) 'var)
+	     (let ((entry (assq (nth 2 (nth 1 expr)) math-regs)))
+	       (if entry
+		   (math-rwcomp-same-instr part (nth 1 entry) t)
+		 (if math-copy-neg
+		     (let ((reg (math-rwcomp-best-reg (nth 1 expr))))
+		       (math-rwcomp-copy-instr part reg t)
+		       (math-rwcomp-pattern (nth 1 expr) reg))
+		   (setcar (cdr (cdr (math-rwcomp-reg-entry part))) t)
+		   (math-rwcomp-pattern (nth 1 expr) part))))
+	   (if (math-rwcomp-is-algebraic (nth 1 expr))
+	       (math-rwcomp-cond-instr (list 'calcFunc-eq
+					     (math-rwcomp-register-expr part)
+					     expr))
+	     (let ((reg (math-rwcomp-reg)))
+	       (math-rwcomp-instr 'func part 'neg reg)
+	       (math-rwcomp-pattern (nth 1 expr) reg)))))
+ 	((and (eq (car expr) 'calcFunc-apply)
+	      (= (length expr) 3))
+ 	 (let ((reg1 (math-rwcomp-reg))
+	       (reg2 (math-rwcomp-reg)))
+	   (math-rwcomp-instr 'apply part reg1 reg2)
+	   (math-rwcomp-pattern (nth 1 expr) reg1)
+	   (math-rwcomp-pattern (nth 2 expr) reg2)))
+ 	((and (eq (car expr) 'calcFunc-cons)
+	      (= (length expr) 3))
+ 	 (let ((reg1 (math-rwcomp-reg))
+	       (reg2 (math-rwcomp-reg)))
+	   (math-rwcomp-instr 'cons part reg1 reg2)
+	   (math-rwcomp-pattern (nth 1 expr) reg1)
+	   (math-rwcomp-pattern (nth 2 expr) reg2)))
+ 	((and (eq (car expr) 'calcFunc-rcons)
+	      (= (length expr) 3))
+ 	 (let ((reg1 (math-rwcomp-reg))
+	       (reg2 (math-rwcomp-reg)))
+	   (math-rwcomp-instr 'rcons part reg1 reg2)
+	   (math-rwcomp-pattern (nth 1 expr) reg1)
+	   (math-rwcomp-pattern (nth 2 expr) reg2)))
+ 	((and (eq (car expr) 'calcFunc-condition)
+	      (>= (length expr) 3))
+ 	 (math-rwcomp-pattern (nth 1 expr) part)
+ 	 (setq expr (cdr expr))
+ 	 (while (setq expr (cdr expr))
+	   (let ((cond (math-flatten-lands (car expr))))
+	     (while cond
+	       (if (math-rwcomp-all-regs-done (car cond))
+		   (math-rwcomp-cond-instr (car cond))
+ 		 (setq math-conds (cons (car cond) math-conds)))
+	       (setq cond (cdr cond))))))
+ 	((and (eq (car expr) 'calcFunc-pand)
+	      (= (length expr) 3))
+ 	 (math-rwcomp-pattern (nth 1 expr) part)
+ 	 (math-rwcomp-pattern (nth 2 expr) part))
+ 	((and (eq (car expr) 'calcFunc-por)
+	      (= (length expr) 3))
+ 	 (math-rwcomp-instr 'alt nil nil [nil nil 4])
+ 	 (let ((math-conds nil)
+	       (head math-prog-last)
+	       (mark math-bound-vars)
+	       (math-copy-neg t))
+	   (math-rwcomp-pattern (nth 1 expr) part t)
+	   (let ((amark math-aliased-vars)
+		 (math-aliased-vars math-aliased-vars)
+ 		 (tail math-prog-last)
+		 (p math-bound-vars)
+		 entry)
+	     (while (not (eq p mark))
+	       (setq entry (assq (car p) math-regs)
+		     math-aliased-vars (cons (list (car p) (nth 1 entry) nil)
+					     math-aliased-vars)
+		     p (cdr p))
+	       (setcar (math-rwcomp-reg-entry (nth 1 entry)) nil))
+	     (setcar (cdr (car head)) (cdr head))
+	     (setcdr head nil)
+	     (setq math-prog-last head)
+	     (math-rwcomp-pattern (nth 2 expr) part)
+	     (math-rwcomp-instr 'same 0 0)
+	     (setcdr tail math-prog-last)
+	     (setq p math-aliased-vars)
+	     (while (not (eq p amark))
+	       (if (car (car p))
+		   (setcar (math-rwcomp-reg-entry (nth 1 (car p)))
+			   (car (car p))))
+	       (setq p (cdr p)))))
+ 	 (math-rwcomp-do-conditions))
+ 	((and (eq (car expr) 'calcFunc-pnot)
+	      (= (length expr) 2))
+ 	 (math-rwcomp-instr 'alt nil nil [nil nil 4])
+ 	 (let ((head math-prog-last)
+	       (mark math-bound-vars))
+	   (math-rwcomp-pattern (nth 1 expr) part)
+	   (math-rwcomp-unbind-vars mark)
+	   (math-rwcomp-instr 'end-alt head)
+	   (math-rwcomp-instr 'backtrack)
+	   (setcar (cdr (car head)) (cdr head))
+	   (setcdr head nil)
+	   (setq math-prog-last head)))
+ 	(t (let ((props (get (car expr) 'math-rewrite-props)))
+	     (if (and (eq (car expr) 'calcFunc-plain)
+		      (= (length expr) 2)
+		      (not (math-primp (nth 1 expr))))
+ 		 (setq expr (nth 1 expr))) ; but "props" is still nil
+	     (if (and (memq 'algebraic props)
+		      (math-rwcomp-is-algebraic expr))
+ 		 (math-rwcomp-cond-instr (list 'calcFunc-eq
+					       (math-rwcomp-register-expr part)
+					       expr))
+	       (if (and (memq 'commut props)
+ 			(= (length expr) 3))
+		   (let ((arg1 (nth 1 expr))
+ 			 (arg2 (nth 2 expr))
+ 			 try1 def code head (flip nil))
+		     (if (eq (car expr) '-)
+ 			 (setq arg2 (math-rwcomp-neg arg2)))
+		     (setq arg1 (cons arg1 (math-rwcomp-best-reg arg1))
+			   arg2 (cons arg2 (math-rwcomp-best-reg arg2)))
+		     (or (math-rwcomp-order arg1 arg2)
+ 			 (setq def arg1 arg1 arg2 arg2 def flip t))
+		     (if (math-rwcomp-optional-arg (car expr) arg1)
+ 			 (error "Too many opt( ) arguments in this context"))
+		     (setq def (math-rwcomp-optional-arg (car expr) arg2)
+			   head (if (memq (car expr) '(+ -))
+				    '(+ -)
+				  (if (eq (car expr) '*)
+				      '(* /)
+				    (list (car expr))))
+			   code (if (math-rwcomp-is-constrained
+				     (car arg1) head)
+				    (if (math-rwcomp-is-constrained
+ 					 (car arg2) head)
+ 					0 1)
+				  2))
+		     (math-rwcomp-multi-instr (and def (list def))
+					      'try part head
+					      (vector nil nil nil code flip)
+					      (cdr arg1))
+		     (setq try1 (car math-prog-last))
+		     (math-rwcomp-pattern (car arg1) (cdr arg1))
+		     (math-rwcomp-instr 'try2 try1 (cdr arg2))
+		     (if (and (= part 0) (not def) (not math-rewrite-whole)
+			      (not (eq math-rhs t))
+ 			      (setq def (get (car expr)
+ 					     'math-rewrite-default)))
+ 			 (let ((reg1 (math-rwcomp-reg))
+ 			       (reg2 (math-rwcomp-reg)))
+ 			   (if (= (aref (nth 3 try1) 3) 0)
+ 			       (aset (nth 3 try1) 3 1))
+			   (math-rwcomp-instr 'try (cdr arg2)
+					      (if (equal head '(* /))
+						  '(*) head)
+ 					      (vector nil nil nil
+ 						      (if (= code 0)
+ 							  1 2)
+ 						      nil)
+ 					      reg1 def)
+ 			   (setq try1 (car math-prog-last))
+ 			   (math-rwcomp-pattern (car arg2) reg1)
+ 			   (math-rwcomp-instr 'try2 try1 reg2)
+ 			   (setq math-rhs (list (if (eq (car expr) '-)
+ 						    '+ (car expr))
+ 						math-rhs
+ 						(list 'calcFunc-register
+ 						      reg2))))
+ 		       (math-rwcomp-pattern (car arg2) (cdr arg2))))
+ 		 (let* ((args (mapcar (function
+ 				       (lambda (x)
+ 					 (cons x (math-rwcomp-best-reg x))))
+ 				      (cdr expr)))
+ 			(args2 (copy-sequence args))
+ 			(argp (reverse args2))
+ 			(defs nil)
+ 			(num 1))
+ 		   (while argp
+ 		     (let ((def (math-rwcomp-optional-arg (car expr)
+ 							  (car argp))))
+ 		       (if def
+ 			   (progn
+ 			     (setq args2 (delq (car argp) args2)
+ 				   defs (cons (cons def (cdr (car argp)))
+ 					      defs))
+ 			     (math-rwcomp-multi-instr
+ 			      (mapcar 'cdr args2)
+ 			      (if (or (and (memq 'unary1 props)
+ 					   (= (length args2) 1)
+ 					   (eq (car args2) (car args)))
+ 				      (and (memq 'unary2 props)
+ 					   (= (length args) 2)
+ 					   (eq (car args2) (nth 1 args))))
+ 				  'func-opt
+ 				'func-def)
+ 			      part (car expr)
+ 			      defs))))
+ 		     (setq argp (cdr argp)))
+ 		   (math-rwcomp-multi-instr (mapcar 'cdr args)
+ 					    'func part (car expr))
+ 		   (setq args (sort args 'math-rwcomp-order))
+ 		   (while args
+ 		     (math-rwcomp-pattern (car (car args)) (cdr (car args)))
+ 		     (setq num (1+ num)
+ 			   args (cdr args)))))))))
+)
+
+(defun math-rwcomp-best-reg (x)
+  (or (and (eq (car-safe x) 'var)
+	   (let ((entry (assq (nth 2 x) math-aliased-vars)))
+	     (and entry
+		  (not (nth 2 entry))
+		  (not (nth 2 (math-rwcomp-reg-entry (nth 1 entry))))
+		  (progn
+		    (setcar (cdr (cdr entry)) t)
+		    (nth 1 entry)))))
+      (math-rwcomp-reg))
+)
+
+(defun math-rwcomp-all-regs-done (expr)
+  (if (Math-primp expr)
+      (or (not (eq (car-safe expr) 'var))
+	  (assq (nth 2 expr) math-regs)
+	  (eq (nth 2 expr) 'var-remember)
+	  (math-const-var expr))
+    (if (and (eq (car expr) 'calcFunc-let)
+	     (= (length expr) 3))
+	(math-rwcomp-all-regs-done (nth 2 expr))
+      (if (and (eq (car expr) 'calcFunc-let)
+	       (= (length expr) 2)
+	       (eq (car-safe (nth 1 expr)) 'calcFunc-assign)
+	       (= (length (nth 1 expr)) 3))
+	  (math-rwcomp-all-regs-done (nth 2 (nth 1 expr)))
+	(while (and (setq expr (cdr expr))
+		    (math-rwcomp-all-regs-done (car expr))))
+	(null expr))))
+)
+
+(defun math-rwcomp-no-vars (expr)
+  (if (Math-primp expr)
+      (or (not (eq (car-safe expr) 'var))
+	  (math-const-var expr))
+    (and (not (memq (car expr) '(calcFunc-condition
+				 calcFunc-select calcFunc-quote
+				 calcFunc-plain calcFunc-opt
+				 calcFunc-por calcFunc-pand
+				 calcFunc-pnot calcFunc-apply
+				 calcFunc-cons calcFunc-rcons)))
+	 (progn
+	   (while (and (setq expr (cdr expr))
+		       (math-rwcomp-no-vars (car expr))))
+	   (null expr))))
+)
+
+(defun math-rwcomp-is-algebraic (expr)
+  (if (Math-primp expr)
+      (or (not (eq (car-safe expr) 'var))
+	  (math-const-var expr)
+	  (assq (nth 2 expr) math-regs))
+    (and (memq 'algebraic (get (car expr) 'math-rewrite-props))
+	 (progn
+	   (while (and (setq expr (cdr expr))
+		       (math-rwcomp-is-algebraic (car expr))))
+	   (null expr))))
+)
+
+(defun math-rwcomp-is-constrained (expr not-these)
+  (if (Math-primp expr)
+      (not (eq (car-safe expr) 'var))
+    (if (eq (car expr) 'calcFunc-plain)
+	(math-rwcomp-is-constrained (nth 1 expr) not-these)
+      (not (or (memq (car expr) '(neg calcFunc-select))
+	       (memq (car expr) not-these)
+	       (and (memq 'commut (get (car expr) 'math-rewrite-props))
+		    (or (eq (car-safe (nth 1 expr)) 'calcFunc-opt)
+			(eq (car-safe (nth 2 expr)) 'calcFunc-opt)))))))
+)
+
+(defun math-rwcomp-optional-arg (head argp)
+  (let ((arg (car argp)))
+    (if (eq (car-safe arg) 'calcFunc-opt)
+	(and (memq (length arg) '(2 3))
+	     (progn
+	       (or (eq (car-safe (nth 1 arg)) 'var)
+		   (error "First argument of opt( ) must be a variable"))
+	       (setcar argp (nth 1 arg))
+	       (if (= (length arg) 2)
+		   (or (get head 'math-rewrite-default)
+		       (error "opt( ) must include a default in this context"))
+		 (nth 2 arg))))
+      (and (eq (car-safe arg) 'neg)
+	   (let* ((part (list (nth 1 arg)))
+		  (partp (math-rwcomp-optional-arg head part)))
+	     (and partp
+		  (setcar argp (math-rwcomp-neg (car part)))
+		  (math-neg partp))))))
+)
+
+(defun math-rwcomp-neg (expr)
+  (if (memq (car-safe expr) '(* /))
+      (if (eq (car-safe (nth 1 expr)) 'var)
+	  (list (car expr) (list 'neg (nth 1 expr)) (nth 2 expr))
+	(if (eq (car-safe (nth 2 expr)) 'var)
+	    (list (car expr) (nth 1 expr) (list 'neg (nth 2 expr)))
+	  (math-neg expr)))
+    (math-neg expr))
+)
+
+(defun math-rwcomp-assoc-args (expr)
+  (if (and (eq (car-safe (nth 1 expr)) (car expr))
+	   (= (length (nth 1 expr)) 3))
+      (math-rwcomp-assoc-args (nth 1 expr))
+    (setq math-args (cons (nth 1 expr) math-args)))
+  (if (and (eq (car-safe (nth 2 expr)) (car expr))
+	   (= (length (nth 2 expr)) 3))
+      (math-rwcomp-assoc-args (nth 2 expr))
+    (setq math-args (cons (nth 2 expr) math-args)))
+)
+
+(defun math-rwcomp-addsub-args (expr)
+  (if (memq (car-safe (nth 1 expr)) '(+ -))
+      (math-rwcomp-addsub-args (nth 1 expr))
+    (setq math-args (cons (nth 1 expr) math-args)))
+  (if (eq (car expr) '-)
+      (setq math-args (cons (math-rwcomp-neg (nth 2 expr)) math-args))
+    (if (eq (car-safe (nth 2 expr)) '+)
+	(math-rwcomp-addsub-args (nth 2 expr))
+      (setq math-args (cons (nth 2 expr) math-args))))
+)
+
+(defun math-rwcomp-order (a b)
+  (< (math-rwcomp-priority (car a))
+     (math-rwcomp-priority (car b)))
+)
+
+;;; Order of priority:    0 Constants and other exact matches (first)
+;;;                      10 Functions (except below)
+;;;			 20 Meta-variables which occur more than once
+;;;			 30 Algebraic functions
+;;;			 40 Commutative/associative functions
+;;;			 50 Meta-variables which occur only once
+;;;		       +100 for every "!!!" (pnot) in the pattern
+;;;		      10000 Optional arguments (last)
+
+(defun math-rwcomp-priority (expr)
+  (+ (math-rwcomp-count-pnots expr)
+     (cond ((eq (car-safe expr) 'calcFunc-opt)
+	    10000)
+	   ((math-rwcomp-no-vars expr)
+	    0)
+	   ((eq (car expr) 'calcFunc-quote)
+	    0)
+	   ((eq (car expr) 'var)
+	    (if (assq (nth 2 expr) math-regs)
+		0
+	      (if (= (math-rwcomp-count-refs expr) 1)
+		  50
+		20)))
+	   (t (let ((props (get (car expr) 'math-rewrite-props)))
+		(if (or (memq 'commut props)
+			(memq 'assoc props))
+		    40
+		  (if (memq 'algebraic props)
+		      30
+		    10))))))
+)
+
+(defun math-rwcomp-count-refs (var)
+  (let ((count (or (math-expr-contains-count math-pattern var) 0))
+	(p math-conds))
+    (while p
+      (if (eq (car-safe (car p)) 'calcFunc-let)
+	  (if (= (length (car p)) 3)
+	      (setq count (+ count
+			     (or (math-expr-contains-count (nth 2 (car p)) var)
+				 0)))
+	    (if (and (= (length (car p)) 2)
+		     (eq (car-safe (nth 1 (car p))) 'calcFunc-assign)
+		     (= (length (nth 1 (car p))) 3))
+		(setq count (+ count
+			       (or (math-expr-contains-count
+				    (nth 2 (nth 1 (car p))) var) 0))))))
+      (setq p (cdr p)))
+    count)
+)
+
+(defun math-rwcomp-count-pnots (expr)
+  (if (Math-primp expr)
+      0
+    (if (eq (car expr) 'calcFunc-pnot)
+	100
+      (let ((count 0))
+	(while (setq expr (cdr expr))
+	  (setq count (+ count (math-rwcomp-count-pnots (car expr)))))
+	count)))
+)
+
+;;; In the current implementation, all associative functions must
+;;; also be commutative.
+
+(put '+		     'math-rewrite-props '(algebraic assoc commut))
+(put '-		     'math-rewrite-props '(algebraic assoc commut)) ; see below
+(put '*		     'math-rewrite-props '(algebraic assoc commut)) ; see below
+(put '/		     'math-rewrite-props '(algebraic unary1))
+(put '^		     'math-rewrite-props '(algebraic unary1))
+(put '%		     'math-rewrite-props '(algebraic))
+(put 'neg	     'math-rewrite-props '(algebraic))
+(put 'calcFunc-idiv  'math-rewrite-props '(algebraic))
+(put 'calcFunc-abs   'math-rewrite-props '(algebraic))
+(put 'calcFunc-sign  'math-rewrite-props '(algebraic))
+(put 'calcFunc-round 'math-rewrite-props '(algebraic))
+(put 'calcFunc-rounde 'math-rewrite-props '(algebraic))
+(put 'calcFunc-roundu 'math-rewrite-props '(algebraic))
+(put 'calcFunc-trunc 'math-rewrite-props '(algebraic))
+(put 'calcFunc-floor 'math-rewrite-props '(algebraic))
+(put 'calcFunc-ceil  'math-rewrite-props '(algebraic))
+(put 'calcFunc-re    'math-rewrite-props '(algebraic))
+(put 'calcFunc-im    'math-rewrite-props '(algebraic))
+(put 'calcFunc-conj  'math-rewrite-props '(algebraic))
+(put 'calcFunc-arg   'math-rewrite-props '(algebraic))
+(put 'calcFunc-and   'math-rewrite-props '(assoc commut))
+(put 'calcFunc-or    'math-rewrite-props '(assoc commut))
+(put 'calcFunc-xor   'math-rewrite-props '(assoc commut))
+(put 'calcFunc-eq    'math-rewrite-props '(commut))
+(put 'calcFunc-neq   'math-rewrite-props '(commut))
+(put 'calcFunc-land  'math-rewrite-props '(assoc commut))
+(put 'calcFunc-lor   'math-rewrite-props '(assoc commut))
+(put 'calcFunc-beta  'math-rewrite-props '(commut))
+(put 'calcFunc-gcd   'math-rewrite-props '(assoc commut))
+(put 'calcFunc-lcm   'math-rewrite-props '(assoc commut))
+(put 'calcFunc-max   'math-rewrite-props '(algebraic assoc commut))
+(put 'calcFunc-min   'math-rewrite-props '(algebraic assoc commut))
+(put 'calcFunc-vunion 'math-rewrite-props '(assoc commut))
+(put 'calcFunc-vint  'math-rewrite-props '(assoc commut))
+(put 'calcFunc-vxor  'math-rewrite-props '(assoc commut))
+
+;;; Note: "*" is not commutative for matrix args, but we pretend it is.
+;;; Also, "-" is not commutative but the code tweaks things so that it is.
+
+(put '+		     'math-rewrite-default  0)
+(put '-		     'math-rewrite-default  0)
+(put '*		     'math-rewrite-default  1)
+(put '/		     'math-rewrite-default  1)
+(put '^		     'math-rewrite-default  1)
+(put 'calcFunc-land  'math-rewrite-default  1)
+(put 'calcFunc-lor   'math-rewrite-default  0)
+(put 'calcFunc-vunion 'math-rewrite-default '(vec))
+(put 'calcFunc-vint  'math-rewrite-default '(vec))
+(put 'calcFunc-vdiff 'math-rewrite-default '(vec))
+(put 'calcFunc-vxor  'math-rewrite-default '(vec))
+
+(defmacro math-rwfail (&optional back)
+  (list 'setq 'pc
+	(list 'and
+	      (if back
+		  '(setq btrack (cdr btrack))
+		'btrack)
+	      ''((backtrack))))
+)
+
+;;; This monstrosity is necessary because the use of static vectors of
+;;; registers makes rewrite rules non-reentrant.  Yucko!
+(defmacro math-rweval (form)
+  (list 'let '((orig (car rules)))
+	'(setcar rules (quote (nil nil nil no-phase)))
+	(list 'unwind-protect
+	      form
+	      '(setcar rules orig)))
+)
+
+(setq math-rewrite-phase 1)
+
+(defun math-apply-rewrites (expr rules &optional heads ruleset)
+  (and
+   (setq rules (cdr (or (assq (car-safe expr) rules)
+			(assq nil rules))))
+   (let ((result nil)
+	 op regs inst part pc mark btrack
+	 (tracing math-rwcomp-tracing)
+	 (phase math-rewrite-phase))
+     (while rules
+       (or
+	(and (setq part (nth 2 (car rules)))
+	     heads
+	     (not (memq part heads)))
+	(and (setq part (nth 3 (car rules)))
+	     (not (memq phase part)))
+	(progn
+	  (setq regs (car (car rules))
+		pc (nth 1 (car rules))
+		btrack nil)
+	  (aset regs 0 expr)
+	  (while pc
+	     
+	    (and tracing
+		 (progn (terpri) (princ (car pc))
+			(if (and (natnump (nth 1 (car pc)))
+				 (< (nth 1 (car pc)) (length regs)))
+			    (princ (format "\n  part = %s"
+					   (aref regs (nth 1 (car pc))))))))
+	    
+	    (cond ((eq (setq op (car (setq inst (car pc)))) 'func)
+		   (if (and (consp (setq part (aref regs (car (cdr inst)))))
+			    (eq (car part)
+				(car (setq inst (cdr (cdr inst)))))
+			    (progn
+			      (while (and (setq inst (cdr inst)
+						part (cdr part))
+					  inst)
+				(aset regs (car inst) (car part)))
+			      (not (or inst part))))
+		       (setq pc (cdr pc))
+		     (math-rwfail)))
+		  
+		  ((eq op 'same)
+		   (if (or (equal (setq part (aref regs (nth 1 inst)))
+				  (setq mark (aref regs (nth 2 inst))))
+			   (Math-equal part mark))
+		       (setq pc (cdr pc))
+		     (math-rwfail)))
+		  
+		  ((and (eq op 'try)
+			calc-matrix-mode
+			(not (eq calc-matrix-mode 'scalar))
+			(eq (car (nth 2 inst)) '*)
+			(consp (setq part (aref regs (car (cdr inst)))))
+			(eq (car part) '*)
+			(not (math-known-scalarp part)))
+		   (setq mark (nth 3 inst)
+			 pc (cdr pc))
+		   (if (aref mark 4)
+		       (progn
+			 (aset regs (nth 4 inst) (nth 2 part))
+			 (aset mark 1 (cdr (cdr part))))
+		     (aset regs (nth 4 inst) (nth 1 part))
+		     (aset mark 1 (cdr part)))
+		   (aset mark 0 (cdr part))
+		   (aset mark 2 0))
+		  
+		  ((eq op 'try)
+		   (if (and (consp (setq part (aref regs (car (cdr inst)))))
+			    (memq (car part) (nth 2 inst))
+			    (= (length part) 3)
+			    (or (not (eq (car part) '/))
+				(Math-objectp (nth 2 part))))
+		       (progn
+			 (setq op nil
+			       mark (car (cdr (setq inst (cdr (cdr inst))))))
+			 (and
+			  (memq 'assoc (get (car part) 'math-rewrite-props))
+			  (not (= (aref mark 3) 0))
+			  (while (if (and (consp (nth 1 part))
+					  (memq (car (nth 1 part)) (car inst)))
+				     (setq op (cons (if (eq (car part) '-)
+							(math-rwapply-neg
+							 (nth 2 part))
+						      (nth 2 part))
+						    op)
+					   part (nth 1 part))
+				   (if (and (consp (nth 2 part))
+					    (memq (car (nth 2 part))
+						  (car inst))
+					    (not (eq (car (nth 2 part)) '-)))
+				       (setq op (cons (nth 1 part) op)
+					     part (nth 2 part))))))
+			 (setq op (cons (nth 1 part)
+					(cons (if (eq (car part) '-)
+						  (math-rwapply-neg
+						   (nth 2 part))
+						(if (eq (car part) '/)
+						    (math-rwapply-inv
+						     (nth 2 part))
+						  (nth 2 part)))
+					      op))
+			       btrack (cons pc btrack)
+			       pc (cdr pc))
+			 (aset regs (nth 2 inst) (car op))
+			 (aset mark 0 op)
+			 (aset mark 1 op)
+			 (aset mark 2 (if (cdr (cdr op)) 1 0)))
+		     (if (nth 5 inst)
+			 (if (and (consp part)
+				  (eq (car part) 'neg)
+				  (eq (car (nth 2 inst)) '*)
+				  (eq (nth 5 inst) 1))
+			     (progn
+			       (setq mark (nth 3 inst)
+				     pc (cdr pc))
+			       (aset regs (nth 4 inst) (nth 1 part))
+			       (aset mark 1 -1)
+			       (aset mark 2 4))
+			   (setq mark (nth 3 inst)
+				 pc (cdr pc))
+			   (aset regs (nth 4 inst) part)
+			   (aset mark 2 3))
+		       (math-rwfail))))
+		  
+		  ((eq op 'try2)
+		   (setq part (nth 1 inst)   ; try instr
+			 mark (nth 3 part)
+			 op (aref mark 2)
+			 pc (cdr pc))
+		   (aset regs (nth 2 inst)
+			 (cond
+			  ((eq op 0)
+			   (if (eq (aref mark 0) (aref mark 1))
+			       (nth 1 (aref mark 0))
+			     (car (aref mark 0))))
+			  ((eq op 1)
+			   (setq mark (delq (car (aref mark 1))
+					    (copy-sequence (aref mark 0)))
+				 op (car (nth 2 part)))
+			   (if (eq op '*)
+			       (progn
+				 (setq mark (nreverse mark)
+				       part (list '* (nth 1 mark) (car mark))
+				       mark (cdr mark))
+				 (while (setq mark (cdr mark))
+				   (setq part (list '* (car mark) part))))
+			     (setq part (car mark)
+				   mark (cdr mark)
+				   part (if (and (eq op '+)
+						 (consp (car mark))
+						 (eq (car (car mark)) 'neg))
+					    (list '- part
+						  (nth 1 (car mark)))
+					  (list op part (car mark))))
+			     (while (setq mark (cdr mark))
+			       (setq part (if (and (eq op '+)
+						   (consp (car mark))
+						   (eq (car (car mark)) 'neg))
+					      (list '- part
+						    (nth 1 (car mark)))
+					    (list op part (car mark))))))
+			   part)
+			  ((eq op 2)
+			   (car (aref mark 1)))
+			  ((eq op 3) (nth 5 part))
+			  (t (aref mark 1)))))
+		  
+		  ((eq op 'select)
+		   (setq pc (cdr pc))
+		   (if (and (consp (setq part (aref regs (nth 1 inst))))
+			    (eq (car part) 'calcFunc-select))
+		       (aset regs (nth 2 inst) (nth 1 part))
+		     (if math-rewrite-selections
+			 (math-rwfail)
+		       (aset regs (nth 2 inst) part))))
+		  
+		  ((eq op 'same-neg)
+		   (if (or (equal (setq part (aref regs (nth 1 inst)))
+				  (setq mark (math-neg
+					      (aref regs (nth 2 inst)))))
+			   (Math-equal part mark))
+		       (setq pc (cdr pc))
+		     (math-rwfail)))
+		  
+		  ((eq op 'backtrack)
+		   (setq inst (car (car btrack))   ; "try" or "alt" instr
+			 pc (cdr (car btrack))
+			 mark (or (nth 3 inst) [nil nil 4])
+			 op (aref mark 2))
+		   (cond ((eq op 0)
+			  (if (setq op (cdr (aref mark 1)))
+			      (aset regs (nth 4 inst) (car (aset mark 1 op)))
+			    (if (nth 5 inst)
+				(progn
+				  (aset mark 2 3)
+				  (aset regs (nth 4 inst)
+					(aref regs (nth 1 inst))))
+			      (math-rwfail t))))
+			 ((eq op 1)
+			  (if (setq op (cdr (aref mark 1)))
+			      (aset regs (nth 4 inst) (car (aset mark 1 op)))
+			    (if (= (aref mark 3) 1)
+				(if (nth 5 inst)
+				    (progn
+				      (aset mark 2 3)
+				      (aset regs (nth 4 inst)
+					    (aref regs (nth 1 inst))))
+				  (math-rwfail t))
+			      (aset mark 2 2)
+			      (aset mark 1 (cons nil (aref mark 0)))
+			      (math-rwfail))))
+			 ((eq op 2)
+			  (if (setq op (cdr (aref mark 1)))
+			      (progn
+				(setq mark (delq (car (aset mark 1 op))
+						 (copy-sequence
+						  (aref mark 0)))
+				      op (car (nth 2 inst)))
+				(if (eq op '*)
+				    (progn
+				      (setq mark (nreverse mark)
+					    part (list '* (nth 1 mark)
+						       (car mark))
+					    mark (cdr mark))
+				      (while (setq mark (cdr mark))
+					(setq part (list '* (car mark)
+							 part))))
+				  (setq part (car mark)
+					mark (cdr mark)
+					part (if (and (eq op '+)
+						      (consp (car mark))
+						      (eq (car (car mark))
+							  'neg))
+						 (list '- part
+						       (nth 1 (car mark)))
+					       (list op part (car mark))))
+				  (while (setq mark (cdr mark))
+				    (setq part (if (and (eq op '+)
+							(consp (car mark))
+							(eq (car (car mark))
+							    'neg))
+						   (list '- part
+							 (nth 1 (car mark)))
+						 (list op part (car mark))))))
+				(aset regs (nth 4 inst) part))
+			    (if (nth 5 inst)
+				(progn
+				  (aset mark 2 3)
+				  (aset regs (nth 4 inst)
+					(aref regs (nth 1 inst))))
+			      (math-rwfail t))))
+			 ((eq op 4)
+			  (setq btrack (cdr btrack)))
+			 (t (math-rwfail t))))
+		  
+		  ((eq op 'integer)
+		   (if (Math-integerp (setq part (aref regs (nth 1 inst))))
+		       (setq pc (cdr pc))
+		     (if (Math-primp part)
+			 (math-rwfail)
+		       (setq part (math-rweval (math-simplify part)))
+		       (if (Math-integerp part)
+			   (setq pc (cdr pc))
+			 (math-rwfail)))))
+		  
+		  ((eq op 'real)
+		   (if (Math-realp (setq part (aref regs (nth 1 inst))))
+		       (setq pc (cdr pc))
+		     (if (Math-primp part)
+			 (math-rwfail)
+		       (setq part (math-rweval (math-simplify part)))
+		       (if (Math-realp part)
+			   (setq pc (cdr pc))
+			 (math-rwfail)))))
+		  
+		  ((eq op 'constant)
+		   (if (math-constp (setq part (aref regs (nth 1 inst))))
+		       (setq pc (cdr pc))
+		     (if (Math-primp part)
+			 (math-rwfail)
+		       (setq part (math-rweval (math-simplify part)))
+		       (if (math-constp part)
+			   (setq pc (cdr pc))
+			 (math-rwfail)))))
+		  
+		  ((eq op 'negative)
+		   (if (math-looks-negp (setq part (aref regs (nth 1 inst))))
+		       (setq pc (cdr pc))
+		     (if (Math-primp part)
+			 (math-rwfail)
+		       (setq part (math-rweval (math-simplify part)))
+		       (if (math-looks-negp part)
+			   (setq pc (cdr pc))
+			 (math-rwfail)))))
+		  
+		  ((eq op 'rel)
+		   (setq part (math-compare (aref regs (nth 1 inst))
+					    (aref regs (nth 3 inst)))
+			 op (nth 2 inst))
+		   (if (= part 2)
+		       (setq part (math-rweval
+				   (math-simplify
+				    (calcFunc-sign
+				     (math-sub (aref regs (nth 1 inst))
+					       (aref regs (nth 3 inst))))))))
+		   (if (cond ((eq op 'calcFunc-eq)
+			      (eq part 0))
+			     ((eq op 'calcFunc-neq)
+			      (memq part '(-1 1)))
+			     ((eq op 'calcFunc-lt)
+			      (eq part -1))
+			     ((eq op 'calcFunc-leq)
+			      (memq part '(-1 0)))
+			     ((eq op 'calcFunc-gt)
+			      (eq part 1))
+			     ((eq op 'calcFunc-geq)
+			      (memq part '(0 1))))
+		       (setq pc (cdr pc))
+		     (math-rwfail)))
+		  
+		  ((eq op 'func-def)
+		   (if (and (consp (setq part (aref regs (car (cdr inst)))))
+			    (eq (car part)
+				(car (setq inst (cdr (cdr inst))))))
+		       (progn
+			 (setq inst (cdr inst)
+			       mark (car inst))
+			 (while (and (setq inst (cdr inst)
+					   part (cdr part))
+				     inst)
+			   (aset regs (car inst) (car part)))
+			 (if (or inst part)
+			     (setq pc (cdr pc))
+			   (while (eq (car (car (setq pc (cdr pc))))
+				      'func-def))
+			   (setq pc (cdr pc))   ; skip over "func"
+			   (while mark
+			     (aset regs (cdr (car mark)) (car (car mark)))
+			     (setq mark (cdr mark)))))
+		     (math-rwfail)))
+
+		  ((eq op 'func-opt)
+		   (if (or (not (and (consp
+				      (setq part (aref regs (car (cdr inst)))))
+				     (eq (car part) (nth 2 inst))))
+			   (and (= (length part) 2)
+				(setq part (nth 1 part))))
+		       (progn
+			 (setq mark (nth 3 inst))
+			 (aset regs (nth 4 inst) part)
+			 (while (eq (car (car (setq pc (cdr pc)))) 'func-def))
+			 (setq pc (cdr pc))   ; skip over "func"
+			 (while mark
+			   (aset regs (cdr (car mark)) (car (car mark)))
+			   (setq mark (cdr mark))))
+		     (setq pc (cdr pc))))
+
+		  ((eq op 'mod)
+		   (if (if (Math-zerop (setq part (aref regs (nth 1 inst))))
+			   (Math-zerop (nth 3 inst))
+			 (and (not (Math-zerop (nth 2 inst)))
+			      (progn
+				(setq part (math-mod part (nth 2 inst)))
+				(or (Math-numberp part)
+				    (setq part (math-rweval
+						(math-simplify part))))
+				(Math-equal part (nth 3 inst)))))
+		       (setq pc (cdr pc))
+		     (math-rwfail)))
+
+		  ((eq op 'apply)
+		   (if (and (consp (setq part (aref regs (car (cdr inst)))))
+			    (not (Math-objvecp part))
+			    (not (eq (car part) 'var)))
+		       (progn
+			 (aset regs (nth 2 inst)
+			       (math-calcFunc-to-var (car part)))
+			 (aset regs (nth 3 inst)
+			       (cons 'vec (cdr part)))
+			 (setq pc (cdr pc)))
+		     (math-rwfail)))
+
+		  ((eq op 'cons)
+		   (if (and (consp (setq part (aref regs (car (cdr inst)))))
+			    (eq (car part) 'vec)
+			    (cdr part))
+		       (progn
+			 (aset regs (nth 2 inst) (nth 1 part))
+			 (aset regs (nth 3 inst) (cons 'vec (cdr (cdr part))))
+			 (setq pc (cdr pc)))
+		     (math-rwfail)))
+
+		  ((eq op 'rcons)
+		   (if (and (consp (setq part (aref regs (car (cdr inst)))))
+			    (eq (car part) 'vec)
+			    (cdr part))
+		       (progn
+			 (aset regs (nth 2 inst) (calcFunc-rhead part))
+			 (aset regs (nth 3 inst) (calcFunc-rtail part))
+			 (setq pc (cdr pc)))
+		     (math-rwfail)))
+
+		  ((eq op 'cond)
+		   (if (math-is-true
+			(math-rweval
+			 (math-simplify
+			  (math-rwapply-replace-regs (nth 1 inst)))))
+		       (setq pc (cdr pc))
+		     (math-rwfail)))
+		  
+		  ((eq op 'let)
+		   (aset regs (nth 1 inst)
+			 (math-rweval
+			  (math-normalize
+			   (math-rwapply-replace-regs (nth 2 inst)))))
+		   (setq pc (cdr pc)))
+		  
+		  ((eq op 'copy)
+		   (aset regs (nth 2 inst) (aref regs (nth 1 inst)))
+		   (setq pc (cdr pc)))
+		  
+		  ((eq op 'copy-neg)
+		   (aset regs (nth 2 inst)
+			 (math-rwapply-neg (aref regs (nth 1 inst))))
+		   (setq pc (cdr pc)))
+		  
+		  ((eq op 'alt)
+		   (setq btrack (cons pc btrack)
+			 pc (nth 1 inst)))
+		  
+		  ((eq op 'end-alt)
+		   (while (and btrack (not (eq (car btrack) (nth 1 inst))))
+		     (setq btrack (cdr btrack)))
+		   (setq btrack (cdr btrack)
+			 pc (cdr pc)))
+		  
+		  ((eq op 'done)
+		   (setq result (math-rwapply-replace-regs (nth 1 inst)))
+		   (if (or (and (eq (car-safe result) '+)
+				(eq (nth 2 result) 0))
+			   (and (eq (car-safe result) '*)
+				(eq (nth 2 result) 1)))
+		       (setq result (nth 1 result)))
+		   (setq part (and (nth 2 inst)
+				   (math-is-true
+				    (math-rweval
+				     (math-simplify
+				      (math-rwapply-replace-regs
+				       (nth 2 inst)))))))
+		   (if (or (equal result expr)
+			   (equal (setq result (math-normalize result)) expr))
+		       (setq result nil)
+		     (if part (math-rwapply-remember expr result))
+		     (setq rules nil))
+		   (setq pc nil))
+		  
+		  (t (error "%s is not a valid rewrite opcode" op))))))
+       (setq rules (cdr rules)))
+     result))
+)
+
+(defun math-rwapply-neg (expr)
+  (if (and (consp expr)
+	   (memq (car expr) '(* /)))
+      (if (Math-objectp (nth 2 expr))
+	  (list (car expr) (nth 1 expr) (math-neg (nth 2 expr)))
+	(list (car expr)
+	      (if (Math-objectp (nth 1 expr))
+		  (math-neg (nth 1 expr))
+		(list '* -1 (nth 1 expr)))
+	      (nth 2 expr)))
+    (math-neg expr))
+)
+
+(defun math-rwapply-inv (expr)
+  (if (and (Math-integerp expr)
+	   calc-prefer-frac)
+      (math-make-frac 1 expr)
+    (list '/ 1 expr))
+)
+
+(defun math-rwapply-replace-regs (expr)
+  (cond ((Math-primp expr)
+	 expr)
+	((eq (car expr) 'calcFunc-register)
+	 (setq expr (aref regs (nth 1 expr)))
+	 (if (eq (car-safe expr) '*)
+	     (if (eq (nth 1 expr) -1)
+		 (math-neg (nth 2 expr))
+	       (if (eq (nth 1 expr) 1)
+		   (nth 2 expr)
+		 expr))
+	   expr))
+	((and (eq (car expr) 'calcFunc-eval)
+	      (= (length expr) 2))
+	 (calc-with-default-simplification
+	  (math-normalize (math-rwapply-replace-regs (nth 1 expr)))))
+	((and (eq (car expr) 'calcFunc-evalsimp)
+	      (= (length expr) 2))
+	 (math-simplify (math-rwapply-replace-regs (nth 1 expr))))
+	((and (eq (car expr) 'calcFunc-evalextsimp)
+	      (= (length expr) 2))
+	 (math-simplify-extended (math-rwapply-replace-regs (nth 1 expr))))
+	((and (eq (car expr) 'calcFunc-apply)
+	      (= (length expr) 3))
+	 (let ((func (math-rwapply-replace-regs (nth 1 expr)))
+	       (args (math-rwapply-replace-regs (nth 2 expr)))
+	       call)
+	   (if (and (math-vectorp args)
+		    (not (eq (car-safe (setq call (math-build-call
+						   (math-var-to-calcFunc func)
+						   (cdr args))))
+			     'calcFunc-call)))
+	       call
+	     (list 'calcFunc-apply func args))))
+	((and (eq (car expr) 'calcFunc-cons)
+	      (= (length expr) 3))
+	 (let ((head (math-rwapply-replace-regs (nth 1 expr)))
+	       (tail (math-rwapply-replace-regs (nth 2 expr))))
+	   (if (math-vectorp tail)
+	       (cons 'vec (cons head (cdr tail)))
+	     (list 'calcFunc-cons head tail))))
+	((and (eq (car expr) 'calcFunc-rcons)
+	      (= (length expr) 3))
+	 (let ((head (math-rwapply-replace-regs (nth 1 expr)))
+	       (tail (math-rwapply-replace-regs (nth 2 expr))))
+	   (if (math-vectorp head)
+	       (append head (list tail))
+	     (list 'calcFunc-rcons head tail))))
+	((and (eq (car expr) 'neg)
+	      (math-rwapply-reg-looks-negp (nth 1 expr)))
+	 (math-rwapply-reg-neg (nth 1 expr)))
+	((and (eq (car expr) 'neg)
+	      (eq (car-safe (nth 1 expr)) 'calcFunc-register)
+	      (math-scalarp (aref regs (nth 1 (nth 1 expr)))))
+	 (math-neg (math-rwapply-replace-regs (nth 1 expr))))
+	((and (eq (car expr) '+)
+	      (math-rwapply-reg-looks-negp (nth 1 expr)))
+	 (list '- (math-rwapply-replace-regs (nth 2 expr))
+	       (math-rwapply-reg-neg (nth 1 expr))))
+	((and (eq (car expr) '+)
+	      (math-rwapply-reg-looks-negp (nth 2 expr)))
+	 (list '- (math-rwapply-replace-regs (nth 1 expr))
+	       (math-rwapply-reg-neg (nth 2 expr))))
+	((and (eq (car expr) '-)
+	      (math-rwapply-reg-looks-negp (nth 2 expr)))
+	 (list '+ (math-rwapply-replace-regs (nth 1 expr))
+	       (math-rwapply-reg-neg (nth 2 expr))))
+	((eq (car expr) '*)
+	 (cond ((eq (nth 1 expr) -1)
+		(if (math-rwapply-reg-looks-negp (nth 2 expr))
+		    (math-rwapply-reg-neg (nth 2 expr))
+		  (math-neg (math-rwapply-replace-regs (nth 2 expr)))))
+	       ((eq (nth 1 expr) 1)
+		(math-rwapply-replace-regs (nth 2 expr)))
+	       ((eq (nth 2 expr) -1)
+		(if (math-rwapply-reg-looks-negp (nth 1 expr))
+		    (math-rwapply-reg-neg (nth 1 expr))
+		  (math-neg (math-rwapply-replace-regs (nth 1 expr)))))
+	       ((eq (nth 2 expr) 1)
+		(math-rwapply-replace-regs (nth 1 expr)))
+	       (t
+		(let ((arg1 (math-rwapply-replace-regs (nth 1 expr)))
+		      (arg2 (math-rwapply-replace-regs (nth 2 expr))))
+		  (cond ((and (eq (car-safe arg1) '/)
+			      (eq (nth 1 arg1) 1))
+			 (list '/ arg2 (nth 2 arg1)))
+			((and (eq (car-safe arg2) '/)
+			      (eq (nth 1 arg2) 1))
+			 (list '/ arg1 (nth 2 arg2)))
+			(t (list '* arg1 arg2)))))))
+	((eq (car expr) '/)
+	 (let ((arg1 (math-rwapply-replace-regs (nth 1 expr)))
+	       (arg2 (math-rwapply-replace-regs (nth 2 expr))))
+	   (if (eq (car-safe arg2) '/)
+	       (list '/ (list '* arg1 (nth 2 arg2)) (nth 1 arg2))
+	     (list '/ arg1 arg2))))
+	((and (eq (car expr) 'calcFunc-plain)
+	      (= (length expr) 2))
+	 (if (Math-primp (nth 1 expr))
+	     (nth 1 expr)
+	   (if (eq (car (nth 1 expr)) 'calcFunc-register)
+	       (aref regs (nth 1 (nth 1 expr)))
+	     (cons (car (nth 1 expr)) (mapcar 'math-rwapply-replace-regs
+					      (cdr (nth 1 expr)))))))
+	(t (cons (car expr) (mapcar 'math-rwapply-replace-regs (cdr expr)))))
+)
+
+(defun math-rwapply-reg-looks-negp (expr)
+  (if (eq (car-safe expr) 'calcFunc-register)
+      (math-looks-negp (aref regs (nth 1 expr)))
+    (if (memq (car-safe expr) '(* /))
+	(or (math-rwapply-reg-looks-negp (nth 1 expr))
+	    (math-rwapply-reg-looks-negp (nth 2 expr)))))
+)
+
+(defun math-rwapply-reg-neg (expr)  ; expr must satisfy rwapply-reg-looks-negp
+  (if (eq (car expr) 'calcFunc-register)
+      (math-neg (math-rwapply-replace-regs expr))
+    (if (math-rwapply-reg-looks-negp (nth 1 expr))
+	(math-rwapply-replace-regs (list (car expr)
+					 (math-rwapply-reg-neg (nth 1 expr))
+					 (nth 2 expr)))
+      (math-rwapply-replace-regs (list (car expr)
+				       (nth 1 expr)
+				       (math-rwapply-reg-neg (nth 2 expr))))))
+)
+
+(defun math-rwapply-remember (old new)
+  (let ((varval (symbol-value (nth 2 (car ruleset))))
+	(rules (assq (car-safe old) ruleset)))
+    (if (and (eq (car-safe varval) 'vec)
+	     (not (memq (car-safe old) '(nil schedule + -)))
+	     rules)
+	(progn
+	  (setcdr varval (cons (list 'calcFunc-assign
+				     (if (math-rwcomp-no-vars old)
+					 old
+				       (list 'calcFunc-quote old))
+				     new)
+			       (cdr varval)))
+	  (setcdr rules (cons (list (vector nil old)
+				    (list (list 'same 0 1)
+					  (list 'done new nil))
+				    nil nil)
+			      (cdr rules))))))
+)
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/calc-rules.el	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,444 @@
+;; Calculator for GNU Emacs, part II [calc-rules.el]
+;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+;; Written by Dave Gillespie, daveg@synaptics.com.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY.  No author or distributor
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing.  Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License.   A copy of this license is
+;; supposed to have been given to you along with GNU Emacs so you
+;; can know your rights and responsibilities.  It should be in a
+;; file named COPYING.  Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+
+
+
+;; This file is autoloaded from calc-ext.el.
+(require 'calc-ext)
+
+(require 'calc-macs)
+
+(defun calc-Need-calc-rules () nil)
+
+
+(defun calc-compile-rule-set (name rules)
+  (prog2
+   (message "Preparing rule set %s..." name)
+   (math-read-plain-expr rules t)
+   (message "Preparing rule set %s...done" name))
+)
+
+(defun calc-CommuteRules ()
+  "CommuteRules"
+  (calc-compile-rule-set
+   "CommuteRules" "[
+iterations(1),
+select(plain(a + b))		:=  select(plain(b + a)),
+select(plain(a - b))		:=  select(plain((-b) + a)),
+select(plain((1/a) * b))	:=  select(b / a),
+select(plain(a * b))		:=  select(b * a),
+select((1/a) / b)		:=  select((1/b) / a),
+select(a / b)			:=  select((1/b) * a),
+select((a^b) ^ c)		:=  select((a^c) ^ b),
+select(log(a, b))		:=  select(1 / log(b, a)),
+select(plain(a && b))		:=  select(b && a),
+select(plain(a || b))		:=  select(b || a),
+select(plain(a = b))		:=  select(b = a),
+select(plain(a != b))		:=  select(b != a),
+select(a < b)			:=  select(b > a),
+select(a > b)			:=  select(b < a),
+select(a <= b)			:=  select(b >= a),
+select(a >= b)			:=  select(b <= a) ]")
+)
+
+(defun calc-JumpRules ()
+  "JumpRules"
+  (calc-compile-rule-set
+   "JumpRules" "[
+iterations(1),
+plain(select(x) = y)		:=  0 = select(-x) + y,
+plain(a + select(x) = y)	:=  a = select(-x) + y,
+plain(a - select(x) = y)	:=  a = select(x) + y,
+plain(select(x) + a = y)	:=  a = select(-x) + y,
+plain(a * select(x) = y)	:=  a = y / select(x),
+plain(a / select(x) = y)	:=  a = select(x) * y,
+plain(select(x) / a = y)	:=  1/a = y / select(x),
+plain(a ^ select(2) = y)	:=  a = select(sqrt(y)),
+plain(a ^ select(x) = y)	:=  a = y ^ select(1/x),
+plain(select(x) ^ a = y)	:=  a = log(y, select(x)),
+plain(log(a, select(x)) = y)	:=  a = select(x) ^ y,
+plain(log(select(x), a) = y)	:=  a = select(x) ^ (1/y),
+plain(y = select(x))		:=  y - select(x) = 0,
+plain(y = a + select(x))	:=  y - select(x) = a,
+plain(y = a - select(x))	:=  y + select(x) = a,
+plain(y = select(x) + a)	:=  y - select(x) = a,
+plain(y = a * select(x))	:=  y / select(x) = a,
+plain(y = a / select(x))	:=  y * select(x) = a,
+plain(y = select(x) / a)	:=  y / select(x) = 1/a,
+plain(y = a ^ select(2))	:=  select(sqrt(y)) = a,
+plain(y = a ^ select(x))	:=  y ^ select(1/x) = a,
+plain(y = select(x) ^ a)	:=  log(y, select(x)) = a,
+plain(y = log(a, select(x)))	:=  select(x) ^ y = a,
+plain(y = log(select(x), a))	:=  select(x) ^ (1/y) = a ]")
+)
+
+(defun calc-DistribRules ()
+  "DistribRules"
+  (calc-compile-rule-set
+   "DistribRules" "[
+iterations(1),
+x * select(a + b)		:=  x*select(a) + x*b,
+x * select(sum(a,b,c,d))	:=  sum(x*select(a),b,c,d),
+x / select(a + b)		:=  1 / (select(a)/x + b/x),
+select(a + b) / x		:=  select(a)/x + b/x,
+sum(select(a),b,c,d) / x	:=  sum(select(a)/x,b,c,d),
+x ^ select(a + b)		:=  x^select(a) * x^b,
+x ^ select(sum(a,b,c,d))	:=  prod(x^select(a),b,c,d),
+x ^ select(a * b)		:=  (x^a)^select(b),
+x ^ select(a / b)		:=  (x^a)^select(1/b),
+select(a + b) ^ n		:=  select(x)
+				    :: integer(n) :: n >= 2
+				    :: let(x, expandpow(a+b,n))
+				    :: quote(matches(x,y+z)),
+select(a + b) ^ x		:=  a*select(a+b)^(x-1) + b*select(a+b)^(x-1),
+select(a * b) ^ x		:=  a^x * select(b)^x,
+select(prod(a,b,c,d)) ^ x	:=  prod(select(a)^x,b,c,d),
+select(a / b) ^ x		:=  select(a)^x / b^x,
+select(- a) ^ x			:=  (-1)^x * select(a)^x,
+plain(-select(a + b))		:=  select(-a) - b,
+plain(-select(sum(a,b,c,d)))    :=  sum(select(-a),b,c,d),
+plain(-select(a * b))	        :=  select(-a) * b,
+plain(-select(a / b))	        :=  select(-a) / b,
+sqrt(select(a * b))		:=  sqrt(select(a)) * sqrt(b),
+sqrt(select(prod(a,b,c,d)))	:=  prod(sqrt(select(a)),b,c,d),
+sqrt(select(a / b))		:=  sqrt(select(a)) / sqrt(b),
+sqrt(select(- a))		:=  sqrt(-1) sqrt(select(a)),
+exp(select(a + b))		:=  exp(select(a)) / exp(-b) :: negative(b),
+exp(select(a + b))		:=  exp(select(a)) * exp(b),
+exp(select(sum(a,b,c,d)))	:=  prod(exp(select(a)),b,c,d),
+exp(select(a * b))		:=  exp(select(a)) ^ b :: constant(b),
+exp(select(a * b))		:=  exp(select(a)) ^ b,
+exp(select(a / b))		:=  exp(select(a)) ^ (1/b),
+ln(select(a * b))		:=  ln(select(a)) + ln(b),
+ln(select(prod(a,b,c,d)))	:=  sum(ln(select(a)),b,c,d),
+ln(select(a / b))		:=  ln(select(a)) - ln(b),
+ln(select(a ^ b))		:=  ln(select(a)) * b,
+log10(select(a * b))		:=  log10(select(a)) + log10(b),
+log10(select(prod(a,b,c,d)))	:=  sum(log10(select(a)),b,c,d),
+log10(select(a / b))		:=  log10(select(a)) - log10(b),
+log10(select(a ^ b))		:=  log10(select(a)) * b,
+log(select(a * b), x)		:=  log(select(a), x) + log(b,x),
+log(select(prod(a,b,c,d)),x)	:=  sum(log(select(a),x),b,c,d),
+log(select(a / b), x)		:=  log(select(a), x) - log(b,x),
+log(select(a ^ b), x)		:=  log(select(a), x) * b,
+log(a, select(b))		:=  ln(a) / select(ln(b)),
+sin(select(a + b))		:=  sin(select(a)) cos(b) + cos(a) sin(b),
+sin(select(2 a))		:=  2 sin(select(a)) cos(a),
+sin(select(n a))		:=  2sin((n-1) select(a)) cos(a) - sin((n-2) a)
+				    :: integer(n) :: n > 2,
+cos(select(a + b))		:=  cos(select(a)) cos(b) - sin(a) sin(b),
+cos(select(2 a))		:=  2 cos(select(a))^2 - 1,
+cos(select(n a))		:=  2cos((n-1) select(a)) cos(a) - cos((n-2) a)
+				    :: integer(n) :: n > 2,
+tan(select(a + b))		:=  (tan(select(a)) + tan(b)) /
+				    (1 - tan(a) tan(b)),
+tan(select(2 a))		:=  2 tan(select(a)) / (1 - tan(a)^2),
+tan(select(n a))		:=  (tan((n-1) select(a)) + tan(a)) /
+				    (1 - tan((n-1) a) tan(a))
+				    :: integer(n) :: n > 2,
+sinh(select(a + b))		:=  sinh(select(a)) cosh(b) + cosh(a) sinh(b),
+cosh(select(a + b))		:=  cosh(select(a)) cosh(b) + sinh(a) sinh(b),
+tanh(select(a + b))		:=  (tanh(select(a)) + tanh(b)) /
+				    (1 + tanh(a) tanh(b)),
+x && select(a || b)		:=  (x && select(a)) || (x && b),
+select(a || b) && x		:=  (select(a) && x) || (b && x),
+! select(a && b)		:=  (!a) || (!b),
+! select(a || b)		:=  (!a) && (!b) ]")
+)
+
+(defun calc-MergeRules ()
+  "MergeRules"
+  (calc-compile-rule-set
+   "MergeRules" "[
+iterations(1),
+ (x*opt(a)) + select(x*b)	:=  x * (a + select(b)),
+ (x*opt(a)) - select(x*b)	:=  x * (a - select(b)),
+sum(select(x)*a,b,c,d)		:=  x * sum(select(a),b,c,d),
+ (a/x) + select(b/x)		:=  (a + select(b)) / x,
+ (a/x) - select(b/x)		:=  (a - select(b)) / x,
+sum(a/select(x),b,c,d)		:=  sum(select(a),b,c,d) / x,
+ (a/opt(b)) + select(c/d)	:=  ((select(a)*d) + (b*c)) / (b*d),
+ (a/opt(b)) - select(c/d)	:=  ((select(a)*d) - (b*c)) / (b*d),
+ (x^opt(a)) * select(x^b)	:=  x ^ (a + select(b)),
+ (x^opt(a)) / select(x^b)	:=  x ^ (a - select(b)),
+select(x^a) / (x^opt(b))	:=  x ^ (select(a) - b),
+prod(select(x)^a,b,c,d)		:=  x ^ sum(select(a),b,c,d),
+select(x^a) / (x^opt(b))	:=  x ^ (select(a) - b),
+ (a^x) * select(b^x)		:=  select((a * b) ^x),
+ (a^x) / select(b^x)		:=  select((b / b) ^ x),
+select(a^x) / (b^x)		:=  select((a / b) ^ x),
+prod(a^select(x),b,c,d)		:=  select(prod(a,b,c,d) ^ x),
+ (a^x) * select(b^y)		:=  select((a * b^(y-x)) ^x),
+ (a^x) / select(b^y)		:=  select((b / b^(y-x)) ^ x),
+select(a^x) / (b^y)		:=  select((a / b^(y-x)) ^ x),
+select(x^a) ^ b			:=  x ^ select(a * b),
+ (x^a) ^ select(b)		:=  x ^ select(a * b),
+select(sqrt(a)) ^ b		:=  select(a ^ (b / 2)),
+sqrt(a) ^ select(b)		:=  select(a ^ (b / 2)),
+sqrt(select(a) ^ b)		:=  select(a ^ (b / 2)),
+sqrt(a ^ select(b))		:=  select(a ^ (b / 2)),
+sqrt(a) * select(sqrt(b))	:=  select(sqrt(a * b)),
+sqrt(a) / select(sqrt(b))	:=  select(sqrt(a / b)),
+select(sqrt(a)) / sqrt(b)	:=  select(sqrt(a / b)),
+prod(select(sqrt(a)),b,c,d)	:=  select(sqrt(prod(a,b,c,d))),
+exp(a) * select(exp(b))		:=  select(exp(a + b)),
+exp(a) / select(exp(b))		:=  select(exp(a - b)),
+select(exp(a)) / exp(b)		:=  select(exp(a - b)),
+prod(select(exp(a)),b,c,d)	:=  select(exp(sum(a,b,c,d))),
+select(exp(a)) ^ b		:=  select(exp(a * b)),
+exp(a) ^ select(b)		:=  select(exp(a * b)),
+ln(a) + select(ln(b))		:=  select(ln(a * b)),
+ln(a) - select(ln(b))		:=  select(ln(a / b)),
+select(ln(a)) - ln(b)		:=  select(ln(a / b)),
+sum(select(ln(a)),b,c,d)	:=  select(ln(prod(a,b,c,d))),
+b * select(ln(a))		:=  select(ln(a ^ b)),
+select(b) * ln(a)		:=  select(ln(a ^ b)),
+select(ln(a)) / ln(b)		:=  select(log(a, b)),
+ln(a) / select(ln(b))		:=  select(log(a, b)),
+select(ln(a)) / b		:=  select(ln(a ^ (1/b))),
+ln(a) / select(b)		:=  select(ln(a ^ (1/b))),
+log10(a) + select(log10(b))	:=  select(log10(a * b)),
+log10(a) - select(log10(b))	:=  select(log10(a / b)),
+select(log10(a)) - log10(b)	:=  select(log10(a / b)),
+sum(select(log10(a)),b,c,d)	:=  select(log10(prod(a,b,c,d))),
+b * select(log10(a))		:=  select(log10(a ^ b)),
+select(b) * log10(a)		:=  select(log10(a ^ b)),
+select(log10(a)) / log10(b)	:=  select(log(a, b)),
+log10(a) / select(log10(b))	:=  select(log(a, b)),
+select(log10(a)) / b		:=  select(log10(a ^ (1/b))),
+log10(a) / select(b)		:=  select(log10(a ^ (1/b))),
+log(a,x) + select(log(b,x))	:=  select(log(a * b,x)),
+log(a,x) - select(log(b,x))	:=  select(log(a / b,x)),
+select(log(a,x)) - log(b,x)	:=  select(log(a / b,x)),
+sum(select(log(a,x)),b,c,d)	:=  select(log(prod(a,b,c,d),x)),
+b * select(log(a,x))		:=  select(log(a ^ b,x)),
+select(b) * log(a,x)		:=  select(log(a ^ b,x)),
+select(log(a,x)) / log(b,x)	:=  select(log(a, b)),
+log(a,x) / select(log(b,x))	:=  select(log(a, b)),
+select(log(a,x)) / b		:=  select(log(a ^ (1/b),x)),
+log(a,x) / select(b)		:=  select(log(a ^ (1/b),x)),
+select(x && a) || (x && opt(b)) :=  x && (select(a) || b) ]")
+)
+
+(defun calc-NegateRules ()
+  "NegateRules"
+  (calc-compile-rule-set
+   "NegateRules" "[
+iterations(1),
+a + select(x)			:=  a - select(-x),
+a - select(x)			:=  a + select(-x),
+sum(select(x),b,c,d)		:=  -sum(select(-x),b,c,d),
+a * select(x)			:=  -a * select(-x),
+a / select(x)			:=  -a / select(-x),
+select(x) / a			:=  -select(-x) / a,
+prod(select(x),b,c,d)		:=  (-1)^(d-c+1) * prod(select(-x),b,c,d),
+select(x) ^ n			:=  select(-x) ^ a :: integer(n) :: n%2 = 0,
+select(x) ^ n			:=  -(select(-x) ^ a) :: integer(n) :: n%2 = 1,
+select(x) ^ a			:=  (-select(-x)) ^ a,
+a ^ select(x)			:=  (1 / a)^select(-x),
+abs(select(x))			:=  abs(select(-x)),
+i sqrt(select(x))		:=  -sqrt(select(-x)),
+sqrt(select(x))			:=  i sqrt(select(-x)),
+re(select(x))			:=  -re(select(-x)),
+im(select(x))			:=  -im(select(-x)),
+conj(select(x))			:=  -conj(select(-x)),
+trunc(select(x))		:=  -trunc(select(-x)),
+round(select(x))		:=  -round(select(-x)),
+floor(select(x))		:=  -ceil(select(-x)),
+ceil(select(x))			:=  -floor(select(-x)),
+ftrunc(select(x))		:=  -ftrunc(select(-x)),
+fround(select(x))		:=  -fround(select(-x)),
+ffloor(select(x))		:=  -fceil(select(-x)),
+fceil(select(x))		:=  -ffloor(select(-x)),
+exp(select(x))			:=  1 / exp(select(-x)),
+sin(select(x))			:=  -sin(select(-x)),
+cos(select(x))			:=  cos(select(-x)),
+tan(select(x))			:=  -tan(select(-x)),
+arcsin(select(x))		:=  -arcsin(select(-x)),
+arccos(select(x))		:=  4 arctan(1) - arccos(select(-x)),
+arctan(select(x))		:=  -arctan(select(-x)),
+sinh(select(x))			:=  -sinh(select(-x)),
+cosh(select(x))			:=  cosh(select(-x)),
+tanh(select(x))			:=  -tanh(select(-x)),
+arcsinh(select(x))		:=  -arcsinh(select(-x)),
+arctanh(select(x))		:=  -arctanh(select(-x)),
+select(x) = a			:=  select(-x) = -a,
+select(x) != a			:=  select(-x) != -a,
+select(x) < a			:=  select(-x) > -a,
+select(x) > a			:=  select(-x) < -a,
+select(x) <= a			:=  select(-x) >= -a,
+select(x) >= a			:=  select(-x) <= -a,
+a < select(x)			:=  -a > select(-x),
+a > select(x)			:=  -a < select(-x),
+a <= select(x)			:=  -a >= select(-x),
+a >= select(x)			:=  -a <= select(-x),
+select(x)			:=  -select(-x) ]")
+)
+
+(defun calc-InvertRules ()
+  "InvertRules"
+  (calc-compile-rule-set
+   "InvertRules" "[
+iterations(1),
+a * select(x)			:=  a / select(1/x),
+a / select(x)			:=  a * select(1/x),
+select(x) / a			:=  1 / (select(1/x) a),
+prod(select(x),b,c,d)		:=  1 / prod(select(1/x),b,c,d),
+abs(select(x))			:=  1 / abs(select(1/x)),
+sqrt(select(x))			:=  1 / sqrt(select(1/x)),
+ln(select(x))			:=  -ln(select(1/x)),
+log10(select(x))		:=  -log10(select(1/x)),
+log(select(x), a)		:=  -log(select(1/x), a),
+log(a, select(x))		:=  -log(a, select(1/x)),
+arctan(select(x))               :=  simplify(2 arctan(1))-arctan(select(1/x)),
+select(x) = a			:=  select(1/x) = 1/a,
+select(x) != a			:=  select(1/x) != 1/a,
+select(x) < a			:=  select(1/x) > 1/a,
+select(x) > a			:=  select(1/x) < 1/a,
+select(x) <= a			:=  select(1/x) >= 1/a,
+select(x) >= a			:=  select(1/x) <= 1/a,
+a < select(x)			:=  1/a > select(1/x),
+a > select(x)			:=  1/a < select(1/x),
+a <= select(x)			:=  1/a >= select(1/x),
+a >= select(x)			:=  1/a <= select(1/x),
+select(x)			:=  1 / select(1/x) ]")
+)
+
+
+(defun calc-FactorRules ()
+  "FactorRules"
+  (calc-compile-rule-set
+   "FactorRules" "[
+thecoefs(x, [z, a+b, c]) := thefactors(x, [d x + d a/c, (c/d) x + (b/d)])
+        :: z = a b/c :: let(d := pgcd(pcont(c), pcont(b))),
+thecoefs(x, [z, a, c]) := thefactors(x, [(r x + a/(2 r))^2])
+        :: z = (a/2)^2/c :: let(r := esimplify(sqrt(c)))
+        :: !matches(r, sqrt(rr)),
+thecoefs(x, [z, 0, c]) := thefactors(x, [rc x + rz, rc x - rz])
+        :: negative(z)
+        :: let(rz := esimplify(sqrt(-z))) :: !matches(rz, sqrt(rzz))
+        :: let(rc := esimplify(sqrt(c))) :: !matches(rc, sqrt(rcc)),
+thecoefs(x, [z, 0, c]) := thefactors(x, [rz + rc x, rz - rc x])
+        :: negative(c)
+        :: let(rz := esimplify(sqrt(z))) :: !matches(rz, sqrt(rzz))
+        :: let(rc := esimplify(sqrt(-c))) :: !matches(rc, sqrt(rcc))
+ ]")
+)
+;;(setq var-FactorRules 'calc-FactorRules)
+
+
+(defun calc-IntegAfterRules ()
+  "IntegAfterRules"
+  (calc-compile-rule-set
+   "IntegAfterRules" "[
+ opt(a) ln(x) + opt(b) ln(y) := 2 a esimplify(arctanh(x-1))
+     :: a + b = 0 :: nrat(x + y) = 2 || nrat(x - y) = 2,
+ a * (b + c) := a b + a c :: constant(a)
+ ]")
+)
+
+;;(setq var-IntegAfterRules 'calc-IntegAfterRules)
+
+
+(defun calc-FitRules ()
+  "FitRules"
+  (calc-compile-rule-set
+   "FitRules" "[
+
+schedule(1,2,3,4),
+iterations(inf),
+
+phase(1),
+e^x  		:=  exp(x),
+x^y		:=  exp(y ln(x))  :: !istrue(constant(y)),
+x/y		:=  x fitinv(y),
+fitinv(x y)	:=  fitinv(x) fitinv(y),
+exp(a) exp(b)	:=  exp(a + b),
+a exp(b)	:=  exp(ln(a) + b)  :: !hasfitvars(a),
+fitinv(exp(a))  :=  exp(-a),
+ln(a b)		:=  ln(a) + ln(b),
+ln(fitinv(a))	:=  -ln(a),
+log10(a b)	:=  log10(a) + log10(b),
+log10(fitinv(a)) := -log10(a),
+log(a,b)	:=  ln(a)/ln(b),
+ln(exp(a))	:=  a,
+a*(b+c)		:=  a*b + a*c,
+(a+b)^n		:=  x  :: integer(n) :: n >= 2
+		       :: let(x, expandpow(a+b,n))
+		       :: quote(matches(x,y+z)),
+
+phase(1,2),
+fitmodel(y = x)   :=  fitmodel(0, y - x),
+fitmodel(y, x+c)  :=  fitmodel(y-c, x)  :: !hasfitparams(c),
+fitmodel(y, x c)  :=  fitmodel(y/c, x)  :: !hasfitparams(c),
+fitmodel(y, x/(c opt(d)))  :=  fitmodel(y c, x/d)  :: !hasfitparams(c),
+fitmodel(y, apply(f,[x]))  :=  fitmodel(yy, x)
+			       :: hasfitparams(x)
+			       :: let(FTemp() = yy,
+			              solve(apply(f,[FTemp()]) = y,
+					    FTemp())),
+fitmodel(y, apply(f,[x,c]))  :=  fitmodel(yy, x)
+				 :: !hasfitparams(c)
+				 :: let(FTemp() = yy,
+				        solve(apply(f,[FTemp(),c]) = y,
+					      FTemp())),
+fitmodel(y, apply(f,[c,x]))  :=  fitmodel(yy, x)
+				 :: !hasfitparams(c)
+				 :: let(FTemp() = yy,
+				        solve(apply(f,[c,FTemp()]) = y,
+					      FTemp())),
+
+phase(2,3),
+fitmodel(y, x)              :=  fitsystem(y, [], [], fitpart(1,1,x)),
+fitpart(a,b,plain(x + y))   :=  fitpart(a,b,x) + fitpart(a,b,y),
+fitpart(a,b,plain(x - y))   :=  fitpart(a,b,x) + fitpart(-a,b,y),
+fitpart(a,b,plain(-x))	    :=  fitpart(-a,b,x),
+fitpart(a,b,x opt(c))	    :=  fitpart(a,x b,c)  :: !hasfitvars(x),
+fitpart(a,x opt(b),c)	    :=  fitpart(x a,b,c)  :: !hasfitparams(x),
+fitpart(a,x y + x opt(z),c) :=	fitpart(a,x*(y+z),c),
+fitpart(a,b,c)		    :=  fitpart2(a,b,c),
+
+phase(3),
+fitpart2(a1,b1,x) + fitpart2(a2,b2,x)  :=  fitpart(1, a1 b1 + a2 b2, x),
+fitpart2(a1,x,c1) + fitpart2(a2,x,c2)  :=  fitpart2(1, x, a1 c1 + a2 c2),
+
+phase(4),
+fitinv(x)  	:=  1 / x,
+exp(x + ln(y))  :=  y exp(x),
+exp(x ln(y))	:=  y^x,
+ln(x) + ln(y)	:=  ln(x y),
+ln(x) - ln(y)	:=  ln(x/y),
+x*y + x*z	:=  x*(y+z),
+fitsystem(y, xv, pv, fitpart2(a,fitparam(b),c) + opt(d))
+		:=  fitsystem(y, rcons(xv, a c),
+      		              rcons(pv, fitdummy(b) = fitparam(b)), d)
+		    :: b = vlen(pv)+1,
+fitsystem(y, xv, pv, fitpart2(a,b,c) + opt(d))
+		:=  fitsystem(y, rcons(xv, a c),
+			      rcons(pv, fitdummy(vlen(pv)+1) = b), d),
+fitsystem(y, xv, pv, 0)  :=  fitsystem(y, xv, cons(fvh,fvt))
+			     :: !hasfitparams(xv)
+			     :: let(cons(fvh,fvt),
+				    solve(pv, table(fitparam(j), j, 1,
+						    hasfitparams(pv)))),
+fitparam(n) = x  :=  x ]")
+)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/calc-sel.el	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,867 @@
+;; Calculator for GNU Emacs, part II [calc-sel.el]
+;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+;; Written by Dave Gillespie, daveg@synaptics.com.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY.  No author or distributor
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing.  Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License.   A copy of this license is
+;; supposed to have been given to you along with GNU Emacs so you
+;; can know your rights and responsibilities.  It should be in a
+;; file named COPYING.  Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+
+
+
+;; This file is autoloaded from calc-ext.el.
+(require 'calc-ext)
+
+(require 'calc-macs)
+
+(defun calc-Need-calc-sel () nil)
+
+
+;;; Selection commands.
+
+(defun calc-select-here (num &optional once keep)
+  (interactive "P")
+  (calc-wrapper
+   (calc-prepare-selection)
+   (let ((found (calc-find-selected-part))
+	 (entry calc-selection-cache-entry))
+     (or (and keep (nth 2 entry))
+	 (progn
+	   (if once (progn
+		      (setq calc-keep-selection nil)
+		      (message "(Selection will apply to next command only)")))
+	   (calc-change-current-selection 
+	    (if found
+		(if (and num (> (setq num (prefix-numeric-value num)) 0))
+		    (progn
+		      (while (and (>= (setq num (1- num)) 0)
+				  (not (eq found (car entry))))
+			(setq found (calc-find-assoc-parent-formula
+				     (car entry) found)))
+		      found)
+		  (calc-grow-assoc-formula (car entry) found))
+	      (car entry)))))))
+)
+
+(defun calc-select-once (num)
+  (interactive "P")
+  (calc-select-here num t)
+)
+
+(defun calc-select-here-maybe (num)
+  (interactive "P")
+  (calc-select-here num nil t)
+)
+
+(defun calc-select-once-maybe (num)
+  (interactive "P")
+  (calc-select-here num t t)
+)
+
+(defun calc-select-additional ()
+  (interactive)
+  (calc-wrapper
+   (let (calc-keep-selection)
+     (calc-prepare-selection))
+   (let ((found (calc-find-selected-part))
+	 (entry calc-selection-cache-entry))
+     (calc-change-current-selection
+      (if found
+	  (let ((sel (nth 2 entry)))
+	    (if sel
+		(progn
+		  (while (not (or (eq sel (car entry))
+				  (calc-find-sub-formula sel found)))
+		    (setq sel (calc-find-assoc-parent-formula
+			       (car entry) sel)))
+		  sel)
+	      (calc-grow-assoc-formula (car entry) found)))
+	(car entry)))))
+)
+
+(defun calc-select-more (num)
+  (interactive "P")
+  (calc-wrapper
+   (calc-prepare-selection)
+   (let ((entry calc-selection-cache-entry))
+     (if (nth 2 entry)
+	 (let ((sel (nth 2 entry)))
+	   (while (and (not (eq sel (car entry)))
+		       (>= (setq num (1- (prefix-numeric-value num))) 0))
+	     (setq sel (calc-find-assoc-parent-formula (car entry) sel)))
+	   (calc-change-current-selection sel))
+       (calc-select-here num))))
+)
+
+(defun calc-select-less (num)
+  (interactive "p")
+  (calc-wrapper
+   (calc-prepare-selection)
+   (let ((found (calc-find-selected-part))
+	 (entry calc-selection-cache-entry))
+     (calc-change-current-selection 
+      (and found
+	   (let ((sel (nth 2 entry))
+		 old index op)
+	     (while (and sel
+			 (not (eq sel found))
+			 (>= (setq num (1- num)) 0))
+	       (setq old sel
+		     index (calc-find-sub-formula sel found))
+	       (and (setq sel (and index (nth index old)))
+		    calc-assoc-selections
+		    (setq op (assq (car-safe sel) calc-assoc-ops))
+		    (memq (car old) (nth index op))
+		    (setq num (1+ num))))
+	     sel)))))
+)
+
+(defun calc-select-part (num)
+  (interactive "P")
+  (or num (setq num (- last-command-char ?0)))
+  (calc-wrapper
+   (calc-prepare-selection)
+   (let ((sel (calc-find-nth-part (or (nth 2 calc-selection-cache-entry)
+				      (car calc-selection-cache-entry))
+				  num)))
+     (if sel
+	 (calc-change-current-selection sel)
+       (error "%d is not a valid sub-formula index" num))))
+)
+
+(defun calc-find-nth-part (expr num)
+  (if (and calc-assoc-selections
+	   (assq (car-safe expr) calc-assoc-ops))
+      (let (op)
+	(calc-find-nth-part-rec expr))
+    (if (eq (car-safe expr) 'intv)
+	(and (>= num 1) (<= num 2) (nth (1+ num) expr))
+      (and (not (Math-primp expr)) (>= num 1) (< num (length expr))
+	   (nth num expr))))
+)
+
+(defun calc-find-nth-part-rec (expr)   ; uses num, op
+  (or (if (and (setq op (assq (car-safe (nth 1 expr)) calc-assoc-ops))
+	       (memq (car expr) (nth 1 op)))
+	  (calc-find-nth-part-rec (nth 1 expr))
+	(and (= (setq num (1- num)) 0)
+	     (nth 1 expr)))
+      (if (and (setq op (assq (car-safe (nth 2 expr)) calc-assoc-ops))
+	       (memq (car expr) (nth 2 op)))
+	  (calc-find-nth-part-rec (nth 2 expr))
+	(and (= (setq num (1- num)) 0)
+	     (nth 2 expr))))
+)
+
+(defun calc-select-next (num)
+  (interactive "p")
+  (if (< num 0)
+      (calc-select-previous (- num))
+    (calc-wrapper
+     (calc-prepare-selection)
+     (let* ((entry calc-selection-cache-entry)
+	    (sel (nth 2 entry)))
+       (if sel
+	   (progn
+	     (while (>= (setq num (1- num)) 0)
+	       (let* ((parent (calc-find-parent-formula (car entry) sel))
+		     (p parent)
+		     op)
+		 (and (eq p t) (setq p nil))
+		 (while (and (setq p (cdr p))
+			     (not (eq (car p) sel))))
+		 (if (cdr p)
+		     (setq sel (or (and calc-assoc-selections
+					(setq op (assq (car-safe (nth 1 p))
+						       calc-assoc-ops))
+					(memq (car parent) (nth 2 op))
+					(nth 1 (nth 1 p)))
+				   (nth 1 p)))
+		   (if (and calc-assoc-selections
+			    (setq op (assq (car-safe parent) calc-assoc-ops))
+			    (consp (setq p (calc-find-parent-formula
+					    (car entry) parent)))
+			    (eq (nth 1 p) parent)
+			    (memq (car p) (nth 1 op)))
+		       (setq sel (nth 2 p))
+		     (error "No \"next\" sub-formula")))))
+	     (calc-change-current-selection sel))
+	 (if (Math-primp (car entry))
+	     (calc-change-current-selection (car entry))
+	   (calc-select-part num))))))
+)
+
+(defun calc-select-previous (num)
+  (interactive "p")
+  (if (< num 0)
+      (calc-select-next (- num))
+    (calc-wrapper
+     (calc-prepare-selection)
+     (let* ((entry calc-selection-cache-entry)
+	    (sel (nth 2 entry)))
+       (if sel
+	   (progn
+	     (while (>= (setq num (1- num)) 0)
+	       (let* ((parent (calc-find-parent-formula (car entry) sel))
+		      (p (cdr-safe parent))
+		      (prev nil)
+		      op)
+		 (if (eq (car-safe parent) 'intv) (setq p (cdr p)))
+		 (while (and (not (eq (car p) sel))
+			     (setq prev (car p)
+				   p (cdr p))))
+		 (if prev
+		     (setq sel (or (and calc-assoc-selections
+					(setq op (assq (car-safe prev)
+						       calc-assoc-ops))
+					(memq (car parent) (nth 1 op))
+					(nth 2 prev))
+				   prev))
+		   (if (and calc-assoc-selections
+			    (setq op (assq (car-safe parent) calc-assoc-ops))
+			    (consp (setq p (calc-find-parent-formula
+					    (car entry) parent)))
+			    (eq (nth 2 p) parent)
+			    (memq (car p) (nth 2 op)))
+		       (setq sel (nth 1 p))
+		     (error "No \"previous\" sub-formula")))))
+	     (calc-change-current-selection sel))
+	 (if (Math-primp (car entry))
+	     (calc-change-current-selection (car entry))
+	   (let ((len (if (and calc-assoc-selections
+			       (assq (car (car entry)) calc-assoc-ops))
+			  (let (op (num 0))
+			    (calc-find-nth-part-rec (car entry))
+			    (- 1 num))
+			(length (car entry)))))
+	     (calc-select-part (- len num))))))))
+)
+
+(defun calc-find-parent-formula (expr part)
+  (cond ((eq expr part) t)
+	((Math-primp expr) nil)
+	(t
+	 (let ((p expr) res)
+	   (while (and (setq p (cdr p))
+		       (not (setq res (calc-find-parent-formula
+				       (car p) part)))))
+	   (and p
+		(if (eq res t) expr res)))))
+)
+
+
+(defun calc-find-assoc-parent-formula (expr part)
+  (calc-grow-assoc-formula expr (calc-find-parent-formula expr part))
+)
+
+(defun calc-grow-assoc-formula (expr part)
+  (if calc-assoc-selections
+      (let ((op (assq (car-safe part) calc-assoc-ops)))
+	(if op
+	    (let (new)
+	      (while (and (consp (setq new (calc-find-parent-formula
+					    expr part)))
+			  (memq (car new)
+				(nth (calc-find-sub-formula new part) op)))
+		(setq part new))))
+	part)
+    part)
+)
+
+(defun calc-find-sub-formula (expr part)
+  (cond ((eq expr part) t)
+	((Math-primp expr) nil)
+	(t
+	 (let ((num 1))
+	   (while (and (setq expr (cdr expr))
+		       (not (calc-find-sub-formula (car expr) part)))
+	     (setq num (1+ num)))
+	   (and expr num))))
+)
+
+(defun calc-unselect (num)
+  (interactive "P")
+  (calc-wrapper
+   (calc-prepare-selection num)
+   (calc-change-current-selection nil))
+)
+
+(defun calc-clear-selections ()
+  (interactive)
+  (calc-wrapper
+   (let ((limit (calc-stack-size))
+	 (n 1))
+     (while (<= n limit)
+       (if (calc-top n 'sel)
+	   (progn
+	     (calc-prepare-selection n)
+	     (calc-change-current-selection nil)))
+       (setq n (1+ n))))
+   (calc-clear-command-flag 'position-point))
+)
+
+(defun calc-show-selections (arg)
+  (interactive "P")
+  (calc-wrapper
+   (calc-preserve-point)
+   (setq calc-show-selections (if arg
+				  (> (prefix-numeric-value arg) 0)
+				(not calc-show-selections)))
+   (let ((p calc-stack))
+     (while (and p
+		 (or (null (nth 2 (car p)))
+		     (equal (car p) calc-selection-cache-entry)))
+       (setq p (cdr p)))
+     (or (and p
+	      (let ((calc-selection-cache-default-entry
+		     calc-selection-cache-entry))
+		(calc-do-refresh)))
+	 (and calc-selection-cache-entry
+	      (let ((sel (nth 2 calc-selection-cache-entry)))
+		(setcar (nthcdr 2 calc-selection-cache-entry) nil)
+		(calc-change-current-selection sel)))))
+   (message (if calc-show-selections
+		"Displaying only selected part of formulas"
+	      "Displaying all but selected part of formulas")))
+)
+
+(defun calc-preserve-point ()
+  (or (looking-at "\\.\n+\\'")
+      (progn
+	(setq calc-final-point-line (+ (count-lines (point-min) (point))
+				       (if (bolp) 1 0))
+	      calc-final-point-column (current-column))
+	(calc-set-command-flag 'position-point)))
+)
+
+(defun calc-enable-selections (arg)
+  (interactive "P")
+  (calc-wrapper
+   (calc-preserve-point)
+   (setq calc-use-selections (if arg
+				 (> (prefix-numeric-value arg) 0)
+			       (not calc-use-selections)))
+   (calc-set-command-flag 'renum-stack)
+   (message (if calc-use-selections
+		"Commands operate only on selected sub-formulas"
+	      "Selections of sub-formulas have no effect")))
+)
+
+(defun calc-break-selections (arg)
+  (interactive "P")
+  (calc-wrapper
+   (calc-preserve-point)
+   (setq calc-assoc-selections (if arg
+				   (<= (prefix-numeric-value arg) 0)
+				 (not calc-assoc-selections)))
+   (message (if calc-assoc-selections
+		"Selection treats a+b+c as a sum of three terms"
+	      "Selection treats a+b+c as (a+b)+c")))
+)
+
+(defun calc-prepare-selection (&optional num)
+  (or num (setq num (calc-locate-cursor-element (point))))
+  (setq calc-selection-true-num num
+	calc-keep-selection t)
+  (or (> num 0) (setq num 1))
+  ;; (if (or (< num 1) (> num (calc-stack-size)))
+  ;;     (error "Cursor must be positioned on a stack element"))
+  (let* ((entry (calc-top num 'entry))
+	 ww w)
+    (or (equal entry calc-selection-cache-entry)
+	(progn
+	  (setcar entry (calc-encase-atoms (car entry)))
+	  (setq calc-selection-cache-entry entry
+		calc-selection-cache-num num
+		calc-selection-cache-comp
+		(let ((math-comp-tagged t))
+		  (math-compose-expr (car entry) 0))
+		calc-selection-cache-offset
+		(+ (car (math-stack-value-offset calc-selection-cache-comp))
+		   (length calc-left-label)
+		   (if calc-line-numbering 4 0))))))
+  (calc-preserve-point)
+)
+(setq calc-selection-cache-entry nil)
+
+;;; The following ensures that no two subformulas will be "eq" to each other!
+(defun calc-encase-atoms (x)
+  (if (or (not (consp x))
+	  (equal x '(float 0 0)))
+      (list 'cplx x 0)
+    (calc-encase-atoms-rec x)
+    x)
+)
+
+(defun calc-encase-atoms-rec (x)
+  (or (Math-primp x)
+      (progn
+	(if (eq (car x) 'intv)
+	    (setq x (cdr x)))
+	(while (setq x (cdr x))
+	  (if (or (not (consp (car x)))
+		  (equal (car x) '(float 0 0)))
+	      (setcar x (list 'cplx (car x) 0))
+	    (calc-encase-atoms-rec (car x))))))
+)
+
+(defun calc-find-selected-part ()
+  (let* ((math-comp-sel-hpos (- (current-column) calc-selection-cache-offset))
+	 toppt
+	 (lcount 0)
+	 (spaces 0)
+	 (math-comp-sel-vpos (save-excursion
+			       (beginning-of-line)
+			       (let ((line (point)))
+				 (calc-cursor-stack-index
+				  calc-selection-cache-num)
+				 (setq toppt (point))
+				 (while (< (point) line)
+				   (forward-line 1)
+				   (setq spaces (+ spaces
+						   (current-indentation))
+					 lcount (1+ lcount)))
+				 (- lcount (math-comp-ascent
+					    calc-selection-cache-comp) -1))))
+	 (math-comp-sel-cpos (- (point) toppt calc-selection-cache-offset
+				spaces lcount))
+	 (math-comp-sel-tag nil))
+    (and (>= math-comp-sel-hpos 0)
+	 (> calc-selection-true-num 0)
+	 (math-composition-to-string calc-selection-cache-comp 1000000))
+    (nth 1 math-comp-sel-tag))
+)
+
+(defun calc-change-current-selection (sub-expr)
+  (or (eq sub-expr (nth 2 calc-selection-cache-entry))
+      (let ((calc-prepared-composition calc-selection-cache-comp)
+	    (buffer-read-only nil)
+	    top)
+	(calc-set-command-flag 'renum-stack)
+	(setcar (nthcdr 2 calc-selection-cache-entry) sub-expr)
+	(calc-cursor-stack-index calc-selection-cache-num)
+	(setq top (point))
+	(calc-cursor-stack-index (1- calc-selection-cache-num))
+	(delete-region top (point))
+	(let ((calc-selection-cache-default-entry calc-selection-cache-entry))
+	  (insert (math-format-stack-value calc-selection-cache-entry)
+		  "\n"))))
+)
+
+(defun calc-top-selected (&optional n m)
+  (and calc-any-selections
+       calc-use-selections
+       (progn
+	 (or n (setq n 1))
+	 (or m (setq m 1))
+	 (calc-check-stack (+ n m -1))
+	 (let ((top (nthcdr (+ m calc-stack-top -1) calc-stack))
+	       (sel nil))
+	   (while (>= (setq n (1- n)) 0)
+	     (if (nth 2 (car top))
+		 (setq sel (if sel t (nth 2 (car top)))))
+	     (setq top (cdr top)))
+	   sel)))
+)
+
+(defun calc-replace-sub-formula (expr old new)
+  (setq new (calc-encase-atoms new))
+  (calc-replace-sub-formula-rec expr)
+)
+
+(defun calc-replace-sub-formula-rec (expr)
+  (cond ((eq expr old) new)
+	((Math-primp expr) expr)
+	(t
+	 (cons (car expr)
+	       (mapcar 'calc-replace-sub-formula-rec (cdr expr)))))
+)
+
+(defun calc-sel-error ()
+  (error "Illegal operation on sub-formulas")
+)
+
+(defun calc-replace-selections (n vals m)
+  (if (calc-top-selected n m)
+      (let ((num (length vals)))
+	(calc-preserve-point)
+	(cond
+	 ((= n num)
+	  (let* ((old (calc-top-list n m 'entry))
+		 (new nil)
+		 (sel nil)
+		 val)
+	    (while old
+	      (if (nth 2 (car old))
+		  (setq val (calc-encase-atoms (car vals))
+			new (cons (calc-replace-sub-formula (car (car old))
+							    (nth 2 (car old))
+							    val)
+				  new)
+			sel (cons val sel))
+		(setq new (cons (car vals) new)
+		      sel (cons nil sel)))
+	      (setq vals (cdr vals)
+		    old (cdr old)))
+	    (calc-pop-stack n m t)
+	    (calc-push-list (nreverse new)
+			    m (and calc-keep-selection (nreverse sel)))))
+	 ((= num 1)
+	  (let* ((old (calc-top-list n m 'entry))
+		 more)
+	    (while (and old (not (nth 2 (car old))))
+	      (setq old (cdr old)))
+	    (setq more old)
+	    (while (and (setq more (cdr more)) (not (nth 2 (car more)))))
+	    (and more
+		 (calc-sel-error))
+	    (calc-pop-stack n m t)
+	    (if old
+		(let ((val (calc-encase-atoms (car vals))))
+		  (calc-push-list (list (calc-replace-sub-formula
+					 (car (car old))
+					 (nth 2 (car old))
+					 val))
+				  m (and calc-keep-selection (list val))))
+	      (calc-push-list vals))))
+	 (t (calc-sel-error))))
+    (calc-pop-stack n m t)
+    (calc-push-list vals m))
+)
+(setq calc-keep-selection t)
+
+(defun calc-delete-selection (n)
+  (let ((entry (calc-top n 'entry)))
+    (if (nth 2 entry)
+	(if (eq (nth 2 entry) (car entry))
+	    (progn
+	      (calc-pop-stack 1 n t)
+	      (calc-push-list '(0) n))
+	  (let ((parent (calc-find-parent-formula (car entry) (nth 2 entry)))
+		(repl nil))
+	    (calc-preserve-point)
+	    (calc-pop-stack 1 n t)
+	    (cond ((or (memq (car parent) '(* / %))
+		       (and (eq (car parent) '^)
+			    (eq (nth 2 parent) (nth 2 entry))))
+		   (setq repl 1))
+		  ((memq (car parent) '(vec calcFunc-min calcFunc-max)))
+		  ((and (assq (car parent) calc-tweak-eqn-table)
+			(= (length parent) 3))
+		   (setq repl 'del))
+		  (t
+		   (setq repl 0)))
+	    (cond
+	     ((eq repl 'del)
+	      (calc-push-list (list
+			       (calc-normalize
+				(calc-replace-sub-formula
+				 (car entry)
+				 parent
+				 (if (eq (nth 2 entry) (nth 1 parent))
+				     (nth 2 parent)
+				   (nth 1 parent)))))
+			      n))
+	     (repl
+	      (calc-push-list (list
+			       (calc-normalize
+				(calc-replace-sub-formula (car entry)
+							  (nth 2 entry)
+							  repl)))
+			      n))
+	     (t
+	      (calc-push-list (list
+			       (calc-normalize
+				(calc-replace-sub-formula (car entry)
+							  parent
+							  (delq (nth 2 entry)
+								(copy-sequence
+								 parent)))))
+			      n)))))
+      (calc-pop-stack 1 n t)))
+)
+
+(defun calc-roll-down-with-selections (n m)
+  (let ((vals (append (calc-top-list m 1)
+		      (calc-top-list (- n m) (1+ m))))
+	(sels (append (calc-top-list m 1 'sel)
+		      (calc-top-list (- n m) (1+ m) 'sel))))
+    (calc-pop-push-list n vals 1 sels))
+)
+
+(defun calc-roll-up-with-selections (n m)
+  (let ((vals (append (calc-top-list (- n m) 1)
+		      (calc-top-list m (- n m -1))))
+	(sels (append (calc-top-list (- n m) 1 'sel)
+		      (calc-top-list m (- n m -1) 'sel))))
+    (calc-pop-push-list n vals 1 sels))
+)
+
+(defun calc-auto-selection (entry)
+  (or (nth 2 entry)
+      (progn
+	(and (boundp 'reselect) (setq reselect nil))
+	(calc-prepare-selection)
+	(calc-grow-assoc-formula (car entry) (calc-find-selected-part))))
+)
+
+(defun calc-copy-selection ()
+  (interactive)
+  (calc-wrapper
+   (calc-preserve-point)
+   (let* ((num (max 1 (calc-locate-cursor-element (point))))
+	  (entry (calc-top num 'entry)))
+     (calc-push (or (calc-auto-selection entry) (car entry)))))
+)
+
+(defun calc-del-selection ()
+  (interactive)
+  (calc-wrapper
+   (calc-preserve-point)
+   (let* ((num (max 1 (calc-locate-cursor-element (point))))
+	  (entry (calc-top num 'entry))
+	  (sel (calc-auto-selection entry)))
+     (setcar (nthcdr 2 entry) (and (not (eq sel (car entry))) sel))
+     (calc-delete-selection num)))
+)
+
+(defun calc-enter-selection ()
+  (interactive)
+  (calc-wrapper
+   (calc-preserve-point)
+   (let* ((num (max 1 (calc-locate-cursor-element (point))))
+	  (reselect calc-keep-selection)
+	  (entry (calc-top num 'entry))
+	  (expr (car entry))
+	  (sel (or (calc-auto-selection entry) expr))
+	  alg)
+     (let ((calc-dollar-values (list sel))
+	   (calc-dollar-used 0))
+       (setq alg (calc-do-alg-entry "" "Replace selection with: "))
+       (and alg
+	    (progn
+	      (setq alg (calc-encase-atoms (car alg)))
+	      (calc-pop-push-record-list 1 "repl"
+					 (list (calc-replace-sub-formula
+						expr sel alg))
+					 num
+					 (list (and reselect alg))))))
+     (calc-handle-whys)))
+)
+
+(defun calc-edit-selection ()
+  (interactive)
+  (calc-wrapper
+   (calc-preserve-point)
+   (let* ((num (max 1 (calc-locate-cursor-element (point))))
+	  (reselect calc-keep-selection)
+	  (entry (calc-top num 'entry))
+	  (expr (car entry))
+	  (sel (or (calc-auto-selection entry) expr))
+	  alg)
+     (let ((str (math-showing-full-precision
+		 (math-format-nice-expr sel (screen-width)))))
+       (calc-edit-mode (list 'calc-finish-selection-edit
+			     num (list 'quote sel) reselect))
+       (insert str "\n"))))
+  (calc-show-edit-buffer)
+)
+
+(defun calc-finish-selection-edit (num sel reselect)
+  (let ((buf (current-buffer))
+	(str (buffer-substring (point) (point-max)))
+	(start (point)))
+    (switch-to-buffer calc-original-buffer)
+    (let ((val (math-read-expr str)))
+      (if (eq (car-safe val) 'error)
+	  (progn
+	    (switch-to-buffer buf)
+	    (goto-char (+ start (nth 1 val)))
+	    (error (nth 2 val))))
+      (calc-wrapper
+       (calc-preserve-point)
+       (if disp-trail
+	   (calc-trail-display 1 t))
+       (setq val (calc-encase-atoms (calc-normalize val)))
+       (let ((expr (calc-top num 'full)))
+	 (if (calc-find-sub-formula expr sel)
+	     (calc-pop-push-record-list 1 "edit"
+					(list (calc-replace-sub-formula
+					       expr sel val))
+					num
+					(list (and reselect val)))
+	   (calc-push val)
+	   (error "Original selection has been lost"))))))
+)
+
+(defun calc-sel-evaluate (arg)
+  (interactive "p")
+  (calc-slow-wrapper
+   (calc-preserve-point)
+   (let* ((num (max 1 (calc-locate-cursor-element (point))))
+	  (reselect calc-keep-selection)
+	  (entry (calc-top num 'entry))
+	  (sel (or (calc-auto-selection entry) (car entry))))
+     (calc-with-default-simplification
+      (let ((math-simplify-only nil))
+	(calc-modify-simplify-mode arg)
+	(let ((val (calc-encase-atoms (calc-normalize sel))))
+	  (calc-pop-push-record-list 1 "jsmp"
+				     (list (calc-replace-sub-formula
+					    (car entry) sel val))
+				     num
+				     (list (and reselect val))))))
+     (calc-handle-whys)))
+)
+
+(defun calc-sel-expand-formula (arg)
+  (interactive "p")
+  (calc-slow-wrapper
+   (calc-preserve-point)
+   (let* ((num (max 1 (calc-locate-cursor-element (point))))
+	  (reselect calc-keep-selection)
+	  (entry (calc-top num 'entry))
+	  (sel (or (calc-auto-selection entry) (car entry))))
+     (calc-with-default-simplification
+      (let ((math-simplify-only nil))
+	(calc-modify-simplify-mode arg)
+	(let* ((math-expand-formulas (> arg 0))
+	       (val (calc-normalize sel))
+	       top)
+	  (and (<= arg 0)
+	       (setq top (math-expand-formula val))
+	       (setq val (calc-normalize top)))
+	  (setq val (calc-encase-atoms val))
+	  (calc-pop-push-record-list 1 "jexf"
+				     (list (calc-replace-sub-formula
+					    (car entry) sel val))
+				     num
+				     (list (and reselect val))))))
+     (calc-handle-whys)))
+)
+
+(defun calc-sel-mult-both-sides (no-simp &optional divide)
+  (interactive "P")
+  (calc-wrapper
+   (calc-preserve-point)
+   (let* ((num (max 1 (calc-locate-cursor-element (point))))
+	  (reselect calc-keep-selection)
+	  (entry (calc-top num 'entry))
+	  (expr (car entry))
+	  (sel (or (calc-auto-selection entry) expr))
+	  (func (car-safe sel))
+	  alg lhs rhs)
+     (setq alg (calc-with-default-simplification
+		(car (calc-do-alg-entry ""
+					(if divide
+					    "Divide both sides by: "
+					  "Multiply both sides by: ")))))
+     (and alg
+	  (progn
+	    (if (and (or (eq func '/)
+			 (assq func calc-tweak-eqn-table))
+		     (= (length sel) 3))
+		(progn
+		  (or (memq func '(/ calcFunc-eq calcFunc-neq))
+		      (if (math-known-nonposp alg)
+			  (progn
+			    (setq func (nth 1 (assq func
+						    calc-tweak-eqn-table)))
+			    (or (math-known-negp alg)
+				(message "Assuming this factor is nonzero")))
+			(or (math-known-posp alg)
+			    (if (math-known-nonnegp alg)
+				(message "Assuming this factor is nonzero")
+			      (message "Assuming this factor is positive")))))
+		  (setq lhs (list (if divide '/ '*) (nth 1 sel) alg)
+			rhs (list (if divide '/ '*) (nth 2 sel) alg))
+		  (or no-simp
+		      (progn
+			(setq lhs (math-simplify lhs)
+			      rhs (math-simplify rhs))
+			(and (eq func '/)
+			     (or (Math-equal (nth 1 sel) 1)
+				 (Math-equal (nth 1 sel) -1)
+				 (and (memq (car-safe (nth 2 sel)) '(+ -))
+				      (memq (car-safe alg) '(+ -))))
+			     (setq rhs (math-expand-term rhs)))))
+		  (setq alg (calc-encase-atoms
+			     (calc-normalize (list func lhs rhs)))))
+	      (setq rhs (list (if divide '* '/) sel alg))
+	      (or no-simp
+		  (setq rhs (math-simplify rhs)))
+	      (setq alg (calc-encase-atoms
+			 (calc-normalize (if divide
+					     (list '/ rhs alg)
+					   (list '* alg rhs))))))
+	    (calc-pop-push-record-list 1 (if divide "div" "mult")
+				       (list (calc-replace-sub-formula
+					      expr sel alg))
+				       num
+				       (list (and reselect alg)))))
+     (calc-handle-whys)))
+)
+
+(defun calc-sel-div-both-sides (no-simp)
+  (interactive "P")
+  (calc-sel-mult-both-sides no-simp t)
+)
+
+(defun calc-sel-add-both-sides (no-simp &optional subtract)
+  (interactive "P")
+  (calc-wrapper
+   (calc-preserve-point)
+   (let* ((num (max 1 (calc-locate-cursor-element (point))))
+	  (reselect calc-keep-selection)
+	  (entry (calc-top num 'entry))
+	  (expr (car entry))
+	  (sel (or (calc-auto-selection entry) expr))
+	  (func (car-safe sel))
+	  alg lhs rhs)
+     (setq alg (calc-with-default-simplification
+		(car (calc-do-alg-entry ""
+					(if subtract
+					    "Subtract from both sides: "
+					  "Add to both sides: ")))))
+     (and alg
+	  (progn
+	    (if (and (assq func calc-tweak-eqn-table)
+		     (= (length sel) 3))
+		(progn
+		  (setq lhs (list (if subtract '- '+) (nth 1 sel) alg)
+			rhs (list (if subtract '- '+) (nth 2 sel) alg))
+		  (or no-simp
+		      (setq lhs (math-simplify lhs)
+			    rhs (math-simplify rhs)))
+		  (setq alg (calc-encase-atoms
+			     (calc-normalize (list func lhs rhs)))))
+	      (setq rhs (list (if subtract '+ '-) sel alg))
+	      (or no-simp
+		  (setq rhs (math-simplify rhs)))
+	      (setq alg (calc-encase-atoms
+			 (calc-normalize (list (if subtract '- '+) alg rhs)))))
+	    (calc-pop-push-record-list 1 (if subtract "sub" "add")
+				       (list (calc-replace-sub-formula
+					      expr sel alg))
+				       num
+				       (list (and reselect alg)))))
+     (calc-handle-whys)))
+)
+
+(defun calc-sel-sub-both-sides (no-simp)
+  (interactive "P")
+  (calc-sel-add-both-sides no-simp t)
+)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/calc-stat.el	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,629 @@
+;; Calculator for GNU Emacs, part II [calc-stat.el]
+;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+;; Written by Dave Gillespie, daveg@synaptics.com.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY.  No author or distributor
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing.  Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License.   A copy of this license is
+;; supposed to have been given to you along with GNU Emacs so you
+;; can know your rights and responsibilities.  It should be in a
+;; file named COPYING.  Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+
+
+
+;; This file is autoloaded from calc-ext.el.
+(require 'calc-ext)
+
+(require 'calc-macs)
+
+(defun calc-Need-calc-stat () nil)
+
+
+;;; Statistical operations on vectors.
+
+(defun calc-vector-count (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-vector-op "coun" 'calcFunc-vcount arg))
+)
+
+(defun calc-vector-sum (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (if (calc-is-hyperbolic)
+       (calc-vector-op "vprd" 'calcFunc-vprod arg)
+     (calc-vector-op "vsum" 'calcFunc-vsum arg)))
+)
+
+(defun calc-vector-product (arg)
+  (interactive "P")
+  (calc-hyperbolic-func)
+  (calc-vector-sum arg)
+)
+
+(defun calc-vector-max (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (if (calc-is-inverse)
+       (calc-vector-op "vmin" 'calcFunc-vmin arg)
+     (calc-vector-op "vmax" 'calcFunc-vmax arg)))
+)
+
+(defun calc-vector-min (arg)
+  (interactive "P")
+  (calc-invert-func)
+  (calc-vector-max arg)
+)
+
+(defun calc-vector-mean (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (if (calc-is-hyperbolic)
+       (if (calc-is-inverse)
+	   (calc-vector-op "harm" 'calcFunc-vhmean arg)
+	 (calc-vector-op "medn" 'calcFunc-vmedian arg))
+     (if (calc-is-inverse)
+	 (calc-vector-op "meae" 'calcFunc-vmeane arg)
+       (calc-vector-op "mean" 'calcFunc-vmean arg))))
+)
+
+(defun calc-vector-mean-error (arg)
+  (interactive "P")
+  (calc-invert-func)
+  (calc-vector-mean arg)
+)
+
+(defun calc-vector-median (arg)
+  (interactive "P")
+  (calc-hyperbolic-func)
+  (calc-vector-mean arg)
+)
+
+(defun calc-vector-harmonic-mean (arg)
+  (interactive "P")
+  (calc-invert-func)
+  (calc-hyperbolic-func)
+  (calc-vector-mean arg)
+)
+
+(defun calc-vector-geometric-mean (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (if (calc-is-hyperbolic)
+       (calc-binary-op "geom" 'calcFunc-agmean arg)
+     (calc-vector-op "geom" 'calcFunc-vgmean arg)))
+)
+
+(defun calc-vector-sdev (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (if (calc-is-hyperbolic)
+       (if (calc-is-inverse)
+	   (calc-vector-op "pvar" 'calcFunc-vpvar arg)
+	 (calc-vector-op "var" 'calcFunc-vvar arg))
+     (if (calc-is-inverse)
+	 (calc-vector-op "psdv" 'calcFunc-vpsdev arg)
+       (calc-vector-op "sdev" 'calcFunc-vsdev arg))))
+)
+
+(defun calc-vector-pop-sdev (arg)
+  (interactive "P")
+  (calc-invert-func)
+  (calc-vector-sdev arg)
+)
+
+(defun calc-vector-variance (arg)
+  (interactive "P")
+  (calc-hyperbolic-func)
+  (calc-vector-sdev arg)
+)
+
+(defun calc-vector-pop-variance (arg)
+  (interactive "P")
+  (calc-invert-func)
+  (calc-hyperbolic-func)
+  (calc-vector-sdev arg)
+)
+
+(defun calc-vector-covariance (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (let ((n (if (eq arg 1) 1 2)))
+     (if (calc-is-hyperbolic)
+	 (calc-enter-result n "corr" (cons 'calcFunc-vcorr
+					   (calc-top-list-n n)))
+       (if (calc-is-inverse)
+	   (calc-enter-result n "pcov" (cons 'calcFunc-vpcov
+					     (calc-top-list-n n)))
+	 (calc-enter-result n "cov" (cons 'calcFunc-vcov
+					  (calc-top-list-n n)))))))
+)
+
+(defun calc-vector-pop-covariance (arg)
+  (interactive "P")
+  (calc-invert-func)
+  (calc-vector-covariance arg)
+)
+
+(defun calc-vector-correlation (arg)
+  (interactive "P")
+  (calc-hyperbolic-func)
+  (calc-vector-covariance arg)
+)
+
+(defun calc-vector-op (name func arg)
+  (setq calc-aborted-prefix name
+	arg (prefix-numeric-value arg))
+  (if (< arg 0)
+      (error "Negative arguments not allowed"))
+  (calc-enter-result arg name (cons func (calc-top-list-n arg)))
+)
+
+
+
+
+;;; Useful statistical functions
+
+;;; Sum, product, etc., of one or more values or vectors.
+;;; Each argument must be either a number or a vector.  Vectors
+;;; are flattened, but variables inside are assumed to represent
+;;; non-vectors.
+
+(defun calcFunc-vsum (&rest vecs)
+  (math-reduce-many-vecs 'calcFunc-add 'calcFunc-vsum vecs 0)
+)
+
+(defun calcFunc-vprod (&rest vecs)
+  (math-reduce-many-vecs 'calcFunc-mul 'calcFunc-vprod vecs 1)
+)
+
+(defun calcFunc-vmax (&rest vecs)
+  (if (eq (car-safe (car vecs)) 'sdev)
+      '(var inf var-inf)
+    (if (eq (car-safe (car vecs)) 'intv)
+	(nth 3 (math-fix-int-intv (car vecs)))
+      (math-reduce-many-vecs 'calcFunc-max 'calcFunc-vmax vecs
+			     '(neg (var inf var-inf)))))
+)
+
+(defun calcFunc-vmin (&rest vecs)
+  (if (eq (car-safe (car vecs)) 'sdev)
+      '(neg (var inf var-inf))
+    (if (eq (car-safe (car vecs)) 'intv)
+	(nth 2 (math-fix-int-intv (car vecs)))
+      (math-reduce-many-vecs 'calcFunc-min 'calcFunc-vmin vecs
+			     '(var inf var-inf))))
+)
+
+(defun math-reduce-many-vecs (func whole-func vecs ident)
+  (let ((const-part nil)
+	(symb-part nil)
+	val vec)
+    (let ((calc-internal-prec (+ calc-internal-prec 2)))
+      (while vecs
+	(setq val (car vecs))
+	(and (eq (car-safe val) 'var)
+	     (eq (car-safe (calc-var-value (nth 2 val))) 'vec)
+	     (setq val (symbol-value (nth 2 val))))
+	(cond ((Math-vectorp val)
+	       (setq vec (append (and const-part (list const-part))
+				 (math-flatten-vector val)))
+	       (setq const-part (if vec
+				    (calcFunc-reducer
+				     (math-calcFunc-to-var func)
+				     (cons 'vec vec))
+				  ident)))
+	      ((or (Math-objectp val) (math-infinitep val))
+	       (setq const-part (if const-part
+				    (funcall func const-part val)
+				  val)))
+	      (t
+	       (setq symb-part (nconc symb-part (list val)))))
+	(setq vecs (cdr vecs))))
+    (if const-part
+	(progn
+	  (setq const-part (math-normalize const-part))
+	  (if symb-part
+	      (funcall func const-part (cons whole-func symb-part))
+	    const-part))
+      (if symb-part (cons whole-func symb-part) ident)))
+)
+
+
+;;; Return the number of data elements among the arguments.
+(defun calcFunc-vcount (&rest vecs)
+  (let ((count 0))
+    (while vecs
+      (setq count (if (Math-vectorp (car vecs))
+		      (+ count (math-count-elements (car vecs)))
+		    (if (Math-objectp (car vecs))
+			(1+ count)
+		      (if (and (eq (car-safe (car vecs)) 'var)
+			       (eq (car-safe (calc-var-value
+					      (nth 2 (car vecs))))
+				   'vec))
+			  (+ count (math-count-elements
+				    (symbol-value (nth 2 (car vecs)))))
+			(math-reject-arg (car vecs) 'numvecp))))
+	    vecs (cdr vecs)))
+    count)
+)
+
+(defun math-count-elements (vec)
+  (let ((count 0))
+    (while (setq vec (cdr vec))
+      (setq count (if (Math-vectorp (car vec))
+		      (+ count (math-count-elements (car vec)))
+		    (1+ count))))
+    count)
+)
+
+
+(defun math-flatten-many-vecs (vecs)
+  (let ((p vecs)
+	(vec (list 'vec)))
+    (while p
+      (setq vec (nconc vec
+		       (if (Math-vectorp (car p))
+			   (math-flatten-vector (car p))
+			 (if (Math-objectp (car p))
+			     (list (car p))
+			   (if (and (eq (car-safe (car p)) 'var)
+				    (eq (car-safe (calc-var-value
+						   (nth 2 (car p)))) 'vec))
+			       (math-flatten-vector (symbol-value
+						     (nth 2 (car p))))
+			     (math-reject-arg (car p) 'numvecp)))))
+	    p (cdr p)))
+    vec)
+)
+
+(defun calcFunc-vflat (&rest vecs)
+  (math-flatten-many-vecs vecs)
+)
+
+(defun math-split-sdev-vec (vec zero-ok)
+  (let ((means (list 'vec))
+	(wts (list 'vec))
+	(exact nil)
+	(p vec))
+    (while (and (setq p (cdr p))
+		(not (and (consp (car p))
+			  (eq (car (car p)) 'sdev)))))
+    (if (null p)
+	(list vec nil)
+      (while (setq vec (cdr vec))
+	(if (and (consp (setq p (car vec)))
+		 (eq (car p) 'sdev))
+	    (or exact
+		(setq means (cons (nth 1 p) means)
+		      wts (cons (nth 2 p) wts)))
+	  (if zero-ok
+	      (setq means (cons (nth 1 p) means)
+		    wts (cons 0 wts))
+	    (or exact
+		(setq means (list 'vec)
+		      wts nil
+		      exact t))
+	    (setq means (cons p means)))))
+      (list (nreverse means)
+	    (and wts (nreverse wts)))))
+)
+
+
+;;; Return the arithmetic mean of the argument numbers or vectors.
+;;; (If numbers are error forms, computes the weighted mean.)
+(defun calcFunc-vmean (&rest vecs)
+  (let* ((split (math-split-sdev-vec (math-flatten-many-vecs vecs) nil))
+	 (means (car split))
+	 (wts (nth 1 split))
+	 (len (1- (length means))))
+    (if (= len 0)
+	(math-reject-arg nil "*Must be at least 1 argument")
+      (if (and (= len 1) (eq (car-safe (nth 1 means)) 'intv))
+	  (let ((x (math-fix-int-intv (nth 1 means))))
+	    (calcFunc-vmean (nth 2 x) (nth 3 x)))
+	(math-with-extra-prec 2
+	  (if (and wts (> len 1))
+	      (let* ((sqrwts (calcFunc-map '(var mul var-mul) wts wts))
+		     (suminvsqrwts (calcFunc-reduce
+				    '(var add var-add)
+				    (calcFunc-map '(var div var-div)
+						  1 sqrwts))))
+		(math-div (calcFunc-reduce '(var add var-add)
+					   (calcFunc-map '(var div var-div)
+							 means sqrwts))
+			  suminvsqrwts))
+	    (math-div (calcFunc-reduce '(var add var-add) means) len))))))
+)
+
+(defun math-fix-int-intv (x)
+  (if (math-floatp x)
+      x
+    (list 'intv 3
+	  (if (memq (nth 1 x) '(2 3)) (nth 2 x) (math-add (nth 2 x) 1))
+	  (if (memq (nth 1 x) '(1 3)) (nth 3 x) (math-sub (nth 3 x) 1))))
+)
+
+;;; Compute the mean with an error estimate.
+(defun calcFunc-vmeane (&rest vecs)
+  (let* ((split (math-split-sdev-vec (math-flatten-many-vecs vecs) nil))
+	 (means (car split))
+	 (wts (nth 1 split))
+	 (len (1- (length means))))
+    (if (= len 0)
+	(math-reject-arg nil "*Must be at least 1 argument")
+      (math-with-extra-prec 2
+	(if wts
+	    (let* ((sqrwts (calcFunc-map '(var mul var-mul) wts wts))
+		   (suminvsqrwts (calcFunc-reduce
+				  '(var add var-add)
+				  (calcFunc-map '(var div var-div)
+						1 sqrwts))))
+	      (math-make-sdev
+	       (math-div (calcFunc-reduce '(var add var-add)
+					  (calcFunc-map '(var div var-div)
+							means sqrwts))
+			 suminvsqrwts)
+	       (list 'calcFunc-sqrt (math-div 1 suminvsqrwts))))
+	  (let ((mean (math-div (calcFunc-reduce '(var add var-add) means)
+				len)))
+	    (math-make-sdev
+	     mean
+	     (list 'calcFunc-sqrt
+		   (math-div (calcFunc-reducer
+			      '(var add var-add)
+			      (calcFunc-map '(var pow var-pow)
+					    (calcFunc-map '(var abs var-abs)
+							  (calcFunc-map
+							   '(var add var-add)
+							   means
+							   (math-neg mean)))
+					    2))
+			     (math-mul len (1- len))))))))))
+)
+
+
+;;; Compute the median of a list of values.
+(defun calcFunc-vmedian (&rest vecs)
+  (let* ((flat (copy-sequence (cdr (math-flatten-many-vecs vecs))))
+	 (p flat)
+	 (len (length flat))
+	 (hlen (/ len 2)))
+    (if (= len 0)
+	(math-reject-arg nil "*Must be at least 1 argument")
+      (if (and (= len 1) (memq (car-safe (car flat)) '(sdev intv)))
+	  (calcFunc-vmean (car flat))
+	(while p
+	  (if (eq (car-safe (car p)) 'sdev)
+	      (setcar p (nth 1 (car p))))
+	  (or (Math-anglep (car p))
+	      (math-reject-arg (car p) 'anglep))
+	  (setq p (cdr p)))
+	(setq flat (sort flat 'math-lessp))
+	(if (= (% len 2) 0)
+	    (math-div (math-add (nth (1- hlen) flat) (nth hlen flat)) 2)
+	  (nth hlen flat)))))
+)
+
+
+(defun calcFunc-vgmean (&rest vecs)
+  (let* ((flat (math-flatten-many-vecs vecs))
+	 (len (1- (length flat))))
+    (if (= len 0)
+	(math-reject-arg nil "*Must be at least 1 argument")
+      (math-with-extra-prec 2
+	(let ((x (calcFunc-reduce '(var mul math-mul) flat)))
+	  (if (= len 2)
+	      (math-sqrt x)
+	    (math-pow x (list 'frac 1 len)))))))
+)
+
+
+(defun calcFunc-agmean (a b)
+  (cond ((Math-equal a b) a)
+	((math-zerop a) a)
+	((math-zerop b) b)
+	(calc-symbolic-mode (math-inexact-result))
+	((not (Math-realp a)) (math-reject-arg a 'realp))
+	((not (Math-realp b)) (math-reject-arg b 'realp))
+	(t
+	 (math-with-extra-prec 2
+	   (setq a (math-float (math-abs a))
+		 b (math-float (math-abs b)))
+	   (let (mean)
+	     (while (not (math-nearly-equal-float a b))
+	       (setq mean (math-mul-float (math-add-float a b) '(float 5 -1))
+		     b (math-sqrt-float (math-mul-float a b))
+		     a mean))
+	     a))))
+)
+
+
+(defun calcFunc-vhmean (&rest vecs)
+  (let* ((flat (math-flatten-many-vecs vecs))
+	 (len (1- (length flat))))
+    (if (= len 0)
+	(math-reject-arg nil "*Must be at least 1 argument")
+      (math-with-extra-prec 2
+	(math-div len
+		  (calcFunc-reduce '(var add math-add)
+				   (calcFunc-map '(var inv var-inv) flat))))))
+)
+
+
+
+;;; Compute the sample variance or standard deviation of numbers or vectors.
+;;; (If the numbers are error forms, only the mean part of them is used.)
+(defun calcFunc-vvar (&rest vecs)
+  (if (and (= (length vecs) 1)
+	   (memq (car-safe (car vecs)) '(sdev intv)))
+      (if (eq (car-safe (car vecs)) 'intv)
+	  (math-intv-variance (car vecs) nil)
+	(math-sqr (nth 2 (car vecs))))
+    (math-covariance vecs nil nil 0))
+)
+
+(defun calcFunc-vsdev (&rest vecs)
+  (if (and (= (length vecs) 1)
+	   (memq (car-safe (car vecs)) '(sdev intv)))
+      (if (eq (car-safe (car vecs)) 'intv)
+	  (if (math-floatp (car vecs))
+	      (math-div (math-sub (nth 3 (car vecs)) (nth 2 (car vecs)))
+			(math-sqrt-12))
+	    (math-sqrt (calcFunc-vvar (car vecs))))
+	(nth 2 (car vecs)))
+    (math-sqrt (math-covariance vecs nil nil 0)))
+)
+
+;;; Compute the population variance or std deviation of numbers or vectors.
+(defun calcFunc-vpvar (&rest vecs)
+  (if (and (= (length vecs) 1)
+	   (memq (car-safe (car vecs)) '(sdev intv)))
+      (if (eq (car-safe (car vecs)) 'intv)
+	  (math-intv-variance (car vecs) t)
+	(math-sqr (nth 2 (car vecs))))
+    (math-covariance vecs nil t 0))
+)
+
+(defun calcFunc-vpsdev (&rest vecs)
+  (if (and (= (length vecs) 1)
+	   (memq (car-safe (car vecs)) '(sdev intv)))
+      (if (eq (car-safe (car vecs)) 'intv)
+	  (if (math-floatp (car vecs))
+	      (math-div (math-sub (nth 3 (car vecs)) (nth 2 (car vecs)))
+			(math-sqrt-12))
+	    (math-sqrt (calcFunc-vpvar (car vecs))))
+	(nth 2 (car vecs)))
+    (math-sqrt (math-covariance vecs nil t 0)))
+)
+
+(defun math-intv-variance (x pop)
+  (or (math-constp x) (math-reject-arg x 'constp))
+  (if (math-floatp x)
+      (math-div (math-sqr (math-sub (nth 3 x) (nth 2 x))) 12)
+    (let* ((x (math-fix-int-intv x))
+	   (len (math-sub (nth 3 x) (nth 2 x)))
+	   (hlen (math-quotient len 2)))
+      (math-div (if (math-evenp len)
+		    (calcFunc-sum '(^ (var X var-X) 2) '(var X var-X)
+				  (math-neg hlen) hlen)
+		  (calcFunc-sum '(^ (- (var X var-X) (/ 1 2)) 2)
+				'(var X var-X)
+				(math-neg hlen) (math-add hlen 1)))
+		(if pop (math-add len 1) len))))
+)
+
+;;; Compute the covariance and linear correlation coefficient.
+(defun calcFunc-vcov (vec1 &optional vec2)
+  (math-covariance (list vec1) (list vec2) nil 1)
+)
+
+(defun calcFunc-vpcov (vec1 &optional vec2)
+  (math-covariance (list vec1) (list vec2) t 1)
+)
+
+(defun calcFunc-vcorr (vec1 &optional vec2)
+  (math-covariance (list vec1) (list vec2) nil 2)
+)
+
+
+(defun math-covariance (vec1 vec2 pop mode)
+  (or (car vec2) (= mode 0)
+      (progn
+	(if (and (eq (car-safe (car vec1)) 'var)
+		 (eq (car-safe (calc-var-value (nth 2 (car vec1)))) 'vec))
+	    (setq vec1 (symbol-value (nth 2 (car vec1))))
+	  (setq vec1 (car vec1)))
+	(or (math-matrixp vec1) (math-dimension-error))
+	(or (= (length (nth 1 vec1)) 3) (math-dimension-error))
+	(setq vec2 (list (math-mat-col vec1 2))
+	      vec1 (list (math-mat-col vec1 1)))))
+  (math-with-extra-prec 2
+    (let* ((split1 (math-split-sdev-vec (math-flatten-many-vecs vec1) nil))
+	   (means1 (car split1))
+	   (wts1 (nth 1 split1))
+	   split2 means2 (wts2 nil)
+	   (sqrwts nil)
+	   suminvsqrwts
+	   (len (1- (length means1))))
+      (if (< len (if pop 1 2))
+	  (math-reject-arg nil (if pop
+				   "*Must be at least 1 argument"
+				 "*Must be at least 2 arguments")))
+      (if (or wts1 wts2)
+	  (setq sqrwts (math-add
+			(if wts1
+			    (calcFunc-map '(var mul var-mul) wts1 wts1)
+			  0)
+			(if wts2
+			    (calcFunc-map '(var mul var-mul) wts2 wts2)
+			  0))
+		suminvsqrwts (calcFunc-reduce
+			      '(var add var-add)
+			      (calcFunc-map '(var div var-div) 1 sqrwts))))
+      (or (= mode 0)
+	  (progn
+	    (setq split2 (math-split-sdev-vec (math-flatten-many-vecs vec2)
+					      nil)
+		  means2 (car split2)
+		  wts2 (nth 2 split1))
+	    (or (= len (1- (length means2))) (math-dimension-error))))
+      (let* ((diff1 (calcFunc-map
+		     '(var add var-add)
+		     means1
+		     (if sqrwts
+			 (math-div (calcFunc-reduce
+				    '(var add var-add)
+				    (calcFunc-map '(var div var-div)
+						  means1 sqrwts))
+				   (math-neg suminvsqrwts))
+		       (math-div (calcFunc-reducer '(var add var-add) means1)
+				 (- len)))))
+	     (diff2 (if (= mode 0)
+			diff1
+		      (calcFunc-map
+		       '(var add var-add)
+		       means2
+		       (if sqrwts
+			   (math-div (calcFunc-reduce
+				      '(var add var-add)
+				      (calcFunc-map '(var div var-div)
+						    means2 sqrwts))
+				     (math-neg suminvsqrwts))
+			 (math-div (calcFunc-reducer '(var add var-add) means2)
+				   (- len))))))
+	     (covar (calcFunc-map '(var mul var-mul) diff1 diff2)))
+	(if sqrwts
+	    (setq covar (calcFunc-map '(var div var-div) covar sqrwts)))
+	(math-div
+	 (calcFunc-reducer '(var add var-add) covar)
+	 (if (= mode 2)
+	     (let ((var1 (calcFunc-map '(var mul var-mul) diff1 diff1))
+		   (var2 (calcFunc-map '(var mul var-mul) diff2 diff2)))
+	       (if sqrwts
+		   (setq var1 (calcFunc-map '(var div var-div) var1 sqrwts)
+			 var2 (calcFunc-map '(var div var-div) var2 sqrwts)))
+	       (math-sqrt
+		(math-mul (calcFunc-reducer '(var add var-add) var1)
+			  (calcFunc-reducer '(var add var-add) var2))))
+	   (if sqrwts
+	       (if pop
+		   suminvsqrwts
+		 (math-div (math-mul suminvsqrwts (1- len)) len))
+	     (if pop len (1- len))))))))
+)
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/calc-store.el	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,663 @@
+;; Calculator for GNU Emacs, part II [calc-store.el]
+;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+;; Written by Dave Gillespie, daveg@synaptics.com.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY.  No author or distributor
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing.  Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License.   A copy of this license is
+;; supposed to have been given to you along with GNU Emacs so you
+;; can know your rights and responsibilities.  It should be in a
+;; file named COPYING.  Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+
+
+
+;; This file is autoloaded from calc-ext.el.
+(require 'calc-ext)
+
+(require 'calc-macs)
+
+(defun calc-Need-calc-store () nil)
+
+
+;;; Memory commands.
+
+(defun calc-store (&optional var)
+  (interactive)
+  (let ((calc-store-keep t))
+    (calc-store-into var))
+)
+(setq calc-store-keep nil)
+
+(defun calc-store-into (&optional var)
+  (interactive)
+  (calc-wrapper
+   (let ((calc-given-value nil)
+	 (calc-given-value-flag 1))
+     (or var (setq var (calc-read-var-name "Store: " t)))
+     (if var
+	 (let ((found (assq var '( ( + . calc-store-plus )
+				   ( - . calc-store-minus )
+				   ( * . calc-store-times )
+				   ( / . calc-store-div )
+				   ( ^ . calc-store-power )
+				   ( | . calc-store-concat ) ))))
+	   (if found
+	       (funcall (cdr found))
+	     (calc-store-value var (or calc-given-value (calc-top 1))
+			       "" calc-given-value-flag)
+	     (message "Stored to variable \"%s\"" (calc-var-name var))))
+       (setq var (calc-is-assignments (calc-top 1)))
+       (if var
+	   (while var
+	     (calc-store-value (car (car var)) (cdr (car var))
+			       (if (not (cdr var)) "")
+			       (if (not (cdr var)) 1))
+	     (setq var (cdr var)))))))
+)
+
+(defun calc-store-plus (&optional var)
+  (interactive)
+  (calc-store-binary var "+" '+)
+)
+
+(defun calc-store-minus (&optional var)
+  (interactive)
+  (calc-store-binary var "-" '-)
+)
+
+(defun calc-store-times (&optional var)
+  (interactive)
+  (calc-store-binary var "*" '*)
+)
+
+(defun calc-store-div (&optional var)
+  (interactive)
+  (calc-store-binary var "/" '/)
+)
+
+(defun calc-store-power (&optional var)
+  (interactive)
+  (calc-store-binary var "^" '^)
+)
+
+(defun calc-store-concat (&optional var)
+  (interactive)
+  (calc-store-binary var "|" '|)
+)
+
+(defun calc-store-neg (n &optional var)
+  (interactive "p")
+  (calc-store-binary var "n" '/ (- n))
+)
+
+(defun calc-store-inv (n &optional var)
+  (interactive "p")
+  (calc-store-binary var "&" '^ (- n))
+)
+
+(defun calc-store-incr (n &optional var)
+  (interactive "p")
+  (calc-store-binary var "n" '- (- n))
+)
+
+(defun calc-store-decr (n &optional var)
+  (interactive "p")
+  (calc-store-binary var "n" '- n)
+)
+
+(defun calc-store-value (var value tag &optional pop)
+  (if var
+      (let ((old (calc-var-value var)))
+	(set var value)
+	(if pop (or calc-store-keep (calc-pop-stack pop)))
+	(calc-record-undo (list 'store (symbol-name var) old))
+	(if tag
+	    (let ((calc-full-trail-vectors nil))
+	      (calc-record value (format ">%s%s" tag (calc-var-name var)))))
+	(and (memq var '(var-e var-i var-pi var-phi var-gamma))
+	     (eq (car-safe old) 'special-const)
+	     (message "(Note: Built-in definition of %s has been lost)" var))
+	(and (memq var '(var-inf var-uinf var-nan))
+	     (null old)
+	     (message "(Note: %s has built-in meanings which may interfere)"
+		      var))
+	(calc-refresh-evaltos var)))
+)
+
+(defun calc-var-name (var)
+  (if (symbolp var) (setq var (symbol-name var)))
+  (if (string-match "\\`var-." var)
+      (substring var 4)
+    var)
+)
+
+(defun calc-store-binary (var tag func &optional val)
+  (calc-wrapper
+   (let ((calc-simplify-mode (if (eq calc-simplify-mode 'none)
+				 'num calc-simplify-mode))
+	 (value (or val (calc-top 1))))
+     (or var (setq var (calc-read-var-name (format "Store %s: " tag))))
+     (if var
+	 (let ((old (calc-var-value var)))
+	   (or old
+	       (error "No such variable: \"%s\"" (calc-var-name var)))
+	   (if (stringp old)
+	       (setq old (math-read-expr old)))
+	   (if (eq (car-safe old) 'error)
+	       (error "Bad format in variable contents: %s" (nth 2 old)))
+	   (calc-store-value var
+			     (calc-normalize (if (calc-is-inverse)
+						 (list func value old)
+					       (list func old value)))
+			     tag (and (not val) 1))
+	   (message "Stored to variable \"%s\"" (calc-var-name var))))))
+)
+
+(defun calc-read-var-name (prompt &optional calc-store-opers)
+  (setq calc-given-value nil
+	calc-aborted-prefix nil)
+  (let ((var (let ((minibuffer-completion-table obarray)
+		   (minibuffer-completion-predicate 'boundp)
+		   (minibuffer-completion-confirm t))
+	       (read-from-minibuffer prompt "var-" calc-var-name-map nil))))
+    (setq calc-aborted-prefix "")
+    (and (not (equal var ""))
+	 (not (equal var "var-"))
+	 (if (string-match "\\`\\([-a-zA-Z0-9]+\\) *:?=" var)
+	     (if (null calc-given-value-flag)
+		 (error "Assignment is not allowed in this command")
+	       (let ((svar (intern (substring var 0 (match-end 1)))))
+		 (setq calc-given-value-flag 0
+		       calc-given-value (math-read-expr
+					 (substring var (match-end 0))))
+		 (if (eq (car-safe calc-given-value) 'error)
+		     (error "Bad format: %s" (nth 2 calc-given-value)))
+		 (setq calc-given-value (math-evaluate-expr calc-given-value))
+		 svar))
+	   (intern var))))
+)
+(setq calc-given-value-flag nil)
+
+(defvar calc-var-name-map nil "Keymap for reading Calc variable names.")
+(if calc-var-name-map
+    ()
+  (setq calc-var-name-map (copy-keymap minibuffer-local-completion-map))
+  (define-key calc-var-name-map " " 'self-insert-command)
+  (mapcar (function
+	   (lambda (x)
+	     (define-key calc-var-name-map (char-to-string x)
+	       'calcVar-digit)))
+	  "0123456789")
+  (mapcar (function
+	   (lambda (x)
+	     (define-key calc-var-name-map (char-to-string x)
+	       'calcVar-oper)))
+	  "+-*/^|")
+)
+
+(defun calcVar-digit ()
+  (interactive)
+  (if (calc-minibuffer-contains "var-\\'")
+      (if (eq calc-store-opers 0)
+	  (beep)
+	(insert "q")
+	(self-insert-and-exit))
+    (self-insert-command 1))
+)
+
+(defun calcVar-oper ()
+  (interactive)
+  (if (and (eq calc-store-opers t)
+	   (calc-minibuffer-contains "var-\\'"))
+      (progn
+	(erase-buffer)
+	(self-insert-and-exit))
+    (self-insert-command 1))
+)
+
+(defun calc-store-map (&optional oper var)
+  (interactive)
+  (calc-wrapper
+   (let* ((sel-mode nil)
+	  (calc-dollar-values (mapcar 'calc-get-stack-element
+				      (nthcdr calc-stack-top calc-stack)))
+	  (calc-dollar-used 0)
+	  (oper (or oper (calc-get-operator "Store Mapping")))
+	  (nargs (car oper)))
+     (or var (setq var (calc-read-var-name (format "Store Mapping %s: "
+						   (nth 2 oper)))))
+     (if var
+	 (let ((old (or (calc-var-value var)
+			(error "No such variable: \"%s\""
+			       (calc-var-name var))))
+	       (calc-simplify-mode (if (eq calc-simplify-mode 'none)
+				       'num calc-simplify-mode))
+	       (values (and (> nargs 1)
+			    (calc-top-list (1- nargs) (1+ calc-dollar-used)))))
+	   (message "Working...")
+	   (calc-set-command-flag 'clear-message)
+	   (if (stringp old)
+	       (setq old (math-read-expr old)))
+	   (if (eq (car-safe old) 'error)
+	       (error "Bad format in variable contents: %s" (nth 2 old)))
+	   (setq values (if (calc-is-inverse)
+			    (append values (list old))
+			  (append (list old) values)))
+	   (calc-store-value var
+			     (calc-normalize (cons (nth 1 oper) values))
+			     (nth 2 oper)
+			     (+ calc-dollar-used (1- nargs)))))))
+)
+
+(defun calc-store-exchange (&optional var)
+  (interactive)
+  (calc-wrapper
+   (let ((calc-given-value nil)
+	 (calc-given-value-flag 1)
+	 top)
+     (or var (setq var (calc-read-var-name "Exchange with: ")))
+     (if var
+	 (let ((value (calc-var-value var)))
+	   (or value
+	       (error "No such variable: \"%s\"" (calc-var-name var)))
+	   (if (eq (car-safe value) 'special-const)
+	       (error "%s is a special constant" var))
+	   (setq top (or calc-given-value (calc-top 1)))
+	   (calc-store-value var top nil)
+	   (calc-pop-push-record calc-given-value-flag
+				 (concat "<>" (calc-var-name var)) value)))))
+)
+
+(defun calc-unstore (&optional var)
+  (interactive)
+  (calc-wrapper
+   (or var (setq var (calc-read-var-name "Unstore: ")))
+   (if var
+       (progn
+	 (and (memq var '(var-e var-i var-pi var-phi var-gamma))
+	      (eq (car-safe (calc-var-value var)) 'special-const)
+	      (message "(Note: Built-in definition of %s has been lost)" var))
+	 (if (and (boundp var) (symbol-value var))
+	     (message "Unstored variable \"%s\"" (calc-var-name var))
+	   (message "Variable \"%s\" remains unstored" (calc-var-name var)))
+	 (makunbound var)
+	 (calc-refresh-evaltos var))))
+)
+
+(defun calc-let (&optional var)
+  (interactive)
+  (calc-wrapper
+   (let* ((calc-given-value nil)
+	  (calc-given-value-flag 1)
+	  thing value)
+     (or var (setq var (calc-read-var-name "Let variable: ")))
+     (if calc-given-value
+	 (setq value calc-given-value
+	       thing (calc-top 1))
+       (setq value (calc-top 1)
+	     thing (calc-top 2)))
+     (setq var (if var
+		   (list (cons var value))
+		 (calc-is-assignments value)))
+     (if var
+	 (calc-pop-push-record
+	  (1+ calc-given-value-flag)
+	  (concat "=" (calc-var-name (car (car var))))
+	  (let ((saved-val (mapcar (function
+				    (lambda (v)
+				      (and (boundp (car v))
+					   (symbol-value (car v)))))
+				   var)))
+	    (unwind-protect
+		(let ((vv var))
+		  (while vv
+		    (set (car (car vv)) (calc-normalize (cdr (car vv))))
+		    (calc-refresh-evaltos (car (car vv)))
+		    (setq vv (cdr vv)))
+		  (math-evaluate-expr thing))
+	      (while saved-val
+		(if (car saved-val)
+		    (set (car (car var)) (car saved-val))
+		  (makunbound (car (car var))))
+		(setq saved-val (cdr saved-val)
+		      var (cdr var)))
+	      (calc-handle-whys)))))))
+)
+
+(defun calc-is-assignments (value)
+  (if (memq (car-safe value) '(calcFunc-eq calcFunc-assign))
+      (and (eq (car-safe (nth 1 value)) 'var)
+	   (list (cons (nth 2 (nth 1 value)) (nth 2 value))))
+    (if (eq (car-safe value) 'vec)
+	(let ((vv nil))
+	  (while (and (setq value (cdr value))
+		      (memq (car-safe (car value))
+			    '(calcFunc-eq calcFunc-assign))
+		      (eq (car-safe (nth 1 (car value))) 'var))
+	    (setq vv (cons (cons (nth 2 (nth 1 (car value)))
+				 (nth 2 (car value)))
+			   vv)))
+	  (and (not value)
+	       vv))))
+)
+
+(defun calc-recall (&optional var)
+  (interactive)
+  (calc-wrapper
+   (or var (setq var (calc-read-var-name "Recall: ")))
+   (if var
+       (let ((value (calc-var-value var)))
+	 (or value
+	     (error "No such variable: \"%s\"" (calc-var-name var)))
+	 (if (stringp value)
+	     (setq value (math-read-expr value)))
+	 (if (eq (car-safe value) 'error)
+	     (error "Bad format in variable contents: %s" (nth 2 value)))
+	 (setq value (calc-normalize value))
+	 (let ((calc-full-trail-vectors nil))
+	   (calc-record value (concat "<" (calc-var-name var))))
+	 (calc-push value))))
+)
+
+(defun calc-store-quick ()
+  (interactive)
+  (calc-store (intern (format "var-q%c" last-command-char)))
+)
+
+(defun calc-store-into-quick ()
+  (interactive)
+  (calc-store-into (intern (format "var-q%c" last-command-char)))
+)
+
+(defun calc-recall-quick ()
+  (interactive)
+  (calc-recall (intern (format "var-q%c" last-command-char)))
+)
+
+(defun calc-copy-variable (&optional var1 var2)
+  (interactive)
+  (calc-wrapper
+   (or var1 (setq var1 (calc-read-var-name "Copy variable: ")))
+   (if var1
+       (let ((value (calc-var-value var1)))
+	 (or value
+	     (error "No such variable: \"%s\"" (calc-var-name var)))
+	 (or var2 (setq var2 (calc-read-var-name
+			      (format "Copy variable: %s, to: " var1))))
+	 (if var2
+	     (calc-store-value var2 value "")))))
+)
+
+(defun calc-edit-variable (&optional var)
+  (interactive)
+  (calc-wrapper
+   (or var (setq var (calc-read-var-name
+		      (if calc-last-edited-variable
+			  (format "Edit: (default %s) "
+				  (calc-var-name calc-last-edited-variable))
+			"Edit: "))))
+   (or var (setq var calc-last-edited-variable))
+   (if var
+       (let* ((value (calc-var-value var)))
+	 (if (eq (car-safe value) 'special-const)
+	     (error "%s is a special constant" var))
+	 (setq calc-last-edited-variable var)
+	 (calc-edit-mode (list 'calc-finish-stack-edit (list 'quote var))
+			 t
+			 (concat "Editing " (calc-var-name var)))
+	 (and value
+	      (insert (math-format-nice-expr value (screen-width)) "\n")))))
+  (calc-show-edit-buffer)
+)
+(setq calc-last-edited-variable nil)
+
+(defun calc-edit-Decls ()
+  (interactive)
+  (calc-edit-variable 'var-Decls)
+)
+
+(defun calc-edit-EvalRules ()
+  (interactive)
+  (calc-edit-variable 'var-EvalRules)
+)
+
+(defun calc-edit-FitRules ()
+  (interactive)
+  (calc-edit-variable 'var-FitRules)
+)
+
+(defun calc-edit-GenCount ()
+  (interactive)
+  (calc-edit-variable 'var-GenCount)
+)
+
+(defun calc-edit-Holidays ()
+  (interactive)
+  (calc-edit-variable 'var-Holidays)
+)
+
+(defun calc-edit-IntegLimit ()
+  (interactive)
+  (calc-edit-variable 'var-IntegLimit)
+)
+
+(defun calc-edit-LineStyles ()
+  (interactive)
+  (calc-edit-variable 'var-LineStyles)
+)
+
+(defun calc-edit-PointStyles ()
+  (interactive)
+  (calc-edit-variable 'var-PointStyles)
+)
+
+(defun calc-edit-PlotRejects ()
+  (interactive)
+  (calc-edit-variable 'var-PlotRejects)
+)
+
+(defun calc-edit-AlgSimpRules ()
+  (interactive)
+  (calc-edit-variable 'var-AlgSimpRules)
+)
+
+(defun calc-edit-TimeZone ()
+  (interactive)
+  (calc-edit-variable 'var-TimeZone)
+)
+
+(defun calc-edit-Units ()
+  (interactive)
+  (calc-edit-variable 'var-Units)
+)
+
+(defun calc-edit-ExtSimpRules ()
+  (interactive)
+  (calc-edit-variable 'var-ExtSimpRules)
+)
+
+(defun calc-declare-variable (&optional var)
+  (interactive)
+  (calc-wrapper
+   (or var (setq var (calc-read-var-name "Declare: " 0)))
+   (or var (setq var 'var-All))
+   (let* (dp decl def row rp)
+     (or (and (calc-var-value 'var-Decls)
+	      (eq (car-safe var-Decls) 'vec))
+	 (setq var-Decls (list 'vec)))
+     (setq dp var-Decls)
+     (while (and (setq dp (cdr dp))
+		 (or (not (eq (car-safe (car dp)) 'vec))
+		     (/= (length (car dp)) 3)
+		     (progn
+		       (setq row (nth 1 (car dp))
+			     rp row)
+		       (if (eq (car-safe row) 'vec)
+			   (progn
+			     (while
+				 (and (setq rp (cdr rp))
+				      (or (not (eq (car-safe (car rp)) 'var))
+					  (not (eq (nth 2 (car rp)) var)))))
+			     (setq rp (car rp)))
+			 (if (or (not (eq (car-safe row) 'var))
+				 (not (eq (nth 2 row) var)))
+			     (setq rp nil)))
+		       (not rp)))))
+     (calc-unread-command ?\C-a)
+     (setq decl (read-string (format "Declare: %s  to be: " var)
+			     (and rp
+				  (math-format-flat-expr (nth 2 (car dp)) 0))))
+     (setq decl (and (string-match "[^ \t]" decl)
+		     (math-read-exprs decl)))
+     (if (eq (car-safe decl) 'error)
+	 (error "Bad format in declaration: %s" (nth 2 decl)))
+     (if (cdr decl)
+	 (setq decl (cons 'vec decl))
+       (setq decl (car decl)))
+     (and (eq (car-safe decl) 'vec)
+	  (= (length decl) 2)
+	  (setq decl (nth 1 decl)))
+     (calc-record (append '(vec) (list (math-build-var-name var))
+			  (and decl (list decl)))
+		  "decl")
+     (setq var-Decls (copy-sequence var-Decls))
+     (if (eq (car-safe row) 'vec)
+	 (progn
+	   (setcdr row (delq rp (cdr row)))
+	   (or (cdr row)
+	       (setq var-Decls (delq (car dp) var-Decls))))
+       (setq var-Decls (delq (car dp) var-Decls)))
+     (if decl
+	 (progn
+	   (setq dp (and (not (eq var 'var-All)) var-Decls))
+	   (while (and (setq dp (cdr dp))
+		       (or (not (eq (car-safe (car dp)) 'vec))
+			   (/= (length (car dp)) 3)
+			   (not (equal (nth 2 (car dp)) decl)))))
+	   (if dp
+	       (setcar (cdr (car dp))
+		       (append (if (eq (car-safe (nth 1 (car dp))) 'vec)
+				   (nth 1 (car dp))
+				 (list 'vec (nth 1 (car dp))))
+			       (list (math-build-var-name var))))
+	     (setq var-Decls (append var-Decls
+				     (list (list 'vec
+						 (math-build-var-name var)
+						 decl)))))))
+     (calc-refresh-evaltos 'var-Decls)))
+)
+
+(defun calc-permanent-variable (&optional var)
+  (interactive)
+  (calc-wrapper
+   (or var (setq var (calc-read-var-name "Save variable (default=all): ")))
+   (let (pos)
+     (and var (or (and (boundp var) (symbol-value var))
+		  (error "No such variable")))
+     (set-buffer (find-file-noselect (substitute-in-file-name
+				      calc-settings-file)))
+     (if var
+	 (calc-insert-permanent-variable var)
+       (mapatoms (function
+		  (lambda (x)
+		    (and (string-match "\\`var-" (symbol-name x))
+			 (not (memq x calc-dont-insert-variables))
+			 (calc-var-value x)
+			 (not (eq (car-safe (symbol-value x)) 'special-const))
+			 (calc-insert-permanent-variable x))))))
+     (save-buffer)))
+)
+(defvar calc-dont-insert-variables '(var-FitRules var-FactorRules
+				     var-CommuteRules var-JumpRules
+				     var-DistribRules var-MergeRules
+				     var-NegateRules var-InvertRules
+				     var-IntegAfterRules
+				     var-TimeZone var-PlotRejects
+				     var-PlotData1 var-PlotData2
+				     var-PlotData3 var-PlotData4
+				     var-PlotData5 var-PlotData6
+				     var-DUMMY
+))
+
+(defun calc-insert-permanent-variable (var)
+  (goto-char (point-min))
+  (if (search-forward (concat "(setq " (symbol-name var) " '") nil t)
+      (progn
+	(setq pos (point-marker))
+	(forward-line -1)
+	(if (looking-at ";;; Variable .* stored by Calc on ")
+	    (progn
+	      (delete-region (match-end 0) (progn (end-of-line) (point)))
+	      (insert (current-time-string))))
+	(goto-char (- pos 8 (length (symbol-name var))))
+	(forward-sexp 1)
+	(backward-char 1)
+	(delete-region pos (point)))
+    (goto-char (point-max))
+    (insert "\n;;; Variable \""
+	    (symbol-name var)
+	    "\" stored by Calc on "
+	    (current-time-string)
+	    "\n(setq "
+	    (symbol-name var)
+	    " ')\n")
+    (backward-char 2))
+  (insert (prin1-to-string (calc-var-value var)))
+  (forward-line 1)
+)
+
+(defun calc-insert-variables (buf)
+  (interactive "bBuffer in which to save variable values: ")
+  (save-excursion
+    (set-buffer buf)
+    (mapatoms (function
+	       (lambda (x)
+		 (and (string-match "\\`var-" (symbol-name x))
+		      (not (memq x calc-dont-insert-variables))
+		      (calc-var-value x)
+		      (not (eq (car-safe (symbol-value x)) 'special-const))
+		      (or (not (eq x 'var-Decls))
+			  (not (equal var-Decls '(vec))))
+		      (or (not (eq x 'var-Holidays))
+			  (not (equal var-Holidays '(vec (var sat var-sat)
+							 (var sun var-sun)))))
+		      (insert "(setq "
+			      (symbol-name x)
+			      " "
+			      (prin1-to-string
+			       (let ((calc-language
+				      (if (memq calc-language '(nil big))
+					  'flat
+					calc-language)))
+				 (math-format-value (symbol-value x) 100000)))
+			      ")\n"))))))
+)
+
+(defun calc-assign (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-binary-op ":=" 'calcFunc-assign arg))
+)
+
+(defun calc-evalto (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-unary-op "=>" 'calcFunc-evalto arg))
+)
+
+(defun calc-subscript (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-binary-op "sub" 'calcFunc-subscr arg))
+)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/calc-stuff.el	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,300 @@
+;; Calculator for GNU Emacs, part II [calc-stuff.el]
+;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+;; Written by Dave Gillespie, daveg@synaptics.com.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY.  No author or distributor
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing.  Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License.   A copy of this license is
+;; supposed to have been given to you along with GNU Emacs so you
+;; can know your rights and responsibilities.  It should be in a
+;; file named COPYING.  Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+
+
+
+;; This file is autoloaded from calc-ext.el.
+(require 'calc-ext)
+
+(require 'calc-macs)
+
+(defun calc-Need-calc-stuff () nil)
+
+
+(defun calc-num-prefix (n)
+  "Use the number at the top of stack as the numeric prefix for the next command.
+With a prefix, push that prefix as a number onto the stack."
+  (interactive "P")
+  (calc-wrapper
+   (if n
+       (calc-enter-result 0 "" (prefix-numeric-value n))
+     (let ((num (calc-top 1)))
+       (if (math-messy-integerp num)
+	   (setq num (math-trunc num)))
+       (or (integerp num)
+	   (error "Argument must be a small integer"))
+       (calc-pop-stack 1)
+       (setq prefix-arg num)
+       (message "%d-" num))))    ; a (lame) simulation of the real thing...
+)
+
+
+(defun calc-more-recursion-depth (n)
+  (interactive "P")
+  (calc-wrapper
+   (if (calc-is-inverse)
+       (calc-less-recursion-depth n)
+     (let ((n (if n (prefix-numeric-value n) 2)))
+       (if (> n 1)
+	   (setq max-specpdl-size (* max-specpdl-size n)
+		 max-lisp-eval-depth (* max-lisp-eval-depth n))))
+     (message "max-lisp-eval-depth is now %d" max-lisp-eval-depth)))
+)
+
+(defun calc-less-recursion-depth (n)
+  (interactive "P")
+  (let ((n (if n (prefix-numeric-value n) 2)))
+    (if (> n 1)
+	(setq max-specpdl-size
+	      (max (/ max-specpdl-size n) 600)
+	      max-lisp-eval-depth
+	      (max (/ max-lisp-eval-depth n) 200))))
+  (message "max-lisp-eval-depth is now %d" max-lisp-eval-depth)
+)
+
+
+(defun calc-explain-why (why &optional more)
+  (if (eq (car why) '*)
+      (setq why (cdr why)))
+  (let* ((pred (car why))
+	 (arg (nth 1 why))
+	 (msg (cond ((not pred) "Wrong type of argument")
+		    ((stringp pred) pred)
+		    ((eq pred 'integerp) "Integer expected")
+		    ((eq pred 'natnump)
+		     (if (and arg (Math-objvecp arg) (not (Math-integerp arg)))
+			 "Integer expected"
+		       "Nonnegative integer expected"))
+		    ((eq pred 'posintp)
+		     (if (and arg (Math-objvecp arg) (not (Math-integerp arg)))
+			 "Integer expected"
+		       "Positive integer expected"))
+		    ((eq pred 'fixnump)
+		     (if (and arg (Math-integerp arg))
+			 "Small integer expected"
+		       "Integer expected"))
+		    ((eq pred 'fixnatnump)
+		     (if (and arg (Math-natnump arg))
+			 "Small integer expected"
+		       (if (and arg (Math-objvecp arg)
+				(not (Math-integerp arg)))
+			   "Integer expected"
+			 "Nonnegative integer expected")))
+		    ((eq pred 'fixposintp)
+		     (if (and arg (Math-integerp arg) (Math-posp arg))
+			 "Small integer expected"
+		       (if (and arg (Math-objvecp arg)
+				(not (Math-integerp arg)))
+			   "Integer expected"
+			 "Positive integer expected")))
+		    ((eq pred 'posp) "Positive number expected")
+		    ((eq pred 'negp) "Negative number expected")
+		    ((eq pred 'nonzerop) "Nonzero number expected")
+		    ((eq pred 'realp) "Real number expected")
+		    ((eq pred 'anglep) "Real number expected")
+		    ((eq pred 'hmsp) "HMS form expected")
+		    ((eq pred 'datep)
+		     (if (and arg (Math-objectp arg)
+			      (not (Math-realp arg)))
+			 "Real number or date form expected"
+		       "Date form expected"))
+		    ((eq pred 'numberp) "Number expected")
+		    ((eq pred 'scalarp) "Number expected")
+		    ((eq pred 'vectorp) "Vector or matrix expected")
+		    ((eq pred 'numvecp) "Number or vector expected")
+		    ((eq pred 'matrixp) "Matrix expected")
+		    ((eq pred 'square-matrixp)
+		     (if (and arg (math-matrixp arg))
+			 "Square matrix expected"
+		       "Matrix expected"))
+		    ((eq pred 'objectp) "Number expected")
+		    ((eq pred 'constp) "Constant expected")
+		    ((eq pred 'range) "Argument out of range")
+		    (t (format "%s expected" pred))))
+	 (punc ": ")
+	 (calc-can-abbrev-vectors t))
+    (while (setq why (cdr why))
+      (and (car why)
+	   (setq msg (concat msg punc (if (stringp (car why))
+					  (car why)
+					(math-format-flat-expr (car why) 0)))
+		 punc ", ")))
+    (message "%s%s" msg (if more "  [w=more]" "")))
+)
+
+(defun calc-why ()
+  (interactive)
+  (if (not (eq this-command last-command))
+      (if (eq last-command calc-last-why-command)
+	  (setq calc-which-why (cdr calc-why))
+	(setq calc-which-why calc-why)))
+  (if calc-which-why
+      (progn
+	(calc-explain-why (car calc-which-why) (cdr calc-which-why))
+	(setq calc-which-why (cdr calc-which-why)))
+    (if calc-why
+	(progn
+	  (message "(No further explanations available)")
+	  (setq calc-which-why calc-why))
+      (message "No explanations available")))
+)
+(setq calc-which-why nil)
+(setq calc-last-why-command nil)
+
+
+(defun calc-version ()
+  (interactive)
+  (message "Calc %s, installed %s" calc-version calc-installed-date))
+
+
+(defun calc-flush-caches ()
+  (interactive)
+  (calc-wrapper
+   (setq math-lud-cache nil
+	 math-log2-cache nil
+	 math-radix-digits-cache nil
+	 math-radix-float-cache-tag nil
+	 math-random-cache nil
+	 math-max-digits-cache nil
+	 math-checked-rewrites nil
+	 math-integral-cache nil
+	 math-units-table nil
+	 math-decls-cache-tag nil
+	 math-eval-rules-cache-tag t
+	 math-graph-var-cache nil
+	 math-graph-data-cache nil
+	 math-format-date-cache nil
+	 math-holidays-cache-tag t)
+   (mapcar (function (lambda (x) (set x -100))) math-cache-list)
+   (message "All internal calculator caches have been reset."))
+)
+
+
+;;; Conversions.
+
+(defun calc-clean (n)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-with-default-simplification
+    (let ((func (if (calc-is-hyperbolic) 'calcFunc-clean 'calcFunc-pclean)))
+      (calc-enter-result 1 "cln"
+			 (if n
+			     (let ((n (prefix-numeric-value n)))
+			       (list func
+				     (calc-top-n 1)
+				     (if (<= n 0)
+					 (+ n calc-internal-prec)
+				       n)))
+			   (list func (calc-top-n 1)))))))
+)
+
+(defun calc-clean-num (num)
+  (interactive "P")
+  (calc-clean (- (if num
+		     (prefix-numeric-value num) 
+		   (if (and (>= last-command-char ?0)
+			    (<= last-command-char ?9))
+		       (- last-command-char ?0)
+		     (error "Number required")))))
+)
+
+
+(defun calcFunc-clean (a &optional prec)   ; [X X S] [Public]
+  (if prec
+      (cond ((Math-messy-integerp prec)
+	     (calcFunc-clean a (math-trunc prec)))
+	    ((or (not (integerp prec))
+		 (< prec 3))
+	     (calc-record-why "*Precision must be an integer 3 or above")
+	     (list 'calcFunc-clean a prec))
+	    ((not (Math-objvecp a))
+	     (list 'calcFunc-clean a prec))
+	    (t (let ((calc-internal-prec prec)
+		     (math-chopping-small t))
+		 (calcFunc-clean (math-normalize a)))))
+    (cond ((eq (car-safe a) 'polar)
+	   (let ((theta (math-mod (nth 2 a)
+				  (if (eq calc-angle-mode 'rad)
+				      (math-two-pi)
+				    360))))
+	     (math-neg
+	      (math-neg
+	       (math-normalize
+		(list 'polar
+		      (calcFunc-clean (nth 1 a))
+		      (calcFunc-clean theta)))))))
+	  ((memq (car-safe a) '(vec date hms))
+	   (cons (car a) (mapcar 'calcFunc-clean (cdr a))))
+	  ((memq (car-safe a) '(cplx mod sdev intv))
+	   (math-normalize (cons (car a) (mapcar 'calcFunc-clean (cdr a)))))
+	  ((eq (car-safe a) 'float)
+	   (if math-chopping-small
+	       (if (or (> (nth 2 a) (- calc-internal-prec))
+		       (Math-lessp (- calc-internal-prec) (calcFunc-xpon a)))
+		   (if (and (math-num-integerp a)
+			    (math-lessp (calcFunc-xpon a) calc-internal-prec))
+		       (math-trunc a)
+		     a)
+		 0)
+	     a))
+	  ((Math-objectp a) a)
+	  ((math-infinitep a) a)
+	  (t (list 'calcFunc-clean a))))
+)
+(setq math-chopping-small nil)
+
+(defun calcFunc-pclean (a &optional prec)
+  (math-map-over-constants (function (lambda (x) (calcFunc-clean x prec)))
+			   a)
+)
+
+(defun calcFunc-pfloat (a)
+  (math-map-over-constants 'math-float a)
+)
+
+(defun calcFunc-pfrac (a &optional tol)
+  (math-map-over-constants (function (lambda (x) (calcFunc-frac x tol)))
+			   a)
+)
+
+(defun math-map-over-constants (func expr)
+  (math-map-over-constants-rec expr)
+)
+
+(defun math-map-over-constants-rec (expr)
+  (cond ((or (Math-primp expr)
+	     (memq (car expr) '(intv sdev)))
+	 (or (and (Math-objectp expr)
+		  (funcall func expr))
+	     expr))
+	((and (memq (car expr) '(^ calcFunc-subscr))
+	      (eq func 'math-float)
+	      (= (length expr) 3)
+	      (Math-integerp (nth 2 expr)))
+	 (list (car expr)
+	       (math-map-over-constants-rec (nth 1 expr))
+	       (nth 2 expr)))
+	(t (cons (car expr) (mapcar 'math-map-over-constants-rec (cdr expr)))))
+)
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/calc-trail.el	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,190 @@
+;; Calculator for GNU Emacs, part II [calc-trail.el]
+;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+;; Written by Dave Gillespie, daveg@synaptics.com.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY.  No author or distributor
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing.  Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License.   A copy of this license is
+;; supposed to have been given to you along with GNU Emacs so you
+;; can know your rights and responsibilities.  It should be in a
+;; file named COPYING.  Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+
+
+
+;; This file is autoloaded from calc-ext.el.
+(require 'calc-ext)
+
+(require 'calc-macs)
+
+(defun calc-Need-calc-trail () nil)
+
+
+;;; Trail commands.
+
+(defun calc-trail-in ()
+  (interactive)
+  (let ((win (get-buffer-window (calc-trail-display t))))
+    (and win (select-window win)))
+)
+
+(defun calc-trail-out ()
+  (interactive)
+  (calc-select-buffer)
+  (let ((win (get-buffer-window (current-buffer))))
+    (if win
+	(progn
+	  (select-window win)
+	  (calc-align-stack-window))
+      (calc)))
+)
+
+(defun calc-trail-next (n)
+  (interactive "p")
+  (calc-with-trail-buffer
+   (forward-line n)
+   (calc-trail-here))
+)
+
+(defun calc-trail-previous (n)
+  (interactive "p")
+  (calc-with-trail-buffer
+   (forward-line (- n))
+   (calc-trail-here))
+)
+
+(defun calc-trail-first (n)
+  (interactive "p")
+  (calc-with-trail-buffer
+   (goto-char (point-min))
+   (forward-line n)
+   (calc-trail-here))
+)
+
+(defun calc-trail-last (n)
+  (interactive "p")
+  (calc-with-trail-buffer
+   (goto-char (point-max))
+   (forward-line (- n))
+   (calc-trail-here))
+)
+
+(defun calc-trail-scroll-left (n)
+  (interactive "P")
+  (let ((curwin (selected-window)))
+    (calc-with-trail-buffer
+     (unwind-protect
+	 (progn
+	   (select-window (get-buffer-window (current-buffer)))
+	   (calc-scroll-left n))
+       (select-window curwin))))
+)
+
+(defun calc-trail-scroll-right (n)
+  (interactive "P")
+  (let ((curwin (selected-window)))
+    (calc-with-trail-buffer
+     (unwind-protect
+	 (progn
+	   (select-window (get-buffer-window (current-buffer)))
+	   (calc-scroll-right n))
+       (select-window curwin))))
+)
+
+(defun calc-trail-forward (n)
+  (interactive "p")
+  (calc-with-trail-buffer
+   (forward-line (* n (1- (window-height))))
+   (calc-trail-here))
+)
+
+(defun calc-trail-backward (n)
+  (interactive "p")
+  (calc-with-trail-buffer
+   (forward-line (- (* n (1- (window-height)))))
+   (calc-trail-here))
+)
+
+(defun calc-trail-isearch-forward ()
+  (interactive)
+  (calc-with-trail-buffer
+   (save-window-excursion
+     (select-window (get-buffer-window (current-buffer)))
+     (let ((search-exit-char ?\r))
+       (isearch-forward)))
+   (calc-trail-here))
+)
+
+(defun calc-trail-isearch-backward ()
+  (interactive)
+  (calc-with-trail-buffer
+   (save-window-excursion
+     (select-window (get-buffer-window (current-buffer)))
+     (let ((search-exit-char ?\r))
+       (isearch-backward)))
+   (calc-trail-here))
+)
+
+(defun calc-trail-yank (arg)
+  (interactive "P")
+  (calc-wrapper
+   (or arg (calc-set-command-flag 'hold-trail))
+   (calc-enter-result 0 "yank"
+		      (calc-with-trail-buffer
+		       (if arg
+			   (forward-line (- (prefix-numeric-value arg))))
+		       (if (or (looking-at "Emacs Calc")
+			       (looking-at "----")
+			       (looking-at " ? ? ?[^ \n]* *$")
+			       (looking-at "..?.?$"))
+			   (error "Can't yank that line"))
+		       (if (looking-at ".*, \\.\\.\\., ")
+			   (error "Can't yank (vector was abbreviated)"))
+		       (forward-char 4)
+		       (search-forward " ")
+		       (let* ((next (save-excursion (forward-line 1) (point)))
+			      (str (buffer-substring (point) (1- next)))
+			      (val (save-excursion
+				     (set-buffer save-buf)
+				     (math-read-plain-expr str))))
+			 (if (eq (car-safe val) 'error)
+			     (error "Can't yank that line: %s" (nth 2 val))
+			   val)))))
+)
+
+(defun calc-trail-marker (str)
+  (interactive "sText to insert in trail: ")
+  (calc-with-trail-buffer
+   (forward-line 1)
+   (let ((buffer-read-only nil))
+     (insert "---- " str "\n"))
+   (forward-line -1)
+   (calc-trail-here))
+)
+
+(defun calc-trail-kill (n)
+  (interactive "p")
+  (calc-with-trail-buffer
+   (let ((buffer-read-only nil))
+     (save-restriction
+       (narrow-to-region   ; don't delete "Emacs Trail" header
+	(save-excursion
+	  (goto-char (point-min))
+	  (forward-line 1)
+	  (point))
+	(point-max))
+       (kill-line n)))
+   (calc-trail-here))
+)
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/calc-undo.el	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,159 @@
+;; Calculator for GNU Emacs, part II [calc-undo.el]
+;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+;; Written by Dave Gillespie, daveg@synaptics.com.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY.  No author or distributor
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing.  Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License.   A copy of this license is
+;; supposed to have been given to you along with GNU Emacs so you
+;; can know your rights and responsibilities.  It should be in a
+;; file named COPYING.  Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+
+
+
+;; This file is autoloaded from calc-ext.el.
+(require 'calc-ext)
+
+(require 'calc-macs)
+
+(defun calc-Need-calc-undo () nil)
+
+
+;;; Undo.
+
+(defun calc-undo (n)
+  (interactive "p")
+  (and calc-executing-macro
+       (error "Use C-x e, not X, to run a keyboard macro that uses Undo."))
+  (if (<= n 0)
+      (if (< n 0)
+	  (calc-redo (- n))
+	(calc-last-args 1))
+    (calc-wrapper
+     (if (null (nthcdr (1- n) calc-undo-list))
+	 (error "No further undo information available"))
+     (setq calc-undo-list
+	   (prog1
+	       (nthcdr n calc-undo-list)
+	     (let ((saved-stack-top calc-stack-top))
+	       (let ((calc-stack-top 0))
+		 (calc-handle-undos calc-undo-list n))
+	       (setq calc-stack-top saved-stack-top))))
+     (message "Undo!")))
+)
+
+(defun calc-handle-undos (cl n)
+  (if (> n 0)
+      (progn
+	(let ((old-redo calc-redo-list))
+	  (setq calc-undo-list nil)
+	  (calc-handle-undo (car cl))
+	  (setq calc-redo-list (append calc-undo-list old-redo)))
+	(calc-handle-undos (cdr cl) (1- n))))
+)
+
+(defun calc-handle-undo (list)
+  (and list
+       (let ((action (car list)))
+	 (cond
+	  ((eq (car action) 'push)
+	   (calc-pop-stack 1 (nth 1 action) t))
+	  ((eq (car action) 'pop)
+	   (calc-push-list (nth 2 action) (nth 1 action)))
+	  ((eq (car action) 'set)
+	   (calc-record-undo (list 'set (nth 1 action)
+				   (symbol-value (nth 1 action))))
+	   (set (nth 1 action) (nth 2 action)))
+	  ((eq (car action) 'store)
+	   (let ((v (intern (nth 1 action))))
+	     (calc-record-undo (list 'store (nth 1 action)
+				     (and (boundp v) (symbol-value v))))
+	     (if (y-or-n-p (format "Un-store variable %s? " (nth 1 action)))
+		 (progn
+		   (if (nth 2 action)
+		       (set v (nth 2 action))
+		     (makunbound v))
+		   (calc-refresh-evaltos v)))))
+	  ((eq (car action) 'eval)
+	   (calc-record-undo (append (list 'eval (nth 2 action) (nth 1 action))
+				     (cdr (cdr (cdr action)))))
+	   (apply (nth 1 action) (cdr (cdr (cdr action))))))
+	 (calc-handle-undo (cdr list))))
+)
+
+(defun calc-redo (n)
+  (interactive "p")
+  (and calc-executing-macro
+       (error "Use C-x e, not X, to run a keyboard macro that uses Redo."))
+  (if (<= n 0)
+      (calc-undo (- n))
+    (calc-wrapper
+     (if (null (nthcdr (1- n) calc-redo-list))
+	 (error "Unable to redo"))
+     (setq calc-redo-list
+	   (prog1
+	       (nthcdr n calc-redo-list)
+	     (let ((saved-stack-top calc-stack-top))
+	       (let ((calc-stack-top 0))
+		 (calc-handle-redos calc-redo-list n))
+	       (setq calc-stack-top saved-stack-top))))
+     (message "Redo!")))
+)
+
+(defun calc-handle-redos (cl n)
+  (if (> n 0)
+      (progn
+	(let ((old-undo calc-undo-list))
+	  (setq calc-undo-list nil)
+	  (calc-handle-undo (car cl))
+	  (setq calc-undo-list (append calc-undo-list old-undo)))
+	(calc-handle-redos (cdr cl) (1- n))))
+)
+
+(defun calc-last-args (n)
+  (interactive "p")
+  (and calc-executing-macro
+       (error "Use C-x e, not X, to run a keyboard macro that uses last-args."))
+  (calc-wrapper
+   (let ((urec (calc-find-last-x calc-undo-list n)))
+     (if urec
+	 (calc-handle-last-x urec)
+       (error "Not enough undo information available"))))
+)
+
+(defun calc-handle-last-x (list)
+  (and list
+       (let ((action (car list)))
+	 (if (eq (car action) 'pop)
+	     (calc-pop-push-record-list 0 "larg"
+					(delq 'top-of-stack (nth 2 action))))
+	 (calc-handle-last-x (cdr list))))
+)
+
+(defun calc-find-last-x (ul n)
+  (and ul
+       (if (calc-undo-does-pushes (car ul))
+	   (if (<= n 1)
+	       (car ul)
+	     (calc-find-last-x (cdr ul) (1- n)))
+	 (calc-find-last-x (cdr ul) n)))
+)
+
+(defun calc-undo-does-pushes (list)
+  (and list
+       (or (eq (car (car list)) 'pop)
+	   (calc-undo-does-pushes (cdr list))))
+)
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/calc-units.el	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,1352 @@
+;; Calculator for GNU Emacs, part II [calc-units.el]
+;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+;; Written by Dave Gillespie, daveg@synaptics.com.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY.  No author or distributor
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing.  Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License.   A copy of this license is
+;; supposed to have been given to you along with GNU Emacs so you
+;; can know your rights and responsibilities.  It should be in a
+;; file named COPYING.  Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+
+
+
+;; This file is autoloaded from calc-ext.el.
+(require 'calc-ext)
+
+(require 'calc-macs)
+
+(defun calc-Need-calc-units () nil)
+
+
+;;; Units commands.
+
+(defun calc-base-units ()
+  (interactive)
+  (calc-slow-wrapper
+   (let ((calc-autorange-units nil))
+     (calc-enter-result 1 "bsun" (math-simplify-units
+				  (math-to-standard-units (calc-top-n 1)
+							  nil)))))
+)
+
+(defun calc-quick-units ()
+  (interactive)
+  (calc-slow-wrapper
+   (let* ((num (- last-command-char ?0))
+	  (pos (if (= num 0) 10 num))
+	  (units (calc-var-value 'var-Units))
+	  (expr (calc-top-n 1)))
+     (or (and (>= num 0) (<= num 9))
+	 (error "Bad unit number"))
+     (or (math-vectorp units)
+	 (error "No \"quick units\" are defined"))
+     (or (< pos (length units))
+	 (error "Unit number %d not defined" pos))
+     (if (math-units-in-expr-p expr nil)
+	 (calc-enter-result 1 (format "cun%d" num)
+			    (math-convert-units expr (nth pos units)))
+       (calc-enter-result 1 (format "*un%d" num)
+			  (math-simplify-units
+			   (math-mul expr (nth pos units)))))))
+)
+
+(defun calc-convert-units (&optional old-units new-units)
+  (interactive)
+  (calc-slow-wrapper
+   (let ((expr (calc-top-n 1))
+	 (uoldname nil)
+	 unew)
+     (or (math-units-in-expr-p expr t)
+	 (let ((uold (or old-units
+			 (progn
+			   (setq uoldname (read-string "Old units: "))
+			   (if (equal uoldname "")
+			       (progn
+				 (setq uoldname "1")
+				 1)
+			     (if (string-match "\\` */" uoldname)
+				 (setq uoldname (concat "1" uoldname)))
+			     (math-read-expr uoldname))))))
+	   (if (eq (car-safe uold) 'error)
+	       (error "Bad format in units expression: %s" (nth 1 uold)))
+	   (setq expr (math-mul expr uold))))
+     (or new-units
+	 (setq new-units (read-string (if uoldname
+					  (concat "Old units: "
+						  uoldname
+						  ", new units: ")
+					"New units: "))))
+     (if (string-match "\\` */" new-units)
+	 (setq new-units (concat "1" new-units)))
+     (setq units (math-read-expr new-units))
+     (if (eq (car-safe units) 'error)
+	 (error "Bad format in units expression: %s" (nth 2 units)))
+     (let ((unew (math-units-in-expr-p units t))
+	   (std (and (eq (car-safe units) 'var)
+		     (assq (nth 1 units) math-standard-units-systems))))
+       (if std
+	   (calc-enter-result 1 "cvun" (math-simplify-units
+					(math-to-standard-units expr
+								(nth 1 std))))
+	 (or unew
+	     (error "No units specified"))
+	 (calc-enter-result 1 "cvun"
+			    (math-convert-units
+			     expr units
+			     (and uoldname (not (equal uoldname "1")))))))))
+)
+
+(defun calc-autorange-units (arg)
+  (interactive "P")
+  (calc-wrapper
+   (calc-change-mode 'calc-autorange-units arg nil t)
+   (message (if calc-autorange-units
+		"Adjusting target unit prefix automatically."
+	      "Using target units exactly.")))
+)
+
+(defun calc-convert-temperature (&optional old-units new-units)
+  (interactive)
+  (calc-slow-wrapper
+   (let ((expr (calc-top-n 1))
+	 (uold nil)
+	 (uoldname nil)
+	 unew)
+     (setq uold (or old-units
+		    (let ((units (math-single-units-in-expr-p expr)))
+		      (if units
+			  (if (consp units)
+			      (list 'var (car units)
+				    (intern (concat "var-"
+						    (symbol-name
+						     (car units)))))
+			    (error "Not a pure temperature expression"))
+			(math-read-expr
+			 (setq uoldname (read-string
+					 "Old temperature units: ")))))))
+     (if (eq (car-safe uold) 'error)
+	 (error "Bad format in units expression: %s" (nth 2 uold)))
+     (or (math-units-in-expr-p expr nil)
+	 (setq expr (math-mul expr uold)))
+     (setq unew (or new-units
+		    (math-read-expr
+		     (read-string (if uoldname
+				      (concat "Old temperature units: "
+					      uoldname
+					      ", new units: ")
+				    "New temperature units: ")))))
+     (if (eq (car-safe unew) 'error)
+	 (error "Bad format in units expression: %s" (nth 2 unew)))
+     (calc-enter-result 1 "cvtm" (math-simplify-units
+				  (math-convert-temperature expr uold unew
+							    uoldname)))))
+)
+
+(defun calc-remove-units ()
+  (interactive)
+  (calc-slow-wrapper
+   (calc-enter-result 1 "rmun" (math-simplify-units
+				(math-remove-units (calc-top-n 1)))))
+)
+
+(defun calc-extract-units ()
+  (interactive)
+  (calc-slow-wrapper
+   (calc-enter-result 1 "rmun" (math-simplify-units
+				(math-extract-units (calc-top-n 1)))))
+)
+
+(defun calc-explain-units ()
+  (interactive)
+  (calc-wrapper
+   (let ((num-units nil)
+	 (den-units nil))
+     (calc-explain-units-rec (calc-top-n 1) 1)
+     (and den-units (string-match "^[^(].* .*[^)]$" den-units)
+	  (setq den-units (concat "(" den-units ")")))
+     (if num-units
+	 (if den-units
+	     (message "%s per %s" num-units den-units)
+	   (message "%s" num-units))
+       (if den-units
+	   (message "1 per %s" den-units)
+	 (message "No units in expression")))))
+)
+
+(defun calc-explain-units-rec (expr pow)
+  (let ((u (math-check-unit-name expr))
+	pos)
+    (if (and u (not (math-zerop pow)))
+	(let ((name (or (nth 2 u) (symbol-name (car u)))))
+	  (if (eq (aref name 0) ?\*)
+	      (setq name (substring name 1)))
+	  (if (string-match "[^a-zA-Z0-9']" name)
+	      (if (string-match "^[a-zA-Z0-9' ()]*$" name)
+		  (while (setq pos (string-match "[ ()]" name))
+		    (setq name (concat (substring name 0 pos)
+				       (if (eq (aref name pos) 32) "-" "")
+				       (substring name (1+ pos)))))
+		(setq name (concat "(" name ")"))))
+	  (or (eq (nth 1 expr) (car u))
+	      (setq name (concat (nth 2 (assq (aref (symbol-name
+						     (nth 1 expr)) 0)
+					      math-unit-prefixes))
+				 (if (and (string-match "[^a-zA-Z0-9']" name)
+					  (not (memq (car u) '(mHg gf))))
+				     (concat "-" name)
+				   (downcase name)))))
+	  (cond ((or (math-equal-int pow 1)
+		     (math-equal-int pow -1)))
+		((or (math-equal-int pow 2)
+		     (math-equal-int pow -2))
+		 (if (equal (nth 4 u) '((m . 1)))
+		     (setq name (concat "Square-" name))
+		   (setq name (concat name "-squared"))))
+		((or (math-equal-int pow 3)
+		     (math-equal-int pow -3))
+		 (if (equal (nth 4 u) '((m . 1)))
+		     (setq name (concat "Cubic-" name))
+		   (setq name (concat name "-cubed"))))
+		(t
+		 (setq name (concat name "^"
+				    (math-format-number (math-abs pow))))))
+	  (if (math-posp pow)
+	      (setq num-units (if num-units
+				  (concat num-units " " name)
+				name))
+	    (setq den-units (if den-units
+				(concat den-units " " name)
+			      name))))
+      (cond ((eq (car-safe expr) '*)
+	     (calc-explain-units-rec (nth 1 expr) pow)
+	     (calc-explain-units-rec (nth 2 expr) pow))
+	    ((eq (car-safe expr) '/)
+	     (calc-explain-units-rec (nth 1 expr) pow)
+	     (calc-explain-units-rec (nth 2 expr) (- pow)))
+	    ((memq (car-safe expr) '(neg + -))
+	     (calc-explain-units-rec (nth 1 expr) pow))
+	    ((and (eq (car-safe expr) '^)
+		  (math-realp (nth 2 expr)))
+	     (calc-explain-units-rec (nth 1 expr)
+				     (math-mul pow (nth 2 expr)))))))
+)
+
+(defun calc-simplify-units ()
+  (interactive)
+  (calc-slow-wrapper
+   (calc-with-default-simplification
+    (calc-enter-result 1 "smun" (math-simplify-units (calc-top-n 1)))))
+)
+
+(defun calc-view-units-table (n)
+  (interactive "P")
+  (and n (setq math-units-table-buffer-valid nil))
+  (let ((win (get-buffer-window "*Units Table*")))
+    (if (and win
+	     math-units-table
+	     math-units-table-buffer-valid)
+	(progn
+	  (bury-buffer (window-buffer win))
+	  (let ((curwin (selected-window)))
+	    (select-window win)
+	    (switch-to-buffer nil)
+	    (select-window curwin)))
+      (math-build-units-table-buffer nil)))
+)
+
+(defun calc-enter-units-table (n)
+  (interactive "P")
+  (and n (setq math-units-table-buffer-valid nil))
+  (math-build-units-table-buffer t)
+  (message (substitute-command-keys "Type \\[calc] to return to the Calculator."))
+)
+
+(defun calc-define-unit (uname desc)
+  (interactive "SDefine unit name: \nsDescription: ")
+  (calc-wrapper
+   (let ((form (calc-top-n 1))
+	 (unit (assq uname math-additional-units)))
+     (or unit
+	 (setq math-additional-units
+	       (cons (setq unit (list uname nil nil))
+		     math-additional-units)
+	       math-units-table nil))
+     (setcar (cdr unit) (and (not (and (eq (car-safe form) 'var)
+				       (eq (nth 1 form) uname)))
+			     (not (math-equal-int form 1))
+			     (math-format-flat-expr form 0)))
+     (setcar (cdr (cdr unit)) (and (not (equal desc ""))
+				   desc))))
+  (calc-invalidate-units-table)
+)
+
+(defun calc-undefine-unit (uname)
+  (interactive "SUndefine unit name: ")
+  (calc-wrapper
+   (let ((unit (assq uname math-additional-units)))
+     (or unit
+	 (if (assq uname math-standard-units)
+	     (error "\"%s\" is a predefined unit name" uname)
+	   (error "Unit name \"%s\" not found" uname)))
+     (setq math-additional-units (delq unit math-additional-units)
+	   math-units-table nil)))
+  (calc-invalidate-units-table)
+)
+
+(defun calc-invalidate-units-table ()
+  (setq math-units-table nil)
+  (let ((buf (get-buffer "*Units Table*")))
+    (and buf
+	 (save-excursion
+	   (set-buffer buf)
+	   (save-excursion
+	     (goto-char (point-min))
+	     (if (looking-at "Calculator Units Table")
+		 (let ((buffer-read-only nil))
+		   (insert "(Obsolete) ")))))))
+)
+
+(defun calc-get-unit-definition (uname)
+  (interactive "SGet definition for unit: ")
+  (calc-wrapper
+   (math-build-units-table)
+   (let ((unit (assq uname math-units-table)))
+     (or unit
+	 (error "Unit name \"%s\" not found" uname))
+     (let ((msg (nth 2 unit)))
+       (if (stringp msg)
+	   (if (string-match "^\\*" msg)
+	       (setq msg (substring msg 1)))
+	 (setq msg (symbol-name uname)))
+       (if (nth 1 unit)
+	   (progn
+	     (calc-enter-result 0 "ugdf" (nth 1 unit))
+	     (message "Derived unit: %s" msg))
+	 (calc-enter-result 0 "ugdf" (list 'var uname
+					   (intern
+					    (concat "var-"
+						    (symbol-name uname)))))
+	 (message "Base unit: %s" msg)))))
+)
+
+(defun calc-permanent-units ()
+  (interactive)
+  (calc-wrapper
+   (let (pos)
+     (set-buffer (find-file-noselect (substitute-in-file-name
+				      calc-settings-file)))
+     (goto-char (point-min))
+     (if (and (search-forward ";;; Custom units stored by Calc" nil t)
+	      (progn
+		(beginning-of-line)
+		(setq pos (point))
+		(search-forward "\n;;; End of custom units" nil t)))
+	 (progn
+	   (beginning-of-line)
+	   (forward-line 1)
+	   (delete-region pos (point)))
+       (goto-char (point-max))
+       (insert "\n\n")
+       (forward-char -1))
+     (insert ";;; Custom units stored by Calc on " (current-time-string) "\n")
+     (if math-additional-units
+	 (progn
+	   (insert "(setq math-additional-units '(\n")
+	   (let ((list math-additional-units))
+	     (while list
+	       (insert "  (" (symbol-name (car (car list))) " "
+		       (if (nth 1 (car list))
+			   (if (stringp (nth 1 (car list)))
+			       (prin1-to-string (nth 1 (car list)))
+			     (prin1-to-string (math-format-flat-expr
+					       (nth 1 (car list)) 0)))
+			 "nil")
+		       " "
+		       (prin1-to-string (nth 2 (car list)))
+		       ")\n")
+	       (setq list (cdr list))))
+	   (insert "))\n"))
+       (insert ";;; (no custom units defined)\n"))
+     (insert ";;; End of custom units\n")
+     (save-buffer)))
+)
+
+
+
+
+
+;;; Units operations.
+
+;;; Units table last updated 9-Jan-91 by Ulrich Mueller (ulm@vsnhd1.cern.ch)
+;;; with some additions by Przemek Klosowski (przemek@rrdstrad.nist.gov)
+
+(defvar math-standard-units
+  '( ;; Length
+     ( m       nil		     "*Meter" )
+     ( in      "2.54 cm"             "Inch" )
+     ( ft      "12 in"		     "Foot" )
+     ( yd      "3 ft"		     "Yard" )
+     ( mi      "5280 ft"	     "Mile" )
+     ( au      "1.495979e11 m"       "Astronomical Unit" )
+     ( lyr     "9460536207068016 m"  "Light Year" )
+     ( pc      "206264.80625 au"     "Parsec" )
+     ( nmi     "1852 m"		     "Nautical Mile" )
+     ( fath    "6 ft"		     "Fathom" )
+     ( u       "1 um"		     "Micron" )
+     ( mil     "in/1000"	     "Mil" )
+     ( point   "in/72"		     "Point (1/72 inch)" )
+     ( tpt     "in/72.27"	     "Point (TeX conventions)" )
+     ( Ang     "1e-10 m"	     "Angstrom" )
+     ( mfi     "mi+ft+in"	     "Miles + feet + inches" )
+     
+     ;; Area
+     ( hect    "10000 m^2"	     "*Hectare" )
+     ( acre    "mi^2 / 640"	     "Acre" )
+     ( b       "1e-28 m^2"	     "Barn" )
+     
+     ;; Volume
+     ( l       "1e-3 m^3"	     "*Liter" )
+     ( L       "1e-3 m^3"	     "Liter" )
+     ( gal     "4 qt"		     "US Gallon" )
+     ( qt      "2 pt"		     "Quart" )
+     ( pt      "2 cup"		     "Pint" )
+     ( cup     "8 ozfl"		     "Cup" )
+     ( ozfl    "2 tbsp"		     "Fluid Ounce" )
+     ( floz    "2 tbsp"		     "Fluid Ounce" )
+     ( tbsp    "3 tsp"		     "Tablespoon" )
+     ( tsp     "4.92892159375 ml"    "Teaspoon" )
+     ( vol     "tsp+tbsp+ozfl+cup+pt+qt+gal" "Gallons + ... + teaspoons" )
+     ( galC    "4.54609 l"	     "Canadian Gallon" )
+     ( galUK   "4.546092 l"	     "UK Gallon" )
+     
+     ;; Time
+     ( s       nil		     "*Second" )
+     ( sec     "s"		     "Second" )
+     ( min     "60 s"		     "Minute" )
+     ( hr      "60 min"		     "Hour" )
+     ( day     "24 hr"		     "Day" )
+     ( wk      "7 day"		     "Week" )
+     ( hms     "wk+day+hr+min+s"     "Hours, minutes, seconds" )
+     ( yr      "365.25 day"	     "Year" )
+     ( Hz      "1/s"		     "Hertz" )
+
+     ;; Speed
+     ( mph     "mi/hr"		     "*Miles per hour" )
+     ( kph     "km/hr"		     "Kilometers per hour" )
+     ( knot    "nmi/hr"		     "Knot" )
+     ( c       "2.99792458e8 m/s"    "Speed of light" )     
+     
+     ;; Acceleration
+     ( ga      "9.80665 m/s^2"	     "*\"g\" acceleration" )
+
+     ;; Mass
+     ( g       nil                   "*Gram" )
+     ( lb      "16 oz"		     "Pound (mass)" )
+     ( oz      "28.349523125 g"	     "Ounce (mass)" )
+     ( ton     "2000 lb"	     "Ton" )
+     ( tpo     "ton+lb+oz"	     "Tons + pounds + ounces (mass)" )
+     ( t       "1000 kg"	     "Metric ton" )
+     ( tonUK   "1016.0469088 kg"     "UK ton" )
+     ( lbt     "12 ozt"		     "Troy pound" )
+     ( ozt     "31.103475 g"	     "Troy ounce" )
+     ( ct      ".2 g"		     "Carat" )
+     ( amu     "1.6605402e-24 g"     "Unified atomic mass" )
+
+     ;; Force
+     ( N       "m kg/s^2"	     "*Newton" )
+     ( dyn     "1e-5 N"		     "Dyne" )
+     ( gf      "ga g"		     "Gram (force)" )
+     ( lbf     "4.44822161526 N"     "Pound (force)" )
+     ( kip     "1000 lbf"	     "Kilopound (force)" )
+     ( pdl     "0.138255 N"	     "Poundal" )
+
+     ;; Energy
+     ( J       "N m"		     "*Joule" )
+     ( erg     "1e-7 J"		     "Erg" )
+     ( cal     "4.1868 J"	     "International Table Calorie" )
+     ( Btu     "1055.05585262 J"     "International Table Btu" )
+     ( eV      "ech V"               "Electron volt" )
+     ( ev      "eV"                  "Electron volt" )
+     ( therm   "105506000 J"	     "EEC therm" )
+     ( invcm   "h c/cm"	  	     "Energy in inverse centimeters" )
+     ( Kayser  "invcm"		     "Kayser (inverse centimeter energy)" )
+     ( men     "100/invcm"	     "Inverse energy in meters" )
+     ( Hzen    "h Hz"		     "Energy in Hertz")
+     ( Ken     "k K"		     "Energy in Kelvins")
+     ;; ( invcm   "eV / 8065.47835185"    "Energy in inverse centimeters" )
+     ;; ( Hzen    "eV / 2.41796958004e14" "Energy in Hertz")
+     ;; ( Ken     "eV / 11604.7967327"    "Energy in Kelvins")
+
+     ;; Power
+     ( W       "J/s"		     "*Watt" )
+     ( hp      "745.7 W"	     "Horsepower" )
+
+     ;; Temperature
+     ( K       nil                   "*Degree Kelvin"     K )
+     ( dK      "K"		     "Degree Kelvin"	  K )
+     ( degK    "K"		     "Degree Kelvin"	  K )
+     ( dC      "K"		     "Degree Celsius"	  C )
+     ( degC    "K"      	     "Degree Celsius"	  C )
+     ( dF      "(5/9) K"	     "Degree Fahrenheit"  F )
+     ( degF    "(5/9) K"	     "Degree Fahrenheit"  F )
+
+     ;; Pressure
+     ( Pa      "N/m^2"		     "*Pascal" )
+     ( bar     "1e5 Pa"		     "Bar" )
+     ( atm     "101325 Pa"	     "Standard atmosphere" )
+     ( torr    "atm/760"	     "Torr" )
+     ( mHg     "1000 torr"	     "Meter of mercury" )
+     ( inHg    "25.4 mmHg"	     "Inch of mercury" )
+     ( inH2O   "248.84 Pa"	     "Inch of water" )
+     ( psi     "6894.75729317 Pa"    "Pound per square inch" )
+
+     ;; Viscosity
+     ( P       "0.1 Pa s"	     "*Poise" )
+     ( St      "1e-4 m^2/s"	     "Stokes" )
+
+     ;; Electromagnetism
+     ( A       nil                   "*Ampere" )
+     ( C       "A s"		     "Coulomb" )
+     ( Fdy     "ech Nav"  	     "Faraday" )
+     ( e       "1.60217733e-19 C"    "Elementary charge" )
+     ( ech     "1.60217733e-19 C"    "Elementary charge" )
+     ( V       "W/A"		     "Volt" )
+     ( ohm     "V/A"		     "Ohm" )
+     ( mho     "A/V"		     "Mho" )
+     ( S       "A/V"		     "Siemens" )
+     ( F       "C/V"		     "Farad" )
+     ( H       "Wb/A"		     "Henry" )
+     ( T       "Wb/m^2"		     "Tesla" )
+     ( G       "1e-4 T"		     "Gauss" )
+     ( Wb      "V s"		     "Weber" )
+
+     ;; Luminous intensity
+     ( cd      nil                   "*Candela" )
+     ( sb      "1e4 cd/m^2"	     "Stilb" )
+     ( lm      "cd sr"		     "Lumen" )
+     ( lx      "lm/m^2"		     "Lux" )
+     ( ph      "1e4 lx"		     "Phot" )
+     ( fc      "10.76 lx"	     "Footcandle" )
+     ( lam     "1e4 lm/m^2"	     "Lambert" )
+     ( flam    "1.07639104e-3 lam"   "Footlambert" )
+
+     ;; Radioactivity
+     ( Bq      "1/s"  		     "*Becquerel" )
+     ( Ci      "3.7e10 Bq"	     "Curie" )
+     ( Gy      "J/kg"		     "Gray" )
+     ( Sv      "Gy"		     "Sievert" )
+     ( R       "2.58e-4 C/kg"	     "Roentgen" )
+     ( rd      ".01 Gy"		     "Rad" )
+     ( rem     "rd"		     "Rem" )
+
+     ;; Amount of substance
+     ( mol     nil                   "*Mole" )
+
+     ;; Plane angle
+     ( rad     nil                   "*Radian" )
+     ( circ    "2 pi rad"	     "Full circle" )
+     ( rev     "circ"		     "Full revolution" )
+     ( deg     "circ/360"            "Degree" )
+     ( arcmin  "deg/60"		     "Arc minute" )
+     ( arcsec  "arcmin/60"	     "Arc second" )
+     ( grad    "circ/400"            "Grade" )
+     ( rpm     "rev/min"	     "Revolutions per minute" )
+
+     ;; Solid angle
+     ( sr      nil		     "*Steradian" )
+
+     ;; Other physical quantities (Physics Letters B239, 1 (1990))
+     ( h       "6.6260755e-34 J s"   "*Planck's constant" )
+     ( hbar    "h / 2 pi"	     "Planck's constant" )
+     ( mu0     "4 pi 1e-7 H/m"       "Permeability of vacuum" )
+     ( Grav    "6.67259e-11 N m^2/kg^2"  "Gravitational constant" )
+     ( Nav     "6.0221367e23 / mol"  "Avagadro's constant" )
+     ( me      "0.51099906 MeV/c^2"  "Electron rest mass" )
+     ( mp      "1.007276470 amu"     "Proton rest mass" )
+     ( mn      "1.008664904 amu"     "Neutron rest mass" )
+     ( mu      "0.113428913 amu"     "Muon rest mass" )
+     ( Ryd     "1.0973731571e5 invcm" "Rydberg's constant" )
+     ( k       "1.3806513e-23 J/K"   "Boltzmann's constant" )
+     ( fsc     "1 / 137.0359895"     "Fine structure constant" )
+     ( muB     "5.78838263e-11 MeV/T"  "Bohr magneton" )
+     ( muN     "3.15245166e-14 MeV/T"  "Nuclear magneton" )
+     ( mue     "1.001159652193 muB"  "Electron magnetic moment" )
+     ( mup     "2.792847386 muN"     "Proton magnetic moment" )
+     ( R0      "Nav k"               "Molar gas constant" )
+     ( V0      "22.413992 L/mol"     "Standard volume of ideal gas" )
+))
+
+
+(defvar math-additional-units nil
+  "*Additional units table for user-defined units.
+Must be formatted like math-standard-units.
+If this is changed, be sure to set math-units-table to nil to ensure
+that the combined units table will be rebuilt.")
+
+(defvar math-unit-prefixes
+  '( ( ?E  (float 1 18)  "Exa"    )
+     ( ?P  (float 1 15)  "Peta"   )
+     ( ?T  (float 1 12)  "Tera"	  )
+     ( ?G  (float 1 9)   "Giga"	  )
+     ( ?M  (float 1 6)   "Mega"	  )
+     ( ?k  (float 1 3)   "Kilo"	  )
+     ( ?K  (float 1 3)   "Kilo"	  )
+     ( ?h  (float 1 2)   "Hecto"  )
+     ( ?H  (float 1 2)   "Hecto"  )
+     ( ?D  (float 1 1)   "Deka"	  )
+     ( 0   (float 1 0)   nil      )
+     ( ?d  (float 1 -1)  "Deci"	  )
+     ( ?c  (float 1 -2)  "Centi"  )
+     ( ?m  (float 1 -3)  "Milli"  )
+     ( ?u  (float 1 -6)  "Micro"  )
+     ( ?n  (float 1 -9)  "Nano"	  )
+     ( ?p  (float 1 -12) "Pico"	  )
+     ( ?f  (float 1 -15) "Femto"  )
+     ( ?a  (float 1 -18) "Atto"   )
+))
+
+(defvar math-standard-units-systems
+  '( ( base  nil )
+     ( si    ( ( g   '(* (var kg var-kg) (float 1 -3)) ) ) )
+     ( mks   ( ( g   '(* (var kg var-kg) (float 1 -3)) ) ) )
+     ( cgs   ( ( m   '(* (var cm var-cm) 100         ) ) ) )
+))
+
+(defvar math-units-table nil
+  "Internal units table derived from math-defined-units.
+Entries are (SYMBOL EXPR DOC-STRING TEMP-TYPE BASE-UNITS).")
+
+(defvar math-units-table-buffer-valid nil)
+
+
+(defun math-build-units-table ()
+  (or math-units-table
+      (let* ((combined-units (append math-additional-units
+				     math-standard-units))
+	     (unit-list (mapcar 'car combined-units))
+	     tab)
+	(message "Building units table...")
+	(setq math-units-table-buffer-valid nil)
+	(setq tab (mapcar (function
+			   (lambda (x)
+			     (list (car x)
+				   (and (nth 1 x)
+					(if (stringp (nth 1 x))
+					    (let ((exp (math-read-plain-expr
+							(nth 1 x))))
+					      (if (eq (car-safe exp) 'error)
+						  (error "Format error in definition of %s in units table: %s"
+							 (car x) (nth 2 exp))
+						exp))
+					  (nth 1 x)))
+				   (nth 2 x)
+				   (nth 3 x)
+				   (and (not (nth 1 x))
+					(list (cons (car x) 1))))))
+			  combined-units))
+	(let ((math-units-table tab))
+	  (mapcar 'math-find-base-units tab))
+	(message "Building units table...done")
+	(setq math-units-table tab)))
+)
+
+(defun math-find-base-units (entry)
+  (if (eq (nth 4 entry) 'boom)
+      (error "Circular definition involving unit %s" (car entry)))
+  (or (nth 4 entry)
+      (let (base)
+	(setcar (nthcdr 4 entry) 'boom)
+	(math-find-base-units-rec (nth 1 entry) 1)
+	'(or base
+	    (error "Dimensionless definition for unit %s" (car entry)))
+	(while (eq (cdr (car base)) 0)
+	  (setq base (cdr base)))
+	(let ((b base))
+	  (while (cdr b)
+	    (if (eq (cdr (car (cdr b))) 0)
+		(setcdr b (cdr (cdr b)))
+	      (setq b (cdr b)))))
+	(setq base (sort base 'math-compare-unit-names))
+	(setcar (nthcdr 4 entry) base)
+	base))
+)
+
+(defun math-compare-unit-names (a b)
+  (memq (car b) (cdr (memq (car a) unit-list)))
+)
+
+(defun math-find-base-units-rec (expr pow)
+  (let ((u (math-check-unit-name expr)))
+    (cond (u
+	   (let ((ulist (math-find-base-units u)))
+	     (while ulist
+	       (let ((p (* (cdr (car ulist)) pow))
+		     (old (assq (car (car ulist)) base)))
+		 (if old
+		     (setcdr old (+ (cdr old) p))
+		   (setq base (cons (cons (car (car ulist)) p) base))))
+	       (setq ulist (cdr ulist)))))
+	  ((math-scalarp expr))
+	  ((and (eq (car expr) '^)
+		(integerp (nth 2 expr)))
+	   (math-find-base-units-rec (nth 1 expr) (* pow (nth 2 expr))))
+	  ((eq (car expr) '*)
+	   (math-find-base-units-rec (nth 1 expr) pow)
+	   (math-find-base-units-rec (nth 2 expr) pow))
+	  ((eq (car expr) '/)
+	   (math-find-base-units-rec (nth 1 expr) pow)
+	   (math-find-base-units-rec (nth 2 expr) (- pow)))
+	  ((eq (car expr) 'neg)
+	   (math-find-base-units-rec (nth 1 expr) pow))
+	  ((eq (car expr) '+)
+	   (math-find-base-units-rec (nth 1 expr) pow))
+	  ((eq (car expr) 'var)
+	   (or (eq (nth 1 expr) 'pi)
+	       (error "Unknown name %s in defining expression for unit %s"
+		      (nth 1 expr) (car entry))))
+	  (t (error "Malformed defining expression for unit %s" (car entry)))))
+)
+
+
+(defun math-units-in-expr-p (expr sub-exprs)
+  (and (consp expr)
+       (if (eq (car expr) 'var)
+	   (math-check-unit-name expr)
+	 (and (or sub-exprs
+		  (memq (car expr) '(* / ^)))
+	      (or (math-units-in-expr-p (nth 1 expr) sub-exprs)
+		  (math-units-in-expr-p (nth 2 expr) sub-exprs)))))
+)
+
+(defun math-only-units-in-expr-p (expr)
+  (and (consp expr)
+       (if (eq (car expr) 'var)
+	   (math-check-unit-name expr)
+	 (if (memq (car expr) '(* /))
+	     (and (math-only-units-in-expr-p (nth 1 expr))
+		  (math-only-units-in-expr-p (nth 2 expr)))
+	   (and (eq (car expr) '^)
+		(and (math-only-units-in-expr-p (nth 1 expr))
+		     (math-realp (nth 2 expr)))))))
+)
+
+(defun math-single-units-in-expr-p (expr)
+  (cond ((math-scalarp expr) nil)
+	((eq (car expr) 'var)
+	 (math-check-unit-name expr))
+	((eq (car expr) '*)
+	 (let ((u1 (math-single-units-in-expr-p (nth 1 expr)))
+	       (u2 (math-single-units-in-expr-p (nth 2 expr))))
+	   (or (and u1 u2 'wrong)
+	       u1
+	       u2)))
+	((eq (car expr) '/)
+	 (if (math-units-in-expr-p (nth 2 expr) nil)
+	     'wrong
+	   (math-single-units-in-expr-p (nth 1 expr))))
+	(t 'wrong))
+)
+
+(defun math-check-unit-name (v)
+  (and (eq (car-safe v) 'var)
+       (or (assq (nth 1 v) (or math-units-table (math-build-units-table)))
+	   (let ((name (symbol-name (nth 1 v))))
+	     (and (> (length name) 1)
+		  (assq (aref name 0) math-unit-prefixes)
+		  (or (assq (intern (substring name 1)) math-units-table)
+		      (and (eq (aref name 0) ?M)
+			   (> (length name) 3)
+			   (eq (aref name 1) ?e)
+			   (eq (aref name 2) ?g)
+			   (assq (intern (substring name 3))
+				 math-units-table)))))))
+)
+
+
+(defun math-to-standard-units (expr which-standard)
+  (math-to-standard-rec expr)
+)
+
+(defun math-to-standard-rec (expr)
+  (if (eq (car-safe expr) 'var)
+      (let ((u (math-check-unit-name expr))
+	    (base (nth 1 expr)))
+	(if u
+	    (progn
+	      (if (nth 1 u)
+		  (setq expr (math-to-standard-rec (nth 1 u)))
+		(let ((st (assq (car u) which-standard)))
+		  (if st
+		      (setq expr (nth 1 st))
+		    (setq expr (list 'var (car u)
+				     (intern (concat "var-"
+						     (symbol-name
+						      (car u)))))))))
+	      (or (null u)
+		  (eq base (car u))
+		  (setq expr (list '*
+				   (nth 1 (assq (aref (symbol-name base) 0)
+						math-unit-prefixes))
+				   expr)))
+	      expr)
+	  (if (eq base 'pi)
+	      (math-pi)
+	    expr)))
+    (if (Math-primp expr)
+	expr
+      (cons (car expr)
+	    (mapcar 'math-to-standard-rec (cdr expr)))))
+)
+
+(defun math-apply-units (expr units ulist &optional pure)
+  (if ulist
+      (let ((new 0)
+	    value)
+	(setq expr (math-simplify-units expr))
+	(or (math-numberp expr)
+	    (error "Incompatible units"))
+	(while (cdr ulist)
+	  (setq value (math-div expr (nth 1 (car ulist)))
+		value (math-floor (let ((calc-internal-prec
+					 (1- calc-internal-prec)))
+				    (math-normalize value)))
+		new (math-add new (math-mul value (car (car ulist))))
+		expr (math-sub expr (math-mul value (nth 1 (car ulist))))
+		ulist (cdr ulist)))
+	(math-add new (math-mul (math-div expr (nth 1 (car ulist)))
+				(car (car ulist)))))
+    (math-simplify-units (if pure
+			     expr
+			   (list '* expr units))))
+)
+
+(defun math-decompose-units (units)
+  (let ((u (math-check-unit-name units)))
+    (and u (eq (car-safe (nth 1 u)) '+)
+	 (setq units (nth 1 u))))
+  (setq units (calcFunc-expand units))
+  (and (eq (car-safe units) '+)
+       (let ((entry (list units calc-internal-prec calc-prefer-frac)))
+	 (or (equal entry (car math-decompose-units-cache))
+	     (let ((ulist nil)
+		   (utemp units)
+		   qty unit)
+	       (while (eq (car-safe utemp) '+)
+		 (setq ulist (cons (math-decompose-unit-part (nth 2 utemp))
+				   ulist)
+		       utemp (nth 1 utemp)))
+	       (setq ulist (cons (math-decompose-unit-part utemp) ulist)
+		     utemp ulist)
+	       (while (setq utemp (cdr utemp))
+		 (or (equal (nth 2 (car utemp)) (nth 2 (car ulist)))
+		     (error "Inconsistent units in sum")))
+	       (setq math-decompose-units-cache
+		     (cons entry
+			   (sort ulist
+				 (function
+				  (lambda (x y)
+				    (not (Math-lessp (nth 1 x)
+						     (nth 1 y))))))))))
+	 (cdr math-decompose-units-cache)))
+)
+(setq math-decompose-units-cache nil)
+
+(defun math-decompose-unit-part (unit)
+  (cons unit
+	(math-is-multiple (math-simplify-units (math-to-standard-units
+						unit nil))
+			  t))
+)
+
+(defun math-find-compatible-unit (expr unit)
+  (let ((u (math-check-unit-name unit)))
+    (if u
+	(math-find-compatible-unit-rec expr 1)))
+)
+
+(defun math-find-compatible-unit-rec (expr pow)
+  (cond ((eq (car-safe expr) '*)
+	 (or (math-find-compatible-unit-rec (nth 1 expr) pow)
+	     (math-find-compatible-unit-rec (nth 2 expr) pow)))
+	((eq (car-safe expr) '/)
+	 (or (math-find-compatible-unit-rec (nth 1 expr) pow)
+	     (math-find-compatible-unit-rec (nth 2 expr) (- pow))))
+	((and (eq (car-safe expr) '^)
+	      (integerp (nth 2 expr)))
+	 (math-find-compatible-unit-rec (nth 1 expr) (* pow (nth 2 expr))))
+	(t
+	 (let ((u2 (math-check-unit-name expr)))
+	   (if (equal (nth 4 u) (nth 4 u2))
+	       (cons expr pow)))))
+)
+
+(defun math-convert-units (expr new-units &optional pure)
+  (math-with-extra-prec 2
+    (let ((compat (and (not pure) (math-find-compatible-unit expr new-units)))
+	  (unit-list nil)
+	  (math-combining-units nil))
+      (if compat
+	  (math-simplify-units
+	   (math-mul (math-mul (math-simplify-units
+				(math-div expr (math-pow (car compat)
+							 (cdr compat))))
+			       (math-pow new-units (cdr compat)))
+		     (math-simplify-units
+		      (math-to-standard-units
+		       (math-pow (math-div (car compat) new-units)
+				 (cdr compat))
+		       nil))))
+	(if (setq unit-list (math-decompose-units new-units))
+	    (setq new-units (nth 2 (car unit-list))))
+	(if (eq (car-safe expr) '+)
+	    (setq expr (math-simplify-units expr)))
+	(if (math-units-in-expr-p expr t)
+	    (math-convert-units-rec expr)
+	  (math-apply-units (math-to-standard-units
+			     (list '/ expr new-units) nil)
+			    new-units unit-list pure)))))
+)
+
+(defun math-convert-units-rec (expr)
+  (if (math-units-in-expr-p expr nil)
+      (math-apply-units (math-to-standard-units (list '/ expr new-units) nil)
+			new-units unit-list pure)
+    (if (Math-primp expr)
+	expr
+      (cons (car expr)
+	    (mapcar 'math-convert-units-rec (cdr expr)))))
+)
+
+(defun math-convert-temperature (expr old new &optional pure)
+  (let* ((units (math-single-units-in-expr-p expr))
+	 (uold (if old
+		   (if (or (null units)
+			   (equal (nth 1 old) (car units)))
+		       (math-check-unit-name old)
+		     (error "Inconsistent temperature units"))
+		 units))
+	 (unew (math-check-unit-name new)))
+    (or (and (consp unew) (nth 3 unew))
+	(error "Not a valid temperature unit"))
+    (or (and (consp uold) (nth 3 uold))
+	(error "Not a pure temperature expression"))
+    (let ((v (car uold)))
+      (setq expr (list '/ expr (list 'var v
+				     (intern (concat "var-"
+						     (symbol-name v)))))))
+    (or (eq (nth 3 uold) (nth 3 unew))
+	(cond ((eq (nth 3 uold) 'K)
+	       (setq expr (list '- expr '(float 27315 -2)))
+	       (if (eq (nth 3 unew) 'F)
+		   (setq expr (list '+ (list '* expr '(frac 9 5)) 32))))
+	      ((eq (nth 3 uold) 'C)
+	       (if (eq (nth 3 unew) 'F)
+		   (setq expr (list '+ (list '* expr '(frac 9 5)) 32))
+		 (setq expr (list '+ expr '(float 27315 -2)))))
+	      (t
+	       (setq expr (list '* (list '- expr 32) '(frac 5 9)))
+	       (if (eq (nth 3 unew) 'K)
+		   (setq expr (list '+ expr '(float 27315 -2)))))))
+    (if pure
+	expr
+      (list '* expr new)))
+)
+
+
+
+(defun math-simplify-units (a)
+  (let ((math-simplifying-units t)
+	(calc-matrix-mode 'scalar))
+    (math-simplify a))
+)
+(fset 'calcFunc-usimplify (symbol-function 'math-simplify-units))
+
+(math-defsimplify (+ -)
+  (and math-simplifying-units
+       (math-units-in-expr-p (nth 1 expr) nil)
+       (let* ((units (math-extract-units (nth 1 expr)))
+	      (ratio (math-simplify (math-to-standard-units
+				     (list '/ (nth 2 expr) units) nil))))
+	 (if (math-units-in-expr-p ratio nil)
+	     (progn
+	       (calc-record-why "*Inconsistent units" expr)
+	       expr)
+	   (list '* (math-add (math-remove-units (nth 1 expr))
+			      (if (eq (car expr) '-) (math-neg ratio) ratio))
+		 units))))
+)
+
+(math-defsimplify *
+  (math-simplify-units-prod)
+)
+
+(defun math-simplify-units-prod ()
+  (and math-simplifying-units
+       calc-autorange-units
+       (Math-realp (nth 1 expr))
+       (let* ((num (math-float (nth 1 expr)))
+	      (xpon (calcFunc-xpon num))
+	      (unitp (cdr (cdr expr)))
+	      (unit (car unitp))
+	      (pow (if (eq (car expr) '*) 1 -1))
+	      u)
+	 (and (eq (car-safe unit) '*)
+	      (setq unitp (cdr unit)
+		    unit (car unitp)))
+	 (and (eq (car-safe unit) '^)
+	      (integerp (nth 2 unit))
+	      (setq pow (* pow (nth 2 unit))
+		    unitp (cdr unit)
+		    unit (car unitp)))
+	 (and (setq u (math-check-unit-name unit))
+	      (integerp xpon)
+	      (or (< xpon 0)
+		  (>= xpon (if (eq (car u) 'm) 1 3)))
+	      (let* ((uxpon 0)
+		     (pref (if (< pow 0)
+			       (reverse math-unit-prefixes)
+			     math-unit-prefixes))
+		     (p pref)
+		     pxpon pname)
+		(or (eq (car u) (nth 1 unit))
+		    (setq uxpon (* pow
+				   (nth 2 (nth 1 (assq
+						  (aref (symbol-name
+							 (nth 1 unit)) 0)
+						  math-unit-prefixes))))))
+		(setq xpon (+ xpon uxpon))
+		(while (and p
+			    (or (memq (car (car p)) '(?d ?D ?h ?H))
+				(and (eq (car (car p)) ?c)
+				     (not (eq (car u) 'm)))
+				(< xpon (setq pxpon (* (nth 2 (nth 1 (car p)))
+						       pow)))
+				(progn
+				  (setq pname (math-build-var-name
+					       (if (eq (car (car p)) 0)
+						   (car u)
+						 (concat (char-to-string
+							  (car (car p)))
+							 (symbol-name
+							  (car u))))))
+				  (and (/= (car (car p)) 0)
+				       (assq (nth 1 pname)
+					     math-units-table)))))
+		  (setq p (cdr p)))
+		(and p
+		     (/= pxpon uxpon)
+		     (or (not (eq p pref))
+			 (< xpon (+ pxpon (* (math-abs pow) 3))))
+		     (progn
+		       (setcar (cdr expr)
+			       (let ((calc-prefer-frac nil))
+				 (calcFunc-scf (nth 1 expr)
+					       (- uxpon pxpon))))
+		       (setcar unitp pname)
+		       expr))))))
+)
+
+(math-defsimplify /
+  (and math-simplifying-units
+       (let ((np (cdr expr))
+	     (try-cancel-units 0)
+	     n nn)
+	 (setq n (if (eq (car-safe (nth 2 expr)) '*)
+		     (cdr (nth 2 expr))
+		   (nthcdr 2 expr)))
+	 (if (math-realp (car n))
+	     (progn
+	       (setcar (cdr expr) (math-mul (nth 1 expr)
+					    (let ((calc-prefer-frac nil))
+					      (math-div 1 (car n)))))
+	       (setcar n 1)))
+	 (while (eq (car-safe (setq n (car np))) '*)
+	   (math-simplify-units-divisor (cdr n) (cdr (cdr expr)))
+	   (setq np (cdr (cdr n))))
+	 (math-simplify-units-divisor np (cdr (cdr expr)))
+	 (if (eq try-cancel-units 0)
+	     (let* ((math-simplifying-units nil)
+		    (base (math-simplify (math-to-standard-units expr nil))))
+	       (if (Math-numberp base)
+		   (setq expr base))))
+	 (if (eq (car-safe expr) '/)
+	     (math-simplify-units-prod))
+	 expr))
+)
+
+(defun math-simplify-units-divisor (np dp)
+  (let ((n (car np))
+	d dd temp)
+    (while (eq (car-safe (setq d (car dp))) '*)
+      (if (setq temp (math-simplify-units-quotient n (nth 1 d)))
+	  (progn
+	    (setcar np (setq n temp))
+	    (setcar (cdr d) 1)))
+      (setq dp (cdr (cdr d))))
+    (if (setq temp (math-simplify-units-quotient n d))
+	(progn
+	  (setcar np (setq n temp))
+	  (setcar dp 1))))
+)
+
+;; Simplify, e.g., "in / cm" to "2.54" in a units expression.
+(defun math-simplify-units-quotient (n d)
+  (let ((pow1 1)
+	(pow2 1))
+    (and (eq (car-safe n) '^)
+	 (integerp (nth 2 n))
+	 (setq pow1 (nth 2 n) n (nth 1 n)))
+    (and (eq (car-safe d) '^)
+	 (integerp (nth 2 d))
+	 (setq pow2 (nth 2 d) d (nth 1 d)))
+    (let ((un (math-check-unit-name n))
+	  (ud (math-check-unit-name d)))
+      (and un ud
+	   (if (and (equal (nth 4 un) (nth 4 ud))
+		    (eq pow1 pow2))
+	       (math-to-standard-units (list '/ n d) nil)
+	     (let (ud1)
+	       (setq un (nth 4 un)
+		     ud (nth 4 ud))
+	       (while un
+		 (setq ud1 ud)
+		 (while ud1
+		   (and (eq (car (car un)) (car (car ud1)))
+			(setq try-cancel-units
+			      (+ try-cancel-units
+				 (- (* (cdr (car un)) pow1)
+				    (* (cdr (car ud)) pow2)))))
+		   (setq ud1 (cdr ud1)))
+		 (setq un (cdr un)))
+	       nil)))))
+)
+
+(math-defsimplify ^
+  (and math-simplifying-units
+       (math-realp (nth 2 expr))
+       (if (memq (car-safe (nth 1 expr)) '(* /))
+	   (list (car (nth 1 expr))
+		 (list '^ (nth 1 (nth 1 expr)) (nth 2 expr))
+		 (list '^ (nth 2 (nth 1 expr)) (nth 2 expr)))
+	 (math-simplify-units-pow (nth 1 expr) (nth 2 expr))))
+)
+
+(math-defsimplify calcFunc-sqrt
+  (and math-simplifying-units
+       (if (memq (car-safe (nth 1 expr)) '(* /))
+	   (list (car (nth 1 expr))
+		 (list 'calcFunc-sqrt (nth 1 (nth 1 expr)))
+		 (list 'calcFunc-sqrt (nth 2 (nth 1 expr))))
+	 (math-simplify-units-pow (nth 1 expr) '(frac 1 2))))
+)
+
+(math-defsimplify (calcFunc-floor
+		   calcFunc-ceil
+		   calcFunc-round
+		   calcFunc-rounde
+		   calcFunc-roundu
+		   calcFunc-trunc
+		   calcFunc-float
+		   calcFunc-frac
+		   calcFunc-abs
+		   calcFunc-clean)
+  (and math-simplifying-units
+       (= (length expr) 2)
+       (if (math-only-units-in-expr-p (nth 1 expr))
+	   (nth 1 expr)
+	 (if (and (memq (car-safe (nth 1 expr)) '(* /))
+		  (or (math-only-units-in-expr-p
+		       (nth 1 (nth 1 expr)))
+		      (math-only-units-in-expr-p
+		       (nth 2 (nth 1 expr)))))
+	     (list (car (nth 1 expr))
+		   (cons (car expr)
+			 (cons (nth 1 (nth 1 expr))
+			       (cdr (cdr expr))))
+		   (cons (car expr)
+			 (cons (nth 2 (nth 1 expr))
+			       (cdr (cdr expr)))))))))
+
+(defun math-simplify-units-pow (a pow)
+  (if (and (eq (car-safe a) '^)
+	   (math-check-unit-name (nth 1 a))
+	   (math-realp (nth 2 a)))
+      (list '^ (nth 1 a) (math-mul pow (nth 2 a)))
+    (let* ((u (math-check-unit-name a))
+	   (pf (math-to-simple-fraction pow))
+	   (d (and (eq (car-safe pf) 'frac) (nth 2 pf))))
+      (and u d
+	   (math-units-are-multiple u d)
+	   (list '^ (math-to-standard-units a nil) pow))))
+)
+
+
+(defun math-units-are-multiple (u n)
+  (setq u (nth 4 u))
+  (while (and u (= (% (cdr (car u)) n) 0))
+    (setq u (cdr u)))
+  (null u)
+)
+
+(math-defsimplify calcFunc-sin
+  (and math-simplifying-units
+       (math-units-in-expr-p (nth 1 expr) nil)
+       (let ((rad (math-simplify-units
+		   (math-evaluate-expr
+		    (math-to-standard-units (nth 1 expr) nil))))
+	     (calc-angle-mode 'rad))
+	 (and (eq (car-safe rad) '*)
+	      (math-realp (nth 1 rad))
+	      (eq (car-safe (nth 2 rad)) 'var)
+	      (eq (nth 1 (nth 2 rad)) 'rad)
+	      (list 'calcFunc-sin (nth 1 rad)))))
+)
+
+(math-defsimplify calcFunc-cos
+  (and math-simplifying-units
+       (math-units-in-expr-p (nth 1 expr) nil)
+       (let ((rad (math-simplify-units
+		   (math-evaluate-expr
+		    (math-to-standard-units (nth 1 expr) nil))))
+	     (calc-angle-mode 'rad))
+	 (and (eq (car-safe rad) '*)
+	      (math-realp (nth 1 rad))
+	      (eq (car-safe (nth 2 rad)) 'var)
+	      (eq (nth 1 (nth 2 rad)) 'rad)
+	      (list 'calcFunc-cos (nth 1 rad)))))
+)
+
+(math-defsimplify calcFunc-tan
+  (and math-simplifying-units
+       (math-units-in-expr-p (nth 1 expr) nil)
+       (let ((rad (math-simplify-units
+		   (math-evaluate-expr
+		    (math-to-standard-units (nth 1 expr) nil))))
+	     (calc-angle-mode 'rad))
+	 (and (eq (car-safe rad) '*)
+	      (math-realp (nth 1 rad))
+	      (eq (car-safe (nth 2 rad)) 'var)
+	      (eq (nth 1 (nth 2 rad)) 'rad)
+	      (list 'calcFunc-tan (nth 1 rad)))))
+)
+
+
+(defun math-remove-units (expr)
+  (if (math-check-unit-name expr)
+      1
+    (if (Math-primp expr)
+	expr
+      (cons (car expr)
+	    (mapcar 'math-remove-units (cdr expr)))))
+)
+
+(defun math-extract-units (expr)
+  (if (memq (car-safe expr) '(* /))
+      (cons (car expr)
+	    (mapcar 'math-extract-units (cdr expr)))
+    (if (math-check-unit-name expr) expr 1))
+)
+
+(defun math-build-units-table-buffer (enter-buffer)
+  (if (not (and math-units-table math-units-table-buffer-valid
+		(get-buffer "*Units Table*")))
+      (let ((buf (get-buffer-create "*Units Table*"))
+	    (uptr (math-build-units-table))
+	    (calc-language (if (eq calc-language 'big) nil calc-language))
+	    (calc-float-format '(float 0))
+	    (calc-group-digits nil)
+	    (calc-number-radix 10)
+	    (calc-point-char ".")
+	    (std nil)
+	    u name shadowed)
+	(save-excursion
+	  (message "Formatting units table...")
+	  (set-buffer buf)
+	  (setq buffer-read-only nil)
+	  (erase-buffer)
+	  (insert "Calculator Units Table:\n\n")
+	  (insert "Unit    Type  Definition                  Description\n\n")
+	  (while uptr
+	    (setq u (car uptr)
+		  name (nth 2 u))
+	    (if (eq (car u) 'm)
+		(setq std t))
+	    (setq shadowed (and std (assq (car u) math-additional-units)))
+	    (if (and name
+		     (> (length name) 1)
+		     (eq (aref name 0) ?\*))
+		(progn
+		  (or (eq uptr math-units-table)
+		      (insert "\n"))
+		  (setq name (substring name 1))))
+	    (insert " ")
+	    (and shadowed (insert "("))
+	    (insert (symbol-name (car u)))
+	    (and shadowed (insert ")"))
+	    (if (nth 3 u)
+		(progn
+		  (indent-to 10)
+		  (insert (symbol-name (nth 3 u))))
+	      (or std
+		  (progn
+		    (indent-to 10)
+		    (insert "U"))))
+	    (indent-to 14)
+	    (and shadowed (insert "("))
+	    (if (nth 1 u)
+		(insert (math-format-value (nth 1 u) 80))
+	      (insert (symbol-name (car u))))
+	    (and shadowed (insert ")"))
+	    (indent-to 41)
+	    (insert " ")
+	    (if name
+		(insert name))
+	    (if shadowed
+		(insert " (redefined above)")
+	      (or (nth 1 u)
+		  (insert " (base unit)")))
+	    (insert "\n")
+	    (setq uptr (cdr uptr)))
+	  (insert "\n\nUnit Prefix Table:\n\n")
+	  (setq uptr math-unit-prefixes)
+	  (while uptr
+	    (setq u (car uptr))
+	    (insert " " (char-to-string (car u)))
+	    (if (equal (nth 1 u) (nth 1 (nth 1 uptr)))
+		(insert " " (char-to-string (car (car (setq uptr (cdr uptr)))))
+			"   ")
+	      (insert "     "))
+	    (insert "10^" (int-to-string (nth 2 (nth 1 u))))
+	    (indent-to 15)
+	    (insert "   " (nth 2 u) "\n")
+	    (while (eq (car (car (setq uptr (cdr uptr)))) 0)))
+	  (insert "\n")
+	  (setq buffer-read-only t)
+	  (message "Formatting units table...done"))
+	(setq math-units-table-buffer-valid t)
+	(let ((oldbuf (current-buffer)))
+	  (set-buffer buf)
+	  (goto-char (point-min))
+	  (set-buffer oldbuf))
+	(if enter-buffer
+	    (pop-to-buffer buf)
+	  (display-buffer buf)))
+    (if enter-buffer
+	(pop-to-buffer (get-buffer "*Units Table*"))
+      (display-buffer (get-buffer "*Units Table*"))))
+)
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/calc-vec.el	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,1698 @@
+;; Calculator for GNU Emacs, part II [calc-vec.el]
+;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+;; Written by Dave Gillespie, daveg@synaptics.com.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY.  No author or distributor
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing.  Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License.   A copy of this license is
+;; supposed to have been given to you along with GNU Emacs so you
+;; can know your rights and responsibilities.  It should be in a
+;; file named COPYING.  Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+
+
+
+;; This file is autoloaded from calc-ext.el.
+(require 'calc-ext)
+
+(require 'calc-macs)
+
+(defun calc-Need-calc-vec () nil)
+
+
+(defun calc-display-strings (n)
+  (interactive "P")
+  (calc-wrapper
+   (message (if (calc-change-mode 'calc-display-strings n t t)
+		"Displaying vectors of integers as quoted strings."
+	      "Displaying vectors of integers normally.")))
+)
+
+
+(defun calc-pack (n)
+  (interactive "P")
+  (calc-wrapper
+   (let* ((nn (if n 1 2))
+	  (mode (if n (prefix-numeric-value n) (calc-top-n 1)))
+	  (mode (if (and (Math-vectorp mode) (cdr mode)) (cdr mode)
+		  (if (integerp mode) mode
+		    (error "Packing mode must be an integer or vector of integers"))))
+	  (num (calc-pack-size mode))
+	  (items (calc-top-list num nn)))
+     (calc-enter-result (+ nn num -1) "pack" (calc-pack-items mode items))))
+)
+
+(defun calc-pack-size (mode)
+  (cond ((consp mode)
+	 (let ((size 1))
+	   (while mode
+	     (or (integerp (car mode)) (error "Vector of integers expected"))
+	     (setq size (* size (calc-pack-size (car mode)))
+		   mode (cdr mode)))
+	   (if (= size 0)
+	       (error "Zero dimensions not allowed")
+	     size)))
+	((>= mode 0) mode)
+	(t (or (cdr (assq mode '((-3 . 3) (-13 . 1) (-14 . 3) (-15 . 6))))
+	       2)))
+)
+
+(defun calc-pack-items (mode items)
+  (cond ((consp mode)
+	 (if (cdr mode)
+	     (let* ((size (calc-pack-size (cdr mode)))
+		    (len (length items))
+		    (new nil)
+		    p row)
+	       (while (> len 0)
+		 (setq p (nthcdr (1- size) items)
+		       row items
+		       items (cdr p)
+		       len (- len size))
+		 (setcdr p nil)
+		 (setq new (cons (calc-pack-items (cdr mode) row) new)))
+	       (calc-pack-items (car mode) (nreverse new)))
+	   (calc-pack-items (car mode) items)))
+	((>= mode 0)
+	 (cons 'vec items))
+	((= mode -3)
+	 (if (and (math-objvecp (car items))
+		  (math-objvecp (nth 1 items))
+		  (math-objvecp (nth 2 items)))
+	     (if (and (math-num-integerp (car items))
+		      (math-num-integerp (nth 1 items)))
+		 (if (math-realp (nth 2 items))
+		     (cons 'hms items)
+		   (error "Seconds must be real"))
+	       (error "Hours and minutes must be integers"))
+	   (math-normalize (list '+
+				 (list '+
+				       (if (eq calc-angle-mode 'rad)
+					   (list '* (car items)
+						 '(hms 1 0 0))
+					 (car items))
+				       (list '* (nth 1 items) '(hms 0 1 0)))
+				 (list '* (nth 2 items) '(hms 0 0 1))))))
+	((= mode -13)
+	 (if (math-realp (car items))
+	     (cons 'date items)
+	   (if (eq (car-safe (car items)) 'date)
+	       (car items)
+	     (if (math-objvecp (car items))
+		 (error "Date value must be real")
+	       (cons 'calcFunc-date items)))))
+	((memq mode '(-14 -15))
+	 (let ((p items))
+	   (while (and p (math-objvecp (car p)))
+	     (or (math-integerp (car p))
+		 (error "Components must be integers"))
+	     (setq p (cdr p)))
+	   (if p
+	       (cons 'calcFunc-date items)
+	     (list 'date (math-dt-to-date items)))))
+	((or (eq (car-safe (car items)) 'vec)
+	     (eq (car-safe (nth 1 items)) 'vec))
+	 (let* ((x (car items))
+		(vx (eq (car-safe x) 'vec))
+		(y (nth 1 items))
+		(vy (eq (car-safe y) 'vec))
+		(z nil)
+		(n (1- (length (if vx x y)))))
+	   (and vx vy
+		(/= n (1- (length y)))
+		(error "Vectors must be the same length"))
+	   (while (>= (setq n (1- n)) 0)
+	     (setq z (cons (calc-pack-items
+			    mode
+			    (list (if vx (car (setq x (cdr x))) x)
+				  (if vy (car (setq y (cdr y))) y)))
+			   z)))
+	   (cons 'vec (nreverse z))))
+	((= mode -1)
+	 (if (and (math-realp (car items)) (math-realp (nth 1 items)))
+	     (cons 'cplx items)
+	   (if (and (math-objectp (car items)) (math-objectp (nth 1 items)))
+	       (error "Components must be real"))
+	   (math-normalize (list '+ (car items)
+				 (list '* (nth 1 items) '(cplx 0 1))))))
+	((= mode -2)
+	 (if (and (math-realp (car items)) (math-anglep (nth 1 items)))
+	     (cons 'polar items)
+	   (if (and (math-objectp (car items)) (math-objectp (nth 1 items)))
+	       (error "Components must be real"))
+	   (math-normalize (list '* (car items)
+				 (if (math-anglep (nth 1 items))
+				     (list 'polar 1 (nth 1 items))
+				   (list 'calcFunc-exp
+					 (list '*
+					       (math-to-radians-2
+						(nth 1 items))
+					       (list 'polar
+						     1
+						     (math-quarter-circle
+						      nil)))))))))
+	((= mode -4)
+	 (let ((x (car items))
+	       (sigma (nth 1 items)))
+	   (if (or (math-scalarp x) (not (math-objvecp x)))
+	       (if (or (math-anglep sigma) (not (math-objvecp sigma)))
+		   (math-make-sdev x sigma)
+		 (error "Error component must be real"))
+	     (error "Mean component must be real or complex"))))
+	((= mode -5)
+	 (let ((a (car items))
+	       (m (nth 1 items)))
+	   (if (and (math-anglep a) (math-anglep m))
+	       (if (math-posp m)
+		   (math-make-mod a m)
+		 (error "Modulus must be positive"))
+	     (if (and (math-objectp a) (math-objectp m))
+		 (error "Components must be real"))
+	     (list 'calcFunc-makemod a m))))
+	((memq mode '(-6 -7 -8 -9))
+	 (let ((lo (car items))
+	       (hi (nth 1 items)))
+	   (if (and (or (math-anglep lo) (eq (car lo) 'date)
+			(not (math-objvecp lo)))
+		    (or (math-anglep hi) (eq (car hi) 'date)
+			(not (math-objvecp hi))))
+	       (math-make-intv (+ mode 9) lo hi)
+	     (error "Components must be real"))))
+	((eq mode -10)
+	 (if (math-zerop (nth 1 items))
+	     (error "Denominator must not be zero")
+	   (if (and (math-integerp (car items)) (math-integerp (nth 1 items)))
+	       (math-normalize (cons 'frac items))
+	     (if (and (math-objectp (car items)) (math-objectp (nth 1 items)))
+		 (error "Components must be integers"))
+	     (cons 'calcFunc-fdiv items))))
+	((memq mode '(-11 -12))
+	 (if (and (math-realp (car items)) (math-integerp (nth 1 items)))
+	     (calcFunc-scf (math-float (car items)) (nth 1 items))
+	   (if (and (math-objectp (car items)) (math-objectp (nth 1 items)))
+	       (error "Components must be integers"))
+	   (math-normalize
+	    (list 'calcFunc-scf
+		  (list 'calcFunc-float (car items))
+		  (nth 1 items)))))
+	(t
+	 (error "Invalid packing mode: %d" mode)))
+)
+
+(defun calc-unpack (mode)
+  (interactive "P")
+  (calc-wrapper
+   (let ((calc-unpack-with-type t))
+     (calc-pop-push-record-list 1 "unpk" (calc-unpack-item
+					  (and mode
+					       (prefix-numeric-value mode))
+					  (calc-top)))))
+)
+
+(defun calc-unpack-type (item)
+  (cond ((eq (car-safe item) 'vec)
+	 (1- (length item)))
+	((eq (car-safe item) 'intv)
+	 (- (nth 1 item) 9))
+	(t
+	 (or (cdr (assq (car-safe item) '( (cplx . -1) (polar . -2)
+					   (hms . -3) (sdev . -4) (mod . -5)
+					   (frac . -10) (float . -11)
+					   (date . -13) )))
+	     (error "Argument must be a composite object"))))
+)
+
+(defun calc-unpack-item (mode item)
+  (cond ((not mode)
+	 (if (or (and (not (memq (car-safe item) '(frac float cplx polar vec
+							hms date sdev mod
+							intv)))
+		      (math-objvecp item))
+		 (eq (car-safe item) 'var))
+	     (error "Argument must be a composite object or function call"))
+	 (if (eq (car item) 'intv)
+	     (cdr (cdr item))
+	   (cdr item)))
+	((> mode 0)
+	 (let ((dims nil)
+	       type new row)
+	   (setq item (list item))
+	   (while (> mode 0)
+	     (setq type (calc-unpack-type (car item))
+		   dims (cons type dims)
+		   new (calc-unpack-item nil (car item)))
+	     (while (setq item (cdr item))
+	       (or (= (calc-unpack-type (car item)) type)
+		   (error "Inconsistent types or dimensions in vector elements"))
+	       (setq new (append new (calc-unpack-item nil (car item)))))
+	     (setq item new
+		   mode (1- mode)))
+	   (if (cdr dims) (setq dims (list (cons 'vec (nreverse dims)))))
+	   (cond ((eq calc-unpack-with-type 'pair)
+		  (list (car dims) (cons 'vec item)))
+		 (calc-unpack-with-type
+		  (append item dims))
+		 (t item))))
+	((eq calc-unpack-with-type 'pair)
+	 (let ((calc-unpack-with-type nil))
+	   (list mode (cons 'vec (calc-unpack-item mode item)))))
+	((= mode -3)
+	 (if (eq (car-safe item) 'hms)
+	     (cdr item)
+	   (error "Argument must be an HMS form")))
+	((= mode -13)
+	 (if (eq (car-safe item) 'date)
+	     (cdr item)
+	   (error "Argument must be a date form")))
+	((= mode -14)
+	 (if (eq (car-safe item) 'date)
+	     (math-date-to-dt (math-floor (nth 1 item)))
+	   (error "Argument must be a date form")))
+	((= mode -15)
+	 (if (eq (car-safe item) 'date)
+	     (append (math-date-to-dt (nth 1 item))
+		     (and (not (math-integerp (nth 1 item)))
+			  (list 0 0 0)))
+	   (error "Argument must be a date form")))
+	((eq (car-safe item) 'vec)
+	 (let ((x nil)
+	       (y nil)
+	       res)
+	   (while (setq item (cdr item))
+	     (setq res (calc-unpack-item mode (car item))
+		   x (cons (car res) x)
+		   y (cons (nth 1 res) y)))
+	   (list (cons 'vec (nreverse x))
+		 (cons 'vec (nreverse y)))))
+	((= mode -1)
+	 (if (eq (car-safe item) 'cplx)
+	     (cdr item)
+	   (if (eq (car-safe item) 'polar)
+	       (cdr (math-complex item))
+	     (if (Math-realp item)
+		 (list item 0)
+	       (error "Argument must be a complex number")))))
+	((= mode -2)
+	 (if (or (memq (car-safe item) '(cplx polar))
+		 (Math-realp item))
+	     (cdr (math-polar item))
+	   (error "Argument must be a complex number")))
+	((= mode -4)
+	 (if (eq (car-safe item) 'sdev)
+	     (cdr item)
+	   (list item 0)))
+	((= mode -5)
+	 (if (eq (car-safe item) 'mod)
+	     (cdr item)
+	   (error "Argument must be a modulo form")))
+	((memq mode '(-6 -7 -8 -9))
+	 (if (eq (car-safe item) 'intv)
+	     (cdr (cdr item))
+	   (list item item)))
+	((= mode -10)
+	 (if (eq (car-safe item) 'frac)
+	     (cdr item)
+	   (if (Math-integerp item)
+	       (list item 1)
+	     (error "Argument must be a rational number"))))
+	((= mode -11)
+	 (if (eq (car-safe item) 'float)
+	     (list (nth 1 item) (math-normalize (nth 2 item)))
+	   (error "Expected a floating-point number")))
+	((= mode -12)
+	 (if (eq (car-safe item) 'float)
+	     (list (calcFunc-mant item) (calcFunc-xpon item))
+	   (error "Expected a floating-point number")))
+	(t
+	 (error "Invalid unpacking mode: %d" mode)))
+)
+(setq calc-unpack-with-type nil)
+
+(defun calc-diag (n)
+  (interactive "P")
+  (calc-wrapper
+   (calc-enter-result 1 "diag" (if n
+				   (list 'calcFunc-diag (calc-top-n 1)
+					 (prefix-numeric-value n))
+				 (list 'calcFunc-diag (calc-top-n 1)))))
+)
+
+(defun calc-ident (n)
+  (interactive "NDimension of identity matrix = ")
+  (calc-wrapper
+   (calc-enter-result 0 "idn" (if (eq n 0)
+				  '(calcFunc-idn 1)
+				(list 'calcFunc-idn 1
+				      (prefix-numeric-value n)))))
+)
+
+(defun calc-index (n &optional stack)
+  (interactive "NSize of vector = \nP")
+  (calc-wrapper
+   (if (consp stack)
+       (calc-enter-result 3 "indx" (cons 'calcFunc-index (calc-top-list-n 3)))
+     (calc-enter-result 0 "indx" (list 'calcFunc-index
+				       (prefix-numeric-value n)))))
+)
+
+(defun calc-build-vector (n)
+  (interactive "NSize of vector = ")
+  (calc-wrapper
+   (calc-enter-result 1 "bldv" (list 'calcFunc-cvec
+				     (calc-top-n 1)
+				     (prefix-numeric-value n))))
+)
+
+(defun calc-cons (arg)
+  (interactive "P")
+  (calc-wrapper
+   (if (calc-is-hyperbolic)
+       (calc-binary-op "rcns" 'calcFunc-rcons arg)
+     (calc-binary-op "cons" 'calcFunc-cons arg)))
+)
+
+
+(defun calc-head (arg)
+  (interactive "P")
+  (calc-wrapper
+   (if (calc-is-inverse)
+       (if (calc-is-hyperbolic)
+	   (calc-unary-op "rtai" 'calcFunc-rtail arg)
+	 (calc-unary-op "tail" 'calcFunc-tail arg))
+     (if (calc-is-hyperbolic)
+	 (calc-unary-op "rhed" 'calcFunc-rhead arg)
+       (calc-unary-op "head" 'calcFunc-head arg))))
+)
+
+(defun calc-tail (arg)
+  (interactive "P")
+  (calc-invert-func)
+  (calc-head arg)
+)
+
+(defun calc-vlength (arg)
+  (interactive "P")
+  (calc-wrapper
+   (if (calc-is-hyperbolic)
+       (calc-unary-op "dims" 'calcFunc-mdims arg)
+     (calc-unary-op "len" 'calcFunc-vlen arg)))
+)
+
+(defun calc-arrange-vector (n)
+  (interactive "NNumber of columns = ")
+  (calc-wrapper
+   (calc-enter-result 1 "arng" (list 'calcFunc-arrange (calc-top-n 1)
+				     (prefix-numeric-value n))))
+)
+
+(defun calc-vector-find (arg)
+  (interactive "P")
+  (calc-wrapper
+   (let ((func (cons 'calcFunc-find (calc-top-list-n 2))))
+     (calc-enter-result
+      2 "find"
+      (if arg (append func (list (prefix-numeric-value arg))) func))))
+)
+
+(defun calc-subvector ()
+  (interactive)
+  (calc-wrapper
+   (if (calc-is-inverse)
+       (calc-enter-result 3 "rsvc" (cons 'calcFunc-rsubvec
+					 (calc-top-list-n 3)))
+     (calc-enter-result 3 "svec" (cons 'calcFunc-subvec (calc-top-list-n 3)))))
+)
+
+(defun calc-reverse-vector (arg)
+  (interactive "P")
+  (calc-wrapper
+   (calc-unary-op "rev" 'calcFunc-rev arg))
+)
+
+(defun calc-mask-vector (arg)
+  (interactive "P")
+  (calc-wrapper
+   (calc-binary-op "vmsk" 'calcFunc-vmask arg))
+)
+
+(defun calc-expand-vector (arg)
+  (interactive "P")
+  (calc-wrapper
+   (if (calc-is-hyperbolic)
+       (calc-enter-result 3 "vexp" (cons 'calcFunc-vexp (calc-top-list-n 3)))
+     (calc-binary-op "vexp" 'calcFunc-vexp arg)))
+)
+
+(defun calc-sort ()
+  (interactive)
+  (calc-slow-wrapper
+   (if (calc-is-inverse)
+       (calc-enter-result 1 "rsrt" (list 'calcFunc-rsort (calc-top-n 1)))
+     (calc-enter-result 1 "sort" (list 'calcFunc-sort (calc-top-n 1)))))
+)
+
+(defun calc-grade ()
+  (interactive)
+  (calc-slow-wrapper
+   (if (calc-is-inverse)
+       (calc-enter-result 1 "rgrd" (list 'calcFunc-rgrade (calc-top-n 1)))
+     (calc-enter-result 1 "grad" (list 'calcFunc-grade (calc-top-n 1)))))
+)
+
+(defun calc-histogram (n)
+  (interactive "NNumber of bins: ")
+  (calc-slow-wrapper
+   (if calc-hyperbolic-flag
+       (calc-enter-result 2 "hist" (list 'calcFunc-histogram
+					 (calc-top-n 2)
+					 (calc-top-n 1)
+					 (prefix-numeric-value n)))
+     (calc-enter-result 1 "hist" (list 'calcFunc-histogram
+				       (calc-top-n 1)
+				       (prefix-numeric-value n)))))
+)
+
+(defun calc-transpose (arg)
+  (interactive "P")
+  (calc-wrapper
+   (calc-unary-op "trn" 'calcFunc-trn arg))
+)
+
+(defun calc-conj-transpose (arg)
+  (interactive "P")
+  (calc-wrapper
+   (calc-unary-op "ctrn" 'calcFunc-ctrn arg))
+)
+
+(defun calc-cross (arg)
+  (interactive "P")
+  (calc-wrapper
+   (calc-binary-op "cros" 'calcFunc-cross arg))
+)
+
+(defun calc-remove-duplicates (arg)
+  (interactive "P")
+  (calc-wrapper
+   (calc-unary-op "rdup" 'calcFunc-rdup arg))
+)
+
+(defun calc-set-union (arg)
+  (interactive "P")
+  (calc-wrapper
+   (calc-binary-op "unio" 'calcFunc-vunion arg '(vec) 'calcFunc-rdup))
+)
+
+(defun calc-set-intersect (arg)
+  (interactive "P")
+  (calc-wrapper
+   (calc-binary-op "intr" 'calcFunc-vint arg '(vec) 'calcFunc-rdup))
+)
+
+(defun calc-set-difference (arg)
+  (interactive "P")
+  (calc-wrapper
+   (calc-binary-op "diff" 'calcFunc-vdiff arg '(vec) 'calcFunc-rdup))
+)
+
+(defun calc-set-xor (arg)
+  (interactive "P")
+  (calc-wrapper
+   (calc-binary-op "xor" 'calcFunc-vxor arg '(vec) 'calcFunc-rdup))
+)
+
+(defun calc-set-complement (arg)
+  (interactive "P")
+  (calc-wrapper
+   (calc-unary-op "cmpl" 'calcFunc-vcompl arg))
+)
+
+(defun calc-set-floor (arg)
+  (interactive "P")
+  (calc-wrapper
+   (calc-unary-op "vflr" 'calcFunc-vfloor arg))
+)
+
+(defun calc-set-enumerate (arg)
+  (interactive "P")
+  (calc-wrapper
+   (calc-unary-op "enum" 'calcFunc-venum arg))
+)
+
+(defun calc-set-span (arg)
+  (interactive "P")
+  (calc-wrapper
+   (calc-unary-op "span" 'calcFunc-vspan arg))
+)
+
+(defun calc-set-cardinality (arg)
+  (interactive "P")
+  (calc-wrapper
+   (calc-unary-op "card" 'calcFunc-vcard arg))
+)
+
+(defun calc-unpack-bits (arg)
+  (interactive "P")
+  (calc-wrapper
+   (if (calc-is-inverse)
+       (calc-unary-op "bpck" 'calcFunc-vpack arg)
+     (calc-unary-op "bupk" 'calcFunc-vunpack arg)))
+)
+
+(defun calc-pack-bits (arg)
+  (interactive "P")
+  (calc-invert-func)
+  (calc-unpack-bits arg)
+)
+
+
+(defun calc-rnorm (arg)
+  (interactive "P")
+  (calc-wrapper
+   (calc-unary-op "rnrm" 'calcFunc-rnorm arg))
+)
+
+(defun calc-cnorm (arg)
+  (interactive "P")
+  (calc-wrapper
+   (calc-unary-op "cnrm" 'calcFunc-cnorm arg))
+)
+
+(defun calc-mrow (n &optional nn)
+  (interactive "NRow number: \nP")
+  (calc-wrapper
+   (if (consp nn)
+       (calc-enter-result 2 "mrow" (cons 'calcFunc-mrow (calc-top-list-n 2)))
+     (setq n (prefix-numeric-value n))
+     (if (= n 0)
+	 (calc-enter-result 1 "getd" (list 'calcFunc-getdiag (calc-top-n 1)))
+       (if (< n 0)
+	   (calc-enter-result 1 "rrow" (list 'calcFunc-mrrow
+					     (calc-top-n 1) (- n)))
+	 (calc-enter-result 1 "mrow" (list 'calcFunc-mrow
+					   (calc-top-n 1) n))))))
+)
+
+(defun calc-mcol (n &optional nn)
+  (interactive "NColumn number: \nP")
+  (calc-wrapper
+   (if (consp nn)
+       (calc-enter-result 2 "mcol" (cons 'calcFunc-mcol (calc-top-list-n 2)))
+     (setq n (prefix-numeric-value n))
+     (if (= n 0)
+	 (calc-enter-result 1 "getd" (list 'calcFunc-getdiag (calc-top-n 1)))
+       (if (< n 0)
+	   (calc-enter-result 1 "rcol" (list 'calcFunc-mrcol
+					     (calc-top-n 1) (- n)))
+	 (calc-enter-result 1 "mcol" (list 'calcFunc-mcol
+					   (calc-top-n 1) n))))))
+)
+
+
+;;;; Vectors.
+
+(defun calcFunc-mdims (m)
+  (or (math-vectorp m)
+      (math-reject-arg m 'vectorp))
+  (cons 'vec (math-mat-dimens m))
+)
+
+
+;;; Apply a function elementwise to vector A.  [V X V; N X N] [Public]
+(defun math-map-vec (f a)
+  (if (math-vectorp a)
+      (cons 'vec (mapcar f (cdr a)))
+    (funcall f a))
+)
+
+(defun math-dimension-error ()
+  (calc-record-why "*Dimension error")
+  (signal 'wrong-type-argument nil)
+)
+
+
+;;; Build a vector out of a list of objects.  [Public]
+(defun calcFunc-vec (&rest objs)
+  (cons 'vec objs)
+)
+
+
+;;; Build a constant vector or matrix.  [Public]
+(defun calcFunc-cvec (obj &rest dims)
+  (math-make-vec-dimen obj dims)
+)
+
+(defun math-make-vec-dimen (obj dims)
+  (if dims
+      (if (natnump (car dims))
+	  (if (or (cdr dims)
+		  (not (math-numberp obj)))
+	      (cons 'vec (copy-sequence
+			  (make-list (car dims)
+				     (math-make-vec-dimen obj (cdr dims)))))
+	    (cons 'vec (make-list (car dims) obj)))
+	(math-reject-arg (car dims) 'fixnatnump))
+    obj)
+)
+
+(defun calcFunc-head (vec)
+  (if (and (Math-vectorp vec)
+	   (cdr vec))
+      (nth 1 vec)
+    (calc-record-why 'vectorp vec)
+    (list 'calcFunc-head vec))
+)
+
+(defun calcFunc-tail (vec)
+  (if (and (Math-vectorp vec)
+	   (cdr vec))
+      (cons 'vec (cdr (cdr vec)))
+    (calc-record-why 'vectorp vec)
+    (list 'calcFunc-tail vec))
+)
+
+(defun calcFunc-cons (head tail)
+  (if (Math-vectorp tail)
+      (cons 'vec (cons head (cdr tail)))
+    (calc-record-why 'vectorp tail)
+    (list 'calcFunc-cons head tail))
+)
+
+(defun calcFunc-rhead (vec)
+  (if (and (Math-vectorp vec)
+	   (cdr vec))
+      (let ((vec (copy-sequence vec)))
+	(setcdr (nthcdr (- (length vec) 2) vec) nil)
+	vec)
+    (calc-record-why 'vectorp vec)
+    (list 'calcFunc-rhead vec))
+)
+
+(defun calcFunc-rtail (vec)
+  (if (and (Math-vectorp vec)
+	   (cdr vec))
+      (nth (1- (length vec)) vec)
+    (calc-record-why 'vectorp vec)
+    (list 'calcFunc-rtail vec))
+)
+
+(defun calcFunc-rcons (head tail)
+  (if (Math-vectorp head)
+      (append head (list tail))
+    (calc-record-why 'vectorp head)
+    (list 'calcFunc-rcons head tail))
+)
+
+
+
+;;; Apply a function elementwise to vectors A and B.  [O X O O] [Public]
+(defun math-map-vec-2 (f a b)
+  (if (math-vectorp a)
+      (if (math-vectorp b)
+	  (let ((v nil))
+	    (while (setq a (cdr a))
+	      (or (setq b (cdr b))
+		  (math-dimension-error))
+	      (setq v (cons (funcall f (car a) (car b)) v)))
+	    (if a (math-dimension-error))
+	    (cons 'vec (nreverse v)))
+	(let ((v nil))
+	  (while (setq a (cdr a))
+	    (setq v (cons (funcall f (car a) b) v)))
+	  (cons 'vec (nreverse v))))
+    (if (math-vectorp b)
+	(let ((v nil))
+	  (while (setq b (cdr b))
+	    (setq v (cons (funcall f a (car b)) v)))
+	  (cons 'vec (nreverse v)))
+      (funcall f a b)))
+)
+
+
+
+;;; "Reduce" a function over a vector (left-associatively).  [O X V] [Public]
+(defun math-reduce-vec (f a)
+  (if (math-vectorp a)
+      (if (cdr a)
+	  (let ((accum (car (setq a (cdr a)))))
+	    (while (setq a (cdr a))
+	      (setq accum (funcall f accum (car a))))
+	    accum)
+	0)
+    a)
+)
+
+;;; Reduce a function over the columns of matrix A.  [V X V] [Public]
+(defun math-reduce-cols (f a)
+  (if (math-matrixp a)
+      (cons 'vec (math-reduce-cols-col-step f (cdr a) 1 (length (nth 1 a))))
+    a)
+)
+
+(defun math-reduce-cols-col-step (f a col cols)
+  (and (< col cols)
+       (cons (math-reduce-cols-row-step f (nth col (car a)) col (cdr a))
+	     (math-reduce-cols-col-step f a (1+ col) cols)))
+)
+
+(defun math-reduce-cols-row-step (f tot col a)
+  (if a
+      (math-reduce-cols-row-step f
+				 (funcall f tot (nth col (car a)))
+				 col
+				 (cdr a))
+    tot)
+)
+
+
+
+(defun math-dot-product (a b)
+  (if (setq a (cdr a) b (cdr b))
+      (let ((accum (math-mul (car a) (car b))))
+	(while (setq a (cdr a) b (cdr b))
+	  (setq accum (math-add accum (math-mul (car a) (car b)))))
+	accum)
+    0)
+)
+
+
+;;; Return the number of elements in vector V.  [Public]
+(defun calcFunc-vlen (v)
+  (if (math-vectorp v)
+      (1- (length v))
+    (if (math-objectp v)
+	0
+      (list 'calcFunc-vlen v)))
+)
+
+;;; Get the Nth row of a matrix.
+(defun calcFunc-mrow (mat n)   ; [Public]
+  (if (Math-vectorp n)
+      (math-map-vec (function (lambda (x) (calcFunc-mrow mat x))) n)
+    (if (and (eq (car-safe n) 'intv) (math-constp n))
+	(calcFunc-subvec mat
+			 (math-add (nth 2 n) (if (memq (nth 1 n) '(2 3)) 0 1))
+			 (math-add (nth 3 n) (if (memq (nth 1 n) '(1 3)) 1 0)))
+      (or (and (integerp (setq n (math-check-integer n)))
+	       (> n 0))
+	  (math-reject-arg n 'fixposintp))
+      (or (Math-vectorp mat)
+	  (math-reject-arg mat 'vectorp))
+      (or (nth n mat)
+	  (math-reject-arg n "*Index out of range"))))
+)
+
+(defun calcFunc-subscr (mat n &optional m)
+  (setq mat (calcFunc-mrow mat n))
+  (if m
+      (if (math-num-integerp n)
+	  (calcFunc-mrow mat m)
+	(calcFunc-mcol mat m))
+    mat)
+)
+
+;;; Get the Nth column of a matrix.
+(defun math-mat-col (mat n)
+  (cons 'vec (mapcar (function (lambda (x) (elt x n))) (cdr mat)))
+)
+
+(defun calcFunc-mcol (mat n)   ; [Public]
+  (if (Math-vectorp n)
+      (calcFunc-trn
+       (math-map-vec (function (lambda (x) (calcFunc-mcol mat x))) n))
+    (if (and (eq (car-safe n) 'intv) (math-constp n))
+	(if (math-matrixp mat)
+	    (math-map-vec (function (lambda (x) (calcFunc-mrow x n))) mat)
+	  (calcFunc-mrow mat n))
+      (or (and (integerp (setq n (math-check-integer n)))
+	       (> n 0))
+	  (math-reject-arg n 'fixposintp))
+      (or (Math-vectorp mat)
+	  (math-reject-arg mat 'vectorp))
+      (or (if (math-matrixp mat)
+	      (and (< n (length (nth 1 mat)))
+		   (math-mat-col mat n))
+	    (nth n mat))
+	  (math-reject-arg n "*Index out of range"))))
+)
+
+;;; Remove the Nth row from a matrix.
+(defun math-mat-less-row (mat n)
+  (if (<= n 0)
+      (cdr mat)
+    (cons (car mat)
+	  (math-mat-less-row (cdr mat) (1- n))))
+)
+
+(defun calcFunc-mrrow (mat n)   ; [Public]
+  (and (integerp (setq n (math-check-integer n)))
+       (> n 0)
+       (< n (length mat))
+       (math-mat-less-row mat n))
+)
+
+;;; Remove the Nth column from a matrix.
+(defun math-mat-less-col (mat n)
+  (cons 'vec (mapcar (function (lambda (x) (math-mat-less-row x n)))
+		     (cdr mat)))
+)
+
+(defun calcFunc-mrcol (mat n)   ; [Public]
+  (and (integerp (setq n (math-check-integer n)))
+       (> n 0)
+       (if (math-matrixp mat)
+	   (and (< n (length (nth 1 mat)))
+		(math-mat-less-col mat n))
+	 (math-mat-less-row mat n)))
+)
+
+(defun calcFunc-getdiag (mat)   ; [Public]
+  (if (math-square-matrixp mat)
+      (cons 'vec (math-get-diag-step (cdr mat) 1))
+    (calc-record-why 'square-matrixp mat)
+    (list 'calcFunc-getdiag mat))
+)
+
+(defun math-get-diag-step (row n)
+  (and row
+       (cons (nth n (car row))
+	     (math-get-diag-step (cdr row) (1+ n))))
+)
+
+(defun math-transpose (mat)   ; [Public]
+  (let ((m nil)
+	(col (length (nth 1 mat))))
+    (while (> (setq col (1- col)) 0)
+      (setq m (cons (math-mat-col mat col) m)))
+    (cons 'vec m))
+)
+
+(defun calcFunc-trn (mat)
+  (if (math-vectorp mat)
+      (if (math-matrixp mat)
+	  (math-transpose mat)
+	(math-col-matrix mat))
+    (if (math-numberp mat)
+	mat
+      (math-reject-arg mat 'matrixp)))
+)
+
+(defun calcFunc-ctrn (mat)
+  (calcFunc-conj (calcFunc-trn mat))
+)
+
+(defun calcFunc-pack (mode els)
+  (or (Math-vectorp els) (math-reject-arg els 'vectorp))
+  (if (and (Math-vectorp mode) (cdr mode))
+      (setq mode (cdr mode))
+    (or (integerp mode) (math-reject-arg mode 'fixnump)))
+  (condition-case err
+      (if (= (calc-pack-size mode) (1- (length els)))
+	  (calc-pack-items mode (cdr els))
+	(math-reject-arg els "*Wrong number of elements"))
+    (error (math-reject-arg els (nth 1 err))))
+)
+
+(defun calcFunc-unpack (mode thing)
+  (or (integerp mode) (math-reject-arg mode 'fixnump))
+  (condition-case err
+      (cons 'vec (calc-unpack-item mode thing))
+    (error (math-reject-arg thing (nth 1 err))))
+)
+
+(defun calcFunc-unpackt (mode thing)
+  (let ((calc-unpack-with-type 'pair))
+    (calcFunc-unpack mode thing))
+)
+
+(defun calcFunc-arrange (vec cols)   ; [Public]
+  (setq cols (math-check-fixnum cols t))
+  (if (math-vectorp vec)
+      (let* ((flat (math-flatten-vector vec))
+	     (mat (list 'vec))
+	     next)
+	(if (<= cols 0)
+	    (nconc mat flat)
+	  (while (>= (length flat) cols)
+	    (setq next (nthcdr cols flat))
+	    (setcdr (nthcdr (1- cols) flat) nil)
+	    (setq mat (nconc mat (list (cons 'vec flat)))
+		  flat next))
+	  (if flat
+	      (setq mat (nconc mat (list (cons 'vec flat)))))
+	  mat)))
+)
+
+(defun math-flatten-vector (vec)   ; [L V]
+  (if (math-vectorp vec)
+      (apply 'append (mapcar 'math-flatten-vector (cdr vec)))
+    (list vec))
+)
+
+(defun calcFunc-vconcat (a b)
+  (math-normalize (list '| a b))
+)
+
+(defun calcFunc-vconcatrev (a b)
+  (math-normalize (list '| b a))
+)
+
+(defun calcFunc-append (v1 v2)
+  (if (and (math-vectorp v1) (math-vectorp v2))
+      (append v1 (cdr v2))
+    (list 'calcFunc-append v1 v2))
+)
+
+(defun calcFunc-appendrev (v1 v2)
+  (calcFunc-append v2 v1)
+)
+
+
+;;; Copy a matrix.  [Public]
+(defun math-copy-matrix (m)
+  (if (math-vectorp (nth 1 m))
+      (cons 'vec (mapcar 'copy-sequence (cdr m)))
+    (copy-sequence m))
+)
+
+;;; Convert a scalar or vector into an NxN diagonal matrix.  [Public]
+(defun calcFunc-diag (a &optional n)
+  (and n (not (integerp n))
+       (setq n (math-check-fixnum n)))
+  (if (math-vectorp a)
+      (if (and n (/= (length a) (1+ n)))
+	  (list 'calcFunc-diag a n)
+	(if (math-matrixp a)
+	    (if (and n (/= (length (elt a 1)) (1+ n)))
+		(list 'calcFunc-diag a n)
+	      a)
+	  (cons 'vec (math-diag-step (cdr a) 0 (1- (length a))))))
+    (if n
+	(cons 'vec (math-diag-step (make-list n a) 0 n))
+      (list 'calcFunc-diag a)))
+)
+
+(defun calcFunc-idn (a &optional n)
+  (if n
+      (if (math-vectorp a)
+	  (math-reject-arg a 'numberp)
+	(calcFunc-diag a n))
+    (if (integerp calc-matrix-mode)
+	(calcFunc-idn a calc-matrix-mode)
+      (list 'calcFunc-idn a)))
+)
+
+(defun math-mimic-ident (a m)
+  (if (math-square-matrixp m)
+      (calcFunc-idn a (1- (length m)))
+    (if (math-vectorp m)
+	(if (math-zerop a)
+	    (cons 'vec (mapcar (function (lambda (x)
+					   (if (math-vectorp x)
+					       (math-mimic-ident a x)
+					     a)))
+			       (cdr m)))
+	  (math-dimension-error))
+      (calcFunc-idn a)))
+)
+
+(defun math-diag-step (a n m)
+  (if (< n m)
+      (cons (cons 'vec
+		  (nconc (make-list n 0)
+			 (cons (car a)
+			       (make-list (1- (- m n)) 0))))
+	    (math-diag-step (cdr a) (1+ n) m))
+    nil)
+)
+
+;;; Create a vector of consecutive integers. [Public]
+(defun calcFunc-index (n &optional start incr)
+  (if (math-messy-integerp n)
+      (math-float (calcFunc-index (math-trunc n) start incr))
+    (and (not (integerp n))
+	 (setq n (math-check-fixnum n)))
+    (let ((vec nil))
+      (if start
+	  (progn
+	    (if (>= n 0)
+		(while (>= (setq n (1- n)) 0)
+		  (setq vec (cons start vec)
+			start (math-add start (or incr 1))))
+	      (while (<= (setq n (1+ n)) 0)
+		(setq vec (cons start vec)
+		      start (math-mul start (or incr 2)))))
+	    (setq vec (nreverse vec)))
+	(if (>= n 0)
+	    (while (> n 0)
+	      (setq vec (cons n vec)
+		    n (1- n)))
+	  (let ((i -1))
+	    (while (>= i n)
+	      (setq vec (cons i vec)
+		    i (1- i))))))
+      (cons 'vec vec)))
+)
+
+;;; Find an element in a vector.
+(defun calcFunc-find (vec x &optional start)
+  (setq start (if start (math-check-fixnum start t) 1))
+  (if (< start 1) (math-reject-arg start 'posp))
+  (setq vec (nthcdr start vec))
+  (let ((n start))
+    (while (and vec (not (Math-equal x (car vec))))
+      (setq n (1+ n)
+	    vec (cdr vec)))
+    (if vec n 0))
+)
+
+;;; Return a subvector of a vector.
+(defun calcFunc-subvec (vec start &optional end)
+  (setq start (math-check-fixnum start t)
+	end (math-check-fixnum (or end 0) t))
+  (or (math-vectorp vec) (math-reject-arg vec 'vectorp))
+  (let ((len (1- (length vec))))
+    (if (<= start 0)
+	(setq start (+ len start 1)))
+    (if (<= end 0)
+	(setq end (+ len end 1)))
+    (if (or (> start len)
+	    (<= end start))
+	'(vec)
+      (setq vec (nthcdr start vec))
+      (if (<= end len)
+	  (let ((chop (nthcdr (- end start 1) (setq vec (copy-sequence vec)))))
+	    (setcdr chop nil)))
+      (cons 'vec vec)))
+)
+
+;;; Remove a subvector from a vector.
+(defun calcFunc-rsubvec (vec start &optional end)
+  (setq start (math-check-fixnum start t)
+	end (math-check-fixnum (or end 0) t))
+  (or (math-vectorp vec) (math-reject-arg vec 'vectorp))
+  (let ((len (1- (length vec))))
+    (if (<= start 0)
+	(setq start (+ len start 1)))
+    (if (<= end 0)
+	(setq end (+ len end 1)))
+    (if (or (> start len)
+	    (<= end start))
+	vec
+      (let ((tail (nthcdr end vec))
+	    (chop (nthcdr (1- start) (setq vec (copy-sequence vec)))))
+	(setcdr chop nil)
+	(append vec tail))))
+)
+
+;;; Reverse the order of the elements of a vector.
+(defun calcFunc-rev (vec)
+  (if (math-vectorp vec)
+      (cons 'vec (reverse (cdr vec)))
+    (math-reject-arg vec 'vectorp))
+)
+
+;;; Compress a vector according to a mask vector.
+(defun calcFunc-vmask (mask vec)
+  (if (math-numberp mask)
+      (if (math-zerop mask)
+	  '(vec)
+	vec)
+    (or (math-vectorp mask) (math-reject-arg mask 'vectorp))
+    (or (math-constp mask) (math-reject-arg mask 'constp))
+    (or (math-vectorp vec) (math-reject-arg vec 'vectorp))
+    (or (= (length mask) (length vec)) (math-dimension-error))
+    (let ((new nil))
+      (while (setq mask (cdr mask) vec (cdr vec))
+	(or (math-zerop (car mask))
+	    (setq new (cons (car vec) new))))
+      (cons 'vec (nreverse new))))
+)
+
+;;; Expand a vector according to a mask vector.
+(defun calcFunc-vexp (mask vec &optional filler)
+  (or (math-vectorp mask) (math-reject-arg mask 'vectorp))
+  (or (math-constp mask) (math-reject-arg mask 'constp))
+  (or (math-vectorp vec) (math-reject-arg vec 'vectorp))
+  (let ((new nil)
+	(fvec (and filler (math-vectorp filler))))
+    (while (setq mask (cdr mask))
+      (if (math-zerop (car mask))
+	  (setq new (cons (or (if fvec
+				  (car (setq filler (cdr filler)))
+				filler)
+			      (car mask)) new))
+	(setq vec (cdr vec)
+	      new (cons (or (car vec) (car mask)) new))))
+    (cons 'vec (nreverse new)))
+)
+
+
+;;; Compute the row and column norms of a vector or matrix.  [Public]
+(defun calcFunc-rnorm (a)
+  (if (and (Math-vectorp a)
+	   (math-constp a))
+      (if (math-matrixp a)
+	  (math-reduce-vec 'math-max (math-map-vec 'calcFunc-cnorm a))
+	(math-reduce-vec 'math-max (math-map-vec 'math-abs a)))
+    (calc-record-why 'vectorp a)
+    (list 'calcFunc-rnorm a))
+)
+
+(defun calcFunc-cnorm (a)
+  (if (and (Math-vectorp a)
+	   (math-constp a))
+      (if (math-matrixp a)
+	  (math-reduce-vec 'math-max
+			   (math-reduce-cols 'math-add-abs a))
+	(math-reduce-vec 'math-add-abs a))
+    (calc-record-why 'vectorp a)
+    (list 'calcFunc-cnorm a))
+)
+
+(defun math-add-abs (a b)
+  (math-add (math-abs a) (math-abs b))
+)
+
+
+;;; Sort the elements of a vector into increasing order.
+(defun calcFunc-sort (vec)   ; [Public]
+  (if (math-vectorp vec)
+      (cons 'vec (sort (copy-sequence (cdr vec)) 'math-beforep))
+    (math-reject-arg vec 'vectorp))
+)
+
+(defun calcFunc-rsort (vec)   ; [Public]
+  (if (math-vectorp vec)
+      (cons 'vec (nreverse (sort (copy-sequence (cdr vec)) 'math-beforep)))
+    (math-reject-arg vec 'vectorp))
+)
+
+(defun calcFunc-grade (grade-vec)
+  (if (math-vectorp grade-vec)
+      (let* ((len (1- (length grade-vec))))
+	(cons 'vec (sort (cdr (calcFunc-index len)) 'math-grade-beforep)))
+    (math-reject-arg grade-vec 'vectorp))
+)
+
+(defun calcFunc-rgrade (grade-vec)
+  (if (math-vectorp grade-vec)
+      (let* ((len (1- (length grade-vec))))
+	(cons 'vec (nreverse (sort (cdr (calcFunc-index len))
+				   'math-grade-beforep))))
+    (math-reject-arg grade-vec 'vectorp))
+)
+
+(defun math-grade-beforep (i j)
+  (math-beforep (nth i grade-vec) (nth j grade-vec))
+)
+
+
+;;; Compile a histogram of data from a vector.
+(defun calcFunc-histogram (vec wts &optional n)
+  (or n (setq n wts wts 1))
+  (or (Math-vectorp vec)
+      (math-reject-arg vec 'vectorp))
+  (if (Math-vectorp wts)
+      (or (= (length vec) (length wts))
+	  (math-dimension-error)))
+  (or (natnump n)
+      (math-reject-arg n 'fixnatnump))
+  (let ((res (make-vector n 0))
+	(vp vec)
+	(wvec (Math-vectorp wts))
+	(wp wts)
+	bin)
+    (while (setq vp (cdr vp))
+      (setq bin (car vp))
+      (or (natnump bin)
+	  (setq bin (math-floor bin)))
+      (and (natnump bin)
+	   (< bin n)
+	   (aset res bin (math-add (aref res bin)
+				   (if wvec (car (setq wp (cdr wp))) wts)))))
+    (cons 'vec (append res nil)))
+)
+
+
+;;; Set operations.
+
+(defun calcFunc-vunion (a b)
+  (if (Math-objectp a)
+      (setq a (list 'vec a))
+    (or (math-vectorp a) (math-reject-arg a 'vectorp)))
+  (if (Math-objectp b)
+      (setq b (list b))
+    (or (math-vectorp b) (math-reject-arg b 'vectorp))
+    (setq b (cdr b)))
+  (calcFunc-rdup (append a b))
+)
+
+(defun calcFunc-vint (a b)
+  (if (and (math-simple-set a) (math-simple-set b))
+      (progn
+	(setq a (cdr (calcFunc-rdup a)))
+	(setq b (cdr (calcFunc-rdup b)))
+	(let ((vec (list 'vec)))
+	  (while (and a b)
+	    (if (math-beforep (car a) (car b))
+		(setq a (cdr a))
+	      (if (Math-equal (car a) (car b))
+		  (setq vec (cons (car a) vec)
+			a (cdr a)))
+	      (setq b (cdr b))))
+	  (nreverse vec)))
+    (calcFunc-vcompl (calcFunc-vunion (calcFunc-vcompl a)
+				      (calcFunc-vcompl b))))
+)
+
+(defun calcFunc-vdiff (a b)
+  (if (and (math-simple-set a) (math-simple-set b))
+      (progn
+	(setq a (cdr (calcFunc-rdup a)))
+	(setq b (cdr (calcFunc-rdup b)))
+	(let ((vec (list 'vec)))
+	  (while a
+	    (while (and b (math-beforep (car b) (car a)))
+	      (setq b (cdr b)))
+	    (if (and b (Math-equal (car a) (car b)))
+		(setq a (cdr a)
+		      b (cdr b))
+	      (setq vec (cons (car a) vec)
+		    a (cdr a))))
+	  (nreverse vec)))
+    (calcFunc-vcompl (calcFunc-vunion (calcFunc-vcompl a) b)))
+)
+
+(defun calcFunc-vxor (a b)
+  (if (and (math-simple-set a) (math-simple-set b))
+      (progn
+	(setq a (cdr (calcFunc-rdup a)))
+	(setq b (cdr (calcFunc-rdup b)))
+	(let ((vec (list 'vec)))
+	  (while (or a b)
+	    (if (and a
+		     (or (not b)
+			 (math-beforep (car a) (car b))))
+		(setq vec (cons (car a) vec)
+		      a (cdr a))
+	      (if (and a (Math-equal (car a) (car b)))
+		  (setq a (cdr a))
+		(setq vec (cons (car b) vec)))
+	      (setq b (cdr b))))
+	  (nreverse vec)))
+    (let ((ca (calcFunc-vcompl a))
+	  (cb (calcFunc-vcompl b)))
+      (calcFunc-vunion (calcFunc-vcompl (calcFunc-vunion ca b))
+		       (calcFunc-vcompl (calcFunc-vunion a cb)))))
+)
+
+(defun calcFunc-vcompl (a)
+  (setq a (math-prepare-set a))
+  (let ((vec (list 'vec))
+	(prev '(neg (var inf var-inf)))
+	(closed 2))
+    (while (setq a (cdr a))
+      (or (and (equal (nth 2 (car a)) '(neg (var inf var-inf)))
+	       (memq (nth 1 (car a)) '(2 3)))
+	  (setq vec (cons (list 'intv
+				(+ closed
+				   (if (memq (nth 1 (car a)) '(0 1)) 1 0))
+				prev
+				(nth 2 (car a)))
+			  vec)))
+      (setq prev (nth 3 (car a))
+	    closed (if (memq (nth 1 (car a)) '(0 2)) 2 0)))
+    (or (and (equal prev '(var inf var-inf))
+	     (= closed 0))
+	(setq vec (cons (list 'intv (+ closed 1)
+			      prev '(var inf var-inf))
+			vec)))
+    (math-clean-set (nreverse vec)))
+)
+
+(defun calcFunc-vspan (a)
+  (setq a (math-prepare-set a))
+  (if (cdr a)
+      (let ((last (nth (1- (length a)) a)))
+	(math-make-intv (+ (logand (nth 1 (nth 1 a)) 2)
+			   (logand (nth 1 last) 1))
+			(nth 2 (nth 1 a))
+			(nth 3 last)))
+    '(intv 2 0 0))
+)
+
+(defun calcFunc-vfloor (a &optional always-vec)
+  (setq a (math-prepare-set a))
+  (let ((vec (list 'vec)) (p a) (prev nil) b mask)
+    (while (setq p (cdr p))
+      (setq mask (nth 1 (car p))
+	    a (nth 2 (car p))
+	    b (nth 3 (car p)))
+      (and (memq mask '(0 1))
+	   (not (math-infinitep a))
+	   (setq mask (logior mask 2))
+	   (math-num-integerp a)
+	   (setq a (math-add a 1)))
+      (setq a (math-ceiling a))
+      (and (memq mask '(0 2))
+	   (not (math-infinitep b))
+	   (setq mask (logior mask 1))
+	   (math-num-integerp b)
+	   (setq b (math-sub b 1)))
+      (setq b (math-floor b))
+      (if (and prev (Math-equal (math-sub a 1) (nth 3 prev)))
+	  (setcar (nthcdr 3 prev) b)
+	(or (Math-lessp b a)
+	    (setq vec (cons (setq prev (list 'intv mask a b)) vec)))))
+    (setq vec (nreverse vec))
+    (math-clean-set vec always-vec))
+)
+
+(defun calcFunc-vcard (a)
+  (setq a (calcFunc-vfloor a t))
+  (or (math-constp a) (math-reject-arg a "*Set must be finite"))
+  (let ((count 0))
+    (while (setq a (cdr a))
+      (if (eq (car-safe (car a)) 'intv)
+	  (setq count (math-add count (math-sub (nth 3 (car a))
+						(nth 2 (car a))))))
+      (setq count (math-add count 1)))
+    count)
+)
+
+(defun calcFunc-venum (a)
+  (setq a (calcFunc-vfloor a t))
+  (or (math-constp a) (math-reject-arg a "*Set must be finite"))
+  (let ((p a) next)
+    (while (cdr p)
+      (setq next (cdr p))
+      (if (eq (car-safe (nth 1 p)) 'intv)
+	  (setcdr p (nconc (cdr (calcFunc-index (math-add
+						 (math-sub (nth 3 (nth 1 p))
+							   (nth 2 (nth 1 p)))
+						 1)
+						(nth 2 (nth 1 p))))
+			   (cdr (cdr p)))))
+      (setq p next))
+    a)
+)
+
+(defun calcFunc-vpack (a)
+  (setq a (calcFunc-vfloor a t))
+  (if (and (cdr a)
+	   (math-negp (if (eq (car-safe (nth 1 a)) 'intv)
+			  (nth 2 (nth 1 a))
+			(nth 1 a))))
+      (math-reject-arg (nth 1 a) 'posp))
+  (let ((accum 0))
+    (while (setq a (cdr a))
+      (if (eq (car-safe (car a)) 'intv)
+	  (if (equal (nth 3 (car a)) '(var inf var-inf))
+	      (setq accum (math-sub accum
+				    (math-power-of-2 (nth 2 (car a)))))
+	    (setq accum (math-add accum
+				  (math-sub
+				   (math-power-of-2 (1+ (nth 3 (car a))))
+				   (math-power-of-2 (nth 2 (car a)))))))
+	(setq accum (math-add accum (math-power-of-2 (car a))))))
+    accum)
+)
+
+(defun calcFunc-vunpack (a &optional w)
+  (or (math-num-integerp a) (math-reject-arg a 'integerp))
+  (if w (setq a (math-clip a w)))
+  (if (math-messy-integerp a) (setq a (math-trunc a)))
+  (let* ((calc-number-radix 2)
+	 (neg (math-negp a))
+	 (aa (if neg (math-sub -1 a) a))
+	 (str (if (eq aa 0)
+		  ""
+		(if (consp aa)
+		    (math-format-bignum-binary (cdr aa))
+		  (math-format-binary aa))))
+	 (zero (if neg ?1 ?0))
+	 (one (if neg ?0 ?1))
+	 (len (length str))
+	 (vec (list 'vec))
+	 (pos (1- len)) pos2)
+    (while (>= pos 0)
+      (if (eq (aref str pos) zero)
+	  (setq pos (1- pos))
+	(setq pos2 pos)
+	(while (and (>= pos 0) (eq (aref str pos) one))
+	  (setq pos (1- pos)))
+	(setq vec (cons (if (= pos (1- pos2))
+			    (- len pos2 1)
+			  (list 'intv 3 (- len pos2 1) (- len pos 2)))
+			vec))))
+    (if neg
+	(setq vec (cons (list 'intv 2 len '(var inf var-inf)) vec)))
+    (math-clean-set (nreverse vec)))
+)
+
+(defun calcFunc-rdup (a)
+  (if (math-simple-set a)
+      (progn
+	(and (Math-objectp a) (setq a (list 'vec a)))
+	(or (math-vectorp a) (math-reject-arg a 'vectorp))
+	(setq a (sort (copy-sequence (cdr a)) 'math-beforep))
+	(let ((p a))
+	  (while (cdr p)
+	    (if (Math-equal (car p) (nth 1 p))
+		(setcdr p (cdr (cdr p)))
+	      (setq p (cdr p)))))
+	(cons 'vec a))
+    (math-clean-set (math-prepare-set a)))
+)
+
+(defun math-prepare-set (a)
+  (if (Math-objectp a)
+      (setq a (list 'vec a))
+    (or (math-vectorp a) (math-reject-arg a 'vectorp))
+    (setq a (cons 'vec (sort (copy-sequence (cdr a)) 'math-beforep))))
+  (let ((p a) res)
+
+    ;; Convert all elements to non-empty intervals.
+    (while (cdr p)
+      (if (eq (car-safe (nth 1 p)) 'intv)
+	  (if (math-intv-constp (nth 1 p))
+	      (if (and (memq (nth 1 (nth 1 p)) '(0 1 2))
+		       (Math-equal (nth 2 (nth 1 p)) (nth 3 (nth 1 p))))
+		  (setcdr p (cdr (cdr p)))
+		(setq p (cdr p)))
+	    (math-reject-arg (nth 1 p) 'constp))
+	(or (Math-anglep (nth 1 p))
+	    (eq (car (nth 1 p)) 'date)
+	    (equal (nth 1 p) '(var inf var-inf))
+	    (equal (nth 1 p) '(neg (var inf var-inf)))
+	    (math-reject-arg (nth 1 p) 'realp))
+	(setcar (cdr p) (list 'intv 3 (nth 1 p) (nth 1 p)))
+	(setq p (cdr p))))
+
+    ;; Combine redundant intervals.
+    (setq p a)
+    (while (cdr (cdr p))
+      (if (or (memq (setq res (math-compare (nth 3 (nth 1 p))
+					    (nth 2 (nth 2 p))))
+		    '(-1 2))
+	      (and (eq res 0)
+		   (memq (nth 1 (nth 1 p)) '(0 2))
+		   (memq (nth 1 (nth 2 p)) '(0 1))))
+	  (setq p (cdr p))
+	(setq res (math-compare (nth 3 (nth 1 p)) (nth 3 (nth 2 p))))
+	(setcdr p (cons (list 'intv
+			      (+ (logand (logior (nth 1 (nth 1 p))
+						 (if (Math-equal
+						      (nth 2 (nth 1 p))
+						      (nth 2 (nth 2 p)))
+						     (nth 1 (nth 2 p))
+						   0))
+					 2)
+				 (logand (logior (if (memq res '(1 0 2))
+						     (nth 1 (nth 1 p)) 0)
+						 (if (memq res '(-1 0 2))
+						     (nth 1 (nth 2 p)) 0))
+					 1))
+			      (nth 2 (nth 1 p))
+			      (if (eq res 1)
+				  (nth 3 (nth 1 p))
+				(nth 3 (nth 2 p))))
+			(cdr (cdr (cdr p))))))))
+  a
+)
+
+(defun math-clean-set (a &optional always-vec)
+  (let ((p a) res)
+    (while (cdr p)
+      (if (and (eq (car-safe (nth 1 p)) 'intv)
+	       (Math-equal (nth 2 (nth 1 p)) (nth 3 (nth 1 p))))
+	  (setcar (cdr p) (nth 2 (nth 1 p))))
+      (setq p (cdr p)))
+    (if (and (not (cdr (cdr a)))
+	     (eq (car-safe (nth 1 a)) 'intv)
+	     (not always-vec))
+	(nth 1 a)
+      a))
+)
+
+(defun math-simple-set (a)
+  (or (and (Math-objectp a)
+	   (not (eq (car-safe a) 'intv)))
+      (and (Math-vectorp a)
+	   (progn
+	     (while (and (setq a (cdr a))
+			 (not (eq (car-safe (car a)) 'intv))))
+	     (null a))))
+)
+
+
+
+
+;;; Compute a right-handed vector cross product.  [O O O] [Public]
+(defun calcFunc-cross (a b)
+  (if (and (eq (car-safe a) 'vec)
+	   (= (length a) 4))
+      (if (and (eq (car-safe b) 'vec)
+	       (= (length b) 4))
+	  (list 'vec
+		(math-sub (math-mul (nth 2 a) (nth 3 b))
+			  (math-mul (nth 3 a) (nth 2 b)))
+		(math-sub (math-mul (nth 3 a) (nth 1 b))
+			  (math-mul (nth 1 a) (nth 3 b)))
+		(math-sub (math-mul (nth 1 a) (nth 2 b))
+			  (math-mul (nth 2 a) (nth 1 b))))
+	(math-reject-arg b "*Three-vector expected"))
+    (math-reject-arg a "*Three-vector expected"))
+)
+
+
+
+
+
+(defun math-read-brackets (space-sep close)
+  (and space-sep (setq space-sep (not (math-check-for-commas))))
+  (math-read-token)
+  (while (eq exp-token 'space)
+    (math-read-token))
+  (if (or (equal exp-data close)
+	  (eq exp-token 'end))
+      (progn
+	(math-read-token)
+	'(vec))
+    (let ((save-exp-pos exp-pos)
+	  (save-exp-old-pos exp-old-pos)
+	  (save-exp-token exp-token)
+	  (save-exp-data exp-data)
+	  (vals (let ((exp-keep-spaces space-sep))
+		  (if (or (equal exp-data "\\dots")
+			  (equal exp-data "\\ldots"))
+		      '(vec (neg (var inf var-inf)))
+		    (catch 'syntax (math-read-vector))))))
+      (if (stringp vals)
+	  (if space-sep
+	      (let ((error-exp-pos exp-pos)
+		    (error-exp-old-pos exp-old-pos)
+		    vals2)
+		(setq exp-pos save-exp-pos
+		      exp-old-pos save-exp-old-pos
+		      exp-token save-exp-token
+		      exp-data save-exp-data)
+		(let ((exp-keep-spaces nil))
+		  (setq vals2 (catch 'syntax (math-read-vector))))
+		(if (and (not (stringp vals2))
+			 (or (assoc exp-data '(("\\ldots") ("\\dots") (";")))
+			     (equal exp-data close)
+			     (eq exp-token 'end)))
+		    (setq space-sep nil
+			  vals vals2)
+		  (setq exp-pos error-exp-pos
+			exp-old-pos error-exp-old-pos)
+		  (throw 'syntax vals)))
+	    (throw 'syntax vals)))
+      (if (or (equal exp-data "\\dots")
+	      (equal exp-data "\\ldots"))
+	  (progn
+	    (math-read-token)
+	    (setq vals (if (> (length vals) 2)
+			   (cons 'calcFunc-mul (cdr vals)) (nth 1 vals)))
+	    (let ((exp2 (if (or (equal exp-data close)
+				(equal exp-data ")")
+				(eq exp-token 'end))
+			    '(var inf var-inf)
+			  (math-read-expr-level 0))))
+	      (setq vals
+		    (list 'intv
+			  (if (equal exp-data ")") 2 3)
+			  vals
+			  exp2)))
+	    (if (not (or (equal exp-data close)
+			 (equal exp-data ")")
+			 (eq exp-token 'end)))
+		(throw 'syntax "Expected `]'")))
+	(if (equal exp-data ";")
+	    (let ((exp-keep-spaces space-sep))
+	      (setq vals (cons 'vec (math-read-matrix (list vals))))))
+	(if (not (or (equal exp-data close)
+		     (eq exp-token 'end)))
+	    (throw 'syntax "Expected `]'")))
+      (or (eq exp-token 'end)
+	  (math-read-token))
+      vals))
+)
+
+(defun math-check-for-commas (&optional balancing)
+  (let ((count 0)
+	(pos (1- exp-pos)))
+    (while (and (>= count 0)
+		(setq pos (string-match
+			   (if balancing "[],[{}()<>]" "[],[{}()]")
+			   exp-str (1+ pos)))
+		(or (/= (aref exp-str pos) ?,) (> count 0) balancing))
+      (cond ((memq (aref exp-str pos) '(?\[ ?\{ ?\( ?\<))
+	     (setq count (1+ count)))
+	    ((memq (aref exp-str pos) '(?\] ?\} ?\) ?\>))
+	     (setq count (1- count)))))
+    (if balancing
+	pos
+      (and pos (= (aref exp-str pos) ?,))))
+)
+
+(defun math-read-vector ()
+  (let* ((val (list (math-read-expr-level 0)))
+	 (last val))
+    (while (progn
+	     (while (eq exp-token 'space)
+	       (math-read-token))
+	     (and (not (eq exp-token 'end))
+		  (not (equal exp-data ";"))
+		  (not (equal exp-data close))
+		  (not (equal exp-data "\\dots"))
+		  (not (equal exp-data "\\ldots"))))
+      (if (equal exp-data ",")
+	  (math-read-token))
+      (while (eq exp-token 'space)
+	(math-read-token))
+      (let ((rest (list (math-read-expr-level 0))))
+	(setcdr last rest)
+	(setq last rest)))
+    (cons 'vec val))
+)
+
+(defun math-read-matrix (mat)
+  (while (equal exp-data ";")
+    (math-read-token)
+    (while (eq exp-token 'space)
+      (math-read-token))
+    (setq mat (nconc mat (list (math-read-vector)))))
+  mat
+)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/calc-yank.el	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,593 @@
+;; Calculator for GNU Emacs, part II [calc-yank.el]
+;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+;; Written by Dave Gillespie, daveg@synaptics.com.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY.  No author or distributor
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing.  Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License.   A copy of this license is
+;; supposed to have been given to you along with GNU Emacs so you
+;; can know your rights and responsibilities.  It should be in a
+;; file named COPYING.  Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+
+
+
+;; This file is autoloaded from calc-ext.el.
+(require 'calc-ext)
+
+(require 'calc-macs)
+
+(defun calc-Need-calc-yank () nil)
+
+
+;;; Kill ring commands.
+
+(defun calc-kill (nn &optional no-delete)
+  (interactive "P")
+  (if (eq major-mode 'calc-mode)
+      (calc-wrapper
+       (calc-force-refresh)
+       (calc-set-command-flag 'no-align)
+       (let ((num (max (calc-locate-cursor-element (point)) 1))
+	     (n (prefix-numeric-value nn)))
+	 (if (< n 0)
+	     (progn
+	       (if (eobp)
+		   (setq num (1- num)))
+	       (setq num (- num n)
+		     n (- n))))
+	 (let ((stuff (calc-top-list n (- num n -1))))
+	   (calc-cursor-stack-index num)
+	   (let ((first (point)))
+	     (calc-cursor-stack-index (- num n))
+	     (if (null nn)
+		 (backward-char 1))   ; don't include newline for raw C-k
+	     (copy-region-as-kill first (point))
+	     (if (not no-delete)
+		 (calc-pop-stack n (- num n -1))))
+	   (setq calc-last-kill (cons (car kill-ring) stuff)))))
+    (kill-line nn))
+)
+
+(defun calc-force-refresh ()
+  (if (or calc-executing-macro calc-display-dirty)
+      (let ((calc-executing-macro nil))
+	(calc-refresh)))
+)
+
+(defun calc-locate-cursor-element (pt)
+  (save-excursion
+    (goto-char (point-max))
+    (calc-locate-cursor-scan (- calc-stack-top) calc-stack pt))
+)
+
+(defun calc-locate-cursor-scan (n stack pt)
+  (if (or (<= (point) pt)
+	  (null stack))
+      n
+    (forward-line (- (nth 1 (car stack))))
+    (calc-locate-cursor-scan (1+ n) (cdr stack) pt))
+)
+
+(defun calc-kill-region (top bot &optional no-delete)
+  (interactive "r")
+  (if (eq major-mode 'calc-mode)
+      (calc-wrapper
+       (calc-force-refresh)
+       (calc-set-command-flag 'no-align)
+       (let* ((top-num (calc-locate-cursor-element top))
+	      (bot-num (calc-locate-cursor-element (1- bot)))
+	      (num (- top-num bot-num -1)))
+	 (copy-region-as-kill top bot)
+	 (setq calc-last-kill (cons (car kill-ring)
+				    (calc-top-list num bot-num)))
+	 (if (not no-delete)
+	     (calc-pop-stack num bot-num))))
+    (if no-delete
+	(copy-region-as-kill top bot)
+      (kill-region top bot)))
+)
+
+(defun calc-copy-as-kill (n)
+  (interactive "P")
+  (calc-kill n t)
+)
+
+(defun calc-copy-region-as-kill (top bot)
+  (interactive "r")
+  (calc-kill-region top bot t)
+)
+
+;;; This function uses calc-last-kill if possible to get an exact result,
+;;; otherwise it just parses the yanked string.
+;;; Modified to use Emacs 19 extended concept of kill-ring. -- daveg 12/15/96
+(defun calc-yank ()
+  (interactive)
+  (calc-wrapper
+   (calc-pop-push-record-list
+    0 "yank"
+    (let ((thing (if (fboundp 'current-kill)
+		     (current-kill 0 t)
+		   (car kill-ring-yank-pointer))))
+      (if (eq (car-safe calc-last-kill) thing)
+	  (cdr calc-last-kill)
+	(if (stringp thing)
+	    (let ((val (math-read-exprs (calc-clean-newlines thing))))
+	      (if (eq (car-safe val) 'error)
+		  (progn
+		    (setq val (math-read-exprs thing))
+		    (if (eq (car-safe val) 'error)
+			(error "Bad format in yanked data")
+		      val))
+		val)))))))
+)
+
+(defun calc-clean-newlines (s)
+  (cond
+   
+   ;; Omit leading/trailing whitespace
+   ((or (string-match "\\`[ \n\r]+\\([^\001]*\\)\\'" s)
+	(string-match "\\`\\([^\001]*\\)[ \n\r]+\\'" s))
+    (calc-clean-newlines (math-match-substring s 1)))
+
+   ;; Convert newlines to commas
+   ((string-match "\\`\\(.*\\)[\n\r]+\\([^\001]*\\)\\'" s)
+    (calc-clean-newlines (concat (math-match-substring s 1) ","
+				 (math-match-substring s 2))))
+   
+   (t s))
+)
+
+
+(defun calc-do-grab-region (top bot arg)
+  (and (memq major-mode '(calc-mode calc-trail-mode))
+       (error "This command works only in a regular text buffer."))
+  (let* ((from-buffer (current-buffer))
+	 (calc-was-started (get-buffer-window "*Calculator*"))
+	 (single nil)
+	 data vals pos)
+    (if arg
+	(if (consp arg)
+	    (setq single t)
+	  (setq arg (prefix-numeric-value arg))
+	  (if (= arg 0)
+	      (save-excursion
+		(beginning-of-line)
+		(setq top (point))
+		(end-of-line)
+		(setq bot (point)))
+	    (save-excursion
+	      (setq top (point))
+	      (forward-line arg)
+	      (if (> arg 0)
+		  (setq bot (point))
+		(setq bot top
+		      top (point)))))))
+    (setq data (buffer-substring top bot))
+    (calc)
+    (if single
+	(setq vals (math-read-expr data))
+      (setq vals (math-read-expr (concat "[" data "]")))
+      (and (eq (car-safe vals) 'vec)
+	   (= (length vals) 2)
+	   (eq (car-safe (nth 1 vals)) 'vec)
+	   (setq vals (nth 1 vals))))
+    (if (eq (car-safe vals) 'error)
+	(progn
+	  (if calc-was-started
+	      (pop-to-buffer from-buffer)
+	    (calc-quit t)
+	    (switch-to-buffer from-buffer))
+	  (goto-char top)
+	  (forward-char (+ (nth 1 vals) (if single 0 1)))
+	  (error (nth 2 vals))))
+    (calc-slow-wrapper
+     (calc-enter-result 0 "grab" vals)))
+)
+
+
+(defun calc-do-grab-rectangle (top bot arg &optional reduce)
+  (and (memq major-mode '(calc-mode calc-trail-mode))
+       (error "This command works only in a regular text buffer."))
+  (let* ((col1 (save-excursion (goto-char top) (current-column)))
+	 (col2 (save-excursion (goto-char bot) (current-column)))
+	 (from-buffer (current-buffer))
+	 (calc-was-started (get-buffer-window "*Calculator*"))
+	 data mat vals lnum pt pos)
+    (if (= col1 col2)
+	(save-excursion
+	  (or (= col1 0)
+	      (error "Point and mark must be at beginning of line, or define a rectangle"))
+	  (goto-char top)
+	  (while (< (point) bot)
+	    (setq pt (point))
+	    (forward-line 1)
+	    (setq data (cons (buffer-substring pt (1- (point))) data)))
+	  (setq data (nreverse data)))
+      (setq data (extract-rectangle top bot)))
+    (calc)
+    (setq mat (list 'vec)
+	  lnum 0)
+    (and arg
+	 (setq arg (if (consp arg) 0 (prefix-numeric-value arg))))
+    (while data
+      (if (natnump arg)
+	  (progn
+	    (if (= arg 0)
+		(setq arg 1000000))
+	    (setq pos 0
+		  vals (list 'vec))
+	    (let ((w (length (car data)))
+		  j v)
+	      (while (< pos w)
+		(setq j (+ pos arg)
+		      v (if (>= j w)
+			    (math-read-expr (substring (car data) pos))
+			  (math-read-expr (substring (car data) pos j))))
+		(if (eq (car-safe v) 'error)
+		    (setq vals v w 0)
+		  (setq vals (nconc vals (list v))
+			pos j)))))
+	(if (string-match "\\` *-?[0-9][0-9]?[0-9]?[0-9]?[0-9]?[0-9]? *\\'"
+			  (car data))
+	    (setq vals (list 'vec (string-to-int (car data))))
+	  (if (and (null arg)
+		   (string-match "[[{][^][{}]*[]}]" (car data)))
+	      (setq pos (match-beginning 0)
+		    vals (math-read-expr (math-match-substring (car data) 0)))
+	    (let ((s (if (string-match
+			  "\\`\\([0-9]+:[ \t]\\)?\\(.*[^, \t]\\)[, \t]*\\'"
+			  (car data))
+			 (math-match-substring (car data) 2)
+		       (car data))))
+	      (setq pos -1
+		    vals (math-read-expr (concat "[" s "]")))
+	      (if (eq (car-safe vals) 'error)
+		  (let ((v2 (math-read-expr s)))
+		    (or (eq (car-safe v2) 'error)
+			(setq vals (list 'vec v2)))))))))
+      (if (eq (car-safe vals) 'error)
+	  (progn
+	    (if calc-was-started
+		(pop-to-buffer from-buffer)
+	      (calc-quit t)
+	      (switch-to-buffer from-buffer))
+	    (goto-char top)
+	    (forward-line lnum)
+	    (forward-char (+ (nth 1 vals) (min col1 col2) pos))
+	    (error (nth 2 vals))))
+      (or (equal vals '(vec))
+	  (setq mat (cons vals mat)))
+      (setq data (cdr data)
+	    lnum (1+ lnum)))
+    (calc-slow-wrapper
+     (if reduce
+	 (calc-enter-result 0 "grb+" (list reduce '(var add var-add)
+					   (nreverse mat)))
+       (calc-enter-result 0 "grab" (nreverse mat)))))
+)
+
+
+(defun calc-copy-to-buffer (nn)
+  "Copy the top of stack into an editing buffer."
+  (interactive "P")
+  (let ((thebuf (and (not (memq major-mode '(calc-mode calc-trail-mode)))
+		     (current-buffer)))
+	(movept nil)
+	oldbuf newbuf)
+    (calc-wrapper
+     (save-excursion
+       (calc-force-refresh)
+       (let ((n (prefix-numeric-value nn))
+	     (eat-lnums calc-line-numbering)
+	     (big-offset (if (eq calc-language 'big) 1 0))
+	     top bot)
+	 (setq oldbuf (current-buffer)
+	       newbuf (or thebuf
+			  (calc-find-writable-buffer (buffer-list) 0)
+			  (calc-find-writable-buffer (buffer-list) 1)
+			  (error "No other buffer")))
+	 (cond ((and (or (null nn)
+			 (consp nn))
+		     (= (calc-substack-height 0)
+			(- (1- (calc-substack-height 1)) big-offset)))
+		(calc-cursor-stack-index 1)
+		(if (looking-at
+		     (if calc-line-numbering "[0-9]+: *[^ \n]" " *[^ \n]"))
+		    (goto-char (1- (match-end 0))))
+		(setq eat-lnums nil
+		      top (point))
+		(calc-cursor-stack-index 0)
+		(setq bot (- (1- (point)) big-offset)))
+	       ((> n 0)
+		(calc-cursor-stack-index n)
+		(setq top (point))
+		(calc-cursor-stack-index 0)
+		(setq bot (- (point) big-offset)))
+	       ((< n 0)
+		(calc-cursor-stack-index (- n))
+		(setq top (point))
+		(calc-cursor-stack-index (1- (- n)))
+		(setq bot (point)))
+	       (t
+		(goto-char (point-min))
+		(forward-line 1)
+		(setq top (point))
+		(calc-cursor-stack-index 0)
+		(setq bot (point))))
+	 (save-excursion
+	   (set-buffer newbuf)
+	   (if (consp nn)
+	       (kill-region (region-beginning) (region-end)))
+	   (push-mark (point) t)
+	   (if (and overwrite-mode (not (consp nn)))
+	       (calc-overwrite-string (save-excursion
+					(set-buffer oldbuf)
+					(buffer-substring top bot))
+				      eat-lnums)
+	     (or (bolp) (setq eat-lnums nil))
+	     (insert-buffer-substring oldbuf top bot)
+	     (and eat-lnums
+		  (let ((n 1))
+		    (while (and (> (point) (mark))
+				(progn
+				  (forward-line -1)
+				  (>= (point) (mark))))
+		      (delete-char 4)
+		      (setq n (1+ n)))
+		    (forward-line n))))
+	   (if thebuf (setq movept (point)))
+	   (if (get-buffer-window (current-buffer))
+	       (set-window-point (get-buffer-window (current-buffer))
+				 (point)))))))
+    (if movept (goto-char movept))
+    (and (consp nn)
+	 (not thebuf)
+	 (progn
+	   (calc-quit t)
+	   (switch-to-buffer newbuf))))
+)
+
+(defun calc-overwrite-string (str eat-lnums)
+  (if (string-match "\n\\'" str)
+      (setq str (substring str 0 -1)))
+  (if eat-lnums
+      (setq str (substring str 4)))
+  (if (and (string-match "\\`[-+]?[0-9.]+\\(e-?[0-9]+\\)?\\'" str)
+	   (looking-at "[-+]?[0-9.]+\\(e-?[0-9]+\\)?"))
+      (progn
+	(delete-region (point) (match-end 0))
+	(insert str))
+    (let ((i 0))
+      (while (< i (length str))
+	(if (= (setq last-command-char (aref str i)) ?\n)
+	    (or (= i (1- (length str)))
+		(let ((pt (point)))
+		  (end-of-line)
+		  (delete-region pt (point))
+		  (if (eobp)
+		      (insert "\n")
+		    (forward-char 1))
+		  (if eat-lnums (setq i (+ i 4)))))
+	  (self-insert-command 1))
+	(setq i (1+ i)))))
+)
+
+;;; First, require that buffer is visible and does not begin with "*"
+;;; Second, require only that it not begin with "*Calc"
+(defun calc-find-writable-buffer (buf mode)
+  (and buf
+       (if (or (string-match "\\`\\( .*\\|\\*Calc.*\\)"
+			     (buffer-name (car buf)))
+	       (and (= mode 0)
+		    (or (string-match "\\`\\*.*" (buffer-name (car buf)))
+			(not (get-buffer-window (car buf))))))
+	   (calc-find-writable-buffer (cdr buf) mode)
+	 (car buf)))
+)
+
+
+(defun calc-edit (n)
+  (interactive "p")
+  (calc-slow-wrapper
+   (if (eq n 0)
+       (setq n (calc-stack-size)))
+   (let* ((flag nil)
+	  (allow-ret (> n 1))
+	  (list (math-showing-full-precision
+		 (mapcar (if (> n 1)
+			     (function (lambda (x)
+					 (math-format-flat-expr x 0)))
+			   (function
+			    (lambda (x)
+			      (if (math-vectorp x) (setq allow-ret t))
+			      (math-format-nice-expr x (screen-width)))))
+			 (if (> n 0)
+			     (calc-top-list n)
+			   (calc-top-list 1 (- n)))))))
+     (calc-edit-mode (list 'calc-finish-stack-edit (or flag n)) allow-ret)
+     (while list
+       (insert (car list) "\n")
+       (setq list (cdr list)))))
+  (calc-show-edit-buffer)
+)
+
+(defun calc-alg-edit (str)
+  (calc-edit-mode '(calc-finish-stack-edit 0))
+  (calc-show-edit-buffer)
+  (insert str "\n")
+  (backward-char 1)
+  (calc-set-command-flag 'do-edit)
+)
+
+(defvar calc-edit-mode-map nil "Keymap for use by the calc-edit command.")
+(if calc-edit-mode-map
+    ()
+  (setq calc-edit-mode-map (make-sparse-keymap))
+  (define-key calc-edit-mode-map "\n" 'calc-edit-finish)
+  (define-key calc-edit-mode-map "\r" 'calc-edit-return)
+  (define-key calc-edit-mode-map "\C-c\C-c" 'calc-edit-finish)
+)
+
+(defun calc-edit-mode (&optional handler allow-ret title)
+  "Calculator editing mode.  Press RET, LFD, or C-c C-c to finish.
+To cancel the edit, simply kill the *Calc Edit* buffer."
+  (interactive)
+  (or handler
+      (error "This command can be used only indirectly through calc-edit."))
+  (let ((oldbuf (current-buffer))
+	(buf (get-buffer-create "*Calc Edit*")))
+    (set-buffer buf)
+    (kill-all-local-variables)
+    (use-local-map calc-edit-mode-map)
+    (setq buffer-read-only nil)
+    (setq truncate-lines nil)
+    (setq major-mode 'calc-edit-mode)
+    (setq mode-name "Calc Edit")
+    (run-hooks 'calc-edit-mode-hook)
+    (make-local-variable 'calc-original-buffer)
+    (setq calc-original-buffer oldbuf)
+    (make-local-variable 'calc-return-buffer)
+    (setq calc-return-buffer oldbuf)
+    (make-local-variable 'calc-one-window)
+    (setq calc-one-window (and (one-window-p t) pop-up-windows))
+    (make-local-variable 'calc-edit-handler)
+    (setq calc-edit-handler handler)
+    (make-local-variable 'calc-restore-trail)
+    (setq calc-restore-trail (get-buffer-window (calc-trail-buffer)))
+    (make-local-variable 'calc-allow-ret)
+    (setq calc-allow-ret allow-ret)
+    (erase-buffer)
+    (insert (or title title "Calc Edit Mode")
+	    ".  Press "
+	    (if (eq (lookup-key (current-global-map) "\e#") 'calc-dispatch)
+		"M-# M-# or C-c C-c"
+	      (if allow-ret "C-c C-c" "RET"))
+	    " to finish, "
+	    (if (eq (lookup-key (current-global-map) "\e#") 'calc-dispatch)
+		"M-# x"
+	      "C-x k RET")
+	    " to cancel.\n"))
+)
+(put 'calc-edit-mode 'mode-class 'special)
+
+(defun calc-show-edit-buffer ()
+  (let ((buf (current-buffer)))
+    (if (and (one-window-p t) pop-up-windows)
+	(pop-to-buffer (get-buffer-create "*Calc Edit*"))
+      (and calc-embedded-info (get-buffer-window (aref calc-embedded-info 1))
+	   (select-window (get-buffer-window (aref calc-embedded-info 1))))
+      (switch-to-buffer (get-buffer-create "*Calc Edit*")))
+    (setq calc-return-buffer buf)
+    (if (and (< (window-width) (screen-width))
+	     calc-display-trail)
+	(let ((win (get-buffer-window (calc-trail-buffer))))
+	  (if win
+	      (delete-window win))))
+    (set-buffer-modified-p nil)
+    (goto-char (point-min))
+    (forward-line 1))
+)
+
+(defun calc-edit-return ()
+  (interactive)
+  (if (and (boundp 'calc-allow-ret) calc-allow-ret)
+      (newline)
+    (calc-edit-finish))
+)
+
+(defun calc-edit-finish (&optional keep)
+  "Finish calc-edit mode.  Parse buffer contents and push them on the stack."
+  (interactive "P")
+  (message "Working...")
+  (or (and (boundp 'calc-original-buffer)
+	   (boundp 'calc-return-buffer)
+	   (boundp 'calc-one-window)
+	   (boundp 'calc-edit-handler)
+	   (boundp 'calc-restore-trail)
+	   (eq major-mode 'calc-edit-mode))
+      (error "This command is valid only in buffers created by calc-edit."))
+  (let ((buf (current-buffer))
+	(original calc-original-buffer)
+	(return calc-return-buffer)
+	(one-window calc-one-window)
+	(disp-trail calc-restore-trail))
+    (save-excursion
+      (if (or (null (buffer-name original))
+	      (progn
+		(set-buffer original)
+		(not (eq major-mode 'calc-mode))))
+	  (error "Original calculator buffer has been corrupted.")))
+    (goto-char (point-min))
+    (if (looking-at "Calc Edit\\|Editing ")
+	(forward-line 1))
+    (if (buffer-modified-p)
+	(eval calc-edit-handler))
+    (if one-window
+	(delete-window))
+    (if (get-buffer-window return)
+	(select-window (get-buffer-window return))
+      (switch-to-buffer return))
+    (if keep
+	(bury-buffer buf)
+      (kill-buffer buf))
+    (if disp-trail
+	(calc-wrapper
+	 (calc-trail-display 1 t)))
+    (message ""))
+)
+
+(defun calc-edit-cancel ()
+  "Cancel calc-edit mode.  Ignore the Calc Edit buffer and don't change stack."
+  (interactive)
+  (let ((calc-edit-handler nil))
+    (calc-edit-finish))
+  (message "(Cancelled)")
+)
+
+(defun calc-finish-stack-edit (num)
+  (let ((buf (current-buffer))
+	(str (buffer-substring (point) (point-max)))
+	(start (point))
+	pos)
+    (if (and (integerp num) (> num 1))
+	(while (setq pos (string-match "\n." str))
+	  (aset str pos ?\,)))
+    (switch-to-buffer calc-original-buffer)
+    (let ((vals (let ((calc-language nil)
+		      (math-expr-opers math-standard-opers))
+		  (and (string-match "[^\n\t ]" str)
+		       (math-read-exprs str)))))
+      (if (eq (car-safe vals) 'error)
+	  (progn
+	    (switch-to-buffer buf)
+	    (goto-char (+ start (nth 1 vals)))
+	    (error (nth 2 vals))))
+      (calc-wrapper
+       (if (symbolp num)
+	   (progn
+	     (set num (car vals))
+	     (calc-refresh-evaltos num))
+	 (if disp-trail
+	     (calc-trail-display 1 t))
+	 (and vals
+	      (let ((calc-simplify-mode (if (eq last-command-char ?\C-j)
+					    'none
+					  calc-simplify-mode)))
+		(if (>= num 0)
+		    (calc-enter-result num "edit" vals)
+		  (calc-enter-result 1 "edit" vals (- num)))))))))
+)
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/calc.el	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,3557 @@
+;; Calculator for GNU Emacs, part I
+;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+;; Written by Dave Gillespie, daveg@synaptics.com.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY.  No author or distributor
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing.  Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License.   A copy of this license is
+;; supposed to have been given to you along with GNU Emacs so you
+;; can know your rights and responsibilities.  It should be in a
+;; file named COPYING.  Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+
+
+
+;;; Calc is split into many files.  This file is the main entry point.
+;;; This file includes autoload commands for various other basic Calc
+;;; facilities.  The more advanced features are based in calc-ext, which
+;;; in turn contains autoloads for the rest of the Calc files.  This
+;;; odd set of interactions is designed to make Calc's loading time
+;;; be as short as possible when only simple calculations are needed.
+
+;;; Suggested usage:
+;;;
+;;;   (autoload 'calc-dispatch "calc" "Emacs Calculator" t nil)
+;;;   (global-set-key "\e#" 'calc-dispatch)
+;;;   Type `M-# M-#' to start.
+;;;
+;;; The Calc home directory must be added to the Emacs load-path:
+;;; 
+;;;   (setq load-path (cons "/x/y/z/calc" load-path))
+;;;
+;;; where "/x/y/z/calc" represents the full name of the Calc home directory.
+;;;
+;;; See the file INSTALL for a complete list of recommeded autoload
+;;; commands (though only calc-dispatch is absolutely necessary).
+
+
+;;; Author's address:
+;;;   Dave Gillespie, daveg@synaptics.com, uunet!synaptx!daveg.
+;;;   Synaptics, Inc., 2698 Orchard Parkway, San Jose, CA 95134.
+;;;
+;;; The old address daveg@csvax.cs.caltech.edu will continue to
+;;; work for the foreseeable future.
+;;;
+;;; The latest version of Calc is always available from anonymous FTP
+;;; on csvax.cs.caltech.edu [131.215.131.131]; look in ~ftp/pub/calc*.
+;;; It should also be available on prep.ai.mit.edu.
+;;;
+;;; Bug reports and suggestions are always welcome!
+
+
+;;; All functions, macros, and Lisp variables defined here begin with one
+;;; of the prefixes "math", "Math", or "calc", with the exceptions of
+;;; "full-calc", "full-calc-keypad", "another-calc", "quick-calc",
+;;; "report-calc-bug", and "defmath".  User-accessible variables begin
+;;; with "var-".
+
+
+
+(provide 'calc)
+
+
+(defun calc-record-compilation-date ()
+  (calc-record-compilation-date-macro)
+)
+(calc-record-compilation-date)
+
+
+;;; The "###autoload" comment will be used by Emacs version 19 for
+;;; maintaining the loaddefs.el file automatically.
+
+;;;###autoload
+(defvar calc-info-filename "calc.info"
+  "*File name in which to look for the Calculator's Info documentation.")
+
+;;;###autoload
+(defvar calc-settings-file "~/.emacs"
+  "*File in which to record permanent settings; default is \"~/.emacs\".")
+
+;;;###autoload
+(defvar calc-autoload-directory nil
+  "Name of directory from which additional \".elc\" files for Calc should be
+loaded.  Should include a trailing \"/\".
+If nil, use original installation directory.
+This can safely be nil as long as the Calc files are on the load-path.")
+
+;;;###autoload
+(defvar calc-gnuplot-name "gnuplot"
+  "*Name of GNUPLOT program, for calc-graph features.")
+
+;;;###autoload
+(defvar calc-gnuplot-plot-command nil
+  "*Name of command for displaying GNUPLOT output; %s = file name to print.")
+
+;;;###autoload
+(defvar calc-gnuplot-print-command "lp %s"
+  "*Name of command for printing GNUPLOT output; %s = file name to print.")
+
+
+;; Address of the author of Calc, for use by report-calc-bug.
+(defvar calc-bug-address "daveg@synaptics.com")
+
+
+;; If T, scan keymaps to find all DEL-like keys.
+;; If NIL, only DEL itself is mapped to calc-pop.
+(defvar calc-scan-for-dels t)
+
+
+
+(defvar calc-extensions-loaded nil)
+
+
+
+;;; IDEAS:
+;;;
+;;;   Fix rewrite mechanism to do less gratuitous rearrangement of terms.
+;;;   Implement a pattern-based "refers" predicate.
+;;;
+;;;   Make it possible to Undo a selection command.
+;;;   Figure out how to allow selecting rows of matrices.
+;;;   If cursor was in selection before, move it after j n, j p, j L, etc.
+;;;   Consider reimplementing calc-delete-selection using rewrites.
+;;;
+;;;   Implement line-breaking in non-flat compositions (is this desirable?).
+;;;   Implement matrix formatting with multi-line components.
+;;;
+;;;   Have "Z R" define a user command based on a set of rewrite rules.
+;;;   Support "incf" and "decf" in defmath definitions.
+;;;   Have defmath generate calls to calc-binary-op or calc-unary-op.
+;;;   Make some way to define algebraic functions using keyboard macros.
+;;;
+;;;   Allow calc-word-size=0 => Common Lisp-style signed bitwise arithmetic.
+;;;   Consider digamma function (and thus arb. prec. Euler's gamma constant).
+;;;   May as well make continued-fractions stuff available to the user.
+;;;
+;;;   How about matrix eigenvalues, SVD, pseudo-inverse, etc.?
+;;;   Should cache matrix inverses as well as decompositions.
+;;;   If dividing by a non-square matrix, use least-squares automatically.
+;;;   Consider supporting matrix exponentials.
+;;;
+;;;   Have ninteg detect and work around singularities at the endpoints.
+;;;   Use an adaptive subdivision algorithm for ninteg.
+;;;   Provide nsum and nprod to go along with ninteg.
+;;;
+;;;   Handle TeX-mode parsing of \matrix{ ... } where ... contains braces.
+;;;   Support AmS-TeX's \{d,t,}frac, \{d,t,}binom notations.
+;;;   Format and parse sums and products in Eqn and Math modes.
+;;;
+;;;   Get math-read-big-expr to read sums, products, etc.
+;;;   Change calc-grab-region to use math-read-big-expr.
+;;;   Have a way to define functions using := in Embedded Mode.
+;;;
+;;;   Support polar plotting with GNUPLOT.
+;;;   Make a calc-graph-histogram function.
+;;;
+;;;   Replace hokey formulas for complex functions with formulas designed
+;;;      to minimize roundoff while maintaining the proper branch cuts.
+;;;   Test accuracy of advanced math functions over whole complex plane.
+;;;   Extend Bessel functions to provide arbitrary precision.
+;;;   Extend advanced math functions to handle error forms and intervals.
+;;;   Provide a better implementation for math-sin-cos-raw.
+;;;   Provide a better implementation for math-hypot.
+;;;   Provide a better implementation for math-make-frac.
+;;;   Provide a better implementation for calcFunc-prfac.
+;;;   Provide a better implementation for calcFunc-factor.
+;;;
+;;;   Provide more examples in the tutorial section of the manual.
+;;;   Cover in the tutorial:  simplification modes, declarations,
+;;;       bitwise stuff, selections, matrix mapping, financial functions.
+;;;   Provide more Lisp programming examples in the manual.
+;;;   Finish the Internals section of the manual (and bring it up to date).
+;;;
+;;;   Tim suggests adding spreadsheet-like features.
+;;;   Implement language modes for Gnuplot, Lisp, Ada, APL, ...?
+;;;
+
+
+;;; For atan series, if x > tan(pi/12) (about 0.268) reduce using the identity
+;;;   atan(x) = atan((x * sqrt(3) - 1) / (sqrt(3) + x)) + pi/6.
+
+
+;;; A better integration algorithm:
+;;;   Use breadth-first instead of depth-first search, as follows:
+;;;	The integral cache allows unfinished integrals in symbolic notation
+;;;	on the righthand side.  An entry with no unfinished integrals on the
+;;;	RHS is "complete"; references to it elsewhere are replaced by the
+;;;	integrated value.  More than one cache entry for the same integral
+;;;	may exist, though if one becomes complete, the others may be deleted.
+;;;	The integrator works by using every applicable rule (such as
+;;;	substitution, parts, linearity, etc.) to generate possible righthand
+;;;	sides, all of which are entered into the cache.  Now, as long as the
+;;;	target integral is not complete (and the time limit has not run out)
+;;;	choose an incomplete integral from the cache and, for every integral
+;;;	appearing in its RHS's, add those integrals to the cache using the
+;;;	same substitition, parts, etc. rules.  The cache should be organized
+;;;	as a priority queue, choosing the "simplest" incomplete integral at
+;;;	each step, or choosing randomly among equally simple integrals.
+;;;	Simplicity equals small size, and few steps removed from the original
+;;;	target integral.  Note that when the integrator finishes, incomplete
+;;;	integrals can be left in the cache, so the algorithm can start where
+;;;	it left off if another similar integral is later requested.
+;;;   Breadth-first search would avoid the nagging problem of, e.g., whether
+;;;   to use parts or substitution first, and which decomposition is best.
+;;;   All are tried, and any path that diverges will quickly be put on the
+;;;   back burner by the priority queue.
+;;;   Note: Probably a good idea to call math-simplify-extended before
+;;;   measuring a formula's simplicity.
+
+
+
+
+
+
+;; Calculator stack.
+;; Entries are 3-lists:  Formula, Height (in lines), Selection (or nil).
+(defvar calc-stack '((top-of-stack 1 nil)))
+
+;; Index into calc-stack of "top" of stack.
+;; This is 1 unless calc-truncate-stack has been used.
+;;(defvar calc-stack-top 1)
+
+;; If non-NIL, load the calc-ext module automatically when calc is loaded.
+;;(defvar calc-always-load-extensions nil)
+
+;; If non-NIL, display line numbers in Calculator stack.
+;;(defvar calc-line-numbering t)
+
+;; If non-NIL, break long values across multiple lines in Calculator stack.
+;;(defvar calc-line-breaking t)
+
+;; If NIL, stack display is left-justified.
+;; If 'right, stack display is right-justified.
+;; If 'center, stack display is centered."
+;;(defvar calc-display-just nil)
+
+;; Horizontal origin of displayed stack entries.
+;; In left-justified mode, this is effectively indentation.  (Default 0).
+;; In right-justified mode, this is effectively window width.
+;; In centered mode, center of stack entry is placed here.
+;;(defvar calc-display-origin nil)
+
+;; Radix for entry and display of numbers in calc-mode, 2-36.
+;;(defvar calc-number-radix 10)
+
+;; If non-NIL, leading zeros are provided to pad integers to calc-word-size.
+;;(defvar calc-leading-zeros nil)
+
+;; If non-NIL, group digits in large displayed integers by inserting spaces.
+;; If an integer, group that many digits at a time.
+;; If 't', use 4 for binary and hex, 3 otherwise.
+;;(defvar calc-group-digits nil)
+
+;; The character (in the form of a string) to be used for grouping digits.
+;; This is used only when calc-group-digits mode is on.
+;;(defvar calc-group-char ",")
+
+;; The character (in the form of a string) to be used as a decimal point.
+;;(defvar calc-point-char ".")
+
+;; Format of displayed fractions; a string of one or two of ":" or "/".
+;;(defvar calc-frac-format '(":" nil))
+
+;; If non-NIL, prefer fractional over floating-point results.
+;;(defvar calc-prefer-frac nil)
+
+;; Format of displayed hours-minutes-seconds angles, a format string.
+;; String must contain three %s marks for hours, minutes, seconds respectively.
+;;(defvar calc-hms-format "%s@ %s' %s\"")
+
+;; Format of displayed date forms.
+;;(defvar calc-date-format '((H ":" mm ":" SS pp " ") Www " " Mmm " " D ", " YYYY))
+
+;; Format to use for display of floating-point numbers in calc-mode.
+;; Must be a list of one of the following forms:
+;;  (float 0)      Floating point format, display full precision.
+;;  (float N)      N > 0: Floating point format, at most N significant figures.
+;;  (float -N)     -N < 0: Floating point format, calc-internal-prec - N figs.
+;;  (fix N)        N >= 0: Fixed point format, N places after decimal point.
+;;  (sci 0)        Scientific notation, full precision.
+;;  (sci N)        N > 0: Scientific notation, N significant figures.
+;;  (sci -N)       -N < 0: Scientific notation, calc-internal-prec - N figs.
+;;  (eng 0)        Engineering notation, full precision.
+;;  (eng N)        N > 0: Engineering notation, N significant figures.
+;;  (eng -N)       -N < 0: Engineering notation, calc-internal-prec - N figs.
+;;(defvar calc-float-format '(float 0))
+
+;; Format to use when full precision must be displayed.
+;;(defvar calc-full-float-format '(float 0))
+
+;; Format to use for display of complex numbers in calc-mode.  Must be one of:
+;;   nil            Use (x, y) form.
+;;   i              Use x + yi form.
+;;   j              Use x + yj form.
+;;(defvar calc-complex-format nil)
+
+;; Preferred form, either 'cplx or 'polar, for complex numbers.
+;;(defvar calc-complex-mode 'cplx)
+
+;; If NIL, 1 / 0 is left unsimplified.
+;; If 0, 1 / 0 is changed to inf (zeros are considered positive).
+;; Otherwise, 1 / 0 is changed to uinf (undirected infinity).
+;;(defvar calc-infinite-mode nil)
+
+;; If non-NIL, display vectors of byte-sized integers as strings.
+;;(defvar calc-display-strings nil)
+
+;; If NIL, vector elements are left-justified.
+;; If 'right, vector elements are right-justified.
+;; If 'center, vector elements are centered."
+;;(defvar calc-matrix-just 'center)
+
+;; If non-NIL, display vectors one element per line.
+;;(defvar calc-break-vectors nil)
+
+;; If non-NIL, display long vectors in full.  If NIL, use abbreviated form.
+;;(defvar calc-full-vectors t)
+
+;; If non-NIL, display long vectors in full in the trail.
+;;(defvar calc-full-trail-vectors t)
+
+;; If non-NIL, separate elements of displayed vectors with this string.
+;;(defvar calc-vector-commas ",")
+
+;; If non-NIL, surround displayed vectors with these characters.
+;;(defvar calc-vector-brackets "[]")
+
+;; A list of code-letter symbols that control "big" matrix display.
+;; If 'R is present, display inner brackets for matrices.
+;; If 'O is present, display outer brackets for matrices (above/below).
+;; If 'C is present, display outer brackets for matrices (centered).
+;;(defvar calc-matrix-brackets '(R O))
+
+;; Language or format for entry and display of stack values.  Must be one of:
+;;   nil            Use standard Calc notation.
+;;   flat           Use standard Calc notation, one-line format.
+;;   big 	    Display formulas in 2-d notation (enter w/std notation).
+;;   unform	    Use unformatted display: add(a, mul(b,c)).
+;;   c              Use C language notation.
+;;   pascal         Use Pascal language notation.
+;;   fortran        Use Fortran language notation.
+;;   tex            Use TeX notation.
+;;   eqn	    Use eqn notation.
+;;   math           Use Mathematica(tm) notation.
+;;   maple	    Use Maple notation.
+;;(defvar calc-language nil)
+
+;; Numeric prefix argument for the command that set calc-language.
+;;(defvar calc-language-option nil)
+
+;; Open-parenthesis string for function call notation.
+;;(defvar calc-function-open "(")
+
+;; Close-parenthesis string for function call notation.
+;;(defvar calc-function-close ")")
+
+;; Function through which to pass strings after formatting.
+;;(defvar calc-language-output-filter nil)
+
+;; Function through which to pass strings before parsing.
+;;(defvar calc-language-input-filter nil)
+
+;; Formatting function used for non-decimal numbers.
+;;(defvar calc-radix-formatter nil)
+
+;; Label to display at left of formula.
+;;(defvar calc-left-label "")
+
+;; Label to display at right of formula.
+;;(defvar calc-right-label "")
+
+;; Minimum number of bits per word, if any, for binary operations in calc-mode.
+;;(defvar calc-word-size 32)
+
+;; Most recently used value of M in a modulo form.
+;;(defvar calc-previous-modulo nil)
+
+;; Type of simplification applied to results.
+;; If 'none, results are not simplified when pushed on the stack.
+;; If 'num, functions are simplified only when args are constant.
+;; If NIL, only fast simplifications are applied.
+;; If 'binary, math-clip is applied if appropriate.
+;; If 'alg, math-simplify is applied.
+;; If 'ext, math-simplify-extended is applied.
+;; If 'units, math-simplify-units is applied.
+;;(defvar calc-simplify-mode nil)
+
+;; If non-NIL, recompute evalto's automatically when necessary.
+;;(defvar calc-auto-recompute t)
+
+;; If non-NIL, display shows unformatted Lisp exprs.  (For debugging)
+;;(defvar calc-display-raw nil)
+
+;; Number of digits of internal precision for calc-mode calculations.
+;;(defvar calc-internal-prec 12)
+
+;; If non-NIL, next operation is Inverse.
+;;(defvar calc-inverse-flag nil)
+
+;; If non-NIL, next operation is Hyperbolic.
+;;(defvar calc-hyperbolic-flag nil)
+
+;; If non-NIL, next operation should not remove its arguments from stack.
+;;(defvar calc-keep-args-flag nil)
+
+;; If deg, angles are in degrees; if rad, angles are in radians.
+;; If hms, angles are in degrees-minutes-seconds.
+;;(defvar calc-angle-mode 'deg)
+
+;; If non-NIL, numeric entry accepts whole algebraic expressions.
+;; If NIL, algebraic expressions must be preceded by "'".
+;;(defvar calc-algebraic-mode nil)
+
+;; Like calc-algebraic-mode except only affects ( and [ keys.
+;;(defvar calc-incomplete-algebraic-mode nil)
+
+;; If non-NIL, inexact numeric computations like sqrt(2) are postponed.
+;; If NIL, computations on numbers always yield numbers where possible.
+;;(defvar calc-symbolic-mode nil)
+
+;; If 'matrix, variables are assumed to be matrix-valued.
+;; If a number, variables are assumed to be NxN matrices.
+;; If 'scalar, variables are assumed to be scalar-valued.
+;; If NIL, symbolic math routines make no assumptions about variables.
+;;(defvar calc-matrix-mode nil)
+
+;; If non-NIL, shifted letter keys are prefix keys rather than normal meanings.
+;;(defvar calc-shift-prefix nil)
+
+;; Initial height of Calculator window.
+;;(defvar calc-window-height 7)
+
+;; If non-NIL, M-x calc creates a window to display Calculator trail.
+;;(defvar calc-display-trail t)
+
+;; If non-NIL, selected sub-formulas are shown by obscuring rest of formula.
+;; If NIL, selected sub-formulas are highlighted by obscuring the sub-formulas.
+;;(defvar calc-show-selections t)
+
+;; If non-NIL, commands operate only on selected portions of formulas.
+;; If NIL, selections displayed but ignored.
+;;(defvar calc-use-selections t)
+
+;; If non-NIL, selection hides deep structure of associative formulas.
+;;(defvar calc-assoc-selections t)
+
+;; If non-NIL, display "Working..." for potentially slow Calculator commands.
+;;(defvar calc-display-working-message 'lots)
+
+;; If non-NIL, automatically execute a "why" command to explain odd results.
+;;(defvar calc-auto-why nil)
+
+;; If non-NIL, display timing information on each slow command.
+;;(defvar calc-timing nil)
+
+;; Floating-point numbers with this positive exponent or higher above the
+;; current precision are displayed in scientific notation in calc-mode.
+(defvar calc-display-sci-high 0)
+
+;; Floating-point numbers with this negative exponent or lower are displayed
+;; scientific notation in calc-mode.
+(defvar calc-display-sci-low -3)
+
+
+;; List of used-defined strings to append to Calculator mode line.
+(defvar calc-other-modes nil)
+
+;; List of strings for Y prefix help.
+(defvar calc-Y-help-msgs nil)
+
+;; T if calc-settings-file has been loaded yet.
+(defvar calc-loaded-settings-file nil)
+
+
+
+(defconst calc-mode-var-list '((calc-always-load-extensions nil)
+			       (calc-mode-save-mode local)
+			       (calc-line-numbering t)
+			       (calc-line-breaking t)
+			       (calc-display-just nil)
+			       (calc-display-origin nil)
+			       (calc-left-label "")
+			       (calc-right-label "")
+			       (calc-number-radix 10)
+			       (calc-leading-zeros nil)
+			       (calc-group-digits nil)
+			       (calc-group-char ",")
+			       (calc-point-char ".")
+			       (calc-frac-format (":" nil))
+			       (calc-prefer-frac nil)
+			       (calc-hms-format "%s@ %s' %s\"")
+			       (calc-date-format ((H ":" mm C SS pp " ")
+						  Www " " Mmm " " D ", " YYYY))
+			       (calc-standard-date-formats
+				("N"
+				 "<H:mm:SSpp >Www Mmm D, YYYY"
+				 "D Mmm YYYY<, h:mm:SS>"
+				 "Www Mmm BD< hh:mm:ss> YYYY"
+				 "M/D/Y< H:mm:SSpp>"
+				 "D.M.Y< h:mm:SS>"
+				 "M-D-Y< H:mm:SSpp>"
+				 "D-M-Y< h:mm:SS>"
+				 "j<, h:mm:SS>"
+				 "YYddd< hh:mm:ss>"))
+			       (calc-float-format (float 0))
+			       (calc-full-float-format (float 0))
+			       (calc-complex-format nil)
+			       (calc-matrix-just center)
+			       (calc-full-vectors t)
+			       (calc-full-trail-vectors t)
+			       (calc-break-vectors nil)
+			       (calc-vector-commas ",")
+			       (calc-vector-brackets "[]")
+			       (calc-matrix-brackets (R O))
+			       (calc-complex-mode cplx)
+			       (calc-infinite-mode nil)
+			       (calc-display-strings nil)
+			       (calc-simplify-mode nil)
+			       (calc-auto-recompute t)
+			       (calc-word-size 32)
+			       (calc-previous-modulo nil)
+			       (calc-display-raw nil)
+			       (calc-internal-prec 12)
+			       (calc-angle-mode deg)
+			       (calc-algebraic-mode nil)
+			       (calc-incomplete-algebraic-mode nil)
+			       (calc-symbolic-mode nil)
+			       (calc-matrix-mode nil)
+			       (calc-autorange-units nil)
+			       (calc-shift-prefix nil)
+			       (calc-window-height 7)
+			       (calc-was-keypad-mode nil)
+			       (calc-full-mode nil)
+			       (calc-language nil)
+			       (calc-language-option nil)
+			       (calc-user-parse-tables nil)
+			       (calc-show-selections t)
+			       (calc-use-selections t)
+			       (calc-assoc-selections t)
+			       (calc-display-trail t)
+			       (calc-display-working-message lots)
+			       (calc-auto-why 'maybe)
+			       (calc-timing nil)
+			       (calc-gnuplot-default-device "default")
+			       (calc-gnuplot-default-output "STDOUT")
+			       (calc-gnuplot-print-device "postscript")
+			       (calc-gnuplot-print-output "auto")
+			       (calc-gnuplot-geometry nil)
+			       (calc-graph-default-resolution 15)
+			       (calc-graph-default-resolution-3d 5)
+			       (calc-invocation-macro nil)))
+
+(defconst calc-local-var-list '(calc-stack
+				calc-stack-top
+				calc-undo-list
+				calc-redo-list
+				calc-always-load-extensions
+				calc-mode-save-mode
+				calc-display-raw
+				calc-line-numbering
+				calc-line-breaking
+				calc-display-just
+				calc-display-origin
+				calc-left-label
+				calc-right-label
+				calc-auto-why
+				calc-algebraic-mode
+				calc-incomplete-algebraic-mode
+				calc-symbolic-mode
+				calc-matrix-mode
+				calc-inverse-flag
+				calc-hyperbolic-flag
+				calc-keep-args-flag
+				calc-angle-mode
+				calc-number-radix
+				calc-leading-zeros
+				calc-group-digits
+				calc-group-char
+				calc-point-char
+				calc-frac-format
+				calc-prefer-frac
+				calc-hms-format
+				calc-date-format
+				calc-standard-date-formats
+				calc-float-format
+				calc-full-float-format
+				calc-complex-format
+				calc-matrix-just
+				calc-full-vectors
+				calc-full-trail-vectors
+				calc-break-vectors
+				calc-vector-commas
+				calc-vector-brackets
+				calc-matrix-brackets
+				calc-complex-mode
+				calc-infinite-mode
+				calc-display-strings
+				calc-simplify-mode
+				calc-auto-recompute
+				calc-autorange-units
+				calc-show-plain
+				calc-show-selections
+				calc-use-selections
+				calc-assoc-selections
+				calc-word-size
+				calc-internal-prec))
+
+
+(defun calc-init-base ()
+
+  ;; Verify that Calc is running on the right kind of system.
+  (setq calc-emacs-type-epoch (and (fboundp 'epoch::version) epoch::version)
+	calc-emacs-type-19 (not (or calc-emacs-type-epoch
+				    (string-lessp emacs-version "19")))
+	calc-emacs-type-lucid (not (not (string-match "Lucid" emacs-version)))
+	calc-emacs-type-gnu19 (and calc-emacs-type-19
+				   (not calc-emacs-type-lucid)))
+
+  ;; Set up the standard keystroke (M-#) to run the Calculator, if that key
+  ;; has not yet been bound to anything.  For best results, the user should
+  ;; do this before Calc is even loaded, so that M-# can auto-load Calc.
+  (or (global-key-binding "\e#")
+      (global-set-key "\e#" 'calc-dispatch))
+
+  ;; Set up the autoloading linkage.
+  (let ((name (and (fboundp 'calc-dispatch)
+		   (eq (car-safe (symbol-function 'calc-dispatch)) 'autoload)
+		   (nth 1 (symbol-function 'calc-dispatch))))
+	(p load-path))
+
+    ;; If Calc files exist on the load-path, we're all set.
+    (while (and p (not (file-exists-p
+			(expand-file-name "calc-misc.elc" (car p)))))
+      (setq p (cdr p)))
+    (or p
+
+	;; If Calc is autoloaded using a path name, look there for Calc files.
+	;; This works for both relative ("calc/calc.elc") and absolute paths.
+	(and name (file-name-directory name)
+	     (let ((p2 load-path)
+		   (name2 (concat (file-name-directory name)
+				  "calc-misc.elc")))
+	       (while (and p2 (not (file-exists-p
+				    (expand-file-name name2 (car p2)))))
+		 (setq p2 (cdr p2)))
+	       (if p2
+		   (setq load-path (nconc load-path
+					  (list
+					   (directory-file-name
+					    (file-name-directory
+					     (expand-file-name
+					      name (car p2))))))))))
+
+	;; If calc-autoload-directory is given, use that (and hope it works!).
+	(and calc-autoload-directory
+	     (not (equal calc-autoload-directory ""))
+	     (setq load-path (nconc load-path
+				    (list (directory-file-name
+					   calc-autoload-directory)))))))
+
+  ;; The following modes use specially-formatted data.
+  (put 'calc-mode 'mode-class 'special)
+  (put 'calc-trail-mode 'mode-class 'special)
+  
+  ;; Define "inexact-result" as an e-lisp error symbol.
+  (put 'inexact-result 'error-conditions '(error inexact-result calc-error))
+  (put 'inexact-result 'error-message "Calc internal error (inexact-result)")
+  
+  ;; Define "math-overflow" and "math-underflow" as e-lisp error symbols.
+  (put 'math-overflow 'error-conditions '(error math-overflow calc-error))
+  (put 'math-overflow 'error-message "Floating-point overflow occurred")
+  (put 'math-underflow 'error-conditions '(error math-underflow calc-error))
+  (put 'math-underflow 'error-message "Floating-point underflow occurred")
+  
+  (setq calc-version "2.02f"
+	calc-version-date "Sun Dec 15 1996"
+	calc-trail-pointer nil		; "Current" entry in trail buffer.
+        calc-trail-overlay nil		; Value of overlay-arrow-string.
+	calc-was-split nil		; Had multiple windows before Calc.
+        calc-undo-list nil		; List of previous operations for undo.
+        calc-redo-list nil		; List of recent undo operations.
+        calc-main-buffer nil		; Pointer to Calculator buffer.
+	calc-trail-buffer nil		; Pointer to Calc Trail buffer.
+        calc-why nil			; Explanations of most recent errors.
+        calc-next-why nil
+	calc-inverse-flag nil
+	calc-hyperbolic-flag nil
+	calc-keep-args-flag nil
+	calc-function-open "("
+	calc-function-close ")"
+	calc-language-output-filter nil
+	calc-language-input-filter nil
+	calc-radix-formatter nil
+        calc-last-kill nil		; Last number killed in calc-mode.
+        calc-previous-alg-entry nil	; Previous algebraic entry.
+        calc-dollar-values nil		; Values to be used for '$'.
+        calc-dollar-used nil		; Highest order of '$' that occurred.
+	calc-hashes-used nil            ; Highest order of '#' that occurred.
+        calc-quick-prev-results nil	; Previous results from Quick Calc.
+	calc-said-hello nil		; Has welcome message been said yet?
+	calc-executing-macro nil	; Kbd macro executing from "K" key.
+	calc-any-selections nil 	; Nil means no selections present.
+	calc-help-phase 0		; Count of consecutive "?" keystrokes.
+	calc-full-help-flag nil		; Executing calc-full-help?
+	calc-refresh-count 0		; Count of calc-refresh calls.
+	calc-display-dirty nil
+	calc-prepared-composition nil
+	calc-selection-cache-default-entry nil
+	calc-embedded-info nil
+	calc-embedded-active nil
+	calc-standalone-flag nil
+	var-EvalRules nil
+	math-eval-rules-cache-tag t
+	math-radix-explicit-format t
+	math-expr-function-mapping nil
+	math-expr-variable-mapping nil
+	math-read-expr-quotes nil
+	math-working-step nil
+	math-working-step-2 nil
+        var-i '(special-const (math-imaginary 1))
+        var-pi '(special-const (math-pi))
+        var-e '(special-const (math-e))
+	var-phi '(special-const (math-phi))
+        var-gamma '(special-const (math-gamma-const))
+	var-Modes '(special-const (math-get-modes-vec)))
+
+  (mapcar (function (lambda (v) (or (boundp (car v)) (set (car v) (nth 1 v)))))
+	  calc-mode-var-list)
+  (mapcar (function (lambda (v) (or (boundp v) (set v nil))))
+	  calc-local-var-list)
+
+  (if (boundp 'calc-mode-map)
+      nil
+    (setq calc-mode-map (make-keymap))
+    (suppress-keymap calc-mode-map t)
+    (define-key calc-mode-map "+" 'calc-plus)
+    (define-key calc-mode-map "-" 'calc-minus)
+    (define-key calc-mode-map "*" 'calc-times)
+    (define-key calc-mode-map "/" 'calc-divide)
+    (define-key calc-mode-map "%" 'calc-mod)
+    (define-key calc-mode-map "&" 'calc-inv)
+    (define-key calc-mode-map "^" 'calc-power)
+    (define-key calc-mode-map "\M-%" 'calc-percent)
+    (define-key calc-mode-map "e" 'calcDigit-start)
+    (define-key calc-mode-map "i" 'calc-info)
+    (define-key calc-mode-map "n" 'calc-change-sign)
+    (define-key calc-mode-map "q" 'calc-quit)
+    (define-key calc-mode-map "Y" 'nil)
+    (define-key calc-mode-map "Y?" 'calc-shift-Y-prefix-help)
+    (define-key calc-mode-map "?" 'calc-help)
+    (define-key calc-mode-map " " 'calc-enter)
+    (define-key calc-mode-map "'" 'calc-algebraic-entry)
+    (define-key calc-mode-map "$" 'calc-auto-algebraic-entry)
+    (define-key calc-mode-map "\"" 'calc-auto-algebraic-entry)
+    (define-key calc-mode-map "\t" 'calc-roll-down)
+    (define-key calc-mode-map "\M-\t" 'calc-roll-up)
+    (define-key calc-mode-map "\C-m" 'calc-enter)
+    (define-key calc-mode-map "\M-\C-m" 'calc-last-args-stub)
+    (define-key calc-mode-map "\C-j" 'calc-over)
+
+    (mapcar (function
+	     (lambda (x)
+	       (define-key calc-mode-map (char-to-string x) 'undefined)))
+	    "lOW")
+    (mapcar (function
+	     (lambda (x)
+	       (define-key calc-mode-map (char-to-string x)
+		 'calc-missing-key)))
+	    (concat "ABCDEFGHIJKLMNPQRSTUVXZabcdfghjkmoprstuvwxyz"
+		    ":\\|!()[]<>{},;=~`\C-k\M-k\C-w\M-w\C-y\C-_"))
+    (mapcar (function
+	     (lambda (x)
+	       (define-key calc-mode-map (char-to-string x) 'calcDigit-start)))
+	    "_0123456789.#@")
+
+    (setq calc-digit-map (make-keymap))
+    (if calc-emacs-type-lucid
+	(map-keymap (function
+		     (lambda (keys bind)
+		       (define-key calc-digit-map keys
+			 (if (eq bind 'undefined)
+			     'undefined 'calcDigit-nondigit))))
+		    calc-mode-map)
+      (let ((cmap (if calc-emacs-type-19 (nth 1 calc-mode-map) calc-mode-map))
+	    (dmap (if calc-emacs-type-19 (nth 1 calc-digit-map)
+		    calc-digit-map))
+	    (i 0))
+	(while (< i 128)
+	  (aset dmap i
+		(if (eq (aref cmap i) 'undefined)
+		    'undefined 'calcDigit-nondigit))
+	  (setq i (1+ i)))))
+    (mapcar (function
+	     (lambda (x)
+	       (define-key calc-digit-map (char-to-string x)
+		 'calcDigit-key)))
+	    "_0123456789.e+-:n#@oh'\"mspM")
+    (mapcar (function
+	     (lambda (x)
+	       (define-key calc-digit-map (char-to-string x)
+		 'calcDigit-letter)))
+	    "abcdfgijklqrtuvwxyzABCDEFGHIJKLNOPQRSTUVWXYZ")
+    (define-key calc-digit-map "'" 'calcDigit-algebraic)
+    (define-key calc-digit-map "`" 'calcDigit-edit)
+    (define-key calc-digit-map "\C-g" 'abort-recursive-edit)
+
+    (mapcar (function
+	     (lambda (x)
+	       (condition-case err
+		   (progn
+		     (define-key calc-digit-map x 'calcDigit-backspace)
+		     (define-key calc-mode-map x 'calc-pop)
+		     (define-key calc-mode-map
+		       (if (vectorp x)
+			   (if calc-emacs-type-lucid
+			       (if (= (length x) 1)
+				   (vector (if (consp (aref x 0))
+					       (cons 'meta (aref x 0))
+					     (list 'meta (aref x 0))))
+				 "\e\C-d")
+			     (vconcat "\e" x))
+			 (concat "\e" x))
+		       'calc-pop-above))
+		 (error nil))))
+	    (if calc-scan-for-dels
+		(append (where-is-internal 'delete-backward-char global-map)
+			(where-is-internal 'backward-delete-char global-map)
+			'("\C-d"))
+	      '("\177" "\C-d")))
+
+    (setq calc-dispatch-map (make-keymap))
+    (mapcar (function
+	     (lambda (x)
+	       (define-key calc-dispatch-map (char-to-string (car x)) (cdr x))
+	       (if (string-match "abcdefhijklnopqrstuwxyz"
+				 (char-to-string (car x)))
+		   (define-key calc-dispatch-map
+		     (char-to-string (- (car x) ?a -1)) (cdr x)))
+	       (define-key calc-dispatch-map (format "\e%c" (car x)) (cdr x))))
+	    '( ( ?a . calc-embedded-activate )
+	       ( ?b . calc-big-or-small )
+	       ( ?c . calc )
+	       ( ?d . calc-embedded-duplicate )
+	       ( ?e . calc-embedded )
+	       ( ?f . calc-embedded-new-formula )
+	       ( ?g . calc-grab-region )
+	       ( ?h . calc-dispatch-help )
+	       ( ?i . calc-info )
+	       ( ?j . calc-embedded-select )
+	       ( ?k . calc-keypad )
+	       ( ?l . calc-load-everything )
+	       ( ?m . read-kbd-macro )
+	       ( ?n . calc-embedded-next )
+	       ( ?o . calc-other-window )
+	       ( ?p . calc-embedded-previous )
+	       ( ?q . quick-calc )
+	       ( ?r . calc-grab-rectangle )
+	       ( ?s . calc-info-summary )
+	       ( ?t . calc-tutorial )
+	       ( ?u . calc-embedded-update-formula )
+	       ( ?w . calc-embedded-word )
+	       ( ?x . calc-quit )
+	       ( ?y . calc-copy-to-buffer )
+	       ( ?z . calc-user-invocation )
+	       ( ?= . calc-embedded-update-formula )
+	       ( ?\' . calc-embedded-new-formula )
+	       ( ?\` . calc-embedded-edit )
+	       ( ?: . calc-grab-sum-down )
+	       ( ?_ . calc-grab-sum-across )
+	       ( ?0 . calc-reset )
+	       ( ?# . calc-same-interface )
+	       ( ?? . calc-dispatch-help ) ))
+    )
+
+  (autoload 'calc-extensions "calc-ext")
+  (autoload 'calc-need-macros "calc-macs")
+
+;;;; (Autoloads here)
+  (mapcar (function (lambda (x)
+    (mapcar (function (lambda (func)
+      (autoload func (car x)))) (cdr x))))
+    '(
+
+ ("calc-aent" calc-Need-calc-aent calc-alg-digit-entry calc-alg-entry
+calc-check-user-syntax calc-do-alg-entry calc-do-calc-eval
+calc-do-quick-calc calc-match-user-syntax math-build-parse-table
+math-find-user-tokens math-read-expr-list math-read-exprs math-read-if
+math-read-token math-remove-dashes)
+
+ ("calc-misc" calc-Need-calc-misc calc-delete-windows-keep
+calc-do-handle-whys calc-do-refresh calc-num-prefix-name
+calc-record-list calc-record-why calc-report-bug calc-roll-down-stack
+calc-roll-up-stack calc-temp-minibuffer-message calcFunc-floor
+calcFunc-inv calcFunc-trunc math-concat math-constp math-div2
+math-div2-bignum math-do-working math-evenp math-fixnatnump
+math-fixnump math-floor math-imod math-ipow math-looks-negp math-mod
+math-negp math-posp math-pow math-read-radix-digit math-reject-arg
+math-trunc math-zerop)
+
+))
+
+  (mapcar (function (lambda (x)
+    (mapcar (function (lambda (cmd)
+      (autoload cmd (car x) nil t))) (cdr x))))
+    '(
+
+ ("calc-aent" calc-algebraic-entry calc-auto-algebraic-entry
+calcDigit-algebraic calcDigit-edit)
+
+ ("calc-misc" another-calc calc-big-or-small calc-dispatch-help
+calc-help calc-info calc-info-summary calc-inv calc-last-args-stub
+calc-missing-key calc-mod calc-other-window calc-over calc-percent
+calc-pop-above calc-power calc-roll-down calc-roll-up
+calc-shift-Y-prefix-help calc-tutorial calcDigit-letter
+report-calc-bug)
+
+))
+
+)
+
+(calc-init-base)
+
+
+;;;###autoload (global-set-key "\e#" 'calc-dispatch)
+
+;;;###autoload
+(defun calc-dispatch (&optional arg)
+  "Invoke the GNU Emacs Calculator.  See calc-dispatch-help for details."
+  (interactive "P")
+  (sit-for echo-keystrokes)
+  (condition-case err   ; look for other keys bound to calc-dispatch
+      (let ((keys (this-command-keys)))
+	(or (not (stringp keys))
+	    (string-match "\\`\C-u\\|\\`\e[-0-9#]\\|`[\M--\M-0-\M-9]" keys)
+	    (eq (lookup-key calc-dispatch-map keys) 'calc-same-interface)
+	    (progn
+	      (and (string-match "\\`[\C-@-\C-_]" keys)
+		   (symbolp
+		    (lookup-key calc-dispatch-map (substring keys 0 1)))
+		   (define-key calc-dispatch-map (substring keys 0 1) nil))
+	      (define-key calc-dispatch-map keys 'calc-same-interface))))
+    (error nil))
+  (calc-do-dispatch arg)
+)
+
+(defun calc-do-dispatch (arg)
+  (let ((key (calc-read-key-sequence
+	      (if calc-dispatch-help
+		  "Calc options: Calc, Keypad, Quick, Embed; eXit; Info, Tutorial; Grab; ?=more"
+		(format "%s  (Type ? for a list of Calc options)"
+			(key-description (this-command-keys))))
+	      calc-dispatch-map)))
+    (setq key (lookup-key calc-dispatch-map key))
+    (message "")
+    (if key
+	(progn
+	  (or (commandp key) (calc-extensions))
+	  (call-interactively key))
+      (beep)))
+)
+(setq calc-dispatch-help nil)
+
+(defun calc-read-key-sequence (prompt map)
+  (let ((prompt2 (format "%s " (key-description (this-command-keys))))
+	(glob (current-global-map))
+	(loc (current-local-map)))
+    (or (input-pending-p) (message prompt))
+    (let ((key (calc-read-key t)))
+      (calc-unread-command (cdr key))
+      (unwind-protect
+	  (progn
+	    (use-global-map map)
+	    (use-local-map nil)
+	    (read-key-sequence
+	     (if (commandp (key-binding (if calc-emacs-type-19
+					    (vector (cdr key))
+					  (char-to-string (cdr key)))))
+		 "" prompt2)))
+	(use-global-map glob)
+	(use-local-map loc))))
+)
+
+
+
+(defun calc-mode ()
+  "Calculator major mode.
+
+This is an RPN calculator featuring arbitrary-precision integer, rational,
+floating-point, complex, matrix, and symbolic arithmetic.
+
+RPN calculation:  2 RET 3 +    produces 5.
+Algebraic style:  ' 2+3 RET    produces 5.
+
+Basic operators are +, -, *, /, ^, & (reciprocal), % (modulo), n (change-sign).
+
+Press ? repeatedly for more complete help.  Press `h i' to read the
+Calc manual on-line, `h s' to read the summary, or `h t' for the tutorial.
+
+Notations:  3.14e6     3.14 * 10^6
+            _23        negative number -23 (or type `23 n')
+            17:3       the fraction 17/3
+            5:2:3      the fraction 5 and 2/3
+            16#12C     the integer 12C base 16 = 300 base 10
+            8#177:100  the fraction 177:100 base 8 = 127:64 base 10
+            (2, 4)     complex number 2 + 4i
+            (2; 4)     polar complex number (r; theta)
+            [1, 2, 3]  vector  ([[1, 2], [3, 4]] is a matrix)
+            [1 .. 4)   semi-open interval, 1 <= x < 4
+            2 +/- 3    (p key) number with mean 2, standard deviation 3
+            2 mod 3    (M key) number 2 computed modulo 3
+	    <1 jan 91> Date form (enter using ' key)
+
+
+\\{calc-mode-map}
+"
+  (interactive)
+  (mapcar (function
+	   (lambda (v) (set-default v (symbol-value v)))) calc-local-var-list)
+  (kill-all-local-variables)
+  (use-local-map (if (eq calc-algebraic-mode 'total)
+		     (progn (calc-extensions) calc-alg-map) calc-mode-map))
+  (mapcar (function (lambda (v) (make-local-variable v))) calc-local-var-list)
+  (make-local-variable 'overlay-arrow-position)
+  (make-local-variable 'overlay-arrow-string)
+  (setq truncate-lines t)
+  (setq buffer-read-only t)
+  (setq major-mode 'calc-mode)
+  (setq mode-name "Calculator")
+  (setq calc-stack-top (length (or (memq (assq 'top-of-stack calc-stack)
+					 calc-stack)
+				   (setq calc-stack (list (list 'top-of-stack
+								1 nil))))))
+  (setq calc-stack-top (- (length calc-stack) calc-stack-top -1))
+  (or calc-loaded-settings-file
+      (string-match "\\.emacs" calc-settings-file)
+      (progn
+	(setq calc-loaded-settings-file t)
+	(load calc-settings-file t)))   ; t = missing-ok
+  (if (and (eq window-system 'x) (boundp 'mouse-map))
+      (substitute-key-definition 'x-paste-text 'calc-x-paste-text
+				 mouse-map))
+  (let ((p command-line-args))
+    (while p
+      (and (equal (car p) "-f")
+	   (string-match "calc" (nth 1 p))
+	   (string-match "full" (nth 1 p))
+	   (setq calc-standalone-flag t))
+      (setq p (cdr p))))
+  (run-hooks 'calc-mode-hook)
+  (calc-refresh t)
+  (calc-set-mode-line)
+  ;; The calc-defs variable is a relic.  Use calc-define properties instead.
+  (if (and (boundp 'calc-defs)
+	   calc-defs)
+      (progn
+	(message "Evaluating calc-defs...")
+	(calc-need-macros)
+	(eval (cons 'progn calc-defs))
+	(setq calc-defs nil)
+	(calc-set-mode-line)))
+  (calc-check-defines)
+)
+
+(defun calc-check-defines ()
+  (if (symbol-plist 'calc-define)
+      (let ((plist (copy-sequence (symbol-plist 'calc-define))))
+	(while (and plist (null (nth 1 plist)))
+	  (setq plist (cdr (cdr plist))))
+	(if plist
+	    (save-excursion
+	      (calc-extensions)
+	      (calc-need-macros)
+	      (set-buffer "*Calculator*")
+	      (while plist
+		(put 'calc-define (car plist) nil)
+		(eval (nth 1 plist))
+		(setq plist (cdr (cdr plist))))
+	      ;; See if this has added any more calc-define properties.
+	      (calc-check-defines))
+	  (setplist 'calc-define nil))))
+)
+(setq calc-check-defines 'calc-check-defines)  ; suitable for run-hooks
+
+(defun calc-trail-mode (&optional buf)
+  "Calc Trail mode.
+This mode is used by the *Calc Trail* buffer, which records all results
+obtained by the GNU Emacs Calculator.
+
+Calculator commands beginning with the `t' key are used to manipulate
+the Trail.
+
+This buffer uses the same key map as the *Calculator* buffer; calculator
+commands given here will actually operate on the *Calculator* stack."
+  (interactive)
+  (fundamental-mode)
+  (use-local-map calc-mode-map)
+  (setq major-mode 'calc-trail-mode)
+  (setq mode-name "Calc Trail")
+  (setq truncate-lines t)
+  (setq buffer-read-only t)
+  (make-local-variable 'overlay-arrow-position)
+  (make-local-variable 'overlay-arrow-string)
+  (if buf
+      (progn
+	(make-local-variable 'calc-main-buffer)
+	(setq calc-main-buffer buf)))
+  (if (= (buffer-size) 0)
+      (let ((buffer-read-only nil))
+	(insert "Emacs Calculator v" calc-version " by Dave Gillespie, "
+		"installed " calc-installed-date "\n")))
+  (run-hooks 'calc-trail-mode-hook)
+)
+
+(defun calc-create-buffer ()
+  (set-buffer (get-buffer-create "*Calculator*"))
+  (or (eq major-mode 'calc-mode)
+      (calc-mode))
+  (setq max-lisp-eval-depth (max max-lisp-eval-depth 1000))
+  (if calc-always-load-extensions
+      (calc-extensions))
+  (if calc-language
+      (progn
+	(calc-extensions)
+	(calc-set-language calc-language calc-language-option t)))
+)
+
+;;;###autoload
+(defun calc (&optional arg full-display interactive)
+  "The Emacs Calculator.  Full documentation is listed under \"calc-mode\"."
+  (interactive "P")
+  (if arg
+      (or (eq arg 0)
+	  (progn
+	    (calc-extensions)
+	    (if (= (prefix-numeric-value arg) -1)
+		(calc-grab-region (region-beginning) (region-end) nil)
+	      (if (= (prefix-numeric-value arg) -2)
+		  (calc-keypad)))))
+    (if (get-buffer-window "*Calc Keypad*")
+	(progn
+	  (calc-keypad)
+	  (set-buffer (window-buffer (selected-window)))))
+    (if (eq major-mode 'calc-mode)
+	(calc-quit)
+      (let ((oldbuf (current-buffer)))
+	(calc-create-buffer)
+	(setq calc-was-keypad-mode nil)
+	(if (or (eq full-display t)
+		(and (null full-display) calc-full-mode))
+	    (switch-to-buffer (current-buffer) t)
+	  (if (get-buffer-window (current-buffer))
+	      (select-window (get-buffer-window (current-buffer)))
+	    (setq calc-was-split nil)
+	    (if (and (boundp 'calc-window-hook) calc-window-hook)
+		(run-hooks 'calc-window-hook)
+	      (let ((w (get-largest-window)))
+		(if (and pop-up-windows
+			 (> (window-height w)
+			    (+ window-min-height calc-window-height 2)))
+		    (progn
+		      (or (one-window-p)
+			  (setq calc-was-split (list w (window-height w)
+						     (selected-window))))
+		      (setq w (split-window w
+					    (- (window-height w)
+					       calc-window-height 2)
+					    nil))
+		      (set-window-buffer w (current-buffer))
+		      (select-window w))
+		  (pop-to-buffer (current-buffer)))))))
+	(save-excursion
+	  (set-buffer (calc-trail-buffer))
+	  (and calc-display-trail
+	       (= (window-width) (screen-width))
+	       (calc-trail-display 1 t)))
+	(message "Welcome to the GNU Emacs Calculator!  Press `?' or `h' for help, `q' to quit.")
+	(run-hooks 'calc-start-hook)
+	(and (windowp full-display)
+	     (window-point full-display)
+	     (select-window full-display))
+	(calc-check-defines)
+	(and calc-said-hello
+	     (or (interactive-p) interactive)
+	     (progn
+	       (sit-for 2)
+	       (message "")))
+	(setq calc-said-hello t))))
+)
+
+;;;###autoload
+(defun full-calc ()
+  "Invoke the Calculator and give it a full-sized window."
+  (interactive)
+  (calc nil t (interactive-p))
+)
+
+(defun calc-same-interface (arg)
+  "Invoke the Calculator using the most recent interface (calc or calc-keypad)."
+  (interactive "P")
+  (if (and (equal (buffer-name) "*Gnuplot Trail*")
+	   (> (recursion-depth) 0))
+      (exit-recursive-edit)
+    (if (eq major-mode 'calc-edit-mode)
+	(calc-edit-finish arg)
+      (if (eq major-mode 'MacEdit-mode)
+	  (MacEdit-finish-edit)
+	(if calc-was-keypad-mode
+	    (calc-keypad)
+	  (calc arg calc-full-mode t)))))
+)
+
+
+(defun calc-quit (&optional non-fatal)
+  (interactive)
+  (and calc-standalone-flag (not non-fatal)
+       (save-buffers-kill-emacs nil))
+  (if (and (equal (buffer-name) "*Gnuplot Trail*")
+	   (> (recursion-depth) 0))
+      (exit-recursive-edit))
+  (if (eq major-mode 'calc-edit-mode)
+      (calc-edit-cancel)
+    (if (eq major-mode 'MacEdit-mode)
+	(MacEdit-cancel-edit)
+      (if (and (interactive-p)
+	       calc-embedded-info
+	       (eq (current-buffer) (aref calc-embedded-info 0)))
+	  (calc-embedded nil)
+	(or (eq major-mode 'calc-mode)
+	    (calc-create-buffer))
+	(run-hooks 'calc-end-hook)
+	(setq calc-undo-list nil calc-redo-list nil)
+	(mapcar (function (lambda (v) (set-default v (symbol-value v))))
+		calc-local-var-list)
+	(let ((buf (current-buffer))
+	      (win (get-buffer-window (current-buffer)))
+	      (kbuf (get-buffer "*Calc Keypad*")))
+	  (delete-windows-on (calc-trail-buffer))
+	  (if (and win
+		   (< (window-height win) (1- (screen-height)))
+		   (= (window-width win) (screen-width))  ; avoid calc-keypad
+		   (not (get-buffer-window "*Calc Keypad*")))
+	      (setq calc-window-height (- (window-height win) 2)))
+	  (if calc-was-split
+	      (calc-delete-windows-keep buf kbuf)
+	    (delete-windows-on buf)
+	    (delete-windows-on kbuf))
+	  (bury-buffer buf)
+	  (bury-buffer calc-trail-buffer)
+	  (and kbuf (bury-buffer kbuf))))))
+)
+
+;;;###autoload
+(defun quick-calc ()
+  "Do a quick calculation in the minibuffer without invoking full Calculator."
+  (interactive)
+  (calc-do-quick-calc)
+)
+
+;;;###autoload
+(defun calc-eval (str &optional separator &rest args)
+  "Do a quick calculation and return the result as a string.
+Return value will either be the formatted result in string form,
+or a list containing a character position and an error message in string form."
+  (calc-do-calc-eval str separator args)
+)
+
+;;;###autoload
+(defun calc-keypad ()
+  "Invoke the Calculator in \"visual keypad\" mode.
+This is most useful in the X window system.
+In this mode, click on the Calc \"buttons\" using the left mouse button.
+Or, position the cursor manually and do M-x calc-keypad-press."
+  (interactive)
+  (calc-extensions)
+  (calc-do-keypad calc-full-mode (interactive-p))
+)
+
+;;;###autoload
+(defun full-calc-keypad ()
+  "Invoke the Calculator in full-screen \"visual keypad\" mode.
+See calc-keypad for details."
+  (interactive)
+  (calc-extensions)
+  (calc-do-keypad t (interactive-p))
+)
+
+
+;;; Note that modifications to this function may break calc-pass-errors.
+(defun calc-do (do-body &optional do-slow)
+  (calc-check-defines)
+  (let* ((calc-command-flags nil)
+	 (calc-start-time (and calc-timing (not calc-start-time)
+			       (calc-extensions)
+			       (current-time-string)))
+	 (gc-cons-threshold (max gc-cons-threshold
+				 (if calc-timing 2000000 100000))))
+    (setq calc-aborted-prefix "")
+    (unwind-protect
+	(condition-case err
+	    (save-excursion
+	      (if calc-embedded-info
+		  (calc-embedded-select-buffer)
+		(calc-select-buffer))
+	      (and (eq calc-algebraic-mode 'total)
+		   (calc-extensions)
+		   (use-local-map calc-alg-map))
+	      (and do-slow calc-display-working-message
+		   (progn
+		     (message "Working...")
+		     (calc-set-command-flag 'clear-message)))
+	      (funcall do-body)
+	      (setq calc-aborted-prefix nil)
+	      (and (memq 'renum-stack calc-command-flags)
+		   (calc-renumber-stack))
+	      (and (memq 'clear-message calc-command-flags)
+		   (message "")))
+	  (error
+	   (if (and (eq (car err) 'error)
+		    (stringp (nth 1 err))
+		    (string-match "max-specpdl-size\\|max-lisp-eval-depth"
+				  (nth 1 err)))
+	       (error "Computation got stuck or ran too long.  Type `M' to increase the limit.")
+	     (setq calc-aborted-prefix nil)
+	     (signal (car err) (cdr err)))))
+      (setq calc-old-aborted-prefix calc-aborted-prefix)
+      (and calc-aborted-prefix
+	   (calc-record "<Aborted>" calc-aborted-prefix))
+      (and calc-start-time
+	   (let* ((calc-internal-prec 12)
+		  (calc-date-format nil)
+		  (end-time (current-time-string))
+		  (time (if (equal calc-start-time end-time)
+			    0
+			  (math-sub
+			   (calcFunc-unixtime (math-parse-date end-time) 0)
+			   (calcFunc-unixtime (math-parse-date calc-start-time)
+					      0)))))
+	     (if (math-lessp 1 time)
+		 (calc-record time "(t)"))))
+      (or (memq 'no-align calc-command-flags)
+	  (eq major-mode 'calc-trail-mode)
+	  (calc-align-stack-window))
+      (and (memq 'position-point calc-command-flags)
+	   (if (eq major-mode 'calc-mode)
+	       (progn
+		 (goto-line calc-final-point-line)
+		 (move-to-column calc-final-point-column))
+	     (save-excursion
+	       (calc-select-buffer)
+	       (goto-line calc-final-point-line)
+	       (move-to-column calc-final-point-column))))
+      (or (memq 'keep-flags calc-command-flags)
+	  (save-excursion
+	    (calc-select-buffer)
+	    (setq calc-inverse-flag nil
+		  calc-hyperbolic-flag nil
+		  calc-keep-args-flag nil)))
+      (and (memq 'do-edit calc-command-flags)
+	   (switch-to-buffer (get-buffer-create "*Calc Edit*")))
+      (calc-set-mode-line)
+      (and calc-embedded-info
+	   (calc-embedded-finish-command))))
+  (identity nil)  ; allow a GC after timing is done
+)
+(setq calc-aborted-prefix nil)
+(setq calc-start-time nil)
+
+(defun calc-set-command-flag (f)
+  (if (not (memq f calc-command-flags))
+      (setq calc-command-flags (cons f calc-command-flags)))
+)
+
+(defun calc-select-buffer ()
+  (or (eq major-mode 'calc-mode)
+      (if calc-main-buffer
+	  (set-buffer calc-main-buffer)
+	(let ((buf (get-buffer "*Calculator*")))
+	  (if buf
+	      (set-buffer buf)
+	    (error "Calculator buffer not available")))))
+)
+
+(defun calc-cursor-stack-index (&optional index)
+  (goto-char (point-max))
+  (forward-line (- (calc-substack-height (or index 1))))
+)
+
+(defun calc-stack-size ()
+  (- (length calc-stack) calc-stack-top)
+)
+
+(defun calc-substack-height (n)
+  (let ((sum 0)
+	(stack calc-stack))
+    (setq n (+ n calc-stack-top))
+    (while (and (> n 0) stack)
+      (setq sum (+ sum (nth 1 (car stack)))
+	    n (1- n)
+	    stack (cdr stack)))
+    sum)
+)
+
+(defun calc-set-mode-line ()
+  (save-excursion
+    (calc-select-buffer)
+    (let* ((fmt (car calc-float-format))
+	   (figs (nth 1 calc-float-format))
+	   (new-mode-string
+	    (format "Calc%s%s: %d %s %-14s"
+		    (if calc-embedded-info "Embed" "")
+		    (if (and (> (length (buffer-name)) 12)
+			     (equal (substring (buffer-name) 0 12)
+				    "*Calculator*"))
+			(substring (buffer-name) 12)
+		      "")
+		    calc-internal-prec
+		    (capitalize (symbol-name calc-angle-mode))
+		    (concat
+
+		     ;; Input-related modes
+		     (if (eq calc-algebraic-mode 'total) "Alg* "
+		       (if calc-algebraic-mode "Alg "
+			 (if calc-incomplete-algebraic-mode "Alg[( " "")))
+
+		     ;; Computational modes
+		     (if calc-symbolic-mode "Symb " "")
+		     (cond ((eq calc-matrix-mode 'matrix) "Matrix ")
+			   ((integerp calc-matrix-mode)
+			    (format "Matrix%d " calc-matrix-mode))
+			   ((eq calc-matrix-mode 'scalar) "Scalar ")
+			   (t ""))
+		     (if (eq calc-complex-mode 'polar) "Polar " "")
+		     (if calc-prefer-frac "Frac " "")
+		     (cond ((null calc-infinite-mode) "")
+			   ((eq calc-infinite-mode 1) "+Inf ")
+			   (t "Inf "))
+		     (cond ((eq calc-simplify-mode 'none) "NoSimp ")
+			   ((eq calc-simplify-mode 'num) "NumSimp ")
+			   ((eq calc-simplify-mode 'binary)
+			    (format "BinSimp%d " calc-word-size))
+			   ((eq calc-simplify-mode 'alg) "AlgSimp ")
+			   ((eq calc-simplify-mode 'ext) "ExtSimp ")
+			   ((eq calc-simplify-mode 'units) "UnitSimp ")
+			   (t ""))
+
+		     ;; Display modes
+		     (cond ((= calc-number-radix 10) "")
+			   ((= calc-number-radix 2) "Bin ")
+			   ((= calc-number-radix 8) "Oct ")
+			   ((= calc-number-radix 16) "Hex ")
+			   (t (format "Radix%d " calc-number-radix)))
+		     (if calc-leading-zeros "Zero " "")
+		     (cond ((null calc-language) "")
+			   ((eq calc-language 'tex) "TeX ")
+			   (t (concat
+			       (capitalize (symbol-name calc-language))
+			       " ")))
+		     (cond ((eq fmt 'float)
+			    (if (zerop figs) "" (format "Norm%d " figs)))
+			   ((eq fmt 'fix) (format "Fix%d " figs))
+			   ((eq fmt 'sci)
+			    (if (zerop figs) "Sci " (format "Sci%d " figs)))
+			   ((eq fmt 'eng)
+			    (if (zerop figs) "Eng " (format "Eng%d " figs))))
+		     (cond ((not calc-display-just)
+			    (if calc-display-origin
+				(format "Left%d " calc-display-origin) ""))
+			   ((eq calc-display-just 'right)
+			    (if calc-display-origin
+				(format "Right%d " calc-display-origin)
+			      "Right "))
+			   (t
+			    (if calc-display-origin
+				(format "Center%d " calc-display-origin)
+			      "Center ")))
+		     (cond ((integerp calc-line-breaking)
+			    (format "Wid%d " calc-line-breaking))
+			   (calc-line-breaking "")
+			   (t "Wide "))
+
+		     ;; Miscellaneous other modes/indicators
+		     (if calc-assoc-selections "" "Break ")
+		     (cond ((eq calc-mode-save-mode 'save) "Save ")
+			   ((not calc-embedded-info) "")
+			   ((eq calc-mode-save-mode 'local) "Local ")
+			   ((eq calc-mode-save-mode 'edit) "LocEdit ")
+			   ((eq calc-mode-save-mode 'perm) "LocPerm ")
+			   ((eq calc-mode-save-mode 'global) "Global ")
+			   (t ""))
+		     (if calc-auto-recompute "" "Manual ")
+		     (if (and (fboundp 'calc-gnuplot-alive)
+			      (calc-gnuplot-alive)) "Graph " "")
+		     (if (and calc-embedded-info
+			      (> (calc-stack-size) 0)
+			      (calc-top 1 'sel)) "Sel " "")
+		     (if calc-display-dirty "Dirty " "")
+		     (if calc-inverse-flag "Inv " "")
+		     (if calc-hyperbolic-flag "Hyp " "")
+		     (if calc-keep-args-flag "Keep " "")
+		     (if (/= calc-stack-top 1) "Narrow " "")
+		     (apply 'concat calc-other-modes)))))
+      (if (equal new-mode-string mode-line-buffer-identification)
+	  nil
+	(setq mode-line-buffer-identification new-mode-string)
+	(set-buffer-modified-p (buffer-modified-p))
+	(and calc-embedded-info (calc-embedded-mode-line-change)))))
+)
+
+(defun calc-align-stack-window ()
+  (if (eq major-mode 'calc-mode)
+      (progn
+	(let ((win (get-buffer-window (current-buffer))))
+	  (if win
+	      (progn
+		(calc-cursor-stack-index 0)
+		(vertical-motion (- 2 (window-height win)))
+		(set-window-start win (point)))))
+	(calc-cursor-stack-index 0)
+	(if (looking-at " *\\.$")
+	    (goto-char (1- (match-end 0)))))
+    (save-excursion
+      (calc-select-buffer)
+      (calc-align-stack-window)))
+)
+
+(defun calc-check-stack (n)
+  (if (> n (calc-stack-size))
+      (error "Too few elements on stack"))
+  (if (< n 0)
+      (error "Invalid argument"))
+)
+
+(defun calc-push-list (vals &optional m sels)
+  (while vals
+    (if calc-executing-macro
+	(calc-push-list-in-macro vals m sels)
+      (save-excursion
+	(calc-select-buffer)
+	(let* ((val (car vals))
+	       (entry (list val 1 (car sels)))
+	       (mm (+ (or m 1) calc-stack-top)))
+	  (calc-cursor-stack-index (1- (or m 1)))
+	  (if (> mm 1)
+	      (setcdr (nthcdr (- mm 2) calc-stack)
+		      (cons entry (nthcdr (1- mm) calc-stack)))
+	    (setq calc-stack (cons entry calc-stack)))
+	  (let ((buffer-read-only nil))
+	    (insert (math-format-stack-value entry) "\n"))
+	  (calc-record-undo (list 'push mm))
+	  (calc-set-command-flag 'renum-stack))))
+    (setq vals (cdr vals)
+	  sels (cdr sels)))
+)
+
+(defun calc-pop-push-list (n vals &optional m sels)
+  (if (and calc-any-selections (null sels))
+      (calc-replace-selections n vals m)
+    (calc-pop-stack n m sels)
+    (calc-push-list vals m sels))
+)
+
+(defun calc-pop-push-record-list (n prefix vals &optional m sels)
+  (or (and (consp vals)
+	   (or (integerp (car vals))
+	       (consp (car vals))))
+      (and vals (setq vals (list vals)
+		      sels (and sels (list sels)))))
+  (calc-check-stack (+ n (or m 1) -1))
+  (if prefix
+      (if (cdr vals)
+	  (calc-record-list vals prefix)
+	(calc-record (car vals) prefix)))
+  (calc-pop-push-list n vals m sels)
+)
+
+(defun calc-enter-result (n prefix vals &optional m)
+  (setq calc-aborted-prefix prefix)
+  (if (and (consp vals)
+	   (or (integerp (car vals))
+	       (consp (car vals))))
+      (setq vals (mapcar 'calc-normalize vals))
+    (setq vals (calc-normalize vals)))
+  (or (and (consp vals)
+	   (or (integerp (car vals))
+	       (consp (car vals))))
+      (setq vals (list vals)))
+  (if (equal vals '((nil)))
+      (setq vals nil))
+  (calc-pop-push-record-list n prefix vals m)
+  (calc-handle-whys)
+)
+
+(defun calc-normalize (val)
+  (if (memq calc-simplify-mode '(nil none num))
+      (math-normalize val)
+    (calc-extensions)
+    (calc-normalize-fancy val))
+)
+
+(defun calc-handle-whys ()
+  (if calc-next-why
+      (calc-do-handle-whys))
+)
+
+
+(defun calc-pop-stack (&optional n m sel-ok)  ; pop N objs at level M of stack.
+  (or n (setq n 1))
+  (or m (setq m 1))
+  (or calc-keep-args-flag
+      (let ((mm (+ m calc-stack-top)))
+	(if (and calc-any-selections (not sel-ok)
+		 (calc-top-selected n m))
+	    (calc-sel-error))
+	(if calc-executing-macro
+	    (calc-pop-stack-in-macro n mm)
+	  (calc-record-undo (list 'pop mm (calc-top-list n m 'full)))
+	  (save-excursion
+	    (calc-select-buffer)
+	    (let ((buffer-read-only nil))
+	      (if (> mm 1)
+		  (progn
+		    (calc-cursor-stack-index (1- m))
+		    (let ((bot (point)))
+		      (calc-cursor-stack-index (+ n m -1))
+		      (delete-region (point) bot))
+		    (setcdr (nthcdr (- mm 2) calc-stack)
+			    (nthcdr (+ n mm -1) calc-stack)))
+		(calc-cursor-stack-index n)
+		(setq calc-stack (nthcdr n calc-stack))
+		(delete-region (point) (point-max))))
+	    (calc-set-command-flag 'renum-stack)))))
+)
+
+(defun calc-get-stack-element (x)
+  (cond ((eq sel-mode 'entry)
+	 x)
+	((eq sel-mode 'sel)
+	 (nth 2 x))
+	((or (null (nth 2 x))
+	     (eq sel-mode 'full)
+	     (not calc-use-selections))
+	 (car x))
+	(sel-mode
+	 (calc-sel-error))
+	(t (nth 2 x)))
+)
+
+;; Get the Nth element of the stack (N=1 is the top element).
+(defun calc-top (&optional n sel-mode)
+  (or n (setq n 1))
+  (calc-check-stack n)
+  (calc-get-stack-element (nth (+ n calc-stack-top -1) calc-stack))
+)
+
+(defun calc-top-n (&optional n sel-mode)    ; in case precision has changed
+  (math-check-complete (calc-normalize (calc-top n sel-mode)))
+)
+
+(defun calc-top-list (&optional n m sel-mode)
+  (or n (setq n 1))
+  (or m (setq m 1))
+  (calc-check-stack (+ n m -1))
+  (and (> n 0)
+       (let ((top (copy-sequence (nthcdr (+ m calc-stack-top -1)
+					 calc-stack))))
+	 (setcdr (nthcdr (1- n) top) nil)
+	 (nreverse (mapcar 'calc-get-stack-element top))))
+)
+
+(defun calc-top-list-n (&optional n m sel-mode)
+  (mapcar 'math-check-complete
+	  (mapcar 'calc-normalize (calc-top-list n m sel-mode)))
+)
+
+
+(defun calc-renumber-stack ()
+  (if calc-line-numbering
+      (save-excursion
+	(calc-cursor-stack-index 0)
+	(let ((lnum 1)
+	      (buffer-read-only nil)
+	      (stack (nthcdr calc-stack-top calc-stack)))
+	  (if (re-search-forward "^[0-9]+[:*]" nil t)
+	      (progn
+		(beginning-of-line)
+		(while (re-search-forward "^[0-9]+[:*]" nil t)
+		  (let ((buffer-read-only nil))
+		    (beginning-of-line)
+		    (delete-char 4)
+		    (insert "    ")))
+		(calc-cursor-stack-index 0)))
+	  (while (re-search-backward "^[0-9]+[:*]" nil t)
+	    (delete-char 4)
+	    (if (> lnum 999)
+		(insert (format "%03d%s" (% lnum 1000)
+				(if (and (nth 2 (car stack))
+					 calc-use-selections) "*" ":")))
+	      (let ((prefix (int-to-string lnum)))
+		(insert prefix (if (and (nth 2 (car stack))
+					calc-use-selections) "*" ":")
+			(make-string (- 3 (length prefix)) 32))))
+	    (beginning-of-line)
+	    (setq lnum (1+ lnum)
+		  stack (cdr stack))))))
+  (and calc-embedded-info (calc-embedded-stack-change))
+)
+
+(defun calc-refresh (&optional align)
+  (interactive)
+  (and (eq major-mode 'calc-mode)
+       (not calc-executing-macro)
+       (let* ((buffer-read-only nil)
+	      (save-point (point))
+	      (save-mark (condition-case err (mark) (error nil)))
+	      (save-aligned (looking-at "\\.$"))
+	      (thing calc-stack))
+	 (setq calc-any-selections nil
+	       calc-any-evaltos nil)
+	 (erase-buffer)
+	 (insert "--- Emacs Calculator Mode ---\n")
+	 (while thing
+	   (goto-char (point-min))
+	   (forward-line 1)
+	   (insert (math-format-stack-value (car thing)) "\n")
+	   (setq thing (cdr thing)))
+	 (calc-renumber-stack)
+	 (if calc-display-dirty
+	     (calc-wrapper (setq calc-display-dirty nil)))
+	 (and calc-any-evaltos calc-auto-recompute
+	      (calc-wrapper (calc-refresh-evaltos)))
+	 (if (or align save-aligned)
+	     (calc-align-stack-window)
+	   (goto-char save-point))
+	 (if save-mark (set-mark save-mark))))
+  (and calc-embedded-info (not (eq major-mode 'calc-mode))
+       (save-excursion
+	 (set-buffer (aref calc-embedded-info 1))
+	 (calc-refresh align)))
+  (setq calc-refresh-count (1+ calc-refresh-count))
+)
+
+
+(defun calc-x-paste-text (arg)
+  "Move point to mouse position and insert window system cut buffer contents.
+If mouse is pressed in Calc window, push cut buffer contents onto the stack."
+  (x-mouse-select arg)
+  (if (memq major-mode '(calc-mode calc-trail-mode))
+      (progn
+	(calc-wrapper
+	 (calc-extensions)
+	 (let* ((buf (x-get-cut-buffer))
+		(val (math-read-exprs (calc-clean-newlines buf))))
+	   (if (eq (car-safe val) 'error)
+	       (progn
+		 (setq val (math-read-exprs buf))
+		 (if (eq (car-safe val) 'error)
+		     (error "%s in yanked data" (nth 2 val)))))
+	   (calc-enter-result 0 "Xynk" val))))
+    (x-paste-text arg))
+)
+
+
+
+;;;; The Calc Trail buffer.
+
+(defun calc-check-trail-aligned ()
+  (save-excursion
+    (let ((win (get-buffer-window (current-buffer))))
+      (and win
+	   (pos-visible-in-window-p (1- (point-max)) win))))
+)
+
+(defun calc-trail-buffer ()
+  (and (or (null calc-trail-buffer)
+	   (null (buffer-name calc-trail-buffer)))
+       (save-excursion
+	 (setq calc-trail-buffer (get-buffer-create "*Calc Trail*"))
+	 (let ((buf (or (and (not (eq major-mode 'calc-mode))
+			     (get-buffer "*Calculator*"))
+			(current-buffer))))
+	   (set-buffer calc-trail-buffer)
+	   (or (eq major-mode 'calc-trail-mode)
+	       (calc-trail-mode buf)))))
+  (or (and calc-trail-pointer
+	   (eq (marker-buffer calc-trail-pointer) calc-trail-buffer))
+      (save-excursion
+	(set-buffer calc-trail-buffer)
+	(goto-line 2)
+	(setq calc-trail-pointer (point-marker))))
+  calc-trail-buffer
+)
+
+(defun calc-record (val &optional prefix)
+  (setq calc-aborted-prefix nil)
+  (or calc-executing-macro
+      (let* ((mainbuf (current-buffer))
+	     (buf (calc-trail-buffer))
+	     (calc-display-raw nil)
+	     (calc-can-abbrev-vectors t)
+	     (fval (if val
+		       (if (stringp val)
+			   val
+			 (math-showing-full-precision
+			  (math-format-flat-expr val 0)))
+		     "")))
+	(save-excursion
+	  (set-buffer buf)
+	  (let ((aligned (calc-check-trail-aligned))
+		(buffer-read-only nil))
+	    (goto-char (point-max))
+	    (cond ((null prefix) (insert "     "))
+		  ((and (> (length prefix) 4)
+			(string-match " " prefix 4))
+		   (insert (substring prefix 0 4) " "))
+		  (t (insert (format "%4s " prefix))))
+	    (insert fval "\n")
+	    (let ((win (get-buffer-window buf)))
+	      (if (and aligned win (not (memq 'hold-trail calc-command-flags)))
+		  (calc-trail-here))
+	      (goto-char (1- (point-max))))))))
+  val
+)
+
+
+(defun calc-trail-display (flag &optional no-refresh)
+  (interactive "P")
+  (let ((win (get-buffer-window (calc-trail-buffer))))
+    (if (setq calc-display-trail
+	      (not (if flag (memq flag '(nil 0)) win)))
+	(if (null win)
+	    (progn
+	      (if (and (boundp 'calc-trail-window-hook) calc-trail-window-hook)
+		  (run-hooks 'calc-trail-window-hook)
+		(let ((w (split-window nil (/ (* (window-width) 2) 3) t)))
+		  (set-window-buffer w calc-trail-buffer)))
+	      (calc-wrapper
+	       (setq overlay-arrow-string calc-trail-overlay
+		     overlay-arrow-position calc-trail-pointer)
+	       (or no-refresh
+		   (if (interactive-p)
+		       (calc-do-refresh)
+		     (calc-refresh))))))
+      (if win
+	  (progn
+	    (delete-window win)
+	    (calc-wrapper
+	     (or no-refresh
+		 (if (interactive-p)
+		     (calc-do-refresh)
+		   (calc-refresh))))))))
+  calc-trail-buffer
+)
+
+(defun calc-trail-here ()
+  (interactive)
+  (if (eq major-mode 'calc-trail-mode)
+      (progn
+	(beginning-of-line)
+	(if (bobp)
+	    (forward-line 1)
+	  (if (eobp)
+	      (forward-line -1)))
+	(if (or (bobp) (eobp))
+	    (setq overlay-arrow-position nil)   ; trail is empty
+	  (set-marker calc-trail-pointer (point) (current-buffer))
+	  (setq calc-trail-overlay (concat (buffer-substring (point)
+							     (+ (point) 4))
+					   ">")
+		overlay-arrow-string calc-trail-overlay
+		overlay-arrow-position calc-trail-pointer)
+	  (forward-char 4)
+	  (let ((win (get-buffer-window (current-buffer))))
+	    (if win
+		(save-excursion
+		  (forward-line (/ (window-height win) 2))
+		  (forward-line (- 1 (window-height win)))
+		  (set-window-start win (point))
+		  (set-window-point win (+ calc-trail-pointer 4))
+		  (set-buffer calc-main-buffer)
+		  (setq overlay-arrow-string calc-trail-overlay
+			overlay-arrow-position calc-trail-pointer))))))
+    (error "Not in Calc Trail buffer"))
+)
+
+
+
+
+;;;; The Undo list.
+
+(defun calc-record-undo (rec)
+  (or calc-executing-macro
+      (if (memq 'undo calc-command-flags)
+	  (setq calc-undo-list (cons (cons rec (car calc-undo-list))
+				     (cdr calc-undo-list)))
+	(setq calc-undo-list (cons (list rec) calc-undo-list)
+	      calc-redo-list nil)
+	(calc-set-command-flag 'undo)))
+)
+
+
+
+
+;;; Arithmetic commands.
+
+(defun calc-binary-op (name func arg &optional ident unary func2)
+  (setq calc-aborted-prefix name)
+  (if (null arg)
+      (calc-enter-result 2 name (cons (or func2 func)
+				      (mapcar 'math-check-complete
+					      (calc-top-list 2))))
+    (calc-extensions)
+    (calc-binary-op-fancy name func arg ident unary))
+)
+
+(defun calc-unary-op (name func arg &optional func2)
+  (setq calc-aborted-prefix name)
+  (if (null arg)
+      (calc-enter-result 1 name (list (or func2 func)
+				      (math-check-complete (calc-top 1))))
+    (calc-extensions)
+    (calc-unary-op-fancy name func arg))
+)
+
+
+(defun calc-plus (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-binary-op "+" 'calcFunc-add arg 0 nil '+))
+)
+
+(defun calc-minus (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-binary-op "-" 'calcFunc-sub arg 0 'neg '-))
+)
+
+(defun calc-times (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-binary-op "*" 'calcFunc-mul arg 1 nil '*))
+)
+
+(defun calc-divide (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (calc-binary-op "/" 'calcFunc-div arg 0 'calcFunc-inv '/))
+)
+
+
+(defun calc-change-sign (arg)
+  (interactive "P")
+  (calc-wrapper
+   (calc-unary-op "chs" 'neg arg))
+)
+
+
+
+;;; Stack management commands.
+
+(defun calc-enter (n)
+  (interactive "p")
+  (calc-wrapper
+   (cond ((< n 0)
+	  (calc-push-list (calc-top-list 1 (- n))))
+	 ((= n 0)
+	  (calc-push-list (calc-top-list (calc-stack-size))))
+	 (t
+	  (calc-push-list (calc-top-list n)))))
+)
+
+
+(defun calc-pop (n)
+  (interactive "P")
+  (calc-wrapper
+   (let* ((nn (prefix-numeric-value n))
+	  (top (and (null n) (calc-top 1))))
+     (cond ((and (null n)
+		 (eq (car-safe top) 'incomplete)
+		 (> (length top) (if (eq (nth 1 top) 'intv) 3 2)))
+	    (calc-pop-push-list 1 (let ((tt (copy-sequence top)))
+				    (setcdr (nthcdr (- (length tt) 2) tt) nil)
+				    (list tt))))
+	   ((< nn 0)
+	    (if (and calc-any-selections
+		     (calc-top-selected 1 (- nn)))
+		(calc-delete-selection (- nn))
+	      (calc-pop-stack 1 (- nn) t)))
+	   ((= nn 0)
+	    (calc-pop-stack (calc-stack-size) 1 t))
+	   (t
+	    (if (and calc-any-selections
+		     (= nn 1)
+		     (calc-top-selected 1 1))
+		(calc-delete-selection 1)
+	      (calc-pop-stack nn))))))
+)
+
+
+
+
+;;;; Reading a number using the minibuffer.
+
+(defun calcDigit-start ()
+  (interactive)
+  (calc-wrapper
+   (if (or calc-algebraic-mode
+	   (and (> calc-number-radix 14) (eq last-command-char ?e)))
+       (calc-alg-digit-entry)
+     (calc-unread-command)
+     (setq calc-aborted-prefix nil)
+     (let* ((calc-digit-value nil)
+	    (calc-prev-char nil)
+	    (calc-prev-prev-char nil)
+	    (calc-buffer (current-buffer))
+	    (buf (if calc-emacs-type-lucid
+		     (catch 'calc-foo
+		       (catch 'execute-kbd-macro
+			 (throw 'calc-foo
+				(read-from-minibuffer
+				 "Calc: " "" calc-digit-map)))
+		       (error "Lucid Emacs requires RET after %s"
+			      "digit entry in kbd macro"))
+		   (let ((old-esc (lookup-key global-map "\e")))
+		     (unwind-protect
+			 (progn
+			   (define-key global-map "\e" nil)
+			   (read-from-minibuffer "Calc: " "" calc-digit-map))
+		       (define-key global-map "\e" old-esc))))))
+       (or calc-digit-value (setq calc-digit-value (math-read-number buf)))
+       (if (stringp calc-digit-value)
+	   (calc-alg-entry calc-digit-value)
+	 (if calc-digit-value
+	     (calc-push-list (list (calc-record (calc-normalize
+						 calc-digit-value))))))
+       (if (eq calc-prev-char 'dots)
+	   (progn
+	     (calc-extensions)
+	     (calc-dots))))))
+)
+
+(defun calcDigit-nondigit ()
+  (interactive)
+  ;; Exercise for the reader:  Figure out why this is a good precaution!
+  (or (boundp 'calc-buffer)
+      (use-local-map minibuffer-local-map))
+  (let ((str (buffer-string)))
+    (setq calc-digit-value (save-excursion
+			     (set-buffer calc-buffer)
+			     (math-read-number str))))
+  (if (and (null calc-digit-value) (> (buffer-size) 0))
+      (progn
+	(beep)
+	(calc-temp-minibuffer-message " [Bad format]"))
+    (or (memq last-command-char '(32 13))
+	(progn (setq prefix-arg current-prefix-arg)
+	       (calc-unread-command (if (and (eq last-command-char 27)
+					     (>= last-input-char 128))
+					last-input-char
+				      nil))))
+    (exit-minibuffer))
+)
+
+
+(defun calc-minibuffer-contains (rex)
+  (save-excursion
+    (goto-char (point-min))
+    (looking-at rex))
+)
+
+(defun calcDigit-key ()
+  (interactive)
+  (goto-char (point-max))
+  (if (or (and (memq last-command-char '(?+ ?-))
+	       (> (buffer-size) 0)
+	       (/= (preceding-char) ?e))
+	  (and (memq last-command-char '(?m ?s))
+	       (not (calc-minibuffer-contains "[-+]?[0-9]+\\.?0*[@oh].*"))
+	       (not (calc-minibuffer-contains "[-+]?\\(1[1-9]\\|[2-9][0-9]\\)#.*"))))
+      (calcDigit-nondigit)
+    (if (calc-minibuffer-contains "\\([-+]?\\|.* \\)\\'")
+	(cond ((memq last-command-char '(?. ?@)) (insert "0"))
+	      ((and (memq last-command-char '(?o ?h ?m))
+		    (not (calc-minibuffer-contains ".*#.*"))) (insert "0"))
+	      ((memq last-command-char '(?: ?e)) (insert "1"))
+	      ((eq last-command-char ?#)
+	       (insert (int-to-string calc-number-radix)))))
+    (if (and (calc-minibuffer-contains "\\([-+]?[0-9]+#\\|[^:]*:\\)\\'")
+	     (eq last-command-char ?:))
+	(insert "1"))
+    (if (and (calc-minibuffer-contains "[-+]?[0-9]+#\\'")
+	     (eq last-command-char ?.))
+	(insert "0"))
+    (if (and (calc-minibuffer-contains "[-+]?0*\\([2-9]\\|1[0-4]\\)#\\'")
+	     (eq last-command-char ?e))
+	(insert "1"))
+    (if (or (and (memq last-command-char '(?h ?o ?m ?s ?p))
+		 (calc-minibuffer-contains ".*#.*"))
+	    (and (eq last-command-char ?e)
+		 (calc-minibuffer-contains "[-+]?\\(1[5-9]\\|[2-9][0-9]\\)#.*"))
+	    (and (eq last-command-char ?n)
+		 (calc-minibuffer-contains "[-+]?\\(2[4-9]\\|[3-9][0-9]\\)#.*")))
+	(setq last-command-char (upcase last-command-char)))
+    (cond
+     ((memq last-command-char '(?_ ?n))
+      (goto-char (point-min))
+      (if (and (search-forward " +/- " nil t)
+	       (not (search-forward "e" nil t)))
+	  (beep)
+	(and (not (calc-minibuffer-contains "[-+]?\\(1[5-9]\\|[2-9][0-9]\\)#.*"))
+	     (search-forward "e" nil t))
+	(if (looking-at "+")
+	    (delete-char 1))
+	(if (looking-at "-")
+	    (delete-char 1)
+	  (insert "-")))
+      (goto-char (point-max)))
+     ((eq last-command-char ?p)
+      (if (or (calc-minibuffer-contains ".*\\+/-.*")
+	      (calc-minibuffer-contains ".*mod.*")
+	      (calc-minibuffer-contains ".*#.*")
+	      (calc-minibuffer-contains ".*[-+e:]\\'"))
+	  (beep)
+	(if (not (calc-minibuffer-contains ".* \\'"))
+	    (insert " "))
+	(insert "+/- ")))
+     ((and (eq last-command-char ?M)
+	   (not (calc-minibuffer-contains
+		 "[-+]?\\(2[3-9]\\|[3-9][0-9]\\)#.*")))
+      (if (or (calc-minibuffer-contains ".*\\+/-.*")
+	      (calc-minibuffer-contains ".*mod *[^ ]+")
+	      (calc-minibuffer-contains ".*[-+e:]\\'"))
+	  (beep)
+	(if (calc-minibuffer-contains ".*mod \\'")
+	    (if calc-previous-modulo
+		(insert (math-format-flat-expr calc-previous-modulo 0))
+	      (beep))
+	  (if (not (calc-minibuffer-contains ".* \\'"))
+	      (insert " "))
+	  (insert "mod "))))
+     (t
+      (insert (char-to-string last-command-char))
+      (if (or (and (calc-minibuffer-contains "[-+]?\\(.*\\+/- *\\|.*mod *\\)?\\([0-9][0-9]?\\)#[0-9a-zA-Z]*\\(:[0-9a-zA-Z]*\\(:[0-9a-zA-Z]*\\)?\\|.[0-9a-zA-Z]*\\(e[-+]?[0-9]*\\)?\\)?\\'")
+		   (let ((radix (string-to-int
+				 (buffer-substring
+				  (match-beginning 2) (match-end 2)))))
+		     (and (>= radix 2)
+			  (<= radix 36)
+			  (or (memq last-command-char '(?# ?: ?. ?e ?+ ?-))
+			      (let ((dig (math-read-radix-digit
+					  (upcase last-command-char))))
+				(and dig
+				     (< dig radix)))))))
+	      (save-excursion
+		(goto-char (point-min))
+         	(looking-at
+		 "[-+]?\\(.*\\+/- *\\|.*mod *\\)?\\([0-9]+\\.?0*[@oh] *\\)?\\([0-9]+\\.?0*['m] *\\)?[0-9]*\\(\\.?[0-9]*\\(e[-+]?[0-3]?[0-9]?[0-9]?[0-9]?[0-9]?[0-9]?[0-9]?\\)?\\|[0-9]:\\([0-9]+:\\)?[0-9]*\\)?[\"s]?\\'")))
+	  (if (and (memq last-command-char '(?@ ?o ?h ?\' ?m))
+		   (string-match " " calc-hms-format))
+	      (insert " "))
+	(if (and (eq this-command last-command)
+		 (eq last-command-char ?.))
+	    (progn
+	      (calc-extensions)
+	      (calc-digit-dots))
+	  (delete-backward-char 1)
+	  (beep)
+	  (calc-temp-minibuffer-message " [Bad format]"))))))
+  (setq calc-prev-prev-char calc-prev-char
+	calc-prev-char last-command-char)
+)
+
+
+(defun calcDigit-backspace ()
+  (interactive)
+  (goto-char (point-max))
+  (cond ((calc-minibuffer-contains ".* \\+/- \\'")
+	 (backward-delete-char 5))
+	((calc-minibuffer-contains ".* mod \\'")
+	 (backward-delete-char 5))
+	((calc-minibuffer-contains ".* \\'")
+	 (backward-delete-char 2))
+	((eq last-command 'calcDigit-start)
+	 (erase-buffer))
+	(t (backward-delete-char 1)))
+  (if (= (buffer-size) 0)
+      (progn
+	(setq last-command-char 13)
+	(calcDigit-nondigit)))
+)
+
+
+
+
+
+
+
+;;;; Arithmetic routines.
+;;;
+;;; An object as manipulated by one of these routines may take any of the
+;;; following forms:
+;;;
+;;; integer                 An integer.  For normalized numbers, this format
+;;;			    is used only for -999999 ... 999999.
+;;;
+;;; (bigpos N0 N1 N2 ...)   A big positive integer, N0 + N1*1000 + N2*10^6 ...
+;;; (bigneg N0 N1 N2 ...)   A big negative integer, - N0 - N1*1000 ...
+;;;			    Each digit N is in the range 0 ... 999.
+;;;			    Normalized, always at least three N present,
+;;;			    and the most significant N is nonzero.
+;;;
+;;; (frac NUM DEN)          A fraction.  NUM and DEN are small or big integers.
+;;;                         Normalized, DEN > 1.
+;;;
+;;; (float NUM EXP)         A floating-point number, NUM * 10^EXP;
+;;;                         NUM is a small or big integer, EXP is a small int.
+;;;			    Normalized, NUM is not a multiple of 10, and
+;;;			    abs(NUM) < 10^calc-internal-prec.
+;;;			    Normalized zero is stored as (float 0 0).
+;;;
+;;; (cplx REAL IMAG)        A complex number; REAL and IMAG are any of above.
+;;;			    Normalized, IMAG is nonzero.
+;;;
+;;; (polar R THETA)         Polar complex number.  Normalized, R > 0 and THETA
+;;;                         is neither zero nor 180 degrees (pi radians).
+;;;
+;;; (vec A B C ...)         Vector of objects A, B, C, ...  A matrix is a
+;;;                         vector of vectors.
+;;;
+;;; (hms H M S)             Angle in hours-minutes-seconds form.  All three
+;;;                         components have the same sign; H and M must be
+;;;                         numerically integers; M and S are expected to
+;;;                         lie in the range [0,60).
+;;;
+;;; (date N)                A date or date/time object.  N is an integer to
+;;;			    store a date only, or a fraction or float to
+;;;			    store a date and time.
+;;;
+;;; (sdev X SIGMA)          Error form, X +/- SIGMA.  When normalized,
+;;;                         SIGMA > 0.  X is any complex number and SIGMA
+;;;			    is real numbers; or these may be symbolic
+;;;                         expressions where SIGMA is assumed real.
+;;;
+;;; (intv MASK LO HI)       Interval form.  MASK is 0=(), 1=(], 2=[), or 3=[].
+;;;                         LO and HI are any real numbers, or symbolic
+;;;			    expressions which are assumed real, and LO < HI.
+;;;			    For [LO..HI], if LO = HI normalization produces LO,
+;;;			    and if LO > HI normalization produces [LO..LO).
+;;;			    For other intervals, if LO > HI normalization
+;;;			    sets HI equal to LO.
+;;;
+;;; (mod N M)	    	    Number modulo M.  When normalized, 0 <= N < M.
+;;;			    N and M are real numbers.
+;;;
+;;; (var V S)		    Symbolic variable.  V is a Lisp symbol which
+;;;			    represents the variable's visible name.  S is
+;;;			    the symbol which actually stores the variable's
+;;;			    value:  (var pi var-pi).
+;;;
+;;; In general, combining rational numbers in a calculation always produces
+;;; a rational result, but if either argument is a float, result is a float.
+
+;;; In the following comments, [x y z] means result is x, args must be y, z,
+;;; respectively, where the code letters are:
+;;;
+;;;    O  Normalized object (vector or number)
+;;;    V  Normalized vector
+;;;    N  Normalized number of any type
+;;;    N  Normalized complex number
+;;;    R  Normalized real number (float or rational)
+;;;    F  Normalized floating-point number
+;;;    T  Normalized rational number
+;;;    I  Normalized integer
+;;;    B  Normalized big integer
+;;;    S  Normalized small integer
+;;;    D  Digit (small integer, 0..999)
+;;;    L  Normalized bignum digit list (without "bigpos" or "bigneg" symbol)
+;;;       or normalized vector element list (without "vec")
+;;;    P  Predicate (truth value)
+;;;    X  Any Lisp object
+;;;    Z  "nil"
+;;;
+;;; Lower-case letters signify possibly un-normalized values.
+;;; "L.D" means a cons of an L and a D.
+;;; [N N; n n] means result will be normalized if argument is.
+;;; Also, [Public] marks routines intended to be called from outside.
+;;; [This notation has been neglected in many recent routines.]
+
+;;; Reduce an object to canonical (normalized) form.  [O o; Z Z] [Public]
+(defun math-normalize (a)
+  (cond
+   ((not (consp a))
+    (if (integerp a)
+	(if (or (>= a 1000000) (<= a -1000000))
+	    (math-bignum a)
+	  a)
+      a))
+   ((eq (car a) 'bigpos)
+    (if (eq (nth (1- (length a)) a) 0)
+	(let* ((last (setq a (copy-sequence a))) (digs a))
+	  (while (setq digs (cdr digs))
+	    (or (eq (car digs) 0) (setq last digs)))
+	  (setcdr last nil)))
+    (if (cdr (cdr (cdr a)))
+	a
+      (cond
+       ((cdr (cdr a)) (+ (nth 1 a) (* (nth 2 a) 1000)))
+       ((cdr a) (nth 1 a))
+       (t 0))))
+   ((eq (car a) 'bigneg)
+    (if (eq (nth (1- (length a)) a) 0)
+	(let* ((last (setq a (copy-sequence a))) (digs a))
+	  (while (setq digs (cdr digs))
+	    (or (eq (car digs) 0) (setq last digs)))
+	  (setcdr last nil)))
+    (if (cdr (cdr (cdr a)))
+	a
+      (cond
+       ((cdr (cdr a)) (- (+ (nth 1 a) (* (nth 2 a) 1000))))
+       ((cdr a) (- (nth 1 a)))
+       (t 0))))
+   ((eq (car a) 'float)
+    (math-make-float (math-normalize (nth 1 a)) (nth 2 a)))
+   ((or (memq (car a) '(frac cplx polar hms date mod sdev intv vec var quote
+			     special-const calcFunc-if calcFunc-lambda
+			     calcFunc-quote calcFunc-condition
+			     calcFunc-evalto))
+	(integerp (car a))
+	(and (consp (car a)) (not (eq (car (car a)) 'lambda))))
+    (calc-extensions)
+    (math-normalize-fancy a))
+   (t
+    (or (and calc-simplify-mode
+	     (calc-extensions)
+	     (math-normalize-nonstandard))
+	(let ((args (mapcar 'math-normalize (cdr a))))
+	  (or (condition-case err
+		  (let ((func (assq (car a) '( ( + . math-add )
+					       ( - . math-sub )
+					       ( * . math-mul )
+					       ( / . math-div )
+					       ( % . math-mod )
+					       ( ^ . math-pow )
+					       ( neg . math-neg )
+					       ( | . math-concat ) ))))
+		    (or (and var-EvalRules
+			     (progn
+			       (or (eq var-EvalRules math-eval-rules-cache-tag)
+				   (progn
+				     (calc-extensions)
+				     (math-recompile-eval-rules)))
+			       (and (or math-eval-rules-cache-other
+					(assq (car a) math-eval-rules-cache))
+				    (math-apply-rewrites
+				     (cons (car a) args)
+				     (cdr math-eval-rules-cache)
+				     nil math-eval-rules-cache))))
+			(if func
+			    (apply (cdr func) args)
+			  (and (or (consp (car a))
+				   (fboundp (car a))
+				   (and (not calc-extensions-loaded)
+					(calc-extensions)
+					(fboundp (car a))))
+			       (apply (car a) args)))))
+		(wrong-number-of-arguments
+		 (calc-record-why "*Wrong number of arguments"
+				  (cons (car a) args))
+		 nil)
+		(wrong-type-argument
+		 (or calc-next-why (calc-record-why "Wrong type of argument"
+						    (cons (car a) args)))
+		 nil)
+		(args-out-of-range
+		 (calc-record-why "*Argument out of range" (cons (car a) args))
+		 nil)
+		(inexact-result
+		 (calc-record-why "No exact representation for result"
+				  (cons (car a) args))
+		 nil)
+		(math-overflow
+		 (calc-record-why "*Floating-point overflow occurred"
+				  (cons (car a) args))
+		 nil)
+		(math-underflow
+		 (calc-record-why "*Floating-point underflow occurred"
+				  (cons (car a) args))
+		 nil)
+		(void-variable
+		 (if (eq (nth 1 err) 'var-EvalRules)
+		     (progn
+		       (setq var-EvalRules nil)
+		       (math-normalize (cons (car a) args)))
+		   (calc-record-why "*Variable is void" (nth 1 err)))))
+	      (if (consp (car a))
+		  (math-dimension-error)
+		(cons (car a) args)))))))
+)
+
+
+
+;;; True if A is a floating-point real or complex number.  [P x] [Public]
+(defun math-floatp (a)
+  (cond ((eq (car-safe a) 'float) t)
+	((memq (car-safe a) '(cplx polar mod sdev intv))
+	 (or (math-floatp (nth 1 a))
+	     (math-floatp (nth 2 a))
+	     (and (eq (car a) 'intv) (math-floatp (nth 3 a)))))
+	((eq (car-safe a) 'date)
+	 (math-floatp (nth 1 a))))
+)
+
+
+
+;;; Verify that A is a complete object and return A.  [x x] [Public]
+(defun math-check-complete (a)
+  (cond ((integerp a) a)
+	((eq (car-safe a) 'incomplete)
+	 (calc-incomplete-error a))
+	((consp a) a)
+	(t (error "Invalid data object encountered")))
+)
+
+
+
+;;; Coerce integer A to be a bignum.  [B S]
+(defun math-bignum (a)
+  (if (>= a 0)
+      (cons 'bigpos (math-bignum-big a))
+    (cons 'bigneg (math-bignum-big (- a))))
+)
+
+(defun math-bignum-big (a)   ; [L s]
+  (if (= a 0)
+      nil
+    (cons (% a 1000) (math-bignum-big (/ a 1000))))
+)
+
+
+;;; Build a normalized floating-point number.  [F I S]
+(defun math-make-float (mant exp)
+  (if (eq mant 0)
+      '(float 0 0)
+    (let* ((ldiff (- calc-internal-prec (math-numdigs mant))))
+      (if (< ldiff 0)
+	  (setq mant (math-scale-rounding mant ldiff)
+		exp (- exp ldiff))))
+    (if (consp mant)
+	(let ((digs (cdr mant)))
+	  (if (= (% (car digs) 10) 0)
+	      (progn
+		(while (= (car digs) 0)
+		  (setq digs (cdr digs)
+			exp (+ exp 3)))
+		(while (= (% (car digs) 10) 0)
+		  (setq digs (math-div10-bignum digs)
+			exp (1+ exp)))
+		(setq mant (math-normalize (cons (car mant) digs))))))
+      (while (= (% mant 10) 0)
+	(setq mant (/ mant 10)
+	      exp (1+ exp))))
+    (if (and (<= exp -4000000)
+	     (<= (+ exp (math-numdigs mant) -1) -4000000))
+	(signal 'math-underflow nil)
+      (if (and (>= exp 3000000)
+	       (>= (+ exp (math-numdigs mant) -1) 4000000))
+	  (signal 'math-overflow nil)
+	(list 'float mant exp))))
+)
+
+(defun math-div10-bignum (a)   ; [l l]
+  (if (cdr a)
+      (cons (+ (/ (car a) 10) (* (% (nth 1 a) 10) 100))
+	    (math-div10-bignum (cdr a)))
+    (list (/ (car a) 10)))
+)
+
+;;; Coerce A to be a float.  [F N; V V] [Public]
+(defun math-float (a)
+  (cond ((Math-integerp a) (math-make-float a 0))
+	((eq (car a) 'frac) (math-div (math-float (nth 1 a)) (nth 2 a)))
+	((eq (car a) 'float) a)
+	((memq (car a) '(cplx polar vec hms date sdev mod))
+	 (cons (car a) (mapcar 'math-float (cdr a))))
+	(t (math-float-fancy a)))
+)
+
+
+(defun math-neg (a)
+  (cond ((not (consp a)) (- a))
+	((eq (car a) 'bigpos) (cons 'bigneg (cdr a)))
+	((eq (car a) 'bigneg) (cons 'bigpos (cdr a)))
+	((memq (car a) '(frac float))
+	 (list (car a) (Math-integer-neg (nth 1 a)) (nth 2 a)))
+	((memq (car a) '(cplx vec hms date calcFunc-idn))
+	 (cons (car a) (mapcar 'math-neg (cdr a))))
+	(t (math-neg-fancy a)))
+)
+
+
+;;; Compute the number of decimal digits in integer A.  [S I]
+(defun math-numdigs (a)
+  (if (consp a)
+      (if (cdr a)
+	  (let* ((len (1- (length a)))
+		 (top (nth len a)))
+	    (+ (* len 3) (cond ((>= top 100) 0) ((>= top 10) -1) (t -2))))
+	0)
+    (cond ((>= a 100) (+ (math-numdigs (/ a 1000)) 3))
+	  ((>= a 10) 2)
+	  ((>= a 1) 1)
+	  ((= a 0) 0)
+	  ((> a -10) 1)
+	  ((> a -100) 2)
+	  (t (math-numdigs (- a)))))
+)
+
+;;; Multiply (with truncation toward 0) the integer A by 10^N.  [I i S]
+(defun math-scale-int (a n)
+  (cond ((= n 0) a)
+	((> n 0) (math-scale-left a n))
+	(t (math-normalize (math-scale-right a (- n)))))
+)
+
+(defun math-scale-left (a n)   ; [I I S]
+  (if (= n 0)
+      a
+    (if (consp a)
+	(cons (car a) (math-scale-left-bignum (cdr a) n))
+      (if (>= n 3)
+	  (if (or (>= a 1000) (<= a -1000))
+	      (math-scale-left (math-bignum a) n)
+	    (math-scale-left (* a 1000) (- n 3)))
+	(if (= n 2)
+	    (if (or (>= a 10000) (<= a -10000))
+		(math-scale-left (math-bignum a) 2)
+	      (* a 100))
+	  (if (or (>= a 100000) (<= a -100000))
+	      (math-scale-left (math-bignum a) 1)
+	    (* a 10))))))
+)
+
+(defun math-scale-left-bignum (a n)
+  (if (>= n 3)
+      (while (>= (setq a (cons 0 a)
+		       n (- n 3)) 3)))
+  (if (> n 0)
+      (math-mul-bignum-digit a (if (= n 2) 100 10) 0)
+    a)
+)
+
+(defun math-scale-right (a n)   ; [i i S]
+  (if (= n 0)
+      a
+    (if (consp a)
+	(cons (car a) (math-scale-right-bignum (cdr a) n))
+      (if (<= a 0)
+	  (if (= a 0)
+	      0
+	    (- (math-scale-right (- a) n)))
+	(if (>= n 3)
+	    (while (and (> (setq a (/ a 1000)) 0)
+			(>= (setq n (- n 3)) 3))))
+	(if (= n 2)
+	    (/ a 100)
+	  (if (= n 1)
+	      (/ a 10)
+	    a)))))
+)
+
+(defun math-scale-right-bignum (a n)   ; [L L S; l l S]
+  (if (>= n 3)
+      (setq a (nthcdr (/ n 3) a)
+	    n (% n 3)))
+  (if (> n 0)
+      (cdr (math-mul-bignum-digit a (if (= n 2) 10 100) 0))
+    a)
+)
+
+;;; Multiply (with rounding) the integer A by 10^N.   [I i S]
+(defun math-scale-rounding (a n)
+  (cond ((>= n 0)
+	 (math-scale-left a n))
+	((consp a)
+	 (math-normalize
+	  (cons (car a)
+		(let ((val (if (< n -3)
+			       (math-scale-right-bignum (cdr a) (- -3 n))
+			     (if (= n -2)
+				 (math-mul-bignum-digit (cdr a) 10 0)
+			       (if (= n -1)
+				   (math-mul-bignum-digit (cdr a) 100 0)
+				 (cdr a))))))  ; n = -3
+		  (if (and val (>= (car val) 500))
+		      (if (cdr val)
+			  (if (eq (car (cdr val)) 999)
+			      (math-add-bignum (cdr val) '(1))
+			    (cons (1+ (car (cdr val))) (cdr (cdr val))))
+			'(1))
+		    (cdr val))))))
+	(t
+	 (if (< a 0)
+	     (- (math-scale-rounding (- a) n))
+	   (if (= n -1)
+	       (/ (+ a 5) 10)
+	     (/ (+ (math-scale-right a (- -1 n)) 5) 10)))))
+)
+
+
+;;; Compute the sum of A and B.  [O O O] [Public]
+(defun math-add (a b)
+  (or
+   (and (not (or (consp a) (consp b)))
+	(progn
+	  (setq a (+ a b))
+	  (if (or (<= a -1000000) (>= a 1000000))
+	      (math-bignum a)
+	    a)))
+   (and (Math-zerop a) (not (eq (car-safe a) 'mod))
+	(if (and (math-floatp a) (Math-ratp b)) (math-float b) b))
+   (and (Math-zerop b) (not (eq (car-safe b) 'mod))
+	(if (and (math-floatp b) (Math-ratp a)) (math-float a) a))
+   (and (Math-objvecp a) (Math-objvecp b)
+	(or
+	 (and (Math-integerp a) (Math-integerp b)
+	      (progn
+		(or (consp a) (setq a (math-bignum a)))
+		(or (consp b) (setq b (math-bignum b)))
+		(if (eq (car a) 'bigneg)
+		    (if (eq (car b) 'bigneg)
+			(cons 'bigneg (math-add-bignum (cdr a) (cdr b)))
+		      (math-normalize
+		       (let ((diff (math-sub-bignum (cdr b) (cdr a))))
+			 (if (eq diff 'neg)
+			     (cons 'bigneg (math-sub-bignum (cdr a) (cdr b)))
+			   (cons 'bigpos diff)))))
+		  (if (eq (car b) 'bigneg)
+		      (math-normalize
+		       (let ((diff (math-sub-bignum (cdr a) (cdr b))))
+			 (if (eq diff 'neg)
+			     (cons 'bigneg (math-sub-bignum (cdr b) (cdr a)))
+			   (cons 'bigpos diff))))
+		    (cons 'bigpos (math-add-bignum (cdr a) (cdr b)))))))
+	 (and (Math-ratp a) (Math-ratp b)
+	      (calc-extensions)
+	      (calc-add-fractions a b))
+	 (and (Math-realp a) (Math-realp b)
+	      (progn
+		(or (and (consp a) (eq (car a) 'float))
+		    (setq a (math-float a)))
+		(or (and (consp b) (eq (car b) 'float))
+		    (setq b (math-float b)))
+		(math-add-float a b)))
+	 (and (calc-extensions)
+	      (math-add-objects-fancy a b))))
+   (and (calc-extensions)
+	(math-add-symb-fancy a b)))
+)
+
+(defun math-add-bignum (a b)   ; [L L L; l l l]
+  (if a
+      (if b
+	  (let* ((a (copy-sequence a)) (aa a) (carry nil) sum)
+	    (while (and aa b)
+	      (if carry
+		  (if (< (setq sum (+ (car aa) (car b))) 999)
+		      (progn
+			(setcar aa (1+ sum))
+			(setq carry nil))
+		    (setcar aa (+ sum -999)))
+		(if (< (setq sum (+ (car aa) (car b))) 1000)
+		    (setcar aa sum)
+		  (setcar aa (+ sum -1000))
+		  (setq carry t)))
+	      (setq aa (cdr aa)
+		    b (cdr b)))
+	    (if carry
+		(if b
+		    (nconc a (math-add-bignum b '(1)))
+		  (while (eq (car aa) 999)
+		    (setcar aa 0)
+		    (setq aa (cdr aa)))
+		  (if aa
+		      (progn
+			(setcar aa (1+ (car aa)))
+			a)
+		    (nconc a '(1))))
+	      (if b
+		  (nconc a b)
+		a)))
+	a)
+    b)
+)
+
+(defun math-sub-bignum (a b)   ; [l l l]
+  (if b
+      (if a
+	  (let* ((a (copy-sequence a)) (aa a) (borrow nil) sum)
+	    (while (and aa b)
+	      (if borrow
+		  (if (>= (setq diff (- (car aa) (car b))) 1)
+		      (progn
+			(setcar aa (1- diff))
+			(setq borrow nil))
+		    (setcar aa (+ diff 999)))
+		(if (>= (setq diff (- (car aa) (car b))) 0)
+		    (setcar aa diff)
+		  (setcar aa (+ diff 1000))
+		  (setq borrow t)))
+	      (setq aa (cdr aa)
+		    b (cdr b)))
+	    (if borrow
+		(progn
+		  (while (eq (car aa) 0)
+		    (setcar aa 999)
+		    (setq aa (cdr aa)))
+		  (if aa
+		      (progn
+			(setcar aa (1- (car aa)))
+			a)
+		    'neg))
+	      (while (eq (car b) 0)
+		(setq b (cdr b)))
+	      (if b
+		  'neg
+		a)))
+	(while (eq (car b) 0)
+	  (setq b (cdr b)))
+	(and b
+	     'neg))
+    a)
+)
+
+(defun math-add-float (a b)   ; [F F F]
+  (let ((ediff (- (nth 2 a) (nth 2 b))))
+    (if (>= ediff 0)
+	(if (>= ediff (+ calc-internal-prec calc-internal-prec))
+	    a
+	  (math-make-float (math-add (nth 1 b)
+				     (if (eq ediff 0)
+					 (nth 1 a)
+				       (math-scale-left (nth 1 a) ediff)))
+			   (nth 2 b)))
+      (if (>= (setq ediff (- ediff))
+	      (+ calc-internal-prec calc-internal-prec))
+	  b
+	(math-make-float (math-add (nth 1 a)
+				   (math-scale-left (nth 1 b) ediff))
+			 (nth 2 a)))))
+)
+
+;;; Compute the difference of A and B.  [O O O] [Public]
+(defun math-sub (a b)
+  (if (or (consp a) (consp b))
+      (math-add a (math-neg b))
+    (setq a (- a b))
+    (if (or (<= a -1000000) (>= a 1000000))
+	(math-bignum a)
+      a))
+)
+
+(defun math-sub-float (a b)   ; [F F F]
+  (let ((ediff (- (nth 2 a) (nth 2 b))))
+    (if (>= ediff 0)
+	(if (>= ediff (+ calc-internal-prec calc-internal-prec))
+	    a
+	  (math-make-float (math-add (Math-integer-neg (nth 1 b))
+				     (if (eq ediff 0)
+					 (nth 1 a)
+				       (math-scale-left (nth 1 a) ediff)))
+			   (nth 2 b)))
+      (if (>= (setq ediff (- ediff))
+	      (+ calc-internal-prec calc-internal-prec))
+	  b
+	(math-make-float (math-add (nth 1 a)
+				   (Math-integer-neg
+				    (math-scale-left (nth 1 b) ediff)))
+			 (nth 2 a)))))
+)
+
+
+;;; Compute the product of A and B.  [O O O] [Public]
+(defun math-mul (a b)
+  (or
+   (and (not (consp a)) (not (consp b))
+	(< a 1000) (> a -1000) (< b 1000) (> b -1000)
+	(* a b))
+   (and (Math-zerop a) (not (eq (car-safe b) 'mod))
+	(if (Math-scalarp b)
+	    (if (and (math-floatp b) (Math-ratp a)) (math-float a) a)
+	  (calc-extensions)
+	  (math-mul-zero a b)))
+   (and (Math-zerop b) (not (eq (car-safe a) 'mod))
+	(if (Math-scalarp a)
+	    (if (and (math-floatp a) (Math-ratp b)) (math-float b) b)
+	  (calc-extensions)
+	  (math-mul-zero b a)))
+   (and (Math-objvecp a) (Math-objvecp b)
+	(or
+	 (and (Math-integerp a) (Math-integerp b)
+	      (progn
+		(or (consp a) (setq a (math-bignum a)))
+		(or (consp b) (setq b (math-bignum b)))
+		(math-normalize
+		 (cons (if (eq (car a) (car b)) 'bigpos 'bigneg)
+		       (if (cdr (cdr a))
+			   (if (cdr (cdr b))
+			       (math-mul-bignum (cdr a) (cdr b))
+			     (math-mul-bignum-digit (cdr a) (nth 1 b) 0))
+			 (math-mul-bignum-digit (cdr b) (nth 1 a) 0))))))
+	 (and (Math-ratp a) (Math-ratp b)
+	      (calc-extensions)
+	      (calc-mul-fractions a b))
+	 (and (Math-realp a) (Math-realp b)
+	      (progn
+		(or (and (consp a) (eq (car a) 'float))
+		    (setq a (math-float a)))
+		(or (and (consp b) (eq (car b) 'float))
+		    (setq b (math-float b)))
+		(math-make-float (math-mul (nth 1 a) (nth 1 b))
+				 (+ (nth 2 a) (nth 2 b)))))
+	 (and (calc-extensions)
+	      (math-mul-objects-fancy a b))))
+   (and (calc-extensions)
+	(math-mul-symb-fancy a b)))
+)
+
+(defun math-infinitep (a &optional undir)
+  (while (and (consp a) (memq (car a) '(* / neg)))
+    (if (or (not (eq (car a) '*)) (math-infinitep (nth 1 a)))
+	(setq a (nth 1 a))
+      (setq a (nth 2 a))))
+  (and (consp a)
+       (eq (car a) 'var)
+       (memq (nth 2 a) '(var-inf var-uinf var-nan))
+       (if (and undir (eq (nth 2 a) 'var-inf))
+	   '(var uinf var-uinf)
+	 a))
+)
+
+;;; Multiply digit lists A and B.  [L L L; l l l]
+(defun math-mul-bignum (a b)
+  (and a b
+       (let* ((sum (if (<= (car b) 1)
+		       (if (= (car b) 0)
+			   (list 0)
+			 (copy-sequence a))
+		     (math-mul-bignum-digit a (car b) 0)))
+	      (sump sum) c d aa ss prod)
+	 (while (setq b (cdr b))
+	   (setq ss (setq sump (or (cdr sump) (setcdr sump (list 0))))
+		 d (car b)
+		 c 0
+		 aa a)
+	   (while (progn
+		    (setcar ss (% (setq prod (+ (+ (car ss) (* (car aa) d))
+						c)) 1000))
+		    (setq aa (cdr aa)))
+	     (setq c (/ prod 1000)
+		   ss (or (cdr ss) (setcdr ss (list 0)))))
+	   (if (>= prod 1000)
+	       (if (cdr ss)
+		   (setcar (cdr ss) (+ (/ prod 1000) (car (cdr ss))))
+		 (setcdr ss (list (/ prod 1000))))))
+	 sum))
+)
+
+;;; Multiply digit list A by digit D.  [L L D D; l l D D]
+(defun math-mul-bignum-digit (a d c)
+  (if a
+      (if (<= d 1)
+	  (and (= d 1) a)
+	(let* ((a (copy-sequence a)) (aa a) prod)
+	  (while (progn
+		   (setcar aa (% (setq prod (+ (* (car aa) d) c)) 1000))
+		   (cdr aa))
+	    (setq aa (cdr aa)
+		  c (/ prod 1000)))
+	  (if (>= prod 1000)
+	      (setcdr aa (list (/ prod 1000))))
+	  a))
+    (and (> c 0)
+	 (list c)))
+)
+
+
+;;; Compute the integer (quotient . remainder) of A and B, which may be
+;;; small or big integers.  Type and consistency of truncation is undefined
+;;; if A or B is negative.  B must be nonzero.  [I.I I I] [Public]
+(defun math-idivmod (a b)
+  (if (eq b 0)
+      (math-reject-arg a "*Division by zero"))
+  (if (or (consp a) (consp b))
+      (if (and (natnump b) (< b 1000))
+	  (let ((res (math-div-bignum-digit (cdr a) b)))
+	    (cons
+	     (math-normalize (cons (car a) (car res)))
+	     (cdr res)))
+	(or (consp a) (setq a (math-bignum a)))
+	(or (consp b) (setq b (math-bignum b)))
+	(let ((res (math-div-bignum (cdr a) (cdr b))))
+	  (cons
+	   (math-normalize (cons (if (eq (car a) (car b)) 'bigpos 'bigneg)
+				 (car res)))
+	   (math-normalize (cons (car a) (cdr res))))))
+    (cons (/ a b) (% a b)))
+)
+
+(defun math-quotient (a b)   ; [I I I] [Public]
+  (if (and (not (consp a)) (not (consp b)))
+      (if (= b 0)
+	  (math-reject-arg a "*Division by zero")
+	(/ a b))
+    (if (and (natnump b) (< b 1000))
+	(if (= b 0)
+	    (math-reject-arg a "*Division by zero")
+	  (math-normalize (cons (car a)
+				(car (math-div-bignum-digit (cdr a) b)))))
+      (or (consp a) (setq a (math-bignum a)))
+      (or (consp b) (setq b (math-bignum b)))
+      (let* ((alen (1- (length a)))
+	     (blen (1- (length b)))
+	     (d (/ 1000 (1+ (nth (1- blen) (cdr b)))))
+	     (res (math-div-bignum-big (math-mul-bignum-digit (cdr a) d 0)
+				       (math-mul-bignum-digit (cdr b) d 0)
+				       alen blen)))
+	(math-normalize (cons (if (eq (car a) (car b)) 'bigpos 'bigneg)
+			      (car res))))))
+)
+
+
+;;; Divide a bignum digit list by another.  [l.l l L]
+;;; The following division algorithm is borrowed from Knuth vol. II, sec. 4.3.1
+(defun math-div-bignum (a b)
+  (if (cdr b)
+      (let* ((alen (length a))
+	     (blen (length b))
+	     (d (/ 1000 (1+ (nth (1- blen) b))))
+	     (res (math-div-bignum-big (math-mul-bignum-digit a d 0)
+				       (math-mul-bignum-digit b d 0)
+				       alen blen)))
+	(if (= d 1)
+	    res
+	  (cons (car res)
+		(car (math-div-bignum-digit (cdr res) d)))))
+    (let ((res (math-div-bignum-digit a (car b))))
+      (cons (car res) (list (cdr res)))))
+)
+
+;;; Divide a bignum digit list by a digit.  [l.D l D]
+(defun math-div-bignum-digit (a b)
+  (if a
+      (let* ((res (math-div-bignum-digit (cdr a) b))
+	     (num (+ (* (cdr res) 1000) (car a))))
+	(cons
+	 (cons (/ num b) (car res))
+	 (% num b)))
+    '(nil . 0))
+)
+
+(defun math-div-bignum-big (a b alen blen)   ; [l.l l L]
+  (if (< alen blen)
+      (cons nil a)
+    (let* ((res (math-div-bignum-big (cdr a) b (1- alen) blen))
+	   (num (cons (car a) (cdr res)))
+	   (res2 (math-div-bignum-part num b blen)))
+      (cons
+       (cons (car res2) (car res))
+       (cdr res2))))
+)
+
+(defun math-div-bignum-part (a b blen)   ; a < b*1000  [D.l l L]
+  (let* ((num (+ (* (or (nth blen a) 0) 1000) (or (nth (1- blen) a) 0)))
+	 (den (nth (1- blen) b))
+	 (guess (min (/ num den) 999)))
+    (math-div-bignum-try a b (math-mul-bignum-digit b guess 0) guess))
+)
+
+(defun math-div-bignum-try (a b c guess)   ; [D.l l l D]
+  (let ((rem (math-sub-bignum a c)))
+    (if (eq rem 'neg)
+	(math-div-bignum-try a b (math-sub-bignum c b) (1- guess))
+      (cons guess rem)))
+)
+
+
+;;; Compute the quotient of A and B.  [O O N] [Public]
+(defun math-div (a b)
+  (or
+   (and (Math-zerop b)
+	(calc-extensions)
+	(math-div-by-zero a b))
+   (and (Math-zerop a) (not (eq (car-safe b) 'mod))
+	(if (Math-scalarp b)
+	    (if (and (math-floatp b) (Math-ratp a)) (math-float a) a)
+	  (calc-extensions)
+	  (math-div-zero a b)))
+   (and (Math-objvecp a) (Math-objvecp b)
+	(or
+	 (and (Math-integerp a) (Math-integerp b)
+	      (let ((q (math-idivmod a b)))
+		(if (eq (cdr q) 0)
+		    (car q)
+		  (if calc-prefer-frac
+		      (progn
+			(calc-extensions)
+			(math-make-frac a b))
+		    (math-div-float (math-make-float a 0)
+				    (math-make-float b 0))))))
+	 (and (Math-ratp a) (Math-ratp b)
+	      (calc-extensions)
+	      (calc-div-fractions a b))
+	 (and (Math-realp a) (Math-realp b)
+	      (progn
+		(or (and (consp a) (eq (car a) 'float))
+		    (setq a (math-float a)))
+		(or (and (consp b) (eq (car b) 'float))
+		    (setq b (math-float b)))
+		(math-div-float a b)))
+	 (and (calc-extensions)
+	      (math-div-objects-fancy a b))))
+   (and (calc-extensions)
+	(math-div-symb-fancy a b)))
+)
+
+(defun math-div-float (a b)   ; [F F F]
+  (let ((ldiff (max (- (1+ calc-internal-prec)
+		       (- (math-numdigs (nth 1 a)) (math-numdigs (nth 1 b))))
+		    0)))
+    (math-make-float (math-quotient (math-scale-int (nth 1 a) ldiff) (nth 1 b))
+		     (- (- (nth 2 a) (nth 2 b)) ldiff)))
+)
+
+
+
+
+
+;;; Format the number A as a string.  [X N; X Z] [Public]
+(defun math-format-stack-value (entry)
+  (setq calc-selection-cache-entry calc-selection-cache-default-entry)
+  (let* ((a (car entry))
+	 (math-comp-selected (nth 2 entry))
+	 (c (cond ((null a) "<nil>")
+		  ((eq calc-display-raw t) (format "%s" a))
+		  ((stringp a) a)
+		  ((eq a 'top-of-stack) ".")
+		  (calc-prepared-composition
+		   calc-prepared-composition)
+		  ((and (Math-scalarp a)
+			(memq calc-language '(nil flat unform))
+			(null math-comp-selected))
+		   (math-format-number a))
+		  (t (calc-extensions)
+		     (math-compose-expr a 0))))
+	 (off (math-stack-value-offset c))
+	 s w)
+    (and math-comp-selected (setq calc-any-selections t))
+    (setq w (cdr off)
+	  off (car off))
+    (if (> off 0)
+	(setq c (math-comp-concat (make-string off ? ) c)))
+    (or (equal calc-left-label "")
+	(setq c (math-comp-concat (if (eq a 'top-of-stack)
+				      (make-string (length calc-left-label) ? )
+				    calc-left-label)
+				  c)))
+    (if calc-line-numbering
+	(setq c (math-comp-concat (if (eq calc-language 'big)
+				      (if math-comp-selected
+					  '(tag t "1:  ") "1:  ")
+				    "    ")
+				  c)))
+    (or (equal calc-right-label "")
+	(eq a 'top-of-stack)
+	(progn
+	  (calc-extensions)
+	  (setq c (list 'horiz c
+			(make-string (max (- w (math-comp-width c)
+					     (length calc-right-label)) 0) ? )
+			'(break -1)
+			calc-right-label))))
+    (setq s (if (stringp c)
+		(if calc-display-raw
+		    (prin1-to-string c)
+		  c)
+	      (math-composition-to-string c w)))
+    (if calc-language-output-filter
+	(setq s (funcall calc-language-output-filter s)))
+    (if (eq calc-language 'big)
+	(setq s (concat s "\n"))
+      (if calc-line-numbering
+	  (progn
+	    (aset s 0 ?1)
+	    (aset s 1 ?:))))
+    (setcar (cdr entry) (calc-count-lines s))
+    s)
+)
+
+(defun math-stack-value-offset (c)
+  (let* ((num (if calc-line-numbering 4 0))
+	 (wid (calc-window-width))
+	 off)
+    (if calc-display-just
+	(progn
+	  (calc-extensions)
+	  (math-stack-value-offset-fancy))
+      (setq off (or calc-display-origin 0))
+      (if (integerp calc-line-breaking)
+	  (setq wid calc-line-breaking)))
+    (cons (max (- off (length calc-left-label)) 0)
+	  (+ wid num)))
+)
+
+(defun calc-count-lines (s)
+  (let ((pos 0)
+	(num 1))
+    (while (setq newpos (string-match "\n" s pos))
+      (setq pos (1+ newpos)
+	    num (1+ num)))
+    num)
+)
+
+(defun math-format-value (a &optional w)
+  (if (and (Math-scalarp a)
+	   (memq calc-language '(nil flat unform)))
+      (math-format-number a)
+    (calc-extensions)
+    (let ((calc-line-breaking nil))
+      (math-composition-to-string (math-compose-expr a 0) w)))
+)
+
+(defun calc-window-width ()
+  (if calc-embedded-info
+      (let ((win (get-buffer-window (aref calc-embedded-info 0))))
+	(1- (if win (window-width win) (screen-width))))
+    (- (window-width (get-buffer-window (current-buffer)))
+       (if calc-line-numbering 5 1)))
+)
+
+(defun math-comp-concat (c1 c2)
+  (if (and (stringp c1) (stringp c2))
+      (concat c1 c2)
+    (list 'horiz c1 c2))
+)
+
+
+
+;;; Format an expression as a one-line string suitable for re-reading.
+
+(defun math-format-flat-expr (a prec)
+  (cond
+   ((or (not (or (consp a) (integerp a)))
+	(eq calc-display-raw t))
+    (let ((print-escape-newlines t))
+      (concat "'" (prin1-to-string a))))
+   ((Math-scalarp a)
+    (let ((calc-group-digits nil)
+	  (calc-point-char ".")
+	  (calc-frac-format (if (> (length (car calc-frac-format)) 1)
+				'("::" nil) '(":" nil)))
+	  (calc-complex-format nil)
+	  (calc-hms-format "%s@ %s' %s\"")
+	  (calc-language nil))
+      (math-format-number a)))
+   (t
+    (calc-extensions)
+    (math-format-flat-expr-fancy a prec)))
+)
+
+
+
+;;; Format a number as a string.
+(defun math-format-number (a &optional prec)   ; [X N]   [Public]
+  (cond
+   ((eq calc-display-raw t) (format "%s" a))
+   ((and (nth 1 calc-frac-format) (Math-integerp a))
+    (calc-extensions)
+    (math-format-number (math-adjust-fraction a)))
+   ((integerp a)
+    (if (not (or calc-group-digits calc-leading-zeros))
+	(if (= calc-number-radix 10)
+	    (int-to-string a)
+	  (if (< a 0)
+	      (concat "-" (math-format-number (- a)))
+	    (calc-extensions)
+	    (if math-radix-explicit-format
+		(if calc-radix-formatter
+		    (funcall calc-radix-formatter
+			     calc-number-radix
+			     (if (= calc-number-radix 2)
+				 (math-format-binary a)
+			       (math-format-radix a)))
+		  (format "%d#%s" calc-number-radix
+			  (if (= calc-number-radix 2)
+			      (math-format-binary a)
+			    (math-format-radix a))))
+	      (math-format-radix a))))
+      (math-format-number (math-bignum a))))
+   ((stringp a) a)
+   ((not (consp a)) (prin1-to-string a))
+   ((eq (car a) 'bigpos) (math-format-bignum (cdr a)))
+   ((eq (car a) 'bigneg) (concat "-" (math-format-bignum (cdr a))))
+   ((and (eq (car a) 'float) (= calc-number-radix 10))
+    (if (Math-integer-negp (nth 1 a))
+	(concat "-" (math-format-number (math-neg a)))
+      (let ((mant (nth 1 a))
+	    (exp (nth 2 a))
+	    (fmt (car calc-float-format))
+	    (figs (nth 1 calc-float-format))
+	    (point calc-point-char)
+	    str)
+	(if (and (eq fmt 'fix)
+		 (or (and (< figs 0) (setq figs (- figs)))
+		     (> (+ exp (math-numdigs mant)) (- figs))))
+	    (progn
+	      (setq mant (math-scale-rounding mant (+ exp figs))
+		    str (if (integerp mant)
+			    (int-to-string mant)
+			  (math-format-bignum-decimal (cdr mant))))
+	      (if (<= (length str) figs)
+		  (setq str (concat (make-string (1+ (- figs (length str))) ?0)
+				    str)))
+	      (if (> figs 0)
+		  (setq str (concat (substring str 0 (- figs)) point
+				    (substring str (- figs))))
+		(setq str (concat str point)))
+	      (if calc-group-digits
+		  (setq str (math-group-float str))))
+	  (if (< figs 0)
+	      (setq figs (+ calc-internal-prec figs)))
+	  (if (> figs 0)
+	      (let ((adj (- figs (math-numdigs mant))))
+		(if (< adj 0)
+		    (setq mant (math-scale-rounding mant adj)
+			  exp (- exp adj)))))
+	  (setq str (if (integerp mant)
+			(int-to-string mant)
+		      (math-format-bignum-decimal (cdr mant))))
+	  (let* ((len (length str))
+		 (dpos (+ exp len)))
+	    (if (and (eq fmt 'float)
+		     (<= dpos (+ calc-internal-prec calc-display-sci-high))
+		     (>= dpos (+ calc-display-sci-low 2)))
+		(progn
+		  (cond
+		   ((= dpos 0)
+		    (setq str (concat "0" point str)))
+		   ((and (<= exp 0) (> dpos 0))
+		    (setq str (concat (substring str 0 dpos) point
+				      (substring str dpos))))
+		   ((> exp 0)
+		    (setq str (concat str (make-string exp ?0) point)))
+		   (t   ; (< dpos 0)
+		    (setq str (concat "0" point
+				      (make-string (- dpos) ?0) str))))
+		  (if calc-group-digits
+		      (setq str (math-group-float str))))
+	      (let* ((eadj (+ exp len))
+		     (scale (if (eq fmt 'eng)
+				(1+ (math-mod (+ eadj 300002) 3))
+			      1)))
+		(if (> scale (length str))
+		    (setq str (concat str (make-string (- scale (length str))
+						       ?0))))
+		(if (< scale (length str))
+		    (setq str (concat (substring str 0 scale) point
+				      (substring str scale))))
+		(if calc-group-digits
+		    (setq str (math-group-float str)))
+		(setq str (format (if (memq calc-language '(math maple))
+				      (if (and prec (> prec 191))
+					  "(%s*10.^%d)" "%s*10.^%d")
+				    "%se%d")
+				  str (- eadj scale)))))))
+	str)))
+   (t
+    (calc-extensions)
+    (math-format-number-fancy a prec)))
+)
+
+(defun math-format-bignum (a)   ; [X L]
+  (if (and (= calc-number-radix 10)
+	   (not calc-leading-zeros)
+	   (not calc-group-digits))
+      (math-format-bignum-decimal a)
+    (calc-extensions)
+    (math-format-bignum-fancy a))
+)
+
+(defun math-format-bignum-decimal (a)   ; [X L]
+  (if a
+      (let ((s ""))
+	(while (cdr (cdr a))
+	  (setq s (concat (format "%06d" (+ (* (nth 1 a) 1000) (car a))) s)
+		a (cdr (cdr a))))
+	(concat (int-to-string (+ (* (or (nth 1 a) 0) 1000) (car a))) s))
+    "0")
+)
+
+
+
+;;; Parse a simple number in string form.   [N X] [Public]
+(defun math-read-number (s)
+  (math-normalize
+   (cond
+
+    ;; Integers (most common case)
+    ((string-match "\\` *\\([0-9]+\\) *\\'" s)
+     (let ((digs (math-match-substring s 1)))
+       (if (and (eq calc-language 'c)
+		(> (length digs) 1)
+		(eq (aref digs 0) ?0))
+	   (math-read-number (concat "8#" digs))
+	 (if (<= (length digs) 6)
+	     (string-to-int digs)
+	   (cons 'bigpos (math-read-bignum digs))))))
+
+    ;; Clean up the string if necessary
+    ((string-match "\\`\\(.*\\)[ \t\n]+\\([^\001]*\\)\\'" s)
+     (math-read-number (concat (math-match-substring s 1)
+			       (math-match-substring s 2))))
+
+    ;; Plus and minus signs
+    ((string-match "^[-_+]\\(.*\\)$" s)
+     (let ((val (math-read-number (math-match-substring s 1))))
+       (and val (if (eq (aref s 0) ?+) val (math-neg val)))))
+
+    ;; Forms that require extensions module
+    ((string-match "[^-+0-9eE.]" s)
+     (calc-extensions)
+     (math-read-number-fancy s))
+
+    ;; Decimal point
+    ((string-match "^\\([0-9]*\\)\\.\\([0-9]*\\)$" s)
+     (let ((int (math-match-substring s 1))
+	   (frac (math-match-substring s 2)))
+       (let ((ilen (length int))
+	     (flen (length frac)))
+	 (let ((int (if (> ilen 0) (math-read-number int) 0))
+	       (frac (if (> flen 0) (math-read-number frac) 0)))
+	   (and int frac (or (> ilen 0) (> flen 0))
+		(list 'float
+		      (math-add (math-scale-int int flen) frac)
+		      (- flen)))))))
+
+    ;; "e" notation
+    ((string-match "^\\(.*\\)[eE]\\([-+]?[0-9]+\\)$" s)
+     (let ((mant (math-match-substring s 1))
+	   (exp (math-match-substring s 2)))
+       (let ((mant (if (> (length mant) 0) (math-read-number mant) 1))
+	     (exp (if (<= (length exp) (if (memq (aref exp 0) '(?+ ?-)) 8 7))
+		      (string-to-int exp))))
+	 (and mant exp (Math-realp mant) (> exp -4000000) (< exp 4000000)
+	      (let ((mant (math-float mant)))
+		(list 'float (nth 1 mant) (+ (nth 2 mant) exp)))))))
+
+    ;; Syntax error!
+    (t nil)))
+)
+
+(defun math-match-substring (s n)
+  (if (match-beginning n)
+      (substring s (match-beginning n) (match-end n))
+    "")
+)
+
+(defun math-read-bignum (s)   ; [l X]
+  (if (> (length s) 3)
+      (cons (string-to-int (substring s -3))
+	    (math-read-bignum (substring s 0 -3)))
+    (list (string-to-int s)))
+)
+
+
+(defconst math-tex-ignore-words
+  '( ("\\hbox") ("\\mbox") ("\\text") ("\\left") ("\\right")
+     ("\\,") ("\\>") ("\\:") ("\\;") ("\\!") ("\\ ")
+     ("\\quad") ("\\qquad") ("\\hfil") ("\\hfill")
+     ("\\displaystyle") ("\\textstyle") ("\\dsize") ("\\tsize")
+     ("\\scriptstyle") ("\\scriptscriptstyle") ("\\ssize") ("\\sssize")
+     ("\\rm") ("\\bf") ("\\it") ("\\sl")
+     ("\\roman") ("\\bold") ("\\italic") ("\\slanted")
+     ("\\cal") ("\\mit") ("\\Cal") ("\\Bbb") ("\\frak") ("\\goth")
+     ("\\evalto")
+     ("\\matrix" mat) ("\\bmatrix" mat) ("\\pmatrix" mat)
+     ("\\cr" punc ";") ("\\\\" punc ";") ("\\*" punc "*")
+     ("\\{" punc "[") ("\\}" punc "]")
+))
+
+(defconst math-eqn-ignore-words
+  '( ("roman") ("bold") ("italic") ("mark") ("lineup") ("evalto")
+     ("left" ("floor") ("ceil"))
+     ("right" ("floor") ("ceil"))
+     ("arc" ("sin") ("cos") ("tan") ("sinh") ("cosh") ("tanh"))
+     ("size" n) ("font" n) ("fwd" n) ("back" n) ("up" n) ("down" n)
+     ("above" punc ",")
+))
+
+(defconst math-standard-opers
+  '( ( "_"     calcFunc-subscr 1200 1201 )
+     ( "%"     calcFunc-percent 1100 -1 )
+     ( "u+"    ident	     -1 1000 )
+     ( "u-"    neg	     -1 1000 197 )
+     ( "u!"    calcFunc-lnot -1 1000 )
+     ( "mod"   mod	     400 400 185 )
+     ( "+/-"   sdev	     300 300 185 )
+     ( "!!"    calcFunc-dfact 210 -1 )
+     ( "!"     calcFunc-fact 210  -1 )
+     ( "^"     ^             201 200 )
+     ( "**"    ^             201 200 )
+     ( "*"     *             196 195 )
+     ( "2x"    *             196 195 )
+     ( "/"     /             190 191 )
+     ( "%"     %             190 191 )
+     ( "\\"    calcFunc-idiv 190 191 )
+     ( "+"     +	     180 181 )
+     ( "-"     -	     180 181 )
+     ( "|"     |	     170 171 )
+     ( "<"     calcFunc-lt   160 161 )
+     ( ">"     calcFunc-gt   160 161 )
+     ( "<="    calcFunc-leq  160 161 )
+     ( ">="    calcFunc-geq  160 161 )
+     ( "="     calcFunc-eq   160 161 )
+     ( "=="    calcFunc-eq   160 161 )
+     ( "!="    calcFunc-neq  160 161 )
+     ( "&&"    calcFunc-land 110 111 )
+     ( "||"    calcFunc-lor  100 101 )
+     ( "?"     (math-read-if) 91  90 )
+     ( "!!!"   calcFunc-pnot  -1  85 )
+     ( "&&&"   calcFunc-pand  80  81 )
+     ( "|||"   calcFunc-por   75  76 )
+     ( ":="    calcFunc-assign 51 50 )
+     ( "::"    calcFunc-condition 45 46 )
+     ( "=>"    calcFunc-evalto 40 41 )
+     ( "=>"    calcFunc-evalto 40 -1 )
+))
+(setq math-expr-opers math-standard-opers)
+
+
+;;;###autoload
+(defun calc-grab-region (top bot arg)
+  "Parse the region as a vector of numbers and push it on the Calculator stack."
+  (interactive "r\nP")
+  (calc-extensions)
+  (calc-do-grab-region top bot arg)
+)
+
+;;;###autoload
+(defun calc-grab-rectangle (top bot arg)
+  "Parse a rectangle as a matrix of numbers and push it on the Calculator stack."
+  (interactive "r\nP")
+  (calc-extensions)
+  (calc-do-grab-rectangle top bot arg)
+)
+
+(defun calc-grab-sum-down (top bot arg)
+  "Parse a rectangle as a matrix of numbers and sum its columns."
+  (interactive "r\nP")
+  (calc-extensions)
+  (calc-do-grab-rectangle top bot arg 'calcFunc-reduced)
+)
+
+(defun calc-grab-sum-across (top bot arg)
+  "Parse a rectangle as a matrix of numbers and sum its rows."
+  (interactive "r\nP")
+  (calc-extensions)
+  (calc-do-grab-rectangle top bot arg 'calcFunc-reducea)
+)
+
+
+;;;###autoload
+(defun calc-embedded (arg &optional end obeg oend)
+  "Start Calc Embedded mode on the formula surrounding point."
+  (interactive "P")
+  (calc-extensions)
+  (calc-do-embedded arg end obeg oend)
+)
+
+;;;###autoload
+(defun calc-embedded-activate (&optional arg cbuf)
+  "Scan the current editing buffer for all embedded := and => formulas.
+Also looks for the equivalent TeX words, \\gets and \\evalto."
+  (interactive "P")
+  (calc-do-embedded-activate arg cbuf)
+)
+
+
+(defun calc-user-invocation ()
+  (interactive)
+  (or (stringp calc-invocation-macro)
+      (error "Use `Z I' inside Calc to define a `M-# Z' keyboard macro"))
+  (execute-kbd-macro calc-invocation-macro nil)
+)
+
+
+
+
+;;; User-programmability.
+
+;;;###autoload
+(defmacro defmath (func args &rest body)   ;  [Public]
+  (calc-extensions)
+  (math-do-defmath func args body)
+)
+
+
+;;; Functions needed for Lucid Emacs support.
+
+(defun calc-read-key (&optional optkey)
+  (cond (calc-emacs-type-lucid
+	 (let ((event (next-command-event)))
+	   (let ((key (event-to-character event t t)))
+	     (or key optkey (error "Expected a plain keystroke"))
+	     (cons key event))))
+	(calc-emacs-type-gnu19
+	 (let ((key (read-event)))
+	   (cons key key)))
+	(t
+	 (let ((key (read-char)))
+	   (cons key key))))
+)
+
+(defun calc-unread-command (&optional input)
+  (cond (calc-emacs-type-gnu19
+	 (setq unread-command-events (cons (or input last-command-event)
+					   unread-command-events)))
+	(calc-emacs-type-lucid
+	 (setq unread-command-event
+	       (if (integerp input) (character-to-event input)
+		 (or input last-command-event))))
+	(t
+	 (setq unread-command-char (or input last-command-char))))
+)
+
+(defun calc-clear-unread-commands ()
+  (cond (calc-emacs-type-gnu19 (setq unread-command-events nil))
+	(calc-emacs-type-lucid (setq unread-command-event nil))
+	(t (setq unread-command-char -1)))
+)
+
+(if calc-always-load-extensions
+    (progn
+      (calc-extensions)
+      (calc-load-everything))
+)
+
+
+(run-hooks 'calc-load-hook)
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/calcalg2.el	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,3507 @@
+;; Calculator for GNU Emacs, part II [calc-alg-2.el]
+;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+;; Written by Dave Gillespie, daveg@synaptics.com.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY.  No author or distributor
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing.  Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License.   A copy of this license is
+;; supposed to have been given to you along with GNU Emacs so you
+;; can know your rights and responsibilities.  It should be in a
+;; file named COPYING.  Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+
+
+
+;; This file is autoloaded from calc-ext.el.
+(require 'calc-ext)
+
+(require 'calc-macs)
+
+(defun calc-Need-calc-alg-2 () nil)
+
+
+(defun calc-derivative (var num)
+  (interactive "sDifferentiate with respect to: \np")
+  (calc-slow-wrapper
+   (and (< num 0) (error "Order of derivative must be positive"))
+   (let ((func (if (calc-is-hyperbolic) 'calcFunc-tderiv 'calcFunc-deriv))
+	 n expr)
+     (if (or (equal var "") (equal var "$"))
+	 (setq n 2
+	       expr (calc-top-n 2)
+	       var (calc-top-n 1))
+       (setq var (math-read-expr var))
+       (if (eq (car-safe var) 'error)
+	   (error "Bad format in expression: %s" (nth 1 var)))
+       (setq n 1
+	     expr (calc-top-n 1)))
+     (while (>= (setq num (1- num)) 0)
+       (setq expr (list func expr var)))
+     (calc-enter-result n "derv" expr)))
+)
+
+(defun calc-integral (var)
+  (interactive "sIntegration variable: ")
+  (calc-slow-wrapper
+   (if (or (equal var "") (equal var "$"))
+       (calc-enter-result 2 "intg" (list 'calcFunc-integ
+					 (calc-top-n 2)
+					 (calc-top-n 1)))
+     (let ((var (math-read-expr var)))
+       (if (eq (car-safe var) 'error)
+	   (error "Bad format in expression: %s" (nth 1 var)))
+       (calc-enter-result 1 "intg" (list 'calcFunc-integ
+					 (calc-top-n 1)
+					 var)))))
+)
+
+(defun calc-num-integral (&optional varname lowname highname)
+  (interactive "sIntegration variable: ")
+  (calc-tabular-command 'calcFunc-ninteg "Integration" "nint"
+			nil varname lowname highname)
+)
+
+(defun calc-summation (arg &optional varname lowname highname)
+  (interactive "P\nsSummation variable: ")
+  (calc-tabular-command 'calcFunc-sum "Summation" "sum"
+			arg varname lowname highname)
+)
+
+(defun calc-alt-summation (arg &optional varname lowname highname)
+  (interactive "P\nsSummation variable: ")
+  (calc-tabular-command 'calcFunc-asum "Summation" "asum"
+			arg varname lowname highname)
+)
+
+(defun calc-product (arg &optional varname lowname highname)
+  (interactive "P\nsIndex variable: ")
+  (calc-tabular-command 'calcFunc-prod "Index" "prod"
+			arg varname lowname highname)
+)
+
+(defun calc-tabulate (arg &optional varname lowname highname)
+  (interactive "P\nsIndex variable: ")
+  (calc-tabular-command 'calcFunc-table "Index" "tabl"
+			arg varname lowname highname)
+)
+
+(defun calc-tabular-command (func prompt prefix arg varname lowname highname)
+  (calc-slow-wrapper
+   (let (var (low nil) (high nil) (step nil) stepname stepnum (num 1) expr)
+     (if (consp arg)
+	 (setq stepnum 1)
+       (setq stepnum 0))
+     (if (or (equal varname "") (equal varname "$") (null varname))
+	 (setq high (calc-top-n (+ stepnum 1))
+	       low (calc-top-n (+ stepnum 2))
+	       var (calc-top-n (+ stepnum 3))
+	       num (+ stepnum 4))
+       (setq var (if (stringp varname) (math-read-expr varname) varname))
+       (if (eq (car-safe var) 'error)
+	   (error "Bad format in expression: %s" (nth 1 var)))
+       (or lowname
+	   (setq lowname (read-string (concat prompt " variable: " varname
+					      ", from: "))))
+       (if (or (equal lowname "") (equal lowname "$"))
+	   (setq high (calc-top-n (+ stepnum 1))
+		 low (calc-top-n (+ stepnum 2))
+		 num (+ stepnum 3))
+	 (setq low (if (stringp lowname) (math-read-expr lowname) lowname))
+	 (if (eq (car-safe low) 'error)
+	     (error "Bad format in expression: %s" (nth 1 low)))
+	 (or highname
+	     (setq highname (read-string (concat prompt " variable: " varname
+						 ", from: " lowname
+						 ", to: "))))
+	 (if (or (equal highname "") (equal highname "$"))
+	     (setq high (calc-top-n (+ stepnum 1))
+		   num (+ stepnum 2))
+	   (setq high (if (stringp highname) (math-read-expr highname)
+			highname))
+	   (if (eq (car-safe high) 'error)
+	       (error "Bad format in expression: %s" (nth 1 high)))
+	   (if (consp arg)
+	       (progn
+		 (setq stepname (read-string (concat prompt " variable: "
+						     varname
+						     ", from: " lowname
+						     ", to: " highname
+						     ", step: ")))
+		 (if (or (equal stepname "") (equal stepname "$"))
+		     (setq step (calc-top-n 1)
+			   num 2)
+		   (setq step (math-read-expr stepname))
+		   (if (eq (car-safe step) 'error)
+		       (error "Bad format in expression: %s"
+			      (nth 1 step)))))))))
+     (or step
+	 (if (consp arg)
+	     (setq step (calc-top-n 1))
+	   (if arg
+	       (setq step (prefix-numeric-value arg)))))
+     (setq expr (calc-top-n num))
+     (calc-enter-result num prefix (append (list func expr var low high)
+					   (and step (list step))))))
+)
+
+(defun calc-solve-for (var)
+  (interactive "sVariable to solve for: ")
+  (calc-slow-wrapper
+   (let ((func (if (calc-is-inverse)
+		   (if (calc-is-hyperbolic) 'calcFunc-ffinv 'calcFunc-finv)
+		 (if (calc-is-hyperbolic) 'calcFunc-fsolve 'calcFunc-solve))))
+     (if (or (equal var "") (equal var "$"))
+	 (calc-enter-result 2 "solv" (list func
+					   (calc-top-n 2)
+					   (calc-top-n 1)))
+       (let ((var (if (and (string-match ",\\|[^ ] +[^ ]" var)
+			   (not (string-match "\\[" var)))
+		      (math-read-expr (concat "[" var "]"))
+		    (math-read-expr var))))
+	 (if (eq (car-safe var) 'error)
+	     (error "Bad format in expression: %s" (nth 1 var)))
+	 (calc-enter-result 1 "solv" (list func
+					   (calc-top-n 1)
+					   var))))))
+)
+
+(defun calc-poly-roots (var)
+  (interactive "sVariable to solve for: ")
+  (calc-slow-wrapper
+   (if (or (equal var "") (equal var "$"))
+       (calc-enter-result 2 "prts" (list 'calcFunc-roots
+					 (calc-top-n 2)
+					 (calc-top-n 1)))
+     (let ((var (if (and (string-match ",\\|[^ ] +[^ ]" var)
+			 (not (string-match "\\[" var)))
+		    (math-read-expr (concat "[" var "]"))
+		  (math-read-expr var))))
+       (if (eq (car-safe var) 'error)
+	   (error "Bad format in expression: %s" (nth 1 var)))
+       (calc-enter-result 1 "prts" (list 'calcFunc-roots
+					 (calc-top-n 1)
+					 var)))))
+)
+
+(defun calc-taylor (var nterms)
+  (interactive "sTaylor expansion variable: \nNNumber of terms: ")
+  (calc-slow-wrapper
+   (let ((var (math-read-expr var)))
+     (if (eq (car-safe var) 'error)
+	 (error "Bad format in expression: %s" (nth 1 var)))
+     (calc-enter-result 1 "tylr" (list 'calcFunc-taylor
+				       (calc-top-n 1)
+				       var
+				       (prefix-numeric-value nterms)))))
+)
+
+
+(defun math-derivative (expr)   ; uses global values: deriv-var, deriv-total.
+  (cond ((equal expr deriv-var)
+	 1)
+	((or (Math-scalarp expr)
+	     (eq (car expr) 'sdev)
+	     (and (eq (car expr) 'var)
+		  (or (not deriv-total)
+		      (math-const-var expr)
+		      (progn
+			(math-setup-declarations)
+			(memq 'const (nth 1 (or (assq (nth 2 expr)
+						      math-decls-cache)
+						math-decls-all)))))))
+	 0)
+	((eq (car expr) '+)
+	 (math-add (math-derivative (nth 1 expr))
+		   (math-derivative (nth 2 expr))))
+	((eq (car expr) '-)
+	 (math-sub (math-derivative (nth 1 expr))
+		   (math-derivative (nth 2 expr))))
+	((memq (car expr) '(calcFunc-eq calcFunc-neq calcFunc-lt
+					calcFunc-gt calcFunc-leq calcFunc-geq))
+	 (list (car expr)
+	       (math-derivative (nth 1 expr))
+	       (math-derivative (nth 2 expr))))
+	((eq (car expr) 'neg)
+	 (math-neg (math-derivative (nth 1 expr))))
+	((eq (car expr) '*)
+	 (math-add (math-mul (nth 2 expr)
+			     (math-derivative (nth 1 expr)))
+		   (math-mul (nth 1 expr)
+			     (math-derivative (nth 2 expr)))))
+	((eq (car expr) '/)
+	 (math-sub (math-div (math-derivative (nth 1 expr))
+			     (nth 2 expr))
+		   (math-div (math-mul (nth 1 expr)
+				       (math-derivative (nth 2 expr)))
+			     (math-sqr (nth 2 expr)))))
+	((eq (car expr) '^)
+	 (let ((du (math-derivative (nth 1 expr)))
+	       (dv (math-derivative (nth 2 expr))))
+	   (or (Math-zerop du)
+	       (setq du (math-mul (nth 2 expr)
+				  (math-mul (math-normalize
+					     (list '^
+						   (nth 1 expr)
+						   (math-add (nth 2 expr) -1)))
+					    du))))
+	   (or (Math-zerop dv)
+	       (setq dv (math-mul (math-normalize
+				   (list 'calcFunc-ln (nth 1 expr)))
+				  (math-mul expr dv))))
+	   (math-add du dv)))
+	((eq (car expr) '%)
+	 (math-derivative (nth 1 expr)))   ; a reasonable definition
+	((eq (car expr) 'vec)
+	 (math-map-vec 'math-derivative expr))
+	((and (memq (car expr) '(calcFunc-conj calcFunc-re calcFunc-im))
+	      (= (length expr) 2))
+	 (list (car expr) (math-derivative (nth 1 expr))))
+	((and (memq (car expr) '(calcFunc-subscr calcFunc-mrow calcFunc-mcol))
+	      (= (length expr) 3))
+	 (let ((d (math-derivative (nth 1 expr))))
+	   (if (math-numberp d)
+	       0    ; assume x and x_1 are independent vars
+	     (list (car expr) d (nth 2 expr)))))
+	(t (or (and (symbolp (car expr))
+		    (if (= (length expr) 2)
+			(let ((handler (get (car expr) 'math-derivative)))
+			  (and handler
+			       (let ((deriv (math-derivative (nth 1 expr))))
+				 (if (Math-zerop deriv)
+				     deriv
+				   (math-mul (funcall handler (nth 1 expr))
+					     deriv)))))
+		      (let ((handler (get (car expr) 'math-derivative-n)))
+			(and handler
+			     (funcall handler expr)))))
+	       (and (not (eq deriv-symb 'pre-expand))
+		    (let ((exp (math-expand-formula expr)))
+		      (and exp
+			   (or (let ((deriv-symb 'pre-expand))
+				 (catch 'math-deriv (math-derivative expr)))
+			       (math-derivative exp)))))
+	       (if (or (Math-objvecp expr)
+		       (eq (car expr) 'var)
+		       (not (symbolp (car expr))))
+		   (if deriv-symb
+		       (throw 'math-deriv nil)
+		     (list (if deriv-total 'calcFunc-tderiv 'calcFunc-deriv)
+			   expr
+			   deriv-var))
+		 (let ((accum 0)
+		       (arg expr)
+		       (n 1)
+		       derv)
+		   (while (setq arg (cdr arg))
+		     (or (Math-zerop (setq derv (math-derivative (car arg))))
+			 (let ((func (intern (concat (symbol-name (car expr))
+						     "'"
+						     (if (> n 1)
+							 (int-to-string n)
+						       ""))))
+			       (prop (cond ((= (length expr) 2)
+					    'math-derivative-1)
+					   ((= (length expr) 3)
+					    'math-derivative-2)
+					   ((= (length expr) 4)
+					    'math-derivative-3)
+					   ((= (length expr) 5)
+					    'math-derivative-4)
+					   ((= (length expr) 6)
+					    'math-derivative-5))))
+			   (setq accum
+				 (math-add
+				  accum
+				  (math-mul
+				   derv
+				   (let ((handler (get func prop)))
+				     (or (and prop handler
+					      (apply handler (cdr expr)))
+					 (if (and deriv-symb
+						  (not (get func
+							    'calc-user-defn)))
+					     (throw 'math-deriv nil)
+					   (cons func (cdr expr))))))))))
+		     (setq n (1+ n)))
+		   accum)))))
+)
+
+(defun calcFunc-deriv (expr deriv-var &optional deriv-value deriv-symb)
+  (let* ((deriv-total nil)
+	 (res (catch 'math-deriv (math-derivative expr))))
+    (or (eq (car-safe res) 'calcFunc-deriv)
+	(null res)
+	(setq res (math-normalize res)))
+    (and res
+	 (if deriv-value
+	     (math-expr-subst res deriv-var deriv-value)
+	   res)))
+)
+
+(defun calcFunc-tderiv (expr deriv-var &optional deriv-value deriv-symb)
+  (math-setup-declarations)
+  (let* ((deriv-total t)
+	 (res (catch 'math-deriv (math-derivative expr))))
+    (or (eq (car-safe res) 'calcFunc-tderiv)
+	(null res)
+	(setq res (math-normalize res)))
+    (and res
+	 (if deriv-value
+	     (math-expr-subst res deriv-var deriv-value)
+	   res)))
+)
+
+(put 'calcFunc-inv\' 'math-derivative-1
+     (function (lambda (u) (math-neg (math-div 1 (math-sqr u))))))
+
+(put 'calcFunc-sqrt\' 'math-derivative-1
+     (function (lambda (u) (math-div 1 (math-mul 2 (list 'calcFunc-sqrt u))))))
+
+(put 'calcFunc-deg\' 'math-derivative-1
+     (function (lambda (u) (math-div-float '(float 18 1) (math-pi)))))
+
+(put 'calcFunc-rad\' 'math-derivative-1
+     (function (lambda (u) (math-pi-over-180))))
+
+(put 'calcFunc-ln\' 'math-derivative-1
+     (function (lambda (u) (math-div 1 u))))
+
+(put 'calcFunc-log10\' 'math-derivative-1
+     (function (lambda (u)
+		 (math-div (math-div 1 (math-normalize '(calcFunc-ln 10)))
+			   u))))
+
+(put 'calcFunc-lnp1\' 'math-derivative-1
+     (function (lambda (u) (math-div 1 (math-add u 1)))))
+
+(put 'calcFunc-log\' 'math-derivative-2
+     (function (lambda (x b)
+		 (and (not (Math-zerop b))
+		      (let ((lnv (math-normalize
+				  (list 'calcFunc-ln b))))
+			(math-div 1 (math-mul lnv x)))))))
+
+(put 'calcFunc-log\'2 'math-derivative-2
+     (function (lambda (x b)
+		 (let ((lnv (list 'calcFunc-ln b)))
+		   (math-neg (math-div (list 'calcFunc-log x b)
+				       (math-mul lnv b)))))))
+
+(put 'calcFunc-exp\' 'math-derivative-1
+     (function (lambda (u) (math-normalize (list 'calcFunc-exp u)))))
+
+(put 'calcFunc-expm1\' 'math-derivative-1
+     (function (lambda (u) (math-normalize (list 'calcFunc-expm1 u)))))
+
+(put 'calcFunc-sin\' 'math-derivative-1
+     (function (lambda (u) (math-to-radians-2 (math-normalize
+					       (list 'calcFunc-cos u))))))
+
+(put 'calcFunc-cos\' 'math-derivative-1
+     (function (lambda (u) (math-neg (math-to-radians-2
+				      (math-normalize
+				       (list 'calcFunc-sin u)))))))
+
+(put 'calcFunc-tan\' 'math-derivative-1
+     (function (lambda (u) (math-to-radians-2
+			    (math-div 1 (math-sqr
+					 (math-normalize
+					  (list 'calcFunc-cos u))))))))
+
+(put 'calcFunc-arcsin\' 'math-derivative-1
+     (function (lambda (u)
+		 (math-from-radians-2
+		  (math-div 1 (math-normalize
+			       (list 'calcFunc-sqrt
+				     (math-sub 1 (math-sqr u)))))))))
+
+(put 'calcFunc-arccos\' 'math-derivative-1
+     (function (lambda (u)
+		 (math-from-radians-2
+		  (math-div -1 (math-normalize
+				(list 'calcFunc-sqrt
+				      (math-sub 1 (math-sqr u)))))))))
+
+(put 'calcFunc-arctan\' 'math-derivative-1
+     (function (lambda (u) (math-from-radians-2
+			    (math-div 1 (math-add 1 (math-sqr u)))))))
+
+(put 'calcFunc-sinh\' 'math-derivative-1
+     (function (lambda (u) (math-normalize (list 'calcFunc-cosh u)))))
+
+(put 'calcFunc-cosh\' 'math-derivative-1
+     (function (lambda (u) (math-normalize (list 'calcFunc-sinh u)))))
+
+(put 'calcFunc-tanh\' 'math-derivative-1
+     (function (lambda (u) (math-div 1 (math-sqr
+					(math-normalize
+					 (list 'calcFunc-cosh u)))))))
+
+(put 'calcFunc-arcsinh\' 'math-derivative-1
+     (function (lambda (u)
+		 (math-div 1 (math-normalize
+			      (list 'calcFunc-sqrt
+				    (math-add (math-sqr u) 1)))))))
+
+(put 'calcFunc-arccosh\' 'math-derivative-1
+     (function (lambda (u)
+		  (math-div 1 (math-normalize
+			       (list 'calcFunc-sqrt
+				     (math-add (math-sqr u) -1)))))))
+
+(put 'calcFunc-arctanh\' 'math-derivative-1
+     (function (lambda (u) (math-div 1 (math-sub 1 (math-sqr u))))))
+
+(put 'calcFunc-bern\'2 'math-derivative-2
+     (function (lambda (n x)
+		 (math-mul n (list 'calcFunc-bern (math-add n -1) x)))))
+
+(put 'calcFunc-euler\'2 'math-derivative-2
+     (function (lambda (n x)
+		 (math-mul n (list 'calcFunc-euler (math-add n -1) x)))))
+
+(put 'calcFunc-gammag\'2 'math-derivative-2
+     (function (lambda (a x) (math-deriv-gamma a x 1))))
+
+(put 'calcFunc-gammaG\'2 'math-derivative-2
+     (function (lambda (a x) (math-deriv-gamma a x -1))))
+
+(put 'calcFunc-gammaP\'2 'math-derivative-2
+     (function (lambda (a x) (math-deriv-gamma a x
+					       (math-div
+						1 (math-normalize
+						   (list 'calcFunc-gamma
+							 a)))))))
+
+(put 'calcFunc-gammaQ\'2 'math-derivative-2
+     (function (lambda (a x) (math-deriv-gamma a x
+					       (math-div
+						-1 (math-normalize
+						    (list 'calcFunc-gamma
+							  a)))))))
+
+(defun math-deriv-gamma (a x scale)
+  (math-mul scale
+	    (math-mul (math-pow x (math-add a -1))
+		      (list 'calcFunc-exp (math-neg x))))
+)
+
+(put 'calcFunc-betaB\' 'math-derivative-3
+     (function (lambda (x a b) (math-deriv-beta x a b 1))))
+
+(put 'calcFunc-betaI\' 'math-derivative-3
+     (function (lambda (x a b) (math-deriv-beta x a b
+						(math-div
+						 1 (list 'calcFunc-beta
+							 a b))))))
+
+(defun math-deriv-beta (x a b scale)
+  (math-mul (math-mul (math-pow x (math-add a -1))
+		      (math-pow (math-sub 1 x) (math-add b -1)))
+	    scale)
+)
+
+(put 'calcFunc-erf\' 'math-derivative-1
+     (function (lambda (x) (math-div 2
+				     (math-mul (list 'calcFunc-exp
+						     (math-sqr x))
+					       (if calc-symbolic-mode
+						   '(calcFunc-sqrt
+						     (var pi var-pi))
+						 (math-sqrt-pi)))))))
+
+(put 'calcFunc-erfc\' 'math-derivative-1
+     (function (lambda (x) (math-div -2
+				     (math-mul (list 'calcFunc-exp
+						     (math-sqr x))
+					       (if calc-symbolic-mode
+						   '(calcFunc-sqrt
+						     (var pi var-pi))
+						 (math-sqrt-pi)))))))
+
+(put 'calcFunc-besJ\'2 'math-derivative-2
+     (function (lambda (v z) (math-div (math-sub (list 'calcFunc-besJ
+						       (math-add v -1)
+						       z)
+						 (list 'calcFunc-besJ
+						       (math-add v 1)
+						       z))
+				       2))))
+
+(put 'calcFunc-besY\'2 'math-derivative-2
+     (function (lambda (v z) (math-div (math-sub (list 'calcFunc-besY
+						       (math-add v -1)
+						       z)
+						 (list 'calcFunc-besY
+						       (math-add v 1)
+						       z))
+				       2))))
+
+(put 'calcFunc-sum 'math-derivative-n
+     (function
+      (lambda (expr)
+	(if (math-expr-contains (cons 'vec (cdr (cdr expr))) deriv-var)
+	    (throw 'math-deriv nil)
+	  (cons 'calcFunc-sum
+		(cons (math-derivative (nth 1 expr))
+		      (cdr (cdr expr))))))))
+
+(put 'calcFunc-prod 'math-derivative-n
+     (function
+      (lambda (expr)
+	(if (math-expr-contains (cons 'vec (cdr (cdr expr))) deriv-var)
+	    (throw 'math-deriv nil)
+	  (math-mul expr
+		    (cons 'calcFunc-sum
+			  (cons (math-div (math-derivative (nth 1 expr))
+					  (nth 1 expr))
+				(cdr (cdr expr)))))))))
+
+(put 'calcFunc-integ 'math-derivative-n
+     (function
+      (lambda (expr)
+	(if (= (length expr) 3)
+	    (if (equal (nth 2 expr) deriv-var)
+		(nth 1 expr)
+	      (math-normalize
+	       (list 'calcFunc-integ
+		     (math-derivative (nth 1 expr))
+		     (nth 2 expr))))
+	  (if (= (length expr) 5)
+	      (let ((lower (math-expr-subst (nth 1 expr) (nth 2 expr)
+					    (nth 3 expr)))
+		    (upper (math-expr-subst (nth 1 expr) (nth 2 expr)
+					    (nth 4 expr))))
+		(math-add (math-sub (math-mul upper
+					      (math-derivative (nth 4 expr)))
+				    (math-mul lower
+					      (math-derivative (nth 3 expr))))
+			  (if (equal (nth 2 expr) deriv-var)
+			      0
+			    (math-normalize
+			     (list 'calcFunc-integ
+				   (math-derivative (nth 1 expr)) (nth 2 expr)
+				   (nth 3 expr) (nth 4 expr)))))))))))
+
+(put 'calcFunc-if 'math-derivative-n
+     (function
+      (lambda (expr)
+	(and (= (length expr) 4)
+	     (list 'calcFunc-if (nth 1 expr)
+		   (math-derivative (nth 2 expr))
+		   (math-derivative (nth 3 expr)))))))
+
+(put 'calcFunc-subscr 'math-derivative-n
+     (function
+      (lambda (expr)
+	(and (= (length expr) 3)
+	     (list 'calcFunc-subscr (nth 1 expr)
+		   (math-derivative (nth 2 expr)))))))
+
+
+
+
+
+(setq math-integ-var '(var X ---))
+(setq math-integ-var-2 '(var Y ---))
+(setq math-integ-vars (list 'f math-integ-var math-integ-var-2))
+(setq math-integ-var-list (list math-integ-var))
+(setq math-integ-var-list-list (list math-integ-var-list))
+
+(defmacro math-tracing-integral (&rest parts)
+  (list 'and
+	'trace-buffer
+	(list 'save-excursion
+	      '(set-buffer trace-buffer)
+	      '(goto-char (point-max))
+	      (list 'and
+		    '(bolp)
+		    '(insert (make-string (- math-integral-limit
+					     math-integ-level) 32)
+			     (format "%2d " math-integ-depth)
+			     (make-string math-integ-level 32)))
+	      ;;(list 'condition-case 'err
+		    (cons 'insert parts)
+		;;    '(error (insert (prin1-to-string err))))
+	      '(sit-for 0)))
+)
+
+;;; The following wrapper caches results and avoids infinite recursion.
+;;; Each cache entry is: ( A B )          Integral of A is B;
+;;;			 ( A N )          Integral of A failed at level N;
+;;;			 ( A busy )	  Currently working on integral of A;
+;;;			 ( A parts )	  Currently working, integ-by-parts;
+;;;			 ( A parts2 )	  Currently working, integ-by-parts;
+;;;			 ( A cancelled )  Ignore this cache entry;
+;;;			 ( A [B] )        Same result as for cur-record = B.
+(defun math-integral (expr &optional simplify same-as-above)
+  (let* ((simp cur-record)
+	 (cur-record (assoc expr math-integral-cache))
+	 (math-integ-depth (1+ math-integ-depth))
+	 (val 'cancelled))
+    (math-tracing-integral "Integrating "
+			   (math-format-value expr 1000)
+			   "...\n")
+    (and cur-record
+	 (progn
+	   (math-tracing-integral "Found "
+				  (math-format-value (nth 1 cur-record) 1000))
+	   (and (consp (nth 1 cur-record))
+		(math-replace-integral-parts cur-record))
+	   (math-tracing-integral " => "
+				  (math-format-value (nth 1 cur-record) 1000)
+				  "\n")))
+    (or (and cur-record
+	     (not (eq (nth 1 cur-record) 'cancelled))
+	     (or (not (integerp (nth 1 cur-record)))
+		 (>= (nth 1 cur-record) math-integ-level)))
+	(and (math-integral-contains-parts expr)
+	     (progn
+	       (setq val nil)
+	       t))
+	(unwind-protect
+	    (progn
+	      (let (math-integ-msg)
+		(if (eq calc-display-working-message 'lots)
+		    (progn
+		      (calc-set-command-flag 'clear-message)
+		      (setq math-integ-msg (format
+					    "Working... Integrating %s"
+					    (math-format-flat-expr expr 0)))
+		      (message math-integ-msg)))
+		(if cur-record
+		    (setcar (cdr cur-record)
+			    (if same-as-above (vector simp) 'busy))
+		  (setq cur-record
+			(list expr (if same-as-above (vector simp) 'busy))
+			math-integral-cache (cons cur-record
+						  math-integral-cache)))
+		(if (eq simplify 'yes)
+		    (progn
+		      (math-tracing-integral "Simplifying...")
+		      (setq simp (math-simplify expr))
+		      (setq val (if (equal simp expr)
+				    (progn
+				      (math-tracing-integral " no change\n")
+				      (math-do-integral expr))
+				  (math-tracing-integral " simplified\n")
+				  (math-integral simp 'no t))))
+		  (or (setq val (math-do-integral expr))
+		      (eq simplify 'no)
+		      (let ((simp (math-simplify expr)))
+			(or (equal simp expr)
+			    (progn
+			      (math-tracing-integral "Trying again after "
+						     "simplification...\n")
+			      (setq val (math-integral simp 'no t))))))))
+	      (if (eq calc-display-working-message 'lots)
+		  (message math-integ-msg)))
+	  (setcar (cdr cur-record) (or val
+				       (if (or math-enable-subst
+					       (not math-any-substs))
+					   math-integ-level
+					 'cancelled)))))
+    (setq val cur-record)
+    (while (vectorp (nth 1 val))
+      (setq val (aref (nth 1 val) 0)))
+    (setq val (if (memq (nth 1 val) '(parts parts2))
+		  (progn
+		    (setcar (cdr val) 'parts2)
+		    (list 'var 'PARTS val))
+		(and (consp (nth 1 val))
+		     (nth 1 val))))
+    (math-tracing-integral "Integral of "
+			   (math-format-value expr 1000)
+			   "  is  "
+			   (math-format-value val 1000)
+			   "\n")
+    val)
+)
+(defvar math-integral-cache nil)
+(defvar math-integral-cache-state nil)
+
+(defun math-integral-contains-parts (expr)
+  (if (Math-primp expr)
+      (and (eq (car-safe expr) 'var)
+	   (eq (nth 1 expr) 'PARTS)
+	   (listp (nth 2 expr)))
+    (while (and (setq expr (cdr expr))
+		(not (math-integral-contains-parts (car expr)))))
+    expr)
+)
+
+(defun math-replace-integral-parts (expr)
+  (or (Math-primp expr)
+      (while (setq expr (cdr expr))
+	(and (consp (car expr))
+	     (if (eq (car (car expr)) 'var)
+		 (and (eq (nth 1 (car expr)) 'PARTS)
+		      (consp (nth 2 (car expr)))
+		      (if (listp (nth 1 (nth 2 (car expr))))
+			  (progn
+			    (setcar expr (nth 1 (nth 2 (car expr))))
+			    (math-replace-integral-parts (cons 'foo expr)))
+			(setcar (cdr cur-record) 'cancelled)))
+	       (math-replace-integral-parts (car expr))))))
+)
+
+(defun math-do-integral (expr)
+  (let (t1 t2)
+    (or (cond ((not (math-expr-contains expr math-integ-var))
+	       (math-mul expr math-integ-var))
+	      ((equal expr math-integ-var)
+	       (math-div (math-sqr expr) 2))
+	      ((eq (car expr) '+)
+	       (and (setq t1 (math-integral (nth 1 expr)))
+		    (setq t2 (math-integral (nth 2 expr)))
+		    (math-add t1 t2)))
+	      ((eq (car expr) '-)
+	       (and (setq t1 (math-integral (nth 1 expr)))
+		    (setq t2 (math-integral (nth 2 expr)))
+		    (math-sub t1 t2)))
+	      ((eq (car expr) 'neg)
+	       (and (setq t1 (math-integral (nth 1 expr)))
+		    (math-neg t1)))
+	      ((eq (car expr) '*)
+	       (cond ((not (math-expr-contains (nth 1 expr) math-integ-var))
+		      (and (setq t1 (math-integral (nth 2 expr)))
+			   (math-mul (nth 1 expr) t1)))
+		     ((not (math-expr-contains (nth 2 expr) math-integ-var))
+		      (and (setq t1 (math-integral (nth 1 expr)))
+			   (math-mul t1 (nth 2 expr))))
+		     ((memq (car-safe (nth 1 expr)) '(+ -))
+		      (math-integral (list (car (nth 1 expr))
+					   (math-mul (nth 1 (nth 1 expr))
+						     (nth 2 expr))
+					   (math-mul (nth 2 (nth 1 expr))
+						     (nth 2 expr)))
+				     'yes t))
+		     ((memq (car-safe (nth 2 expr)) '(+ -))
+		      (math-integral (list (car (nth 2 expr))
+					   (math-mul (nth 1 (nth 2 expr))
+						     (nth 1 expr))
+					   (math-mul (nth 2 (nth 2 expr))
+						     (nth 1 expr)))
+				     'yes t))))
+	      ((eq (car expr) '/)
+	       (cond ((and (not (math-expr-contains (nth 1 expr)
+						    math-integ-var))
+			   (not (math-equal-int (nth 1 expr) 1)))
+		      (and (setq t1 (math-integral (math-div 1 (nth 2 expr))))
+			   (math-mul (nth 1 expr) t1)))
+		     ((not (math-expr-contains (nth 2 expr) math-integ-var))
+		      (and (setq t1 (math-integral (nth 1 expr)))
+			   (math-div t1 (nth 2 expr))))
+		     ((and (eq (car-safe (nth 1 expr)) '*)
+			   (not (math-expr-contains (nth 1 (nth 1 expr))
+						    math-integ-var)))
+		      (and (setq t1 (math-integral
+				     (math-div (nth 2 (nth 1 expr))
+					       (nth 2 expr))))
+			   (math-mul t1 (nth 1 (nth 1 expr)))))
+		     ((and (eq (car-safe (nth 1 expr)) '*)
+			   (not (math-expr-contains (nth 2 (nth 1 expr))
+						    math-integ-var)))
+		      (and (setq t1 (math-integral
+				     (math-div (nth 1 (nth 1 expr))
+					       (nth 2 expr))))
+			   (math-mul t1 (nth 2 (nth 1 expr)))))
+		     ((and (eq (car-safe (nth 2 expr)) '*)
+			   (not (math-expr-contains (nth 1 (nth 2 expr))
+						    math-integ-var)))
+		      (and (setq t1 (math-integral
+				     (math-div (nth 1 expr)
+					       (nth 2 (nth 2 expr)))))
+			   (math-div t1 (nth 1 (nth 2 expr)))))
+		     ((and (eq (car-safe (nth 2 expr)) '*)
+			   (not (math-expr-contains (nth 2 (nth 2 expr))
+						    math-integ-var)))
+		      (and (setq t1 (math-integral
+				     (math-div (nth 1 expr)
+					       (nth 1 (nth 2 expr)))))
+			   (math-div t1 (nth 2 (nth 2 expr)))))
+		     ((eq (car-safe (nth 2 expr)) 'calcFunc-exp)
+		      (math-integral
+		       (math-mul (nth 1 expr)
+				 (list 'calcFunc-exp
+				       (math-neg (nth 1 (nth 2 expr)))))))))
+	      ((eq (car expr) '^)
+	       (cond ((not (math-expr-contains (nth 1 expr) math-integ-var))
+		      (or (and (setq t1 (math-is-polynomial (nth 2 expr)
+							    math-integ-var 1))
+			       (math-div expr
+					 (math-mul (nth 1 t1)
+						   (math-normalize
+						    (list 'calcFunc-ln
+							  (nth 1 expr))))))
+			  (math-integral
+			   (list 'calcFunc-exp
+				 (math-mul (nth 2 expr)
+					   (math-normalize
+					    (list 'calcFunc-ln
+						  (nth 1 expr)))))
+			   'yes t)))
+		     ((not (math-expr-contains (nth 2 expr) math-integ-var))
+		      (if (and (integerp (nth 2 expr)) (< (nth 2 expr) 0))
+			  (math-integral
+			   (list '/ 1 (math-pow (nth 1 expr) (- (nth 2 expr))))
+			   nil t)
+			(or (and (setq t1 (math-is-polynomial (nth 1 expr)
+							      math-integ-var
+							      1))
+				 (setq t2 (math-add (nth 2 expr) 1))
+				 (math-div (math-pow (nth 1 expr) t2)
+					   (math-mul t2 (nth 1 t1))))
+			    (and (Math-negp (nth 2 expr))
+				 (math-integral
+				  (math-div 1
+					    (math-pow (nth 1 expr)
+						      (math-neg
+						       (nth 2 expr))))
+				  nil t))
+			    nil))))))
+
+	;; Integral of a polynomial.
+	(and (setq t1 (math-is-polynomial expr math-integ-var 20))
+	     (let ((accum 0)
+		   (n 1))
+	       (while t1
+		 (if (setq accum (math-add accum
+					   (math-div (math-mul (car t1)
+							       (math-pow
+								math-integ-var
+								n))
+						     n))
+			   t1 (cdr t1))
+		     (setq n (1+ n))))
+	       accum))
+
+	;; Try looking it up!
+	(cond ((= (length expr) 2)
+	       (and (symbolp (car expr))
+		    (setq t1 (get (car expr) 'math-integral))
+		    (progn
+		      (while (and t1
+				  (not (setq t2 (funcall (car t1)
+							 (nth 1 expr)))))
+			(setq t1 (cdr t1)))
+		      (and t2 (math-normalize t2)))))
+	      ((= (length expr) 3)
+	       (and (symbolp (car expr))
+		    (setq t1 (get (car expr) 'math-integral-2))
+		    (progn
+		      (while (and t1
+				  (not (setq t2 (funcall (car t1)
+							 (nth 1 expr)
+							 (nth 2 expr)))))
+			(setq t1 (cdr t1)))
+		      (and t2 (math-normalize t2))))))
+
+	;; Integral of a rational function.
+	(and (math-ratpoly-p expr math-integ-var)
+	     (setq t1 (calcFunc-apart expr math-integ-var))
+	     (not (equal t1 expr))
+	     (math-integral t1))
+
+	;; Try user-defined integration rules.
+	(and has-rules
+	     (let ((math-old-integ (symbol-function 'calcFunc-integ))
+		   (input (list 'calcFunc-integtry expr math-integ-var))
+		   res part)
+	       (unwind-protect
+		   (progn
+		     (fset 'calcFunc-integ 'math-sub-integration)
+		     (setq res (math-rewrite input
+					     '(var IntegRules var-IntegRules)
+					     1))
+		     (fset 'calcFunc-integ math-old-integ)
+		     (and (not (equal res input))
+			  (if (setq part (math-expr-calls
+					  res '(calcFunc-integsubst)))
+			      (and (memq (length part) '(3 4 5))
+				   (let ((parts (mapcar
+						 (function
+						  (lambda (x)
+						    (math-expr-subst
+						     x (nth 2 part)
+						     math-integ-var)))
+						 (cdr part))))
+				     (math-integrate-by-substitution
+				      expr (car parts) t
+				      (or (nth 2 parts)
+					  (list 'calcFunc-integfailed
+						math-integ-var))
+				      (nth 3 parts))))
+			    (if (not (math-expr-calls res
+						      '(calcFunc-integtry
+							calcFunc-integfailed)))
+				res))))
+		 (fset 'calcFunc-integ math-old-integ))))
+
+	;; See if the function is a symbolic derivative.
+	(and (string-match "'" (symbol-name (car expr)))
+	     (let ((name (symbol-name (car expr)))
+		   (p expr) (n 0) (which nil) (bad nil))
+	       (while (setq n (1+ n) p (cdr p))
+		 (if (equal (car p) math-integ-var)
+		     (if which (setq bad t) (setq which n))
+		   (if (math-expr-contains (car p) math-integ-var)
+		       (setq bad t))))
+	       (and which (not bad)
+		    (let ((prime (if (= which 1) "'" (format "'%d" which))))
+		      (and (string-match (concat prime "\\('['0-9]*\\|$\\)")
+					 name)
+			   (cons (intern
+				  (concat
+				   (substring name 0 (match-beginning 0))
+				   (substring name (+ (match-beginning 0)
+						      (length prime)))))
+				 (cdr expr)))))))
+
+	;; Try transformation methods (parts, substitutions).
+	(and (> math-integ-level 0)
+	     (math-do-integral-methods expr))
+
+	;; Try expanding the function's definition.
+	(let ((res (math-expand-formula expr)))
+	  (and res
+	       (math-integral res)))))
+)
+
+(defun math-sub-integration (expr &rest rest)
+  (or (if (or (not rest)
+	      (and (< math-integ-level math-integral-limit)
+		   (eq (car rest) math-integ-var)))
+	  (math-integral expr)
+	(let ((res (apply math-old-integ expr rest)))
+	  (and (or (= math-integ-level math-integral-limit)
+		   (not (math-expr-calls res 'calcFunc-integ)))
+	       res)))
+      (list 'calcFunc-integfailed expr))
+)
+
+(defun math-do-integral-methods (expr)
+  (let ((so-far math-integ-var-list-list)
+	rat-in)
+
+    ;; Integration by substitution, for various likely sub-expressions.
+    ;; (In first pass, we look only for sub-exprs that are linear in X.)
+    (or (if math-enable-subst
+	    (math-integ-try-substitutions expr)
+	  (math-integ-try-linear-substitutions expr))
+
+	;; If function has sines and cosines, try tan(x/2) substitution.
+	(and (let ((p (setq rat-in (math-expr-rational-in expr))))
+	       (while (and p
+			   (memq (car (car p)) '(calcFunc-sin
+						 calcFunc-cos
+						 calcFunc-tan))
+			   (equal (nth 1 (car p)) math-integ-var))
+		 (setq p (cdr p)))
+	       (null p))
+	     (or (and (math-integ-parts-easy expr)
+		      (math-integ-try-parts expr t))
+		 (math-integrate-by-good-substitution
+		  expr (list 'calcFunc-tan (math-div math-integ-var 2)))))
+
+	;; If function has sinh and cosh, try tanh(x/2) substitution.
+	(and (let ((p rat-in))
+	       (while (and p
+			   (memq (car (car p)) '(calcFunc-sinh
+						 calcFunc-cosh
+						 calcFunc-tanh
+						 calcFunc-exp))
+			   (equal (nth 1 (car p)) math-integ-var))
+		 (setq p (cdr p)))
+	       (null p))
+	     (or (and (math-integ-parts-easy expr)
+		      (math-integ-try-parts expr t))
+		 (math-integrate-by-good-substitution
+		  expr (list 'calcFunc-tanh (math-div math-integ-var 2)))))
+
+	;; If function has square roots, try sin, tan, or sec substitution.
+	(and (let ((p rat-in))
+	       (setq t1 nil)
+	       (while (and p
+			   (or (equal (car p) math-integ-var)
+			       (and (eq (car (car p)) 'calcFunc-sqrt)
+				    (setq t1 (math-is-polynomial
+					      (nth 1 (setq t2 (car p)))
+					      math-integ-var 2)))))
+		 (setq p (cdr p)))
+	       (and (null p) t1))
+	     (if (cdr (cdr t1))
+		 (if (math-guess-if-neg (nth 2 t1))
+		     (let* ((c (math-sqrt (math-neg (nth 2 t1))))
+			    (d (math-div (nth 1 t1) (math-mul -2 c)))
+			    (a (math-sqrt (math-add (car t1) (math-sqr d)))))
+		       (math-integrate-by-good-substitution
+			expr (list 'calcFunc-arcsin
+				   (math-div-thru
+				    (math-add (math-mul c math-integ-var) d)
+				    a))))
+		   (let* ((c (math-sqrt (nth 2 t1)))
+			  (d (math-div (nth 1 t1) (math-mul 2 c)))
+			  (aa (math-sub (car t1) (math-sqr d))))
+		     (if (and nil (not (and (eq d 0) (eq c 1))))
+			 (math-integrate-by-good-substitution
+			  expr (math-add (math-mul c math-integ-var) d))
+		       (if (math-guess-if-neg aa)
+			   (math-integrate-by-good-substitution
+			    expr (list 'calcFunc-arccosh
+				       (math-div-thru
+					(math-add (math-mul c math-integ-var)
+						  d)
+					(math-sqrt (math-neg aa)))))
+			 (math-integrate-by-good-substitution
+			  expr (list 'calcFunc-arcsinh
+				     (math-div-thru
+				      (math-add (math-mul c math-integ-var)
+						d)
+				      (math-sqrt aa))))))))
+	       (math-integrate-by-good-substitution expr t2)) )
+
+	;; Try integration by parts.
+	(math-integ-try-parts expr)
+
+	;; Give up.
+	nil))
+)
+
+(defun math-integ-parts-easy (expr)
+  (cond ((Math-primp expr) t)
+	((memq (car expr) '(+ - *))
+	 (and (math-integ-parts-easy (nth 1 expr))
+	      (math-integ-parts-easy (nth 2 expr))))
+	((eq (car expr) '/)
+	 (and (math-integ-parts-easy (nth 1 expr))
+	      (math-atomic-factorp (nth 2 expr))))
+	((eq (car expr) '^)
+	 (and (natnump (nth 2 expr))
+	      (math-integ-parts-easy (nth 1 expr))))
+	((eq (car expr) 'neg)
+	 (math-integ-parts-easy (nth 1 expr)))
+	(t t))
+)
+
+(defun math-integ-try-parts (expr &optional math-good-parts)
+  ;; Integration by parts:
+  ;;   integ(f(x) g(x),x) = f(x) h(x) - integ(h(x) f'(x),x)
+  ;;     where h(x) = integ(g(x),x).
+  (or (let ((exp (calcFunc-expand expr)))
+	(and (not (equal exp expr))
+	     (math-integral exp)))
+      (and (eq (car expr) '*)
+	   (let ((first-bad (or (math-polynomial-p (nth 1 expr)
+						   math-integ-var)
+				(equal (nth 2 expr) math-prev-parts-v))))
+	     (or (and first-bad   ; so try this one first
+		      (math-integrate-by-parts (nth 1 expr) (nth 2 expr)))
+		 (math-integrate-by-parts (nth 2 expr) (nth 1 expr))
+		 (and (not first-bad)
+		      (math-integrate-by-parts (nth 1 expr) (nth 2 expr))))))
+      (and (eq (car expr) '/)
+	   (math-expr-contains (nth 1 expr) math-integ-var)
+	   (let ((recip (math-div 1 (nth 2 expr))))
+	     (or (math-integrate-by-parts (nth 1 expr) recip)
+		 (math-integrate-by-parts recip (nth 1 expr)))))
+      (and (eq (car expr) '^)
+	   (math-integrate-by-parts (math-pow (nth 1 expr)
+					      (math-sub (nth 2 expr) 1))
+				    (nth 1 expr))))
+)
+
+(defun math-integrate-by-parts (u vprime)
+  (let ((math-integ-level (if (or math-good-parts
+				  (math-polynomial-p u math-integ-var))
+			      math-integ-level
+			    (1- math-integ-level)))
+	(math-doing-parts t)
+	v temp)
+    (and (>= math-integ-level 0)
+	 (unwind-protect
+	     (progn
+	       (setcar (cdr cur-record) 'parts)
+	       (math-tracing-integral "Integrating by parts, u = "
+				      (math-format-value u 1000)
+				      ", v' = "
+				      (math-format-value vprime 1000)
+				      "\n")
+	       (and (setq v (math-integral vprime))
+		    (setq temp (calcFunc-deriv u math-integ-var nil t))
+		    (setq temp (let ((math-prev-parts-v v))
+				 (math-integral (math-mul v temp) 'yes)))
+		    (setq temp (math-sub (math-mul u v) temp))
+		    (if (eq (nth 1 cur-record) 'parts)
+			(calcFunc-expand temp)
+		      (setq v (list 'var 'PARTS cur-record)
+			    var-thing (list 'vec (math-sub v temp) v)
+			    temp (let (calc-next-why)
+				   (math-solve-for (math-sub v temp) 0 v nil)))
+		      (and temp (not (integerp temp))
+			   (math-simplify-extended temp)))))
+	   (setcar (cdr cur-record) 'busy))))
+)
+
+;;; This tries two different formulations, hoping the algebraic simplifier
+;;; will be strong enough to handle at least one.
+(defun math-integrate-by-substitution (expr u &optional user uinv uinvprime)
+  (and (> math-integ-level 0)
+       (let ((math-integ-level (max (- math-integ-level 2) 0)))
+	 (math-integrate-by-good-substitution expr u user uinv uinvprime)))
+)
+
+(defun math-integrate-by-good-substitution (expr u &optional user
+						 uinv uinvprime)
+  (let ((math-living-dangerously t)
+	deriv temp)
+    (and (setq uinv (if uinv
+			(math-expr-subst uinv math-integ-var
+					 math-integ-var-2)
+		      (let (calc-next-why)
+			(math-solve-for u
+					math-integ-var-2
+					math-integ-var nil))))
+	 (progn
+	   (math-tracing-integral "Integrating by substitution, u = "
+				  (math-format-value u 1000)
+				  "\n")
+	   (or (and (setq deriv (calcFunc-deriv u
+						math-integ-var nil
+						(not user)))
+		    (setq temp (math-integral (math-expr-subst
+					       (math-expr-subst
+						(math-expr-subst
+						 (math-div expr deriv)
+						 u
+						 math-integ-var-2)
+						math-integ-var
+						uinv)
+					       math-integ-var-2
+					       math-integ-var)
+					      'yes)))
+	       (and (setq deriv (or uinvprime
+				    (calcFunc-deriv uinv
+						    math-integ-var-2
+						    math-integ-var
+						    (not user))))
+		    (setq temp (math-integral (math-mul
+					       (math-expr-subst
+						(math-expr-subst
+						 (math-expr-subst
+						  expr
+						  u
+						  math-integ-var-2)
+						 math-integ-var
+						 uinv)
+						math-integ-var-2
+						math-integ-var)
+					       deriv)
+					      'yes)))))
+	 (math-simplify-extended
+	  (math-expr-subst temp math-integ-var u))))
+)
+
+;;; Look for substitutions of the form u = a x + b.
+(defun math-integ-try-linear-substitutions (sub-expr)
+  (and (not (Math-primp sub-expr))
+       (or (and (not (memq (car sub-expr) '(+ - * / neg)))
+		(not (and (eq (car sub-expr) '^)
+			  (integerp (nth 2 sub-expr))))
+		(math-expr-contains sub-expr math-integ-var)
+		(let ((res nil))
+		  (while (and (setq sub-expr (cdr sub-expr))
+			      (or (not (math-linear-in (car sub-expr)
+						       math-integ-var))
+				  (assoc (car sub-expr) so-far)
+				  (progn
+				    (setq so-far (cons (list (car sub-expr))
+						       so-far))
+				    (not (setq res
+					       (math-integrate-by-substitution
+						expr (car sub-expr))))))))
+		  res))
+	   (let ((res nil))
+	     (while (and (setq sub-expr (cdr sub-expr))
+			 (not (setq res (math-integ-try-linear-substitutions
+					 (car sub-expr))))))
+	     res)))
+)
+
+;;; Recursively try different substitutions based on various sub-expressions.
+(defun math-integ-try-substitutions (sub-expr &optional allow-rat)
+  (and (not (Math-primp sub-expr))
+       (not (assoc sub-expr so-far))
+       (math-expr-contains sub-expr math-integ-var)
+       (or (and (if (and (not (memq (car sub-expr) '(+ - * / neg)))
+			 (not (and (eq (car sub-expr) '^)
+				   (integerp (nth 2 sub-expr)))))
+		    (setq allow-rat t)
+		  (prog1 allow-rat (setq allow-rat nil)))
+		(not (eq sub-expr expr))
+		(or (math-integrate-by-substitution expr sub-expr)
+		    (and (eq (car sub-expr) '^)
+			 (integerp (nth 2 sub-expr))
+			 (< (nth 2 sub-expr) 0)
+			 (math-integ-try-substitutions
+			  (math-pow (nth 1 sub-expr) (- (nth 2 sub-expr)))
+			  t))))
+	   (let ((res nil))
+	     (setq so-far (cons (list sub-expr) so-far))
+	     (while (and (setq sub-expr (cdr sub-expr))
+			 (not (setq res (math-integ-try-substitutions
+					 (car sub-expr) allow-rat)))))
+	     res)))
+)
+
+(defun math-expr-rational-in (expr)
+  (let ((parts nil))
+    (math-expr-rational-in-rec expr)
+    (mapcar 'car parts))
+)
+
+(defun math-expr-rational-in-rec (expr)
+  (cond ((Math-primp expr)
+	 (and (equal expr math-integ-var)
+	      (not (assoc expr parts))
+	      (setq parts (cons (list expr) parts))))
+	((or (memq (car expr) '(+ - * / neg))
+	     (and (eq (car expr) '^) (integerp (nth 2 expr))))
+	 (math-expr-rational-in-rec (nth 1 expr))
+	 (and (nth 2 expr) (math-expr-rational-in-rec (nth 2 expr))))
+	((and (eq (car expr) '^)
+	      (eq (math-quarter-integer (nth 2 expr)) 2))
+	 (math-expr-rational-in-rec (list 'calcFunc-sqrt (nth 1 expr))))
+	(t
+	 (and (not (assoc expr parts))
+	      (math-expr-contains expr math-integ-var)
+	      (setq parts (cons (list expr) parts)))))
+)
+
+(defun math-expr-calls (expr funcs &optional arg-contains)
+  (if (consp expr)
+      (if (or (memq (car expr) funcs)
+	      (and (eq (car expr) '^) (eq (car funcs) 'calcFunc-sqrt)
+		   (eq (math-quarter-integer (nth 2 expr)) 2)))
+	  (and (or (not arg-contains)
+		   (math-expr-contains expr arg-contains))
+	       expr)
+	(and (not (Math-primp expr))
+	     (let ((res nil))
+	       (while (and (setq expr (cdr expr))
+			   (not (setq res (math-expr-calls
+					   (car expr) funcs arg-contains)))))
+	       res))))
+)
+
+(defun math-fix-const-terms (expr except-vars)
+  (cond ((not (math-expr-depends expr except-vars)) 0)
+	((Math-primp expr) expr)
+	((eq (car expr) '+)
+	 (math-add (math-fix-const-terms (nth 1 expr) except-vars)
+		   (math-fix-const-terms (nth 2 expr) except-vars)))
+	((eq (car expr) '-)
+	 (math-sub (math-fix-const-terms (nth 1 expr) except-vars)
+		   (math-fix-const-terms (nth 2 expr) except-vars)))
+	(t expr))
+)
+
+;; Command for debugging the Calculator's symbolic integrator.
+(defun calc-dump-integral-cache (&optional arg)
+  (interactive "P")
+  (let ((buf (current-buffer)))
+    (unwind-protect
+	(let ((p math-integral-cache)
+	      cur-record)
+	  (display-buffer (get-buffer-create "*Integral Cache*")) 
+	  (set-buffer (get-buffer "*Integral Cache*"))
+	  (erase-buffer)
+	  (while p
+	    (setq cur-record (car p))
+	    (or arg (math-replace-integral-parts cur-record))
+	    (insert (math-format-flat-expr (car cur-record) 0)
+		    " --> "
+		    (if (symbolp (nth 1 cur-record))
+			(concat "(" (symbol-name (nth 1 cur-record)) ")")
+		      (math-format-flat-expr (nth 1 cur-record) 0))
+		    "\n")
+	    (setq p (cdr p)))
+	  (goto-char (point-min)))
+      (set-buffer buf)))
+)
+
+(defun math-try-integral (expr)
+  (let ((math-integ-level math-integral-limit)
+	(math-integ-depth 0)
+	(math-integ-msg "Working...done")
+	(cur-record nil)   ; a technicality
+	(math-integrating t)
+	(calc-prefer-frac t)
+	(calc-symbolic-mode t)
+	(has-rules (calc-has-rules 'var-IntegRules)))
+    (or (math-integral expr 'yes)
+	(and math-any-substs
+	     (setq math-enable-subst t)
+	     (math-integral expr 'yes))
+	(and (> math-max-integral-limit math-integral-limit)
+	     (setq math-integral-limit math-max-integral-limit
+		   math-integ-level math-integral-limit)
+	     (math-integral expr 'yes))))
+)
+
+(defun calcFunc-integ (expr var &optional low high)
+  (cond
+   ;; Do these even if the parts turn out not to be integrable.
+   ((eq (car-safe expr) '+)
+    (math-add (calcFunc-integ (nth 1 expr) var low high)
+	      (calcFunc-integ (nth 2 expr) var low high)))
+   ((eq (car-safe expr) '-)
+    (math-sub (calcFunc-integ (nth 1 expr) var low high)
+	      (calcFunc-integ (nth 2 expr) var low high)))
+   ((eq (car-safe expr) 'neg)
+    (math-neg (calcFunc-integ (nth 1 expr) var low high)))
+   ((and (eq (car-safe expr) '*)
+	 (not (math-expr-contains (nth 1 expr) var)))
+    (math-mul (nth 1 expr) (calcFunc-integ (nth 2 expr) var low high)))
+   ((and (eq (car-safe expr) '*)
+	 (not (math-expr-contains (nth 2 expr) var)))
+    (math-mul (calcFunc-integ (nth 1 expr) var low high) (nth 2 expr)))
+   ((and (eq (car-safe expr) '/)
+	 (not (math-expr-contains (nth 1 expr) var))
+	 (not (math-equal-int (nth 1 expr) 1)))
+    (math-mul (nth 1 expr)
+	      (calcFunc-integ (math-div 1 (nth 2 expr)) var low high)))
+   ((and (eq (car-safe expr) '/)
+	 (not (math-expr-contains (nth 2 expr) var)))
+    (math-div (calcFunc-integ (nth 1 expr) var low high) (nth 2 expr)))
+   ((and (eq (car-safe expr) '/)
+	 (eq (car-safe (nth 1 expr)) '*)
+	 (not (math-expr-contains (nth 1 (nth 1 expr)) var)))
+    (math-mul (nth 1 (nth 1 expr))
+	      (calcFunc-integ (math-div (nth 2 (nth 1 expr)) (nth 2 expr))
+			      var low high)))
+   ((and (eq (car-safe expr) '/)
+	 (eq (car-safe (nth 1 expr)) '*)
+	 (not (math-expr-contains (nth 2 (nth 1 expr)) var)))
+    (math-mul (nth 2 (nth 1 expr))
+	      (calcFunc-integ (math-div (nth 1 (nth 1 expr)) (nth 2 expr))
+			      var low high)))
+   ((and (eq (car-safe expr) '/)
+	 (eq (car-safe (nth 2 expr)) '*)
+	 (not (math-expr-contains (nth 1 (nth 2 expr)) var)))
+    (math-div (calcFunc-integ (math-div (nth 1 expr) (nth 2 (nth 2 expr)))
+			      var low high)
+	      (nth 1 (nth 2 expr))))
+   ((and (eq (car-safe expr) '/)
+	 (eq (car-safe (nth 2 expr)) '*)
+	 (not (math-expr-contains (nth 2 (nth 2 expr)) var)))
+    (math-div (calcFunc-integ (math-div (nth 1 expr) (nth 1 (nth 2 expr)))
+			      var low high)
+	      (nth 2 (nth 2 expr))))
+   ((eq (car-safe expr) 'vec)
+    (cons 'vec (mapcar (function (lambda (x) (calcFunc-integ x var low high)))
+		       (cdr expr))))
+   (t
+    (let ((state (list calc-angle-mode
+		       ;;calc-symbolic-mode
+		       ;;calc-prefer-frac
+		       calc-internal-prec
+		       (calc-var-value 'var-IntegRules)
+		       (calc-var-value 'var-IntegSimpRules))))
+      (or (equal state math-integral-cache-state)
+	  (setq math-integral-cache-state state
+		math-integral-cache nil)))
+    (let* ((math-max-integral-limit (or (and (boundp 'var-IntegLimit)
+					     (natnump var-IntegLimit)
+					     var-IntegLimit)
+					3))
+	   (math-integral-limit 1)
+	   (sexpr (math-expr-subst expr var math-integ-var))
+	   (trace-buffer (get-buffer "*Trace*"))
+	   (calc-language (if (eq calc-language 'big) nil calc-language))
+	   (math-any-substs t)
+	   (math-enable-subst nil)
+	   (math-prev-parts-v nil)
+	   (math-doing-parts nil)
+	   (math-good-parts nil)
+	   (res
+	    (if trace-buffer
+		(let ((calcbuf (current-buffer))
+		      (calcwin (selected-window)))
+		  (unwind-protect
+		      (progn
+			(if (get-buffer-window trace-buffer)
+			    (select-window (get-buffer-window trace-buffer)))
+			(set-buffer trace-buffer)
+			(goto-char (point-max))
+			(or (assq 'scroll-stop (buffer-local-variables))
+			    (progn
+			      (make-local-variable 'scroll-step)
+			      (setq scroll-step 3)))
+			(insert "\n\n\n")
+			(set-buffer calcbuf)
+			(math-try-integral sexpr))
+		    (select-window calcwin)
+		      (set-buffer calcbuf)))
+	      (math-try-integral sexpr))))
+      (if res
+	  (progn
+	    (if (calc-has-rules 'var-IntegAfterRules)
+		(setq res (math-rewrite res '(var IntegAfterRules
+						  var-IntegAfterRules))))
+	    (math-simplify
+	     (if (and low high)
+		 (math-sub (math-expr-subst res math-integ-var high)
+			   (math-expr-subst res math-integ-var low))
+	       (setq res (math-fix-const-terms res math-integ-vars))
+	       (if low
+		   (math-expr-subst res math-integ-var low)
+		 (math-expr-subst res math-integ-var var)))))
+	(append (list 'calcFunc-integ expr var)
+		(and low (list low))
+		(and high (list high)))))))
+)
+
+
+(math-defintegral calcFunc-inv
+  (math-integral (math-div 1 u)))
+
+(math-defintegral calcFunc-conj
+  (let ((int (math-integral u)))
+    (and int
+	 (list 'calcFunc-conj int))))
+
+(math-defintegral calcFunc-deg
+  (let ((int (math-integral u)))
+    (and int
+	 (list 'calcFunc-deg int))))
+
+(math-defintegral calcFunc-rad
+  (let ((int (math-integral u)))
+    (and int
+	 (list 'calcFunc-rad int))))
+
+(math-defintegral calcFunc-re
+  (let ((int (math-integral u)))
+    (and int
+	 (list 'calcFunc-re int))))
+
+(math-defintegral calcFunc-im
+  (let ((int (math-integral u)))
+    (and int
+	 (list 'calcFunc-im int))))
+
+(math-defintegral calcFunc-sqrt
+  (and (equal u math-integ-var)
+       (math-mul '(frac 2 3)
+		 (list 'calcFunc-sqrt (math-pow u 3)))))
+
+(math-defintegral calcFunc-exp
+  (or (and (equal u math-integ-var)
+	   (list 'calcFunc-exp u))
+      (let ((p (math-is-polynomial u math-integ-var 2)))
+	(and (nth 2 p)
+	     (let ((sqa (math-sqrt (math-neg (nth 2 p)))))
+	       (math-div
+		(math-mul
+		 (math-mul (math-div (list 'calcFunc-sqrt '(var pi var-pi))
+				     sqa)
+			   (math-normalize
+			    (list 'calcFunc-exp
+				  (math-div (math-sub (math-mul (car p)
+								(nth 2 p))
+						      (math-div
+						       (math-sqr (nth 1 p))
+						       4))
+					    (nth 2 p)))))
+		 (list 'calcFunc-erf
+		       (math-sub (math-mul sqa math-integ-var)
+				 (math-div (nth 1 p) (math-mul 2 sqa)))))
+		2))))))
+
+(math-defintegral calcFunc-ln
+  (or (and (equal u math-integ-var)
+	   (math-sub (math-mul u (list 'calcFunc-ln u)) u))
+      (and (eq (car u) '*)
+	   (math-integral (math-add (list 'calcFunc-ln (nth 1 u))
+				    (list 'calcFunc-ln (nth 2 u)))))
+      (and (eq (car u) '/)
+	   (math-integral (math-sub (list 'calcFunc-ln (nth 1 u))
+				    (list 'calcFunc-ln (nth 2 u)))))
+      (and (eq (car u) '^)
+	   (math-integral (math-mul (nth 2 u)
+				    (list 'calcFunc-ln (nth 1 u)))))))
+
+(math-defintegral calcFunc-log10
+  (and (equal u math-integ-var)
+       (math-sub (math-mul u (list 'calcFunc-ln u))
+		 (math-div u (list 'calcFunc-ln 10)))))
+
+(math-defintegral-2 calcFunc-log
+  (math-integral (math-div (list 'calcFunc-ln u)
+			   (list 'calcFunc-ln v))))
+
+(math-defintegral calcFunc-sin
+  (or (and (equal u math-integ-var)
+	   (math-neg (math-from-radians-2 (list 'calcFunc-cos u))))
+      (and (nth 2 (math-is-polynomial u math-integ-var 2))
+	   (math-integral (math-to-exponentials (list 'calcFunc-sin u))))))
+
+(math-defintegral calcFunc-cos
+  (or (and (equal u math-integ-var)
+	   (math-from-radians-2 (list 'calcFunc-sin u)))
+      (and (nth 2 (math-is-polynomial u math-integ-var 2))
+	   (math-integral (math-to-exponentials (list 'calcFunc-cos u))))))
+
+(math-defintegral calcFunc-tan
+  (and (equal u math-integ-var)
+       (math-neg (math-from-radians-2
+		  (list 'calcFunc-ln (list 'calcFunc-cos u))))))
+
+(math-defintegral calcFunc-arcsin
+  (and (equal u math-integ-var)
+       (math-add (math-mul u (list 'calcFunc-arcsin u))
+		 (math-from-radians-2
+		  (list 'calcFunc-sqrt (math-sub 1 (math-sqr u)))))))
+
+(math-defintegral calcFunc-arccos
+  (and (equal u math-integ-var)
+       (math-sub (math-mul u (list 'calcFunc-arccos u))
+		 (math-from-radians-2
+		  (list 'calcFunc-sqrt (math-sub 1 (math-sqr u)))))))
+
+(math-defintegral calcFunc-arctan
+  (and (equal u math-integ-var)
+       (math-sub (math-mul u (list 'calcFunc-arctan u))
+		 (math-from-radians-2
+		  (math-div (list 'calcFunc-ln (math-add 1 (math-sqr u)))
+			    2)))))
+
+(math-defintegral calcFunc-sinh
+  (and (equal u math-integ-var)
+       (list 'calcFunc-cosh u)))
+
+(math-defintegral calcFunc-cosh
+  (and (equal u math-integ-var)
+       (list 'calcFunc-sinh u)))
+
+(math-defintegral calcFunc-tanh
+  (and (equal u math-integ-var)
+       (list 'calcFunc-ln (list 'calcFunc-cosh u))))
+
+(math-defintegral calcFunc-arcsinh
+  (and (equal u math-integ-var)
+       (math-sub (math-mul u (list 'calcFunc-arcsinh u))
+		 (list 'calcFunc-sqrt (math-add (math-sqr u) 1)))))
+
+(math-defintegral calcFunc-arccosh
+  (and (equal u math-integ-var)
+       (math-sub (math-mul u (list 'calcFunc-arccosh u))
+		 (list 'calcFunc-sqrt (math-sub 1 (math-sqr u))))))
+
+(math-defintegral calcFunc-arctanh
+  (and (equal u math-integ-var)
+       (math-sub (math-mul u (list 'calcFunc-arctan u))
+		 (math-div (list 'calcFunc-ln
+				 (math-add 1 (math-sqr u)))
+			   2))))
+
+;;; (Ax + B) / (ax^2 + bx + c)^n forms.
+(math-defintegral-2 /
+  (math-integral-rational-funcs u v))
+
+(defun math-integral-rational-funcs (u v)
+  (let ((pu (math-is-polynomial u math-integ-var 1))
+	(vpow 1) pv)
+    (and pu
+	 (catch 'int-rat
+	   (if (and (eq (car-safe v) '^) (natnump (nth 2 v)))
+	       (setq vpow (nth 2 v)
+		     v (nth 1 v)))
+	   (and (setq pv (math-is-polynomial v math-integ-var 2))
+		(let ((int (math-mul-thru
+			    (car pu)
+			    (math-integral-q02 (car pv) (nth 1 pv)
+					       (nth 2 pv) v vpow))))
+		  (if (cdr pu)
+		      (setq int (math-add int
+					  (math-mul-thru
+					   (nth 1 pu)
+					   (math-integral-q12
+					    (car pv) (nth 1 pv)
+					    (nth 2 pv) v vpow)))))
+		  int))))))
+
+(defun math-integral-q12 (a b c v vpow)
+  (let (q)
+    (cond ((not c)
+	   (cond ((= vpow 1)
+		  (math-sub (math-div math-integ-var b)
+			    (math-mul (math-div a (math-sqr b))
+				      (list 'calcFunc-ln v))))
+		 ((= vpow 2)
+		  (math-div (math-add (list 'calcFunc-ln v)
+				      (math-div a v))
+			    (math-sqr b)))
+		 (t
+		  (let ((nm1 (math-sub vpow 1))
+			(nm2 (math-sub vpow 2)))
+		    (math-div (math-sub
+			       (math-div a (math-mul nm1 (math-pow v nm1)))
+			       (math-div 1 (math-mul nm2 (math-pow v nm2))))
+			      (math-sqr b))))))
+	  ((math-zerop
+	    (setq q (math-sub (math-mul 4 (math-mul a c)) (math-sqr b))))
+	   (let ((part (math-div b (math-mul 2 c))))
+	     (math-mul-thru (math-pow c vpow)
+			    (math-integral-q12 part 1 nil
+					       (math-add math-integ-var part)
+					       (* vpow 2)))))
+	  ((= vpow 1)
+	   (and (math-ratp q) (math-negp q)
+		(let ((calc-symbolic-mode t))
+		  (math-ratp (math-sqrt (math-neg q))))
+		(throw 'int-rat nil))  ; should have used calcFunc-apart first
+	   (math-sub (math-div (list 'calcFunc-ln v) (math-mul 2 c))
+		     (math-mul-thru (math-div b (math-mul 2 c))
+				    (math-integral-q02 a b c v 1))))
+	  (t
+	   (let ((n (1- vpow)))
+	     (math-sub (math-neg (math-div
+				  (math-add (math-mul b math-integ-var)
+					    (math-mul 2 a))
+				  (math-mul n (math-mul q (math-pow v n)))))
+		       (math-mul-thru (math-div (math-mul b (1- (* 2 n)))
+						(math-mul n q))
+				      (math-integral-q02 a b c v n)))))))
+)
+
+(defun math-integral-q02 (a b c v vpow)
+  (let (q rq part)
+    (cond ((not c)
+	   (cond ((= vpow 1)
+		  (math-div (list 'calcFunc-ln v) b))
+		 (t
+		  (math-div (math-pow v (- 1 vpow))
+			    (math-mul (- 1 vpow) b)))))
+	  ((math-zerop
+	    (setq q (math-sub (math-mul 4 (math-mul a c)) (math-sqr b))))
+	   (let ((part (math-div b (math-mul 2 c))))
+	     (math-mul-thru (math-pow c vpow)
+			    (math-integral-q02 part 1 nil
+					       (math-add math-integ-var part)
+					       (* vpow 2)))))
+	  ((progn
+	     (setq part (math-add (math-mul 2 (math-mul c math-integ-var)) b))
+	     (> vpow 1))
+	   (let ((n (1- vpow)))
+	     (math-add (math-div part (math-mul n (math-mul q (math-pow v n))))
+		       (math-mul-thru (math-div (math-mul (- (* 4 n) 2) c)
+						(math-mul n q))
+				      (math-integral-q02 a b c v n)))))
+	  ((math-guess-if-neg q)
+	   (setq rq (list 'calcFunc-sqrt (math-neg q)))
+	   ;;(math-div-thru (list 'calcFunc-ln
+	   ;;			(math-div (math-sub part rq)
+	   ;;				  (math-add part rq)))
+	   ;;		  rq)
+	   (math-div (math-mul -2 (list 'calcFunc-arctanh
+					(math-div part rq)))
+		     rq))
+	  (t
+	   (setq rq (list 'calcFunc-sqrt q))
+	   (math-div (math-mul 2 (math-to-radians-2
+				  (list 'calcFunc-arctan
+					(math-div part rq))))
+		     rq))))
+)
+
+
+(math-defintegral calcFunc-erf
+  (and (equal u math-integ-var)
+       (math-add (math-mul u (list 'calcFunc-erf u))
+		 (math-div 1 (math-mul (list 'calcFunc-exp (math-sqr u))
+				       (list 'calcFunc-sqrt
+					     '(var pi var-pi)))))))
+
+(math-defintegral calcFunc-erfc
+  (and (equal u math-integ-var)
+       (math-sub (math-mul u (list 'calcFunc-erfc u))
+		 (math-div 1 (math-mul (list 'calcFunc-exp (math-sqr u))
+				       (list 'calcFunc-sqrt
+					     '(var pi var-pi)))))))
+
+
+
+
+(defun calcFunc-table (expr var &optional low high step)
+  (or low (setq low '(neg (var inf var-inf)) high '(var inf var-inf)))
+  (or high (setq high low low 1))
+  (and (or (math-infinitep low) (math-infinitep high))
+       (not step)
+       (math-scan-for-limits expr))
+  (and step (math-zerop step) (math-reject-arg step 'nonzerop))
+  (let ((known (+ (if (Math-objectp low) 1 0)
+		  (if (Math-objectp high) 1 0)
+		  (if (or (null step) (Math-objectp step)) 1 0)))
+	(count '(var inf var-inf))
+	vec)
+    (or (= known 2)   ; handy optimization
+	(equal high '(var inf var-inf))
+	(progn
+	  (setq count (math-div (math-sub high low) (or step 1)))
+	  (or (Math-objectp count)
+	      (setq count (math-simplify count)))
+	  (if (Math-messy-integerp count)
+	      (setq count (math-trunc count)))))
+    (if (Math-negp count)
+	(setq count -1))
+    (if (integerp count)
+	(let ((var-DUMMY nil)
+	      (vec math-tabulate-initial)
+	      (math-working-step-2 (1+ count))
+	      (math-working-step 0))
+	  (setq expr (math-evaluate-expr
+		      (math-expr-subst expr var '(var DUMMY var-DUMMY))))
+	  (while (>= count 0)
+	    (setq math-working-step (1+ math-working-step)
+		  var-DUMMY low
+		  vec (cond ((eq math-tabulate-function 'calcFunc-sum)
+			     (math-add vec (math-evaluate-expr expr)))
+			    ((eq math-tabulate-function 'calcFunc-prod)
+			     (math-mul vec (math-evaluate-expr expr)))
+			    (t
+			     (cons (math-evaluate-expr expr) vec)))
+		  low (math-add low (or step 1))
+		  count (1- count)))
+	  (if math-tabulate-function
+	      vec
+	    (cons 'vec (nreverse vec))))
+      (if (Math-integerp count)
+	  (calc-record-why 'fixnump high)
+	(if (Math-num-integerp low)
+	    (if (Math-num-integerp high)
+		(calc-record-why 'integerp step)
+	      (calc-record-why 'integerp high))
+	  (calc-record-why 'integerp low)))
+      (append (list (or math-tabulate-function 'calcFunc-table)
+		    expr var)
+	      (and (not (and (equal low '(neg (var inf var-inf)))
+			     (equal high '(var inf var-inf))))
+		   (list low high))
+	      (and step (list step)))))
+)
+
+(setq math-tabulate-initial nil)
+(setq math-tabulate-function nil)
+
+(defun math-scan-for-limits (x)
+  (cond ((Math-primp x))
+	((and (eq (car x) 'calcFunc-subscr)
+	      (Math-vectorp (nth 1 x))
+	      (math-expr-contains (nth 2 x) var))
+	 (let* ((calc-next-why nil)
+		(low-val (math-solve-for (nth 2 x) 1 var nil))
+		(high-val (math-solve-for (nth 2 x) (1- (length (nth 1 x)))
+					  var nil))
+		temp)
+	   (and low-val (math-realp low-val)
+		high-val (math-realp high-val))
+	   (and (Math-lessp high-val low-val)
+		(setq temp low-val low-val high-val high-val temp))
+	   (setq low (math-max low (math-ceiling low-val))
+		 high (math-min high (math-floor high-val)))))
+	(t
+	 (while (setq x (cdr x))
+	   (math-scan-for-limits (car x)))))
+)
+
+
+(defun calcFunc-sum (expr var &optional low high step)
+  (if math-disable-sums (math-reject-arg))
+  (let* ((res (let* ((calc-internal-prec (+ calc-internal-prec 2)))
+		(math-sum-rec expr var low high step)))
+	 (math-disable-sums t))
+    (math-normalize res))
+)
+(setq math-disable-sums nil)
+
+(defun math-sum-rec (expr var &optional low high step)
+  (or low (setq low '(neg (var inf var-inf)) high '(var inf var-inf)))
+  (and low (not high) (setq high low low 1))
+  (let (t1 t2 val)
+    (setq val
+	  (cond
+	   ((not (math-expr-contains expr var))
+	    (math-mul expr (math-add (math-div (math-sub high low) (or step 1))
+				     1)))
+	   ((and step (not (math-equal-int step 1)))
+	    (if (math-negp step)
+		(math-sum-rec expr var high low (math-neg step))
+	      (let ((lo (math-simplify (math-div low step))))
+		(if (math-known-num-integerp lo)
+		    (math-sum-rec (math-normalize
+				   (math-expr-subst expr var
+						    (math-mul step var)))
+				  var lo (math-simplify (math-div high step)))
+		  (math-sum-rec (math-normalize
+				 (math-expr-subst expr var
+						  (math-add (math-mul step var)
+							    low)))
+				var 0
+				(math-simplify (math-div (math-sub high low)
+							 step)))))))
+	   ((memq (setq t1 (math-compare low high)) '(0 1))
+	    (if (eq t1 0)
+		(math-expr-subst expr var low)
+	      0))
+	   ((setq t1 (math-is-polynomial expr var 20))
+	    (let ((poly nil)
+		  (n 0))
+	      (while t1
+		(setq poly (math-poly-mix poly 1
+					  (math-sum-integer-power n) (car t1))
+		      n (1+ n)
+		      t1 (cdr t1)))
+	      (setq n (math-build-polynomial-expr poly high))
+	      (if (memq low '(0 1))
+		  n
+		(math-sub n (math-build-polynomial-expr poly
+							(math-sub low 1))))))
+	   ((and (memq (car expr) '(+ -))
+		 (setq t1 (math-sum-rec (nth 1 expr) var low high)
+		       t2 (math-sum-rec (nth 2 expr) var low high))
+		 (not (and (math-expr-calls t1 '(calcFunc-sum))
+			   (math-expr-calls t2 '(calcFunc-sum)))))
+	    (list (car expr) t1 t2))
+	   ((and (eq (car expr) '*)
+		 (setq t1 (math-sum-const-factors expr var)))
+	    (math-mul (car t1) (math-sum-rec (cdr t1) var low high)))
+	   ((and (eq (car expr) '*) (memq (car-safe (nth 1 expr)) '(+ -)))
+	    (math-sum-rec (math-add-or-sub (math-mul (nth 1 (nth 1 expr))
+						     (nth 2 expr))
+					   (math-mul (nth 2 (nth 1 expr))
+						     (nth 2 expr))
+					   nil (eq (car (nth 1 expr)) '-))
+			  var low high))
+	   ((and (eq (car expr) '*) (memq (car-safe (nth 2 expr)) '(+ -)))
+	    (math-sum-rec (math-add-or-sub (math-mul (nth 1 expr)
+						     (nth 1 (nth 2 expr)))
+					   (math-mul (nth 1 expr)
+						     (nth 2 (nth 2 expr)))
+					   nil (eq (car (nth 2 expr)) '-))
+			  var low high))
+	   ((and (eq (car expr) '/)
+		 (not (math-primp (nth 1 expr)))
+		 (setq t1 (math-sum-const-factors (nth 1 expr) var)))
+	    (math-mul (car t1)
+		      (math-sum-rec (math-div (cdr t1) (nth 2 expr))
+				    var low high)))
+	   ((and (eq (car expr) '/)
+		 (setq t1 (math-sum-const-factors (nth 2 expr) var)))
+	    (math-div (math-sum-rec (math-div (nth 1 expr) (cdr t1))
+				    var low high)
+		      (car t1)))
+	   ((eq (car expr) 'neg)
+	    (math-neg (math-sum-rec (nth 1 expr) var low high)))
+	   ((and (eq (car expr) '^)
+		 (not (math-expr-contains (nth 1 expr) var))
+		 (setq t1 (math-is-polynomial (nth 2 expr) var 1)))
+	    (let ((x (math-pow (nth 1 expr) (nth 1 t1))))
+	      (math-div (math-mul (math-sub (math-pow x (math-add 1 high))
+					    (math-pow x low))
+				  (math-pow (nth 1 expr) (car t1)))
+			(math-sub x 1))))
+	   ((and (setq t1 (math-to-exponentials expr))
+		 (setq t1 (math-sum-rec t1 var low high))
+		 (not (math-expr-calls t1 '(calcFunc-sum))))
+	    (math-to-exps t1))
+	   ((memq (car expr) '(calcFunc-ln calcFunc-log10))
+	    (list (car expr) (calcFunc-prod (nth 1 expr) var low high)))
+	   ((and (eq (car expr) 'calcFunc-log)
+		 (= (length expr) 3)
+		 (not (math-expr-contains (nth 2 expr) var)))
+	    (list 'calcFunc-log
+		  (calcFunc-prod (nth 1 expr) var low high)
+		  (nth 2 expr)))))
+    (if (equal val '(var nan var-nan)) (setq val nil))
+    (or val
+	(let* ((math-tabulate-initial 0)
+	       (math-tabulate-function 'calcFunc-sum))
+	  (calcFunc-table expr var low high))))
+)
+
+(defun calcFunc-asum (expr var low &optional high step no-mul-flag)
+  (or high (setq high low low 1))
+  (if (and step (not (math-equal-int step 1)))
+      (if (math-negp step)
+	  (math-mul (math-pow -1 low)
+		    (calcFunc-asum expr var high low (math-neg step) t))
+	(let ((lo (math-simplify (math-div low step))))
+	  (if (math-num-integerp lo)
+	      (calcFunc-asum (math-normalize
+			      (math-expr-subst expr var
+					       (math-mul step var)))
+			     var lo (math-simplify (math-div high step)))
+	    (calcFunc-asum (math-normalize
+			    (math-expr-subst expr var
+					     (math-add (math-mul step var)
+						       low)))
+			   var 0
+			   (math-simplify (math-div (math-sub high low)
+						    step))))))
+    (math-mul (if no-mul-flag 1 (math-pow -1 low))
+	      (calcFunc-sum (math-mul (math-pow -1 var) expr) var low high)))
+)
+
+(defun math-sum-const-factors (expr var)
+  (let ((const nil)
+	(not-const nil)
+	(p expr))
+    (while (eq (car-safe p) '*)
+      (if (math-expr-contains (nth 1 p) var)
+	  (setq not-const (cons (nth 1 p) not-const))
+	(setq const (cons (nth 1 p) const)))
+      (setq p (nth 2 p)))
+    (if (math-expr-contains p var)
+	(setq not-const (cons p not-const))
+      (setq const (cons p const)))
+    (and const
+	 (cons (let ((temp (car const)))
+		 (while (setq const (cdr const))
+		   (setq temp (list '* (car const) temp)))
+		 temp)
+	       (let ((temp (or (car not-const) 1)))
+		 (while (setq not-const (cdr not-const))
+		   (setq temp (list '* (car not-const) temp)))
+		 temp))))
+)
+
+;; Following is from CRC Math Tables, 27th ed, pp. 52-53.
+(defun math-sum-integer-power (pow)
+  (let ((calc-prefer-frac t)
+	(n (length math-sum-int-pow-cache)))
+    (while (<= n pow)
+      (let* ((new (list 0 0))
+	     (lin new)
+	     (pp (cdr (nth (1- n) math-sum-int-pow-cache)))
+	     (p 2)
+	     (sum 0)
+	     q)
+	(while pp
+	  (setq q (math-div (car pp) p)
+		new (cons (math-mul q n) new)
+		sum (math-add sum q)
+		p (1+ p)
+		pp (cdr pp)))
+	(setcar lin (math-sub 1 (math-mul n sum)))
+	(setq math-sum-int-pow-cache
+	      (nconc math-sum-int-pow-cache (list (nreverse new)))
+	      n (1+ n))))
+    (nth pow math-sum-int-pow-cache))
+)
+(setq math-sum-int-pow-cache (list '(0 1)))
+
+(defun math-to-exponentials (expr)
+  (and (consp expr)
+       (= (length expr) 2)
+       (let ((x (nth 1 expr))
+	     (pi (if calc-symbolic-mode '(var pi var-pi) (math-pi)))
+	     (i (if calc-symbolic-mode '(var i var-i) '(cplx 0 1))))
+	 (cond ((eq (car expr) 'calcFunc-exp)
+		(list '^ '(var e var-e) x))
+	       ((eq (car expr) 'calcFunc-sin)
+		(or (eq calc-angle-mode 'rad)
+		    (setq x (list '/ (list '* x pi) 180)))
+		(list '/ (list '-
+			       (list '^ '(var e var-e) (list '* x i))
+			       (list '^ '(var e var-e)
+				     (list 'neg (list '* x i))))
+		      (list '* 2 i)))
+	       ((eq (car expr) 'calcFunc-cos)
+		(or (eq calc-angle-mode 'rad)
+		    (setq x (list '/ (list '* x pi) 180)))
+		(list '/ (list '+
+			       (list '^ '(var e var-e)
+				     (list '* x i))
+			       (list '^ '(var e var-e)
+				     (list 'neg (list '* x i))))
+		      2))
+	       ((eq (car expr) 'calcFunc-sinh)
+		(list '/ (list '-
+			       (list '^ '(var e var-e) x)
+			       (list '^ '(var e var-e) (list 'neg x)))
+		      2))
+	       ((eq (car expr) 'calcFunc-cosh)
+		(list '/ (list '+
+			       (list '^ '(var e var-e) x)
+			       (list '^ '(var e var-e) (list 'neg x)))
+		      2))
+	       (t nil))))
+)
+
+(defun math-to-exps (expr)
+  (cond (calc-symbolic-mode expr)
+	((Math-primp expr)
+	 (if (equal expr '(var e var-e)) (math-e) expr))
+	((and (eq (car expr) '^)
+	      (equal (nth 1 expr) '(var e var-e)))
+	 (list 'calcFunc-exp (nth 2 expr)))
+	(t
+	 (cons (car expr) (mapcar 'math-to-exps (cdr expr)))))
+)
+
+
+(defun calcFunc-prod (expr var &optional low high step)
+  (if math-disable-prods (math-reject-arg))
+  (let* ((res (let* ((calc-internal-prec (+ calc-internal-prec 2)))
+		(math-prod-rec expr var low high step)))
+	 (math-disable-prods t))
+    (math-normalize res))
+)
+(setq math-disable-prods nil)
+
+(defun math-prod-rec (expr var &optional low high step)
+  (or low (setq low '(neg (var inf var-inf)) high '(var inf var-inf)))
+  (and low (not high) (setq high '(var inf var-inf)))
+  (let (t1 t2 t3 val)
+    (setq val
+	  (cond
+	   ((not (math-expr-contains expr var))
+	    (math-pow expr (math-add (math-div (math-sub high low) (or step 1))
+				     1)))
+	   ((and step (not (math-equal-int step 1)))
+	    (if (math-negp step)
+		(math-prod-rec expr var high low (math-neg step))
+	      (let ((lo (math-simplify (math-div low step))))
+		(if (math-known-num-integerp lo)
+		    (math-prod-rec (math-normalize
+				    (math-expr-subst expr var
+						     (math-mul step var)))
+				   var lo (math-simplify (math-div high step)))
+		  (math-prod-rec (math-normalize
+				  (math-expr-subst expr var
+						   (math-add (math-mul step
+								       var)
+							     low)))
+				 var 0
+				 (math-simplify (math-div (math-sub high low)
+							  step)))))))
+	   ((and (memq (car expr) '(* /))
+		 (setq t1 (math-prod-rec (nth 1 expr) var low high)
+		       t2 (math-prod-rec (nth 2 expr) var low high))
+		 (not (and (math-expr-calls t1 '(calcFunc-prod))
+			   (math-expr-calls t2 '(calcFunc-prod)))))
+	    (list (car expr) t1 t2))
+	   ((and (eq (car expr) '^)
+		 (not (math-expr-contains (nth 2 expr) var)))
+	    (math-pow (math-prod-rec (nth 1 expr) var low high)
+		      (nth 2 expr)))
+	   ((and (eq (car expr) '^)
+		 (not (math-expr-contains (nth 1 expr) var)))
+	    (math-pow (nth 1 expr)
+		      (calcFunc-sum (nth 2 expr) var low high)))
+	   ((eq (car expr) 'sqrt)
+	    (math-normalize (list 'calcFunc-sqrt
+				  (list 'calcFunc-prod (nth 1 expr)
+					var low high))))
+	   ((eq (car expr) 'neg)
+	    (math-mul (math-pow -1 (math-add (math-sub high low) 1))
+		      (math-prod-rec (nth 1 expr) var low high)))
+	   ((eq (car expr) 'calcFunc-exp)
+	    (list 'calcFunc-exp (calcFunc-sum (nth 1 expr) var low high)))
+	   ((and (setq t1 (math-is-polynomial expr var 1))
+		 (setq t2
+		       (cond
+			((or (and (math-equal-int (nth 1 t1) 1)
+				  (setq low (math-simplify
+					     (math-add low (car t1)))
+					high (math-simplify
+					      (math-add high (car t1)))))
+			     (and (math-equal-int (nth 1 t1) -1)
+				  (setq t2 low
+					low (math-simplify
+					     (math-sub (car t1) high))
+					high (math-simplify
+					      (math-sub (car t1) t2)))))
+			 (if (or (math-zerop low) (math-zerop high))
+			     0
+			   (if (and (or (math-negp low) (math-negp high))
+				    (or (math-num-integerp low)
+					(math-num-integerp high)))
+			       (if (math-posp high)
+				   0
+				 (math-mul (math-pow -1
+						     (math-add
+						      (math-add low high) 1))
+					   (list '/
+						 (list 'calcFunc-fact
+						       (math-neg low))
+						 (list 'calcFunc-fact
+						       (math-sub -1 high)))))
+			     (list '/
+				   (list 'calcFunc-fact high)
+				   (list 'calcFunc-fact (math-sub low 1))))))
+			((and (or (and (math-equal-int (nth 1 t1) 2)
+				       (setq t2 (math-simplify
+						 (math-add (math-mul low 2)
+							   (car t1)))
+					     t3 (math-simplify
+						 (math-add (math-mul high 2)
+							   (car t1)))))
+				  (and (math-equal-int (nth 1 t1) -2)
+				       (setq t2 (math-simplify
+						 (math-sub (car t1)
+							   (math-mul high 2)))
+					     t3 (math-simplify 
+						 (math-sub (car t1)
+							   (math-mul low
+								     2))))))
+			      (or (math-integerp t2)
+				  (and (math-messy-integerp t2)
+				       (setq t2 (math-trunc t2)))
+				  (math-integerp t3)
+				  (and (math-messy-integerp t3)
+				       (setq t3 (math-trunc t3)))))
+			 (if (or (math-zerop t2) (math-zerop t3))
+			     0
+			   (if (or (math-evenp t2) (math-evenp t3))
+			       (if (or (math-negp t2) (math-negp t3))
+				   (if (math-posp high)
+				       0
+				     (list '/
+					   (list 'calcFunc-dfact
+						 (math-neg t2))
+					   (list 'calcFunc-dfact
+						 (math-sub -2 t3))))
+				 (list '/
+				       (list 'calcFunc-dfact t3)
+				       (list 'calcFunc-dfact
+					     (math-sub t2 2))))
+			     (if (math-negp t3)
+				 (list '*
+				       (list '^ -1
+					     (list '/ (list '- (list '- t2 t3)
+							    2)
+						   2))
+				       (list '/
+					     (list 'calcFunc-dfact
+						   (math-neg t2))
+					     (list 'calcFunc-dfact
+						   (math-sub -2 t3))))
+			       (if (math-posp t2)
+				   (list '/
+					 (list 'calcFunc-dfact t3)
+					 (list 'calcFunc-dfact
+					       (math-sub t2 2)))
+				 nil))))))))
+	    t2)))
+    (if (equal val '(var nan var-nan)) (setq val nil))
+    (or val
+	(let* ((math-tabulate-initial 1)
+	       (math-tabulate-function 'calcFunc-prod))
+	  (calcFunc-table expr var low high))))
+)
+
+
+
+
+;;; Attempt to reduce lhs = rhs to solve-var = rhs', where solve-var appears
+;;; in lhs but not in rhs or rhs'; return rhs'.
+;;; Uses global values: solve-*.
+(defun math-try-solve-for (lhs rhs &optional sign no-poly)
+  (let (t1 t2 t3)
+    (cond ((equal lhs solve-var)
+	   (setq math-solve-sign sign)
+	   (if (eq solve-full 'all)
+	       (let ((vec (list 'vec (math-evaluate-expr rhs)))
+		     newvec var p)
+		 (while math-solve-ranges
+		   (setq p (car math-solve-ranges)
+			 var (car p)
+			 newvec (list 'vec))
+		   (while (setq p (cdr p))
+		     (setq newvec (nconc newvec
+					 (cdr (math-expr-subst
+					       vec var (car p))))))
+		   (setq vec newvec
+			 math-solve-ranges (cdr math-solve-ranges)))
+		 (math-normalize vec))
+	     rhs))
+	  ((Math-primp lhs)
+	   nil)
+	  ((and (eq (car lhs) '-)
+		(eq (car-safe (nth 1 lhs)) (car-safe (nth 2 lhs)))
+		(Math-zerop rhs)
+		(= (length (nth 1 lhs)) 2)
+		(= (length (nth 2 lhs)) 2)
+		(setq t1 (get (car (nth 1 lhs)) 'math-inverse))
+		(setq t2 (funcall t1 '(var SOLVEDUM SOLVEDUM)))
+		(eq (math-expr-contains-count t2 '(var SOLVEDUM SOLVEDUM)) 1)
+		(setq t3 (math-solve-above-dummy t2))
+		(setq t1 (math-try-solve-for (math-sub (nth 1 (nth 1 lhs))
+						       (math-expr-subst
+							t2 t3
+							(nth 1 (nth 2 lhs))))
+					     0)))
+	   t1)
+	  ((eq (car lhs) 'neg)
+	   (math-try-solve-for (nth 1 lhs) (math-neg rhs)
+			       (and sign (- sign))))
+	  ((and (not (eq solve-full 't)) (math-try-solve-prod)))
+	  ((and (not no-poly)
+		(setq t2 (math-decompose-poly lhs solve-var 15 rhs)))
+	   (setq t1 (cdr (nth 1 t2))
+		 t1 (let ((math-solve-ranges math-solve-ranges))
+		      (cond ((= (length t1) 5)
+			     (apply 'math-solve-quartic (car t2) t1))
+			    ((= (length t1) 4)
+			     (apply 'math-solve-cubic (car t2) t1))
+			    ((= (length t1) 3)
+			     (apply 'math-solve-quadratic (car t2) t1))
+			    ((= (length t1) 2)
+			     (apply 'math-solve-linear (car t2) sign t1))
+			    (solve-full
+			     (math-poly-all-roots (car t2) t1))
+			    (calc-symbolic-mode nil)
+			    (t
+			     (math-try-solve-for
+			      (car t2)
+			      (math-poly-any-root (reverse t1) 0 t)
+			      nil t)))))
+	   (if t1
+	       (if (eq (nth 2 t2) 1)
+		   t1
+		 (math-solve-prod t1 (math-try-solve-for (nth 2 t2) 0 nil t)))
+	     (calc-record-why "*Unable to find a symbolic solution")
+	     nil))
+	  ((and (math-solve-find-root-term lhs nil)
+		(eq (math-expr-contains-count lhs t1) 1))   ; just in case
+	   (math-try-solve-for (math-simplify
+				(math-sub (if (or t3 (math-evenp t2))
+					      (math-pow t1 t2)
+					    (math-neg (math-pow t1 t2)))
+					  (math-expand-power
+					   (math-sub (math-normalize
+						      (math-expr-subst
+						       lhs t1 0))
+						     rhs)
+					   t2 solve-var)))
+			       0))
+	  ((eq (car lhs) '+)
+	   (cond ((not (math-expr-contains (nth 1 lhs) solve-var))
+		  (math-try-solve-for (nth 2 lhs)
+				      (math-sub rhs (nth 1 lhs))
+				      sign))
+		 ((not (math-expr-contains (nth 2 lhs) solve-var))
+		  (math-try-solve-for (nth 1 lhs)
+				      (math-sub rhs (nth 2 lhs))
+				      sign))))
+	  ((eq (car lhs) 'calcFunc-eq)
+	   (math-try-solve-for (math-sub (nth 1 lhs) (nth 2 lhs))
+			       rhs sign no-poly))
+	  ((eq (car lhs) '-)
+	   (cond ((or (and (eq (car-safe (nth 1 lhs)) 'calcFunc-sin)
+			   (eq (car-safe (nth 2 lhs)) 'calcFunc-cos))
+		      (and (eq (car-safe (nth 1 lhs)) 'calcFunc-cos)
+			   (eq (car-safe (nth 2 lhs)) 'calcFunc-sin)))
+		  (math-try-solve-for (math-sub (nth 1 lhs)
+						(list (car (nth 1 lhs))
+						      (math-sub
+						       (math-quarter-circle t)
+						       (nth 1 (nth 2 lhs)))))
+				      rhs))
+		 ((not (math-expr-contains (nth 1 lhs) solve-var))
+		  (math-try-solve-for (nth 2 lhs)
+				      (math-sub (nth 1 lhs) rhs)
+				      (and sign (- sign))))
+		 ((not (math-expr-contains (nth 2 lhs) solve-var))
+		  (math-try-solve-for (nth 1 lhs)
+				      (math-add rhs (nth 2 lhs))
+				      sign))))
+	  ((and (eq solve-full 't) (math-try-solve-prod)))
+	  ((and (eq (car lhs) '%)
+		(not (math-expr-contains (nth 2 lhs) solve-var)))
+	   (math-try-solve-for (nth 1 lhs) (math-add rhs
+						     (math-solve-get-int
+						      (nth 2 lhs)))))
+	  ((eq (car lhs) 'calcFunc-log)
+	   (cond ((not (math-expr-contains (nth 2 lhs) solve-var))
+		  (math-try-solve-for (nth 1 lhs) (math-pow (nth 2 lhs) rhs)))
+		 ((not (math-expr-contains (nth 1 lhs) solve-var))
+		  (math-try-solve-for (nth 2 lhs) (math-pow
+						   (nth 1 lhs)
+						   (math-div 1 rhs))))))
+	  ((and (= (length lhs) 2)
+		(symbolp (car lhs))
+		(setq t1 (get (car lhs) 'math-inverse))
+		(setq t2 (funcall t1 rhs)))
+	   (setq t1 (get (car lhs) 'math-inverse-sign))
+	   (math-try-solve-for (nth 1 lhs) (math-normalize t2)
+			       (and sign t1
+				    (if (integerp t1)
+					(* t1 sign)
+				      (funcall t1 lhs sign)))))
+	  ((and (symbolp (car lhs))
+		(setq t1 (get (car lhs) 'math-inverse-n))
+		(setq t2 (funcall t1 lhs rhs)))
+	   t2)
+	  ((setq t1 (math-expand-formula lhs))
+	   (math-try-solve-for t1 rhs sign))
+	  (t
+	   (calc-record-why "*No inverse known" lhs)
+	   nil)))
+)
+
+(setq math-solve-ranges nil)
+
+(defun math-try-solve-prod ()
+  (cond ((eq (car lhs) '*)
+	 (cond ((not (math-expr-contains (nth 1 lhs) solve-var))
+		(math-try-solve-for (nth 2 lhs)
+				    (math-div rhs (nth 1 lhs))
+				    (math-solve-sign sign (nth 1 lhs))))
+	       ((not (math-expr-contains (nth 2 lhs) solve-var))
+		(math-try-solve-for (nth 1 lhs)
+				    (math-div rhs (nth 2 lhs))
+				    (math-solve-sign sign (nth 2 lhs))))
+	       ((Math-zerop rhs)
+		(math-solve-prod (let ((math-solve-ranges math-solve-ranges))
+				   (math-try-solve-for (nth 2 lhs) 0))
+				 (math-try-solve-for (nth 1 lhs) 0)))))
+	((eq (car lhs) '/)
+	 (cond ((not (math-expr-contains (nth 1 lhs) solve-var))
+		(math-try-solve-for (nth 2 lhs)
+				    (math-div (nth 1 lhs) rhs)
+				    (math-solve-sign sign (nth 1 lhs))))
+	       ((not (math-expr-contains (nth 2 lhs) solve-var))
+		(math-try-solve-for (nth 1 lhs)
+				    (math-mul rhs (nth 2 lhs))
+				    (math-solve-sign sign (nth 2 lhs))))
+	       ((setq t1 (math-try-solve-for (math-sub (nth 1 lhs)
+						       (math-mul (nth 2 lhs)
+								 rhs))
+					     0))
+		t1)))
+	((eq (car lhs) '^)
+	 (cond ((not (math-expr-contains (nth 1 lhs) solve-var))
+		(math-try-solve-for
+		 (nth 2 lhs)
+		 (math-add (math-normalize
+			    (list 'calcFunc-log rhs (nth 1 lhs)))
+			   (math-div
+			    (math-mul 2
+				      (math-mul '(var pi var-pi)
+						(math-solve-get-int
+						 '(var i var-i))))
+			    (math-normalize
+			     (list 'calcFunc-ln (nth 1 lhs)))))))
+	       ((not (math-expr-contains (nth 2 lhs) solve-var))
+		(cond ((and (integerp (nth 2 lhs))
+			    (>= (nth 2 lhs) 2)
+			    (setq t1 (math-integer-log2 (nth 2 lhs))))
+		       (setq t2 rhs)
+		       (if (and (eq solve-full t)
+				(math-known-realp (nth 1 lhs)))
+			   (progn
+			     (while (>= (setq t1 (1- t1)) 0)
+			       (setq t2 (list 'calcFunc-sqrt t2)))
+			     (setq t2 (math-solve-get-sign t2)))
+			 (while (>= (setq t1 (1- t1)) 0)
+			   (setq t2 (math-solve-get-sign
+				     (math-normalize
+				      (list 'calcFunc-sqrt t2))))))
+		       (math-try-solve-for
+			(nth 1 lhs)
+			(math-normalize t2)))
+		      ((math-looks-negp (nth 2 lhs))
+		       (math-try-solve-for
+			(list '^ (nth 1 lhs) (math-neg (nth 2 lhs)))
+			(math-div 1 rhs)))
+		      ((and (eq solve-full t)
+			    (Math-integerp (nth 2 lhs))
+			    (math-known-realp (nth 1 lhs)))
+		       (setq t1 (math-normalize
+				 (list 'calcFunc-nroot rhs (nth 2 lhs))))
+		       (if (math-evenp (nth 2 lhs))
+			   (setq t1 (math-solve-get-sign t1)))
+		       (math-try-solve-for
+			(nth 1 lhs) t1
+			(and sign
+			     (math-oddp (nth 2 lhs))
+			     (math-solve-sign sign (nth 2 lhs)))))
+		      (t (math-try-solve-for
+			  (nth 1 lhs)
+			  (math-mul
+			   (math-normalize
+			    (list 'calcFunc-exp
+				  (if (Math-realp (nth 2 lhs))
+				      (math-div (math-mul
+						 '(var pi var-pi)
+						 (math-solve-get-int
+						  '(var i var-i)
+						  (and (integerp (nth 2 lhs))
+						       (math-abs
+							(nth 2 lhs)))))
+						(math-div (nth 2 lhs) 2))
+				    (math-div (math-mul
+					       2
+					       (math-mul
+						'(var pi var-pi)
+						(math-solve-get-int
+						 '(var i var-i)
+						 (and (integerp (nth 2 lhs))
+						      (math-abs
+						       (nth 2 lhs))))))
+					      (nth 2 lhs)))))
+			   (math-normalize
+			    (list 'calcFunc-nroot
+				  rhs
+				  (nth 2 lhs))))
+			  (and sign
+			       (math-oddp (nth 2 lhs))
+			       (math-solve-sign sign (nth 2 lhs)))))))))
+	(t nil))
+)
+
+(defun math-solve-prod (lsoln rsoln)
+  (cond ((null lsoln)
+	 rsoln)
+	((null rsoln)
+	 lsoln)
+	((eq solve-full 'all)
+	 (cons 'vec (append (cdr lsoln) (cdr rsoln))))
+	(solve-full
+	 (list 'calcFunc-if
+	       (list 'calcFunc-gt (math-solve-get-sign 1) 0)
+	       lsoln
+	       rsoln))
+	(t lsoln))
+)
+
+;;; This deals with negative, fractional, and symbolic powers of "x".
+(defun math-solve-poly-funny-powers (sub-rhs)    ; uses "t1", "t2"
+  (setq t1 lhs)
+  (let ((pp math-poly-neg-powers)
+	fac)
+    (while pp
+      (setq fac (math-pow (car pp) (or math-poly-mult-powers 1))
+	    t1 (math-mul t1 fac)
+	    rhs (math-mul rhs fac)
+	    pp (cdr pp))))
+  (if sub-rhs (setq t1 (math-sub t1 rhs)))
+  (let ((math-poly-neg-powers nil))
+    (setq t2 (math-mul (or math-poly-mult-powers 1)
+		       (let ((calc-prefer-frac t))
+			 (math-div 1 math-poly-frac-powers)))
+	  t1 (math-is-polynomial (math-simplify (calcFunc-expand t1)) b 50)))
+)
+
+;;; This converts "a x^8 + b x^5 + c x^2" to "(a (x^3)^2 + b (x^3) + c) * x^2".
+(defun math-solve-crunch-poly (max-degree)   ; uses "t1", "t3"
+  (let ((count 0))
+    (while (and t1 (Math-zerop (car t1)))
+      (setq t1 (cdr t1)
+	    count (1+ count)))
+    (and t1
+	 (let* ((degree (1- (length t1)))
+		(scale degree))
+	   (while (and (> scale 1) (= (car t3) 1))
+	     (and (= (% degree scale) 0)
+		  (let ((p t1)
+			(n 0)
+			(new-t1 nil)
+			(okay t))
+		    (while (and p okay)
+		      (if (= (% n scale) 0)
+			  (setq new-t1 (nconc new-t1 (list (car p))))
+			(or (Math-zerop (car p))
+			    (setq okay nil)))
+		      (setq p (cdr p)
+			    n (1+ n)))
+		    (if okay
+			(setq t3 (cons scale (cdr t3))
+			      t1 new-t1))))
+	     (setq scale (1- scale)))
+	   (setq t3 (list (math-mul (car t3) t2) (math-mul count t2)))
+	   (<= (1- (length t1)) max-degree))))
+)
+
+(defun calcFunc-poly (expr var &optional degree)
+  (if degree
+      (or (natnump degree) (math-reject-arg degree 'fixnatnump))
+    (setq degree 50))
+  (let ((p (math-is-polynomial expr var degree 'gen)))
+    (if p
+	(if (equal p '(0))
+	    (list 'vec)
+	  (cons 'vec p))
+      (math-reject-arg expr "Expected a polynomial")))
+)
+
+(defun calcFunc-gpoly (expr var &optional degree)
+  (if degree
+      (or (natnump degree) (math-reject-arg degree 'fixnatnump))
+    (setq degree 50))
+  (let* ((math-poly-base-variable var)
+	 (d (math-decompose-poly expr var degree nil)))
+    (if d
+	(cons 'vec d)
+      (math-reject-arg expr "Expected a polynomial")))
+)
+
+(defun math-decompose-poly (lhs solve-var degree sub-rhs)
+  (let ((rhs (or sub-rhs 1))
+	t1 t2 t3)
+    (setq t2 (math-polynomial-base
+	      lhs
+	      (function
+	       (lambda (b)
+		 (let ((math-poly-neg-powers '(1))
+		       (math-poly-mult-powers nil)
+		       (math-poly-frac-powers 1)
+		       (math-poly-exp-base t))
+		   (and (not (equal b lhs))
+			(or (not (memq (car-safe b) '(+ -))) sub-rhs)
+			(setq t3 '(1 0) t2 1
+			      t1 (math-is-polynomial lhs b 50))
+			(if (and (equal math-poly-neg-powers '(1))
+				 (memq math-poly-mult-powers '(nil 1))
+				 (eq math-poly-frac-powers 1)
+				 sub-rhs)
+			    (setq t1 (cons (math-sub (car t1) rhs)
+					   (cdr t1)))
+			  (math-solve-poly-funny-powers sub-rhs))
+			(math-solve-crunch-poly degree)
+			(or (math-expr-contains b solve-var)
+			    (math-expr-contains (car t3) solve-var))))))))
+    (if t2
+	(list (math-pow t2 (car t3))
+	      (cons 'vec t1)
+	      (if sub-rhs
+		  (math-pow t2 (nth 1 t3))
+		(math-div (math-pow t2 (nth 1 t3)) rhs)))))
+)
+
+(defun math-solve-linear (var sign b a)
+  (math-try-solve-for var
+		      (math-div (math-neg b) a)
+		      (math-solve-sign sign a)
+		      t)
+)
+
+(defun math-solve-quadratic (var c b a)
+  (math-try-solve-for
+   var
+   (if (math-looks-evenp b)
+       (let ((halfb (math-div b 2)))
+	 (math-div
+	  (math-add
+	   (math-neg halfb)
+	   (math-solve-get-sign
+	    (math-normalize
+	     (list 'calcFunc-sqrt
+		   (math-add (math-sqr halfb)
+			     (math-mul (math-neg c) a))))))
+	  a))
+     (math-div
+      (math-add
+       (math-neg b)
+       (math-solve-get-sign
+	(math-normalize
+	 (list 'calcFunc-sqrt
+	       (math-add (math-sqr b)
+			 (math-mul 4 (math-mul (math-neg c) a)))))))
+      (math-mul 2 a)))
+   nil t)
+)
+
+(defun math-solve-cubic (var d c b a)
+  (let* ((p (math-div b a))
+	 (q (math-div c a))
+	 (r (math-div d a))
+	 (psqr (math-sqr p))
+	 (aa (math-sub q (math-div psqr 3)))
+	 (bb (math-add r
+		       (math-div (math-sub (math-mul 2 (math-mul psqr p))
+					   (math-mul 9 (math-mul p q)))
+				 27)))
+	 m)
+    (if (Math-zerop aa)
+	(math-try-solve-for (math-pow (math-add var (math-div p 3)) 3)
+			    (math-neg bb) nil t)
+      (if (Math-zerop bb)
+	  (math-try-solve-for
+	   (math-mul (math-add var (math-div p 3))
+		     (math-add (math-sqr (math-add var (math-div p 3)))
+			       aa))
+	   0 nil t)
+	(setq m (math-mul 2 (list 'calcFunc-sqrt (math-div aa -3))))
+	(math-try-solve-for
+	 var
+	 (math-sub
+	  (math-normalize
+	   (math-mul
+	    m
+	    (list 'calcFunc-cos
+		  (math-div
+		   (math-sub (list 'calcFunc-arccos
+				   (math-div (math-mul 3 bb)
+					     (math-mul aa m)))
+			     (math-mul 2
+				       (math-mul
+					(math-add 1 (math-solve-get-int
+						     1 3))
+					(math-half-circle
+					 calc-symbolic-mode))))
+		   3))))
+	  (math-div p 3))
+	 nil t))))
+)
+
+(defun math-solve-quartic (var d c b a aa)
+  (setq a (math-div a aa))
+  (setq b (math-div b aa))
+  (setq c (math-div c aa))
+  (setq d (math-div d aa))
+  (math-try-solve-for
+   var
+   (let* ((asqr (math-sqr a))
+	  (asqr4 (math-div asqr 4))
+	  (y (let ((solve-full nil)
+		   calc-next-why)
+	       (math-solve-cubic solve-var
+				 (math-sub (math-sub
+					    (math-mul 4 (math-mul b d))
+					    (math-mul asqr d))
+					   (math-sqr c))
+				 (math-sub (math-mul a c)
+					   (math-mul 4 d))
+				 (math-neg b)
+				 1)))
+	  (rsqr (math-add (math-sub asqr4 b) y))
+	  (r (list 'calcFunc-sqrt rsqr))
+	  (sign1 (math-solve-get-sign 1))
+	  (de (list 'calcFunc-sqrt
+		    (math-add
+		     (math-sub (math-mul 3 asqr4)
+			       (math-mul 2 b))
+		     (if (Math-zerop rsqr)
+			 (math-mul
+			  2
+			  (math-mul sign1
+				    (list 'calcFunc-sqrt
+					  (math-sub (math-sqr y)
+						    (math-mul 4 d)))))
+		       (math-sub
+			(math-mul sign1
+				  (math-div
+				   (math-sub (math-sub
+					      (math-mul 4 (math-mul a b))
+					      (math-mul 8 c))
+					     (math-mul asqr a))
+				   (math-mul 4 r)))
+			rsqr))))))
+     (math-normalize
+      (math-sub (math-add (math-mul sign1 (math-div r 2))
+			  (math-solve-get-sign (math-div de 2)))
+		(math-div a 4))))
+   nil t)
+)
+
+(defun math-poly-all-roots (var p &optional math-factoring)
+  (catch 'ouch
+    (let* ((math-symbolic-solve calc-symbolic-mode)
+	   (roots nil)
+	   (deg (1- (length p)))
+	   (orig-p (reverse p))
+	   (math-int-coefs nil)
+	   (math-int-scale nil)
+	   (math-double-roots nil)
+	   (math-int-factors nil)
+	   (math-int-threshold nil)
+	   (pp p))
+      ;; If rational coefficients, look for exact rational factors.
+      (while (and pp (Math-ratp (car pp)))
+	(setq pp (cdr pp)))
+      (if pp
+	  (if (or math-factoring math-symbolic-solve)
+	      (throw 'ouch nil))
+	(let ((lead (car orig-p))
+	      (calc-prefer-frac t)
+	      (scale (apply 'math-lcm-denoms p)))
+	  (setq math-int-scale (math-abs (math-mul scale lead))
+		math-int-threshold (math-div '(float 5 -2) math-int-scale)
+		math-int-coefs (cdr (math-div (cons 'vec orig-p) lead)))))
+      (if (> deg 4)
+	  (let ((calc-prefer-frac nil)
+		(calc-symbolic-mode nil)
+		(pp p)
+		(def-p (copy-sequence orig-p)))
+	    (while pp
+	      (if (Math-numberp (car pp))
+		  (setq pp (cdr pp))
+		(throw 'ouch nil)))
+	    (while (> deg (if math-symbolic-solve 2 4))
+	      (let* ((x (math-poly-any-root def-p '(float 0 0) nil))
+		     b c pp)
+		(if (and (eq (car-safe x) 'cplx)
+			 (math-nearly-zerop (nth 2 x) (nth 1 x)))
+		    (setq x (calcFunc-re x)))
+		(or math-factoring
+		    (setq roots (cons x roots)))
+		(or (math-numberp x)
+		    (setq x (math-evaluate-expr x)))
+		(setq pp def-p
+		      b (car def-p))
+		(while (setq pp (cdr pp))
+		  (setq c (car pp))
+		  (setcar pp b)
+		  (setq b (math-add (math-mul x b) c)))
+		(setq def-p (cdr def-p)
+		      deg (1- deg))))
+	    (setq p (reverse def-p))))
+      (if (> deg 1)
+	  (let ((solve-var '(var DUMMY var-DUMMY))
+		(math-solve-sign nil)
+		(math-solve-ranges nil)
+		(solve-full 'all))
+	    (if (= (length p) (length math-int-coefs))
+		(setq p (reverse math-int-coefs)))
+	    (setq roots (append (cdr (apply (cond ((= deg 2)
+						   'math-solve-quadratic)
+						  ((= deg 3)
+						   'math-solve-cubic)
+						  (t
+						   'math-solve-quartic))
+					    solve-var p))
+				roots)))
+	(if (> deg 0)
+	    (setq roots (cons (math-div (math-neg (car p)) (nth 1 p))
+			      roots))))
+      (if math-factoring
+	  (progn
+	    (while roots
+	      (math-poly-integer-root (car roots))
+	      (setq roots (cdr roots)))
+	    (list math-int-factors (nreverse math-int-coefs) math-int-scale))
+	(let ((vec nil) res)
+	  (while roots
+	    (let ((root (car roots))
+		  (solve-full (and solve-full 'all)))
+	      (if (math-floatp root)
+		  (setq root (math-poly-any-root orig-p root t)))
+	      (setq vec (append vec
+				(cdr (or (math-try-solve-for var root nil t)
+					 (throw 'ouch nil))))))
+	    (setq roots (cdr roots)))
+	  (setq vec (cons 'vec (nreverse vec)))
+	  (if math-symbolic-solve
+	      (setq vec (math-normalize vec)))
+	  (if (eq solve-full t)
+	      (list 'calcFunc-subscr
+		    vec
+		    (math-solve-get-int 1 (1- (length orig-p)) 1))
+	    vec)))))
+)
+(setq math-symbolic-solve nil)
+
+(defun math-lcm-denoms (&rest fracs)
+  (let ((den 1))
+    (while fracs
+      (if (eq (car-safe (car fracs)) 'frac)
+	  (setq den (calcFunc-lcm den (nth 2 (car fracs)))))
+      (setq fracs (cdr fracs)))
+    den)
+)
+
+(defun math-poly-any-root (p x polish)    ; p is a reverse poly coeff list
+  (let* ((newt (if (math-zerop x)
+		   (math-poly-newton-root
+		    p '(cplx (float 123 -6) (float 1 -4)) 4)
+		 (math-poly-newton-root p x 4)))
+	 (res (if (math-zerop (cdr newt))
+		  (car newt)
+		(if (and (math-lessp (cdr newt) '(float 1 -3)) (not polish))
+		    (setq newt (math-poly-newton-root p (car newt) 30)))
+		(if (math-zerop (cdr newt))
+		    (car newt)
+		  (math-poly-laguerre-root p x polish)))))
+    (and math-symbolic-solve (math-floatp res)
+	 (throw 'ouch nil))
+    res)
+)
+
+(defun math-poly-newton-root (p x iters)
+  (let* ((calc-prefer-frac nil)
+	 (calc-symbolic-mode nil)
+	 (try-integer math-int-coefs)
+	 (dx x) b d)
+    (while (and (> (setq iters (1- iters)) 0)
+		(let ((pp p))
+		  (math-working "newton" x)
+		  (setq b (car p)
+			d 0)
+		  (while (setq pp (cdr pp))
+		    (setq d (math-add (math-mul x d) b)
+			  b (math-add (math-mul x b) (car pp))))
+		  (not (math-zerop d)))
+		(progn
+		  (setq dx (math-div b d)
+			x (math-sub x dx))
+		  (if try-integer
+		      (let ((adx (math-abs-approx dx)))
+			(and (math-lessp adx math-int-threshold)
+			     (let ((iroot (math-poly-integer-root x)))
+			       (if iroot
+				   (setq x iroot dx 0)
+				 (setq try-integer nil))))))
+		  (or (not (or (eq dx 0)
+			       (math-nearly-zerop dx (math-abs-approx x))))
+		      (progn (setq dx 0) nil)))))
+    (cons x (if (math-zerop x)
+		1 (math-div (math-abs-approx dx) (math-abs-approx x)))))
+)
+
+(defun math-poly-integer-root (x)
+  (and (math-lessp (calcFunc-xpon (math-abs-approx x)) calc-internal-prec)
+       math-int-coefs
+       (let* ((calc-prefer-frac t)
+	      (xre (calcFunc-re x))
+	      (xim (calcFunc-im x))
+	      (xresq (math-sqr xre))
+	      (ximsq (math-sqr xim)))
+	 (if (math-lessp ximsq (calcFunc-scf xresq -1))
+	     ;; Look for linear factor
+	     (let* ((rnd (math-div (math-round (math-mul xre math-int-scale))
+				   math-int-scale))
+		    (icp math-int-coefs)
+		    (rem (car icp))
+		    (newcoef nil))
+	       (while (setq icp (cdr icp))
+		 (setq newcoef (cons rem newcoef)
+		       rem (math-add (car icp)
+				     (math-mul rem rnd))))
+	       (and (math-zerop rem)
+		    (progn
+		      (setq math-int-coefs (nreverse newcoef)
+			    math-int-factors (cons (list (math-neg rnd))
+						   math-int-factors))
+		      rnd)))
+	   ;; Look for irreducible quadratic factor
+	   (let* ((rnd1 (math-div (math-round
+				   (math-mul xre (math-mul -2 math-int-scale)))
+				  math-int-scale))
+		  (sqscale (math-sqr math-int-scale))
+		  (rnd0 (math-div (math-round (math-mul (math-add xresq ximsq)
+							sqscale))
+				  sqscale))
+		  (rem1 (car math-int-coefs))
+		  (icp (cdr math-int-coefs))
+		  (rem0 (car icp))
+		  (newcoef nil)
+		  (found (assoc (list rnd0 rnd1 (math-posp xim))
+				math-double-roots))
+		  this)
+	     (if found
+		 (setq math-double-roots (delq found math-double-roots)
+		       rem0 0 rem1 0)
+	       (while (setq icp (cdr icp))
+		 (setq this rem1
+		       newcoef (cons rem1 newcoef)
+		       rem1 (math-sub rem0 (math-mul this rnd1))
+		       rem0 (math-sub (car icp) (math-mul this rnd0)))))
+	     (and (math-zerop rem0)
+		  (math-zerop rem1)
+		  (let ((aa (math-div rnd1 -2)))
+		    (or found (setq math-int-coefs (reverse newcoef)
+				    math-double-roots (cons (list
+							     (list
+							      rnd0 rnd1
+							      (math-negp xim)))
+							    math-double-roots)
+				    math-int-factors (cons (cons rnd0 rnd1)
+							   math-int-factors)))
+		    (math-add aa
+			      (let ((calc-symbolic-mode math-symbolic-solve))
+				(math-mul (math-sqrt (math-sub (math-sqr aa)
+							       rnd0))
+					  (if (math-negp xim) -1 1))))))))))
+)
+(setq math-int-coefs nil)
+
+;;; The following routine is from Numerical Recipes, section 9.5.
+(defun math-poly-laguerre-root (p x polish)
+  (let* ((calc-prefer-frac nil)
+	 (calc-symbolic-mode nil)
+	 (iters 0)
+	 (m (1- (length p)))
+	 (try-newt (not polish))
+	 (tried-newt nil)
+	 b d f x1 dx dxold)
+    (while
+	(and (or (< (setq iters (1+ iters)) 50)
+		 (math-reject-arg x "*Laguerre's method failed to converge"))
+	     (let ((err (math-abs-approx (car p)))
+		   (abx (math-abs-approx x))
+		   (pp p))
+	       (setq b (car p)
+		     d 0 f 0)
+	       (while (setq pp (cdr pp))
+		 (setq f (math-add (math-mul x f) d)
+		       d (math-add (math-mul x d) b)
+		       b (math-add (math-mul x b) (car pp))
+		       err (math-add (math-abs-approx b) (math-mul abx err))))
+	       (math-lessp (calcFunc-scf err (- -2 calc-internal-prec))
+			   (math-abs-approx b)))
+	     (or (not (math-zerop d))
+		 (not (math-zerop f))
+		 (progn
+		   (setq x (math-pow (math-neg b) (list 'frac 1 m)))
+		   nil))
+	     (let* ((g (math-div d b))
+		    (g2 (math-sqr g))
+		    (h (math-sub g2 (math-mul 2 (math-div f b))))
+		    (sq (math-sqrt
+			 (math-mul (1- m) (math-sub (math-mul m h) g2))))
+		    (gp (math-add g sq))
+		    (gm (math-sub g sq)))
+	       (if (math-lessp (calcFunc-abssqr gp) (calcFunc-abssqr gm))
+		   (setq gp gm))
+	       (setq dx (math-div m gp)
+		     x1 (math-sub x dx))
+	       (if (and try-newt
+			(math-lessp (math-abs-approx dx)
+				    (calcFunc-scf (math-abs-approx x) -3)))
+		   (let ((newt (math-poly-newton-root p x1 7)))
+		     (setq tried-newt t
+			   try-newt nil)
+		     (if (math-zerop (cdr newt))
+			 (setq x (car newt) x1 x)
+		       (if (math-lessp (cdr newt) '(float 1 -6))
+			   (let ((newt2 (math-poly-newton-root
+					 p (car newt) 20)))
+			     (if (math-zerop (cdr newt2))
+				 (setq x (car newt2) x1 x)
+			       (setq x (car newt))))))))
+	       (not (or (eq x x1)
+			(math-nearly-equal x x1))))
+	     (let ((cdx (math-abs-approx dx)))
+	       (setq x x1
+		     tried-newt nil)
+	       (prog1
+		   (or (<= iters 6)
+		       (math-lessp cdx dxold)
+		       (progn
+			 (if polish
+			     (let ((digs (calcFunc-xpon
+					  (math-div (math-abs-approx x) cdx))))
+			       (calc-record-why
+				"*Could not attain full precision")
+			       (if (natnump digs)
+				   (let ((calc-internal-prec (max 3 digs)))
+				     (setq x (math-normalize x))))))
+			 nil))
+		 (setq dxold cdx)))
+	     (or polish
+		 (math-lessp (calcFunc-scf (math-abs-approx x)
+					   (- calc-internal-prec))
+			     dxold))))
+    (or (and (math-floatp x)
+	     (math-poly-integer-root x))
+	x))
+)
+
+(defun math-solve-above-dummy (x)
+  (and (not (Math-primp x))
+       (if (and (equal (nth 1 x) '(var SOLVEDUM SOLVEDUM))
+		(= (length x) 2))
+	   x
+	 (let ((res nil))
+	   (while (and (setq x (cdr x))
+		       (not (setq res (math-solve-above-dummy (car x))))))
+	   res)))
+)
+
+(defun math-solve-find-root-term (x neg)    ; sets "t2", "t3"
+  (if (math-solve-find-root-in-prod x)
+      (setq t3 neg
+	    t1 x)
+    (and (memq (car-safe x) '(+ -))
+	 (or (math-solve-find-root-term (nth 1 x) neg)
+	     (math-solve-find-root-term (nth 2 x)
+					(if (eq (car x) '-) (not neg) neg)))))
+)
+
+(defun math-solve-find-root-in-prod (x)
+  (and (consp x)
+       (math-expr-contains x solve-var)
+       (or (and (eq (car x) 'calcFunc-sqrt)
+		(setq t2 2))
+	   (and (eq (car x) '^)
+		(or (and (memq (math-quarter-integer (nth 2 x)) '(1 2 3))
+			 (setq t2 2))
+		    (and (eq (car-safe (nth 2 x)) 'frac)
+			 (eq (nth 2 (nth 2 x)) 3)
+			 (setq t2 3))))
+	   (and (memq (car x) '(* /))
+		(or (and (not (math-expr-contains (nth 1 x) solve-var))
+			 (math-solve-find-root-in-prod (nth 2 x)))
+		    (and (not (math-expr-contains (nth 2 x) solve-var))
+			 (math-solve-find-root-in-prod (nth 1 x)))))))
+)
+
+
+(defun math-solve-system (exprs solve-vars solve-full)
+  (setq exprs (mapcar 'list (if (Math-vectorp exprs)
+				(cdr exprs)
+			      (list exprs)))
+	solve-vars (if (Math-vectorp solve-vars)
+		       (cdr solve-vars)
+		     (list solve-vars)))
+  (or (let ((math-solve-simplifying nil))
+	(math-solve-system-rec exprs solve-vars nil))
+      (let ((math-solve-simplifying t))
+	(math-solve-system-rec exprs solve-vars nil)))
+)
+
+;;; The following backtracking solver works by choosing a variable
+;;; and equation, and trying to solve the equation for the variable.
+;;; If it succeeds it calls itself recursively with that variable and
+;;; equation removed from their respective lists, and with the solution
+;;; added to solns as well as being substituted into all existing
+;;; equations.  The algorithm terminates when any solution path
+;;; manages to remove all the variables from var-list.
+
+;;; To support calcFunc-roots, entries in eqn-list and solns are
+;;; actually lists of equations.
+
+(defun math-solve-system-rec (eqn-list var-list solns)
+  (if var-list
+      (let ((v var-list)
+	    (res nil))
+
+	;; Try each variable in turn.
+	(while
+	    (and
+	     v
+	     (let* ((vv (car v))
+		    (e eqn-list)
+		    (elim (eq (car-safe vv) 'calcFunc-elim)))
+	       (if elim
+		   (setq vv (nth 1 vv)))
+
+	       ;; Try each equation in turn.
+	       (while
+		   (and
+		    e
+		    (let ((e2 (car e))
+			  (eprev nil)
+			  res2)
+		      (setq res nil)
+
+		      ;; Try to solve for vv the list of equations e2.
+		      (while (and e2
+				  (setq res2 (or (and (eq (car e2) eprev)
+						      res2)
+						 (math-solve-for (car e2) 0 vv
+								 solve-full))))
+			(setq eprev (car e2)
+			      res (cons (if (eq solve-full 'all)
+					    (cdr res2)
+					  (list res2))
+					res)
+			      e2 (cdr e2)))
+		      (if e2
+			  (setq res nil)
+
+			;; Found a solution.  Now try other variables.
+			(setq res (nreverse res)
+			      res (math-solve-system-rec
+				   (mapcar
+				    'math-solve-system-subst
+				    (delq (car e)
+					  (copy-sequence eqn-list)))
+				   (delq (car v) (copy-sequence var-list))
+				   (let ((math-solve-simplifying nil)
+					 (s (mapcar
+					     (function
+					      (lambda (x)
+						(cons
+						 (car x)
+						 (math-solve-system-subst
+						  (cdr x)))))
+					     solns)))
+				     (if elim
+					 s
+				       (cons (cons vv (apply 'append res))
+					     s)))))
+			(not res))))
+		 (setq e (cdr e)))
+	       (not res)))
+	  (setq v (cdr v)))
+	res)
+
+    ;; Eliminated all variables, so now put solution into the proper format.
+    (setq solns (sort solns
+		      (function
+		       (lambda (x y)
+			 (not (memq (car x) (memq (car y) solve-vars)))))))
+    (if (eq solve-full 'all)
+	(math-transpose
+	 (math-normalize
+	  (cons 'vec
+		(if solns
+		    (mapcar (function (lambda (x) (cons 'vec (cdr x)))) solns)
+		  (mapcar (function (lambda (x) (cons 'vec x))) eqn-list)))))
+      (math-normalize
+       (cons 'vec 
+	     (if solns
+		 (mapcar (function (lambda (x) (cons 'calcFunc-eq x))) solns)
+	       (mapcar 'car eqn-list))))))
+)
+
+(defun math-solve-system-subst (x)    ; uses "res" and "v"
+  (let ((accum nil)
+	(res2 res))
+    (while x
+      (setq accum (nconc accum
+			 (mapcar (function
+				  (lambda (r)
+				    (if math-solve-simplifying
+					(math-simplify
+					 (math-expr-subst (car x) vv r))
+				      (math-expr-subst (car x) vv r))))
+				 (car res2)))
+	    x (cdr x)
+	    res2 (cdr res2)))
+    accum)
+)
+
+
+(defun math-get-from-counter (name)
+  (let ((ctr (assq name calc-command-flags)))
+    (if ctr
+	(setcdr ctr (1+ (cdr ctr)))
+      (setq ctr (cons name 1)
+	    calc-command-flags (cons ctr calc-command-flags)))
+    (cdr ctr))
+)
+
+(defun math-solve-get-sign (val)
+  (setq val (math-simplify val))
+  (if (and (eq (car-safe val) '*)
+	   (Math-numberp (nth 1 val)))
+      (list '* (nth 1 val) (math-solve-get-sign (nth 2 val)))
+    (and (eq (car-safe val) 'calcFunc-sqrt)
+	 (eq (car-safe (nth 1 val)) '^)
+	 (setq val (math-normalize (list '^
+					 (nth 1 (nth 1 val))
+					 (math-div (nth 2 (nth 1 val)) 2)))))
+    (if solve-full
+	(if (and (calc-var-value 'var-GenCount)
+		 (Math-natnump var-GenCount)
+		 (not (eq solve-full 'all)))
+	    (prog1
+		(math-mul (list 'calcFunc-as var-GenCount) val)
+	      (setq var-GenCount (math-add var-GenCount 1))
+	      (calc-refresh-evaltos 'var-GenCount))
+	  (let* ((var (concat "s" (math-get-from-counter 'solve-sign)))
+		 (var2 (list 'var (intern var) (intern (concat "var-" var)))))
+	    (if (eq solve-full 'all)
+		(setq math-solve-ranges (cons (list var2 1 -1)
+					      math-solve-ranges)))
+	    (math-mul var2 val)))
+      (calc-record-why "*Choosing positive solution")
+      val))
+)
+
+(defun math-solve-get-int (val &optional range first)
+  (if solve-full
+      (if (and (calc-var-value 'var-GenCount)
+	       (Math-natnump var-GenCount)
+	       (not (eq solve-full 'all)))
+	  (prog1
+	      (math-mul val (list 'calcFunc-an var-GenCount))
+	    (setq var-GenCount (math-add var-GenCount 1))
+	    (calc-refresh-evaltos 'var-GenCount))
+	(let* ((var (concat "n" (math-get-from-counter 'solve-int)))
+	       (var2 (list 'var (intern var) (intern (concat "var-" var)))))
+	  (if (and range (eq solve-full 'all))
+	      (setq math-solve-ranges (cons (cons var2
+						  (cdr (calcFunc-index
+							range (or first 0))))
+					    math-solve-ranges)))
+	  (math-mul val var2)))
+    (calc-record-why "*Choosing 0 for arbitrary integer in solution")
+    0)
+)
+
+(defun math-solve-sign (sign expr)
+  (and sign
+       (let ((s1 (math-possible-signs expr)))
+	 (cond ((memq s1 '(4 6))
+		sign)
+	       ((memq s1 '(1 3))
+		(- sign)))))
+)
+
+(defun math-looks-evenp (expr)
+  (if (Math-integerp expr)
+      (math-evenp expr)
+    (if (memq (car expr) '(* /))
+	(math-looks-evenp (nth 1 expr))))
+)
+
+(defun math-solve-for (lhs rhs solve-var solve-full &optional sign)
+  (if (math-expr-contains rhs solve-var)
+      (math-solve-for (math-sub lhs rhs) 0 solve-var solve-full)
+    (and (math-expr-contains lhs solve-var)
+	 (math-with-extra-prec 1
+	   (let* ((math-poly-base-variable solve-var)
+		  (res (math-try-solve-for lhs rhs sign)))
+	     (if (and (eq solve-full 'all)
+		      (math-known-realp solve-var))
+		 (let ((old-len (length res))
+		       new-len)
+		   (setq res (delq nil
+				   (mapcar (function
+					    (lambda (x)
+					      (and (not (memq (car-safe x)
+							      '(cplx polar)))
+						   x)))
+					   res))
+			 new-len (length res))
+		   (if (< new-len old-len)
+		       (calc-record-why (if (= new-len 1)
+					    "*All solutions were complex"
+					  (format
+					   "*Omitted %d complex solutions"
+					   (- old-len new-len)))))))
+	     res))))
+)
+
+(defun math-solve-eqn (expr var full)
+  (if (memq (car-safe expr) '(calcFunc-neq calcFunc-lt calcFunc-gt
+					   calcFunc-leq calcFunc-geq))
+      (let ((res (math-solve-for (cons '- (cdr expr))
+				 0 var full
+				 (if (eq (car expr) 'calcFunc-neq) nil 1))))
+	(and res
+	     (if (eq math-solve-sign 1)
+		 (list (car expr) var res)
+	       (if (eq math-solve-sign -1)
+		   (list (car expr) res var)
+		 (or (eq (car expr) 'calcFunc-neq)
+		     (calc-record-why
+		      "*Can't determine direction of inequality"))
+		 (and (memq (car expr) '(calcFunc-neq calcFunc-lt calcFunc-gt))
+		      (list 'calcFunc-neq var res))))))
+    (let ((res (math-solve-for expr 0 var full)))
+      (and res
+	   (list 'calcFunc-eq var res))))
+)
+
+(defun math-reject-solution (expr var func)
+  (if (math-expr-contains expr var)
+      (or (equal (car calc-next-why) '(* "Unable to find a symbolic solution"))
+	  (calc-record-why "*Unable to find a solution")))
+  (list func expr var)
+)
+
+(defun calcFunc-solve (expr var)
+  (or (if (or (Math-vectorp expr) (Math-vectorp var))
+	  (math-solve-system expr var nil)
+	(math-solve-eqn expr var nil))
+      (math-reject-solution expr var 'calcFunc-solve))
+)
+
+(defun calcFunc-fsolve (expr var)
+  (or (if (or (Math-vectorp expr) (Math-vectorp var))
+	  (math-solve-system expr var t)
+	(math-solve-eqn expr var t))
+      (math-reject-solution expr var 'calcFunc-fsolve))
+)
+
+(defun calcFunc-roots (expr var)
+  (let ((math-solve-ranges nil))
+    (or (if (or (Math-vectorp expr) (Math-vectorp var))
+	    (math-solve-system expr var 'all)
+	  (math-solve-for expr 0 var 'all))
+      (math-reject-solution expr var 'calcFunc-roots)))
+)
+
+(defun calcFunc-finv (expr var)
+  (let ((res (math-solve-for expr math-integ-var var nil)))
+    (if res
+	(math-normalize (math-expr-subst res math-integ-var var))
+      (math-reject-solution expr var 'calcFunc-finv)))
+)
+
+(defun calcFunc-ffinv (expr var)
+  (let ((res (math-solve-for expr math-integ-var var t)))
+    (if res
+	(math-normalize (math-expr-subst res math-integ-var var))
+      (math-reject-solution expr var 'calcFunc-finv)))
+)
+
+
+(put 'calcFunc-inv 'math-inverse
+     (function (lambda (x) (math-div 1 x))))
+(put 'calcFunc-inv 'math-inverse-sign -1)
+
+(put 'calcFunc-sqrt 'math-inverse
+     (function (lambda (x) (math-sqr x))))
+
+(put 'calcFunc-conj 'math-inverse
+     (function (lambda (x) (list 'calcFunc-conj x))))
+
+(put 'calcFunc-abs 'math-inverse
+     (function (lambda (x) (math-solve-get-sign x))))
+
+(put 'calcFunc-deg 'math-inverse
+     (function (lambda (x) (list 'calcFunc-rad x))))
+(put 'calcFunc-deg 'math-inverse-sign 1)
+
+(put 'calcFunc-rad 'math-inverse
+     (function (lambda (x) (list 'calcFunc-deg x))))
+(put 'calcFunc-rad 'math-inverse-sign 1)
+
+(put 'calcFunc-ln 'math-inverse
+     (function (lambda (x) (list 'calcFunc-exp x))))
+(put 'calcFunc-ln 'math-inverse-sign 1)
+
+(put 'calcFunc-log10 'math-inverse
+     (function (lambda (x) (list 'calcFunc-exp10 x))))
+(put 'calcFunc-log10 'math-inverse-sign 1)
+
+(put 'calcFunc-lnp1 'math-inverse
+     (function (lambda (x) (list 'calcFunc-expm1 x))))
+(put 'calcFunc-lnp1 'math-inverse-sign 1)
+
+(put 'calcFunc-exp 'math-inverse
+     (function (lambda (x) (math-add (math-normalize (list 'calcFunc-ln x))
+				     (math-mul 2
+					       (math-mul '(var pi var-pi)
+							 (math-solve-get-int
+							  '(var i var-i))))))))
+(put 'calcFunc-exp 'math-inverse-sign 1)
+
+(put 'calcFunc-expm1 'math-inverse
+     (function (lambda (x) (math-add (math-normalize (list 'calcFunc-lnp1 x))
+				     (math-mul 2
+					       (math-mul '(var pi var-pi)
+							 (math-solve-get-int
+							  '(var i var-i))))))))
+(put 'calcFunc-expm1 'math-inverse-sign 1)
+
+(put 'calcFunc-sin 'math-inverse
+     (function (lambda (x) (let ((n (math-solve-get-int 1)))
+			     (math-add (math-mul (math-normalize
+						  (list 'calcFunc-arcsin x))
+						 (math-pow -1 n))
+				       (math-mul (math-half-circle t)
+						 n))))))
+
+(put 'calcFunc-cos 'math-inverse
+     (function (lambda (x) (math-add (math-solve-get-sign
+				      (math-normalize
+				       (list 'calcFunc-arccos x)))
+				     (math-solve-get-int
+				      (math-full-circle t))))))
+
+(put 'calcFunc-tan 'math-inverse
+     (function (lambda (x) (math-add (math-normalize (list 'calcFunc-arctan x))
+				     (math-solve-get-int
+				      (math-half-circle t))))))
+
+(put 'calcFunc-arcsin 'math-inverse
+     (function (lambda (x) (math-normalize (list 'calcFunc-sin x)))))
+
+(put 'calcFunc-arccos 'math-inverse
+     (function (lambda (x) (math-normalize (list 'calcFunc-cos x)))))
+
+(put 'calcFunc-arctan 'math-inverse
+     (function (lambda (x) (math-normalize (list 'calcFunc-tan x)))))
+
+(put 'calcFunc-sinh 'math-inverse
+     (function (lambda (x) (let ((n (math-solve-get-int 1)))
+			     (math-add (math-mul (math-normalize
+						  (list 'calcFunc-arcsinh x))
+						 (math-pow -1 n))
+				       (math-mul (math-half-circle t)
+						 (math-mul
+						  '(var i var-i)
+						  n)))))))
+(put 'calcFunc-sinh 'math-inverse-sign 1)
+
+(put 'calcFunc-cosh 'math-inverse
+     (function (lambda (x) (math-add (math-solve-get-sign
+				      (math-normalize
+				       (list 'calcFunc-arccosh x)))
+				     (math-mul (math-full-circle t)
+					       (math-solve-get-int
+						'(var i var-i)))))))
+
+(put 'calcFunc-tanh 'math-inverse
+     (function (lambda (x) (math-add (math-normalize
+				      (list 'calcFunc-arctanh x))
+				     (math-mul (math-half-circle t)
+					       (math-solve-get-int
+						'(var i var-i)))))))
+(put 'calcFunc-tanh 'math-inverse-sign 1)
+
+(put 'calcFunc-arcsinh 'math-inverse
+     (function (lambda (x) (math-normalize (list 'calcFunc-sinh x)))))
+(put 'calcFunc-arcsinh 'math-inverse-sign 1)
+
+(put 'calcFunc-arccosh 'math-inverse
+     (function (lambda (x) (math-normalize (list 'calcFunc-cosh x)))))
+
+(put 'calcFunc-arctanh 'math-inverse
+     (function (lambda (x) (math-normalize (list 'calcFunc-tanh x)))))
+(put 'calcFunc-arctanh 'math-inverse-sign 1)
+
+
+
+(defun calcFunc-taylor (expr var num)
+  (let ((x0 0) (v var))
+    (if (memq (car-safe var) '(+ - calcFunc-eq))
+	(setq x0 (if (eq (car var) '+) (math-neg (nth 2 var)) (nth 2 var))
+	      v (nth 1 var)))
+    (or (and (eq (car-safe v) 'var)
+	     (math-expr-contains expr v)
+	     (natnump num)
+	     (let ((accum (math-expr-subst expr v x0))
+		   (var2 (if (eq (car var) 'calcFunc-eq)
+			     (cons '- (cdr var))
+			   var))
+		   (n 0)
+		   (nfac 1)
+		   (fprime expr))
+	       (while (and (<= (setq n (1+ n)) num)
+			   (setq fprime (calcFunc-deriv fprime v nil t)))
+		 (setq fprime (math-simplify fprime)
+		       nfac (math-mul nfac n)
+		       accum (math-add accum
+				       (math-div (math-mul (math-pow var2 n)
+							   (math-expr-subst
+							    fprime v x0))
+						 nfac))))
+	       (and fprime
+		    (math-normalize accum))))
+	(list 'calcFunc-taylor expr var num)))
+)
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/calcalg3.el	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,1824 @@
+;; Calculator for GNU Emacs, part II [calc-alg-3.el]
+;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+;; Written by Dave Gillespie, daveg@synaptics.com.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY.  No author or distributor
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing.  Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License.   A copy of this license is
+;; supposed to have been given to you along with GNU Emacs so you
+;; can know your rights and responsibilities.  It should be in a
+;; file named COPYING.  Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+
+
+
+;; This file is autoloaded from calc-ext.el.
+(require 'calc-ext)
+
+(require 'calc-macs)
+
+(defun calc-Need-calc-alg-3 () nil)
+
+
+(defun calc-find-root (var)
+  (interactive "sVariable(s) to solve for: ")
+  (calc-slow-wrapper
+   (let ((func (if (calc-is-hyperbolic) 'calcFunc-wroot 'calcFunc-root)))
+     (if (or (equal var "") (equal var "$"))
+	 (calc-enter-result 2 "root" (list func
+					   (calc-top-n 3)
+					   (calc-top-n 1)
+					   (calc-top-n 2)))
+       (let ((var (if (and (string-match ",\\|[^ ] +[^ ]" var)
+			   (not (string-match "\\[" var)))
+		      (math-read-expr (concat "[" var "]"))
+		    (math-read-expr var))))
+	 (if (eq (car-safe var) 'error)
+	     (error "Bad format in expression: %s" (nth 1 var)))
+	 (calc-enter-result 1 "root" (list func
+					   (calc-top-n 2)
+					   var
+					   (calc-top-n 1)))))))
+)
+
+(defun calc-find-minimum (var)
+  (interactive "sVariable(s) to minimize over: ")
+  (calc-slow-wrapper
+   (let ((func (if (calc-is-inverse)
+		   (if (calc-is-hyperbolic)
+		       'calcFunc-wmaximize 'calcFunc-maximize)
+		 (if (calc-is-hyperbolic)
+		     'calcFunc-wminimize 'calcFunc-minimize)))
+	 (tag (if (calc-is-inverse) "max" "min")))
+     (if (or (equal var "") (equal var "$"))
+	 (calc-enter-result 2 tag (list func
+					(calc-top-n 3)
+					(calc-top-n 1)
+					(calc-top-n 2)))
+       (let ((var (if (and (string-match ",\\|[^ ] +[^ ]" var)
+			   (not (string-match "\\[" var)))
+		      (math-read-expr (concat "[" var "]"))
+		    (math-read-expr var))))
+	 (if (eq (car-safe var) 'error)
+	     (error "Bad format in expression: %s" (nth 1 var)))
+	 (calc-enter-result 1 tag (list func
+					(calc-top-n 2)
+					var
+					(calc-top-n 1)))))))
+)
+
+(defun calc-find-maximum (var)
+  (interactive "sVariable to maximize over: ")
+  (calc-invert-func)
+  (calc-find-minimum var)
+)
+
+
+(defun calc-poly-interp (arg)
+  (interactive "P")
+  (calc-slow-wrapper
+   (let ((data (calc-top 2)))
+     (if (or (consp arg) (eq arg 0) (eq arg 2))
+	 (setq data (cons 'vec (calc-top-list 2 2)))
+       (or (null arg)
+	   (error "Bad prefix argument")))
+     (if (calc-is-hyperbolic)
+	 (calc-enter-result 1 "rati" (list 'calcFunc-ratint data (calc-top 1)))
+       (calc-enter-result 1 "poli" (list 'calcFunc-polint data
+					 (calc-top 1))))))
+)
+
+
+(defun calc-curve-fit (arg &optional model coefnames varnames)
+  (interactive "P")
+  (calc-slow-wrapper
+   (setq calc-aborted-prefix nil)
+   (let ((func (if (calc-is-inverse) 'calcFunc-xfit
+		 (if (calc-is-hyperbolic) 'calcFunc-efit
+		   'calcFunc-fit)))
+	 key (which 0)
+	 n nvars temp data
+	 (homog nil)
+	 (msgs '( "(Press ? for help)"
+		  "1 = linear or multilinear"
+		  "2-9 = polynomial fits; i = interpolating polynomial"
+		  "p = a x^b, ^ = a b^x"
+		  "e = a exp(b x), x = exp(a + b x), l = a + b ln(x)"
+		  "E = a 10^(b x), X = 10^(a + b x), L = a + b log10(x)"
+		  "q = a + b (x-c)^2"
+		  "g = (a/b sqrt(2 pi)) exp(-0.5*((x-c)/b)^2)"
+		  "h prefix = homogeneous model (no constant term)"
+		  "' = alg entry, $ = stack, u = Model1, U = Model2")))
+     (while (not model)
+       (message "Fit to model: %s:%s"
+		(nth which msgs)
+		(if homog " h" ""))
+       (setq key (read-char))
+       (cond ((= key ?\C-g)
+	      (keyboard-quit))
+	     ((= key ??)
+	      (setq which (% (1+ which) (length msgs))))
+	     ((memq key '(?h ?H))
+	      (setq homog (not homog)))
+	     ((progn
+		(if (eq key ?\$)
+		    (setq n 1)
+		  (setq n 0))
+		(cond ((null arg)
+		       (setq n (1+ n)
+			     data (calc-top n)))
+		      ((or (consp arg) (eq arg 0))
+		       (setq n (+ n 2)
+			     data (calc-top n)
+			     data (if (math-matrixp data)
+				      (append data (list (calc-top (1- n))))
+				    (list 'vec data (calc-top (1- n))))))
+		      ((> (setq arg (prefix-numeric-value arg)) 0)
+		       (setq data (cons 'vec (calc-top-list arg (1+ n)))
+			     n (+ n arg)))
+		      (t (error "Bad prefix argument")))
+		(or (math-matrixp data) (not (cdr (cdr data)))
+		    (error "Data matrix is not a matrix!"))
+		(setq nvars (- (length data) 2)
+		      coefnames nil
+		      varnames nil)
+		nil))
+	     ((= key ?1)  ; linear or multilinear
+	      (calc-get-fit-variables nvars (1+ nvars) (and homog 0))
+	      (setq model (math-mul coefnames
+				    (cons 'vec (cons 1 (cdr varnames))))))
+	     ((and (>= key ?2) (<= key ?9))   ; polynomial
+	      (calc-get-fit-variables 1 (- key ?0 -1) (and homog 0))
+	      (setq model (math-build-polynomial-expr (cdr coefnames)
+						      (nth 1 varnames))))
+	     ((= key ?i)  ; exact polynomial
+	      (calc-get-fit-variables 1 (1- (length (nth 1 data)))
+				      (and homog 0))
+	      (setq model (math-build-polynomial-expr (cdr coefnames)
+						      (nth 1 varnames))))
+	     ((= key ?p)  ; power law
+	      (calc-get-fit-variables nvars (1+ nvars) (and homog 1))
+	      (setq model (math-mul (nth 1 coefnames)
+				    (calcFunc-reduce
+				     '(var mul var-mul)
+				     (calcFunc-map
+				      '(var pow var-pow)
+				      varnames
+				      (cons 'vec (cdr (cdr coefnames))))))))
+	     ((= key ?^)  ; exponential law
+	      (calc-get-fit-variables nvars (1+ nvars) (and homog 1))
+	      (setq model (math-mul (nth 1 coefnames)
+				    (calcFunc-reduce
+				     '(var mul var-mul)
+				     (calcFunc-map
+				      '(var pow var-pow)
+				      (cons 'vec (cdr (cdr coefnames)))
+				      varnames)))))
+	     ((memq key '(?e ?E))
+	      (calc-get-fit-variables nvars (1+ nvars) (and homog 1))
+	      (setq model (math-mul (nth 1 coefnames)
+				    (calcFunc-reduce
+				     '(var mul var-mul)
+				     (calcFunc-map
+				      (if (eq key ?e)
+					  '(var exp var-exp)
+					'(calcFunc-lambda
+					  (var a var-a)
+					  (^ 10 (var a var-a))))
+				      (calcFunc-map
+				       '(var mul var-mul)
+				       (cons 'vec (cdr (cdr coefnames)))
+				       varnames))))))
+	     ((memq key '(?x ?X))
+	      (calc-get-fit-variables nvars (1+ nvars) (and homog 0))
+	      (setq model (math-mul coefnames
+				    (cons 'vec (cons 1 (cdr varnames)))))
+	      (setq model (if (eq key ?x)
+			      (list 'calcFunc-exp model)
+			    (list '^ 10 model))))
+	     ((memq key '(?l ?L))
+	      (calc-get-fit-variables nvars (1+ nvars) (and homog 0))
+	      (setq model (math-mul coefnames
+				    (cons 'vec
+					  (cons 1 (cdr (calcFunc-map
+							(if (eq key ?l)
+							    '(var ln var-ln)
+							  '(var log10
+								var-log10))
+							varnames)))))))
+	     ((= key ?q)
+	      (calc-get-fit-variables nvars (1+ (* 2 nvars)) (and homog 0))
+	      (let ((c coefnames)
+		    (v varnames))
+		(setq model (nth 1 c))
+		(while (setq v (cdr v) c (cdr (cdr c)))
+		  (setq model (math-add
+			       model
+			       (list '*
+				     (car c)
+				     (list '^
+					   (list '- (car v) (nth 1 c))
+					   2)))))))
+	     ((= key ?g)
+	      (setq model (math-read-expr "(AFit / BFit sqrt(2 pi)) exp(-0.5 * ((XFit - CFit) / BFit)^2)")
+		    varnames '(vec (var XFit var-XFit))
+		    coefnames '(vec (var AFit var-AFit)
+				    (var BFit var-BFit)
+				    (var CFit var-CFit)))
+	      (calc-get-fit-variables 1 (1- (length coefnames)) (and homog 1)))
+	     ((memq key '(?\$ ?\' ?u ?U))
+	      (let* ((defvars nil)
+		     (record-entry nil))
+		(if (eq key ?\')
+		    (let* ((calc-dollar-values calc-arg-values)
+			   (calc-dollar-used 0)
+			   (calc-hashes-used 0))
+		      (setq model (calc-do-alg-entry "" "Model formula: "))
+		      (if (/= (length model) 1)
+			  (error "Bad format"))
+		      (setq model (car model)
+			    record-entry t)
+		      (if (> calc-dollar-used 0)
+			  (setq coefnames
+				(cons 'vec
+				      (nthcdr (- (length calc-arg-values)
+						 calc-dollar-used)
+					      (reverse calc-arg-values))))
+			(if (> calc-hashes-used 0)
+			    (setq coefnames
+				  (cons 'vec (calc-invent-args
+					      calc-hashes-used))))))
+		  (progn
+		    (setq model (cond ((eq key ?u)
+				       (calc-var-value 'var-Model1))
+				      ((eq key ?U)
+				       (calc-var-value 'var-Model2))
+				      (t (calc-top 1))))
+		    (or model (error "User model not yet defined"))
+		    (if (math-vectorp model)
+			(if (and (memq (length model) '(3 4))
+				 (not (math-objvecp (nth 1 model)))
+				 (math-vectorp (nth 2 model))
+				 (or (null (nth 3 model))
+				     (math-vectorp (nth 3 model))))
+			    (setq varnames (nth 2 model)
+				  coefnames (or (nth 3 model)
+						(cons 'vec
+						      (math-all-vars-but
+						       model varnames)))
+				  model (nth 1 model))
+			  (error "Incorrect model specifier")))))
+		(or varnames
+		    (let ((with-y (eq (car-safe model) 'calcFunc-eq)))
+		      (if coefnames
+			  (calc-get-fit-variables (if with-y (1+ nvars) nvars)
+						  (1- (length coefnames))
+						  (math-all-vars-but
+						   model coefnames)
+						  nil with-y)
+			(let* ((coefs (math-all-vars-but model nil))
+			       (vars nil)
+			       (n (- (length coefs) nvars (if with-y 2 1)))
+			       p)
+			  (if (< n 0)
+			      (error "Not enough variables in model"))
+			  (setq p (nthcdr n coefs))
+			  (setq vars (cdr p))
+			  (setcdr p nil)
+			  (calc-get-fit-variables (if with-y (1+ nvars) nvars)
+						  (length coefs)
+						  vars coefs with-y)))))
+		(if record-entry
+		    (calc-record (list 'vec model varnames coefnames)
+				 "modl"))))
+	     (t (beep))))
+     (let ((calc-fit-to-trail t))
+       (calc-enter-result n (substring (symbol-name func) 9)
+			  (list func model
+				(if (= (length varnames) 2)
+				    (nth 1 varnames)
+				  varnames)
+				(if (= (length coefnames) 2)
+				    (nth 1 coefnames)
+				  coefnames)
+				data))
+       (if (consp calc-fit-to-trail)
+	   (calc-record (calc-normalize calc-fit-to-trail) "parm")))))
+)
+
+(defun calc-invent-independent-variables (n &optional but)
+  (calc-invent-variables n but '(x y z t) "x")
+)
+
+(defun calc-invent-parameter-variables (n &optional but)
+  (calc-invent-variables n but '(a b c d) "a")
+)
+
+(defun calc-invent-variables (num but names base)
+  (let ((vars nil)
+	(n num) (nn 0)
+	var)
+    (while (and (> n 0) names)
+      (setq var (math-build-var-name (if (consp names)
+					 (car names)
+				       (concat base (setq nn (1+ nn))))))
+      (or (math-expr-contains (cons 'vec but) var)
+	  (setq vars (cons var vars)
+		n (1- n)))
+      (or (symbolp names) (setq names (cdr names))))
+    (if (= n 0)
+	(nreverse vars)
+      (calc-invent-variables num but t base)))
+)
+
+(defun calc-get-fit-variables (nv nc &optional defv defc with-y homog)
+  (or (= nv (if with-y (1+ nvars) nvars))
+      (error "Wrong number of data vectors for this type of model"))
+  (if (integerp defv)
+      (setq homog defv
+	    defv nil))
+  (if homog
+      (setq nc (1- nc)))
+  (or defv
+      (setq defv (calc-invent-independent-variables nv)))
+  (or defc
+      (setq defc (calc-invent-parameter-variables nc defv)))
+  (let ((vars (read-string (format "Fitting variables: (default %s; %s) "
+				   (mapconcat 'symbol-name
+					      (mapcar (function (lambda (v)
+								  (nth 1 v)))
+						      defv)
+					      ",")
+				   (mapconcat 'symbol-name
+					      (mapcar (function (lambda (v)
+								  (nth 1 v)))
+						      defc)
+					      ","))))
+	(coefs nil))
+    (setq vars (if (string-match "\\[" vars)
+		   (math-read-expr vars)
+		 (math-read-expr (concat "[" vars "]"))))
+    (if (eq (car-safe vars) 'error)
+	(error "Bad format in expression: %s" (nth 2 vars)))
+    (or (math-vectorp vars)
+	(error "Expected a variable or vector of variables"))
+    (if (equal vars '(vec))
+	(setq vars (cons 'vec defv)
+	      coefs (cons 'vec defc))
+      (if (math-vectorp (nth 1 vars))
+	  (if (and (= (length vars) 3)
+		   (math-vectorp (nth 2 vars)))
+	      (setq coefs (nth 2 vars)
+		    vars (nth 1 vars))
+	    (error
+	     "Expected independent variables vector, then parameters vector"))
+	(setq coefs (cons 'vec defc))))
+    (or (= nv (1- (length vars)))
+	(and (not with-y) (= (1+ nv) (1- (length vars))))
+	(error "Expected %d independent variable%s" nv (if (= nv 1) "" "s")))
+    (or (= nc (1- (length coefs)))
+	(error "Expected %d parameter variable%s" nc (if (= nc 1) "" "s")))
+    (if homog
+	(setq coefs (cons 'vec (cons homog (cdr coefs)))))
+    (if varnames
+	(setq model (math-multi-subst model (cdr varnames) (cdr vars))))
+    (if coefnames
+	(setq model (math-multi-subst model (cdr coefnames) (cdr coefs))))
+    (setq varnames vars
+	  coefnames coefs))
+)
+
+
+
+
+;;; The following algorithms are from Numerical Recipes chapter 9.
+
+;;; "rtnewt" with safety kludges
+(defun math-newton-root (expr deriv guess orig-guess limit)
+  (math-working "newton" guess)
+  (let* ((var-DUMMY guess)
+	 next dval)
+    (setq next (math-evaluate-expr expr)
+	  dval (math-evaluate-expr deriv))
+    (if (and (Math-numberp next)
+	     (Math-numberp dval)
+	     (not (Math-zerop dval)))
+	(progn
+	  (setq next (math-sub guess (math-div next dval)))
+	  (if (math-nearly-equal guess (setq next (math-float next)))
+	      (progn
+		(setq var-DUMMY next)
+		(list 'vec next (math-evaluate-expr expr)))
+	    (if (Math-lessp (math-abs-approx (math-sub next orig-guess))
+			    limit)
+		(math-newton-root expr deriv next orig-guess limit)
+	      (math-reject-arg next "*Newton's method failed to converge"))))
+      (math-reject-arg next "*Newton's method encountered a singularity")))
+)
+
+;;; Inspired by "rtsafe"
+(defun math-newton-search-root (expr deriv guess vguess ostep oostep
+				     low vlow high vhigh)
+  (let ((var-DUMMY guess)
+	(better t)
+	pos step next vnext)
+    (if guess
+	(math-working "newton" (list 'intv 0 low high))
+      (math-working "bisect" (list 'intv 0 low high))
+      (setq ostep (math-mul-float (math-sub-float high low)
+				  '(float 5 -1))
+	    guess (math-add-float low ostep)
+	    var-DUMMY guess
+	    vguess (math-evaluate-expr expr))
+      (or (Math-realp vguess)
+	  (progn
+	    (setq ostep (math-mul-float ostep '(float 6 -1))
+		  guess (math-add-float low ostep)
+		  var-DUMMY guess
+		  vguess (math-evaluate-expr expr))
+	    (or (math-realp vguess)
+		(progn
+		  (setq ostep (math-mul-float ostep '(float 123456 -5))
+			guess (math-add-float low ostep)
+			var-DUMMY guess
+			vguess nil))))))
+    (or vguess
+	(setq vguess (math-evaluate-expr expr)))
+    (or (Math-realp vguess)
+	(math-reject-arg guess "*Newton's method encountered a singularity"))
+    (setq vguess (math-float vguess))
+    (if (eq (Math-negp vlow) (setq pos (Math-posp vguess)))
+	(setq high guess
+	      vhigh vguess)
+      (if (eq (Math-negp vhigh) pos)
+	  (setq low guess
+		vlow vguess)
+	(setq better nil)))
+    (if (or (Math-zerop vguess)
+	    (math-nearly-equal low high))
+	(list 'vec guess vguess)
+      (setq step (math-evaluate-expr deriv))
+      (if (and (Math-realp step)
+	       (not (Math-zerop step))
+	       (setq step (math-div-float vguess (math-float step))
+		     next (math-sub-float guess step))
+	       (not (math-lessp-float high next))
+	       (not (math-lessp-float next low)))
+	  (progn
+	    (setq var-DUMMY next
+		  vnext (math-evaluate-expr expr))
+	    (if (or (Math-zerop vnext)
+		    (math-nearly-equal next guess))
+		(list 'vec next vnext)
+	      (if (and better
+		       (math-lessp-float (math-abs (or oostep
+						       (math-sub-float
+							high low)))
+					 (math-abs
+					  (math-mul-float '(float 2 0)
+							  step))))
+		  (math-newton-search-root expr deriv nil nil nil ostep
+					   low vlow high vhigh)
+		(math-newton-search-root expr deriv next vnext step ostep
+					 low vlow high vhigh))))
+	(if (or (and (Math-posp vlow) (Math-posp vhigh))
+		(and (Math-negp vlow) (Math-negp vhigh)))
+	    (math-search-root expr deriv low vlow high vhigh)
+	  (math-newton-search-root expr deriv nil nil nil ostep
+				   low vlow high vhigh)))))
+)
+
+;;; Search for a root in an interval with no overt zero crossing.
+(defun math-search-root (expr deriv low vlow high vhigh)
+  (let (found)
+    (if root-widen
+	(let ((iters 0)
+	      (iterlim (if (eq root-widen 'point)
+			   (+ calc-internal-prec 10)
+			 20))
+	      (factor (if (eq root-widen 'point)
+			  '(float 9 0)
+			'(float 16 -1)))
+	      (prev nil) vprev waslow
+	      diff)
+	  (while (or (and (math-posp vlow) (math-posp vhigh))
+		     (and (math-negp vlow) (math-negp vhigh)))
+	    (math-working "widen" (list 'intv 0 low high))
+	    (if (> (setq iters (1+ iters)) iterlim)
+		(math-reject-arg (list 'intv 0 low high)
+				 "*Unable to bracket root"))
+	    (if (= iters calc-internal-prec)
+		(setq factor '(float 16 -1)))
+	    (setq diff (math-mul-float (math-sub-float high low) factor))
+	    (if (Math-zerop diff)
+		(setq high (calcFunc-incr high 10))
+	      (if (math-lessp-float (math-abs vlow) (math-abs vhigh))
+		  (setq waslow t
+			prev low
+			low (math-sub low diff)
+			var-DUMMY low
+			vprev vlow
+			vlow (math-evaluate-expr expr))
+		(setq waslow nil
+		      prev high
+		      high (math-add high diff)
+		      var-DUMMY high
+		      vprev vhigh
+		      vhigh (math-evaluate-expr expr)))))
+	  (if prev
+	      (if waslow
+		  (setq high prev vhigh vprev)
+		(setq low prev vlow vprev)))
+	  (setq found t))
+      (or (Math-realp vlow)
+	  (math-reject-arg vlow 'realp))
+      (or (Math-realp vhigh)
+	  (math-reject-arg vhigh 'realp))
+      (let ((xvals (list low high))
+	    (yvals (list vlow vhigh))
+	    (pos (Math-posp vlow))
+	    (levels 0)
+	    (step (math-sub-float high low))
+	    xp yp var-DUMMY)
+	(while (and (<= (setq levels (1+ levels)) 5)
+		    (not found))
+	  (setq xp xvals
+		yp yvals
+		step (math-mul-float step '(float 497 -3)))
+	  (while (and (cdr xp) (not found))
+	    (if (Math-realp (car yp))
+		(setq low (car xp)
+		      vlow (car yp)))
+	    (setq high (math-add-float (car xp) step)
+		  var-DUMMY high
+		  vhigh (math-evaluate-expr expr))
+	    (math-working "search" high)
+	    (if (and (Math-realp vhigh)
+		     (eq (math-negp vhigh) pos))
+		(setq found t)
+	      (setcdr xp (cons high (cdr xp)))
+	      (setcdr yp (cons vhigh (cdr yp)))
+	      (setq xp (cdr (cdr xp))
+		    yp (cdr (cdr yp))))))))
+    (if found
+	(if (Math-zerop vhigh)
+	    (list 'vec high vhigh)
+	  (if (Math-zerop vlow)
+	      (list 'vec low vlow)
+	    (if deriv
+		(math-newton-search-root expr deriv nil nil nil nil
+					 low vlow high vhigh)
+	      (math-bisect-root expr low vlow high vhigh))))
+      (math-reject-arg (list 'intv 3 low high)
+		       "*Unable to find a sign change in this interval")))
+)
+
+;;; "rtbis"  (but we should be using Brent's method)
+(defun math-bisect-root (expr low vlow high vhigh)
+  (let ((step (math-sub-float high low))
+	(pos (Math-posp vhigh))
+	var-DUMMY
+	mid vmid)
+    (while (not (or (math-nearly-equal low
+				       (setq step (math-mul-float
+						   step '(float 5 -1))
+					     mid (math-add-float low step)))
+		    (progn
+		      (setq var-DUMMY mid
+			    vmid (math-evaluate-expr expr))
+		      (Math-zerop vmid))))
+      (math-working "bisect" mid)
+      (if (eq (Math-posp vmid) pos)
+	  (setq high mid
+		vhigh vmid)
+	(setq low mid
+	      vlow vmid)))
+    (list 'vec mid vmid))
+)
+
+;;; "mnewt"
+(defun math-newton-multi (expr jacob n guess orig-guess limit)
+  (let ((m -1)
+	(p guess)
+	p2 expr-val jacob-val next)
+    (while (< (setq p (cdr p) m (1+ m)) n)
+      (set (nth 2 (aref math-root-vars m)) (car p)))
+    (setq expr-val (math-evaluate-expr expr)
+	  jacob-val (math-evaluate-expr jacob))
+    (or (and (math-constp expr-val)
+	     (math-constp jacob-val))
+	(math-reject-arg guess "*Newton's method encountered a singularity"))
+    (setq next (math-add guess (math-div (math-float (math-neg expr-val))
+					 (math-float jacob-val)))
+	  p guess p2 next)
+    (math-working "newton" next)
+    (while (and (setq p (cdr p) p2 (cdr p2))
+		(math-nearly-equal (car p) (car p2))))
+    (if p
+	(if (Math-lessp (math-abs-approx (math-sub next orig-guess))
+			limit)
+	    (math-newton-multi expr jacob n next orig-guess limit)
+	  (math-reject-arg nil "*Newton's method failed to converge"))
+      (list 'vec next expr-val)))
+)
+
+(defvar math-root-vars [(var DUMMY var-DUMMY)])
+
+(defun math-find-root (expr var guess root-widen)
+  (if (eq (car-safe expr) 'vec)
+      (let ((n (1- (length expr)))
+	    (calc-symbolic-mode nil)
+	    (var-DUMMY nil)
+	    (jacob (list 'vec))
+	    p p2 m row)
+	(or (eq (car-safe var) 'vec)
+	    (math-reject-arg var 'vectorp))
+	(or (= (length var) (1+ n))
+	    (math-dimension-error))
+	(setq expr (copy-sequence expr))
+	(while (>= n (length math-root-vars))
+	  (let ((symb (intern (concat "math-root-v"
+				      (int-to-string
+				       (length math-root-vars))))))
+	    (setq math-root-vars (vconcat math-root-vars
+					  (vector (list 'var symb symb))))))
+	(setq m -1)
+	(while (< (setq m (1+ m)) n)
+	  (set (nth 2 (aref math-root-vars m)) nil))
+	(setq m -1 p var)
+	(while (setq m (1+ m) p (cdr p))
+	  (or (eq (car-safe (car p)) 'var)
+	      (math-reject-arg var "*Expected a variable"))
+	  (setq p2 expr)
+	  (while (setq p2 (cdr p2))
+	    (setcar p2 (math-expr-subst (car p2) (car p)
+					(aref math-root-vars m)))))
+	(or (eq (car-safe guess) 'vec)
+	    (math-reject-arg guess 'vectorp))
+	(or (= (length guess) (1+ n))
+	    (math-dimension-error))
+	(setq guess (copy-sequence guess)
+	      p guess)
+	(while (setq p (cdr p))
+	  (or (Math-numberp (car guess))
+	      (math-reject-arg guess 'numberp))
+	  (setcar p (math-float (car p))))
+	(setq p expr)
+	(while (setq p (cdr p))
+	  (if (assq (car-safe (car p)) calc-tweak-eqn-table)
+	      (setcar p (math-sub (nth 1 (car p)) (nth 2 (car p)))))
+	  (setcar p (math-evaluate-expr (car p)))
+	  (setq row (list 'vec)
+		m -1)
+	  (while (< (setq m (1+ m)) n)
+	    (nconc row (list (math-evaluate-expr
+			      (or (calcFunc-deriv (car p)
+						  (aref math-root-vars m)
+						  nil t)
+				  (math-reject-arg
+				   expr
+				   "*Formulas must be differentiable"))))))
+	  (nconc jacob (list row)))
+	(setq m (math-abs-approx guess))
+	(math-newton-multi expr jacob n guess guess
+			   (if (math-zerop m) '(float 1 3) (math-mul m 10))))
+    (or (eq (car-safe var) 'var)
+	(math-reject-arg var "*Expected a variable"))
+    (or (math-expr-contains expr var)
+	(math-reject-arg expr "*Formula does not contain specified variable"))
+    (if (assq (car expr) calc-tweak-eqn-table)
+	(setq expr (math-sub (nth 1 expr) (nth 2 expr))))
+    (math-with-extra-prec 2
+      (setq expr (math-expr-subst expr var '(var DUMMY var-DUMMY)))
+      (let* ((calc-symbolic-mode nil)
+	     (var-DUMMY nil)
+	     (expr (math-evaluate-expr expr))
+	     (deriv (calcFunc-deriv expr '(var DUMMY var-DUMMY) nil t))
+	     low high vlow vhigh)
+	(and deriv (setq deriv (math-evaluate-expr deriv)))
+	(setq guess (math-float guess))
+	(if (and (math-numberp guess)
+		 deriv)
+	    (math-newton-root expr deriv guess guess
+			      (if (math-zerop guess) '(float 1 6)
+				(math-mul (math-abs-approx guess) 100)))
+	  (if (Math-realp guess)
+	      (setq low guess
+		    high guess
+		    var-DUMMY guess
+		    vlow (math-evaluate-expr expr)
+		    vhigh vlow
+		    root-widen 'point)
+	    (if (eq (car guess) 'intv)
+		(progn
+		  (or (math-constp guess) (math-reject-arg guess 'constp))
+		  (setq low (nth 2 guess)
+			high (nth 3 guess))
+		  (if (memq (nth 1 guess) '(0 1))
+		      (setq low (calcFunc-incr low 1 high)))
+		  (if (memq (nth 1 guess) '(0 2))
+		      (setq high (calcFunc-incr high -1 low)))
+		  (setq var-DUMMY low
+			vlow (math-evaluate-expr expr)
+			var-DUMMY high
+			vhigh (math-evaluate-expr expr)))
+	      (if (math-complexp guess)
+		  (math-reject-arg "*Complex root finder must have derivative")
+		(math-reject-arg guess 'realp))))
+	  (if (Math-zerop vlow)
+	      (list 'vec low vlow)
+	    (if (Math-zerop vhigh)
+		(list 'vec high vhigh)
+	      (if (and deriv (Math-numberp vlow) (Math-numberp vhigh))
+		  (math-newton-search-root expr deriv nil nil nil nil
+					   low vlow high vhigh)
+		(if (or (and (Math-posp vlow) (Math-posp vhigh))
+			(and (Math-negp vlow) (Math-negp vhigh))
+			(not (Math-numberp vlow))
+			(not (Math-numberp vhigh)))
+		    (math-search-root expr deriv low vlow high vhigh)
+		  (math-bisect-root expr low vlow high vhigh)))))))))
+)
+
+(defun calcFunc-root (expr var guess)
+  (math-find-root expr var guess nil)
+)
+
+(defun calcFunc-wroot (expr var guess)
+  (math-find-root expr var guess t)
+)
+
+
+
+
+;;; The following algorithms come from Numerical Recipes, chapter 10.
+
+(defun math-min-eval (expr a)
+  (if (Math-vectorp a)
+      (let ((m -1))
+	(while (setq m (1+ m) a (cdr a))
+	  (set (nth 2 (aref math-min-vars m)) (car a))))
+    (setq var-DUMMY a))
+  (setq a (math-evaluate-expr expr))
+  (if (Math-ratp a)
+      (math-float a)
+    (if (eq (car a) 'float)
+	a
+      (math-reject-arg a 'realp)))
+)
+
+
+;;; A bracket for a minimum is a < b < c where f(b) < f(a) and f(b) < f(c).
+
+;;; "mnbrak"
+(defun math-widen-min (expr a b)
+  (let ((done nil)
+	(iters 30)
+	incr c va vb vc u vu r q ulim bc ba qr)
+    (or b (setq b (math-mul a '(float 101 -2))))
+    (setq va (math-min-eval expr a)
+	  vb (math-min-eval expr b))
+    (if (math-lessp-float va vb)
+	(setq u a a b b u
+	      vu va va vb vb vu))
+    (setq c (math-add-float b (math-mul-float '(float 161803 -5)
+					      (math-sub-float b a)))
+	  vc (math-min-eval expr c))
+    (while (and (not done) (math-lessp-float vc vb))
+      (math-working "widen" (list 'intv 0 a c))
+      (if (= (setq iters (1- iters)) 0)
+	  (math-reject-arg nil (format "*Unable to find a %s near the interval"
+				       math-min-or-max)))
+      (setq bc (math-sub-float b c)
+	    ba (math-sub-float b a)
+	    r (math-mul-float ba (math-sub-float vb vc))
+	    q (math-mul-float bc (math-sub-float vb va))
+	    qr (math-sub-float q r))
+      (if (math-lessp-float (math-abs qr) '(float 1 -20))
+	  (setq qr (if (math-negp qr) '(float -1 -20) '(float 1 -20))))
+      (setq u (math-sub-float
+	       b
+	       (math-div-float (math-sub-float (math-mul-float bc q)
+					       (math-mul-float ba r))
+			       (math-mul-float '(float 2 0) qr)))
+	    ulim (math-add-float b (math-mul-float '(float -1 2) bc))
+	    incr (math-negp bc))
+      (if (if incr (math-lessp-float b u) (math-lessp-float u b))
+	  (if (if incr (math-lessp-float u c) (math-lessp-float c u))
+	      (if (math-lessp-float (setq vu (math-min-eval expr u)) vc)
+		  (setq a b  va vb
+			b u  vb vu
+			done t)
+		(if (math-lessp-float vb vu)
+		    (setq c u  vc vu
+			  done t)
+		  (setq u (math-add-float c (math-mul-float '(float -161803 -5)
+							    bc))
+			vu (math-min-eval expr u))))
+	    (if (if incr (math-lessp-float u ulim) (math-lessp-float ulim u))
+		(if (math-lessp-float (setq vu (math-min-eval expr u)) vc)
+		    (setq b c  vb vc
+			  c u  vc vu
+			  u (math-add-float c (math-mul-float
+					       '(float -161803 -5)
+					       (math-sub-float b c)))
+			  vu (math-min-eval expr u)))
+	      (setq u ulim
+		    vu (math-min-eval expr u))))
+	(setq u (math-add-float c (math-mul-float '(float -161803 -5)
+						  bc))
+	      vu (math-min-eval expr u)))
+      (setq a b  va vb
+	    b c  vb vc
+	    c u  vc vu))
+    (if (math-lessp-float a c)
+	(list a va b vb c vc)
+      (list c vc b vb a va)))
+)
+
+(defun math-narrow-min (expr a c intv)
+  (let ((xvals (list a c))
+	(yvals (list (math-min-eval expr a)
+		     (math-min-eval expr c)))
+	(levels 0)
+	(step (math-sub-float c a))
+	(found nil)
+	xp yp b)
+    (while (and (<= (setq levels (1+ levels)) 5)
+		(not found))
+      (setq xp xvals
+	    yp yvals
+	    step (math-mul-float step '(float 497 -3)))
+      (while (and (cdr xp) (not found))
+	(setq b (math-add-float (car xp) step))
+	(math-working "search" b)
+	(setcdr xp (cons b (cdr xp)))
+	(setcdr yp (cons (math-min-eval expr b) (cdr yp)))
+	(if (and (math-lessp-float (nth 1 yp) (car yp))
+		 (math-lessp-float (nth 1 yp) (nth 2 yp)))
+	    (setq found t)
+	  (setq xp (cdr xp)
+		yp (cdr yp))
+	  (if (and (cdr (cdr yp))
+		   (math-lessp-float (nth 1 yp) (car yp))
+		   (math-lessp-float (nth 1 yp) (nth 2 yp)))
+	      (setq found t)
+	    (setq xp (cdr xp)
+		  yp (cdr yp))))))
+    (if found
+	(list (car xp) (car yp)
+	      (nth 1 xp) (nth 1 yp)
+	      (nth 2 xp) (nth 2 yp))
+      (or (if (math-lessp-float (car yvals) (nth 1 yvals))
+	      (and (memq (nth 1 intv) '(2 3))
+		   (let ((min (car yvals)))
+		     (while (and (setq yvals (cdr yvals))
+				 (math-lessp-float min (car yvals))))
+		     (and (not yvals)
+			  (list (nth 2 intv) min))))
+	    (and (memq (nth 1 intv) '(1 3))
+		 (setq yvals (nreverse yvals))
+		 (let ((min (car yvals)))
+		   (while (and (setq yvals (cdr yvals))
+			       (math-lessp-float min (car yvals))))
+		   (and (not yvals)
+			(list (nth 3 intv) min)))))
+	  (math-reject-arg nil (format "*Unable to find a %s in the interval"
+				       math-min-or-max)))))
+)
+
+;;; "brent"
+(defun math-brent-min (expr prec a va x vx b vb)
+  (let ((iters (+ 20 (* 5 prec)))
+	(w x)
+	(vw vx)
+	(v x)
+	(vv vx)
+	(tol (list 'float 1 (- -1 prec)))
+	(zeps (list 'float 1 (- -5 prec)))
+	(e '(float 0 0))
+	u vu xm tol1 tol2 etemp p q r xv xw)
+    (while (progn
+	     (setq xm (math-mul-float '(float 5 -1)
+				      (math-add-float a b))
+		   tol1 (math-add-float
+			 zeps
+			 (math-mul-float tol (math-abs x)))
+		   tol2 (math-mul-float tol1 '(float 2 0)))
+	     (math-lessp-float (math-sub-float tol2
+					       (math-mul-float
+						'(float 5 -1)
+						(math-sub-float b a)))
+			       (math-abs (math-sub-float x xm))))
+      (if (= (setq iters (1- iters)) 0)
+	  (math-reject-arg nil (format "*Unable to converge on a %s"
+				       math-min-or-max)))
+      (math-working "brent" x)
+      (if (math-lessp-float (math-abs e) tol1)
+	  (setq e (if (math-lessp-float x xm)
+		      (math-sub-float b x)
+		    (math-sub-float a x))
+		d (math-mul-float '(float 381966 -6) e))
+	(setq xw (math-sub-float x w)
+	      r (math-mul-float xw (math-sub-float vx vv))
+	      xv (math-sub-float x v)
+	      q (math-mul-float xv (math-sub-float vx vw))
+	      p (math-sub-float (math-mul-float xv q)
+				(math-mul-float xw r))
+	      q (math-mul-float '(float 2 0) (math-sub-float q r)))
+	(if (math-posp q)
+	    (setq p (math-neg-float p))
+	  (setq q (math-neg-float q)))
+	(setq etemp e
+	      e d)
+	(if (and (math-lessp-float (math-abs p)
+				   (math-abs (math-mul-float
+					      '(float 5 -1)
+					      (math-mul-float q etemp))))
+		 (math-lessp-float (math-mul-float
+				    q (math-sub-float a x)) p)
+		 (math-lessp-float p (math-mul-float
+				      q (math-sub-float b x))))
+	    (progn
+	      (setq d (math-div-float p q)
+		    u (math-add-float x d))
+	      (if (or (math-lessp-float (math-sub-float u a) tol2)
+		      (math-lessp-float (math-sub-float b u) tol2))
+		  (setq d (if (math-lessp-float xm x)
+			      (math-neg-float tol1)
+			    tol1))))
+	  (setq e (if (math-lessp-float x xm)
+		      (math-sub-float b x)
+		    (math-sub-float a x))
+		d (math-mul-float '(float 381966 -6) e))))
+      (setq u (math-add-float x
+			      (if (math-lessp-float (math-abs d) tol1)
+				  (if (math-negp d)
+				      (math-neg-float tol1)
+				    tol1)
+				d))
+	    vu (math-min-eval expr u))
+      (if (math-lessp-float vx vu)
+	  (progn
+	    (if (math-lessp-float u x)
+		(setq a u)
+	      (setq b u))
+	    (if (or (equal w x)
+		    (not (math-lessp-float vw vu)))
+		(setq v w  vv vw
+		      w u  vw vu)
+	      (if (or (equal v x)
+		      (equal v w)
+		      (not (math-lessp-float vv vu)))
+		  (setq v u  vv vu))))
+	(if (math-lessp-float u x)
+	    (setq b x)
+	  (setq a x))
+	(setq v w  vv vw
+	      w x  vw vx
+	      x u  vx vu)))
+    (list 'vec x vx))
+)
+
+;;; "powell"
+(defun math-powell-min (expr n guesses prec)
+  (let* ((f1dim (math-line-min-func expr n))
+	 (xi (calcFunc-idn 1 n))
+	 (p (cons 'vec (mapcar 'car guesses)))
+	 (pt p)
+	 (ftol (list 'float 1 (- prec)))
+	 (fret (math-min-eval expr p))
+	 fp ptt fptt xit i ibig del diff res)
+    (while (progn
+	     (setq fp fret
+		   ibig 0
+		   del '(float 0 0)
+		   i 0)
+	     (while (<= (setq i (1+ i)) n)
+	       (setq fptt fret
+		     res (math-line-min f1dim p
+					(math-mat-col xi i)
+					n prec)
+		     p (let ((calc-internal-prec prec))
+			 (math-normalize (car res)))
+		     fret (nth 2 res)
+		     diff (math-abs (math-sub-float fptt fret)))
+	       (if (math-lessp-float del diff)
+		   (setq del diff
+			 ibig i)))
+	     (math-lessp-float
+	      (math-mul-float ftol
+			      (math-add-float (math-abs fp)
+					      (math-abs fret)))
+	      (math-mul-float '(float 2 0)
+			      (math-abs (math-sub-float fp
+							fret)))))
+      (setq ptt (math-sub (math-mul '(float 2 0) p) pt)
+	    xit (math-sub p pt)
+	    pt p
+	    fptt (math-min-eval expr ptt))
+      (if (and (math-lessp-float fptt fp)
+	       (math-lessp-float
+		(math-mul-float
+		 (math-mul-float '(float 2 0)
+				 (math-add-float
+				  (math-sub-float fp
+						  (math-mul-float '(float 2 0)
+								  fret))
+				  fptt))
+		 (math-sqr-float (math-sub-float
+				  (math-sub-float fp fret) del)))
+		(math-mul-float del
+				(math-sqr-float (math-sub-float fp fptt)))))
+	  (progn
+	    (setq res (math-line-min f1dim p xit n prec)
+		  p (car res)
+		  fret (nth 2 res)
+		  i 0)
+	    (while (<= (setq i (1+ i)) n)
+	      (setcar (nthcdr ibig (nth i xi))
+		      (nth i (nth 1 res)))))))
+    (list 'vec p fret))
+)
+
+(defun math-line-min-func (expr n)
+  (let ((m -1))
+    (while (< (setq m (1+ m)) n)
+      (set (nth 2 (aref math-min-vars m))
+	   (list '+
+		 (list '*
+		       '(var DUMMY var-DUMMY)
+		       (list 'calcFunc-mrow '(var line-xi line-xi) (1+ m)))
+		 (list 'calcFunc-mrow '(var line-p line-p) (1+ m)))))
+    (math-evaluate-expr expr))
+)
+
+(defun math-line-min (f1dim line-p line-xi n prec)
+  (let* ((var-DUMMY nil)
+	 (expr (math-evaluate-expr f1dim))
+	 (params (math-widen-min expr '(float 0 0) '(float 1 0)))
+	 (res (apply 'math-brent-min expr prec params))
+	 (xi (math-mul (nth 1 res) line-xi)))
+    (list (math-add line-p xi) xi (nth 2 res)))
+)
+
+
+(defvar math-min-vars [(var DUMMY var-DUMMY)])
+
+(defun math-find-minimum (expr var guess min-widen)
+  (let* ((calc-symbolic-mode nil)
+	 (n 0)
+	 (var-DUMMY nil)
+	 (isvec (math-vectorp var))
+	 g guesses)
+    (or (math-vectorp var)
+	(setq var (list 'vec var)))
+    (or (math-vectorp guess)
+	(setq guess (list 'vec guess)))
+    (or (= (length var) (length guess))
+	(math-dimension-error))
+    (while (setq var (cdr var) guess (cdr guess))
+      (or (eq (car-safe (car var)) 'var)
+	  (math-reject-arg (car vg) "*Expected a variable"))
+      (or (math-expr-contains expr (car var))
+	  (math-reject-arg (car var)
+			   "*Formula does not contain specified variable"))
+      (while (>= (1+ n) (length math-min-vars))
+	(let ((symb (intern (concat "math-min-v"
+				    (int-to-string
+				     (length math-min-vars))))))
+	  (setq math-min-vars (vconcat math-min-vars
+				       (vector (list 'var symb symb))))))
+      (set (nth 2 (aref math-min-vars n)) nil)
+      (set (nth 2 (aref math-min-vars (1+ n))) nil)
+      (if (math-complexp (car guess))
+	  (setq expr (math-expr-subst expr
+				      (car var)
+				      (list '+ (aref math-min-vars n)
+					    (list '*
+						  (aref math-min-vars (1+ n))
+						  '(cplx 0 1))))
+		guesses (let ((g (math-float (math-complex (car guess)))))
+			  (cons (list (nth 2 g) nil nil)
+				(cons (list (nth 1 g) nil nil t)
+				      guesses)))
+		n (+ n 2))
+	(setq expr (math-expr-subst expr
+				    (car var)
+				    (aref math-min-vars n))
+	      guesses (cons (if (math-realp (car guess))
+				(list (math-float (car guess)) nil nil)
+			      (if (and (eq (car-safe (car guess)) 'intv)
+				       (math-constp (car guess)))
+				  (list (math-mul
+					 (math-add (nth 2 (car guess))
+						   (nth 3 (car guess)))
+					 '(float 5 -1))
+					(math-float (nth 2 (car guess)))
+					(math-float (nth 3 (car guess)))
+					(car guess))
+				(math-reject-arg (car guess) 'realp)))
+			    guesses)
+	      n (1+ n))))
+    (setq guesses (nreverse guesses)
+	  expr (math-evaluate-expr expr))
+    (if (= n 1)
+	(let* ((params (if (nth 1 (car guesses))
+			   (if min-widen
+			       (math-widen-min expr
+					       (nth 1 (car guesses))
+					       (nth 2 (car guesses)))
+			     (math-narrow-min expr
+					      (nth 1 (car guesses))
+					      (nth 2 (car guesses))
+					      (nth 3 (car guesses))))
+			 (math-widen-min expr
+					 (car (car guesses))
+					 nil)))
+	       (prec calc-internal-prec)
+	       (res (if (cdr (cdr params))
+			(math-with-extra-prec (+ calc-internal-prec 2)
+			  (apply 'math-brent-min expr prec params))
+		      (cons 'vec params))))
+	  (if isvec
+	      (list 'vec (list 'vec (nth 1 res)) (nth 2 res))
+	    res))
+      (let* ((prec calc-internal-prec)
+	     (res (math-with-extra-prec (+ calc-internal-prec 2)
+		    (math-powell-min expr n guesses prec)))
+	     (p (nth 1 res))
+	     (vec (list 'vec)))
+	(while (setq p (cdr p))
+	  (if (nth 3 (car guesses))
+	      (progn
+		(nconc vec (list (math-normalize
+				  (list 'cplx (car p) (nth 1 p)))))
+		(setq p (cdr p)
+		      guesses (cdr guesses)))
+	    (nconc vec (list (car p))))
+	  (setq guesses (cdr guesses)))
+	(if isvec
+	    (list 'vec vec (nth 2 res))
+	  (list 'vec (nth 1 vec) (nth 2 res))))))
+)
+(setq math-min-or-max "minimum")
+
+(defun calcFunc-minimize (expr var guess)
+  (let ((calc-internal-prec (max (/ calc-internal-prec 2) 3))
+	(math-min-or-max "minimum"))
+    (math-find-minimum (math-normalize expr)
+		       (math-normalize var)
+		       (math-normalize guess) nil))
+)
+
+(defun calcFunc-wminimize (expr var guess)
+  (let ((calc-internal-prec (max (/ calc-internal-prec 2) 3))
+	(math-min-or-max "minimum"))
+    (math-find-minimum (math-normalize expr)
+		       (math-normalize var)
+		       (math-normalize guess) t))
+)
+
+(defun calcFunc-maximize (expr var guess)
+  (let* ((calc-internal-prec (max (/ calc-internal-prec 2) 3))
+	 (math-min-or-max "maximum")
+	 (res (math-find-minimum (math-normalize (math-neg expr))
+				 (math-normalize var)
+				 (math-normalize guess) nil)))
+    (list 'vec (nth 1 res) (math-neg (nth 2 res))))
+)
+
+(defun calcFunc-wmaximize (expr var guess)
+  (let* ((calc-internal-prec (max (/ calc-internal-prec 2) 3))
+	 (math-min-or-max "maximum")
+	 (res (math-find-minimum (math-normalize (math-neg expr))
+				 (math-normalize var)
+				 (math-normalize guess) t)))
+    (list 'vec (nth 1 res) (math-neg (nth 2 res))))
+)
+
+
+
+
+;;; The following algorithms come from Numerical Recipes, chapter 3.
+
+(defun calcFunc-polint (data x)
+  (or (math-matrixp data) (math-reject-arg data 'matrixp))
+  (or (= (length data) 3)
+      (math-reject-arg data "*Wrong number of data rows"))
+  (or (> (length (nth 1 data)) 2)
+      (math-reject-arg data "*Too few data points"))
+  (if (and (math-vectorp x) (or (math-constp x) math-expand-formulas))
+      (cons 'vec (mapcar (function (lambda (x) (calcFunc-polint data x)))
+			 (cdr x)))
+    (or (math-objectp x) math-expand-formulas (math-reject-arg x 'objectp))
+    (math-with-extra-prec 2
+      (cons 'vec (math-poly-interp (cdr (nth 1 data)) (cdr (nth 2 data)) x
+				   nil))))
+)
+(put 'calcFunc-polint 'math-expandable t)
+
+
+(defun calcFunc-ratint (data x)
+  (or (math-matrixp data) (math-reject-arg data 'matrixp))
+  (or (= (length data) 3)
+      (math-reject-arg data "*Wrong number of data rows"))
+  (or (> (length (nth 1 data)) 2)
+      (math-reject-arg data "*Too few data points"))
+  (if (and (math-vectorp x) (or (math-constp x) math-expand-formulas))
+      (cons 'vec (mapcar (function (lambda (x) (calcFunc-ratint data x)))
+			 (cdr x)))
+    (or (math-objectp x) math-expand-formulas (math-reject-arg x 'objectp))
+    (math-with-extra-prec 2
+      (cons 'vec (math-poly-interp (cdr (nth 1 data)) (cdr (nth 2 data)) x
+				   (cdr (cdr (cdr (nth 1 data))))))))
+)
+(put 'calcFunc-ratint 'math-expandable t)
+
+
+(defun math-poly-interp (xa ya x ratp)
+  (let ((n (length xa))
+	(dif nil)
+	(ns nil)
+	(xax nil)
+	(c (copy-sequence ya))
+	(d (copy-sequence ya))
+	(i 0)
+	(m 0)
+	y dy (xp xa) xpm cp dp temp)
+    (while (<= (setq i (1+ i)) n)
+      (setq xax (cons (math-sub (car xp) x) xax)
+	    xp (cdr xp)
+	    temp (math-abs (car xax)))
+      (if (or (null dif) (math-lessp temp dif))
+	  (setq dif temp
+		ns i)))
+    (setq xax (nreverse xax)
+	  ns (1- ns)
+	  y (nth ns ya))
+    (if (math-zerop dif)
+	(list y 0)
+      (while (< (setq m (1+ m)) n)
+	(setq i 0
+	      xp xax
+	      xpm (nthcdr m xax)
+	      cp c
+	      dp d)
+	(while (<= (setq i (1+ i)) (- n m))
+	  (if ratp
+	      (let ((t2 (math-div (math-mul (car xp) (car dp)) (car xpm))))
+		(setq temp (math-div (math-sub (nth 1 cp) (car dp))
+				     (math-sub t2 (nth 1 cp))))
+		(setcar dp (math-mul (nth 1 cp) temp))
+		(setcar cp (math-mul t2 temp)))
+	    (if (math-equal (car xp) (car xpm))
+		(math-reject-arg (cons 'vec xa) "*Duplicate X values"))
+	    (setq temp (math-div (math-sub (nth 1 cp) (car dp))
+				 (math-sub (car xp) (car xpm))))
+	    (setcar dp (math-mul (car xpm) temp))
+	    (setcar cp (math-mul (car xp) temp)))
+	  (setq cp (cdr cp)
+		dp (cdr dp)
+		xp (cdr xp)
+		xpm (cdr xpm)))
+	(if (< (+ ns ns) (- n m))
+	    (setq dy (nth ns c))
+	  (setq ns (1- ns)
+		dy (nth ns d)))
+	(setq y (math-add y dy)))
+      (list y dy)))
+)
+
+
+
+;;; The following algorithms come from Numerical Recipes, chapter 4.
+
+(defun calcFunc-ninteg (expr var lo hi)
+  (setq lo (math-evaluate-expr lo)
+	hi (math-evaluate-expr hi))
+  (or (math-numberp lo) (math-infinitep lo) (math-reject-arg lo 'numberp))
+  (or (math-numberp hi) (math-infinitep hi) (math-reject-arg hi 'numberp))
+  (if (math-lessp hi lo)
+      (math-neg (calcFunc-ninteg expr var hi lo))
+    (setq expr (math-expr-subst expr var '(var DUMMY var-DUMMY)))
+    (let ((var-DUMMY nil)
+	  (calc-symbolic-mode nil)
+	  (calc-prefer-frac nil)
+	  (sum 0))
+      (setq expr (math-evaluate-expr expr))
+      (if (equal lo '(neg (var inf var-inf)))
+	  (let ((thi (if (math-lessp hi '(float -2 0))
+			 hi '(float -2 0))))
+	    (setq sum (math-ninteg-romberg
+		       'math-ninteg-midpoint expr
+			 (math-float lo) (math-float thi) 'inf)
+		  lo thi)))
+      (if (equal hi '(var inf var-inf))
+	  (let ((tlo (if (math-lessp '(float 2 0) lo)
+			 lo '(float 2 0))))
+	    (setq sum (math-add sum
+				(math-ninteg-romberg
+				 'math-ninteg-midpoint expr
+				 (math-float tlo) (math-float hi) 'inf))
+		  hi tlo)))
+      (or (math-equal lo hi)
+	  (setq sum (math-add sum
+			      (math-ninteg-romberg
+			       'math-ninteg-midpoint expr
+			       (math-float lo) (math-float hi) nil))))
+      sum))
+)
+
+
+;;; Open Romberg method; "qromo" in section 4.4.
+(defun math-ninteg-romberg (func expr lo hi mode)    
+  (let ((curh '(float 1 0))
+	(h nil)
+	(s nil)
+	(j 0)
+	(ss nil)
+	(prec calc-internal-prec)
+	(integ-temp nil))
+    (math-with-extra-prec 2
+      ;; Limit on "j" loop must be 14 or less to keep "it" from overflowing.
+      (or (while (and (null ss) (<= (setq j (1+ j)) 8))
+	    (setq s (nconc s (list (funcall func expr lo hi mode)))
+		  h (nconc h (list curh)))
+	    (if (>= j 3)
+		(let ((res (math-poly-interp h s '(float 0 0) nil)))
+		  (if (math-lessp (math-abs (nth 1 res))
+				  (calcFunc-scf (math-abs (car res))
+						(- prec)))
+		      (setq math-ninteg-convergence j
+			    ss (car res)))))
+	    (if (>= j 5)
+		(setq s (cdr s)
+		      h (cdr h)))
+	    (setq curh (math-div-float curh '(float 9 0))))
+	  ss
+	  (math-reject-arg nil (format "*Integral failed to converge")))))
+)
+
+
+(defun math-ninteg-evaluate (expr x mode)
+  (if (eq mode 'inf)
+      (setq x (math-div '(float 1 0) x)))
+  (let* ((var-DUMMY x)
+	 (res (math-evaluate-expr expr)))
+    (or (Math-numberp res)
+	(math-reject-arg res "*Integrand does not evaluate to a number"))
+    (if (eq mode 'inf)
+	(setq res (math-mul res (math-sqr x))))
+    res)
+)
+
+
+(defun math-ninteg-midpoint (expr lo hi mode)    ; uses "integ-temp"
+  (if (eq mode 'inf)
+      (let ((math-infinite-mode t) temp)
+	(setq temp (math-div 1 lo)
+	      lo (math-div 1 hi)
+	      hi temp)))
+  (if integ-temp
+      (let* ((it3 (* 3 (car integ-temp)))
+	     (math-working-step-2 (* 2 (car integ-temp)))
+	     (math-working-step 0)
+	     (range (math-sub hi lo))
+	     (del (math-div range (math-float it3)))
+	     (del2 (math-add del del))
+	     (del3 (math-add del del2))
+	     (x (math-add lo (math-mul '(float 5 -1) del)))
+	     (sum '(float 0 0))
+	     (j 0) temp)
+	(while (<= (setq j (1+ j)) (car integ-temp))
+	  (setq math-working-step (1+ math-working-step)
+		temp (math-ninteg-evaluate expr x mode)
+		math-working-step (1+ math-working-step)
+		sum (math-add sum (math-add temp (math-ninteg-evaluate
+						  expr (math-add x del2)
+						  mode)))
+		x (math-add x del3)))
+	(setq integ-temp (list it3
+			       (math-add (math-div (nth 1 integ-temp)
+						   '(float 3 0))
+					 (math-mul sum del)))))
+    (setq integ-temp (list 1 (math-mul
+			      (math-sub hi lo)
+			      (math-ninteg-evaluate
+			       expr
+			       (math-mul (math-add lo hi) '(float 5 -1))
+			       mode)))))
+  (nth 1 integ-temp)
+)
+
+
+
+
+
+;;; The following algorithms come from Numerical Recipes, chapter 14.
+
+(setq math-dummy-vars [(var DUMMY var-DUMMY)])
+(setq math-dummy-counter 0)
+
+(defun math-dummy-variable ()
+  (if (= math-dummy-counter (length math-dummy-vars))
+      (let ((symb (intern (format "math-dummy-%d" math-dummy-counter))))
+	(setq math-dummy-vars (vconcat math-dummy-vars
+				       (vector (list 'var symb symb))))))
+  (set (nth 2 (aref math-dummy-vars math-dummy-counter)) nil)
+  (prog1
+      (aref math-dummy-vars math-dummy-counter)
+    (setq math-dummy-counter (1+ math-dummy-counter)))
+)
+
+
+
+(defun calcFunc-fit (expr vars &optional coefs data)
+  (let ((math-in-fit 10))
+    (math-with-extra-prec 2
+      (math-general-fit expr vars coefs data nil)))
+)
+
+(defun calcFunc-efit (expr vars &optional coefs data)
+  (let ((math-in-fit 10))
+    (math-with-extra-prec 2
+      (math-general-fit expr vars coefs data 'sdev)))
+)
+
+(defun calcFunc-xfit (expr vars &optional coefs data)
+  (let ((math-in-fit 10))
+    (math-with-extra-prec 2
+      (math-general-fit expr vars coefs data 'full)))
+)
+
+(defun math-general-fit (expr vars coefs data mode)
+  (let ((calc-simplify-mode nil)
+	(math-dummy-counter math-dummy-counter)
+	(math-in-fit 1)
+	(extended (eq mode 'full))
+	(first-coef math-dummy-counter)
+	first-var
+	(plain-expr expr)
+	orig-expr
+	have-sdevs need-chisq chisq
+	(x-funcs nil)
+	(y-filter nil)
+	y-dummy
+	(coef-filters nil)
+	new-coefs
+	(xy-values nil)
+	(weights nil)
+	(var-YVAL nil) (var-YVALX nil)
+	covar beta
+	n nn m mm v dummy p)
+
+    ;; Validate and parse arguments.
+    (or data
+	(if coefs
+	    (setq data coefs
+		  coefs nil)
+	  (if (math-vectorp expr)
+	      (if (memq (length expr) '(3 4))
+		  (setq data vars
+			vars (nth 2 expr)
+			coefs (nth 3 expr)
+			expr (nth 1 expr))
+		(math-dimension-error))
+	    (setq data vars
+		  vars nil
+		  coefs nil))))
+    (or (math-matrixp data) (math-reject-arg data 'matrixp))
+    (setq v (1- (length data))
+	  n (1- (length (nth 1 data))))
+    (or (math-vectorp vars) (null vars)
+	(setq vars (list 'vec vars)))
+    (or (math-vectorp coefs) (null coefs)
+	(setq coefs (list 'vec coefs)))
+    (or coefs
+	(setq coefs (cons 'vec (math-all-vars-but expr vars))))
+    (or vars
+	(if (<= (1- (length coefs)) v)
+	    (math-reject-arg coefs "*Not enough variables in model")
+	  (setq coefs (copy-sequence coefs))
+	  (let ((p (nthcdr (- (length coefs) v
+			      (if (eq (car-safe expr) 'calcFunc-eq) 1 0))
+			   coefs)))
+	    (setq vars (cons 'vec (cdr p)))
+	    (setcdr p nil))))
+    (or (= (1- (length vars)) v)
+	(= (length vars) v)
+	(math-reject-arg vars "*Number of variables does not match data"))
+    (setq m (1- (length coefs)))
+    (if (< m 1)
+	(math-reject-arg coefs "*Need at least one parameter"))
+
+    ;; Rewrite expr in terms of fitparam and fitvar, make into an equation.
+    (setq p coefs)
+    (while (setq p (cdr p))
+      (or (eq (car-safe (car p)) 'var)
+	  (math-reject-arg (car p) "*Expected a variable"))
+      (setq dummy (math-dummy-variable)
+	    expr (math-expr-subst expr (car p)
+				  (list 'calcFunc-fitparam
+					(- math-dummy-counter first-coef)))))
+    (setq first-var math-dummy-counter
+	  p vars)
+    (while (setq p (cdr p))
+      (or (eq (car-safe (car p)) 'var)
+	  (math-reject-arg (car p) "*Expected a variable"))
+      (setq dummy (math-dummy-variable)
+	    expr (math-expr-subst expr (car p)
+				  (list 'calcFunc-fitvar
+					(- math-dummy-counter first-var)))))
+    (if (< math-dummy-counter (+ first-var v))
+	(setq dummy (math-dummy-variable))) ; dependent variable may be unnamed
+    (setq y-dummy dummy
+	  orig-expr expr)
+    (or (eq (car-safe expr) 'calcFunc-eq)
+	(setq expr (list 'calcFunc-eq (list 'calcFunc-fitvar v) expr)))
+
+    (let ((calc-symbolic-mode nil))
+
+      ;; Apply rewrites to put expr into a linear-like form.
+      (setq expr (math-evaluate-expr expr)
+	    expr (math-rewrite (list 'calcFunc-fitmodel expr)
+			       '(var FitRules var-FitRules))
+	    math-in-fit 2
+	    expr (math-evaluate-expr expr))
+      (or (and (eq (car-safe expr) 'calcFunc-fitsystem)
+	       (= (length expr) 4)
+	       (math-vectorp (nth 2 expr))
+	       (math-vectorp (nth 3 expr))
+	       (> (length (nth 2 expr)) 1)
+	       (= (length (nth 3 expr)) (1+ m)))
+	  (math-reject-arg plain-expr "*Model expression is too complex"))
+      (setq y-filter (nth 1 expr)
+	    x-funcs (vconcat (cdr (nth 2 expr)))
+	    coef-filters (nth 3 expr)
+	    mm (length x-funcs))
+      (if (equal y-filter y-dummy)
+	  (setq y-filter nil))
+
+      ;; Build the (square) system of linear equations to be solved.
+      (setq beta (cons 'vec (make-list mm 0))
+	    covar (cons 'vec (mapcar 'copy-sequence (make-list mm beta))))
+      (let* ((ptrs (vconcat (cdr data)))
+	     (isigsq 1)
+	     (xvals (make-vector mm 0))
+	     (i 0)
+	     j k xval yval sigmasqr wt covj covjk covk betaj lud)
+	(while (<= (setq i (1+ i)) n)
+
+	  ;; Assign various independent variables for this data point.
+	  (setq j 0
+		sigmasqr nil)
+	  (while (< j v)
+	    (aset ptrs j (cdr (aref ptrs j)))
+	    (setq xval (car (aref ptrs j)))
+	    (if (= j (1- v))
+		(if sigmasqr
+		    (progn
+		      (if (eq (car-safe xval) 'sdev)
+			  (setq sigmasqr (math-add (math-sqr (nth 2 xval))
+						   sigmasqr)
+				xval (nth 1 xval)))
+		      (if y-filter
+			  (setq xval (math-make-sdev xval
+						     (math-sqrt sigmasqr))))))
+	      (if (eq (car-safe xval) 'sdev)
+		  (setq sigmasqr (math-add (math-sqr (nth 2 xval))
+					   (or sigmasqr 0))
+			xval (nth 1 xval))))
+	    (set (nth 2 (aref math-dummy-vars (+ first-var j))) xval)
+	    (setq j (1+ j)))
+
+	  ;; Compute Y value for this data point.
+	  (if y-filter
+	      (setq yval (math-evaluate-expr y-filter))
+	    (setq yval (symbol-value (nth 2 y-dummy))))
+	  (if (eq (car-safe yval) 'sdev)
+	      (setq sigmasqr (math-sqr (nth 2 yval))
+		    yval (nth 1 yval)))
+	  (if (= i 1)
+	      (setq have-sdevs sigmasqr
+		    need-chisq (or extended
+				   (and (eq mode 'sdev) (not have-sdevs)))))
+	  (if have-sdevs
+	      (if sigmasqr
+		  (progn
+		    (setq isigsq (math-div 1 sigmasqr))
+		    (if need-chisq
+			(setq weights (cons isigsq weights))))
+		(math-reject-arg yval "*Mixed error forms and plain numbers"))
+	    (if sigmasqr
+		(math-reject-arg yval "*Mixed error forms and plain numbers")))
+
+	  ;; Compute X values for this data point and update covar and beta.
+	  (if (eq (car-safe xval) 'sdev)
+	      (set (nth 2 y-dummy) (nth 1 xval)))
+	  (setq j 0
+		covj covar
+		betaj beta)
+	  (while (< j mm)
+	    (setq wt (math-evaluate-expr (aref x-funcs j)))
+	    (aset xvals j wt)
+	    (setq wt (math-mul wt isigsq)
+		  betaj (cdr betaj)
+		  covjk (car (setq covj (cdr covj)))
+		  k 0)
+	    (while (<= k j)
+	      (setq covjk (cdr covjk))
+	      (setcar covjk (math-add (car covjk)
+				      (math-mul wt (aref xvals k))))
+	      (setq k (1+ k)))
+	    (setcar betaj (math-add (car betaj) (math-mul wt yval)))
+	    (setq j (1+ j)))
+	  (if need-chisq
+	      (setq xy-values (cons (append xvals (list yval)) xy-values))))
+
+	;; Fill in symmetric half of covar matrix.
+	(setq j 0
+	      covj covar)
+	(while (< j (1- mm))
+	  (setq k j
+		j (1+ j)
+		covjk (nthcdr j (car (setq covj (cdr covj))))
+		covk (nthcdr j covar))
+	  (while (< (setq k (1+ k)) mm)
+	    (setq covjk (cdr covjk)
+		  covk (cdr covk))
+	    (setcar covjk (nth j (car covk))))))
+
+      ;; Solve the linear system.
+      (if mode
+	  (progn
+	    (setq covar (math-matrix-inv-raw covar))
+	    (if covar
+		(setq beta (math-mul covar beta))
+	      (if (math-zerop (math-abs beta))
+		  (setq covar (calcFunc-diag 0 (1- (length beta))))
+		(math-reject-arg orig-expr "*Singular matrix")))
+	    (or (math-vectorp covar)
+		(setq covar (list 'vec (list 'vec covar)))))
+	(setq beta (math-div beta covar)))
+
+      ;; Compute chi-square statistic if necessary.
+      (if need-chisq
+	  (let (bp xp sum)
+	    (setq chisq 0)
+	    (while xy-values
+	      (setq bp beta
+		    xp (car xy-values)
+		    sum 0)
+	      (while (setq bp (cdr bp))
+		(setq sum (math-add sum (math-mul (car bp) (car xp)))
+		      xp (cdr xp)))
+	      (setq sum (math-sqr (math-sub (car xp) sum)))
+	      (if weights (setq sum (math-mul sum (car weights))))
+	      (setq chisq (math-add chisq sum)
+		    weights (cdr weights)
+		    xy-values (cdr xy-values)))))
+
+      ;; Convert coefficients back into original terms.
+      (setq new-coefs (copy-sequence beta))
+      (let* ((bp new-coefs)
+	     (cp covar)
+	     (sigdat 1)
+	     (math-in-fit 3)
+	     (j 0))
+	(and mode (not have-sdevs)
+	     (setq sigdat (if (<= n mm)
+			      0
+			    (math-div chisq (- n mm)))))
+	(if mode
+	    (while (setq bp (cdr bp))
+	      (setcar bp (math-make-sdev
+			  (car bp)
+			  (math-sqrt (math-mul (nth (setq j (1+ j))
+						    (car (setq cp (cdr cp))))
+					       sigdat))))))
+	(setq new-coefs (math-evaluate-expr coef-filters))
+	(if calc-fit-to-trail
+	    (let ((bp new-coefs)
+		  (cp coefs)
+		  (vec nil))
+	      (while (setq bp (cdr bp) cp (cdr cp))
+		(setq vec (cons (list 'calcFunc-eq (car cp) (car bp)) vec)))
+	      (setq calc-fit-to-trail (cons 'vec (nreverse vec)))))))
+
+    ;; Substitute best-fit coefficients back into original formula.
+    (setq expr (math-multi-subst
+		orig-expr
+		(let ((n v)
+		      (vec nil))
+		  (while (>= n 1)
+		    (setq vec (cons (list 'calcFunc-fitvar n) vec)
+			  n (1- n)))
+		  (setq n m)
+		  (while (>= n 1)
+		    (setq vec (cons (list 'calcFunc-fitparam n) vec)
+			  n (1- n)))
+		  vec)
+		(append (cdr new-coefs) (cdr vars))))
+
+    ;; Package the result.
+    (math-normalize
+     (if extended
+	 (list 'vec expr beta covar
+	       (let ((p coef-filters)
+		     (n 0))
+		 (while (and (setq n (1+ n) p (cdr p))
+			     (eq (car-safe (car p)) 'calcFunc-fitdummy)
+			     (eq (nth 1 (car p)) n)))
+		 (if p
+		     coef-filters
+		   (list 'vec)))
+	       chisq
+	       (if (and have-sdevs (> n mm))
+		   (list 'calcFunc-utpc chisq (- n mm))
+		 '(var nan var-nan)))
+       expr)))
+)
+
+(setq math-in-fit 0)
+(setq calc-fit-to-trail nil)
+
+(defun calcFunc-fitvar (x)
+  (if (>= math-in-fit 2)
+      (progn
+	(setq x (aref math-dummy-vars (+ first-var x -1)))
+	(or (calc-var-value (nth 2 x)) x))
+    (math-reject-arg x))
+)
+
+(defun calcFunc-fitparam (x)
+  (if (>= math-in-fit 2)
+      (progn
+	(setq x (aref math-dummy-vars (+ first-coef x -1)))
+	(or (calc-var-value (nth 2 x)) x))
+    (math-reject-arg x))
+)
+
+(defun calcFunc-fitdummy (x)
+  (if (= math-in-fit 3)
+      (nth x new-coefs)
+    (math-reject-arg x))
+)
+
+(defun calcFunc-hasfitvars (expr)
+  (if (Math-primp expr)
+      0
+    (if (eq (car expr) 'calcFunc-fitvar)
+	(nth 1 expr)
+      (apply 'max (mapcar 'calcFunc-hasfitvars (cdr expr)))))
+)
+
+(defun calcFunc-hasfitparams (expr)
+  (if (Math-primp expr)
+      0
+    (if (eq (car expr) 'calcFunc-fitparam)
+	(nth 1 expr)
+      (apply 'max (mapcar 'calcFunc-hasfitparams (cdr expr)))))
+)
+
+
+(defun math-all-vars-but (expr but)
+  (let* ((vars (math-all-vars-in expr))
+	 (p but))
+    (while p
+      (setq vars (delq (assoc (car-safe p) vars) vars)
+	    p (cdr p)))
+    (sort (mapcar 'car vars)
+	  (function (lambda (x y) (string< (nth 1 x) (nth 1 y))))))
+)
+
+(defun math-all-vars-in (expr)
+  (let ((vars nil)
+	found)
+    (math-all-vars-rec expr)
+    vars)
+)
+
+(defun math-all-vars-rec (expr)
+  (if (Math-primp expr)
+      (if (eq (car-safe expr) 'var)
+	  (or (math-const-var expr)
+	      (if (setq found (assoc expr vars))
+		  (setcdr found (1+ (cdr found)))
+		(setq vars (cons (cons expr 1) vars)))))
+    (while (setq expr (cdr expr))
+      (math-all-vars-rec (car expr))))
+)
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/calccomp.el	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,1755 @@
+;; Calculator for GNU Emacs, part II [calc-comp.el]
+;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+;; Written by Dave Gillespie, daveg@synaptics.com.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY.  No author or distributor
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing.  Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License.   A copy of this license is
+;; supposed to have been given to you along with GNU Emacs so you
+;; can know your rights and responsibilities.  It should be in a
+;; file named COPYING.  Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+
+
+
+;; This file is autoloaded from calc-ext.el.
+(require 'calc-ext)
+
+(require 'calc-macs)
+
+(defun calc-Need-calc-comp () nil)
+
+
+;;; A "composition" has one of the following forms:
+;;;
+;;;    "string"              A literal string
+;;;
+;;;    (horiz C1 C2 ...)     Horizontally abutted sub-compositions
+;;;
+;;;    (set LEVEL OFF)       Set left margin + offset for line-break level
+;;;    (break LEVEL)         A potential line-break point
+;;;
+;;;    (vleft N C1 C2 ...)   Vertically stacked, left-justified sub-comps
+;;;    (vcent N C1 C2 ...)   Vertically stacked, centered sub-comps
+;;;    (vright N C1 C2 ...)  Vertically stacked, right-justified sub-comps
+;;;                          N specifies baseline of the stack, 0=top line.
+;;;
+;;;    (supscr C1 C2)        Composition C1 with superscript C2
+;;;    (subscr C1 C2)        Composition C1 with subscript C2
+;;;    (rule X)              Horizontal line of X, full width of enclosing comp
+;;;
+;;;    (tag X C)             Composition C corresponds to sub-expression X
+
+(defun math-compose-expr (a prec)
+  (let ((math-compose-level (1+ math-compose-level)))
+    (cond
+     ((or (and (eq a math-comp-selected) a)
+	  (and math-comp-tagged
+	       (not (eq math-comp-tagged a))))
+      (let ((math-comp-selected nil))
+	(and math-comp-tagged (setq math-comp-tagged a))
+	(list 'tag a (math-compose-expr a prec))))
+     ((and (not (consp a)) (not (integerp a)))
+      (concat "'" (prin1-to-string a)))
+     ((math-scalarp a)
+      (if (or (eq (car-safe a) 'frac)
+	      (and (nth 1 calc-frac-format) (Math-integerp a)))
+	  (if (memq calc-language '(tex eqn math maple c fortran pascal))
+	      (let ((aa (math-adjust-fraction a))
+		    (calc-frac-format nil))
+		(math-compose-expr (list '/
+					 (if (memq calc-language '(c fortran))
+					     (math-float (nth 1 aa))
+					   (nth 1 aa))
+					 (nth 2 aa)) prec))
+	    (if (and (eq calc-language 'big)
+		     (= (length (car calc-frac-format)) 1))
+		(let* ((aa (math-adjust-fraction a))
+		       (calc-frac-format nil)
+		       (math-radix-explicit-format nil)
+		       (c (list 'horiz
+				(if (math-negp (nth 1 aa))
+				    "- " "")
+				(list 'vcent 1
+				      (math-format-number
+				       (math-abs (nth 1 aa)))
+				      '(rule ?-)
+				      (math-format-number (nth 2 aa))))))
+		  (if (= calc-number-radix 10)
+		      c
+		    (list 'horiz "(" c
+			  (list 'subscr ")"
+				(int-to-string calc-number-radix)))))
+	      (math-format-number a)))
+	(if (not (eq calc-language 'big))
+	    (math-format-number a prec)
+	  (if (memq (car-safe a) '(cplx polar))
+	      (if (math-zerop (nth 2 a))
+		  (math-compose-expr (nth 1 a) prec)
+		(list 'horiz "("
+		      (math-compose-expr (nth 1 a) 0)
+		      (if (eq (car a) 'cplx) ", " "; ")
+		      (math-compose-expr (nth 2 a) 0) ")"))
+	    (if (or (= calc-number-radix 10)
+		    (not (Math-realp a))
+		    (and calc-group-digits
+			 (not (assoc calc-group-char '((",") (" "))))))
+		(math-format-number a prec)
+	      (let ((s (math-format-number a prec))
+		    (c nil))
+		(while (string-match (if (> calc-number-radix 14)
+					 "\\([0-9]+\\)#\\([0-9a-zA-Z., ]+\\)"
+				       "\\([0-9]+\\)#\\([0-9a-dA-D., ]+\\)")
+				     s)
+		  (setq c (nconc c (list (substring s 0 (match-beginning 0))
+					 (list 'subscr
+					       (math-match-substring s 2)
+					       (math-match-substring s 1))))
+			s (substring s (match-end 0))))
+		(if (string-match
+		     "\\*\\([0-9.]+\\)\\^\\(-?[0-9]+\\)\\()?\\)\\'" s)
+		    (setq s (list 'horiz
+				  (substring s 0 (match-beginning 0)) " "
+				  (list 'supscr
+					(math-match-substring s 1)
+					(math-match-substring s 2))
+				  (math-match-substring s 3))))
+		(if c (cons 'horiz (nconc c (list s))) s)))))))
+     ((and (get (car a) 'math-compose-forms)
+	   (not (eq calc-language 'unform))
+	   (let ((comps (get (car a) 'math-compose-forms))
+		 temp temp2)
+	     (or (and (setq temp (assq calc-language comps))
+		      (or (and (setq temp2 (assq (1- (length a)) (cdr temp)))
+			       (setq temp (apply (cdr temp2) (cdr a)))
+			       (math-compose-expr temp prec))
+			  (and (setq temp2 (assq nil (cdr temp)))
+			       (funcall (cdr temp2) a))))
+		 (and (setq temp (assq nil comps))
+		      (or (and (setq temp2 (assq (1- (length a)) (cdr temp)))
+			       (setq temp (apply (cdr temp2) (cdr a)))
+			       (math-compose-expr temp prec))
+			  (and (setq temp2 (assq nil (cdr temp)))
+			       (funcall (cdr temp2) a))))))))
+     ((eq (car a) 'vec)
+      (let* ((left-bracket (if calc-vector-brackets
+			       (substring calc-vector-brackets 0 1) ""))
+	     (right-bracket (if calc-vector-brackets
+				(substring calc-vector-brackets 1 2) ""))
+	     (inner-brackets (memq 'R calc-matrix-brackets))
+	     (outer-brackets (memq 'O calc-matrix-brackets))
+	     (row-commas (memq 'C calc-matrix-brackets))
+	     (comma-spc (or calc-vector-commas " "))
+	     (comma (or calc-vector-commas ""))
+	     (vector-prec (if (or (and calc-vector-commas
+				       (math-vector-no-parens a))
+				  (memq 'P calc-matrix-brackets)) 0 1000))
+	     (just (cond ((eq calc-matrix-just 'right) 'vright)
+			 ((eq calc-matrix-just 'center) 'vcent)
+			 (t 'vleft)))
+	     (break calc-break-vectors))
+	(if (and (memq calc-language '(nil big))
+		 (not calc-break-vectors)
+		 (math-matrixp a) (not (math-matrixp (nth 1 a)))
+		 (or calc-full-vectors
+		     (and (< (length a) 7) (< (length (nth 1 a)) 7))
+		     (progn (setq break t) nil)))
+	    (if (progn
+		  (setq vector-prec (if (or (and calc-vector-commas
+						 (math-vector-no-parens
+						  (nth 1 a)))
+					    (memq 'P calc-matrix-brackets))
+					0 1000))
+		  (= (length a) 2))
+		(list 'horiz
+		      (concat left-bracket left-bracket " ")
+		      (math-compose-vector (cdr (nth 1 a)) (concat comma " ")
+					   vector-prec)
+		      (concat " " right-bracket right-bracket))
+	      (let* ((rows (1- (length a)))
+		     (cols (1- (length (nth 1 a))))
+		     (base (/ (1- rows) 2))
+		     (calc-language 'flat))
+		(append '(horiz)
+			(list (append '(vleft)
+				      (list base)
+				      (list (concat (and outer-brackets
+							 (concat left-bracket
+								 " "))
+						    (and inner-brackets
+							 (concat left-bracket
+								 " "))))
+				      (make-list (1- rows)
+						 (concat (and outer-brackets
+							      "  ")
+							 (and inner-brackets
+							      (concat
+							       left-bracket
+							       " "))))))
+			(math-compose-matrix (cdr a) 1 cols base)
+			(list (append '(vleft)
+				      (list base)
+				      (make-list (1- rows)
+						 (if inner-brackets
+						     (concat " "
+							     right-bracket
+							     (and row-commas
+								  comma))
+						   (if (and outer-brackets
+							    row-commas)
+						       ";" "")))
+				      (list (concat
+					     (and inner-brackets
+						  (concat " "
+							  right-bracket))
+					     (and outer-brackets
+						  (concat
+						   " "
+						   right-bracket)))))))))
+	  (if (and calc-display-strings
+		   (cdr a)
+		   (math-vector-is-string a))
+	      (math-vector-to-string a t)
+	    (if (and break (cdr a)
+		     (not (eq calc-language 'flat)))
+		(let* ((full (or calc-full-vectors (< (length a) 7)))
+		       (rows (if full (1- (length a)) 5))
+		       (base (/ (1- rows) 2))
+		       (just 'vleft)
+		       (calc-break-vectors nil))
+		  (list 'horiz
+			(cons 'vleft (cons base
+					   (math-compose-rows
+					    (cdr a)
+					    (if full rows 3) t)))))
+	      (if (or calc-full-vectors (< (length a) 7))
+		  (if (and (eq calc-language 'tex)
+			   (math-matrixp a))
+		      (append '(horiz "\\matrix{ ")
+			      (math-compose-tex-matrix (cdr a))
+			      '(" }"))
+		    (if (and (eq calc-language 'eqn)
+			     (math-matrixp a))
+			(append '(horiz "matrix { ")
+				(math-compose-eqn-matrix
+				 (cdr (math-transpose a)))
+				'("}"))
+		      (if (and (eq calc-language 'maple)
+			       (math-matrixp a))
+			  (list 'horiz
+				"matrix("
+				left-bracket
+				(math-compose-vector (cdr a) (concat comma " ")
+						     vector-prec)
+				right-bracket
+				")")
+			(list 'horiz
+			      left-bracket
+			      (math-compose-vector (cdr a) (concat comma " ")
+						   vector-prec)
+			      right-bracket))))
+		(list 'horiz
+		      left-bracket
+		      (math-compose-vector (list (nth 1 a) (nth 2 a) (nth 3 a))
+					   (concat comma " ") vector-prec)
+		      comma (if (eq calc-language 'tex) " \\ldots" " ...")
+		      comma " "
+		      (list 'break math-compose-level)
+		      (math-compose-expr (nth (1- (length a)) a)
+					 (if (equal comma "") 1000 0))
+		      right-bracket)))))))
+     ((eq (car a) 'incomplete)
+      (if (cdr (cdr a))
+	  (cond ((eq (nth 1 a) 'vec)
+		 (list 'horiz "["
+		       (math-compose-vector (cdr (cdr a)) ", " 0)
+		       " ..."))
+		((eq (nth 1 a) 'cplx)
+		 (list 'horiz "("
+		       (math-compose-vector (cdr (cdr a)) ", " 0)
+		       ", ..."))
+		((eq (nth 1 a) 'polar)
+		 (list 'horiz "("
+		       (math-compose-vector (cdr (cdr a)) "; " 0)
+		       "; ..."))
+		((eq (nth 1 a) 'intv)
+		 (list 'horiz
+		       (if (memq (nth 2 a) '(0 1)) "(" "[")
+		       (math-compose-vector (cdr (cdr (cdr a))) " .. " 0)
+		       " .. ..."))
+		(t (format "%s" a)))
+	(cond ((eq (nth 1 a) 'vec) "[ ...")
+	      ((eq (nth 1 a) 'intv)
+	       (if (memq (nth 2 a) '(0 1)) "( ..." "[ ..."))
+	      (t "( ..."))))
+     ((eq (car a) 'var)
+      (let ((v (rassq (nth 2 a) math-expr-variable-mapping)))
+	(if v
+	    (symbol-name (car v))
+	  (if (and (eq calc-language 'tex)
+		   calc-language-option
+		   (not (= calc-language-option 0))
+		   (string-match "\\`[a-zA-Z][a-zA-Z0-9]+\\'"
+				 (symbol-name (nth 1 a))))
+	      (format "\\hbox{%s}" (symbol-name (nth 1 a)))
+	    (if (and math-compose-hash-args
+		     (let ((p calc-arg-values))
+		       (setq v 1)
+		       (while (and p (not (equal (car p) a)))
+			 (setq p (and (eq math-compose-hash-args t) (cdr p))
+			       v (1+ v)))
+		       p))
+		(if (eq math-compose-hash-args 1)
+		    "#"
+		  (format "#%d" v))
+	      (if (memq calc-language '(c fortran pascal maple))
+		  (math-to-underscores (symbol-name (nth 1 a)))
+		(if (and (eq calc-language 'eqn)
+			 (string-match ".'\\'" (symbol-name (nth 2 a))))
+		    (math-compose-expr
+		     (list 'calcFunc-Prime
+			   (list
+			    'var
+			    (intern (substring (symbol-name (nth 1 a)) 0 -1))
+			    (intern (substring (symbol-name (nth 2 a)) 0 -1))))
+		     prec)
+		  (symbol-name (nth 1 a)))))))))
+     ((eq (car a) 'intv)
+      (list 'horiz
+	    (if (eq calc-language 'maple) ""
+	      (if (memq (nth 1 a) '(0 1)) "(" "["))
+	    (math-compose-expr (nth 2 a) 0)
+	    (if (eq calc-language 'tex) " \\ldots "
+	      (if (eq calc-language 'eqn) " ... " " .. "))
+	    (math-compose-expr (nth 3 a) 0)
+	    (if (eq calc-language 'maple) ""
+	      (if (memq (nth 1 a) '(0 2)) ")" "]"))))
+     ((eq (car a) 'date)
+      (if (eq (car calc-date-format) 'X)
+	  (math-format-date a)
+	(concat "<" (math-format-date a) ">")))
+     ((and (eq (car a) 'calcFunc-subscr) (cdr (cdr a))
+	   (memq calc-language '(c pascal fortran maple)))
+      (let ((args (cdr (cdr a))))
+	(while (and (memq calc-language '(pascal fortran))
+		    (eq (car-safe (nth 1 a)) 'calcFunc-subscr))
+	  (setq args (append (cdr (cdr (nth 1 a))) args)
+		a (nth 1 a)))
+	(list 'horiz
+	      (math-compose-expr (nth 1 a) 1000)
+	      (if (eq calc-language 'fortran) "(" "[")
+	      (math-compose-vector args ", " 0)
+	      (if (eq calc-language 'fortran) ")" "]"))))
+     ((and (eq (car a) 'calcFunc-subscr) (= (length a) 3)
+	   (eq calc-language 'big))
+      (let* ((a1 (math-compose-expr (nth 1 a) 1000))
+	     (calc-language 'flat)
+	     (a2 (math-compose-expr (nth 2 a) 0)))
+	(if (or (eq (car-safe a1) 'subscr)
+		(and (eq (car-safe a1) 'tag)
+		     (eq (car-safe (nth 2 a1)) 'subscr)
+		     (setq a1 (nth 2 a1))))
+	    (list 'subscr
+		  (nth 1 a1)
+		  (list 'horiz
+			(nth 2 a1)
+			", "
+			a2))
+	  (list 'subscr a1 a2))))
+     ((and (eq (car a) 'calcFunc-subscr) (= (length a) 3)
+	   (eq calc-language 'math))
+      (list 'horiz
+	    (math-compose-expr (nth 1 a) 1000)
+	    "[["
+	    (math-compose-expr (nth 2 a) 0)
+	    "]]"))
+     ((and (eq (car a) 'calcFunc-sqrt)
+	   (eq calc-language 'tex))
+      (list 'horiz
+	    "\\sqrt{"
+	    (math-compose-expr (nth 1 a) 0)
+	    "}"))
+     ((and nil (eq (car a) 'calcFunc-sqrt)
+	   (eq calc-language 'eqn))
+      (list 'horiz
+	    "sqrt {"
+	    (math-compose-expr (nth 1 a) -1)
+	    "}"))
+     ((and (eq (car a) '^)
+	   (eq calc-language 'big))
+      (list 'supscr
+	    (if (or (math-looks-negp (nth 1 a))
+		    (memq (car-safe (nth 1 a)) '(^ / frac calcFunc-sqrt))
+		    (and (eq (car-safe (nth 1 a)) 'cplx)
+			 (math-negp (nth 1 (nth 1 a)))
+			 (eq (nth 2 (nth 1 a)) 0)))
+		(list 'horiz "(" (math-compose-expr (nth 1 a) 0) ")")
+	      (math-compose-expr (nth 1 a) 201))
+	    (let ((calc-language 'flat)
+		  (calc-number-radix 10))
+	      (math-compose-expr (nth 2 a) 0))))
+     ((and (eq (car a) '/)
+	   (eq calc-language 'big))
+      (let ((a1 (let ((calc-language (if (memq (car-safe (nth 1 a)) '(/ frac))
+					 'flat 'big)))
+		  (math-compose-expr (nth 1 a) 0)))
+	    (a2 (let ((calc-language (if (memq (car-safe (nth 2 a)) '(/ frac))
+					 'flat 'big)))
+		  (math-compose-expr (nth 2 a) 0))))
+	(list 'vcent
+	      (math-comp-height a1)
+	      a1 '(rule ?-) a2)))
+     ((and (memq (car a) '(calcFunc-sum calcFunc-prod))
+	   (eq calc-language 'tex)
+	   (= (length a) 5))
+      (list 'horiz (if (eq (car a) 'calcFunc-sum) "\\sum" "\\prod")
+	    "_{" (math-compose-expr (nth 2 a) 0)
+	    "=" (math-compose-expr (nth 3 a) 0)
+	    "}^{" (math-compose-expr (nth 4 a) 0)
+	    "}{" (math-compose-expr (nth 1 a) 0) "}"))
+     ((and (eq (car a) 'calcFunc-lambda)
+	   (> (length a) 2)
+	   (memq calc-language '(nil flat big)))
+      (let ((p (cdr a))
+	    (ap calc-arg-values)
+	    (math-compose-hash-args (if (= (length a) 3) 1 t)))
+	(while (and (cdr p) (equal (car p) (car ap)))
+	  (setq p (cdr p) ap (cdr ap)))
+	(append '(horiz "<")
+		(if (cdr p)
+		    (list (math-compose-vector
+			   (nreverse (cdr (reverse (cdr a)))) ", " 0)
+			  " : ")
+		  nil)
+		(list (math-compose-expr (nth (1- (length a)) a) 0)
+		      ">"))))
+     ((and (eq (car a) 'calcFunc-string)
+	   (= (length a) 2)
+	   (math-vectorp (nth 1 a))
+	   (math-vector-is-string (nth 1 a)))
+      (if (eq calc-language 'unform)
+	  (concat "string(" (math-vector-to-string (nth 1 a) t) ")")
+	(math-vector-to-string (nth 1 a) nil)))
+     ((and (eq (car a) 'calcFunc-bstring)
+	   (= (length a) 2)
+	   (math-vectorp (nth 1 a))
+	   (math-vector-is-string (nth 1 a)))
+      (if (eq calc-language 'unform)
+	  (concat "bstring(" (math-vector-to-string (nth 1 a) t) ")")
+	(let ((c nil)
+	      (s (math-vector-to-string (nth 1 a) nil))
+	      p)
+	  (while (string-match "[^ ] +[^ ]" s)
+	    (setq p (1- (match-end 0))
+		  c (cons (list 'break math-compose-level)
+			  (cons (substring s 0 p)
+				c))
+		  s (substring s p)))
+	  (setq c (nreverse (cons s c)))
+	  (or (= prec -123)
+	      (setq c (cons (list 'set math-compose-level 2) c)))
+	  (cons 'horiz c))))
+     ((and (eq (car a) 'calcFunc-cprec)
+	   (not (eq calc-language 'unform))
+	   (= (length a) 3)
+	   (integerp (nth 2 a)))
+      (let ((c (math-compose-expr (nth 1 a) -1)))
+	(if (> prec (nth 2 a))
+	    (if (eq calc-language 'tex)
+		(list 'horiz "\\left( " c " \\right)")
+	      (if (eq calc-language 'eqn)
+		  (list 'horiz "{left ( " c " right )}")
+		(list 'horiz "(" c ")")))
+	  c)))
+     ((and (eq (car a) 'calcFunc-choriz)
+	   (not (eq calc-language 'unform))
+	   (memq (length a) '(2 3 4))
+	   (math-vectorp (nth 1 a))
+	   (if (integerp (nth 2 a))
+	       (or (null (nth 3 a))
+		   (and (math-vectorp (nth 3 a))
+			(math-vector-is-string (nth 3 a))))
+	     (or (null (nth 2 a))
+		 (and (math-vectorp (nth 2 a))
+		      (math-vector-is-string (nth 2 a))))))
+      (let* ((cprec (and (integerp (nth 2 a)) (nth 2 a)))
+	     (sep (nth (if cprec 3 2) a))
+	     (bprec nil))
+	(if sep
+	    (math-compose-vector (cdr (nth 1 a))
+				 (math-vector-to-string sep nil)
+				 (or cprec prec))
+	  (cons 'horiz (mapcar (function
+				(lambda (x)
+				  (if (eq (car-safe x) 'calcFunc-bstring)
+				      (prog1
+					  (math-compose-expr
+					   x (or bprec cprec prec))
+					(setq bprec -123))
+				    (math-compose-expr x (or cprec prec)))))
+			       (cdr (nth 1 a)))))))
+     ((and (memq (car a) '(calcFunc-cvert calcFunc-clvert calcFunc-crvert))
+	   (not (eq calc-language 'unform))
+	   (memq (length a) '(2 3))
+	   (math-vectorp (nth 1 a))
+	   (or (null (nth 2 a))
+	       (integerp (nth 2 a))))
+      (let* ((base 0)
+	     (v 0)
+	     (prec (or (nth 2 a) prec))
+	     (c (mapcar (function
+			 (lambda (x)
+			   (let ((b nil) (cc nil) a d)
+			     (if (and (memq (car-safe x) '(calcFunc-cbase
+							   calcFunc-ctbase
+							   calcFunc-cbbase))
+				      (memq (length x) '(1 2)))
+				 (setq b (car x)
+				       x (nth 1 x)))
+			     (if (and (eq (car-safe x) 'calcFunc-crule)
+				      (memq (length x) '(1 2))
+				      (or (null (nth 1 x))
+					  (and (math-vectorp (nth 1 x))
+					       (= (length (nth 1 x)) 2)
+					       (math-vector-is-string
+						(nth 1 x)))
+					  (and (natnump (nth 1 x))
+					       (<= (nth 1 x) 255))))
+				 (setq cc (list
+					   'rule
+					   (if (math-vectorp (nth 1 x))
+					       (aref (math-vector-to-string
+						      (nth 1 x) nil) 0)
+					     (or (nth 1 x) ?-))))
+			       (or (and (memq (car-safe x) '(calcFunc-cvspace
+							     calcFunc-ctspace
+							     calcFunc-cbspace))
+					(memq (length x) '(2 3))
+					(eq (nth 1 x) 0))
+				   (null x)
+				   (setq cc (math-compose-expr x prec))))
+			     (setq a (if cc (math-comp-ascent cc) 0)
+				   d (if cc (math-comp-descent cc) 0))
+			     (if (eq b 'calcFunc-cbase)
+				 (setq base (+ v a -1))
+			       (if (eq b 'calcFunc-ctbase)
+				   (setq base v)
+				 (if (eq b 'calcFunc-cbbase)
+				     (setq base (+ v a d -1)))))
+			     (setq v (+ v a d))
+			     cc)))
+			(cdr (nth 1 a)))))
+	(setq c (delq nil c))
+	(if c
+	    (cons (if (eq (car a) 'calcFunc-cvert) 'vcent
+		    (if (eq (car a) 'calcFunc-clvert) 'vleft 'vright))
+		  (cons base c))
+	  " ")))
+     ((and (memq (car a) '(calcFunc-csup calcFunc-csub))
+	   (not (eq calc-language 'unform))
+	   (memq (length a) '(3 4))
+	   (or (null (nth 3 a))
+	       (integerp (nth 3 a))))
+      (list (if (eq (car a) 'calcFunc-csup) 'supscr 'subscr)
+	    (math-compose-expr (nth 1 a) (or (nth 3 a) 0))
+	    (math-compose-expr (nth 2 a) 0)))
+     ((and (eq (car a) 'calcFunc-cflat)
+	   (not (eq calc-language 'unform))
+	   (memq (length a) '(2 3))
+	   (or (null (nth 2 a))
+	       (integerp (nth 2 a))))
+      (let ((calc-language (if (memq calc-language '(nil big))
+			       'flat calc-language)))
+	(math-compose-expr (nth 1 a) (or (nth 2 a) 0))))
+     ((and (eq (car a) 'calcFunc-cspace)
+	   (memq (length a) '(2 3))
+	   (natnump (nth 1 a)))
+      (if (nth 2 a)
+	  (cons 'horiz (make-list (nth 1 a)
+				  (if (and (math-vectorp (nth 2 a))
+					   (math-vector-is-string (nth 2 a)))
+				      (math-vector-to-string (nth 2 a) nil)
+				    (math-compose-expr (nth 2 a) 0))))
+	(make-string (nth 1 a) ?\ )))
+     ((and (memq (car a) '(calcFunc-cvspace calcFunc-ctspace calcFunc-cbspace))
+	   (memq (length a) '(2 3))
+	   (natnump (nth 1 a)))
+      (if (= (nth 1 a) 0)
+	  ""
+	(let* ((c (if (nth 2 a)
+		      (if (and (math-vectorp (nth 2 a))
+			       (math-vector-is-string (nth 2 a)))
+			  (math-vector-to-string (nth 2 a) nil)
+			(math-compose-expr (nth 2 a) 0))
+		    " "))
+	       (ca (math-comp-ascent c))
+	       (cd (math-comp-descent c)))
+	  (cons 'vleft
+		(cons (if (eq (car a) 'calcFunc-ctspace)
+			  (1- ca)
+			(if (eq (car a) 'calcFunc-cbspace)
+			    (+ (* (1- (nth 1 a)) (+ ca cd)) (1- ca))
+			  (/ (1- (* (nth 1 a) (+ ca cd))) 2)))
+		      (make-list (nth 1 a) c))))))
+     ((and (eq (car a) 'calcFunc-evalto)
+	   (setq calc-any-evaltos t)
+	   (memq calc-language '(tex eqn))
+	   (= math-compose-level (if math-comp-tagged 2 1))
+	   (= (length a) 3))
+      (list 'horiz
+	    (if (eq calc-language 'tex) "\\evalto " "evalto ")
+	    (math-compose-expr (nth 1 a) 0)
+	    (if (eq calc-language 'tex) " \\to " " -> ")
+	    (math-compose-expr (nth 2 a) 0)))
+     (t
+      (let ((op (and (not (eq calc-language 'unform))
+		     (if (and (eq (car a) 'calcFunc-if) (= (length a) 4))
+			 (assoc "?" math-expr-opers)
+		       (math-assq2 (car a) math-expr-opers)))))
+	(cond ((and op
+		    (or (= (length a) 3) (eq (car a) 'calcFunc-if))
+		    (/= (nth 3 op) -1))
+	       (cond
+		((> prec (or (nth 4 op) (min (nth 2 op) (nth 3 op))))
+		 (if (and (eq calc-language 'tex)
+			  (not (math-tex-expr-is-flat a)))
+		     (if (eq (car-safe a) '/)
+			 (list 'horiz "{" (math-compose-expr a -1) "}")
+		       (list 'horiz "\\left( "
+			     (math-compose-expr a -1)
+			     " \\right)"))
+		   (if (eq calc-language 'eqn)
+		       (if (or (eq (car-safe a) '/)
+			       (= (/ prec 100) 9))
+			   (list 'horiz "{" (math-compose-expr a -1) "}")
+			 (if (math-tex-expr-is-flat a)
+			     (list 'horiz "( " (math-compose-expr a -1) " )")
+			   (list 'horiz "{left ( "
+				 (math-compose-expr a -1)
+				 " right )}")))
+		     (list 'horiz "(" (math-compose-expr a 0) ")"))))
+		((and (eq calc-language 'tex)
+		      (memq (car a) '(/ calcFunc-choose calcFunc-evalto))
+		      (>= prec 0))
+		 (list 'horiz "{" (math-compose-expr a -1) "}"))
+		((eq (car a) 'calcFunc-if)
+		 (list 'horiz
+		       (math-compose-expr (nth 1 a) (nth 2 op))
+		       " ? "
+		       (math-compose-expr (nth 2 a) 0)
+		       " : "
+		       (math-compose-expr (nth 3 a) (nth 3 op))))
+		(t
+		 (let* ((math-comp-tagged (and math-comp-tagged
+					       (not (math-primp a))
+					       math-comp-tagged))
+			(setlev (if (= prec (min (nth 2 op) (nth 3 op)))
+				    (progn
+				      (setq math-compose-level
+					    (1- math-compose-level))
+				      nil)
+				  math-compose-level))
+			(lhs (math-compose-expr (nth 1 a) (nth 2 op)))
+			(rhs (math-compose-expr (nth 2 a) (nth 3 op))))
+		   (and (equal (car op) "^")
+			(eq (math-comp-first-char lhs) ?-)
+			(setq lhs (list 'horiz "(" lhs ")")))
+		   (and (eq calc-language 'tex)
+			(or (equal (car op) "^") (equal (car op) "_"))
+			(not (and (stringp rhs) (= (length rhs) 1)))
+			(setq rhs (list 'horiz "{" rhs "}")))
+		   (or (and (eq (car a) '*)
+			    (or (null calc-language)
+				(assoc "2x" math-expr-opers))
+			    (let* ((prevt (math-prod-last-term (nth 1 a)))
+				   (nextt (math-prod-first-term (nth 2 a)))
+				   (prevc (or (math-comp-last-char lhs)
+					      (and (memq (car-safe prevt)
+							 '(^ calcFunc-subscr
+							     calcFunc-sqrt
+							     frac))
+						   (eq calc-language 'big)
+						   ?0)))
+				   (nextc (or (math-comp-first-char rhs)
+					      (and (memq (car-safe nextt)
+							 '(calcFunc-sqrt
+							   calcFunc-sum
+							   calcFunc-prod
+							   calcFunc-integ))
+						   (eq calc-language 'big)
+						   ?0))))
+			      (and prevc nextc
+				   (or (and (>= nextc ?a) (<= nextc ?z))
+				       (and (>= nextc ?A) (<= nextc ?Z))
+				       (and (>= nextc ?0) (<= nextc ?9))
+				       (memq nextc '(?. ?_ ?#
+							?\( ?\[ ?\{))
+				       (and (eq nextc ?\\)
+					    (not (string-match
+						  "\\`\\\\left("
+						  (math-comp-first-string
+						   rhs)))))
+				   (not (and (eq (car-safe prevt) 'var)
+					     (eq nextc ?\()))
+				   (list 'horiz
+					 (list 'set setlev 1)
+					 lhs
+					 (list 'break math-compose-level)
+					 " "
+					 rhs))))
+		       (list 'horiz
+			     (list 'set setlev 1)
+			     lhs
+			     (list 'break math-compose-level)
+			     (if (or (equal (car op) "^")
+				     (equal (car op) "_")
+				     (equal (car op) "**")
+				     (and (equal (car op) "*")
+					  (math-comp-last-char lhs)
+					  (math-comp-first-char rhs))
+				     (and (equal (car op) "/")
+					  (math-num-integerp (nth 1 a))
+					  (math-integerp (nth 2 a))))
+				 (car op)
+			       (if (and (eq calc-language 'big)
+					(equal (car op) "=>"))
+				   "  =>  "
+				 (concat " " (car op) " ")))
+			     rhs))))))
+	      ((and op (= (length a) 2) (= (nth 3 op) -1))
+	       (cond
+		((or (> prec (or (nth 4 op) (nth 2 op)))
+		     (and (not (eq (assoc (car op) math-expr-opers) op))
+			  (> prec 0)))   ; don't write x% + y
+		 (if (and (eq calc-language 'tex)
+			  (not (math-tex-expr-is-flat a)))
+		     (list 'horiz "\\left( "
+			   (math-compose-expr a -1)
+			   " \\right)")
+		   (if (eq calc-language 'eqn)
+		       (if (= (/ prec 100) 9)
+			   (list 'horiz "{" (math-compose-expr a -1) "}")
+			 (if (math-tex-expr-is-flat a)
+			     (list 'horiz "{( " (math-compose-expr a -1) " )}")
+			   (list 'horiz "{left ( "
+				 (math-compose-expr a -1)
+				 " right )}")))
+		     (list 'horiz "(" (math-compose-expr a 0) ")"))))
+		(t
+		 (let ((lhs (math-compose-expr (nth 1 a) (nth 2 op))))
+		 (list 'horiz
+		       lhs
+		       (if (or (> (length (car op)) 1)
+			       (not (math-comp-is-flat lhs)))
+			   (concat " " (car op))
+			 (car op)))))))
+	      ((and op (= (length a) 2) (= (nth 2 op) -1))
+	       (cond
+		((eq (nth 3 op) 0)
+		 (let ((lr (and (eq calc-language 'tex)
+				(not (math-tex-expr-is-flat (nth 1 a))))))
+		   (list 'horiz
+			 (if lr "\\left" "")
+			 (if (string-match "\\`u\\([^a-zA-Z]\\)\\'" (car op))
+			     (substring (car op) 1)
+			   (car op))
+			 (if (or lr (> (length (car op)) 2)) " " "")
+			 (math-compose-expr (nth 1 a) -1)
+			 (if (or lr (> (length (car op)) 2)) " " "")
+			 (if lr "\\right" "")
+			 (car (nth 1 (memq op math-expr-opers))))))
+		((> prec (or (nth 4 op) (nth 3 op)))
+		 (if (and (eq calc-language 'tex)
+			  (not (math-tex-expr-is-flat a)))
+		     (list 'horiz "\\left( "
+			   (math-compose-expr a -1)
+			   " \\right)")
+		   (if (eq calc-language 'eqn)
+		       (if (= (/ prec 100) 9)
+			   (list 'horiz "{" (math-compose-expr a -1) "}")
+			 (if (math-tex-expr-is-flat a)
+			     (list 'horiz "{( " (math-compose-expr a -1) " )}")
+			   (list 'horiz "{left ( "
+				 (math-compose-expr a -1)
+				 " right )}")))
+		     (list 'horiz "(" (math-compose-expr a 0) ")"))))
+		(t
+		 (let ((rhs (math-compose-expr (nth 1 a) (nth 3 op))))
+		   (list 'horiz
+			 (let ((ops (if (string-match "\\`u\\([^a-zA-Z]\\)\\'"
+						      (car op))
+					(substring (car op) 1)
+				      (car op))))
+			   (if (or (> (length ops) 1)
+				   (not (math-comp-is-flat rhs)))
+			       (concat ops " ")
+			     ops))
+			 rhs)))))
+	      ((and (eq calc-language 'big)
+		    (setq op (get (car a) 'math-compose-big))
+		    (funcall op a prec)))
+	      ((and (setq op (assq calc-language
+				   '( ( nil . math-compose-normal )
+				      ( flat . math-compose-normal )
+				      ( big . math-compose-normal )
+				      ( c . math-compose-c )
+				      ( pascal . math-compose-pascal )
+				      ( fortran . math-compose-fortran )
+				      ( tex . math-compose-tex )
+				      ( eqn . math-compose-eqn )
+				      ( math . math-compose-math )
+				      ( maple . math-compose-maple ))))
+		    (setq op (get (car a) (cdr op)))
+		    (funcall op a prec)))
+	      (t
+	       (let* ((func (car a))
+		      (func2 (assq func '(( mod . calcFunc-makemod )
+					  ( sdev . calcFunc-sdev )
+					  ( + . calcFunc-add )
+					  ( - . calcFunc-sub )
+					  ( * . calcFunc-mul )
+					  ( / . calcFunc-div )
+					  ( % . calcFunc-mod )
+					  ( ^ . calcFunc-pow )
+					  ( neg . calcFunc-neg )
+					  ( | . calcFunc-vconcat ))))
+		      left right args)
+		 (if func2
+		     (setq func (cdr func2)))
+		 (if (setq func2 (rassq func math-expr-function-mapping))
+		     (setq func (car func2)))
+		 (setq func (math-remove-dashes
+			     (if (string-match
+				  "\\`calcFunc-\\([a-zA-Z0-9']+\\)\\'"
+				  (symbol-name func))
+				 (math-match-substring (symbol-name func) 1)
+			       (symbol-name func))))
+		 (if (memq calc-language '(c fortran pascal maple))
+		     (setq func (math-to-underscores func)))
+		 (if (and (eq calc-language 'tex)
+			  calc-language-option
+			  (not (= calc-language-option 0))
+			  (string-match "\\`[a-zA-Z][a-zA-Z0-9]+\\'" func))
+		     (if (< (prefix-numeric-value calc-language-option) 0)
+			 (setq func (format "\\%s" func))
+		       (setq func (format "\\hbox{%s}" func))))
+		 (if (and (eq calc-language 'eqn)
+			  (string-match "[^']'+\\'" func))
+		     (let ((n (- (length func) (match-beginning 0) 1)))
+		       (setq func (substring func 0 (- n)))
+		       (while (>= (setq n (1- n)) 0)
+			 (setq func (concat func " prime")))))
+		 (cond ((and (eq calc-language 'tex)
+			     (or (> (length a) 2)
+				 (not (math-tex-expr-is-flat (nth 1 a)))))
+			(setq left "\\left( "
+			      right " \\right)"))
+		       ((and (eq calc-language 'eqn)
+			     (or (> (length a) 2)
+				 (not (math-tex-expr-is-flat (nth 1 a)))))
+			(setq left "{left ( "
+			      right " right )}"))
+		       ((and (or (and (eq calc-language 'tex)
+				      (eq (aref func 0) ?\\))
+				 (and (eq calc-language 'eqn)
+				      (memq (car a) math-eqn-special-funcs)))
+			     (not (string-match "\\hbox{" func))
+			     (= (length a) 2)
+			     (or (Math-realp (nth 1 a))
+				 (memq (car (nth 1 a)) '(var *))))
+			(setq left (if (eq calc-language 'eqn) "~{" "{")
+			      right "}"))
+		       ((eq calc-language 'eqn)
+			(setq left " ( "
+			      right " )"))
+		       (t (setq left calc-function-open
+				right calc-function-close)))
+		 (list 'horiz func left
+		       (math-compose-vector (cdr a)
+					    (if (eq calc-language 'eqn)
+						" , " ", ")
+					    0)
+		       right))))))))
+)
+
+(defconst math-eqn-special-funcs
+  '( calcFunc-log
+     calcFunc-ln calcFunc-exp
+     calcFunc-sin calcFunc-cos calcFunc-tan
+     calcFunc-sinh calcFunc-cosh calcFunc-tanh
+     calcFunc-arcsin calcFunc-arccos calcFunc-arctan
+     calcFunc-arcsinh calcFunc-arccosh calcFunc-arctanh
+))
+
+
+(defun math-prod-first-term (x)
+  (while (eq (car-safe x) '*)
+    (setq x (nth 1 x)))
+  x
+)
+
+(defun math-prod-last-term (x)
+  (while (eq (car-safe x) '*)
+    (setq x (nth 2 x)))
+  x
+)
+
+(defun math-compose-vector (a sep prec)
+  (if a
+      (cons 'horiz
+	    (cons (list 'set math-compose-level)
+		  (let ((c (list (math-compose-expr (car a) prec))))
+		    (while (setq a (cdr a))
+		      (setq c (cons (if (eq (car-safe (car a))
+					    'calcFunc-bstring)
+					(let ((math-compose-level
+					       (1- math-compose-level)))
+					  (math-compose-expr (car a) -123))
+				      (math-compose-expr (car a) prec))
+				    (cons (list 'break math-compose-level)
+					  (cons sep c)))))
+		    (nreverse c))))
+    "")
+)
+
+(defun math-vector-no-parens (a)
+  (or (cdr (cdr a))
+      (not (eq (car-safe (nth 1 a)) '*)))
+)
+
+(defun math-compose-matrix (a col cols base)
+  (let ((col 0)
+	(res nil))
+    (while (<= (setq col (1+ col)) cols)
+      (setq res (cons (cons just
+			    (cons base
+				  (mapcar (function
+					   (lambda (r)
+					     (list 'horiz
+						   (math-compose-expr
+						    (nth col r)
+						    vector-prec)
+						   (if (= col cols)
+						       ""
+						     (concat comma-spc " ")))))
+					  a)))
+		      res)))
+    (nreverse res))
+)
+
+(defun math-compose-rows (a count first)
+  (if (cdr a)
+      (if (<= count 0)
+	  (if (< count 0)
+	      (math-compose-rows (cdr a) -1 nil)
+	    (cons (concat (if (eq calc-language 'tex) "  \\ldots" "  ...")
+			  comma)
+		  (math-compose-rows (cdr a) -1 nil)))
+	(cons (list 'horiz
+		    (if first (concat left-bracket " ") "  ")
+		    (math-compose-expr (car a) vector-prec)
+		    comma)
+	      (math-compose-rows (cdr a) (1- count) nil)))
+    (list (list 'horiz
+		(if first (concat left-bracket " ") "  ")
+		(math-compose-expr (car a) vector-prec)
+		(concat " " right-bracket))))
+)
+
+(defun math-compose-tex-matrix (a)
+  (if (cdr a)
+      (cons (math-compose-vector (cdr (car a)) " & " 0)
+	    (cons " \\\\ "
+		  (math-compose-tex-matrix (cdr a))))
+    (list (math-compose-vector (cdr (car a)) " & " 0)))
+)
+
+(defun math-compose-eqn-matrix (a)
+  (if a
+      (cons
+       (cond ((eq calc-matrix-just 'right) "rcol ")
+	     ((eq calc-matrix-just 'center) "ccol ")
+	     (t "lcol "))
+       (cons
+	(list 'break math-compose-level)
+	(cons
+	 "{ "
+	 (cons
+	  (let ((math-compose-level (1+ math-compose-level)))
+	    (math-compose-vector (cdr (car a)) " above " 1000))
+	  (cons
+	   " } "
+	   (math-compose-eqn-matrix (cdr a)))))))
+    nil)
+)
+
+(defun math-vector-is-string (a)
+  (while (and (setq a (cdr a))
+	      (or (and (natnump (car a))
+		       (<= (car a) 255))
+		  (and (eq (car-safe (car a)) 'cplx)
+		       (natnump (nth 1 (car a)))
+		       (eq (nth 2 (car a)) 0)
+		       (<= (nth 1 (car a)) 255)))))
+  (null a)
+)
+
+(defun math-vector-to-string (a &optional quoted)
+  (setq a (concat (mapcar (function (lambda (x) (if (consp x) (nth 1 x) x)))
+			  (cdr a))))
+  (if (string-match "[\000-\037\177\\\"]" a)
+      (let ((p 0)
+	    (pat (if quoted "[\000-\037\177\\\"]" "[\000-\037\177]"))
+	    (codes (if quoted math-vector-to-string-chars '((?\^? . "^?"))))
+	    (fmt (if quoted "\\^%c" "^%c"))
+	    new)
+	(while (setq p (string-match pat a p))
+	  (if (setq new (assq (aref a p) codes))
+	      (setq a (concat (substring a 0 p)
+			      (cdr new)
+			      (substring a (1+ p)))
+		    p (+ p (length (cdr new))))
+	    (setq a (concat (substring a 0 p)
+			    (format fmt (+ (aref a p) 64))
+			    (substring a (1+ p)))
+		  p (+ p 2))))))
+  (if quoted
+      (concat "\"" a "\"")
+    a)
+)
+(defconst math-vector-to-string-chars '( ( ?\" . "\\\"" )
+					 ( ?\\ . "\\\\" )
+					 ( ?\a . "\\a" )
+					 ( ?\b . "\\b" )
+					 ( ?\e . "\\e" )
+					 ( ?\f . "\\f" )
+					 ( ?\n . "\\n" )
+					 ( ?\r . "\\r" )
+					 ( ?\t . "\\t" )
+					 ( ?\^? . "\\^?" )
+))
+
+(defun math-to-underscores (x)
+  (if (string-match "\\`\\(.*\\)#\\(.*\\)\\'" x)
+      (math-to-underscores
+       (concat (math-match-substring x 1) "_" (math-match-substring x 2)))
+    x)
+)
+
+(defun math-tex-expr-is-flat (a)
+  (or (Math-integerp a)
+      (memq (car a) '(float var))
+      (and (memq (car a) '(+ - * neg))
+	   (progn
+	     (while (and (setq a (cdr a))
+			 (math-tex-expr-is-flat (car a))))
+	     (null a)))
+      (and (memq (car a) '(^ calcFunc-subscr))
+	   (math-tex-expr-is-flat (nth 1 a))))
+)
+
+(put 'calcFunc-log 'math-compose-big 'math-compose-log)
+(defun math-compose-log (a prec)
+  (and (= (length a) 3)
+       (list 'horiz
+	     (list 'subscr "log"
+		   (let ((calc-language 'flat))
+		     (math-compose-expr (nth 2 a) 1000)))
+	     "("
+	     (math-compose-expr (nth 1 a) 1000)
+	     ")"))
+)
+
+(put 'calcFunc-log10 'math-compose-big 'math-compose-log10)
+(defun math-compose-log10 (a prec)
+  (and (= (length a) 2)
+       (list 'horiz
+	     (list 'subscr "log" "10")
+	     "("
+	     (math-compose-expr (nth 1 a) 1000)
+	     ")"))
+)
+
+(put 'calcFunc-deriv 'math-compose-big 'math-compose-deriv)
+(put 'calcFunc-tderiv 'math-compose-big 'math-compose-deriv)
+(defun math-compose-deriv (a prec)
+  (and (= (length a) 3)
+       (math-compose-expr (list '/
+				(list 'calcFunc-choriz
+				      (list 'vec
+					    '(calcFunc-string (vec ?d))
+					    (nth 1 a)))
+				(list 'calcFunc-choriz
+				      (list 'vec
+					    '(calcFunc-string (vec ?d))
+					    (nth 2 a))))
+			  prec))
+)
+
+(put 'calcFunc-sqrt 'math-compose-big 'math-compose-sqrt)
+(defun math-compose-sqrt (a prec)
+  (and (= (length a) 2)
+       (let* ((c (math-compose-expr (nth 1 a) 0))
+	      (a (math-comp-ascent c))
+	      (d (math-comp-descent c))
+	      (h (+ a d))
+	      (w (math-comp-width c)))
+	 (list 'vleft
+	       a
+	       (concat (if (= h 1) " " "  ")
+		       (make-string (+ w 2) ?\_))
+	       (list 'horiz
+		     (if (= h 1)
+			 "V"
+		       (append (list 'vleft (1- a))
+			       (make-list (1- h) " |")
+			       '("\\|")))
+		     " "
+		     c))))
+)
+
+(put 'calcFunc-choose 'math-compose-big 'math-compose-choose)
+(defun math-compose-choose (a prec)
+  (let ((a1 (math-compose-expr (nth 1 a) 0))
+	(a2 (math-compose-expr (nth 2 a) 0)))
+    (list 'horiz
+	  "("
+	  (list 'vcent
+		(math-comp-height a1)
+		a1 " " a2)
+	  ")"))
+)
+
+(put 'calcFunc-integ 'math-compose-big 'math-compose-integ)
+(defun math-compose-integ (a prec)
+  (and (memq (length a) '(3 5))
+       (eq (car-safe (nth 2 a)) 'var)
+       (let* ((parens (and (>= prec 196) (/= prec 1000)))
+	      (var (math-compose-expr (nth 2 a) 0))
+	      (over (and (eq (car-safe (nth 2 a)) 'var)
+			 (or (and (eq (car-safe (nth 1 a)) '/)
+				  (math-numberp (nth 1 (nth 1 a))))
+			     (and (eq (car-safe (nth 1 a)) '^)
+				  (math-looks-negp (nth 2 (nth 1 a)))))))
+	      (expr (math-compose-expr (if over
+					   (math-mul (nth 1 a)
+						     (math-build-var-name
+						      (format
+						       "d%s"
+						       (nth 1 (nth 2 a)))))
+					 (nth 1 a)) 185))
+	      (calc-language 'flat)
+	      (low (and (nth 3 a) (math-compose-expr (nth 3 a) 0)))
+	      (high (and (nth 4 a) (math-compose-expr (nth 4 a) 0))))
+	 (list 'horiz
+	       (if parens "(" "")
+	       (append (list 'vcent (if high 3 2))
+		       (and high (list (list 'horiz "  " high)))
+		       '("  /"
+			 " | "
+			 " | "
+			 " | "
+			 "/  ")
+		       (and low (list (list 'horiz low "  "))))
+	       expr
+	       (if over
+		   ""
+		 (list 'horiz " d" var))
+	       (if parens ")" ""))))
+)
+
+(put 'calcFunc-sum 'math-compose-big 'math-compose-sum)
+(defun math-compose-sum (a prec)
+  (and (memq (length a) '(3 5 6))
+       (let* ((expr (math-compose-expr (nth 1 a) 185))
+	      (calc-language 'flat)
+	      (var (math-compose-expr (nth 2 a) 0))
+	      (low (and (nth 3 a) (math-compose-expr (nth 3 a) 0)))
+	      (high (and (nth 4 a) (math-compose-vector (nthcdr 4 a) ", " 0))))
+	 (list 'horiz
+	       (if (memq prec '(180 201)) "(" "")
+	       (append (list 'vcent (if high 3 2))
+		       (and high (list high))
+		       '("---- "
+			 "\\    "
+			 " >   "
+			 "/    "
+			 "---- ")
+		       (if low
+			   (list (list 'horiz var " = " low))
+			 (list var)))
+	       (if (memq (car-safe (nth 1 a)) '(calcFunc-sum calcFunc-prod))
+		   " " "")
+	       expr
+	       (if (memq prec '(180 201)) ")" ""))))
+)
+
+(put 'calcFunc-prod 'math-compose-big 'math-compose-prod)
+(defun math-compose-prod (a prec)
+  (and (memq (length a) '(3 5 6))
+       (let* ((expr (math-compose-expr (nth 1 a) 198))
+	      (calc-language 'flat)
+	      (var (math-compose-expr (nth 2 a) 0))
+	      (low (and (nth 3 a) (math-compose-expr (nth 3 a) 0)))
+	      (high (and (nth 4 a) (math-compose-vector (nthcdr 4 a) ", " 0))))
+	 (list 'horiz
+	       (if (memq prec '(196 201)) "(" "")
+	       (append (list 'vcent (if high 3 2))
+		       (and high (list high))
+		       '("----- "
+			 " | |  "
+			 " | |  "
+			 " | |  ")
+		       (if low
+			   (list (list 'horiz var " = " low))
+			 (list var)))
+	       (if (memq (car-safe (nth 1 a)) '(calcFunc-sum calcFunc-prod))
+		   " " "")
+	       expr
+	       (if (memq prec '(196 201)) ")" ""))))
+)
+
+
+(defun math-stack-value-offset-fancy ()
+  (let ((cwid (+ (math-comp-width c))))
+    (cond ((eq calc-display-just 'right)
+	   (if calc-display-origin
+	       (setq wid (max calc-display-origin 5))
+	     (if (integerp calc-line-breaking)
+		 (setq wid calc-line-breaking)))
+	   (setq off (- wid cwid
+			(max (- (length calc-right-label)
+				(if (and (integerp calc-line-breaking)
+					 calc-display-origin)
+				    (max (- calc-line-breaking
+					    calc-display-origin)
+					 0)
+				  0))
+			     0))))
+	  (t
+	   (if calc-display-origin
+	       (progn
+		 (setq off (- calc-display-origin (/ cwid 2)))
+		 (if (integerp calc-line-breaking)
+		     (setq off (min off (- calc-line-breaking cwid
+					   (length calc-right-label)))))
+		 (if (>= off 0)
+		     (setq wid (max wid (+ off cwid)))))
+	     (if (integerp calc-line-breaking)
+		 (setq wid calc-line-breaking))
+	     (setq off (/ (- wid cwid) 2)))))
+    (and (integerp calc-line-breaking)
+	 (or (< off 0)
+	     (and calc-display-origin
+		  (> calc-line-breaking calc-display-origin)))
+	 (setq wid calc-line-breaking)))
+)
+
+
+
+;;; Convert a composition to string form, with embedded \n's if necessary.
+
+(defun math-composition-to-string (c &optional width)
+  (or width (setq width (calc-window-width)))
+  (if calc-display-raw
+      (math-comp-to-string-raw c 0)
+    (if (math-comp-is-flat c)
+	(math-comp-to-string-flat c width)
+      (math-vert-comp-to-string
+       (math-comp-simplify c width))))
+)
+
+(defun math-comp-is-flat (c)     ; check if c's height is 1.
+  (cond ((not (consp c)) t)
+	((memq (car c) '(set break)) t)
+	((eq (car c) 'horiz)
+	 (while (and (setq c (cdr c))
+		     (math-comp-is-flat (car c))))
+	 (null c))
+	((memq (car c) '(vleft vcent vright))
+	 (and (= (length c) 3)
+	      (= (nth 1 c) 0)
+	      (math-comp-is-flat (nth 2 c))))
+	((eq (car c) 'tag)
+	 (math-comp-is-flat (nth 2 c)))
+	(t nil))
+)
+
+
+;;; Convert a one-line composition to a string.  Break into multiple
+;;; lines if necessary, choosing break points according to the structure
+;;; of the formula.
+
+(defun math-comp-to-string-flat (c full-width)
+  (if math-comp-sel-hpos
+      (let ((comp-pos 0))
+	(math-comp-sel-flat-term c))
+    (let ((comp-buf "")
+	  (comp-word "")
+	  (comp-pos 0)
+	  (comp-margin 0)
+	  (comp-highlight (and math-comp-selected calc-show-selections))
+	  (comp-level -1))
+      (math-comp-to-string-flat-term '(set -1 0))
+      (math-comp-to-string-flat-term c)
+      (math-comp-to-string-flat-term '(break -1))
+      (let ((str (aref math-comp-buf-string 0))
+	    (prefix ""))
+	(and (> (length str) 0) (= (aref str 0) ? )
+	     (> (length comp-buf) 0)
+	     (let ((k (length comp-buf)))
+	       (while (not (= (aref comp-buf (setq k (1- k))) ?\n)))
+	       (aset comp-buf k ? )
+	       (if (and (< (1+ k) (length comp-buf))
+			(= (aref comp-buf (1+ k)) ? ))
+		   (progn
+		     (aset comp-buf (1+ k) ?\n)
+		     (setq prefix " "))
+		 (setq prefix "\n"))))
+	(concat comp-buf prefix str))))
+)
+(setq math-comp-buf-string (make-vector 10 ""))
+(setq math-comp-buf-margin (make-vector 10 0))
+(setq math-comp-buf-level (make-vector 10 0))
+
+(defun math-comp-to-string-flat-term (c)
+  (cond ((not (consp c))
+	 (if comp-highlight
+	     (setq c (math-comp-highlight-string c)))
+	 (setq comp-word (if (= (length comp-word) 0) c (concat comp-word c))
+	       comp-pos (+ comp-pos (length c))))
+
+	((eq (car c) 'horiz)
+	 (while (setq c (cdr c))
+	   (math-comp-to-string-flat-term (car c))))
+
+	((eq (car c) 'set)
+	 (if (nth 1 c)
+	     (progn
+	       (setq comp-level (1+ comp-level))
+	       (if (>= comp-level (length math-comp-buf-string))
+		   (setq math-comp-buf-string (vconcat math-comp-buf-string
+						       math-comp-buf-string)
+			 math-comp-buf-margin (vconcat math-comp-buf-margin
+						       math-comp-buf-margin)
+			 math-comp-buf-level (vconcat math-comp-buf-level
+						      math-comp-buf-level)))
+	       (aset math-comp-buf-string comp-level "")
+	       (aset math-comp-buf-margin comp-level (+ comp-pos
+							(or (nth 2 c) 0)))
+	       (aset math-comp-buf-level comp-level (nth 1 c)))))
+
+	((eq (car c) 'break)
+	 (if (not calc-line-breaking)
+	     (setq comp-buf (concat comp-buf comp-word)
+		   comp-word "")
+	   (let ((i 0) str)
+	     (if (and (> comp-pos full-width)
+		      (progn
+			(while (progn
+				 (setq str (aref math-comp-buf-string i))
+				 (and (= (length str) 0) (< i comp-level)))
+			  (setq i (1+ i)))
+			(or (> (length str) 0) (> (length comp-buf) 0))))
+		 (let ((prefix "") mrg wid)
+		   (setq mrg (aref math-comp-buf-margin i))
+		   (if (> mrg 12)  ; indenting too far, go back to far left
+		       (let ((j i) (new (if calc-line-numbering 5 1)))
+			 '(while (<= j comp-level)
+			   (aset math-comp-buf-margin j
+				 (+ (aref math-comp-buf-margin j) (- new mrg)))
+			   (setq j (1+ j)))
+			 (setq mrg new)))
+		   (setq wid (+ (length str) comp-margin))
+		   (and (> (length str) 0) (= (aref str 0) ? )
+			(> (length comp-buf) 0)
+			(let ((k (length comp-buf)))
+			  (while (not (= (aref comp-buf (setq k (1- k))) ?\n)))
+			  (aset comp-buf k ? )
+			  (if (and (< (1+ k) (length comp-buf))
+				   (= (aref comp-buf (1+ k)) ? ))
+			      (progn
+				(aset comp-buf (1+ k) ?\n)
+				(setq prefix " "))
+			    (setq prefix "\n"))))
+		   (setq comp-buf (concat comp-buf prefix str "\n"
+					  (make-string mrg ? ))
+			 comp-pos (+ comp-pos (- mrg wid))
+			 comp-margin mrg)
+		   (aset math-comp-buf-string i "")
+		   (while (<= (setq i (1+ i)) comp-level)
+		     (if (> (aref math-comp-buf-margin i) wid)
+			 (aset math-comp-buf-margin i
+			       (+ (aref math-comp-buf-margin i)
+				  (- mrg wid))))))))
+	   (if (and (= (nth 1 c) (aref math-comp-buf-level comp-level))
+		    (< comp-pos (+ (aref math-comp-buf-margin comp-level) 2)))
+	       ()  ; avoid stupid breaks, e.g., "1 +\n really_long_expr"
+	     (let ((str (aref math-comp-buf-string comp-level)))
+	       (setq str (if (= (length str) 0)
+			     comp-word
+			   (concat str comp-word))
+		     comp-word "")
+	       (while (< (nth 1 c) (aref math-comp-buf-level comp-level))
+		 (setq comp-level (1- comp-level))
+		 (or (= (length (aref math-comp-buf-string comp-level)) 0)
+		     (setq str (concat (aref math-comp-buf-string comp-level)
+				       str))))
+	       (aset math-comp-buf-string comp-level str)))))
+
+	((eq (car c) 'tag)
+	 (cond ((eq (nth 1 c) math-comp-selected)
+		(let ((comp-highlight (not calc-show-selections)))
+		  (math-comp-to-string-flat-term (nth 2 c))))
+	       ((eq (nth 1 c) t)
+		(let ((comp-highlight nil))
+		  (math-comp-to-string-flat-term (nth 2 c))))
+	       (t (math-comp-to-string-flat-term (nth 2 c)))))
+
+	(t (math-comp-to-string-flat-term (nth 2 c))))
+)
+
+(defun math-comp-highlight-string (s)
+  (setq s (copy-sequence s))
+  (let ((i (length s)))
+    (while (>= (setq i (1- i)) 0)
+      (or (memq (aref s i) '(32 ?\n))
+	  (aset s i (if calc-show-selections ?\. ?\#)))))
+  s
+)
+
+(defun math-comp-sel-flat-term (c)
+  (cond ((not (consp c))
+	 (setq comp-pos (+ comp-pos (length c))))
+	((memq (car c) '(set break)))
+	((eq (car c) 'horiz)
+	 (while (and (setq c (cdr c)) (< math-comp-sel-cpos 1000000))
+	   (math-comp-sel-flat-term (car c))))
+	((eq (car c) 'tag)
+	 (if (<= comp-pos math-comp-sel-cpos)
+	     (progn
+	       (math-comp-sel-flat-term (nth 2 c))
+	       (if (> comp-pos math-comp-sel-cpos)
+		   (setq math-comp-sel-tag c
+			 math-comp-sel-cpos 1000000)))
+	   (math-comp-sel-flat-term (nth 2 c))))
+	(t (math-comp-sel-flat-term (nth 2 c))))
+)
+
+
+;;; Simplify a composition to a canonical form consisting of
+;;;   (vleft n "string" "string" "string" ...)
+;;; where 0 <= n < number-of-strings.
+
+(defun math-comp-simplify (c full-width)
+  (let ((comp-buf (list ""))
+	(comp-base 0)
+	(comp-height 1)
+	(comp-hpos 0)
+	(comp-vpos 0)
+	(comp-highlight (and math-comp-selected calc-show-selections))
+	(comp-tag nil))
+    (math-comp-simplify-term c)
+    (cons 'vleft (cons comp-base comp-buf)))
+)
+
+(defun math-comp-add-string (s h v)
+  (and (> (length s) 0)
+       (let ((vv (+ v comp-base)))
+	 (if math-comp-sel-hpos
+	     (math-comp-add-string-sel h vv (length s) 1)
+	   (if (< vv 0)
+	       (setq comp-buf (nconc (make-list (- vv) "") comp-buf)
+		     comp-base (- v)
+		     comp-height (- comp-height vv)
+		     vv 0)
+	     (if (>= vv comp-height)
+		 (setq comp-buf (nconc comp-buf
+				       (make-list (1+ (- vv comp-height)) ""))
+		       comp-height (1+ vv))))
+	   (let ((str (nthcdr vv comp-buf)))
+	     (setcar str (concat (car str)
+				 (make-string (- h (length (car str))) 32)
+				 (if comp-highlight
+				     (math-comp-highlight-string s)
+				   s)))))))
+)
+
+(defun math-comp-add-string-sel (x y w h)
+  (if (and (<= y math-comp-sel-vpos)
+	   (> (+ y h) math-comp-sel-vpos)
+	   (<= x math-comp-sel-hpos)
+	   (> (+ x w) math-comp-sel-hpos))
+      (setq math-comp-sel-tag comp-tag
+	    math-comp-sel-vpos 10000))
+)
+
+(defun math-comp-simplify-term (c)
+  (cond ((stringp c)
+	 (math-comp-add-string c comp-hpos comp-vpos)
+	 (setq comp-hpos (+ comp-hpos (length c))))
+	((memq (car c) '(set break))
+	 nil)
+	((eq (car c) 'horiz)
+	 (while (setq c (cdr c))
+	   (math-comp-simplify-term (car c))))
+	((memq (car c) '(vleft vcent vright))
+	 (let* ((comp-vpos (+ (- comp-vpos (nth 1 c))
+			      (1- (math-comp-ascent (nth 2 c)))))
+		(widths (mapcar 'math-comp-width (cdr (cdr c))))
+		(maxwid (apply 'max widths))
+		(bias (cond ((eq (car c) 'vleft) 0)
+			    ((eq (car c) 'vcent) 1)
+			    (t 2))))
+	   (setq c (cdr c))
+	   (while (setq c (cdr c))
+	     (if (eq (car-safe (car c)) 'rule)
+		 (math-comp-add-string (make-string maxwid (nth 1 (car c)))
+				       comp-hpos comp-vpos)
+	       (let ((comp-hpos (+ comp-hpos (/ (* bias (- maxwid
+							   (car widths)))
+						2))))
+		 (math-comp-simplify-term (car c))))
+	     (and (cdr c)
+		  (setq comp-vpos (+ comp-vpos
+				     (+ (math-comp-descent (car c))
+					(math-comp-ascent (nth 1 c))))
+			widths (cdr widths))))
+	   (setq comp-hpos (+ comp-hpos maxwid))))
+	((eq (car c) 'supscr)
+	 (let* ((asc (or 1 (math-comp-ascent (nth 1 c))))
+		(desc (math-comp-descent (nth 2 c)))
+		(oldh (prog1
+			  comp-hpos
+			(math-comp-simplify-term (nth 1 c))))
+		(comp-vpos (- comp-vpos (+ asc desc))))
+	   (math-comp-simplify-term (nth 2 c))
+	   (if math-comp-sel-hpos
+	       (math-comp-add-string-sel oldh
+					 (- comp-vpos
+					    -1
+					    (math-comp-ascent (nth 2 c)))
+					 (- comp-hpos oldh)
+					 (math-comp-height c)))))
+	((eq (car c) 'subscr)
+	 (let* ((asc (math-comp-ascent (nth 2 c)))
+		(desc (math-comp-descent (nth 1 c)))
+		(oldv comp-vpos)
+		(oldh (prog1
+			  comp-hpos
+			(math-comp-simplify-term (nth 1 c))))
+		(comp-vpos (+ comp-vpos (+ asc desc))))
+	   (math-comp-simplify-term (nth 2 c))
+	   (if math-comp-sel-hpos
+	       (math-comp-add-string-sel oldh oldv
+					 (- comp-hpos oldh)
+					 (math-comp-height c)))))
+	((eq (car c) 'tag)
+	 (cond ((eq (nth 1 c) math-comp-selected)
+		(let ((comp-highlight (not calc-show-selections)))
+		  (math-comp-simplify-term (nth 2 c))))
+	       ((eq (nth 1 c) t)
+		(let ((comp-highlight nil))
+		  (math-comp-simplify-term (nth 2 c))))
+	       (t (let ((comp-tag c))
+		    (math-comp-simplify-term (nth 2 c)))))))
+)
+
+
+;;; Measuring a composition.
+
+(defun math-comp-first-char (c)
+  (cond ((stringp c)
+	 (and (> (length c) 0)
+	      (elt c 0)))
+	((memq (car c) '(horiz subscr supscr))
+	 (while (and (setq c (cdr c))
+		     (math-comp-is-null (car c))))
+	 (and c (math-comp-first-char (car c))))
+	((eq (car c) 'tag)
+	 (math-comp-first-char (nth 2 c))))
+)
+
+(defun math-comp-first-string (c)
+  (cond ((stringp c)
+	 (and (> (length c) 0)
+	      c))
+	((eq (car c) 'horiz)
+	 (while (and (setq c (cdr c))
+		     (math-comp-is-null (car c))))
+	 (and c (math-comp-first-string (car c))))
+	((eq (car c) 'tag)
+	 (math-comp-first-string (nth 2 c))))
+)
+
+(defun math-comp-last-char (c)
+  (cond ((stringp c)
+	 (and (> (length c) 0)
+	      (elt c (1- (length c)))))
+	((eq (car c) 'horiz)
+	 (let ((c (reverse (cdr c))))
+	   (while (and c (math-comp-is-null (car c)))
+	     (setq c (cdr c)))
+	   (and c (math-comp-last-char (car c)))))
+	((eq (car c) 'tag)
+	 (math-comp-last-char (nth 2 c))))
+)
+
+(defun math-comp-is-null (c)
+  (cond ((stringp c) (= (length c) 0))
+	((memq (car c) '(horiz subscr supscr))
+	 (while (and (setq c (cdr c))
+		     (math-comp-is-null (car c))))
+	 (null c))
+	((eq (car c) 'tag)
+	 (math-comp-is-null (nth 2 c)))
+	((memq (car c) '(set break)) t))
+)
+
+(defun math-comp-width (c)
+  (cond ((not (consp c)) (length c))
+	((memq (car c) '(horiz subscr supscr))
+	 (let ((accum 0))
+	   (while (setq c (cdr c))
+	     (setq accum (+ accum (math-comp-width (car c)))))
+	   accum))
+	((memq (car c) '(vcent vleft vright))
+	 (setq c (cdr c))
+	 (let ((accum 0))
+	   (while (setq c (cdr c))
+	     (setq accum (max accum (math-comp-width (car c)))))
+	   accum))
+	((eq (car c) 'tag)
+	 (math-comp-width (nth 2 c)))
+	(t 0))
+)
+
+(defun math-comp-height (c)
+  (if (stringp c)
+      1
+    (+ (math-comp-ascent c) (math-comp-descent c)))
+)
+
+(defun math-comp-ascent (c)
+  (cond ((not (consp c)) 1)
+	((eq (car c) 'horiz)
+	 (let ((accum 0))
+	   (while (setq c (cdr c))
+	     (setq accum (max accum (math-comp-ascent (car c)))))
+	   accum))
+	((memq (car c) '(vcent vleft vright))
+	 (if (> (nth 1 c) 0) (1+ (nth 1 c)) 1))
+	((eq (car c) 'supscr)
+	 (max (math-comp-ascent (nth 1 c)) (1+ (math-comp-height (nth 2 c)))))
+	((eq (car c) 'subscr)
+	 (math-comp-ascent (nth 1 c)))
+	((eq (car c) 'tag)
+	 (math-comp-ascent (nth 2 c)))
+	(t 1))
+)
+
+(defun math-comp-descent (c)
+  (cond ((not (consp c)) 0)
+	((eq (car c) 'horiz)
+	 (let ((accum 0))
+	   (while (setq c (cdr c))
+	     (setq accum (max accum (math-comp-descent (car c)))))
+	   accum))
+	((memq (car c) '(vcent vleft vright))
+	 (let ((accum (- (nth 1 c))))
+	   (setq c (cdr c))
+	   (while (setq c (cdr c))
+	     (setq accum (+ accum (math-comp-height (car c)))))
+	   (max (1- accum) 0)))
+	((eq (car c) 'supscr)
+	 (math-comp-descent (nth 1 c)))
+	((eq (car c) 'subscr)
+	 (+ (math-comp-descent (nth 1 c)) (math-comp-height (nth 2 c))))
+	((eq (car c) 'tag)
+	 (math-comp-descent (nth 2 c)))
+	(t 0))
+)
+
+(defun calcFunc-cwidth (a &optional prec)
+  (if (and prec (not (integerp prec))) (math-reject-arg prec 'fixnump))
+  (math-comp-width (math-compose-expr a (or prec 0)))
+)
+
+(defun calcFunc-cheight (a &optional prec)
+  (if (and prec (not (integerp prec))) (math-reject-arg prec 'fixnump))
+  (if (and (memq (car a) '(calcFunc-cvspace calcFunc-ctspace calcFunc-cbspace))
+	   (memq (length a) '(2 3))
+	   (eq (nth 1 a) 0))
+      0
+    (math-comp-height (math-compose-expr a (or prec 0))))
+)
+
+(defun calcFunc-cascent (a &optional prec)
+  (if (and prec (not (integerp prec))) (math-reject-arg prec 'fixnump))
+  (if (and (memq (car a) '(calcFunc-cvspace calcFunc-ctspace calcFunc-cbspace))
+	   (memq (length a) '(2 3))
+	   (eq (nth 1 a) 0))
+      0
+    (math-comp-ascent (math-compose-expr a (or prec 0))))
+)
+
+(defun calcFunc-cdescent (a &optional prec)
+  (if (and prec (not (integerp prec))) (math-reject-arg prec 'fixnump))
+  (math-comp-descent (math-compose-expr a (or prec 0)))
+)
+
+
+;;; Convert a simplified composition into string form.
+
+(defun math-vert-comp-to-string (c)
+  (if (stringp c)
+      c
+    (math-vert-comp-to-string-step (cdr (cdr c))))
+)
+
+(defun math-vert-comp-to-string-step (c)
+  (if (cdr c)
+      (concat (car c) "\n" (math-vert-comp-to-string-step (cdr c)))
+    (car c))
+)
+
+
+;;; Convert a composition to a string in "raw" form (for debugging).
+
+(defun math-comp-to-string-raw (c indent)
+  (cond ((or (not (consp c)) (eq (car c) 'set))
+	 (prin1-to-string c))
+	((null (cdr c))
+	 (concat "(" (symbol-name (car c)) ")"))
+	(t
+	 (let ((next-indent (+ indent 2 (length (symbol-name (car c))))))
+	   (concat "("
+		   (symbol-name (car c))
+		   " "
+		   (math-comp-to-string-raw (nth 1 c) next-indent)
+		   (math-comp-to-string-raw-step (cdr (cdr c))
+						 next-indent)
+		   ")"))))
+)
+
+(defun math-comp-to-string-raw-step (cl indent)
+  (if cl
+      (concat "\n"
+	      (make-string indent 32)
+	      (math-comp-to-string-raw (car cl) indent)
+	      (math-comp-to-string-raw-step (cdr cl) indent))
+    "")
+)
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/calcsel2.el	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,303 @@
+;; Calculator for GNU Emacs, part II [calc-sel-2.el]
+;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+;; Written by Dave Gillespie, daveg@synaptics.com.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY.  No author or distributor
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing.  Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License.   A copy of this license is
+;; supposed to have been given to you along with GNU Emacs so you
+;; can know your rights and responsibilities.  It should be in a
+;; file named COPYING.  Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+
+
+
+;; This file is autoloaded from calc-ext.el.
+(require 'calc-ext)
+
+(require 'calc-macs)
+
+(defun calc-Need-calc-sel-2 () nil)
+
+
+(defun calc-commute-left (arg)
+  (interactive "p")
+  (if (< arg 0)
+      (calc-commute-right (- arg))
+    (calc-wrapper
+     (calc-preserve-point)
+     (let ((num (max 1 (calc-locate-cursor-element (point))))
+	   (reselect calc-keep-selection))
+       (if (= arg 0) (setq arg nil))
+       (while (or (null arg) (>= (setq arg (1- arg)) 0))
+	 (let* ((entry (calc-top num 'entry))
+		(expr (car entry))
+		(sel (calc-auto-selection entry))
+		parent new)
+	   (or (and sel
+		    (consp (setq parent (calc-find-assoc-parent-formula
+					 expr sel))))
+	       (error "No term is selected"))
+	   (if (and calc-assoc-selections
+		    (assq (car parent) calc-assoc-ops))
+	       (let ((outer (calc-find-parent-formula parent sel)))
+		 (if (eq sel (nth 2 outer))
+		     (setq new (calc-replace-sub-formula
+				parent outer
+				(cond
+				 ((memq (car outer)
+					(nth 1 (assq (car-safe (nth 1 outer))
+						     calc-assoc-ops)))
+				  (let* ((other (nth 2 (nth 1 outer)))
+					 (new (calc-build-assoc-term
+					       (car (nth 1 outer))
+					       (calc-build-assoc-term
+						(car outer)
+						(nth 1 (nth 1 outer))
+						sel)
+					       other)))
+				    (setq sel (nth 2 (nth 1 new)))
+				    new))
+				 ((eq (car outer) '-)
+				  (calc-build-assoc-term
+				   '+
+				   (setq sel (math-neg sel))
+				   (nth 1 outer)))
+				 ((eq (car outer) '/)
+				  (calc-build-assoc-term
+				   '*
+				   (setq sel (calcFunc-div 1 sel))
+				   (nth 1 outer)))
+				 (t (calc-build-assoc-term
+				     (car outer) sel (nth 1 outer))))))
+		   (let ((next (calc-find-parent-formula parent outer)))
+		     (if (not (and (consp next)
+				   (eq outer (nth 2 next))
+				   (eq (car next) (car outer))))
+			 (setq new nil)
+		       (setq new (calc-build-assoc-term
+				  (car next)
+				  sel
+				  (calc-build-assoc-term
+				   (car next) (nth 1 next) (nth 2 outer)))
+			     sel (nth 1 new)
+			     new (calc-replace-sub-formula
+				  parent next new))))))
+	     (if (eq (nth 1 parent) sel)
+		 (setq new nil)
+	       (let ((p (nthcdr (1- (calc-find-sub-formula parent sel))
+				(setq new (copy-sequence parent)))))
+		 (setcar (cdr p) (car p))
+		 (setcar p sel))))
+	   (if (null new)
+	       (if arg
+		   (error "Term is already leftmost")
+		 (or reselect
+		     (calc-pop-push-list 1 (list expr) num '(nil)))
+		 (setq arg 0))
+	     (calc-pop-push-record-list
+	      1 "left"
+	      (list (calc-replace-sub-formula expr parent new))
+	      num
+	      (list (and (or (not (eq arg 0)) reselect)
+			 sel)))))))))
+)
+
+(defun calc-commute-right (arg)
+  (interactive "p")
+  (if (< arg 0)
+      (calc-commute-left (- arg))
+    (calc-wrapper
+     (calc-preserve-point)
+     (let ((num (max 1 (calc-locate-cursor-element (point))))
+	   (reselect calc-keep-selection))
+       (if (= arg 0) (setq arg nil))
+       (while (or (null arg) (>= (setq arg (1- arg)) 0))
+	 (let* ((entry (calc-top num 'entry))
+		(expr (car entry))
+		(sel (calc-auto-selection entry))
+		parent new)
+	   (or (and sel
+		    (consp (setq parent (calc-find-assoc-parent-formula
+					 expr sel))))
+	       (error "No term is selected"))
+	   (if (and calc-assoc-selections
+		    (assq (car parent) calc-assoc-ops))
+	       (let ((outer (calc-find-parent-formula parent sel)))
+		 (if (eq sel (nth 1 outer))
+		     (setq new (calc-replace-sub-formula
+				parent outer
+				(if (memq (car outer)
+					  (nth 2 (assq (car-safe (nth 2 outer))
+						       calc-assoc-ops)))
+				    (let ((other (nth 1 (nth 2 outer))))
+				      (calc-build-assoc-term
+				       (car outer)
+				       other
+				       (calc-build-assoc-term
+					(car (nth 2 outer))
+					sel
+					(nth 2 (nth 2 outer)))))
+				  (let ((new (cond
+					      ((eq (car outer) '-)
+					       (calc-build-assoc-term
+						'+
+						(math-neg (nth 2 outer))
+						sel))
+					      ((eq (car outer) '/)
+					       (calc-build-assoc-term
+						'*
+						(calcFunc-div 1 (nth 2 outer))
+						sel))
+					      (t (calc-build-assoc-term
+						  (car outer)
+						  (nth 2 outer)
+						  sel)))))
+				    (setq sel (nth 2 new))
+				    new))))
+		   (let ((next (calc-find-parent-formula parent outer)))
+		     (if (not (and (consp next)
+				   (eq outer (nth 1 next))))
+			 (setq new nil)
+		       (setq new (calc-build-assoc-term
+				  (car outer)
+				  (calc-build-assoc-term
+				   (car next) (nth 1 outer) (nth 2 next))
+				  sel)
+			     sel (nth 2 new)
+			     new (calc-replace-sub-formula
+				  parent next new))))))
+	     (if (eq (nth (1- (length parent)) parent) sel)
+		 (setq new nil)
+	       (let ((p (nthcdr (calc-find-sub-formula parent sel)
+				(setq new (copy-sequence parent)))))
+		 (setcar p (nth 1 p))
+		 (setcar (cdr p) sel))))
+	   (if (null new)
+	       (if arg
+		   (error "Term is already rightmost")
+		 (or reselect
+		     (calc-pop-push-list 1 (list expr) num '(nil)))
+		 (setq arg 0))
+	     (calc-pop-push-record-list
+	      1 "rght"
+	      (list (calc-replace-sub-formula expr parent new))
+	      num
+	      (list (and (or (not (eq arg 0)) reselect)
+			 sel)))))))))
+)
+
+(defun calc-build-assoc-term (op lhs rhs)
+  (cond ((and (eq op '+) (or (math-looks-negp rhs)
+			     (and (eq (car-safe rhs) 'cplx)
+				  (math-negp (nth 1 rhs))
+				  (eq (nth 2 rhs) 0))))
+	 (list '- lhs (math-neg rhs)))
+	((and (eq op '-) (or (math-looks-negp rhs)
+			     (and (eq (car-safe rhs) 'cplx)
+				  (math-negp (nth 1 rhs))
+				  (eq (nth 2 rhs) 0))))
+	 (list '+ lhs (math-neg rhs)))
+	((and (eq op '*) (and (eq (car-safe rhs) '/)
+			      (or (math-equal-int (nth 1 rhs) 1)
+				  (equal (nth 1 rhs) '(cplx 1 0)))))
+	 (list '/ lhs (nth 2 rhs)))
+	((and (eq op '/) (and (eq (car-safe rhs) '/)
+			      (or (math-equal-int (nth 1 rhs) 1)
+				  (equal (nth 1 rhs) '(cplx 1 0)))))
+	 (list '/ lhs (nth 2 rhs)))
+	(t (list op lhs rhs)))
+)
+
+(defun calc-sel-unpack ()
+  (interactive)
+  (calc-wrapper
+   (calc-preserve-point)
+   (let* ((num (max 1 (calc-locate-cursor-element (point))))
+	  (reselect calc-keep-selection)
+	  (entry (calc-top num 'entry))
+	  (expr (car entry))
+	  (sel (or (calc-auto-selection entry) expr)))
+     (or (and (not (math-primp sel))
+	      (= (length sel) 2))
+	 (error "Selection must be a function of one argument"))
+     (calc-pop-push-record-list 1 "unpk"
+				(list (calc-replace-sub-formula
+				       expr sel (nth 1 sel)))
+				num
+				(list (and reselect (nth 1 sel))))))
+)
+
+(defun calc-sel-isolate ()
+  (interactive)
+  (calc-slow-wrapper
+   (calc-preserve-point)
+   (let* ((num (max 1 (calc-locate-cursor-element (point))))
+	  (reselect calc-keep-selection)
+	  (entry (calc-top num 'entry))
+	  (expr (car entry))
+	  (sel (or (calc-auto-selection entry) (error "No selection")))
+	  (eqn sel)
+	  soln)
+     (while (and (or (consp (setq eqn (calc-find-parent-formula expr eqn)))
+		     (error "Selection must be a member of an equation"))
+		 (not (assq (car eqn) calc-tweak-eqn-table))))
+     (setq soln (math-solve-eqn eqn sel calc-hyperbolic-flag))
+     (or soln
+	 (error "No solution found"))
+     (setq soln (calc-encase-atoms
+		 (if (eq (not (calc-find-sub-formula (nth 2 eqn) sel))
+			 (eq (nth 1 soln) sel))
+		     soln
+		   (list (nth 1 (assq (car soln) calc-tweak-eqn-table))
+			 (nth 2 soln)
+			 (nth 1 soln)))))
+     (calc-pop-push-record-list 1 "isol"
+				(list (calc-replace-sub-formula
+				       expr eqn soln))
+				num
+				(list (and reselect sel)))
+     (calc-handle-whys)))
+)
+
+(defun calc-sel-commute (many)
+  (interactive "P")
+  (let ((calc-assoc-selections nil))
+    (calc-rewrite-selection "CommuteRules" many "cmut"))
+  (calc-set-mode-line)
+)
+
+(defun calc-sel-jump-equals (many)
+  (interactive "P")
+  (calc-rewrite-selection "JumpRules" many "jump")
+)
+
+(defun calc-sel-distribute (many)
+  (interactive "P")
+  (calc-rewrite-selection "DistribRules" many "dist")
+)
+
+(defun calc-sel-merge (many)
+  (interactive "P")
+  (calc-rewrite-selection "MergeRules" many "merg")
+)
+
+(defun calc-sel-negate (many)
+  (interactive "P")
+  (calc-rewrite-selection "NegateRules" many "jneg")
+)
+
+(defun calc-sel-invert (many)
+  (interactive "P")
+  (calc-rewrite-selection "InvertRules" many "jinv")
+)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/calc/macedit.el	Tue Nov 06 18:59:06 2001 +0000
@@ -0,0 +1,716 @@
+;; Keyboard macro editor for GNU Emacs.  Version 1.05.
+;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+;; Written by Dave Gillespie, daveg@synaptics.com.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY.  No author or distributor
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing.  Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License.   A copy of this license is
+;; supposed to have been given to you along with GNU Emacs so you
+;; can know your rights and responsibilities.  It should be in a
+;; file named COPYING.  Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+
+;; Installation:
+;;   (autoload 'edit-kbd-macro "macedit" "Edit a named keyboard macro" t)
+;;   (autoload 'edit-last-kbd-macro "macedit" "Edit a keyboard macro" t)
+;;   (autoload 'read-kbd-macro "macedit" "Parse region as keyboard macro" t)
+
+
+
+;; To use, type `M-x edit-last-kbd-macro' to edit the most recently
+;; defined keyboard macro.  If you have used `M-x name-last-kbd-macro'
+;; to give a keyboard macro a name, type `M-x edit-kbd-macro' to edit
+;; the macro by name.  When you are done editing, type `C-c C-c' to
+;; record your changes back into the original keyboard macro.
+
+
+
+
+;;; The user-level commands for editing macros.
+
+;;;###autoload
+(defun edit-last-kbd-macro (&optional prefix buffer hook)
+  "Edit the most recently defined keyboard macro."
+  (interactive "P")
+  (MacEdit-edit-macro last-kbd-macro
+		      (function (lambda (x arg) (setq last-kbd-macro x)))
+		      prefix buffer hook)
+)
+
+;;;###autoload
+(defun edit-kbd-macro (cmd &optional prefix buffer hook in-hook out-hook)
+  "Edit a keyboard macro which has been assigned a name by name-last-kbd-macro.
+\(See also edit-last-kbd-macro.)"
+  (interactive "CCommand name: \nP")
+  (and cmd
+       (MacEdit-edit-macro (if in-hook
+			       (funcall in-hook cmd)
+			     (symbol-function cmd))
+			   (or out-hook
+			       (list 'lambda '(x arg)
+				     (list 'fset
+					   (list 'quote cmd)
+					   'x)))
+			   prefix buffer hook cmd))
+)
+
+;;;###autoload
+(defun read-kbd-macro (start &optional end)
+  "Read the region as a keyboard macro definition.
+The region is interpreted as spelled-out keystrokes, e.g., `M-x abc RET'.
+The resulting macro is installed as the \"current\" keyboard macro.
+
+Symbols:  RET, SPC, TAB, DEL, LFD, NUL; C-key; M-key.  (Must be uppercase.)
+          REM marks the rest of a line as a comment.
+          Whitespace is ignored; other characters are copied into the macro."
+  (interactive "r")
+  (if (stringp start)
+      (setq last-kbd-macro (MacEdit-parse-keys start))
+    (setq last-kbd-macro (MacEdit-parse-keys (buffer-substring start end)))
+    (if (and (string-match "\\`\C-x(" last-kbd-macro)
+	     (string-match "\C-x)\\'" last-kbd-macro))
+	(setq last-kbd-macro (substring last-kbd-macro 2 -2))))
+)
+
+
+
+
+;;; Formatting a keyboard macro as human-readable text.
+
+(defun MacEdit-print-macro (macro-str local-map)
+  (let ((save-map (current-local-map))
+	(print-escape-newlines t)
+	key-symbol key-str key-last prefix-arg this-prefix)
+    (unwind-protect
+	(progn
+	  (use-local-map local-map)
+	  (while (MacEdit-peek-char)
+	    (MacEdit-read-key)
+	    (setq this-prefix prefix-arg)
+	    (or (memq key-symbol '(digit-argument
+				   negative-argument
+				   universal-argument))
+		(null prefix-arg)
+		(progn
+		  (cond ((consp prefix-arg)
+			 (insert (format "prefix-arg (%d)\n"
+					 (car prefix-arg))))
+			((eq prefix-arg '-)
+			 (insert "prefix-arg -\n"))
+			((numberp prefix-arg)
+			 (insert (format "prefix-arg %d\n" prefix-arg))))
+		  (setq prefix-arg nil)))
+	    (cond ((null key-symbol)
+		   (insert "type \"")
+		   (MacEdit-insert-string macro-str)
+		   (insert "\"\n")
+		   (setq macro-str ""))
+		  ((stringp key-symbol)   ; key defined by another kbd macro
+		   (insert "type \"")
+		   (MacEdit-insert-string key-symbol)
+		   (insert "\"\n"))
+		  ((eq key-symbol 'digit-argument)
+		   (MacEdit-prefix-arg key-last nil prefix-arg))
+		  ((eq key-symbol 'negative-argument)
+		   (MacEdit-prefix-arg ?- nil prefix-arg))
+		  ((eq key-symbol 'universal-argument)
+		   (let* ((c-u 4) (argstartchar key-last)
+			  (char (MacEdit-read-char)))
+		     (while (= char argstartchar)
+		       (setq c-u (* 4 c-u)
+			     char (MacEdit-read-char)))
+		     (MacEdit-prefix-arg char c-u nil)))
+		  ((eq key-symbol 'self-insert-command)
+		   (insert "insert ")
+		   (if (and (>= key-last 32) (<= key-last 126))
+		       (let ((str ""))
+			 (while (or (and (eq key-symbol
+					     'self-insert-command)
+					 (< (length str) 60)
+					 (>= key-last 32)
+					 (<= key-last 126))
+				    (and (memq key-symbol
+					       '(backward-delete-char
+						 delete-backward-char
+						 backward-delete-char-untabify))
+					 (> (length str) 0)))
+			   (if (eq key-symbol 'self-insert-command)
+			       (setq str (concat str
+						 (char-to-string key-last)))
+			     (setq str (substring str 0 -1)))
+			   (MacEdit-read-key))
+			 (insert "\"" str "\"\n")
+			 (MacEdit-unread-chars key-str))
+		     (insert "\"")
+		     (MacEdit-insert-string (char-to-string key-last))
+		     (insert "\"\n")))
+		  ((and (eq key-symbol 'quoted-insert)
+			(MacEdit-peek-char))
+		   (insert "quoted-insert\n")
+		   (let ((ch (MacEdit-read-char))
+			 ch2)
+		     (if (and (>= ch ?0) (<= ch ?7))
+			 (progn
+			   (setq ch (- ch ?0)
+				 ch2 (MacEdit-read-char))
+			   (if ch2
+			       (if (and (>= ch2 ?0) (<= ch2 ?7))
+				   (progn
+				     (setq ch (+ (* ch 8) (- ch2 ?0))
+					   ch2 (MacEdit-read-char))
+				     (if ch2
+					 (if (and (>= ch2 ?0) (<= ch2 ?7))
+					     (setq ch (+ (* ch 8) (- ch2 ?0)))
+					   (MacEdit-unread-chars ch2))))
+				 (MacEdit-unread-chars ch2)))))
+		     (if (or (and (>= ch ?0) (<= ch ?7))
+			     (< ch 32) (> ch 126))
+			 (insert (format "type \"\\%03o\"\n" ch))
+		       (insert "type \"" (char-to-string ch) "\"\n"))))
+		  ((memq key-symbol '(isearch-forward
+				      isearch-backward
+				      isearch-forward-regexp
+				      isearch-backward-regexp))
+		   (insert (symbol-name key-symbol) "\n")
+		   (MacEdit-isearch-argument))
+		  ((eq key-symbol 'execute-extended-command)
+		   (MacEdit-read-argument obarray 'commandp))
+		  (t
+		   (let ((cust (get key-symbol 'MacEdit-print)))
+		     (if cust
+			 (funcall cust)
+		       (insert (symbol-name key-symbol))
+		       (indent-to 30)
+		       (insert " # ")
+		       (MacEdit-insert-string key-str)
+		       (insert "\n")
+		       (let ((int (MacEdit-get-interactive key-symbol)))
+			 (if (string-match "\\`\\*" int)
+			     (setq int (substring int 1)))
+			 (while (> (length int) 0)
+			   (cond ((= (aref int 0) ?a)
+				  (MacEdit-read-argument
+				   obarray nil))
+				 ((memq (aref int 0) '(?b ?B ?D ?f ?F ?n
+							  ?s ?S ?x ?X))
+				  (MacEdit-read-argument))
+				 ((and (= (aref int 0) ?c)
+				       (MacEdit-peek-char))
+				  (insert "type \"")
+				  (MacEdit-insert-string
+				   (char-to-string
+				    (MacEdit-read-char)))
+				  (insert "\"\n"))
+				 ((= (aref int 0) ?C)
+				  (MacEdit-read-argument
+				   obarray 'commandp))
+				 ((= (aref int 0) ?k)
+				  (MacEdit-read-key)
+				  (if key-symbol
+				      (progn
+					(insert "type \"")
+					(MacEdit-insert-string key-str)
+					(insert "\"\n"))
+				    (MacEdit-unread-chars key-str)))
+				 ((= (aref int 0) ?N)
+				  (or this-prefix
+				      (MacEdit-read-argument)))
+				 ((= (aref int 0) ?v)
+				  (MacEdit-read-argument
+				   obarray 'user-variable-p)))
+			   (let ((nl (string-match "\n" int)))
+			     (setq int (if nl
+					   (substring int (1+ nl))
+					 "")))))))))))
+      (use-local-map save-map)))
+)
+
+(defun MacEdit-prefix-arg (char c-u value)
+  (let ((sign 1))
+    (if (and (numberp value) (< value 0))
+	(setq sign -1 value (- value)))
+    (if (eq value '-)
+	(setq sign -1 value nil))
+    (while (and char (= ?- char))
+      (setq sign (- sign) c-u nil)
+      (setq char (MacEdit-read-char)))
+    (while (and char (>= char ?0) (<= char ?9))
+      (setq value (+ (* (if (numberp value) value 0) 10) (- char ?0)) c-u nil)
+      (setq char (MacEdit-read-char)))
+    (setq prefix-arg
+	  (cond (c-u (list c-u))
+		((numberp value) (* value sign))
+		((= sign -1) '-)))
+    (MacEdit-unread-chars char))
+)
+
+(defun MacEdit-insert-string (str)
+  (let ((i 0) j ch)
+    (while (< i (length str))
+      (if (and (> (setq ch (aref str i)) 127)
+	       (< ch 160))
+	  (progn
+	    (setq ch (- ch 128))
+	    (insert "\\M-")))
+      (if (< ch 32)
+	  (cond ((= ch 8)  (insert "\\b"))
+		((= ch 9)  (insert "\\t"))
+		((= ch 10) (insert "\\n"))
+		((= ch 13) (insert "\\r"))
+		((= ch 27) (insert "\\e"))
+		(t (insert "\\C-" (char-to-string (downcase (+ ch 64))))))
+	(if (< ch 127)
+	    (if (or (= ch 34) (= ch 92))
+		(insert "\\" (char-to-string ch))
+	      (setq j i)
+	      (while (and (< (setq i (1+ i)) (length str))
+			  (>= (setq ch (aref str i)) 32)
+			  (/= ch 34) (/= ch 92)
+			  (< ch 127)))
+	      (insert (substring str j i))
+	      (setq i (1- i)))
+	  (if (memq ch '(127 255))
+	      (insert (format "\\%03o" ch))
+	    (insert "\\M-" (char-to-string (- ch 128))))))
+      (setq i (1+ i))))
+)
+
+(defun MacEdit-lookup-key (map)
+  (let ((loc (and map (lookup-key map macro-str)))
+	(glob (lookup-key (current-global-map) macro-str))
+	(loc-str macro-str)
+	(glob-str macro-str))
+    (and (integerp loc)
+	 (setq loc-str (substring macro-str 0 loc)
+	       loc (lookup-key map loc-str)))
+    (and (consp loc)
+	 (setq loc nil))
+    (or loc
+	(setq loc-str ""))
+    (and (integerp glob)
+	 (setq glob-str (substring macro-str 0 glob)
+	       glob (lookup-key (current-global-map) glob-str)))
+    (and (consp glob)
+	 (setq glob nil))
+    (or glob
+	(setq glob-str ""))
+    (if (> (length glob-str) (length loc-str))
+	(setq key-symbol glob
+	      key-str glob-str)
+      (setq key-symbol loc
+	    key-str loc-str))
+    (setq key-last (and (> (length key-str) 0)
+			(logand (aref key-str (1- (length key-str))) 127)))
+    key-symbol)
+)
+
+(defun MacEdit-read-argument (&optional obarray pred)   ;; currently ignored
+  (let ((str "")
+	(min-bsp 0)
+	(exec (eq key-symbol 'execute-extended-command))
+	str-base)
+    (while (progn
+	     (MacEdit-lookup-key (current-global-map))
+	     (or (and (eq key-symbol 'self-insert-command)
+		      (< (length str) 60))
+		 (memq key-symbol
+			    '(backward-delete-char
+			      delete-backward-char
+			      backward-delete-char-untabify))
+		 (eq key-last 9)))
+      (setq macro-str (substring macro-str (length key-str)))
+      (or (and (eq key-last 9)
+	       obarray
+	       (let ((comp (try-completion str obarray pred)))
+		 (and (stringp comp)
+		      (> (length comp) (length str))
+		      (setq str comp))))
+	  (if (or (eq key-symbol 'self-insert-command)
+		  (and (or (eq key-last 9)
+			   (<= (length str) min-bsp))
+		       (setq min-bsp (+ (length str) (length key-str)))))
+	      (setq str (concat str key-str))
+	    (setq str (substring str 0 -1)))))
+    (setq str-base str
+	  str (concat str key-str)
+	  macro-str (substring macro-str (length key-str)))
+    (if exec
+	(let ((comp (try-completion str-base obarray pred)))
+	  (if (if (stringp comp)
+		  (and (commandp (intern comp))
+		       (setq str-base comp))
+		(commandp (intern str-base)))
+	      (insert str-base "\n")
+	    (insert "execute-extended-command\n")
+	    (insert "type \"")
+	    (MacEdit-insert-string str)
+	    (insert "\"\n")))
+      (if (> (length str) 0)
+	  (progn
+	    (insert "type \"")
+	    (MacEdit-insert-string str)
+	    (insert "\"\n")))))
+)
+
+(defun MacEdit-isearch-argument ()
+  (let ((str "")
+	(min-bsp 0)
+	ch)
+    (while (and (setq ch (MacEdit-read-char))
+		(or (<= ch 127) (not search-exit-option))
+		(not (eq ch search-exit-char))
+		(or (eq ch search-repeat-char)
+		    (eq ch search-reverse-char)
+		    (eq ch search-delete-char)
+		    (eq ch search-yank-word-char)
+		    (eq ch search-yank-line-char)
+		    (eq ch search-quote-char)
+		    (eq ch ?\r)
+		    (eq ch ?\t)
+		    (not search-exit-option)
+		    (and (/= ch 127) (>= ch 32))))
+      (if (and (eq ch search-quote-char)
+	       (MacEdit-peek-char))
+	  (setq str (concat str (char-to-string ch)
+			    (char-to-string (MacEdit-read-char)))
+		min-bsp (length str))
+	(if (or (and (< ch 127) (>= ch 32))
+		(eq ch search-yank-word-char)
+		(eq ch search-yank-line-char)
+		(and (or (not (eq ch search-delete-char))
+			 (<= (length str) min-bsp))
+		     (setq min-bsp (1+ (length str)))))
+	    (setq str (concat str (char-to-string ch)))
+	  (setq str (substring str 0 -1)))))
+    (if (eq ch search-exit-char)
+	(if (= (length str) 0)  ;; non-incremental search
+	    (progn
+	      (setq str (concat str (char-to-string ch)))
+	      (and (eq (MacEdit-peek-char) ?\C-w)
+		   (progn
+		     (setq str (concat str "\C-w"))
+		     (MacEdit-read-char)))
+	      (if (> (length str) 0)
+		  (progn
+		    (insert "type \"")
+		    (MacEdit-insert-string str)
+		    (insert "\"\n")))
+	      (MacEdit-read-argument)
+	      (setq str "")))
+      (MacEdit-unread-chars ch))
+    (if (> (length str) 0)
+	(progn
+	  (insert "type \"")
+	  (MacEdit-insert-string str)
+	  (insert "\\e\"\n"))))
+)
+
+;;; Get the next keystroke-sequence from the input stream.
+;;; Sets key-symbol, key-str, and key-last as a side effect.
+(defun MacEdit-read-key ()
+  (MacEdit-lookup-key (current-local-map))
+  (and key-symbol
+       (setq macro-str (substring macro-str (length key-str))))
+)
+
+(defun MacEdit-peek-char ()
+  (and (> (length macro-str) 0)
+       (aref macro-str 0))
+)
+
+(defun MacEdit-read-char ()
+  (and (> (length macro-str) 0)
+       (prog1
+	   (aref macro-str 0)
+	 (setq macro-str (substring macro-str 1))))
+)
+
+(defun MacEdit-unread-chars (chars)
+  (and (integerp chars)
+       (setq chars (char-to-string chars)))
+  (and chars
+       (setq macro-str (concat chars macro-str)))
+)
+
+(defun MacEdit-dump (mac)
+  (set-mark-command nil)
+  (insert "\n\n")
+  (MacEdit-print-macro mac (current-local-map))
+)
+
+
+
+;;; Parse a string of spelled-out keystrokes, as produced by key-description.
+
+(defun MacEdit-parse-keys (str)
+  (let ((pos 0)
+	(mac "")
+	part)
+    (while (and (< pos (length str))
+		(string-match "[^ \t\n]+" str pos))
+      (setq pos (match-end 0)
+	    part (substring str (match-beginning 0) (match-end 0))
+	    mac (concat mac
+			(if (and (> (length part) 2)
+				 (= (aref part 1) ?-)
+				 (= (aref part 0) ?M))
+			    (progn
+			      (setq part (substring part 2))
+			      "\e")
+			  (if (and (> (length part) 4)
+				   (= (aref part 0) ?C)
+				   (= (aref part 1) ?-)
+				   (= (aref part 2) ?M)
+				   (= (aref part 3) ?-))
+			      (progn
+				(setq part (concat "C-" (substring part 4)))
+				"\e")
+			    ""))
+			(or (cdr (assoc part '( ( "NUL" . "\0" )
+						( "RET" . "\r" )
+						( "LFD" . "\n" )
+						( "TAB" . "\t" )
+						( "ESC" . "\e" )
+						( "SPC" . " " )
+						( "DEL" . "\177" )
+						( "C-?" . "\177" )
+						( "C-2" . "\0" )
+						( "C-SPC" . "\0") )))
+			    (and (equal part "REM")
+				 (setq pos (or (string-match "\n" str pos)
+					       (length str)))
+				 "")
+			    (and (= (length part) 3)
+				 (= (aref part 0) ?C)
+				 (= (aref part 1) ?-)
+				 (char-to-string (logand (aref part 2) 31)))
+			    part))))
+    mac)
+)
+
+
+
+
+;;; Parse a keyboard macro description in MacEdit-print-macro's format.
+
+(defun MacEdit-read-macro (&optional map)
+  (or map (setq map (current-local-map)))
+  (let ((macro-str ""))
+    (while (not (progn
+		  (skip-chars-forward " \t\n")
+		  (eobp)))
+      (cond ((looking-at "#"))   ;; comment
+	    ((looking-at "prefix-arg[ \t]*-[ \t]*\n")
+	     (MacEdit-append-chars "\C-u-"))
+	    ((looking-at "prefix-arg[ \t]*\\(-?[0-9]+\\)[ \t]*\n")
+	     (MacEdit-append-chars (concat "\C-u" (MacEdit-match-string 1))))
+	    ((looking-at "prefix-arg[ \t]*(\\([0-9]+\\))[ \t]*\n")
+	     (let ((val (string-to-int (MacEdit-match-string 1))))
+	       (while (> val 1)
+		 (or (= (% val 4) 0)
+		     (error "Bad prefix argument value"))
+		 (MacEdit-append-chars "\C-u")
+		 (setq val (/ val 4)))))
+	    ((looking-at "prefix-arg")
+	     (error "Bad prefix argument syntax"))
+	    ((looking-at "insert ")
+	     (forward-char 7)
+	     (MacEdit-append-chars (read (current-buffer)))
+	     (if (< (current-column) 7)
+		 (forward-line -1)))
+	    ((looking-at "type ")
+	     (forward-char 5)
+	     (MacEdit-append-chars (read (current-buffer)))
+	     (if (< (current-column) 5)
+		 (forward-line -1)))
+	    ((looking-at "keys \\(.*\\)\n")
+	     (goto-char (1- (match-end 0)))
+	     (MacEdit-append-chars (MacEdit-parse-keys
+				    (buffer-substring (match-beginning 1)
+						      (match-end 1)))))
+	    ((looking-at "\\([-a-zA-z0-9_]+\\)[ \t]*\\(.*\\)\n")
+	     (let* ((func (intern (MacEdit-match-string 1)))
+		    (arg (MacEdit-match-string 2))
+		    (cust (get func 'MacEdit-read)))
+	       (if cust
+		   (funcall cust arg)
+		 (or (commandp func)
+		     (error "Not an Emacs command"))
+		 (or (equal arg "")
+		     (string-match "\\`#" arg)
+		     (error "Unexpected argument to command"))
+		 (let ((keys
+			(or (where-is-internal func map t)
+			    (where-is-internal func (current-global-map) t))))
+		   (if keys
+		       (MacEdit-append-chars keys)
+		     (MacEdit-append-chars (concat "\ex"
+						   (symbol-name func)
+						   "\n")))))))
+	    (t (error "Syntax error")))
+      (forward-line 1))
+    macro-str)
+)
+
+(defun MacEdit-append-chars (chars)
+  (setq macro-str (concat macro-str chars))
+)
+
+(defun MacEdit-match-string (n)
+  (if (match-beginning n)
+      (buffer-substring (match-beginning n) (match-end n))
+    "")
+)
+
+
+
+(defun MacEdit-get-interactive (func)
+  (if (symbolp func)
+      (let ((cust (get func 'MacEdit-interactive)))
+	(if cust
+	    cust
+	  (MacEdit-get-interactive (symbol-function func))))
+    (or (and (eq (car-safe func) 'lambda)
+	     (let ((int (if (consp (nth 2 func))
+			    (nth 2 func)
+			  (nth 3 func))))
+	       (and (eq (car-safe int) 'interactive)
+		    (stringp (nth 1 int))
+		    (nth 1 int))))
+	""))
+)
+
+(put 'search-forward           'MacEdit-interactive "s")
+(put 'search-backward          'MacEdit-interactive "s")
+(put 'word-search-forward      'MacEdit-interactive "s")
+(put 'word-search-backward     'MacEdit-interactive "s")
+(put 're-search-forward        'MacEdit-interactive "s")
+(put 're-search-backward       'MacEdit-interactive "s")
+(put 'switch-to-buffer         'MacEdit-interactive "B")
+(put 'kill-buffer              'MacEdit-interactive "B")
+(put 'rename-buffer            'MacEdit-interactive "B\nB")
+(put 'goto-char                'MacEdit-interactive "N")
+(put 'global-set-key           'MacEdit-interactive "k\nC")
+(put 'global-unset-key         'MacEdit-interactive "k")
+(put 'local-set-key            'MacEdit-interactive "k\nC")
+(put 'local-unset-key          'MacEdit-interactive "k")
+
+;;; Think about kbd-macro-query
+
+
+
+;;; Edit a keyboard macro in another buffer.
+;;; (Prefix argument is currently ignored.)
+
+(defun MacEdit-edit-macro (mac repl &optional prefix buffer hook arg)
+  (or (stringp mac)
+      (error "Not a keyboard macro"))
+  (let ((oldbuf (current-buffer))
+	(from-calc (and (get-buffer-window "*Calculator*")
+			(eq (lookup-key (current-global-map) "\e#")
+			    'calc-dispatch)))
+	(local (current-local-map))
+	(buf (get-buffer-create (or buffer "*Edit Macro*"))))
+    (set-buffer buf)
+    (kill-all-local-variables)
+    (use-local-map MacEdit-mode-map)
+    (setq buffer-read-only nil)
+    (setq major-mode 'MacEdit-mode)
+    (setq mode-name "Edit Macro")
+    (make-local-variable 'MacEdit-original-buffer)
+    (setq MacEdit-original-buffer oldbuf)
+    (make-local-variable 'MacEdit-replace-function)
+    (setq MacEdit-replace-function repl)
+    (make-local-variable 'MacEdit-replace-argument)
+    (setq MacEdit-replace-argument arg)
+    (make-local-variable 'MacEdit-finish-hook)
+    (setq MacEdit-finish-hook hook)
+    (erase-buffer)
+    (insert "# Keyboard Macro Editor.  Press "
+	    (if from-calc "M-# M-#" "C-c C-c")
+	    " to finish; press "
+	    (if from-calc "M-# x" "C-x k RET")
+	    " to cancel.\n")
+    (insert "# Original keys: " (key-description mac) "\n\n")
+    (message "Formatting keyboard macro...")
+    (MacEdit-print-macro mac local)
+    (switch-to-buffer buf)
+    (goto-char (point-min))
+    (forward-line 3)
+    (recenter '(4))
+    (set-buffer-modified-p nil)
+    (message "Formatting keyboard macro...done")
+    (run-hooks 'MacEdit-format-hook))
+)
+
+(defun MacEdit-finish-edit ()
+  (interactive)
+  (or (and (boundp 'MacEdit-original-buffer)
+	   (boundp 'MacEdit-replace-function)
+	   (boundp 'MacEdit-replace-argument)
+	   (boundp 'MacEdit-finish-hook)
+	   (eq major-mode 'MacEdit-mode))
+      (error "This command is valid only in buffers created by edit-kbd-macro."))
+  (let ((buf (current-buffer))
+	(str (buffer-string))
+	(func MacEdit-replace-function)
+	(arg MacEdit-replace-argument)
+	(hook MacEdit-finish-hook))
+    (goto-char (point-min))
+    (and (buffer-modified-p)
+	 func
+	 (progn
+	   (message "Compiling keyboard macro...")
+	   (run-hooks 'MacEdit-compile-hook)
+	   (let ((mac (MacEdit-read-macro
+		       (and (buffer-name MacEdit-original-buffer)
+			    (save-excursion
+			      (set-buffer MacEdit-original-buffer)
+			      (current-local-map))))))
+	     (and (buffer-name MacEdit-original-buffer)
+		  (switch-to-buffer MacEdit-original-buffer))
+	     (funcall func mac arg))
+	   (message "Compiling keyboard macro...done")))
+    (kill-buffer buf)
+    (if hook
+	(funcall hook arg)))
+)
+
+(defun MacEdit-cancel-edit ()
+  (interactive)
+  (if (eq major-mode 'MacEdit-mode)
+      (set-buffer-modified-p nil))
+  (MacEdit-finish-edit)
+  (message "(Cancelled)")
+)
+
+(defun MacEdit-mode ()
+  "Keyboard Macro Editing mode.  Press C-c C-c to save and exit.
+To abort the edit, just kill this buffer with C-x k RET.
+
+The keyboard macro is represented as a series of M-x style command names.
+Keystrokes which do not correspond to simple M-x commands are written as
+\"type\" commands.  When you press C-c C-c, MacEdit converts each command
+back into a suitable keystroke sequence; \"type\" commands are converted
+directly back into keystrokes."
+  (interactive)
+  (error "This mode can be enabled only by edit-kbd-macro or edit-last-kbd-macro.")
+)
+(put 'MacEdit-mode 'mode-class 'special)
+
+(defvar MacEdit-mode-map nil)
+(if MacEdit-mode-map
+    ()
+  (setq MacEdit-mode-map (make-sparse-keymap))
+  (define-key MacEdit-mode-map "\C-c\C-c" 'MacEdit-finish-edit)
+)
+