Add `backward-delete-char-untabify' to the list of bindings to remap when
[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)
84b4b70d 1012 (where-is-internal 'backward-delete-char-untabify global-map)
2a78421d
JB
1013 '("\C-d"))
1014 '("\177" "\C-d")))
136211a9 1015
730576f3
CW
1016(defvar calc-dispatch-map
1017 (let ((map (make-keymap)))
2a78421d
JB
1018 (mapc (lambda (x)
1019 (define-key map (char-to-string (car x)) (cdr x))
1020 (when (string-match "abcdefhijklnopqrstuwxyz"
1021 (char-to-string (car x)))
1022 (define-key map (char-to-string (- (car x) ?a -1)) (cdr x)))
1023 (define-key map (format "\e%c" (car x)) (cdr x)))
1024 '( ( ?a . calc-embedded-activate )
1025 ( ?b . calc-big-or-small )
1026 ( ?c . calc )
1027 ( ?d . calc-embedded-duplicate )
1028 ( ?e . calc-embedded )
1029 ( ?f . calc-embedded-new-formula )
1030 ( ?g . calc-grab-region )
1031 ( ?h . calc-dispatch-help )
1032 ( ?i . calc-info )
1033 ( ?j . calc-embedded-select )
1034 ( ?k . calc-keypad )
1035 ( ?l . calc-load-everything )
1036 ( ?m . read-kbd-macro )
1037 ( ?n . calc-embedded-next )
1038 ( ?o . calc-other-window )
1039 ( ?p . calc-embedded-previous )
1040 ( ?q . quick-calc )
1041 ( ?r . calc-grab-rectangle )
1042 ( ?s . calc-info-summary )
1043 ( ?t . calc-tutorial )
1044 ( ?u . calc-embedded-update-formula )
1045 ( ?w . calc-embedded-word )
1046 ( ?x . calc-quit )
1047 ( ?y . calc-copy-to-buffer )
1048 ( ?z . calc-user-invocation )
1049 ( ?\' . calc-embedded-new-formula )
1050 ( ?\` . calc-embedded-edit )
1051 ( ?: . calc-grab-sum-down )
1052 ( ?_ . calc-grab-sum-across )
1053 ( ?0 . calc-reset )
1054 ( ?? . calc-dispatch-help )
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 )
1062 ( ?- . calc-same-interface ) ))
80f952a2 1063 map))
136211a9 1064
136211a9 1065;;;; (Autoloads here)
2a78421d 1066(mapc
730576f3 1067 (lambda (x) (dolist (func (cdr x)) (autoload func (car x))))
136211a9
EZ
1068 '(
1069
451d4c5c 1070 ("calc-aent" calc-alg-digit-entry calc-alg-entry
730576f3
CW
1071 calc-check-user-syntax calc-do-alg-entry calc-do-calc-eval
1072 calc-do-quick-calc calc-match-user-syntax math-build-parse-table
1073 math-find-user-tokens math-read-expr-list math-read-exprs math-read-if
5ff9dafd 1074 math-read-token math-remove-dashes math-read-preprocess-string)
136211a9 1075
451d4c5c
JB
1076 ("calc-embed" calc-do-embedded-activate)
1077
2a78421d 1078 ("calc-misc"
730576f3
CW
1079 calc-do-handle-whys calc-do-refresh calc-num-prefix-name
1080 calc-record-list calc-record-why calc-report-bug calc-roll-down-stack
1081 calc-roll-up-stack calc-temp-minibuffer-message calcFunc-floor
1082 calcFunc-inv calcFunc-trunc math-concat math-constp math-div2
1083 math-div2-bignum math-do-working math-evenp math-fixnatnump
1084 math-fixnump math-floor math-imod math-ipow math-looks-negp math-mod
1085 math-negp math-posp math-pow math-read-radix-digit math-reject-arg
1086 math-trunc math-zerop)))
1087
2a78421d 1088(mapc
730576f3 1089 (lambda (x) (dolist (cmd (cdr x)) (autoload cmd (car x) nil t)))
136211a9
EZ
1090 '(
1091
1092 ("calc-aent" calc-algebraic-entry calc-auto-algebraic-entry
730576f3 1093 calcDigit-algebraic calcDigit-edit)
136211a9
EZ
1094
1095 ("calc-misc" another-calc calc-big-or-small calc-dispatch-help
2a78421d 1096 calc-help calc-info calc-info-goto-node calc-info-summary calc-inv
9d3c486a 1097 calc-last-args-stub
730576f3
CW
1098 calc-missing-key calc-mod calc-other-window calc-over calc-percent
1099 calc-pop-above calc-power calc-roll-down calc-roll-up
1100 calc-shift-Y-prefix-help calc-tutorial calcDigit-letter
1101 report-calc-bug)))
136211a9
EZ
1102
1103
d24f83d4 1104;;;###autoload (define-key ctl-x-map "*" 'calc-dispatch)
136211a9
EZ
1105
1106;;;###autoload
1107(defun calc-dispatch (&optional arg)
f269b73e 1108 "Invoke the GNU Emacs Calculator. See `calc-dispatch-help' for details."
136211a9 1109 (interactive "P")
99992264 1110; (sit-for echo-keystrokes)
136211a9
EZ
1111 (condition-case err ; look for other keys bound to calc-dispatch
1112 (let ((keys (this-command-keys)))
cd012309
CW
1113 (unless (or (not (stringp keys))
1114 (string-match "\\`\C-u\\|\\`\e[-0-9#]\\|`[\M--\M-0-\M-9]" keys)
1115 (eq (lookup-key calc-dispatch-map keys) 'calc-same-interface))
1116 (when (and (string-match "\\`[\C-@-\C-_]" keys)
1117 (symbolp
1118 (lookup-key calc-dispatch-map (substring keys 0 1))))
1119 (define-key calc-dispatch-map (substring keys 0 1) nil))
1120 (define-key calc-dispatch-map keys 'calc-same-interface)))
136211a9 1121 (error nil))
bf77c646 1122 (calc-do-dispatch arg))
136211a9 1123
f269b73e 1124(defvar calc-dispatch-help nil)
136211a9
EZ
1125(defun calc-do-dispatch (arg)
1126 (let ((key (calc-read-key-sequence
1127 (if calc-dispatch-help
1128 "Calc options: Calc, Keypad, Quick, Embed; eXit; Info, Tutorial; Grab; ?=more"
1129 (format "%s (Type ? for a list of Calc options)"
1130 (key-description (this-command-keys))))
1131 calc-dispatch-map)))
1132 (setq key (lookup-key calc-dispatch-map key))
1133 (message "")
1134 (if key
1135 (progn
ce805efa 1136 (or (commandp key) (require 'calc-ext))
136211a9 1137 (call-interactively key))
bf77c646 1138 (beep))))
136211a9
EZ
1139
1140(defun calc-read-key-sequence (prompt map)
1141 (let ((prompt2 (format "%s " (key-description (this-command-keys))))
1142 (glob (current-global-map))
1143 (loc (current-local-map)))
1144 (or (input-pending-p) (message prompt))
1145 (let ((key (calc-read-key t)))
1146 (calc-unread-command (cdr key))
1147 (unwind-protect
1148 (progn
1149 (use-global-map map)
1150 (use-local-map nil)
7e1637c2 1151 (read-key-sequence nil))
136211a9 1152 (use-global-map glob)
bf77c646 1153 (use-local-map loc)))))
136211a9 1154
f5a3eb30 1155(defvar calc-alg-map) ; Defined in calc-ext.el
136211a9 1156
bd149d6e
JB
1157(defun calc-version ()
1158 "Return version of this version of Calc."
1159 (interactive)
1160 (message (concat "Calc version " calc-version)))
1161
136211a9
EZ
1162(defun calc-mode ()
1163 "Calculator major mode.
1164
1165This is an RPN calculator featuring arbitrary-precision integer, rational,
1166floating-point, complex, matrix, and symbolic arithmetic.
1167
1168RPN calculation: 2 RET 3 + produces 5.
1169Algebraic style: ' 2+3 RET produces 5.
1170
1171Basic operators are +, -, *, /, ^, & (reciprocal), % (modulo), n (change-sign).
1172
1173Press ? repeatedly for more complete help. Press `h i' to read the
1174Calc manual on-line, `h s' to read the summary, or `h t' for the tutorial.
1175
1176Notations: 3.14e6 3.14 * 10^6
1177 _23 negative number -23 (or type `23 n')
1178 17:3 the fraction 17/3
1179 5:2:3 the fraction 5 and 2/3
1180 16#12C the integer 12C base 16 = 300 base 10
1181 8#177:100 the fraction 177:100 base 8 = 127:64 base 10
1182 (2, 4) complex number 2 + 4i
1183 (2; 4) polar complex number (r; theta)
1184 [1, 2, 3] vector ([[1, 2], [3, 4]] is a matrix)
1185 [1 .. 4) semi-open interval, 1 <= x < 4
1186 2 +/- 3 (p key) number with mean 2, standard deviation 3
1187 2 mod 3 (M key) number 2 computed modulo 3
1188 <1 jan 91> Date form (enter using ' key)
1189
1190
1191\\{calc-mode-map}
1192"
1193 (interactive)
2a78421d
JB
1194 (mapc (function
1195 (lambda (v) (set-default v (symbol-value v)))) calc-local-var-list)
136211a9
EZ
1196 (kill-all-local-variables)
1197 (use-local-map (if (eq calc-algebraic-mode 'total)
ce805efa 1198 (progn (require 'calc-ext) calc-alg-map) calc-mode-map))
2a78421d 1199 (mapc (function (lambda (v) (make-local-variable v))) calc-local-var-list)
136211a9
EZ
1200 (make-local-variable 'overlay-arrow-position)
1201 (make-local-variable 'overlay-arrow-string)
558f9ba1 1202 (add-hook 'change-major-mode-hook 'font-lock-defontify nil t)
136211a9
EZ
1203 (setq truncate-lines t)
1204 (setq buffer-read-only t)
1205 (setq major-mode 'calc-mode)
1206 (setq mode-name "Calculator")
1207 (setq calc-stack-top (length (or (memq (assq 'top-of-stack calc-stack)
1208 calc-stack)
1209 (setq calc-stack (list (list 'top-of-stack
1210 1 nil))))))
1211 (setq calc-stack-top (- (length calc-stack) calc-stack-top -1))
1212 (or calc-loaded-settings-file
f269b73e 1213 (null calc-settings-file)
a8aee43b 1214 (equal calc-settings-file user-init-file)
136211a9
EZ
1215 (progn
1216 (setq calc-loaded-settings-file t)
6bbfeec5 1217 (load (file-name-sans-extension calc-settings-file) t))) ; t = missing-ok
136211a9
EZ
1218 (let ((p command-line-args))
1219 (while p
1220 (and (equal (car p) "-f")
1221 (string-match "calc" (nth 1 p))
1222 (string-match "full" (nth 1 p))
1223 (setq calc-standalone-flag t))
1224 (setq p (cdr p))))
d74fa98c 1225 (run-mode-hooks 'calc-mode-hook)
136211a9
EZ
1226 (calc-refresh t)
1227 (calc-set-mode-line)
bf77c646 1228 (calc-check-defines))
136211a9 1229
f269b73e 1230(defvar calc-check-defines 'calc-check-defines) ; suitable for run-hooks
136211a9
EZ
1231(defun calc-check-defines ()
1232 (if (symbol-plist 'calc-define)
1233 (let ((plist (copy-sequence (symbol-plist 'calc-define))))
1234 (while (and plist (null (nth 1 plist)))
1235 (setq plist (cdr (cdr plist))))
1236 (if plist
1237 (save-excursion
ce805efa
JB
1238 (require 'calc-ext)
1239 (require 'calc-macs)
136211a9
EZ
1240 (set-buffer "*Calculator*")
1241 (while plist
1242 (put 'calc-define (car plist) nil)
1243 (eval (nth 1 plist))
1244 (setq plist (cdr (cdr plist))))
1245 ;; See if this has added any more calc-define properties.
1246 (calc-check-defines))
bf77c646 1247 (setplist 'calc-define nil)))))
136211a9
EZ
1248
1249(defun calc-trail-mode (&optional buf)
1250 "Calc Trail mode.
1251This mode is used by the *Calc Trail* buffer, which records all results
1252obtained by the GNU Emacs Calculator.
1253
1254Calculator commands beginning with the `t' key are used to manipulate
1255the Trail.
1256
1257This buffer uses the same key map as the *Calculator* buffer; calculator
1258commands given here will actually operate on the *Calculator* stack."
1259 (interactive)
1260 (fundamental-mode)
1261 (use-local-map calc-mode-map)
1262 (setq major-mode 'calc-trail-mode)
1263 (setq mode-name "Calc Trail")
1264 (setq truncate-lines t)
1265 (setq buffer-read-only t)
1266 (make-local-variable 'overlay-arrow-position)
1267 (make-local-variable 'overlay-arrow-string)
cd012309
CW
1268 (when buf
1269 (set (make-local-variable 'calc-main-buffer) buf))
1270 (when (= (buffer-size) 0)
1271 (let ((buffer-read-only nil))
802ed9b9 1272 (insert (propertize (concat "Emacs Calculator Trail\n")
cd012309 1273 'font-lock-face 'italic))))
d74fa98c 1274 (run-mode-hooks 'calc-trail-mode-hook))
136211a9
EZ
1275
1276(defun calc-create-buffer ()
1277 (set-buffer (get-buffer-create "*Calculator*"))
1278 (or (eq major-mode 'calc-mode)
1279 (calc-mode))
1280 (setq max-lisp-eval-depth (max max-lisp-eval-depth 1000))
cd012309 1281 (when calc-always-load-extensions
ce805efa 1282 (require 'calc-ext))
cd012309 1283 (when calc-language
ce805efa 1284 (require 'calc-ext)
cd012309 1285 (calc-set-language calc-language calc-language-option t)))
136211a9
EZ
1286
1287;;;###autoload
1288(defun calc (&optional arg full-display interactive)
1289 "The Emacs Calculator. Full documentation is listed under \"calc-mode\"."
577e1b74 1290 (interactive "P\ni\np")
136211a9 1291 (if arg
cd012309 1292 (unless (eq arg 0)
ce805efa 1293 (require 'calc-ext)
cd012309
CW
1294 (if (= (prefix-numeric-value arg) -1)
1295 (calc-grab-region (region-beginning) (region-end) nil)
1296 (when (= (prefix-numeric-value arg) -2)
1297 (calc-keypad))))
1298 (when (get-buffer-window "*Calc Keypad*")
1299 (calc-keypad)
1300 (set-buffer (window-buffer (selected-window))))
136211a9
EZ
1301 (if (eq major-mode 'calc-mode)
1302 (calc-quit)
1303 (let ((oldbuf (current-buffer)))
1304 (calc-create-buffer)
1305 (setq calc-was-keypad-mode nil)
1306 (if (or (eq full-display t)
1307 (and (null full-display) calc-full-mode))
1308 (switch-to-buffer (current-buffer) t)
1309 (if (get-buffer-window (current-buffer))
1310 (select-window (get-buffer-window (current-buffer)))
ed65ed86
JB
1311 (if calc-window-hook
1312 (run-hooks 'calc-window-hook)
1313 (let ((w (get-largest-window)))
1314 (if (and pop-up-windows
1315 (> (window-height w)
1316 (+ window-min-height calc-window-height 2)))
1317 (progn
1318 (setq w (split-window w
1319 (- (window-height w)
1320 calc-window-height 2)
1321 nil))
1322 (set-window-buffer w (current-buffer))
1323 (select-window w))
1324 (pop-to-buffer (current-buffer)))))))
136211a9
EZ
1325 (save-excursion
1326 (set-buffer (calc-trail-buffer))
1327 (and calc-display-trail
31b85a14 1328 (= (window-width) (frame-width))
136211a9 1329 (calc-trail-display 1 t)))
f269b73e 1330 (message "Welcome to the GNU Emacs Calculator! Press `?' or `h' for help, `q' to quit")
136211a9
EZ
1331 (run-hooks 'calc-start-hook)
1332 (and (windowp full-display)
1333 (window-point full-display)
1334 (select-window full-display))
1335 (calc-check-defines)
577e1b74 1336 (when (and calc-said-hello interactive)
cd012309
CW
1337 (sit-for 2)
1338 (message ""))
bf77c646 1339 (setq calc-said-hello t)))))
136211a9
EZ
1340
1341;;;###autoload
577e1b74 1342(defun full-calc (&optional interactive)
136211a9 1343 "Invoke the Calculator and give it a full-sized window."
577e1b74
JB
1344 (interactive "p")
1345 (calc nil t interactive))
136211a9
EZ
1346
1347(defun calc-same-interface (arg)
1348 "Invoke the Calculator using the most recent interface (calc or calc-keypad)."
1349 (interactive "P")
1350 (if (and (equal (buffer-name) "*Gnuplot Trail*")
1351 (> (recursion-depth) 0))
1352 (exit-recursive-edit)
1353 (if (eq major-mode 'calc-edit-mode)
1354 (calc-edit-finish arg)
c84eeafa
JB
1355 (if calc-was-keypad-mode
1356 (calc-keypad)
1357 (calc arg calc-full-mode t)))))
136211a9 1358
577e1b74
JB
1359(defun calc-quit (&optional non-fatal interactive)
1360 (interactive "i\np")
136211a9
EZ
1361 (and calc-standalone-flag (not non-fatal)
1362 (save-buffers-kill-emacs nil))
1363 (if (and (equal (buffer-name) "*Gnuplot Trail*")
1364 (> (recursion-depth) 0))
1365 (exit-recursive-edit))
1366 (if (eq major-mode 'calc-edit-mode)
1367 (calc-edit-cancel)
c84eeafa
JB
1368 (if (and interactive
1369 calc-embedded-info
1370 (eq (current-buffer) (aref calc-embedded-info 0)))
1371 (calc-embedded nil)
1372 (unless (eq major-mode 'calc-mode)
1373 (calc-create-buffer))
1374 (run-hooks 'calc-end-hook)
1375 (setq calc-undo-list nil calc-redo-list nil)
2a78421d
JB
1376 (mapc (function (lambda (v) (set-default v (symbol-value v))))
1377 calc-local-var-list)
c84eeafa
JB
1378 (let ((buf (current-buffer))
1379 (win (get-buffer-window (current-buffer)))
1380 (kbuf (get-buffer "*Calc Keypad*")))
1381 (delete-windows-on (calc-trail-buffer))
1382 (if (and win
1383 (< (window-height win) (1- (frame-height)))
1384 (= (window-width win) (frame-width)) ; avoid calc-keypad
1385 (not (get-buffer-window "*Calc Keypad*")))
1386 (setq calc-window-height (- (window-height win) 2)))
1387 (progn
1388 (delete-windows-on buf)
1389 (delete-windows-on kbuf))
1390 (bury-buffer buf)
1391 (bury-buffer calc-trail-buffer)
1392 (and kbuf (bury-buffer kbuf))))))
136211a9
EZ
1393
1394;;;###autoload
1395(defun quick-calc ()
1396 "Do a quick calculation in the minibuffer without invoking full Calculator."
1397 (interactive)
bf77c646 1398 (calc-do-quick-calc))
136211a9
EZ
1399
1400;;;###autoload
1401(defun calc-eval (str &optional separator &rest args)
1402 "Do a quick calculation and return the result as a string.
1403Return value will either be the formatted result in string form,
1404or a list containing a character position and an error message in string form."
bf77c646 1405 (calc-do-calc-eval str separator args))
136211a9
EZ
1406
1407;;;###autoload
577e1b74 1408(defun calc-keypad (&optional interactive)
136211a9
EZ
1409 "Invoke the Calculator in \"visual keypad\" mode.
1410This is most useful in the X window system.
1411In this mode, click on the Calc \"buttons\" using the left mouse button.
1412Or, position the cursor manually and do M-x calc-keypad-press."
577e1b74 1413 (interactive "p")
ce805efa 1414 (require 'calc-ext)
577e1b74 1415 (calc-do-keypad calc-full-mode interactive))
136211a9
EZ
1416
1417;;;###autoload
577e1b74 1418(defun full-calc-keypad (&optional interactive)
136211a9
EZ
1419 "Invoke the Calculator in full-screen \"visual keypad\" mode.
1420See calc-keypad for details."
577e1b74 1421 (interactive "p")
ce805efa 1422 (require 'calc-ext)
577e1b74 1423 (calc-do-keypad t interactive))
136211a9
EZ
1424
1425
f269b73e
CW
1426(defvar calc-aborted-prefix nil)
1427(defvar calc-start-time nil)
730576f3
CW
1428(defvar calc-command-flags)
1429(defvar calc-final-point-line)
1430(defvar calc-final-point-column)
136211a9
EZ
1431;;; Note that modifications to this function may break calc-pass-errors.
1432(defun calc-do (do-body &optional do-slow)
1433 (calc-check-defines)
1434 (let* ((calc-command-flags nil)
1435 (calc-start-time (and calc-timing (not calc-start-time)
ce805efa 1436 (require 'calc-ext)
136211a9
EZ
1437 (current-time-string)))
1438 (gc-cons-threshold (max gc-cons-threshold
730576f3
CW
1439 (if calc-timing 2000000 100000)))
1440 calc-final-point-line calc-final-point-column)
136211a9
EZ
1441 (setq calc-aborted-prefix "")
1442 (unwind-protect
1443 (condition-case err
1444 (save-excursion
1445 (if calc-embedded-info
1446 (calc-embedded-select-buffer)
1447 (calc-select-buffer))
1448 (and (eq calc-algebraic-mode 'total)
ce805efa 1449 (require 'calc-ext)
136211a9 1450 (use-local-map calc-alg-map))
f269b73e
CW
1451 (when (and do-slow calc-display-working-message)
1452 (message "Working...")
1453 (calc-set-command-flag 'clear-message))
136211a9
EZ
1454 (funcall do-body)
1455 (setq calc-aborted-prefix nil)
f269b73e
CW
1456 (when (memq 'renum-stack calc-command-flags)
1457 (calc-renumber-stack))
1458 (when (memq 'clear-message calc-command-flags)
1459 (message "")))
136211a9
EZ
1460 (error
1461 (if (and (eq (car err) 'error)
1462 (stringp (nth 1 err))
1463 (string-match "max-specpdl-size\\|max-lisp-eval-depth"
1464 (nth 1 err)))
f269b73e 1465 (error "Computation got stuck or ran too long. Type `M' to increase the limit")
136211a9
EZ
1466 (setq calc-aborted-prefix nil)
1467 (signal (car err) (cdr err)))))
f269b73e
CW
1468 (when calc-aborted-prefix
1469 (calc-record "<Aborted>" calc-aborted-prefix))
136211a9
EZ
1470 (and calc-start-time
1471 (let* ((calc-internal-prec 12)
1472 (calc-date-format nil)
1473 (end-time (current-time-string))
1474 (time (if (equal calc-start-time end-time)
1475 0
1476 (math-sub
1477 (calcFunc-unixtime (math-parse-date end-time) 0)
1478 (calcFunc-unixtime (math-parse-date calc-start-time)
1479 0)))))
1480 (if (math-lessp 1 time)
1481 (calc-record time "(t)"))))
1482 (or (memq 'no-align calc-command-flags)
1483 (eq major-mode 'calc-trail-mode)
1484 (calc-align-stack-window))
1485 (and (memq 'position-point calc-command-flags)
1486 (if (eq major-mode 'calc-mode)
1487 (progn
1488 (goto-line calc-final-point-line)
1489 (move-to-column calc-final-point-column))
730576f3 1490 (save-current-buffer
136211a9
EZ
1491 (calc-select-buffer)
1492 (goto-line calc-final-point-line)
1493 (move-to-column calc-final-point-column))))
f269b73e
CW
1494 (unless (memq 'keep-flags calc-command-flags)
1495 (save-excursion
1496 (calc-select-buffer)
1497 (setq calc-inverse-flag nil
1498 calc-hyperbolic-flag nil
1499 calc-keep-args-flag nil)))
1500 (when (memq 'do-edit calc-command-flags)
1501 (switch-to-buffer (get-buffer-create "*Calc Edit*")))
136211a9 1502 (calc-set-mode-line)
f269b73e
CW
1503 (when calc-embedded-info
1504 (calc-embedded-finish-command))))
bf77c646
CW
1505 (identity nil)) ; allow a GC after timing is done
1506
136211a9
EZ
1507
1508(defun calc-set-command-flag (f)
f269b73e
CW
1509 (unless (memq f calc-command-flags)
1510 (setq calc-command-flags (cons f calc-command-flags))))
136211a9
EZ
1511
1512(defun calc-select-buffer ()
1513 (or (eq major-mode 'calc-mode)
1514 (if calc-main-buffer
1515 (set-buffer calc-main-buffer)
1516 (let ((buf (get-buffer "*Calculator*")))
1517 (if buf
1518 (set-buffer buf)
bf77c646 1519 (error "Calculator buffer not available"))))))
136211a9
EZ
1520
1521(defun calc-cursor-stack-index (&optional index)
1522 (goto-char (point-max))
bf77c646 1523 (forward-line (- (calc-substack-height (or index 1)))))
136211a9
EZ
1524
1525(defun calc-stack-size ()
bf77c646 1526 (- (length calc-stack) calc-stack-top))
136211a9
EZ
1527
1528(defun calc-substack-height (n)
1529 (let ((sum 0)
1530 (stack calc-stack))
1531 (setq n (+ n calc-stack-top))
1532 (while (and (> n 0) stack)
1533 (setq sum (+ sum (nth 1 (car stack)))
1534 n (1- n)
1535 stack (cdr stack)))
bf77c646 1536 sum))
136211a9
EZ
1537
1538(defun calc-set-mode-line ()
1539 (save-excursion
1540 (calc-select-buffer)
1541 (let* ((fmt (car calc-float-format))
1542 (figs (nth 1 calc-float-format))
1543 (new-mode-string
1544 (format "Calc%s%s: %d %s %-14s"
1545 (if calc-embedded-info "Embed" "")
1546 (if (and (> (length (buffer-name)) 12)
1547 (equal (substring (buffer-name) 0 12)
1548 "*Calculator*"))
1549 (substring (buffer-name) 12)
1550 "")
1551 calc-internal-prec
1552 (capitalize (symbol-name calc-angle-mode))
1553 (concat
1554
1555 ;; Input-related modes
1556 (if (eq calc-algebraic-mode 'total) "Alg* "
1557 (if calc-algebraic-mode "Alg "
1558 (if calc-incomplete-algebraic-mode "Alg[( " "")))
1559
1560 ;; Computational modes
1561 (if calc-symbolic-mode "Symb " "")
1562 (cond ((eq calc-matrix-mode 'matrix) "Matrix ")
1563 ((integerp calc-matrix-mode)
1564 (format "Matrix%d " calc-matrix-mode))
bbcaa3e3 1565 ((eq calc-matrix-mode 'sqmatrix) "SqMatrix ")
136211a9
EZ
1566 ((eq calc-matrix-mode 'scalar) "Scalar ")
1567 (t ""))
1568 (if (eq calc-complex-mode 'polar) "Polar " "")
1569 (if calc-prefer-frac "Frac " "")
1570 (cond ((null calc-infinite-mode) "")
1571 ((eq calc-infinite-mode 1) "+Inf ")
1572 (t "Inf "))
1573 (cond ((eq calc-simplify-mode 'none) "NoSimp ")
1574 ((eq calc-simplify-mode 'num) "NumSimp ")
1575 ((eq calc-simplify-mode 'binary)
1576 (format "BinSimp%d " calc-word-size))
1577 ((eq calc-simplify-mode 'alg) "AlgSimp ")
1578 ((eq calc-simplify-mode 'ext) "ExtSimp ")
1579 ((eq calc-simplify-mode 'units) "UnitSimp ")
1580 (t ""))
1581
1582 ;; Display modes
1583 (cond ((= calc-number-radix 10) "")
1584 ((= calc-number-radix 2) "Bin ")
1585 ((= calc-number-radix 8) "Oct ")
1586 ((= calc-number-radix 16) "Hex ")
1587 (t (format "Radix%d " calc-number-radix)))
1588 (if calc-leading-zeros "Zero " "")
1589 (cond ((null calc-language) "")
1590 ((eq calc-language 'tex) "TeX ")
ad1c32c7 1591 ((eq calc-language 'latex) "LaTeX ")
136211a9
EZ
1592 (t (concat
1593 (capitalize (symbol-name calc-language))
1594 " ")))
1595 (cond ((eq fmt 'float)
1596 (if (zerop figs) "" (format "Norm%d " figs)))
1597 ((eq fmt 'fix) (format "Fix%d " figs))
1598 ((eq fmt 'sci)
1599 (if (zerop figs) "Sci " (format "Sci%d " figs)))
1600 ((eq fmt 'eng)
1601 (if (zerop figs) "Eng " (format "Eng%d " figs))))
1602 (cond ((not calc-display-just)
1603 (if calc-display-origin
1604 (format "Left%d " calc-display-origin) ""))
1605 ((eq calc-display-just 'right)
1606 (if calc-display-origin
1607 (format "Right%d " calc-display-origin)
1608 "Right "))
1609 (t
1610 (if calc-display-origin
1611 (format "Center%d " calc-display-origin)
1612 "Center ")))
1613 (cond ((integerp calc-line-breaking)
1614 (format "Wid%d " calc-line-breaking))
1615 (calc-line-breaking "")
1616 (t "Wide "))
1617
1618 ;; Miscellaneous other modes/indicators
1619 (if calc-assoc-selections "" "Break ")
1620 (cond ((eq calc-mode-save-mode 'save) "Save ")
1621 ((not calc-embedded-info) "")
1622 ((eq calc-mode-save-mode 'local) "Local ")
1623 ((eq calc-mode-save-mode 'edit) "LocEdit ")
1624 ((eq calc-mode-save-mode 'perm) "LocPerm ")
1625 ((eq calc-mode-save-mode 'global) "Global ")
1626 (t ""))
1627 (if calc-auto-recompute "" "Manual ")
1628 (if (and (fboundp 'calc-gnuplot-alive)
1629 (calc-gnuplot-alive)) "Graph " "")
1630 (if (and calc-embedded-info
1631 (> (calc-stack-size) 0)
1632 (calc-top 1 'sel)) "Sel " "")
1633 (if calc-display-dirty "Dirty " "")
1634 (if calc-inverse-flag "Inv " "")
1635 (if calc-hyperbolic-flag "Hyp " "")
1636 (if calc-keep-args-flag "Keep " "")
1637 (if (/= calc-stack-top 1) "Narrow " "")
1638 (apply 'concat calc-other-modes)))))
1639 (if (equal new-mode-string mode-line-buffer-identification)
1640 nil
1641 (setq mode-line-buffer-identification new-mode-string)
1642 (set-buffer-modified-p (buffer-modified-p))
bf77c646 1643 (and calc-embedded-info (calc-embedded-mode-line-change))))))
136211a9
EZ
1644
1645(defun calc-align-stack-window ()
1646 (if (eq major-mode 'calc-mode)
1647 (progn
1648 (let ((win (get-buffer-window (current-buffer))))
1649 (if win
1650 (progn
1651 (calc-cursor-stack-index 0)
1652 (vertical-motion (- 2 (window-height win)))
1653 (set-window-start win (point)))))
1654 (calc-cursor-stack-index 0)
1655 (if (looking-at " *\\.$")
1656 (goto-char (1- (match-end 0)))))
1657 (save-excursion
1658 (calc-select-buffer)
bf77c646 1659 (calc-align-stack-window))))
136211a9
EZ
1660
1661(defun calc-check-stack (n)
1662 (if (> n (calc-stack-size))
1663 (error "Too few elements on stack"))
1664 (if (< n 0)
bf77c646 1665 (error "Invalid argument")))
136211a9
EZ
1666
1667(defun calc-push-list (vals &optional m sels)
1668 (while vals
1669 (if calc-executing-macro
1670 (calc-push-list-in-macro vals m sels)
1671 (save-excursion
1672 (calc-select-buffer)
1673 (let* ((val (car vals))
1674 (entry (list val 1 (car sels)))
1675 (mm (+ (or m 1) calc-stack-top)))
1676 (calc-cursor-stack-index (1- (or m 1)))
1677 (if (> mm 1)
1678 (setcdr (nthcdr (- mm 2) calc-stack)
1679 (cons entry (nthcdr (1- mm) calc-stack)))
1680 (setq calc-stack (cons entry calc-stack)))
1681 (let ((buffer-read-only nil))
1682 (insert (math-format-stack-value entry) "\n"))
1683 (calc-record-undo (list 'push mm))
1684 (calc-set-command-flag 'renum-stack))))
1685 (setq vals (cdr vals)
bf77c646 1686 sels (cdr sels))))
136211a9
EZ
1687
1688(defun calc-pop-push-list (n vals &optional m sels)
1689 (if (and calc-any-selections (null sels))
1690 (calc-replace-selections n vals m)
1691 (calc-pop-stack n m sels)
bf77c646 1692 (calc-push-list vals m sels)))
136211a9
EZ
1693
1694(defun calc-pop-push-record-list (n prefix vals &optional m sels)
1695 (or (and (consp vals)
1696 (or (integerp (car vals))
1697 (consp (car vals))))
1698 (and vals (setq vals (list vals)
1699 sels (and sels (list sels)))))
1700 (calc-check-stack (+ n (or m 1) -1))
1701 (if prefix
1702 (if (cdr vals)
1703 (calc-record-list vals prefix)
1704 (calc-record (car vals) prefix)))
bf77c646 1705 (calc-pop-push-list n vals m sels))
136211a9
EZ
1706
1707(defun calc-enter-result (n prefix vals &optional m)
1708 (setq calc-aborted-prefix prefix)
1709 (if (and (consp vals)
1710 (or (integerp (car vals))
1711 (consp (car vals))))
1712 (setq vals (mapcar 'calc-normalize vals))
1713 (setq vals (calc-normalize vals)))
1714 (or (and (consp vals)
1715 (or (integerp (car vals))
1716 (consp (car vals))))
1717 (setq vals (list vals)))
1718 (if (equal vals '((nil)))
1719 (setq vals nil))
1720 (calc-pop-push-record-list n prefix vals m)
bf77c646 1721 (calc-handle-whys))
136211a9
EZ
1722
1723(defun calc-normalize (val)
1724 (if (memq calc-simplify-mode '(nil none num))
1725 (math-normalize val)
ce805efa 1726 (require 'calc-ext)
bf77c646 1727 (calc-normalize-fancy val)))
136211a9
EZ
1728
1729(defun calc-handle-whys ()
1730 (if calc-next-why
bf77c646 1731 (calc-do-handle-whys)))
136211a9
EZ
1732
1733
1734(defun calc-pop-stack (&optional n m sel-ok) ; pop N objs at level M of stack.
1735 (or n (setq n 1))
1736 (or m (setq m 1))
1737 (or calc-keep-args-flag
1738 (let ((mm (+ m calc-stack-top)))
1739 (if (and calc-any-selections (not sel-ok)
1740 (calc-top-selected n m))
1741 (calc-sel-error))
1742 (if calc-executing-macro
1743 (calc-pop-stack-in-macro n mm)
1744 (calc-record-undo (list 'pop mm (calc-top-list n m 'full)))
1745 (save-excursion
1746 (calc-select-buffer)
1747 (let ((buffer-read-only nil))
1748 (if (> mm 1)
1749 (progn
1750 (calc-cursor-stack-index (1- m))
1751 (let ((bot (point)))
1752 (calc-cursor-stack-index (+ n m -1))
1753 (delete-region (point) bot))
1754 (setcdr (nthcdr (- mm 2) calc-stack)
1755 (nthcdr (+ n mm -1) calc-stack)))
1756 (calc-cursor-stack-index n)
1757 (setq calc-stack (nthcdr n calc-stack))
1758 (delete-region (point) (point-max))))
bf77c646 1759 (calc-set-command-flag 'renum-stack))))))
136211a9 1760
730576f3 1761(defvar sel-mode)
136211a9
EZ
1762(defun calc-get-stack-element (x)
1763 (cond ((eq sel-mode 'entry)
1764 x)
1765 ((eq sel-mode 'sel)
1766 (nth 2 x))
1767 ((or (null (nth 2 x))
1768 (eq sel-mode 'full)
1769 (not calc-use-selections))
1770 (car x))
1771 (sel-mode
1772 (calc-sel-error))
bf77c646 1773 (t (nth 2 x))))
136211a9
EZ
1774
1775;; Get the Nth element of the stack (N=1 is the top element).
1776(defun calc-top (&optional n sel-mode)
1777 (or n (setq n 1))
1778 (calc-check-stack n)
bf77c646 1779 (calc-get-stack-element (nth (+ n calc-stack-top -1) calc-stack)))
136211a9
EZ
1780
1781(defun calc-top-n (&optional n sel-mode) ; in case precision has changed
bf77c646 1782 (math-check-complete (calc-normalize (calc-top n sel-mode))))
136211a9
EZ
1783
1784(defun calc-top-list (&optional n m sel-mode)
1785 (or n (setq n 1))
1786 (or m (setq m 1))
1787 (calc-check-stack (+ n m -1))
1788 (and (> n 0)
1789 (let ((top (copy-sequence (nthcdr (+ m calc-stack-top -1)
1790 calc-stack))))
1791 (setcdr (nthcdr (1- n) top) nil)
bf77c646 1792 (nreverse (mapcar 'calc-get-stack-element top)))))
136211a9
EZ
1793
1794(defun calc-top-list-n (&optional n m sel-mode)
1795 (mapcar 'math-check-complete
bf77c646 1796 (mapcar 'calc-normalize (calc-top-list n m sel-mode))))
136211a9
EZ
1797
1798
1799(defun calc-renumber-stack ()
1800 (if calc-line-numbering
1801 (save-excursion
1802 (calc-cursor-stack-index 0)
1803 (let ((lnum 1)
1804 (buffer-read-only nil)
1805 (stack (nthcdr calc-stack-top calc-stack)))
1806 (if (re-search-forward "^[0-9]+[:*]" nil t)
1807 (progn
1808 (beginning-of-line)
1809 (while (re-search-forward "^[0-9]+[:*]" nil t)
1810 (let ((buffer-read-only nil))
1811 (beginning-of-line)
1812 (delete-char 4)
1813 (insert " ")))
1814 (calc-cursor-stack-index 0)))
1815 (while (re-search-backward "^[0-9]+[:*]" nil t)
1816 (delete-char 4)
1817 (if (> lnum 999)
1818 (insert (format "%03d%s" (% lnum 1000)
1819 (if (and (nth 2 (car stack))
1820 calc-use-selections) "*" ":")))
1821 (let ((prefix (int-to-string lnum)))
1822 (insert prefix (if (and (nth 2 (car stack))
1823 calc-use-selections) "*" ":")
1824 (make-string (- 3 (length prefix)) 32))))
1825 (beginning-of-line)
1826 (setq lnum (1+ lnum)
1827 stack (cdr stack))))))
bf77c646 1828 (and calc-embedded-info (calc-embedded-stack-change)))
136211a9 1829
11bfbbd2 1830(defvar calc-any-evaltos nil)
136211a9
EZ
1831(defun calc-refresh (&optional align)
1832 (interactive)
1833 (and (eq major-mode 'calc-mode)
1834 (not calc-executing-macro)
1835 (let* ((buffer-read-only nil)
1836 (save-point (point))
1837 (save-mark (condition-case err (mark) (error nil)))
1838 (save-aligned (looking-at "\\.$"))
730576f3
CW
1839 (thing calc-stack)
1840 (calc-any-evaltos nil))
1841 (setq calc-any-selections nil)
136211a9 1842 (erase-buffer)
1501f4f6 1843 (when calc-show-banner
cd012309
CW
1844 (insert (propertize "--- Emacs Calculator Mode ---\n"
1845 'font-lock-face 'italic)))
136211a9
EZ
1846 (while thing
1847 (goto-char (point-min))
1501f4f6
MB
1848 (when calc-show-banner
1849 (forward-line 1))
136211a9
EZ
1850 (insert (math-format-stack-value (car thing)) "\n")
1851 (setq thing (cdr thing)))
1852 (calc-renumber-stack)
1853 (if calc-display-dirty
1854 (calc-wrapper (setq calc-display-dirty nil)))
1855 (and calc-any-evaltos calc-auto-recompute
1856 (calc-wrapper (calc-refresh-evaltos)))
1857 (if (or align save-aligned)
1858 (calc-align-stack-window)
1859 (goto-char save-point))
1860 (if save-mark (set-mark save-mark))))
1861 (and calc-embedded-info (not (eq major-mode 'calc-mode))
1862 (save-excursion
1863 (set-buffer (aref calc-embedded-info 1))
1864 (calc-refresh align)))
bf77c646 1865 (setq calc-refresh-count (1+ calc-refresh-count)))
136211a9 1866
136211a9
EZ
1867;;;; The Calc Trail buffer.
1868
1869(defun calc-check-trail-aligned ()
1870 (save-excursion
1871 (let ((win (get-buffer-window (current-buffer))))
1872 (and win
bf77c646 1873 (pos-visible-in-window-p (1- (point-max)) win)))))
136211a9
EZ
1874
1875(defun calc-trail-buffer ()
1876 (and (or (null calc-trail-buffer)
1877 (null (buffer-name calc-trail-buffer)))
1878 (save-excursion
1879 (setq calc-trail-buffer (get-buffer-create "*Calc Trail*"))
1880 (let ((buf (or (and (not (eq major-mode 'calc-mode))
1881 (get-buffer "*Calculator*"))
1882 (current-buffer))))
1883 (set-buffer calc-trail-buffer)
1884 (or (eq major-mode 'calc-trail-mode)
1885 (calc-trail-mode buf)))))
1886 (or (and calc-trail-pointer
1887 (eq (marker-buffer calc-trail-pointer) calc-trail-buffer))
1888 (save-excursion
1889 (set-buffer calc-trail-buffer)
1890 (goto-line 2)
1891 (setq calc-trail-pointer (point-marker))))
bf77c646 1892 calc-trail-buffer)
136211a9
EZ
1893
1894(defun calc-record (val &optional prefix)
1895 (setq calc-aborted-prefix nil)
1896 (or calc-executing-macro
1897 (let* ((mainbuf (current-buffer))
1898 (buf (calc-trail-buffer))
1899 (calc-display-raw nil)
1900 (calc-can-abbrev-vectors t)
1901 (fval (if val
1902 (if (stringp val)
1903 val
1904 (math-showing-full-precision
1905 (math-format-flat-expr val 0)))
1906 "")))
1907 (save-excursion
1908 (set-buffer buf)
1909 (let ((aligned (calc-check-trail-aligned))
1910 (buffer-read-only nil))
1911 (goto-char (point-max))
1912 (cond ((null prefix) (insert " "))
1913 ((and (> (length prefix) 4)
1914 (string-match " " prefix 4))
1915 (insert (substring prefix 0 4) " "))
1916 (t (insert (format "%4s " prefix))))
1917 (insert fval "\n")
1918 (let ((win (get-buffer-window buf)))
1919 (if (and aligned win (not (memq 'hold-trail calc-command-flags)))
1920 (calc-trail-here))
1921 (goto-char (1- (point-max))))))))
bf77c646 1922 val)
136211a9
EZ
1923
1924
577e1b74
JB
1925(defun calc-trail-display (flag &optional no-refresh interactive)
1926 (interactive "P\ni\np")
136211a9
EZ
1927 (let ((win (get-buffer-window (calc-trail-buffer))))
1928 (if (setq calc-display-trail
1929 (not (if flag (memq flag '(nil 0)) win)))
1930 (if (null win)
1931 (progn
ed65ed86
JB
1932 (if calc-trail-window-hook
1933 (run-hooks 'calc-trail-window-hook)
1934 (let ((w (split-window nil (/ (* (window-width) 2) 3) t)))
1935 (set-window-buffer w calc-trail-buffer)))
1936 (calc-wrapper
1937 (setq overlay-arrow-string calc-trail-overlay
1938 overlay-arrow-position calc-trail-pointer)
1939 (or no-refresh
1940 (if interactive
1941 (calc-do-refresh)
1942 (calc-refresh))))))
136211a9
EZ
1943 (if win
1944 (progn
1945 (delete-window win)
1946 (calc-wrapper
1947 (or no-refresh
577e1b74 1948 (if interactive
136211a9
EZ
1949 (calc-do-refresh)
1950 (calc-refresh))))))))
bf77c646 1951 calc-trail-buffer)
136211a9
EZ
1952
1953(defun calc-trail-here ()
1954 (interactive)
1955 (if (eq major-mode 'calc-trail-mode)
1956 (progn
1957 (beginning-of-line)
1958 (if (bobp)
1959 (forward-line 1)
1960 (if (eobp)
1961 (forward-line -1)))
1962 (if (or (bobp) (eobp))
1963 (setq overlay-arrow-position nil) ; trail is empty
1964 (set-marker calc-trail-pointer (point) (current-buffer))
1965 (setq calc-trail-overlay (concat (buffer-substring (point)
1966 (+ (point) 4))
1967 ">")
1968 overlay-arrow-string calc-trail-overlay
1969 overlay-arrow-position calc-trail-pointer)
1970 (forward-char 4)
1971 (let ((win (get-buffer-window (current-buffer))))
1972 (if win
1973 (save-excursion
1974 (forward-line (/ (window-height win) 2))
1975 (forward-line (- 1 (window-height win)))
1976 (set-window-start win (point))
1977 (set-window-point win (+ calc-trail-pointer 4))
1978 (set-buffer calc-main-buffer)
1979 (setq overlay-arrow-string calc-trail-overlay
1980 overlay-arrow-position calc-trail-pointer))))))
bf77c646 1981 (error "Not in Calc Trail buffer")))
136211a9
EZ
1982
1983
1984
1985
1986;;;; The Undo list.
1987
1988(defun calc-record-undo (rec)
1989 (or calc-executing-macro
1990 (if (memq 'undo calc-command-flags)
1991 (setq calc-undo-list (cons (cons rec (car calc-undo-list))
1992 (cdr calc-undo-list)))
1993 (setq calc-undo-list (cons (list rec) calc-undo-list)
1994 calc-redo-list nil)
bf77c646 1995 (calc-set-command-flag 'undo))))
136211a9
EZ
1996
1997
1998
1999
2000;;; Arithmetic commands.
2001
2002(defun calc-binary-op (name func arg &optional ident unary func2)
2003 (setq calc-aborted-prefix name)
2004 (if (null arg)
2005 (calc-enter-result 2 name (cons (or func2 func)
2006 (mapcar 'math-check-complete
2007 (calc-top-list 2))))
ce805efa 2008 (require 'calc-ext)
bf77c646 2009 (calc-binary-op-fancy name func arg ident unary)))
136211a9
EZ
2010
2011(defun calc-unary-op (name func arg &optional func2)
2012 (setq calc-aborted-prefix name)
2013 (if (null arg)
2014 (calc-enter-result 1 name (list (or func2 func)
2015 (math-check-complete (calc-top 1))))
ce805efa 2016 (require 'calc-ext)
bf77c646 2017 (calc-unary-op-fancy name func arg)))
136211a9
EZ
2018
2019
2020(defun calc-plus (arg)
2021 (interactive "P")
2022 (calc-slow-wrapper
bf77c646 2023 (calc-binary-op "+" 'calcFunc-add arg 0 nil '+)))
136211a9
EZ
2024
2025(defun calc-minus (arg)
2026 (interactive "P")
2027 (calc-slow-wrapper
bf77c646 2028 (calc-binary-op "-" 'calcFunc-sub arg 0 'neg '-)))
136211a9
EZ
2029
2030(defun calc-times (arg)
2031 (interactive "P")
2032 (calc-slow-wrapper
bf77c646 2033 (calc-binary-op "*" 'calcFunc-mul arg 1 nil '*)))
136211a9
EZ
2034
2035(defun calc-divide (arg)
2036 (interactive "P")
2037 (calc-slow-wrapper
bf77c646 2038 (calc-binary-op "/" 'calcFunc-div arg 0 'calcFunc-inv '/)))
136211a9 2039
431bbd67
JB
2040(defun calc-left-divide (arg)
2041 (interactive "P")
2042 (calc-slow-wrapper
2043 (calc-binary-op "ldiv" 'calcFunc-ldiv arg 0 nil nil)))
136211a9
EZ
2044
2045(defun calc-change-sign (arg)
2046 (interactive "P")
2047 (calc-wrapper
bf77c646 2048 (calc-unary-op "chs" 'neg arg)))
136211a9
EZ
2049
2050
2051
2052;;; Stack management commands.
2053
2054(defun calc-enter (n)
2055 (interactive "p")
2056 (calc-wrapper
2057 (cond ((< n 0)
2058 (calc-push-list (calc-top-list 1 (- n))))
2059 ((= n 0)
2060 (calc-push-list (calc-top-list (calc-stack-size))))
2061 (t
bf77c646 2062 (calc-push-list (calc-top-list n))))))
136211a9
EZ
2063
2064
2065(defun calc-pop (n)
2066 (interactive "P")
2067 (calc-wrapper
2068 (let* ((nn (prefix-numeric-value n))
2069 (top (and (null n) (calc-top 1))))
2070 (cond ((and (null n)
2071 (eq (car-safe top) 'incomplete)
2072 (> (length top) (if (eq (nth 1 top) 'intv) 3 2)))
2073 (calc-pop-push-list 1 (let ((tt (copy-sequence top)))
2074 (setcdr (nthcdr (- (length tt) 2) tt) nil)
2075 (list tt))))
2076 ((< nn 0)
2077 (if (and calc-any-selections
2078 (calc-top-selected 1 (- nn)))
2079 (calc-delete-selection (- nn))
2080 (calc-pop-stack 1 (- nn) t)))
2081 ((= nn 0)
2082 (calc-pop-stack (calc-stack-size) 1 t))
2083 (t
2084 (if (and calc-any-selections
2085 (= nn 1)
2086 (calc-top-selected 1 1))
2087 (calc-delete-selection 1)
bf77c646 2088 (calc-pop-stack nn)))))))
136211a9
EZ
2089
2090
2091
2092
2093;;;; Reading a number using the minibuffer.
730576f3
CW
2094(defvar calc-buffer)
2095(defvar calc-prev-char)
2096(defvar calc-prev-prev-char)
2097(defvar calc-digit-value)
136211a9
EZ
2098(defun calcDigit-start ()
2099 (interactive)
2100 (calc-wrapper
2101 (if (or calc-algebraic-mode
2102 (and (> calc-number-radix 14) (eq last-command-char ?e)))
2103 (calc-alg-digit-entry)
2104 (calc-unread-command)
2105 (setq calc-aborted-prefix nil)
2106 (let* ((calc-digit-value nil)
2107 (calc-prev-char nil)
2108 (calc-prev-prev-char nil)
2109 (calc-buffer (current-buffer))
6546555e 2110 (buf (if (featurep 'xemacs)
136211a9
EZ
2111 (catch 'calc-foo
2112 (catch 'execute-kbd-macro
2113 (throw 'calc-foo
2114 (read-from-minibuffer
2115 "Calc: " "" calc-digit-map)))
6546555e 2116 (error "XEmacs requires RET after %s"
136211a9
EZ
2117 "digit entry in kbd macro"))
2118 (let ((old-esc (lookup-key global-map "\e")))
2119 (unwind-protect
2120 (progn
2121 (define-key global-map "\e" nil)
2122 (read-from-minibuffer "Calc: " "" calc-digit-map))
2123 (define-key global-map "\e" old-esc))))))
2124 (or calc-digit-value (setq calc-digit-value (math-read-number buf)))
2125 (if (stringp calc-digit-value)
2126 (calc-alg-entry calc-digit-value)
2127 (if calc-digit-value
2128 (calc-push-list (list (calc-record (calc-normalize
2129 calc-digit-value))))))
2130 (if (eq calc-prev-char 'dots)
2131 (progn
ce805efa 2132 (require 'calc-ext)
bf77c646 2133 (calc-dots)))))))
136211a9 2134
91e51f9a
EZ
2135(defsubst calc-minibuffer-size ()
2136 (- (point-max) (minibuffer-prompt-end)))
2137
136211a9
EZ
2138(defun calcDigit-nondigit ()
2139 (interactive)
2140 ;; Exercise for the reader: Figure out why this is a good precaution!
2141 (or (boundp 'calc-buffer)
2142 (use-local-map minibuffer-local-map))
91e51f9a 2143 (let ((str (minibuffer-contents)))
136211a9
EZ
2144 (setq calc-digit-value (save-excursion
2145 (set-buffer calc-buffer)
2146 (math-read-number str))))
91e51f9a 2147 (if (and (null calc-digit-value) (> (calc-minibuffer-size) 0))
136211a9
EZ
2148 (progn
2149 (beep)
2150 (calc-temp-minibuffer-message " [Bad format]"))
2151 (or (memq last-command-char '(32 13))
2152 (progn (setq prefix-arg current-prefix-arg)
2153 (calc-unread-command (if (and (eq last-command-char 27)
2154 (>= last-input-char 128))
2155 last-input-char
2156 nil))))
bf77c646 2157 (exit-minibuffer)))
136211a9
EZ
2158
2159
2160(defun calc-minibuffer-contains (rex)
2161 (save-excursion
91e51f9a 2162 (goto-char (minibuffer-prompt-end))
bf77c646 2163 (looking-at rex)))
136211a9
EZ
2164
2165(defun calcDigit-key ()
2166 (interactive)
2167 (goto-char (point-max))
2168 (if (or (and (memq last-command-char '(?+ ?-))
2169 (> (buffer-size) 0)
2170 (/= (preceding-char) ?e))
2171 (and (memq last-command-char '(?m ?s))
2172 (not (calc-minibuffer-contains "[-+]?[0-9]+\\.?0*[@oh].*"))
2173 (not (calc-minibuffer-contains "[-+]?\\(1[1-9]\\|[2-9][0-9]\\)#.*"))))
2174 (calcDigit-nondigit)
2175 (if (calc-minibuffer-contains "\\([-+]?\\|.* \\)\\'")
2176 (cond ((memq last-command-char '(?. ?@)) (insert "0"))
2177 ((and (memq last-command-char '(?o ?h ?m))
2178 (not (calc-minibuffer-contains ".*#.*"))) (insert "0"))
2179 ((memq last-command-char '(?: ?e)) (insert "1"))
2180 ((eq last-command-char ?#)
2181 (insert (int-to-string calc-number-radix)))))
2182 (if (and (calc-minibuffer-contains "\\([-+]?[0-9]+#\\|[^:]*:\\)\\'")
2183 (eq last-command-char ?:))
2184 (insert "1"))
2185 (if (and (calc-minibuffer-contains "[-+]?[0-9]+#\\'")
2186 (eq last-command-char ?.))
2187 (insert "0"))
2188 (if (and (calc-minibuffer-contains "[-+]?0*\\([2-9]\\|1[0-4]\\)#\\'")
2189 (eq last-command-char ?e))
2190 (insert "1"))
2191 (if (or (and (memq last-command-char '(?h ?o ?m ?s ?p))
2192 (calc-minibuffer-contains ".*#.*"))
2193 (and (eq last-command-char ?e)
2194 (calc-minibuffer-contains "[-+]?\\(1[5-9]\\|[2-9][0-9]\\)#.*"))
2195 (and (eq last-command-char ?n)
2196 (calc-minibuffer-contains "[-+]?\\(2[4-9]\\|[3-9][0-9]\\)#.*")))
2197 (setq last-command-char (upcase last-command-char)))
2198 (cond
2199 ((memq last-command-char '(?_ ?n))
cd01f5b9 2200 (goto-char (minibuffer-prompt-end))
136211a9
EZ
2201 (if (and (search-forward " +/- " nil t)
2202 (not (search-forward "e" nil t)))
2203 (beep)
2204 (and (not (calc-minibuffer-contains "[-+]?\\(1[5-9]\\|[2-9][0-9]\\)#.*"))
2205 (search-forward "e" nil t))
2206 (if (looking-at "+")
2207 (delete-char 1))
2208 (if (looking-at "-")
2209 (delete-char 1)
2210 (insert "-")))
2211 (goto-char (point-max)))
2212 ((eq last-command-char ?p)
2213 (if (or (calc-minibuffer-contains ".*\\+/-.*")
2214 (calc-minibuffer-contains ".*mod.*")
2215 (calc-minibuffer-contains ".*#.*")
2216 (calc-minibuffer-contains ".*[-+e:]\\'"))
2217 (beep)
2218 (if (not (calc-minibuffer-contains ".* \\'"))
2219 (insert " "))
2220 (insert "+/- ")))
2221 ((and (eq last-command-char ?M)
2222 (not (calc-minibuffer-contains
2223 "[-+]?\\(2[3-9]\\|[3-9][0-9]\\)#.*")))
2224 (if (or (calc-minibuffer-contains ".*\\+/-.*")
2225 (calc-minibuffer-contains ".*mod *[^ ]+")
2226 (calc-minibuffer-contains ".*[-+e:]\\'"))
2227 (beep)
2228 (if (calc-minibuffer-contains ".*mod \\'")
2229 (if calc-previous-modulo
2230 (insert (math-format-flat-expr calc-previous-modulo 0))
2231 (beep))
2232 (if (not (calc-minibuffer-contains ".* \\'"))
2233 (insert " "))
2234 (insert "mod "))))
2235 (t
2236 (insert (char-to-string last-command-char))
2237 (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 2238 (let ((radix (string-to-number
136211a9
EZ
2239 (buffer-substring
2240 (match-beginning 2) (match-end 2)))))
2241 (and (>= radix 2)
2242 (<= radix 36)
2243 (or (memq last-command-char '(?# ?: ?. ?e ?+ ?-))
2244 (let ((dig (math-read-radix-digit
2245 (upcase last-command-char))))
2246 (and dig
2247 (< dig radix)))))))
91e51f9a
EZ
2248 (calc-minibuffer-contains
2249 "[-+]?\\(.*\\+/- *\\|.*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
2250 (if (and (memq last-command-char '(?@ ?o ?h ?\' ?m))
2251 (string-match " " calc-hms-format))
2252 (insert " "))
2253 (if (and (eq this-command last-command)
2254 (eq last-command-char ?.))
2255 (progn
ce805efa 2256 (require 'calc-ext)
136211a9
EZ
2257 (calc-digit-dots))
2258 (delete-backward-char 1)
2259 (beep)
2260 (calc-temp-minibuffer-message " [Bad format]"))))))
2261 (setq calc-prev-prev-char calc-prev-char
bf77c646 2262 calc-prev-char last-command-char))
136211a9
EZ
2263
2264
2265(defun calcDigit-backspace ()
2266 (interactive)
2267 (goto-char (point-max))
2268 (cond ((calc-minibuffer-contains ".* \\+/- \\'")
2269 (backward-delete-char 5))
2270 ((calc-minibuffer-contains ".* mod \\'")
2271 (backward-delete-char 5))
2272 ((calc-minibuffer-contains ".* \\'")
2273 (backward-delete-char 2))
2274 ((eq last-command 'calcDigit-start)
2275 (erase-buffer))
2276 (t (backward-delete-char 1)))
91e51f9a 2277 (if (= (calc-minibuffer-size) 0)
136211a9
EZ
2278 (progn
2279 (setq last-command-char 13)
bf77c646 2280 (calcDigit-nondigit))))
136211a9
EZ
2281
2282
2283
2284
2a78421d 2285(defconst math-bignum-digit-length
37cecd78 2286 (truncate (/ (log10 (/ most-positive-fixnum 2)) 2))
a6d107f1
JB
2287 "The length of a \"digit\" in Calc bignums.
2288If a big integer is of the form (bigpos N0 N1 ...), this is the
2289length of the allowable Emacs integers N0, N1,...
2290The value of 2*10^(2*MATH-BIGNUM-DIGIT-LENGTH) must be less than the
2291largest Emacs integer.")
136211a9 2292
2a78421d 2293(defconst math-bignum-digit-size
236e165a 2294 (expt 10 math-bignum-digit-length)
a6d107f1
JB
2295 "An upper bound for the size of the \"digit\"s in Calc bignums.")
2296
2a78421d 2297(defconst math-small-integer-size
236e165a 2298 (expt math-bignum-digit-size 2)
a6d107f1 2299 "An upper bound for the size of \"small integer\"s in Calc.")
136211a9
EZ
2300
2301
2302;;;; Arithmetic routines.
2303;;;
2304;;; An object as manipulated by one of these routines may take any of the
2305;;; following forms:
2306;;;
2307;;; integer An integer. For normalized numbers, this format
2a78421d 2308;;; is used only for
a6d107f1
JB
2309;;; negative math-small-integer-size + 1 to
2310;;; math-small-integer-size - 1
136211a9 2311;;;
2a78421d
JB
2312;;; (bigpos N0 N1 N2 ...) A big positive integer,
2313;;; N0 + N1*math-bignum-digit-size
a6d107f1 2314;;; + N2*(math-bignum-digit-size)^2 ...
2a78421d 2315;;; (bigneg N0 N1 N2 ...) A big negative integer,
a6d107f1 2316;;; - N0 - N1*math-bignum-digit-size ...
2a78421d 2317;;; Each digit N is in the range
a6d107f1 2318;;; 0 ... math-bignum-digit-size -1.
136211a9
EZ
2319;;; Normalized, always at least three N present,
2320;;; and the most significant N is nonzero.
2321;;;
2322;;; (frac NUM DEN) A fraction. NUM and DEN are small or big integers.
2323;;; Normalized, DEN > 1.
2324;;;
2325;;; (float NUM EXP) A floating-point number, NUM * 10^EXP;
2326;;; NUM is a small or big integer, EXP is a small int.
2327;;; Normalized, NUM is not a multiple of 10, and
2328;;; abs(NUM) < 10^calc-internal-prec.
2329;;; Normalized zero is stored as (float 0 0).
2330;;;
2331;;; (cplx REAL IMAG) A complex number; REAL and IMAG are any of above.
2332;;; Normalized, IMAG is nonzero.
2333;;;
2334;;; (polar R THETA) Polar complex number. Normalized, R > 0 and THETA
2335;;; is neither zero nor 180 degrees (pi radians).
2336;;;
2337;;; (vec A B C ...) Vector of objects A, B, C, ... A matrix is a
2338;;; vector of vectors.
2339;;;
2340;;; (hms H M S) Angle in hours-minutes-seconds form. All three
2341;;; components have the same sign; H and M must be
2342;;; numerically integers; M and S are expected to
2343;;; lie in the range [0,60).
2344;;;
2345;;; (date N) A date or date/time object. N is an integer to
2346;;; store a date only, or a fraction or float to
2347;;; store a date and time.
2348;;;
2349;;; (sdev X SIGMA) Error form, X +/- SIGMA. When normalized,
2350;;; SIGMA > 0. X is any complex number and SIGMA
2351;;; is real numbers; or these may be symbolic
2352;;; expressions where SIGMA is assumed real.
2353;;;
2354;;; (intv MASK LO HI) Interval form. MASK is 0=(), 1=(], 2=[), or 3=[].
2355;;; LO and HI are any real numbers, or symbolic
2356;;; expressions which are assumed real, and LO < HI.
2357;;; For [LO..HI], if LO = HI normalization produces LO,
2358;;; and if LO > HI normalization produces [LO..LO).
2359;;; For other intervals, if LO > HI normalization
2360;;; sets HI equal to LO.
2361;;;
2362;;; (mod N M) Number modulo M. When normalized, 0 <= N < M.
2363;;; N and M are real numbers.
2364;;;
2365;;; (var V S) Symbolic variable. V is a Lisp symbol which
2366;;; represents the variable's visible name. S is
2367;;; the symbol which actually stores the variable's
2368;;; value: (var pi var-pi).
2369;;;
2370;;; In general, combining rational numbers in a calculation always produces
2371;;; a rational result, but if either argument is a float, result is a float.
2372
2373;;; In the following comments, [x y z] means result is x, args must be y, z,
2374;;; respectively, where the code letters are:
2375;;;
2376;;; O Normalized object (vector or number)
2377;;; V Normalized vector
2378;;; N Normalized number of any type
2379;;; N Normalized complex number
2380;;; R Normalized real number (float or rational)
2381;;; F Normalized floating-point number
2382;;; T Normalized rational number
2383;;; I Normalized integer
2384;;; B Normalized big integer
2385;;; S Normalized small integer
2386;;; D Digit (small integer, 0..999)
2387;;; L Normalized bignum digit list (without "bigpos" or "bigneg" symbol)
2388;;; or normalized vector element list (without "vec")
2389;;; P Predicate (truth value)
2390;;; X Any Lisp object
2391;;; Z "nil"
2392;;;
2393;;; Lower-case letters signify possibly un-normalized values.
2394;;; "L.D" means a cons of an L and a D.
2395;;; [N N; n n] means result will be normalized if argument is.
2396;;; Also, [Public] marks routines intended to be called from outside.
2397;;; [This notation has been neglected in many recent routines.]
2398
730576f3
CW
2399(defvar math-eval-rules-cache)
2400(defvar math-eval-rules-cache-other)
136211a9 2401;;; Reduce an object to canonical (normalized) form. [O o; Z Z] [Public]
dc781413
JB
2402
2403(defvar math-normalize-a)
2404(defun math-normalize (math-normalize-a)
136211a9 2405 (cond
dc781413
JB
2406 ((not (consp math-normalize-a))
2407 (if (integerp math-normalize-a)
2a78421d 2408 (if (or (>= math-normalize-a math-small-integer-size)
a6d107f1 2409 (<= math-normalize-a (- math-small-integer-size)))
dc781413
JB
2410 (math-bignum math-normalize-a)
2411 math-normalize-a)
2412 math-normalize-a))
2413 ((eq (car math-normalize-a) 'bigpos)
2414 (if (eq (nth (1- (length math-normalize-a)) math-normalize-a) 0)
2a78421d 2415 (let* ((last (setq math-normalize-a
dc781413 2416 (copy-sequence math-normalize-a))) (digs math-normalize-a))
136211a9
EZ
2417 (while (setq digs (cdr digs))
2418 (or (eq (car digs) 0) (setq last digs)))
2419 (setcdr last nil)))
dc781413
JB
2420 (if (cdr (cdr (cdr math-normalize-a)))
2421 math-normalize-a
136211a9 2422 (cond
2a78421d
JB
2423 ((cdr (cdr math-normalize-a)) (+ (nth 1 math-normalize-a)
2424 (* (nth 2 math-normalize-a)
a6d107f1 2425 math-bignum-digit-size)))
dc781413 2426 ((cdr math-normalize-a) (nth 1 math-normalize-a))
136211a9 2427 (t 0))))
dc781413
JB
2428 ((eq (car math-normalize-a) 'bigneg)
2429 (if (eq (nth (1- (length math-normalize-a)) math-normalize-a) 0)
2a78421d 2430 (let* ((last (setq math-normalize-a (copy-sequence math-normalize-a)))
dc781413 2431 (digs math-normalize-a))
136211a9
EZ
2432 (while (setq digs (cdr digs))
2433 (or (eq (car digs) 0) (setq last digs)))
2434 (setcdr last nil)))
dc781413
JB
2435 (if (cdr (cdr (cdr math-normalize-a)))
2436 math-normalize-a
136211a9 2437 (cond
2a78421d
JB
2438 ((cdr (cdr math-normalize-a)) (- (+ (nth 1 math-normalize-a)
2439 (* (nth 2 math-normalize-a)
a6d107f1 2440 math-bignum-digit-size))))
dc781413 2441 ((cdr math-normalize-a) (- (nth 1 math-normalize-a)))
136211a9 2442 (t 0))))
dc781413 2443 ((eq (car math-normalize-a) 'float)
2a78421d 2444 (math-make-float (math-normalize (nth 1 math-normalize-a))
dc781413 2445 (nth 2 math-normalize-a)))
2a78421d 2446 ((or (memq (car math-normalize-a)
dc781413
JB
2447 '(frac cplx polar hms date mod sdev intv vec var quote
2448 special-const calcFunc-if calcFunc-lambda
2449 calcFunc-quote calcFunc-condition
2450 calcFunc-evalto))
2451 (integerp (car math-normalize-a))
2a78421d 2452 (and (consp (car math-normalize-a))
dc781413 2453 (not (eq (car (car math-normalize-a)) 'lambda))))
ce805efa 2454 (require 'calc-ext)
dc781413 2455 (math-normalize-fancy math-normalize-a))
136211a9
EZ
2456 (t
2457 (or (and calc-simplify-mode
ce805efa 2458 (require 'calc-ext)
136211a9 2459 (math-normalize-nonstandard))
dc781413 2460 (let ((args (mapcar 'math-normalize (cdr math-normalize-a))))
136211a9 2461 (or (condition-case err
2a78421d 2462 (let ((func
dc781413
JB
2463 (assq (car math-normalize-a) '( ( + . math-add )
2464 ( - . math-sub )
2465 ( * . math-mul )
2466 ( / . math-div )
2467 ( % . math-mod )
2468 ( ^ . math-pow )
2469 ( neg . math-neg )
2470 ( | . math-concat ) ))))
136211a9
EZ
2471 (or (and var-EvalRules
2472 (progn
2473 (or (eq var-EvalRules math-eval-rules-cache-tag)
2474 (progn
ce805efa 2475 (require 'calc-ext)
136211a9
EZ
2476 (math-recompile-eval-rules)))
2477 (and (or math-eval-rules-cache-other
2a78421d 2478 (assq (car math-normalize-a)
dc781413 2479 math-eval-rules-cache))
136211a9 2480 (math-apply-rewrites
dc781413 2481 (cons (car math-normalize-a) args)
136211a9
EZ
2482 (cdr math-eval-rules-cache)
2483 nil math-eval-rules-cache))))
2484 (if func
2485 (apply (cdr func) args)
dc781413
JB
2486 (and (or (consp (car math-normalize-a))
2487 (fboundp (car math-normalize-a))
ce805efa
JB
2488 (and (not (featurep 'calc-ext))
2489 (require 'calc-ext)
dc781413
JB
2490 (fboundp (car math-normalize-a))))
2491 (apply (car math-normalize-a) args)))))
136211a9
EZ
2492 (wrong-number-of-arguments
2493 (calc-record-why "*Wrong number of arguments"
dc781413 2494 (cons (car math-normalize-a) args))
136211a9
EZ
2495 nil)
2496 (wrong-type-argument
2a78421d 2497 (or calc-next-why
dc781413
JB
2498 (calc-record-why "Wrong type of argument"
2499 (cons (car math-normalize-a) args)))
136211a9
EZ
2500 nil)
2501 (args-out-of-range
2a78421d 2502 (calc-record-why "*Argument out of range"
dc781413 2503 (cons (car math-normalize-a) args))
136211a9
EZ
2504 nil)
2505 (inexact-result
2506 (calc-record-why "No exact representation for result"
dc781413 2507 (cons (car math-normalize-a) args))
136211a9
EZ
2508 nil)
2509 (math-overflow
2510 (calc-record-why "*Floating-point overflow occurred"
dc781413 2511 (cons (car math-normalize-a) args))
136211a9
EZ
2512 nil)
2513 (math-underflow
2514 (calc-record-why "*Floating-point underflow occurred"
dc781413 2515 (cons (car math-normalize-a) args))
136211a9
EZ
2516 nil)
2517 (void-variable
2518 (if (eq (nth 1 err) 'var-EvalRules)
2519 (progn
2520 (setq var-EvalRules nil)
dc781413 2521 (math-normalize (cons (car math-normalize-a) args)))
136211a9 2522 (calc-record-why "*Variable is void" (nth 1 err)))))
dc781413 2523 (if (consp (car math-normalize-a))
136211a9 2524 (math-dimension-error)
dc781413 2525 (cons (car math-normalize-a) args))))))))
136211a9
EZ
2526
2527
2528
2529;;; True if A is a floating-point real or complex number. [P x] [Public]
2530(defun math-floatp (a)
2531 (cond ((eq (car-safe a) 'float) t)
2532 ((memq (car-safe a) '(cplx polar mod sdev intv))
2533 (or (math-floatp (nth 1 a))
2534 (math-floatp (nth 2 a))
2535 (and (eq (car a) 'intv) (math-floatp (nth 3 a)))))
2536 ((eq (car-safe a) 'date)
bf77c646 2537 (math-floatp (nth 1 a)))))
136211a9
EZ
2538
2539
2540
2541;;; Verify that A is a complete object and return A. [x x] [Public]
2542(defun math-check-complete (a)
2543 (cond ((integerp a) a)
2544 ((eq (car-safe a) 'incomplete)
2545 (calc-incomplete-error a))
2546 ((consp a) a)
bf77c646 2547 (t (error "Invalid data object encountered"))))
136211a9
EZ
2548
2549
2550
2551;;; Coerce integer A to be a bignum. [B S]
2552(defun math-bignum (a)
2553 (if (>= a 0)
2554 (cons 'bigpos (math-bignum-big a))
bf77c646 2555 (cons 'bigneg (math-bignum-big (- a)))))
136211a9
EZ
2556
2557(defun math-bignum-big (a) ; [L s]
2558 (if (= a 0)
2559 nil
2a78421d 2560 (cons (% a math-bignum-digit-size)
a6d107f1 2561 (math-bignum-big (/ a math-bignum-digit-size)))))
136211a9
EZ
2562
2563
2564;;; Build a normalized floating-point number. [F I S]
2565(defun math-make-float (mant exp)
2566 (if (eq mant 0)
2567 '(float 0 0)
2568 (let* ((ldiff (- calc-internal-prec (math-numdigs mant))))
2569 (if (< ldiff 0)
2570 (setq mant (math-scale-rounding mant ldiff)
2571 exp (- exp ldiff))))
2572 (if (consp mant)
2573 (let ((digs (cdr mant)))
2574 (if (= (% (car digs) 10) 0)
2575 (progn
2576 (while (= (car digs) 0)
2577 (setq digs (cdr digs)
a6d107f1 2578 exp (+ exp math-bignum-digit-length)))
136211a9
EZ
2579 (while (= (% (car digs) 10) 0)
2580 (setq digs (math-div10-bignum digs)
2581 exp (1+ exp)))
2582 (setq mant (math-normalize (cons (car mant) digs))))))
2583 (while (= (% mant 10) 0)
2584 (setq mant (/ mant 10)
2585 exp (1+ exp))))
2586 (if (and (<= exp -4000000)
2587 (<= (+ exp (math-numdigs mant) -1) -4000000))
2588 (signal 'math-underflow nil)
2589 (if (and (>= exp 3000000)
2590 (>= (+ exp (math-numdigs mant) -1) 4000000))
2591 (signal 'math-overflow nil)
bf77c646 2592 (list 'float mant exp)))))
136211a9
EZ
2593
2594(defun math-div10-bignum (a) ; [l l]
2595 (if (cdr a)
2a78421d 2596 (cons (+ (/ (car a) 10) (* (% (nth 1 a) 10)
a6d107f1 2597 (expt 10 (1- math-bignum-digit-length))))
136211a9 2598 (math-div10-bignum (cdr a)))
bf77c646 2599 (list (/ (car a) 10))))
136211a9
EZ
2600
2601;;; Coerce A to be a float. [F N; V V] [Public]
2602(defun math-float (a)
2603 (cond ((Math-integerp a) (math-make-float a 0))
2604 ((eq (car a) 'frac) (math-div (math-float (nth 1 a)) (nth 2 a)))
2605 ((eq (car a) 'float) a)
2606 ((memq (car a) '(cplx polar vec hms date sdev mod))
2607 (cons (car a) (mapcar 'math-float (cdr a))))
bf77c646 2608 (t (math-float-fancy a))))
136211a9
EZ
2609
2610
2611(defun math-neg (a)
2612 (cond ((not (consp a)) (- a))
2613 ((eq (car a) 'bigpos) (cons 'bigneg (cdr a)))
2614 ((eq (car a) 'bigneg) (cons 'bigpos (cdr a)))
2615 ((memq (car a) '(frac float))
2616 (list (car a) (Math-integer-neg (nth 1 a)) (nth 2 a)))
2617 ((memq (car a) '(cplx vec hms date calcFunc-idn))
2618 (cons (car a) (mapcar 'math-neg (cdr a))))
bf77c646 2619 (t (math-neg-fancy a))))
136211a9
EZ
2620
2621
2622;;; Compute the number of decimal digits in integer A. [S I]
2623(defun math-numdigs (a)
2624 (if (consp a)
2625 (if (cdr a)
2626 (let* ((len (1- (length a)))
2627 (top (nth len a)))
a6d107f1 2628 (+ (* (1- len) math-bignum-digit-length) (math-numdigs top)))
136211a9
EZ
2629 0)
2630 (cond ((>= a 100) (+ (math-numdigs (/ a 1000)) 3))
2631 ((>= a 10) 2)
2632 ((>= a 1) 1)
2633 ((= a 0) 0)
2634 ((> a -10) 1)
2635 ((> a -100) 2)
bf77c646 2636 (t (math-numdigs (- a))))))
136211a9
EZ
2637
2638;;; Multiply (with truncation toward 0) the integer A by 10^N. [I i S]
2639(defun math-scale-int (a n)
2640 (cond ((= n 0) a)
2641 ((> n 0) (math-scale-left a n))
bf77c646 2642 (t (math-normalize (math-scale-right a (- n))))))
136211a9
EZ
2643
2644(defun math-scale-left (a n) ; [I I S]
2645 (if (= n 0)
2646 a
2647 (if (consp a)
2648 (cons (car a) (math-scale-left-bignum (cdr a) n))
a6d107f1 2649 (if (>= n math-bignum-digit-length)
2a78421d 2650 (if (or (>= a math-bignum-digit-size)
a6d107f1 2651 (<= a (- math-bignum-digit-size)))
136211a9 2652 (math-scale-left (math-bignum a) n)
2a78421d 2653 (math-scale-left (* a math-bignum-digit-size)
a6d107f1
JB
2654 (- n math-bignum-digit-length)))
2655 (let ((sz (expt 10 (- (* 2 math-bignum-digit-length) n))))
2656 (if (or (>= a sz) (<= a (- sz)))
2657 (math-scale-left (math-bignum a) n)
2658 (* a (expt 10 n))))))))
136211a9
EZ
2659
2660(defun math-scale-left-bignum (a n)
a6d107f1 2661 (if (>= n math-bignum-digit-length)
136211a9 2662 (while (>= (setq a (cons 0 a)
2a78421d 2663 n (- n math-bignum-digit-length))
a6d107f1 2664 math-bignum-digit-length)))
136211a9 2665 (if (> n 0)
a6d107f1 2666 (math-mul-bignum-digit a (expt 10 n) 0)
bf77c646 2667 a))
136211a9
EZ
2668
2669(defun math-scale-right (a n) ; [i i S]
2670 (if (= n 0)
2671 a
2672 (if (consp a)
2673 (cons (car a) (math-scale-right-bignum (cdr a) n))
2674 (if (<= a 0)
2675 (if (= a 0)
2676 0
2677 (- (math-scale-right (- a) n)))
a6d107f1
JB
2678 (if (>= n math-bignum-digit-length)
2679 (while (and (> (setq a (/ a math-bignum-digit-size)) 0)
2a78421d 2680 (>= (setq n (- n math-bignum-digit-length))
a6d107f1
JB
2681 math-bignum-digit-length))))
2682 (if (> n 0)
2683 (/ a (expt 10 n))
2684 a)))))
136211a9
EZ
2685
2686(defun math-scale-right-bignum (a n) ; [L L S; l l S]
a6d107f1
JB
2687 (if (>= n math-bignum-digit-length)
2688 (setq a (nthcdr (/ n math-bignum-digit-length) a)
2689 n (% n math-bignum-digit-length)))
136211a9 2690 (if (> n 0)
a6d107f1 2691 (cdr (math-mul-bignum-digit a (expt 10 (- math-bignum-digit-length n)) 0))
bf77c646 2692 a))
136211a9
EZ
2693
2694;;; Multiply (with rounding) the integer A by 10^N. [I i S]
2695(defun math-scale-rounding (a n)
2696 (cond ((>= n 0)
2697 (math-scale-left a n))
2698 ((consp a)
2699 (math-normalize
2700 (cons (car a)
a6d107f1 2701 (let ((val (if (< n (- math-bignum-digit-length))
2a78421d
JB
2702 (math-scale-right-bignum
2703 (cdr a)
a6d107f1
JB
2704 (- (- math-bignum-digit-length) n))
2705 (if (< n 0)
2a78421d
JB
2706 (math-mul-bignum-digit
2707 (cdr a)
a6d107f1
JB
2708 (expt 10 (+ math-bignum-digit-length n)) 0)
2709 (cdr a))))) ; n = -math-bignum-digit-length
2710 (if (and val (>= (car val) (/ math-bignum-digit-size 2)))
136211a9 2711 (if (cdr val)
a6d107f1 2712 (if (eq (car (cdr val)) (1- math-bignum-digit-size))
136211a9
EZ
2713 (math-add-bignum (cdr val) '(1))
2714 (cons (1+ (car (cdr val))) (cdr (cdr val))))
2715 '(1))
2716 (cdr val))))))
2717 (t
2718 (if (< a 0)
2719 (- (math-scale-rounding (- a) n))
2720 (if (= n -1)
2721 (/ (+ a 5) 10)
bf77c646 2722 (/ (+ (math-scale-right a (- -1 n)) 5) 10))))))
136211a9
EZ
2723
2724
2725;;; Compute the sum of A and B. [O O O] [Public]
2726(defun math-add (a b)
2727 (or
2728 (and (not (or (consp a) (consp b)))
2729 (progn
2730 (setq a (+ a b))
a6d107f1 2731 (if (or (<= a (- math-small-integer-size)) (>= a math-small-integer-size))
136211a9
EZ
2732 (math-bignum a)
2733 a)))
2734 (and (Math-zerop a) (not (eq (car-safe a) 'mod))
2735 (if (and (math-floatp a) (Math-ratp b)) (math-float b) b))
2736 (and (Math-zerop b) (not (eq (car-safe b) 'mod))
2737 (if (and (math-floatp b) (Math-ratp a)) (math-float a) a))
2738 (and (Math-objvecp a) (Math-objvecp b)
2739 (or
2740 (and (Math-integerp a) (Math-integerp b)
2741 (progn
2742 (or (consp a) (setq a (math-bignum a)))
2743 (or (consp b) (setq b (math-bignum b)))
2744 (if (eq (car a) 'bigneg)
2745 (if (eq (car b) 'bigneg)
2746 (cons 'bigneg (math-add-bignum (cdr a) (cdr b)))
2747 (math-normalize
2748 (let ((diff (math-sub-bignum (cdr b) (cdr a))))
2749 (if (eq diff 'neg)
2750 (cons 'bigneg (math-sub-bignum (cdr a) (cdr b)))
2751 (cons 'bigpos diff)))))
2752 (if (eq (car b) 'bigneg)
2753 (math-normalize
2754 (let ((diff (math-sub-bignum (cdr a) (cdr b))))
2755 (if (eq diff 'neg)
2756 (cons 'bigneg (math-sub-bignum (cdr b) (cdr a)))
2757 (cons 'bigpos diff))))
2758 (cons 'bigpos (math-add-bignum (cdr a) (cdr b)))))))
2759 (and (Math-ratp a) (Math-ratp b)
ce805efa 2760 (require 'calc-ext)
136211a9
EZ
2761 (calc-add-fractions a b))
2762 (and (Math-realp a) (Math-realp b)
2763 (progn
2764 (or (and (consp a) (eq (car a) 'float))
2765 (setq a (math-float a)))
2766 (or (and (consp b) (eq (car b) 'float))
2767 (setq b (math-float b)))
2768 (math-add-float a b)))
ce805efa 2769 (and (require 'calc-ext)
136211a9 2770 (math-add-objects-fancy a b))))
ce805efa 2771 (and (require 'calc-ext)
bf77c646 2772 (math-add-symb-fancy a b))))
136211a9
EZ
2773
2774(defun math-add-bignum (a b) ; [L L L; l l l]
2775 (if a
2776 (if b
2777 (let* ((a (copy-sequence a)) (aa a) (carry nil) sum)
2778 (while (and aa b)
2779 (if carry
2a78421d 2780 (if (< (setq sum (+ (car aa) (car b)))
a6d107f1 2781 (1- math-bignum-digit-size))
136211a9
EZ
2782 (progn
2783 (setcar aa (1+ sum))
2784 (setq carry nil))
9ae06d96 2785 (setcar aa (- sum (1- math-bignum-digit-size))))
a6d107f1 2786 (if (< (setq sum (+ (car aa) (car b))) math-bignum-digit-size)
136211a9 2787 (setcar aa sum)
a6d107f1 2788 (setcar aa (- sum math-bignum-digit-size))
136211a9
EZ
2789 (setq carry t)))
2790 (setq aa (cdr aa)
2791 b (cdr b)))
2792 (if carry
2793 (if b
2794 (nconc a (math-add-bignum b '(1)))
9ae06d96 2795 (while (eq (car aa) (1- math-bignum-digit-size))
136211a9
EZ
2796 (setcar aa 0)
2797 (setq aa (cdr aa)))
2798 (if aa
2799 (progn
2800 (setcar aa (1+ (car aa)))
2801 a)
2802 (nconc a '(1))))
2803 (if b
2804 (nconc a b)
2805 a)))
2806 a)
bf77c646 2807 b))
136211a9
EZ
2808
2809(defun math-sub-bignum (a b) ; [l l l]
2810 (if b
2811 (if a
730576f3 2812 (let* ((a (copy-sequence a)) (aa a) (borrow nil) sum diff)
136211a9
EZ
2813 (while (and aa b)
2814 (if borrow
2815 (if (>= (setq diff (- (car aa) (car b))) 1)
2816 (progn
2817 (setcar aa (1- diff))
2818 (setq borrow nil))
a6d107f1 2819 (setcar aa (+ diff (1- math-bignum-digit-size))))
136211a9
EZ
2820 (if (>= (setq diff (- (car aa) (car b))) 0)
2821 (setcar aa diff)
a6d107f1 2822 (setcar aa (+ diff math-bignum-digit-size))
136211a9
EZ
2823 (setq borrow t)))
2824 (setq aa (cdr aa)
2825 b (cdr b)))
2826 (if borrow
2827 (progn
2828 (while (eq (car aa) 0)
a6d107f1 2829 (setcar aa (1- math-bignum-digit-size))
136211a9
EZ
2830 (setq aa (cdr aa)))
2831 (if aa
2832 (progn
2833 (setcar aa (1- (car aa)))
2834 a)
2835 'neg))
2836 (while (eq (car b) 0)
2837 (setq b (cdr b)))
2838 (if b
2839 'neg
2840 a)))
2841 (while (eq (car b) 0)
2842 (setq b (cdr b)))
2843 (and b
2844 'neg))
bf77c646 2845 a))
136211a9
EZ
2846
2847(defun math-add-float (a b) ; [F F F]
2848 (let ((ediff (- (nth 2 a) (nth 2 b))))
2849 (if (>= ediff 0)
2850 (if (>= ediff (+ calc-internal-prec calc-internal-prec))
2851 a
2852 (math-make-float (math-add (nth 1 b)
2853 (if (eq ediff 0)
2854 (nth 1 a)
2855 (math-scale-left (nth 1 a) ediff)))
2856 (nth 2 b)))
2857 (if (>= (setq ediff (- ediff))
2858 (+ calc-internal-prec calc-internal-prec))
2859 b
2860 (math-make-float (math-add (nth 1 a)
2861 (math-scale-left (nth 1 b) ediff))
bf77c646 2862 (nth 2 a))))))
136211a9
EZ
2863
2864;;; Compute the difference of A and B. [O O O] [Public]
2865(defun math-sub (a b)
2866 (if (or (consp a) (consp b))
2867 (math-add a (math-neg b))
2868 (setq a (- a b))
a6d107f1 2869 (if (or (<= a (- math-small-integer-size)) (>= a math-small-integer-size))
136211a9 2870 (math-bignum a)
bf77c646 2871 a)))
136211a9
EZ
2872
2873(defun math-sub-float (a b) ; [F F F]
2874 (let ((ediff (- (nth 2 a) (nth 2 b))))
2875 (if (>= ediff 0)
2876 (if (>= ediff (+ calc-internal-prec calc-internal-prec))
2877 a
2878 (math-make-float (math-add (Math-integer-neg (nth 1 b))
2879 (if (eq ediff 0)
2880 (nth 1 a)
2881 (math-scale-left (nth 1 a) ediff)))
2882 (nth 2 b)))
2883 (if (>= (setq ediff (- ediff))
2884 (+ calc-internal-prec calc-internal-prec))
2885 b
2886 (math-make-float (math-add (nth 1 a)
2887 (Math-integer-neg
2888 (math-scale-left (nth 1 b) ediff)))
bf77c646 2889 (nth 2 a))))))
136211a9
EZ
2890
2891
2892;;; Compute the product of A and B. [O O O] [Public]
2893(defun math-mul (a b)
2894 (or
2895 (and (not (consp a)) (not (consp b))
2a78421d 2896 (< a math-bignum-digit-size) (> a (- math-bignum-digit-size))
a6d107f1 2897 (< b math-bignum-digit-size) (> b (- math-bignum-digit-size))
136211a9
EZ
2898 (* a b))
2899 (and (Math-zerop a) (not (eq (car-safe b) 'mod))
2900 (if (Math-scalarp b)
2901 (if (and (math-floatp b) (Math-ratp a)) (math-float a) a)
ce805efa 2902 (require 'calc-ext)
136211a9
EZ
2903 (math-mul-zero a b)))
2904 (and (Math-zerop b) (not (eq (car-safe a) 'mod))
2905 (if (Math-scalarp a)
2906 (if (and (math-floatp a) (Math-ratp b)) (math-float b) b)
ce805efa 2907 (require 'calc-ext)
136211a9
EZ
2908 (math-mul-zero b a)))
2909 (and (Math-objvecp a) (Math-objvecp b)
2910 (or
2911 (and (Math-integerp a) (Math-integerp b)
2912 (progn
2913 (or (consp a) (setq a (math-bignum a)))
2914 (or (consp b) (setq b (math-bignum b)))
2915 (math-normalize
2916 (cons (if (eq (car a) (car b)) 'bigpos 'bigneg)
2917 (if (cdr (cdr a))
2918 (if (cdr (cdr b))
2919 (math-mul-bignum (cdr a) (cdr b))
2920 (math-mul-bignum-digit (cdr a) (nth 1 b) 0))
2921 (math-mul-bignum-digit (cdr b) (nth 1 a) 0))))))
2922 (and (Math-ratp a) (Math-ratp b)
ce805efa 2923 (require 'calc-ext)
136211a9
EZ
2924 (calc-mul-fractions a b))
2925 (and (Math-realp a) (Math-realp b)
2926 (progn
2927 (or (and (consp a) (eq (car a) 'float))
2928 (setq a (math-float a)))
2929 (or (and (consp b) (eq (car b) 'float))
2930 (setq b (math-float b)))
2931 (math-make-float (math-mul (nth 1 a) (nth 1 b))
2932 (+ (nth 2 a) (nth 2 b)))))
ce805efa 2933 (and (require 'calc-ext)
136211a9 2934 (math-mul-objects-fancy a b))))
ce805efa 2935 (and (require 'calc-ext)
bf77c646 2936 (math-mul-symb-fancy a b))))
136211a9
EZ
2937
2938(defun math-infinitep (a &optional undir)
2939 (while (and (consp a) (memq (car a) '(* / neg)))
2940 (if (or (not (eq (car a) '*)) (math-infinitep (nth 1 a)))
2941 (setq a (nth 1 a))
2942 (setq a (nth 2 a))))
2943 (and (consp a)
2944 (eq (car a) 'var)
2945 (memq (nth 2 a) '(var-inf var-uinf var-nan))
2946 (if (and undir (eq (nth 2 a) 'var-inf))
2947 '(var uinf var-uinf)
bf77c646 2948 a)))
136211a9
EZ
2949
2950;;; Multiply digit lists A and B. [L L L; l l l]
2951(defun math-mul-bignum (a b)
2952 (and a b
2953 (let* ((sum (if (<= (car b) 1)
2954 (if (= (car b) 0)
2955 (list 0)
2956 (copy-sequence a))
2957 (math-mul-bignum-digit a (car b) 0)))
2958 (sump sum) c d aa ss prod)
2959 (while (setq b (cdr b))
2960 (setq ss (setq sump (or (cdr sump) (setcdr sump (list 0))))
2961 d (car b)
2962 c 0
2963 aa a)
2964 (while (progn
2965 (setcar ss (% (setq prod (+ (+ (car ss) (* (car aa) d))
a6d107f1 2966 c)) math-bignum-digit-size))
136211a9 2967 (setq aa (cdr aa)))
a6d107f1 2968 (setq c (/ prod math-bignum-digit-size)
136211a9 2969 ss (or (cdr ss) (setcdr ss (list 0)))))
a6d107f1 2970 (if (>= prod math-bignum-digit-size)
136211a9 2971 (if (cdr ss)
a6d107f1
JB
2972 (setcar (cdr ss) (+ (/ prod math-bignum-digit-size) (car (cdr ss))))
2973 (setcdr ss (list (/ prod math-bignum-digit-size))))))
bf77c646 2974 sum)))
136211a9
EZ
2975
2976;;; Multiply digit list A by digit D. [L L D D; l l D D]
2977(defun math-mul-bignum-digit (a d c)
2978 (if a
2979 (if (<= d 1)
2980 (and (= d 1) a)
2981 (let* ((a (copy-sequence a)) (aa a) prod)
2982 (while (progn
2a78421d
JB
2983 (setcar aa
2984 (% (setq prod (+ (* (car aa) d) c))
a6d107f1 2985 math-bignum-digit-size))
136211a9
EZ
2986 (cdr aa))
2987 (setq aa (cdr aa)
a6d107f1
JB
2988 c (/ prod math-bignum-digit-size)))
2989 (if (>= prod math-bignum-digit-size)
2990 (setcdr aa (list (/ prod math-bignum-digit-size))))
136211a9
EZ
2991 a))
2992 (and (> c 0)
bf77c646 2993 (list c))))
136211a9
EZ
2994
2995
2996;;; Compute the integer (quotient . remainder) of A and B, which may be
2997;;; small or big integers. Type and consistency of truncation is undefined
2998;;; if A or B is negative. B must be nonzero. [I.I I I] [Public]
2999(defun math-idivmod (a b)
3000 (if (eq b 0)
3001 (math-reject-arg a "*Division by zero"))
3002 (if (or (consp a) (consp b))
a6d107f1 3003 (if (and (natnump b) (< b math-bignum-digit-size))
136211a9
EZ
3004 (let ((res (math-div-bignum-digit (cdr a) b)))
3005 (cons
3006 (math-normalize (cons (car a) (car res)))
3007 (cdr res)))
3008 (or (consp a) (setq a (math-bignum a)))
3009 (or (consp b) (setq b (math-bignum b)))
3010 (let ((res (math-div-bignum (cdr a) (cdr b))))
3011 (cons
3012 (math-normalize (cons (if (eq (car a) (car b)) 'bigpos 'bigneg)
3013 (car res)))
3014 (math-normalize (cons (car a) (cdr res))))))
bf77c646 3015 (cons (/ a b) (% a b))))
136211a9
EZ
3016
3017(defun math-quotient (a b) ; [I I I] [Public]
3018 (if (and (not (consp a)) (not (consp b)))
3019 (if (= b 0)
3020 (math-reject-arg a "*Division by zero")
3021 (/ a b))
a6d107f1 3022 (if (and (natnump b) (< b math-bignum-digit-size))
136211a9
EZ
3023 (if (= b 0)
3024 (math-reject-arg a "*Division by zero")
3025 (math-normalize (cons (car a)
3026 (car (math-div-bignum-digit (cdr a) b)))))
3027 (or (consp a) (setq a (math-bignum a)))
3028 (or (consp b) (setq b (math-bignum b)))
3029 (let* ((alen (1- (length a)))
3030 (blen (1- (length b)))
a6d107f1 3031 (d (/ math-bignum-digit-size (1+ (nth (1- blen) (cdr b)))))
136211a9
EZ
3032 (res (math-div-bignum-big (math-mul-bignum-digit (cdr a) d 0)
3033 (math-mul-bignum-digit (cdr b) d 0)
3034 alen blen)))
3035 (math-normalize (cons (if (eq (car a) (car b)) 'bigpos 'bigneg)
bf77c646 3036 (car res)))))))
136211a9
EZ
3037
3038
3039;;; Divide a bignum digit list by another. [l.l l L]
3040;;; The following division algorithm is borrowed from Knuth vol. II, sec. 4.3.1
3041(defun math-div-bignum (a b)
3042 (if (cdr b)
3043 (let* ((alen (length a))
3044 (blen (length b))
a6d107f1 3045 (d (/ math-bignum-digit-size (1+ (nth (1- blen) b))))
136211a9
EZ
3046 (res (math-div-bignum-big (math-mul-bignum-digit a d 0)
3047 (math-mul-bignum-digit b d 0)
3048 alen blen)))
3049 (if (= d 1)
3050 res
3051 (cons (car res)
3052 (car (math-div-bignum-digit (cdr res) d)))))
3053 (let ((res (math-div-bignum-digit a (car b))))
bf77c646 3054 (cons (car res) (list (cdr res))))))
136211a9
EZ
3055
3056;;; Divide a bignum digit list by a digit. [l.D l D]
3057(defun math-div-bignum-digit (a b)
3058 (if a
3059 (let* ((res (math-div-bignum-digit (cdr a) b))
a6d107f1 3060 (num (+ (* (cdr res) math-bignum-digit-size) (car a))))
136211a9
EZ
3061 (cons
3062 (cons (/ num b) (car res))
3063 (% num b)))
bf77c646 3064 '(nil . 0)))
136211a9
EZ
3065
3066(defun math-div-bignum-big (a b alen blen) ; [l.l l L]
3067 (if (< alen blen)
3068 (cons nil a)
3069 (let* ((res (math-div-bignum-big (cdr a) b (1- alen) blen))
3070 (num (cons (car a) (cdr res)))
3071 (res2 (math-div-bignum-part num b blen)))
3072 (cons
3073 (cons (car res2) (car res))
bf77c646 3074 (cdr res2)))))
136211a9 3075
a6d107f1 3076(defun math-div-bignum-part (a b blen) ; a < b*math-bignum-digit-size [D.l l L]
2a78421d 3077 (let* ((num (+ (* (or (nth blen a) 0) math-bignum-digit-size)
a6d107f1 3078 (or (nth (1- blen) a) 0)))
136211a9 3079 (den (nth (1- blen) b))
a6d107f1 3080 (guess (min (/ num den) (1- math-bignum-digit-size))))
bf77c646 3081 (math-div-bignum-try a b (math-mul-bignum-digit b guess 0) guess)))
136211a9
EZ
3082
3083(defun math-div-bignum-try (a b c guess) ; [D.l l l D]
3084 (let ((rem (math-sub-bignum a c)))
3085 (if (eq rem 'neg)
3086 (math-div-bignum-try a b (math-sub-bignum c b) (1- guess))
bf77c646 3087 (cons guess rem))))
136211a9
EZ
3088
3089
3090;;; Compute the quotient of A and B. [O O N] [Public]
3091(defun math-div (a b)
3092 (or
3093 (and (Math-zerop b)
ce805efa 3094 (require 'calc-ext)
136211a9
EZ
3095 (math-div-by-zero a b))
3096 (and (Math-zerop a) (not (eq (car-safe b) 'mod))
3097 (if (Math-scalarp b)
3098 (if (and (math-floatp b) (Math-ratp a)) (math-float a) a)
ce805efa 3099 (require 'calc-ext)
136211a9
EZ
3100 (math-div-zero a b)))
3101 (and (Math-objvecp a) (Math-objvecp b)
3102 (or
3103 (and (Math-integerp a) (Math-integerp b)
3104 (let ((q (math-idivmod a b)))
3105 (if (eq (cdr q) 0)
3106 (car q)
3107 (if calc-prefer-frac
3108 (progn
ce805efa 3109 (require 'calc-ext)
136211a9
EZ
3110 (math-make-frac a b))
3111 (math-div-float (math-make-float a 0)
3112 (math-make-float b 0))))))
3113 (and (Math-ratp a) (Math-ratp b)
ce805efa 3114 (require 'calc-ext)
136211a9
EZ
3115 (calc-div-fractions a b))
3116 (and (Math-realp a) (Math-realp b)
3117 (progn
3118 (or (and (consp a) (eq (car a) 'float))
3119 (setq a (math-float a)))
3120 (or (and (consp b) (eq (car b) 'float))
3121 (setq b (math-float b)))
3122 (math-div-float a b)))
ce805efa 3123 (and (require 'calc-ext)
136211a9 3124 (math-div-objects-fancy a b))))
ce805efa 3125 (and (require 'calc-ext)
bf77c646 3126 (math-div-symb-fancy a b))))
136211a9
EZ
3127
3128(defun math-div-float (a b) ; [F F F]
3129 (let ((ldiff (max (- (1+ calc-internal-prec)
3130 (- (math-numdigs (nth 1 a)) (math-numdigs (nth 1 b))))
3131 0)))
3132 (math-make-float (math-quotient (math-scale-int (nth 1 a) ldiff) (nth 1 b))
bf77c646 3133 (- (- (nth 2 a) (nth 2 b)) ldiff))))
136211a9
EZ
3134
3135
3136
3137
730576f3 3138(defvar calc-selection-cache-entry)
136211a9
EZ
3139;;; Format the number A as a string. [X N; X Z] [Public]
3140(defun math-format-stack-value (entry)
3141 (setq calc-selection-cache-entry calc-selection-cache-default-entry)
3142 (let* ((a (car entry))
3143 (math-comp-selected (nth 2 entry))
3144 (c (cond ((null a) "<nil>")
3145 ((eq calc-display-raw t) (format "%s" a))
3146 ((stringp a) a)
cd012309 3147 ((eq a 'top-of-stack) (propertize "." 'font-lock-face 'bold))
136211a9
EZ
3148 (calc-prepared-composition
3149 calc-prepared-composition)
3150 ((and (Math-scalarp a)
3151 (memq calc-language '(nil flat unform))
3152 (null math-comp-selected))
3153 (math-format-number a))
ce805efa 3154 (t (require 'calc-ext)
136211a9
EZ
3155 (math-compose-expr a 0))))
3156 (off (math-stack-value-offset c))
3157 s w)
3158 (and math-comp-selected (setq calc-any-selections t))
3159 (setq w (cdr off)
3160 off (car off))
cd012309 3161 (when (> off 0)
111a5355 3162 (setq c (math-comp-concat (make-string off ?\s) c)))
136211a9
EZ
3163 (or (equal calc-left-label "")
3164 (setq c (math-comp-concat (if (eq a 'top-of-stack)
111a5355 3165 (make-string (length calc-left-label) ?\s)
136211a9
EZ
3166 calc-left-label)
3167 c)))
cd012309
CW
3168 (when calc-line-numbering
3169 (setq c (math-comp-concat (if (eq calc-language 'big)
2363bd8d
DK
3170 (if math-comp-selected
3171 '(tag t "1: ")
3172 "1: ")
cd012309
CW
3173 " ")
3174 c)))
3175 (unless (or (equal calc-right-label "")
3176 (eq a 'top-of-stack))
ce805efa 3177 (require 'calc-ext)
cd012309
CW
3178 (setq c (list 'horiz c
3179 (make-string (max (- w (math-comp-width c)
111a5355 3180 (length calc-right-label)) 0) ?\s)
cd012309
CW
3181 '(break -1)
3182 calc-right-label)))
136211a9
EZ
3183 (setq s (if (stringp c)
3184 (if calc-display-raw
3185 (prin1-to-string c)
3186 c)
3187 (math-composition-to-string c w)))
cd012309
CW
3188 (when calc-language-output-filter
3189 (setq s (funcall calc-language-output-filter s)))
136211a9
EZ
3190 (if (eq calc-language 'big)
3191 (setq s (concat s "\n"))
cd012309 3192 (when calc-line-numbering
6a3ed064 3193 (setq s (concat "1:" (substring s 2)))))
136211a9 3194 (setcar (cdr entry) (calc-count-lines s))
bf77c646 3195 s))
136211a9 3196
f0a35df4
JB
3197;; The variables math-svo-c, math-svo-wid and math-svo-off are local
3198;; to math-stack-value-offset, but are used by math-stack-value-offset-fancy
3199;; in calccomp.el.
3200
3201(defun math-stack-value-offset (math-svo-c)
136211a9 3202 (let* ((num (if calc-line-numbering 4 0))
f0a35df4
JB
3203 (math-svo-wid (calc-window-width))
3204 math-svo-off)
136211a9
EZ
3205 (if calc-display-just
3206 (progn
ce805efa 3207 (require 'calc-ext)
136211a9 3208 (math-stack-value-offset-fancy))
f0a35df4 3209 (setq math-svo-off (or calc-display-origin 0))
cd012309 3210 (when (integerp calc-line-breaking)
f0a35df4
JB
3211 (setq math-svo-wid calc-line-breaking)))
3212 (cons (max (- math-svo-off (length calc-left-label)) 0)
3213 (+ math-svo-wid num))))
136211a9
EZ
3214
3215(defun calc-count-lines (s)
3216 (let ((pos 0)
3217 (num 1))
730576f3
CW
3218 (while (setq pos (string-match "\n" s pos))
3219 (setq pos (1+ pos)
136211a9 3220 num (1+ num)))
bf77c646 3221 num))
136211a9
EZ
3222
3223(defun math-format-value (a &optional w)
3224 (if (and (Math-scalarp a)
3225 (memq calc-language '(nil flat unform)))
3226 (math-format-number a)
ce805efa 3227 (require 'calc-ext)
136211a9 3228 (let ((calc-line-breaking nil))
bf77c646 3229 (math-composition-to-string (math-compose-expr a 0) w))))
136211a9
EZ
3230
3231(defun calc-window-width ()
3232 (if calc-embedded-info
3233 (let ((win (get-buffer-window (aref calc-embedded-info 0))))
31b85a14 3234 (1- (if win (window-width win) (frame-width))))
136211a9 3235 (- (window-width (get-buffer-window (current-buffer)))
bf77c646 3236 (if calc-line-numbering 5 1))))
136211a9
EZ
3237
3238(defun math-comp-concat (c1 c2)
3239 (if (and (stringp c1) (stringp c2))
3240 (concat c1 c2)
bf77c646 3241 (list 'horiz c1 c2)))
136211a9
EZ
3242
3243
3244
3245;;; Format an expression as a one-line string suitable for re-reading.
3246
3247(defun math-format-flat-expr (a prec)
3248 (cond
3249 ((or (not (or (consp a) (integerp a)))
3250 (eq calc-display-raw t))
3251 (let ((print-escape-newlines t))
3252 (concat "'" (prin1-to-string a))))
3253 ((Math-scalarp a)
3254 (let ((calc-group-digits nil)
3255 (calc-point-char ".")
3256 (calc-frac-format (if (> (length (car calc-frac-format)) 1)
3257 '("::" nil) '(":" nil)))
3258 (calc-complex-format nil)
3259 (calc-hms-format "%s@ %s' %s\"")
3260 (calc-language nil))
3261 (math-format-number a)))
3262 (t
ce805efa 3263 (require 'calc-ext)
bf77c646 3264 (math-format-flat-expr-fancy a prec))))
136211a9
EZ
3265
3266
3267
3268;;; Format a number as a string.
3269(defun math-format-number (a &optional prec) ; [X N] [Public]
3270 (cond
3271 ((eq calc-display-raw t) (format "%s" a))
3272 ((and (nth 1 calc-frac-format) (Math-integerp a))
ce805efa 3273 (require 'calc-ext)
136211a9
EZ
3274 (math-format-number (math-adjust-fraction a)))
3275 ((integerp a)
3276 (if (not (or calc-group-digits calc-leading-zeros))
3277 (if (= calc-number-radix 10)
3278 (int-to-string a)
3279 (if (< a 0)
3280 (concat "-" (math-format-number (- a)))
ce805efa 3281 (require 'calc-ext)
136211a9
EZ
3282 (if math-radix-explicit-format
3283 (if calc-radix-formatter
3284 (funcall calc-radix-formatter
3285 calc-number-radix
3286 (if (= calc-number-radix 2)
3287 (math-format-binary a)
3288 (math-format-radix a)))
3289 (format "%d#%s" calc-number-radix
3290 (if (= calc-number-radix 2)
3291 (math-format-binary a)
3292 (math-format-radix a))))
3293 (math-format-radix a))))
3294 (math-format-number (math-bignum a))))
3295 ((stringp a) a)
3296 ((not (consp a)) (prin1-to-string a))
3297 ((eq (car a) 'bigpos) (math-format-bignum (cdr a)))
3298 ((eq (car a) 'bigneg) (concat "-" (math-format-bignum (cdr a))))
3299 ((and (eq (car a) 'float) (= calc-number-radix 10))
3300 (if (Math-integer-negp (nth 1 a))
3301 (concat "-" (math-format-number (math-neg a)))
3302 (let ((mant (nth 1 a))
3303 (exp (nth 2 a))
3304 (fmt (car calc-float-format))
3305 (figs (nth 1 calc-float-format))
3306 (point calc-point-char)
3307 str)
3308 (if (and (eq fmt 'fix)
3309 (or (and (< figs 0) (setq figs (- figs)))
3310 (> (+ exp (math-numdigs mant)) (- figs))))
3311 (progn
3312 (setq mant (math-scale-rounding mant (+ exp figs))
3313 str (if (integerp mant)
3314 (int-to-string mant)
3315 (math-format-bignum-decimal (cdr mant))))
3316 (if (<= (length str) figs)
3317 (setq str (concat (make-string (1+ (- figs (length str))) ?0)
3318 str)))
3319 (if (> figs 0)
3320 (setq str (concat (substring str 0 (- figs)) point
3321 (substring str (- figs))))
3322 (setq str (concat str point)))
91da6442
CW
3323 (when calc-group-digits
3324 (require 'calc-ext)
3325 (setq str (math-group-float str))))
cd012309
CW
3326 (when (< figs 0)
3327 (setq figs (+ calc-internal-prec figs)))
3328 (when (> figs 0)
3329 (let ((adj (- figs (math-numdigs mant))))
3330 (when (< adj 0)
3331 (setq mant (math-scale-rounding mant adj)
3332 exp (- exp adj)))))
136211a9
EZ
3333 (setq str (if (integerp mant)
3334 (int-to-string mant)
3335 (math-format-bignum-decimal (cdr mant))))
3336 (let* ((len (length str))
3337 (dpos (+ exp len)))
3338 (if (and (eq fmt 'float)
3339 (<= dpos (+ calc-internal-prec calc-display-sci-high))
3340 (>= dpos (+ calc-display-sci-low 2)))
3341 (progn
3342 (cond
3343 ((= dpos 0)
3344 (setq str (concat "0" point str)))
3345 ((and (<= exp 0) (> dpos 0))
3346 (setq str (concat (substring str 0 dpos) point
3347 (substring str dpos))))
3348 ((> exp 0)
3349 (setq str (concat str (make-string exp ?0) point)))
3350 (t ; (< dpos 0)
3351 (setq str (concat "0" point
3352 (make-string (- dpos) ?0) str))))
91da6442
CW
3353 (when calc-group-digits
3354 (require 'calc-ext)
3355 (setq str (math-group-float str))))
136211a9
EZ
3356 (let* ((eadj (+ exp len))
3357 (scale (if (eq fmt 'eng)
3358 (1+ (math-mod (+ eadj 300002) 3))
3359 1)))
3360 (if (> scale (length str))
3361 (setq str (concat str (make-string (- scale (length str))
3362 ?0))))
3363 (if (< scale (length str))
3364 (setq str (concat (substring str 0 scale) point
3365 (substring str scale))))
91da6442
CW
3366 (when calc-group-digits
3367 (require 'calc-ext)
3368 (setq str (math-group-float str)))
136211a9
EZ
3369 (setq str (format (if (memq calc-language '(math maple))
3370 (if (and prec (> prec 191))
3371 "(%s*10.^%d)" "%s*10.^%d")
3372 "%se%d")
3373 str (- eadj scale)))))))
3374 str)))
3375 (t
ce805efa 3376 (require 'calc-ext)
bf77c646 3377 (math-format-number-fancy a prec))))
136211a9
EZ
3378
3379(defun math-format-bignum (a) ; [X L]
3380 (if (and (= calc-number-radix 10)
3381 (not calc-leading-zeros)
3382 (not calc-group-digits))
3383 (math-format-bignum-decimal a)
ce805efa 3384 (require 'calc-ext)
bf77c646 3385 (math-format-bignum-fancy a)))
136211a9
EZ
3386
3387(defun math-format-bignum-decimal (a) ; [X L]
3388 (if a
3389 (let ((s ""))
3390 (while (cdr (cdr a))
2a78421d
JB
3391 (setq s (concat
3392 (format
3393 (concat "%0"
3394 (number-to-string (* 2 math-bignum-digit-length))
a6d107f1
JB
3395 "d")
3396 (+ (* (nth 1 a) math-bignum-digit-size) (car a))) s)
136211a9 3397 a (cdr (cdr a))))
2a78421d 3398 (concat (int-to-string
a6d107f1 3399 (+ (* (or (nth 1 a) 0) math-bignum-digit-size) (car a))) s))
bf77c646 3400 "0"))
136211a9
EZ
3401
3402
3403
3404;;; Parse a simple number in string form. [N X] [Public]
3405(defun math-read-number (s)
e90988a0 3406 "Convert the string S into a Calc number."
136211a9
EZ
3407 (math-normalize
3408 (cond
3409
3410 ;; Integers (most common case)
3411 ((string-match "\\` *\\([0-9]+\\) *\\'" s)
3412 (let ((digs (math-match-substring s 1)))
3413 (if (and (eq calc-language 'c)
3414 (> (length digs) 1)
3415 (eq (aref digs 0) ?0))
3416 (math-read-number (concat "8#" digs))
e90988a0 3417 (if (<= (length digs) (* 2 math-bignum-digit-length))
28572d7d 3418 (string-to-number digs)
136211a9
EZ
3419 (cons 'bigpos (math-read-bignum digs))))))
3420
3421 ;; Clean up the string if necessary
3422 ((string-match "\\`\\(.*\\)[ \t\n]+\\([^\001]*\\)\\'" s)
3423 (math-read-number (concat (math-match-substring s 1)
3424 (math-match-substring s 2))))
3425
3426 ;; Plus and minus signs
3427 ((string-match "^[-_+]\\(.*\\)$" s)
3428 (let ((val (math-read-number (math-match-substring s 1))))
3429 (and val (if (eq (aref s 0) ?+) val (math-neg val)))))
3430
3431 ;; Forms that require extensions module
3432 ((string-match "[^-+0-9eE.]" s)
ce805efa 3433 (require 'calc-ext)
136211a9
EZ
3434 (math-read-number-fancy s))
3435
3436 ;; Decimal point
3437 ((string-match "^\\([0-9]*\\)\\.\\([0-9]*\\)$" s)
3438 (let ((int (math-match-substring s 1))
3439 (frac (math-match-substring s 2)))
3440 (let ((ilen (length int))
3441 (flen (length frac)))
3442 (let ((int (if (> ilen 0) (math-read-number int) 0))
3443 (frac (if (> flen 0) (math-read-number frac) 0)))
3444 (and int frac (or (> ilen 0) (> flen 0))
3445 (list 'float
3446 (math-add (math-scale-int int flen) frac)
3447 (- flen)))))))
3448
3449 ;; "e" notation
3450 ((string-match "^\\(.*\\)[eE]\\([-+]?[0-9]+\\)$" s)
3451 (let ((mant (math-match-substring s 1))
3452 (exp (math-match-substring s 2)))
3453 (let ((mant (if (> (length mant) 0) (math-read-number mant) 1))
3454 (exp (if (<= (length exp) (if (memq (aref exp 0) '(?+ ?-)) 8 7))
28572d7d 3455 (string-to-number exp))))
136211a9
EZ
3456 (and mant exp (Math-realp mant) (> exp -4000000) (< exp 4000000)
3457 (let ((mant (math-float mant)))
3458 (list 'float (nth 1 mant) (+ (nth 2 mant) exp)))))))
3459
3460 ;; Syntax error!
bf77c646 3461 (t nil))))
136211a9 3462
1f26c380
JB
3463;;; Parse a very simple number, keeping all digits.
3464(defun math-read-number-simple (s)
e90988a0
JB
3465 "Convert the string S into a Calc number.
3466S is assumed to be a simple number (integer or float without an exponent)
3467and all digits are kept, regardless of Calc's current precision."
1f26c380
JB
3468 (cond
3469 ;; Integer
3470 ((string-match "^[0-9]+$" s)
aefad52d
JB
3471 (if (string-match "^\\(0+\\)" s)
3472 (setq s (substring s (match-end 0))))
e90988a0
JB
3473 (if (<= (length s) (* 2 math-bignum-digit-length))
3474 (string-to-number s)
3475 (cons 'bigpos (math-read-bignum s))))
1f26c380
JB
3476 ;; Minus sign
3477 ((string-match "^-[0-9]+$" s)
e90988a0
JB
3478 (if (<= (length s) (1+ (* 2 math-bignum-digit-length)))
3479 (string-to-number s)
3480 (cons 'bigneg (math-read-bignum (substring s 1)))))
1f26c380
JB
3481 ;; Decimal point
3482 ((string-match "^\\(-?[0-9]*\\)\\.\\([0-9]*\\)$" s)
3483 (let ((int (math-match-substring s 1))
3484 (frac (math-match-substring s 2)))
3485 (list 'float (math-read-number-simple (concat int frac))
3486 (- (length frac)))))
3487 ;; Syntax error!
3488 (t nil)))
3489
136211a9
EZ
3490(defun math-match-substring (s n)
3491 (if (match-beginning n)
3492 (substring s (match-beginning n) (match-end n))
bf77c646 3493 ""))
136211a9
EZ
3494
3495(defun math-read-bignum (s) ; [l X]
a6d107f1
JB
3496 (if (> (length s) math-bignum-digit-length)
3497 (cons (string-to-number (substring s (- math-bignum-digit-length)))
3498 (math-read-bignum (substring s 0 (- math-bignum-digit-length))))
28572d7d 3499 (list (string-to-number s))))
136211a9
EZ
3500
3501
3502(defconst math-tex-ignore-words
3503 '( ("\\hbox") ("\\mbox") ("\\text") ("\\left") ("\\right")
3504 ("\\,") ("\\>") ("\\:") ("\\;") ("\\!") ("\\ ")
3505 ("\\quad") ("\\qquad") ("\\hfil") ("\\hfill")
3506 ("\\displaystyle") ("\\textstyle") ("\\dsize") ("\\tsize")
3507 ("\\scriptstyle") ("\\scriptscriptstyle") ("\\ssize") ("\\sssize")
3508 ("\\rm") ("\\bf") ("\\it") ("\\sl")
3509 ("\\roman") ("\\bold") ("\\italic") ("\\slanted")
3510 ("\\cal") ("\\mit") ("\\Cal") ("\\Bbb") ("\\frak") ("\\goth")
3511 ("\\evalto")
3512 ("\\matrix" mat) ("\\bmatrix" mat) ("\\pmatrix" mat)
dacc4c70 3513 ("\\begin" begenv)
136211a9 3514 ("\\cr" punc ";") ("\\\\" punc ";") ("\\*" punc "*")
998858ae
JB
3515 ("\\{" punc "[") ("\\}" punc "]")))
3516
3517(defconst math-latex-ignore-words
3518 (append math-tex-ignore-words
3519 '(("\\begin" begenv))))
136211a9
EZ
3520
3521(defconst math-eqn-ignore-words
3522 '( ("roman") ("bold") ("italic") ("mark") ("lineup") ("evalto")
3523 ("left" ("floor") ("ceil"))
3524 ("right" ("floor") ("ceil"))
3525 ("arc" ("sin") ("cos") ("tan") ("sinh") ("cosh") ("tanh"))
3526 ("size" n) ("font" n) ("fwd" n) ("back" n) ("up" n) ("down" n)
998858ae 3527 ("above" punc ",")))
136211a9
EZ
3528
3529(defconst math-standard-opers
3530 '( ( "_" calcFunc-subscr 1200 1201 )
3531 ( "%" calcFunc-percent 1100 -1 )
136211a9
EZ
3532 ( "u!" calcFunc-lnot -1 1000 )
3533 ( "mod" mod 400 400 185 )
3534 ( "+/-" sdev 300 300 185 )
3535 ( "!!" calcFunc-dfact 210 -1 )
3536 ( "!" calcFunc-fact 210 -1 )
3537 ( "^" ^ 201 200 )
3538 ( "**" ^ 201 200 )
c8d00744
JB
3539 ( "u+" ident -1 197 )
3540 ( "u-" neg -1 197 )
136211a9
EZ
3541 ( "/" / 190 191 )
3542 ( "%" % 190 191 )
3543 ( "\\" calcFunc-idiv 190 191 )
3544 ( "+" + 180 181 )
3545 ( "-" - 180 181 )
3546 ( "|" | 170 171 )
3547 ( "<" calcFunc-lt 160 161 )
3548 ( ">" calcFunc-gt 160 161 )
3549 ( "<=" calcFunc-leq 160 161 )
3550 ( ">=" calcFunc-geq 160 161 )
3551 ( "=" calcFunc-eq 160 161 )
3552 ( "==" calcFunc-eq 160 161 )
3553 ( "!=" calcFunc-neq 160 161 )
3554 ( "&&" calcFunc-land 110 111 )
3555 ( "||" calcFunc-lor 100 101 )
3556 ( "?" (math-read-if) 91 90 )
3557 ( "!!!" calcFunc-pnot -1 85 )
3558 ( "&&&" calcFunc-pand 80 81 )
3559 ( "|||" calcFunc-por 75 76 )
3560 ( ":=" calcFunc-assign 51 50 )
3561 ( "::" calcFunc-condition 45 46 )
3562 ( "=>" calcFunc-evalto 40 41 )
f269b73e 3563 ( "=>" calcFunc-evalto 40 -1 )))
515e955e
JB
3564
3565(defun math-standard-ops ()
3566 (if calc-multiplication-has-precedence
3567 (cons
3568 '( "*" * 196 195 )
3569 (cons
3570 '( "2x" * 196 195 )
3571 math-standard-opers))
3572 (cons
cad63e32 3573 '( "*" * 190 191 )
515e955e 3574 (cons
cad63e32 3575 '( "2x" * 190 191 )
515e955e
JB
3576 math-standard-opers))))
3577
a6a0d3cb
JB
3578(defvar math-expr-opers (math-standard-ops))
3579
515e955e
JB
3580(defun math-standard-ops-p ()
3581 (let ((meo (caar math-expr-opers)))
3582 (and (stringp meo)
3583 (string= meo "*"))))
3584
515e955e
JB
3585(defun math-expr-ops ()
3586 (if (math-standard-ops-p)
3587 (math-standard-ops)
3588 math-expr-opers))
136211a9
EZ
3589
3590;;;###autoload
3591(defun calc-grab-region (top bot arg)
3592 "Parse the region as a vector of numbers and push it on the Calculator stack."
3593 (interactive "r\nP")
ce805efa 3594 (require 'calc-ext)
bf77c646 3595 (calc-do-grab-region top bot arg))
136211a9
EZ
3596
3597;;;###autoload
3598(defun calc-grab-rectangle (top bot arg)
3599 "Parse a rectangle as a matrix of numbers and push it on the Calculator stack."
3600 (interactive "r\nP")
ce805efa 3601 (require 'calc-ext)
bf77c646 3602 (calc-do-grab-rectangle top bot arg))
136211a9
EZ
3603
3604(defun calc-grab-sum-down (top bot arg)
3605 "Parse a rectangle as a matrix of numbers and sum its columns."
3606 (interactive "r\nP")
ce805efa 3607 (require 'calc-ext)
bf77c646 3608 (calc-do-grab-rectangle top bot arg 'calcFunc-reduced))
136211a9
EZ
3609
3610(defun calc-grab-sum-across (top bot arg)
3611 "Parse a rectangle as a matrix of numbers and sum its rows."
3612 (interactive "r\nP")
ce805efa 3613 (require 'calc-ext)
bf77c646 3614 (calc-do-grab-rectangle top bot arg 'calcFunc-reducea))
136211a9
EZ
3615
3616
3617;;;###autoload
3618(defun calc-embedded (arg &optional end obeg oend)
3619 "Start Calc Embedded mode on the formula surrounding point."
3620 (interactive "P")
ce805efa 3621 (require 'calc-ext)
bf77c646 3622 (calc-do-embedded arg end obeg oend))
136211a9
EZ
3623
3624;;;###autoload
3625(defun calc-embedded-activate (&optional arg cbuf)
3626 "Scan the current editing buffer for all embedded := and => formulas.
3627Also looks for the equivalent TeX words, \\gets and \\evalto."
3628 (interactive "P")
bf77c646 3629 (calc-do-embedded-activate arg cbuf))
136211a9 3630
136211a9
EZ
3631(defun calc-user-invocation ()
3632 (interactive)
dd168a3e 3633 (unless calc-invocation-macro
d24f83d4 3634 (error "Use `Z I' inside Calc to define a `C-x * Z' keyboard macro"))
bf77c646 3635 (execute-kbd-macro calc-invocation-macro nil))
136211a9 3636
136211a9
EZ
3637;;; User-programmability.
3638
3639;;;###autoload
3640(defmacro defmath (func args &rest body) ; [Public]
ce805efa 3641 (require 'calc-ext)
bf77c646 3642 (math-do-defmath func args body))
136211a9 3643
136211a9
EZ
3644;;; Functions needed for Lucid Emacs support.
3645
3646(defun calc-read-key (&optional optkey)
6546555e 3647 (cond ((featurep 'xemacs)
136211a9
EZ
3648 (let ((event (next-command-event)))
3649 (let ((key (event-to-character event t t)))
3650 (or key optkey (error "Expected a plain keystroke"))
3651 (cons key event))))
136211a9 3652 (t
cecd4c20 3653 (let ((key (read-event)))
bf77c646 3654 (cons key key)))))
136211a9
EZ
3655
3656(defun calc-unread-command (&optional input)
31b85a14
EZ
3657 (if (featurep 'xemacs)
3658 (setq unread-command-event
3659 (if (integerp input) (character-to-event input)
3660 (or input last-command-event)))
3661 (push (or input last-command-event) unread-command-events)))
136211a9
EZ
3662
3663(defun calc-clear-unread-commands ()
a1506d29 3664 (if (featurep 'xemacs)
6546555e 3665 (setq unread-command-event nil)
31b85a14 3666 (setq unread-command-events nil)))
136211a9 3667
cd012309 3668(when calc-always-load-extensions
ce805efa 3669 (require 'calc-ext)
cd012309 3670 (calc-load-everything))
136211a9
EZ
3671
3672
3673(run-hooks 'calc-load-hook)
3674
ce805efa
JB
3675(provide 'calc)
3676
ab5796a9 3677;;; arch-tag: 0c3b170c-4ce6-4eaf-8d9b-5834d1fe938f
bf77c646 3678;;; calc.el ends here