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