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