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