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