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