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