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