* emacs-lisp/byte-opt.el (byte-compile-trueconstp): Handle more
[bpt/emacs.git] / lisp / calc / calc.el
CommitLineData
7054901c 1;;; calc.el --- the GNU Emacs calculator
f269b73e 2
58ba2f8f 3;; Copyright (C) 1990, 1991, 1992, 1993, 2001, 2002, 2003, 2004,
f0fa15c5 4;; 2005, 2006, 2007 Free Software Foundation, Inc.
f269b73e
CW
5
6;; Author: David Gillespie <daveg@synaptics.com>
b943a9d6 7;; Maintainer: Jay Belanger <jay.p.belanger@gmail.com>
f269b73e 8;; Keywords: convenience, extensions
58ba2f8f 9;; Version: 2.1
136211a9
EZ
10
11;; This file is part of GNU Emacs.
12
7c671b23
GM
13;; GNU Emacs is free software; you can redistribute it and/or modify
14;; it under the terms of the GNU General Public License as published by
075969b4 15;; the Free Software Foundation; either version 3, or (at your option)
7c671b23
GM
16;; any later version.
17
136211a9 18;; GNU Emacs is distributed in the hope that it will be useful,
7c671b23
GM
19;; but WITHOUT ANY WARRANTY; without even the implied warranty of
20;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21;; GNU General Public License for more details.
22
23;; You should have received a copy of the GNU General Public License
24;; along with GNU Emacs; see the file COPYING. If not, write to the
25;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
26;; Boston, MA 02110-1301, USA.
136211a9 27
f269b73e 28;;; Commentary:
136211a9 29
906bd0ef
CW
30;; Calc is split into many files. This file is the main entry point.
31;; This file includes autoload commands for various other basic Calc
32;; facilities. The more advanced features are based in calc-ext, which
33;; in turn contains autoloads for the rest of the Calc files. This
34;; odd set of interactions is designed to make Calc's loading time
35;; be as short as possible when only simple calculations are needed.
36
37;; Original author's address:
38;; Dave Gillespie, daveg@synaptics.com, uunet!synaptx!daveg.
39;; Synaptics, Inc., 2698 Orchard Parkway, San Jose, CA 95134.
40;;
41;; The old address daveg@csvax.cs.caltech.edu will continue to
42;; work for the foreseeable future.
43;;
44;; Bug reports and suggestions are always welcome! (Type M-x
45;; report-calc-bug to send them).
46
47;; All functions, macros, and Lisp variables defined here begin with one
48;; of the prefixes "math", "Math", or "calc", with the exceptions of
49;; "full-calc", "full-calc-keypad", "another-calc", "quick-calc",
50;; "report-calc-bug", and "defmath". User-accessible variables begin
51;; with "var-".
52
53;;; TODO:
54
55;; Fix rewrite mechanism to do less gratuitous rearrangement of terms.
56;; Implement a pattern-based "refers" predicate.
57;;
58;; Make it possible to Undo a selection command.
59;; Figure out how to allow selecting rows of matrices.
60;; If cursor was in selection before, move it after j n, j p, j L, etc.
61;; Consider reimplementing calc-delete-selection using rewrites.
62;;
63;; Implement line-breaking in non-flat compositions (is this desirable?).
64;; Implement matrix formatting with multi-line components.
65;;
66;; Have "Z R" define a user command based on a set of rewrite rules.
67;; Support "incf" and "decf" in defmath definitions.
68;; Have defmath generate calls to calc-binary-op or calc-unary-op.
69;; Make some way to define algebraic functions using keyboard macros.
70;;
71;; Allow calc-word-size=0 => Common Lisp-style signed bitwise arithmetic.
72;; Consider digamma function (and thus arb. prec. Euler's gamma constant).
73;; May as well make continued-fractions stuff available to the user.
74;;
75;; How about matrix eigenvalues, SVD, pseudo-inverse, etc.?
76;; Should cache matrix inverses as well as decompositions.
77;; If dividing by a non-square matrix, use least-squares automatically.
78;; Consider supporting matrix exponentials.
79;;
80;; Have ninteg detect and work around singularities at the endpoints.
81;; Use an adaptive subdivision algorithm for ninteg.
82;; Provide nsum and nprod to go along with ninteg.
83;;
84;; Handle TeX-mode parsing of \matrix{ ... } where ... contains braces.
85;; Support AmS-TeX's \{d,t,}frac, \{d,t,}binom notations.
86;; Format and parse sums and products in Eqn and Math modes.
87;;
88;; Get math-read-big-expr to read sums, products, etc.
89;; Change calc-grab-region to use math-read-big-expr.
90;; Have a way to define functions using := in Embedded Mode.
91;;
92;; Support polar plotting with GNUPLOT.
93;; Make a calc-graph-histogram function.
94;;
95;; Replace hokey formulas for complex functions with formulas designed
96;; to minimize roundoff while maintaining the proper branch cuts.
97;; Test accuracy of advanced math functions over whole complex plane.
98;; Extend Bessel functions to provide arbitrary precision.
99;; Extend advanced math functions to handle error forms and intervals.
100;; Provide a better implementation for math-sin-cos-raw.
101;; Provide a better implementation for math-hypot.
102;; Provide a better implementation for math-make-frac.
103;; Provide a better implementation for calcFunc-prfac.
104;; Provide a better implementation for calcFunc-factor.
105;;
106;; Provide more examples in the tutorial section of the manual.
107;; Cover in the tutorial: simplification modes, declarations,
108;; bitwise stuff, selections, matrix mapping, financial functions.
109;; Provide more Lisp programming examples in the manual.
110;; Finish the Internals section of the manual (and bring it up to date).
111;;
112;; Tim suggests adding spreadsheet-like features.
113;; Implement language modes for Gnuplot, Lisp, Ada, APL, ...?
114;;
115;; For atan series, if x > tan(pi/12) (about 0.268) reduce using the identity
116;; atan(x) = atan((x * sqrt(3) - 1) / (sqrt(3) + x)) + pi/6.
117;;
118;; A better integration algorithm:
119;; Use breadth-first instead of depth-first search, as follows:
120;; The integral cache allows unfinished integrals in symbolic notation
121;; on the righthand side. An entry with no unfinished integrals on the
122;; RHS is "complete"; references to it elsewhere are replaced by the
123;; integrated value. More than one cache entry for the same integral
124;; may exist, though if one becomes complete, the others may be deleted.
125;; The integrator works by using every applicable rule (such as
126;; substitution, parts, linearity, etc.) to generate possible righthand
127;; sides, all of which are entered into the cache. Now, as long as the
128;; target integral is not complete (and the time limit has not run out)
129;; choose an incomplete integral from the cache and, for every integral
130;; appearing in its RHS's, add those integrals to the cache using the
131;; same substitition, parts, etc. rules. The cache should be organized
132;; as a priority queue, choosing the "simplest" incomplete integral at
133;; each step, or choosing randomly among equally simple integrals.
134;; Simplicity equals small size, and few steps removed from the original
135;; target integral. Note that when the integrator finishes, incomplete
136;; integrals can be left in the cache, so the algorithm can start where
137;; it left off if another similar integral is later requested.
138;; Breadth-first search would avoid the nagging problem of, e.g., whether
139;; to use parts or substitution first, and which decomposition is best.
140;; All are tried, and any path that diverges will quickly be put on the
141;; back burner by the priority queue.
142;; Note: Probably a good idea to call math-simplify-extended before
143;; measuring a formula's simplicity.
144
145;; From: "Robert J. Chassell" <bob@rattlesnake.com>
146;; Subject: Re: fix for `Cannot open load file: calc-alg-3'
147;; To: walters@debian.org
148;; Date: Sat, 24 Nov 2001 21:44:21 +0000 (UTC)
a1506d29 149;;
906bd0ef 150;; Could you add logistic curve fitting to the current list?
a1506d29 151;;
906bd0ef
CW
152;; (I guess the key binding for a logistic curve would have to be `s'
153;; since a logistic curve is an `s' curve; both `l' and `L' are already
154;; taken for logarithms.)
a1506d29 155;;
906bd0ef 156;; Here is the current list for curve fitting;
a1506d29 157;;
906bd0ef
CW
158;; `1'
159;; Linear or multilinear. a + b x + c y + d z.
a1506d29 160;;
906bd0ef
CW
161;; `2-9'
162;; Polynomials. a + b x + c x^2 + d x^3.
a1506d29 163;;
906bd0ef
CW
164;; `e'
165;; Exponential. a exp(b x) exp(c y).
a1506d29 166;;
906bd0ef
CW
167;; `E'
168;; Base-10 exponential. a 10^(b x) 10^(c y).
a1506d29 169;;
906bd0ef
CW
170;; `x'
171;; Exponential (alternate notation). exp(a + b x + c y).
a1506d29 172;;
906bd0ef
CW
173;; `X'
174;; Base-10 exponential (alternate). 10^(a + b x + c y).
a1506d29 175;;
906bd0ef
CW
176;; `l'
177;; Logarithmic. a + b ln(x) + c ln(y).
a1506d29 178;;
906bd0ef
CW
179;; `L'
180;; Base-10 logarithmic. a + b log10(x) + c log10(y).
a1506d29 181;;
906bd0ef
CW
182;; `^'
183;; General exponential. a b^x c^y.
a1506d29 184;;
906bd0ef
CW
185;; `p'
186;; Power law. a x^b y^c.
a1506d29 187;;
906bd0ef
CW
188;; `q'
189;; Quadratic. a + b (x-c)^2 + d (x-e)^2.
a1506d29 190;;
906bd0ef
CW
191;; `g'
192;; Gaussian. (a / b sqrt(2 pi)) exp(-0.5*((x-c)/b)^2).
a1506d29
JB
193;;
194;;
906bd0ef
CW
195;; Logistic curves are used a great deal in ecology, and in predicting
196;; human actions, such as use of different kinds of energy in a country
197;; (wood, coal, oil, natural gas, etc.) or the number of scientific
198;; papers a person publishes, or the number of movies made.
a1506d29 199;;
906bd0ef
CW
200;; (The less information on which to base the curve, the higher the error
201;; rate. Theodore Modis ran some Monte Carlo simulations and produced
202;; what may be useful set of confidence levels for different amounts of
203;; initial information.)
136211a9 204
f269b73e 205;;; Code:
136211a9 206
91e51f9a 207(require 'calc-macs)
136211a9 208
60afc271 209(defgroup calc nil
111a5355 210 "GNU Calc."
60afc271 211 :prefix "calc-"
462789ab
LK
212 :tag "Calc"
213 :group 'applications)
60afc271 214
136211a9 215;;;###autoload
2a78421d 216(defcustom calc-settings-file
60afc271
JB
217 (convert-standard-filename "~/.calc.el")
218 "*File in which to record permanent settings."
219 :group 'calc
220 :type '(file))
221
222(defcustom calc-language-alist
223 '((latex-mode . latex)
224 (tex-mode . tex)
225 (plain-tex-mode . tex)
226 (context-mode . tex)
227 (nroff-mode . eqn)
228 (pascal-mode . pascal)
229 (c-mode . c)
230 (c++-mode . c)
231 (fortran-mode . fortran)
82f36338
JB
232 (f90-mode . fortran)
233 (texinfo-mode . calc-normal-language))
60afc271
JB
234 "*Alist of major modes with appropriate Calc languages."
235 :group 'calc
2a78421d 236 :type '(alist :key-type (symbol :tag "Major mode")
2f145e58 237 :value-type (symbol :tag "Calc language")))
60afc271 238
2a78421d 239(defcustom calc-embedded-announce-formula
60afc271
JB
240 "%Embed\n\\(% .*\n\\)*"
241 "*A regular expression which is sure to be followed by a calc-embedded formula."
242 :group 'calc
243 :type '(regexp))
244
b2d2748d 245(defcustom calc-embedded-announce-formula-alist
0124a115 246 '((c++-mode . "//Embed\n\\(// .*\n\\)*")
b2d2748d 247 (c-mode . "/\\*Embed\\*/\n\\(/\\* .*\\*/\n\\)*")
0124a115 248 (f90-mode . "!Embed\n\\(! .*\n\\)*")
b2d2748d 249 (fortran-mode . "C Embed\n\\(C .*\n\\)*")
0124a115
JB
250 (html-helper-mode . "<!-- Embed -->\n\\(<!-- .* -->\n\\)*")
251 (html-mode . "<!-- Embed -->\n\\(<!-- .* -->\n\\)*")
252 (nroff-mode . "\\\\\"Embed\n\\(\\\\\" .*\n\\)*")
253 (pascal-mode . "{Embed}\n\\({.*}\n\\)*")
254 (sgml-mode . "<!-- Embed -->\n\\(<!-- .* -->\n\\)*")
255 (xml-mode . "<!-- Embed -->\n\\(<!-- .* -->\n\\)*")
256 (texinfo-mode . "@c Embed\n\\(@c .*\n\\)*"))
b2d2748d
JB
257 "*Alist of major modes with appropriate values for `calc-embedded-announce-formula'."
258 :group 'calc
259 :type '(alist :key-type (symbol :tag "Major mode")
260 :value-type (regexp :tag "Regexp to announce formula")))
261
2a78421d 262(defcustom calc-embedded-open-formula
60afc271
JB
263 "\\`\\|^\n\\|\\$\\$?\\|\\\\\\[\\|^\\\\begin[^{].*\n\\|^\\\\begin{.*[^x]}.*\n\\|^@.*\n\\|^\\.EQ.*\n\\|\\\\(\\|^%\n\\|^\\.\\\\\"\n"
264 "*A regular expression for the opening delimiter of a formula used by calc-embedded."
265 :group 'calc
266 :type '(regexp))
267
2a78421d 268(defcustom calc-embedded-close-formula
60afc271
JB
269 "\\'\\|\n$\\|\\$\\$?\\|\\\\]\\|^\\\\end[^{].*\n\\|^\\\\end{.*[^x]}.*\n\\|^@.*\n\\|^\\.EN.*\n\\|\\\\)\\|\n%\n\\|^\\.\\\\\"\n"
270 "*A regular expression for the closing delimiter of a formula used by calc-embedded."
271 :group 'calc
272 :type '(regexp))
273
b2d2748d
JB
274(defcustom calc-embedded-open-close-formula-alist
275 nil
276 "*Alist of major modes with pairs of formula delimiters used by calc-embedded."
277 :group 'calc
278 :type '(alist :key-type (symbol :tag "Major mode")
279 :value-type (list (regexp :tag "Opening formula delimiter")
280 (regexp :tag "Closing formula delimiter"))))
281
2a78421d 282(defcustom calc-embedded-open-word
60afc271
JB
283 "^\\|[^-+0-9.eE]"
284 "*A regular expression for the opening delimiter of a formula used by calc-embedded-word."
285 :group 'calc
286 :type '(regexp))
287
2a78421d 288(defcustom calc-embedded-close-word
60afc271
JB
289 "$\\|[^-+0-9.eE]"
290 "*A regular expression for the closing delimiter of a formula used by calc-embedded-word."
291 :group 'calc
292 :type '(regexp))
293
b2d2748d
JB
294(defcustom calc-embedded-open-close-word-alist
295 nil
296 "*Alist of major modes with pairs of word delimiters used by calc-embedded."
297 :group 'calc
298 :type '(alist :key-type (symbol :tag "Major mode")
299 :value-type (list (regexp :tag "Opening word delimiter")
300 (regexp :tag "Closing word delimiter"))))
301
2a78421d 302(defcustom calc-embedded-open-plain
60afc271
JB
303 "%%% "
304 "*A string which is the opening delimiter for a \"plain\" formula.
305If calc-show-plain mode is enabled, this is inserted at the front of
306each formula."
307 :group 'calc
308 :type '(string))
309
2a78421d 310(defcustom calc-embedded-close-plain
60afc271
JB
311 " %%%\n"
312 "*A string which is the closing delimiter for a \"plain\" formula.
313See calc-embedded-open-plain."
314 :group 'calc
315 :type '(string))
316
b2d2748d 317(defcustom calc-embedded-open-close-plain-alist
0124a115 318 '((c++-mode "// %% " " %%\n")
b2d2748d 319 (c-mode "/* %% " " %% */\n")
0124a115 320 (f90-mode "! %% " " %%\n")
b2d2748d 321 (fortran-mode "C %% " " %%\n")
0124a115
JB
322 (html-helper-mode "<!-- %% " " %% -->\n")
323 (html-mode "<!-- %% " " %% -->\n")
324 (nroff-mode "\\\" %% " " %%\n")
325 (pascal-mode "{%% " " %%}\n")
326 (sgml-mode "<!-- %% " " %% -->\n")
327 (xml-mode "<!-- %% " " %% -->\n")
328 (texinfo-mode "@c %% " " %%\n"))
b2d2748d
JB
329 "*Alist of major modes with pairs of delimiters for \"plain\" formulas."
330 :group 'calc
331 :type '(alist :key-type (symbol :tag "Major mode")
332 :value-type (list (string :tag "Opening \"plain\" delimiter")
333 (string :tag "Closing \"plain\" delimiter"))))
334
2a78421d 335(defcustom calc-embedded-open-new-formula
60afc271
JB
336 "\n\n"
337 "*A string which is inserted at front of formula by calc-embedded-new-formula."
338 :group 'calc
339 :type '(string))
340
2a78421d 341(defcustom calc-embedded-close-new-formula
60afc271
JB
342 "\n\n"
343 "*A string which is inserted at end of formula by calc-embedded-new-formula."
344 :group 'calc
345 :type '(string))
346
b2d2748d
JB
347(defcustom calc-embedded-open-close-new-formula-alist
348 nil
349 "*Alist of major modes with pairs of new formula delimiters used by calc-embedded."
350 :group 'calc
351 :type '(alist :key-type (symbol :tag "Major mode")
352 :value-type (list (string :tag "Opening new formula delimiter")
353 (string :tag "Closing new formula delimiter"))))
354
2a78421d 355(defcustom calc-embedded-open-mode
60afc271
JB
356 "% "
357 "*A string which should precede calc-embedded mode annotations.
358This is not required to be present for user-written mode annotations."
359 :group 'calc
360 :type '(string))
361
2a78421d 362(defcustom calc-embedded-close-mode
60afc271
JB
363 "\n"
364 "*A string which should follow calc-embedded mode annotations.
365This is not required to be present for user-written mode annotations."
366 :group 'calc
367 :type '(string))
368
b2d2748d 369(defcustom calc-embedded-open-close-mode-alist
0124a115 370 '((c++-mode "// " "\n")
b2d2748d 371 (c-mode "/* " " */\n")
0124a115 372 (f90-mode "! " "\n")
b2d2748d 373 (fortran-mode "C " "\n")
0124a115
JB
374 (html-helper-mode "<!-- " " -->\n")
375 (html-mode "<!-- " " -->\n")
376 (nroff-mode "\\\" " "\n")
377 (pascal-mode "{ " " }\n")
378 (sgml-mode "<!-- " " -->\n")
379 (xml-mode "<!-- " " -->\n")
380 (texinfo-mode "@c " "\n"))
b2d2748d
JB
381 "*Alist of major modes with pairs of strings to delimit annotations."
382 :group 'calc
383 :type '(alist :key-type (symbol :tag "Major mode")
384 :value-type (list (string :tag "Opening annotation delimiter")
385 (string :tag "Closing annotation delimiter"))))
386
2a78421d 387(defcustom calc-gnuplot-name
60afc271
JB
388 "gnuplot"
389 "*Name of GNUPLOT program, for calc-graph features."
390 :group 'calc
391 :type '(string))
392
2a78421d 393(defcustom calc-gnuplot-plot-command
60afc271
JB
394 nil
395 "*Name of command for displaying GNUPLOT output; %s = file name to print."
396 :group 'calc
397 :type '(choice (string) (sexp)))
398
2a78421d 399(defcustom calc-gnuplot-print-command
60afc271
JB
400 "lp %s"
401 "*Name of command for printing GNUPLOT output; %s = file name to print."
402 :group 'calc
403 :type '(choice (string) (sexp)))
136211a9 404
515e955e
JB
405(defcustom calc-multiplication-has-precedence
406 t
407 "*If non-nil, multiplication has precedence over division
408in normal mode."
409 :group 'calc
410 :type 'boolean)
411
b943a9d6 412(defvar calc-bug-address "jay.p.belanger@gmail.com"
ed65ed86 413 "Address of the maintainer of Calc, for use by `report-calc-bug'.")
136211a9 414
730576f3
CW
415(defvar calc-scan-for-dels t
416 "If t, scan keymaps to find all DEL-like keys.
417if nil, only DEL itself is mapped to calc-pop.")
136211a9 418
730576f3
CW
419(defvar calc-stack '((top-of-stack 1 nil))
420 "Calculator stack.
421Entries are 3-lists: Formula, Height (in lines), Selection (or nil).")
136211a9 422
730576f3
CW
423(defvar calc-stack-top 1
424 "Index into `calc-stack' of \"top\" of stack.
425This is 1 unless `calc-truncate-stack' has been used.")
136211a9 426
7b2cda38
JB
427(defvar calc-display-sci-high 0
428 "Floating-point numbers with this positive exponent or higher above the
429current precision are displayed in scientific notation in calc-mode.")
430
431(defvar calc-display-sci-low -3
432 "Floating-point numbers with this negative exponent or lower are displayed
433scientific notation in calc-mode.")
434
435(defvar calc-other-modes nil
436 "List of used-defined strings to append to Calculator mode line.")
136211a9 437
7b2cda38
JB
438(defvar calc-Y-help-msgs nil
439 "List of strings for Y prefix help.")
136211a9 440
7b2cda38
JB
441(defvar calc-loaded-settings-file nil
442 "t if `calc-settings-file' has been loaded yet.")
136211a9 443
6c8e7554
JB
444
445(defvar calc-mode-var-list '()
446 "List of variables used in customizing GNU Calc.")
447
448(defmacro defcalcmodevar (var defval &optional doc)
449 `(progn
450 (defvar ,var ,defval ,doc)
451 (add-to-list 'calc-mode-var-list (list (quote ,var) ,defval))))
452
453(defun calc-mode-var-list-restore-default-values ()
454 (mapcar (function (lambda (v) (set (car v) (nth 1 v))))
455 calc-mode-var-list))
456
457(defun calc-mode-var-list-restore-saved-values ()
458 (let ((newvarlist '()))
459 (save-excursion
f1ed747e
JB
460 (let (pos
461 (file (substitute-in-file-name calc-settings-file)))
462 (when (and
463 (file-regular-p file)
464 (set-buffer (find-file-noselect file))
465 (goto-char (point-min))
466 (search-forward ";;; Mode settings stored by Calc" nil t)
467 (progn
468 (forward-line 1)
469 (setq pos (point))
470 (search-forward "\n;;; End of mode settings" nil t)))
6c8e7554
JB
471 (beginning-of-line)
472 (calc-mode-var-list-restore-default-values)
473 (eval-region pos (point))
474 (let ((varlist calc-mode-var-list))
475 (while varlist
476 (let ((var (car varlist)))
477 (setq newvarlist
478 (cons (list (car var) (symbol-value (car var)))
479 newvarlist)))
480 (setq varlist (cdr varlist)))))))
481 (if newvarlist
482 (mapcar (function (lambda (v) (set (car v) (nth 1 v))))
483 newvarlist)
484 (calc-mode-var-list-restore-default-values))))
485
486(defcalcmodevar calc-always-load-extensions nil
487 "If non-nil, load the calc-ext module automatically when calc is loaded.")
488
489(defcalcmodevar calc-line-numbering t
490 "If non-nil, display line numbers in Calculator stack.")
491
492(defcalcmodevar calc-line-breaking t
493 "If non-nil, break long values across multiple lines in Calculator stack.")
494
495(defcalcmodevar calc-display-just nil
496 "If nil, stack display is left-justified.
730576f3
CW
497If `right', stack display is right-justified.
498If `center', stack display is centered.")
136211a9 499
6c8e7554
JB
500(defcalcmodevar calc-display-origin nil
501 "Horizontal origin of displayed stack entries.
730576f3
CW
502In left-justified mode, this is effectively indentation. (Default 0).
503In right-justified mode, this is effectively window width.
504In centered mode, center of stack entry is placed here.")
505
6c8e7554
JB
506(defcalcmodevar calc-number-radix 10
507 "Radix for entry and display of numbers in calc-mode, 2-36.")
730576f3 508
6c8e7554
JB
509(defcalcmodevar calc-leading-zeros nil
510 "If non-nil, leading zeros are provided to pad integers to calc-word-size.")
730576f3 511
6c8e7554
JB
512(defcalcmodevar calc-group-digits nil
513 "If non-nil, group digits in large displayed integers by inserting spaces.
730576f3
CW
514If an integer, group that many digits at a time.
515If t, use 4 for binary and hex, 3 otherwise.")
516
6c8e7554
JB
517(defcalcmodevar calc-group-char ","
518 "The character (in the form of a string) to be used for grouping digits.
730576f3
CW
519This is used only when calc-group-digits mode is on.")
520
6c8e7554
JB
521(defcalcmodevar calc-point-char "."
522 "The character (in the form of a string) to be used as a decimal point.")
2a78421d 523
6c8e7554
JB
524(defcalcmodevar calc-frac-format '(":" nil)
525 "Format of displayed fractions; a string of one or two of \":\" or \"/\".")
730576f3 526
6c8e7554
JB
527(defcalcmodevar calc-prefer-frac nil
528 "If non-nil, prefer fractional over floating-point results.")
730576f3 529
6c8e7554
JB
530(defcalcmodevar calc-hms-format "%s@ %s' %s\""
531 "Format of displayed hours-minutes-seconds angles, a format string.
730576f3
CW
532String must contain three %s marks for hours, minutes, seconds respectively.")
533
6c8e7554
JB
534(defcalcmodevar calc-date-format '((H ":" mm C SS pp " ")
535 Www " " Mmm " " D ", " YYYY)
536 "Format of displayed date forms.")
730576f3 537
6c8e7554
JB
538(defcalcmodevar calc-float-format '(float 0)
539 "Format to use for display of floating-point numbers in calc-mode.
730576f3
CW
540Must be a list of one of the following forms:
541 (float 0) Floating point format, display full precision.
542 (float N) N > 0: Floating point format, at most N significant figures.
543 (float -N) -N < 0: Floating point format, calc-internal-prec - N figs.
544 (fix N) N >= 0: Fixed point format, N places after decimal point.
545 (sci 0) Scientific notation, full precision.
546 (sci N) N > 0: Scientific notation, N significant figures.
547 (sci -N) -N < 0: Scientific notation, calc-internal-prec - N figs.
548 (eng 0) Engineering notation, full precision.
549 (eng N) N > 0: Engineering notation, N significant figures.
550 (eng -N) -N < 0: Engineering notation, calc-internal-prec - N figs.")
551
6c8e7554
JB
552(defcalcmodevar calc-full-float-format '(float 0)
553 "Format to use when full precision must be displayed.")
730576f3 554
6c8e7554
JB
555(defcalcmodevar calc-complex-format nil
556 "Format to use for display of complex numbers in calc-mode. Must be one of:
730576f3
CW
557 nil Use (x, y) form.
558 i Use x + yi form.
559 j Use x + yj form.")
560
6c8e7554
JB
561(defcalcmodevar calc-complex-mode 'cplx
562 "Preferred form, either `cplx' or `polar', for complex numbers.")
136211a9 563
6c8e7554
JB
564(defcalcmodevar calc-infinite-mode nil
565 "If nil, 1 / 0 is left unsimplified.
730576f3
CW
566If 0, 1 / 0 is changed to inf (zeros are considered positive).
567Otherwise, 1 / 0 is changed to uinf (undirected infinity).")
568
6c8e7554
JB
569(defcalcmodevar calc-display-strings nil
570 "If non-nil, display vectors of byte-sized integers as strings.")
136211a9 571
6c8e7554
JB
572(defcalcmodevar calc-matrix-just 'center
573 "If nil, vector elements are left-justified.
730576f3
CW
574If `right', vector elements are right-justified.
575If `center', vector elements are centered.")
576
6c8e7554
JB
577(defcalcmodevar calc-break-vectors nil
578 "If non-nil, display vectors one element per line.")
136211a9 579
6c8e7554
JB
580(defcalcmodevar calc-full-vectors t
581 "If non-nil, display long vectors in full. If nil, use abbreviated form.")
730576f3 582
6c8e7554
JB
583(defcalcmodevar calc-full-trail-vectors t
584 "If non-nil, display long vectors in full in the trail.")
136211a9 585
6c8e7554
JB
586(defcalcmodevar calc-vector-commas ","
587 "If non-nil, separate elements of displayed vectors with this string.")
730576f3 588
6c8e7554
JB
589(defcalcmodevar calc-vector-brackets "[]"
590 "If non-nil, surround displayed vectors with these characters.")
730576f3 591
6c8e7554
JB
592(defcalcmodevar calc-matrix-brackets '(R O)
593 "A list of code-letter symbols that control \"big\" matrix display.
730576f3
CW
594If `R' is present, display inner brackets for matrices.
595If `O' is present, display outer brackets for matrices (above/below).
596If `C' is present, display outer brackets for matrices (centered).")
597
6c8e7554
JB
598(defcalcmodevar calc-language nil
599 "Language or format for entry and display of stack values. Must be one of:
730576f3
CW
600 nil Use standard Calc notation.
601 flat Use standard Calc notation, one-line format.
602 big Display formulas in 2-d notation (enter w/std notation).
603 unform Use unformatted display: add(a, mul(b,c)).
604 c Use C language notation.
605 pascal Use Pascal language notation.
606 fortran Use Fortran language notation.
607 tex Use TeX notation.
ad1c32c7 608 latex Use LaTeX notation.
730576f3
CW
609 eqn Use eqn notation.
610 math Use Mathematica(tm) notation.
611 maple Use Maple notation.")
136211a9 612
6c8e7554
JB
613(defcalcmodevar calc-language-option nil
614 "Numeric prefix argument for the command that set `calc-language'.")
136211a9 615
6c8e7554
JB
616(defcalcmodevar calc-left-label ""
617 "Label to display at left of formula.")
136211a9 618
6c8e7554
JB
619(defcalcmodevar calc-right-label ""
620 "Label to display at right of formula.")
136211a9 621
6c8e7554
JB
622(defcalcmodevar calc-word-size 32
623 "Minimum number of bits per word, if any, for binary operations in calc-mode.")
136211a9 624
6c8e7554
JB
625(defcalcmodevar calc-previous-modulo nil
626 "Most recently used value of M in a modulo form.")
136211a9 627
6c8e7554
JB
628(defcalcmodevar calc-simplify-mode nil
629 "Type of simplification applied to results.
730576f3
CW
630If `none', results are not simplified when pushed on the stack.
631If `num', functions are simplified only when args are constant.
632If nil, only fast simplifications are applied.
633If `binary', `math-clip' is applied if appropriate.
634If `alg', `math-simplify' is applied.
635If `ext', `math-simplify-extended' is applied.
636If `units', `math-simplify-units' is applied.")
136211a9 637
6c8e7554
JB
638(defcalcmodevar calc-auto-recompute t
639 "If non-nil, recompute evalto's automatically when necessary.")
136211a9 640
6c8e7554 641(defcalcmodevar calc-display-raw nil
650cb9f1 642 "If non-nil, display shows unformatted Lisp exprs. (For debugging)")
136211a9 643
6c8e7554
JB
644(defcalcmodevar calc-internal-prec 12
645 "Number of digits of internal precision for calc-mode calculations.")
136211a9 646
6c8e7554
JB
647(defcalcmodevar calc-angle-mode 'deg
648 "If deg, angles are in degrees; if rad, angles are in radians.
730576f3 649If hms, angles are in degrees-minutes-seconds.")
136211a9 650
6c8e7554
JB
651(defcalcmodevar calc-algebraic-mode nil
652 "If non-nil, numeric entry accepts whole algebraic expressions.
730576f3 653If nil, algebraic expressions must be preceded by \"'\".")
136211a9 654
6c8e7554
JB
655(defcalcmodevar calc-incomplete-algebraic-mode nil
656 "Like calc-algebraic-mode except only affects ( and [ keys.")
730576f3 657
6c8e7554
JB
658(defcalcmodevar calc-symbolic-mode nil
659 "If non-nil, inexact numeric computations like sqrt(2) are postponed.
730576f3
CW
660If nil, computations on numbers always yield numbers where possible.")
661
6c8e7554
JB
662(defcalcmodevar calc-matrix-mode nil
663 "If `matrix', variables are assumed to be matrix-valued.
730576f3 664If a number, variables are assumed to be NxN matrices.
bbcaa3e3 665If `sqmatrix', variables are assumed to be square matrices of an unspecified size.
730576f3
CW
666If `scalar', variables are assumed to be scalar-valued.
667If nil, symbolic math routines make no assumptions about variables.")
668
6c8e7554
JB
669(defcalcmodevar calc-shift-prefix nil
670 "If non-nil, shifted letter keys are prefix keys rather than normal meanings.")
730576f3 671
6c8e7554
JB
672(defcalcmodevar calc-window-height 7
673 "Initial height of Calculator window.")
730576f3 674
6c8e7554
JB
675(defcalcmodevar calc-display-trail t
676 "If non-nil, M-x calc creates a window to display Calculator trail.")
730576f3 677
6c8e7554
JB
678(defcalcmodevar calc-show-selections t
679 "If non-nil, selected sub-formulas are shown by obscuring rest of formula.
730576f3
CW
680If nil, selected sub-formulas are highlighted by obscuring the sub-formulas.")
681
6c8e7554
JB
682(defcalcmodevar calc-use-selections t
683 "If non-nil, commands operate only on selected portions of formulas.
730576f3
CW
684If nil, selections displayed but ignored.")
685
6c8e7554
JB
686(defcalcmodevar calc-assoc-selections t
687 "If non-nil, selection hides deep structure of associative formulas.")
730576f3 688
6c8e7554
JB
689(defcalcmodevar calc-display-working-message 'lots
690 "If non-nil, display \"Working...\" for potentially slow Calculator commands.")
730576f3 691
6c8e7554
JB
692(defcalcmodevar calc-auto-why 'maybe
693 "If non-nil, automatically execute a \"why\" command to explain odd results.")
730576f3 694
6c8e7554
JB
695(defcalcmodevar calc-timing nil
696 "If non-nil, display timing information on each slow command.")
730576f3 697
6c8e7554 698(defcalcmodevar calc-mode-save-mode 'local)
730576f3 699
6c8e7554
JB
700(defcalcmodevar calc-standard-date-formats
701 '("N"
cde090ee
JB
702 "<H:mm:SSpp >Www Mmm D, YYYY"
703 "D Mmm YYYY<, h:mm:SS>"
704 "Www Mmm BD< hh:mm:ss> YYYY"
705 "M/D/Y< H:mm:SSpp>"
706 "D.M.Y< h:mm:SS>"
707 "M-D-Y< H:mm:SSpp>"
708 "D-M-Y< h:mm:SS>"
709 "j<, h:mm:SS>"
710 "YYddd< hh:mm:ss>"))
730576f3 711
6c8e7554 712(defcalcmodevar calc-autorange-units nil)
2a78421d 713
6c8e7554 714(defcalcmodevar calc-was-keypad-mode nil)
2a78421d 715
6c8e7554 716(defcalcmodevar calc-full-mode nil)
730576f3 717
6c8e7554 718(defcalcmodevar calc-user-parse-tables nil)
730576f3 719
6c8e7554 720(defcalcmodevar calc-gnuplot-default-device "default")
730576f3 721
6c8e7554 722(defcalcmodevar calc-gnuplot-default-output "STDOUT")
7b2cda38 723
6c8e7554 724(defcalcmodevar calc-gnuplot-print-device "postscript")
2a78421d 725
6c8e7554 726(defcalcmodevar calc-gnuplot-print-output "auto")
7b2cda38 727
6c8e7554 728(defcalcmodevar calc-gnuplot-geometry nil)
7b2cda38 729
6c8e7554 730(defcalcmodevar calc-graph-default-resolution 15)
730576f3 731
6c8e7554 732(defcalcmodevar calc-graph-default-resolution-3d 5)
2a78421d 733
6c8e7554
JB
734(defcalcmodevar calc-invocation-macro nil)
735
736(defcalcmodevar calc-show-banner t
737 "*If non-nil, show a friendly greeting above the stack.")
136211a9
EZ
738
739(defconst calc-local-var-list '(calc-stack
740 calc-stack-top
741 calc-undo-list
742 calc-redo-list
743 calc-always-load-extensions
744 calc-mode-save-mode
745 calc-display-raw
746 calc-line-numbering
747 calc-line-breaking
748 calc-display-just
749 calc-display-origin
750 calc-left-label
751 calc-right-label
752 calc-auto-why
753 calc-algebraic-mode
754 calc-incomplete-algebraic-mode
755 calc-symbolic-mode
756 calc-matrix-mode
757 calc-inverse-flag
758 calc-hyperbolic-flag
759 calc-keep-args-flag
760 calc-angle-mode
761 calc-number-radix
762 calc-leading-zeros
763 calc-group-digits
764 calc-group-char
765 calc-point-char
766 calc-frac-format
767 calc-prefer-frac
768 calc-hms-format
769 calc-date-format
770 calc-standard-date-formats
771 calc-float-format
772 calc-full-float-format
773 calc-complex-format
774 calc-matrix-just
775 calc-full-vectors
776 calc-full-trail-vectors
777 calc-break-vectors
778 calc-vector-commas
779 calc-vector-brackets
780 calc-matrix-brackets
781 calc-complex-mode
782 calc-infinite-mode
783 calc-display-strings
784 calc-simplify-mode
785 calc-auto-recompute
786 calc-autorange-units
787 calc-show-plain
788 calc-show-selections
789 calc-use-selections
790 calc-assoc-selections
791 calc-word-size
792 calc-internal-prec))
793
f55320b5
JB
794(defvar calc-mode-hook nil
795 "Hook run when entering calc-mode.")
796
797(defvar calc-trail-mode-hook nil
798 "Hook run when entering calc-trail-mode.")
799
800(defvar calc-start-hook nil
801 "Hook run when calc is started.")
802
803(defvar calc-end-hook nil
804 "Hook run when calc is quit.")
805
806(defvar calc-load-hook nil
807 "Hook run when calc.el is loaded.")
136211a9 808
ed65ed86
JB
809(defvar calc-window-hook nil
810 "Hook called to create the Calc window.")
811
812(defvar calc-trail-window-hook nil
813 "Hook called to create the Calc trail window.")
814
b2d2748d
JB
815(defvar calc-embedded-new-buffer-hook nil
816 "Hook run when starting embedded mode in a new buffer.")
817
818(defvar calc-embedded-new-formula-hook nil
819 "Hook run when starting embedded mode in a new formula.")
820
821(defvar calc-embedded-mode-hook nil
822 "Hook run when starting embedded mode.")
823
730576f3
CW
824;; Set up the autoloading linkage.
825(let ((name (and (fboundp 'calc-dispatch)
136211a9
EZ
826 (eq (car-safe (symbol-function 'calc-dispatch)) 'autoload)
827 (nth 1 (symbol-function 'calc-dispatch))))
828 (p load-path))
829
830 ;; If Calc files exist on the load-path, we're all set.
831 (while (and p (not (file-exists-p
832 (expand-file-name "calc-misc.elc" (car p)))))
833 (setq p (cdr p)))
834 (or p
835
836 ;; If Calc is autoloaded using a path name, look there for Calc files.
837 ;; This works for both relative ("calc/calc.elc") and absolute paths.
838 (and name (file-name-directory name)
839 (let ((p2 load-path)
840 (name2 (concat (file-name-directory name)
841 "calc-misc.elc")))
842 (while (and p2 (not (file-exists-p
843 (expand-file-name name2 (car p2)))))
844 (setq p2 (cdr p2)))
cd012309
CW
845 (when p2
846 (setq load-path (nconc load-path
847 (list
848 (directory-file-name
849 (file-name-directory
850 (expand-file-name
ce805efa 851 name (car p2))))))))))))
136211a9 852
730576f3
CW
853;; The following modes use specially-formatted data.
854(put 'calc-mode 'mode-class 'special)
855(put 'calc-trail-mode 'mode-class 'special)
a1506d29 856
730576f3
CW
857;; Define "inexact-result" as an e-lisp error symbol.
858(put 'inexact-result 'error-conditions '(error inexact-result calc-error))
859(put 'inexact-result 'error-message "Calc internal error (inexact-result)")
a1506d29 860
730576f3
CW
861;; Define "math-overflow" and "math-underflow" as e-lisp error symbols.
862(put 'math-overflow 'error-conditions '(error math-overflow calc-error))
863(put 'math-overflow 'error-message "Floating-point overflow occurred")
864(put 'math-underflow 'error-conditions '(error math-underflow calc-error))
865(put 'math-underflow 'error-message "Floating-point underflow occurred")
a1506d29 866
f7e30874 867(defconst calc-version "2.1")
730576f3
CW
868(defvar calc-trail-pointer nil) ; "Current" entry in trail buffer.
869(defvar calc-trail-overlay nil) ; Value of overlay-arrow-string.
870(defvar calc-undo-list nil) ; List of previous operations for undo.
871(defvar calc-redo-list nil) ; List of recent undo operations.
872(defvar calc-main-buffer nil) ; Pointer to Calculator buffer.
873(defvar calc-trail-buffer nil) ; Pointer to Calc Trail buffer.
874(defvar calc-why nil) ; Explanations of most recent errors.
875(defvar calc-next-why nil)
7b2cda38
JB
876(defvar calc-inverse-flag nil
877 "If non-nil, next operation is Inverse.")
878(defvar calc-hyperbolic-flag nil
879 "If non-nil, next operation is Hyperbolic.")
880(defvar calc-keep-args-flag nil
881 "If non-nil, next operation should not remove its arguments from stack.")
882(defvar calc-function-open "("
883 "Open-parenthesis string for function call notation.")
884(defvar calc-function-close ")"
885 "Close-parenthesis string for function call notation.")
886(defvar calc-language-output-filter nil
887 "Function through which to pass strings after formatting.")
888(defvar calc-language-input-filter nil
889 "Function through which to pass strings before parsing.")
890(defvar calc-radix-formatter nil
891 "Formatting function used for non-decimal numbers.")
892
730576f3 893(defvar calc-last-kill nil) ; Last number killed in calc-mode.
730576f3
CW
894(defvar calc-dollar-values nil) ; Values to be used for '$'.
895(defvar calc-dollar-used nil) ; Highest order of '$' that occurred.
896(defvar calc-hashes-used nil) ; Highest order of '#' that occurred.
897(defvar calc-quick-prev-results nil) ; Previous results from Quick Calc.
898(defvar calc-said-hello nil) ; Has welcome message been said yet?
899(defvar calc-executing-macro nil) ; Kbd macro executing from "K" key.
900(defvar calc-any-selections nil) ; Nil means no selections present.
901(defvar calc-help-phase 0) ; Count of consecutive "?" keystrokes.
902(defvar calc-full-help-flag nil) ; Executing calc-full-help?
903(defvar calc-refresh-count 0) ; Count of calc-refresh calls.
904(defvar calc-display-dirty nil)
905(defvar calc-prepared-composition nil)
906(defvar calc-selection-cache-default-entry nil)
907(defvar calc-embedded-info nil)
908(defvar calc-embedded-active nil)
909(defvar calc-standalone-flag nil)
910(defvar var-EvalRules nil)
911(defvar math-eval-rules-cache-tag t)
912(defvar math-radix-explicit-format t)
913(defvar math-expr-function-mapping nil)
ad1c32c7 914(defvar math-expr-special-function-mapping nil)
730576f3
CW
915(defvar math-expr-variable-mapping nil)
916(defvar math-read-expr-quotes nil)
917(defvar math-working-step nil)
918(defvar math-working-step-2 nil)
919(defvar var-i '(special-const (math-imaginary 1)))
920(defvar var-pi '(special-const (math-pi)))
921(defvar var-e '(special-const (math-e)))
922(defvar var-phi '(special-const (math-phi)))
923(defvar var-gamma '(special-const (math-gamma-const)))
924(defvar var-Modes '(special-const (math-get-modes-vec)))
925
2a78421d
JB
926(mapc (lambda (v) (or (boundp v) (set v nil)))
927 calc-local-var-list)
136211a9 928
730576f3
CW
929(defvar calc-mode-map
930 (let ((map (make-keymap)))
931 (suppress-keymap map t)
932 (define-key map "+" 'calc-plus)
933 (define-key map "-" 'calc-minus)
934 (define-key map "*" 'calc-times)
935 (define-key map "/" 'calc-divide)
936 (define-key map "%" 'calc-mod)
937 (define-key map "&" 'calc-inv)
938 (define-key map "^" 'calc-power)
939 (define-key map "\M-%" 'calc-percent)
940 (define-key map "e" 'calcDigit-start)
941 (define-key map "i" 'calc-info)
942 (define-key map "n" 'calc-change-sign)
943 (define-key map "q" 'calc-quit)
944 (define-key map "Y" 'nil)
945 (define-key map "Y?" 'calc-shift-Y-prefix-help)
946 (define-key map "?" 'calc-help)
947 (define-key map " " 'calc-enter)
948 (define-key map "'" 'calc-algebraic-entry)
949 (define-key map "$" 'calc-auto-algebraic-entry)
950 (define-key map "\"" 'calc-auto-algebraic-entry)
951 (define-key map "\t" 'calc-roll-down)
952 (define-key map "\M-\t" 'calc-roll-up)
953 (define-key map "\C-m" 'calc-enter)
954 (define-key map "\M-\C-m" 'calc-last-args-stub)
955 (define-key map "\C-j" 'calc-over)
956
6a3ed064
SM
957 (mapc (lambda (x) (define-key map (char-to-string x) 'undefined))
958 "lOW")
959 (mapc (lambda (x) (define-key map (char-to-string x) 'calc-missing-key))
960 (concat "ABCDEFGHIJKLMNPQRSTUVXZabcdfghjkmoprstuvwxyz"
961 ":\\|!()[]<>{},;=~`\C-k\M-k\C-w\M-w\C-y\C-_"))
962 (mapc (lambda (x) (define-key map (char-to-string x) 'calcDigit-start))
963 "_0123456789.#@")
730576f3 964 map))
136211a9 965
730576f3
CW
966(defvar calc-digit-map
967 (let ((map (make-keymap)))
6546555e 968 (if (featurep 'xemacs)
136211a9
EZ
969 (map-keymap (function
970 (lambda (keys bind)
730576f3 971 (define-key map keys
136211a9
EZ
972 (if (eq bind 'undefined)
973 'undefined 'calcDigit-nondigit))))
974 calc-mode-map)
cecd4c20
JB
975 (let ((cmap (nth 1 calc-mode-map))
976 (dmap (nth 1 map))
136211a9
EZ
977 (i 0))
978 (while (< i 128)
979 (aset dmap i
980 (if (eq (aref cmap i) 'undefined)
981 'undefined 'calcDigit-nondigit))
982 (setq i (1+ i)))))
2a78421d
JB
983 (mapc (lambda (x) (define-key map (char-to-string x) 'calcDigit-key))
984 "_0123456789.e+-:n#@oh'\"mspM")
985 (mapc (lambda (x) (define-key map (char-to-string x) 'calcDigit-letter))
136211a9 986 "abcdfgijklqrtuvwxyzABCDEFGHIJKLNOPQRSTUVWXYZ")
730576f3
CW
987 (define-key map "'" 'calcDigit-algebraic)
988 (define-key map "`" 'calcDigit-edit)
989 (define-key map "\C-g" 'abort-recursive-edit)
990 map))
136211a9 991
2a78421d
JB
992(mapc (lambda (x)
993 (condition-case err
994 (progn
995 (define-key calc-digit-map x 'calcDigit-backspace)
996 (define-key calc-mode-map x 'calc-pop)
997 (define-key calc-mode-map
998 (if (vectorp x)
6546555e 999 (if (featurep 'xemacs)
2a78421d
JB
1000 (if (= (length x) 1)
1001 (vector (if (consp (aref x 0))
1002 (cons 'meta (aref x 0))
1003 (list 'meta (aref x 0))))
1004 "\e\C-d")
1005 (vconcat "\e" x))
1006 (concat "\e" x))
1007 'calc-pop-above))
1008 (error nil)))
1009 (if calc-scan-for-dels
1010 (append (where-is-internal 'delete-backward-char global-map)
1011 (where-is-internal 'backward-delete-char global-map)
1012 '("\C-d"))
1013 '("\177" "\C-d")))
136211a9 1014
730576f3
CW
1015(defvar calc-dispatch-map
1016 (let ((map (make-keymap)))
2a78421d
JB
1017 (mapc (lambda (x)
1018 (define-key map (char-to-string (car x)) (cdr x))
1019 (when (string-match "abcdefhijklnopqrstuwxyz"
1020 (char-to-string (car x)))
1021 (define-key map (char-to-string (- (car x) ?a -1)) (cdr x)))
1022 (define-key map (format "\e%c" (car x)) (cdr x)))
1023 '( ( ?a . calc-embedded-activate )
1024 ( ?b . calc-big-or-small )
1025 ( ?c . calc )
1026 ( ?d . calc-embedded-duplicate )
1027 ( ?e . calc-embedded )
1028 ( ?f . calc-embedded-new-formula )
1029 ( ?g . calc-grab-region )
1030 ( ?h . calc-dispatch-help )
1031 ( ?i . calc-info )
1032 ( ?j . calc-embedded-select )
1033 ( ?k . calc-keypad )
1034 ( ?l . calc-load-everything )
1035 ( ?m . read-kbd-macro )
1036 ( ?n . calc-embedded-next )
1037 ( ?o . calc-other-window )
1038 ( ?p . calc-embedded-previous )
1039 ( ?q . quick-calc )
1040 ( ?r . calc-grab-rectangle )
1041 ( ?s . calc-info-summary )
1042 ( ?t . calc-tutorial )
1043 ( ?u . calc-embedded-update-formula )
1044 ( ?w . calc-embedded-word )
1045 ( ?x . calc-quit )
1046 ( ?y . calc-copy-to-buffer )
1047 ( ?z . calc-user-invocation )
1048 ( ?\' . calc-embedded-new-formula )
1049 ( ?\` . calc-embedded-edit )
1050 ( ?: . calc-grab-sum-down )
1051 ( ?_ . calc-grab-sum-across )
1052 ( ?0 . calc-reset )
1053 ( ?? . calc-dispatch-help )
1054 ( ?# . calc-same-interface )
1055 ( ?& . calc-same-interface )
1056 ( ?\\ . calc-same-interface )
1057 ( ?= . calc-same-interface )
1058 ( ?* . calc-same-interface )
1059 ( ?/ . calc-same-interface )
1060 ( ?+ . calc-same-interface )
1061 ( ?- . calc-same-interface ) ))
80f952a2 1062 map))
136211a9 1063
136211a9 1064;;;; (Autoloads here)
2a78421d 1065(mapc
730576f3 1066 (lambda (x) (dolist (func (cdr x)) (autoload func (car x))))
136211a9
EZ
1067 '(
1068
451d4c5c 1069 ("calc-aent" calc-alg-digit-entry calc-alg-entry
730576f3
CW
1070 calc-check-user-syntax calc-do-alg-entry calc-do-calc-eval
1071 calc-do-quick-calc calc-match-user-syntax math-build-parse-table
1072 math-find-user-tokens math-read-expr-list math-read-exprs math-read-if
5ff9dafd 1073 math-read-token math-remove-dashes math-read-preprocess-string)
136211a9 1074
451d4c5c
JB
1075 ("calc-embed" calc-do-embedded-activate)
1076
2a78421d 1077 ("calc-misc"
730576f3
CW
1078 calc-do-handle-whys calc-do-refresh calc-num-prefix-name
1079 calc-record-list calc-record-why calc-report-bug calc-roll-down-stack
1080 calc-roll-up-stack calc-temp-minibuffer-message calcFunc-floor
1081 calcFunc-inv calcFunc-trunc math-concat math-constp math-div2
1082 math-div2-bignum math-do-working math-evenp math-fixnatnump
1083 math-fixnump math-floor math-imod math-ipow math-looks-negp math-mod
1084 math-negp math-posp math-pow math-read-radix-digit math-reject-arg
1085 math-trunc math-zerop)))
1086
2a78421d 1087(mapc
730576f3 1088 (lambda (x) (dolist (cmd (cdr x)) (autoload cmd (car x) nil t)))
136211a9
EZ
1089 '(
1090
1091 ("calc-aent" calc-algebraic-entry calc-auto-algebraic-entry
730576f3 1092 calcDigit-algebraic calcDigit-edit)
136211a9
EZ
1093
1094 ("calc-misc" another-calc calc-big-or-small calc-dispatch-help
2a78421d 1095 calc-help calc-info calc-info-goto-node calc-info-summary calc-inv
9d3c486a 1096 calc-last-args-stub
730576f3
CW
1097 calc-missing-key calc-mod calc-other-window calc-over calc-percent
1098 calc-pop-above calc-power calc-roll-down calc-roll-up
1099 calc-shift-Y-prefix-help calc-tutorial calcDigit-letter
1100 report-calc-bug)))
136211a9
EZ
1101
1102
d24f83d4 1103;;;###autoload (define-key ctl-x-map "*" 'calc-dispatch)
136211a9
EZ
1104
1105;;;###autoload
1106(defun calc-dispatch (&optional arg)
f269b73e 1107 "Invoke the GNU Emacs Calculator. See `calc-dispatch-help' for details."
136211a9 1108 (interactive "P")
99992264 1109; (sit-for echo-keystrokes)
136211a9
EZ
1110 (condition-case err ; look for other keys bound to calc-dispatch
1111 (let ((keys (this-command-keys)))
cd012309
CW
1112 (unless (or (not (stringp keys))
1113 (string-match "\\`\C-u\\|\\`\e[-0-9#]\\|`[\M--\M-0-\M-9]" keys)
1114 (eq (lookup-key calc-dispatch-map keys) 'calc-same-interface))
1115 (when (and (string-match "\\`[\C-@-\C-_]" keys)
1116 (symbolp
1117 (lookup-key calc-dispatch-map (substring keys 0 1))))
1118 (define-key calc-dispatch-map (substring keys 0 1) nil))
1119 (define-key calc-dispatch-map keys 'calc-same-interface)))
136211a9 1120 (error nil))
bf77c646 1121 (calc-do-dispatch arg))
136211a9 1122
f269b73e 1123(defvar calc-dispatch-help nil)
136211a9
EZ
1124(defun calc-do-dispatch (arg)
1125 (let ((key (calc-read-key-sequence
1126 (if calc-dispatch-help
1127 "Calc options: Calc, Keypad, Quick, Embed; eXit; Info, Tutorial; Grab; ?=more"
1128 (format "%s (Type ? for a list of Calc options)"
1129 (key-description (this-command-keys))))
1130 calc-dispatch-map)))
1131 (setq key (lookup-key calc-dispatch-map key))
1132 (message "")
1133 (if key
1134 (progn
ce805efa 1135 (or (commandp key) (require 'calc-ext))
136211a9 1136 (call-interactively key))
bf77c646 1137 (beep))))
136211a9
EZ
1138
1139(defun calc-read-key-sequence (prompt map)
1140 (let ((prompt2 (format "%s " (key-description (this-command-keys))))
1141 (glob (current-global-map))
1142 (loc (current-local-map)))
1143 (or (input-pending-p) (message prompt))
1144 (let ((key (calc-read-key t)))
1145 (calc-unread-command (cdr key))
1146 (unwind-protect
1147 (progn
1148 (use-global-map map)
1149 (use-local-map nil)
7e1637c2 1150 (read-key-sequence nil))
136211a9 1151 (use-global-map glob)
bf77c646 1152 (use-local-map loc)))))
136211a9 1153
f5a3eb30 1154(defvar calc-alg-map) ; Defined in calc-ext.el
136211a9 1155
bd149d6e
JB
1156(defun calc-version ()
1157 "Return version of this version of Calc."
1158 (interactive)
1159 (message (concat "Calc version " calc-version)))
1160
136211a9
EZ
1161(defun calc-mode ()
1162 "Calculator major mode.
1163
1164This is an RPN calculator featuring arbitrary-precision integer, rational,
1165floating-point, complex, matrix, and symbolic arithmetic.
1166
1167RPN calculation: 2 RET 3 + produces 5.
1168Algebraic style: ' 2+3 RET produces 5.
1169
1170Basic operators are +, -, *, /, ^, & (reciprocal), % (modulo), n (change-sign).
1171
1172Press ? repeatedly for more complete help. Press `h i' to read the
1173Calc manual on-line, `h s' to read the summary, or `h t' for the tutorial.
1174
1175Notations: 3.14e6 3.14 * 10^6
1176 _23 negative number -23 (or type `23 n')
1177 17:3 the fraction 17/3
1178 5:2:3 the fraction 5 and 2/3
1179 16#12C the integer 12C base 16 = 300 base 10
1180 8#177:100 the fraction 177:100 base 8 = 127:64 base 10
1181 (2, 4) complex number 2 + 4i
1182 (2; 4) polar complex number (r; theta)
1183 [1, 2, 3] vector ([[1, 2], [3, 4]] is a matrix)
1184 [1 .. 4) semi-open interval, 1 <= x < 4
1185 2 +/- 3 (p key) number with mean 2, standard deviation 3
1186 2 mod 3 (M key) number 2 computed modulo 3
1187 <1 jan 91> Date form (enter using ' key)
1188
1189
1190\\{calc-mode-map}
1191"
1192 (interactive)
2a78421d
JB
1193 (mapc (function
1194 (lambda (v) (set-default v (symbol-value v)))) calc-local-var-list)
136211a9
EZ
1195 (kill-all-local-variables)
1196 (use-local-map (if (eq calc-algebraic-mode 'total)
ce805efa 1197 (progn (require 'calc-ext) calc-alg-map) calc-mode-map))
2a78421d 1198 (mapc (function (lambda (v) (make-local-variable v))) calc-local-var-list)
136211a9
EZ
1199 (make-local-variable 'overlay-arrow-position)
1200 (make-local-variable 'overlay-arrow-string)
558f9ba1 1201 (add-hook 'change-major-mode-hook 'font-lock-defontify nil t)
136211a9
EZ
1202 (setq truncate-lines t)
1203 (setq buffer-read-only t)
1204 (setq major-mode 'calc-mode)
1205 (setq mode-name "Calculator")
1206 (setq calc-stack-top (length (or (memq (assq 'top-of-stack calc-stack)
1207 calc-stack)
1208 (setq calc-stack (list (list 'top-of-stack
1209 1 nil))))))
1210 (setq calc-stack-top (- (length calc-stack) calc-stack-top -1))
1211 (or calc-loaded-settings-file
f269b73e 1212 (null calc-settings-file)
a8aee43b 1213 (equal calc-settings-file user-init-file)
136211a9
EZ
1214 (progn
1215 (setq calc-loaded-settings-file t)
6bbfeec5 1216 (load (file-name-sans-extension calc-settings-file) t))) ; t = missing-ok
136211a9
EZ
1217 (let ((p command-line-args))
1218 (while p
1219 (and (equal (car p) "-f")
1220 (string-match "calc" (nth 1 p))
1221 (string-match "full" (nth 1 p))
1222 (setq calc-standalone-flag t))
1223 (setq p (cdr p))))
d74fa98c 1224 (run-mode-hooks 'calc-mode-hook)
136211a9
EZ
1225 (calc-refresh t)
1226 (calc-set-mode-line)
bf77c646 1227 (calc-check-defines))
136211a9 1228
f269b73e 1229(defvar calc-check-defines 'calc-check-defines) ; suitable for run-hooks
136211a9
EZ
1230(defun calc-check-defines ()
1231 (if (symbol-plist 'calc-define)
1232 (let ((plist (copy-sequence (symbol-plist 'calc-define))))
1233 (while (and plist (null (nth 1 plist)))
1234 (setq plist (cdr (cdr plist))))
1235 (if plist
1236 (save-excursion
ce805efa
JB
1237 (require 'calc-ext)
1238 (require 'calc-macs)
136211a9
EZ
1239 (set-buffer "*Calculator*")
1240 (while plist
1241 (put 'calc-define (car plist) nil)
1242 (eval (nth 1 plist))
1243 (setq plist (cdr (cdr plist))))
1244 ;; See if this has added any more calc-define properties.
1245 (calc-check-defines))
bf77c646 1246 (setplist 'calc-define nil)))))
136211a9
EZ
1247
1248(defun calc-trail-mode (&optional buf)
1249 "Calc Trail mode.
1250This mode is used by the *Calc Trail* buffer, which records all results
1251obtained by the GNU Emacs Calculator.
1252
1253Calculator commands beginning with the `t' key are used to manipulate
1254the Trail.
1255
1256This buffer uses the same key map as the *Calculator* buffer; calculator
1257commands given here will actually operate on the *Calculator* stack."
1258 (interactive)
1259 (fundamental-mode)
1260 (use-local-map calc-mode-map)
1261 (setq major-mode 'calc-trail-mode)
1262 (setq mode-name "Calc Trail")
1263 (setq truncate-lines t)
1264 (setq buffer-read-only t)
1265 (make-local-variable 'overlay-arrow-position)
1266 (make-local-variable 'overlay-arrow-string)
cd012309
CW
1267 (when buf
1268 (set (make-local-variable 'calc-main-buffer) buf))
1269 (when (= (buffer-size) 0)
1270 (let ((buffer-read-only nil))
802ed9b9 1271 (insert (propertize (concat "Emacs Calculator Trail\n")
cd012309 1272 'font-lock-face 'italic))))
d74fa98c 1273 (run-mode-hooks 'calc-trail-mode-hook))
136211a9
EZ
1274
1275(defun calc-create-buffer ()
1276 (set-buffer (get-buffer-create "*Calculator*"))
1277 (or (eq major-mode 'calc-mode)
1278 (calc-mode))
1279 (setq max-lisp-eval-depth (max max-lisp-eval-depth 1000))
cd012309 1280 (when calc-always-load-extensions
ce805efa 1281 (require 'calc-ext))
cd012309 1282 (when calc-language
ce805efa 1283 (require 'calc-ext)
cd012309 1284 (calc-set-language calc-language calc-language-option t)))
136211a9
EZ
1285
1286;;;###autoload
1287(defun calc (&optional arg full-display interactive)
1288 "The Emacs Calculator. Full documentation is listed under \"calc-mode\"."
577e1b74 1289 (interactive "P\ni\np")
136211a9 1290 (if arg
cd012309 1291 (unless (eq arg 0)
ce805efa 1292 (require 'calc-ext)
cd012309
CW
1293 (if (= (prefix-numeric-value arg) -1)
1294 (calc-grab-region (region-beginning) (region-end) nil)
1295 (when (= (prefix-numeric-value arg) -2)
1296 (calc-keypad))))
1297 (when (get-buffer-window "*Calc Keypad*")
1298 (calc-keypad)
1299 (set-buffer (window-buffer (selected-window))))
136211a9
EZ
1300 (if (eq major-mode 'calc-mode)
1301 (calc-quit)
1302 (let ((oldbuf (current-buffer)))
1303 (calc-create-buffer)
1304 (setq calc-was-keypad-mode nil)
1305 (if (or (eq full-display t)
1306 (and (null full-display) calc-full-mode))
1307 (switch-to-buffer (current-buffer) t)
1308 (if (get-buffer-window (current-buffer))
1309 (select-window (get-buffer-window (current-buffer)))
ed65ed86
JB
1310 (if calc-window-hook
1311 (run-hooks 'calc-window-hook)
1312 (let ((w (get-largest-window)))
1313 (if (and pop-up-windows
1314 (> (window-height w)
1315 (+ window-min-height calc-window-height 2)))
1316 (progn
1317 (setq w (split-window w
1318 (- (window-height w)
1319 calc-window-height 2)
1320 nil))
1321 (set-window-buffer w (current-buffer))
1322 (select-window w))
1323 (pop-to-buffer (current-buffer)))))))
136211a9
EZ
1324 (save-excursion
1325 (set-buffer (calc-trail-buffer))
1326 (and calc-display-trail
31b85a14 1327 (= (window-width) (frame-width))
136211a9 1328 (calc-trail-display 1 t)))
f269b73e 1329 (message "Welcome to the GNU Emacs Calculator! Press `?' or `h' for help, `q' to quit")
136211a9
EZ
1330 (run-hooks 'calc-start-hook)
1331 (and (windowp full-display)
1332 (window-point full-display)
1333 (select-window full-display))
1334 (calc-check-defines)
577e1b74 1335 (when (and calc-said-hello interactive)
cd012309
CW
1336 (sit-for 2)
1337 (message ""))
bf77c646 1338 (setq calc-said-hello t)))))
136211a9
EZ
1339
1340;;;###autoload
577e1b74 1341(defun full-calc (&optional interactive)
136211a9 1342 "Invoke the Calculator and give it a full-sized window."
577e1b74
JB
1343 (interactive "p")
1344 (calc nil t interactive))
136211a9
EZ
1345
1346(defun calc-same-interface (arg)
1347 "Invoke the Calculator using the most recent interface (calc or calc-keypad)."
1348 (interactive "P")
1349 (if (and (equal (buffer-name) "*Gnuplot Trail*")
1350 (> (recursion-depth) 0))
1351 (exit-recursive-edit)
1352 (if (eq major-mode 'calc-edit-mode)
1353 (calc-edit-finish arg)
c84eeafa
JB
1354 (if calc-was-keypad-mode
1355 (calc-keypad)
1356 (calc arg calc-full-mode t)))))
136211a9 1357
577e1b74
JB
1358(defun calc-quit (&optional non-fatal interactive)
1359 (interactive "i\np")
136211a9
EZ
1360 (and calc-standalone-flag (not non-fatal)
1361 (save-buffers-kill-emacs nil))
1362 (if (and (equal (buffer-name) "*Gnuplot Trail*")
1363 (> (recursion-depth) 0))
1364 (exit-recursive-edit))
1365 (if (eq major-mode 'calc-edit-mode)
1366 (calc-edit-cancel)
c84eeafa
JB
1367 (if (and interactive
1368 calc-embedded-info
1369 (eq (current-buffer) (aref calc-embedded-info 0)))
1370 (calc-embedded nil)
1371 (unless (eq major-mode 'calc-mode)
1372 (calc-create-buffer))
1373 (run-hooks 'calc-end-hook)
1374 (setq calc-undo-list nil calc-redo-list nil)
2a78421d
JB
1375 (mapc (function (lambda (v) (set-default v (symbol-value v))))
1376 calc-local-var-list)
c84eeafa
JB
1377 (let ((buf (current-buffer))
1378 (win (get-buffer-window (current-buffer)))
1379 (kbuf (get-buffer "*Calc Keypad*")))
1380 (delete-windows-on (calc-trail-buffer))
1381 (if (and win
1382 (< (window-height win) (1- (frame-height)))
1383 (= (window-width win) (frame-width)) ; avoid calc-keypad
1384 (not (get-buffer-window "*Calc Keypad*")))
1385 (setq calc-window-height (- (window-height win) 2)))
1386 (progn
1387 (delete-windows-on buf)
1388 (delete-windows-on kbuf))
1389 (bury-buffer buf)
1390 (bury-buffer calc-trail-buffer)
1391 (and kbuf (bury-buffer kbuf))))))
136211a9
EZ
1392
1393;;;###autoload
1394(defun quick-calc ()
1395 "Do a quick calculation in the minibuffer without invoking full Calculator."
1396 (interactive)
bf77c646 1397 (calc-do-quick-calc))
136211a9
EZ
1398
1399;;;###autoload
1400(defun calc-eval (str &optional separator &rest args)
1401 "Do a quick calculation and return the result as a string.
1402Return value will either be the formatted result in string form,
1403or a list containing a character position and an error message in string form."
bf77c646 1404 (calc-do-calc-eval str separator args))
136211a9
EZ
1405
1406;;;###autoload
577e1b74 1407(defun calc-keypad (&optional interactive)
136211a9
EZ
1408 "Invoke the Calculator in \"visual keypad\" mode.
1409This is most useful in the X window system.
1410In this mode, click on the Calc \"buttons\" using the left mouse button.
1411Or, position the cursor manually and do M-x calc-keypad-press."
577e1b74 1412 (interactive "p")
ce805efa 1413 (require 'calc-ext)
577e1b74 1414 (calc-do-keypad calc-full-mode interactive))
136211a9
EZ
1415
1416;;;###autoload
577e1b74 1417(defun full-calc-keypad (&optional interactive)
136211a9
EZ
1418 "Invoke the Calculator in full-screen \"visual keypad\" mode.
1419See calc-keypad for details."
577e1b74 1420 (interactive "p")
ce805efa 1421 (require 'calc-ext)
577e1b74 1422 (calc-do-keypad t interactive))
136211a9
EZ
1423
1424
f269b73e
CW
1425(defvar calc-aborted-prefix nil)
1426(defvar calc-start-time nil)
730576f3
CW
1427(defvar calc-command-flags)
1428(defvar calc-final-point-line)
1429(defvar calc-final-point-column)
136211a9
EZ
1430;;; Note that modifications to this function may break calc-pass-errors.
1431(defun calc-do (do-body &optional do-slow)
1432 (calc-check-defines)
1433 (let* ((calc-command-flags nil)
1434 (calc-start-time (and calc-timing (not calc-start-time)
ce805efa 1435 (require 'calc-ext)
136211a9
EZ
1436 (current-time-string)))
1437 (gc-cons-threshold (max gc-cons-threshold
730576f3
CW
1438 (if calc-timing 2000000 100000)))
1439 calc-final-point-line calc-final-point-column)
136211a9
EZ
1440 (setq calc-aborted-prefix "")
1441 (unwind-protect
1442 (condition-case err
1443 (save-excursion
1444 (if calc-embedded-info
1445 (calc-embedded-select-buffer)
1446 (calc-select-buffer))
1447 (and (eq calc-algebraic-mode 'total)
ce805efa 1448 (require 'calc-ext)
136211a9 1449 (use-local-map calc-alg-map))
f269b73e
CW
1450 (when (and do-slow calc-display-working-message)
1451 (message "Working...")
1452 (calc-set-command-flag 'clear-message))
136211a9
EZ
1453 (funcall do-body)
1454 (setq calc-aborted-prefix nil)
f269b73e
CW
1455 (when (memq 'renum-stack calc-command-flags)
1456 (calc-renumber-stack))
1457 (when (memq 'clear-message calc-command-flags)
1458 (message "")))
136211a9
EZ
1459 (error
1460 (if (and (eq (car err) 'error)
1461 (stringp (nth 1 err))
1462 (string-match "max-specpdl-size\\|max-lisp-eval-depth"
1463 (nth 1 err)))
f269b73e 1464 (error "Computation got stuck or ran too long. Type `M' to increase the limit")
136211a9
EZ
1465 (setq calc-aborted-prefix nil)
1466 (signal (car err) (cdr err)))))
f269b73e
CW
1467 (when calc-aborted-prefix
1468 (calc-record "<Aborted>" calc-aborted-prefix))
136211a9
EZ
1469 (and calc-start-time
1470 (let* ((calc-internal-prec 12)
1471 (calc-date-format nil)
1472 (end-time (current-time-string))
1473 (time (if (equal calc-start-time end-time)
1474 0
1475 (math-sub
1476 (calcFunc-unixtime (math-parse-date end-time) 0)
1477 (calcFunc-unixtime (math-parse-date calc-start-time)
1478 0)))))
1479 (if (math-lessp 1 time)
1480 (calc-record time "(t)"))))
1481 (or (memq 'no-align calc-command-flags)
1482 (eq major-mode 'calc-trail-mode)
1483 (calc-align-stack-window))
1484 (and (memq 'position-point calc-command-flags)
1485 (if (eq major-mode 'calc-mode)
1486 (progn
1487 (goto-line calc-final-point-line)
1488 (move-to-column calc-final-point-column))
730576f3 1489 (save-current-buffer
136211a9
EZ
1490 (calc-select-buffer)
1491 (goto-line calc-final-point-line)
1492 (move-to-column calc-final-point-column))))
f269b73e
CW
1493 (unless (memq 'keep-flags calc-command-flags)
1494 (save-excursion
1495 (calc-select-buffer)
1496 (setq calc-inverse-flag nil
1497 calc-hyperbolic-flag nil
1498 calc-keep-args-flag nil)))
1499 (when (memq 'do-edit calc-command-flags)
1500 (switch-to-buffer (get-buffer-create "*Calc Edit*")))
136211a9 1501 (calc-set-mode-line)
f269b73e
CW
1502 (when calc-embedded-info
1503 (calc-embedded-finish-command))))
bf77c646
CW
1504 (identity nil)) ; allow a GC after timing is done
1505
136211a9
EZ
1506
1507(defun calc-set-command-flag (f)
f269b73e
CW
1508 (unless (memq f calc-command-flags)
1509 (setq calc-command-flags (cons f calc-command-flags))))
136211a9
EZ
1510
1511(defun calc-select-buffer ()
1512 (or (eq major-mode 'calc-mode)
1513 (if calc-main-buffer
1514 (set-buffer calc-main-buffer)
1515 (let ((buf (get-buffer "*Calculator*")))
1516 (if buf
1517 (set-buffer buf)
bf77c646 1518 (error "Calculator buffer not available"))))))
136211a9
EZ
1519
1520(defun calc-cursor-stack-index (&optional index)
1521 (goto-char (point-max))
bf77c646 1522 (forward-line (- (calc-substack-height (or index 1)))))
136211a9
EZ
1523
1524(defun calc-stack-size ()
bf77c646 1525 (- (length calc-stack) calc-stack-top))
136211a9
EZ
1526
1527(defun calc-substack-height (n)
1528 (let ((sum 0)
1529 (stack calc-stack))
1530 (setq n (+ n calc-stack-top))
1531 (while (and (> n 0) stack)
1532 (setq sum (+ sum (nth 1 (car stack)))
1533 n (1- n)
1534 stack (cdr stack)))
bf77c646 1535 sum))
136211a9
EZ
1536
1537(defun calc-set-mode-line ()
1538 (save-excursion
1539 (calc-select-buffer)
1540 (let* ((fmt (car calc-float-format))
1541 (figs (nth 1 calc-float-format))
1542 (new-mode-string
1543 (format "Calc%s%s: %d %s %-14s"
1544 (if calc-embedded-info "Embed" "")
1545 (if (and (> (length (buffer-name)) 12)
1546 (equal (substring (buffer-name) 0 12)
1547 "*Calculator*"))
1548 (substring (buffer-name) 12)
1549 "")
1550 calc-internal-prec
1551 (capitalize (symbol-name calc-angle-mode))
1552 (concat
1553
1554 ;; Input-related modes
1555 (if (eq calc-algebraic-mode 'total) "Alg* "
1556 (if calc-algebraic-mode "Alg "
1557 (if calc-incomplete-algebraic-mode "Alg[( " "")))
1558
1559 ;; Computational modes
1560 (if calc-symbolic-mode "Symb " "")
1561 (cond ((eq calc-matrix-mode 'matrix) "Matrix ")
1562 ((integerp calc-matrix-mode)
1563 (format "Matrix%d " calc-matrix-mode))
bbcaa3e3 1564 ((eq calc-matrix-mode 'sqmatrix) "SqMatrix ")
136211a9
EZ
1565 ((eq calc-matrix-mode 'scalar) "Scalar ")
1566 (t ""))
1567 (if (eq calc-complex-mode 'polar) "Polar " "")
1568 (if calc-prefer-frac "Frac " "")
1569 (cond ((null calc-infinite-mode) "")
1570 ((eq calc-infinite-mode 1) "+Inf ")
1571 (t "Inf "))
1572 (cond ((eq calc-simplify-mode 'none) "NoSimp ")
1573 ((eq calc-simplify-mode 'num) "NumSimp ")
1574 ((eq calc-simplify-mode 'binary)
1575 (format "BinSimp%d " calc-word-size))
1576 ((eq calc-simplify-mode 'alg) "AlgSimp ")
1577 ((eq calc-simplify-mode 'ext) "ExtSimp ")
1578 ((eq calc-simplify-mode 'units) "UnitSimp ")
1579 (t ""))
1580
1581 ;; Display modes
1582 (cond ((= calc-number-radix 10) "")
1583 ((= calc-number-radix 2) "Bin ")
1584 ((= calc-number-radix 8) "Oct ")
1585 ((= calc-number-radix 16) "Hex ")
1586 (t (format "Radix%d " calc-number-radix)))
1587 (if calc-leading-zeros "Zero " "")
1588 (cond ((null calc-language) "")
1589 ((eq calc-language 'tex) "TeX ")
ad1c32c7 1590 ((eq calc-language 'latex) "LaTeX ")
136211a9
EZ
1591 (t (concat
1592 (capitalize (symbol-name calc-language))
1593 " ")))
1594 (cond ((eq fmt 'float)
1595 (if (zerop figs) "" (format "Norm%d " figs)))
1596 ((eq fmt 'fix) (format "Fix%d " figs))
1597 ((eq fmt 'sci)
1598 (if (zerop figs) "Sci " (format "Sci%d " figs)))
1599 ((eq fmt 'eng)
1600 (if (zerop figs) "Eng " (format "Eng%d " figs))))
1601 (cond ((not calc-display-just)
1602 (if calc-display-origin
1603 (format "Left%d " calc-display-origin) ""))
1604 ((eq calc-display-just 'right)
1605 (if calc-display-origin
1606 (format "Right%d " calc-display-origin)
1607 "Right "))
1608 (t
1609 (if calc-display-origin
1610 (format "Center%d " calc-display-origin)
1611 "Center ")))
1612 (cond ((integerp calc-line-breaking)
1613 (format "Wid%d " calc-line-breaking))
1614 (calc-line-breaking "")
1615 (t "Wide "))
1616
1617 ;; Miscellaneous other modes/indicators
1618 (if calc-assoc-selections "" "Break ")
1619 (cond ((eq calc-mode-save-mode 'save) "Save ")
1620 ((not calc-embedded-info) "")
1621 ((eq calc-mode-save-mode 'local) "Local ")
1622 ((eq calc-mode-save-mode 'edit) "LocEdit ")
1623 ((eq calc-mode-save-mode 'perm) "LocPerm ")
1624 ((eq calc-mode-save-mode 'global) "Global ")
1625 (t ""))
1626 (if calc-auto-recompute "" "Manual ")
1627 (if (and (fboundp 'calc-gnuplot-alive)
1628 (calc-gnuplot-alive)) "Graph " "")
1629 (if (and calc-embedded-info
1630 (> (calc-stack-size) 0)
1631 (calc-top 1 'sel)) "Sel " "")
1632 (if calc-display-dirty "Dirty " "")
1633 (if calc-inverse-flag "Inv " "")
1634 (if calc-hyperbolic-flag "Hyp " "")
1635 (if calc-keep-args-flag "Keep " "")
1636 (if (/= calc-stack-top 1) "Narrow " "")
1637 (apply 'concat calc-other-modes)))))
1638 (if (equal new-mode-string mode-line-buffer-identification)
1639 nil
1640 (setq mode-line-buffer-identification new-mode-string)
1641 (set-buffer-modified-p (buffer-modified-p))
bf77c646 1642 (and calc-embedded-info (calc-embedded-mode-line-change))))))
136211a9
EZ
1643
1644(defun calc-align-stack-window ()
1645 (if (eq major-mode 'calc-mode)
1646 (progn
1647 (let ((win (get-buffer-window (current-buffer))))
1648 (if win
1649 (progn
1650 (calc-cursor-stack-index 0)
1651 (vertical-motion (- 2 (window-height win)))
1652 (set-window-start win (point)))))
1653 (calc-cursor-stack-index 0)
1654 (if (looking-at " *\\.$")
1655 (goto-char (1- (match-end 0)))))
1656 (save-excursion
1657 (calc-select-buffer)
bf77c646 1658 (calc-align-stack-window))))
136211a9
EZ
1659
1660(defun calc-check-stack (n)
1661 (if (> n (calc-stack-size))
1662 (error "Too few elements on stack"))
1663 (if (< n 0)
bf77c646 1664 (error "Invalid argument")))
136211a9
EZ
1665
1666(defun calc-push-list (vals &optional m sels)
1667 (while vals
1668 (if calc-executing-macro
1669 (calc-push-list-in-macro vals m sels)
1670 (save-excursion
1671 (calc-select-buffer)
1672 (let* ((val (car vals))
1673 (entry (list val 1 (car sels)))
1674 (mm (+ (or m 1) calc-stack-top)))
1675 (calc-cursor-stack-index (1- (or m 1)))
1676 (if (> mm 1)
1677 (setcdr (nthcdr (- mm 2) calc-stack)
1678 (cons entry (nthcdr (1- mm) calc-stack)))
1679 (setq calc-stack (cons entry calc-stack)))
1680 (let ((buffer-read-only nil))
1681 (insert (math-format-stack-value entry) "\n"))
1682 (calc-record-undo (list 'push mm))
1683 (calc-set-command-flag 'renum-stack))))
1684 (setq vals (cdr vals)
bf77c646 1685 sels (cdr sels))))
136211a9
EZ
1686
1687(defun calc-pop-push-list (n vals &optional m sels)
1688 (if (and calc-any-selections (null sels))
1689 (calc-replace-selections n vals m)
1690 (calc-pop-stack n m sels)
bf77c646 1691 (calc-push-list vals m sels)))
136211a9
EZ
1692
1693(defun calc-pop-push-record-list (n prefix vals &optional m sels)
1694 (or (and (consp vals)
1695 (or (integerp (car vals))
1696 (consp (car vals))))
1697 (and vals (setq vals (list vals)
1698 sels (and sels (list sels)))))
1699 (calc-check-stack (+ n (or m 1) -1))
1700 (if prefix
1701 (if (cdr vals)
1702 (calc-record-list vals prefix)
1703 (calc-record (car vals) prefix)))
bf77c646 1704 (calc-pop-push-list n vals m sels))
136211a9
EZ
1705
1706(defun calc-enter-result (n prefix vals &optional m)
1707 (setq calc-aborted-prefix prefix)
1708 (if (and (consp vals)
1709 (or (integerp (car vals))
1710 (consp (car vals))))
1711 (setq vals (mapcar 'calc-normalize vals))
1712 (setq vals (calc-normalize vals)))
1713 (or (and (consp vals)
1714 (or (integerp (car vals))
1715 (consp (car vals))))
1716 (setq vals (list vals)))
1717 (if (equal vals '((nil)))
1718 (setq vals nil))
1719 (calc-pop-push-record-list n prefix vals m)
bf77c646 1720 (calc-handle-whys))
136211a9
EZ
1721
1722(defun calc-normalize (val)
1723 (if (memq calc-simplify-mode '(nil none num))
1724 (math-normalize val)
ce805efa 1725 (require 'calc-ext)
bf77c646 1726 (calc-normalize-fancy val)))
136211a9
EZ
1727
1728(defun calc-handle-whys ()
1729 (if calc-next-why
bf77c646 1730 (calc-do-handle-whys)))
136211a9
EZ
1731
1732
1733(defun calc-pop-stack (&optional n m sel-ok) ; pop N objs at level M of stack.
1734 (or n (setq n 1))
1735 (or m (setq m 1))
1736 (or calc-keep-args-flag
1737 (let ((mm (+ m calc-stack-top)))
1738 (if (and calc-any-selections (not sel-ok)
1739 (calc-top-selected n m))
1740 (calc-sel-error))
1741 (if calc-executing-macro
1742 (calc-pop-stack-in-macro n mm)
1743 (calc-record-undo (list 'pop mm (calc-top-list n m 'full)))
1744 (save-excursion
1745 (calc-select-buffer)
1746 (let ((buffer-read-only nil))
1747 (if (> mm 1)
1748 (progn
1749 (calc-cursor-stack-index (1- m))
1750 (let ((bot (point)))
1751 (calc-cursor-stack-index (+ n m -1))
1752 (delete-region (point) bot))
1753 (setcdr (nthcdr (- mm 2) calc-stack)
1754 (nthcdr (+ n mm -1) calc-stack)))
1755 (calc-cursor-stack-index n)
1756 (setq calc-stack (nthcdr n calc-stack))
1757 (delete-region (point) (point-max))))
bf77c646 1758 (calc-set-command-flag 'renum-stack))))))
136211a9 1759
730576f3 1760(defvar sel-mode)
136211a9
EZ
1761(defun calc-get-stack-element (x)
1762 (cond ((eq sel-mode 'entry)
1763 x)
1764 ((eq sel-mode 'sel)
1765 (nth 2 x))
1766 ((or (null (nth 2 x))
1767 (eq sel-mode 'full)
1768 (not calc-use-selections))
1769 (car x))
1770 (sel-mode
1771 (calc-sel-error))
bf77c646 1772 (t (nth 2 x))))
136211a9
EZ
1773
1774;; Get the Nth element of the stack (N=1 is the top element).
1775(defun calc-top (&optional n sel-mode)
1776 (or n (setq n 1))
1777 (calc-check-stack n)
bf77c646 1778 (calc-get-stack-element (nth (+ n calc-stack-top -1) calc-stack)))
136211a9
EZ
1779
1780(defun calc-top-n (&optional n sel-mode) ; in case precision has changed
bf77c646 1781 (math-check-complete (calc-normalize (calc-top n sel-mode))))
136211a9
EZ
1782
1783(defun calc-top-list (&optional n m sel-mode)
1784 (or n (setq n 1))
1785 (or m (setq m 1))
1786 (calc-check-stack (+ n m -1))
1787 (and (> n 0)
1788 (let ((top (copy-sequence (nthcdr (+ m calc-stack-top -1)
1789 calc-stack))))
1790 (setcdr (nthcdr (1- n) top) nil)
bf77c646 1791 (nreverse (mapcar 'calc-get-stack-element top)))))
136211a9
EZ
1792
1793(defun calc-top-list-n (&optional n m sel-mode)
1794 (mapcar 'math-check-complete
bf77c646 1795 (mapcar 'calc-normalize (calc-top-list n m sel-mode))))
136211a9
EZ
1796
1797
1798(defun calc-renumber-stack ()
1799 (if calc-line-numbering
1800 (save-excursion
1801 (calc-cursor-stack-index 0)
1802 (let ((lnum 1)
1803 (buffer-read-only nil)
1804 (stack (nthcdr calc-stack-top calc-stack)))
1805 (if (re-search-forward "^[0-9]+[:*]" nil t)
1806 (progn
1807 (beginning-of-line)
1808 (while (re-search-forward "^[0-9]+[:*]" nil t)
1809 (let ((buffer-read-only nil))
1810 (beginning-of-line)
1811 (delete-char 4)
1812 (insert " ")))
1813 (calc-cursor-stack-index 0)))
1814 (while (re-search-backward "^[0-9]+[:*]" nil t)
1815 (delete-char 4)
1816 (if (> lnum 999)
1817 (insert (format "%03d%s" (% lnum 1000)
1818 (if (and (nth 2 (car stack))
1819 calc-use-selections) "*" ":")))
1820 (let ((prefix (int-to-string lnum)))
1821 (insert prefix (if (and (nth 2 (car stack))
1822 calc-use-selections) "*" ":")
1823 (make-string (- 3 (length prefix)) 32))))
1824 (beginning-of-line)
1825 (setq lnum (1+ lnum)
1826 stack (cdr stack))))))
bf77c646 1827 (and calc-embedded-info (calc-embedded-stack-change)))
136211a9 1828
11bfbbd2 1829(defvar calc-any-evaltos nil)
136211a9
EZ
1830(defun calc-refresh (&optional align)
1831 (interactive)
1832 (and (eq major-mode 'calc-mode)
1833 (not calc-executing-macro)
1834 (let* ((buffer-read-only nil)
1835 (save-point (point))
1836 (save-mark (condition-case err (mark) (error nil)))
1837 (save-aligned (looking-at "\\.$"))
730576f3
CW
1838 (thing calc-stack)
1839 (calc-any-evaltos nil))
1840 (setq calc-any-selections nil)
136211a9 1841 (erase-buffer)
1501f4f6 1842 (when calc-show-banner
cd012309
CW
1843 (insert (propertize "--- Emacs Calculator Mode ---\n"
1844 'font-lock-face 'italic)))
136211a9
EZ
1845 (while thing
1846 (goto-char (point-min))
1501f4f6
MB
1847 (when calc-show-banner
1848 (forward-line 1))
136211a9
EZ
1849 (insert (math-format-stack-value (car thing)) "\n")
1850 (setq thing (cdr thing)))
1851 (calc-renumber-stack)
1852 (if calc-display-dirty
1853 (calc-wrapper (setq calc-display-dirty nil)))
1854 (and calc-any-evaltos calc-auto-recompute
1855 (calc-wrapper (calc-refresh-evaltos)))
1856 (if (or align save-aligned)
1857 (calc-align-stack-window)
1858 (goto-char save-point))
1859 (if save-mark (set-mark save-mark))))
1860 (and calc-embedded-info (not (eq major-mode 'calc-mode))
1861 (save-excursion
1862 (set-buffer (aref calc-embedded-info 1))
1863 (calc-refresh align)))
bf77c646 1864 (setq calc-refresh-count (1+ calc-refresh-count)))
136211a9 1865
136211a9
EZ
1866;;;; The Calc Trail buffer.
1867
1868(defun calc-check-trail-aligned ()
1869 (save-excursion
1870 (let ((win (get-buffer-window (current-buffer))))
1871 (and win
bf77c646 1872 (pos-visible-in-window-p (1- (point-max)) win)))))
136211a9
EZ
1873
1874(defun calc-trail-buffer ()
1875 (and (or (null calc-trail-buffer)
1876 (null (buffer-name calc-trail-buffer)))
1877 (save-excursion
1878 (setq calc-trail-buffer (get-buffer-create "*Calc Trail*"))
1879 (let ((buf (or (and (not (eq major-mode 'calc-mode))
1880 (get-buffer "*Calculator*"))
1881 (current-buffer))))
1882 (set-buffer calc-trail-buffer)
1883 (or (eq major-mode 'calc-trail-mode)
1884 (calc-trail-mode buf)))))
1885 (or (and calc-trail-pointer
1886 (eq (marker-buffer calc-trail-pointer) calc-trail-buffer))
1887 (save-excursion
1888 (set-buffer calc-trail-buffer)
1889 (goto-line 2)
1890 (setq calc-trail-pointer (point-marker))))
bf77c646 1891 calc-trail-buffer)
136211a9
EZ
1892
1893(defun calc-record (val &optional prefix)
1894 (setq calc-aborted-prefix nil)
1895 (or calc-executing-macro
1896 (let* ((mainbuf (current-buffer))
1897 (buf (calc-trail-buffer))
1898 (calc-display-raw nil)
1899 (calc-can-abbrev-vectors t)
1900 (fval (if val
1901 (if (stringp val)
1902 val
1903 (math-showing-full-precision
1904 (math-format-flat-expr val 0)))
1905 "")))
1906 (save-excursion
1907 (set-buffer buf)
1908 (let ((aligned (calc-check-trail-aligned))
1909 (buffer-read-only nil))
1910 (goto-char (point-max))
1911 (cond ((null prefix) (insert " "))
1912 ((and (> (length prefix) 4)
1913 (string-match " " prefix 4))
1914 (insert (substring prefix 0 4) " "))
1915 (t (insert (format "%4s " prefix))))
1916 (insert fval "\n")
1917 (let ((win (get-buffer-window buf)))
1918 (if (and aligned win (not (memq 'hold-trail calc-command-flags)))
1919 (calc-trail-here))
1920 (goto-char (1- (point-max))))))))
bf77c646 1921 val)
136211a9
EZ
1922
1923
577e1b74
JB
1924(defun calc-trail-display (flag &optional no-refresh interactive)
1925 (interactive "P\ni\np")
136211a9
EZ
1926 (let ((win (get-buffer-window (calc-trail-buffer))))
1927 (if (setq calc-display-trail
1928 (not (if flag (memq flag '(nil 0)) win)))
1929 (if (null win)
1930 (progn
ed65ed86
JB
1931 (if calc-trail-window-hook
1932 (run-hooks 'calc-trail-window-hook)
1933 (let ((w (split-window nil (/ (* (window-width) 2) 3) t)))
1934 (set-window-buffer w calc-trail-buffer)))
1935 (calc-wrapper
1936 (setq overlay-arrow-string calc-trail-overlay
1937 overlay-arrow-position calc-trail-pointer)
1938 (or no-refresh
1939 (if interactive
1940 (calc-do-refresh)
1941 (calc-refresh))))))
136211a9
EZ
1942 (if win
1943 (progn
1944 (delete-window win)
1945 (calc-wrapper
1946 (or no-refresh
577e1b74 1947 (if interactive
136211a9
EZ
1948 (calc-do-refresh)
1949 (calc-refresh))))))))
bf77c646 1950 calc-trail-buffer)
136211a9
EZ
1951
1952(defun calc-trail-here ()
1953 (interactive)
1954 (if (eq major-mode 'calc-trail-mode)
1955 (progn
1956 (beginning-of-line)
1957 (if (bobp)
1958 (forward-line 1)
1959 (if (eobp)
1960 (forward-line -1)))
1961 (if (or (bobp) (eobp))
1962 (setq overlay-arrow-position nil) ; trail is empty
1963 (set-marker calc-trail-pointer (point) (current-buffer))
1964 (setq calc-trail-overlay (concat (buffer-substring (point)
1965 (+ (point) 4))
1966 ">")
1967 overlay-arrow-string calc-trail-overlay
1968 overlay-arrow-position calc-trail-pointer)
1969 (forward-char 4)
1970 (let ((win (get-buffer-window (current-buffer))))
1971 (if win
1972 (save-excursion
1973 (forward-line (/ (window-height win) 2))
1974 (forward-line (- 1 (window-height win)))
1975 (set-window-start win (point))
1976 (set-window-point win (+ calc-trail-pointer 4))
1977 (set-buffer calc-main-buffer)
1978 (setq overlay-arrow-string calc-trail-overlay
1979 overlay-arrow-position calc-trail-pointer))))))
bf77c646 1980 (error "Not in Calc Trail buffer")))
136211a9
EZ
1981
1982
1983
1984
1985;;;; The Undo list.
1986
1987(defun calc-record-undo (rec)
1988 (or calc-executing-macro
1989 (if (memq 'undo calc-command-flags)
1990 (setq calc-undo-list (cons (cons rec (car calc-undo-list))
1991 (cdr calc-undo-list)))
1992 (setq calc-undo-list (cons (list rec) calc-undo-list)
1993 calc-redo-list nil)
bf77c646 1994 (calc-set-command-flag 'undo))))
136211a9
EZ
1995
1996
1997
1998
1999;;; Arithmetic commands.
2000
2001(defun calc-binary-op (name func arg &optional ident unary func2)
2002 (setq calc-aborted-prefix name)
2003 (if (null arg)
2004 (calc-enter-result 2 name (cons (or func2 func)
2005 (mapcar 'math-check-complete
2006 (calc-top-list 2))))
ce805efa 2007 (require 'calc-ext)
bf77c646 2008 (calc-binary-op-fancy name func arg ident unary)))
136211a9
EZ
2009
2010(defun calc-unary-op (name func arg &optional func2)
2011 (setq calc-aborted-prefix name)
2012 (if (null arg)
2013 (calc-enter-result 1 name (list (or func2 func)
2014 (math-check-complete (calc-top 1))))
ce805efa 2015 (require 'calc-ext)
bf77c646 2016 (calc-unary-op-fancy name func arg)))
136211a9
EZ
2017
2018
2019(defun calc-plus (arg)
2020 (interactive "P")
2021 (calc-slow-wrapper
bf77c646 2022 (calc-binary-op "+" 'calcFunc-add arg 0 nil '+)))
136211a9
EZ
2023
2024(defun calc-minus (arg)
2025 (interactive "P")
2026 (calc-slow-wrapper
bf77c646 2027 (calc-binary-op "-" 'calcFunc-sub arg 0 'neg '-)))
136211a9
EZ
2028
2029(defun calc-times (arg)
2030 (interactive "P")
2031 (calc-slow-wrapper
bf77c646 2032 (calc-binary-op "*" 'calcFunc-mul arg 1 nil '*)))
136211a9
EZ
2033
2034(defun calc-divide (arg)
2035 (interactive "P")
2036 (calc-slow-wrapper
bf77c646 2037 (calc-binary-op "/" 'calcFunc-div arg 0 'calcFunc-inv '/)))
136211a9 2038
431bbd67
JB
2039(defun calc-left-divide (arg)
2040 (interactive "P")
2041 (calc-slow-wrapper
2042 (calc-binary-op "ldiv" 'calcFunc-ldiv arg 0 nil nil)))
136211a9
EZ
2043
2044(defun calc-change-sign (arg)
2045 (interactive "P")
2046 (calc-wrapper
bf77c646 2047 (calc-unary-op "chs" 'neg arg)))
136211a9
EZ
2048
2049
2050
2051;;; Stack management commands.
2052
2053(defun calc-enter (n)
2054 (interactive "p")
2055 (calc-wrapper
2056 (cond ((< n 0)
2057 (calc-push-list (calc-top-list 1 (- n))))
2058 ((= n 0)
2059 (calc-push-list (calc-top-list (calc-stack-size))))
2060 (t
bf77c646 2061 (calc-push-list (calc-top-list n))))))
136211a9
EZ
2062
2063
2064(defun calc-pop (n)
2065 (interactive "P")
2066 (calc-wrapper
2067 (let* ((nn (prefix-numeric-value n))
2068 (top (and (null n) (calc-top 1))))
2069 (cond ((and (null n)
2070 (eq (car-safe top) 'incomplete)
2071 (> (length top) (if (eq (nth 1 top) 'intv) 3 2)))
2072 (calc-pop-push-list 1 (let ((tt (copy-sequence top)))
2073 (setcdr (nthcdr (- (length tt) 2) tt) nil)
2074 (list tt))))
2075 ((< nn 0)
2076 (if (and calc-any-selections
2077 (calc-top-selected 1 (- nn)))
2078 (calc-delete-selection (- nn))
2079 (calc-pop-stack 1 (- nn) t)))
2080 ((= nn 0)
2081 (calc-pop-stack (calc-stack-size) 1 t))
2082 (t
2083 (if (and calc-any-selections
2084 (= nn 1)
2085 (calc-top-selected 1 1))
2086 (calc-delete-selection 1)
bf77c646 2087 (calc-pop-stack nn)))))))
136211a9
EZ
2088
2089
2090
2091
2092;;;; Reading a number using the minibuffer.
730576f3
CW
2093(defvar calc-buffer)
2094(defvar calc-prev-char)
2095(defvar calc-prev-prev-char)
2096(defvar calc-digit-value)
136211a9
EZ
2097(defun calcDigit-start ()
2098 (interactive)
2099 (calc-wrapper
2100 (if (or calc-algebraic-mode
2101 (and (> calc-number-radix 14) (eq last-command-char ?e)))
2102 (calc-alg-digit-entry)
2103 (calc-unread-command)
2104 (setq calc-aborted-prefix nil)
2105 (let* ((calc-digit-value nil)
2106 (calc-prev-char nil)
2107 (calc-prev-prev-char nil)
2108 (calc-buffer (current-buffer))
6546555e 2109 (buf (if (featurep 'xemacs)
136211a9
EZ
2110 (catch 'calc-foo
2111 (catch 'execute-kbd-macro
2112 (throw 'calc-foo
2113 (read-from-minibuffer
2114 "Calc: " "" calc-digit-map)))
6546555e 2115 (error "XEmacs requires RET after %s"
136211a9
EZ
2116 "digit entry in kbd macro"))
2117 (let ((old-esc (lookup-key global-map "\e")))
2118 (unwind-protect
2119 (progn
2120 (define-key global-map "\e" nil)
2121 (read-from-minibuffer "Calc: " "" calc-digit-map))
2122 (define-key global-map "\e" old-esc))))))
2123 (or calc-digit-value (setq calc-digit-value (math-read-number buf)))
2124 (if (stringp calc-digit-value)
2125 (calc-alg-entry calc-digit-value)
2126 (if calc-digit-value
2127 (calc-push-list (list (calc-record (calc-normalize
2128 calc-digit-value))))))
2129 (if (eq calc-prev-char 'dots)
2130 (progn
ce805efa 2131 (require 'calc-ext)
bf77c646 2132 (calc-dots)))))))
136211a9 2133
91e51f9a
EZ
2134(defsubst calc-minibuffer-size ()
2135 (- (point-max) (minibuffer-prompt-end)))
2136
136211a9
EZ
2137(defun calcDigit-nondigit ()
2138 (interactive)
2139 ;; Exercise for the reader: Figure out why this is a good precaution!
2140 (or (boundp 'calc-buffer)
2141 (use-local-map minibuffer-local-map))
91e51f9a 2142 (let ((str (minibuffer-contents)))
136211a9
EZ
2143 (setq calc-digit-value (save-excursion
2144 (set-buffer calc-buffer)
2145 (math-read-number str))))
91e51f9a 2146 (if (and (null calc-digit-value) (> (calc-minibuffer-size) 0))
136211a9
EZ
2147 (progn
2148 (beep)
2149 (calc-temp-minibuffer-message " [Bad format]"))
2150 (or (memq last-command-char '(32 13))
2151 (progn (setq prefix-arg current-prefix-arg)
2152 (calc-unread-command (if (and (eq last-command-char 27)
2153 (>= last-input-char 128))
2154 last-input-char
2155 nil))))
bf77c646 2156 (exit-minibuffer)))
136211a9
EZ
2157
2158
2159(defun calc-minibuffer-contains (rex)
2160 (save-excursion
91e51f9a 2161 (goto-char (minibuffer-prompt-end))
bf77c646 2162 (looking-at rex)))
136211a9
EZ
2163
2164(defun calcDigit-key ()
2165 (interactive)
2166 (goto-char (point-max))
2167 (if (or (and (memq last-command-char '(?+ ?-))
2168 (> (buffer-size) 0)
2169 (/= (preceding-char) ?e))
2170 (and (memq last-command-char '(?m ?s))
2171 (not (calc-minibuffer-contains "[-+]?[0-9]+\\.?0*[@oh].*"))
2172 (not (calc-minibuffer-contains "[-+]?\\(1[1-9]\\|[2-9][0-9]\\)#.*"))))
2173 (calcDigit-nondigit)
2174 (if (calc-minibuffer-contains "\\([-+]?\\|.* \\)\\'")
2175 (cond ((memq last-command-char '(?. ?@)) (insert "0"))
2176 ((and (memq last-command-char '(?o ?h ?m))
2177 (not (calc-minibuffer-contains ".*#.*"))) (insert "0"))
2178 ((memq last-command-char '(?: ?e)) (insert "1"))
2179 ((eq last-command-char ?#)
2180 (insert (int-to-string calc-number-radix)))))
2181 (if (and (calc-minibuffer-contains "\\([-+]?[0-9]+#\\|[^:]*:\\)\\'")
2182 (eq last-command-char ?:))
2183 (insert "1"))
2184 (if (and (calc-minibuffer-contains "[-+]?[0-9]+#\\'")
2185 (eq last-command-char ?.))
2186 (insert "0"))
2187 (if (and (calc-minibuffer-contains "[-+]?0*\\([2-9]\\|1[0-4]\\)#\\'")
2188 (eq last-command-char ?e))
2189 (insert "1"))
2190 (if (or (and (memq last-command-char '(?h ?o ?m ?s ?p))
2191 (calc-minibuffer-contains ".*#.*"))
2192 (and (eq last-command-char ?e)
2193 (calc-minibuffer-contains "[-+]?\\(1[5-9]\\|[2-9][0-9]\\)#.*"))
2194 (and (eq last-command-char ?n)
2195 (calc-minibuffer-contains "[-+]?\\(2[4-9]\\|[3-9][0-9]\\)#.*")))
2196 (setq last-command-char (upcase last-command-char)))
2197 (cond
2198 ((memq last-command-char '(?_ ?n))
cd01f5b9 2199 (goto-char (minibuffer-prompt-end))
136211a9
EZ
2200 (if (and (search-forward " +/- " nil t)
2201 (not (search-forward "e" nil t)))
2202 (beep)
2203 (and (not (calc-minibuffer-contains "[-+]?\\(1[5-9]\\|[2-9][0-9]\\)#.*"))
2204 (search-forward "e" nil t))
2205 (if (looking-at "+")
2206 (delete-char 1))
2207 (if (looking-at "-")
2208 (delete-char 1)
2209 (insert "-")))
2210 (goto-char (point-max)))
2211 ((eq last-command-char ?p)
2212 (if (or (calc-minibuffer-contains ".*\\+/-.*")
2213 (calc-minibuffer-contains ".*mod.*")
2214 (calc-minibuffer-contains ".*#.*")
2215 (calc-minibuffer-contains ".*[-+e:]\\'"))
2216 (beep)
2217 (if (not (calc-minibuffer-contains ".* \\'"))
2218 (insert " "))
2219 (insert "+/- ")))
2220 ((and (eq last-command-char ?M)
2221 (not (calc-minibuffer-contains
2222 "[-+]?\\(2[3-9]\\|[3-9][0-9]\\)#.*")))
2223 (if (or (calc-minibuffer-contains ".*\\+/-.*")
2224 (calc-minibuffer-contains ".*mod *[^ ]+")
2225 (calc-minibuffer-contains ".*[-+e:]\\'"))
2226 (beep)
2227 (if (calc-minibuffer-contains ".*mod \\'")
2228 (if calc-previous-modulo
2229 (insert (math-format-flat-expr calc-previous-modulo 0))
2230 (beep))
2231 (if (not (calc-minibuffer-contains ".* \\'"))
2232 (insert " "))
2233 (insert "mod "))))
2234 (t
2235 (insert (char-to-string last-command-char))
2236 (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]*\\)?\\)?\\'")
28572d7d 2237 (let ((radix (string-to-number
136211a9
EZ
2238 (buffer-substring
2239 (match-beginning 2) (match-end 2)))))
2240 (and (>= radix 2)
2241 (<= radix 36)
2242 (or (memq last-command-char '(?# ?: ?. ?e ?+ ?-))
2243 (let ((dig (math-read-radix-digit
2244 (upcase last-command-char))))
2245 (and dig
2246 (< dig radix)))))))
91e51f9a
EZ
2247 (calc-minibuffer-contains
2248 "[-+]?\\(.*\\+/- *\\|.*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]?\\'"))
136211a9
EZ
2249 (if (and (memq last-command-char '(?@ ?o ?h ?\' ?m))
2250 (string-match " " calc-hms-format))
2251 (insert " "))
2252 (if (and (eq this-command last-command)
2253 (eq last-command-char ?.))
2254 (progn
ce805efa 2255 (require 'calc-ext)
136211a9
EZ
2256 (calc-digit-dots))
2257 (delete-backward-char 1)
2258 (beep)
2259 (calc-temp-minibuffer-message " [Bad format]"))))))
2260 (setq calc-prev-prev-char calc-prev-char
bf77c646 2261 calc-prev-char last-command-char))
136211a9
EZ
2262
2263
2264(defun calcDigit-backspace ()
2265 (interactive)
2266 (goto-char (point-max))
2267 (cond ((calc-minibuffer-contains ".* \\+/- \\'")
2268 (backward-delete-char 5))
2269 ((calc-minibuffer-contains ".* mod \\'")
2270 (backward-delete-char 5))
2271 ((calc-minibuffer-contains ".* \\'")
2272 (backward-delete-char 2))
2273 ((eq last-command 'calcDigit-start)
2274 (erase-buffer))
2275 (t (backward-delete-char 1)))
91e51f9a 2276 (if (= (calc-minibuffer-size) 0)
136211a9
EZ
2277 (progn
2278 (setq last-command-char 13)
bf77c646 2279 (calcDigit-nondigit))))
136211a9
EZ
2280
2281
2282
2283
2a78421d 2284(defconst math-bignum-digit-length
37cecd78 2285 (truncate (/ (log10 (/ most-positive-fixnum 2)) 2))
a6d107f1
JB
2286 "The length of a \"digit\" in Calc bignums.
2287If a big integer is of the form (bigpos N0 N1 ...), this is the
2288length of the allowable Emacs integers N0, N1,...
2289The value of 2*10^(2*MATH-BIGNUM-DIGIT-LENGTH) must be less than the
2290largest Emacs integer.")
136211a9 2291
2a78421d 2292(defconst math-bignum-digit-size
236e165a 2293 (expt 10 math-bignum-digit-length)
a6d107f1
JB
2294 "An upper bound for the size of the \"digit\"s in Calc bignums.")
2295
2a78421d 2296(defconst math-small-integer-size
236e165a 2297 (expt math-bignum-digit-size 2)
a6d107f1 2298 "An upper bound for the size of \"small integer\"s in Calc.")
136211a9
EZ
2299
2300
2301;;;; Arithmetic routines.
2302;;;
2303;;; An object as manipulated by one of these routines may take any of the
2304;;; following forms:
2305;;;
2306;;; integer An integer. For normalized numbers, this format
2a78421d 2307;;; is used only for
a6d107f1
JB
2308;;; negative math-small-integer-size + 1 to
2309;;; math-small-integer-size - 1
136211a9 2310;;;
2a78421d
JB
2311;;; (bigpos N0 N1 N2 ...) A big positive integer,
2312;;; N0 + N1*math-bignum-digit-size
a6d107f1 2313;;; + N2*(math-bignum-digit-size)^2 ...
2a78421d 2314;;; (bigneg N0 N1 N2 ...) A big negative integer,
a6d107f1 2315;;; - N0 - N1*math-bignum-digit-size ...
2a78421d 2316;;; Each digit N is in the range
a6d107f1 2317;;; 0 ... math-bignum-digit-size -1.
136211a9
EZ
2318;;; Normalized, always at least three N present,
2319;;; and the most significant N is nonzero.
2320;;;
2321;;; (frac NUM DEN) A fraction. NUM and DEN are small or big integers.
2322;;; Normalized, DEN > 1.
2323;;;
2324;;; (float NUM EXP) A floating-point number, NUM * 10^EXP;
2325;;; NUM is a small or big integer, EXP is a small int.
2326;;; Normalized, NUM is not a multiple of 10, and
2327;;; abs(NUM) < 10^calc-internal-prec.
2328;;; Normalized zero is stored as (float 0 0).
2329;;;
2330;;; (cplx REAL IMAG) A complex number; REAL and IMAG are any of above.
2331;;; Normalized, IMAG is nonzero.
2332;;;
2333;;; (polar R THETA) Polar complex number. Normalized, R > 0 and THETA
2334;;; is neither zero nor 180 degrees (pi radians).
2335;;;
2336;;; (vec A B C ...) Vector of objects A, B, C, ... A matrix is a
2337;;; vector of vectors.
2338;;;
2339;;; (hms H M S) Angle in hours-minutes-seconds form. All three
2340;;; components have the same sign; H and M must be
2341;;; numerically integers; M and S are expected to
2342;;; lie in the range [0,60).
2343;;;
2344;;; (date N) A date or date/time object. N is an integer to
2345;;; store a date only, or a fraction or float to
2346;;; store a date and time.
2347;;;
2348;;; (sdev X SIGMA) Error form, X +/- SIGMA. When normalized,
2349;;; SIGMA > 0. X is any complex number and SIGMA
2350;;; is real numbers; or these may be symbolic
2351;;; expressions where SIGMA is assumed real.
2352;;;
2353;;; (intv MASK LO HI) Interval form. MASK is 0=(), 1=(], 2=[), or 3=[].
2354;;; LO and HI are any real numbers, or symbolic
2355;;; expressions which are assumed real, and LO < HI.
2356;;; For [LO..HI], if LO = HI normalization produces LO,
2357;;; and if LO > HI normalization produces [LO..LO).
2358;;; For other intervals, if LO > HI normalization
2359;;; sets HI equal to LO.
2360;;;
2361;;; (mod N M) Number modulo M. When normalized, 0 <= N < M.
2362;;; N and M are real numbers.
2363;;;
2364;;; (var V S) Symbolic variable. V is a Lisp symbol which
2365;;; represents the variable's visible name. S is
2366;;; the symbol which actually stores the variable's
2367;;; value: (var pi var-pi).
2368;;;
2369;;; In general, combining rational numbers in a calculation always produces
2370;;; a rational result, but if either argument is a float, result is a float.
2371
2372;;; In the following comments, [x y z] means result is x, args must be y, z,
2373;;; respectively, where the code letters are:
2374;;;
2375;;; O Normalized object (vector or number)
2376;;; V Normalized vector
2377;;; N Normalized number of any type
2378;;; N Normalized complex number
2379;;; R Normalized real number (float or rational)
2380;;; F Normalized floating-point number
2381;;; T Normalized rational number
2382;;; I Normalized integer
2383;;; B Normalized big integer
2384;;; S Normalized small integer
2385;;; D Digit (small integer, 0..999)
2386;;; L Normalized bignum digit list (without "bigpos" or "bigneg" symbol)
2387;;; or normalized vector element list (without "vec")
2388;;; P Predicate (truth value)
2389;;; X Any Lisp object
2390;;; Z "nil"
2391;;;
2392;;; Lower-case letters signify possibly un-normalized values.
2393;;; "L.D" means a cons of an L and a D.
2394;;; [N N; n n] means result will be normalized if argument is.
2395;;; Also, [Public] marks routines intended to be called from outside.
2396;;; [This notation has been neglected in many recent routines.]
2397
730576f3
CW
2398(defvar math-eval-rules-cache)
2399(defvar math-eval-rules-cache-other)
136211a9 2400;;; Reduce an object to canonical (normalized) form. [O o; Z Z] [Public]
dc781413
JB
2401
2402(defvar math-normalize-a)
2403(defun math-normalize (math-normalize-a)
136211a9 2404 (cond
dc781413
JB
2405 ((not (consp math-normalize-a))
2406 (if (integerp math-normalize-a)
2a78421d 2407 (if (or (>= math-normalize-a math-small-integer-size)
a6d107f1 2408 (<= math-normalize-a (- math-small-integer-size)))
dc781413
JB
2409 (math-bignum math-normalize-a)
2410 math-normalize-a)
2411 math-normalize-a))
2412 ((eq (car math-normalize-a) 'bigpos)
2413 (if (eq (nth (1- (length math-normalize-a)) math-normalize-a) 0)
2a78421d 2414 (let* ((last (setq math-normalize-a
dc781413 2415 (copy-sequence math-normalize-a))) (digs math-normalize-a))
136211a9
EZ
2416 (while (setq digs (cdr digs))
2417 (or (eq (car digs) 0) (setq last digs)))
2418 (setcdr last nil)))
dc781413
JB
2419 (if (cdr (cdr (cdr math-normalize-a)))
2420 math-normalize-a
136211a9 2421 (cond
2a78421d
JB
2422 ((cdr (cdr math-normalize-a)) (+ (nth 1 math-normalize-a)
2423 (* (nth 2 math-normalize-a)
a6d107f1 2424 math-bignum-digit-size)))
dc781413 2425 ((cdr math-normalize-a) (nth 1 math-normalize-a))
136211a9 2426 (t 0))))
dc781413
JB
2427 ((eq (car math-normalize-a) 'bigneg)
2428 (if (eq (nth (1- (length math-normalize-a)) math-normalize-a) 0)
2a78421d 2429 (let* ((last (setq math-normalize-a (copy-sequence math-normalize-a)))
dc781413 2430 (digs math-normalize-a))
136211a9
EZ
2431 (while (setq digs (cdr digs))
2432 (or (eq (car digs) 0) (setq last digs)))
2433 (setcdr last nil)))
dc781413
JB
2434 (if (cdr (cdr (cdr math-normalize-a)))
2435 math-normalize-a
136211a9 2436 (cond
2a78421d
JB
2437 ((cdr (cdr math-normalize-a)) (- (+ (nth 1 math-normalize-a)
2438 (* (nth 2 math-normalize-a)
a6d107f1 2439 math-bignum-digit-size))))
dc781413 2440 ((cdr math-normalize-a) (- (nth 1 math-normalize-a)))
136211a9 2441 (t 0))))
dc781413 2442 ((eq (car math-normalize-a) 'float)
2a78421d 2443 (math-make-float (math-normalize (nth 1 math-normalize-a))
dc781413 2444 (nth 2 math-normalize-a)))
2a78421d 2445 ((or (memq (car math-normalize-a)
dc781413
JB
2446 '(frac cplx polar hms date mod sdev intv vec var quote
2447 special-const calcFunc-if calcFunc-lambda
2448 calcFunc-quote calcFunc-condition
2449 calcFunc-evalto))
2450 (integerp (car math-normalize-a))
2a78421d 2451 (and (consp (car math-normalize-a))
dc781413 2452 (not (eq (car (car math-normalize-a)) 'lambda))))
ce805efa 2453 (require 'calc-ext)
dc781413 2454 (math-normalize-fancy math-normalize-a))
136211a9
EZ
2455 (t
2456 (or (and calc-simplify-mode
ce805efa 2457 (require 'calc-ext)
136211a9 2458 (math-normalize-nonstandard))
dc781413 2459 (let ((args (mapcar 'math-normalize (cdr math-normalize-a))))
136211a9 2460 (or (condition-case err
2a78421d 2461 (let ((func
dc781413
JB
2462 (assq (car math-normalize-a) '( ( + . math-add )
2463 ( - . math-sub )
2464 ( * . math-mul )
2465 ( / . math-div )
2466 ( % . math-mod )
2467 ( ^ . math-pow )
2468 ( neg . math-neg )
2469 ( | . math-concat ) ))))
136211a9
EZ
2470 (or (and var-EvalRules
2471 (progn
2472 (or (eq var-EvalRules math-eval-rules-cache-tag)
2473 (progn
ce805efa 2474 (require 'calc-ext)
136211a9
EZ
2475 (math-recompile-eval-rules)))
2476 (and (or math-eval-rules-cache-other
2a78421d 2477 (assq (car math-normalize-a)
dc781413 2478 math-eval-rules-cache))
136211a9 2479 (math-apply-rewrites
dc781413 2480 (cons (car math-normalize-a) args)
136211a9
EZ
2481 (cdr math-eval-rules-cache)
2482 nil math-eval-rules-cache))))
2483 (if func
2484 (apply (cdr func) args)
dc781413
JB
2485 (and (or (consp (car math-normalize-a))
2486 (fboundp (car math-normalize-a))
ce805efa
JB
2487 (and (not (featurep 'calc-ext))
2488 (require 'calc-ext)
dc781413
JB
2489 (fboundp (car math-normalize-a))))
2490 (apply (car math-normalize-a) args)))))
136211a9
EZ
2491 (wrong-number-of-arguments
2492 (calc-record-why "*Wrong number of arguments"
dc781413 2493 (cons (car math-normalize-a) args))
136211a9
EZ
2494 nil)
2495 (wrong-type-argument
2a78421d 2496 (or calc-next-why
dc781413
JB
2497 (calc-record-why "Wrong type of argument"
2498 (cons (car math-normalize-a) args)))
136211a9
EZ
2499 nil)
2500 (args-out-of-range
2a78421d 2501 (calc-record-why "*Argument out of range"
dc781413 2502 (cons (car math-normalize-a) args))
136211a9
EZ
2503 nil)
2504 (inexact-result
2505 (calc-record-why "No exact representation for result"
dc781413 2506 (cons (car math-normalize-a) args))
136211a9
EZ
2507 nil)
2508 (math-overflow
2509 (calc-record-why "*Floating-point overflow occurred"
dc781413 2510 (cons (car math-normalize-a) args))
136211a9
EZ
2511 nil)
2512 (math-underflow
2513 (calc-record-why "*Floating-point underflow occurred"
dc781413 2514 (cons (car math-normalize-a) args))
136211a9
EZ
2515 nil)
2516 (void-variable
2517 (if (eq (nth 1 err) 'var-EvalRules)
2518 (progn
2519 (setq var-EvalRules nil)
dc781413 2520 (math-normalize (cons (car math-normalize-a) args)))
136211a9 2521 (calc-record-why "*Variable is void" (nth 1 err)))))
dc781413 2522 (if (consp (car math-normalize-a))
136211a9 2523 (math-dimension-error)
dc781413 2524 (cons (car math-normalize-a) args))))))))
136211a9
EZ
2525
2526
2527
2528;;; True if A is a floating-point real or complex number. [P x] [Public]
2529(defun math-floatp (a)
2530 (cond ((eq (car-safe a) 'float) t)
2531 ((memq (car-safe a) '(cplx polar mod sdev intv))
2532 (or (math-floatp (nth 1 a))
2533 (math-floatp (nth 2 a))
2534 (and (eq (car a) 'intv) (math-floatp (nth 3 a)))))
2535 ((eq (car-safe a) 'date)
bf77c646 2536 (math-floatp (nth 1 a)))))
136211a9
EZ
2537
2538
2539
2540;;; Verify that A is a complete object and return A. [x x] [Public]
2541(defun math-check-complete (a)
2542 (cond ((integerp a) a)
2543 ((eq (car-safe a) 'incomplete)
2544 (calc-incomplete-error a))
2545 ((consp a) a)
bf77c646 2546 (t (error "Invalid data object encountered"))))
136211a9
EZ
2547
2548
2549
2550;;; Coerce integer A to be a bignum. [B S]
2551(defun math-bignum (a)
2552 (if (>= a 0)
2553 (cons 'bigpos (math-bignum-big a))
bf77c646 2554 (cons 'bigneg (math-bignum-big (- a)))))
136211a9
EZ
2555
2556(defun math-bignum-big (a) ; [L s]
2557 (if (= a 0)
2558 nil
2a78421d 2559 (cons (% a math-bignum-digit-size)
a6d107f1 2560 (math-bignum-big (/ a math-bignum-digit-size)))))
136211a9
EZ
2561
2562
2563;;; Build a normalized floating-point number. [F I S]
2564(defun math-make-float (mant exp)
2565 (if (eq mant 0)
2566 '(float 0 0)
2567 (let* ((ldiff (- calc-internal-prec (math-numdigs mant))))
2568 (if (< ldiff 0)
2569 (setq mant (math-scale-rounding mant ldiff)
2570 exp (- exp ldiff))))
2571 (if (consp mant)
2572 (let ((digs (cdr mant)))
2573 (if (= (% (car digs) 10) 0)
2574 (progn
2575 (while (= (car digs) 0)
2576 (setq digs (cdr digs)
a6d107f1 2577 exp (+ exp math-bignum-digit-length)))
136211a9
EZ
2578 (while (= (% (car digs) 10) 0)
2579 (setq digs (math-div10-bignum digs)
2580 exp (1+ exp)))
2581 (setq mant (math-normalize (cons (car mant) digs))))))
2582 (while (= (% mant 10) 0)
2583 (setq mant (/ mant 10)
2584 exp (1+ exp))))
2585 (if (and (<= exp -4000000)
2586 (<= (+ exp (math-numdigs mant) -1) -4000000))
2587 (signal 'math-underflow nil)
2588 (if (and (>= exp 3000000)
2589 (>= (+ exp (math-numdigs mant) -1) 4000000))
2590 (signal 'math-overflow nil)
bf77c646 2591 (list 'float mant exp)))))
136211a9
EZ
2592
2593(defun math-div10-bignum (a) ; [l l]
2594 (if (cdr a)
2a78421d 2595 (cons (+ (/ (car a) 10) (* (% (nth 1 a) 10)
a6d107f1 2596 (expt 10 (1- math-bignum-digit-length))))
136211a9 2597 (math-div10-bignum (cdr a)))
bf77c646 2598 (list (/ (car a) 10))))
136211a9
EZ
2599
2600;;; Coerce A to be a float. [F N; V V] [Public]
2601(defun math-float (a)
2602 (cond ((Math-integerp a) (math-make-float a 0))
2603 ((eq (car a) 'frac) (math-div (math-float (nth 1 a)) (nth 2 a)))
2604 ((eq (car a) 'float) a)
2605 ((memq (car a) '(cplx polar vec hms date sdev mod))
2606 (cons (car a) (mapcar 'math-float (cdr a))))
bf77c646 2607 (t (math-float-fancy a))))
136211a9
EZ
2608
2609
2610(defun math-neg (a)
2611 (cond ((not (consp a)) (- a))
2612 ((eq (car a) 'bigpos) (cons 'bigneg (cdr a)))
2613 ((eq (car a) 'bigneg) (cons 'bigpos (cdr a)))
2614 ((memq (car a) '(frac float))
2615 (list (car a) (Math-integer-neg (nth 1 a)) (nth 2 a)))
2616 ((memq (car a) '(cplx vec hms date calcFunc-idn))
2617 (cons (car a) (mapcar 'math-neg (cdr a))))
bf77c646 2618 (t (math-neg-fancy a))))
136211a9
EZ
2619
2620
2621;;; Compute the number of decimal digits in integer A. [S I]
2622(defun math-numdigs (a)
2623 (if (consp a)
2624 (if (cdr a)
2625 (let* ((len (1- (length a)))
2626 (top (nth len a)))
a6d107f1 2627 (+ (* (1- len) math-bignum-digit-length) (math-numdigs top)))
136211a9
EZ
2628 0)
2629 (cond ((>= a 100) (+ (math-numdigs (/ a 1000)) 3))
2630 ((>= a 10) 2)
2631 ((>= a 1) 1)
2632 ((= a 0) 0)
2633 ((> a -10) 1)
2634 ((> a -100) 2)
bf77c646 2635 (t (math-numdigs (- a))))))
136211a9
EZ
2636
2637;;; Multiply (with truncation toward 0) the integer A by 10^N. [I i S]
2638(defun math-scale-int (a n)
2639 (cond ((= n 0) a)
2640 ((> n 0) (math-scale-left a n))
bf77c646 2641 (t (math-normalize (math-scale-right a (- n))))))
136211a9
EZ
2642
2643(defun math-scale-left (a n) ; [I I S]
2644 (if (= n 0)
2645 a
2646 (if (consp a)
2647 (cons (car a) (math-scale-left-bignum (cdr a) n))
a6d107f1 2648 (if (>= n math-bignum-digit-length)
2a78421d 2649 (if (or (>= a math-bignum-digit-size)
a6d107f1 2650 (<= a (- math-bignum-digit-size)))
136211a9 2651 (math-scale-left (math-bignum a) n)
2a78421d 2652 (math-scale-left (* a math-bignum-digit-size)
a6d107f1
JB
2653 (- n math-bignum-digit-length)))
2654 (let ((sz (expt 10 (- (* 2 math-bignum-digit-length) n))))
2655 (if (or (>= a sz) (<= a (- sz)))
2656 (math-scale-left (math-bignum a) n)
2657 (* a (expt 10 n))))))))
136211a9
EZ
2658
2659(defun math-scale-left-bignum (a n)
a6d107f1 2660 (if (>= n math-bignum-digit-length)
136211a9 2661 (while (>= (setq a (cons 0 a)
2a78421d 2662 n (- n math-bignum-digit-length))
a6d107f1 2663 math-bignum-digit-length)))
136211a9 2664 (if (> n 0)
a6d107f1 2665 (math-mul-bignum-digit a (expt 10 n) 0)
bf77c646 2666 a))
136211a9
EZ
2667
2668(defun math-scale-right (a n) ; [i i S]
2669 (if (= n 0)
2670 a
2671 (if (consp a)
2672 (cons (car a) (math-scale-right-bignum (cdr a) n))
2673 (if (<= a 0)
2674 (if (= a 0)
2675 0
2676 (- (math-scale-right (- a) n)))
a6d107f1
JB
2677 (if (>= n math-bignum-digit-length)
2678 (while (and (> (setq a (/ a math-bignum-digit-size)) 0)
2a78421d 2679 (>= (setq n (- n math-bignum-digit-length))
a6d107f1
JB
2680 math-bignum-digit-length))))
2681 (if (> n 0)
2682 (/ a (expt 10 n))
2683 a)))))
136211a9
EZ
2684
2685(defun math-scale-right-bignum (a n) ; [L L S; l l S]
a6d107f1
JB
2686 (if (>= n math-bignum-digit-length)
2687 (setq a (nthcdr (/ n math-bignum-digit-length) a)
2688 n (% n math-bignum-digit-length)))
136211a9 2689 (if (> n 0)
a6d107f1 2690 (cdr (math-mul-bignum-digit a (expt 10 (- math-bignum-digit-length n)) 0))
bf77c646 2691 a))
136211a9
EZ
2692
2693;;; Multiply (with rounding) the integer A by 10^N. [I i S]
2694(defun math-scale-rounding (a n)
2695 (cond ((>= n 0)
2696 (math-scale-left a n))
2697 ((consp a)
2698 (math-normalize
2699 (cons (car a)
a6d107f1 2700 (let ((val (if (< n (- math-bignum-digit-length))
2a78421d
JB
2701 (math-scale-right-bignum
2702 (cdr a)
a6d107f1
JB
2703 (- (- math-bignum-digit-length) n))
2704 (if (< n 0)
2a78421d
JB
2705 (math-mul-bignum-digit
2706 (cdr a)
a6d107f1
JB
2707 (expt 10 (+ math-bignum-digit-length n)) 0)
2708 (cdr a))))) ; n = -math-bignum-digit-length
2709 (if (and val (>= (car val) (/ math-bignum-digit-size 2)))
136211a9 2710 (if (cdr val)
a6d107f1 2711 (if (eq (car (cdr val)) (1- math-bignum-digit-size))
136211a9
EZ
2712 (math-add-bignum (cdr val) '(1))
2713 (cons (1+ (car (cdr val))) (cdr (cdr val))))
2714 '(1))
2715 (cdr val))))))
2716 (t
2717 (if (< a 0)
2718 (- (math-scale-rounding (- a) n))
2719 (if (= n -1)
2720 (/ (+ a 5) 10)
bf77c646 2721 (/ (+ (math-scale-right a (- -1 n)) 5) 10))))))
136211a9
EZ
2722
2723
2724;;; Compute the sum of A and B. [O O O] [Public]
2725(defun math-add (a b)
2726 (or
2727 (and (not (or (consp a) (consp b)))
2728 (progn
2729 (setq a (+ a b))
a6d107f1 2730 (if (or (<= a (- math-small-integer-size)) (>= a math-small-integer-size))
136211a9
EZ
2731 (math-bignum a)
2732 a)))
2733 (and (Math-zerop a) (not (eq (car-safe a) 'mod))
2734 (if (and (math-floatp a) (Math-ratp b)) (math-float b) b))
2735 (and (Math-zerop b) (not (eq (car-safe b) 'mod))
2736 (if (and (math-floatp b) (Math-ratp a)) (math-float a) a))
2737 (and (Math-objvecp a) (Math-objvecp b)
2738 (or
2739 (and (Math-integerp a) (Math-integerp b)
2740 (progn
2741 (or (consp a) (setq a (math-bignum a)))
2742 (or (consp b) (setq b (math-bignum b)))
2743 (if (eq (car a) 'bigneg)
2744 (if (eq (car b) 'bigneg)
2745 (cons 'bigneg (math-add-bignum (cdr a) (cdr b)))
2746 (math-normalize
2747 (let ((diff (math-sub-bignum (cdr b) (cdr a))))
2748 (if (eq diff 'neg)
2749 (cons 'bigneg (math-sub-bignum (cdr a) (cdr b)))
2750 (cons 'bigpos diff)))))
2751 (if (eq (car b) 'bigneg)
2752 (math-normalize
2753 (let ((diff (math-sub-bignum (cdr a) (cdr b))))
2754 (if (eq diff 'neg)
2755 (cons 'bigneg (math-sub-bignum (cdr b) (cdr a)))
2756 (cons 'bigpos diff))))
2757 (cons 'bigpos (math-add-bignum (cdr a) (cdr b)))))))
2758 (and (Math-ratp a) (Math-ratp b)
ce805efa 2759 (require 'calc-ext)
136211a9
EZ
2760 (calc-add-fractions a b))
2761 (and (Math-realp a) (Math-realp b)
2762 (progn
2763 (or (and (consp a) (eq (car a) 'float))
2764 (setq a (math-float a)))
2765 (or (and (consp b) (eq (car b) 'float))
2766 (setq b (math-float b)))
2767 (math-add-float a b)))
ce805efa 2768 (and (require 'calc-ext)
136211a9 2769 (math-add-objects-fancy a b))))
ce805efa 2770 (and (require 'calc-ext)
bf77c646 2771 (math-add-symb-fancy a b))))
136211a9
EZ
2772
2773(defun math-add-bignum (a b) ; [L L L; l l l]
2774 (if a
2775 (if b
2776 (let* ((a (copy-sequence a)) (aa a) (carry nil) sum)
2777 (while (and aa b)
2778 (if carry
2a78421d 2779 (if (< (setq sum (+ (car aa) (car b)))
a6d107f1 2780 (1- math-bignum-digit-size))
136211a9
EZ
2781 (progn
2782 (setcar aa (1+ sum))
2783 (setq carry nil))
9ae06d96 2784 (setcar aa (- sum (1- math-bignum-digit-size))))
a6d107f1 2785 (if (< (setq sum (+ (car aa) (car b))) math-bignum-digit-size)
136211a9 2786 (setcar aa sum)
a6d107f1 2787 (setcar aa (- sum math-bignum-digit-size))
136211a9
EZ
2788 (setq carry t)))
2789 (setq aa (cdr aa)
2790 b (cdr b)))
2791 (if carry
2792 (if b
2793 (nconc a (math-add-bignum b '(1)))
9ae06d96 2794 (while (eq (car aa) (1- math-bignum-digit-size))
136211a9
EZ
2795 (setcar aa 0)
2796 (setq aa (cdr aa)))
2797 (if aa
2798 (progn
2799 (setcar aa (1+ (car aa)))
2800 a)
2801 (nconc a '(1))))
2802 (if b
2803 (nconc a b)
2804 a)))
2805 a)
bf77c646 2806 b))
136211a9
EZ
2807
2808(defun math-sub-bignum (a b) ; [l l l]
2809 (if b
2810 (if a
730576f3 2811 (let* ((a (copy-sequence a)) (aa a) (borrow nil) sum diff)
136211a9
EZ
2812 (while (and aa b)
2813 (if borrow
2814 (if (>= (setq diff (- (car aa) (car b))) 1)
2815 (progn
2816 (setcar aa (1- diff))
2817 (setq borrow nil))
a6d107f1 2818 (setcar aa (+ diff (1- math-bignum-digit-size))))
136211a9
EZ
2819 (if (>= (setq diff (- (car aa) (car b))) 0)
2820 (setcar aa diff)
a6d107f1 2821 (setcar aa (+ diff math-bignum-digit-size))
136211a9
EZ
2822 (setq borrow t)))
2823 (setq aa (cdr aa)
2824 b (cdr b)))
2825 (if borrow
2826 (progn
2827 (while (eq (car aa) 0)
a6d107f1 2828 (setcar aa (1- math-bignum-digit-size))
136211a9
EZ
2829 (setq aa (cdr aa)))
2830 (if aa
2831 (progn
2832 (setcar aa (1- (car aa)))
2833 a)
2834 'neg))
2835 (while (eq (car b) 0)
2836 (setq b (cdr b)))
2837 (if b
2838 'neg
2839 a)))
2840 (while (eq (car b) 0)
2841 (setq b (cdr b)))
2842 (and b
2843 'neg))
bf77c646 2844 a))
136211a9
EZ
2845
2846(defun math-add-float (a b) ; [F F F]
2847 (let ((ediff (- (nth 2 a) (nth 2 b))))
2848 (if (>= ediff 0)
2849 (if (>= ediff (+ calc-internal-prec calc-internal-prec))
2850 a
2851 (math-make-float (math-add (nth 1 b)
2852 (if (eq ediff 0)
2853 (nth 1 a)
2854 (math-scale-left (nth 1 a) ediff)))
2855 (nth 2 b)))
2856 (if (>= (setq ediff (- ediff))
2857 (+ calc-internal-prec calc-internal-prec))
2858 b
2859 (math-make-float (math-add (nth 1 a)
2860 (math-scale-left (nth 1 b) ediff))
bf77c646 2861 (nth 2 a))))))
136211a9
EZ
2862
2863;;; Compute the difference of A and B. [O O O] [Public]
2864(defun math-sub (a b)
2865 (if (or (consp a) (consp b))
2866 (math-add a (math-neg b))
2867 (setq a (- a b))
a6d107f1 2868 (if (or (<= a (- math-small-integer-size)) (>= a math-small-integer-size))
136211a9 2869 (math-bignum a)
bf77c646 2870 a)))
136211a9
EZ
2871
2872(defun math-sub-float (a b) ; [F F F]
2873 (let ((ediff (- (nth 2 a) (nth 2 b))))
2874 (if (>= ediff 0)
2875 (if (>= ediff (+ calc-internal-prec calc-internal-prec))
2876 a
2877 (math-make-float (math-add (Math-integer-neg (nth 1 b))
2878 (if (eq ediff 0)
2879 (nth 1 a)
2880 (math-scale-left (nth 1 a) ediff)))
2881 (nth 2 b)))
2882 (if (>= (setq ediff (- ediff))
2883 (+ calc-internal-prec calc-internal-prec))
2884 b
2885 (math-make-float (math-add (nth 1 a)
2886 (Math-integer-neg
2887 (math-scale-left (nth 1 b) ediff)))
bf77c646 2888 (nth 2 a))))))
136211a9
EZ
2889
2890
2891;;; Compute the product of A and B. [O O O] [Public]
2892(defun math-mul (a b)
2893 (or
2894 (and (not (consp a)) (not (consp b))
2a78421d 2895 (< a math-bignum-digit-size) (> a (- math-bignum-digit-size))
a6d107f1 2896 (< b math-bignum-digit-size) (> b (- math-bignum-digit-size))
136211a9
EZ
2897 (* a b))
2898 (and (Math-zerop a) (not (eq (car-safe b) 'mod))
2899 (if (Math-scalarp b)
2900 (if (and (math-floatp b) (Math-ratp a)) (math-float a) a)
ce805efa 2901 (require 'calc-ext)
136211a9
EZ
2902 (math-mul-zero a b)))
2903 (and (Math-zerop b) (not (eq (car-safe a) 'mod))
2904 (if (Math-scalarp a)
2905 (if (and (math-floatp a) (Math-ratp b)) (math-float b) b)
ce805efa 2906 (require 'calc-ext)
136211a9
EZ
2907 (math-mul-zero b a)))
2908 (and (Math-objvecp a) (Math-objvecp b)
2909 (or
2910 (and (Math-integerp a) (Math-integerp b)
2911 (progn
2912 (or (consp a) (setq a (math-bignum a)))
2913 (or (consp b) (setq b (math-bignum b)))
2914 (math-normalize
2915 (cons (if (eq (car a) (car b)) 'bigpos 'bigneg)
2916 (if (cdr (cdr a))
2917 (if (cdr (cdr b))
2918 (math-mul-bignum (cdr a) (cdr b))
2919 (math-mul-bignum-digit (cdr a) (nth 1 b) 0))
2920 (math-mul-bignum-digit (cdr b) (nth 1 a) 0))))))
2921 (and (Math-ratp a) (Math-ratp b)
ce805efa 2922 (require 'calc-ext)
136211a9
EZ
2923 (calc-mul-fractions a b))
2924 (and (Math-realp a) (Math-realp b)
2925 (progn
2926 (or (and (consp a) (eq (car a) 'float))
2927 (setq a (math-float a)))
2928 (or (and (consp b) (eq (car b) 'float))
2929 (setq b (math-float b)))
2930 (math-make-float (math-mul (nth 1 a) (nth 1 b))
2931 (+ (nth 2 a) (nth 2 b)))))
ce805efa 2932 (and (require 'calc-ext)
136211a9 2933 (math-mul-objects-fancy a b))))
ce805efa 2934 (and (require 'calc-ext)
bf77c646 2935 (math-mul-symb-fancy a b))))
136211a9
EZ
2936
2937(defun math-infinitep (a &optional undir)
2938 (while (and (consp a) (memq (car a) '(* / neg)))
2939 (if (or (not (eq (car a) '*)) (math-infinitep (nth 1 a)))
2940 (setq a (nth 1 a))
2941 (setq a (nth 2 a))))
2942 (and (consp a)
2943 (eq (car a) 'var)
2944 (memq (nth 2 a) '(var-inf var-uinf var-nan))
2945 (if (and undir (eq (nth 2 a) 'var-inf))
2946 '(var uinf var-uinf)
bf77c646 2947 a)))
136211a9
EZ
2948
2949;;; Multiply digit lists A and B. [L L L; l l l]
2950(defun math-mul-bignum (a b)
2951 (and a b
2952 (let* ((sum (if (<= (car b) 1)
2953 (if (= (car b) 0)
2954 (list 0)
2955 (copy-sequence a))
2956 (math-mul-bignum-digit a (car b) 0)))
2957 (sump sum) c d aa ss prod)
2958 (while (setq b (cdr b))
2959 (setq ss (setq sump (or (cdr sump) (setcdr sump (list 0))))
2960 d (car b)
2961 c 0
2962 aa a)
2963 (while (progn
2964 (setcar ss (% (setq prod (+ (+ (car ss) (* (car aa) d))
a6d107f1 2965 c)) math-bignum-digit-size))
136211a9 2966 (setq aa (cdr aa)))
a6d107f1 2967 (setq c (/ prod math-bignum-digit-size)
136211a9 2968 ss (or (cdr ss) (setcdr ss (list 0)))))
a6d107f1 2969 (if (>= prod math-bignum-digit-size)
136211a9 2970 (if (cdr ss)
a6d107f1
JB
2971 (setcar (cdr ss) (+ (/ prod math-bignum-digit-size) (car (cdr ss))))
2972 (setcdr ss (list (/ prod math-bignum-digit-size))))))
bf77c646 2973 sum)))
136211a9
EZ
2974
2975;;; Multiply digit list A by digit D. [L L D D; l l D D]
2976(defun math-mul-bignum-digit (a d c)
2977 (if a
2978 (if (<= d 1)
2979 (and (= d 1) a)
2980 (let* ((a (copy-sequence a)) (aa a) prod)
2981 (while (progn
2a78421d
JB
2982 (setcar aa
2983 (% (setq prod (+ (* (car aa) d) c))
a6d107f1 2984 math-bignum-digit-size))
136211a9
EZ
2985 (cdr aa))
2986 (setq aa (cdr aa)
a6d107f1
JB
2987 c (/ prod math-bignum-digit-size)))
2988 (if (>= prod math-bignum-digit-size)
2989 (setcdr aa (list (/ prod math-bignum-digit-size))))
136211a9
EZ
2990 a))
2991 (and (> c 0)
bf77c646 2992 (list c))))
136211a9
EZ
2993
2994
2995;;; Compute the integer (quotient . remainder) of A and B, which may be
2996;;; small or big integers. Type and consistency of truncation is undefined
2997;;; if A or B is negative. B must be nonzero. [I.I I I] [Public]
2998(defun math-idivmod (a b)
2999 (if (eq b 0)
3000 (math-reject-arg a "*Division by zero"))
3001 (if (or (consp a) (consp b))
a6d107f1 3002 (if (and (natnump b) (< b math-bignum-digit-size))
136211a9
EZ
3003 (let ((res (math-div-bignum-digit (cdr a) b)))
3004 (cons
3005 (math-normalize (cons (car a) (car res)))
3006 (cdr res)))
3007 (or (consp a) (setq a (math-bignum a)))
3008 (or (consp b) (setq b (math-bignum b)))
3009 (let ((res (math-div-bignum (cdr a) (cdr b))))
3010 (cons
3011 (math-normalize (cons (if (eq (car a) (car b)) 'bigpos 'bigneg)
3012 (car res)))
3013 (math-normalize (cons (car a) (cdr res))))))
bf77c646 3014 (cons (/ a b) (% a b))))
136211a9
EZ
3015
3016(defun math-quotient (a b) ; [I I I] [Public]
3017 (if (and (not (consp a)) (not (consp b)))
3018 (if (= b 0)
3019 (math-reject-arg a "*Division by zero")
3020 (/ a b))
a6d107f1 3021 (if (and (natnump b) (< b math-bignum-digit-size))
136211a9
EZ
3022 (if (= b 0)
3023 (math-reject-arg a "*Division by zero")
3024 (math-normalize (cons (car a)
3025 (car (math-div-bignum-digit (cdr a) b)))))
3026 (or (consp a) (setq a (math-bignum a)))
3027 (or (consp b) (setq b (math-bignum b)))
3028 (let* ((alen (1- (length a)))
3029 (blen (1- (length b)))
a6d107f1 3030 (d (/ math-bignum-digit-size (1+ (nth (1- blen) (cdr b)))))
136211a9
EZ
3031 (res (math-div-bignum-big (math-mul-bignum-digit (cdr a) d 0)
3032 (math-mul-bignum-digit (cdr b) d 0)
3033 alen blen)))
3034 (math-normalize (cons (if (eq (car a) (car b)) 'bigpos 'bigneg)
bf77c646 3035 (car res)))))))
136211a9
EZ
3036
3037
3038;;; Divide a bignum digit list by another. [l.l l L]
3039;;; The following division algorithm is borrowed from Knuth vol. II, sec. 4.3.1
3040(defun math-div-bignum (a b)
3041 (if (cdr b)
3042 (let* ((alen (length a))
3043 (blen (length b))
a6d107f1 3044 (d (/ math-bignum-digit-size (1+ (nth (1- blen) b))))
136211a9
EZ
3045 (res (math-div-bignum-big (math-mul-bignum-digit a d 0)
3046 (math-mul-bignum-digit b d 0)
3047 alen blen)))
3048 (if (= d 1)
3049 res
3050 (cons (car res)
3051 (car (math-div-bignum-digit (cdr res) d)))))
3052 (let ((res (math-div-bignum-digit a (car b))))
bf77c646 3053 (cons (car res) (list (cdr res))))))
136211a9
EZ
3054
3055;;; Divide a bignum digit list by a digit. [l.D l D]
3056(defun math-div-bignum-digit (a b)
3057 (if a
3058 (let* ((res (math-div-bignum-digit (cdr a) b))
a6d107f1 3059 (num (+ (* (cdr res) math-bignum-digit-size) (car a))))
136211a9
EZ
3060 (cons
3061 (cons (/ num b) (car res))
3062 (% num b)))
bf77c646 3063 '(nil . 0)))
136211a9
EZ
3064
3065(defun math-div-bignum-big (a b alen blen) ; [l.l l L]
3066 (if (< alen blen)
3067 (cons nil a)
3068 (let* ((res (math-div-bignum-big (cdr a) b (1- alen) blen))
3069 (num (cons (car a) (cdr res)))
3070 (res2 (math-div-bignum-part num b blen)))
3071 (cons
3072 (cons (car res2) (car res))
bf77c646 3073 (cdr res2)))))
136211a9 3074
a6d107f1 3075(defun math-div-bignum-part (a b blen) ; a < b*math-bignum-digit-size [D.l l L]
2a78421d 3076 (let* ((num (+ (* (or (nth blen a) 0) math-bignum-digit-size)
a6d107f1 3077 (or (nth (1- blen) a) 0)))
136211a9 3078 (den (nth (1- blen) b))
a6d107f1 3079 (guess (min (/ num den) (1- math-bignum-digit-size))))
bf77c646 3080 (math-div-bignum-try a b (math-mul-bignum-digit b guess 0) guess)))
136211a9
EZ
3081
3082(defun math-div-bignum-try (a b c guess) ; [D.l l l D]
3083 (let ((rem (math-sub-bignum a c)))
3084 (if (eq rem 'neg)
3085 (math-div-bignum-try a b (math-sub-bignum c b) (1- guess))
bf77c646 3086 (cons guess rem))))
136211a9
EZ
3087
3088
3089;;; Compute the quotient of A and B. [O O N] [Public]
3090(defun math-div (a b)
3091 (or
3092 (and (Math-zerop b)
ce805efa 3093 (require 'calc-ext)
136211a9
EZ
3094 (math-div-by-zero a b))
3095 (and (Math-zerop a) (not (eq (car-safe b) 'mod))
3096 (if (Math-scalarp b)
3097 (if (and (math-floatp b) (Math-ratp a)) (math-float a) a)
ce805efa 3098 (require 'calc-ext)
136211a9
EZ
3099 (math-div-zero a b)))
3100 (and (Math-objvecp a) (Math-objvecp b)
3101 (or
3102 (and (Math-integerp a) (Math-integerp b)
3103 (let ((q (math-idivmod a b)))
3104 (if (eq (cdr q) 0)
3105 (car q)
3106 (if calc-prefer-frac
3107 (progn
ce805efa 3108 (require 'calc-ext)
136211a9
EZ
3109 (math-make-frac a b))
3110 (math-div-float (math-make-float a 0)
3111 (math-make-float b 0))))))
3112 (and (Math-ratp a) (Math-ratp b)
ce805efa 3113 (require 'calc-ext)
136211a9
EZ
3114 (calc-div-fractions a b))
3115 (and (Math-realp a) (Math-realp b)
3116 (progn
3117 (or (and (consp a) (eq (car a) 'float))
3118 (setq a (math-float a)))
3119 (or (and (consp b) (eq (car b) 'float))
3120 (setq b (math-float b)))
3121 (math-div-float a b)))
ce805efa 3122 (and (require 'calc-ext)
136211a9 3123 (math-div-objects-fancy a b))))
ce805efa 3124 (and (require 'calc-ext)
bf77c646 3125 (math-div-symb-fancy a b))))
136211a9
EZ
3126
3127(defun math-div-float (a b) ; [F F F]
3128 (let ((ldiff (max (- (1+ calc-internal-prec)
3129 (- (math-numdigs (nth 1 a)) (math-numdigs (nth 1 b))))
3130 0)))
3131 (math-make-float (math-quotient (math-scale-int (nth 1 a) ldiff) (nth 1 b))
bf77c646 3132 (- (- (nth 2 a) (nth 2 b)) ldiff))))
136211a9
EZ
3133
3134
3135
3136
730576f3 3137(defvar calc-selection-cache-entry)
136211a9
EZ
3138;;; Format the number A as a string. [X N; X Z] [Public]
3139(defun math-format-stack-value (entry)
3140 (setq calc-selection-cache-entry calc-selection-cache-default-entry)
3141 (let* ((a (car entry))
3142 (math-comp-selected (nth 2 entry))
3143 (c (cond ((null a) "<nil>")
3144 ((eq calc-display-raw t) (format "%s" a))
3145 ((stringp a) a)
cd012309 3146 ((eq a 'top-of-stack) (propertize "." 'font-lock-face 'bold))
136211a9
EZ
3147 (calc-prepared-composition
3148 calc-prepared-composition)
3149 ((and (Math-scalarp a)
3150 (memq calc-language '(nil flat unform))
3151 (null math-comp-selected))
3152 (math-format-number a))
ce805efa 3153 (t (require 'calc-ext)
136211a9
EZ
3154 (math-compose-expr a 0))))
3155 (off (math-stack-value-offset c))
3156 s w)
3157 (and math-comp-selected (setq calc-any-selections t))
3158 (setq w (cdr off)
3159 off (car off))
cd012309 3160 (when (> off 0)
111a5355 3161 (setq c (math-comp-concat (make-string off ?\s) c)))
136211a9
EZ
3162 (or (equal calc-left-label "")
3163 (setq c (math-comp-concat (if (eq a 'top-of-stack)
111a5355 3164 (make-string (length calc-left-label) ?\s)
136211a9
EZ
3165 calc-left-label)
3166 c)))
cd012309
CW
3167 (when calc-line-numbering
3168 (setq c (math-comp-concat (if (eq calc-language 'big)
2363bd8d
DK
3169 (if math-comp-selected
3170 '(tag t "1: ")
3171 "1: ")
cd012309
CW
3172 " ")
3173 c)))
3174 (unless (or (equal calc-right-label "")
3175 (eq a 'top-of-stack))
ce805efa 3176 (require 'calc-ext)
cd012309
CW
3177 (setq c (list 'horiz c
3178 (make-string (max (- w (math-comp-width c)
111a5355 3179 (length calc-right-label)) 0) ?\s)
cd012309
CW
3180 '(break -1)
3181 calc-right-label)))
136211a9
EZ
3182 (setq s (if (stringp c)
3183 (if calc-display-raw
3184 (prin1-to-string c)
3185 c)
3186 (math-composition-to-string c w)))
cd012309
CW
3187 (when calc-language-output-filter
3188 (setq s (funcall calc-language-output-filter s)))
136211a9
EZ
3189 (if (eq calc-language 'big)
3190 (setq s (concat s "\n"))
cd012309 3191 (when calc-line-numbering
6a3ed064 3192 (setq s (concat "1:" (substring s 2)))))
136211a9 3193 (setcar (cdr entry) (calc-count-lines s))
bf77c646 3194 s))
136211a9 3195
f0a35df4
JB
3196;; The variables math-svo-c, math-svo-wid and math-svo-off are local
3197;; to math-stack-value-offset, but are used by math-stack-value-offset-fancy
3198;; in calccomp.el.
3199
3200(defun math-stack-value-offset (math-svo-c)
136211a9 3201 (let* ((num (if calc-line-numbering 4 0))
f0a35df4
JB
3202 (math-svo-wid (calc-window-width))
3203 math-svo-off)
136211a9
EZ
3204 (if calc-display-just
3205 (progn
ce805efa 3206 (require 'calc-ext)
136211a9 3207 (math-stack-value-offset-fancy))
f0a35df4 3208 (setq math-svo-off (or calc-display-origin 0))
cd012309 3209 (when (integerp calc-line-breaking)
f0a35df4
JB
3210 (setq math-svo-wid calc-line-breaking)))
3211 (cons (max (- math-svo-off (length calc-left-label)) 0)
3212 (+ math-svo-wid num))))
136211a9
EZ
3213
3214(defun calc-count-lines (s)
3215 (let ((pos 0)
3216 (num 1))
730576f3
CW
3217 (while (setq pos (string-match "\n" s pos))
3218 (setq pos (1+ pos)
136211a9 3219 num (1+ num)))
bf77c646 3220 num))
136211a9
EZ
3221
3222(defun math-format-value (a &optional w)
3223 (if (and (Math-scalarp a)
3224 (memq calc-language '(nil flat unform)))
3225 (math-format-number a)
ce805efa 3226 (require 'calc-ext)
136211a9 3227 (let ((calc-line-breaking nil))
bf77c646 3228 (math-composition-to-string (math-compose-expr a 0) w))))
136211a9
EZ
3229
3230(defun calc-window-width ()
3231 (if calc-embedded-info
3232 (let ((win (get-buffer-window (aref calc-embedded-info 0))))
31b85a14 3233 (1- (if win (window-width win) (frame-width))))
136211a9 3234 (- (window-width (get-buffer-window (current-buffer)))
bf77c646 3235 (if calc-line-numbering 5 1))))
136211a9
EZ
3236
3237(defun math-comp-concat (c1 c2)
3238 (if (and (stringp c1) (stringp c2))
3239 (concat c1 c2)
bf77c646 3240 (list 'horiz c1 c2)))
136211a9
EZ
3241
3242
3243
3244;;; Format an expression as a one-line string suitable for re-reading.
3245
3246(defun math-format-flat-expr (a prec)
3247 (cond
3248 ((or (not (or (consp a) (integerp a)))
3249 (eq calc-display-raw t))
3250 (let ((print-escape-newlines t))
3251 (concat "'" (prin1-to-string a))))
3252 ((Math-scalarp a)
3253 (let ((calc-group-digits nil)
3254 (calc-point-char ".")
3255 (calc-frac-format (if (> (length (car calc-frac-format)) 1)
3256 '("::" nil) '(":" nil)))
3257 (calc-complex-format nil)
3258 (calc-hms-format "%s@ %s' %s\"")
3259 (calc-language nil))
3260 (math-format-number a)))
3261 (t
ce805efa 3262 (require 'calc-ext)
bf77c646 3263 (math-format-flat-expr-fancy a prec))))
136211a9
EZ
3264
3265
3266
3267;;; Format a number as a string.
3268(defun math-format-number (a &optional prec) ; [X N] [Public]
3269 (cond
3270 ((eq calc-display-raw t) (format "%s" a))
3271 ((and (nth 1 calc-frac-format) (Math-integerp a))
ce805efa 3272 (require 'calc-ext)
136211a9
EZ
3273 (math-format-number (math-adjust-fraction a)))
3274 ((integerp a)
3275 (if (not (or calc-group-digits calc-leading-zeros))
3276 (if (= calc-number-radix 10)
3277 (int-to-string a)
3278 (if (< a 0)
3279 (concat "-" (math-format-number (- a)))
ce805efa 3280 (require 'calc-ext)
136211a9
EZ
3281 (if math-radix-explicit-format
3282 (if calc-radix-formatter
3283 (funcall calc-radix-formatter
3284 calc-number-radix
3285 (if (= calc-number-radix 2)
3286 (math-format-binary a)
3287 (math-format-radix a)))
3288 (format "%d#%s" calc-number-radix
3289 (if (= calc-number-radix 2)
3290 (math-format-binary a)
3291 (math-format-radix a))))
3292 (math-format-radix a))))
3293 (math-format-number (math-bignum a))))
3294 ((stringp a) a)
3295 ((not (consp a)) (prin1-to-string a))
3296 ((eq (car a) 'bigpos) (math-format-bignum (cdr a)))
3297 ((eq (car a) 'bigneg) (concat "-" (math-format-bignum (cdr a))))
3298 ((and (eq (car a) 'float) (= calc-number-radix 10))
3299 (if (Math-integer-negp (nth 1 a))
3300 (concat "-" (math-format-number (math-neg a)))
3301 (let ((mant (nth 1 a))
3302 (exp (nth 2 a))
3303 (fmt (car calc-float-format))
3304 (figs (nth 1 calc-float-format))
3305 (point calc-point-char)
3306 str)
3307 (if (and (eq fmt 'fix)
3308 (or (and (< figs 0) (setq figs (- figs)))
3309 (> (+ exp (math-numdigs mant)) (- figs))))
3310 (progn
3311 (setq mant (math-scale-rounding mant (+ exp figs))
3312 str (if (integerp mant)
3313 (int-to-string mant)
3314 (math-format-bignum-decimal (cdr mant))))
3315 (if (<= (length str) figs)
3316 (setq str (concat (make-string (1+ (- figs (length str))) ?0)
3317 str)))
3318 (if (> figs 0)
3319 (setq str (concat (substring str 0 (- figs)) point
3320 (substring str (- figs))))
3321 (setq str (concat str point)))
91da6442
CW
3322 (when calc-group-digits
3323 (require 'calc-ext)
3324 (setq str (math-group-float str))))
cd012309
CW
3325 (when (< figs 0)
3326 (setq figs (+ calc-internal-prec figs)))
3327 (when (> figs 0)
3328 (let ((adj (- figs (math-numdigs mant))))
3329 (when (< adj 0)
3330 (setq mant (math-scale-rounding mant adj)
3331 exp (- exp adj)))))
136211a9
EZ
3332 (setq str (if (integerp mant)
3333 (int-to-string mant)
3334 (math-format-bignum-decimal (cdr mant))))
3335 (let* ((len (length str))
3336 (dpos (+ exp len)))
3337 (if (and (eq fmt 'float)
3338 (<= dpos (+ calc-internal-prec calc-display-sci-high))
3339 (>= dpos (+ calc-display-sci-low 2)))
3340 (progn
3341 (cond
3342 ((= dpos 0)
3343 (setq str (concat "0" point str)))
3344 ((and (<= exp 0) (> dpos 0))
3345 (setq str (concat (substring str 0 dpos) point
3346 (substring str dpos))))
3347 ((> exp 0)
3348 (setq str (concat str (make-string exp ?0) point)))
3349 (t ; (< dpos 0)
3350 (setq str (concat "0" point
3351 (make-string (- dpos) ?0) str))))
91da6442
CW
3352 (when calc-group-digits
3353 (require 'calc-ext)
3354 (setq str (math-group-float str))))
136211a9
EZ
3355 (let* ((eadj (+ exp len))
3356 (scale (if (eq fmt 'eng)
3357 (1+ (math-mod (+ eadj 300002) 3))
3358 1)))
3359 (if (> scale (length str))
3360 (setq str (concat str (make-string (- scale (length str))
3361 ?0))))
3362 (if (< scale (length str))
3363 (setq str (concat (substring str 0 scale) point
3364 (substring str scale))))
91da6442
CW
3365 (when calc-group-digits
3366 (require 'calc-ext)
3367 (setq str (math-group-float str)))
136211a9
EZ
3368 (setq str (format (if (memq calc-language '(math maple))
3369 (if (and prec (> prec 191))
3370 "(%s*10.^%d)" "%s*10.^%d")
3371 "%se%d")
3372 str (- eadj scale)))))))
3373 str)))
3374 (t
ce805efa 3375 (require 'calc-ext)
bf77c646 3376 (math-format-number-fancy a prec))))
136211a9
EZ
3377
3378(defun math-format-bignum (a) ; [X L]
3379 (if (and (= calc-number-radix 10)
3380 (not calc-leading-zeros)
3381 (not calc-group-digits))
3382 (math-format-bignum-decimal a)
ce805efa 3383 (require 'calc-ext)
bf77c646 3384 (math-format-bignum-fancy a)))
136211a9
EZ
3385
3386(defun math-format-bignum-decimal (a) ; [X L]
3387 (if a
3388 (let ((s ""))
3389 (while (cdr (cdr a))
2a78421d
JB
3390 (setq s (concat
3391 (format
3392 (concat "%0"
3393 (number-to-string (* 2 math-bignum-digit-length))
a6d107f1
JB
3394 "d")
3395 (+ (* (nth 1 a) math-bignum-digit-size) (car a))) s)
136211a9 3396 a (cdr (cdr a))))
2a78421d 3397 (concat (int-to-string
a6d107f1 3398 (+ (* (or (nth 1 a) 0) math-bignum-digit-size) (car a))) s))
bf77c646 3399 "0"))
136211a9
EZ
3400
3401
3402
3403;;; Parse a simple number in string form. [N X] [Public]
3404(defun math-read-number (s)
e90988a0 3405 "Convert the string S into a Calc number."
136211a9
EZ
3406 (math-normalize
3407 (cond
3408
3409 ;; Integers (most common case)
3410 ((string-match "\\` *\\([0-9]+\\) *\\'" s)
3411 (let ((digs (math-match-substring s 1)))
3412 (if (and (eq calc-language 'c)
3413 (> (length digs) 1)
3414 (eq (aref digs 0) ?0))
3415 (math-read-number (concat "8#" digs))
e90988a0 3416 (if (<= (length digs) (* 2 math-bignum-digit-length))
28572d7d 3417 (string-to-number digs)
136211a9
EZ
3418 (cons 'bigpos (math-read-bignum digs))))))
3419
3420 ;; Clean up the string if necessary
3421 ((string-match "\\`\\(.*\\)[ \t\n]+\\([^\001]*\\)\\'" s)
3422 (math-read-number (concat (math-match-substring s 1)
3423 (math-match-substring s 2))))
3424
3425 ;; Plus and minus signs
3426 ((string-match "^[-_+]\\(.*\\)$" s)
3427 (let ((val (math-read-number (math-match-substring s 1))))
3428 (and val (if (eq (aref s 0) ?+) val (math-neg val)))))
3429
3430 ;; Forms that require extensions module
3431 ((string-match "[^-+0-9eE.]" s)
ce805efa 3432 (require 'calc-ext)
136211a9
EZ
3433 (math-read-number-fancy s))
3434
3435 ;; Decimal point
3436 ((string-match "^\\([0-9]*\\)\\.\\([0-9]*\\)$" s)
3437 (let ((int (math-match-substring s 1))
3438 (frac (math-match-substring s 2)))
3439 (let ((ilen (length int))
3440 (flen (length frac)))
3441 (let ((int (if (> ilen 0) (math-read-number int) 0))
3442 (frac (if (> flen 0) (math-read-number frac) 0)))
3443 (and int frac (or (> ilen 0) (> flen 0))
3444 (list 'float
3445 (math-add (math-scale-int int flen) frac)
3446 (- flen)))))))
3447
3448 ;; "e" notation
3449 ((string-match "^\\(.*\\)[eE]\\([-+]?[0-9]+\\)$" s)
3450 (let ((mant (math-match-substring s 1))
3451 (exp (math-match-substring s 2)))
3452 (let ((mant (if (> (length mant) 0) (math-read-number mant) 1))
3453 (exp (if (<= (length exp) (if (memq (aref exp 0) '(?+ ?-)) 8 7))
28572d7d 3454 (string-to-number exp))))
136211a9
EZ
3455 (and mant exp (Math-realp mant) (> exp -4000000) (< exp 4000000)
3456 (let ((mant (math-float mant)))
3457 (list 'float (nth 1 mant) (+ (nth 2 mant) exp)))))))
3458
3459 ;; Syntax error!
bf77c646 3460 (t nil))))
136211a9 3461
1f26c380
JB
3462;;; Parse a very simple number, keeping all digits.
3463(defun math-read-number-simple (s)
e90988a0
JB
3464 "Convert the string S into a Calc number.
3465S is assumed to be a simple number (integer or float without an exponent)
3466and all digits are kept, regardless of Calc's current precision."
1f26c380
JB
3467 (cond
3468 ;; Integer
3469 ((string-match "^[0-9]+$" s)
aefad52d
JB
3470 (if (string-match "^\\(0+\\)" s)
3471 (setq s (substring s (match-end 0))))
e90988a0
JB
3472 (if (<= (length s) (* 2 math-bignum-digit-length))
3473 (string-to-number s)
3474 (cons 'bigpos (math-read-bignum s))))
1f26c380
JB
3475 ;; Minus sign
3476 ((string-match "^-[0-9]+$" s)
e90988a0
JB
3477 (if (<= (length s) (1+ (* 2 math-bignum-digit-length)))
3478 (string-to-number s)
3479 (cons 'bigneg (math-read-bignum (substring s 1)))))
1f26c380
JB
3480 ;; Decimal point
3481 ((string-match "^\\(-?[0-9]*\\)\\.\\([0-9]*\\)$" s)
3482 (let ((int (math-match-substring s 1))
3483 (frac (math-match-substring s 2)))
3484 (list 'float (math-read-number-simple (concat int frac))
3485 (- (length frac)))))
3486 ;; Syntax error!
3487 (t nil)))
3488
136211a9
EZ
3489(defun math-match-substring (s n)
3490 (if (match-beginning n)
3491 (substring s (match-beginning n) (match-end n))
bf77c646 3492 ""))
136211a9
EZ
3493
3494(defun math-read-bignum (s) ; [l X]
a6d107f1
JB
3495 (if (> (length s) math-bignum-digit-length)
3496 (cons (string-to-number (substring s (- math-bignum-digit-length)))
3497 (math-read-bignum (substring s 0 (- math-bignum-digit-length))))
28572d7d 3498 (list (string-to-number s))))
136211a9
EZ
3499
3500
3501(defconst math-tex-ignore-words
3502 '( ("\\hbox") ("\\mbox") ("\\text") ("\\left") ("\\right")
3503 ("\\,") ("\\>") ("\\:") ("\\;") ("\\!") ("\\ ")
3504 ("\\quad") ("\\qquad") ("\\hfil") ("\\hfill")
3505 ("\\displaystyle") ("\\textstyle") ("\\dsize") ("\\tsize")
3506 ("\\scriptstyle") ("\\scriptscriptstyle") ("\\ssize") ("\\sssize")
3507 ("\\rm") ("\\bf") ("\\it") ("\\sl")
3508 ("\\roman") ("\\bold") ("\\italic") ("\\slanted")
3509 ("\\cal") ("\\mit") ("\\Cal") ("\\Bbb") ("\\frak") ("\\goth")
3510 ("\\evalto")
3511 ("\\matrix" mat) ("\\bmatrix" mat) ("\\pmatrix" mat)
dacc4c70 3512 ("\\begin" begenv)
136211a9 3513 ("\\cr" punc ";") ("\\\\" punc ";") ("\\*" punc "*")
998858ae
JB
3514 ("\\{" punc "[") ("\\}" punc "]")))
3515
3516(defconst math-latex-ignore-words
3517 (append math-tex-ignore-words
3518 '(("\\begin" begenv))))
136211a9
EZ
3519
3520(defconst math-eqn-ignore-words
3521 '( ("roman") ("bold") ("italic") ("mark") ("lineup") ("evalto")
3522 ("left" ("floor") ("ceil"))
3523 ("right" ("floor") ("ceil"))
3524 ("arc" ("sin") ("cos") ("tan") ("sinh") ("cosh") ("tanh"))
3525 ("size" n) ("font" n) ("fwd" n) ("back" n) ("up" n) ("down" n)
998858ae 3526 ("above" punc ",")))
136211a9
EZ
3527
3528(defconst math-standard-opers
3529 '( ( "_" calcFunc-subscr 1200 1201 )
3530 ( "%" calcFunc-percent 1100 -1 )
136211a9
EZ
3531 ( "u!" calcFunc-lnot -1 1000 )
3532 ( "mod" mod 400 400 185 )
3533 ( "+/-" sdev 300 300 185 )
3534 ( "!!" calcFunc-dfact 210 -1 )
3535 ( "!" calcFunc-fact 210 -1 )
3536 ( "^" ^ 201 200 )
3537 ( "**" ^ 201 200 )
c8d00744
JB
3538 ( "u+" ident -1 197 )
3539 ( "u-" neg -1 197 )
136211a9
EZ
3540 ( "/" / 190 191 )
3541 ( "%" % 190 191 )
3542 ( "\\" calcFunc-idiv 190 191 )
3543 ( "+" + 180 181 )
3544 ( "-" - 180 181 )
3545 ( "|" | 170 171 )
3546 ( "<" calcFunc-lt 160 161 )
3547 ( ">" calcFunc-gt 160 161 )
3548 ( "<=" calcFunc-leq 160 161 )
3549 ( ">=" calcFunc-geq 160 161 )
3550 ( "=" calcFunc-eq 160 161 )
3551 ( "==" calcFunc-eq 160 161 )
3552 ( "!=" calcFunc-neq 160 161 )
3553 ( "&&" calcFunc-land 110 111 )
3554 ( "||" calcFunc-lor 100 101 )
3555 ( "?" (math-read-if) 91 90 )
3556 ( "!!!" calcFunc-pnot -1 85 )
3557 ( "&&&" calcFunc-pand 80 81 )
3558 ( "|||" calcFunc-por 75 76 )
3559 ( ":=" calcFunc-assign 51 50 )
3560 ( "::" calcFunc-condition 45 46 )
3561 ( "=>" calcFunc-evalto 40 41 )
f269b73e 3562 ( "=>" calcFunc-evalto 40 -1 )))
515e955e
JB
3563
3564(defun math-standard-ops ()
3565 (if calc-multiplication-has-precedence
3566 (cons
3567 '( "*" * 196 195 )
3568 (cons
3569 '( "2x" * 196 195 )
3570 math-standard-opers))
3571 (cons
cad63e32 3572 '( "*" * 190 191 )
515e955e 3573 (cons
cad63e32 3574 '( "2x" * 190 191 )
515e955e
JB
3575 math-standard-opers))))
3576
a6a0d3cb
JB
3577(defvar math-expr-opers (math-standard-ops))
3578
515e955e
JB
3579(defun math-standard-ops-p ()
3580 (let ((meo (caar math-expr-opers)))
3581 (and (stringp meo)
3582 (string= meo "*"))))
3583
515e955e
JB
3584(defun math-expr-ops ()
3585 (if (math-standard-ops-p)
3586 (math-standard-ops)
3587 math-expr-opers))
136211a9
EZ
3588
3589;;;###autoload
3590(defun calc-grab-region (top bot arg)
3591 "Parse the region as a vector of numbers and push it on the Calculator stack."
3592 (interactive "r\nP")
ce805efa 3593 (require 'calc-ext)
bf77c646 3594 (calc-do-grab-region top bot arg))
136211a9
EZ
3595
3596;;;###autoload
3597(defun calc-grab-rectangle (top bot arg)
3598 "Parse a rectangle as a matrix of numbers and push it on the Calculator stack."
3599 (interactive "r\nP")
ce805efa 3600 (require 'calc-ext)
bf77c646 3601 (calc-do-grab-rectangle top bot arg))
136211a9
EZ
3602
3603(defun calc-grab-sum-down (top bot arg)
3604 "Parse a rectangle as a matrix of numbers and sum its columns."
3605 (interactive "r\nP")
ce805efa 3606 (require 'calc-ext)
bf77c646 3607 (calc-do-grab-rectangle top bot arg 'calcFunc-reduced))
136211a9
EZ
3608
3609(defun calc-grab-sum-across (top bot arg)
3610 "Parse a rectangle as a matrix of numbers and sum its rows."
3611 (interactive "r\nP")
ce805efa 3612 (require 'calc-ext)
bf77c646 3613 (calc-do-grab-rectangle top bot arg 'calcFunc-reducea))
136211a9
EZ
3614
3615
3616;;;###autoload
3617(defun calc-embedded (arg &optional end obeg oend)
3618 "Start Calc Embedded mode on the formula surrounding point."
3619 (interactive "P")
ce805efa 3620 (require 'calc-ext)
bf77c646 3621 (calc-do-embedded arg end obeg oend))
136211a9
EZ
3622
3623;;;###autoload
3624(defun calc-embedded-activate (&optional arg cbuf)
3625 "Scan the current editing buffer for all embedded := and => formulas.
3626Also looks for the equivalent TeX words, \\gets and \\evalto."
3627 (interactive "P")
bf77c646 3628 (calc-do-embedded-activate arg cbuf))
136211a9 3629
136211a9
EZ
3630(defun calc-user-invocation ()
3631 (interactive)
dd168a3e 3632 (unless calc-invocation-macro
d24f83d4 3633 (error "Use `Z I' inside Calc to define a `C-x * Z' keyboard macro"))
bf77c646 3634 (execute-kbd-macro calc-invocation-macro nil))
136211a9 3635
136211a9
EZ
3636;;; User-programmability.
3637
3638;;;###autoload
3639(defmacro defmath (func args &rest body) ; [Public]
ce805efa 3640 (require 'calc-ext)
bf77c646 3641 (math-do-defmath func args body))
136211a9 3642
136211a9
EZ
3643;;; Functions needed for Lucid Emacs support.
3644
3645(defun calc-read-key (&optional optkey)
6546555e 3646 (cond ((featurep 'xemacs)
136211a9
EZ
3647 (let ((event (next-command-event)))
3648 (let ((key (event-to-character event t t)))
3649 (or key optkey (error "Expected a plain keystroke"))
3650 (cons key event))))
136211a9 3651 (t
cecd4c20 3652 (let ((key (read-event)))
bf77c646 3653 (cons key key)))))
136211a9
EZ
3654
3655(defun calc-unread-command (&optional input)
31b85a14
EZ
3656 (if (featurep 'xemacs)
3657 (setq unread-command-event
3658 (if (integerp input) (character-to-event input)
3659 (or input last-command-event)))
3660 (push (or input last-command-event) unread-command-events)))
136211a9
EZ
3661
3662(defun calc-clear-unread-commands ()
a1506d29 3663 (if (featurep 'xemacs)
6546555e 3664 (setq unread-command-event nil)
31b85a14 3665 (setq unread-command-events nil)))
136211a9 3666
cd012309 3667(when calc-always-load-extensions
ce805efa 3668 (require 'calc-ext)
cd012309 3669 (calc-load-everything))
136211a9
EZ
3670
3671
3672(run-hooks 'calc-load-hook)
3673
ce805efa
JB
3674(provide 'calc)
3675
ab5796a9 3676;;; arch-tag: 0c3b170c-4ce6-4eaf-8d9b-5834d1fe938f
bf77c646 3677;;; calc.el ends here